@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
@@ -14,6 +14,31 @@
14
14
 
15
15
  import type { HostProxyCapability, InterfaceId } from "../channels/types.js";
16
16
  import type { ServerMessage } from "../daemon/message-protocol.js";
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Message type → capability inference
20
+ // ---------------------------------------------------------------------------
21
+
22
+ const HOST_PREFIX_TO_CAPABILITY: Record<string, HostProxyCapability> = {
23
+ host_bash: "host_bash",
24
+ host_file: "host_file",
25
+ host_transfer: "host_file", // transfers piggyback on host_file capability
26
+ host_cu: "host_cu",
27
+ host_browser: "host_browser",
28
+ host_app_control: "host_app_control",
29
+ };
30
+
31
+ /**
32
+ * Infer the {@link HostProxyCapability} a message should be targeted at based
33
+ * on its `type` field. Returns `undefined` for message types that are not
34
+ * host-proxy messages (i.e. they should broadcast to all subscribers).
35
+ */
36
+ export function capabilityForMessageType(
37
+ type: string,
38
+ ): HostProxyCapability | undefined {
39
+ const stem = type.replace(/_(request|cancel)$/, "");
40
+ return HOST_PREFIX_TO_CAPABILITY[stem];
41
+ }
17
42
  import { emitFeedEvent } from "../home/emit-feed-event.js";
18
43
  import { rewriteCommandPreview } from "../home/rewrite-command-preview.js";
19
44
  import { redactSecrets } from "../security/secret-scanner.js";
@@ -22,7 +47,6 @@ import { summarizeToolInput } from "../tools/tool-input-summary.js";
22
47
  import { getLogger } from "../util/logger.js";
23
48
  import type { AssistantEvent } from "./assistant-event.js";
24
49
  import { buildAssistantEvent } from "./assistant-event.js";
25
- import * as pendingInteractions from "./pending-interactions.js";
26
50
 
27
51
  const log = getLogger("assistant-event-hub");
28
52
 
@@ -56,18 +80,29 @@ interface BaseSubscriberEntry {
56
80
  lastActiveAt: Date;
57
81
  }
58
82
 
