@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,85 @@
1
+ /**
2
+ * Schedule-worker MCP bootstrap and reload.
3
+ *
4
+ * The worker hosts execute/wake/workflow turns in its own process, so it
5
+ * has to connect MCP servers itself. Tool-backed schedules must not fire
6
+ * until that pass has settled: a 20s grace lets notify/script start, and
7
+ * the readiness latch defers the rest until registration finishes or
8
+ * fails closed.
9
+ */
10
+
11
+ import {
12
+ restartConfiguredMcpServers,
13
+ startConfiguredMcpServers,
14
+ } from "../mcp/startup.js";
15
+ import {
16
+ EMPTY_MCP_STARTUP_SNAPSHOT,
17
+ type McpStartupSnapshot,
18
+ } from "../mcp/tool-caps.js";
19
+ import { getLogger } from "../util/logger.js";
20
+ import {
21
+ markScheduleToolSurfaceReady,
22
+ markScheduleToolSurfaceReloading,
23
+ markScheduleToolSurfaceStarting,
24
+ } from "./tool-surface-readiness.js";
25
+
26
+ export { MCP_NOT_READY_DEFER_MS } from "./tool-surface-readiness.js";
27
+
28
+ const log = getLogger("schedule-worker-mcp");
29
+
30
+ /**
31
+ * How long startup waits before arming notify/script ticks.
32
+ *
33
+ * Connecting is worth waiting for. It is not worth waiting for without
34
+ * limit: each server may take 30s to connect and 30s to list tools. Past
35
+ * this deadline those ticks start. Tool-backed schedules stay deferred
36
+ * until {@link markScheduleToolSurfaceReady}.
37
+ */
38
+ export const MCP_STARTUP_GRACE_MS = 20_000;
39
+
40
+ export async function bootstrapScheduleWorkerMcp(options?: {
41
+ start?: () => Promise<McpStartupSnapshot>;
42
+ graceMs?: number;
43
+ }): Promise<void> {
44
+ const start = options?.start ?? startConfiguredMcpServers;
45
+ const graceMs = options?.graceMs ?? MCP_STARTUP_GRACE_MS;
46
+ markScheduleToolSurfaceStarting();
47
+ const startup = start()
48
+ .then((snapshot) => {
49
+ markScheduleToolSurfaceReady(snapshot);
50
+ log.info(snapshot, "MCP tool surface ready in schedule worker");
51
+ return snapshot;
52
+ })
53
+ .catch((err: unknown) => {
54
+ markScheduleToolSurfaceReady(EMPTY_MCP_STARTUP_SNAPSHOT);
55
+ log.error(
56
+ { err },
57
+ "MCP tool surface failed in schedule worker; continuing without MCP tools",
58
+ );
59
+ return EMPTY_MCP_STARTUP_SNAPSHOT;
60
+ });
61
+
62
+ await Promise.race([
63
+ startup,
64
+ new Promise<void>((resolve) => {
65
+ setTimeout(resolve, graceMs).unref();
66
+ }),
67
+ ]);
68
+ }
69
+
70
+ export async function reloadScheduleWorkerMcp(options?: {
71
+ restart?: () => Promise<McpStartupSnapshot>;
72
+ }): Promise<McpStartupSnapshot> {
73
+ const restart = options?.restart ?? restartConfiguredMcpServers;
74
+ markScheduleToolSurfaceReloading();
75
+ try {
76
+ const snapshot = await restart();
77
+ markScheduleToolSurfaceReady(snapshot);
78
+ log.info(snapshot, "MCP servers reloaded in schedule worker");
79
+ return snapshot;
80
+ } catch (err) {
81
+ markScheduleToolSurfaceReady(EMPTY_MCP_STARTUP_SNAPSHOT);
82
+ log.warn({ err }, "MCP reload failed in schedule worker");
83
+ throw err;
84
+ }
85
+ }
@@ -22,10 +22,6 @@ import { rehydratePlatformCredentials } from "../config/platform-rehydration.js"
22
22
  import { startConversationEvictor } from "../daemon/conversation-evictor.js";
