@nervekit/orchestrator 0.1.0 → 0.2.0

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 (271) hide show
  1. package/dist/domains/agents/run/agent-run-session.d.ts.map +1 -1
  2. package/dist/domains/agents/run/agent-run-session.js +25 -2
  3. package/dist/domains/agents/run/agent-run-session.js.map +1 -1
  4. package/dist/domains/agents/run/agent-runner.d.ts +12 -1
  5. package/dist/domains/agents/run/agent-runner.d.ts.map +1 -1
  6. package/dist/domains/agents/run/agent-runner.js +166 -1
  7. package/dist/domains/agents/run/agent-runner.js.map +1 -1
  8. package/dist/domains/agents/run/inline-command-results.d.ts +8 -0
  9. package/dist/domains/agents/run/inline-command-results.d.ts.map +1 -0
  10. package/dist/domains/agents/run/inline-command-results.js +109 -0
  11. package/dist/domains/agents/run/inline-command-results.js.map +1 -0
  12. package/dist/domains/tasks/task-manager-foreground.d.ts.map +1 -1
  13. package/dist/domains/tasks/task-manager-foreground.js +4 -1
  14. package/dist/domains/tasks/task-manager-foreground.js.map +1 -1
  15. package/dist/domains/tasks/task-manager.d.ts +2 -1
  16. package/dist/domains/tasks/task-manager.d.ts.map +1 -1
  17. package/dist/domains/tasks/task-manager.js.map +1 -1
  18. package/dist/domains/tasks/task-supervisor.d.ts.map +1 -1
  19. package/dist/domains/tasks/task-supervisor.js +12 -1
  20. package/dist/domains/tasks/task-supervisor.js.map +1 -1
  21. package/dist/domains/tools/orchestration-tool-dispatcher.d.ts.map +1 -1
  22. package/dist/domains/tools/orchestration-tool-dispatcher.js +2 -1
  23. package/dist/domains/tools/orchestration-tool-dispatcher.js.map +1 -1
  24. package/dist/domains/tools/tool-service.d.ts +2 -0
  25. package/dist/domains/tools/tool-service.d.ts.map +1 -1
  26. package/dist/domains/tools/tool-service.js.map +1 -1
  27. package/dist/registry.d.ts +11 -11
  28. package/dist/runtime/runtime-state.d.ts +2 -2
  29. package/dist/web/assets/{dist-DVpGQCt0.js → dist-BaA_eB0I.js} +1 -1
  30. package/dist/web/assets/{index-DFKLdj_D.css → index-C45Kmr75.css} +1 -1
  31. package/dist/web/assets/index-DHfIkEia.js +167 -0
  32. package/dist/web/index.html +2 -2
  33. package/dist/web/sw.js +1 -1
  34. package/package.json +4 -4
  35. package/dist/agent-process.d.ts +0 -32
  36. package/dist/agent-process.d.ts.map +0 -1
  37. package/dist/agent-process.js +0 -129
  38. package/dist/agent-process.js.map +0 -1
  39. package/dist/agent-runner/agent-runner.d.ts +0 -65
  40. package/dist/agent-runner/agent-runner.d.ts.map +0 -1
  41. package/dist/agent-runner/agent-runner.js +0 -802
  42. package/dist/agent-runner/agent-runner.js.map +0 -1
  43. package/dist/agent-runner/index.d.ts +0 -6
  44. package/dist/agent-runner/index.d.ts.map +0 -1
  45. package/dist/agent-runner/index.js +0 -4
  46. package/dist/agent-runner/index.js.map +0 -1
  47. package/dist/agent-runner/message-mirror.d.ts +0 -44
  48. package/dist/agent-runner/message-mirror.d.ts.map +0 -1
  49. package/dist/agent-runner/message-mirror.js +0 -154
  50. package/dist/agent-runner/message-mirror.js.map +0 -1
  51. package/dist/agent-runner/run-state.d.ts +0 -12
  52. package/dist/agent-runner/run-state.d.ts.map +0 -1
  53. package/dist/agent-runner/run-state.js +0 -2
  54. package/dist/agent-runner/run-state.js.map +0 -1
  55. package/dist/agent-runner/subagent-runner.d.ts +0 -29
  56. package/dist/agent-runner/subagent-runner.d.ts.map +0 -1
  57. package/dist/agent-runner/subagent-runner.js +0 -84
  58. package/dist/agent-runner/subagent-runner.js.map +0 -1
  59. package/dist/agent-runner/system-prompt-builder.d.ts +0 -19
  60. package/dist/agent-runner/system-prompt-builder.d.ts.map +0 -1
  61. package/dist/agent-runner/system-prompt-builder.js +0 -35
  62. package/dist/agent-runner/system-prompt-builder.js.map +0 -1
  63. package/dist/agent-runner/tool-draft-streaming.d.ts +0 -2
  64. package/dist/agent-runner/tool-draft-streaming.d.ts.map +0 -1
  65. package/dist/agent-runner/tool-draft-streaming.js +0 -5
  66. package/dist/agent-runner/tool-draft-streaming.js.map +0 -1
  67. package/dist/agent-suspension-service.d.ts +0 -44
  68. package/dist/agent-suspension-service.d.ts.map +0 -1
  69. package/dist/agent-suspension-service.js +0 -96
  70. package/dist/agent-suspension-service.js.map +0 -1
  71. package/dist/agent-tool-adapter.d.ts +0 -20
  72. package/dist/agent-tool-adapter.d.ts.map +0 -1
  73. package/dist/agent-tool-adapter.js +0 -215
  74. package/dist/agent-tool-adapter.js.map +0 -1
  75. package/dist/agents/agent-authority.d.ts +0 -5
  76. package/dist/agents/agent-authority.d.ts.map +0 -1
  77. package/dist/agents/agent-authority.js +0 -28
  78. package/dist/agents/agent-authority.js.map +0 -1
  79. package/dist/agents/agent-budget.d.ts +0 -3
  80. package/dist/agents/agent-budget.d.ts.map +0 -1
  81. package/dist/agents/agent-budget.js +0 -17
  82. package/dist/agents/agent-budget.js.map +0 -1
  83. package/dist/agents/agent-status.d.ts +0 -4
  84. package/dist/agents/agent-status.d.ts.map +0 -1
  85. package/dist/agents/agent-status.js +0 -10
  86. package/dist/agents/agent-status.js.map +0 -1
  87. package/dist/conversation-operations/compaction-service.d.ts +0 -37
  88. package/dist/conversation-operations/compaction-service.d.ts.map +0 -1
  89. package/dist/conversation-operations/compaction-service.js +0 -102
  90. package/dist/conversation-operations/compaction-service.js.map +0 -1
  91. package/dist/conversation-operations/export-service.d.ts +0 -22
  92. package/dist/conversation-operations/export-service.d.ts.map +0 -1
  93. package/dist/conversation-operations/export-service.js +0 -79
  94. package/dist/conversation-operations/export-service.js.map +0 -1
  95. package/dist/conversation-operations/import-service.d.ts +0 -20
  96. package/dist/conversation-operations/import-service.d.ts.map +0 -1
  97. package/dist/conversation-operations/import-service.js +0 -97
  98. package/dist/conversation-operations/import-service.js.map +0 -1
  99. package/dist/conversation-operations/index.d.ts +0 -8
  100. package/dist/conversation-operations/index.d.ts.map +0 -1
  101. package/dist/conversation-operations/index.js +0 -6
  102. package/dist/conversation-operations/index.js.map +0 -1
  103. package/dist/conversation-operations/navigation-service.d.ts +0 -18
  104. package/dist/conversation-operations/navigation-service.d.ts.map +0 -1
  105. package/dist/conversation-operations/navigation-service.js +0 -102
  106. package/dist/conversation-operations/navigation-service.js.map +0 -1
  107. package/dist/conversation-operations/summary.d.ts +0 -11
  108. package/dist/conversation-operations/summary.d.ts.map +0 -1
  109. package/dist/conversation-operations/summary.js +0 -29
  110. package/dist/conversation-operations/summary.js.map +0 -1
  111. package/dist/conversation-runtime.d.ts +0 -96
  112. package/dist/conversation-runtime.d.ts.map +0 -1
  113. package/dist/conversation-runtime.js +0 -363
  114. package/dist/conversation-runtime.js.map +0 -1
  115. package/dist/conversation-service.d.ts +0 -17
  116. package/dist/conversation-service.d.ts.map +0 -1
  117. package/dist/conversation-service.js +0 -56
  118. package/dist/conversation-service.js.map +0 -1
  119. package/dist/domains/processes/index.d.ts +0 -10
  120. package/dist/domains/processes/index.d.ts.map +0 -1
  121. package/dist/domains/processes/index.js +0 -7
  122. package/dist/domains/processes/index.js.map +0 -1
  123. package/dist/domains/processes/process-launch-config.store.d.ts +0 -21
  124. package/dist/domains/processes/process-launch-config.store.d.ts.map +0 -1
  125. package/dist/domains/processes/process-launch-config.store.js +0 -49
  126. package/dist/domains/processes/process-launch-config.store.js.map +0 -1
  127. package/dist/domains/processes/process-log.service.d.ts +0 -25
  128. package/dist/domains/processes/process-log.service.d.ts.map +0 -1
  129. package/dist/domains/processes/process-log.service.js +0 -155
  130. package/dist/domains/processes/process-log.service.js.map +0 -1
  131. package/dist/domains/processes/process-manager.d.ts +0 -107
  132. package/dist/domains/processes/process-manager.d.ts.map +0 -1
  133. package/dist/domains/processes/process-manager.js +0 -814
  134. package/dist/domains/processes/process-manager.js.map +0 -1
  135. package/dist/domains/processes/process-readiness.service.d.ts +0 -7
  136. package/dist/domains/processes/process-readiness.service.d.ts.map +0 -1
  137. package/dist/domains/processes/process-readiness.service.js +0 -26
  138. package/dist/domains/processes/process-readiness.service.js.map +0 -1
  139. package/dist/domains/processes/process-status.d.ts +0 -5
  140. package/dist/domains/processes/process-status.d.ts.map +0 -1
  141. package/dist/domains/processes/process-status.js +0 -13
  142. package/dist/domains/processes/process-status.js.map +0 -1
  143. package/dist/domains/processes/process-supervisor.d.ts +0 -34
  144. package/dist/domains/processes/process-supervisor.d.ts.map +0 -1
  145. package/dist/domains/processes/process-supervisor.js +0 -211
  146. package/dist/domains/processes/process-supervisor.js.map +0 -1
  147. package/dist/domains/processes/process.repository.d.ts +0 -11
  148. package/dist/domains/processes/process.repository.d.ts.map +0 -1
  149. package/dist/domains/processes/process.repository.js +0 -31
  150. package/dist/domains/processes/process.repository.js.map +0 -1
  151. package/dist/domains/tasks/task-completion.service.d.ts +0 -31
  152. package/dist/domains/tasks/task-completion.service.d.ts.map +0 -1
  153. package/dist/domains/tasks/task-completion.service.js +0 -147
  154. package/dist/domains/tasks/task-completion.service.js.map +0 -1
  155. package/dist/domains/tasks/task-legacy-migration.d.ts +0 -15
  156. package/dist/domains/tasks/task-legacy-migration.d.ts.map +0 -1
  157. package/dist/domains/tasks/task-legacy-migration.js +0 -191
  158. package/dist/domains/tasks/task-legacy-migration.js.map +0 -1
  159. package/dist/events.d.ts +0 -2
  160. package/dist/events.d.ts.map +0 -1
  161. package/dist/events.js +0 -2
  162. package/dist/events.js.map +0 -1
  163. package/dist/git/git-service.d.ts +0 -51
  164. package/dist/git/git-service.d.ts.map +0 -1
  165. package/dist/git/git-service.js +0 -716
  166. package/dist/git/git-service.js.map +0 -1
  167. package/dist/git/git-status.d.ts +0 -24
  168. package/dist/git/git-status.d.ts.map +0 -1
  169. package/dist/git/git-status.js +0 -133
  170. package/dist/git/git-status.js.map +0 -1
  171. package/dist/harness-manager.d.ts +0 -21
  172. package/dist/harness-manager.d.ts.map +0 -1
  173. package/dist/harness-manager.js +0 -105
  174. package/dist/harness-manager.js.map +0 -1
  175. package/dist/index-store.d.ts +0 -2
  176. package/dist/index-store.d.ts.map +0 -1
  177. package/dist/index-store.js +0 -2
  178. package/dist/index-store.js.map +0 -1
  179. package/dist/plan-paths.d.ts +0 -6
  180. package/dist/plan-paths.d.ts.map +0 -1
  181. package/dist/plan-paths.js +0 -30
  182. package/dist/plan-paths.js.map +0 -1
  183. package/dist/plan-service.d.ts +0 -61
  184. package/dist/plan-service.d.ts.map +0 -1
  185. package/dist/plan-service.js +0 -255
  186. package/dist/plan-service.js.map +0 -1
  187. package/dist/policy.d.ts +0 -14
  188. package/dist/policy.d.ts.map +0 -1
  189. package/dist/policy.js +0 -247
  190. package/dist/policy.js.map +0 -1
  191. package/dist/process-manager.d.ts +0 -72
  192. package/dist/process-manager.d.ts.map +0 -1
  193. package/dist/process-manager.js +0 -376
  194. package/dist/process-manager.js.map +0 -1
  195. package/dist/registry/agent-lifecycle-service.d.ts +0 -38
  196. package/dist/registry/agent-lifecycle-service.d.ts.map +0 -1
  197. package/dist/registry/agent-lifecycle-service.js +0 -199
  198. package/dist/registry/agent-lifecycle-service.js.map +0 -1
  199. package/dist/registry/conversation-lifecycle-service.d.ts +0 -35
  200. package/dist/registry/conversation-lifecycle-service.d.ts.map +0 -1
  201. package/dist/registry/conversation-lifecycle-service.js +0 -136
  202. package/dist/registry/conversation-lifecycle-service.js.map +0 -1
  203. package/dist/registry/pinned-command-service.d.ts +0 -11
  204. package/dist/registry/pinned-command-service.d.ts.map +0 -1
  205. package/dist/registry/pinned-command-service.js +0 -40
  206. package/dist/registry/pinned-command-service.js.map +0 -1
  207. package/dist/registry/project-lifecycle-service.d.ts +0 -22
  208. package/dist/registry/project-lifecycle-service.d.ts.map +0 -1
  209. package/dist/registry/project-lifecycle-service.js +0 -87
  210. package/dist/registry/project-lifecycle-service.js.map +0 -1
  211. package/dist/repositories/agent-repository.d.ts +0 -12
  212. package/dist/repositories/agent-repository.d.ts.map +0 -1
  213. package/dist/repositories/agent-repository.js +0 -33
  214. package/dist/repositories/agent-repository.js.map +0 -1
  215. package/dist/repositories/conversation-repository.d.ts +0 -13
  216. package/dist/repositories/conversation-repository.d.ts.map +0 -1
  217. package/dist/repositories/conversation-repository.js +0 -39
  218. package/dist/repositories/conversation-repository.js.map +0 -1
  219. package/dist/repositories/entry-repository.d.ts +0 -15
  220. package/dist/repositories/entry-repository.d.ts.map +0 -1
  221. package/dist/repositories/entry-repository.js +0 -81
  222. package/dist/repositories/entry-repository.js.map +0 -1
  223. package/dist/repositories/index.d.ts +0 -7
  224. package/dist/repositories/index.d.ts.map +0 -1
  225. package/dist/repositories/index.js +0 -7
  226. package/dist/repositories/index.js.map +0 -1
  227. package/dist/repositories/pinned-command-repository.d.ts +0 -10
  228. package/dist/repositories/pinned-command-repository.d.ts.map +0 -1
  229. package/dist/repositories/pinned-command-repository.js +0 -28
  230. package/dist/repositories/pinned-command-repository.js.map +0 -1
  231. package/dist/repositories/project-repository.d.ts +0 -12
  232. package/dist/repositories/project-repository.d.ts.map +0 -1
  233. package/dist/repositories/project-repository.js +0 -33
  234. package/dist/repositories/project-repository.js.map +0 -1
  235. package/dist/repositories/prompt-queue-repository.d.ts +0 -28
  236. package/dist/repositories/prompt-queue-repository.d.ts.map +0 -1
  237. package/dist/repositories/prompt-queue-repository.js +0 -88
  238. package/dist/repositories/prompt-queue-repository.js.map +0 -1
  239. package/dist/routes/process-routes.d.ts +0 -4
  240. package/dist/routes/process-routes.d.ts.map +0 -1
  241. package/dist/routes/process-routes.js +0 -43
  242. package/dist/routes/process-routes.js.map +0 -1
  243. package/dist/storage.d.ts +0 -2
  244. package/dist/storage.d.ts.map +0 -1
  245. package/dist/storage.js +0 -2
  246. package/dist/storage.js.map +0 -1
  247. package/dist/tool-service.d.ts +0 -82
  248. package/dist/tool-service.d.ts.map +0 -1
  249. package/dist/tool-service.js +0 -409
  250. package/dist/tool-service.js.map +0 -1
  251. package/dist/transcription-service.d.ts +0 -15
  252. package/dist/transcription-service.d.ts.map +0 -1
  253. package/dist/transcription-service.js +0 -128
  254. package/dist/transcription-service.js.map +0 -1
  255. package/dist/usage/anthropic-client.d.ts +0 -9
  256. package/dist/usage/anthropic-client.d.ts.map +0 -1
  257. package/dist/usage/anthropic-client.js +0 -207
  258. package/dist/usage/anthropic-client.js.map +0 -1
  259. package/dist/usage/codex-client.d.ts +0 -18
  260. package/dist/usage/codex-client.d.ts.map +0 -1
  261. package/dist/usage/codex-client.js +0 -316
  262. package/dist/usage/codex-client.js.map +0 -1
  263. package/dist/usage/subscription-usage-service.d.ts +0 -42
  264. package/dist/usage/subscription-usage-service.d.ts.map +0 -1
  265. package/dist/usage/subscription-usage-service.js +0 -131
  266. package/dist/usage/subscription-usage-service.js.map +0 -1
  267. package/dist/web/assets/index-DP6SGqvJ.js +0 -165
  268. package/dist/worker-manager.d.ts +0 -51
  269. package/dist/worker-manager.d.ts.map +0 -1
  270. package/dist/worker-manager.js +0 -116
  271. package/dist/worker-manager.js.map +0 -1
