phi-code-agent 0.56.3 → 0.74.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/README.md +109 -33
  2. package/dist/agent-loop.d.ts +3 -0
  3. package/dist/agent-loop.d.ts.map +1 -1
  4. package/dist/agent-loop.js +298 -127
  5. package/dist/agent-loop.js.map +1 -1
  6. package/dist/agent.d.ts +88 -127
  7. package/dist/agent.d.ts.map +1 -1
  8. package/dist/agent.js +323 -318
  9. package/dist/agent.js.map +1 -1
  10. package/dist/harness/agent-harness.d.ts +85 -0
  11. package/dist/harness/agent-harness.d.ts.map +1 -0
  12. package/dist/harness/agent-harness.js +728 -0
  13. package/dist/harness/agent-harness.js.map +1 -0
  14. package/dist/harness/compaction/branch-summarization.d.ts +88 -0
  15. package/dist/harness/compaction/branch-summarization.d.ts.map +1 -0
  16. package/dist/harness/compaction/branch-summarization.js +243 -0
  17. package/dist/harness/compaction/branch-summarization.js.map +1 -0
  18. package/dist/harness/compaction/compaction.d.ts +122 -0
  19. package/dist/harness/compaction/compaction.d.ts.map +1 -0
  20. package/dist/harness/compaction/compaction.js +632 -0
  21. package/dist/harness/compaction/compaction.js.map +1 -0
  22. package/dist/harness/compaction/utils.d.ts +38 -0
  23. package/dist/harness/compaction/utils.d.ts.map +1 -0
  24. package/dist/harness/compaction/utils.js +153 -0
  25. package/dist/harness/compaction/utils.js.map +1 -0
  26. package/dist/harness/env/nodejs.d.ts +44 -0
  27. package/dist/harness/env/nodejs.d.ts.map +1 -0
  28. package/dist/harness/env/nodejs.js +348 -0
  29. package/dist/harness/env/nodejs.js.map +1 -0
  30. package/dist/harness/execution-env.d.ts +4 -0
  31. package/dist/harness/execution-env.d.ts.map +1 -0
  32. package/dist/harness/execution-env.js +3 -0
  33. package/dist/harness/execution-env.js.map +1 -0
  34. package/dist/harness/messages.d.ts +51 -0
  35. package/dist/harness/messages.d.ts.map +1 -0
  36. package/dist/harness/messages.js +102 -0
  37. package/dist/harness/messages.js.map +1 -0
  38. package/dist/harness/prompt-templates.d.ts +45 -0
  39. package/dist/harness/prompt-templates.d.ts.map +1 -0
  40. package/dist/harness/prompt-templates.js +200 -0
  41. package/dist/harness/prompt-templates.js.map +1 -0
  42. package/dist/harness/session/repo/jsonl.d.ts +20 -0
  43. package/dist/harness/session/repo/jsonl.d.ts.map +1 -0
  44. package/dist/harness/session/repo/jsonl.js +92 -0
  45. package/dist/harness/session/repo/jsonl.js.map +1 -0
  46. package/dist/harness/session/repo/memory.d.ts +18 -0
  47. package/dist/harness/session/repo/memory.d.ts.map +1 -0
  48. package/dist/harness/session/repo/memory.js +42 -0
  49. package/dist/harness/session/repo/memory.js.map +1 -0
  50. package/dist/harness/session/repo/shared.d.ts +10 -0
  51. package/dist/harness/session/repo/shared.d.ts.map +1 -0
  52. package/dist/harness/session/repo/shared.js +31 -0
  53. package/dist/harness/session/repo/shared.js.map +1 -0
  54. package/dist/harness/session/session.d.ts +32 -0
  55. package/dist/harness/session/session.d.ts.map +1 -0
  56. package/dist/harness/session/session.js +196 -0
  57. package/dist/harness/session/session.js.map +1 -0
  58. package/dist/harness/session/storage/jsonl.d.ts +30 -0
  59. package/dist/harness/session/storage/jsonl.d.ts.map +1 -0
  60. package/dist/harness/session/storage/jsonl.js +171 -0
  61. package/dist/harness/session/storage/jsonl.js.map +1 -0
  62. package/dist/harness/session/storage/memory.d.ts +26 -0
  63. package/dist/harness/session/storage/memory.d.ts.map +1 -0
  64. package/dist/harness/session/storage/memory.js +90 -0
  65. package/dist/harness/session/storage/memory.js.map +1 -0
  66. package/dist/harness/skills.d.ts +41 -0
  67. package/dist/harness/skills.d.ts.map +1 -0
  68. package/dist/harness/skills.js +259 -0
  69. package/dist/harness/skills.js.map +1 -0
  70. package/dist/harness/system-prompt.d.ts +3 -0
  71. package/dist/harness/system-prompt.d.ts.map +1 -0
  72. package/dist/harness/system-prompt.js +30 -0
  73. package/dist/harness/system-prompt.js.map +1 -0
  74. package/dist/harness/types.d.ts +525 -0
  75. package/dist/harness/types.d.ts.map +1 -0
  76. package/dist/harness/types.js +16 -0
  77. package/dist/harness/types.js.map +1 -0
  78. package/dist/harness/utils/shell-output.d.ts +14 -0
  79. package/dist/harness/utils/shell-output.d.ts.map +1 -0
  80. package/dist/harness/utils/shell-output.js +97 -0
  81. package/dist/harness/utils/shell-output.js.map +1 -0
  82. package/dist/harness/utils/truncate.d.ts +70 -0
  83. package/dist/harness/utils/truncate.d.ts.map +1 -0
  84. package/dist/harness/utils/truncate.js +205 -0
  85. package/dist/harness/utils/truncate.js.map +1 -0
  86. package/dist/index.d.ts +15 -0
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +16 -0
  89. package/dist/index.js.map +1 -1
  90. package/dist/proxy.d.ts +4 -20
  91. package/dist/proxy.d.ts.map +1 -1
  92. package/dist/proxy.js +32 -5
  93. package/dist/proxy.js.map +1 -1
  94. package/dist/types.d.ts +224 -16
  95. package/dist/types.d.ts.map +1 -1
  96. package/dist/types.js.map +1 -1
  97. package/package.json +6 -3
