@vellumai/assistant 0.6.5 → 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 (1520) hide show
  1. package/AGENTS.md +29 -1
  2. package/ARCHITECTURE.md +60 -53
  3. package/Dockerfile +25 -3
  4. package/README.md +8 -10
  5. package/__tests__/permissions/gateway-threshold-reader.test.ts +277 -0
  6. package/bun.lock +306 -119
  7. package/docs/architecture/integrations.md +32 -39
  8. package/docs/architecture/memory.md +26 -120
  9. package/docs/architecture/security.md +22 -36
  10. package/docs/browser-use-architecture-phase2.md +63 -20
  11. package/docs/credential-execution-service.md +7 -5
  12. package/docs/plugins.md +761 -0
  13. package/docs/skills.md +10 -10
  14. package/docs/stt-provider-onboarding.md +17 -45
  15. package/examples/plugins/echo/README.md +132 -0
  16. package/examples/plugins/echo/bun.lock +25 -0
  17. package/examples/plugins/echo/package.json +17 -0
  18. package/examples/plugins/echo/register.ts +187 -0
  19. package/knip.json +8 -22
  20. package/node_modules/@vellumai/ces-client/bun.lock +33 -0
  21. package/node_modules/@vellumai/ces-client/package.json +25 -0
  22. package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +631 -0
  23. package/node_modules/@vellumai/ces-client/src/__tests__/package-boundary.test.ts +138 -0
  24. package/node_modules/@vellumai/ces-client/src/credential-rpc.ts +13 -0
  25. package/node_modules/@vellumai/ces-client/src/http-credentials.ts +296 -0
  26. package/node_modules/@vellumai/ces-client/src/http-log-export.ts +111 -0
  27. package/node_modules/@vellumai/ces-client/src/index.ts +43 -0
  28. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +445 -0
  29. package/node_modules/@vellumai/credential-storage/src/__tests__/package-boundary.test.ts +32 -6
  30. package/node_modules/@vellumai/egress-proxy/src/__tests__/package-boundary.test.ts +32 -1
  31. package/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
  32. package/node_modules/@vellumai/gateway-client/bun.lock +39 -0
  33. package/node_modules/@vellumai/gateway-client/package.json +23 -0
  34. package/node_modules/@vellumai/gateway-client/src/__tests__/gateway-client.test.ts +343 -0
  35. package/node_modules/@vellumai/gateway-client/src/__tests__/package-boundary.test.ts +140 -0
  36. package/node_modules/@vellumai/gateway-client/src/http-delivery.ts +422 -0
  37. package/node_modules/@vellumai/gateway-client/src/index.ts +35 -0
  38. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +331 -0
  39. package/node_modules/@vellumai/gateway-client/src/types.ts +131 -0
  40. package/node_modules/@vellumai/gateway-client/tsconfig.json +20 -0
  41. package/node_modules/@vellumai/{ces-contracts → service-contracts}/bun.lock +1 -1
  42. package/node_modules/@vellumai/{ces-contracts → service-contracts}/package.json +4 -2
  43. package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/__tests__/contracts.test.ts +5 -1
  44. package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +155 -0
  45. package/node_modules/@vellumai/service-contracts/src/credential-rpc.ts +23 -0
  46. package/node_modules/@vellumai/service-contracts/src/index.ts +25 -0
  47. package/node_modules/@vellumai/{ces-contracts/src/index.ts → service-contracts/src/transport.ts} +6 -28
  48. package/node_modules/@vellumai/service-contracts/src/trust-rules.ts +116 -0
  49. package/node_modules/@vellumai/service-contracts/tsconfig.json +20 -0
  50. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +891 -0
  51. package/node_modules/@vellumai/skill-host-contracts/bun.lock +24 -0
  52. package/node_modules/@vellumai/skill-host-contracts/package.json +18 -0
  53. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +91 -0
  54. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +1348 -0
  55. package/node_modules/@vellumai/skill-host-contracts/src/index.ts +6 -0
  56. package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +11 -0
  57. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +32 -0
  58. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +333 -0
  59. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +444 -0
  60. package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +20 -0
  61. package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +12 -0
  62. package/openapi.yaml +3135 -692
  63. package/package.json +13 -7
  64. package/scripts/check-circular-deps.ts +80 -0
  65. package/scripts/generate-openapi.ts +24 -7
  66. package/{src/memory/graph/inspect.ts → scripts/memory-inspect.ts} +28 -28
  67. package/src/__tests__/access-request-decision.test.ts +2 -11
  68. package/src/__tests__/acp-session.test.ts +4 -150
  69. package/src/__tests__/actor-token-service.test.ts +17 -678
  70. package/src/__tests__/agent-loop-callsite-precedence.test.ts +2 -6
  71. package/src/__tests__/agent-loop-override-profile.test.ts +404 -0
  72. package/src/__tests__/agent-loop-thinking.test.ts +4 -4
  73. package/src/__tests__/agent-wake-override-profile.test.ts +261 -0
  74. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -1
  75. package/src/__tests__/anthropic-provider.test.ts +127 -15
  76. package/src/__tests__/app-compiler.test.ts +57 -0
  77. package/src/__tests__/app-routes-csp.test.ts +106 -55
  78. package/src/__tests__/approval-cascade.test.ts +10 -357
  79. package/src/__tests__/approval-conversation-turn.test.ts +3 -8
  80. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +1 -1
  81. package/src/__tests__/approval-primitive.test.ts +2 -1
  82. package/src/__tests__/approval-routes-http.test.ts +34 -451
  83. package/src/__tests__/assistant-events-sse-hardening.test.ts +73 -80
  84. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -3
  85. package/src/__tests__/attachment-upload-trusted-source.test.ts +139 -0
  86. package/src/__tests__/attachments-store.test.ts +46 -1
  87. package/src/__tests__/audit-log-rotation.test.ts +2 -1
  88. package/src/__tests__/auto-analysis-end-to-end.test.ts +9 -20
  89. package/src/__tests__/avatar-generator.test.ts +4 -2
  90. package/src/__tests__/background-shell-bash.test.ts +227 -0
  91. package/src/__tests__/background-shell-host-bash.test.ts +474 -0
  92. package/src/__tests__/background-tool-registry.test.ts +145 -0
  93. package/src/__tests__/background-tool-routes.test.ts +175 -0
  94. package/src/__tests__/btw-routes.test.ts +147 -183
  95. package/src/__tests__/bundled-asset.test.ts +6 -6
  96. package/src/__tests__/call-controller.test.ts +15 -2
  97. package/src/__tests__/call-conversation-messages.test.ts +2 -1
  98. package/src/__tests__/call-domain.test.ts +2 -2
  99. package/src/__tests__/call-pointer-messages.test.ts +11 -13
  100. package/src/__tests__/call-recovery.test.ts +2 -1
  101. package/src/__tests__/call-routes-http.test.ts +3 -14
  102. package/src/__tests__/call-store.test.ts +2 -1
  103. package/src/__tests__/cancel-resolves-conversation-key.test.ts +31 -62
  104. package/src/__tests__/canonical-guardian-store.test.ts +2 -2
  105. package/src/__tests__/catalog-cache.test.ts +69 -0
  106. package/src/__tests__/catalog-files.test.ts +0 -26
  107. package/src/__tests__/ces-rpc-credential-backend.test.ts +1 -1
  108. package/src/__tests__/channel-approval-routes.test.ts +79 -49
  109. package/src/__tests__/channel-approval.test.ts +9 -7
  110. package/src/__tests__/channel-approvals.test.ts +9 -180
  111. package/src/__tests__/channel-delivery-store.test.ts +11 -10
  112. package/src/__tests__/channel-guardian.test.ts +14 -25
  113. package/src/__tests__/channel-readiness-service.test.ts +8 -6
  114. package/src/__tests__/channel-reply-delivery.test.ts +3 -19
  115. package/src/__tests__/channel-retry-sweep.test.ts +2 -5
  116. package/src/__tests__/checker.test.ts +447 -3806
  117. package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
  118. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +208 -0
  119. package/src/__tests__/cli.test.ts +1 -38
  120. package/src/__tests__/compaction-events.test.ts +500 -0
  121. package/src/__tests__/compaction-pipeline.test.ts +210 -0
  122. package/src/__tests__/compaction-strip-metadata-clear.test.ts +181 -0
  123. package/src/__tests__/compaction-timeout-recovery.test.ts +262 -0
  124. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -7
  125. package/src/__tests__/config-model-image-provider.test.ts +109 -0
  126. package/src/__tests__/config-schema-cmd.test.ts +1 -1
  127. package/src/__tests__/config-schema.test.ts +25 -203
  128. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
  129. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +4 -25
  130. package/src/__tests__/contact-store-user-file.test.ts +2 -1
  131. package/src/__tests__/contacts-tools.test.ts +71 -18
  132. package/src/__tests__/contacts-write.test.ts +6 -61
  133. package/src/__tests__/context-overflow-policy.test.ts +7 -7
  134. package/src/__tests__/context-search-agent-protocol.test.ts +230 -0
  135. package/src/__tests__/context-search-agent-runner.test.ts +998 -0
  136. package/src/__tests__/context-search-conversations-source.test.ts +320 -0
  137. package/src/__tests__/context-search-fanout.test.ts +380 -0
  138. package/src/__tests__/context-search-memory-source.test.ts +311 -0
  139. package/src/__tests__/context-search-pkb-source.test.ts +444 -0
  140. package/src/__tests__/context-search-types.test.ts +95 -0
  141. package/src/__tests__/context-search-workspace-source.test.ts +545 -0
  142. package/src/__tests__/context-window-manager.test.ts +380 -4
  143. package/src/__tests__/conversation-abort-tool-results.test.ts +14 -2
  144. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +631 -0
  145. package/src/__tests__/conversation-agent-loop-overflow.test.ts +41 -32
  146. package/src/__tests__/conversation-agent-loop.test.ts +54 -143
  147. package/src/__tests__/conversation-analysis-routes.test.ts +60 -82
  148. package/src/__tests__/conversation-attachments.test.ts +9 -20
  149. package/src/__tests__/conversation-attention-store.test.ts +2 -1
  150. package/src/__tests__/conversation-attention-telegram.test.ts +4 -2
  151. package/src/__tests__/conversation-clear-safety.test.ts +53 -95
  152. package/src/__tests__/conversation-confirmation-signals.test.ts +7 -40
  153. package/src/__tests__/conversation-crud-inference-profile.test.ts +54 -0
  154. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +63 -157
  155. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  156. package/src/__tests__/conversation-disk-view.test.ts +5 -4
  157. package/src/__tests__/conversation-fork-crud.test.ts +26 -55
  158. package/src/__tests__/conversation-fork-route.test.ts +5 -74
  159. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  160. package/src/__tests__/conversation-inference-profile-list.test.ts +128 -0
  161. package/src/__tests__/conversation-inference-profile-route.test.ts +216 -0
  162. package/src/__tests__/conversation-init.benchmark.test.ts +4 -95
  163. package/src/__tests__/conversation-key-store-disk-view.test.ts +2 -1
  164. package/src/__tests__/conversation-lifecycle.test.ts +0 -1
  165. package/src/__tests__/conversation-list-source.test.ts +2 -2
  166. package/src/__tests__/conversation-load-history-repair.test.ts +0 -1
  167. package/src/__tests__/conversation-pairing.test.ts +174 -11
  168. package/src/__tests__/conversation-pre-run-repair.test.ts +137 -294
  169. package/src/__tests__/conversation-process-callsite.test.ts +3 -1
  170. package/src/__tests__/conversation-provider-retry-repair.test.ts +22 -8
  171. package/src/__tests__/conversation-queue.test.ts +30 -47
  172. package/src/__tests__/conversation-routes-disk-view.test.ts +131 -103
  173. package/src/__tests__/conversation-routes-guardian-reply.test.ts +80 -55
  174. package/src/__tests__/conversation-routes-slash-commands.test.ts +83 -12
  175. package/src/__tests__/conversation-runtime-assembly.test.ts +196 -194
  176. package/src/__tests__/conversation-runtime-workspace.test.ts +23 -38
  177. package/src/__tests__/conversation-seed-composer.test.ts +2 -2
  178. package/src/__tests__/conversation-slash-commands.test.ts +6 -43
  179. package/src/__tests__/conversation-slash-queue.test.ts +7 -3
  180. package/src/__tests__/conversation-slash-unknown.test.ts +25 -3
  181. package/src/__tests__/conversation-speed-override.test.ts +6 -2
  182. package/src/__tests__/conversation-starter-routes.test.ts +177 -55
  183. package/src/__tests__/conversation-starters-cadence.test.ts +2 -2
  184. package/src/__tests__/conversation-store.test.ts +2 -375
  185. package/src/__tests__/conversation-title-service.test.ts +116 -0
  186. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +42 -3
  187. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +6 -6
  188. package/src/__tests__/conversation-unread-route.test.ts +1 -1
  189. package/src/__tests__/conversation-usage.test.ts +3 -2
  190. package/src/__tests__/conversation-wipe.test.ts +2 -103
  191. package/src/__tests__/conversation-workspace-cache-state.test.ts +4 -2
  192. package/src/__tests__/conversation-workspace-injection.test.ts +3 -1
  193. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -2
  194. package/src/__tests__/conversations-defer-cli.test.ts +150 -0
  195. package/src/__tests__/credential-execution-admin-cli.test.ts +1 -1
  196. package/src/__tests__/credential-execution-api-key-propagation.test.ts +2 -2
  197. package/src/__tests__/credential-execution-approval-bridge.test.ts +22 -289
  198. package/src/__tests__/credential-execution-client.test.ts +1 -1
  199. package/src/__tests__/credential-execution-managed-contract.test.ts +1 -1
  200. package/src/__tests__/credential-health-service.test.ts +78 -9
  201. package/src/__tests__/credential-security-invariants.test.ts +16 -2
  202. package/src/__tests__/credentials-cli.test.ts +45 -21
  203. package/src/__tests__/daemon-credential-client.test.ts +23 -108
  204. package/src/__tests__/db-acp-history.test.ts +284 -0
  205. package/src/__tests__/db-activation-state.test.ts +240 -0
  206. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +2 -1
  207. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +248 -0
  208. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +2 -1
  209. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +116 -0
  210. package/src/__tests__/db-rename-inference-profile-snake-case-migration.test.ts +132 -0
  211. package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
  212. package/src/__tests__/delete-propagation.test.ts +3 -2
  213. package/src/__tests__/deterministic-verification-control-plane.test.ts +39 -32
  214. package/src/__tests__/dm-backfill.test.ts +3 -2
  215. package/src/__tests__/edit-propagation.test.ts +5 -7
  216. package/src/__tests__/embedding-managed-proxy-selection.test.ts +1 -1
  217. package/src/__tests__/empty-response-pipeline.test.ts +305 -0
  218. package/src/__tests__/events-client-registration.test.ts +297 -0
  219. package/src/__tests__/file-write-tool.test.ts +2 -4
  220. package/src/__tests__/filing-service.test.ts +144 -17
  221. package/src/__tests__/first-greeting.test.ts +247 -5
  222. package/src/__tests__/followup-tools.test.ts +2 -1
  223. package/src/__tests__/gateway-client-managed-outbound.test.ts +8 -12
  224. package/src/__tests__/gateway-only-enforcement.test.ts +2 -6
  225. package/src/__tests__/gateway-only-guard.test.ts +4 -3
  226. package/src/__tests__/gemini-provider.test.ts +276 -10
  227. package/src/__tests__/graph-extraction-event-date.test.ts +30 -0
  228. package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -1
  229. package/src/__tests__/guardian-action-followup-executor.test.ts +2 -2
  230. package/src/__tests__/guardian-action-followup-store.test.ts +2 -1
  231. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +9 -9
  232. package/src/__tests__/guardian-action-late-reply.test.ts +2 -1
  233. package/src/__tests__/guardian-action-store.test.ts +2 -1
  234. package/src/__tests__/guardian-action-sweep.test.ts +9 -8
  235. package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -1
  236. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +21 -118
  237. package/src/__tests__/guardian-dispatch.test.ts +14 -11
  238. package/src/__tests__/guardian-grant-minting.test.ts +9 -15
  239. package/src/__tests__/guardian-outbound-http.test.ts +71 -106
  240. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -2
  241. package/src/__tests__/guardian-routing-invariants.test.ts +34 -90
  242. package/src/__tests__/guardian-routing-state.test.ts +14 -22
  243. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -2
  244. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +253 -0
  245. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +8 -4
  246. package/src/__tests__/headless-browser-mode.test.ts +57 -0
  247. package/src/__tests__/heartbeat-service.test.ts +39 -21
  248. package/src/__tests__/helpers/call-route-handler.ts +72 -0
  249. package/src/__tests__/helpers/channel-test-adapter.ts +161 -0
  250. package/src/__tests__/helpers/gateway-classify-mock.ts +67 -0
  251. package/src/__tests__/helpers/mock-logger.ts +36 -0
  252. package/src/__tests__/history-repair-pipeline.test.ts +399 -0
  253. package/src/__tests__/home-state-routes.test.ts +10 -31
  254. package/src/__tests__/host-browser-e2e-cloud.test.ts +309 -1
  255. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +12 -2
  256. package/src/__tests__/host-browser-routes.test.ts +36 -91
  257. package/src/__tests__/host-browser-ws-events-e2e.test.ts +10 -2
  258. package/src/__tests__/host-proxy-interface.test.ts +38 -4
  259. package/src/__tests__/host-shell-tool.test.ts +2 -4
  260. package/src/__tests__/host-transfer-pending-interactions.test.ts +160 -0
  261. package/src/__tests__/host-transfer-proxy.test.ts +733 -0
  262. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  263. package/src/__tests__/http-user-message-parity.test.ts +20 -11
  264. package/src/__tests__/image-credentials.test.ts +137 -0
  265. package/src/__tests__/image-service-dispatcher.test.ts +186 -0
  266. package/src/__tests__/inbound-invite-redemption.test.ts +3 -2
  267. package/src/__tests__/injector-chain.test.ts +525 -0
  268. package/src/__tests__/inline-skill-load-permissions.test.ts +41 -206
  269. package/src/__tests__/install-skill-routing.test.ts +1 -1
  270. package/src/__tests__/intent-routing.test.ts +0 -26
  271. package/src/__tests__/invite-redemption-service.test.ts +2 -1
  272. package/src/__tests__/invite-routes-http.test.ts +80 -12
  273. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +2 -1
  274. package/src/__tests__/jobs-store-upsert-debounced.test.ts +2 -1
  275. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +157 -0
  276. package/src/__tests__/list-messages-attachments.test.ts +52 -55
  277. package/src/__tests__/list-messages-page-latest.test.ts +283 -0
  278. package/src/__tests__/list-messages-tool-merge.test.ts +16 -17
  279. package/src/__tests__/llm-call-pipeline.test.ts +284 -0
  280. package/src/__tests__/llm-context-normalization.test.ts +69 -4
  281. package/src/__tests__/llm-context-route-provider.test.ts +39 -113
  282. package/src/__tests__/llm-request-log-turn-query.test.ts +2 -1
  283. package/src/__tests__/llm-resolver.test.ts +211 -0
  284. package/src/__tests__/llm-schema.test.ts +56 -0
  285. package/src/__tests__/llm-usage-store.test.ts +2 -1
  286. package/src/__tests__/log-export-workspace.test.ts +28 -17
  287. package/src/__tests__/mcp-abort-signal.test.ts +2 -3
  288. package/src/__tests__/mcp-client-auth.test.ts +2 -3
  289. package/src/__tests__/media-generate-image.test.ts +119 -13
  290. package/src/__tests__/memory-admin-recall.test.ts +221 -0
  291. package/src/__tests__/memory-recall-log-store.test.ts +2 -1
  292. package/src/__tests__/memory-retrieval-pipeline.test.ts +399 -0
  293. package/src/__tests__/memory-upsert-concurrency.test.ts +3 -1
  294. package/src/__tests__/migration-cross-version-compatibility.test.ts +14 -13
  295. package/src/__tests__/migration-export-http.test.ts +17 -17
  296. package/src/__tests__/migration-export-to-gcs.test.ts +491 -0
  297. package/src/__tests__/migration-import-commit-http.test.ts +16 -16
  298. package/src/__tests__/migration-import-from-gcs.test.ts +533 -0
  299. package/src/__tests__/migration-import-from-url.test.ts +21 -91
  300. package/src/__tests__/migration-import-preflight-http.test.ts +13 -13
  301. package/src/__tests__/migration-jobs-status.test.ts +164 -0
  302. package/src/__tests__/migration-validate-http.test.ts +48 -83
  303. package/src/__tests__/mock-gateway-ipc.ts +32 -62
  304. package/src/__tests__/model-intents.test.ts +16 -1
  305. package/src/__tests__/nl-approval-parser.test.ts +13 -17
  306. package/src/__tests__/non-member-access-request.test.ts +13 -5
  307. package/src/__tests__/notification-broadcaster.test.ts +3 -3
  308. package/src/__tests__/notification-decision-strategy.test.ts +0 -11
  309. package/src/__tests__/notification-guardian-path.test.ts +15 -8
  310. package/src/__tests__/notification-schedule-notify-dedup.test.ts +109 -0
  311. package/src/__tests__/notification-telegram-adapter.test.ts +57 -55
  312. package/src/__tests__/oauth-apps-routes.test.ts +77 -123
  313. package/src/__tests__/oauth-cli.test.ts +28 -13
  314. package/src/__tests__/oauth-connect-orchestrator.test.ts +4 -13
  315. package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
  316. package/src/__tests__/oauth-provider-serializer.test.ts +6 -4
  317. package/src/__tests__/oauth-provider-visibility.test.ts +6 -6
  318. package/src/__tests__/oauth-providers-routes.test.ts +81 -103
  319. package/src/__tests__/oauth-store.test.ts +44 -77
  320. package/src/__tests__/oauth2-gateway-transport.test.ts +6 -3
  321. package/src/__tests__/onboarding-template-contract.test.ts +16 -64
  322. package/src/__tests__/openai-image-service.test.ts +368 -0
  323. package/src/__tests__/openai-provider.test.ts +105 -6
  324. package/src/__tests__/openai-responses-provider.test.ts +146 -4
  325. package/src/__tests__/openrouter-provider-only.test.ts +22 -4
  326. package/src/__tests__/overflow-reduce-pipeline.test.ts +671 -0
  327. package/src/__tests__/permission-types.test.ts +3 -18
  328. package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
  329. package/src/__tests__/persistence-pipeline.test.ts +378 -0
  330. package/src/__tests__/pipeline-runner.test.ts +565 -0
  331. package/src/__tests__/platform-bash-auto-approve.test.ts +27 -20
  332. package/src/__tests__/platform.test.ts +10 -59
  333. package/src/__tests__/playbook-execution.test.ts +2 -1
  334. package/src/__tests__/playbook-tools.test.ts +2 -1
  335. package/src/__tests__/plugin-bootstrap.test.ts +529 -0
  336. package/src/__tests__/plugin-registry.test.ts +303 -0
  337. package/src/__tests__/plugin-route-contribution.test.ts +294 -0
  338. package/src/__tests__/plugin-skill-contribution.test.ts +367 -0
  339. package/src/__tests__/plugin-tool-contribution.test.ts +292 -0
  340. package/src/__tests__/plugin-types.test.ts +320 -0
  341. package/src/__tests__/pricing.test.ts +195 -14
  342. package/src/__tests__/profiler-routes.test.ts +112 -177
  343. package/src/__tests__/provider-send-message-override-profile.test.ts +223 -0
  344. package/src/__tests__/proxy-approval-callback.test.ts +6 -493
  345. package/src/__tests__/qdrant-collection-migration.test.ts +7 -7
  346. package/src/__tests__/reaction-persistence.test.ts +4 -2
  347. package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
  348. package/src/__tests__/recording-handler.test.ts +0 -2
  349. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  350. package/src/__tests__/registry.test.ts +1 -2
  351. package/src/__tests__/relay-server.test.ts +19 -4
  352. package/src/__tests__/require-fresh-approval.test.ts +19 -168
  353. package/src/__tests__/resolve-trust-class.test.ts +2 -1
  354. package/src/__tests__/retry-thinking-tool-choice.test.ts +19 -7
  355. package/src/__tests__/retry-verbosity-normalization.test.ts +139 -0
  356. package/src/__tests__/runtime-attachment-metadata.test.ts +26 -6
  357. package/src/__tests__/runtime-events-sse-parity.test.ts +12 -13
  358. package/src/__tests__/runtime-events-sse.test.ts +13 -21
  359. package/src/__tests__/schedule-routes.test.ts +304 -77
  360. package/src/__tests__/schedule-store.test.ts +119 -1
  361. package/src/__tests__/schedule-tools.test.ts +2 -1
  362. package/src/__tests__/scheduler-recurrence.test.ts +16 -71
  363. package/src/__tests__/scheduler-reuse-conversation.test.ts +12 -51
  364. package/src/__tests__/scheduler-wake.test.ts +356 -0
  365. package/src/__tests__/scoped-approval-grants.test.ts +2 -1
  366. package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -1
  367. package/src/__tests__/secret-detection-handler.test.ts +2 -19
  368. package/src/__tests__/secret-ingress-http.test.ts +38 -21
  369. package/src/__tests__/secret-routes-managed-proxy.test.ts +46 -102
  370. package/src/__tests__/secret-scanner-executor.test.ts +1 -2
  371. package/src/__tests__/send-endpoint-busy.test.ts +38 -25
  372. package/src/__tests__/sequence-store.test.ts +2 -1
  373. package/src/__tests__/server-history-render.test.ts +2 -2
  374. package/src/__tests__/service-contracts-import-guard.test.ts +185 -0
  375. package/src/__tests__/set-permission-mode.test.ts +0 -10
  376. package/src/__tests__/settings-routes.test.ts +35 -68
  377. package/src/__tests__/skill-boundary-guard.test.ts +105 -0
  378. package/src/__tests__/skill-load-inline-command.test.ts +2 -2
  379. package/src/__tests__/skill-load-inline-includes.test.ts +2 -2
  380. package/src/__tests__/skill-runtime-path.test.ts +64 -0
  381. package/src/__tests__/skills-file-content-endpoint.test.ts +0 -2
  382. package/src/__tests__/slack-inbound-verification.test.ts +11 -2
  383. package/src/__tests__/slack-messaging-token-resolution.test.ts +1 -3
  384. package/src/__tests__/slack-reaction-approvals.test.ts +4 -4
  385. package/src/__tests__/slack-share-routes.test.ts +37 -72
  386. package/src/__tests__/subagent-call-site-routing.test.ts +79 -0
  387. package/src/__tests__/subagent-fork-spawn.test.ts +20 -28
  388. package/src/__tests__/subagent-notify-parent.test.ts +6 -29
  389. package/src/__tests__/subagent-role-registry.test.ts +3 -3
  390. package/src/__tests__/subagent-spawn-tool-fork.test.ts +52 -104
  391. package/src/__tests__/subagent-tools.test.ts +0 -1
  392. package/src/__tests__/suggestion-routes.test.ts +149 -57
  393. package/src/__tests__/task-compiler.test.ts +2 -1
  394. package/src/__tests__/task-management-tools.test.ts +2 -1
  395. package/src/__tests__/task-memory-cleanup.test.ts +3 -1
  396. package/src/__tests__/task-scheduler.test.ts +5 -16
  397. package/src/__tests__/telegram-config.test.ts +0 -1
  398. package/src/__tests__/terminal-tools.test.ts +5 -314
  399. package/src/__tests__/thread-backfill.test.ts +3 -2
  400. package/src/__tests__/title-generate-pipeline.test.ts +224 -0
  401. package/src/__tests__/token-estimate-pipeline.test.ts +484 -0
  402. package/src/__tests__/tool-approval-handler.test.ts +21 -63
  403. package/src/__tests__/tool-audit-listener.test.ts +3 -3
  404. package/src/__tests__/tool-domain-event-publisher.test.ts +3 -3
  405. package/src/__tests__/tool-error-pipeline.test.ts +244 -0
  406. package/src/__tests__/tool-execute-pipeline.test.ts +429 -0
  407. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +61 -4
  408. package/src/__tests__/tool-executor-lifecycle-events.test.ts +28 -56
  409. package/src/__tests__/tool-executor.test.ts +434 -1604
  410. package/src/__tests__/tool-grant-request-escalation.test.ts +90 -311
  411. package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
  412. package/src/__tests__/tool-result-truncation.test.ts +0 -110
  413. package/src/__tests__/trust-context-guards.test.ts +1 -1
  414. package/src/__tests__/trusted-contact-approval-notifier.test.ts +7 -15
  415. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +178 -354
  416. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +3 -2
  417. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -2
  418. package/src/__tests__/trusted-contact-verification.test.ts +2 -1
  419. package/src/__tests__/turn-boundary-resolution.test.ts +2 -1
  420. package/src/__tests__/twilio-routes.test.ts +25 -66
  421. package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -7
  422. package/src/__tests__/usage-routes.test.ts +73 -90
  423. package/src/__tests__/user-plugin-loader.test.ts +233 -0
  424. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +2 -2
  425. package/src/__tests__/verification-control-plane-policy.test.ts +95 -14
  426. package/src/__tests__/voice-ingress-preflight.test.ts +5 -5
  427. package/src/__tests__/voice-invite-redemption.test.ts +2 -1
  428. package/src/__tests__/voice-scoped-grant-consumer.test.ts +3 -3
  429. package/src/__tests__/voice-session-bridge.test.ts +285 -106
  430. package/src/__tests__/volume-security-guard.test.ts +0 -2
  431. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -1
  432. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +3 -1
  433. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +2 -1
  434. package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +1 -1
  435. package/src/__tests__/workspace-migration-046-seed-conversation-starters-callsite.test.ts +185 -0
  436. package/src/__tests__/workspace-migration-049-release-notes-default-sonnet.test.ts +100 -0
  437. package/src/__tests__/workspace-migration-050-seed-main-agent-opus-callsite.test.ts +171 -0
  438. package/src/__tests__/workspace-migration-051-seed-conversation-summarization-callsite.test.ts +252 -0
  439. package/src/__tests__/workspace-migration-052-seed-default-inference-profiles.test.ts +260 -0
  440. package/src/__tests__/workspace-migration-053-release-notes-acp-codex.test.ts +225 -0
  441. package/src/__tests__/workspace-migration-054-seed-recall-callsite.test.ts +235 -0
  442. package/src/__tests__/workspace-migration-055-release-notes-agentic-recall.test.ts +128 -0
  443. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +232 -0
  444. package/src/__tests__/workspace-migration-acp-sessions-ui.test.ts +144 -0
  445. package/src/__tests__/workspace-migration-drop-user-md.test.ts +1 -1
  446. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +274 -0
  447. package/src/__tests__/workspace-migration-remove-hooks.test.ts +99 -0
  448. package/src/__tests__/workspace-policy.test.ts +21 -3
  449. package/src/acp/__tests__/client-handler.test.ts +64 -0
  450. package/src/acp/__tests__/helpers/acp-config-stub.ts +62 -0
  451. package/src/acp/__tests__/helpers/which-stub.ts +45 -0
  452. package/src/acp/__tests__/session-manager-persistence.test.ts +366 -0
  453. package/src/acp/__tests__/session-manager-startup.test.ts +159 -0
  454. package/src/acp/__tests__/session-manager.test.ts +83 -0
  455. package/src/acp/client-handler.ts +23 -139
  456. package/src/acp/resolve-agent.test.ts +291 -0
  457. package/src/acp/resolve-agent.ts +176 -0
  458. package/src/acp/session-manager.ts +166 -7
  459. package/src/acp/types.ts +2 -50
  460. package/src/agent/loop.ts +365 -104
  461. package/src/agent/message-types.ts +0 -2
  462. package/src/approvals/AGENTS.md +1 -1
  463. package/src/approvals/__tests__/guardian-feed-event.test.ts +296 -0
  464. package/src/approvals/approval-primitive.ts +3 -20
  465. package/src/approvals/guardian-decision-primitive.ts +37 -68
  466. package/src/approvals/guardian-request-resolvers.ts +109 -103
  467. package/src/avatar/character-components.ts +6 -6
  468. package/src/{config/bundled-skills/settings/tools → avatar}/identity-avatar.ts +1 -1
  469. package/src/backup/__tests__/backup-worker.test.ts +2 -15
  470. package/src/backup/__tests__/paths.test.ts +3 -2
  471. package/src/backup/backup-worker.ts +3 -24
  472. package/src/backup/paths.ts +2 -18
  473. package/src/backup/restore.ts +7 -11
  474. package/src/browser/__tests__/operations.test.ts +0 -35
  475. package/src/browser/operations.ts +1 -47
  476. package/src/bundler/app-compiler.ts +84 -1
  477. package/src/bundler/package-resolver.ts +2 -6
  478. package/src/calls/active-call-lease.ts +1 -1
  479. package/src/calls/call-constants.ts +1 -1
  480. package/src/calls/call-controller.ts +1 -5
  481. package/src/calls/call-domain.ts +14 -14
  482. package/src/calls/call-pointer-messages.ts +4 -9
  483. package/src/calls/call-state.ts +2 -2
  484. package/src/calls/call-store.ts +2 -1
  485. package/src/calls/guardian-action-sweep.ts +9 -25
  486. package/src/calls/guardian-dispatch.ts +1 -20
  487. package/src/calls/media-stream-audio-transcode.ts +2 -41
  488. package/src/calls/media-stream-server.ts +2 -3
  489. package/src/calls/media-stream-stt-session.ts +1 -3
  490. package/src/calls/relay-access-wait.ts +5 -8
  491. package/src/calls/relay-server.ts +15 -18
  492. package/src/calls/relay-setup-router.ts +2 -2
  493. package/src/calls/relay-verification.ts +4 -4
  494. package/src/calls/twilio-rest.ts +1 -1
  495. package/src/calls/twilio-routes.ts +160 -78
  496. package/src/calls/voice-control-protocol.ts +10 -10
  497. package/src/calls/voice-ingress-preflight.ts +2 -2
  498. package/src/calls/voice-session-bridge.ts +137 -42
  499. package/src/channels/__tests__/types.test.ts +28 -6
  500. package/src/channels/permission-profiles.ts +2 -72
  501. package/src/channels/types.ts +48 -30
  502. package/src/cli/AGENTS.md +1 -0
  503. package/src/cli/__tests__/notifications.test.ts +92 -214
  504. package/src/cli/commands/__tests__/attachment.test.ts +14 -8
  505. package/src/cli/commands/__tests__/backup.test.ts +4 -15
  506. package/src/cli/commands/__tests__/browser.test.ts +36 -31
  507. package/src/cli/commands/__tests__/cache.test.ts +23 -18
  508. package/src/cli/commands/__tests__/image-generation.test.ts +255 -35
  509. package/src/cli/commands/__tests__/inference-send.test.ts +12 -0
  510. package/src/cli/commands/__tests__/memory-v2.test.ts +396 -0
  511. package/src/cli/commands/__tests__/task.test.ts +36 -35
  512. package/src/cli/commands/__tests__/trust.test.ts +602 -0
  513. package/src/cli/commands/__tests__/tts-synthesize.test.ts +12 -0
  514. package/src/cli/commands/__tests__/ui-confirm.test.ts +14 -14
  515. package/src/cli/commands/__tests__/ui.test.ts +17 -17
  516. package/src/cli/commands/__tests__/watchers.test.ts +29 -29
  517. package/src/cli/commands/__tests__/webhooks.test.ts +544 -0
  518. package/src/cli/commands/attachment.ts +12 -8
  519. package/src/cli/commands/auth.ts +1 -1
  520. package/src/cli/commands/avatar.ts +192 -9
  521. package/src/cli/commands/backup.ts +16 -46
  522. package/src/cli/commands/browser.ts +52 -4
  523. package/src/cli/commands/cache.ts +7 -5
  524. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  525. package/src/cli/commands/clients.ts +137 -0
  526. package/src/cli/commands/completions.ts +3 -10
  527. package/src/cli/commands/contacts.ts +10 -10
  528. package/src/cli/commands/conversations-defer.ts +364 -0
  529. package/src/cli/commands/conversations-import.ts +2 -3
  530. package/src/cli/commands/conversations.ts +115 -57
  531. package/src/cli/commands/credential-execution.ts +1 -1
  532. package/src/cli/commands/credentials.ts +139 -5
  533. package/src/cli/commands/default-action.ts +1 -1
  534. package/src/cli/commands/domain.ts +2 -2
  535. package/src/cli/commands/email.ts +7 -7
  536. package/src/cli/commands/image-generation.ts +33 -34
  537. package/src/cli/commands/keys.ts +2 -2
  538. package/src/cli/commands/mcp.ts +1 -1
  539. package/src/cli/commands/memory-v2.ts +343 -0
  540. package/src/cli/commands/memory.ts +8 -8
  541. package/src/cli/commands/notifications.ts +87 -121
  542. package/src/cli/commands/oauth/__tests__/connect.test.ts +23 -5
  543. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +1 -1
  544. package/src/cli/commands/oauth/__tests__/mode.test.ts +1 -1
  545. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -1
  546. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
  547. package/src/cli/commands/oauth/__tests__/status.test.ts +1 -1
  548. package/src/cli/commands/oauth/__tests__/token.test.ts +1 -1
  549. package/src/cli/commands/oauth/connect.ts +4 -4
  550. package/src/cli/commands/oauth/providers.ts +176 -8
  551. package/src/cli/commands/oauth/shared.ts +29 -2
  552. package/src/cli/commands/oauth/status.ts +46 -36
  553. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -6
  554. package/src/cli/commands/platform/__tests__/connect.test.ts +23 -11
  555. package/src/cli/commands/platform/__tests__/disconnect.test.ts +22 -10
  556. package/src/cli/commands/platform/__tests__/status.test.ts +22 -10
  557. package/src/cli/commands/platform/connect.ts +3 -3
  558. package/src/cli/commands/platform/disconnect.ts +4 -6
  559. package/src/cli/commands/platform/index.ts +12 -10
  560. package/src/cli/commands/routes.ts +7 -1
  561. package/src/cli/commands/sequence.ts +7 -7
  562. package/src/cli/commands/skills.ts +189 -84
  563. package/src/cli/commands/task.ts +12 -10
  564. package/src/cli/commands/trust.ts +460 -162
  565. package/src/cli/commands/ui.ts +3 -3
  566. package/src/cli/commands/usage.ts +10 -5
  567. package/src/cli/commands/watchers.ts +8 -8
  568. package/src/cli/commands/webhooks.ts +270 -0
  569. package/src/cli/lib/daemon-avatar-client.ts +37 -0
  570. package/src/cli/lib/daemon-credential-client.ts +27 -189
  571. package/src/cli/lib/ipc-params.ts +22 -0
  572. package/src/cli/program.ts +29 -29
  573. package/src/cli.ts +1 -61
  574. package/src/config/__tests__/backup-schema.test.ts +7 -2
  575. package/src/config/acp-defaults.test.ts +57 -0
  576. package/src/config/acp-defaults.ts +40 -0
  577. package/src/config/acp-schema.ts +1 -1
  578. package/src/config/assistant-feature-flags.ts +18 -142
  579. package/src/config/bundled-skills/acp/SKILL.md +44 -16
  580. package/src/config/bundled-skills/acp/TOOLS.json +45 -1
  581. package/src/config/bundled-skills/{screen-watch/tools/start-screen-watch.ts → acp/tools/acp-list-agents.ts} +2 -2
  582. package/src/config/bundled-skills/acp/tools/acp-steer.ts +12 -0
  583. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  584. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +10 -10
  585. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +66 -87
  586. package/src/config/bundled-skills/contacts/tools/contact-search.ts +25 -51
  587. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +31 -44
  588. package/src/config/bundled-skills/image-studio/SKILL.md +2 -1
  589. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -1
  590. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +23 -39
  591. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +6 -6
  592. package/src/config/bundled-skills/media-processing/services/reduce.ts +0 -13
  593. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  594. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +207 -0
  595. package/src/config/bundled-skills/messaging/tools/gmail-mime-helpers.ts +1 -1
  596. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +1 -1
  597. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +12 -0
  598. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +58 -0
  599. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -1
  600. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +1 -1
  601. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -1
  602. package/src/config/bundled-skills/schedule/SKILL.md +8 -3
  603. package/src/config/bundled-skills/schedule/TOOLS.json +15 -7
  604. package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +59 -0
  605. package/src/config/bundled-skills/settings/SKILL.md +2 -17
  606. package/src/config/bundled-skills/settings/TOOLS.json +0 -56
  607. package/src/config/bundled-skills/subagent/SKILL.md +2 -0
  608. package/src/config/bundled-tool-registry.ts +4 -21
  609. package/src/config/env.ts +7 -8
  610. package/src/config/feature-flag-registry.json +25 -17
  611. package/src/config/llm-resolver.ts +51 -33
  612. package/src/config/loader.ts +12 -15
  613. package/src/config/schema.ts +22 -70
  614. package/src/config/schemas/__tests__/filing.test.ts +58 -0
  615. package/src/config/schemas/__tests__/memory-v2.test.ts +186 -0
  616. package/src/config/schemas/backup.ts +1 -1
  617. package/src/config/schemas/conversations.ts +16 -0
  618. package/src/config/schemas/filing.ts +12 -0
  619. package/src/config/schemas/host-browser.ts +2 -2
  620. package/src/config/schemas/inference.ts +0 -2
  621. package/src/config/schemas/ingress.ts +1 -1
  622. package/src/config/schemas/llm.ts +51 -10
  623. package/src/config/schemas/memory-storage.ts +1 -1
  624. package/src/config/schemas/memory-v2.ts +176 -0
  625. package/src/config/schemas/memory.ts +2 -0
  626. package/src/config/schemas/security.ts +0 -60
  627. package/src/config/schemas/services.ts +46 -7
  628. package/src/config/schemas/tts.ts +11 -0
  629. package/src/config/skill-state.ts +6 -2
  630. package/src/config/skills.ts +95 -6
  631. package/src/config/types.ts +0 -41
  632. package/src/contacts/contact-store.ts +2 -2
  633. package/src/contacts/contacts-write.ts +0 -38
  634. package/src/contacts/types.ts +8 -10
  635. package/src/context/__tests__/compact-prompt.test.ts +27 -9
  636. package/src/context/prompts/compact.md +26 -12
  637. package/src/context/token-estimator.ts +1 -1
  638. package/src/context/tool-result-truncation.ts +4 -64
  639. package/src/context/window-manager.ts +191 -17
  640. package/src/credential-execution/approval-bridge.ts +7 -69
  641. package/src/credential-execution/client.ts +17 -422
  642. package/src/credential-execution/feature-gates.ts +1 -2
  643. package/src/credential-execution/managed-catalog.ts +1 -1
  644. package/src/credential-health/credential-health-service.ts +20 -7
  645. package/src/daemon/__tests__/conversation-feed-event.test.ts +304 -0
  646. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +4 -12
  647. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
  648. package/src/daemon/__tests__/conversation-tool-setup.test.ts +14 -15
  649. package/src/daemon/__tests__/daemon-skill-host.test.ts +272 -0
  650. package/src/daemon/__tests__/meet-host-supervisor.test.ts +587 -0
  651. package/src/daemon/__tests__/meet-manifest-loader.test.ts +463 -0
  652. package/src/daemon/approval-generators.ts +2 -14
  653. package/src/daemon/classifier.ts +0 -106
  654. package/src/daemon/config-watcher.ts +14 -56
  655. package/src/daemon/connection-policy.ts +0 -14
  656. package/src/daemon/context-overflow-policy.ts +4 -13
  657. package/src/daemon/conversation-agent-loop-handlers.ts +120 -28
  658. package/src/daemon/conversation-agent-loop.ts +1113 -701
  659. package/src/daemon/conversation-attachments.ts +5 -81
  660. package/src/daemon/conversation-error.ts +9 -5
  661. package/src/daemon/conversation-history.ts +11 -20
  662. package/src/daemon/conversation-launch.ts +1 -1
  663. package/src/daemon/conversation-lifecycle.ts +37 -19
  664. package/src/daemon/conversation-messaging.ts +1 -1
  665. package/src/daemon/conversation-notifiers.ts +3 -111
  666. package/src/daemon/conversation-process.ts +23 -20
  667. package/src/daemon/conversation-runtime-assembly.ts +530 -471
  668. package/src/daemon/conversation-slash.ts +4 -160
  669. package/src/daemon/conversation-store.ts +368 -0
  670. package/src/daemon/conversation-surfaces.ts +5 -4
  671. package/src/daemon/conversation-tool-setup.ts +49 -161
  672. package/src/daemon/conversation.ts +126 -217
  673. package/src/daemon/daemon-control.ts +3 -3
  674. package/src/daemon/daemon-skill-host.ts +262 -0
  675. package/src/daemon/external-plugins-bootstrap.ts +532 -0
  676. package/src/daemon/first-greeting.ts +191 -14
  677. package/src/daemon/handlers/config-channels.ts +2 -2
  678. package/src/daemon/handlers/config-embeddings.ts +1 -1
  679. package/src/daemon/handlers/config-ingress.ts +24 -2
  680. package/src/daemon/handlers/config-model.test.ts +17 -0
  681. package/src/daemon/handlers/config-model.ts +18 -52
  682. package/src/daemon/handlers/config-telegram.ts +6 -53
  683. package/src/daemon/handlers/config-voice.ts +1 -1
  684. package/src/daemon/handlers/conversations.ts +22 -156
  685. package/src/daemon/handlers/recording.ts +1 -1
  686. package/src/daemon/handlers/shared.ts +34 -35
  687. package/src/daemon/handlers/skills.ts +20 -24
  688. package/src/daemon/host-transfer-proxy.ts +500 -0
  689. package/src/daemon/lifecycle.ts +56 -326
  690. package/src/daemon/meet-host-startup.ts +51 -0
  691. package/src/daemon/meet-host-supervisor.ts +781 -0
  692. package/src/daemon/meet-manifest-loader.ts +410 -0
  693. package/src/daemon/memory-v2-startup.ts +35 -0
  694. package/src/daemon/message-protocol.ts +4 -7
  695. package/src/daemon/message-types/acp.ts +1 -0
  696. package/src/daemon/message-types/computer-use.ts +2 -34
  697. package/src/daemon/message-types/conversations.ts +65 -2
  698. package/src/daemon/message-types/host-transfer.ts +41 -0
  699. package/src/daemon/message-types/integrations.ts +6 -0
  700. package/src/daemon/message-types/messages.ts +26 -14
  701. package/src/daemon/message-types/schedules.ts +1 -0
  702. package/src/daemon/message-types/settings.ts +0 -6
  703. package/src/daemon/message-types/shared.ts +5 -2
  704. package/src/daemon/message-types/subagents.ts +2 -1
  705. package/src/daemon/message-types/workspace.ts +0 -2
  706. package/src/daemon/pkb-reminder-builder.test.ts +13 -12
  707. package/src/daemon/pkb-reminder-builder.ts +8 -16
  708. package/src/daemon/process-message.ts +616 -0
  709. package/src/daemon/providers-setup.ts +14 -6
  710. package/src/daemon/server.ts +79 -1272
  711. package/src/daemon/shutdown-handlers.ts +3 -13
  712. package/src/daemon/startup-error.ts +1 -1
  713. package/src/daemon/tool-side-effects.ts +14 -56
  714. package/src/daemon/trust-context.ts +32 -0
  715. package/src/daemon/wake-target-adapter.ts +223 -0
  716. package/src/email/feature-gate.ts +1 -1
  717. package/src/events/domain-events.ts +1 -8
  718. package/src/events/tool-audit-listener.ts +2 -8
  719. package/src/events/tool-metrics-listener.ts +1 -4
  720. package/src/filing/filing-service.ts +194 -54
  721. package/src/followups/followup-store.ts +3 -71
  722. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +228 -0
  723. package/src/heartbeat/heartbeat-service.ts +52 -8
  724. package/src/home/__tests__/feed-population-integration.test.ts +312 -0
  725. package/src/home/__tests__/phase5-exit-criteria.test.ts +18 -1
  726. package/src/home/__tests__/rollup-producer.test.ts +67 -2
  727. package/src/home/assistant-feed-authoring.ts +8 -1
  728. package/src/home/emit-feed-event.ts +7 -0
  729. package/src/home/feed-types.ts +42 -3
  730. package/src/home/relationship-state-writer.ts +1 -1
  731. package/src/home/rewrite-command-preview.ts +66 -0
  732. package/src/home/rewrite-feed-title.ts +58 -0
  733. package/src/home/rollup-producer.ts +16 -3
  734. package/src/inbound/platform-callback-registration.ts +1 -17
  735. package/src/ipc/__tests__/attachment-ipc.test.ts +128 -66
  736. package/src/ipc/__tests__/browser-ipc.test.ts +75 -51
  737. package/src/ipc/__tests__/cache-ipc.test.ts +52 -107
  738. package/src/ipc/__tests__/cli-ipc.test.ts +9 -6
  739. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +254 -0
  740. package/src/ipc/__tests__/skill-server.test.ts +182 -0
  741. package/src/ipc/__tests__/socket-path.test.ts +44 -37
  742. package/src/ipc/__tests__/ui-request-route.test.ts +241 -216
  743. package/src/ipc/__tests__/watcher-ipc.test.ts +33 -33
  744. package/src/ipc/assistant-server.ts +450 -0
  745. package/src/ipc/cli-client.ts +3 -3
  746. package/src/ipc/gateway-client.test.ts +131 -0
  747. package/src/ipc/gateway-client.ts +98 -120
  748. package/src/ipc/ipc-framing.ts +281 -0
  749. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +152 -0
  750. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +219 -0
  751. package/src/ipc/routes/db-proxy.ts +73 -0
  752. package/src/ipc/routes/route-adapter.ts +32 -0
  753. package/src/ipc/routes/trust-rules.test.ts +218 -0
  754. package/src/ipc/skill-ipc-types.ts +13 -0
  755. package/src/ipc/skill-routes/__tests__/config.test.ts +146 -0
  756. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +402 -0
  757. package/src/ipc/skill-routes/__tests__/identity.test.ts +81 -0
  758. package/src/ipc/skill-routes/__tests__/log.test.ts +133 -0
  759. package/src/ipc/skill-routes/__tests__/memory.test.ts +178 -0
  760. package/src/ipc/skill-routes/__tests__/platform.test.ts +111 -0
  761. package/src/ipc/skill-routes/__tests__/providers.test.ts +265 -0
  762. package/src/ipc/skill-routes/__tests__/registries.test.ts +361 -0
  763. package/src/ipc/skill-routes/config.ts +47 -0
  764. package/src/ipc/skill-routes/events.ts +131 -0
  765. package/src/ipc/skill-routes/identity.ts +34 -0
  766. package/src/ipc/skill-routes/index.ts +37 -0
  767. package/src/ipc/skill-routes/log.ts +40 -0
  768. package/src/ipc/skill-routes/memory.ts +76 -0
  769. package/src/ipc/skill-routes/platform.ts +39 -0
  770. package/src/ipc/skill-routes/providers.ts +163 -0
  771. package/src/ipc/skill-routes/registries.ts +393 -0
  772. package/src/ipc/skill-server.ts +771 -0
  773. package/src/ipc/skill-socket-path.ts +20 -0
  774. package/src/ipc/socket-cleanup.ts +92 -0
  775. package/src/ipc/socket-path.ts +55 -48
  776. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +374 -0
  777. package/src/live-voice/__tests__/live-voice-archive.test.ts +525 -0
  778. package/src/live-voice/__tests__/live-voice-events.test.ts +473 -0
  779. package/src/live-voice/__tests__/live-voice-integration.test.ts +359 -0
  780. package/src/live-voice/__tests__/live-voice-metrics.test.ts +179 -0
  781. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +349 -0
  782. package/src/live-voice/__tests__/live-voice-stt.test.ts +244 -0
  783. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +337 -0
  784. package/src/live-voice/__tests__/live-voice-tts.test.ts +337 -0
  785. package/src/live-voice/__tests__/protocol.test.ts +295 -0
  786. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +421 -0
  787. package/src/live-voice/live-voice-archive.ts +758 -0
  788. package/src/live-voice/live-voice-metrics.ts +472 -0
  789. package/src/live-voice/live-voice-session-manager.ts +222 -0
  790. package/src/live-voice/live-voice-session.ts +1144 -0
  791. package/src/live-voice/live-voice-tts.ts +260 -0
  792. package/src/live-voice/protocol.ts +524 -0
  793. package/src/mcp/client.ts +2 -2
  794. package/src/media/app-icon-generator.ts +23 -46
  795. package/src/media/avatar-router.ts +26 -41
  796. package/src/media/gemini-image-service.ts +8 -41
  797. package/src/media/image-credentials.ts +73 -0
  798. package/src/media/image-service.ts +85 -0
  799. package/src/media/openai-image-service.ts +131 -0
  800. package/src/media/types.ts +46 -0
  801. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +4 -28
  802. package/src/memory/__tests__/auto-analysis-guard.test.ts +2 -2
  803. package/src/memory/__tests__/conversation-analyze-job.test.ts +7 -62
  804. package/src/memory/__tests__/conversation-group-migration.test.ts +2 -2
  805. package/src/memory/__tests__/find-analysis-conversation.test.ts +2 -1
  806. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +235 -0
  807. package/src/memory/admin.ts +65 -7
  808. package/src/memory/app-git-service.ts +0 -14
  809. package/src/memory/attachments-store.ts +14 -16
  810. package/src/memory/auto-analysis-enqueue.ts +2 -17
  811. package/src/memory/canonical-guardian-store.ts +2 -1
  812. package/src/memory/channel-verification-sessions.ts +1 -1
  813. package/src/memory/checkpoints.ts +1 -1
  814. package/src/memory/context-search/agent-protocol.ts +424 -0
  815. package/src/memory/context-search/agent-runner.ts +1295 -0
  816. package/src/memory/context-search/format.ts +160 -0
  817. package/src/memory/context-search/limits.ts +106 -0
  818. package/src/memory/context-search/search.ts +387 -0
  819. package/src/memory/context-search/sources/conversations.ts +278 -0
  820. package/src/memory/context-search/sources/memory.ts +90 -0
  821. package/src/memory/context-search/sources/pkb.ts +468 -0
  822. package/src/memory/context-search/sources/workspace.ts +1255 -0
  823. package/src/memory/context-search/types.ts +49 -0
  824. package/src/memory/conversation-analyze-job.ts +3 -24
  825. package/src/memory/conversation-attention-store.ts +1 -1
  826. package/src/memory/conversation-bootstrap.ts +1 -1
  827. package/src/memory/conversation-crud.ts +117 -145
  828. package/src/memory/conversation-directories.ts +1 -11
  829. package/src/memory/conversation-display-order-migration.ts +11 -2
  830. package/src/memory/conversation-group-migration.ts +20 -4
  831. package/src/memory/conversation-key-store.ts +3 -4
  832. package/src/memory/conversation-queries.ts +69 -29
  833. package/src/memory/conversation-starter-validation.ts +88 -0
  834. package/src/memory/conversation-starters-cadence.ts +1 -1
  835. package/src/memory/conversation-title-service.ts +27 -1
  836. package/src/memory/db-init.ts +22 -4
  837. package/src/memory/db-maintenance.ts +1 -1
  838. package/src/memory/delivery-channels.ts +1 -14
  839. package/src/memory/delivery-crud.ts +2 -32
  840. package/src/memory/delivery-status.ts +1 -1
  841. package/src/memory/embedding-gemini.test.ts +44 -5
  842. package/src/memory/embedding-gemini.ts +6 -1
  843. package/src/memory/external-conversation-store.ts +1 -1
  844. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +412 -0
  845. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +225 -0
  846. package/src/memory/graph/bootstrap.test.ts +277 -0
  847. package/src/memory/graph/bootstrap.ts +10 -6
  848. package/src/memory/graph/capability-seed.ts +3 -3
  849. package/src/memory/graph/compaction.ts +1 -1
  850. package/src/memory/graph/consolidation.ts +13 -10
  851. package/src/memory/graph/conversation-graph-memory.ts +151 -1
  852. package/src/memory/graph/decay.ts +1 -1
  853. package/src/memory/graph/extraction.ts +63 -23
  854. package/src/memory/graph/graph-memory-state-store.ts +1 -1
  855. package/src/memory/graph/graph-search.test.ts +95 -2
  856. package/src/memory/graph/graph-search.ts +22 -7
  857. package/src/memory/graph/image-ref-utils.ts +1 -1
  858. package/src/memory/graph/retriever.test.ts +158 -4
  859. package/src/memory/graph/retriever.ts +27 -8
  860. package/src/memory/graph/store.test.ts +2 -1
  861. package/src/memory/graph/store.ts +1 -1
  862. package/src/memory/graph/tool-handlers.ts +73 -247
  863. package/src/memory/graph/tools.ts +35 -53
  864. package/src/memory/group-crud.ts +1 -2
  865. package/src/memory/guardian-action-store.ts +2 -1
  866. package/src/memory/guardian-approvals.ts +1 -1
  867. package/src/memory/guardian-rate-limits.ts +1 -1
  868. package/src/memory/indexer.ts +43 -17
  869. package/src/memory/invite-store.ts +1 -1
  870. package/src/memory/job-handlers/backfill.ts +1 -1
  871. package/src/memory/job-handlers/cleanup.ts +2 -1
  872. package/src/memory/job-handlers/conversation-starters.ts +18 -10
  873. package/src/memory/job-handlers/embedding.test.ts +2 -1
  874. package/src/memory/job-handlers/embedding.ts +1 -1
  875. package/src/memory/job-handlers/index-maintenance.ts +1 -1
  876. package/src/memory/job-handlers/summarization.ts +3 -3
  877. package/src/memory/job-utils.ts +3 -3
  878. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +362 -0
  879. package/src/memory/jobs/embed-concept-page.ts +210 -0
  880. package/src/memory/jobs/embed-pkb-file.test.ts +2 -1
  881. package/src/memory/jobs-store.ts +10 -2
  882. package/src/memory/jobs-worker.ts +58 -5
  883. package/src/memory/lifecycle-events-store.ts +1 -1
  884. package/src/memory/llm-request-log-store.ts +1 -1
  885. package/src/memory/llm-usage-store.ts +1 -1
  886. package/src/memory/media-store.ts +1 -1
  887. package/src/memory/memory-recall-log-store.ts +1 -1
  888. package/src/memory/migrations/038-actor-token-records.ts +3 -0
  889. package/src/memory/migrations/039-actor-refresh-token-records.ts +3 -0
  890. package/src/memory/migrations/041-approval-prompt-ts-tracker.ts +26 -0
  891. package/src/memory/migrations/149-oauth-tables.ts +1 -0
  892. package/src/memory/migrations/223-schedule-script-column.ts +11 -0
  893. package/src/memory/migrations/224-oauth-providers-managed-service-is-paid.ts +24 -0
  894. package/src/memory/migrations/225-oauth-providers-available-scopes.ts +13 -0
  895. package/src/memory/migrations/226-schedule-wake-conversation-id.ts +11 -0
  896. package/src/memory/migrations/227-add-conversation-inference-profile.ts +18 -0
  897. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +27 -0
  898. package/src/memory/migrations/229-delete-private-conversations.test.ts +1087 -0
  899. package/src/memory/migrations/229-delete-private-conversations.ts +210 -0
  900. package/src/memory/migrations/230-acp-session-history.ts +41 -0
  901. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +128 -0
  902. package/src/memory/migrations/232-activation-state.ts +38 -0
  903. package/src/memory/migrations/index.ts +14 -0
  904. package/src/memory/migrations/registry.ts +7 -0
  905. package/src/memory/pkb/pkb-index.test.ts +5 -5
  906. package/src/memory/pkb/pkb-reconcile.test.ts +5 -5
  907. package/src/memory/pkb/pkb-search.test.ts +148 -7
  908. package/src/memory/pkb/pkb-search.ts +65 -30
  909. package/src/memory/published-pages-store.ts +1 -1
  910. package/src/memory/qdrant-client.test.ts +60 -0
  911. package/src/memory/qdrant-client.ts +25 -0
  912. package/src/memory/schema/acp.ts +30 -0
  913. package/src/memory/schema/conversations.ts +1 -1
  914. package/src/memory/schema/index.ts +1 -0
  915. package/src/memory/schema/infrastructure.ts +2 -32
  916. package/src/memory/schema/memory-graph.ts +36 -14
  917. package/src/memory/schema/oauth.ts +4 -1
  918. package/src/memory/scoped-approval-grants.ts +2 -1
  919. package/src/memory/search/semantic.ts +2 -2
  920. package/src/memory/shared-app-links-store.ts +2 -1
  921. package/src/memory/tool-usage-store.ts +1 -1
  922. package/src/memory/trace-event-store.ts +2 -1
  923. package/src/memory/turn-events-store.ts +1 -1
  924. package/src/memory/v2/__tests__/activation-store.test.ts +202 -0
  925. package/src/memory/v2/__tests__/activation.test.ts +956 -0
  926. package/src/memory/v2/__tests__/backfill-jobs.test.ts +610 -0
  927. package/src/memory/v2/__tests__/consolidation-job.test.ts +395 -0
  928. package/src/memory/v2/__tests__/edges.test.ts +435 -0
  929. package/src/memory/v2/__tests__/injection.test.ts +792 -0
  930. package/src/memory/v2/__tests__/migration.test.ts +812 -0
  931. package/src/memory/v2/__tests__/page-store.test.ts +334 -0
  932. package/src/memory/v2/__tests__/qdrant.test.ts +438 -0
  933. package/src/memory/v2/__tests__/sim.test.ts +549 -0
  934. package/src/memory/v2/__tests__/skill-content.test.ts +85 -0
  935. package/src/memory/v2/__tests__/skill-qdrant.test.ts +657 -0
  936. package/src/memory/v2/__tests__/skill-store.test.ts +351 -0
  937. package/src/memory/v2/__tests__/sweep-job.test.ts +441 -0
  938. package/src/memory/v2/activation-store.ts +109 -0
  939. package/src/memory/v2/activation.ts +490 -0
  940. package/src/memory/v2/backfill-jobs.ts +442 -0
  941. package/src/memory/v2/consolidation-job.ts +304 -0
  942. package/src/memory/v2/edges.ts +217 -0
  943. package/src/memory/v2/injection.ts +307 -0
  944. package/src/memory/v2/migration.ts +654 -0
  945. package/src/memory/v2/now-text.ts +38 -0
  946. package/src/memory/v2/page-store.ts +245 -0
  947. package/src/memory/v2/prompts/consolidation.ts +185 -0
  948. package/src/memory/v2/prompts/sweep.ts +56 -0
  949. package/src/memory/v2/qdrant.ts +342 -0
  950. package/src/memory/v2/sim.ts +206 -0
  951. package/src/memory/v2/skill-content.ts +42 -0
  952. package/src/memory/v2/skill-qdrant.ts +395 -0
  953. package/src/memory/v2/skill-store.ts +128 -0
  954. package/src/memory/v2/sweep-job.ts +298 -0
  955. package/src/memory/v2/types.ts +116 -0
  956. package/src/memory/validation.ts +1 -1
  957. package/src/messaging/providers/index.ts +262 -0
  958. package/src/messaging/providers/slack/api.ts +242 -0
  959. package/src/messaging/providers/slack/message-metadata.ts +1 -1
  960. package/src/messaging/providers/slack/render-transcript.test.ts +77 -29
  961. package/src/messaging/providers/slack/render-transcript.ts +58 -0
  962. package/src/messaging/providers/slack/send.ts +383 -0
  963. package/src/messaging/providers/telegram-bot/adapter.ts +4 -42
  964. package/src/messaging/providers/telegram-bot/api.ts +253 -0
  965. package/src/messaging/providers/telegram-bot/client.ts +17 -58
  966. package/src/messaging/providers/telegram-bot/send.ts +232 -0
  967. package/src/messaging/providers/whatsapp/adapter.ts +4 -36
  968. package/src/messaging/providers/whatsapp/api.ts +319 -0
  969. package/src/messaging/providers/whatsapp/client.ts +4 -48
  970. package/src/messaging/providers/whatsapp/send.ts +209 -0
  971. package/src/notifications/adapters/slack.ts +5 -23
  972. package/src/notifications/adapters/telegram.ts +8 -29
  973. package/src/notifications/conversation-candidates.ts +1 -1
  974. package/src/notifications/conversation-pairing.ts +78 -19
  975. package/src/notifications/conversation-seed-composer.ts +12 -6
  976. package/src/notifications/copy-composer.ts +1 -6
  977. package/src/notifications/decision-engine.ts +1 -1
  978. package/src/notifications/decisions-store.ts +1 -1
  979. package/src/notifications/deliveries-store.ts +2 -1
  980. package/src/notifications/deterministic-checks.ts +1 -1
  981. package/src/notifications/emit-signal.ts +1 -1
  982. package/src/notifications/events-store.ts +1 -13
  983. package/src/notifications/preferences-store.ts +1 -1
  984. package/src/notifications/signal.ts +1 -11
  985. package/src/oauth/AGENTS.md +1 -1
  986. package/src/oauth/__tests__/identity-verifier.test.ts +2 -1
  987. package/src/oauth/connect-orchestrator.ts +8 -34
  988. package/src/oauth/connect-types.ts +6 -10
  989. package/src/oauth/connection-resolver.ts +11 -2
  990. package/src/oauth/manual-token-connection.ts +23 -0
  991. package/src/oauth/oauth-store.ts +32 -15
  992. package/src/oauth/provider-serializer.ts +6 -1
  993. package/src/oauth/seed-providers.ts +56 -108
  994. package/src/outbound-proxy/http-forwarder.ts +9 -0
  995. package/src/outbound-proxy/index.ts +0 -1
  996. package/src/permissions/approval-policy.test.ts +398 -106
  997. package/src/permissions/approval-policy.ts +134 -108
  998. package/src/permissions/checker.test.ts +632 -0
  999. package/src/permissions/checker.ts +280 -345
  1000. package/src/permissions/gateway-threshold-reader.ts +177 -0
  1001. package/src/permissions/ipc-risk-types.ts +95 -0
  1002. package/src/permissions/prompter.ts +8 -9
  1003. package/src/permissions/risk-types.ts +24 -153
  1004. package/src/permissions/types.ts +19 -47
  1005. package/src/permissions/workspace-policy.ts +10 -7
  1006. package/src/playbooks/playbook-compiler.ts +1 -1
  1007. package/src/plugins/defaults/circuit-breaker.ts +146 -0
  1008. package/src/plugins/defaults/compaction.ts +145 -0
  1009. package/src/plugins/defaults/empty-response.ts +126 -0
  1010. package/src/plugins/defaults/history-repair.ts +85 -0
  1011. package/src/plugins/defaults/index.ts +116 -0
  1012. package/src/plugins/defaults/injectors.ts +488 -0
  1013. package/src/plugins/defaults/llm-call.ts +79 -0
  1014. package/src/plugins/defaults/memory-retrieval.ts +221 -0
  1015. package/src/plugins/defaults/overflow-reduce.ts +185 -0
  1016. package/src/plugins/defaults/persistence.ts +129 -0
  1017. package/src/plugins/defaults/title-generate.ts +95 -0
  1018. package/src/plugins/defaults/token-estimate.ts +103 -0
  1019. package/src/plugins/defaults/tool-error.ts +126 -0
  1020. package/src/plugins/defaults/tool-execute.ts +89 -0
  1021. package/src/plugins/defaults/tool-result-truncate.ts +88 -0
  1022. package/src/plugins/pipeline.ts +316 -0
  1023. package/src/plugins/plugin-skill-contributions.ts +292 -0
  1024. package/src/plugins/registry.ts +301 -0
  1025. package/src/plugins/types.ts +1133 -0
  1026. package/src/plugins/user-loader.ts +203 -0
  1027. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +197 -0
  1028. package/src/prompts/persona-resolver.ts +2 -4
  1029. package/src/prompts/system-prompt.ts +39 -0
  1030. package/src/prompts/templates/BOOTSTRAP.md +27 -77
  1031. package/src/prompts/templates/SOUL.md +3 -1
  1032. package/src/providers/__tests__/provider-env-vars.test.ts +0 -21
  1033. package/src/providers/__tests__/retry-callsite.test.ts +3 -6
  1034. package/src/providers/anthropic/client.ts +71 -19
  1035. package/src/providers/call-site-routing.ts +7 -3
  1036. package/src/providers/fireworks/client.ts +3 -0
  1037. package/src/providers/gemini/client.ts +96 -22
  1038. package/src/providers/managed-proxy/context.ts +0 -12
  1039. package/src/providers/model-catalog.ts +123 -25
  1040. package/src/providers/model-intents.ts +6 -7
  1041. package/src/providers/openai/chat-completions-provider.ts +37 -7
  1042. package/src/providers/openai/responses-provider.ts +39 -4
  1043. package/src/providers/openrouter/client.ts +9 -6
  1044. package/src/providers/provider-env-vars.ts +4 -12
  1045. package/src/providers/provider-send-message.ts +16 -11
  1046. package/src/providers/registry.ts +1 -1
  1047. package/src/providers/retry.ts +52 -23
  1048. package/src/providers/speech-to-text/deepgram-realtime.test.ts +61 -0
  1049. package/src/providers/speech-to-text/deepgram-realtime.ts +57 -0
  1050. package/src/providers/speech-to-text/openai-whisper-stream.ts +1 -1
  1051. package/src/providers/speech-to-text/openai-whisper.ts +3 -6
  1052. package/src/providers/speech-to-text/provider-catalog.ts +75 -0
  1053. package/src/providers/speech-to-text/xai-realtime.test.ts +72 -4
  1054. package/src/providers/speech-to-text/xai-realtime.ts +39 -14
  1055. package/src/providers/speech-to-text/xai.ts +5 -5
  1056. package/src/providers/thinking-config.ts +34 -0
  1057. package/src/providers/types.ts +22 -10
  1058. package/src/runtime/AGENTS.md +27 -17
  1059. package/src/runtime/__tests__/agent-wake.test.ts +33 -9
  1060. package/src/runtime/__tests__/client-registry.test.ts +271 -0
  1061. package/src/runtime/__tests__/interactive-ui.test.ts +157 -246
  1062. package/src/runtime/access-request-helper.ts +9 -20
  1063. package/src/runtime/actor-trust-resolver.ts +2 -2
  1064. package/src/runtime/agent-wake.ts +174 -68
  1065. package/src/runtime/approval-conversation-turn.ts +2 -15
  1066. package/src/runtime/approval-message-composer.ts +11 -60
  1067. package/src/runtime/assistant-event.ts +18 -66
  1068. package/src/runtime/auth/__tests__/guard-tests.test.ts +6 -30
  1069. package/src/runtime/auth/__tests__/middleware.test.ts +10 -10
  1070. package/src/runtime/auth/__tests__/route-policy.test.ts +0 -8
  1071. package/src/runtime/auth/context.ts +9 -0
  1072. package/src/runtime/auth/middleware.ts +4 -4
  1073. package/src/runtime/auth/route-policy.ts +195 -4
  1074. package/src/runtime/auth/token-service.ts +1 -100
  1075. package/src/runtime/capability-tokens.ts +89 -313
  1076. package/src/runtime/channel-approval-types.ts +1 -6
  1077. package/src/runtime/channel-approvals.ts +7 -79
  1078. package/src/runtime/channel-readiness-service.ts +2 -2
  1079. package/src/runtime/channel-reply-delivery.ts +2 -8
  1080. package/src/runtime/channel-retry-sweep.ts +20 -17
  1081. package/src/runtime/client-registry.ts +254 -0
  1082. package/src/runtime/confirmation-request-guardian-bridge.ts +2 -7
  1083. package/src/runtime/gateway-client.ts +37 -378
  1084. package/src/runtime/guardian-action-grant-minter.ts +2 -3
  1085. package/src/runtime/guardian-action-message-composer.ts +11 -52
  1086. package/src/runtime/guardian-action-service.ts +19 -7
  1087. package/src/runtime/guardian-decision-types.ts +4 -65
  1088. package/src/runtime/guardian-reply-router.ts +10 -19
  1089. package/src/runtime/guardian-vellum-migration.ts +5 -64
  1090. package/src/runtime/http-errors.ts +3 -0
  1091. package/src/runtime/http-router.ts +50 -7
  1092. package/src/runtime/http-server.ts +345 -1041
  1093. package/src/runtime/http-types.ts +15 -100
  1094. package/src/runtime/interactive-ui-types.ts +145 -0
  1095. package/src/runtime/interactive-ui.ts +38 -196
  1096. package/src/runtime/invite-redemption-service.ts +1 -1
  1097. package/src/runtime/invite-redemption-templates.ts +1 -1
  1098. package/src/runtime/local-actor-identity.ts +13 -43
  1099. package/src/runtime/message-composer-types.ts +134 -0
  1100. package/src/runtime/middleware/rate-limiter.ts +1 -1
  1101. package/src/runtime/middleware/request-logger.ts +5 -2
  1102. package/src/runtime/migrations/__tests__/job-registry.test.ts +346 -0
  1103. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +16 -0
  1104. package/src/runtime/migrations/job-registry.ts +281 -0
  1105. package/src/runtime/migrations/vbundle-builder.ts +4 -26
  1106. package/src/runtime/migrations/vbundle-importer.ts +1 -1
  1107. package/src/runtime/migrations/vbundle-streaming-importer.ts +0 -13
  1108. package/src/runtime/migrations/vbundle-tar-stream.ts +11 -3
  1109. package/src/runtime/nl-approval-parser.ts +16 -21
  1110. package/src/runtime/pending-interactions.ts +29 -12
  1111. package/src/runtime/routes/__tests__/acp-routes.test.ts +395 -0
  1112. package/src/runtime/routes/__tests__/backup-routes.test.ts +204 -320
  1113. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +72 -4
  1114. package/src/runtime/routes/__tests__/stt-routes.test.ts +182 -223
  1115. package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +230 -0
  1116. package/src/{ipc/__tests__/task-ipc.test.ts → runtime/routes/__tests__/task-routes.test.ts} +116 -96
  1117. package/src/runtime/routes/__tests__/tts-routes.test.ts +185 -289
  1118. package/src/runtime/routes/access-request-decision.ts +25 -50
  1119. package/src/runtime/routes/acp-routes.test.ts +371 -0
  1120. package/src/runtime/routes/acp-routes.ts +392 -166
  1121. package/src/runtime/routes/app-management-routes.ts +464 -660
  1122. package/src/runtime/routes/app-routes.ts +192 -177
  1123. package/src/runtime/routes/approval-prompt-ts-tracker.ts +51 -31
  1124. package/src/runtime/routes/approval-routes.ts +133 -434
  1125. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +24 -84
  1126. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +3 -10
  1127. package/src/runtime/routes/attachment-routes.ts +409 -253
  1128. package/src/runtime/routes/audio-routes.ts +51 -18
  1129. package/src/runtime/routes/avatar-routes.ts +82 -75
  1130. package/src/runtime/routes/background-tool-routes.ts +94 -0
  1131. package/src/runtime/routes/backup-routes.ts +154 -336
  1132. package/src/runtime/routes/brain-graph-routes.ts +83 -110
  1133. package/src/runtime/routes/browser-routes.ts +141 -0
  1134. package/src/runtime/routes/btw-routes.ts +62 -106
  1135. package/src/runtime/routes/cache-routes.ts +96 -0
  1136. package/src/runtime/routes/call-routes.ts +208 -247
  1137. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +1 -1
  1138. package/src/runtime/routes/channel-delivery-routes.ts +25 -27
  1139. package/src/runtime/routes/channel-readiness-routes.ts +83 -120
  1140. package/src/runtime/routes/channel-route-definitions.ts +62 -0
  1141. package/src/runtime/routes/channel-route-shared.ts +14 -18
  1142. package/src/runtime/routes/channel-verification-routes.ts +207 -187
  1143. package/src/runtime/routes/client-routes.ts +48 -0
  1144. package/src/runtime/routes/contact-routes.ts +533 -407
  1145. package/src/runtime/routes/conversation-analysis-routes.ts +48 -49
  1146. package/src/runtime/routes/conversation-attention-routes.ts +55 -67
  1147. package/src/runtime/routes/conversation-list-routes.ts +265 -0
  1148. package/src/runtime/routes/conversation-management-routes.ts +626 -715
  1149. package/src/runtime/routes/conversation-query-routes.ts +510 -460
  1150. package/src/runtime/routes/conversation-routes.ts +652 -457
  1151. package/src/runtime/routes/conversation-starter-routes.ts +121 -71
  1152. package/src/runtime/routes/credential-prompt-routes.ts +124 -0
  1153. package/src/runtime/routes/debug-routes.ts +34 -39
  1154. package/src/runtime/routes/defer-routes.ts +230 -0
  1155. package/src/runtime/routes/diagnostics-routes.ts +79 -70
  1156. package/src/runtime/routes/documents-routes.ts +117 -106
  1157. package/src/runtime/routes/errors.ts +132 -0
  1158. package/src/runtime/routes/events-routes.ts +97 -58
  1159. package/src/runtime/routes/filing-routes.ts +65 -78
  1160. package/src/runtime/routes/global-search-routes.ts +51 -57
  1161. package/src/runtime/routes/group-routes.ts +199 -181
  1162. package/src/runtime/routes/guardian-action-routes.ts +103 -169
  1163. package/src/runtime/routes/guardian-approval-interception.ts +27 -58
  1164. package/src/runtime/routes/guardian-approval-prompt.ts +10 -21
  1165. package/src/runtime/routes/guardian-approval-reply-helpers.ts +2 -6
  1166. package/src/runtime/routes/guardian-expiry-sweep.ts +19 -36
  1167. package/src/runtime/routes/heartbeat-routes.ts +194 -209
  1168. package/src/runtime/routes/home-feed-routes.ts +85 -187
  1169. package/src/runtime/routes/home-state-routes.ts +27 -24
  1170. package/src/runtime/routes/host-bash-routes.ts +42 -52
  1171. package/src/runtime/routes/host-browser-routes.ts +38 -69
  1172. package/src/runtime/routes/host-cu-routes.ts +74 -70
  1173. package/src/runtime/routes/host-file-routes.ts +50 -60
  1174. package/src/runtime/routes/host-transfer-routes.ts +220 -0
  1175. package/src/runtime/routes/http-adapter.ts +172 -0
  1176. package/src/runtime/routes/identity-routes.ts +83 -79
  1177. package/src/runtime/routes/inbound-conversation.ts +11 -18
  1178. package/src/runtime/routes/inbound-message-handler.ts +162 -123
  1179. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +79 -138
  1180. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +2 -3
  1181. package/src/runtime/routes/inbound-stages/background-dispatch.ts +54 -90
  1182. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +25 -50
  1183. package/src/runtime/routes/inbound-stages/edit-intercept.ts +7 -7
  1184. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +5 -5
  1185. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +5 -6
  1186. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -24
  1187. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -10
  1188. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -4
  1189. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +3 -3
  1190. package/src/runtime/routes/inbound-stages/verification-intercept.ts +19 -26
  1191. package/src/runtime/routes/index.ts +197 -0
  1192. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +25 -32
  1193. package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +22 -31
  1194. package/src/runtime/routes/integrations/slack/channel.ts +69 -66
  1195. package/src/runtime/routes/integrations/slack/share.ts +49 -58
  1196. package/src/runtime/routes/integrations/telegram.ts +91 -74
  1197. package/src/runtime/routes/integrations/twilio.ts +163 -240
  1198. package/src/runtime/routes/integrations/vercel.ts +57 -54
  1199. package/src/runtime/routes/interface-routes.ts +43 -0
  1200. package/src/runtime/routes/internal-oauth-routes.ts +56 -0
  1201. package/src/runtime/routes/internal-twilio-routes.ts +46 -0
  1202. package/src/runtime/routes/llm-context-normalization.ts +4 -2
  1203. package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
  1204. package/src/runtime/routes/log-export-routes.ts +90 -100
  1205. package/src/runtime/routes/memory-item-routes.test.ts +153 -175
  1206. package/src/runtime/routes/memory-item-routes.ts +243 -323
  1207. package/src/runtime/routes/memory-v2-routes.ts +193 -0
  1208. package/src/runtime/routes/migration-rollback-routes.ts +167 -212
  1209. package/src/runtime/routes/migration-routes.ts +877 -377
  1210. package/src/runtime/routes/notification-routes.ts +199 -70
  1211. package/src/runtime/routes/oauth-apps.ts +254 -251
  1212. package/src/runtime/routes/oauth-providers.ts +66 -57
  1213. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +224 -0
  1214. package/src/runtime/routes/playground/__tests__/guard.test.ts +60 -0
  1215. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +250 -0
  1216. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +195 -0
  1217. package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +159 -0
  1218. package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +207 -0
  1219. package/src/runtime/routes/playground/__tests__/state.test.ts +175 -0
  1220. package/src/runtime/routes/playground/conversation-not-found.ts +27 -0
  1221. package/src/runtime/routes/playground/force-compact.ts +60 -0
  1222. package/src/runtime/routes/playground/guard.ts +36 -0
  1223. package/src/runtime/routes/playground/helpers.ts +103 -0
  1224. package/src/runtime/routes/playground/index.ts +18 -0
  1225. package/src/runtime/routes/playground/inject-failures.ts +143 -0
  1226. package/src/runtime/routes/playground/reset-circuit.ts +89 -0
  1227. package/src/runtime/routes/playground/seed-conversation.ts +113 -0
  1228. package/src/runtime/routes/playground/seeded-conversations.ts +74 -0
  1229. package/src/runtime/routes/playground/state.ts +77 -0
  1230. package/src/runtime/routes/profiler-routes.ts +132 -167
  1231. package/src/runtime/routes/ps-routes.ts +120 -0
  1232. package/src/runtime/routes/recording-routes.ts +197 -258
  1233. package/src/runtime/routes/rename-conversation-routes.ts +89 -0
  1234. package/src/runtime/routes/schedule-routes.ts +284 -207
  1235. package/src/runtime/routes/secret-routes.ts +219 -265
  1236. package/src/runtime/routes/secrets-deps.ts +24 -0
  1237. package/src/runtime/routes/settings-routes.ts +361 -441
  1238. package/src/runtime/routes/skills-routes.ts +434 -469
  1239. package/src/runtime/routes/stt-routes.ts +196 -206
  1240. package/src/runtime/routes/subagents-routes.ts +125 -141
  1241. package/src/runtime/routes/suggest-trust-rule-routes.ts +244 -0
  1242. package/src/runtime/routes/surface-action-routes.ts +135 -190
  1243. package/src/runtime/routes/surface-content-routes.ts +84 -118
  1244. package/src/runtime/routes/task-routes.ts +354 -0
  1245. package/src/runtime/routes/telemetry-routes.ts +33 -49
  1246. package/src/runtime/routes/trace-event-routes.ts +55 -74
  1247. package/src/runtime/routes/trust-rules-routes.ts +147 -239
  1248. package/src/runtime/routes/tts-routes.ts +187 -169
  1249. package/src/runtime/routes/types.ts +139 -0
  1250. package/src/{ipc/routes/ui-request.ts → runtime/routes/ui-request-routes.ts} +23 -17
  1251. package/src/runtime/routes/upgrade-broadcast-routes.ts +156 -197
  1252. package/src/runtime/routes/usage-routes.ts +143 -169
  1253. package/src/runtime/routes/user-routes.ts +102 -18
  1254. package/src/runtime/routes/wake-conversation-routes.ts +49 -0
  1255. package/src/{ipc/routes/watcher.ts → runtime/routes/watcher-routes.ts} +84 -39
  1256. package/src/runtime/routes/wipe-conversation-routes.ts +89 -0
  1257. package/src/runtime/routes/work-items-routes.test.ts +10 -20
  1258. package/src/runtime/routes/work-items-routes.ts +418 -433
  1259. package/src/runtime/routes/workspace-commit-routes.ts +30 -61
  1260. package/src/runtime/routes/workspace-routes.test.ts +254 -381
  1261. package/src/runtime/routes/workspace-routes.ts +238 -246
  1262. package/src/runtime/runtime-mode.ts +8 -1
  1263. package/src/runtime/services/__tests__/analyze-conversation.test.ts +80 -118
  1264. package/src/runtime/services/analyze-conversation.ts +14 -41
  1265. package/src/runtime/services/conversation-serializer.ts +181 -0
  1266. package/src/runtime/skill-route-registry.ts +75 -15
  1267. package/src/runtime/trust-context-resolver.ts +3 -2
  1268. package/src/runtime/verification-outbound-actions.ts +13 -49
  1269. package/src/schedule/run-script.ts +68 -0
  1270. package/src/schedule/schedule-store.ts +70 -2
  1271. package/src/schedule/scheduler.ts +149 -8
  1272. package/src/security/ces-credential-client.ts +32 -169
  1273. package/src/security/ces-rpc-credential-backend.ts +1 -1
  1274. package/src/security/credential-backend.ts +6 -6
  1275. package/src/security/oauth-completion-page.ts +1 -1
  1276. package/src/security/oauth2.ts +3 -6
  1277. package/src/sequence/analytics.ts +1 -1
  1278. package/src/sequence/guardrails.ts +3 -3
  1279. package/src/sequence/store.ts +2 -1
  1280. package/src/signals/bash.ts +1 -1
  1281. package/src/signals/event-stream.ts +1 -1
  1282. package/src/skills/catalog-cache.ts +19 -5
  1283. package/src/skills/catalog-files.ts +0 -5
  1284. package/src/skills/catalog-install.ts +28 -18
  1285. package/src/skills/category-inference.ts +0 -11
  1286. package/src/skills/clawhub.ts +2 -2
  1287. package/src/skills/managed-store.ts +2 -2
  1288. package/src/skills/remote-skill-policy.ts +6 -7
  1289. package/src/subagent/index.ts +2 -6
  1290. package/src/subagent/manager.ts +27 -23
  1291. package/src/subagent/types.ts +9 -0
  1292. package/src/tasks/SPEC.md +2 -2
  1293. package/src/tasks/task-compiler.ts +1 -1
  1294. package/src/tasks/task-runner.ts +2 -22
  1295. package/src/tasks/task-store.ts +1 -1
  1296. package/src/tools/acp/list-agents.test.ts +115 -0
  1297. package/src/tools/acp/list-agents.ts +31 -0
  1298. package/src/tools/acp/spawn.test.ts +379 -0
  1299. package/src/tools/acp/spawn.ts +142 -62
  1300. package/src/tools/acp/steer.test.ts +101 -0
  1301. package/src/tools/acp/steer.ts +38 -0
  1302. package/src/tools/background-tool-registry.ts +98 -0
  1303. package/src/tools/browser/__tests__/browser-status.test.ts +189 -0
  1304. package/src/tools/browser/browser-execution.ts +122 -26
  1305. package/src/tools/browser/browser-manager.ts +1 -8
  1306. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +230 -0
  1307. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +146 -3
  1308. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +1 -1
  1309. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +3 -1
  1310. package/src/tools/browser/cdp-client/extension-cdp-client.ts +54 -3
  1311. package/src/tools/browser/cdp-client/factory.ts +15 -4
  1312. package/src/tools/browser/cdp-client/types.ts +4 -1
  1313. package/src/tools/computer-use/definitions.ts +1 -1
  1314. package/src/tools/credential-execution/make-authenticated-request.ts +2 -2
  1315. package/src/tools/credential-execution/manage-secure-command-tool.ts +1 -1
  1316. package/src/tools/credential-execution/run-authenticated-command.ts +2 -2
  1317. package/src/tools/credentials/broker-types.ts +2 -1
  1318. package/src/tools/document/editor-template.ts +1 -1
  1319. package/src/tools/execution-timeout.ts +1 -1
  1320. package/src/tools/executor.ts +123 -76
  1321. package/src/tools/host-filesystem/transfer.test.ts +268 -0
  1322. package/src/tools/host-filesystem/transfer.ts +234 -0
  1323. package/src/tools/host-terminal/host-shell.ts +189 -11
  1324. package/src/tools/mcp/mcp-tool-factory.ts +1 -1
  1325. package/src/tools/memory/register.test.ts +161 -1
  1326. package/src/tools/memory/register.ts +19 -34
  1327. package/src/tools/network/script-proxy/session-manager.ts +37 -1
  1328. package/src/tools/permission-checker.ts +103 -255
  1329. package/src/tools/policy-context.ts +5 -8
  1330. package/src/tools/registry.ts +156 -4
  1331. package/src/tools/schedule/create.ts +23 -8
  1332. package/src/tools/schedule/update.ts +3 -1
  1333. package/src/tools/secret-detection-handler.ts +13 -154
  1334. package/src/tools/shared/shell-output.ts +4 -1
  1335. package/src/tools/side-effects.ts +2 -2
  1336. package/src/tools/skills/execute.ts +1 -1
  1337. package/src/tools/subagent/spawn.ts +35 -11
  1338. package/src/tools/system/avatar-generator.ts +6 -2
  1339. package/src/tools/terminal/safe-env.ts +9 -1
  1340. package/src/tools/terminal/shell.ts +161 -31
  1341. package/src/tools/tool-approval-handler.ts +4 -70
  1342. package/src/tools/tool-input-summary.ts +10 -0
  1343. package/src/tools/types.ts +157 -151
  1344. package/src/tools/ui-surface/definitions.ts +2 -2
  1345. package/src/util/debounce.ts +0 -21
  1346. package/src/util/errors.ts +0 -8
  1347. package/src/util/log-redact.ts +0 -1
  1348. package/src/util/platform.ts +85 -119
  1349. package/src/util/pricing.ts +135 -9
  1350. package/src/watcher/engine.ts +42 -20
  1351. package/src/watcher/watcher-store.ts +2 -1
  1352. package/src/work-items/work-item-store.ts +1 -1
  1353. package/src/workspace/git-service.ts +1 -6
  1354. package/src/workspace/migrations/006-services-config.ts +11 -4
  1355. package/src/workspace/migrations/017-seed-persona-dirs.ts +1 -1
  1356. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +1 -1
  1357. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +2 -3
  1358. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +1 -1
  1359. package/src/workspace/migrations/031-drop-user-md.ts +1 -1
  1360. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +3 -4
  1361. package/src/workspace/migrations/045-release-notes-meet-avatar.ts +3 -4
  1362. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +108 -0
  1363. package/src/workspace/migrations/047-remove-watch-callsites.ts +54 -0
  1364. package/src/workspace/migrations/048-remove-workspace-hooks.ts +81 -0
  1365. package/src/workspace/migrations/049-release-notes-default-sonnet.ts +80 -0
  1366. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +86 -0
  1367. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +128 -0
  1368. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +150 -0
  1369. package/src/workspace/migrations/053-release-notes-acp-codex.ts +107 -0
  1370. package/src/workspace/migrations/054-seed-recall-callsite.ts +102 -0
  1371. package/src/workspace/migrations/055-release-notes-agentic-recall.ts +63 -0
  1372. package/src/workspace/migrations/056-release-notes-inference-profile-reordering.ts +65 -0
  1373. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +98 -0
  1374. package/src/workspace/migrations/058-release-notes-acp-sessions-ui.ts +71 -0
  1375. package/src/workspace/migrations/059-move-pid-to-workspace.ts +53 -0
  1376. package/src/workspace/migrations/060-memory-v2-init.ts +53 -0
  1377. package/src/workspace/migrations/rebuild-conversation-disk-view.ts +1 -1
  1378. package/src/workspace/migrations/registry.ts +30 -0
  1379. package/src/workspace/migrations/runner.ts +2 -2
  1380. package/src/workspace/provider-commit-message-generator.ts +1 -1
  1381. package/tsconfig.json +1 -1
  1382. package/hook-templates/debug-prompt-logger/hook.json +0 -7
  1383. package/hook-templates/debug-prompt-logger/run.sh +0 -66
  1384. package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +0 -471
  1385. package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +0 -436
  1386. package/src/__tests__/cli-command-risk-guard.test.ts +0 -368
  1387. package/src/__tests__/compaction-circuit-breaker.test.ts +0 -336
  1388. package/src/__tests__/config-watcher-feature-flags.test.ts +0 -211
  1389. package/src/__tests__/context-overflow-approval.test.ts +0 -156
  1390. package/src/__tests__/conversation-approval-overrides.test.ts +0 -207
  1391. package/src/__tests__/conversation-host-access-routes.test.ts +0 -229
  1392. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +0 -226
  1393. package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +0 -167
  1394. package/src/__tests__/ephemeral-permissions.test.ts +0 -474
  1395. package/src/__tests__/extension-id-sync-guard.test.ts +0 -241
  1396. package/src/__tests__/hooks-blocking.test.ts +0 -178
  1397. package/src/__tests__/hooks-cli.test.ts +0 -182
  1398. package/src/__tests__/hooks-config.test.ts +0 -108
  1399. package/src/__tests__/hooks-discovery.test.ts +0 -211
  1400. package/src/__tests__/hooks-integration.test.ts +0 -196
  1401. package/src/__tests__/hooks-manager.test.ts +0 -226
  1402. package/src/__tests__/hooks-runner.test.ts +0 -175
  1403. package/src/__tests__/hooks-settings.test.ts +0 -160
  1404. package/src/__tests__/hooks-templates.test.ts +0 -169
  1405. package/src/__tests__/hooks-ts-runner.test.ts +0 -170
  1406. package/src/__tests__/hooks-watch.test.ts +0 -112
  1407. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +0 -374
  1408. package/src/__tests__/native-host-marker-sync-guard.test.ts +0 -157
  1409. package/src/__tests__/notification-schedule-dedup.test.ts +0 -213
  1410. package/src/__tests__/oauth-scope-policy.test.ts +0 -180
  1411. package/src/__tests__/pairing-concurrent.test.ts +0 -84
  1412. package/src/__tests__/pairing-routes.test.ts +0 -181
  1413. package/src/__tests__/parser.test.ts +0 -595
  1414. package/src/__tests__/permission-checker-host-gate.test.ts +0 -512
  1415. package/src/__tests__/permission-controls-v2-flag.test.ts +0 -55
  1416. package/src/__tests__/permission-mode.test.ts +0 -89
  1417. package/src/__tests__/provider-env-vars-scope.test.ts +0 -52
  1418. package/src/__tests__/risk-classifier-parity.test.ts +0 -230
  1419. package/src/__tests__/send-notification-tool.test.ts +0 -83
  1420. package/src/__tests__/shell-identity.test.ts +0 -370
  1421. package/src/__tests__/shell-parser-fuzz.test.ts +0 -629
  1422. package/src/__tests__/shell-parser-property.test.ts +0 -936
  1423. package/src/__tests__/starter-bundle.test.ts +0 -173
  1424. package/src/__tests__/stt-catalog-parity.test.ts +0 -282
  1425. package/src/__tests__/task-runner.test.ts +0 -224
  1426. package/src/__tests__/tool-executor-shell-integration.test.ts +0 -357
  1427. package/src/__tests__/trust-store-pattern-matches.test.ts +0 -29
  1428. package/src/__tests__/trust-store.test.ts +0 -2013
  1429. package/src/__tests__/v2-consent-policy.test.ts +0 -103
  1430. package/src/browser/identifiers.ts +0 -51
  1431. package/src/cli/commands/shotgun.ts +0 -266
  1432. package/src/cli/db.ts +0 -1
  1433. package/src/config/bundled-skills/conversations/SKILL.md +0 -20
  1434. package/src/config/bundled-skills/conversations/TOOLS.json +0 -23
  1435. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +0 -88
  1436. package/src/config/bundled-skills/heartbeat/SKILL.md +0 -43
  1437. package/src/config/bundled-skills/notifications/SKILL.md +0 -40
  1438. package/src/config/bundled-skills/notifications/TOOLS.json +0 -80
  1439. package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -152
  1440. package/src/config/bundled-skills/notifications/tools/shared.ts +0 -13
  1441. package/src/config/bundled-skills/screen-watch/SKILL.md +0 -27
  1442. package/src/config/bundled-skills/screen-watch/TOOLS.json +0 -35
  1443. package/src/config/bundled-skills/settings/tools/avatar-get.ts +0 -40
  1444. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +0 -64
  1445. package/src/config/bundled-skills/settings/tools/avatar-update.ts +0 -88
  1446. package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -84
  1447. package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +0 -127
  1448. package/src/daemon/approved-devices-store.ts +0 -110
  1449. package/src/daemon/context-overflow-approval.ts +0 -52
  1450. package/src/daemon/external-skills-bootstrap.ts +0 -41
  1451. package/src/daemon/message-types/trust.ts +0 -71
  1452. package/src/daemon/pairing-store.ts +0 -229
  1453. package/src/daemon/watch-handler.ts +0 -399
  1454. package/src/hooks/cli.ts +0 -253
  1455. package/src/hooks/config.ts +0 -100
  1456. package/src/hooks/discovery.ts +0 -135
  1457. package/src/hooks/manager.ts +0 -179
  1458. package/src/hooks/runner.ts +0 -117
  1459. package/src/hooks/templates.ts +0 -77
  1460. package/src/hooks/types.ts +0 -75
  1461. package/src/ipc/cli-server.ts +0 -252
  1462. package/src/ipc/routes/attachment.ts +0 -114
  1463. package/src/ipc/routes/browser-context.ts +0 -61
  1464. package/src/ipc/routes/browser.ts +0 -96
  1465. package/src/ipc/routes/cache.ts +0 -96
  1466. package/src/ipc/routes/index.ts +0 -21
  1467. package/src/ipc/routes/task-queue.ts +0 -226
  1468. package/src/ipc/routes/task.ts +0 -173
  1469. package/src/ipc/routes/wake-conversation.ts +0 -19
  1470. package/src/memory/db.ts +0 -23
  1471. package/src/oauth/scope-policy.ts +0 -89
  1472. package/src/permissions/bash-risk-classifier.test.ts +0 -1208
  1473. package/src/permissions/bash-risk-classifier.ts +0 -707
  1474. package/src/permissions/command-registry.test.ts +0 -535
  1475. package/src/permissions/command-registry.ts +0 -825
  1476. package/src/permissions/defaults.ts +0 -313
  1477. package/src/permissions/file-risk-classifier.test.ts +0 -535
  1478. package/src/permissions/file-risk-classifier.ts +0 -274
  1479. package/src/permissions/permission-mode.ts +0 -24
  1480. package/src/permissions/shell-identity.ts +0 -337
  1481. package/src/permissions/skill-risk-classifier.test.ts +0 -311
  1482. package/src/permissions/skill-risk-classifier.ts +0 -214
  1483. package/src/permissions/trust-client.ts +0 -359
  1484. package/src/permissions/trust-store-interface.ts +0 -100
  1485. package/src/permissions/trust-store.ts +0 -1330
  1486. package/src/permissions/v2-consent-policy.ts +0 -87
  1487. package/src/permissions/web-risk-classifier.test.ts +0 -170
  1488. package/src/permissions/web-risk-classifier.ts +0 -89
  1489. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +0 -715
  1490. package/src/runtime/__tests__/capability-tokens.test.ts +0 -258
  1491. package/src/runtime/actor-refresh-token-store.ts +0 -156
  1492. package/src/runtime/actor-token-store.ts +0 -207
  1493. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -264
  1494. package/src/runtime/auth/credential-service.ts +0 -352
  1495. package/src/runtime/conversation-approval-overrides.ts +0 -86
  1496. package/src/runtime/gateway-internal-client.ts +0 -94
  1497. package/src/runtime/routes/browser-extension-pair-routes.ts +0 -556
  1498. package/src/runtime/routes/channel-routes.ts +0 -112
  1499. package/src/runtime/routes/contact-routes.test.ts +0 -298
  1500. package/src/runtime/routes/guardian-bootstrap-routes.ts +0 -175
  1501. package/src/runtime/routes/guardian-refresh-routes.ts +0 -79
  1502. package/src/runtime/routes/invite-routes.ts +0 -280
  1503. package/src/runtime/routes/pairing-routes.ts +0 -431
  1504. package/src/runtime/routes/watch-routes.ts +0 -156
  1505. package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +0 -67
  1506. package/src/runtime/services/analyze-deps-singleton.ts +0 -32
  1507. package/src/signals/shotgun.ts +0 -203
  1508. package/src/tasks/ephemeral-permissions.ts +0 -55
  1509. package/src/tools/terminal/parser.ts +0 -623
  1510. package/src/tools/watch/screen-watch.ts +0 -144
  1511. package/src/tools/watch/watch-state.ts +0 -142
  1512. package/src/types/qrcode.d.ts +0 -13
  1513. package/src/util/network-info.ts +0 -55
  1514. /package/node_modules/@vellumai/{ces-contracts → ces-client}/tsconfig.json +0 -0
  1515. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/__tests__/grants.test.ts +0 -0
  1516. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/error.ts +0 -0
  1517. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/grants.ts +0 -0
  1518. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/handles.ts +0 -0
  1519. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/rendering.ts +0 -0
  1520. /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/rpc.ts +0 -0
