@vellumai/assistant 0.12.3-staging.1 → 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 (560) hide show
  1. package/ARCHITECTURE.md +43 -29
  2. package/Dockerfile +63 -0
  3. package/docs/architecture/security.md +10 -5
  4. package/docs/architecture/turn-actor.md +2 -0
  5. package/docs/desktop-browser-cli.md +45 -4
  6. package/docs/live-voice-task-outcomes.md +100 -0
  7. package/docs/mode-sessions.md +183 -0
  8. package/docs/voice-input-diagnostics.md +58 -0
  9. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  10. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  11. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  12. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  13. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  14. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  15. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
  16. package/node_modules/@vellumai/gateway-client/src/index.ts +4 -1
  17. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +38 -7
  18. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +5 -6
  19. package/node_modules/@vellumai/service-contracts/package.json +2 -1
  20. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  21. package/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  22. package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
  23. package/openapi.yaml +665 -14
  24. package/package.json +1 -1
  25. package/scripts/smoke-desktop-browser-cli.ts +10 -26
  26. package/scripts/smoke-desktop-window-theme.ts +2 -3
  27. package/src/__tests__/agent-loop-output-hooks.test.ts +150 -1
  28. package/src/__tests__/agent-loop-provider-error-recording.test.ts +87 -19
  29. package/src/__tests__/annotate-activity-metadata.test.ts +3 -1
  30. package/src/__tests__/annotate-risk-options.test.ts +2 -0
  31. package/src/__tests__/answered-question-persistence.test.ts +2 -0
  32. package/src/__tests__/anthropic-gateway-shared.test.ts +22 -0
  33. package/src/__tests__/approval-message-composer.test.ts +1 -118
  34. package/src/__tests__/approval-routes-http.test.ts +3 -0
  35. package/src/__tests__/assistant-event-hub-connection-history.test.ts +111 -0
  36. package/src/__tests__/assistant-event-hub-targeted.test.ts +50 -0
  37. package/src/__tests__/assistant-event-targeting.test.ts +186 -0
  38. package/src/__tests__/assistant-stream-state.test.ts +29 -9
  39. package/src/__tests__/browser-fill-credential.test.ts +11 -22
  40. package/src/__tests__/btw-routes.test.ts +4 -1
  41. package/src/__tests__/build-persisted-content.test.ts +1 -1
  42. package/src/__tests__/call-conversation-messages.test.ts +5 -0
  43. package/src/__tests__/call-recovery.test.ts +7 -2
  44. package/src/__tests__/call-routes-http.test.ts +12 -0
  45. package/src/__tests__/call-store.test.ts +7 -2
  46. package/src/__tests__/channel-retry-sweep.test.ts +9 -0
  47. package/src/__tests__/chat-reveal-guard-priming.test.ts +2 -0
  48. package/src/__tests__/checker.test.ts +11 -3
  49. package/src/__tests__/client-os-metadata-persistence.test.ts +35 -1
  50. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -25
  51. package/src/__tests__/computer-use-tools.test.ts +1 -233
  52. package/src/__tests__/config-model-image-provider.test.ts +39 -0
  53. package/src/__tests__/config-schema.test.ts +16 -0
  54. package/src/__tests__/config-watcher.test.ts +24 -0
  55. package/src/__tests__/context-search-agent-runner.test.ts +260 -1
  56. package/src/__tests__/context-search-fanout.test.ts +1 -1
  57. package/src/__tests__/context-search-types.test.ts +7 -7
  58. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +8 -2
  59. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +2 -0
  60. package/src/__tests__/conversation-agent-loop.test.ts +546 -16
  61. package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
  62. package/src/__tests__/conversation-evictor.test.ts +62 -37
  63. package/src/__tests__/conversation-history-boundary-repair-failure.test.ts +174 -0
  64. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +2 -0
  65. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
  66. package/src/__tests__/conversation-retry-route.test.ts +22 -0
  67. package/src/__tests__/conversation-routes-disk-view.test.ts +2 -0
  68. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +2 -0
  69. package/src/__tests__/conversation-routes-guardian-reply.test.ts +10 -0
  70. package/src/__tests__/conversation-routes-hidden-queue.test.ts +2 -0
  71. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
  72. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -0
  73. package/src/__tests__/conversation-surface-snapshots.test.ts +543 -0
  74. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +151 -0
  75. package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +63 -1
  76. package/src/__tests__/conversation-tool-setup-attribution.test.ts +23 -0
  77. package/src/__tests__/conversation-undo.test.ts +61 -0
  78. package/src/__tests__/credential-execution-client.test.ts +6 -6
  79. package/src/__tests__/credential-prompt-route.test.ts +35 -3
  80. package/src/__tests__/cu-unified-flow.test.ts +82 -1
  81. package/src/__tests__/db-mode-sessions-migration.test.ts +175 -0
  82. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -0
  83. package/src/__tests__/dm-backfill.test.ts +91 -1
  84. package/src/__tests__/document-create-route.test.ts +88 -0
  85. package/src/__tests__/document-sync-tags.test.ts +27 -0
  86. package/src/__tests__/emit-signal-routing-intent.test.ts +142 -2
  87. package/src/__tests__/events-tail-route.test.ts +25 -0
  88. package/src/__tests__/evict-conversations-for-reload.test.ts +57 -8
  89. package/src/__tests__/guardian-action-sweep.test.ts +16 -0
  90. package/src/__tests__/guardian-dispatch.test.ts +13 -0
  91. package/src/__tests__/headless-browser-interactions.test.ts +64 -20
  92. package/src/__tests__/heartbeat-service.test.ts +2 -59
  93. package/src/__tests__/helpers/mock-conversation.ts +21 -0
  94. package/src/__tests__/helpers/native-web-search-harness.ts +2 -0
  95. package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +5 -0
  96. package/src/__tests__/host-cu-proxy.test.ts +46 -2
  97. package/src/__tests__/http-user-message-parity.test.ts +2 -0
  98. package/src/__tests__/image-credentials.test.ts +49 -0
  99. package/src/__tests__/image-service-dispatcher.test.ts +45 -0
  100. package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
  101. package/src/__tests__/interrupt-on-send.test.ts +57 -43
  102. package/src/__tests__/interrupt-turn-note.test.ts +5 -6
  103. package/src/__tests__/llm-catalog-parity.test.ts +2 -2
  104. package/src/__tests__/media-generate-image.test.ts +49 -1
  105. package/src/__tests__/message-provenance-contact-id.test.ts +69 -0
  106. package/src/__tests__/migration-export-to-gcs.test.ts +142 -0
  107. package/src/__tests__/mode-session-history.test.ts +245 -0
  108. package/src/__tests__/mode-session-recovery.test.ts +222 -0
  109. package/src/__tests__/mode-session-wire.test.ts +141 -0
  110. package/src/__tests__/notification-guardian-path.test.ts +7 -0
  111. package/src/__tests__/notification-telegram-adapter.test.ts +2 -2
  112. package/src/__tests__/notification-vellum-adapter.test.ts +34 -0
  113. package/src/__tests__/oauth-provider-serializer.test.ts +12 -0
  114. package/src/__tests__/oauth-providers-routes.test.ts +1 -0
  115. package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
  116. package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
  117. package/src/__tests__/plugin-api-provider.test.ts +5 -0
  118. package/src/__tests__/plugin-api-resolve-credential.test.ts +97 -0
  119. package/src/__tests__/plugin-import-boundary-guard.test.ts +9 -0
  120. package/src/__tests__/process-message-display-content.test.ts +56 -0
  121. package/src/__tests__/reaction-persistence.test.ts +5 -0
  122. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +25 -9
  123. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
  124. package/src/__tests__/scripted-turn-metadata-persistence.test.ts +73 -0
  125. package/src/__tests__/secret-ingress-http.test.ts +2 -0
  126. package/src/__tests__/secure-keys.test.ts +43 -1
  127. package/src/__tests__/send-endpoint-busy.test.ts +163 -1
  128. package/src/__tests__/server-history-render.test.ts +91 -1
  129. package/src/__tests__/settings-routes.test.ts +50 -1
  130. package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
  131. package/src/__tests__/subagent-fork-notifications.test.ts +1 -2
  132. package/src/__tests__/subagent-manager-notify.test.ts +1 -2
  133. package/src/__tests__/subagent-notify-parent.test.ts +146 -39
  134. package/src/__tests__/subagent-notify-stale-rebuild.test.ts +2 -4
  135. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +2 -0
  136. package/src/__tests__/thread-backfill.test.ts +53 -0
  137. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
  138. package/src/__tests__/tool-result-metadata-plumbing.test.ts +3 -1
  139. package/src/__tests__/tool-start-timestamp.test.ts +2 -0
  140. package/src/__tests__/twilio-routes.test.ts +1 -0
  141. package/src/__tests__/web-search-backend-failure.test.ts +1 -1
  142. package/src/activation/progress-store.test.ts +12 -7
  143. package/src/agent/loop.ts +99 -41
  144. package/src/api/events/assistant-turn-start.ts +3 -0
  145. package/src/api/events/generation-handoff.ts +2 -0
  146. package/src/api/events/message-complete.ts +2 -0
  147. package/src/api/events/notification-conversation-created.ts +14 -16
  148. package/src/api/events/notification-intent.ts +4 -2
  149. package/src/api/events/tool-result.ts +85 -0
  150. package/src/api/events/tool-use-start.ts +3 -0
  151. package/src/api/events/user-message-echo.ts +3 -0
  152. package/src/api/index.ts +31 -6
  153. package/src/api/mode-session.test.ts +131 -0
  154. package/src/api/mode-session.ts +148 -0
  155. package/src/api/remember-tool.ts +15 -0
  156. package/src/api/responses/conversation-message.ts +6 -0
  157. package/src/approvals/AGENTS.md +4 -2
  158. package/src/browser/__tests__/operations.test.ts +29 -0
  159. package/src/browser/operation-meta.ts +2 -1
  160. package/src/browser/operations.ts +29 -0
  161. package/src/browser/virtual-desktop-target.ts +2 -8
  162. package/src/bundler/bundle-signer.ts +1 -3
  163. package/src/calls/__tests__/barge-in-guard.test.ts +3 -0
  164. package/src/calls/__tests__/call-controller.test.ts +94 -0
  165. package/src/calls/__tests__/call-funnel-telemetry.test.ts +204 -0
  166. package/src/calls/__tests__/voice-control-protocol.test.ts +15 -0
  167. package/src/calls/__tests__/voice-escalation-judge.test.ts +209 -0
  168. package/src/calls/__tests__/voice-leg-coordinator.test.ts +168 -0
  169. package/src/{live-voice/__tests__/live-voice-metrics.test.ts → calls/__tests__/voice-metrics.test.ts} +32 -38
  170. package/src/calls/__tests__/voice-session-bridge.test.ts +576 -122
  171. package/src/calls/barge-in-guard.ts +5 -0
  172. package/src/calls/call-controller.ts +196 -1
  173. package/src/calls/call-domain.ts +4 -0
  174. package/src/calls/call-store.ts +87 -2
  175. package/src/calls/guardian-action-sweep.ts +22 -8
  176. package/src/calls/media-stream-audio-transcode.ts +1 -3
  177. package/src/calls/typesafe-noul.ts +156 -0
  178. package/src/calls/voice-control-protocol.ts +6 -0
  179. package/src/calls/voice-escalation-judge.ts +145 -0
  180. package/src/calls/voice-escalation-target.ts +10 -0
  181. package/src/calls/voice-leg-coordinator.ts +121 -3
  182. package/src/{live-voice/live-voice-metrics.ts → calls/voice-metrics.ts} +94 -87
  183. package/src/calls/voice-session-bridge.ts +256 -112
  184. package/src/calls/voice-triage-escalate.ts +7 -0
  185. package/src/cli/__tests__/roadmap-cli.test.ts +4 -41
  186. package/src/cli/commands/__tests__/notifications.test.ts +35 -10
  187. package/src/cli/commands/browser.help.ts +4 -5
  188. package/src/cli/commands/browser.ts +0 -1
  189. package/src/cli/commands/clients.help.ts +46 -0
  190. package/src/cli/commands/clients.ts +116 -0
  191. package/src/cli/commands/credentials.help.ts +6 -1
  192. package/src/cli/commands/notifications.help.ts +16 -2
  193. package/src/cli/commands/notifications.ts +30 -8
  194. package/src/cli/commands/roadmap.help.ts +18 -21
  195. package/src/cli/commands/roadmap.ts +4 -21
  196. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
  197. package/src/cli/lib/bundled-marketplace.json +84 -34
  198. package/src/cli/lib/plugin-marketplace.ts +8 -0
  199. package/src/cli/lib/publish-plugin.ts +1 -2
  200. package/src/config/__tests__/default-provider.test.ts +3 -1
  201. package/src/config/__tests__/memory-retrospective-schema.test.ts +14 -1
  202. package/src/config/bundled-skills/computer-use/SKILL.md +1 -1
  203. package/src/config/bundled-skills/computer-use/TOOLS.json +89 -1
  204. package/src/config/bundled-skills/image-studio/SKILL.md +17 -2
  205. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -11
  206. package/src/config/bundled-skills/sequences/TOOLS.json +1 -5
  207. package/src/config/call-site-defaults.ts +9 -0
  208. package/src/config/feature-flag-registry.json +16 -0
  209. package/src/config/profile-text-generation.test.ts +2 -2
  210. package/src/config/schemas/__tests__/tools.test.ts +31 -0
  211. package/src/config/schemas/call-site-catalog.ts +14 -0
  212. package/src/config/schemas/channels.ts +0 -18
  213. package/src/config/schemas/llm.ts +3 -1
  214. package/src/config/schemas/mcp.ts +2 -1
  215. package/src/config/schemas/memory-retrospective.ts +11 -2
  216. package/src/config/schemas/services.ts +15 -6
  217. package/src/config/schemas/tools.ts +10 -0
  218. package/src/config/session-groups-gate.ts +21 -0
  219. package/src/config/skills.ts +2 -6
  220. package/src/conversations/__tests__/message-consolidation.test.ts +149 -0
  221. package/src/conversations/message-consolidation.ts +102 -5
  222. package/src/credential-execution/ces-connect.test.ts +69 -0
  223. package/src/credential-execution/ces-connect.ts +115 -0
  224. package/src/credential-execution/ces-runtime.ts +55 -93
  225. package/src/credential-execution/executable-discovery.ts +1 -11
  226. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
  227. package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
  228. package/src/daemon/browser-mode-session.test.ts +402 -0
  229. package/src/daemon/browser-mode-session.ts +186 -0
  230. package/src/daemon/computer-use-mode-session.test.ts +210 -0
  231. package/src/daemon/computer-use-mode-session.ts +105 -0
  232. package/src/daemon/config-watcher.ts +10 -0
  233. package/src/daemon/conversation-agent-loop-handlers.ts +58 -10
  234. package/src/daemon/conversation-agent-loop.ts +219 -25
  235. package/src/daemon/conversation-evictor.ts +5 -24
  236. package/src/daemon/conversation-history.ts +10 -0
  237. package/src/daemon/conversation-interrupt-repair.ts +4 -43
  238. package/src/daemon/conversation-interrupt.ts +7 -11
  239. package/src/daemon/conversation-messaging.ts +58 -5
  240. package/src/daemon/conversation-mode-session.test.ts +1667 -0
  241. package/src/daemon/conversation-mode-session.ts +1008 -0
  242. package/src/daemon/conversation-process.ts +5 -0
  243. package/src/daemon/conversation-runtime-assembly.ts +10 -20
  244. package/src/daemon/conversation-skill-tools.ts +1 -0
  245. package/src/daemon/conversation-store.ts +4 -4
  246. package/src/daemon/conversation-surface-snapshots.ts +135 -0
  247. package/src/daemon/conversation-surfaces.ts +113 -5
  248. package/src/daemon/conversation-tool-setup.ts +8 -3
  249. package/src/daemon/conversation.ts +143 -41
  250. package/src/daemon/handlers/config-model.ts +7 -5
  251. package/src/daemon/handlers/shared.ts +55 -16
  252. package/src/daemon/host-cu-proxy.ts +51 -22
  253. package/src/daemon/lifecycle.ts +30 -13
  254. package/src/daemon/message-protocol.ts +0 -1
  255. package/src/daemon/message-provenance.ts +28 -4
  256. package/src/daemon/mode-session-startup-recovery.ts +23 -0
  257. package/src/daemon/mode-session-tracking.ts +54 -0
  258. package/src/daemon/process-message.ts +13 -4
  259. package/src/daemon/virtual-desktop-context.ts +21 -0
  260. package/src/desktop/__tests__/fake-desktop.ts +1 -0
  261. package/src/desktop/desktop-accessibility-script.ts +88 -0
  262. package/src/desktop/desktop-accessibility.test.ts +160 -0
  263. package/src/desktop/desktop-accessibility.ts +169 -0
  264. package/src/desktop/desktop-automation-lease.test.ts +76 -68
  265. package/src/desktop/desktop-automation-lease.ts +41 -50
  266. package/src/desktop/desktop-browser-endpoint.ts +4 -0
  267. package/src/desktop/desktop-computer-use-routing.test.ts +330 -0
  268. package/src/desktop/desktop-computer-use.test.ts +449 -0
  269. package/src/desktop/desktop-computer-use.ts +502 -0
  270. package/src/desktop/desktop-dependencies.ts +47 -293
  271. package/src/desktop/desktop-display.ts +2 -2
  272. package/src/desktop/desktop-panel-config.test.ts +13 -3
  273. package/src/desktop/desktop-panel-config.ts +109 -15
  274. package/src/desktop/desktop-session-manager.test.ts +69 -21
  275. package/src/desktop/desktop-session-manager.ts +76 -22
  276. package/src/desktop/desktop-stream-bridge.test.ts +11 -122
  277. package/src/desktop/desktop-stream-bridge.ts +6 -8
  278. package/src/desktop/desktop-window-theme.ts +5 -25
  279. package/src/desktop/virtual-desktop-feature.ts +52 -2
  280. package/src/desktop/virtual-desktop-platform.test.ts +5 -9
  281. package/src/documents/document-store.ts +23 -0
  282. package/src/heartbeat/__tests__/heartbeat-service.test.ts +22 -26
  283. package/src/heartbeat/heartbeat-service.ts +5 -33
  284. package/src/ipc/__tests__/browser-ipc.test.ts +215 -6
  285. package/src/ipc/assistant-server.ts +2 -0
  286. package/src/ipc/routes/__tests__/channel-reply-ipc-routes.test.ts +111 -0
  287. package/src/ipc/routes/channel-reply-ipc-routes.ts +73 -0
  288. package/src/live-voice/__tests__/continuation-judge.test.ts +151 -0
  289. package/src/live-voice/__tests__/live-activity-reporter.test.ts +154 -15
  290. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +743 -31
  291. package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +191 -10
  292. package/src/live-voice/__tests__/live-voice-session-groups-gate.test.ts +87 -0
  293. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +5 -1
  294. package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +41 -0
  295. package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +1017 -9
  296. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +224 -1
  297. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +101 -0
  298. package/src/live-voice/__tests__/live-voice-tts.test.ts +44 -0
  299. package/src/live-voice/__tests__/live-voice-vad.test.ts +939 -75
  300. package/src/live-voice/__tests__/microphone-idle-gate.test.ts +87 -0
  301. package/src/live-voice/__tests__/session-controls.test.ts +23 -0
  302. package/src/live-voice/__tests__/task-outcomes.test.ts +117 -0
  303. package/src/live-voice/__tests__/voice-input-diagnostics.test.ts +117 -0
  304. package/src/live-voice/camera-mode-session.test.ts +265 -0
  305. package/src/live-voice/camera-mode-session.ts +277 -0
  306. package/src/live-voice/continuation-judge.ts +123 -0
  307. package/src/live-voice/live-activity-reporter.ts +115 -6
  308. package/src/live-voice/live-voice-manager.ts +36 -1
  309. package/src/live-voice/live-voice-photo.ts +88 -7
  310. package/src/live-voice/live-voice-session-manager.ts +15 -0
  311. package/src/live-voice/live-voice-session.ts +1443 -747
  312. package/src/live-voice/live-voice-tts.ts +22 -4
  313. package/src/live-voice/microphone-idle-gate.ts +56 -0
  314. package/src/live-voice/protocol.ts +171 -4
  315. package/src/live-voice/session-controls.ts +11 -3
  316. package/src/live-voice/task-outcomes.ts +131 -0
  317. package/src/live-voice/voice-input-diagnostics.ts +117 -0
  318. package/src/mcp/__tests__/manager-tool-caps.test.ts +63 -18
  319. package/src/mcp/__tests__/tool-caps.test.ts +28 -1
  320. package/src/mcp/manager.ts +3 -0
  321. package/src/mcp/tool-caps.ts +12 -4
  322. package/src/media/__tests__/image-models.test.ts +58 -0
  323. package/src/media/image-credentials.ts +5 -0
  324. package/src/media/image-models.ts +52 -0
  325. package/src/media/image-service.ts +8 -0
  326. package/src/media/openrouter-image-service.test.ts +133 -0
  327. package/src/media/openrouter-image-service.ts +153 -0
  328. package/src/media/types.ts +1 -1
  329. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +65 -11
  330. package/src/messaging/providers/discord/send.ts +4 -17
  331. package/src/messaging/providers/discord/transport.ts +2 -2
  332. package/src/messaging/providers/outlook/client.ts +16 -22
  333. package/src/messaging/providers/telegram-bot/send.test.ts +236 -1
  334. package/src/messaging/providers/telegram-bot/send.ts +10 -7
  335. package/src/messaging/providers/telegram-bot/transport.ts +3 -10
  336. package/src/messaging/providers/whatsapp/send.test.ts +169 -4
  337. package/src/monitoring/__tests__/control.test.ts +17 -5
  338. package/src/monitoring/control.ts +15 -5
  339. package/src/notifications/AGENTS.md +1 -1
  340. package/src/notifications/README.md +83 -99
  341. package/src/notifications/__tests__/broadcaster.test.ts +1 -1
  342. package/src/notifications/__tests__/channel-allowlist.test.ts +39 -0
  343. package/src/notifications/__tests__/copy-composer.test.ts +1 -1
  344. package/src/notifications/__tests__/decision-engine.test.ts +79 -2
  345. package/src/notifications/__tests__/deterministic-checks.test.ts +10 -10
  346. package/src/notifications/__tests__/home-feed-side-effect.test.ts +93 -4
  347. package/src/notifications/__tests__/notification-utils.test.ts +18 -0
  348. package/src/notifications/adapters/macos.ts +37 -46
  349. package/src/notifications/broadcaster.ts +5 -6
  350. package/src/notifications/channel-allowlist.ts +44 -0
  351. package/src/notifications/copy-composer.ts +0 -23
  352. package/src/notifications/decision-engine.ts +24 -14
  353. package/src/notifications/deterministic-checks.ts +1 -1
  354. package/src/notifications/emit-signal.ts +123 -37
  355. package/src/notifications/home-feed-side-effect.ts +9 -7
  356. package/src/notifications/notification-utils.ts +19 -0
  357. package/src/notifications/signal.ts +4 -19
  358. package/src/notifications/types.ts +15 -0
  359. package/src/oauth/connection-resolver.ts +1 -2
  360. package/src/oauth/oauth-store.ts +1 -3
  361. package/src/oauth/provider-serializer.ts +7 -0
  362. package/src/oauth/seed-providers.ts +30 -0
  363. package/src/onboarding/onboarding-events-store.ts +99 -12
  364. package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
  365. package/src/persistence/client-connection-events-store.ts +377 -0
  366. package/src/persistence/conversation-crud.ts +55 -6
  367. package/src/persistence/conversation-mode-sessions.test.ts +424 -0
  368. package/src/persistence/conversation-mode-sessions.ts +460 -0
  369. package/src/persistence/conversation-queries.ts +6 -19
  370. package/src/persistence/llm-usage-store.ts +3 -9
  371. package/src/persistence/message-metadata.ts +25 -0
  372. package/src/persistence/migrations/381-create-conversation-mode-sessions.ts +41 -0
  373. package/src/persistence/migrations/382-create-client-connection-events.ts +40 -0
  374. package/src/persistence/migrations/__tests__/382-create-client-connection-events.test.ts +56 -0
  375. package/src/persistence/schema/conversations.ts +67 -0
  376. package/src/persistence/schema/infrastructure.ts +29 -0
  377. package/src/persistence/steps.ts +17 -0
  378. package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
  379. package/src/plugin-api/effective-context-window.ts +33 -0
  380. package/src/plugin-api/index.ts +24 -5
  381. package/src/plugin-api/plugin-name-env.ts +125 -0
  382. package/src/plugin-api/resolve-credential.ts +79 -20
  383. package/src/plugin-api/vision-support.test.ts +22 -0
  384. package/src/plugin-api/vision-support.ts +17 -5
  385. package/src/plugins/__tests__/active-plugin-env.test.ts +136 -0
  386. package/src/plugins/active-plugin-env.ts +51 -0
  387. package/src/plugins/defaults/index.ts +24 -0
  388. package/src/plugins/defaults/memory/__tests__/archive-removal-framing.test.ts +64 -0
  389. package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
  390. package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
  391. package/src/plugins/defaults/memory/context-search/agent-runner.ts +78 -22
  392. package/src/plugins/defaults/memory/context-search/format.ts +51 -7
  393. package/src/plugins/defaults/memory/context-search/limits.ts +10 -12
  394. package/src/plugins/defaults/memory/context-search/recall-input.ts +38 -0
  395. package/src/plugins/defaults/memory/context-search/search.ts +8 -14
  396. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +1 -0
  397. package/src/plugins/defaults/memory/context-search/types.ts +1 -11
  398. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
  399. package/src/plugins/defaults/memory/graph/tool-handlers.ts +12 -21
  400. package/src/plugins/defaults/memory/graph/tools.ts +35 -64
  401. package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
  402. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +5 -0
  403. package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
  404. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +2 -2
  405. package/src/plugins/defaults/memory/tools.test.ts +124 -9
  406. package/src/plugins/defaults/memory/tools.ts +38 -11
  407. package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +165 -27
  408. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
  409. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +46 -27
  410. package/src/plugins/defaults/memory/v3/orchestrate.ts +78 -38
  411. package/src/plugins/defaults/memory/v3/pool-log-store.ts +65 -79
  412. package/src/plugins/defaults/memory/v3/pool-select.test.ts +14 -5
  413. package/src/plugins/defaults/memory/v3/pool-select.ts +683 -44
  414. package/src/plugins/defaults/memory/worker-control.ts +15 -5
  415. package/src/plugins/defaults/task-progress/__tests__/registration.test.ts +70 -0
  416. package/src/plugins/defaults/task-progress/__tests__/task-progress-context.test.ts +380 -0
  417. package/src/plugins/defaults/task-progress/hooks/post-compact.ts +19 -0
  418. package/src/plugins/defaults/task-progress/hooks/user-prompt-submit.ts +24 -0
  419. package/src/plugins/defaults/task-progress/package.json +14 -0
  420. package/src/plugins/defaults/task-progress/src/apply-task-progress-context.ts +93 -0
  421. package/src/plugins/defaults/task-progress/src/format-task-progress-context.ts +67 -0
  422. package/src/providers/__tests__/context-overflow-error.test.ts +10 -0
  423. package/src/providers/__tests__/search-provider-catalog.test.ts +18 -0
  424. package/src/providers/anthropic/client.ts +10 -1
  425. package/src/providers/anthropic-gateway-shared.ts +6 -0
  426. package/src/providers/fetch-provider-catalog.ts +11 -0
  427. package/src/providers/gemini/client.ts +25 -8
  428. package/src/providers/inference/adapter-factory.ts +1 -1
  429. package/src/providers/jev/client.test.ts +10 -0
  430. package/src/providers/jev/client.ts +20 -4
  431. package/src/providers/model-catalog.ts +4 -3
  432. package/src/providers/openai/__tests__/chat-completions-extra-body.test.ts +94 -1
  433. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +106 -1
  434. package/src/providers/openai/__tests__/chat-template-flatten.test.ts +24 -0
  435. package/src/providers/openai/__tests__/google-thought-signature.test.ts +1 -2
  436. package/src/providers/openai/chat-completions-provider.ts +100 -29
  437. package/src/providers/openai/google-thought-signature.ts +0 -6
  438. package/src/providers/openai/responses-provider.ts +23 -1
  439. package/src/providers/ratelimit.ts +1 -3
  440. package/src/providers/search-provider-catalog.ts +24 -0
  441. package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +24 -0
  442. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +7 -1
  443. package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +50 -1
  444. package/src/providers/speech-to-text/deepgram-flux-frames.ts +11 -0
  445. package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +13 -0
  446. package/src/providers/types.ts +5 -0
  447. package/src/routes/control.ts +7 -5
  448. package/src/runtime/AGENTS.md +4 -2
  449. package/src/runtime/actor-trust-resolver.ts +3 -3
  450. package/src/runtime/agent-wake.ts +1 -1
  451. package/src/runtime/approval-message-composer.ts +3 -69
  452. package/src/runtime/assistant-event-hub.ts +73 -75
  453. package/src/runtime/assistant-event-publish-options.ts +7 -0
  454. package/src/runtime/assistant-event-targeting.ts +79 -0
  455. package/src/runtime/assistant-stream-state.ts +13 -100
  456. package/src/runtime/background-job-runner.ts +5 -5
  457. package/src/runtime/channel-retry-sweep.ts +1 -0
  458. package/src/runtime/guardian-action-message-composer.ts +8 -161
  459. package/src/runtime/guardian-reply-router.ts +28 -32
  460. package/src/runtime/http-types.ts +6 -0
  461. package/src/runtime/message-composer-types.ts +3 -61
  462. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +67 -1
  463. package/src/runtime/migrations/vbundle-builder.ts +24 -1
  464. package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -4
  465. package/src/runtime/migrations/vbundle-import-policy.ts +10 -0
  466. package/src/runtime/migrations/vbundle-importer.ts +4 -1
  467. package/src/runtime/migrations/vbundle-streaming-importer.ts +4 -1
  468. package/src/runtime/migrations/vbundle-validator.ts +1 -0
  469. package/src/runtime/pending-interactions-mode-session.test.ts +62 -0
  470. package/src/runtime/pending-interactions.ts +29 -0
  471. package/src/runtime/routes/__tests__/client-history-routes.test.ts +104 -0
  472. package/src/runtime/routes/__tests__/image-generation-routes.test.ts +97 -0
  473. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +1 -1
  474. package/src/runtime/routes/__tests__/roadmap-routes.test.ts +29 -6
  475. package/src/runtime/routes/browser-context.ts +31 -11
  476. package/src/runtime/routes/browser-routes.ts +43 -4
  477. package/src/runtime/routes/btw-routes.ts +9 -4
  478. package/src/runtime/routes/client-routes.ts +108 -0
  479. package/src/runtime/routes/conversation-management-routes.ts +4 -1
  480. package/src/runtime/routes/conversation-routes.ts +113 -27
  481. package/src/runtime/routes/credential-prompt-routes.ts +4 -3
  482. package/src/runtime/routes/credential-routes.ts +1 -2
  483. package/src/runtime/routes/desktop-setup-routes.test.ts +9 -18
  484. package/src/runtime/routes/desktop-setup-routes.ts +4 -6
  485. package/src/runtime/routes/documents-routes.ts +51 -0
  486. package/src/runtime/routes/email-routes.ts +3 -7
  487. package/src/runtime/routes/events-routes.ts +75 -54
  488. package/src/runtime/routes/identity-routes.ts +1 -5
  489. package/src/runtime/routes/image-generation-routes.ts +8 -14
  490. package/src/runtime/routes/inbound-message-handler.ts +35 -38
  491. package/src/runtime/routes/inbound-stages/backfill-sender-provenance.test.ts +168 -0
  492. package/src/runtime/routes/inbound-stages/backfill-sender-provenance.ts +96 -0
  493. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +38 -9
  494. package/src/runtime/routes/inbound-stages/background-dispatch.ts +2 -5
  495. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -0
  496. package/src/runtime/routes/llm-context-normalization.ts +1 -7
  497. package/src/runtime/routes/migration-routes.ts +73 -2
  498. package/src/runtime/routes/notification-routes.ts +10 -0
  499. package/src/runtime/routes/oauth-providers.ts +7 -0
  500. package/src/runtime/routes/plugins-routes.ts +6 -0
  501. package/src/runtime/routes/roadmap-routes.ts +47 -8
  502. package/src/runtime/routes/secret-routes.ts +1 -1
  503. package/src/runtime/routes/settings-routes.ts +10 -4
  504. package/src/runtime/routes/watcher-routes.ts +1 -3
  505. package/src/runtime/trust-class.test.ts +7 -6
  506. package/src/runtime/trust-class.ts +9 -17
  507. package/src/schedule/__tests__/worker-control.test.ts +36 -5
  508. package/src/schedule/worker-control.ts +15 -5
  509. package/src/security/secure-keys.ts +53 -103
  510. package/src/skills/clawhub.ts +3 -8
  511. package/src/skills/managed-store.ts +1 -5
  512. package/src/stt/types.ts +4 -0
  513. package/src/subagent/notify.ts +54 -34
  514. package/src/subagent/parent-notification.ts +6 -0
  515. package/src/telemetry/__tests__/phone-call-funnel.test.ts +72 -0
  516. package/src/telemetry/phone-call-funnel.ts +144 -0
  517. package/src/tools/__tests__/tool-schema-root-combinator-guard.test.ts +81 -0
  518. package/src/tools/ask-question/ask-question-tool.ts +6 -4
  519. package/src/tools/browser/browser-execution.ts +22 -59
  520. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +561 -39
  521. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +435 -39
  522. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +1 -8
  523. package/src/tools/client-os.ts +15 -0
  524. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
  525. package/src/tools/computer-use/target.ts +42 -0
  526. package/src/tools/document/document-tool.ts +13 -18
  527. package/src/tools/execution-target.ts +14 -16
  528. package/src/tools/host-terminal/host-shell.ts +4 -1
  529. package/src/tools/network/__tests__/web-fetch-tinyfish.test.ts +250 -0
  530. package/src/tools/network/__tests__/web-search.test.ts +203 -0
  531. package/src/tools/network/web-fetch.ts +274 -7
  532. package/src/tools/network/web-search.ts +468 -6
  533. package/src/tools/permission-checker.ts +3 -3
  534. package/src/tools/policy-context.ts +3 -1
  535. package/src/tools/skills/load.ts +2 -1
  536. package/src/tools/skills/sandbox-runner.ts +11 -2
  537. package/src/tools/skills/skill-script-runner.ts +7 -0
  538. package/src/tools/skills/skill-tool-factory.ts +15 -1
  539. package/src/tools/terminal/__tests__/safe-env.test.ts +11 -0
  540. package/src/tools/terminal/safe-env.ts +4 -0
  541. package/src/tools/terminal/shell.ts +2 -0
  542. package/src/tools/tool-approval-handler.ts +5 -1
  543. package/src/tools/tool-types.ts +3 -3
  544. package/src/tools/types.ts +8 -2
  545. package/src/util/__tests__/worker-process-command.test.ts +5 -4
  546. package/src/util/abort-reasons.ts +18 -26
  547. package/src/util/canonicalize-identity.test.ts +21 -0
  548. package/src/util/canonicalize-identity.ts +16 -0
  549. package/src/util/errors.ts +13 -3
  550. package/src/util/provider-error-patterns.ts +3 -0
  551. package/src/util/worker-process.ts +77 -35
  552. package/src/workspace/migrations/157-add-desktop-files-launcher.ts +94 -0
  553. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +4 -10
  554. package/src/workspace/migrations/__tests__/157-add-desktop-files-launcher.test.ts +113 -0
  555. package/src/workspace/migrations/registry.ts +2 -0
  556. package/src/__tests__/computer-use-window-schema.test.ts +0 -24
  557. package/src/api/events/heartbeat-alert.ts +0 -20
  558. package/src/daemon/message-types/web-activity.ts +0 -65
  559. package/src/desktop/desktop-dependencies.test.ts +0 -131
  560. package/src/tools/computer-use/definitions.ts +0 -607
