@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
@@ -32,6 +32,16 @@ interface ListHomeFeedPayload {
32
32
  updatedAt: string;
33
33
  }
34
34
 
35
+ function parseCommaSeparatedList(raw: string): string[] | undefined {
36
+ const items = raw
37
+ .split(",")
38
+ .map((item) => item.trim())
39
+ .filter((item) => {
40
+ return item.length > 0;
41
+ });
42
+ return items.length > 0 ? items : undefined;
43
+ }
44
+
35
45
  function parseBoundedInt(
36
46
  raw: string | undefined,
37
47
  label: string,
@@ -142,6 +152,7 @@ export function registerNotificationsCommand(program: Command): void {
142
152
  visibleInSourceNow: boolean;
143
153
  deadlineAt?: string;
144
154
  preferredChannels?: string;
155
+ channels?: string;
145
156
  sessionId?: string;
146
157
  dedupeKey?: string;
147
158
  deepLinkMetadata?: string;
@@ -220,14 +231,12 @@ export function registerNotificationsCommand(program: Command): void {
220
231
  deadlineAt = parsed;
221
232
  }
222
233
 
223
- // Parse --preferred-channels
224
- let preferredChannels: string[] | undefined;
225
- if (opts.preferredChannels) {
226
- preferredChannels = opts.preferredChannels
227
- .split(",")
228
- .map((ch) => ch.trim())
229
- .filter((ch) => ch.length > 0);
230
- }
234
+ const preferredChannels = opts.preferredChannels
235
+ ? parseCommaSeparatedList(opts.preferredChannels)
236
+ : undefined;
237
+ const channelAllowlist = opts.channels
238
+ ? parseCommaSeparatedList(opts.channels)
239
+ : undefined;
231
240
 
232
241
  // Parse --deep-link-metadata
233
242
  let deepLinkMetadata: Record<string, unknown> | undefined;
@@ -283,6 +292,9 @@ export function registerNotificationsCommand(program: Command): void {
283
292
  dispatched: boolean;
284
293
  deduplicated: boolean;
285
294
  reason: string;
295
+ selectedChannels?: string[];
296
+ deliveryResults?: unknown[];
297
+ receiptClass?: string;
286
298
  }>("emit_notification_signal", {
287
299
  body: {
288
300
  sourceChannel,
@@ -300,6 +312,7 @@ export function registerNotificationsCommand(program: Command): void {
300
312
  requestedBySource: sourceChannel,
301
313
  ...(opts.title ? { requestedTitle: opts.title } : {}),
302
314
  ...(preferredChannels?.length ? { preferredChannels } : {}),
315
+ ...(channelAllowlist?.length ? { channelAllowlist } : {}),
303
316
  ...(deepLinkMetadata ? { deepLinkMetadata } : {}),
304
317
  },
305
318
  ...(opts.dedupeKey ? { dedupeKey: opts.dedupeKey } : {}),
@@ -326,6 +339,9 @@ export function registerNotificationsCommand(program: Command): void {
326
339
  signalId: signal.signalId,
327
340
  dispatched: signal.dispatched,
328
341
  reason: signal.reason,
342
+ selectedChannels: signal.selectedChannels ?? [],
343
+ deliveryResults: signal.deliveryResults ?? [],
344
+ receiptClass: signal.receiptClass ?? "unknown",
329
345
  });
330
346
 
331
347
  if (!shouldOutputJson(cmd)) {
@@ -335,6 +351,12 @@ export function registerNotificationsCommand(program: Command): void {
335
351
  if (signal.reason) {
336
352
  log.info(` Reason: ${signal.reason}`);
337
353
  }
354
+ if (signal.selectedChannels && signal.selectedChannels.length > 0) {
355
+ log.info(` Channels: ${signal.selectedChannels.join(", ")}`);
356
+ }
357
+ if (signal.receiptClass) {
358
+ log.info(` Receipt: ${signal.receiptClass}`);
359
+ }
338
360
  }
339
361
  } catch (err) {
340
362
  const message = err instanceof Error ? err.message : String(err);
@@ -258,6 +258,11 @@ Examples:
258
258
  description:
259
259
  "Dot-notation path to a boolean field that must be truthy for the response to be valid",
260
260
  },
261
+ {
262
+ flags: "--response-ok-field <field>",
263
+ description:
264
+ "Dot-notation path to the boolean every response body carries to report success (Slack: ok); an explicit false under a 2xx fails the request",
265
+ },
261
266
  {
262
267
  flags: "--setup-notes <json>",
263
268
  description:
@@ -430,6 +435,11 @@ Examples:
430
435
  flags: "--identity-ok-field <field>",
431
436
  description: "Dot-notation path to a boolean ok field",
432
437
  },
438
+ {
439
+ flags: "--response-ok-field <field>",
440
+ description:
441
+ "Dot-notation path to the boolean every response body carries to report success",
442
+ },
433
443
  {
434
444
  flags: "--setup-notes <json>",
435
445
  description: "JSON array of setup instruction notes",
@@ -49,6 +49,7 @@ interface SerializedProvider {
49
49
  identityResponsePaths?: string[] | null;
50
50
  identityFormat?: string | null;
51
51
  identityOkField?: string | null;
52
+ responseOkField?: string | null;
52
53
  availableScopes?: unknown;
53
54
  setupNotes?: string[] | unknown;
54
55
  featureFlag?: string | null;
@@ -217,6 +218,9 @@ function formatProviderDetail(p: SerializedProvider): string {
217
218
  if (p.identityOkField) {
218
219
  lines.push(` Identity ok field: ${p.identityOkField}`);
219
220
  }
221
+ if (p.responseOkField) {
222
+ lines.push(` Response ok field: ${p.responseOkField}`);
223
+ }
220
224
  if (p.setupNotes) {
221
225
  if (Array.isArray(p.setupNotes)) {
222
226
  lines.push(
@@ -403,6 +407,7 @@ export function registerProviderCommands(oauth: Command): void {
403
407
  identityResponsePaths?: string;
404
408
  identityFormat?: string;
405
409
  identityOkField?: string;
410
+ responseOkField?: string;
406
411
  setupNotes?: string;
407
412
  availableScopes?: string;
408
413
  },
@@ -505,6 +510,9 @@ export function registerProviderCommands(oauth: Command): void {
505
510
  if (opts.identityOkField !== undefined) {
506
511
  body.identity_ok_field = opts.identityOkField;
507
512
  }
513
+ if (opts.responseOkField !== undefined) {
514
+ body.response_ok_field = opts.responseOkField;
515
+ }
508
516
  if (opts.setupNotes !== undefined) {
509
517
  body.setup_notes = JSON.parse(opts.setupNotes);
510
518
  }
@@ -578,6 +586,7 @@ export function registerProviderCommands(oauth: Command): void {
578
586
  identityResponsePaths?: string;
579
587
  identityFormat?: string;
580
588
  identityOkField?: string;
589
+ responseOkField?: string;
581
590
  setupNotes?: string;
582
591
  availableScopes?: string;
583
592
  },
@@ -686,6 +695,9 @@ export function registerProviderCommands(oauth: Command): void {
686
695
  if (opts.identityOkField !== undefined) {
687
696
  body.identity_ok_field = opts.identityOkField;
688
697
  }
698
+ if (opts.responseOkField !== undefined) {
699
+ body.response_ok_field = opts.responseOkField;
700
+ }
689
701
  if (opts.setupNotes !== undefined) {
690
702
  body.setup_notes = JSON.parse(opts.setupNotes);
691
703
  }
@@ -17,6 +17,7 @@ let handleRequestResult: {
17
17
  body: unknown;
18
18
  bodyEncoding?: "base64";
19
19
  account?: string | null;
20
+ hint?: string;
20
21
  } = {
21
22
  ok: true,
22
23
  status: 200,
@@ -71,18 +72,71 @@ afterEach(() => {
71
72
  process.exitCode = 0;
72
73
  });
73
74
 
74
- async function runRequestCommand(args: string[]): Promise<{
75
+ /**
76
+ * Runs the command with both streams captured and `process.exit` recorded.
77
+ * The stream stubs honour a write callback the way the real streams do, so an
78
+ * exit that rides the last write lands in `exitCalls`, and only after every
79
+ * chunk written before it has been captured. `holdStderr` keeps stderr
80
+ * callbacks back and returns them, for the case where stderr is still in
81
+ * flight when stdout has drained.
82
+ */
83
+ async function runRequestCommand(
84
+ args: string[],
85
+ options: { holdStderr?: boolean } = {},
86
+ ): Promise<{
75
87
  stdout: Buffer;
88
+ stderr: string;
76
89
  exitCode: number;
90
+ exitCalls: number[];
91
+ heldStderrCallbacks: Array<() => void>;
77
92
  }> {
78
93
  const chunks: Buffer[] = [];
94
+ const stderrChunks: string[] = [];
95
+ const exitCalls: number[] = [];
96
+ const heldStderrCallbacks: Array<() => void> = [];
79
97
  const originalWrite = process.stdout.write;
80
- process.stdout.write = ((chunk: string | Uint8Array) => {
98
+ const originalStderrWrite = process.stderr.write;
99
+ const originalExit = process.exit;
100
+ const callbackOf = (rest: unknown[]): (() => void) | undefined =>
101
+ rest.find((arg) => typeof arg === "function") as (() => void) | undefined;
102
+ process.stdout.write = ((chunk: string | Uint8Array, ...rest: unknown[]) => {
81
103
  chunks.push(
82
104
  typeof chunk === "string" ? Buffer.from(chunk) : Buffer.from(chunk),
83
105
  );
106
+ callbackOf(rest)?.();
84
107
  return true;
85
108
  }) as typeof process.stdout.write;
109
+ process.stderr.write = ((chunk: string | Uint8Array, ...rest: unknown[]) => {
110
+ stderrChunks.push(String(chunk));
111
+ const callback = callbackOf(rest);
112
+ if (callback) {
113
+ if (options.holdStderr) {
114
+ heldStderrCallbacks.push(holdCallback(callback));
115
+ } else {
116
+ callback();
117
+ }
118
+ }
119
+ return true;
120
+ }) as typeof process.stderr.write;
121
+ const recordExit = ((code?: number) => {
122
+ exitCalls.push(code ?? Number(process.exitCode ?? 0));
123
+ }) as typeof process.exit;
124
+ process.exit = recordExit;
125
+ // A held callback runs after this function has restored the real
126
+ // `process.exit`, so it reinstalls the recorder for the duration of the
127
+ // call; the exit it triggers must land in `exitCalls`, never end the test
128
+ // process.
129
+ const holdCallback = (callback: () => void): (() => void) => {
130
+ return () => {
131
+ const current = process.exit;
132
+ process.exit = recordExit;
133
+ try {
134
+ callback();
135
+ } finally {
136
+ process.exit = current;
137
+ }
138
+ };
139
+ };
86
140
 
87
141
  try {
88
142
  const program = new Command();
@@ -101,11 +155,16 @@ async function runRequestCommand(args: string[]): Promise<{
101
155
  // Commander may throw under exitOverride for parse errors.
102
156
  } finally {
103
157
  process.stdout.write = originalWrite;
158
+ process.stderr.write = originalStderrWrite;
159
+ process.exit = originalExit;
104
160
  }
105
161
 
106
162
  return {
107
163
  stdout: Buffer.concat(chunks),
164
+ stderr: stderrChunks.join(""),
108
165
  exitCode: Number(process.exitCode ?? 0),
166
+ exitCalls,
167
+ heldStderrCallbacks,
109
168
  };
110
169
  }
111
170
 
@@ -308,6 +367,124 @@ describe("oauth request body output", () => {
308
367
  expect(parsed.bodyEncoding).toBe("base64");
309
368
  });
310
369
 
370
+ test("exits non-zero when the route reports failure inside a 2xx", async () => {
371
+ // The exit code follows the route's verdict, so a caller that only checks
372
+ // the exit code sees a refused call as a failure; the body still prints,
373
+ // since it carries the provider's own error code.
374
+ handleRequestResult = {
375
+ ok: false,
376
+ status: 200,
377
+ headers: { "content-type": "application/json" },
378
+ body: { ok: false, error: "not_in_channel" },
379
+ account: "user@example.com",
380
+ };
381
+ const { stdout, exitCode } = await runRequestCommand([
382
+ "--provider",
383
+ "slack_channel",
384
+ "-s",
385
+ "/chat.postMessage",
386
+ ]);
387
+
388
+ expect(exitCode).toBe(1);
389
+ expect(stdout.toString("utf8")).toContain("not_in_channel");
390
+ });
391
+
392
+ test("exits itself once the whole body has drained", async () => {
393
+ // The in-process route leaves handles open, so the command has to exit;
394
+ // and it must do so on the write callback, because a bare exit after a
395
+ // large piped write drops everything past the first 64 KB.
396
+ const body = "x".repeat(200_000);
397
+ handleRequestResult = {
398
+ ok: true,
399
+ status: 200,
400
+ headers: { "content-type": "text/plain" },
401
+ body,
402
+ account: "user@example.com",
403
+ };
404
+ const { stdout, exitCode, exitCalls } = await runRequestCommand([
405
+ "--provider",
406
+ "google",
407
+ "-s",
408
+ "https://api.google.com/v1/big",
409
+ ]);
410
+
411
+ expect(stdout.toString("utf8")).toBe(body + "\n");
412
+ expect(exitCode).toBe(0);
413
+ expect(exitCalls).toEqual([0]);
414
+ });
415
+
416
+ test("exits after writing an empty body to a file", async () => {
417
+ const target = join(tempDir, "empty.bin");
418
+ handleRequestResult = {
419
+ ok: true,
420
+ status: 204,
421
+ headers: {},
422
+ body: null,
423
+ account: "user@example.com",
424
+ };
425
+ const { exitCalls } = await runRequestCommand([
426
+ "--provider",
427
+ "google",
428
+ "-s",
429
+ "-o",
430
+ target,
431
+ "https://api.google.com/v1/none",
432
+ ]);
433
+
434
+ expect(readFileSync(target)).toHaveLength(0);
435
+ expect(exitCalls).toEqual([0]);
436
+ });
437
+
438
+ test("waits for stderr to drain before exiting when stdout carried nothing", async () => {
439
+ // With `-o`, stdout carries nothing, so the exit cannot ride a stdout
440
+ // write, and the diagnostics on stderr (the account line, a hint) may
441
+ // still be in flight. The exit waits for the last of them.
442
+ const target = join(tempDir, "body.json");
443
+ handleRequestResult = {
444
+ ok: false,
445
+ status: 200,
446
+ headers: { "content-type": "application/json" },
447
+ body: { ok: false, error: "not_in_channel" },
448
+ account: "user@example.com",
449
+ hint: "slack_channel answered HTTP 200 but reported ok: false",
450
+ };
451
+ const { stderr, exitCalls, heldStderrCallbacks } = await runRequestCommand(
452
+ ["--provider", "slack_channel", "-o", target, "/chat.postMessage"],
453
+ { holdStderr: true },
454
+ );
455
+
456
+ expect(stderr).toContain("Account: user@example.com");
457
+ expect(stderr).toContain("ok: false");
458
+ expect(heldStderrCallbacks).toHaveLength(2);
459
+ expect(exitCalls).toEqual([]);
460
+
461
+ heldStderrCallbacks[0]();
462
+ expect(exitCalls).toEqual([]);
463
+ heldStderrCallbacks[1]();
464
+ expect(exitCalls).toEqual([1]);
465
+ });
466
+
467
+ test("a stdout body waits for stderr diagnostics written before it", async () => {
468
+ handleRequestResult = {
469
+ ok: true,
470
+ status: 200,
471
+ headers: { "content-type": "application/json" },
472
+ body: { hello: "world" },
473
+ account: "user@example.com",
474
+ };
475
+ const { stdout, exitCalls, heldStderrCallbacks } = await runRequestCommand(
476
+ ["--provider", "google", "https://api.google.com/v1/me"],
477
+ { holdStderr: true },
478
+ );
479
+
480
+ expect(stdout.toString("utf8")).toContain("hello");
481
+ expect(heldStderrCallbacks).toHaveLength(1);
482
+ expect(exitCalls).toEqual([]);
483
+
484
+ heldStderrCallbacks[0]();
485
+ expect(exitCalls).toEqual([0]);
486
+ });
487
+
311
488
  test("writes text bodies as UTF-8 and appends a newline on stdout", async () => {
312
489
  handleRequestResult = {
313
490
  ok: true,
@@ -142,11 +142,38 @@ export async function runAuthenticatedRequest(params: {
142
142
  const { providerKey, url, opts, cmd } = params;
143
143
  const jsonMode = shouldOutputJson(cmd);
144
144
 
145
+ // The command exits itself, once its last write on either stream has
146
+ // drained. Running the route in-process leaves handles open that the event
147
+ // loop waits on (the lazy CES connection the credential resolves through is
148
+ // never closed by the CLI), so returning from the action would leave the
149
+ // process alive after a complete response. A bare `process.exit()` is not
150
+ // the answer either: with a pipe on the other end, Bun flushes what the
151
+ // pipe accepts and drops the rest, so the exit rides write callbacks, which
152
+ // fire when the bytes are out. Stdout's last write carries `exit` itself;
153
+ // stderr's writes are counted, so an exit requested while one is still in
154
+ // flight waits for it. The pipe's capacity is not a bound to lean on: a
155
+ // busy host can shrink an unprivileged pipe to a single page.
156
+ let stderrInFlight = 0;
157
+ let exitRequested = false;
158
+ const exit = (): void => {
159
+ exitRequested = true;
160
+ if (stderrInFlight === 0) {
161
+ process.exit(Number(process.exitCode ?? 0));
162
+ }
163
+ };
164
+
145
165
  // Helper: write info to stderr (respects -s)
146
166
  const writeInfo = (msg: string): void => {
147
- if (!opts.silent) {
148
- process.stderr.write(msg + "\n");
167
+ if (opts.silent) {
168
+ return;
149
169
  }
170
+ stderrInFlight += 1;
171
+ process.stderr.write(msg + "\n", () => {
172
+ stderrInFlight -= 1;
173
+ if (exitRequested) {
174
+ exit();
175
+ }
176
+ });
150
177
  };
151
178
 
152
179
  try {
@@ -232,17 +259,18 @@ export async function runAuthenticatedRequest(params: {
232
259
  // reported the way every other failure here is, so `--json` gets its
233
260
  // envelope and the caller's diagnostics hint is not lost; only the
234
261
  // exit code comes from the route's status.
235
- writeError(cmd, `${err.message}\n\n${params.diagnosticsHint}`);
236
262
  process.exitCode = exitCodeFromIpcResult({
237
263
  statusCode: err.statusCode,
238
264
  });
265
+ writeError(cmd, `${err.message}\n\n${params.diagnosticsHint}`, exit);
239
266
  return;
240
267
  }
241
268
  throw err;
242
269
  }
243
270
 
244
- // Non-2xx exit code
245
- if (result.status < 200 || result.status >= 300) {
271
+ // The route's verdict, not the status code: a provider that reports
272
+ // failure inside a 2xx (Slack's `ok: false`) is a failed request.
273
+ if (!result.ok) {
246
274
  process.exitCode = 1;
247
275
  }
248
276
 
@@ -261,7 +289,7 @@ export async function runAuthenticatedRequest(params: {
261
289
 
262
290
  // JSON output mode
263
291
  if (jsonMode) {
264
- writeOutput(cmd, result);
292
+ writeOutput(cmd, result, exit);
265
293
  return;
266
294
  }
267
295
 
@@ -282,20 +310,23 @@ export async function runAuthenticatedRequest(params: {
282
310
  if (output) {
283
311
  if (opts.output) {
284
312
  writeFileSync(opts.output, output.bytes);
313
+ } else if (output.isBinary) {
314
+ process.stdout.write(output.bytes, exit);
315
+ return;
285
316
  } else {
286
317
  process.stdout.write(output.bytes);
287
- if (!output.isBinary) {
288
- process.stdout.write("\n");
289
- }
318
+ process.stdout.write("\n", exit);
319
+ return;
290
320
  }
291
321
  }
292
322
  } else if (opts.output) {
293
323
  writeFileSync(opts.output, Buffer.alloc(0));
294
324
  }
325
+ exit();
295
326
  } catch (err) {
296
327
  const message = err instanceof Error ? err.message : String(err);
297
- writeError(cmd, `${message}\n\n${params.diagnosticsHint}`);
298
328
  process.exitCode = 1;
329
+ writeError(cmd, `${message}\n\n${params.diagnosticsHint}`, exit);
299
330
  }
300
331
  }
301
332
 
@@ -238,11 +238,18 @@ export function registerPluginsCommand(program: Command): void {
238
238
  const platformEnabled =
239
239
  libs.catalogLocal.arePlatformFeaturesEnabled();
240
240
  if (platformEnabled) {
241
- const match = (
242
- await libs.catalogCache.getPluginCatalog(DEFAULT_PLUGIN_REF, {
243
- fetch: globalThis.fetch.bind(globalThis),
244
- })
245
- ).matches.find((candidate) => candidate.name === nameOrUrl);
241
+ let match;
242
+ try {
243
+ match = (
244
+ await libs.catalogCache.getPluginCatalog(
245
+ DEFAULT_PLUGIN_REF,
246
+ { fetch: globalThis.fetch.bind(globalThis) },
247
+ )
248
+ ).matches.find((candidate) => candidate.name === nameOrUrl);
249
+ } catch {
250
+ // The install endpoint remains authoritative and can succeed
251
+ // independently when catalog discovery is unavailable.
252
+ }
246
253
  if (match?.source.kind === "local") {
247
254
  result = await libs.installGitHub.installPlugin(
248
255
  {
@@ -25,7 +25,7 @@ no verb to post one.
25
25
  Examples:
26
26
  $ assistant roadmap list --sort upvotes --limit 10
27
27
  $ assistant roadmap get scheduled-messages
28
- $ assistant roadmap create --title "Add dark mode" --tag ui
28
+ $ assistant roadmap create --title "Add dark mode" --tag area-interface
29
29
  $ assistant roadmap upvote scheduled-messages`,
30
30
  subcommands: [
31
31
  {
@@ -79,10 +79,13 @@ Examples:
79
79
  options: [
80
80
  {
81
81
  flags: "--title <title>",
82
- description: "Item title (required)",
82
+ description: "Item title, 1 to 200 characters (required)",
83
83
  required: true,
84
84
  },
85
- { flags: "--description <desc>", description: "Item description" },
85
+ {
86
+ flags: "--description <desc>",
87
+ description: "Item description, up to 5000 characters",
88
+ },
86
89
  {
87
90
  flags: "--tag <slug>",
88
91
  description:
@@ -97,41 +100,35 @@ accepted, since status is assigned by Vellum.
97
100
  Examples:
98
101
  $ assistant roadmap create --title "Add dark mode"
99
102
  $ assistant roadmap create --title "Recurring reminders" \\
100
- --description "Repeat a scheduled message weekly" --tag scheduling`,
103
+ --description "Repeat a scheduled message weekly" --tag area-assistant`,
101
104
  },
102
105
  {
103
106
  name: "update",
104
107
  args: "<slug>",
105
- description: "Update a roadmap item",
108
+ description:
109
+ "Edit the title or description of an item the assistant filed",
106
110
  options: [
107
- { flags: "--title <title>", description: "New title" },
108
- { flags: "--description <desc>", description: "New description" },
109
111
  {
110
- flags: "--status <status>",
111
- description: "New status (e.g. open, planned, in_progress, someday)",
112
- },
113
- {
114
- flags: "--tag <slug>",
115
- description: "Replacement tag slug, repeatable",
112
+ flags: "--title <title>",
113
+ description: "New title, 1 to 200 characters",
116
114
  },
117
115
  {
118
- flags: "--clear-tags",
119
- description: "Remove every tag (cannot be combined with --tag)",
116
+ flags: "--description <desc>",
117
+ description: "New description, up to 5000 characters",
120
118
  },
121
119
  ],
122
120
  helpText: `
123
121
  Arguments:
124
122
  <slug> Item slug, as printed in the URL by 'assistant roadmap list'
125
123
 
126
- At least one field is required. Passing --tag replaces the whole tag set
127
- rather than adding to it, so list every tag the item should end up with.
128
- Vellum decides which items an assistant may edit, so this fails for items the
129
- assistant does not own.
124
+ At least one of --title or --description is required. Only items this
125
+ assistant filed can be edited, and only while their status is still open.
126
+ Status and tags are set by Vellum staff, so an item's tags are chosen once,
127
+ on 'roadmap create'.
130
128
 
131
129
  Examples:
132
130
  $ assistant roadmap update dark-mode --description "Follow the OS setting"
133
- $ assistant roadmap update dark-mode --tag ui --tag theming
134
- $ assistant roadmap update dark-mode --clear-tags`,
131
+ $ assistant roadmap update dark-mode --title "Dark mode that follows the OS"`,
135
132
  },
136
133
  {
137
134
  name: "delete",
@@ -14,7 +14,7 @@ import { stripAnsiAndControlChars as sanitize } from "../../util/ansi.js";
14
14
  import { applyCommandHelp, subcommand } from "../lib/cli-command-help.js";
15
15
  import { registerCommand } from "../lib/register-command.js";
16
16
  import { log } from "../logger.js";
17
- import { shouldOutputJson, writeError, writeOutput } from "../output.js";
17
+ import { shouldOutputJson, writeOutput } from "../output.js";
18
18
  import { roadmapHelp } from "./roadmap.help.js";
19
19
 
20
20
  // ---------------------------------------------------------------------------
@@ -227,9 +227,6 @@ async function runCreate(cmd: Command, opts: CreateOpts): Promise<void> {
227
227
  interface UpdateOpts {
228
228
  title?: string;
229
229
  description?: string;
230
- status?: string;
231
- tag?: string[];
232
- clearTags?: boolean;
233
230
  }
234
231
 
235
232
  async function runUpdate(
@@ -237,24 +234,11 @@ async function runUpdate(
237
234
  slug: string,
238
235
  opts: UpdateOpts,
239
236
  ): Promise<void> {
240
- if (opts.clearTags && opts.tag) {
241
- writeError(
242
- cmd,
243
- "--clear-tags and --tag conflict. Drop --clear-tags to set tags, or drop --tag to remove them all.",
244
- );
245
- process.exitCode = 1;
246
- return;
247
- }
248
-
249
237
  const item = await call<MutatedRoadmapItem>("roadmap_update", {
250
238
  pathParams: { slug },
251
239
  body: {
252
240
  title: opts.title,
253
241
  description: opts.description,
254
- status: opts.status,
255
- // `--tag` always carries a value, so an empty set is only reachable
256
- // through `--clear-tags`.
257
- tags: opts.clearTags ? [] : opts.tag,
258
242
  },
259
243
  });
260
244
 
@@ -334,10 +318,9 @@ export function registerRoadmapCommand(program: Command): void {
334
318
  makeTagRepeatable(create);
335
319
  create.action((opts: CreateOpts, cmd: Command) => runCreate(cmd, opts));
336
320
 
337
- const update = subcommand(roadmap, "update");
338
- makeTagRepeatable(update);
339
- update.action((slug: string, opts: UpdateOpts, cmd: Command) =>
340
- runUpdate(cmd, slug, opts),
321
+ subcommand(roadmap, "update").action(
322
+ (slug: string, opts: UpdateOpts, cmd: Command) =>
323
+ runUpdate(cmd, slug, opts),
341
324
  );
342
325
 
343
326
  subcommand(roadmap, "delete").action(
@@ -35,6 +35,7 @@ interface ScheduleRecord {
35
35
  mode: string;
36
36
  status: string;
37
37
  routingIntent: string;
38
+ quiet: boolean;
38
39
  reuseConversation: boolean;
39
40
  wakeConversationId: string | null;
40
41
  sourceKey: string | null;
@@ -268,6 +269,7 @@ export function registerSchedulesCommand(program: Command): void {
268
269
  formatScheduleInferenceProfile(schedule.inferenceProfile),
269
270
  ],
270
271
  ["Routing intent", schedule.routingIntent],
272
+ ["Quiet", schedule.quiet ? "yes" : "no"],
271
273
  ["Reuse conversation", schedule.reuseConversation ? "yes" : "no"],
272
274
  ["Wake conversation", schedule.wakeConversationId ?? "—"],
273
275
  ["Retry count", String(schedule.retryCount)],