@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
@@ -32,10 +32,10 @@ import {
32
32
  writeSync,
33
33
  } from "node:fs";
34
34
  import { dirname, join } from "node:path";
35
- import { kill } from "node:process";
36
35
  import { setTimeout as sleep } from "node:timers/promises";
37
36
 
38
37
  import { getLogger } from "../util/logger.js";
38
+ import { isProcessAlive } from "../util/process-liveness.js";
39
39
  import { getLocalBackupsDir } from "./paths.js";
40
40
 
41
41
  const log = getLogger("snapshot-lock");
@@ -88,29 +88,6 @@ export function getSnapshotLockPath(): string {
88
88
  return join(dirname(getLocalBackupsDir()), ".snapshot.lock");
89
89
  }
90
90
 
91
- /**
92
- * Check whether a PID refers to a live process. Uses `kill(pid, 0)`, which
93
- * does not send any signal — it just probes for existence and permission.
94
- *
95
- * Returns `false` for obviously invalid PIDs (<= 0) and for any error that
96
- * indicates the process is gone. Returns `true` for ESRCH-negative results
97
- * (meaning a process exists) and for EPERM (process exists but is owned by
98
- * another user — still a live process, still should not be taken over).
99
- */
100
- function isProcessAlive(pid: number): boolean {
101
- if (!Number.isInteger(pid) || pid <= 0) return false;
102
- try {
103
- kill(pid, 0);
104
- return true;
105
- } catch (err) {
106
- const code = (err as NodeJS.ErrnoException).code;
107
- // EPERM means the PID exists but we cannot signal it — treat as alive so
108
- // we don't accidentally take over another user's lock.
109
- if (code === "EPERM") return true;
110
- return false;
111
- }
112
- }
113
-
114
91
  /**
115
92
  * Try to atomically create the lock file with mode `0o600` and the current
116
93
  * PID as its contents. Returns `true` on success, `false` if the file
@@ -348,9 +325,7 @@ export async function acquireSnapshotLock(
348
325
  }
349
326
 
350
327
  if (isProcessAlive(holder.pid)) {
351
- throw new Error(
352
- `snapshot in progress (locked by pid ${holder.pid})`,
353
- );
328
+ throw new Error(`snapshot in progress (locked by pid ${holder.pid})`);
354
329
  }
355
330
 
356
331
  // --- Step 3: stale takeover via rename-aside ---
@@ -15,10 +15,11 @@ import {
15
15
  rmSync,
16
16
  writeFileSync,
17
17
  } from "node:fs";
18
- import { arch, homedir, platform } from "node:os";
18
+ import { arch, platform } from "node:os";
19
19
  import { join } from "node:path";
20
20
 
21
21
  import { getLogger } from "../util/logger.js";
22
+ import { getWorkspaceDir } from "../util/platform.js";
22
23
  import { PromiseGuard } from "../util/promise-guard.js";
23
24
 
24
25
  const log = getLogger("compiler-tools");
@@ -44,7 +45,7 @@ interface VersionManifest {
44
45
  }
45
46
 
46
47
  function getToolsDir(): string {
47
- return join(homedir(), ".vellum", "workspace", "compiler-tools");
48
+ return join(getWorkspaceDir(), "compiler-tools");
48
49
  }
49
50
 
50
51
  const installGuard = new PromiseGuard<void>();
@@ -6,6 +6,21 @@
6
6
  import { addMessage } from "../memory/conversation-crud.js";
7
7
  import { getCallEvents, getCallSession } from "./call-store.js";
8
8
 
9
+ function buildCallSummaryLabel(
10
+ status: string | undefined,
11
+ duration: number | null,
12
+ eventCount: number,
13
+ ): string {
14
+ const statusLabel =
15
+ status === "failed"
16
+ ? "Call failed"
17
+ : status === "cancelled"
18
+ ? "Call cancelled"
19
+ : "Call completed";
20
+ const durationStr = duration != null ? ` (${duration}s)` : "";
21
+ return `**${statusLabel}**${durationStr}. ${eventCount} event(s) recorded.`;
22
+ }
23
+
9
24
  export function buildCallCompletionMessage(callSessionId: string): string {
10
25
  const callSession = getCallSession(callSessionId);
11
26
  const events = getCallEvents(callSessionId);
@@ -13,25 +28,46 @@ export function buildCallCompletionMessage(callSessionId: string): string {
13
28
  callSession?.endedAt && callSession?.startedAt
14
29
  ? Math.round((callSession.endedAt - callSession.startedAt) / 1000)
15
30
  : null;
16
- const durationStr = duration != null ? ` (${duration}s)` : "";
17
- const statusLabel =
18
- callSession?.status === "failed"
19
- ? "Call failed"
20
- : callSession?.status === "cancelled"
21
- ? "Call cancelled"
22
- : "Call completed";
23
- return `**${statusLabel}**${durationStr}. ${events.length} event(s) recorded.`;
31
+ return buildCallSummaryLabel(callSession?.status, duration, events.length);
24
32
  }
25
33
 
26
34
  export async function persistCallCompletionMessage(
27
35
  conversationId: string,
28
36
  callSessionId: string,
29
37
  ): Promise<string> {
30
- const summaryText = buildCallCompletionMessage(callSessionId);
38
+ const callSession = getCallSession(callSessionId);
39
+ const events = getCallEvents(callSessionId);
40
+ const duration =
41
+ callSession?.endedAt && callSession?.startedAt
42
+ ? Math.round((callSession.endedAt - callSession.startedAt) / 1000)
43
+ : null;
44
+ const summaryText = buildCallSummaryLabel(
45
+ callSession?.status,
46
+ duration,
47
+ events.length,
48
+ );
49
+
31
50
  await addMessage(
32
51
  conversationId,
33
52
  "assistant",
34
- JSON.stringify([{ type: "text", text: summaryText }]),
53
+ JSON.stringify([
54
+ {
55
+ type: "ui_surface",
56
+ surfaceType: "call_summary",
57
+ surfaceId: crypto.randomUUID(),
58
+ completed: true,
59
+ data: {
60
+ summaryText,
61
+ status: callSession?.status ?? "completed",
62
+ duration,
63
+ events: events.map((e) => ({
64
+ eventType: e.eventType,
65
+ payloadJson: e.payloadJson,
66
+ createdAt: e.createdAt,
67
+ })),
68
+ },
69
+ },
70
+ ]),
35
71
  {
36
72
  userMessageChannel: "phone",
37
73
  assistantMessageChannel: "phone",
@@ -14,7 +14,6 @@ let mockPlatformContext: Record<string, unknown> = {
14
14
  isPlatform: false,
15
15
  platformBaseUrl: "",
16
16
  assistantId: "",
17
- hasInternalApiKey: false,
18
17
  hasAssistantApiKey: false,
19
18
  authHeader: null,
20
19
  enabled: false,
@@ -128,7 +127,6 @@ function connectedContext(
128
127
  isPlatform: false,
129
128
  platformBaseUrl: "https://test-platform.vellum.ai",
130
129
  assistantId: "019d6d4f-6dbd-779f-91d3-cb273b9429a5",
131
- hasInternalApiKey: false,
132
130
  hasAssistantApiKey: true,
133
131
  authHeader: "Api-Key vak_test123",
134
132
  enabled: true,
@@ -145,7 +143,6 @@ describe("assistant webhooks register", () => {
145
143
  isPlatform: false,
146
144
  platformBaseUrl: "",
147
145
  assistantId: "",
148
- hasInternalApiKey: false,
149
146
  hasAssistantApiKey: false,
150
147
  authHeader: null,
151
148
  enabled: false,
@@ -466,7 +463,6 @@ describe("assistant webhooks list", () => {
466
463
  isPlatform: false,
467
464
  platformBaseUrl: "",
468
465
  assistantId: "",
469
- hasInternalApiKey: false,
470
466
  hasAssistantApiKey: false,
471
467
  authHeader: null,
472
468
  enabled: false,
@@ -1,23 +1,11 @@
1
- import { randomUUID } from "node:crypto";
2
- import {
3
- existsSync,
4
- mkdirSync,
5
- readFileSync,
6
- unlinkSync,
7
- writeFileSync,
8
- } from "node:fs";
9
- import { join } from "node:path";
10
-
11
1
  import type { Command } from "commander";
12
2
 
13
- import { getSignalsDir } from "../../util/platform.js";
3
+ import { cliIpcCall } from "../../ipc/cli-client.js";
14
4
  import { log } from "../logger.js";
15
5
 
16
6
  const DEFAULT_TIMEOUT_MS = 30_000;
17
- const POLL_INTERVAL_MS = 100;
18
7
 
19
- interface BashSignalResult {
20
- requestId: string;
8
+ interface DebugBashResult {
21
9
  stdout: string;
22
10
  stderr: string;
23
11
  exitCode: number | null;
@@ -39,20 +27,16 @@ export function registerBashCommand(program: Command): void {
39
27
  .addHelpText(
40
28
  "after",
41
29
  `
42
- Sends a shell command to the running assistant for execution via the
43
- signals directory. The assistant spawns the command in its own process environment
44
- and returns stdout, stderr, and the exit code.
30
+ Sends a shell command to the running assistant for execution via the IPC
31
+ socket. The assistant spawns the command in its own process environment and
32
+ returns stdout, stderr, and the exit code.
45
33
 
46
34
  This is a developer debugging tool for inspecting how the assistant invokes and
47
35
  observes shell commands. The command runs with the assistant's environment, working
48
36
  directory, and process context — not the caller's shell.
49
37
 
50
38
  Requires the assistant to be running with VELLUM_DEBUG=1. When debug mode is off
51
- (the default), the assistant ignores bash signal files and returns an error.
52
-
53
- The CLI writes the command to signals/bash.<requestId> and polls
54
- signals/bash.<requestId>.result for the output. The assistant must be running
55
- for this to work.
39
+ (the default), the assistant returns an error immediately.
56
40
 
57
41
  Arguments:
58
42
  command The shell command string to execute (e.g. "echo hello", "ls -la").
@@ -64,7 +48,7 @@ Examples:
64
48
  $ assistant bash "env | grep PATH" --timeout 10000
65
49
  $ assistant bash "ls -la"`,
66
50
  )
67
- .action((command: string, opts: { timeout: string }) => {
51
+ .action(async (command: string, opts: { timeout: string }) => {
68
52
  const timeoutMs = parseInt(opts.timeout, 10);
69
53
  if (!Number.isFinite(timeoutMs) || timeoutMs < 1) {
70
54
  log.error("Invalid timeout value. Must be a positive integer.");
@@ -72,105 +56,48 @@ Examples:
72
56
  return;
73
57
  }
74
58
 
75
- const requestId = randomUUID();
76
- const signalsDir = getSignalsDir();
59
+ const result = await cliIpcCall<DebugBashResult>(
60
+ "debug_bash",
61
+ { body: { command, timeoutMs } },
62
+ { timeoutMs: timeoutMs + 10_000 },
63
+ );
77
64
 
78
- try {
79
- mkdirSync(signalsDir, { recursive: true });
80
- } catch {
81
- log.error("Failed to create signals directory.");
65
+ if (!result.ok) {
66
+ log.error(result.error ?? "Failed to reach the assistant.");
82
67
  process.exitCode = 1;
83
68
  return;
84
69
  }
85
70
 
86
- // Write the command signal for the assistant to pick up.
87
- const signalPath = join(signalsDir, `bash.${requestId}`);
88
- const resultPath = join(signalsDir, `bash.${requestId}.result`);
89
-
90
- try {
91
- writeFileSync(
92
- signalPath,
93
- JSON.stringify({ requestId, command, timeoutMs }),
94
- );
95
- } catch {
96
- log.error("Failed to write bash signal file.");
71
+ const data = result.result!;
72
+
73
+ if (data.error) {
74
+ log.error(data.error);
97
75
  process.exitCode = 1;
98
76
  return;
99
77
  }
100
78
 
101
- log.info(`Sent command to assistant (requestId: ${requestId})`);
102
- log.info("Waiting for result...");
103
-
104
- // Poll for the result file until timeout.
105
- const deadline = Date.now() + timeoutMs + 5_000; // extra buffer for assistant overhead
106
-
107
- const poll = setInterval(() => {
108
- if (Date.now() > deadline) {
109
- clearInterval(poll);
110
- cleanupSignalFiles();
111
- log.error(
112
- "Timed out waiting for response. Is the assistant running?",
113
- );
114
- process.exitCode = 1;
115
- return;
116
- }
117
-
118
- if (!existsSync(resultPath)) return;
119
-
120
- let result: BashSignalResult;
121
- try {
122
- const content = readFileSync(resultPath, "utf-8");
123
- result = JSON.parse(content) as BashSignalResult;
124
- } catch {
125
- // File may be partially written; retry on next poll.
126
- return;
127
- }
128
-
129
- // Ignore stale results from a previous invocation.
130
- if (result.requestId !== requestId) return;
131
-
132
- clearInterval(poll);
133
- cleanupSignalFiles();
134
-
135
- if (result.error) {
136
- log.error(result.error);
137
- process.exitCode = 1;
138
- return;
139
- }
140
-
141
- if (result.stdout) {
142
- process.stdout.write(result.stdout);
143
- if (!result.stdout.endsWith("\n")) {
144
- process.stdout.write("\n");
145
- }
146
- }
147
-
148
- if (result.stderr) {
149
- process.stderr.write(result.stderr);
150
- if (!result.stderr.endsWith("\n")) {
151
- process.stderr.write("\n");
152
- }
153
- }
154
-
155
- if (result.timedOut) {
156
- log.info(`Command timed out in assistant.`);
79
+ if (data.stdout) {
80
+ process.stdout.write(data.stdout);
81
+ if (!data.stdout.endsWith("\n")) {
82
+ process.stdout.write("\n");
157
83
  }
84
+ }
158
85
 
159
- if (result.exitCode != null && result.exitCode !== 0) {
160
- log.info(`Exit code: ${result.exitCode}`);
86
+ if (data.stderr) {
87
+ process.stderr.write(data.stderr);
88
+ if (!data.stderr.endsWith("\n")) {
89
+ process.stderr.write("\n");
161
90
  }
91
+ }
162
92
 
163
- process.exitCode = result.exitCode ?? 1;
164
- }, POLL_INTERVAL_MS);
93
+ if (data.timedOut) {
94
+ log.info(`Command timed out in assistant.`);
95
+ }
165
96
 
166
- function cleanupSignalFiles(): void {
167
- for (const p of [signalPath, resultPath]) {
168
- try {
169
- unlinkSync(p);
170
- } catch {
171
- // Best-effort cleanup; the file may already be gone.
172
- }
173
- }
97
+ if (data.exitCode != null && data.exitCode !== 0) {
98
+ log.info(`Exit code: ${data.exitCode}`);
174
99
  }
100
+
101
+ process.exitCode = data.exitCode ?? 1;
175
102
  });
176
103
  }
@@ -35,19 +35,70 @@ import { shouldOutputJson, writeOutput } from "../output.js";
35
35
  // Human-readable formatters
36
36
  // ---------------------------------------------------------------------------
37
37
 
38
- function formatChannelSummary(ch: ContactChannel): string {
39
- const parts = [ch.type, ch.address];
40
- if (ch.status !== "active") parts.push(`(${ch.status})`);
41
- if (ch.policy !== "allow") parts.push(`[${ch.policy}]`);
42
- return parts.join(" ");
38
+ function formatContactTable(contacts: ContactWithChannels[]): string {
39
+ const headers = ["ID", "NAME", "ROLE", "CHANNELS"];
40
+ const rows = contacts.map((c) => [
41
+ c.id,
42
+ c.displayName,
43
+ `${c.role}/${c.contactType}`,
44
+ String(c.channels.length),
45
+ ]);
46
+
47
+ // Pad all columns
48
+ const widths = headers.map((h, i) =>
49
+ Math.max(h.length, ...rows.map((r) => r[i]?.length ?? 0)),
50
+ );
51
+
52
+ const pad = (s: string, w: number) => s.padEnd(w);
53
+ const headerLine = headers.map((h, i) => pad(h, widths[i])).join(" ");
54
+ const separator = widths.map((w) => "─".repeat(w)).join(" ");
55
+
56
+ const dataLines = rows.map((row) =>
57
+ row.map((cell, i) => pad(cell, widths[i])).join(" "),
58
+ );
59
+
60
+ return [headerLine, separator, ...dataLines].join("\n");
43
61
  }
44
62
 
45
- function formatContactRow(c: ContactWithChannels): string {
46
- const channels =
47
- c.channels.length > 0
48
- ? c.channels.map(formatChannelSummary).join(", ")
49
- : "(no channels)";
50
- return `${c.id} ${c.displayName} ${c.role}/${c.contactType} ${channels}`;
63
+ function formatChannelTable(channels: ContactChannel[]): string {
64
+ const headers = ["ID", "TYPE", "ADDRESS", "FLAGS"];
65
+ const rows = channels.map((ch) => {
66
+ const flags = [
67
+ ch.isPrimary ? "primary" : null,
68
+ ch.status !== "active" ? ch.status : null,
69
+ ch.policy !== "allow" ? ch.policy : null,
70
+ ]
71
+ .filter(Boolean)
72
+ .join(", ");
73
+ return [ch.id, ch.type, ch.address, flags];
74
+ });
75
+
76
+ // Pad all columns except the last (FLAGS can be empty)
77
+ const fixedCols = headers.length - 1;
78
+ const widths = headers
79
+ .slice(0, fixedCols)
80
+ .map((h, i) => Math.max(h.length, ...rows.map((r) => r[i]?.length ?? 0)));
81
+
82
+ const pad = (s: string, w: number) => s.padEnd(w);
83
+ const headerLine = [
84
+ ...headers.slice(0, fixedCols).map((h, i) => pad(h, widths[i])),
85
+ headers[fixedCols],
86
+ ].join(" ");
87
+ const separator = [
88
+ ...widths.map((w) => "─".repeat(w)),
89
+ "─".repeat(headers[fixedCols].length),
90
+ ].join(" ");
91
+
92
+ const dataLines = rows.map((row) =>
93
+ [
94
+ ...row.slice(0, fixedCols).map((cell, i) => pad(cell, widths[i])),
95
+ row[fixedCols],
96
+ ].join(" "),
97
+ );
98
+
99
+ return [headerLine, separator, ...dataLines]
100
+ .map((l) => ` ${l}`)
101
+ .join("\n");
51
102
  }
52
103
 
53
104
  function formatContactDetail(
@@ -67,17 +118,7 @@ function formatContactDetail(
67
118
  if (c.channels.length > 0) {
68
119
  lines.push("");
69
120
  lines.push("Channels:");
70
- for (const ch of c.channels) {
71
- const flags = [
72
- ch.isPrimary ? "primary" : null,
73
- ch.status !== "active" ? ch.status : null,
74
- ch.policy !== "allow" ? ch.policy : null,
75
- ]
76
- .filter(Boolean)
77
- .join(", ");
78
- const suffix = flags ? ` (${flags})` : "";
79
- lines.push(` ${ch.id} ${ch.type} ${ch.address}${suffix}`);
80
- }
121
+ lines.push(formatChannelTable(c.channels));
81
122
  }
82
123
  if (assistantMeta?.metadata && "assistantId" in assistantMeta.metadata) {
83
124
  lines.push("");
@@ -205,9 +246,7 @@ Examples:
205
246
  } else if (results.length === 0) {
206
247
  process.stdout.write("No contacts found.\n");
207
248
  } else {
208
- for (const c of results) {
209
- process.stdout.write(formatContactRow(c) + "\n");
210
- }
249
+ process.stdout.write(formatContactTable(results) + "\n");
211
250
  process.stdout.write(`\n${results.length} contact(s)\n`);
212
251
  }
213
252
  } catch (err) {
@@ -15,6 +15,7 @@ import {
15
15
  import type { CredentialPromptResult } from "../../runtime/routes/credential-prompt-routes.js";
16
16
  import { credentialKey } from "../../security/credential-key.js";
17
17
  import {
18
+ getActiveBackendInfoAsync,
18
19
  getSecureKeyAsync,
19
20
  getSecureKeyResultAsync,
20
21
  } from "../../security/secure-keys.js";
@@ -393,6 +394,61 @@ Examples:
393
394
  }
394
395
  });
395
396
 
397
+ // -------------------------------------------------------------------------
398
+ // status
399
+ // -------------------------------------------------------------------------
400
+
401
+ credential
402
+ .command("status")
403
+ .description("Show the active credential backend and its configuration")
404
+ .addHelpText(
405
+ "after",
406
+ `
407
+ Shows which credential storage backend this process is using and backend-specific
408
+ path or connection details. Run this to diagnose credential lookup mismatches —
409
+ for example, when the CLI and the daemon are reading from different stores.
410
+
411
+ Backend types:
412
+ encrypted-store Direct file read from keys.enc (standalone CLI, no daemon)
413
+ ces-rpc Delegates to the running CES process via stdio RPC (daemon)
414
+ ces-http Delegates to CES sidecar over HTTP (containerized/Docker mode)
415
+
416
+ Also shows the CREDENTIAL_SECURITY_DIR, GATEWAY_SECURITY_DIR, and
417
+ VELLUM_WORKSPACE_DIR env vars so you can confirm which instance directory this
418
+ process is scoped to.
419
+
420
+ Examples:
421
+ $ assistant credentials status
422
+ $ assistant credentials status --json`,
423
+ )
424
+ .action(async (_opts: Record<string, unknown>, cmd: Command) => {
425
+ try {
426
+ const info = await getActiveBackendInfoAsync();
427
+
428
+ if (shouldOutputJson(cmd)) {
429
+ writeOutput(cmd, { ok: true, ...info });
430
+ } else {
431
+ log.info(`Backend: ${info.backend}`);
432
+ if (info.backend === "encrypted-store") {
433
+ log.info(
434
+ ` Store path: ${info.storePath} [${info.storeExists ? "exists" : "missing"}]`,
435
+ );
436
+ log.info(
437
+ ` Key path: ${info.storeKeyPath} [${info.storeKeyExists ? "exists" : "missing"}]`,
438
+ );
439
+ } else if (info.backend === "ces-rpc") {
440
+ log.info(` RPC ready: ${info.ready}`);
441
+ } else if (info.backend === "ces-http") {
442
+ log.info(` URL: ${info.url}`);
443
+ }
444
+ }
445
+ } catch (err) {
446
+ const message = err instanceof Error ? err.message : String(err);
447
+ writeError(cmd, message);
448
+ process.exitCode = 1;
449
+ }
450
+ });
451
+
396
452
  // -------------------------------------------------------------------------
397
453
  // set
398
454
  // -------------------------------------------------------------------------
@@ -25,9 +25,9 @@
25
25
  * violation lists). Does not mutate the workspace.
26
26
  *
27
27
  * Lives alongside the existing v1 `memory` command rather than replacing it
28
- * because v1 graph + PKB stays write-active until the cutover PR. Until the
29
- * `memory-v2-enabled` feature flag flips on, the workspace keeps both v1 and
30
- * v2 state side-by-side.
28
+ * so flipping `memory-v2-enabled` back to off fully re-engages the v1
29
+ * pipeline. While the flag is on, v1 graph extraction/maintenance and PKB
30
+ * filing are suppressed; v1 data stays in place but stops being updated.
31
31
  */
32
32
 
33
33
  import type { Command } from "commander";
@@ -267,9 +267,10 @@ Examples:
267
267
  "after",
268
268
  `
269
269
  Re-runs the v2 skill catalog seed against the current skill set, replacing
270
- both the in-process skill cache and the memory_v2_skills Qdrant collection.
271
- Useful after editing a skill's SKILL.md, after a feature-flag flip changes
272
- the enabled-skill set, or to recover a corrupted skills collection.
270
+ both the in-process skill cache and the skill entries in the unified
271
+ memory_v2_concept_pages Qdrant collection (under the skills/<id> slug
272
+ prefix). Useful after editing a skill's SKILL.md, after a feature-flag flip
273
+ changes the enabled-skill set, or to recover corrupted skill embeddings.
273
274
 
274
275
  Unlike 'reembed' (concept pages), this runs synchronously inside the
275
276
  daemon — the command returns only once the seed completes. Requires both