@vellumai/assistant 0.12.2 → 0.12.3-staging.2

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 (772) hide show
  1. package/.env.example +2 -0
  2. package/AGENTS.md +1 -1
  3. package/ARCHITECTURE.md +43 -29
  4. package/Dockerfile +63 -0
  5. package/docs/architecture/integrations.md +7 -0
  6. package/docs/architecture/memory.md +17 -2
  7. package/docs/architecture/security.md +10 -5
  8. package/docs/architecture/turn-actor.md +2 -0
  9. package/docs/credential-execution-service.md +1 -1
  10. package/docs/desktop-browser-cli.md +50 -5
  11. package/docs/live-voice-task-outcomes.md +100 -0
  12. package/docs/mode-sessions.md +183 -0
  13. package/docs/voice-input-diagnostics.md +58 -0
  14. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  15. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
  16. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  17. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  18. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
  19. package/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
  20. package/node_modules/@vellumai/environments/src/shell.ts +24 -0
  21. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  22. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
  23. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  24. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  25. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
  26. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
  27. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -2
  28. package/node_modules/@vellumai/gateway-client/src/index.ts +4 -1
  29. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +38 -7
  30. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +5 -6
  31. package/node_modules/@vellumai/service-contracts/package.json +2 -1
  32. package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
  33. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  34. package/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  35. package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
  36. package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
  37. package/openapi.yaml +716 -16
  38. package/package.json +1 -1
  39. package/scripts/smoke-desktop-browser-cli.ts +11 -26
  40. package/scripts/smoke-desktop-window-theme.ts +2 -3
  41. package/scripts/sync-llm-catalog.ts +3 -0
  42. package/scripts/voice-ttft-spike.ts +2 -2
  43. package/src/__tests__/agent-loop-output-hooks.test.ts +150 -1
  44. package/src/__tests__/agent-loop-provider-error-recording.test.ts +87 -19
  45. package/src/__tests__/agent-loop.test.ts +259 -0
  46. package/src/__tests__/agent-wake-delegation-prompt.test.ts +64 -2
  47. package/src/__tests__/annotate-activity-metadata.test.ts +3 -1
  48. package/src/__tests__/annotate-risk-options.test.ts +2 -0
  49. package/src/__tests__/answered-question-persistence.test.ts +2 -0
  50. package/src/__tests__/anthropic-gateway-shared.test.ts +22 -0
  51. package/src/__tests__/anthropic-provider.test.ts +55 -0
  52. package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
  53. package/src/__tests__/approval-message-composer.test.ts +1 -118
  54. package/src/__tests__/approval-routes-http.test.ts +3 -0
  55. package/src/__tests__/assistant-event-hub-connection-history.test.ts +111 -0
  56. package/src/__tests__/assistant-event-hub-targeted.test.ts +50 -0
  57. package/src/__tests__/assistant-event-targeting.test.ts +186 -0
  58. package/src/__tests__/assistant-stream-state.test.ts +29 -9
  59. package/src/__tests__/attachments-store.test.ts +22 -3
  60. package/src/__tests__/browser-fill-credential.test.ts +11 -22
  61. package/src/__tests__/btw-routes.test.ts +4 -1
  62. package/src/__tests__/build-persisted-content.test.ts +1 -1
  63. package/src/__tests__/call-conversation-messages.test.ts +5 -0
  64. package/src/__tests__/call-recovery.test.ts +7 -2
  65. package/src/__tests__/call-routes-http.test.ts +12 -0
  66. package/src/__tests__/call-store.test.ts +7 -2
  67. package/src/__tests__/channel-approval.test.ts +9 -14
  68. package/src/__tests__/channel-reply-delivery.test.ts +56 -0
  69. package/src/__tests__/channel-retry-sweep.test.ts +9 -0
  70. package/src/__tests__/chat-credential-redaction.test.ts +23 -0
  71. package/src/__tests__/chat-reveal-guard-priming.test.ts +2 -0
  72. package/src/__tests__/checker.test.ts +11 -3
  73. package/src/__tests__/client-os-metadata-persistence.test.ts +35 -1
  74. package/src/__tests__/computer-use-screenshot-attachments.test.ts +411 -0
  75. package/src/__tests__/computer-use-screenshot-selection.test.ts +50 -0
  76. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -25
  77. package/src/__tests__/computer-use-tools.test.ts +1 -233
  78. package/src/__tests__/config-model-image-provider.test.ts +39 -0
  79. package/src/__tests__/config-schema.test.ts +16 -0
  80. package/src/__tests__/config-watcher.test.ts +24 -0
  81. package/src/__tests__/context-search-agent-runner.test.ts +260 -1
  82. package/src/__tests__/context-search-fanout.test.ts +1 -1
  83. package/src/__tests__/context-search-types.test.ts +7 -7
  84. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +8 -2
  85. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +2 -0
  86. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  87. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
  88. package/src/__tests__/conversation-agent-loop.test.ts +797 -16
  89. package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
  90. package/src/__tests__/conversation-attachments.test.ts +106 -0
  91. package/src/__tests__/conversation-evictor.test.ts +62 -37
  92. package/src/__tests__/conversation-fork-crud.test.ts +191 -0
  93. package/src/__tests__/conversation-history-boundary-repair-failure.test.ts +174 -0
  94. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +2 -0
  95. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
  96. package/src/__tests__/conversation-rendered-delegation-state.test.ts +276 -0
  97. package/src/__tests__/conversation-retry-route.test.ts +22 -0
  98. package/src/__tests__/conversation-routes-disk-view.test.ts +2 -0
  99. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +2 -0
  100. package/src/__tests__/conversation-routes-guardian-reply.test.ts +10 -0
  101. package/src/__tests__/conversation-routes-hidden-queue.test.ts +2 -0
  102. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
  103. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -0
  104. package/src/__tests__/conversation-surface-snapshots.test.ts +543 -0
  105. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +151 -0
  106. package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +63 -1
  107. package/src/__tests__/conversation-tool-setup-attribution.test.ts +23 -0
  108. package/src/__tests__/conversation-undo.test.ts +61 -0
  109. package/src/__tests__/credential-execution-client.test.ts +72 -55
  110. package/src/__tests__/credential-prompt-route.test.ts +35 -3
  111. package/src/__tests__/cu-unified-flow.test.ts +82 -1
  112. package/src/__tests__/db-conversation-tool-surface.test.ts +221 -0
  113. package/src/__tests__/db-mode-sessions-migration.test.ts +175 -0
  114. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -0
  115. package/src/__tests__/dm-backfill.test.ts +91 -1
  116. package/src/__tests__/document-create-route.test.ts +88 -0
  117. package/src/__tests__/document-sync-tags.test.ts +27 -0
  118. package/src/__tests__/emit-signal-routing-intent.test.ts +142 -2
  119. package/src/__tests__/events-tail-route.test.ts +58 -0
  120. package/src/__tests__/evict-conversations-for-reload.test.ts +57 -8
  121. package/src/__tests__/guardian-action-sweep.test.ts +16 -0
  122. package/src/__tests__/guardian-dispatch.test.ts +13 -0
  123. package/src/__tests__/headless-browser-interactions.test.ts +64 -20
  124. package/src/__tests__/heartbeat-service.test.ts +2 -59
  125. package/src/__tests__/helpers/mock-conversation.ts +21 -0
  126. package/src/__tests__/helpers/native-web-search-harness.ts +2 -0
  127. package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +5 -0
  128. package/src/__tests__/history-repair.test.ts +53 -0
  129. package/src/__tests__/host-cu-proxy.test.ts +46 -2
  130. package/src/__tests__/http-user-message-parity.test.ts +2 -0
  131. package/src/__tests__/image-credentials.test.ts +49 -0
  132. package/src/__tests__/image-service-dispatcher.test.ts +45 -0
  133. package/src/__tests__/inference-profile-session-handler.test.ts +26 -0
  134. package/src/__tests__/interrupt-on-send.test.ts +57 -43
  135. package/src/__tests__/interrupt-turn-note.test.ts +5 -6
  136. package/src/__tests__/list-messages-tool-merge.test.ts +85 -1
  137. package/src/__tests__/llm-catalog-parity.test.ts +27 -4
  138. package/src/__tests__/media-generate-image.test.ts +49 -1
  139. package/src/__tests__/message-provenance-contact-id.test.ts +69 -0
  140. package/src/__tests__/migration-export-to-gcs.test.ts +142 -0
  141. package/src/__tests__/mode-session-history.test.ts +245 -0
  142. package/src/__tests__/mode-session-recovery.test.ts +222 -0
  143. package/src/__tests__/mode-session-wire.test.ts +141 -0
  144. package/src/__tests__/notification-guardian-path.test.ts +7 -0
  145. package/src/__tests__/notification-telegram-adapter.test.ts +2 -2
  146. package/src/__tests__/notification-vellum-adapter.test.ts +34 -0
  147. package/src/__tests__/oauth-apps-routes.test.ts +1 -0
  148. package/src/__tests__/oauth-commands-routes.test.ts +114 -101
  149. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
  150. package/src/__tests__/oauth-provider-serializer.test.ts +13 -0
  151. package/src/__tests__/oauth-providers-routes.test.ts +3 -0
  152. package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
  153. package/src/__tests__/persist-media-references.test.ts +50 -0
  154. package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
  155. package/src/__tests__/plugin-api-provider.test.ts +5 -0
  156. package/src/__tests__/plugin-api-resolve-credential.test.ts +97 -0
  157. package/src/__tests__/plugin-import-boundary-guard.test.ts +9 -1
  158. package/src/__tests__/process-message-display-content.test.ts +56 -0
  159. package/src/__tests__/reaction-persistence.test.ts +5 -0
  160. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +25 -9
  161. package/src/__tests__/run-conversation-turn-persistence.test.ts +138 -1
  162. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
  163. package/src/__tests__/schedule-routes.test.ts +20 -0
  164. package/src/__tests__/scheduler-result-notification.test.ts +23 -4
  165. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  166. package/src/__tests__/scripted-turn-metadata-persistence.test.ts +73 -0
  167. package/src/__tests__/secret-ingress-http.test.ts +2 -0
  168. package/src/__tests__/secret-routes-platform-proxy.test.ts +86 -31
  169. package/src/__tests__/secret-routes-scrub.test.ts +22 -27
  170. package/src/__tests__/secret-scanner.test.ts +20 -0
  171. package/src/__tests__/secure-keys-managed-failover.test.ts +8 -0
  172. package/src/__tests__/secure-keys.test.ts +50 -4
  173. package/src/__tests__/send-endpoint-busy.test.ts +163 -1
  174. package/src/__tests__/server-history-render.test.ts +91 -1
  175. package/src/__tests__/server-tool-pairing.test.ts +107 -0
  176. package/src/__tests__/settings-routes.test.ts +50 -1
  177. package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
  178. package/src/__tests__/skills.test.ts +5 -4
  179. package/src/__tests__/subagent-fork-notifications.test.ts +1 -2
  180. package/src/__tests__/subagent-manager-notify.test.ts +1 -2
  181. package/src/__tests__/subagent-notify-parent.test.ts +146 -39
  182. package/src/__tests__/subagent-notify-stale-rebuild.test.ts +2 -4
  183. package/src/__tests__/subagent-tool-gate-mode.test.ts +226 -0
  184. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +2 -0
  185. package/src/__tests__/terminal-tools.test.ts +8 -0
  186. package/src/__tests__/thread-backfill.test.ts +53 -0
  187. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
  188. package/src/__tests__/tool-result-follow-up.test.ts +99 -0
  189. package/src/__tests__/tool-result-metadata-plumbing.test.ts +66 -1
  190. package/src/__tests__/tool-start-timestamp.test.ts +2 -0
  191. package/src/__tests__/twilio-routes.test.ts +1 -0
  192. package/src/__tests__/unicode.test.ts +36 -0
  193. package/src/__tests__/web-search-backend-failure.test.ts +1 -1
  194. package/src/activation/progress-store.test.ts +12 -7
  195. package/src/agent/loop.ts +136 -53
  196. package/src/agent/tool-result-follow-up.ts +70 -0
  197. package/src/api/attachment-provenance.test.ts +68 -0
  198. package/src/api/computer-use-tool.test.ts +55 -0
  199. package/src/api/computer-use-tool.ts +27 -0
  200. package/src/api/events/assistant-outbound-attachment.ts +3 -0
  201. package/src/api/events/assistant-turn-start.ts +3 -0
  202. package/src/api/events/desktop-activity-changed.ts +10 -0
  203. package/src/api/events/generation-handoff.ts +2 -0
  204. package/src/api/events/message-complete.ts +2 -0
  205. package/src/api/events/notification-conversation-created.ts +14 -16
  206. package/src/api/events/notification-intent.ts +4 -2
  207. package/src/api/events/question-request.ts +1 -0
  208. package/src/api/events/tool-result.ts +85 -0
  209. package/src/api/events/tool-use-start.ts +3 -0
  210. package/src/api/events/user-message-echo.ts +3 -0
  211. package/src/api/index.ts +42 -6
  212. package/src/api/mode-session.test.ts +131 -0
  213. package/src/api/mode-session.ts +148 -0
  214. package/src/api/remember-tool.ts +15 -0
  215. package/src/api/responses/conversation-message.ts +9 -0
  216. package/src/approvals/AGENTS.md +4 -2
  217. package/src/approvals/approval-primitive.ts +5 -2
  218. package/src/approvals/scoped-approval-grants.ts +6 -2
  219. package/src/browser/__tests__/operations.test.ts +29 -0
  220. package/src/browser/operation-meta.ts +2 -1
  221. package/src/browser/operations.ts +29 -0
  222. package/src/browser/virtual-desktop-target.ts +2 -9
  223. package/src/bundler/bundle-signer.ts +1 -3
  224. package/src/calls/__tests__/barge-in-guard.test.ts +3 -0
  225. package/src/calls/__tests__/call-controller.test.ts +94 -0
  226. package/src/calls/__tests__/call-funnel-telemetry.test.ts +204 -0
  227. package/src/calls/__tests__/voice-control-protocol.test.ts +15 -0
  228. package/src/calls/__tests__/voice-escalation-judge.test.ts +209 -0
  229. package/src/calls/__tests__/voice-leg-coordinator.test.ts +168 -0
  230. package/src/{live-voice/__tests__/live-voice-metrics.test.ts → calls/__tests__/voice-metrics.test.ts} +32 -38
  231. package/src/calls/__tests__/voice-session-bridge.test.ts +576 -122
  232. package/src/calls/barge-in-guard.ts +5 -0
  233. package/src/calls/call-controller.ts +196 -1
  234. package/src/calls/call-domain.ts +4 -0
  235. package/src/calls/call-store.ts +87 -2
  236. package/src/calls/guardian-action-sweep.ts +22 -8
  237. package/src/calls/media-stream-audio-transcode.ts +1 -3
  238. package/src/calls/typesafe-noul.ts +156 -0
  239. package/src/calls/voice-control-protocol.ts +6 -0
  240. package/src/calls/voice-escalation-judge.ts +145 -0
  241. package/src/calls/voice-escalation-target.ts +10 -0
  242. package/src/calls/voice-leg-coordinator.ts +121 -3
  243. package/src/{live-voice/live-voice-metrics.ts → calls/voice-metrics.ts} +94 -87
  244. package/src/calls/voice-session-bridge.ts +256 -112
  245. package/src/calls/voice-triage-escalate.ts +7 -0
  246. package/src/cli/__tests__/roadmap-cli.test.ts +4 -41
  247. package/src/cli/commands/__tests__/cli-test-harness.ts +21 -3
  248. package/src/cli/commands/__tests__/notifications.test.ts +35 -10
  249. package/src/cli/commands/__tests__/plugins.test.ts +20 -1
  250. package/src/cli/commands/__tests__/schedules.test.ts +14 -0
  251. package/src/cli/commands/bash.help.ts +4 -3
  252. package/src/cli/commands/browser.help.ts +9 -6
  253. package/src/cli/commands/browser.ts +0 -1
  254. package/src/cli/commands/clients.help.ts +46 -0
  255. package/src/cli/commands/clients.ts +116 -0
  256. package/src/cli/commands/credentials.help.ts +9 -4
  257. package/src/cli/commands/notifications.help.ts +16 -2
  258. package/src/cli/commands/notifications.ts +30 -8
  259. package/src/cli/commands/oauth/index.help.ts +10 -0
  260. package/src/cli/commands/oauth/providers.ts +12 -0
  261. package/src/cli/commands/oauth/request.test.ts +179 -2
  262. package/src/cli/commands/oauth/request.ts +41 -10
  263. package/src/cli/commands/plugins.ts +12 -5
  264. package/src/cli/commands/roadmap.help.ts +18 -21
  265. package/src/cli/commands/roadmap.ts +4 -21
  266. package/src/cli/commands/schedules.ts +2 -0
  267. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  268. package/src/cli/lib/__tests__/install-from-github.test.ts +41 -0
  269. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
  270. package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +133 -51
  271. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +8 -2
  272. package/src/cli/lib/bundled-marketplace.json +906 -1
  273. package/src/cli/lib/bundled-plugin-packages.json +783 -1
  274. package/src/cli/lib/inspect-plugin.ts +11 -4
  275. package/src/cli/lib/plugin-marketplace.ts +8 -0
  276. package/src/cli/lib/publish-plugin.ts +1 -2
  277. package/src/cli/lib/upgrade-plugin.ts +19 -11
  278. package/src/cli/output.ts +18 -4
  279. package/src/config/__tests__/default-provider.test.ts +6 -0
  280. package/src/config/__tests__/memory-retrospective-schema.test.ts +14 -1
  281. package/src/config/bundled-skills/computer-use/SKILL.md +1 -1
  282. package/src/config/bundled-skills/computer-use/TOOLS.json +89 -1
  283. package/src/config/bundled-skills/image-studio/SKILL.md +17 -2
  284. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -11
  285. package/src/config/bundled-skills/schedule/SKILL.md +6 -6
  286. package/src/config/bundled-skills/sequences/TOOLS.json +1 -5
  287. package/src/config/call-site-defaults.ts +9 -0
  288. package/src/config/feature-flag-registry.json +16 -0
  289. package/src/config/loader.ts +9 -17
  290. package/src/config/platform-identity.ts +8 -8
  291. package/src/config/profile-text-generation.test.ts +51 -0
  292. package/src/config/profile-text-generation.ts +51 -0
  293. package/src/config/schemas/__tests__/memory-v3.test.ts +12 -0
  294. package/src/config/schemas/__tests__/tools.test.ts +31 -0
  295. package/src/config/schemas/call-site-catalog.ts +14 -0
  296. package/src/config/schemas/channels.ts +0 -18
  297. package/src/config/schemas/llm.ts +9 -2
  298. package/src/config/schemas/mcp.ts +6 -1
  299. package/src/config/schemas/memory-retrospective.ts +11 -2
  300. package/src/config/schemas/memory-v3.ts +12 -0
  301. package/src/config/schemas/services.ts +15 -6
  302. package/src/config/schemas/tools.ts +10 -0
  303. package/src/config/session-groups-gate.ts +21 -0
  304. package/src/config/skills.ts +2 -6
  305. package/src/conversations/__tests__/message-consolidation.test.ts +149 -0
  306. package/src/conversations/message-consolidation.ts +102 -5
  307. package/src/credential-execution/ces-connect.test.ts +69 -0
  308. package/src/credential-execution/ces-connect.ts +115 -0
  309. package/src/credential-execution/ces-runtime.ts +55 -93
  310. package/src/credential-execution/executable-discovery.ts +34 -142
  311. package/src/credential-execution/process-manager.test.ts +20 -24
  312. package/src/credential-execution/process-manager.ts +24 -19
  313. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
  314. package/src/daemon/__tests__/conversation-tool-setup.test.ts +43 -0
  315. package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
  316. package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +36 -0
  317. package/src/daemon/assistant-attachments.ts +20 -12
  318. package/src/daemon/browser-mode-session.test.ts +402 -0
  319. package/src/daemon/browser-mode-session.ts +186 -0
  320. package/src/daemon/chat-credential-redaction.ts +16 -1
  321. package/src/daemon/computer-use-mode-session.test.ts +210 -0
  322. package/src/daemon/computer-use-mode-session.ts +105 -0
  323. package/src/daemon/config-watcher.ts +10 -0
  324. package/src/daemon/conversation-agent-loop-handlers.ts +132 -13
  325. package/src/daemon/conversation-agent-loop.ts +231 -25
  326. package/src/daemon/conversation-attachments.ts +93 -12
  327. package/src/daemon/conversation-evictor.ts +5 -24
  328. package/src/daemon/conversation-history.ts +10 -0
  329. package/src/daemon/conversation-interrupt-repair.ts +4 -43
  330. package/src/daemon/conversation-interrupt.ts +7 -11
  331. package/src/daemon/conversation-messaging.ts +58 -5
  332. package/src/daemon/conversation-mode-session.test.ts +1667 -0
  333. package/src/daemon/conversation-mode-session.ts +1008 -0
  334. package/src/daemon/conversation-process.ts +5 -0
  335. package/src/daemon/conversation-runtime-assembly.ts +10 -20
  336. package/src/daemon/conversation-skill-tools.ts +1 -0
  337. package/src/daemon/conversation-store.ts +4 -4
  338. package/src/daemon/conversation-surface-snapshots.ts +135 -0
  339. package/src/daemon/conversation-surfaces.ts +113 -5
  340. package/src/daemon/conversation-tool-setup.ts +79 -6
  341. package/src/daemon/conversation-turn-finalize.ts +26 -13
  342. package/src/daemon/conversation.ts +215 -58
  343. package/src/daemon/daemon-control.ts +3 -7
  344. package/src/daemon/handlers/config-model.ts +7 -5
  345. package/src/daemon/handlers/shared.ts +55 -16
  346. package/src/daemon/host-cu-proxy.ts +51 -22
  347. package/src/daemon/lifecycle.ts +30 -13
  348. package/src/daemon/mcp-reload-service.ts +1 -1
  349. package/src/daemon/message-protocol.ts +0 -1
  350. package/src/daemon/message-provenance.ts +28 -4
  351. package/src/daemon/message-types/shared.ts +1 -0
  352. package/src/daemon/mode-session-startup-recovery.ts +23 -0
  353. package/src/daemon/mode-session-tracking.ts +54 -0
  354. package/src/daemon/orphan-reaper.ts +4 -3
  355. package/src/daemon/persist-media-references.ts +20 -3
  356. package/src/daemon/process-message.ts +13 -4
  357. package/src/daemon/tool-setup-types.ts +6 -0
  358. package/src/daemon/virtual-desktop-context.ts +21 -0
  359. package/src/daemon/wake-conversation-ops.ts +50 -15
  360. package/src/desktop/__tests__/fake-desktop.ts +1 -0
  361. package/src/desktop/desktop-accessibility-script.ts +88 -0
  362. package/src/desktop/desktop-accessibility.test.ts +160 -0
  363. package/src/desktop/desktop-accessibility.ts +169 -0
  364. package/src/desktop/desktop-automation-lease.test.ts +302 -64
  365. package/src/desktop/desktop-automation-lease.ts +129 -54
  366. package/src/desktop/desktop-browser-endpoint.ts +4 -0
  367. package/src/desktop/desktop-computer-use-routing.test.ts +330 -0
  368. package/src/desktop/desktop-computer-use.test.ts +449 -0
  369. package/src/desktop/desktop-computer-use.ts +502 -0
  370. package/src/desktop/desktop-dependencies.ts +47 -293
  371. package/src/desktop/desktop-display.ts +2 -2
  372. package/src/desktop/desktop-help.ts +15 -0
  373. package/src/desktop/desktop-panel-config.test.ts +13 -3
  374. package/src/desktop/desktop-panel-config.ts +109 -15
  375. package/src/desktop/desktop-session-manager.test.ts +69 -21
  376. package/src/desktop/desktop-session-manager.ts +76 -22
  377. package/src/desktop/desktop-stream-bridge.test.ts +76 -132
  378. package/src/desktop/desktop-stream-bridge.ts +9 -11
  379. package/src/desktop/desktop-wallpaper-renderer.ts +132 -0
  380. package/src/desktop/desktop-wallpaper-worker.ts +17 -0
  381. package/src/desktop/desktop-wallpaper.test.ts +48 -7
  382. package/src/desktop/desktop-wallpaper.ts +34 -102
  383. package/src/desktop/desktop-window-theme.ts +5 -25
  384. package/src/desktop/virtual-desktop-feature.ts +53 -3
  385. package/src/desktop/virtual-desktop-platform.test.ts +5 -9
  386. package/src/documents/document-store.ts +23 -0
  387. package/src/heartbeat/__tests__/heartbeat-service.test.ts +22 -26
  388. package/src/heartbeat/heartbeat-service.ts +5 -33
  389. package/src/ipc/__tests__/browser-ipc.test.ts +215 -6
  390. package/src/ipc/assistant-server.ts +2 -0
  391. package/src/ipc/routes/__tests__/channel-reply-ipc-routes.test.ts +111 -0
  392. package/src/ipc/routes/channel-reply-ipc-routes.ts +73 -0
  393. package/src/live-voice/__tests__/continuation-judge.test.ts +151 -0
  394. package/src/live-voice/__tests__/live-activity-reporter.test.ts +154 -15
  395. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +743 -31
  396. package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +191 -10
  397. package/src/live-voice/__tests__/live-voice-session-groups-gate.test.ts +87 -0
  398. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +5 -1
  399. package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +41 -0
  400. package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +1017 -9
  401. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +224 -1
  402. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +101 -0
  403. package/src/live-voice/__tests__/live-voice-tts.test.ts +44 -0
  404. package/src/live-voice/__tests__/live-voice-vad.test.ts +939 -75
  405. package/src/live-voice/__tests__/microphone-idle-gate.test.ts +87 -0
  406. package/src/live-voice/__tests__/session-controls.test.ts +23 -0
  407. package/src/live-voice/__tests__/task-outcomes.test.ts +117 -0
  408. package/src/live-voice/__tests__/voice-input-diagnostics.test.ts +117 -0
  409. package/src/live-voice/camera-mode-session.test.ts +265 -0
  410. package/src/live-voice/camera-mode-session.ts +277 -0
  411. package/src/live-voice/continuation-judge.ts +123 -0
  412. package/src/live-voice/live-activity-reporter.ts +115 -6
  413. package/src/live-voice/live-voice-manager.ts +36 -1
  414. package/src/live-voice/live-voice-photo.ts +88 -7
  415. package/src/live-voice/live-voice-session-manager.ts +15 -0
  416. package/src/live-voice/live-voice-session.ts +1443 -747
  417. package/src/live-voice/live-voice-tts.ts +22 -4
  418. package/src/live-voice/microphone-idle-gate.ts +56 -0
  419. package/src/live-voice/protocol.ts +171 -4
  420. package/src/live-voice/session-controls.ts +11 -3
  421. package/src/live-voice/task-outcomes.ts +131 -0
  422. package/src/live-voice/voice-input-diagnostics.ts +117 -0
  423. package/src/mcp/__tests__/manager-tool-caps.test.ts +156 -0
  424. package/src/mcp/__tests__/startup.test.ts +30 -7
  425. package/src/mcp/__tests__/tool-caps.test.ts +134 -0
  426. package/src/mcp/manager.ts +171 -101
  427. package/src/mcp/startup.ts +33 -13
  428. package/src/mcp/tool-caps.ts +184 -0
  429. package/src/media/__tests__/image-models.test.ts +58 -0
  430. package/src/media/image-credentials.ts +5 -0
  431. package/src/media/image-models.ts +52 -0
  432. package/src/media/image-service.ts +8 -0
  433. package/src/media/openrouter-image-service.test.ts +133 -0
  434. package/src/media/openrouter-image-service.ts +153 -0
  435. package/src/media/types.ts +1 -1
  436. package/src/messaging/provider-message-metadata.ts +3 -3
  437. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +65 -11
  438. package/src/messaging/providers/discord/send.ts +4 -17
  439. package/src/messaging/providers/discord/transport.ts +2 -2
  440. package/src/messaging/providers/outlook/client.ts +16 -22
  441. package/src/messaging/providers/telegram-bot/send.test.ts +236 -1
  442. package/src/messaging/providers/telegram-bot/send.ts +10 -7
  443. package/src/messaging/providers/telegram-bot/transport.ts +3 -10
  444. package/src/messaging/providers/whatsapp/send.test.ts +169 -4
  445. package/src/monitoring/__tests__/control.test.ts +17 -5
  446. package/src/monitoring/control.ts +15 -5
  447. package/src/notifications/AGENTS.md +1 -1
  448. package/src/notifications/README.md +83 -99
  449. package/src/notifications/__tests__/broadcaster.test.ts +1 -1
  450. package/src/notifications/__tests__/channel-allowlist.test.ts +39 -0
  451. package/src/notifications/__tests__/copy-composer.test.ts +71 -1
  452. package/src/notifications/__tests__/decision-engine.test.ts +79 -2
  453. package/src/notifications/__tests__/deterministic-checks.test.ts +10 -10
  454. package/src/notifications/__tests__/home-feed-side-effect.test.ts +93 -4
  455. package/src/notifications/__tests__/notification-utils.test.ts +18 -0
  456. package/src/notifications/adapters/macos.ts +37 -46
  457. package/src/notifications/broadcaster.ts +5 -6
  458. package/src/notifications/channel-allowlist.ts +44 -0
  459. package/src/notifications/copy-composer.ts +11 -26
  460. package/src/notifications/decision-engine.ts +24 -14
  461. package/src/notifications/deterministic-checks.ts +1 -1
  462. package/src/notifications/emit-signal.ts +123 -37
  463. package/src/notifications/home-feed-side-effect.ts +9 -7
  464. package/src/notifications/notification-utils.ts +19 -0
  465. package/src/notifications/schedule-result-producer.ts +4 -6
  466. package/src/notifications/signal.ts +4 -19
  467. package/src/notifications/types.ts +15 -0
  468. package/src/oauth/AGENTS.md +2 -0
  469. package/src/oauth/__tests__/identity-verifier.test.ts +36 -1
  470. package/src/oauth/connection-resolver.ts +1 -2
  471. package/src/oauth/identity-verifier.ts +24 -0
  472. package/src/oauth/oauth-store.ts +12 -4
  473. package/src/oauth/provider-serializer.ts +8 -0
  474. package/src/oauth/seed-providers.ts +42 -0
  475. package/src/onboarding/onboarding-events-store.ts +99 -12
  476. package/src/permissions/confirmation-guardian-request.test.ts +16 -0
  477. package/src/permissions/confirmation-guardian-request.ts +2 -3
  478. package/src/permissions/question-prompter.test.ts +31 -0
  479. package/src/permissions/question-prompter.ts +2 -0
  480. package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
  481. package/src/persistence/attachments-store.ts +84 -44
  482. package/src/persistence/client-connection-events-store.ts +377 -0
  483. package/src/persistence/conversation-crud.ts +166 -26
  484. package/src/persistence/conversation-mode-sessions.test.ts +424 -0
  485. package/src/persistence/conversation-mode-sessions.ts +460 -0
  486. package/src/persistence/conversation-plugin-facade.ts +30 -0
  487. package/src/persistence/conversation-queries.ts +6 -19
  488. package/src/persistence/conversation-tool-surface.ts +135 -0
  489. package/src/persistence/conversation-types.test.ts +32 -0
  490. package/src/persistence/conversation-types.ts +26 -4
  491. package/src/persistence/llm-usage-store.ts +3 -9
  492. package/src/persistence/message-metadata.ts +25 -0
  493. package/src/persistence/migrations/378-create-conversation-tool-surfaces.test.ts +78 -0
  494. package/src/persistence/migrations/378-create-conversation-tool-surfaces.ts +29 -0
  495. package/src/persistence/migrations/379-oauth-providers-response-ok-field.test.ts +92 -0
  496. package/src/persistence/migrations/379-oauth-providers-response-ok-field.ts +32 -0
  497. package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.test.ts +90 -0
  498. package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.ts +34 -0
  499. package/src/persistence/migrations/381-create-conversation-mode-sessions.ts +41 -0
  500. package/src/persistence/migrations/382-create-client-connection-events.ts +40 -0
  501. package/src/persistence/migrations/__tests__/382-create-client-connection-events.test.ts +56 -0
  502. package/src/persistence/schema/conversation-tool-surfaces.ts +32 -0
  503. package/src/persistence/schema/conversations.ts +67 -0
  504. package/src/persistence/schema/index.ts +1 -0
  505. package/src/persistence/schema/infrastructure.ts +29 -0
  506. package/src/persistence/schema/oauth.ts +1 -0
  507. package/src/persistence/steps.ts +41 -3
  508. package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
  509. package/src/plugin-api/conversation-turn.ts +31 -7
  510. package/src/plugin-api/effective-context-window.ts +33 -0
  511. package/src/plugin-api/index.ts +35 -6
  512. package/src/plugin-api/plugin-channel-turn-trust.test.ts +133 -0
  513. package/src/plugin-api/plugin-channel-turn-trust.ts +71 -0
  514. package/src/plugin-api/plugin-name-env.ts +125 -0
  515. package/src/plugin-api/resolve-credential.ts +79 -20
  516. package/src/plugin-api/vision-support.test.ts +22 -0
  517. package/src/plugin-api/vision-support.ts +17 -5
  518. package/src/plugins/__tests__/active-plugin-env.test.ts +136 -0
  519. package/src/plugins/active-plugin-env.ts +51 -0
  520. package/src/plugins/defaults/index.ts +24 -0
  521. package/src/plugins/defaults/memory/AGENTS.md +39 -5
  522. package/src/plugins/defaults/memory/__tests__/archive-removal-framing.test.ts +64 -0
  523. package/src/plugins/defaults/memory/__tests__/buffer-file.test.ts +365 -0
  524. package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +43 -0
  525. package/src/plugins/defaults/memory/__tests__/conversation-memory-purge.test.ts +1 -0
  526. package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +2 -0
  527. package/src/plugins/defaults/memory/__tests__/fixtures/buffer-appender.ts +17 -0
  528. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +74 -0
  529. package/src/plugins/defaults/memory/__tests__/memory-run-evidence.test.ts +161 -0
  530. package/src/plugins/defaults/memory/__tests__/relocated-memory-test-rows.ts +10 -0
  531. package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
  532. package/src/plugins/defaults/memory/buffer-file.ts +354 -0
  533. package/src/plugins/defaults/memory/buffer-format.ts +40 -0
  534. package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
  535. package/src/plugins/defaults/memory/context-search/agent-runner.ts +77 -22
  536. package/src/plugins/defaults/memory/context-search/format.ts +53 -8
  537. package/src/plugins/defaults/memory/context-search/limits.ts +10 -12
  538. package/src/plugins/defaults/memory/context-search/recall-input.ts +38 -0
  539. package/src/plugins/defaults/memory/context-search/search.ts +8 -14
  540. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +1 -0
  541. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +2 -1
  542. package/src/plugins/defaults/memory/context-search/sources/workspace.ts +2 -1
  543. package/src/plugins/defaults/memory/context-search/types.ts +1 -11
  544. package/src/plugins/defaults/memory/conversation-memory-purge.ts +4 -0
  545. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
  546. package/src/plugins/defaults/memory/graph/capability-seed.ts +1 -2
  547. package/src/plugins/defaults/memory/graph/tool-handlers.ts +13 -63
  548. package/src/plugins/defaults/memory/graph/tools.ts +35 -64
  549. package/src/plugins/defaults/memory/host-utils.ts +0 -10
  550. package/src/plugins/defaults/memory/injectors.ts +4 -3
  551. package/src/plugins/defaults/memory/memory-retrospective-job.ts +72 -183
  552. package/src/plugins/defaults/memory/memory-run-evidence.ts +213 -0
  553. package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
  554. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +6 -1
  555. package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
  556. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +407 -99
  557. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +10 -0
  558. package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +107 -7
  559. package/src/plugins/defaults/memory/substrate/consolidation-job.ts +307 -86
  560. package/src/plugins/defaults/memory/substrate/consolidation-tool-surface.ts +34 -0
  561. package/src/plugins/defaults/memory/substrate/page-index.ts +2 -1
  562. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +91 -51
  563. package/src/plugins/defaults/memory/substrate/sweep-job.ts +1 -1
  564. package/src/plugins/defaults/memory/tools.test.ts +124 -9
  565. package/src/plugins/defaults/memory/tools.ts +38 -11
  566. package/src/plugins/defaults/memory/v1/graph/consolidation.ts +2 -2
  567. package/src/plugins/defaults/memory/v1/graph/extraction.ts +2 -1
  568. package/src/plugins/defaults/memory/v1/graph/retriever.ts +1 -1
  569. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +5 -0
  570. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +5 -2
  571. package/src/plugins/defaults/memory/v2/reranker.ts +2 -1
  572. package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +81 -1
  573. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +87 -0
  574. package/src/plugins/defaults/memory/v3/__tests__/plugin-schema.test.ts +12 -0
  575. package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +332 -15
  576. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
  577. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +148 -28
  578. package/src/plugins/defaults/memory/v3/card.ts +2 -1
  579. package/src/plugins/defaults/memory/v3/injector.ts +212 -178
  580. package/src/plugins/defaults/memory/v3/orchestrate.ts +159 -32
  581. package/src/plugins/defaults/memory/v3/plugin-schema.ts +54 -4
  582. package/src/plugins/defaults/memory/v3/pool-log-store.ts +275 -37
  583. package/src/plugins/defaults/memory/v3/pool-select.test.ts +47 -5
  584. package/src/plugins/defaults/memory/v3/pool-select.ts +710 -59
  585. package/src/plugins/defaults/memory/v3/sections.ts +2 -1
  586. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +41 -14
  587. package/src/plugins/defaults/memory/worker-control.ts +15 -5
  588. package/src/plugins/defaults/task-progress/__tests__/registration.test.ts +70 -0
  589. package/src/plugins/defaults/task-progress/__tests__/task-progress-context.test.ts +380 -0
  590. package/src/plugins/defaults/task-progress/hooks/post-compact.ts +19 -0
  591. package/src/plugins/defaults/task-progress/hooks/user-prompt-submit.ts +24 -0
  592. package/src/plugins/defaults/task-progress/package.json +14 -0
  593. package/src/plugins/defaults/task-progress/src/apply-task-progress-context.ts +93 -0
  594. package/src/plugins/defaults/task-progress/src/format-task-progress-context.ts +67 -0
  595. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +4 -1
  596. package/src/plugins/defaults/tool-result-truncate/terminal.ts +1 -46
  597. package/src/prompts/__tests__/parallel-tasks-section.test.ts +25 -0
  598. package/src/prompts/delegation-gate.ts +57 -0
  599. package/src/prompts/system-prompt.ts +14 -32
  600. package/src/providers/__tests__/context-overflow-error.test.ts +10 -0
  601. package/src/providers/__tests__/search-provider-catalog.test.ts +18 -0
  602. package/src/providers/anthropic/client.ts +10 -1
  603. package/src/providers/anthropic-gateway-shared.ts +6 -0
  604. package/src/providers/fetch-provider-catalog.ts +11 -0
  605. package/src/providers/gemini/client.ts +25 -8
  606. package/src/providers/inference/adapter-factory.ts +6 -0
  607. package/src/providers/jev/client.test.ts +270 -0
  608. package/src/providers/jev/client.ts +534 -0
  609. package/src/providers/model-catalog.ts +59 -3
  610. package/src/providers/openai/__tests__/chat-completions-extra-body.test.ts +94 -1
  611. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +106 -1
  612. package/src/providers/openai/__tests__/chat-template-flatten.test.ts +24 -0
  613. package/src/providers/openai/__tests__/google-thought-signature.test.ts +1 -2
  614. package/src/providers/openai/chat-completions-provider.ts +100 -29
  615. package/src/providers/openai/google-thought-signature.ts +0 -6
  616. package/src/providers/openai/responses-provider.ts +23 -1
  617. package/src/providers/ratelimit.ts +1 -3
  618. package/src/providers/search-provider-catalog.ts +24 -0
  619. package/src/providers/server-tool-pairing.ts +16 -7
  620. package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +24 -0
  621. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +7 -1
  622. package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +50 -1
  623. package/src/providers/speech-to-text/deepgram-flux-frames.ts +11 -0
  624. package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +13 -0
  625. package/src/providers/types.ts +5 -0
  626. package/src/routes/control.ts +7 -5
  627. package/src/runtime/AGENTS.md +6 -4
  628. package/src/runtime/__tests__/agent-wake.test.ts +94 -1
  629. package/src/runtime/actor-trust-resolver.ts +3 -3
  630. package/src/runtime/agent-wake.ts +32 -5
  631. package/src/runtime/approval-message-composer.ts +3 -69
  632. package/src/runtime/assistant-event-hub.ts +73 -75
  633. package/src/runtime/assistant-event-publish-options.ts +7 -0
  634. package/src/runtime/assistant-event-targeting.ts +79 -0
  635. package/src/runtime/assistant-stream-state.ts +13 -100
  636. package/src/runtime/background-job-runner.ts +5 -5
  637. package/src/runtime/channel-retry-sweep.ts +1 -0
  638. package/src/runtime/guardian-action-message-composer.ts +8 -161
  639. package/src/runtime/guardian-action-service.ts +2 -17
  640. package/src/runtime/guardian-reply-router.ts +29 -40
  641. package/src/runtime/http-server.ts +2 -2
  642. package/src/runtime/http-types.ts +6 -0
  643. package/src/runtime/message-composer-types.ts +3 -61
  644. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +67 -1
  645. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +89 -0
  646. package/src/runtime/migrations/vbundle-builder.ts +24 -1
  647. package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -4
  648. package/src/runtime/migrations/vbundle-import-policy.ts +43 -11
  649. package/src/runtime/migrations/vbundle-importer.ts +4 -1
  650. package/src/runtime/migrations/vbundle-streaming-importer.ts +4 -1
  651. package/src/runtime/migrations/vbundle-validator.ts +1 -0
  652. package/src/runtime/pending-interactions-mode-session.test.ts +62 -0
  653. package/src/runtime/pending-interactions.ts +29 -0
  654. package/src/runtime/routes/__tests__/client-history-routes.test.ts +104 -0
  655. package/src/runtime/routes/__tests__/image-generation-routes.test.ts +97 -0
  656. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +24 -2
  657. package/src/runtime/routes/__tests__/roadmap-routes.test.ts +29 -6
  658. package/src/runtime/routes/browser-context.ts +31 -11
  659. package/src/runtime/routes/browser-routes.ts +43 -4
  660. package/src/runtime/routes/btw-routes.ts +9 -4
  661. package/src/runtime/routes/channel-route-shared.ts +1 -9
  662. package/src/runtime/routes/client-routes.ts +108 -0
  663. package/src/runtime/routes/conversation-management-routes.ts +4 -1
  664. package/src/runtime/routes/conversation-routes.ts +125 -14
  665. package/src/runtime/routes/credential-prompt-routes.ts +4 -3
  666. package/src/runtime/routes/credential-routes.ts +1 -2
  667. package/src/runtime/routes/desktop-setup-routes.test.ts +9 -18
  668. package/src/runtime/routes/desktop-setup-routes.ts +8 -7
  669. package/src/runtime/routes/documents-routes.ts +51 -0
  670. package/src/runtime/routes/email-routes.ts +3 -7
  671. package/src/runtime/routes/events-routes.ts +75 -54
  672. package/src/runtime/routes/guardian-approval-interception.ts +24 -0
  673. package/src/runtime/routes/identity-routes.ts +1 -5
  674. package/src/runtime/routes/image-generation-routes.ts +8 -14
  675. package/src/runtime/routes/inbound-message-handler.ts +37 -41
  676. package/src/runtime/routes/inbound-stages/backfill-sender-provenance.test.ts +168 -0
  677. package/src/runtime/routes/inbound-stages/backfill-sender-provenance.ts +96 -0
  678. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +39 -10
  679. package/src/runtime/routes/inbound-stages/background-dispatch.ts +9 -9
  680. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -0
  681. package/src/runtime/routes/inference-profile-session-handler.ts +11 -1
  682. package/src/runtime/routes/inference-profiles-routes.ts +9 -0
  683. package/src/runtime/routes/llm-context-normalization.ts +1 -7
  684. package/src/runtime/routes/migration-routes.ts +73 -2
  685. package/src/runtime/routes/notification-routes.ts +10 -0
  686. package/src/runtime/routes/oauth-commands-routes.ts +57 -54
  687. package/src/runtime/routes/oauth-providers.ts +11 -0
  688. package/src/runtime/routes/oauth-request-hints.test.ts +246 -0
  689. package/src/runtime/routes/oauth-request-hints.ts +149 -0
  690. package/src/runtime/routes/plugins-routes.ts +6 -0
  691. package/src/runtime/routes/roadmap-routes.ts +47 -8
  692. package/src/runtime/routes/schedule-routes.ts +2 -0
  693. package/src/runtime/routes/secret-routes.ts +99 -119
  694. package/src/runtime/routes/settings-routes.ts +10 -4
  695. package/src/runtime/routes/watcher-routes.ts +1 -3
  696. package/src/runtime/trust-class.test.ts +7 -6
  697. package/src/runtime/trust-class.ts +9 -17
  698. package/src/schedule/__tests__/worker-control.test.ts +36 -5
  699. package/src/schedule/__tests__/worker-mcp-bootstrap.test.ts +107 -0
  700. package/src/schedule/__tests__/worker-mcp-readiness.test.ts +173 -0
  701. package/src/schedule/__tests__/worker-mcp-tools.test.ts +13 -47
  702. package/src/schedule/run-script.ts +2 -2
  703. package/src/schedule/scheduler.ts +47 -11
  704. package/src/schedule/tool-surface-readiness.ts +65 -0
  705. package/src/schedule/worker-control.ts +15 -5
  706. package/src/schedule/worker-mcp.ts +85 -0
  707. package/src/schedule/worker.ts +9 -31
  708. package/src/security/secure-keys.ts +74 -112
  709. package/src/skills/clawhub.ts +3 -8
  710. package/src/skills/managed-store.ts +1 -5
  711. package/src/stt/types.ts +4 -0
  712. package/src/subagent/notify.ts +54 -34
  713. package/src/subagent/parent-notification.ts +6 -0
  714. package/src/telemetry/__tests__/phone-call-funnel.test.ts +72 -0
  715. package/src/telemetry/phone-call-funnel.ts +144 -0
  716. package/src/tools/__tests__/tool-schema-root-combinator-guard.test.ts +81 -0
  717. package/src/tools/ask-question/ask-question-tool.test.ts +167 -5
  718. package/src/tools/ask-question/ask-question-tool.ts +120 -22
  719. package/src/tools/browser/browser-execution.ts +29 -60
  720. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +561 -39
  721. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +435 -39
  722. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +1 -8
  723. package/src/tools/client-os.ts +15 -0
  724. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
  725. package/src/tools/computer-use/target.ts +42 -0
  726. package/src/tools/document/document-tool.ts +13 -18
  727. package/src/tools/execution-target.ts +14 -16
  728. package/src/tools/host-terminal/host-shell.ts +16 -7
  729. package/src/tools/network/__tests__/web-fetch-tinyfish.test.ts +250 -0
  730. package/src/tools/network/__tests__/web-search.test.ts +203 -0
  731. package/src/tools/network/web-fetch.ts +274 -7
  732. package/src/tools/network/web-search.ts +468 -6
  733. package/src/tools/permission-checker.ts +3 -3
  734. package/src/tools/policy-context.ts +3 -1
  735. package/src/tools/shared/filesystem/file-ops-service.ts +1 -31
  736. package/src/tools/shared/shell-output.test.ts +10 -0
  737. package/src/tools/shared/shell-output.ts +14 -2
  738. package/src/tools/skills/load.ts +2 -1
  739. package/src/tools/skills/sandbox-runner.ts +24 -4
  740. package/src/tools/skills/scaffold-managed.ts +2 -1
  741. package/src/tools/skills/skill-script-runner.ts +7 -0
  742. package/src/tools/skills/skill-tool-factory.ts +15 -1
  743. package/src/tools/terminal/__tests__/safe-env.test.ts +44 -4
  744. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -14
  745. package/src/tools/terminal/safe-env.ts +39 -24
  746. package/src/tools/terminal/sanitized-bash.ts +15 -2
  747. package/src/tools/terminal/shell-launch.test.ts +162 -0
  748. package/src/tools/terminal/shell.test.ts +29 -0
  749. package/src/tools/terminal/shell.ts +15 -7
  750. package/src/tools/tool-approval-handler.ts +5 -1
  751. package/src/tools/tool-types.ts +3 -3
  752. package/src/tools/types.ts +8 -2
  753. package/src/util/__tests__/worker-process-command.test.ts +5 -4
  754. package/src/util/abort-reasons.ts +18 -26
  755. package/src/util/browser-human-verification.ts +14 -0
  756. package/src/util/canonicalize-identity.test.ts +21 -0
  757. package/src/util/canonicalize-identity.ts +16 -0
  758. package/src/util/errors.ts +13 -3
  759. package/src/util/host-process.test.ts +17 -1
  760. package/src/util/host-process.ts +24 -0
  761. package/src/util/provider-error-patterns.ts +3 -0
  762. package/src/util/unicode.ts +29 -0
  763. package/src/util/worker-process.ts +77 -35
  764. package/src/workspace/migrations/157-add-desktop-files-launcher.ts +94 -0
  765. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +4 -10
  766. package/src/workspace/migrations/__tests__/157-add-desktop-files-launcher.test.ts +113 -0
  767. package/src/workspace/migrations/registry.ts +2 -0
  768. package/src/__tests__/computer-use-window-schema.test.ts +0 -24
  769. package/src/api/events/heartbeat-alert.ts +0 -20
  770. package/src/daemon/message-types/web-activity.ts +0 -65
  771. package/src/desktop/desktop-dependencies.test.ts +0 -131
  772. package/src/tools/computer-use/definitions.ts +0 -607
