@vellumai/assistant 0.6.3 → 0.6.4

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 (667) hide show
  1. package/ARCHITECTURE.md +273 -10
  2. package/Dockerfile +2 -3
  3. package/bun.lock +5 -13
  4. package/docs/backup-troubleshooting.md +52 -0
  5. package/docs/browser-use-architecture-phase2.md +174 -0
  6. package/docs/stt-provider-onboarding.md +120 -0
  7. package/knip.json +12 -2
  8. package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
  9. package/node_modules/@vellumai/ces-contracts/package.json +3 -3
  10. package/openapi.yaml +982 -72
  11. package/package.json +4 -6
  12. package/scripts/generate-openapi.ts +0 -1
  13. package/scripts/test.sh +73 -18
  14. package/src/__tests__/agent-image-optimize.test.ts +28 -0
  15. package/src/__tests__/agent-loop.test.ts +123 -0
  16. package/src/__tests__/anthropic-provider.test.ts +263 -10
  17. package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
  18. package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
  19. package/src/__tests__/browser-fill-credential.test.ts +11 -0
  20. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  21. package/src/__tests__/browser-skill-endstate.test.ts +31 -7
  22. package/src/__tests__/btw-routes.test.ts +7 -0
  23. package/src/__tests__/call-controller.test.ts +581 -20
  24. package/src/__tests__/catalog-files.test.ts +138 -0
  25. package/src/__tests__/channel-invite-transport.test.ts +2 -2
  26. package/src/__tests__/channel-readiness-routes.test.ts +16 -20
  27. package/src/__tests__/channel-readiness-service.test.ts +12 -7
  28. package/src/__tests__/checker.test.ts +157 -10
  29. package/src/__tests__/clawhub-files.test.ts +347 -0
  30. package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
  31. package/src/__tests__/config-analysis.test.ts +100 -0
  32. package/src/__tests__/config-schema.test.ts +1013 -66
  33. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
  34. package/src/__tests__/config-watcher.test.ts +43 -8
  35. package/src/__tests__/contact-store-user-file.test.ts +512 -0
  36. package/src/__tests__/contacts-write.test.ts +197 -0
  37. package/src/__tests__/context-window-manager.test.ts +88 -0
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  40. package/src/__tests__/conversation-agent-loop.test.ts +98 -2
  41. package/src/__tests__/conversation-confirmation-signals.test.ts +135 -0
  42. package/src/__tests__/conversation-error.test.ts +70 -0
  43. package/src/__tests__/conversation-history-web-search.test.ts +11 -4
  44. package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
  45. package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
  46. package/src/__tests__/conversation-list-source.test.ts +145 -0
  47. package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
  48. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
  49. package/src/__tests__/conversation-queue.test.ts +901 -60
  50. package/src/__tests__/conversation-routes-disk-view.test.ts +270 -0
  51. package/src/__tests__/conversation-runtime-assembly.test.ts +55 -0
  52. package/src/__tests__/conversation-skill-tools.test.ts +7 -4
  53. package/src/__tests__/conversation-slash-commands.test.ts +33 -0
  54. package/src/__tests__/conversation-slash-queue.test.ts +89 -18
  55. package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
  56. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
  57. package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
  58. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
  59. package/src/__tests__/credential-health-service.test.ts +352 -0
  60. package/src/__tests__/credential-security-invariants.test.ts +5 -3
  61. package/src/__tests__/credential-vault-unit.test.ts +379 -3
  62. package/src/__tests__/credentials-cli.test.ts +40 -16
  63. package/src/__tests__/cross-provider-web-search.test.ts +146 -35
  64. package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
  65. package/src/__tests__/device-id.test.ts +112 -0
  66. package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
  67. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
  68. package/src/__tests__/email-html-renderer.test.ts +71 -0
  69. package/src/__tests__/email-invite-adapter.test.ts +36 -32
  70. package/src/__tests__/emit-event-signal.test.ts +71 -0
  71. package/src/__tests__/extension-id-sync-guard.test.ts +75 -8
  72. package/src/__tests__/fixtures/mock-chrome-extension.ts +11 -0
  73. package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
  74. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  75. package/src/__tests__/gemini-provider.test.ts +64 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
  77. package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
  78. package/src/__tests__/gmail-archive-gate.test.ts +246 -0
  79. package/src/__tests__/gmail-preferences.test.ts +117 -0
  80. package/src/__tests__/headless-browser-interactions.test.ts +43 -0
  81. package/src/__tests__/headless-browser-mode.test.ts +614 -0
  82. package/src/__tests__/headless-browser-navigate.test.ts +142 -5
  83. package/src/__tests__/headless-browser-read-tools.test.ts +11 -0
  84. package/src/__tests__/headless-browser-snapshot.test.ts +10 -0
  85. package/src/__tests__/heartbeat-service.test.ts +70 -17
  86. package/src/__tests__/home-state-routes.test.ts +162 -0
  87. package/src/__tests__/host-bash-proxy.test.ts +0 -5
  88. package/src/__tests__/host-browser-e2e-cloud.test.ts +138 -4
  89. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +4 -4
  90. package/src/__tests__/host-browser-ws-events-e2e.test.ts +103 -0
  91. package/src/__tests__/host-cu-proxy.test.ts +0 -5
  92. package/src/__tests__/identity-intro-cache.test.ts +40 -10
  93. package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
  94. package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
  95. package/src/__tests__/llm-context-normalization.test.ts +488 -0
  96. package/src/__tests__/llm-context-route-provider.test.ts +86 -5
  97. package/src/__tests__/llm-usage-store.test.ts +363 -0
  98. package/src/__tests__/media-stream-output.test.ts +555 -0
  99. package/src/__tests__/media-stream-parser.test.ts +374 -0
  100. package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
  101. package/src/__tests__/media-stream-stt-session.test.ts +588 -0
  102. package/src/__tests__/media-turn-detector.test.ts +440 -0
  103. package/src/__tests__/message-queue.test.ts +125 -0
  104. package/src/__tests__/migration-export-http.test.ts +6 -6
  105. package/src/__tests__/migration-import-commit-http.test.ts +8 -6
  106. package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
  107. package/src/__tests__/migration-validate-http.test.ts +3 -3
  108. package/src/__tests__/mock-gateway-ipc.ts +151 -0
  109. package/src/__tests__/model-intents.test.ts +2 -2
  110. package/src/__tests__/oauth-apps-routes.test.ts +1 -0
  111. package/src/__tests__/oauth-cli.test.ts +2 -0
  112. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
  113. package/src/__tests__/oauth-provider-serializer.test.ts +1 -0
  114. package/src/__tests__/oauth-providers-routes.test.ts +2 -0
  115. package/src/__tests__/oauth-store.test.ts +85 -0
  116. package/src/__tests__/oauth2-gateway-transport.test.ts +249 -6
  117. package/src/__tests__/onboarding-template-contract.test.ts +6 -13
  118. package/src/__tests__/openai-provider.test.ts +176 -0
  119. package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
  120. package/src/__tests__/openai-responses-provider.test.ts +1105 -0
  121. package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
  122. package/src/__tests__/outlook-unsubscribe.test.ts +31 -2
  123. package/src/__tests__/persona-resolver.test.ts +251 -0
  124. package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
  125. package/src/__tests__/platform.test.ts +92 -1
  126. package/src/__tests__/post-turn-tool-result-truncation.test.ts +47 -0
  127. package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
  128. package/src/__tests__/pricing.test.ts +174 -0
  129. package/src/__tests__/qdrant-manager.test.ts +29 -8
  130. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
  131. package/src/__tests__/relationship-state-contract.test.ts +175 -0
  132. package/src/__tests__/relay-server.test.ts +423 -5
  133. package/src/__tests__/search-skills-unified.test.ts +118 -0
  134. package/src/__tests__/secret-scanner-executor.test.ts +4 -0
  135. package/src/__tests__/secure-keys.test.ts +107 -0
  136. package/src/__tests__/send-endpoint-busy.test.ts +5 -1
  137. package/src/__tests__/sequence-store.test.ts +1 -1
  138. package/src/__tests__/server-history-render.test.ts +49 -0
  139. package/src/__tests__/settings-routes.test.ts +201 -0
  140. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  141. package/src/__tests__/skills-file-content-endpoint.test.ts +276 -145
  142. package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
  143. package/src/__tests__/skills.test.ts +5 -2
  144. package/src/__tests__/skillssh-files.test.ts +446 -0
  145. package/src/__tests__/slack-block-formatting.test.ts +110 -0
  146. package/src/__tests__/slack-channel-config.test.ts +564 -1
  147. package/src/__tests__/stt-catalog-parity.test.ts +282 -0
  148. package/src/__tests__/stt-stream-session.test.ts +535 -0
  149. package/src/__tests__/system-prompt.test.ts +112 -26
  150. package/src/__tests__/telephony-stt-routing.test.ts +329 -0
  151. package/src/__tests__/terminal-tools.test.ts +18 -7
  152. package/src/__tests__/test-preload.ts +18 -0
  153. package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
  155. package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
  156. package/src/__tests__/tool-executor.test.ts +33 -24
  157. package/src/__tests__/tool-result-truncation.test.ts +36 -0
  158. package/src/__tests__/trust-store.test.ts +7 -1
  159. package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
  160. package/src/__tests__/tts-catalog-parity.test.ts +345 -0
  161. package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
  162. package/src/__tests__/twilio-routes.test.ts +376 -0
  163. package/src/__tests__/unicode.test.ts +293 -0
  164. package/src/__tests__/update-bulletin-format.test.ts +59 -0
  165. package/src/__tests__/update-bulletin.test.ts +206 -5
  166. package/src/__tests__/usage-routes.test.ts +25 -4
  167. package/src/__tests__/user-reference.test.ts +46 -61
  168. package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
  169. package/src/__tests__/voice-config-update.test.ts +403 -0
  170. package/src/__tests__/voice-quality.test.ts +434 -19
  171. package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
  172. package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
  173. package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
  174. package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
  175. package/src/__tests__/workspace-migration-meets.test.ts +244 -0
  176. package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
  177. package/src/__tests__/workspace-policy.test.ts +2 -0
  178. package/src/agent/image-optimize.ts +24 -12
  179. package/src/agent/loop.ts +43 -3
  180. package/src/backup/__tests__/backup-key.test.ts +152 -0
  181. package/src/backup/__tests__/backup-worker.test.ts +767 -0
  182. package/src/backup/__tests__/list-snapshots.test.ts +87 -0
  183. package/src/backup/__tests__/local-writer.test.ts +218 -0
  184. package/src/backup/__tests__/offsite-writer.test.ts +641 -0
  185. package/src/backup/__tests__/paths.test.ts +300 -0
  186. package/src/backup/__tests__/restore.test.ts +498 -0
  187. package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
  188. package/src/backup/__tests__/stream-crypt.test.ts +228 -0
  189. package/src/backup/backup-key.ts +137 -0
  190. package/src/backup/backup-worker.ts +459 -0
  191. package/src/backup/list-snapshots.ts +147 -0
  192. package/src/backup/local-writer.ts +133 -0
  193. package/src/backup/offsite-writer.ts +222 -0
  194. package/src/backup/paths.ts +226 -0
  195. package/src/backup/restore.ts +322 -0
  196. package/src/backup/snapshot-lock.ts +431 -0
  197. package/src/backup/stream-crypt.ts +263 -0
  198. package/src/bundler/package-resolver.ts +4 -0
  199. package/src/calls/audio-store.ts +11 -5
  200. package/src/calls/call-controller.ts +226 -71
  201. package/src/calls/call-domain.ts +9 -0
  202. package/src/calls/call-speech-output.ts +190 -0
  203. package/src/calls/call-transport.ts +77 -0
  204. package/src/calls/media-stream-audio-transcode.ts +173 -0
  205. package/src/calls/media-stream-output.ts +660 -0
  206. package/src/calls/media-stream-parser.ts +300 -0
  207. package/src/calls/media-stream-protocol.ts +166 -0
  208. package/src/calls/media-stream-server.ts +592 -0
  209. package/src/calls/media-stream-stt-session.ts +460 -0
  210. package/src/calls/media-turn-detector.ts +230 -0
  211. package/src/calls/relay-server.ts +90 -75
  212. package/src/calls/resolve-call-tts-provider.ts +136 -0
  213. package/src/calls/telephony-stt-routing.ts +145 -0
  214. package/src/calls/tts-call-strategy.ts +161 -0
  215. package/src/calls/tts-text-sanitizer.ts +32 -16
  216. package/src/calls/twilio-routes.ts +281 -17
  217. package/src/calls/voice-quality.ts +78 -35
  218. package/src/calls/voice-session-bridge.ts +8 -1
  219. package/src/channels/types.ts +16 -0
  220. package/src/cli/__tests__/run-assistant-command.ts +11 -1
  221. package/src/cli/commands/__tests__/backup.test.ts +1165 -0
  222. package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
  223. package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
  224. package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
  225. package/src/cli/commands/__tests__/email-download.test.ts +16 -1
  226. package/src/cli/commands/__tests__/email-list.test.ts +22 -4
  227. package/src/cli/commands/__tests__/email-register.test.ts +4 -4
  228. package/src/cli/commands/__tests__/email-send.test.ts +37 -4
  229. package/src/cli/commands/__tests__/email-status.test.ts +5 -1
  230. package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
  231. package/src/cli/commands/backup.ts +993 -0
  232. package/src/cli/commands/conversations.ts +77 -0
  233. package/src/cli/commands/credentials.ts +0 -1
  234. package/src/cli/commands/domain.ts +210 -0
  235. package/src/cli/commands/email.ts +255 -3
  236. package/src/cli/commands/oauth/__tests__/connect.test.ts +12 -0
  237. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +1 -0
  238. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -0
  239. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -0
  240. package/src/cli/commands/oauth/mode.ts +12 -3
  241. package/src/cli/commands/oauth/providers.ts +15 -0
  242. package/src/cli/commands/oauth/shared.ts +2 -1
  243. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +4 -9
  244. package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
  245. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  246. package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
  247. package/src/cli/program.ts +30 -4
  248. package/src/config/__tests__/backup-schema.test.ts +134 -0
  249. package/src/config/assistant-feature-flags.ts +61 -62
  250. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +37 -1
  251. package/src/config/bundled-skills/browser/SKILL.md +30 -5
  252. package/src/config/bundled-skills/browser/TOOLS.json +123 -0
  253. package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
  254. package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
  255. package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
  256. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +2 -2
  258. package/src/config/bundled-skills/gmail/SKILL.md +53 -7
  259. package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
  260. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
  261. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
  262. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
  263. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
  264. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
  265. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
  266. package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
  267. package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
  268. package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
  269. package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
  270. package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
  271. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
  272. package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
  273. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
  274. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  275. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
  276. package/src/config/bundled-skills/outlook/SKILL.md +2 -2
  277. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
  278. package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
  279. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
  280. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
  281. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  282. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
  283. package/src/config/bundled-skills/slack/SKILL.md +1 -0
  284. package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
  285. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
  286. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
  287. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
  288. package/src/config/bundled-tool-registry.ts +8 -0
  289. package/src/config/env-registry.ts +24 -0
  290. package/src/config/env.ts +34 -10
  291. package/src/config/feature-flag-registry.json +46 -14
  292. package/src/config/loader.ts +26 -12
  293. package/src/config/schema.ts +35 -10
  294. package/src/config/schemas/__tests__/stt.test.ts +43 -0
  295. package/src/config/schemas/analysis.ts +51 -0
  296. package/src/config/schemas/backup.ts +72 -0
  297. package/src/config/schemas/calls.ts +1 -26
  298. package/src/config/schemas/elevenlabs.ts +0 -59
  299. package/src/config/schemas/filing.ts +47 -7
  300. package/src/config/schemas/heartbeat.ts +27 -5
  301. package/src/config/schemas/host-browser.ts +47 -1
  302. package/src/config/schemas/inference.ts +1 -1
  303. package/src/config/schemas/memory-lifecycle.ts +14 -2
  304. package/src/config/schemas/services.ts +44 -0
  305. package/src/config/schemas/stt.ts +59 -0
  306. package/src/config/schemas/tts.ts +230 -0
  307. package/src/config/schemas/updates.ts +14 -0
  308. package/src/config/skills.ts +4 -0
  309. package/src/config/types.ts +4 -0
  310. package/src/contacts/contact-store.ts +56 -11
  311. package/src/contacts/contacts-write.ts +38 -1
  312. package/src/context/post-turn-tool-result-truncation.ts +3 -2
  313. package/src/context/tool-result-truncation.ts +2 -1
  314. package/src/context/window-manager.ts +45 -12
  315. package/src/credential-execution/executable-discovery.ts +12 -2
  316. package/src/credential-execution/process-manager.ts +33 -2
  317. package/src/credential-health/credential-health-service.ts +366 -0
  318. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
  319. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
  320. package/src/daemon/__tests__/conversation-tool-setup.test.ts +17 -8
  321. package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
  322. package/src/daemon/config-watcher.ts +99 -5
  323. package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
  324. package/src/daemon/conversation-agent-loop.ts +101 -24
  325. package/src/daemon/conversation-error.ts +11 -0
  326. package/src/daemon/conversation-history.ts +40 -6
  327. package/src/daemon/conversation-launch.ts +220 -0
  328. package/src/daemon/conversation-lifecycle.ts +59 -9
  329. package/src/daemon/conversation-messaging.ts +37 -3
  330. package/src/daemon/conversation-notifiers.ts +5 -0
  331. package/src/daemon/conversation-process.ts +581 -19
  332. package/src/daemon/conversation-queue-manager.ts +24 -0
  333. package/src/daemon/conversation-runtime-assembly.ts +11 -1
  334. package/src/daemon/conversation-slash.ts +36 -0
  335. package/src/daemon/conversation-surfaces.ts +94 -4
  336. package/src/daemon/conversation-tool-setup.ts +25 -0
  337. package/src/daemon/conversation-usage.ts +7 -4
  338. package/src/daemon/conversation.ts +86 -28
  339. package/src/daemon/handlers/config-slack-channel.ts +269 -94
  340. package/src/daemon/handlers/conversations.ts +4 -1
  341. package/src/daemon/handlers/shared.ts +22 -0
  342. package/src/daemon/handlers/skills.ts +321 -77
  343. package/src/daemon/host-browser-proxy.ts +2 -1
  344. package/src/daemon/lifecycle.ts +122 -25
  345. package/src/daemon/message-protocol.ts +6 -0
  346. package/src/daemon/message-types/conversations.ts +34 -1
  347. package/src/daemon/message-types/home.ts +40 -0
  348. package/src/daemon/message-types/meet.ts +143 -0
  349. package/src/daemon/message-types/messages.ts +14 -0
  350. package/src/daemon/message-types/schedules.ts +34 -2
  351. package/src/daemon/message-types/skills.ts +16 -0
  352. package/src/daemon/message-types/surfaces.ts +2 -0
  353. package/src/daemon/server.ts +347 -2
  354. package/src/daemon/shutdown-handlers.ts +32 -4
  355. package/src/daemon/shutdown-registry.ts +40 -0
  356. package/src/daemon/tool-side-effects.ts +9 -0
  357. package/src/email/html-renderer.ts +76 -0
  358. package/src/heartbeat/heartbeat-service.ts +93 -7
  359. package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
  360. package/src/home/__tests__/emit-feed-event.test.ts +169 -0
  361. package/src/home/__tests__/feed-scheduler.test.ts +194 -0
  362. package/src/home/__tests__/feed-types.test.ts +275 -0
  363. package/src/home/__tests__/feed-writer.test.ts +688 -0
  364. package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
  365. package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
  366. package/src/home/__tests__/progress-formula.test.ts +213 -0
  367. package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
  368. package/src/home/__tests__/rollup-producer.test.ts +398 -0
  369. package/src/home/assistant-feed-authoring.ts +124 -0
  370. package/src/home/emit-feed-event.ts +158 -0
  371. package/src/home/feed-scheduler.ts +247 -0
  372. package/src/home/feed-types.ts +181 -0
  373. package/src/home/feed-writer.ts +469 -0
  374. package/src/home/platform-gmail-digest.ts +163 -0
  375. package/src/home/progress-formula.ts +86 -0
  376. package/src/home/relationship-state-writer.ts +824 -0
  377. package/src/home/relationship-state.ts +143 -0
  378. package/src/home/rollup-producer.ts +384 -0
  379. package/src/hooks/runner.ts +7 -0
  380. package/src/inbound/platform-callback-registration.ts +12 -3
  381. package/src/inbound/public-ingress-urls.ts +12 -0
  382. package/src/instrument.ts +1 -1
  383. package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
  384. package/src/ipc/cli-client.ts +151 -0
  385. package/src/ipc/cli-server.ts +234 -0
  386. package/src/ipc/gateway-client.ts +180 -0
  387. package/src/ipc/routes/index.ts +5 -0
  388. package/src/ipc/routes/wake-conversation.ts +19 -0
  389. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
  390. package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
  391. package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
  392. package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
  393. package/src/memory/app-store.ts +1 -1
  394. package/src/memory/attachments-store.ts +70 -0
  395. package/src/memory/auto-analysis-enqueue.ts +127 -0
  396. package/src/memory/auto-analysis-guard.ts +27 -0
  397. package/src/memory/cleanup-schedule-state.ts +37 -0
  398. package/src/memory/conversation-analyze-job.ts +73 -0
  399. package/src/memory/conversation-crud.ts +99 -0
  400. package/src/memory/conversation-disk-view.ts +7 -0
  401. package/src/memory/conversation-group-migration.ts +34 -2
  402. package/src/memory/conversation-queries.ts +6 -5
  403. package/src/memory/db-init.ts +6 -0
  404. package/src/memory/db-maintenance.ts +108 -0
  405. package/src/memory/db.ts +1 -0
  406. package/src/memory/graph/conversation-graph-memory.ts +15 -0
  407. package/src/memory/graph/extraction.test.ts +23 -0
  408. package/src/memory/graph/extraction.ts +8 -0
  409. package/src/memory/graph/retriever.ts +27 -18
  410. package/src/memory/graph/scoring.test.ts +186 -0
  411. package/src/memory/graph/scoring.ts +31 -1
  412. package/src/memory/graph/tools.ts +1 -1
  413. package/src/memory/group-crud.ts +6 -1
  414. package/src/memory/indexer.ts +95 -16
  415. package/src/memory/job-handlers/cleanup.ts +11 -8
  416. package/src/memory/job-handlers/conversation-starters.ts +16 -10
  417. package/src/memory/jobs-store.ts +64 -4
  418. package/src/memory/jobs-worker.ts +22 -9
  419. package/src/memory/llm-usage-store.ts +92 -56
  420. package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
  421. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
  422. package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
  423. package/src/memory/migrations/index.ts +6 -0
  424. package/src/memory/migrations/registry.ts +8 -0
  425. package/src/memory/qdrant-manager.ts +43 -16
  426. package/src/memory/schema/conversations.ts +2 -0
  427. package/src/memory/schema/oauth.ts +3 -0
  428. package/src/memory/usage-buckets.ts +396 -0
  429. package/src/messaging/providers/gmail/client.ts +57 -6
  430. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
  431. package/src/messaging/providers/slack/adapter.ts +143 -38
  432. package/src/messaging/providers/slack/client.ts +16 -0
  433. package/src/messaging/providers/slack/types.ts +4 -0
  434. package/src/notifications/decision-engine.ts +3 -3
  435. package/src/notifications/signal.ts +5 -0
  436. package/src/oauth/__tests__/identity-verifier.test.ts +1 -0
  437. package/src/oauth/byo-connection.test.ts +18 -1
  438. package/src/oauth/byo-connection.ts +3 -1
  439. package/src/oauth/connect-orchestrator.ts +2 -0
  440. package/src/oauth/connection-resolver.ts +6 -2
  441. package/src/oauth/connection.ts +2 -0
  442. package/src/oauth/oauth-store.ts +9 -0
  443. package/src/oauth/platform-connection.test.ts +98 -0
  444. package/src/oauth/platform-connection.ts +52 -31
  445. package/src/oauth/seed-providers.ts +7 -0
  446. package/src/permissions/checker.ts +16 -6
  447. package/src/permissions/defaults.ts +49 -1
  448. package/src/permissions/trust-store.ts +3 -3
  449. package/src/permissions/workspace-policy.ts +3 -0
  450. package/src/platform/client.test.ts +10 -0
  451. package/src/platform/sync-identity.ts +129 -0
  452. package/src/prompts/persona-resolver.ts +126 -2
  453. package/src/prompts/system-prompt.ts +59 -18
  454. package/src/prompts/templates/BOOTSTRAP.md +5 -5
  455. package/src/prompts/templates/SOUL.md +3 -1
  456. package/src/prompts/templates/UPDATES.md +12 -0
  457. package/src/prompts/templates/channels/slack.md +20 -0
  458. package/src/prompts/update-bulletin-format.ts +26 -9
  459. package/src/prompts/update-bulletin.ts +34 -23
  460. package/src/prompts/user-reference.ts +20 -17
  461. package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
  462. package/src/providers/anthropic/client.ts +157 -61
  463. package/src/providers/fireworks/client.ts +2 -2
  464. package/src/providers/gemini/client.ts +9 -1
  465. package/src/providers/model-catalog.ts +6 -0
  466. package/src/providers/model-intents.ts +4 -4
  467. package/src/providers/ollama/client.ts +2 -2
  468. package/src/providers/openai/chat-completions-provider.ts +474 -0
  469. package/src/providers/openai/client.ts +25 -440
  470. package/src/providers/openai/responses-provider.ts +502 -0
  471. package/src/providers/openrouter/client.ts +101 -4
  472. package/src/providers/provider-secret-catalog.ts +139 -0
  473. package/src/providers/registry.ts +2 -2
  474. package/src/providers/retry.ts +14 -3
  475. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
  476. package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
  477. package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
  478. package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
  479. package/src/providers/speech-to-text/deepgram.test.ts +332 -0
  480. package/src/providers/speech-to-text/deepgram.ts +115 -0
  481. package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
  482. package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
  483. package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
  484. package/src/providers/speech-to-text/google-gemini.ts +101 -0
  485. package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
  486. package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
  487. package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
  488. package/src/providers/speech-to-text/openai-whisper.ts +63 -33
  489. package/src/providers/speech-to-text/provider-catalog.ts +306 -0
  490. package/src/providers/speech-to-text/resolve.ts +386 -6
  491. package/src/providers/types.ts +9 -0
  492. package/src/runtime/AGENTS.md +43 -1
  493. package/src/runtime/__tests__/agent-wake.test.ts +831 -0
  494. package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
  495. package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
  496. package/src/runtime/agent-wake.ts +512 -0
  497. package/src/runtime/auth/__tests__/route-policy.test.ts +40 -0
  498. package/src/runtime/auth/route-policy.ts +30 -5
  499. package/src/runtime/auth/token-service.ts +56 -1
  500. package/src/runtime/btw-sidechain.ts +2 -0
  501. package/src/runtime/capability-tokens.ts +10 -10
  502. package/src/runtime/channel-invite-transport.ts +1 -1
  503. package/src/runtime/channel-invite-transports/email.ts +14 -6
  504. package/src/runtime/channel-readiness-service.ts +12 -22
  505. package/src/runtime/chrome-extension-registry.ts +38 -2
  506. package/src/runtime/http-server.ts +395 -10
  507. package/src/runtime/http-types.ts +6 -2
  508. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +36 -0
  509. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
  510. package/src/runtime/migrations/migration-transport.ts +1 -0
  511. package/src/runtime/migrations/migration-wizard.ts +1 -0
  512. package/src/runtime/migrations/vbundle-import-analyzer.ts +77 -1
  513. package/src/runtime/migrations/vbundle-importer.ts +34 -0
  514. package/src/runtime/pending-interactions.ts +0 -11
  515. package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
  516. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
  517. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
  518. package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
  519. package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
  520. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
  521. package/src/runtime/routes/app-management-routes.ts +12 -18
  522. package/src/runtime/routes/attachment-routes.test.ts +9 -3
  523. package/src/runtime/routes/attachment-routes.ts +216 -17
  524. package/src/runtime/routes/backup-routes.ts +519 -0
  525. package/src/runtime/routes/browser-extension-pair-routes.ts +82 -23
  526. package/src/runtime/routes/btw-routes.ts +8 -6
  527. package/src/runtime/routes/contact-routes.test.ts +298 -0
  528. package/src/runtime/routes/contact-routes.ts +132 -5
  529. package/src/runtime/routes/conversation-analysis-routes.ts +22 -142
  530. package/src/runtime/routes/conversation-management-routes.ts +115 -0
  531. package/src/runtime/routes/conversation-routes.ts +367 -146
  532. package/src/runtime/routes/filing-routes.ts +93 -0
  533. package/src/runtime/routes/home-feed-routes.ts +334 -0
  534. package/src/runtime/routes/home-state-routes.ts +138 -0
  535. package/src/runtime/routes/host-browser-routes.ts +3 -14
  536. package/src/runtime/routes/identity-intro-cache.ts +7 -3
  537. package/src/runtime/routes/identity-routes.ts +3 -17
  538. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
  539. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
  540. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
  541. package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
  542. package/src/runtime/routes/integrations/slack/channel.ts +11 -3
  543. package/src/runtime/routes/integrations/slack/share.ts +45 -7
  544. package/src/runtime/routes/llm-context-normalization.ts +303 -0
  545. package/src/runtime/routes/memory-item-routes.test.ts +3 -2
  546. package/src/runtime/routes/migration-routes.ts +40 -5
  547. package/src/runtime/routes/settings-routes.ts +22 -5
  548. package/src/runtime/routes/skills-routes.ts +76 -7
  549. package/src/runtime/routes/stt-routes.ts +233 -0
  550. package/src/runtime/routes/surface-action-routes.ts +41 -2
  551. package/src/runtime/routes/tts-routes.ts +108 -24
  552. package/src/runtime/routes/usage-routes.ts +30 -2
  553. package/src/runtime/routes/user-route-dispatcher.ts +50 -5
  554. package/src/runtime/routes/user-routes.ts +13 -1
  555. package/src/runtime/routes/work-items-routes.ts +8 -1
  556. package/src/runtime/runtime-mode.ts +33 -0
  557. package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
  558. package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
  559. package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
  560. package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
  561. package/src/runtime/services/analyze-conversation.ts +344 -0
  562. package/src/runtime/services/analyze-deps-singleton.ts +32 -0
  563. package/src/runtime/services/auto-analysis-prompt.ts +55 -0
  564. package/src/runtime/skill-route-registry.ts +49 -0
  565. package/src/runtime/slack-block-formatting.ts +437 -10
  566. package/src/schedule/scheduler.ts +50 -0
  567. package/src/security/oauth2.ts +26 -4
  568. package/src/security/secure-keys.ts +25 -2
  569. package/src/security/token-manager.ts +8 -0
  570. package/src/sequence/engine.ts +23 -0
  571. package/src/sequence/types.ts +1 -1
  572. package/src/skills/catalog-files.ts +64 -2
  573. package/src/skills/category-inference.ts +122 -0
  574. package/src/skills/clawhub-files.ts +213 -0
  575. package/src/skills/clawhub.ts +84 -23
  576. package/src/skills/skill-file-provider.ts +40 -0
  577. package/src/skills/skillssh-files.ts +395 -0
  578. package/src/skills/skillssh-registry.ts +4 -4
  579. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
  580. package/src/stt/__tests__/types.test.ts +89 -0
  581. package/src/stt/daemon-batch-transcriber.ts +195 -0
  582. package/src/stt/stt-stream-session.ts +499 -0
  583. package/src/stt/types.ts +330 -0
  584. package/src/stt/wav-encoder.test.ts +373 -0
  585. package/src/stt/wav-encoder.ts +175 -0
  586. package/src/subagent/manager.ts +38 -14
  587. package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
  588. package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
  589. package/src/tools/browser/browser-execution.ts +1163 -23
  590. package/src/tools/browser/browser-manager.ts +45 -0
  591. package/src/tools/browser/browser-mode-constants.ts +12 -0
  592. package/src/tools/browser/browser-mode.ts +92 -0
  593. package/src/tools/browser/browser-status-constants.ts +33 -0
  594. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +393 -0
  595. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +29 -0
  596. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1648 -32
  597. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +264 -0
  598. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +183 -17
  599. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +254 -21
  600. package/src/tools/browser/cdp-client/errors.ts +15 -0
  601. package/src/tools/browser/cdp-client/extension-cdp-client.ts +39 -16
  602. package/src/tools/browser/cdp-client/factory.ts +797 -87
  603. package/src/tools/browser/cdp-client/index.ts +16 -2
  604. package/src/tools/browser/cdp-client/types.ts +68 -0
  605. package/src/tools/credentials/vault.ts +35 -6
  606. package/src/tools/network/web-fetch.ts +5 -2
  607. package/src/tools/network/web-search.ts +5 -2
  608. package/src/tools/shared/shell-output.ts +3 -1
  609. package/src/tools/side-effects.ts +2 -0
  610. package/src/tools/skills/sandbox-runner.ts +3 -2
  611. package/src/tools/terminal/safe-env.ts +10 -2
  612. package/src/tools/terminal/shell.ts +15 -4
  613. package/src/tools/tool-manifest.ts +21 -0
  614. package/src/tools/types.ts +17 -0
  615. package/src/tools/ui-surface/definitions.ts +6 -1
  616. package/src/tts/__tests__/provider-adapters.test.ts +834 -0
  617. package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
  618. package/src/tts/__tests__/provider-catalog.test.ts +183 -0
  619. package/src/tts/__tests__/provider-registry.test.ts +90 -0
  620. package/src/tts/provider-catalog.ts +201 -0
  621. package/src/tts/provider-registry.ts +73 -0
  622. package/src/tts/providers/deepgram-provider.ts +219 -0
  623. package/src/tts/providers/elevenlabs-provider.ts +211 -0
  624. package/src/tts/providers/fish-audio-provider.ts +183 -0
  625. package/src/tts/providers/index.ts +42 -0
  626. package/src/tts/providers/register-builtins.ts +130 -0
  627. package/src/tts/synthesize-text.ts +110 -0
  628. package/src/tts/tts-config-resolver.ts +78 -0
  629. package/src/tts/types.ts +153 -0
  630. package/src/types/onboarding-context.ts +7 -0
  631. package/src/util/abort-reasons.ts +58 -0
  632. package/src/util/device-id.ts +32 -16
  633. package/src/util/errors.ts +9 -1
  634. package/src/util/platform.ts +54 -10
  635. package/src/util/pricing.ts +66 -3
  636. package/src/util/spawn.ts +1 -1
  637. package/src/util/truncate.ts +4 -2
  638. package/src/util/unicode.ts +201 -0
  639. package/src/version.ts +19 -24
  640. package/src/watcher/engine.ts +23 -0
  641. package/src/watcher/watcher-store.ts +31 -0
  642. package/src/workspace/migrations/003-seed-device-id.ts +9 -3
  643. package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
  644. package/src/workspace/migrations/029-seed-pkb.ts +1 -1
  645. package/src/workspace/migrations/031-drop-user-md.ts +317 -0
  646. package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
  647. package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
  648. package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
  649. package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
  650. package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
  651. package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
  652. package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
  653. package/src/workspace/migrations/registry.ts +16 -0
  654. package/src/workspace/top-level-renderer.ts +13 -1
  655. package/src/workspace/turn-commit.ts +31 -0
  656. package/src/__tests__/email-cli.test.ts +0 -297
  657. package/src/__tests__/email-service-config-fallback.test.ts +0 -102
  658. package/src/cli/commands/browser-relay.ts +0 -466
  659. package/src/email/guardrails.ts +0 -221
  660. package/src/email/provider.ts +0 -117
  661. package/src/email/providers/agentmail.ts +0 -361
  662. package/src/email/providers/index.ts +0 -65
  663. package/src/email/service.ts +0 -384
  664. package/src/email/types.ts +0 -126
  665. package/src/prompts/templates/USER.md +0 -13
  666. package/src/providers/speech-to-text/types.ts +0 -17
  667. package/src/runtime/routes/browser-cdp-routes.ts +0 -229
