@vellumai/assistant 0.5.13 → 0.5.15

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
package/.env.example CHANGED
@@ -21,12 +21,7 @@ VELLUM_PLATFORM_URL=https://dev-platform.vellum.ai
21
21
 
22
22
  # --- Sentry (crash reporting) ---
23
23
  # Omit to disable Sentry.
24
- SENTRY_DSN_ASSISTANT=https://db2d38a082e4ee35eeaea08c44b376ec@o4504590528675840.ingest.us.sentry.io/4510874712276992
25
-
26
- # --- Telemetry ---
27
- # Omit to disable telemetry reporting.
28
- TELEMETRY_PLATFORM_URL=https://platform.vellum.ai
29
- TELEMETRY_APP_TOKEN=e01cf85768cc3617e986f0a7f1966b72e25316526c5db54c8b94a9c3c5c9eaed
24
+ SENTRY_DSN_ASSISTANT=
30
25
 
31
26
  # --- Network proxy ---
32
27
  # Comma-separated host patterns allowed through the proxy.
package/AGENTS.md CHANGED
@@ -11,3 +11,7 @@ When you introduce a new env var that the assistant process needs to read at run
11
11
  `safe-env.ts` maintains the allowlist of env vars that are forwarded to agent-spawned child processes (bash tool, skill sandbox, etc.). Anything not on the list is stripped to prevent credential leakage. If your new var is needed by commands the agent runs, it must be added.
12
12
 
13
13
  **Default to including it.** If the var doesn't contain secrets (e.g. a URL, a feature flag, a path, a mode string), add it. Only omit it if it carries credential material (tokens, passwords, private keys) — those must stay isolated to CES.
14
+
15
+ ## Code comments
16
+
17
+ When writing or updating comments, **do not reference code that has been removed.** Comments should describe the current state of the codebase, not narrate its history. Avoid phrases like "no longer does X", "previously used Y", or "was removed in PR Z" — future readers should not need to understand past implementations to understand the current code.
package/ARCHITECTURE.md CHANGED
@@ -707,7 +707,6 @@ graph LR
707
707
 
708
708
  subgraph "~/.vellum/ (Root Files)"
709
709
  TRUST["protected/trust.json<br/>Tool permission rules"]
710
- FF_TOKEN["feature-flag-token<br/>Client token for feature-flag API"]
711
710
  end
712
711
 
713
712
  subgraph "~/.vellum/workspace/ (Workspace Files)"
package/bunfig.toml CHANGED
@@ -1,2 +1,3 @@
1
1
  [test]
2
2
  root = "./src"
3
+ preload = ["./src/__tests__/test-preload.ts"]
@@ -260,10 +260,10 @@ The key distinction: normal compaction is a cost-optimized background process th
260
260
  | Config key | Default | Purpose |
261
261
  | ----------------------------------------------------- | ------------------------: | -------------------------------------------------------------------- |
262
262
  | `memory.retrieval.dynamicBudget.enabled` | `true` | Toggle per-turn recall budget calculation from live prompt headroom. |
263
- | `memory.retrieval.dynamicBudget.minInjectTokens` | `1200` | Lower clamp for computed recall injection budget. |
264
- | `memory.retrieval.dynamicBudget.maxInjectTokens` | `10000` | Upper clamp for computed recall injection budget. |
263
+ | `memory.retrieval.dynamicBudget.minInjectTokens` | `2400` | Lower clamp for computed recall injection budget. |
264
+ | `memory.retrieval.dynamicBudget.maxInjectTokens` | `16000` | Upper clamp for computed recall injection budget. |
265
265
  | `memory.retrieval.dynamicBudget.targetHeadroomTokens` | `10000` | Reserved headroom to keep free for response generation/tool traces. |
266
- | `memory.retrieval.maxInjectTokens` | `10000` | Static fallback when dynamic budget is disabled. |
266
+ | `memory.retrieval.maxInjectTokens` | `16000` | Static fallback when dynamic budget is disabled. |
267
267
  | `memory.retrieval.scopePolicy` | `'allow_global_fallback'` | Scope filtering strategy: `'strict'` or `'allow_global_fallback'`. |
268
268
 
269
269
  ### Memory Recall Debugging Playbook
package/openapi.yaml CHANGED
@@ -3,7 +3,7 @@
3
3
  openapi: 3.0.0
4
4
  info:
5
5
  title: Vellum Assistant API
