@vellumai/assistant 0.6.6 → 0.7.0

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 (1346) hide show
  1. package/AGENTS.md +20 -0
  2. package/ARCHITECTURE.md +45 -36
  3. package/Dockerfile +26 -6
  4. package/README.md +8 -10
  5. package/__tests__/permissions/gateway-threshold-reader.test.ts +14 -20
  6. package/bun.lock +306 -119
  7. package/docs/architecture/memory.md +1 -90
  8. package/docs/architecture/security.md +15 -30
  9. package/docs/credential-execution-service.md +7 -5
  10. package/docs/skills.md +10 -10
  11. package/docs/stt-provider-onboarding.md +17 -45
  12. package/examples/plugins/echo/bun.lock +25 -0
  13. package/knip.json +8 -22
  14. package/node_modules/@vellumai/ces-client/bun.lock +33 -0
  15. package/node_modules/@vellumai/ces-client/package.json +25 -0
  16. package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +631 -0
  17. package/node_modules/@vellumai/ces-client/src/__tests__/package-boundary.test.ts +138 -0
  18. package/node_modules/@vellumai/ces-client/src/credential-rpc.ts +13 -0
  19. package/node_modules/@vellumai/ces-client/src/http-credentials.ts +296 -0
  20. package/node_modules/@vellumai/ces-client/src/http-log-export.ts +111 -0
  21. package/node_modules/@vellumai/ces-client/src/index.ts +43 -0
  22. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +445 -0
  23. package/node_modules/@vellumai/credential-storage/src/__tests__/package-boundary.test.ts +32 -6
  24. package/node_modules/@vellumai/egress-proxy/src/__tests__/package-boundary.test.ts +32 -1
  25. package/node_modules/@vellumai/gateway-client/bun.lock +39 -0
  26. package/node_modules/@vellumai/gateway-client/package.json +23 -0
  27. package/node_modules/@vellumai/gateway-client/src/__tests__/gateway-client.test.ts +343 -0
  28. package/node_modules/@vellumai/gateway-client/src/__tests__/package-boundary.test.ts +140 -0
  29. package/node_modules/@vellumai/gateway-client/src/http-delivery.ts +422 -0
  30. package/node_modules/@vellumai/gateway-client/src/index.ts +35 -0
  31. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +331 -0
  32. package/node_modules/@vellumai/gateway-client/src/types.ts +131 -0
  33. package/node_modules/@vellumai/gateway-client/tsconfig.json +20 -0
  34. package/node_modules/@vellumai/{ces-contracts → service-contracts}/bun.lock +1 -1
  35. package/node_modules/@vellumai/{ces-contracts → service-contracts}/package.json +4 -2
  36. package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/__tests__/contracts.test.ts +5 -1
  37. package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +155 -0
  38. package/node_modules/@vellumai/service-contracts/src/credential-rpc.ts +23 -0
  39. package/node_modules/@vellumai/service-contracts/src/index.ts +25 -0
  40. package/node_modules/@vellumai/{ces-contracts/src/index.ts → service-contracts/src/transport.ts} +6 -28
  41. package/node_modules/@vellumai/service-contracts/src/trust-rules.ts +116 -0
  42. package/node_modules/@vellumai/service-contracts/tsconfig.json +20 -0
  43. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +891 -0
  44. package/node_modules/@vellumai/skill-host-contracts/bun.lock +24 -0
  45. package/node_modules/@vellumai/skill-host-contracts/package.json +18 -0
  46. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +91 -0
  47. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +1348 -0
  48. package/node_modules/@vellumai/skill-host-contracts/src/index.ts +6 -0
  49. package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +11 -0
  50. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +32 -0
  51. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +333 -0
  52. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +444 -0
  53. package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +20 -0
  54. package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +12 -0
  55. package/openapi.yaml +2855 -556
  56. package/package.json +13 -7
  57. package/scripts/check-circular-deps.ts +80 -0
  58. package/scripts/generate-openapi.ts +24 -7
  59. package/{src/memory/graph/inspect.ts → scripts/memory-inspect.ts} +27 -27
  60. package/src/__tests__/access-request-decision.test.ts +2 -11
  61. package/src/__tests__/acp-session.test.ts +4 -150
  62. package/src/__tests__/actor-token-service.test.ts +17 -678
  63. package/src/__tests__/agent-loop-callsite-precedence.test.ts +2 -6
  64. package/src/__tests__/agent-loop-override-profile.test.ts +404 -0
  65. package/src/__tests__/agent-loop-thinking.test.ts +4 -4
  66. package/src/__tests__/agent-wake-override-profile.test.ts +261 -0
  67. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -1
  68. package/src/__tests__/anthropic-provider.test.ts +127 -15
  69. package/src/__tests__/app-routes-csp.test.ts +106 -55
  70. package/src/__tests__/approval-cascade.test.ts +3 -355
  71. package/src/__tests__/approval-conversation-turn.test.ts +3 -8
  72. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +1 -1
  73. package/src/__tests__/approval-primitive.test.ts +2 -1
  74. package/src/__tests__/approval-routes-http.test.ts +34 -451
  75. package/src/__tests__/assistant-events-sse-hardening.test.ts +73 -80
  76. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -3
  77. package/src/__tests__/attachment-upload-trusted-source.test.ts +139 -0
  78. package/src/__tests__/attachments-store.test.ts +46 -1
  79. package/src/__tests__/audit-log-rotation.test.ts +2 -1
  80. package/src/__tests__/auto-analysis-end-to-end.test.ts +8 -20
  81. package/src/__tests__/background-shell-bash.test.ts +227 -0
  82. package/src/__tests__/background-shell-host-bash.test.ts +474 -0
  83. package/src/__tests__/background-tool-registry.test.ts +145 -0
  84. package/src/__tests__/background-tool-routes.test.ts +175 -0
  85. package/src/__tests__/btw-routes.test.ts +147 -183
  86. package/src/__tests__/call-controller.test.ts +15 -2
  87. package/src/__tests__/call-conversation-messages.test.ts +2 -1
  88. package/src/__tests__/call-domain.test.ts +2 -2
  89. package/src/__tests__/call-pointer-messages.test.ts +11 -13
  90. package/src/__tests__/call-recovery.test.ts +2 -1
  91. package/src/__tests__/call-routes-http.test.ts +3 -14
  92. package/src/__tests__/call-store.test.ts +2 -1
  93. package/src/__tests__/cancel-resolves-conversation-key.test.ts +31 -62
  94. package/src/__tests__/canonical-guardian-store.test.ts +2 -2
  95. package/src/__tests__/catalog-files.test.ts +0 -26
  96. package/src/__tests__/ces-rpc-credential-backend.test.ts +1 -1
  97. package/src/__tests__/channel-approval-routes.test.ts +79 -49
  98. package/src/__tests__/channel-approval.test.ts +9 -7
  99. package/src/__tests__/channel-approvals.test.ts +9 -180
  100. package/src/__tests__/channel-delivery-store.test.ts +11 -10
  101. package/src/__tests__/channel-guardian.test.ts +14 -25
  102. package/src/__tests__/channel-readiness-service.test.ts +8 -6
  103. package/src/__tests__/channel-reply-delivery.test.ts +3 -19
  104. package/src/__tests__/channel-retry-sweep.test.ts +2 -5
  105. package/src/__tests__/checker.test.ts +274 -3921
  106. package/src/__tests__/circuit-breaker-pipeline.test.ts +1 -1
  107. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +208 -0
  108. package/src/__tests__/cli.test.ts +1 -38
  109. package/src/__tests__/compaction-events.test.ts +0 -1
  110. package/src/__tests__/compaction-pipeline.test.ts +1 -1
  111. package/src/__tests__/compaction-strip-metadata-clear.test.ts +2 -2
  112. package/src/__tests__/compaction-timeout-recovery.test.ts +1 -1
  113. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -7
  114. package/src/__tests__/config-model-image-provider.test.ts +0 -1
  115. package/src/__tests__/config-schema-cmd.test.ts +1 -1
  116. package/src/__tests__/config-schema.test.ts +30 -221
  117. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +4 -25
  118. package/src/__tests__/contact-store-user-file.test.ts +2 -1
  119. package/src/__tests__/contacts-tools.test.ts +56 -29
  120. package/src/__tests__/contacts-write.test.ts +6 -61
  121. package/src/__tests__/context-search-agent-protocol.test.ts +230 -0
  122. package/src/__tests__/context-search-agent-runner.test.ts +998 -0
  123. package/src/__tests__/context-search-conversations-source.test.ts +320 -0
  124. package/src/__tests__/context-search-fanout.test.ts +380 -0
  125. package/src/__tests__/context-search-memory-source.test.ts +311 -0
  126. package/src/__tests__/context-search-pkb-source.test.ts +444 -0
  127. package/src/__tests__/context-search-types.test.ts +95 -0
  128. package/src/__tests__/context-search-workspace-source.test.ts +545 -0
  129. package/src/__tests__/context-window-manager.test.ts +25 -0
  130. package/src/__tests__/conversation-abort-tool-results.test.ts +10 -1
  131. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +631 -0
  132. package/src/__tests__/conversation-agent-loop-overflow.test.ts +15 -2
  133. package/src/__tests__/conversation-agent-loop.test.ts +24 -2
  134. package/src/__tests__/conversation-analysis-routes.test.ts +60 -82
  135. package/src/__tests__/conversation-attachments.test.ts +9 -20
  136. package/src/__tests__/conversation-attention-store.test.ts +2 -1
  137. package/src/__tests__/conversation-attention-telegram.test.ts +4 -2
  138. package/src/__tests__/conversation-clear-safety.test.ts +53 -95
  139. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -39
  140. package/src/__tests__/conversation-crud-inference-profile.test.ts +54 -0
  141. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +63 -157
  142. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  143. package/src/__tests__/conversation-disk-view.test.ts +5 -4
  144. package/src/__tests__/conversation-fork-crud.test.ts +26 -55
  145. package/src/__tests__/conversation-fork-route.test.ts +5 -74
  146. package/src/__tests__/conversation-inference-profile-list.test.ts +128 -0
  147. package/src/__tests__/conversation-inference-profile-route.test.ts +216 -0
  148. package/src/__tests__/conversation-init.benchmark.test.ts +4 -81
  149. package/src/__tests__/conversation-key-store-disk-view.test.ts +2 -1
  150. package/src/__tests__/conversation-lifecycle.test.ts +0 -1
  151. package/src/__tests__/conversation-list-source.test.ts +2 -2
  152. package/src/__tests__/conversation-load-history-repair.test.ts +0 -1
  153. package/src/__tests__/conversation-pairing.test.ts +0 -1
  154. package/src/__tests__/conversation-pre-run-repair.test.ts +137 -297
  155. package/src/__tests__/conversation-process-callsite.test.ts +0 -1
  156. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -1
  157. package/src/__tests__/conversation-queue.test.ts +1 -33
  158. package/src/__tests__/conversation-routes-disk-view.test.ts +124 -97
  159. package/src/__tests__/conversation-routes-guardian-reply.test.ts +80 -55
  160. package/src/__tests__/conversation-routes-slash-commands.test.ts +83 -12
  161. package/src/__tests__/conversation-runtime-assembly.test.ts +41 -84
  162. package/src/__tests__/conversation-slash-commands.test.ts +6 -43
  163. package/src/__tests__/conversation-slash-queue.test.ts +0 -1
  164. package/src/__tests__/conversation-slash-unknown.test.ts +0 -1
  165. package/src/__tests__/conversation-speed-override.test.ts +0 -1
  166. package/src/__tests__/conversation-starter-routes.test.ts +177 -55
  167. package/src/__tests__/conversation-starters-cadence.test.ts +2 -2
  168. package/src/__tests__/conversation-store.test.ts +2 -375
  169. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
  170. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +6 -6
  171. package/src/__tests__/conversation-unread-route.test.ts +1 -1
  172. package/src/__tests__/conversation-usage.test.ts +2 -1
  173. package/src/__tests__/conversation-wipe.test.ts +2 -103
  174. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -1
  175. package/src/__tests__/conversation-workspace-injection.test.ts +0 -1
  176. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -1
  177. package/src/__tests__/conversations-defer-cli.test.ts +150 -0
  178. package/src/__tests__/credential-execution-admin-cli.test.ts +1 -1
  179. package/src/__tests__/credential-execution-api-key-propagation.test.ts +2 -2
  180. package/src/__tests__/credential-execution-approval-bridge.test.ts +22 -289
  181. package/src/__tests__/credential-execution-client.test.ts +1 -1
  182. package/src/__tests__/credential-execution-managed-contract.test.ts +1 -1
  183. package/src/__tests__/credential-security-invariants.test.ts +14 -0
  184. package/src/__tests__/credentials-cli.test.ts +45 -21
  185. package/src/__tests__/daemon-credential-client.test.ts +23 -108
  186. package/src/__tests__/db-acp-history.test.ts +284 -0
  187. package/src/__tests__/db-activation-state.test.ts +240 -0
  188. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +2 -1
  189. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +248 -0
  190. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +2 -1
  191. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +116 -0
  192. package/src/__tests__/db-rename-inference-profile-snake-case-migration.test.ts +132 -0
  193. package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
  194. package/src/__tests__/delete-propagation.test.ts +3 -2
  195. package/src/__tests__/deterministic-verification-control-plane.test.ts +39 -32
  196. package/src/__tests__/dm-backfill.test.ts +3 -2
  197. package/src/__tests__/edit-propagation.test.ts +5 -7
  198. package/src/__tests__/embedding-managed-proxy-selection.test.ts +1 -1
  199. package/src/__tests__/empty-response-pipeline.test.ts +1 -1
  200. package/src/__tests__/events-client-registration.test.ts +297 -0
  201. package/src/__tests__/file-write-tool.test.ts +2 -4
  202. package/src/__tests__/filing-service.test.ts +144 -17
  203. package/src/__tests__/followup-tools.test.ts +2 -1
  204. package/src/__tests__/gateway-client-managed-outbound.test.ts +8 -12
  205. package/src/__tests__/gateway-only-enforcement.test.ts +2 -6
  206. package/src/__tests__/gateway-only-guard.test.ts +4 -3
  207. package/src/__tests__/gemini-provider.test.ts +276 -10
  208. package/src/__tests__/graph-extraction-event-date.test.ts +30 -0
  209. package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -1
  210. package/src/__tests__/guardian-action-followup-executor.test.ts +2 -2
  211. package/src/__tests__/guardian-action-followup-store.test.ts +2 -1
  212. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +9 -9
  213. package/src/__tests__/guardian-action-late-reply.test.ts +2 -1
  214. package/src/__tests__/guardian-action-store.test.ts +2 -1
  215. package/src/__tests__/guardian-action-sweep.test.ts +9 -8
  216. package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -1
  217. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +21 -118
  218. package/src/__tests__/guardian-dispatch.test.ts +14 -11
  219. package/src/__tests__/guardian-grant-minting.test.ts +9 -15
  220. package/src/__tests__/guardian-outbound-http.test.ts +71 -106
  221. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -2
  222. package/src/__tests__/guardian-routing-invariants.test.ts +34 -90
  223. package/src/__tests__/guardian-routing-state.test.ts +14 -22
  224. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -2
  225. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +253 -0
  226. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +8 -4
  227. package/src/__tests__/heartbeat-service.test.ts +39 -21
  228. package/src/__tests__/helpers/call-route-handler.ts +72 -0
  229. package/src/__tests__/helpers/channel-test-adapter.ts +161 -0
  230. package/src/__tests__/helpers/gateway-classify-mock.ts +67 -0
  231. package/src/__tests__/helpers/mock-logger.ts +36 -0
  232. package/src/__tests__/history-repair-pipeline.test.ts +1 -1
  233. package/src/__tests__/home-state-routes.test.ts +10 -31
  234. package/src/__tests__/host-browser-e2e-cloud.test.ts +2 -1
  235. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +12 -2
  236. package/src/__tests__/host-browser-routes.test.ts +36 -91
  237. package/src/__tests__/host-browser-ws-events-e2e.test.ts +10 -2
  238. package/src/__tests__/host-proxy-interface.test.ts +3 -3
  239. package/src/__tests__/host-shell-tool.test.ts +2 -4
  240. package/src/__tests__/host-transfer-pending-interactions.test.ts +160 -0
  241. package/src/__tests__/host-transfer-proxy.test.ts +733 -0
  242. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  243. package/src/__tests__/http-user-message-parity.test.ts +20 -11
  244. package/src/__tests__/inbound-invite-redemption.test.ts +3 -2
  245. package/src/__tests__/injector-chain.test.ts +16 -17
  246. package/src/__tests__/inline-skill-load-permissions.test.ts +41 -206
  247. package/src/__tests__/install-skill-routing.test.ts +1 -1
  248. package/src/__tests__/invite-redemption-service.test.ts +2 -1
  249. package/src/__tests__/invite-routes-http.test.ts +80 -12
  250. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +2 -1
  251. package/src/__tests__/jobs-store-upsert-debounced.test.ts +2 -1
  252. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +157 -0
  253. package/src/__tests__/list-messages-attachments.test.ts +52 -55
  254. package/src/__tests__/list-messages-page-latest.test.ts +283 -0
  255. package/src/__tests__/list-messages-tool-merge.test.ts +16 -17
  256. package/src/__tests__/llm-call-pipeline.test.ts +7 -8
  257. package/src/__tests__/llm-context-normalization.test.ts +69 -4
  258. package/src/__tests__/llm-context-route-provider.test.ts +39 -113
  259. package/src/__tests__/llm-request-log-turn-query.test.ts +2 -1
  260. package/src/__tests__/llm-resolver.test.ts +211 -0
  261. package/src/__tests__/llm-schema.test.ts +57 -1
  262. package/src/__tests__/llm-usage-store.test.ts +2 -1
  263. package/src/__tests__/log-export-workspace.test.ts +28 -17
  264. package/src/__tests__/mcp-abort-signal.test.ts +2 -3
  265. package/src/__tests__/mcp-client-auth.test.ts +2 -3
  266. package/src/__tests__/memory-admin-recall.test.ts +221 -0
  267. package/src/__tests__/memory-recall-log-store.test.ts +2 -1
  268. package/src/__tests__/memory-retrieval-pipeline.test.ts +6 -8
  269. package/src/__tests__/memory-upsert-concurrency.test.ts +2 -1
  270. package/src/__tests__/migration-cross-version-compatibility.test.ts +14 -13
  271. package/src/__tests__/migration-export-http.test.ts +17 -17
  272. package/src/__tests__/migration-export-to-gcs.test.ts +491 -0
  273. package/src/__tests__/migration-import-commit-http.test.ts +16 -16
  274. package/src/__tests__/migration-import-from-gcs.test.ts +533 -0
  275. package/src/__tests__/migration-import-from-url.test.ts +16 -23
  276. package/src/__tests__/migration-import-preflight-http.test.ts +13 -13
  277. package/src/__tests__/migration-jobs-status.test.ts +164 -0
  278. package/src/__tests__/migration-validate-http.test.ts +48 -83
  279. package/src/__tests__/mock-gateway-ipc.ts +32 -62
  280. package/src/__tests__/model-intents.test.ts +15 -2
  281. package/src/__tests__/nl-approval-parser.test.ts +13 -17
  282. package/src/__tests__/non-member-access-request.test.ts +13 -5
  283. package/src/__tests__/notification-guardian-path.test.ts +15 -8
  284. package/src/__tests__/notification-schedule-notify-dedup.test.ts +2 -1
  285. package/src/__tests__/notification-telegram-adapter.test.ts +57 -55
  286. package/src/__tests__/oauth-apps-routes.test.ts +76 -122
  287. package/src/__tests__/oauth-cli.test.ts +14 -1
  288. package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
  289. package/src/__tests__/oauth-provider-visibility.test.ts +3 -1
  290. package/src/__tests__/oauth-providers-routes.test.ts +78 -101
  291. package/src/__tests__/oauth-store.test.ts +3 -1
  292. package/src/__tests__/oauth2-gateway-transport.test.ts +6 -3
  293. package/src/__tests__/openai-provider.test.ts +105 -6
  294. package/src/__tests__/openai-responses-provider.test.ts +146 -4
  295. package/src/__tests__/openrouter-provider-only.test.ts +22 -4
  296. package/src/__tests__/overflow-reduce-pipeline.test.ts +4 -9
  297. package/src/__tests__/permission-types.test.ts +3 -18
  298. package/src/__tests__/persistence-pipeline.test.ts +3 -2
  299. package/src/__tests__/pipeline-runner.test.ts +1 -1
  300. package/src/__tests__/platform-bash-auto-approve.test.ts +27 -20
  301. package/src/__tests__/platform.test.ts +11 -63
  302. package/src/__tests__/playbook-execution.test.ts +2 -1
  303. package/src/__tests__/playbook-tools.test.ts +2 -1
  304. package/src/__tests__/plugin-bootstrap.test.ts +51 -5
  305. package/src/__tests__/plugin-registry.test.ts +30 -0
  306. package/src/__tests__/plugin-route-contribution.test.ts +17 -11
  307. package/src/__tests__/plugin-skill-contribution.test.ts +3 -3
  308. package/src/__tests__/plugin-tool-contribution.test.ts +10 -4
  309. package/src/__tests__/plugin-types.test.ts +1 -1
  310. package/src/__tests__/pricing.test.ts +151 -2
  311. package/src/__tests__/profiler-routes.test.ts +112 -177
  312. package/src/__tests__/provider-send-message-override-profile.test.ts +223 -0
  313. package/src/__tests__/proxy-approval-callback.test.ts +6 -554
  314. package/src/__tests__/qdrant-collection-migration.test.ts +7 -7
  315. package/src/__tests__/reaction-persistence.test.ts +3 -2
  316. package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
  317. package/src/__tests__/recording-handler.test.ts +0 -2
  318. package/src/__tests__/registry.test.ts +1 -0
  319. package/src/__tests__/relay-server.test.ts +19 -4
  320. package/src/__tests__/require-fresh-approval.test.ts +19 -168
  321. package/src/__tests__/resolve-trust-class.test.ts +2 -1
  322. package/src/__tests__/retry-thinking-tool-choice.test.ts +19 -7
  323. package/src/__tests__/retry-verbosity-normalization.test.ts +139 -0
  324. package/src/__tests__/runtime-attachment-metadata.test.ts +26 -6
  325. package/src/__tests__/runtime-events-sse-parity.test.ts +12 -13
  326. package/src/__tests__/runtime-events-sse.test.ts +13 -21
  327. package/src/__tests__/schedule-routes.test.ts +226 -129
  328. package/src/__tests__/schedule-store.test.ts +119 -1
  329. package/src/__tests__/schedule-tools.test.ts +2 -1
  330. package/src/__tests__/scheduler-recurrence.test.ts +2 -1
  331. package/src/__tests__/scheduler-reuse-conversation.test.ts +2 -1
  332. package/src/__tests__/scheduler-wake.test.ts +356 -0
  333. package/src/__tests__/scoped-approval-grants.test.ts +2 -1
  334. package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -1
  335. package/src/__tests__/secret-detection-handler.test.ts +2 -9
  336. package/src/__tests__/secret-ingress-http.test.ts +38 -21
  337. package/src/__tests__/secret-routes-managed-proxy.test.ts +46 -102
  338. package/src/__tests__/secret-scanner-executor.test.ts +1 -2
  339. package/src/__tests__/send-endpoint-busy.test.ts +38 -25
  340. package/src/__tests__/sequence-store.test.ts +2 -1
  341. package/src/__tests__/server-history-render.test.ts +2 -2
  342. package/src/__tests__/service-contracts-import-guard.test.ts +185 -0
  343. package/src/__tests__/set-permission-mode.test.ts +0 -10
  344. package/src/__tests__/settings-routes.test.ts +35 -68
  345. package/src/__tests__/skill-boundary-guard.test.ts +105 -0
  346. package/src/__tests__/skill-load-inline-command.test.ts +2 -2
  347. package/src/__tests__/skill-load-inline-includes.test.ts +2 -2
  348. package/src/__tests__/skill-runtime-path.test.ts +64 -0
  349. package/src/__tests__/skills-file-content-endpoint.test.ts +0 -2
  350. package/src/__tests__/slack-inbound-verification.test.ts +11 -2
  351. package/src/__tests__/slack-messaging-token-resolution.test.ts +1 -3
  352. package/src/__tests__/slack-reaction-approvals.test.ts +4 -4
  353. package/src/__tests__/slack-share-routes.test.ts +37 -72
  354. package/src/__tests__/subagent-call-site-routing.test.ts +79 -0
  355. package/src/__tests__/subagent-fork-spawn.test.ts +20 -28
  356. package/src/__tests__/subagent-notify-parent.test.ts +6 -29
  357. package/src/__tests__/subagent-role-registry.test.ts +3 -3
  358. package/src/__tests__/subagent-spawn-tool-fork.test.ts +52 -104
  359. package/src/__tests__/subagent-tools.test.ts +0 -1
  360. package/src/__tests__/suggestion-routes.test.ts +55 -62
  361. package/src/__tests__/task-compiler.test.ts +2 -1
  362. package/src/__tests__/task-management-tools.test.ts +2 -1
  363. package/src/__tests__/task-memory-cleanup.test.ts +2 -1
  364. package/src/__tests__/task-scheduler.test.ts +2 -1
  365. package/src/__tests__/telegram-config.test.ts +0 -1
  366. package/src/__tests__/terminal-tools.test.ts +5 -314
  367. package/src/__tests__/test-preload.ts +0 -11
  368. package/src/__tests__/thread-backfill.test.ts +3 -2
  369. package/src/__tests__/token-estimate-pipeline.test.ts +68 -15
  370. package/src/__tests__/tool-approval-handler.test.ts +21 -63
  371. package/src/__tests__/tool-audit-listener.test.ts +3 -3
  372. package/src/__tests__/tool-domain-event-publisher.test.ts +3 -3
  373. package/src/__tests__/tool-error-pipeline.test.ts +6 -6
  374. package/src/__tests__/tool-execute-pipeline.test.ts +6 -8
  375. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +64 -1
  376. package/src/__tests__/tool-executor-lifecycle-events.test.ts +28 -56
  377. package/src/__tests__/tool-executor.test.ts +322 -1633
  378. package/src/__tests__/tool-grant-request-escalation.test.ts +90 -311
  379. package/src/__tests__/tool-result-truncate-pipeline.test.ts +1 -1
  380. package/src/__tests__/trust-context-guards.test.ts +1 -1
  381. package/src/__tests__/trusted-contact-approval-notifier.test.ts +7 -15
  382. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +178 -354
  383. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +3 -2
  384. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -2
  385. package/src/__tests__/trusted-contact-verification.test.ts +2 -1
  386. package/src/__tests__/turn-boundary-resolution.test.ts +2 -1
  387. package/src/__tests__/twilio-routes.test.ts +25 -66
  388. package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -7
  389. package/src/__tests__/usage-routes.test.ts +73 -90
  390. package/src/__tests__/user-plugin-loader.test.ts +54 -12
  391. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +2 -2
  392. package/src/__tests__/verification-control-plane-policy.test.ts +95 -14
  393. package/src/__tests__/voice-ingress-preflight.test.ts +5 -5
  394. package/src/__tests__/voice-invite-redemption.test.ts +2 -1
  395. package/src/__tests__/voice-scoped-grant-consumer.test.ts +3 -3
  396. package/src/__tests__/voice-session-bridge.test.ts +285 -106
  397. package/src/__tests__/volume-security-guard.test.ts +0 -2
  398. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -1
  399. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +3 -1
  400. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +2 -1
  401. package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +1 -1
  402. package/src/__tests__/workspace-migration-052-seed-default-inference-profiles.test.ts +260 -0
  403. package/src/__tests__/workspace-migration-053-release-notes-acp-codex.test.ts +225 -0
  404. package/src/__tests__/workspace-migration-054-seed-recall-callsite.test.ts +235 -0
  405. package/src/__tests__/workspace-migration-055-release-notes-agentic-recall.test.ts +128 -0
  406. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +232 -0
  407. package/src/__tests__/workspace-migration-acp-sessions-ui.test.ts +144 -0
  408. package/src/__tests__/workspace-migration-drop-user-md.test.ts +1 -1
  409. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +274 -0
  410. package/src/acp/__tests__/client-handler.test.ts +64 -0
  411. package/src/acp/__tests__/helpers/acp-config-stub.ts +62 -0
  412. package/src/acp/__tests__/helpers/which-stub.ts +45 -0
  413. package/src/acp/__tests__/session-manager-persistence.test.ts +366 -0
  414. package/src/acp/__tests__/session-manager-startup.test.ts +159 -0
  415. package/src/acp/__tests__/session-manager.test.ts +83 -0
  416. package/src/acp/client-handler.ts +23 -139
  417. package/src/acp/resolve-agent.test.ts +291 -0
  418. package/src/acp/resolve-agent.ts +176 -0
  419. package/src/acp/session-manager.ts +166 -7
  420. package/src/acp/types.ts +2 -50
  421. package/src/agent/loop.ts +37 -14
  422. package/src/agent/message-types.ts +0 -2
  423. package/src/approvals/AGENTS.md +1 -1
  424. package/src/approvals/__tests__/guardian-feed-event.test.ts +1 -9
  425. package/src/approvals/approval-primitive.ts +3 -20
  426. package/src/approvals/guardian-decision-primitive.ts +37 -68
  427. package/src/approvals/guardian-request-resolvers.ts +29 -103
  428. package/src/avatar/character-components.ts +6 -6
  429. package/src/{config/bundled-skills/settings/tools → avatar}/identity-avatar.ts +1 -1
  430. package/src/backup/__tests__/backup-worker.test.ts +0 -2
  431. package/src/backup/__tests__/paths.test.ts +3 -2
  432. package/src/backup/backup-worker.ts +1 -10
  433. package/src/backup/paths.ts +2 -18
  434. package/src/backup/restore.ts +7 -11
  435. package/src/browser/__tests__/operations.test.ts +0 -35
  436. package/src/browser/operations.ts +1 -47
  437. package/src/bundler/package-resolver.ts +2 -6
  438. package/src/calls/active-call-lease.ts +1 -1
  439. package/src/calls/call-constants.ts +1 -1
  440. package/src/calls/call-controller.ts +1 -5
  441. package/src/calls/call-domain.ts +14 -14
  442. package/src/calls/call-pointer-messages.ts +4 -9
  443. package/src/calls/call-store.ts +2 -1
  444. package/src/calls/guardian-action-sweep.ts +9 -25
  445. package/src/calls/guardian-dispatch.ts +1 -20
  446. package/src/calls/media-stream-audio-transcode.ts +2 -41
  447. package/src/calls/media-stream-server.ts +2 -3
  448. package/src/calls/media-stream-stt-session.ts +1 -3
  449. package/src/calls/relay-access-wait.ts +5 -8
  450. package/src/calls/relay-server.ts +15 -18
  451. package/src/calls/relay-setup-router.ts +2 -2
  452. package/src/calls/relay-verification.ts +4 -4
  453. package/src/calls/twilio-rest.ts +1 -1
  454. package/src/calls/twilio-routes.ts +160 -78
  455. package/src/calls/voice-control-protocol.ts +10 -10
  456. package/src/calls/voice-ingress-preflight.ts +2 -2
  457. package/src/calls/voice-session-bridge.ts +137 -42
  458. package/src/channels/__tests__/types.test.ts +25 -3
  459. package/src/channels/permission-profiles.ts +2 -72
  460. package/src/channels/types.ts +42 -26
  461. package/src/cli/AGENTS.md +1 -0
  462. package/src/cli/__tests__/notifications.test.ts +12 -10
  463. package/src/cli/commands/__tests__/attachment.test.ts +14 -8
  464. package/src/cli/commands/__tests__/backup.test.ts +3 -14
  465. package/src/cli/commands/__tests__/browser.test.ts +36 -31
  466. package/src/cli/commands/__tests__/cache.test.ts +23 -18
  467. package/src/cli/commands/__tests__/memory-v2.test.ts +396 -0
  468. package/src/cli/commands/__tests__/task.test.ts +36 -35
  469. package/src/cli/commands/__tests__/trust.test.ts +602 -0
  470. package/src/cli/commands/__tests__/ui-confirm.test.ts +14 -14
  471. package/src/cli/commands/__tests__/ui.test.ts +17 -17
  472. package/src/cli/commands/__tests__/watchers.test.ts +29 -29
  473. package/src/cli/commands/__tests__/webhooks.test.ts +544 -0
  474. package/src/cli/commands/attachment.ts +12 -8
  475. package/src/cli/commands/auth.ts +1 -1
  476. package/src/cli/commands/avatar.ts +192 -9
  477. package/src/cli/commands/backup.ts +14 -44
  478. package/src/cli/commands/browser.ts +52 -4
  479. package/src/cli/commands/cache.ts +7 -5
  480. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  481. package/src/cli/commands/clients.ts +11 -12
  482. package/src/cli/commands/completions.ts +1 -1
  483. package/src/cli/commands/contacts.ts +10 -10
  484. package/src/cli/commands/conversations-defer.ts +364 -0
  485. package/src/cli/commands/conversations-import.ts +2 -3
  486. package/src/cli/commands/conversations.ts +63 -53
  487. package/src/cli/commands/credential-execution.ts +1 -1
  488. package/src/cli/commands/credentials.ts +139 -5
  489. package/src/cli/commands/default-action.ts +1 -1
  490. package/src/cli/commands/domain.ts +2 -2
  491. package/src/cli/commands/email.ts +7 -7
  492. package/src/cli/commands/image-generation.ts +1 -1
  493. package/src/cli/commands/keys.ts +2 -2
  494. package/src/cli/commands/mcp.ts +1 -1
  495. package/src/cli/commands/memory-v2.ts +343 -0
  496. package/src/cli/commands/memory.ts +8 -8
  497. package/src/cli/commands/notifications.ts +21 -20
  498. package/src/cli/commands/oauth/__tests__/connect.test.ts +23 -5
  499. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +1 -1
  500. package/src/cli/commands/oauth/__tests__/mode.test.ts +1 -1
  501. package/src/cli/commands/oauth/__tests__/status.test.ts +1 -1
  502. package/src/cli/commands/oauth/__tests__/token.test.ts +1 -1
  503. package/src/cli/commands/oauth/connect.ts +2 -2
  504. package/src/cli/commands/oauth/shared.ts +29 -2
  505. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -6
  506. package/src/cli/commands/platform/__tests__/connect.test.ts +23 -11
  507. package/src/cli/commands/platform/__tests__/disconnect.test.ts +22 -10
  508. package/src/cli/commands/platform/__tests__/status.test.ts +22 -10
  509. package/src/cli/commands/platform/connect.ts +3 -3
  510. package/src/cli/commands/platform/disconnect.ts +4 -6
  511. package/src/cli/commands/platform/index.ts +12 -10
  512. package/src/cli/commands/routes.ts +7 -1
  513. package/src/cli/commands/sequence.ts +7 -7
  514. package/src/cli/commands/skills.ts +188 -82
  515. package/src/cli/commands/task.ts +12 -10
  516. package/src/cli/commands/trust.ts +460 -162
  517. package/src/cli/commands/ui.ts +3 -3
  518. package/src/cli/commands/usage.ts +10 -5
  519. package/src/cli/commands/watchers.ts +8 -8
  520. package/src/cli/commands/webhooks.ts +270 -0
  521. package/src/cli/lib/daemon-avatar-client.ts +37 -0
  522. package/src/cli/lib/daemon-credential-client.ts +27 -189
  523. package/src/cli/lib/ipc-params.ts +22 -0
  524. package/src/cli/program.ts +4 -0
  525. package/src/cli.ts +1 -61
  526. package/src/config/acp-defaults.test.ts +57 -0
  527. package/src/config/acp-defaults.ts +40 -0
  528. package/src/config/acp-schema.ts +1 -1
  529. package/src/config/assistant-feature-flags.ts +18 -142
  530. package/src/config/bundled-skills/acp/SKILL.md +44 -16
  531. package/src/config/bundled-skills/acp/TOOLS.json +45 -1
  532. package/src/config/bundled-skills/acp/tools/acp-list-agents.ts +12 -0
  533. package/src/config/bundled-skills/acp/tools/acp-steer.ts +12 -0
  534. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +14 -14
  535. package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -4
  536. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +11 -6
  537. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +6 -6
  538. package/src/config/bundled-skills/media-processing/services/reduce.ts +0 -13
  539. package/src/config/bundled-skills/messaging/tools/gmail-mime-helpers.ts +1 -1
  540. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +1 -1
  541. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -1
  542. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +1 -1
  543. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -1
  544. package/src/config/bundled-skills/settings/SKILL.md +2 -17
  545. package/src/config/bundled-skills/settings/TOOLS.json +0 -56
  546. package/src/config/bundled-skills/subagent/SKILL.md +2 -0
  547. package/src/config/bundled-tool-registry.ts +4 -6
  548. package/src/config/env.ts +7 -8
  549. package/src/config/feature-flag-registry.json +16 -24
  550. package/src/config/llm-resolver.ts +51 -33
  551. package/src/config/loader.ts +12 -15
  552. package/src/config/schema.ts +5 -72
  553. package/src/config/schemas/__tests__/filing.test.ts +58 -0
  554. package/src/config/schemas/__tests__/memory-v2.test.ts +186 -0
  555. package/src/config/schemas/filing.ts +12 -0
  556. package/src/config/schemas/host-browser.ts +2 -2
  557. package/src/config/schemas/inference.ts +0 -2
  558. package/src/config/schemas/ingress.ts +1 -1
  559. package/src/config/schemas/llm.ts +51 -9
  560. package/src/config/schemas/memory-storage.ts +1 -1
  561. package/src/config/schemas/memory-v2.ts +176 -0
  562. package/src/config/schemas/memory.ts +2 -0
  563. package/src/config/schemas/security.ts +0 -60
  564. package/src/config/schemas/services.ts +46 -7
  565. package/src/config/skills.ts +1 -1
  566. package/src/config/types.ts +0 -41
  567. package/src/contacts/contact-store.ts +2 -2
  568. package/src/contacts/contacts-write.ts +0 -38
  569. package/src/contacts/types.ts +8 -10
  570. package/src/context/token-estimator.ts +1 -1
  571. package/src/context/tool-result-truncation.ts +1 -1
  572. package/src/context/window-manager.ts +1 -1
  573. package/src/credential-execution/approval-bridge.ts +7 -69
  574. package/src/credential-execution/client.ts +17 -422
  575. package/src/credential-execution/feature-gates.ts +1 -2
  576. package/src/credential-execution/managed-catalog.ts +1 -1
  577. package/src/credential-health/credential-health-service.ts +1 -1
  578. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -13
  579. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
  580. package/src/daemon/__tests__/daemon-skill-host.test.ts +272 -0
  581. package/src/daemon/__tests__/meet-host-supervisor.test.ts +587 -0
  582. package/src/daemon/__tests__/meet-manifest-loader.test.ts +463 -0
  583. package/src/daemon/approval-generators.ts +2 -14
  584. package/src/daemon/classifier.ts +0 -106
  585. package/src/daemon/config-watcher.ts +14 -54
  586. package/src/daemon/connection-policy.ts +0 -14
  587. package/src/daemon/conversation-agent-loop-handlers.ts +37 -6
  588. package/src/daemon/conversation-agent-loop.ts +164 -53
  589. package/src/daemon/conversation-attachments.ts +5 -81
  590. package/src/daemon/conversation-error.ts +9 -5
  591. package/src/daemon/conversation-history.ts +1 -1
  592. package/src/daemon/conversation-launch.ts +1 -1
  593. package/src/daemon/conversation-messaging.ts +1 -1
  594. package/src/daemon/conversation-notifiers.ts +1 -1
  595. package/src/daemon/conversation-process.ts +9 -13
  596. package/src/daemon/conversation-runtime-assembly.ts +26 -88
  597. package/src/daemon/conversation-slash.ts +4 -160
  598. package/src/daemon/conversation-store.ts +368 -0
  599. package/src/daemon/conversation-surfaces.ts +5 -4
  600. package/src/daemon/conversation-tool-setup.ts +23 -172
  601. package/src/daemon/conversation.ts +46 -182
  602. package/src/daemon/daemon-control.ts +3 -3
  603. package/src/daemon/daemon-skill-host.ts +262 -0
  604. package/src/daemon/external-plugins-bootstrap.ts +67 -13
  605. package/src/daemon/handlers/config-channels.ts +2 -2
  606. package/src/daemon/handlers/config-embeddings.ts +1 -1
  607. package/src/daemon/handlers/config-ingress.ts +24 -2
  608. package/src/daemon/handlers/config-model.test.ts +17 -0
  609. package/src/daemon/handlers/config-model.ts +7 -52
  610. package/src/daemon/handlers/config-telegram.ts +6 -53
  611. package/src/daemon/handlers/config-voice.ts +1 -1
  612. package/src/daemon/handlers/conversations.ts +22 -156
  613. package/src/daemon/handlers/recording.ts +1 -1
  614. package/src/daemon/handlers/shared.ts +34 -35
  615. package/src/daemon/handlers/skills.ts +15 -23
  616. package/src/daemon/host-transfer-proxy.ts +500 -0
  617. package/src/daemon/lifecycle.ts +23 -258
  618. package/src/daemon/meet-host-startup.ts +51 -0
  619. package/src/daemon/meet-host-supervisor.ts +781 -0
  620. package/src/daemon/meet-manifest-loader.ts +410 -0
  621. package/src/daemon/memory-v2-startup.ts +35 -0
  622. package/src/daemon/message-protocol.ts +4 -7
  623. package/src/daemon/message-types/acp.ts +1 -0
  624. package/src/daemon/message-types/conversations.ts +16 -2
  625. package/src/daemon/message-types/host-transfer.ts +41 -0
  626. package/src/daemon/message-types/integrations.ts +6 -0
  627. package/src/daemon/message-types/messages.ts +14 -14
  628. package/src/daemon/message-types/schedules.ts +1 -0
  629. package/src/daemon/message-types/settings.ts +0 -6
  630. package/src/daemon/message-types/shared.ts +5 -2
  631. package/src/daemon/message-types/subagents.ts +2 -1
  632. package/src/daemon/message-types/workspace.ts +0 -2
  633. package/src/daemon/pkb-reminder-builder.test.ts +13 -12
  634. package/src/daemon/pkb-reminder-builder.ts +8 -16
  635. package/src/daemon/process-message.ts +616 -0
  636. package/src/daemon/providers-setup.ts +14 -6
  637. package/src/daemon/server.ts +79 -1274
  638. package/src/daemon/shutdown-handlers.ts +1 -1
  639. package/src/daemon/startup-error.ts +1 -1
  640. package/src/daemon/trust-context.ts +32 -0
  641. package/src/daemon/wake-target-adapter.ts +223 -0
  642. package/src/email/feature-gate.ts +1 -1
  643. package/src/events/domain-events.ts +1 -8
  644. package/src/events/tool-audit-listener.ts +2 -8
  645. package/src/events/tool-metrics-listener.ts +1 -4
  646. package/src/filing/filing-service.ts +194 -54
  647. package/src/followups/followup-store.ts +3 -71
  648. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +89 -21
  649. package/src/heartbeat/heartbeat-service.ts +32 -11
  650. package/src/home/__tests__/phase5-exit-criteria.test.ts +18 -1
  651. package/src/home/__tests__/rollup-producer.test.ts +67 -2
  652. package/src/home/assistant-feed-authoring.ts +8 -1
  653. package/src/home/feed-types.ts +1 -1
  654. package/src/home/relationship-state-writer.ts +1 -1
  655. package/src/home/rewrite-feed-title.ts +58 -0
  656. package/src/home/rollup-producer.ts +16 -3
  657. package/src/inbound/platform-callback-registration.ts +1 -17
  658. package/src/ipc/__tests__/attachment-ipc.test.ts +128 -66
  659. package/src/ipc/__tests__/browser-ipc.test.ts +75 -51
  660. package/src/ipc/__tests__/cache-ipc.test.ts +52 -107
  661. package/src/ipc/__tests__/cli-ipc.test.ts +9 -6
  662. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +254 -0
  663. package/src/ipc/__tests__/skill-server.test.ts +182 -0
  664. package/src/ipc/__tests__/socket-path.test.ts +69 -23
  665. package/src/ipc/__tests__/ui-request-route.test.ts +241 -216
  666. package/src/ipc/__tests__/watcher-ipc.test.ts +33 -33
  667. package/src/ipc/assistant-server.ts +450 -0
  668. package/src/ipc/cli-client.ts +3 -3
  669. package/src/ipc/gateway-client.test.ts +131 -0
  670. package/src/ipc/gateway-client.ts +98 -123
  671. package/src/ipc/ipc-framing.ts +281 -0
  672. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +152 -0
  673. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +219 -0
  674. package/src/ipc/routes/db-proxy.ts +73 -0
  675. package/src/ipc/routes/route-adapter.ts +32 -0
  676. package/src/ipc/routes/trust-rules.test.ts +218 -0
  677. package/src/ipc/skill-ipc-types.ts +13 -0
  678. package/src/ipc/skill-routes/__tests__/config.test.ts +146 -0
  679. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +402 -0
  680. package/src/ipc/skill-routes/__tests__/identity.test.ts +81 -0
  681. package/src/ipc/skill-routes/__tests__/log.test.ts +133 -0
  682. package/src/ipc/skill-routes/__tests__/memory.test.ts +178 -0
  683. package/src/ipc/skill-routes/__tests__/platform.test.ts +111 -0
  684. package/src/ipc/skill-routes/__tests__/providers.test.ts +265 -0
  685. package/src/ipc/skill-routes/__tests__/registries.test.ts +361 -0
  686. package/src/ipc/skill-routes/config.ts +47 -0
  687. package/src/ipc/skill-routes/events.ts +131 -0
  688. package/src/ipc/skill-routes/identity.ts +34 -0
  689. package/src/ipc/skill-routes/index.ts +37 -0
  690. package/src/ipc/skill-routes/log.ts +40 -0
  691. package/src/ipc/skill-routes/memory.ts +76 -0
  692. package/src/ipc/skill-routes/platform.ts +39 -0
  693. package/src/ipc/skill-routes/providers.ts +163 -0
  694. package/src/ipc/skill-routes/registries.ts +393 -0
  695. package/src/ipc/skill-server.ts +771 -0
  696. package/src/ipc/skill-socket-path.ts +20 -0
  697. package/src/ipc/socket-cleanup.ts +92 -0
  698. package/src/ipc/socket-path.ts +63 -32
  699. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +374 -0
  700. package/src/live-voice/__tests__/live-voice-archive.test.ts +525 -0
  701. package/src/live-voice/__tests__/live-voice-events.test.ts +473 -0
  702. package/src/live-voice/__tests__/live-voice-integration.test.ts +359 -0
  703. package/src/live-voice/__tests__/live-voice-metrics.test.ts +179 -0
  704. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +349 -0
  705. package/src/live-voice/__tests__/live-voice-stt.test.ts +244 -0
  706. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +337 -0
  707. package/src/live-voice/__tests__/live-voice-tts.test.ts +337 -0
  708. package/src/live-voice/__tests__/protocol.test.ts +295 -0
  709. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +421 -0
  710. package/src/live-voice/live-voice-archive.ts +758 -0
  711. package/src/live-voice/live-voice-metrics.ts +472 -0
  712. package/src/live-voice/live-voice-session-manager.ts +222 -0
  713. package/src/live-voice/live-voice-session.ts +1144 -0
  714. package/src/live-voice/live-voice-tts.ts +260 -0
  715. package/src/live-voice/protocol.ts +524 -0
  716. package/src/mcp/client.ts +2 -2
  717. package/src/media/types.ts +4 -4
  718. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +4 -28
  719. package/src/memory/__tests__/auto-analysis-guard.test.ts +2 -2
  720. package/src/memory/__tests__/conversation-analyze-job.test.ts +7 -62
  721. package/src/memory/__tests__/conversation-group-migration.test.ts +2 -2
  722. package/src/memory/__tests__/find-analysis-conversation.test.ts +2 -1
  723. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +235 -0
  724. package/src/memory/admin.ts +65 -7
  725. package/src/memory/app-git-service.ts +0 -14
  726. package/src/memory/attachments-store.ts +14 -16
  727. package/src/memory/auto-analysis-enqueue.ts +2 -17
  728. package/src/memory/canonical-guardian-store.ts +2 -1
  729. package/src/memory/channel-verification-sessions.ts +1 -1
  730. package/src/memory/checkpoints.ts +1 -1
  731. package/src/memory/context-search/agent-protocol.ts +424 -0
  732. package/src/memory/context-search/agent-runner.ts +1295 -0
  733. package/src/memory/context-search/format.ts +160 -0
  734. package/src/memory/context-search/limits.ts +106 -0
  735. package/src/memory/context-search/search.ts +387 -0
  736. package/src/memory/context-search/sources/conversations.ts +278 -0
  737. package/src/memory/context-search/sources/memory.ts +90 -0
  738. package/src/memory/context-search/sources/pkb.ts +468 -0
  739. package/src/memory/context-search/sources/workspace.ts +1255 -0
  740. package/src/memory/context-search/types.ts +49 -0
  741. package/src/memory/conversation-analyze-job.ts +3 -24
  742. package/src/memory/conversation-attention-store.ts +1 -1
  743. package/src/memory/conversation-bootstrap.ts +1 -1
  744. package/src/memory/conversation-crud.ts +69 -127
  745. package/src/memory/conversation-directories.ts +1 -11
  746. package/src/memory/conversation-display-order-migration.ts +11 -2
  747. package/src/memory/conversation-group-migration.ts +20 -4
  748. package/src/memory/conversation-key-store.ts +3 -4
  749. package/src/memory/conversation-queries.ts +13 -26
  750. package/src/memory/conversation-starter-validation.ts +88 -0
  751. package/src/memory/conversation-starters-cadence.ts +1 -1
  752. package/src/memory/conversation-title-service.ts +2 -1
  753. package/src/memory/db-init.ts +14 -4
  754. package/src/memory/db-maintenance.ts +1 -1
  755. package/src/memory/delivery-channels.ts +1 -14
  756. package/src/memory/delivery-crud.ts +2 -32
  757. package/src/memory/delivery-status.ts +1 -1
  758. package/src/memory/embedding-gemini.test.ts +4 -4
  759. package/src/memory/external-conversation-store.ts +1 -1
  760. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +412 -0
  761. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +225 -0
  762. package/src/memory/graph/bootstrap.test.ts +2 -7
  763. package/src/memory/graph/bootstrap.ts +2 -1
  764. package/src/memory/graph/capability-seed.ts +3 -3
  765. package/src/memory/graph/compaction.ts +1 -1
  766. package/src/memory/graph/consolidation.ts +13 -10
  767. package/src/memory/graph/conversation-graph-memory.ts +151 -1
  768. package/src/memory/graph/decay.ts +1 -1
  769. package/src/memory/graph/extraction.ts +53 -21
  770. package/src/memory/graph/graph-memory-state-store.ts +1 -1
  771. package/src/memory/graph/graph-search.test.ts +94 -2
  772. package/src/memory/graph/graph-search.ts +22 -7
  773. package/src/memory/graph/image-ref-utils.ts +1 -1
  774. package/src/memory/graph/retriever.test.ts +158 -4
  775. package/src/memory/graph/retriever.ts +17 -5
  776. package/src/memory/graph/store.test.ts +2 -1
  777. package/src/memory/graph/store.ts +1 -1
  778. package/src/memory/graph/tool-handlers.ts +73 -247
  779. package/src/memory/graph/tools.ts +35 -53
  780. package/src/memory/group-crud.ts +1 -2
  781. package/src/memory/guardian-action-store.ts +2 -1
  782. package/src/memory/guardian-approvals.ts +1 -1
  783. package/src/memory/guardian-rate-limits.ts +1 -1
  784. package/src/memory/indexer.ts +43 -17
  785. package/src/memory/invite-store.ts +1 -1
  786. package/src/memory/job-handlers/backfill.ts +1 -1
  787. package/src/memory/job-handlers/cleanup.ts +2 -1
  788. package/src/memory/job-handlers/conversation-starters.ts +18 -10
  789. package/src/memory/job-handlers/embedding.test.ts +2 -1
  790. package/src/memory/job-handlers/embedding.ts +1 -1
  791. package/src/memory/job-handlers/index-maintenance.ts +1 -1
  792. package/src/memory/job-handlers/summarization.ts +3 -3
  793. package/src/memory/job-utils.ts +3 -3
  794. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +362 -0
  795. package/src/memory/jobs/embed-concept-page.ts +210 -0
  796. package/src/memory/jobs/embed-pkb-file.test.ts +2 -1
  797. package/src/memory/jobs-store.ts +10 -2
  798. package/src/memory/jobs-worker.ts +58 -5
  799. package/src/memory/lifecycle-events-store.ts +1 -1
  800. package/src/memory/llm-request-log-store.ts +1 -1
  801. package/src/memory/llm-usage-store.ts +1 -1
  802. package/src/memory/media-store.ts +1 -1
  803. package/src/memory/memory-recall-log-store.ts +1 -1
  804. package/src/memory/migrations/038-actor-token-records.ts +3 -0
  805. package/src/memory/migrations/039-actor-refresh-token-records.ts +3 -0
  806. package/src/memory/migrations/226-schedule-wake-conversation-id.ts +11 -0
  807. package/src/memory/migrations/227-add-conversation-inference-profile.ts +18 -0
  808. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +27 -0
  809. package/src/memory/migrations/229-delete-private-conversations.test.ts +1087 -0
  810. package/src/memory/migrations/229-delete-private-conversations.ts +210 -0
  811. package/src/memory/migrations/230-acp-session-history.ts +41 -0
  812. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +128 -0
  813. package/src/memory/migrations/232-activation-state.ts +38 -0
  814. package/src/memory/migrations/index.ts +10 -0
  815. package/src/memory/migrations/registry.ts +7 -0
  816. package/src/memory/pkb/pkb-index.test.ts +4 -5
  817. package/src/memory/pkb/pkb-reconcile.test.ts +4 -5
  818. package/src/memory/pkb/pkb-search.test.ts +83 -3
  819. package/src/memory/pkb/pkb-search.ts +27 -14
  820. package/src/memory/published-pages-store.ts +1 -1
  821. package/src/memory/schema/acp.ts +30 -0
  822. package/src/memory/schema/conversations.ts +1 -1
  823. package/src/memory/schema/index.ts +1 -0
  824. package/src/memory/schema/infrastructure.ts +1 -32
  825. package/src/memory/schema/memory-graph.ts +36 -14
  826. package/src/memory/scoped-approval-grants.ts +2 -1
  827. package/src/memory/search/semantic.ts +2 -2
  828. package/src/memory/shared-app-links-store.ts +2 -1
  829. package/src/memory/tool-usage-store.ts +1 -1
  830. package/src/memory/trace-event-store.ts +2 -1
  831. package/src/memory/turn-events-store.ts +1 -1
  832. package/src/memory/v2/__tests__/activation-store.test.ts +202 -0
  833. package/src/memory/v2/__tests__/activation.test.ts +956 -0
  834. package/src/memory/v2/__tests__/backfill-jobs.test.ts +610 -0
  835. package/src/memory/v2/__tests__/consolidation-job.test.ts +395 -0
  836. package/src/memory/v2/__tests__/edges.test.ts +435 -0
  837. package/src/memory/v2/__tests__/injection.test.ts +792 -0
  838. package/src/memory/v2/__tests__/migration.test.ts +812 -0
  839. package/src/memory/v2/__tests__/page-store.test.ts +334 -0
  840. package/src/memory/v2/__tests__/qdrant.test.ts +438 -0
  841. package/src/memory/v2/__tests__/sim.test.ts +549 -0
  842. package/src/memory/v2/__tests__/skill-content.test.ts +85 -0
  843. package/src/memory/v2/__tests__/skill-qdrant.test.ts +657 -0
  844. package/src/memory/v2/__tests__/skill-store.test.ts +351 -0
  845. package/src/memory/v2/__tests__/sweep-job.test.ts +441 -0
  846. package/src/memory/v2/activation-store.ts +109 -0
  847. package/src/memory/v2/activation.ts +490 -0
  848. package/src/memory/v2/backfill-jobs.ts +442 -0
  849. package/src/memory/v2/consolidation-job.ts +304 -0
  850. package/src/memory/v2/edges.ts +217 -0
  851. package/src/memory/v2/injection.ts +307 -0
  852. package/src/memory/v2/migration.ts +654 -0
  853. package/src/memory/v2/now-text.ts +38 -0
  854. package/src/memory/v2/page-store.ts +245 -0
  855. package/src/memory/v2/prompts/consolidation.ts +185 -0
  856. package/src/memory/v2/prompts/sweep.ts +56 -0
  857. package/src/memory/v2/qdrant.ts +342 -0
  858. package/src/memory/v2/sim.ts +206 -0
  859. package/src/memory/v2/skill-content.ts +42 -0
  860. package/src/memory/v2/skill-qdrant.ts +395 -0
  861. package/src/memory/v2/skill-store.ts +128 -0
  862. package/src/memory/v2/sweep-job.ts +298 -0
  863. package/src/memory/v2/types.ts +116 -0
  864. package/src/memory/validation.ts +1 -1
  865. package/src/messaging/providers/index.ts +262 -0
  866. package/src/messaging/providers/slack/api.ts +242 -0
  867. package/src/messaging/providers/slack/message-metadata.ts +1 -1
  868. package/src/messaging/providers/slack/send.ts +383 -0
  869. package/src/messaging/providers/telegram-bot/adapter.ts +4 -42
  870. package/src/messaging/providers/telegram-bot/api.ts +253 -0
  871. package/src/messaging/providers/telegram-bot/client.ts +17 -58
  872. package/src/messaging/providers/telegram-bot/send.ts +232 -0
  873. package/src/messaging/providers/whatsapp/adapter.ts +4 -36
  874. package/src/messaging/providers/whatsapp/api.ts +319 -0
  875. package/src/messaging/providers/whatsapp/client.ts +4 -48
  876. package/src/messaging/providers/whatsapp/send.ts +209 -0
  877. package/src/notifications/adapters/slack.ts +5 -23
  878. package/src/notifications/adapters/telegram.ts +8 -29
  879. package/src/notifications/conversation-candidates.ts +1 -1
  880. package/src/notifications/conversation-seed-composer.ts +12 -6
  881. package/src/notifications/copy-composer.ts +1 -1
  882. package/src/notifications/decision-engine.ts +1 -1
  883. package/src/notifications/decisions-store.ts +1 -1
  884. package/src/notifications/deliveries-store.ts +2 -1
  885. package/src/notifications/deterministic-checks.ts +1 -1
  886. package/src/notifications/events-store.ts +1 -13
  887. package/src/notifications/preferences-store.ts +1 -1
  888. package/src/notifications/signal.ts +0 -9
  889. package/src/oauth/connection-resolver.ts +11 -2
  890. package/src/oauth/oauth-store.ts +2 -1
  891. package/src/outbound-proxy/index.ts +0 -1
  892. package/src/permissions/approval-policy.test.ts +149 -132
  893. package/src/permissions/approval-policy.ts +65 -91
  894. package/src/permissions/checker.test.ts +632 -0
  895. package/src/permissions/checker.ts +266 -459
  896. package/src/permissions/gateway-threshold-reader.ts +28 -47
  897. package/src/permissions/ipc-risk-types.ts +95 -0
  898. package/src/permissions/prompter.ts +4 -9
  899. package/src/permissions/risk-types.ts +24 -210
  900. package/src/permissions/types.ts +17 -47
  901. package/src/permissions/workspace-policy.ts +2 -4
  902. package/src/playbooks/playbook-compiler.ts +1 -1
  903. package/src/plugins/defaults/index.ts +1 -1
  904. package/src/plugins/defaults/injectors.ts +18 -21
  905. package/src/plugins/defaults/llm-call.ts +6 -9
  906. package/src/plugins/defaults/memory-retrieval.ts +1 -6
  907. package/src/plugins/defaults/overflow-reduce.ts +9 -5
  908. package/src/plugins/defaults/token-estimate.ts +2 -3
  909. package/src/plugins/registry.ts +61 -1
  910. package/src/plugins/types.ts +6 -7
  911. package/src/plugins/user-loader.ts +36 -10
  912. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +197 -0
  913. package/src/prompts/persona-resolver.ts +2 -4
  914. package/src/prompts/system-prompt.ts +39 -0
  915. package/src/prompts/templates/SOUL.md +3 -1
  916. package/src/providers/__tests__/provider-env-vars.test.ts +0 -21
  917. package/src/providers/__tests__/retry-callsite.test.ts +3 -6
  918. package/src/providers/anthropic/client.ts +71 -19
  919. package/src/providers/call-site-routing.ts +7 -3
  920. package/src/providers/fireworks/client.ts +3 -0
  921. package/src/providers/gemini/client.ts +96 -22
  922. package/src/providers/managed-proxy/context.ts +0 -12
  923. package/src/providers/model-catalog.ts +83 -8
  924. package/src/providers/model-intents.ts +7 -8
  925. package/src/providers/openai/chat-completions-provider.ts +37 -7
  926. package/src/providers/openai/responses-provider.ts +39 -4
  927. package/src/providers/openrouter/client.ts +4 -5
  928. package/src/providers/provider-env-vars.ts +4 -12
  929. package/src/providers/provider-send-message.ts +16 -11
  930. package/src/providers/registry.ts +1 -1
  931. package/src/providers/retry.ts +52 -23
  932. package/src/providers/speech-to-text/openai-whisper-stream.ts +1 -1
  933. package/src/providers/speech-to-text/openai-whisper.ts +3 -6
  934. package/src/providers/speech-to-text/provider-catalog.ts +75 -0
  935. package/src/providers/speech-to-text/xai.ts +5 -5
  936. package/src/providers/thinking-config.ts +34 -0
  937. package/src/providers/types.ts +22 -10
  938. package/src/runtime/AGENTS.md +10 -9
  939. package/src/runtime/__tests__/agent-wake.test.ts +33 -9
  940. package/src/runtime/__tests__/client-registry.test.ts +5 -27
  941. package/src/runtime/__tests__/interactive-ui.test.ts +157 -246
  942. package/src/runtime/access-request-helper.ts +9 -20
  943. package/src/runtime/actor-trust-resolver.ts +2 -2
  944. package/src/runtime/agent-wake.ts +174 -68
  945. package/src/runtime/approval-conversation-turn.ts +2 -15
  946. package/src/runtime/approval-message-composer.ts +11 -60
  947. package/src/runtime/assistant-event.ts +18 -66
  948. package/src/runtime/auth/__tests__/guard-tests.test.ts +6 -30
  949. package/src/runtime/auth/__tests__/middleware.test.ts +10 -10
  950. package/src/runtime/auth/__tests__/route-policy.test.ts +0 -8
  951. package/src/runtime/auth/context.ts +9 -0
  952. package/src/runtime/auth/middleware.ts +4 -4
  953. package/src/runtime/auth/route-policy.ts +195 -4
  954. package/src/runtime/auth/token-service.ts +1 -100
  955. package/src/runtime/capability-tokens.ts +89 -313
  956. package/src/runtime/channel-approval-types.ts +1 -6
  957. package/src/runtime/channel-approvals.ts +7 -79
  958. package/src/runtime/channel-readiness-service.ts +2 -2
  959. package/src/runtime/channel-reply-delivery.ts +2 -8
  960. package/src/runtime/channel-retry-sweep.ts +20 -17
  961. package/src/runtime/client-registry.ts +21 -28
  962. package/src/runtime/confirmation-request-guardian-bridge.ts +2 -7
  963. package/src/runtime/gateway-client.ts +37 -378
  964. package/src/runtime/guardian-action-grant-minter.ts +2 -3
  965. package/src/runtime/guardian-action-message-composer.ts +11 -52
  966. package/src/runtime/guardian-action-service.ts +19 -7
  967. package/src/runtime/guardian-decision-types.ts +4 -65
  968. package/src/runtime/guardian-reply-router.ts +10 -19
  969. package/src/runtime/guardian-vellum-migration.ts +5 -64
  970. package/src/runtime/http-errors.ts +3 -0
  971. package/src/runtime/http-router.ts +50 -7
  972. package/src/runtime/http-server.ts +345 -1110
  973. package/src/runtime/http-types.ts +15 -98
  974. package/src/runtime/interactive-ui-types.ts +145 -0
  975. package/src/runtime/interactive-ui.ts +38 -196
  976. package/src/runtime/invite-redemption-service.ts +1 -1
  977. package/src/runtime/invite-redemption-templates.ts +1 -1
  978. package/src/runtime/local-actor-identity.ts +13 -43
  979. package/src/runtime/message-composer-types.ts +134 -0
  980. package/src/runtime/middleware/rate-limiter.ts +1 -1
  981. package/src/runtime/middleware/request-logger.ts +5 -2
  982. package/src/runtime/migrations/__tests__/job-registry.test.ts +346 -0
  983. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +16 -0
  984. package/src/runtime/migrations/job-registry.ts +281 -0
  985. package/src/runtime/migrations/vbundle-builder.ts +3 -4
  986. package/src/runtime/migrations/vbundle-importer.ts +1 -1
  987. package/src/runtime/migrations/vbundle-streaming-importer.ts +0 -13
  988. package/src/runtime/migrations/vbundle-tar-stream.ts +11 -3
  989. package/src/runtime/nl-approval-parser.ts +16 -21
  990. package/src/runtime/pending-interactions.ts +29 -12
  991. package/src/runtime/routes/__tests__/acp-routes.test.ts +395 -0
  992. package/src/runtime/routes/__tests__/backup-routes.test.ts +204 -320
  993. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +72 -4
  994. package/src/runtime/routes/__tests__/stt-routes.test.ts +182 -223
  995. package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +230 -0
  996. package/src/{ipc/__tests__/task-ipc.test.ts → runtime/routes/__tests__/task-routes.test.ts} +116 -96
  997. package/src/runtime/routes/__tests__/tts-routes.test.ts +185 -289
  998. package/src/runtime/routes/access-request-decision.ts +25 -50
  999. package/src/runtime/routes/acp-routes.test.ts +371 -0
  1000. package/src/runtime/routes/acp-routes.ts +392 -166
  1001. package/src/runtime/routes/app-management-routes.ts +464 -660
  1002. package/src/runtime/routes/app-routes.ts +192 -177
  1003. package/src/runtime/routes/approval-routes.ts +116 -434
  1004. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +24 -84
  1005. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +3 -10
  1006. package/src/runtime/routes/attachment-routes.ts +409 -253
  1007. package/src/runtime/routes/audio-routes.ts +51 -18
  1008. package/src/runtime/routes/avatar-routes.ts +82 -75
  1009. package/src/runtime/routes/background-tool-routes.ts +94 -0
  1010. package/src/runtime/routes/backup-routes.ts +154 -336
  1011. package/src/runtime/routes/brain-graph-routes.ts +83 -110
  1012. package/src/runtime/routes/browser-routes.ts +141 -0
  1013. package/src/runtime/routes/btw-routes.ts +62 -106
  1014. package/src/runtime/routes/cache-routes.ts +96 -0
  1015. package/src/runtime/routes/call-routes.ts +208 -247
  1016. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +1 -1
  1017. package/src/runtime/routes/channel-delivery-routes.ts +25 -27
  1018. package/src/runtime/routes/channel-readiness-routes.ts +83 -120
  1019. package/src/runtime/routes/channel-route-definitions.ts +62 -0
  1020. package/src/runtime/routes/channel-route-shared.ts +14 -18
  1021. package/src/runtime/routes/channel-verification-routes.ts +207 -187
  1022. package/src/runtime/routes/client-routes.ts +48 -0
  1023. package/src/runtime/routes/contact-routes.ts +533 -407
  1024. package/src/runtime/routes/conversation-analysis-routes.ts +48 -49
  1025. package/src/runtime/routes/conversation-attention-routes.ts +55 -67
  1026. package/src/runtime/routes/conversation-list-routes.ts +265 -0
  1027. package/src/runtime/routes/conversation-management-routes.ts +626 -715
  1028. package/src/runtime/routes/conversation-query-routes.ts +510 -460
  1029. package/src/runtime/routes/conversation-routes.ts +456 -368
  1030. package/src/runtime/routes/conversation-starter-routes.ts +121 -71
  1031. package/src/runtime/routes/credential-prompt-routes.ts +124 -0
  1032. package/src/runtime/routes/debug-routes.ts +34 -39
  1033. package/src/runtime/routes/defer-routes.ts +230 -0
  1034. package/src/runtime/routes/diagnostics-routes.ts +79 -70
  1035. package/src/runtime/routes/documents-routes.ts +117 -106
  1036. package/src/runtime/routes/errors.ts +132 -0
  1037. package/src/runtime/routes/events-routes.ts +97 -58
  1038. package/src/runtime/routes/filing-routes.ts +65 -78
  1039. package/src/runtime/routes/global-search-routes.ts +51 -57
  1040. package/src/runtime/routes/group-routes.ts +199 -181
  1041. package/src/runtime/routes/guardian-action-routes.ts +103 -169
  1042. package/src/runtime/routes/guardian-approval-interception.ts +27 -58
  1043. package/src/runtime/routes/guardian-approval-prompt.ts +10 -21
  1044. package/src/runtime/routes/guardian-approval-reply-helpers.ts +2 -6
  1045. package/src/runtime/routes/guardian-expiry-sweep.ts +19 -36
  1046. package/src/runtime/routes/heartbeat-routes.ts +194 -209
  1047. package/src/runtime/routes/home-feed-routes.ts +85 -187
  1048. package/src/runtime/routes/home-state-routes.ts +27 -24
  1049. package/src/runtime/routes/host-bash-routes.ts +42 -52
  1050. package/src/runtime/routes/host-browser-routes.ts +38 -69
  1051. package/src/runtime/routes/host-cu-routes.ts +74 -70
  1052. package/src/runtime/routes/host-file-routes.ts +50 -60
  1053. package/src/runtime/routes/host-transfer-routes.ts +220 -0
  1054. package/src/runtime/routes/http-adapter.ts +172 -0
  1055. package/src/runtime/routes/identity-routes.ts +83 -79
  1056. package/src/runtime/routes/inbound-conversation.ts +11 -18
  1057. package/src/runtime/routes/inbound-message-handler.ts +74 -110
  1058. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +79 -138
  1059. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +2 -3
  1060. package/src/runtime/routes/inbound-stages/background-dispatch.ts +54 -90
  1061. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +25 -50
  1062. package/src/runtime/routes/inbound-stages/edit-intercept.ts +7 -7
  1063. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +5 -5
  1064. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +5 -6
  1065. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -24
  1066. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -10
  1067. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -4
  1068. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +3 -3
  1069. package/src/runtime/routes/inbound-stages/verification-intercept.ts +19 -26
  1070. package/src/runtime/routes/index.ts +197 -0
  1071. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +25 -32
  1072. package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +22 -31
  1073. package/src/runtime/routes/integrations/slack/channel.ts +69 -66
  1074. package/src/runtime/routes/integrations/slack/share.ts +49 -58
  1075. package/src/runtime/routes/integrations/telegram.ts +91 -74
  1076. package/src/runtime/routes/integrations/twilio.ts +163 -240
  1077. package/src/runtime/routes/integrations/vercel.ts +57 -54
  1078. package/src/runtime/routes/interface-routes.ts +43 -0
  1079. package/src/runtime/routes/internal-oauth-routes.ts +56 -0
  1080. package/src/runtime/routes/internal-twilio-routes.ts +46 -0
  1081. package/src/runtime/routes/llm-context-normalization.ts +4 -2
  1082. package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
  1083. package/src/runtime/routes/log-export-routes.ts +90 -100
  1084. package/src/runtime/routes/memory-item-routes.test.ts +152 -175
  1085. package/src/runtime/routes/memory-item-routes.ts +243 -323
  1086. package/src/runtime/routes/memory-v2-routes.ts +193 -0
  1087. package/src/runtime/routes/migration-rollback-routes.ts +167 -212
  1088. package/src/runtime/routes/migration-routes.ts +877 -374
  1089. package/src/runtime/routes/notification-routes.ts +199 -70
  1090. package/src/runtime/routes/oauth-apps.ts +254 -251
  1091. package/src/runtime/routes/oauth-providers.ts +66 -57
  1092. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +60 -120
  1093. package/src/runtime/routes/playground/__tests__/guard.test.ts +34 -54
  1094. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +107 -151
  1095. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +41 -117
  1096. package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +95 -138
  1097. package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +115 -217
  1098. package/src/runtime/routes/playground/__tests__/state.test.ts +41 -90
  1099. package/src/runtime/routes/playground/conversation-not-found.ts +9 -11
  1100. package/src/runtime/routes/playground/force-compact.ts +41 -54
  1101. package/src/runtime/routes/playground/guard.ts +18 -19
  1102. package/src/runtime/routes/playground/helpers.ts +103 -0
  1103. package/src/runtime/routes/playground/index.ts +15 -25
  1104. package/src/runtime/routes/playground/inject-failures.ts +48 -64
  1105. package/src/runtime/routes/playground/reset-circuit.ts +31 -57
  1106. package/src/runtime/routes/playground/seed-conversation.ts +66 -92
  1107. package/src/runtime/routes/playground/seeded-conversations.ts +60 -64
  1108. package/src/runtime/routes/playground/state.ts +23 -24
  1109. package/src/runtime/routes/profiler-routes.ts +132 -167
  1110. package/src/runtime/routes/ps-routes.ts +120 -0
  1111. package/src/runtime/routes/recording-routes.ts +197 -258
  1112. package/src/runtime/routes/rename-conversation-routes.ts +89 -0
  1113. package/src/runtime/routes/schedule-routes.ts +238 -242
  1114. package/src/runtime/routes/secret-routes.ts +219 -265
  1115. package/src/runtime/routes/secrets-deps.ts +24 -0
  1116. package/src/runtime/routes/settings-routes.ts +361 -441
  1117. package/src/runtime/routes/skills-routes.ts +434 -469
  1118. package/src/runtime/routes/stt-routes.ts +196 -206
  1119. package/src/runtime/routes/subagents-routes.ts +125 -141
  1120. package/src/runtime/routes/suggest-trust-rule-routes.ts +244 -0
  1121. package/src/runtime/routes/surface-action-routes.ts +135 -190
  1122. package/src/runtime/routes/surface-content-routes.ts +84 -118
  1123. package/src/runtime/routes/task-routes.ts +354 -0
  1124. package/src/runtime/routes/telemetry-routes.ts +33 -49
  1125. package/src/runtime/routes/trace-event-routes.ts +55 -74
  1126. package/src/runtime/routes/trust-rules-routes.ts +147 -239
  1127. package/src/runtime/routes/tts-routes.ts +187 -169
  1128. package/src/runtime/routes/types.ts +139 -0
  1129. package/src/{ipc/routes/ui-request.ts → runtime/routes/ui-request-routes.ts} +23 -17
  1130. package/src/runtime/routes/upgrade-broadcast-routes.ts +156 -197
  1131. package/src/runtime/routes/usage-routes.ts +143 -169
  1132. package/src/runtime/routes/user-routes.ts +102 -18
  1133. package/src/runtime/routes/wake-conversation-routes.ts +49 -0
  1134. package/src/{ipc/routes/watcher.ts → runtime/routes/watcher-routes.ts} +84 -39
  1135. package/src/runtime/routes/wipe-conversation-routes.ts +89 -0
  1136. package/src/runtime/routes/work-items-routes.test.ts +10 -20
  1137. package/src/runtime/routes/work-items-routes.ts +418 -433
  1138. package/src/runtime/routes/workspace-commit-routes.ts +30 -61
  1139. package/src/runtime/routes/workspace-routes.test.ts +254 -381
  1140. package/src/runtime/routes/workspace-routes.ts +238 -246
  1141. package/src/runtime/runtime-mode.ts +8 -1
  1142. package/src/runtime/services/__tests__/analyze-conversation.test.ts +80 -118
  1143. package/src/runtime/services/analyze-conversation.ts +14 -41
  1144. package/src/runtime/services/conversation-serializer.ts +181 -0
  1145. package/src/runtime/trust-context-resolver.ts +3 -2
  1146. package/src/runtime/verification-outbound-actions.ts +13 -49
  1147. package/src/schedule/schedule-store.ts +64 -2
  1148. package/src/schedule/scheduler.ts +101 -0
  1149. package/src/security/ces-credential-client.ts +32 -169
  1150. package/src/security/ces-rpc-credential-backend.ts +1 -1
  1151. package/src/security/credential-backend.ts +6 -6
  1152. package/src/security/oauth-completion-page.ts +1 -1
  1153. package/src/security/oauth2.ts +3 -6
  1154. package/src/sequence/analytics.ts +1 -1
  1155. package/src/sequence/guardrails.ts +3 -3
  1156. package/src/sequence/store.ts +2 -1
  1157. package/src/signals/bash.ts +1 -1
  1158. package/src/signals/event-stream.ts +1 -1
  1159. package/src/skills/catalog-cache.ts +7 -0
  1160. package/src/skills/catalog-files.ts +0 -5
  1161. package/src/skills/catalog-install.ts +28 -18
  1162. package/src/skills/category-inference.ts +0 -11
  1163. package/src/skills/clawhub.ts +2 -2
  1164. package/src/skills/managed-store.ts +2 -2
  1165. package/src/skills/remote-skill-policy.ts +6 -7
  1166. package/src/subagent/index.ts +2 -6
  1167. package/src/subagent/manager.ts +27 -23
  1168. package/src/subagent/types.ts +9 -0
  1169. package/src/tasks/SPEC.md +2 -2
  1170. package/src/tasks/task-compiler.ts +1 -1
  1171. package/src/tasks/task-runner.ts +2 -22
  1172. package/src/tasks/task-store.ts +1 -1
  1173. package/src/tools/acp/list-agents.test.ts +115 -0
  1174. package/src/tools/acp/list-agents.ts +31 -0
  1175. package/src/tools/acp/spawn.test.ts +379 -0
  1176. package/src/tools/acp/spawn.ts +142 -62
  1177. package/src/tools/acp/steer.test.ts +101 -0
  1178. package/src/tools/acp/steer.ts +38 -0
  1179. package/src/tools/background-tool-registry.ts +98 -0
  1180. package/src/tools/browser/browser-execution.ts +34 -7
  1181. package/src/tools/browser/browser-manager.ts +1 -8
  1182. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +1 -1
  1183. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +3 -1
  1184. package/src/tools/browser/cdp-client/types.ts +4 -1
  1185. package/src/tools/computer-use/definitions.ts +1 -1
  1186. package/src/tools/credential-execution/make-authenticated-request.ts +2 -2
  1187. package/src/tools/credential-execution/manage-secure-command-tool.ts +1 -1
  1188. package/src/tools/credential-execution/run-authenticated-command.ts +2 -2
  1189. package/src/tools/credentials/broker-types.ts +2 -1
  1190. package/src/tools/document/editor-template.ts +1 -1
  1191. package/src/tools/execution-timeout.ts +1 -1
  1192. package/src/tools/executor.ts +10 -15
  1193. package/src/tools/host-filesystem/transfer.test.ts +268 -0
  1194. package/src/tools/host-filesystem/transfer.ts +234 -0
  1195. package/src/tools/host-terminal/host-shell.ts +189 -11
  1196. package/src/tools/mcp/mcp-tool-factory.ts +1 -1
  1197. package/src/tools/memory/register.test.ts +161 -1
  1198. package/src/tools/memory/register.ts +19 -34
  1199. package/src/tools/permission-checker.ts +18 -219
  1200. package/src/tools/policy-context.ts +1 -8
  1201. package/src/tools/registry.ts +16 -1
  1202. package/src/tools/secret-detection-handler.ts +13 -103
  1203. package/src/tools/shared/shell-output.ts +4 -1
  1204. package/src/tools/side-effects.ts +2 -2
  1205. package/src/tools/skills/execute.ts +1 -1
  1206. package/src/tools/subagent/spawn.ts +35 -11
  1207. package/src/tools/terminal/safe-env.ts +9 -1
  1208. package/src/tools/terminal/shell.ts +161 -31
  1209. package/src/tools/tool-approval-handler.ts +4 -70
  1210. package/src/tools/tool-input-summary.ts +10 -0
  1211. package/src/tools/types.ts +143 -163
  1212. package/src/tools/ui-surface/definitions.ts +2 -2
  1213. package/src/util/debounce.ts +0 -21
  1214. package/src/util/errors.ts +0 -8
  1215. package/src/util/log-redact.ts +0 -1
  1216. package/src/util/platform.ts +85 -124
  1217. package/src/util/pricing.ts +109 -6
  1218. package/src/watcher/engine.ts +42 -20
  1219. package/src/watcher/watcher-store.ts +2 -1
  1220. package/src/work-items/work-item-store.ts +1 -1
  1221. package/src/workspace/git-service.ts +1 -6
  1222. package/src/workspace/migrations/006-services-config.ts +10 -1
  1223. package/src/workspace/migrations/017-seed-persona-dirs.ts +1 -1
  1224. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +1 -1
  1225. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +1 -1
  1226. package/src/workspace/migrations/031-drop-user-md.ts +1 -1
  1227. package/src/workspace/migrations/045-release-notes-meet-avatar.ts +3 -4
  1228. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +150 -0
  1229. package/src/workspace/migrations/053-release-notes-acp-codex.ts +107 -0
  1230. package/src/workspace/migrations/054-seed-recall-callsite.ts +102 -0
  1231. package/src/workspace/migrations/055-release-notes-agentic-recall.ts +63 -0
  1232. package/src/workspace/migrations/056-release-notes-inference-profile-reordering.ts +65 -0
  1233. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +98 -0
  1234. package/src/workspace/migrations/058-release-notes-acp-sessions-ui.ts +71 -0
  1235. package/src/workspace/migrations/059-move-pid-to-workspace.ts +53 -0
  1236. package/src/workspace/migrations/060-memory-v2-init.ts +53 -0
  1237. package/src/workspace/migrations/rebuild-conversation-disk-view.ts +1 -1
  1238. package/src/workspace/migrations/registry.ts +18 -0
  1239. package/src/workspace/migrations/runner.ts +2 -2
  1240. package/src/workspace/provider-commit-message-generator.ts +1 -1
  1241. package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +0 -471
  1242. package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +0 -436
  1243. package/src/__tests__/cli-command-risk-guard.test.ts +0 -368
  1244. package/src/__tests__/config-watcher-feature-flags.test.ts +0 -211
  1245. package/src/__tests__/conversation-approval-overrides.test.ts +0 -207
  1246. package/src/__tests__/conversation-host-access-routes.test.ts +0 -229
  1247. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +0 -226
  1248. package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +0 -167
  1249. package/src/__tests__/ephemeral-permissions.test.ts +0 -474
  1250. package/src/__tests__/extension-id-sync-guard.test.ts +0 -241
  1251. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +0 -374
  1252. package/src/__tests__/native-host-marker-sync-guard.test.ts +0 -157
  1253. package/src/__tests__/pairing-concurrent.test.ts +0 -84
  1254. package/src/__tests__/pairing-routes.test.ts +0 -181
  1255. package/src/__tests__/parser.test.ts +0 -595
  1256. package/src/__tests__/permission-checker-host-gate.test.ts +0 -488
  1257. package/src/__tests__/permission-controls-v2-flag.test.ts +0 -55
  1258. package/src/__tests__/permission-mode.test.ts +0 -89
  1259. package/src/__tests__/provider-env-vars-scope.test.ts +0 -52
  1260. package/src/__tests__/risk-classifier-parity.test.ts +0 -230
  1261. package/src/__tests__/shell-identity.test.ts +0 -236
  1262. package/src/__tests__/shell-parser-fuzz.test.ts +0 -629
  1263. package/src/__tests__/shell-parser-property.test.ts +0 -936
  1264. package/src/__tests__/starter-bundle.test.ts +0 -173
  1265. package/src/__tests__/stt-catalog-parity.test.ts +0 -282
  1266. package/src/__tests__/task-runner.test.ts +0 -224
  1267. package/src/__tests__/tool-executor-shell-integration.test.ts +0 -354
  1268. package/src/__tests__/trust-store-pattern-matches.test.ts +0 -29
  1269. package/src/__tests__/trust-store.test.ts +0 -2013
  1270. package/src/__tests__/v2-consent-policy.test.ts +0 -103
  1271. package/src/browser/identifiers.ts +0 -51
  1272. package/src/cli/db.ts +0 -1
  1273. package/src/config/bundled-skills/settings/tools/avatar-get.ts +0 -40
  1274. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +0 -64
  1275. package/src/config/bundled-skills/settings/tools/avatar-update.ts +0 -88
  1276. package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +0 -127
  1277. package/src/daemon/approved-devices-store.ts +0 -110
  1278. package/src/daemon/external-skills-bootstrap.ts +0 -41
  1279. package/src/daemon/message-types/trust.ts +0 -71
  1280. package/src/daemon/pairing-store.ts +0 -229
  1281. package/src/ipc/cli-server.ts +0 -252
  1282. package/src/ipc/routes/attachment.ts +0 -114
  1283. package/src/ipc/routes/browser-context.ts +0 -63
  1284. package/src/ipc/routes/browser.ts +0 -97
  1285. package/src/ipc/routes/cache.ts +0 -96
  1286. package/src/ipc/routes/get-contact.ts +0 -16
  1287. package/src/ipc/routes/index.ts +0 -35
  1288. package/src/ipc/routes/list-clients.ts +0 -31
  1289. package/src/ipc/routes/merge-contacts.ts +0 -17
  1290. package/src/ipc/routes/notification.ts +0 -133
  1291. package/src/ipc/routes/rename-conversation.ts +0 -59
  1292. package/src/ipc/routes/search-contacts.ts +0 -19
  1293. package/src/ipc/routes/task-queue.ts +0 -226
  1294. package/src/ipc/routes/task.ts +0 -173
  1295. package/src/ipc/routes/upsert-contact.ts +0 -25
  1296. package/src/ipc/routes/wake-conversation.ts +0 -19
  1297. package/src/memory/db.ts +0 -23
  1298. package/src/permissions/arg-parser.test.ts +0 -161
  1299. package/src/permissions/arg-parser.ts +0 -141
  1300. package/src/permissions/bash-risk-classifier.test.ts +0 -1620
  1301. package/src/permissions/bash-risk-classifier.ts +0 -950
  1302. package/src/permissions/command-registry.test.ts +0 -774
  1303. package/src/permissions/command-registry.ts +0 -1005
  1304. package/src/permissions/defaults.ts +0 -314
  1305. package/src/permissions/file-risk-classifier.test.ts +0 -535
  1306. package/src/permissions/file-risk-classifier.ts +0 -274
  1307. package/src/permissions/permission-mode.ts +0 -24
  1308. package/src/permissions/schedule-risk-classifier.test.ts +0 -129
  1309. package/src/permissions/schedule-risk-classifier.ts +0 -85
  1310. package/src/permissions/shell-identity.ts +0 -297
  1311. package/src/permissions/skill-risk-classifier.test.ts +0 -311
  1312. package/src/permissions/skill-risk-classifier.ts +0 -214
  1313. package/src/permissions/trust-client.ts +0 -359
  1314. package/src/permissions/trust-store-interface.ts +0 -100
  1315. package/src/permissions/trust-store.ts +0 -1330
  1316. package/src/permissions/v2-consent-policy.ts +0 -87
  1317. package/src/permissions/web-risk-classifier.test.ts +0 -170
  1318. package/src/permissions/web-risk-classifier.ts +0 -89
  1319. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +0 -715
  1320. package/src/runtime/__tests__/capability-tokens.test.ts +0 -258
  1321. package/src/runtime/actor-refresh-token-store.ts +0 -156
  1322. package/src/runtime/actor-token-store.ts +0 -207
  1323. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -264
  1324. package/src/runtime/auth/credential-service.ts +0 -352
  1325. package/src/runtime/conversation-approval-overrides.ts +0 -86
  1326. package/src/runtime/routes/browser-extension-pair-routes.ts +0 -575
  1327. package/src/runtime/routes/channel-routes.ts +0 -112
  1328. package/src/runtime/routes/contact-routes.test.ts +0 -298
  1329. package/src/runtime/routes/guardian-bootstrap-routes.ts +0 -175
  1330. package/src/runtime/routes/guardian-refresh-routes.ts +0 -79
  1331. package/src/runtime/routes/invite-routes.ts +0 -280
  1332. package/src/runtime/routes/pairing-routes.ts +0 -431
  1333. package/src/runtime/routes/playground/deps.ts +0 -56
  1334. package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +0 -67
  1335. package/src/runtime/services/analyze-deps-singleton.ts +0 -32
  1336. package/src/tasks/ephemeral-permissions.ts +0 -55
  1337. package/src/tools/terminal/parser.ts +0 -623
  1338. package/src/types/qrcode.d.ts +0 -13
  1339. package/src/util/network-info.ts +0 -55
  1340. /package/node_modules/@vellumai/{ces-contracts → ces-client}/tsconfig.json +0 -0
  1341. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/__tests__/grants.test.ts +0 -0
  1342. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/error.ts +0 -0
  1343. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/grants.ts +0 -0
  1344. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/handles.ts +0 -0
  1345. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/rendering.ts +0 -0
  1346. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/rpc.ts +0 -0
