perf(background-agent): use Set for countedToolPartIDs, cache circuit breaker settings, optimize loop detector

- Replace countedToolPartIDs string[] with Set<string> for O(1) has/add vs O(n) includes/spread (C2)
- Cache resolveCircuitBreakerSettings at manager level to avoid repeated object creation (C3)
- Optimize recordToolCall to avoid full array copy with slice (L1)
This commit is contained in:
YeonGyu-Kim
2026-03-18 14:18:38 +09:00
parent 952bd5338d
commit 2da19fe608
4 changed files with 8 additions and 4 deletions

View File

@@ -44,7 +44,9 @@ export function recordToolCall(
): ToolCallWindow {
const previous = window?.toolSignatures ?? []
const signature = createToolCallSignature(toolName, toolInput)
const toolSignatures = [...previous, signature].slice(-settings.windowSize)
const toolSignatures = previous.length >= settings.windowSize
? [...previous.slice(1), signature]
: [...previous, signature]
return {
toolSignatures,

View File

@@ -233,7 +233,7 @@ describe("BackgroundManager circuit breaker", () => {
expect(task.status).toBe("running")
expect(task.progress?.toolCalls).toBe(1)
expect(task.progress?.countedToolPartIDs).toEqual(["tool-1"])
expect(task.progress?.countedToolPartIDs).toEqual(new Set(["tool-1"]))
})
})

View File

@@ -57,6 +57,7 @@ import {
detectRepetitiveToolUse,
recordToolCall,
resolveCircuitBreakerSettings,
type CircuitBreakerSettings,
} from "./loop-detector"
import {
createSubagentDepthLimitError,
@@ -152,6 +153,7 @@ export class BackgroundManager {
private preStartDescendantReservations: Set<string>
private enableParentSessionNotifications: boolean
readonly taskHistory = new TaskHistory()
private cachedCircuitBreakerSettings?: CircuitBreakerSettings
constructor(
ctx: PluginInput,
@@ -918,7 +920,7 @@ export class BackgroundManager {
task.progress.toolCalls += 1
task.progress.lastTool = partInfo.tool
const circuitBreaker = resolveCircuitBreakerSettings(this.config)
const circuitBreaker = this.cachedCircuitBreakerSettings ?? (this.cachedCircuitBreakerSettings = resolveCircuitBreakerSettings(this.config))
if (partInfo.tool) {
task.progress.toolCallWindow = recordToolCall(
task.progress.toolCallWindow,

View File

@@ -19,7 +19,7 @@ export interface TaskProgress {
toolCalls: number
lastTool?: string
toolCallWindow?: ToolCallWindow
countedToolPartIDs?: string[]
countedToolPartIDs?: Set<string>
lastUpdate: Date
lastMessage?: string
lastMessageAt?: Date