6
- version: 0.5.12
6
+ version: 0.5.13
7
7
  description: Auto-generated OpenAPI specification for the Vellum Assistant runtime HTTP server.
8
8
  servers:
9
9
  - url: http://127.0.0.1:7821
@@ -3144,7 +3144,7 @@ paths:
3144
3144
  post:
3145
3145
  operationId: export_post
3146
3146
  summary: Export logs and audit data
3147
- description: Export audit records, daemon logs, workspace contents, and config as a tar.gz archive.
3147
+ description: Export audit records, assistant logs, workspace contents, and config as a tar.gz archive.
3148
3148
  tags:
3149
3149
  - export
3150
3150
  responses:
@@ -3158,24 +3158,19 @@ paths:
3158
3158
  type: object
3159
3159
  properties:
3160
3160
  auditLimit:
3161
+ description: Max audit records (default 1000)
3161
3162
  type: integer
3162
3163
  minimum: -9007199254740991
3163
3164
  maximum: 9007199254740991
3164
- description: Max audit records (default 1000)
3165
3165
  conversationId:
3166
- type: string
3167
3166
  description: Scope to a single conversation
3167
+ type: string
3168
3168
  startTime:
3169
- type: number
3170
3169
  description: Lower bound epoch ms
3171
- endTime:
3172
3170
  type: number
3171
+ endTime:
3173
3172
  description: Upper bound epoch ms
3174
- required:
3175
- - auditLimit
3176
- - conversationId
3177
- - startTime
3178
- - endTime
3173
+ type: number
3179
3174
  additionalProperties: false
3180
3175
  /v1/guardian-actions/decision:
3181
3176
  post:
@@ -3316,6 +3311,52 @@ paths:
3316
3311
  - cpu
3317
3312
  - migrations
3318
3313
  additionalProperties: false
3314
+ /v1/healthz:
3315
+ get:
3316
+ operationId: healthz_get
3317
+ summary: Detailed health check (alias)
3318
+ description: Alias for /v1/health. Returns runtime health including version, disk, memory, CPU, and migration status.
3319
+ tags:
3320
+ - system
3321
+ responses:
3322
+ "200":
3323
+ description: Successful response
3324
+ content:
3325
+ application/json:
3326
+ schema:
3327
+ type: object
3328
+ properties:
3329
+ status:
3330
+ type: string
3331
+ timestamp:
3332
+ type: string
3333
+ version:
3334
+ type: string
3335
+ disk:
3336
+ type: object
3337
+ properties: {}
3338
+ additionalProperties: {}
3339
+ memory:
3340
+ type: object
3341
+ properties: {}
3342
+ additionalProperties: {}
3343
+ cpu:
3344
+ type: object
3345
+ properties: {}
3346
+ additionalProperties: {}
3347
+ migrations:
3348
+ type: object
3349
+ properties: {}
3350
+ additionalProperties: {}
3351
+ required:
3352
+ - status
3353
+ - timestamp
3354
+ - version
3355
+ - disk
3356
+ - memory
3357
+ - cpu
3358
+ - migrations
3359
+ additionalProperties: false
3319
3360
  /v1/heartbeat/checklist:
3320
3361
  get:
3321
3362
  operationId: heartbeat_checklist_get
@@ -3968,6 +4009,38 @@ paths:
3968
4009
  responses:
3969
4010
  "200":
3970
4011
  description: Successful response
4012
+ /v1/logs/export:
4013
+ post:
4014
+ operationId: logs_export_post
4015
+ summary: Export logs and audit data (alias)
4016
+ description: Alias for /v1/export. Export audit records, assistant logs, workspace contents, and config as a tar.gz archive.
4017
+ tags:
4018
+ - export
4019
+ responses:
4020
+ "200":
4021
+ description: Successful response
4022
+ requestBody:
4023
+ required: true
4024
+ content:
4025
+ application/json:
4026
+ schema:
4027
+ type: object
4028
+ properties:
4029
+ auditLimit:
4030
+ description: Max audit records (default 1000)
4031
+ type: integer
4032
+ minimum: -9007199254740991
4033
+ maximum: 9007199254740991
4034
+ conversationId:
4035
+ description: Scope to a single conversation
4036
+ type: string
4037
+ startTime:
4038
+ description: Lower bound epoch ms
4039
+ type: number
4040
+ endTime:
4041
+ description: Upper bound epoch ms
4042
+ type: number
4043
+ additionalProperties: false
3971
4044
  /v1/memory-items:
3972
4045
  get:
3973
4046
  operationId: memoryitems_get