23
23
  import { stopMcpServerManager } from "../mcp/manager.js";
24
24
  import { MCP_RELOAD_SIGNAL_FILE } from "../mcp/reload-signal.js";
25
- import {
26
- restartConfiguredMcpServers,
27
- startConfiguredMcpServers,
28
- } from "../mcp/startup.js";
29
25
  import { resetDb } from "../persistence/db-connection.js";
30
26
  import { registerWorkerPluginSurface } from "../plugins/worker-plugin-surface.js";
31
27
  import { disableStreamSeqStamping } from "../runtime/assistant-stream-state.js";
@@ -37,6 +33,10 @@ import {
37
33
  startWorkerPidFileGuard,
38
34
  } from "../util/worker-process.js";
39
35
  import { runDueSchedulesOnce } from "./scheduler.js";
36
+ import {
37
+ bootstrapScheduleWorkerMcp,
38
+ reloadScheduleWorkerMcp,
39
+ } from "./worker-mcp.js";
40
40
 
41
41
  const log = getLogger("schedule-worker-process");
42
42
 
@@ -46,19 +46,6 @@ const TICK_INTERVAL_MS = 15_000;
46
46
  /** How often this process re-reads flag overrides from the gateway. */
47
47
  const FLAG_REFRESH_INTERVAL_MS = 60_000;
48
48
 
