@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
@@ -1,18 +1,16 @@
1
1
  /**
2
2
  * Tests for the v2 routing wired into `ConversationGraphMemory.prepareMemory`.
3
3
  *
4
- * The wiring layer at `conversation-graph-memory.ts` reads two signals to
5
- * decide whether to swap v1's injection step for the v2 activation pipeline:
4
+ * The wiring layer at `conversation-graph-memory.ts` reads
5
+ * `config.memory.v2.enabled` to decide whether to swap v1's injection step
6
+ * for the v2 activation pipeline.
6
7
  *
7
- * 1. The `memory-v2-enabled` feature flag (`isAssistantFeatureFlagEnabled`).
8
- * 2. The workspace config value `memory.v2.enabled`.
9
- *
10
- * Both must be true for v2 to take over. This file uses the *real*
11
- * `injectMemoryV2Block` and stubs only the lower-level deps (Qdrant client,
12
- * embedding backend) the way `memory/v2/__tests__/injection.test.ts` does
13
- * mocking `injection.js` itself would clobber that sibling test when both
14
- * files run in the same `bun test` invocation, since `mock.module` is
15
- * process-global. Avoiding the mock keeps the suite hermetic in either order.
8
+ * This file uses the *real* `injectMemoryV2Block` and stubs only the
9
+ * lower-level deps (Qdrant client, embedding backend) the way
10
+ * `memory/v2/__tests__/injection.test.ts` does — mocking `injection.js`
11
+ * itself would clobber that sibling test when both files run in the same
12
+ * `bun test` invocation, since `mock.module` is process-global. Avoiding
13
+ * the mock keeps the suite hermetic in either order.
16
14
  */
17
15
  import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
18
16
  import { tmpdir } from "node:os";
@@ -20,7 +18,6 @@ import { join } from "node:path";
20
18
  import { Database } from "bun:sqlite";
21
19
  import {
22
20
  afterAll,
23
- afterEach,
24
21
  beforeAll,
25
22
  beforeEach,
26
23
  describe,
@@ -98,9 +95,11 @@ class MockQdrantClient {
98
95
  _name: string,
99
96
  params: { using: string; limit: number; filter?: unknown },
100
97
  ) {
101
- const queue =
102
- qdrantState.queryResponses[params.using as "dense" | "sparse"];
103
- return queue.shift() ?? { points: [] };
98
+ // The four-channel hybrid query fires body-dense, body-sparse,
99
+ // summary-dense, summary-sparse in order; both dense channels share
100
+ // the dense queue and both sparse channels share the sparse queue.
101
+ const channel = params.using.endsWith("sparse") ? "sparse" : "dense";
102
+ return qdrantState.queryResponses[channel].shift() ?? { points: [] };
104
103
  }
105
104
  }
106
105
 
@@ -170,14 +169,14 @@ import type { DrizzleDb } from "../../db-connection.js";
170
169
 
171
170
  const { ConversationGraphMemory } =
172
171
  await import("../conversation-graph-memory.js");
173
- const { _setOverridesForTesting } =
174
- await import("../../../config/assistant-feature-flags.js");
175
172
  const { applyNestedDefaults } = await import("../../../config/loader.js");
176
173
  const { getSqliteFrom } = await import("../../db-connection.js");
177
174
  const { migrateActivationState } =
178
175
  await import("../../migrations/232-activation-state.js");
179
176
  const schema = await import("../../schema.js");
180
177
  const { _resetMemoryV2QdrantForTests } = await import("../../v2/qdrant.js");
178
+ const { hydrate: hydrateActivationState } =
179
+ await import("../../v2/activation-store.js");
181
180
 
182
181
  // The wiring layer calls `getDb()` to fetch the SQLite handle. We mock
183
182
  // only that one export and spread the real module so unrelated callers
@@ -240,10 +239,21 @@ function makeMemory(): InstanceType<typeof ConversationGraphMemory> {
240
239
  return m;
241
240
  }
242
241
 
