@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
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Smoke tests for cliIpcCallBinary and cliIpcCallStream.
3
+ *
4
+ * Uses a real AssistantIpcServer with fixture routes injected via module mocks.
5
+ * Pattern mirrors cli-ipc.test.ts.
6
+ */
7
+
8
+ import { Socket } from "node:net";
9
+ import { afterEach, describe, expect, mock, test } from "bun:test";
10
+
11
+ // Ensure tests use a workspace-based socket path rather than any pre-existing
12
+ // system socket (e.g. stale root-owned /run/assistant-ipc/assistant.sock).
13
+ delete process.env.ASSISTANT_IPC_SOCKET_DIR;
14
+
15
+ import { AssistantIpcServer } from "../assistant-server.js";
16
+ import { cliIpcCallBinary, cliIpcCallStream } from "../cli-client.js";
17
+ import { writeMessage } from "../ipc-framing.js";
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Fixture routes
21
+ // ---------------------------------------------------------------------------
22
+
23
+ const STREAM_FIXTURE_ROUTE = {
24
+ operationId: "stream_fixture",
25
+ endpoint: "/stream-fixture",
26
+ method: "GET" as const,
27
+ handler: async () => ({
28
+ stream: new ReadableStream<Uint8Array>({
29
+ start(ctrl) {
30
+ ctrl.enqueue(new TextEncoder().encode("chunk1"));
31
+ ctrl.enqueue(new TextEncoder().encode("chunk2"));
32
+ ctrl.close();
33
+ },
34
+ }),
35
+ headers: { "x-fixture": "streaming" },
36
+ }),
37
+ };
38
+
39
+ const BINARY_FIXTURE_ROUTE = {
40
+ operationId: "binary_fixture",
41
+ endpoint: "/binary-fixture",
42
+ method: "GET" as const,
43
+ handler: async () => ({
44
+ binary: new TextEncoder().encode("hello"),
45
+ headers: { "content-type": "application/octet-stream" },
46
+ }),
47
+ };
48
+
49
+ let slowStreamAborted = false;
50
+ const SLOW_STREAM_FIXTURE_ROUTE = {
51
+ operationId: "slow_stream_fixture",
52
+ endpoint: "/slow-stream-fixture",
53
+ method: "GET" as const,
54
+ // Delays 50 ms before returning the stream so the test can destroy the
55
+ // socket first, exercising the sendStreamingResponse early-return path.
56
+ handler: async (params: Record<string, unknown> | undefined) => {
57
+ slowStreamAborted = false;
58
+ const signal = (params as { abortSignal?: AbortSignal })?.abortSignal;
59
+ signal?.addEventListener("abort", () => { slowStreamAborted = true; }, { once: true });
60
+ await new Promise((r) => setTimeout(r, 50));
61
+ return {
62
+ stream: new ReadableStream<Uint8Array>({ start(ctrl) { ctrl.close(); } }),
63
+ headers: {} as Record<string, string>,
64
+ };
65
+ },
66
+ };
67
+
68
+ let cancelAborted = false;
69
+ const CANCEL_FIXTURE_ROUTE = {
70
+ operationId: "cancel_fixture",
71
+ endpoint: "/cancel-fixture",
72
+ method: "GET" as const,
73
+ // Returns a stream immediately that holds open until the abortSignal fires.
74
+ // This lets cliIpcCallStream resolve (opening envelope arrives), then the
75
+ // test can call abort() and verify the signal is delivered to the handler.
76
+ handler: async (params: Record<string, unknown> | undefined) => {
77
+ cancelAborted = false;
78
+ const signal = (params as { abortSignal?: AbortSignal })?.abortSignal;
79
+ return {
80
+ stream: new ReadableStream<Uint8Array>({
81
+ start(ctrl) {
82
+ if (signal?.aborted) {
83
+ cancelAborted = true;
84
+ ctrl.error(new DOMException("Aborted", "AbortError"));
85
+ return;
86
+ }
87
+ signal?.addEventListener("abort", () => {
88
+ cancelAborted = true;
89
+ ctrl.error(new DOMException("Aborted", "AbortError"));
90
+ }, { once: true });
91
+ // Hold open — no close() until aborted
92
+ },
93
+ }),
94
+ headers: {} as Record<string, string>,
95
+ };
96
+ },
97
+ };
98
+
99
+ mock.module("../../runtime/routes/index.js", () => ({
100
+ ROUTES: [STREAM_FIXTURE_ROUTE, BINARY_FIXTURE_ROUTE, CANCEL_FIXTURE_ROUTE, SLOW_STREAM_FIXTURE_ROUTE],
101
+ }));
102
+
103
+ // ---------------------------------------------------------------------------
104
+ // Setup
105
+ // ---------------------------------------------------------------------------
106
+
107
+ let server: AssistantIpcServer | null = null;
108
+
109
+ async function startServer(): Promise<void> {
110
+ server = new AssistantIpcServer({ watchdogIntervalMs: 0 });
111
+ await server.start();
112
+ await new Promise((r) => setTimeout(r, 50));
113
+ }
114
+
115
+ afterEach(() => {
116
+ server?.stop();
117
+ server = null;
118
+ cancelAborted = false;
119
+ slowStreamAborted = false;
120
+ });
121
+
122
+ // ---------------------------------------------------------------------------
123
+ // cliIpcCallStream tests
124
+ // ---------------------------------------------------------------------------
125
+
126
+ describe("cliIpcCallStream", () => {
127
+ test("resolves ok with correct headers", async () => {
128
+ await startServer();
129
+ const r = await cliIpcCallStream("stream_fixture");
130
+ expect(r.ok).toBe(true);
131
+ if (!r.ok) return;
132
+ expect(r.headers["x-fixture"]).toBe("streaming");
133
+ // Drain the body to avoid resource leaks
134
+ const reader = r.body.getReader();
135
+ while (true) {
136
+ const { done } = await reader.read();
137
+ if (done) break;
138
+ }
139
+ });
140
+
141
+ test("chunks arrive in order", async () => {
142
+ await startServer();
143
+ const r = await cliIpcCallStream("stream_fixture");
144
+ expect(r.ok).toBe(true);
145
+ if (!r.ok) return;
146
+
147
+ const chunks: string[] = [];
148
+ const reader = r.body.getReader();
149
+ const dec = new TextDecoder();
150
+ while (true) {
151
+ const { done, value } = await reader.read();
152
+ if (done) break;
153
+ chunks.push(dec.decode(value));
154
+ }
155
+ expect(chunks.join("")).toBe("chunk1chunk2");
156
+ });
157
+
158
+ test("abort() cancels mid-stream", async () => {
159
+ await startServer();
160
+ const r = await cliIpcCallStream("cancel_fixture");
161
+ expect(r.ok).toBe(true);
162
+ if (!r.ok) return;
163
+
164
+ const bodyReader = r.body.getReader();
165
+ r.abort();
166
+
167
+ // The stream should error after abort — either DOMException or connection close
168
+ try {
169
+ await bodyReader.read();
170
+ } catch (err) {
171
+ expect(err).toBeDefined();
172
+ }
173
+
174
+ // Give the server a tick to process the $cancel envelope
175
+ await new Promise((res) => setTimeout(res, 200));
176
+ expect(cancelAborted).toBe(true);
177
+ });
178
+
179
+ test("returns ok: false when no server", async () => {
180
+ const r = await cliIpcCallStream("stream_fixture");
181
+ expect(r.ok).toBe(false);
182
+ });
183
+
184
+ test("body.cancel() sends $cancel to server (Fix F)", async () => {
185
+ await startServer();
186
+ const r = await cliIpcCallStream("cancel_fixture");
187
+ expect(r.ok).toBe(true);
188
+ if (!r.ok) return;
189
+
190
+ // Cancel the ReadableStream body — the cancel() callback should call abort()
191
+ // which sends $cancel on the wire and ends the socket.
192
+ await r.body.cancel();
193
+
194
+ // Give the server a tick to process the $cancel envelope
195
+ await new Promise((res) => setTimeout(res, 200));
196
+ expect(cancelAborted).toBe(true);
197
+ });
198
+
199
+ test("abortController cleaned up when socket destroyed before stream starts (Fix E)", async () => {
200
+ await startServer();
201
+ const socketPath = server!.getSocketPath();
202
+
203
+ // Use a raw socket so we can destroy it immediately after sending the
204
+ // request, before slow_stream_fixture's 50ms handler delay expires.
205
+ const rawSocket = new Socket();
206
+ await new Promise<void>((res) => rawSocket.connect(socketPath, res));
207
+ writeMessage(rawSocket, { id: crypto.randomUUID(), method: "slow_stream_fixture", params: {} });
208
+ rawSocket.destroy();
209
+
210
+ // Wait for the handler to complete and sendStreamingResponse to run
211
+ await new Promise((res) => setTimeout(res, 200));
212
+
213
+ // Handler's abortSignal fired → confirms abort+delete ran in the
214
+ // sendStreamingResponse early-return (socket already destroyed) path.
215
+ expect(slowStreamAborted).toBe(true);
216
+ });
217
+ });
218
+
219
+ // ---------------------------------------------------------------------------
220
+ // cliIpcCallBinary tests
221
+ // ---------------------------------------------------------------------------
222
+
223
+ describe("cliIpcCallBinary", () => {
224
+ test("returns bytes from binary route", async () => {
225
+ await startServer();
226
+ const r = await cliIpcCallBinary("binary_fixture");
227
+ expect(r.ok).toBe(true);
228
+ if (!r.ok) return;
229
+ expect(new TextDecoder().decode(r.bytes)).toBe("hello");
230
+ expect(r.headers["content-type"]).toBe("application/octet-stream");
231
+ });
232
+
233
+ test("returns ok: false when no server", async () => {
234
+ const r = await cliIpcCallBinary("binary_fixture");
235
+ expect(r.ok).toBe(false);
236
+ });
237
+ });
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Unit tests for IpcFrameReader — pure in-memory, no network.
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+
7
+ import { IpcFrameReader, type StreamCallbacks } from "../ipc-framing.js";
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Helpers
11
+ // ---------------------------------------------------------------------------
12
+
13
+ /** Build a single length-prefixed frame: 4-byte big-endian length + payload. */
14
+ function buildFrame(payload: Uint8Array | Buffer): Buffer {
15
+ const header = Buffer.alloc(4);
16
+ header.writeUInt32BE(payload.length, 0);
17
+ return Buffer.concat([header, Buffer.from(payload)]);
18
+ }
19
+
20
+ /** Build a zero-length terminator frame (4 bytes of 0x00). */
21
+ function buildTerminator(): Buffer {
22
+ return Buffer.alloc(4);
23
+ }
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // Tests
27
+ // ---------------------------------------------------------------------------
28
+
29
+ describe("IpcFrameReader", () => {
30
+ test("parses JSON-only envelope", () => {
31
+ const envelope = { id: "req-1", result: { foo: "bar" } };
32
+ const json = Buffer.from(JSON.stringify(envelope), "utf-8");
33
+ const frame = buildFrame(json);
34
+
35
+ const received: Array<{ envelope: unknown; binary: Uint8Array | undefined }> = [];
36
+
37
+ const reader = new IpcFrameReader((env, binary) => {
38
+ received.push({ envelope: env, binary });
39
+ });
40
+
41
+ reader.push(frame);
42
+
43
+ expect(received).toHaveLength(1);
44
+ expect(received[0].envelope).toEqual(envelope);
45
+ expect(received[0].binary).toBeUndefined();
46
+ });
47
+
48
+ test("parses envelope + binary frame (content-length)", () => {
49
+ const binaryData = new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05]);
50
+
51
+ const envelope = {
52
+ id: "req-2",
53
+ result: "ok",
54
+ headers: { "content-length": "5" },
55
+ };
56
+ const jsonFrame = buildFrame(Buffer.from(JSON.stringify(envelope), "utf-8"));
57
+ const binaryFrame = buildFrame(Buffer.from(binaryData));
58
+
59
+ const allData = Buffer.concat([jsonFrame, binaryFrame]);
60
+
61
+ const received: Array<{ envelope: unknown; binary: Uint8Array | undefined }> = [];
62
+
63
+ const reader = new IpcFrameReader((env, binary) => {
64
+ received.push({ envelope: env, binary });
65
+ });
66
+
67
+ reader.push(allData);
68
+
69
+ expect(received).toHaveLength(1);
70
+ expect(received[0].envelope).toEqual(envelope);
71
+ expect(received[0].binary).toBeInstanceOf(Uint8Array);
72
+ expect(received[0].binary).toHaveLength(5);
73
+ expect(Array.from(received[0].binary!)).toEqual([0x01, 0x02, 0x03, 0x04, 0x05]);
74
+ });
75
+
76
+ test("parses chunked stream (transfer-encoding: chunked)", () => {
77
+ const chunk1 = new Uint8Array([0x61, 0x62]); // "ab"
78
+ const chunk2 = new Uint8Array([0x63, 0x64, 0x65]); // "cde"
79
+
80
+ const envelope = {
81
+ id: "req-3",
82
+ headers: { "transfer-encoding": "chunked" },
83
+ };
84
+ const jsonFrame = buildFrame(Buffer.from(JSON.stringify(envelope), "utf-8"));
85
+ const chunk1Frame = buildFrame(Buffer.from(chunk1));
86
+ const chunk2Frame = buildFrame(Buffer.from(chunk2));
87
+ const terminator = buildTerminator();
88
+
89
+ const allData = Buffer.concat([jsonFrame, chunk1Frame, chunk2Frame, terminator]);
90
+
91
+ const events: string[] = [];
92
+ let startEnvelope: unknown = null;
93
+ const chunks: Uint8Array[] = [];
94
+
95
+ const streamCallbacks: StreamCallbacks = {
96
+ onStreamStart: (env) => {
97
+ events.push("start");
98
+ startEnvelope = env;
99
+ },
100
+ onStreamChunk: (chunk) => {
101
+ events.push("chunk");
102
+ chunks.push(chunk);
103
+ },
104
+ onStreamEnd: () => {
105
+ events.push("end");
106
+ },
107
+ };
108
+
109
+ const reader = new IpcFrameReader(
110
+ (_env, _binary) => {
111
+ events.push("message");
112
+ },
113
+ undefined,
114
+ streamCallbacks,
115
+ );
116
+
117
+ reader.push(allData);
118
+
119
+ expect(events).toEqual(["start", "chunk", "chunk", "end"]);
120
+ expect(startEnvelope).toEqual(envelope);
121
+ expect(chunks).toHaveLength(2);
122
+ expect(Array.from(chunks[0])).toEqual([0x61, 0x62]);
123
+ expect(Array.from(chunks[1])).toEqual([0x63, 0x64, 0x65]);
124
+ });
125
+
126
+ test("detects legacy newline-JSON", () => {
127
+ const legacyPayload = JSON.stringify({ id: "x", result: 1 }) + "\n";
128
+ const buf = Buffer.from(legacyPayload, "utf-8");
129
+
130
+ const received: Array<{ envelope: unknown; binary: Uint8Array | undefined }> = [];
131
+
132
+ const reader = new IpcFrameReader((env, binary) => {
133
+ received.push({ envelope: env, binary });
134
+ });
135
+
136
+ reader.push(buf);
137
+
138
+ expect(received).toHaveLength(1);
139
+ expect(received[0].envelope).toEqual({ id: "x", result: 1 });
140
+ expect(reader.isLegacy).toBe(true);
141
+ });
142
+ });
@@ -28,9 +28,13 @@
28
28
  * back to a shorter deterministic path so CLI commands can still connect.
