@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
@@ -11,7 +11,6 @@
11
11
  import { z } from "zod";
12
12
 
13
13
  import {
14
- deleteContact,
15
14
  getAssistantContactMetadata,
16
15
  getChannelById,
17
16
  getContact,
@@ -42,7 +41,6 @@ import {
42
41
  import {
43
42
  BadRequestError,
44
43
  ConflictError,
45
- ForbiddenError,
46
44
  NotFoundError,
47
45
  } from "./errors.js";
48
46
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
@@ -154,17 +152,6 @@ function handleGetContact(contactId: string) {
154
152
  };
155
153
  }
156
154
 
157
- function handleDeleteContact(contactId: string) {
158
- const result = deleteContact(contactId);
159
- if (result === "not_found") {
160
- throw new NotFoundError(`Contact "${contactId}" not found`);
161
- }
162
- if (result === "is_guardian") {
163
- throw new ForbiddenError("Cannot delete a guardian contact");
164
- }
165
- return null;
166
- }
167
-
168
155
  // ---------------------------------------------------------------------------
169
156
  // Invite handlers (transport-agnostic)
170
157
  // ---------------------------------------------------------------------------
@@ -502,18 +489,6 @@ export const ROUTES: RouteDefinition[] = [
502
489
  handler: ({ pathParams }: RouteHandlerArgs) =>
503
490
  handleGetContact(pathParams!.id),
504
491
  },
505
- {
506
- operationId: "deleteContact",
507
- endpoint: "contacts/:id",
508
- method: "DELETE",
509
- policyKey: "contacts",
510
- summary: "Delete a contact",
511
- description: "Delete a contact by ID.",
512
- tags: ["contacts"],
513
- responseStatus: "204",
514
- handler: ({ pathParams }: RouteHandlerArgs) =>
515
- handleDeleteContact(pathParams!.id),
516
- },
517
492
  {
518
493
  operationId: "upsert_contact",
519
494
  endpoint: "contacts",
@@ -39,6 +39,7 @@ import {
39
39
  resolveSlash,
40
40
  } from "../../daemon/conversation-slash.js";
41
41
  import { getOrCreateConversation as getOrCreateConversationInstance } from "../../daemon/conversation-store.js";
42
+ import { canonicalizeTimeZone } from "../../daemon/date-context.js";
42
43
  import {
43
44
  getCannedFirstGreeting,
44
45
  isWakeUpGreeting,
@@ -86,6 +87,8 @@ import {
86
87
  getOrCreateConversation,
87
88
  } from "../../memory/conversation-key-store.js";
88
89
  import { searchConversations } from "../../memory/conversation-queries.js";
90
+ import { normalizeOnboardingContext } from "../../prompts/normalize-onboarding.js";
91
+ import { writeOnboardingSection } from "../../prompts/persona-resolver.js";
89
92
  import { getConfiguredProvider } from "../../providers/provider-send-message.js";
90
93
  import type { Provider } from "../../providers/types.js";
91
94
  import { checkIngressForSecrets } from "../../security/secret-ingress.js";
@@ -999,7 +1002,7 @@ function mergeConsecutiveAssistantMessages(messages: MessageRow[]): {
999
1002
  /**
1000
1003
  * Persist the pre-chat onboarding payload to disk.
1001
1004
  *
1002
- * Runs only on the very first message of a fresh conversation. Three
1005
+ * Runs only on the very first message of a fresh conversation. Four
1003
1006
  * artifacts are produced:
1004
1007
  *
1005
1008
  * 1. `data/onboarding-context.json` — sidecar read by the
@@ -1007,12 +1010,15 @@ function mergeConsecutiveAssistantMessages(messages: MessageRow[]): {
1007
1010
  * the pure-recomputation write cycle (every turn boundary rebuilds
1008
1011
  * facts from markdown; the sidecar is the durable source for the
1009
1012
  * tool/task/tone chips).
1010
- * 2. `IDENTITY.md` / `USER.md` persona seed files, only written
1011
- * when missing so we never clobber existing content. These feed
1012
- * the system prompt and the relationship-state writer's
1013
- * `parseIdentity` / `parseUserName` helpers after a daemon
1014
- * restart when the in-memory onboarding context is gone.
1015
- * 3. `data/relationship-state.json` kicked off fire-and-forget so
1013
+ * 2. `IDENTITY.md` assistant persona seed file, only written when
1014
+ * missing so we never clobber existing content. Feeds the system
1015
+ * prompt and the relationship-state writer's `parseIdentity`
1016
+ * helper after a daemon restart when the in-memory onboarding
1017
+ * context is gone.
1018
+ * 3. Onboarding section in the guardian persona file — written via
1019
+ * `writeOnboardingSection`, which handles the user's preferred
1020
+ * name (with fallback to root `USER.md`).
1021
+ * 4. `data/relationship-state.json` — kicked off fire-and-forget so
1016
1022
  * the Home page can populate immediately on first visit instead
1017
1023
  * of waiting for the first agent-turn boundary.
1018
1024
  *
@@ -1057,25 +1063,11 @@ export function persistOnboardingArtifacts(onboarding: {
1057
1063
  }
1058
1064
  }
1059
1065
 
1060
- const userName = onboarding.userName?.trim();
1061
- if (userName) {
1062
- const userPath = getWorkspacePromptPath("USER.md");
1063
- try {
1064
- if (existsSync(userPath)) {
1065
- const content = readFileSync(userPath, "utf-8");
1066
- const updated = content.replace(
1067
- /^- (?:\*\*)?Name:(?:\*\*)?\s*.*$/m,
1068
- () => `- **Name:** ${userName}`,
1069
- );
1070
- if (updated !== content) {
1071
- writeFileSync(userPath, updated, "utf-8");
1072
- }
1073
- } else {
1074
- writeFileSync(userPath, `# User\n\n- **Name:** ${userName}\n`, "utf-8");
1075
- }
1076
- } catch (err) {
1077
- log.warn({ err, userPath }, "Failed to seed USER.md from onboarding");
1078
- }
1066
+ try {
1067
+ const normalized = normalizeOnboardingContext(onboarding);
1068
+ writeOnboardingSection(normalized);
1069
+ } catch (err) {
1070
+ log.warn({ err }, "Failed to write onboarding section to persona file");
1079
1071
  }
1080
1072
 
1081
1073
  void writeRelationshipState().catch((err) => {
@@ -1104,6 +1096,7 @@ export async function handleSendMessage(
1104
1096
  bypassSecretCheck?: boolean;
1105
1097
  hostHomeDir?: string;
1106
1098
  hostUsername?: string;
1099
+ clientTimezone?: unknown;
1107
1100
  clientId?: string;
1108
1101
  clientMessageId?: string;
1109
1102
  inferenceProfile?: string | null;
@@ -1183,6 +1176,10 @@ export async function handleSendMessage(
1183
1176
  )}`,
1184
1177
  );
1185
1178
  }
1179
+ const clientTimezone =
1180
+ typeof body.clientTimezone === "string"
1181
+ ? (canonicalizeTimeZone(body.clientTimezone) ?? undefined)
1182
+ : undefined;
1186
1183
 
1187
1184
  // When conversationKey is omitted, derive a stable default from
1188
1185
  // sourceChannel + sourceInterface so that repeated calls from the same
@@ -1302,10 +1299,12 @@ export async function handleSendMessage(
1302
1299
  interfaceId: sourceInterface,
1303
1300
  hostHomeDir: body.hostHomeDir,
1304
1301
  hostUsername: body.hostUsername,
1302
+ ...(clientTimezone ? { clientTimezone } : {}),
1305
1303
  } satisfies HostProxyTransportMetadata)
1306
1304
  : ({
1307
1305
  channelId: sourceChannel,
1308
1306
  interfaceId: sourceInterface,
1307
+ ...(clientTimezone ? { clientTimezone } : {}),
1309
1308
  } satisfies NonHostProxyTransportMetadata);
1310
1309
 
1311
1310
  const conversation = await smDeps.getOrCreateConversation(
@@ -1991,6 +1990,13 @@ async function generateLlmSuggestion(
1991
1990
  // prefill-safe model. Keep `stop_sequences: ["</reply>"]` as an
1992
1991
  // early-termination hint; the parser below handles both tagged and
1993
1992
  // untagged responses so untagged "casual answer" replies still work.
1993
+ //
1994
+ // Force `thinking: disabled` + `effort: none` so the call works on any
1995
+ // user profile — including thinking-enabled profiles (Opus 4.x at
1996
+ // `effort: high|xhigh`, etc.) where Anthropic 400s on `temperature` ≠ 1
1997
+ // when thinking is enabled or in adaptive mode. A 60-token reply chip
1998
+ // doesn't benefit from extended thinking anyway, and burning thinking
1999
+ // tokens here would be wasteful.
1994
2000
  const response = await provider.sendMessage(
1995
2001
  [{ role: "user", content: [{ type: "text", text: userPrompt }] }],
1996
2002
  [], // no tools
@@ -2001,6 +2007,8 @@ async function generateLlmSuggestion(
2001
2007
  max_tokens: 60,
2002
2008
  stop_sequences: ["</reply>"],
2003
2009
  temperature: 0.7,
2010
+ thinking: { type: "disabled" },
2011
+ effort: "none",
2004
2012
  },
2005
2013
  },
2006
2014
  );
@@ -2274,6 +2282,7 @@ export const ROUTES: RouteDefinition[] = [
2274
2282
  .optional(),
2275
2283
  conversationType: z.string().optional(),
2276
2284
  slashCommand: z.string().optional(),
2285
+ clientTimezone: z.string().optional(),
2277
2286
  inferenceProfile: z.string().nullable().optional(),
2278
2287
  riskThreshold: z.enum(VALID_RISK_THRESHOLDS).optional(),
2279
2288
  }),
@@ -0,0 +1,163 @@
1
+ /**
2
+ * IPC route for executing shell commands through the assistant process.
3
+ *
4
+ * The CLI sends the command over the IPC socket and receives a single
5
+ * response containing stdout, stderr, and the exit code.
6
+ *
7
+ * **Security**: Gated behind VELLUM_DEBUG=1. When debug mode is off (the
8
+ * default), the handler returns an error immediately so the CLI surfaces a
9
+ * clear rejection instead of hanging. The assistant must be restarted with
10
+ * VELLUM_DEBUG=1 for this route to execute commands.
11
+ */
12
+
13
+ import { spawn } from "node:child_process";
14
+
15
+ import { z } from "zod";
16
+
17
+ import { getIsContainerized } from "../../config/env-registry.js";
18
+ import { getWorkspaceDir } from "../../util/platform.js";
19
+ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
20
+
21
+ const DEFAULT_TIMEOUT_MS = 30_000;
22
+
23
+ function isDebugMode(): boolean {
24
+ return (
25
+ process.env.VELLUM_DEBUG === "1" || process.env.VELLUM_DEBUG === "true"
26
+ );
27
+ }
28
+
29
+ interface DebugBashResult {
30
+ stdout: string;
31
+ stderr: string;
32
+ exitCode: number | null;
33
+ timedOut: boolean;
34
+ error?: string;
35
+ }
36
+
37
+ function handleDebugBash({ body }: RouteHandlerArgs): Promise<DebugBashResult> {
38
+ if (getIsContainerized()) {
39
+ return Promise.resolve({
40
+ stdout: "",
41
+ stderr: "",
42
+ exitCode: null,
43
+ timedOut: false,
44
+ error: "debug bash is not available in containerized environments",
45
+ });
46
+ }
47
+
48
+ if (!isDebugMode()) {
49
+ return Promise.resolve({
50
+ stdout: "",
51
+ stderr: "",
52
+ exitCode: null,
53
+ timedOut: false,
54
+ error:
55
+ "Bash debug execution is disabled. The running assistant process must have been started with VELLUM_DEBUG=1 (setting it on the CLI command alone is not enough). Restart the assistant with: vellum sleep && VELLUM_DEBUG=1 vellum wake",
56
+ });
57
+ }
58
+
59
+ const { command, timeoutMs } = body as {
60
+ command?: string;
61
+ timeoutMs?: number;
62
+ };
63
+
64
+ if (!command || typeof command !== "string") {
65
+ return Promise.resolve({
66
+ stdout: "",
67
+ stderr: "",
68
+ exitCode: null,
69
+ timedOut: false,
70
+ error: "command is required",
71
+ });
72
+ }
73
+
74
+ const effectiveTimeout =
75
+ typeof timeoutMs === "number" && timeoutMs > 0
76
+ ? timeoutMs
77
+ : DEFAULT_TIMEOUT_MS;
78
+
79
+ return new Promise<DebugBashResult>((resolve) => {
80
+ const stdoutChunks: Buffer[] = [];
81
+ const stderrChunks: Buffer[] = [];
82
+ let timedOut = false;
83
+ let settled = false;
84
+
85
+ const finish = (result: DebugBashResult) => {
86
+ if (settled) return;
87
+ settled = true;
88
+ resolve(result);
89
+ };
90
+
91
+ const child = spawn("bash", ["-c", command], {
92
+ cwd: getWorkspaceDir(),
93
+ stdio: ["ignore", "pipe", "pipe"],
94
+ detached: true,
95
+ });
96
+
97
+ const timer = setTimeout(() => {
98
+ timedOut = true;
99
+ try {
100
+ process.kill(-child.pid!, "SIGKILL");
101
+ } catch {
102
+ // Process group may have already exited.
103
+ }
104
+ }, effectiveTimeout);
105
+
106
+ child.stdout.on("data", (data: Buffer) => {
107
+ stdoutChunks.push(data);
108
+ });
109
+
110
+ child.stderr.on("data", (data: Buffer) => {
111
+ stderrChunks.push(data);
112
+ });
113
+
114
+ child.on("close", (code) => {
115
+ clearTimeout(timer);
116
+ finish({
117
+ stdout: Buffer.concat(stdoutChunks).toString(),
118
+ stderr: Buffer.concat(stderrChunks).toString(),
119
+ exitCode: code,
120
+ timedOut,
121
+ });
122
+ });
123
+
124
+ child.on("error", (err) => {
125
+ clearTimeout(timer);
126
+ finish({
127
+ stdout: "",
128
+ stderr: "",
129
+ exitCode: null,
130
+ timedOut: false,
131
+ error: err.message,
132
+ });
133
+ });
134
+ });
135
+ }
136
+
137
+ export const ROUTES: RouteDefinition[] = [
138
+ {
139
+ operationId: "debug_bash",
140
+ endpoint: "debug/bash",
141
+ method: "POST",
142
+ requireGuardian: false,
143
+ summary: "Execute a shell command in the assistant process",
144
+ description:
145
+ "Developer debugging tool. Requires the assistant to be running with VELLUM_DEBUG=1.",
146
+ tags: ["debug"],
147
+ requestBody: z.object({
148
+ command: z.string().describe("Shell command to execute via bash -c"),
149
+ timeoutMs: z
150
+ .number()
151
+ .optional()
152
+ .describe("Execution timeout in milliseconds (default: 30000)"),
153
+ }),
154
+ responseBody: z.object({
155
+ stdout: z.string(),
156
+ stderr: z.string(),
157
+ exitCode: z.number().nullable(),
158
+ timedOut: z.boolean(),
159
+ error: z.string().optional(),
160
+ }),
161
+ handler: handleDebugBash,
162
+ },
163
+ ];
@@ -0,0 +1,121 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ acknowledgeDiskPressureLock,
5
+ DISK_PRESSURE_OVERRIDE_CONFIRMATION,
6
+ getDiskPressureStatus,
7
+ overrideDiskPressureLock,
8
+ } from "../../daemon/disk-pressure-guard.js";
9
+ import { RouteError } from "./errors.js";
10
+ import type { RouteDefinition } from "./types.js";
11
+
12
+ const DiskPressureStatusSchema = z.object({
13
+ enabled: z.boolean(),
14
+ state: z.enum(["disabled", "ok", "critical", "unknown"]),
15
+ locked: z.boolean(),
16
+ acknowledged: z.boolean(),
17
+ overrideActive: z.boolean(),
18
+ effectivelyLocked: z.boolean(),
19
+ lockId: z.string().nullable(),
20
+ usagePercent: z.number().nullable(),
21
+ thresholdPercent: z.number(),
22
+ path: z.string().nullable(),
23
+ lastCheckedAt: z.string().nullable(),
24
+ blockedCapabilities: z.array(
25
+ z.enum(["agent-turns", "background-work", "remote-ingress"]),
26
+ ),
27
+ error: z.string().nullable(),
28
+ });
29
+
30
+ const DiskPressureActionResponseSchema = z.object({
31
+ status: DiskPressureStatusSchema,
32
+ });
33
+
34
+ const OverrideRequestSchema = z.object({
35
+ confirmation: z.string(),
36
+ });
37
+
38
+ function statusResponse() {
39
+ return { status: getDiskPressureStatus() };
40
+ }
41
+
42
+ function transitionErrorCode(
43
+ reason: "not_locked" | "already_acknowledged" | "already_overridden",
44
+ ): string {
45
+ if (reason === "not_locked") return "NOT_LOCKED";
46
+ if (reason === "already_acknowledged") return "ALREADY_ACKNOWLEDGED";
47
+ return "ALREADY_OVERRIDDEN";
48
+ }
49
+
50
+ export const ROUTES: RouteDefinition[] = [
51
+ {
52
+ operationId: "getDiskPressureStatus",
53
+ endpoint: "disk-pressure/status",
54
+ method: "GET",
55
+ policyKey: "disk-pressure/status",
56
+ requirePolicyEnforcement: true,
57
+ summary: "Get disk pressure status",
58
+ description:
59
+ "Return the current disk pressure status snapshot. When safe storage limits are disabled, returns a disabled status.",
60
+ tags: ["disk-pressure"],
61
+ responseBody: DiskPressureActionResponseSchema,
62
+ handler: () => statusResponse(),
63
+ },
64
+ {
65
+ operationId: "acknowledgeDiskPressure",
66
+ endpoint: "disk-pressure/acknowledge",
67
+ method: "POST",
68
+ policyKey: "disk-pressure/acknowledge",
69
+ requirePolicyEnforcement: true,
70
+ summary: "Acknowledge disk pressure",
71
+ description:
72
+ "Acknowledge the current disk pressure lock and enter cleanup mode without overriding assistant protections.",
73
+ tags: ["disk-pressure"],
74
+ responseBody: DiskPressureActionResponseSchema,
75
+ additionalResponses: {
76
+ "409": { description: "No active lock or lock already acknowledged." },
77
+ },
78
+ handler: () => {
79
+ const result = acknowledgeDiskPressureLock();
80
+ if (result.ok) return { status: result.status };
81
+ if (result.reason === "invalid_confirmation") {
82
+ throw new RouteError(result.message, "INVALID_CONFIRMATION", 400);
83
+ }
84
+ throw new RouteError(
85
+ result.message,
86
+ transitionErrorCode(result.reason),
87
+ 409,
88
+ );
89
+ },
90
+ },
91
+ {
92
+ operationId: "overrideDiskPressure",
93
+ endpoint: "disk-pressure/override",
94
+ method: "POST",
95
+ policyKey: "disk-pressure/override",
96
+ requirePolicyEnforcement: true,
97
+ summary: "Override disk pressure",
98
+ description: `Override the current disk pressure lock only after confirming "${DISK_PRESSURE_OVERRIDE_CONFIRMATION}".`,
99
+ tags: ["disk-pressure"],
100
+ requestBody: OverrideRequestSchema,
101
+ responseBody: DiskPressureActionResponseSchema,
102
+ additionalResponses: {
103
+ "400": { description: "Confirmation phrase is invalid." },
104
+ "409": { description: "No active lock or lock already overridden." },
105
+ },
106
+ handler: ({ body }) => {
107
+ const parsed = OverrideRequestSchema.safeParse(body);
108
+ const confirmation = parsed.success ? parsed.data.confirmation : "";
109
+ const result = overrideDiskPressureLock(confirmation);
110
+ if (result.ok) return { status: result.status };
111
+ if (result.reason === "invalid_confirmation") {
112
+ throw new RouteError(result.message, "INVALID_CONFIRMATION", 400);
113
+ }
114
+ throw new RouteError(
115
+ result.message,
116
+ transitionErrorCode(result.reason),
117
+ 409,
118
+ );
119
+ },
120
+ },
121
+ ];
@@ -146,8 +146,12 @@ export async function renderMarkdownToPDF(
146
146
  const pw = await importPlaywright();
147
147
  const browser = await pw.chromium.launch({ headless: true });
148
148
  try {
149
- const page = await browser.newPage();
150
- await page.setContent(fullHtml, { waitUntil: "networkidle" });
149
+ const context = await browser.newContext({
150
+ javaScriptEnabled: false,
151
+ });
152
+ const page = await context.newPage();
153
+ await page.route("**/*", (route) => route.abort());
154
+ await page.setContent(fullHtml, { waitUntil: "domcontentloaded" });
151
155
  const pdfBuffer = await page.pdf({
152
156
  format: "A4",
153
157
  margin: {
@@ -6,7 +6,8 @@
6
6
  */
7
7
  import { z } from "zod";
8
8
 
9
- import { rawAll, rawGet, rawRun } from "../../memory/raw-query.js";
9
+ import { saveDocument } from "../../documents/document-store.js";
10
+ import { rawAll, rawGet } from "../../memory/raw-query.js";
10
11
  import { getLogger } from "../../util/logger.js";
11
12
  import { renderMarkdownToPDF } from "./document-pdf-renderer.js";
12
13
  import { BadRequestError, InternalError, NotFoundError } from "./errors.js";
@@ -27,80 +28,6 @@ interface DocumentRow {
27
28
 
28
29
  type DocumentListRow = Omit<DocumentRow, "content">;
29
30
 
30
- // ---------------------------------------------------------------------------
31
- // Junction table helper
32
- // ---------------------------------------------------------------------------
33
-
34
- /** Insert a document–conversation association (idempotent via INSERT OR IGNORE). */
35
- function addDocumentConversation(
36
- surfaceId: string,
37
- conversationId: string,
38
- ): void {
39
- rawRun(
40
- /*sql*/ `INSERT OR IGNORE INTO document_conversations (surface_id, conversation_id, created_at) VALUES (?, ?, ?)`,
41
- surfaceId,
42
- conversationId,
43
- Date.now(),
44
- );
45
- }
46
-
47
- // ---------------------------------------------------------------------------
48
- // Shared business logic (used by both message handlers and HTTP routes)
49
- // ---------------------------------------------------------------------------
50
-
51
- function saveDocument(params: {
52
- surfaceId: string;
53
- conversationId: string;
54
- title: string;
55
- content: string;
56
- wordCount: number;
57
- }): { success: true; surfaceId: string } | { success: false; error: string } {
58
- try {
59
- const now = Date.now();
60
- rawRun(
61
- `INSERT INTO documents (surface_id, conversation_id, title, content, word_count, created_at, updated_at)
62
- VALUES (?, ?, ?, ?, ?, ?, ?)
63
- ON CONFLICT(surface_id) DO UPDATE SET
64
- title = excluded.title,
65
- content = excluded.content,
66
- word_count = excluded.word_count,
67
- updated_at = excluded.updated_at`,
68
- params.surfaceId,
69
- params.conversationId,
70
- params.title,
71
- params.content,
72
- params.wordCount,
73
- now,
74
- now,
75
- );
76
- log.info(
77
- { surfaceId: params.surfaceId, title: params.title },
78
- "Saved document",
79
- );
80
-
81
- // Best-effort: associate the document with the conversation.
82
- // Failures (e.g. migration not yet applied, table missing) must not
83
- // cause the save response to report failure — the document itself is
84
- // already persisted at this point.
85
- try {
86
- addDocumentConversation(params.surfaceId, params.conversationId);
87
- } catch (err) {
88
- log.warn(
89
- { err, surfaceId: params.surfaceId },
90
- "Failed to record document–conversation association",
91
- );
92
- }
93
-
94
- return { success: true, surfaceId: params.surfaceId };
95
- } catch (error) {
96
- log.error({ err: error, surfaceId: params.surfaceId }, "Save error");
97
- return {
98
- success: false,
99
- error: error instanceof Error ? error.message : "Unknown error",
100
- };
101
- }
102
- }
103
-
104
31
  function loadDocument(surfaceId: string):
105
32
  | {
106
33
  success: true;