@@ -89,7 +89,8 @@ function webSearchResultOnlyMessage(): Message[] {
89
89
  // Mock OpenAI SDK
90
90
  // ---------------------------------------------------------------------------
91
91
 
92
- let lastOpenAIParams: Record<string, unknown> | null = null;
92
+ let lastOpenAIResponsesParams: Record<string, unknown> | null = null;
93
+ let lastOpenAIChatParams: Record<string, unknown> | null = null;
93
94
 
94
95
  mock.module("openai", () => {
95
96
  class FakeAPIError extends Error {
@@ -110,7 +111,7 @@ mock.module("openai", () => {
110
111
  chat = {
111
112
  completions: {
112
113
  create: (params: Record<string, unknown>) => {
113
- lastOpenAIParams = JSON.parse(JSON.stringify(params));
114
+ lastOpenAIChatParams = JSON.parse(JSON.stringify(params));
114
115
  return (async function* () {
115
116
  yield {
116
117
  choices: [
@@ -126,6 +127,28 @@ mock.module("openai", () => {
126
127
  },
127
128
  },
128
129
  };
130
+ responses = {
131
+ stream: (params: Record<string, unknown>) => {
132
+ lastOpenAIResponsesParams = JSON.parse(JSON.stringify(params));
133
+ return (async function* () {
134
+ yield {
135
+ type: "response.output_text.delta",
136
+ delta: "OK",
137
+ };
138
+ yield {
139
+ type: "response.completed",
140
+ response: {
141
+ model: "gpt-4o",
142
+ status: "completed",
143
+ usage: {
144
+ input_tokens: 10,
145
+ output_tokens: 5,
146
+ },
147
+ },
148
+ };
149
+ })();
150
+ },
151
+ };
129
152
  },
130
153
  };
131
154
  });
@@ -172,60 +195,137 @@ mock.module("@google/genai", () => {
172
195
 
173
196
  // Import providers after mocking
174
197
  import { GeminiProvider } from "../providers/gemini/client.js";
175
- import { OpenAIProvider } from "../providers/openai/client.js";
198
+ import {
199
+ OpenAIChatCompletionsProvider,
200
+ OpenAIResponsesProvider,
201
+ } from "../providers/openai/client.js";
176
202
 
177
203
  // ---------------------------------------------------------------------------
178
- // OpenAI provider tests
204
+ // OpenAI Responses API provider tests
179
205
  // ---------------------------------------------------------------------------
180
206
 
181
- describe("Cross-Provider Web Search — OpenAI", () => {
207
+ describe("Cross-Provider Web Search — OpenAI (Responses API)", () => {
182
208
  beforeEach(() => {
183
- lastOpenAIParams = null;
209
+ lastOpenAIResponsesParams = null;
184
210
  });
185
211
 
186
- test("degrades server_tool_use in assistant message to text placeholder", async () => {
187
- const provider = new OpenAIProvider("sk-test", "gpt-4o");
212
+ test("degrades server_tool_use in assistant message to text placeholder in Responses input", async () => {
213
+ const provider = new OpenAIResponsesProvider("sk-test", "gpt-4o");
188
214
  await provider.sendMessage(webSearchConversation());
189
215
 
190
- const messages = lastOpenAIParams!.messages as Array<{
191
- role: string;
192
- content: unknown;
216
+ const input = lastOpenAIResponsesParams!.input as Array<{
217
+ type: string;
218
+ role?: string;
219
+ content?: Array<{ type: string; text?: string }>;
193
220
  }>;
194
221
 
195
- const assistantMsg = messages.find((m) => m.role === "assistant");
196
- expect(assistantMsg).toBeDefined();
197
- expect(assistantMsg!.content).toContain("[Web search: web_search]");
198
- expect(assistantMsg!.content).toContain("Here are the results.");
222
+ const assistantItems = input.filter(
223
+ (item) => item.type === "message" && item.role === "assistant",
224
+ );
225
+ const hasWebSearchPlaceholder = assistantItems.some((item) =>
226
+ item.content?.some(
227
+ (part) =>
228
+ part.type === "output_text" &&
229
+ part.text?.includes("[Web search: web_search]"),
230
+ ),
231
+ );
232
+ expect(hasWebSearchPlaceholder).toBe(true);
233
+
234
+ const hasResultsText = assistantItems.some((item) =>
235
+ item.content?.some(
236
+ (part) =>
237
+ part.type === "output_text" &&
238
+ part.text?.includes("Here are the results."),
239
+ ),
240
+ );
241
+ expect(hasResultsText).toBe(true);
199
242
  });
200
243
 
201
- test("degrades web_search_tool_result in user message to text placeholder", async () => {
202
- const provider = new OpenAIProvider("sk-test", "gpt-4o");
244
+ test("degrades web_search_tool_result in user message to text placeholder in Responses input", async () => {
245
+ const provider = new OpenAIResponsesProvider("sk-test", "gpt-4o");
203
246
  await provider.sendMessage(webSearchConversation());
204
247
 
205
- const messages = lastOpenAIParams!.messages as Array<{
206
- role: string;
207
- content: unknown;
248
+ const input = lastOpenAIResponsesParams!.input as Array<{
249
+ type: string;
250
+ role?: string;
251
+ content?: Array<{ type: string; text?: string }>;
208
252
  }>;
209
253
 
210
- const userMsgs = messages.filter((m) => m.role === "user");
211
- const hasWebSearchResult = userMsgs.some((m) => {
212
- if (typeof m.content === "string") return false;
213
- if (Array.isArray(m.content)) {
214
- return (m.content as Array<{ type: string; text?: string }>).some(
215
- (part) =>
216
- part.type === "text" && part.text === "[Web search results]",
217
- );
218
- }
219
- return false;
220
- });
254
+ const userItems = input.filter(
255
+ (item) => item.type === "message" && item.role === "user",
256
+ );
257
+ const hasWebSearchResult = userItems.some((item) =>
258
+ item.content?.some(
259
+ (part) =>
260
+ part.type === "input_text" && part.text === "[Web search results]",
261
+ ),
262
+ );
221
263
  expect(hasWebSearchResult).toBe(true);
222
264
  });
223
265
 
224
266
  test("handles message containing only web_search_tool_result", async () => {
225
- const provider = new OpenAIProvider("sk-test", "gpt-4o");
267
+ const provider = new OpenAIResponsesProvider("sk-test", "gpt-4o");
226
268
  await provider.sendMessage(webSearchResultOnlyMessage());
227
269
 
228
- const messages = lastOpenAIParams!.messages as Array<{
270
+ const input = lastOpenAIResponsesParams!.input as Array<{
271
+ type: string;
272
+ role?: string;
273
+ content?: Array<{ type: string; text?: string }>;
274
+ }>;
275
+
276
+ const assistantItems = input.filter(
277
+ (item) => item.type === "message" && item.role === "assistant",
278
+ );
279
+ const hasWebSearchPlaceholder = assistantItems.some((item) =>
280
+ item.content?.some(
281
+ (part) =>
282
+ part.type === "output_text" &&
283
+ part.text?.includes("[Web search: web_search]"),
284
+ ),
285
+ );
286
+ expect(hasWebSearchPlaceholder).toBe(true);
287
+
288
+ const userItems = input.filter(
289
+ (item) => item.type === "message" && item.role === "user",
290
+ );
291
+ const hasWebSearchResult = userItems.some((item) =>
292
+ item.content?.some(
293
+ (part) =>
294
+ part.type === "input_text" && part.text === "[Web search results]",
295
+ ),
296
+ );
297
+ expect(hasWebSearchResult).toBe(true);
298
+ });
299
+
300
+ test("does not produce function_call items for server_tool_use blocks", async () => {
301
+ const provider = new OpenAIResponsesProvider("sk-test", "gpt-4o");
302
+ await provider.sendMessage(webSearchConversation());
303
+
304
+ const input = lastOpenAIResponsesParams!.input as Array<{
305
+ type: string;
306
+ }>;
307
+
308
+ const functionCallItems = input.filter(
309
+ (item) => item.type === "function_call",
310
+ );
311
+ expect(functionCallItems).toHaveLength(0);
312
+ });
313
+ });
314
+
315
+ // ---------------------------------------------------------------------------
316
+ // OpenAI Chat Completions compatibility provider tests
317
+ // ---------------------------------------------------------------------------
318
+
319
+ describe("Cross-Provider Web Search — OpenAI Chat Completions (compatibility)", () => {
320
+ beforeEach(() => {
321
+ lastOpenAIChatParams = null;
322
+ });
323
+
324
+ test("degrades server_tool_use in assistant message to text placeholder", async () => {
325
+ const provider = new OpenAIChatCompletionsProvider("sk-test", "gpt-4o");
326
+ await provider.sendMessage(webSearchConversation());
327
+
328
+ const messages = lastOpenAIChatParams!.messages as Array<{
229
329
  role: string;
230
330
  content: unknown;
231
331
  }>;
@@ -233,6 +333,17 @@ describe("Cross-Provider Web Search — OpenAI", () => {
233
333
  const assistantMsg = messages.find((m) => m.role === "assistant");
234
334
  expect(assistantMsg).toBeDefined();
235
335
  expect(assistantMsg!.content).toContain("[Web search: web_search]");
336
+ expect(assistantMsg!.content).toContain("Here are the results.");
337
+ });
338
+
339
+ test("degrades web_search_tool_result in user message to text placeholder", async () => {
340
+ const provider = new OpenAIChatCompletionsProvider("sk-test", "gpt-4o");
341
+ await provider.sendMessage(webSearchConversation());
342
+
343
+ const messages = lastOpenAIChatParams!.messages as Array<{
344
+ role: string;
345
+ content: unknown;
346
+ }>;
236
347
 
237
348
  const userMsgs = messages.filter((m) => m.role === "user");
238
349
  const hasWebSearchResult = userMsgs.some((m) => {
@@ -249,10 +360,10 @@ describe("Cross-Provider Web Search — OpenAI", () => {
249
360
  });
250
361
 
251
362
  test("does not produce tool_calls for server_tool_use blocks", async () => {
252
- const provider = new OpenAIProvider("sk-test", "gpt-4o");
363
+ const provider = new OpenAIChatCompletionsProvider("sk-test", "gpt-4o");
253
364
  await provider.sendMessage(webSearchConversation());
254
365
 
255
- const messages = lastOpenAIParams!.messages as Array<{
366
+ const messages = lastOpenAIChatParams!.messages as Array<{
256
367
  role: string;
257
368
  tool_calls?: unknown[];
258
369
  }>;
@@ -31,6 +31,7 @@ mock.module("../config/env.js", () => ({
31
31
  // Imports (after mocks)
32
32
  // ---------------------------------------------------------------------------
33
33
 
34
+ import type { TwilioRelaySpeechConfig } from "../calls/twilio-routes.js";
34
35
  import { generateTwiML } from "../calls/twilio-routes.js";
35
36
  import { initializeDb } from "../memory/db-init.js";
36
37
  import {
@@ -100,9 +101,14 @@ describe("Channel verification reply templates", () => {
100
101
  describe("TwiML parameter propagation", () => {
101
102
  const defaultProfile = {
102
103
  language: "en-US",
103
- transcriptionProvider: "deepgram",
104
104
  ttsProvider: "google",
105
105
  voice: "en-US-Standard-A",
106
+ };
107
+
108
+ const defaultSpeechConfig: TwilioRelaySpeechConfig = {
109
+ transcriptionProvider: "deepgram",
110
+ speechModel: undefined,
111
+ hints: undefined,
106
112
  interruptSensitivity: "low",
107
113
  };
108
114
 
@@ -112,6 +118,7 @@ describe("TwiML parameter propagation", () => {
112
118
  "wss://example.com/v1/calls/relay",
113
119
  null,
114
120
  defaultProfile,
121
+ defaultSpeechConfig,
115
122
  undefined,
116
123
  { verificationSessionId: "gv-session-456" },
117
124
  );
@@ -126,6 +133,7 @@ describe("TwiML parameter propagation", () => {
126
133
  "wss://example.com/v1/calls/relay",
127
134
  null,
128
135
  defaultProfile,
136
+ defaultSpeechConfig,
129
137
  );
130
138
  expect(twiml).not.toContain("<Parameter");
131
139
  });
@@ -136,6 +144,7 @@ describe("TwiML parameter propagation", () => {
136
144
  "wss://example.com/v1/calls/relay",
137
145
  null,
138
146
  defaultProfile,
147
+ defaultSpeechConfig,
139
148
  "token123",
140
149
  undefined,
141
150
  );
@@ -0,0 +1,112 @@
1
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
5
+
6
+ // Suppress logger output before importing the module under test.
7
+ mock.module("../util/logger.js", () => ({
8
+ getLogger: () =>
9
+ new Proxy({} as Record<string, unknown>, {
10
+ get: () => () => {},
11
+ }),
12
+ }));
13
+
14
+ import { getDeviceId, resetDeviceIdCache } from "../util/device-id.js";
15
+
16
+ const originalVellumEnvironment = process.env.VELLUM_ENVIRONMENT;
17
+ const originalXdgConfigHome = process.env.XDG_CONFIG_HOME;
18
+ const originalIsContainerized = process.env.IS_CONTAINERIZED;
19
+
20
+ let tempDir: string;
21
+
22
+ beforeEach(() => {
23
+ tempDir = mkdtempSync(join(tmpdir(), "vellum-device-id-test-"));
24
+ resetDeviceIdCache();
25
+ });
26
+
27
+ afterEach(() => {
28
+ resetDeviceIdCache();
29
+
30
+ if (originalVellumEnvironment == null) {
31
+ delete process.env.VELLUM_ENVIRONMENT;
32
+ } else {
33
+ process.env.VELLUM_ENVIRONMENT = originalVellumEnvironment;
34
+ }
35
+ if (originalXdgConfigHome == null) {
36
+ delete process.env.XDG_CONFIG_HOME;
37
+ } else {
38
+ process.env.XDG_CONFIG_HOME = originalXdgConfigHome;
39
+ }
40
+ if (originalIsContainerized == null) {
41
+ delete process.env.IS_CONTAINERIZED;
42
+ } else {
43
+ process.env.IS_CONTAINERIZED = originalIsContainerized;
44
+ }
45
+
46
+ try {
47
+ rmSync(tempDir, { recursive: true, force: true });
48
+ } catch {
49
+ /* best-effort */
50
+ }
51
+ });
52
+
53
+ describe("getDeviceId env-awareness", () => {
54
+ test("non-prod (dev) writes device.json under $XDG_CONFIG_HOME/vellum-dev", () => {
55
+ // Guarantee we're not containerized — the test-preload deletes this,
56
+ // but be defensive.
57
+ delete process.env.IS_CONTAINERIZED;
58
+ process.env.VELLUM_ENVIRONMENT = "dev";
59
+ process.env.XDG_CONFIG_HOME = tempDir;
60
+
61
+ const id = getDeviceId();
62
+ expect(typeof id).toBe("string");
63
+ expect(id.length).toBeGreaterThan(0);
64
+
65
+ const expectedPath = join(tempDir, "vellum-dev", "device.json");
66
+ expect(existsSync(expectedPath)).toBe(true);
67
+
68
+ const parsed = JSON.parse(readFileSync(expectedPath, "utf-8"));
69
+ expect(parsed.deviceId).toBe(id);
70
+ });
71
+
72
+ test("staging environment writes under $XDG_CONFIG_HOME/vellum-staging", () => {
73
+ delete process.env.IS_CONTAINERIZED;
74
+ process.env.VELLUM_ENVIRONMENT = "staging";
75
+ process.env.XDG_CONFIG_HOME = tempDir;
76
+
77
+ getDeviceId();
78
+
79
+ const expectedPath = join(tempDir, "vellum-staging", "device.json");
80
+ expect(existsSync(expectedPath)).toBe(true);
81
+ });
82
+
83
+ test("unknown environment does NOT write under $XDG_CONFIG_HOME/vellum-<unknown>", () => {
84
+ // Unknown env names fall back to the legacy production behavior.
85
+ // We can't assert the exact legacy path without mocking homedir(),
86
+ // but we can assert that the XDG env-scoped dir is NOT created.
87
+ delete process.env.IS_CONTAINERIZED;
88
+ process.env.VELLUM_ENVIRONMENT = "no-such-env";
89
+ process.env.XDG_CONFIG_HOME = tempDir;
90
+
91
+ getDeviceId();
92
+
93
+ // No `vellum-no-such-env` directory created under our XDG tempdir.
94
+ const envScopedPath = join(tempDir, "vellum-no-such-env", "device.json");
95
+ expect(existsSync(envScopedPath)).toBe(false);
96
+ // Legacy fallback would write under `${homedir()}/.vellum` — not touched.
97
+ const productionXdgPath = join(tempDir, "vellum", "device.json");
98
+ expect(existsSync(productionXdgPath)).toBe(false);
99
+ });
100
+
101
+ test("production does NOT write under $XDG_CONFIG_HOME/vellum", () => {
102
+ // Production path is ~/.vellum/device.json, never XDG_CONFIG_HOME.
103
+ delete process.env.IS_CONTAINERIZED;
104
+ delete process.env.VELLUM_ENVIRONMENT;
105
+ process.env.XDG_CONFIG_HOME = tempDir;
106
+
107
+ getDeviceId();
108
+
109
+ const xdgPath = join(tempDir, "vellum", "device.json");
110
+ expect(existsSync(xdgPath)).toBe(false);
111
+ });
112
+ });
@@ -1,9 +1,17 @@
1
1
  /**
2
- * Tests for resolveSigningKey() covering env var injection (Docker)
3
- * and file-based load/create (local mode).
2
+ * Tests for resolveSigningKey() covering env var injection (Docker),
3
+ * file-based load/create (local mode), and env-to-disk sync for CLI
4
+ * signing-key convergence.
4
5
  */
5
6
 
6
- import { existsSync, rmSync } from "node:fs";
7
+ import {
8
+ existsSync,
9
+ mkdirSync,
10
+ readFileSync,
11
+ rmSync,
12
+ writeFileSync,
13
+ } from "node:fs";
14
+ import { dirname, join } from "node:path";
7
15
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
8
16
 
9
17
  mock.module("../util/logger.js", () => ({
@@ -13,7 +21,15 @@ mock.module("../util/logger.js", () => ({
13
21
  }),
14
22
  }));
15
23
 
16
- const { resolveSigningKey } = await import("../runtime/auth/token-service.js");
24
+ const {
25
+ resolveSigningKey,
26
+ initAuthSigningKey,
27
+ loadSigningKey,
28
+ mintToken,
29
+ verifyToken,
30
+ _resetSigningKeyForTesting,
31
+ } = await import("../runtime/auth/token-service.js");
32
+ const { CURRENT_POLICY_EPOCH } = await import("../runtime/auth/policy.js");
17
33
  const { getDeprecatedDir } = await import("../util/platform.js");
18
34
 
19
35
  const VALID_HEX_KEY = "ab".repeat(32); // 64 hex chars = 32 bytes
@@ -22,6 +38,7 @@ const savedEnv: Record<string, string | undefined> = {};
22
38
 
23
39
  beforeEach(() => {
24
40
  savedEnv.ACTOR_TOKEN_SIGNING_KEY = process.env.ACTOR_TOKEN_SIGNING_KEY;
41
+ savedEnv.IS_CONTAINERIZED = process.env.IS_CONTAINERIZED;
25
42
  // Clean up key files from previous tests so they don't leak between cases.
26
43
  const deprecatedDir = getDeprecatedDir();
27
44
  if (existsSync(deprecatedDir))
@@ -34,6 +51,13 @@ afterEach(() => {
34
51
  } else {
35
52
  process.env.ACTOR_TOKEN_SIGNING_KEY = savedEnv.ACTOR_TOKEN_SIGNING_KEY;
36
53
  }
54
+ if (savedEnv.IS_CONTAINERIZED === undefined) {
55
+ delete process.env.IS_CONTAINERIZED;
56
+ } else {
57
+ process.env.IS_CONTAINERIZED = savedEnv.IS_CONTAINERIZED;
58
+ }
59
+ // Reset signing key so interop tests don't leak state
60
+ _resetSigningKeyForTesting();
37
61
  });
38
62
 
39
63
  describe("resolveSigningKey", () => {
@@ -76,3 +100,142 @@ describe("resolveSigningKey", () => {
76
100
  expect(key2.toString("hex")).not.toBe(key1.toString("hex"));
77
101
  });
78
102
  });
103
+
104
+ // ---------------------------------------------------------------------------
105
+ // Env-to-disk signing key sync
106
+ // ---------------------------------------------------------------------------
107
+
108
+ describe("env-to-disk signing key sync", () => {
109
+ test("env key syncs to canonical disk path in non-containerized mode", () => {
110
+ delete process.env.IS_CONTAINERIZED;
111
+ process.env.ACTOR_TOKEN_SIGNING_KEY = VALID_HEX_KEY;
112
+
113
+ const key = resolveSigningKey();
114
+
115
+ expect(key.toString("hex")).toBe(VALID_HEX_KEY);
116
+
117
+ const keyPath = join(getDeprecatedDir(), "actor-token-signing-key");
118
+ expect(existsSync(keyPath)).toBe(true);
119
+ const diskKey = readFileSync(keyPath);
120
+ expect(diskKey.length).toBe(32);
121
+ expect(diskKey.toString("hex")).toBe(VALID_HEX_KEY);
122
+ });
123
+
124
+ test("env key does NOT sync to disk in containerized mode", () => {
125
+ process.env.IS_CONTAINERIZED = "true";
126
+ process.env.ACTOR_TOKEN_SIGNING_KEY = VALID_HEX_KEY;
127
+
128
+ const key = resolveSigningKey();
129
+
130
+ expect(key.toString("hex")).toBe(VALID_HEX_KEY);
131
+
132
+ const keyPath = join(getDeprecatedDir(), "actor-token-signing-key");
133
+ expect(existsSync(keyPath)).toBe(false);
134
+ });
135
+
136
+ test("mismatched disk key is updated to env key in non-containerized mode", () => {
137
+ delete process.env.IS_CONTAINERIZED;
138
+
139
+ // Write a mismatched key to disk first
140
+ const keyPath = join(getDeprecatedDir(), "actor-token-signing-key");
141
+ const dir = dirname(keyPath);
142
+ if (!existsSync(dir)) {
143
+ mkdirSync(dir, { recursive: true });
144
+ }
145
+ const mismatchedKey = Buffer.from("ff".repeat(32), "hex");
146
+ writeFileSync(keyPath, mismatchedKey, { mode: 0o600 });
147
+
148
+ // Set a different env key
149
+ process.env.ACTOR_TOKEN_SIGNING_KEY = VALID_HEX_KEY;
150
+
151
+ const key = resolveSigningKey();
152
+ expect(key.toString("hex")).toBe(VALID_HEX_KEY);
153
+
154
+ // Disk key should now match env key
155
+ const diskKey = readFileSync(keyPath);
156
+ expect(diskKey.toString("hex")).toBe(VALID_HEX_KEY);
157
+ });
158
+
159
+ test("matching disk key is not rewritten (no-op)", () => {
160
+ delete process.env.IS_CONTAINERIZED;
161
+ process.env.ACTOR_TOKEN_SIGNING_KEY = VALID_HEX_KEY;
162
+
163
+ // First call writes the key
164
+ resolveSigningKey();
165
+ const keyPath = join(getDeprecatedDir(), "actor-token-signing-key");
166
+ expect(existsSync(keyPath)).toBe(true);
167
+
168
+ // Second call with same key should not throw or fail
169
+ const key2 = resolveSigningKey();
170
+ expect(key2.toString("hex")).toBe(VALID_HEX_KEY);
171
+
172
+ const diskKey = readFileSync(keyPath);
173
+ expect(diskKey.toString("hex")).toBe(VALID_HEX_KEY);
174
+ });
175
+ });
176
+
177
+ // ---------------------------------------------------------------------------
178
+ // Signature interoperability between daemon (env key) and CLI (disk key)
179
+ // ---------------------------------------------------------------------------
180
+
181
+ describe("daemon/CLI signing key interoperability", () => {
182
+ test("token minted via CLI disk-load path verifies with daemon env key after sync", () => {
183
+ delete process.env.IS_CONTAINERIZED;
184
+
185
+ // Pre-seed a mismatched "legacy" disk key to simulate the pre-fix state
186
+ const keyPath = join(getDeprecatedDir(), "actor-token-signing-key");
187
+ const dir = dirname(keyPath);
188
+ if (!existsSync(dir)) {
189
+ mkdirSync(dir, { recursive: true });
190
+ }
191
+ const legacyKey = Buffer.from("ee".repeat(32), "hex");
192
+ writeFileSync(keyPath, legacyKey, { mode: 0o600 });
193
+
194
+ // --- Daemon startup path ---
195
+ // Set the env key and call resolveSigningKey (daemon behavior).
196
+ // This syncs the env key to disk.
197
+ process.env.ACTOR_TOKEN_SIGNING_KEY = VALID_HEX_KEY;
198
+ const daemonKey = resolveSigningKey();
199
+ initAuthSigningKey(daemonKey);
200
+
201
+ // Mint a token using the daemon's key
202
+ const daemonToken = mintToken({
203
+ aud: "vellum-daemon",
204
+ sub: "svc:daemon:self",
205
+ scope_profile: "gateway_service_v1",
206
+ policy_epoch: CURRENT_POLICY_EPOCH,
207
+ ttlSeconds: 60,
208
+ });
209
+
210
+ // --- CLI subprocess path ---
211
+ // Reset signing key to simulate a fresh CLI subprocess context
212
+ _resetSigningKeyForTesting();
213
+
214
+ // CLI loads key from disk (post-sync, disk now matches env key)
215
+ const cliDiskKey = loadSigningKey();
216
+ expect(cliDiskKey).toBeDefined();
217
+ initAuthSigningKey(cliDiskKey!);
218
+
219
+ // Mint a token using the CLI's disk-loaded key
220
+ const cliToken = mintToken({
221
+ aud: "vellum-daemon",
222
+ sub: "svc:daemon:self",
223
+ scope_profile: "gateway_service_v1",
224
+ policy_epoch: CURRENT_POLICY_EPOCH,
225
+ ttlSeconds: 60,
226
+ });
227
+
228
+ // --- Cross-verification ---
229
+ // CLI-minted token must verify with daemon key
230
+ _resetSigningKeyForTesting();
231
+ initAuthSigningKey(daemonKey);
232
+ const cliResult = verifyToken(cliToken, "vellum-daemon");
233
+ expect(cliResult.ok).toBe(true);
234
+
235
+ // Daemon-minted token must verify with CLI disk key
236
+ _resetSigningKeyForTesting();
237
+ initAuthSigningKey(cliDiskKey!);
238
+ const daemonResult = verifyToken(daemonToken, "vellum-daemon");
239
+ expect(daemonResult.ok).toBe(true);
240
+ });
241
+ });
@@ -83,15 +83,13 @@ describe("Dynamic Skill Authoring Workflow moved to tool descriptions", () => {
83
83
  expect(result).not.toContain("**test-skill**");
84
84
  });
85
85
 
86
- test("prompt is additive with IDENTITY/SOUL/USER files", () => {
86
+ test("prompt is additive with IDENTITY/SOUL files", () => {
87
87
  writeFileSync(join(TEST_DIR, "IDENTITY.md"), "Identity here");
88
88
  writeFileSync(join(TEST_DIR, "SOUL.md"), "Soul here");
89
- writeFileSync(join(TEST_DIR, "USER.md"), "User here");
90
89
 
91
90
  const result = buildSystemPrompt();
92
91
  expect(result).toContain("Identity here");
93
92
  expect(result).toContain("Soul here");
94
- expect(result).toContain("User here");
95
93
  });
96
94
 
97
95
  test("browser skill activation hints no longer appear in system prompt", () => {