@@ -0,0 +1,1348 @@
1
+ /**
2
+ * `SkillHostClient` — IPC-backed concretion of the neutral `SkillHost`
3
+ * interface. Lets an out-of-process first-party skill consume the daemon's
4
+ * host surface over the Unix domain socket exposed by `SkillIpcServer`.
5
+ *
6
+ * Wire protocol (mirrors `assistant/src/ipc/skill-server.ts`):
7
+ *
8
+ * skill-initiated RPC (one-shot)
9
+ * → { id: "s:<n>", method, params? }
10
+ * ← { id: "s:<n>", result } | { id: "s:<n>", error }
11
+ *
12
+ * daemon-initiated RPC (one-shot, requires registered handler)
13
+ * ← { id: "d:<n>", method, params? }
14
+ * → { id: "d:<n>", result } | { id: "d:<n>", error }
15
+ *
16
+ * streaming RPC (e.g. `host.events.subscribe`, skill-initiated only)
17
+ * → { id: "s:<n>", method, params? }
18
+ * ← { id: "s:<n>", result: { subscribed: true } } (open ack)
19
+ * ← { id: "s:<n>", event: "delivery", payload: <data> } (0..N)
20
+ * ← { id: "s:<n>", error } (terminal)
21
+ * → { id: "s:<n>", method: "host.events.subscribe.close",
22
+ * params: { subscribeId: <original-id> } }
23
+ * ← { id: "s:<n>", result: { closed: true } }
24
+ *
25
+ * The `s:` / `d:` id prefixes namespace the two directions so each side can
26
+ * route inbound responses to its own pending-request map without collision.
27
+ *
28
+ * ### Daemon-initiated dispatch handlers
29
+ *
30
+ * After the skill registers tools / routes / shutdown hooks via
31
+ * `registries.registerTools`, `registries.registerSkillRoute`, and
32
+ * `registries.registerShutdownHook`, the client also installs local
33
+ * handlers for the matching `skill.dispatch_*` methods so the daemon can
34
+ * invoke skill-side closures over the bidirectional RPC. The wire shapes
35
+ * are:
36
+ *
37
+ * skill.dispatch_tool
38
+ * daemon → skill: { name: string, input: Record<string, unknown>,
39
+ * context?: unknown }
40
+ * skill → daemon: { result: unknown }
41
+ * errors: throws "unknown tool: <name>" when the tool name is not in
42
+ * the most recently registered provider's output.
43
+ *
44
+ * skill.dispatch_route
45
+ * daemon → skill: { patternSource: string,
46
+ * request: { method: string, url: string,
47
+ * headers?: Record<string, string>,
48
+ * body?: string } }
49
+ * skill → daemon: { status: number,
50
+ * headers: Record<string, string>,
51
+ * body: string }
52
+ * errors: throws "unknown route: <patternSource>" when no registered
53
+ * route matches the patternSource, or "url did not match
54
+ * pattern: <patternSource>" when the regex fails to match.
55
+ *
56
+ * skill.shutdown
57
+ * daemon → skill: { name?: string, reason?: string }
58
+ * skill → daemon: { ok: true }
59
+ * semantics: when `name` is set, runs only that hook; otherwise runs
60
+ * all registered hooks in reverse-registration order. Per-
61
+ * hook errors are swallowed (logged via the host logger if
62
+ * `connect()` has populated one).
63
+ *
64
+ * ### Sync-method bootstrap
65
+ *
66
+ * The `SkillHost` contract exposes a number of synchronous accessors
67
+ * (`identity.internalAssistantId`, `platform.workspaceDir()`,
68
+ * `platform.runtimeMode()`, etc.) that naturally cannot round-trip an async
69
+ * IPC call on every invocation. `connect()` prefetches the stable subset of
70
+ * these values once, caches them locally, and every subsequent sync accessor
71
+ * reads from the cache. Skill code MUST await `connect()` before any
72
+ * synchronous host accessor fires; calling a sync accessor before connect
73
+ * throws a clear "not connected" error.
74
+ *
75
+ * ### Opaque handle methods
76
+ *
77
+ * Several provider accessors on `SkillHost` (`providers.llm.getConfigured`,
78
+ * `providers.llm.userMessage`, `providers.llm.extractToolUse`,
79
+ * `providers.stt.resolveStreamingTranscriber`, `providers.tts.get`,
80
+ * `speakers.createTracker`) return opaque handles whose concrete types live
81
+ * inside `assistant/`. Across IPC they cannot carry the handle's method
82
+ * closures — the skill treats the return value as a black-box token and
83
+ * threads it into `host.providers.llm.complete` / future dispatch routes.
84
+ * The client implements each as a passthrough that returns a tagged
85
+ * descriptor object; the daemon-side handler that ultimately consumes the
86
+ * token narrows it back to the concrete type at its boundary.
87
+ *
88
+ * ### Reconnect
89
+ *
90
+ * When `autoReconnect` is enabled, a lost socket connection is retried with
91
+ * exponential backoff (capped at `reconnectMaxDelayMs`). In-flight requests
92
+ * are rejected with a clear error because no response correlation survives
93
+ * a socket reset; callers are responsible for retrying at a higher level.
94
+ * Long-lived subscriptions are re-opened on reconnect with the same filter
95
+ * so skill-side callbacks keep firing once the socket is back.
96
+ */
97
+
98
+ import { randomUUID } from "node:crypto";
99
+ import { connect, type Socket } from "node:net";
100
+
101
+ import type { AssistantEvent } from "./assistant-event.js";
102
+ import type { DaemonRuntimeMode } from "./runtime-mode.js";
103
+ import type { ServerMessage } from "./server-message.js";
104
+ import type {
105
+ AssistantEventCallback,
106
+ ConfigFacet,
107
+ EventsFacet,
108
+ Filter,
109
+ IdentityFacet,
110
+ InsertMessageFn,
111
+ LlmProvidersFacet,
112
+ Logger,
113
+ LoggerFacet,
114
+ MemoryFacet,
115
+ PlatformFacet,
116
+ Provider,
117
+ ProvidersFacet,
118
+ RegistriesFacet,
119
+ SecureKeysFacet,
120
+ SkillHost,
121
+ SkillRoute,
122
+ SkillRouteHandle,
123
+ SpeakersFacet,
124
+ SttProvidersFacet,
125
+ Subscription,
126
+ ToolUse,
127
+ TtsConfig,
128
+ TtsProvider,
129
+ TtsProvidersFacet,
130
+ UserMessage,
131
+ } from "./skill-host.js";
132
+ import type { Tool, ToolContext } from "./tool-types.js";
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // Constants
136
+ // ---------------------------------------------------------------------------
137
+
138
+ const SUBSCRIBE_CLOSE_METHOD = "host.events.subscribe.close" as const;
139
+ const DEFAULT_CALL_TIMEOUT_MS = 30_000;
140
+ const DEFAULT_CONNECT_TIMEOUT_MS = 3_000;
141
+ const DEFAULT_RECONNECT_BASE_DELAY_MS = 200;
142
+ const DEFAULT_RECONNECT_MAX_DELAY_MS = 10_000;
143
+
144
+ /** Prefix for ids minted by the daemon (server) side. */
145
+ const DAEMON_ID_PREFIX = "d:" as const;
146
+ /** Prefix for ids minted by the skill (client) side. */
147
+ const SKILL_ID_PREFIX = "s:" as const;
148
+
149
+ // ---------------------------------------------------------------------------
150
+ // Wire-format types
151
+ // ---------------------------------------------------------------------------
152
+
153
+ type IpcRequest = {
154
+ id: string;
155
+ method: string;
156
+ params?: Record<string, unknown>;
157
+ };
158
+
159
+ type IpcResponseFrame = {
160
+ id: string;
161
+ method?: string;
162
+ params?: unknown;
163
+ result?: unknown;
164
+ error?: string;
165
+ event?: "delivery";
166
+ payload?: unknown;
167
+ };
168
+
169
+ /**
170
+ * Handler for a daemon-initiated request. Returning a value (or a Promise)
171
+ * resolves the daemon's `sendRequest` call; throwing rejects it with the
172
+ * thrown error's message. Synchronous returns are wrapped automatically.
173
+ */
174
+ export type SkillHostRequestHandler = (
175
+ params: unknown,
176
+ ) => unknown | Promise<unknown>;
177
+
178
+ // ---------------------------------------------------------------------------
179
+ // Public options
180
+ // ---------------------------------------------------------------------------
181
+
182
+ export interface SkillHostClientOptions {
183
+ /** Absolute path to the `assistant-skill.sock` Unix domain socket. */
184
+ socketPath: string;
185
+ /**
186
+ * Identifier for the owning skill. Sent as the default logger-scope name
187
+ * when `logger.get(name)` is not explicitly scoped, and reserved for
188
+ * future per-skill routing at the daemon boundary.
189
+ */
190
+ skillId: string;
191
+ /**
192
+ * Automatically reconnect the underlying socket when it drops. Existing
193
+ * subscriptions are reopened with the same filter; in-flight one-shot
194
+ * requests are rejected with a "connection lost" error.
195
+ *
196
+ * @default false
197
+ */
198
+ autoReconnect?: boolean;
199
+ /** Initial retry delay (ms). Exponentially backs off to the max. */
200
+ reconnectBaseDelayMs?: number;
201
+ /** Maximum retry delay (ms). */
202
+ reconnectMaxDelayMs?: number;
203
+ /** Per-call timeout for one-shot RPCs. */
204
+ callTimeoutMs?: number;
205
+ /** Socket `connect()` timeout. */
206
+ connectTimeoutMs?: number;
207
+ }
208
+
209
+ // ---------------------------------------------------------------------------
210
+ // Internal state for pending calls and subscriptions
211
+ // ---------------------------------------------------------------------------
212
+
213
+ interface PendingCall {
214
+ resolve: (value: unknown) => void;
215
+ reject: (err: Error) => void;
216
+ timer: ReturnType<typeof setTimeout>;
217
+ }
218
+
219
+ interface ActiveSubscription {
220
+ id: string;
221
+ filter: Filter;
222
+ callback: AssistantEventCallback;
223
+ disposed: boolean;
224
+ }
225
+
226
+ // ---------------------------------------------------------------------------
227
+ // Helpers
228
+ // ---------------------------------------------------------------------------
229
+
230
+ function notConnected(): Error {
231
+ return new Error(
232
+ "SkillHostClient: not connected. Call `await client.connect()` before using synchronous host accessors.",
233
+ );
234
+ }
235
+
236
+ /**
237
+ * Wraps a sync logger call so a host.log RPC failure never throws at the
238
+ * call site — skills treat logging as side-effectful and don't want a
239
+ * transient socket issue to abort whatever they were doing.
240
+ */
241
+ function swallow(err: unknown): void {
242
+ // Intentional no-op; logging here would recurse into the same broken
243
+ // logger. The stderr path is a deliberate last-resort sink.
244
+ if (err && process.env.SKILL_HOST_CLIENT_DEBUG) {
245
+ // eslint-disable-next-line no-console
246
+ console.error("[SkillHostClient] log RPC failed:", err);
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Stringify an unknown error value for the wire — `Error.message` when
252
+ * available, otherwise `String(err)` so non-Error throws still surface
253
+ * something readable on the daemon side.
254
+ */
255
+ function errorMessage(err: unknown): string {
256
+ if (err instanceof Error) return err.message;
257
+ return String(err);
258
+ }
259
+
260
+ // ---------------------------------------------------------------------------
261
+ // Client implementation
262
+ // ---------------------------------------------------------------------------
263
+
264
+ export class SkillHostClient implements SkillHost {
265
+ // Facets are populated in the constructor so every `SkillHost` method
266
+ // has a concrete target even before `connect()` resolves. Sync methods
267
+ // that depend on prefetched state throw `notConnected()` until then.
268
+ readonly logger: LoggerFacet;
269
+ readonly config: ConfigFacet;
270
+ readonly identity: IdentityFacet;
271
+ readonly platform: PlatformFacet;
272
+ readonly providers: ProvidersFacet;
273
+ readonly memory: MemoryFacet;
274
+ readonly events: EventsFacet;
275
+ readonly registries: RegistriesFacet;
276
+ readonly speakers: SpeakersFacet;
277
+
278
+ private readonly options: Required<
279
+ Pick<
280
+ SkillHostClientOptions,
281
+ | "socketPath"
282
+ | "skillId"
283
+ | "callTimeoutMs"
284
+ | "connectTimeoutMs"
285
+ | "reconnectBaseDelayMs"
286
+ | "reconnectMaxDelayMs"
287
+ >
288
+ > & { autoReconnect: boolean };
289
+
290
+ private socket: Socket | null = null;
291
+ private buffer = "";
292
+ private readonly pending = new Map<string, PendingCall>();
293
+ private readonly subscriptions = new Map<string, ActiveSubscription>();
294
+ private connectingPromise: Promise<void> | null = null;
295
+ private closed = false;
296
+ private reconnectAttempt = 0;
297
+ /**
298
+ * Monotonic counter for skill-initiated request ids, formatted as
299
+ * `s:<n>`. The daemon mints `d:<n>` ids independently, so the two
300
+ * sequences never collide on a shared socket.
301
+ */
302
+ private nextSkillRequestSeq = 1;
303
+ /**
304
+ * Handlers for daemon-initiated requests, keyed by method name. Populated
305
+ * via `registerHandler(method, handler)`. Daemon→skill request frames
306
+ * (id starts with `d:`) are dispatched through this table.
307
+ */
308
+ private readonly daemonRequestHandlers = new Map<
309
+ string,
310
+ SkillHostRequestHandler
311
+ >();
312
+
313
+ // Prefetched sync state — populated by `connect()`.
314
+ private cachedInternalAssistantId: string | null = null;
315
+ private cachedAssistantName: string | undefined = undefined;
316
+ private cachedWorkspaceDir: string | null = null;
317
+ private cachedVellumRoot: string | null = null;
318
+ private cachedRuntimeMode: DaemonRuntimeMode | null = null;
319
+
320
+ // ── Local dispatch state ────────────────────────────────────────────────
321
+ // Caches populated by `registries.register*` so the daemon can dispatch
322
+ // skill-owned closures back over the bidirectional RPC. Mirrors what the
323
+ // out-of-process skill installed in-process before the IPC split.
324
+
325
+ /** Most recently registered tool provider (last writer wins, matching the in-process semantics where a single skill module owns one provider). */
326
+ private cachedToolsProvider: (() => Tool[]) | null = null;
327
+ /**
328
+ * Routes keyed by `pattern.source`. Last writer wins on collision so
329
+ * re-registering the same regex source replaces the prior handler — mirrors
330
+ * how an in-process skill would re-`registerSkillRoute` on hot reload.
331
+ */
332
+ private readonly cachedRoutes = new Map<string, SkillRoute>();
333
+ /**
334
+ * Shutdown hooks ordered by registration time. We use an array (not a Map
335
+ * keyed by name) because the spec requires running hooks in reverse-
336
+ * registration order when no name is provided. Re-registering an existing
337
+ * name replaces the prior entry in place to keep the cache idempotent.
338
+ */
339
+ private readonly cachedShutdownHooks: Array<{
340
+ name: string;
341
+ hook: (reason: string) => Promise<void>;
342
+ }> = [];
343
+
344
+ constructor(options: SkillHostClientOptions) {
345
+ this.options = {
346
+ socketPath: options.socketPath,
347
+ skillId: options.skillId,
348
+ autoReconnect: options.autoReconnect ?? false,
349
+ callTimeoutMs: options.callTimeoutMs ?? DEFAULT_CALL_TIMEOUT_MS,
350
+ connectTimeoutMs: options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS,
351
+ reconnectBaseDelayMs:
352
+ options.reconnectBaseDelayMs ?? DEFAULT_RECONNECT_BASE_DELAY_MS,
353
+ reconnectMaxDelayMs:
354
+ options.reconnectMaxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS,
355
+ };
356
+
357
+ this.logger = this.buildLoggerFacet();
358
+ this.config = this.buildConfigFacet();
359
+ this.identity = this.buildIdentityFacet();
360
+ this.platform = this.buildPlatformFacet();
361
+ this.providers = this.buildProvidersFacet();
362
+ this.memory = this.buildMemoryFacet();
363
+ this.events = this.buildEventsFacet();
364
+ this.registries = this.buildRegistriesFacet();
365
+ this.speakers = this.buildSpeakersFacet();
366
+ }
367
+
368
+ // ── Public lifecycle ────────────────────────────────────────────────────
369
+
370
+ /**
371
+ * Connect to the skill IPC socket and prefetch sync-cacheable state
372
+ * (assistant id, workspace dir, vellum root, runtime mode, assistant
373
+ * name). Safe to call multiple times — the first call initiates the
374
+ * connection, concurrent calls await the same promise.
375
+ */
376
+ async connect(): Promise<void> {
377
+ if (this.closed) {
378
+ throw new Error("SkillHostClient: cannot connect after close()");
379
+ }
380
+ if (this.connectingPromise) return this.connectingPromise;
381
+ // Fully connected: live socket *and* prefetch already populated.
382
+ // If the socket survived but a prior `prefetchSyncState()` rejected,
383
+ // the caches are still null and sync accessors would throw — fall
384
+ // through and re-run prefetch over the existing socket.
385
+ const socketAlive = !!this.socket && !this.socket.destroyed;
386
+ const prefetchDone = this.cachedInternalAssistantId !== null;
387
+ if (socketAlive && prefetchDone) return;
388
+
389
+ const ensureSocket = socketAlive ? Promise.resolve() : this.doConnect();
390
+ this.connectingPromise = ensureSocket
391
+ .then(async () => {
392
+ await this.prefetchSyncState();
393
+ })
394
+ .finally(() => {
395
+ this.connectingPromise = null;
396
+ });
397
+ return this.connectingPromise;
398
+ }
399
+
400
+ /**
401
+ * Close the socket, reject outstanding calls, and dispose all active
402
+ * subscriptions. Safe to call multiple times.
403
+ */
404
+ close(): void {
405
+ if (this.closed) return;
406
+ this.closed = true;
407
+ // Mark every subscription disposed so stray deliveries during teardown
408
+ // don't fire user callbacks.
409
+ for (const sub of this.subscriptions.values()) {
410
+ sub.disposed = true;
411
+ }
412
+ this.subscriptions.clear();
413
+ // Reject any in-flight calls.
414
+ const closeErr = new Error(
415
+ "SkillHostClient: client closed while request was in flight",
416
+ );
417
+ for (const { reject, timer } of this.pending.values()) {
418
+ clearTimeout(timer);
419
+ reject(closeErr);
420
+ }
421
+ this.pending.clear();
422
+ if (this.socket && !this.socket.destroyed) {
423
+ this.socket.destroy();
424
+ }
425
+ this.socket = null;
426
+ }
427
+
428
+ /**
429
+ * Install a handler for daemon-initiated requests of the given method.
430
+ * The daemon's `SkillIpcServer.sendRequest(connection, method, ...)`
431
+ * resolves with whatever the handler returns (or rejects with the
432
+ * handler's thrown error). Re-registering a method replaces the prior
433
+ * handler — last writer wins.
434
+ */
435
+ registerHandler(method: string, handler: SkillHostRequestHandler): void {
436
+ this.daemonRequestHandlers.set(method, handler);
437
+ }
438
+
439
+ // ── Internal: socket lifecycle ──────────────────────────────────────────
440
+
441
+ private async doConnect(): Promise<void> {
442
+ const { socketPath, connectTimeoutMs } = this.options;
443
+ return new Promise<void>((resolve, reject) => {
444
+ const socket = connect(socketPath);
445
+ let settled = false;
446
+
447
+ const timer = setTimeout(() => {
448
+ if (settled) return;
449
+ settled = true;
450
+ socket.destroy();
451
+ reject(
452
+ new Error(
453
+ `SkillHostClient: connect timed out after ${connectTimeoutMs}ms (${socketPath})`,
454
+ ),
455
+ );
456
+ }, connectTimeoutMs);
457
+
458
+ socket.once("connect", () => {
459
+ if (settled) return;
460
+ settled = true;
461
+ clearTimeout(timer);
462
+ // The client may have been `close()`d while `connect()` was
463
+ // still pending. If we attach now we'd reintroduce a live
464
+ // socket on a closed client and leak the server-side connection
465
+ // until process teardown.
466
+ if (this.closed) {
467
+ socket.destroy();
468
+ reject(new Error("SkillHostClient: closed during connect"));
469
+ return;
470
+ }
471
+ this.attachSocket(socket);
472
+ resolve();
473
+ });
474
+
475
+ socket.once("error", (err) => {
476
+ if (settled) return;
477
+ settled = true;
478
+ clearTimeout(timer);
479
+ reject(
480
+ new Error(
481
+ `SkillHostClient: socket error during connect: ${err.message}`,
482
+ ),
483
+ );
484
+ });
485
+ });
486
+ }
487
+
488
+ private attachSocket(socket: Socket): void {
489
+ this.socket = socket;
490
+ this.buffer = "";
491
+ this.reconnectAttempt = 0;
492
+
493
+ socket.on("data", (chunk) => {
494
+ this.buffer += chunk.toString();
495
+ let newlineIdx: number;
496
+ while ((newlineIdx = this.buffer.indexOf("\n")) !== -1) {
497
+ const line = this.buffer.slice(0, newlineIdx).trim();
498
+ this.buffer = this.buffer.slice(newlineIdx + 1);
499
+ if (line) this.handleFrame(line);
500
+ }
501
+ });
502
+
503
+ socket.on("close", () => {
504
+ this.socket = null;
505
+ const err = new Error(
506
+ "SkillHostClient: socket closed before response",
507
+ );
508
+ for (const { reject, timer } of this.pending.values()) {
509
+ clearTimeout(timer);
510
+ reject(err);
511
+ }
512
+ this.pending.clear();
513
+ if (!this.closed && this.options.autoReconnect) {
514
+ void this.scheduleReconnect();
515
+ }
516
+ });
517
+
518
+ socket.on("error", (err) => {
519
+ swallow(err);
520
+ });
521
+ }
522
+
523
+ private async scheduleReconnect(): Promise<void> {
524
+ if (this.closed) return;
525
+ this.reconnectAttempt += 1;
526
+ const delay = Math.min(
527
+ this.options.reconnectBaseDelayMs *
528
+ Math.pow(2, this.reconnectAttempt - 1),
529
+ this.options.reconnectMaxDelayMs,
530
+ );
531
+ await new Promise((resolve) => setTimeout(resolve, delay));
532
+ if (this.closed) return;
533
+ try {
534
+ await this.doConnect();
535
+ // Re-open every live subscription with a fresh request so the
536
+ // server-side hub installs a new callback.
537
+ const live = [...this.subscriptions.values()].filter((s) => !s.disposed);
538
+ this.subscriptions.clear();
539
+ for (const sub of live) {
540
+ this.reopenSubscription(sub);
541
+ }
542
+ } catch (err) {
543
+ swallow(err);
544
+ if (!this.closed) {
545
+ void this.scheduleReconnect();
546
+ }
547
+ }
548
+ }
549
+
550
+ private reopenSubscription(prev: ActiveSubscription): void {
551
+ // Same id so the application-visible Subscription handle still works.
552
+ const fresh: ActiveSubscription = {
553
+ id: prev.id,
554
+ filter: prev.filter,
555
+ callback: prev.callback,
556
+ disposed: false,
557
+ };
558
+ this.subscriptions.set(fresh.id, fresh);
559
+ // Mirror `openSubscription`: pre-register a pending entry so the
560
+ // server's `{ id, result: { subscribed: true } }` ack frame is
561
+ // matched (otherwise `handleFrame` silently drops it) and so we
562
+ // tear the subscription down on ack timeout instead of leaking it.
563
+ this.registerSubscribeAck(fresh);
564
+ try {
565
+ this.writeFrame({
566
+ id: fresh.id,
567
+ method: "host.events.subscribe",
568
+ params: { filter: fresh.filter },
569
+ });
570
+ } catch (err) {
571
+ this.cancelSubscribeAck(fresh);
572
+ swallow(err);
573
+ }
574
+ }
575
+
576
+ private registerSubscribeAck(active: ActiveSubscription): void {
577
+ const ackTimer = setTimeout(() => {
578
+ if (this.pending.delete(active.id)) {
579
+ active.disposed = true;
580
+ this.subscriptions.delete(active.id);
581
+ }
582
+ }, this.options.callTimeoutMs);
583
+ this.pending.set(active.id, {
584
+ resolve: () => {
585
+ clearTimeout(ackTimer);
586
+ },
587
+ reject: (err) => {
588
+ clearTimeout(ackTimer);
589
+ active.disposed = true;
590
+ this.subscriptions.delete(active.id);
591
+ swallow(err);
592
+ },
593
+ timer: ackTimer,
594
+ });
595
+ }
596
+
597
+ private cancelSubscribeAck(active: ActiveSubscription): void {
598
+ const entry = this.pending.get(active.id);
599
+ if (entry) {
600
+ clearTimeout(entry.timer);
601
+ this.pending.delete(active.id);
602
+ }
603
+ active.disposed = true;
604
+ this.subscriptions.delete(active.id);
605
+ }
606
+
607
+ // ── Internal: frame I/O ─────────────────────────────────────────────────
608
+
609
+ private handleFrame(line: string): void {
610
+ let frame: IpcResponseFrame;
611
+ try {
612
+ frame = JSON.parse(line) as IpcResponseFrame;
613
+ } catch (err) {
614
+ swallow(err);
615
+ return;
616
+ }
617
+
618
+ if (
619
+ !frame ||
620
+ typeof frame !== "object" ||
621
+ Array.isArray(frame) ||
622
+ typeof frame.id !== "string"
623
+ ) {
624
+ return;
625
+ }
626
+
627
+ // Delivery frames route into the subscription callback.
628
+ if (frame.event === "delivery") {
629
+ const sub = this.subscriptions.get(frame.id);
630
+ if (sub && !sub.disposed) {
631
+ try {
632
+ const r = sub.callback(frame.payload as AssistantEvent);
633
+ if (r instanceof Promise) r.catch(swallow);
634
+ } catch (err) {
635
+ swallow(err);
636
+ }
637
+ }
638
+ return;
639
+ }
640
+
641
+ // Daemon-initiated request frame — dispatch to a registered handler
642
+ // and write back the response. Identified by the `d:` id prefix and
643
+ // the presence of a `method` field.
644
+ if (
645
+ typeof frame.method === "string" &&
646
+ frame.id.startsWith(DAEMON_ID_PREFIX)
647
+ ) {
648
+ this.dispatchDaemonRequest(frame.id, frame.method, frame.params);
649
+ return;
650
+ }
651
+
652
+ // Response frame — resolve or reject the pending call.
653
+ const pending = this.pending.get(frame.id);
654
+ if (pending) {
655
+ this.pending.delete(frame.id);
656
+ clearTimeout(pending.timer);
657
+ if (frame.error !== undefined) {
658
+ pending.reject(
659
+ new Error(`SkillHostClient: remote error: ${frame.error}`),
660
+ );
661
+ } else {
662
+ pending.resolve(frame.result);
663
+ }
664
+ return;
665
+ }
666
+
667
+ // No pending entry — could be a terminal error on a subscription.
668
+ if (frame.error !== undefined) {
669
+ const sub = this.subscriptions.get(frame.id);
670
+ if (sub) {
671
+ sub.disposed = true;
672
+ this.subscriptions.delete(frame.id);
673
+ }
674
+ }
675
+ }
676
+
677
+ private dispatchDaemonRequest(
678
+ id: string,
679
+ method: string,
680
+ params: unknown,
681
+ ): void {
682
+ const handler = this.daemonRequestHandlers.get(method);
683
+ if (!handler) {
684
+ this.writeResponseFrame({
685
+ id,
686
+ error: `method not found: ${method}`,
687
+ });
688
+ return;
689
+ }
690
+ let result: unknown;
691
+ try {
692
+ result = handler(params);
693
+ } catch (err) {
694
+ this.writeResponseFrame({ id, error: errorMessage(err) });
695
+ return;
696
+ }
697
+ if (result instanceof Promise) {
698
+ result.then(
699
+ (value) => {
700
+ this.writeResponseFrame({ id, result: value });
701
+ },
702
+ (err) => {
703
+ this.writeResponseFrame({ id, error: errorMessage(err) });
704
+ },
705
+ );
706
+ } else {
707
+ this.writeResponseFrame({ id, result });
708
+ }
709
+ }
710
+
711
+ private writeResponseFrame(response: {
712
+ id: string;
713
+ result?: unknown;
714
+ error?: string;
715
+ }): void {
716
+ if (!this.socket || this.socket.destroyed) {
717
+ // The peer is gone; silently drop. The daemon-side pending entry
718
+ // will already have been rejected by the connection-close path.
719
+ return;
720
+ }
721
+ this.socket.write(JSON.stringify(response) + "\n");
722
+ }
723
+
724
+ private writeFrame(req: IpcRequest): void {
725
+ if (!this.socket || this.socket.destroyed) {
726
+ throw new Error("SkillHostClient: not connected");
727
+ }
728
+ this.socket.write(JSON.stringify(req) + "\n");
729
+ }
730
+
731
+ /** Allocate the next `s:<n>` id for a skill-initiated request. */
732
+ private nextSkillRequestId(): string {
733
+ return `${SKILL_ID_PREFIX}${this.nextSkillRequestSeq++}`;
734
+ }
735
+
736
+ private async call<T>(
737
+ method: string,
738
+ params?: Record<string, unknown>,
739
+ ): Promise<T> {
740
+ if (this.closed) {
741
+ throw new Error("SkillHostClient: client is closed");
742
+ }
743
+ if (!this.socket || this.socket.destroyed) {
744
+ throw new Error(
745
+ "SkillHostClient: not connected. Call `await client.connect()` first.",
746
+ );
747
+ }
748
+ const id = this.nextSkillRequestId();
749
+ return new Promise<T>((resolve, reject) => {
750
+ const timer = setTimeout(() => {
751
+ if (this.pending.delete(id)) {
752
+ reject(
753
+ new Error(
754
+ `SkillHostClient: call '${method}' timed out after ${this.options.callTimeoutMs}ms`,
755
+ ),
756
+ );
757
+ }
758
+ }, this.options.callTimeoutMs);
759
+ this.pending.set(id, {
760
+ resolve: (v) => resolve(v as T),
761
+ reject,
762
+ timer,
763
+ });
764
+ try {
765
+ this.writeFrame({ id, method, params });
766
+ } catch (err) {
767
+ this.pending.delete(id);
768
+ clearTimeout(timer);
769
+ reject(err as Error);
770
+ }
771
+ });
772
+ }
773
+
774
+ // ── Internal: bootstrap cache ───────────────────────────────────────────
775
+
776
+ private async prefetchSyncState(): Promise<void> {
777
+ const [assistantId, workspaceDir, vellumRootValue, runtimeMode, name] =
778
+ await Promise.all([
779
+ this.call<string>("host.identity.getInternalAssistantId"),
780
+ this.call<string>("host.platform.workspaceDir"),
781
+ this.call<string>("host.platform.vellumRoot"),
782
+ this.call<DaemonRuntimeMode>("host.platform.runtimeMode"),
783
+ this.call<string | null>("host.identity.getAssistantName"),
784
+ ]);
785
+ this.cachedInternalAssistantId = assistantId;
786
+ this.cachedWorkspaceDir = workspaceDir;
787
+ this.cachedVellumRoot = vellumRootValue;
788
+ this.cachedRuntimeMode = runtimeMode;
789
+ this.cachedAssistantName = name ?? undefined;
790
+ }
791
+
792
+ // ── Facet builders ──────────────────────────────────────────────────────
793
+
794
+ private buildLogger(name: string): Logger {
795
+ const scope = name || this.options.skillId;
796
+ const write = (
797
+ level: "debug" | "info" | "warn" | "error",
798
+ msg: string,
799
+ meta?: unknown,
800
+ ) => {
801
+ // Fire-and-forget: skills expect logging to be non-blocking and
802
+ // infallible. If the socket is down we just drop the line.
803
+ this.call("host.log", { level, msg, name: scope, meta }).catch(swallow);
804
+ };
805
+ return {
806
+ debug: (msg, meta) => write("debug", msg, meta),
807
+ info: (msg, meta) => write("info", msg, meta),
808
+ warn: (msg, meta) => write("warn", msg, meta),
809
+ error: (msg, meta) => write("error", msg, meta),
810
+ };
811
+ }
812
+
813
+ private buildLoggerFacet(): LoggerFacet {
814
+ return {
815
+ get: (name) => this.buildLogger(name),
816
+ };
817
+ }
818
+
819
+ private buildConfigFacet(): ConfigFacet {
820
+ return {
821
+ // `isFeatureFlagEnabled` and `getSection` are typed as sync on the
822
+ // contract but require a round-trip to resolve. We cannot block on
823
+ // async I/O inside a sync accessor, so the client surfaces the
824
+ // async semantics by returning a stale-safe value if one has been
825
+ // cached via `prefetchFlag` / `prefetchSection` helpers (future
826
+ // work) — for now, these throw a clear error so skill code that
827
+ // ever reaches them on the client path is audible instead of
828
+ // silently returning a wrong value. Async callers should use the
829
+ // underlying IPC method names directly via `rawCall`.
830
+ isFeatureFlagEnabled: (_key: string): boolean => {
831
+ throw new Error(
832
+ "SkillHostClient.config.isFeatureFlagEnabled: synchronous feature-flag reads are not supported over IPC. Use `client.rawCall('host.config.isFeatureFlagEnabled', { key })` and await the result.",
833
+ );
834
+ },
835
+ getSection: <T>(_path: string): T | undefined => {
836
+ throw new Error(
837
+ "SkillHostClient.config.getSection: synchronous config reads are not supported over IPC. Use `client.rawCall('host.config.getSection', { path })` and await the result.",
838
+ );
839
+ },
840
+ };
841
+ }
842
+
843
+ private buildIdentityFacet(): IdentityFacet {
844
+ const self = this;
845
+ return {
846
+ getAssistantName: () => {
847
+ if (self.cachedInternalAssistantId === null) throw notConnected();
848
+ return self.cachedAssistantName;
849
+ },
850
+ get internalAssistantId(): string {
851
+ if (self.cachedInternalAssistantId === null) throw notConnected();
852
+ return self.cachedInternalAssistantId;
853
+ },
854
+ };
855
+ }
856
+
857
+ private buildPlatformFacet(): PlatformFacet {
858
+ return {
859
+ workspaceDir: () => {
860
+ if (this.cachedWorkspaceDir === null) throw notConnected();
861
+ return this.cachedWorkspaceDir;
862
+ },
863
+ vellumRoot: () => {
864
+ if (this.cachedVellumRoot === null) throw notConnected();
865
+ return this.cachedVellumRoot;
866
+ },
867
+ runtimeMode: () => {
868
+ if (this.cachedRuntimeMode === null) throw notConnected();
869
+ return this.cachedRuntimeMode;
870
+ },
871
+ };
872
+ }
873
+
874
+ private buildLlmProvidersFacet(): LlmProvidersFacet {
875
+ // The provider, user-message, and tool-use values are opaque tokens on
876
+ // the contract; the client synthesizes structurally inert descriptors
877
+ // that round-trip through future dispatch routes.
878
+ return {
879
+ getConfigured: async (callSite: string): Promise<Provider | null> =>
880
+ ({
881
+ __vellumSkillHostClientHandle: "llm-provider",
882
+ callSite,
883
+ }) as unknown as Provider,
884
+ userMessage: (text: string): UserMessage =>
885
+ ({
886
+ __vellumSkillHostClientHandle: "user-message",
887
+ text,
888
+ }) as unknown as UserMessage,
889
+ extractToolUse: (_response: unknown): ToolUse | null => {
890
+ // The client cannot inspect daemon-shaped completion responses
891
+ // without pulling in the Anthropic SDK types; skills that need
892
+ // typed tool-use extraction should do it via the completion's
893
+ // `content` array directly. Return null as the conservative
894
+ // "no tool_use" answer.
895
+ return null;
896
+ },
897
+ createTimeout: (ms: number) => {
898
+ const controller = new AbortController();
899
+ const timer = setTimeout(() => controller.abort(), ms);
900
+ return {
901
+ signal: controller.signal,
902
+ cleanup: () => clearTimeout(timer),
903
+ };
904
+ },
905
+ };
906
+ }
907
+
908
+ private buildSttProvidersFacet(): SttProvidersFacet {
909
+ // stt sub-facet exposes two pure-data queries and one opaque-handle
910
+ // builder. The data queries would require async fetches; we expose
911
+ // them synchronously via the same "call rawCall" pattern the config
912
+ // facet uses.
913
+ return {
914
+ listProviderIds: (): string[] => {
915
+ throw new Error(
916
+ "SkillHostClient.providers.stt.listProviderIds: use `client.rawCall('host.providers.stt.listProviderIds')` and await the result.",
917
+ );
918
+ },
919
+ supportsBoundary: (_id: string): boolean => {
920
+ throw new Error(
921
+ "SkillHostClient.providers.stt.supportsBoundary: use `client.rawCall('host.providers.stt.supportsBoundary', { id, boundary: 'daemon-streaming' })` and await the result.",
922
+ );
923
+ },
924
+ resolveStreamingTranscriber: async (spec: unknown) =>
925
+ ({
926
+ __vellumSkillHostClientHandle: "streaming-transcriber",
927
+ spec,
928
+ }) as unknown,
929
+ };
930
+ }
931
+
932
+ private buildTtsProvidersFacet(): TtsProvidersFacet {
933
+ return {
934
+ get: (id: string): TtsProvider =>
935
+ ({
936
+ __vellumSkillHostClientHandle: "tts-provider",
937
+ id,
938
+ }) as unknown as TtsProvider,
939
+ resolveConfig: (): TtsConfig => {
940
+ throw new Error(
941
+ "SkillHostClient.providers.tts.resolveConfig: use `client.rawCall('host.providers.tts.resolveConfig')` and await the result.",
942
+ );
943
+ },
944
+ };
945
+ }
946
+
947
+ private buildSecureKeysFacet(): SecureKeysFacet {
948
+ return {
949
+ getProviderKey: async (id: string): Promise<string | null> =>
950
+ this.call<string | null>("host.providers.secureKeys.getProviderKey", {
951
+ id,
952
+ }),
953
+ };
954
+ }
955
+
956
+ private buildProvidersFacet(): ProvidersFacet {
957
+ return {
958
+ llm: this.buildLlmProvidersFacet(),
959
+ stt: this.buildSttProvidersFacet(),
960
+ tts: this.buildTtsProvidersFacet(),
961
+ secureKeys: this.buildSecureKeysFacet(),
962
+ };
963
+ }
964
+
965
+ private buildMemoryFacet(): MemoryFacet {
966
+ const addMessage: InsertMessageFn = async (
967
+ conversationId,
968
+ role,
969
+ content,
970
+ metadata,
971
+ opts,
972
+ ) =>
973
+ this.call("host.memory.addMessage", {
974
+ conversationId,
975
+ role,
976
+ content,
977
+ metadata,
978
+ opts,
979
+ });
980
+
981
+ return {
982
+ addMessage,
983
+ wakeAgentForOpportunity: async (req) => {
984
+ // The contract types `req` as opaque; the daemon route validates
985
+ // the concrete `{ conversationId, hint, source }` shape.
986
+ await this.call("host.memory.wakeAgentForOpportunity", {
987
+ ...(req as Record<string, unknown>),
988
+ });
989
+ },
990
+ };
991
+ }
992
+
993
+ private buildEventsFacet(): EventsFacet {
994
+ return {
995
+ publish: async (event) => {
996
+ await this.call("host.events.publish", { event });
997
+ },
998
+ subscribe: (filter, cb) => this.openSubscription(filter, cb),
999
+ buildEvent: (message: ServerMessage, conversationId?: string) => {
1000
+ // `buildEvent` is typed as sync on the contract (the daemon
1001
+ // allocates a uuid + timestamp and returns the envelope). A sync
1002
+ // round-trip isn't possible, so the client produces an envelope
1003
+ // locally using the cached assistant id and the standard uuid /
1004
+ // timestamp sources. This matches the observable shape of the
1005
+ // daemon's `buildAssistantEvent` without the round-trip.
1006
+ if (this.cachedInternalAssistantId === null) throw notConnected();
1007
+ return {
1008
+ id: randomUUID(),
1009
+ assistantId: this.cachedInternalAssistantId,
1010
+ conversationId,
1011
+ emittedAt: new Date().toISOString(),
1012
+ message,
1013
+ };
1014
+ },
1015
+ };
1016
+ }
1017
+
1018
+ private openSubscription(
1019
+ filter: Filter,
1020
+ callback: AssistantEventCallback,
1021
+ ): Subscription {
1022
+ const id = this.nextSkillRequestId();
1023
+ const active: ActiveSubscription = {
1024
+ id,
1025
+ filter,
1026
+ callback,
1027
+ disposed: false,
1028
+ };
1029
+ this.subscriptions.set(id, active);
1030
+ // Pre-register a pending call for the open ack. The server writes a
1031
+ // `{ id, result: { subscribed: true } }` frame back; subsequent
1032
+ // `delivery` frames share the same id.
1033
+ this.registerSubscribeAck(active);
1034
+ try {
1035
+ this.writeFrame({
1036
+ id,
1037
+ method: "host.events.subscribe",
1038
+ params: { filter },
1039
+ });
1040
+ } catch (err) {
1041
+ this.cancelSubscribeAck(active);
1042
+ throw err;
1043
+ }
1044
+
1045
+ const self = this;
1046
+ return {
1047
+ get active() {
1048
+ return !active.disposed;
1049
+ },
1050
+ dispose: () => {
1051
+ if (active.disposed) return;
1052
+ active.disposed = true;
1053
+ self.subscriptions.delete(id);
1054
+ // Fire-and-forget close RPC — we don't await the ack because the
1055
+ // server also tears down on socket close, which is the fallback.
1056
+ if (self.socket && !self.socket.destroyed) {
1057
+ self
1058
+ .call(SUBSCRIBE_CLOSE_METHOD, { subscribeId: id })
1059
+ .catch(swallow);
1060
+ }
1061
+ },
1062
+ };
1063
+ }
1064
+
1065
+ private buildRegistriesFacet(): RegistriesFacet {
1066
+ return {
1067
+ registerTools: (provider) => {
1068
+ // Invoke the provider synchronously so a failure blows up at the
1069
+ // registration call site (matching the in-process semantics)
1070
+ // rather than silently dropping the tools into the RPC.
1071
+ const tools: Tool[] = provider();
1072
+ const manifests = tools.map((t) => {
1073
+ const def = t.getDefinition();
1074
+ return {
1075
+ name: t.name,
1076
+ description: t.description,
1077
+ input_schema: def.input_schema,
1078
+ defaultRiskLevel: t.defaultRiskLevel,
1079
+ category: t.category,
1080
+ executionTarget: t.executionTarget,
1081
+ executionMode: t.executionMode ?? "proxy",
1082
+ ownerSkillId: t.ownerSkillId ?? this.options.skillId,
1083
+ ownerSkillBundled: t.ownerSkillBundled,
1084
+ ownerSkillVersionHash: t.ownerSkillVersionHash,
1085
+ };
1086
+ });
1087
+ // Cache the provider so `skill.dispatch_tool` can resolve a tool
1088
+ // name back to its `execute` closure. Last writer wins.
1089
+ this.cachedToolsProvider = provider;
1090
+ this.ensureDaemonHandler(
1091
+ "skill.dispatch_tool",
1092
+ this.dispatchTool.bind(this),
1093
+ );
1094
+ // Fire-and-forget; registration failures surface in the daemon log.
1095
+ this.call("host.registries.register_tools", { tools: manifests }).catch(
1096
+ swallow,
1097
+ );
1098
+ },
1099
+ registerSkillRoute: (route: SkillRoute): SkillRouteHandle => {
1100
+ // Cache the route by its regex source — `skill.dispatch_route` uses
1101
+ // the same key to find the handler closure. Re-registering the same
1102
+ // source replaces the prior route, matching in-process hot-reload.
1103
+ this.cachedRoutes.set(route.pattern.source, route);
1104
+ this.ensureDaemonHandler(
1105
+ "skill.dispatch_route",
1106
+ this.dispatchRoute.bind(this),
1107
+ );
1108
+ // The `handler` closure cannot cross IPC; the daemon side installs
1109
+ // a proxy that dispatches back over `skill.dispatch_route` (PR D).
1110
+ // `patternFlags` ships separately so `i/m/g/s/u/y` survive the
1111
+ // RegExp → string round-trip — `new RegExp(source)` alone drops them.
1112
+ this.call("host.registries.register_skill_route", {
1113
+ patternSource: route.pattern.source,
1114
+ patternFlags: route.pattern.flags,
1115
+ methods: route.methods,
1116
+ }).catch(swallow);
1117
+ // The contract models the handle as a branded opaque object — we
1118
+ // return a structurally inert placeholder.
1119
+ return {} as SkillRouteHandle;
1120
+ },
1121
+ registerShutdownHook: (name: string, hook) => {
1122
+ // Cache the hook so `skill.shutdown` can invoke it. If the same
1123
+ // name is re-registered, replace in place to keep the array tidy
1124
+ // without disturbing relative order of unrelated entries.
1125
+ const existingIdx = this.cachedShutdownHooks.findIndex(
1126
+ (h) => h.name === name,
1127
+ );
1128
+ const entry = { name, hook };
1129
+ if (existingIdx >= 0) {
1130
+ this.cachedShutdownHooks[existingIdx] = entry;
1131
+ } else {
1132
+ this.cachedShutdownHooks.push(entry);
1133
+ }
1134
+ this.ensureDaemonHandler(
1135
+ "skill.shutdown",
1136
+ this.dispatchShutdown.bind(this),
1137
+ );
1138
+ // Fire-and-forget; the daemon registers a proxy that fires the
1139
+ // skill.shutdown dispatch at teardown (PR D).
1140
+ this.call("host.registries.register_shutdown_hook", { name }).catch(
1141
+ swallow,
1142
+ );
1143
+ },
1144
+ };
1145
+ }
1146
+
1147
+ // ── Local dispatch helpers ──────────────────────────────────────────────
1148
+
1149
+ /**
1150
+ * Install a daemon-initiated request handler exactly once per method.
1151
+ * Idempotent so repeated `register*` calls don't churn the handler table
1152
+ * — every dispatch is routed through the same bound method anyway.
1153
+ */
1154
+ private ensureDaemonHandler(
1155
+ method: string,
1156
+ handler: SkillHostRequestHandler,
1157
+ ): void {
1158
+ if (!this.daemonRequestHandlers.has(method)) {
1159
+ this.daemonRequestHandlers.set(method, handler);
1160
+ }
1161
+ }
1162
+
1163
+ /**
1164
+ * `skill.dispatch_tool` handler — resolves the tool by name from the
1165
+ * cached provider and invokes its `execute(input, context)`. Returns
1166
+ * `{ result }` so the daemon can distinguish the wrapper from the
1167
+ * tool's own (potentially undefined) return value.
1168
+ */
1169
+ private async dispatchTool(params: unknown): Promise<{ result: unknown }> {
1170
+ const { name, input, context } = (params ?? {}) as {
1171
+ name?: unknown;
1172
+ input?: unknown;
1173
+ context?: unknown;
1174
+ };
1175
+ if (typeof name !== "string" || !name) {
1176
+ throw new Error(
1177
+ "skill.dispatch_tool: missing or invalid 'name' parameter",
1178
+ );
1179
+ }
1180
+ const provider = this.cachedToolsProvider;
1181
+ if (!provider) {
1182
+ throw new Error(`unknown tool: ${name}`);
1183
+ }
1184
+ // Re-invoke the provider on each dispatch so feature-flag-gated tool
1185
+ // lists stay live — matches the daemon's lazy-manifest semantics in
1186
+ // `assistant/src/tools/registry.ts`.
1187
+ const tools = provider();
1188
+ const tool = tools.find((t) => t.name === name);
1189
+ if (!tool) {
1190
+ throw new Error(`unknown tool: ${name}`);
1191
+ }
1192
+ // The daemon-side `ToolContext` is opaque on the wire; the skill's
1193
+ // `Tool.execute` runtime-validates any field it actually reads, so a
1194
+ // structural cast is sufficient here. Missing required-on-paper fields
1195
+ // are tolerated in practice — meet-host's tools only consult a small
1196
+ // subset that the daemon serializes through.
1197
+ const ctx = (context ?? {}) as ToolContext;
1198
+ const result = await tool.execute(
1199
+ (input ?? {}) as Record<string, unknown>,
1200
+ ctx,
1201
+ );
1202
+ return { result };
1203
+ }
1204
+
1205
+ /**
1206
+ * `skill.dispatch_route` handler — looks up the route by patternSource,
1207
+ * re-runs the regex against the inbound URL to recover match groups,
1208
+ * invokes the handler, and serializes the `Response` to a
1209
+ * JSON-friendly `{ status, headers, body }`.
1210
+ */
1211
+ private async dispatchRoute(params: unknown): Promise<{
1212
+ status: number;
1213
+ headers: Record<string, string>;
1214
+ body: string;
1215
+ }> {
1216
+ const { patternSource, request } = (params ?? {}) as {
1217
+ patternSource?: unknown;
1218
+ request?: unknown;
1219
+ };
1220
+ if (typeof patternSource !== "string" || !patternSource) {
1221
+ throw new Error(
1222
+ "skill.dispatch_route: missing or invalid 'patternSource' parameter",
1223
+ );
1224
+ }
1225
+ const route = this.cachedRoutes.get(patternSource);
1226
+ if (!route) {
1227
+ throw new Error(`unknown route: ${patternSource}`);
1228
+ }
1229
+ const req = (request ?? {}) as {
1230
+ method?: string;
1231
+ url?: string;
1232
+ headers?: Record<string, string>;
1233
+ body?: string;
1234
+ };
1235
+ if (typeof req.url !== "string" || !req.url) {
1236
+ throw new Error(
1237
+ "skill.dispatch_route: missing or invalid 'request.url' parameter",
1238
+ );
1239
+ }
1240
+ // Resolve against a synthetic base so `new Request` accepts the URL
1241
+ // (it rejects bare paths, but the daemon forwards `pathname + search`)
1242
+ // and so the regex can run against `pathname` alone — keeps query
1243
+ // strings out of anchored patterns like `^/v1/...$`.
1244
+ const parsedUrl = new URL(req.url, "http://skill.local");
1245
+ // Reset lastIndex so a global/sticky regex doesn't carry state across
1246
+ // dispatches — `exec()` mutates lastIndex on g/y flags and the route's
1247
+ // RegExp may be reused across requests.
1248
+ if (route.pattern.global || route.pattern.sticky) {
1249
+ route.pattern.lastIndex = 0;
1250
+ }
1251
+ const match = route.pattern.exec(parsedUrl.pathname);
1252
+ if (!match) {
1253
+ throw new Error(`url did not match pattern: ${patternSource}`);
1254
+ }
1255
+ const init: RequestInit = {
1256
+ method: req.method ?? "GET",
1257
+ headers: req.headers ?? {},
1258
+ };
1259
+ // GET/HEAD requests cannot carry a body in the standard fetch `Request`
1260
+ // constructor; only attach when the verb permits.
1261
+ if (
1262
+ req.body !== undefined &&
1263
+ init.method !== "GET" &&
1264
+ init.method !== "HEAD"
1265
+ ) {
1266
+ init.body = req.body;
1267
+ }
1268
+ const response = await route.handler(
1269
+ new Request(parsedUrl.toString(), init),
1270
+ match,
1271
+ );
1272
+ const headers: Record<string, string> = {};
1273
+ response.headers.forEach((value, key) => {
1274
+ headers[key] = value;
1275
+ });
1276
+ const body = await response.text();
1277
+ return { status: response.status, headers, body };
1278
+ }
1279
+
1280
+ /**
1281
+ * `skill.shutdown` handler — runs cached shutdown hooks. With `name`
1282
+ * set, runs only that hook; otherwise runs all hooks in reverse-
1283
+ * registration order. Per-hook errors are logged via the host logger
1284
+ * and otherwise swallowed so one misbehaving hook can't block the
1285
+ * daemon's overall teardown.
1286
+ */
1287
+ private async dispatchShutdown(params: unknown): Promise<{ ok: true }> {
1288
+ const { name, reason } = (params ?? {}) as {
1289
+ name?: unknown;
1290
+ reason?: unknown;
1291
+ };
1292
+ const reasonStr = typeof reason === "string" ? reason : "shutdown";
1293
+ const log = this.buildLogger(this.options.skillId);
1294
+ const runOne = async (entry: {
1295
+ name: string;
1296
+ hook: (reason: string) => Promise<void>;
1297
+ }): Promise<void> => {
1298
+ try {
1299
+ await entry.hook(reasonStr);
1300
+ } catch (err) {
1301
+ log.warn(`shutdown hook '${entry.name}' threw`, {
1302
+ error: errorMessage(err),
1303
+ });
1304
+ }
1305
+ };
1306
+ if (typeof name === "string" && name) {
1307
+ const entry = this.cachedShutdownHooks.find((h) => h.name === name);
1308
+ if (entry) await runOne(entry);
1309
+ // Silently no-op for unknown names — the daemon may call shutdown
1310
+ // for a hook that was never registered (e.g. a stale registration
1311
+ // leftover from a previous skill load), which shouldn't fail the
1312
+ // overall teardown.
1313
+ return { ok: true };
1314
+ }
1315
+ // Reverse-registration order so later-registered hooks (which often
1316
+ // depend on earlier ones) tear down first.
1317
+ for (let i = this.cachedShutdownHooks.length - 1; i >= 0; i--) {
1318
+ const entry = this.cachedShutdownHooks[i];
1319
+ if (entry) await runOne(entry);
1320
+ }
1321
+ return { ok: true };
1322
+ }
1323
+
1324
+ private buildSpeakersFacet(): SpeakersFacet {
1325
+ return {
1326
+ createTracker: () =>
1327
+ ({
1328
+ __vellumSkillHostClientHandle: "speaker-tracker",
1329
+ }) as unknown,
1330
+ };
1331
+ }
1332
+
1333
+ // ── Public escape hatch ─────────────────────────────────────────────────
1334
+
1335
+ /**
1336
+ * Escape hatch for invoking any `host.*` IPC method directly. Callers
1337
+ * that need to bypass the sync-method ergonomic gap (e.g. async reads
1338
+ * of `host.config.*` or `host.providers.stt.listProviderIds`) use this
1339
+ * to await a single RPC round-trip. The return type is unknown because
1340
+ * the method surface is open.
1341
+ */
1342
+ async rawCall<T = unknown>(
1343
+ method: string,
1344
+ params?: Record<string, unknown>,
1345
+ ): Promise<T> {
1346
+ return this.call<T>(method, params);
1347
+ }
1348
+ }