@vellumai/assistant 0.7.2 → 0.7.3

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 (347) hide show
  1. package/ARCHITECTURE.md +16 -1
  2. package/docs/architecture/memory.md +5 -2
  3. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +13 -4
  4. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -9
  5. package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
  6. package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
  7. package/openapi.yaml +449 -22
  8. package/package.json +1 -1
  9. package/src/__tests__/app-control-flow.test.ts +21 -11
  10. package/src/__tests__/assistant-event-hub.test.ts +48 -0
  11. package/src/__tests__/assistant-event.test.ts +0 -10
  12. package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -7
  13. package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -0
  14. package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
  15. package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
  16. package/src/__tests__/call-conversation-messages.test.ts +8 -2
  17. package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
  18. package/src/__tests__/channel-readiness-service.test.ts +4 -2
  19. package/src/__tests__/config-loader-backfill.test.ts +379 -0
  20. package/src/__tests__/config-schema.test.ts +1 -0
  21. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +18 -9
  22. package/src/__tests__/config-watcher.test.ts +140 -69
  23. package/src/__tests__/context-search-agent-runner.test.ts +61 -3
  24. package/src/__tests__/context-search-conversations-source.test.ts +0 -24
  25. package/src/__tests__/context-search-fanout.test.ts +0 -1
  26. package/src/__tests__/context-search-memory-source.test.ts +3 -7
  27. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
  28. package/src/__tests__/context-search-pkb-source.test.ts +0 -1
  29. package/src/__tests__/context-search-workspace-source.test.ts +0 -1
  30. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  31. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
  32. package/src/__tests__/conversation-agent-loop.test.ts +454 -5
  33. package/src/__tests__/conversation-error.test.ts +150 -3
  34. package/src/__tests__/conversation-process-callsite.test.ts +43 -0
  35. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  36. package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
  37. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  38. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  39. package/src/__tests__/conversation-store.test.ts +0 -18
  40. package/src/__tests__/conversation-surfaces-app-control.test.ts +15 -4
  41. package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
  42. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
  43. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  44. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  45. package/src/__tests__/credentials-cli.test.ts +7 -0
  46. package/src/__tests__/cu-unified-flow.test.ts +176 -10
  47. package/src/__tests__/date-context.test.ts +164 -2
  48. package/src/__tests__/disk-pressure-guard.test.ts +262 -0
  49. package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
  50. package/src/__tests__/disk-pressure-policy.test.ts +241 -0
  51. package/src/__tests__/disk-pressure-routes.test.ts +379 -0
  52. package/src/__tests__/disk-pressure-tools.test.ts +277 -0
  53. package/src/__tests__/disk-usage.test.ts +150 -0
  54. package/src/__tests__/events-client-registration.test.ts +52 -0
  55. package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
  56. package/src/__tests__/file-write-tool.test.ts +4 -10
  57. package/src/__tests__/filing-service.test.ts +3 -4
  58. package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
  59. package/src/__tests__/heartbeat-service.test.ts +260 -11
  60. package/src/__tests__/host-app-control-proxy.test.ts +195 -25
  61. package/src/__tests__/host-bash-proxy.test.ts +227 -34
  62. package/src/__tests__/host-bash-routes.test.ts +178 -13
  63. package/src/__tests__/host-cu-proxy.test.ts +210 -3
  64. package/src/__tests__/host-cu-routes-targeted.test.ts +141 -12
  65. package/src/__tests__/host-file-proxy-targeted.test.ts +48 -9
  66. package/src/__tests__/host-file-proxy.test.ts +268 -6
  67. package/src/__tests__/host-file-routes-targeted.test.ts +175 -17
  68. package/src/__tests__/host-transfer-proxy-targeted.test.ts +408 -59
  69. package/src/__tests__/host-transfer-routes-targeted.test.ts +232 -17
  70. package/src/__tests__/http-user-message-parity.test.ts +107 -1
  71. package/src/__tests__/injector-chain.test.ts +18 -6
  72. package/src/__tests__/injector-disk-pressure.test.ts +224 -0
  73. package/src/__tests__/managed-profile-guard.test.ts +18 -0
  74. package/src/__tests__/mcp-abort-signal.test.ts +130 -0
  75. package/src/__tests__/memory-admin-recall.test.ts +3 -11
  76. package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
  77. package/src/__tests__/normalize-onboarding.test.ts +180 -0
  78. package/src/__tests__/oauth-connect-routes.test.ts +316 -0
  79. package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
  80. package/src/__tests__/onboarding-persona-write.test.ts +308 -0
  81. package/src/__tests__/openai-provider.test.ts +45 -8
  82. package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
  83. package/src/__tests__/platform-callback-registration.test.ts +21 -4
  84. package/src/__tests__/platform.test.ts +2 -1
  85. package/src/__tests__/playbook-execution.test.ts +0 -43
  86. package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
  87. package/src/__tests__/prechat-onboarding-contract.test.ts +214 -27
  88. package/src/__tests__/provider-tool-name.test.ts +23 -0
  89. package/src/__tests__/relay-server.test.ts +15 -4
  90. package/src/__tests__/runtime-events-sse.test.ts +4 -8
  91. package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
  92. package/src/__tests__/secret-ingress-http.test.ts +0 -1
  93. package/src/__tests__/suggestion-routes.test.ts +46 -0
  94. package/src/__tests__/twilio-validation.test.ts +2 -2
  95. package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
  96. package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
  97. package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
  98. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
  99. package/src/approvals/guardian-decision-primitive.ts +13 -0
  100. package/src/approvals/guardian-request-resolvers.ts +16 -17
  101. package/src/backup/snapshot-lock.ts +2 -27
  102. package/src/bundler/compiler-tools.ts +3 -2
  103. package/src/calls/call-conversation-messages.ts +46 -10
  104. package/src/cli/commands/__tests__/webhooks.test.ts +0 -4
  105. package/src/cli/commands/bash.ts +35 -108
  106. package/src/cli/commands/contacts.ts +64 -25
  107. package/src/cli/commands/credentials.ts +56 -0
  108. package/src/cli/commands/memory-v2.ts +7 -6
  109. package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
  110. package/src/cli/commands/oauth/connect.ts +127 -1
  111. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -3
  112. package/src/cli/commands/platform/__tests__/connect.test.ts +7 -1
  113. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  114. package/src/cli/commands/platform/__tests__/status.test.ts +103 -6
  115. package/src/cli/commands/platform/index.ts +16 -7
  116. package/src/cli/commands/status.ts +57 -0
  117. package/src/cli/program.ts +4 -2
  118. package/src/config/assistant-feature-flags.ts +13 -3
  119. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
  120. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +13 -7
  121. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
  122. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
  123. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
  124. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
  125. package/src/config/env.ts +0 -8
  126. package/src/config/feature-flag-registry.json +27 -3
  127. package/src/config/loader.ts +127 -8
  128. package/src/config/schemas/__tests__/memory-v2.test.ts +10 -5
  129. package/src/config/schemas/call-site-catalog.ts +14 -0
  130. package/src/config/schemas/channels.ts +0 -5
  131. package/src/config/schemas/heartbeat.ts +1 -1
  132. package/src/config/schemas/llm.ts +2 -0
  133. package/src/config/schemas/memory-lifecycle.ts +13 -0
  134. package/src/config/schemas/memory-v2.ts +75 -11
  135. package/src/config/schemas/platform.ts +43 -3
  136. package/src/config/schemas/services.ts +28 -0
  137. package/src/config/seed-inference-profiles.ts +230 -33
  138. package/src/contacts/contact-store.ts +0 -25
  139. package/src/daemon/__tests__/conversation-tool-setup.test.ts +86 -25
  140. package/src/daemon/assistant-attachments.ts +4 -4
  141. package/src/daemon/config-watcher.ts +85 -57
  142. package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
  143. package/src/daemon/conversation-agent-loop.ts +170 -33
  144. package/src/daemon/conversation-error.ts +87 -15
  145. package/src/daemon/conversation-lifecycle.ts +1 -3
  146. package/src/daemon/conversation-process.ts +8 -0
  147. package/src/daemon/conversation-runtime-assembly.ts +26 -0
  148. package/src/daemon/conversation-store.ts +2 -2
  149. package/src/daemon/conversation-surfaces.ts +195 -15
  150. package/src/daemon/conversation-tool-setup.ts +57 -14
  151. package/src/daemon/conversation.ts +17 -22
  152. package/src/daemon/date-context.ts +71 -22
  153. package/src/daemon/disk-pressure-background-gate.ts +73 -0
  154. package/src/daemon/disk-pressure-guard.ts +343 -0
  155. package/src/daemon/disk-pressure-policy.ts +163 -0
  156. package/src/daemon/handlers/shared.ts +0 -1
  157. package/src/daemon/handlers/skills.ts +3 -4
  158. package/src/daemon/host-app-control-proxy.ts +137 -41
  159. package/src/daemon/host-bash-proxy.ts +46 -21
  160. package/src/daemon/host-cu-proxy.ts +49 -3
  161. package/src/daemon/host-file-proxy.ts +43 -7
  162. package/src/daemon/host-transfer-proxy.ts +95 -4
  163. package/src/daemon/lifecycle.ts +79 -28
  164. package/src/daemon/meet-host-supervisor.ts +4 -4
  165. package/src/daemon/meet-manifest-loader.ts +0 -1
  166. package/src/daemon/memory-v2-startup.ts +14 -4
  167. package/src/daemon/message-protocol.ts +3 -0
  168. package/src/daemon/message-types/conversations.ts +4 -0
  169. package/src/daemon/message-types/disk-pressure.ts +9 -0
  170. package/src/daemon/message-types/messages.ts +3 -0
  171. package/src/daemon/profiler-run-store.ts +5 -5
  172. package/src/daemon/tool-setup-types.ts +2 -2
  173. package/src/documents/document-store.ts +85 -0
  174. package/src/filing/filing-service.ts +30 -5
  175. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +9 -16
  176. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +36 -0
  177. package/src/heartbeat/heartbeat-run-store.ts +13 -0
  178. package/src/heartbeat/heartbeat-service.ts +205 -31
  179. package/src/home/feed-scheduler.ts +18 -0
  180. package/src/inbound/platform-callback-registration.ts +8 -15
  181. package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
  182. package/src/ipc/assistant-server.ts +56 -2
  183. package/src/ipc/gateway-client.ts +37 -3
  184. package/src/live-voice/live-voice-archive.ts +4 -4
  185. package/src/live-voice/protocol.ts +5 -7
  186. package/src/media/image-service.ts +1 -7
  187. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
  188. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
  189. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
  190. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
  191. package/src/memory/admin.ts +5 -9
  192. package/src/memory/context-search/agent-runner.ts +19 -2
  193. package/src/memory/context-search/sources/conversations.ts +2 -11
  194. package/src/memory/context-search/sources/memory-v2.ts +5 -4
  195. package/src/memory/context-search/sources/memory.ts +0 -1
  196. package/src/memory/context-search/types.ts +0 -1
  197. package/src/memory/conversation-crud.ts +4 -12
  198. package/src/memory/db-init.ts +2 -0
  199. package/src/memory/embedding-runtime-manager.ts +119 -5
  200. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +32 -21
  201. package/src/memory/graph/conversation-graph-memory.ts +42 -54
  202. package/src/memory/graph/extraction.ts +1 -3
  203. package/src/memory/graph/graph-search.test.ts +10 -67
  204. package/src/memory/graph/graph-search.ts +1 -20
  205. package/src/memory/graph/retriever.test.ts +6 -0
  206. package/src/memory/graph/retriever.ts +6 -10
  207. package/src/memory/indexer.ts +54 -45
  208. package/src/memory/job-handlers/backfill.ts +2 -11
  209. package/src/memory/job-handlers/cleanup.ts +43 -0
  210. package/src/memory/job-handlers/embedding.ts +6 -8
  211. package/src/memory/job-handlers/summarization.ts +2 -7
  212. package/src/memory/jobs-store.ts +48 -0
  213. package/src/memory/jobs-worker.ts +81 -43
  214. package/src/memory/memory-v2-activation-log-store.ts +32 -14
  215. package/src/memory/memory-v2-concept-frequency.ts +169 -0
  216. package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
  217. package/src/memory/migrations/index.ts +1 -0
  218. package/src/memory/pkb/pkb-search.test.ts +6 -0
  219. package/src/memory/qdrant-client.ts +0 -13
  220. package/src/memory/rerank-local.ts +374 -0
  221. package/src/memory/search/semantic.ts +6 -67
  222. package/src/memory/trace-event-store.ts +1 -17
  223. package/src/memory/v2/__tests__/activation.test.ts +311 -250
  224. package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
  225. package/src/memory/v2/__tests__/injection.test.ts +157 -167
  226. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
  227. package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
  228. package/src/memory/v2/__tests__/reranker.test.ts +338 -0
  229. package/src/memory/v2/__tests__/sim.test.ts +5 -199
  230. package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
  231. package/src/memory/v2/__tests__/static-context.test.ts +76 -1
  232. package/src/memory/v2/activation.ts +149 -156
  233. package/src/memory/v2/consolidation-job.ts +62 -12
  234. package/src/memory/v2/injection.ts +47 -60
  235. package/src/memory/v2/prompts/consolidation.ts +36 -1
  236. package/src/memory/v2/qdrant.ts +99 -0
  237. package/src/memory/v2/reranker.ts +177 -0
  238. package/src/memory/v2/sim.ts +10 -84
  239. package/src/memory/v2/skill-content.ts +4 -3
  240. package/src/memory/v2/skill-store.ts +82 -59
  241. package/src/memory/v2/static-context.ts +22 -0
  242. package/src/memory/v2/types.ts +10 -10
  243. package/src/notifications/copy-composer.ts +13 -0
  244. package/src/notifications/signal.ts +4 -0
  245. package/src/oauth/AGENTS.md +3 -1
  246. package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
  247. package/src/oauth/connect-orchestrator.ts +2 -0
  248. package/src/oauth/connection-resolver.test.ts +66 -1
  249. package/src/oauth/connection-resolver.ts +55 -1
  250. package/src/oauth/oauth-connect-state.ts +77 -0
  251. package/src/oauth/seed-providers.ts +58 -1
  252. package/src/plugins/defaults/injectors.ts +35 -2
  253. package/src/plugins/defaults/memory-retrieval.ts +5 -6
  254. package/src/plugins/types.ts +7 -0
  255. package/src/proactive-artifact/aux-message-injector.ts +74 -0
  256. package/src/proactive-artifact/decision.test.ts +226 -0
  257. package/src/proactive-artifact/decision.ts +165 -0
  258. package/src/proactive-artifact/index.ts +7 -0
  259. package/src/proactive-artifact/job.test.ts +867 -0
  260. package/src/proactive-artifact/job.ts +352 -0
  261. package/src/proactive-artifact/message-copy.ts +41 -0
  262. package/src/proactive-artifact/trigger-state.test.ts +277 -0
  263. package/src/proactive-artifact/trigger-state.ts +119 -0
  264. package/src/prompts/normalize-onboarding.ts +80 -0
  265. package/src/prompts/persona-resolver.ts +101 -9
  266. package/src/prompts/system-prompt.ts +21 -7
  267. package/src/prompts/templates/BOOTSTRAP.md +13 -5
  268. package/src/providers/__tests__/retry-callsite.test.ts +222 -1
  269. package/src/providers/model-intents.ts +7 -0
  270. package/src/providers/openrouter/client.ts +8 -0
  271. package/src/providers/retry.ts +50 -0
  272. package/src/providers/types.ts +1 -0
  273. package/src/runtime/__tests__/agent-wake.test.ts +456 -3
  274. package/src/runtime/agent-wake.ts +238 -100
  275. package/src/runtime/assistant-event-hub.ts +36 -6
  276. package/src/runtime/assistant-event.ts +0 -1
  277. package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
  278. package/src/runtime/auth/route-policy.ts +14 -1
  279. package/src/runtime/auth/same-actor.ts +216 -0
  280. package/src/runtime/channel-retry-sweep.ts +65 -1
  281. package/src/runtime/guardian-reply-router.ts +10 -0
  282. package/src/runtime/local-actor-identity.ts +52 -11
  283. package/src/runtime/pending-interactions.ts +8 -0
  284. package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
  285. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +0 -5
  286. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  287. package/src/runtime/routes/client-routes.ts +20 -2
  288. package/src/runtime/routes/contact-routes.ts +0 -25
  289. package/src/runtime/routes/conversation-routes.ts +35 -26
  290. package/src/runtime/routes/debug-bash-routes.ts +163 -0
  291. package/src/runtime/routes/disk-pressure-routes.ts +121 -0
  292. package/src/runtime/routes/document-pdf-renderer.ts +6 -2
  293. package/src/runtime/routes/documents-routes.ts +2 -75
  294. package/src/runtime/routes/events-routes.ts +41 -9
  295. package/src/runtime/routes/host-bash-routes.ts +23 -3
  296. package/src/runtime/routes/host-cu-routes.ts +33 -6
  297. package/src/runtime/routes/host-file-routes.ts +32 -6
  298. package/src/runtime/routes/host-transfer-routes.ts +79 -16
  299. package/src/runtime/routes/identity-routes.ts +7 -138
  300. package/src/runtime/routes/inbound-message-handler.ts +77 -12
  301. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
  302. package/src/runtime/routes/index.ts +6 -0
  303. package/src/runtime/routes/memory-item-routes.test.ts +41 -15
  304. package/src/runtime/routes/memory-v2-routes.ts +33 -0
  305. package/src/runtime/routes/oauth-connect-routes.ts +153 -0
  306. package/src/runtime/verification-outbound-actions.ts +4 -4
  307. package/src/schedule/run-script.ts +37 -5
  308. package/src/schedule/scheduler.ts +20 -1
  309. package/src/security/encrypted-store.ts +2 -0
  310. package/src/security/secure-keys.ts +55 -0
  311. package/src/skills/remote-skill-policy.ts +4 -10
  312. package/src/subagent/index.ts +1 -7
  313. package/src/subagent/manager.ts +1 -15
  314. package/src/tasks/task-runner.ts +0 -1
  315. package/src/tasks/task-store.ts +0 -3
  316. package/src/tools/background-tool-registry.ts +17 -3
  317. package/src/tools/host-filesystem/edit.test.ts +151 -0
  318. package/src/tools/host-filesystem/edit.ts +43 -1
  319. package/src/tools/host-filesystem/read.test.ts +129 -0
  320. package/src/tools/host-filesystem/read.ts +43 -1
  321. package/src/tools/host-filesystem/transfer.test.ts +127 -2
  322. package/src/tools/host-filesystem/transfer.ts +56 -11
  323. package/src/tools/host-filesystem/write.test.ts +134 -0
  324. package/src/tools/host-filesystem/write.ts +43 -1
  325. package/src/tools/host-terminal/host-shell.ts +13 -6
  326. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  327. package/src/tools/memory/register.test.ts +12 -9
  328. package/src/tools/memory/register.ts +1 -2
  329. package/src/tools/provider-tool-name.ts +28 -0
  330. package/src/tools/registry.ts +30 -9
  331. package/src/tools/terminal/shell.ts +9 -1
  332. package/src/tools/tool-approval-handler.ts +31 -6
  333. package/src/tools/types.ts +24 -2
  334. package/src/tts/provider-catalog.ts +3 -5
  335. package/src/util/disk-usage.ts +138 -0
  336. package/src/util/platform.ts +21 -11
  337. package/src/util/process-liveness.ts +26 -0
  338. package/src/workspace/heartbeat-service.ts +19 -0
  339. package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
  340. package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
  341. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
  342. package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
  343. package/src/workspace/migrations/registry.ts +8 -0
  344. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
  345. package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
  346. package/src/memory/v2/skill-qdrant.ts +0 -404
  347. package/src/signals/bash.ts +0 -198