package/src/agent/loop.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  import type { AnsweredQuestion } from "../api/events/question-answered.js";
2
+ import type { ToolActivityMetadata } from "../api/events/tool-result.js";
3
+ import { resolveCallSiteConfig } from "../config/llm-resolver.js";
4
+ import { getConfig } from "../config/loader.js";
2
5
  import type { LLMCallSite } from "../config/schemas/llm.js";
3
6
  import { SEND_USER_MESSAGE_TOOL_NAME } from "../config/send-user-message-constants.js";
4
7
  import { recordEstimate } from "../context/estimator-calibration.js";
@@ -11,7 +14,6 @@ import {
11
14
  getCalibrationProviderKey,
12
15
  } from "../context/token-estimator.js";
13
16
  import { spoolAndStubOversizedToolResults } from "../context/tool-result-spool.js";
14
- import type { ToolActivityMetadata } from "../daemon/message-types/web-activity.js";
15
17
  import { parseActualTokensFromError } from "../daemon/parse-actual-tokens-from-error.js";
16
18
  import type { TrustContext } from "../daemon/trust-context-types.js";
17
19
  import type {
@@ -42,6 +44,7 @@ import type {
42
44
  Provider,
43
45
  ProviderResponse,
44
46
  SendMessageOptions,
47
+ TextContent,
45
48
  ToolDefinition,
46
49
  ToolResultContent,
47
50
  } from "../providers/types.js";
@@ -74,6 +77,7 @@ import {
74
77
  isRepairableOrderingError,
75
78
  isUserTerminalHistoryError,
76
79
  } from "./history-repair/history-repair.js";
80
+ import { buildToolResultFollowUp } from "./tool-result-follow-up.js";
77
81
 
78
82
  const log = getLogger("agent-loop");
79
83
 
@@ -441,25 +445,26 @@ export type AgentEvent =
441
445
  /**
442
446
  * Emitted when the provider call throws — i.e. the provider
443
447
  * rejected the request before returning a usable response. Carries
444
- * the loop-level raw request we attempted to send (messages, tools,
445
- * system prompt, provider-agnostic config) plus the thrown error.
448
+ * the wire request we attempted to send plus the thrown error.
446
449
  * Consumers (`handleProviderError` in the daemon handlers, the
447
450
  * `onEvent` in `agent-wake`) persist these as `llm_request_logs`
448
451
  * rows so failed calls are queryable in the LLM inspector instead
449
452
  * of only surfacing in pino logs.
450
453
  *
451
- * `rawRequest` is the loop-level abstract shape rather than the
452
- * provider-specific payload (which the provider builds internally
453
- * and never returns when it throws). `actualProvider` echoes the
454
- * `ProviderError.provider` tag when available so the persisted row
455
- * has the same `provider` column value as a successful `usage` row.
454
+ * `rawRequest` is `ProviderError.rawRequest` when the throw carried
455
+ * an inspectable SDK/wire payload (including extra body fields such
456
+ * as `directions`). The loop does not invent a substitute snapshot
457
+ * of messages/tools/systemPrompt; a missing payload stays missing.
458
+ * `actualProvider` echoes `ProviderError.provider` so a routed
459
+ * invocation (e.g. Vellum via a Fireworks default wrapper) is
460
+ * attributed to the transport that actually ran.
456
461
  *
457
462
  * Re-thrown by the inner LLM-call try/catch after emission so the
458
463
  * outer agent-loop catch still handles abort, the existing `error`
459
464
  * event, and the loop break.
460
465
  */
461
466
  type: "provider_error";
462
- rawRequest: unknown;
467
+ rawRequest?: unknown;
463
468
  error: Error;
464
469
  actualProvider?: string;
465
470
  }
