@vellumai/assistant 0.5.13 → 0.5.14

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 (425) hide show
  1. package/.env.example +1 -6
  2. package/AGENTS.md +4 -0
  3. package/ARCHITECTURE.md +0 -1
  4. package/bunfig.toml +1 -0
  5. package/docs/architecture/memory.md +3 -3
  6. package/openapi.yaml +127 -22
  7. package/package.json +1 -1
  8. package/src/__tests__/access-request-decision.test.ts +2 -32
  9. package/src/__tests__/actor-token-service.test.ts +1 -31
  10. package/src/__tests__/anthropic-provider.test.ts +53 -40
  11. package/src/__tests__/app-git-history.test.ts +9 -17
  12. package/src/__tests__/app-git-service.test.ts +14 -20
  13. package/src/__tests__/app-store-dir-names.test.ts +10 -20
  14. package/src/__tests__/approval-cascade.test.ts +2 -19
  15. package/src/__tests__/approval-primitive.test.ts +2 -27
  16. package/src/__tests__/approval-routes-http.test.ts +2 -30
  17. package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -28
  18. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -45
  19. package/src/__tests__/attachments-store.test.ts +5 -32
  20. package/src/__tests__/audit-log-rotation.test.ts +5 -36
  21. package/src/__tests__/avatar-e2e.test.ts +1 -9
  22. package/src/__tests__/avatar-generator.test.ts +1 -7
  23. package/src/__tests__/browser-fill-credential.test.ts +0 -4
  24. package/src/__tests__/browser-manager.test.ts +0 -6
  25. package/src/__tests__/call-controller.test.ts +1 -22
  26. package/src/__tests__/call-conversation-messages.test.ts +0 -21
  27. package/src/__tests__/call-domain.test.ts +0 -25
  28. package/src/__tests__/call-pointer-messages.test.ts +0 -21
  29. package/src/__tests__/call-recovery.test.ts +0 -22
  30. package/src/__tests__/call-routes-http.test.ts +0 -24
  31. package/src/__tests__/call-store.test.ts +0 -21
  32. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -24
  33. package/src/__tests__/canonical-guardian-store.test.ts +48 -21
  34. package/src/__tests__/channel-approval-routes.test.ts +6 -26
  35. package/src/__tests__/channel-approvals.test.ts +1 -38
  36. package/src/__tests__/channel-delivery-store.test.ts +0 -21
  37. package/src/__tests__/channel-guardian.test.ts +0 -26
  38. package/src/__tests__/channel-reply-delivery.test.ts +5 -0
  39. package/src/__tests__/channel-retry-sweep.test.ts +0 -21
  40. package/src/__tests__/checker.test.ts +26 -61
  41. package/src/__tests__/clawhub.test.ts +9 -25
  42. package/src/__tests__/cli-command-risk-guard.test.ts +0 -18
  43. package/src/__tests__/config-loader-backfill.test.ts +9 -28
  44. package/src/__tests__/config-schema-cmd.test.ts +5 -25
  45. package/src/__tests__/config-schema.test.ts +21 -40
  46. package/src/__tests__/config-watcher.test.ts +4 -91
  47. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -21
  48. package/src/__tests__/contacts-tools.test.ts +0 -21
  49. package/src/__tests__/context-memory-e2e.test.ts +0 -21
  50. package/src/__tests__/context-window-manager.test.ts +130 -3
  51. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -4
  52. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -4
  53. package/src/__tests__/conversation-agent-loop.test.ts +0 -4
  54. package/src/__tests__/conversation-attachments.test.ts +1 -24
  55. package/src/__tests__/conversation-attention-store.test.ts +0 -21
  56. package/src/__tests__/conversation-attention-telegram.test.ts +0 -22
  57. package/src/__tests__/conversation-clear-safety.test.ts +0 -22
  58. package/src/__tests__/conversation-confirmation-signals.test.ts +2 -21
  59. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -24
  60. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -23
  61. package/src/__tests__/conversation-disk-view.test.ts +5 -27
  62. package/src/__tests__/conversation-error.test.ts +1 -1
  63. package/src/__tests__/conversation-fork-crud.test.ts +1 -33
  64. package/src/__tests__/conversation-fork-route.test.ts +0 -27
  65. package/src/__tests__/conversation-history-web-search.test.ts +23 -16
  66. package/src/__tests__/conversation-init.benchmark.test.ts +22 -43
  67. package/src/__tests__/conversation-key-store-disk-view.test.ts +8 -34
  68. package/src/__tests__/conversation-load-history-repair.test.ts +0 -4
  69. package/src/__tests__/conversation-pre-run-repair.test.ts +0 -4
  70. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -4
  71. package/src/__tests__/conversation-queue.test.ts +8 -8
  72. package/src/__tests__/conversation-routes-disk-view.test.ts +13 -51
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +64 -38
  74. package/src/__tests__/conversation-slash-commands.test.ts +5 -0
  75. package/src/__tests__/conversation-slash-queue.test.ts +0 -4
  76. package/src/__tests__/conversation-slash-unknown.test.ts +0 -4
  77. package/src/__tests__/conversation-speed-override.test.ts +326 -0
  78. package/src/__tests__/conversation-starter-routes.test.ts +0 -23
  79. package/src/__tests__/conversation-store.test.ts +0 -21
  80. package/src/__tests__/conversation-unread-route.test.ts +0 -24
  81. package/src/__tests__/conversation-usage.test.ts +56 -21
  82. package/src/__tests__/conversation-wipe.test.ts +0 -21
  83. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  84. package/src/__tests__/conversation-workspace-injection.test.ts +0 -4
  85. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -4
  86. package/src/__tests__/credential-execution-shell-lockdown.test.ts +8 -5
  87. package/src/__tests__/credential-vault-unit.test.ts +9 -428
  88. package/src/__tests__/credentials-cli.test.ts +10 -10
  89. package/src/__tests__/daemon-assistant-events.test.ts +0 -19
  90. package/src/__tests__/date-context.test.ts +77 -97
  91. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +7 -24
  92. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +29 -42
  93. package/src/__tests__/delete-managed-skill-tool.test.ts +2 -10
  94. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -26
  95. package/src/__tests__/docker-signing-key-bootstrap.test.ts +61 -15
  96. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -36
  97. package/src/__tests__/email-cli.test.ts +6 -6
  98. package/src/__tests__/ephemeral-permissions.test.ts +5 -17
  99. package/src/__tests__/first-greeting.test.ts +4 -32
  100. package/src/__tests__/followup-tools.test.ts +0 -21
  101. package/src/__tests__/gateway-only-enforcement.test.ts +0 -20
  102. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -23
  103. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -23
  104. package/src/__tests__/guardian-action-followup-store.test.ts +0 -21
  105. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -21
  106. package/src/__tests__/guardian-action-late-reply.test.ts +0 -21
  107. package/src/__tests__/guardian-action-store.test.ts +0 -21
  108. package/src/__tests__/guardian-action-sweep.test.ts +0 -21
  109. package/src/__tests__/guardian-binding-drift-heal.test.ts +0 -23
  110. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +172 -22
  111. package/src/__tests__/guardian-dispatch.test.ts +0 -21
  112. package/src/__tests__/guardian-grant-minting.test.ts +0 -22
  113. package/src/__tests__/guardian-outbound-http.test.ts +0 -22
  114. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -23
  115. package/src/__tests__/guardian-routing-invariants.test.ts +0 -22
  116. package/src/__tests__/guardian-routing-state.test.ts +0 -22
  117. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -24
  118. package/src/__tests__/headless-browser-interactions.test.ts +0 -4
  119. package/src/__tests__/headless-browser-navigate.test.ts +0 -4
  120. package/src/__tests__/headless-browser-read-tools.test.ts +0 -4
  121. package/src/__tests__/headless-browser-snapshot.test.ts +0 -4
  122. package/src/__tests__/heartbeat-service.test.ts +99 -26
  123. package/src/__tests__/hooks-blocking.test.ts +3 -3
  124. package/src/__tests__/hooks-config.test.ts +7 -7
  125. package/src/__tests__/hooks-discovery.test.ts +3 -3
  126. package/src/__tests__/hooks-integration.test.ts +5 -5
  127. package/src/__tests__/hooks-manager.test.ts +3 -3
  128. package/src/__tests__/hooks-runner.test.ts +5 -23
  129. package/src/__tests__/hooks-settings.test.ts +3 -3
  130. package/src/__tests__/hooks-templates.test.ts +3 -3
  131. package/src/__tests__/http-conversation-lineage.test.ts +0 -27
  132. package/src/__tests__/identity-intro-cache.test.ts +0 -4
  133. package/src/__tests__/inbound-invite-redemption.test.ts +0 -22
  134. package/src/__tests__/inline-skill-load-permissions.test.ts +5 -16
  135. package/src/__tests__/intent-routing.test.ts +2 -55
  136. package/src/__tests__/invite-redemption-service.test.ts +0 -21
  137. package/src/__tests__/invite-routes-http.test.ts +0 -21
  138. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +0 -17
  139. package/src/__tests__/journal-context.test.ts +8 -75
  140. package/src/__tests__/list-messages-attachments.test.ts +0 -22
  141. package/src/__tests__/llm-context-route-provider.test.ts +0 -21
  142. package/src/__tests__/llm-request-log-turn-query.test.ts +46 -28
  143. package/src/__tests__/llm-usage-store.test.ts +0 -21
  144. package/src/__tests__/log-export-workspace.test.ts +1 -1
  145. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
  146. package/src/__tests__/managed-store.test.ts +1 -1
  147. package/src/__tests__/mcp-cli.test.ts +7 -10
  148. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -21
  149. package/src/__tests__/memory-jobs-worker-backoff.test.ts +0 -11
  150. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -21
  151. package/src/__tests__/memory-recall-log-store.test.ts +0 -27
  152. package/src/__tests__/memory-recall-quality.test.ts +0 -21
  153. package/src/__tests__/memory-regressions.experimental.test.ts +31 -30
  154. package/src/__tests__/memory-regressions.test.ts +282 -70
  155. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -21
  156. package/src/__tests__/memory-upsert-concurrency.test.ts +0 -21
  157. package/src/__tests__/messaging-send-tool.test.ts +201 -0
  158. package/src/__tests__/migration-cross-version-compatibility.test.ts +18 -13
  159. package/src/__tests__/migration-export-http.test.ts +7 -1
  160. package/src/__tests__/migration-import-commit-http.test.ts +16 -14
  161. package/src/__tests__/migration-import-preflight-http.test.ts +27 -44
  162. package/src/__tests__/migration-validate-http.test.ts +1 -28
  163. package/src/__tests__/native-web-search.test.ts +25 -22
  164. package/src/__tests__/non-member-access-request.test.ts +0 -22
  165. package/src/__tests__/notification-guardian-path.test.ts +0 -21
  166. package/src/__tests__/notification-schedule-dedup.test.ts +1 -25
  167. package/src/__tests__/oauth-apps-routes.test.ts +103 -2
  168. package/src/__tests__/oauth-cli.test.ts +52 -0
  169. package/src/__tests__/oauth-provider-profiles.test.ts +0 -16
  170. package/src/__tests__/oauth-provider-serializer.test.ts +232 -0
  171. package/src/__tests__/oauth-providers-routes.test.ts +257 -0
  172. package/src/__tests__/oauth-store.test.ts +0 -21
  173. package/src/__tests__/onboarding-template-contract.test.ts +2 -2
  174. package/src/__tests__/openai-provider.test.ts +261 -0
  175. package/src/__tests__/pairing-concurrent.test.ts +6 -6
  176. package/src/__tests__/pairing-routes.test.ts +7 -1
  177. package/src/__tests__/path-policy.test.ts +1 -1
  178. package/src/__tests__/platform.test.ts +64 -88
  179. package/src/__tests__/playbook-execution.test.ts +0 -21
  180. package/src/__tests__/playbook-tools.test.ts +0 -21
  181. package/src/__tests__/pricing.test.ts +100 -0
  182. package/src/__tests__/relay-server.test.ts +1 -25
  183. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -24
  184. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -24
  185. package/src/__tests__/runtime-events-sse.test.ts +0 -24
  186. package/src/__tests__/sandbox-diagnostics.test.ts +2 -1
  187. package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
  188. package/src/__tests__/schedule-store.test.ts +0 -21
  189. package/src/__tests__/schedule-tools.test.ts +0 -21
  190. package/src/__tests__/scheduler-recurrence.test.ts +0 -21
  191. package/src/__tests__/scoped-approval-grants.test.ts +0 -21
  192. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -21
  193. package/src/__tests__/secret-allowlist.test.ts +1 -1
  194. package/src/__tests__/secret-ingress-channel.test.ts +0 -5
  195. package/src/__tests__/secret-ingress-cli.test.ts +0 -6
  196. package/src/__tests__/secret-ingress-http.test.ts +0 -5
  197. package/src/__tests__/secret-ingress.test.ts +0 -5
  198. package/src/__tests__/send-endpoint-busy.test.ts +0 -24
  199. package/src/__tests__/sequence-store.test.ts +0 -21
  200. package/src/__tests__/server-history-render.test.ts +0 -24
  201. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -4
  202. package/src/__tests__/skill-load-inline-command.test.ts +9 -0
  203. package/src/__tests__/skill-load-inline-includes.test.ts +9 -0
  204. package/src/__tests__/skill-load-tool.test.ts +11 -0
  205. package/src/__tests__/skills-uninstall.test.ts +10 -8
  206. package/src/__tests__/skills.test.ts +1 -1
  207. package/src/__tests__/slack-channel-config.test.ts +1 -1
  208. package/src/__tests__/slack-inbound-verification.test.ts +0 -22
  209. package/src/__tests__/starter-bundle.test.ts +4 -1
  210. package/src/__tests__/suggestion-routes.test.ts +2 -0
  211. package/src/__tests__/system-prompt.test.ts +1 -1
  212. package/src/__tests__/terminal-tools.test.ts +1 -1
  213. package/src/__tests__/test-preload.ts +31 -0
  214. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
  215. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  216. package/src/__tests__/tool-executor.test.ts +0 -20
  217. package/src/__tests__/tool-input-summary.test.ts +124 -0
  218. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -1
  219. package/src/__tests__/trust-store.test.ts +7 -1
  220. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -1
  221. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +1 -1
  222. package/src/__tests__/trusted-contact-multichannel.test.ts +1 -1
  223. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  224. package/src/__tests__/turn-boundary-resolution.test.ts +1 -1
  225. package/src/__tests__/twilio-routes.test.ts +1 -1
  226. package/src/__tests__/update-bulletin.test.ts +1 -1
  227. package/src/__tests__/vbundle-pax-and-symlink.test.ts +1 -1
  228. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -0
  229. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
  230. package/src/__tests__/voice-session-bridge.test.ts +1 -1
  231. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +4 -4
  232. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
  233. package/src/__tests__/workspace-migration-down-functions.test.ts +15 -3
  234. package/src/__tests__/workspace-migration-seed-device-id.test.ts +40 -4
  235. package/src/agent/loop.ts +6 -9
  236. package/src/approvals/guardian-decision-primitive.ts +46 -18
  237. package/src/approvals/guardian-request-resolvers.ts +19 -2
  238. package/src/calls/active-call-lease.ts +2 -2
  239. package/src/cli/AGENTS.md +1 -1
  240. package/src/cli/commands/doctor.ts +9 -9
  241. package/src/cli/commands/memory.ts +142 -0
  242. package/src/cli/commands/oauth/__tests__/connect.test.ts +13 -11
  243. package/src/cli/commands/oauth/__tests__/ping.test.ts +1 -1
  244. package/src/cli/commands/oauth/connect.ts +13 -12
  245. package/src/cli/commands/oauth/index.ts +1 -1
  246. package/src/cli/commands/oauth/providers.ts +47 -62
  247. package/src/cli/commands/platform/__tests__/connect.test.ts +72 -46
  248. package/src/cli/commands/platform/__tests__/disconnect.test.ts +54 -1
  249. package/src/cli/commands/platform/__tests__/status.test.ts +36 -0
  250. package/src/cli/commands/platform/connect.ts +17 -7
  251. package/src/cli/commands/platform/disconnect.ts +28 -3
  252. package/src/cli/commands/platform/index.ts +3 -3
  253. package/src/cli.ts +1 -299
  254. package/src/config/assistant-feature-flags.ts +23 -15
  255. package/src/config/bundled-skills/app-builder/TOOLS.json +16 -0
  256. package/src/config/bundled-skills/app-builder/tools/app-create.ts +4 -0
  257. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +5 -1
  258. package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +9 -1
  259. package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +5 -1
  260. package/src/config/bundled-skills/contacts/TOOLS.json +8 -0
  261. package/src/config/bundled-skills/contacts/tools/contact-search.ts +10 -1
  262. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +16 -2
  263. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +1 -0
  264. package/src/config/bundled-skills/messaging/SKILL.md +7 -7
  265. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +37 -0
  266. package/src/config/bundled-skills/slack/SKILL.md +18 -0
  267. package/src/config/env-registry.ts +15 -11
  268. package/src/config/env.ts +1 -11
  269. package/src/config/feature-flag-registry.json +16 -0
  270. package/src/config/schema.ts +4 -0
  271. package/src/config/schemas/heartbeat.ts +6 -1
  272. package/src/config/schemas/inference.ts +14 -3
  273. package/src/config/schemas/memory-processing.ts +16 -8
  274. package/src/config/schemas/memory-retrieval.ts +3 -3
  275. package/src/config/skills.ts +1 -1
  276. package/src/context/window-manager.ts +174 -51
  277. package/src/credential-execution/executable-discovery.ts +2 -2
  278. package/src/daemon/approved-devices-store.ts +2 -2
  279. package/src/daemon/assistant-attachments.ts +2 -0
  280. package/src/daemon/config-watcher.ts +4 -50
  281. package/src/daemon/conversation-agent-loop-handlers.ts +9 -1
  282. package/src/daemon/conversation-agent-loop.ts +12 -0
  283. package/src/daemon/conversation-error.ts +3 -5
  284. package/src/daemon/conversation-history.ts +7 -3
  285. package/src/daemon/conversation-lifecycle.ts +16 -0
  286. package/src/daemon/conversation-messaging.ts +1 -0
  287. package/src/daemon/conversation-notifiers.ts +67 -30
  288. package/src/daemon/conversation-process.ts +161 -2
  289. package/src/daemon/conversation-queue-manager.ts +2 -0
  290. package/src/daemon/conversation-runtime-assembly.ts +33 -11
  291. package/src/daemon/conversation-slash.ts +14 -3
  292. package/src/daemon/conversation-tool-setup.ts +2 -0
  293. package/src/daemon/conversation-usage.ts +32 -4
  294. package/src/daemon/conversation.ts +33 -1
  295. package/src/daemon/daemon-control.ts +32 -16
  296. package/src/daemon/date-context.ts +47 -45
  297. package/src/daemon/dictation-profile-store.ts +2 -2
  298. package/src/daemon/handlers/conversations.ts +19 -0
  299. package/src/daemon/handlers/shared.ts +14 -21
  300. package/src/daemon/lifecycle.ts +5 -7
  301. package/src/daemon/message-types/conversations.ts +2 -0
  302. package/src/daemon/message-types/guardian-actions.ts +3 -17
  303. package/src/daemon/message-types/integrations.ts +11 -1
  304. package/src/daemon/message-types/messages.ts +1 -0
  305. package/src/daemon/pairing-store.ts +2 -79
  306. package/src/daemon/server.ts +154 -8
  307. package/src/daemon/watch-handler.ts +65 -21
  308. package/src/email/guardrails.ts +3 -3
  309. package/src/heartbeat/heartbeat-service.ts +14 -7
  310. package/src/hooks/cli.ts +2 -2
  311. package/src/hooks/config.ts +2 -2
  312. package/src/hooks/discovery.ts +2 -2
  313. package/src/hooks/manager.ts +2 -2
  314. package/src/hooks/runner.ts +5 -2
  315. package/src/hooks/templates.ts +2 -2
  316. package/src/memory/admin.ts +181 -2
  317. package/src/memory/app-git-service.ts +61 -4
  318. package/src/memory/attachments-store.ts +2 -0
  319. package/src/memory/canonical-guardian-store.ts +16 -0
  320. package/src/memory/db-init.ts +8 -0
  321. package/src/memory/embedding-local.ts +5 -2
  322. package/src/memory/indexer.ts +44 -26
  323. package/src/memory/items-extractor.ts +34 -82
  324. package/src/memory/job-handlers/batch-extraction.ts +741 -0
  325. package/src/memory/job-handlers/journal-carry-forward.test.ts +383 -0
  326. package/src/memory/job-handlers/journal-carry-forward.ts +255 -0
  327. package/src/memory/jobs-store.ts +28 -0
  328. package/src/memory/jobs-worker.ts +56 -9
  329. package/src/memory/lifecycle-events-store.ts +4 -2
  330. package/src/memory/llm-request-log-store.ts +40 -2
  331. package/src/memory/llm-usage-store.ts +4 -3
  332. package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +71 -0
  333. package/src/memory/migrations/200-usage-llm-call-count.ts +20 -0
  334. package/src/memory/migrations/index.ts +2 -0
  335. package/src/memory/query-expansion.ts +83 -0
  336. package/src/memory/retriever.test.ts +119 -0
  337. package/src/memory/retriever.ts +513 -105
  338. package/src/memory/schema/guardian.ts +4 -0
  339. package/src/memory/schema/infrastructure.ts +1 -0
  340. package/src/memory/search/formatting.test.ts +140 -0
  341. package/src/memory/search/formatting.ts +143 -198
  342. package/src/memory/search/mmr.ts +136 -0
  343. package/src/memory/search/staleness.ts +0 -15
  344. package/src/memory/search/tier-classifier.ts +10 -21
  345. package/src/memory/search/types.ts +17 -0
  346. package/src/messaging/providers/slack/adapter.ts +51 -5
  347. package/src/notifications/broadcaster.ts +13 -0
  348. package/src/notifications/copy-composer.ts +8 -0
  349. package/src/oauth/connect-orchestrator.ts +1 -1
  350. package/src/oauth/connection-resolver.ts +2 -2
  351. package/src/oauth/provider-serializer.ts +116 -0
  352. package/src/permissions/trust-store.ts +24 -7
  353. package/src/prompts/__tests__/build-cli-reference-section.test.ts +5 -0
  354. package/src/prompts/journal-context.ts +50 -35
  355. package/src/prompts/persona-resolver.ts +1 -1
  356. package/src/prompts/system-prompt.ts +27 -28
  357. package/src/prompts/templates/BOOTSTRAP.md +14 -1
  358. package/src/prompts/templates/HEARTBEAT.md +10 -0
  359. package/src/prompts/templates/NOW.md +19 -25
  360. package/src/prompts/templates/SOUL.md +13 -1
  361. package/src/prompts/templates/UPDATES.md +12 -0
  362. package/src/prompts/update-bulletin.ts +1 -1
  363. package/src/providers/anthropic/client.ts +89 -18
  364. package/src/providers/model-catalog.ts +22 -2
  365. package/src/providers/model-intents.ts +2 -2
  366. package/src/providers/openai/client.ts +40 -1
  367. package/src/providers/retry.ts +23 -4
  368. package/src/providers/types.ts +2 -0
  369. package/src/runtime/assistant-scope.ts +1 -1
  370. package/src/runtime/auth/__tests__/credential-service.test.ts +1 -0
  371. package/src/runtime/auth/route-policy.ts +1 -0
  372. package/src/runtime/auth/token-service.ts +51 -29
  373. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -1
  374. package/src/runtime/guardian-decision-types.ts +16 -10
  375. package/src/runtime/http-server.ts +3 -14
  376. package/src/runtime/http-types.ts +1 -0
  377. package/src/runtime/migrations/vbundle-builder.ts +7 -4
  378. package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -4
  379. package/src/runtime/migrations/vbundle-importer.ts +1 -1
  380. package/src/runtime/routes/conversation-query-routes.ts +40 -8
  381. package/src/runtime/routes/conversation-routes.ts +125 -3
  382. package/src/runtime/routes/guardian-action-routes.ts +9 -3
  383. package/src/runtime/routes/identity-routes.ts +25 -4
  384. package/src/runtime/routes/llm-context-normalization.ts +1 -0
  385. package/src/runtime/routes/log-export-routes.ts +34 -12
  386. package/src/runtime/routes/migration-routes.ts +6 -10
  387. package/src/runtime/routes/oauth-apps.ts +2 -9
  388. package/src/runtime/routes/oauth-providers.ts +60 -0
  389. package/src/runtime/routes/pairing-routes.ts +0 -8
  390. package/src/runtime/routes/settings-routes.ts +0 -1
  391. package/src/runtime/routes/telemetry-routes.ts +16 -4
  392. package/src/security/encrypted-store.ts +2 -2
  393. package/src/security/secret-allowlist.ts +3 -3
  394. package/src/signals/emit-event.ts +42 -0
  395. package/src/signals/user-message.ts +37 -0
  396. package/src/telemetry/usage-telemetry-reporter.test.ts +83 -19
  397. package/src/telemetry/usage-telemetry-reporter.ts +23 -17
  398. package/src/tools/browser/runtime-check.ts +2 -2
  399. package/src/tools/credentials/vault.ts +2 -249
  400. package/src/tools/memory/definitions.ts +1 -1
  401. package/src/tools/memory/handlers.test.ts +50 -8
  402. package/src/tools/memory/handlers.ts +3 -1
  403. package/src/tools/side-effects.ts +1 -6
  404. package/src/tools/terminal/safe-env.ts +3 -2
  405. package/src/tools/terminal/shell.ts +11 -14
  406. package/src/tools/tool-approval-handler.ts +20 -1
  407. package/src/tools/tool-input-summary.ts +66 -0
  408. package/src/tools/types.ts +4 -0
  409. package/src/usage/types.ts +4 -0
  410. package/src/util/device-id.ts +10 -10
  411. package/src/util/platform.ts +71 -33
  412. package/src/util/pricing.ts +19 -6
  413. package/src/util/strip-comment-lines.ts +28 -0
  414. package/src/workspace/git-service.ts +8 -18
  415. package/src/workspace/migrations/003-seed-device-id.ts +6 -4
  416. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +7 -1
  417. package/src/workspace/migrations/017-seed-persona-dirs.ts +2 -4
  418. package/src/workspace/migrations/021-move-signals-to-workspace.ts +84 -0
  419. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +94 -0
  420. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +86 -0
  421. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +126 -0
  422. package/src/workspace/migrations/migrate-to-workspace-volume.ts +3 -6
  423. package/src/workspace/migrations/registry.ts +8 -0
  424. package/src/signals/confirm.ts +0 -82
  425. package/src/signals/trust-rule.ts +0 -174
