From 62e16572746c6da9131de88af2a5ba3cb249cc10 Mon Sep 17 00:00:00 2001 From: mp Date: Mon, 9 Dec 2024 19:45:45 -0800 Subject: [PATCH 1/4] change config key + merge --- src/vs/workbench/contrib/void/browser/registerConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/void/browser/registerConfig.ts b/src/vs/workbench/contrib/void/browser/registerConfig.ts index a8d1884d..b56d6bb6 100644 --- a/src/vs/workbench/contrib/void/browser/registerConfig.ts +++ b/src/vs/workbench/contrib/void/browser/registerConfig.ts @@ -14,7 +14,7 @@ import { defaultVoidProviderState, ProviderName, VoidProviderState } from '../.. -const VOID_CONFIG_KEY = 'void.partialVoidConfig' +const VOID_CONFIG_KEY = 'void.config' type SetStateFn = ( providerName: K, From 24fdb1ca0d6dc7b977147c97ad09b193082cb4ec Mon Sep 17 00:00:00 2001 From: mp Date: Tue, 10 Dec 2024 17:29:55 -0800 Subject: [PATCH 2/4] minor changes --- src/vs/platform/void/common/configTypes.ts | 2 +- .../react/src/sidebar-tsx/SidebarChat.tsx | 34 +++++++++---------- .../contrib/void/browser/registerThreads.ts | 8 ++--- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/vs/platform/void/common/configTypes.ts b/src/vs/platform/void/common/configTypes.ts index c9eac9ee..2b698fb0 100644 --- a/src/vs/platform/void/common/configTypes.ts +++ b/src/vs/platform/void/common/configTypes.ts @@ -254,7 +254,7 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName else if (settingName === 'endpoint') { return { title: providerName === 'ollama' ? 'The endpoint of your Ollama instance.' : - providerName === 'openAICompatible' ? 'The baseUrl (exluding /chat/completions).' + providerName === 'openAICompatible' ? 'The baseUrl (excluding /chat/completions).' : '(never)', type: 'string', placeholder: providerName === 'ollama' || providerName === 'openAICompatible' ? 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 70168aa5..d3a7a014 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 @@ -47,7 +47,7 @@ export const SelectedFiles = (
{selections.map((selection, i) => ( - + {/* selection display summary */} - {/* selection text */} + {/* selection full text */} {type === 'staging' && selection.selectionStr && { @@ -96,9 +96,8 @@ export const SelectedFiles = ( const ChatBubble = ({ chatMessage }: { chatMessage: ChatMessage }) => { const role = chatMessage.role - const children = chatMessage.displayContent - if (!children) + if (!chatMessage.displayContent) return null let chatbubbleContents: React.ReactNode @@ -106,11 +105,11 @@ const ChatBubble = ({ chatMessage }: { chatMessage: ChatMessage }) => { if (role === 'user') { chatbubbleContents = <> - {children} + {chatMessage.displayContent} } else if (role === 'assistant') { - chatbubbleContents = // sectionsHTML + chatbubbleContents = // sectionsHTML } return
@@ -143,7 +142,6 @@ export const SidebarChat = () => { // config state const voidConfigState = useConfigState() - // threads state const threadsState = useThreadsState() const threadsStateService = useService('threadsStateService') @@ -184,15 +182,13 @@ export const SidebarChat = () => { const systemPromptElt: ChatMessage = { role: 'system', content: generateDiffInstructions } threadsStateService.addMessageToCurrentThread(systemPromptElt) - const userContent = userInstructionsStr(instructions, selections) - const userHistoryElt: ChatMessage = { role: 'user', content: userContent, displayContent: instructions, selections } + // add user's message to chat history + const userHistoryElt: ChatMessage = { role: 'user', content: userInstructionsStr(instructions, selections), displayContent: instructions, selections } threadsStateService.addMessageToCurrentThread(userHistoryElt) const currentThread = threadsStateService.getCurrentThread(threadsStateService.state) // the the instant state right now, don't wait for the React state - // send message to LLM - const object: LLMMessageServiceParams = { logging: { loggingName: 'Chat' }, messages: [...(currentThread?.messages ?? []).map(m => ({ role: m.role, content: m.content || '(null)' })),], @@ -238,7 +234,7 @@ export const SidebarChat = () => { } const onAbort = () => { - // abort the LLM + // abort the LLM call if (latestRequestIdRef.current) sendLLMMessageService.abort(latestRequestIdRef.current) @@ -263,12 +259,13 @@ export const SidebarChat = () => { {currentThread !== null && currentThread?.messages.map((message, i) => )} + {/* message stream */}
- {/* chatbar */} +
- {/* selection */} + {/* input box */}
@@ -282,8 +279,10 @@ export const SidebarChat = () => { { setLatestError(null) }} - />} + /> + } + {/* user input box */}
{ onSubmit={(e) => { console.log('submit!') onSubmit(e) - }}> + }} + > - {/* input */} + {/* text input */} Date: Wed, 11 Dec 2024 20:02:07 -0800 Subject: [PATCH 3/4] Sidebar restructure --- ...ringifyFiles.ts => stringifySelections.ts} | 9 +- .../react/src/sidebar-tsx/SidebarChat.tsx | 204 ++++++++++++------ .../browser/react/src/sidebar-tsx/inputs.tsx | 9 + .../contrib/void/browser/registerThreads.ts | 4 +- 4 files changed, 159 insertions(+), 67 deletions(-) rename src/vs/workbench/contrib/void/browser/prompt/{stringifyFiles.ts => stringifySelections.ts} (75%) diff --git a/src/vs/workbench/contrib/void/browser/prompt/stringifyFiles.ts b/src/vs/workbench/contrib/void/browser/prompt/stringifySelections.ts similarity index 75% rename from src/vs/workbench/contrib/void/browser/prompt/stringifyFiles.ts rename to src/vs/workbench/contrib/void/browser/prompt/stringifySelections.ts index 11056b43..45be6d8d 100644 --- a/src/vs/workbench/contrib/void/browser/prompt/stringifyFiles.ts +++ b/src/vs/workbench/contrib/void/browser/prompt/stringifySelections.ts @@ -1,13 +1,16 @@ import { CodeSelection } from '../registerThreads.js'; -export const filesStr = (selections: CodeSelection[]) => { +export const stringifySelections = (selections: CodeSelection[]) => { + + return selections.map(({ fileURI, content, selectionStr }) => `\ File: ${fileURI.fsPath} \`\`\` -${content} +${content // this was the enite file which is foolish + } \`\`\`${selectionStr === null ? '' : ` Selection: ${selectionStr}`} `).join('\n') @@ -17,7 +20,7 @@ Selection: ${selectionStr}`} export const userInstructionsStr = (instructions: string, selections: CodeSelection[] | null) => { let str = ''; if (selections && selections.length > 0) { - str += filesStr(selections); + str += stringifySelections(selections); str += `Please edit the selected code following these instructions:\n` } str += `${instructions}`; 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 d3a7a014..509985f3 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 @@ -5,9 +5,9 @@ import React, { FormEvent, Fragment, useCallback, useEffect, useRef, useState } from 'react'; -import { useConfigState, useService, useThreadsState } from '../util/services.js'; +import { useConfigState, useService, useSidebarState, useThreadsState } from '../util/services.js'; import { generateDiffInstructions } from '../../../prompt/systemPrompts.js'; -import { userInstructionsStr } from '../../../prompt/stringifyFiles.js'; +import { userInstructionsStr } from '../../../prompt/stringifySelections.js'; import { ChatMessage, CodeSelection, CodeStagingSelection } from '../../../registerThreads.js'; import { BlockCode } from '../markdown/BlockCode.js'; @@ -22,6 +22,68 @@ import { getCmdKey } from '../../../getCmdKey.js' import { HistoryInputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js'; import { VoidInputBox } from './inputs.js'; + +const IconX = ({ size, className = '' }: { size: number, className?: string }) => { + return ( + + + + ); +}; + + +const IconArrowUp = ({ size, className = '' }: { size: number, className?: string }) => { + return ( + + + + + ); +}; + + +const IconSquare = ({ size, className = '' }: { size: number, className?: string }) => { + return ( + + + + ); +}; + + // read files from VSCode const VSReadFile = async (modelService: IModelService, uri: URI): Promise => { const model = modelService.getModel(uri) @@ -42,49 +104,67 @@ export const SelectedFiles = ( | { type: 'past', selections: CodeSelection[] | null; setStaging?: undefined } | { type: 'staging', selections: CodeStagingSelection[] | null; setStaging: ((files: CodeStagingSelection[]) => void) } ) => { + + // index -> isOpened + const [selectionIsOpened, setSelectionIsOpened] = useState<(boolean)[]>(selections?.map(() => false) ?? []) + return ( !!selections && selections.length !== 0 && (
{selections.map((selection, i) => ( - {/* selection display summary */} - + + + } +
{/* selection full text */} - {type === 'staging' && selection.selectionStr && { - setStaging([...selections.slice(0, i), { ...selection, selectionStr: null }, ...selections.slice(i + 1, Infinity)]) - }} - className="btn btn-secondary btn-sm border border-vscode-input-border rounded" - >Remove - )} />} + {type === 'staging' && selection.selectionStr && selectionIsOpened[i] && + { // clear the selection string but keep the file + // // setStaging([...selections.slice(0, i), { ...selection, selectionStr: null }, ...selections.slice(i + 1, Infinity)]) + // // }} + // onClick={() => { + // if (type !== 'staging') return + // setStaging([...selections.slice(0, i), ...selections.slice(i + 1, Infinity)]) + // }} + // className="btn btn-secondary btn-sm border border-vscode-input-border rounded" + // >Remove + // )} + /> + } ))}
@@ -171,19 +251,33 @@ export const SidebarChat = () => { if (isLoading) return - const currSelns = threadsStateService.state._currentStagingSelections + + const currSelns = threadsStateService.state._currentStagingSelections ?? [] const selections = !currSelns ? null : await Promise.all( currSelns.map(async (sel) => ({ ...sel, content: await VSReadFile(modelService, sel.fileURI) })) ).then( (files) => files.filter(file => file.content !== null) as CodeSelection[] ) + + // // TODO don't save files to the thread history + // const selectedSnippets = currSelns.filter(sel => sel.selectionStr !== null) + // const selectedFiles = await Promise.all( // do not add these to the context history + // currSelns.filter(sel => sel.selectionStr === null) + // .map(async (sel) => ({ ...sel, content: await VSReadFile(modelService, sel.fileURI) })) + // ).then( + // (files) => files.filter(file => file.content !== null) as CodeSelection[] + // ) + // const contextToSendToLLM = '' + // const contextToAddToHistory = '' + + // add system message to chat history const systemPromptElt: ChatMessage = { role: 'system', content: generateDiffInstructions } threadsStateService.addMessageToCurrentThread(systemPromptElt) // add user's message to chat history - const userHistoryElt: ChatMessage = { role: 'user', content: userInstructionsStr(instructions, selections), displayContent: instructions, selections } + const userHistoryElt: ChatMessage = { role: 'user', content: userInstructionsStr(instructions, selections), displayContent: instructions, selections: selections } threadsStateService.addMessageToCurrentThread(userHistoryElt) const currentThread = threadsStateService.getCurrentThread(threadsStateService.state) // the the instant state right now, don't wait for the React state @@ -264,15 +358,17 @@ export const SidebarChat = () => {
+ {/* user input box */}
- {/* input box */}
{/* selections */} - {(selections && selections.length !== 0) &&
- -
} + {(selections && selections.length !== 0) && +
+ +
+ } {/* error message */} {latestError === null ? null : @@ -282,7 +378,6 @@ export const SidebarChat = () => { /> } - {/* user input box */} { initVal='' /> - {/*