@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,17 +1,16 @@
1
1
  /**
2
2
  * Tests for `assistant/src/memory/v2/consolidation-job.ts`.
3
3
  *
4
- * Coverage matrix (from PR 20 acceptance criteria):
5
- * - Flag off → no provider/wake calls; returns flag_off.
6
- * - Flag on, empty buffer → no wake call; returns empty_buffer.
7
- * - Flag on, non-empty buffer → bootstrap conversation, wake invoked with
8
- * the cutoff-templated prompt, follow-up jobs enqueued.
9
- * - Lock file already present → second call returns locked; first call's
10
- * in-flight semantics preserved by leaving the lock in place.
11
- * - Wake returns invoked: false → orphan conversation cleaned up; no
12
- * follow-up jobs enqueued.
13
- * - Wake throws → orphan conversation cleaned up; lock released; handler
14
- * does NOT propagate the error (treated like any other wake failure).
4
+ * Coverage matrix:
5
+ * - Flag off → no runner call; returns disabled.
6
+ * - Flag on, empty buffer → no runner call; returns empty_buffer.
7
+ * - Flag on, non-empty buffer → runner invoked with the cutoff-templated
8
+ * prompt and `suppressFailureNotifications: true`; follow-up jobs
9
+ * enqueued on success.
10
+ * - Lock file already present second call returns locked.
11
+ * - Runner returns ok=false → run_failed surfaced; NO follow-up jobs;
12
+ * `emitNotificationSignal` was NOT called as a result of the failure
13
+ * (suppression is honored end-to-end).
15
14
  *
16
15
  * Tests use temp workspaces (mkdtemp) and never touch `~/.vellum/`. Sample
17
16
  * content uses generic placeholders (Alice).
@@ -27,7 +26,6 @@ import { tmpdir } from "node:os";
27
26
  import { join } from "node:path";
28
27
  import {
29
28
  afterAll,
30
- afterEach,
31
29
  beforeAll,
32
30
  beforeEach,
33
31
  describe,
@@ -42,31 +40,49 @@ mock.module("../../../util/logger.js", () => ({
42
40
  getLogger: () => makeMockLogger(),
43
41
  }));
44
42
 
45
- // ── bootstrapConversation mock ──────────────────────────────────────
46
- let bootstrapCalls = 0;
47
- let bootstrapLastArgs: Record<string, unknown> | null = null;
48
-
49
- mock.module("../../conversation-bootstrap.js", () => ({
50
- bootstrapConversation: (opts: Record<string, unknown>) => {
51
- bootstrapCalls += 1;
52
- bootstrapLastArgs = opts;
53
- return { id: `conv-${bootstrapCalls}` };
43
+ // ── runBackgroundJob mock ───────────────────────────────────────────
44
+ //
45
+ // The consolidation handler delegates the bootstrap + processMessage +
46
+ // timeout + classification + suppress-aware emit to runBackgroundJob.
47
+ // We stub it here and assert (a) the runner is called with
48
+ // `suppressFailureNotifications: true`, and (b) the prompt + callSite
49
+ // + trustContext + origin match what the consolidation surface expects.
50
+ let runnerCalls = 0;
51
+ let runnerLastArgs: Record<string, unknown> | null = null;
52
+ let runnerImpl: () => Promise<{
53
+ conversationId: string;
54
+ ok: boolean;
55
+ error?: Error;
56
+ errorKind?: string;
57
+ }> = async () => ({ conversationId: "conv-1", ok: true });
58
+
59
+ mock.module("../../../runtime/background-job-runner.js", () => ({
60
+ runBackgroundJob: async (opts: Record<string, unknown>) => {
61
+ runnerCalls += 1;
62
+ runnerLastArgs = opts;
63
+ return runnerImpl();
54
64
  },
55
65
  }));
56
66
 
57
- // ── deleteConversation mock (orphan cleanup path) ───────────────────
58
- let deleteCalls = 0;
59
- const deletedIds: string[] = [];
60
- let deleteShouldThrow = false;
61
-
62
- mock.module("../../conversation-crud.js", () => ({
63
- deleteConversation: (id: string) => {
64
- deleteCalls += 1;
65
- deletedIds.push(id);
66
- if (deleteShouldThrow) {
67
- throw new Error("simulated delete failure");
68
- }
69
- return { segmentIds: [], deletedSummaryIds: [] };
67
+ // ── emitNotificationSignal spy ──────────────────────────────────────
68
+ //
69
+ // The runner is stubbed above, so the real `emit-signal` module never
70
+ // runs in these tests. We mock it as a defensive belt-and-suspenders
71
+ // assertion: even if the runner stub were swapped out for the real
72
+ // implementation, this counter would catch any path that ends up
73
+ // emitting a signal as a result of consolidation failure.
74
+ const emitCalls: Array<Record<string, unknown>> = [];
75
+
76
+ mock.module("../../../notifications/emit-signal.js", () => ({
77
+ emitNotificationSignal: async (params: Record<string, unknown>) => {
78
+ emitCalls.push(params);
79
+ return {
80
+ signalId: "sig-1",
81
+ deduplicated: false,
82
+ dispatched: true,
83
+ reason: "ok",
84
+ deliveryResults: [],
85
+ };
70
86
  },
71
87
  }));
72
88
 
@@ -88,28 +104,6 @@ mock.module("../../jobs-store.js", () => ({
88
104
  },
89
105
  }));
90
106
 
91
- // ── wakeAgentForOpportunity mock ────────────────────────────────────
92
- let wakeCalls = 0;
93
- let wakeLastArgs: Record<string, unknown> | null = null;
94
- let wakeShouldThrow = false;
95
- let wakeInvoked = true;
96
- let wakeReason: string | undefined;
97
-
98
- mock.module("../../../runtime/agent-wake.js", () => ({
99
- wakeAgentForOpportunity: async (opts: Record<string, unknown>) => {
100
- wakeCalls += 1;
101
- wakeLastArgs = opts;
102
- if (wakeShouldThrow) {
103
- throw new Error("simulated wake failure");
104
- }
105
- return {
106
- invoked: wakeInvoked,
107
- producedToolCalls: false,
108
- ...(wakeReason ? { reason: wakeReason } : {}),
109
- };
110
- },
111
- }));
112
-
113
107
  // ── Workspace pin ───────────────────────────────────────────────────
114
108
  let tmpWorkspace: string;
115
109
  let previousWorkspaceEnv: string | undefined;
@@ -129,19 +123,18 @@ afterAll(() => {
129
123
  rmSync(tmpWorkspace, { recursive: true, force: true });
130
124
  });
131
125
 
132
- const { _setOverridesForTesting } =
133
- await import("../../../config/assistant-feature-flags.js");
134
126
  const { memoryV2ConsolidateJob } = await import("../consolidation-job.js");
135
127
  const { CUTOFF_PLACEHOLDER, CONSOLIDATION_PROMPT } =
136
128
  await import("../prompts/consolidation.js");
137
129
 
138
- // `isAssistantFeatureFlagEnabled` ignores the `config` argument it receives
139
- // (resolution is purely from the overrides + registry caches), and the
140
- // resolver only reads `config.memory.v2.consolidation_prompt_path` so a
141
- // minimal stand-in covers both call sites without materializing the full
142
- // default config.
130
+ // The resolver only reads `config.memory.v2.enabled` and
131
+ // `config.memory.v2.consolidation_prompt_path`, so a minimal stand-in
132
+ // covers both call sites without materializing the full default config.
143
133
  const CONFIG = {
144
- memory: { v2: { consolidation_prompt_path: null } },
134
+ memory: { v2: { enabled: true, consolidation_prompt_path: null } },
135
+ } as Parameters<typeof memoryV2ConsolidateJob>[1];
136
+ const CONFIG_DISABLED = {
137
+ memory: { v2: { enabled: false, consolidation_prompt_path: null } },
145
138
  } as Parameters<typeof memoryV2ConsolidateJob>[1];
146
139
 
147
140
  function makeJob(): Parameters<typeof memoryV2ConsolidateJob>[0] {
@@ -173,56 +166,39 @@ beforeEach(() => {
173
166
  mkdirSync(join(memoryDir(), "concepts"), { recursive: true });
174
167
  mkdirSync(join(memoryDir(), "archive"), { recursive: true });
175
168
 
176
- bootstrapCalls = 0;
177
- bootstrapLastArgs = null;
178
- deleteCalls = 0;
179
- deletedIds.length = 0;
180
- deleteShouldThrow = false;
169
+ runnerCalls = 0;
170
+ runnerLastArgs = null;
171
+ runnerImpl = async () => ({ conversationId: "conv-1", ok: true });
172
+ emitCalls.length = 0;
181
173
  enqueuedJobs.length = 0;
182
174
  nextJobIdCounter = 0;
183
- wakeCalls = 0;
184
- wakeLastArgs = null;
185
- wakeShouldThrow = false;
186
- wakeInvoked = true;
187
- wakeReason = undefined;
188
- });
189
-
190
- afterEach(() => {
191
- _setOverridesForTesting({});
192
175
  });
193
176
 
194
177
  // ---------------------------------------------------------------------------
195
178
 
196
- describe("memoryV2ConsolidateJob — flag off", () => {
197
- test("returns flag_off without invoking the wake when flag is off", async () => {
198
- _setOverridesForTesting({ "memory-v2-enabled": false });
179
+ describe("memoryV2ConsolidateJob — v2 disabled", () => {
180
+ test("returns disabled without invoking the runner when memory.v2.enabled is false", async () => {
199
181
  writeFileSync(bufferPath(), "- [Apr 27, 9:00 AM] Alice prefers VS Code.\n");
200
182
 
201
- const result = await memoryV2ConsolidateJob(makeJob(), CONFIG);
183
+ const result = await memoryV2ConsolidateJob(makeJob(), CONFIG_DISABLED);
202
184
 
203
- expect(result).toEqual({ kind: "flag_off" });
204
- expect(bootstrapCalls).toBe(0);
205
- expect(wakeCalls).toBe(0);
185
+ expect(result).toEqual({ kind: "disabled" });
186
+ expect(runnerCalls).toBe(0);
206
187
  expect(enqueuedJobs).toHaveLength(0);
207
- // Lock must NOT linger on the flag-off path — the handler bailed before
188
+ // Lock must NOT linger on the disabled path — the handler bailed before
208
189
  // the lock was acquired.
209
190
  expect(existsSync(lockPath())).toBe(false);
210
191
  });
211
192
  });
212
193
 
213
- describe("memoryV2ConsolidateJob — flag on, empty buffer", () => {
214
- beforeEach(() => {
215
- _setOverridesForTesting({ "memory-v2-enabled": true });
216
- });
217
-
194
+ describe("memoryV2ConsolidateJob — empty buffer", () => {
218
195
  test("returns empty_buffer when buffer.md is missing", async () => {
219
196
  expect(existsSync(bufferPath())).toBe(false);
220
197
 
221
198
  const result = await memoryV2ConsolidateJob(makeJob(), CONFIG);
222
199
 
223
200
  expect(result).toEqual({ kind: "empty_buffer" });
224
- expect(bootstrapCalls).toBe(0);
225
- expect(wakeCalls).toBe(0);
201
+ expect(runnerCalls).toBe(0);
226
202
  expect(enqueuedJobs).toHaveLength(0);
227
203
  });
228
204
 
@@ -232,8 +208,7 @@ describe("memoryV2ConsolidateJob — flag on, empty buffer", () => {
232
208
  const result = await memoryV2ConsolidateJob(makeJob(), CONFIG);
233
209
 
234
210
  expect(result).toEqual({ kind: "empty_buffer" });
235
- expect(bootstrapCalls).toBe(0);
236
- expect(wakeCalls).toBe(0);
211
+ expect(runnerCalls).toBe(0);
237
212
  expect(enqueuedJobs).toHaveLength(0);
238
213
  });
239
214
 
@@ -244,9 +219,8 @@ describe("memoryV2ConsolidateJob — flag on, empty buffer", () => {
244
219
  });
245
220
  });
246
221
 
247
- describe("memoryV2ConsolidateJob — flag on, non-empty buffer", () => {
222
+ describe("memoryV2ConsolidateJob — non-empty buffer", () => {
248
223
  beforeEach(() => {
249
- _setOverridesForTesting({ "memory-v2-enabled": true });
250
224
  writeFileSync(
251
225
  bufferPath(),
252
226
  "- [Apr 27, 9:00 AM] Alice prefers VS Code over Vim.\n" +
@@ -254,32 +228,37 @@ describe("memoryV2ConsolidateJob — flag on, non-empty buffer", () => {
254
228
  );
255
229
  });
256
230
 
257
- test("bootstraps a background conversation and wakes the assistant with a templated prompt", async () => {
231
+ test("invokes runBackgroundJob with the cutoff-templated prompt and suppressFailureNotifications: true", async () => {
258
232
  const result = await memoryV2ConsolidateJob(makeJob(), CONFIG);
259
233
 
260
234
  expect(result.kind).toBe("invoked");
261
- expect(bootstrapCalls).toBe(1);
262
- expect(bootstrapLastArgs).toEqual({
263
- conversationType: "background",
264
- source: "memory_v2_consolidation",
265
- origin: "memory_consolidation",
266
- systemHint: "Running memory consolidation",
267
- groupId: "system:background",
235
+ expect(runnerCalls).toBe(1);
236
+ expect(runnerLastArgs).not.toBeNull();
237
+ expect(runnerLastArgs?.jobName).toBe("memory.consolidate");
238
+ expect(runnerLastArgs?.source).toBe("memory_v2_consolidation");
239
+ expect(runnerLastArgs?.callSite).toBe("mainAgent");
240
+ expect(runnerLastArgs?.origin).toBe("memory_consolidation");
241
+ // The whole point of this PR: opt out of activity.failed notifications
242
+ // because consolidation runs on tight intervals and transient failures
243
+ // would spam the home feed.
244
+ expect(runnerLastArgs?.suppressFailureNotifications).toBe(true);
245
+ expect(runnerLastArgs?.trustContext).toEqual({
246
+ sourceChannel: "vellum",
247
+ trustClass: "guardian",
268
248
  });
269
-
270
- expect(wakeCalls).toBe(1);
271
- expect(wakeLastArgs?.conversationId).toBe("conv-1");
272
- expect(wakeLastArgs?.source).toBe("memory_v2_consolidation");
273
-
274
- // The hint must contain the prompt body with the cutoff timestamp
275
- // substituted in. Asserting the placeholder is GONE catches a regression
276
- // where `replaceAll` is dropped and the model receives `{{CUTOFF}}`.
277
- const hint = wakeLastArgs?.hint as string;
278
- expect(hint).toContain("memory consolidation");
279
- expect(hint).not.toContain(CUTOFF_PLACEHOLDER);
280
- // Cutoff is an ISO-8601 timestamp check the year prefix matches the
281
- // current year so we know the substitution actually happened.
282
- expect(hint).toContain(`${new Date().getFullYear()}`);
249
+ expect(typeof runnerLastArgs?.timeoutMs).toBe("number");
250
+ expect((runnerLastArgs?.timeoutMs as number) > 0).toBe(true);
251
+
252
+ // The prompt must contain the rendered consolidation body with the
253
+ // cutoff substituted in. Asserting the placeholder is GONE catches a
254
+ // regression where `replaceAll` is dropped and the model receives
255
+ // `{{CUTOFF}}` literally.
256
+ const prompt = runnerLastArgs?.prompt as string;
257
+ expect(prompt).toContain("memory consolidation");
258
+ expect(prompt).not.toContain(CUTOFF_PLACEHOLDER);
259
+ // Cutoff is a buffer-entry-format timestamp (`Mon D, h:mm AM/PM`) so it
260
+ // compares like-with-like against `buffer.md` lines at minute precision.
261
+ expect(prompt).toMatch(/\b[A-Z][a-z]{2} \d{1,2}, \d{1,2}:\d{2} (AM|PM)\b/);
283
262
  });
284
263
 
285
264
  test("honors memory.v2.consolidation_prompt_path override when set", async () => {
@@ -288,16 +267,20 @@ describe("memoryV2ConsolidateJob — flag on, non-empty buffer", () => {
288
267
  "CUSTOM CONSOLIDATION at {{CUTOFF}}\n",
289
268
  );
290
269
  const overrideConfig = {
291
- memory: { v2: { consolidation_prompt_path: "custom-prompt.md" } },
270
+ memory: {
271
+ v2: { enabled: true, consolidation_prompt_path: "custom-prompt.md" },
272
+ },
292
273
  } as Parameters<typeof memoryV2ConsolidateJob>[1];
293
274
 
294
275
  const result = await memoryV2ConsolidateJob(makeJob(), overrideConfig);
295
276
 
296
277
  expect(result.kind).toBe("invoked");
297
- const hint = wakeLastArgs?.hint as string;
298
- expect(hint).toMatch(/^CUSTOM CONSOLIDATION at \d{4}-/);
299
- expect(hint).not.toContain("You are running memory consolidation");
300
- expect(hint).not.toContain(CUTOFF_PLACEHOLDER);
278
+ const prompt = runnerLastArgs?.prompt as string;
279
+ expect(prompt).toMatch(
280
+ /^CUSTOM CONSOLIDATION at [A-Z][a-z]{2} \d{1,2}, \d{1,2}:\d{2} (AM|PM)$/m,
281
+ );
282
+ expect(prompt).not.toContain("You are running memory consolidation");
283
+ expect(prompt).not.toContain(CUTOFF_PLACEHOLDER);
301
284
  });
302
285
 
303
286
  test("enqueues the memory_v2_reembed follow-up job on success", async () => {
@@ -321,54 +304,51 @@ describe("memoryV2ConsolidateJob — flag on, non-empty buffer", () => {
321
304
  expect(existsSync(lockPath())).toBe(false);
322
305
  });
323
306
 
324
- test("returns wake_failed and cleans up the orphan conversation when wake returns invoked: false", async () => {
325
- wakeInvoked = false;
326
- wakeReason = "no_resolver";
307
+ test("returns run_failed and skips follow-ups when the runner reports failure", async () => {
308
+ runnerImpl = async () => ({
309
+ conversationId: "conv-1",
310
+ ok: false,
311
+ error: new Error("simulated runner failure"),
312
+ errorKind: "exception",
313
+ });
327
314
 
328
315
  const result = await memoryV2ConsolidateJob(makeJob(), CONFIG);
329
316
 
330
- expect(result.kind).toBe("wake_failed");
331
- if (result.kind === "wake_failed") {
332
- expect(result.reason).toBe("no_resolver");
317
+ expect(result.kind).toBe("run_failed");
318
+ if (result.kind === "run_failed") {
319
+ expect(result.reason).toBe("simulated runner failure");
333
320
  }
334
- expect(deleteCalls).toBe(1);
335
- expect(deletedIds).toEqual(["conv-1"]);
336
- // Critical: do NOT enqueue follow-ups when the wake didn't run — there's
337
- // nothing for them to operate on.
321
+ // No follow-ups: the agent's writes may be partial and re-embedding
322
+ // partial state would be misleading.
338
323
  expect(enqueuedJobs).toHaveLength(0);
339
- });
340
-
341
- test("returns wake_failed without throwing when wake itself rejects", async () => {
342
- wakeShouldThrow = true;
343
-
344
- const result = await memoryV2ConsolidateJob(makeJob(), CONFIG);
345
-
346
- expect(result.kind).toBe("wake_failed");
347
- if (result.kind === "wake_failed") {
348
- expect(result.reason).toBe("simulated wake failure");
349
- }
350
- // Lock must still be released on the throw path.
324
+ // Lock must still be released on the failure path so the next
325
+ // scheduled consolidation can re-attempt.
351
326
  expect(existsSync(lockPath())).toBe(false);
352
- expect(deleteCalls).toBe(1);
353
- expect(enqueuedJobs).toHaveLength(0);
354
327
  });
355
328
 
356
- test("does not propagate when deleteConversation throws on the cleanup path", async () => {
357
- wakeInvoked = false;
358
- deleteShouldThrow = true;
329
+ test("does NOT emit a notification signal when the runner fails (suppression honored)", async () => {
330
+ // This is the user-visible payoff of `suppressFailureNotifications: true`:
331
+ // even when the runner stub reports a failure, the consolidation
332
+ // handler must not produce any notification side-effect. The runner
333
+ // itself owns the suppression behavior; this test guards the contract
334
+ // from the consolidation surface — if a future change ever bypasses
335
+ // the runner and emits its own signal on the failure path, this assert
336
+ // will catch it.
337
+ runnerImpl = async () => ({
338
+ conversationId: "conv-1",
339
+ ok: false,
340
+ error: new Error("network blip"),
341
+ errorKind: "model_provider",
342
+ });
359
343
 
360
- await expect(
361
- memoryV2ConsolidateJob(makeJob(), CONFIG),
362
- ).resolves.toMatchObject({ kind: "wake_failed" });
344
+ await memoryV2ConsolidateJob(makeJob(), CONFIG);
363
345
 
364
- expect(deleteCalls).toBe(1);
365
- expect(existsSync(lockPath())).toBe(false);
346
+ expect(emitCalls).toHaveLength(0);
366
347
  });
367
348
  });
368
349
 
369
350
  describe("memoryV2ConsolidateJob — concurrent invocations", () => {
370
351
  beforeEach(() => {
371
- _setOverridesForTesting({ "memory-v2-enabled": true });
372
352
  writeFileSync(bufferPath(), "- [Apr 27, 9:00 AM] Alice prefers VS Code.\n");
373
353
  });
374
354
 
@@ -385,8 +365,7 @@ describe("memoryV2ConsolidateJob — concurrent invocations", () => {
385
365
  if (result.kind === "locked") {
386
366
  expect(result.holder).toContain(`${process.pid}`);
387
367
  }
388
- expect(bootstrapCalls).toBe(0);
389
- expect(wakeCalls).toBe(0);
368
+ expect(runnerCalls).toBe(0);
390
369
  expect(enqueuedJobs).toHaveLength(0);
391
370
  // The live holder's lock must NOT be removed by a contender.
392
371
  expect(existsSync(lockPath())).toBe(true);
@@ -403,8 +382,7 @@ describe("memoryV2ConsolidateJob — concurrent invocations", () => {
403
382
  const result = await memoryV2ConsolidateJob(makeJob(), CONFIG);
404
383
 
405
384
  expect(result.kind).toBe("invoked");
406
- expect(bootstrapCalls).toBe(1);
407
- expect(wakeCalls).toBe(1);
385
+ expect(runnerCalls).toBe(1);
408
386
  // Lock is released in the finally block after a successful run.
409
387
  expect(existsSync(lockPath())).toBe(false);
410
388
  });
@@ -420,8 +398,7 @@ describe("memoryV2ConsolidateJob — concurrent invocations", () => {
420
398
  const result = await memoryV2ConsolidateJob(makeJob(), CONFIG);
421
399
 
422
400
  expect(result.kind).toBe("invoked");
423
- expect(bootstrapCalls).toBe(1);
424
- expect(wakeCalls).toBe(1);
401
+ expect(runnerCalls).toBe(1);
425
402
  expect(existsSync(lockPath())).toBe(false);
426
403
  });
427
404
  });
@@ -36,7 +36,7 @@ afterEach(() => {
36
36
  function makePage(slug: string, edges: string[] = [], body = ""): ConceptPage {
37
37
  return {
38
38
  slug,
39
- frontmatter: { edges, ref_files: [] },
39
+ frontmatter: { edges, ref_files: [], ref_urls: [] },
40
40
  body,
41
41
  };
42
42
  }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Tests for `assistant/src/memory/v2/frontmatter-sweep.ts`.
3
+ *
4
+ * Coverage:
5
+ * - Empty workspace → no warns, no throw.
6
+ * - One bad page (unknown frontmatter key) → exactly one warn carrying
7
+ * `errCode: "unrecognized_keys"` and the offending slug.
8
+ * - Two bad + one good page → two warns; good page produces nothing.
9
+ * - Malformed YAML → a warn surfaces; the sweep does not crash.
10
+ */
11
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
12
+ import { tmpdir } from "node:os";
13
+ import { join } from "node:path";
14
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
15
+
16
+ const warnCalls: Array<{ data: Record<string, unknown>; msg: string }> = [];
17
+ const recordingLogger = {
18
+ warn: (data: Record<string, unknown>, msg: string) => {
19
+ warnCalls.push({ data, msg });
20
+ },
21
+ info: () => {},
22
+ debug: () => {},
23
+ error: () => {},
24
+ trace: () => {},
25
+ fatal: () => {},
26
+ child: () => recordingLogger,
27
+ };
28
+
29
+ mock.module("../../../util/logger.js", () => ({
30
+ getLogger: () => recordingLogger,
31
+ }));
32
+
33
+ const { sweepConceptPageFrontmatter } = await import("../frontmatter-sweep.js");
34
+
35
+ function makeWorkspace(pages: Record<string, string>): string {
36
+ const dir = mkdtempSync(join(tmpdir(), "frontmatter-sweep-"));
37
+ const conceptsDir = join(dir, "memory", "concepts");
38
+ if (Object.keys(pages).length > 0) {
39
+ mkdirSync(conceptsDir, { recursive: true });
40
+ for (const [slug, content] of Object.entries(pages)) {
41
+ writeFileSync(join(conceptsDir, `${slug}.md`), content, "utf-8");
42
+ }
43
+ }
44
+ return dir;
45
+ }
46
+
47
+ const goodPage = `---\nedges: []\nref_files: []\n---\nbody\n`;
48
+ const badPage = `---\nedges: []\nref_files: []\nbogus_field: 1\n---\nbody\n`;
49
+
50
+ describe("sweepConceptPageFrontmatter", () => {
51
+ beforeEach(() => {
52
+ warnCalls.length = 0;
53
+ });
54
+ afterEach(() => {
55
+ warnCalls.length = 0;
56
+ });
57
+
58
+ test("empty workspace: no warns, no throw", async () => {
59
+ const dir = makeWorkspace({});
60
+ try {
61
+ await sweepConceptPageFrontmatter(dir);
62
+ expect(warnCalls).toHaveLength(0);
63
+ } finally {
64
+ rmSync(dir, { recursive: true, force: true });
65
+ }
66
+ });
67
+
68
+ test("one bad page emits exactly one unrecognized_keys warn", async () => {
69
+ const dir = makeWorkspace({ "bad-one": badPage });
70
+ try {
71
+ await sweepConceptPageFrontmatter(dir);
72
+ expect(warnCalls).toHaveLength(1);
73
+ expect(warnCalls[0].data.slug).toBe("bad-one");
74
+ expect(warnCalls[0].data.errCode).toBe("unrecognized_keys");
75
+ expect(warnCalls[0].data.errKeys).toEqual(["bogus_field"]);
76
+ } finally {
77
+ rmSync(dir, { recursive: true, force: true });
78
+ }
79
+ });
80
+
81
+ test("two bad and one good page: one warn per bad slug, none for the good", async () => {
82
+ const dir = makeWorkspace({
83
+ good: goodPage,
84
+ "bad-a": badPage,
85
+ "bad-b": badPage,
86
+ });
87
+ try {
88
+ await sweepConceptPageFrontmatter(dir);
89
+ const slugs = warnCalls.map((c) => c.data.slug).sort();
90
+ expect(slugs).toEqual(["bad-a", "bad-b"]);
91
+ for (const call of warnCalls) {
92
+ expect(call.data.errCode).toBe("unrecognized_keys");
93
+ }
94
+ } finally {
95
+ rmSync(dir, { recursive: true, force: true });
96
+ }
97
+ });
98
+
99
+ test("malformed YAML: warn surfaces, sweep does not throw", async () => {
100
+ const dir = makeWorkspace({
101
+ mangled: `---\nedges: [unterminated\n---\nbody\n`,
102
+ });
103
+ try {
104
+ await sweepConceptPageFrontmatter(dir);
105
+ expect(warnCalls.length).toBeGreaterThanOrEqual(1);
106
+ expect(warnCalls.some((c) => c.data.slug === "mangled")).toBe(true);
107
+ } finally {
108
+ rmSync(dir, { recursive: true, force: true });
109
+ }
110
+ });
111
+ });