@vellumai/assistant 0.7.3 → 0.8.1

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 (778) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +29 -28
  3. package/Dockerfile +6 -4
  4. package/README.md +2 -2
  5. package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
  6. package/bun.lock +3 -0
  7. package/docker-entrypoint.sh +16 -0
  8. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  9. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  10. package/eslint.config.mjs +12 -0
  11. package/knip.json +3 -1
  12. package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
  13. package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
  14. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
  15. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
  16. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
  17. package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/openapi.yaml +4126 -959
  20. package/package.json +5 -1
  21. package/scripts/generate-openapi.ts +52 -4
  22. package/scripts/sync-llm-catalog.ts +165 -0
  23. package/scripts/sync-web-search-catalog.ts +107 -0
  24. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  25. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  26. package/src/__tests__/annotate-risk-options.test.ts +291 -0
  27. package/src/__tests__/anthropic-provider.test.ts +92 -2
  28. package/src/__tests__/app-control-flow.test.ts +7 -0
  29. package/src/__tests__/approval-cascade.test.ts +8 -16
  30. package/src/__tests__/approval-routes-http.test.ts +6 -0
  31. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  32. package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
  33. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  34. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  35. package/src/__tests__/btw-routes.test.ts +1 -0
  36. package/src/__tests__/call-constants.test.ts +10 -1
  37. package/src/__tests__/call-controller.test.ts +127 -0
  38. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  39. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  40. package/src/__tests__/channel-policy.test.ts +12 -0
  41. package/src/__tests__/checker.test.ts +89 -0
  42. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
  43. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  44. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  45. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  46. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +345 -8
  48. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  49. package/src/__tests__/config-schema.test.ts +14 -3
  50. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  51. package/src/__tests__/config-set-route.test.ts +198 -0
  52. package/src/__tests__/config-watcher.test.ts +6 -0
  53. package/src/__tests__/contacts-tools.test.ts +51 -199
  54. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  55. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  56. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  57. package/src/__tests__/context-search-fanout.test.ts +20 -157
  58. package/src/__tests__/context-search-memory-source.test.ts +3 -26
  59. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  60. package/src/__tests__/context-search-types.test.ts +7 -2
  61. package/src/__tests__/context-window-manager.test.ts +389 -1
  62. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
  63. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  64. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
  65. package/src/__tests__/conversation-agent-loop.test.ts +3 -3
  66. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
  67. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  68. package/src/__tests__/conversation-error.test.ts +38 -0
  69. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  70. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  71. package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
  72. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  74. package/src/__tests__/conversation-process-callsite.test.ts +22 -7
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
  76. package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
  77. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  78. package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
  79. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  81. package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
  82. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
  83. package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
  84. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
  85. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  86. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  87. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  88. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  89. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  90. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  91. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  92. package/src/__tests__/filing-service.test.ts +25 -22
  93. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  94. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  95. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  96. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
  97. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  98. package/src/__tests__/heartbeat-service.test.ts +50 -233
  99. package/src/__tests__/history-repair.test.ts +89 -0
  100. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  101. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  102. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  103. package/src/__tests__/host-browser-routes.test.ts +325 -33
  104. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  105. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  106. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  107. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  108. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  109. package/src/__tests__/injector-chain.test.ts +24 -16
  110. package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
  111. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  112. package/src/__tests__/install-skill-routing.test.ts +2 -2
  113. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
  114. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  115. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  116. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  117. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  118. package/src/__tests__/llm-resolver.test.ts +46 -0
  119. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  120. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  121. package/src/__tests__/mcp-cli.test.ts +182 -220
  122. package/src/__tests__/mcp-health-check.test.ts +56 -27
  123. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  124. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  125. package/src/__tests__/notification-decision-fallback.test.ts +91 -0
  126. package/src/__tests__/notification-decision-strategy.test.ts +22 -0
  127. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  128. package/src/__tests__/oauth-cli.test.ts +38 -1888
  129. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  130. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  131. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  132. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  133. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  134. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  135. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  136. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  137. package/src/__tests__/plugin-types.test.ts +13 -11
  138. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  139. package/src/__tests__/profile-entry-status.test.ts +43 -0
  140. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  141. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  142. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  143. package/src/__tests__/relay-server.test.ts +164 -2
  144. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  145. package/src/__tests__/schedule-retry.test.ts +56 -4
  146. package/src/__tests__/schedule-routes.test.ts +104 -0
  147. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  148. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  149. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  150. package/src/__tests__/scheduler-wake.test.ts +0 -63
  151. package/src/__tests__/secret-allowlist.test.ts +1 -0
  152. package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
  153. package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
  154. package/src/__tests__/secret-response-routing.test.ts +7 -5
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  156. package/src/__tests__/server-history-render.test.ts +82 -0
  157. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  158. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  159. package/src/__tests__/skill-include-graph.test.ts +31 -0
  160. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  161. package/src/__tests__/skill-load-tool.test.ts +42 -16
  162. package/src/__tests__/skills.test.ts +39 -0
  163. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  164. package/src/__tests__/suggestion-routes.test.ts +3 -3
  165. package/src/__tests__/sync-message-contract.test.ts +63 -0
  166. package/src/__tests__/task-scheduler.test.ts +88 -23
  167. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
  168. package/src/__tests__/tool-executor.test.ts +155 -0
  169. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  170. package/src/__tests__/usage-cli.test.ts +11 -73
  171. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  172. package/src/__tests__/vercel-config.test.ts +168 -0
  173. package/src/__tests__/voice-session-bridge.test.ts +3 -0
  174. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  175. package/src/__tests__/web-search.test.ts +303 -2
  176. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  177. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  178. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
  179. package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
  180. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  181. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  182. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  183. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  184. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  185. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  186. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  187. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +15 -27
  188. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  189. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  190. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  191. package/src/acp/resolve-agent.test.ts +25 -0
  192. package/src/acp/resolve-agent.ts +13 -2
  193. package/src/acp/session-manager.ts +14 -0
  194. package/src/agent/loop.ts +11 -0
  195. package/src/approvals/guardian-decision-primitive.ts +0 -13
  196. package/src/approvals/guardian-request-resolvers.ts +19 -102
  197. package/src/calls/call-constants.ts +5 -8
  198. package/src/calls/call-controller.ts +130 -67
  199. package/src/calls/relay-server.ts +42 -1
  200. package/src/calls/relay-setup-router.ts +36 -0
  201. package/src/calls/types.ts +1 -0
  202. package/src/calls/voice-session-bridge.ts +24 -5
  203. package/src/channels/config.ts +14 -1
  204. package/src/channels/types.ts +1 -0
  205. package/src/cli/AGENTS.md +164 -4
  206. package/src/cli/__tests__/notifications.test.ts +54 -0
  207. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  208. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  209. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  210. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  211. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  212. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  213. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  214. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  215. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  216. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  217. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  218. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  219. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  220. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  221. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  222. package/src/cli/commands/__tests__/status.test.ts +249 -0
  223. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  224. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  225. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  226. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  227. package/src/cli/commands/attachment.ts +8 -3
  228. package/src/cli/commands/audit.ts +95 -64
  229. package/src/cli/commands/auth.ts +61 -58
  230. package/src/cli/commands/avatar.ts +276 -390
  231. package/src/cli/commands/backup.ts +409 -505
  232. package/src/cli/commands/bash.ts +9 -5
  233. package/src/cli/commands/browser.ts +28 -9
  234. package/src/cli/commands/cache.ts +9 -4
  235. package/src/cli/commands/changelog.ts +414 -0
  236. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  237. package/src/cli/commands/clients.ts +8 -3
  238. package/src/cli/commands/completions.ts +9 -9
  239. package/src/cli/commands/config.ts +102 -72
  240. package/src/cli/commands/contacts.ts +575 -696
  241. package/src/cli/commands/conversations-defer.ts +17 -69
  242. package/src/cli/commands/conversations-import.ts +90 -253
  243. package/src/cli/commands/conversations.ts +346 -436
  244. package/src/cli/commands/credential-execution.ts +9 -6
  245. package/src/cli/commands/credentials.ts +456 -736
  246. package/src/cli/commands/domain.ts +128 -206
  247. package/src/cli/commands/email.ts +606 -794
  248. package/src/cli/commands/gateway.ts +8 -1
  249. package/src/cli/commands/image-generation.ts +157 -205
  250. package/src/cli/commands/inference-providers.ts +352 -0
  251. package/src/cli/commands/inference-session.ts +415 -0
  252. package/src/cli/commands/inference.ts +87 -65
  253. package/src/cli/commands/keys.ts +8 -3
  254. package/src/cli/commands/mcp.ts +103 -287
  255. package/src/cli/commands/memory-v2.ts +163 -517
  256. package/src/cli/commands/notifications.ts +33 -7
  257. package/src/cli/commands/oauth/apps.ts +292 -261
  258. package/src/cli/commands/oauth/connect.ts +182 -345
  259. package/src/cli/commands/oauth/disconnect.ts +16 -215
  260. package/src/cli/commands/oauth/index.ts +49 -45
  261. package/src/cli/commands/oauth/mode.ts +43 -199
  262. package/src/cli/commands/oauth/ping.ts +17 -125
  263. package/src/cli/commands/oauth/providers.ts +732 -921
  264. package/src/cli/commands/oauth/request.ts +60 -350
  265. package/src/cli/commands/oauth/shared.ts +11 -121
  266. package/src/cli/commands/oauth/status.ts +31 -121
  267. package/src/cli/commands/oauth/token.ts +13 -55
  268. package/src/cli/commands/pending.ts +19 -10
  269. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  270. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  271. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  272. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  273. package/src/cli/commands/platform/connect.ts +16 -80
  274. package/src/cli/commands/platform/disconnect.ts +14 -112
  275. package/src/cli/commands/platform/index.ts +177 -246
  276. package/src/cli/commands/routes.ts +153 -336
  277. package/src/cli/commands/sequence.ts +316 -360
  278. package/src/cli/commands/skills.ts +449 -671
  279. package/src/cli/commands/status.ts +58 -37
  280. package/src/cli/commands/stt.ts +94 -262
  281. package/src/cli/commands/task.ts +14 -40
  282. package/src/cli/commands/trust.ts +8 -3
  283. package/src/cli/commands/tts.ts +162 -167
  284. package/src/cli/commands/ui.ts +35 -42
  285. package/src/cli/commands/usage.ts +188 -126
  286. package/src/cli/commands/watchers.ts +8 -3
  287. package/src/cli/commands/webhooks.ts +99 -193
  288. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  289. package/src/cli/lib/daemon-credential-client.ts +4 -5
  290. package/src/cli/lib/nested-value.ts +44 -0
  291. package/src/cli/lib/open-browser.ts +36 -0
  292. package/src/cli/lib/register-command.ts +19 -0
  293. package/src/cli/lib/time-ago.ts +34 -0
  294. package/src/cli/program.ts +2 -4
  295. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  296. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  297. package/src/cli/utils/conversation-id.ts +30 -0
  298. package/src/cli/utils/parse-duration.ts +41 -0
  299. package/src/config/acp-defaults.test.ts +5 -1
  300. package/src/config/acp-defaults.ts +11 -4
  301. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  302. package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
  303. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  304. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  305. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  306. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  307. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  308. package/src/config/bundled-tool-registry.ts +0 -2
  309. package/src/config/feature-flag-registry.json +17 -17
  310. package/src/config/llm-resolver.ts +16 -1
  311. package/src/config/loader.ts +148 -33
  312. package/src/config/raw-config-utils.ts +2 -30
  313. package/src/config/schema.ts +4 -0
  314. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  315. package/src/config/schemas/call-site-catalog.ts +29 -7
  316. package/src/config/schemas/llm-request-logs.ts +57 -0
  317. package/src/config/schemas/llm.ts +52 -2
  318. package/src/config/schemas/memory-retrospective.ts +48 -0
  319. package/src/config/schemas/memory-v2.ts +33 -2
  320. package/src/config/schemas/memory.ts +4 -0
  321. package/src/config/schemas/services.ts +15 -12
  322. package/src/config/seed-inference-profiles.ts +195 -134
  323. package/src/contacts/contact-store.ts +0 -61
  324. package/src/context/window-manager.ts +191 -5
  325. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
  326. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  327. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  328. package/src/daemon/approval-generators.ts +23 -29
  329. package/src/daemon/config-watcher.ts +2 -0
  330. package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
  331. package/src/daemon/conversation-agent-loop.ts +140 -107
  332. package/src/daemon/conversation-error.ts +21 -0
  333. package/src/daemon/conversation-lifecycle.ts +68 -13
  334. package/src/daemon/conversation-process.ts +36 -19
  335. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  336. package/src/daemon/conversation-slash.ts +175 -23
  337. package/src/daemon/conversation-store.ts +17 -10
  338. package/src/daemon/conversation-surfaces.ts +92 -26
  339. package/src/daemon/conversation-tool-setup.ts +33 -19
  340. package/src/daemon/conversation.ts +49 -10
  341. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  342. package/src/daemon/guardian-action-generators.ts +7 -22
  343. package/src/daemon/handlers/config-model.ts +8 -126
  344. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  345. package/src/daemon/handlers/config-vercel.ts +3 -1
  346. package/src/daemon/handlers/shared.ts +26 -0
  347. package/src/daemon/handlers/skills.ts +84 -5
  348. package/src/daemon/history-repair.ts +33 -6
  349. package/src/daemon/host-app-control-proxy.ts +44 -19
  350. package/src/daemon/host-bash-proxy.ts +85 -158
  351. package/src/daemon/host-browser-proxy.ts +97 -36
  352. package/src/daemon/host-cu-proxy.ts +1 -1
  353. package/src/daemon/host-file-proxy.ts +1 -1
  354. package/src/daemon/host-proxy-base.ts +13 -1
  355. package/src/daemon/host-proxy-preactivation.ts +25 -1
  356. package/src/daemon/host-transfer-proxy.ts +2 -2
  357. package/src/daemon/identity-helpers.ts +19 -0
  358. package/src/daemon/lifecycle.ts +128 -114
  359. package/src/daemon/meet-host-supervisor.ts +15 -15
  360. package/src/daemon/memory-v2-startup.ts +62 -14
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/bookmarks.ts +18 -0
  363. package/src/daemon/message-types/conversations.ts +12 -9
  364. package/src/daemon/message-types/messages.ts +28 -2
  365. package/src/daemon/message-types/sync.ts +60 -0
  366. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  367. package/src/daemon/pkb-reminder-builder.ts +21 -7
  368. package/src/daemon/process-message.ts +56 -23
  369. package/src/daemon/server.ts +23 -18
  370. package/src/daemon/shutdown-handlers.ts +0 -2
  371. package/src/daemon/tool-setup-types.ts +9 -0
  372. package/src/daemon/tool-side-effects.ts +6 -4
  373. package/src/daemon/wake-target-adapter.ts +11 -0
  374. package/src/documents/document-store.ts +35 -1
  375. package/src/export/transcript-formatter.ts +61 -2
  376. package/src/filing/filing-service.ts +42 -56
  377. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  378. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  379. package/src/heartbeat/heartbeat-service.ts +149 -128
  380. package/src/home/__tests__/feed-types.test.ts +63 -131
  381. package/src/home/__tests__/feed-writer.test.ts +77 -278
  382. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  383. package/src/home/feed-types.ts +19 -73
  384. package/src/home/feed-writer.ts +25 -156
  385. package/src/home/post-connect-feed.ts +1 -3
  386. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  387. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  388. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  389. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  390. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  391. package/src/ipc/assistant-server.ts +148 -42
  392. package/src/ipc/cli-client.ts +370 -50
  393. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  394. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  395. package/src/ipc/skill-routes/events.ts +30 -3
  396. package/src/ipc/skill-server.ts +99 -42
  397. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  398. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  399. package/src/live-voice/live-voice-session-manager.ts +11 -4
  400. package/src/live-voice/live-voice-session.ts +14 -6
  401. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  402. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  403. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  404. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  405. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +10 -57
  406. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  407. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  408. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  409. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  412. package/src/memory/bookmark-crud.ts +179 -0
  413. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  414. package/src/memory/context-search/agent-protocol.ts +5 -1
  415. package/src/memory/context-search/agent-runner.ts +60 -85
  416. package/src/memory/context-search/limits.ts +1 -4
  417. package/src/memory/context-search/search.ts +23 -113
  418. package/src/memory/context-search/sources/conversations.ts +18 -6
  419. package/src/memory/context-search/sources/memory-v2.ts +40 -31
  420. package/src/memory/context-search/sources/memory.ts +9 -2
  421. package/src/memory/context-search/sources/workspace.ts +13 -10
  422. package/src/memory/context-search/types.ts +1 -1
  423. package/src/memory/conversation-bootstrap.ts +11 -0
  424. package/src/memory/conversation-crud.ts +312 -10
  425. package/src/memory/conversation-queries.ts +9 -5
  426. package/src/memory/conversation-title-service.ts +1 -0
  427. package/src/memory/conversation-types.ts +16 -0
  428. package/src/memory/db-init.ts +14 -0
  429. package/src/memory/embedding-backend.ts +2 -1
  430. package/src/memory/embedding-runtime-manager.ts +1 -2
  431. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
  432. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
  433. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  434. package/src/memory/graph/conversation-graph-memory.ts +108 -14
  435. package/src/memory/graph/extraction.ts +4 -0
  436. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  437. package/src/memory/graph/graph-search.test.ts +6 -5
  438. package/src/memory/graph/graph-search.ts +3 -4
  439. package/src/memory/graph/retriever.test.ts +12 -7
  440. package/src/memory/graph/retriever.ts +4 -5
  441. package/src/memory/graph/tool-handlers.ts +20 -11
  442. package/src/memory/graph/tools.ts +48 -9
  443. package/src/memory/indexer.ts +18 -2
  444. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
  445. package/src/memory/jobs/embed-concept-page.ts +261 -89
  446. package/src/memory/jobs-store.ts +51 -1
  447. package/src/memory/jobs-worker.ts +60 -7
  448. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  449. package/src/memory/llm-request-log-source-local.ts +26 -0
  450. package/src/memory/llm-request-log-source.ts +97 -0
  451. package/src/memory/llm-request-log-store.ts +1 -1
  452. package/src/memory/memory-retrospective-constants.ts +13 -0
  453. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  454. package/src/memory/memory-retrospective-job.ts +351 -0
  455. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  456. package/src/memory/memory-retrospective-state.ts +162 -0
  457. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  458. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  459. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  460. package/src/memory/message-content.ts +38 -1
  461. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  462. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  463. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  464. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  465. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  466. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  467. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  468. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  469. package/src/memory/migrations/243-provider-connections.ts +68 -0
  470. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  471. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  472. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  473. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  474. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  475. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  476. package/src/memory/migrations/index.ts +7 -0
  477. package/src/memory/pkb/pkb-search.test.ts +6 -5
  478. package/src/memory/pkb/pkb-search.ts +4 -5
  479. package/src/memory/published-pages-store.ts +16 -0
  480. package/src/memory/qdrant-client.ts +3 -0
  481. package/src/memory/schema/bookmarks.ts +38 -0
  482. package/src/memory/schema/conversations.ts +2 -0
  483. package/src/memory/schema/index.ts +2 -0
  484. package/src/memory/schema/inference.ts +29 -0
  485. package/src/memory/schema/memory-core.ts +9 -0
  486. package/src/memory/search/semantic.ts +5 -9
  487. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  488. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  489. package/src/memory/v2/__tests__/activation.test.ts +46 -9
  490. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  491. package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
  492. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  493. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  494. package/src/memory/v2/__tests__/injection.test.ts +768 -33
  495. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  496. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  497. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  498. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  499. package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
  500. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  501. package/src/memory/v2/__tests__/router.test.ts +516 -0
  502. package/src/memory/v2/__tests__/sim.test.ts +163 -8
  503. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  504. package/src/memory/v2/__tests__/static-context.test.ts +8 -35
  505. package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
  506. package/src/memory/v2/activation-store.ts +34 -5
  507. package/src/memory/v2/activation.ts +40 -27
  508. package/src/memory/v2/backfill-jobs.ts +17 -84
  509. package/src/memory/v2/consolidation-job.ts +92 -86
  510. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  511. package/src/memory/v2/injection.ts +466 -115
  512. package/src/memory/v2/migration.ts +117 -20
  513. package/src/memory/v2/page-index.ts +191 -0
  514. package/src/memory/v2/page-store.ts +42 -0
  515. package/src/memory/v2/prompts/consolidation.ts +14 -7
  516. package/src/memory/v2/prompts/router.ts +192 -0
  517. package/src/memory/v2/qdrant.ts +307 -133
  518. package/src/memory/v2/reranker.ts +14 -7
  519. package/src/memory/v2/router.ts +322 -0
  520. package/src/memory/v2/sim.ts +88 -34
  521. package/src/memory/v2/skill-store.ts +118 -29
  522. package/src/memory/v2/static-context.ts +20 -17
  523. package/src/memory/v2/sweep-job.ts +127 -102
  524. package/src/memory/v2/types.ts +16 -5
  525. package/src/memory/validation.ts +13 -0
  526. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  527. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  528. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  529. package/src/notifications/adapters/platform.ts +171 -0
  530. package/src/notifications/conversation-pairing.ts +2 -2
  531. package/src/notifications/copy-composer.ts +61 -12
  532. package/src/notifications/decision-engine.ts +46 -0
  533. package/src/notifications/destination-resolver.ts +21 -0
  534. package/src/notifications/emit-signal.ts +28 -1
  535. package/src/notifications/home-feed-side-effect.ts +111 -0
  536. package/src/notifications/signal.ts +5 -0
  537. package/src/permissions/checker.ts +12 -0
  538. package/src/permissions/gateway-threshold-reader.ts +116 -8
  539. package/src/permissions/ipc-risk-types.ts +2 -0
  540. package/src/permissions/prompter.ts +86 -96
  541. package/src/permissions/secret-prompter.ts +31 -31
  542. package/src/plugin-api/index.ts +13 -0
  543. package/src/plugin-api/package.json +12 -0
  544. package/src/plugin-api/types.ts +62 -0
  545. package/src/plugins/defaults/injectors.ts +20 -5
  546. package/src/plugins/external-plugin-loader.ts +294 -0
  547. package/src/plugins/types.ts +46 -30
  548. package/src/plugins/user-loader.ts +64 -41
  549. package/src/proactive-artifact/job.test.ts +63 -8
  550. package/src/proactive-artifact/job.ts +20 -2
  551. package/src/proactive-artifact/message-copy.ts +18 -1
  552. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  553. package/src/proactive-artifact/trigger-state.ts +4 -0
  554. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  555. package/src/prompts/system-prompt.ts +22 -1
  556. package/src/prompts/templates/SOUL.md +13 -28
  557. package/src/prompts/update-bulletin-job.ts +61 -73
  558. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  559. package/src/providers/__tests__/inference.test.ts +288 -0
  560. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  561. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  562. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  563. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  564. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  565. package/src/providers/anthropic/client.ts +95 -26
  566. package/src/providers/call-site-routing.ts +94 -16
  567. package/src/providers/connection-resolution.ts +163 -0
  568. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  569. package/src/providers/inference/adapter-factory.ts +173 -0
  570. package/src/providers/inference/auth.ts +112 -0
  571. package/src/providers/inference/backfill.ts +196 -0
  572. package/src/providers/inference/connections.ts +356 -0
  573. package/src/providers/inference/resolve-auth.ts +65 -0
  574. package/src/providers/model-catalog.ts +104 -6
  575. package/src/providers/openai/responses-provider.ts +4 -2
  576. package/src/providers/provider-env-vars.ts +17 -7
  577. package/src/providers/provider-secret-catalog.ts +49 -30
  578. package/src/providers/provider-send-message.ts +41 -20
  579. package/src/providers/registry.ts +143 -159
  580. package/src/providers/retry.ts +18 -10
  581. package/src/providers/search-provider-catalog.ts +121 -0
  582. package/src/runtime/AGENTS.md +18 -5
  583. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  584. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  585. package/src/runtime/actor-trust-resolver.ts +32 -10
  586. package/src/runtime/agent-wake.ts +35 -6
  587. package/src/runtime/assistant-event-hub.ts +3 -85
  588. package/src/runtime/auth/route-policy.ts +304 -8
  589. package/src/runtime/auth/same-actor.ts +2 -0
  590. package/src/runtime/background-job-runner.ts +339 -0
  591. package/src/runtime/btw-sidechain.ts +1 -0
  592. package/src/runtime/channel-approvals.ts +3 -2
  593. package/src/runtime/guardian-reply-router.ts +0 -10
  594. package/src/runtime/http-router.ts +36 -1
  595. package/src/runtime/http-server.ts +31 -5
  596. package/src/runtime/http-types.ts +2 -0
  597. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  598. package/src/runtime/middleware/request-logger.ts +62 -1
  599. package/src/runtime/pending-interactions.ts +19 -15
  600. package/src/runtime/pre-first-message-gate.ts +83 -0
  601. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  602. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  603. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  604. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  605. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  606. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  607. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  608. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
  609. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  610. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  611. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  612. package/src/runtime/routes/acp-routes.ts +10 -8
  613. package/src/runtime/routes/app-management-routes.ts +228 -3
  614. package/src/runtime/routes/approval-routes.ts +7 -21
  615. package/src/runtime/routes/audit-routes.ts +43 -0
  616. package/src/runtime/routes/auth-routes.ts +72 -0
  617. package/src/runtime/routes/avatar-routes.ts +273 -20
  618. package/src/runtime/routes/backup-routes.ts +406 -2
  619. package/src/runtime/routes/bookmark-routes.ts +154 -0
  620. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  621. package/src/runtime/routes/consolidation-routes.ts +8 -9
  622. package/src/runtime/routes/contact-routes.ts +0 -160
  623. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  624. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  625. package/src/runtime/routes/conversation-query-routes.ts +373 -82
  626. package/src/runtime/routes/conversation-routes.ts +31 -10
  627. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  628. package/src/runtime/routes/credential-routes.ts +540 -0
  629. package/src/runtime/routes/debug-bash-routes.ts +2 -0
  630. package/src/runtime/routes/debug-routes.ts +2 -2
  631. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  632. package/src/runtime/routes/domain-routes.ts +167 -0
  633. package/src/runtime/routes/email-routes.ts +603 -0
  634. package/src/runtime/routes/errors.ts +2 -2
  635. package/src/runtime/routes/events-routes.ts +192 -0
  636. package/src/runtime/routes/filing-routes.ts +2 -3
  637. package/src/runtime/routes/home-feed-routes.ts +6 -78
  638. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  639. package/src/runtime/routes/host-browser-routes.ts +103 -22
  640. package/src/runtime/routes/http-adapter.ts +2 -0
  641. package/src/runtime/routes/identity-routes.ts +5 -0
  642. package/src/runtime/routes/image-generation-routes.ts +99 -0
  643. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  644. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  645. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  646. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
  647. package/src/runtime/routes/index.ts +36 -0
  648. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  649. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  650. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  651. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  652. package/src/runtime/routes/inference-send-routes.ts +115 -0
  653. package/src/runtime/routes/integrations/twilio.ts +1 -0
  654. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  655. package/src/runtime/routes/memory-item-routes.test.ts +3 -9
  656. package/src/runtime/routes/memory-item-routes.ts +5 -6
  657. package/src/runtime/routes/memory-v2-routes.ts +105 -404
  658. package/src/runtime/routes/notification-routes.ts +2 -0
  659. package/src/runtime/routes/oauth-apps.ts +112 -7
  660. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  661. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  662. package/src/runtime/routes/oauth-providers.ts +298 -8
  663. package/src/runtime/routes/platform-routes.ts +336 -0
  664. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  665. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  666. package/src/runtime/routes/playground/state.ts +2 -1
  667. package/src/runtime/routes/publish-routes.ts +221 -0
  668. package/src/runtime/routes/schedule-routes.ts +82 -0
  669. package/src/runtime/routes/sequence-routes.ts +291 -0
  670. package/src/runtime/routes/settings-routes.ts +2 -10
  671. package/src/runtime/routes/skills-routes.ts +31 -1
  672. package/src/runtime/routes/stt-routes.ts +240 -3
  673. package/src/runtime/routes/surface-action-routes.ts +43 -7
  674. package/src/runtime/routes/tts-routes.ts +67 -0
  675. package/src/runtime/routes/types.ts +32 -0
  676. package/src/runtime/routes/user-routes-cli.ts +243 -0
  677. package/src/runtime/routes/webhook-routes.ts +165 -0
  678. package/src/runtime/sync/resource-sync-events.ts +25 -0
  679. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  680. package/src/runtime/sync/sync-publisher.ts +21 -0
  681. package/src/schedule/scheduler.ts +200 -123
  682. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  683. package/src/security/secret-patterns.ts +3 -0
  684. package/src/sequence/engine.ts +38 -40
  685. package/src/skills/include-graph.ts +35 -13
  686. package/src/subagent/manager.ts +20 -15
  687. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  688. package/src/tools/browser/browser-execution.ts +15 -4
  689. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  690. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  691. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  692. package/src/tools/browser/cdp-client/factory.ts +66 -5
  693. package/src/tools/browser/runtime-check.ts +77 -0
  694. package/src/tools/document/document-tool.ts +20 -0
  695. package/src/tools/executor.ts +18 -2
  696. package/src/tools/memory/register.test.ts +10 -8
  697. package/src/tools/memory/register.ts +9 -1
  698. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  699. package/src/tools/network/web-search.ts +280 -37
  700. package/src/tools/permission-checker.ts +28 -5
  701. package/src/tools/skills/load.ts +24 -20
  702. package/src/tools/subagent/spawn.ts +3 -3
  703. package/src/tools/terminal/shell.ts +44 -0
  704. package/src/tools/tool-name-aliases.ts +19 -0
  705. package/src/tools/types.ts +19 -1
  706. package/src/usage/attribution.ts +3 -2
  707. package/src/util/pricing.ts +86 -160
  708. package/src/watcher/__tests__/engine.test.ts +301 -0
  709. package/src/watcher/constants.ts +7 -0
  710. package/src/watcher/engine.ts +90 -90
  711. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  712. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  713. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  714. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
  715. package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
  716. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
  717. package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
  718. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  719. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  720. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  721. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  722. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  723. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  724. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  725. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  726. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  727. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  728. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  729. package/src/workspace/migrations/registry.ts +28 -0
  730. package/src/workspace/migrations/runner.ts +13 -2
  731. package/src/workspace/migrations/types.ts +13 -3
  732. package/src/workspace/provider-commit-message-generator.ts +3 -2
  733. package/src/__tests__/context-search-pkb-source.test.ts +0 -492
  734. package/src/__tests__/credentials-cli.test.ts +0 -1225
  735. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  736. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  737. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  738. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  739. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  740. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  741. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  742. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  743. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  744. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  745. package/src/cli/commands/autonomy.ts +0 -365
  746. package/src/cli/commands/memory.ts +0 -424
  747. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -1201
  748. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  749. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  750. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  751. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  752. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  753. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  754. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  755. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  756. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  757. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  758. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  759. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  760. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  761. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  762. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  763. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  764. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  765. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  766. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  767. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  768. package/src/home/assistant-feed-authoring.ts +0 -135
  769. package/src/home/emit-feed-event.ts +0 -169
  770. package/src/home/feed-scheduler.ts +0 -281
  771. package/src/home/platform-gmail-digest.ts +0 -163
  772. package/src/home/rewrite-command-preview.ts +0 -66
  773. package/src/home/rewrite-feed-title.ts +0 -58
  774. package/src/home/rollup-producer.ts +0 -426
  775. package/src/memory/admin.ts +0 -326
  776. package/src/memory/context-search/sources/pkb.ts +0 -477
  777. package/src/memory/graph/compaction.ts +0 -299
  778. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -9,9 +9,10 @@