@@ -1089,6 +1089,7 @@ async function drainSingleMessage(
1089
1089
  content: resolvedContent,
1090
1090
  attachments: next.attachments,
1091
1091
  requestId: next.requestId,
1092
+ activeSurfaceId: next.activeSurfaceId,
1092
1093
  metadata: { ...next.metadata, sentAt: next.sentAt },
1093
1094
  displayContent: next.displayContent,
1094
1095
  clientMessageId: next.clientMessageId,
@@ -1155,6 +1156,7 @@ async function drainSingleMessage(
1155
1156
  messageId: userMessageId,
1156
1157
  requestId: next.requestId,
1157
1158
  clientMessageId: next.clientMessageId,
1159
+ modeSession: conversation.modeSessions.getTurnOwner(next.requestId),
1158
1160
  });
1159
1161
  // The row this echo announces is already durably persisted, so advance
1160
1162
  // the snapshot↔stream anchor to the echo's seq (stamped inline by the
@@ -1464,6 +1466,7 @@ async function drainBatch(
1464
1466
  content: qmContent,
1465
1467
  attachments: qm.attachments,
1466
1468
  requestId: qm.requestId,
1469
+ activeSurfaceId: qm.activeSurfaceId,
1467
1470
  metadata: { ...qm.metadata, sentAt: qm.sentAt },
1468
1471
  displayContent: qm.displayContent,
1469
1472
  clientMessageId: qm.clientMessageId,
@@ -1574,6 +1577,7 @@ async function drainBatch(
1574
1577
  messageId: lastUserMessageId,
1575
1578
  requestId: qm.requestId,
1576
1579
  clientMessageId: qm.clientMessageId,
1580
+ modeSession: conversation.modeSessions.getTurnOwner(qm.requestId),
1577
1581
  });
