@aria-cli/cli 1.0.49 → 1.0.51

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 (319) hide show
  1. package/bin/aria.mjs +2 -2
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/attached-local-control-client.js +826 -0
  4. package/dist/bootstrap-local-control-client.js +2 -0
  5. package/dist/capability-aware-method-proxy.js +42 -0
  6. package/dist/cli-context.js +160 -0
  7. package/dist/commands/arions.js +174 -0
  8. package/dist/commands/auth.js +123 -0
  9. package/dist/commands/daemon.js +245 -0
  10. package/dist/commands/definitions.js +176 -0
  11. package/dist/commands/index.js +74 -0
  12. package/dist/commands/login-handler.js +1108 -0
  13. package/dist/commands/logout-handler.js +92 -0
  14. package/dist/commands/memory-handlers.js +89 -0
  15. package/dist/commands/pairing.js +60 -0
  16. package/dist/commands/runtime-cutover-reset-command.js +12 -0
  17. package/dist/commands/runtime-cutover-reset.js +265 -0
  18. package/dist/commands/terminal-setup.js +84 -0
  19. package/dist/config/aria-config.js +238 -0
  20. package/dist/config/index.js +3 -0
  21. package/dist/config/loader.js +97 -0
  22. package/dist/config.js +142 -0
  23. package/dist/daemon-info.js +10 -0
  24. package/dist/ensure-daemon.js +128 -0
  25. package/dist/entrypoints/command-mode.js +5 -0
  26. package/dist/entrypoints/daemon.js +50 -0
  27. package/dist/entrypoints/headless-stdio.js +25 -0
  28. package/dist/entrypoints/interactive.js +80 -0
  29. package/dist/event-loop-watchdog.js +73 -0
  30. package/dist/headless/auth-orchestrator.js +508 -0
  31. package/dist/headless/auth-service.js +43 -0
  32. package/dist/headless/bootstrap-fast-path.js +112 -0
  33. package/dist/headless/call-command.js +143 -0
  34. package/dist/headless/daemon-service.js +318 -0
  35. package/dist/headless/hook-actions.js +235 -0
  36. package/dist/headless/hook-service.js +42 -0
  37. package/dist/headless/kernel-services.js +216 -0
  38. package/dist/headless/kernel.js +785 -0
  39. package/dist/headless/operations/arion.js +119 -0
  40. package/dist/headless/operations/auth.js +45 -0
  41. package/dist/headless/operations/client.js +31 -0
  42. package/dist/headless/operations/config.js +69 -0
  43. package/dist/headless/operations/daemon.js +47 -0
  44. package/dist/headless/operations/hook.js +56 -0
  45. package/dist/headless/operations/index.js +11 -0
  46. package/dist/headless/operations/memory.js +102 -0
  47. package/dist/headless/operations/message.js +279 -0
  48. package/dist/headless/operations/model.js +100 -0
  49. package/dist/headless/operations/peer.js +56 -0
  50. package/dist/headless/operations/run.js +24 -0
  51. package/dist/headless/operations/session.js +90 -0
  52. package/dist/headless/operations/system.js +19 -0
  53. package/dist/headless/operations/utils.js +35 -0
  54. package/dist/headless/run-orchestrator.js +703 -0
  55. package/dist/headless/stdio-server.js +439 -0
  56. package/dist/history/SessionHistory.js +8 -0
  57. package/dist/history/SessionHistoryClient.js +186 -0
  58. package/dist/history/conversation-message.js +112 -0
  59. package/dist/history/index.js +8 -0
  60. package/dist/history/jsonl-replay.js +154 -0
  61. package/dist/history/repair-tool-pairing.js +84 -0
  62. package/dist/history/stall-phase-bridge.js +11 -0
  63. package/dist/history/turn-accumulator.js +427 -0
  64. package/dist/index.js +7 -0
  65. package/dist/ink-repl.js +4183 -0
  66. package/dist/local-control-bootstrap.js +26 -0
  67. package/dist/local-control-client.js +2 -0
  68. package/dist/local-control-error-reporting.js +34 -0
  69. package/dist/local-control-http-client.js +362 -0
  70. package/dist/local-control-lazy-wrapper.js +363 -0
  71. package/dist/local-control-manager.js +146 -0
  72. package/dist/main.js +38 -0
  73. package/dist/network-security.js +62 -0
  74. package/dist/networking-server.js +38 -0
  75. package/dist/peer-identity.js +23 -0
  76. package/dist/polling-subscription.js +34 -0
  77. package/dist/relaunch.js +588 -0
  78. package/dist/release-notes.js +35 -0
  79. package/dist/repl-cleanup.js +47 -0
  80. package/dist/runtime/configure-bun-sqlite.js +3 -0
  81. package/dist/runtime/crash-handlers.js +111 -0
  82. package/dist/runtime/interactive-invocation.js +39 -0
  83. package/dist/runtime/internal-mode.js +14 -0
  84. package/dist/runtime/launch-spec.js +64 -0
  85. package/dist/runtime/owner-lease.js +44 -0
  86. package/dist/runtime/public-mode.js +20 -0
  87. package/dist/runtime/run-internal-mode.js +18 -0
  88. package/dist/runtime/runtime-kind.js +32 -0
  89. package/dist/runtime/spawn-aria.js +38 -0
  90. package/dist/selectable-client.js +2 -0
  91. package/dist/selectable-peer.js +2 -0
  92. package/dist/session.js +203 -0
  93. package/dist/slash-commands.js +80 -0
  94. package/dist/sounds.js +210 -0
  95. package/dist/ui/App.js +526 -0
  96. package/dist/ui/components/AnthropicMethodPicker.js +6 -0
  97. package/dist/ui/components/ArionPrompt.js +15 -0
  98. package/dist/ui/components/AutocompleteDropdown.js +23 -0
  99. package/dist/ui/components/AutonomySelector.js +55 -0
  100. package/dist/ui/components/Banner.js +98 -0
  101. package/dist/ui/components/ConversationHistory.js +175 -0
  102. package/dist/ui/components/CopilotDeviceLoginFlow.js +88 -0
  103. package/dist/ui/components/CopilotSourcePicker.js +50 -0
  104. package/dist/ui/components/Cost.js +10 -0
  105. package/dist/ui/components/CustomSelect/option-map.js +30 -0
  106. package/dist/ui/components/CustomSelect/select-option.js +13 -0
  107. package/dist/ui/components/CustomSelect/select.js +42 -0
  108. package/dist/ui/components/CustomSelect/use-select-state.js +179 -0
  109. package/dist/ui/components/CustomSelect/use-select.js +15 -0
  110. package/dist/ui/components/ErrorDisplay.js +35 -0
  111. package/dist/ui/components/FallbackToolUseRejectedMessage.js +7 -0
  112. package/dist/ui/components/FileEditToolUpdatedMessage.js +57 -0
  113. package/dist/ui/components/HandoffMarker.js +18 -0
  114. package/dist/ui/components/HighlightedCode.js +21 -0
  115. package/dist/ui/components/InputArea.js +187 -0
  116. package/dist/ui/components/Message.js +25 -0
  117. package/dist/ui/components/OAuthLoginFlow.js +113 -0
  118. package/dist/ui/components/OutputTruncation.js +35 -0
  119. package/dist/ui/components/PermissionPrompt.js +79 -0
  120. package/dist/ui/components/PipelineTimingPanel.js +15 -0
  121. package/dist/ui/components/ProviderMethodPicker.js +61 -0
  122. package/dist/ui/components/ProviderPicker.js +63 -0
  123. package/dist/ui/components/RenderItemView.js +71 -0
  124. package/dist/ui/components/Spinner.js +46 -0
  125. package/dist/ui/components/StatusBar.js +95 -0
  126. package/dist/ui/components/StreamingIndicator.js +55 -0
  127. package/dist/ui/components/StructuredDiff.js +168 -0
  128. package/dist/ui/components/TextInputOverlay.js +43 -0
  129. package/dist/ui/components/ThinkingBlock.js +82 -0
  130. package/dist/ui/components/ToolCost.js +17 -0
  131. package/dist/ui/components/ToolExecution.js +61 -0
  132. package/dist/ui/components/ToolHeader.js +51 -0
  133. package/dist/ui/components/ToolRenderLayoutContext.js +14 -0
  134. package/dist/ui/components/ToolResultWrapper.js +6 -0
  135. package/dist/ui/components/ToolUseLoader.js +35 -0
  136. package/dist/ui/components/TraceWaterfall.js +91 -0
  137. package/dist/ui/components/index.js +33 -0
  138. package/dist/ui/components/messages/AssistantTextMessage.js +25 -0
  139. package/dist/ui/components/messages/UserImageMessage.js +12 -0
  140. package/dist/ui/components/messages/UserTextMessage.js +12 -0
  141. package/dist/ui/components/overlays/ArionSelector.js +68 -0
  142. package/dist/ui/components/overlays/ClientSelector.js +62 -0
  143. package/dist/ui/components/overlays/CommandPalette.js +67 -0
  144. package/dist/ui/components/overlays/DaemonControl.js +87 -0
  145. package/dist/ui/components/overlays/InviteShareOverlay.js +15 -0
  146. package/dist/ui/components/overlays/JoinInviteOverlay.js +32 -0
  147. package/dist/ui/components/overlays/MemoryBrowser.js +100 -0
  148. package/dist/ui/components/overlays/MessageSelector.js +123 -0
  149. package/dist/ui/components/overlays/ModelSelector.js +211 -0
  150. package/dist/ui/components/overlays/PairRequestOverlay.js +42 -0
  151. package/dist/ui/components/overlays/PeerSelector.js +84 -0
  152. package/dist/ui/components/overlays/SessionSelector.js +102 -0
  153. package/dist/ui/components/overlays/SoundSelector.js +86 -0
  154. package/dist/ui/components/overlays/ThemeSelector.js +139 -0
  155. package/dist/ui/components/overlays/index.js +15 -0
  156. package/dist/ui/components/permissions/BashPermissionRequest/BashPermissionRequest.js +53 -0
  157. package/dist/ui/components/permissions/FallbackPermissionRequest.js +56 -0
  158. package/dist/ui/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js +76 -0
  159. package/dist/ui/components/permissions/FileEditPermissionRequest/FileEditToolDiff.js +18 -0
  160. package/dist/ui/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js +64 -0
  161. package/dist/ui/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js +26 -0
  162. package/dist/ui/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +141 -0
  163. package/dist/ui/components/permissions/PermissionRequest.js +70 -0
  164. package/dist/ui/components/permissions/PermissionRequestTitle.js +41 -0
  165. package/dist/ui/components/permissions/hooks.js +10 -0
  166. package/dist/ui/components/permissions/toolUseOptions.js +68 -0
  167. package/dist/ui/components/permissions/utils.js +10 -0
  168. package/dist/ui/components/text-input/Cursor.js +326 -0
  169. package/dist/ui/components/text-input/TextInput.js +231 -0
  170. package/dist/ui/components/text-input/imagePaste.js +28 -0
  171. package/dist/ui/components/text-input/index.js +6 -0
  172. package/dist/ui/components/text-input/useDoublePress.js +30 -0
  173. package/dist/ui/components/text-input/useTextInput.js +245 -0
  174. package/dist/ui/components/tool-types.js +9 -0
  175. package/dist/ui/constants/figures.js +4 -0
  176. package/dist/ui/constants/index.js +3 -0
  177. package/dist/ui/display-mode.js +93 -0
  178. package/dist/ui/display-policy.js +19 -0
  179. package/dist/ui/hooks/index.js +6 -0
  180. package/dist/ui/hooks/useCommandAutocomplete.js +93 -0
  181. package/dist/ui/hooks/useDoublePress.js +37 -0
  182. package/dist/ui/hooks/useIndicatorState.js +55 -0
  183. package/dist/ui/hooks/useInterval.js +23 -0
  184. package/dist/ui/hooks/useKeyboardShortcuts.js +127 -0
  185. package/dist/ui/hooks/useTerminalSize.js +55 -0
  186. package/dist/ui/hooks/useUnifiedMessages.js +117 -0
  187. package/dist/ui/indicator-state.js +44 -0
  188. package/dist/ui/markdown/highlight.js +44 -0
  189. package/dist/ui/markdown/index.js +1460 -0
  190. package/dist/ui/markdown/tokenizer.js +24 -0
  191. package/dist/ui/render-item.js +5 -0
  192. package/dist/ui/screens/REPL.js +119 -0
  193. package/dist/ui/screens/approval-lifecycle.js +38 -0
  194. package/dist/ui/status-line.js +72 -0
  195. package/dist/ui/theme/index.js +51 -0
  196. package/dist/ui/theme/themes/claude-dark-daltonized.js +51 -0
  197. package/dist/ui/theme/themes/claude-dark.js +50 -0
  198. package/dist/ui/theme/themes/claude-light-daltonized.js +51 -0
  199. package/dist/ui/theme/themes/claude-light.js +50 -0
  200. package/dist/ui/theme/themes/dark-accessible.js +18 -0
  201. package/dist/ui/theme/themes/dark.js +49 -0
  202. package/dist/ui/theme/themes/light-accessible.js +18 -0
  203. package/dist/ui/theme/themes/light.js +49 -0
  204. package/dist/ui/theme/types.js +3 -0
  205. package/dist/ui/theme.js +142 -0
  206. package/dist/ui/to-render-items.js +145 -0
  207. package/dist/ui/tools/AgentTool/index.js +30 -0
  208. package/dist/ui/tools/ArchitectTool/index.js +31 -0
  209. package/dist/ui/tools/AskUserTool/index.js +46 -0
  210. package/dist/ui/tools/BashTool/BashToolResultMessage.js +11 -0
  211. package/dist/ui/tools/BashTool/OutputLine.js +21 -0
  212. package/dist/ui/tools/BashTool/index.js +91 -0
  213. package/dist/ui/tools/BrowseTool/index.js +43 -0
  214. package/dist/ui/tools/BrowserTool/index.js +47 -0
  215. package/dist/ui/tools/CbmTool/index.js +188 -0
  216. package/dist/ui/tools/CheckDelegationTool/index.js +46 -0
  217. package/dist/ui/tools/CheckMessagesTool/index.js +85 -0
  218. package/dist/ui/tools/CreateQuipTool/index.js +30 -0
  219. package/dist/ui/tools/CreateSkillTool/index.js +22 -0
  220. package/dist/ui/tools/CreateToolTool/index.js +31 -0
  221. package/dist/ui/tools/DelegateRemoteTool/index.js +42 -0
  222. package/dist/ui/tools/DeployTool/index.js +47 -0
  223. package/dist/ui/tools/FffTool/index.js +103 -0
  224. package/dist/ui/tools/FileEditTool/index.js +67 -0
  225. package/dist/ui/tools/FileReadTool/index.js +68 -0
  226. package/dist/ui/tools/FileWriteTool/index.js +61 -0
  227. package/dist/ui/tools/ForkTool/index.js +47 -0
  228. package/dist/ui/tools/FrgTool/index.js +96 -0
  229. package/dist/ui/tools/GetThreadTool/index.js +39 -0
  230. package/dist/ui/tools/GlobTool/index.js +50 -0
  231. package/dist/ui/tools/GrepTool/index.js +84 -0
  232. package/dist/ui/tools/HatchArionTool/index.js +36 -0
  233. package/dist/ui/tools/LearnSkillTool/index.js +22 -0
  234. package/dist/ui/tools/LearnTool/index.js +43 -0
  235. package/dist/ui/tools/LearnToolTool/index.js +22 -0
  236. package/dist/ui/tools/ListClientsTool/index.js +39 -0
  237. package/dist/ui/tools/LspTool/index.js +261 -0
  238. package/dist/ui/tools/MCPTool/index.js +33 -0
  239. package/dist/ui/tools/ManageNetworkTool/index.js +53 -0
  240. package/dist/ui/tools/MemoryReadTool/index.js +64 -0
  241. package/dist/ui/tools/MemoryWriteTool/index.js +20 -0
  242. package/dist/ui/tools/NotebookEditTool/index.js +33 -0
  243. package/dist/ui/tools/NotebookReadTool/index.js +25 -0
  244. package/dist/ui/tools/OutlookReadTool/index.js +66 -0
  245. package/dist/ui/tools/OutlookReplyTool/index.js +49 -0
  246. package/dist/ui/tools/OutlookSendTool/index.js +49 -0
  247. package/dist/ui/tools/PauseDelegationTool/index.js +35 -0
  248. package/dist/ui/tools/ProbeTool/index.js +121 -0
  249. package/dist/ui/tools/ProcessTool/index.js +66 -0
  250. package/dist/ui/tools/QuestListTool/index.js +46 -0
  251. package/dist/ui/tools/QuestReportTool/index.js +49 -0
  252. package/dist/ui/tools/QuestUpdateTool/index.js +87 -0
  253. package/dist/ui/tools/QuipCommentTool/index.js +69 -0
  254. package/dist/ui/tools/QuipReadTool/index.js +71 -0
  255. package/dist/ui/tools/RestArionTool/index.js +32 -0
  256. package/dist/ui/tools/RestartTool/index.js +35 -0
  257. package/dist/ui/tools/ResumeDelegationTool/index.js +35 -0
  258. package/dist/ui/tools/RetireArionTool/index.js +32 -0
  259. package/dist/ui/tools/RgTool/index.js +73 -0
  260. package/dist/ui/tools/SearchKnowledgeTool/index.js +43 -0
  261. package/dist/ui/tools/SearchMessagesTool/index.js +43 -0
  262. package/dist/ui/tools/SelfDiagnoseTool/index.js +61 -0
  263. package/dist/ui/tools/SendMessageTool/index.js +45 -0
  264. package/dist/ui/tools/SerenaTool/index.js +124 -0
  265. package/dist/ui/tools/SessionHistoryTool/index.js +52 -0
  266. package/dist/ui/tools/SgTool/index.js +80 -0
  267. package/dist/ui/tools/SlackReactTool/index.js +41 -0
  268. package/dist/ui/tools/SlackReadTool/index.js +48 -0
  269. package/dist/ui/tools/SlackSendTool/index.js +45 -0
  270. package/dist/ui/tools/SpawnWorkerTool/index.js +33 -0
  271. package/dist/ui/tools/StickerRequestTool/index.js +19 -0
  272. package/dist/ui/tools/ThinkTool/index.js +17 -0
  273. package/dist/ui/tools/UgTool/index.js +108 -0
  274. package/dist/ui/tools/UseSkillTool/index.js +22 -0
  275. package/dist/ui/tools/WakeArionTool/index.js +32 -0
  276. package/dist/ui/tools/WebFetchTool/index.js +56 -0
  277. package/dist/ui/tools/WebSearchTool/index.js +44 -0
  278. package/dist/ui/tools/lsTool/index.js +58 -0
  279. package/dist/ui/tools/registry.js +197 -0
  280. package/dist/ui/tools/tool-renderer.js +11 -0
  281. package/dist/ui/tools/truncation.js +35 -0
  282. package/dist/ui/types/anthropic.js +4 -0
  283. package/dist/ui/types/index.js +2 -0
  284. package/dist/ui/types/message.js +3 -0
  285. package/dist/ui/types/tool.js +4 -0
  286. package/dist/ui/utils/array.js +4 -0
  287. package/dist/ui/utils/cursor.js +131 -0
  288. package/dist/ui/utils/diff.js +120 -0
  289. package/dist/ui/utils/format.js +42 -0
  290. package/dist/ui/utils/fuzzy.js +59 -0
  291. package/dist/ui/utils/index.js +11 -0
  292. package/dist/ui/utils/keys.js +8 -0
  293. package/dist/ui/utils/patch.js +17 -0
  294. package/dist/ui/utils/risk.js +114 -0
  295. package/dist/ui/utils/terminal-image.js +70 -0
  296. package/dist/ui/utils/validation.js +48 -0
  297. package/dist/ui/verb-pairs.js +248 -0
  298. package/dist/ui.js +131 -0
  299. package/package.json +73 -14
  300. package/src/entrypoints/command-mode.ts +5 -0
  301. package/src/entrypoints/daemon.ts +54 -0
  302. package/src/entrypoints/headless-stdio.ts +27 -0
  303. package/src/entrypoints/interactive.ts +112 -0
  304. package/src/main.ts +44 -0
  305. package/src/runtime/configure-bun-sqlite.ts +3 -0
  306. package/src/runtime/crash-handlers.ts +128 -0
  307. package/src/runtime/interactive-invocation.test.ts +42 -0
  308. package/src/runtime/interactive-invocation.ts +51 -0
  309. package/src/runtime/internal-mode.test.ts +19 -0
  310. package/src/runtime/internal-mode.ts +24 -0
  311. package/src/runtime/launch-spec.test.ts +26 -0
  312. package/src/runtime/launch-spec.ts +84 -0
  313. package/src/runtime/owner-lease.ts +52 -0
  314. package/src/runtime/public-mode.test.ts +18 -0
  315. package/src/runtime/public-mode.ts +19 -0
  316. package/src/runtime/run-internal-mode.ts +19 -0
  317. package/src/runtime/runtime-kind.test.ts +23 -0
  318. package/src/runtime/runtime-kind.ts +41 -0
  319. package/src/runtime/spawn-aria.ts +62 -0