@@ -5,15 +5,6 @@
5
5
  * configured port (default: 7821).
6
6
  */
7
7
 
8
- import {
9
- existsSync,
10
- mkdirSync,
11
- readFileSync,
12
- renameSync,
13
- unlinkSync,
14
- writeFileSync,
15
- } from "node:fs";
16
- import { dirname, resolve } from "node:path";
17
8
 
18
9
  import type { ServerWebSocket } from "bun";
19
10
 
@@ -35,75 +26,40 @@ import {
35
26
  handleStatusCallback,
36
27
  handleVoiceWebhook,
37
28
  } from "../calls/twilio-routes.js";
38
- import { parseChannelId } from "../channels/types.js";
39
- import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
40
29
  import {
41
- getGatewayInternalBaseUrl,
42
30
  hasUngatedHttpAuthDisabled,
43
31
  isHttpAuthDisabled,
44
32
  } from "../config/env.js";
45
33
  import { getConfig } from "../config/loader.js";
46
- import type { ServerMessage } from "../daemon/message-protocol.js";
47
- import { PairingStore } from "../daemon/pairing-store.js";
48
- import {
49
- type AttentionState,
50
- type Confidence,
51
- getAttentionStateByConversationIds,
52
- markConversationUnread,
53
- recordConversationSeenSignal,
54
- type SignalType,
55
- } from "../memory/conversation-attention-store.js";
56
- import {
57
- addMessage,
58
- type ConversationRow,
59
- createConversation,
60
- deleteConversation,
61
- forkConversation as forkConversationInStore,
62
- getConversation,
63
- getDisplayMetaForConversations,
64
- } from "../memory/conversation-crud.js";
65
- import { resolveConversationId } from "../memory/conversation-key-store.js";
34
+ import { processMessage } from "../daemon/process-message.js";
35
+ import { createLiveVoiceSession } from "../live-voice/live-voice-session.js";
36
+ import { LiveVoiceSessionManager } from "../live-voice/live-voice-session-manager.js";
66
37
  import {
67
- countConversations,
68
- listConversations,
69
- listConversationsByTitlePrefix,
70
- listPinnedConversations,
71
- } from "../memory/conversation-queries.js";
72
- import type { ExternalConversationBinding } from "../memory/external-conversation-store.js";
73
- import * as externalConversationStore from "../memory/external-conversation-store.js";
74
- import { listGroups } from "../memory/group-crud.js";
75
- import { enqueueMemoryJob } from "../memory/jobs-store.js";
38
+ type LiveVoiceClientFrame,
39
+ type LiveVoiceProtocolError,
40
+ LiveVoiceProtocolErrorCode,
41
+ type LiveVoiceServerFrame,
42
+ parseLiveVoiceBinaryAudioFrame,
43
+ parseLiveVoiceClientTextFrame,
44
+ } from "../live-voice/protocol.js";
76
45
  import { resolveStreamingTranscriber } from "../providers/speech-to-text/resolve.js";