49
- /**
50
- * How long startup waits for MCP servers before arming the tick.
51
- *
52
- * Connecting is worth waiting for: a schedule that fires first would fail its
53
- * `mcp__*` calls as unknown tools. It is not worth waiting for without limit.
54
- * `McpServerManager.start()` walks servers one at a time and allows each 30s to
55
- * connect and 30s more to list its tools, so a handful of unreachable ones can
56
- * hold the first tick for minutes, including the notify and script schedules
57
- * that never touch MCP. Past this deadline the connect continues in the
58
- * background and the tick starts without it.
59
- */
60
- const MCP_STARTUP_GRACE_MS = 20_000;
61
-
62
49
  /**
63
50
  * Rebuild this process's MCP connections whenever the daemon reports a reload.
64
51
  *
@@ -85,10 +72,7 @@ function watchForMcpReload(): void {
85
72
  restartQueued = true;
86
73
  return;
87
74
  }
88
- restarting = restartConfiguredMcpServers()
89
- .then((toolCount) => {
90
- log.info({ toolCount }, "MCP servers reloaded in schedule worker");
91
- })
75
+ restarting = reloadScheduleWorkerMcp()
92
76
  .catch((err: unknown) => {
93
77
  log.warn({ err }, "MCP reload failed in schedule worker");
94
78
  })
@@ -193,16 +177,10 @@ async function main(): Promise<void> {
193
177
  // keeps this process independent of the daemon's event loop, which is the
194
178
  // reason it is a separate process at all.
195
179
  //
196
- // Bounded by MCP_STARTUP_GRACE_MS: unreachable servers must not hold the
197
- // schedules that do not use them. The connect runs on past the deadline.
198
- const mcpStartup = startConfiguredMcpServers();
199
- await Promise.race([
200
- mcpStartup,
201
- // Unref'd so a connect that beats the deadline leaves nothing pending.
202
- new Promise((resolve) => {
203
- setTimeout(resolve, MCP_STARTUP_GRACE_MS).unref();
204
- }),
205
- ]);
180
+ // Bounded by MCP_STARTUP_GRACE_MS so notify/script can fire. Execute, wake,
181
+ // and workflow schedules stay deferred until the connect settles and the
182
+ // tool surface is marked ready.
183
+ await bootstrapScheduleWorkerMcp();
206
184
 
207
185
  // React to an MCP reload in the daemon. The server set belongs to the config
208
186
  // and the daemon owns the watcher that notices it change; this process holds
@@ -1,24 +1,22 @@
1
1
  /**
2
- * Unified secure key storage — single-backend routing through CredentialBackend
2
+ * Unified secure key storage: single-backend routing through CredentialBackend
3
3
  * adapters.
4
4
  *
5
5
  * Backend selection (`resolveBackendAsync`) is the single async decision point:
6
- * 1. CES RPC (primary) — injected via `setCesClient()`: delegates credential
7
- * operations to the CES process over Unix socket RPC. This is the default
8
- * path for the daemon (which calls startCes() at boot) and for non-daemon
9
- * processes that lazily connect via the CES_LOCAL_SOCKET path (see below).
10
- * 2. CES HTTP — containerized mode (IS_CONTAINERIZED + CES_CREDENTIAL_URL):
11
- * delegates to the CES sidecar over HTTP. Used in Docker/managed mode,
12
- * including failover when the bootstrap RPC transport dies later.
13
- * 3. Lazy CES RPC connect — non-daemon processes (workers, CLI subprocesses)
14
- * that inherit CES_LOCAL_SOCKET but never call startCes(). On first
15
- * credential resolution, a direct CES connection is established and
16
- * cached. On failure, falls through to the encrypted file store.
17
- * 4. Encrypted file store (fallback) — used when CES is unavailable.
6
+ * 1. CES RPC (primary) - connect to the CES bootstrap socket and talk RPC.
7
+ * `openCesRpcSession` is the one client constructor. The assistant
8
+ * claims session ownership at boot (`startCes`) and hands CES the
9
+ * assistant API key. Child processes open a session on first credential
10
+ * read only when this process has no client and no reconnect owner.
11
+ * 2. CES HTTP - containerized failover when IPC is unavailable
12
+ * (`IS_CONTAINERIZED` + `CES_CREDENTIAL_URL`). Used if the assistant's
13
+ * bootstrap RPC transport is down, or if a process with HTTP env could
14
+ * not open the socket.
15
+ * 3. Encrypted file store (fallback) - used when CES is unavailable locally.
18
16
  *
19
17
  * All operations (reads, writes, lists, deletes) go to exactly one backend.
20
18
  * There are no cross-store fallbacks or merges. The only transport failover is
21
- * CES RPC → CES HTTP in managed mode; both backends target the same CES
19
+ * CES RPC to CES HTTP in managed mode; both backends target the same CES
22
20
  * sidecar and credential data.
23
21
  */
24
22
 
@@ -33,13 +31,11 @@ import type {
33
31
 
34
32
  import { getIsContainerized } from "../config/env-registry.js";
35
33
  import {
36
- type CesClient,
37
- createCesClient,
38
- } from "../credential-execution/client.js";
39
- import {
40
- CesUnavailableError,
41
- createCesProcessManager,
42
- } from "../credential-execution/process-manager.js";
34
+ openCesRpcSession,
35
+ reconnectCesRpcSession,
36
+ } from "../credential-execution/ces-connect.js";
37
+ import { type CesClient } from "../credential-execution/client.js";
38
+ import { discoverCes } from "../credential-execution/executable-discovery.js";
43
39
  import { getAnyProviderEnvVar } from "../providers/provider-env-vars.js";
44
40
  import { getLogger } from "../util/logger.js";
45
41
  import { getProtectedDir } from "../util/platform.js";
@@ -82,13 +78,13 @@ let _resolvedBackend: CredentialBackend | undefined;
82
78
  let _resolvePromise: Promise<CredentialBackend> | undefined;
83
79
 
