From a9aa9a26ea697fd550f0fd2214f7a2113dda2a6d Mon Sep 17 00:00:00 2001 From: Ismail Pelaseyed Date: Fri, 9 May 2025 14:59:27 +0200 Subject: [PATCH 01/49] feat: add support for applying shellscripts and bash directly to terminal --- .../src/markdown/ApplyBlockHoverButtons.tsx | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx index 41b5a649..7c994e08 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx @@ -243,26 +243,51 @@ export const ApplyButtonsHTML = ({ codeStr, applyBoxId, uri, + language, }: { codeStr: string, applyBoxId: string, -} & ({ + language?: string, +} & { uri: URI | 'current'; -}) -) => { +}) => { const accessor = useAccessor() const editCodeService = accessor.get('IEditCodeService') const metricsService = accessor.get('IMetricsService') + const terminalToolService = accessor.get('ITerminalToolService') const settingsState = useSettingsState() const isDisabled = !!isFeatureNameDisabled('Apply', settingsState) || !applyBoxId const { currStreamStateRef, setApplying } = useApplyStreamState({ applyBoxId }) + const isShellLanguage = language === 'bash' || language === 'shellscript' const onClickSubmit = useCallback(async () => { if (currStreamStateRef.current === 'streaming') return + // For shell scripts, run in terminal instead of applying to file + if (isShellLanguage) { + try { + // Create a terminal if none exists or use terminal 1 + const terminalIds = terminalToolService.listPersistentTerminalIds() + let terminalId = '1'; + if (!terminalIds.includes(terminalId)) { + terminalId = await terminalToolService.createPersistentTerminal({ cwd: null }) + } + await terminalToolService.runCommand( + codeStr, + { type: 'persistent', persistentTerminalId: terminalId } + ); + await terminalToolService.focusPersistentTerminal(terminalId) + metricsService.capture('Execute Shell', { length: codeStr.length }) + } catch (e) { + console.error('Failed to execute in terminal:', e) + } + return; + } + + // Normal file apply logic for non-shell languages await editCodeService.callBeforeApplyOrEdit(uri) const [newApplyingUri, applyDonePromise] = editCodeService.startApplying({ @@ -281,7 +306,7 @@ export const ApplyButtonsHTML = ({ }) metricsService.capture('Apply Code', { length: codeStr.length }) // capture the length only - }, [setApplying, currStreamStateRef, editCodeService, codeStr, uri, applyBoxId, metricsService]) + }, [setApplying, currStreamStateRef, editCodeService, codeStr, uri, applyBoxId, metricsService, isShellLanguage, terminalToolService]) const onClickStop = useCallback(() => { @@ -451,7 +476,7 @@ export const BlockCodeApplyWrapper = ({
{currStreamState === 'idle-no-changes' && } - +
From 168b92f6c4816fe00ec79b211e8d69945a6d01c7 Mon Sep 17 00:00:00 2001 From: Steven Wexler Date: Fri, 9 May 2025 15:38:32 -0600 Subject: [PATCH 02/49] Add Void: Copy Prompt as menu item to the ExplorerContext window --- .../contrib/void/browser/fileService.ts | 89 +++++++++++++++++++ .../contrib/void/browser/void.contribution.ts | 3 + .../contrib/void/common/prompt/prompts.ts | 6 +- 3 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/vs/workbench/contrib/void/browser/fileService.ts diff --git a/src/vs/workbench/contrib/void/browser/fileService.ts b/src/vs/workbench/contrib/void/browser/fileService.ts new file mode 100644 index 00000000..8857feb4 --- /dev/null +++ b/src/vs/workbench/contrib/void/browser/fileService.ts @@ -0,0 +1,89 @@ +import { localize2 } from '../../../../nls.js'; +import { URI } from '../../../../base/common/uri.js'; +import { Action2, registerAction2, MenuId } from '../../../../platform/actions/common/actions.js'; +import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js'; +import { INotificationService } from '../../../../platform/notification/common/notification.js'; +import { IFileService } from '../../../../platform/files/common/files.js'; +import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js'; +import { IDirectoryStrService } from '../common/directoryStrService.js'; +import { readFile, DEFAULT_FILE_SIZE_LIMIT } from '../common/prompt/prompts.js'; + + + +async function filePrompt(fileService: IFileService, uri: URI, clipboardService: IClipboardService): Promise { + const { val } = await readFile(fileService, uri, DEFAULT_FILE_SIZE_LIMIT) + const fileName = uri.fsPath.split('/').pop() ?? '' + if (!val) { + throw new Error('Failed to copy prompt') + } + const prompt = ` +${fileName}: +\`\`\` +${val} +\`\`\``.trim() + return prompt +} + +/** + * Add a menu item to the explorer context menu that copies a prompt for the selected file or directory. + * + * Example file prompt: + * + * ``` + * index.js: + * \`\`\` + * console.log('Hello World!'); + * \`\`\` + * + * Example directory prompt: + * ``` + * Directory of /path/to/src: + * src/ + * ├── index.ts + * ├── src.ts + * ├── latest/ + * │ ├── index.ts + * │ └── src.ts + * ├── types.ts + * └── util.ts + * ``` + */ +class FilePromptActionService extends Action2 { + private static readonly VOID_COPY_FILE_PROMPT_ID = 'void.copyfileprompt' + + constructor() { + super({ + id: FilePromptActionService.VOID_COPY_FILE_PROMPT_ID, + title: localize2('voidCopyPrompt', "Void: Copy Prompt"), + menu: [{ + id: MenuId.ExplorerContext, + group: '8_void', + order: 1, + }] + }); + } + + async run(accessor: ServicesAccessor, uri: URI): Promise { + try { + const fileService = accessor.get(IFileService); + const clipboardService = accessor.get(IClipboardService) + const directoryStrService = accessor.get(IDirectoryStrService) + const stat = await fileService.resolve(uri) + const prompt = stat.isFile + ? await filePrompt(fileService, uri, clipboardService) + : await directoryStrService.getDirectoryStrTool(uri) + await clipboardService.writeText(prompt) + } catch (error) { + const notificationService = accessor.get(INotificationService) + FilePromptActionService._onError(notificationService, error) + } + } + + private static _onError(notificationService: INotificationService, error: Error) { + const errorMessage = localize2('voidCopyPromptError', 'Failed to copy prompt') + notificationService.error(errorMessage.value) + throw error + } +} + +registerAction2(FilePromptActionService) diff --git a/src/vs/workbench/contrib/void/browser/void.contribution.ts b/src/vs/workbench/contrib/void/browser/void.contribution.ts index c0e84606..3ab89abf 100644 --- a/src/vs/workbench/contrib/void/browser/void.contribution.ts +++ b/src/vs/workbench/contrib/void/browser/void.contribution.ts @@ -58,6 +58,9 @@ import './voidOnboardingService.js' // register misc service import './miscWokrbenchContrib.js' +// register file service (for explorer context menu) +import './fileService.js' + // ---------- common (unclear if these actually need to be imported, because they're already imported wherever they're used) ---------- // llmMessage diff --git a/src/vs/workbench/contrib/void/common/prompt/prompts.ts b/src/vs/workbench/contrib/void/common/prompt/prompts.ts index 613142b8..5f53cd07 100644 --- a/src/vs/workbench/contrib/void/common/prompt/prompts.ts +++ b/src/vs/workbench/contrib/void/common/prompt/prompts.ts @@ -525,7 +525,9 @@ ${details.map((d, i) => `${i + 1}. ${d}`).join('\n\n')}`) // chat_systemMessage({ chatMode, workspaceFolders: [], openedURIs: [], activeURI: 'pee', persistentTerminalIDs: [], directoryStr: 'lol', })) // } -const readFile = async (fileService: IFileService, uri: URI, fileSizeLimit: number): Promise<{ +export const DEFAULT_FILE_SIZE_LIMIT = 2_000_000 + +export const readFile = async (fileService: IFileService, uri: URI, fileSizeLimit: number): Promise<{ val: string, truncated: boolean, fullFileLen: number, @@ -561,7 +563,7 @@ export const chat_userMessageContent = async (instructions: string, currSelns: S selnsStrs = await Promise.all(currSelns?.map(async (s) => { if (s.type === 'File' || s.type === 'CodeSelection') { - const { val } = await readFile(opts.fileService, s.uri, 2_000_000) + const { val } = await readFile(opts.fileService, s.uri, DEFAULT_FILE_SIZE_LIMIT) const lineNumAdd = s.type === 'CodeSelection' ? lineNumAddition(s.range) : '' const content = val === null ? 'null' : `${tripleTick[0]}${s.language}\n${val}\n${tripleTick[1]}` const str = `${s.uri.fsPath}${lineNumAdd}:\n${content}` From 08274637e15ffc70ddca913f302c3cf5f28f3fd9 Mon Sep 17 00:00:00 2001 From: Steven Wexler Date: Fri, 9 May 2025 15:40:34 -0600 Subject: [PATCH 03/49] Small touchups --- src/vs/workbench/contrib/void/browser/fileService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/fileService.ts b/src/vs/workbench/contrib/void/browser/fileService.ts index 8857feb4..518803ed 100644 --- a/src/vs/workbench/contrib/void/browser/fileService.ts +++ b/src/vs/workbench/contrib/void/browser/fileService.ts @@ -9,7 +9,6 @@ import { IDirectoryStrService } from '../common/directoryStrService.js'; import { readFile, DEFAULT_FILE_SIZE_LIMIT } from '../common/prompt/prompts.js'; - async function filePrompt(fileService: IFileService, uri: URI, clipboardService: IClipboardService): Promise { const { val } = await readFile(fileService, uri, DEFAULT_FILE_SIZE_LIMIT) const fileName = uri.fsPath.split('/').pop() ?? '' @@ -54,7 +53,7 @@ class FilePromptActionService extends Action2 { constructor() { super({ id: FilePromptActionService.VOID_COPY_FILE_PROMPT_ID, - title: localize2('voidCopyPrompt', "Void: Copy Prompt"), + title: localize2('voidCopyPrompt', 'Void: Copy Prompt'), menu: [{ id: MenuId.ExplorerContext, group: '8_void', From 5232b4c30c67546d42748a3749ee215381e2424f Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sat, 10 May 2025 02:28:40 -0700 Subject: [PATCH 04/49] update prompt to work better in agent --- src/vs/workbench/contrib/void/common/prompt/prompts.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/void/common/prompt/prompts.ts b/src/vs/workbench/contrib/void/common/prompt/prompts.ts index 613142b8..c558dba1 100644 --- a/src/vs/workbench/contrib/void/common/prompt/prompts.ts +++ b/src/vs/workbench/contrib/void/common/prompt/prompts.ts @@ -479,12 +479,13 @@ ${directoryStr} details.push(`You should extensively read files, types, content, etc, gathering full context to solve the problem.`) } - - if (mode === 'gather' || mode === 'normal') { - details.push(`If you write any code blocks, please use this format: + details.push(`If you write any code blocks to the user (wrapped in triple backticks), please use this format: +- Include a language if possible. Terminal should have the language 'shell'. - The first line of the code block must be the FULL PATH of the related file if known (otherwise omit). - The remaining contents of the file should proceed as usual.`) + if (mode === 'gather' || mode === 'normal') { + details.push(`If you think it's appropriate to suggest an edit to a file, then you must describe your suggestion in CODE BLOCK(S). - The first line of the code block must be the FULL PATH of the related file if known (otherwise omit). - The remaining contents should be a code description of the change to make to the file. \ From d6295e5d659532b2d6dba671a1607317d786d397 Mon Sep 17 00:00:00 2001 From: Hunter Evangelista Date: Sun, 11 May 2025 16:02:17 -0700 Subject: [PATCH 05/49] added optional json config for VoidStaticModelInfo --- src/vs/workbench/contrib/void/common/modelCapabilities.ts | 5 ++++- .../void/electron-main/llmMessage/sendLLMMessage.impl.ts | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/void/common/modelCapabilities.ts b/src/vs/workbench/contrib/void/common/modelCapabilities.ts index e9eec31b..c254535f 100644 --- a/src/vs/workbench/contrib/void/common/modelCapabilities.ts +++ b/src/vs/workbench/contrib/void/common/modelCapabilities.ts @@ -153,6 +153,9 @@ export type VoidStaticModelInfo = { // not stateful specialToolFormat?: 'openai-style' | 'anthropic-style' | 'gemini-style', // typically you should use 'openai-style'. null means "can't call tools by default", and asks the LLM to output XML in agent mode supportsFIM: boolean; // whether the model was specifically designed for autocomplete or "FIM" ("fill-in-middle" format) + // do we need any additional information? + additionalConfig?: { [key: string]: string } // additional info for openAI requests + // reasoning options reasoningCapabilities: false | { readonly supportsReasoning: true; // for clarity, this must be true if anything below is specified @@ -186,7 +189,7 @@ export type VoidStaticModelInfo = { // not stateful export type ModelOverrides = Pick diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 4eec4850..66aa67b4 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -236,6 +236,7 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE modelName, specialToolFormat, reasoningCapabilities, + additionalConfig } = getModelCapabilities(providerName, modelName_, overridesOfModel) const { providerReasoningIOSettings } = getProviderCapabilities(providerName) @@ -245,8 +246,11 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE const reasoningInfo = getSendableReasoningInfo('Chat', providerName, modelName_, modelSelectionOptions, overridesOfModel) // user's modelName_ here const includeInPayload = providerReasoningIOSettings?.input?.includeInPayload?.(reasoningInfo) || {} + const additionalOpenAIPayload = additionalConfig || {} + console.log('include', includeInPayload) console.log('reasoningInfo', reasoningInfo) + console.log('additionalOpenAIPayload', additionalOpenAIPayload) // tools const potentialTools = chatMode !== null ? openAITools(chatMode) : null const nativeToolsObj = potentialTools && specialToolFormat === 'openai-style' ? @@ -260,6 +264,7 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE messages: messages as any, stream: true, ...nativeToolsObj, + ...additionalOpenAIPayload // max_completion_tokens: maxTokens, } From 970fd7ecbb59fc0dcac2a162121cfbf1e382966c Mon Sep 17 00:00:00 2001 From: Hunter Evangelista Date: Sun, 11 May 2025 17:09:47 -0700 Subject: [PATCH 06/49] moved payload to sdk initialization --- .../void/electron-main/llmMessage/sendLLMMessage.impl.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 7dfd63ff..007b4413 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -68,10 +68,11 @@ const parseHeadersJSON = (s: string | undefined): Record { +const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includeInPayload, additionalOpenAIPayload }: { settingsOfProvider: SettingsOfProvider, providerName: ProviderName, includeInPayload?: { [s: string]: any }, additionalOpenAIPayload?: { [s: string]: string } }) => { const commonPayloadOpts: ClientOptions = { dangerouslyAllowBrowser: true, ...includeInPayload, + ...additionalOpenAIPayload } if (providerName === 'openAI') { const thisConfig = settingsOfProvider[providerName] @@ -256,7 +257,7 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE : {} // instance - const openai: OpenAI = await newOpenAICompatibleSDK({ providerName, settingsOfProvider, includeInPayload }) + const openai: OpenAI = await newOpenAICompatibleSDK({ providerName, settingsOfProvider, includeInPayload, additionalOpenAIPayload }) const options: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming = { model: modelName, messages: messages as any, From dd42e40a8d38408b3487221e6ec28ceccd4c2be4 Mon Sep 17 00:00:00 2001 From: Ujjwal Jain Date: Sun, 11 May 2025 22:01:04 -0400 Subject: [PATCH 07/49] fix: preserve selection when adding to chat via CTRL+L with closed panel --- .../contrib/void/browser/sidebarActions.ts | 41 ++++++++----------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/sidebarActions.ts b/src/vs/workbench/contrib/void/browser/sidebarActions.ts index 0e962e09..a2db29ea 100644 --- a/src/vs/workbench/contrib/void/browser/sidebarActions.ts +++ b/src/vs/workbench/contrib/void/browser/sidebarActions.ts @@ -89,10 +89,7 @@ registerAction2(class extends Action2 { }); } async run(accessor: ServicesAccessor): Promise { - - - // Get the views service to check if the sidebar is open - // const viewsService = accessor.get(IViewsService) + // Get services const commandService = accessor.get(ICommandService) const viewsService = accessor.get(IViewsService) const metricsService = accessor.get(IMetricsService) @@ -101,31 +98,28 @@ registerAction2(class extends Action2 { metricsService.capture('Ctrl+L', {}) + // Capture selection and model BEFORE opening the chat panel + const editor = editorService.getActiveCodeEditor() + const model = editor?.getModel() + if (!model) return + + const selectionRange = roundRangeToLines(editor?.getSelection(), { emptySelectionBehavior: 'null' }) + + // Now check if panel is open and open it if needed const wasAlreadyOpen = viewsService.isViewContainerVisible(VOID_VIEW_CONTAINER_ID) if (!wasAlreadyOpen) { await commandService.executeCommand(VOID_OPEN_SIDEBAR_ACTION_ID) - return } - - // if was already open - - const model = accessor.get(ICodeEditorService).getActiveCodeEditor()?.getModel() - if (!model) return - - const editor = editorService.getActiveCodeEditor() - const selectionRange = roundRangeToLines(editor?.getSelection(), { emptySelectionBehavior: 'null' }) - - // if has no selection, close + return - // if (!selectionRange) { - // viewsService.closeViewContainer(VOID_VIEW_CONTAINER_ID); - // return; - // } - - + // Add selection to chat (whether it was already open or we just opened it) // add line selection if (selectionRange) { - editor?.setSelection({ startLineNumber: selectionRange.startLineNumber, endLineNumber: selectionRange.endLineNumber, startColumn: 1, endColumn: Number.MAX_SAFE_INTEGER }) + editor?.setSelection({ + startLineNumber: selectionRange.startLineNumber, + endLineNumber: selectionRange.endLineNumber, + startColumn: 1, + endColumn: Number.MAX_SAFE_INTEGER + }) chatThreadService.addNewStagingSelection({ type: 'CodeSelection', uri: model.uri, @@ -142,12 +136,9 @@ registerAction2(class extends Action2 { language: model.getLanguageId(), state: { wasAddedAsCurrentFile: false }, }) - } await chatThreadService.focusCurrentChat() - - } }) From 9a905f6cb2cc1937b3bb42ed109d0c2410941cc5 Mon Sep 17 00:00:00 2001 From: Ismail Pelaseyed Date: Mon, 12 May 2025 09:06:22 +0200 Subject: [PATCH 08/49] add support for stopping the terminal command --- .../src/markdown/ApplyBlockHoverButtons.tsx | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx index 89137cbc..b158acc2 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx @@ -264,25 +264,30 @@ export const ApplyButtonsHTML = ({ const isShellLanguage = language === 'bash' || language === 'shellscript' + const [isShellRunning, setIsShellRunning] = useState(false) + const interruptToolRef = useRef<(() => void) | null>(null) + const onClickSubmit = useCallback(async () => { - if (currStreamStateRef.current === 'streaming') return + if (currStreamStateRef.current === 'streaming' || isShellRunning) return // For shell scripts, run in terminal instead of applying to file if (isShellLanguage) { try { + setIsShellRunning(true) // Create a terminal if none exists or use terminal 1 const terminalIds = terminalToolService.listPersistentTerminalIds() let terminalId = '1'; if (!terminalIds.includes(terminalId)) { terminalId = await terminalToolService.createPersistentTerminal({ cwd: null }) } - await terminalToolService.runCommand( + const { interrupt } = await terminalToolService.runCommand( codeStr, { type: 'persistent', persistentTerminalId: terminalId } ); - await terminalToolService.focusPersistentTerminal(terminalId) + interruptToolRef.current = interrupt metricsService.capture('Execute Shell', { length: codeStr.length }) } catch (e) { + setIsShellRunning(false) console.error('Failed to execute in terminal:', e) } return; @@ -338,6 +343,19 @@ export const ApplyButtonsHTML = ({ const currStreamState = currStreamStateRef.current console.log('currStreamState...', currStreamState) + if (isShellRunning) { + return ( + { + interruptToolRef.current?.(); + setIsShellRunning(false); + }} + {...tooltipPropsForApplyBlock({ tooltipName: 'Stop' })} + /> + ); + } + if (currStreamState === 'streaming') { return Date: Mon, 12 May 2025 11:50:25 -0700 Subject: [PATCH 09/49] use 1st terminal id --- .../react/src/markdown/ApplyBlockHoverButtons.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx index b158acc2..99847fe0 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx @@ -248,7 +248,6 @@ export const ApplyButtonsHTML = ({ codeStr: string, applyBoxId: string, language?: string, -} & { uri: URI | 'current'; }) => { const accessor = useAccessor() @@ -270,16 +269,19 @@ export const ApplyButtonsHTML = ({ const onClickSubmit = useCallback(async () => { if (currStreamStateRef.current === 'streaming' || isShellRunning) return - // For shell scripts, run in terminal instead of applying to file + // for shell scripts, run in terminal instead of applying to file if (isShellLanguage) { try { setIsShellRunning(true) - // Create a terminal if none exists or use terminal 1 + // create a terminal if none exists or use terminal 1 const terminalIds = terminalToolService.listPersistentTerminalIds() - let terminalId = '1'; - if (!terminalIds.includes(terminalId)) { + + let terminalId: string + if (terminalIds.length !== 0) + terminalId = terminalIds[0] // use 1st terminal id + else terminalId = await terminalToolService.createPersistentTerminal({ cwd: null }) - } + const { interrupt } = await terminalToolService.runCommand( codeStr, { type: 'persistent', persistentTerminalId: terminalId } From e8b7c9c470957b3734e7827e804061c721418ecb Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 11:56:08 -0700 Subject: [PATCH 10/49] always create terminal when apply --- .../react/src/markdown/ApplyBlockHoverButtons.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx index 786fb737..94fae35b 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx @@ -273,14 +273,7 @@ export const ApplyButtonsHTML = ({ if (isShellLanguage) { try { setIsShellRunning(true) - // create a terminal if none exists or use terminal 1 - const terminalIds = terminalToolService.listPersistentTerminalIds() - - let terminalId: string - if (terminalIds.length !== 0) - terminalId = terminalIds[0] // use 1st terminal id - else - terminalId = await terminalToolService.createPersistentTerminal({ cwd: null }) + const terminalId = await terminalToolService.createPersistentTerminal({ cwd: null }) const { interrupt } = await terminalToolService.runCommand( codeStr, From 3fa680e8bab5c64afa1fd0703d96450392d3f5ae Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 12:09:55 -0700 Subject: [PATCH 11/49] identify more shells --- .../src/markdown/ApplyBlockHoverButtons.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx index 94fae35b..834909b9 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx @@ -239,6 +239,21 @@ export const StatusIndicatorForApplyButton = ({ applyBoxId, uri }: { applyBoxId: } +const terminalLanguages = new Set([ + 'bash', + 'shellscript', + 'shell', + 'powershell', + 'bat', + 'zsh', + 'sh', + 'fish', + 'nushell', + 'ksh', + 'xonsh', + 'elvish', +]) + export const ApplyButtonsHTML = ({ codeStr, applyBoxId, @@ -261,7 +276,7 @@ export const ApplyButtonsHTML = ({ const { currStreamStateRef, setApplying } = useApplyStreamState({ applyBoxId }) - const isShellLanguage = language === 'bash' || language === 'shellscript' + const isShellLanguage = !!language && terminalLanguages.has(language) const [isShellRunning, setIsShellRunning] = useState(false) const interruptToolRef = useRef<(() => void) | null>(null) From 45f7e4b157dc815dcd2e91c0cd88ad0869ab883d Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 16:48:27 -0700 Subject: [PATCH 12/49] minor updates --- src/vs/workbench/contrib/void/browser/sidebarActions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/sidebarActions.ts b/src/vs/workbench/contrib/void/browser/sidebarActions.ts index a2db29ea..4112745c 100644 --- a/src/vs/workbench/contrib/void/browser/sidebarActions.ts +++ b/src/vs/workbench/contrib/void/browser/sidebarActions.ts @@ -98,20 +98,20 @@ registerAction2(class extends Action2 { metricsService.capture('Ctrl+L', {}) - // Capture selection and model BEFORE opening the chat panel + // capture selection and model before opening the chat panel const editor = editorService.getActiveCodeEditor() const model = editor?.getModel() if (!model) return const selectionRange = roundRangeToLines(editor?.getSelection(), { emptySelectionBehavior: 'null' }) - // Now check if panel is open and open it if needed + // open panel const wasAlreadyOpen = viewsService.isViewContainerVisible(VOID_VIEW_CONTAINER_ID) if (!wasAlreadyOpen) { await commandService.executeCommand(VOID_OPEN_SIDEBAR_ACTION_ID) } - // Add selection to chat (whether it was already open or we just opened it) + // Add selection to chat // add line selection if (selectionRange) { editor?.setSelection({ From 7066b4285b281345c3d3ef80342c07aba21fff65 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 18:20:44 -0700 Subject: [PATCH 13/49] file and folder copy uniform --- .../contrib/void/browser/fileService.ts | 88 ++++++++----------- .../contrib/void/common/prompt/prompts.ts | 86 +++++++++++------- 2 files changed, 93 insertions(+), 81 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/fileService.ts b/src/vs/workbench/contrib/void/browser/fileService.ts index 518803ed..93da1b1e 100644 --- a/src/vs/workbench/contrib/void/browser/fileService.ts +++ b/src/vs/workbench/contrib/void/browser/fileService.ts @@ -6,47 +6,11 @@ import { INotificationService } from '../../../../platform/notification/common/n import { IFileService } from '../../../../platform/files/common/files.js'; import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js'; import { IDirectoryStrService } from '../common/directoryStrService.js'; -import { readFile, DEFAULT_FILE_SIZE_LIMIT } from '../common/prompt/prompts.js'; +import { messageOfSelection } from '../common/prompt/prompts.js'; +import { IVoidModelService } from '../common/voidModelService.js'; -async function filePrompt(fileService: IFileService, uri: URI, clipboardService: IClipboardService): Promise { - const { val } = await readFile(fileService, uri, DEFAULT_FILE_SIZE_LIMIT) - const fileName = uri.fsPath.split('/').pop() ?? '' - if (!val) { - throw new Error('Failed to copy prompt') - } - const prompt = ` -${fileName}: -\`\`\` -${val} -\`\`\``.trim() - return prompt -} -/** - * Add a menu item to the explorer context menu that copies a prompt for the selected file or directory. - * - * Example file prompt: - * - * ``` - * index.js: - * \`\`\` - * console.log('Hello World!'); - * \`\`\` - * - * Example directory prompt: - * ``` - * Directory of /path/to/src: - * src/ - * ├── index.ts - * ├── src.ts - * ├── latest/ - * │ ├── index.ts - * │ └── src.ts - * ├── types.ts - * └── util.ts - * ``` - */ class FilePromptActionService extends Action2 { private static readonly VOID_COPY_FILE_PROMPT_ID = 'void.copyfileprompt' @@ -67,22 +31,48 @@ class FilePromptActionService extends Action2 { const fileService = accessor.get(IFileService); const clipboardService = accessor.get(IClipboardService) const directoryStrService = accessor.get(IDirectoryStrService) - const stat = await fileService.resolve(uri) - const prompt = stat.isFile - ? await filePrompt(fileService, uri, clipboardService) - : await directoryStrService.getDirectoryStrTool(uri) - await clipboardService.writeText(prompt) + const voidModelService = accessor.get(IVoidModelService) + + const stat = await fileService.stat(uri) + + const folderOpts = { + maxChildren: 1000, + maxCharsPerFile: 2_000_000, + } as const + + let m: string = 'No contents detected' + if (stat.isFile) { + m = await messageOfSelection({ + type: 'File', + uri, + language: (await voidModelService.getModelSafe(uri)).model?.getLanguageId() || '', + state: { wasAddedAsCurrentFile: false, }, + }, { + folderOpts, + directoryStrService, + fileService, + }) + } + + if (stat.isDirectory) { + m = await messageOfSelection({ + type: 'Folder', + uri, + }, { + folderOpts, + fileService, + directoryStrService, + }) + } + + await clipboardService.writeText(m) + } catch (error) { const notificationService = accessor.get(INotificationService) - FilePromptActionService._onError(notificationService, error) + notificationService.error(error + '') } } - private static _onError(notificationService: INotificationService, error: Error) { - const errorMessage = localize2('voidCopyPromptError', 'Failed to copy prompt') - notificationService.error(errorMessage.value) - throw error - } } registerAction2(FilePromptActionService) diff --git a/src/vs/workbench/contrib/void/common/prompt/prompts.ts b/src/vs/workbench/contrib/void/common/prompt/prompts.ts index 5f53cd07..a4c0daa8 100644 --- a/src/vs/workbench/contrib/void/common/prompt/prompts.ts +++ b/src/vs/workbench/contrib/void/common/prompt/prompts.ts @@ -551,46 +551,68 @@ export const readFile = async (fileService: IFileService, uri: URI, fileSizeLimi +export const messageOfSelection = async ( + s: StagingSelectionItem, + opts: { + directoryStrService: IDirectoryStrService, + fileService: IFileService, + folderOpts: { + maxChildren: number, + maxCharsPerFile: number, + } + } +) => { + const lineNumAddition = (range: [number, number]) => ` (lines ${range[0]}:${range[1]})` + + if (s.type === 'File' || s.type === 'CodeSelection') { + const { val } = await readFile(opts.fileService, s.uri, DEFAULT_FILE_SIZE_LIMIT) + const lineNumAdd = s.type === 'CodeSelection' ? lineNumAddition(s.range) : '' + const content = val === null ? 'null' : `${tripleTick[0]}${s.language}\n${val}\n${tripleTick[1]}` + const str = `${s.uri.fsPath}${lineNumAdd}:\n${content}` + return str + } + else if (s.type === 'Folder') { + const dirStr: string = await opts.directoryStrService.getDirectoryStrTool(s.uri) + const folderStructure = `${s.uri.fsPath} folder structure:${tripleTick[0]}\n${dirStr}\n${tripleTick[1]}` + + const uris = await opts.directoryStrService.getAllURIsInDirectory(s.uri, { maxResults: opts.folderOpts.maxChildren }) + const strOfFiles = await Promise.all(uris.map(async uri => { + const { val, truncated } = await readFile(opts.fileService, uri, opts.folderOpts.maxCharsPerFile) + const truncationStr = truncated ? `\n... file truncated ...` : '' + const content = val === null ? 'null' : `${tripleTick[0]}\n${val}${truncationStr}\n${tripleTick[1]}` + const str = `${uri.fsPath}:\n${content}` + return str + })) + const contentStr = [folderStructure, ...strOfFiles].join('\n\n') + return contentStr + } + else + return '' + +} - -export const chat_userMessageContent = async (instructions: string, currSelns: StagingSelectionItem[] | null, - opts: { directoryStrService: IDirectoryStrService, fileService: IFileService } +export const chat_userMessageContent = async ( + instructions: string, + currSelns: StagingSelectionItem[] | null, + opts: { + directoryStrService: IDirectoryStrService, + fileService: IFileService + }, ) => { - const lineNumAddition = (range: [number, number]) => ` (lines ${range[0]}:${range[1]})` - let selnsStrs: string[] = [] - selnsStrs = await Promise.all(currSelns?.map(async (s) => { + const selnsStrs = await Promise.all((currSelns ?? []).map(async (s) => + messageOfSelection(s, { + ...opts, + folderOpts: { maxChildren: 100, maxCharsPerFile: 100_000, } + }) + )) - if (s.type === 'File' || s.type === 'CodeSelection') { - const { val } = await readFile(opts.fileService, s.uri, DEFAULT_FILE_SIZE_LIMIT) - const lineNumAdd = s.type === 'CodeSelection' ? lineNumAddition(s.range) : '' - const content = val === null ? 'null' : `${tripleTick[0]}${s.language}\n${val}\n${tripleTick[1]}` - const str = `${s.uri.fsPath}${lineNumAdd}:\n${content}` - return str - } - else if (s.type === 'Folder') { - const dirStr: string = await opts.directoryStrService.getDirectoryStrTool(s.uri) - const folderStructure = `${s.uri.fsPath} folder structure:${tripleTick[0]}\n${dirStr}\n${tripleTick[1]}` - const uris = await opts.directoryStrService.getAllURIsInDirectory(s.uri, { maxResults: 100 }) - const strOfFiles = await Promise.all(uris.map(async uri => { - const { val, truncated } = await readFile(opts.fileService, uri, 100_000) - const truncationStr = truncated ? `\n... file truncated ...` : '' - const content = val === null ? 'null' : `${tripleTick[0]}\n${val}${truncationStr}\n${tripleTick[1]}` - const str = `${uri.fsPath}:\n${content}` - return str - })) - const contentStr = [folderStructure, ...strOfFiles].join('\n\n') - return contentStr - } - else - return '' - }) ?? []) - - const selnsStr = selnsStrs.join('\n') ?? '' let str = '' str += `${instructions}` + + const selnsStr = selnsStrs.join('\n\n') ?? '' if (selnsStr) str += `\n---\nSELECTIONS\n${selnsStr}` return str; } From f98894ad77c36423a07ba29c54196827b6b04064 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 18:22:59 -0700 Subject: [PATCH 14/49] format --- .../contrib/void/common/prompt/prompts.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/void/common/prompt/prompts.ts b/src/vs/workbench/contrib/void/common/prompt/prompts.ts index b5cae7cb..5746067e 100644 --- a/src/vs/workbench/contrib/void/common/prompt/prompts.ts +++ b/src/vs/workbench/contrib/void/common/prompt/prompts.ts @@ -605,12 +605,14 @@ export const chat_userMessageContent = async ( }, ) => { - const selnsStrs = await Promise.all((currSelns ?? []).map(async (s) => - messageOfSelection(s, { - ...opts, - folderOpts: { maxChildren: 100, maxCharsPerFile: 100_000, } - }) - )) + const selnsStrs = await Promise.all( + (currSelns ?? []).map(async (s) => + messageOfSelection(s, { + ...opts, + folderOpts: { maxChildren: 100, maxCharsPerFile: 100_000, } + }) + ) + ) let str = '' From 1c6edf70234e812327218eea17e99f6fe362ecda Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 18:45:33 -0700 Subject: [PATCH 15/49] generalize --- .../src/markdown/ApplyBlockHoverButtons.tsx | 134 +++++++++++------- 1 file changed, 86 insertions(+), 48 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx index 834909b9..4674f9a0 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx @@ -254,7 +254,69 @@ const terminalLanguages = new Set([ 'elvish', ]) -export const ApplyButtonsHTML = ({ +const ApplyButtonsForTerminal = ({ + codeStr, + applyBoxId, + uri, + language, +}: { + codeStr: string, + applyBoxId: string, + language?: string, + uri: URI | 'current'; +}) => { + const accessor = useAccessor() + const metricsService = accessor.get('IMetricsService') + const terminalToolService = accessor.get('ITerminalToolService') + + const settingsState = useSettingsState() + const isDisabled = !!isFeatureNameDisabled('Apply', settingsState) || !applyBoxId + + const [isShellRunning, setIsShellRunning] = useState(false) + const interruptToolRef = useRef<(() => void) | null>(null) + + const onClickSubmit = useCallback(async () => { + if (isShellRunning) return + try { + setIsShellRunning(true) + const terminalId = await terminalToolService.createPersistentTerminal({ cwd: null }) + const { interrupt } = await terminalToolService.runCommand( + codeStr, + { type: 'persistent', persistentTerminalId: terminalId } + ); + interruptToolRef.current = interrupt + metricsService.capture('Execute Shell', { length: codeStr.length }) + } catch (e) { + setIsShellRunning(false) + console.error('Failed to execute in terminal:', e) + } + }, [codeStr, uri, applyBoxId, metricsService, terminalToolService, isShellRunning]) + + if (isShellRunning) { + return ( + { + interruptToolRef.current?.(); + setIsShellRunning(false); + }} + {...tooltipPropsForApplyBlock({ tooltipName: 'Stop' })} + /> + ); + } + if (isDisabled) { + return null + } + return +} + + + +const ApplyButtonsForEdit = ({ codeStr, applyBoxId, uri, @@ -268,7 +330,6 @@ export const ApplyButtonsHTML = ({ const accessor = useAccessor() const editCodeService = accessor.get('IEditCodeService') const metricsService = accessor.get('IMetricsService') - const terminalToolService = accessor.get('ITerminalToolService') const notificationService = accessor.get('INotificationService') const settingsState = useSettingsState() @@ -276,34 +337,9 @@ export const ApplyButtonsHTML = ({ const { currStreamStateRef, setApplying } = useApplyStreamState({ applyBoxId }) - const isShellLanguage = !!language && terminalLanguages.has(language) - - const [isShellRunning, setIsShellRunning] = useState(false) - const interruptToolRef = useRef<(() => void) | null>(null) - const onClickSubmit = useCallback(async () => { - if (currStreamStateRef.current === 'streaming' || isShellRunning) return + if (currStreamStateRef.current === 'streaming') return - // for shell scripts, run in terminal instead of applying to file - if (isShellLanguage) { - try { - setIsShellRunning(true) - const terminalId = await terminalToolService.createPersistentTerminal({ cwd: null }) - - const { interrupt } = await terminalToolService.runCommand( - codeStr, - { type: 'persistent', persistentTerminalId: terminalId } - ); - interruptToolRef.current = interrupt - metricsService.capture('Execute Shell', { length: codeStr.length }) - } catch (e) { - setIsShellRunning(false) - console.error('Failed to execute in terminal:', e) - } - return; - } - - // Normal file apply logic for non-shell languages await editCodeService.callBeforeApplyOrEdit(uri) const [newApplyingUri, applyDonePromise] = editCodeService.startApplying({ @@ -327,7 +363,7 @@ export const ApplyButtonsHTML = ({ }) metricsService.capture('Apply Code', { length: codeStr.length }) // capture the length only - }, [setApplying, currStreamStateRef, editCodeService, codeStr, uri, applyBoxId, metricsService, isShellLanguage, terminalToolService]) + }, [setApplying, currStreamStateRef, editCodeService, codeStr, uri, applyBoxId, metricsService, notificationService]) const onClickStop = useCallback(() => { @@ -349,22 +385,7 @@ export const ApplyButtonsHTML = ({ if (uri) editCodeService.acceptOrRejectAllDiffAreas({ uri: uri, behavior: 'reject', removeCtrlKs: false }) }, [uri, applyBoxId, editCodeService]) - const currStreamState = currStreamStateRef.current - - if (isShellRunning) { - return ( - { - interruptToolRef.current?.(); - setIsShellRunning(false); - }} - {...tooltipPropsForApplyBlock({ tooltipName: 'Stop' })} - /> - ); - } - if (currStreamState === 'streaming') { return } - if (isDisabled) { return null } - - if (currStreamState === 'idle-no-changes') { return } - if (currStreamState === 'idle-has-changes') { return { + const { language } = params + const isShellLanguage = !!language && terminalLanguages.has(language) + + if (isShellLanguage) { + return + } + else { + return + } +} + + + + + export const EditToolAcceptRejectButtonsHTML = ({ codeStr, applyBoxId, From 3772cf98eabd17518c3ef50ca44170c4a1801662 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 18:47:40 -0700 Subject: [PATCH 16/49] delete --- src/vs/workbench/contrib/void/browser/terminalToolService.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/void/browser/terminalToolService.ts b/src/vs/workbench/contrib/void/browser/terminalToolService.ts index b079eb5a..d5bb5228 100644 --- a/src/vs/workbench/contrib/void/browser/terminalToolService.ts +++ b/src/vs/workbench/contrib/void/browser/terminalToolService.ts @@ -277,6 +277,8 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ terminal.dispose() if (!isPersistent) delete this.temporaryTerminalInstanceOfId[params.terminalId] + else + delete this.persistentTerminalInstanceOfId[params.persistentTerminalId] } const waitForResult = async () => { From 67ed52415e5ad88bbe0dbcc6fd6716f31d4939bf Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 19:29:45 -0700 Subject: [PATCH 17/49] apply terminal? --- .../workbench/contrib/void/browser/terminalToolService.ts | 7 ++++++- src/vs/workbench/contrib/void/browser/toolsService.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/terminalToolService.ts b/src/vs/workbench/contrib/void/browser/terminalToolService.ts index d5bb5228..2e18511b 100644 --- a/src/vs/workbench/contrib/void/browser/terminalToolService.ts +++ b/src/vs/workbench/contrib/void/browser/terminalToolService.ts @@ -22,7 +22,12 @@ export interface ITerminalToolService { readonly _serviceBrand: undefined; listPersistentTerminalIds(): string[]; - runCommand(command: string, opts: { type: 'persistent', persistentTerminalId: string } | { type: 'ephemeral', cwd: string | null, terminalId: string }): Promise<{ interrupt: () => void; resPromise: Promise<{ result: string, resolveReason: TerminalResolveReason }> }>; + runCommand(command: string, opts: + | { type: 'persistent', persistentTerminalId: string } + | { type: 'temporary', cwd: string | null, terminalId: string } + // | { type: 'apply', terminalId: string } + ): Promise<{ interrupt: () => void; resPromise: Promise<{ result: string, resolveReason: TerminalResolveReason }> }>; + focusPersistentTerminal(terminalId: string): Promise persistentTerminalExists(terminalId: string): boolean diff --git a/src/vs/workbench/contrib/void/browser/toolsService.ts b/src/vs/workbench/contrib/void/browser/toolsService.ts index bba085d8..02edf047 100644 --- a/src/vs/workbench/contrib/void/browser/toolsService.ts +++ b/src/vs/workbench/contrib/void/browser/toolsService.ts @@ -430,7 +430,7 @@ export class ToolsService implements IToolsService { }, // --- run_command: async ({ command, cwd, terminalId }) => { - const { resPromise, interrupt } = await this.terminalToolService.runCommand(command, { type: 'ephemeral', cwd, terminalId }) + const { resPromise, interrupt } = await this.terminalToolService.runCommand(command, { type: 'temporary', cwd, terminalId }) return { result: resPromise, interruptTool: interrupt } }, run_persistent_command: async ({ command, persistentTerminalId }) => { From 28dcdff189fba6c0e868f6e67ff56cf40a6a1975 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 19:31:05 -0700 Subject: [PATCH 18/49] isdisabled fix --- .../void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx index 4674f9a0..93e26b0d 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx @@ -270,10 +270,10 @@ const ApplyButtonsForTerminal = ({ const terminalToolService = accessor.get('ITerminalToolService') const settingsState = useSettingsState() - const isDisabled = !!isFeatureNameDisabled('Apply', settingsState) || !applyBoxId const [isShellRunning, setIsShellRunning] = useState(false) const interruptToolRef = useRef<(() => void) | null>(null) + const isDisabled = isShellRunning const onClickSubmit = useCallback(async () => { if (isShellRunning) return From f65e4f51a24ba9e27fe85ed6eafc423d72ff777f Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 19:40:39 -0700 Subject: [PATCH 19/49] misc --- .../contrib/void/common/modelCapabilities.ts | 11 ++++++--- .../llmMessage/sendLLMMessage.impl.ts | 23 +++++++++++-------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/void/common/modelCapabilities.ts b/src/vs/workbench/contrib/void/common/modelCapabilities.ts index 4a1750e3..52cc3947 100644 --- a/src/vs/workbench/contrib/void/common/modelCapabilities.ts +++ b/src/vs/workbench/contrib/void/common/modelCapabilities.ts @@ -153,8 +153,7 @@ export type VoidStaticModelInfo = { // not stateful specialToolFormat?: 'openai-style' | 'anthropic-style' | 'gemini-style', // typically you should use 'openai-style'. null means "can't call tools by default", and asks the LLM to output XML in agent mode supportsFIM: boolean; // whether the model was specifically designed for autocomplete or "FIM" ("fill-in-middle" format) - // do we need any additional information? - additionalConfig?: { [key: string]: string } // additional info for openAI requests + additionalOpenAIPayload?: { [key: string]: string } // additional info for openAI requests // reasoning options reasoningCapabilities: false | { @@ -189,7 +188,13 @@ export type VoidStaticModelInfo = { // not stateful export type ModelOverrides = Pick diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 007b4413..c58daeb7 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -68,11 +68,10 @@ const parseHeadersJSON = (s: string | undefined): Record { +const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includeInPayload }: { settingsOfProvider: SettingsOfProvider, providerName: ProviderName, includeInPayload?: { [s: string]: any } }) => { const commonPayloadOpts: ClientOptions = { dangerouslyAllowBrowser: true, ...includeInPayload, - ...additionalOpenAIPayload } if (providerName === 'openAI') { const thisConfig = settingsOfProvider[providerName] @@ -148,7 +147,12 @@ const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includ const _sendOpenAICompatibleFIM = async ({ messages: { prefix, suffix, stopTokens }, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, overridesOfModel }: SendFIMParams_Internal) => { - const { modelName, supportsFIM } = getModelCapabilities(providerName, modelName_, overridesOfModel) + const { + modelName, + supportsFIM, + additionalOpenAIPayload, + } = getModelCapabilities(providerName, modelName_, overridesOfModel) + if (!supportsFIM) { if (modelName === modelName_) onError({ message: `Model ${modelName} does not support FIM.`, fullError: null }) @@ -157,7 +161,7 @@ const _sendOpenAICompatibleFIM = async ({ messages: { prefix, suffix, stopTokens return } - const openai = await newOpenAICompatibleSDK({ providerName, settingsOfProvider }) + const openai = await newOpenAICompatibleSDK({ providerName, settingsOfProvider, includeInPayload: additionalOpenAIPayload }) openai.completions .create({ model: modelName, @@ -237,7 +241,7 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE modelName, specialToolFormat, reasoningCapabilities, - additionalConfig + additionalOpenAIPayload, } = getModelCapabilities(providerName, modelName_, overridesOfModel) const { providerReasoningIOSettings } = getProviderCapabilities(providerName) @@ -245,10 +249,11 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE // reasoning const { canIOReasoning, openSourceThinkTags } = reasoningCapabilities || {} const reasoningInfo = getSendableReasoningInfo('Chat', providerName, modelName_, modelSelectionOptions, overridesOfModel) // user's modelName_ here - const includeInPayload = providerReasoningIOSettings?.input?.includeInPayload?.(reasoningInfo) || {} - - const additionalOpenAIPayload = additionalConfig || {} + const includeInPayload = { + ...providerReasoningIOSettings?.input?.includeInPayload?.(reasoningInfo), + ...additionalOpenAIPayload + } // tools const potentialTools = chatMode !== null ? openAITools(chatMode) : null @@ -257,7 +262,7 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE : {} // instance - const openai: OpenAI = await newOpenAICompatibleSDK({ providerName, settingsOfProvider, includeInPayload, additionalOpenAIPayload }) + const openai: OpenAI = await newOpenAICompatibleSDK({ providerName, settingsOfProvider, includeInPayload }) const options: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming = { model: modelName, messages: messages as any, From 2e5ecb291d33afbe4565921664fb7e183189c1c5 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 19:44:42 -0700 Subject: [PATCH 20/49] comment --- src/vs/workbench/contrib/void/common/modelCapabilities.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/void/common/modelCapabilities.ts b/src/vs/workbench/contrib/void/common/modelCapabilities.ts index 6048f143..8e338d07 100644 --- a/src/vs/workbench/contrib/void/common/modelCapabilities.ts +++ b/src/vs/workbench/contrib/void/common/modelCapabilities.ts @@ -153,6 +153,8 @@ export type VoidStaticModelInfo = { // not stateful specialToolFormat?: 'openai-style' | 'anthropic-style' | 'gemini-style', // typically you should use 'openai-style'. null means "can't call tools by default", and asks the LLM to output XML in agent mode supportsFIM: boolean; // whether the model was specifically designed for autocomplete or "FIM" ("fill-in-middle" format) + additionalOpenAIPayload?: { [key: string]: string } // additional payload in the message body for requests that are openai-compatible (ollama, vllm, openai, openrouter, etc) + // reasoning options reasoningCapabilities: false | { readonly supportsReasoning: true; // for clarity, this must be true if anything below is specified From 2e64f5a24be24d0b5e42aee31df2b71f5622edb3 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 19:46:18 -0700 Subject: [PATCH 21/49] overrides link update --- .../void/browser/react/src/void-settings-tsx/Settings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx index 2200dee7..9fa3e7cb 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx @@ -276,7 +276,7 @@ const SimpleModelSettingsDialog = ({ onClose(); }; - const sourcecodeOverridesLink = `https://github.com/voideditor/void/blob/d33b5ff9a32a748a22ac99e543a9eedd2e600062/src/vs/workbench/contrib/void/common/modelCapabilities.ts#L146-L170` + const sourcecodeOverridesLink = `https://github.com/voideditor/void/blob/2e5ecb291d33afbe4565921664fb7e183189c1c5/src/vs/workbench/contrib/void/common/modelCapabilities.ts#L146-L172` return (
Date: Mon, 12 May 2025 19:48:50 -0700 Subject: [PATCH 22/49] fix azure? --- .../void/electron-main/llmMessage/sendLLMMessage.impl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 5174e910..a1c90675 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -115,7 +115,7 @@ const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includ else if (providerName === 'microsoftAzure') { // https://learn.microsoft.com/en-us/rest/api/aifoundry/model-inference/get-chat-completions/get-chat-completions?view=rest-aifoundry-model-inference-2024-05-01-preview&tabs=HTTP const thisConfig = settingsOfProvider[providerName] - const baseURL = `https://${thisConfig.project}.services.ai.azure.com/api/models/chat/completions??api-version=${thisConfig.azureApiVersion}` + const baseURL = `https://${thisConfig.project}.services.ai.azure.com/api/models/chat/completions?api-version=${thisConfig.azureApiVersion}` return new OpenAI({ baseURL: baseURL, apiKey: thisConfig.apiKey, ...commonPayloadOpts }) } From b54dd7fedcb0c0069787bf0126679dd2340640bd Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 19:53:58 -0700 Subject: [PATCH 23/49] 1.3.7 / 0031 --- product.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/product.json b/product.json index d4d8b671..568a2416 100644 --- a/product.json +++ b/product.json @@ -1,8 +1,8 @@ { "nameShort": "Void", "nameLong": "Void", - "voidVersion": "1.3.6", - "voidRelease": "0030", + "voidVersion": "1.3.7", + "voidRelease": "0031", "applicationName": "void", "dataFolderName": ".void-editor", "win32MutexName": "voideditor", From f4c1321f256d707e6e401aff93498283a7061c83 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 12 May 2025 20:08:54 -0700 Subject: [PATCH 24/49] rm thinking from 2 flash --- src/vs/workbench/contrib/void/common/modelCapabilities.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/void/common/modelCapabilities.ts b/src/vs/workbench/contrib/void/common/modelCapabilities.ts index fe1fc7ac..a5afb521 100644 --- a/src/vs/workbench/contrib/void/common/modelCapabilities.ts +++ b/src/vs/workbench/contrib/void/common/modelCapabilities.ts @@ -791,13 +791,7 @@ const geminiModelOptions = { // https://ai.google.dev/gemini-api/docs/pricing supportsFIM: false, supportsSystemMessage: 'separated', specialToolFormat: 'gemini-style', - reasoningCapabilities: { // thinking: experimental as of 5-10-25 - supportsReasoning: true, - canTurnOffReasoning: true, - canIOReasoning: false, - reasoningSlider: { type: 'budget_slider', min: 1024, max: 8192, default: 1024 }, // max is really 24576 - reasoningReservedOutputTokenSpace: 8192, - }, + reasoningCapabilities: false, }, 'gemini-2.0-flash-lite-preview-02-05': { contextWindow: 1_048_576, From 6df3b588dfa55d48ec5b198eaa0ef8acc534246b Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 17:25:29 -0700 Subject: [PATCH 25/49] fix anthropic empty err message --- .../workbench/contrib/void/browser/convertToLLMMessageService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/void/browser/convertToLLMMessageService.ts b/src/vs/workbench/contrib/void/browser/convertToLLMMessageService.ts index 1b7df00e..01fd58aa 100644 --- a/src/vs/workbench/contrib/void/browser/convertToLLMMessageService.ts +++ b/src/vs/workbench/contrib/void/browser/convertToLLMMessageService.ts @@ -418,6 +418,7 @@ const prepareOpenAIOrAnthropicMessages = ({ else { // allowed to be empty if has a tool in it or following it if (currMsg.content.find(c => c.type === 'tool_result' || c.type === 'tool_use')) { + currMsg.content = currMsg.content.filter(c => !(c.type === 'text' && !c.text)) as any continue } if (nextMsg?.role === 'tool') continue From 609f4c9cbfc2f256360025d77f854e0104b03bc4 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 17:27:46 -0700 Subject: [PATCH 26/49] UI --- .../void/browser/react/src/sidebar-tsx/SidebarChat.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 0252381b..3587438b 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 @@ -2605,7 +2605,7 @@ const CommandBarInChat = () => { // !select-text cursor-auto - const fileDetailsContent =
+ const fileDetailsContent =
{sortedCommandBarURIs.map((uri, i) => { const basename = getBasename(uri.fsPath) @@ -2856,12 +2856,16 @@ export const SidebarChat = () => { // resolve mount info const isResolved = chatThreadsState.allThreads[threadId]?.state.mountedInfo?.mountedIsResolvedRef.current + useEffect(() => { if (isResolved) return chatThreadsState.allThreads[threadId]?.state.mountedInfo?._whenMountedResolver?.({ textAreaRef: textAreaRef, scrollToBottom: () => scrollToBottom(scrollContainerRef), }) + + // Trigger a window resize event to ensure proper layout calculations + window.dispatchEvent(new Event('resize')) }, [chatThreadsState, threadId, textAreaRef, scrollContainerRef, isResolved]) From b35dfdf4755a2e18f13681a45d32d03e32ea62c8 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 18:29:04 -0700 Subject: [PATCH 27/49] trigger resize --- .../contrib/void/browser/miscWokrbenchContrib.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/vs/workbench/contrib/void/browser/miscWokrbenchContrib.ts b/src/vs/workbench/contrib/void/browser/miscWokrbenchContrib.ts index 49a0d524..83b3ed7b 100644 --- a/src/vs/workbench/contrib/void/browser/miscWokrbenchContrib.ts +++ b/src/vs/workbench/contrib/void/browser/miscWokrbenchContrib.ts @@ -8,6 +8,8 @@ import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase import { IExtensionTransferService } from './extensionTransferService.js'; import { os } from '../common/helpers/systemInfo.js'; import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js'; +import { timeout } from '../../../../base/common/async.js'; +import { getActiveWindow } from '../../../../base/browser/dom.js'; // Onboarding contribution that mounts the component at startup export class MiscWorkbenchContribs extends Disposable implements IWorkbenchContribution { @@ -31,6 +33,16 @@ export class MiscWorkbenchContribs extends Disposable implements IWorkbenchContr this.extensionTransferService.deleteBlacklistExtensions(os) } + + // after some time, trigger a resize event for the blank screen error + timeout(5_000).then(() => { + // Get the active window reference for multi-window support + const targetWindow = getActiveWindow(); + // Trigger a window resize event to ensure proper layout calculations + targetWindow.dispatchEvent(new Event('resize')) + + }) + } } From 78c6baed82d557dd90d650613133011979155da6 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 19:54:45 -0700 Subject: [PATCH 28/49] revert --- .../void/browser/react/src/sidebar-tsx/SidebarChat.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 3587438b..7e60cac8 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 @@ -2856,16 +2856,13 @@ export const SidebarChat = () => { // resolve mount info const isResolved = chatThreadsState.allThreads[threadId]?.state.mountedInfo?.mountedIsResolvedRef.current - useEffect(() => { if (isResolved) return chatThreadsState.allThreads[threadId]?.state.mountedInfo?._whenMountedResolver?.({ textAreaRef: textAreaRef, scrollToBottom: () => scrollToBottom(scrollContainerRef), }) - - // Trigger a window resize event to ensure proper layout calculations - window.dispatchEvent(new Event('resize')) + }, [chatThreadsState, threadId, textAreaRef, scrollContainerRef, isResolved]) From aafe5563339b6a43ff610fc2d136d6a65fd2810d Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 20:00:39 -0700 Subject: [PATCH 29/49] azure via AzureOpenAI --- package-lock.json | 350 ++++++++++++++++-- package.json | 1 + .../llmMessage/sendLLMMessage.impl.ts | 9 +- 3 files changed, 335 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5c783599..3300199e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "license": "MIT", "dependencies": { "@anthropic-ai/sdk": "^0.40.0", + "@azure/identity": "^4.9.1", "@c4312/eventsource-umd": "^3.0.5", "@floating-ui/react": "^0.27.8", "@google/genai": "^0.13.0", @@ -284,7 +285,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "dev": true, "dependencies": { "tslib": "^2.6.2" }, @@ -299,13 +299,31 @@ "dev": true }, "node_modules/@azure/core-auth": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.7.2.tgz", - "integrity": "sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g==", - "dev": true, + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.9.0.tgz", + "integrity": "sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", - "@azure/core-util": "^1.1.0", + "@azure/core-util": "^1.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.4.tgz", + "integrity": "sha512-f7IxTD15Qdux30s2qFARH+JxgwxWLG2Rlr4oSkPGuLWm+1p5y1+C04XGLA0vmX6EtqfutmjvpNmAfgwVIS5hpw==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-rest-pipeline": "^1.20.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.6.1", + "@azure/logger": "^1.0.0", "tslib": "^2.6.2" }, "engines": { @@ -448,18 +466,17 @@ } }, "node_modules/@azure/core-rest-pipeline": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.0.tgz", - "integrity": "sha512-CeuTvsXxCUmEuxH5g/aceuSl6w2EugvNHKAtKKVdiX915EjJJxAwfzNNWZreNnbxHZ2fi0zaM6wwS23x2JVqSQ==", - "dev": true, + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.20.0.tgz", + "integrity": "sha512-ASoP8uqZBS3H/8N8at/XwFr6vYrRP3syTK0EUjDXQy0Y1/AUS+QeIRThKmTNJO2RggvBBxaXDPM7YoIwDGeA0g==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", - "@azure/core-auth": "^1.4.0", + "@azure/core-auth": "^1.8.0", "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.9.0", + "@azure/core-util": "^1.11.0", "@azure/logger": "^1.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", + "@typespec/ts-http-runtime": "^0.2.2", "tslib": "^2.6.2" }, "engines": { @@ -470,7 +487,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.2.tgz", "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==", - "dev": true, "dependencies": { "tslib": "^2.6.2" }, @@ -479,23 +495,90 @@ } }, "node_modules/@azure/core-util": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.9.0.tgz", - "integrity": "sha512-AfalUQ1ZppaKuxPPMsFEUdX6GZPB3d9paR9d/TTL7Ow2De8cJaC7ibi7kWVlFAVPCYo31OcnGymc0R89DX8Oaw==", - "dev": true, + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.12.0.tgz", + "integrity": "sha512-13IyjTQgABPARvG90+N2dXpC+hwp466XCdQXPCRlbWHgd3SJd5Q1VvaBGv6k1BIa4MQm6hAF1UBU1m8QUxV8sQ==", + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", + "@typespec/ts-http-runtime": "^0.2.2", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, + "node_modules/@azure/identity": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.9.1.tgz", + "integrity": "sha512-986D7Cf1AOwYqSDtO/FnMAyk/Jc8qpftkGsxuehoh4F85MhQ4fICBGX/44+X1y78lN4Sqib3Bsoaoh/FvOGgmg==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^4.2.0", + "@azure/msal-node": "^3.5.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/identity/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@azure/identity/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@azure/identity/node_modules/open": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", + "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@azure/logger": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.3.tgz", "integrity": "sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g==", - "dev": true, "dependencies": { "tslib": "^2.2.0" }, @@ -503,6 +586,50 @@ "node": ">=12.0.0" } }, + "node_modules/@azure/msal-browser": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.12.0.tgz", + "integrity": "sha512-WD1lmVWchg7wn1mI7Tr4v7QPyTwK+8Nuyje3jRpOFENLRLEBsdK8VVdTw3C+TypZmYn4cOAdj3zREnuFXgvfIA==", + "license": "MIT", + "dependencies": { + "@azure/msal-common": "15.6.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.6.0.tgz", + "integrity": "sha512-EotmBz42apYGjqiIV9rDUdptaMptpTn4TdGf3JfjLvFvinSe9BJ6ywU92K9ky+t/b0ghbeTSe9RfqlgLh8f2jA==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.5.3.tgz", + "integrity": "sha512-c5mifzHX5mwm5JqMIlURUyp6LEEdKF1a8lmcNRLBo0lD7zpSYPHupa4jHyhJyg9ccLwszLguZJdk2h3ngnXwNw==", + "license": "MIT", + "dependencies": { + "@azure/msal-common": "15.6.0", + "jsonwebtoken": "^9.0.0", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@azure/msal-node/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@azure/storage-blob": { "version": "12.8.0", "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.8.0.tgz", @@ -4257,6 +4384,20 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.2.2.tgz", + "integrity": "sha512-Gz/Sm64+Sq/vklJu1tt9t+4R2lvnud8NbTD/ZfpZtMiUX7YeVpCA8j6NSW8ptwcoLL+NmYANwqP8DV0q/bwl2w==", + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@vscode/deviceid": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@vscode/deviceid/-/deviceid-0.1.1.tgz", @@ -6281,6 +6422,21 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bundle-require": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", @@ -7779,6 +7935,34 @@ "node": ">=4.0.0" } }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/default-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", @@ -13478,6 +13662,39 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-interactive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", @@ -14175,6 +14392,49 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -14732,11 +14992,40 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "license": "MIT" }, "node_modules/lodash.memoize": { @@ -14752,6 +15041,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, "node_modules/lodash.some": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", @@ -19455,6 +19750,18 @@ "node": ">=16" } }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", @@ -22255,7 +22562,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD" }, "node_modules/tsscmp": { diff --git a/package.json b/package.json index 7a5bc366..199c8a2e 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ }, "dependencies": { "@anthropic-ai/sdk": "^0.40.0", + "@azure/identity": "^4.9.1", "@c4312/eventsource-umd": "^3.0.5", "@floating-ui/react": "^0.27.8", "@google/genai": "^0.13.0", diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 2e05c62d..e861e118 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -7,7 +7,8 @@ /* eslint-disable */ import Anthropic from '@anthropic-ai/sdk'; import { Ollama } from 'ollama'; -import OpenAI, { ClientOptions } from 'openai'; +import OpenAI, { ClientOptions, AzureOpenAI } from 'openai'; +import { getBearerTokenProvider, DefaultAzureCredential } from '@azure/identity'; import { MistralCore } from '@mistralai/mistralai/core.js'; import { fimComplete } from '@mistralai/mistralai/funcs/fimComplete.js'; import { Tool as GeminiTool, FunctionDeclaration, GoogleGenAI, ThinkingConfig, Schema, Type } from '@google/genai'; @@ -114,9 +115,11 @@ const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includ } else if (providerName === 'microsoftAzure') { // https://learn.microsoft.com/en-us/rest/api/aifoundry/model-inference/get-chat-completions/get-chat-completions?view=rest-aifoundry-model-inference-2024-05-01-preview&tabs=HTTP + const credential = new DefaultAzureCredential() const thisConfig = settingsOfProvider[providerName] - const baseURL = `https://${thisConfig.project}.services.ai.azure.com/api/models/chat/completions?api-version=${thisConfig.azureApiVersion}` - return new OpenAI({ baseURL: baseURL, apiKey: thisConfig.apiKey, ...commonPayloadOpts }) + const scope = thisConfig.project + const azureADTokenProvider = getBearerTokenProvider(credential, scope) + return new AzureOpenAI({ azureADTokenProvider, apiVersion: thisConfig.azureApiVersion }) } else if (providerName === 'deepseek') { From e771edbe2ea4af5a822a3cd0c83580d9d89ceab5 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 20:04:40 -0700 Subject: [PATCH 30/49] update azure --- .../void/electron-main/llmMessage/sendLLMMessage.impl.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index e861e118..a398c46a 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -8,7 +8,6 @@ import Anthropic from '@anthropic-ai/sdk'; import { Ollama } from 'ollama'; import OpenAI, { ClientOptions, AzureOpenAI } from 'openai'; -import { getBearerTokenProvider, DefaultAzureCredential } from '@azure/identity'; import { MistralCore } from '@mistralai/mistralai/core.js'; import { fimComplete } from '@mistralai/mistralai/funcs/fimComplete.js'; import { Tool as GeminiTool, FunctionDeclaration, GoogleGenAI, ThinkingConfig, Schema, Type } from '@google/genai'; @@ -115,11 +114,8 @@ const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includ } else if (providerName === 'microsoftAzure') { // https://learn.microsoft.com/en-us/rest/api/aifoundry/model-inference/get-chat-completions/get-chat-completions?view=rest-aifoundry-model-inference-2024-05-01-preview&tabs=HTTP - const credential = new DefaultAzureCredential() const thisConfig = settingsOfProvider[providerName] - const scope = thisConfig.project - const azureADTokenProvider = getBearerTokenProvider(credential, scope) - return new AzureOpenAI({ azureADTokenProvider, apiVersion: thisConfig.azureApiVersion }) + return new AzureOpenAI({ apiKey: thisConfig.apiKey, apiVersion: thisConfig.azureApiVersion, project: thisConfig.project }) } else if (providerName === 'deepseek') { From 96000273cf19db0dd8312979f10671bdb9816046 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 20:05:35 -0700 Subject: [PATCH 31/49] payload --- .../void/electron-main/llmMessage/sendLLMMessage.impl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index a398c46a..513ec0e6 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -115,7 +115,7 @@ const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includ else if (providerName === 'microsoftAzure') { // https://learn.microsoft.com/en-us/rest/api/aifoundry/model-inference/get-chat-completions/get-chat-completions?view=rest-aifoundry-model-inference-2024-05-01-preview&tabs=HTTP const thisConfig = settingsOfProvider[providerName] - return new AzureOpenAI({ apiKey: thisConfig.apiKey, apiVersion: thisConfig.azureApiVersion, project: thisConfig.project }) + return new AzureOpenAI({ apiKey: thisConfig.apiKey, apiVersion: thisConfig.azureApiVersion, project: thisConfig.project, ...commonPayloadOpts }) } else if (providerName === 'deepseek') { From 8c760980b692a5ae3135a151d9c8781774a52a2e Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 21:00:20 -0700 Subject: [PATCH 32/49] fix grok 3 --- .../contrib/void/common/modelCapabilities.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/void/common/modelCapabilities.ts b/src/vs/workbench/contrib/void/common/modelCapabilities.ts index a5afb521..005f5dc6 100644 --- a/src/vs/workbench/contrib/void/common/modelCapabilities.ts +++ b/src/vs/workbench/contrib/void/common/modelCapabilities.ts @@ -84,8 +84,8 @@ export const defaultModelsOfProvider = { 'claude-3-opus-latest', ], xAI: [ // https://docs.x.ai/docs/models?cluster=us-east-1 - 'grok-2-latest', - 'grok-3-latest', + 'grok-2', + 'grok-3', ], gemini: [ // https://ai.google.dev/gemini-api/docs/models/gemini 'gemini-2.5-pro-exp-03-25', @@ -386,7 +386,8 @@ const extensiveModelOptionsFallback: VoidStaticProviderInfo['modelOptionsFallbac if (lower.includes('claude-3-5') || lower.includes('claude-3.5')) return toFallback(anthropicModelOptions, 'claude-3-5-sonnet-20241022') if (lower.includes('claude')) return toFallback(anthropicModelOptions, 'claude-3-7-sonnet-20250219') - if (lower.includes('grok')) return toFallback(xAIModelOptions, 'grok-2') + if (lower.includes('grok2') || lower.includes('grok2')) return toFallback(xAIModelOptions, 'grok-2') + if (lower.includes('grok')) return toFallback(xAIModelOptions, 'grok-3') if (lower.includes('deepseek-r1') || lower.includes('deepseek-reasoner')) return toFallback(openSourceModelOptions_assumingOAICompat, 'deepseekR1') if (lower.includes('deepseek') && lower.includes('v2')) return toFallback(openSourceModelOptions_assumingOAICompat, 'deepseekCoderV2') @@ -667,6 +668,7 @@ const xAIModelOptions = { downloadable: false, supportsFIM: false, supportsSystemMessage: 'system-role', + specialToolFormat: 'openai-style', reasoningCapabilities: false, }, 'grok-3': { @@ -676,6 +678,7 @@ const xAIModelOptions = { downloadable: false, supportsFIM: false, supportsSystemMessage: 'system-role', + specialToolFormat: 'openai-style', reasoningCapabilities: false, }, 'grok-3-fast': { @@ -685,6 +688,7 @@ const xAIModelOptions = { downloadable: false, supportsFIM: false, supportsSystemMessage: 'system-role', + specialToolFormat: 'openai-style', reasoningCapabilities: false, }, // only mini supports thinking @@ -695,6 +699,7 @@ const xAIModelOptions = { downloadable: false, supportsFIM: false, supportsSystemMessage: 'system-role', + specialToolFormat: 'openai-style', reasoningCapabilities: { supportsReasoning: true, canTurnOffReasoning: false, canIOReasoning: false, reasoningSlider: { type: 'effort_slider', values: ['low', 'high'], default: 'low' } }, }, 'grok-3-mini-fast': { @@ -704,6 +709,7 @@ const xAIModelOptions = { downloadable: false, supportsFIM: false, supportsSystemMessage: 'system-role', + specialToolFormat: 'openai-style', reasoningCapabilities: { supportsReasoning: true, canTurnOffReasoning: false, canIOReasoning: false, reasoningSlider: { type: 'effort_slider', values: ['low', 'high'], default: 'low' } }, }, } as const satisfies { [s: string]: VoidStaticModelInfo } @@ -714,6 +720,7 @@ const xAISettings: VoidStaticProviderInfo = { const lower = modelName.toLowerCase() let fallbackName: keyof typeof xAIModelOptions | null = null if (lower.includes('grok-2')) fallbackName = 'grok-2' + if (lower.includes('grok-3')) fallbackName = 'grok-3' if (fallbackName) return { modelName: fallbackName, recognizedModelName: fallbackName, ...xAIModelOptions[fallbackName] } return null }, From 7fd06b946baca66d3305d365ed9ea046186d0911 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 21:00:47 -0700 Subject: [PATCH 33/49] fallback --- src/vs/workbench/contrib/void/common/modelCapabilities.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/void/common/modelCapabilities.ts b/src/vs/workbench/contrib/void/common/modelCapabilities.ts index 005f5dc6..a5bc858e 100644 --- a/src/vs/workbench/contrib/void/common/modelCapabilities.ts +++ b/src/vs/workbench/contrib/void/common/modelCapabilities.ts @@ -721,6 +721,7 @@ const xAISettings: VoidStaticProviderInfo = { let fallbackName: keyof typeof xAIModelOptions | null = null if (lower.includes('grok-2')) fallbackName = 'grok-2' if (lower.includes('grok-3')) fallbackName = 'grok-3' + if (lower.includes('grok')) fallbackName = 'grok-3' if (fallbackName) return { modelName: fallbackName, recognizedModelName: fallbackName, ...xAIModelOptions[fallbackName] } return null }, From 4b9e2c2319ec7ccc5ee9c41be02c94de0f38074a Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 21:02:44 -0700 Subject: [PATCH 34/49] azure link --- .../contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 513ec0e6..a7f6ac31 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -114,6 +114,7 @@ const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includ } else if (providerName === 'microsoftAzure') { // https://learn.microsoft.com/en-us/rest/api/aifoundry/model-inference/get-chat-completions/get-chat-completions?view=rest-aifoundry-model-inference-2024-05-01-preview&tabs=HTTP + // https://github.com/openai/openai-node?tab=readme-ov-file#microsoft-azure-openai const thisConfig = settingsOfProvider[providerName] return new AzureOpenAI({ apiKey: thisConfig.apiKey, apiVersion: thisConfig.azureApiVersion, project: thisConfig.project, ...commonPayloadOpts }) } From 3954056a41fc2ef75f4cd3aa6cb10831cfbc00dc Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 21:32:21 -0700 Subject: [PATCH 35/49] 1.3.8 --- product.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/product.json b/product.json index 568a2416..395bb89f 100644 --- a/product.json +++ b/product.json @@ -1,8 +1,8 @@ { "nameShort": "Void", "nameLong": "Void", - "voidVersion": "1.3.7", - "voidRelease": "0031", + "voidVersion": "1.3.8", + "voidRelease": "0032", "applicationName": "void", "dataFolderName": ".void-editor", "win32MutexName": "voideditor", From e95922802fdec796789709fbab2ca4ac3b50b5c1 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 21:32:57 -0700 Subject: [PATCH 36/49] rm azure identity --- package-lock.json | 306 ++-------------------------------------------- package.json | 1 - 2 files changed, 9 insertions(+), 298 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3300199e..5158d409 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "license": "MIT", "dependencies": { "@anthropic-ai/sdk": "^0.40.0", - "@azure/identity": "^4.9.1", "@c4312/eventsource-umd": "^3.0.5", "@floating-ui/react": "^0.27.8", "@google/genai": "^0.13.0", @@ -285,6 +284,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dev": true, "dependencies": { "tslib": "^2.6.2" }, @@ -302,6 +302,7 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.9.0.tgz", "integrity": "sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==", + "dev": true, "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", @@ -312,24 +313,6 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/core-client": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.4.tgz", - "integrity": "sha512-f7IxTD15Qdux30s2qFARH+JxgwxWLG2Rlr4oSkPGuLWm+1p5y1+C04XGLA0vmX6EtqfutmjvpNmAfgwVIS5hpw==", - "license": "MIT", - "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.20.0", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.6.1", - "@azure/logger": "^1.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@azure/core-http": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-2.2.2.tgz", @@ -469,6 +452,7 @@ "version": "1.20.0", "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.20.0.tgz", "integrity": "sha512-ASoP8uqZBS3H/8N8at/XwFr6vYrRP3syTK0EUjDXQy0Y1/AUS+QeIRThKmTNJO2RggvBBxaXDPM7YoIwDGeA0g==", + "dev": true, "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", @@ -487,6 +471,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.2.tgz", "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==", + "dev": true, "dependencies": { "tslib": "^2.6.2" }, @@ -498,6 +483,7 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.12.0.tgz", "integrity": "sha512-13IyjTQgABPARvG90+N2dXpC+hwp466XCdQXPCRlbWHgd3SJd5Q1VvaBGv6k1BIa4MQm6hAF1UBU1m8QUxV8sQ==", + "dev": true, "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", @@ -508,77 +494,11 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/identity": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.9.1.tgz", - "integrity": "sha512-986D7Cf1AOwYqSDtO/FnMAyk/Jc8qpftkGsxuehoh4F85MhQ4fICBGX/44+X1y78lN4Sqib3Bsoaoh/FvOGgmg==", - "license": "MIT", - "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-auth": "^1.9.0", - "@azure/core-client": "^1.9.2", - "@azure/core-rest-pipeline": "^1.17.0", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.11.0", - "@azure/logger": "^1.0.0", - "@azure/msal-browser": "^4.2.0", - "@azure/msal-node": "^3.5.0", - "open": "^10.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/identity/node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@azure/identity/node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@azure/identity/node_modules/open": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", - "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", - "license": "MIT", - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@azure/logger": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.3.tgz", "integrity": "sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g==", + "dev": true, "dependencies": { "tslib": "^2.2.0" }, @@ -586,50 +506,6 @@ "node": ">=12.0.0" } }, - "node_modules/@azure/msal-browser": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.12.0.tgz", - "integrity": "sha512-WD1lmVWchg7wn1mI7Tr4v7QPyTwK+8Nuyje3jRpOFENLRLEBsdK8VVdTw3C+TypZmYn4cOAdj3zREnuFXgvfIA==", - "license": "MIT", - "dependencies": { - "@azure/msal-common": "15.6.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@azure/msal-common": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.6.0.tgz", - "integrity": "sha512-EotmBz42apYGjqiIV9rDUdptaMptpTn4TdGf3JfjLvFvinSe9BJ6ywU92K9ky+t/b0ghbeTSe9RfqlgLh8f2jA==", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@azure/msal-node": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.5.3.tgz", - "integrity": "sha512-c5mifzHX5mwm5JqMIlURUyp6LEEdKF1a8lmcNRLBo0lD7zpSYPHupa4jHyhJyg9ccLwszLguZJdk2h3ngnXwNw==", - "license": "MIT", - "dependencies": { - "@azure/msal-common": "15.6.0", - "jsonwebtoken": "^9.0.0", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@azure/msal-node/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@azure/storage-blob": { "version": "12.8.0", "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.8.0.tgz", @@ -4388,6 +4264,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.2.2.tgz", "integrity": "sha512-Gz/Sm64+Sq/vklJu1tt9t+4R2lvnud8NbTD/ZfpZtMiUX7YeVpCA8j6NSW8ptwcoLL+NmYANwqP8DV0q/bwl2w==", + "dev": true, "license": "MIT", "dependencies": { "http-proxy-agent": "^7.0.0", @@ -6422,21 +6299,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "license": "MIT", - "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bundle-require": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", @@ -7935,34 +7797,6 @@ "node": ">=4.0.0" } }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "license": "MIT", - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/default-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", @@ -13662,39 +13496,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "license": "MIT", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-inside-container/node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-interactive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", @@ -14392,49 +14193,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "license": "MIT", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jsonwebtoken/node_modules/jwa": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jsonwebtoken/node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "license": "MIT", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -14992,40 +14750,11 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT" - }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, "license": "MIT" }, "node_modules/lodash.memoize": { @@ -15041,12 +14770,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "license": "MIT" - }, "node_modules/lodash.some": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", @@ -19750,18 +19473,6 @@ "node": ">=16" } }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/run-parallel": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", @@ -22562,6 +22273,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, "license": "0BSD" }, "node_modules/tsscmp": { diff --git a/package.json b/package.json index 199c8a2e..7a5bc366 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ }, "dependencies": { "@anthropic-ai/sdk": "^0.40.0", - "@azure/identity": "^4.9.1", "@c4312/eventsource-umd": "^3.0.5", "@floating-ui/react": "^0.27.8", "@google/genai": "^0.13.0", From 9fac1e27a9e218c0bda49a05a1e1cf2a316c36dc Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 13 May 2025 22:58:37 -0700 Subject: [PATCH 37/49] fix certain cases of advanced settings --- .../react/src/void-settings-tsx/Settings.tsx | 40 ++++++++----------- .../contrib/void/common/modelCapabilities.ts | 22 ++++++---- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx index 9fa3e7cb..a133ff49 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx @@ -17,7 +17,7 @@ import { os } from '../../../../common/helpers/systemInfo.js' import { IconLoading } from '../sidebar-tsx/SidebarChat.js' import { ToolApprovalType, toolApprovalTypes } from '../../../../common/toolsServiceTypes.js' import Severity from '../../../../../../../base/common/severity.js' -import { getModelCapabilities, ModelOverrides } from '../../../../common/modelCapabilities.js'; +import { getModelCapabilities, modelOverrideKeys, ModelOverrides } from '../../../../common/modelCapabilities.js'; import { TransferEditorType, TransferFilesInfo } from '../../../extensionTransferTypes.js'; const ButtonLeftTextRightOption = ({ text, leftButton }: { text: string, leftButton?: React.ReactNode }) => { @@ -185,6 +185,11 @@ const ConfirmButton = ({ children, onConfirm, className }: { children: React.Rea }; // ---------------- Simplified Model Settings Dialog ------------------ + +// keys of ModelOverrides we allow the user to override + + + // This new dialog replaces the verbose UI with a single JSON override box. const SimpleModelSettingsDialog = ({ isOpen, @@ -208,39 +213,26 @@ const SimpleModelSettingsDialog = ({ const currentOverrides = settingsState.overridesOfModel?.[providerName]?.[modelName] ?? undefined; const { recognizedModelName, isUnrecognizedModel } = defaultModelCapabilities - // keys of ModelOverrides we allow the user to override - const allowedKeys: (string & (keyof ModelOverrides))[] = [ - 'contextWindow', - 'reservedOutputTokenSpace', - 'supportsSystemMessage', - 'specialToolFormat', - 'supportsFIM', - 'reasoningCapabilities', - ]; - // Create the placeholder with the default values for allowed keys const partialDefaults: Partial = {}; - for (const k of allowedKeys) { if (defaultModelCapabilities[k]) partialDefaults[k] = defaultModelCapabilities[k] as any; } + for (const k of modelOverrideKeys) { if (defaultModelCapabilities[k]) partialDefaults[k] = defaultModelCapabilities[k] as any; } const placeholder = JSON.stringify(partialDefaults, null, 2); const [overrideEnabled, setOverrideEnabled] = useState(() => !!currentOverrides); - const [jsonText, setJsonText] = useState(() => currentOverrides ? JSON.stringify(currentOverrides, null, 2) : placeholder); - const [readOnlyHeight, setReadOnlyHeight] = useState(undefined); const [errorMsg, setErrorMsg] = useState(null); + const textAreaRef = useRef(null) + // reset when dialog toggles useEffect(() => { if (!isOpen) return; const cur = settingsState.overridesOfModel?.[providerName]?.[modelName]; setOverrideEnabled(!!cur); - // If there are overrides, show them; otherwise use default values - setJsonText(cur ? JSON.stringify(cur, null, 2) : placeholder); setErrorMsg(null); }, [isOpen, providerName, modelName, settingsState.overridesOfModel, placeholder]); const onSave = async () => { - // if disabled override, reset overrides if (!overrideEnabled) { await settingsStateService.setOverridesOfModel(providerName, modelName, undefined); @@ -251,9 +243,10 @@ const SimpleModelSettingsDialog = ({ // enabled overrides // parse json let parsedInput: Record - if (jsonText.trim()) { + + if (textAreaRef.current?.value) { try { - parsedInput = JSON.parse(jsonText); + parsedInput = JSON.parse(textAreaRef.current.value); } catch (e) { setErrorMsg('Invalid JSON'); return; @@ -265,10 +258,10 @@ const SimpleModelSettingsDialog = ({ // only keep allowed keys const cleaned: Partial = {}; - for (const k of allowedKeys) { + for (const k of modelOverrideKeys) { if (!(k in parsedInput)) continue const isEmpty = parsedInput[k] === '' || parsedInput[k] === null || parsedInput[k] === undefined; - if (!isEmpty && (k in partialDefaults)) { + if (!isEmpty) { cleaned[k] = parsedInput[k] as any; } } @@ -333,10 +326,11 @@ const SimpleModelSettingsDialog = ({
}