@vellumai/assistant 0.4.17 → 0.4.19

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