@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,404 @@
1
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ // Mock the persistence layer the surface helpers reach into so we can
4
+ // observe writes without touching SQLite. We swap this out per test by
5
+ // re-assigning the spies recorded on the closure below.
6
+ let getMessagesImpl: (conversationId: string) => Array<{
7
+ id: string;
8
+ conversationId: string;
9
+ role: string;
10
+ content: string;
11
+ createdAt: number;
12
+ metadata: string | null;
13
+ }> = () => [];
14
+ let updateMessageContentSpy: (id: string, content: string) => void = () => {};
15
+
16
+ const realCrud = await import("../memory/conversation-crud.js");
17
+
18
+ mock.module("../memory/conversation-crud.js", () => ({
19
+ ...realCrud,
20
+ getMessages: (conversationId: string) => getMessagesImpl(conversationId),
21
+ updateMessageContent: (id: string, content: string) =>
22
+ updateMessageContentSpy(id, content),
23
+ }));
24
+
25
+ // Imports must come AFTER mock.module so the surface module picks up
26
+ // the mocked persistence functions.
27
+ const {
28
+ cancelPendingSurfaceDataPersists,
29
+ flushPendingSurfaceDataPersists,
30
+ createSurfaceMutex,
31
+ flushSurfaceDataPersist,
32
+ markSurfaceCompleted,
33
+ scheduleSurfaceDataPersist,
34
+ surfaceProxyResolver,
35
+ } = await import("../daemon/conversation-surfaces.js");
36
+
37
+ import type { SurfaceConversationContext } from "../daemon/conversation-surfaces.js";
38
+ import type {
39
+ CardSurfaceData,
40
+ ServerMessage,
41
+ SurfaceData,
42
+ SurfaceType,
43
+ } from "../daemon/message-protocol.js";
44
+
45
+ function makeContext(sent: ServerMessage[] = []): SurfaceConversationContext {
46
+ return {
47
+ conversationId: "conv-persist-1",
48
+ traceEmitter: { emit: () => {} },
49
+ sendToClient: (msg) => sent.push(msg),
50
+ pendingSurfaceActions: new Map<string, { surfaceType: SurfaceType }>(),
51
+ lastSurfaceAction: new Map<
52
+ string,
53
+ { actionId: string; data?: Record<string, unknown> }
54
+ >(),
55
+ surfaceState: new Map<
56
+ string,
57
+ { surfaceType: SurfaceType; data: SurfaceData; title?: string }
58
+ >(),
59
+ surfaceUndoStacks: new Map<string, string[]>(),
60
+ accumulatedSurfaceState: new Map<string, Record<string, unknown>>(),
61
+ surfaceActionRequestIds: new Set<string>(),
62
+ currentTurnSurfaces: [],
63
+ isProcessing: () => false,
64
+ enqueueMessage: () => ({ queued: false, requestId: "req-1" }),
65
+ getQueueDepth: () => 0,
66
+ processMessage: async () => "ok",
67
+ withSurface: createSurfaceMutex(),
68
+ };
69
+ }
70
+
71
+ function seedRows(rows: Array<{ id: string; content: unknown }>): void {
72
+ getMessagesImpl = () =>
73
+ rows.map((r) => ({
74
+ id: r.id,
75
+ conversationId: "conv-persist-1",
76
+ role: "assistant",
77
+ content:
78
+ typeof r.content === "string" ? r.content : JSON.stringify(r.content),
79
+ createdAt: 0,
80
+ metadata: null,
81
+ }));
82
+ }
83
+
84
+ describe("ui_surface_update persistence", () => {
85
+ let writes: Array<{ id: string; content: unknown }> = [];
86
+
87
+ beforeEach(() => {
88
+ writes = [];
89
+ updateMessageContentSpy = (id: string, content: string) => {
90
+ writes.push({ id, content: JSON.parse(content) });
91
+ };
92
+ getMessagesImpl = () => [];
93
+ // Make sure module-level pending timers from a previous test don't
94
+ // leak into this one.
95
+ cancelPendingSurfaceDataPersists();
96
+ });
97
+
98
+ afterEach(() => {
99
+ cancelPendingSurfaceDataPersists();
100
+ });
101
+
102
+ test("ui_update schedules a debounced DB write that lands within ~600ms", async () => {
103
+ const sent: ServerMessage[] = [];
104
+ const ctx = makeContext(sent);
105
+
106
+ // Seed an existing in-memory surface and a persisted message that
107
+ // contains the matching ui_surface block.
108
+ const surfaceId = "surface-debounced-1";
109
+ const initial: CardSurfaceData = {
110
+ title: "Health check",
111
+ body: "",
112
+ template: "task_progress",
113
+ templateData: { status: "in_progress", steps: [] },
114
+ };
115
+ ctx.surfaceState.set(surfaceId, { surfaceType: "card", data: initial });
116
+ seedRows([
117
+ {
118
+ id: "msg-1",
119
+ content: [
120
+ { type: "text", text: "running" },
121
+ {
122
+ type: "ui_surface",
123
+ surfaceId,
124
+ surfaceType: "card",
125
+ data: initial,
126
+ },
127
+ ],
128
+ },
129
+ ]);
130
+
131
+ const result = await surfaceProxyResolver(ctx, "ui_update", {
132
+ surface_id: surfaceId,
133
+ data: { templateData: { status: "completed" } },
134
+ });
135
+ expect(result.isError).toBe(false);
136
+
137
+ // Write must not have happened synchronously.
138
+ expect(writes).toHaveLength(0);
139
+
140
+ // After the debounce window the write lands.
141
+ await new Promise((r) => setTimeout(r, 600));
142
+ expect(writes).toHaveLength(1);
143
+ expect(writes[0].id).toBe("msg-1");
144
+ const persistedBlocks = writes[0].content as Array<Record<string, unknown>>;
145
+ const persistedSurface = persistedBlocks.find(
146
+ (b) => b.type === "ui_surface",
147
+ );
148
+ expect(persistedSurface).toBeDefined();
149
+ const persistedData = persistedSurface!.data as CardSurfaceData;
150
+ expect((persistedData.templateData as Record<string, unknown>).status).toBe(
151
+ "completed",
152
+ );
153
+ });
154
+
155
+ test("multiple rapid updates collapse to a single DB write", async () => {
156
+ const sent: ServerMessage[] = [];
157
+ const ctx = makeContext(sent);
158
+
159
+ const surfaceId = "surface-debounced-2";
160
+ const initial: CardSurfaceData = {
161
+ title: "Health check",
162
+ body: "",
163
+ template: "task_progress",
164
+ templateData: { status: "in_progress", steps: [] },
165
+ };
166
+ ctx.surfaceState.set(surfaceId, { surfaceType: "card", data: initial });
167
+ seedRows([
168
+ {
169
+ id: "msg-2",
170
+ content: [
171
+ {
172
+ type: "ui_surface",
173
+ surfaceId,
174
+ surfaceType: "card",
175
+ data: initial,
176
+ },
177
+ ],
178
+ },
179
+ ]);
180
+
181
+ for (const status of ["a", "b", "c", "d"]) {
182
+ // Patches arrive faster than the debounce window.
183
+ await surfaceProxyResolver(ctx, "ui_update", {
184
+ surface_id: surfaceId,
185
+ data: { templateData: { status } },
186
+ });
187
+ await new Promise((r) => setTimeout(r, 50));
188
+ }
189
+
190
+ // Wait past the debounce window after the LAST update.
191
+ await new Promise((r) => setTimeout(r, 600));
192
+
193
+ expect(writes).toHaveLength(1);
194
+ const persistedSurface = (
195
+ writes[0].content as Array<Record<string, unknown>>
196
+ ).find((b) => b.type === "ui_surface");
197
+ const persistedData = persistedSurface!.data as CardSurfaceData;
198
+ expect((persistedData.templateData as Record<string, unknown>).status).toBe(
199
+ "d",
200
+ );
201
+ });
202
+
203
+ test("markSurfaceCompleted force-flushes any pending debounced write", async () => {
204
+ const surfaceId = "surface-flush-1";
205
+ const initial: CardSurfaceData = {
206
+ title: "x",
207
+ body: "",
208
+ template: "task_progress",
209
+ templateData: { status: "in_progress" },
210
+ };
211
+ seedRows([
212
+ {
213
+ id: "msg-flush",
214
+ content: [
215
+ {
216
+ type: "ui_surface",
217
+ surfaceId,
218
+ surfaceType: "card",
219
+ data: initial,
220
+ },
221
+ ],
222
+ },
223
+ ]);
224
+
225
+ // Schedule a debounced persist directly.
226
+ scheduleSurfaceDataPersist("conv-persist-1", surfaceId, {
227
+ ...initial,
228
+ templateData: { status: "completed" },
229
+ } as SurfaceData);
230
+
231
+ expect(writes).toHaveLength(0);
232
+
233
+ // Calling markSurfaceCompleted should immediately flush the pending
234
+ // data persist AND apply its own completion patch — two writes
235
+ // against the same row, with the completion landing last.
236
+ markSurfaceCompleted({ conversationId: "conv-persist-1" }, surfaceId, "ok");
237
+
238
+ expect(writes.length).toBeGreaterThanOrEqual(2);
239
+ const finalBlocks = writes[writes.length - 1].content as Array<
240
+ Record<string, unknown>
241
+ >;
242
+ const finalSurface = finalBlocks.find((b) => b.type === "ui_surface")!;
243
+ expect(finalSurface.completed).toBe(true);
244
+ expect(finalSurface.completionSummary).toBe("ok");
245
+ });
246
+
247
+ test("flushSurfaceDataPersist fires the latest data immediately", () => {
248
+ const surfaceId = "surface-flush-2";
249
+ seedRows([
250
+ {
251
+ id: "msg-flush-2",
252
+ content: [
253
+ {
254
+ type: "ui_surface",
255
+ surfaceId,
256
+ surfaceType: "card",
257
+ data: { title: "x", body: "" },
258
+ },
259
+ ],
260
+ },
261
+ ]);
262
+ scheduleSurfaceDataPersist("conv-persist-1", surfaceId, {
263
+ title: "x",
264
+ body: "later",
265
+ } as SurfaceData);
266
+
267
+ expect(writes).toHaveLength(0);
268
+ flushSurfaceDataPersist(surfaceId);
269
+ expect(writes).toHaveLength(1);
270
+ const block = (writes[0].content as Array<Record<string, unknown>>).find(
271
+ (b) => b.type === "ui_surface",
272
+ );
273
+ expect((block!.data as Record<string, unknown>).body).toBe("later");
274
+ });
275
+
276
+ test("update arriving before the message is persisted is safely skipped", async () => {
277
+ const surfaceId = "surface-orphan-1";
278
+ // No rows seeded — simulates mid-stream before message_complete persists.
279
+ seedRows([]);
280
+
281
+ scheduleSurfaceDataPersist("conv-persist-1", surfaceId, {
282
+ title: "x",
283
+ body: "",
284
+ } as SurfaceData);
285
+
286
+ await new Promise((r) => setTimeout(r, 600));
287
+
288
+ // No write — and no crash.
289
+ expect(writes).toHaveLength(0);
290
+ });
291
+
292
+ test("cancelPendingSurfaceDataPersists clears scoped timers without firing", async () => {
293
+ const surfaceId = "surface-cancel-1";
294
+ seedRows([
295
+ {
296
+ id: "msg-cancel",
297
+ content: [
298
+ {
299
+ type: "ui_surface",
300
+ surfaceId,
301
+ surfaceType: "card",
302
+ data: { title: "x", body: "" },
303
+ },
304
+ ],
305
+ },
306
+ ]);
307
+
308
+ scheduleSurfaceDataPersist("conv-persist-1", surfaceId, {
309
+ title: "x",
310
+ body: "queued",
311
+ } as SurfaceData);
312
+
313
+ cancelPendingSurfaceDataPersists("conv-persist-1");
314
+ await new Promise((r) => setTimeout(r, 600));
315
+
316
+ expect(writes).toHaveLength(0);
317
+ });
318
+
319
+ test("flushPendingSurfaceDataPersists writes pending updates synchronously and clears timers", async () => {
320
+ const surfaceId = "surface-flush-pending-1";
321
+ seedRows([
322
+ {
323
+ id: "msg-flush-pending",
324
+ content: [
325
+ {
326
+ type: "ui_surface",
327
+ surfaceId,
328
+ surfaceType: "card",
329
+ data: { title: "x", body: "" },
330
+ },
331
+ ],
332
+ },
333
+ ]);
334
+
335
+ scheduleSurfaceDataPersist("conv-persist-1", surfaceId, {
336
+ title: "x",
337
+ body: "shutdown-flush",
338
+ } as SurfaceData);
339
+
340
+ // Write should not have fired yet (debounce hasn't elapsed).
341
+ expect(writes).toHaveLength(0);
342
+
343
+ flushPendingSurfaceDataPersists("conv-persist-1");
344
+
345
+ // Synchronous flush — write lands immediately with the latest data.
346
+ expect(writes).toHaveLength(1);
347
+ expect(writes[0].id).toBe("msg-flush-pending");
348
+ const block = (writes[0].content as Array<Record<string, unknown>>).find(
349
+ (b) => b.type === "ui_surface",
350
+ )!;
351
+ expect((block.data as Record<string, unknown>).body).toBe("shutdown-flush");
352
+
353
+ // Timer is cleared — waiting past the debounce window doesn't fire again.
354
+ await new Promise((r) => setTimeout(r, 600));
355
+ expect(writes).toHaveLength(1);
356
+ });
357
+
358
+ test("flushPendingSurfaceDataPersists scoped to one conversation leaves other conversations' timers alone", async () => {
359
+ const surfaceA = "surface-flush-scoped-a";
360
+ const surfaceB = "surface-flush-scoped-b";
361
+ seedRows([
362
+ {
363
+ id: "msg-scoped-a",
364
+ content: [
365
+ {
366
+ type: "ui_surface",
367
+ surfaceId: surfaceA,
368
+ surfaceType: "card",
369
+ data: { title: "x", body: "" },
370
+ },
371
+ ],
372
+ },
373
+ {
374
+ id: "msg-scoped-b",
375
+ content: [
376
+ {
377
+ type: "ui_surface",
378
+ surfaceId: surfaceB,
379
+ surfaceType: "card",
380
+ data: { title: "x", body: "" },
381
+ },
382
+ ],
383
+ },
384
+ ]);
385
+
386
+ scheduleSurfaceDataPersist("conv-persist-1", surfaceA, {
387
+ title: "x",
388
+ body: "a",
389
+ } as SurfaceData);
390
+ scheduleSurfaceDataPersist("conv-other", surfaceB, {
391
+ title: "x",
392
+ body: "b",
393
+ } as SurfaceData);
394
+
395
+ flushPendingSurfaceDataPersists("conv-persist-1");
396
+
397
+ // Only conv-persist-1's surface flushed; conv-other's still pending.
398
+ expect(writes).toHaveLength(1);
399
+ expect(writes[0].id).toBe("msg-scoped-a");
400
+
401
+ // Cleanup the other conversation's timer.
402
+ cancelPendingSurfaceDataPersists("conv-other");
403
+ });
404
+ });
@@ -95,7 +95,6 @@ function makeCtx(overrides: Partial<ToolSetupContext> = {}): ToolSetupContext {
95
95
  getQueueDepth: () => 0,
96
96
  processMessage: async () => "",
97
97
  withSurface: async <T>(_id: string, fn: () => T | Promise<T>) => fn(),
98
- memoryPolicy: { scopeId: "default" },
99
98
  ...overrides,
100
99
  };
