From 6f1905a962854530deb69b67e2a65b53f539965a Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Fri, 17 Jan 2025 17:30:52 -0800 Subject: [PATCH] fix streaming issue, cleanup chat error styles --- .../platform/void/common/llmMessageService.ts | 2 +- .../contrib/void/browser/chatThreadService.ts | 24 ++-- .../react/src/sidebar-tsx/SidebarChat.tsx | 133 ++++++++++-------- 3 files changed, 84 insertions(+), 75 deletions(-) diff --git a/src/vs/platform/void/common/llmMessageService.ts b/src/vs/platform/void/common/llmMessageService.ts index 0bd8bf13..caaeb0c8 100644 --- a/src/vs/platform/void/common/llmMessageService.ts +++ b/src/vs/platform/void/common/llmMessageService.ts @@ -65,7 +65,7 @@ export class LLMMessageService extends Disposable implements ILLMMessageService this._onRequestIdDone(e.requestId) })) this._register((this.channel.listen('onError_llm') satisfies Event)(e => { - console.log('Error in LLMMessageService:', JSON.stringify(e)) + console.error('Error in LLMMessageService:', JSON.stringify(e)) this.onErrorHooks_llm[e.requestId]?.(e) this._onRequestIdDone(e.requestId) })) diff --git a/src/vs/workbench/contrib/void/browser/chatThreadService.ts b/src/vs/workbench/contrib/void/browser/chatThreadService.ts index 0faf4725..7fede377 100644 --- a/src/vs/workbench/contrib/void/browser/chatThreadService.ts +++ b/src/vs/workbench/contrib/void/browser/chatThreadService.ts @@ -74,9 +74,9 @@ export type ThreadsState = { export type ThreadStreamState = { [threadId: string]: undefined | { - streamingToken?: string; error?: { message: string, fullError: Error | null }; messageSoFar?: string; + streamingToken?: string; } } @@ -177,6 +177,13 @@ class ChatThreadService extends Disposable implements IChatThreadService { // ---------- streaming ---------- + finishStreaming = (threadId: string, content: string, error?: { message: string, fullError: Error | null }) => { + // add assistant's message to chat history, and clear selection + const assistantHistoryElt: ChatMessage = { role: 'assistant', content, displayContent: content || null } + this._addMessageToThread(threadId, assistantHistoryElt) + this._setStreamState(threadId, { messageSoFar: undefined, streamingToken: undefined, error }) + } + async addUserMessageAndStreamResponse(userMessage: string) { const threadId = this.getCurrentThread().id @@ -192,12 +199,6 @@ class ChatThreadService extends Disposable implements IChatThreadService { const userHistoryElt: ChatMessage = { role: 'user', content: chat_prompt(instructions, selections), displayContent: instructions, selections: selections } this._addMessageToThread(threadId, userHistoryElt) - const onDone = (content: string, error?: { message: string, fullError: Error | null }) => { - // add assistant's message to chat history, and clear selection - const assistantHistoryElt: ChatMessage = { role: 'assistant', content, displayContent: content || null } - this._addMessageToThread(threadId, assistantHistoryElt) - this._setStreamState(threadId, { messageSoFar: undefined, streamingToken: undefined, error }) - } this._setStreamState(threadId, { error: undefined }) @@ -211,11 +212,10 @@ class ChatThreadService extends Disposable implements IChatThreadService { this._setStreamState(threadId, { messageSoFar: fullText }) }, onFinalMessage: ({ fullText: content }) => { - onDone(content) + this.finishStreaming(threadId, content) }, onError: (error) => { - console.log('Void Chat Error:', error) - onDone(this.streamState[threadId]?.messageSoFar ?? '', error) + this.finishStreaming(threadId, this.streamState[threadId]?.messageSoFar ?? '', error) }, useProviderFor: 'Ctrl+L', @@ -227,8 +227,8 @@ class ChatThreadService extends Disposable implements IChatThreadService { cancelStreaming(threadId: string) { const llmCancelToken = this.streamState[threadId]?.streamingToken - if (llmCancelToken) this._llmMessageService.abort(llmCancelToken) - this._setStreamState(threadId, { streamingToken: undefined }) + if (llmCancelToken !== undefined) this._llmMessageService.abort(llmCancelToken) + this.finishStreaming(threadId, this.streamState[threadId]?.messageSoFar ?? '') } dismissStreamError(threadId: string): void { 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 d17ac19a..17245a51 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 @@ -18,7 +18,7 @@ import { ErrorDisplay } from './ErrorDisplay.js'; import { OnError, ServiceSendLLMMessageParams } from '../../../../../../../platform/void/common/llmMessageTypes.js'; import { HistoryInputBox, InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js'; import { TextAreaFns, VoidCodeEditorProps, VoidInputBox2 } from '../util/inputs.js'; -import { ModelDropdown } from '../void-settings-tsx/ModelDropdown.js'; +import { ModelDropdown, WarningBox } from '../void-settings-tsx/ModelDropdown.js'; import { chat_systemMessage, chat_prompt } from '../../../prompt/prompts.js'; import { ISidebarStateService } from '../../../sidebarStateService.js'; import { ILLMMessageService } from '../../../../../../../platform/void/common/llmMessageService.js'; @@ -29,6 +29,7 @@ import { VOID_CTRL_L_ACTION_ID } from '../../../actionIDs.js'; import { ArrowBigLeftDash, CopyX, Delete, FileX2, SquareX, X } from 'lucide-react'; import { filenameToVscodeLanguage } from '../../../helpers/detectLanguage.js'; import { Pencil } from 'lucide-react' +import { VOID_OPEN_SETTINGS_ACTION_ID } from '../../../voidSettingsPane.js'; export const IconX = ({ size, className = '', ...props }: { size: number, className?: string } & React.SVGProps) => { @@ -438,10 +439,47 @@ export const SelectedFiles = ( -const ChatBubble = ({ chatMessage, isLoading }: { - chatMessage: ChatMessage, - isLoading?: boolean, -}) => { +const ChatBubble_ = ({ isEditMode, isLoading, children, role }: { role: ChatMessage['role'], children: React.ReactNode, isLoading: boolean, isEditMode: boolean }) => { + + return
+
+ {children} + {isLoading && } +
+ + {/* edit button */} + {/* {role === 'user' && + { setIsEditMode(v => !v); }} + /> + } */} +
+} + + +const ChatBubble = ({ chatMessage, isLoading }: { chatMessage: ChatMessage, isLoading?: boolean, }) => { const role = chatMessage.role @@ -480,41 +518,9 @@ const ChatBubble = ({ chatMessage, isLoading }: { chatbubbleContents = } - return
-
- {chatbubbleContents} - {isLoading && } -
- - {/* edit button */} - {/* {role === 'user' && - { setIsEditMode(v => !v); }} - /> - } */} -
+ return + {chatbubbleContents} + } @@ -524,7 +530,8 @@ export const SidebarChat = () => { const textAreaFnsRef = useRef(null) const accessor = useAccessor() - const modelService = accessor.get('IModelService') + // const modelService = accessor.get('IModelService') + const commandService = accessor.get('ICommandService') // ----- HIGHER STATE ----- // sidebar state @@ -549,11 +556,10 @@ export const SidebarChat = () => { const selections = chatThreadsState.currentStagingSelections // stream state - const chatThreadsStreamState = useChatThreadsStreamState(chatThreadsState.currentThreadId) - const streamingToken = chatThreadsStreamState?.streamingToken - const isStreaming = !!streamingToken - const latestError = chatThreadsStreamState?.error - const messageSoFar = chatThreadsStreamState?.messageSoFar + const currThreadStreamState = useChatThreadsStreamState(chatThreadsState.currentThreadId) + const isStreaming = !!currThreadStreamState?.streamingToken + const latestError = currThreadStreamState?.error + const messageSoFar = currThreadStreamState?.messageSoFar // ----- SIDEBAR CHAT state (local) ----- @@ -585,9 +591,8 @@ export const SidebarChat = () => { } const onAbort = () => { - // this assumes an instant cancellation doesn't happen, since streamingToken state must have updated by this time - if (!streamingToken) return - chatThreadsService.cancelStreaming(streamingToken) + const threadId = currentThread.id + chatThreadsService.cancelStreaming(threadId) } // const [_test_messages, _set_test_messages] = useState([]) @@ -617,7 +622,7 @@ export const SidebarChat = () => { scrollContainerRef={scrollContainerRef} className={` w-full h-auto - flex flex-col gap-0 + flex flex-col gap-1 overflow-x-hidden overflow-y-auto `} @@ -631,6 +636,21 @@ export const SidebarChat = () => { {/* message stream */} + + {/* error message */} + {latestError === undefined ? null : +
+ { chatThreadsService.dismissStreamError(currentThread.id) }} + showDismiss={true} + /> + + { commandService.executeCommand(VOID_OPEN_SETTINGS_ACTION_ID) }} text='Open settings' /> +
+ } + @@ -655,18 +675,7 @@ export const SidebarChat = () => { {/* top row */} <> {/* selections */} - - - - {/* error message */} - {latestError === undefined ? null : - { chatThreadsService.dismissStreamError(currentThread.id) }} - showDismiss={true} - /> - } + {/* middle row */}