@@ -0,0 +1,272 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ mock.module("../../util/logger.js", () => ({
4
+ getLogger: () =>
5
+ new Proxy({} as Record<string, unknown>, {
6
+ get: () => () => {},
7
+ }),
8
+ }));
9
+
10
+ mock.module("../../config/loader.js", () => ({
11
+ getConfig: () => ({
12
+ ui: {},
13
+ model: "test",
14
+ provider: "test",
15
+ memory: { enabled: false },
16
+ rateLimit: { maxRequestsPerMinute: 0 },
17
+ secretDetection: { enabled: false },
18
+ }),
19
+ }));
20
+
21
+ let listPagesImpl: (workspaceDir: string) => Promise<string[]> = async () => [];
22
+
23
+ mock.module("../v2/page-store.js", () => ({
24
+ listPages: (workspaceDir: string) => listPagesImpl(workspaceDir),
25
+ }));
26
+
27
+ import { getDb } from "../db-connection.js";
28
+ import { initializeDb } from "../db-init.js";
29
+ import {
30
+ type MemoryV2ConceptRowRecord,
31
+ recordMemoryV2ActivationLog,
32
+ } from "../memory-v2-activation-log-store.js";
33
+ import { getConceptFrequencySummary } from "../memory-v2-concept-frequency.js";
34
+ import { memoryV2ActivationLogs } from "../schema.js";
35
+ import { sampleConfig } from "./fixtures/memory-v2-activation-fixtures.js";
36
+
37
+ initializeDb();
38
+
39
+ const WORKSPACE = "/tmp/memory-v2-concept-frequency-test";
40
+
41
+ function makeConcept(
42
+ slug: string,
43
+ status: MemoryV2ConceptRowRecord["status"],
44
+ ): MemoryV2ConceptRowRecord {
45
+ return {
46
+ slug,
47
+ finalActivation: 0.5,
48
+ ownActivation: 0.4,
49
+ priorActivation: 0.1,
50
+ simUser: 0.3,
51
+ simAssistant: 0.2,
52
+ simNow: 0.1,
53
+ simUserRerankBoost: 0,
54
+ simAssistantRerankBoost: 0,
55
+ inRerankPool: false,
56
+ spreadContribution: 0.1,
57
+ source: "ann_top50",
58
+ status,
59
+ };
60
+ }
61
+
62
+ function resetTables(): void {
63
+ getDb().delete(memoryV2ActivationLogs).run();
64
+ }
65
+
66
+ describe("memory-v2-concept-frequency", () => {
67
+ beforeEach(() => {
68
+ resetTables();
69
+ listPagesImpl = async () => [];
70
+ });
71
+
72
+ test("aggregates per-status counts across multiple turns", async () => {
73
+ const conv = "conv-1";
74
+ recordMemoryV2ActivationLog({
75
+ conversationId: conv,
76
+ turn: 1,
77
+ mode: "context-load",
78
+ concepts: [
79
+ makeConcept("alice", "injected"),
80
+ makeConcept("bob", "not_injected"),
81
+ ],
82
+ config: sampleConfig,
83
+ });
84
+ recordMemoryV2ActivationLog({
85
+ conversationId: conv,
86
+ turn: 2,
87
+ mode: "per-turn",
88
+ concepts: [
89
+ makeConcept("alice", "in_context"),
90
+ makeConcept("bob", "injected"),
91
+ ],
92
+ config: sampleConfig,
93
+ });
94
+ recordMemoryV2ActivationLog({
95
+ conversationId: conv,
96
+ turn: 3,
97
+ mode: "per-turn",
98
+ concepts: [
99
+ makeConcept("alice", "injected"),
100
+ makeConcept("charlie", "page_missing"),
101
+ ],
102
+ config: sampleConfig,
103
+ });
104
+
105
+ listPagesImpl = async () => ["alice", "bob", "delta"];
106
+
107
+ const result = await getConceptFrequencySummary(WORKSPACE, {});
108
+
109
+ expect(result.totals.logCount).toBe(3);
110
+ expect(result.totals.conceptOccurrences).toBe(6);
111
+ expect(result.filters).toEqual({ conversationId: null, sinceMs: null });
112
+
113
+ const bySlug = new Map(result.concepts.map((c) => [c.slug, c]));
114
+
115
+ expect(bySlug.get("alice")!.counts).toEqual({
116
+ injected: 2,
117
+ in_context: 1,
118
+ not_injected: 0,
119
+ page_missing: 0,
120
+ });
121
+ expect(bySlug.get("alice")!.totalEvaluations).toBe(3);
122
+ expect(bySlug.get("alice")!.onDisk).toBe(true);
123
+ expect(bySlug.get("alice")!.lastInjectedAt).not.toBeNull();
124
+
125
+ expect(bySlug.get("bob")!.counts).toEqual({
126
+ injected: 1,
127
+ in_context: 0,
128
+ not_injected: 1,
129
+ page_missing: 0,
130
+ });
131
+ expect(bySlug.get("bob")!.totalEvaluations).toBe(2);
132
+ expect(bySlug.get("bob")!.onDisk).toBe(true);
133
+
134
+ expect(bySlug.get("charlie")!.counts).toEqual({
135
+ injected: 0,
136
+ in_context: 0,
137
+ not_injected: 0,
138
+ page_missing: 1,
139
+ });
140
+ expect(bySlug.get("charlie")!.onDisk).toBe(false);
141
+ expect(bySlug.get("charlie")!.lastInjectedAt).toBeNull();
142
+
143
+ // Sorted by totalEvaluations desc — alice (3) before bob (2) before charlie (1).
144
+ expect(result.concepts.map((c) => c.slug)).toEqual([
145
+ "alice",
146
+ "bob",
147
+ "charlie",
148
+ ]);
149
+
150
+ // delta is on disk but never appeared in any log row.
151
+ expect(result.neverEvaluatedSlugs).toEqual(["delta"]);
152
+ });
153
+
154
+ test("conversationId filter narrows aggregation", async () => {
155
+ recordMemoryV2ActivationLog({
156
+ conversationId: "conv-a",
157
+ turn: 1,
158
+ mode: "per-turn",
159
+ concepts: [makeConcept("alice", "injected")],
160
+ config: sampleConfig,
161
+ });
162
+ recordMemoryV2ActivationLog({
163
+ conversationId: "conv-b",
164
+ turn: 1,
165
+ mode: "per-turn",
166
+ concepts: [
167
+ makeConcept("alice", "injected"),
168
+ makeConcept("alice", "injected"),
169
+ ],
170
+ config: sampleConfig,
171
+ });
172
+
173
+ listPagesImpl = async () => ["alice"];
174
+
175
+ const all = await getConceptFrequencySummary(WORKSPACE, {});
176
+ expect(all.totals.logCount).toBe(2);
177
+ expect(all.concepts[0]!.counts.injected).toBe(3);
178
+ expect(all.filters.conversationId).toBeNull();
179
+
180
+ const onlyA = await getConceptFrequencySummary(WORKSPACE, {
181
+ conversationId: "conv-a",
182
+ });
183
+ expect(onlyA.totals.logCount).toBe(1);
184
+ expect(onlyA.concepts[0]!.counts.injected).toBe(1);
185
+ expect(onlyA.filters.conversationId).toBe("conv-a");
186
+
187
+ const onlyB = await getConceptFrequencySummary(WORKSPACE, {
188
+ conversationId: "conv-b",
189
+ });
190
+ expect(onlyB.totals.logCount).toBe(1);
191
+ expect(onlyB.concepts[0]!.counts.injected).toBe(2);
192
+ });
193
+
194
+ test("sinceMs filter excludes older log rows", async () => {
195
+ recordMemoryV2ActivationLog({
196
+ conversationId: "conv-1",
197
+ turn: 1,
198
+ mode: "per-turn",
199
+ concepts: [makeConcept("alice", "injected")],
200
+ config: sampleConfig,
201
+ });
202
+ // Backdate the just-written row — recordMemoryV2ActivationLog uses Date.now().
203
+ getDb().update(memoryV2ActivationLogs).set({ createdAt: 1_000 }).run();
204
+
205
+ recordMemoryV2ActivationLog({
206
+ conversationId: "conv-1",
207
+ turn: 2,
208
+ mode: "per-turn",
209
+ concepts: [makeConcept("alice", "injected")],
210
+ config: sampleConfig,
211
+ });
212
+
213
+ listPagesImpl = async () => ["alice"];
214
+
215
+ const all = await getConceptFrequencySummary(WORKSPACE, {});
216
+ expect(all.totals.logCount).toBe(2);
217
+ expect(all.concepts[0]!.counts.injected).toBe(2);
218
+
219
+ const recent = await getConceptFrequencySummary(WORKSPACE, {
220
+ sinceMs: 10_000,
221
+ });
222
+ expect(recent.totals.logCount).toBe(1);
223
+ expect(recent.concepts[0]!.counts.injected).toBe(1);
224
+ expect(recent.filters.sinceMs).toBe(10_000);
225
+ });
226
+
227
+ test("never-evaluated list excludes slugs that appeared in any status", async () => {
228
+ recordMemoryV2ActivationLog({
229
+ conversationId: "conv-1",
230
+ turn: 1,
231
+ mode: "per-turn",
232
+ concepts: [
233
+ makeConcept("alice", "injected"),
234
+ makeConcept("bob", "not_injected"),
235
+ makeConcept("charlie", "page_missing"),
236
+ ],
237
+ config: sampleConfig,
238
+ });
239
+
240
+ listPagesImpl = async () => ["alice", "bob", "delta", "echo"];
241
+
242
+ const result = await getConceptFrequencySummary(WORKSPACE, {});
243
+ // bob was scored but rejected — still excluded from neverEvaluated.
244
+ expect(result.neverEvaluatedSlugs).toEqual(["delta", "echo"]);
245
+ });
246
+
247
+ test("returns empty result when no logs exist", async () => {
248
+ listPagesImpl = async () => ["alice", "bob"];
249
+
250
+ const result = await getConceptFrequencySummary(WORKSPACE, {});
251
+ expect(result.totals).toEqual({ logCount: 0, conceptOccurrences: 0 });
252
+ expect(result.concepts).toEqual([]);
253
+ expect(result.neverEvaluatedSlugs).toEqual(["alice", "bob"]);
254
+ });
255
+
256
+ test("flags slugs that appear in logs but no longer have a page on disk", async () => {
257
+ recordMemoryV2ActivationLog({
258
+ conversationId: "conv-1",
259
+ turn: 1,
260
+ mode: "per-turn",
261
+ concepts: [makeConcept("ghost", "injected")],
262
+ config: sampleConfig,
263
+ });
264
+
265
+ listPagesImpl = async () => ["alice"];
266
+
267
+ const result = await getConceptFrequencySummary(WORKSPACE, {});
268
+ const ghost = result.concepts.find((c) => c.slug === "ghost")!;
269
+ expect(ghost.onDisk).toBe(false);
270
+ expect(ghost.counts.injected).toBe(1);
271
+ });
272
+ });
@@ -6,7 +6,6 @@ import { getWorkspaceDir } from "../util/platform.js";
6
6
  import { deleteMemoryCheckpoint } from "./checkpoints.js";