@@ -1,802 +0,0 @@
1
- import { AgentHarness, AgentToolSuspension, buildConversationContext, Conversation, computeContextUsage, convertToLlm, estimateContextTokens, getModelContextWindow, isAgentToolSuspension, NodeExecutionEnv, resolveAgentModel, shouldCompact, } from "@nerve/agent";
2
- import { createId, toolNameSchema, } from "@nerve/shared";
3
- import { activeToolNamesForAgent, createAgentToolsForAgent, toolPromptMetadata, } from "../domains/tools/agent-tool-adapter.js";
4
- import { HttpError } from "../http/errors.js";
5
- import { planDirForStorageHome } from "../domains/plans/plan-paths.js";
6
- import { loadHarnessResources } from "../resource-loader.js";
7
- import { SubagentRunner } from "./subagent-runner.js";
8
- import { composeAgentSystemPrompt } from "./system-prompt-builder.js";
9
- import { shouldStreamToolDraftArguments } from "./tool-draft-streaming.js";
10
- export class AgentRunner {
11
- deps;
12
- subagents;
13
- constructor(deps) {
14
- this.deps = deps;
15
- this.subagents = new SubagentRunner({
16
- storage: deps.storage,
17
- events: deps.events,
18
- harnessManager: deps.harnessManager,
19
- createAgent: deps.createAgent,
20
- runAgentPrompt: (agent, request) => this.runAgentPrompt(agent, request),
21
- appendEntry: deps.appendEntry,
22
- getConversation: deps.getConversation,
23
- updateConversation: deps.updateConversation,
24
- });
25
- }
26
- async promptAgent(agentId, request) {
27
- const agent = this.deps.agents.get(agentId);
28
- if (!agent)
29
- throw new HttpError(404, "AGENT_NOT_FOUND", "Agent not found.");
30
- if (agent.status === "awaiting_user") {
31
- throw new HttpError(409, "AGENT_AWAITING_USER", "Agent is awaiting a human-in-the-loop tool response.");
32
- }
33
- const activeRun = this.deps.runs.get(agent.id);
34
- if (activeRun) {
35
- const behavior = request.behavior ?? "steer";
36
- if (behavior === "reject-if-busy") {
37
- throw new HttpError(409, "AGENT_BUSY", "Agent is already running.");
38
- }
39
- const callback = behavior === "follow-up" ? activeRun.followUp : activeRun.steer;
40
- if (!callback) {
41
- throw new HttpError(409, "AGENT_BUSY", "Agent is already running.");
42
- }
43
- const queuedPrompt = await this.deps.promptQueue.enqueue({
44
- agentId: agent.id,
45
- conversationId: agent.conversationId,
46
- projectId: agent.projectId,
47
- runId: activeRun.runId,
48
- behavior,
49
- text: request.text,
50
- images: request.images,
51
- });
52
- this.deps.conversationRuntime.queuePrompt(activeRun.runId, queuedPrompt);
53
- await this.deps.events.publish("conversation.prompt.queued", {
54
- conversationId: agent.conversationId,
55
- agentId: agent.id,
56
- projectId: agent.projectId,
57
- runId: activeRun.runId,
58
- queuedPrompt,
59
- });
60
- try {
61
- await callback(request.text, request, queuedPrompt.id);
62
- const accepted = await this.deps.promptQueue.markAccepted(queuedPrompt.id, agent.id, activeRun.runId);
63
- if (accepted)
64
- this.deps.conversationRuntime.queuePrompt(activeRun.runId, accepted);
65
- }
66
- catch (error) {
67
- await this.deps.promptQueue.markFailed(queuedPrompt.id, agent.id, error instanceof Error ? error.message : String(error));
68
- throw error;
69
- }
70
- return;
71
- }
72
- void this.runAgentPrompt(agent, request).catch(() => undefined);
73
- }
74
- async continueAgent(agentId) {
75
- const agent = this.deps.agents.get(agentId);
76
- if (!agent)
77
- throw new HttpError(404, "AGENT_NOT_FOUND", "Agent not found.");
78
- if (this.deps.runs.has(agent.id)) {
79
- throw new HttpError(409, "AGENT_BUSY", "Agent is already running.");
80
- }
81
- void this.runAgentPrompt(agent, { text: "Continue after resolved tool result." }, { continue: true }).catch(() => undefined);
82
- }
83
- async continueFromFailedTurn(agentId, failedEntryId) {
84
- const agent = this.deps.agents.get(agentId);
85
- if (!agent)
86
- throw new HttpError(404, "AGENT_NOT_FOUND", "Agent not found.");
87
- if (this.deps.runs.has(agent.id)) {
88
- throw new HttpError(409, "AGENT_BUSY", "Agent is already running.");
89
- }
90
- const conversation = this.deps.getConversation(agent.conversationId);
91
- const project = this.deps.getProject(agent.projectId);
92
- const storage = await this.deps.harnessManager.openStorage(conversation, project.dir);
93
- const failedEntry = await storage.getEntry(failedEntryId);
94
- const failedMessage = failedEntry?.type === "message" ? failedEntry.message : undefined;
95
- if (!failedEntry ||
96
- failedEntry.type !== "message" ||
97
- failedMessage?.role !== "assistant" ||
98
- failedMessage.stopReason !== "error" ||
99
- failedEntry.parentId === null) {
100
- throw new HttpError(400, "INVALID_FAILED_ENTRY", "Failed entry is not a retryable assistant failure.");
101
- }
102
- await new Conversation(storage).moveTo(failedEntry.parentId);
103
- void this.runAgentPrompt(agent, { text: "Continue from failed model request." }, { continue: true }).catch(() => undefined);
104
- }
105
- async abortAgent(agentId) {
106
- const agent = this.deps.agents.get(agentId);
107
- if (!agent)
108
- throw new HttpError(404, "AGENT_NOT_FOUND", "Agent not found.");
109
- for (const child of this.deps.agents.values()) {
110
- if (child.parentAgentId === agent.id)
111
- await this.abortAgent(child.id);
112
- }
113
- const run = this.deps.runs.get(agentId);
114
- if (!run)
115
- return;
116
- run.abort();
117
- await this.deps.events.publish("agent.abort_requested", {
118
- agentId,
119
- runId: run.runId,
120
- });
121
- }
122
- runSubagent(parent, args) {
123
- return this.subagents.runSubagent(parent, args);
124
- }
125
- async runAgentPrompt(agent, request, options = {}) {
126
- if (this.deps.runs.has(agent.id)) {
127
- throw new HttpError(409, "AGENT_BUSY", "Agent is already running.");
128
- }
129
- const runId = createId("run");
130
- const runStartedAt = performance.now();
131
- let abortRequested = false;
132
- let lastAssistantEntry;
133
- let currentTurnId;
134
- let currentLiveMessageId;
135
- const liveToolDraftNames = new Map();
136
- const pendingProviderToolCalls = new Map();
137
- try {
138
- await this.deps.logger.info("Agent run preparing", {
139
- agentId: agent.id,
140
- conversationId: agent.conversationId,
141
- projectId: agent.projectId,
142
- runId,
143
- context: { behavior: request.behavior, continue: options.continue },
144
- });
145
- const conversation = this.deps.getConversation(agent.conversationId);
146
- const project = this.deps.getProject(agent.projectId);
147
- const storage = await this.deps.harnessManager.openStorage(conversation, project.dir);
148
- const harnessConversation = new Conversation(storage);
149
- const initialHarnessEntryIds = new Set((await storage.getEntries()).map((entry) => entry.id));
150
- const activeToolNames = activeToolNamesForAgent(agent);
151
- const model = resolveAgentModel(agent.model);
152
- this.deps.subscriptionUsage.touchProvider(model.provider);
153
- const env = new NodeExecutionEnv({ cwd: agent.projectDir });
154
- const resources = await loadHarnessResources(agent.projectDir);
155
- const latestAgent = () => this.deps.agents.get(agent.id) ?? agent;
156
- const composeLatestSystemPrompt = () => {
157
- const currentAgent = latestAgent();
158
- const currentActiveToolNames = activeToolNamesForAgent(currentAgent);
159
- return composeAgentSystemPrompt(currentAgent, currentActiveToolNames, toolPromptMetadata(currentActiveToolNames), resources, { planDir: planDirForStorageHome(this.deps.storage.paths.home) });
160
- };
161
- const harness = new AgentHarness({
162
- env,
163
- conversation: harnessConversation,
164
- resources: { skills: resources.skills },
165
- tools: createAgentToolsForAgent(agent, this.deps.tools, {
166
- runId,
167
- resolveToolAnchor: (providerToolCallId) => this.deps.conversationRuntime.resolveToolAnchor(runId, providerToolCallId),
168
- }),
169
- activeToolNames,
170
- model,
171
- thinkingLevel: agent.thinkingLevel,
172
- getApiKeyAndHeaders: async (requestModel) => {
173
- if (requestModel.provider === "nerve-faux")
174
- return undefined;
175
- const apiKey = await this.deps.auth.getApiKey(requestModel.provider);
176
- return apiKey ? { apiKey } : undefined;
177
- },
178
- systemPrompt: composeLatestSystemPrompt,
179
- });
180
- harness.subscribe(async (event) => {
181
- if (event.type === "after_provider_response") {
182
- if (model.provider === "openai-codex") {
183
- this.deps.subscriptionUsage.applyCodexHeaders(event.headers);
184
- }
185
- return;
186
- }
187
- if (event.type === "turn_start") {
188
- const turn = this.deps.conversationRuntime.startTurn(runId);
189
- currentTurnId = turn.turnId;
190
- currentLiveMessageId = undefined;
191
- pendingProviderToolCalls.clear();
192
- return;
193
- }
194
- if (event.type === "tool_execution_start") {
195
- pendingProviderToolCalls.set(event.toolCallId, {
196
- toolName: event.toolName,
197
- args: recordFromUnknown(event.args),
198
- });
199
- return;
200
- }
201
- if (event.type === "tool_execution_end") {
202
- const started = pendingProviderToolCalls.get(event.toolCallId);
203
- pendingProviderToolCalls.delete(event.toolCallId);
204
- if (!event.isError)
205
- return;
206
- if (this.deps.tools.findToolCallByProviderToolCallId(event.toolCallId)) {
207
- return;
208
- }
209
- const parsedToolName = toolNameSchema.safeParse(event.toolName);
210
- if (!parsedToolName.success) {
211
- await this.deps.logger.warn("Unknown tool call failed before execution", {
212
- agentId: agent.id,
213
- conversationId: agent.conversationId,
214
- projectId: agent.projectId,
215
- runId,
216
- context: {
217
- toolName: event.toolName,
218
- providerToolCallId: event.toolCallId,
219
- },
220
- });
221
- return;
222
- }
223
- await this.deps.tools.recordProviderToolCallError(agent, parsedToolName.data, started?.args ?? {}, errorTextFromToolResult(event.result, event.toolName), {
224
- sourceToolCallId: event.toolCallId,
225
- providerToolCallId: event.toolCallId,
226
- runId,
227
- anchor: this.deps.conversationRuntime.resolveToolAnchor(runId, event.toolCallId),
228
- });
229
- return;
230
- }
231
- if (event.type === "message_start" &&
232
- event.message.role === "assistant") {
233
- if (!currentTurnId) {
234
- const turn = this.deps.conversationRuntime.startTurn(runId);
235
- currentTurnId = turn.turnId;
236
- }
237
- const started = this.deps.conversationRuntime.startAssistantMessage(runId, currentTurnId);
238
- currentLiveMessageId = started.liveMessageId;
239
- liveToolDraftNames.clear();
240
- await this.deps.events.publish("conversation.live.message.started", started, { durability: "transient" });
241
- return;
242
- }
243
- if (event.type === "message_update") {
244
- if (!currentTurnId || !currentLiveMessageId)
245
- return;
246
- const update = event.assistantMessageEvent;
247
- if (update.type === "text_delta") {
248
- const data = this.deps.conversationRuntime.applyContentDelta({
249
- runId,
250
- turnId: currentTurnId,
251
- liveMessageId: currentLiveMessageId,
252
- contentIndex: update.contentIndex,
253
- kind: "text",
254
- delta: update.delta,
255
- });
256
- await this.deps.events.publish("conversation.live.content.delta", data, { durability: "transient" });
257
- }
258
- else if (update.type === "thinking_delta") {
259
- const data = this.deps.conversationRuntime.applyContentDelta({
260
- runId,
261
- turnId: currentTurnId,
262
- liveMessageId: currentLiveMessageId,
263
- contentIndex: update.contentIndex,
264
- kind: "thinking",
265
- delta: update.delta,
266
- });
267
- await this.deps.events.publish("conversation.live.content.delta", data, { durability: "transient" });
268
- }
269
- else if (update.type === "text_end") {
270
- const data = this.deps.conversationRuntime.finishContent({
271
- runId,
272
- turnId: currentTurnId,
273
- liveMessageId: currentLiveMessageId,
274
- contentIndex: update.contentIndex,
275
- kind: "text",
276
- finalText: update.content,
277
- });
278
- await this.deps.events.publish("conversation.live.content.done", data, {
279
- durability: "transient",
280
- });
281
- }
282
- else if (update.type === "thinking_end") {
283
- const data = this.deps.conversationRuntime.finishContent({
284
- runId,
285
- turnId: currentTurnId,
286
- liveMessageId: currentLiveMessageId,
287
- contentIndex: update.contentIndex,
288
- kind: "thinking",
289
- finalText: update.content,
290
- redacted: assistantContentRedacted(update.partial, update.contentIndex),
291
- });
292
- await this.deps.events.publish("conversation.live.content.done", data, {
293
- durability: "transient",
294
- });
295
- }
296
- else if (update.type === "toolcall_start") {
297
- const draft = assistantToolCallDraft(update.partial, update.contentIndex);
298
- liveToolDraftNames.set(update.contentIndex, draft?.name);
299
- const data = this.deps.conversationRuntime.startToolDraft({
300
- runId,
301
- turnId: currentTurnId,
302
- liveMessageId: currentLiveMessageId,
303
- contentIndex: update.contentIndex,
304
- providerToolCallId: draft?.id,
305
- toolName: draft?.name,
306
- });
307
- await this.deps.events.publish("conversation.live.tool_draft.started", data, { durability: "transient" });
308
- }
309
- else if (update.type === "toolcall_delta") {
310
- const draft = assistantToolCallDraft(update.partial, update.contentIndex);
311
- const toolName = draft?.name ?? liveToolDraftNames.get(update.contentIndex);
312
- if (draft?.name)
313
- liveToolDraftNames.set(update.contentIndex, draft.name);
314
- if (!shouldStreamToolDraftArguments(toolName))
315
- return;
316
- const data = this.deps.conversationRuntime.applyToolDraftDelta({
317
- runId,
318
- turnId: currentTurnId,
319
- liveMessageId: currentLiveMessageId,
320
- contentIndex: update.contentIndex,
321
- delta: update.delta,
322
- });
323
- await this.deps.events.publish("conversation.live.tool_draft.delta", data, { durability: "transient" });
324
- }
325
- else if (update.type === "toolcall_end") {
326
- liveToolDraftNames.delete(update.contentIndex);
327
- const data = this.deps.conversationRuntime.finishToolDraft({
328
- runId,
329
- turnId: currentTurnId,
330
- liveMessageId: currentLiveMessageId,
331
- contentIndex: update.contentIndex,
332
- providerToolCallId: update.toolCall.id,
333
- toolName: update.toolCall.name,
334
- args: update.toolCall.arguments,
335
- });
336
- await this.deps.events.publish("conversation.live.tool_draft.done", data, { durability: "transient" });
337
- }
338
- return;
339
- }
340
- if (event.type === "message_end") {
341
- const liveMessageId = event.message.role === "assistant"
342
- ? currentLiveMessageId
343
- : undefined;
344
- const mirrored = await this.deps.messageMirror.mirrorNewHarnessEntries(agent, storage, initialHarnessEntryIds, {
345
- runId,
346
- turnId: currentTurnId,
347
- liveMessageId,
348
- });
349
- let shouldPublishContextUsage = false;
350
- for (const entry of mirrored) {
351
- await this.deps.events.publish("conversation.entry.appended", {
352
- conversationId: agent.conversationId,
353
- agentId: agent.id,
354
- runId,
355
- turnId: entry.turnId ?? currentTurnId,
356
- liveMessageId: entry.liveMessageId,
357
- entry,
358
- });
359
- if (entry.role === "user") {
360
- await this.maybeMarkQueuedPromptDelivered(agent, runId, entry);
361
- await this.deps.messageMirror.maybeDeriveInitialConversationTitle(conversation.id, entry.text);
362
- }
363
- else if (entry.role === "assistant") {
364
- lastAssistantEntry = entry;
365
- if (entry.usage)
366
- shouldPublishContextUsage = true;
367
- }
368
- }
369
- if (shouldPublishContextUsage) {
370
- await this.publishContextUsage(agent.conversationId, agent.id, runId).catch((error) => {
371
- process.emitWarning(`Context-usage publish failed for ${agent.conversationId}: ${error instanceof Error ? error.message : String(error)}`);
372
- });
373
- }
374
- if (event.message.role === "assistant")
375
- currentLiveMessageId = undefined;
376
- return;
377
- }
378
- });
379
- const startedAt = new Date().toISOString();
380
- this.deps.conversationRuntime.startRun({
381
- agentId: agent.id,
382
- projectId: agent.projectId,
383
- conversationId: agent.conversationId,
384
- runId,
385
- startedAt,
386
- });
387
- await this.deps.events.publish("conversation.run.started", {
388
- agentId: agent.id,
389
- projectId: agent.projectId,
390
- conversationId: agent.conversationId,
391
- runId,
392
- parentEntryId: conversation.activeEntryId,
393
- startedAt,
394
- });
395
- await this.deps.logger.info("Agent run started", {
396
- agentId: agent.id,
397
- conversationId: agent.conversationId,
398
- projectId: agent.projectId,
399
- runId,
400
- context: {
401
- parentEntryId: conversation.activeEntryId,
402
- model: model.id,
403
- provider: model.provider,
404
- },
405
- });
406
- this.deps.runs.set(agent.id, {
407
- runId,
408
- abort: () => {
409
- abortRequested = true;
410
- this.deps.conversationRuntime.markAborting(runId);
411
- void harness.abort();
412
- },
413
- messages: this.deps.conversationService.getForAgent(agent.id) ?? [],
414
- steer: (text, options) => harness.steer(text, { images: options?.images }),
415
- followUp: (text, options) => harness.followUp(text, { images: options?.images }),
416
- updateAgentRuntimeConfig: async (updatedAgent) => {
417
- await harness.setActiveTools(activeToolNamesForAgent(updatedAgent));
418
- },
419
- });
420
- await this.deps.setAgentStatus(agent, "running");
421
- const runAssistant = await this.runHarnessWithRetries({
422
- harness,
423
- conversation: harnessConversation,
424
- request,
425
- continue: options.continue === true,
426
- runId,
427
- agent,
428
- });
429
- const latest = this.deps.agents.get(agent.id);
430
- this.deps.runs.delete(agent.id);
431
- const branch = await storage.getPathToRoot(await storage.getLeafId());
432
- const messages = convertToLlm(buildConversationContext(branch).messages);
433
- this.deps.conversationService.setForAgent(agent.id, messages);
434
- const assistantEntry = lastAssistantEntry;
435
- if (!assistantEntry) {
436
- throw new Error("Agent run completed without an assistant entry.");
437
- }
438
- if (runAssistant.stopReason === "error" ||
439
- runAssistant.stopReason === "aborted") {
440
- const aborted = runAssistant.stopReason === "aborted" || abortRequested;
441
- if (latest)
442
- await this.deps.setAgentStatus(latest, aborted ? "aborted" : "error");
443
- if (!aborted) {
444
- await this.maybeAppendRetryExhaustedStatus(agent, runId, assistantEntry, runAssistant);
445
- }
446
- await this.deps.events.publish("conversation.run.failed", {
447
- agentId: agent.id,
448
- projectId: agent.projectId,
449
- runId,
450
- conversationId: agent.conversationId,
451
- message: runAssistant.errorMessage ?? "Agent run failed.",
452
- aborted,
453
- failedAt: new Date().toISOString(),
454
- });
455
- await this.deps.logger.warn("Agent run failed", {
456
- agentId: agent.id,
457
- conversationId: agent.conversationId,
458
- projectId: agent.projectId,
459
- runId,
460
- durationMs: Math.round(performance.now() - runStartedAt),
461
- context: {
462
- finalEntryId: assistantEntry.id,
463
- stopReason: runAssistant.stopReason,
464
- errorMessage: runAssistant.errorMessage,
465
- },
466
- });
467
- this.deps.conversationRuntime.failRun(runId);
468
- return assistantEntry;
469
- }
470
- if (latest)
471
- await this.deps.setAgentStatus(latest, "idle");
472
- const completedAt = new Date().toISOString();
473
- await this.deps.events.publish("conversation.run.completed", {
474
- agentId: agent.id,
475
- projectId: agent.projectId,
476
- runId,
477
- conversationId: agent.conversationId,
478
- finalEntryId: assistantEntry.id,
479
- completedAt,
480
- });
481
- await this.deps.logger.info("Agent run completed", {
482
- agentId: agent.id,
483
- conversationId: agent.conversationId,
484
- projectId: agent.projectId,
485
- runId,
486
- durationMs: Math.round(performance.now() - runStartedAt),
487
- context: { finalEntryId: assistantEntry.id },
488
- });
489
- this.deps.conversationRuntime.completeRun(runId);
490
- await this.maybeAutoCompact(agent.conversationId).catch((error) => {
491
- process.emitWarning(`Auto-compaction failed for ${agent.conversationId}: ${error instanceof Error ? error.message : String(error)}`);
492
- });
493
- await this.publishContextUsage(agent.conversationId, agent.id, runId).catch((error) => {
494
- process.emitWarning(`Context-usage publish failed for ${agent.conversationId}: ${error instanceof Error ? error.message : String(error)}`);
495
- });
496
- return assistantEntry;
497
- }
498
- catch (error) {
499
- const suspensionError = isAgentToolSuspension(error)
500
- ? error
501
- : this.suspensionFromWaitingToolCall(agent, runId, error);
502
- if (suspensionError) {
503
- this.deps.runs.delete(agent.id);
504
- const latest = this.deps.agents.get(agent.id);
505
- const toolCall = this.deps.tools.getToolCall(suspensionError.data.toolCallId);
506
- const providerToolCallId = toolCall.providerToolCallId ??
507
- toolCall.sourceToolCallId ??
508
- suspensionError.data.toolCall?.id ??
509
- suspensionError.data.toolCallId;
510
- const suspension = await this.deps.suspensions.createSuspension({
511
- agentId: agent.id,
512
- conversationId: agent.conversationId,
513
- projectId: agent.projectId,
514
- runId,
515
- turnId: currentTurnId,
516
- liveMessageId: currentLiveMessageId,
517
- assistantEntryId: lastAssistantEntry?.id,
518
- toolCallId: toolCall.id,
519
- providerToolCallId,
520
- toolName: toolCall.toolName,
521
- remainingToolCalls: (suspensionError.data.remainingToolCalls ?? []).map((remaining) => ({
522
- id: remaining.id,
523
- name: remaining.name,
524
- arguments: remaining.arguments,
525
- })),
526
- reason: suspensionError.data.reason,
527
- });
528
- if (latest)
529
- await this.deps.setAgentStatus(latest, "awaiting_user");
530
- const suspendedAt = new Date().toISOString();
531
- await this.deps.events.publish("conversation.run.suspended", {
532
- agentId: agent.id,
533
- projectId: agent.projectId,
534
- runId,
535
- conversationId: agent.conversationId,
536
- suspensionId: suspension.id,
537
- toolCallId: toolCall.id,
538
- suspendedAt,
539
- reason: suspensionError.data.reason,
540
- });
541
- await this.deps.logger.info("Agent run suspended", {
542
- agentId: agent.id,
543
- conversationId: agent.conversationId,
544
- projectId: agent.projectId,
545
- runId,
546
- toolCallId: toolCall.id,
547
- durationMs: Math.round(performance.now() - runStartedAt),
548
- context: {
549
- suspensionId: suspension.id,
550
- reason: suspensionError.data.reason,
551
- },
552
- });
553
- this.deps.conversationRuntime.completeRun(runId);
554
- if (lastAssistantEntry)
555
- return lastAssistantEntry;
556
- throw new Error("Agent run suspended without an assistant entry.");
557
- }
558
- this.deps.runs.delete(agent.id);
559
- const aborted = abortRequested;
560
- const latest = this.deps.agents.get(agent.id);
561
- if (latest)
562
- await this.deps.setAgentStatus(latest, aborted ? "aborted" : "error");
563
- await this.deps.events.publish("conversation.run.failed", {
564
- agentId: agent.id,
565
- projectId: agent.projectId,
566
- runId,
567
- conversationId: agent.conversationId,
568
- message: error instanceof Error ? error.message : String(error),
569
- aborted,
570
- failedAt: new Date().toISOString(),
571
- });
572
- await this.deps.logger[aborted ? "warn" : "error"](aborted ? "Agent run aborted" : "Agent run failed", {
573
- agentId: agent.id,
574
- conversationId: agent.conversationId,
575
- projectId: agent.projectId,
576
- runId,
577
- durationMs: Math.round(performance.now() - runStartedAt),
578
- context: { aborted },
579
- error,
580
- });
581
- this.deps.conversationRuntime.failRun(runId);
582
- throw error;
583
- }
584
- }
585
- async maybeAppendRetryExhaustedStatus(agent, runId, assistantEntry, assistant) {
586
- const settings = this.deps.storage.settings.retry;
587
- if (!settings.enabled ||
588
- settings.maxRetries <= 0 ||
589
- !isRetryableAssistantError(assistant)) {
590
- return;
591
- }
592
- const details = {
593
- type: "agent_run_retry_status",
594
- state: "retry_exhausted",
595
- runId,
596
- failedEntryId: assistantEntry.id,
597
- attempt: settings.maxRetries,
598
- maxRetries: settings.maxRetries,
599
- errorMessage: assistant.errorMessage,
600
- retryable: true,
601
- };
602
- const statusEntry = await this.deps.appendEntry({
603
- conversationId: agent.conversationId,
604
- agentId: agent.id,
605
- runId,
606
- parentEntryId: assistantEntry.id,
607
- role: "system",
608
- kind: "run_status",
609
- text: `Model request failed after ${settings.maxRetries} ${settings.maxRetries === 1 ? "retry" : "retries"}.`,
610
- details,
611
- }, { mirrorToHarness: false });
612
- await this.deps.events.publish("conversation.entry.appended", {
613
- conversationId: agent.conversationId,
614
- agentId: agent.id,
615
- projectId: agent.projectId,
616
- runId,
617
- entry: statusEntry,
618
- });
619
- }
620
- async runHarnessWithRetries(input) {
621
- const settings = this.deps.storage.settings.retry;
622
- let attempt = 0;
623
- let continueRun = input.continue;
624
- while (true) {
625
- const assistant = continueRun
626
- ? await input.harness.continue()
627
- : await input.harness.prompt(input.request.text, {
628
- images: input.request.images,
629
- });
630
- if (assistant.stopReason !== "error" ||
631
- !isRetryableAssistantError(assistant) ||
632
- !settings.enabled ||
633
- attempt >= settings.maxRetries) {
634
- return assistant;
635
- }
636
- attempt += 1;
637
- const delayMs = settings.baseDelayMs * 2 ** (attempt - 1);
638
- const retryAt = new Date(Date.now() + delayMs).toISOString();
639
- const leafId = await input.conversation.getLeafId();
640
- const leaf = leafId
641
- ? await input.conversation.getEntry(leafId)
642
- : undefined;
643
- const failedEntryId = leaf?.type === "message" ? leaf.id : undefined;
644
- const retry = {
645
- attempt,
646
- maxRetries: settings.maxRetries,
647
- delayMs,
648
- retryAt,
649
- errorMessage: assistant.errorMessage,
650
- failedEntryId,
651
- };
652
- this.deps.conversationRuntime.markRetrying(input.runId, retry);
653
- await this.deps.events.publish("conversation.run.retrying", {
654
- agentId: input.agent.id,
655
- conversationId: input.agent.conversationId,
656
- projectId: input.agent.projectId,
657
- runId: input.runId,
658
- ...retry,
659
- });
660
- await this.deps.logger.warn("Retrying transient agent error", {
661
- agentId: input.agent.id,
662
- conversationId: input.agent.conversationId,
663
- projectId: input.agent.projectId,
664
- runId: input.runId,
665
- context: {
666
- attempt,
667
- maxRetries: settings.maxRetries,
668
- errorMessage: assistant.errorMessage,
669
- },
670
- });
671
- if (leaf?.parentId !== undefined)
672
- await input.conversation.moveTo(leaf.parentId);
673
- await delay(delayMs);
674
- this.deps.conversationRuntime.clearRetry(input.runId);
675
- continueRun = true;
676
- }
677
- }
678
- async maybeMarkQueuedPromptDelivered(agent, runId, entry) {
679
- const queuedPrompt = (await this.deps.promptQueue.pendingForAgent(agent.id))
680
- .filter((candidate) => candidate.runId === runId &&
681
- (candidate.status === "accepted" || candidate.status === "queued") &&
682
- candidate.text === entry.text)
683
- .at(0);
684
- if (!queuedPrompt)
685
- return;
686
- const delivered = await this.deps.promptQueue.markDelivered(queuedPrompt.id, agent.id, entry.id);
687
- if (!delivered)
688
- return;
689
- this.deps.conversationRuntime.removeQueuedPrompt(runId, delivered.id);
690
- await this.deps.events.publish("conversation.prompt.dequeued", {
691
- conversationId: agent.conversationId,
692
- agentId: agent.id,
693
- projectId: agent.projectId,
694
- runId,
695
- queuedPrompt: delivered,
696
- entryId: entry.id,
697
- });
698
- }
699
- suspensionFromWaitingToolCall(agent, runId, error) {
700
- const message = error instanceof Error ? error.message : String(error);
701
- const toolCall = this.deps.tools
702
- .listToolCalls()
703
- .find((candidate) => candidate.agentId === agent.id &&
704
- candidate.runId === runId &&
705
- candidate.status === "waiting_for_user" &&
706
- (candidate.toolName === "ask_user" ||
707
- candidate.toolName === "plan_mode_present"));
708
- if (!toolCall)
709
- return undefined;
710
- return new AgentToolSuspension({
711
- toolCallId: toolCall.id,
712
- toolName: toolCall.toolName,
713
- reason: message || `Tool ${toolCall.toolName} is awaiting user input.`,
714
- remainingToolCalls: [],
715
- });
716
- }
717
- /** Compute compaction-aware context-window usage for a conversation. */
718
- async getContextUsage(conversationId) {
719
- const conversation = this.deps.getConversation(conversationId);
720
- const project = this.deps.getProject(conversation.projectId);
721
- const storage = await this.deps.harnessManager.openStorage(conversation, project.dir);
722
- const branch = await storage.getPathToRoot(await storage.getLeafId());
723
- const messages = buildConversationContext(branch).messages;
724
- const agent = conversation.activeAgentId
725
- ? this.deps.agents.get(conversation.activeAgentId)
726
- : undefined;
727
- const contextWindow = getModelContextWindow(agent?.model);
728
- return computeContextUsage(messages, branch, contextWindow);
729
- }
730
- async publishContextUsage(conversationId, agentId, runId) {
731
- const contextUsage = await this.getContextUsage(conversationId);
732
- await this.deps.events.publish("conversation.context.updated", { conversationId, agentId, runId, contextUsage }, { durability: "transient" });
733
- }
734
- async maybeAutoCompact(conversationId) {
735
- if (!this.deps.storage.settings.compaction.auto)
736
- return;
737
- const conversation = this.deps.getConversation(conversationId);
738
- const project = this.deps.getProject(conversation.projectId);
739
- const storage = await this.deps.harnessManager.openStorage(conversation, project.dir);
740
- const branch = await storage.getPathToRoot(await storage.getLeafId());
741
- const tokens = estimateContextTokens(buildConversationContext(branch).messages).tokens;
742
- const agent = conversation.activeAgentId
743
- ? this.deps.agents.get(conversation.activeAgentId)
744
- : undefined;
745
- const contextWindow = getModelContextWindow(agent?.model);
746
- if (contextWindow <= 0)
747
- return;
748
- const settings = {
749
- enabled: this.deps.storage.settings.compaction.auto,
750
- reserveTokens: this.deps.storage.settings.compaction.reserveTokens,
751
- keepRecentTokens: this.deps.storage.settings.compaction.keepRecentTokens,
752
- };
753
- if (!shouldCompact(tokens, contextWindow, settings))
754
- return;
755
- await this.deps.compactionService.compactConversation(conversationId, {
756
- instructions: "Automatic compaction after the selected model's context threshold was exceeded.",
757
- keepRecentTokens: settings.keepRecentTokens,
758
- });
759
- }
760
- }
761
- function recordFromUnknown(value) {
762
- return value && typeof value === "object"
763
- ? value
764
- : {};
765
- }
766
- function errorTextFromToolResult(result, toolName) {
767
- const record = recordFromUnknown(result);
768
- const content = Array.isArray(record.content) ? record.content : [];
769
- const text = content
770
- .map((part) => {
771
- const partRecord = recordFromUnknown(part);
772
- return partRecord.type === "text" && typeof partRecord.text === "string"
773
- ? partRecord.text
774
- : "";
775
- })
776
- .filter(Boolean)
777
- .join("\n");
778
- return text.trim() || `Tool ${toolName} failed before execution.`;
779
- }
780
- function isRetryableAssistantError(message) {
781
- if (message.stopReason !== "error" || !message.errorMessage)
782
- return false;
783
- const error = message.errorMessage;
784
- if (/GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing|context.?length|context.?window|maximum context|too many tokens/i.test(error)) {
785
- return false;
786
- }
787
- return /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i.test(error);
788
- }
789
- function delay(ms) {
790
- return new Promise((resolve) => setTimeout(resolve, ms));
791
- }
792
- function assistantContentRedacted(message, contentIndex) {
793
- const block = message.content[contentIndex];
794
- return block?.type === "thinking" ? block.redacted : undefined;
795
- }
796
- function assistantToolCallDraft(message, contentIndex) {
797
- const block = message.content[contentIndex];
798
- return block?.type === "toolCall"
799
- ? { id: block.id, name: block.name }
800
- : undefined;
801
- }
802
- //# sourceMappingURL=agent-runner.js.map