@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
@@ -39,16 +39,29 @@ import {
39
39
  import { getConversationDirPath } from "../memory/conversation-disk-view.js";
40
40
  import { getDb } from "../memory/db-connection.js";
41
41
  import { initializeDb } from "../memory/db-init.js";
42
+ import {
43
+ loadGraphMemoryState,
44
+ saveGraphMemoryState,
45
+ } from "../memory/graph/graph-memory-state-store.js";
42
46
  import { getRequestLogsByMessageId } from "../memory/llm-request-log-store.js";
43
47
  import {
48
+ bumpRetrospectiveLastRunAt,
49
+ getRetrospectiveState,
50
+ upsertRetrospectiveState,
51
+ } from "../memory/memory-retrospective-state.js";
52
+ import {
53
+ activationState,
44
54
  channelInboundEvents,
45
55
  conversationAssistantAttentionState,
56
+ conversationGraphMemoryState,
46
57
  conversations,
47
58
  externalConversationBindings,
48
59
  llmRequestLogs,
49
60
  memoryJobs,
61
+ memoryRetrospectiveState,
50
62
  toolInvocations,
51
63
  } from "../memory/schema.js";
64
+ import { hydrate as hydrateActivationState } from "../memory/v2/activation-store.js";
52
65
 
53
66
  initializeDb();
54
67
 
@@ -57,6 +70,9 @@ function resetTables(): void {
57
70
  db.delete(channelInboundEvents).run();
58
71
  db.delete(externalConversationBindings).run();
59
72
  db.delete(conversationAssistantAttentionState).run();
73
+ db.delete(activationState).run();
74
+ db.delete(conversationGraphMemoryState).run();
75
+ db.delete(memoryRetrospectiveState).run();
60
76
  db.delete(llmRequestLogs).run();
61
77
  db.delete(toolInvocations).run();
62
78
  db.delete(memoryJobs).run();
@@ -137,7 +153,6 @@ describe("forkConversation", () => {
137
153
  ).toBe(true);
138
154
  });
139
155
 
140
-
141
156
  test("preserves source order when source messages share a timestamp", () => {
142
157
  const source = createConversation("Equal timestamp thread");
143
158
  const db = getDb();
@@ -500,4 +515,229 @@ describe("forkConversation", () => {
500
515
  expect(forkInboundEventCount).toBe(0);
501
516
  expect(forkQueuedWorkCount).toBe(0);
502
517
  });
518
+
519
+ test("copies the parent's v2 activation state into the fork", async () => {
520
+ const source = createConversation("Activation thread");
521
+ const sourceMessage = await addMessage(
522
+ source.id,
523
+ "user",
524
+ "Tell me about the Q3 launch plan",
525
+ undefined,
526
+ { skipIndexing: true },
527
+ );
528
+
529
+ const db = getDb();
530
+ db.insert(activationState)
531
+ .values({
532
+ conversationId: source.id,
533
+ messageId: sourceMessage.id,
534
+ stateJson: JSON.stringify({
535
+ "concepts/q3-launch-plan": 0.71,
536
+ "concepts/marketing-ops": 0.34,
537
+ }),
538
+ everInjectedJson: JSON.stringify([
539
+ { slug: "concepts/q3-launch-plan", turn: 1 },
540
+ { slug: "concepts/marketing-ops", turn: 1 },
541
+ ]),
542
+ currentTurn: 2,
543
+ updatedAt: 1_700_000_000_000,
544
+ })
545
+ .run();
546
+
547
+ const fork = forkConversation({ conversationId: source.id });
548
+
549
+ const childState = await hydrateActivationState(db, fork.id);
550
+ expect(childState).toEqual({
551
+ messageId: sourceMessage.id,
552
+ state: {
553
+ "concepts/q3-launch-plan": 0.71,
554
+ "concepts/marketing-ops": 0.34,
555
+ },
556
+ everInjected: [
557
+ { slug: "concepts/q3-launch-plan", turn: 1 },
558
+ { slug: "concepts/marketing-ops", turn: 1 },
559
+ ],
560
+ currentTurn: 2,
561
+ updatedAt: 1_700_000_000_000,
562
+ });
563
+
564
+ // Parent state is untouched.
565
+ const parentState = await hydrateActivationState(db, source.id);
566
+ expect(parentState?.currentTurn).toBe(2);
567
+ });
568
+
569
+ test("copies the parent's v1 graph memory state into the fork", async () => {
570
+ const source = createConversation("Graph tracker thread");
571
+ await addMessage(
572
+ source.id,
573
+ "user",
574
+ "Look up alice's preferences",
575
+ undefined,
576
+ {
577
+ skipIndexing: true,
578
+ },
579
+ );
580
+
581
+ const trackerSnapshot = JSON.stringify({
582
+ initialized: true,
583
+ needsReload: false,
584
+ inContext: ["node-alice", "node-bob"],
585
+ log: [
586
+ { nodeId: "node-alice", turn: 1 },
587
+ { nodeId: "node-bob", turn: 2 },
588
+ ],
589
+ currentTurn: 3,
590
+ });
591
+ saveGraphMemoryState(source.id, trackerSnapshot);
592
+
593
+ const fork = forkConversation({ conversationId: source.id });
594
+
595
+ expect(loadGraphMemoryState(fork.id)).toBe(trackerSnapshot);
596
+ // Parent row is untouched.
597
+ expect(loadGraphMemoryState(source.id)).toBe(trackerSnapshot);
598
+ });
599
+
600
+ test("leaves both memory state tables empty when the parent has none", async () => {
601
+ const source = createConversation("Pristine thread");
602
+ await addMessage(source.id, "user", "first message", undefined, {
603
+ skipIndexing: true,
604
+ });
605
+
606
+ const fork = forkConversation({ conversationId: source.id });
607
+
608
+ const db = getDb();
609
+ expect(await hydrateActivationState(db, fork.id)).toBeNull();
610
+ expect(loadGraphMemoryState(fork.id)).toBeNull();
611
+ });
612
+ });
613
+
614
+ describe("forkConversation + memory_retrospective_state", () => {
615
+ beforeEach(() => {
616
+ resetTables();
617
+ });
618
+
619
+ test("does not seed state when the source has none", async () => {
620
+ const source = createConversation("Untouched thread");
621
+ await addMessage(source.id, "user", "Message 1", undefined, {
622
+ skipIndexing: true,
623
+ });
624
+
625
+ const fork = forkConversation({ conversationId: source.id });
626
+
627
+ expect(getRetrospectiveState(fork.id)).toBeNull();
628
+ });
629
+
630
+ test("maps the source pointer when it falls within the copied range", async () => {
631
+ const source = createConversation("In-range thread");
632
+ await addMessage(source.id, "user", "Message 1", undefined, {
633
+ skipIndexing: true,
634
+ });
635
+ const processedMessage = await addMessage(
636
+ source.id,
637
+ "assistant",
638
+ "Message 2",
639
+ undefined,
640
+ { skipIndexing: true },
641
+ );
642
+ await addMessage(source.id, "user", "Message 3", undefined, {
643
+ skipIndexing: true,
644
+ });
645
+
646
+ upsertRetrospectiveState({
647
+ conversationId: source.id,
648
+ lastProcessedMessageId: processedMessage.id,
649
+ lastRunAt: 1_700_000_000_000,
650
+ });
651
+
652
+ const fork = forkConversation({ conversationId: source.id });
653
+ const forkState = getRetrospectiveState(fork.id);
654
+ const forkMessages = getMessages(fork.id);
655
+ const mappedProcessedId = forkMessages.find((m) => {
656
+ const md = parseMetadata(m.metadata) as {
657
+ forkSourceMessageId?: string;
658
+ } | null;
659
+ return md?.forkSourceMessageId === processedMessage.id;
660
+ })?.id;
661
+
662
+ expect(mappedProcessedId).toBeDefined();
663
+ expect(forkState).not.toBeNull();
664
+ expect(forkState?.lastProcessedMessageId).toBe(mappedProcessedId);
665
+ expect(forkState?.lastRunAt).toBe(1_700_000_000_000);
666
+ });
667
+
668
+ test("clamps to the last copied message when the source pointer is past the fork boundary", async () => {
669
+ const source = createConversation("Past-boundary thread");
670
+ await addMessage(source.id, "user", "Message 1", undefined, {
671
+ skipIndexing: true,
672
+ });
673
+ const branchPoint = await addMessage(
674
+ source.id,
675
+ "assistant",
676
+ "Message 2",
677
+ undefined,
678
+ { skipIndexing: true },
679
+ );
680
+ const pastBoundaryMessage = await addMessage(
681
+ source.id,
682
+ "user",
683
+ "Message 3",
684
+ undefined,
685
+ { skipIndexing: true },
686
+ );
687
+ await addMessage(source.id, "assistant", "Message 4", undefined, {
688
+ skipIndexing: true,
689
+ });
690
+
691
+ upsertRetrospectiveState({
692
+ conversationId: source.id,
693
+ lastProcessedMessageId: pastBoundaryMessage.id,
694
+ lastRunAt: 1_700_000_000_000,
695
+ });
696
+
697
+ const fork = forkConversation({
698
+ conversationId: source.id,
699
+ throughMessageId: branchPoint.id,
700
+ });
701
+ const forkState = getRetrospectiveState(fork.id);
702
+ const forkMessages = getMessages(fork.id);
703
+ const lastForkedMessageId = forkMessages.at(-1)?.id;
704
+
705
+ expect(forkMessages).toHaveLength(2);
706
+ expect(forkState?.lastProcessedMessageId).toBe(lastForkedMessageId);
707
+ expect(forkState?.lastRunAt).toBe(1_700_000_000_000);
708
+ });
709
+
710
+ test("preserves the empty-string sentinel from a failure-only source", async () => {
711
+ const source = createConversation("Failure-only thread");
712
+ await addMessage(source.id, "user", "Message 1", undefined, {
713
+ skipIndexing: true,
714
+ });
715
+ bumpRetrospectiveLastRunAt(source.id, 1_700_000_000_000);
716
+
717
+ const fork = forkConversation({ conversationId: source.id });
718
+ const forkState = getRetrospectiveState(fork.id);
719
+
720
+ expect(forkState?.lastProcessedMessageId).toBe("");
721
+ expect(forkState?.lastRunAt).toBe(1_700_000_000_000);
722
+ });
723
+
724
+ test("copies lastRunAt so the cooldown gate inherits from the source", async () => {
725
+ const source = createConversation("Cooldown thread");
726
+ const message = await addMessage(
727
+ source.id,
728
+ "user",
729
+ "Message 1",
730
+ undefined,
731
+ { skipIndexing: true },
732
+ );
733
+ upsertRetrospectiveState({
734
+ conversationId: source.id,
735
+ lastProcessedMessageId: message.id,
736
+ lastRunAt: 1_700_000_000_000,
737
+ });
738
+
739
+ const fork = forkConversation({ conversationId: source.id });
740
+
741
+ expect(getRetrospectiveState(fork.id)?.lastRunAt).toBe(1_700_000_000_000);
742
+ });
503
743
  });
@@ -78,7 +78,7 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
78
78
  },