29
29
  */
30
30
 
31
- import { existsSync, mkdirSync, unlinkSync } from "node:fs";
31
+ import { existsSync, unlinkSync } from "node:fs";
32
32
  import { createServer, type Server, type Socket } from "node:net";
33
- import { dirname } from "node:path";
33
+
34
+ import {
35
+ ensureSocketDir,
36
+ SocketWatchdog,
37
+ } from "@vellumai/ipc-server-utils";
34
38
 
35
39
  import { findLocalGuardianPrincipalId } from "../runtime/local-actor-identity.js";
36
40
  import { RouteError } from "../runtime/routes/errors.js";
@@ -49,6 +53,10 @@ import {
49
53
  writeStreamEnd,
50
54
  } from "./ipc-framing.js";
51
55
  import { type DbProxyParams, handleDbProxy } from "./routes/db-proxy.js";
56
+ import {
57
+ type DbProxyTransactionParams,
58
+ handleDbProxyTransaction,
59
+ } from "./routes/db-proxy-transaction.js";
52
60
  import { routeDefinitionsToIpcMethods } from "./routes/route-adapter.js";
53
61
  import { ensureSocketPathFree } from "./socket-cleanup.js";
54
62
  import { resolveIpcSocketPath } from "./socket-path.js";
@@ -130,13 +138,30 @@ function isIpcBinaryResponse(value: unknown): value is IpcBinaryResponse {
130
138
  // Server
131
139
  // ---------------------------------------------------------------------------
132
140
 
141
+ /** Optional configuration for {@link AssistantIpcServer}. */
142
+ export interface AssistantIpcServerOptions {
143
+ /**
144
+ * How often the socket-file watchdog stats the listening socket path.
145
+ * Set to `0` to disable. Defaults to {@link SocketWatchdog}'s 5000ms.
146
+ */
147
+ watchdogIntervalMs?: number;
148
+ }
149
+
133
150
  export class AssistantIpcServer {
134
151
  private server: Server | null = null;
135
152
  private clients = new Set<Socket>();
136
153
  private methods = new Map<string, RouteDefinition["handler"]>();
137
154
  private socketPath: string;
155
+ private watchdog: SocketWatchdog;
156
+ /**
157
+ * Servers whose listener path has been replaced by a re-bind. Kept around
158
+ * so already-connected sockets continue to work; closed gracefully once
159
+ * their accept loops drain.
160
+ */
161
+ private legacyServers = new Set<Server>();
162
+ private abortControllers = new Map<string, AbortController>();
138
163
 
139
- constructor() {
164
+ constructor(options?: AssistantIpcServerOptions) {
140
165
  const resolution = resolveIpcSocketPath("assistant");
141
166
  this.socketPath = resolution.path;
142
167
  log.info(
@@ -147,69 +172,75 @@ export class AssistantIpcServer {
147
172
  this.methods.set(route.operationId, route.handler);
148
173
  }
149
174
 
150
- // ⚠️ TEMPORARY — gateway→assistant DB proxy (see ipc/routes/db-proxy.ts).
151
- // This is the ONLY route defined directly here; all other routes go in ROUTES.
152
- // Remove once contacts/guardian-binding logic is fully migrated to the
153
- // gateway's own database.
175
+ // ⚠️ TEMPORARY — gateway→assistant DB proxies (see ipc/routes/db-proxy.ts
176
+ // and ipc/routes/db-proxy-transaction.ts). These are the ONLY routes
177
+ // defined directly here; all other routes go in ROUTES. Remove once
178
+ // contacts/guardian-binding logic is fully migrated to the gateway's
179
+ // own database.
154
180
  this.methods.set("db_proxy", (params) =>
155
181
  handleDbProxy(params as unknown as DbProxyParams),
156
182
  );
183
+ this.methods.set("db_proxy_transaction", (params) =>
184
+ handleDbProxyTransaction(params as unknown as DbProxyTransactionParams),
185
+ );
186
+
187
+ this.methods.set("$cancel", (params) => {
188
+ const targetId = (params as { targetId?: string }).targetId;
189
+ if (targetId) this.abortControllers.get(targetId)?.abort();
190
+ return null;
191
+ });
192
+
193
+ this.watchdog = new SocketWatchdog({
194
+ socketPath: this.socketPath,
195
+ intervalMs: options?.watchdogIntervalMs,
196
+ getServer: () => this.server,
197
+ createServer: () => this.createListeningServer(),
198
+ onRebind: (newServer, oldServer) => {
199
+ this.server = newServer;
200
+ this.legacyServers.add(oldServer);
201
+ oldServer.close(() => {
202
+ this.legacyServers.delete(oldServer);
203
+ });
204
+ },
205
+ log,
206
+ });
157
207
  }
158
208
 
159
209
  /** Start listening on the Unix domain socket. */
160
210
  async start(): Promise<void> {
161
211
  // Ensure the parent directory exists before listening.
162
- const socketDir = dirname(this.socketPath);
163
- if (!existsSync(socketDir)) {
164
- mkdirSync(socketDir, { recursive: true, mode: 0o700 });
165
- }
212
+ ensureSocketDir(this.socketPath);
166
213
 
167
214
  // Probe before unlink so a second daemon can't silently orphan an active
168
215
  // listener (Unix lets you unlink a still-bound socket file). See
169
216
  // `ensureSocketPathFree` for the behavior matrix.
170
217
  await ensureSocketPathFree(this.socketPath);
171
218
 
172
- this.server = createServer((socket) => {
173
- this.clients.add(socket);
174
- log.debug("IPC client connected");
175
-
176
- const reader = new IpcFrameReader(
177
- (envelope, binary) =>
178
- this.handleEnvelope(socket, reader, envelope, binary),
179
- (err) => log.warn({ err }, "IPC frame read error"),
180
- );
181
-
182
- socket.on("data", (chunk) => {
183
- reader.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
184
- });
185
-
186
- socket.on("close", () => {
187
- this.clients.delete(socket);
188
- log.debug("IPC client disconnected");
189
- });
190
-
191
- socket.on("error", (err) => {
192
- log.warn({ err }, "IPC client socket error");
193
- this.clients.delete(socket);
194
- });
195
- });
196
-
197
- this.server.on("error", (err) => {
198
- log.error({ err }, "Assistant IPC server error");
199
- });
200
-
219
+ this.server = this.createListeningServer();
201
220
  this.server.listen(this.socketPath, () => {
202
221
  log.info({ path: this.socketPath }, "Assistant IPC server listening");
203
222
  });
223
+
224
+ this.watchdog.start();
204
225
  }
205
226
 
206
227
  /** Stop the server and disconnect all clients. */
207
228
  stop(): void {
229
+ this.watchdog.stop();
230
+
231
+ for (const ctrl of this.abortControllers.values()) ctrl.abort();
232
+ this.abortControllers.clear();
233
+
208
234
  for (const client of this.clients) {
209
235
  if (!client.destroyed) client.destroy();
210
236
  }
211
237
  this.clients.clear();
212
238
 
239
+ for (const legacy of this.legacyServers) {
240
+ legacy.close();
241
+ }
242
+ this.legacyServers.clear();
243
+
213
244
  if (this.server) {
214
245
  this.server.close();
215
246
  this.server = null;
@@ -229,8 +260,52 @@ export class AssistantIpcServer {
229
260
  return this.socketPath;
230
261
  }
231
262
 
263
+ /**
264
+ * Re-bind the listening socket if its path entry is missing on disk.
265
+ *
266
+ * Public for tests so the watchdog can be exercised deterministically
267
+ * without waiting for the interval. Returns `true` when a re-bind was
268
+ * performed, `false` otherwise.
269
+ */
270
+ async rebindIfMissing(): Promise<boolean> {
271
+ return this.watchdog.rebindIfMissing();
272
+ }
273
+
232
274
  // ── Internal ──────────────────────────────────────────────────────────
233
275
 
276
+ private createListeningServer(): Server {
277
+ const server = createServer((socket) => {
278
+ this.clients.add(socket);
279
+ log.debug("IPC client connected");
280
+
281
+ const reader = new IpcFrameReader(
282
+ (envelope, binary) =>
283
+ this.handleEnvelope(socket, reader, envelope, binary),
284
+ (err) => log.warn({ err }, "IPC frame read error"),
285
+ );
286
+
287
+ socket.on("data", (chunk) => {
288
+ reader.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
289
+ });
290
+
291
+ socket.on("close", () => {
292
+ this.clients.delete(socket);
293
+ log.debug("IPC client disconnected");
294
+ });
295
+
296
+ socket.on("error", (err) => {
297
+ log.warn({ err }, "IPC client socket error");
298
+ this.clients.delete(socket);
299
+ });
300
+ });
301
+
302
+ server.on("error", (err) => {
303
+ log.error({ err }, "Assistant IPC server error");
304
+ });
305
+
306
+ return server;
307
+ }
308
+
234
309
  private handleEnvelope(
235
310
  socket: Socket,
236
311
  reader: IpcFrameReader,
@@ -259,16 +334,33 @@ export class AssistantIpcServer {
259
334
 
260
335
  void binary;
261
336
 
337
+ // Skip AbortController for the $cancel meta-method itself
338
+ const needsAbortTracking = req.method !== "$cancel";
339
+ let abortController: AbortController | undefined;
340
+ if (needsAbortTracking) {
341
+ abortController = new AbortController();
342
+ this.abortControllers.set(req.id, abortController);
343
+ }
344
+
262
345
  try {
263
- const handlerArgs = injectLocalActorHeader(req.params);
346
+ const handlerArgs = {
347
+ ...injectLocalActorHeader(req.params),
348
+ ...(abortController && { abortSignal: abortController.signal }),
349
+ };
264
350
  const result = handler(handlerArgs);
265
351
 
266
352
  if (result instanceof Promise) {
267
353
  result
268
354
  .then((value) => {
355
+ // For streaming responses, keep the AbortController alive until the
356
+ // stream ends — sendStreamingResponse deletes it on completion/error.
357
+ if (!isIpcStreamingResponse(value)) {
358
+ this.abortControllers.delete(req.id);
359
+ }
269
360
  this.sendResult(socket, reader, req.id, value);
270
361
  })
271
362
  .catch((err) => {
363
+ this.abortControllers.delete(req.id);
272
364
  log.warn({ err, method: req.method }, "IPC handler error");
273
365
  this.sendResponse(
274
366
  socket,
@@ -277,9 +369,13 @@ export class AssistantIpcServer {
277
369
  );
278
370
  });
279
371
  } else {
372
+ if (!isIpcStreamingResponse(result)) {
373
+ this.abortControllers.delete(req.id);
374
+ }
280
375
  this.sendResult(socket, reader, req.id, result);
281
376
  }
282
377
  } catch (err) {
378
+ this.abortControllers.delete(req.id);
283
379
  log.warn({ err, method: req.method }, "IPC handler error");
284
380
  this.sendResponse(socket, reader, this.buildErrorResponse(req.id, err));
285
381
  }
@@ -345,7 +441,11 @@ export class AssistantIpcServer {
345
441
  requestId: string,
346
442
  response: IpcStreamingResponse,
347
443
  ): void {
348
- if (socket.destroyed) return;
444
+ if (socket.destroyed) {
445
+ this.abortControllers.get(requestId)?.abort();
446
+ this.abortControllers.delete(requestId);
447
+ return;
448
+ }
349
449
 
350
450
  // Legacy clients can't handle chunked streaming — fall back to
351
451
  // buffering the full stream and sending as a single binary response.
@@ -369,10 +469,13 @@ export class AssistantIpcServer {
369
469
  .read()
370
470
  .then(({ done, value }) => {
371
471
  if (socket.destroyed) {
472
+ this.abortControllers.get(requestId)?.abort();
473
+ this.abortControllers.delete(requestId);
372
474
  streamReader.cancel().catch(() => {});
373
475
  return;
374
476
  }
375
477
  if (done) {
478
+ this.abortControllers.delete(requestId);
376
479
  writeStreamEnd(socket);
377
480
  return;
378
481
  }
@@ -380,6 +483,7 @@ export class AssistantIpcServer {
380
483
  pump();
381
484
  })
382
485
  .catch((err) => {
486
+ this.abortControllers.delete(requestId);
383
487
  log.warn({ err }, "IPC stream read error");
384
488
  if (!socket.destroyed) {
385
489
  writeStreamEnd(socket);
@@ -407,6 +511,7 @@ export class AssistantIpcServer {
407
511
  .read()
408
512
  .then(({ done, value }) => {
409
513
  if (done) {
514
+ this.abortControllers.delete(requestId);
410
515
  const totalLength = chunks.reduce(
411
516
  (sum, c) => sum + c.byteLength,
412
517
  0,
@@ -431,6 +536,7 @@ export class AssistantIpcServer {
431
536
  pump();
432
537
  })
433
538
  .catch((err) => {
539
+ this.abortControllers.delete(requestId);
434
540
  log.warn({ err }, "IPC legacy stream buffer error");
435
541
  this.sendResponse(socket, reader, {
436
542
  id: requestId,