package/dist/agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Agent class that uses the agent-loop directly.\n * No transport abstraction - calls streamSimple via the loop.\n */\n\nimport {\n\tgetModel,\n\ttype ImageContent,\n\ttype Message,\n\ttype Model,\n\tstreamSimple,\n\ttype TextContent,\n\ttype ThinkingBudgets,\n\ttype Transport,\n} from \"phi-code-ai\";\nimport { agentLoop, agentLoopContinue } from \"./agent-loop.js\";\nimport type {\n\tAgentContext,\n\tAgentEvent,\n\tAgentLoopConfig,\n\tAgentMessage,\n\tAgentState,\n\tAgentTool,\n\tStreamFn,\n\tThinkingLevel,\n} from \"./types.js\";\n\n/**\n * Default convertToLlm: Keep only LLM-compatible messages, convert attachments.\n */\nfunction defaultConvertToLlm(messages: AgentMessage[]): Message[] {\n\treturn messages.filter((m) => m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\");\n}\n\nexport interface AgentOptions {\n\tinitialState?: Partial<AgentState>;\n\n\t/**\n\t * Converts AgentMessage[] to LLM-compatible Message[] before each LLM call.\n\t * Default filters to user/assistant/toolResult and converts attachments.\n\t */\n\tconvertToLlm?: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\n\t/**\n\t * Optional transform applied to context before convertToLlm.\n\t * Use for context pruning, injecting external context, etc.\n\t */\n\ttransformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\n\t/**\n\t * Steering mode: \"all\" = send all steering messages at once, \"one-at-a-time\" = one per turn\n\t */\n\tsteeringMode?: \"all\" | \"one-at-a-time\";\n\n\t/**\n\t * Follow-up mode: \"all\" = send all follow-up messages at once, \"one-at-a-time\" = one per turn\n\t */\n\tfollowUpMode?: \"all\" | \"one-at-a-time\";\n\n\t/**\n\t * Custom stream function (for proxy backends, etc.). Default uses streamSimple.\n\t */\n\tstreamFn?: StreamFn;\n\n\t/**\n\t * Optional session identifier forwarded to LLM providers.\n\t * Used by providers that support session-based caching (e.g., OpenAI Codex).\n\t */\n\tsessionId?: string;\n\n\t/**\n\t * Resolves an API key dynamically for each LLM call.\n\t * Useful for expiring tokens (e.g., GitHub Copilot OAuth).\n\t */\n\tgetApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\n\t/**\n\t * Custom token budgets for thinking levels (token-based providers only).\n\t */\n\tthinkingBudgets?: ThinkingBudgets;\n\n\t/**\n\t * Preferred transport for providers that support multiple transports.\n\t */\n\ttransport?: Transport;\n\n\t/**\n\t * Maximum delay in milliseconds to wait for a retry when the server requests a long wait.\n\t * If the server's requested delay exceeds this value, the request fails immediately,\n\t * allowing higher-level retry logic to handle it with user visibility.\n\t * Default: 60000 (60 seconds). Set to 0 to disable the cap.\n\t */\n\tmaxRetryDelayMs?: number;\n}\n\nexport class Agent {\n\tprivate _state: AgentState = {\n\t\tsystemPrompt: \"\",\n\t\tmodel: getModel(\"google\", \"gemini-2.5-flash-lite-preview-06-17\"),\n\t\tthinkingLevel: \"off\",\n\t\ttools: [],\n\t\tmessages: [],\n\t\tisStreaming: false,\n\t\tstreamMessage: null,\n\t\tpendingToolCalls: new Set<string>(),\n\t\terror: undefined,\n\t};\n\n\tprivate listeners = new Set<(e: AgentEvent) => void>();\n\tprivate abortController?: AbortController;\n\tprivate convertToLlm: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\tprivate transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\tprivate steeringQueue: AgentMessage[] = [];\n\tprivate followUpQueue: AgentMessage[] = [];\n\tprivate steeringMode: \"all\" | \"one-at-a-time\";\n\tprivate followUpMode: \"all\" | \"one-at-a-time\";\n\tpublic streamFn: StreamFn;\n\tprivate _sessionId?: string;\n\tpublic getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\tprivate runningPrompt?: Promise<void>;\n\tprivate resolveRunningPrompt?: () => void;\n\tprivate _thinkingBudgets?: ThinkingBudgets;\n\tprivate _transport: Transport;\n\tprivate _maxRetryDelayMs?: number;\n\n\tconstructor(opts: AgentOptions = {}) {\n\t\tthis._state = { ...this._state, ...opts.initialState };\n\t\tthis.convertToLlm = opts.convertToLlm || defaultConvertToLlm;\n\t\tthis.transformContext = opts.transformContext;\n\t\tthis.steeringMode = opts.steeringMode || \"one-at-a-time\";\n\t\tthis.followUpMode = opts.followUpMode || \"one-at-a-time\";\n\t\tthis.streamFn = opts.streamFn || streamSimple;\n\t\tthis._sessionId = opts.sessionId;\n\t\tthis.getApiKey = opts.getApiKey;\n\t\tthis._thinkingBudgets = opts.thinkingBudgets;\n\t\tthis._transport = opts.transport ?? \"sse\";\n\t\tthis._maxRetryDelayMs = opts.maxRetryDelayMs;\n\t}\n\n\t/**\n\t * Get the current session ID used for provider caching.\n\t */\n\tget sessionId(): string | undefined {\n\t\treturn this._sessionId;\n\t}\n\n\t/**\n\t * Set the session ID for provider caching.\n\t * Call this when switching sessions (new session, branch, resume).\n\t */\n\tset sessionId(value: string | undefined) {\n\t\tthis._sessionId = value;\n\t}\n\n\t/**\n\t * Get the current thinking budgets.\n\t */\n\tget thinkingBudgets(): ThinkingBudgets | undefined {\n\t\treturn this._thinkingBudgets;\n\t}\n\n\t/**\n\t * Set custom thinking budgets for token-based providers.\n\t */\n\tset thinkingBudgets(value: ThinkingBudgets | undefined) {\n\t\tthis._thinkingBudgets = value;\n\t}\n\n\t/**\n\t * Get the current preferred transport.\n\t */\n\tget transport(): Transport {\n\t\treturn this._transport;\n\t}\n\n\t/**\n\t * Set the preferred transport.\n\t */\n\tsetTransport(value: Transport) {\n\t\tthis._transport = value;\n\t}\n\n\t/**\n\t * Get the current max retry delay in milliseconds.\n\t */\n\tget maxRetryDelayMs(): number | undefined {\n\t\treturn this._maxRetryDelayMs;\n\t}\n\n\t/**\n\t * Set the maximum delay to wait for server-requested retries.\n\t * Set to 0 to disable the cap.\n\t */\n\tset maxRetryDelayMs(value: number | undefined) {\n\t\tthis._maxRetryDelayMs = value;\n\t}\n\n\tget state(): AgentState {\n\t\treturn this._state;\n\t}\n\n\tsubscribe(fn: (e: AgentEvent) => void): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => this.listeners.delete(fn);\n\t}\n\n\t// State mutators\n\tsetSystemPrompt(v: string) {\n\t\tthis._state.systemPrompt = v;\n\t}\n\n\tsetModel(m: Model<any>) {\n\t\tthis._state.model = m;\n\t}\n\n\tsetThinkingLevel(l: ThinkingLevel) {\n\t\tthis._state.thinkingLevel = l;\n\t}\n\n\tsetSteeringMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.steeringMode = mode;\n\t}\n\n\tgetSteeringMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.steeringMode;\n\t}\n\n\tsetFollowUpMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.followUpMode = mode;\n\t}\n\n\tgetFollowUpMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.followUpMode;\n\t}\n\n\tsetTools(t: AgentTool<any>[]) {\n\t\tthis._state.tools = t;\n\t}\n\n\treplaceMessages(ms: AgentMessage[]) {\n\t\tthis._state.messages = ms.slice();\n\t}\n\n\tappendMessage(m: AgentMessage) {\n\t\tthis._state.messages = [...this._state.messages, m];\n\t}\n\n\t/**\n\t * Queue a steering message to interrupt the agent mid-run.\n\t * Delivered after current tool execution, skips remaining tools.\n\t */\n\tsteer(m: AgentMessage) {\n\t\tthis.steeringQueue.push(m);\n\t}\n\n\t/**\n\t * Queue a follow-up message to be processed after the agent finishes.\n\t * Delivered only when agent has no more tool calls or steering messages.\n\t */\n\tfollowUp(m: AgentMessage) {\n\t\tthis.followUpQueue.push(m);\n\t}\n\n\tclearSteeringQueue() {\n\t\tthis.steeringQueue = [];\n\t}\n\n\tclearFollowUpQueue() {\n\t\tthis.followUpQueue = [];\n\t}\n\n\tclearAllQueues() {\n\t\tthis.steeringQueue = [];\n\t\tthis.followUpQueue = [];\n\t}\n\n\thasQueuedMessages(): boolean {\n\t\treturn this.steeringQueue.length > 0 || this.followUpQueue.length > 0;\n\t}\n\n\tprivate dequeueSteeringMessages(): AgentMessage[] {\n\t\tif (this.steeringMode === \"one-at-a-time\") {\n\t\t\tif (this.steeringQueue.length > 0) {\n\t\t\t\tconst first = this.steeringQueue[0];\n\t\t\t\tthis.steeringQueue = this.steeringQueue.slice(1);\n\t\t\t\treturn [first];\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\n\t\tconst steering = this.steeringQueue.slice();\n\t\tthis.steeringQueue = [];\n\t\treturn steering;\n\t}\n\n\tprivate dequeueFollowUpMessages(): AgentMessage[] {\n\t\tif (this.followUpMode === \"one-at-a-time\") {\n\t\t\tif (this.followUpQueue.length > 0) {\n\t\t\t\tconst first = this.followUpQueue[0];\n\t\t\t\tthis.followUpQueue = this.followUpQueue.slice(1);\n\t\t\t\treturn [first];\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\n\t\tconst followUp = this.followUpQueue.slice();\n\t\tthis.followUpQueue = [];\n\t\treturn followUp;\n\t}\n\n\tclearMessages() {\n\t\tthis._state.messages = [];\n\t}\n\n\tabort() {\n\t\tthis.abortController?.abort();\n\t}\n\n\twaitForIdle(): Promise<void> {\n\t\treturn this.runningPrompt ?? Promise.resolve();\n\t}\n\n\treset() {\n\t\tthis._state.messages = [];\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis._state.error = undefined;\n\t\tthis.steeringQueue = [];\n\t\tthis.followUpQueue = [];\n\t}\n\n\t/** Send a prompt with an AgentMessage */\n\tasync prompt(message: AgentMessage | AgentMessage[]): Promise<void>;\n\tasync prompt(input: string, images?: ImageContent[]): Promise<void>;\n\tasync prompt(input: string | AgentMessage | AgentMessage[], images?: ImageContent[]) {\n\t\tif (this._state.isStreaming) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.\",\n\t\t\t);\n\t\t}\n\n\t\tconst model = this._state.model;\n\t\tif (!model) throw new Error(\"No model configured\");\n\n\t\tlet msgs: AgentMessage[];\n\n\t\tif (Array.isArray(input)) {\n\t\t\tmsgs = input;\n\t\t} else if (typeof input === \"string\") {\n\t\t\tconst content: Array<TextContent | ImageContent> = [{ type: \"text\", text: input }];\n\t\t\tif (images && images.length > 0) {\n\t\t\t\tcontent.push(...images);\n\t\t\t}\n\t\t\tmsgs = [\n\t\t\t\t{\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t];\n\t\t} else {\n\t\t\tmsgs = [input];\n\t\t}\n\n\t\tawait this._runLoop(msgs);\n\t}\n\n\t/**\n\t * Continue from current context (used for retries and resuming queued messages).\n\t */\n\tasync continue() {\n\t\tif (this._state.isStreaming) {\n\t\t\tthrow new Error(\"Agent is already processing. Wait for completion before continuing.\");\n\t\t}\n\n\t\tconst messages = this._state.messages;\n\t\tif (messages.length === 0) {\n\t\t\tthrow new Error(\"No messages to continue from\");\n\t\t}\n\t\tif (messages[messages.length - 1].role === \"assistant\") {\n\t\t\tconst queuedSteering = this.dequeueSteeringMessages();\n\t\t\tif (queuedSteering.length > 0) {\n\t\t\t\tawait this._runLoop(queuedSteering, { skipInitialSteeringPoll: true });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst queuedFollowUp = this.dequeueFollowUpMessages();\n\t\t\tif (queuedFollowUp.length > 0) {\n\t\t\t\tawait this._runLoop(queuedFollowUp);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow new Error(\"Cannot continue from message role: assistant\");\n\t\t}\n\n\t\tawait this._runLoop(undefined);\n\t}\n\n\t/**\n\t * Run the agent loop.\n\t * If messages are provided, starts a new conversation turn with those messages.\n\t * Otherwise, continues from existing context.\n\t */\n\tprivate async _runLoop(messages?: AgentMessage[], options?: { skipInitialSteeringPoll?: boolean }) {\n\t\tconst model = this._state.model;\n\t\tif (!model) throw new Error(\"No model configured\");\n\n\t\tthis.runningPrompt = new Promise<void>((resolve) => {\n\t\t\tthis.resolveRunningPrompt = resolve;\n\t\t});\n\n\t\tthis.abortController = new AbortController();\n\t\tthis._state.isStreaming = true;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.error = undefined;\n\n\t\tconst reasoning = this._state.thinkingLevel === \"off\" ? undefined : this._state.thinkingLevel;\n\n\t\tconst context: AgentContext = {\n\t\t\tsystemPrompt: this._state.systemPrompt,\n\t\t\tmessages: this._state.messages.slice(),\n\t\t\ttools: this._state.tools,\n\t\t};\n\n\t\tlet skipInitialSteeringPoll = options?.skipInitialSteeringPoll === true;\n\n\t\tconst config: AgentLoopConfig = {\n\t\t\tmodel,\n\t\t\treasoning,\n\t\t\tsessionId: this._sessionId,\n\t\t\ttransport: this._transport,\n\t\t\tthinkingBudgets: this._thinkingBudgets,\n\t\t\tmaxRetryDelayMs: this._maxRetryDelayMs,\n\t\t\tconvertToLlm: this.convertToLlm,\n\t\t\ttransformContext: this.transformContext,\n\t\t\tgetApiKey: this.getApiKey,\n\t\t\tgetSteeringMessages: async () => {\n\t\t\t\tif (skipInitialSteeringPoll) {\n\t\t\t\t\tskipInitialSteeringPoll = false;\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\treturn this.dequeueSteeringMessages();\n\t\t\t},\n\t\t\tgetFollowUpMessages: async () => this.dequeueFollowUpMessages(),\n\t\t};\n\n\t\tlet partial: AgentMessage | null = null;\n\n\t\ttry {\n\t\t\tconst stream = messages\n\t\t\t\t? agentLoop(messages, context, config, this.abortController.signal, this.streamFn)\n\t\t\t\t: agentLoopContinue(context, config, this.abortController.signal, this.streamFn);\n\n\t\t\tfor await (const event of stream) {\n\t\t\t\t// Update internal state based on events\n\t\t\t\tswitch (event.type) {\n\t\t\t\t\tcase \"message_start\":\n\t\t\t\t\t\tpartial = event.message;\n\t\t\t\t\t\tthis._state.streamMessage = event.message;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"message_update\":\n\t\t\t\t\t\tpartial = event.message;\n\t\t\t\t\t\tthis._state.streamMessage = event.message;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"message_end\":\n\t\t\t\t\t\tpartial = null;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tthis.appendMessage(event.message);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"tool_execution_start\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.add(event.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"tool_execution_end\": {\n\t\t\t\t\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\t\t\t\t\ts.delete(event.toolCallId);\n\t\t\t\t\t\tthis._state.pendingToolCalls = s;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"turn_end\":\n\t\t\t\t\t\tif (event.message.role === \"assistant\" && (event.message as any).errorMessage) {\n\t\t\t\t\t\t\tthis._state.error = (event.message as any).errorMessage;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"agent_end\":\n\t\t\t\t\t\tthis._state.isStreaming = false;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Emit to listeners\n\t\t\t\tthis.emit(event);\n\t\t\t}\n\n\t\t\t// Handle any remaining partial message\n\t\t\tif (partial && partial.role === \"assistant\" && partial.content.length > 0) {\n\t\t\t\tconst onlyEmpty = !partial.content.some(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\t(c.type === \"thinking\" && c.thinking.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"text\" && c.text.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"toolCall\" && c.name.trim().length > 0),\n\t\t\t\t);\n\t\t\t\tif (!onlyEmpty) {\n\t\t\t\t\tthis.appendMessage(partial);\n\t\t\t\t} else {\n\t\t\t\t\tif (this.abortController?.signal.aborted) {\n\t\t\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err: any) {\n\t\t\tconst errorMsg: AgentMessage = {\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\t\tapi: model.api,\n\t\t\t\tprovider: model.provider,\n\t\t\t\tmodel: model.id,\n\t\t\t\tusage: {\n\t\t\t\t\tinput: 0,\n\t\t\t\t\toutput: 0,\n\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t},\n\t\t\t\tstopReason: this.abortController?.signal.aborted ? \"aborted\" : \"error\",\n\t\t\t\terrorMessage: err?.message || String(err),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t} as AgentMessage;\n\n\t\t\tthis.appendMessage(errorMsg);\n\t\t\tthis._state.error = err?.message || String(err);\n\t\t\tthis.emit({ type: \"agent_end\", messages: [errorMsg] });\n\t\t} finally {\n\t\t\tthis._state.isStreaming = false;\n\t\t\tthis._state.streamMessage = null;\n\t\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\t\tthis.abortController = undefined;\n\t\t\tthis.resolveRunningPrompt?.();\n\t\t\tthis.runningPrompt = undefined;\n\t\t\tthis.resolveRunningPrompt = undefined;\n\t\t}\n\t}\n\n\tprivate emit(e: AgentEvent) {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener(e);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype ImageContent,\n\ttype Message,\n\ttype Model,\n\ttype SimpleStreamOptions,\n\tstreamSimple,\n\ttype TextContent,\n\ttype ThinkingBudgets,\n\ttype Transport,\n} from \"phi-code-ai\";\nimport { runAgentLoop, runAgentLoopContinue } from \"./agent-loop.js\";\nimport type {\n\tAfterToolCallContext,\n\tAfterToolCallResult,\n\tAgentContext,\n\tAgentEvent,\n\tAgentLoopConfig,\n\tAgentLoopTurnUpdate,\n\tAgentMessage,\n\tAgentState,\n\tAgentTool,\n\tBeforeToolCallContext,\n\tBeforeToolCallResult,\n\tStreamFn,\n\tToolExecutionMode,\n} from \"./types.js\";\n\nfunction defaultConvertToLlm(messages: AgentMessage[]): Message[] {\n\treturn messages.filter(\n\t\t(message) => message.role === \"user\" || message.role === \"assistant\" || message.role === \"toolResult\",\n\t);\n}\n\nconst EMPTY_USAGE = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\ttotalTokens: 0,\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\nconst DEFAULT_MODEL = {\n\tid: \"unknown\",\n\tname: \"unknown\",\n\tapi: \"unknown\",\n\tprovider: \"unknown\",\n\tbaseUrl: \"\",\n\treasoning: false,\n\tinput: [],\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\tcontextWindow: 0,\n\tmaxTokens: 0,\n} satisfies Model<any>;\n\nexport type QueueMode = \"all\" | \"one-at-a-time\";\n\ntype MutableAgentState = Omit<AgentState, \"isStreaming\" | \"streamingMessage\" | \"pendingToolCalls\" | \"errorMessage\"> & {\n\tisStreaming: boolean;\n\tstreamingMessage?: AgentMessage;\n\tpendingToolCalls: Set<string>;\n\terrorMessage?: string;\n};\n\nfunction createMutableAgentState(\n\tinitialState?: Partial<Omit<AgentState, \"pendingToolCalls\" | \"isStreaming\" | \"streamingMessage\" | \"errorMessage\">>,\n): MutableAgentState {\n\tlet tools = initialState?.tools?.slice() ?? [];\n\tlet messages = initialState?.messages?.slice() ?? [];\n\n\treturn {\n\t\tsystemPrompt: initialState?.systemPrompt ?? \"\",\n\t\tmodel: initialState?.model ?? DEFAULT_MODEL,\n\t\tthinkingLevel: initialState?.thinkingLevel ?? \"off\",\n\t\tget tools() {\n\t\t\treturn tools;\n\t\t},\n\t\tset tools(nextTools: AgentTool<any>[]) {\n\t\t\ttools = nextTools.slice();\n\t\t},\n\t\tget messages() {\n\t\t\treturn messages;\n\t\t},\n\t\tset messages(nextMessages: AgentMessage[]) {\n\t\t\tmessages = nextMessages.slice();\n\t\t},\n\t\tisStreaming: false,\n\t\tstreamingMessage: undefined,\n\t\tpendingToolCalls: new Set<string>(),\n\t\terrorMessage: undefined,\n\t};\n}\n\n/** Options for constructing an {@link Agent}. */\nexport interface AgentOptions {\n\tinitialState?: Partial<Omit<AgentState, \"pendingToolCalls\" | \"isStreaming\" | \"streamingMessage\" | \"errorMessage\">>;\n\tconvertToLlm?: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\ttransformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\tstreamFn?: StreamFn;\n\tgetApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\tonPayload?: SimpleStreamOptions[\"onPayload\"];\n\tonResponse?: SimpleStreamOptions[\"onResponse\"];\n\tbeforeToolCall?: (context: BeforeToolCallContext, signal?: AbortSignal) => Promise<BeforeToolCallResult | undefined>;\n\tafterToolCall?: (context: AfterToolCallContext, signal?: AbortSignal) => Promise<AfterToolCallResult | undefined>;\n\tprepareNextTurn?: (\n\t\tsignal?: AbortSignal,\n\t) => Promise<AgentLoopTurnUpdate | undefined> | AgentLoopTurnUpdate | undefined;\n\tsteeringMode?: QueueMode;\n\tfollowUpMode?: QueueMode;\n\tsessionId?: string;\n\tthinkingBudgets?: ThinkingBudgets;\n\ttransport?: Transport;\n\tmaxRetryDelayMs?: number;\n\ttoolExecution?: ToolExecutionMode;\n}\n\nclass PendingMessageQueue {\n\tprivate messages: AgentMessage[] = [];\n\n\tconstructor(public mode: QueueMode) {}\n\n\tenqueue(message: AgentMessage): void {\n\t\tthis.messages.push(message);\n\t}\n\n\thasItems(): boolean {\n\t\treturn this.messages.length > 0;\n\t}\n\n\tdrain(): AgentMessage[] {\n\t\tif (this.mode === \"all\") {\n\t\t\tconst drained = this.messages.slice();\n\t\t\tthis.messages = [];\n\t\t\treturn drained;\n\t\t}\n\n\t\tconst first = this.messages[0];\n\t\tif (!first) {\n\t\t\treturn [];\n\t\t}\n\t\tthis.messages = this.messages.slice(1);\n\t\treturn [first];\n\t}\n\n\tclear(): void {\n\t\tthis.messages = [];\n\t}\n}\n\ntype ActiveRun = {\n\tpromise: Promise<void>;\n\tresolve: () => void;\n\tabortController: AbortController;\n};\n\n/**\n * Stateful wrapper around the low-level agent loop.\n *\n * `Agent` owns the current transcript, emits lifecycle events, executes tools,\n * and exposes queueing APIs for steering and follow-up messages.\n */\nexport class Agent {\n\tprivate _state: MutableAgentState;\n\tprivate readonly listeners = new Set<(event: AgentEvent, signal: AbortSignal) => Promise<void> | void>();\n\tprivate readonly steeringQueue: PendingMessageQueue;\n\tprivate readonly followUpQueue: PendingMessageQueue;\n\n\tpublic convertToLlm: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\tpublic transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\tpublic streamFn: StreamFn;\n\tpublic getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\tpublic onPayload?: SimpleStreamOptions[\"onPayload\"];\n\tpublic onResponse?: SimpleStreamOptions[\"onResponse\"];\n\tpublic beforeToolCall?: (\n\t\tcontext: BeforeToolCallContext,\n\t\tsignal?: AbortSignal,\n\t) => Promise<BeforeToolCallResult | undefined>;\n\tpublic afterToolCall?: (\n\t\tcontext: AfterToolCallContext,\n\t\tsignal?: AbortSignal,\n\t) => Promise<AfterToolCallResult | undefined>;\n\tpublic prepareNextTurn?: (\n\t\tsignal?: AbortSignal,\n\t) => Promise<AgentLoopTurnUpdate | undefined> | AgentLoopTurnUpdate | undefined;\n\tprivate activeRun?: ActiveRun;\n\t/** Session identifier forwarded to providers for cache-aware backends. */\n\tpublic sessionId?: string;\n\t/** Optional per-level thinking token budgets forwarded to the stream function. */\n\tpublic thinkingBudgets?: ThinkingBudgets;\n\t/** Preferred transport forwarded to the stream function. */\n\tpublic transport: Transport;\n\t/** Optional cap for provider-requested retry delays. */\n\tpublic maxRetryDelayMs?: number;\n\t/** Tool execution strategy for assistant messages that contain multiple tool calls. */\n\tpublic toolExecution: ToolExecutionMode;\n\n\tconstructor(options: AgentOptions = {}) {\n\t\tthis._state = createMutableAgentState(options.initialState);\n\t\tthis.convertToLlm = options.convertToLlm ?? defaultConvertToLlm;\n\t\tthis.transformContext = options.transformContext;\n\t\tthis.streamFn = options.streamFn ?? streamSimple;\n\t\tthis.getApiKey = options.getApiKey;\n\t\tthis.onPayload = options.onPayload;\n\t\tthis.onResponse = options.onResponse;\n\t\tthis.beforeToolCall = options.beforeToolCall;\n\t\tthis.afterToolCall = options.afterToolCall;\n\t\tthis.prepareNextTurn = options.prepareNextTurn;\n\t\tthis.steeringQueue = new PendingMessageQueue(options.steeringMode ?? \"one-at-a-time\");\n\t\tthis.followUpQueue = new PendingMessageQueue(options.followUpMode ?? \"one-at-a-time\");\n\t\tthis.sessionId = options.sessionId;\n\t\tthis.thinkingBudgets = options.thinkingBudgets;\n\t\tthis.transport = options.transport ?? \"auto\";\n\t\tthis.maxRetryDelayMs = options.maxRetryDelayMs;\n\t\tthis.toolExecution = options.toolExecution ?? \"parallel\";\n\t}\n\n\t/**\n\t * Subscribe to agent lifecycle events.\n\t *\n\t * Listener promises are awaited in subscription order and are included in\n\t * the current run's settlement. Listeners also receive the active abort\n\t * signal for the current run.\n\t *\n\t * `agent_end` is the final emitted event for a run, but the agent does not\n\t * become idle until all awaited listeners for that event have settled.\n\t */\n\tsubscribe(listener: (event: AgentEvent, signal: AbortSignal) => Promise<void> | void): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => this.listeners.delete(listener);\n\t}\n\n\t/**\n\t * Current agent state.\n\t *\n\t * Assigning `state.tools` or `state.messages` copies the provided top-level array.\n\t */\n\tget state(): AgentState {\n\t\treturn this._state;\n\t}\n\n\t/** Controls how queued steering messages are drained. */\n\tset steeringMode(mode: QueueMode) {\n\t\tthis.steeringQueue.mode = mode;\n\t}\n\n\tget steeringMode(): QueueMode {\n\t\treturn this.steeringQueue.mode;\n\t}\n\n\t/** Controls how queued follow-up messages are drained. */\n\tset followUpMode(mode: QueueMode) {\n\t\tthis.followUpQueue.mode = mode;\n\t}\n\n\tget followUpMode(): QueueMode {\n\t\treturn this.followUpQueue.mode;\n\t}\n\n\t/** Queue a message to be injected after the current assistant turn finishes. */\n\tsteer(message: AgentMessage): void {\n\t\tthis.steeringQueue.enqueue(message);\n\t}\n\n\t/** Queue a message to run only after the agent would otherwise stop. */\n\tfollowUp(message: AgentMessage): void {\n\t\tthis.followUpQueue.enqueue(message);\n\t}\n\n\t/** Remove all queued steering messages. */\n\tclearSteeringQueue(): void {\n\t\tthis.steeringQueue.clear();\n\t}\n\n\t/** Remove all queued follow-up messages. */\n\tclearFollowUpQueue(): void {\n\t\tthis.followUpQueue.clear();\n\t}\n\n\t/** Remove all queued steering and follow-up messages. */\n\tclearAllQueues(): void {\n\t\tthis.clearSteeringQueue();\n\t\tthis.clearFollowUpQueue();\n\t}\n\n\t/** Returns true when either queue still contains pending messages. */\n\thasQueuedMessages(): boolean {\n\t\treturn this.steeringQueue.hasItems() || this.followUpQueue.hasItems();\n\t}\n\n\t/** Active abort signal for the current run, if any. */\n\tget signal(): AbortSignal | undefined {\n\t\treturn this.activeRun?.abortController.signal;\n\t}\n\n\t/** Abort the current run, if one is active. */\n\tabort(): void {\n\t\tthis.activeRun?.abortController.abort();\n\t}\n\n\t/**\n\t * Resolve when the current run and all awaited event listeners have finished.\n\t *\n\t * This resolves after `agent_end` listeners settle.\n\t */\n\twaitForIdle(): Promise<void> {\n\t\treturn this.activeRun?.promise ?? Promise.resolve();\n\t}\n\n\t/** Clear transcript state, runtime state, and queued messages. */\n\treset(): void {\n\t\tthis._state.messages = [];\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamingMessage = undefined;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis._state.errorMessage = undefined;\n\t\tthis.clearFollowUpQueue();\n\t\tthis.clearSteeringQueue();\n\t}\n\n\t/** Start a new prompt from text, a single message, or a batch of messages. */\n\tasync prompt(message: AgentMessage | AgentMessage[]): Promise<void>;\n\tasync prompt(input: string, images?: ImageContent[]): Promise<void>;\n\tasync prompt(input: string | AgentMessage | AgentMessage[], images?: ImageContent[]): Promise<void> {\n\t\tif (this.activeRun) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.\",\n\t\t\t);\n\t\t}\n\t\tconst messages = this.normalizePromptInput(input, images);\n\t\tawait this.runPromptMessages(messages);\n\t}\n\n\t/** Continue from the current transcript. The last message must be a user or tool-result message. */\n\tasync continue(): Promise<void> {\n\t\tif (this.activeRun) {\n\t\t\tthrow new Error(\"Agent is already processing. Wait for completion before continuing.\");\n\t\t}\n\n\t\tconst lastMessage = this._state.messages[this._state.messages.length - 1];\n\t\tif (!lastMessage) {\n\t\t\tthrow new Error(\"No messages to continue from\");\n\t\t}\n\n\t\tif (lastMessage.role === \"assistant\") {\n\t\t\tconst queuedSteering = this.steeringQueue.drain();\n\t\t\tif (queuedSteering.length > 0) {\n\t\t\t\tawait this.runPromptMessages(queuedSteering, { skipInitialSteeringPoll: true });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst queuedFollowUps = this.followUpQueue.drain();\n\t\t\tif (queuedFollowUps.length > 0) {\n\t\t\t\tawait this.runPromptMessages(queuedFollowUps);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow new Error(\"Cannot continue from message role: assistant\");\n\t\t}\n\n\t\tawait this.runContinuation();\n\t}\n\n\tprivate normalizePromptInput(\n\t\tinput: string | AgentMessage | AgentMessage[],\n\t\timages?: ImageContent[],\n\t): AgentMessage[] {\n\t\tif (Array.isArray(input)) {\n\t\t\treturn input;\n\t\t}\n\n\t\tif (typeof input !== \"string\") {\n\t\t\treturn [input];\n\t\t}\n\n\t\tconst content: Array<TextContent | ImageContent> = [{ type: \"text\", text: input }];\n\t\tif (images && images.length > 0) {\n\t\t\tcontent.push(...images);\n\t\t}\n\t\treturn [{ role: \"user\", content, timestamp: Date.now() }];\n\t}\n\n\tprivate async runPromptMessages(\n\t\tmessages: AgentMessage[],\n\t\toptions: { skipInitialSteeringPoll?: boolean } = {},\n\t): Promise<void> {\n\t\tawait this.runWithLifecycle(async (signal) => {\n\t\t\tawait runAgentLoop(\n\t\t\t\tmessages,\n\t\t\t\tthis.createContextSnapshot(),\n\t\t\t\tthis.createLoopConfig(options),\n\t\t\t\t(event) => this.processEvents(event),\n\t\t\t\tsignal,\n\t\t\t\tthis.streamFn,\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate async runContinuation(): Promise<void> {\n\t\tawait this.runWithLifecycle(async (signal) => {\n\t\t\tawait runAgentLoopContinue(\n\t\t\t\tthis.createContextSnapshot(),\n\t\t\t\tthis.createLoopConfig(),\n\t\t\t\t(event) => this.processEvents(event),\n\t\t\t\tsignal,\n\t\t\t\tthis.streamFn,\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate createContextSnapshot(): AgentContext {\n\t\treturn {\n\t\t\tsystemPrompt: this._state.systemPrompt,\n\t\t\tmessages: this._state.messages.slice(),\n\t\t\ttools: this._state.tools.slice(),\n\t\t};\n\t}\n\n\tprivate createLoopConfig(options: { skipInitialSteeringPoll?: boolean } = {}): AgentLoopConfig {\n\t\tlet skipInitialSteeringPoll = options.skipInitialSteeringPoll === true;\n\t\treturn {\n\t\t\tmodel: this._state.model,\n\t\t\treasoning: this._state.thinkingLevel === \"off\" ? undefined : this._state.thinkingLevel,\n\t\t\tsessionId: this.sessionId,\n\t\t\tonPayload: this.onPayload,\n\t\t\tonResponse: this.onResponse,\n\t\t\ttransport: this.transport,\n\t\t\tthinkingBudgets: this.thinkingBudgets,\n\t\t\tmaxRetryDelayMs: this.maxRetryDelayMs,\n\t\t\ttoolExecution: this.toolExecution,\n\t\t\tbeforeToolCall: this.beforeToolCall,\n\t\t\tafterToolCall: this.afterToolCall,\n\t\t\tprepareNextTurn: this.prepareNextTurn ? async () => await this.prepareNextTurn?.(this.signal) : undefined,\n\t\t\tconvertToLlm: this.convertToLlm,\n\t\t\ttransformContext: this.transformContext,\n\t\t\tgetApiKey: this.getApiKey,\n\t\t\tgetSteeringMessages: async () => {\n\t\t\t\tif (skipInitialSteeringPoll) {\n\t\t\t\t\tskipInitialSteeringPoll = false;\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\treturn this.steeringQueue.drain();\n\t\t\t},\n\t\t\tgetFollowUpMessages: async () => this.followUpQueue.drain(),\n\t\t};\n\t}\n\n\tprivate async runWithLifecycle(executor: (signal: AbortSignal) => Promise<void>): Promise<void> {\n\t\tif (this.activeRun) {\n\t\t\tthrow new Error(\"Agent is already processing.\");\n\t\t}\n\n\t\tconst abortController = new AbortController();\n\t\tlet resolvePromise = () => {};\n\t\tconst promise = new Promise<void>((resolve) => {\n\t\t\tresolvePromise = resolve;\n\t\t});\n\t\tthis.activeRun = { promise, resolve: resolvePromise, abortController };\n\n\t\tthis._state.isStreaming = true;\n\t\tthis._state.streamingMessage = undefined;\n\t\tthis._state.errorMessage = undefined;\n\n\t\ttry {\n\t\t\tawait executor(abortController.signal);\n\t\t} catch (error) {\n\t\t\tawait this.handleRunFailure(error, abortController.signal.aborted);\n\t\t} finally {\n\t\t\tthis.finishRun();\n\t\t}\n\t}\n\n\tprivate async handleRunFailure(error: unknown, aborted: boolean): Promise<void> {\n\t\tconst failureMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\tapi: this._state.model.api,\n\t\t\tprovider: this._state.model.provider,\n\t\t\tmodel: this._state.model.id,\n\t\t\tusage: EMPTY_USAGE,\n\t\t\tstopReason: aborted ? \"aborted\" : \"error\",\n\t\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\t\ttimestamp: Date.now(),\n\t\t} satisfies AgentMessage;\n\t\tawait this.processEvents({ type: \"message_start\", message: failureMessage });\n\t\tawait this.processEvents({ type: \"message_end\", message: failureMessage });\n\t\tawait this.processEvents({ type: \"turn_end\", message: failureMessage, toolResults: [] });\n\t\tawait this.processEvents({ type: \"agent_end\", messages: [failureMessage] });\n\t}\n\n\tprivate finishRun(): void {\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamingMessage = undefined;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis.activeRun?.resolve();\n\t\tthis.activeRun = undefined;\n\t}\n\n\t/**\n\t * Reduce internal state for a loop event, then await listeners.\n\t *\n\t * `agent_end` only means no further loop events will be emitted. The run is\n\t * considered idle later, after all awaited listeners for `agent_end` finish\n\t * and `finishRun()` clears runtime-owned state.\n\t */\n\tprivate async processEvents(event: AgentEvent): Promise<void> {\n\t\tswitch (event.type) {\n\t\t\tcase \"message_start\":\n\t\t\t\tthis._state.streamingMessage = event.message;\n\t\t\t\tbreak;\n\n\t\t\tcase \"message_update\":\n\t\t\t\tthis._state.streamingMessage = event.message;\n\t\t\t\tbreak;\n\n\t\t\tcase \"message_end\":\n\t\t\t\tthis._state.streamingMessage = undefined;\n\t\t\t\tthis._state.messages.push(event.message);\n\t\t\t\tbreak;\n\n\t\t\tcase \"tool_execution_start\": {\n\t\t\t\tconst pendingToolCalls = new Set(this._state.pendingToolCalls);\n\t\t\t\tpendingToolCalls.add(event.toolCallId);\n\t\t\t\tthis._state.pendingToolCalls = pendingToolCalls;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"tool_execution_end\": {\n\t\t\t\tconst pendingToolCalls = new Set(this._state.pendingToolCalls);\n\t\t\t\tpendingToolCalls.delete(event.toolCallId);\n\t\t\t\tthis._state.pendingToolCalls = pendingToolCalls;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"turn_end\":\n\t\t\t\tif (event.message.role === \"assistant\" && event.message.errorMessage) {\n\t\t\t\t\tthis._state.errorMessage = event.message.errorMessage;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"agent_end\":\n\t\t\t\tthis._state.streamingMessage = undefined;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tconst signal = this.activeRun?.abortController.signal;\n\t\tif (!signal) {\n\t\t\tthrow new Error(\"Agent listener invoked outside active run\");\n\t\t}\n\t\tfor (const listener of this.listeners) {\n\t\t\tawait listener(event, signal);\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,85 @@
1
+ import { type AssistantMessage, type ImageContent, type Model } from "phi-code-ai";
2
+ import { Agent, type QueueMode } from "../agent.js";
3
+ import type { AgentMessage, AgentTool, ThinkingLevel } from "../types.js";
4
+ import type { AbortResult, AgentHarnessEvent, AgentHarnessEventResultMap, AgentHarnessOptions, AgentHarnessOwnEvent, AgentHarnessResources, AgentHarnessStreamOptions, ExecutionEnv, NavigateTreeResult, PromptTemplate, Skill } from "./types.js";
5
+ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate extends PromptTemplate = PromptTemplate, TTool extends AgentTool = AgentTool> {
6
+ readonly agent: Agent;
7
+ readonly env: ExecutionEnv;
8
+ private session;
9
+ private model;
10
+ private thinkingLevel;
11
+ private activeToolNames;
12
+ private nextTurnQueue;
13
+ private phase;
14
+ private steerQueue;
15
+ private followUpQueue;
16
+ private pendingSessionWrites;
17
+ private resources;
18
+ private streamOptions;
19
+ private appliedStreamOptions;
20
+ private appliedSessionId?;
21
+ private systemPrompt;
22
+ private getApiKeyAndHeaders?;
23
+ private tools;
24
+ private listeners;
25
+ private hooks;
26
+ constructor(options: AgentHarnessOptions<TSkill, TPromptTemplate, TTool>);
27
+ private emitOwn;
28
+ private emitAny;
29
+ private emitHook;
30
+ private emitBeforeProviderRequest;
31
+ private emitBeforeProviderPayload;
32
+ private emitQueueUpdate;
33
+ private createTurnState;
34
+ private applyTurnState;
35
+ private validateToolNames;
36
+ private flushPendingSessionWrites;
37
+ private handleAgentEvent;
38
+ private executeTurn;
39
+ prompt(text: string, options?: {
40
+ images?: ImageContent[];
41
+ }): Promise<AssistantMessage>;
42
+ skill(name: string, additionalInstructions?: string): Promise<AssistantMessage>;
43
+ promptFromTemplate(name: string, args?: string[]): Promise<AssistantMessage>;
44
+ steer(text: string, options?: {
45
+ images?: ImageContent[];
46
+ }): void;
47
+ followUp(text: string, options?: {
48
+ images?: ImageContent[];
49
+ }): void;
50
+ nextTurn(text: string, options?: {
51
+ images?: ImageContent[];
52
+ }): void;
53
+ appendMessage(message: AgentMessage): Promise<void>;
54
+ compact(customInstructions?: string): Promise<{
55
+ summary: string;
56
+ firstKeptEntryId: string;
57
+ tokensBefore: number;
58
+ details?: unknown;
59
+ }>;
60
+ navigateTree(targetId: string, options?: {
61
+ summarize?: boolean;
62
+ customInstructions?: string;
63
+ replaceInstructions?: boolean;
64
+ label?: string;
65
+ }): Promise<NavigateTreeResult>;
66
+ setModel(model: Model<any>): Promise<void>;
67
+ setThinkingLevel(level: ThinkingLevel): Promise<void>;
68
+ setActiveTools(toolNames: string[]): Promise<void>;
69
+ get steeringMode(): QueueMode;
70
+ set steeringMode(mode: QueueMode);
71
+ get followUpMode(): QueueMode;
72
+ set followUpMode(mode: QueueMode);
73
+ getResources(): AgentHarnessResources<TSkill, TPromptTemplate>;
74
+ setResources(resources: AgentHarnessResources<TSkill, TPromptTemplate>): Promise<void>;
75
+ getStreamOptions(): AgentHarnessStreamOptions;
76
+ setStreamOptions(streamOptions: AgentHarnessStreamOptions): void;
77
+ setTools(tools: TTool[], activeToolNames?: string[]): Promise<void>;
78
+ abort(): Promise<AbortResult>;
79
+ waitForIdle(): Promise<void>;
80
+ subscribe(listener: (event: AgentHarnessEvent<TSkill, TPromptTemplate>, signal?: AbortSignal) => Promise<void> | void): () => void;
81
+ on<TType extends keyof AgentHarnessEventResultMap>(type: TType, handler: (event: Extract<AgentHarnessOwnEvent, {
82
+ type: TType;
83
+ }>) => Promise<AgentHarnessEventResultMap[TType]> | AgentHarnessEventResultMap[TType]): () => void;
84
+ }
85
+ //# sourceMappingURL=agent-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-harness.d.ts","sourceRoot":"","sources":["../../src/harness/agent-harness.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AssistantMessage, type ImageContent, type Model, streamSimple, type UserMessage } from \"phi-code-ai\";\nimport { Agent, type QueueMode } from \"../agent.js\";\nimport type { AgentEvent, AgentMessage, AgentTool, ThinkingLevel } from \"../types.js\";\nimport { collectEntriesForBranchSummary, generateBranchSummary } from \"./compaction/branch-summarization.js\";\nimport { compact, DEFAULT_COMPACTION_SETTINGS, prepareCompaction } from \"./compaction/compaction.js\";\nimport { formatPromptTemplateInvocation } from \"./prompt-templates.js\";\nimport { formatSkillInvocation } from \"./skills.js\";\nimport type {\n\tAbortResult,\n\tAgentHarnessEvent,\n\tAgentHarnessEventResultMap,\n\tAgentHarnessOptions,\n\tAgentHarnessOwnEvent,\n\tAgentHarnessPhase,\n\tAgentHarnessResources,\n\tAgentHarnessStreamOptions,\n\tAgentHarnessStreamOptionsPatch,\n\tExecutionEnv,\n\tNavigateTreeResult,\n\tPendingSessionWrite,\n\tPromptTemplate,\n\tSession,\n\tSkill,\n} from \"./types.js\";\n\nfunction createUserMessage(text: string, images?: ImageContent[]): UserMessage {\n\tconst content: Array<{ type: \"text\"; text: string } | ImageContent> = [{ type: \"text\", text }];\n\tif (images) content.push(...images);\n\treturn { role: \"user\", content, timestamp: Date.now() };\n}\n\nfunction cloneStreamOptions(streamOptions?: AgentHarnessStreamOptions): AgentHarnessStreamOptions {\n\treturn {\n\t\t...streamOptions,\n\t\theaders: streamOptions?.headers ? { ...streamOptions.headers } : undefined,\n\t\tmetadata: streamOptions?.metadata ? { ...streamOptions.metadata } : undefined,\n\t};\n}\n\nfunction mergeHeaders(...headers: Array<Record<string, string> | undefined>): Record<string, string> | undefined {\n\tconst merged: Record<string, string> = {};\n\tlet hasHeaders = false;\n\tfor (const entry of headers) {\n\t\tif (!entry) continue;\n\t\tObject.assign(merged, entry);\n\t\thasHeaders = true;\n\t}\n\treturn hasHeaders ? merged : undefined;\n}\n\nfunction hasOwn(object: object, key: PropertyKey): boolean {\n\treturn Object.hasOwn(object, key);\n}\n\nfunction applyStreamOptionsPatch(\n\tbase: AgentHarnessStreamOptions,\n\tpatch?: AgentHarnessStreamOptionsPatch,\n): AgentHarnessStreamOptions {\n\tconst result = cloneStreamOptions(base);\n\tif (!patch) return result;\n\n\tif (hasOwn(patch, \"transport\")) result.transport = patch.transport;\n\tif (hasOwn(patch, \"timeoutMs\")) result.timeoutMs = patch.timeoutMs;\n\tif (hasOwn(patch, \"maxRetries\")) result.maxRetries = patch.maxRetries;\n\tif (hasOwn(patch, \"maxRetryDelayMs\")) result.maxRetryDelayMs = patch.maxRetryDelayMs;\n\tif (hasOwn(patch, \"cacheRetention\")) result.cacheRetention = patch.cacheRetention;\n\n\tif (hasOwn(patch, \"headers\")) {\n\t\tif (patch.headers === undefined) {\n\t\t\tresult.headers = undefined;\n\t\t} else {\n\t\t\tconst headers = { ...(result.headers ?? {}) };\n\t\t\tfor (const [key, value] of Object.entries(patch.headers)) {\n\t\t\t\tif (value === undefined) delete headers[key];\n\t\t\t\telse headers[key] = value;\n\t\t\t}\n\t\t\tresult.headers = Object.keys(headers).length > 0 ? headers : undefined;\n\t\t}\n\t}\n\n\tif (hasOwn(patch, \"metadata\")) {\n\t\tif (patch.metadata === undefined) {\n\t\t\tresult.metadata = undefined;\n\t\t} else {\n\t\t\tconst metadata = { ...(result.metadata ?? {}) };\n\t\t\tfor (const [key, value] of Object.entries(patch.metadata)) {\n\t\t\t\tif (value === undefined) delete metadata[key];\n\t\t\t\telse metadata[key] = value;\n\t\t\t}\n\t\t\tresult.metadata = Object.keys(metadata).length > 0 ? metadata : undefined;\n\t\t}\n\t}\n\n\treturn result;\n}\n\ninterface AgentHarnessTurnState<\n\tTSkill extends Skill = Skill,\n\tTPromptTemplate extends PromptTemplate = PromptTemplate,\n\tTTool extends AgentTool = AgentTool,\n> {\n\tmessages: AgentMessage[];\n\tresources: AgentHarnessResources<TSkill, TPromptTemplate>;\n\tstreamOptions: AgentHarnessStreamOptions;\n\tsessionId: string;\n\tsystemPrompt: string;\n\tmodel: Model<any>;\n\tthinkingLevel: ThinkingLevel;\n\ttools: TTool[];\n\tactiveTools: TTool[];\n}\n\nexport class AgentHarness<\n\tTSkill extends Skill = Skill,\n\tTPromptTemplate extends PromptTemplate = PromptTemplate,\n\tTTool extends AgentTool = AgentTool,\n> {\n\treadonly agent: Agent;\n\treadonly env: ExecutionEnv;\n\tprivate session: Session;\n\tprivate model: Model<any>;\n\tprivate thinkingLevel: ThinkingLevel;\n\tprivate activeToolNames: string[];\n\tprivate nextTurnQueue: AgentMessage[] = [];\n\tprivate phase: AgentHarnessPhase = \"idle\";\n\tprivate steerQueue: UserMessage[] = [];\n\tprivate followUpQueue: UserMessage[] = [];\n\tprivate pendingSessionWrites: PendingSessionWrite[] = [];\n\tprivate resources: AgentHarnessResources<TSkill, TPromptTemplate>;\n\tprivate streamOptions: AgentHarnessStreamOptions;\n\tprivate appliedStreamOptions: AgentHarnessStreamOptions = {};\n\tprivate appliedSessionId?: string;\n\tprivate systemPrompt: AgentHarnessOptions<TSkill, TPromptTemplate, TTool>[\"systemPrompt\"];\n\tprivate getApiKeyAndHeaders?: AgentHarnessOptions[\"getApiKeyAndHeaders\"];\n\tprivate tools = new Map<string, TTool>();\n\tprivate listeners = new Set<\n\t\t(event: AgentHarnessEvent<TSkill, TPromptTemplate>, signal?: AbortSignal) => Promise<void> | void\n\t>();\n\tprivate hooks = new Map<keyof AgentHarnessEventResultMap, Set<(event: any) => Promise<any> | any>>();\n\n\tconstructor(options: AgentHarnessOptions<TSkill, TPromptTemplate, TTool>) {\n\t\tthis.agent = new Agent({\n\t\t\tinitialState: {\n\t\t\t\tmodel: options.model,\n\t\t\t\tthinkingLevel: options.thinkingLevel,\n\t\t\t\ttools: options.tools ?? [],\n\t\t\t},\n\t\t\tstreamFn: async (model, context, streamOptions) => {\n\t\t\t\tconst auth = await this.getApiKeyAndHeaders?.(model);\n\t\t\t\tconst snapshotOptions: AgentHarnessStreamOptions = {\n\t\t\t\t\t...this.appliedStreamOptions,\n\t\t\t\t\theaders: mergeHeaders(this.appliedStreamOptions.headers, auth?.headers),\n\t\t\t\t};\n\t\t\t\tconst requestOptions = await this.emitBeforeProviderRequest(\n\t\t\t\t\tmodel,\n\t\t\t\t\tthis.appliedSessionId ?? \"\",\n\t\t\t\t\tsnapshotOptions,\n\t\t\t\t);\n\t\t\t\treturn streamSimple(model, context, {\n\t\t\t\t\tcacheRetention: requestOptions.cacheRetention,\n\t\t\t\t\theaders: requestOptions.headers,\n\t\t\t\t\tmaxRetries: requestOptions.maxRetries,\n\t\t\t\t\tmaxRetryDelayMs: requestOptions.maxRetryDelayMs,\n\t\t\t\t\tmetadata: requestOptions.metadata,\n\t\t\t\t\tonPayload: async (payload) => await this.emitBeforeProviderPayload(model, payload),\n\t\t\t\t\tonResponse: async (response) => {\n\t\t\t\t\t\tconst headers = { ...(response.headers as Record<string, string>) };\n\t\t\t\t\t\tawait this.emitOwn(\n\t\t\t\t\t\t\t{ type: \"after_provider_response\", status: response.status, headers },\n\t\t\t\t\t\t\tthis.agent.signal,\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t\treasoning: streamOptions?.reasoning,\n\t\t\t\t\tsignal: streamOptions?.signal,\n\t\t\t\t\tsessionId: this.appliedSessionId,\n\t\t\t\t\ttimeoutMs: requestOptions.timeoutMs,\n\t\t\t\t\ttransport: requestOptions.transport,\n\t\t\t\t\tapiKey: auth?.apiKey,\n\t\t\t\t});\n\t\t\t},\n\t\t\tsteeringMode: options.steeringMode,\n\t\t\tfollowUpMode: options.followUpMode,\n\t\t});\n\t\tthis.env = options.env;\n\t\tthis.session = options.session;\n\t\tthis.resources = options.resources ?? {};\n\t\tthis.streamOptions = cloneStreamOptions(options.streamOptions);\n\t\tthis.systemPrompt = options.systemPrompt;\n\t\tthis.getApiKeyAndHeaders = options.getApiKeyAndHeaders;\n\t\tfor (const tool of options.tools ?? []) {\n\t\t\tthis.tools.set(tool.name, tool);\n\t\t}\n\t\tthis.model = options.model;\n\t\tthis.thinkingLevel = options.thinkingLevel ?? this.agent.state.thinkingLevel;\n\t\tthis.activeToolNames = options.activeToolNames ?? (options.tools ?? []).map((tool) => tool.name);\n\t\tthis.agent.state.model = this.model;\n\t\tthis.agent.state.thinkingLevel = this.thinkingLevel;\n\t\tthis.agent.transformContext = async (messages) => {\n\t\t\tconst result = await this.emitHook({ type: \"context\", messages: [...messages] });\n\t\t\treturn result?.messages ?? messages;\n\t\t};\n\t\tthis.agent.beforeToolCall = async ({ toolCall, args }) => {\n\t\t\tconst result = await this.emitHook({\n\t\t\t\ttype: \"tool_call\",\n\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\ttoolName: toolCall.name,\n\t\t\t\tinput: args as Record<string, unknown>,\n\t\t\t});\n\t\t\treturn result ? { block: result.block, reason: result.reason } : undefined;\n\t\t};\n\t\tthis.agent.afterToolCall = async ({ toolCall, args, result, isError }) => {\n\t\t\tconst patch = await this.emitHook({\n\t\t\t\ttype: \"tool_result\",\n\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\ttoolName: toolCall.name,\n\t\t\t\tinput: args as Record<string, unknown>,\n\t\t\t\tcontent: result.content,\n\t\t\t\tdetails: result.details,\n\t\t\t\tisError,\n\t\t\t});\n\t\t\treturn patch\n\t\t\t\t? { content: patch.content, details: patch.details, isError: patch.isError, terminate: patch.terminate }\n\t\t\t\t: undefined;\n\t\t};\n\t\tthis.agent.prepareNextTurn = async () => {\n\t\t\tawait this.flushPendingSessionWrites();\n\t\t\tconst turnState = await this.createTurnState();\n\t\t\tthis.applyTurnState(turnState);\n\t\t\treturn {\n\t\t\t\tcontext: {\n\t\t\t\t\tsystemPrompt: turnState.systemPrompt,\n\t\t\t\t\tmessages: turnState.messages.slice(),\n\t\t\t\t\ttools: turnState.activeTools.slice(),\n\t\t\t\t},\n\t\t\t\tmodel: turnState.model,\n\t\t\t\tthinkingLevel: turnState.thinkingLevel,\n\t\t\t};\n\t\t};\n\t\tthis.agent.subscribe(async (event, signal) => {\n\t\t\tawait this.handleAgentEvent(event, signal);\n\t\t});\n\t}\n\n\tprivate async emitOwn(event: AgentHarnessOwnEvent<TSkill, TPromptTemplate>, signal?: AbortSignal): Promise<void> {\n\t\tfor (const listener of this.listeners) {\n\t\t\tawait listener(event, signal);\n\t\t}\n\t}\n\n\tprivate async emitAny(event: AgentHarnessEvent<TSkill, TPromptTemplate>, signal?: AbortSignal): Promise<void> {\n\t\tfor (const listener of this.listeners) {\n\t\t\tawait listener(event, signal);\n\t\t}\n\t}\n\n\tprivate async emitHook<TType extends keyof AgentHarnessEventResultMap>(\n\t\tevent: Extract<AgentHarnessOwnEvent, { type: TType }>,\n\t): Promise<AgentHarnessEventResultMap[TType] | undefined> {\n\t\tconst handlers = this.hooks.get(event.type as TType);\n\t\tif (!handlers || handlers.size === 0) return undefined;\n\t\tlet lastResult: AgentHarnessEventResultMap[TType] | undefined;\n\t\tfor (const handler of handlers) {\n\t\t\tconst result = await handler(event);\n\t\t\tif (result !== undefined) {\n\t\t\t\tlastResult = result;\n\t\t\t}\n\t\t}\n\t\treturn lastResult;\n\t}\n\n\tprivate async emitBeforeProviderRequest(\n\t\tmodel: Model<any>,\n\t\tsessionId: string,\n\t\tstreamOptions: AgentHarnessStreamOptions,\n\t): Promise<AgentHarnessStreamOptions> {\n\t\tconst handlers = this.hooks.get(\"before_provider_request\");\n\t\tlet current = cloneStreamOptions(streamOptions);\n\t\tif (!handlers || handlers.size === 0) return current;\n\t\tfor (const handler of handlers) {\n\t\t\tconst result = await handler({\n\t\t\t\ttype: \"before_provider_request\",\n\t\t\t\tmodel,\n\t\t\t\tsessionId,\n\t\t\t\tstreamOptions: cloneStreamOptions(current),\n\t\t\t});\n\t\t\tif (result?.streamOptions) {\n\t\t\t\tcurrent = applyStreamOptionsPatch(current, result.streamOptions);\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t}\n\n\tprivate async emitBeforeProviderPayload(model: Model<any>, payload: unknown): Promise<unknown> {\n\t\tconst handlers = this.hooks.get(\"before_provider_payload\");\n\t\tlet current = payload;\n\t\tif (!handlers || handlers.size === 0) return current;\n\t\tfor (const handler of handlers) {\n\t\t\tconst result = await handler({ type: \"before_provider_payload\", model, payload: current });\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrent = result.payload;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t}\n\n\tprivate async emitQueueUpdate(): Promise<void> {\n\t\tawait this.emitOwn({\n\t\t\ttype: \"queue_update\",\n\t\t\tsteer: [...this.steerQueue],\n\t\t\tfollowUp: [...this.followUpQueue],\n\t\t\tnextTurn: [...this.nextTurnQueue],\n\t\t});\n\t}\n\n\tprivate async createTurnState(): Promise<AgentHarnessTurnState<TSkill, TPromptTemplate, TTool>> {\n\t\tconst context = await this.session.buildContext();\n\t\tconst resources = this.getResources();\n\t\tconst sessionMetadata = await this.session.getMetadata();\n\t\tconst tools = [...this.tools.values()];\n\t\tconst activeTools = this.activeToolNames\n\t\t\t.map((name) => this.tools.get(name))\n\t\t\t.filter((tool): tool is TTool => tool !== undefined);\n\t\tlet systemPrompt = \"You are a helpful assistant.\";\n\t\tif (typeof this.systemPrompt === \"string\") {\n\t\t\tsystemPrompt = this.systemPrompt;\n\t\t} else if (this.systemPrompt) {\n\t\t\tsystemPrompt = await this.systemPrompt({\n\t\t\t\tenv: this.env,\n\t\t\t\tsession: this.session,\n\t\t\t\tmodel: this.model,\n\t\t\t\tthinkingLevel: this.thinkingLevel,\n\t\t\t\tactiveTools,\n\t\t\t\tresources,\n\t\t\t});\n\t\t}\n\t\treturn {\n\t\t\tmessages: context.messages,\n\t\t\tresources,\n\t\t\tstreamOptions: cloneStreamOptions(this.streamOptions),\n\t\t\tsessionId: sessionMetadata.id,\n\t\t\tsystemPrompt,\n\t\t\tmodel: this.model,\n\t\t\tthinkingLevel: this.thinkingLevel,\n\t\t\ttools,\n\t\t\tactiveTools,\n\t\t};\n\t}\n\n\tprivate applyTurnState(turnState: AgentHarnessTurnState<TSkill, TPromptTemplate, TTool>): void {\n\t\tthis.agent.state.messages = turnState.messages;\n\t\tthis.appliedStreamOptions = cloneStreamOptions(turnState.streamOptions);\n\t\tthis.appliedSessionId = turnState.sessionId;\n\t\tthis.agent.state.systemPrompt = turnState.systemPrompt;\n\t\tthis.agent.state.model = turnState.model;\n\t\tthis.agent.state.thinkingLevel = turnState.thinkingLevel;\n\t\tthis.agent.state.tools = turnState.activeTools;\n\t}\n\n\tprivate validateToolNames(toolNames: string[]): void {\n\t\tconst missing = toolNames.filter((name) => !this.tools.has(name));\n\t\tif (missing.length > 0) throw new Error(`Unknown tool(s): ${missing.join(\", \")}`);\n\t}\n\n\tprivate async flushPendingSessionWrites(): Promise<void> {\n\t\tconst writes = this.pendingSessionWrites;\n\t\tthis.pendingSessionWrites = [];\n\t\tfor (const write of writes) {\n\t\t\tif (write.type === \"message\") {\n\t\t\t\tawait this.session.appendMessage(write.message);\n\t\t\t} else if (write.type === \"model_change\") {\n\t\t\t\tawait this.session.appendModelChange(write.provider, write.modelId);\n\t\t\t} else if (write.type === \"thinking_level_change\") {\n\t\t\t\tawait this.session.appendThinkingLevelChange(write.thinkingLevel);\n\t\t\t} else if (write.type === \"custom\") {\n\t\t\t\tawait this.session.appendCustomEntry(write.customType, write.data);\n\t\t\t} else if (write.type === \"custom_message\") {\n\t\t\t\tawait this.session.appendCustomMessageEntry(write.customType, write.content, write.display, write.details);\n\t\t\t} else if (write.type === \"label\") {\n\t\t\t\tawait this.session.appendLabel(write.targetId, write.label);\n\t\t\t} else if (write.type === \"session_info\") {\n\t\t\t\tawait this.session.appendSessionName(write.name ?? \"\");\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async handleAgentEvent(event: AgentEvent, signal?: AbortSignal): Promise<void> {\n\t\tawait this.emitAny(event, signal);\n\t\tif (event.type === \"message_start\" && event.message.role === \"user\") {\n\t\t\tconst steerIndex = this.steerQueue.indexOf(event.message);\n\t\t\tif (steerIndex !== -1) {\n\t\t\t\tthis.steerQueue.splice(steerIndex, 1);\n\t\t\t\tawait this.emitQueueUpdate();\n\t\t\t} else {\n\t\t\t\tconst followUpIndex = this.followUpQueue.indexOf(event.message);\n\t\t\t\tif (followUpIndex !== -1) {\n\t\t\t\t\tthis.followUpQueue.splice(followUpIndex, 1);\n\t\t\t\t\tawait this.emitQueueUpdate();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (event.type === \"message_end\") {\n\t\t\tawait this.session.appendMessage(event.message);\n\t\t}\n\t\tif (event.type === \"turn_end\") {\n\t\t\tconst hadPendingMutations = this.pendingSessionWrites.length > 0;\n\t\t\tawait this.flushPendingSessionWrites();\n\t\t\tawait this.emitOwn({\n\t\t\t\ttype: \"save_point\",\n\t\t\t\thadPendingMutations,\n\t\t\t});\n\t\t}\n\t\tif (event.type === \"agent_end\") {\n\t\t\tawait this.flushPendingSessionWrites();\n\t\t\tthis.phase = \"idle\";\n\t\t\tawait this.emitOwn({ type: \"settled\", nextTurnCount: this.nextTurnQueue.length }, signal);\n\t\t}\n\t}\n\n\tprivate async executeTurn(\n\t\tturnState: AgentHarnessTurnState<TSkill, TPromptTemplate, TTool>,\n\t\ttext: string,\n\t\toptions?: { images?: ImageContent[] },\n\t): Promise<AssistantMessage> {\n\t\tthis.applyTurnState(turnState);\n\t\tconst beforeLength = this.agent.state.messages.length;\n\t\tlet messages: AgentMessage[] = [createUserMessage(text, options?.images)];\n\t\tif (this.nextTurnQueue.length > 0) {\n\t\t\tmessages = [...this.nextTurnQueue, messages[0]!];\n\t\t\tthis.nextTurnQueue = [];\n\t\t\tawait this.emitQueueUpdate();\n\t\t}\n\t\tconst beforeResult = await this.emitHook({\n\t\t\ttype: \"before_agent_start\",\n\t\t\tprompt: text,\n\t\t\timages: options?.images,\n\t\t\tsystemPrompt: turnState.systemPrompt,\n\t\t\tresources: turnState.resources,\n\t\t});\n\t\tif (beforeResult?.messages) messages = [...beforeResult.messages, ...messages];\n\t\tif (beforeResult?.systemPrompt) this.agent.state.systemPrompt = beforeResult.systemPrompt;\n\t\ttry {\n\t\t\tawait this.agent.prompt(messages);\n\t\t} finally {\n\t\t\tawait this.flushPendingSessionWrites();\n\t\t}\n\t\tlet response: AssistantMessage | undefined;\n\t\tconst newMessages = this.agent.state.messages.slice(beforeLength);\n\t\tfor (let i = newMessages.length - 1; i >= 0; i--) {\n\t\t\tconst message = newMessages[i]!;\n\t\t\tif (message.role === \"assistant\") {\n\t\t\t\tresponse = message;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!response) throw new Error(\"AgentHarness prompt completed without an assistant message\");\n\t\treturn response;\n\t}\n\n\tasync prompt(text: string, options?: { images?: ImageContent[] }): Promise<AssistantMessage> {\n\t\tif (this.phase !== \"idle\") throw new Error(\"AgentHarness is busy\");\n\t\tthis.phase = \"turn\";\n\t\ttry {\n\t\t\tconst turnState = await this.createTurnState();\n\t\t\treturn await this.executeTurn(turnState, text, options);\n\t\t} catch (error) {\n\t\t\tthis.phase = \"idle\";\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync skill(name: string, additionalInstructions?: string): Promise<AssistantMessage> {\n\t\tif (this.phase !== \"idle\") throw new Error(\"AgentHarness is busy\");\n\t\tthis.phase = \"turn\";\n\t\ttry {\n\t\t\tconst turnState = await this.createTurnState();\n\t\t\tconst skill = (turnState.resources.skills ?? []).find((candidate) => candidate.name === name);\n\t\t\tif (!skill) throw new Error(`Unknown skill: ${name}`);\n\t\t\treturn await this.executeTurn(turnState, formatSkillInvocation(skill, additionalInstructions));\n\t\t} catch (error) {\n\t\t\tthis.phase = \"idle\";\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync promptFromTemplate(name: string, args: string[] = []): Promise<AssistantMessage> {\n\t\tif (this.phase !== \"idle\") throw new Error(\"AgentHarness is busy\");\n\t\tthis.phase = \"turn\";\n\t\ttry {\n\t\t\tconst turnState = await this.createTurnState();\n\t\t\tconst template = (turnState.resources.promptTemplates ?? []).find((candidate) => candidate.name === name);\n\t\t\tif (!template) throw new Error(`Unknown prompt template: ${name}`);\n\t\t\treturn await this.executeTurn(turnState, formatPromptTemplateInvocation(template, args));\n\t\t} catch (error) {\n\t\t\tthis.phase = \"idle\";\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tsteer(text: string, options?: { images?: ImageContent[] }): void {\n\t\tif (this.phase === \"idle\") throw new Error(\"Cannot steer while idle\");\n\t\tconst message = createUserMessage(text, options?.images);\n\t\tthis.steerQueue.push(message);\n\t\tthis.agent.steer(message);\n\t\tvoid this.emitQueueUpdate();\n\t}\n\n\tfollowUp(text: string, options?: { images?: ImageContent[] }): void {\n\t\tif (this.phase === \"idle\") throw new Error(\"Cannot follow up while idle\");\n\t\tconst message = createUserMessage(text, options?.images);\n\t\tthis.followUpQueue.push(message);\n\t\tthis.agent.followUp(message);\n\t\tvoid this.emitQueueUpdate();\n\t}\n\n\tnextTurn(text: string, options?: { images?: ImageContent[] }): void {\n\t\tthis.nextTurnQueue.push(createUserMessage(text, options?.images));\n\t\tvoid this.emitQueueUpdate();\n\t}\n\n\tasync appendMessage(message: AgentMessage): Promise<void> {\n\t\tif (this.phase === \"idle\") {\n\t\t\tawait this.session.appendMessage(message);\n\t\t} else {\n\t\t\tthis.pendingSessionWrites.push({ type: \"message\", message });\n\t\t}\n\t}\n\n\tasync compact(\n\t\tcustomInstructions?: string,\n\t): Promise<{ summary: string; firstKeptEntryId: string; tokensBefore: number; details?: unknown }> {\n\t\tif (this.phase !== \"idle\") throw new Error(\"compact() requires idle harness\");\n\t\tthis.phase = \"compaction\";\n\t\tconst model = this.model;\n\t\tif (!model) throw new Error(\"No model set for compaction\");\n\t\tconst auth = await this.getApiKeyAndHeaders?.(model);\n\t\tif (!auth) throw new Error(\"No auth available for compaction\");\n\t\tconst branchEntries = await this.session.getBranch();\n\t\tconst preparation = prepareCompaction(branchEntries, DEFAULT_COMPACTION_SETTINGS);\n\t\tif (!preparation) throw new Error(\"Nothing to compact\");\n\t\tconst hookResult = await this.emitHook({\n\t\t\ttype: \"session_before_compact\",\n\t\t\tpreparation,\n\t\t\tbranchEntries,\n\t\t\tcustomInstructions,\n\t\t\tsignal: new AbortController().signal,\n\t\t});\n\t\tif (hookResult?.cancel) {\n\t\t\tthis.phase = \"idle\";\n\t\t\tthrow new Error(\"Compaction cancelled\");\n\t\t}\n\t\tconst provided = hookResult?.compaction;\n\t\tconst result =\n\t\t\tprovided ??\n\t\t\t(await compact(\n\t\t\t\tpreparation,\n\t\t\t\tmodel,\n\t\t\t\tauth.apiKey,\n\t\t\t\tauth.headers,\n\t\t\t\tcustomInstructions,\n\t\t\t\tundefined,\n\t\t\t\tthis.thinkingLevel,\n\t\t\t));\n\t\tconst entryId = await this.session.appendCompaction(\n\t\t\tresult.summary,\n\t\t\tresult.firstKeptEntryId,\n\t\t\tresult.tokensBefore,\n\t\t\tresult.details,\n\t\t\tprovided !== undefined,\n\t\t);\n\t\tconst entry = await this.session.getEntry(entryId);\n\t\tif (entry?.type === \"compaction\") {\n\t\t\tawait this.emitOwn({ type: \"session_compact\", compactionEntry: entry, fromHook: provided !== undefined });\n\t\t}\n\t\tthis.phase = \"idle\";\n\t\treturn result;\n\t}\n\n\tasync navigateTree(\n\t\ttargetId: string,\n\t\toptions?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string },\n\t): Promise<NavigateTreeResult> {\n\t\tif (this.phase !== \"idle\") throw new Error(\"navigateTree() requires idle harness\");\n\t\tthis.phase = \"branch_summary\";\n\t\tconst oldLeafId = await this.session.getLeafId();\n\t\tif (oldLeafId === targetId) {\n\t\t\tthis.phase = \"idle\";\n\t\t\treturn { cancelled: false };\n\t\t}\n\t\tconst targetEntry = await this.session.getEntry(targetId);\n\t\tif (!targetEntry) throw new Error(`Entry ${targetId} not found`);\n\t\tconst { entries, commonAncestorId } = await collectEntriesForBranchSummary(this.session, oldLeafId, targetId);\n\t\tconst preparation = {\n\t\t\ttargetId,\n\t\t\toldLeafId,\n\t\t\tcommonAncestorId,\n\t\t\tentriesToSummarize: entries,\n\t\t\tuserWantsSummary: options?.summarize ?? false,\n\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\tlabel: options?.label,\n\t\t};\n\t\tconst signal = new AbortController().signal;\n\t\tconst hookResult = await this.emitHook({\n\t\t\ttype: \"session_before_tree\",\n\t\t\tpreparation,\n\t\t\tsignal,\n\t\t});\n\t\tif (hookResult?.cancel) {\n\t\t\tthis.phase = \"idle\";\n\t\t\treturn { cancelled: true };\n\t\t}\n\t\tlet summaryEntry: any | undefined;\n\t\tlet summaryText: string | undefined = hookResult?.summary?.summary;\n\t\tlet summaryDetails: unknown = hookResult?.summary?.details;\n\t\tif (!summaryText && options?.summarize && entries.length > 0) {\n\t\t\tconst model = this.model;\n\t\t\tif (!model) throw new Error(\"No model set for branch summary\");\n\t\t\tconst auth = await this.getApiKeyAndHeaders?.(model);\n\t\t\tif (!auth) throw new Error(\"No auth available for branch summary\");\n\t\t\tconst branchSummary = await generateBranchSummary(entries, {\n\t\t\t\tmodel,\n\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\theaders: auth.headers,\n\t\t\t\tsignal: new AbortController().signal,\n\t\t\t\tcustomInstructions: hookResult?.customInstructions ?? options?.customInstructions,\n\t\t\t\treplaceInstructions: hookResult?.replaceInstructions ?? options?.replaceInstructions,\n\t\t\t});\n\t\t\tif (branchSummary.aborted) {\n\t\t\t\tthis.phase = \"idle\";\n\t\t\t\treturn { cancelled: true };\n\t\t\t}\n\t\t\tif (branchSummary.error) throw new Error(branchSummary.error);\n\t\t\tsummaryText = branchSummary.summary;\n\t\t\tsummaryDetails = {\n\t\t\t\treadFiles: branchSummary.readFiles ?? [],\n\t\t\t\tmodifiedFiles: branchSummary.modifiedFiles ?? [],\n\t\t\t};\n\t\t}\n\t\tlet editorText: string | undefined;\n\t\tlet newLeafId: string | null;\n\t\tif (targetEntry.type === \"message\" && targetEntry.message.role === \"user\") {\n\t\t\tnewLeafId = targetEntry.parentId;\n\t\t\tconst content = targetEntry.message.content;\n\t\t\teditorText =\n\t\t\t\ttypeof content === \"string\"\n\t\t\t\t\t? content\n\t\t\t\t\t: content\n\t\t\t\t\t\t\t.filter((c): c is { readonly type: \"text\"; readonly text: string } => c.type === \"text\")\n\t\t\t\t\t\t\t.map((c) => c.text)\n\t\t\t\t\t\t\t.join(\"\");\n\t\t} else if (targetEntry.type === \"custom_message\") {\n\t\t\tnewLeafId = targetEntry.parentId;\n\t\t\teditorText =\n\t\t\t\ttypeof targetEntry.content === \"string\"\n\t\t\t\t\t? targetEntry.content\n\t\t\t\t\t: targetEntry.content\n\t\t\t\t\t\t\t.filter((c): c is { readonly type: \"text\"; readonly text: string } => c.type === \"text\")\n\t\t\t\t\t\t\t.map((c) => c.text)\n\t\t\t\t\t\t\t.join(\"\");\n\t\t} else {\n\t\t\tnewLeafId = targetId;\n\t\t}\n\t\tconst summaryId = await this.session.moveTo(\n\t\t\tnewLeafId,\n\t\t\tsummaryText\n\t\t\t\t? {\n\t\t\t\t\t\tsummary: summaryText,\n\t\t\t\t\t\tdetails: summaryDetails,\n\t\t\t\t\t\tfromHook: hookResult?.summary !== undefined,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t);\n\t\tif (summaryId) {\n\t\t\tsummaryEntry = await this.session.getEntry(summaryId);\n\t\t}\n\t\tawait this.emitOwn({\n\t\t\ttype: \"session_tree\",\n\t\t\tnewLeafId: await this.session.getLeafId(),\n\t\t\toldLeafId,\n\t\t\tsummaryEntry,\n\t\t\tfromHook: hookResult?.summary !== undefined,\n\t\t});\n\t\tthis.phase = \"idle\";\n\t\treturn { cancelled: false, editorText, summaryEntry };\n\t}\n\n\tasync setModel(model: Model<any>): Promise<void> {\n\t\tconst previousModel = this.model;\n\t\tthis.model = model;\n\t\tif (this.phase === \"idle\") {\n\t\t\tthis.agent.state.model = model;\n\t\t\tawait this.session.appendModelChange(model.provider, model.id);\n\t\t} else {\n\t\t\tthis.pendingSessionWrites.push({ type: \"model_change\", provider: model.provider, modelId: model.id });\n\t\t}\n\t\tawait this.emitOwn({ type: \"model_select\", model, previousModel, source: \"set\" });\n\t}\n\n\tasync setThinkingLevel(level: ThinkingLevel): Promise<void> {\n\t\tconst previousLevel = this.thinkingLevel;\n\t\tthis.thinkingLevel = level;\n\t\tif (this.phase === \"idle\") {\n\t\t\tthis.agent.state.thinkingLevel = level;\n\t\t\tawait this.session.appendThinkingLevelChange(level);\n\t\t} else {\n\t\t\tthis.pendingSessionWrites.push({ type: \"thinking_level_change\", thinkingLevel: level });\n\t\t}\n\t\tawait this.emitOwn({ type: \"thinking_level_select\", level, previousLevel });\n\t}\n\n\tasync setActiveTools(toolNames: string[]): Promise<void> {\n\t\tthis.validateToolNames(toolNames);\n\t\tthis.activeToolNames = [...toolNames];\n\t\tif (this.phase === \"idle\") {\n\t\t\tthis.agent.state.tools = this.activeToolNames.map((name) => this.tools.get(name)!);\n\t\t}\n\t}\n\n\tget steeringMode(): QueueMode {\n\t\treturn this.agent.steeringMode;\n\t}\n\n\tset steeringMode(mode: QueueMode) {\n\t\tthis.agent.steeringMode = mode;\n\t}\n\n\tget followUpMode(): QueueMode {\n\t\treturn this.agent.followUpMode;\n\t}\n\n\tset followUpMode(mode: QueueMode) {\n\t\tthis.agent.followUpMode = mode;\n\t}\n\n\tgetResources(): AgentHarnessResources<TSkill, TPromptTemplate> {\n\t\treturn {\n\t\t\tskills: this.resources.skills?.slice(),\n\t\t\tpromptTemplates: this.resources.promptTemplates?.slice(),\n\t\t};\n\t}\n\n\tasync setResources(resources: AgentHarnessResources<TSkill, TPromptTemplate>): Promise<void> {\n\t\tconst previousResources = this.getResources();\n\t\tthis.resources = {\n\t\t\tskills: resources.skills?.slice(),\n\t\t\tpromptTemplates: resources.promptTemplates?.slice(),\n\t\t};\n\t\tawait this.emitOwn({ type: \"resources_update\", resources: this.getResources(), previousResources });\n\t}\n\n\tgetStreamOptions(): AgentHarnessStreamOptions {\n\t\treturn cloneStreamOptions(this.streamOptions);\n\t}\n\n\tsetStreamOptions(streamOptions: AgentHarnessStreamOptions): void {\n\t\tthis.streamOptions = cloneStreamOptions(streamOptions);\n\t}\n\n\tasync setTools(tools: TTool[], activeToolNames?: string[]): Promise<void> {\n\t\tthis.tools = new Map(tools.map((tool) => [tool.name, tool]));\n\t\tif (activeToolNames) {\n\t\t\tthis.validateToolNames(activeToolNames);\n\t\t\tthis.activeToolNames = [...activeToolNames];\n\t\t} else {\n\t\t\tthis.validateToolNames(this.activeToolNames);\n\t\t}\n\t\tif (this.phase === \"idle\") {\n\t\t\tthis.agent.state.tools = this.activeToolNames.map((name) => this.tools.get(name)!);\n\t\t}\n\t}\n\n\tasync abort(): Promise<AbortResult> {\n\t\tconst clearedSteer = [...this.steerQueue];\n\t\tconst clearedFollowUp = [...this.followUpQueue];\n\t\tthis.steerQueue = [];\n\t\tthis.followUpQueue = [];\n\t\tthis.agent.clearAllQueues();\n\t\tawait this.emitQueueUpdate();\n\t\tthis.agent.abort();\n\t\tawait this.agent.waitForIdle();\n\t\tawait this.emitOwn({ type: \"abort\", clearedSteer, clearedFollowUp });\n\t\treturn { clearedSteer, clearedFollowUp };\n\t}\n\n\tasync waitForIdle(): Promise<void> {\n\t\tawait this.agent.waitForIdle();\n\t}\n\n\tsubscribe(\n\t\tlistener: (event: AgentHarnessEvent<TSkill, TPromptTemplate>, signal?: AbortSignal) => Promise<void> | void,\n\t): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => this.listeners.delete(listener);\n\t}\n\n\ton<TType extends keyof AgentHarnessEventResultMap>(\n\t\ttype: TType,\n\t\thandler: (\n\t\t\tevent: Extract<AgentHarnessOwnEvent, { type: TType }>,\n\t\t) => Promise<AgentHarnessEventResultMap[TType]> | AgentHarnessEventResultMap[TType],\n\t): () => void {\n\t\tlet handlers = this.hooks.get(type);\n\t\tif (!handlers) {\n\t\t\thandlers = new Set();\n\t\t\tthis.hooks.set(type, handlers);\n\t\t}\n\t\thandlers.add(handler as any);\n\t\treturn () => handlers!.delete(handler as any);\n\t}\n}\n"]}