9
9
  * deterministic fallback for long AF_UNIX paths.
10
10
  */
11
11
 
12
- import { connect, type Socket } from "node:net";
12
+ import { Socket } from "node:net";
13
13
 
14
14
  import { getLogger } from "../util/logger.js";
15
+ import { IpcFrameReader, writeMessage } from "./ipc-framing.js";
15
16
  import { getAssistantSocketPath } from "./socket-path.js";
16
17
 
17
18
  const log = getLogger("cli-ipc-client");
@@ -20,12 +21,6 @@ const log = getLogger("cli-ipc-client");
20
21
  // Types (mirror cli-server.ts protocol)
21
22
  // ---------------------------------------------------------------------------
22
23
 
23
- type IpcRequest = {
24
- id: string;
25
- method: string;
26
- params?: Record<string, unknown>;
27
- };
28
-
29
24
  type IpcResponse = {
30
25
  id: string;
31
26
  result?: unknown;
@@ -74,10 +69,15 @@ export interface CliIpcCallResult<T = unknown> {
74
69
  export async function cliIpcCall<T = unknown>(
75
70
  method: string,
76
71
  params?: Record<string, unknown>,
77
- options?: { timeoutMs?: number },
72
+ options?: { timeoutMs?: number; signal?: AbortSignal },
78
73
  ): Promise<CliIpcCallResult<T>> {
74
+ if (options?.signal?.aborted) {
75
+ throw options.signal.reason ?? new DOMException("Aborted", "AbortError");
76
+ }
77
+
79
78
  const socketPath = getAssistantSocketPath();
80
79
  const callTimeoutMs = options?.timeoutMs ?? DEFAULT_CALL_TIMEOUT_MS;
80
+ const opts = options; // alias used in the Promise callback below
81
81
 
82
82
  return new Promise<CliIpcCallResult<T>>((resolve) => {
83
83
  let settled = false;
@@ -99,20 +99,65 @@ export async function cliIpcCall<T = unknown>(
99
99
  );
100
100
  finish({
101
101
  ok: false,
102
- error: "Could not connect to assistant daemon. Is it running?",
102
+ error: `Could not connect to the assistant at ${socketPath}.\nRun \`assistant status\` to check, or \`assistant gateway start\` to start it.`,
103
103
  });
104
104
  }, CONNECT_TIMEOUT_MS);
105
105
 
106
- const socket: Socket = connect(socketPath);
106
+ // Create the socket without connecting first so error/close handlers are
107
+ // registered before initiating the connection. In Bun, socket errors can
108
+ // fire synchronously during connect(), before listeners added afterward.
109
+ const socket = new Socket();
107
110
  socket.unref();
108
111
 
109
- let buffer = "";
112
+ socket.on("error", (err) => {
113
+ const code = (err as NodeJS.ErrnoException).code;
114
+ log.debug({ err, code, method, socketPath }, "CLI IPC socket error");
115
+ finish({
116
+ ok: false,
117
+ error:
118
+ code === "ENOENT" || code === "ECONNREFUSED"
119
+ ? `Could not connect to the assistant at ${socketPath}.\nRun \`assistant status\` to check, or \`assistant gateway start\` to start it.`
120
+ : `Connection error: ${code ?? err.message}`,
121
+ });
122
+ });
123
+
124
+ socket.on("close", (hadError) => {
125
+ if (!settled) {
126
+ finish({
127
+ ok: false,
128
+ // hadError is true when close follows a socket error (e.g. ENOENT).
129
+ error: hadError
130
+ ? `Could not connect to the assistant at ${socketPath}.\nRun \`assistant status\` to check, or \`assistant gateway start\` to start it.`
131
+ : "Connection closed before response",
132
+ });
133
+ }
134
+ });
135
+
110
136
  const reqId = crypto.randomUUID();
111
137
 
138
+ opts?.signal?.addEventListener("abort", () => {
139
+ finish({ ok: false, error: "Request aborted" });
140
+ }, { once: true });
141
+
142
+ const reader = new IpcFrameReader(
143
+ (envelope) => {
144
+ if (envelope.id !== reqId) return;
145
+ const msg = envelope as IpcResponse;
146
+ if (msg.error) {
147
+ finish({ ok: false, error: msg.error,
148
+ ...(msg.statusCode != null && { statusCode: msg.statusCode }),
149
+ ...(msg.errorCode != null && { errorCode: msg.errorCode }),
150
+ ...(msg.errorDetails != null && { errorDetails: msg.errorDetails }) });
151
+ } else {
152
+ finish({ ok: true, result: msg.result as T });
153
+ }
154
+ },
155
+ (err) => finish({ ok: false, error: err.message }),
156
+ );
157
+
112
158
  socket.on("connect", () => {
113
159
  clearTimeout(connectTimer);
114
- const req: IpcRequest = { id: reqId, method, params };
115
- socket.write(JSON.stringify(req) + "\n");
160
+ writeMessage(socket, { id: reqId, method, params });
116
161
 
117
162
  callTimer = setTimeout(() => {
118
163
  log.debug(
@@ -123,61 +168,336 @@ export async function cliIpcCall<T = unknown>(
123
168
  }, callTimeoutMs);
124
169
 
125
170
  socket.on("data", (chunk) => {
126
- buffer += chunk.toString();
127
- let newlineIdx: number;
128
- while ((newlineIdx = buffer.indexOf("\n")) !== -1) {
129
- const line = buffer.slice(0, newlineIdx).trim();
130
- buffer = buffer.slice(newlineIdx + 1);
131
- if (!line) continue;
132
-
133
- try {
134
- const msg = JSON.parse(line) as IpcResponse;
135
- if (msg.id === reqId) {
136
- if (msg.error) {
137
- finish({
138
- ok: false,
139
- error: msg.error,
140
- ...(msg.statusCode !== undefined && {
141
- statusCode: msg.statusCode,
142
- }),
143
- ...(msg.errorCode !== undefined && {
144
- errorCode: msg.errorCode,
145
- }),
146
- ...(msg.errorDetails !== undefined && {
147
- errorDetails: msg.errorDetails,
148
- }),
149
- });
150
- } else {
151
- finish({ ok: true, result: msg.result as T });
152
- }
153
- return;
154
- }
155
- } catch {
156
- // Ignore malformed lines
157
- }
158
- }
171
+ reader.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
159
172
  });
160
173
  });
161
174
 
175
+ socket.connect(socketPath);
176
+ });
177
+ }
178
+
179
+ // ---------------------------------------------------------------------------
180
+ // Binary one-shot client
181
+ // ---------------------------------------------------------------------------
182
+
183
+ const DEFAULT_BINARY_TIMEOUT_MS = 60_000;
184
+
185
+ /**
186
+ * One-shot IPC call that expects a single binary frame response.
187
+ *
188
+ * Use when the route returns an IpcBinaryResponse (content-length header
189
+ * + one binary data frame). Returns the headers and raw bytes.
190
+ *
191
+ * @example
192
+ * const r = await cliIpcCallBinary("export_file", { id: "abc" });
193
+ * if (!r.ok) return exitFromIpcResult(r, cmd);
194
+ * fs.writeFileSync("out.bin", Buffer.from(r.bytes));
195
+ */
196
+ export async function cliIpcCallBinary(
197
+ method: string,
198
+ params?: Record<string, unknown>,
199
+ opts?: { timeoutMs?: number; signal?: AbortSignal },
200
+ ): Promise<
201
+ | { ok: true; headers: Record<string, string>; bytes: Uint8Array }
202
+ | { ok: false; error: string; statusCode?: number; errorCode?: string; errorDetails?: unknown }
203
+ > {
204
+ if (opts?.signal?.aborted) {
205
+ throw opts.signal.reason ?? new DOMException("Aborted", "AbortError");
206
+ }
207
+
208
+ const socketPath = getAssistantSocketPath();
209
+ const callTimeoutMs = opts?.timeoutMs ?? DEFAULT_BINARY_TIMEOUT_MS;
210
+
211
+ return new Promise((resolve) => {
212
+ let settled = false;
213
+ let callTimer: ReturnType<typeof setTimeout> | undefined;
214
+
215
+ const finish = (
216
+ result:
217
+ | { ok: true; headers: Record<string, string>; bytes: Uint8Array }
218
+ | { ok: false; error: string; statusCode?: number; errorCode?: string; errorDetails?: unknown },
219
+ ) => {
220
+ if (settled) return;
221
+ settled = true;
222
+ clearTimeout(connectTimer);
223
+ if (callTimer) clearTimeout(callTimer);
224
+ socket.destroy();
225
+ resolve(result);
226
+ };
227
+
228
+ const connectTimer = setTimeout(() => {
229
+ log.debug({ method, socketPath, timeoutMs: CONNECT_TIMEOUT_MS }, "CLI IPC binary connect timed out");
230
+ finish({ ok: false, error: `Could not connect to the assistant at ${socketPath}.\nRun \`assistant status\` to check, or \`assistant gateway start\` to start it.` });
231
+ }, CONNECT_TIMEOUT_MS);
232
+
233
+ const socket = new Socket();
234
+ socket.unref();
235
+
162
236
  socket.on("error", (err) => {
163
237
  const code = (err as NodeJS.ErrnoException).code;
164
- log.debug({ err, code, method, socketPath }, "CLI IPC socket error");
238
+ log.debug({ err, code, method, socketPath }, "CLI IPC binary socket error");
165
239
  finish({
166
240
  ok: false,
167
241
  error:
168
242
  code === "ENOENT" || code === "ECONNREFUSED"
169
- ? "Could not connect to assistant daemon. Is it running?"
243
+ ? `Could not connect to the assistant at ${socketPath}.\nRun \`assistant status\` to check, or \`assistant gateway start\` to start it.`
170
244
  : `Connection error: ${code ?? err.message}`,
171
245
  });
172
246
  });
173
247
 
174
- socket.on("close", () => {
248
+ socket.on("close", (hadError) => {
175
249
  if (!settled) {
176
250
  finish({
177
251
  ok: false,
178
- error: "Connection closed before response",
252
+ error: hadError
253
+ ? `Could not connect to the assistant at ${socketPath}.\nRun \`assistant status\` to check, or \`assistant gateway start\` to start it.`
254
+ : "Connection closed before response",
179
255
  });
180
256
  }
181
257
  });
258
+
259
+ const reqId = crypto.randomUUID();
260
+
261
+ opts?.signal?.addEventListener("abort", () => {
262
+ finish({ ok: false, error: "Request aborted" });
263
+ }, { once: true });
264
+
265
+ const reader = new IpcFrameReader(
266
+ (envelope, binary) => {
267
+ if (envelope.id !== reqId) return;
268
+ const msg = envelope as IpcResponse;
269
+ if (msg.error) {
270
+ finish({ ok: false, error: msg.error,
271
+ ...(msg.statusCode != null && { statusCode: msg.statusCode }),
272
+ ...(msg.errorCode != null && { errorCode: msg.errorCode }),
273
+ ...(msg.errorDetails != null && { errorDetails: msg.errorDetails }) });
274
+ } else if (binary === undefined) {
275
+ finish({ ok: false, error: "Expected binary frame but received JSON-only response" });
276
+ } else {
277
+ finish({ ok: true, headers: (envelope.headers ?? {}) as Record<string, string>, bytes: binary });
278
+ }
279
+ },
280
+ (err) => finish({ ok: false, error: err.message }),
281
+ );
282
+
283
+ socket.on("connect", () => {
284
+ clearTimeout(connectTimer);
285
+ writeMessage(socket, { id: reqId, method, params });
286
+
287
+ callTimer = setTimeout(() => {
288
+ log.debug({ method, socketPath, timeoutMs: callTimeoutMs }, "CLI IPC binary call timed out");
289
+ finish({ ok: false, error: "Request timed out" });
290
+ }, callTimeoutMs);
291
+
292
+ socket.on("data", (chunk) => {
293
+ reader.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
294
+ });
295
+ });
296
+
297
+ socket.connect(socketPath);
182
298
  });
183
299
  }
300
+
301
+ // ---------------------------------------------------------------------------
302
+ // Streaming client
303
+ // ---------------------------------------------------------------------------
304
+
305
+ const DEFAULT_FIRST_BYTE_TIMEOUT_MS = 30_000;
306
+
307
+ /**
308
+ * Streaming IPC call. Returns a ReadableStream of binary chunks.
309
+ *
310
+ * The promise resolves once the opening envelope arrives (or fails). The
311
+ * stream body is delivered asynchronously afterward. Call abort() to
312
+ * cancel mid-stream — this sends a $cancel envelope to the server.
313
+ *
314
+ * No total timeout. Only a first-byte timeout (default 30s).
315
+ *
316
+ * @example
317
+ * const r = await cliIpcCallStream("export_stream", { id: "abc" });
318
+ * if (!r.ok) return exitFromIpcResult(r, cmd);
319
+ * for await (const chunk of r.body) process.stdout.write(chunk);
320
+ */
321
+ export async function cliIpcCallStream(
322
+ method: string,
323
+ params?: Record<string, unknown>,
324
+ opts?: { firstByteTimeoutMs?: number; signal?: AbortSignal },
325
+ ): Promise<
326
+ | { ok: true; headers: Record<string, string>; body: ReadableStream<Uint8Array>; abort: () => void }
327
+ | { ok: false; error: string; statusCode?: number; errorCode?: string; errorDetails?: unknown }
328
+ > {
329
+ if (opts?.signal?.aborted) {
330
+ throw opts.signal.reason ?? new DOMException("Aborted", "AbortError");
331
+ }
332
+
333
+ const socketPath = getAssistantSocketPath();
334
+ const firstByteTimeoutMs = opts?.firstByteTimeoutMs ?? DEFAULT_FIRST_BYTE_TIMEOUT_MS;
335
+
336
+ return new Promise((resolve) => {
337
+ let settled = false;
338
+ let firstByteTimer: ReturnType<typeof setTimeout> | undefined;
339
+ let streamController: ReadableStreamDefaultController<Uint8Array> | undefined;
340
+
341
+ const finishError = (
342
+ result: { ok: false; error: string; statusCode?: number; errorCode?: string; errorDetails?: unknown },
343
+ ) => {
344
+ if (settled) return;
345
+ settled = true;
346
+ clearTimeout(connectTimer);
347
+ clearTimeout(firstByteTimer);
348
+ socket.destroy();
349
+ resolve(result);
350
+ };
351
+
352
+ const abort = () => {
353
+ if (settled && streamController) {
354
+ streamController.error(new DOMException("Aborted", "AbortError"));
355
+ streamController = undefined;
356
+ }
357
+ if (!socket.destroyed) {
358
+ writeMessage(socket, {
359
+ id: crypto.randomUUID(),
360
+ method: "$cancel",
361
+ params: { targetId: reqId },
362
+ });
363
+ // Use end() not destroy() so the $cancel frame flushes before the FIN.
364
+ socket.end();
365
+ }
366
+ };
367
+
368
+ const connectTimer = setTimeout(() => {
369
+ log.debug({ method, socketPath, timeoutMs: CONNECT_TIMEOUT_MS }, "CLI IPC stream connect timed out");
370
+ finishError({ ok: false, error: `Could not connect to the assistant at ${socketPath}.\nRun \`assistant status\` to check, or \`assistant gateway start\` to start it.` });
371
+ }, CONNECT_TIMEOUT_MS);
372
+
373
+ const socket = new Socket();
374
+ socket.unref();
375
+
376
+ socket.on("error", (err) => {
377
+ const code = (err as NodeJS.ErrnoException).code;
378
+ log.debug({ err, code, method, socketPath }, "CLI IPC stream socket error");
379
+ if (!settled) {
380
+ finishError({
381
+ ok: false,
382
+ error:
383
+ code === "ENOENT" || code === "ECONNREFUSED"
384
+ ? `Could not connect to the assistant at ${socketPath}.\nRun \`assistant status\` to check, or \`assistant gateway start\` to start it.`
385
+ : `Connection error: ${code ?? err.message}`,
386
+ });
387
+ } else {
388
+ streamController?.error(err);
389
+ streamController = undefined;
390
+ }
391
+ });
392
+
393
+ socket.on("close", (hadError) => {
394
+ if (!settled) {
395
+ finishError({
396
+ ok: false,
397
+ error: hadError
398
+ ? `Could not connect to the assistant at ${socketPath}.\nRun \`assistant status\` to check, or \`assistant gateway start\` to start it.`
399
+ : "Connection closed before response",
400
+ });
401
+ } else if (streamController) {
402
+ streamController.error(new Error("Connection closed before stream ended"));
403
+ streamController = undefined;
404
+ }
405
+ });
406
+
407
+ const reqId = crypto.randomUUID();
408
+
409
+ opts?.signal?.addEventListener("abort", () => { abort(); }, { once: true });
410
+
411
+ const reader = new IpcFrameReader(
412
+ (envelope) => {
413
+ // Non-streaming envelope with error (e.g. method not found, auth failure)
414
+ if (envelope.id !== reqId) return;
415
+ const msg = envelope as IpcResponse;
416
+ finishError({ ok: false, error: msg.error ?? "Unexpected non-streaming response",
417
+ ...(msg.statusCode != null && { statusCode: msg.statusCode }),
418
+ ...(msg.errorCode != null && { errorCode: msg.errorCode }),
419
+ ...(msg.errorDetails != null && { errorDetails: msg.errorDetails }) });
420
+ },
421
+ (err) => finishError({ ok: false, error: err.message }),
422
+ {
423
+ onStreamStart: (envelope) => {
424
+ if (envelope.id !== reqId) return;
425
+ clearTimeout(firstByteTimer);
426
+ const body = new ReadableStream<Uint8Array>({
427
+ start(ctrl) {
428
+ streamController = ctrl;
429
+ },
430
+ cancel() {
431
+ // Consumer cancelled (reader.cancel(), for-await break, pipe abort).
432
+ // Clear the controller reference first so abort() skips the
433
+ // already-closing stream's error() call, then send $cancel.
434
+ streamController = undefined;
435
+ abort();
436
+ },
437
+ });
438
+ settled = true;
439
+ clearTimeout(connectTimer);
440
+ resolve({ ok: true, headers: (envelope.headers ?? {}) as Record<string, string>, body, abort });
441
+ },
442
+ onStreamChunk: (chunk) => {
443
+ streamController?.enqueue(chunk);
444
+ },
445
+ onStreamEnd: () => {
446
+ streamController?.close();
447
+ streamController = undefined;
448
+ socket.destroy();
449
+ },
450
+ },
451
+ );
452
+
453
+ socket.on("connect", () => {
454
+ clearTimeout(connectTimer);
455
+ writeMessage(socket, { id: reqId, method, params });
456
+
457
+ firstByteTimer = setTimeout(() => {
458
+ log.debug({ method, socketPath, timeoutMs: firstByteTimeoutMs }, "CLI IPC stream first-byte timeout");
459
+ finishError({ ok: false, error: "Stream timed out waiting for first byte" });
460
+ }, firstByteTimeoutMs);
461
+
462
+ socket.on("data", (chunk) => {
463
+ reader.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
464
+ });
465
+ });
466
+
467
+ socket.connect(socketPath);
468
+ });
469
+ }
470
+
471
+ // ---------------------------------------------------------------------------
472
+ // Exit helper
473
+ // ---------------------------------------------------------------------------
474
+
475
+ /**
476
+ * Map an IPC error result to a process exit code and terminate.
477
+ *
478
+ * Exit code matrix (DESIGN.md §3.6):
479
+ * 0 — success (not reached via this helper; call process.exit(0) directly)
480
+ * 1 — generic CLI error (fallback for unexpected status codes)
481
+ * 2 — daemon returned 4xx (bad params, not found, unauthorized)
482
+ * 3 — daemon returned 5xx (server-side error)
483
+ * 10 — IPC transport error (can't connect, timeout, closed before response)
484
+ *
485
+ * @example
486
+ * const r = await cliIpcCall<FooResponse>("foo", params);
487
+ * if (!r.ok) return exitFromIpcResult(r, cmd);
488
+ */
489
+ export function exitFromIpcResult(
490
+ r: { ok: boolean; error?: string; statusCode?: number },
491
+ _cmd?: unknown,
492
+ ): never {
493
+ process.stderr.write((r.error ?? "Unknown error") + "\n");
494
+ if (r.statusCode === undefined) {
495
+ process.exit(10);
496
+ } else if (r.statusCode >= 500) {
497
+ process.exit(3);
498
+ } else if (r.statusCode >= 400) {
499
+ process.exit(2);
500
+ } else {
501
+ process.exit(1);
502
+ }
503
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * ⚠️ TEMPORARY HACK — DO NOT EXTEND ⚠️
3
+ *
4
+ * IPC route that lets the gateway execute multiple write statements against
5
+ * the assistant's SQLite database inside a single atomic transaction.
6
+ *
7
+ * Companion to db-proxy.ts. Exists because some gateway-orchestrated writes
8
+ * (e.g. invite redemption: upsert contact channel + record invite use) must
9
+ * be all-or-nothing. With the contacts/guardian/invite tables still living
10
+ * in the assistant DB, the gateway needs a way to commit several writes
11
+ * atomically there.
12
+ *
13
+ * Each step is a write (INSERT/UPDATE/DELETE). All steps run inside a
14
+ * BEGIN IMMEDIATE transaction. If any step throws — including a step whose
15
+ * `requireChanges` constraint is unmet — the entire transaction rolls back.
16
+ *
17
+ * Read-modify-write across steps is not supported (the IPC is one-shot;
18
+ * later steps cannot react to earlier step results except via SQL conditions
19
+ * embedded in the WHERE clause and the optional `requireChanges` guard).
20
+ *
21
+ * This route is intentionally NOT in the shared ROUTES array — it is a
22
+ * private implementation detail between the gateway and assistant IPC
23
+ * servers and must not be discoverable by clients or the OpenAPI spec.
24
+ *
25
+ * Remove once contacts/guardian/invite logic is fully migrated to the
26
+ * gateway's own database.
27
+ */
28
+
29
+ import { getSqlite } from "../../memory/db-connection.js";
30
+ import { RouteError } from "../../runtime/routes/errors.js";
31
+ import { getLogger } from "../../util/logger.js";
32
+
33
+ const log = getLogger("db-proxy-transaction");
34
+
35
+ /** Column value types that SQLite can return. */
36
+ type SqliteValue = string | number | null | Uint8Array;
37
+
38
+ export interface DbProxyTransactionStep {
39
+ /** The SQL write statement to execute. */
40
+ sql: string;
41
+ /** Positional bind parameters. */
42
+ bind?: SqliteValue[];
43
+ /**
44
+ * If set, abort the transaction (rollback) when this step's row-change
45
+ * count is below this threshold. Used for stale-write detection — e.g.
46
+ * "increment use_count only if status = 'active' AND use_count < max_uses",
47
+ * with `requireChanges: 1` to abort when no rows match.
48
+ */
49
+ requireChanges?: number;
50
+ }
51
+
52
+ export interface DbProxyTransactionParams {
53
+ steps: DbProxyTransactionStep[];
54
+ }
55
+
56
+ export type DbProxyTransactionResult =
57
+ | {
58
+ ok: true;
59
+ results: Array<{ changes: number; lastInsertRowid: number }>;
60
+ }
61
+ | {
62
+ ok: false;
63
+ reason: "require_changes_failed";
64
+ failedStep: number;
65
+ actualChanges: number;
66
+ requiredChanges: number;
67
+ };
68
+
69
+ export function handleDbProxyTransaction(
70
+ params: DbProxyTransactionParams,
71
+ ): DbProxyTransactionResult {
72
+ const db = getSqlite();
73
+
74
+ if (!Array.isArray(params.steps) || params.steps.length === 0) {
75
+ throw new RouteError(
76
+ "db_proxy_transaction requires at least one step",
77
+ "INVALID_PARAMS",
78
+ 400,
79
+ );
80
+ }
81
+
82
+ // Sentinel used to abort the transaction without leaking through as a generic
83
+ // SQL error. Better-sqlite3 rolls back when the inner function throws.
84
+ class RequireChangesFailure extends Error {
85
+ constructor(
86
+ public failedStep: number,
87
+ public actualChanges: number,
88
+ public requiredChanges: number,
89
+ ) {
90
+ super(
91
+ `Step ${failedStep} affected ${actualChanges} rows, requires ${requiredChanges}`,
92
+ );
93
+ }
94
+ }
95
+
96
+ const results: Array<{ changes: number; lastInsertRowid: number }> = [];
97
+
98
+ try {
99
+ db.transaction(() => {
100
+ for (let i = 0; i < params.steps.length; i++) {
101
+ const step = params.steps[i];
102
+ const stmt = db.prepare(step.sql);
103
+ const result = step.bind ? stmt.run(...step.bind) : stmt.run();
104
+ const changes = result.changes;
105
+ results.push({
106
+ changes,
107
+ lastInsertRowid: Number(result.lastInsertRowid),
108
+ });
109
+
110
+ if (
111
+ step.requireChanges !== undefined &&
112
+ changes < step.requireChanges
113
+ ) {
114
+ throw new RequireChangesFailure(i, changes, step.requireChanges);
115
+ }
116
+ }
117
+ }).immediate();
118
+ } catch (err) {
119
+ if (err instanceof RequireChangesFailure) {
120
+ log.debug(
121
+ {
122
+ failedStep: err.failedStep,
123
+ actualChanges: err.actualChanges,
124
+ requiredChanges: err.requiredChanges,
125
+ },
126
+ "db-proxy-transaction aborted by requireChanges guard",
127
+ );
128
+ return {
129
+ ok: false,
130
+ reason: "require_changes_failed",
131
+ failedStep: err.failedStep,
132
+ actualChanges: err.actualChanges,
133
+ requiredChanges: err.requiredChanges,
134
+ };
135
+ }
136
+ // Wrap raw SQL/runtime errors in RouteError so the IPC envelope carries
137
+ // a statusCode + errorCode. Without this, the gateway-side strict caller
138
+ // sees a structureless `msg.error` and misclassifies it as a transport
139
+ // failure ("assistant may not be ready"), masking the real SQL error
140
+ // and breaking debuggability + retry decisions.
141
+ const message = err instanceof Error ? err.message : String(err);
142
+ log.warn({ err }, "db-proxy-transaction execution failed");
143
+ throw new RouteError(message, "DB_PROXY_TRANSACTION_FAILED", 500);
144
+ }
145
+
146
+ log.debug(
147
+ { stepCount: params.steps.length },
148
+ "db-proxy-transaction committed",
149
+ );
150
+ return { ok: true, results };
151
+ }
@@ -192,6 +192,66 @@ describe("host.events.publish", () => {
192
192
 
193
193
  client.close();
194
194
  });
195
+
196
+ test.each([
197
+ "host_bash_request",
198
+ "host_bash_cancel",
199
+ "host_file_request",
200
+ "host_file_cancel",
201
+ "host_browser_request",
202
+ "host_browser_cancel",
203
+ "host_cu_request",
204
+ "host_transfer_request",
205
+ "confirmation_request",
206
+ "secret_request",
207
+ ])("rejects blocked event type: %s", async (blockedType) => {
208
+ const client = await openClient();
209
+ const event = {
210
+ id: "evt-blocked",
211
+ emittedAt: new Date().toISOString(),
212
+ message: { type: blockedType },
213
+ };
214
+ client.send({
215
+ id: "req-blocked",
216
+ method: "host.events.publish",
217
+ params: { event },
218
+ });
219
+
220
+ const frame = await client.nextFrame();
221
+ expect("error" in frame && frame.error).toContain("cannot publish");
222
+
223
+ client.close();
224
+ });
225
+
226
+ test("allows non-blocked event types through", async () => {
227
+ const received: AssistantEvent[] = [];
228
+ const subscription = assistantEventHub.subscribe({
229
+ type: "process",
230
+ callback: (evt) => { received.push(evt); },
231
+ });
232
+
233
+ try {
234
+ const client = await openClient();
235
+ const event = {
236
+ id: "evt-ok",
237
+ emittedAt: new Date().toISOString(),
238
+ message: { type: "skill_custom_event", data: "hello" },
239
+ };
240
+ client.send({
241
+ id: "req-ok",
242
+ method: "host.events.publish",
243
+ params: { event },
244
+ });
245
+
246
+ const frame = await client.nextFrame();
247
+ expect("result" in frame && frame.result).toEqual({ published: true });
248
+ expect(received).toHaveLength(1);
249
+
250
+ client.close();
251
+ } finally {
252
+ subscription.dispose();
253
+ }
254
+ });
195
255
  });
196
256
 
197
257
  describe("host.events.buildEvent", () => {