7
7
  import { runDeterministicRecallSearch } from "./context-search/search.js";
8
8
  import type { RecallEvidence } from "./context-search/types.js";
9
- import { getConversationMemoryScopeId } from "./conversation-crud.js";
10
9
  import { getDb } from "./db-connection.js";
11
10
  import { getMemoryBackendStatus } from "./embedding-backend.js";
12
11
  import {
@@ -32,7 +31,7 @@ import {
32
31
 
33
32
  const log = getLogger("memory-admin");
34
33
 
35
- export interface MemorySystemStatus {
34
+ interface MemorySystemStatus {
36
35
  enabled: boolean;
37
36
  degraded: boolean;
38
37
  reason: string | null;
@@ -47,7 +46,7 @@ export interface MemorySystemStatus {
47
46
  jobs: Record<string, number>;
48
47
  }
49
48
 
50
- export interface AdminMemoryQueryResult {
49
+ interface AdminMemoryQueryResult {
51
50
  results: Array<{
52
51
  id: string;
53
52
  content: string;
@@ -106,7 +105,6 @@ export async function queryMemory(
106
105
  { query, sources: ["memory", "conversations", "pkb"] },
107
106
  {
108
107
  workingDir: getWorkspaceDir(),
109
- memoryScopeId: getConversationMemoryScopeId(conversationId) ?? "default",
110
108
  conversationId,
111
109
  config,
112
110
  },
@@ -148,7 +146,7 @@ function readNumericMetadata(
148
146
 
149
147
  // ── Short segment cleanup ─────────────────────────────────────────────
150
148
 
151
- export interface CleanupShortSegmentsResult {
149
+ interface CleanupShortSegmentsResult {
152
150
  removed: number;
153
151
  failed: number;
154
152
  dryRunCount?: number;
@@ -216,7 +214,7 @@ export async function compactLongMemoryNodes(
216
214
 
217
215
  // ── Re-extraction ──────────────────────────────────────────────────────
218
216
 
219
- export interface ReextractTarget {
217
+ interface ReextractTarget {
220
218
  conversationId: string;
221
219
  title: string | null;
222
220
  messageCount: number;
@@ -312,11 +310,9 @@ export function requestReextract(targets: ReextractTarget[]): {
312
310
  )
313
311
  .run();
314
312
 
315
- // Resolve scope and enqueue re-extraction
316
- const scopeId = getConversationMemoryScopeId(conversationId);
317
313
  const jobId = enqueueMemoryJob("graph_extract", {
318
314
  conversationId,
319
- scopeId,
315
+ scopeId: "default",
320
316
  });
321
317
  jobIds.push(jobId);
322
318
 
@@ -306,7 +306,17 @@ export async function runAgenticRecall(
306
306
  [...RECALL_AGENT_TOOL_DEFINITIONS],
307
307
  undefined,
308
308
  {
309
- config: { callSite: "recall", temperature: 0 },
309
+ // `thinking: disabled` is required because we set `temperature: 0`
310
+ // explicitly. Anthropic 400s on `temperature` ≠ 1 whenever thinking
311
+ // is enabled or in adaptive mode; without this, profiles that
312
+ // resolve thinking-enabled (Opus 4.x at `effort: high|xhigh`, etc.)
313
+ // would fail. Recall is tool-call-heavy reasoning where determinism
314
+ // matters more than extended chain-of-thought.
315
+ config: {
316
+ callSite: "recall",
317
+ temperature: 0,
318
+ thinking: { type: "disabled" },
319
+ },
310
320
  signal: context.signal,
311
321
  },
312
322
  );
@@ -597,7 +607,14 @@ async function tryFinalFinishRecall(options: {
597
607
  [FINISH_RECALL_TOOL_DEFINITION],
598
608
  undefined,
599
609
  {
600
- config: { callSite: "recall", temperature: 0 },
610
+ // `thinking: disabled` required for the same reason as the agent
611
+ // round above — Anthropic 400s on `temperature` ≠ 1 whenever
612
+ // thinking is enabled or in adaptive mode.
613
+ config: {
614
+ callSite: "recall",
615
+ temperature: 0,
616
+ thinking: { type: "disabled" },
617
+ },
601
618
  signal: options.context.signal,
602
619
  },
603
620
  );
@@ -88,10 +88,7 @@ export async function searchConversationSource(
88
88
 
89
89
  for (const ftsMatch of ftsMatches) {
90
90
  try {
91
- rows = mergeConversationRows(
92
- rows,
93
- searchWithFts(ftsMatch, context.memoryScopeId, queryLimit),
94
- );
91
+ rows = mergeConversationRows(rows, searchWithFts(ftsMatch, queryLimit));
95
92
  } catch {
96
93
  // Try the next, broader query shape.
97
94
  }
@@ -100,7 +97,7 @@ export async function searchConversationSource(
100
97
  }
101
98
 
102
99
  if (rows.length === 0) {
103
- rows = searchWithLike(trimmedQuery, context.memoryScopeId, queryLimit);
100
+ rows = searchWithLike(trimmedQuery, queryLimit);
104
101
  }
105
102
 
106
103
  const sortedRows = rows
@@ -130,7 +127,6 @@ export async function searchConversationSource(
130
127
 
131
128
  function searchWithFts(
132
129
  ftsMatch: string,
133
- memoryScopeId: string,
134
130
  limit: number,
135
131
  ): ConversationEvidenceRow[] {
136
132
  return rawAll<ConversationEvidenceRow>(
@@ -146,14 +142,12 @@ function searchWithFts(
146
142
  JOIN messages m ON m.id = messages_fts.message_id
147
143
  JOIN conversations c ON c.id = m.conversation_id
148
144
  WHERE messages_fts MATCH ?
149
- AND c.memory_scope_id = ?
150
145
  AND (c.conversation_type IS NULL OR c.conversation_type != 'private')
151
146
  AND (c.source IS NULL OR c.source NOT IN (?, ?))
152
147
  ORDER BY bm25(messages_fts), m.created_at DESC
153
148
  LIMIT ?
154
149
  `,
155
150
  ftsMatch,
156
- memoryScopeId,
157
151
  SUBAGENT_SOURCE,
158
152
  AUTO_ANALYSIS_SOURCE,
159
153
  limit,
@@ -162,7 +156,6 @@ function searchWithFts(
162
156
 
163
157
  function searchWithLike(
164
158
  query: string,
165
- memoryScopeId: string,
166
159
  limit: number,
167
160
  ): ConversationEvidenceRow[] {
168
161
  return rawAll<ConversationEvidenceRow>(
@@ -177,14 +170,12 @@ function searchWithLike(
177
170
  FROM messages m
178
171
  JOIN conversations c ON c.id = m.conversation_id
179
172
  WHERE m.content LIKE ? ESCAPE '\\'
180
- AND c.memory_scope_id = ?
181
173
  AND (c.conversation_type IS NULL OR c.conversation_type != 'private')
182
174
  AND (c.source IS NULL OR c.source NOT IN (?, ?))
183
175
  ORDER BY m.created_at DESC
184
176
  LIMIT ?
185
177
  `,
186
178
  buildLikePattern(query),
187
- memoryScopeId,
188
179
  SUBAGENT_SOURCE,
189
180
  AUTO_ANALYSIS_SOURCE,
190
181
  limit,
@@ -47,10 +47,11 @@ import type {
47
47
  } from "../types.js";
48
48
 
49
49
  /**
50
- * True when both v2 gates are on. Single source of truth shared by the recall
51
- * `memory` source (which delegates to v2), the `pkb` source (which
52
- * short-circuits because v2 absorbs PKB as a read source), and the per-turn
53
- * PKB injectors (which go silent so v2 owns the read path end-to-end).
50
+ * True when both v2 gates are on. Single source of truth for whether v2 is
51
+ * the active memory subsystem used by recall sources (`memory`, `pkb`),
52
+ * per-turn injectors, the indexer's v1 graph_extract suppression, and the
53
+ * v1/v2 maintenance scheduler. The historical name retains "Read" but the
54
+ * predicate now gates both read and write paths.
54
55
  */
55
56
  export function isMemoryV2ReadActive(config: AssistantConfig): boolean {
56
57
  return (
@@ -47,7 +47,6 @@ export async function searchMemorySource(
47
47
  const searchResults = await searchGraphNodes(
48
48
  queryVector,
49
49
  normalizedLimit,
50
- [context.memoryScopeId],
51
50
  sparseVector,
52
51
  );
53
52
 
@@ -24,7 +24,6 @@ export interface RecallEvidence {
24
24
 
25
25
  export interface RecallSearchContext {
26
26
  workingDir: string;
27
- memoryScopeId: string;
28
27
  conversationId: string;
29
28
  config: AssistantConfig;
30
29
  signal?: AbortSignal;
@@ -115,8 +115,6 @@ export const messageMetadataSchema = z
115
115
  })
116
116
  .passthrough();
117
117
 
118
- export type MessageMetadata = z.infer<typeof messageMetadataSchema>;
119
-
120
118
  function cloneForkMessageMetadata(
121
119
  metadata: string | null,
122
120
  sourceMessageId: string,
@@ -444,11 +442,6 @@ export function getConversationSource(conversationId: string): string | null {
444
442
  return row?.source ?? null;
445
443
  }
446
444
 
447
- export function getConversationMemoryScopeId(conversationId: string): string {
448
- const conv = getConversation(conversationId);
449
- return conv?.memoryScopeId ?? "default";
450
- }
451
-
452
445
  /**
453
446
  * Fetch group_id for a conversation via raw SQL. group_id is NOT in the
454
447
  * Drizzle schema (raw-query-only pattern), so ConversationRow doesn't
@@ -912,7 +905,6 @@ export async function addMessage(
912
905
  if (!opts?.skipIndexing) {
913
906
  try {
914
907
  const config = getConfig();
915
- const scopeId = getConversationMemoryScopeId(conversationId);
916
908
  const parsed = metadata
917
909
  ? messageMetadataSchema.safeParse(metadata)
918
910
  : null;
@@ -927,7 +919,7 @@ export async function addMessage(
927
919
  role: message.role,
928
920
  content: message.content,
929
921
  createdAt: message.createdAt,
930
- scopeId,
922
+ scopeId: "default",
931
923
  provenanceTrustClass,
932
924
  automated,
933
925
  },
@@ -1027,7 +1019,7 @@ export function hasMessages(conversationId: string): boolean {
1027
1019
  return row !== undefined;
1028
1020
  }
1029
1021
 
1030
- export interface PaginatedMessagesResult {
1022
+ interface PaginatedMessagesResult {
1031
1023
  messages: MessageRow[];
1032
1024
  hasMore: boolean;
1033
1025
  }
@@ -1441,12 +1433,12 @@ export function deleteLastExchange(conversationId: string): number {
1441
1433
  * Callers must delete these from the Qdrant collection after the
1442
1434
  * SQLite transaction commits.
1443
1435
  */
1444
- export interface DeletedMemoryIds {
1436
+ interface DeletedMemoryIds {
1445
1437
  segmentIds: string[];
1446
1438
  deletedSummaryIds: string[];
1447
1439
  }
1448
1440
 
1449
- export interface WipeConversationResult extends DeletedMemoryIds {
1441
+ interface WipeConversationResult extends DeletedMemoryIds {
1450
1442
  cancelledJobCount: number;
1451
1443
  }
1452
1444
 
@@ -165,6 +165,7 @@ import {
165
165
  migrateStripPlaceholderSentinelsFromMessages,
166
166
  migrateStripThinkingFromConsolidated,
167
167
  migrateToolInvocationsMatchedRuleId,
168
+ migrateTraceEventsCreatedAtIndex,
168
169
  migrateUsageDashboardIndexes,
169
170
  migrateUsageLlmCallCount,
170
171
  migrateVoiceInviteColumns,
@@ -408,6 +409,7 @@ export function initializeDb(): void {
408
409
  backfillAppConversationIds();
409
410
  },
410
411
  migrateScheduleRetryPolicy,
412
+ migrateTraceEventsCreatedAtIndex,
411
413
  ];
412
414
 
413
415
  // Run each migration step, catching and logging individual failures so one