@@ -18,6 +18,14 @@ import type {
18
18
 
19
19
  const log = getLogger("retry");
20
20
 
21
+ /** Providers that support the `effort` config (extended thinking / reasoning). */
22
+ const EFFORT_SUPPORTED_PROVIDERS = new Set([
23
+ "anthropic",
24
+ "openai",
25
+ "openrouter",
26
+ "fireworks",
27
+ ]);
28
+
21
29
  /** Patterns that indicate a transient streaming corruption from the SDK. */
22
30
  const RETRYABLE_STREAM_PATTERNS = [
23
31
  "Unexpected event order",
@@ -59,13 +67,16 @@ function normalizeSendMessageOptions(
59
67
  const needsThinkingStrip =
60
68
  providerName !== "anthropic" && config.thinking !== undefined;
61
69
  const needsEffortStrip =
62
- providerName !== "anthropic" && config.effort !== undefined;
70
+ !EFFORT_SUPPORTED_PROVIDERS.has(providerName) && config.effort !== undefined;
71
+ const needsSpeedStrip =
72
+ providerName !== "anthropic" && config.speed !== undefined;
63
73
 
64
74
  if (
65
75
  !hasIntent &&
66
76
  explicitModel === config.model &&
67
77
  !needsThinkingStrip &&
68
- !needsEffortStrip
78
+ !needsEffortStrip &&
79
+ !needsSpeedStrip
69
80
  ) {
70
81
  return options;
71
82
  }
@@ -78,11 +89,19 @@ function normalizeSendMessageOptions(
78
89
  delete nextConfig.thinking;
79
90
  }
80
91
 
81
- // effort is Anthropic-specific; strip it for other providers
82
- if (providerName !== "anthropic" && nextConfig.effort !== undefined) {
92
+ // effort is supported by Anthropic, OpenAI, and OpenAI-compatible providers; strip for others
93
+ if (
94
+ !EFFORT_SUPPORTED_PROVIDERS.has(providerName) &&
95
+ nextConfig.effort !== undefined
96
+ ) {
83
97
  delete nextConfig.effort;
84
98
  }
85
99
 
100
+ // speed (fast mode) is Anthropic-specific; strip for other providers
101
+ if (providerName !== "anthropic" && nextConfig.speed !== undefined) {
102
+ delete nextConfig.speed;
103
+ }
104
+
86
105
  if (explicitModel) {
87
106
  nextConfig.model = explicitModel;
88
107
  } else if (intent) {
@@ -101,6 +101,7 @@ export interface ProviderResponse {
101
101
  outputTokens: number;
102
102
  cacheCreationInputTokens?: number;
103
103
  cacheReadInputTokens?: number;
104
+ reasoningTokens?: number;
104
105
  };
105
106
  stopReason: string;
106
107
  /** Raw JSON request body sent to the provider (for diagnostics logging). */
@@ -131,6 +132,7 @@ export interface SendMessageConfig {
131
132
  model?: string;
132
133
  modelIntent?: ModelIntent;
133
134
  effort?: "low" | "medium" | "high" | "max";
135
+ speed?: "standard" | "fast";
134
136
  [key: string]: unknown;
135
137
  }
136
138
 
@@ -8,7 +8,7 @@
8
8
  * IDs — use this constant instead.
9
9
  *
10
10
  * Multi-instance invariant: each daemon process is single-tenant within
11
- * its own BASE_DATA_DIR. The fixed "self" value works across multiple
11
+ * its own workspace. The fixed "self" value works across multiple
12
12
  * local instances because each instance has isolated storage — there is
13
13
  * no cross-instance data sharing that would require disambiguating IDs.
14
14
  */
@@ -50,6 +50,7 @@ const TEST_KEY = Buffer.from("test-signing-key-32-bytes-long!!");
50
50
  initializeDb();
51
51
 
52
52
  beforeEach(() => {
53
+ process.env.VELLUM_ASSISTANT_NAME = "vellum-test-eel";
53
54
  initAuthSigningKey(TEST_KEY);
54
55
  resetExternalAssistantIdCache();
55
56
  resetDb();
@@ -463,6 +463,7 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
463
463
  { endpoint: "oauth/apps/connections", scopes: ["settings.read"] },
464
464
  { endpoint: "oauth/apps/connect", scopes: ["settings.write"] },
465
465
  { endpoint: "oauth/connections", scopes: ["settings.write"] },
466
+ { endpoint: "oauth/providers", scopes: ["settings.read"] },
466
467
 
467
468
  // Ingress config
468
469
  { endpoint: "integrations/ingress/config:GET", scopes: ["settings.read"] },
@@ -19,10 +19,11 @@ import {
19
19
  renameSync,
20
20
  writeFileSync,
21
21
  } from "node:fs";
22
+ import { homedir } from "node:os";
22
23
  import { dirname, join } from "node:path";
23
24
 
24
25
  import { getLogger } from "../../util/logger.js";
25
- import { getRootDir } from "../../util/platform.js";
26
+ import { getDeprecatedDir } from "../../util/platform.js";
26
27
  import { CURRENT_POLICY_EPOCH, isStaleEpoch } from "./policy.js";
27
28
  import type { ScopeProfile, TokenAudience, TokenClaims } from "./types.js";
28
29
 
@@ -35,51 +36,71 @@ const log = getLogger("token-service");
35
36
  let _authSigningKey: Buffer | undefined;
36
37
 
37
38
  /**
38
- * Path to the persisted signing key file.
39
- * Stored in the protected directory alongside other sensitive material.
39
+ * Hardcoded legacy path to the signing key under ~/.vellum/protected/.
40
+ * Used as a read-only fallback so existing assistants keep working after
41
+ * the code update — avoids generating a new key that would break auth
42
+ * with an already-running daemon.
43
+ *
44
+ * This constant can be deleted once we stop calling the gateway directly.
45
+ */
46
+ const LEGACY_SIGNING_KEY_PATH = join(
47
+ homedir(),
48
+ ".vellum",
49
+ "protected",
50
+ "actor-token-signing-key",
51
+ );
52
+
53
+ /**
54
+ * Returns the canonical path to the signing key file under workspace/deprecated/.
55
+ *
56
+ * This file can be fully deleted once the assistant stops making direct
57
+ * calls to the gateway (i.e. all auth flows go through the env var).
40
58
  */
41
59
  function getSigningKeyPath(): string {
42
- return join(getRootDir(), "protected", "actor-token-signing-key");
60
+ return join(getDeprecatedDir(), "actor-token-signing-key");
43
61
  }
44
62
 
45
63
  /**
46
- * Load a signing key from disk. Returns the key buffer if found and valid,
47
- * or undefined if the file does not exist or is invalid.
48
- *
49
- * Used in the Docker 403-fallback path where generating a new key would
50
- * create a mismatch with the gateway's already-bootstrapped key.
64
+ * Load a signing key from a file on disk. Returns the key buffer if found
65
+ * and valid, or undefined if the file does not exist or is invalid.
51
66
  */
52
67
  export function loadSigningKey(): Buffer | undefined {
53
- const keyPath = getSigningKeyPath();
54
- if (!existsSync(keyPath)) {
55
- return undefined;
56
- }
57
- try {
58
- const raw = readFileSync(keyPath);
59
- if (raw.length === 32) {
60
- log.info("Auth signing key loaded from disk");
61
- return raw;
68
+ // Try the canonical workspace/deprecated/ path first, then fall back to
69
+ // the legacy protected/ path so existing assistants keep working.
70
+ for (const keyPath of [getSigningKeyPath(), LEGACY_SIGNING_KEY_PATH]) {
71
+ if (!existsSync(keyPath)) {
72
+ continue;
73
+ }
74
+ try {
75
+ const raw = readFileSync(keyPath);
76
+ if (raw.length === 32) {
77
+ log.info({ keyPath }, "Auth signing key loaded from disk");
78
+ return raw;
79
+ }
80
+ log.warn({ keyPath }, "Signing key file has unexpected length");
81
+ } catch (err) {
82
+ log.warn({ err, keyPath }, "Failed to read signing key file");
62
83
  }
63
- log.warn("Signing key file has unexpected length");
64
- return undefined;
65
- } catch (err) {
66
- log.warn({ err }, "Failed to read signing key file");
67
- return undefined;
68
84
  }
85
+ return undefined;
69
86
  }
70
87
 
71
88
  /**
72
89
  * Load a signing key from disk or generate and persist a new one.
73
90
  * Uses atomic-write + chmod 0o600 for safe persistence.
91
+ *
92
+ * The key is stored at workspace/deprecated/actor-token-signing-key.
93
+ * This file can be fully deleted once the assistant stops making direct
94
+ * calls to the gateway (i.e. all auth flows go through the env var).
74
95
  */
75
96
  export function loadOrCreateSigningKey(): Buffer {
97
+ const keyPath = getSigningKeyPath();
76
98
  const existing = loadSigningKey();
77
99
  if (existing) {
78
100
  return existing;
79
101
  }
80
102
 
81
103
  // Generate and persist a new key
82
- const keyPath = getSigningKeyPath();
83
104
  const newKey = randomBytes(32);
84
105
  const dir = dirname(keyPath);
85
106
  if (!existsSync(dir)) {
@@ -95,11 +116,9 @@ export function loadOrCreateSigningKey(): Buffer {
95
116
  }
96
117
 
97
118
  /**
98
- * Resolve the signing key for the current environment.
99
- *
100
- * Resolution order:
101
- * 1. ACTOR_TOKEN_SIGNING_KEY env var (hex-encoded, set by CLI for Docker)
102
- * 2. File-based load/create (~/.vellum/protected/actor-token-signing-key)
119
+ * Resolve the signing key for the daemon from the `ACTOR_TOKEN_SIGNING_KEY`
120
+ * env var (hex-encoded, 64 chars). The CLI launcher sets this before
121
+ * spawning the daemon; in Docker the gateway injects it.
103
122
  */
104
123
  export function resolveSigningKey(): Buffer {
105
124
  const envKey = process.env.ACTOR_TOKEN_SIGNING_KEY;
@@ -113,6 +132,9 @@ export function resolveSigningKey(): Buffer {
113
132
  return Buffer.from(envKey, "hex");
114
133
  }
115
134
 
135
+ // Fallback: env var not set (e.g. daemon spawned by cli/src/lib/local.ts
136
+ // which does not yet inject the env var). Load or create from disk.
137
+ log.warn("ACTOR_TOKEN_SIGNING_KEY env var not set — falling back to disk");
116
138
  return loadOrCreateSigningKey();
117
139
  }
118
140
 
@@ -140,7 +140,9 @@ export function bridgeConfirmationRequestToGuardian(
140
140
  trustContext.requesterExternalUserId ||
141
141
  "unknown";
142
142
 
143
- const questionText = `Tool approval request: ${toolName}`;
143
+ const questionText = canonicalRequest.activityText
144
+ ? `Approve tool: ${toolName} — ${canonicalRequest.activityText}`
145
+ : `Approve tool: ${toolName}`;
144
146
 
145
147
  // Emit guardian.question notification so the guardian is alerted.
146
148
  const signalPromise = emitNotificationSignal({
@@ -31,6 +31,14 @@ export interface GuardianDecisionPrompt {
31
31
  * store. Absent for legacy-only prompts.
32
32
  */
33
33
  kind?: string;
34
+ /** Human-readable preview of the command being approved (e.g. shell command). */
35
+ commandPreview?: string;
36
+ /** Risk level label for the request (e.g. 'low', 'medium', 'high'). */
37
+ riskLevel?: string;
38
+ /** Short activity description for richer prompt display. */
39
+ activityText?: string;
40
+ /** Where the tool will execute — sandbox or host. */
41
+ executionTarget?: "sandbox" | "host";
34
42
  }
35
43
 
36
44
  export interface GuardianDecisionAction {
@@ -55,12 +63,12 @@ export const GUARDIAN_DECISION_ACTIONS = {
55
63
  },
56
64
  approve_10m: {
57
65
  action: "approve_10m",
58
- label: "Allow 10 min",
66
+ label: "Allow all, 10 min",
59
67
  description: "All tools for 10 minutes",
60
68
  },
61
69
  approve_conversation: {
62
70
  action: "approve_conversation",
63
- label: "Allow conversation",
71
+ label: "Allow all, convo",
64
72
  description: "All tools for this conversation",
65
73
  },
66
74
  approve_always: {
@@ -76,12 +84,11 @@ export const GUARDIAN_DECISION_ACTIONS = {
76
84
  * respecting whether persistent decisions (approve_always) are allowed.
77
85
  *
78
86
  * When `persistentDecisionsAllowed` is `false`, the `approve_always` action
79
- * is excluded. When `forGuardianOnBehalf` is `true` (guardian acting on behalf
80
- * of a requester), both `approve_always` and the temporary modes are excluded
81
- * since guardians cannot grant broad delegated allow modes on behalf of others.
82
- *
83
- * Temporary modes (`approve_10m`, `approve_conversation`) are included for
84
- * requester-side standard approval flows when persistent decisions are allowed.
87
+ * and temporary modes are excluded. When `forGuardianOnBehalf` is `true`
88
+ * (guardian acting on behalf of a requester), only `approve_always` is excluded
89
+ * temporary modes (`approve_10m`, `approve_conversation`) are permitted
90
+ * because grants are scoped to the tool+input signature via scopeMode:
91
+ * "tool_signature".
85
92
  */
86
93
  export function buildDecisionActions(opts?: {
87
94
  persistentDecisionsAllowed?: boolean;
@@ -89,8 +96,7 @@ export function buildDecisionActions(opts?: {
89
96
  }): GuardianDecisionAction[] {
90
97
  const showAlways =
91
98
  opts?.persistentDecisionsAllowed !== false && !opts?.forGuardianOnBehalf;
92
- const showTemporary =
93
- opts?.persistentDecisionsAllowed !== false && !opts?.forGuardianOnBehalf;
99
+ const showTemporary = opts?.persistentDecisionsAllowed !== false;
94
100
  return [
95
101
  GUARDIAN_DECISION_ACTIONS.approve_once,
96
102
  ...(showTemporary
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { existsSync, readFileSync } from "node:fs";
9
- import { join, resolve } from "node:path";
9
+ import { resolve } from "node:path";
10
10
 
11
11
  import type { ServerWebSocket } from "bun";
12
12
 
@@ -61,7 +61,6 @@ import {
61
61
  } from "../security/oauth-callback-registry.js";
62
62
  import { UserError } from "../util/errors.js";
63
63
  import { getLogger } from "../util/logger.js";
64
- import { getRootDir } from "../util/platform.js";
65
64
  import { buildAssistantEvent } from "./assistant-event.js";
66
65
  import { assistantEventHub } from "./assistant-event-hub.js";
67
66
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "./assistant-scope.js";
@@ -163,6 +162,7 @@ import { migrationRollbackRouteDefinitions } from "./routes/migration-rollback-r
163
162
  import { migrationRouteDefinitions } from "./routes/migration-routes.js";
164
163
  import { notificationRouteDefinitions } from "./routes/notification-routes.js";
165
164
  import { oauthAppsRouteDefinitions } from "./routes/oauth-apps.js";
165
+ import { oauthProvidersRouteDefinitions } from "./routes/oauth-providers.js";
166
166
  import type { PairingHandlerContext } from "./routes/pairing-routes.js";
167
167
  import {
168
168
  handlePairingRequest,
@@ -293,23 +293,11 @@ export class RuntimeHttpServer {
293
293
  this.pairingBroadcast = fn;
294
294
  }
295
295
 
296
- /** Read the feature-flag client token from disk so it can be included in pairing approval responses. */
297
- private readFeatureFlagToken(): string | undefined {
298
- try {
299
- const tokenPath = join(getRootDir(), "feature-flag-token");
300
- const token = readFileSync(tokenPath, "utf-8").trim();
301
- return token || undefined;
302
- } catch {
303
- return undefined;
304
- }
305
- }
306
-
307
296
  private get pairingContext(): PairingHandlerContext {
308
297
  const broadcast = this.pairingBroadcast;
309
298
  return {
310
299
  pairingStore: this.pairingStore,
311
300
  bearerToken: this.bearerToken,
312
- featureFlagToken: this.readFeatureFlagToken(),
313
301
  pairingBroadcast: broadcast
314
302
  ? (msg) => {
315
303
  // Broadcast to all clients via the event hub so HTTP/SSE clients
@@ -1204,6 +1192,7 @@ export class RuntimeHttpServer {
1204
1192
  ...twilioRouteDefinitions(),
1205
1193
  ...vercelRouteDefinitions(),
1206
1194
  ...channelReadinessRouteDefinitions(),
1195
+ ...oauthProvidersRouteDefinitions(),
1207
1196
  ...oauthAppsRouteDefinitions(),
1208
1197
  ...attachmentRouteDefinitions(),
1209
1198
 
@@ -272,5 +272,6 @@ export interface RuntimeMessagePayload {
272
272
  display?: string;
273
273
  }>;
274
274
  textSegments?: string[];
275
+ thinkingSegments?: string[];
275
276
  contentOrder?: string[];
276
277
  }
@@ -395,9 +395,12 @@ export interface BuildExportVBundleOptions {
395
395
  /** Absolute path to trust.json. If provided and the file exists, it is included in the archive. */
396
396
  trustPath?: string;
397
397
  /**
398
- * Absolute path to the hooks directory (~/.vellum/hooks/).
399
- * Hooks live outside the workspace, so they must be included explicitly.
400
- * Included in the archive under the "hooks/" prefix for backward compat.
398
+ * Absolute path to the hooks directory. Previously hooks lived outside the
399
+ * workspace at ~/.vellum/hooks/ and needed explicit inclusion. Now hooks
400
+ * live under workspace (~/.vellum/workspace/hooks/) and are included in
401
+ * the workspace walk. Only pass this for backward-compat scenarios where
402
+ * hooks are still outside the workspace; otherwise omit to avoid double
403
+ * export. Included in the archive under the "hooks/" prefix.
401
404
  */
402
405
  hooksDir?: string;
403
406
  /**
@@ -455,7 +458,7 @@ export function buildExportVBundle(
455
458
  files.push(
456
459
  ...walkDirectory(workspaceDir, "workspace", {
457
460
  includeBinary: true,
458
- skipDirs: ["embedding-models", "data/qdrant"],
461
+ skipDirs: ["embedding-models", "data/qdrant", "signals", "deprecated"],
459
462
  }),
460
463
  );
461
464
  }
@@ -88,7 +88,6 @@ export interface PathResolver {
88
88
 
89
89
  export class DefaultPathResolver implements PathResolver {
90
90
  constructor(
91
- private protectedDir?: string,
92
91
  private workspaceDir?: string,
93
92
  private hooksDir?: string,
94
93
  ) {}
@@ -114,9 +113,6 @@ export class DefaultPathResolver implements PathResolver {
114
113
  if (archivePath === "config/settings.json" && this.workspaceDir) {
115
114
  return join(this.workspaceDir, "config.json");
116
115
  }
117
- if (archivePath === "trust/trust.json" && this.protectedDir) {
118
- return join(this.protectedDir, "trust.json");
119
- }
120
116
  if (archivePath.startsWith("skills/") && this.workspaceDir) {
121
117
  const resolved = resolve(
122
118
  this.workspaceDir,
@@ -164,7 +164,7 @@ export function commitImport(options: ImportCommitOptions): ImportCommitResult {
164
164
  }
165
165
 
166
166
  // Directories to preserve when clearing the workspace (large/regenerable).
167
- const WORKSPACE_SKIP_DIRS = new Set(["embedding-models"]);
167
+ const WORKSPACE_SKIP_DIRS = new Set(["embedding-models", "deprecated"]);
168
168
  // data/qdrant is nested — we skip "qdrant" inside "data/"
169
169
  const DATA_SKIP_DIRS = new Set(["qdrant"]);
170
170
 
@@ -48,9 +48,13 @@ import { deleteQueuedMessage } from "../../daemon/handlers/conversations.js";
48
48
  import { getAssistantMessageIdsInTurn } from "../../memory/conversation-crud.js";
49
49
  import { getRequestLogsByMessageId } from "../../memory/llm-request-log-store.js";
50
50
  import { getMemoryRecallLogByMessageIds } from "../../memory/memory-recall-log-store.js";
51
+ import { resolvePricingForUsage } from "../../util/pricing.js";
51
52
  import { httpError } from "../http-errors.js";
52
53
  import type { RouteDefinition } from "../http-router.js";
53
- import { normalizeLlmContextPayloads } from "./llm-context-normalization.js";
54
+ import {
55
+ type LlmContextSummary,
56
+ normalizeLlmContextPayloads,
57
+ } from "./llm-context-normalization.js";
54
58
 
55
59
  const validProviderSet = new Set<string>(VALID_INFERENCE_PROVIDERS);
56
60
  const validEmbeddingProviderSet = new Set<string>(
@@ -71,20 +75,48 @@ type LlmContextRouteResult = Omit<LlmContextNormalizationResult, "summary"> & {
71
75
  summary?: LlmContextSummaryResponse;
72
76
  };
73
77
 
78
+ function attachEstimatedCost(summary: LlmContextSummary): LlmContextSummary {
79
+ const { provider, model, inputTokens, outputTokens } = summary;
80
+ if (!model || inputTokens == null || outputTokens == null) {
81
+ return summary;
82
+ }
83
+
84
+ const cacheCreation = summary.cacheCreationInputTokens ?? 0;
85
+ const cacheRead = summary.cacheReadInputTokens ?? 0;
86
+ const directInputTokens = Math.max(
87
+ inputTokens - cacheCreation - cacheRead,
88
+ 0,
89
+ );
90
+
91
+ const result = resolvePricingForUsage(provider, model, {
92
+ directInputTokens,
93
+ outputTokens,
94
+ cacheCreationInputTokens: cacheCreation,
95
+ cacheReadInputTokens: cacheRead,
96
+ anthropicCacheCreation: null,
97
+ });
98
+
99
+ return { ...summary, estimatedCostUsd: result.estimatedCostUsd };
100
+ }
101
+
74
102
  function applyStoredProviderToLlmContextResult(
75
103
  normalized: LlmContextNormalizationResult,
76
104
  provider: string | null,
77
105
  ): LlmContextRouteResult {
78
106
  if (!provider) {
79
- return normalized as LlmContextRouteResult;
107
+ const summary = normalized.summary
108
+ ? attachEstimatedCost(normalized.summary)
109
+ : undefined;
110
+ return { ...normalized, summary } as LlmContextRouteResult;
80
111
  }
81
112
 
82
- return {
83
- ...normalized,
84
- summary: normalized.summary
85
- ? { ...normalized.summary, provider }
86
- : { provider },
87
- };
113
+ const mergedSummary = normalized.summary
114
+ ? { ...normalized.summary, provider }
115
+ : { provider };
116
+ const summary = attachEstimatedCost(
117
+ mergedSummary as LlmContextSummary,
118
+ );
119
+ return { ...normalized, summary };
88
120
  }
89
121
 
90
122
  // ---------------------------------------------------------------------------