@@ -4644,6 +4717,28 @@ paths:
4644
4717
  required: true
4645
4718
  schema:
4646
4719
  type: string
4720
+ /v1/oauth/providers:
4721
+ get:
4722
+ operationId: oauth_providers_get
4723
+ tags:
4724
+ - oauth-providers
4725
+ responses:
4726
+ "200":
4727
+ description: Successful response
4728
+ /v1/oauth/providers/{providerKey}:
4729
+ get:
4730
+ operationId: oauth_providers_by_providerKey_get
4731
+ tags:
4732
+ - oauth-providers
4733
+ responses:
4734
+ "200":
4735
+ description: Successful response
4736
+ parameters:
4737
+ - name: providerKey
4738
+ in: path
4739
+ required: true
4740
+ schema:
4741
+ type: string
4647
4742
  /v1/oauth/start:
4648
4743
  post:
4649
4744
  operationId: oauth_start_post
@@ -6281,17 +6376,27 @@ paths:
6281
6376
  content:
6282
6377
  application/json:
6283
6378
  schema:
6284
- type: object
6285
- properties:
6286
- id:
6287
- type: string
6288
- description: Event ID
6289
- event_name:
6290
- type: string
6291
- required:
6292
- - id
6293
- - event_name
6294
- additionalProperties: false
6379
+ anyOf:
6380
+ - type: object
6381
+ properties:
6382
+ id:
6383
+ type: string
6384
+ description: Event ID
6385
+ event_name:
6386
+ type: string
6387
+ required:
6388
+ - id
6389
+ - event_name
6390
+ additionalProperties: false
6391
+ - type: object
6392
+ properties:
6393
+ skipped:
6394
+ type: boolean
6395
+ const: true
6396
+ description: Event skipped due to usage data collection being disabled
6397
+ required:
6398
+ - skipped
6399
+ additionalProperties: false
6295
6400
  requestBody:
6296
6401
  required: true
6297
6402
  content:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.5.13",
3
+ "version": "0.5.15",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -8,28 +8,7 @@
8
8
  * - Stale: handles already-resolved requests gracefully.
9
9
  * - Idempotent: approving same request twice does not create duplicate sessions.
10
10
  */
11
- import { mkdtempSync, rmSync } from "node:fs";
12
- import { tmpdir } from "node:os";
13
- import { join } from "node:path";
14
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
15
-
16
- // ---------------------------------------------------------------------------
17
- // Test isolation: in-memory SQLite via temp directory
18
- // ---------------------------------------------------------------------------
19
-
20
- const testDir = mkdtempSync(join(tmpdir(), "access-request-decision-test-"));
21
-
22
- mock.module("../util/platform.js", () => ({
23
- getRootDir: () => testDir,
24
- getDataDir: () => testDir,
25
- isMacOS: () => process.platform === "darwin",
26
- isLinux: () => process.platform === "linux",
27
- isWindows: () => process.platform === "win32",
28
- getPidPath: () => join(testDir, "test.pid"),
29
- getDbPath: () => join(testDir, "test.db"),
30
- getLogPath: () => join(testDir, "test.log"),
31
- ensureDataDir: () => {},
32
- }));
11
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
33
12
 
