@vellumai/assistant 0.4.17 → 0.4.18

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