mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-10-06 02:47:56 +00:00
Merge 3068bdca4b into 2bb826039b
This commit is contained in:
commit
eae1f3bdfc
10 changed files with 238 additions and 1 deletions
|
|
@ -176,6 +176,7 @@ export const globalSettingsSchema = z.object({
|
||||||
terminalZshOhMy: z.boolean().optional(),
|
terminalZshOhMy: z.boolean().optional(),
|
||||||
terminalZshP10k: z.boolean().optional(),
|
terminalZshP10k: z.boolean().optional(),
|
||||||
terminalZdotdir: z.boolean().optional(),
|
terminalZdotdir: z.boolean().optional(),
|
||||||
|
maxTerminalPoolSize: z.number().int().min(1).max(20).optional(),
|
||||||
execaShellPath: z.string().optional(),
|
execaShellPath: z.string().optional(),
|
||||||
|
|
||||||
diagnosticsEnabled: z.boolean().optional(),
|
diagnosticsEnabled: z.boolean().optional(),
|
||||||
|
|
@ -356,6 +357,7 @@ export const EVALS_SETTINGS: RooCodeSettings = {
|
||||||
terminalZshP10k: false,
|
terminalZshP10k: false,
|
||||||
terminalZdotdir: true,
|
terminalZdotdir: true,
|
||||||
terminalShellIntegrationDisabled: true,
|
terminalShellIntegrationDisabled: true,
|
||||||
|
maxTerminalPoolSize: 5,
|
||||||
|
|
||||||
diagnosticsEnabled: true,
|
diagnosticsEnabled: true,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,7 @@ export type ExtensionState = Pick<
|
||||||
| "terminalZshOhMy"
|
| "terminalZshOhMy"
|
||||||
| "terminalZshP10k"
|
| "terminalZshP10k"
|
||||||
| "terminalZdotdir"
|
| "terminalZdotdir"
|
||||||
|
| "maxTerminalPoolSize"
|
||||||
| "execaShellPath"
|
| "execaShellPath"
|
||||||
| "diagnosticsEnabled"
|
| "diagnosticsEnabled"
|
||||||
| "language"
|
| "language"
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ import { EMBEDDING_MODEL_PROFILES } from "../../shared/embeddingModels"
|
||||||
import { ProfileValidator } from "../../shared/ProfileValidator"
|
import { ProfileValidator } from "../../shared/ProfileValidator"
|
||||||
|
|
||||||
import { Terminal } from "../../integrations/terminal/Terminal"
|
import { Terminal } from "../../integrations/terminal/Terminal"
|
||||||
|
import { TerminalRegistry } from "../../integrations/terminal/TerminalRegistry"
|
||||||
import { downloadTask, getTaskFileName } from "../../integrations/misc/export-markdown"
|
import { downloadTask, getTaskFileName } from "../../integrations/misc/export-markdown"
|
||||||
import { resolveDefaultSaveUri, saveLastExportPath } from "../../utils/export"
|
import { resolveDefaultSaveUri, saveLastExportPath } from "../../utils/export"
|
||||||
import { getTheme } from "../../integrations/theme/getTheme"
|
import { getTheme } from "../../integrations/theme/getTheme"
|
||||||
|
|
@ -852,6 +853,7 @@ export class ClineProvider
|
||||||
terminalZshP10k = false,
|
terminalZshP10k = false,
|
||||||
terminalPowershellCounter = false,
|
terminalPowershellCounter = false,
|
||||||
terminalZdotdir = false,
|
terminalZdotdir = false,
|
||||||
|
maxTerminalPoolSize = TerminalRegistry.DEFAULT_MAX_TERMINAL_POOL_SIZE,
|
||||||
ttsEnabled,
|
ttsEnabled,
|
||||||
ttsSpeed,
|
ttsSpeed,
|
||||||
}) => {
|
}) => {
|
||||||
|
|
@ -863,6 +865,7 @@ export class ClineProvider
|
||||||
Terminal.setTerminalZshP10k(terminalZshP10k)
|
Terminal.setTerminalZshP10k(terminalZshP10k)
|
||||||
Terminal.setPowershellCounter(terminalPowershellCounter)
|
Terminal.setPowershellCounter(terminalPowershellCounter)
|
||||||
Terminal.setTerminalZdotdir(terminalZdotdir)
|
Terminal.setTerminalZdotdir(terminalZdotdir)
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(maxTerminalPoolSize)
|
||||||
setTtsEnabled(ttsEnabled ?? false)
|
setTtsEnabled(ttsEnabled ?? false)
|
||||||
setTtsSpeed(ttsSpeed ?? 1)
|
setTtsSpeed(ttsSpeed ?? 1)
|
||||||
},
|
},
|
||||||
|
|
@ -2162,6 +2165,7 @@ export class ClineProvider
|
||||||
terminalZshOhMy,
|
terminalZshOhMy,
|
||||||
terminalZshP10k,
|
terminalZshP10k,
|
||||||
terminalZdotdir,
|
terminalZdotdir,
|
||||||
|
maxTerminalPoolSize,
|
||||||
mcpEnabled,
|
mcpEnabled,
|
||||||
currentApiConfigName,
|
currentApiConfigName,
|
||||||
listApiConfigMeta,
|
listApiConfigMeta,
|
||||||
|
|
@ -2282,6 +2286,7 @@ export class ClineProvider
|
||||||
terminalZshOhMy: terminalZshOhMy ?? false,
|
terminalZshOhMy: terminalZshOhMy ?? false,
|
||||||
terminalZshP10k: terminalZshP10k ?? false,
|
terminalZshP10k: terminalZshP10k ?? false,
|
||||||
terminalZdotdir: terminalZdotdir ?? false,
|
terminalZdotdir: terminalZdotdir ?? false,
|
||||||
|
maxTerminalPoolSize: maxTerminalPoolSize ?? TerminalRegistry.DEFAULT_MAX_TERMINAL_POOL_SIZE,
|
||||||
mcpEnabled: mcpEnabled ?? true,
|
mcpEnabled: mcpEnabled ?? true,
|
||||||
currentApiConfigName: currentApiConfigName ?? "default",
|
currentApiConfigName: currentApiConfigName ?? "default",
|
||||||
listApiConfigMeta: listApiConfigMeta ?? [],
|
listApiConfigMeta: listApiConfigMeta ?? [],
|
||||||
|
|
@ -2509,6 +2514,7 @@ export class ClineProvider
|
||||||
terminalZshOhMy: stateValues.terminalZshOhMy ?? false,
|
terminalZshOhMy: stateValues.terminalZshOhMy ?? false,
|
||||||
terminalZshP10k: stateValues.terminalZshP10k ?? false,
|
terminalZshP10k: stateValues.terminalZshP10k ?? false,
|
||||||
terminalZdotdir: stateValues.terminalZdotdir ?? false,
|
terminalZdotdir: stateValues.terminalZdotdir ?? false,
|
||||||
|
maxTerminalPoolSize: stateValues.maxTerminalPoolSize ?? TerminalRegistry.DEFAULT_MAX_TERMINAL_POOL_SIZE,
|
||||||
mode: stateValues.mode ?? defaultModeSlug,
|
mode: stateValues.mode ?? defaultModeSlug,
|
||||||
language: stateValues.language ?? formatLanguage(vscode.env.language),
|
language: stateValues.language ?? formatLanguage(vscode.env.language),
|
||||||
mcpEnabled: stateValues.mcpEnabled ?? true,
|
mcpEnabled: stateValues.mcpEnabled ?? true,
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ import { CodeIndexManager } from "../../services/code-index/manager"
|
||||||
import { checkExistKey } from "../../shared/checkExistApiConfig"
|
import { checkExistKey } from "../../shared/checkExistApiConfig"
|
||||||
import { experimentDefault } from "../../shared/experiments"
|
import { experimentDefault } from "../../shared/experiments"
|
||||||
import { Terminal } from "../../integrations/terminal/Terminal"
|
import { Terminal } from "../../integrations/terminal/Terminal"
|
||||||
|
import { TerminalRegistry } from "../../integrations/terminal/TerminalRegistry"
|
||||||
import { openFile } from "../../integrations/misc/open-file"
|
import { openFile } from "../../integrations/misc/open-file"
|
||||||
import { openImage, saveImage } from "../../integrations/misc/image-handler"
|
import { openImage, saveImage } from "../../integrations/misc/image-handler"
|
||||||
import { selectImages } from "../../integrations/misc/process-images"
|
import { selectImages } from "../../integrations/misc/process-images"
|
||||||
|
|
@ -718,6 +719,10 @@ export const webviewMessageHandler = async (
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
Terminal.setTerminalZdotdir(value as boolean)
|
Terminal.setTerminalZdotdir(value as boolean)
|
||||||
}
|
}
|
||||||
|
} else if (key === "maxTerminalPoolSize") {
|
||||||
|
if (value !== undefined) {
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(value as number)
|
||||||
|
}
|
||||||
} else if (key === "execaShellPath") {
|
} else if (key === "execaShellPath") {
|
||||||
Terminal.setExecaShellPath(value as string | undefined)
|
Terminal.setExecaShellPath(value as string | undefined)
|
||||||
} else if (key === "mcpEnabled") {
|
} else if (key === "mcpEnabled") {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,25 @@ export class TerminalRegistry {
|
||||||
private static disposables: vscode.Disposable[] = []
|
private static disposables: vscode.Disposable[] = []
|
||||||
private static isInitialized = false
|
private static isInitialized = false
|
||||||
|
|
||||||
|
public static readonly DEFAULT_MAX_TERMINAL_POOL_SIZE = 5
|
||||||
|
private static maxTerminalPoolSize: number = TerminalRegistry.DEFAULT_MAX_TERMINAL_POOL_SIZE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum terminal pool size.
|
||||||
|
* @param size The maximum number of terminals to keep in the pool (1-20)
|
||||||
|
*/
|
||||||
|
public static setMaxTerminalPoolSize(size: number): void {
|
||||||
|
this.maxTerminalPoolSize = Math.max(1, Math.min(20, size))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the maximum terminal pool size.
|
||||||
|
* @returns The maximum number of terminals allowed in the pool
|
||||||
|
*/
|
||||||
|
public static getMaxTerminalPoolSize(): number {
|
||||||
|
return this.maxTerminalPoolSize
|
||||||
|
}
|
||||||
|
|
||||||
public static initialize() {
|
public static initialize() {
|
||||||
if (this.isInitialized) {
|
if (this.isInitialized) {
|
||||||
throw new Error("TerminalRegistry.initialize() should only be called once")
|
throw new Error("TerminalRegistry.initialize() should only be called once")
|
||||||
|
|
@ -128,6 +147,9 @@ export class TerminalRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createTerminal(cwd: string, provider: RooTerminalProvider): RooTerminal {
|
public static createTerminal(cwd: string, provider: RooTerminalProvider): RooTerminal {
|
||||||
|
// Enforce pool size limit before creating a new terminal.
|
||||||
|
this.enforcePoolSizeLimit()
|
||||||
|
|
||||||
let newTerminal
|
let newTerminal
|
||||||
|
|
||||||
if (provider === "vscode") {
|
if (provider === "vscode") {
|
||||||
|
|
@ -277,16 +299,29 @@ export class TerminalRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases all terminals associated with a task.
|
* Releases all terminals associated with a task. Idle terminals that
|
||||||
|
* are not busy and have no unretrieved output are disposed (closed).
|
||||||
|
* Busy terminals are simply unassigned from the task.
|
||||||
*
|
*
|
||||||
* @param taskId The task ID
|
* @param taskId The task ID
|
||||||
*/
|
*/
|
||||||
public static releaseTerminalsForTask(taskId: string): void {
|
public static releaseTerminalsForTask(taskId: string): void {
|
||||||
|
const terminalsToDispose: RooTerminal[] = []
|
||||||
|
|
||||||
this.terminals.forEach((terminal) => {
|
this.terminals.forEach((terminal) => {
|
||||||
if (terminal.taskId === taskId) {
|
if (terminal.taskId === taskId) {
|
||||||
terminal.taskId = undefined
|
terminal.taskId = undefined
|
||||||
|
|
||||||
|
// Dispose idle terminals that have no pending output.
|
||||||
|
if (!terminal.busy && !terminal.running && !terminal.process?.hasUnretrievedOutput()) {
|
||||||
|
terminalsToDispose.push(terminal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
for (const terminal of terminalsToDispose) {
|
||||||
|
this.disposeTerminal(terminal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getAllTerminals(): RooTerminal[] {
|
private static getAllTerminals(): RooTerminal[] {
|
||||||
|
|
@ -325,4 +360,47 @@ export class TerminalRegistry {
|
||||||
ShellIntegrationManager.zshCleanupTmpDir(id)
|
ShellIntegrationManager.zshCleanupTmpDir(id)
|
||||||
this.terminals = this.terminals.filter((t) => t.id !== id)
|
this.terminals = this.terminals.filter((t) => t.id !== id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enforces the terminal pool size limit by disposing the oldest idle
|
||||||
|
* terminals when the pool is at or above the maximum size.
|
||||||
|
*/
|
||||||
|
private static enforcePoolSizeLimit(): void {
|
||||||
|
const allTerminals = this.getAllTerminals()
|
||||||
|
|
||||||
|
if (allTerminals.length < this.maxTerminalPoolSize) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find idle terminals (not busy, not running, no task assigned).
|
||||||
|
const idleTerminals = allTerminals.filter(
|
||||||
|
(t) => !t.busy && !t.running && !t.taskId && !t.process?.hasUnretrievedOutput(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dispose oldest idle terminals until we're under the limit.
|
||||||
|
// Terminals are ordered by creation (oldest first).
|
||||||
|
let toRemove = allTerminals.length - this.maxTerminalPoolSize + 1 // +1 to make room for the new one
|
||||||
|
|
||||||
|
for (const terminal of idleTerminals) {
|
||||||
|
if (toRemove <= 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
this.disposeTerminal(terminal)
|
||||||
|
toRemove--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes a terminal by closing the underlying VSCode terminal
|
||||||
|
* and removing it from the registry.
|
||||||
|
*/
|
||||||
|
private static disposeTerminal(terminal: RooTerminal): void {
|
||||||
|
// For VSCode terminals, dispose the underlying terminal.
|
||||||
|
if (terminal instanceof Terminal) {
|
||||||
|
terminal.terminal.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeTerminal(terminal.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,4 +123,113 @@ describe("TerminalRegistry", () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("maxTerminalPoolSize", () => {
|
||||||
|
it("has a default pool size of 5", () => {
|
||||||
|
expect(TerminalRegistry.getMaxTerminalPoolSize()).toBe(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("allows setting pool size within bounds", () => {
|
||||||
|
const original = TerminalRegistry.getMaxTerminalPoolSize()
|
||||||
|
try {
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(10)
|
||||||
|
expect(TerminalRegistry.getMaxTerminalPoolSize()).toBe(10)
|
||||||
|
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(1)
|
||||||
|
expect(TerminalRegistry.getMaxTerminalPoolSize()).toBe(1)
|
||||||
|
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(20)
|
||||||
|
expect(TerminalRegistry.getMaxTerminalPoolSize()).toBe(20)
|
||||||
|
} finally {
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(original)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("clamps pool size to minimum of 1", () => {
|
||||||
|
const original = TerminalRegistry.getMaxTerminalPoolSize()
|
||||||
|
try {
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(0)
|
||||||
|
expect(TerminalRegistry.getMaxTerminalPoolSize()).toBe(1)
|
||||||
|
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(-5)
|
||||||
|
expect(TerminalRegistry.getMaxTerminalPoolSize()).toBe(1)
|
||||||
|
} finally {
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(original)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("clamps pool size to maximum of 20", () => {
|
||||||
|
const original = TerminalRegistry.getMaxTerminalPoolSize()
|
||||||
|
try {
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(25)
|
||||||
|
expect(TerminalRegistry.getMaxTerminalPoolSize()).toBe(20)
|
||||||
|
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(100)
|
||||||
|
expect(TerminalRegistry.getMaxTerminalPoolSize()).toBe(20)
|
||||||
|
} finally {
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(original)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("disposes oldest idle terminal when pool is at capacity", () => {
|
||||||
|
const original = TerminalRegistry.getMaxTerminalPoolSize()
|
||||||
|
try {
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(2)
|
||||||
|
|
||||||
|
// Create 2 terminals to reach the limit
|
||||||
|
const t1 = TerminalRegistry.createTerminal("/test/path1", "vscode")
|
||||||
|
const t2 = TerminalRegistry.createTerminal("/test/path2", "vscode")
|
||||||
|
|
||||||
|
// The first terminal should have been disposed to make room for the second
|
||||||
|
// since pool size is 2, creating the 2nd should be fine
|
||||||
|
// but creating a 3rd should dispose the first idle one
|
||||||
|
const t3 = TerminalRegistry.createTerminal("/test/path3", "vscode")
|
||||||
|
|
||||||
|
// t1's underlying vscode terminal should have been disposed
|
||||||
|
expect((t1 as Terminal).terminal.dispose).toHaveBeenCalled()
|
||||||
|
} finally {
|
||||||
|
TerminalRegistry.setMaxTerminalPoolSize(original)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("releaseTerminalsForTask", () => {
|
||||||
|
it("disposes idle terminals when releasing a task", () => {
|
||||||
|
const t1 = TerminalRegistry.createTerminal("/test/path", "vscode")
|
||||||
|
t1.taskId = "task-1"
|
||||||
|
|
||||||
|
TerminalRegistry.releaseTerminalsForTask("task-1")
|
||||||
|
|
||||||
|
// The terminal should have been disposed since it was idle
|
||||||
|
expect((t1 as Terminal).terminal.dispose).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("does not dispose busy terminals when releasing a task", () => {
|
||||||
|
const t1 = TerminalRegistry.createTerminal("/test/path", "vscode")
|
||||||
|
t1.taskId = "task-2"
|
||||||
|
t1.busy = true
|
||||||
|
|
||||||
|
TerminalRegistry.releaseTerminalsForTask("task-2")
|
||||||
|
|
||||||
|
// The terminal should NOT have been disposed since it was busy
|
||||||
|
expect((t1 as Terminal).terminal.dispose).not.toHaveBeenCalled()
|
||||||
|
// But its taskId should have been cleared
|
||||||
|
expect(t1.taskId).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("does not dispose terminals belonging to other tasks", () => {
|
||||||
|
const t1 = TerminalRegistry.createTerminal("/test/path", "vscode")
|
||||||
|
t1.taskId = "task-3"
|
||||||
|
|
||||||
|
const t2 = TerminalRegistry.createTerminal("/test/path", "vscode")
|
||||||
|
t2.taskId = "task-4"
|
||||||
|
|
||||||
|
TerminalRegistry.releaseTerminalsForTask("task-3")
|
||||||
|
|
||||||
|
// t1 should be disposed (idle, belongs to task-3)
|
||||||
|
expect((t1 as Terminal).terminal.dispose).toHaveBeenCalled()
|
||||||
|
// t2 should NOT be disposed (belongs to task-4)
|
||||||
|
expect((t2 as Terminal).terminal.dispose).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
||||||
terminalZshOhMy,
|
terminalZshOhMy,
|
||||||
terminalZshP10k,
|
terminalZshP10k,
|
||||||
terminalZdotdir,
|
terminalZdotdir,
|
||||||
|
maxTerminalPoolSize,
|
||||||
writeDelayMs,
|
writeDelayMs,
|
||||||
showRooIgnoredFiles,
|
showRooIgnoredFiles,
|
||||||
enableSubfolderRules,
|
enableSubfolderRules,
|
||||||
|
|
@ -396,6 +397,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
||||||
terminalZshOhMy,
|
terminalZshOhMy,
|
||||||
terminalZshP10k,
|
terminalZshP10k,
|
||||||
terminalZdotdir,
|
terminalZdotdir,
|
||||||
|
maxTerminalPoolSize: maxTerminalPoolSize ?? 5,
|
||||||
terminalOutputPreviewSize: terminalOutputPreviewSize ?? "medium",
|
terminalOutputPreviewSize: terminalOutputPreviewSize ?? "medium",
|
||||||
mcpEnabled,
|
mcpEnabled,
|
||||||
maxOpenTabsContext: Math.min(Math.max(0, maxOpenTabsContext ?? 20), 500),
|
maxOpenTabsContext: Math.min(Math.max(0, maxOpenTabsContext ?? 20), 500),
|
||||||
|
|
@ -862,6 +864,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
||||||
terminalZshOhMy={terminalZshOhMy}
|
terminalZshOhMy={terminalZshOhMy}
|
||||||
terminalZshP10k={terminalZshP10k}
|
terminalZshP10k={terminalZshP10k}
|
||||||
terminalZdotdir={terminalZdotdir}
|
terminalZdotdir={terminalZdotdir}
|
||||||
|
maxTerminalPoolSize={maxTerminalPoolSize}
|
||||||
setCachedStateField={setCachedStateField}
|
setCachedStateField={setCachedStateField}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ type TerminalSettingsProps = HTMLAttributes<HTMLDivElement> & {
|
||||||
terminalZshOhMy?: boolean
|
terminalZshOhMy?: boolean
|
||||||
terminalZshP10k?: boolean
|
terminalZshP10k?: boolean
|
||||||
terminalZdotdir?: boolean
|
terminalZdotdir?: boolean
|
||||||
|
maxTerminalPoolSize?: number
|
||||||
setCachedStateField: SetCachedStateField<
|
setCachedStateField: SetCachedStateField<
|
||||||
| "terminalOutputPreviewSize"
|
| "terminalOutputPreviewSize"
|
||||||
| "terminalShellIntegrationTimeout"
|
| "terminalShellIntegrationTimeout"
|
||||||
|
|
@ -36,6 +37,7 @@ type TerminalSettingsProps = HTMLAttributes<HTMLDivElement> & {
|
||||||
| "terminalZshOhMy"
|
| "terminalZshOhMy"
|
||||||
| "terminalZshP10k"
|
| "terminalZshP10k"
|
||||||
| "terminalZdotdir"
|
| "terminalZdotdir"
|
||||||
|
| "maxTerminalPoolSize"
|
||||||
>
|
>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,6 +51,7 @@ export const TerminalSettings = ({
|
||||||
terminalZshOhMy,
|
terminalZshOhMy,
|
||||||
terminalZshP10k,
|
terminalZshP10k,
|
||||||
terminalZdotdir,
|
terminalZdotdir,
|
||||||
|
maxTerminalPoolSize,
|
||||||
setCachedStateField,
|
setCachedStateField,
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
|
|
@ -124,6 +127,28 @@ export const TerminalSettings = ({
|
||||||
{t("settings:terminal.outputPreviewSize.description")}
|
{t("settings:terminal.outputPreviewSize.description")}
|
||||||
</div>
|
</div>
|
||||||
</SearchableSetting>
|
</SearchableSetting>
|
||||||
|
|
||||||
|
<SearchableSetting
|
||||||
|
settingId="terminal-max-pool-size"
|
||||||
|
section="terminal"
|
||||||
|
label={t("settings:terminal.maxPoolSize.label")}>
|
||||||
|
<label className="block font-medium mb-1">{t("settings:terminal.maxPoolSize.label")}</label>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Slider
|
||||||
|
min={1}
|
||||||
|
max={20}
|
||||||
|
step={1}
|
||||||
|
value={[maxTerminalPoolSize ?? 5]}
|
||||||
|
onValueChange={([value]) =>
|
||||||
|
setCachedStateField("maxTerminalPoolSize", Math.min(20, Math.max(1, value)))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="w-10">{maxTerminalPoolSize ?? 5}</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-vscode-descriptionForeground text-sm mt-1">
|
||||||
|
{t("settings:terminal.maxPoolSize.description")}
|
||||||
|
</div>
|
||||||
|
</SearchableSetting>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,8 @@ export interface ExtensionStateContextType extends ExtensionState {
|
||||||
setWriteDelayMs: (value: number) => void
|
setWriteDelayMs: (value: number) => void
|
||||||
terminalOutputPreviewSize?: "small" | "medium" | "large"
|
terminalOutputPreviewSize?: "small" | "medium" | "large"
|
||||||
setTerminalOutputPreviewSize: (value: "small" | "medium" | "large") => void
|
setTerminalOutputPreviewSize: (value: "small" | "medium" | "large") => void
|
||||||
|
maxTerminalPoolSize?: number
|
||||||
|
setMaxTerminalPoolSize: (value: number) => void
|
||||||
mcpEnabled: boolean
|
mcpEnabled: boolean
|
||||||
setMcpEnabled: (value: boolean) => void
|
setMcpEnabled: (value: boolean) => void
|
||||||
taskSyncEnabled: boolean
|
taskSyncEnabled: boolean
|
||||||
|
|
@ -207,6 +209,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
||||||
language: "en", // Default language code
|
language: "en", // Default language code
|
||||||
writeDelayMs: 1000,
|
writeDelayMs: 1000,
|
||||||
terminalShellIntegrationTimeout: 4000,
|
terminalShellIntegrationTimeout: 4000,
|
||||||
|
maxTerminalPoolSize: 5,
|
||||||
mcpEnabled: true,
|
mcpEnabled: true,
|
||||||
taskSyncEnabled: false,
|
taskSyncEnabled: false,
|
||||||
currentApiConfigName: "default",
|
currentApiConfigName: "default",
|
||||||
|
|
@ -545,6 +548,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
||||||
setTerminalShellIntegrationDisabled: (value) =>
|
setTerminalShellIntegrationDisabled: (value) =>
|
||||||
setState((prevState) => ({ ...prevState, terminalShellIntegrationDisabled: value })),
|
setState((prevState) => ({ ...prevState, terminalShellIntegrationDisabled: value })),
|
||||||
setTerminalZdotdir: (value) => setState((prevState) => ({ ...prevState, terminalZdotdir: value })),
|
setTerminalZdotdir: (value) => setState((prevState) => ({ ...prevState, terminalZdotdir: value })),
|
||||||
|
setMaxTerminalPoolSize: (value) => setState((prevState) => ({ ...prevState, maxTerminalPoolSize: value })),
|
||||||
setMcpEnabled: (value) => setState((prevState) => ({ ...prevState, mcpEnabled: value })),
|
setMcpEnabled: (value) => setState((prevState) => ({ ...prevState, mcpEnabled: value })),
|
||||||
setTaskSyncEnabled: (value) => setState((prevState) => ({ ...prevState, taskSyncEnabled: value }) as any),
|
setTaskSyncEnabled: (value) => setState((prevState) => ({ ...prevState, taskSyncEnabled: value }) as any),
|
||||||
setCurrentApiConfigName: (value) => setState((prevState) => ({ ...prevState, currentApiConfigName: value })),
|
setCurrentApiConfigName: (value) => setState((prevState) => ({ ...prevState, currentApiConfigName: value })),
|
||||||
|
|
|
||||||
|
|
@ -757,6 +757,10 @@
|
||||||
"label": "Terminal character limit",
|
"label": "Terminal character limit",
|
||||||
"description": "Overrides the line limit to prevent memory issues by enforcing a hard cap on output size. If exceeded, keeps the beginning and end and shows a placeholder to Roo where content is skipped. <0>Learn more</0>"
|
"description": "Overrides the line limit to prevent memory issues by enforcing a hard cap on output size. If exceeded, keeps the beginning and end and shows a placeholder to Roo where content is skipped. <0>Learn more</0>"
|
||||||
},
|
},
|
||||||
|
"maxPoolSize": {
|
||||||
|
"label": "Maximum terminal pool size",
|
||||||
|
"description": "Maximum number of terminals Roo Code can keep open at the same time. When this limit is reached, the oldest idle terminal is closed before creating a new one. Lower values help keep your workspace tidy; higher values avoid repeatedly opening new terminals."
|
||||||
|
},
|
||||||
"outputPreviewSize": {
|
"outputPreviewSize": {
|
||||||
"label": "Command output preview size",
|
"label": "Command output preview size",
|
||||||
"description": "Controls how much command output Roo sees directly. Full output is always saved and accessible when needed.",
|
"description": "Controls how much command output Roo sees directly. Full output is always saved and accessible when needed.",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue