@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
@@ -9,10 +9,16 @@ import {
9
9
  setCesReconnect,
10
10
  } from "../security/secure-keys.js";
11
11
  import { getLogger } from "../util/logger.js";
12
- import { type CesClient, createCesClient } from "./client.js";
12
+ import {
13
+ openCesRpcSession,
14
+ reconnectCesRpcSession,
15
+ } from "./ces-connect.js";
16
+ import {
17
+ type CesClient,
18
+ type CesClientHandshakeOptions,
19
+ } from "./client.js";
13
20
  import {
14
21
  type CesProcessManager,
15
- CesUnavailableError,
16
22
  createCesProcessManager,
17
23
  } from "./process-manager.js";
18
24
  import {
@@ -45,70 +51,69 @@ interface CesStartupResult {
45
51
  }
46
52
 
47
53
  /**
48
- * Start the CES process and perform the RPC handshake. Returns immediately with
49
- * handles to the in-flight initialization — callers don't need to await this
50
- * for startup to continue.
54
+ * Open the assistant's CES RPC client and perform the handshake. Returns
55
+ * immediately with handles to the in-flight initialization: callers don't
56
+ * need to await this for startup to continue.
51
57
  *
52
- * The managed sidecar accepts exactly one bootstrap connection, so this must be
53
- * called at the process level (not per-conversation).
58
+ * Claims reconnect ownership before any credential read so boot identity
59
+ * loading cannot open a second, identity-less session through the child
60
+ * entry point. CES serves a multi-connection Unix socket, so child
61
+ * processes in other address spaces still open their own connections.
54
62
  */
55
63
  function startCesProcess(config: AssistantConfig): CesStartupResult {
56
64
  const pm = createCesProcessManager({ assistantConfig: config });
57
65
  const abortController = new AbortController();
58
66
  let currentClient: CesClient | undefined;
67
+ let handshake: CesClientHandshakeOptions = {};
68
+
69
+ // Own this process's CES session before resolveManagedProxyContext()
70
+ // reads the API key. That read must not take the child open path.
71
+ setCesReconnect(async () => {
72
+ const client = await reconnectCesRpcSession(pm, handshake);
73
+ if (client) {
74
+ log.info("CES reconnection handshake accepted");
75
+ }
76
+ return client;
77
+ });
59
78
 
60
79
  const handshakePromise = (async (): Promise<CesClient | undefined> => {
61
80
  try {
62
- const transport = await pm.start();
63
- if (abortController.signal.aborted) {
64
- throw new Error("CES initialization aborted during shutdown");
65
- }
66
- const client = createCesClient(transport);
67
- currentClient = client;
68
81
  // Resolve the assistant API key so CES can use it for platform
69
82
  // credential materialisation. In managed mode the key is provisioned
70
- // after hatch and stored in the credential store — CES can't read
71
- // the env var, so we pass it via the handshake.
83
+ // after hatch and stored in the credential store. CES can't read
84
+ // the env var, so we pass it via the handshake. Reconnect ownership
85
+ // is already claimed, so this read uses HTTP or the encrypted store,
86
+ // not a second RPC session.
72
87
  const proxyCtx = await resolveManagedProxyContext();
88
+ if (abortController.signal.aborted) {
89
+ return undefined;
90
+ }
73
91
  const assistantId = getPlatformAssistantId();
74
- const { accepted, reason } = await client.handshake({
92
+ handshake = {
75
93
  ...(proxyCtx.assistantApiKey
76
94
  ? { assistantApiKey: proxyCtx.assistantApiKey }
77
95
  : {}),
78
96
  ...(assistantId ? { assistantId } : {}),
97
+ };
98
+ const session = await openCesRpcSession({
99
+ processManager: pm,
100
+ signal: abortController.signal,
101
+ handshake,
79
102
  });
80
- if (abortController.signal.aborted) {
81
- client.close();
82
- throw new Error("CES initialization aborted during shutdown");
83
- }
84
- if (accepted) {
103
+ currentClient = session?.client;
104
+ if (session) {
85
105
  log.info(
86
106
  "CES client initialized and handshake accepted (server-level)",
87
107
  );
88
- return client;
89
108
  }
109
+ return session?.client;
110
+ } catch (err) {
90
111
  log.warn(
91
- { reason },
92
- "CES handshake rejected — CES tools will be unavailable",
112
+ { error: err instanceof Error ? err.message : String(err) },
113
+ "Failed to initialize CES client",
93
114
  );
94
- client.close();
95
115
  currentClient = undefined;
96
- await pm.stop();
97
- return undefined;
98
- } catch (err) {
99
- if (err instanceof CesUnavailableError) {
100
- log.info(
101
- { reason: err.message },
102
- "CES is not available — CES tools will be unavailable",
103
- );
104
- } else {
105
- log.warn(
106
- { error: err instanceof Error ? err.message : String(err) },
107
- "Failed to initialize CES client — CES tools will be unavailable",
108
- );
109
- }
110
116
  await pm.stop().catch(() => {});
111
- currentClient = undefined;
112
117
  return undefined;
113
118
  }
114
119
  })();
@@ -154,11 +159,11 @@ function updateClientRef(client: CesClient | undefined): void {
154
159
  }
155
160
 
156
161
  /**
157
- * Bring up the daemon's CES connection: start the process, run the handshake
158
- * (blocking up to a 20s timeout so credential reads can route through CES
159
- * before provider init), register the reconnection callback, and keep the live
160
- * client reference in sync. Non-fatal — on failure the daemon falls back to the
161
- * direct credential store.
162
+ * Open the assistant's CES RPC client: handshake (blocking up to a 20s
163
+ * timeout so credential reads can route through CES before provider init)
164
+ * and keep the live client reference in sync. Reconnect ownership is
165
+ * claimed before the identity read. Non-fatal: on failure the assistant
166
+ * falls back to the direct credential store.
162
167
  */
163
168
  export async function startCes(config: AssistantConfig): Promise<void> {
164
169
  const cesResult = startCesProcess(config);
@@ -171,7 +176,7 @@ export async function startCes(config: AssistantConfig): Promise<void> {
171
176
  timeoutMs: DEFAULT_CES_STARTUP_TIMEOUT_MS,
172
177
  onTimeout: () => {
173
178
  log.warn(
174
- "CES handshake timed out after 20s — falling back to direct credential store",
179
+ "CES handshake timed out after 20s, falling back to direct credential store",
175
180
  );
176
181
  },
177
182
  });
@@ -193,56 +198,13 @@ export async function startCes(config: AssistantConfig): Promise<void> {
193
198
  }
194
199
  }
195
200
 
196
- // Register CES reconnection callback so the credential layer can re-establish
197
- // the connection when the transport dies, instead of falling back to the
198
- // encrypted file store.
201
+ // Reconnect ownership is claimed inside startCesProcess before the
202
+ // identity read. Snapshotting the API key there (not here) avoids a
203
+ // second resolveManagedProxyContext() after setCesClient, which would
204
+ // read the key through CES while reconnecting.
199
205
  if (cesResult.processManager) {
200
206
  const pm = cesResult.processManager;
201
207
 
202
- // Snapshot the managed-proxy context and assistant ID at CES startup so the
203
- // reconnect closure below never calls back into `resolveManagedProxyContext()`.
204
- // That function reads the assistant API key via `getSecureKeyAsync()`, which
205
- // — once `setCesClient()` has resolved the backend to CES RPC — routes the
206
- // read through CES itself. During a reconnect the old transport is dead and
207
- // a new one is being set up by this very closure, so the nested credential
208
- // read recursively awaits its own in-flight reconnection and deadlocks until
209
- // `CREDENTIAL_OP_TIMEOUT_MS` (45s) fires. That 45-second stall delays every
210
- // CES restart and causes dependent credential reads (e.g. Meet's STT
211
- // provider resolution) to return `undefined` during the window. API key
212
- // rotation uses the `updateAssistantApiKey` RPC on the live client, not a
213
- // reconnect, so caching at startup is safe.
214
- const startupProxyCtx = await resolveManagedProxyContext();
215
- const startupAssistantId = getPlatformAssistantId();
216
-
217
- setCesReconnect(async () => {
218
- try {
219
- await pm.stop();
220
- const transport = await pm.start();
221
- const newClient = createCesClient(transport);
222
- const { accepted, reason } = await newClient.handshake({
223
- ...(startupProxyCtx.assistantApiKey
224
- ? { assistantApiKey: startupProxyCtx.assistantApiKey }
225
- : {}),
226
- ...(startupAssistantId ? { assistantId: startupAssistantId } : {}),
227
- });
228
- if (accepted) {
229
- log.info("CES reconnection handshake accepted");
230
- return newClient;
231
- }
232
- log.warn({ reason }, "CES reconnection handshake rejected");
233
- newClient.close();
234
- await pm.stop().catch(() => {});
235
- return undefined;
236
- } catch (err) {
237
- log.warn(
238
- { error: err instanceof Error ? err.message : String(err) },
239
- "CES reconnection attempt failed",
240
- );
241
- await pm.stop().catch(() => {});
242
- return undefined;
243
- }
244
- });
245
-
246
208
  // Proactive reconnect: when the transport dies (socket close, process
247
209
  // exit), start a retry-with-backoff loop immediately instead of waiting
248
210
  // for the next credential operation to trigger the lazy reconnect path.
@@ -1,196 +1,88 @@
1
1
  /**
2
- * CES executable discovery and transport bootstrap.
2
+ * CES socket discovery and transport bootstrap.
3
3
  *
4
- * Provides two discovery strategies:
5
- *
6
- * 1. **Sibling mode** — Locates the CLI-launched CES sibling process via its
7
- * Unix socket (`CES_LOCAL_SOCKET`). Used by bare-metal/local instances.
8
- *
9
- * 2. **Managed mode** — Locates the bootstrap Unix socket exposed by the CES
10
- * sidecar container through a shared emptyDir volume, and returns a
11
- * connected Unix socket transport.
12
- *
13
- * Both strategies fail closed: if the socket cannot be found, the discovery
14
- * returns a structured error rather than falling back to in-process
15
- * credential handling.
4
+ * Local siblings and managed sidecars share one resolver: `ces.sock` under
5
+ * `CES_BOOTSTRAP_SOCKET_DIR` (default `/run/ces-bootstrap`). Discovery fails
6
+ * closed if the socket cannot be found.
16
7
  */
17
8
 
18
9
  import { existsSync } from "node:fs";
19
- import { join } from "node:path";
20
10
 
21
- import { getIsContainerized } from "../config/env-registry.js";
11
+ import {
12
+ isNamedPipePath,
13
+ resolveIpcEndpoint,
14
+ } from "@vellumai/ipc-server-utils";
15
+
22
16
  import { getLogger } from "../util/logger.js";
23
17
 
24
18
  const log = getLogger("ces-discovery");
25
19
 
26
- // ---------------------------------------------------------------------------
27
- // Well-known paths
28
- // ---------------------------------------------------------------------------
29
-
30
- /** Default directory for the bootstrap socket shared volume. */
20
+ /** Default directory for the CES Unix socket. */
31
21
  const DEFAULT_BOOTSTRAP_SOCKET_DIR = "/run/ces-bootstrap";
32
22
 
33
- /** Bootstrap socket filename. */
34
- const BOOTSTRAP_SOCKET_NAME = "ces.sock";
35
-
36
23
  /**
37
- * Resolve the CES bootstrap socket path.
38
- *
39
- * Priority:
40
- * 1. `CES_BOOTSTRAP_SOCKET_DIR` env var (directory) — appends `ces.sock`
41
- * 2. `CES_BOOTSTRAP_SOCKET` env var (full file path override)
42
- * 3. Hardcoded default: `/run/ces-bootstrap/ces.sock`
24
+ * Resolve the CES socket path used in every environment.
43
25
  *
44
- * The pod template exports `CES_BOOTSTRAP_SOCKET_DIR`; the full-path
45
- * override is kept for local testing convenience.
26
+ * Uses `CES_BOOTSTRAP_SOCKET_DIR` when set, otherwise `/run/ces-bootstrap`.
27
+ * `ces.sock` is resolved through `resolveIpcEndpoint`.
46
28
  */
47
- function getManagedBootstrapSocketPath(): string {
48
- const dir = process.env["CES_BOOTSTRAP_SOCKET_DIR"];
49
- if (dir) {
50
- return join(dir, BOOTSTRAP_SOCKET_NAME);
51
- }
52
- return (
53
- process.env["CES_BOOTSTRAP_SOCKET"] ??
54
- join(DEFAULT_BOOTSTRAP_SOCKET_DIR, BOOTSTRAP_SOCKET_NAME)
55
- );
29
+ function getCesSocketPath(): string {
30
+ const dir =
31
+ process.env["CES_BOOTSTRAP_SOCKET_DIR"]?.trim() ||
32
+ DEFAULT_BOOTSTRAP_SOCKET_DIR;
33
+ return resolveIpcEndpoint("ces", { workspaceDir: dir }).path;
56
34
  }
57
35
 
58
- // ---------------------------------------------------------------------------
59
- // Discovery result types
60
- // ---------------------------------------------------------------------------
61
-
62
36
  export interface ManagedDiscoverySuccess {
63
37
  mode: "managed";
64
38
  socketPath: string;
65
39
  }
66
40
 
67
- /**
68
- * A local CES running as an independent sibling process (not spawned by the
69
- * assistant), reached over a Unix socket. Transport-identical to managed; the
70
- * distinct mode records that the assistant does not own this process's
71
- * lifecycle. This is the default topology for bare-metal/local instances.
72
- */
73
- export interface SiblingDiscoverySuccess {
74
- mode: "sibling";
75
- socketPath: string;
76
- }
77
-
78
41
  export interface DiscoveryFailure {
79
42
  mode: "unavailable";
80
43
  reason: string;
81
44
  }
82
45
 
83
- export type DiscoveryResult =
84
- | ManagedDiscoverySuccess
85
- | SiblingDiscoverySuccess
86
- | DiscoveryFailure;
87
-
88
- // ---------------------------------------------------------------------------
89
- // Managed discovery
90
- // ---------------------------------------------------------------------------
46
+ export type DiscoveryResult = ManagedDiscoverySuccess | DiscoveryFailure;
91
47
 
92
48
  /**
93
- * Discover the managed CES sidecar via its bootstrap Unix socket.
94
- *
95
- * Checks that the well-known socket file exists on disk. Does NOT open a
96
- * connection — the CES sidecar accepts exactly one connection and then
97
- * unlinks the socket, so a probe would consume the only slot. The actual
98
- * connection is made later by `CesProcessManager.start()`.
49
+ * Discover CES via the shared bootstrap Unix socket.
99
50
  *
100
- * The socket path is derived from `CES_BOOTSTRAP_SOCKET_DIR` (matching the
101
- * pod template), with `CES_BOOTSTRAP_SOCKET` as a full-path fallback.
51
+ * Checks that the well-known socket exists. Does not open a connection.
52
+ * CES serves a multi-connection listener, so the assistant and its child
53
+ * processes can each connect. The actual connection is made later by
54
+ * `CesProcessManager.start()`.
102
55
  */
103
- export function discoverManagedCes():
104
- | ManagedDiscoverySuccess
105
- | DiscoveryFailure {
106
- const socketPath = getManagedBootstrapSocketPath();
56
+ export function discoverCes(): DiscoveryResult {
57
+ const socketPath = getCesSocketPath();
107
58
 
108
- if (!existsSync(socketPath)) {
59
+ if (!isNamedPipePath(socketPath) && !existsSync(socketPath)) {
109
60
  const reason = `CES bootstrap socket not found at ${socketPath}`;
110
61
  log.warn(reason);
111
62
  return { mode: "unavailable", reason };
112
63
  }
113
64
 
114
- log.info({ socketPath }, "Managed CES bootstrap socket found");
65
+ log.info({ socketPath }, "CES bootstrap socket found");
115
66
  return { mode: "managed", socketPath };
116
67
  }
117
68
 
118
- // ---------------------------------------------------------------------------
119
- // Sibling discovery (local bare-metal topology)
120
- // ---------------------------------------------------------------------------
121
-
122
- /**
123
- * Discover a CLI-launched local CES sibling via its Unix socket. The CLI sets
124
- * `CES_LOCAL_SOCKET` on both the sibling and the daemon so they agree on the
125
- * path. Does not open a connection — that happens in `CesProcessManager.start()`.
126
- */
127
- export function discoverLocalSiblingCes():
128
- | SiblingDiscoverySuccess
129
- | DiscoveryFailure {
130
- const socketPath = process.env["CES_LOCAL_SOCKET"];
131
- if (!socketPath) {
132
- const reason =
133
- "CES_LOCAL_SOCKET is not set — cannot locate the CES sibling socket. The CLI should set this during wake/hatch.";
134
- log.warn(reason);
135
- return { mode: "unavailable", reason };
136
- }
137
- if (!existsSync(socketPath)) {
138
- return {
139
- mode: "unavailable",
140
- reason: `CES sibling socket not found at ${socketPath}`,
141
- };
142
- }
143
- log.info({ socketPath }, "Local CES sibling socket found");
144
- return { mode: "sibling", socketPath };
145
- }
146
-
147
- // ---------------------------------------------------------------------------
148
- // Auto-discovery
149
- // ---------------------------------------------------------------------------
150
-
151
- /**
152
- * Automatically discover CES using the appropriate strategy for the
153
- * current deployment topology.
154
- *
155
- * - Containerized environments → managed sidecar discovery
156
- * - Non-containerized → CLI-launched sibling socket discovery
157
- */
158
- export function discoverCes(): DiscoveryResult {
159
- if (getIsContainerized()) {
160
- return discoverManagedCes();
161
- }
162
- return discoverLocalSiblingCes();
163
- }
164
-
165
- /** How long to poll for the managed bootstrap socket before giving up. */
69
+ /** How long to poll for the CES socket before giving up. */
166
70
  const MANAGED_DISCOVERY_TIMEOUT_MS = 3_000;
167
71
 
168
- /** Delay between managed bootstrap-socket discovery attempts. */
72
+ /** Delay between CES socket discovery attempts. */
169
73
  const MANAGED_DISCOVERY_INTERVAL_MS = 100;
170
74
 
171
75
  /**
172
- * Discover CES, polling for the managed bootstrap socket with a short
173
- * backoff before failing.
174
- *
175
- * The managed CES sidecar re-binds its bootstrap socket after each assistant
176
- * session ends — it outlives any single assistant and accepts the next
177
- * connection (see `credential-executor/src/main.ts`). A reconnecting
178
- * assistant (e.g. after a container restart) can therefore probe during the
179
- * brief window before the socket is re-bound. A single existence check would
180
- * race that window and incorrectly report the sidecar as unavailable; polling
181
- * absorbs the gap.
76
+ * Discover CES, polling for the socket with a short backoff before failing.
182
77
  *
183
- * Local discovery is returned immediately — a missing binary will not appear
184
- * by waiting, so there is nothing to poll for.
78
+ * CES binds its socket asynchronously. A reconnecting assistant can probe
79
+ * during the brief window before the socket is re-bound. Polling absorbs
80
+ * that gap.
185
81
  */
186
82
  export async function discoverCesWithRetry({
187
83
  timeoutMs = MANAGED_DISCOVERY_TIMEOUT_MS,
188
84
  intervalMs = MANAGED_DISCOVERY_INTERVAL_MS,
189
85
  }: { timeoutMs?: number; intervalMs?: number } = {}): Promise<DiscoveryResult> {
190
- // Both the managed bootstrap socket and the CLI-launched sibling socket
191
- // are bound asynchronously, so polling is worthwhile. A missing local
192
- // binary (the old stdio path) would not appear by waiting, but that path
193
- // is gone — the sibling is the only local topology now.
194
86
  const deadline = Date.now() + timeoutMs;
195
87
  let result = discoverCes();
196
88
  while (result.mode === "unavailable" && Date.now() < deadline) {
@@ -3,12 +3,10 @@ import { createServer, type Server } from "node:net";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import {
6
- afterAll,
7
6
  afterEach,
8
7
  beforeEach,
9
8
  describe,
10
9
  expect,
11
- mock,
12
10
  test,
13
11
  } from "bun:test";
14
12
 
@@ -21,22 +19,18 @@ const untilClosed = (predicate: () => boolean) =>
21
19
  message: "socket close never propagated to the transport",
22
20
  });
23
21
 
24
- // ---------------------------------------------------------------------------
25
- // onTransportClose tests
26
- // ---------------------------------------------------------------------------
27
-
28
- // Mock executable-discovery so start() connects to our test socket.
29
- const realDiscovery = await import("./executable-discovery.js");
30
-
31
22
  let mockSocketPath = "";
32
23
 
33
- mock.module("./executable-discovery.js", () => ({
34
- ...realDiscovery,
35
- discoverCesWithRetry: async () => ({
36
- mode: "sibling" as const,
24
+ function discoverTestSocket() {
25
+ return Promise.resolve({
26
+ mode: "managed" as const,
37
27
  socketPath: mockSocketPath,
38
- }),
39
- }));
28
+ });
29
+ }
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // onTransportClose tests
33
+ // ---------------------------------------------------------------------------
40
34
 
41
35
  describe("CesProcessManager.onTransportClose", () => {
42
36
  let tempDir: string;
@@ -67,12 +61,8 @@ describe("CesProcessManager.onTransportClose", () => {
67
61
  rmSync(tempDir, { recursive: true, force: true });
68
62
  });
69
63
 
70
- afterAll(() => {
71
- mock.module("./executable-discovery.js", () => realDiscovery);
72
- });
73
-
74
64
  test("fires handler when the transport dies (socket closed)", async () => {
75
- const pm = createCesProcessManager({});
65
+ const pm = createCesProcessManager({ discover: discoverTestSocket });
76
66
  const transport = await pm.start();
77
67
  expect(transport.isAlive()).toBe(true);
78
68
 
@@ -93,7 +83,7 @@ describe("CesProcessManager.onTransportClose", () => {
93
83
  });
94
84
 
95
85
  test("does not fire handler before the transport dies", async () => {
96
- const pm = createCesProcessManager({});
86
+ const pm = createCesProcessManager({ discover: discoverTestSocket });
97
87
  await pm.start();
98
88
 
99
89
  let closeFired = false;
@@ -109,7 +99,7 @@ describe("CesProcessManager.onTransportClose", () => {
109
99
  });
110
100
 
111
101
  test("fires handler immediately if transport is already dead", async () => {
112
- const pm = createCesProcessManager({});
102
+ const pm = createCesProcessManager({ discover: discoverTestSocket });
113
103
  const transport = await pm.start();
114
104
 
115
105
  // Kill the transport by destroying the server-side socket.
@@ -186,7 +176,10 @@ describe("CesProcessManager transport-death logging", () => {
186
176
 
187
177
  test("logs WARN when the transport dies unexpectedly (remote close)", async () => {
188
178
  const { calls, logger } = makeRecordingLogger();
189
- const pm = createCesProcessManager({ logger });
179
+ const pm = createCesProcessManager({
180
+ logger,
181
+ discover: discoverTestSocket,
182
+ });
190
183
  const transport = await pm.start();
191
184
 
192
185
  // The remote (server) closes the connection: genuinely-unexpected death.
@@ -205,7 +198,10 @@ describe("CesProcessManager transport-death logging", () => {
205
198
 
206
199
  test("does not log WARN on an intentional stop()", async () => {
207
200
  const { calls, logger } = makeRecordingLogger();
208
- const pm = createCesProcessManager({ logger });
201
+ const pm = createCesProcessManager({
202
+ logger,
203
+ discover: discoverTestSocket,
204
+ });
209
205
  await pm.start();
210
206
 
211
207
  await pm.stop();
@@ -1,17 +1,17 @@
1
1
  /**
2
2
  * CES process manager.
3
3
  *
4
- * Creates transport connections to the CES process — either a CLI-launched
5
- * sibling over a Unix socket (bare-metal/local), or a managed sidecar over
6
- * its bootstrap socket (containerized). The process manager owns only the
7
- * transport connection lifecycle; the CES process itself is managed by the
8
- * CLI (sibling) or the pod infrastructure (managed).
4
+ * Creates a transport connection to the CES process over the shared bootstrap
5
+ * socket. Local CLI siblings and managed sidecars bind the same path under
6
+ * `CES_BOOTSTRAP_SOCKET_DIR`. The process manager owns only the transport
7
+ * connection lifecycle; the CES process itself is managed by the CLI
8
+ * (sibling) or the pod infrastructure (managed).
9
9
  *
10
- * Managed env contract:
11
- * - CES_BOOTSTRAP_SOCKET — Path to the bootstrap Unix socket (shared emptyDir)
12
- * - /assistant-data-ro — Assistant data mounted read-only into the CES sidecar
13
- * - /ces-data — CES private data directory (separate PVC)
14
- * - CES_HEALTH_PORT — Health check port exposed by the CES sidecar
10
+ * Env contract:
11
+ * - CES_BOOTSTRAP_SOCKET_DIR: directory containing `ces.sock`
12
+ * - /assistant-data-ro: assistant data mounted read-only into CES
13
+ * - /ces-data: CES private data directory (separate PVC)
14
+ * - CES_HEALTH_PORT: health check port exposed by the CES sidecar
15
15
  */
16
16
 
17
17
  import { createConnection, type Socket } from "node:net";
@@ -24,7 +24,6 @@ import {
24
24
  discoverCesWithRetry,
25
25
  type DiscoveryResult,
26
26
  type ManagedDiscoverySuccess,
27
- type SiblingDiscoverySuccess,
28
27
  } from "./executable-discovery.js";
29
28
 
30
29
  const log = getLogger("ces-process-manager");
@@ -62,6 +61,12 @@ export interface CesProcessManagerConfig {
62
61
 
63
62
  /** Logger override. Defaults to the module logger; injected in tests. */
64
63
  logger?: PmLogger;
64
+
65
+ /**
66
+ * Socket discovery. Defaults to `discoverCesWithRetry`. Tests inject a
67
+ * stub that returns a known socket path.
68
+ */
69
+ discover?: typeof discoverCesWithRetry;
65
70
  }
66
71
 
67
72
  // ---------------------------------------------------------------------------
@@ -70,7 +75,7 @@ export interface CesProcessManagerConfig {
70
75
 
71
76
  export interface CesProcessManager {
72
77
  /**
73
- * Connect to the CES process (sibling socket or managed sidecar socket).
78
+ * Connect to the CES bootstrap socket.
74
79
  * Returns a CesTransport ready for use with createCesClient().
75
80
  *
76
81
  * Throws if CES is unavailable.
@@ -107,6 +112,7 @@ export function createCesProcessManager(
107
112
  config: CesProcessManagerConfig,
108
113
  ): CesProcessManager {
109
114
  const pmLog = config.logger ?? log;
115
+ const discover = config.discover ?? discoverCesWithRetry;
110
116
  let managedSocket: Socket | null = null;
111
117
  let discoveryResult: DiscoveryResult | null = null;
112
118
  let running = false;
@@ -119,16 +125,15 @@ export function createCesProcessManager(
119
125
  throw new Error("CES process manager is already running");
120
126
  }
121
127
 
122
- // Poll for the socket with a short backoff. Both the managed bootstrap
123
- // socket and the CLI-launched sibling socket are bound asynchronously,
124
- // so a reconnecting assistant can briefly race the re-bind.
125
- discoveryResult = await discoverCesWithRetry();
128
+ // Poll for the socket with a short backoff. CES binds
129
+ // asynchronously, so a reconnecting assistant can briefly race
130
+ // the re-bind.
131
+ discoveryResult = await discover();
126
132
 
127
133
  if (discoveryResult.mode === "unavailable") {
128
134
  throw new CesUnavailableError(discoveryResult.reason);
129
135
  }
130
136
 
131
- // managed sidecar or CLI-launched sibling — both connect to a socket.
132
137
  const transport = await connectManagedSocket(discoveryResult);
133
138
  currentTransport = transport;
134
139
  wireTransportClose(transport);
@@ -200,11 +205,11 @@ export function createCesProcessManager(
200
205
  }
201
206
 
202
207
  // -------------------------------------------------------------------------
203
- // Socket connection — managed sidecar or CLI-launched local sibling
208
+ // Socket connection
204
209
  // -------------------------------------------------------------------------
205
210
 
206
211
  async function connectManagedSocket(
207
- discovery: ManagedDiscoverySuccess | SiblingDiscoverySuccess,
212
+ discovery: ManagedDiscoverySuccess,
208
213
  ): Promise<SocketTransport> {
209
214
  pmLog.info(
210
215
  { socketPath: discovery.socketPath, mode: discovery.mode },
@@ -440,7 +440,12 @@ describe("handleSurfaceAction — launch_conversation dispatch", () => {
440
440
  // claimed to eliminate that round-trip; this test enforces it.
441
441
  nextKeyStoreResult = { conversationId: "conv-pending-set" };
442
442
 
443
- const ctx = makeContext();
443
+ const settleStructuralWait = mock(() => true);
444
+ const ctx = makeContext({
445
+ modeSessions: {
446
+ settleStructuralWait,
447
+ } as unknown as Conversation["modeSessions"],
448
+ });
444
449
  registerCardSurface(ctx, "surface-pending");
445
450
  // Simulate `ui_show` having stamped a pending entry for this surface
446
451
  // (which it does for any interactive card, including persistent ones).
@@ -473,6 +478,10 @@ describe("handleSurfaceAction — launch_conversation dispatch", () => {
473
478
  // Pending entry was deleted so subsequent sibling clicks on the same
474
479
  // persistent card aren't blocked behind a stale "owes-an-answer" flag.
475
480
  expect(ctx.pendingSurfaceActions.has("surface-pending")).toBe(false);
481
+ expect(settleStructuralWait).toHaveBeenCalledWith(
482
+ { kind: "surface", responseId: "surface-pending" },
483
+ { status: "completed", endReason: "surface_launch_settled" },
484
+ );
476
485
 
477
486
  await processStartedPromise;
478
487
  resolveProcess();