@vellumai/assistant 0.12.2 → 0.12.3-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) hide show
  1. package/.env.example +2 -0
  2. package/AGENTS.md +1 -1
  3. package/ARCHITECTURE.md +43 -29
  4. package/Dockerfile +63 -0
  5. package/docs/architecture/integrations.md +7 -0
  6. package/docs/architecture/memory.md +17 -2
  7. package/docs/architecture/security.md +10 -5
  8. package/docs/architecture/turn-actor.md +2 -0
  9. package/docs/credential-execution-service.md +1 -1
  10. package/docs/desktop-browser-cli.md +50 -5
  11. package/docs/live-voice-task-outcomes.md +100 -0
  12. package/docs/mode-sessions.md +183 -0
  13. package/docs/voice-input-diagnostics.md +58 -0
  14. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  15. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
  16. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  17. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  18. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
  19. package/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
  20. package/node_modules/@vellumai/environments/src/shell.ts +24 -0
  21. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  22. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
  23. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  24. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  25. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
  26. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
  27. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -2
  28. package/node_modules/@vellumai/gateway-client/src/index.ts +4 -1
  29. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +38 -7
  30. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +5 -6
  31. package/node_modules/@vellumai/service-contracts/package.json +2 -1
  32. package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
  33. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  34. package/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  35. package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
  36. package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
  37. package/openapi.yaml +716 -16
  38. package/package.json +1 -1
  39. package/scripts/smoke-desktop-browser-cli.ts +11 -26
  40. package/scripts/smoke-desktop-window-theme.ts +2 -3
  41. package/scripts/sync-llm-catalog.ts +3 -0
  42. package/scripts/voice-ttft-spike.ts +2 -2
  43. package/src/__tests__/agent-loop-output-hooks.test.ts +150 -1
  44. package/src/__tests__/agent-loop-provider-error-recording.test.ts +87 -19
  45. package/src/__tests__/agent-loop.test.ts +259 -0
  46. package/src/__tests__/agent-wake-delegation-prompt.test.ts +64 -2
  47. package/src/__tests__/annotate-activity-metadata.test.ts +3 -1
  48. package/src/__tests__/annotate-risk-options.test.ts +2 -0
  49. package/src/__tests__/answered-question-persistence.test.ts +2 -0
  50. package/src/__tests__/anthropic-gateway-shared.test.ts +22 -0
  51. package/src/__tests__/anthropic-provider.test.ts +55 -0
  52. package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
  53. package/src/__tests__/approval-message-composer.test.ts +1 -118
  54. package/src/__tests__/approval-routes-http.test.ts +3 -0
  55. package/src/__tests__/assistant-event-hub-connection-history.test.ts +111 -0
  56. package/src/__tests__/assistant-event-hub-targeted.test.ts +50 -0
  57. package/src/__tests__/assistant-event-targeting.test.ts +186 -0
  58. package/src/__tests__/assistant-stream-state.test.ts +29 -9
  59. package/src/__tests__/attachments-store.test.ts +22 -3
  60. package/src/__tests__/browser-fill-credential.test.ts +11 -22
  61. package/src/__tests__/btw-routes.test.ts +4 -1
  62. package/src/__tests__/build-persisted-content.test.ts +1 -1
  63. package/src/__tests__/call-conversation-messages.test.ts +5 -0
  64. package/src/__tests__/call-recovery.test.ts +7 -2
  65. package/src/__tests__/call-routes-http.test.ts +12 -0
  66. package/src/__tests__/call-store.test.ts +7 -2
  67. package/src/__tests__/channel-approval.test.ts +9 -14
  68. package/src/__tests__/channel-reply-delivery.test.ts +56 -0
  69. package/src/__tests__/channel-retry-sweep.test.ts +9 -0
  70. package/src/__tests__/chat-credential-redaction.test.ts +23 -0
  71. package/src/__tests__/chat-reveal-guard-priming.test.ts +2 -0
  72. package/src/__tests__/checker.test.ts +11 -3
  73. package/src/__tests__/client-os-metadata-persistence.test.ts +35 -1
  74. package/src/__tests__/computer-use-screenshot-attachments.test.ts +411 -0
  75. package/src/__tests__/computer-use-screenshot-selection.test.ts +50 -0
  76. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -25
  77. package/src/__tests__/computer-use-tools.test.ts +1 -233
  78. package/src/__tests__/config-model-image-provider.test.ts +39 -0
  79. package/src/__tests__/config-schema.test.ts +16 -0
  80. package/src/__tests__/config-watcher.test.ts +24 -0
  81. package/src/__tests__/context-search-agent-runner.test.ts +260 -1
  82. package/src/__tests__/context-search-fanout.test.ts +1 -1
  83. package/src/__tests__/context-search-types.test.ts +7 -7
  84. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +8 -2
  85. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +2 -0
  86. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  87. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
  88. package/src/__tests__/conversation-agent-loop.test.ts +797 -16
  89. package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
  90. package/src/__tests__/conversation-attachments.test.ts +106 -0
  91. package/src/__tests__/conversation-evictor.test.ts +62 -37
  92. package/src/__tests__/conversation-fork-crud.test.ts +191 -0
  93. package/src/__tests__/conversation-history-boundary-repair-failure.test.ts +174 -0
  94. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +2 -0
  95. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
  96. package/src/__tests__/conversation-rendered-delegation-state.test.ts +276 -0
  97. package/src/__tests__/conversation-retry-route.test.ts +22 -0
  98. package/src/__tests__/conversation-routes-disk-view.test.ts +2 -0
  99. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +2 -0
  100. package/src/__tests__/conversation-routes-guardian-reply.test.ts +10 -0
  101. package/src/__tests__/conversation-routes-hidden-queue.test.ts +2 -0
  102. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
  103. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -0
  104. package/src/__tests__/conversation-surface-snapshots.test.ts +543 -0
  105. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +151 -0
  106. package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +63 -1
  107. package/src/__tests__/conversation-tool-setup-attribution.test.ts +23 -0
  108. package/src/__tests__/conversation-undo.test.ts +61 -0
  109. package/src/__tests__/credential-execution-client.test.ts +72 -55
  110. package/src/__tests__/credential-prompt-route.test.ts +35 -3
  111. package/src/__tests__/cu-unified-flow.test.ts +82 -1
  112. package/src/__tests__/db-conversation-tool-surface.test.ts +221 -0
  113. package/src/__tests__/db-mode-sessions-migration.test.ts +175 -0
  114. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -0
  115. package/src/__tests__/dm-backfill.test.ts +91 -1
  116. package/src/__tests__/document-create-route.test.ts +88 -0
  117. package/src/__tests__/document-sync-tags.test.ts +27 -0
  118. package/src/__tests__/emit-signal-routing-intent.test.ts +142 -2
  119. package/src/__tests__/events-tail-route.test.ts +58 -0
  120. package/src/__tests__/evict-conversations-for-reload.test.ts +57 -8
  121. package/src/__tests__/guardian-action-sweep.test.ts +16 -0
  122. package/src/__tests__/guardian-dispatch.test.ts +13 -0
  123. package/src/__tests__/headless-browser-interactions.test.ts +64 -20
  124. package/src/__tests__/heartbeat-service.test.ts +2 -59
  125. package/src/__tests__/helpers/mock-conversation.ts +21 -0
  126. package/src/__tests__/helpers/native-web-search-harness.ts +2 -0
  127. package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +5 -0
  128. package/src/__tests__/history-repair.test.ts +53 -0
  129. package/src/__tests__/host-cu-proxy.test.ts +46 -2
  130. package/src/__tests__/http-user-message-parity.test.ts +2 -0
  131. package/src/__tests__/image-credentials.test.ts +49 -0
  132. package/src/__tests__/image-service-dispatcher.test.ts +45 -0
  133. package/src/__tests__/inference-profile-session-handler.test.ts +26 -0
  134. package/src/__tests__/interrupt-on-send.test.ts +57 -43
  135. package/src/__tests__/interrupt-turn-note.test.ts +5 -6
  136. package/src/__tests__/list-messages-tool-merge.test.ts +85 -1
  137. package/src/__tests__/llm-catalog-parity.test.ts +27 -4
  138. package/src/__tests__/media-generate-image.test.ts +49 -1
  139. package/src/__tests__/message-provenance-contact-id.test.ts +69 -0
  140. package/src/__tests__/migration-export-to-gcs.test.ts +142 -0
  141. package/src/__tests__/mode-session-history.test.ts +245 -0
  142. package/src/__tests__/mode-session-recovery.test.ts +222 -0
  143. package/src/__tests__/mode-session-wire.test.ts +141 -0
  144. package/src/__tests__/notification-guardian-path.test.ts +7 -0
  145. package/src/__tests__/notification-telegram-adapter.test.ts +2 -2
  146. package/src/__tests__/notification-vellum-adapter.test.ts +34 -0
  147. package/src/__tests__/oauth-apps-routes.test.ts +1 -0
  148. package/src/__tests__/oauth-commands-routes.test.ts +114 -101
  149. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
  150. package/src/__tests__/oauth-provider-serializer.test.ts +13 -0
  151. package/src/__tests__/oauth-providers-routes.test.ts +3 -0
  152. package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
  153. package/src/__tests__/persist-media-references.test.ts +50 -0
  154. package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
  155. package/src/__tests__/plugin-api-provider.test.ts +5 -0
  156. package/src/__tests__/plugin-api-resolve-credential.test.ts +97 -0
  157. package/src/__tests__/plugin-import-boundary-guard.test.ts +9 -1
  158. package/src/__tests__/process-message-display-content.test.ts +56 -0
  159. package/src/__tests__/reaction-persistence.test.ts +5 -0
  160. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +25 -9
  161. package/src/__tests__/run-conversation-turn-persistence.test.ts +138 -1
  162. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
  163. package/src/__tests__/schedule-routes.test.ts +20 -0
  164. package/src/__tests__/scheduler-result-notification.test.ts +23 -4
  165. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  166. package/src/__tests__/scripted-turn-metadata-persistence.test.ts +73 -0
  167. package/src/__tests__/secret-ingress-http.test.ts +2 -0
  168. package/src/__tests__/secret-routes-platform-proxy.test.ts +86 -31
  169. package/src/__tests__/secret-routes-scrub.test.ts +22 -27
  170. package/src/__tests__/secret-scanner.test.ts +20 -0
  171. package/src/__tests__/secure-keys-managed-failover.test.ts +8 -0
  172. package/src/__tests__/secure-keys.test.ts +50 -4
  173. package/src/__tests__/send-endpoint-busy.test.ts +163 -1
  174. package/src/__tests__/server-history-render.test.ts +91 -1
  175. package/src/__tests__/server-tool-pairing.test.ts +107 -0
  176. package/src/__tests__/settings-routes.test.ts +50 -1
  177. package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
  178. package/src/__tests__/skills.test.ts +5 -4
  179. package/src/__tests__/subagent-fork-notifications.test.ts +1 -2
  180. package/src/__tests__/subagent-manager-notify.test.ts +1 -2
  181. package/src/__tests__/subagent-notify-parent.test.ts +146 -39
  182. package/src/__tests__/subagent-notify-stale-rebuild.test.ts +2 -4
  183. package/src/__tests__/subagent-tool-gate-mode.test.ts +226 -0
  184. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +2 -0
  185. package/src/__tests__/terminal-tools.test.ts +8 -0
  186. package/src/__tests__/thread-backfill.test.ts +53 -0
  187. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
  188. package/src/__tests__/tool-result-follow-up.test.ts +99 -0
  189. package/src/__tests__/tool-result-metadata-plumbing.test.ts +66 -1
  190. package/src/__tests__/tool-start-timestamp.test.ts +2 -0
  191. package/src/__tests__/twilio-routes.test.ts +1 -0
  192. package/src/__tests__/unicode.test.ts +36 -0
  193. package/src/__tests__/web-search-backend-failure.test.ts +1 -1
  194. package/src/activation/progress-store.test.ts +12 -7
  195. package/src/agent/loop.ts +136 -53
  196. package/src/agent/tool-result-follow-up.ts +70 -0
  197. package/src/api/attachment-provenance.test.ts +68 -0
  198. package/src/api/computer-use-tool.test.ts +55 -0
  199. package/src/api/computer-use-tool.ts +27 -0
  200. package/src/api/events/assistant-outbound-attachment.ts +3 -0
  201. package/src/api/events/assistant-turn-start.ts +3 -0
  202. package/src/api/events/desktop-activity-changed.ts +10 -0
  203. package/src/api/events/generation-handoff.ts +2 -0
  204. package/src/api/events/message-complete.ts +2 -0
  205. package/src/api/events/notification-conversation-created.ts +14 -16
  206. package/src/api/events/notification-intent.ts +4 -2
  207. package/src/api/events/question-request.ts +1 -0
  208. package/src/api/events/tool-result.ts +85 -0
  209. package/src/api/events/tool-use-start.ts +3 -0
  210. package/src/api/events/user-message-echo.ts +3 -0
  211. package/src/api/index.ts +42 -6
  212. package/src/api/mode-session.test.ts +131 -0
  213. package/src/api/mode-session.ts +148 -0
  214. package/src/api/remember-tool.ts +15 -0
  215. package/src/api/responses/conversation-message.ts +9 -0
  216. package/src/approvals/AGENTS.md +4 -2
  217. package/src/approvals/approval-primitive.ts +5 -2
  218. package/src/approvals/scoped-approval-grants.ts +6 -2
  219. package/src/browser/__tests__/operations.test.ts +29 -0
  220. package/src/browser/operation-meta.ts +2 -1
  221. package/src/browser/operations.ts +29 -0
  222. package/src/browser/virtual-desktop-target.ts +2 -9
  223. package/src/bundler/bundle-signer.ts +1 -3
  224. package/src/calls/__tests__/barge-in-guard.test.ts +3 -0
  225. package/src/calls/__tests__/call-controller.test.ts +94 -0
  226. package/src/calls/__tests__/call-funnel-telemetry.test.ts +204 -0
  227. package/src/calls/__tests__/voice-control-protocol.test.ts +15 -0
  228. package/src/calls/__tests__/voice-escalation-judge.test.ts +209 -0
  229. package/src/calls/__tests__/voice-leg-coordinator.test.ts +168 -0
  230. package/src/{live-voice/__tests__/live-voice-metrics.test.ts → calls/__tests__/voice-metrics.test.ts} +32 -38
  231. package/src/calls/__tests__/voice-session-bridge.test.ts +576 -122
  232. package/src/calls/barge-in-guard.ts +5 -0
  233. package/src/calls/call-controller.ts +196 -1
  234. package/src/calls/call-domain.ts +4 -0
  235. package/src/calls/call-store.ts +87 -2
  236. package/src/calls/guardian-action-sweep.ts +22 -8
  237. package/src/calls/media-stream-audio-transcode.ts +1 -3
  238. package/src/calls/typesafe-noul.ts +156 -0
  239. package/src/calls/voice-control-protocol.ts +6 -0
  240. package/src/calls/voice-escalation-judge.ts +145 -0
  241. package/src/calls/voice-escalation-target.ts +10 -0
  242. package/src/calls/voice-leg-coordinator.ts +121 -3
  243. package/src/{live-voice/live-voice-metrics.ts → calls/voice-metrics.ts} +94 -87
  244. package/src/calls/voice-session-bridge.ts +256 -112
  245. package/src/calls/voice-triage-escalate.ts +7 -0
  246. package/src/cli/__tests__/roadmap-cli.test.ts +4 -41
  247. package/src/cli/commands/__tests__/cli-test-harness.ts +21 -3
  248. package/src/cli/commands/__tests__/notifications.test.ts +35 -10
  249. package/src/cli/commands/__tests__/plugins.test.ts +20 -1
  250. package/src/cli/commands/__tests__/schedules.test.ts +14 -0
  251. package/src/cli/commands/bash.help.ts +4 -3
  252. package/src/cli/commands/browser.help.ts +9 -6
  253. package/src/cli/commands/browser.ts +0 -1
  254. package/src/cli/commands/clients.help.ts +46 -0
  255. package/src/cli/commands/clients.ts +116 -0
  256. package/src/cli/commands/credentials.help.ts +9 -4
  257. package/src/cli/commands/notifications.help.ts +16 -2
  258. package/src/cli/commands/notifications.ts +30 -8
  259. package/src/cli/commands/oauth/index.help.ts +10 -0
  260. package/src/cli/commands/oauth/providers.ts +12 -0
  261. package/src/cli/commands/oauth/request.test.ts +179 -2
  262. package/src/cli/commands/oauth/request.ts +41 -10
  263. package/src/cli/commands/plugins.ts +12 -5
  264. package/src/cli/commands/roadmap.help.ts +18 -21
  265. package/src/cli/commands/roadmap.ts +4 -21
  266. package/src/cli/commands/schedules.ts +2 -0
  267. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  268. package/src/cli/lib/__tests__/install-from-github.test.ts +41 -0
  269. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
  270. package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +133 -51
  271. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +8 -2
  272. package/src/cli/lib/bundled-marketplace.json +906 -1
  273. package/src/cli/lib/bundled-plugin-packages.json +783 -1
  274. package/src/cli/lib/inspect-plugin.ts +11 -4
  275. package/src/cli/lib/plugin-marketplace.ts +8 -0
  276. package/src/cli/lib/publish-plugin.ts +1 -2
  277. package/src/cli/lib/upgrade-plugin.ts +19 -11
  278. package/src/cli/output.ts +18 -4
  279. package/src/config/__tests__/default-provider.test.ts +6 -0
  280. package/src/config/__tests__/memory-retrospective-schema.test.ts +14 -1
  281. package/src/config/bundled-skills/computer-use/SKILL.md +1 -1
  282. package/src/config/bundled-skills/computer-use/TOOLS.json +89 -1
  283. package/src/config/bundled-skills/image-studio/SKILL.md +17 -2
  284. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -11
  285. package/src/config/bundled-skills/schedule/SKILL.md +6 -6
  286. package/src/config/bundled-skills/sequences/TOOLS.json +1 -5
  287. package/src/config/call-site-defaults.ts +9 -0
  288. package/src/config/feature-flag-registry.json +16 -0
  289. package/src/config/loader.ts +9 -17
  290. package/src/config/platform-identity.ts +8 -8
  291. package/src/config/profile-text-generation.test.ts +51 -0
  292. package/src/config/profile-text-generation.ts +51 -0
  293. package/src/config/schemas/__tests__/memory-v3.test.ts +12 -0
  294. package/src/config/schemas/__tests__/tools.test.ts +31 -0
  295. package/src/config/schemas/call-site-catalog.ts +14 -0
  296. package/src/config/schemas/channels.ts +0 -18
  297. package/src/config/schemas/llm.ts +9 -2
  298. package/src/config/schemas/mcp.ts +6 -1
  299. package/src/config/schemas/memory-retrospective.ts +11 -2
  300. package/src/config/schemas/memory-v3.ts +12 -0
  301. package/src/config/schemas/services.ts +15 -6
  302. package/src/config/schemas/tools.ts +10 -0
  303. package/src/config/session-groups-gate.ts +21 -0
  304. package/src/config/skills.ts +2 -6
  305. package/src/conversations/__tests__/message-consolidation.test.ts +149 -0
  306. package/src/conversations/message-consolidation.ts +102 -5
  307. package/src/credential-execution/ces-connect.test.ts +69 -0
  308. package/src/credential-execution/ces-connect.ts +115 -0
  309. package/src/credential-execution/ces-runtime.ts +55 -93
  310. package/src/credential-execution/executable-discovery.ts +34 -142
  311. package/src/credential-execution/process-manager.test.ts +20 -24
  312. package/src/credential-execution/process-manager.ts +24 -19
  313. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
  314. package/src/daemon/__tests__/conversation-tool-setup.test.ts +43 -0
  315. package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
  316. package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +36 -0
  317. package/src/daemon/assistant-attachments.ts +20 -12
  318. package/src/daemon/browser-mode-session.test.ts +402 -0
  319. package/src/daemon/browser-mode-session.ts +186 -0
  320. package/src/daemon/chat-credential-redaction.ts +16 -1
  321. package/src/daemon/computer-use-mode-session.test.ts +210 -0
  322. package/src/daemon/computer-use-mode-session.ts +105 -0
  323. package/src/daemon/config-watcher.ts +10 -0
  324. package/src/daemon/conversation-agent-loop-handlers.ts +132 -13
  325. package/src/daemon/conversation-agent-loop.ts +231 -25
  326. package/src/daemon/conversation-attachments.ts +93 -12
  327. package/src/daemon/conversation-evictor.ts +5 -24
  328. package/src/daemon/conversation-history.ts +10 -0
  329. package/src/daemon/conversation-interrupt-repair.ts +4 -43
  330. package/src/daemon/conversation-interrupt.ts +7 -11
  331. package/src/daemon/conversation-messaging.ts +58 -5
  332. package/src/daemon/conversation-mode-session.test.ts +1667 -0
  333. package/src/daemon/conversation-mode-session.ts +1008 -0
  334. package/src/daemon/conversation-process.ts +5 -0
  335. package/src/daemon/conversation-runtime-assembly.ts +10 -20
  336. package/src/daemon/conversation-skill-tools.ts +1 -0
  337. package/src/daemon/conversation-store.ts +4 -4
  338. package/src/daemon/conversation-surface-snapshots.ts +135 -0
  339. package/src/daemon/conversation-surfaces.ts +113 -5
  340. package/src/daemon/conversation-tool-setup.ts +79 -6
  341. package/src/daemon/conversation-turn-finalize.ts +26 -13
  342. package/src/daemon/conversation.ts +215 -58
  343. package/src/daemon/daemon-control.ts +3 -7
  344. package/src/daemon/handlers/config-model.ts +7 -5
  345. package/src/daemon/handlers/shared.ts +55 -16
  346. package/src/daemon/host-cu-proxy.ts +51 -22
  347. package/src/daemon/lifecycle.ts +30 -13
  348. package/src/daemon/mcp-reload-service.ts +1 -1
  349. package/src/daemon/message-protocol.ts +0 -1
  350. package/src/daemon/message-provenance.ts +28 -4
  351. package/src/daemon/message-types/shared.ts +1 -0
  352. package/src/daemon/mode-session-startup-recovery.ts +23 -0
  353. package/src/daemon/mode-session-tracking.ts +54 -0
  354. package/src/daemon/orphan-reaper.ts +4 -3
  355. package/src/daemon/persist-media-references.ts +20 -3
  356. package/src/daemon/process-message.ts +13 -4
  357. package/src/daemon/tool-setup-types.ts +6 -0
  358. package/src/daemon/virtual-desktop-context.ts +21 -0
  359. package/src/daemon/wake-conversation-ops.ts +50 -15
  360. package/src/desktop/__tests__/fake-desktop.ts +1 -0
  361. package/src/desktop/desktop-accessibility-script.ts +88 -0
  362. package/src/desktop/desktop-accessibility.test.ts +160 -0
  363. package/src/desktop/desktop-accessibility.ts +169 -0
  364. package/src/desktop/desktop-automation-lease.test.ts +302 -64
  365. package/src/desktop/desktop-automation-lease.ts +129 -54
  366. package/src/desktop/desktop-browser-endpoint.ts +4 -0
  367. package/src/desktop/desktop-computer-use-routing.test.ts +330 -0
  368. package/src/desktop/desktop-computer-use.test.ts +449 -0
  369. package/src/desktop/desktop-computer-use.ts +502 -0
  370. package/src/desktop/desktop-dependencies.ts +47 -293
  371. package/src/desktop/desktop-display.ts +2 -2
  372. package/src/desktop/desktop-help.ts +15 -0
  373. package/src/desktop/desktop-panel-config.test.ts +13 -3
  374. package/src/desktop/desktop-panel-config.ts +109 -15
  375. package/src/desktop/desktop-session-manager.test.ts +69 -21
  376. package/src/desktop/desktop-session-manager.ts +76 -22
  377. package/src/desktop/desktop-stream-bridge.test.ts +76 -132
  378. package/src/desktop/desktop-stream-bridge.ts +9 -11
  379. package/src/desktop/desktop-wallpaper-renderer.ts +132 -0
  380. package/src/desktop/desktop-wallpaper-worker.ts +17 -0
  381. package/src/desktop/desktop-wallpaper.test.ts +48 -7
  382. package/src/desktop/desktop-wallpaper.ts +34 -102
  383. package/src/desktop/desktop-window-theme.ts +5 -25
  384. package/src/desktop/virtual-desktop-feature.ts +53 -3
  385. package/src/desktop/virtual-desktop-platform.test.ts +5 -9
  386. package/src/documents/document-store.ts +23 -0
  387. package/src/heartbeat/__tests__/heartbeat-service.test.ts +22 -26
  388. package/src/heartbeat/heartbeat-service.ts +5 -33
  389. package/src/ipc/__tests__/browser-ipc.test.ts +215 -6
  390. package/src/ipc/assistant-server.ts +2 -0
  391. package/src/ipc/routes/__tests__/channel-reply-ipc-routes.test.ts +111 -0
  392. package/src/ipc/routes/channel-reply-ipc-routes.ts +73 -0
  393. package/src/live-voice/__tests__/continuation-judge.test.ts +151 -0
  394. package/src/live-voice/__tests__/live-activity-reporter.test.ts +154 -15
  395. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +743 -31
  396. package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +191 -10
  397. package/src/live-voice/__tests__/live-voice-session-groups-gate.test.ts +87 -0
  398. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +5 -1
  399. package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +41 -0
  400. package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +1017 -9
  401. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +224 -1
  402. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +101 -0
  403. package/src/live-voice/__tests__/live-voice-tts.test.ts +44 -0
  404. package/src/live-voice/__tests__/live-voice-vad.test.ts +939 -75
  405. package/src/live-voice/__tests__/microphone-idle-gate.test.ts +87 -0
  406. package/src/live-voice/__tests__/session-controls.test.ts +23 -0
  407. package/src/live-voice/__tests__/task-outcomes.test.ts +117 -0
  408. package/src/live-voice/__tests__/voice-input-diagnostics.test.ts +117 -0
  409. package/src/live-voice/camera-mode-session.test.ts +265 -0
  410. package/src/live-voice/camera-mode-session.ts +277 -0
  411. package/src/live-voice/continuation-judge.ts +123 -0
  412. package/src/live-voice/live-activity-reporter.ts +115 -6
  413. package/src/live-voice/live-voice-manager.ts +36 -1
  414. package/src/live-voice/live-voice-photo.ts +88 -7
  415. package/src/live-voice/live-voice-session-manager.ts +15 -0
  416. package/src/live-voice/live-voice-session.ts +1443 -747
  417. package/src/live-voice/live-voice-tts.ts +22 -4
  418. package/src/live-voice/microphone-idle-gate.ts +56 -0
  419. package/src/live-voice/protocol.ts +171 -4
  420. package/src/live-voice/session-controls.ts +11 -3
  421. package/src/live-voice/task-outcomes.ts +131 -0
  422. package/src/live-voice/voice-input-diagnostics.ts +117 -0
  423. package/src/mcp/__tests__/manager-tool-caps.test.ts +156 -0
  424. package/src/mcp/__tests__/startup.test.ts +30 -7
  425. package/src/mcp/__tests__/tool-caps.test.ts +134 -0
  426. package/src/mcp/manager.ts +171 -101
  427. package/src/mcp/startup.ts +33 -13
  428. package/src/mcp/tool-caps.ts +184 -0
  429. package/src/media/__tests__/image-models.test.ts +58 -0
  430. package/src/media/image-credentials.ts +5 -0
  431. package/src/media/image-models.ts +52 -0
  432. package/src/media/image-service.ts +8 -0
  433. package/src/media/openrouter-image-service.test.ts +133 -0
  434. package/src/media/openrouter-image-service.ts +153 -0
  435. package/src/media/types.ts +1 -1
  436. package/src/messaging/provider-message-metadata.ts +3 -3
  437. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +65 -11
  438. package/src/messaging/providers/discord/send.ts +4 -17
  439. package/src/messaging/providers/discord/transport.ts +2 -2
  440. package/src/messaging/providers/outlook/client.ts +16 -22
  441. package/src/messaging/providers/telegram-bot/send.test.ts +236 -1
  442. package/src/messaging/providers/telegram-bot/send.ts +10 -7
  443. package/src/messaging/providers/telegram-bot/transport.ts +3 -10
  444. package/src/messaging/providers/whatsapp/send.test.ts +169 -4
  445. package/src/monitoring/__tests__/control.test.ts +17 -5
  446. package/src/monitoring/control.ts +15 -5
  447. package/src/notifications/AGENTS.md +1 -1
  448. package/src/notifications/README.md +83 -99
  449. package/src/notifications/__tests__/broadcaster.test.ts +1 -1
  450. package/src/notifications/__tests__/channel-allowlist.test.ts +39 -0
  451. package/src/notifications/__tests__/copy-composer.test.ts +71 -1
  452. package/src/notifications/__tests__/decision-engine.test.ts +79 -2
  453. package/src/notifications/__tests__/deterministic-checks.test.ts +10 -10
  454. package/src/notifications/__tests__/home-feed-side-effect.test.ts +93 -4
  455. package/src/notifications/__tests__/notification-utils.test.ts +18 -0
  456. package/src/notifications/adapters/macos.ts +37 -46
  457. package/src/notifications/broadcaster.ts +5 -6
  458. package/src/notifications/channel-allowlist.ts +44 -0
  459. package/src/notifications/copy-composer.ts +11 -26
  460. package/src/notifications/decision-engine.ts +24 -14
  461. package/src/notifications/deterministic-checks.ts +1 -1
  462. package/src/notifications/emit-signal.ts +123 -37
  463. package/src/notifications/home-feed-side-effect.ts +9 -7
  464. package/src/notifications/notification-utils.ts +19 -0
  465. package/src/notifications/schedule-result-producer.ts +4 -6
  466. package/src/notifications/signal.ts +4 -19
  467. package/src/notifications/types.ts +15 -0
  468. package/src/oauth/AGENTS.md +2 -0
  469. package/src/oauth/__tests__/identity-verifier.test.ts +36 -1
  470. package/src/oauth/connection-resolver.ts +1 -2
  471. package/src/oauth/identity-verifier.ts +24 -0
  472. package/src/oauth/oauth-store.ts +12 -4
  473. package/src/oauth/provider-serializer.ts +8 -0
  474. package/src/oauth/seed-providers.ts +42 -0
  475. package/src/onboarding/onboarding-events-store.ts +99 -12
  476. package/src/permissions/confirmation-guardian-request.test.ts +16 -0
  477. package/src/permissions/confirmation-guardian-request.ts +2 -3
  478. package/src/permissions/question-prompter.test.ts +31 -0
  479. package/src/permissions/question-prompter.ts +2 -0
  480. package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
  481. package/src/persistence/attachments-store.ts +84 -44
  482. package/src/persistence/client-connection-events-store.ts +377 -0
  483. package/src/persistence/conversation-crud.ts +166 -26
  484. package/src/persistence/conversation-mode-sessions.test.ts +424 -0
  485. package/src/persistence/conversation-mode-sessions.ts +460 -0
  486. package/src/persistence/conversation-plugin-facade.ts +30 -0
  487. package/src/persistence/conversation-queries.ts +6 -19
  488. package/src/persistence/conversation-tool-surface.ts +135 -0
  489. package/src/persistence/conversation-types.test.ts +32 -0
  490. package/src/persistence/conversation-types.ts +26 -4
  491. package/src/persistence/llm-usage-store.ts +3 -9
  492. package/src/persistence/message-metadata.ts +25 -0
  493. package/src/persistence/migrations/378-create-conversation-tool-surfaces.test.ts +78 -0
  494. package/src/persistence/migrations/378-create-conversation-tool-surfaces.ts +29 -0
  495. package/src/persistence/migrations/379-oauth-providers-response-ok-field.test.ts +92 -0
  496. package/src/persistence/migrations/379-oauth-providers-response-ok-field.ts +32 -0
  497. package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.test.ts +90 -0
  498. package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.ts +34 -0
  499. package/src/persistence/migrations/381-create-conversation-mode-sessions.ts +41 -0
  500. package/src/persistence/migrations/382-create-client-connection-events.ts +40 -0
  501. package/src/persistence/migrations/__tests__/382-create-client-connection-events.test.ts +56 -0
  502. package/src/persistence/schema/conversation-tool-surfaces.ts +32 -0
  503. package/src/persistence/schema/conversations.ts +67 -0
  504. package/src/persistence/schema/index.ts +1 -0
  505. package/src/persistence/schema/infrastructure.ts +29 -0
  506. package/src/persistence/schema/oauth.ts +1 -0
  507. package/src/persistence/steps.ts +41 -3
  508. package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
  509. package/src/plugin-api/conversation-turn.ts +31 -7
  510. package/src/plugin-api/effective-context-window.ts +33 -0
  511. package/src/plugin-api/index.ts +35 -6
  512. package/src/plugin-api/plugin-channel-turn-trust.test.ts +133 -0
  513. package/src/plugin-api/plugin-channel-turn-trust.ts +71 -0
  514. package/src/plugin-api/plugin-name-env.ts +125 -0
  515. package/src/plugin-api/resolve-credential.ts +79 -20
  516. package/src/plugin-api/vision-support.test.ts +22 -0
  517. package/src/plugin-api/vision-support.ts +17 -5
  518. package/src/plugins/__tests__/active-plugin-env.test.ts +136 -0
  519. package/src/plugins/active-plugin-env.ts +51 -0
  520. package/src/plugins/defaults/index.ts +24 -0
  521. package/src/plugins/defaults/memory/AGENTS.md +39 -5
  522. package/src/plugins/defaults/memory/__tests__/archive-removal-framing.test.ts +64 -0
  523. package/src/plugins/defaults/memory/__tests__/buffer-file.test.ts +365 -0
  524. package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +43 -0
  525. package/src/plugins/defaults/memory/__tests__/conversation-memory-purge.test.ts +1 -0
  526. package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +2 -0
  527. package/src/plugins/defaults/memory/__tests__/fixtures/buffer-appender.ts +17 -0
  528. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +74 -0
  529. package/src/plugins/defaults/memory/__tests__/memory-run-evidence.test.ts +161 -0
  530. package/src/plugins/defaults/memory/__tests__/relocated-memory-test-rows.ts +10 -0
  531. package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
  532. package/src/plugins/defaults/memory/buffer-file.ts +354 -0
  533. package/src/plugins/defaults/memory/buffer-format.ts +40 -0
  534. package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
  535. package/src/plugins/defaults/memory/context-search/agent-runner.ts +77 -22
  536. package/src/plugins/defaults/memory/context-search/format.ts +53 -8
  537. package/src/plugins/defaults/memory/context-search/limits.ts +10 -12
  538. package/src/plugins/defaults/memory/context-search/recall-input.ts +38 -0
  539. package/src/plugins/defaults/memory/context-search/search.ts +8 -14
  540. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +1 -0
  541. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +2 -1
  542. package/src/plugins/defaults/memory/context-search/sources/workspace.ts +2 -1
  543. package/src/plugins/defaults/memory/context-search/types.ts +1 -11
  544. package/src/plugins/defaults/memory/conversation-memory-purge.ts +4 -0
  545. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
  546. package/src/plugins/defaults/memory/graph/capability-seed.ts +1 -2
  547. package/src/plugins/defaults/memory/graph/tool-handlers.ts +13 -63
  548. package/src/plugins/defaults/memory/graph/tools.ts +35 -64
  549. package/src/plugins/defaults/memory/host-utils.ts +0 -10
  550. package/src/plugins/defaults/memory/injectors.ts +4 -3
  551. package/src/plugins/defaults/memory/memory-retrospective-job.ts +72 -183
  552. package/src/plugins/defaults/memory/memory-run-evidence.ts +213 -0
  553. package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
  554. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +6 -1
  555. package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
  556. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +407 -99
  557. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +10 -0
  558. package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +107 -7
  559. package/src/plugins/defaults/memory/substrate/consolidation-job.ts +307 -86
  560. package/src/plugins/defaults/memory/substrate/consolidation-tool-surface.ts +34 -0
  561. package/src/plugins/defaults/memory/substrate/page-index.ts +2 -1
  562. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +91 -51
  563. package/src/plugins/defaults/memory/substrate/sweep-job.ts +1 -1
  564. package/src/plugins/defaults/memory/tools.test.ts +124 -9
  565. package/src/plugins/defaults/memory/tools.ts +38 -11
  566. package/src/plugins/defaults/memory/v1/graph/consolidation.ts +2 -2
  567. package/src/plugins/defaults/memory/v1/graph/extraction.ts +2 -1
  568. package/src/plugins/defaults/memory/v1/graph/retriever.ts +1 -1
  569. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +5 -0
  570. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +5 -2
  571. package/src/plugins/defaults/memory/v2/reranker.ts +2 -1
  572. package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +81 -1
  573. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +87 -0
  574. package/src/plugins/defaults/memory/v3/__tests__/plugin-schema.test.ts +12 -0
  575. package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +332 -15
  576. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
  577. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +148 -28
  578. package/src/plugins/defaults/memory/v3/card.ts +2 -1
  579. package/src/plugins/defaults/memory/v3/injector.ts +212 -178
  580. package/src/plugins/defaults/memory/v3/orchestrate.ts +159 -32
  581. package/src/plugins/defaults/memory/v3/plugin-schema.ts +54 -4
  582. package/src/plugins/defaults/memory/v3/pool-log-store.ts +275 -37
  583. package/src/plugins/defaults/memory/v3/pool-select.test.ts +47 -5
  584. package/src/plugins/defaults/memory/v3/pool-select.ts +710 -59
  585. package/src/plugins/defaults/memory/v3/sections.ts +2 -1
  586. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +41 -14
  587. package/src/plugins/defaults/memory/worker-control.ts +15 -5
  588. package/src/plugins/defaults/task-progress/__tests__/registration.test.ts +70 -0
  589. package/src/plugins/defaults/task-progress/__tests__/task-progress-context.test.ts +380 -0
  590. package/src/plugins/defaults/task-progress/hooks/post-compact.ts +19 -0
  591. package/src/plugins/defaults/task-progress/hooks/user-prompt-submit.ts +24 -0
  592. package/src/plugins/defaults/task-progress/package.json +14 -0
  593. package/src/plugins/defaults/task-progress/src/apply-task-progress-context.ts +93 -0
  594. package/src/plugins/defaults/task-progress/src/format-task-progress-context.ts +67 -0
  595. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +4 -1
  596. package/src/plugins/defaults/tool-result-truncate/terminal.ts +1 -46
  597. package/src/prompts/__tests__/parallel-tasks-section.test.ts +25 -0
  598. package/src/prompts/delegation-gate.ts +57 -0
  599. package/src/prompts/system-prompt.ts +14 -32
  600. package/src/providers/__tests__/context-overflow-error.test.ts +10 -0
  601. package/src/providers/__tests__/search-provider-catalog.test.ts +18 -0
  602. package/src/providers/anthropic/client.ts +10 -1
  603. package/src/providers/anthropic-gateway-shared.ts +6 -0
  604. package/src/providers/fetch-provider-catalog.ts +11 -0
  605. package/src/providers/gemini/client.ts +25 -8
  606. package/src/providers/inference/adapter-factory.ts +6 -0
  607. package/src/providers/jev/client.test.ts +270 -0
  608. package/src/providers/jev/client.ts +534 -0
  609. package/src/providers/model-catalog.ts +59 -3
  610. package/src/providers/openai/__tests__/chat-completions-extra-body.test.ts +94 -1
  611. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +106 -1
  612. package/src/providers/openai/__tests__/chat-template-flatten.test.ts +24 -0
  613. package/src/providers/openai/__tests__/google-thought-signature.test.ts +1 -2
  614. package/src/providers/openai/chat-completions-provider.ts +100 -29
  615. package/src/providers/openai/google-thought-signature.ts +0 -6
  616. package/src/providers/openai/responses-provider.ts +23 -1
  617. package/src/providers/ratelimit.ts +1 -3
  618. package/src/providers/search-provider-catalog.ts +24 -0
  619. package/src/providers/server-tool-pairing.ts +16 -7
  620. package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +24 -0
  621. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +7 -1
  622. package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +50 -1
  623. package/src/providers/speech-to-text/deepgram-flux-frames.ts +11 -0
  624. package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +13 -0
  625. package/src/providers/types.ts +5 -0
  626. package/src/routes/control.ts +7 -5
  627. package/src/runtime/AGENTS.md +6 -4
  628. package/src/runtime/__tests__/agent-wake.test.ts +94 -1
  629. package/src/runtime/actor-trust-resolver.ts +3 -3
  630. package/src/runtime/agent-wake.ts +32 -5
  631. package/src/runtime/approval-message-composer.ts +3 -69
  632. package/src/runtime/assistant-event-hub.ts +73 -75
  633. package/src/runtime/assistant-event-publish-options.ts +7 -0
  634. package/src/runtime/assistant-event-targeting.ts +79 -0
  635. package/src/runtime/assistant-stream-state.ts +13 -100
  636. package/src/runtime/background-job-runner.ts +5 -5
  637. package/src/runtime/channel-retry-sweep.ts +1 -0
  638. package/src/runtime/guardian-action-message-composer.ts +8 -161
  639. package/src/runtime/guardian-action-service.ts +2 -17
  640. package/src/runtime/guardian-reply-router.ts +29 -40
  641. package/src/runtime/http-server.ts +2 -2
  642. package/src/runtime/http-types.ts +6 -0
  643. package/src/runtime/message-composer-types.ts +3 -61
  644. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +67 -1
  645. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +89 -0
  646. package/src/runtime/migrations/vbundle-builder.ts +24 -1
  647. package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -4
  648. package/src/runtime/migrations/vbundle-import-policy.ts +43 -11
  649. package/src/runtime/migrations/vbundle-importer.ts +4 -1
  650. package/src/runtime/migrations/vbundle-streaming-importer.ts +4 -1
  651. package/src/runtime/migrations/vbundle-validator.ts +1 -0
  652. package/src/runtime/pending-interactions-mode-session.test.ts +62 -0
  653. package/src/runtime/pending-interactions.ts +29 -0
  654. package/src/runtime/routes/__tests__/client-history-routes.test.ts +104 -0
  655. package/src/runtime/routes/__tests__/image-generation-routes.test.ts +97 -0
  656. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +24 -2
  657. package/src/runtime/routes/__tests__/roadmap-routes.test.ts +29 -6
  658. package/src/runtime/routes/browser-context.ts +31 -11
  659. package/src/runtime/routes/browser-routes.ts +43 -4
  660. package/src/runtime/routes/btw-routes.ts +9 -4
  661. package/src/runtime/routes/channel-route-shared.ts +1 -9
  662. package/src/runtime/routes/client-routes.ts +108 -0
  663. package/src/runtime/routes/conversation-management-routes.ts +4 -1
  664. package/src/runtime/routes/conversation-routes.ts +125 -14
  665. package/src/runtime/routes/credential-prompt-routes.ts +4 -3
  666. package/src/runtime/routes/credential-routes.ts +1 -2
  667. package/src/runtime/routes/desktop-setup-routes.test.ts +9 -18
  668. package/src/runtime/routes/desktop-setup-routes.ts +8 -7
  669. package/src/runtime/routes/documents-routes.ts +51 -0
  670. package/src/runtime/routes/email-routes.ts +3 -7
  671. package/src/runtime/routes/events-routes.ts +75 -54
  672. package/src/runtime/routes/guardian-approval-interception.ts +24 -0
  673. package/src/runtime/routes/identity-routes.ts +1 -5
  674. package/src/runtime/routes/image-generation-routes.ts +8 -14
  675. package/src/runtime/routes/inbound-message-handler.ts +37 -41
  676. package/src/runtime/routes/inbound-stages/backfill-sender-provenance.test.ts +168 -0
  677. package/src/runtime/routes/inbound-stages/backfill-sender-provenance.ts +96 -0
  678. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +39 -10
  679. package/src/runtime/routes/inbound-stages/background-dispatch.ts +9 -9
  680. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -0
  681. package/src/runtime/routes/inference-profile-session-handler.ts +11 -1
  682. package/src/runtime/routes/inference-profiles-routes.ts +9 -0
  683. package/src/runtime/routes/llm-context-normalization.ts +1 -7
  684. package/src/runtime/routes/migration-routes.ts +73 -2
  685. package/src/runtime/routes/notification-routes.ts +10 -0
  686. package/src/runtime/routes/oauth-commands-routes.ts +57 -54
  687. package/src/runtime/routes/oauth-providers.ts +11 -0
  688. package/src/runtime/routes/oauth-request-hints.test.ts +246 -0
  689. package/src/runtime/routes/oauth-request-hints.ts +149 -0
  690. package/src/runtime/routes/plugins-routes.ts +6 -0
  691. package/src/runtime/routes/roadmap-routes.ts +47 -8
  692. package/src/runtime/routes/schedule-routes.ts +2 -0
  693. package/src/runtime/routes/secret-routes.ts +99 -119
  694. package/src/runtime/routes/settings-routes.ts +10 -4
  695. package/src/runtime/routes/watcher-routes.ts +1 -3
  696. package/src/runtime/trust-class.test.ts +7 -6
  697. package/src/runtime/trust-class.ts +9 -17
  698. package/src/schedule/__tests__/worker-control.test.ts +36 -5
  699. package/src/schedule/__tests__/worker-mcp-bootstrap.test.ts +107 -0
  700. package/src/schedule/__tests__/worker-mcp-readiness.test.ts +173 -0
  701. package/src/schedule/__tests__/worker-mcp-tools.test.ts +13 -47
  702. package/src/schedule/run-script.ts +2 -2
  703. package/src/schedule/scheduler.ts +47 -11
  704. package/src/schedule/tool-surface-readiness.ts +65 -0
  705. package/src/schedule/worker-control.ts +15 -5
  706. package/src/schedule/worker-mcp.ts +85 -0
  707. package/src/schedule/worker.ts +9 -31
  708. package/src/security/secure-keys.ts +74 -112
  709. package/src/skills/clawhub.ts +3 -8
  710. package/src/skills/managed-store.ts +1 -5
  711. package/src/stt/types.ts +4 -0
  712. package/src/subagent/notify.ts +54 -34
  713. package/src/subagent/parent-notification.ts +6 -0
  714. package/src/telemetry/__tests__/phone-call-funnel.test.ts +72 -0
  715. package/src/telemetry/phone-call-funnel.ts +144 -0
  716. package/src/tools/__tests__/tool-schema-root-combinator-guard.test.ts +81 -0
  717. package/src/tools/ask-question/ask-question-tool.test.ts +167 -5
  718. package/src/tools/ask-question/ask-question-tool.ts +120 -22
  719. package/src/tools/browser/browser-execution.ts +29 -60
  720. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +561 -39
  721. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +435 -39
  722. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +1 -8
  723. package/src/tools/client-os.ts +15 -0
  724. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
  725. package/src/tools/computer-use/target.ts +42 -0
  726. package/src/tools/document/document-tool.ts +13 -18
  727. package/src/tools/execution-target.ts +14 -16
  728. package/src/tools/host-terminal/host-shell.ts +16 -7
  729. package/src/tools/network/__tests__/web-fetch-tinyfish.test.ts +250 -0
  730. package/src/tools/network/__tests__/web-search.test.ts +203 -0
  731. package/src/tools/network/web-fetch.ts +274 -7
  732. package/src/tools/network/web-search.ts +468 -6
  733. package/src/tools/permission-checker.ts +3 -3
  734. package/src/tools/policy-context.ts +3 -1
  735. package/src/tools/shared/filesystem/file-ops-service.ts +1 -31
  736. package/src/tools/shared/shell-output.test.ts +10 -0
  737. package/src/tools/shared/shell-output.ts +14 -2
  738. package/src/tools/skills/load.ts +2 -1
  739. package/src/tools/skills/sandbox-runner.ts +24 -4
  740. package/src/tools/skills/scaffold-managed.ts +2 -1
  741. package/src/tools/skills/skill-script-runner.ts +7 -0
  742. package/src/tools/skills/skill-tool-factory.ts +15 -1
  743. package/src/tools/terminal/__tests__/safe-env.test.ts +44 -4
  744. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -14
  745. package/src/tools/terminal/safe-env.ts +39 -24
  746. package/src/tools/terminal/sanitized-bash.ts +15 -2
  747. package/src/tools/terminal/shell-launch.test.ts +162 -0
  748. package/src/tools/terminal/shell.test.ts +29 -0
  749. package/src/tools/terminal/shell.ts +15 -7
  750. package/src/tools/tool-approval-handler.ts +5 -1
  751. package/src/tools/tool-types.ts +3 -3
  752. package/src/tools/types.ts +8 -2
  753. package/src/util/__tests__/worker-process-command.test.ts +5 -4
  754. package/src/util/abort-reasons.ts +18 -26
  755. package/src/util/browser-human-verification.ts +14 -0
  756. package/src/util/canonicalize-identity.test.ts +21 -0
  757. package/src/util/canonicalize-identity.ts +16 -0
  758. package/src/util/errors.ts +13 -3
  759. package/src/util/host-process.test.ts +17 -1
  760. package/src/util/host-process.ts +24 -0
  761. package/src/util/provider-error-patterns.ts +3 -0
  762. package/src/util/unicode.ts +29 -0
  763. package/src/util/worker-process.ts +77 -35
  764. package/src/workspace/migrations/157-add-desktop-files-launcher.ts +94 -0
  765. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +4 -10
  766. package/src/workspace/migrations/__tests__/157-add-desktop-files-launcher.test.ts +113 -0
  767. package/src/workspace/migrations/registry.ts +2 -0
  768. package/src/__tests__/computer-use-window-schema.test.ts +0 -24
  769. package/src/api/events/heartbeat-alert.ts +0 -20
  770. package/src/daemon/message-types/web-activity.ts +0 -65
  771. package/src/desktop/desktop-dependencies.test.ts +0 -131
  772. package/src/tools/computer-use/definitions.ts +0 -607
