diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index bddb94cc9e..99131af9c8 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -22,6 +22,13 @@ import { languagesSchema } from "./vscode.js" */ export const DEFAULT_WRITE_DELAY_MS = 1000 +/** + * Default terminal output character limit constant. + * This provides a reasonable default that aligns with typical terminal usage + * while preventing context window explosions from extremely long lines. + */ +export const DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT = 50_000 + /** * GlobalSettings */ @@ -85,6 +92,7 @@ export const globalSettingsSchema = z.object({ maxReadFileLine: z.number().optional(), terminalOutputLineLimit: z.number().optional(), + terminalOutputCharacterLimit: z.number().optional(), terminalShellIntegrationTimeout: z.number().optional(), terminalShellIntegrationDisabled: z.boolean().optional(), terminalCommandDelay: z.number().optional(), @@ -227,6 +235,7 @@ export const EVALS_SETTINGS: RooCodeSettings = { soundVolume: 0.5, terminalOutputLineLimit: 500, + terminalOutputCharacterLimit: DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT, terminalShellIntegrationTimeout: 30000, terminalCommandDelay: 0, terminalPowershellCounter: false, diff --git a/src/core/environment/getEnvironmentDetails.ts b/src/core/environment/getEnvironmentDetails.ts index 6f0c9fe2bf..b83b37c75b 100644 --- a/src/core/environment/getEnvironmentDetails.ts +++ b/src/core/environment/getEnvironmentDetails.ts @@ -6,6 +6,7 @@ import pWaitFor from "p-wait-for" import delay from "delay" import type { ExperimentId } from "@roo-code/types" +import { DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT } from "@roo-code/types" import { EXPERIMENT_IDS, experiments as Experiments } from "../../shared/experiments" import { formatLanguage } from "../../shared/language" @@ -25,7 +26,11 @@ export async function getEnvironmentDetails(cline: Task, includeFileDetails: boo const clineProvider = cline.providerRef.deref() const state = await clineProvider?.getState() - const { terminalOutputLineLimit = 500, maxWorkspaceFiles = 200 } = state ?? {} + const { + terminalOutputLineLimit = 500, + terminalOutputCharacterLimit = DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT, + maxWorkspaceFiles = 200, + } = state ?? {} // It could be useful for cline to know if the user went from one or no // file to another between messages, so we always include this context. @@ -111,7 +116,11 @@ export async function getEnvironmentDetails(cline: Task, includeFileDetails: boo let newOutput = TerminalRegistry.getUnretrievedOutput(busyTerminal.id) if (newOutput) { - newOutput = Terminal.compressTerminalOutput(newOutput, terminalOutputLineLimit) + newOutput = Terminal.compressTerminalOutput( + newOutput, + terminalOutputLineLimit, + terminalOutputCharacterLimit, + ) terminalDetails += `\n### New Output\n${newOutput}` } } @@ -139,7 +148,11 @@ export async function getEnvironmentDetails(cline: Task, includeFileDetails: boo let output = process.getUnretrievedOutput() if (output) { - output = Terminal.compressTerminalOutput(output, terminalOutputLineLimit) + output = Terminal.compressTerminalOutput( + output, + terminalOutputLineLimit, + terminalOutputCharacterLimit, + ) terminalOutputs.push(`Command: \`${process.command}\`\n${output}`) } } diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index e895701721..81dc1993b2 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -4,7 +4,7 @@ import * as vscode from "vscode" import delay from "delay" -import { CommandExecutionStatus } from "@roo-code/types" +import { CommandExecutionStatus, DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT } from "@roo-code/types" import { TelemetryService } from "@roo-code/telemetry" import { Task } from "../task/Task" @@ -63,7 +63,11 @@ export async function executeCommandTool( const executionId = cline.lastMessageTs?.toString() ?? Date.now().toString() const clineProvider = await cline.providerRef.deref() const clineProviderState = await clineProvider?.getState() - const { terminalOutputLineLimit = 500, terminalShellIntegrationDisabled = false } = clineProviderState ?? {} + const { + terminalOutputLineLimit = 500, + terminalOutputCharacterLimit = DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT, + terminalShellIntegrationDisabled = false, + } = clineProviderState ?? {} // Get command execution timeout from VSCode configuration (in seconds) const commandExecutionTimeoutSeconds = vscode.workspace @@ -87,6 +91,7 @@ export async function executeCommandTool( customCwd, terminalShellIntegrationDisabled, terminalOutputLineLimit, + terminalOutputCharacterLimit, commandExecutionTimeout, } @@ -133,6 +138,7 @@ export type ExecuteCommandOptions = { customCwd?: string terminalShellIntegrationDisabled?: boolean terminalOutputLineLimit?: number + terminalOutputCharacterLimit?: number commandExecutionTimeout?: number } @@ -144,6 +150,7 @@ export async function executeCommand( customCwd, terminalShellIntegrationDisabled = false, terminalOutputLineLimit = 500, + terminalOutputCharacterLimit = DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT, commandExecutionTimeout = 0, }: ExecuteCommandOptions, ): Promise<[boolean, ToolResponse]> { @@ -179,7 +186,11 @@ export async function executeCommand( const callbacks: RooTerminalCallbacks = { onLine: async (lines: string, process: RooTerminalProcess) => { accumulatedOutput += lines - const compressedOutput = Terminal.compressTerminalOutput(accumulatedOutput, terminalOutputLineLimit) + const compressedOutput = Terminal.compressTerminalOutput( + accumulatedOutput, + terminalOutputLineLimit, + terminalOutputCharacterLimit, + ) const status: CommandExecutionStatus = { executionId, status: "output", output: compressedOutput } clineProvider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) @@ -198,7 +209,11 @@ export async function executeCommand( } catch (_error) {} }, onCompleted: (output: string | undefined) => { - result = Terminal.compressTerminalOutput(output ?? "", terminalOutputLineLimit) + result = Terminal.compressTerminalOutput( + output ?? "", + terminalOutputLineLimit, + terminalOutputCharacterLimit, + ) cline.say("command_output", result) completed = true }, diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index ceb6671767..6231f08167 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -28,6 +28,7 @@ import { openRouterDefaultModelId, glamaDefaultModelId, ORGANIZATION_ALLOW_ALL, + DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT, } from "@roo-code/types" import { TelemetryService } from "@roo-code/telemetry" import { CloudService, getRooCodeApiUrl } from "@roo-code/cloud" @@ -1393,6 +1394,7 @@ export class ClineProvider cachedChromeHostUrl, writeDelayMs, terminalOutputLineLimit, + terminalOutputCharacterLimit, terminalShellIntegrationTimeout, terminalShellIntegrationDisabled, terminalCommandDelay, @@ -1493,6 +1495,7 @@ export class ClineProvider cachedChromeHostUrl: cachedChromeHostUrl, writeDelayMs: writeDelayMs ?? DEFAULT_WRITE_DELAY_MS, terminalOutputLineLimit: terminalOutputLineLimit ?? 500, + terminalOutputCharacterLimit: terminalOutputCharacterLimit ?? DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT, terminalShellIntegrationTimeout: terminalShellIntegrationTimeout ?? Terminal.defaultShellIntegrationTimeout, terminalShellIntegrationDisabled: terminalShellIntegrationDisabled ?? false, terminalCommandDelay: terminalCommandDelay ?? 0, @@ -1662,6 +1665,8 @@ export class ClineProvider fuzzyMatchThreshold: stateValues.fuzzyMatchThreshold ?? 1.0, writeDelayMs: stateValues.writeDelayMs ?? DEFAULT_WRITE_DELAY_MS, terminalOutputLineLimit: stateValues.terminalOutputLineLimit ?? 500, + terminalOutputCharacterLimit: + stateValues.terminalOutputCharacterLimit ?? DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT, terminalShellIntegrationTimeout: stateValues.terminalShellIntegrationTimeout ?? Terminal.defaultShellIntegrationTimeout, terminalShellIntegrationDisabled: stateValues.terminalShellIntegrationDisabled ?? false, diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 1bb76734db..f204739095 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -1049,8 +1049,29 @@ export const webviewMessageHandler = async ( await provider.postStateToWebview() break case "terminalOutputLineLimit": - await updateGlobalState("terminalOutputLineLimit", message.value) - await provider.postStateToWebview() + // Validate that the line limit is a positive number + const lineLimit = message.value + if (typeof lineLimit === "number" && lineLimit > 0) { + await updateGlobalState("terminalOutputLineLimit", lineLimit) + await provider.postStateToWebview() + } else { + vscode.window.showErrorMessage( + t("common:errors.invalid_line_limit") || "Terminal output line limit must be a positive number", + ) + } + break + case "terminalOutputCharacterLimit": + // Validate that the character limit is a positive number + const charLimit = message.value + if (typeof charLimit === "number" && charLimit > 0) { + await updateGlobalState("terminalOutputCharacterLimit", charLimit) + await provider.postStateToWebview() + } else { + vscode.window.showErrorMessage( + t("common:errors.invalid_character_limit") || + "Terminal output character limit must be a positive number", + ) + } break case "terminalShellIntegrationTimeout": await updateGlobalState("terminalShellIntegrationTimeout", message.value) diff --git a/src/integrations/misc/__tests__/extract-text.spec.ts b/src/integrations/misc/__tests__/extract-text.spec.ts index 04b06cfa83..bb4b52fe93 100644 --- a/src/integrations/misc/__tests__/extract-text.spec.ts +++ b/src/integrations/misc/__tests__/extract-text.spec.ts @@ -306,6 +306,197 @@ describe("truncateOutput", () => { const expectedLines = ["line1", "", "[...10 lines omitted...]", "", "line12", "line13", "line14", "line15"] expect(resultLines).toEqual(expectedLines) }) + + describe("character limit functionality", () => { + it("returns original content when no character limit provided", () => { + const content = "a".repeat(1000) + expect(truncateOutput(content, undefined, undefined)).toBe(content) + }) + + it("returns original content when characters are under limit", () => { + const content = "a".repeat(100) + expect(truncateOutput(content, undefined, 200)).toBe(content) + }) + + it("truncates content by character limit with 20/80 split", () => { + // Create content with 1000 characters + const content = "a".repeat(1000) + + // Set character limit to 100 + const result = truncateOutput(content, undefined, 100) + + // Should keep: + // - First 20 characters (20% of 100) + // - Last 80 characters (80% of 100) + // - Omission indicator in between + const expectedStart = "a".repeat(20) + const expectedEnd = "a".repeat(80) + const expected = expectedStart + "\n[...900 characters omitted...]\n" + expectedEnd + + expect(result).toBe(expected) + }) + + it("prioritizes character limit over line limit", () => { + // Create content with few lines but many characters per line + const longLine = "a".repeat(500) + const content = `${longLine}\n${longLine}\n${longLine}` + + // Set both limits - character limit should take precedence + const result = truncateOutput(content, 10, 100) + + // Should truncate by character limit, not line limit + const expectedStart = "a".repeat(20) + const expectedEnd = "a".repeat(80) + // Total content: 1502 chars, limit: 100, so 1402 chars omitted + const expected = expectedStart + "\n[...1402 characters omitted...]\n" + expectedEnd + + expect(result).toBe(expected) + }) + + it("falls back to line limit when character limit is satisfied", () => { + // Create content with many short lines + const lines = Array.from({ length: 25 }, (_, i) => `line${i + 1}`) + const content = lines.join("\n") + + // Character limit is high enough, so line limit should apply + const result = truncateOutput(content, 10, 10000) + + // Should truncate by line limit + const expectedLines = [ + "line1", + "line2", + "", + "[...15 lines omitted...]", + "", + "line18", + "line19", + "line20", + "line21", + "line22", + "line23", + "line24", + "line25", + ] + expect(result).toBe(expectedLines.join("\n")) + }) + + it("handles edge case where character limit equals content length", () => { + const content = "exactly100chars".repeat(6) + "1234" // exactly 100 chars + const result = truncateOutput(content, undefined, 100) + expect(result).toBe(content) + }) + + it("handles very small character limits", () => { + const content = "a".repeat(1000) + const result = truncateOutput(content, undefined, 10) + + // 20% of 10 = 2, 80% of 10 = 8 + const expected = "aa\n[...990 characters omitted...]\n" + "a".repeat(8) + expect(result).toBe(expected) + }) + + it("handles character limit with mixed content", () => { + const content = "Hello world! This is a test with mixed content including numbers 123 and symbols @#$%" + const result = truncateOutput(content, undefined, 50) + + // 20% of 50 = 10, 80% of 50 = 40 + const expectedStart = content.slice(0, 10) // "Hello worl" + const expectedEnd = content.slice(-40) // last 40 chars + const omittedChars = content.length - 50 + const expected = expectedStart + `\n[...${omittedChars} characters omitted...]\n` + expectedEnd + + expect(result).toBe(expected) + }) + + describe("edge cases with very small character limits", () => { + it("handles character limit of 1", () => { + const content = "abcdefghijklmnopqrstuvwxyz" + const result = truncateOutput(content, undefined, 1) + + // 20% of 1 = 0.2 (floor = 0), so beforeLimit = 0 + // afterLimit = 1 - 0 = 1 + // Should keep 0 chars from start and 1 char from end + const expected = "\n[...25 characters omitted...]\nz" + expect(result).toBe(expected) + }) + + it("handles character limit of 2", () => { + const content = "abcdefghijklmnopqrstuvwxyz" + const result = truncateOutput(content, undefined, 2) + + // 20% of 2 = 0.4 (floor = 0), so beforeLimit = 0 + // afterLimit = 2 - 0 = 2 + // Should keep 0 chars from start and 2 chars from end + const expected = "\n[...24 characters omitted...]\nyz" + expect(result).toBe(expected) + }) + + it("handles character limit of 5", () => { + const content = "abcdefghijklmnopqrstuvwxyz" + const result = truncateOutput(content, undefined, 5) + + // 20% of 5 = 1, so beforeLimit = 1 + // afterLimit = 5 - 1 = 4 + // Should keep 1 char from start and 4 chars from end + const expected = "a\n[...21 characters omitted...]\nwxyz" + expect(result).toBe(expected) + }) + + it("handles character limit with multi-byte characters", () => { + const content = "🚀🎉🔥💻🌟🎨🎯🎪🎭🎬" // 10 emojis, each is multi-byte + const result = truncateOutput(content, undefined, 10) + + // Character limit works on string length, not byte count + // 20% of 10 = 2, 80% of 10 = 8 + // Note: In JavaScript, each emoji is actually 2 characters (surrogate pair) + // So the content is actually 20 characters long, not 10 + const expected = "🚀\n[...10 characters omitted...]\n🎯🎪🎭🎬" + expect(result).toBe(expected) + }) + + it("handles character limit with newlines in content", () => { + const content = "line1\nline2\nline3\nline4\nline5" + const result = truncateOutput(content, undefined, 15) + + // Total length is 29 chars (including newlines) + // 20% of 15 = 3, 80% of 15 = 12 + // The slice will take first 3 chars: "lin" + // And last 12 chars: "e4\nline5" (counting backwards) + const expected = "lin\n[...14 characters omitted...]\n\nline4\nline5" + expect(result).toBe(expected) + }) + + it("handles character limit exactly matching content with omission message", () => { + // Edge case: when the omission message would make output longer than original + const content = "short" + const result = truncateOutput(content, undefined, 10) + + // Content is 5 chars, limit is 10, so no truncation needed + expect(result).toBe(content) + }) + + it("handles character limit smaller than omission message", () => { + const content = "a".repeat(100) + const result = truncateOutput(content, undefined, 3) + + // 20% of 3 = 0.6 (floor = 0), so beforeLimit = 0 + // afterLimit = 3 - 0 = 3 + const expected = "\n[...97 characters omitted...]\naaa" + expect(result).toBe(expected) + }) + + it("prioritizes character limit even with very high line limit", () => { + const content = "a".repeat(1000) + const result = truncateOutput(content, 999999, 50) + + // Character limit should still apply despite high line limit + const expectedStart = "a".repeat(10) // 20% of 50 + const expectedEnd = "a".repeat(40) // 80% of 50 + const expected = expectedStart + "\n[...950 characters omitted...]\n" + expectedEnd + expect(result).toBe(expected) + }) + }) + }) }) describe("applyRunLengthEncoding", () => { diff --git a/src/integrations/misc/extract-text.ts b/src/integrations/misc/extract-text.ts index 8c7e7408a6..eb02f63b95 100644 --- a/src/integrations/misc/extract-text.ts +++ b/src/integrations/misc/extract-text.ts @@ -135,17 +135,58 @@ export function stripLineNumbers(content: string, aggressive: boolean = false): * When truncation is needed, it keeps 20% of the lines from the start and 80% from the end, * with a clear indicator of how many lines were omitted in between. * + * IMPORTANT: Character limit takes precedence over line limit. This is because: + * 1. Character limit provides a hard cap on memory usage and context window consumption + * 2. A single line with millions of characters could bypass line limits and cause issues + * 3. Character limit ensures consistent behavior regardless of line structure + * + * When both limits are specified: + * - If content exceeds character limit, character-based truncation is applied (regardless of line count) + * - If content is within character limit but exceeds line limit, line-based truncation is applied + * - This prevents edge cases where extremely long lines could consume excessive resources + * * @param content The multi-line string to truncate - * @param lineLimit Optional maximum number of lines to keep. If not provided or 0, returns the original content - * @returns The truncated string with an indicator of omitted lines, or the original content if no truncation needed + * @param lineLimit Optional maximum number of lines to keep. If not provided or 0, no line limit is applied + * @param characterLimit Optional maximum number of characters to keep. If not provided or 0, no character limit is applied + * @returns The truncated string with an indicator of omitted content, or the original content if no truncation needed * * @example * // With 10 line limit on 25 lines of content: * // - Keeps first 2 lines (20% of 10) * // - Keeps last 8 lines (80% of 10) * // - Adds "[...15 lines omitted...]" in between + * + * @example + * // With character limit on long single line: + * // - Keeps first 20% of characters + * // - Keeps last 80% of characters + * // - Adds "[...X characters omitted...]" in between + * + * @example + * // Character limit takes precedence: + * // content = "A".repeat(50000) + "\n" + "B".repeat(50000) // 2 lines, 100,002 chars + * // truncateOutput(content, 10, 40000) // Uses character limit, not line limit + * // Result: First ~8000 chars + "[...60002 characters omitted...]" + Last ~32000 chars */ -export function truncateOutput(content: string, lineLimit?: number): string { +export function truncateOutput(content: string, lineLimit?: number, characterLimit?: number): string { + // If no limits are specified, return original content + if (!lineLimit && !characterLimit) { + return content + } + + // Character limit takes priority over line limit + if (characterLimit && content.length > characterLimit) { + const beforeLimit = Math.floor(characterLimit * 0.2) // 20% of characters before + const afterLimit = characterLimit - beforeLimit // remaining 80% after + + const startSection = content.slice(0, beforeLimit) + const endSection = content.slice(-afterLimit) + const omittedChars = content.length - characterLimit + + return startSection + `\n[...${omittedChars} characters omitted...]\n` + endSection + } + + // If character limit is not exceeded or not specified, check line limit if (!lineLimit) { return content } diff --git a/src/integrations/terminal/BaseTerminal.ts b/src/integrations/terminal/BaseTerminal.ts index 8137881b8c..a79d417b07 100644 --- a/src/integrations/terminal/BaseTerminal.ts +++ b/src/integrations/terminal/BaseTerminal.ts @@ -1,4 +1,5 @@ import { truncateOutput, applyRunLengthEncoding, processBackspaces, processCarriageReturns } from "../misc/extract-text" +import { DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT } from "@roo-code/types" import type { RooTerminalProvider, @@ -262,11 +263,13 @@ export abstract class BaseTerminal implements RooTerminal { } /** - * Compresses terminal output by applying run-length encoding and truncating to line limit + * Compresses terminal output by applying run-length encoding and truncating to line and character limits * @param input The terminal output to compress + * @param lineLimit Maximum number of lines to keep + * @param characterLimit Optional maximum number of characters to keep (defaults to DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT) * @returns The compressed terminal output */ - public static compressTerminalOutput(input: string, lineLimit: number): string { + public static compressTerminalOutput(input: string, lineLimit: number, characterLimit?: number): string { let processedInput = input if (BaseTerminal.compressProgressBar) { @@ -274,7 +277,10 @@ export abstract class BaseTerminal implements RooTerminal { processedInput = processBackspaces(processedInput) } - return truncateOutput(applyRunLengthEncoding(processedInput), lineLimit) + // Default character limit to prevent context window explosion + const effectiveCharLimit = characterLimit ?? DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT + + return truncateOutput(applyRunLengthEncoding(processedInput), lineLimit, effectiveCharLimit) } /** diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 060ec8cb15..4f2aa2da15 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -205,6 +205,7 @@ export type ExtensionState = Pick< // | "maxReadFileLine" // Optional in GlobalSettings, required here. | "maxConcurrentFileReads" // Optional in GlobalSettings, required here. | "terminalOutputLineLimit" + | "terminalOutputCharacterLimit" | "terminalShellIntegrationTimeout" | "terminalShellIntegrationDisabled" | "terminalCommandDelay" diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index e983ce720d..cc92ee30e8 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -116,6 +116,7 @@ export interface WebviewMessage { | "submitEditedMessage" | "editMessageConfirm" | "terminalOutputLineLimit" + | "terminalOutputCharacterLimit" | "terminalShellIntegrationTimeout" | "terminalShellIntegrationDisabled" | "terminalCommandDelay" diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index fd3a8a129b..882da54ab4 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -155,6 +155,7 @@ const SettingsView = forwardRef(({ onDone, t soundVolume, telemetrySetting, terminalOutputLineLimit, + terminalOutputCharacterLimit, terminalShellIntegrationTimeout, terminalShellIntegrationDisabled, // Added from upstream terminalCommandDelay, @@ -301,6 +302,7 @@ const SettingsView = forwardRef(({ onDone, t vscode.postMessage({ type: "writeDelayMs", value: writeDelayMs }) vscode.postMessage({ type: "screenshotQuality", value: screenshotQuality ?? 75 }) vscode.postMessage({ type: "terminalOutputLineLimit", value: terminalOutputLineLimit ?? 500 }) + vscode.postMessage({ type: "terminalOutputCharacterLimit", value: terminalOutputCharacterLimit ?? 50000 }) vscode.postMessage({ type: "terminalShellIntegrationTimeout", value: terminalShellIntegrationTimeout }) vscode.postMessage({ type: "terminalShellIntegrationDisabled", bool: terminalShellIntegrationDisabled }) vscode.postMessage({ type: "terminalCommandDelay", value: terminalCommandDelay }) @@ -674,6 +676,7 @@ const SettingsView = forwardRef(({ onDone, t {activeTab === "terminal" && ( & { terminalOutputLineLimit?: number + terminalOutputCharacterLimit?: number terminalShellIntegrationTimeout?: number terminalShellIntegrationDisabled?: boolean terminalCommandDelay?: number @@ -29,6 +30,7 @@ type TerminalSettingsProps = HTMLAttributes & { terminalCompressProgressBar?: boolean setCachedStateField: SetCachedStateField< | "terminalOutputLineLimit" + | "terminalOutputCharacterLimit" | "terminalShellIntegrationTimeout" | "terminalShellIntegrationDisabled" | "terminalCommandDelay" @@ -43,6 +45,7 @@ type TerminalSettingsProps = HTMLAttributes & { export const TerminalSettings = ({ terminalOutputLineLimit, + terminalOutputCharacterLimit, terminalShellIntegrationTimeout, terminalShellIntegrationDisabled, terminalCommandDelay, @@ -129,6 +132,36 @@ export const TerminalSettings = ({ +
+ +
+ + setCachedStateField("terminalOutputCharacterLimit", value) + } + data-testid="terminal-output-character-limit-slider" + /> + {terminalOutputCharacterLimit ?? 50000} +
+
+ + + {" "} + + +
+
void terminalOutputLineLimit?: number setTerminalOutputLineLimit: (value: number) => void + terminalOutputCharacterLimit?: number + setTerminalOutputCharacterLimit: (value: number) => void mcpEnabled: boolean setMcpEnabled: (value: boolean) => void enableMcpServerCreation: boolean @@ -176,6 +178,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode browserViewportSize: "900x600", screenshotQuality: 75, terminalOutputLineLimit: 500, + terminalOutputCharacterLimit: 50000, terminalShellIntegrationTimeout: 4000, mcpEnabled: true, enableMcpServerCreation: false, @@ -410,6 +413,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setScreenshotQuality: (value) => setState((prevState) => ({ ...prevState, screenshotQuality: value })), setTerminalOutputLineLimit: (value) => setState((prevState) => ({ ...prevState, terminalOutputLineLimit: value })), + setTerminalOutputCharacterLimit: (value) => + setState((prevState) => ({ ...prevState, terminalOutputCharacterLimit: value })), setTerminalShellIntegrationTimeout: (value) => setState((prevState) => ({ ...prevState, terminalShellIntegrationTimeout: value })), setTerminalShellIntegrationDisabled: (value) => diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 15018e64ab..2a24845c92 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -504,6 +504,10 @@ "label": "Límit de sortida de terminal", "description": "Nombre màxim de línies a incloure a la sortida del terminal en executar comandes. Quan s'excedeix, s'eliminaran línies del mig, estalviant token. <0>Més informació" }, + "outputCharacterLimit": { + "label": "Límit de caràcters del terminal", + "description": "Nombre màxim de caràcters a incloure en la sortida del terminal en executar ordres. Aquest límit té precedència sobre el límit de línies per evitar problemes de memòria amb línies extremadament llargues. Quan se superi, la sortida es truncarà. <0>Més informació" + }, "shellIntegrationTimeout": { "label": "Temps d'espera d'integració de shell del terminal", "description": "Temps màxim d'espera per a la inicialització de la integració de shell abans d'executar comandes. Per a usuaris amb temps d'inici de shell llargs, aquest valor pot necessitar ser augmentat si veieu errors \"Shell Integration Unavailable\" al terminal. <0>Més informació" diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index bb5ed1146b..82fb43901e 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -504,6 +504,10 @@ "label": "Terminal-Ausgabelimit", "description": "Maximale Anzahl von Zeilen, die in der Terminal-Ausgabe bei der Ausführung von Befehlen enthalten sein sollen. Bei Überschreitung werden Zeilen aus der Mitte entfernt, wodurch Token gespart werden. <0>Mehr erfahren" }, + "outputCharacterLimit": { + "label": "Terminal-Zeichenlimit", + "description": "Maximale Anzahl von Zeichen, die in die Terminalausgabe bei der Ausführung von Befehlen aufgenommen werden sollen. Dieses Limit hat Vorrang vor dem Zeilenlimit, um Speicherprobleme durch extrem lange Zeilen zu vermeiden. Bei Überschreitung wird die Ausgabe abgeschnitten. <0>Mehr erfahren" + }, "shellIntegrationTimeout": { "label": "Terminal-Shell-Integrationszeit-Limit", "description": "Maximale Wartezeit für die Shell-Integration, bevor Befehle ausgeführt werden. Für Benutzer mit langen Shell-Startzeiten musst du diesen Wert möglicherweise erhöhen, wenn du Fehler vom Typ \"Shell Integration Unavailable\" im Terminal siehst. <0>Mehr erfahren" diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 728e856502..07aae5cbd0 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -504,6 +504,10 @@ "label": "Terminal output limit", "description": "Maximum number of lines to include in terminal output when executing commands. When exceeded lines will be removed from the middle, saving tokens. <0>Learn more" }, + "outputCharacterLimit": { + "label": "Terminal character limit", + "description": "Maximum number of characters to include in terminal output when executing commands. This limit takes precedence over the line limit to prevent memory issues from extremely long lines. When exceeded, output will be truncated. <0>Learn more" + }, "shellIntegrationTimeout": { "label": "Terminal shell integration timeout", "description": "Maximum time to wait for shell integration to initialize before executing commands. For users with long shell startup times, this value may need to be increased if you see \"Shell Integration Unavailable\" errors in the terminal. <0>Learn more" diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 5836933b46..12ade53b33 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -504,6 +504,10 @@ "label": "Límite de salida de terminal", "description": "Número máximo de líneas a incluir en la salida del terminal al ejecutar comandos. Cuando se excede, se eliminarán líneas del medio, ahorrando token. <0>Más información" }, + "outputCharacterLimit": { + "label": "Límite de caracteres del terminal", + "description": "Número máximo de caracteres a incluir en la salida del terminal al ejecutar comandos. Este límite tiene prioridad sobre el límite de líneas para evitar problemas de memoria con líneas extremadamente largas. Cuando se excede, la salida se truncará. <0>Aprende más" + }, "shellIntegrationTimeout": { "label": "Tiempo de espera de integración del shell del terminal", "description": "Tiempo máximo de espera para la inicialización de la integración del shell antes de ejecutar comandos. Para usuarios con tiempos de inicio de shell largos, este valor puede necesitar ser aumentado si ve errores \"Shell Integration Unavailable\" en el terminal. <0>Más información" diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 833a789e5a..73ac3378d3 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -504,6 +504,10 @@ "label": "Limite de sortie du terminal", "description": "Nombre maximum de lignes à inclure dans la sortie du terminal lors de l'exécution de commandes. Lorsque ce nombre est dépassé, les lignes seront supprimées du milieu, économisant des token. <0>En savoir plus" }, + "outputCharacterLimit": { + "label": "Limite de caractères du terminal", + "description": "Nombre maximum de caractères à inclure dans la sortie du terminal lors de l'exécution de commandes. Cette limite prévaut sur la limite de lignes pour éviter les problèmes de mémoire avec des lignes extrêmement longues. Lorsque cette limite est dépassée, la sortie sera tronquée. <0>En savoir plus" + }, "shellIntegrationTimeout": { "label": "Délai d'intégration du shell du terminal", "description": "Temps maximum d'attente pour l'initialisation de l'intégration du shell avant d'exécuter des commandes. Pour les utilisateurs avec des temps de démarrage de shell longs, cette valeur peut nécessiter d'être augmentée si vous voyez des erreurs \"Shell Integration Unavailable\" dans le terminal. <0>En savoir plus" diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 0749943508..f0098c148f 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -504,6 +504,10 @@ "label": "टर्मिनल आउटपुट सीमा", "description": "कमांड निष्पादित करते समय टर्मिनल आउटपुट में शामिल करने के लिए पंक्तियों की अधिकतम संख्या। पार होने पर पंक्तियाँ मध्य से हटा दी जाएंगी, token बचाते हुए। <0>अधिक जानें" }, + "outputCharacterLimit": { + "label": "टर्मिनल वर्ण सीमा", + "description": "कमांड निष्पादित करते समय टर्मिनल आउटपुट में शामिल किए जाने वाले वर्णों की अधिकतम संख्या। यह सीमा अत्यधिक लंबी लाइनों से मेमोरी समस्याओं को रोकने के लिए लाइन सीमा पर पूर्वता लेती है। जब यह सीमा पार हो जाती है, तो आउटपुट छोटा कर दिया जाएगा। <0>और जानें" + }, "shellIntegrationTimeout": { "label": "टर्मिनल शेल एकीकरण टाइमआउट", "description": "कमांड निष्पादित करने से पहले शेल एकीकरण के आरंभ होने के लिए प्रतीक्षा का अधिकतम समय। लंबे शेल स्टार्टअप समय वाले उपयोगकर्ताओं के लिए, यदि आप टर्मिनल में \"Shell Integration Unavailable\" त्रुटियाँ देखते हैं तो इस मान को बढ़ाने की आवश्यकता हो सकती है। <0>अधिक जानें" diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index 4a0c51d39d..aacc0bca3c 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -508,6 +508,10 @@ "label": "Batas output terminal", "description": "Jumlah maksimum baris yang disertakan dalam output terminal saat mengeksekusi perintah. Ketika terlampaui, baris akan dihapus dari tengah, menghemat token. <0>Pelajari lebih lanjut" }, + "outputCharacterLimit": { + "label": "Batas karakter terminal", + "description": "Jumlah maksimum karakter yang akan disertakan dalam output terminal saat menjalankan perintah. Batas ini lebih diutamakan daripada batas baris untuk mencegah masalah memori dari baris yang sangat panjang. Ketika terlampaui, output akan dipotong. <0>Pelajari lebih lanjut" + }, "shellIntegrationTimeout": { "label": "Timeout integrasi shell terminal", "description": "Waktu maksimum untuk menunggu integrasi shell menginisialisasi sebelum mengeksekusi perintah. Untuk pengguna dengan waktu startup shell yang lama, nilai ini mungkin perlu ditingkatkan jika kamu melihat error \"Shell Integration Unavailable\" di terminal. <0>Pelajari lebih lanjut" diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 9d9be82868..98b4c67c32 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -504,6 +504,10 @@ "label": "Limite output terminale", "description": "Numero massimo di righe da includere nell'output del terminale durante l'esecuzione dei comandi. Quando superato, le righe verranno rimosse dal centro, risparmiando token. <0>Scopri di più" }, + "outputCharacterLimit": { + "label": "Limite di caratteri del terminale", + "description": "Numero massimo di caratteri da includere nell'output del terminale durante l'esecuzione dei comandi. Questo limite ha la precedenza sul limite di righe per prevenire problemi di memoria causati da righe estremamente lunghe. Se superato, l'output verrà troncato. <0>Scopri di più" + }, "shellIntegrationTimeout": { "label": "Timeout integrazione shell del terminale", "description": "Tempo massimo di attesa per l'inizializzazione dell'integrazione della shell prima di eseguire i comandi. Per gli utenti con tempi di avvio della shell lunghi, questo valore potrebbe dover essere aumentato se si vedono errori \"Shell Integration Unavailable\" nel terminale. <0>Scopri di più" diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 9fc03cbfb1..f124be36c4 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -504,6 +504,10 @@ "label": "ターミナル出力制限", "description": "コマンド実行時にターミナル出力に含める最大行数。超過すると中央から行が削除され、tokenを節約します。 <0>詳細情報" }, + "outputCharacterLimit": { + "label": "ターミナルの文字数制限", + "description": "コマンド実行時にターミナル出力に含める最大文字数。この制限は、非常に長い行によるメモリ問題を回避するため、行数制限よりも優先されます。超過した場合、出力は切り捨てられます。<0>詳細" + }, "shellIntegrationTimeout": { "label": "ターミナルシェル統合タイムアウト", "description": "コマンドを実行する前にシェル統合の初期化を待つ最大時間。シェルの起動時間が長いユーザーの場合、ターミナルで「Shell Integration Unavailable」エラーが表示される場合は、この値を増やす必要があるかもしれません。 <0>詳細情報" diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 219daa05a4..0ca29d9641 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -504,6 +504,10 @@ "label": "터미널 출력 제한", "description": "명령 실행 시 터미널 출력에 포함할 최대 라인 수. 초과 시 중간에서 라인이 제거되어 token이 절약됩니다. <0>더 알아보기" }, + "outputCharacterLimit": { + "label": "터미널 문자 제한", + "description": "명령을 실행할 때 터미널 출력에 포함할 최대 문자 수입니다. 이 제한은 매우 긴 줄로 인한 메모리 문제를 방지하기 위해 줄 제한보다 우선합니다. 초과하면 출력이 잘립니다. <0>더 알아보기" + }, "shellIntegrationTimeout": { "label": "터미널 쉘 통합 타임아웃", "description": "명령을 실행하기 전에 쉘 통합이 초기화될 때까지 기다리는 최대 시간. 쉘 시작 시간이 긴 사용자의 경우, 터미널에서 \"Shell Integration Unavailable\" 오류가 표시되면 이 값을 늘려야 할 수 있습니다. <0>더 알아보기" diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index e184f4d85e..2f57d366da 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -504,6 +504,10 @@ "label": "Terminaluitvoerlimiet", "description": "Maximaal aantal regels dat wordt opgenomen in de terminaluitvoer bij het uitvoeren van commando's. Overtollige regels worden uit het midden verwijderd om tokens te besparen. <0>Meer informatie" }, + "outputCharacterLimit": { + "label": "Tekenlimiet terminal", + "description": "Maximaal aantal tekens dat moet worden opgenomen in de terminaluitvoer bij het uitvoeren van commando's. Deze limiet heeft voorrang op de regellimiet om geheugenproblemen door extreem lange regels te voorkomen. Bij overschrijding wordt de uitvoer afgekapt. <0>Meer informatie" + }, "shellIntegrationTimeout": { "label": "Terminal shell-integratie timeout", "description": "Maximale wachttijd voor het initialiseren van shell-integratie voordat commando's worden uitgevoerd. Voor gebruikers met lange shell-opstarttijden moet deze waarde mogelijk worden verhoogd als je 'Shell Integration Unavailable'-fouten ziet in de terminal. <0>Meer informatie" diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 23d3ce707d..b077286b5a 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -504,6 +504,10 @@ "label": "Limit wyjścia terminala", "description": "Maksymalna liczba linii do uwzględnienia w wyjściu terminala podczas wykonywania poleceń. Po przekroczeniu linie będą usuwane ze środka, oszczędzając token. <0>Dowiedz się więcej" }, + "outputCharacterLimit": { + "label": "Limit znaków w terminalu", + "description": "Maksymalna liczba znaków do uwzględnienia w danych wyjściowych terminala podczas wykonywania poleceń. Limit ten ma pierwszeństwo przed limitem linii, aby zapobiec problemom z pamięcią spowodowanym przez bardzo długie linie. Po przekroczeniu limitu dane wyjściowe zostaną obcięte. <0>Dowiedz się więcej" + }, "shellIntegrationTimeout": { "label": "Limit czasu integracji powłoki terminala", "description": "Maksymalny czas oczekiwania na inicjalizację integracji powłoki przed wykonaniem poleceń. Dla użytkowników z długim czasem uruchamiania powłoki, ta wartość może wymagać zwiększenia, jeśli widzisz błędy \"Shell Integration Unavailable\" w terminalu. <0>Dowiedz się więcej" diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 102036622c..dd24514786 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -504,6 +504,10 @@ "label": "Limite de saída do terminal", "description": "Número máximo de linhas a incluir na saída do terminal ao executar comandos. Quando excedido, as linhas serão removidas do meio, economizando token. <0>Saiba mais" }, + "outputCharacterLimit": { + "label": "Limite de caracteres do terminal", + "description": "Número máximo de caracteres a serem incluídos na saída do terminal ao executar comandos. Este limite tem precedência sobre o limite de linhas para evitar problemas de memória com linhas extremamente longas. Quando excedido, a saída será truncada. <0>Saiba mais" + }, "shellIntegrationTimeout": { "label": "Tempo limite de integração do shell do terminal", "description": "Tempo máximo de espera para a inicialização da integração do shell antes de executar comandos. Para usuários com tempos de inicialização de shell longos, este valor pode precisar ser aumentado se você vir erros \"Shell Integration Unavailable\" no terminal. <0>Saiba mais" diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 5952dd8c89..94dfb0001b 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -504,6 +504,10 @@ "label": "Лимит вывода терминала", "description": "Максимальное количество строк, включаемых в вывод терминала при выполнении команд. При превышении строки из середины будут удаляться для экономии токенов. <0>Подробнее" }, + "outputCharacterLimit": { + "label": "Лимит символов терминала", + "description": "Максимальное количество символов для включения в вывод терминала при выполнении команд. Этот лимит имеет приоритет над лимитом строк, чтобы предотвратить проблемы с памятью из-за чрезвычайно длинных строк. При превышении лимита вывод будет усечен. <0>Узнать больше" + }, "shellIntegrationTimeout": { "label": "Таймаут интеграции оболочки терминала", "description": "Максимальное время ожидания инициализации интеграции оболочки перед выполнением команд. Для пользователей с долгим стартом shell это значение можно увеличить, если появляются ошибки \"Shell Integration Unavailable\". <0>Подробнее" diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 625ca4d5ea..14aec7c370 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -504,6 +504,10 @@ "label": "Terminal çıktısı sınırı", "description": "Komutları yürütürken terminal çıktısına dahil edilecek maksimum satır sayısı. Aşıldığında, token tasarrufu sağlayarak satırlar ortadan kaldırılacaktır. <0>Daha fazla bilgi" }, + "outputCharacterLimit": { + "label": "Terminal karakter sınırı", + "description": "Komutları yürütürken terminal çıktısına dahil edilecek maksimum karakter sayısı. Bu sınır, aşırı uzun satırlardan kaynaklanan bellek sorunlarını önlemek için satır sınırına göre önceliklidir. Aşıldığında, çıktı kesilir. <0>Daha fazla bilgi edinin" + }, "shellIntegrationTimeout": { "label": "Terminal kabuk entegrasyonu zaman aşımı", "description": "Komutları yürütmeden önce kabuk entegrasyonunun başlatılması için beklenecek maksimum süre. Kabuk başlatma süresi uzun olan kullanıcılar için, terminalde \"Shell Integration Unavailable\" hatalarını görürseniz bu değerin artırılması gerekebilir. <0>Daha fazla bilgi" diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 52a9db5b93..edd0af538c 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -504,6 +504,10 @@ "label": "Giới hạn đầu ra terminal", "description": "Số dòng tối đa để đưa vào đầu ra terminal khi thực hiện lệnh. Khi vượt quá, các dòng sẽ bị xóa khỏi phần giữa, tiết kiệm token. <0>Tìm hiểu thêm" }, + "outputCharacterLimit": { + "label": "Giới hạn ký tự của terminal", + "description": "Số ký tự tối đa để bao gồm trong đầu ra của terminal khi thực thi lệnh. Giới hạn này được ưu tiên hơn giới hạn dòng để ngăn chặn các vấn đề về bộ nhớ do các dòng quá dài. Khi vượt quá, đầu ra sẽ bị cắt bớt. <0>Tìm hiểu thêm" + }, "shellIntegrationTimeout": { "label": "Thời gian chờ tích hợp shell terminal", "description": "Thời gian tối đa để chờ tích hợp shell khởi tạo trước khi thực hiện lệnh. Đối với người dùng có thời gian khởi động shell dài, giá trị này có thể cần được tăng lên nếu bạn thấy lỗi \"Shell Integration Unavailable\" trong terminal. <0>Tìm hiểu thêm" diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 151ee9e744..b52ee00199 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -504,6 +504,10 @@ "label": "终端输出限制", "description": "执行命令时在终端输出中包含的最大行数。超过时将从中间删除行,节省 token。 <0>了解更多" }, + "outputCharacterLimit": { + "label": "终端字符限制", + "description": "执行命令时在终端输出中包含的最大字符数。此限制优先于行数限制,以防止因行过长而导致的内存问题。超出后,输出将被截断。 <0>了解更多" + }, "shellIntegrationTimeout": { "label": "终端初始化等待时间", "description": "执行命令前等待 Shell 集成初始化的最长时间。对于 Shell 启动时间较长的用户,如果在终端中看到\"Shell Integration Unavailable\"错误,可能需要增加此值。 <0>了解更多" diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index ab4caeea5b..85baae6ce2 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -504,6 +504,10 @@ "label": "終端機輸出行數限制", "description": "執行命令時終端機輸出的最大行數。超過此限制時,會從中間移除多餘的行數,以節省 token 用量。 <0>瞭解更多" }, + "outputCharacterLimit": { + "label": "終端機字元限制", + "description": "執行指令時在終端輸出中包含的最大字元數。此限制優先於行數限制,以防止因行過長而導致的記憶體問題。超過後,輸出將被截斷。 <0>了解更多" + }, "shellIntegrationTimeout": { "label": "終端機 Shell 整合逾時", "description": "執行命令前等待 Shell 整合初始化的最長時間。如果您的 Shell 啟動較慢,且終端機出現「Shell 整合無法使用」的錯誤訊息,可能需要提高此數值。 <0>瞭解更多"