@vellumai/assistant 0.4.16 → 0.4.18

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