@vellumai/assistant 0.4.17 → 0.4.19

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 (528) hide show
  1. package/docs/runbook-trusted-contacts.md +5 -3
  2. package/eslint.config.mjs +2 -2
  3. package/package.json +1 -1
  4. package/src/__tests__/access-request-decision.test.ts +128 -120
  5. package/src/__tests__/account-registry.test.ts +121 -110
  6. package/src/__tests__/active-skill-tools.test.ts +200 -172
  7. package/src/__tests__/actor-token-service.test.ts +341 -274
  8. package/src/__tests__/agent-loop-thinking.test.ts +28 -19
  9. package/src/__tests__/agent-loop.test.ts +798 -378
  10. package/src/__tests__/anthropic-provider.test.ts +405 -247
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
  12. package/src/__tests__/app-bundler.test.ts +112 -79
  13. package/src/__tests__/app-executors.test.ts +205 -178
  14. package/src/__tests__/app-git-history.test.ts +90 -73
  15. package/src/__tests__/app-git-service.test.ts +67 -53
  16. package/src/__tests__/app-open-proxy.test.ts +29 -25
  17. package/src/__tests__/approval-conversation-turn.test.ts +100 -81
  18. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
  19. package/src/__tests__/approval-message-composer.test.ts +119 -119
  20. package/src/__tests__/approval-primitive.test.ts +264 -233
  21. package/src/__tests__/approval-routes-http.test.ts +4 -3
  22. package/src/__tests__/asset-materialize-tool.test.ts +250 -178
  23. package/src/__tests__/asset-search-tool.test.ts +251 -191
  24. package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
  25. package/src/__tests__/assistant-attachments.test.ts +254 -186
  26. package/src/__tests__/assistant-event-hub.test.ts +105 -63
  27. package/src/__tests__/assistant-event.test.ts +66 -58
  28. package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
  29. package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
  30. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
  32. package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
  33. package/src/__tests__/attachments-store.test.ts +240 -183
  34. package/src/__tests__/attachments.test.ts +70 -62
  35. package/src/__tests__/audit-log-rotation.test.ts +50 -35
  36. package/src/__tests__/browser-fill-credential.test.ts +169 -101
  37. package/src/__tests__/browser-manager.test.ts +97 -75
  38. package/src/__tests__/browser-runtime-check.test.ts +16 -15
  39. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
  40. package/src/__tests__/browser-skill-endstate.test.ts +97 -72
  41. package/src/__tests__/bundle-scanner.test.ts +47 -22
  42. package/src/__tests__/bundled-asset.test.ts +74 -47
  43. package/src/__tests__/call-constants.test.ts +19 -19
  44. package/src/__tests__/call-controller.test.ts +0 -1
  45. package/src/__tests__/call-conversation-messages.test.ts +90 -65
  46. package/src/__tests__/call-domain.test.ts +149 -121
  47. package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
  48. package/src/__tests__/call-pointer-messages.test.ts +213 -154
  49. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
  50. package/src/__tests__/call-recovery.test.ts +232 -212
  51. package/src/__tests__/call-routes-http.test.ts +0 -1
  52. package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
  53. package/src/__tests__/call-state-machine.test.ts +62 -51
  54. package/src/__tests__/call-state.test.ts +89 -75
  55. package/src/__tests__/call-store.test.ts +387 -316
  56. package/src/__tests__/callback-handoff-copy.test.ts +84 -82
  57. package/src/__tests__/canonical-guardian-store.test.ts +331 -280
  58. package/src/__tests__/channel-approval-routes.test.ts +1643 -1115
  59. package/src/__tests__/channel-approval.test.ts +139 -137
  60. package/src/__tests__/channel-approvals.test.ts +7 -2
  61. package/src/__tests__/channel-delivery-store.test.ts +232 -194
  62. package/src/__tests__/channel-guardian.test.ts +5 -3
  63. package/src/__tests__/channel-invite-transport.test.ts +107 -92
  64. package/src/__tests__/channel-policy.test.ts +42 -38
  65. package/src/__tests__/channel-readiness-service.test.ts +119 -102
  66. package/src/__tests__/channel-reply-delivery.test.ts +147 -118
  67. package/src/__tests__/channel-retry-sweep.test.ts +153 -110
  68. package/src/__tests__/checker.test.ts +3309 -1850
  69. package/src/__tests__/clarification-resolver.test.ts +91 -79
  70. package/src/__tests__/classifier.test.ts +64 -54
  71. package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
  72. package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
  73. package/src/__tests__/clawhub.test.ts +92 -82
  74. package/src/__tests__/cli.test.ts +30 -30
  75. package/src/__tests__/clipboard.test.ts +53 -46
  76. package/src/__tests__/commit-guarantee.test.ts +59 -52
  77. package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
  78. package/src/__tests__/compaction.benchmark.test.ts +33 -31
  79. package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
  80. package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
  81. package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
  82. package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
  83. package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
  84. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
  85. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
  86. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
  87. package/src/__tests__/computer-use-tools.test.ts +121 -98
  88. package/src/__tests__/config-schema.test.ts +443 -347
  89. package/src/__tests__/config-watcher.test.ts +96 -81
  90. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
  91. package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
  92. package/src/__tests__/conflict-policy.test.ts +151 -80
  93. package/src/__tests__/conflict-store.test.ts +203 -157
  94. package/src/__tests__/connection-policy.test.ts +89 -59
  95. package/src/__tests__/contacts-tools.test.ts +247 -178
  96. package/src/__tests__/context-memory-e2e.test.ts +306 -214
  97. package/src/__tests__/context-token-estimator.test.ts +114 -74
  98. package/src/__tests__/context-window-manager.test.ts +269 -167
  99. package/src/__tests__/contradiction-checker.test.ts +161 -135
  100. package/src/__tests__/conversation-attention-store.test.ts +350 -290
  101. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  102. package/src/__tests__/conversation-pairing.test.ts +220 -113
  103. package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
  104. package/src/__tests__/conversation-store.test.ts +390 -235
  105. package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
  106. package/src/__tests__/credential-broker-server-use.test.ts +283 -243
  107. package/src/__tests__/credential-broker.test.ts +128 -74
  108. package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
  109. package/src/__tests__/credential-metadata-store.test.ts +360 -311
  110. package/src/__tests__/credential-policy-validate.test.ts +81 -65
  111. package/src/__tests__/credential-resolve.test.ts +212 -145
  112. package/src/__tests__/credential-security-e2e.test.ts +144 -103
  113. package/src/__tests__/credential-security-invariants.test.ts +253 -208
  114. package/src/__tests__/credential-selection.test.ts +254 -146
  115. package/src/__tests__/credential-vault-unit.test.ts +531 -341
  116. package/src/__tests__/credential-vault.test.ts +761 -484
  117. package/src/__tests__/daemon-assistant-events.test.ts +91 -66
  118. package/src/__tests__/daemon-lifecycle.test.ts +258 -190
  119. package/src/__tests__/daemon-server-session-init.test.ts +2 -1
  120. package/src/__tests__/date-context.test.ts +314 -249
  121. package/src/__tests__/db-migration-rollback.test.ts +259 -130
  122. package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
  123. package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
  124. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  125. package/src/__tests__/dictation-mode-detection.test.ts +77 -55
  126. package/src/__tests__/dictation-profile-store.test.ts +70 -56
  127. package/src/__tests__/dictation-text-processing.test.ts +53 -35
  128. package/src/__tests__/diff.test.ts +102 -98
  129. package/src/__tests__/domain-normalize.test.ts +54 -54
  130. package/src/__tests__/domain-policy.test.ts +71 -55
  131. package/src/__tests__/dynamic-page-surface.test.ts +31 -33
  132. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
  133. package/src/__tests__/edit-engine.test.ts +56 -56
  134. package/src/__tests__/elevenlabs-client.test.ts +117 -91
  135. package/src/__tests__/elevenlabs-config.test.ts +32 -31
  136. package/src/__tests__/email-classifier.test.ts +15 -12
  137. package/src/__tests__/email-cli.test.ts +121 -108
  138. package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
  139. package/src/__tests__/encrypted-store.test.ts +180 -154
  140. package/src/__tests__/entity-extractor.test.ts +108 -87
  141. package/src/__tests__/entity-search.test.ts +664 -258
  142. package/src/__tests__/ephemeral-permissions.test.ts +224 -188
  143. package/src/__tests__/event-bus.test.ts +81 -77
  144. package/src/__tests__/extract-email.test.ts +29 -20
  145. package/src/__tests__/file-edit-tool.test.ts +62 -44
  146. package/src/__tests__/file-ops-service.test.ts +131 -114
  147. package/src/__tests__/file-read-tool.test.ts +48 -31
  148. package/src/__tests__/file-write-tool.test.ts +43 -37
  149. package/src/__tests__/filesystem-tools.test.ts +238 -209
  150. package/src/__tests__/followup-tools.test.ts +237 -162
  151. package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
  152. package/src/__tests__/frontmatter.test.ts +96 -81
  153. package/src/__tests__/fuzzy-match-property.test.ts +75 -81
  154. package/src/__tests__/fuzzy-match.test.ts +71 -65
  155. package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
  156. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  157. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  158. package/src/__tests__/gemini-image-service.test.ts +113 -100
  159. package/src/__tests__/gemini-provider.test.ts +297 -220
  160. package/src/__tests__/get-weather.test.ts +188 -114
  161. package/src/__tests__/gmail-integration.test.ts +13 -5
  162. package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
  163. package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
  164. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  165. package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
  166. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
  167. package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
  168. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
  169. package/src/__tests__/guardian-action-store.test.ts +158 -109
  170. package/src/__tests__/guardian-action-sweep.test.ts +114 -100
  171. package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
  172. package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
  173. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
  174. package/src/__tests__/guardian-dispatch.test.ts +316 -256
  175. package/src/__tests__/guardian-grant-minting.test.ts +247 -178
  176. package/src/__tests__/guardian-outbound-http.test.ts +5 -3
  177. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
  178. package/src/__tests__/guardian-question-copy.test.ts +17 -17
  179. package/src/__tests__/guardian-question-mode.test.ts +134 -100
  180. package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
  181. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  182. package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
  183. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  184. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
  185. package/src/__tests__/handle-user-message-secret-resume.test.ts +7 -2
  186. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
  187. package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
  188. package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
  189. package/src/__tests__/handlers-slack-config.test.ts +63 -54
  190. package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
  191. package/src/__tests__/handlers-telegram-config.test.ts +662 -329
  192. package/src/__tests__/handlers-twitter-config.test.ts +525 -298
  193. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +5 -2
  194. package/src/__tests__/headless-browser-interactions.test.ts +444 -280
  195. package/src/__tests__/headless-browser-navigate.test.ts +116 -79
  196. package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
  197. package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
  198. package/src/__tests__/heartbeat-service.test.ts +76 -58
  199. package/src/__tests__/history-repair-observability.test.ts +14 -14
  200. package/src/__tests__/history-repair.test.ts +171 -167
  201. package/src/__tests__/home-base-bootstrap.test.ts +30 -27
  202. package/src/__tests__/hooks-blocking.test.ts +86 -37
  203. package/src/__tests__/hooks-cli.test.ts +104 -68
  204. package/src/__tests__/hooks-config.test.ts +81 -43
  205. package/src/__tests__/hooks-discovery.test.ts +106 -96
  206. package/src/__tests__/hooks-integration.test.ts +78 -72
  207. package/src/__tests__/hooks-manager.test.ts +99 -61
  208. package/src/__tests__/hooks-runner.test.ts +94 -71
  209. package/src/__tests__/hooks-settings.test.ts +69 -64
  210. package/src/__tests__/hooks-templates.test.ts +85 -54
  211. package/src/__tests__/hooks-ts-runner.test.ts +82 -45
  212. package/src/__tests__/hooks-watch.test.ts +32 -22
  213. package/src/__tests__/host-file-edit-tool.test.ts +190 -148
  214. package/src/__tests__/host-file-read-tool.test.ts +86 -63
  215. package/src/__tests__/host-file-write-tool.test.ts +98 -64
  216. package/src/__tests__/host-shell-tool.test.ts +342 -233
  217. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  218. package/src/__tests__/ingress-member-store.test.ts +163 -159
  219. package/src/__tests__/ingress-reconcile.test.ts +13 -6
  220. package/src/__tests__/ingress-routes-http.test.ts +441 -356
  221. package/src/__tests__/ingress-url-consistency.test.ts +125 -64
  222. package/src/__tests__/integration-status.test.ts +93 -73
  223. package/src/__tests__/intent-routing.test.ts +148 -118
  224. package/src/__tests__/invite-redemption-service.test.ts +163 -121
  225. package/src/__tests__/ipc-blob-store.test.ts +104 -91
  226. package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
  227. package/src/__tests__/ipc-contract.test.ts +24 -23
  228. package/src/__tests__/ipc-protocol.test.ts +52 -46
  229. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
  230. package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
  231. package/src/__tests__/ipc-validate.test.ts +240 -179
  232. package/src/__tests__/key-migration.test.ts +123 -90
  233. package/src/__tests__/keychain.test.ts +150 -123
  234. package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
  235. package/src/__tests__/llm-usage-store.test.ts +112 -87
  236. package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
  237. package/src/__tests__/managed-store.test.ts +411 -360
  238. package/src/__tests__/mcp-cli.test.ts +190 -124
  239. package/src/__tests__/mcp-health-check.test.ts +26 -21
  240. package/src/__tests__/media-generate-image.test.ts +122 -99
  241. package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
  242. package/src/__tests__/media-visibility-policy.test.ts +86 -38
  243. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
  244. package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
  245. package/src/__tests__/memory-query-builder.test.ts +32 -33
  246. package/src/__tests__/memory-recall-quality.test.ts +761 -407
  247. package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
  248. package/src/__tests__/memory-regressions.test.ts +3725 -2642
  249. package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
  250. package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
  251. package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
  252. package/src/__tests__/messaging-send-tool.test.ts +36 -29
  253. package/src/__tests__/migration-cli-flows.test.ts +69 -53
  254. package/src/__tests__/migration-ordering.test.ts +103 -86
  255. package/src/__tests__/mime-builder.test.ts +55 -32
  256. package/src/__tests__/mock-signup-server.test.ts +384 -246
  257. package/src/__tests__/model-intents.test.ts +61 -37
  258. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
  259. package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
  260. package/src/__tests__/non-member-access-request.test.ts +3 -2
  261. package/src/__tests__/notification-broadcaster.test.ts +99 -81
  262. package/src/__tests__/notification-decision-fallback.test.ts +223 -178
  263. package/src/__tests__/notification-decision-strategy.test.ts +375 -337
  264. package/src/__tests__/notification-deep-link.test.ts +67 -61
  265. package/src/__tests__/notification-guardian-path.test.ts +248 -206
  266. package/src/__tests__/notification-routing-intent.test.ts +166 -93
  267. package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
  268. package/src/__tests__/notification-thread-candidates.test.ts +64 -61
  269. package/src/__tests__/oauth-callback-registry.test.ts +40 -30
  270. package/src/__tests__/oauth-connect-handler.test.ts +109 -89
  271. package/src/__tests__/oauth-scope-policy.test.ts +63 -55
  272. package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
  273. package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
  274. package/src/__tests__/onboarding-template-contract.test.ts +93 -94
  275. package/src/__tests__/openai-provider.test.ts +366 -274
  276. package/src/__tests__/pairing-concurrent.test.ts +18 -12
  277. package/src/__tests__/pairing-routes.test.ts +45 -41
  278. package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
  279. package/src/__tests__/parser.test.ts +316 -226
  280. package/src/__tests__/path-classifier.test.ts +24 -25
  281. package/src/__tests__/path-policy.test.ts +187 -147
  282. package/src/__tests__/phone.test.ts +36 -36
  283. package/src/__tests__/platform-move-helper.test.ts +48 -40
  284. package/src/__tests__/platform-socket-path.test.ts +23 -24
  285. package/src/__tests__/platform-workspace-migration.test.ts +464 -414
  286. package/src/__tests__/platform.test.ts +61 -53
  287. package/src/__tests__/playbook-execution.test.ts +397 -265
  288. package/src/__tests__/playbook-tools.test.ts +267 -196
  289. package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
  290. package/src/__tests__/pricing.test.ts +316 -136
  291. package/src/__tests__/profile-compiler.test.ts +206 -188
  292. package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
  293. package/src/__tests__/provider-error-scenarios.test.ts +212 -158
  294. package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
  295. package/src/__tests__/provider-registry-ollama.test.ts +13 -9
  296. package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
  297. package/src/__tests__/proxy-approval-callback.test.ts +180 -119
  298. package/src/__tests__/public-ingress-urls.test.ts +112 -94
  299. package/src/__tests__/qdrant-manager.test.ts +147 -98
  300. package/src/__tests__/ratelimit.test.ts +152 -82
  301. package/src/__tests__/recording-handler.test.ts +273 -151
  302. package/src/__tests__/recording-intent-fallback.test.ts +94 -75
  303. package/src/__tests__/recording-intent-handler.test.ts +9 -2
  304. package/src/__tests__/recording-intent.test.ts +578 -379
  305. package/src/__tests__/recording-state-machine.test.ts +530 -316
  306. package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
  307. package/src/__tests__/recurrence-engine.test.ts +81 -41
  308. package/src/__tests__/recurrence-types.test.ts +63 -44
  309. package/src/__tests__/relay-server.test.ts +2131 -1602
  310. package/src/__tests__/reminder-store.test.ts +158 -80
  311. package/src/__tests__/reminder.test.ts +113 -109
  312. package/src/__tests__/remote-skill-policy.test.ts +96 -72
  313. package/src/__tests__/request-file-tool.test.ts +74 -67
  314. package/src/__tests__/response-tier.test.ts +131 -74
  315. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  316. package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
  317. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  318. package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
  319. package/src/__tests__/sandbox-host-parity.test.ts +377 -301
  320. package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
  321. package/src/__tests__/schedule-store.test.ts +268 -205
  322. package/src/__tests__/schedule-tools.test.ts +702 -524
  323. package/src/__tests__/scheduler-recurrence.test.ts +240 -130
  324. package/src/__tests__/scoped-approval-grants.test.ts +258 -168
  325. package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
  326. package/src/__tests__/script-proxy-certs.test.ts +38 -35
  327. package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
  328. package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
  329. package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
  330. package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
  331. package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
  332. package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
  333. package/src/__tests__/script-proxy-policy.test.ts +308 -153
  334. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
  335. package/src/__tests__/script-proxy-router.test.ts +111 -77
  336. package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
  337. package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
  338. package/src/__tests__/secret-allowlist.test.ts +105 -90
  339. package/src/__tests__/secret-ingress-handler.test.ts +41 -30
  340. package/src/__tests__/secret-onetime-send.test.ts +67 -50
  341. package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
  342. package/src/__tests__/secret-response-routing.test.ts +50 -41
  343. package/src/__tests__/secret-scanner-executor.test.ts +152 -111
  344. package/src/__tests__/secret-scanner.test.ts +495 -413
  345. package/src/__tests__/secure-keys.test.ts +132 -121
  346. package/src/__tests__/send-endpoint-busy.test.ts +8 -3
  347. package/src/__tests__/send-notification-tool.test.ts +43 -42
  348. package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
  349. package/src/__tests__/sequence-store.test.ts +335 -167
  350. package/src/__tests__/server-history-render.test.ts +341 -202
  351. package/src/__tests__/session-abort-tool-results.test.ts +133 -70
  352. package/src/__tests__/session-confirmation-signals.test.ts +252 -160
  353. package/src/__tests__/session-conflict-gate.test.ts +775 -585
  354. package/src/__tests__/session-error.test.ts +222 -191
  355. package/src/__tests__/session-evictor.test.ts +79 -62
  356. package/src/__tests__/session-init.benchmark.test.ts +170 -108
  357. package/src/__tests__/session-load-history-repair.test.ts +273 -139
  358. package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
  359. package/src/__tests__/session-pre-run-repair.test.ts +106 -59
  360. package/src/__tests__/session-profile-injection.test.ts +198 -130
  361. package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
  362. package/src/__tests__/session-queue.test.ts +624 -321
  363. package/src/__tests__/session-runtime-assembly.test.ts +425 -329
  364. package/src/__tests__/session-runtime-workspace.test.ts +69 -61
  365. package/src/__tests__/session-skill-tools.test.ts +973 -678
  366. package/src/__tests__/session-slash-known.test.ts +185 -133
  367. package/src/__tests__/session-slash-queue.test.ts +147 -81
  368. package/src/__tests__/session-slash-unknown.test.ts +135 -90
  369. package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
  370. package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
  371. package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
  372. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
  373. package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
  374. package/src/__tests__/session-undo.test.ts +43 -30
  375. package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
  376. package/src/__tests__/session-workspace-injection.test.ts +245 -117
  377. package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
  378. package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
  379. package/src/__tests__/shell-credential-ref.test.ts +126 -90
  380. package/src/__tests__/shell-identity.test.ts +134 -111
  381. package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
  382. package/src/__tests__/shell-parser-property.test.ts +435 -288
  383. package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
  384. package/src/__tests__/size-guard.test.ts +42 -44
  385. package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
  386. package/src/__tests__/skill-feature-flags.test.ts +75 -47
  387. package/src/__tests__/skill-include-graph.test.ts +143 -148
  388. package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
  389. package/src/__tests__/skill-load-tool.test.ts +371 -199
  390. package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
  391. package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
  392. package/src/__tests__/skill-script-runner-host.test.ts +460 -250
  393. package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
  394. package/src/__tests__/skill-script-runner.test.ts +115 -74
  395. package/src/__tests__/skill-tool-factory.test.ts +140 -96
  396. package/src/__tests__/skill-tool-manifest.test.ts +306 -210
  397. package/src/__tests__/skill-version-hash.test.ts +70 -56
  398. package/src/__tests__/skills.test.ts +0 -1
  399. package/src/__tests__/slack-channel-config.test.ts +127 -84
  400. package/src/__tests__/slack-skill.test.ts +60 -47
  401. package/src/__tests__/slash-commands-catalog.test.ts +37 -31
  402. package/src/__tests__/slash-commands-parser.test.ts +71 -64
  403. package/src/__tests__/slash-commands-resolver.test.ts +143 -107
  404. package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
  405. package/src/__tests__/sms-messaging-provider.test.ts +4 -0
  406. package/src/__tests__/speaker-identification.test.ts +28 -25
  407. package/src/__tests__/starter-bundle.test.ts +27 -23
  408. package/src/__tests__/starter-task-flow.test.ts +67 -52
  409. package/src/__tests__/subagent-manager-notify.test.ts +154 -108
  410. package/src/__tests__/subagent-tools.test.ts +311 -270
  411. package/src/__tests__/subagent-types.test.ts +40 -40
  412. package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
  413. package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
  414. package/src/__tests__/swarm-orchestrator.test.ts +135 -101
  415. package/src/__tests__/swarm-plan-validator.test.ts +125 -73
  416. package/src/__tests__/swarm-recursion.test.ts +58 -46
  417. package/src/__tests__/swarm-router-planner.test.ts +99 -74
  418. package/src/__tests__/swarm-session-integration.test.ts +148 -91
  419. package/src/__tests__/swarm-tool.test.ts +65 -45
  420. package/src/__tests__/swarm-worker-backend.test.ts +59 -45
  421. package/src/__tests__/swarm-worker-runner.test.ts +133 -118
  422. package/src/__tests__/system-prompt.test.ts +311 -256
  423. package/src/__tests__/task-compiler.test.ts +176 -120
  424. package/src/__tests__/task-management-tools.test.ts +561 -456
  425. package/src/__tests__/task-memory-cleanup.test.ts +627 -362
  426. package/src/__tests__/task-runner.test.ts +117 -94
  427. package/src/__tests__/task-scheduler.test.ts +113 -84
  428. package/src/__tests__/task-tools.test.ts +349 -264
  429. package/src/__tests__/terminal-sandbox.test.ts +138 -108
  430. package/src/__tests__/terminal-tools.test.ts +350 -305
  431. package/src/__tests__/thread-seed-composer.test.ts +307 -180
  432. package/src/__tests__/tool-approval-handler.test.ts +238 -137
  433. package/src/__tests__/tool-audit-listener.test.ts +69 -69
  434. package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
  435. package/src/__tests__/tool-execution-abort-cleanup.test.ts +155 -146
  436. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
  437. package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
  438. package/src/__tests__/tool-executor-redaction.test.ts +112 -109
  439. package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
  440. package/src/__tests__/tool-executor.test.ts +1274 -674
  441. package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
  442. package/src/__tests__/tool-metrics-listener.test.ts +97 -85
  443. package/src/__tests__/tool-notification-listener.test.ts +42 -25
  444. package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
  445. package/src/__tests__/tool-policy.test.ts +44 -25
  446. package/src/__tests__/tool-profiling-listener.test.ts +99 -93
  447. package/src/__tests__/tool-result-truncation.test.ts +5 -4
  448. package/src/__tests__/tool-trace-listener.test.ts +131 -111
  449. package/src/__tests__/top-level-renderer.test.ts +62 -58
  450. package/src/__tests__/top-level-scanner.test.ts +68 -64
  451. package/src/__tests__/trace-emitter.test.ts +56 -56
  452. package/src/__tests__/trust-context-guards.test.ts +65 -65
  453. package/src/__tests__/trust-store.test.ts +1239 -806
  454. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  455. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  456. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +3 -2
  457. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -2
  458. package/src/__tests__/trusted-contact-verification.test.ts +251 -231
  459. package/src/__tests__/turn-commit.test.ts +259 -200
  460. package/src/__tests__/twilio-provider.test.ts +140 -126
  461. package/src/__tests__/twilio-rest.test.ts +22 -18
  462. package/src/__tests__/twilio-routes-elevenlabs.test.ts +0 -1
  463. package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
  464. package/src/__tests__/twilio-routes.test.ts +0 -1
  465. package/src/__tests__/twitter-auth-handler.test.ts +184 -139
  466. package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
  467. package/src/__tests__/twitter-cli-routing.test.ts +146 -99
  468. package/src/__tests__/twitter-oauth-client.test.ts +82 -65
  469. package/src/__tests__/update-bulletin-format.test.ts +69 -66
  470. package/src/__tests__/update-bulletin-state.test.ts +66 -60
  471. package/src/__tests__/update-bulletin.test.ts +150 -114
  472. package/src/__tests__/update-template-contract.test.ts +15 -10
  473. package/src/__tests__/url-safety.test.ts +288 -265
  474. package/src/__tests__/user-reference.test.ts +32 -32
  475. package/src/__tests__/view-image-tool.test.ts +118 -96
  476. package/src/__tests__/voice-invite-redemption.test.ts +111 -106
  477. package/src/__tests__/voice-quality.test.ts +117 -102
  478. package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
  479. package/src/__tests__/voice-session-bridge.test.ts +351 -216
  480. package/src/__tests__/weather-skill-regression.test.ts +170 -120
  481. package/src/__tests__/web-fetch.test.ts +664 -526
  482. package/src/__tests__/web-search.test.ts +379 -213
  483. package/src/__tests__/work-item-output.test.ts +90 -53
  484. package/src/__tests__/workspace-git-service.test.ts +437 -356
  485. package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
  486. package/src/__tests__/workspace-lifecycle.test.ts +98 -64
  487. package/src/__tests__/workspace-policy.test.ts +139 -71
  488. package/src/cli/mcp.ts +81 -28
  489. package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
  490. package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
  491. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +25 -10
  492. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
  493. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +6 -11
  494. package/src/config/bundled-skills/messaging/SKILL.md +4 -3
  495. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
  496. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
  497. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -2
  498. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
  499. package/src/config/bundled-skills/sms-setup/SKILL.md +8 -16
  500. package/src/config/bundled-skills/telegram-setup/SKILL.md +3 -3
  501. package/src/config/bundled-skills/trusted-contacts/SKILL.md +13 -25
  502. package/src/config/bundled-skills/twilio-setup/SKILL.md +13 -23
  503. package/src/config/bundled-tool-registry.ts +2 -0
  504. package/src/config/env.ts +3 -4
  505. package/src/config/system-prompt.ts +32 -0
  506. package/src/mcp/client.ts +2 -7
  507. package/src/memory/db-connection.ts +16 -10
  508. package/src/messaging/providers/gmail/adapter.ts +10 -3
  509. package/src/messaging/providers/gmail/client.ts +280 -72
  510. package/src/runtime/auth/__tests__/context.test.ts +75 -65
  511. package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
  512. package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
  513. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
  514. package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
  515. package/src/runtime/auth/__tests__/policy.test.ts +9 -9
  516. package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
  517. package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
  518. package/src/runtime/auth/__tests__/subject.test.ts +54 -54
  519. package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
  520. package/src/runtime/auth/scopes.ts +3 -0
  521. package/src/runtime/auth/token-service.ts +4 -1
  522. package/src/runtime/auth/types.ts +2 -1
  523. package/src/runtime/http-server.ts +2 -1
  524. package/src/security/secure-keys.ts +120 -54
  525. package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
  526. package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
  527. package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
  528. package/src/tools/terminal/safe-env.ts +7 -0
