diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/MarkdownRender.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/MarkdownRender.tsx index e17beb37..ce41e17c 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/MarkdownRender.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/MarkdownRender.tsx @@ -212,7 +212,7 @@ const RenderToken = ({ token, nested = false }: { token: Token | string, nested? } export const MarkdownRender = ({ string, nested = false }: { string: string, nested?: boolean }) => { - const tokens = marked.lexer(string); // https://marked.js.org/using_pro#renderer + const tokens = marked.lexer(string ?? '(empty)'); // https://marked.js.org/using_pro#renderer return ( <> {tokens.map((token, index) => ( diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/ollama.tsx b/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/ollama.tsx index 44b7ff1e..399065cb 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/ollama.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/ollama.tsx @@ -1,4 +1,4 @@ -import { Ollama } from 'ollama/browser'; +import { Ollama, ErrorResponse } from 'ollama/browser'; import { parseMaxTokensStr } from '../../../registerConfig.js'; import { SendLLMMessageFnTypeInternal } from './_types.js'; @@ -29,7 +29,15 @@ export const sendOllamaMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, }) // when error/fail - .catch(error => { + .catch((error) => { + if (typeof error === 'object') { + const e = error.error as ErrorResponse['error'] + if (e) { + const name = error.name ?? 'Error' + onError({ error: `${name}: ${e}` }) + return; + } + } onError({ error }) }) diff --git a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/sendLLMMessage.tsx b/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/sendLLMMessage.tsx index f5bca7dd..d7872ddf 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/sendLLMMessage.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sendLLMMessage/sendLLMMessage.tsx @@ -44,15 +44,16 @@ export const sendLLMMessage = ({ messages, onText: onText_, onFinalMessage: onFi } const onError: OnError = ({ error }) => { - console.error('sendLLMMessage onError:', error) if (_didAbort) return + console.error('sendLLMMessage onError:', error) captureChatEvent(`${loggingName} - Error`, { error }) onError_({ error }) } const onAbort = () => { captureChatEvent(`${loggingName} - Abort`, { messageLengthSoFar: _fullTextSoFar.length }) - _aborter?.() + try { _aborter?.() } // aborter sometimes automatically throws an error + catch (e) { } _didAbort = true } abortRef_.current = onAbort @@ -90,8 +91,8 @@ export const sendLLMMessage = ({ messages, onText: onText_, onFinalMessage: onFi catch (error) { if (error instanceof Error) { onError({ error }) } else { onError({ error: `Unexpected Error in sendLLMMessage: ${error}` }); } - ; (_aborter as any)?.() - _didAbort = true + // ; (_aborter as any)?.() + // _didAbort = true } diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/ErrorDisplay.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/ErrorDisplay.tsx index 1663aad1..c137d56f 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/ErrorDisplay.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/ErrorDisplay.tsx @@ -33,7 +33,7 @@ const getErrorDetails = (error: unknown) => { } // sometimes error is an object but not an Error else if (typeof error === 'object') { - e = new Error(`The server didn't give a very useful error message. More details below.`, { cause: JSON.stringify(error) }) + e = new Error(`More details below.`, { cause: JSON.stringify(error) }) } else { diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/Sidebar.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/Sidebar.tsx index ce9bad77..a0deeb2d 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/Sidebar.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/Sidebar.tsx @@ -18,8 +18,9 @@ const Sidebar = () => { const sidebarState = useSidebarState() const { isHistoryOpen, currentTab: tab } = sidebarState + // className='@@void-scope' return
-
+
{/* { const tabs = ['chat', 'settings', 'threadSelector'] @@ -27,7 +28,7 @@ const Sidebar = () => { sidebarStateService.setState({ currentTab: tabs[(index + 1) % tabs.length] as any }) }}>clickme {tab} */} -
+
@@ -42,6 +43,7 @@ const Sidebar = () => {
+ } diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx index dbca67e9..9bb7a9e1 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx @@ -21,7 +21,6 @@ import { LLMMessageServiceParams } from '../../../../../../../platform/void/comm import { getCmdKey } from '../../../getCmdKey.js' import { VSCodeDropdown } from '@vscode/webview-ui-toolkit/react'; -import { InputBox } from './InputBox.js'; // read files from VSCode const VSReadFile = async (modelService: IModelService, uri: URI): Promise => { @@ -260,7 +259,7 @@ export const SidebarChat = () => { sendLLMMessageService.abort(latestRequestIdRef.current) // if messageStream was not empty, add it to the history - const llmContent = messageStream || '(null)' + const llmContent = messageStream || '(empty)' const newHistoryElt: ChatMessage = { role: 'assistant', content: llmContent, displayContent: messageStream, } threadsStateService.addMessageToCurrentThread(newHistoryElt) diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarThreadSelector.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarThreadSelector.tsx index 7ae8acef..9953259d 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarThreadSelector.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarThreadSelector.tsx @@ -23,10 +23,10 @@ export const SidebarThreadSelector = () => { const { allThreads } = threadsState // sorted by most recent to least recent - const sortedThreadIds = Object.keys(allThreads ?? {}).sort((threadId1, threadId2) => allThreads![threadId1].lastModified > allThreads![threadId2].lastModified ? 1 : -1) + const sortedThreadIds = Object.keys(allThreads ?? {}).sort((threadId1, threadId2) => allThreads![threadId1].lastModified > allThreads![threadId2].lastModified ? -1 : 1) return ( -
+
{/* X button at top right */}
diff --git a/src/vs/workbench/contrib/void/browser/registerSidebar.ts b/src/vs/workbench/contrib/void/browser/registerSidebar.ts index db939649..4865de98 100644 --- a/src/vs/workbench/contrib/void/browser/registerSidebar.ts +++ b/src/vs/workbench/contrib/void/browser/registerSidebar.ts @@ -11,7 +11,6 @@ import { } from '../../../common/views.js'; import * as nls from '../../../../nls.js'; -import * as dom from '../../../../base/browser/dom.js'; import { Codicon } from '../../../../base/common/codicons.js'; import { localize } from '../../../../nls.js'; @@ -101,9 +100,7 @@ class VoidSidebarViewPane extends ViewPane { protected override renderBody(parent: HTMLElement): void { super.renderBody(parent); - - const { root } = dom.h('div@root') - dom.append(parent, root); + parent.style.overflow = 'auto' // gets set immediately this.instantiationService.invokeFunction(accessor => { @@ -117,7 +114,7 @@ class VoidSidebarViewPane extends ViewPane { sendLLMMessageService: accessor.get(ISendLLMMessageService), contextViewService: accessor.get(IContextViewService), } - mountFn(root, services); + mountFn(parent, services); }); } diff --git a/src/vs/workbench/contrib/void/browser/registerThreads.ts b/src/vs/workbench/contrib/void/browser/registerThreads.ts index e942a079..91b3d5c4 100644 --- a/src/vs/workbench/contrib/void/browser/registerThreads.ts +++ b/src/vs/workbench/contrib/void/browser/registerThreads.ts @@ -133,6 +133,8 @@ class ThreadHistoryService extends Disposable implements IThreadHistoryService { } switchToThread(threadId: string) { + // console.log('threadId', threadId) + // console.log('messages', this.state.allThreads[threadId].messages) this._setState({ _currentThreadId: threadId }, true) } @@ -194,3 +196,29 @@ class ThreadHistoryService extends Disposable implements IThreadHistoryService { } registerSingleton(IThreadHistoryService, ThreadHistoryService, InstantiationType.Eager); + + + +// [ +// { +// "role": "system", +// "content": "\nYou are a coding assistant. You are given a list of relevant files `files`, a selection that the user is making `selection`, and instructions to follow `instructions`.\n\nPlease edit the selected file following the user's instructions (or, if appropriate, answer their question instead).\n\nAll changes made to files must be outputted in unified diff format.\nUnified diff format instructions:\n1. Each diff must begin with ```@@ ... @@```.\n2. Each line must start with a `+` or `-` or ` ` symbol.\n3. Make diffs more than a few lines.\n4. Make high-level diffs rather than many one-line diffs.\n\nHere's an example of unified diff format:\n\n```\n@@ ... @@\n-def factorial(n):\n- if n == 0:\n- return 1\n- else:\n- return n * factorial(n-1)\n+def factorial(number):\n+ if number == 0:\n+ return 1\n+ else:\n+ return number * factorial(number-1)\n```\n\nPlease create high-level diffs where you group edits together if they are near each other, like in the above example. Another way to represent the above example is to make many small line edits. However, this is less preferred, because the edits are not high-level. The edits are close together and should be grouped:\n\n```\n@@ ... @@ # This is less preferred because edits are close together and should be grouped:\n-def factorial(n):\n+def factorial(number):\n- if n == 0:\n+ if number == 0:\n return 1\n else:\n- return n * factorial(n-1)\n+ return number * factorial(number-1)\n```\n\n# Example 1:\n\nFILES\nselected file `test.ts`:\n```\nx = 1\n\n{{selection}}\n\nz = 3\n```\n\nSELECTION\n```const y = 2```\n\nINSTRUCTIONS\n```y = 3```\n\nEXPECTED RESULT\n\nWe should change the selection from ```y = 2``` to ```y = 3```.\n```\n@@ ... @@\n-x = 1\n-\n-y = 2\n+x = 1\n+\n+y = 3\n```\n\n# Example 2:\n\nFILES\nselected file `Sidebar.tsx`:\n```\nimport React from 'react';\nimport styles from './Sidebar.module.css';\n\ninterface SidebarProps {\n items: { label: string; href: string }[];\n onItemSelect?: (label: string) => void;\n onExtraButtonClick?: () => void;\n}\n\nconst Sidebar: React.FC = ({ items, onItemSelect, onExtraButtonClick }) => {\n return (\n
\n
    \n {items.map((item, index) => (\n
  • \n {{selection}}\n className={styles.sidebarButton}\n onClick={() => onItemSelect?.(item.label)}\n >\n {item.label}\n \n
  • \n ))}\n
\n \n
\n );\n};\n\nexport default Sidebar;\n```\n\nSELECTION\n``` \n-
    \n- {items.map((item, index) => (\n-\t
  • \n-\t onItemSelect?.(item.label)}\n-\t >\n-\t\t{item.label}\n-\t \n-\t
  • \n- ))}\n-
\n-\n-
\n+
\n+
    \n+ {items.map((item, index) => (\n+\t
  • \n+\t onItemSelect?.(item.label)}\n+\t >\n+\t\t{item.label}\n+\t
\n+\t\n+ ))}\n+\n+
\n+ Extra Action\n+
\n+
\n```\n" +// }, +// { +// "role": "user", +// "content": "test", +// "displayContent": "test", +// "selections": null +// }, +// { +// "role": "assistant", +// "content": { +// "requestId": "49d4c9e6-5e53-4768-a77e-5c297223fa9c", +// "fullText": "I apologize, but I don't have enough context to provide a meaningful response based on just the word \"test\". If you have a specific question or topic you'd like me to assist with, please provide more details or context so I can better understand how to help you. I'm here to engage in conversation and provide information to the best of my abilities." +// }, +// "displayContent": { +// "requestId": "49d4c9e6-5e53-4768-a77e-5c297223fa9c", +// "fullText": "I apologize, but I don't have enough context to provide a meaningful response based on just the word \"test\". If you have a specific question or topic you'd like me to assist with, please provide more details or context so I can better understand how to help you. I'm here to engage in conversation and provide information to the best of my abilities." +// } +// } +// ]