add more logs and catches to ai chat (#5524)
This commit is contained in:
@@ -196,7 +196,7 @@
|
||||
| 'csharp'
|
||||
| 'nu'
|
||||
| 'java'
|
||||
// KJQXZ
|
||||
// KJQXZ
|
||||
export let code: string = ''
|
||||
export let cmdEnterAction: (() => void) | undefined = undefined
|
||||
export let formatAction: (() => void) | undefined = undefined
|
||||
@@ -612,8 +612,12 @@
|
||||
}
|
||||
|
||||
function addChatHandler(editor: meditor.IStandaloneCodeEditor) {
|
||||
aiChatEditorHandler = new AIChatEditorHandler(editor)
|
||||
reviewingChanges = aiChatEditorHandler.reviewingChanges
|
||||
try {
|
||||
aiChatEditorHandler = new AIChatEditorHandler(editor)
|
||||
reviewingChanges = aiChatEditorHandler.reviewingChanges
|
||||
} catch (err) {
|
||||
console.error('Could not add chat handler', err)
|
||||
}
|
||||
}
|
||||
|
||||
$: $reviewingChanges && autocompletor?.reject()
|
||||
@@ -621,58 +625,62 @@
|
||||
let completorDisposable: Disposable | undefined = undefined
|
||||
let autocompletor: Autocompletor | undefined = undefined
|
||||
function addSuperCompletor(editor: meditor.IStandaloneCodeEditor) {
|
||||
if (completorDisposable) {
|
||||
completorDisposable.dispose()
|
||||
}
|
||||
autocompletor = new Autocompletor(editor, lang)
|
||||
|
||||
// last user events (currently disabled):
|
||||
// let lastTs = Date.now()
|
||||
// editor.onDidChangeModelContent((e) => {
|
||||
// const thisTs = Date.now()
|
||||
// lastTs = thisTs
|
||||
// setTimeout(() => {
|
||||
// if (thisTs === lastTs) {
|
||||
// autocompletor?.savePatch()
|
||||
// }
|
||||
// }, 150)
|
||||
// })
|
||||
|
||||
completorDisposable = editor.onDidChangeCursorPosition((e) => {
|
||||
autocompletor?.reject()
|
||||
if ($reviewingChanges) {
|
||||
return
|
||||
try {
|
||||
if (completorDisposable) {
|
||||
completorDisposable.dispose()
|
||||
}
|
||||
const position = editor.getPosition()
|
||||
if (!position) {
|
||||
return
|
||||
}
|
||||
const upToText = editor.getModel()?.getValueInRange({
|
||||
startLineNumber: position.lineNumber,
|
||||
startColumn: 0,
|
||||
endLineNumber: position.lineNumber,
|
||||
endColumn: position.column
|
||||
})
|
||||
const lastChar = upToText ? upToText[upToText.length - 1] : ''
|
||||
if (lastChar && lastChar.match(/[\(\{\s:="',]/)) {
|
||||
autocompletor?.predict()
|
||||
}
|
||||
})
|
||||
autocompletor = new Autocompletor(editor, lang)
|
||||
|
||||
editor.addCommand(KeyCode.Tab, () => {
|
||||
if (autocompletor?.hasChanges()) {
|
||||
autocompletor?.accept()
|
||||
autocompletor?.predict()
|
||||
} else {
|
||||
editor.trigger('keyboard', 'tab', {})
|
||||
}
|
||||
})
|
||||
// last user events (currently disabled):
|
||||
// let lastTs = Date.now()
|
||||
// editor.onDidChangeModelContent((e) => {
|
||||
// const thisTs = Date.now()
|
||||
// lastTs = thisTs
|
||||
// setTimeout(() => {
|
||||
// if (thisTs === lastTs) {
|
||||
// autocompletor?.savePatch()
|
||||
// }
|
||||
// }, 150)
|
||||
// })
|
||||
|
||||
editor.onKeyDown((e) => {
|
||||
if (e.keyCode === KeyCode.Escape) {
|
||||
completorDisposable = editor.onDidChangeCursorPosition((e) => {
|
||||
autocompletor?.reject()
|
||||
}
|
||||
})
|
||||
if ($reviewingChanges) {
|
||||
return
|
||||
}
|
||||
const position = editor.getPosition()
|
||||
if (!position) {
|
||||
return
|
||||
}
|
||||
const upToText = editor.getModel()?.getValueInRange({
|
||||
startLineNumber: position.lineNumber,
|
||||
startColumn: 0,
|
||||
endLineNumber: position.lineNumber,
|
||||
endColumn: position.column
|
||||
})
|
||||
const lastChar = upToText ? upToText[upToText.length - 1] : ''
|
||||
if (lastChar && lastChar.match(/[\(\{\s:="',]/)) {
|
||||
autocompletor?.predict()
|
||||
}
|
||||
})
|
||||
|
||||
editor.addCommand(KeyCode.Tab, () => {
|
||||
if (autocompletor?.hasChanges()) {
|
||||
autocompletor?.accept()
|
||||
autocompletor?.predict()
|
||||
} else {
|
||||
editor.trigger('keyboard', 'tab', {})
|
||||
}
|
||||
})
|
||||
|
||||
editor.onKeyDown((e) => {
|
||||
if (e.keyCode === KeyCode.Escape) {
|
||||
autocompletor?.reject()
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('Could not add supercompletor', err)
|
||||
}
|
||||
}
|
||||
|
||||
$: $copilotInfo.enabled &&
|
||||
|
||||
@@ -25,36 +25,44 @@
|
||||
export let args: Record<string, any>
|
||||
export let path: string | undefined
|
||||
|
||||
$: contextCodePath =
|
||||
(path?.split('/').pop() ?? 'script') + '.' + langToExt(scriptLangToEditorLang(lang))
|
||||
$: contextCodePath = path
|
||||
? path.split('/').pop() + '.' + langToExt(scriptLangToEditorLang(lang))
|
||||
: undefined
|
||||
|
||||
let initializedWithInitCode: boolean | null = null
|
||||
$: lang && (initializedWithInitCode = null)
|
||||
function onCodeChange() {
|
||||
if (initializedWithInitCode === null && code) {
|
||||
if (isInitialCode(code)) {
|
||||
initializedWithInitCode = true
|
||||
} else {
|
||||
initializedWithInitCode = false
|
||||
if (!contextCodePath) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
if (initializedWithInitCode === null && code) {
|
||||
if (isInitialCode(code)) {
|
||||
initializedWithInitCode = true
|
||||
} else {
|
||||
initializedWithInitCode = false
|
||||
selectedContext = [
|
||||
{
|
||||
type: 'code',
|
||||
title: contextCodePath
|
||||
}
|
||||
]
|
||||
}
|
||||
} else if (initializedWithInitCode) {
|
||||
// if the code was initial and was changed, add code context, then prevent it from being added again
|
||||
selectedContext = [
|
||||
{
|
||||
type: 'code',
|
||||
title: contextCodePath
|
||||
}
|
||||
]
|
||||
initializedWithInitCode = false
|
||||
}
|
||||
} else if (initializedWithInitCode) {
|
||||
// if the code was initial and was changed, add code context, then prevent it from being added again
|
||||
selectedContext = [
|
||||
{
|
||||
type: 'code',
|
||||
title: contextCodePath
|
||||
}
|
||||
]
|
||||
initializedWithInitCode = false
|
||||
} catch (err) {
|
||||
console.error('Could not update context', err)
|
||||
}
|
||||
}
|
||||
$: code && onCodeChange()
|
||||
$: contextCodePath && code && onCodeChange()
|
||||
|
||||
let db: { schema: DBSchema; resource: string } | undefined = undefined
|
||||
|
||||
@@ -63,17 +71,21 @@
|
||||
args: Record<string, any>,
|
||||
dbSchemas: DBSchemas
|
||||
) {
|
||||
const schemaRes = lang === 'graphql' ? args.api : args.database
|
||||
if (typeof schemaRes === 'string') {
|
||||
const schemaPath = schemaRes.replace('$res:', '')
|
||||
const schema = dbSchemas[schemaPath]
|
||||
if (schema && schema.lang === lang) {
|
||||
db = { schema, resource: schemaPath }
|
||||
try {
|
||||
const schemaRes = lang === 'graphql' ? args.api : args.database
|
||||
if (typeof schemaRes === 'string') {
|
||||
const schemaPath = schemaRes.replace('$res:', '')
|
||||
const schema = dbSchemas[schemaPath]
|
||||
if (schema && schema.lang === lang) {
|
||||
db = { schema, resource: schemaPath }
|
||||
} else {
|
||||
db = undefined
|
||||
}
|
||||
} else {
|
||||
db = undefined
|
||||
}
|
||||
} else {
|
||||
db = undefined
|
||||
} catch (err) {
|
||||
console.error('Could not update schema', err)
|
||||
}
|
||||
}
|
||||
$: updateSchema(lang, args, $dbSchemas)
|
||||
@@ -83,42 +95,49 @@
|
||||
let availableContext: ContextElement[] = []
|
||||
|
||||
function updateAvailableContext(
|
||||
contextCodePath: string,
|
||||
contextCodePath: string | undefined,
|
||||
code: string,
|
||||
lang: ScriptLang | 'bunnative',
|
||||
error: string | undefined,
|
||||
db: { schema: DBSchema; resource: string } | undefined,
|
||||
providerModel: AIProviderModel | undefined
|
||||
) {
|
||||
availableContext = [
|
||||
{
|
||||
type: 'code',
|
||||
title: contextCodePath,
|
||||
content: code,
|
||||
lang
|
||||
}
|
||||
]
|
||||
|
||||
if (error) {
|
||||
availableContext = [
|
||||
...availableContext,
|
||||
{
|
||||
type: 'error',
|
||||
title: 'error',
|
||||
content: error
|
||||
}
|
||||
]
|
||||
if (!contextCodePath) {
|
||||
return
|
||||
}
|
||||
|
||||
if (db && !providerModel?.model.endsWith('/thinking')) {
|
||||
try {
|
||||
availableContext = [
|
||||
...availableContext,
|
||||
{
|
||||
type: 'db',
|
||||
title: db.resource,
|
||||
schema: db.schema
|
||||
type: 'code',
|
||||
title: contextCodePath,
|
||||
content: code,
|
||||
lang
|
||||
}
|
||||
]
|
||||
|
||||
if (error) {
|
||||
availableContext = [
|
||||
...availableContext,
|
||||
{
|
||||
type: 'error',
|
||||
title: 'error',
|
||||
content: error
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
if (db && !providerModel?.model.endsWith('/thinking')) {
|
||||
availableContext = [
|
||||
...availableContext,
|
||||
{
|
||||
type: 'db',
|
||||
title: db.resource,
|
||||
schema: db.schema
|
||||
}
|
||||
]
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Could not update available context', err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,17 +182,22 @@
|
||||
let abortController: AbortController | undefined = undefined
|
||||
|
||||
function updateSelectedContextElements() {
|
||||
const contextElements: ContextElement[] = []
|
||||
try {
|
||||
const contextElements: ContextElement[] = []
|
||||
|
||||
for (const selected of selectedContext) {
|
||||
const el = availableContext.find(
|
||||
(c) => c.type === selected.type && c.title === selected.title
|
||||
)
|
||||
if (el) {
|
||||
contextElements.push(el)
|
||||
for (const selected of selectedContext) {
|
||||
const el = availableContext.find(
|
||||
(c) => c.type === selected.type && c.title === selected.title
|
||||
)
|
||||
if (el) {
|
||||
contextElements.push(el)
|
||||
}
|
||||
}
|
||||
return contextElements
|
||||
} catch (err) {
|
||||
console.error('Could not update selected context elements', err)
|
||||
return []
|
||||
}
|
||||
return contextElements
|
||||
}
|
||||
let selectedContextElements: ContextElement[] = []
|
||||
|
||||
@@ -289,6 +313,9 @@
|
||||
}
|
||||
|
||||
export function fix() {
|
||||
if (!contextCodePath) {
|
||||
return
|
||||
}
|
||||
instructions = 'Fix the error'
|
||||
|
||||
selectedContext = [
|
||||
@@ -320,19 +347,26 @@
|
||||
|
||||
let indexDB: IDBPDatabase<ChatSchema> | undefined = undefined
|
||||
async function initIndexDB() {
|
||||
indexDB = await openDB<ChatSchema>('copilot-chat-history', 1, {
|
||||
upgrade(indexDB) {
|
||||
if (!indexDB.objectStoreNames.contains('chats')) {
|
||||
indexDB.createObjectStore('chats', { keyPath: 'id' })
|
||||
try {
|
||||
console.log('Initializing chat history database')
|
||||
indexDB = await openDB<ChatSchema>('copilot-chat-history', 1, {
|
||||
upgrade(indexDB) {
|
||||
if (!indexDB.objectStoreNames.contains('chats')) {
|
||||
indexDB.createObjectStore('chats', { keyPath: 'id' })
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
console.log('Chat history database initialized')
|
||||
|
||||
const chats = await indexDB.getAll('chats')
|
||||
savedChats = chats.reduce((acc, chat) => {
|
||||
acc[chat.id] = chat
|
||||
return acc
|
||||
}, {} as typeof savedChats)
|
||||
const chats = await indexDB.getAll('chats')
|
||||
console.log('Retrieved chats')
|
||||
savedChats = chats.reduce((acc, chat) => {
|
||||
acc[chat.id] = chat
|
||||
return acc
|
||||
}, {} as typeof savedChats)
|
||||
} catch (err) {
|
||||
console.error('Could not open chat history database', err)
|
||||
}
|
||||
}
|
||||
|
||||
initIndexDB()
|
||||
|
||||
Reference in New Issue
Block a user