243
- /** Stage one set of dense/sparse hits for each channel of the activation
244
- * pipeline (1 candidate query + 3 simBatch channels). */
242
+ /** Stage one set of body and summary dense/sparse hits for each channel of
243
+ * the activation pipeline (1 candidate query + 3 simBatch channels). Each
244
+ * `hybridQueryConceptPages` call now fires four sub-queries (body-dense,
245
+ * body-sparse, summary-dense, summary-sparse) so we push four entries per
246
+ * channel iteration. Hits without `summary*Score` set produce empty point
247
+ * lists for the summary channels — fine for tests that only care about body
248
+ * scoring. */
245
249
  function stageTurn(
246
- hits: Array<{ slug: string; denseScore?: number; sparseScore?: number }>,
250
+ hits: Array<{
251
+ slug: string;
252
+ denseScore?: number;
253
+ sparseScore?: number;
254
+ summaryDenseScore?: number;
255
+ summarySparseScore?: number;
256
+ }>,
247
257
  ): void {
248
258
  for (let i = 0; i < 4; i++) {
249
259
  qdrantState.queryResponses.dense.push({
@@ -256,6 +266,22 @@ function stageTurn(
256
266
  .filter((h) => h.sparseScore !== undefined)
257
267
  .map((h) => ({ score: h.sparseScore, payload: { slug: h.slug } })),
258
268
  });
269
+ qdrantState.queryResponses.dense.push({
270
+ points: hits
271
+ .filter((h) => h.summaryDenseScore !== undefined)
272
+ .map((h) => ({
273
+ score: h.summaryDenseScore,
274
+ payload: { slug: h.slug },
275
+ })),
276
+ });
277
+ qdrantState.queryResponses.sparse.push({
278
+ points: hits
279
+ .filter((h) => h.summarySparseScore !== undefined)
280
+ .map((h) => ({
281
+ score: h.summarySparseScore,
282
+ payload: { slug: h.slug },
283
+ })),
284
+ });
259
285
  }
260
286
  }
261
287
 
@@ -270,39 +296,12 @@ beforeEach(() => {
270
296
  _resetMemoryV2QdrantForTests();
271
297
  });
272
298
 
273
- afterEach(() => {
274
- _setOverridesForTesting({});
275
- });
276
-
277
299
  // ---------------------------------------------------------------------------
278
300
  // Tests
279
301
  // ---------------------------------------------------------------------------
280
302
 
281
303
  describe("ConversationGraphMemory.prepareMemory — v2 routing (per-turn path)", () => {
282
- test("flag off → v2 not run, messages unchanged", async () => {
283
- _setOverridesForTesting({ "memory-v2-enabled": false });
284
- stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
285
-
286
- const memory = makeMemory();
287
- const config = makeConfig(true);
288
- const messages = makeMessages();
289
-
290
- const result = await memory.prepareMemory(
291
- messages,
292
- config,
293
- new AbortController().signal,
294
- noopEvent,
295
- );
296
-
297
- expect(result.mode).toBe("per-turn");
298
- expect(result.injectedBlockText).toBeNull();
299
- // No v2 block prepended — the v1 retriever returned zero nodes so the
300
- // user message is exactly the input.
301
- expect(result.runMessages).toEqual(messages);
302
- });
303
-
304
- test("flag on + config off → v2 not run, messages unchanged", async () => {
305
- _setOverridesForTesting({ "memory-v2-enabled": true });
304
+ test("config off → v2 not run, messages unchanged", async () => {
306
305
  stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
307
306
 
308
307
  const memory = makeMemory();
@@ -321,8 +320,7 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (per-turn path)",
321
320
  expect(result.runMessages).toEqual(messages);
322
321
  });
323
322
 
324
- test("flag on + config on → v2 block prepended, mode is per-turn", async () => {
325
- _setOverridesForTesting({ "memory-v2-enabled": true });
323
+ test("config on → v2 block prepended, mode is per-turn", async () => {
326
324
  stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
327
325
 
328
326
  const memory = makeMemory();
@@ -339,7 +337,9 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (per-turn path)",
339
337
  expect(result.mode).toBe("per-turn");
340
338
  expect(result.injectedBlockText).not.toBeNull();
341
339
  expect(result.injectedBlockText).not.toContain("<memory>");
342
- expect(result.injectedBlockText).toContain("### alice-vscode");
340
+ expect(result.injectedBlockText).toContain(
341
+ "# memory/concepts/alice-vscode.md",
342
+ );
343
343
 
344
344
  // The leading content block on the user message is the v2 block,
345
345
  // wrapped exactly once.
@@ -361,7 +361,6 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (per-turn path)",
361
361
  // Regression for the double-wrap bug: v2 cached `lastInjectedBlock`
362
362
  // already wrapped, then `reinjectCachedMemory` re-wrapped via
363
363
  // `injectTextBlock`, producing `<memory>\n<memory>\n...\n</memory>\n</memory>`.
364
- _setOverridesForTesting({ "memory-v2-enabled": true });
365
364
  stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
366
365
 
367
366
  const memory = makeMemory();
@@ -388,11 +387,10 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (per-turn path)",
388
387
  expect(firstBlock.text.endsWith("\n</memory>")).toBe(true);
389
388
  expect(firstBlock.text.match(/<memory>/g)?.length).toBe(1);
390
389
  expect(firstBlock.text.match(/<\/memory>/g)?.length).toBe(1);
391
- expect(firstBlock.text).toContain("### alice-vscode");
390
+ expect(firstBlock.text).toContain("# memory/concepts/alice-vscode.md");
392
391
  });
393
392
 
394
- test("flag on + config on with empty Qdrant hits → no v2 block, v1 fallback skipped", async () => {
395
- _setOverridesForTesting({ "memory-v2-enabled": true });
393
+ test("config on with empty Qdrant hits → no v2 block, v1 fallback skipped", async () => {
396
394
  // No `stageTurn` call — every channel returns `{ points: [] }` so the
397
395
  // candidate set is empty and `injectMemoryV2Block` returns block=null.
398
396
  const memory = makeMemory();
@@ -412,8 +410,7 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (per-turn path)",
412
410
  });
413
411
 
414
412
  describe("ConversationGraphMemory.prepareMemory — v2 routing (context-load path)", () => {
415
- test("flag on + config on → v2 fires with mode=context-load", async () => {
416
- _setOverridesForTesting({ "memory-v2-enabled": true });
413
+ test("config on → v2 fires with mode=context-load", async () => {
417
414
  stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
418
415
 
419
416
  // Fresh memory → initialized=false → runContextLoad branch.
@@ -430,7 +427,9 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (context-load pat
430
427
 
431
428
  expect(result.mode).toBe("context-load");
432
429
  expect(result.injectedBlockText).not.toBeNull();
433
- expect(result.injectedBlockText).toContain("### alice-vscode");
430
+ expect(result.injectedBlockText).toContain(
431
+ "# memory/concepts/alice-vscode.md",
432
+ );
434
433
  // injectedBlockText is the unwrapped inner content; the wrapper is
435
434
  // applied at injection time on the run message.
436
435
  expect(result.injectedBlockText).not.toContain("<memory>");
@@ -443,12 +442,11 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (context-load pat
443
442
  expect(loadContextMemoryMock).not.toHaveBeenCalled();
444
443
  });
445
444
 
446
- test("flag off → v2 not run on first turn either", async () => {
447
- _setOverridesForTesting({ "memory-v2-enabled": false });
445
+ test("config off → v2 not run on first turn either", async () => {
448
446
  stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
449
447
 
450
448
  const memory = new ConversationGraphMemory("conv-test-cl-off");
451
- const config = makeConfig(true);
449
+ const config = makeConfig(false);
452
450
  const messages = makeMessages("first message of the conversation here");
453
451
 
454
452
  const result = await memory.prepareMemory(
@@ -462,3 +460,48 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (context-load pat
462
460
  expect(result.injectedBlockText).toBeNull();
463
461
  });
464
462
  });
463
+
464
+ describe("ConversationGraphMemory.onCompacted — v2 activation eviction", () => {
465
+ test("clears everInjected so a previously-injected slug can re-attach", async () => {
466
+ // Without this wiring, `selectInjections` keeps subtracting the slug from
467
+ // every per-turn delta even though compaction discarded the cached
468
+ // `<memory>` attachment that previously made it visible.
469
+ const conversationId = "conv-test-evict";
470
+ const memory = new ConversationGraphMemory(conversationId);
471
+ const config = makeConfig(true);
472
+
473
+ // Turn 1 — context-load fires (initialized=false), injecting alice-vscode.
474
+ stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
475
+ const initial = await memory.prepareMemory(
476
+ makeMessages("Tell me about Alice's editor preferences"),
477
+ config,
478
+ new AbortController().signal,
479
+ noopEvent,
480
+ );
481
+ expect(initial.injectedBlockText).toContain(
482
+ "# memory/concepts/alice-vscode.md",
483
+ );
484
+
485
+ const before = await hydrateActivationState(testDbHandle!, conversationId);
486
+ expect(before?.everInjected.map((e) => e.slug)).toContain("alice-vscode");
487
+
488
+ await memory.onCompacted(1);
489
+
490
+ const after = await hydrateActivationState(testDbHandle!, conversationId);
491
+ expect(after?.everInjected).toEqual([]);
492
+
493
+ // Turn 2 — same Qdrant relevance. With everInjected cleared the slug
494
+ // should appear again in the injection block (re-attached on the new
495
+ // user message after compaction).
496
+ stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
497
+ const next = await memory.prepareMemory(
498
+ makeMessages("And what about Alice's editor again?"),
499
+ config,
500
+ new AbortController().signal,
501
+ noopEvent,
502
+ );
503
+ expect(next.injectedBlockText).toContain(
504
+ "# memory/concepts/alice-vscode.md",
505
+ );
506
+ });
507
+ });
@@ -1,19 +1,14 @@
1
1
  /**
2
- * Tests for `handleRemember` flag-routing between v1 (PKB) and v2 (memory/).
2
+ * Tests for `handleRemember` routing between v1 (PKB) and v2 (memory/).
3
3
  *
4
- * Verifies:
5
- * - Flag on → writes go to `memory/buffer.md` + `memory/archive/<today>.md`
6
- * and NO PKB re-index job is enqueued.
7
- * - Flag off → existing PKB path is unchanged (writes to `pkb/buffer.md`
8
- * + `pkb/archive/<today>.md`, both files are re-indexed).
9
- * - Archive filename uses today's local date.
4
+ * Routing follows `config.memory.v2.enabled`: when true, writes go to
5
+ * memory/; otherwise they fall back to v1 PKB.
10
6
  */
11
7
  import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
12
8
  import { tmpdir } from "node:os";
13
9
  import { join } from "node:path";
14
10
  import {
15
11
  afterAll,
16
- afterEach,
17
12
  beforeAll,
18
13
  beforeEach,
19
14
  describe,
@@ -62,11 +57,13 @@ afterAll(() => {
62
57
  // Imports are deferred to after the env var is set so any internal use of
63
58
  // `getWorkspaceDir()` resolves to the tmpdir.
64
59
  const { handleRemember } = await import("../tool-handlers.js");
65
- const { _setOverridesForTesting } =
66
- await import("../../../config/assistant-feature-flags.js");
67
60
  const { applyNestedDefaults } = await import("../../../config/loader.js");
68
61
 
69
62
  const CONFIG = applyNestedDefaults({});
63
+ const CONFIG_V2_OFF = {
64
+ ...CONFIG,
65
+ memory: { ...CONFIG.memory, v2: { ...CONFIG.memory.v2, enabled: false } },
66
+ };
70
67
 
71
68
  beforeEach(() => {
72
69
  enqueueCalls.length = 0;
@@ -76,10 +73,6 @@ beforeEach(() => {
76
73
  rmSync(join(tmpWorkspace, "memory"), { recursive: true, force: true });
77
74
  });
78
75
 
79
- afterEach(() => {
80
- _setOverridesForTesting({});
81
- });
82
-
83
76
  function todaysArchiveBasename(now: Date = new Date()): string {
84
77
  const yyyy = now.getFullYear();
85
78
  const mm = String(now.getMonth() + 1).padStart(2, "0");
@@ -87,11 +80,7 @@ function todaysArchiveBasename(now: Date = new Date()): string {
87
80
  return `${yyyy}-${mm}-${dd}.md`;
88
81
  }
89
82
 
90
- describe("handleRemember — memory-v2 flag on", () => {
91
- beforeEach(() => {
92
- _setOverridesForTesting({ "memory-v2-enabled": true });
93
- });
94
-
83
+ describe("handleRemember — memory.v2.enabled on", () => {
95
84
  test("writes to memory/buffer.md and memory/archive/<today>.md", () => {
96
85
  const result = handleRemember(
97
86
  { content: "Alice prefers VS Code over Vim" },
@@ -175,17 +164,13 @@ describe("handleRemember — memory-v2 flag on", () => {
175
164
  });
176
165
  });
177
166
 
178
- describe("handleRemember — memory-v2 flag off (v1 PKB path)", () => {
179
- beforeEach(() => {
180
- _setOverridesForTesting({ "memory-v2-enabled": false });
181
- });
182
-
167
+ describe("handleRemember — memory.v2.enabled off (v1 PKB path)", () => {
183
168
  test("writes to pkb/buffer.md and pkb/archive/<today>.md", () => {
184
169
  const result = handleRemember(
185
170
  { content: "v1 path still works" },
186
171
  "conv-v1-1",
187
172
  "default",
188
- CONFIG,
173
+ CONFIG_V2_OFF,
189
174
  );
190
175
 
191
176
  expect(result.success).toBe(true);
@@ -206,7 +191,7 @@ describe("handleRemember — memory-v2 flag off (v1 PKB path)", () => {
206
191
  { content: "index me" },
207
192
  "conv-v1-2",
208
193
  "default",
209
- CONFIG,
194
+ CONFIG_V2_OFF,
210
195
  );
211
196
 
212
197
  expect(result.success).toBe(true);
@@ -0,0 +1,55 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ let flagEnabled = false;
4
+
5
+ mock.module("../../../config/assistant-feature-flags.js", () => ({
6
+ isAssistantFeatureFlagEnabled: (_key: string, _config: unknown) =>
7
+ flagEnabled,
8
+ }));
9
+
10
+ import { getRememberDescription } from "../tools.js";
11
+
12
+ const stubConfig = {} as unknown as Parameters<
13
+ typeof getRememberDescription
14
+ >[0];
15
+
16
+ describe("getRememberDescription", () => {
17
+ beforeEach(() => {
18
+ flagEnabled = false;
19
+ });
20
+
21
+ test("flag off — returns the default high-pressure description", () => {
22
+ const desc = getRememberDescription(stubConfig);
23
+ expect(desc).toContain("**CRITICAL:**");
24
+ expect(desc).toContain("most frequently used tool");
25
+ expect(desc).toContain("almost every turn");
26
+ });
27
+
28
+ test("flag on — returns the relaxed judgment-framing description", () => {
29
+ flagEnabled = true;
30
+ const desc = getRememberDescription(stubConfig);
31
+ expect(desc).not.toContain("**CRITICAL:**");
32
+ expect(desc).not.toContain("almost every turn");
33
+ expect(desc).toContain("a retrospective pass");
34
+ expect(desc).toContain("Use judgment");
35
+ });
36
+
37
+ test("the two variants differ", () => {
38
+ flagEnabled = false;
39
+ const off = getRememberDescription(stubConfig);
40
+ flagEnabled = true;
41
+ const on = getRememberDescription(stubConfig);
42
+ expect(off).not.toBe(on);
43
+ });
44
+
45
+ test("corrections-are-priority language is preserved in BOTH variants", () => {
46
+ flagEnabled = false;
47
+ expect(getRememberDescription(stubConfig)).toMatch(
48
+ /Corrections are.*highest priority/i,
49
+ );
50
+ flagEnabled = true;
51
+ expect(getRememberDescription(stubConfig)).toMatch(
52
+ /Corrections are.*highest priority/i,
53
+ );
54
+ });
55
+ });
@@ -7,8 +7,8 @@
7
7
  // ---------------------------------------------------------------------------
8
8
 
9
9
  import { and, desc, eq, inArray, ne, notInArray } from "drizzle-orm";
10
+ import { z } from "zod";
10
11
 
11
- import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
12
12
  import type { AssistantConfig } from "../../config/types.js";
13
13
  import { estimateTextTokens } from "../../context/token-estimator.js";
14
14
  import type { ServerMessage } from "../../daemon/message-protocol.js";
@@ -20,9 +20,16 @@ import type {
20
20
  import { getLogger } from "../../util/logger.js";
21
21
  import { getWorkspaceDir } from "../../util/platform.js";
22
22
  import { getDb } from "../db-connection.js";
23
+ import { embedWithRetry } from "../embed.js";
24
+ import { generateSparseEmbedding } from "../embedding-backend.js";
23
25
  import type { QdrantSparseVector } from "../qdrant-client.js";
24
26
  import { memorySummaries } from "../schema.js";
25
27
  import { conversations } from "../schema/conversations.js";
28
+ import {
29
+ evictCompactedTurns as evictCompactedTurnsV2,
30
+ hydrate as hydrateV2State,
31
+ save as saveV2State,
32
+ } from "../v2/activation-store.js";
26
33
  import {
27
34
  injectMemoryV2Block,
28
35
  type InjectMemoryV2Mode,
@@ -206,11 +213,33 @@ export class ConversationGraphMemory {
206
213
  * Notify that context compaction just happened.
207
214
  * On the next turn, we'll re-run full context load.
208
215
  */
209
- onCompacted(compactedMessageCount: number): void {
216
+ async onCompacted(compactedMessageCount: number): Promise<void> {
210
217
  // Evict everything — compaction summarized all prior turns.
211
218
  // The tracker can't know exactly which turns were compacted,
212
219
  // so we conservatively clear everything and reload.
213
- this.tracker.evictCompactedTurns(this.tracker.getTurn());
220
+ const upToTurn = this.tracker.getTurn();
221
+ this.tracker.evictCompactedTurns(upToTurn);
222
+
223
+ // Mirror the eviction on the v2 activation row: the cached `<memory>`
224
+ // attachments those slugs lived on are gone, but `everInjected` would
225
+ // otherwise keep them deduped from per-turn deltas forever.
226
+ try {
227
+ const db = getDb();
228
+ const state = await hydrateV2State(db, this.conversationId);
229
+ if (state) {
230
+ await saveV2State(
231
+ db,
232
+ this.conversationId,
233
+ evictCompactedTurnsV2(state, upToTurn),
234
+ );
235
+ }
236
+ } catch (err) {
237
+ log.warn(
238
+ { err: err instanceof Error ? err.message : String(err) },
239
+ "Failed to evict v2 activation state on compaction (non-fatal)",
240
+ );
241
+ }
242
+
214
243
  this.needsReload = true;
215
244
  log.info(
216
245
  { compactedMessageCount },
@@ -362,8 +391,15 @@ export class ConversationGraphMemory {
362
391
 
363
392
  return await this.runPerTurn(messages, config, abortSignal);
364
393
  } catch (err) {
394
+ const errCode =
395
+ err instanceof z.ZodError ? err.issues[0]?.code : undefined;
365
396
  log.warn(
366
- { err: err instanceof Error ? err.message : String(err) },
397
+ {
398
+ err: err instanceof Error ? err.message : String(err),
399
+ conversationId: this.conversationId,
400
+ turn: this.tracker.getTurn(),
401
+ errCode,
402
+ },
367
403
  "Memory retrieval failed (non-fatal)",
368
404
  );
369
405
  return noopResult;
@@ -396,10 +432,19 @@ export class ConversationGraphMemory {
396
432
  "",
397
433
  signal,
398
434
  );
399
- this.initialized = true;
400
- this.needsReload = false;
401
435
 
402
436
  if (v2.routed) {
437
+ // Surface a user-query embedding so PKB hint search still runs on v2
438
+ // turns. v1's `loadContextMemory` produced these as a side effect of
439
+ // hybrid retrieval; the v2 path skips that retrieval, so embed
440
+ // explicitly here.
441
+ const userQueryEmbed = await this.computeQueryVectors(
442
+ rawUserText ?? userQuery ?? "",
443
+ config,
444
+ signal,
445
+ );
446
+ this.initialized = true;
447
+ this.needsReload = false;
403
448
  this.lastInjectedBlock = v2.injectedBlockText;
404
449
  this.lastInjectedNodeIds = [];
405
450
  this.lastInjectedImages = new Map();
@@ -412,6 +457,8 @@ export class ConversationGraphMemory {
412
457
  mode: "context-load" as const,
413
458
  injectedBlockText: v2.injectedBlockText,
414
459
  metrics: null,
460
+ userQueryVector: userQueryEmbed.dense,
461
+ userQuerySparseVector: userQueryEmbed.sparse,
415
462
  };
416
463
  }
417
464
 
@@ -423,6 +470,12 @@ export class ConversationGraphMemory {
423
470
  config,
424
471
  signal,
425
472
  });
473
+ // Set initialized only after v1 retrieval succeeds. If `loadContextMemory`
474
+ // throws (transient DB/Qdrant failure), `prepareMemory` catches and
475
+ // returns noop, but we want the next turn to retry the bootstrap path
476
+ // rather than be stuck in per-turn mode.
477
+ this.initialized = true;
478
+ this.needsReload = false;
426
479
 
427
480
  if (result.nodes.length === 0) {
428
481
  this.lastInjectedBlock = null;
@@ -543,6 +596,14 @@ export class ConversationGraphMemory {
543
596
  signal,
544
597
  );
545
598
  if (v2.routed) {
599
+ // Surface a per-turn query embedding so PKB hint search still runs
600
+ // on v2 turns. v1's `retrieveForTurn` produced these as a side effect;
601
+ // the v2 path skips that retrieval, so embed explicitly here.
602
+ const perTurnEmbed = await this.computeQueryVectors(
603
+ userLast,
604
+ config,
605
+ signal,
606
+ );
546
607
  this.lastInjectedBlock = v2.injectedBlockText;
547
608
  this.lastInjectedNodeIds = [];
548
609
  this.lastInjectedImages = new Map();
@@ -555,6 +616,8 @@ export class ConversationGraphMemory {
555
616
  mode: "per-turn" as const,
556
617
  injectedBlockText: v2.injectedBlockText,
557
618
  metrics: null,
619
+ queryVector: perTurnEmbed.dense,
620
+ sparseVector: perTurnEmbed.sparse,
558
621
  };
559
622
  }
560
623
 
@@ -627,8 +690,37 @@ export class ConversationGraphMemory {
627
690
  }
628
691
 
629
692
  /**
630
- * Run the v2 activation pipeline when the `memory-v2-enabled` feature flag
631
- * *and* the workspace config (`memory.v2.enabled`) are both on.
693
+ * Embed a query string for PKB hint search on v2 turns. v1 retrieval
694
+ * produced these vectors as a side effect; on v2 we skip retrieval, so
695
+ * the agent loop loses the dense/sparse pair it needs to drive
696
+ * `buildPkbReminderWithHints`. Failures here degrade PKB hints to the
697
+ * static fallback rather than blocking the turn.
698
+ */
699
+ private async computeQueryVectors(
700
+ text: string,
701
+ config: AssistantConfig,
702
+ signal: AbortSignal,
703
+ ): Promise<{ dense?: number[]; sparse?: QdrantSparseVector }> {
704
+ const trimmed = text.trim();
705
+ if (trimmed.length === 0) return {};
706
+ let dense: number[] | undefined;
707
+ try {
708
+ const result = await embedWithRetry(config, [trimmed], { signal });
709
+ dense = result.vectors[0];
710
+ } catch (err) {
711
+ log.warn(
712
+ { err: err instanceof Error ? err.message : String(err) },
713
+ "Failed to embed query for PKB hints on v2 path",
714
+ );
715
+ }
716
+ const sparseRaw = generateSparseEmbedding(trimmed);
717
+ const sparse = sparseRaw.indices.length > 0 ? sparseRaw : undefined;
718
+ return { dense, sparse };
719
+ }
720
+
721
+ /**
722
+ * Run the v2 activation pipeline when the workspace config
723
+ * (`memory.v2.enabled`) is on.
632
724
  *
633
725
  * The two outcomes the caller distinguishes via `routed`:
634
726
  * - `routed: false` — v2 disabled; caller falls through to the legacy v1
@@ -650,10 +742,7 @@ export class ConversationGraphMemory {
650
742
  runMessages: Message[];
651
743
  injectedBlockText: string | null;
652
744
  }> {
653
- if (
654
- !isAssistantFeatureFlagEnabled("memory-v2-enabled", config) ||
655
- !config.memory.v2.enabled
656
- ) {
745
+ if (!config.memory.v2.enabled) {
657
746
  return { routed: false, runMessages: messages, injectedBlockText: null };
658
747
  }
659
748
 
@@ -693,7 +782,11 @@ export class ConversationGraphMemory {
693
782
  * Count the leading content blocks on a user message that were added by
694
783
  * `injectMemoryBlock`. Memory-injected images use a 3-block pattern
695
784
  * (opening `<memory_image>` text + image + closing `</memory_image>` text),
696
- * followed by a `<memory>…</memory>` text block (legacy `<memory __injected>` is also accepted). A legacy
785
+ * followed by a `<memory>…</memory>` text block (legacy `<memory __injected>` is also accepted).
786
+ * The bare `<memory>` form is matched only when the block also ends with
787
+ * `\n</memory>`, so user-authored content that happens to begin with
788
+ * `<memory>` (for example, a message discussing the XML-like markup) is not
789
+ * mistaken for an injected prefix and stripped on re-injection. A legacy
697
790
  * 2-block image pattern (no closing tag) is also accepted for backward
698
791
  * compatibility. The injection prefix is always contiguous at the start,
699
792
  * so we stop at the first non-memory block.
@@ -706,7 +799,8 @@ export function countMemoryPrefixBlocks(content: ContentBlock[]): number {
706
799
  const block = content[firstNonMemory];
707
800
  if (
708
801
  block.type === "text" &&
709
- (block.text.startsWith("<memory>\n") ||
802
+ ((block.text.startsWith("<memory>\n") &&
803
+ block.text.endsWith("\n</memory>")) ||
710
804
  block.text.startsWith("<memory __injected>\n"))
711
805
  ) {
712
806
  firstNonMemory++;
@@ -723,8 +723,12 @@ export function parseExtractionResponse(
723
723
 
724
724
  // Auto-create event trigger when event_date is set but LLM didn't include one,
725
725
  // or replace a malformed event trigger (event_date unset) with a valid one.
726
+ // Only auto-create for future events — past-dated memories (historical
727
+ // milestones, dated events that already happened) shouldn't generate
728
+ // ramp/follow-up reminders.
726
729
  if (
727
730
  node.eventDate != null &&
731
+ node.eventDate > now &&
728
732
  (!Array.isArray(raw.triggers) ||
729
733
  !raw.triggers.some((t) => t.type === "event" && t.event_date != null))
730
734
  ) {