@@ -1,30 +1,33 @@
1
- import { randomBytes } from 'node:crypto';
2
- import { existsSync,mkdirSync, rmSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
5
-
6
- import { afterAll,beforeEach, describe, expect, test } from 'bun:test';
7
- import { mock } from 'bun:test';
8
-
9
- mock.module('../util/logger.js', () => ({
10
- getLogger: () => new Proxy({} as Record<string, unknown>, {
11
- get: () => () => {},
12
- }),
1
+ import { randomBytes } from "node:crypto";
2
+ import { existsSync, mkdirSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { afterAll, beforeEach, describe, expect, test } from "bun:test";
6
+ import { mock } from "bun:test";
7
+
8
+ mock.module("../util/logger.js", () => ({
9
+ getLogger: () =>
10
+ new Proxy({} as Record<string, unknown>, {
11
+ get: () => () => {},
12
+ }),
13
13
  }));
14
14
 
15
15
  import {
16
16
  _setMetadataPath,
17
17
  upsertCredentialMetadata,
18
- } from '../tools/credentials/metadata-store.js';
18
+ } from "../tools/credentials/metadata-store.js";
19
19
  import {
20
20
  resolveById,
21
21
  resolveByServiceField,
22
22
  resolveCredentialRef,
23
23
  resolveForDomain,
24
- } from '../tools/credentials/resolve.js';
24
+ } from "../tools/credentials/resolve.js";
25
25
 
26
- const TEST_DIR = join(tmpdir(), `vellum-credresolve-test-${randomBytes(4).toString('hex')}`);
27
- const META_PATH = join(TEST_DIR, 'metadata.json');
26
+ const TEST_DIR = join(
27
+ tmpdir(),
28
+ `vellum-credresolve-test-${randomBytes(4).toString("hex")}`,
29
+ );
30
+ const META_PATH = join(TEST_DIR, "metadata.json");
28
31
 
29
32
  beforeEach(() => {
30
33
  if (existsSync(TEST_DIR)) {
@@ -41,107 +44,119 @@ afterAll(() => {
41
44
  }
42
45
  });
43
46
 
44
- describe('credential resolver', () => {
45
- describe('resolveByServiceField', () => {
46
- test('resolves existing credential', () => {
47
- const created = upsertCredentialMetadata('github', 'token', {
48
- allowedTools: ['browser_fill_credential'],
47
+ describe("credential resolver", () => {
48
+ describe("resolveByServiceField", () => {
49
+ test("resolves existing credential", () => {
50
+ const created = upsertCredentialMetadata("github", "token", {
51
+ allowedTools: ["browser_fill_credential"],
49
52
  });
50
53
 
51
- const result = resolveByServiceField('github', 'token');
54
+ const result = resolveByServiceField("github", "token");
52
55
  expect(result).toBeDefined();
53
56
  expect(result!.credentialId).toBe(created.credentialId);
54
- expect(result!.service).toBe('github');
55
- expect(result!.field).toBe('token');
56
- expect(result!.storageKey).toBe('credential:github:token');
57
- expect(result!.metadata.allowedTools).toEqual(['browser_fill_credential']);
57
+ expect(result!.service).toBe("github");
58
+ expect(result!.field).toBe("token");
59
+ expect(result!.storageKey).toBe("credential:github:token");
60
+ expect(result!.metadata.allowedTools).toEqual([
61
+ "browser_fill_credential",
62
+ ]);
58
63
  });
59
64
 
60
- test('returns undefined for non-existent credential', () => {
61
- expect(resolveByServiceField('nonexistent', 'field')).toBeUndefined();
65
+ test("returns undefined for non-existent credential", () => {
66
+ expect(resolveByServiceField("nonexistent", "field")).toBeUndefined();
62
67
  });
63
68
 
64
- test('includes alias when set', () => {
65
- upsertCredentialMetadata('fal', 'api_key', { alias: 'fal-primary' });
66
- const result = resolveByServiceField('fal', 'api_key');
67
- expect(result!.alias).toBe('fal-primary');
69
+ test("includes alias when set", () => {
70
+ upsertCredentialMetadata("fal", "api_key", { alias: "fal-primary" });
71
+ const result = resolveByServiceField("fal", "api_key");
72
+ expect(result!.alias).toBe("fal-primary");
68
73
  });
69
74
 
70
- test('alias is undefined when not set', () => {
71
- upsertCredentialMetadata('fal', 'api_key');
72
- const result = resolveByServiceField('fal', 'api_key');
75
+ test("alias is undefined when not set", () => {
76
+ upsertCredentialMetadata("fal", "api_key");
77
+ const result = resolveByServiceField("fal", "api_key");
73
78
  expect(result!.alias).toBeUndefined();
74
79
  });
75
80
 
76
- test('includes injection templates when set', () => {
77
- upsertCredentialMetadata('fal', 'api_key', {
81
+ test("includes injection templates when set", () => {
82
+ upsertCredentialMetadata("fal", "api_key", {
78
83
  injectionTemplates: [
79
- { hostPattern: '*.fal.ai', injectionType: 'header', headerName: 'Authorization', valuePrefix: 'Key ' },
84
+ {
85
+ hostPattern: "*.fal.ai",
86
+ injectionType: "header",
87
+ headerName: "Authorization",
88
+ valuePrefix: "Key ",
89
+ },
80
90
  ],
81
91
  });
82
- const result = resolveByServiceField('fal', 'api_key');
92
+ const result = resolveByServiceField("fal", "api_key");
83
93
  expect(result!.injectionTemplates).toHaveLength(1);
84
- expect(result!.injectionTemplates[0].hostPattern).toBe('*.fal.ai');
85
- expect(result!.injectionTemplates[0].injectionType).toBe('header');
94
+ expect(result!.injectionTemplates[0].hostPattern).toBe("*.fal.ai");
95
+ expect(result!.injectionTemplates[0].injectionType).toBe("header");
86
96
  });
87
97
 
88
- test('injection templates default to empty array', () => {
89
- upsertCredentialMetadata('github', 'token');
90
- const result = resolveByServiceField('github', 'token');
98
+ test("injection templates default to empty array", () => {
99
+ upsertCredentialMetadata("github", "token");
100
+ const result = resolveByServiceField("github", "token");
91
101
  expect(result!.injectionTemplates).toEqual([]);
92
102
  });
93
103
  });
94
104
 
95
- describe('resolveById', () => {
96
- test('resolves existing credential by ID', () => {
97
- const created = upsertCredentialMetadata('gmail', 'password');
105
+ describe("resolveById", () => {
106
+ test("resolves existing credential by ID", () => {
107
+ const created = upsertCredentialMetadata("gmail", "password");
98
108
 
99
109
  const result = resolveById(created.credentialId);
100
110
  expect(result).toBeDefined();
101
111
  expect(result!.credentialId).toBe(created.credentialId);
102
- expect(result!.service).toBe('gmail');
103
- expect(result!.field).toBe('password');
104
- expect(result!.storageKey).toBe('credential:gmail:password');
112
+ expect(result!.service).toBe("gmail");
113
+ expect(result!.field).toBe("password");
114
+ expect(result!.storageKey).toBe("credential:gmail:password");
105
115
  });
106
116
 
107
- test('returns undefined for non-existent ID', () => {
108
- expect(resolveById('non-existent-id')).toBeUndefined();
117
+ test("returns undefined for non-existent ID", () => {
118
+ expect(resolveById("non-existent-id")).toBeUndefined();
109
119
  });
110
120
 
111
- test('includes alias and injection templates', () => {
112
- const created = upsertCredentialMetadata('replicate', 'api_key', {
113
- alias: 'replicate-prod',
121
+ test("includes alias and injection templates", () => {
122
+ const created = upsertCredentialMetadata("replicate", "api_key", {
123
+ alias: "replicate-prod",
114
124
  injectionTemplates: [
115
- { hostPattern: 'api.replicate.com', injectionType: 'header', headerName: 'Authorization', valuePrefix: 'Bearer ' },
125
+ {
126
+ hostPattern: "api.replicate.com",
127
+ injectionType: "header",
128
+ headerName: "Authorization",
129
+ valuePrefix: "Bearer ",
130
+ },
116
131
  ],
117
132
  });
118
133
 
119
134
  const result = resolveById(created.credentialId);
120
- expect(result!.alias).toBe('replicate-prod');
135
+ expect(result!.alias).toBe("replicate-prod");
121
136
  expect(result!.injectionTemplates).toHaveLength(1);
122
- expect(result!.injectionTemplates[0].valuePrefix).toBe('Bearer ');
137
+ expect(result!.injectionTemplates[0].valuePrefix).toBe("Bearer ");
123
138
  });
124
139
 
125
- test('deterministic lookup among multiple credentials for same provider', () => {
126
- const cred1 = upsertCredentialMetadata('openai', 'api_key_primary');
127
- const cred2 = upsertCredentialMetadata('openai', 'api_key_secondary');
140
+ test("deterministic lookup among multiple credentials for same provider", () => {
141
+ const cred1 = upsertCredentialMetadata("openai", "api_key_primary");
142
+ const cred2 = upsertCredentialMetadata("openai", "api_key_secondary");
128
143
 
129
144
  const result1 = resolveById(cred1.credentialId);
130
145
  const result2 = resolveById(cred2.credentialId);
131
146
 
132
147
  expect(result1!.credentialId).toBe(cred1.credentialId);
133
- expect(result1!.field).toBe('api_key_primary');
148
+ expect(result1!.field).toBe("api_key_primary");
134
149
  expect(result2!.credentialId).toBe(cred2.credentialId);
135
- expect(result2!.field).toBe('api_key_secondary');
150
+ expect(result2!.field).toBe("api_key_secondary");
136
151
  expect(result1!.credentialId).not.toBe(result2!.credentialId);
137
152
  });
138
153
  });
139
154
 
140
- describe('cross-resolution', () => {
141
- test('service/field and ID resolve to same credential', () => {
142
- const created = upsertCredentialMetadata('github', 'token');
155
+ describe("cross-resolution", () => {
156
+ test("service/field and ID resolve to same credential", () => {
157
+ const created = upsertCredentialMetadata("github", "token");
143
158
 
144
- const byServiceField = resolveByServiceField('github', 'token');
159
+ const byServiceField = resolveByServiceField("github", "token");
145
160
  const byId = resolveById(created.credentialId);
146
161
 
147
162
  expect(byServiceField).toBeDefined();
@@ -150,176 +165,228 @@ describe('credential resolver', () => {
150
165
  expect(byServiceField!.storageKey).toBe(byId!.storageKey);
151
166
  });
152
167
 
153
- test('both paths return identical injection templates', () => {
168
+ test("both paths return identical injection templates", () => {
154
169
  const templates = [
155
- { hostPattern: '*.fal.ai', injectionType: 'header' as const, headerName: 'Authorization', valuePrefix: 'Key ' },
170
+ {
171
+ hostPattern: "*.fal.ai",
172
+ injectionType: "header" as const,
173
+ headerName: "Authorization",
174
+ valuePrefix: "Key ",
175
+ },
156
176
  ];
157
- const created = upsertCredentialMetadata('fal', 'api_key', {
177
+ const created = upsertCredentialMetadata("fal", "api_key", {
158
178
  injectionTemplates: templates,
159
- alias: 'fal-test',
179
+ alias: "fal-test",
160
180
  });
161
181
 
162
- const byServiceField = resolveByServiceField('fal', 'api_key');
182
+ const byServiceField = resolveByServiceField("fal", "api_key");
163
183
  const byId = resolveById(created.credentialId);
164
184
 
165
- expect(byServiceField!.injectionTemplates).toEqual(byId!.injectionTemplates);
185
+ expect(byServiceField!.injectionTemplates).toEqual(
186
+ byId!.injectionTemplates,
187
+ );
166
188
  expect(byServiceField!.alias).toBe(byId!.alias);
167
189
  });
168
190
  });
169
191
 
170
- describe('storage key format', () => {
171
- test('storage key follows credential:{service}:{field} format', () => {
172
- upsertCredentialMetadata('my-service', 'api-key');
173
- const result = resolveByServiceField('my-service', 'api-key');
174
- expect(result!.storageKey).toBe('credential:my-service:api-key');
192
+ describe("storage key format", () => {
193
+ test("storage key follows credential:{service}:{field} format", () => {
194
+ upsertCredentialMetadata("my-service", "api-key");
195
+ const result = resolveByServiceField("my-service", "api-key");
196
+ expect(result!.storageKey).toBe("credential:my-service:api-key");
175
197
  });
176
198
  });
177
199
 
178
- describe('resolveForDomain', () => {
179
- test('returns credentials matching the hostname', () => {
180
- upsertCredentialMetadata('fal', 'api_key', {
200
+ describe("resolveForDomain", () => {
201
+ test("returns credentials matching the hostname", () => {
202
+ upsertCredentialMetadata("fal", "api_key", {
181
203
  injectionTemplates: [
182
- { hostPattern: '*.fal.ai', injectionType: 'header', headerName: 'Authorization', valuePrefix: 'Key ' },
204
+ {
205
+ hostPattern: "*.fal.ai",
206
+ injectionType: "header",
207
+ headerName: "Authorization",
208
+ valuePrefix: "Key ",
209
+ },
183
210
  ],
184
211
  });
185
- upsertCredentialMetadata('replicate', 'api_key', {
212
+ upsertCredentialMetadata("replicate", "api_key", {
186
213
  injectionTemplates: [
187
- { hostPattern: 'api.replicate.com', injectionType: 'header', headerName: 'Authorization', valuePrefix: 'Bearer ' },
214
+ {
215
+ hostPattern: "api.replicate.com",
216
+ injectionType: "header",
217
+ headerName: "Authorization",
218
+ valuePrefix: "Bearer ",
219
+ },
188
220
  ],
189
221
  });
190
222
 
191
- const results = resolveForDomain('queue.fal.ai');
223
+ const results = resolveForDomain("queue.fal.ai");
192
224
  expect(results).toHaveLength(1);
193
- expect(results[0].service).toBe('fal');
225
+ expect(results[0].service).toBe("fal");
194
226
  expect(results[0].injectionTemplates).toHaveLength(1);
195
- expect(results[0].injectionTemplates[0].valuePrefix).toBe('Key ');
227
+ expect(results[0].injectionTemplates[0].valuePrefix).toBe("Key ");
196
228
  });
197
229
 
198
- test('returns empty array when no templates match', () => {
199
- upsertCredentialMetadata('fal', 'api_key', {
230
+ test("returns empty array when no templates match", () => {
231
+ upsertCredentialMetadata("fal", "api_key", {
200
232
  injectionTemplates: [
201
- { hostPattern: '*.fal.ai', injectionType: 'header', headerName: 'Authorization', valuePrefix: 'Key ' },
233
+ {
234
+ hostPattern: "*.fal.ai",
235
+ injectionType: "header",
236
+ headerName: "Authorization",
237
+ valuePrefix: "Key ",
238
+ },
202
239
  ],
203
240
  });
204
241
 
205
- const results = resolveForDomain('api.openai.com');
242
+ const results = resolveForDomain("api.openai.com");
206
243
  expect(results).toHaveLength(0);
207
244
  });
208
245
 
209
- test('returns empty array for credentials without injection templates', () => {
210
- upsertCredentialMetadata('github', 'token');
246
+ test("returns empty array for credentials without injection templates", () => {
247
+ upsertCredentialMetadata("github", "token");
211
248
 
212
- const results = resolveForDomain('github.com');
249
+ const results = resolveForDomain("github.com");
213
250
  expect(results).toHaveLength(0);
214
251
  });
215
252
 
216
- test('filters injection templates to only matching entries', () => {
217
- upsertCredentialMetadata('multi', 'key', {
253
+ test("filters injection templates to only matching entries", () => {
254
+ upsertCredentialMetadata("multi", "key", {
218
255
  injectionTemplates: [
219
- { hostPattern: '*.fal.ai', injectionType: 'header', headerName: 'Authorization', valuePrefix: 'Key ' },
220
- { hostPattern: '*.replicate.com', injectionType: 'header', headerName: 'Authorization', valuePrefix: 'Bearer ' },
256
+ {
257
+ hostPattern: "*.fal.ai",
258
+ injectionType: "header",
259
+ headerName: "Authorization",
260
+ valuePrefix: "Key ",
261
+ },
262
+ {
263
+ hostPattern: "*.replicate.com",
264
+ injectionType: "header",
265
+ headerName: "Authorization",
266
+ valuePrefix: "Bearer ",
267
+ },
221
268
  ],
222
269
  });
223
270
 
224
- const results = resolveForDomain('api.replicate.com');
271
+ const results = resolveForDomain("api.replicate.com");
225
272
  expect(results).toHaveLength(1);
226
273
  expect(results[0].injectionTemplates).toHaveLength(1);
227
- expect(results[0].injectionTemplates[0].hostPattern).toBe('*.replicate.com');
274
+ expect(results[0].injectionTemplates[0].hostPattern).toBe(
275
+ "*.replicate.com",
276
+ );
228
277
  });
229
278
 
230
- test('returns multiple credentials when multiple match', () => {
231
- upsertCredentialMetadata('provider-a', 'key1', {
279
+ test("returns multiple credentials when multiple match", () => {
280
+ upsertCredentialMetadata("provider-a", "key1", {
232
281
  injectionTemplates: [
233
- { hostPattern: '*.example.com', injectionType: 'header', headerName: 'X-Api-Key' },
282
+ {
283
+ hostPattern: "*.example.com",
284
+ injectionType: "header",
285
+ headerName: "X-Api-Key",
286
+ },
234
287
  ],
235
288
  });
236
- upsertCredentialMetadata('provider-b', 'key2', {
289
+ upsertCredentialMetadata("provider-b", "key2", {
237
290
  injectionTemplates: [
238
- { hostPattern: '*.example.com', injectionType: 'query', queryParamName: 'api_key' },
291
+ {
292
+ hostPattern: "*.example.com",
293
+ injectionType: "query",
294
+ queryParamName: "api_key",
295
+ },
239
296
  ],
240
297
  });
241
298
 
242
- const results = resolveForDomain('api.example.com');
299
+ const results = resolveForDomain("api.example.com");
243
300
  expect(results).toHaveLength(2);
244
301
  const services = results.map((r) => r.service).sort();
245
- expect(services).toEqual(['provider-a', 'provider-b']);
302
+ expect(services).toEqual(["provider-a", "provider-b"]);
246
303
  });
247
304
 
248
- test('exact host pattern matches', () => {
249
- upsertCredentialMetadata('exact', 'key', {
305
+ test("exact host pattern matches", () => {
306
+ upsertCredentialMetadata("exact", "key", {
250
307
  injectionTemplates: [
251
- { hostPattern: 'api.exact.com', injectionType: 'header', headerName: 'Authorization' },
308
+ {
309
+ hostPattern: "api.exact.com",
310
+ injectionType: "header",
311
+ headerName: "Authorization",
312
+ },
252
313
  ],
253
314
  });
254
315
 
255
- expect(resolveForDomain('api.exact.com')).toHaveLength(1);
256
- expect(resolveForDomain('other.exact.com')).toHaveLength(0);
316
+ expect(resolveForDomain("api.exact.com")).toHaveLength(1);
317
+ expect(resolveForDomain("other.exact.com")).toHaveLength(0);
257
318
  });
258
319
 
259
- test('matches hostnames case-insensitively', () => {
260
- upsertCredentialMetadata('casefold', 'key', {
320
+ test("matches hostnames case-insensitively", () => {
321
+ upsertCredentialMetadata("casefold", "key", {
261
322
  injectionTemplates: [
262
- { hostPattern: '*.Example.COM', injectionType: 'header', headerName: 'Authorization' },
323
+ {
324
+ hostPattern: "*.Example.COM",
325
+ injectionType: "header",
326
+ headerName: "Authorization",
327
+ },
263
328
  ],
264
329
  });
265
330
 
266
- expect(resolveForDomain('api.example.com')).toHaveLength(1);
267
- expect(resolveForDomain('API.EXAMPLE.COM')).toHaveLength(1);
268
- expect(resolveForDomain('Api.Example.Com')).toHaveLength(1);
331
+ expect(resolveForDomain("api.example.com")).toHaveLength(1);
332
+ expect(resolveForDomain("API.EXAMPLE.COM")).toHaveLength(1);
333
+ expect(resolveForDomain("Api.Example.Com")).toHaveLength(1);
269
334
  });
270
335
  });
271
336
 
272
- describe('resolveCredentialRef', () => {
273
- test('resolves by UUID', () => {
274
- const created = upsertCredentialMetadata('github', 'token');
337
+ describe("resolveCredentialRef", () => {
338
+ test("resolves by UUID", () => {
339
+ const created = upsertCredentialMetadata("github", "token");
275
340
  const result = resolveCredentialRef(created.credentialId);
276
341
  expect(result).toBeDefined();
277
342
  expect(result!.credentialId).toBe(created.credentialId);
278
- expect(result!.service).toBe('github');
343
+ expect(result!.service).toBe("github");
279
344
  });
280
345
 
281
- test('resolves by service/field', () => {
282
- upsertCredentialMetadata('fal', 'api_key');
283
- const result = resolveCredentialRef('fal/api_key');
346
+ test("resolves by service/field", () => {
347
+ upsertCredentialMetadata("fal", "api_key");
348
+ const result = resolveCredentialRef("fal/api_key");
284
349
  expect(result).toBeDefined();
285
- expect(result!.service).toBe('fal');
286
- expect(result!.field).toBe('api_key');
350
+ expect(result!.service).toBe("fal");
351
+ expect(result!.field).toBe("api_key");
287
352
  });
288
353
 
289
- test('returns undefined for unknown UUID', () => {
290
- expect(resolveCredentialRef('00000000-0000-0000-0000-000000000000')).toBeUndefined();
354
+ test("returns undefined for unknown UUID", () => {
355
+ expect(
356
+ resolveCredentialRef("00000000-0000-0000-0000-000000000000"),
357
+ ).toBeUndefined();
291
358
  });
292
359
 
293
- test('returns undefined for unknown service/field', () => {
294
- expect(resolveCredentialRef('nonexistent/field')).toBeUndefined();
360
+ test("returns undefined for unknown service/field", () => {
361
+ expect(resolveCredentialRef("nonexistent/field")).toBeUndefined();
295
362
  });
296
363
 
297
- test('returns undefined for empty string', () => {
298
- expect(resolveCredentialRef('')).toBeUndefined();
364
+ test("returns undefined for empty string", () => {
365
+ expect(resolveCredentialRef("")).toBeUndefined();
299
366
  });
300
367
 
301
- test('returns undefined for whitespace-only string', () => {
302
- expect(resolveCredentialRef(' ')).toBeUndefined();
368
+ test("returns undefined for whitespace-only string", () => {
369
+ expect(resolveCredentialRef(" ")).toBeUndefined();
303
370
  });
304
371
 
305
- test('returns undefined for malformed ref with no slash', () => {
306
- expect(resolveCredentialRef('fal')).toBeUndefined();
372
+ test("returns undefined for malformed ref with no slash", () => {
373
+ expect(resolveCredentialRef("fal")).toBeUndefined();
307
374
  });
308
375
 
309
- test('returns undefined for malformed ref with too many slashes', () => {
310
- expect(resolveCredentialRef('fal/api/key')).toBeUndefined();
376
+ test("returns undefined for malformed ref with too many slashes", () => {
377
+ expect(resolveCredentialRef("fal/api/key")).toBeUndefined();
311
378
  });
312
379
 
313
- test('returns undefined for ref with empty service segment', () => {
314
- expect(resolveCredentialRef('/api_key')).toBeUndefined();
380
+ test("returns undefined for ref with empty service segment", () => {
381
+ expect(resolveCredentialRef("/api_key")).toBeUndefined();
315
382
  });
316
383
 
317
- test('returns undefined for ref with empty field segment', () => {
318
- expect(resolveCredentialRef('fal/')).toBeUndefined();
384
+ test("returns undefined for ref with empty field segment", () => {
385
+ expect(resolveCredentialRef("fal/")).toBeUndefined();
319
386
  });
320
387
 
321
- test('UUID takes precedence when both UUID and service/field would match', () => {
322
- const created = upsertCredentialMetadata('github', 'token');
388
+ test("UUID takes precedence when both UUID and service/field would match", () => {
389
+ const created = upsertCredentialMetadata("github", "token");
323
390
  // The credentialId is a UUID, not a service/field, so resolveById finds it first
324
391
  const result = resolveCredentialRef(created.credentialId);
325
392
  expect(result).toBeDefined();