mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
ui improvements - abort fix
This commit is contained in:
parent
411167ee44
commit
e1692758c6
9 changed files with 54 additions and 19 deletions
|
|
@ -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) => (
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ const Sidebar = () => {
|
|||
const sidebarState = useSidebarState()
|
||||
const { isHistoryOpen, currentTab: tab } = sidebarState
|
||||
|
||||
// className='@@void-scope'
|
||||
return <div className='@@void-scope'>
|
||||
<div className={`flex flex-col h-screen w-full px-2 py-2 overflow-y-auto`}>
|
||||
<div className={`flex flex-col h-screen w-full px-2 py-2`}>
|
||||
|
||||
{/* <span onClick={() => {
|
||||
const tabs = ['chat', 'settings', 'threadSelector']
|
||||
|
|
@ -27,7 +28,7 @@ const Sidebar = () => {
|
|||
sidebarStateService.setState({ currentTab: tabs[(index + 1) % tabs.length] as any })
|
||||
}}>clickme {tab}</span> */}
|
||||
|
||||
<div className={`mb-2 h-[30vh] overflow-y-auto ${isHistoryOpen ? '' : 'hidden'}`}>
|
||||
<div className={`mb-2 ${isHistoryOpen ? '' : 'hidden'}`}>
|
||||
<SidebarThreadSelector />
|
||||
</div>
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ const Sidebar = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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<string | null> => {
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<div className="flex flex-col gap-y-1">
|
||||
<div className="flex flex-col gap-y-1 overflow-y-auto h-[30vh]">
|
||||
|
||||
{/* X button at top right */}
|
||||
<div className="text-right">
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<SidebarProps> = ({ items, onItemSelect, onExtraButtonClick }) => {\n return (\n <div className={styles.sidebar}>\n <ul>\n {items.map((item, index) => (\n <li key={index}>\n {{selection}}\n className={styles.sidebarButton}\n onClick={() => onItemSelect?.(item.label)}\n >\n {item.label}\n </button>\n </li>\n ))}\n </ul>\n <button className={styles.extraButton} onClick={onExtraButtonClick}>\n Extra Action\n </button>\n </div>\n );\n};\n\nexport default Sidebar;\n```\n\nSELECTION\n``` <button```\n\nINSTRUCTIONS\n```make all the buttons like this into divs```\n\nEXPECTED OUTPUT\n\nWe should change all the buttons like the one selected into a div component. Here is the change:\n```\n@@ ... @@\n-<div className={styles.sidebar}>\n-<ul>\n- {items.map((item, index) => (\n-\t<li key={index}>\n-\t <button\n-\t\tclassName={styles.sidebarButton}\n-\t\tonClick={() => onItemSelect?.(item.label)}\n-\t >\n-\t\t{item.label}\n-\t </button>\n-\t</li>\n- ))}\n-</ul>\n-<button className={styles.extraButton} onClick={onExtraButtonClick}>\n- Extra Action\n-</button>\n-</div>\n+<div className={styles.sidebar}>\n+<ul>\n+ {items.map((item, index) => (\n+\t<li key={index}>\n+\t <div\n+\t\tclassName={styles.sidebarButton}\n+\t\tonClick={() => onItemSelect?.(item.label)}\n+\t >\n+\t\t{item.label}\n+\t </div>\n+\t</li>\n+ ))}\n+</ul>\n+<div className={styles.extraButton} onClick={onExtraButtonClick}>\n+ Extra Action\n+</div>\n+</div>\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."
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
|
|
|
|||
Loading…
Reference in a new issue