@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
@@ -0,0 +1,174 @@
1
+ import { afterEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ mock.module("../plugins/defaults/memory/indexer.js", () => ({
4
+ MIN_SEGMENT_CHARS: 50,
5
+ indexMessageNow: async () => ({ indexedSegments: 0, enqueuedJobs: 0 }),
6
+ enqueueBackfillJob: () => "",
7
+ enqueueRebuildIndexJob: () => "",
8
+ }));
9
+
10
+ import { consolidateAssistantMessages } from "../daemon/conversation-history.js";
11
+ import {
12
+ addMessage,
13
+ createConversation,
14
+ deleteLastExchange,
15
+ getMessages,
16
+ } from "../persistence/conversation-crud.js";
17
+ import {
18
+ beginConversationModeSession,
19
+ updateConversationModeSessionBoundaries,
20
+ } from "../persistence/conversation-mode-sessions.js";
21
+ import { getDb } from "../persistence/db-connection.js";
22
+ import { initializeDb } from "../persistence/db-init.js";
23
+
24
+ await initializeDb();
25
+
26
+ const FAIL_REPAIR_TRIGGER = "fail_mode_session_boundary_repair";
27
+
28
+ function installFailingBoundaryRepairTrigger(): void {
29
+ getDb().run(/* sql */ `
30
+ CREATE TRIGGER ${FAIL_REPAIR_TRIGGER}
31
+ BEFORE UPDATE ON conversation_mode_sessions
32
+ BEGIN
33
+ SELECT RAISE(ABORT, 'injected boundary repair failure');
34
+ END
35
+ `);
36
+ }
37
+
38
+ afterEach(() => {
39
+ getDb().run(`DROP TRIGGER IF EXISTS ${FAIL_REPAIR_TRIGGER}`);
40
+ });
41
+
42
+ describe("message deletion mode-session boundary repair failures", () => {
43
+ test("consolidation deletes every donor without duplicating copied content", async () => {
44
+ const conversation = createConversation("Boundary repair consolidation");
45
+ const sessionId = `session-${conversation.id}`;
46
+ const owner = { id: sessionId, mode: "browser" as const };
47
+ const sourceStartedAt = Date.now() - 10_000;
48
+ expect(
49
+ beginConversationModeSession({
50
+ id: sessionId,
51
+ conversationId: conversation.id,
52
+ mode: owner.mode,
53
+ sourceStartedAt,
54
+ }),
55
+ ).toMatchObject({ ok: true });
56
+
57
+ const user = await addMessage(conversation.id, "user", "Run the tool");
58
+ const retained = await addMessage(
59
+ conversation.id,
60
+ "assistant",
61
+ JSON.stringify([
62
+ { type: "tool_use", id: "tool-1", name: "example", input: {} },
63
+ ]),
64
+ { metadata: { modeSession: owner } },
65
+ );
66
+ const toolResult = await addMessage(
67
+ conversation.id,
68
+ "user",
69
+ JSON.stringify([
70
+ { type: "tool_result", tool_use_id: "tool-1", content: "done" },
71
+ ]),
72
+ { metadata: { modeSession: owner } },
73
+ );
74
+ const donor = await addMessage(
75
+ conversation.id,
76
+ "assistant",
77
+ JSON.stringify([{ type: "text", text: "Finished once." }]),
78
+ { metadata: { modeSession: owner } },
79
+ );
80
+ expect(
81
+ updateConversationModeSessionBoundaries({
82
+ id: sessionId,
83
+ conversationId: conversation.id,
84
+ expectedRevision: 1,
85
+ firstIncluded: {
86
+ at: retained.createdAt,
87
+ messageId: retained.id,
88
+ },
89
+ lastActivityAt: donor.createdAt,
90
+ lastOwnedMessageId: donor.id,
91
+ }),
92
+ ).toMatchObject({ ok: true });
93
+ installFailingBoundaryRepairTrigger();
94
+
95
+ expect(consolidateAssistantMessages(conversation.id, user.id)).toBe(true);
96
+ const rows = getMessages(conversation.id);
97
+ expect(rows.map((row) => row.id)).toEqual([user.id, retained.id]);
98
+ const retainedContent = rows[1]!.content;
99
+ expect(retainedContent).toEqual([
100
+ { type: "tool_use", id: "tool-1", name: "example", input: {} },
101
+ { type: "text", text: "Finished once." },
102
+ { type: "tool_result", tool_use_id: "tool-1", content: "done" },
103
+ ]);
104
+
105
+ expect(consolidateAssistantMessages(conversation.id, user.id)).toBe(false);
106
+ expect(getMessages(conversation.id)[1]!.content).toEqual(retainedContent);
107
+ expect(
108
+ getMessages(conversation.id).some((row) => row.id === donor.id),
109
+ ).toBe(false);
110
+ expect(
111
+ getMessages(conversation.id).some((row) => row.id === toolResult.id),
112
+ ).toBe(false);
113
+ });
114
+
115
+ test("tail deletion returns its committed count when boundary repair fails", async () => {
116
+ const conversation = createConversation("Boundary repair tail delete");
117
+ const sessionId = `session-${conversation.id}`;
118
+ const owner = { id: sessionId, mode: "browser" as const };
119
+ expect(
120
+ beginConversationModeSession({
121
+ id: sessionId,
122
+ conversationId: conversation.id,
123
+ mode: owner.mode,
124
+ sourceStartedAt: Date.now() - 10_000,
125
+ }),
126
+ ).toMatchObject({ ok: true });
127
+ const keptUser = await addMessage(conversation.id, "user", "Keep this");
128
+ const keptAssistant = await addMessage(
129
+ conversation.id,
130
+ "assistant",
131
+ "Kept reply",
132
+ );
133
+ const deletedUser = await addMessage(
134
+ conversation.id,
135
+ "user",
136
+ "Delete this",
137
+ { metadata: { modeSession: owner } },
138
+ );
139
+ const deletedAssistant = await addMessage(
140
+ conversation.id,
141
+ "assistant",
142
+ "Deleted reply",
143
+ { metadata: { modeSession: owner } },
144
+ );
145
+ expect(
146
+ updateConversationModeSessionBoundaries({
147
+ id: sessionId,
148
+ conversationId: conversation.id,
149
+ expectedRevision: 1,
150
+ firstIncluded: {
151
+ at: deletedAssistant.createdAt,
152
+ messageId: deletedAssistant.id,
153
+ },
154
+ lastActivityAt: deletedAssistant.createdAt,
155
+ lastOwnedMessageId: deletedAssistant.id,
156
+ }),
157
+ ).toMatchObject({ ok: true });
158
+ installFailingBoundaryRepairTrigger();
159
+
160
+ expect(deleteLastExchange(conversation.id)).toBe(2);
161
+ expect(getMessages(conversation.id).map((row) => row.id)).toEqual([
162
+ keptUser.id,
163
+ keptAssistant.id,
164
+ ]);
165
+ expect(
166
+ getMessages(conversation.id).some((row) => row.id === deletedUser.id),
167
+ ).toBe(false);
168
+ expect(
169
+ getMessages(conversation.id).some(
170
+ (row) => row.id === deletedAssistant.id,
171
+ ),
172
+ ).toBe(false);
173
+ });
174
+ });
@@ -89,6 +89,7 @@ import {
89
89
  handleMessageComplete,
90
90
  } from "../daemon/conversation-agent-loop-handlers.js";
91
91
  import { getConversationPersistedSeq } from "../persistence/conversation-crud.js";
92
+ import { mockUnownedModeSessions } from "./helpers/mock-conversation.js";
92
93
 
93
94
  const CONVERSATION_ID = "test-session-id";
94
95
 
@@ -101,6 +102,7 @@ function createMockDeps(): EventHandlerDeps {
101
102
  emitActivityState: () => {},
102
103
  markWorkspaceTopLevelDirty: () => {},
103
104
  currentTurnSurfaces: [],
105
+ modeSessions: mockUnownedModeSessions(),
104
106
  } as unknown as EventHandlerDeps["ctx"],
105
107
  onEvent: (_msg: AssistantEvent) => {},
106
108
  reqId: "test-req-id",
@@ -87,6 +87,7 @@ import {
87
87
  type QueuedMessage,
88
88
  } from "../daemon/conversation-queue-manager.js";
89
89
  import type { TrustContext } from "../daemon/trust-context-types.js";
90
+ import { mockUnownedModeSessions } from "./helpers/mock-conversation.js";
90
91
 
91
92
  // ---------------------------------------------------------------------------
92
93
  // Fake context — captures preactivation calls, satisfies the bare minimum
@@ -117,6 +118,7 @@ function makeFakeContext(opts: {
117
118
  abortController: null,
118
119
  queue: opts.queue,
119
120
  surfaceActionRequestIds: new Set<string>(),
121
+ modeSessions: mockUnownedModeSessions(),
120
122
  usageStats: { inputTokens: 0, outputTokens: 0, estimatedCost: 0 },
121
123
  get preactivatedSkillIds(): string[] | undefined {
122
124
  return preactivatedSkillIds;
@@ -0,0 +1,276 @@
1
+ /**
2
+ * `Conversation.buildCurrentSystemPrompt` captures the delegation-section
3
+ * state the prompt it builds renders (`renderedDelegateIndependentTasks`),
4
+ * which the wire-surface recorder persists for a retrospective fork to
5
+ * replay. The loop sends the prompt built before the run and never rebuilds
6
+ * it mid-run, so the captured state has to be the one that build used: not a
7
+ * re-derivation at send time, and not the state of a build that failed while
8
+ * the loop kept its previous prompt.
9
+ */
10
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
11
+
12
+ import { CompactionCircuit } from "../agent/compaction-circuit.js";
13
+ import type { AgentEvent } from "../agent/loop.js";
14
+ import type { AssistantEvent } from "../api/index.js";
15
+ import type { Message, ProviderResponse } from "../providers/types.js";
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Mocks — must precede Conversation import
19
+ // ---------------------------------------------------------------------------
20
+
21
+ mock.module("../providers/registry.js", () => ({
22
+ getProvider: () => ({ name: "mock-provider" }),
23
+ initializeProviders: async () => {},
24
+ }));
25
+
26
+ mock.module("../config/assistant-feature-flags.js", () => ({
27
+ isAssistantFeatureFlagEnabled: () => true,
28
+ }));
29
+
30
+ // The builder under the conversation's control: records the options each
31
+ // build receives and can be made to throw, which is what a wake's prompt
32
+ // sync swallows before running on the previous prompt.
33
+ let builtWith: Array<Record<string, unknown> | undefined> = [];
34
+ let throwOnBuild = false;
35
+ mock.module("../prompts/system-prompt.js", () => ({
36
+ buildSystemPrompt: (options?: Record<string, unknown>) => {
37
+ if (throwOnBuild) {
38
+ throw new Error("prompt build failed");
39
+ }
40
+ builtWith.push(options);
41
+ return "system prompt";
42
+ },
43
+ }));
44
+
45
+ mock.module("../config/skills.js", () => ({
46
+ loadSkillCatalog: () => [],
47
+ loadSkillBySelector: () => ({ skill: null }),
48
+ ensureSkillIcon: async () => null,
49
+ }));
50
+
51
+ mock.module("../config/skill-state.js", () => ({
52
+ resolveSkillStates: () => [],
53
+ }));
54
+
55
+ mock.module("../permissions/trust-store.js", () => ({
56
+ addRule: () => {},
57
+ findHighestPriorityRule: () => null,
58
+ clearCache: () => {},
59
+ }));
60
+
61
+ mock.module("../security/secret-allowlist.js", () => ({
62
+ resetAllowlist: () => {},
63
+ }));
64
+
65
+ mock.module("../persistence/conversation-crud.js", () => ({
66
+ setConversationProcessingStartedAt: () => {},
67
+ isConversationProcessing: () => false,
68
+ setConversationOriginChannelIfUnset: () => {},
69
+ updateConversationContextWindow: () => {},
70
+ deleteMessageById: () => {},
71
+ provenanceFromTrustContext: () => ({
72
+ source: "user",
73
+ trustContext: undefined,
74
+ }),
75
+ getConversationOriginInterface: () => null,
76
+ getConversationOriginChannel: () => null,
77
+ getMessages: () => [],
78
+ getConversation: () => ({
79
+ id: "conv-1",
80
+ contextSummary: null,
81
+ contextCompactedMessageCount: 0,
82
+ totalInputTokens: 0,
83
+ totalOutputTokens: 0,
84
+ totalEstimatedCost: 0,
85
+ }),
86
+ createConversation: () => ({ id: "conv-1" }),
87
+ addMessage: () => ({ id: `msg-${Date.now()}` }),
88
+ updateConversationUsage: () => {},
89
+ updateConversationTitle: () => {},
90
+ reserveMessage: mock(async () => ({ id: "msg-reserve" })),
91
+ }));
92
+
93
+ mock.module("../persistence/conversation-queries.js", () => ({
94
+ listConversations: () => [],
95
+ }));
96
+
97
+ mock.module("../persistence/attachments-store.js", () => ({
98
+ uploadAttachment: () => ({ id: `att-${Date.now()}` }),
99
+ linkAttachmentToMessage: () => {},
100
+ }));
101
+
102
+ mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
103
+ ContextWindowManager: class {
104
+ estimateInputTokens() {
105
+ return 0;
106
+ }
107
+ get tokenCountInputs() {
108
+ return { systemPrompt: "", tools: undefined };
109
+ }
110
+ constructor() {}
111
+ updateConfig() {}
112
+ shouldCompact() {
113
+ return { needed: false, estimatedTokens: 0 };
114
+ }
115
+ async maybeCompact() {
116
+ return { compacted: false };
117
+ }
118
+ resetOverflowRecovery() {}
119
+ },
120
+ createContextSummaryMessage: () => ({
121
+ role: "user",
122
+ content: [{ type: "text", text: "summary" }],
123
+ }),
124
+ getSummaryFromContextMessage: () => null,
125
+ }));
126
+
127
+ mock.module("../persistence/llm-usage-store.js", () => ({
128
+ recordUsageEvent: () => ({ id: "mock-id", createdAt: Date.now() }),
129
+ listUsageEvents: () => [],
130
+ }));
131
+
132
+ mock.module("../agent/loop.js", () => ({
133
+ AgentLoop: class {
134
+ compactionCircuit = new CompactionCircuit("test-conv");
135
+ constructor() {}
136
+ getToolTokenBudget() {
137
+ return 0;
138
+ }
139
+ getResolvedTools() {
140
+ return [];
141
+ }
142
+ getActiveModel() {
143
+ return undefined;
144
+ }
145
+ setSystemPrompt() {}
146
+ async run(_options: {
147
+ messages: Message[];
148
+ onEvent: (event: AgentEvent) => void;
149
+ }): Promise<Message[]> {
150
+ return [];
151
+ }
152
+ },
153
+ }));
154
+
155
+ // ---------------------------------------------------------------------------
156
+ // Import Conversation AFTER mocks
157
+ // ---------------------------------------------------------------------------
158
+
159
+ import { Conversation } from "../daemon/conversation.js";
160
+
161
+ // ---------------------------------------------------------------------------
162
+ // Helpers
163
+ // ---------------------------------------------------------------------------
164
+
165
+ function makeProvider() {
166
+ return {
167
+ name: "mock",
168
+ async sendMessage(): Promise<ProviderResponse> {
169
+ return {
170
+ content: [],
171
+ model: "mock",
172
+ usage: { inputTokens: 0, outputTokens: 0 },
173
+ stopReason: "end_turn",
174
+ };
175
+ },
176
+ };
177
+ }
178
+
179
+ let conversationSeq = 0;
180
+
181
+ /**
182
+ * A conversation whose prompt is built, or, given a prompt other than the
183
+ * builder's, one running on a verbatim system-prompt override.
184
+ */
185
+ function makeConversation(systemPrompt = "system prompt"): Conversation {
186
+ conversationSeq += 1;
187
+ return new Conversation(
188
+ `conv-rendered-delegation-${conversationSeq}`,
189
+ makeProvider(),
190
+ systemPrompt,
191
+ (_msg: AssistantEvent) => {},
192
+ "/tmp",
193
+ { maxTokens: 4096 },
194
+ );
195
+ }
196
+
197
+ function lastBuildDelegation(): unknown {
198
+ return builtWith.at(-1)?.delegateIndependentTasks;
199
+ }
200
+
201
+ beforeEach(() => {
202
+ builtWith = [];
203
+ throwOnBuild = false;
204
+ });
205
+
206
+ // ---------------------------------------------------------------------------
207
+ // Tests
208
+ // ---------------------------------------------------------------------------
209
+
210
+ describe("Conversation.buildCurrentSystemPrompt delegation-state capture", () => {
211
+ test("captures the state the build rendered and hands the builder the same value", () => {
212
+ const conversation = makeConversation();
213
+ expect(conversation.renderedDelegateIndependentTasks).toBeUndefined();
214
+
215
+ conversation.buildCurrentSystemPrompt();
216
+
217
+ // An unrestricted turn can spawn, so the section renders on.
218
+ expect(conversation.renderedDelegateIndependentTasks).toBe(true);
219
+ expect(lastBuildDelegation()).toBe(true);
220
+ });
221
+
222
+ test("a change to the gate's inputs after the build does not touch the captured state until the next build", () => {
223
+ const conversation = makeConversation();
224
+ conversation.buildCurrentSystemPrompt();
225
+ expect(conversation.renderedDelegateIndependentTasks).toBe(true);
226
+
227
+ // The loop is still sending the prompt built above, so the recorder must
228
+ // see that prompt's state, whatever the gate would derive now.
229
+ conversation.setSubagentAllowedTools(new Set(["remember"]));
230
+ expect(conversation.renderedDelegateIndependentTasks).toBe(true);
231
+
232
+ conversation.buildCurrentSystemPrompt();
233
+ expect(conversation.renderedDelegateIndependentTasks).toBe(false);
234
+ expect(lastBuildDelegation()).toBe(false);
235
+ });
236
+
237
+ test("a failed build leaves the previously captured state in place", () => {
238
+ const conversation = makeConversation();
239
+ conversation.buildCurrentSystemPrompt();
240
+ expect(conversation.renderedDelegateIndependentTasks).toBe(true);
241
+
242
+ // A wake's prompt sync swallows this and runs on the previous prompt,
243
+ // whose section is still on, even though a rebuild would now render it
244
+ // off.
245
+ conversation.setSubagentAllowedTools(new Set(["remember"]));
246
+ throwOnBuild = true;
247
+ expect(() => conversation.buildCurrentSystemPrompt()).toThrow(
248
+ "prompt build failed",
249
+ );
250
+
251
+ expect(conversation.renderedDelegateIndependentTasks).toBe(true);
252
+ });
253
+
254
+ test("a verbatim system-prompt override captures unknown", () => {
255
+ const conversation = makeConversation("override prompt");
256
+ builtWith = [];
257
+
258
+ expect(conversation.buildCurrentSystemPrompt()).toBe("override prompt");
259
+
260
+ expect(conversation.renderedDelegateIndependentTasks).toBeNull();
261
+ // The override is returned as is; nothing is built.
262
+ expect(builtWith).toEqual([]);
263
+ });
264
+
265
+ test("a replaying wake's recorded state wins over the derivation", () => {
266
+ const conversation = makeConversation();
267
+ // Replaying a channel-sourced conversation that recorded the section off,
268
+ // on a wake whose own scope could spawn.
269
+ conversation.delegateIndependentTasksReplay = false;
270
+
271
+ conversation.buildCurrentSystemPrompt();
272
+
273
+ expect(conversation.renderedDelegateIndependentTasks).toBe(false);
274
+ expect(lastBuildDelegation()).toBe(false);
275
+ });
276
+ });
@@ -197,6 +197,7 @@ function makeConversation(opts: { processing?: boolean } = {}) {
197
197
  const emitActivityState = mock(
198
198
  (_phase: string, _reason: string, _options?: unknown) => {},
199
199
  );
200
+ const invalidateAllStructuralWaits = mock(() => 0);
200
201
  const conversation = {
201
202
  conversationId: "conv-retry-test",
202
203
  trustContext: undefined,
@@ -209,6 +210,7 @@ function makeConversation(opts: { processing?: boolean } = {}) {
209
210
  loadFromDb,
210
211
  runAgentLoop,
211
212
  emitActivityState,
213
+ modeSessions: { invalidateAllStructuralWaits },
212
214
  };
213
215
  return {
214
216
  conversation,
@@ -217,6 +219,7 @@ function makeConversation(opts: { processing?: boolean } = {}) {
217
219
  loadFromDb,
218
220
  runAgentLoop,
219
221
  emitActivityState,
222
+ invalidateAllStructuralWaits,
220
223
  };
221
224
  }
222
225
 
@@ -264,6 +267,24 @@ beforeEach(() => {
264
267
  });
265
268
 
266
269
  describe("POST /v1/conversations/:id/retry", () => {
270
+ test("tracking invalidation failure does not prevent retry", async () => {
271
+ const ctx = makeConversation();
272
+ activeConversation = ctx.conversation;
273
+ ctx.invalidateAllStructuralWaits.mockImplementation(() => {
274
+ throw new Error("session tracking unavailable");
275
+ });
276
+ const res = await callHandler(
277
+ retryHandler,
278
+ makeRequest(),
279
+ { id: "conv-retry-test" },
280
+ 202,
281
+ );
282
+ expect(res.status).toBe(202);
283
+ await settle();
284
+ expect(discardMock).toHaveBeenCalledTimes(1);
285
+ expect(ctx.runAgentLoop).toHaveBeenCalledTimes(1);
286
+ });
287
+
267
288
  test("202s, discards the tail, and re-runs the loop from the anchor", async () => {
268
289
  const ctx = makeConversation();
269
290
  activeConversation = ctx.conversation;
@@ -299,6 +320,7 @@ describe("POST /v1/conversations/:id/retry", () => {
299
320
  expect(ctx.conversation.isProcessing()).toBe(true);
300
321
  expect(ctx.conversation.abortController).not.toBeNull();
301
322
  expect(discardMock).toHaveBeenCalledWith("conv-retry-test");
323
+ expect(ctx.invalidateAllStructuralWaits).toHaveBeenCalledTimes(1);
302
324
 
303
325
  // Origin-less invalidation: the initiating client reconciles too.
304
326
  expect(publishConversationMessagesChangedMock).toHaveBeenCalledTimes(1);
@@ -32,6 +32,7 @@ import * as pendingInteractions from "../runtime/pending-interactions.js";
32
32
  import { handleSendMessage } from "../runtime/routes/conversation-routes.js";
33
33
  import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
34
34
  import { callHandler } from "./helpers/call-route-handler.js";
35
+ import { mockUnownedModeSessions } from "./helpers/mock-conversation.js";
35
36
  import { setConfig } from "./helpers/set-config.js";
36
37
 
37
38
  const testDir = process.env.VELLUM_WORKSPACE_DIR!;
@@ -88,6 +89,7 @@ function createFakeConversation(conversationId: string): Conversation {
88
89
  conversationId,
89
90
  processing: false,
90
91
  currentRequestId: undefined as string | undefined,
92
+ modeSessions: mockUnownedModeSessions(),
91
93
  abortController: null as AbortController | null,
92
94
  trustContext: undefined as unknown,
93
95
  turnChannelContext: null as {
@@ -135,6 +135,7 @@ mock.module("../ipc/gateway-client.js", () => ({
135
135
  import { getEffectiveEnabledPluginSet } from "../daemon/conversation-tool-setup.js";
136
136
  import { handleSendMessage } from "../runtime/routes/conversation-routes.js";
137
137
  import { callHandler } from "./helpers/call-route-handler.js";
138
+ import { mockUnownedModeSessions } from "./helpers/mock-conversation.js";
138
139
 
139
140
  function makeConversation() {
140
141
  const runAgentLoop = mock(async () => undefined);
@@ -156,6 +157,7 @@ function makeConversation() {
156
157
  },
157
158
  abortController: null,
158
159
  currentRequestId: undefined,
160
+ modeSessions: mockUnownedModeSessions(),
159
161
  queue: { length: 0 },
160
162
  setTrustContext: () => {},
161
163
  replayActivityState: () => {},
@@ -113,6 +113,7 @@ mock.module("../contacts/guardian-delivery-reader.js", () => ({
113
113
  import type { AuthContext } from "../runtime/auth/types.js";
114
114
  import { handleSendMessage } from "../runtime/routes/conversation-routes.js";
115
115
  import { callHandler } from "./helpers/call-route-handler.js";
116
+ import { mockUnownedModeSessions } from "./helpers/mock-conversation.js";
116
117
 
117
118
  const _testAuthContext: AuthContext = {
118
119
  subject: "actor:self:test-guardian",
@@ -185,6 +186,7 @@ describe("handleSendMessage guardian reply interception", () => {
185
186
  setHostAppControlProxy: () => {},
186
187
  restoreBrowserProxyAvailability: () => {},
187
188
  addPreactivatedSkillId: () => {},
189
+ modeSessions: mockUnownedModeSessions(),
188
190
  } as unknown as import("../daemon/conversation.js").Conversation;
189
191
 
190
192
  const req = new Request("http://localhost/v1/messages", {
@@ -275,6 +277,7 @@ describe("handleSendMessage guardian reply interception", () => {
275
277
  setHostAppControlProxy: () => {},
276
278
  restoreBrowserProxyAvailability: () => {},
277
279
  addPreactivatedSkillId: () => {},
280
+ modeSessions: mockUnownedModeSessions(),
278
281
  } as unknown as import("../daemon/conversation.js").Conversation;
279
282
 
280
283
  const req = new Request("http://localhost/v1/messages", {
@@ -353,6 +356,7 @@ describe("handleSendMessage guardian reply interception", () => {
353
356
  setHostAppControlProxy: () => {},
354
357
  restoreBrowserProxyAvailability: () => {},
355
358
  addPreactivatedSkillId: () => {},
359
+ modeSessions: mockUnownedModeSessions(),
356
360
  } as unknown as import("../daemon/conversation.js").Conversation;
357
361
 
358
362
  const req = new Request("http://localhost/v1/messages", {
@@ -442,6 +446,7 @@ describe("handleSendMessage guardian reply interception", () => {
442
446
  setHostAppControlProxy: () => {},
443
447
  restoreBrowserProxyAvailability: () => {},
444
448
  addPreactivatedSkillId: () => {},
449
+ modeSessions: mockUnownedModeSessions(),
445
450
  } as unknown as import("../daemon/conversation.js").Conversation;
446
451
 
447
452
  const req = new Request("http://localhost/v1/messages", {
@@ -529,6 +534,7 @@ describe("handleSendMessage guardian reply interception", () => {
529
534
  setHostAppControlProxy: () => {},
530
535
  restoreBrowserProxyAvailability: () => {},
531
536
  addPreactivatedSkillId: () => {},
537
+ modeSessions: mockUnownedModeSessions(),
532
538
  } as unknown as import("../daemon/conversation.js").Conversation;
533
539
 
534
540
  const req = new Request("http://localhost/v1/messages", {
@@ -612,6 +618,7 @@ describe("handleSendMessage guardian reply interception", () => {
612
618
  setHostAppControlProxy: () => {},
613
619
  restoreBrowserProxyAvailability: () => {},
614
620
  addPreactivatedSkillId: () => {},
621
+ modeSessions: mockUnownedModeSessions(),
615
622
  } as unknown as import("../daemon/conversation.js").Conversation;
616
623
 
617
624
  const req = new Request("http://localhost/v1/messages", {
@@ -689,6 +696,7 @@ describe("handleSendMessage guardian reply interception", () => {
689
696
  setHostAppControlProxy: () => {},
690
697
  restoreBrowserProxyAvailability: () => {},
691
698
  addPreactivatedSkillId: () => {},
699
+ modeSessions: mockUnownedModeSessions(),
692
700
  } as unknown as import("../daemon/conversation.js").Conversation;
693
701
 
694
702
  const req = new Request("http://localhost/v1/messages", {
@@ -768,6 +776,7 @@ describe("handleSendMessage guardian reply interception", () => {
768
776
  setHostAppControlProxy: () => {},
769
777
  restoreBrowserProxyAvailability: () => {},
770
778
  addPreactivatedSkillId: () => {},
779
+ modeSessions: mockUnownedModeSessions(),
771
780
  } as unknown as import("../daemon/conversation.js").Conversation;
772
781
 
773
782
  const req = new Request("http://localhost/v1/messages", {
@@ -848,6 +857,7 @@ describe("handleSendMessage guardian reply interception", () => {
848
857
  setHostAppControlProxy: () => {},
849
858
  restoreBrowserProxyAvailability: () => {},
850
859
  addPreactivatedSkillId: () => {},
860
+ modeSessions: mockUnownedModeSessions(),
851
861
  } as unknown as import("../daemon/conversation.js").Conversation;
852
862
 
853
863
  const req = new Request("http://localhost/v1/messages", {
@@ -126,6 +126,7 @@ import {
126
126
  import * as pendingInteractions from "../runtime/pending-interactions.js";
127
127
  import { handleSendMessage } from "../runtime/routes/conversation-routes.js";
128
128
  import { callHandler } from "./helpers/call-route-handler.js";
129
+ import { mockUnownedModeSessions } from "./helpers/mock-conversation.js";
129
130
 
130
131
  const CONV_ID = "conv-hidden-queue";
131
132
 
@@ -159,6 +160,7 @@ function makeConversationWithPendingConfirmation(
159
160
  },
160
161
  },
161
162
  currentRequestId: undefined,
163
+ modeSessions: mockUnownedModeSessions(),
162
164
  queue: {
163
165
  length: 0,
164
166
  promoteToHead: (requestId: string) => ({ requestId }),
@@ -166,6 +166,7 @@ import { CONVERSATION_BUSY_MESSAGE } from "../daemon/conversation-messaging.js";
166
166
  import type { AuthContext } from "../runtime/auth/types.js";
167
167
  import { handleSendMessage } from "../runtime/routes/conversation-routes.js";
168
168
  import { callHandler } from "./helpers/call-route-handler.js";
169
+ import { mockUnownedModeSessions } from "./helpers/mock-conversation.js";
169
170
 
170
171
  const _testAuthContext: AuthContext = {
171
172
  subject: "actor:self:test-guardian",
@@ -233,6 +234,7 @@ function makeConversation() {
233
234
  messages,
234
235
  abortController: null,
235
236
  currentRequestId: undefined,
237
+ modeSessions: mockUnownedModeSessions(),
236
238
  queue: { length: 0 },
237
239
  setTrustContext: () => {},
238
240
  replayActivityState: () => {},