84
80
  /**
85
- * In-flight lazy CES connection promise for non-daemon processes.
81
+ * In-flight CES RPC session promise for processes that did not call startCes().
86
82
  *
87
- * Workers and CLI subprocesses inherit CES_LOCAL_SOCKET but never call
88
- * startCes(). When they hit resolveBackendAsync() with no _cesClient and
89
- * no _cesReconnect (daemon-only), this promise memoizes a direct CES
90
- * connection attempt so concurrent credential reads in the same process
91
- * share a single connect+handshake rather than racing.
83
+ * Workers and CLI subprocesses never call startCes(). When they hit
84
+ * resolveBackendAsync() with no _cesClient and no _cesReconnect
85
+ * (assistant-boot only), this promise memoizes `openCesRpcSession` so
86
+ * concurrent credential reads in the same process share a single
87
+ * connect+handshake rather than racing.
92
88
  */
93
89
  let _lazyConnectPromise: Promise<CesClient | undefined> | undefined;
94
90
 
@@ -203,14 +199,14 @@ function getEncryptedStoreBackend(): CredentialBackend {
203
199
  * Resolve the primary credential backend for this process (async).
204
200
  *
205
201
  * Priority:
206
- * 1. CES RPC client → primary path for all local modes.
207
- * 2. Containerized + CES_CREDENTIAL_URL → CES HTTP client (Docker/managed).
208
- * 3. Encrypted file store → fallback when CES is unavailable.
202
+ * 1. CES RPC: live client, or open one via `openCesRpcSession`.
203
+ * 2. Containerized + CES_CREDENTIAL_URL: CES HTTP, only if IPC is down.
204
+ * 3. Encrypted file store: local fallback when CES is unavailable.
209
205
  *
210
206
  * Once resolved, the backend is cached. If it becomes unavailable (e.g. the
211
207
  * CES transport dies), we attempt to reconnect via `_cesReconnect` rather
212
208
  * than falling back to a different backend. In managed cloud mode CES is the
213
- * primary credential source — falling back to the encrypted file store would
209
+ * primary credential source. Falling back to the encrypted file store would
214
210
  * silently serve stale or empty data.
215
211
  *
216
212
  * In managed mode, if the CES bootstrap RPC transport dies, we first fail
@@ -411,17 +407,19 @@ export async function attemptCesReconnection(
411
407
  }
412
408
 
413
409
  /**
414
- * Lazily connect to a CES sibling socket from a non-daemon process.
410
+ * Open a CES RPC session from a process that did not call startCes().
415
411
  *
416
- * Workers and CLI subprocesses inherit CES_LOCAL_SOCKET from the daemon's
417
- * environment but never call startCes(). This function establishes a direct
418
- * CES connection on first credential resolution, memoizing the in-flight
419
- * promise so concurrent callers share a single connect+handshake.
412
+ * Workers and CLI subprocesses never call startCes(). This function
413
+ * opens the same `openCesRpcSession` path the assistant uses at boot,
414
+ * memoizing the in-flight promise so concurrent callers share a single
415
+ * connect+handshake. Discovery uses the shared CES bootstrap socket; a
416
+ * missing socket fails immediately so callers can fall through without
417
+ * polling.
420
418
  *
421
419
  * On success, the client is injected via setCesClient() so subsequent
422
- * resolveBackendAsync() calls take the fast CES RPC path (step 1). A
423
- * reconnect callback is also registered so the lazy connection can heal
424
- * if the transport drops mid-process.
420
+ * resolveBackendAsync() calls take the live CES RPC path. A reconnect
421
+ * callback is also registered so the session can heal if the transport
422
+ * drops mid-process.
425
423
  *
426
424
  * Returns undefined on any failure (socket not found, handshake rejected,
427
425
  * timeout) so the caller falls through to the encrypted file store.
@@ -432,62 +430,30 @@ async function tryLazyCesConnect(): Promise<CesClient | undefined> {
432
430
  }
433
431
 
434
432
  _lazyConnectPromise = (async () => {
435
- try {
436
- const pm = createCesProcessManager({});
437
- const transport = await pm.start();
438
- const client = createCesClient(transport);
439
- const { accepted, reason } = await client.handshake();
440
- if (!accepted) {
441
- log.warn(
442
- { reason },
443
- "Lazy CES connection handshake rejected — falling back to encrypted file store",
444
- );
445
- client.close();
446
- await pm.stop().catch(() => {});
447
- return undefined;
448
- }
433
+ const discovery = discoverCes();
434
+ if (discovery.mode === "unavailable") {
449
435
  log.info(
450
- "Lazy CES connection established — credential operations routed through CES RPC",
436
+ { reason: discovery.reason },
437
+ "CES socket not reachable for lazy connect, falling back to encrypted file store",
451
438
  );
452
- setCesClient(client);
453
- // Register a reconnect callback so the lazy connection self-heals
454
- // if the transport drops, mirroring the daemon's proactive reconnect.
455
- setCesReconnect(async () => {
456
- try {
457
- await pm.stop();
458
- const newTransport = await pm.start();
459
- const newClient = createCesClient(newTransport);
460
- const { accepted: ok } = await newClient.handshake();
461
- if (ok) {
462
- log.info("Lazy CES reconnection successful");
463
- return newClient;
464
- }
465
- newClient.close();
466
- await pm.stop().catch(() => {});
467
- return undefined;
468
- } catch (err) {
469
- log.warn(
470
- { error: err instanceof Error ? err.message : String(err) },
471
- "Lazy CES reconnection failed",
472
- );
473
- return undefined;
474
- }
475
- });
476
- return client;
477
- } catch (err) {
478
- if (err instanceof CesUnavailableError) {
479
- log.info(
480
- { reason: err.message },
481
- "CES socket not reachable for lazy connect — falling back to encrypted file store",
482
- );
483
- } else {
484
- log.warn(
485
- { error: err instanceof Error ? err.message : String(err) },
486
- "Lazy CES connection failed — falling back to encrypted file store",
487
- );
488
- }
489
439
  return undefined;
490
440
  }
441
+ const session = await openCesRpcSession();
442
+ if (!session) {
443
+ return undefined;
444
+ }
445
+ log.info(
446
+ "CES RPC session established; credential operations route through CES RPC",
447
+ );
448
+ setCesClient(session.client);
449
+ setCesReconnect(async () => {
450
+ const client = await reconnectCesRpcSession(session.processManager);
451
+ if (client) {
452
+ log.info("CES RPC reconnection successful");
453
+ }
454
+ return client;
455
+ });
456
+ return session.client;
491
457
  })();
492
458
 
493
459
  try {
@@ -498,7 +464,10 @@ async function tryLazyCesConnect(): Promise<CesClient | undefined> {
498
464
  }
499
465
 
500
466
  async function doResolveBackend(): Promise<CredentialBackend> {
501
- // 1. CES RPC — primary credential backend for all local modes
467
+ // 1. CES RPC. Primary credential backend in every environment. Boot
468
+ // claims reconnect ownership before it reads handshake identity, so
469
+ // that read cannot open a second session. Children open here only
470
+ // when this process has no client and no reconnect owner.
502
471
  if (_cesClient) {
503
472
  const cesRpc = new CesRpcCredentialBackend(_cesClient);
504
473
  if (cesRpc.isAvailable()) {
@@ -511,7 +480,19 @@ async function doResolveBackend(): Promise<CredentialBackend> {
511
480
  );
512
481
  }
513
482
 
514
- // 2. CES HTTP — containerized / Docker / managed mode
483
+ if (!_cesClient && !_cesReconnect) {
484
+ const client = await tryLazyCesConnect();
485
+ if (client) {
486
+ const cesRpc = new CesRpcCredentialBackend(client);
487
+ if (cesRpc.isAvailable()) {
488
+ _resolvedBackend = cesRpc;
489
+ log.info("Resolved credential backend: ces-rpc");
490
+ return cesRpc;
491
+ }
492
+ }
493
+ }
494
+
495
+ // 2. CES HTTP. Managed failover when IPC is unavailable.
515
496
  if (getIsContainerized() && process.env.CES_CREDENTIAL_URL) {
516
497
  const ces = createCesCredentialBackend();
517
498
  if (ces.isAvailable()) {
@@ -525,25 +506,6 @@ async function doResolveBackend(): Promise<CredentialBackend> {
525
506
  );
526
507
  }
527
508
 
528
- // 2.5. Lazy CES RPC connect — non-daemon processes (workers, CLI
529
- // subprocesses) inherit CES_LOCAL_SOCKET but never call startCes().
530
- // When the daemon's setCesReconnect() is NOT registered, attempt a
531
- // direct connection to the CES sibling socket. On success, inject
532
- // the client via setCesClient() and re-resolve through the CES RPC
533
- // path. On failure, fall through to the encrypted file store.
534
- if (!_cesClient && !_cesReconnect && process.env.CES_LOCAL_SOCKET) {
535
- const lazyClient = await tryLazyCesConnect();
536
- if (lazyClient) {
537
- const cesRpc = new CesRpcCredentialBackend(lazyClient);
538
- if (cesRpc.isAvailable()) {
539
- _resolvedBackend = cesRpc;
540
- log.info("Resolved credential backend: ces-rpc (lazy connect)");
541
- return cesRpc;
542
- }
543
- }
544
- // Lazy connect failed; fall through.
545
- }
546
-
547
509
  // 3. On a containerized pod the local encrypted store does not exist and CES
548
510
  // owns credentials. Never resolve to the encrypted store here; it would
549
511
  // report a provisioned credential as absent. Return an unreachable backend
@@ -11,11 +11,6 @@ import {
11
11
 
12
12
  const log = getLogger("clawhub");
13
13
 
14
- // Managed skills directory — where installed skill folders live
15
- function getManagedSkillsDir(): string {
16
- return getWorkspaceSkillsDir();
17
- }
18
-
19
14
  // ClaWHub project root — clawhub creates a `skills/` subdir inside its cwd,
20
15
  // so we use the parent of the managed skills dir as the project root.
21
16
  function getClawhubProjectRoot(): string {
@@ -39,7 +34,7 @@ interface IntegrityRecord {
39
34
  type IntegrityManifest = Record<string, IntegrityRecord>;
40
35
 
41
36
  function getIntegrityPath(): string {
42
- return join(getManagedSkillsDir(), ".integrity.json");
37
+ return join(getWorkspaceSkillsDir(), ".integrity.json");
43
38
  }
44
39
 
45
40
  function loadIntegrityManifest(): IntegrityManifest {
@@ -66,7 +61,7 @@ function loadIntegrityManifest(): IntegrityManifest {
66
61
  * from skills that haven't been migrated yet.
67
62
  */
68
63
  export function verifyAndRecordSkillHash(slug: string): void {
69
- const skillDir = join(getManagedSkillsDir(), slug);
64
+ const skillDir = join(getWorkspaceSkillsDir(), slug);
70
65
  const hash = computeSkillHash(skillDir);
71
66
  if (!hash) {
72
67
  log.warn({ slug }, "Could not compute content hash for installed skill");
@@ -232,7 +227,7 @@ function getSkillNameFromSlug(slug: string): string {
232
227
  }
233
228
 
234
229
  function getClawhubSkillsDir(projectRoot?: string): string {
235
- return projectRoot ? join(projectRoot, "skills") : getManagedSkillsDir();
230
+ return projectRoot ? join(projectRoot, "skills") : getWorkspaceSkillsDir();
236
231
  }
237
232
 
238
233
  function hasRootSkillFile(skillDir: string): boolean {
@@ -44,13 +44,9 @@ export function validateManagedSkillId(id: string): string | null {
44
44
 
45
45
  // ─── Path helpers ────────────────────────────────────────────────────────────
46
46
 
47
- function getManagedSkillsDir(): string {
48
- return getWorkspaceSkillsDir();
49
- }
50
-
51
47
  /** Absolute path of a managed skill's directory (whether or not it exists). */
52
48
  export function getManagedSkillDir(id: string): string {
53
- return join(getManagedSkillsDir(), id);
49
+ return join(getWorkspaceSkillsDir(), id);
54
50
  }
55
51
 
56
52
  interface ResolvedCompanionPath {
package/src/stt/types.ts CHANGED
@@ -436,6 +436,10 @@ export interface SttStreamServerTurnEndEvent {
436
436
  * provider does not surface a score.
437
437
  */
438
438
  readonly confidence?: number;
439
+ /** Provider-reported cause of the turn boundary, when available. */
440
+ readonly trigger?: "model" | "manual" | "timeout";
441
+ /** End of the decoded audio window, in seconds from stream start. */
442
+ readonly audioWindowEndSeconds?: number;
439
443
  /**
440
444
  * Provider's index for the turn being closed, matching the
441
445
  * {@link SttStreamServerTurnStartEvent} that opened it. A consumer can
@@ -8,16 +8,20 @@
8
8
  * manager out of the import graph lets tool modules import these helpers without
9
9
  * pulling in the conversation/agent-loop core.
10
10
  *
11
- * Delivery targets the parent's in-process `Conversation` via the conversation
12
- * registry: a notification is injected only when the parent is live here. A
13
- * stale idle parent is rebuilt through `getOrCreateConversation` first so the
14
- * injected turn uses the current provider, prompt, and credentials.
11
+ * An active live-voice session owns delivery for its conversation. Otherwise,
12
+ * delivery targets the parent's in-process `Conversation` via the registry.
13
+ * A stale idle parent is rebuilt through `getOrCreateConversation` first so
14
+ * the injected turn uses the current provider, prompt, and credentials.
15
15
  */
16
16
 
17
+ import { getConfig } from "../config/loader.js";
18
+ import { resolveTurnCommitWaitMs } from "../daemon/abort-watchdog.js";
17
19
  import {
18
20
  findConversation,
19
21
  findConversationOrSubagent,
20
22
  } from "../daemon/conversation-registry.js";
23
+ import { startAfterTurnFinalization } from "../daemon/turn-finalization.js";
24
+ import { deliverSubagentNotificationToLiveVoice } from "../live-voice/live-voice-manager.js";
21
25
  import { getSubagentRecordByConversationId } from "../persistence/subagent-store.js";
22
26
  import { getLogger } from "../util/logger.js";
23
27
  import { type SubagentStatus, TERMINAL_STATUSES } from "./types.js";
@@ -25,9 +29,9 @@ import { type SubagentStatus, TERMINAL_STATUSES } from "./types.js";
25
29
  const log = getLogger("subagent-notify");
26
30
 
27
31
  /**
28
- * Enqueue (or persist + run) `message` as a user-role turn in the parent
29
- * conversation. No-op with a warning when the parent conversation is not live
30
- * in this process.
32
+ * Deliver task updates through the parent's live voice session when present,
33
+ * otherwise enqueue a parent turn. No-op with a warning
34
+ * when neither the session nor the parent conversation is live here.
31
35
  *
32
36
  * Shared by the child-triggered {@link notifyParentFromChild} and the
33
37
  * manager's terminal/abort injections so every subagent → parent turn lands
@@ -37,8 +41,30 @@ export function injectMessageIntoParent(
37
41
  parentConversationId: string,
38
42
  message: string,
39
43
  metadata?: Record<string, unknown>,
40
- opts?: { cronRunId?: string | null },
44
+ opts?: { cronRunId?: string | null; bypassLiveVoice?: boolean },
41
45
  ): void {
46
+ const notification = metadata?.subagentNotification;
47
+ // The live child's conversation ID is stable even if its cosmetic record changes.
48
+ if (
49
+ !opts?.bypassLiveVoice &&
50
+ notification !== null &&
51
+ typeof notification === "object" &&
52
+ "subagentId" in notification &&
53
+ typeof notification.subagentId === "string" &&
54
+ metadata !== undefined &&
55
+ deliverSubagentNotificationToLiveVoice(parentConversationId, {
56
+ taskId:
57
+ "conversationId" in notification &&
58
+ typeof notification.conversationId === "string"
59
+ ? notification.conversationId
60
+ : notification.subagentId,
61
+ message,
62
+ metadata,
63
+ cronRunId: opts?.cronRunId,
64
+ })
65
+ ) {
66
+ return;
67
+ }
42
68
  const existing = findConversation(parentConversationId);
43
69
  if (!existing) {
44
70
  log.warn(
@@ -76,17 +102,10 @@ function deliverToParent(
76
102
  content: string;
77
103
  metadata?: Record<string, unknown>;
78
104
  isInteractive: boolean;
105
+ queueWhenIdle: boolean;
79
106
  cronRunId?: string | null;
80
107
  }) => { queued: boolean; rejected?: boolean };
81
- persistUserMessage: (options: {
82
- content: string;
83
- metadata?: Record<string, unknown>;
84
- }) => Promise<{ id: string }>;
85
- runAgentLoop: (
86
- message: string,
87
- messageId: string,
88
- options: { isInteractive: boolean; cronRunId?: string | null },
89
- ) => Promise<unknown>;
108
+ kickDrainQueue: (reason: "loop_complete", origin: string) => Promise<void>;
90
109
  },
91
110
  parentConversationId: string,
92
111
  message: string,
@@ -95,33 +114,34 @@ function deliverToParent(
95
114
  ): void {
96
115
  // The continuation this notification starts is still the scheduled firing's
97
116
  // work, so it carries the same run id as the child whose result triggered it.
98
- // Both delivery paths need it: the queued one drains after the enqueuing turn
99
- // has ended, so the id has to travel on the message.
117
+ // The queue drains after the enqueuing turn, so the id travels on the message.
100
118
  const cronRunId = opts?.cronRunId ?? null;
101
119
  // Machine-injected with no human asserted present, so the notification
102
120
  // turn runs non-interactive; it still streams to whoever is watching
103
121
  // through the parent's sink.
104
122
  const enqueueResult = parentConversation.enqueueMessage({
105
123
  content: message,
106
- metadata,
124
+ metadata: { ...metadata, scripted: true },
107
125
  isInteractive: false,
126
+ queueWhenIdle: true,
108
127
  ...(cronRunId ? { cronRunId } : {}),
109
128
  });
110
- if (!enqueueResult.queued && !enqueueResult.rejected) {
111
- parentConversation
112
- .persistUserMessage({ content: message, metadata })
113
- .then(({ id: messageId }) =>
114
- parentConversation.runAgentLoop(message, messageId, {
115
- isInteractive: false,
116
- ...(cronRunId ? { cronRunId } : {}),
117
- }),
118
- )
119
- .catch((err) => {
120
- log.error(
121
- { parentConversationId, err },
122
- "Failed to process subagent notification in parent",
129
+ if (enqueueResult.queued) {
130
+ startAfterTurnFinalization(
131
+ parentConversationId,
132
+ resolveTurnCommitWaitMs(getConfig().workspaceGit?.turnCommitMaxWaitMs),
133
+ () => {
134
+ void parentConversation.kickDrainQueue(
135
+ "loop_complete",
136
+ "subagent_notification",
123
137
  );
124
- });
138
+ },
139
+ );
140
+ } else {
141
+ log.error(
142
+ { parentConversationId },
143
+ "Parent queue rejected subagent notification",
144
+ );
125
145
  }
126
146
  }
127
147
 
@@ -0,0 +1,6 @@
1
+ export interface SubagentParentNotification {
2
+ taskId: string;
3
+ message: string;
4
+ metadata: Record<string, unknown>;
5
+ cronRunId?: string | null;
6
+ }