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