@vellumai/assistant 0.7.1 → 0.7.3

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 (739) hide show
  1. package/ARCHITECTURE.md +48 -50
  2. package/Dockerfile +1 -0
  3. package/README.md +1 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +9 -3
  5. package/bun.lock +26 -26
  6. package/docs/architecture/memory.md +5 -2
  7. package/docs/architecture/security.md +20 -0
  8. package/docs/plugins.md +7 -9
  9. package/knip.json +1 -0
  10. package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
  11. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +52 -5
  12. package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
  13. package/node_modules/@vellumai/service-contracts/package.json +2 -0
  14. package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
  15. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
  16. package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
  17. package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
  18. package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
  19. package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
  20. package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
  21. package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
  22. package/node_modules/@vellumai/twilio-client/package.json +18 -0
  23. package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
  24. package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
  25. package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
  26. package/openapi.yaml +1020 -40
  27. package/package.json +6 -3
  28. package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
  29. package/src/__tests__/app-bundler.test.ts +170 -1
  30. package/src/__tests__/app-control-flow.test.ts +384 -0
  31. package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
  32. package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
  33. package/src/__tests__/app-executors.test.ts +30 -43
  34. package/src/__tests__/approval-routes-http.test.ts +23 -6
  35. package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
  36. package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
  37. package/src/__tests__/assistant-event-hub.test.ts +157 -2
  38. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -7
  39. package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
  40. package/src/__tests__/background-shell-host-bash.test.ts +14 -15
  41. package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
  42. package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
  43. package/src/__tests__/btw-routes.test.ts +13 -4
  44. package/src/__tests__/call-controller.test.ts +49 -1
  45. package/src/__tests__/call-conversation-messages.test.ts +8 -2
  46. package/src/__tests__/call-domain.test.ts +0 -2
  47. package/src/__tests__/call-routes-http.test.ts +0 -2
  48. package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
  49. package/src/__tests__/channel-readiness-service.test.ts +62 -2
  50. package/src/__tests__/checker.test.ts +3 -4
  51. package/src/__tests__/config-loader-backfill.test.ts +461 -147
  52. package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
  53. package/src/__tests__/config-schema-cmd.test.ts +0 -1
  54. package/src/__tests__/config-schema.test.ts +1 -0
  55. package/src/__tests__/config-set-platform-guard.test.ts +48 -4
  56. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +20 -11
  57. package/src/__tests__/config-watcher.test.ts +142 -71
  58. package/src/__tests__/context-search-agent-runner.test.ts +61 -3
  59. package/src/__tests__/context-search-conversations-source.test.ts +0 -24
  60. package/src/__tests__/context-search-fanout.test.ts +0 -1
  61. package/src/__tests__/context-search-memory-source.test.ts +3 -7
  62. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
  63. package/src/__tests__/context-search-pkb-source.test.ts +0 -1
  64. package/src/__tests__/context-search-workspace-source.test.ts +0 -1
  65. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  66. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
  67. package/src/__tests__/conversation-agent-loop.test.ts +454 -5
  68. package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
  69. package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
  70. package/src/__tests__/conversation-error.test.ts +150 -3
  71. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  72. package/src/__tests__/conversation-lifecycle.test.ts +36 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
  74. package/src/__tests__/conversation-process-callsite.test.ts +43 -0
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  76. package/src/__tests__/conversation-routes-disk-view.test.ts +6 -0
  77. package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -72
  78. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  79. package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
  80. package/src/__tests__/conversation-slash-commands.test.ts +0 -4
  81. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  82. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  83. package/src/__tests__/conversation-store.test.ts +0 -18
  84. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
  85. package/src/__tests__/conversation-surfaces-app-control.test.ts +328 -0
  86. package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
  87. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
  88. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  89. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  90. package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
  91. package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
  92. package/src/__tests__/credentials-cli.test.ts +12 -12
  93. package/src/__tests__/cu-unified-flow.test.ts +351 -23
  94. package/src/__tests__/daemon-credential-client.test.ts +101 -19
  95. package/src/__tests__/date-context.test.ts +164 -2
  96. package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
  97. package/src/__tests__/disk-pressure-guard.test.ts +262 -0
  98. package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
  99. package/src/__tests__/disk-pressure-policy.test.ts +241 -0
  100. package/src/__tests__/disk-pressure-routes.test.ts +379 -0
  101. package/src/__tests__/disk-pressure-tools.test.ts +277 -0
  102. package/src/__tests__/disk-usage.test.ts +150 -0
  103. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  104. package/src/__tests__/events-client-registration.test.ts +52 -0
  105. package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
  106. package/src/__tests__/file-write-tool.test.ts +4 -10
  107. package/src/__tests__/filing-service.test.ts +3 -4
  108. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  109. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
  110. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -2
  111. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -1
  112. package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
  113. package/src/__tests__/heartbeat-service.test.ts +968 -2
  114. package/src/__tests__/helpers/call-route-handler.ts +7 -1
  115. package/src/__tests__/host-app-control-proxy.test.ts +772 -0
  116. package/src/__tests__/host-app-control-routes.test.ts +263 -0
  117. package/src/__tests__/host-bash-proxy.test.ts +439 -47
  118. package/src/__tests__/host-bash-routes.test.ts +459 -0
  119. package/src/__tests__/host-browser-proxy.test.ts +24 -22
  120. package/src/__tests__/host-browser-routes.test.ts +39 -13
  121. package/src/__tests__/host-cu-proxy.test.ts +248 -52
  122. package/src/__tests__/host-cu-routes-targeted.test.ts +429 -0
  123. package/src/__tests__/host-file-edit-tool.test.ts +47 -1
  124. package/src/__tests__/host-file-proxy-targeted.test.ts +378 -0
  125. package/src/__tests__/host-file-proxy.test.ts +301 -45
  126. package/src/__tests__/host-file-read-tool.test.ts +17 -0
  127. package/src/__tests__/host-file-routes-targeted.test.ts +420 -0
  128. package/src/__tests__/host-file-write-tool.test.ts +42 -1
  129. package/src/__tests__/host-proxy-base.test.ts +312 -0
  130. package/src/__tests__/host-shell-tool.test.ts +22 -4
  131. package/src/__tests__/host-transfer-proxy-targeted.test.ts +932 -0
  132. package/src/__tests__/host-transfer-proxy.test.ts +121 -22
  133. package/src/__tests__/host-transfer-routes-targeted.test.ts +662 -0
  134. package/src/__tests__/http-user-message-parity.test.ts +108 -1
  135. package/src/__tests__/identity-intro-cache.test.ts +29 -0
  136. package/src/__tests__/identity-routes.test.ts +103 -1
  137. package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
  138. package/src/__tests__/injector-chain.test.ts +18 -6
  139. package/src/__tests__/injector-disk-pressure.test.ts +224 -0
  140. package/src/__tests__/inline-command-runner.test.ts +0 -1
  141. package/src/__tests__/inline-skill-load-permissions.test.ts +5 -11
  142. package/src/__tests__/integration-status.test.ts +85 -5
  143. package/src/__tests__/intent-routing.test.ts +0 -1
  144. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
  145. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
  146. package/src/__tests__/managed-profile-guard.test.ts +18 -0
  147. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
  148. package/src/__tests__/mcp-abort-signal.test.ts +130 -0
  149. package/src/__tests__/mcp-auth-routes.test.ts +197 -0
  150. package/src/__tests__/mcp-cli.test.ts +338 -2
  151. package/src/__tests__/memory-admin-recall.test.ts +3 -11
  152. package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
  153. package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
  154. package/src/__tests__/migration-import-commit-http.test.ts +108 -2
  155. package/src/__tests__/mock-gateway-ipc.ts +1 -0
  156. package/src/__tests__/normalize-onboarding.test.ts +180 -0
  157. package/src/__tests__/oauth-cli.test.ts +0 -2
  158. package/src/__tests__/oauth-connect-routes.test.ts +316 -0
  159. package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
  160. package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
  161. package/src/__tests__/onboarding-persona-write.test.ts +308 -0
  162. package/src/__tests__/openai-provider.test.ts +45 -8
  163. package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
  164. package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
  165. package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
  166. package/src/__tests__/platform-callback-registration.test.ts +21 -4
  167. package/src/__tests__/platform.test.ts +2 -1
  168. package/src/__tests__/playbook-execution.test.ts +0 -43
  169. package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
  170. package/src/__tests__/prechat-onboarding-contract.test.ts +214 -25
  171. package/src/__tests__/process-message-background-slack.test.ts +2 -0
  172. package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
  173. package/src/__tests__/provider-tool-name.test.ts +23 -0
  174. package/src/__tests__/public-ingress-urls.test.ts +97 -0
  175. package/src/__tests__/relay-server.test.ts +15 -4
  176. package/src/__tests__/require-fresh-approval.test.ts +0 -1
  177. package/src/__tests__/retry-backoff.test.ts +87 -0
  178. package/src/__tests__/runtime-events-sse.test.ts +2 -2
  179. package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
  180. package/src/__tests__/schedule-retry.test.ts +715 -0
  181. package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
  182. package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
  183. package/src/__tests__/secret-ingress-http.test.ts +1 -1
  184. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  185. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
  186. package/src/__tests__/skill-feature-flags.test.ts +43 -41
  187. package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
  188. package/src/__tests__/skill-load-inline-command.test.ts +0 -51
  189. package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
  190. package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
  191. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
  192. package/src/__tests__/slack-channel-config.test.ts +9 -14
  193. package/src/__tests__/suggestion-routes.test.ts +46 -0
  194. package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
  195. package/src/__tests__/system-prompt.test.ts +0 -1
  196. package/src/__tests__/telegram-config.test.ts +0 -1
  197. package/src/__tests__/test-preload.ts +8 -0
  198. package/src/__tests__/tool-approval-handler.test.ts +3 -4
  199. package/src/__tests__/tool-audit-listener.test.ts +48 -0
  200. package/src/__tests__/tool-execute-pipeline.test.ts +0 -1
  201. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
  202. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  203. package/src/__tests__/tool-executor.test.ts +0 -1
  204. package/src/__tests__/twilio-config.test.ts +3 -16
  205. package/src/__tests__/twilio-routes.test.ts +3 -5
  206. package/src/__tests__/twilio-validation.test.ts +93 -0
  207. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -4
  208. package/src/__tests__/verification-control-plane-policy.test.ts +2 -4
  209. package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
  210. package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
  211. package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
  212. package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
  213. package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
  214. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
  215. package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
  216. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
  217. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
  218. package/src/approvals/guardian-decision-primitive.ts +13 -0
  219. package/src/approvals/guardian-request-resolvers.ts +16 -17
  220. package/src/backup/__tests__/paths.test.ts +0 -22
  221. package/src/backup/__tests__/restore.test.ts +51 -151
  222. package/src/backup/paths.ts +2 -18
  223. package/src/backup/restore.ts +107 -231
  224. package/src/backup/snapshot-lock.ts +2 -27
  225. package/src/bundler/app-bundler.ts +51 -3
  226. package/src/bundler/compiler-tools.ts +3 -2
  227. package/src/calls/call-conversation-messages.ts +46 -10
  228. package/src/calls/relay-server.ts +4 -44
  229. package/src/calls/twilio-config.ts +2 -17
  230. package/src/calls/twilio-rest.ts +33 -105
  231. package/src/calls/twilio-routes.ts +11 -12
  232. package/src/channels/types.ts +8 -7
  233. package/src/cli/commands/__tests__/backup.test.ts +6 -277
  234. package/src/cli/commands/__tests__/gateway.test.ts +288 -0
  235. package/src/cli/commands/__tests__/memory-v2.test.ts +4 -0
  236. package/src/cli/commands/__tests__/webhooks.test.ts +0 -5
  237. package/src/cli/commands/backup.ts +6 -331
  238. package/src/cli/commands/bash.ts +35 -108
  239. package/src/cli/commands/clients.ts +36 -37
  240. package/src/cli/commands/contacts.ts +137 -25
  241. package/src/cli/commands/conversations.ts +2 -5
  242. package/src/cli/commands/credentials.ts +71 -7
  243. package/src/cli/commands/domain.ts +66 -15
  244. package/src/cli/commands/gateway.ts +183 -0
  245. package/src/cli/commands/keys.ts +9 -6
  246. package/src/cli/commands/mcp.ts +116 -156
  247. package/src/cli/commands/memory-v2.ts +303 -7
  248. package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
  249. package/src/cli/commands/oauth/connect.ts +127 -1
  250. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -4
  251. package/src/cli/commands/platform/__tests__/connect.test.ts +7 -3
  252. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -3
  253. package/src/cli/commands/platform/__tests__/status.test.ts +116 -21
  254. package/src/cli/commands/platform/disconnect.ts +5 -4
  255. package/src/cli/commands/platform/index.ts +16 -25
  256. package/src/cli/commands/status.ts +57 -0
  257. package/src/cli/lib/daemon-credential-client.ts +110 -28
  258. package/src/cli/program.ts +6 -2
  259. package/src/config/assistant-feature-flags.ts +79 -12
  260. package/src/config/bundled-skills/acp/SKILL.md +6 -0
  261. package/src/config/bundled-skills/acp/TOOLS.json +1 -22
  262. package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
  263. package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
  264. package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
  265. package/src/config/bundled-skills/app-control/SKILL.md +75 -0
  266. package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
  267. package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
  268. package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
  269. package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
  270. package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
  271. package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
  272. package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
  273. package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
  274. package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
  275. package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
  276. package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
  277. package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
  278. package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
  279. package/src/config/bundled-skills/document/TOOLS.json +0 -8
  280. package/src/config/bundled-skills/followups/TOOLS.json +0 -12
  281. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  282. package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
  283. package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
  284. package/src/config/bundled-skills/messaging/TOOLS.json +0 -40
  285. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
  286. package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
  287. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +25 -4
  288. package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
  289. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
  290. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
  291. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
  292. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
  293. package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
  294. package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
  295. package/src/config/bundled-skills/settings/SKILL.md +4 -0
  296. package/src/config/bundled-skills/settings/TOOLS.json +0 -12
  297. package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
  298. package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
  299. package/src/config/bundled-skills/subagent/SKILL.md +6 -2
  300. package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
  301. package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
  302. package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
  303. package/src/config/bundled-tool-registry.ts +21 -0
  304. package/src/config/env-registry.ts +0 -2
  305. package/src/config/env.ts +19 -20
  306. package/src/config/feature-flag-registry.json +47 -135
  307. package/src/config/loader.ts +197 -104
  308. package/src/config/sanitize-for-transfer.ts +2 -0
  309. package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
  310. package/src/config/schemas/__tests__/memory-v2.test.ts +17 -9
  311. package/src/config/schemas/call-site-catalog.ts +14 -0
  312. package/src/config/schemas/calls.ts +0 -9
  313. package/src/config/schemas/channels.ts +0 -5
  314. package/src/config/schemas/heartbeat.ts +64 -1
  315. package/src/config/schemas/ingress.ts +10 -6
  316. package/src/config/schemas/llm.ts +7 -10
  317. package/src/config/schemas/memory-lifecycle.ts +90 -24
  318. package/src/config/schemas/memory-v2.ts +121 -13
  319. package/src/config/schemas/platform.ts +49 -3
  320. package/src/config/schemas/services.ts +29 -15
  321. package/src/config/schemas/skills.ts +0 -6
  322. package/src/config/seed-inference-profiles.ts +230 -33
  323. package/src/contacts/contact-store.ts +0 -55
  324. package/src/contacts/contacts-write.ts +0 -27
  325. package/src/context/window-manager.ts +1 -2
  326. package/src/credential-execution/feature-gates.ts +10 -10
  327. package/src/credential-execution/process-manager.ts +12 -41
  328. package/src/daemon/__tests__/conversation-tool-setup.test.ts +187 -5
  329. package/src/daemon/assistant-attachments.ts +4 -4
  330. package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
  331. package/src/daemon/config-watcher.ts +89 -60
  332. package/src/daemon/conversation-agent-loop-handlers.ts +27 -3
  333. package/src/daemon/conversation-agent-loop.ts +202 -61
  334. package/src/daemon/conversation-error.ts +87 -15
  335. package/src/daemon/conversation-lifecycle.ts +9 -4
  336. package/src/daemon/conversation-process.ts +24 -11
  337. package/src/daemon/conversation-runtime-assembly.ts +28 -2
  338. package/src/daemon/conversation-store.ts +2 -2
  339. package/src/daemon/conversation-surfaces.ts +305 -4
  340. package/src/daemon/conversation-tool-setup.ts +66 -62
  341. package/src/daemon/conversation.ts +38 -24
  342. package/src/daemon/date-context.ts +71 -22
  343. package/src/daemon/disk-pressure-background-gate.ts +73 -0
  344. package/src/daemon/disk-pressure-guard.ts +343 -0
  345. package/src/daemon/disk-pressure-policy.ts +163 -0
  346. package/src/daemon/doordash-steps.ts +1 -1
  347. package/src/daemon/handlers/shared.ts +4 -2
  348. package/src/daemon/handlers/skills.ts +3 -4
  349. package/src/daemon/host-app-control-proxy.ts +389 -0
  350. package/src/daemon/host-bash-proxy.ts +117 -82
  351. package/src/daemon/host-browser-proxy.ts +67 -82
  352. package/src/daemon/host-cu-proxy.ts +127 -86
  353. package/src/daemon/host-file-proxy.ts +129 -69
  354. package/src/daemon/host-proxy-base.ts +294 -0
  355. package/src/daemon/host-proxy-preactivation.ts +82 -0
  356. package/src/daemon/host-transfer-proxy.ts +338 -129
  357. package/src/daemon/lifecycle.ts +194 -145
  358. package/src/daemon/meet-host-supervisor.ts +4 -4
  359. package/src/daemon/meet-manifest-loader.ts +0 -1
  360. package/src/daemon/memory-v2-startup.ts +14 -4
  361. package/src/daemon/message-protocol.ts +6 -8
  362. package/src/daemon/message-types/contacts.ts +23 -1
  363. package/src/daemon/message-types/conversations.ts +15 -8
  364. package/src/daemon/message-types/disk-pressure.ts +9 -0
  365. package/src/daemon/message-types/host-app-control.ts +150 -0
  366. package/src/daemon/message-types/host-bash.ts +4 -0
  367. package/src/daemon/message-types/host-cu.ts +2 -0
  368. package/src/daemon/message-types/host-file.ts +4 -0
  369. package/src/daemon/message-types/host-transfer.ts +3 -0
  370. package/src/daemon/message-types/messages.ts +3 -0
  371. package/src/daemon/message-types/schedules.ts +8 -3
  372. package/src/daemon/message-types/skills.ts +2 -2
  373. package/src/daemon/process-message.ts +18 -1
  374. package/src/daemon/profiler-run-store.ts +5 -5
  375. package/src/daemon/shutdown-handlers.ts +0 -3
  376. package/src/daemon/tool-setup-types.ts +51 -0
  377. package/src/daemon/tool-side-effects.ts +1 -1
  378. package/src/documents/document-store.ts +85 -0
  379. package/src/events/tool-audit-listener.ts +2 -1
  380. package/src/filing/filing-service.ts +30 -5
  381. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +24 -23
  382. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +252 -0
  383. package/src/heartbeat/heartbeat-run-store.ts +249 -0
  384. package/src/heartbeat/heartbeat-service.ts +459 -54
  385. package/src/home/__tests__/post-connect-feed.test.ts +99 -0
  386. package/src/home/__tests__/relationship-state-writer.test.ts +11 -9
  387. package/src/home/__tests__/suggested-prompts.test.ts +89 -0
  388. package/src/home/feed-scheduler.ts +18 -0
  389. package/src/home/post-connect-feed.ts +68 -0
  390. package/src/home/relationship-state-writer.ts +17 -92
  391. package/src/home/suggested-prompts.ts +46 -10
  392. package/src/inbound/platform-callback-registration.ts +8 -15
  393. package/src/inbound/public-ingress-urls.ts +32 -34
  394. package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
  395. package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
  396. package/src/ipc/assistant-server.ts +70 -3
  397. package/src/ipc/cli-client.ts +32 -1
  398. package/src/ipc/gateway-client.ts +37 -3
  399. package/src/live-voice/live-voice-archive.ts +4 -4
  400. package/src/live-voice/live-voice-metrics.ts +10 -10
  401. package/src/live-voice/protocol.ts +5 -7
  402. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
  403. package/src/mcp/mcp-auth-orchestrator.ts +213 -0
  404. package/src/mcp/mcp-auth-state.ts +133 -0
  405. package/src/mcp/mcp-oauth-provider.ts +19 -0
  406. package/src/media/image-service.ts +1 -7
  407. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
  408. package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
  409. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
  412. package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
  413. package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
  414. package/src/memory/admin.ts +5 -9
  415. package/src/memory/anisotropy.test.ts +247 -0
  416. package/src/memory/anisotropy.ts +443 -0
  417. package/src/memory/auto-analysis-constants.ts +17 -0
  418. package/src/memory/auto-analysis-guard.ts +5 -15
  419. package/src/memory/canonical-guardian-store.ts +7 -7
  420. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
  421. package/src/memory/context-search/agent-protocol.ts +6 -6
  422. package/src/memory/context-search/agent-runner.ts +51 -9
  423. package/src/memory/context-search/sources/conversations.ts +2 -11
  424. package/src/memory/context-search/sources/memory-v2.ts +22 -9
  425. package/src/memory/context-search/sources/memory.ts +0 -1
  426. package/src/memory/context-search/types.ts +0 -1
  427. package/src/memory/conversation-crud.ts +5 -13
  428. package/src/memory/conversation-key-store.ts +2 -15
  429. package/src/memory/db-init.ts +6 -0
  430. package/src/memory/embedding-backend.ts +9 -21
  431. package/src/memory/embedding-runtime-manager.ts +119 -5
  432. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +81 -25
  433. package/src/memory/graph/conversation-graph-memory.ts +43 -78
  434. package/src/memory/graph/extraction.ts +1 -3
  435. package/src/memory/graph/graph-search.test.ts +10 -67
  436. package/src/memory/graph/graph-search.ts +9 -20
  437. package/src/memory/graph/retriever.test.ts +6 -0
  438. package/src/memory/graph/retriever.ts +34 -10
  439. package/src/memory/graph/tools.ts +1 -1
  440. package/src/memory/indexer.ts +54 -45
  441. package/src/memory/job-handlers/backfill.ts +2 -11
  442. package/src/memory/job-handlers/cleanup.ts +43 -0
  443. package/src/memory/job-handlers/embedding.ts +6 -8
  444. package/src/memory/job-handlers/summarization.ts +2 -7
  445. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
  446. package/src/memory/jobs/embed-concept-page.ts +28 -2
  447. package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
  448. package/src/memory/jobs-store.ts +114 -22
  449. package/src/memory/jobs-worker.ts +193 -106
  450. package/src/memory/memory-v2-activation-log-store.ts +33 -15
  451. package/src/memory/memory-v2-concept-frequency.ts +169 -0
  452. package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
  453. package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
  454. package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
  455. package/src/memory/migrations/index.ts +6 -0
  456. package/src/memory/migrations/registry.ts +8 -0
  457. package/src/memory/pkb/pkb-search.test.ts +6 -0
  458. package/src/memory/pkb/pkb-search.ts +7 -0
  459. package/src/memory/qdrant-client.ts +49 -32
  460. package/src/memory/rerank-local.ts +374 -0
  461. package/src/memory/schema/infrastructure.ts +15 -0
  462. package/src/memory/search/semantic.ts +13 -67
  463. package/src/memory/sparse-tokenize.ts +49 -0
  464. package/src/memory/trace-event-store.ts +1 -17
  465. package/src/memory/v2/__tests__/activation.test.ts +387 -344
  466. package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
  467. package/src/memory/v2/__tests__/injection.test.ts +181 -169
  468. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
  469. package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
  470. package/src/memory/v2/__tests__/reranker.test.ts +338 -0
  471. package/src/memory/v2/__tests__/sim.test.ts +154 -188
  472. package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
  473. package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
  474. package/src/memory/v2/__tests__/static-context.test.ts +76 -2
  475. package/src/memory/v2/activation.ts +213 -239
  476. package/src/memory/v2/consolidation-job.ts +65 -17
  477. package/src/memory/v2/constants.ts +7 -0
  478. package/src/memory/v2/injection.ts +123 -103
  479. package/src/memory/v2/prompts/consolidation.ts +348 -92
  480. package/src/memory/v2/qdrant.ts +198 -1
  481. package/src/memory/v2/reranker.ts +177 -0
  482. package/src/memory/v2/sim.ts +113 -77
  483. package/src/memory/v2/skill-content.ts +4 -3
  484. package/src/memory/v2/skill-store.ts +91 -53
  485. package/src/memory/v2/sparse-bm25.ts +245 -0
  486. package/src/memory/v2/static-context.ts +28 -5
  487. package/src/memory/v2/types.ts +10 -10
  488. package/src/messaging/providers/gmail/types.ts +0 -49
  489. package/src/messaging/providers/slack/adapter.ts +1 -31
  490. package/src/messaging/providers/slack/types.ts +0 -32
  491. package/src/notifications/README.md +10 -10
  492. package/src/notifications/broadcaster.ts +1 -1
  493. package/src/notifications/copy-composer.ts +13 -0
  494. package/src/notifications/guardian-question-mode.ts +5 -5
  495. package/src/notifications/signal.ts +4 -0
  496. package/src/oauth/AGENTS.md +3 -1
  497. package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
  498. package/src/oauth/connect-orchestrator.ts +6 -0
  499. package/src/oauth/connection-resolver.test.ts +66 -1
  500. package/src/oauth/connection-resolver.ts +55 -1
  501. package/src/oauth/credential-token-resolver.ts +1 -3
  502. package/src/oauth/manual-token-connection.ts +0 -4
  503. package/src/oauth/oauth-connect-state.ts +77 -0
  504. package/src/oauth/seed-providers.ts +58 -1
  505. package/src/outbound-proxy/index.ts +1 -37
  506. package/src/outbound-proxy/logging.ts +1 -1
  507. package/src/outbound-proxy/policy.ts +6 -5
  508. package/src/outbound-proxy/router.ts +2 -1
  509. package/src/permissions/approval-policy.test.ts +6 -275
  510. package/src/permissions/approval-policy.ts +0 -51
  511. package/src/permissions/checker.test.ts +0 -1
  512. package/src/permissions/checker.ts +3 -17
  513. package/src/permissions/gateway-threshold-reader.ts +2 -0
  514. package/src/permissions/prompter.ts +34 -1
  515. package/src/permissions/secret-prompter.ts +6 -2
  516. package/src/plugins/defaults/injectors.ts +35 -2
  517. package/src/plugins/defaults/memory-retrieval.ts +5 -6
  518. package/src/plugins/types.ts +7 -0
  519. package/src/proactive-artifact/aux-message-injector.ts +74 -0
  520. package/src/proactive-artifact/decision.test.ts +226 -0
  521. package/src/proactive-artifact/decision.ts +165 -0
  522. package/src/proactive-artifact/index.ts +7 -0
  523. package/src/proactive-artifact/job.test.ts +867 -0
  524. package/src/proactive-artifact/job.ts +352 -0
  525. package/src/proactive-artifact/message-copy.ts +41 -0
  526. package/src/proactive-artifact/trigger-state.test.ts +277 -0
  527. package/src/proactive-artifact/trigger-state.ts +119 -0
  528. package/src/prompts/bootstrap-cleanup.ts +27 -0
  529. package/src/prompts/normalize-onboarding.ts +80 -0
  530. package/src/prompts/persona-resolver.ts +101 -9
  531. package/src/prompts/system-prompt.ts +23 -24
  532. package/src/prompts/templates/BOOTSTRAP.md +13 -5
  533. package/src/prompts/templates/SOUL.md +13 -1
  534. package/src/providers/__tests__/retry-callsite.test.ts +222 -1
  535. package/src/providers/model-intents.ts +7 -0
  536. package/src/providers/openrouter/client.ts +8 -0
  537. package/src/providers/retry.ts +50 -0
  538. package/src/providers/speech-to-text/provider-catalog.ts +7 -8
  539. package/src/providers/types.ts +1 -0
  540. package/src/runtime/__tests__/agent-wake.test.ts +456 -3
  541. package/src/runtime/agent-wake.ts +238 -100
  542. package/src/runtime/assistant-event-hub.ts +151 -99
  543. package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
  544. package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
  545. package/src/runtime/auth/middleware.ts +0 -96
  546. package/src/runtime/auth/route-policy.ts +32 -0
  547. package/src/runtime/auth/same-actor.ts +216 -0
  548. package/src/runtime/btw-sidechain.ts +2 -3
  549. package/src/runtime/channel-invite-transport.ts +2 -48
  550. package/src/runtime/channel-invite-transports/email.ts +1 -1
  551. package/src/runtime/channel-invite-transports/slack.ts +1 -1
  552. package/src/runtime/channel-invite-transports/telegram.ts +1 -1
  553. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  554. package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
  555. package/src/runtime/channel-invite-types.ts +54 -0
  556. package/src/runtime/channel-readiness-service.ts +32 -13
  557. package/src/runtime/channel-retry-sweep.ts +65 -1
  558. package/src/runtime/guardian-reply-router.ts +10 -0
  559. package/src/runtime/http-server.ts +3 -329
  560. package/src/runtime/http-types.ts +0 -5
  561. package/src/runtime/local-actor-identity.ts +52 -11
  562. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
  563. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
  564. package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
  565. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +153 -1
  566. package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
  567. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
  568. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
  569. package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
  570. package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
  571. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +51 -1
  572. package/src/runtime/migrations/migration-transport.ts +7 -7
  573. package/src/runtime/migrations/vbundle-builder.ts +327 -60
  574. package/src/runtime/migrations/vbundle-import-analyzer.ts +4 -4
  575. package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
  576. package/src/runtime/migrations/vbundle-importer.ts +245 -68
  577. package/src/runtime/migrations/vbundle-streaming-importer.ts +326 -35
  578. package/src/runtime/migrations/vbundle-streaming-validator.ts +157 -4
  579. package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
  580. package/src/runtime/migrations/vbundle-validator.ts +114 -0
  581. package/src/runtime/pending-interactions.ts +43 -9
  582. package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
  583. package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
  584. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -5
  585. package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
  586. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
  587. package/src/runtime/routes/approval-interception-types.ts +13 -0
  588. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
  589. package/src/runtime/routes/backup-routes.ts +15 -38
  590. package/src/runtime/routes/btw-routes.ts +14 -37
  591. package/src/runtime/routes/client-routes.ts +21 -2
  592. package/src/runtime/routes/contact-prompt-routes.ts +183 -0
  593. package/src/runtime/routes/contact-routes.ts +0 -25
  594. package/src/runtime/routes/conversation-query-routes.ts +36 -1
  595. package/src/runtime/routes/conversation-routes.ts +65 -39
  596. package/src/runtime/routes/debug-bash-routes.ts +163 -0
  597. package/src/runtime/routes/disk-pressure-routes.ts +121 -0
  598. package/src/runtime/routes/document-pdf-renderer.ts +169 -0
  599. package/src/runtime/routes/documents-routes.ts +32 -75
  600. package/src/runtime/routes/errors.ts +19 -4
  601. package/src/runtime/routes/events-routes.ts +38 -0
  602. package/src/runtime/routes/gateway-log-routes.ts +79 -0
  603. package/src/runtime/routes/guardian-approval-interception.ts +2 -8
  604. package/src/runtime/routes/heartbeat-routes.ts +103 -38
  605. package/src/runtime/routes/host-app-control-routes.ts +134 -0
  606. package/src/runtime/routes/host-bash-routes.ts +56 -6
  607. package/src/runtime/routes/host-browser-routes.ts +108 -13
  608. package/src/runtime/routes/host-cu-routes.ts +66 -9
  609. package/src/runtime/routes/host-file-routes.ts +54 -5
  610. package/src/runtime/routes/host-transfer-routes.ts +122 -19
  611. package/src/runtime/routes/http-adapter.ts +1 -0
  612. package/src/runtime/routes/identity-intro-cache.ts +30 -0
  613. package/src/runtime/routes/identity-routes.ts +21 -180
  614. package/src/runtime/routes/inbound-message-handler.ts +78 -21
  615. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -7
  616. package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
  617. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
  618. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
  619. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
  620. package/src/runtime/routes/index.ts +14 -0
  621. package/src/runtime/routes/mcp-auth-routes.ts +132 -0
  622. package/src/runtime/routes/memory-item-routes.test.ts +41 -15
  623. package/src/runtime/routes/memory-item-routes.ts +10 -12
  624. package/src/runtime/routes/memory-v2-routes.ts +474 -1
  625. package/src/runtime/routes/migration-routes.ts +96 -0
  626. package/src/runtime/routes/oauth-connect-routes.ts +153 -0
  627. package/src/runtime/routes/schedule-routes.ts +7 -0
  628. package/src/runtime/verification-outbound-actions.ts +4 -4
  629. package/src/runtime/verification-templates.ts +4 -7
  630. package/src/schedule/integration-status.ts +66 -2
  631. package/src/schedule/recurrence-engine.ts +4 -1
  632. package/src/schedule/retry-backoff.ts +18 -0
  633. package/src/schedule/retry-policy.ts +82 -0
  634. package/src/schedule/run-script.ts +37 -5
  635. package/src/schedule/schedule-recovery.ts +64 -0
  636. package/src/schedule/schedule-store.ts +106 -2
  637. package/src/schedule/scheduler-types.ts +25 -0
  638. package/src/schedule/scheduler.ts +83 -39
  639. package/src/security/encrypted-store.ts +2 -0
  640. package/src/security/oauth-callback-registry.ts +8 -0
  641. package/src/security/secure-keys.ts +55 -0
  642. package/src/sequence/analytics.ts +5 -5
  643. package/src/sequence/engine.ts +1 -1
  644. package/src/skills/catalog-files.ts +2 -8
  645. package/src/skills/include-graph.ts +5 -5
  646. package/src/skills/remote-skill-policy.ts +10 -16
  647. package/src/skills/skill-file-provider.ts +1 -1
  648. package/src/skills/skill-file-types.ts +13 -0
  649. package/src/skills/skillssh-audit-types.ts +28 -0
  650. package/src/skills/skillssh-registry.ts +8 -21
  651. package/src/subagent/index.ts +1 -7
  652. package/src/subagent/manager.ts +1 -15
  653. package/src/tasks/task-runner.ts +0 -1
  654. package/src/tasks/task-store.ts +0 -3
  655. package/src/telemetry/types.ts +2 -0
  656. package/src/telemetry/usage-telemetry-reporter.test.ts +21 -0
  657. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  658. package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
  659. package/src/tools/apps/executors.ts +56 -69
  660. package/src/tools/background-tool-registry.ts +17 -3
  661. package/src/tools/browser/__tests__/browser-status.test.ts +21 -18
  662. package/src/tools/browser/browser-execution.ts +2 -2
  663. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +55 -4
  664. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
  665. package/src/tools/browser/cdp-client/factory.ts +23 -24
  666. package/src/tools/browser/cdp-client/index.ts +1 -14
  667. package/src/tools/computer-use/definitions.ts +42 -20
  668. package/src/tools/executor.ts +2 -0
  669. package/src/tools/host-filesystem/edit.test.ts +151 -0
  670. package/src/tools/host-filesystem/edit.ts +68 -0
  671. package/src/tools/host-filesystem/read.test.ts +129 -0
  672. package/src/tools/host-filesystem/read.ts +68 -0
  673. package/src/tools/host-filesystem/transfer.test.ts +127 -2
  674. package/src/tools/host-filesystem/transfer.ts +78 -3
  675. package/src/tools/host-filesystem/write.test.ts +134 -0
  676. package/src/tools/host-filesystem/write.ts +68 -0
  677. package/src/tools/host-terminal/host-shell.ts +66 -1
  678. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  679. package/src/tools/memory/register.test.ts +12 -9
  680. package/src/tools/memory/register.ts +1 -2
  681. package/src/tools/provider-tool-name.ts +28 -0
  682. package/src/tools/registry.ts +30 -9
  683. package/src/tools/schedule/create.ts +6 -0
  684. package/src/tools/schedule/list.ts +2 -0
  685. package/src/tools/schedule/update.ts +10 -0
  686. package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
  687. package/src/tools/shared/filesystem/path-policy.ts +25 -1
  688. package/src/tools/skills/load.ts +0 -32
  689. package/src/tools/terminal/shell.ts +9 -1
  690. package/src/tools/tool-approval-handler.ts +32 -11
  691. package/src/tools/types.ts +28 -2
  692. package/src/tts/provider-catalog.ts +3 -5
  693. package/src/usage/pricing.ts +1 -1
  694. package/src/util/disk-usage.ts +138 -0
  695. package/src/util/platform.ts +21 -11
  696. package/src/util/process-liveness.ts +26 -0
  697. package/src/workspace/hatched-date.ts +86 -0
  698. package/src/workspace/heartbeat-service.ts +19 -0
  699. package/src/workspace/migrations/003-seed-device-id.ts +1 -1
  700. package/src/workspace/migrations/006-services-config.ts +8 -5
  701. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
  702. package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
  703. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
  704. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
  705. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
  706. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
  707. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +2 -1
  708. package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
  709. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +3 -8
  710. package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
  711. package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
  712. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
  713. package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
  714. package/src/workspace/migrations/AGENTS.md +1 -1
  715. package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
  716. package/src/workspace/migrations/registry.ts +8 -0
  717. package/src/workspace/migrations/utils.ts +21 -0
  718. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
  719. package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -443
  720. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -226
  721. package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -427
  722. package/src/__tests__/twilio-rest.test.ts +0 -34
  723. package/src/backup/__tests__/backup-key.test.ts +0 -152
  724. package/src/backup/__tests__/backup-worker.test.ts +0 -782
  725. package/src/backup/__tests__/offsite-writer.test.ts +0 -641
  726. package/src/backup/__tests__/stream-crypt.test.ts +0 -228
  727. package/src/backup/backup-key.ts +0 -137
  728. package/src/backup/backup-worker.ts +0 -472
  729. package/src/backup/offsite-writer.ts +0 -222
  730. package/src/backup/stream-crypt.ts +0 -263
  731. package/src/daemon/message-types/pairing.ts +0 -58
  732. package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
  733. package/src/memory/v2/skill-qdrant.ts +0 -395
  734. package/src/outbound-proxy/config.ts +0 -20
  735. package/src/outbound-proxy/health.ts +0 -18
  736. package/src/outbound-proxy/types.ts +0 -150
  737. package/src/runtime/capability-tokens.ts +0 -190
  738. package/src/signals/bash.ts +0 -198
  739. package/src/signals/mcp-reload.ts +0 -18