1578
1582
  // Advance the snapshot↔stream anchor to this echo's seq — the batched
1579
1583
  // row persisted just above and the agent loop for the batch has not
@@ -2298,6 +2302,7 @@ export async function processMessage(
2298
2302
  content: resolvedContent,
2299
2303
  attachments,
2300
2304
  requestId,
2305
+ activeSurfaceId,
2301
2306
  displayContent,
2302
2307
  scripted,
2303
2308
  ...(callerMetadata ? { metadata: callerMetadata } : {}),
@@ -8,6 +8,8 @@
8
8
  import { statSync } from "node:fs";
9
9
  import { join } from "node:path";
10
10
 
11
+ import { TrustClassSchema } from "@vellumai/gateway-client";
12
+
11
13
  import {
12
14
  getApp,
13
15
  getAppDirPath,
@@ -81,7 +83,6 @@ import type {
81
83
  import type { ContentBlock, Message } from "../providers/types.js";
82
84
  import type { TrustClass } from "../runtime/actor-trust-resolver.js";
83
85
  import { resolveCapabilities } from "../runtime/capabilities.js";
84
- import { trustClassSchema } from "../runtime/trust-class.js";
85
86
  import type { SubagentState } from "../subagent/types.js";
86
87
  import { TERMINAL_STATUSES } from "../subagent/types.js";
87
88
  import { canonicalizeInboundIdentity } from "../util/canonicalize-identity.js";
@@ -903,6 +904,11 @@ export function buildChannelCapabilityBlock(
903
904
  "- Do NOT use markdown tables — use bullet lists instead. No markdown headers — use **bold** or CAPS for emphasis.",
904
905
  );
905
906
  }
907
+ if (caps.channel === "email") {
908
+ lines.push(
909
+ "- Conversation text is not emailed. To reply, run `assistant email send` (see `assistant email send --help`). Use `--reply-to` to keep the thread. Skip a reply only when none is needed.",
910
+ );
911
+ }
906
912
  }
907
913
 
908
914
  // Inject group chat etiquette only when the chat type indicates a multi-party
@@ -1183,7 +1189,7 @@ function placeholderForBlockType(type: ContentBlock["type"]): string | null {
1183
1189
  function rowToRenderable(row: SlackTranscriptInputRow): RenderableSlackMessage {
1184
1190
  const slackMeta = readSlackMetadataFromMessageMetadata(row.metadata);
1185
1191
  const provenanceTrustClass = row.metadata
1186
- ? trustClassSchema.safeParse(
1192
+ ? TrustClassSchema.safeParse(
1187
1193
  safeParseRecord(row.metadata).provenanceTrustClass,
1188
1194
  ).data
1189
1195
  : undefined;
@@ -2035,20 +2041,6 @@ export async function composeInjectorChain(ctx: TurnContext): Promise<string> {
2035
2041
  */
2036
2042
  const DEFAULT_PLACEMENT: InjectionPlacement = "append-user-tail";
2037
2043
 
2038
- /**
2039
- * Count leading memory-prefix blocks on a user message's `content`.
2040
- *
2041
- * Delegates to {@link countMemoryPrefixBlocks} from
2042
- * `memory/graph/conversation-graph-memory.js` — the canonical state-machine
2043
- * for locating the memory-prefix boundary. Reusing it here keeps the
2044
- * PKB-context / PKB-reminder / NOW splice rules aligned on a single source
2045
- * of truth so their ordering relative to any memory prefix is stable and
2046
- * testable.
2047
- */
2048
- function countMemoryPrefixBlocksOnContent(content: ContentBlock[]): number {
2049
- return countMemoryPrefixBlocks(content);
2050
- }
2051
-
2052
2044
  /**
2053
2045
  * Apply one injector block to a `runMessages` array according to its
2054
2046
  * declared {@link InjectionPlacement}:
@@ -2101,9 +2093,7 @@ function applyInjectionBlock(
2101
2093
  { ...userTail, content: [...userTail.content, textBlock] },
2102
2094
  ];
2103
2095
  case "after-memory-prefix": {
2104
- const memoryPrefixCount = countMemoryPrefixBlocksOnContent(
2105
- userTail.content,
2106
- );
2096
+ const memoryPrefixCount = countMemoryPrefixBlocks(userTail.content);
2107
2097
  return [
2108
2098
  ...runMessages.slice(0, -1),
2109
2099
  {
@@ -2161,7 +2151,7 @@ function stripTailV2DynamicMemoryPrefix(
2161
2151
  if (!last || last.role !== "user") {
2162
2152
  return messages;
2163
2153
  }
2164
- const prefixCount = countMemoryPrefixBlocksOnContent(last.content);
2154
+ const prefixCount = countMemoryPrefixBlocks(last.content);
2165
2155
  if (prefixCount === 0) {
2166
2156
  return messages;
2167
2157
  }
@@ -463,6 +463,7 @@ export function projectSkillTools(
463
463
  skill.directoryPath,
464
464
  currentHash,
465
465
  skill.bundled,
466
+ skill.owner?.kind === "plugin" ? skill.owner.id : undefined,
466
467
  );
467
468
 
468
469
  if (tools.length > 0) {
@@ -550,10 +550,10 @@ export function clearAllActiveConversations(): number {
550
550
  /**
551
551
  * Evict in-memory conversations after a config/prompt reload so the next
552
552
  * turn rebuilds them against the new config. Conversations with in-flight work
553
- * (a live turn, a queued successor, or an active subagent) are marked stale
554
- * and rebuilt by `getOrCreateConversation` once that work finishes. Idle
555
- * conversations are disposed and dropped. Also used when provider credentials
556
- * change.
553
+ * are marked stale and rebuilt by `getOrCreateConversation` once that work
554
+ * finishes. This includes live mode-session sources and process-local
555
+ * structural continuations. Idle conversations are disposed and dropped. Also
556
+ * used when provider credentials change.
557
557
  */
558
558
  export function evictConversationsForReload(): void {
559
559
  const subagentManager = getSubagentManager();
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Canonical conversation surface snapshots for host readers.
3
+ *
4
+ * Combines an unbounded persisted `ui_surface` scan with the loaded
5
+ * conversation's live `surfaceState` and current-turn snapshots. Hits from
6
+ * the persisted scan are never written into `surfaceState`.
7
+ */
8
+
9
+ import { coerceSurfaceDataRecord } from "../api/surfaces.js";
10
+ import { getMessages } from "../persistence/conversation-crud.js";
11
+ import { resolveCapabilities } from "../runtime/capabilities.js";
12
+ import { isPlainObject } from "../util/object.js";
13
+ import { findConversationOrSubagent } from "./conversation-registry.js";
14
+ import { isRowVisibleToUntrustedActor } from "./message-provenance.js";
15
+
16
+ export interface ConversationSurfaceSnapshot {
17
+ surfaceId: string;
18
+ surfaceType: string;
19
+ data: Record<string, unknown>;
20
+ completed: boolean;
21
+ completionSummary?: string;
22
+ }
23
+
24
+ function cloneSurfaceData(value: unknown): Record<string, unknown> {
25
+ const record = coerceSurfaceDataRecord(value);
26
+ try {
27
+ return structuredClone(record);
28
+ } catch {
29
+ return JSON.parse(JSON.stringify(record)) as Record<string, unknown>;
30
+ }
31
+ }
32
+
33
+ function surfaceTypeFromBlock(value: unknown): string {
34
+ return typeof value === "string" && value.trim().length > 0
35
+ ? value
36
+ : "dynamic_page";
37
+ }
38
+
39
+ function rememberOrder(order: string[], surfaceId: string): void {
40
+ if (!order.includes(surfaceId)) {
41
+ order.push(surfaceId);
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Current surface snapshots for a loaded conversation.
47
+ *
48
+ * Fails closed to an empty list when the conversation is not already
49
+ * loaded or the turn-or-resting trust snapshot is missing. Untrusted
50
+ * views reuse {@link isRowVisibleToUntrustedActor} and do not add
51
+ * live-only cards that never appeared in a visible persisted row.
52
+ */
53
+ export function listConversationSurfaceSnapshots(
54
+ conversationId: string,
55
+ ): ConversationSurfaceSnapshot[] {
56
+ const conversation = findConversationOrSubagent(conversationId);
57
+ if (!conversation) {
58
+ return [];
59
+ }
60
+ const trust = conversation.getTurnOrRestingTrust();
61
+ if (!trust) {
62
+ return [];
63
+ }
64
+ const canAccessMemory = resolveCapabilities(trust.trustClass).canAccessMemory;
65
+ const filterByProvenance = !canAccessMemory;
66
+
67
+ const order: string[] = [];
68
+ const records = new Map<string, ConversationSurfaceSnapshot>();
69
+
70
+ const rows = getMessages(conversationId);
71
+ for (const row of rows) {
72
+ if (filterByProvenance && !isRowVisibleToUntrustedActor(row.metadata)) {
73
+ continue;
74
+ }
75
+ if (!Array.isArray(row.content)) {
76
+ continue;
77
+ }
78
+ for (const block of row.content) {
79
+ if (!isPlainObject(block) || block.type !== "ui_surface") {
80
+ continue;
81
+ }
82
+ const surfaceId = block.surfaceId;
83
+ if (typeof surfaceId !== "string" || surfaceId.length === 0) {
84
+ continue;
85
+ }
86
+ const completionSummary =
87
+ typeof block.completionSummary === "string"
88
+ ? block.completionSummary
89
+ : undefined;
90
+ rememberOrder(order, surfaceId);
91
+ records.set(surfaceId, {
92
+ surfaceId,
93
+ surfaceType: surfaceTypeFromBlock(block.surfaceType),
94
+ data: cloneSurfaceData(block.data),
95
+ completed: block.completed === true,
96
+ ...(completionSummary !== undefined ? { completionSummary } : {}),
97
+ });
98
+ }
99
+ }
100
+
101
+ for (const [surfaceId, entry] of conversation.surfaceState.entries()) {
102
+ const existing = records.get(surfaceId);
103
+ if (!existing && filterByProvenance) {
104
+ continue;
105
+ }
106
+ rememberOrder(order, surfaceId);
107
+ records.set(surfaceId, {
108
+ surfaceId,
109
+ surfaceType: entry.surfaceType,
110
+ data: cloneSurfaceData(entry.data),
111
+ completed: existing?.completed === true,
112
+ ...(existing?.completionSummary !== undefined
113
+ ? { completionSummary: existing.completionSummary }
114
+ : {}),
115
+ });
116
+ }
117
+
118
+ for (const surface of conversation.currentTurnSurfaces) {
119
+ const existing = records.get(surface.surfaceId);
120
+ const completionSummary =
121
+ typeof surface.completionSummary === "string"
122
+ ? surface.completionSummary
123
+ : existing?.completionSummary;
124
+ rememberOrder(order, surface.surfaceId);
125
+ records.set(surface.surfaceId, {
126
+ surfaceId: surface.surfaceId,
127
+ surfaceType: surface.surfaceType,
128
+ data: cloneSurfaceData(surface.data),
129
+ completed: surface.completed === true || existing?.completed === true,
130
+ ...(completionSummary !== undefined ? { completionSummary } : {}),
131
+ });
132
+ }
133
+
134
+ return order.map((surfaceId) => records.get(surfaceId)!);
135
+ }
@@ -28,6 +28,8 @@ import {
28
28
  resolveEffectiveAppHtml,
29
29
  updateApp,
30
30
  } from "../apps/app-store.js";
31
+ import { executeDesktopComputerUse } from "../desktop/desktop-computer-use.js";
32
+ import { canUseVirtualDesktop } from "../desktop/virtual-desktop-feature.js";
31
33
  import { recordActivationEvent } from "../onboarding/onboarding-events-store.js";
32
34
  import {
33
35
  getMessages,
@@ -57,6 +59,7 @@ import {
57
59
  import { resolveAppId } from "../tools/apps/resolve-app-id.js";
58
60
  import { formatDesktopAppRequired } from "../tools/capability-offer.js";
59
61
  import { POINT_AT_PROXY_TOOL } from "../tools/computer-use/skill-proxy-bridge.js";
62
+ import { computerUseTarget } from "../tools/computer-use/target.js";
60
63
  import type { ToolExecutionResult } from "../tools/types.js";
61
64
  import { getLogger } from "../util/logger.js";
62
65
  import { isPlainObject } from "../util/object.js";
@@ -70,7 +73,7 @@ import {
70
73
  type SurfaceShowPair,
71
74
  type SurfaceStateEntry,
72
75
  } from "./conversation-surface-state.js";
73
- import type { HostCuProxy } from "./host-cu-proxy.js";
76
+ import { HostCuProxy } from "./host-cu-proxy.js";
74
77
  import { resolveHostCuTarget } from "./host-cu-target.js";
75
78
  import type {
76
79
  AnySurfaceData,
@@ -89,9 +92,11 @@ import type {
89
92
  } from "./message-protocol.js";
90
93
  import { INTERACTIVE_SURFACE_TYPES } from "./message-protocol.js";
91
94
  import { isRowVisibleToUntrustedActor } from "./message-provenance.js";
95
+ import { bestEffortModeSessionTracking } from "./mode-session-tracking.js";
92
96
  import type { TrustContext } from "./trust-context-types.js";
93
97
  import { restingTrust } from "./trust-context-types.js";
94
98
  import { turnActorPrincipalId } from "./turn-actor.js";
99
+ import { virtualDesktopContext } from "./virtual-desktop-context.js";
95
100
  export {
96
101
  buildSurfaceShowPair,
97
102
  type CurrentTurnSurface,
@@ -178,12 +183,61 @@ const NON_BLOCKING_PENDING_SURFACE_TYPES = new Set<SurfaceType>([
178
183
  export function hasBlockingPendingSurface(ctx: {
179
184
  pendingSurfaceActions: Map<string, { surfaceType: SurfaceType }>;
180
185
  }): boolean {
181
- for (const entry of ctx.pendingSurfaceActions.values()) {
186
+ return blockingPendingSurfaceIds(ctx).length > 0;
187
+ }
188
+
189
+ export function blockingPendingSurfaceIds(ctx: {
190
+ pendingSurfaceActions: Map<string, { surfaceType: SurfaceType }>;
191
+ }): string[] {
192
+ const ids: string[] = [];
193
+ for (const [surfaceId, entry] of ctx.pendingSurfaceActions) {
182
194
  if (!NON_BLOCKING_PENDING_SURFACE_TYPES.has(entry.surfaceType)) {
183
- return true;
195
+ ids.push(surfaceId);
184
196
  }
185
197
  }
186
- return false;
198
+ return ids;
199
+ }
200
+
201
+ function acceptModeSessionSurfaceResponse(
202
+ ctx: Conversation,
203
+ requestId: string,
204
+ surfaceId: string,
205
+ ): void {
206
+ bestEffortModeSessionTracking("surface response admission", () =>
207
+ ctx.modeSessions?.acceptTurn(requestId, {
208
+ kind: "surface",
209
+ responseId: surfaceId,
210
+ }),
211
+ );
212
+ }
213
+
214
+ function invalidateModeSessionSurfaceWait(
215
+ ctx: Partial<Pick<Conversation, "modeSessions">>,
216
+ surfaceId: string,
217
+ ): void {
218
+ bestEffortModeSessionTracking("surface wait invalidation", () =>
219
+ ctx.modeSessions?.invalidateStructuralWait({
220
+ kind: "surface",
221
+ responseId: surfaceId,
222
+ }),
223
+ );
224
+ }
225
+
226
+ function settleModeSessionSurfaceWait(
227
+ ctx: Pick<Conversation, "conversationId" | "modeSessions">,
228
+ surfaceId: string,
229
+ ): void {
230
+ try {
231
+ ctx.modeSessions?.settleStructuralWait(
232
+ { kind: "surface", responseId: surfaceId },
233
+ { status: "completed", endReason: "surface_launch_settled" },
234
+ );
235
+ } catch (err) {
236
+ log.warn(
237
+ { err, conversationId: ctx.conversationId, surfaceId },
238
+ "Mode-session launcher settlement failed",
239
+ );
240
+ }
187
241
  }
188
242
 
189
243
  /**
@@ -1292,7 +1346,8 @@ export function cleanupStandaloneSurface(
1292
1346
  | "lastSurfaceAction"
1293
1347
  | "accumulatedSurfaceState"
1294
1348
  | "surfaceUndoStacks"
1295
- >,
1349
+ > &
1350
+ Partial<Pick<Conversation, "modeSessions">>,
1296
1351
  surfaceId: string,
1297
1352
  ): void {
1298
1353
  const entry = ctx.pendingStandaloneSurfaces?.get(surfaceId);
@@ -1305,6 +1360,7 @@ export function cleanupStandaloneSurface(
1305
1360
  ctx.lastSurfaceAction.delete(surfaceId);
1306
1361
  ctx.accumulatedSurfaceState.delete(surfaceId);
1307
1362
  ctx.surfaceUndoStacks.delete(surfaceId);
1363
+ invalidateModeSessionSurfaceWait(ctx, surfaceId);
1308
1364
 
1309
1365
  // Record a tombstone so late client actions are silently dropped.
1310
1366
  if (ctx.recentlyCompletedStandaloneSurfaces) {
@@ -2110,6 +2166,7 @@ export async function handleSurfaceAction(
2110
2166
  ...(anchorMessageId ? { anchorMessageId } : {}),
2111
2167
  ...(originTrustContext ? { originTrustContext } : {}),
2112
2168
  });
2169
+ settleModeSessionSurfaceWait(ctx, surfaceId);
2113
2170
  log.info(
2114
2171
  { originConversationId: ctx.conversationId, conversationId, surfaceId },
2115
2172
  "launch_conversation dispatched inline from surface action",
@@ -2284,6 +2341,8 @@ export async function handleSurfaceAction(
2284
2341
  return QUEUE_FULL_RESULT;
2285
2342
  }
2286
2343
 
2344
+ acceptModeSessionSurfaceResponse(ctx, requestId, surfaceId);
2345
+
2287
2346
  // Terminal user commit accepted — record the activation milestone if this
2288
2347
  // surface was tagged (best-effort, no-op otherwise). Deferred until after
2289
2348
  // the rejection check so a queue-full click doesn't over-report a moment
@@ -2310,6 +2369,7 @@ export async function handleSurfaceAction(
2310
2369
  type: "user_message_echo",
2311
2370
  text: prompt,
2312
2371
  conversationId: ctx.conversationId,
2372
+ modeSession: ctx.modeSessions.getTurnOwner(requestId),
2313
2373
  });
2314
2374
  }
2315
2375
 
@@ -2537,6 +2597,8 @@ export async function handleSurfaceAction(
2537
2597
  return QUEUE_FULL_RESULT;
2538
2598
  }
2539
2599
 
2600
+ acceptModeSessionSurfaceResponse(ctx, requestId, surfaceId);
2601
+
2540
2602
  // Terminal user commit accepted — record the activation milestone if this
2541
2603
  // surface was tagged (best-effort, no-op otherwise). Deferred until after the
2542
2604
  // rejection check so a queue-full click doesn't over-report a moment (and the
@@ -2563,6 +2625,7 @@ export async function handleSurfaceAction(
2563
2625
  type: "user_message_echo",
2564
2626
  text: prompt,
2565
2627
  conversationId: ctx.conversationId,
2628
+ modeSession: ctx.modeSessions.getTurnOwner(requestId),
2566
2629
  });
2567
2630
  }
2568
2631
  if (result.queued) {
@@ -3161,6 +3224,28 @@ export async function surfaceProxyResolver(
3161
3224
  ): Promise<ToolExecutionResult> {
3162
3225
  // Route CU proxy tools (all computer_use_* action tools)
3163
3226
  if (toolName.startsWith("computer_use_")) {
3227
+ const desktopContext = virtualDesktopContext(ctx, signal);
3228
+ if (
3229
+ toolName !== POINT_AT_PROXY_TOOL &&
3230
+ computerUseTarget(input, desktopContext) === "assistant-desktop"
3231
+ ) {
3232
+ if (!canUseVirtualDesktop(desktopContext)) {
3233
+ return {
3234
+ content:
3235
+ "The assistant desktop requires an identified guardian and an enabled platform-hosted assistant.",
3236
+ isError: true,
3237
+ };
3238
+ }
3239
+ if (!ctx.hostCuProxy) {
3240
+ ctx.setHostCuProxy(new HostCuProxy());
3241
+ }
3242
+ return executeDesktopComputerUse(
3243
+ toolName,
3244
+ input,
3245
+ desktopContext,
3246
+ ctx.hostCuProxy!,
3247
+ );
3248
+ }
3164
3249
  const hostCuProxy = ensureHostCuProxy(ctx);
3165
3250
  if (!hostCuProxy || !hostCuProxy.isAvailable()) {
3166
3251
  return {
@@ -3180,6 +3265,15 @@ export async function surfaceProxyResolver(
3180
3265
  : typeof input.answer === "string"
3181
3266
  ? input.answer
3182
3267
  : "Task complete";
3268
+ bestEffortModeSessionTracking("computer completion", () =>
3269
+ ctx.computerUseModeSessions.endTask({
3270
+ turnId: ctx.currentRequestId,
3271
+ source: {
3272
+ sourceId: hostCuProxy.sourceId,
3273
+ generation: hostCuProxy.resetGeneration,
3274
+ },
3275
+ }),
3276
+ );
3183
3277
  hostCuProxy.endTask(ctx.conversationId);
3184
3278
  return { content: summary, isError: false };
3185
3279
  }
@@ -3215,9 +3309,11 @@ export async function surfaceProxyResolver(
3215
3309
  // `maxStepsPerSession` would let a long walkthrough exhaust a budget
3216
3310
  // meant for actions and be told to call `computer_use_done`, which has
3217
3311
  // nothing to do with what it was doing.
3312
+ const activityAt = Date.now();
3218
3313
  if (toolName !== POINT_AT_PROXY_TOOL) {
3219
3314
  hostCuProxy.recordAction(toolName, input, reasoning);
3220
3315
  }
3316
+ const turnId = ctx.currentRequestId;
3221
3317
  return hostCuProxy.request(
3222
3318
  toolName,
3223
3319
  input,
@@ -3227,6 +3323,18 @@ export async function surfaceProxyResolver(
3227
3323
  signal,
3228
3324
  targetClientId,
3229
3325
  sourceActorPrincipalId,
3326
+ toolName !== POINT_AT_PROXY_TOOL && turnId
3327
+ ? () => {
3328
+ ctx.computerUseModeSessions.recordAction({
3329
+ turnId,
3330
+ source: {
3331
+ sourceId: hostCuProxy.sourceId,
3332
+ generation: hostCuProxy.resetGeneration,
3333
+ },
3334
+ at: activityAt,
3335
+ });
3336
+ }
3337
+ : undefined,
3230
3338
  );
3231
3339
  }
3232
3340
 
@@ -19,6 +19,7 @@ import {
19
19
  resolveSendUserMessageActive,
20
20
  SEND_USER_MESSAGE_TOOL_NAME,
21
21
  } from "../config/send-user-message-gate.js";
22
+ import { canUseVirtualDesktop } from "../desktop/virtual-desktop-feature.js";
22
23
  import { supportsChannelReaction } from "../messaging/providers/index.js";
23
24
  import type { PermissionPrompter } from "../permissions/prompter.js";
24
25
  import type { SecretPrompter } from "../permissions/secret-prompter.js";
@@ -87,6 +88,7 @@ import {
87
88
  } from "./doordash-steps.js";
88
89
  import { runPostExecutionSideEffects } from "./tool-side-effects.js";
89
90
  import { FALLBACK_TURN_TRUST, resolveTrustClass } from "./trust-context.js";
91
+ import { virtualDesktopContext } from "./virtual-desktop-context.js";
90
92
 
91
93
  const log = getLogger("conversation-tool-setup");
92
94
 
@@ -462,8 +464,7 @@ export function createToolExecutor(
462
464
  sendUserMessageActive: resolveSendUserMessageActive(ctx),
463
465
  toolUseId,
464
466
  isPlatformHosted: getIsPlatform(),
465
- transportInterface: ctx.transportInterface,
466
- clientOs: resolveTurnClientOs(ctx).clientOs,
467
+ ...resolveTurnClientOs(ctx),
467
468
  overrideProfile: ctx.currentTurnOverrideProfile,
468
469
  cronRunId: ctx.currentTurnCronRunId,
469
470
  invokingCallSite: ctx.currentCallSite ?? "mainAgent",
@@ -743,6 +744,7 @@ function isToolSupportedOnClientOs(name: string, ctx: Conversation): boolean {
743
744
  clientOs,
744
745
  transportInterface,
745
746
  sourceActorPrincipalId: ctx.getTurnActorPrincipalId?.(),
747
+ trustClass: virtualDesktopContext(ctx).trustClass,
746
748
  });
747
749
  }
748
750
 
@@ -1191,7 +1193,7 @@ export function createResolveToolsCallback(
1191
1193
  definition.name === "bash"
1192
1194
  ? {
1193
1195
  ...definition,
1194
- description: `${definition.description} For browser tasks, use assistant browser navigate --url <url> directly. It installs the virtual desktop if needed, starts Chrome, and completes the action in one call. Use timeout_seconds: ${getConfig().timeouts.shellMaxTimeoutSec} for first use; setup progress is visible in the Virtual desktop panel. Use assistant browser --help for other browser actions. Use this managed path even if saved notes describe manual setup. Do not install packages or launch Chrome, X servers, or screenshot scripts yourself.`,
1196
+ description: `${definition.description} For browser tasks, use assistant browser navigate --url <url> directly. Chrome and desktop components are included in the assistant image. The command starts Chrome and completes the action without installing dependencies. If components are missing, report the image problem. Use assistant browser --help for other browser actions. Use this managed path even if saved notes describe manual setup. Do not install packages or launch Chrome, X servers, or screenshot scripts yourself.`,
1195
1197
  }
1196
1198
  : definition,
1197
1199
  );
@@ -1207,6 +1209,9 @@ export function createResolveToolsCallback(
1207
1209
  const effectivePreactivated = [
1208
1210
  ...DEFAULT_PREACTIVATED_SKILL_IDS,
1209
1211
  ...(ctx.preactivatedSkillIds ?? []),
1212
+ ...(canUseVirtualDesktop(virtualDesktopContext(ctx))
1213
+ ? ["computer-use"]
1214
+ : []),
1210
1215
  ];
1211
1216
  const projection = projectSkillTools(history, {
1212
1217
  preactivatedSkillIds: effectivePreactivated,