34
13
  mock.module("../util/logger.js", () => ({
35
14
  getLogger: () =>
@@ -56,7 +35,7 @@ mock.module("../runtime/gateway-client.js", () => ({
56
35
  },
57
36
  }));
58
37
 
59
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
38
+ import { getDb, initializeDb } from "../memory/db.js";
60
39
  import {
61
40
  createApprovalRequest,
62
41
  getApprovalRequestById,
@@ -72,15 +51,6 @@ import {
72
51
 
73
52
  initializeDb();
74
53
 
75
- afterAll(() => {
76
- resetDb();
77
- try {
78
- rmSync(testDir, { recursive: true });
79
- } catch {
80
- /* best effort */
81
- }
82
- });
83
-
84
54
  // ---------------------------------------------------------------------------
85
55
  // Helpers
86
56
  // ---------------------------------------------------------------------------
@@ -6,25 +6,7 @@
6
6
  * that middleware is replaced by the JWT auth middleware in
7
7
  * runtime/auth/middleware.ts (tested in auth/middleware.test.ts).
8
8
  */
9
- import { mkdtempSync, realpathSync, rmSync } from "node:fs";
10
- import { tmpdir } from "node:os";
11
- import { join } from "node:path";
12
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
13
-
14
- const testDir = realpathSync(mkdtempSync(join(tmpdir(), "actor-token-test-")));
15
-
16
- mock.module("../util/platform.js", () => ({
17
- getRootDir: () => testDir,
18
- getDataDir: () => testDir,
19
- getDbPath: () => join(testDir, "test.db"),
20
- normalizeAssistantId: (id: string) => (id === "self" ? "self" : id),
21
- isMacOS: () => process.platform === "darwin",
22
- isLinux: () => process.platform === "linux",
23
- isWindows: () => process.platform === "win32",
24
- getPidPath: () => join(testDir, "test.pid"),
25
- getLogPath: () => join(testDir, "test.log"),
26
- ensureDataDir: () => {},
27
- }));
9
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
28
10
 
29
11
  mock.module("../util/logger.js", () => ({
30
12
  getLogger: () =>
@@ -40,7 +22,6 @@ mock.module("../config/env.js", () => ({
40
22
  getRuntimeGatewayOriginSecret: () => undefined,
41
23
  isHttpAuthDisabledWithoutSafetyGate: () => false,
42
24
  checkUnrecognizedEnvVars: () => {},
43
- getBaseDataDir: () => testDir,
44
25
  }));
45
26
 
46
27
  import { findGuardianForChannel } from "../contacts/contact-store.js";
@@ -110,12 +91,6 @@ beforeEach(() => {
110
91
  db.run("DELETE FROM contacts");
111
92
  });
112
93
 
113
- afterAll(() => {
114
- try {
115
- rmSync(testDir, { recursive: true, force: true });
116
- } catch {}
117
- });
118
-
119
94
  // ---------------------------------------------------------------------------
120
95
  // Hash-only storage
121
96
  // ---------------------------------------------------------------------------
@@ -462,7 +437,6 @@ describe("pairing credential flow", () => {
462
437
  const ctx = {
463
438
  pairingStore: store,
464
439
  bearerToken,
465
- featureFlagToken: undefined,
466
440
  pairingBroadcast: () => {},
467
441
  };
468
442
 
@@ -520,7 +494,6 @@ describe("pairing credential flow", () => {
520
494
  const ctx = {
521
495
  pairingStore: store,
522
496
  bearerToken,
523
- featureFlagToken: undefined,
524
497
  pairingBroadcast: () => {},
525
498
  };
526
499
 
@@ -577,7 +550,6 @@ describe("pairing credential flow", () => {
577
550
  const ctx = {
578
551
  pairingStore: store,
579
552
  bearerToken,
580
- featureFlagToken: undefined,
581
553
  pairingBroadcast: () => {},
582
554
  };
583
555
 
@@ -637,7 +609,6 @@ describe("pairing credential flow", () => {
637
609
  const ctx = {
638
610
  pairingStore: store,
639
611
  bearerToken,
640
- featureFlagToken: undefined,
641
612
  pairingBroadcast: () => {},
642
613
  };
643
614
 
@@ -727,4 +698,3 @@ describe("bootstrap private-network guard", () => {
727
698
  expect(res.status).toBe(200);
728
699
  });
729
700
  });
730
-
@@ -37,25 +37,37 @@ mock.module("@anthropic-ai/sdk", () => ({
37
37
  constructor(args: Record<string, unknown>) {
38
38
  lastConstructorArgs = { ...args };
39
39
  }
40
+ #streamImpl = (
41
+ params: Record<string, unknown>,
42
+ options?: Record<string, unknown>,
43
+ ) => {
44
+ lastStreamParams = JSON.parse(JSON.stringify(params));
45
+ _lastStreamOptions = options ?? null;
46
+ const handlers: Record<string, ((...args: unknown[]) => void)[]> = {};
47
+ return {
48
+ on(event: string, cb: (...args: unknown[]) => void) {
49
+ (handlers[event] ??= []).push(cb);
50
+ return this;
51
+ },
52
+ async finalMessage() {
53
+ // Fire text events
54
+ for (const cb of handlers["text"] ?? []) cb("Hello");
55
+ return fakeResponse;
56
+ },
57
+ };
58
+ };
40
59
  messages = {
41
60
  stream: (
42
61
  params: Record<string, unknown>,
43
62
  options?: Record<string, unknown>,
44
- ) => {
45
- lastStreamParams = JSON.parse(JSON.stringify(params));
46
- _lastStreamOptions = options ?? null;
47
- const handlers: Record<string, ((...args: unknown[]) => void)[]> = {};
48
- return {
49
- on(event: string, cb: (...args: unknown[]) => void) {
50
- (handlers[event] ??= []).push(cb);
51
- return this;
52
- },
53
- async finalMessage() {
54
- // Fire text events
55
- for (const cb of handlers["text"] ?? []) cb("Hello");
56
- return fakeResponse;
57
- },
58
- };
63
+ ) => this.#streamImpl(params, options),
64
+ };
65
+ beta = {
66
+ messages: {
67
+ stream: (
68
+ params: Record<string, unknown>,
69
+ options?: Record<string, unknown>,
70
+ ) => this.#streamImpl(params, options),
59
71
  },
60
72
  };
61
73
  },
@@ -138,16 +150,16 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
138
150
  // -----------------------------------------------------------------------
139
151
  // System prompt cache control
140
152
  // -----------------------------------------------------------------------
141
- test("system prompt has cache_control ephemeral", async () => {
153
+ test("system prompt has cache_control ephemeral with 1h TTL", async () => {
142
154
  await provider.sendMessage([userMsg("Hi")], undefined, "You are helpful.");
143
155
 
144
156
  const system = lastStreamParams!.system as Array<{
145
157
  type: string;
146
158
  text: string;
147
- cache_control?: { type: string };
159
+ cache_control?: { type: string; ttl?: string };
148
160
  }>;
149
161
  expect(system).toHaveLength(1);
150
- expect(system[0].cache_control).toEqual({ type: "ephemeral" });
162
+ expect(system[0].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
151
163
  });
152
164
 
153
165
  test("no system param when system prompt is omitted", async () => {
@@ -166,13 +178,13 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
166
178
  const system = lastStreamParams!.system as Array<{
167
179
  type: string;
168
180
  text: string;
169
- cache_control?: { type: string };
181
+ cache_control?: { type: string; ttl?: string };
170
182
  }>;
171
183
  expect(system).toHaveLength(2);
172
184
  expect(system[0].text).toBe(staticBlock);
173
- expect(system[0].cache_control).toEqual({ type: "ephemeral" });
185
+ expect(system[0].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
174
186
  expect(system[1].text).toBe(dynamicBlock);
175
- expect(system[1].cache_control).toEqual({ type: "ephemeral" });
187
+ expect(system[1].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
176
188
  });
177
189
 
178
190
  // -----------------------------------------------------------------------
@@ -183,7 +195,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
183
195
 
184
196
  const tools = lastStreamParams!.tools as Array<{
185
197
  name: string;
186
- cache_control?: { type: string };
198
+ cache_control?: { type: string; ttl?: string };
187
199
  }>;
188
200
  expect(tools).toHaveLength(3);
189
201
 
@@ -192,7 +204,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
192
204
  expect(tools[1].cache_control).toBeUndefined();
193
205
 
194
206
  // Last tool: cache_control ephemeral
195
- expect(tools[2].cache_control).toEqual({ type: "ephemeral" });
207
+ expect(tools[2].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
196
208
  });
197
209
 
198
210
  test("single tool gets cache_control", async () => {
@@ -200,10 +212,10 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
200
212
 
201
213
  const tools = lastStreamParams!.tools as Array<{
202
214
  name: string;
203
- cache_control?: { type: string };
215
+ cache_control?: { type: string; ttl?: string };
204
216
  }>;
205
217
  expect(tools).toHaveLength(1);
206
- expect(tools[0].cache_control).toEqual({ type: "ephemeral" });
218
+ expect(tools[0].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
207
219
  });
208
220
 
209
221
  test("no tools param when tools are omitted", async () => {
@@ -223,7 +235,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
223
235
  content: Array<{
224
236
  type: string;
225
237
  text: string;
226
- cache_control?: { type: string };
238
+ cache_control?: { type: string; ttl?: string };
227
239
  }>;
228
240
  }>;
229
241
  const lastUser = messages[messages.length - 1];
@@ -248,7 +260,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
248
260
  content: Array<{
249
261
  type: string;
250
262
  text: string;
251
- cache_control?: { type: string };
263
+ cache_control?: { type: string; ttl?: string };
252
264
  }>;
253
265
  }>;
254
266
 
@@ -264,7 +276,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
264
276
  // Second user turn (second-to-last): cache_control ephemeral
265
277
  const secondUserLastBlock =
266
278
  userMessages[1].content[userMessages[1].content.length - 1];
267
- expect(secondUserLastBlock.cache_control).toEqual({ type: "ephemeral" });
279
+ expect(secondUserLastBlock.cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
268
280
 
269
281
  // Third user turn (last): no cache_control
270
282
  const thirdUserLastBlock =
@@ -280,7 +292,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
280
292
  content: Array<{
281
293
  type: string;
282
294
  text: string;
283
- cache_control?: { type: string };
295
+ cache_control?: { type: string; ttl?: string };
284
296
  }>;
285
297
  }>;
286
298
  const userMessages = sent.filter((m) => m.role === "user");
@@ -303,12 +315,12 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
303
315
 
304
316
  const sent = lastStreamParams!.messages as Array<{
305
317
  role: string;
306
- content: Array<{ type: string; cache_control?: { type: string } }>;
318
+ content: Array<{ type: string; cache_control?: { type: string; ttl?: string } }>;
307
319
  }>;
308
320
  const userMsgs = sent.filter((m) => m.role === "user");
309
321
  // First user msg (second-to-last) should get cache
310
322
  const firstLast = userMsgs[0].content[userMsgs[0].content.length - 1];
311
- expect(firstLast.cache_control).toEqual({ type: "ephemeral" });
323
+ expect(firstLast.cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
312
324
  // tool_result msg (last) should NOT get cache
313
325
  const secondLast = userMsgs[1].content[userMsgs[1].content.length - 1];
314
326
  expect(secondLast.cache_control).toBeUndefined();
@@ -330,7 +342,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
330
342
  content: Array<{
331
343
  type: string;
332
344
  text: string;
333
- cache_control?: { type: string };
345
+ cache_control?: { type: string; ttl?: string };
334
346
  }>;
335
347
  }>;
336
348
  const assistantMsgs = sent.filter((m) => m.role === "assistant");
@@ -361,7 +373,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
361
373
  content: Array<{
362
374
  type: string;
363
375
  text: string;
364
- cache_control?: { type: string };
376
+ cache_control?: { type: string; ttl?: string };
365
377
  }>;
366
378
  }>;
367
379
  const user = sent[0];
@@ -402,7 +414,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
402
414
  content: Array<{
403
415
  type: string;
404
416
  text: string;
405
- cache_control?: { type: string };
417
+ cache_control?: { type: string; ttl?: string };
406
418
  }>;
407
419
  }>;
408
420
  const user = sent[0];
@@ -436,7 +448,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
436
448
  content: Array<{
437
449
  type: string;
438
450
  text: string;
439
- cache_control?: { type: string };
451
+ cache_control?: { type: string; ttl?: string };
440
452
  }>;
441
453
  }>;
442
454
  const user = sent[0];
@@ -1309,7 +1321,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
1309
1321
  content: Array<{
1310
1322
  type: string;
1311
1323
  text: string;
1312
- cache_control?: { type: string };
1324
+ cache_control?: { type: string; ttl?: string };
1313
1325
  }>;
1314
1326
  }>;
1315
1327
  const userMsgs = sent.filter((m) => m.role === "user");
@@ -1321,7 +1333,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
1321
1333
 
1322
1334
  // Turn 2 (second-to-last): cache on last block only
1323
1335
  expect(userMsgs[1].content[0].cache_control).toBeUndefined();
1324
- expect(userMsgs[1].content[1].cache_control).toEqual({ type: "ephemeral" });
1336
+ expect(userMsgs[1].content[1].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
1325
1337
 
1326
1338
  // Turn 3 (last): no cache
1327
1339
  expect(userMsgs[2].content[0].cache_control).toBeUndefined();
@@ -1548,16 +1560,17 @@ describe("AnthropicProvider — Managed Proxy Fallback", () => {
1548
1560
 
1549
1561
  // System prompt cache control
1550
1562
  const system = lastStreamParams!.system as Array<{
1551
- cache_control?: { type: string };
1563
+ cache_control?: { type: string; ttl?: string };
1552
1564
  }>;
1553
- expect(system[0].cache_control).toEqual({ type: "ephemeral" });
1565
+ expect(system[0].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
1554
1566
 
1555
1567
  // Last tool cache control
1556
1568
  const tools = lastStreamParams!.tools as Array<{
1557
- cache_control?: { type: string };
1569
+ cache_control?: { type: string; ttl?: string };
1558
1570
  }>;
1559
1571
  expect(tools[tools.length - 1].cache_control).toEqual({
1560
1572
  type: "ephemeral",
1573
+ ttl: "1h",
1561
1574
  });
1562
1575
  });
1563
1576
  });