@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
@@ -19,6 +19,7 @@ import {
19
19
  } from "../../agent/message-types.js";
20
20
  import {
21
21
  canServiceRegistryBrowser,
22
+ canServiceSseBrowser,
22
23
  CHANNEL_IDS,
23
24
  INTERFACE_IDS,
24
25
  type InterfaceId,
@@ -29,6 +30,7 @@ import {
29
30
  } from "../../channels/types.js";
30
31
  import { isHttpAuthDisabled } from "../../config/env.js";
31
32
  import { getConfig } from "../../config/loader.js";
33
+ import { createApprovalConversationGenerator } from "../../daemon/approval-generators.js";
32
34
  import type { Conversation } from "../../daemon/conversation.js";
33
35
  import {
34
36
  buildModelInfoEvent,
@@ -39,6 +41,7 @@ import {
39
41
  resolveSlash,
40
42
  type SlashContext,
41
43
  } from "../../daemon/conversation-slash.js";
44
+ import { getOrCreateConversation as getOrCreateConversationInstance } from "../../daemon/conversation-store.js";
42
45
  import {
43
46
  getCannedFirstGreeting,
44
47
  isWakeUpGreeting,
@@ -48,19 +51,26 @@ import { HostBashProxy } from "../../daemon/host-bash-proxy.js";
48
51
  import { HostBrowserProxy } from "../../daemon/host-browser-proxy.js";
49
52
  import { HostCuProxy } from "../../daemon/host-cu-proxy.js";
50
53
  import { HostFileProxy } from "../../daemon/host-file-proxy.js";
54
+ import { HostTransferProxy } from "../../daemon/host-transfer-proxy.js";
51
55
  import type { ServerMessage } from "../../daemon/message-protocol.js";
52
56
  import type {
53
57
  HostProxyTransportMetadata,
54
58
  NonHostProxyTransportMetadata,
55
59
  } from "../../daemon/message-types/conversations.js";
56
- import type { HeartbeatService } from "../../heartbeat/heartbeat-service.js";
60
+ import { HeartbeatService } from "../../heartbeat/heartbeat-service.js";
57
61
  import { emitFeedEvent } from "../../home/emit-feed-event.js";
58
62
  import {
59
63
  writeOnboardingSidecar,
60
64
  writeRelationshipState,
61
65
  } from "../../home/relationship-state-writer.js";
62
66
  import { rewriteCommandPreview } from "../../home/rewrite-command-preview.js";
63
- import * as attachmentsStore from "../../memory/attachments-store.js";
67
+ import { ipcCall } from "../../ipc/gateway-client.js";
68
+ import {
69
+ getAttachmentById,
70
+ getAttachmentMetadataForMessage,
71
+ getAttachmentsByIds,
72
+ getSourcePathsForAttachments,
73
+ } from "../../memory/attachments-store.js";
64
74
  import {
65
75
  createCanonicalGuardianRequest,
66
76
  generateCanonicalRequestCode,
@@ -76,6 +86,7 @@ import {
76
86
  hasMessages,
77
87
  type MessageRow,
78
88
  provenanceFromTrustContext,
89
+ setConversationInferenceProfile,
79
90
  setConversationOriginChannelIfUnset,
80
91
  setConversationOriginInterfaceIfUnset,
81
92
  } from "../../memory/conversation-crud.js";
@@ -90,18 +101,19 @@ import { checkIngressForSecrets } from "../../security/secret-ingress.js";
90
101
  import { redactSecrets } from "../../security/secret-scanner.js";
91
102
  import { summarizeToolInput } from "../../tools/tool-input-summary.js";
92
103
  import { getLogger } from "../../util/logger.js";
93
- import { getWorkspacePromptPath } from "../../util/platform.js";
104
+ import {
105
+ getInterfacesDir,
106
+ getWorkspacePromptPath,
107
+ } from "../../util/platform.js";
94
108
  import { silentlyWithLog } from "../../util/silently.js";
95
109
  import { buildAssistantEvent } from "../assistant-event.js";
110
+ import { assistantEventHub } from "../assistant-event-hub.js";
96
111
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
97
- import type { AuthContext } from "../auth/types.js";
98
112
  import { getChromeExtensionRegistry } from "../chrome-extension-registry.js";
99
113
  import { getClientRegistry } from "../client-registry.js";
100
114
  import { bridgeConfirmationRequestToGuardian } from "../confirmation-request-guardian-bridge.js";
101
115
  import { routeGuardianReply } from "../guardian-reply-router.js";
102
116
  import { healGuardianBindingDrift } from "../guardian-vellum-migration.js";
103
- import { httpError } from "../http-errors.js";
104
- import type { RouteDefinition } from "../http-router.js";
105
117
  import type {
106
118
  ApprovalConversationGenerator,
107
119
  RuntimeAttachmentMetadata,
@@ -114,6 +126,9 @@ import {
114
126
  resolveTrustContext,
115
127
  withSourceChannel,
116
128
  } from "../trust-context-resolver.js";
129
+ import { BadRequestError, InternalError, RouteError } from "./errors.js";
130
+ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
131
+ import { RouteResponse } from "./types.js";
117
132
 
118
133
  const log = getLogger("conversation-routes");
119
134
 
@@ -121,6 +136,15 @@ const log = getLogger("conversation-routes");
121
136
  const NO_RESPONSE_INLINE_RE = /<no_response\s*\/?>/g;
122
137
 
123
138
  const SUGGESTION_CACHE_MAX = 100;
139
+ const VALID_RISK_THRESHOLDS = ["none", "low", "medium", "high"] as const;
140
+ type RiskThreshold = (typeof VALID_RISK_THRESHOLDS)[number];
141
+
142
+ function isValidRiskThreshold(value: unknown): value is RiskThreshold {
143
+ return (
144
+ typeof value === "string" &&
145
+ VALID_RISK_THRESHOLDS.includes(value as RiskThreshold)
146
+ );
147
+ }
124
148
 
125
149
  function collectCanonicalGuardianRequestHintIds(
126
150
  conversationId: string,
@@ -368,11 +392,11 @@ function getInterfaceFilesWithMtimes(
368
392
  }
369
393
 
370
394
  export function handleListMessages(
371
- url: URL,
395
+ { queryParams }: RouteHandlerArgs,
372
396
  interfacesDir: string | null,
373
- ): Response {
374
- const conversationId = url.searchParams.get("conversationId");
375
- const conversationKey = url.searchParams.get("conversationKey");
397
+ ): Record<string, unknown> {
398
+ const conversationId = queryParams?.conversationId;
399
+ const conversationKey = queryParams?.conversationKey;
376
400
 
377
401
  let resolvedConversationId: string | undefined;
378
402
  if (conversationId) {
@@ -381,30 +405,40 @@ export function handleListMessages(
381
405
  const mapping = getConversationByKey(conversationKey);
382
406
  resolvedConversationId = mapping?.conversationId;
383
407
  } else {
384
- return httpError(
385
- "BAD_REQUEST",
408
+ throw new BadRequestError(
386
409
  "conversationKey or conversationId query parameter is required",
387
- 400,
388
410
  );
389
411
  }
390
412
 
391
- if (!resolvedConversationId) {
392
- return Response.json({ messages: [] });
393
- }
394
-
395
- const beforeTimestampRaw = url.searchParams.get("beforeTimestamp");
396
- const limitRaw = url.searchParams.get("limit");
413
+ const beforeTimestampRaw = queryParams?.beforeTimestamp;
414
+ const limitRaw = queryParams?.limit;
415
+ const pageRaw = queryParams?.page;
397
416
 
398
417
  // Validate: reject NaN values with 400
399
- if (beforeTimestampRaw !== null && isNaN(Number(beforeTimestampRaw))) {
400
- return httpError(
401
- "BAD_REQUEST",
402
- "beforeTimestamp must be a valid number",
403
- 400,
404
- );
418
+ if (beforeTimestampRaw != null && isNaN(Number(beforeTimestampRaw))) {
419
+ throw new BadRequestError("beforeTimestamp must be a valid number");
420
+ }
421
+ if (limitRaw != null && isNaN(Number(limitRaw))) {
422
+ throw new BadRequestError("limit must be a valid number");
405
423
  }
406
- if (limitRaw !== null && isNaN(Number(limitRaw))) {
407
- return httpError("BAD_REQUEST", "limit must be a valid number", 400);
424
+ if (pageRaw != null && pageRaw !== "latest") {
425
+ throw new BadRequestError("page must be 'latest' when provided");
426
+ }
427
+ const isLatestPage = pageRaw === "latest";
428
+
429
+ if (!resolvedConversationId) {
430
+ // Unresolved conversation keys still need to advertise the stable
431
+ // `page=latest` contract so the web client can rely on metadata fields
432
+ // being present even before any message is persisted.
433
+ if (isLatestPage && beforeTimestampRaw == null) {
434
+ return {
435
+ messages: [],
436
+ hasMore: false,
437
+ oldestTimestamp: null,
438
+ oldestMessageId: null,
439
+ };
440
+ }
441
+ return { messages: [] };
408
442
  }
409
443
 
410
444
  const beforeTimestamp = beforeTimestampRaw
@@ -415,10 +449,12 @@ export function handleListMessages(
415
449
  ? Math.min(Math.max(Math.floor(Number(limitRaw)), 1), 500)
416
450
  : undefined;
417
451
 
418
- // Option A: only paginate when beforeTimestamp is present.
419
- // Initial load and reconnect send limit but no beforeTimestamp — those must continue
420
- // returning all messages for zero regression risk.
421
- const isPaginated = beforeTimestamp != null;
452
+ // Paginate when either `beforeTimestamp` (older-page request) or
453
+ // `page=latest` (initial newest-N request) is set. When both are sent,
454
+ // `beforeTimestamp` wins because the caller is explicitly asking for an
455
+ // older page; `getMessagesPaginated` ignores `beforeTimestamp === undefined`
456
+ // and returns the newest `limit` messages in chronological order.
457
+ const isPaginated = beforeTimestamp != null || isLatestPage;
422
458
 
423
459
  let rawMessages: MessageRow[];
424
460
  let hasMore = false;
@@ -583,12 +619,12 @@ export function handleListMessages(
583
619
  // aren't lost before DB compaction relinks them.
584
620
  const idsToQuery = [m.id, ...(mergedIdMap.get(m.id) ?? [])];
585
621
  const linked = idsToQuery.flatMap((id) =>
586
- attachmentsStore.getAttachmentMetadataForMessage(id),
622
+ getAttachmentMetadataForMessage(id),
587
623
  );
588
624
  if (linked.length > 0) {
589
625
  msgAttachments = linked.map((a) => {
590
626
  if (a.mimeType.startsWith("image/")) {
591
- const full = attachmentsStore.getAttachmentById(a.id, {
627
+ const full = getAttachmentById(a.id, {
592
628
  hydrateFileData: true,
593
629
  });
594
630
  return {
@@ -664,15 +700,28 @@ export function handleListMessages(
664
700
  rawMessages.length > 0 ? rawMessages[0].createdAt : undefined;
665
701
  const oldestMessageId =
666
702
  rawMessages.length > 0 ? rawMessages[0].id : undefined;
667
- return Response.json({
703
+ // `page=latest` always emits both metadata fields so the web client has
704
+ // a stable contract; emit `null` when the conversation is empty.
705
+ // The existing `beforeTimestamp` branch keeps its conditional shape to
706
+ // avoid disturbing current callers.
707
+ if (isLatestPage && beforeTimestamp == null) {
708
+ return {
709
+ messages,
710
+ hasMore,
711
+ oldestTimestamp: oldestTimestamp ?? null,
712
+ oldestMessageId: oldestMessageId ?? null,
713
+ };
714
+ }
715
+
716
+ return {
668
717
  messages,
669
718
  hasMore,
670
719
  ...(oldestTimestamp != null ? { oldestTimestamp } : {}),
671
720
  ...(oldestMessageId != null ? { oldestMessageId } : {}),
672
- });
721
+ };
673
722
  }
674
723
 
675
- return Response.json({ messages });
724
+ return { messages };
676
725
  }
677
726
 
678
727
  // ── Tool-result merging ─────────────────────────────────────────────
@@ -1003,7 +1052,6 @@ function makeHubPublisher(
1003
1052
  allowlistOptions: msg.allowlistOptions,
1004
1053
  scopeOptions: msg.scopeOptions,
1005
1054
  persistentDecisionsAllowed: msg.persistentDecisionsAllowed,
1006
- temporaryOptionsAvailable: msg.temporaryOptionsAvailable,
1007
1055
  },
1008
1056
  });
1009
1057
 
@@ -1024,6 +1072,7 @@ function makeHubPublisher(
1024
1072
  dedupKey,
1025
1073
  urgency: msg.riskLevel === "high" ? "high" : "medium",
1026
1074
  conversationId,
1075
+ detailPanel: { kind: "toolPermission" },
1027
1076
  }).catch((err) => {
1028
1077
  log.warn(
1029
1078
  { err, requestId: msg.requestId },
@@ -1044,6 +1093,7 @@ function makeHubPublisher(
1044
1093
  dedupKey,
1045
1094
  urgency: msg.riskLevel === "high" ? "high" : "medium",
1046
1095
  conversationId,
1096
+ detailPanel: { kind: "toolPermission" },
1047
1097
  });
1048
1098
  }
1049
1099
  })
@@ -1225,83 +1275,93 @@ function registerHostProxyPendingInteraction(
1225
1275
  });
1226
1276
  return msg.requestId;
1227
1277
  }
1278
+ if (msg.type === "host_transfer_request") {
1279
+ pendingInteractions.register(msg.requestId, {
1280
+ conversation,
1281
+ conversationId,
1282
+ kind: "host_transfer",
1283
+ });
1284
+ return msg.requestId;
1285
+ }
1228
1286
  return undefined;
1229
1287
  }
1230
1288
 
1231
1289
  /**
1232
1290
  * Resolve the host_browser sender function for a conversation turn.
1233
1291
  *
1234
- * When the guardian has an active extension connection in the
1235
- * ChromeExtensionRegistry, returns a registry-routed sender that forwards
1236
- * `host_browser_request` / `host_browser_cancel` frames through the
1237
- * WebSocket to the connected extension. Otherwise returns the SSE hub
1238
- * emitter (`onEvent`).
1239
- *
1240
- * For `chrome-extension` turns the registry sender is **always** returned
1241
- * regardless of the POST-time connection check. The chrome-extension
1242
- * interface has no SSE consumer for `host_browser_request` frames, so
1243
- * falling back to `onEvent` would cause CDP calls to stall until the proxy
1244
- * timeout (30 s) instead of failing immediately at send time when the
1245
- * registry throws on a missing connection.
1292
+ * Transport selection:
1293
+ * 1. **WebSocket registry** when the guardian has an active entry in
1294
+ * ChromeExtensionRegistry (self-hosted direct WS connection), the
1295
+ * registry-routed sender is returned. Frames go directly over the
1296
+ * WebSocket to the extension.
1297
+ * 2. **SSE event hub** — when no WebSocket connection exists but a
1298
+ * chrome-extension client is connected via SSE (cloud/platform mode),
1299
+ * the SSE hub sender (`onEvent`) is returned. The extension receives
1300
+ * `host_browser_request` frames as SSE events and POSTs results back
1301
+ * to `/v1/host-browser-result`.
1246
1302
  *
1247
- * This helper is interface-agnostic: both chrome-extension and macOS turns
1248
- * can obtain a registry-routed sender when extension connectivity exists.
1249
- * The `isRegistryRouted` flag lets the caller decide whether to set
1250
- * `hostBrowserSenderOverride` and whether to provision a `HostBrowserProxy`
1251
- * for interfaces that don't statically support host_browser (e.g. macOS).
1303
+ * When neither transport is available, `onEvent` is returned as the
1304
+ * default sender (used by macOS for its native host_browser path).
1305
+ * `hasSseExtension` is `false` in that case so the caller can avoid
1306
+ * provisioning a stale `HostBrowserProxy` for interfaces that don't
1307
+ * natively support host_browser.
1252
1308
  */
1253
1309
  function resolveHostBrowserSender(
1254
1310
  conversation: Conversation,
1255
1311
  conversationId: string,
1256
- authContext: AuthContext,
1312
+ actorPrincipalId: string | undefined,
1257
1313
  onEvent: (msg: ServerMessage) => void,
1258
1314
  sourceInterface: InterfaceId,
1259
- ): { sender: (msg: ServerMessage) => void; isRegistryRouted: boolean } {
1260
- // Check whether the guardian has any active extension connection.
1315
+ ): {
1316
+ sender: (msg: ServerMessage) => void;
1317
+ isRegistryRouted: boolean;
1318
+ hasSseExtension: boolean;
1319
+ } {
1261
1320
  const guardianId =
1262
- conversation.trustContext?.guardianPrincipalId ??
1263
- authContext.actorPrincipalId;
1321
+ conversation.trustContext?.guardianPrincipalId ?? actorPrincipalId;
1264
1322
  const hasExtensionConnection =
1265
1323
  !!guardianId && !!getChromeExtensionRegistry().get(guardianId);
1266
1324
 
1267
- // For chrome-extension, always use the registry sender so that send-time
1268
- // failures produce immediate errors rather than 30-second proxy timeouts.
1269
- // The SSE hub has no extension consumer, so falling back to onEvent is
1270
- // never correct for this interface.
1271
- if (!hasExtensionConnection && sourceInterface !== "chrome-extension") {
1272
- return { sender: onEvent, isRegistryRouted: false };
1273
- }
1274
-
1275
- // Build a registry-routed sender. The guardian principal ID is resolved
1276
- // at send time rather than captured here so that queue-drain restores
1277
- // (which re-fire this closure outside the original POST context) follow
1278
- // the conversation's bound guardian identity rather than a stale
1279
- // authContext.actorPrincipalId.
1280
- const registrySender = (msg: ServerMessage): void => {
1281
- const requestId = registerHostProxyPendingInteraction(
1282
- msg,
1283
- conversation,
1284
- conversationId,
1285
- );
1286
- const gid =
1287
- conversation.trustContext?.guardianPrincipalId ??
1288
- authContext.actorPrincipalId;
1289
- if (!gid) {
1290
- if (requestId) pendingInteractions.resolve(requestId);
1291
- throw new Error(
1292
- "host_browser send skipped: no guardianId on AuthContext",
1293
- );
1294
- }
1295
- const ok = getChromeExtensionRegistry().send(gid, msg);
1296
- if (!ok) {
1297
- if (requestId) pendingInteractions.resolve(requestId);
1298
- throw new Error(
1299
- `host_browser send failed: no active connection for guardian ${gid}`,
1325
+ // Priority 1: WebSocket registry direct WS to the extension.
1326
+ if (hasExtensionConnection) {
1327
+ const registrySender = (msg: ServerMessage): void => {
1328
+ const requestId = registerHostProxyPendingInteraction(
1329
+ msg,
1330
+ conversation,
1331
+ conversationId,
1300
1332
  );
1301
- }
1302
- };
1333
+ const gid =
1334
+ conversation.trustContext?.guardianPrincipalId ?? actorPrincipalId;
1335
+ if (!gid) {
1336
+ if (requestId) pendingInteractions.resolve(requestId);
1337
+ throw new Error(
1338
+ "host_browser send skipped: no guardianId on AuthContext",
1339
+ );
1340
+ }
1341
+ const ok = getChromeExtensionRegistry().send(gid, msg);
1342
+ if (!ok) {
1343
+ if (requestId) pendingInteractions.resolve(requestId);
1344
+ throw new Error(
1345
+ `host_browser send failed: no active connection for guardian ${gid}`,
1346
+ );
1347
+ }
1348
+ };
1349
+ return {
1350
+ sender: registrySender,
1351
+ isRegistryRouted: true,
1352
+ hasSseExtension: false,
1353
+ };
1354
+ }
1355
+
1356
+ // Priority 2: SSE-connected chrome extension (cloud/platform mode).
1357
+ // Check the ClientRegistry for a chrome-extension client specifically —
1358
+ // getMostRecentByCapability("host_browser") would also match macOS
1359
+ // clients, which handle browser frames through their own native path.
1360
+ const hasSseExtension =
1361
+ canServiceSseBrowser(sourceInterface) &&
1362
+ !!getClientRegistry().getMostRecentByInterface("chrome-extension");
1303
1363
 
1304
- return { sender: registrySender, isRegistryRouted: true };
1364
+ return { sender: onEvent, isRegistryRouted: false, hasSseExtension };
1305
1365
  }
1306
1366
 
1307
1367
  /**
@@ -1395,15 +1455,13 @@ export function persistOnboardingArtifacts(onboarding: {
1395
1455
  }
1396
1456
 
1397
1457
  export async function handleSendMessage(
1398
- req: Request,
1458
+ { body: rawBody, headers }: RouteHandlerArgs,
1399
1459
  deps: {
1400
1460
  sendMessageDeps?: SendMessageDeps;
1401
1461
  approvalConversationGenerator?: ApprovalConversationGenerator;
1402
- heartbeatService?: HeartbeatService;
1403
1462
  },
1404
- authContext: AuthContext,
1405
- ): Promise<Response> {
1406
- const body = (await req.json()) as {
1463
+ ): Promise<unknown> {
1464
+ const body = (rawBody ?? {}) as {
1407
1465
  conversationKey?: string;
1408
1466
  content?: string;
1409
1467
  attachmentIds?: string[];
@@ -1416,6 +1474,8 @@ export async function handleSendMessage(
1416
1474
  hostUsername?: string;
1417
1475
  clientId?: string;
1418
1476
  clientMessageId?: string;
1477
+ inferenceProfile?: string | null;
1478
+ riskThreshold?: string;
1419
1479
  onboarding?: {
1420
1480
  tools: string[];
1421
1481
  tasks: string[];
@@ -1425,35 +1485,70 @@ export async function handleSendMessage(
1425
1485
  };
1426
1486
  };
1427
1487
 
1488
+ const actorPrincipalId = headers?.["x-vellum-actor-principal-id"];
1489
+ const principalType = headers?.["x-vellum-principal-type"];
1490
+
1428
1491
  const { conversationKey, content, attachmentIds } = body;
1429
1492
  const clientMessageId =
1430
1493
  typeof body.clientMessageId === "string" ? body.clientMessageId : undefined;
1494
+ const requestedInferenceProfile =
1495
+ typeof body.inferenceProfile === "string"
1496
+ ? body.inferenceProfile
1497
+ : undefined;
1498
+ const requestedRiskThreshold = body.riskThreshold;
1499
+ if (
1500
+ body.inferenceProfile != null &&
1501
+ typeof body.inferenceProfile !== "string"
1502
+ ) {
1503
+ throw new BadRequestError(
1504
+ "inferenceProfile must be a non-empty string or null",
1505
+ );
1506
+ }
1507
+ if (requestedInferenceProfile === "") {
1508
+ throw new BadRequestError(
1509
+ "inferenceProfile must be a non-empty string or null",
1510
+ );
1511
+ }
1512
+ if (requestedInferenceProfile !== undefined) {
1513
+ const profiles = getConfig().llm.profiles ?? {};
1514
+ if (
1515
+ !Object.prototype.hasOwnProperty.call(profiles, requestedInferenceProfile)
1516
+ ) {
1517
+ throw new BadRequestError(
1518
+ `Profile "${requestedInferenceProfile}" is not defined in llm.profiles`,
1519
+ );
1520
+ }
1521
+ }
1522
+ if (
1523
+ requestedRiskThreshold !== undefined &&
1524
+ !isValidRiskThreshold(requestedRiskThreshold)
1525
+ ) {
1526
+ throw new BadRequestError(
1527
+ `riskThreshold must be one of: ${VALID_RISK_THRESHOLDS.join(", ")}`,
1528
+ );
1529
+ }
1431
1530
  if (!body.sourceChannel || typeof body.sourceChannel !== "string") {
1432
- return httpError("BAD_REQUEST", "sourceChannel is required", 400);
1531
+ throw new BadRequestError("sourceChannel is required");
1433
1532
  }
1434
1533
  const sourceChannel = parseChannelId(body.sourceChannel);
1435
1534
 
1436
1535
  if (!sourceChannel) {
1437
- return httpError(
1438
- "BAD_REQUEST",
1536
+ throw new BadRequestError(
1439
1537
  `Invalid sourceChannel: ${
1440
1538
  body.sourceChannel
1441
1539
  }. Valid values: ${CHANNEL_IDS.join(", ")}`,
1442
- 400,
1443
1540
  );
1444
1541
  }
1445
1542
 
1446
1543
  if (!body.interface || typeof body.interface !== "string") {
1447
- return httpError("BAD_REQUEST", "interface is required", 400);
1544
+ throw new BadRequestError("interface is required");
1448
1545
  }
1449
1546
  const sourceInterface = parseInterfaceId(body.interface);
1450
1547
  if (!sourceInterface) {
1451
- return httpError(
1452
- "BAD_REQUEST",
1548
+ throw new BadRequestError(
1453
1549
  `Invalid interface: ${body.interface}. Valid values: ${INTERFACE_IDS.join(
1454
1550
  ", ",
1455
1551
  )}`,
1456
- 400,
1457
1552
  );
1458
1553
  }
1459
1554
 
@@ -1465,7 +1560,7 @@ export async function handleSendMessage(
1465
1560
 
1466
1561
  // Reject non-string content values (numbers, objects, etc.)
1467
1562
  if (content != null && typeof content !== "string") {
1468
- return httpError("BAD_REQUEST", "content must be a string", 400);
1563
+ throw new BadRequestError("content must be a string");
1469
1564
  }
1470
1565
 
1471
1566
  const trimmedContent = typeof content === "string" ? content.trim() : "";
@@ -1473,23 +1568,17 @@ export async function handleSendMessage(
1473
1568
  Array.isArray(attachmentIds) && attachmentIds.length > 0;
1474
1569
 
1475
1570
  if (trimmedContent.length === 0 && !hasAttachments) {
1476
- return httpError(
1477
- "BAD_REQUEST",
1478
- "content or attachmentIds is required",
1479
- 400,
1480
- );
1571
+ throw new BadRequestError("content or attachmentIds is required");
1481
1572
  }
1482
1573
 
1483
1574
  // Validate that all attachment IDs resolve
1484
1575
  if (hasAttachments) {
1485
- const resolved = attachmentsStore.getAttachmentsByIds(attachmentIds);
1576
+ const resolved = getAttachmentsByIds(attachmentIds);
1486
1577
  if (resolved.length !== attachmentIds.length) {
1487
1578
  const resolvedIds = new Set(resolved.map((a) => a.id));
1488
1579
  const missing = attachmentIds.filter((id) => !resolvedIds.has(id));
1489
- return httpError(
1490
- "BAD_REQUEST",
1580
+ throw new BadRequestError(
1491
1581
  `Attachment IDs not found: ${missing.join(", ")}`,
1492
- 400,
1493
1582
  );
1494
1583
  }
1495
1584
  }
@@ -1498,36 +1587,52 @@ export async function handleSendMessage(
1498
1587
  if (trimmedContent.length > 0 && !body.bypassSecretCheck) {
1499
1588
  const ingressResult = checkIngressForSecrets(trimmedContent);
1500
1589
  if (ingressResult.blocked) {
1501
- return Response.json(
1502
- {
1590
+ return new RouteResponse(
1591
+ JSON.stringify({
1503
1592
  accepted: false,
1504
1593
  error: "secret_blocked",
1505
1594
  message: ingressResult.userNotice,
1506
1595
  detectedTypes: ingressResult.detectedTypes,
1507
- },
1508
- { status: 422 },
1596
+ }),
1597
+ { "content-type": "application/json" },
1598
+ 422,
1509
1599
  );
1510
1600
  }
1511
1601
  }
1512
1602
 
1513
1603
  if (!deps.sendMessageDeps) {
1514
- return httpError(
1515
- "SERVICE_UNAVAILABLE",
1604
+ throw new RouteError(
1516
1605
  "Message processing is not available",
1606
+ "SERVICE_UNAVAILABLE",
1517
1607
  503,
1518
1608
  );
1519
1609
  }
1520
1610
 
1521
1611
  // Desktop messages are always from the guardian — reset the heartbeat
1522
1612
  // timer so the next heartbeat is a full interval after this interaction.
1523
- deps.heartbeatService?.resetTimer();
1613
+ HeartbeatService.getInstance()?.resetTimer();
1524
1614
 
1525
- const conversationType =
1526
- body.conversationType === "private" ? ("private" as const) : undefined;
1527
1615
  const mapping = getOrCreateConversation(resolvedConversationKey, {
1528
- conversationType,
1616
+ conversationType: "standard",
1529
1617
  });
1530
1618
 
1619
+ if (requestedRiskThreshold !== undefined) {
1620
+ const result = await ipcCall("set_conversation_threshold", {
1621
+ conversationId: mapping.conversationId,
1622
+ threshold: requestedRiskThreshold,
1623
+ });
1624
+ if (result === undefined) {
1625
+ log.error(
1626
+ {
1627
+ conversationId: mapping.conversationId,
1628
+ threshold: requestedRiskThreshold,
1629
+ },
1630
+ "Failed to set conversation risk threshold override via gateway IPC",
1631
+ );
1632
+ throw new InternalError("Failed to persist risk threshold override");
1633
+ }
1634
+ }
1635
+
1531
1636
  const smDeps = deps.sendMessageDeps;
1532
1637
 
1533
1638
  // Notify all connected clients that the conversation list changed when
@@ -1571,27 +1676,18 @@ export async function handleSendMessage(
1571
1676
  interfaceId: sourceInterface,
1572
1677
  } satisfies NonHostProxyTransportMetadata);
1573
1678
 
1574
- // Register/refresh the client in the unified client registry so
1575
- // `assistant clients list` can discover all connected interfaces.
1576
- // Uses the client-supplied clientId when available (stable per-install
1577
- // UUID), falling back to a synthetic key derived from interfaceId so
1578
- // older clients that don't send clientId still appear in the registry.
1579
- const effectiveClientId =
1580
- typeof body.clientId === "string" && body.clientId.length > 0
1581
- ? body.clientId
1582
- : `synthetic:${sourceInterface}`;
1583
- getClientRegistry().register({
1584
- clientId: effectiveClientId,
1585
- interfaceId: sourceInterface,
1586
- hostHomeDir: body.hostHomeDir,
1587
- hostUsername: body.hostUsername,
1588
- });
1589
-
1590
1679
  const conversation = await smDeps.getOrCreateConversation(
1591
1680
  mapping.conversationId,
1592
1681
  { transport },
1593
1682
  );
1594
1683
 
1684
+ if (requestedInferenceProfile !== undefined) {
1685
+ setConversationInferenceProfile(
1686
+ mapping.conversationId,
1687
+ requestedInferenceProfile,
1688
+ );
1689
+ }
1690
+
1595
1691
  // Store pre-chat onboarding context on the conversation when this is the
1596
1692
  // very first message (no prior messages loaded). Artifact persistence
1597
1693
  // (IDENTITY.md, USER.md, sidecar) is deferred: on the canned greeting
@@ -1607,11 +1703,11 @@ export async function handleSendMessage(
1607
1703
  // Resolve guardian context from the AuthContext's actorPrincipalId.
1608
1704
  // The JWT-verified principal is used as the sender identity through
1609
1705
  // the same trust resolution pipeline that channel ingress uses.
1610
- if (authContext.actorPrincipalId) {
1706
+ if (actorPrincipalId) {
1611
1707
  // Dev bypass (HTTP auth disabled): the synthetic "dev-bypass" principal
1612
1708
  // won't match any guardian binding. Resolve from the local guardian
1613
1709
  // binding instead, which produces the correct guardian trust context.
1614
- if (isHttpAuthDisabled() && authContext.actorPrincipalId === "dev-bypass") {
1710
+ if (isHttpAuthDisabled() && actorPrincipalId === "dev-bypass") {
1615
1711
  conversation.setTrustContext(resolveLocalTrustContext(sourceChannel));
1616
1712
  } else {
1617
1713
  const assistantId = DAEMON_INTERNAL_ASSISTANT_ID;
@@ -1619,24 +1715,24 @@ export async function handleSendMessage(
1619
1715
  assistantId,
1620
1716
  sourceChannel: "vellum",
1621
1717
  conversationExternalId: "local",
1622
- actorExternalId: authContext.actorPrincipalId,
1718
+ actorExternalId: actorPrincipalId,
1623
1719
  });
1624
1720
  if (trustCtx.trustClass === "unknown") {
1625
1721
  // Attempt to heal guardian binding drift: after a DB reset the
1626
1722
  // guardian binding gets a new vellum-principal-* UUID while the
1627
1723
  // client still holds a valid JWT with the old one. The signing
1628
1724
  // key survives the reset, so the JWT is authentic — just stale.
1629
- const healed = healGuardianBindingDrift(authContext.actorPrincipalId);
1725
+ const healed = healGuardianBindingDrift(actorPrincipalId);
1630
1726
  if (healed) {
1631
1727
  trustCtx = resolveTrustContext({
1632
1728
  assistantId,
1633
1729
  sourceChannel: "vellum",
1634
1730
  conversationExternalId: "local",
1635
- actorExternalId: authContext.actorPrincipalId,
1731
+ actorExternalId: actorPrincipalId,
1636
1732
  });
1637
1733
  log.info(
1638
1734
  {
1639
- actorPrincipalId: authContext.actorPrincipalId,
1735
+ actorPrincipalId: actorPrincipalId,
1640
1736
  trustClass: trustCtx.trustClass,
1641
1737
  },
1642
1738
  "Trust re-resolved after guardian binding drift heal",
@@ -1644,10 +1740,10 @@ export async function handleSendMessage(
1644
1740
  } else {
1645
1741
  log.warn(
1646
1742
  {
1647
- actorPrincipalId: authContext.actorPrincipalId,
1743
+ actorPrincipalId: actorPrincipalId,
1648
1744
  sourceChannel,
1649
1745
  trustClass: trustCtx.trustClass,
1650
- principalType: authContext.principalType,
1746
+ principalType: principalType,
1651
1747
  },
1652
1748
  "JWT-verified actor resolved to unknown trust class — possible guardian binding drift (e.g. DB reset without re-bootstrap)",
1653
1749
  );
@@ -1686,17 +1782,19 @@ export async function handleSendMessage(
1686
1782
  conversation.setHostBashProxy(undefined);
1687
1783
  }
1688
1784
  // Resolve the host_browser sender — registry-routed when the guardian has
1689
- // an active extension connection, SSE hub otherwise. This applies to both
1690
- // chrome-extension and macOS interfaces so that macOS turns can route
1691
- // browser automation through the user's real Chrome session when available.
1692
- const { sender: browserProxySendToClient, isRegistryRouted } =
1693
- resolveHostBrowserSender(
1694
- conversation,
1695
- mapping.conversationId,
1696
- authContext,
1697
- onEvent,
1698
- sourceInterface,
1699
- );
1785
+ // an active WS extension connection, SSE hub when a chrome-extension is
1786
+ // connected via SSE (cloud mode), or SSE hub as default for macOS.
1787
+ const {
1788
+ sender: browserProxySendToClient,
1789
+ isRegistryRouted,
1790
+ hasSseExtension,
1791
+ } = resolveHostBrowserSender(
1792
+ conversation,
1793
+ mapping.conversationId,
1794
+ actorPrincipalId,
1795
+ onEvent,
1796
+ sourceInterface,
1797
+ );
1700
1798
 
1701
1799
  // Stash the registry-routed sender on the conversation so queue-drain
1702
1800
  // restores (which run outside of conversation-routes.ts and only have
@@ -1711,16 +1809,18 @@ export async function handleSendMessage(
1711
1809
  conversation.hostBrowserSenderOverride = undefined;
1712
1810
  }
1713
1811
 
1714
- // Provision the host browser proxy. Both macOS and chrome-extension
1715
- // natively support host_browser. For macOS, the proxy is wired to the
1716
- // SSE sender by default so `host_browser_request` frames reach the
1717
- // desktop client directly. When the guardian also has an active extension
1718
- // connection (isRegistryRouted), the registry-routed sender is used
1719
- // instead so browser tools route through the user's real Chrome session.
1720
- // For chrome-extension, the registry sender is always used.
1812
+ // Provision the host browser proxy when a viable transport exists:
1813
+ // - macOS: natively supports host_browser via its own SSE path
1814
+ // - WS registry: extension connected via direct WebSocket
1815
+ // - SSE extension: chrome extension connected via SSE (cloud mode)
1816
+ //
1817
+ // For chrome-extension, require an active transport (WS or SSE). Without
1818
+ // one, host_browser_request frames would be emitted to the SSE hub with
1819
+ // no consumer, causing a 30s proxy timeout instead of failing fast.
1721
1820
  const shouldProvisionBrowserProxy =
1722
- supportsHostProxy(sourceInterface, "host_browser") ||
1723
- (canServiceRegistryBrowser(sourceInterface) && isRegistryRouted);
1821
+ supportsHostProxy(sourceInterface) ||
1822
+ (canServiceRegistryBrowser(sourceInterface) && isRegistryRouted) ||
1823
+ hasSseExtension;
1724
1824
  if (shouldProvisionBrowserProxy) {
1725
1825
  if (!conversation.isProcessing() || !conversation.hostBrowserProxy) {
1726
1826
  const browserProxy = new HostBrowserProxy(
@@ -1741,8 +1841,15 @@ export async function handleSendMessage(
1741
1841
  });
1742
1842
  conversation.setHostFileProxy(fileProxy);
1743
1843
  }
1844
+ if (!conversation.isProcessing() || !conversation.getHostTransferProxy()) {
1845
+ const transferProxy = new HostTransferProxy(onEvent, (requestId) => {
1846
+ pendingInteractions.resolve(requestId);
1847
+ });
1848
+ conversation.setHostTransferProxy(transferProxy);
1849
+ }
1744
1850
  } else if (!conversation.isProcessing()) {
1745
1851
  conversation.setHostFileProxy(undefined);
1852
+ conversation.setHostTransferProxy(undefined);
1746
1853
  }
1747
1854
  if (supportsHostProxy(sourceInterface, "host_cu")) {
1748
1855
  if (!conversation.isProcessing() || !conversation.hostCuProxy) {
@@ -1847,10 +1954,11 @@ export async function handleSendMessage(
1847
1954
  );
1848
1955
  conversation.getMessages().push(assistantMsg);
1849
1956
 
1850
- const response = Response.json(
1851
- { accepted: true, messageId: persisted.id, conversationId },
1852
- { status: 202 },
1853
- );
1957
+ const response = {
1958
+ accepted: true,
1959
+ messageId: persisted.id,
1960
+ conversationId,
1961
+ };
1854
1962
 
1855
1963
  setTimeout(() => {
1856
1964
  onEvent({
@@ -1926,16 +2034,13 @@ export async function handleSendMessage(
1926
2034
  verifiedActorPrincipalId,
1927
2035
  });
1928
2036
  if (inlineReplyResult.consumed) {
1929
- return Response.json(
1930
- {
1931
- accepted: true,
1932
- conversationId: mapping.conversationId,
1933
- ...(inlineReplyResult.messageId
1934
- ? { messageId: inlineReplyResult.messageId }
1935
- : {}),
1936
- },
1937
- { status: 202 },
1938
- );
2037
+ return {
2038
+ accepted: true,
2039
+ conversationId: mapping.conversationId,
2040
+ ...(inlineReplyResult.messageId
2041
+ ? { messageId: inlineReplyResult.messageId }
2042
+ : {}),
2043
+ };
1939
2044
  }
1940
2045
  } catch (err) {
1941
2046
  log.warn(
@@ -1967,9 +2072,10 @@ export async function handleSendMessage(
1967
2072
  clientMessageId,
1968
2073
  );
1969
2074
  if (enqueueResult.rejected) {
1970
- return Response.json(
1971
- { accepted: false, error: "queue_full" },
1972
- { status: 429 },
2075
+ return new RouteResponse(
2076
+ JSON.stringify({ accepted: false, error: "queue_full" }),
2077
+ { "content-type": "application/json" },
2078
+ 429,
1973
2079
  );
1974
2080
  }
1975
2081
 
@@ -2018,10 +2124,11 @@ export async function handleSendMessage(
2018
2124
  );
2019
2125
  }
2020
2126
 
2021
- return Response.json(
2022
- { accepted: true, queued: true, conversationId: mapping.conversationId },
2023
- { status: 202 },
2024
- );
2127
+ return {
2128
+ accepted: true,
2129
+ queued: true,
2130
+ conversationId: mapping.conversationId,
2131
+ };
2025
2132
  }
2026
2133
 
2027
2134
  // Auto-deny pending confirmations for idle conversations. The legacy
@@ -2142,14 +2249,11 @@ export async function handleSendMessage(
2142
2249
  ? await buildModelInfoEvent()
2143
2250
  : null;
2144
2251
 
2145
- const response = Response.json(
2146
- {
2147
- accepted: true,
2148
- messageId: persisted.id,
2149
- conversationId: mapping.conversationId,
2150
- },
2151
- { status: 202 },
2152
- );
2252
+ const response = {
2253
+ accepted: true,
2254
+ messageId: persisted.id,
2255
+ conversationId: mapping.conversationId,
2256
+ };
2153
2257
 
2154
2258
  // Defer event publishing to next tick so the HTTP response reaches the
2155
2259
  // client first. This ensures the client's serverToLocalConversationMap is
@@ -2263,14 +2367,11 @@ export async function handleSendMessage(
2263
2367
  }
2264
2368
  })();
2265
2369
 
2266
- return Response.json(
2267
- {
2268
- accepted: true,
2269
- messageId: persisted.id,
2270
- conversationId,
2271
- },
2272
- { status: 202 },
2273
- );
2370
+ return {
2371
+ accepted: true,
2372
+ messageId: persisted.id,
2373
+ conversationId,
2374
+ };
2274
2375
  }
2275
2376
 
2276
2377
  const resolvedContent = slashResult.content;
@@ -2310,10 +2411,11 @@ export async function handleSendMessage(
2310
2411
  );
2311
2412
  });
2312
2413
 
2313
- return Response.json(
2314
- { accepted: true, messageId, conversationId: mapping.conversationId },
2315
- { status: 202 },
2316
- );
2414
+ return {
2415
+ accepted: true,
2416
+ messageId,
2417
+ conversationId: mapping.conversationId,
2418
+ };
2317
2419
  }
2318
2420
 
2319
2421
  function escapeXmlContent(text: string): string {
@@ -2400,54 +2502,39 @@ async function generateLlmSuggestion(
2400
2502
  }
2401
2503
 
2402
2504
  export async function handleGetSuggestion(
2403
- url: URL,
2505
+ { queryParams }: RouteHandlerArgs,
2404
2506
  deps: {
2405
2507
  suggestionCache: Map<string, string>;
2406
2508
  suggestionInFlight: Map<string, Promise<string | null>>;
2407
2509
  },
2408
- ): Promise<Response> {
2409
- const conversationKey = url.searchParams.get("conversationKey");
2510
+ ): Promise<Record<string, unknown>> {
2511
+ const noSuggestion = {
2512
+ suggestion: null,
2513
+ messageId: null,
2514
+ source: "none" as const,
2515
+ };
2516
+
2517
+ const conversationKey = queryParams?.conversationKey;
2410
2518
  if (!conversationKey) {
2411
- return httpError(
2412
- "BAD_REQUEST",
2413
- "conversationKey query parameter is required",
2414
- 400,
2415
- );
2519
+ throw new BadRequestError("conversationKey query parameter is required");
2416
2520
  }
2417
2521
 
2418
2522
  const mapping = getConversationByKey(conversationKey);
2419
- if (!mapping) {
2420
- return Response.json({
2421
- suggestion: null,
2422
- messageId: null,
2423
- source: "none" as const,
2424
- });
2425
- }
2523
+ if (!mapping) return noSuggestion;
2426
2524
 
2427
2525
  const rawMessages = getMessages(mapping.conversationId);
2428
- if (rawMessages.length === 0) {
2429
- return Response.json({
2430
- suggestion: null,
2431
- messageId: null,
2432
- source: "none" as const,
2433
- });
2434
- }
2526
+ if (rawMessages.length === 0) return noSuggestion;
2435
2527
 
2436
2528
  // Staleness check: compare requested messageId against the latest
2437
2529
  // assistant message BEFORE filtering by text content. This ensures
2438
2530
  // that a newer tool-only assistant turn (empty text) still causes
2439
2531
  // older messageId requests to be correctly marked as stale.
2440
- const requestedMessageId = url.searchParams.get("messageId");
2532
+ const requestedMessageId = queryParams?.messageId;
2441
2533
  if (requestedMessageId) {
2442
2534
  for (let i = rawMessages.length - 1; i >= 0; i--) {
2443
2535
  if (rawMessages[i].role === "assistant") {
2444
2536
  if (rawMessages[i].id !== requestedMessageId) {
2445
- return Response.json({
2446
- suggestion: null,
2447
- messageId: null,
2448
- source: "none" as const,
2449
- stale: true,
2450
- });
2537
+ return { ...noSuggestion, stale: true };
2451
2538
  }
2452
2539
  break;
2453
2540
  }
@@ -2475,22 +2562,13 @@ export async function handleGetSuggestion(
2475
2562
  // If a messageId was requested and the first text-bearing assistant
2476
2563
  // message is a *different* message, the request is stale.
2477
2564
  if (requestedMessageId && msg.id !== requestedMessageId) {
2478
- return Response.json({
2479
- suggestion: null,
2480
- messageId: null,
2481
- source: "none" as const,
2482
- stale: true,
2483
- });
2565
+ return { ...noSuggestion, stale: true };
2484
2566
  }
2485
2567
 
2486
2568
  // Return cached suggestion if we already generated one for this message
2487
2569
  const cached = suggestionCache.get(msg.id);
2488
2570
  if (cached !== undefined) {
2489
- return Response.json({
2490
- suggestion: cached,
2491
- messageId: msg.id,
2492
- source: "llm" as const,
2493
- });
2571
+ return { suggestion: cached, messageId: msg.id, source: "llm" as const };
2494
2572
  }
2495
2573
 
2496
2574
  // Find the most recent user message preceding this assistant turn so the
@@ -2534,11 +2612,11 @@ export async function handleGetSuggestion(
2534
2612
  }
2535
2613
  suggestionCache.set(msg.id, llmSuggestion);
2536
2614
 
2537
- return Response.json({
2615
+ return {
2538
2616
  suggestion: llmSuggestion,
2539
2617
  messageId: msg.id,
2540
2618
  source: "llm" as const,
2541
- });
2619
+ };
2542
2620
  }
2543
2621
  } catch (err) {
2544
2622
  suggestionInFlight.delete(msg.id);
@@ -2554,18 +2632,10 @@ export async function handleGetSuggestion(
2554
2632
  );
2555
2633
  }
2556
2634
 
2557
- return Response.json({
2558
- suggestion: null,
2559
- messageId: null,
2560
- source: "none" as const,
2561
- });
2635
+ return noSuggestion;
2562
2636
  }
2563
2637
 
2564
- return Response.json({
2565
- suggestion: null,
2566
- messageId: null,
2567
- source: "none" as const,
2568
- });
2638
+ return noSuggestion;
2569
2639
  }
2570
2640
 
2571
2641
  /**
@@ -2574,19 +2644,17 @@ export async function handleGetSuggestion(
2574
2644
  * Full-text search across all conversations (message content + titles).
2575
2645
  * Returns ranked results grouped by conversation, each with matching message excerpts.
2576
2646
  */
2577
- function handleSearchConversations(url: URL): Response {
2578
- const query = url.searchParams.get("q") ?? "";
2647
+ function handleSearchConversations({
2648
+ queryParams,
2649
+ }: RouteHandlerArgs): Record<string, unknown> {
2650
+ const query = queryParams?.q ?? "";
2579
2651
  if (!query.trim()) {
2580
- return httpError("BAD_REQUEST", "q query parameter is required", 400);
2652
+ throw new BadRequestError("q query parameter is required");
2581
2653
  }
2582
2654
 
2583
- const limit = url.searchParams.has("limit")
2584
- ? Number(url.searchParams.get("limit"))
2585
- : undefined;
2586
- const maxMessagesPerConversation = url.searchParams.has(
2587
- "maxMessagesPerConversation",
2588
- )
2589
- ? Number(url.searchParams.get("maxMessagesPerConversation"))
2655
+ const limit = queryParams?.limit ? Number(queryParams.limit) : undefined;
2656
+ const maxMessagesPerConversation = queryParams?.maxMessagesPerConversation
2657
+ ? Number(queryParams.maxMessagesPerConversation)
2590
2658
  : undefined;
2591
2659
 
2592
2660
  const results = searchConversations(query, {
@@ -2597,105 +2665,125 @@ function handleSearchConversations(url: URL): Response {
2597
2665
  : {}),
2598
2666
  });
2599
2667
 
2600
- return Response.json({ query, results });
2668
+ return { query, results };
2669
+ }
2670
+
2671
+ // ---------------------------------------------------------------------------
2672
+ // Module-level state
2673
+ // ---------------------------------------------------------------------------
2674
+
2675
+ const suggestionCache = new Map<string, string>();
2676
+ const suggestionInFlight = new Map<string, Promise<string | null>>();
2677
+
2678
+ function resolveAttachments(attachmentIds: string[]) {
2679
+ const resolved = getAttachmentsByIds(attachmentIds, {
2680
+ hydrateFileData: true,
2681
+ });
2682
+ const sourcePaths = getSourcePathsForAttachments(attachmentIds);
2683
+ return resolved.map((a) => ({
2684
+ id: a.id,
2685
+ filename: a.originalFilename,
2686
+ mimeType: a.mimeType,
2687
+ data: a.dataBase64,
2688
+ ...(sourcePaths.has(a.id) ? { filePath: sourcePaths.get(a.id) } : {}),
2689
+ }));
2601
2690
  }
2602
2691
 
2603
2692
  // ---------------------------------------------------------------------------
2604
2693
  // Route definitions
2605
2694
  // ---------------------------------------------------------------------------
2606
2695
 
2607
- export function conversationRouteDefinitions(deps: {
2608
- interfacesDir: string | null;
2609
- sendMessageDeps?: SendMessageDeps;
2610
- approvalConversationGenerator?: ApprovalConversationGenerator;
2611
- suggestionCache: Map<string, string>;
2612
- suggestionInFlight: Map<string, Promise<string | null>>;
2613
- getHeartbeatService?: () => HeartbeatService | undefined;
2614
- }): RouteDefinition[] {
2615
- return [
2616
- {
2617
- endpoint: "messages",
2618
- method: "GET",
2619
- summary: "List messages",
2620
- description:
2621
- "Return messages for a conversation, including attachments and interface file metadata.",
2622
- tags: ["messages"],
2623
- responseBody: z.object({
2624
- messages: z.array(z.unknown()).describe("Array of message objects"),
2625
- hasMore: z
2626
- .boolean()
2627
- .optional()
2628
- .describe("Whether older messages exist beyond this page"),
2629
- oldestTimestamp: z
2630
- .number()
2631
- .optional()
2632
- .describe(
2633
- "Timestamp of the oldest message in this page (ms since epoch)",
2634
- ),
2635
- oldestMessageId: z
2636
- .string()
2637
- .optional()
2638
- .describe("ID of the oldest message in this page"),
2639
- }),
2640
- handler: ({ url }) => handleListMessages(url, deps.interfacesDir),
2641
- },
2642
- {
2643
- endpoint: "messages",
2644
- method: "POST",
2645
- summary: "Send a message",
2646
- description:
2647
- "Send a user message to a conversation and trigger the assistant response.",
2648
- tags: ["messages"],
2649
- requestBody: z.object({
2650
- conversationKey: z.string().optional(),
2651
- content: z.string().describe("Message text content"),
2652
- attachments: z
2653
- .array(z.unknown())
2654
- .describe("Optional file attachments")
2655
- .optional(),
2656
- conversationType: z.string().optional(),
2657
- slashCommand: z.string().optional(),
2658
- }),
2659
- handler: async ({ req, authContext }) =>
2660
- handleSendMessage(
2661
- req,
2662
- {
2663
- sendMessageDeps: deps.sendMessageDeps,
2664
- approvalConversationGenerator: deps.approvalConversationGenerator,
2665
- heartbeatService: deps.getHeartbeatService?.(),
2666
- },
2667
- authContext,
2696
+ export const ROUTES: RouteDefinition[] = [
2697
+ {
2698
+ operationId: "messages_get",
2699
+ endpoint: "messages",
2700
+ method: "GET",
2701
+ summary: "List messages",
2702
+ description:
2703
+ "Return messages for a conversation, including attachments and interface file metadata.",
2704
+ tags: ["messages"],
2705
+ responseBody: z.object({
2706
+ messages: z.array(z.unknown()).describe("Array of message objects"),
2707
+ hasMore: z
2708
+ .boolean()
2709
+ .optional()
2710
+ .describe("Whether older messages exist beyond this page"),
2711
+ oldestTimestamp: z
2712
+ .number()
2713
+ .nullable()
2714
+ .optional()
2715
+ .describe(
2716
+ "Timestamp of the oldest message in this page (ms since epoch). Null when page=latest is used on an empty conversation.",
2668
2717
  ),
2669
- },
2670
- {
2671
- endpoint: "search",
2672
- method: "GET",
2673
- summary: "Search conversations",
2674
- description: "Full-text search across all conversations.",
2675
- tags: ["conversations"],
2676
- responseBody: z.object({
2677
- query: z.string(),
2678
- results: z.array(z.unknown()),
2718
+ oldestMessageId: z
2719
+ .string()
2720
+ .nullable()
2721
+ .optional()
2722
+ .describe("ID of the oldest message in this page"),
2723
+ }),
2724
+ handler: (args) => handleListMessages(args, getInterfacesDir()),
2725
+ },
2726
+ {
2727
+ operationId: "messages_post",
2728
+ endpoint: "messages",
2729
+ method: "POST",
2730
+ summary: "Send a message",
2731
+ description:
2732
+ "Send a user message to a conversation and trigger the assistant response.",
2733
+ tags: ["messages"],
2734
+ responseStatus: "202",
2735
+ requestBody: z.object({
2736
+ conversationKey: z.string().optional(),
2737
+ content: z.string().describe("Message text content"),
2738
+ attachments: z
2739
+ .array(z.unknown())
2740
+ .describe("Optional file attachments")
2741
+ .optional(),
2742
+ conversationType: z.string().optional(),
2743
+ slashCommand: z.string().optional(),
2744
+ inferenceProfile: z.string().nullable().optional(),
2745
+ riskThreshold: z.enum(VALID_RISK_THRESHOLDS).optional(),
2746
+ }),
2747
+ handler: async (args) =>
2748
+ handleSendMessage(args, {
2749
+ sendMessageDeps: {
2750
+ getOrCreateConversation: getOrCreateConversationInstance,
2751
+ assistantEventHub,
2752
+ resolveAttachments,
2753
+ },
2754
+ approvalConversationGenerator: createApprovalConversationGenerator(),
2679
2755
  }),
2680
- handler: ({ url }) => handleSearchConversations(url),
2681
- },
2682
- {
2683
- endpoint: "suggestion",
2684
- method: "GET",
2685
- summary: "Get reply suggestion",
2686
- description:
2687
- "Return an LLM-generated follow-up suggestion for the most recent assistant message.",
2688
- tags: ["messages"],
2689
- responseBody: z.object({
2690
- suggestion: z.string(),
2691
- messageId: z.string(),
2692
- source: z.string(),
2756
+ },
2757
+ {
2758
+ operationId: "search_get",
2759
+ endpoint: "search",
2760
+ method: "GET",
2761
+ summary: "Search conversations",
2762
+ description: "Full-text search across all conversations.",
2763
+ tags: ["conversations"],
2764
+ responseBody: z.object({
2765
+ query: z.string(),
2766
+ results: z.array(z.unknown()),
2767
+ }),
2768
+ handler: handleSearchConversations,
2769
+ },
2770
+ {
2771
+ operationId: "suggestion_get",
2772
+ endpoint: "suggestion",
2773
+ method: "GET",
2774
+ summary: "Get reply suggestion",
2775
+ description:
2776
+ "Return an LLM-generated follow-up suggestion for the most recent assistant message.",
2777
+ tags: ["messages"],
2778
+ responseBody: z.object({
2779
+ suggestion: z.string(),
2780
+ messageId: z.string(),
2781
+ source: z.string(),
2782
+ }),
2783
+ handler: async (args) =>
2784
+ handleGetSuggestion(args, {
2785
+ suggestionCache,
2786
+ suggestionInFlight,
2693
2787
  }),
2694
- handler: async ({ url }) =>
2695
- handleGetSuggestion(url, {
2696
- suggestionCache: deps.suggestionCache,
2697
- suggestionInFlight: deps.suggestionInFlight,
2698
- }),
2699
- },
2700
- ];
2701
- }
2788
+ },
2789
+ ];