101
100
  }
@@ -383,7 +382,7 @@ describe("session-tool-setup app refresh side effects", () => {
383
382
  // Simulate calling app_refresh by name (as the agent loop does)
384
383
  for (const toolName of ["app_refresh"]) {
385
384
  refreshSpy.mockClear();
386
- broadcastSpy.mockClear();
385
+ broadcastSpy.mockClear();
387
386
  broadcastSpy.mockClear();
388
387
  updatePublishedSpy.mockClear();
389
388
 
@@ -423,7 +422,7 @@ describe("session-tool-setup app refresh side effects", () => {
423
422
  "app_file_write",
424
423
  ]) {
425
424
  refreshSpy.mockClear();
426
- broadcastSpy.mockClear();
425
+ broadcastSpy.mockClear();
427
426
  broadcastSpy.mockClear();
428
427
  updatePublishedSpy.mockClear();
429
428
 
@@ -435,6 +434,4 @@ describe("session-tool-setup app refresh side effects", () => {
435
434
  }
436
435
  });
437
436
  });
438
-
439
-
440
437
  });
@@ -1,8 +1,14 @@
1
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  import type { AgentEvent } from "../agent/loop.js";
4
+ import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
4
5
  import type { Message, ProviderResponse } from "../providers/types.js";
5
6
 