59
- export interface ClientEntry extends BaseSubscriberEntry {
83
+ interface ClientEntry extends BaseSubscriberEntry {
60
84
  type: "client";
61
85
  clientId: string;
62
86
  interfaceId: InterfaceId;
63
87
  capabilities: HostProxyCapability[];
88
+ machineName?: string;
89
+ /**
90
+ * The verified actor principal id (canonical user identity, parsed from JWT
91
+ * `sub`) of the user that opened this SSE connection, when available.
92
+ *
93
+ * Populated from `AuthContext.actorPrincipalId` at SSE subscription time.
94
+ * Used by host proxies to gate cross-client targeted execution to the same
95
+ * authenticated user identity. May be `undefined` for legacy or
96
+ * service-token connections that have no principal.
97
+ */
98
+ actorPrincipalId?: string;
64
99
  }
65
100
 
66
- export interface ProcessEntry extends BaseSubscriberEntry {
101
+ interface ProcessEntry extends BaseSubscriberEntry {
67
102
  type: "process";
68
103
  }
69
104
 
70
- export type SubscriberEntry = ClientEntry | ProcessEntry;
105
+ type SubscriberEntry = ClientEntry | ProcessEntry;
71
106
 
72
107
  /** Distributive Omit that preserves union discrimination. */
73
108
  type DistributiveOmit<T, K extends PropertyKey> = T extends unknown
@@ -75,7 +110,7 @@ type DistributiveOmit<T, K extends PropertyKey> = T extends unknown
75
110
  : never;
76
111
 
77
112
  /** Input shape for `subscribe()` — hub fills `active`, `connectedAt`, `lastActiveAt` and defaults `filter`/`onEvict`. */
78
- export type SubscriberInput = DistributiveOmit<
113
+ type SubscriberInput = DistributiveOmit<
79
114
  SubscriberEntry,
80
115
  "active" | "connectedAt" | "lastActiveAt" | "filter" | "onEvict"
81
116
  > & {
@@ -216,7 +251,12 @@ export class AssistantEventHub {
216
251
  * Publish an event to all matching subscribers.
217
252
  *
218
253
  * Matching rules:
219
- * - if `filter.conversationId` is set, `event.conversationId` must equal it
254
+ * - if `targetClientId` is set, deliver only to the subscriber with that
255
+ * clientId, bypassing the conversation-id filter entirely (the web-origin
256
+ * event's conversationId differs from the macOS client's subscribed
257
+ * conversation).
258
+ * - if `filter.conversationId` is set (and `targetClientId` is not), the
259
+ * `event.conversationId` must equal it
220
260
  * - if `targetCapability` is set, only subscribers whose capabilities include
221
261
  * it receive the event; untargeted events go to all
222
262
  *
@@ -225,7 +265,10 @@ export class AssistantEventHub {
225
265
  */
226
266
  async publish(
227
267
  event: AssistantEvent,
228
- options?: { targetCapability?: HostProxyCapability },
268
+ options?: {
269
+ targetCapability?: HostProxyCapability;
270
+ targetClientId?: string;
271
+ },
229
272
  ): Promise<void> {
230
273
  if (event.conversationId) {
231
274
  try {
@@ -236,29 +279,40 @@ export class AssistantEventHub {
236
279
  }
237
280
 
238
281
  const targetCapability = options?.targetCapability;
282
+ const targetClientId = options?.targetClientId;
239
283
  const snapshot = Array.from(this.subscribers);
240
284
  const errors: unknown[] = [];
241
285
 
242
286
  for (const entry of snapshot) {
243
287
  if (!entry.active) continue;
244
288
 
245
- // Conversation scoping: scoped events skip subscribers filtering on a
246
- // different conversation.
247
- if (
248
- event.conversationId != null &&
249
- entry.filter.conversationId != null &&
250
- entry.filter.conversationId !== event.conversationId
251
- )
252
- continue;
253
-
254
- // Capability targeting: targeted events only go to subscribers that
255
- // declare the required capability.
256
- if (targetCapability != null) {
289
+ if (targetClientId != null) {
290
+ // Targeted: bypass conversation filter, deliver only to the named client.
291
+ if (entry.type !== "client" || entry.clientId !== targetClientId)
292
+ continue;
257
293
  if (
258
- entry.type !== "client" ||
294
+ targetCapability != null &&
259
295
  !entry.capabilities.includes(targetCapability)
260
296
  )
261
297
  continue;
298
+ } else {
299
+ // Untargeted: existing conversation-scoped + capability logic.
300
+ if (
301
+ event.conversationId != null &&
302
+ entry.filter.conversationId != null &&
303
+ entry.filter.conversationId !== event.conversationId
304
+ )
305
+ continue;
306
+
307
+ // Capability targeting: targeted events only go to subscribers that
308
+ // declare the required capability.
309
+ if (targetCapability != null) {
310
+ if (
311
+ entry.type !== "client" ||
312
+ !entry.capabilities.includes(targetCapability)
313
+ )
314
+ continue;
315
+ }
262
316
  }
263
317
 
264
318
  try {
@@ -276,6 +330,34 @@ export class AssistantEventHub {
276
330
  }
277
331
  }
278
332
 
333
+ /**
334
+ * Return the active client subscriber with the given clientId, or
335
+ * `undefined` if no such subscriber exists.
336
+ */
337
+ getClientById(clientId: string): ClientEntry | undefined {
338
+ for (const entry of this.subscribers) {
339
+ if (
340
+ entry.active &&
341
+ entry.type === "client" &&
342
+ entry.clientId === clientId
343
+ )
344
+ return entry;
345
+ }
346
+ return undefined;
347
+ }
348
+
349
+ /**
350
+ * Return the verified actor principal id captured at SSE subscription time
351
+ * for the given client, or `undefined` if the client is unknown or
352
+ * connected without a principal (e.g. legacy/service tokens).
353
+ *
354
+ * Used by host proxies to bind cross-client targeted execution to the same
355
+ * authenticated user identity that opened the target client's SSE stream.
356
+ */
357
+ getActorPrincipalIdForClient(clientId: string): string | undefined {
358
+ return this.getClientById(clientId)?.actorPrincipalId;
359
+ }
360
+
279
361
  /**
280
362
  * Returns true when at least one active subscriber would receive the given
281
363
  * event based on the same conversation matching rules as publish().
@@ -338,6 +420,35 @@ export class AssistantEventHub {
338
420
  return this.listClientsByCapability(capability)[0];
339
421
  }
340
422
 
423
+ /**
424
+ * Return the best client for the given capability using an explicit
425
+ * interface preference order. Among clients that support `capability`,
426
+ * the one whose `interfaceId` appears earliest in `interfacePreference`
427
+ * wins. Within the same interface tier, `lastActiveAt` is the tiebreaker
428
+ * (most recent first). Clients not in the preference list are considered last.
429
+ *
430
+ * Used by {@link HostBrowserProxy} to prefer the Chrome Extension
431
+ * (`chrome-extension`) over the macOS SSE bridge (`macos`) when both are
432
+ * connected, so `chrome.debugger` is used ahead of the localhost:9222 path.
433
+ */
434
+ getPreferredClientByCapability(
435
+ capability: HostProxyCapability,
436
+ interfacePreference: InterfaceId[],
437
+ ): ClientEntry | undefined {
438
+ const clients = this.listClientsByCapability(capability);
439
+ if (clients.length === 0) return undefined;
440
+ // listClientsByCapability returns clients sorted by lastActiveAt desc
441
+ // (most recent first). A stable sort by preference index preserves that
442
+ // ordering within each interface tier.
443
+ return clients.sort((a, b) => {
444
+ const ai = interfacePreference.indexOf(a.interfaceId);
445
+ const bi = interfacePreference.indexOf(b.interfaceId);
446
+ const ea = ai === -1 ? interfacePreference.length : ai;
447
+ const eb = bi === -1 ? interfacePreference.length : bi;
448
+ return ea - eb;
449
+ })[0];
450
+ }
451
+
341
452
  /**
342
453
  * Return all client subscribers with the given interface type,
343
454
  * sorted by `lastActiveAt` descending.
@@ -372,10 +483,7 @@ export class AssistantEventHub {
372
483
  disposeClient(clientId: string): number {
373
484
  const targets: SubscriberEntry[] = [];
374
485
  for (const entry of this.subscribers) {
375
- if (
376
- entry.type === "client" &&
377
- entry.clientId === clientId
378
- ) {
486
+ if (entry.type === "client" && entry.clientId === clientId) {
379
487
  targets.push(entry);
380
488
  }
381
489
  }
@@ -432,25 +540,27 @@ let _hubChain = Promise.resolve();
432
540
  * When `conversationId` is omitted, it is auto-extracted from the message
433
541
  * payload (if present).
434
542
  *
543
+ * Target capability is inferred automatically from the message type — callers
544
+ * never need to specify it. Host-proxy messages (`host_bash_*`,
545
+ * `host_file_*`, `host_transfer_*`, `host_cu_*`, `host_browser_*`) are routed
546
+ * only to subscribers that declare the matching capability; all other messages
547
+ * broadcast to every subscriber.
548
+ *
435
549
  * This is the primary entrypoint for emitting events — handlers, routes, and
436
550
  * services should call this directly instead of threading a broadcast callback.
437
551
  */
438
552
  export function broadcastMessage(
439
553
  msg: ServerMessage,
440
554
  conversationId?: string,
441
- options?: { targetCapability?: HostProxyCapability },
555
+ options?: { targetClientId?: string },
442
556
  ): void {
443
557
  const resolvedConversationId = conversationId ?? extractConversationId(msg);
558
+ const targetClientId = options?.targetClientId;
444
559
 
445
- // Register pending interactions so approval/host prompts are tracked
446
- // regardless of which path triggered the broadcast.
447
- if (resolvedConversationId) {
448
- registerPendingInteraction(msg, resolvedConversationId);
449
- }
450
-
451
- // Emit feed events for confirmation requests (tool approval prompts).
560
+ // Confirmation-request side effects: feed event + canonical guardian request.
452
561
  if (msg.type === "confirmation_request" && resolvedConversationId) {
453
562
  void emitConfirmationFeedEvent(msg, resolvedConversationId);
563
+ void createCanonicalRequestForConfirmation(msg, resolvedConversationId);
454
564
  }
455
565
 
456
566
  // `conversation_list_invalidated` is a list-level system event — publish
@@ -460,8 +570,13 @@ export function broadcastMessage(
460
570
  ? undefined
461
571
  : resolvedConversationId;
462
572
  const event = buildAssistantEvent(msg, scopedConversationId);
573
+ const targetCapability = capabilityForMessageType(msg.type);
574
+ const publishOptions =
575
+ targetCapability != null || targetClientId != null
576
+ ? { targetCapability, targetClientId }
577
+ : undefined;
463
578
  _hubChain = _hubChain
464
- .then(() => assistantEventHub.publish(event, options))
579
+ .then(() => assistantEventHub.publish(event, publishOptions))
465
580
  .then(() => {
466
581
  // When a conversation title changes, also broadcast an unscoped
467
582
  // `conversation_list_invalidated` so every connected client's sidebar
@@ -495,7 +610,7 @@ function extractConversationId(msg: ServerMessage): string | undefined {
495
610
  return undefined;
496
611
  }
497
612
 
498
- // ── Pending interaction registration ──────────────────────────────────────────
613
+ // ── Canonical guardian request ────────────────────────────────────────────────
499
614
 
500
615
  function resolveCanonicalRequestSourceType(
501
616
  sourceChannel: string,
@@ -505,74 +620,11 @@ function resolveCanonicalRequestSourceType(
505
620
  return "channel";
506
621
  }
507
622
 
508
- /**
509
- * Register pending interactions for request-type messages so approval and
510
- * host prompts are tracked regardless of which code path broadcasts them.
511
- *
512
- * Heavy dependencies (conversation-store, canonical-guardian-store, etc.) are
513
- * imported lazily so that loading this module during tests doesn't trigger
514
- * config/data-dir side effects.
515
- */
516
- function registerPendingInteraction(
517
- msg: ServerMessage,
518
- conversationId: string,
519
- ): void {
520
- if (msg.type === "confirmation_request") {
521
- pendingInteractions.register(msg.requestId, {
522
- conversationId,
523
- kind: "confirmation",
524
- confirmationDetails: {
525
- toolName: msg.toolName,
526
- input: msg.input,
527
- riskLevel: msg.riskLevel,
528
- executionTarget: msg.executionTarget,
529
- allowlistOptions: msg.allowlistOptions,
530
- scopeOptions: msg.scopeOptions,
531
- persistentDecisionsAllowed: msg.persistentDecisionsAllowed,
532
- },
533
- });
534
-
535
- // Create canonical guardian request asynchronously — heavy deps are
536
- // imported lazily to avoid pulling in conversation-store (and
537
- // transitively config/loader → ensureDataDir) at module-load time.
538
- void createCanonicalRequestForConfirmation(msg, conversationId);
539
- } else if (msg.type === "secret_request") {
540
- pendingInteractions.register(msg.requestId, {
541
- conversationId,
542
- kind: "secret",
543
- });
544
- } else if (msg.type === "host_bash_request") {
545
- pendingInteractions.register(msg.requestId, {
546
- conversationId,
547
- kind: "host_bash",
548
- });
549
- } else if (msg.type === "host_browser_request") {
550
- pendingInteractions.register(msg.requestId, {
551
- conversationId,
552
- kind: "host_browser",
553
- });
554
- } else if (msg.type === "host_file_request") {
555
- pendingInteractions.register(msg.requestId, {
556
- conversationId,
557
- kind: "host_file",
558
- });
559
- } else if (msg.type === "host_cu_request") {
560
- pendingInteractions.register(msg.requestId, {
561
- conversationId,
562
- kind: "host_cu",
563
- });
564
- } else if (msg.type === "host_transfer_request") {
565
- pendingInteractions.register(msg.requestId, {
566
- conversationId,
567
- kind: "host_transfer",
568
- });
569
- }
570
- }
571
623
 
572
624
  /**
573
625
  * Lazily load heavy dependencies and create a canonical guardian request +
574
- * bridge for a confirmation_request message. Runs fire-and-forget from
575
- * registerPendingInteraction.
626
+ * bridge for a confirmation_request message. Called fire-and-forget from
627
+ * broadcastMessage.
576
628
  */
577
629
  async function createCanonicalRequestForConfirmation(
578
630
  msg: ServerMessage & { type: "confirmation_request" },
@@ -35,12 +35,6 @@ mock.module("../../../config/env.js", () => ({
35
35
 
36
36
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../assistant-scope.js";
37
37
  import {
38
- mintHostBrowserCapability,
39
- resetCapabilityTokenSecretForTests,
40
- setCapabilityTokenSecretForTests,
41
- } from "../../capability-tokens.js";
42
- import {
43
- authenticateHostBrowserResultRequest,
44
38
  authenticateRequest,
45
39
  } from "../middleware.js";
46
40
  import { initAuthSigningKey, mintToken } from "../token-service.js";
@@ -272,55 +266,20 @@ describe("authenticateRequest", () => {
272
266
  });
273
267
 
274
268
  // ---------------------------------------------------------------------------
275
- // authenticateHostBrowserResultRequest — capability-token-aware auth for the
276
- // /v1/host-browser-result POST route. Verifies that both the capability-token
277
- // and JWT paths are accepted, and that a garbage bearer falls through to the
278
- // JWT path and emits a 401 like any other invalid token.
269
+ // /v1/host-browser-result auth exercises authenticateRequest with the
270
+ // same request shape the chrome extension sends. Validates that standard
271
+ // JWT auth applies after the capability-token system was removed.
279
272
  // ---------------------------------------------------------------------------
280
273
 
281
- describe("authenticateHostBrowserResultRequest", () => {
282
- const CAPABILITY_SECRET = Buffer.alloc(32, 7);
283
-
284
- beforeEach(() => {
285
- // Pin the capability-token HMAC secret so mint/verify agree across
286
- // the test run. The module-level secret cache is reset between
287
- // tests so dev-bypass flipping doesn't leak stale state.
288
- setCapabilityTokenSecretForTests(CAPABILITY_SECRET);
289
- });
290
-
291
- afterAll(() => {
292
- resetCapabilityTokenSecretForTests();
293
- });
294
-
295
- test("accepts a valid capability token and synthesizes an actor AuthContext", async () => {
296
- const { token } = mintHostBrowserCapability("guardian-cap-happy");
297
- const req = new Request("http://localhost/v1/host-browser-result", {
298
- method: "POST",
299
- headers: { Authorization: `Bearer ${token}` },
300
- });
301
-
302
- const result = await authenticateHostBrowserResultRequest(req);
303
- expect(result.ok).toBe(true);
304
- if (result.ok) {
305
- expect(result.context.principalType).toBe("actor");
306
- expect(result.context.assistantId).toBe(DAEMON_INTERNAL_ASSISTANT_ID);
307
- expect(result.context.actorPrincipalId).toBe("guardian-cap-happy");
308
- expect(result.context.scopeProfile).toBe("actor_client_v1");
309
- // The synthetic context must carry the scopes the route policy
310
- // requires — otherwise the router would 403 the POST even though
311
- // auth succeeded.
312
- expect(result.context.scopes.has("approval.write")).toBe(true);
313
- }
314
- });
315
-
316
- test("accepts a valid daemon-audience JWT (regression for the legacy path)", async () => {
274
+ describe("authenticateRequest for /v1/host-browser-result", () => {
275
+ test("accepts a valid daemon-audience JWT", async () => {
317
276
  const token = mintValidToken({ sub: "actor:self:jwt-principal" });
318
277
  const req = new Request("http://localhost/v1/host-browser-result", {
319
278
  method: "POST",
320
279
  headers: { Authorization: `Bearer ${token}` },
321
280
  });
322
281
 
323
- const result = await authenticateHostBrowserResultRequest(req);
282
+ const result = await authenticateRequest(req);
324
283
  expect(result.ok).toBe(true);
325
284
  if (result.ok) {
326
285
  expect(result.context.principalType).toBe("actor");
@@ -334,25 +293,21 @@ describe("authenticateHostBrowserResultRequest", () => {
334
293
  method: "POST",
335
294
  });
336
295
 
337
- const result = await authenticateHostBrowserResultRequest(req);
296
+ const result = await authenticateRequest(req);
338
297
  expect(result.ok).toBe(false);
339
298
  if (!result.ok) {
340
299
  expect(result.response.status).toBe(401);
341
300
  }
342
301
  });
343
302
 
344
- test("malformed bearer falls through to JWT path and 401s", async () => {
345
- // A bearer that is neither a valid capability token (bad HMAC) nor a
346
- // parseable JWT must fail the JWT path and return 401. This is the
347
- // primary regression guard against someone accidentally making the
348
- // capability-token branch "allow-anything" by swallowing
349
- // verification failures.
303
+ test("malformed bearer returns 401", async () => {
304
+ // A bearer that is not a parseable JWT must return 401.
350
305
  const req = new Request("http://localhost/v1/host-browser-result", {
351
306
  method: "POST",
352
307
  headers: { Authorization: "Bearer not-a-token.xxxxxxxxxxxxx" },
353
308
  });
354
309
 
355
- const result = await authenticateHostBrowserResultRequest(req);
310
+ const result = await authenticateRequest(req);
356
311
  expect(result.ok).toBe(false);
357
312
  if (!result.ok) {
358
313
  expect(result.response.status).toBe(401);
@@ -366,7 +321,7 @@ describe("authenticateHostBrowserResultRequest", () => {
366
321
  method: "POST",
367
322
  });
368
323
 
369
- const result = await authenticateHostBrowserResultRequest(req);
324
+ const result = await authenticateRequest(req);
370
325
  expect(result.ok).toBe(true);
371
326
  if (result.ok) {
372
327
  // Same synthetic context shape as authenticateRequest's dev
@@ -214,4 +214,68 @@ describe("enforcePolicy", () => {
214
214
  const result = enforcePolicy("stt/transcribe", ctx);
215
215
  expect(result).toBeNull();
216
216
  });
217
+
218
+ // -- internal/oauth/connect/start policy ----------------------------------
219
+
220
+ test("internal/oauth/connect/start is registered as a protected endpoint", () => {
221
+ authDisabled = false;
222
+ const policy = getPolicy("internal/oauth/connect/start");
223
+ expect(policy).toBeDefined();
224
+ expect(policy!.allowedPrincipalTypes).toContain("svc_gateway");
225
+ expect(policy!.allowedPrincipalTypes).not.toContain("actor");
226
+ expect(policy!.requiredScopes).toContain("internal.write");
227
+ });
228
+
229
+ test("internal/oauth/connect/start denies non-svc_gateway principals", () => {
230
+ authDisabled = false;
231
+ const ctx = buildTestContext({
232
+ principalType: "actor",
233
+ scopes: ["internal.write"],
234
+ });
235
+ const result = enforcePolicy("internal/oauth/connect/start", ctx);
236
+ expect(result).not.toBeNull();
237
+ expect(result!.status).toBe(403);
238
+ });
239
+
240
+ test("internal/oauth/connect/start allows svc_gateway with internal.write", () => {
241
+ authDisabled = false;
242
+ const ctx = buildTestContext({
243
+ principalType: "svc_gateway",
244
+ scopes: ["internal.write"],
245
+ });
246
+ const result = enforcePolicy("internal/oauth/connect/start", ctx);
247
+ expect(result).toBeNull();
248
+ });
249
+
250
+ // -- internal/oauth/connect/status policy ---------------------------------
251
+
252
+ test("internal/oauth/connect/status is registered as a protected endpoint", () => {
253
+ authDisabled = false;
254
+ const policy = getPolicy("internal/oauth/connect/status");
255
+ expect(policy).toBeDefined();
256
+ expect(policy!.allowedPrincipalTypes).toContain("svc_gateway");
257
+ expect(policy!.allowedPrincipalTypes).not.toContain("actor");
258
+ expect(policy!.requiredScopes).toContain("internal.write");
259
+ });
260
+
261
+ test("internal/oauth/connect/status denies non-svc_gateway principals", () => {
262
+ authDisabled = false;
263
+ const ctx = buildTestContext({
264
+ principalType: "actor",
265
+ scopes: ["internal.write"],
266
+ });
267
+ const result = enforcePolicy("internal/oauth/connect/status", ctx);
268
+ expect(result).not.toBeNull();
269
+ expect(result!.status).toBe(403);
270
+ });
271
+
272
+ test("internal/oauth/connect/status allows svc_gateway with internal.write", () => {
273
+ authDisabled = false;
274
+ const ctx = buildTestContext({
275
+ principalType: "svc_gateway",
276
+ scopes: ["internal.write"],
277
+ });
278
+ const result = enforcePolicy("internal/oauth/connect/status", ctx);
279
+ expect(result).toBeNull();
280
+ });
217
281
  });
@@ -25,7 +25,6 @@
25
25
  import { isHttpAuthDisabled } from "../../config/env.js";
26
26
  import { getLogger } from "../../util/logger.js";
27
27
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
28
- import { verifyHostBrowserCapability } from "../capability-tokens.js";
29
28
  import { extractBearerToken } from "../middleware/auth.js";
30
29
  import { buildAuthContext } from "./context.js";
31
30
  import { resolveScopeProfile } from "./scopes.js";
@@ -188,99 +187,4 @@ export function authenticateRequest(req: Request): AuthenticateResult {
188
187
  return { ok: true, context: contextResult.context };
189
188
  }
190
189
 
191
- // ---------------------------------------------------------------------------
192
- // Capability-token-aware auth for /v1/host-browser-result
193
- // ---------------------------------------------------------------------------
194
190
 
195
- /**
196
- * Build a synthetic AuthContext from a verified host_browser capability
197
- * claim. The resulting context is shaped to look like an
198
- * `actor_client_v1` actor so downstream route policy (which requires
199
- * `approval.write`) and `requireBoundGuardian` (which compares
200
- * `actorPrincipalId` against the bound guardian) both accept it.
201
- *
202
- * The capability token already carries its own HMAC-checked expiry, so
203
- * there is no policy-epoch gate to apply here — we pin `policyEpoch` to
204
- * `Number.MAX_SAFE_INTEGER` the same way the dev-bypass context does.
205
- */
206
- function buildCapabilityAuthContext(guardianId: string): AuthContext {
207
- return {
208
- subject: `actor:${DAEMON_INTERNAL_ASSISTANT_ID}:${guardianId}`,
209
- principalType: "actor",
210
- assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
211
- actorPrincipalId: guardianId,
212
- scopeProfile: "actor_client_v1",
213
- scopes: resolveScopeProfile("actor_client_v1"),
214
- policyEpoch: Number.MAX_SAFE_INTEGER,
215
- };
216
- }
217
-
218
- /**
219
- * Authenticate a request that is allowed to present either a JWT or a
220
- * host_browser capability token. This is the auth entry point for
221
- * `/v1/host-browser-result` POST specifically — the chrome extension
222
- * stores a capability token (minted by the
223
- * `/v1/browser-extension-pair` flow) rather than a daemon JWT, so the
224
- * POST fallback used when the `/v1/browser-relay` WebSocket is
225
- * unavailable would otherwise 401 through the JWT-only
226
- * `authenticateRequest` path.
227
- *
228
- * Order of operations (mirrors `handleBrowserRelayUpgrade`):
229
- * 1. Extract the bearer token. Missing header → 401.
230
- * 2. Try `verifyHostBrowserCapability(token)` first. If it succeeds,
231
- * derive `guardianId` from the capability claims and synthesize an
232
- * AuthContext.
233
- * 3. Otherwise fall through to the standard JWT path so daemon-minted
234
- * JWTs (gateway-proxied or direct) continue to work as a
235
- * regression-safe compatibility path.
236
- *
237
- * Dev bypass (`isHttpAuthDisabled()`) is honored the same way as
238
- * `authenticateRequest` — we delegate to it directly to pick up the
239
- * shared synthetic dev-bypass context.
240
- */
241
- export async function authenticateHostBrowserResultRequest(
242
- req: Request,
243
- ): Promise<AuthenticateResult> {
244
- if (isHttpAuthDisabled()) {
245
- return { ok: true, context: buildDevBypassContext() };
246
- }
247
-
248
- const rawToken = extractBearerToken(req);
249
- if (!rawToken) {
250
- log.warn(
251
- { reason: "missing_token", path: "/v1/host-browser-result" },
252
- "Host browser result auth denied: missing Authorization header",
253
- );
254
- return {
255
- ok: false,
256
- response: Response.json(
257
- {
258
- error: {
259
- code: "UNAUTHORIZED",
260
- message: "Missing Authorization header",
261
- },
262
- },
263
- { status: 401 },
264
- ),
265
- };
266
- }
267
-
268
- // 1) Capability-token path (self-hosted default). The chrome
269
- // extension presents the token it received from the native
270
- // messaging pair flow. We derive `actorPrincipalId` from the
271
- // capability claims directly — the claims are HMAC-signed by the
272
- // same daemon so there is no cross-tenant risk.
273
- const capabilityClaims = await verifyHostBrowserCapability(rawToken);
274
- if (capabilityClaims) {
275
- return {
276
- ok: true,
277
- context: buildCapabilityAuthContext(capabilityClaims.guardianId),
278
- };
279
- }
280
-
281
- // 2) JWT compatibility path. Fall back to the existing daemon/gateway
282
- // JWT verification so cloud callers and any legacy self-hosted
283
- // clients still holding a daemon JWT continue to work. Any 401
284
- // emitted here already includes the JWT-specific reason.
285
- return authenticateRequest(req);
286
- }