@@ -661,6 +666,18 @@ type AgentLoopContextWindowResolver = () => {
661
666
  overflowRecovery: { enabled: boolean; safetyMarginRatio: number };
662
667
  };
663
668
 
669
+ /** Final request surface after the pre-model hook has settled. */
670
+ export interface PreparedModelCall {
671
+ callSite?: LLMCallSite;
672
+ overrideProfile?: string;
673
+ forceOverrideProfile: boolean;
674
+ /** Present when the finalized route opts out of prompt caching. */
675
+ disableCache?: true;
676
+ signal?: AbortSignal;
677
+ systemPrompt: string | null;
678
+ tools: ToolDefinition[];
679
+ }
680
+
664
681
  interface AgentLoopRunOptionsBase {
665
682
  /** Input history the run starts from; the loop appends its output onto a copy. */
666
683
  messages: Message[];
@@ -688,7 +705,10 @@ interface AgentLoopRunOptionsBase {
688
705
  onCheckpoint?: (
689
706
  checkpoint: CheckpointInfo,
690
707
  ) => CheckpointDecision | Promise<CheckpointDecision>;
708
+ /** Semantic call site exposed to hooks, events, and loop behavior. */
691
709
  callSite?: LLMCallSite;
710
+ /** Provider-resolution call site when it differs from turn semantics. */
711
+ inferenceCallSite?: LLMCallSite;
692
712
  /**
693
713
  * Route this run's user-facing text through the `send_user_message` tool
694
714
  * instead of streamed assistant text. The daemon sets it for main-agent runs
@@ -738,6 +758,8 @@ interface AgentLoopRunOptionsBase {
738
758
  */
739
759
  forceOverrideProfile?: boolean;
740
760
  resolveOverrideProfile?: () => string | undefined;
761
+ /** Observe a finalized model request without delaying provider dispatch. */
762
+ onModelCallPrepared?: (prepared: PreparedModelCall) => void;
741
763
  /**
742
764
  * When `true`, the loop owns turn-start and mid-loop compaction. The pre-call
743
765
  * budget gate runs before the very first provider call — subsuming the
@@ -1047,6 +1069,17 @@ export interface AgentLoopConstructorOptions {
1047
1069
  tools?: ToolDefinition[];
1048
1070
  toolExecutor?: LoopToolExecutor;
1049
1071
  resolveTools?: (history: Message[]) => ToolDefinition[];
1072
+ /**
1073
+ * Observer for the final tool array of each provider call, invoked
1074
+ * immediately before the request leaves with exactly what goes on the wire
1075
+ * (after any provider-native tool is appended, past the inter-call throttle
1076
+ * and the pre-model hooks, and not at all once the run is aborted). This is
1077
+ * the only point that sees the sent array: the dynamic `resolveTools`
1078
+ * callback is also consulted out of band (token counting, compaction
1079
+ * estimates), so a consumer that needs "what the last request sent"
1080
+ * subscribes here rather than wrapping the resolver. Must not throw.
1081
+ */
1082
+ onToolsSent?: (tools: ToolDefinition[]) => void;
1050
1083
  /**
1051
1084
  * Conversation this loop drives. Scopes the loop-held compaction circuit
1052
1085
  * breaker and is the source of truth the loop's pipeline contexts and
@@ -1087,6 +1120,7 @@ export class AgentLoop {
1087
1120
  private config: AgentLoopConfig;
1088
1121
  private tools: ToolDefinition[];
1089
1122
  private resolveTools: ((history: Message[]) => ToolDefinition[]) | null;
1123
+ private onToolsSent: ((tools: ToolDefinition[]) => void) | null;
1090
1124
  private toolExecutor: LoopToolExecutor | null;
1091
1125
 
1092
1126
  /**
@@ -1122,6 +1156,7 @@ export class AgentLoop {
1122
1156
  tools,
1123
1157
  toolExecutor,
1124
1158
  resolveTools,
1159
+ onToolsSent,
1125
1160
  conversationId,
1126
1161
  resolveConversationDir,
1127
1162
  transformCompactedHistory,
@@ -1131,6 +1166,7 @@ export class AgentLoop {
1131
1166
  this.config = { ...DEFAULT_CONFIG, ...config };
1132
1167
  this.tools = tools ?? [];
1133
1168
  this.resolveTools = resolveTools ?? null;
1169
+ this.onToolsSent = onToolsSent ?? null;
1134
1170
  this.toolExecutor = toolExecutor ?? null;
1135
1171
  this.conversationId = conversationId;
1136
1172
  this.resolveConversationDir = resolveConversationDir ?? null;
@@ -1413,18 +1449,21 @@ export class AgentLoop {
1413
1449
  requestId,
1414
1450
  onCheckpoint,
1415
1451
  callSite,
1452
+ inferenceCallSite,
1416
1453
  suppressAssistantText = false,
1417
1454
  supportsDynamicUi = true,
1418
1455
  trust,
1419
1456
  overrideProfile,
1420
1457
  forceOverrideProfile = false,
1421
1458
  resolveOverrideProfile,
1459
+ onModelCallPrepared,
1422
1460
  compactInPlace = false,
1423
1461
  isNonInteractive = false,
1424
1462
  model: runModel,
1425
1463
  latencyTracker,
1426
1464
  injectionLedgerResets,
1427
1465
  } = options;
1466
+ const providerCallSite = inferenceCallSite ?? callSite;
1428
1467
  // Snapshot the system prompt once per run. The instance field is mutable
1429
1468
  // (the conversation may update it between turns), but a single run must
1430
1469
  // use one consistent prompt — an aborted run left detached after the
@@ -1544,7 +1583,7 @@ export class AgentLoop {
1544
1583
  turn: number,
1545
1584
  ): Promise<{
1546
1585
  resultBlocks: ContentBlock[];
1547
- additionalContextBlocks: ContentBlock[];
1586
+ additionalContextBlocks: TextContent[];
1548
1587
  }> => {
1549
1588
  if (conversationDir) {
1550
1589
  const toolCallByUseId = new Map(
@@ -1569,7 +1608,7 @@ export class AgentLoop {
1569
1608
  180_000;
1570
1609
 
1571
1610
  const resultBlocks: ContentBlock[] = [];
1572
- const additionalContextBlocks: ContentBlock[] = [];
1611
+ const additionalContextBlocks: TextContent[] = [];
1573
1612
  for (const block of rawBlocks) {
1574
1613
  if (block.type !== "tool_result") {
1575
1614
  resultBlocks.push(block);
@@ -1870,7 +1909,7 @@ export class AgentLoop {
1870
1909
  // unexecutable client tool. The advisor consult's `advisorProfile` can
1871
1910
  // route `subagentSpawn` to a provider/model whose native-search support
1872
1911
  // differs from the construction-time default, so the gate resolves the
1873
- // routed target (callSite + overrideProfile) via
1912
+ // routed target (providerCallSite + overrideProfile) via
1874
1913
  // `supportsNativeWebSearchFor` rather than the static
1875
1914
  // `this.provider.supportsNativeWebSearch` snapshot; providers without
1876
1915
  // the routing-aware probe fall back to the static flag. This is a SERVER
@@ -1882,7 +1921,7 @@ export class AgentLoop {
1882
1921
  .supportsNativeWebSearchFor
1883
1922
  ? this.provider.supportsNativeWebSearchFor(
1884
1923
  buildNativeWebSearchProbeOptions(
1885
- callSite,
1924
+ providerCallSite,
1886
1925
  resolveEffectiveOverrideProfile(),
1887
1926
  forceOverrideProfile,
1888
1927
  this.conversationId,
@@ -1901,11 +1940,11 @@ export class AgentLoop {
1901
1940
  // 1. Per-run explicit (`runModel`)
1902
1941
  // 2. Call-site resolved values (filled by
1903
1942
  // `RetryProvider.normalizeSendMessageOptions` from
1904
- // `resolveCallSiteConfig(callSite, llm)`)
1943
+ // `resolveCallSiteConfig(providerCallSite, llm)`)
1905
1944
  // 3. Conversation defaults (`this.config.*`, from the resolved
1906
1945
  // default call-site config)
1907
1946
  //
1908
- // When `callSite` is present we deliberately leave
1947
+ // When `providerCallSite` is present we deliberately leave
1909
1948
  // `max_tokens`/`thinking`/`effort`/`speed` *unset* in `providerConfig`
1910
1949
  // so the normalizer can fill them from the call-site resolution. The
1911
1950
  // normalizer only writes these fields when they're undefined; if we
@@ -1913,10 +1952,10 @@ export class AgentLoop {
1913
1952
  // for these knobs is silently ignored.
1914
1953
  //
1915
1954
  // `toolChoice` and `cacheTtl` are not part of the call-site schema, so
1916
- // they always come from `this.config` regardless of `callSite`.
1955
+ // they always come from `this.config` regardless of `providerCallSite`.
1917
1956
  const providerConfig: Record<string, unknown> = {};
1918
1957
 
1919
- if (!callSite) {
1958
+ if (!providerCallSite) {
1920
1959
  providerConfig.max_tokens = this.config.maxTokens;
1921
1960
  }
1922
1961
 
@@ -1924,7 +1963,7 @@ export class AgentLoop {
1924
1963
  providerConfig.model = runModel;
1925
1964
  }
1926
1965
 
1927
- if (!callSite) {
1966
+ if (!providerCallSite) {
1928
1967
  const thinking = normalizeThinkingConfigForWire(this.config.thinking);
1929
1968
  if (thinking !== undefined) {
1930
1969
  providerConfig.thinking = thinking;
@@ -1963,9 +2002,9 @@ export class AgentLoop {
1963
2002
  // defaults when absent).
1964
2003
  // User-initiated conversation turns default to `mainAgent` in the
1965
2004
  // agent loop's caller; other invocation contexts (heartbeat, filing,
1966
- // analyze, etc.) pass their own `callSite`.
1967
- if (callSite) {
1968
- providerConfig.callSite = callSite;
2005
+ // analyze, etc.) pass their own provider-resolution site.
2006
+ if (providerCallSite) {
2007
+ providerConfig.callSite = providerCallSite;
1969
2008
  providerConfig.usageTracking = "manual";
1970
2009
  // Per-conversation seed for deterministic `mix`-profile expansion.
1971
2010
  // Sourced from the loop's own conversation id so every LLM call in a
@@ -1993,7 +2032,7 @@ export class AgentLoop {
1993
2032
  // `activeProfile` and any call-site named profile. Threading it on
1994
2033
  // every send (rather than once at construction) keeps subagents that
1995
2034
  // share an `AgentLoop` instance but ought to inherit a different
1996
- // profile correct — and matches how `callSite` is plumbed.
2035
+ // profile correct, matching how the provider call site is plumbed.
1997
2036
  const effectiveOverrideProfile = resolveEffectiveOverrideProfile();
1998
2037
  if (effectiveOverrideProfile) {
1999
2038
  providerConfig.overrideProfile = effectiveOverrideProfile;
@@ -2217,6 +2256,49 @@ export class AgentLoop {
2217
2256
  );
2218
2257
  }
2219
2258
 
2259
+ if (onModelCallPrepared && !signal?.aborted) {
2260
+ const preparedOverrideProfile =
2261
+ typeof providerConfig.overrideProfile === "string" &&
2262
+ providerConfig.overrideProfile.length > 0
2263
+ ? providerConfig.overrideProfile
2264
+ : undefined;
2265
+ try {
2266
+ const preparedForceOverrideProfile =
2267
+ providerConfig.forceOverrideProfile === true;
2268
+ const disableCache =
2269
+ providerCallSite !== undefined &&
2270
+ resolveCallSiteConfig(providerCallSite, getConfig().llm, {
2271
+ ...(preparedOverrideProfile !== undefined
2272
+ ? { overrideProfile: preparedOverrideProfile }
2273
+ : {}),
2274
+ ...(preparedForceOverrideProfile
2275
+ ? { forceOverrideProfile: true }
2276
+ : {}),
2277
+ ...(this.conversationId !== undefined
2278
+ ? { selectionSeed: this.conversationId }
2279
+ : {}),
2280
+ }).disableCache === true;
2281
+ onModelCallPrepared({
2282
+ ...(providerCallSite !== undefined
2283
+ ? { callSite: providerCallSite }
2284
+ : {}),
2285
+ ...(preparedOverrideProfile !== undefined
2286
+ ? { overrideProfile: preparedOverrideProfile }
2287
+ : {}),
2288
+ forceOverrideProfile: preparedForceOverrideProfile,
2289
+ ...(disableCache ? { disableCache: true as const } : {}),
2290
+ ...(signal !== undefined ? { signal } : {}),
2291
+ systemPrompt: providerOptions.systemPrompt ?? null,
2292
+ tools: currentTools,
2293
+ });
2294
+ } catch (preparedError) {
2295
+ rlog.warn(
2296
+ { err: preparedError },
2297
+ "Prepared model-call observer failed; continuing with provider dispatch",
2298
+ );
2299
+ }
2300
+ }
2301
+
2220
2302
  // Announce the LLM-call boundary so downstream handlers (the
2221
2303
  // daemon's persistence pipeline) can reserve an empty assistant row
2222
2304
  // and stamp the resulting `messageId` onto every streaming event the
@@ -2234,13 +2316,18 @@ export class AgentLoop {
2234
2316
  // turn body (tool execution, plugin pipelines, checkpoints), so
2235
2317
  // recording there would risk mis-attributing tool/plugin throws as
2236
2318
  // provider rejections. On provider failure we emit `provider_error`
2237
- // with the loop-level raw request so consumers can persist it as an
2238
- // `llm_request_logs` row, then re-throw so the existing outer catch
2239
- // continues to handle abort sync, the `error` event, and the loop
2240
- // break unchanged.
2319
+ // with the inspectable wire request from the throw (when present)
2320
+ // so consumers can persist it as an `llm_request_logs` row, then
2321
+ // re-throw so the existing outer catch continues to handle abort
2322
+ // sync, the `error` event, and the loop break unchanged.
2241
2323
  // Latency: the request is about to leave for the provider. The span
2242
2324
  // from here to the first streamed token is time-to-first-token.
2243
2325
  latencyTracker?.mark("request_sent");
2326
+ // Every await that could cancel the call is behind us; a run aborted
2327
+ // during the throttle or a hook never reports an array it did not send.
2328
+ if (!signal?.aborted) {
2329
+ this.onToolsSent?.(currentTools);
2330
+ }
2244
2331
  let response: ProviderResponse;
2245
2332
  try {
2246
2333
  response = await traceAsyncSection("agent-loop:provider-send", () =>
@@ -2255,26 +2342,18 @@ export class AgentLoop {
2255
2342
  llmCallError instanceof Error
2256
2343
  ? llmCallError
2257
2344
  : new Error(String(llmCallError));
2258
- // Strip non-serializable / runtime-only fields from `options`
2259
- // before snapshotting. `onEvent` is a closure with side effects
2260
- // and `signal` is an AbortSignal — neither is meaningful in a
2261
- // persisted log row, and `JSON.stringify` would silently drop or
2262
- // misrepresent both.
2263
- const rawRequest = {
2264
- provider: this.provider.name,
2265
- messages: sanitizedHistory,
2266
- tools: providerOptions.tools,
2267
- systemPrompt: providerOptions.systemPrompt,
2268
- config: providerOptions.config,
2269
- };
2345
+ const invocationProvider =
2346
+ errInstance instanceof ProviderError
2347
+ ? errInstance.provider
2348
+ : this.provider.name;
2270
2349
  onEvent({
2271
2350
  type: "provider_error",
2272
- rawRequest,
2351
+ ...(errInstance instanceof ProviderError &&
2352
+ errInstance.rawRequest !== undefined
2353
+ ? { rawRequest: errInstance.rawRequest }
2354
+ : {}),
2273
2355
  error: errInstance,
2274
- actualProvider:
2275
- errInstance instanceof ProviderError
2276
- ? errInstance.provider
2277
- : this.provider.name,
2356
+ actualProvider: invocationProvider,
2278
2357
  });
2279
2358
  }
2280
2359
  providerCallError = llmCallError;
@@ -2945,16 +3024,20 @@ export class AgentLoop {
2945
3024
 
2946
3025
  toolUseTurns++;
2947
3026
 
2948
- // Append any guidance a post-tool-use hook surfaced via
2949
- // `additionalContext` (e.g. tool-error retry coaching) as separate
2950
- // blocks. They join the provider-bound history below but were not part
2951
- // of the tool_result events emitted above, so the model sees the
2952
- // guidance while the client-facing and persisted tool output stay the
2953
- // tool's actual result.
2954
- resultBlocks.push(...additionalContextBlocks);
2955
-
2956
- // Add tool results as a user message and continue the loop.
2957
- history.push({ role: "user", content: resultBlocks });
3027
+ // Add the tool results, plus any guidance a post-tool-use hook
3028
+ // surfaced via `additionalContext` (e.g. tool-error retry coaching),
3029
+ // as a user message and continue the loop. The guidance joins the
3030
+ // provider-bound history only: it was not part of the tool_result
3031
+ // events emitted above, so the client-facing and persisted tool
3032
+ // output stay the tool's actual result.
3033
+ history.push({
3034
+ role: "user",
3035
+ content: buildToolResultFollowUp(
3036
+ history,
3037
+ resultBlocks,
3038
+ additionalContextBlocks,
3039
+ ),
3040
+ });
2958
3041
 
2959
3042
  // Invoke checkpoint callback after tool results are in history.
2960
3043
  // Handoff takes precedence over the budget gate: a handoff decision
@@ -0,0 +1,70 @@
1
+ // Content of the user message that answers a tool-calling assistant turn:
2
+ // the tool_result blocks plus any guidance a post-tool-use hook surfaced via
3
+ // `additionalContext`.
4
+
5
+ import { analyzeServerToolPairing } from "../providers/server-tool-pairing.js";
6
+ import type {
7
+ ContentBlock,
8
+ Message,
9
+ TextContent,
10
+ ToolResultContent,
11
+ } from "../providers/types.js";
12
+
13
+ /**
14
+ * Hook guidance rides as separate blocks after the results, so the model sees
15
+ * it while each tool_result stays the tool's actual output. The exception is
16
+ * an assistant turn that left a server tool (native web search) deferred: the
17
+ * provider runs a deferred server tool only when the answering message holds
18
+ * tool_result blocks alone, and any block after the results closes the
19
+ * assistant turn, after which the provider rejects the unanswered server tool
20
+ * as unpaired. The guidance is then folded into the content of the last
21
+ * errored tool_result (the last tool_result when none errored), where the
22
+ * model still sees it and the search still runs.
23
+ */
24
+ export function buildToolResultFollowUp(
25
+ history: ReadonlyArray<Message>,
26
+ resultBlocks: ContentBlock[],
27
+ additionalContextBlocks: ReadonlyArray<TextContent>,
28
+ ): ContentBlock[] {
29
+ if (additionalContextBlocks.length === 0) {
30
+ return resultBlocks;
31
+ }
32
+ const targetIndex = foldTargetIndex(resultBlocks);
33
+ const pairing = analyzeServerToolPairing([
34
+ ...history,
35
+ { role: "user", content: resultBlocks },
36
+ ]);
37
+ if (pairing.deferredUseIds.size === 0 || targetIndex < 0) {
38
+ return [...resultBlocks, ...additionalContextBlocks];
39
+ }
40
+ const target = resultBlocks[targetIndex] as ToolResultContent;
41
+ const folded: ToolResultContent = {
42
+ ...target,
43
+ content: [target.content, ...additionalContextBlocks.map((b) => b.text)]
44
+ .filter((text) => text.length > 0)
45
+ .join("\n\n"),
46
+ };
47
+ return resultBlocks.map((block, index) =>
48
+ index === targetIndex ? folded : block,
49
+ );
50
+ }
51
+
52
+ /** Index of the last errored tool_result, else the last tool_result, else -1. */
53
+ function foldTargetIndex(blocks: ReadonlyArray<ContentBlock>): number {
54
+ let lastResult = -1;
55
+ for (let index = blocks.length - 1; index >= 0; index--) {
56
+ const block = blocks[index];
57
+ // guard:allow-tool-result-only: the answering user message carries client
58
+ // tool_result blocks only; server-side results live in assistant messages.
59
+ if (block.type !== "tool_result") {
60
+ continue;
61
+ }
62
+ if (block.is_error) {
63
+ return index;
64
+ }
65
+ if (lastResult < 0) {
66
+ lastResult = index;
67
+ }
68
+ }
69
+ return lastResult;
70
+ }
@@ -0,0 +1,68 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { AssistantOutboundAttachmentSchema } from "./events/assistant-outbound-attachment.js";
4
+ import { ConversationMessageAttachmentSchema } from "./responses/conversation-message.js";
5
+
6
+ const outboundFixture = {
7
+ id: "attachment-1",
8
+ filename: "screenshot.png",
9
+ mimeType: "image/png",
10
+ data: "c2NyZWVuc2hvdA==",
11
+ sourceType: "tool_block" as const,
12
+ };
13
+
14
+ const historyFixture = {
15
+ id: "attachment-1",
16
+ filename: "screenshot.png",
17
+ mimeType: "image/png",
18
+ sizeBytes: 10,
19
+ kind: "image",
20
+ };
21
+
22
+ describe("computer-use screenshot attachment provenance", () => {
23
+ test("new schemas accept the marker and its absence", () => {
24
+ expect(
25
+ AssistantOutboundAttachmentSchema.parse({
26
+ ...outboundFixture,
27
+ computerUseScreenshot: true,
28
+ }).computerUseScreenshot,
29
+ ).toBe(true);
30
+ expect(
31
+ AssistantOutboundAttachmentSchema.parse(outboundFixture)
32
+ .computerUseScreenshot,
33
+ ).toBeUndefined();
34
+
35
+ expect(
36
+ ConversationMessageAttachmentSchema.parse({
37
+ ...historyFixture,
38
+ computerUseScreenshot: true,
39
+ }).computerUseScreenshot,
40
+ ).toBe(true);
41
+ expect(
42
+ ConversationMessageAttachmentSchema.parse(historyFixture)
43
+ .computerUseScreenshot,
44
+ ).toBeUndefined();
45
+ });
46
+
47
+ test("legacy object parsers tolerate and strip the additive marker", () => {
48
+ const legacyOutbound = AssistantOutboundAttachmentSchema.omit({
49
+ computerUseScreenshot: true,
50
+ });
51
+ const legacyHistory = ConversationMessageAttachmentSchema.omit({
52
+ computerUseScreenshot: true,
53
+ });
54
+
55
+ expect(
56
+ legacyOutbound.parse({
57
+ ...outboundFixture,
58
+ computerUseScreenshot: true,
59
+ }),
60
+ ).toEqual(outboundFixture);
61
+ expect(
62
+ legacyHistory.parse({
63
+ ...historyFixture,
64
+ computerUseScreenshot: true,
65
+ }),
66
+ ).toEqual(historyFixture);
67
+ });
68
+ });
@@ -0,0 +1,55 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import {
4
+ isComputerUseToolCall,
5
+ resolveComputerUseToolName,
6
+ } from "./computer-use-tool.js";
7
+
8
+ describe("isComputerUseToolCall", () => {
9
+ test("recognizes direct and skill-wrapped computer-use calls", () => {
10
+ expect(isComputerUseToolCall("computer_use_click", {})).toBe(true);
11
+ expect(
12
+ isComputerUseToolCall("skill_execute", { tool: "computer_use_type" }),
13
+ ).toBe(true);
14
+ });
15
+
16
+ test("resolves the direct or wrapped computer-use tool name", () => {
17
+ expect(resolveComputerUseToolName("computer_use_click", {})).toBe(
18
+ "computer_use_click",
19
+ );
20
+ expect(
21
+ resolveComputerUseToolName("skill_execute", {
22
+ tool: "computer_use_scroll",
23
+ }),
24
+ ).toBe("computer_use_scroll");
25
+ });
26
+
27
+ test("rejects unrelated media tools and malformed skill input", () => {
28
+ expect(isComputerUseToolCall("browser_screenshot", {})).toBe(false);
29
+ expect(isComputerUseToolCall("file_read", {})).toBe(false);
30
+ expect(isComputerUseToolCall("image_generate", {})).toBe(false);
31
+ expect(isComputerUseToolCall("skill_execute", null)).toBe(false);
32
+ expect(isComputerUseToolCall("skill_execute", "computer_use_click")).toBe(
33
+ false,
34
+ );
35
+ expect(isComputerUseToolCall("skill_execute", { tool: 42 })).toBe(false);
36
+ expect(
37
+ isComputerUseToolCall("skill_execute", {
38
+ tool: "browser_screenshot",
39
+ }),
40
+ ).toBe(false);
41
+ });
42
+
43
+ test("does not classify raw-only recovered skill input", () => {
44
+ expect(
45
+ isComputerUseToolCall("skill_execute", {
46
+ _raw: '{"tool":"computer_use_click"}',
47
+ }),
48
+ ).toBe(false);
49
+ expect(
50
+ resolveComputerUseToolName("skill_execute", {
51
+ _raw: '{"tool":"computer_use_click"}',
52
+ }),
53
+ ).toBeUndefined();
54
+ });
55
+ });
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Resolve the host computer-use tool behind a direct or skill-wrapped call.
3
+ *
4
+ * Skills expose their selected tool in structured input. Calls recovered only
5
+ * from `_raw` retain their legacy behavior because this helper deliberately
6
+ * does not parse a second input representation.
7
+ */
8
+ export function resolveComputerUseToolName(
9
+ name: string,
10
+ input: unknown,
11
+ ): string | undefined {
12
+ if (name.startsWith("computer_use_")) {
13
+ return name;
14
+ }
15
+ if (name !== "skill_execute" || input === null || typeof input !== "object") {
16
+ return undefined;
17
+ }
18
+ const tool = (input as Record<string, unknown>).tool;
19
+ return typeof tool === "string" && tool.startsWith("computer_use_")
20
+ ? tool
21
+ : undefined;
22
+ }
23
+
24
+ /** True when a tool call is backed by the host computer-use capability. */
25
+ export function isComputerUseToolCall(name: string, input: unknown): boolean {
26
+ return resolveComputerUseToolName(name, input) !== undefined;
27
+ }
@@ -28,6 +28,9 @@ export const AssistantOutboundAttachmentSchema = z.object({
28
28
  * true and the client should hydrate via the /content endpoint. */
29
29
  data: z.string(),
30
30
  sourceType: z.enum(["sandbox_file", "host_file", "tool_block"]).optional(),
31
+ /** True when this existing computer-use screenshot was linked to the reply
32
+ * automatically. Missing or false identifies legacy or explicit placement. */
33
+ computerUseScreenshot: z.boolean().optional(),
31
34
  /** Original file size in bytes. Present when `data` was omitted to
32
35
  * keep payloads small. */
33
36
  sizeBytes: z.number().optional(),
@@ -20,10 +20,13 @@
20
20
 
21
21
  import { z } from "zod";
22
22
 
23
+ import { ModeSessionSchema } from "../mode-session.js";
24
+
23
25
  export const AssistantTurnStartEventSchema = z.object({
24
26
  type: z.literal("assistant_turn_start"),
25
27
  messageId: z.string(),
26
28
  conversationId: z.string().optional(),
29
+ modeSession: ModeSessionSchema.optional(),
27
30
  });
28
31
 
29
32
  export type AssistantTurnStartEvent = z.infer<
@@ -0,0 +1,10 @@
1
+ import { z } from "zod";
2
+
3
+ /** Transient browser activity changed; refetch desktop status. */
4
+ export const DesktopActivityChangedEventSchema = z.object({
5
+ type: z.literal("desktop_activity_changed"),
6
+ });
7
+
8
+ export type DesktopActivityChangedEvent = z.infer<
9
+ typeof DesktopActivityChangedEventSchema
10
+ >;
@@ -18,6 +18,7 @@
18
18
 
19
19
  import { z } from "zod";
20
20
 
21
+ import { ModeSessionSchema } from "../mode-session.js";
21
22
  import { AssistantOutboundAttachmentSchema } from "./assistant-outbound-attachment.js";
22
23
 
23
24
  export const GenerationHandoffEventSchema = z.object({
@@ -30,6 +31,7 @@ export const GenerationHandoffEventSchema = z.object({
30
31
  queuedCount: z.number(),
31
32
  /** Database row id of the just-finished assistant turn. */
32
33
  messageId: z.string().optional(),
34
+ modeSession: ModeSessionSchema.optional(),
33
35
  attachments: z.array(AssistantOutboundAttachmentSchema).optional(),
34
36
  attachmentWarnings: z.array(z.string()).optional(),
35
37
  });