77
- import {
78
- consumeCallback,
79
- consumeCallbackError,
80
- } from "../security/oauth-callback-registry.js";
81
46
  import {
82
47
  activeSttStreamSessions,
83
48
  SttStreamSession,
84
49
  } from "../stt/stt-stream-session.js";
85
- import { UserError } from "../util/errors.js";
86
50
  import { getLogger } from "../util/logger.js";
87
- import { getRuntimePortFilePath } from "../util/platform.js";
88
- import { buildAssistantEvent } from "./assistant-event.js";
89
- import { assistantEventHub } from "./assistant-event-hub.js";
90
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "./assistant-scope.js";
91
51
  // Auth
92
52
  import {
93
53
  authenticateHostBrowserResultRequest,
94
54
  authenticateRequest,
95
55
  } from "./auth/middleware.js";
96
56
  import { parseSub } from "./auth/subject.js";
97
- import {
98
- mintDaemonDeliveryToken,
99
- mintUiPageToken,
100
- verifyToken,
101
- } from "./auth/token-service.js";
57
+ import { verifyToken } from "./auth/token-service.js";
102
58
  import { verifyHostBrowserCapability } from "./capability-tokens.js";
103
59
  import { sweepFailedEvents } from "./channel-retry-sweep.js";
104
60
  import { getChromeExtensionRegistry } from "./chrome-extension-registry.js";