79
79
  });
80
80
 
81
- const result = profileRoute.handler({
81
+ const result = await profileRoute.handler({
82
82
  pathParams: { id: conversation.id },
83
83
  body: { profile: "quality-optimized" },
84
84
  headers: {},
@@ -86,7 +86,7 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
86
86
 
87
87
  await Promise.resolve();
88
88
 
89
- expect(result).toEqual({
89
+ expect(result).toMatchObject({
90
90
  conversationId: conversation.id,
91
91
  profile: "quality-optimized",
92
92
  });
@@ -104,23 +104,23 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
104
104
  subscription.dispose();
105
105
  });
106
106
 
107
- test("rejects unknown profile names with BadRequestError", () => {
107
+ test("rejects unknown profile names with BadRequestError", async () => {
108
108
  const conversation = createConversation("inference-profile-unknown");
109
109
 
110
- expect(() =>
110
+ await expect(
111
111
  profileRoute.handler({
112
112
  pathParams: { id: conversation.id },
113
113
  body: { profile: "does-not-exist" },
114
114
  headers: {},
115
115
  }),
116
- ).toThrow(BadRequestError);
116
+ ).rejects.toThrow(BadRequestError);
117
117
  expect(getConversation(conversation.id)?.inferenceProfile).toBeNull();
118
118
  });
119
119
 
120
120
  test("clears the override when profile is null", async () => {
121
121
  const conversation = createConversation("inference-profile-clear");
122
122
 
123
- profileRoute.handler({
123
+ await profileRoute.handler({
124
124
  pathParams: { id: conversation.id },
125
125
  body: { profile: "balanced" },
126
126
  headers: {},
@@ -137,7 +137,7 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
137
137
  },
138
138
  });
139
139
 
140
- const result = profileRoute.handler({
140
+ const result = await profileRoute.handler({
141
141
  pathParams: { id: conversation.id },
142
142
  body: { profile: null },
143
143
  headers: {},
@@ -145,7 +145,7 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
145
145
 
146
146
  await Promise.resolve();
147
147
 
148
- expect(result).toEqual({
148
+ expect(result).toMatchObject({
149
149
  conversationId: conversation.id,
150
150
  profile: null,
151
151
  });
@@ -158,7 +158,7 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
158
158
  test("skips write and event when the profile is unchanged", async () => {
159
159
  const conversation = createConversation("inference-profile-noop");
160
160
 
161
- profileRoute.handler({
161
+ await profileRoute.handler({
162
162
  pathParams: { id: conversation.id },
163
163
  body: { profile: "balanced" },
164
164
  headers: {},
@@ -175,7 +175,7 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
175
175
  },
176
176
  });
177
177
 
178
- const result = profileRoute.handler({
178
+ const result = await profileRoute.handler({
179
179
  pathParams: { id: conversation.id },
180
180
  body: { profile: "balanced" },
181
181
  headers: {},
@@ -183,7 +183,7 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
183
183
 
184
184
  await Promise.resolve();
185
185
 
186
- expect(result).toEqual({
186
+ expect(result).toMatchObject({
187
187
  conversationId: conversation.id,
188
188
  profile: "balanced",
189
189
  });
@@ -193,13 +193,13 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
193
193
  subscription.dispose();
194
194
  });
195
195
 
196
- test("throws NotFoundError when the conversation does not exist", () => {
197
- expect(() =>
196
+ test("throws NotFoundError when the conversation does not exist", async () => {
197
+ await expect(
198
198
  profileRoute.handler({
199
199
  pathParams: { id: "missing" },
200
200
  body: { profile: "balanced" },
201
201
  headers: {},
202
202
  }),
203
- ).toThrow(NotFoundError);
203
+ ).rejects.toThrow(NotFoundError);
204
204
  });
205
205
  });
@@ -136,6 +136,7 @@ mock.module("../config/loader.js", () => ({
136
136
  "fireworks",
137
137
  "brave",
138
138
  "perplexity",
139
+ "tavily",
139
140
  ],
140
141
  getConfig: () => mockConfig,
141
142
  getConfigReadOnly: () => mockConfig,
@@ -465,7 +466,7 @@ describe("End-to-end session creation benchmark", () => {
465
466
  timings.push(performance.now() - start);
466
467
 
467
468
  if (i === 0) {
468
- expect(session.eventBus.listenerCount()).toBeGreaterThan(0);
469
+ expect(session.eventBus.anyListenerCount()).toBeGreaterThan(0);
469
470
  }
470
471
  session.dispose();
471
472
  }
@@ -368,4 +368,128 @@ describe("loadFromDb metadata injection rehydration", () => {
368
368
  expect(messages).toHaveLength(2);
369
369
  expect(messages[0].content).toEqual([{ type: "text", text: "First" }]);
370
370
  });
371
+
372
+ test("historical user row rehydrates memoryV2StaticBlock between memory and system_reminder", async () => {
373
+ mockConversation = defaultConv();
374
+ mockDbMessages = [
375
+ {
376
+ id: "m1",
377
+ role: "user",
378
+ content: JSON.stringify([{ type: "text", text: "First turn" }]),
379
+ metadata: JSON.stringify({
380
+ memoryInjectedBlock: "mem payload",
381
+ memoryV2StaticBlock:
382
+ "<memory>\n## Essentials\n\nAlice prefers VS Code.\n</memory>",
383
+ pkbSystemReminderBlock:
384
+ "<system_reminder>\npkb payload\n</system_reminder>",
385
+ }),
386
+ },
387
+ {
388
+ id: "m2",
389
+ role: "assistant",
390
+ content: JSON.stringify([{ type: "text", text: "Reply" }]),
391
+ },
392
+ {
393
+ id: "m3",
394
+ role: "user",
395
+ content: JSON.stringify([{ type: "text", text: "Tail turn" }]),
396
+ },
397
+ ];
398
+
399
+ const conversation = makeConversation();
400
+ await conversation.loadFromDb();
401
+ const messages = conversation.getMessages();
402
+
403
+ expect(messages).toHaveLength(3);
404
+ expect(messages[0].role).toBe("user");
405
+ expect(messages[0].content).toEqual([
406
+ { type: "text", text: "<memory>\nmem payload\n</memory>" },
407
+ {
408
+ type: "text",
409
+ text: "<memory>\n## Essentials\n\nAlice prefers VS Code.\n</memory>",
410
+ },
411
+ {
412
+ type: "text",
413
+ text: "<system_reminder>\npkb payload\n</system_reminder>",
414
+ },
415
+ { type: "text", text: "First turn" },
416
+ ]);
417
+ });
418
+
419
+ test("tail user row skips memoryV2StaticBlock", async () => {
420
+ mockConversation = defaultConv();
421
+ mockDbMessages = [
422
+ {
423
+ id: "m1",
424
+ role: "user",
425
+ content: JSON.stringify([{ type: "text", text: "First" }]),
426
+ },
427
+ {
428
+ id: "m2",
429
+ role: "assistant",
430
+ content: JSON.stringify([{ type: "text", text: "Reply" }]),
431
+ },
432
+ {
433
+ id: "m3",
434
+ role: "user",
435
+ content: JSON.stringify([{ type: "text", text: "Tail" }]),
436
+ metadata: JSON.stringify({
437
+ memoryV2StaticBlock: "<memory>\n## Essentials\n\nleak\n</memory>",
438
+ }),
439
+ },
440
+ ];
441
+
442
+ const conversation = makeConversation();
443
+ await conversation.loadFromDb();
444
+ const messages = conversation.getMessages();
445
+
446
+ expect(messages).toHaveLength(3);
447
+ expect(messages[2].role).toBe("user");
448
+ // Tail row receives fresh injection on the next turn — the persisted
449
+ // static block must not rehydrate here.
450
+ expect(messages[2].content).toEqual([{ type: "text", text: "Tail" }]);
451
+ });
452
+
453
+ test("untrusted-actor view does not rehydrate memoryV2StaticBlock", async () => {
454
+ mockConversation = defaultConv();
455
+ // Rows with `trusted_contact` / `unknown` provenance survive the
456
+ // untrusted-actor row filter, so this isolates the rehydrate gate.
457
+ mockDbMessages = [
458
+ {
459
+ id: "m1",
460
+ role: "user",
461
+ content: JSON.stringify([{ type: "text", text: "First" }]),
462
+ metadata: JSON.stringify({
463
+ provenanceTrustClass: "trusted_contact",
464
+ memoryV2StaticBlock:
465
+ "<memory>\n## Essentials\n\nprivate memory\n</memory>",
466
+ }),
467
+ },
468
+ {
469
+ id: "m2",
470
+ role: "assistant",
471
+ content: JSON.stringify([{ type: "text", text: "Reply" }]),
472
+ metadata: JSON.stringify({ provenanceTrustClass: "unknown" }),
473
+ },
474
+ {
475
+ id: "m3",
476
+ role: "user",
477
+ content: JSON.stringify([{ type: "text", text: "Tail" }]),
478
+ metadata: JSON.stringify({ provenanceTrustClass: "trusted_contact" }),
479
+ },
480
+ ];
481
+
482
+ const conversation = makeConversation();
483
+ conversation.setTrustContext({
484
+ trustClass: "trusted_contact",
485
+ sourceChannel: "telegram",
486
+ });
487
+ await conversation.loadFromDb();
488
+ const messages = conversation.getMessages();
489
+
490
+ expect(messages).toHaveLength(3);
491
+ // The historical row survives row-level filtering but the rehydrate gate
492
+ // suppresses the personal-memory block.
493
+ expect(messages[0].content).toEqual([{ type: "text", text: "First" }]);
494
+ });
371
495
  });
@@ -15,7 +15,7 @@
15
15
  * instantiation block use at first-message time.
16
16
  */
17
17
 
18
- import { describe, expect, mock, test } from "bun:test";
18
+ import { afterEach, describe, expect, mock, test } from "bun:test";
19
19
 
20
20
  // ---------------------------------------------------------------------------
21
21
  // Module mocks for downstream side effects (DB writes, slash resolution,
@@ -28,6 +28,20 @@ mock.module("../util/logger.js", () => ({
28
28
  new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
29
29
  }));
30
30
 
31
+ /**
32
+ * Per-test capability client roster. Set in individual tests to simulate
33
+ * a connected macOS client for cross-client drain-path coverage. Reset in
34
+ * afterEach so tests don't bleed state.
35
+ */
36
+ let mockCapabilityClients: Array<{ clientId: string; actorPrincipalId?: string }> = [];
37
+
38
+ mock.module("../runtime/assistant-event-hub.js", () => ({
39
+ assistantEventHub: {
40
+ listClientsByCapability: () => mockCapabilityClients,
41
+ },
42
+ broadcastMessage: () => {},
43
+ }));
44
+
31
45
  mock.module("../memory/conversation-crud.js", () => ({
32
46
  setConversationOriginChannelIfUnset: () => {},
33
47
  setConversationOriginInterfaceIfUnset: () => {},
@@ -145,6 +159,7 @@ function makeFakeContext(opts: {
145
159
  },
146
160
  setTransportHints() {},
147
161
  applyHostEnvFromTransport() {},
162
+ ensureHostProxiesForTurn() {},
148
163
  } as unknown as ProcessConversationContext & FakeRecord;
149
164
  return ctx;
150
165
  }
@@ -170,6 +185,10 @@ function makeQueuedMessage(opts: {
170
185
  // ---------------------------------------------------------------------------
171
186
 
172
187
  describe("drainQueue preactivation re-add for host-proxy interfaces", () => {
188
+ afterEach(() => {
189
+ mockCapabilityClients = [];
190
+ });
191
+
173
192
  test("drainSingleMessage re-adds 'app-control' for macOS-sourced queued message", async () => {
174
193
  const queue = new MessageQueue();
175
194
  const ifCtx: TurnInterfaceContext = {
@@ -280,4 +299,84 @@ describe("drainQueue preactivation re-add for host-proxy interfaces", () => {
280
299
  expect(ctx.preactivatedSkillIdCalls).not.toContain("computer-use");
281
300
  expect(ctx.preactivatedSkillIdCalls).not.toContain("app-control");
282
301
  });
302
+
303
+ // ── Cross-client drain-path: web source + macOS client connected ──────
304
+
305
+ test("drainSingleMessage re-adds 'app-control' for web-sourced message when macOS client is connected", async () => {
306
+ mockCapabilityClients = [
307
+ { clientId: "macos-client-1", actorPrincipalId: "user-1" },
308
+ ];
309
+ const queue = new MessageQueue();
310
+ const ifCtx: TurnInterfaceContext = {
311
+ userMessageInterface: "web",
312
+ assistantMessageInterface: "web",
313
+ };
314
+ queue.push(
315
+ makeQueuedMessage({ requestId: "req-web-1", turnInterfaceContext: ifCtx }),
316
+ );
317
+ const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
318
+
319
+ await drainQueue(ctx);
320
+
321
+ // web natively supports neither host_cu nor host_app_control, but the
322
+ // connected macOS client provides both via cross-client routing — so
323
+ // both skills must be re-preactivated.
324
+ expect(ctx.preactivatedSkillIdCalls).toContain("app-control");
325
+ expect(ctx.preactivatedSkillIds).toContain("app-control");
326
+ expect(ctx.preactivatedSkillIdCalls).toContain("computer-use");
327
+ });
328
+
329
+ test("drainSingleMessage does NOT re-add 'app-control' for web-sourced message when no capable client is connected", async () => {
330
+ // mockCapabilityClients remains [] (reset by afterEach from prior test)
331
+ const queue = new MessageQueue();
332
+ const ifCtx: TurnInterfaceContext = {
333
+ userMessageInterface: "web",
334
+ assistantMessageInterface: "web",
335
+ };
336
+ queue.push(
337
+ makeQueuedMessage({ requestId: "req-web-2", turnInterfaceContext: ifCtx }),
338
+ );
339
+ const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
340
+
341
+ await drainQueue(ctx);
342
+
343
+ expect(ctx.preactivatedSkillIdCalls).not.toContain("app-control");
344
+ expect(ctx.preactivatedSkillIdCalls).not.toContain("computer-use");
345
+ });
346
+
347
+ test("drainSingleMessage re-adds 'computer-use' for web-sourced message when macOS client is connected", async () => {
348
+ mockCapabilityClients = [
349
+ { clientId: "macos-client-1", actorPrincipalId: "user-1" },
350
+ ];
351
+ const queue = new MessageQueue();
352
+ const ifCtx: TurnInterfaceContext = {
353
+ userMessageInterface: "web",
354
+ assistantMessageInterface: "web",
355
+ };
356
+ queue.push(
357
+ makeQueuedMessage({ requestId: "req-web-3", turnInterfaceContext: ifCtx }),
358
+ );
359
+ const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
360
+
361
+ await drainQueue(ctx);
362
+
363
+ expect(ctx.preactivatedSkillIdCalls).toContain("computer-use");
364
+ expect(ctx.preactivatedSkillIds).toContain("computer-use");
365
+ });
366
+
367
+ test("drainSingleMessage does NOT re-add 'computer-use' for web-sourced message when no capable client is connected", async () => {
368
+ const queue = new MessageQueue();
369
+ const ifCtx: TurnInterfaceContext = {
370
+ userMessageInterface: "web",
371
+ assistantMessageInterface: "web",
372
+ };
373
+ queue.push(
374
+ makeQueuedMessage({ requestId: "req-web-4", turnInterfaceContext: ifCtx }),
375
+ );
376
+ const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
377
+
378
+ await drainQueue(ctx);
379
+
380
+ expect(ctx.preactivatedSkillIdCalls).not.toContain("computer-use");
381
+ });
283
382
  });