diff --git a/src/vs/workbench/contrib/void/browser/editCodeService.ts b/src/vs/workbench/contrib/void/browser/editCodeService.ts index 80ee4bc9925..e0af351ed54 100644 --- a/src/vs/workbench/contrib/void/browser/editCodeService.ts +++ b/src/vs/workbench/contrib/void/browser/editCodeService.ts @@ -1408,7 +1408,7 @@ class EditCodeService extends Disposable implements IEditCodeService { const startLine = startRange === 'fullFile' ? 1 : startRange[0] const endLine = startRange === 'fullFile' ? model.getLineCount() : startRange[1] - const { prefix, suffix } = voidPrefixAndSuffix({ fullFileStr: originalFileCode, startLine, endLine }) + const { prefix, suffix } = voidPrefixAndSuffix({ settingsService: this._settingsService, fullFileStr: originalFileCode, startLine, endLine }) const userContent = ctrlKStream_userMessage({ selection: originalCode, instructions: instructions, prefix, suffix, fimTags: quickEditFIMTags, language }) const { messages: a, separateSystemMessage: b } = this._convertToLLMMessageService.prepareLLMSimpleMessages({ 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 97add942891..4a2f8d64286 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 @@ -28,7 +28,7 @@ import { approvalTypeOfBuiltinToolName, BuiltinToolCallParams, BuiltinToolName, import { CopyButton, EditToolAcceptRejectButtonsHTML, IconShell1, JumpToFileButton, JumpToTerminalButton, StatusIndicator, StatusIndicatorForApplyButton, useApplyStreamState, useEditToolStreamState } from '../markdown/ApplyBlockHoverButtons.js'; import { IsRunningType } from '../../../chatThreadService.js'; import { acceptAllBg, acceptBorder, buttonFontSize, buttonTextColor, rejectAllBg, rejectBg, rejectBorder } from '../../../../common/helpers/colors.js'; -import { builtinToolNames, isABuiltinToolName, MAX_FILE_CHARS_PAGE, MAX_TERMINAL_INACTIVE_TIME } from '../../../../common/prompt/prompts.js'; +import { builtinToolNames, isABuiltinToolName } from '../../../../common/prompt/prompts.js'; import { RawToolCallObj } from '../../../../common/sendLLMMessageTypes.js'; import ErrorBoundary from './ErrorBoundary.js'; import { ToolApprovalTypeSwitch } from '../void-settings-tsx/Settings.js'; @@ -1946,7 +1946,7 @@ const builtinToolNameToComponent: { [T in BuiltinToolName]: { resultWrapper: Res const { result } = toolMessage componentParams.onClick = () => { voidOpenFileFn(params.uri, accessor, range) } if (result.hasNextPage && params.pageNumber === 1) // first page - componentParams.desc2 = `(truncated after ${Math.round(MAX_FILE_CHARS_PAGE) / 1000}k)` + componentParams.desc2 = '(truncated)' else if (params.pageNumber > 1) // subsequent pages componentParams.desc2 = `(part ${params.pageNumber})` } 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 acc3c6d6cdc..6ac8f15a5c7 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 @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------*/ import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react'; // Added useRef import just in case it was missed, though likely already present -import { ProviderName, SettingName, displayInfoOfSettingName, providerNames, VoidStatefulModelInfo, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames, displayInfoOfProviderName, nonlocalProviderNames, localProviderNames, GlobalSettingName, featureNames, displayInfoOfFeatureName, isProviderNameDisabled, FeatureName, hasDownloadButtonsOnModelsProviderNames, subTextMdOfProviderName } from '../../../../common/voidSettingsTypes.js' +import { ProviderName, SettingName, displayInfoOfSettingName, providerNames, VoidStatefulModelInfo, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames, displayInfoOfProviderName, nonlocalProviderNames, localProviderNames, GlobalSettingName, featureNames, displayInfoOfFeatureName, isProviderNameDisabled, FeatureName, hasDownloadButtonsOnModelsProviderNames, subTextMdOfProviderName, GlobalSettings, defaultGlobalSettings, displayNameAndDescriptionOfSetting } from '../../../../common/voidSettingsTypes.js' import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js' import { VoidButtonBgDarken, VoidCustomDropdownBox, VoidInputBox2, VoidSimpleInputBox, VoidSwitch } from '../util/inputs.js' import { useAccessor, useIsDark, useIsOptedOut, useRefreshModelListener, useRefreshModelState, useSettingsState } from '../util/services.js' @@ -23,6 +23,7 @@ import { MCPServer } from '../../../../common/mcpServiceTypes.js'; import { useMCPServiceState } from '../util/services.js'; import { OPT_OUT_KEY } from '../../../../common/storageKeys.js'; import { StorageScope, StorageTarget } from '../../../../../../../platform/storage/common/storage.js'; +import { VoidSettingsState } from '../../../../common/voidSettingsService.js'; type Tab = | 'models' @@ -30,6 +31,7 @@ type Tab = | 'providers' | 'featureOptions' | 'mcp' + | 'limits' | 'general' | 'all'; @@ -796,6 +798,57 @@ export const AIInstructionsBox = () => { /> } +export const LimitComponent = ({ setting, onVoidSettingsInit, onVoidDefaultSettingsInit }: { + setting: GlobalSettingName + onVoidSettingsInit: (state: VoidSettingsState) => number + onVoidDefaultSettingsInit: (settings: GlobalSettings) => number +}) => { + const accessor = useAccessor() + const voidSettingsService = accessor.get('IVoidSettingsService') + const voidSettingsState = useSettingsState() + const [name, description] = displayNameAndDescriptionOfSetting(setting) + return ( +
+

{name}

+ {description && ( +
+ {description} +
+ )} + { + const parsed = parseInt(newVal) + if (!parsed || isNaN(parsed)) { + return + } + + voidSettingsService.setGlobalSetting(setting, parsed >= 0 ? parsed : 0) + }} + /> +
+ ) +} + + +export const LimitsList = ({ settings }: { settings: GlobalSettingName[] }) => { + return ( +
+
+ {settings.map((setting) => ( + state.globalSettings[setting] as number} + onVoidDefaultSettingsInit={(settings: GlobalSettings) => settings[setting] as number} + /> + ))} +
+
+ ) +} + const FastApplyMethodDropdown = () => { const accessor = useAccessor() const voidSettingsService = accessor.get('IVoidSettingsService') @@ -1042,6 +1095,7 @@ export const Settings = () => { { tab: 'featureOptions', label: 'Feature Options' }, { tab: 'general', label: 'General' }, { tab: 'mcp', label: 'MCP' }, + { tab: 'limits', label: 'Limits' }, { tab: 'all', label: 'All Settings' }, ]; const shouldShowTab = (tab: Tab) => selectedSection === 'all' || selectedSection === tab; @@ -1551,10 +1605,44 @@ Use Model Context Protocol to provide Agent mode with more tools. + {/* Limits section */} +
+
+
+

Directory Structure

+

Define the maximum allowable limits for directory queries.

+ + + +
+
+

Tool Info

+

Define the maximum limits regarding the tool itself.

+ + + +
+
+

Terminal Info

+

Define the maximum allowed characters for terminal related activities.

+ + + +
+
+

Context

+

Define the maximum how long context strings can be.

+ + + +
+
+
- + + diff --git a/src/vs/workbench/contrib/void/browser/terminalToolService.ts b/src/vs/workbench/contrib/void/browser/terminalToolService.ts index f9e0c791607..2b777ae31a4 100644 --- a/src/vs/workbench/contrib/void/browser/terminalToolService.ts +++ b/src/vs/workbench/contrib/void/browser/terminalToolService.ts @@ -12,9 +12,9 @@ import { createDecorator } from '../../../../platform/instantiation/common/insta import { TerminalLocation } from '../../../../platform/terminal/common/terminal.js'; import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js'; import { ITerminalService, ITerminalInstance, ICreateTerminalOptions } from '../../../../workbench/contrib/terminal/browser/terminal.js'; -import { MAX_TERMINAL_BG_COMMAND_TIME, MAX_TERMINAL_CHARS, MAX_TERMINAL_INACTIVE_TIME } from '../common/prompt/prompts.js'; import { TerminalResolveReason } from '../common/toolsServiceTypes.js'; import { timeout } from '../../../../base/common/async.js'; +import { IVoidSettingsService } from '../common/voidSettingsService.js'; @@ -74,6 +74,7 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ constructor( @ITerminalService private readonly terminalService: ITerminalService, @IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService, + @IVoidSettingsService private readonly voidSettingsService: IVoidSettingsService, ) { super(); @@ -229,8 +230,8 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ let result = removeAnsiEscapeCodes(lines.join('\n')); - if (result.length > MAX_TERMINAL_CHARS) { - const half = MAX_TERMINAL_CHARS / 2; + if (result.length > this.voidSettingsService.state.globalSettings.maxTerminalChars) { + const half = this.voidSettingsService.state.globalSettings.maxTerminalChars / 2; result = result.slice(0, half) + '\n...\n' + result.slice(result.length - half); } @@ -323,7 +324,7 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ setTimeout(() => { resolveReason = { type: 'timeout' }; res() - }, MAX_TERMINAL_BG_COMMAND_TIME * 1000) + }, this.voidSettingsService.state.globalSettings.maxTerminalBgCommandTime * 1000) }) // inactivity-based timeout : new Promise(res => { @@ -335,7 +336,7 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ resolveReason = { type: 'timeout' }; res(); - }, MAX_TERMINAL_INACTIVE_TIME * 1000); + }, this.voidSettingsService.state.globalSettings.maxTerminalInactiveTime * 1000); }; const dTimeout = terminal.onData(() => { resetTimer(); }); @@ -364,8 +365,8 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ if (!isPersistent) result = `$ ${command}\n${result}` result = removeAnsiEscapeCodes(result) // trim - if (result.length > MAX_TERMINAL_CHARS) { - const half = MAX_TERMINAL_CHARS / 2 + if (result.length > this.voidSettingsService.state.globalSettings.maxTerminalChars) { + const half = this.voidSettingsService.state.globalSettings.maxTerminalChars / 2 result = result.slice(0, half) + '\n...\n' + result.slice(result.length - half, Infinity) diff --git a/src/vs/workbench/contrib/void/browser/toolsService.ts b/src/vs/workbench/contrib/void/browser/toolsService.ts index dbd0bdd17be..b6a6f9a0829 100644 --- a/src/vs/workbench/contrib/void/browser/toolsService.ts +++ b/src/vs/workbench/contrib/void/browser/toolsService.ts @@ -16,7 +16,6 @@ import { computeDirectoryTree1Deep, IDirectoryStrService, stringifyDirectoryTree import { IMarkerService, MarkerSeverity } from '../../../../platform/markers/common/markers.js' import { timeout } from '../../../../base/common/async.js' import { RawToolParamsObj } from '../common/sendLLMMessageTypes.js' -import { MAX_CHILDREN_URIs_PAGE, MAX_FILE_CHARS_PAGE, MAX_TERMINAL_BG_COMMAND_TIME, MAX_TERMINAL_INACTIVE_TIME } from '../common/prompt/prompts.js' import { IVoidSettingsService } from '../common/voidSettingsService.js' import { generateUuid } from '../../../../base/common/uuid.js' @@ -311,8 +310,8 @@ export class ToolsService implements IToolsService { const totalNumLines = model.getLineCount() - const fromIdx = MAX_FILE_CHARS_PAGE * (pageNumber - 1) - const toIdx = MAX_FILE_CHARS_PAGE * pageNumber - 1 + const fromIdx = this.voidSettingsService.state.globalSettings.maxFileCharsPage * (pageNumber - 1) + const toIdx = this.voidSettingsService.state.globalSettings.maxFileCharsPage * pageNumber - 1 const fileContents = contents.slice(fromIdx, toIdx + 1) // paginate const hasNextPage = (contents.length - 1) - toIdx >= 1 const totalFileLen = contents.length @@ -320,7 +319,7 @@ export class ToolsService implements IToolsService { }, ls_dir: async ({ uri, pageNumber }) => { - const dirResult = await computeDirectoryTree1Deep(fileService, uri, pageNumber) + const dirResult = await computeDirectoryTree1Deep(fileService, voidSettingsService, uri, pageNumber) return { result: dirResult } }, @@ -338,8 +337,8 @@ export class ToolsService implements IToolsService { }) const data = await searchService.fileSearch(query, CancellationToken.None) - const fromIdx = MAX_CHILDREN_URIs_PAGE * (pageNumber - 1) - const toIdx = MAX_CHILDREN_URIs_PAGE * pageNumber - 1 + const fromIdx = this.voidSettingsService.state.globalSettings.maxChildrenUrisPage * (pageNumber - 1) + const toIdx = this.voidSettingsService.state.globalSettings.maxChildrenUrisPage * pageNumber - 1 const uris = data.results .slice(fromIdx, toIdx + 1) // paginate .map(({ resource, results }) => resource) @@ -360,8 +359,8 @@ export class ToolsService implements IToolsService { const data = await searchService.textSearch(query, CancellationToken.None) - const fromIdx = MAX_CHILDREN_URIs_PAGE * (pageNumber - 1) - const toIdx = MAX_CHILDREN_URIs_PAGE * pageNumber - 1 + const fromIdx = this.voidSettingsService.state.globalSettings.maxChildrenUrisPage * (pageNumber - 1) + const toIdx = this.voidSettingsService.state.globalSettings.maxChildrenUrisPage * pageNumber - 1 const uris = data.results .slice(fromIdx, toIdx + 1) // paginate .map(({ resource, results }) => resource) @@ -470,7 +469,7 @@ export class ToolsService implements IToolsService { return lintErrors .map((e, i) => `Error ${i + 1}:\nLines Affected: ${e.startLineNumber}-${e.endLineNumber}\nError message:${e.message}`) .join('\n\n') - .substring(0, MAX_FILE_CHARS_PAGE) + .substring(0, this.voidSettingsService.state.globalSettings.maxFileCharsPage) } // given to the LLM after the call for successful tool calls @@ -538,7 +537,7 @@ export class ToolsService implements IToolsService { } // normal command if (resolveReason.type === 'timeout') { - return `${result_}\nTerminal command ran, but was automatically killed by Void after ${MAX_TERMINAL_INACTIVE_TIME}s of inactivity and did not finish successfully. To try with more time, open a persistent terminal and run the command there.` + return `${result_}\nTerminal command ran, but was automatically killed by Void after ${this.voidSettingsService.state.globalSettings.maxTerminalInactiveTime}s of inactivity and did not finish successfully. To try with more time, open a persistent terminal and run the command there.` } throw new Error(`Unexpected internal error: Terminal command did not resolve with a valid reason.`) }, @@ -552,7 +551,7 @@ export class ToolsService implements IToolsService { } // bg command if (resolveReason.type === 'timeout') { - return `${result_}\nTerminal command is running in terminal ${persistentTerminalId}. The given outputs are the results after ${MAX_TERMINAL_BG_COMMAND_TIME} seconds.` + return `${result_}\nTerminal command is running in terminal ${persistentTerminalId}. The given outputs are the results after ${this.voidSettingsService.state.globalSettings.maxTerminalBgCommandTime} seconds.` } throw new Error(`Unexpected internal error: Terminal command did not resolve with a valid reason.`) }, diff --git a/src/vs/workbench/contrib/void/common/directoryStrService.ts b/src/vs/workbench/contrib/void/common/directoryStrService.ts index d9d0a319cec..81e60568315 100644 --- a/src/vs/workbench/contrib/void/common/directoryStrService.ts +++ b/src/vs/workbench/contrib/void/common/directoryStrService.ts @@ -10,7 +10,7 @@ import { createDecorator } from '../../../../platform/instantiation/common/insta import { IFileService, IFileStat } from '../../../../platform/files/common/files.js'; import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js'; import { ShallowDirectoryItem, BuiltinToolCallParams, BuiltinToolResultType } from './toolsServiceTypes.js'; -import { MAX_CHILDREN_URIs_PAGE, MAX_DIRSTR_CHARS_TOTAL_BEGINNING, MAX_DIRSTR_CHARS_TOTAL_TOOL } from './prompt/prompts.js'; +import { IVoidSettingsService } from './voidSettingsService.js'; const MAX_FILES_TOTAL = 1000; @@ -74,6 +74,7 @@ const shouldExcludeDirectory = (name: string) => { export const computeDirectoryTree1Deep = async ( fileService: IFileService, + voidSettingsService: IVoidSettingsService, rootURI: URI, pageNumber: number = 1, ): Promise => { @@ -84,8 +85,8 @@ export const computeDirectoryTree1Deep = async ( const nChildren = stat.children?.length ?? 0; - const fromChildIdx = MAX_CHILDREN_URIs_PAGE * (pageNumber - 1); - const toChildIdx = MAX_CHILDREN_URIs_PAGE * pageNumber - 1; // INCLUSIVE + const fromChildIdx = voidSettingsService.state.globalSettings.maxChildrenUrisPage * (pageNumber - 1); + const toChildIdx = voidSettingsService.state.globalSettings.maxChildrenUrisPage * pageNumber - 1; // INCLUSIVE const listChildren = stat.children?.slice(fromChildIdx, toChildIdx + 1); const children: ShallowDirectoryItem[] = listChildren?.map(child => ({ @@ -387,6 +388,7 @@ class DirectoryStrService extends Disposable implements IDirectoryStrService { constructor( @IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService, @IFileService private readonly fileService: IFileService, + @IVoidSettingsService private readonly voidSettingsService: IVoidSettingsService, ) { super(); } @@ -405,7 +407,7 @@ class DirectoryStrService extends Disposable implements IDirectoryStrService { const { content: initialContent, wasCutOff: initialCutOff } = await computeAndStringifyDirectoryTree( eRoot, this.fileService, - MAX_DIRSTR_CHARS_TOTAL_TOOL, + this.voidSettingsService.state.globalSettings.maxDirstrCharsTotalTool, { count: 0 }, { maxDepth: START_MAX_DEPTH, currentDepth: 0, maxItemsPerDir } ); @@ -416,7 +418,7 @@ class DirectoryStrService extends Disposable implements IDirectoryStrService { const result = await computeAndStringifyDirectoryTree( eRoot, this.fileService, - MAX_DIRSTR_CHARS_TOTAL_TOOL, + this.voidSettingsService.state.globalSettings.maxDirstrCharsTotalTool, { count: 0 }, { maxDepth: DEFAULT_MAX_DEPTH, currentDepth: 0, maxItemsPerDir: DEFAULT_MAX_ITEMS_PER_DIR } ); @@ -427,7 +429,7 @@ class DirectoryStrService extends Disposable implements IDirectoryStrService { wasCutOff = initialCutOff; } - let c = content.substring(0, MAX_DIRSTR_CHARS_TOTAL_TOOL) + let c = content.substring(0, this.voidSettingsService.state.globalSettings.maxDirstrCharsTotalTool) c = `Directory of ${uri.fsPath}:\n${content}` if (wasCutOff) c = `${c}\n...Result was truncated...` @@ -459,7 +461,7 @@ class DirectoryStrService extends Disposable implements IDirectoryStrService { const { content: initialContent, wasCutOff: initialCutOff } = await computeAndStringifyDirectoryTree( eRoot, this.fileService, - MAX_DIRSTR_CHARS_TOTAL_BEGINNING - str.length, + this.voidSettingsService.state.globalSettings.maxDirstrCharsTotalBeginning - str.length, { count: 0 }, { maxDepth: START_MAX_DEPTH, currentDepth: 0, maxItemsPerDir: startMaxItemsPerDir } ); @@ -470,7 +472,7 @@ class DirectoryStrService extends Disposable implements IDirectoryStrService { const result = await computeAndStringifyDirectoryTree( eRoot, this.fileService, - MAX_DIRSTR_CHARS_TOTAL_BEGINNING - str.length, + this.voidSettingsService.state.globalSettings.maxDirstrCharsTotalBeginning - str.length, { count: 0 }, { maxDepth: DEFAULT_MAX_DEPTH, currentDepth: 0, maxItemsPerDir: DEFAULT_MAX_ITEMS_PER_DIR } ); diff --git a/src/vs/workbench/contrib/void/common/prompt/prompts.ts b/src/vs/workbench/contrib/void/common/prompt/prompts.ts index fba768159cf..4e3c9d65b99 100644 --- a/src/vs/workbench/contrib/void/common/prompt/prompts.ts +++ b/src/vs/workbench/contrib/void/common/prompt/prompts.ts @@ -11,28 +11,11 @@ import { os } from '../helpers/systemInfo.js'; import { RawToolParamsObj } from '../sendLLMMessageTypes.js'; import { approvalTypeOfBuiltinToolName, BuiltinToolCallParams, BuiltinToolName, BuiltinToolResultType, ToolName } from '../toolsServiceTypes.js'; import { ChatMode } from '../voidSettingsTypes.js'; +import { IVoidSettingsService } from '../voidSettingsService.js'; // Triple backtick wrapper used throughout the prompts for code blocks export const tripleTick = ['```', '```'] -// Maximum limits for directory structure information -export const MAX_DIRSTR_CHARS_TOTAL_BEGINNING = 20_000 -export const MAX_DIRSTR_CHARS_TOTAL_TOOL = 20_000 -export const MAX_DIRSTR_RESULTS_TOTAL_BEGINNING = 100 -export const MAX_DIRSTR_RESULTS_TOTAL_TOOL = 100 - -// tool info -export const MAX_FILE_CHARS_PAGE = 500_000 -export const MAX_CHILDREN_URIs_PAGE = 500 - -// terminal tool info -export const MAX_TERMINAL_CHARS = 100_000 -export const MAX_TERMINAL_INACTIVE_TIME = 8 // seconds -export const MAX_TERMINAL_BG_COMMAND_TIME = 5 - - -// Maximum character limits for prefix and suffix context -export const MAX_PREFIX_SUFFIX_CHARS = 20_000 export const ORIGINAL = `<<<<<<< ORIGINAL` @@ -305,7 +288,7 @@ export const builtinTools: { }, run_command: { name: 'run_command', - description: `Runs a terminal command and waits for the result (times out after ${MAX_TERMINAL_INACTIVE_TIME}s of inactivity). ${terminalDescHelper}`, + description: `Runs a terminal command and waits for the result (times out after inactivity). ${terminalDescHelper}`, params: { command: { description: 'The terminal command to run.' }, cwd: { description: cwdHelper }, @@ -314,7 +297,7 @@ export const builtinTools: { run_persistent_command: { name: 'run_persistent_command', - description: `Runs a terminal command in the persistent terminal that you created with open_persistent_terminal (results after ${MAX_TERMINAL_BG_COMMAND_TIME} are returned, and command continues running in background). ${terminalDescHelper}`, + description: `Runs a terminal command in the persistent terminal that you created with open_persistent_terminal (results after specified command time is returned, and command continues running in background). ${terminalDescHelper}`, params: { command: { description: 'The terminal command to run.' }, persistent_terminal_id: { description: 'The ID of the terminal created using open_persistent_terminal.' }, @@ -695,7 +678,7 @@ ${tripleTick[1]}` -export const voidPrefixAndSuffix = ({ fullFileStr, startLine, endLine }: { fullFileStr: string, startLine: number, endLine: number }) => { +export const voidPrefixAndSuffix = ({ settingsService, fullFileStr, startLine, endLine }: { settingsService: IVoidSettingsService, fullFileStr: string, startLine: number, endLine: number }) => { const fullFileLines = fullFileStr.split('\n') @@ -719,7 +702,7 @@ export const voidPrefixAndSuffix = ({ fullFileStr, startLine, endLine }: { fullF // we'll include fullFileLines[i...(startLine-1)-1].join('\n') in the prefix. while (i !== 0) { const newLine = fullFileLines[i - 1] - if (newLine.length + 1 + prefix.length <= MAX_PREFIX_SUFFIX_CHARS) { // +1 to include the \n + if (newLine.length + 1 + prefix.length <= settingsService.state.globalSettings.maxPrefixSuffixChars) { // +1 to include the \n prefix = `${newLine}\n${prefix}` i -= 1 } @@ -730,7 +713,7 @@ export const voidPrefixAndSuffix = ({ fullFileStr, startLine, endLine }: { fullF let j = endLine - 1 while (j !== fullFileLines.length - 1) { const newLine = fullFileLines[j + 1] - if (newLine.length + 1 + suffix.length <= MAX_PREFIX_SUFFIX_CHARS) { // +1 to include the \n + if (newLine.length + 1 + suffix.length <= settingsService.state.globalSettings.maxPrefixSuffixChars) { // +1 to include the \n suffix = `${suffix}\n${newLine}` j += 1 } diff --git a/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts b/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts index 38497c60ce7..c0780bd4fb9 100644 --- a/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts +++ b/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts @@ -384,6 +384,66 @@ export const displayInfoOfFeatureName = (featureName: FeatureName) => { throw new Error(`Feature Name ${featureName} not allowed`) } +export function displayNameAndDescriptionOfSetting( + setting: string +): [name: string, description: string] { + const settingsMap: Record = { + // directoryStructureLimits + maxDirstrCharsTotalBeginning: [ + 'Max Directory Structure Chars (Beginning)', + 'Maximum number of characters from the beginning of the directory structure representation to include in initial context.', + ], + maxDirstrCharsTotalTool: [ + 'Max Directory Structure Chars (Tool)', + 'Maximum number of characters from the directory structure representation to include when using the directory listing tool.', + ], + maxDirstrResultsTotalBeginning: [ + 'Max Directory Structure Results (Beginning)', + 'Maximum number of directory entries (files/folders) to include in the initial context before truncation.', + ], + maxDirstrResultsTotalTool: [ + 'Max Directory Structure Results (Tool)', + 'Maximum number of directory entries (files/folders) to return when explicitly listing directory contents via tool.', + ], + + // toolInfoLimits + maxFileCharsPage: [ + 'Max File Characters per Page', + 'Maximum number of characters allowed when reading file content in a single tool call or page.', + ], + maxChildrenUrisPage: [ + 'Max Children URIs per Page', + 'Maximum number of child URIs (e.g. files in a directory) that can be listed in a single page.', + ], + + // terminalInfoLimits + maxTerminalChars: [ + 'Max Terminal Characters', + 'Maximum number of characters to capture from terminal output before truncation.', + ], + maxTerminalInactiveTime: [ + 'Max Terminal Inactive Time', + 'Maximum time (in seconds) a terminal session can remain inactive before being terminated.', + ], + maxTerminalBgCommandTime: [ + 'Max Terminal Background Command Time', + 'Maximum time (in seconds) a background terminal command can run before timing out.', + ], + + // contextLimits + maxPrefixSuffixChars: [ + 'Max Prefix Suffix Characters', + 'Maximum number of characters to include as prefix/suffix context around edits or suggestions.', + ], + }; + + if (!(setting in settingsMap)) { + throw new Error(`Unknown setting: "${setting}". Valid settings are: ${Object.keys(settingsMap).join(', ')}`); + } + + return settingsMap[setting]; +} + // the models of these can be refreshed (in theory all can, but not all should) export const refreshableProviderNames = localProviderNames @@ -452,6 +512,16 @@ export type GlobalSettings = { isOnboardingComplete: boolean; disableSystemMessage: boolean; autoAcceptLLMChanges: boolean; + maxDirstrCharsTotalBeginning: number; + maxDirstrCharsTotalTool: number; + maxDirstrResultsTotalBeginning: number; + maxDirstrResultsTotalTool: number; + maxFileCharsPage: number; + maxChildrenUrisPage: number; + maxTerminalChars: number; + maxTerminalInactiveTime: number; + maxTerminalBgCommandTime: number; + maxPrefixSuffixChars: number; } export const defaultGlobalSettings: GlobalSettings = { @@ -468,6 +538,16 @@ export const defaultGlobalSettings: GlobalSettings = { isOnboardingComplete: false, disableSystemMessage: false, autoAcceptLLMChanges: false, + maxDirstrCharsTotalBeginning: 20_000, + maxDirstrCharsTotalTool: 20_000, + maxDirstrResultsTotalBeginning: 100, + maxDirstrResultsTotalTool: 100, + maxFileCharsPage: 500_000, + maxChildrenUrisPage: 500, + maxTerminalChars: 100_000, + maxTerminalInactiveTime: 8, + maxTerminalBgCommandTime: 5, + maxPrefixSuffixChars: 20_000, } export type GlobalSettingName = keyof GlobalSettings