105
- import { httpError } from "./http-errors.js";
106
- import type { RouteDefinition } from "./http-router.js";
61
+ import { httpError, type HttpErrorCode } from "./http-errors.js";
62
+ import type { HTTPRouteDefinition } from "./http-router.js";
107
63
  import { HttpRouter } from "./http-router.js";
108
64
  // Middleware
109
65
  import {
@@ -129,111 +85,25 @@ import {
129
85
  TWILIO_WEBHOOK_RE,
130
86
  validateTwilioWebhook,
131
87
  } from "./middleware/twilio-validation.js";
132
- import { acpRouteDefinitions } from "./routes/acp-routes.js";
133
- import { appManagementRouteDefinitions } from "./routes/app-management-routes.js";
134
- import { handleServePage } from "./routes/app-routes.js";
135
- import { appRouteDefinitions } from "./routes/app-routes.js";
136
- import { approvalRouteDefinitions } from "./routes/approval-routes.js";
137
- import { attachmentRouteDefinitions } from "./routes/attachment-routes.js";
138
- import { handleGetAudio } from "./routes/audio-routes.js";
139
- import { avatarRouteDefinitions } from "./routes/avatar-routes.js";
140
- import { backupRouteDefinitions } from "./routes/backup-routes.js";
141
- import { brainGraphRouteDefinitions } from "./routes/brain-graph-routes.js";
142
- import { handleBrowserExtensionPair } from "./routes/browser-extension-pair-routes.js";
143
- import { btwRouteDefinitions } from "./routes/btw-routes.js";
144
- import { callRouteDefinitions } from "./routes/call-routes.js";
88
+ import { ROUTES as APP_ROUTES } from "./routes/app-routes.js";
89
+ import { ROUTES as AUDIO_ROUTES } from "./routes/audio-routes.js";
145
90
  import {
146
91
  startCanonicalGuardianExpirySweep,
147
92
  stopCanonicalGuardianExpirySweep,
148
93
  } from "./routes/canonical-guardian-expiry-sweep.js";
149
- import { channelReadinessRouteDefinitions } from "./routes/channel-readiness-routes.js";
150
94
  import {
151
- channelRouteDefinitions,
152
95
  startGuardianExpirySweep,
153
96
  stopGuardianExpirySweep,
154
- } from "./routes/channel-routes.js";
155
- import { channelVerificationRouteDefinitions } from "./routes/channel-verification-routes.js";
97
+ } from "./routes/channel-guardian-routes.js";
98
+ import { RouteError } from "./routes/errors.js";
156
99
  import {
157
- contactCatchAllRouteDefinitions,
158
- contactRouteDefinitions,
159
- } from "./routes/contact-routes.js";
160
- import { conversationAnalysisRouteDefinitions } from "./routes/conversation-analysis-routes.js";
161
- import { conversationAttentionRouteDefinitions } from "./routes/conversation-attention-routes.js";
162
- import {
163
- type ConversationManagementDeps,
164
- conversationManagementRouteDefinitions,
165
- } from "./routes/conversation-management-routes.js";
166
- import { conversationQueryRouteDefinitions } from "./routes/conversation-query-routes.js";
167
- import { conversationRouteDefinitions } from "./routes/conversation-routes.js";
168
- import { conversationStarterRouteDefinitions } from "./routes/conversation-starter-routes.js";
169
- import { debugRouteDefinitions } from "./routes/debug-routes.js";
170
- import { diagnosticsRouteDefinitions } from "./routes/diagnostics-routes.js";
171
- import { documentRouteDefinitions } from "./routes/documents-routes.js";
172
- import { eventsRouteDefinitions } from "./routes/events-routes.js";
173
- import { filingRouteDefinitions } from "./routes/filing-routes.js";
174
- import { globalSearchRouteDefinitions } from "./routes/global-search-routes.js";
175
- import { groupRouteDefinitions } from "./routes/group-routes.js";
176
- import { guardianActionRouteDefinitions } from "./routes/guardian-action-routes.js";
177
- import { handleGuardianBootstrap } from "./routes/guardian-bootstrap-routes.js";
178
- import { handleGuardianRefresh } from "./routes/guardian-refresh-routes.js";
179
- import { heartbeatRouteDefinitions } from "./routes/heartbeat-routes.js";
180
- import { homeFeedRouteDefinitions } from "./routes/home-feed-routes.js";
181
- import { homeStateRouteDefinitions } from "./routes/home-state-routes.js";
182
- import { hostBashRouteDefinitions } from "./routes/host-bash-routes.js";
183
- import {
184
- hostBrowserRouteDefinitions,
185
100
  resolveHostBrowserEvent,
186
101
  resolveHostBrowserResultByRequestId,
187
102
  resolveHostBrowserSessionInvalidated,
188
103
  } from "./routes/host-browser-routes.js";