@@ -153,8 +153,6 @@ export interface DisposeContext extends AbortContext {
153
153
  trustContext?: { trustClass: TrustClass };
154
154
  /** Active memory node IDs snapshotted from the conversation's InContextTracker before disposal. */
155
155
  activeContextNodeIds?: string[];
156
- /** Memory scope for extraction — defaults to "default" if omitted. */
157
- memoryScopeId?: string;
158
156
  abort(): void;
159
157
  }
160
158
 
@@ -240,11 +238,18 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
240
238
  }
241
239
 
242
240
  // Memory remains rehydrated on all rows (existing behavior).
241
+ // Strip any pre-existing wrapper before re-wrapping so historical
242
+ // rows persisted with the wrapper (v2 path before the
243
+ // injectedBlockText contract was unified with v1's unwrapped form)
244
+ // don't render double-wrapped after rehydrate.
243
245
  if (typeof meta.memoryInjectedBlock === "string") {
246
+ const inner = meta.memoryInjectedBlock
247
+ .replace(/^<memory>\n/, "")
248
+ .replace(/\n<\/memory>$/, "");
244
249
  content = [
245
250
  {
246
251
  type: "text" as const,
247
- text: `<memory>\n${meta.memoryInjectedBlock}\n</memory>`,
252
+ text: `<memory>\n${inner}\n</memory>`,
248
253
  },
249
254
  ...content,
250
255
  ];
@@ -371,7 +376,7 @@ export function disposeConversation(ctx: DisposeContext): void {
371
376
  try {
372
377
  enqueueMemoryJob("graph_extract", {
373
378
  conversationId: ctx.conversationId,
374
- scopeId: ctx.memoryScopeId ?? "default",
379
+ scopeId: "default",
375
380
  ...(ctx.activeContextNodeIds?.length
376
381
  ? { activeContextNodeIds: ctx.activeContextNodeIds }
377
382
  : {}),
@@ -14,7 +14,6 @@ import {
14
14
  import {
15
15
  parseChannelId,
16
16
  parseInterfaceId,
17
- supportsHostProxy,
18
17
  type TurnChannelContext,
19
18
  type TurnInterfaceContext,
20
19
  } from "../channels/types.js";
@@ -46,6 +45,7 @@ import {
46
45
  type SlashContext,
47
46
  } from "./conversation-slash.js";
48
47
  import { getModelInfo } from "./handlers/config-model.js";
48
+ import { preactivateHostProxySkills } from "./host-proxy-preactivation.js";
49
49
  import type {
50
50
  ServerMessage,
51
51
  UsageStats,
@@ -182,6 +182,8 @@ export interface ProcessConversationContext {
182
182
  forceCompact(): Promise<ContextWindowResult>;
183
183
  /** Set transport-derived hints for the conversation. */
184
184
  setTransportHints(hints: string[] | undefined): void;
185
+ /** IANA timezone reported by the active client for the current turn. */
186
+ clientTimezone?: string;
185
187
  /**
186
188
  * Apply client-reported host env (home dir, username) from transport
187
189
  * metadata, gating on `supportsHostProxy` so non-host-proxy interfaces
@@ -189,6 +191,10 @@ export interface ProcessConversationContext {
189
191
  * `DaemonServer.applyTransportMetadata` and the queue-drain path below.
190
192
  */
191
193
  applyHostEnvFromTransport(transport: ConversationTransportMetadata): void;
194
+ /** Apply the per-turn client timezone reported by transport metadata. */
195
+ applyClientTimezoneFromTransport(
196
+ transport: ConversationTransportMetadata,
197
+ ): void;
192
198
  }
193
199
 
194
200
  function resolveQueuedTurnContext(
@@ -423,16 +429,22 @@ async function drainSingleMessage(
423
429
  // setter used by DaemonServer.applyTransportMetadata so create/reuse
424
430
  // and queue-drain stay in sync without duplicating the gate logic.
425
431
  conversation.applyHostEnvFromTransport(next.transport);
432
+ conversation.applyClientTimezoneFromTransport(next.transport);
426
433
  }
427
434
 
428
- // Preactivate computer-use skill for interactive desktop turns.
435
+ // Re-preactivate host-proxy skills for interactive desktop turns. The
436
+ // dequeue path reset `preactivatedSkillIds` above, so without these
437
+ // re-adds the relevant skill tools wouldn't be projected to the LLM
438
+ // for queued messages 2+ even though the underlying proxies (HostCuProxy,
439
+ // HostAppControlProxy) are still attached. Mirrors the per-message
440
+ // instantiation block in `conversation-routes.ts` / `process-message.ts`.
429
441
  if (next.isInteractive !== false) {
430
442
  const interfaceCtx =
431
443
  queuedInterfaceCtx ?? conversation.getTurnInterfaceContext();
432
- const sourceInterface = interfaceCtx?.userMessageInterface;
433
- if (sourceInterface && supportsHostProxy(sourceInterface)) {
434
- conversation.addPreactivatedSkillId("computer-use");
435
- }
444
+ preactivateHostProxySkills(
445
+ conversation,
446
+ interfaceCtx?.userMessageInterface,
447
+ );
436
448
  }
437
449
 
438
450
  // Snapshot persona context at turn start so later tool turns can't pick up
@@ -860,17 +872,18 @@ async function drainBatch(
860
872
  if (head.transport) {
861
873
  conversation.setTransportHints(buildTransportHints(head.transport));
862
874
  conversation.applyHostEnvFromTransport(head.transport);
875
+ conversation.applyClientTimezoneFromTransport(head.transport);
863
876
  }
864
877
 
865
- // Preactivate computer-use skill for interactive desktop turns.
878
+ // Re-preactivate host-proxy skills for interactive desktop turns.
866
879
  // Mirrors the single-message path exactly — sourced from `head`.
867
880
  if (head.isInteractive !== false) {
868
881
  const interfaceCtx =
869
882
  queuedInterfaceCtx ?? conversation.getTurnInterfaceContext();
870
- const sourceInterface = interfaceCtx?.userMessageInterface;
871
- if (sourceInterface && supportsHostProxy(sourceInterface)) {
872
- conversation.addPreactivatedSkillId("computer-use");
873
- }
883
+ preactivateHostProxySkills(
884
+ conversation,
885
+ interfaceCtx?.userMessageInterface,
886
+ );
874
887
  }
875
888
 
876
889
  // Snapshot persona context at turn start so later tool turns can't pick up
@@ -33,6 +33,7 @@ import {
33
33
  } from "../messaging/providers/slack/render-transcript.js";
34
34
  import { getInjectors } from "../plugins/registry.js";
35
35
  import type {
36
+ DiskPressureInjectionContext,
36
37
  InjectionBlock,
37
38
  InjectionPlacement,
38
39
  TurnContext,
@@ -788,6 +789,9 @@ export interface UnifiedTurnContextOptions {
788
789
  interfaceName?: string;
789
790
  channelName?: string;
790
791
  actorContext?: InboundActorContext | null;
792
+ configuredUserTimezone?: string | null;
793
+ clientTimezone?: string | null;
794
+ detectedTimezone?: string | null;
791
795
  /**
792
796
  * Human-readable duration since the previous user message (e.g. "14h ago",
793
797
  * "yesterday", "3d ago"). Only populated when the gap exceeds 12 hours so
@@ -830,6 +834,25 @@ export function buildUnifiedTurnContextBlock(
830
834
 
831
835
  const lines: string[] = ["<turn_context>"];
832
836
  lines.push(`current_time: ${options.timestamp}`);
837
+ const configuredUserTimezone = options.configuredUserTimezone ?? null;
838
+ const clientDeviceTimezone =
839
+ options.clientTimezone ?? options.detectedTimezone ?? null;
840
+ const hasTimezoneMismatch =
841
+ configuredUserTimezone !== null &&
842
+ clientDeviceTimezone !== null &&
843
+ configuredUserTimezone !== clientDeviceTimezone;
844
+ if (hasTimezoneMismatch) {
845
+ const sanitizedConfiguredTimezone = sanitizeInlineContextValue(
846
+ configuredUserTimezone,
847
+ );
848
+ const sanitizedClientDeviceTimezone =
849
+ sanitizeInlineContextValue(clientDeviceTimezone);
850
+ lines.push(`configured_user_timezone: ${sanitizedConfiguredTimezone}`);
851
+ lines.push(`client_device_timezone: ${sanitizedClientDeviceTimezone}`);
852
+ lines.push(
853
+ `timezone_update_available: after explicit user confirmation, persist client_device_timezone with \`assistant config set ui.userTimezone "${sanitizedClientDeviceTimezone}"\``,
854
+ );
855
+ }
833
856
  if (options.timeSinceLastMessage) {
834
857
  lines.push(`time_since_last_message: ${options.timeSinceLastMessage}`);
835
858
  }
@@ -1317,7 +1340,7 @@ export function getSlackCompactionWatermarkForPrefix(
1317
1340
  );
1318
1341
  }
1319
1342
 
1320
- export function assembleSlackChronologicalContext(
1343
+ function assembleSlackChronologicalContext(
1321
1344
  rows: SlackTranscriptInputRow[],
1322
1345
  capabilities: ChannelCapabilities,
1323
1346
  options: {
@@ -1609,6 +1632,7 @@ export function loadSlackActiveThreadFocusBlock(
1609
1632
  const RUNTIME_INJECTION_PREFIXES = [
1610
1633
  "<channel_capabilities>",
1611
1634
  "<channel_command_context>",
1635
+ "<disk_pressure_warning>",
1612
1636
  "<channel_turn_context>", // backward-compat: strip legacy separate channel blocks
1613
1637
  "<guardian_context>",
1614
1638
  "<inbound_actor_context>", // backward-compat: strip legacy separate actor blocks
@@ -1618,7 +1642,7 @@ const RUNTIME_INJECTION_PREFIXES = [
1618
1642
  "<memory_context __injected>",
1619
1643
  "<memory_context>", // backward-compat: strip legacy blocks from pre-__injected history
1620
1644
  // NOTE: `<memory>` blocks (both the dynamic activation block from
1621
- // `prependMemoryV2Block` and the static `memory-v2-static` injector) are
1645
+ // `injectTextBlock` and the static `memory-v2-static` injector) are
1622
1646
  // intentionally NOT stripped — memory injections persist in history so
1623
1647
  // the assistant retains intra-turn memory state. The activation pipeline
1624
1648
  // dedupes via `everInjected`, and compaction handles aggregate growth, so
@@ -1872,6 +1896,7 @@ function applyInjectionBlock(
1872
1896
  * plugin-overridable default injectors.
1873
1897
  */
1874
1898
  export interface RuntimeInjectionOptions {
1899
+ diskPressureContext?: DiskPressureInjectionContext | null;
1875
1900
  /**
1876
1901
  * Active dashboard-surface context (read from `<active_workspace>`). Kept
1877
1902
  * on the options bag rather than an injector because it is a
@@ -1990,6 +2015,7 @@ function buildTurnInjectionInputs(
1990
2015
  ): TurnInjectionInputs {
1991
2016
  return {
1992
2017
  mode: options.mode,
2018
+ diskPressureContext: options.diskPressureContext,
1993
2019
  workspaceTopLevelContext: options.workspaceTopLevelContext,
1994
2020
  unifiedTurnContext: options.unifiedTurnContext,
1995
2021
  pkbContext: options.pkbContext,
@@ -22,7 +22,7 @@ import { RateLimitProvider } from "../providers/ratelimit.js";
22
22
  import { getProvider } from "../providers/registry.js";
23
23
  import { getSubagentManager } from "../subagent/index.js";
24
24
  import { getSandboxWorkingDir } from "../util/platform.js";
25
- import { Conversation, DEFAULT_MEMORY_POLICY } from "./conversation.js";
25
+ import { Conversation } from "./conversation.js";
26
26
  import type { ConversationEvictor } from "./conversation-evictor.js";
27
27
  import type { ConversationCreateOptions } from "./handlers/shared.js";
28
28
  import { buildTransportHints } from "./transport-hints.js";
@@ -180,6 +180,7 @@ function applyTransportMetadata(
180
180
  if (!transport) return;
181
181
  conversation.setTransportHints(buildTransportHints(transport));
182
182
  conversation.applyHostEnvFromTransport(transport);
183
+ conversation.applyClientTimezoneFromTransport(transport);
183
184
  }
184
185
 
185
186
  /**
@@ -253,7 +254,6 @@ export async function getOrCreateConversation(
253
254
  maxTokens,
254
255
  sendToClient,
255
256
  workingDir,
256
- DEFAULT_MEMORY_POLICY,
257
257
  sharedCesClient,
258
258
  storedOptions?.speed,
259
259
  undefined,
@@ -14,16 +14,21 @@ import {
14
14
  getMessages,
15
15
  updateMessageContent,
16
16
  } from "../memory/conversation-crud.js";
17
- import { broadcastMessage } from "../runtime/assistant-event-hub.js";
17
+ import {
18
+ assistantEventHub,
19
+ broadcastMessage,
20
+ } from "../runtime/assistant-event-hub.js";
21
+ import { enforceSameActorOrErrorResult } from "../runtime/auth/same-actor.js";
18
22
  import type {
19
23
  InteractiveUiRequest,
20
24
  InteractiveUiResult,
21
- } from "../runtime/interactive-ui.js";
25
+ } from "../runtime/interactive-ui-types.js";
22
26
  import type { ToolExecutionResult } from "../tools/types.js";
23
27
  import { getLogger } from "../util/logger.js";
24
28
  import { isPlainObject } from "../util/object.js";
25
29
  import { buildConversationErrorMessage } from "./conversation-error.js";
26
30
  import { launchConversation } from "./conversation-launch.js";
31
+ import type { HostAppControlProxy } from "./host-app-control-proxy.js";
27
32
  import type { HostCuProxy } from "./host-cu-proxy.js";
28
33
  import type {
29
34
  CardSurfaceData,
@@ -41,6 +46,7 @@ import type {
41
46
  } from "./message-protocol.js";
42
47
  import { INTERACTIVE_SURFACE_TYPES } from "./message-protocol.js";
43
48
  import type { ConversationTransportMetadata } from "./message-types/conversations.js";
49
+ import type { HostAppControlInput } from "./message-types/host-app-control.js";
44
50
  import type { UserMessageAttachment } from "./message-types/shared.js";
45
51
  import type { TrustContext } from "./trust-context.js";
46
52
 
@@ -48,6 +54,148 @@ const log = getLogger("conversation-surfaces");
48
54
 
49
55
  const MAX_UNDO_DEPTH = 10;
50
56
 
57
+ /**
58
+ * Debounce window for persisting `ui_surface_update` data back to the
59
+ * message row. Surfaces typically receive bursts of updates (e.g. a
60
+ * Workspace Health Check ticking off items rapidly) — collapsing them
61
+ * to a single DB write avoids hammering SQLite while still bounding the
62
+ * "lost work on crash" window to ~half a second.
63
+ */
64
+ const SURFACE_PERSIST_DEBOUNCE_MS = 500;
65
+
66
+ /**
67
+ * In-flight debounced persist timers keyed by `surfaceId`. Surface IDs
68
+ * are UUIDs and globally unique, so a module-level map is safe across
69
+ * conversations. Each entry holds the latest data snapshot — newer
70
+ * updates clobber older ones since the persisted row carries the full
71
+ * merged state, not a delta.
72
+ */
73
+ const pendingSurfacePersists = new Map<
74
+ string,
75
+ {
76
+ timer: ReturnType<typeof setTimeout>;
77
+ conversationId: string;
78
+ data: SurfaceData;
79
+ }
80
+ >();
81
+
82
+ /**
83
+ * Persist the latest `data` for a `ui_surface` content block by
84
+ * scanning the conversation's messages for one containing the given
85
+ * `surfaceId` and patching its `data` field. Mirrors the scan-and-patch
86
+ * pattern in `markSurfaceCompleted`.
87
+ *
88
+ * Safe to call before the assistant message has been persisted (mid-stream):
89
+ * the scan simply finds nothing and bails. The next update after
90
+ * `handleMessageComplete` runs will pick up the now-persisted row.
91
+ */
92
+ function persistSurfaceData(
93
+ conversationId: string,
94
+ surfaceId: string,
95
+ data: SurfaceData,
96
+ ): void {
97
+ try {
98
+ const rows = getMessages(conversationId);
99
+ for (let r = rows.length - 1; r >= 0; r--) {
100
+ let parsed: unknown[];
101
+ try {
102
+ const result = JSON.parse(rows[r].content);
103
+ if (!Array.isArray(result)) continue;
104
+ parsed = result;
105
+ } catch {
106
+ // Plain-text content rows — skip and keep scanning.
107
+ continue;
108
+ }
109
+ let found = false;
110
+ for (const pb of parsed) {
111
+ const rb = pb as Record<string, unknown>;
112
+ if (rb.type === "ui_surface" && rb.surfaceId === surfaceId) {
113
+ rb.data = data;
114
+ found = true;
115
+ break;
116
+ }
117
+ }
118
+ if (found) {
119
+ updateMessageContent(rows[r].id, JSON.stringify(parsed));
120
+ return;
121
+ }
122
+ }
123
+ } catch (err) {
124
+ log.debug(
125
+ { err, surfaceId, conversationId },
126
+ "Failed to persist surface data update",
127
+ );
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Schedule a debounced write of the merged surface data back to the
133
+ * persisted message row. Repeated calls within the debounce window
134
+ * collapse to a single write carrying the latest data.
135
+ */
136
+ export function scheduleSurfaceDataPersist(
137
+ conversationId: string,
138
+ surfaceId: string,
139
+ data: SurfaceData,
140
+ ): void {
141
+ const existing = pendingSurfacePersists.get(surfaceId);
142
+ if (existing) {
143
+ clearTimeout(existing.timer);
144
+ }
145
+ const timer = setTimeout(() => {
146
+ pendingSurfacePersists.delete(surfaceId);
147
+ persistSurfaceData(conversationId, surfaceId, data);
148
+ }, SURFACE_PERSIST_DEBOUNCE_MS);
149
+ pendingSurfacePersists.set(surfaceId, { timer, conversationId, data });
150
+ }
151
+
152
+ /**
153
+ * Force-flush any pending debounced persist for `surfaceId`. Called on
154
+ * surface completion so the final state is durable before the surface
155
+ * record transitions to `completed`.
156
+ */
157
+ export function flushSurfaceDataPersist(surfaceId: string): void {
158
+ const pending = pendingSurfacePersists.get(surfaceId);
159
+ if (!pending) return;
160
+ clearTimeout(pending.timer);
161
+ pendingSurfacePersists.delete(surfaceId);
162
+ persistSurfaceData(pending.conversationId, surfaceId, pending.data);
163
+ }
164
+
165
+ /**
166
+ * Cancel all pending debounced persists. Called on conversation
167
+ * teardown to avoid timers firing against torn-down state.
168
+ *
169
+ * Use `flushPendingSurfaceDataPersists` instead on a clean shutdown
170
+ * path where the latest in-flight surface state should still be
171
+ * written before teardown.
172
+ */
173
+ export function cancelPendingSurfaceDataPersists(
174
+ conversationId?: string,
175
+ ): void {
176
+ for (const [surfaceId, pending] of pendingSurfacePersists) {
177
+ if (conversationId && pending.conversationId !== conversationId) continue;
178
+ clearTimeout(pending.timer);
179
+ pendingSurfacePersists.delete(surfaceId);
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Synchronously flush all pending debounced persists, optionally scoped
185
+ * to a single conversation. Called on clean conversation teardown so an
186
+ * update that arrived inside the 500ms debounce window still lands in
187
+ * the DB before the conversation goes away. Each entry is removed from
188
+ * the pending map after its write fires.
189
+ */
190
+ export function flushPendingSurfaceDataPersists(conversationId?: string): void {
191
+ for (const [surfaceId, pending] of pendingSurfacePersists) {
192
+ if (conversationId && pending.conversationId !== conversationId) continue;
193
+ clearTimeout(pending.timer);
194
+ pendingSurfacePersists.delete(surfaceId);
195
+ persistSurfaceData(pending.conversationId, surfaceId, pending.data);
196
+ }
197
+ }
198
+
51
199
  /**
52
200
  * Mark a `ui_surface` content block as completed in the database so that
53
201
  * history reconstruction preserves the completion state. Also updates
@@ -58,6 +206,10 @@ export function markSurfaceCompleted(
58
206
  surfaceId: string,
59
207
  summary: string,
60
208
  ): void {
209
+ // Force-flush any pending debounced data persist so the completion
210
+ // patch lands on top of the latest data instead of racing with it.
211
+ flushSurfaceDataPersist(surfaceId);
212
+
61
213
  // Update in-memory messages when available so subsequent reads within
62
214
  // this session see the change without waiting for DB.
63
215
  if (ctx.messages) {
@@ -320,6 +472,15 @@ export interface SurfaceConversationContext {
320
472
  }>;
321
473
  /** Optional proxy for delegating computer-use actions to a connected desktop client. */
322
474
  hostCuProxy?: HostCuProxy;
475
+ /** Optional proxy for delegating per-app app-control actions to a connected desktop client. */
476
+ hostAppControlProxy?: HostAppControlProxy;
477
+ /**
478
+ * Setter that lets the resolver detach the conversation's app-control proxy
479
+ * after `app_control_stop`. Disposes the existing proxy when transitioning
480
+ * to undefined so subsequent tool calls cleanly fail with "unavailable"
481
+ * rather than dispatching to a torn-down proxy.
482
+ */
483
+ setHostAppControlProxy?(proxy: HostAppControlProxy | undefined): void;
323
484
  /** True when no interactive client is connected (headless / channel-only). */
324
485
  readonly hasNoClient?: boolean;
325
486
  isProcessing(): boolean;
@@ -1206,7 +1367,11 @@ export async function handleSurfaceAction(
1206
1367
 
1207
1368
  const requestId = uuid();
1208
1369
  ctx.surfaceActionRequestIds.add(requestId);
1209
- const onEvent = (msg: ServerMessage) => broadcastMessage(msg);
1370
+ // Pass conversationId so events without an inline conversationId (e.g.
1371
+ // text_delta) are published with the correct conversation scope and
1372
+ // reach the SSE subscriber filtered to this conversation.
1373
+ const onEvent = (msg: ServerMessage) =>
1374
+ broadcastMessage(msg, ctx.conversationId);
1210
1375
 
1211
1376
  ctx.traceEmitter.emit("request_received", "Surface action received", {
1212
1377
  requestId,
@@ -1440,7 +1605,11 @@ export async function handleSurfaceAction(
1440
1605
 
1441
1606
  const requestId = uuid();
1442
1607
  ctx.surfaceActionRequestIds.add(requestId);
1443
- const onEvent = (msg: ServerMessage) => broadcastMessage(msg);
1608
+ // Pass conversationId so events without an inline conversationId (e.g.
1609
+ // text_delta) are published with the correct conversation scope and
1610
+ // reach the SSE subscriber filtered to this conversation.
1611
+ const onEvent = (msg: ServerMessage) =>
1612
+ broadcastMessage(msg, ctx.conversationId);
1444
1613
 
1445
1614
  ctx.traceEmitter.emit("request_received", "Surface action received", {
1446
1615
  requestId,
@@ -1761,6 +1930,82 @@ export async function surfaceProxyResolver(
1761
1930
  // Record the action and proxy to the connected desktop client
1762
1931
  const reasoning =
1763
1932
  typeof input.reasoning === "string" ? input.reasoning : undefined;
1933
+ let targetClientId: string | undefined =
1934
+ typeof input.target_client_id === "string" &&
1935
+ input.target_client_id !== ""
1936
+ ? input.target_client_id
1937
+ : undefined;
1938
+
1939
+ // Validate targetClientId existence, capability, and same-user binding
1940
+ // before recordAction so an invalid or cross-user ID does not burn a
1941
+ // step or pollute action history. HostBashProxy / HostFileProxy
1942
+ // validate at the tool-resolution layer for the same reason. The proxy
1943
+ // re-checks same-user (single authoritative gate); using the shared
1944
+ // helper keeps log payload and error wording identical at both layers.
1945
+ const sourceActorPrincipalId = ctx.trustContext?.guardianPrincipalId;
1946
+ if (targetClientId != null) {
1947
+ const client = assistantEventHub.getClientById(targetClientId);
1948
+ if (!client) {
1949
+ return {
1950
+ content: `No connected client with id '${targetClientId}'. Run \`assistant clients list --capability host_cu\` to see available clients.`,
1951
+ isError: true,
1952
+ };
1953
+ }
1954
+ if (!client.capabilities.includes("host_cu")) {
1955
+ return {
1956
+ content: `Client '${targetClientId}' does not support host_cu. Run \`assistant clients list --capability host_cu\` to see available clients.`,
1957
+ isError: true,
1958
+ };
1959
+ }
1960
+ const rejection = enforceSameActorOrErrorResult({
1961
+ hub: assistantEventHub,
1962
+ sourceActorPrincipalId,
1963
+ targetClientId,
1964
+ op: "host_cu",
1965
+ });
1966
+ if (rejection) return rejection;
1967
+ }
1968
+
1969
+ // Guard: require explicit targeting when multiple same-user CU-capable
1970
+ // clients are connected. The tool schemas document target_client_id as
1971
+ // "required when multiple clients support host_cu" but nothing enforced
1972
+ // it at runtime until now. Without this guard, the request would
1973
+ // broadcast to all capable clients simultaneously, causing the same CU
1974
+ // action to execute on multiple machines. The filter mirrors
1975
+ // HostFileProxy's auto-resolve: only same-user clients participate, so
1976
+ // a cross-user client connected to the same daemon does not falsely
1977
+ // trigger this ambiguity error.
1978
+ //
1979
+ // Asymmetry with host_bash / host_file (host-shell.ts): the bash/file
1980
+ // guard additionally checks `transportInterface != null &&
1981
+ // !supportsHostProxy(transportInterface)` and so only fires for non-host-
1982
+ // proxy transports (web, Slack). For CU that check would be a no-op:
1983
+ // every host_cu-capable client is host-proxy-capable by definition
1984
+ // (host_cu only ships on macOS and the Chrome extension), so there is no
1985
+ // host_cu-capable transport for which auto-routing-to-self would be
1986
+ // appropriate. We therefore fire whenever there is genuine ambiguity.
1987
+ if (targetClientId == null) {
1988
+ const allCuClients = assistantEventHub.listClientsByCapability("host_cu");
1989
+ const sameUserCuClients = allCuClients.filter(
1990
+ (c) => c.actorPrincipalId === sourceActorPrincipalId,
1991
+ );
1992
+ if (sameUserCuClients.length > 1) {
1993
+ return {
1994
+ content: `Error: multiple clients support host_cu. Specify which client to target with \`target_client_id\`. Run \`assistant clients list --capability host_cu\` to see client IDs and labels.`,
1995
+ isError: true,
1996
+ };
1997
+ }
1998
+ // When cross-user host_cu clients are connected, we MUST auto-resolve
1999
+ // to the unique same-user client (or fail explicitly) — otherwise the
2000
+ // proxy would broadcast untargeted and the CU action would reach the
2001
+ // cross-user client too. Setting targetClientId here forces the proxy
2002
+ // to deliver only to that client, with the same-user check below as
2003
+ // belt-and-suspenders.
2004
+ if (sameUserCuClients.length === 1 && allCuClients.length > 1) {
2005
+ targetClientId = sameUserCuClients[0].clientId;
2006
+ }
2007
+ }
2008
+
1764
2009
  ctx.hostCuProxy.recordAction(toolName, input, reasoning);
1765
2010
  return ctx.hostCuProxy.request(
1766
2011
  toolName,
@@ -1769,6 +2014,56 @@ export async function surfaceProxyResolver(
1769
2014
  ctx.hostCuProxy.stepCount,
1770
2015
  reasoning,
1771
2016
  signal,
2017
+ targetClientId,
2018
+ sourceActorPrincipalId,
2019
+ );
2020
+ }
2021
+
2022
+ // Route app-control proxy tools (all app_control_* tool variants)
2023
+ if (toolName.startsWith("app_control_")) {
2024
+ if (!ctx.hostAppControlProxy || !ctx.hostAppControlProxy.isAvailable()) {
2025
+ return {
2026
+ content:
2027
+ "App control is not available — enable the `app-control` feature flag and connect a macOS client.",
2028
+ isError: true,
2029
+ };
2030
+ }
2031
+
2032
+ // `app_control_stop` resolves immediately: tear down the proxy without
2033
+ // a client round-trip. Mirrors CU's terminal-tool short-circuit
2034
+ // (`computer_use_done` / `computer_use_respond`). Clear the
2035
+ // conversation's reference (setter disposes the existing proxy) so a
2036
+ // later `app_control_observe`/etc. cleanly fails with "unavailable"
2037
+ // instead of dispatching against a torn-down proxy, and so a sibling
2038
+ // conversation can acquire the released singleton lock without the
2039
+ // disposed proxy still being addressable.
2040
+ if (toolName === "app_control_stop") {
2041
+ if (ctx.setHostAppControlProxy) {
2042
+ ctx.setHostAppControlProxy(undefined);
2043
+ } else {
2044
+ ctx.hostAppControlProxy.dispose();
2045
+ }
2046
+ return { content: "App control stopped.", isError: false };
2047
+ }
2048
+
2049
+ // The TS `HostAppControlInput` (and the Swift mirror) is a discriminated
2050
+ // union on `tool` ("start" | "observe" | "press" | …). The agent's raw
2051
+ // tool input only carries the action-specific payload (app, x/y, text,
2052
+ // …) — the discriminator is implied by `toolName` (`app_control_<tool>`).
2053
+ // Inject it here so the proxy's session-lock guard (`input.tool ===
2054
+ // "start"`) and the Swift client's discriminated-union decoder both see
2055
+ // the field they require.
2056
+ const tool = toolName.slice("app_control_".length);
2057
+ const inputWithTool = {
2058
+ ...input,
2059
+ tool,
2060
+ } as unknown as HostAppControlInput;
2061
+
2062
+ return ctx.hostAppControlProxy.request(
2063
+ toolName,
2064
+ inputWithTool,
2065
+ ctx.conversationId,
2066
+ signal ?? new AbortController().signal,
1772
2067
  );
1773
2068
  }
1774
2069
 
@@ -1956,6 +2251,12 @@ export async function surfaceProxyResolver(
1956
2251
  ctx.currentTurnSurfaces[idx].data = mergedData;
1957
2252
  }
1958
2253
 
2254
+ // Persist the merged data back to the assistant message's
2255
+ // `ui_surface` content block so a refresh / restart shows the
2256
+ // current state instead of the original creation-time snapshot.
2257
+ // Debounced to coalesce bursts of rapid updates.
2258
+ scheduleSurfaceDataPersist(ctx.conversationId, surfaceId, mergedData);
2259
+
1959
2260
  return { content: "Surface updated", isError: false };
1960
2261
  }
1961
2262