7
+ // This test exercises v1 conversation routing. The `memory-v2-enabled` flag
8
+ // (registry default `true`) flips memory routing to v2 — disable it here so
9
+ // the v1 paths under test stay active.
10
+ _setOverridesForTesting({ "memory-v2-enabled": false });
11
+
6
12
  // ---------------------------------------------------------------------------
7
13
  // Track agent loop calls
8
14
  // ---------------------------------------------------------------------------
@@ -1,8 +1,14 @@
1
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  import type { AgentEvent } from "../agent/loop.js";
4
+ import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
4
5
  import type { Message, ProviderResponse } from "../providers/types.js";
5
6
 
7
+ // This test exercises v1 conversation routing. The `memory-v2-enabled` flag
8
+ // (registry default `true`) flips memory routing to v2 — disable it here so
9
+ // the v1 paths under test stay active.
10
+ _setOverridesForTesting({ "memory-v2-enabled": false });
11
+
6
12
  // ---------------------------------------------------------------------------
7
13
  // Configurable agent loop behavior
8
14
  // ---------------------------------------------------------------------------
@@ -53,6 +53,13 @@ mock.module("../security/secure-keys.js", () => ({
53
53
  onCesClientChanged: () => ({ unsubscribe: () => {} }),
54
54
  setCesReconnect: () => {},
55
55
  getActiveBackendName: () => "file",
56
+ getActiveBackendInfoAsync: async () => ({
57
+ backend: "encrypted-store",
58
+ storePath: "/tmp/keys.enc",
59
+ storeKeyPath: "/tmp/store.key",
60
+ storeExists: false,
61
+ storeKeyExists: false,
62
+ }),
56
63
  _resetBackend: () => {},
57
64
  }));
58
65