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='' /> - {/*