189
- import { hostCuRouteDefinitions } from "./routes/host-cu-routes.js";
190
- import { hostFileRouteDefinitions } from "./routes/host-file-routes.js";
191
- import {
192
- handleHealth,
193
- handleReadyz,
194
- identityRouteDefinitions,
195
- } from "./routes/identity-routes.js";
196
- import { slackChannelRouteDefinitions } from "./routes/integrations/slack/channel.js";
197
- import { slackShareRouteDefinitions } from "./routes/integrations/slack/share.js";
198
- import { telegramRouteDefinitions } from "./routes/integrations/telegram.js";
199
- import { twilioRouteDefinitions } from "./routes/integrations/twilio.js";
200
- import { vercelRouteDefinitions } from "./routes/integrations/vercel.js";
201
- import { inviteRouteDefinitions } from "./routes/invite-routes.js";
202
- import { logExportRouteDefinitions } from "./routes/log-export-routes.js";
203
- import { memoryItemRouteDefinitions } from "./routes/memory-item-routes.js";
204
- import { migrationRollbackRouteDefinitions } from "./routes/migration-rollback-routes.js";
205
- import { migrationRouteDefinitions } from "./routes/migration-routes.js";
206
- import { notificationRouteDefinitions } from "./routes/notification-routes.js";
207
- import { oauthAppsRouteDefinitions } from "./routes/oauth-apps.js";
208
- import { oauthProvidersRouteDefinitions } from "./routes/oauth-providers.js";
209
- import type { PairingHandlerContext } from "./routes/pairing-routes.js";
210
- import {
211
- handlePairingRequest,
212
- handlePairingStatus,
213
- pairingRouteDefinitions,
214
- } from "./routes/pairing-routes.js";
215
- import { playgroundRouteDefinitions } from "./routes/playground/index.js";
216
- import { profilerRouteDefinitions } from "./routes/profiler-routes.js";
217
- import { recordingRouteDefinitions } from "./routes/recording-routes.js";
218
- import { scheduleRouteDefinitions } from "./routes/schedule-routes.js";
219
- import { secretRouteDefinitions } from "./routes/secret-routes.js";
220
- import { settingsRouteDefinitions } from "./routes/settings-routes.js";
221
- import { skillRouteDefinitions } from "./routes/skills-routes.js";
222
- import { sttRouteDefinitions } from "./routes/stt-routes.js";
223
- import { subagentRouteDefinitions } from "./routes/subagents-routes.js";
224
- import { surfaceActionRouteDefinitions } from "./routes/surface-action-routes.js";
225
- import { surfaceContentRouteDefinitions } from "./routes/surface-content-routes.js";
226
- import { telemetryRouteDefinitions } from "./routes/telemetry-routes.js";
227
- import { traceEventRouteDefinitions } from "./routes/trace-event-routes.js";
228
- import { trustRulesRouteDefinitions } from "./routes/trust-rules-routes.js";
229
- import { ttsRouteDefinitions } from "./routes/tts-routes.js";
230
- import { upgradeBroadcastRouteDefinitions } from "./routes/upgrade-broadcast-routes.js";
231
- import { usageRouteDefinitions } from "./routes/usage-routes.js";
232
- import { userRouteDefinitions } from "./routes/user-routes.js";
233
- import { workItemRouteDefinitions } from "./routes/work-items-routes.js";
234
- import { workspaceCommitRouteDefinitions } from "./routes/workspace-commit-routes.js";
235
- import { workspaceRouteDefinitions } from "./routes/workspace-routes.js";
236
- import { setAnalysisDeps } from "./services/analyze-deps-singleton.js";
104
+ import { routeDefinitionsToHTTPRoutes } from "./routes/http-adapter.js";
105
+ import { handleHealth, handleReadyz } from "./routes/identity-routes.js";
106
+ import { ROUTES } from "./routes/index.js";
237
107
  import { matchSkillRoute } from "./skill-route-registry.js";
238
108
 
239
109
  // Re-export for consumers
@@ -249,7 +119,6 @@ export type {
249
119
  RuntimeAttachmentMetadata,
250
120
  RuntimeHttpServerOptions,
251
121
  RuntimeMessageConversationOptions,
252
- SendMessageDeps,
253
122
  } from "./http-types.js";
254
123
 
