@vellumai/assistant 0.4.16 → 0.4.18

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