@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,43 +1,55 @@
1
- import { randomBytes } from 'node:crypto';
2
- import { mkdirSync, rmSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
5
-
6
- import { afterAll, afterEach, beforeEach, describe, expect, mock,test } from 'bun:test';
1
+ import { randomBytes } from "node:crypto";
2
+ import { mkdirSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import {
6
+ afterAll,
7
+ afterEach,
8
+ beforeEach,
9
+ describe,
10
+ expect,
11
+ mock,
12
+ test,
13
+ } from "bun:test";
7
14
 
8
15
  // ---------------------------------------------------------------------------
9
16
  // Mock logger
10
17
  // ---------------------------------------------------------------------------
11
18
 
12
- mock.module('../util/logger.js', () => ({
13
- getLogger: () => new Proxy({} as Record<string, unknown>, {
14
- get: () => () => {},
15
- }),
19
+ mock.module("../util/logger.js", () => ({
20
+ getLogger: () =>
21
+ new Proxy({} as Record<string, unknown>, {
22
+ get: () => () => {},
23
+ }),
16
24
  }));
17
25
 
18
26
  // ---------------------------------------------------------------------------
19
27
  // Use encrypted backend (no keychain) with a temp store path
20
28
  // ---------------------------------------------------------------------------
21
29
 
22
- import { _overrideDeps, _resetDeps } from '../security/keychain.js';
30
+ import { _overrideDeps, _resetDeps } from "../security/keychain.js";
23
31
 
24
32
  _overrideDeps({
25
33
  isMacOS: () => false,
26
34
  isLinux: () => false,
27
- execFileSync: (() => '') as unknown as typeof import('node:child_process').execFileSync,
35
+ execFileSync: (() =>
36
+ "") as unknown as typeof import("node:child_process").execFileSync,
28
37
  });
29
38
 
30
- import { _setStorePath } from '../security/encrypted-store.js';
31
- import { _resetBackend } from '../security/secure-keys.js';
39
+ import { _setStorePath } from "../security/encrypted-store.js";
40
+ import { _resetBackend } from "../security/secure-keys.js";
32
41
 
33
- const TEST_DIR = join(tmpdir(), `vellum-broker-fill-test-${randomBytes(4).toString('hex')}`);
34
- const STORE_PATH = join(TEST_DIR, 'keys.enc');
42
+ const TEST_DIR = join(
43
+ tmpdir(),
44
+ `vellum-broker-fill-test-${randomBytes(4).toString("hex")}`,
45
+ );
46
+ const STORE_PATH = join(TEST_DIR, "keys.enc");
35
47
 
36
48
  // ---------------------------------------------------------------------------
37
49
  // Mock registry to avoid double-registration
38
50
  // ---------------------------------------------------------------------------
39
51
 
40
- mock.module('../tools/registry.js', () => ({
52
+ mock.module("../tools/registry.js", () => ({
41
53
  registerTool: () => {},
42
54
  }));
43
55
 
@@ -45,20 +57,25 @@ mock.module('../tools/registry.js', () => ({
45
57
  // Imports under test
46
58
  // ---------------------------------------------------------------------------
47
59
 
48
- import { setSecureKey } from '../security/secure-keys.js';
49
- import { CredentialBroker } from '../tools/credentials/broker.js';
50
- import { _setMetadataPath,upsertCredentialMetadata } from '../tools/credentials/metadata-store.js';
60
+ import { setSecureKey } from "../security/secure-keys.js";
61
+ import { CredentialBroker } from "../tools/credentials/broker.js";
62
+ import {
63
+ _setMetadataPath,
64
+ upsertCredentialMetadata,
65
+ } from "../tools/credentials/metadata-store.js";
51
66
 
52
- afterAll(() => { mock.restore(); });
67
+ afterAll(() => {
68
+ mock.restore();
69
+ });
53
70
 
54
- describe('CredentialBroker.browserFill', () => {
71
+ describe("CredentialBroker.browserFill", () => {
55
72
  let broker: CredentialBroker;
56
73
 
57
74
  beforeEach(() => {
58
75
  mkdirSync(TEST_DIR, { recursive: true });
59
76
  _setStorePath(STORE_PATH);
60
77
  _resetBackend();
61
- _setMetadataPath(join(TEST_DIR, 'metadata.json'));
78
+ _setMetadataPath(join(TEST_DIR, "metadata.json"));
62
79
  broker = new CredentialBroker();
63
80
  });
64
81
 
@@ -69,344 +86,392 @@ describe('CredentialBroker.browserFill', () => {
69
86
  rmSync(TEST_DIR, { recursive: true, force: true });
70
87
  });
71
88
 
72
- test('fills successfully when credential exists', async () => {
73
- upsertCredentialMetadata('github', 'token', { allowedTools: ['browser_fill_credential'] });
74
- setSecureKey('credential:github:token', 'ghp_secret123');
89
+ test("fills successfully when credential exists", async () => {
90
+ upsertCredentialMetadata("github", "token", {
91
+ allowedTools: ["browser_fill_credential"],
92
+ });
93
+ setSecureKey("credential:github:token", "ghp_secret123");
75
94
 
76
95
  let filledValue: string | undefined;
77
96
  const result = await broker.browserFill({
78
- service: 'github',
79
- field: 'token',
80
- toolName: 'browser_fill_credential',
81
- fill: async (value) => { filledValue = value; },
97
+ service: "github",
98
+ field: "token",
99
+ toolName: "browser_fill_credential",
100
+ fill: async (value) => {
101
+ filledValue = value;
102
+ },
82
103
  });
83
104
 
84
105
  expect(result.success).toBe(true);
85
106
  expect(result.reason).toBeUndefined();
86
107
  // The fill callback received the plaintext
87
- expect(filledValue).toBe('ghp_secret123');
108
+ expect(filledValue).toBe("ghp_secret123");
88
109
  });
89
110
 
90
- test('returns metadata-only result (no plaintext in return value)', async () => {
91
- upsertCredentialMetadata('github', 'token', { allowedTools: ['browser_fill_credential'] });
92
- setSecureKey('credential:github:token', 'ghp_secret123');
111
+ test("returns metadata-only result (no plaintext in return value)", async () => {
112
+ upsertCredentialMetadata("github", "token", {
113
+ allowedTools: ["browser_fill_credential"],
114
+ });
115
+ setSecureKey("credential:github:token", "ghp_secret123");
93
116
 
94
117
  const result = await broker.browserFill({
95
- service: 'github',
96
- field: 'token',
97
- toolName: 'browser_fill_credential',
118
+ service: "github",
119
+ field: "token",
120
+ toolName: "browser_fill_credential",
98
121
  fill: async () => {},
99
122
  });
100
123
 
101
124
  // Result has no plaintext value — only success/failure metadata
102
125
  expect(result).toEqual({ success: true });
103
- expect('value' in result).toBe(false);
104
- expect('storageKey' in result).toBe(false);
126
+ expect("value" in result).toBe(false);
127
+ expect("storageKey" in result).toBe(false);
105
128
  });
106
129
 
107
- test('fails when no credential metadata exists', async () => {
130
+ test("fails when no credential metadata exists", async () => {
108
131
  const result = await broker.browserFill({
109
- service: 'nonexistent',
110
- field: 'token',
111
- toolName: 'browser_fill_credential',
112
- fill: async () => { throw new Error('should not be called'); },
132
+ service: "nonexistent",
133
+ field: "token",
134
+ toolName: "browser_fill_credential",
135
+ fill: async () => {
136
+ throw new Error("should not be called");
137
+ },
113
138
  });
114
139
 
115
140
  expect(result.success).toBe(false);
116
- expect(result.reason).toContain('No credential found');
117
- expect(result.reason).toContain('nonexistent/token');
141
+ expect(result.reason).toContain("No credential found");
142
+ expect(result.reason).toContain("nonexistent/token");
118
143
  });
119
144
 
120
- test('fails when metadata exists but no stored secret value', async () => {
121
- upsertCredentialMetadata('github', 'token', { allowedTools: ['browser_fill_credential'] });
145
+ test("fails when metadata exists but no stored secret value", async () => {
146
+ upsertCredentialMetadata("github", "token", {
147
+ allowedTools: ["browser_fill_credential"],
148
+ });
122
149
  // No setSecureKey call — metadata exists but value doesn't
123
150
 
124
151
  const result = await broker.browserFill({
125
- service: 'github',
126
- field: 'token',
127
- toolName: 'browser_fill_credential',
128
- fill: async () => { throw new Error('should not be called'); },
152
+ service: "github",
153
+ field: "token",
154
+ toolName: "browser_fill_credential",
155
+ fill: async () => {
156
+ throw new Error("should not be called");
157
+ },
129
158
  });
130
159
 
131
160
  expect(result.success).toBe(false);
132
- expect(result.reason).toContain('no stored value');
161
+ expect(result.reason).toContain("no stored value");
133
162
  });
134
163
 
135
- test('returns failure when fill callback throws', async () => {
136
- upsertCredentialMetadata('github', 'token', { allowedTools: ['browser_fill_credential'] });
137
- setSecureKey('credential:github:token', 'ghp_secret123');
164
+ test("returns failure when fill callback throws", async () => {
165
+ upsertCredentialMetadata("github", "token", {
166
+ allowedTools: ["browser_fill_credential"],
167
+ });
168
+ setSecureKey("credential:github:token", "ghp_secret123");
138
169
 
139
170
  const result = await broker.browserFill({
140
- service: 'github',
141
- field: 'token',
142
- toolName: 'browser_fill_credential',
143
- fill: async () => { throw new Error('Element not found'); },
171
+ service: "github",
172
+ field: "token",
173
+ toolName: "browser_fill_credential",
174
+ fill: async () => {
175
+ throw new Error("Element not found");
176
+ },
144
177
  });
145
178
 
146
179
  expect(result.success).toBe(false);
147
- expect(result.reason).toContain('Fill operation failed');
180
+ expect(result.reason).toContain("Fill operation failed");
148
181
  // The broker intentionally returns a generic error — the original error
149
182
  // message is NOT included because it could embed the credential value,
150
183
  // leaking plaintext outside the broker's trust boundary.
151
- expect(result.reason).not.toContain('Element not found');
184
+ expect(result.reason).not.toContain("Element not found");
152
185
  });
153
186
 
154
- test('handles multiple fills with different credentials', async () => {
155
- upsertCredentialMetadata('github', 'username', { allowedTools: ['browser_fill_credential'] });
156
- upsertCredentialMetadata('github', 'password', { allowedTools: ['browser_fill_credential'] });
157
- setSecureKey('credential:github:username', 'octocat');
158
- setSecureKey('credential:github:password', 'hunter2');
187
+ test("handles multiple fills with different credentials", async () => {
188
+ upsertCredentialMetadata("github", "username", {
189
+ allowedTools: ["browser_fill_credential"],
190
+ });
191
+ upsertCredentialMetadata("github", "password", {
192
+ allowedTools: ["browser_fill_credential"],
193
+ });
194
+ setSecureKey("credential:github:username", "octocat");
195
+ setSecureKey("credential:github:password", "hunter2");
159
196
 
160
197
  const filled: Record<string, string> = {};
161
198
 
162
199
  const r1 = await broker.browserFill({
163
- service: 'github',
164
- field: 'username',
165
- toolName: 'browser_fill_credential',
166
- fill: async (v) => { filled.username = v; },
200
+ service: "github",
201
+ field: "username",
202
+ toolName: "browser_fill_credential",
203
+ fill: async (v) => {
204
+ filled.username = v;
205
+ },
167
206
  });
168
207
 
169
208
  const r2 = await broker.browserFill({
170
- service: 'github',
171
- field: 'password',
172
- toolName: 'browser_fill_credential',
173
- fill: async (v) => { filled.password = v; },
209
+ service: "github",
210
+ field: "password",
211
+ toolName: "browser_fill_credential",
212
+ fill: async (v) => {
213
+ filled.password = v;
214
+ },
174
215
  });
175
216
 
176
217
  expect(r1.success).toBe(true);
177
218
  expect(r2.success).toBe(true);
178
- expect(filled.username).toBe('octocat');
179
- expect(filled.password).toBe('hunter2');
219
+ expect(filled.username).toBe("octocat");
220
+ expect(filled.password).toBe("hunter2");
180
221
  });
181
222
 
182
- test('allows fill when domain matches allowedDomains', async () => {
183
- upsertCredentialMetadata('github', 'token', {
184
- allowedTools: ['browser_fill_credential'],
185
- allowedDomains: ['github.com'],
223
+ test("allows fill when domain matches allowedDomains", async () => {
224
+ upsertCredentialMetadata("github", "token", {
225
+ allowedTools: ["browser_fill_credential"],
226
+ allowedDomains: ["github.com"],
186
227
  });
187
- setSecureKey('credential:github:token', 'ghp_secret123');
228
+ setSecureKey("credential:github:token", "ghp_secret123");
188
229
 
189
230
  const result = await broker.browserFill({
190
- service: 'github',
191
- field: 'token',
192
- toolName: 'browser_fill_credential',
193
- domain: 'github.com',
231
+ service: "github",
232
+ field: "token",
233
+ toolName: "browser_fill_credential",
234
+ domain: "github.com",
194
235
  fill: async () => {},
195
236
  });
196
237
 
197
238
  expect(result.success).toBe(true);
198
239
  });
199
240
 
200
- test('allows fill on subdomain when registrable domain matches', async () => {
201
- upsertCredentialMetadata('github', 'token', {
202
- allowedTools: ['browser_fill_credential'],
203
- allowedDomains: ['github.com'],
241
+ test("allows fill on subdomain when registrable domain matches", async () => {
242
+ upsertCredentialMetadata("github", "token", {
243
+ allowedTools: ["browser_fill_credential"],
244
+ allowedDomains: ["github.com"],
204
245
  });
205
- setSecureKey('credential:github:token', 'ghp_secret123');
246
+ setSecureKey("credential:github:token", "ghp_secret123");
206
247
 
207
248
  const result = await broker.browserFill({
208
- service: 'github',
209
- field: 'token',
210
- toolName: 'browser_fill_credential',
211
- domain: 'login.github.com',
249
+ service: "github",
250
+ field: "token",
251
+ toolName: "browser_fill_credential",
252
+ domain: "login.github.com",
212
253
  fill: async () => {},
213
254
  });
214
255
 
215
256
  expect(result.success).toBe(true);
216
257
  });
217
258
 
218
- test('denies fill when domain does not match allowedDomains', async () => {
219
- upsertCredentialMetadata('github', 'token', {
220
- allowedTools: ['browser_fill_credential'],
221
- allowedDomains: ['github.com'],
259
+ test("denies fill when domain does not match allowedDomains", async () => {
260
+ upsertCredentialMetadata("github", "token", {
261
+ allowedTools: ["browser_fill_credential"],
262
+ allowedDomains: ["github.com"],
222
263
  });
223
- setSecureKey('credential:github:token', 'ghp_secret123');
264
+ setSecureKey("credential:github:token", "ghp_secret123");
224
265
 
225
266
  const result = await broker.browserFill({
226
- service: 'github',
227
- field: 'token',
228
- toolName: 'browser_fill_credential',
229
- domain: 'evil.com',
230
- fill: async () => { throw new Error('should not be called'); },
267
+ service: "github",
268
+ field: "token",
269
+ toolName: "browser_fill_credential",
270
+ domain: "evil.com",
271
+ fill: async () => {
272
+ throw new Error("should not be called");
273
+ },
231
274
  });
232
275
 
233
276
  expect(result.success).toBe(false);
234
- expect(result.reason).toContain('not allowed');
235
- expect(result.reason).toContain('evil.com');
236
- expect(result.reason).toContain('github.com');
277
+ expect(result.reason).toContain("not allowed");
278
+ expect(result.reason).toContain("evil.com");
279
+ expect(result.reason).toContain("github.com");
237
280
  });
238
281
 
239
- test('denies fill when domain policy exists but no domain provided', async () => {
240
- upsertCredentialMetadata('github', 'token', {
241
- allowedTools: ['browser_fill_credential'],
242
- allowedDomains: ['github.com'],
282
+ test("denies fill when domain policy exists but no domain provided", async () => {
283
+ upsertCredentialMetadata("github", "token", {
284
+ allowedTools: ["browser_fill_credential"],
285
+ allowedDomains: ["github.com"],
243
286
  });
244
- setSecureKey('credential:github:token', 'ghp_secret123');
287
+ setSecureKey("credential:github:token", "ghp_secret123");
245
288
 
246
289
  const result = await broker.browserFill({
247
- service: 'github',
248
- field: 'token',
249
- toolName: 'browser_fill_credential',
250
- fill: async () => { throw new Error('should not be called'); },
290
+ service: "github",
291
+ field: "token",
292
+ toolName: "browser_fill_credential",
293
+ fill: async () => {
294
+ throw new Error("should not be called");
295
+ },
251
296
  });
252
297
 
253
298
  expect(result.success).toBe(false);
254
- expect(result.reason).toContain('no page domain was provided');
299
+ expect(result.reason).toContain("no page domain was provided");
255
300
  });
256
301
 
257
- test('skips domain check when allowedDomains is empty', async () => {
258
- upsertCredentialMetadata('github', 'token', { allowedTools: ['browser_fill_credential'] });
259
- setSecureKey('credential:github:token', 'ghp_secret123');
302
+ test("skips domain check when allowedDomains is empty", async () => {
303
+ upsertCredentialMetadata("github", "token", {
304
+ allowedTools: ["browser_fill_credential"],
305
+ });
306
+ setSecureKey("credential:github:token", "ghp_secret123");
260
307
 
261
308
  // No domain provided and no allowedDomains policy — should succeed
262
309
  const result = await broker.browserFill({
263
- service: 'github',
264
- field: 'token',
265
- toolName: 'browser_fill_credential',
310
+ service: "github",
311
+ field: "token",
312
+ toolName: "browser_fill_credential",
266
313
  fill: async () => {},
267
314
  });
268
315
 
269
316
  expect(result.success).toBe(true);
270
317
  });
271
318
 
272
- test('denies fill when tool is not in allowedTools', async () => {
273
- upsertCredentialMetadata('github', 'token', { allowedTools: ['other_tool'] });
274
- setSecureKey('credential:github:token', 'ghp_secret123');
319
+ test("denies fill when tool is not in allowedTools", async () => {
320
+ upsertCredentialMetadata("github", "token", {
321
+ allowedTools: ["other_tool"],
322
+ });
323
+ setSecureKey("credential:github:token", "ghp_secret123");
275
324
 
276
325
  let fillCalled = false;
277
326
  const result = await broker.browserFill({
278
- service: 'github',
279
- field: 'token',
280
- toolName: 'browser_fill_credential',
281
- fill: async () => { fillCalled = true; },
327
+ service: "github",
328
+ field: "token",
329
+ toolName: "browser_fill_credential",
330
+ fill: async () => {
331
+ fillCalled = true;
332
+ },
282
333
  });
283
334
 
284
335
  expect(result.success).toBe(false);
285
- expect(result.reason).toContain('not allowed');
286
- expect(result.reason).toContain('browser_fill_credential');
336
+ expect(result.reason).toContain("not allowed");
337
+ expect(result.reason).toContain("browser_fill_credential");
287
338
  // Fill callback must not be invoked when policy denies
288
339
  expect(fillCalled).toBe(false);
289
340
  });
290
341
 
291
- test('denies fill when allowedTools is empty (fail-closed)', async () => {
292
- upsertCredentialMetadata('github', 'token', { allowedTools: [] });
293
- setSecureKey('credential:github:token', 'ghp_secret123');
342
+ test("denies fill when allowedTools is empty (fail-closed)", async () => {
343
+ upsertCredentialMetadata("github", "token", { allowedTools: [] });
344
+ setSecureKey("credential:github:token", "ghp_secret123");
294
345
 
295
346
  const result = await broker.browserFill({
296
- service: 'github',
297
- field: 'token',
298
- toolName: 'browser_fill_credential',
299
- fill: async () => { throw new Error('should not be called'); },
347
+ service: "github",
348
+ field: "token",
349
+ toolName: "browser_fill_credential",
350
+ fill: async () => {
351
+ throw new Error("should not be called");
352
+ },
300
353
  });
301
354
 
302
355
  expect(result.success).toBe(false);
303
- expect(result.reason).toContain('No tools are currently allowed');
356
+ expect(result.reason).toContain("No tools are currently allowed");
304
357
  });
305
358
 
306
- test('fill callback error does not leak plaintext in result', async () => {
307
- upsertCredentialMetadata('github', 'token', { allowedTools: ['browser_fill_credential'] });
308
- setSecureKey('credential:github:token', 'ghp_supersecret');
359
+ test("fill callback error does not leak plaintext in result", async () => {
360
+ upsertCredentialMetadata("github", "token", {
361
+ allowedTools: ["browser_fill_credential"],
362
+ });
363
+ setSecureKey("credential:github:token", "ghp_supersecret");
309
364
 
310
365
  const result = await broker.browserFill({
311
- service: 'github',
312
- field: 'token',
313
- toolName: 'browser_fill_credential',
314
- fill: async () => { throw new Error('timeout'); },
366
+ service: "github",
367
+ field: "token",
368
+ toolName: "browser_fill_credential",
369
+ fill: async () => {
370
+ throw new Error("timeout");
371
+ },
315
372
  });
316
373
 
317
374
  expect(result.success).toBe(false);
318
375
  // Ensure the secret value doesn't appear in the error result
319
- expect(JSON.stringify(result)).not.toContain('ghp_supersecret');
376
+ expect(JSON.stringify(result)).not.toContain("ghp_supersecret");
320
377
  });
321
378
 
322
379
  // ---------------------------------------------------------------------------
323
380
  // Baseline: tool/domain policy mismatch deny behavior
324
381
  // ---------------------------------------------------------------------------
325
382
 
326
- describe('baseline — tool/domain policy mismatch deny', () => {
327
- test('denies tool not in multi-tool allowlist and enumerates allowed tools', async () => {
328
- upsertCredentialMetadata('aws', 'access_key', {
329
- allowedTools: ['s3_upload', 'cloudfront_invalidate'],
383
+ describe("baseline — tool/domain policy mismatch deny", () => {
384
+ test("denies tool not in multi-tool allowlist and enumerates allowed tools", async () => {
385
+ upsertCredentialMetadata("aws", "access_key", {
386
+ allowedTools: ["s3_upload", "cloudfront_invalidate"],
330
387
  allowedDomains: [],
331
388
  });
332
- setSecureKey('credential:aws:access_key', 'AKIA_test');
389
+ setSecureKey("credential:aws:access_key", "AKIA_test");
333
390
 
334
391
  let fillCalled = false;
335
392
  const result = await broker.browserFill({
336
- service: 'aws',
337
- field: 'access_key',
338
- toolName: 'browser_fill_credential',
339
- fill: async () => { fillCalled = true; },
393
+ service: "aws",
394
+ field: "access_key",
395
+ toolName: "browser_fill_credential",
396
+ fill: async () => {
397
+ fillCalled = true;
398
+ },
340
399
  });
341
400
 
342
401
  expect(result.success).toBe(false);
343
- expect(result.reason).toContain('browser_fill_credential');
344
- expect(result.reason).toContain('not allowed');
345
- expect(result.reason).toContain('s3_upload');
346
- expect(result.reason).toContain('cloudfront_invalidate');
402
+ expect(result.reason).toContain("browser_fill_credential");
403
+ expect(result.reason).toContain("not allowed");
404
+ expect(result.reason).toContain("s3_upload");
405
+ expect(result.reason).toContain("cloudfront_invalidate");
347
406
  expect(fillCalled).toBe(false);
348
407
  });
349
408
 
350
- test('denies when tool matches but domain does not', async () => {
351
- upsertCredentialMetadata('github', 'pat', {
352
- allowedTools: ['browser_fill_credential'],
353
- allowedDomains: ['github.com'],
409
+ test("denies when tool matches but domain does not", async () => {
410
+ upsertCredentialMetadata("github", "pat", {
411
+ allowedTools: ["browser_fill_credential"],
412
+ allowedDomains: ["github.com"],
354
413
  });
355
- setSecureKey('credential:github:pat', 'ghp_fill_test');
414
+ setSecureKey("credential:github:pat", "ghp_fill_test");
356
415
 
357
416
  let fillCalled = false;
358
417
  const result = await broker.browserFill({
359
- service: 'github',
360
- field: 'pat',
361
- toolName: 'browser_fill_credential',
362
- domain: 'phishing-github.com',
363
- fill: async () => { fillCalled = true; },
418
+ service: "github",
419
+ field: "pat",
420
+ toolName: "browser_fill_credential",
421
+ domain: "phishing-github.com",
422
+ fill: async () => {
423
+ fillCalled = true;
424
+ },
364
425
  });
365
426
 
366
427
  expect(result.success).toBe(false);
367
- expect(result.reason).toContain('phishing-github.com');
368
- expect(result.reason).toContain('not allowed');
428
+ expect(result.reason).toContain("phishing-github.com");
429
+ expect(result.reason).toContain("not allowed");
369
430
  expect(fillCalled).toBe(false);
370
431
  });
371
432
 
372
- test('denies when both tool and domain mismatch — tool check runs first', async () => {
373
- upsertCredentialMetadata('slack', 'bot_token', {
374
- allowedTools: ['slack_post'],
375
- allowedDomains: ['slack.com'],
433
+ test("denies when both tool and domain mismatch — tool check runs first", async () => {
434
+ upsertCredentialMetadata("slack", "bot_token", {
435
+ allowedTools: ["slack_post"],
436
+ allowedDomains: ["slack.com"],
376
437
  });
377
- setSecureKey('credential:slack:bot_token', 'xoxb-test');
438
+ setSecureKey("credential:slack:bot_token", "xoxb-test");
378
439
 
379
440
  const result = await broker.browserFill({
380
- service: 'slack',
381
- field: 'bot_token',
382
- toolName: 'browser_fill_credential',
383
- domain: 'evil.com',
384
- fill: async () => { throw new Error('should not be called'); },
441
+ service: "slack",
442
+ field: "bot_token",
443
+ toolName: "browser_fill_credential",
444
+ domain: "evil.com",
445
+ fill: async () => {
446
+ throw new Error("should not be called");
447
+ },
385
448
  });
386
449
 
387
450
  expect(result.success).toBe(false);
388
451
  // Tool policy is evaluated before domain policy, so the denial
389
452
  // mentions the tool name, not the domain
390
- expect(result.reason).toContain('browser_fill_credential');
391
- expect(result.reason).toContain('not allowed');
453
+ expect(result.reason).toContain("browser_fill_credential");
454
+ expect(result.reason).toContain("not allowed");
392
455
  });
393
456
 
394
- test('denies with empty allowedTools and suggests credential_store', async () => {
395
- upsertCredentialMetadata('custom', 'key', {
457
+ test("denies with empty allowedTools and suggests credential_store", async () => {
458
+ upsertCredentialMetadata("custom", "key", {
396
459
  allowedTools: [],
397
460
  });
398
- setSecureKey('credential:custom:key', 'secret');
461
+ setSecureKey("credential:custom:key", "secret");
399
462
 
400
463
  const result = await broker.browserFill({
401
- service: 'custom',
402
- field: 'key',
403
- toolName: 'browser_fill_credential',
404
- fill: async () => { throw new Error('should not be called'); },
464
+ service: "custom",
465
+ field: "key",
466
+ toolName: "browser_fill_credential",
467
+ fill: async () => {
468
+ throw new Error("should not be called");
469
+ },
405
470
  });
406
471
 
407
472
  expect(result.success).toBe(false);
408
- expect(result.reason).toContain('No tools are currently allowed');
409
- expect(result.reason).toContain('credential_store');
473
+ expect(result.reason).toContain("No tools are currently allowed");
474
+ expect(result.reason).toContain("credential_store");
410
475
  });
411
476
  });
412
477
 
@@ -414,105 +479,115 @@ describe('CredentialBroker.browserFill', () => {
414
479
  // Baseline: service/field uniqueness assumptions
415
480
  // ---------------------------------------------------------------------------
416
481
 
417
- describe('baseline — service/field uniqueness', () => {
418
- test('upsert overwrites metadata for same service+field pair', async () => {
419
- upsertCredentialMetadata('github', 'token', {
420
- allowedTools: ['other_tool'],
482
+ describe("baseline — service/field uniqueness", () => {
483
+ test("upsert overwrites metadata for same service+field pair", async () => {
484
+ upsertCredentialMetadata("github", "token", {
485
+ allowedTools: ["other_tool"],
421
486
  });
422
487
  // Second upsert updates the same record
423
- upsertCredentialMetadata('github', 'token', {
424
- allowedTools: ['browser_fill_credential'],
488
+ upsertCredentialMetadata("github", "token", {
489
+ allowedTools: ["browser_fill_credential"],
425
490
  });
426
- setSecureKey('credential:github:token', 'ghp_updated');
491
+ setSecureKey("credential:github:token", "ghp_updated");
427
492
 
428
493
  let filledValue: string | undefined;
429
494
  const result = await broker.browserFill({
430
- service: 'github',
431
- field: 'token',
432
- toolName: 'browser_fill_credential',
433
- fill: async (v) => { filledValue = v; },
495
+ service: "github",
496
+ field: "token",
497
+ toolName: "browser_fill_credential",
498
+ fill: async (v) => {
499
+ filledValue = v;
500
+ },
434
501
  });
435
502
 
436
503
  // The second upsert's policy should be in effect
437
504
  expect(result.success).toBe(true);
438
- expect(filledValue).toBe('ghp_updated');
505
+ expect(filledValue).toBe("ghp_updated");
439
506
  });
440
507
 
441
- test('same service with different fields are independent credentials', async () => {
442
- upsertCredentialMetadata('github', 'username', {
443
- allowedTools: ['browser_fill_credential'],
508
+ test("same service with different fields are independent credentials", async () => {
509
+ upsertCredentialMetadata("github", "username", {
510
+ allowedTools: ["browser_fill_credential"],
444
511
  });
445
- upsertCredentialMetadata('github', 'password', {
446
- allowedTools: ['other_tool'],
512
+ upsertCredentialMetadata("github", "password", {
513
+ allowedTools: ["other_tool"],
447
514
  });
448
- setSecureKey('credential:github:username', 'octocat');
449
- setSecureKey('credential:github:password', 'hunter2');
515
+ setSecureKey("credential:github:username", "octocat");
516
+ setSecureKey("credential:github:password", "hunter2");
450
517
 
451
518
  // username allows browser_fill_credential
452
519
  const r1 = await broker.browserFill({
453
- service: 'github',
454
- field: 'username',
455
- toolName: 'browser_fill_credential',
520
+ service: "github",
521
+ field: "username",
522
+ toolName: "browser_fill_credential",
456
523
  fill: async () => {},
457
524
  });
458
525
  expect(r1.success).toBe(true);
459
526
 
460
527
  // password does NOT allow browser_fill_credential
461
528
  const r2 = await broker.browserFill({
462
- service: 'github',
463
- field: 'password',
464
- toolName: 'browser_fill_credential',
465
- fill: async () => { throw new Error('should not be called'); },
529
+ service: "github",
530
+ field: "password",
531
+ toolName: "browser_fill_credential",
532
+ fill: async () => {
533
+ throw new Error("should not be called");
534
+ },
466
535
  });
467
536
  expect(r2.success).toBe(false);
468
- expect(r2.reason).toContain('not allowed');
537
+ expect(r2.reason).toContain("not allowed");
469
538
  });
470
539
 
471
- test('different services with same field name are independent', async () => {
472
- upsertCredentialMetadata('github', 'token', {
473
- allowedTools: ['browser_fill_credential'],
474
- allowedDomains: ['github.com'],
540
+ test("different services with same field name are independent", async () => {
541
+ upsertCredentialMetadata("github", "token", {
542
+ allowedTools: ["browser_fill_credential"],
543
+ allowedDomains: ["github.com"],
475
544
  });
476
- upsertCredentialMetadata('gitlab', 'token', {
477
- allowedTools: ['browser_fill_credential'],
478
- allowedDomains: ['gitlab.com'],
545
+ upsertCredentialMetadata("gitlab", "token", {
546
+ allowedTools: ["browser_fill_credential"],
547
+ allowedDomains: ["gitlab.com"],
479
548
  });
480
- setSecureKey('credential:github:token', 'gh_tok');
481
- setSecureKey('credential:gitlab:token', 'gl_tok');
549
+ setSecureKey("credential:github:token", "gh_tok");
550
+ setSecureKey("credential:gitlab:token", "gl_tok");
482
551
 
483
552
  // github credential on github.com succeeds
484
- let filled1 = '';
553
+ let filled1 = "";
485
554
  const r1 = await broker.browserFill({
486
- service: 'github',
487
- field: 'token',
488
- toolName: 'browser_fill_credential',
489
- domain: 'github.com',
490
- fill: async (v) => { filled1 = v; },
555
+ service: "github",
556
+ field: "token",
557
+ toolName: "browser_fill_credential",
558
+ domain: "github.com",
559
+ fill: async (v) => {
560
+ filled1 = v;
561
+ },
491
562
  });
492
563
  expect(r1.success).toBe(true);
493
- expect(filled1).toBe('gh_tok');
564
+ expect(filled1).toBe("gh_tok");
494
565
 
495
566
  // github credential on gitlab.com fails (domain mismatch)
496
567
  const r2 = await broker.browserFill({
497
- service: 'github',
498
- field: 'token',
499
- toolName: 'browser_fill_credential',
500
- domain: 'gitlab.com',
501
- fill: async () => { throw new Error('should not be called'); },
568
+ service: "github",
569
+ field: "token",
570
+ toolName: "browser_fill_credential",
571
+ domain: "gitlab.com",
572
+ fill: async () => {
573
+ throw new Error("should not be called");
574
+ },
502
575
  });
503
576
  expect(r2.success).toBe(false);
504
577
 
505
578
  // gitlab credential on gitlab.com succeeds with its own value
506
- let filled3 = '';
579
+ let filled3 = "";
507
580
  const r3 = await broker.browserFill({
508
- service: 'gitlab',
509
- field: 'token',
510
- toolName: 'browser_fill_credential',
511
- domain: 'gitlab.com',
512
- fill: async (v) => { filled3 = v; },
581
+ service: "gitlab",
582
+ field: "token",
583
+ toolName: "browser_fill_credential",
584
+ domain: "gitlab.com",
585
+ fill: async (v) => {
586
+ filled3 = v;
587
+ },
513
588
  });
514
589
  expect(r3.success).toBe(true);
515
- expect(filled3).toBe('gl_tok');
590
+ expect(filled3).toBe("gl_tok");
516
591
  });
517
592
  });
518
593
  });