255
124
  import type {
@@ -257,9 +126,7 @@ import type {
257
126
  ApprovalCopyGenerator,
258
127
  GuardianActionCopyGenerator,
259
128
  GuardianFollowUpConversationGenerator,
260
- MessageProcessor,
261
129
  RuntimeHttpServerOptions,
262
- SendMessageDeps,
263
130
  } from "./http-types.js";
264
131
 
265
132
  const log = getLogger("runtime-http");
@@ -338,59 +205,44 @@ interface SttStreamWebSocketData {
338
205
  session?: SttStreamSession;
339
206
  }
340
207
 
208
+ /**
209
+ * WebSocket data attached to `/v1/live-voice` connections. The `wsType`
210
+ * discriminator routes frames to the live voice protocol shell instead of
211
+ * the other WebSocket handlers.
212
+ */
213
+ interface LiveVoiceWebSocketData {
214
+ wsType: "live-voice";
215
+ sessionId?: string;
216
+ lastSeq: number;
217
+ }
218
+
341
219
  export class RuntimeHttpServer {
342
220
  private server: ReturnType<typeof Bun.serve> | null = null;
343
221
  private port: number;
344
222
  private hostname: string;
345
- /** Legacy shared secret for pairing routes (not used for delivery or auth). */
346
- private bearerToken: string | undefined;
347
- private processMessage?: MessageProcessor;
223
+
348
224
  private approvalCopyGenerator?: ApprovalCopyGenerator;
349
225
  private approvalConversationGenerator?: ApprovalConversationGenerator;
350
226
  private guardianActionCopyGenerator?: GuardianActionCopyGenerator;
351
227
  private guardianFollowUpConversationGenerator?: GuardianFollowUpConversationGenerator;
352
- private interfacesDir: string | null;
353
- private suggestionCache = new Map<string, string>();
354
- private suggestionInFlight = new Map<string, Promise<string | null>>();
355
228
  private retrySweepTimer: ReturnType<typeof setInterval> | null = null;
356
229
  private sweepInProgress = false;
357
- private pairingStore = new PairingStore();
358
- private pairingBroadcast?: (msg: ServerMessage) => void;
359
- private sendMessageDeps?: SendMessageDeps;
360
- private findConversation?: RuntimeHttpServerOptions["findConversation"];
361
- private findConversationBySurfaceId?: RuntimeHttpServerOptions["findConversationBySurfaceId"];
362
- private getSkillContext?: RuntimeHttpServerOptions["getSkillContext"];
363
- private conversationManagementDeps?: RuntimeHttpServerOptions["conversationManagementDeps"];
364
- private getModelSetContext?: RuntimeHttpServerOptions["getModelSetContext"];
365
- private getRecordingDeps?: RuntimeHttpServerOptions["getRecordingDeps"];
366
- private getCesClient?: RuntimeHttpServerOptions["getCesClient"];
367
- private onProviderCredentialsChanged?: RuntimeHttpServerOptions["onProviderCredentialsChanged"];
368
- private getHeartbeatService?: RuntimeHttpServerOptions["getHeartbeatService"];
369
- private getFilingService?: RuntimeHttpServerOptions["getFilingService"];
230
+
231
+ private readonly liveVoiceSessionManager: LiveVoiceSessionManager;
370
232
  private router: HttpRouter;
371
233
 
372
234
  constructor(options: RuntimeHttpServerOptions = {}) {
373
235
  this.port = options.port ?? DEFAULT_PORT;
374
236
  this.hostname = options.hostname ?? DEFAULT_HOSTNAME;
375
- this.bearerToken = options.bearerToken;
376
- this.processMessage = options.processMessage;
237
+
377
238
  this.approvalCopyGenerator = options.approvalCopyGenerator;
378
239
  this.approvalConversationGenerator = options.approvalConversationGenerator;
379
240
  this.guardianActionCopyGenerator = options.guardianActionCopyGenerator;
380
241
  this.guardianFollowUpConversationGenerator =
381
242
  options.guardianFollowUpConversationGenerator;
382
- this.interfacesDir = options.interfacesDir ?? null;
383
- this.sendMessageDeps = options.sendMessageDeps;
384
- this.findConversation = options.findConversation;
385
- this.findConversationBySurfaceId = options.findConversationBySurfaceId;
386
- this.getSkillContext = options.getSkillContext;
387
- this.conversationManagementDeps = options.conversationManagementDeps;
388
- this.getModelSetContext = options.getModelSetContext;
389
- this.getRecordingDeps = options.getRecordingDeps;
390
- this.getCesClient = options.getCesClient;
391
- this.onProviderCredentialsChanged = options.onProviderCredentialsChanged;
392
- this.getHeartbeatService = options.getHeartbeatService;
393
- this.getFilingService = options.getFilingService;
243
+ this.liveVoiceSessionManager = new LiveVoiceSessionManager({
244
+ createSession: (context) => createLiveVoiceSession(context),
245
+ });
394
246
  this.router = new HttpRouter(this.buildRouteTable());
395
247
  }
396
248
 
@@ -399,40 +251,13 @@ export class RuntimeHttpServer {
399
251
  return this.server?.port ?? this.port;
400
252
  }
401
253
 
402
- /** Expose the pairing store so the daemon server can wire HTTP handlers. */
403
- getPairingStore(): PairingStore {
404
- return this.pairingStore;
405
- }
406
-
407
- /** Set a callback for broadcasting server messages (wired by daemon server). */
408
- setPairingBroadcast(fn: (msg: ServerMessage) => void): void {
409
- this.pairingBroadcast = fn;
410
- }
411
-
412
- private get pairingContext(): PairingHandlerContext {
413
- const broadcast = this.pairingBroadcast;
414
- return {
415
- pairingStore: this.pairingStore,
416
- bearerToken: this.bearerToken,
417
- pairingBroadcast: broadcast
418
- ? (msg) => {
419
- // Broadcast to all clients via the event hub so HTTP/SSE clients
420
- // (e.g. macOS app) receive pairing approval requests.
421
- broadcast(msg);
422
- void assistantEventHub.publish(
423
- buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, msg),
424
- );
425
- }
426
- : undefined,
427
- };
428
- }
429
-
430
254
  async start(): Promise<void> {
431
255
  type AllWebSocketData =
432
256
  | RelayWebSocketData
433
257
  | BrowserRelayWebSocketData
434
258
  | MediaStreamWebSocketData
435
- | SttStreamWebSocketData;
259
+ | SttStreamWebSocketData
260
+ | LiveVoiceWebSocketData;
436
261
  this.server = Bun.serve<AllWebSocketData>({
437
262
  port: this.port,
438
263
  hostname: this.hostname,
@@ -440,7 +265,7 @@ export class RuntimeHttpServer {
440
265
  maxRequestBodySize: MAX_REQUEST_BODY_BYTES,
441
266
  fetch: (req, server) => this.handleRequest(req, server),
442
267
  websocket: {
443
- open(ws) {
268
+ open: (ws) => {
444
269
  const data = ws.data as AllWebSocketData;
445
270
  if ("wsType" in data && data.wsType === "browser-relay") {
446
271
  // When the JWT sub resolved to a guardian principal at upgrade
@@ -547,6 +372,10 @@ export class RuntimeHttpServer {
547
372
  );
548
373
  return;
549
374
  }
375
+ if ("wsType" in data && data.wsType === "live-voice") {
376
+ log.info("Live voice WebSocket opened");
377
+ return;
378
+ }
550
379
  const callSessionId = (data as RelayWebSocketData).callSessionId;
551
380
  log.info({ callSessionId }, "ConversationRelay WebSocket opened");
552
381
  if (callSessionId) {
@@ -557,7 +386,7 @@ export class RuntimeHttpServer {
557
386
  activeRelayConnections.set(callSessionId, connection);
558
387
  }
559
388
  },
560
- message(ws, message) {
389
+ message: (ws, message) => {
561
390
  const data = ws.data as AllWebSocketData;
562
391
  const raw =
563
392
  typeof message === "string"
@@ -708,13 +537,32 @@ export class RuntimeHttpServer {
708
537
  }
709
538
  return;
710
539
  }
540
+ if ("wsType" in data && data.wsType === "live-voice") {
541
+ void this.handleLiveVoiceMessage(
542
+ ws as ServerWebSocket<LiveVoiceWebSocketData>,
543
+ message,
544
+ ).catch((err) => {
545
+ log.warn(
546
+ { error: err instanceof Error ? err.message : String(err) },
547
+ "Live voice WebSocket message handler failed",
548
+ );
549
+ this.sendLiveVoiceError(
550
+ ws as ServerWebSocket<LiveVoiceWebSocketData>,
551
+ {
552
+ code: LiveVoiceProtocolErrorCode.InvalidFrame,
553
+ message: "Live voice frame handling failed",
554
+ },
555
+ );
556
+ });
557
+ return;
558
+ }
711
559
  const callSessionId = (data as RelayWebSocketData).callSessionId;
712
560
  if (callSessionId) {
713
561
  const connection = activeRelayConnections.get(callSessionId);
714
562
  connection?.handleMessage(raw);
715
563
  }
716
564
  },
717
- close(ws, code, reason) {
565
+ close: (ws, code, reason) => {
718
566
  const data = ws.data as AllWebSocketData;
719
567
  if ("wsType" in data && data.wsType === "browser-relay") {
720
568
  // Always attempt to unregister — the registry uses connectionId
@@ -775,6 +623,18 @@ export class RuntimeHttpServer {
775
623
  }
776
624
  return;
777
625
  }
626
+ if ("wsType" in data && data.wsType === "live-voice") {
627
+ log.info(
628
+ {
629
+ sessionId: data.sessionId,
630
+ code,
631
+ reason: reason?.toString(),
632
+ },
633
+ "Live voice WebSocket closed",
634
+ );
635
+ this.releaseLiveVoiceSession(data, "websocket_close");
636
+ return;
637
+ }
778
638
  const callSessionId = (data as RelayWebSocketData).callSessionId;
779
639
  log.info(
780
640
  { callSessionId, code, reason: reason?.toString() },
@@ -801,8 +661,6 @@ export class RuntimeHttpServer {
801
661
  );
802
662
  }
803
663
 
804
- this.pairingStore.start();
805
-
806
664
  if (hasUngatedHttpAuthDisabled()) {
807
665
  log.warn(
808
666
  "DISABLE_HTTP_AUTH is set but VELLUM_UNSAFE_AUTH_BYPASS=1 is not — auth bypass is IGNORED and HTTP authentication remains enabled. Set VELLUM_UNSAFE_AUTH_BYPASS=1 to confirm the bypass.",
@@ -817,15 +675,9 @@ export class RuntimeHttpServer {
817
675
  {
818
676
  port: this.actualPort,
819
677
  hostname: this.hostname,
820
- auth: !!this.bearerToken,
821
678
  },
822
679
  "Runtime HTTP server listening",
823
680
  );
824
-
825
- // Advertise the actual port to thin helpers that need to reach the
826
- // runtime without inheriting the daemon's environment (e.g. the
827
- // chrome-extension native messaging helper, spawned by Chrome).
828
- this.writeRuntimePortFile(this.actualPort);
829
681
  }
830
682
 
831
683
  /**
@@ -834,108 +686,27 @@ export class RuntimeHttpServer {
834
686
  * Extracted from start() to allow future callers to defer sweep startup.
835
687
  */
836
688
  private startBackgroundSweeps(): void {
837
- if (this.processMessage && !this.retrySweepTimer) {
838
- const pm = this.processMessage;
839
- const mintBt = () => mintDaemonDeliveryToken();
689
+ if (!this.retrySweepTimer) {
840
690
  this.retrySweepTimer = setInterval(() => {
841
691
  if (this.sweepInProgress) return;
842
692
  this.sweepInProgress = true;
843
- sweepFailedEvents(pm, mintBt).finally(() => {
693
+ sweepFailedEvents(processMessage).finally(() => {
844
694
  this.sweepInProgress = false;
845
695
  });
846
696
  }, 30_000);
847
697
  }
848
698
 
849
- startGuardianExpirySweep(
850
- getGatewayInternalBaseUrl(),
851
- () => mintDaemonDeliveryToken(),
852
- this.approvalCopyGenerator,
853
- );
699
+ startGuardianExpirySweep(this.approvalCopyGenerator);
854
700
  log.info("Guardian approval expiry sweep started");
855
701
 
856
- startGuardianActionSweep(
857
- getGatewayInternalBaseUrl(),
858
- () => mintDaemonDeliveryToken(),
859
- this.guardianActionCopyGenerator,
860
- );
702
+ startGuardianActionSweep(this.guardianActionCopyGenerator);
861
703
  log.info("Guardian action expiry sweep started");
862
704
 
863
705
  startCanonicalGuardianExpirySweep();
864
706
  log.info("Canonical guardian request expiry sweep started");
865
707
  }
866
708
 
867
- /**
868
- * Atomically publish the runtime HTTP port to ~/.vellum/runtime-port so
869
- * external helpers can locate a non-default `RUNTIME_HTTP_PORT` without
870
- * any manifest changes. Best-effort — write failures never block
871
- * daemon startup (see assistant/AGENTS.md "Daemon startup philosophy").
872
- */
873
- private writeRuntimePortFile(actualPort: number): void {
874
- try {
875
- const portFile = getRuntimePortFilePath();
876
- const dir = dirname(portFile);
877
- if (!existsSync(dir)) {
878
- mkdirSync(dir, { recursive: true });
879
- }
880
- const tmpPath = `${portFile}.tmp.${process.pid}`;
881
- writeFileSync(tmpPath, String(actualPort), { mode: 0o644 });
882
- renameSync(tmpPath, portFile);
883
- log.info({ portFile, actualPort }, "Wrote runtime port file");
884
- } catch (err) {
885
- log.warn(
886
- { err },
887
- "Failed to write runtime port file; non-default assistant ports may require --assistant-port on thin helpers",
888
- );
889
- }
890
- }
891
-
892
- /**
893
- * Remove the runtime port file written by `writeRuntimePortFile`.
894
- * Called from `stop()` on clean shutdown so a stale file does not
895
- * point thin helpers (e.g. the chrome-extension native messaging
896
- * helper) at a dead port until the next daemon start overwrites it.
897
- * Best-effort — unlink failures never block shutdown.
898
- *
899
- * The unlink is conditional: we only remove the file if its current
900
- * contents still match this server's port. The runtime-port file
901
- * lives at the user-home level (`~/.vellum/runtime-port`) and is
902
- * therefore shared across multiple daemon instances running on
903
- * different `RUNTIME_HTTP_PORT`s. If a sibling instance has already
904
- * rewritten the file with its own port, deleting it would strand
905
- * thin helpers on the default port `7821` and break their ability
906
- * to reach the still-running sibling.
907
- *
908
- * Note: this only runs on graceful shutdown. A crash leaves the
909
- * file in place; the next successful startup overwrites it.
910
- */
911
- private removeRuntimePortFile(): void {
912
- try {
913
- const portFile = getRuntimePortFilePath();
914
- if (!existsSync(portFile)) return;
915
- // Read-then-compare-then-unlink. Race-safe enough: the worst case
916
- // is that another instance writes the file between our read and
917
- // our unlink, in which case we erroneously delete its mapping.
918
- // That window is short (a few microseconds) and a sibling startup
919
- // will rewrite the file on its next port-publish call. The much
920
- // more common multi-instance race — sibling already overwrote
921
- // before our stop() runs — is correctly handled here as a no-op.
922
- const current = readFileSync(portFile, "utf-8").trim();
923
- if (current !== String(this.actualPort)) {
924
- log.info(
925
- { portFile, current, actualPort: this.actualPort },
926
- "Leaving runtime port file alone — owned by another instance",
927
- );
928
- return;
929
- }
930
- unlinkSync(portFile);
931
- log.info({ portFile }, "Removed runtime port file");
932
- } catch (err) {
933
- log.warn({ err }, "Failed to remove runtime port file");
934
- }
935
- }
936
-
937
709
  async stop(): Promise<void> {
938
- this.pairingStore.stop();
939
710
  stopGuardianExpirySweep();
940
711
  stopGuardianActionSweep();
941
712
  stopCanonicalGuardianExpirySweep();
@@ -952,12 +723,19 @@ export class RuntimeHttpServer {
952
723
  activeSttStreamSessions.delete(sessionId);
953
724
  }
954
725
 
726
+ const liveVoiceSessionId = this.liveVoiceSessionManager.activeSessionId;
727
+ if (liveVoiceSessionId) {
728
+ await this.liveVoiceSessionManager.releaseSession(
729
+ liveVoiceSessionId,
730
+ "manager_shutdown",
731
+ );
732
+ }
733
+
955
734
  if (this.server) {
956
735
  this.server.stop(true);
957
736
  this.server = null;
958
737
  log.info("Runtime HTTP server stopped");
959
738
  }
960
- this.removeRuntimePortFile();
961
739
  }
962
740
 
963
741
  private async handleRequest(
@@ -1026,43 +804,48 @@ export class RuntimeHttpServer {
1026
804
  return this.handleSttStreamUpgrade(req, server);
1027
805
  }
1028
806
 
807
+ // WebSocket upgrade for live voice — same private-network restrictions
808
+ // and gateway-service token verification as STT streaming.
809
+ if (
810
+ path === "/v1/live-voice" &&
811
+ req.headers.get("upgrade")?.toLowerCase() === "websocket"
812
+ ) {
813
+ return this.handleLiveVoiceUpgrade(req, server);
814
+ }
815
+
1029
816
  // Twilio webhook endpoints — before auth check because Twilio
1030
817
  // webhook POSTs don't include bearer tokens.
1031
818
  const twilioResponse = await this.handleTwilioWebhook(req, path);
1032
819
  if (twilioResponse) return twilioResponse;
1033
820
 
1034
821
  // Audio serving endpoint — before auth check because Twilio
1035
- // fetches these URLs directly. The audioId is an unguessable UUID.
822
+ // fetches these URLs directly (isPublic route, ATL-314).
1036
823
  const audioMatch = path.match(/^\/v1\/audio\/([^/]+)$/);
1037
824
  if (audioMatch && req.method === "GET") {
1038
- return handleGetAudio(audioMatch[1]);
1039
- }
1040
-
1041
- // Pairing endpoints (unauthenticated, secret-gated)
1042
- if (path === "/v1/pairing/request" && req.method === "POST") {
1043
- return await handlePairingRequest(req, this.pairingContext);
1044
- }
1045
- if (path === "/v1/pairing/status" && req.method === "GET") {
1046
- return handlePairingStatus(url, this.pairingContext);
1047
- }
1048
-
1049
- // Chrome extension capability-token pair endpoint — unauthenticated but
1050
- // restricted to loopback peers + an extension-id allowlist. Used by the
1051
- // native messaging helper to bootstrap a scoped token.
1052
- if (path === "/v1/browser-extension-pair") {
1053
- return await handleBrowserExtensionPair(req, server);
1054
- }
1055
-
1056
- // Guardian bootstrap and refresh endpoints — before JWT auth because
1057
- // bootstrap is the first endpoint called to obtain a JWT, and refresh
1058
- // needs to work when the access token is expired. Bootstrap has its
1059
- // own loopback IP validation; refresh is secured by the refresh token
1060
- // in the request body (32 random bytes, hash-only storage).
1061
- if (path === "/v1/guardian/init" && req.method === "POST") {
1062
- return await handleGuardianBootstrap(req, server);
1063
- }
1064
- if (path === "/v1/guardian/refresh" && req.method === "POST") {
1065
- return await handleGuardianRefresh(req);
825
+ const audioDef = AUDIO_ROUTES.find((r) => r.operationId === "audio_get")!;
826
+ const args = { pathParams: { audioId: audioMatch[1] } };
827
+ try {
828
+ const result = await audioDef.handler(args);
829
+ const headers =
830
+ typeof audioDef.responseHeaders === "function"
831
+ ? audioDef.responseHeaders(args)
832
+ : audioDef.responseHeaders;
833
+ if (result instanceof ReadableStream) {
834
+ return new Response(result as ReadableStream<Uint8Array>, {
835
+ headers,
836
+ });
837
+ }
838
+ return new Response(result as BodyInit, { headers });
839
+ } catch (err) {
840
+ if (err instanceof RouteError) {
841
+ return httpError(
842
+ err.code as HttpErrorCode,
843
+ err.message,
844
+ err.statusCode,
845
+ );
846
+ }
847
+ throw err;
848
+ }
1066
849
  }
1067
850
 
1068
851
  // Skill-registered routes (e.g. meet-bot event ingress). Handled before
@@ -1092,7 +875,7 @@ export class RuntimeHttpServer {
1092
875
  const normalizedPath = path.endsWith("/") ? path.slice(0, -1) : path;
1093
876
  const authResult =
1094
877
  normalizedPath === "/v1/host-browser-result" && req.method === "POST"
1095
- ? authenticateHostBrowserResultRequest(req)
878
+ ? await authenticateHostBrowserResultRequest(req)
1096
879
  : authenticateRequest(req);
1097
880
  if (!authResult.ok) {
1098
881
  return authResult.response;
@@ -1102,9 +885,18 @@ export class RuntimeHttpServer {
1102
885
  // Serve shareable app pages (outside /v1/ namespace, no rate limiting)
1103
886
  const pagesMatch = path.match(/^\/pages\/([^/]+)$/);
1104
887
  if (pagesMatch && req.method === "GET") {
1105
- return withErrorHandling("pages", async () =>
1106
- handleServePage(pagesMatch[1]),
1107
- );
888
+ return withErrorHandling("pages", async () => {
889
+ const pageDef = APP_ROUTES.find(
890
+ (r) => r.operationId === "pages_serve",
891
+ )!;
892
+ const args = { pathParams: { appId: pagesMatch[1] } };
893
+ const body = pageDef.handler(args) as string;
894
+ const headers =
895
+ typeof pageDef.responseHeaders === "function"
896
+ ? pageDef.responseHeaders(args)
897
+ : pageDef.responseHeaders;
898
+ return new Response(body, { headers });
899
+ });
1108
900
  }
1109
901
 
1110
902
  // Per-client-IP rate limiting for /v1/* endpoints. Authenticated requests
@@ -1166,10 +958,10 @@ export class RuntimeHttpServer {
1166
958
  return routerResponse ?? httpError("NOT_FOUND", "Not found", 404);
1167
959
  }
1168
960
 
1169
- private handleBrowserRelayUpgrade(
961
+ private async handleBrowserRelayUpgrade(
1170
962
  req: Request,
1171
963
  server: ReturnType<typeof Bun.serve>,
1172
- ): Response {
964
+ ): Promise<Response> {
1173
965
  if (
1174
966
  !isLoopbackHost(new URL(req.url).hostname) &&
1175
967
  !isPrivateNetworkPeer(server, req)
@@ -1185,8 +977,8 @@ export class RuntimeHttpServer {
1185
977
  // `/v1/browser-relay` handshake:
1186
978
  //
1187
979
  // 1. **Capability token** — a signed `host_browser_command`
1188
- // capability minted by `mintHostBrowserCapability()` and handed
1189
- // to the chrome extension by the native-messaging pair flow
980
+ // capability minted by the gateway and handed to the chrome
981
+ // extension by the native-messaging pair flow
1190
982
  // (`/v1/browser-extension-pair`). This is the preferred,
1191
983
  // self-hosted default: the extension never has to touch a
1192
984
  // gateway JWT.
@@ -1235,7 +1027,7 @@ export class RuntimeHttpServer {
1235
1027
  // messaging pair flow. We derive `guardianId` from the
1236
1028
  // capability claims directly — the claims are HMAC-signed by
1237
1029
  // the same daemon so there is no cross-tenant risk.
1238
- const capabilityClaims = verifyHostBrowserCapability(token);
1030
+ const capabilityClaims = await verifyHostBrowserCapability(token);
1239
1031
  if (capabilityClaims) {
1240
1032
  guardianId = capabilityClaims.guardianId;
1241
1033
  } else {
@@ -1304,6 +1096,28 @@ export class RuntimeHttpServer {
1304
1096
  return undefined!;
1305
1097
  }
1306
1098
 
1099
+ private verifyGatewayServiceToken(req: Request): Response | null {
1100
+ if (isHttpAuthDisabled()) return null;
1101
+
1102
+ const wsUrl = new URL(req.url);
1103
+ const token = wsUrl.searchParams.get("token");
1104
+ if (!token) {
1105
+ return httpError("UNAUTHORIZED", "Unauthorized", 401);
1106
+ }
1107
+
1108
+ const jwtResult = verifyToken(token, "vellum-daemon");
1109
+ if (!jwtResult.ok) {
1110
+ return httpError("UNAUTHORIZED", "Unauthorized", 401);
1111
+ }
1112
+
1113
+ const subResult = parseSub(jwtResult.claims.sub);
1114
+ if (!subResult.ok || subResult.principalType !== "svc_gateway") {
1115
+ return httpError("UNAUTHORIZED", "Unauthorized", 401);
1116
+ }
1117
+
1118
+ return null;
1119
+ }
1120
+
1307
1121
  private handleRelayUpgrade(
1308
1122
  req: Request,
1309
1123
  server: ReturnType<typeof Bun.serve>,
@@ -1316,6 +1130,10 @@ export class RuntimeHttpServer {
1316
1130
  );
1317
1131
  }
1318
1132
 
1133
+ // Verify the gateway service token before accepting the upgrade.
1134
+ const tokenError = this.verifyGatewayServiceToken(req);
1135
+ if (tokenError) return tokenError;
1136
+
1319
1137
  const wsUrl = new URL(req.url);
1320
1138
  const callSessionId = wsUrl.searchParams.get("callSessionId");
1321
1139
  if (!callSessionId) {
@@ -1341,6 +1159,10 @@ export class RuntimeHttpServer {
1341
1159
  );
1342
1160
  }
1343
1161
 
1162
+ // Verify the gateway service token before accepting the upgrade.
1163
+ const tokenError = this.verifyGatewayServiceToken(req);
1164
+ if (tokenError) return tokenError;
1165
+
1344
1166
  const wsUrl = new URL(req.url);
1345
1167
  const callSessionId = wsUrl.searchParams.get("callSessionId");
1346
1168
  if (!callSessionId) {
@@ -1382,23 +1204,8 @@ export class RuntimeHttpServer {
1382
1204
  }
1383
1205
 
1384
1206
  // Verify the gateway service token before accepting the upgrade.
1385
- if (!isHttpAuthDisabled()) {
1386
- const wsUrl = new URL(req.url);
1387
- const token = wsUrl.searchParams.get("token");
1388
- if (!token) {
1389
- return httpError("UNAUTHORIZED", "Unauthorized", 401);
1390
- }
1391
- const jwtResult = verifyToken(token, "vellum-daemon");
1392
- if (!jwtResult.ok) {
1393
- return httpError("UNAUTHORIZED", "Unauthorized", 401);
1394
- }
1395
- // Accept gateway service tokens (svc:gateway:*) — these are the
1396
- // only tokens the gateway mints for upstream connections.
1397
- const subResult = parseSub(jwtResult.claims.sub);
1398
- if (!subResult.ok || subResult.principalType !== "svc_gateway") {
1399
- return httpError("UNAUTHORIZED", "Unauthorized", 401);
1400
- }
1401
- }
1207
+ const tokenError = this.verifyGatewayServiceToken(req);
1208
+ if (tokenError) return tokenError;
1402
1209
 
1403
1210
  const wsUrl = new URL(req.url);
1404
1211
  // provider is optional compatibility metadata — the runtime resolves
@@ -1431,6 +1238,175 @@ export class RuntimeHttpServer {
1431
1238
  return undefined!;
1432
1239
  }
1433
1240
 
1241
+ /**
1242
+ * Handle WebSocket upgrade for `/v1/live-voice`.
1243
+ *
1244
+ * The gateway owns downstream client auth and forwards this upstream with
1245
+ * a short-lived gateway service token. The runtime accepts only private
1246
+ * network peers/origins so the shell is not publicly reachable.
1247
+ */
1248
+ private handleLiveVoiceUpgrade(
1249
+ req: Request,
1250
+ server: ReturnType<typeof Bun.serve>,
1251
+ ): Response {
1252
+ if (!isPrivateNetworkPeer(server, req) || !isPrivateNetworkOrigin(req)) {
1253
+ return httpError(
1254
+ "FORBIDDEN",
1255
+ "Direct live voice access disabled — only private network peers allowed",
1256
+ 403,
1257
+ );
1258
+ }
1259
+
1260
+ const tokenError = this.verifyGatewayServiceToken(req);
1261
+ if (tokenError) return tokenError;
1262
+
1263
+ const upgraded = server.upgrade(req, {
1264
+ data: {
1265
+ wsType: "live-voice",
1266
+ lastSeq: 0,
1267
+ } satisfies LiveVoiceWebSocketData,
1268
+ });
1269
+ if (!upgraded) {
1270
+ return new Response("WebSocket upgrade failed", { status: 500 });
1271
+ }
1272
+ return undefined!;
1273
+ }
1274
+
1275
+ private async handleLiveVoiceMessage(
1276
+ ws: ServerWebSocket<LiveVoiceWebSocketData>,
1277
+ message: string | ArrayBuffer | ArrayBufferView,
1278
+ ): Promise<void> {
1279
+ if (typeof message === "string") {
1280
+ const result = parseLiveVoiceClientTextFrame(message);
1281
+ if (!result.ok) {
1282
+ this.sendLiveVoiceError(ws, result.error);
1283
+ return;
1284
+ }
1285
+ await this.dispatchLiveVoiceClientFrame(ws, result.frame);
1286
+ return;
1287
+ }
1288
+
1289
+ const result = parseLiveVoiceBinaryAudioFrame(message);
1290
+ if (!result.ok) {
1291
+ this.sendLiveVoiceError(ws, result.error);
1292
+ return;
1293
+ }
1294
+
1295
+ const sessionId = ws.data.sessionId;
1296
+ if (!sessionId) {
1297
+ this.sendLiveVoiceStateError(
1298
+ ws,
1299
+ "Live voice binary audio received before start",
1300
+ );
1301
+ return;
1302
+ }
1303
+
1304
+ const handled = await this.liveVoiceSessionManager.handleBinaryAudio(
1305
+ sessionId,
1306
+ result.frame.data,
1307
+ );
1308
+ if (handled.status === "not_found") {
1309
+ ws.data.sessionId = undefined;
1310
+ this.sendLiveVoiceStateError(ws, "Live voice session is not active");
1311
+ }
1312
+ }
1313
+
1314
+ private async dispatchLiveVoiceClientFrame(
1315
+ ws: ServerWebSocket<LiveVoiceWebSocketData>,
1316
+ frame: LiveVoiceClientFrame,
1317
+ ): Promise<void> {
1318
+ if (frame.type === "start") {
1319
+ if (ws.data.sessionId) {
1320
+ this.sendLiveVoiceStateError(ws, "Live voice session already started");
1321
+ return;
1322
+ }
1323
+
1324
+ const result = await this.liveVoiceSessionManager.startSession(frame, {
1325
+ sendFrame: async (serverFrame) => {
1326
+ this.sendLiveVoiceFrame(ws, serverFrame);
1327
+ },
1328
+ });
1329
+ if (result.status === "accepted") {
1330
+ ws.data.sessionId = result.sessionId;
1331
+ }
1332
+ return;
1333
+ }
1334
+
1335
+ const sessionId = ws.data.sessionId;
1336
+ if (!sessionId) {
1337
+ this.sendLiveVoiceStateError(
1338
+ ws,
1339
+ `Live voice ${frame.type} frame received before start`,
1340
+ );
1341
+ return;
1342
+ }
1343
+
1344
+ const handled = await this.liveVoiceSessionManager.handleClientFrame(
1345
+ sessionId,
1346
+ frame,
1347
+ );
1348
+ if (handled.status === "not_found") {
1349
+ ws.data.sessionId = undefined;
1350
+ this.sendLiveVoiceStateError(ws, "Live voice session is not active");
1351
+ return;
1352
+ }
1353
+
1354
+ if (frame.type === "end") {
1355
+ ws.data.sessionId = undefined;
1356
+ }
1357
+ }
1358
+
1359
+ private sendLiveVoiceStateError(
1360
+ ws: ServerWebSocket<LiveVoiceWebSocketData>,
1361
+ message: string,
1362
+ ): void {
1363
+ this.sendLiveVoiceError(ws, {
1364
+ code: LiveVoiceProtocolErrorCode.InvalidFrame,
1365
+ message,
1366
+ });
1367
+ }
1368
+
1369
+ private sendLiveVoiceError(
1370
+ ws: ServerWebSocket<LiveVoiceWebSocketData>,
1371
+ error: Pick<LiveVoiceProtocolError, "code" | "message">,
1372
+ ): void {
1373
+ this.sendLiveVoiceFrame(ws, {
1374
+ type: "error",
1375
+ seq: ws.data.lastSeq + 1,
1376
+ code: error.code,
1377
+ message: error.message,
1378
+ });
1379
+ }
1380
+
1381
+ private sendLiveVoiceFrame(
1382
+ ws: ServerWebSocket<LiveVoiceWebSocketData>,
1383
+ frame: LiveVoiceServerFrame,
1384
+ ): void {
1385
+ ws.data.lastSeq = Math.max(ws.data.lastSeq, frame.seq);
1386
+ ws.send(JSON.stringify(frame));
1387
+ }
1388
+
1389
+ private releaseLiveVoiceSession(
1390
+ data: LiveVoiceWebSocketData,
1391
+ reason: "websocket_close",
1392
+ ): void {
1393
+ const sessionId = data.sessionId;
1394
+ data.sessionId = undefined;
1395
+ if (!sessionId) return;
1396
+
1397
+ void this.liveVoiceSessionManager
1398
+ .releaseSession(sessionId, reason)
1399
+ .catch((err) => {
1400
+ log.warn(
1401
+ {
1402
+ error: err instanceof Error ? err.message : String(err),
1403
+ sessionId,
1404
+ },
1405
+ "Failed to release live voice session",
1406
+ );
1407
+ });
1408
+ }
1409
+
1434
1410
  private async handleTwilioWebhook(
1435
1411
  req: Request,
1436
1412
  path: string,
@@ -1471,202 +1447,6 @@ export class RuntimeHttpServer {
1471
1447
  return null;
1472
1448
  }
1473
1449
 
1474
- private handleGetInterface(interfacePath: string): Response {
1475
- if (!this.interfacesDir) {
1476
- return httpError("NOT_FOUND", "Interface not found", 404);
1477
- }
1478
- const fullPath = resolve(this.interfacesDir, interfacePath);
1479
- if (
1480
- (fullPath !== this.interfacesDir &&
1481
- !fullPath.startsWith(this.interfacesDir + "/")) ||
1482
- !existsSync(fullPath)
1483
- ) {
1484
- return httpError("NOT_FOUND", "Interface not found", 404);
1485
- }
1486
- const source = readFileSync(fullPath, "utf-8");
1487
- return new Response(source, {
1488
- headers: { "Content-Type": "text/plain; charset=utf-8" },
1489
- });
1490
- }
1491
-
1492
- private buildAssistantAttention(attentionState: AttentionState | undefined):
1493
- | {
1494
- hasUnseenLatestAssistantMessage: boolean;
1495
- latestAssistantMessageAt?: number;
1496
- lastSeenAssistantMessageAt?: number;
1497
- lastSeenConfidence?: Confidence;
1498
- lastSeenSignalType?: SignalType;
1499
- }
1500
- | undefined {
1501
- if (!attentionState) return undefined;
1502
-
1503
- return {
1504
- hasUnseenLatestAssistantMessage:
1505
- attentionState.latestAssistantMessageAt != null &&
1506
- (attentionState.lastSeenAssistantMessageAt == null ||
1507
- attentionState.lastSeenAssistantMessageAt <
1508
- attentionState.latestAssistantMessageAt),
1509
- ...(attentionState.latestAssistantMessageAt != null
1510
- ? {
1511
- latestAssistantMessageAt: attentionState.latestAssistantMessageAt,
1512
- }
1513
- : {}),
1514
- ...(attentionState.lastSeenAssistantMessageAt != null
1515
- ? {
1516
- lastSeenAssistantMessageAt:
1517
- attentionState.lastSeenAssistantMessageAt,
1518
- }
1519
- : {}),
1520
- ...(attentionState.lastSeenConfidence != null
1521
- ? { lastSeenConfidence: attentionState.lastSeenConfidence }
1522
- : {}),
1523
- ...(attentionState.lastSeenSignalType != null
1524
- ? { lastSeenSignalType: attentionState.lastSeenSignalType }
1525
- : {}),
1526
- };
1527
- }
1528
-
1529
- private buildForkParent(
1530
- conversation: ConversationRow,
1531
- parentCache: Map<string, ConversationRow | null>,
1532
- ): { conversationId: string; messageId: string; title: string } | undefined {
1533
- const parentConversationId = conversation.forkParentConversationId;
1534
- const parentMessageId = conversation.forkParentMessageId;
1535
- if (!parentConversationId || !parentMessageId) return undefined;
1536
-
1537
- let parentConversation: ConversationRow | null | undefined =
1538
- parentCache.get(parentConversationId);
1539
- if (parentConversation === undefined) {
1540
- parentConversation = getConversation(parentConversationId);
1541
- parentCache.set(parentConversationId, parentConversation);
1542
- }
1543
- if (
1544
- !parentConversation ||
1545
- parentConversation.conversationType === "private"
1546
- ) {
1547
- return undefined;
1548
- }
1549
-
1550
- return {
1551
- conversationId: parentConversationId,
1552
- messageId: parentMessageId,
1553
- title: parentConversation.title ?? "Untitled",
1554
- };
1555
- }
1556
-
1557
- private serializeConversationSummary(params: {
1558
- conversation: ConversationRow;
1559
- binding?: ExternalConversationBinding | null;
1560
- attentionState?: AttentionState;
1561
- displayMeta?: {
1562
- displayOrder: number | null;
1563
- isPinned: boolean;
1564
- groupId: string | null;
1565
- };
1566
- parentCache: Map<string, ConversationRow | null>;
1567
- }) {
1568
- const { conversation, binding, attentionState, displayMeta, parentCache } =
1569
- params;
1570
- const originChannel = parseChannelId(conversation.originChannel);
1571
- const assistantAttention = this.buildAssistantAttention(attentionState);
1572
- const forkParent = this.buildForkParent(conversation, parentCache);
1573
-
1574
- return {
1575
- id: conversation.id,
1576
- title: conversation.title ?? "Untitled",
1577
- createdAt: conversation.createdAt,
1578
- updatedAt: conversation.updatedAt,
1579
- lastMessageAt: conversation.lastMessageAt,
1580
- conversationType: conversation.conversationType ?? "standard",
1581
- source: conversation.source ?? "user",
1582
- hostAccess: conversation.hostAccess === 1,
1583
- ...(conversation.scheduleJobId
1584
- ? { scheduleJobId: conversation.scheduleJobId }
1585
- : {}),
1586
- ...(binding
1587
- ? {
1588
- channelBinding: {
1589
- sourceChannel: binding.sourceChannel,
1590
- externalChatId: binding.externalChatId,
1591
- externalUserId: binding.externalUserId,
1592
- displayName: binding.displayName,
1593
- username: binding.username,
1594
- },
1595
- }
1596
- : {}),
1597
- ...(originChannel ? { conversationOriginChannel: originChannel } : {}),
1598
- ...(assistantAttention ? { assistantAttention } : {}),
1599
- ...(displayMeta?.isPinned
1600
- ? {
1601
- isPinned: true as const,
1602
- displayOrder: displayMeta.displayOrder,
1603
- }
1604
- : displayMeta?.displayOrder != null
1605
- ? {
1606
- displayOrder: displayMeta.displayOrder,
1607
- }
1608
- : {}),
1609
- groupId: displayMeta?.groupId ?? null,
1610
- ...(forkParent ? { forkParent } : {}),
1611
- ...(conversation.archivedAt != null
1612
- ? { archivedAt: conversation.archivedAt }
1613
- : {}),
1614
- };
1615
- }
1616
-
1617
- private buildConversationDetailResponse(conversationId: string) {
1618
- const conversation = getConversation(conversationId);
1619
- if (!conversation) {
1620
- return null;
1621
- }
1622
-
1623
- const bindings = externalConversationStore.getBindingsForConversations([
1624
- conversation.id,
1625
- ]);
1626
- const attentionStates = getAttentionStateByConversationIds([
1627
- conversation.id,
1628
- ]);
1629
- const displayMeta = getDisplayMetaForConversations([conversation.id]);
1630
- const parentCache = new Map<string, ConversationRow | null>();
1631
-
1632
- return {
1633
- conversation: this.serializeConversationSummary({
1634
- conversation,
1635
- binding: bindings.get(conversation.id),
1636
- attentionState: attentionStates.get(conversation.id),
1637
- displayMeta: displayMeta.get(conversation.id),
1638
- parentCache,
1639
- }),
1640
- };
1641
- }
1642
-
1643
- private getConversationManagementRouteDeps(): ConversationManagementDeps | null {
1644
- if (!this.conversationManagementDeps) {
1645
- return null;
1646
- }
1647
-
1648
- return {
1649
- ...this.conversationManagementDeps,
1650
- forkConversation:
1651
- this.conversationManagementDeps.forkConversation ??
1652
- (async ({ conversationId, throughMessageId }) => {
1653
- const forkedConversation = forkConversationInStore({
1654
- conversationId,
1655
- throughMessageId,
1656
- });
1657
- const detail = this.buildConversationDetailResponse(
1658
- forkedConversation.id,
1659
- );
1660
- if (!detail) {
1661
- throw new Error(
1662
- `Forked conversation ${forkedConversation.id} could not be loaded`,
1663
- );
1664
- }
1665
- return detail.conversation;
1666
- }),
1667
- };
1668
- }
1669
-
1670
1450
  // ---------------------------------------------------------------------------
1671
1451
  // Declarative route table
1672
1452
  // ---------------------------------------------------------------------------
@@ -1680,552 +1460,7 @@ export class RuntimeHttpServer {
1680
1460
  * `./routes/` and composed here via spread. The composition order
1681
1461
  * preserves the original top-to-bottom matching semantics.
1682
1462
  */
1683
- private buildRouteTable(): RouteDefinition[] {
1684
- const assistantId = DAEMON_INTERNAL_ASSISTANT_ID;
1685
- const conversationManagementDeps =
1686
- this.getConversationManagementRouteDeps();
1687
-
1688
- return [
1689
- ...pairingRouteDefinitions({
1690
- getPairingContext: () => this.pairingContext,
1691
- }),
1692
- ...appRouteDefinitions(),
1693
- ...appManagementRouteDefinitions(),
1694
- ...secretRouteDefinitions({
1695
- getCesClient: this.getCesClient,
1696
- onProviderCredentialsChanged: this.onProviderCredentialsChanged,
1697
- }),
1698
- ...identityRouteDefinitions(),
1699
- ...upgradeBroadcastRouteDefinitions(),
1700
- ...workspaceCommitRouteDefinitions(),
1701
- ...migrationRollbackRouteDefinitions(),
1702
- ...debugRouteDefinitions(),
1703
- ...usageRouteDefinitions(),
1704
- ...telemetryRouteDefinitions(),
1705
- ...workspaceRouteDefinitions(),
1706
- ...memoryItemRouteDefinitions(),
1707
- ...conversationStarterRouteDefinitions(),
1708
- ...settingsRouteDefinitions(),
1709
- ...avatarRouteDefinitions(),
1710
- ...scheduleRouteDefinitions({
1711
- sendMessageDeps: this.sendMessageDeps,
1712
- }),
1713
- ...heartbeatRouteDefinitions({
1714
- getHeartbeatService: this.getHeartbeatService,
1715
- }),
1716
- ...filingRouteDefinitions({
1717
- getFilingService: this.getFilingService,
1718
- }),
1719
- ...homeStateRouteDefinitions(),
1720
- ...homeFeedRouteDefinitions(),
1721
- ...notificationRouteDefinitions(),
1722
- ...diagnosticsRouteDefinitions(),
1723
- ...logExportRouteDefinitions(),
1724
- ...profilerRouteDefinitions(),
1725
- ...documentRouteDefinitions(),
1726
- ...workItemRouteDefinitions(
1727
- this.sendMessageDeps
1728
- ? {
1729
- getOrCreateConversation: (conversationId) =>
1730
- this.sendMessageDeps!.getOrCreateConversation(conversationId),
1731
- findConversation: this.findConversation
1732
- ? (conversationId) => {
1733
- const s = this.findConversation!(conversationId);
1734
- if (!s || !("abort" in s)) return undefined;
1735
- return s as import("../daemon/conversation.js").Conversation;
1736
- }
1737
- : undefined,
1738
- }
1739
- : undefined,
1740
- ),
1741
- ...acpRouteDefinitions(),
1742
- ...subagentRouteDefinitions(),
1743
- ...conversationQueryRouteDefinitions({
1744
- getModelSetContext: this.getModelSetContext,
1745
- findConversationForQueue: this.findConversation
1746
- ? (id) => {
1747
- const s = this.findConversation!(id);
1748
- if (!s?.removeQueuedMessage) return undefined;
1749
- return { removeQueuedMessage: s.removeQueuedMessage.bind(s) };
1750
- }
1751
- : undefined,
1752
- }),
1753
- ...ttsRouteDefinitions(),
1754
- ...sttRouteDefinitions(),
1755
-
1756
- // Conversation list and seen signal — kept inline because they
1757
- // depend on multiple cross-cutting stores that aren't grouped
1758
- // into a single domain module.
1759
- {
1760
- endpoint: "conversations",
1761
- method: "GET",
1762
- handler: ({ url }) => {
1763
- const limit = Number(url.searchParams.get("limit") ?? 50);
1764
- const offset = Number(url.searchParams.get("offset") ?? 0);
1765
- const backgroundOnly =
1766
- url.searchParams.get("conversationType") === "background";
1767
- let rows = listConversations(limit, backgroundOnly, offset);
1768
- const totalCount = countConversations(backgroundOnly);
1769
- // On the first page, ensure all pinned conversations are included
1770
- // even if they fall outside the paginated window.
1771
- if (offset === 0 && !backgroundOnly) {
1772
- const pinned = listPinnedConversations();
1773
- const seen = new Set(rows.map((c) => c.id));
1774
- const missing = pinned.filter((c) => !seen.has(c.id));
1775
- if (missing.length > 0) {
1776
- rows = [...rows, ...missing];
1777
- }
1778
- }
1779
- const conversationIds = rows.map((c) => c.id);
1780
- const displayMeta = getDisplayMetaForConversations(conversationIds);
1781
- const bindings =
1782
- externalConversationStore.getBindingsForConversations(
1783
- conversationIds,
1784
- );
1785
- const attentionStates =
1786
- getAttentionStateByConversationIds(conversationIds);
1787
- const parentCache = new Map<string, ConversationRow | null>();
1788
- const nextOffset = offset + limit;
1789
- const response: Record<string, unknown> = {
1790
- conversations: rows.map((conversation) =>
1791
- this.serializeConversationSummary({
1792
- conversation,
1793
- binding: bindings.get(conversation.id),
1794
- attentionState: attentionStates.get(conversation.id),
1795
- displayMeta: displayMeta.get(conversation.id),
1796
- parentCache,
1797
- }),
1798
- ),
1799
- nextOffset,
1800
- hasMore: nextOffset < totalCount,
1801
- };
1802
- // Include groups array on first page only
1803
- if (offset === 0) {
1804
- const groups = listGroups();
1805
- response.groups = groups.map((g) => ({
1806
- id: g.id,
1807
- name: g.name,
1808
- sortPosition: g.sortPosition,
1809
- isSystemGroup: g.isSystemGroup,
1810
- }));
1811
- }
1812
- return Response.json(response);
1813
- },
1814
- },
1815
- ...conversationAttentionRouteDefinitions(),
1816
-
1817
- ...(conversationManagementDeps
1818
- ? conversationManagementRouteDefinitions(conversationManagementDeps)
1819
- : []),
1820
-
1821
- ...((): RouteDefinition[] => {
1822
- const sendMessageDeps = this.sendMessageDeps;
1823
- if (!sendMessageDeps) return [];
1824
- const analysisDeps = {
1825
- sendMessageDeps,
1826
- buildConversationDetailResponse: (id: string) =>
1827
- this.buildConversationDetailResponse(id),
1828
- };
1829
- // Also expose via the module singleton so background callers
1830
- // (e.g. job handlers) can invoke analyzeConversation() without
1831
- // HTTP-layer wiring. Daemon startup must never block, so failures
1832
- // to register the singleton are logged and swallowed.
1833
- try {
1834
- setAnalysisDeps(analysisDeps);
1835
- } catch (err) {
1836
- log.warn(
1837
- { err },
1838
- "Failed to register analysis deps singleton; background analysis jobs will be skipped",
1839
- );
1840
- }
1841
- return conversationAnalysisRouteDefinitions(analysisDeps);
1842
- })(),
1843
-
1844
- ...groupRouteDefinitions(),
1845
-
1846
- {
1847
- endpoint: "conversations/seen",
1848
- method: "POST",
1849
- handler: async ({ req }) => {
1850
- const body = (await req.json()) as Record<string, unknown>;
1851
- const rawConversationId = body.conversationId as string | undefined;
1852
- if (!rawConversationId)
1853
- return httpError("BAD_REQUEST", "Missing conversationId", 400);
1854
- // The client may send a conversation key rather than the internal
1855
- // conversation ID. Resolve to the internal ID to satisfy FK constraints.
1856
- const conversationId = resolveConversationId(rawConversationId);
1857
- if (!conversationId)
1858
- return httpError(
1859
- "NOT_FOUND",
1860
- `Unknown conversation: ${rawConversationId}`,
1861
- 404,
1862
- );
1863
- try {
1864
- // Snapshot current state to detect whether the seen cursor
1865
- // actually advances (avoids emitting on no-op signals).
1866
- // Only consider a conversation "unseen" when a latest assistant
1867
- // message exists and the seen cursor is behind it — matching
1868
- // the hasUnseenLatestAssistantMessage logic in buildAssistantAttention.
1869
- const priorState = getAttentionStateByConversationIds([
1870
- conversationId,
1871
- ]).get(conversationId);
1872
- const wasUnseen =
1873
- priorState != null &&
1874
- priorState.latestAssistantMessageAt != null &&
1875
- (priorState.lastSeenAssistantMessageAt == null ||
1876
- priorState.lastSeenAssistantMessageAt <
1877
- priorState.latestAssistantMessageAt);
1878
-
1879
- recordConversationSeenSignal({
1880
- conversationId,
1881
- sourceChannel: (body.sourceChannel as string) ?? "vellum",
1882
- signalType: ((body.signalType as string) ??
1883
- "macos_conversation_opened") as SignalType,
1884
- confidence: ((body.confidence as string) ??
1885
- "explicit") as Confidence,
1886
- source: (body.source as string) ?? "http-api",
1887
- evidenceText: body.evidenceText as string | undefined,
1888
- metadata: body.metadata as Record<string, unknown> | undefined,
1889
- observedAt: body.observedAt as number | undefined,
1890
- });
1891
- if (wasUnseen) {
1892
- assistantEventHub
1893
- .publish(
1894
- buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
1895
- type: "conversation_list_invalidated",
1896
- reason: "seen_changed",
1897
- }),
1898
- )
1899
- .catch((err) => {
1900
- log.warn(
1901
- { err },
1902
- "Failed to publish conversation_list_invalidated (seen_changed)",
1903
- );
1904
- });
1905
- }
1906
- return Response.json({ ok: true });
1907
- } catch (err) {
1908
- log.error(
1909
- { err, conversationId },
1910
- "POST /v1/conversations/seen: failed",
1911
- );
1912
- return httpError(
1913
- "INTERNAL_ERROR",
1914
- "Failed to record seen signal",
1915
- 500,
1916
- );
1917
- }
1918
- },
1919
- },
1920
-
1921
- {
1922
- endpoint: "conversations/unread",
1923
- method: "POST",
1924
- handler: async ({ req }) => {
1925
- const body = (await req.json()) as Record<string, unknown>;
1926
- const rawConversationId = body.conversationId as string | undefined;
1927
- if (!rawConversationId)
1928
- return httpError("BAD_REQUEST", "Missing conversationId", 400);
1929
- const conversationId = resolveConversationId(rawConversationId);
1930
- if (!conversationId)
1931
- return httpError(
1932
- "NOT_FOUND",
1933
- `Unknown conversation: ${rawConversationId}`,
1934
- 404,
1935
- );
1936
- try {
1937
- const changed = markConversationUnread(conversationId);
1938
- if (changed) {
1939
- assistantEventHub
1940
- .publish(
1941
- buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
1942
- type: "conversation_list_invalidated",
1943
- reason: "seen_changed",
1944
- }),
1945
- )
1946
- .catch((err) => {
1947
- log.warn(
1948
- { err },
1949
- "Failed to publish conversation_list_invalidated (seen_changed)",
1950
- );
1951
- });
1952
- }
1953
- return Response.json({ ok: true });
1954
- } catch (err) {
1955
- if (err instanceof UserError) {
1956
- return httpError("UNPROCESSABLE_ENTITY", err.message, 422);
1957
- }
1958
- log.error(
1959
- { err, conversationId },
1960
- "POST /v1/conversations/unread: failed",
1961
- );
1962
- return httpError(
1963
- "INTERNAL_ERROR",
1964
- "Failed to mark conversation unread",
1965
- 500,
1966
- );
1967
- }
1968
- },
1969
- },
1970
-
1971
- // conversations/:id must be registered AFTER all literal conversations/<word>
1972
- // routes above (attention, seen, unread) so the parameterized :id does not
1973
- // shadow them.
1974
- {
1975
- endpoint: "conversations/:id",
1976
- method: "GET",
1977
- handler: ({ params }) => {
1978
- const detail = this.buildConversationDetailResponse(params.id);
1979
- if (!detail) {
1980
- return httpError(
1981
- "NOT_FOUND",
1982
- `Conversation ${params.id} not found`,
1983
- 404,
1984
- );
1985
- }
1986
- return Response.json(detail);
1987
- },
1988
- },
1989
-
1990
- ...btwRouteDefinitions({
1991
- sendMessageDeps: this.sendMessageDeps,
1992
- }),
1993
-
1994
- ...conversationRouteDefinitions({
1995
- interfacesDir: this.interfacesDir,
1996
- sendMessageDeps: this.sendMessageDeps,
1997
- approvalConversationGenerator: this.approvalConversationGenerator,
1998
- suggestionCache: this.suggestionCache,
1999
- suggestionInFlight: this.suggestionInFlight,
2000
- getHeartbeatService: this.getHeartbeatService,
2001
- }),
2002
- ...playgroundRouteDefinitions({
2003
- getConversationById: async (id) => {
2004
- // Gate on DB existence first so genuinely-missing IDs return
2005
- // `undefined` (preserving the route handlers' 404 path) rather
2006
- // than triggering `getOrCreateConversation`'s create branch and
2007
- // masking the not-found case. For existing-but-not-loaded rows
2008
- // (e.g. freshly seeded by `POST /playground/seed-conversation`),
2009
- // hydrate the in-memory `Conversation` on demand so conv-scoped
2010
- // playground routes work without first opening the conversation
2011
- // in the main window.
2012
- if (!getConversation(id)) return undefined;
2013
- const sendDeps = this.sendMessageDeps;
2014
- if (!sendDeps) {
2015
- // Fall back to the in-memory active map when the daemon hasn't
2016
- // wired the hydration-capable accessor (e.g. unit tests).
2017
- const s = this.findConversation?.(id);
2018
- if (!s || !("abort" in s)) return undefined;
2019
- return s as import("../daemon/conversation.js").Conversation;
2020
- }
2021
- return sendDeps.getOrCreateConversation(id);
2022
- },
2023
- isPlaygroundEnabled: () =>
2024
- isAssistantFeatureFlagEnabled("compaction-playground", getConfig()),
2025
- listConversationsByTitlePrefix: (prefix) =>
2026
- listConversationsByTitlePrefix(prefix),
2027
- deleteConversationById: (id) => {
2028
- // Existence check first so we can report `false` for missing rows
2029
- // — `deleteConversation` always returns a result object even when
2030
- // no row matched.
2031
- if (!getConversation(id)) return false;
2032
- // Mirror the canonical DELETE /v1/conversations/:id handler in
2033
- // conversation-management-routes.ts: tear down the in-memory
2034
- // Conversation first (so a running agent loop can't write to a
2035
- // deleted row and trip FK constraints), then drop the DB row,
2036
- // then enqueue Qdrant vector cleanup for the returned segment
2037
- // and summary IDs. Without this, seeded-then-deleted playground
2038
- // conversations leak vectors and zombie Conversation objects.
2039
- if (this.findConversation?.(id)) {
2040
- this.conversationManagementDeps?.destroyConversation(id);
2041
- }
2042
- const deleted = deleteConversation(id);
2043
- for (const segId of deleted.segmentIds) {
2044
- enqueueMemoryJob("delete_qdrant_vectors", {
2045
- targetType: "segment",
2046
- targetId: segId,
2047
- });
2048
- }
2049
- for (const summaryId of deleted.deletedSummaryIds) {
2050
- enqueueMemoryJob("delete_qdrant_vectors", {
2051
- targetType: "summary",
2052
- targetId: summaryId,
2053
- });
2054
- }
2055
- return true;
2056
- },
2057
- createConversation: async (title) => {
2058
- const row = createConversation({ title });
2059
- return { id: row.id };
2060
- },
2061
- addMessage: async (conversationId, role, contentJson, options) => {
2062
- const persisted = await addMessage(
2063
- conversationId,
2064
- role,
2065
- contentJson,
2066
- undefined,
2067
- options,
2068
- );
2069
- return { id: persisted.id };
2070
- },
2071
- }),
2072
- ...globalSearchRouteDefinitions(),
2073
- ...approvalRouteDefinitions(),
2074
- ...hostBashRouteDefinitions(),
2075
- ...hostBrowserRouteDefinitions(),
2076
- ...hostCuRouteDefinitions(),
2077
- ...hostFileRouteDefinitions(),
2078
- ...(this.getSkillContext
2079
- ? skillRouteDefinitions({
2080
- getSkillContext: this.getSkillContext,
2081
- })
2082
- : []),
2083
- ...trustRulesRouteDefinitions(),
2084
- ...surfaceActionRouteDefinitions({
2085
- findConversation: this.findConversation,
2086
- findConversationBySurfaceId: this.findConversationBySurfaceId,
2087
- }),
2088
- ...surfaceContentRouteDefinitions({
2089
- findConversation: this.findConversation,
2090
- }),
2091
- ...guardianActionRouteDefinitions(),
2092
-
2093
- ...contactRouteDefinitions(),
2094
- ...inviteRouteDefinitions(),
2095
- // contacts/:id catch-all must follow invite routes to avoid shadowing
2096
- ...contactCatchAllRouteDefinitions(),
2097
-
2098
- ...telegramRouteDefinitions(),
2099
- ...channelVerificationRouteDefinitions(),
2100
- ...slackChannelRouteDefinitions(),
2101
- ...slackShareRouteDefinitions(),
2102
- ...twilioRouteDefinitions(),
2103
- ...vercelRouteDefinitions(),
2104
- ...channelReadinessRouteDefinitions(),
2105
- ...oauthProvidersRouteDefinitions(),
2106
- ...oauthAppsRouteDefinitions(),
2107
- ...attachmentRouteDefinitions(),
2108
-
2109
- ...(this.getRecordingDeps
2110
- ? recordingRouteDefinitions({
2111
- getRecordingDeps: this.getRecordingDeps,
2112
- })
2113
- : []),
2114
-
2115
- {
2116
- endpoint: "interfaces/:path*",
2117
- method: "GET",
2118
- policyKey: "interfaces",
2119
- handler: ({ params }) => this.handleGetInterface(params.path),
2120
- },
2121
-
2122
- ...channelRouteDefinitions({
2123
- assistantId,
2124
- processMessage: this.processMessage,
2125
- approvalCopyGenerator: this.approvalCopyGenerator,
2126
- approvalConversationGenerator: this.approvalConversationGenerator,
2127
- guardianActionCopyGenerator: this.guardianActionCopyGenerator,
2128
- guardianFollowUpConversationGenerator:
2129
- this.guardianFollowUpConversationGenerator,
2130
- getHeartbeatService: this.getHeartbeatService,
2131
- }),
2132
- ...callRouteDefinitions({ assistantId }),
2133
-
2134
- // Internal Twilio forwarding (gateway -> runtime) — kept inline
2135
- // because these reconstruct fake form-encoded requests from JSON,
2136
- // a pattern specific to the gateway-to-daemon bridge.
2137
- {
2138
- endpoint: "internal/twilio/voice-webhook",
2139
- method: "POST",
2140
- handler: async ({ req }) => {
2141
- const json = (await req.json()) as {
2142
- params: Record<string, string>;
2143
- originalUrl?: string;
2144
- };
2145
- const formBody = new URLSearchParams(json.params).toString();
2146
- const reconstructedUrl = json.originalUrl ?? req.url;
2147
- const fakeReq = new Request(reconstructedUrl, {
2148
- method: "POST",
2149
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
2150
- body: formBody,
2151
- });
2152
- return handleVoiceWebhook(fakeReq);
2153
- },
2154
- },
2155
- {
2156
- endpoint: "internal/twilio/status",
2157
- method: "POST",
2158
- handler: async ({ req }) => {
2159
- const json = (await req.json()) as {
2160
- params: Record<string, string>;
2161
- };
2162
- const formBody = new URLSearchParams(json.params).toString();
2163
- const fakeReq = new Request(req.url, {
2164
- method: "POST",
2165
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
2166
- body: formBody,
2167
- });
2168
- return handleStatusCallback(fakeReq);
2169
- },
2170
- },
2171
- {
2172
- endpoint: "internal/twilio/connect-action",
2173
- method: "POST",
2174
- handler: async ({ req }) => {
2175
- const json = (await req.json()) as {
2176
- params: Record<string, string>;
2177
- };
2178
- const formBody = new URLSearchParams(json.params).toString();
2179
- const fakeReq = new Request(req.url, {
2180
- method: "POST",
2181
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
2182
- body: formBody,
2183
- });
2184
- return handleConnectAction(fakeReq);
2185
- },
2186
- },
2187
-
2188
- ...brainGraphRouteDefinitions({ mintUiPageToken }),
2189
- ...eventsRouteDefinitions(),
2190
- ...traceEventRouteDefinitions(),
2191
- ...migrationRouteDefinitions(),
2192
- ...backupRouteDefinitions(),
2193
-
2194
- // User-defined routes under /x/* — must be LAST so built-in routes
2195
- // always take priority.
2196
- ...userRouteDefinitions(),
2197
-
2198
- // Internal OAuth callback (gateway -> runtime)
2199
- {
2200
- endpoint: "internal/oauth/callback",
2201
- method: "POST",
2202
- handler: async ({ req }) => {
2203
- const json = (await req.json()) as {
2204
- state: string;
2205
- code?: string;
2206
- error?: string;
2207
- };
2208
- if (!json.state)
2209
- return httpError("BAD_REQUEST", "Missing state parameter", 400);
2210
- if (json.error) {
2211
- const consumed = consumeCallbackError(json.state, json.error);
2212
- return consumed
2213
- ? Response.json({ ok: true })
2214
- : httpError("NOT_FOUND", "Unknown state", 404);
2215
- }
2216
- if (json.code) {
2217
- const consumed = consumeCallback(json.state, json.code);
2218
- return consumed
2219
- ? Response.json({ ok: true })
2220
- : httpError("NOT_FOUND", "Unknown state", 404);
2221
- }
2222
- return httpError(
2223
- "BAD_REQUEST",
2224
- "Missing code or error parameter",
2225
- 400,
2226
- );
2227
- },
2228
- },
2229
- ];
1463
+ private buildRouteTable(): HTTPRouteDefinition[] {
1464
+ return [...routeDefinitionsToHTTPRoutes(ROUTES)];
2230
1465
  }
2231
1466
  }