@@ -0,0 +1,703 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { isDeepStrictEqual } from "node:util";
3
+ import { setStallPhase, clearStallPhase } from "../event-loop-watchdog.js";
4
+ import { resolveTrustedRuntimeErrorMessage } from "@aria-cli/tools";
5
+ import { fromModelMessages } from "../history/conversation-message.js";
6
+ const SESSION_LEASE_MS = 30_000;
7
+ const SESSION_LEASE_RENEW_INTERVAL_MS = 10_000;
8
+ function initialRunSynthesisState() {
9
+ return {
10
+ output: "",
11
+ messages: [],
12
+ toolCalls: [],
13
+ usage: undefined,
14
+ turnCount: 0,
15
+ thinking: [],
16
+ nativeToolResults: [],
17
+ pipelineTiming: undefined,
18
+ guardrailEvents: [],
19
+ handoffs: [],
20
+ pausedState: null,
21
+ };
22
+ }
23
+ function synthesizeRunResult(state) {
24
+ return {
25
+ success: !state.pausedState,
26
+ ...(state.output ? { output: state.output } : {}),
27
+ ...(state.messages.length > 0 ? { messages: state.messages } : {}),
28
+ ...(state.toolCalls.length > 0 ? { toolCalls: state.toolCalls } : {}),
29
+ ...(state.usage !== undefined ? { usage: state.usage } : {}),
30
+ ...(state.turnCount > 0 ? { turnCount: state.turnCount } : {}),
31
+ ...(state.thinking.length > 0 ? { thinking: state.thinking } : {}),
32
+ ...(state.nativeToolResults.length > 0 ? { nativeToolResults: state.nativeToolResults } : {}),
33
+ ...(state.pipelineTiming !== undefined ? { pipelineTiming: state.pipelineTiming } : {}),
34
+ ...(state.guardrailEvents.length > 0 ? { guardrailEvents: state.guardrailEvents } : {}),
35
+ ...(state.handoffs.length > 0 ? { handoffs: state.handoffs } : {}),
36
+ ...(state.pausedState ? { state: state.pausedState } : {}),
37
+ };
38
+ }
39
+ function toHeadlessError(code, message, details) {
40
+ return {
41
+ code,
42
+ message,
43
+ ...(details ? { details } : {}),
44
+ };
45
+ }
46
+ function toFailureResult(requestId, op, code, message, details) {
47
+ return {
48
+ kind: "result",
49
+ requestId,
50
+ op,
51
+ ok: false,
52
+ error: toHeadlessError(code, message, details),
53
+ };
54
+ }
55
+ function toSuccessResult(requestId, op, result) {
56
+ return {
57
+ kind: "result",
58
+ requestId,
59
+ op,
60
+ ok: true,
61
+ result,
62
+ };
63
+ }
64
+ function buildPolicySnapshot(request) {
65
+ return {
66
+ ...(request.arion ? { arion: request.arion } : {}),
67
+ ...(request.cwd ? { cwd: request.cwd } : {}),
68
+ ...(request.requestedModel ? { requestedModel: request.requestedModel } : {}),
69
+ ...(request.preferredTier ? { preferredTier: request.preferredTier } : {}),
70
+ ...(typeof request.budget === "number" ? { budget: request.budget } : {}),
71
+ ...(typeof request.maxTurns === "number" ? { maxTurns: request.maxTurns } : {}),
72
+ ...(request.autonomy ? { autonomy: request.autonomy } : {}),
73
+ ...(request.allowedTools ? { allowedTools: request.allowedTools } : {}),
74
+ ...(request.deniedTools ? { deniedTools: request.deniedTools } : {}),
75
+ ...(typeof request.noMemory === "boolean" ? { noMemory: request.noMemory } : {}),
76
+ ...(request.systemPrompt ? { systemPrompt: request.systemPrompt } : {}),
77
+ };
78
+ }
79
+ function applySessionArionToRunRequest(request, sessionArion) {
80
+ if (request.arion || !sessionArion) {
81
+ return request;
82
+ }
83
+ return {
84
+ ...request,
85
+ arion: sessionArion,
86
+ };
87
+ }
88
+ function toRuntimeRunRequest(request) {
89
+ const { sessionId: _sessionId, ...runtimeRequest } = request;
90
+ return runtimeRequest;
91
+ }
92
+ function toRuntimeResumeRequest(request) {
93
+ const { sessionId: _sessionId, ...runtimeRequest } = request;
94
+ return runtimeRequest;
95
+ }
96
+ function applySessionModelToRunRequest(request, sessionModel) {
97
+ if (request.requestedModel || !sessionModel) {
98
+ return request;
99
+ }
100
+ return {
101
+ ...request,
102
+ requestedModel: sessionModel,
103
+ };
104
+ }
105
+ function persistTranscript(sessionLedger, sessionId, messages) {
106
+ if (!Array.isArray(messages) || messages.length === 0) {
107
+ return;
108
+ }
109
+ sessionLedger.replaceConversationMessages(sessionId, fromModelMessages(messages));
110
+ }
111
+ function buildInteractionRequest(requestId, sessionId, pausedState) {
112
+ if ((pausedState.pendingUserQuestions?.length ?? 0) > 0) {
113
+ const interactionId = `${sessionId}:questionnaire:${randomUUID()}`;
114
+ const interaction = {
115
+ kind: "questionnaire",
116
+ questions: pausedState.pendingUserQuestions ?? [],
117
+ };
118
+ return {
119
+ record: {
120
+ interactionId,
121
+ requestId,
122
+ source: "run",
123
+ kind: interaction.kind,
124
+ prompt: interaction,
125
+ },
126
+ frame: {
127
+ kind: "interaction.required",
128
+ requestId,
129
+ interactionId,
130
+ source: "run",
131
+ interaction,
132
+ },
133
+ };
134
+ }
135
+ if ((pausedState.pendingToolCalls?.length ?? 0) > 0) {
136
+ const pendingTool = pausedState.pendingToolCalls[0];
137
+ const interactionId = `${sessionId}:tool-approval:${randomUUID()}`;
138
+ const interaction = {
139
+ kind: "tool_approval",
140
+ toolName: pendingTool.name,
141
+ toolInput: pendingTool.arguments,
142
+ prompt: `Approval required for ${pendingTool.name}`,
143
+ };
144
+ return {
145
+ record: {
146
+ interactionId,
147
+ requestId,
148
+ source: "run",
149
+ kind: interaction.kind,
150
+ prompt: interaction,
151
+ },
152
+ frame: {
153
+ kind: "interaction.required",
154
+ requestId,
155
+ interactionId,
156
+ source: "run",
157
+ interaction,
158
+ },
159
+ };
160
+ }
161
+ return null;
162
+ }
163
+ function buildResumeRequestFromInteraction(pausedState, interaction, response, runtimeStateRevision, runtimeStatePolicySnapshot) {
164
+ const baseRequest = {
165
+ state: pausedState,
166
+ ...(runtimeStatePolicySnapshot ?? {}),
167
+ };
168
+ if (interaction.kind === "tool_approval") {
169
+ if (response.response.kind !== "confirm") {
170
+ throw new Error(`Interaction ${interaction.interactionId} requires a confirm response`);
171
+ }
172
+ return {
173
+ ...baseRequest,
174
+ approvalMode: response.response.approved ? "approve" : "deny",
175
+ // Preserve a revision breadcrumb for diagnostics only; ignored by schema consumers.
176
+ ...(runtimeStateRevision >= 0 ? {} : {}),
177
+ };
178
+ }
179
+ if (interaction.kind === "questionnaire") {
180
+ if (response.response.kind !== "questionnaire") {
181
+ throw new Error(`Interaction ${interaction.interactionId} requires a questionnaire response`);
182
+ }
183
+ return {
184
+ ...baseRequest,
185
+ askUserAnswers: response.response.answers,
186
+ };
187
+ }
188
+ throw new Error(`Unsupported run interaction kind ${interaction.kind}`);
189
+ }
190
+ export class HeadlessRunOrchestrator {
191
+ ctx;
192
+ constructor(ctx) {
193
+ this.ctx = ctx;
194
+ }
195
+ renewSessionLease(sessionId, ownerId) {
196
+ const ledger = this.ctx.sessionLedger;
197
+ if (typeof ledger.renewSessionClaim === "function") {
198
+ return ledger.renewSessionClaim(sessionId, ownerId, SESSION_LEASE_MS);
199
+ }
200
+ return ledger.claimSessionForMutation(sessionId, ownerId, SESSION_LEASE_MS);
201
+ }
202
+ clearRunningSession(sessionId, ownerId, expectedRevision) {
203
+ const ledger = this.ctx.sessionLedger;
204
+ if (typeof ledger.clearActiveRun === "function") {
205
+ return ledger.clearActiveRun(sessionId, { ownerId, expectedRevision });
206
+ }
207
+ return ledger.completeRun(sessionId, {}, { ownerId, expectedRevision });
208
+ }
209
+ releaseClaimOnce(sessionId, ownerId) {
210
+ let released = false;
211
+ return () => {
212
+ if (released) {
213
+ return;
214
+ }
215
+ released = true;
216
+ this.ctx.sessionLedger.releaseSessionClaim(sessionId, ownerId);
217
+ };
218
+ }
219
+ static isAbortError(error) {
220
+ return (error instanceof Error &&
221
+ (error.name === "AbortError" ||
222
+ error.message === "The operation was aborted" ||
223
+ error.message === "This operation was aborted"));
224
+ }
225
+ static createAbortReason(code, message) {
226
+ const error = new Error(message);
227
+ error.name = "AbortError";
228
+ error.code = code;
229
+ return error;
230
+ }
231
+ static getAbortCode(signal, error) {
232
+ const candidate = signal?.aborted ? signal.reason : error;
233
+ if (candidate &&
234
+ typeof candidate === "object" &&
235
+ "code" in candidate &&
236
+ typeof candidate.code === "string") {
237
+ return candidate.code;
238
+ }
239
+ return signal?.aborted || HeadlessRunOrchestrator.isAbortError(error) ? "RUN_ABORTED" : null;
240
+ }
241
+ static getAbortMessage(signal, error) {
242
+ const candidate = signal?.aborted ? signal.reason : error;
243
+ if (candidate instanceof Error && candidate.message) {
244
+ return candidate.message;
245
+ }
246
+ return "Run aborted before completion.";
247
+ }
248
+ async *start(requestId, request, signal) {
249
+ const sessionId = request.sessionId?.trim() || requestId;
250
+ const ownerId = `headless:${requestId}`;
251
+ const sessionModel = this.ctx.getSessionModel?.();
252
+ const sessionArion = this.ctx.getSessionArion?.();
253
+ const effectiveRequest = applySessionModelToRunRequest(applySessionArionToRunRequest(request, sessionArion), sessionModel);
254
+ const arionName = effectiveRequest.arion ?? this.ctx.getSessionArion?.() ?? "ARIA";
255
+ const model = effectiveRequest.requestedModel ?? effectiveRequest.preferredTier ?? "balanced";
256
+ const policySnapshot = buildPolicySnapshot(effectiveRequest);
257
+ if (!this.ctx.sessionLedger.loadSession(sessionId)) {
258
+ this.ctx.sessionLedger.createSession(arionName, model, sessionId);
259
+ }
260
+ let claimed = this.ctx.sessionLedger.claimSessionForMutation(sessionId, ownerId, 30_000);
261
+ const releaseClaim = this.releaseClaimOnce(sessionId, ownerId);
262
+ const state = initialRunSynthesisState();
263
+ const controller = new AbortController();
264
+ let releaseExternalAbort = null;
265
+ let renewalTimer = null;
266
+ // Deferred persistence closure — captured in the success path, executed
267
+ // from the finally block via setTimeout(0). This architectural boundary
268
+ // ensures persistence (DELETE+INSERT of entire transcript) NEVER blocks
269
+ // the consumer from receiving the result frame and updating the UI.
270
+ let deferredPersistence = null;
271
+ if (signal) {
272
+ const onAbort = () => {
273
+ controller.abort(HeadlessRunOrchestrator.createAbortReason("CONNECTION_CLOSED", "Connection closed before request completed"));
274
+ };
275
+ if (signal.aborted) {
276
+ onAbort();
277
+ }
278
+ else {
279
+ signal.addEventListener("abort", onAbort, { once: true });
280
+ releaseExternalAbort = () => signal.removeEventListener("abort", onAbort);
281
+ }
282
+ }
283
+ renewalTimer = setInterval(() => {
284
+ try {
285
+ claimed = this.renewSessionLease(sessionId, ownerId);
286
+ }
287
+ catch (error) {
288
+ controller.abort(HeadlessRunOrchestrator.createAbortReason("SESSION_LEASE_LOST", error instanceof Error ? error.message : String(error)));
289
+ }
290
+ }, SESSION_LEASE_RENEW_INTERVAL_MS);
291
+ try {
292
+ for await (const event of this.ctx.localControl.streamRun(toRuntimeRunRequest(effectiveRequest), controller.signal)) {
293
+ if (controller.signal.aborted) {
294
+ releaseClaim();
295
+ return;
296
+ }
297
+ this.consumeRunEvent(state, event);
298
+ yield {
299
+ kind: "event",
300
+ requestId,
301
+ seq: state.turnCount + state.toolCalls.length + state.thinking.length,
302
+ op: "run.start",
303
+ event,
304
+ };
305
+ }
306
+ if (controller.signal.aborted) {
307
+ persistTranscript(this.ctx.sessionLedger, sessionId, state.messages);
308
+ this.clearRunningSession(sessionId, ownerId, claimed.revision);
309
+ releaseClaim();
310
+ const abortCode = HeadlessRunOrchestrator.getAbortCode(controller.signal);
311
+ if (abortCode !== "CONNECTION_CLOSED") {
312
+ yield toFailureResult(requestId, "run.start", abortCode ?? "RUN_ABORTED", HeadlessRunOrchestrator.getAbortMessage(controller.signal), { sessionId, runId: `run:${sessionId}` });
313
+ }
314
+ return;
315
+ }
316
+ if (state.pausedState) {
317
+ persistTranscript(this.ctx.sessionLedger, sessionId, state.pausedState.messages);
318
+ const interaction = buildInteractionRequest(requestId, sessionId, state.pausedState);
319
+ this.ctx.sessionLedger.recordPausedRun(sessionId, `run:${sessionId}`, state.pausedState, policySnapshot, interaction?.record, {
320
+ ownerId,
321
+ expectedRevision: claimed.revision,
322
+ });
323
+ releaseClaim();
324
+ if (interaction) {
325
+ yield interaction.frame;
326
+ }
327
+ yield toFailureResult(requestId, "run.start", "INTERACTION_REQUIRED", "Run paused and requires interaction before it can continue.", {
328
+ sessionId,
329
+ ...(interaction
330
+ ? {
331
+ interactionId: interaction.frame.interactionId,
332
+ source: interaction.frame.source,
333
+ interaction: interaction.frame.interaction,
334
+ }
335
+ : {}),
336
+ });
337
+ return;
338
+ }
339
+ const result = synthesizeRunResult(state);
340
+ // Yield result BEFORE persistence — the consumer must receive the result
341
+ // frame without waiting for SQLite writes. persistTranscript does
342
+ // DELETE + INSERT for the entire conversation transcript, which blocks
343
+ // the event loop for 100-500ms on long conversations. Deferring it to
344
+ // the finally block (via setTimeout) ensures the consumer's for-await
345
+ // loop exits immediately after this yield.
346
+ deferredPersistence = () => {
347
+ const msgCount = Array.isArray(result.messages) ? result.messages.length : 0;
348
+ setStallPhase(`orchestrator:persistTranscript(${msgCount} msgs)`);
349
+ const _pt0 = performance.now();
350
+ persistTranscript(this.ctx.sessionLedger, sessionId, result.messages);
351
+ const _pt1 = performance.now();
352
+ setStallPhase("orchestrator:completeRun");
353
+ this.ctx.sessionLedger.completeRun(sessionId, result, {
354
+ ownerId,
355
+ expectedRevision: claimed.revision,
356
+ });
357
+ const _pt2 = performance.now();
358
+ clearStallPhase();
359
+ releaseClaim();
360
+ const _total = _pt2 - _pt0;
361
+ if (_total > 100) {
362
+ try {
363
+ process.stderr.write(`[Orchestrator][DIAG] deferredPersistence: ` +
364
+ `total=${_total.toFixed(0)}ms transcript=${(_pt1 - _pt0).toFixed(0)}ms ` +
365
+ `completeRun=${(_pt2 - _pt1).toFixed(0)}ms msgs=${msgCount}\n`);
366
+ }
367
+ catch {
368
+ /* best effort */
369
+ }
370
+ }
371
+ };
372
+ yield toSuccessResult(requestId, "run.start", result);
373
+ }
374
+ catch (error) {
375
+ try {
376
+ if (controller.signal.aborted || HeadlessRunOrchestrator.isAbortError(error)) {
377
+ persistTranscript(this.ctx.sessionLedger, sessionId, state.messages);
378
+ this.clearRunningSession(sessionId, ownerId, claimed.revision);
379
+ }
380
+ releaseClaim();
381
+ }
382
+ catch {
383
+ // Best effort cleanup on failure.
384
+ }
385
+ if (controller.signal.aborted || HeadlessRunOrchestrator.isAbortError(error)) {
386
+ const abortCode = HeadlessRunOrchestrator.getAbortCode(controller.signal, error);
387
+ if (abortCode !== "CONNECTION_CLOSED") {
388
+ yield toFailureResult(requestId, "run.start", abortCode ?? "RUN_ABORTED", HeadlessRunOrchestrator.getAbortMessage(controller.signal, error), { sessionId, runId: `run:${sessionId}` });
389
+ }
390
+ return;
391
+ }
392
+ yield toFailureResult(requestId, "run.start", "RUN_START_FAILED", error instanceof Error ? error.message : String(error));
393
+ }
394
+ finally {
395
+ if (renewalTimer) {
396
+ clearInterval(renewalTimer);
397
+ }
398
+ releaseExternalAbort?.();
399
+ // Execute deferred persistence from the success path. Scheduled via
400
+ // setTimeout(0) so it runs AFTER React's microtask render cycle —
401
+ // the consumer sets isStreaming=false and yields, React renders the
402
+ // input area, THEN persistence runs. This makes it structurally
403
+ // impossible for transcript persistence to block the UI transition.
404
+ if (deferredPersistence) {
405
+ const persist = deferredPersistence;
406
+ deferredPersistence = null;
407
+ setTimeout(() => {
408
+ try {
409
+ setStallPhase("orchestrator:deferredPersistence");
410
+ const dpT0 = performance.now();
411
+ persist();
412
+ const dpElapsed = performance.now() - dpT0;
413
+ clearStallPhase();
414
+ if (dpElapsed > 200) {
415
+ try {
416
+ process.stderr.write(`[Orchestrator][DIAG] deferredPersistence blocked ${dpElapsed.toFixed(0)}ms\n`);
417
+ }
418
+ catch {
419
+ /* best effort */
420
+ }
421
+ }
422
+ }
423
+ catch {
424
+ clearStallPhase();
425
+ // Non-fatal: consumer already has the result frame.
426
+ // Crash recovery handles stale session state on next startup.
427
+ releaseClaim();
428
+ }
429
+ }, 0);
430
+ }
431
+ }
432
+ }
433
+ async *resume(requestId, request, signal) {
434
+ const sessionId = request.sessionId?.trim();
435
+ const ownerId = `headless:${requestId}`;
436
+ const sessionModel = this.ctx.getSessionModel?.();
437
+ const sessionArion = this.ctx.getSessionArion?.();
438
+ const effectiveRequest = applySessionModelToRunRequest(applySessionArionToRunRequest(request, sessionArion), sessionModel);
439
+ const runtimeRequest = toRuntimeResumeRequest(effectiveRequest);
440
+ const policySnapshot = buildPolicySnapshot(runtimeRequest);
441
+ let createdSession = false;
442
+ let claimed = null;
443
+ try {
444
+ if (signal?.aborted) {
445
+ return;
446
+ }
447
+ if (sessionId) {
448
+ if (!this.ctx.sessionLedger.loadSession(sessionId)) {
449
+ this.ctx.sessionLedger.createSession(effectiveRequest.arion ?? this.ctx.getSessionArion?.() ?? "ARIA", effectiveRequest.requestedModel ?? effectiveRequest.preferredTier ?? "balanced", sessionId);
450
+ createdSession = true;
451
+ }
452
+ claimed = this.ctx.sessionLedger.claimSessionForMutation(sessionId, ownerId, 30_000);
453
+ }
454
+ const result = await this.ctx.localControl.resumeRun(runtimeRequest);
455
+ if (signal?.aborted) {
456
+ if (sessionId && claimed) {
457
+ this.ctx.sessionLedger.releaseSessionClaim(sessionId, ownerId);
458
+ if (createdSession) {
459
+ this.ctx.sessionLedger.deleteSession(sessionId);
460
+ }
461
+ }
462
+ return;
463
+ }
464
+ if (sessionId && claimed) {
465
+ if (result.state) {
466
+ const pausedState = result.state;
467
+ persistTranscript(this.ctx.sessionLedger, sessionId, pausedState.messages);
468
+ const nextInteraction = buildInteractionRequest(requestId, sessionId, pausedState);
469
+ this.ctx.sessionLedger.recordPausedRun(sessionId, `run:${sessionId}`, pausedState, policySnapshot, nextInteraction?.record, {
470
+ ownerId,
471
+ expectedRevision: claimed.revision,
472
+ });
473
+ this.ctx.sessionLedger.releaseSessionClaim(sessionId, ownerId);
474
+ if (nextInteraction) {
475
+ yield nextInteraction.frame;
476
+ }
477
+ yield toFailureResult(requestId, "run.resume", "INTERACTION_REQUIRED", "Run paused and requires interaction before it can continue.", {
478
+ sessionId,
479
+ ...(nextInteraction
480
+ ? {
481
+ interactionId: nextInteraction.frame.interactionId,
482
+ source: nextInteraction.frame.source,
483
+ interaction: nextInteraction.frame.interaction,
484
+ }
485
+ : {}),
486
+ });
487
+ return;
488
+ }
489
+ persistTranscript(this.ctx.sessionLedger, sessionId, result.messages);
490
+ this.ctx.sessionLedger.completeRun(sessionId, result, {
491
+ ownerId,
492
+ expectedRevision: claimed.revision,
493
+ });
494
+ this.ctx.sessionLedger.releaseSessionClaim(sessionId, ownerId);
495
+ }
496
+ yield toSuccessResult(requestId, "run.resume", result);
497
+ }
498
+ catch (error) {
499
+ if (sessionId && claimed) {
500
+ try {
501
+ this.ctx.sessionLedger.releaseSessionClaim(sessionId, ownerId);
502
+ if (createdSession) {
503
+ this.ctx.sessionLedger.deleteSession(sessionId);
504
+ }
505
+ }
506
+ catch {
507
+ // Best effort cleanup.
508
+ }
509
+ }
510
+ if (signal?.aborted || HeadlessRunOrchestrator.isAbortError(error)) {
511
+ return;
512
+ }
513
+ yield toFailureResult(requestId, "run.resume", "RUN_RESUME_FAILED", error instanceof Error ? error.message : String(error));
514
+ }
515
+ }
516
+ async *abort(requestId, input, activeRunController) {
517
+ const aborted = await (activeRunController ?? this.ctx.activeRunController)?.abort(input);
518
+ if (aborted) {
519
+ yield {
520
+ kind: "result",
521
+ requestId,
522
+ op: "run.abort",
523
+ ok: true,
524
+ result: {
525
+ aborted: true,
526
+ ...(input.runId ? { runId: input.runId } : {}),
527
+ ...(input.sessionId ? { sessionId: input.sessionId } : {}),
528
+ },
529
+ };
530
+ return;
531
+ }
532
+ yield toFailureResult(requestId, "run.abort", "RUN_NOT_FOUND", "No active run matched the requested runId or sessionId.", {
533
+ ...(input.runId ? { runId: input.runId } : {}),
534
+ ...(input.sessionId ? { sessionId: input.sessionId } : {}),
535
+ });
536
+ }
537
+ async *respond(response, signal) {
538
+ const interaction = this.ctx.sessionLedger.getInteraction(response.interactionId);
539
+ if (!interaction) {
540
+ yield toFailureResult(response.requestId, "interaction.respond", "INTERACTION_NOT_FOUND", `Unknown interaction ${response.interactionId}`);
541
+ return;
542
+ }
543
+ if (interaction.source !== "run") {
544
+ yield toFailureResult(response.requestId, "interaction.respond", "UNSUPPORTED_INTERACTION_SOURCE", `Interaction source ${interaction.source} is not handled by the run orchestrator`);
545
+ return;
546
+ }
547
+ const runtimeState = this.ctx.sessionLedger.getSessionRuntimeState(interaction.sessionId);
548
+ if (!runtimeState?.pausedState) {
549
+ yield toFailureResult(response.requestId, "interaction.respond", "SESSION_NOT_PAUSED", `Session ${interaction.sessionId} is not paused`);
550
+ return;
551
+ }
552
+ const ownerId = `headless:${response.requestId}`;
553
+ try {
554
+ if (signal?.aborted) {
555
+ return;
556
+ }
557
+ const claimed = this.ctx.sessionLedger.claimSessionForMutation(interaction.sessionId, ownerId, 30_000);
558
+ let effectiveResponse = response.response;
559
+ let responseRevision = claimed.revision;
560
+ if (interaction.status === "pending") {
561
+ this.ctx.sessionLedger.recordInteractionResponse(interaction.sessionId, interaction.interactionId, effectiveResponse, {
562
+ ownerId,
563
+ expectedRevision: claimed.revision,
564
+ });
565
+ responseRevision += 1;
566
+ }
567
+ else if (interaction.status === "answered") {
568
+ if (!interaction.response) {
569
+ this.ctx.sessionLedger.releaseSessionClaim(interaction.sessionId, ownerId);
570
+ yield toFailureResult(response.requestId, "interaction.respond", "INVALID_INTERACTION_STATE", `Interaction ${interaction.interactionId} is missing its recorded response`);
571
+ return;
572
+ }
573
+ if (!isDeepStrictEqual(interaction.response, effectiveResponse)) {
574
+ this.ctx.sessionLedger.releaseSessionClaim(interaction.sessionId, ownerId);
575
+ yield toFailureResult(response.requestId, "interaction.respond", "INTERACTION_ALREADY_ANSWERED", `Interaction ${interaction.interactionId} was already answered with a different response`);
576
+ return;
577
+ }
578
+ effectiveResponse = interaction.response;
579
+ }
580
+ else {
581
+ this.ctx.sessionLedger.releaseSessionClaim(interaction.sessionId, ownerId);
582
+ yield toFailureResult(response.requestId, "interaction.respond", "INTERACTION_NOT_PENDING", `Interaction ${interaction.interactionId} is not resumable in state ${interaction.status}`);
583
+ return;
584
+ }
585
+ const resumeRequest = buildResumeRequestFromInteraction(runtimeState.pausedState, interaction, {
586
+ ...response,
587
+ response: effectiveResponse,
588
+ }, runtimeState.revision, runtimeState.policySnapshot);
589
+ const result = await this.ctx.localControl.resumeRun(resumeRequest);
590
+ if (signal?.aborted) {
591
+ this.ctx.sessionLedger.releaseSessionClaim(interaction.sessionId, ownerId);
592
+ return;
593
+ }
594
+ if (result.state) {
595
+ const pausedState = result.state;
596
+ persistTranscript(this.ctx.sessionLedger, interaction.sessionId, pausedState.messages);
597
+ const nextInteraction = buildInteractionRequest(response.requestId, interaction.sessionId, pausedState);
598
+ this.ctx.sessionLedger.recordPausedRun(interaction.sessionId, runtimeState.activeRunId ?? `run:${interaction.sessionId}`, pausedState, runtimeState.policySnapshot ?? {}, nextInteraction?.record, {
599
+ ownerId,
600
+ expectedRevision: responseRevision,
601
+ });
602
+ this.ctx.sessionLedger.releaseSessionClaim(interaction.sessionId, ownerId);
603
+ if (nextInteraction) {
604
+ yield nextInteraction.frame;
605
+ }
606
+ yield toFailureResult(response.requestId, "interaction.respond", "INTERACTION_REQUIRED", "Run paused again and requires another interaction.", {
607
+ sessionId: interaction.sessionId,
608
+ ...(nextInteraction
609
+ ? {
610
+ interactionId: nextInteraction.frame.interactionId,
611
+ source: nextInteraction.frame.source,
612
+ interaction: nextInteraction.frame.interaction,
613
+ }
614
+ : {}),
615
+ });
616
+ return;
617
+ }
618
+ persistTranscript(this.ctx.sessionLedger, interaction.sessionId, result.messages);
619
+ this.ctx.sessionLedger.completeRun(interaction.sessionId, result, {
620
+ ownerId,
621
+ expectedRevision: responseRevision,
622
+ });
623
+ this.ctx.sessionLedger.releaseSessionClaim(interaction.sessionId, ownerId);
624
+ yield toSuccessResult(response.requestId, "interaction.respond", result);
625
+ }
626
+ catch (error) {
627
+ try {
628
+ this.ctx.sessionLedger.releaseSessionClaim(interaction.sessionId, ownerId);
629
+ }
630
+ catch {
631
+ // Best effort.
632
+ }
633
+ if (signal?.aborted || HeadlessRunOrchestrator.isAbortError(error)) {
634
+ return;
635
+ }
636
+ yield toFailureResult(response.requestId, "interaction.respond", "INTERACTION_RESPONSE_FAILED", error instanceof Error ? error.message : String(error));
637
+ }
638
+ }
639
+ consumeRunEvent(state, event) {
640
+ switch (event.type) {
641
+ case "text_delta":
642
+ state.output += event.content;
643
+ break;
644
+ case "tool_result":
645
+ state.toolCalls.push({
646
+ id: event.id,
647
+ name: event.name,
648
+ input: event.input,
649
+ result: event.result,
650
+ durationMs: event.durationMs,
651
+ });
652
+ break;
653
+ case "usage_update":
654
+ state.usage = event.usage;
655
+ break;
656
+ case "turn_complete":
657
+ state.turnCount = event.turnNumber;
658
+ break;
659
+ case "guardrail_rejected":
660
+ state.guardrailEvents.push({
661
+ stage: event.stage,
662
+ message: event.message,
663
+ });
664
+ break;
665
+ case "pipeline_timing":
666
+ state.pipelineTiming = event.report;
667
+ break;
668
+ case "messages_snapshot":
669
+ state.messages = Array.isArray(event.messages) ? event.messages : [];
670
+ break;
671
+ case "thinking_end":
672
+ if (event.blocks)
673
+ state.thinking.push(...event.blocks);
674
+ break;
675
+ case "native_tool_result":
676
+ state.nativeToolResults.push(event.metadata);
677
+ break;
678
+ case "handoff_start":
679
+ state.handoffs.push({
680
+ type: "start",
681
+ target: event.target,
682
+ id: event.id,
683
+ });
684
+ break;
685
+ case "handoff_result":
686
+ state.handoffs.push({
687
+ type: "result",
688
+ target: event.target,
689
+ id: event.id,
690
+ result: event.result,
691
+ });
692
+ break;
693
+ case "paused":
694
+ state.pausedState = event.state;
695
+ break;
696
+ case "error":
697
+ throw new Error(resolveTrustedRuntimeErrorMessage(event.error.message, "diagnostic" in event.error ? event.error.diagnostic : undefined) ?? event.error.message);
698
+ default:
699
+ break;
700
+ }
701
+ }
702
+ }
703
+ //# sourceMappingURL=run-orchestrator.js.map