From fc3d2cd985380c1743fd8724543bfdf1c7c063df Mon Sep 17 00:00:00 2001 From: HugoCasa Date: Thu, 27 Mar 2025 18:36:31 +0100 Subject: [PATCH] add more logs and catches to ai chat (#5524) --- frontend/src/lib/components/Editor.svelte | 110 +++++------ .../lib/components/copilot/chat/AIChat.svelte | 172 +++++++++++------- 2 files changed, 162 insertions(+), 120 deletions(-) diff --git a/frontend/src/lib/components/Editor.svelte b/frontend/src/lib/components/Editor.svelte index 5b2aff62ed..77ccf85770 100644 --- a/frontend/src/lib/components/Editor.svelte +++ b/frontend/src/lib/components/Editor.svelte @@ -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 && diff --git a/frontend/src/lib/components/copilot/chat/AIChat.svelte b/frontend/src/lib/components/copilot/chat/AIChat.svelte index 1d103a1666..5030dfb547 100644 --- a/frontend/src/lib/components/copilot/chat/AIChat.svelte +++ b/frontend/src/lib/components/copilot/chat/AIChat.svelte @@ -25,36 +25,44 @@ export let args: Record 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, 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 | undefined = undefined async function initIndexDB() { - indexDB = await openDB('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('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()