@@ -0,0 +1,32 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import {
4
+ COMPUTER_USE_SCREENSHOT_ATTACHMENT_IDS_KEY,
5
+ computerUseScreenshotAttachmentIdsFromMetadata,
6
+ } from "./conversation-types.js";
7
+
8
+ describe("computerUseScreenshotAttachmentIdsFromMetadata", () => {
9
+ test("returns valid nonempty attachment ids", () => {
10
+ expect(
11
+ computerUseScreenshotAttachmentIdsFromMetadata({
12
+ [COMPUTER_USE_SCREENSHOT_ATTACHMENT_IDS_KEY]: [
13
+ "attachment-1",
14
+ "",
15
+ 42,
16
+ "attachment-2",
17
+ ],
18
+ }),
19
+ ).toEqual(["attachment-1", "attachment-2"]);
20
+ });
21
+
22
+ test("treats absent and malformed metadata as legacy", () => {
23
+ expect(computerUseScreenshotAttachmentIdsFromMetadata(undefined)).toEqual(
24
+ [],
25
+ );
26
+ expect(
27
+ computerUseScreenshotAttachmentIdsFromMetadata({
28
+ [COMPUTER_USE_SCREENSHOT_ATTACHMENT_IDS_KEY]: "attachment-1",
29
+ }),
30
+ ).toEqual([]);
31
+ });
32
+ });
@@ -82,7 +82,10 @@ export function isBackgroundConversationType(
82
82
  * columns into one label.
83
83
  */
84
84
  export type ConversationKind =
85
- "user" | "background" | "background_memory_consolidation" | "scheduled";
85
+ | "user"
86
+ | "background"
87
+ | "background_memory_consolidation"
88
+ | "scheduled";
86
89
 
87
90
  /**
88
91
  * Single classifier shared by the LLM-context routes and the notification
@@ -270,6 +273,10 @@ export function isVoiceSessionUserMessage(
270
273
  */
271
274
  export const SIGHT_FRAME_ATTACHMENT_IDS_KEY = "sightFrameAttachmentIds";
272
275
 
276
+ /** Metadata key naming computer-use screenshots automatically linked to a reply. */
277
+ export const COMPUTER_USE_SCREENSHOT_ATTACHMENT_IDS_KEY =
278
+ "computerUseScreenshotAttachmentIds";
279
+
273
280
  /**
274
281
  * The row's attachments that arrived as ambient camera frames, by attachment
275
282
  * id. A user attachment carries no metadata of its own, so the marking lives on
@@ -291,6 +298,23 @@ export function sightFrameAttachmentIdsFromMetadata(
291
298
  );
292
299
  }
293
300
 
301
+ /**
302
+ * Attachment ids whose placement on this row was automatic computer-use
303
+ * screenshot promotion. Malformed and legacy metadata conservatively yields
304
+ * no marked attachments.
305
+ */
306
+ export function computerUseScreenshotAttachmentIdsFromMetadata(
307
+ metadata: Record<string, unknown> | null | undefined,
308
+ ): string[] {
309
+ const ids = metadata?.[COMPUTER_USE_SCREENSHOT_ATTACHMENT_IDS_KEY];
310
+ if (!Array.isArray(ids)) {
311
+ return [];
312
+ }
313
+ return ids.filter(
314
+ (id): id is string => typeof id === "string" && id.length > 0,
315
+ );
316
+ }
317
+
294
318
  /**
295
319
  * True when a stored `messages.metadata` column belongs to a standalone
296
320
  * ambient camera keep: a row the call's own gate sampled, which no one spoke.
@@ -360,9 +384,7 @@ export function isDesktopOriginatedUserMessage(
360
384
  return false;
361
385
  }
362
386
  const clientOs = parseClientOs((client as Record<string, unknown>).os);
363
- return (
364
- clientOs === "macos" || clientOs === "windows" || clientOs === "linux"
365
- );
387
+ return clientOs === "macos" || clientOs === "windows" || clientOs === "linux";
366
388
  }
367
389
 
368
390
  /**
@@ -515,19 +515,13 @@ interface GroupRow {
515
515
 
516
516
  type UsageQueryParam = ScheduleAttributionSqlParam;
517
517
 
518
- function normalizeUsageAggregationFilter(
519
- filter?: UsageAggregationFilter,
520
- ): UsageAggregationFilter {
521
- return normalizeScheduleAttributionFilter(filter);
522
- }
523
-
524
518
  function buildUsageAggregationWhere(
525
519
  range: UsageTimeRange,
526
520
  filter?: UsageAggregationFilter,
527
521
  eventAlias?: string,
528
522
  now: number = Date.now(),
529
523
  ): { sql: string; params: UsageQueryParam[] } {
530
- const normalized = normalizeUsageAggregationFilter(filter);
524
+ const normalized = normalizeScheduleAttributionFilter(filter);
531
525
  const eventTable = eventAlias ?? "llm_usage_events";
532
526
  const createdAt = `${eventTable}.created_at`;
533
527
  const clauses = [`${createdAt} >= ? AND ${createdAt} <= ?`];
@@ -852,7 +846,7 @@ export function getUsageGroupBreakdown(
852
846
  // Runtime allowlist — defense-in-depth against SQL injection via type assertions.
853
847
  assertGroupByDimension(groupBy);
854
848
 
855
- const normalizedFilter = normalizeUsageAggregationFilter(filter);
849
+ const normalizedFilter = normalizeScheduleAttributionFilter(filter);
856
850
 
857
851
  // Conversation grouping requires a JOIN with conversations to resolve titles.
858
852
  if (groupBy === "conversation") {
@@ -984,7 +978,7 @@ export function getUsageGroupedSeries(
984
978
  throw new Error("Grouped usage series does not support conversation");
985
979
  }
986
980
 
987
- const normalizedFilter = normalizeUsageAggregationFilter(filter);
981
+ const normalizedFilter = normalizeScheduleAttributionFilter(filter);
988
982
  let rows: UsageGroupedBucketRow[];
989
983
 
990
984
  if (groupBy === "schedule") {
@@ -1,3 +1,4 @@
1
+ import { type ModeSession, parseModeSession } from "../api/mode-session.js";
1
2
  import { safeParseRecord } from "../util/json.js";
2
3
 
3
4
  /**
@@ -18,3 +19,27 @@ export function mergeMessageMetadata(
18
19
  ...updates,
19
20
  });
20
21
  }
22
+
23
+ export function readModeSessionMetadata(
24
+ metadata: string | null | undefined,
25
+ ): ModeSession | undefined {
26
+ if (!metadata) {
27
+ return undefined;
28
+ }
29
+ return parseModeSession(safeParseRecord(metadata).modeSession);
30
+ }
31
+
32
+ export function readMessageSentAt(
33
+ metadata: string | null | undefined,
34
+ ): number | undefined {
35
+ if (!metadata) {
36
+ return undefined;
37
+ }
38
+ const sentAt = safeParseRecord(metadata).sentAt;
39
+ return typeof sentAt === "number" &&
40
+ Number.isInteger(sentAt) &&
41
+ sentAt >= 0 &&
42
+ Number.isFinite(new Date(sentAt).getTime())
43
+ ? sentAt
44
+ : undefined;
45
+ }
@@ -0,0 +1,78 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import * as schema from "../schema.js";
7
+ import { migrateCreateConversationToolSurfaces } from "./378-create-conversation-tool-surfaces.js";
8
+
9
+ function createTestDb() {
10
+ const sqlite = new Database(":memory:");
11
+ sqlite.run("PRAGMA foreign_keys = ON");
12
+ // Only the parent table the FK points at.
13
+ sqlite.run(/*sql*/ `CREATE TABLE conversations (id TEXT PRIMARY KEY)`);
14
+ return { sqlite, db: drizzle(sqlite, { schema }) };
15
+ }
16
+
17
+ function tableDdl(sqlite: Database): string | undefined {
18
+ const row = sqlite
19
+ .query(
20
+ `SELECT sql FROM sqlite_master WHERE type='table' AND name='conversation_tool_surfaces'`,
21
+ )
22
+ .get() as { sql: string } | null;
23
+ return row?.sql;
24
+ }
25
+
26
+ function insertSurface(sqlite: Database, conversationId: string): void {
27
+ sqlite
28
+ .query(
29
+ /*sql*/ `INSERT INTO conversation_tool_surfaces (conversation_id, tools_json, tools_hash, updated_at) VALUES (?, ?, ?, ?)`,
30
+ )
31
+ .run(conversationId, "[]", "hash", 1);
32
+ }
33
+
34
+ function surfaceCount(sqlite: Database): number {
35
+ const row = sqlite
36
+ .query(`SELECT COUNT(*) AS n FROM conversation_tool_surfaces`)
37
+ .get() as { n: number };
38
+ return row.n;
39
+ }
40
+
41
+ describe("migration 378: conversation_tool_surfaces", () => {
42
+ test("creates the table keyed by conversation with a cascading FK", () => {
43
+ const { sqlite, db } = createTestDb();
44
+ expect(tableDdl(sqlite)).toBeUndefined();
45
+
46
+ migrateCreateConversationToolSurfaces(db);
47
+
48
+ const ddl = tableDdl(sqlite);
49
+ expect(ddl).toContain("conversation_id TEXT PRIMARY KEY");
50
+ expect(ddl).toContain("REFERENCES conversations(id) ON DELETE CASCADE");
51
+ expect(ddl).toContain("tools_json TEXT NOT NULL");
52
+ expect(ddl).toContain("tools_hash TEXT NOT NULL");
53
+ expect(ddl).toContain("updated_at INTEGER NOT NULL");
54
+ });
55
+
56
+ test("deleting a conversation cascades to its surface row", () => {
57
+ const { sqlite, db } = createTestDb();
58
+ migrateCreateConversationToolSurfaces(db);
59
+ sqlite.query(`INSERT INTO conversations (id) VALUES (?)`).run("conv-1");
60
+ insertSurface(sqlite, "conv-1");
61
+ expect(surfaceCount(sqlite)).toBe(1);
62
+
63
+ sqlite.query(`DELETE FROM conversations WHERE id = ?`).run("conv-1");
64
+
65
+ expect(surfaceCount(sqlite)).toBe(0);
66
+ });
67
+
68
+ test("is idempotent: a second run keeps the table and its rows", () => {
69
+ const { sqlite, db } = createTestDb();
70
+ migrateCreateConversationToolSurfaces(db);
71
+ sqlite.query(`INSERT INTO conversations (id) VALUES (?)`).run("conv-1");
72
+ insertSurface(sqlite, "conv-1");
73
+
74
+ expect(() => migrateCreateConversationToolSurfaces(db)).not.toThrow();
75
+
76
+ expect(surfaceCount(sqlite)).toBe(1);
77
+ });
78
+ });
@@ -0,0 +1,29 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+
3
+ const TABLE = "conversation_tool_surfaces";
4
+
5
+ /**
6
+ * Create `conversation_tool_surfaces`: one row per conversation holding the
7
+ * tool definitions its most recent live turn sent to the provider, keyed by
8
+ * conversation with a content hash so an unchanged surface is never rewritten.
9
+ *
10
+ * Its own table rather than a column on `conversations` because the payload
11
+ * is a JSON array of every tool definition (tens of kilobytes) that only fork
12
+ * wakes read, while `conversations` rows are read whole on every hot path.
13
+ * The row cascades with its conversation, so a deleted conversation leaves
14
+ * no surface behind.
15
+ *
16
+ * Idempotent via IF NOT EXISTS.
17
+ */
18
+ export function migrateCreateConversationToolSurfaces(
19
+ database: DrizzleDb,
20
+ ): void {
21
+ database.run(
22
+ `CREATE TABLE IF NOT EXISTS ${TABLE} (
23
+ conversation_id TEXT PRIMARY KEY REFERENCES conversations(id) ON DELETE CASCADE,
24
+ tools_json TEXT NOT NULL,
25
+ tools_hash TEXT NOT NULL,
26
+ updated_at INTEGER NOT NULL
27
+ )`,
28
+ );
29
+ }
@@ -0,0 +1,92 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import * as schema from "../schema.js";
7
+ import { migrateOAuthProvidersResponseOkField } from "./379-oauth-providers-response-ok-field.js";
8
+
9
+ function createTestDb(options: { withTable?: boolean } = {}) {
10
+ const sqlite = new Database(":memory:");
11
+ if (options.withTable !== false) {
12
+ // Pre-379 shape: only the columns the migration and tests touch.
13
+ sqlite.exec(/*sql*/ `
14
+ CREATE TABLE oauth_providers (
15
+ provider_key TEXT PRIMARY KEY,
16
+ identity_ok_field TEXT,
17
+ created_at INTEGER NOT NULL,
18
+ updated_at INTEGER NOT NULL
19
+ );
20
+ `);
21
+ }
22
+ return { sqlite, db: drizzle(sqlite, { schema }) };
23
+ }
24
+
25
+ function columnNames(sqlite: Database): string[] {
26
+ return (
27
+ sqlite.query("PRAGMA table_info(oauth_providers)").all() as Array<{
28
+ name: string;
29
+ }>
30
+ ).map((c) => c.name);
31
+ }
32
+
33
+ describe("migration 379: oauth_providers.response_ok_field", () => {
34
+ test("adds the nullable column beside the identity one", () => {
35
+ const { sqlite, db } = createTestDb();
36
+ expect(columnNames(sqlite)).not.toContain("response_ok_field");
37
+
38
+ migrateOAuthProvidersResponseOkField(db);
39
+
40
+ const column = (
41
+ sqlite.query("PRAGMA table_info(oauth_providers)").all() as Array<{
42
+ name: string;
43
+ notnull: number;
44
+ }>
45
+ ).find((c) => c.name === "response_ok_field");
46
+ expect(column).toBeDefined();
47
+ expect(column?.notnull).toBe(0);
48
+ expect(columnNames(sqlite)).toContain("identity_ok_field");
49
+ });
50
+
51
+ test("rows written before the column existed read back null", () => {
52
+ // A provider that declared nothing is judged by status alone, which is
53
+ // what it was before the column existed.
54
+ const { sqlite, db } = createTestDb();
55
+ sqlite.exec(/*sql*/ `
56
+ INSERT INTO oauth_providers (provider_key, identity_ok_field, created_at, updated_at)
57
+ VALUES ('slack', 'ok', 1000, 1000)
58
+ `);
59
+
60
+ migrateOAuthProvidersResponseOkField(db);
61
+
62
+ const row = sqlite
63
+ .query(
64
+ "SELECT response_ok_field FROM oauth_providers WHERE provider_key = 'slack'",
65
+ )
66
+ .get() as { response_ok_field: unknown };
67
+ expect(row.response_ok_field).toBeNull();
68
+ });
69
+
70
+ test("is idempotent: re-run is a no-op", () => {
71
+ const { sqlite, db } = createTestDb();
72
+
73
+ migrateOAuthProvidersResponseOkField(db);
74
+ expect(() => migrateOAuthProvidersResponseOkField(db)).not.toThrow();
75
+
76
+ expect(
77
+ columnNames(sqlite).filter((n) => n === "response_ok_field"),
78
+ ).toHaveLength(1);
79
+ });
80
+
81
+ test("a missing table is a failure, never a silent success", () => {
82
+ // The runner checkpoints a throwing step as failed and retries it, and
83
+ // the registry defers this step behind the table's own. Swallowing the
84
+ // error here would checkpoint the step as done against no table, and the
85
+ // column would never be added.
86
+ // The driver wraps SQLite's "no such table" in its own message, so the
87
+ // assertion is that the step throws at all.
88
+ const { db } = createTestDb({ withTable: false });
89
+
90
+ expect(() => migrateOAuthProvidersResponseOkField(db)).toThrow();
91
+ });
92
+ });
@@ -0,0 +1,32 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { tableHasColumn } from "./schema-introspection.js";
3
+
4
+ const TABLE_NAME = "oauth_providers";
5
+ const COLUMN_NAME = "response_ok_field";
6
+ const COLUMN_DEFINITION = "response_ok_field TEXT";
7
+
8
+ /**
9
+ * Add `response_ok_field` to `oauth_providers` (migration 149): the dot path
10
+ * of the boolean a provider's API puts in every response body to report
11
+ * success (Slack: `ok`). Its own column, distinct from `identity_ok_field`,
12
+ * because the two declare different facts: the identity field governs the
13
+ * one call the provider row names, this one governs any request made with
14
+ * the credential.
15
+ *
16
+ * Nullable with no backfill: seeding upserts the value for the built-in rows
17
+ * on the next start, and a custom provider that declares nothing is judged by
18
+ * status alone, which is what it was before the column existed.
19
+ *
20
+ * Idempotent: guarded with `tableHasColumn` so a crash between the `ALTER
21
+ * TABLE` and the checkpoint write doesn't cause a duplicate-column error on
22
+ * the next boot. A missing table is not swallowed: the registry declares the
23
+ * dependency on the table's own step, so this one is deferred rather than
24
+ * checkpointed as done against no table.
25
+ */
26
+ export function migrateOAuthProvidersResponseOkField(
27
+ database: DrizzleDb,
28
+ ): void {
29
+ if (!tableHasColumn(database, TABLE_NAME, COLUMN_NAME)) {
30
+ database.run(`ALTER TABLE ${TABLE_NAME} ADD COLUMN ${COLUMN_DEFINITION}`);
31
+ }
32
+ }
@@ -0,0 +1,90 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import * as schema from "../schema.js";
7
+ import { migrateCreateConversationToolSurfaces } from "./378-create-conversation-tool-surfaces.js";
8
+ import { migrateConversationToolSurfacesDelegateIndependentTasks } from "./380-conversation-tool-surfaces-delegate-independent-tasks.js";
9
+
10
+ function createTestDb(options: { withTable?: boolean } = {}) {
11
+ const sqlite = new Database(":memory:");
12
+ sqlite.run("PRAGMA foreign_keys = ON");
13
+ // Only the parent table the FK points at.
14
+ sqlite.run(/*sql*/ `CREATE TABLE conversations (id TEXT PRIMARY KEY)`);
15
+ const db = drizzle(sqlite, { schema });
16
+ if (options.withTable !== false) {
17
+ // Pre-380 shape: the table as migration 378 creates it.
18
+ migrateCreateConversationToolSurfaces(db);
19
+ }
20
+ return { sqlite, db };
21
+ }
22
+
23
+ function columns(sqlite: Database): Array<{ name: string; notnull: number }> {
24
+ return sqlite
25
+ .query("PRAGMA table_info(conversation_tool_surfaces)")
26
+ .all() as Array<{ name: string; notnull: number }>;
27
+ }
28
+
29
+ describe("migration 380: conversation_tool_surfaces.delegate_independent_tasks", () => {
30
+ test("adds the nullable column", () => {
31
+ const { sqlite, db } = createTestDb();
32
+ expect(columns(sqlite).map((c) => c.name)).not.toContain(
33
+ "delegate_independent_tasks",
34
+ );
35
+
36
+ migrateConversationToolSurfacesDelegateIndependentTasks(db);
37
+
38
+ const column = columns(sqlite).find(
39
+ (c) => c.name === "delegate_independent_tasks",
40
+ );
41
+ expect(column).toBeDefined();
42
+ expect(column?.notnull).toBe(0);
43
+ });
44
+
45
+ test("rows written before the column existed read back null", () => {
46
+ // A fork replaying such a row derives the section for itself, which is
47
+ // what it did before the column existed.
48
+ const { sqlite, db } = createTestDb();
49
+ sqlite.query(`INSERT INTO conversations (id) VALUES (?)`).run("conv-1");
50
+ sqlite
51
+ .query(
52
+ /*sql*/ `INSERT INTO conversation_tool_surfaces (conversation_id, tools_json, tools_hash, updated_at) VALUES (?, ?, ?, ?)`,
53
+ )
54
+ .run("conv-1", "[]", "hash", 1);
55
+
56
+ migrateConversationToolSurfacesDelegateIndependentTasks(db);
57
+
58
+ const row = sqlite
59
+ .query(
60
+ "SELECT delegate_independent_tasks FROM conversation_tool_surfaces WHERE conversation_id = 'conv-1'",
61
+ )
62
+ .get() as { delegate_independent_tasks: unknown };
63
+ expect(row.delegate_independent_tasks).toBeNull();
64
+ });
65
+
66
+ test("is idempotent: re-run is a no-op", () => {
67
+ const { sqlite, db } = createTestDb();
68
+
69
+ migrateConversationToolSurfacesDelegateIndependentTasks(db);
70
+ expect(() =>
71
+ migrateConversationToolSurfacesDelegateIndependentTasks(db),
72
+ ).not.toThrow();
73
+
74
+ expect(
75
+ columns(sqlite).filter((c) => c.name === "delegate_independent_tasks"),
76
+ ).toHaveLength(1);
77
+ });
78
+
79
+ test("a missing table is a failure, never a silent success", () => {
80
+ // The runner checkpoints a throwing step as failed and retries it, and
81
+ // the registry defers this step behind the table's own. Swallowing the
82
+ // error here would checkpoint the step as done against no table, and the
83
+ // column would never be added.
84
+ const { db } = createTestDb({ withTable: false });
85
+
86
+ expect(() =>
87
+ migrateConversationToolSurfacesDelegateIndependentTasks(db),
88
+ ).toThrow();
89
+ });
90
+ });
@@ -0,0 +1,34 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { tableHasColumn } from "./schema-introspection.js";
3
+
4
+ const TABLE_NAME = "conversation_tool_surfaces";
5
+ const COLUMN_NAME = "delegate_independent_tasks";
6
+ const COLUMN_DEFINITION = "delegate_independent_tasks INTEGER";
7
+
8
+ /**
9
+ * Add `delegate_independent_tasks` to `conversation_tool_surfaces`: whether
10
+ * the system prompt of the turn that recorded the surface rendered the
11
+ * parallel-delegation section (`01-parallel-tasks`). The prompt derives that
12
+ * section from the same resolved tool surface, so a fork wake replaying the
13
+ * surface needs the rendered state too: the section sits in the system
14
+ * prompt, the second tier of the provider cache prefix, and a fork that
15
+ * derives it from its own restricted scope renders it off where the source
16
+ * rendered it on, missing the source's cached prefix from that byte on.
17
+ *
18
+ * Nullable with no backfill: a row written before the column existed reads
19
+ * null and the fork derives the section for itself, exactly as it did before
20
+ * the column; the next live turn records the state.
21
+ *
22
+ * Idempotent: guarded with `tableHasColumn` so a crash between the `ALTER
23
+ * TABLE` and the checkpoint write doesn't cause a duplicate-column error on
24
+ * the next boot. A missing table is not swallowed: the registry declares the
25
+ * dependency on the table's own step, so this one is deferred rather than
26
+ * checkpointed as done against no table.
27
+ */
28
+ export function migrateConversationToolSurfacesDelegateIndependentTasks(
29
+ database: DrizzleDb,
30
+ ): void {
31
+ if (!tableHasColumn(database, TABLE_NAME, COLUMN_NAME)) {
32
+ database.run(`ALTER TABLE ${TABLE_NAME} ADD COLUMN ${COLUMN_DEFINITION}`);
33
+ }
34
+ }
@@ -0,0 +1,41 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ const TABLE = "conversation_mode_sessions";
5
+
6
+ export function migrateCreateConversationModeSessions(
7
+ database: DrizzleDb,
8
+ ): void {
9
+ const sqlite = getSqliteFrom(database);
10
+ sqlite.exec(/* sql */ `
11
+ CREATE TABLE IF NOT EXISTS ${TABLE} (
12
+ id TEXT PRIMARY KEY,
13
+ conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
14
+ mode TEXT NOT NULL CHECK (mode IN ('computer_use', 'browser', 'live_vision', 'ambient')),
15
+ status TEXT NOT NULL CHECK (status IN ('active', 'completed', 'interrupted')),
16
+ source_started_at INTEGER NOT NULL,
17
+ first_included_at INTEGER,
18
+ first_included_message_id TEXT,
19
+ last_activity_at INTEGER NOT NULL,
20
+ last_owned_message_id TEXT,
21
+ ended_at INTEGER,
22
+ end_reason TEXT,
23
+ revision INTEGER NOT NULL DEFAULT 1 CHECK (revision > 0),
24
+ CHECK ((first_included_at IS NULL) = (first_included_message_id IS NULL)),
25
+ CHECK (
26
+ (status = 'active' AND ended_at IS NULL AND end_reason IS NULL)
27
+ OR (status = 'completed' AND ended_at IS NOT NULL AND end_reason IS NOT NULL AND length(end_reason) > 0)
28
+ OR (status = 'interrupted' AND end_reason IS NOT NULL AND length(end_reason) > 0)
29
+ ),
30
+ CHECK (ended_at IS NULL OR ended_at >= last_activity_at),
31
+ CHECK (last_activity_at >= source_started_at),
32
+ CHECK (first_included_at IS NULL OR first_included_at <= last_activity_at)
33
+ );
34
+ CREATE INDEX IF NOT EXISTS idx_conversation_mode_sessions_conversation_status
35
+ ON ${TABLE} (conversation_id, status);
36
+ `);
37
+ }
38
+
39
+ export function downCreateConversationModeSessions(database: DrizzleDb): void {
40
+ getSqliteFrom(database).exec(`DROP TABLE IF EXISTS ${TABLE}`);
41
+ }
@@ -0,0 +1,40 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ const TABLE = "client_connection_events";
5
+
6
+ /**
7
+ * Create `client_connection_events`: the durable hub subscribe/dispose
8
+ * ledger used by `assistant clients history`.
9
+ *
10
+ * One row per client-subscriber lifecycle event. Reconnects shorter than
11
+ * the flap window are coalesced at read time, not at write time, so the
12
+ * raw event stream stays a complete audit.
13
+ *
14
+ * Idempotent via IF NOT EXISTS.
15
+ */
16
+ export function migrateCreateClientConnectionEvents(database: DrizzleDb): void {
17
+ const sqlite = getSqliteFrom(database);
18
+ sqlite.exec(
19
+ `CREATE TABLE IF NOT EXISTS ${TABLE} (
20
+ id TEXT PRIMARY KEY,
21
+ client_id TEXT NOT NULL,
22
+ interface_id TEXT NOT NULL,
23
+ connection_id TEXT NOT NULL,
24
+ reason TEXT NOT NULL,
25
+ occurred_at INTEGER NOT NULL,
26
+ actor_principal_id TEXT,
27
+ client_version TEXT,
28
+ sse_watchdog INTEGER,
29
+ machine_name TEXT
30
+ )`,
31
+ );
32
+ sqlite.exec(
33
+ `CREATE INDEX IF NOT EXISTS idx_client_connection_events_client_occurred
34
+ ON ${TABLE} (client_id, occurred_at)`,
35
+ );
36
+ sqlite.exec(
37
+ `CREATE INDEX IF NOT EXISTS idx_client_connection_events_occurred
38
+ ON ${TABLE} (occurred_at)`,
39
+ );
40
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Migration 382 creates `client_connection_events`, the durable hub
3
+ * subscribe/dispose ledger used by `assistant clients history`.
4
+ */
5
+
6
+ import { Database } from "bun:sqlite";
7
+ import { describe, expect, test } from "bun:test";
8
+
9
+ import { drizzle } from "drizzle-orm/bun-sqlite";
10
+
11
+ import { getSqliteFrom } from "../../db-connection.js";
12
+ import * as schema from "../../schema.js";
13
+ import { migrateCreateClientConnectionEvents } from "../382-create-client-connection-events.js";
14
+
15
+ function createTestDb() {
16
+ const sqlite = new Database(":memory:");
17
+ sqlite.exec("PRAGMA journal_mode=WAL");
18
+ return drizzle(sqlite, { schema });
19
+ }
20
+
21
+ function tableNames(db: ReturnType<typeof createTestDb>): string[] {
22
+ const rows = getSqliteFrom(db)
23
+ .prepare("SELECT name FROM sqlite_master WHERE type = 'table'")
24
+ .all() as { name: string }[];
25
+ return rows.map((row) => row.name);
26
+ }
27
+
28
+ function indexNames(db: ReturnType<typeof createTestDb>): string[] {
29
+ const rows = getSqliteFrom(db)
30
+ .prepare("SELECT name FROM sqlite_master WHERE type = 'index'")
31
+ .all() as { name: string }[];
32
+ return rows.map((row) => row.name);
33
+ }
34
+
35
+ describe("migrateCreateClientConnectionEvents", () => {
36
+ test("creates the table and its lookup indexes", () => {
37
+ const db = createTestDb();
38
+
39
+ migrateCreateClientConnectionEvents(db);
40
+
41
+ expect(tableNames(db)).toContain("client_connection_events");
42
+ expect(indexNames(db)).toContain(
43
+ "idx_client_connection_events_client_occurred",
44
+ );
45
+ expect(indexNames(db)).toContain("idx_client_connection_events_occurred");
46
+ });
47
+
48
+ test("re-running is a no-op", () => {
49
+ const db = createTestDb();
50
+
51
+ migrateCreateClientConnectionEvents(db);
52
+ migrateCreateClientConnectionEvents(db);
53
+
54
+ expect(tableNames(db)).toContain("client_connection_events");
55
+ });
56
+ });