@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,28 +1,39 @@
1
- import { existsSync, mkdirSync, readFileSync,rmSync } from 'node:fs';
2
- import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
1
+ import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
4
5
 
5
- import { afterEach, beforeEach, describe, expect, mock,test } from 'bun:test';
6
-
7
- import { _resetAppGitState } from '../memory/app-git-service.js';
8
- import { _resetGitServiceRegistry } from '../workspace/git-service.js';
6
+ import { _resetAppGitState } from "../memory/app-git-service.js";
7
+ import { _resetGitServiceRegistry } from "../workspace/git-service.js";
9
8
 
10
9
  // Mock getDataDir to use a temp directory
11
10
  let testDataDir: string;
12
11
 
13
- mock.module('../util/platform.js', () => ({
12
+ mock.module("../util/platform.js", () => ({
14
13
  getDataDir: () => testDataDir,
15
14
  getProjectDir: () => testDataDir,
16
15
  }));
17
16
 
18
17
  // Re-import after mocking so modules use our temp dir
19
- const { createApp, updateApp, getAppsDir } = await import('../memory/app-store.js');
20
- const { getAppHistory, getAppDiff, getAppFileAtVersion, restoreAppVersion, commitAppTurnChanges } = await import('../memory/app-git-service.js');
21
-
22
- describe('App Git History', () => {
18
+ const { createApp, updateApp, getAppsDir } =
19
+ await import("../memory/app-store.js");
20
+ const {
21
+ getAppHistory,
22
+ getAppDiff,
23
+ getAppFileAtVersion,
24
+ restoreAppVersion,
25
+ commitAppTurnChanges,
26
+ } = await import("../memory/app-git-service.js");
27
+
28
+ describe("App Git History", () => {
23
29
  beforeEach(() => {
24
- testDataDir = join(tmpdir(), `vellum-app-git-history-${Date.now()}-${Math.random().toString(36).slice(2)}`);
25
- mkdirSync(join(testDataDir, 'apps'), { recursive: true });
30
+ testDataDir = join(
31
+ tmpdir(),
32
+ `vellum-app-git-history-${Date.now()}-${Math.random()
33
+ .toString(36)
34
+ .slice(2)}`,
35
+ );
36
+ mkdirSync(join(testDataDir, "apps"), { recursive: true });
26
37
  _resetGitServiceRegistry();
27
38
  _resetAppGitState();
28
39
  });
@@ -33,38 +44,38 @@ describe('App Git History', () => {
33
44
  }
34
45
  });
35
46
 
36
- test('getAppHistory returns commits for a specific app', async () => {
47
+ test("getAppHistory returns commits for a specific app", async () => {
37
48
  const app = createApp({
38
- name: 'History App',
39
- schemaJson: '{}',
40
- htmlDefinition: '<h1>v1</h1>',
49
+ name: "History App",
50
+ schemaJson: "{}",
51
+ htmlDefinition: "<h1>v1</h1>",
41
52
  });
42
- await commitAppTurnChanges('session-1', 1);
53
+ await commitAppTurnChanges("session-1", 1);
43
54
 
44
- updateApp(app.id, { htmlDefinition: '<h1>v2</h1>' });
45
- await commitAppTurnChanges('session-1', 2);
55
+ updateApp(app.id, { htmlDefinition: "<h1>v2</h1>" });
56
+ await commitAppTurnChanges("session-1", 2);
46
57
 
47
58
  const history = await getAppHistory(app.id);
48
59
  expect(history.length).toBeGreaterThanOrEqual(2);
49
- expect(history[0].message).toContain('Turn 2');
60
+ expect(history[0].message).toContain("Turn 2");
50
61
  expect(history[0].commitHash).toMatch(/^[0-9a-f]+$/);
51
62
  expect(history[0].timestamp).toBeGreaterThan(0);
52
63
  });
53
64
 
54
- test('getAppHistory does not return commits for other apps', async () => {
65
+ test("getAppHistory does not return commits for other apps", async () => {
55
66
  const app1 = createApp({
56
- name: 'App One',
57
- schemaJson: '{}',
58
- htmlDefinition: '<p>one</p>',
67
+ name: "App One",
68
+ schemaJson: "{}",
69
+ htmlDefinition: "<p>one</p>",
59
70
  });
60
- await commitAppTurnChanges('session-1', 1);
71
+ await commitAppTurnChanges("session-1", 1);
61
72
 
62
73
  const app2 = createApp({
63
- name: 'App Two',
64
- schemaJson: '{}',
65
- htmlDefinition: '<p>two</p>',
74
+ name: "App Two",
75
+ schemaJson: "{}",
76
+ htmlDefinition: "<p>two</p>",
66
77
  });
67
- await commitAppTurnChanges('session-1', 2);
78
+ await commitAppTurnChanges("session-1", 2);
68
79
 
69
80
  const history1 = await getAppHistory(app1.id);
70
81
  const history2 = await getAppHistory(app2.id);
@@ -77,97 +88,103 @@ describe('App Git History', () => {
77
88
  // (turn 2 created app2, so app2 history should not have turn 1 unless initial commit)
78
89
  });
79
90
 
80
- test('getAppHistory respects limit', async () => {
91
+ test("getAppHistory respects limit", async () => {
81
92
  const app = createApp({
82
- name: 'Limited App',
83
- schemaJson: '{}',
84
- htmlDefinition: '<p>v1</p>',
93
+ name: "Limited App",
94
+ schemaJson: "{}",
95
+ htmlDefinition: "<p>v1</p>",
85
96
  });
86
- await commitAppTurnChanges('session-1', 1);
97
+ await commitAppTurnChanges("session-1", 1);
87
98
 
88
- updateApp(app.id, { htmlDefinition: '<p>v2</p>' });
89
- await commitAppTurnChanges('session-1', 2);
99
+ updateApp(app.id, { htmlDefinition: "<p>v2</p>" });
100
+ await commitAppTurnChanges("session-1", 2);
90
101
 
91
- updateApp(app.id, { htmlDefinition: '<p>v3</p>' });
92
- await commitAppTurnChanges('session-1', 3);
102
+ updateApp(app.id, { htmlDefinition: "<p>v3</p>" });
103
+ await commitAppTurnChanges("session-1", 3);
93
104
 
94
105
  const limited = await getAppHistory(app.id, 2);
95
106
  expect(limited.length).toBe(2);
96
107
  });
97
108
 
98
- test('getAppDiff shows changes between versions', async () => {
109
+ test("getAppDiff shows changes between versions", async () => {
99
110
  const app = createApp({
100
- name: 'Diff App',
101
- schemaJson: '{}',
102
- htmlDefinition: '<p>original</p>',
111
+ name: "Diff App",
112
+ schemaJson: "{}",
113
+ htmlDefinition: "<p>original</p>",
103
114
  });
104
- await commitAppTurnChanges('session-1', 1);
115
+ await commitAppTurnChanges("session-1", 1);
105
116
 
106
117
  const history1 = await getAppHistory(app.id);
107
118
  const createHash = history1[0].commitHash;
108
119
 
109
- updateApp(app.id, { htmlDefinition: '<p>modified</p>' });
110
- await commitAppTurnChanges('session-1', 2);
120
+ updateApp(app.id, { htmlDefinition: "<p>modified</p>" });
121
+ await commitAppTurnChanges("session-1", 2);
111
122
 
112
123
  const history2 = await getAppHistory(app.id);
113
124
  const updateHash = history2[0].commitHash;
114
125
 
115
126
  const diff = await getAppDiff(app.id, createHash, updateHash);
116
- expect(diff).toContain('original');
117
- expect(diff).toContain('modified');
127
+ expect(diff).toContain("original");
128
+ expect(diff).toContain("modified");
118
129
  });
119
130
 
120
- test('getAppFileAtVersion returns file content at a specific commit', async () => {
131
+ test("getAppFileAtVersion returns file content at a specific commit", async () => {
121
132
  const app = createApp({
122
- name: 'File Version App',
123
- schemaJson: '{}',
124
- htmlDefinition: '<p>version one</p>',
133
+ name: "File Version App",
134
+ schemaJson: "{}",
135
+ htmlDefinition: "<p>version one</p>",
125
136
  });
126
- await commitAppTurnChanges('session-1', 1);
137
+ await commitAppTurnChanges("session-1", 1);
127
138
 
128
139
  const history1 = await getAppHistory(app.id);
129
140
  const v1Hash = history1[0].commitHash;
130
141
 
131
- updateApp(app.id, { htmlDefinition: '<p>version two</p>' });
132
- await commitAppTurnChanges('session-1', 2);
142
+ updateApp(app.id, { htmlDefinition: "<p>version two</p>" });
143
+ await commitAppTurnChanges("session-1", 2);
133
144
 
134
145
  // Get the file at v1 — should show old content
135
- const v1Content = await getAppFileAtVersion(app.id, 'index.html', v1Hash);
136
- expect(v1Content).toContain('version one');
137
- expect(v1Content).not.toContain('version two');
146
+ const v1Content = await getAppFileAtVersion(app.id, "index.html", v1Hash);
147
+ expect(v1Content).toContain("version one");
148
+ expect(v1Content).not.toContain("version two");
138
149
 
139
150
  // Current file should show new content
140
- const currentContent = readFileSync(join(getAppsDir(), app.id, 'index.html'), 'utf-8');
141
- expect(currentContent).toContain('version two');
151
+ const currentContent = readFileSync(
152
+ join(getAppsDir(), app.id, "index.html"),
153
+ "utf-8",
154
+ );
155
+ expect(currentContent).toContain("version two");
142
156
  });
143
157
 
144
- test('restoreAppVersion restores files and creates a new commit', async () => {
158
+ test("restoreAppVersion restores files and creates a new commit", async () => {
145
159
  const app = createApp({
146
- name: 'Restore App',
147
- schemaJson: '{}',
148
- htmlDefinition: '<p>original content</p>',
160
+ name: "Restore App",
161
+ schemaJson: "{}",
162
+ htmlDefinition: "<p>original content</p>",
149
163
  });
150
- await commitAppTurnChanges('session-1', 1);
164
+ await commitAppTurnChanges("session-1", 1);
151
165
 
152
166
  const history1 = await getAppHistory(app.id);
153
167
  const originalHash = history1[0].commitHash;
154
168
 
155
- updateApp(app.id, { htmlDefinition: '<p>new content</p>' });
156
- await commitAppTurnChanges('session-1', 2);
169
+ updateApp(app.id, { htmlDefinition: "<p>new content</p>" });
170
+ await commitAppTurnChanges("session-1", 2);
157
171
 
158
172
  // Verify current content is "new content"
159
- let current = readFileSync(join(getAppsDir(), app.id, 'index.html'), 'utf-8');
160
- expect(current).toContain('new content');
173
+ let current = readFileSync(
174
+ join(getAppsDir(), app.id, "index.html"),
175
+ "utf-8",
176
+ );
177
+ expect(current).toContain("new content");
161
178
 
162
179
  // Restore to original
163
180
  await restoreAppVersion(app.id, originalHash);
164
181
 
165
182
  // Verify content is restored
166
- current = readFileSync(join(getAppsDir(), app.id, 'index.html'), 'utf-8');
167
- expect(current).toContain('original content');
183
+ current = readFileSync(join(getAppsDir(), app.id, "index.html"), "utf-8");
184
+ expect(current).toContain("original content");
168
185
 
169
186
  // Verify a restore commit was created
170
187
  const history2 = await getAppHistory(app.id);
171
- expect(history2[0].message).toContain('Restore app');
188
+ expect(history2[0].message).toContain("Restore app");
172
189
  });
173
190
  });
@@ -1,28 +1,40 @@
1
- import { execFileSync } from 'node:child_process';
2
- import { existsSync, mkdirSync, readFileSync,rmSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
5
-
6
- import { afterEach, beforeEach, describe, expect, mock,test } from 'bun:test';
7
-
8
- import { _resetAppGitState,commitAppTurnChanges } from '../memory/app-git-service.js';
9
- import { _resetGitServiceRegistry } from '../workspace/git-service.js';
1
+ import { execFileSync } from "node:child_process";
2
+ import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
6
+
7
+ import {
8
+ _resetAppGitState,
9
+ commitAppTurnChanges,
10
+ } from "../memory/app-git-service.js";
11
+ import { _resetGitServiceRegistry } from "../workspace/git-service.js";
10
12
 
11
13
  // Mock getDataDir to use a temp directory
12
14
  let testDataDir: string;
13
15
 
14
- mock.module('../util/platform.js', () => ({
16
+ mock.module("../util/platform.js", () => ({
15
17
  getDataDir: () => testDataDir,
16
18
  getProjectDir: () => testDataDir,
17
19
  }));
18
20
 
19
21
  // Re-import app-store after mocking so it uses our temp dir
20
- const { createApp, updateApp, deleteApp, writeAppFile, editAppFile, getAppsDir } = await import('../memory/app-store.js');
21
-
22
- describe('App Git Service', () => {
22
+ const {
23
+ createApp,
24
+ updateApp,
25
+ deleteApp,
26
+ writeAppFile,
27
+ editAppFile,
28
+ getAppsDir,
29
+ } = await import("../memory/app-store.js");
30
+
31
+ describe("App Git Service", () => {
23
32
  beforeEach(() => {
24
- testDataDir = join(tmpdir(), `vellum-app-git-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
25
- mkdirSync(join(testDataDir, 'apps'), { recursive: true });
33
+ testDataDir = join(
34
+ tmpdir(),
35
+ `vellum-app-git-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
36
+ );
37
+ mkdirSync(join(testDataDir, "apps"), { recursive: true });
26
38
  _resetGitServiceRegistry();
27
39
  _resetAppGitState();
28
40
  });
@@ -35,53 +47,53 @@ describe('App Git Service', () => {
35
47
 
36
48
  function getGitLog(dir: string): string[] {
37
49
  try {
38
- const output = execFileSync('git', ['log', '--oneline', '--format=%s'], {
50
+ const output = execFileSync("git", ["log", "--oneline", "--format=%s"], {
39
51
  cwd: dir,
40
- encoding: 'utf-8',
52
+ encoding: "utf-8",
41
53
  });
42
- return output.trim().split('\n').filter(Boolean);
54
+ return output.trim().split("\n").filter(Boolean);
43
55
  } catch {
44
56
  return [];
45
57
  }
46
58
  }
47
59
 
48
- test('.gitignore excludes preview files and records', async () => {
60
+ test(".gitignore excludes preview files and records", async () => {
49
61
  const appsDir = getAppsDir();
50
- await commitAppTurnChanges('test-session', 1);
62
+ await commitAppTurnChanges("test-session", 1);
51
63
 
52
- const gitignore = readFileSync(join(appsDir, '.gitignore'), 'utf-8');
53
- expect(gitignore).toContain('*.preview');
54
- expect(gitignore).toContain('*/records/');
64
+ const gitignore = readFileSync(join(appsDir, ".gitignore"), "utf-8");
65
+ expect(gitignore).toContain("*.preview");
66
+ expect(gitignore).toContain("*/records/");
55
67
  });
56
68
 
57
- test('mutations do not auto-commit', async () => {
69
+ test("mutations do not auto-commit", async () => {
58
70
  createApp({
59
- name: 'Test App',
60
- schemaJson: '{}',
61
- htmlDefinition: '<h1>Hello</h1>',
71
+ name: "Test App",
72
+ schemaJson: "{}",
73
+ htmlDefinition: "<h1>Hello</h1>",
62
74
  });
63
75
 
64
76
  // Wait to make sure no fire-and-forget commit happens
65
- await new Promise(resolve => setTimeout(resolve, 500));
77
+ await new Promise((resolve) => setTimeout(resolve, 500));
66
78
 
67
79
  const appsDir = getAppsDir();
68
80
  // No git repo should exist yet since no turn commit was triggered
69
- expect(existsSync(join(appsDir, '.git'))).toBe(false);
81
+ expect(existsSync(join(appsDir, ".git"))).toBe(false);
70
82
  });
71
83
 
72
- test('commitAppTurnChanges creates a single commit for multiple mutations', async () => {
84
+ test("commitAppTurnChanges creates a single commit for multiple mutations", async () => {
73
85
  const app = createApp({
74
- name: 'Multi Edit App',
75
- schemaJson: '{}',
76
- htmlDefinition: '<p>v1</p>',
86
+ name: "Multi Edit App",
87
+ schemaJson: "{}",
88
+ htmlDefinition: "<p>v1</p>",
77
89
  });
78
90
 
79
- updateApp(app.id, { htmlDefinition: '<p>v2</p>' });
80
- writeAppFile(app.id, 'styles.css', 'body { color: red; }');
81
- editAppFile(app.id, 'index.html', 'v2', 'v3');
91
+ updateApp(app.id, { htmlDefinition: "<p>v2</p>" });
92
+ writeAppFile(app.id, "styles.css", "body { color: red; }");
93
+ editAppFile(app.id, "index.html", "v2", "v3");
82
94
 
83
95
  // All mutations happened, now commit at turn boundary
84
- await commitAppTurnChanges('session-1', 1);
96
+ await commitAppTurnChanges("session-1", 1);
85
97
 
86
98
  const appsDir = getAppsDir();
87
99
  const commits = getGitLog(appsDir);
@@ -91,47 +103,49 @@ describe('App Git Service', () => {
91
103
  // Either way there should be at most 2 commits, not one per mutation.
92
104
  expect(commits.length).toBeLessThanOrEqual(2);
93
105
  // The turn commit message should appear (or files are in the initial commit)
94
- expect(commits.some(c => c.includes('Turn 1') || c.includes('Initial commit'))).toBe(true);
106
+ expect(
107
+ commits.some((c) => c.includes("Turn 1") || c.includes("Initial commit")),
108
+ ).toBe(true);
95
109
  });
96
110
 
97
- test('commitAppTurnChanges does not commit when nothing changed', async () => {
111
+ test("commitAppTurnChanges does not commit when nothing changed", async () => {
98
112
  // Trigger initial commit by creating and committing an app
99
113
  createApp({
100
- name: 'Static App',
101
- schemaJson: '{}',
102
- htmlDefinition: '<p>hi</p>',
114
+ name: "Static App",
115
+ schemaJson: "{}",
116
+ htmlDefinition: "<p>hi</p>",
103
117
  });
104
- await commitAppTurnChanges('session-1', 1);
118
+ await commitAppTurnChanges("session-1", 1);
105
119
 
106
120
  const appsDir = getAppsDir();
107
121
  const commitsBefore = getGitLog(appsDir);
108
122
 
109
123
  // No mutations — turn commit should be a no-op
110
- await commitAppTurnChanges('session-1', 2);
124
+ await commitAppTurnChanges("session-1", 2);
111
125
 
112
126
  const commitsAfter = getGitLog(appsDir);
113
127
  expect(commitsAfter.length).toBe(commitsBefore.length);
114
128
  });
115
129
 
116
- test('commitAppTurnChanges swallows errors gracefully', async () => {
130
+ test("commitAppTurnChanges swallows errors gracefully", async () => {
117
131
  _resetAppGitState();
118
132
  // This should not throw
119
- await commitAppTurnChanges('test', 1);
133
+ await commitAppTurnChanges("test", 1);
120
134
  });
121
135
 
122
- test('deleteApp changes are captured by turn commit', async () => {
136
+ test("deleteApp changes are captured by turn commit", async () => {
123
137
  const app = createApp({
124
- name: 'Doomed App',
125
- schemaJson: '{}',
126
- htmlDefinition: '<p>bye</p>',
138
+ name: "Doomed App",
139
+ schemaJson: "{}",
140
+ htmlDefinition: "<p>bye</p>",
127
141
  });
128
- await commitAppTurnChanges('session-1', 1);
142
+ await commitAppTurnChanges("session-1", 1);
129
143
 
130
144
  deleteApp(app.id);
131
- await commitAppTurnChanges('session-1', 2);
145
+ await commitAppTurnChanges("session-1", 2);
132
146
 
133
147
  const appsDir = getAppsDir();
134
148
  const commits = getGitLog(appsDir);
135
- expect(commits[0]).toContain('Turn 2: app changes');
149
+ expect(commits[0]).toContain("Turn 2: app changes");
136
150
  });
137
151
  });
@@ -1,63 +1,67 @@
1
- import { describe, expect,test } from 'bun:test';
1
+ import { describe, expect, test } from "bun:test";
2
2
 
3
- import type { ProxyResolver } from '../tools/apps/executors.js';
4
- import { openAppViaSurface } from '../tools/apps/open-proxy.js';
3
+ import type { ProxyResolver } from "../tools/apps/executors.js";
4
+ import { openAppViaSurface } from "../tools/apps/open-proxy.js";
5
5
 
6
- describe('openAppViaSurface', () => {
7
- test('returns proxy result content on success', async () => {
6
+ describe("openAppViaSurface", () => {
7
+ test("returns proxy result content on success", async () => {
8
8
  const resolver: ProxyResolver = async (_name, _input) => ({
9
- content: 'opened-surface-123',
9
+ content: "opened-surface-123",
10
10
  isError: false,
11
11
  });
12
12
 
13
- const result = await openAppViaSurface('app-1', resolver);
14
- expect(result).toBe('opened-surface-123');
13
+ const result = await openAppViaSurface("app-1", resolver);
14
+ expect(result).toBe("opened-surface-123");
15
15
  });
16
16
 
17
- test('passes app_id and extraInput to the resolver', async () => {
17
+ test("passes app_id and extraInput to the resolver", async () => {
18
18
  let capturedName: string | undefined;
19
19
  let capturedInput: Record<string, unknown> | undefined;
20
20
 
21
21
  const resolver: ProxyResolver = async (name, input) => {
22
22
  capturedName = name;
23
23
  capturedInput = input;
24
- return { content: 'ok', isError: false };
24
+ return { content: "ok", isError: false };
25
25
  };
26
26
 
27
- await openAppViaSurface('my-app', resolver, { preview: { title: 'Hello' } });
27
+ await openAppViaSurface("my-app", resolver, {
28
+ preview: { title: "Hello" },
29
+ });
28
30
 
29
- expect(capturedName).toBe('app_open');
31
+ expect(capturedName).toBe("app_open");
30
32
  expect(capturedInput).toEqual({
31
- app_id: 'my-app',
32
- preview: { title: 'Hello' },
33
+ app_id: "my-app",
34
+ preview: { title: "Hello" },
33
35
  });
34
36
  });
35
37
 
36
- test('returns informational message when resolver is undefined', async () => {
37
- const result = await openAppViaSurface('app-1', undefined);
38
+ test("returns informational message when resolver is undefined", async () => {
39
+ const result = await openAppViaSurface("app-1", undefined);
38
40
  expect(result).toBe(
39
- 'App created but could not be opened (no connected client). Use app_open to open it manually.',
41
+ "App created but could not be opened (no connected client). Use app_open to open it manually.",
40
42
  );
41
43
  });
42
44
 
43
- test('returns fallback text when resolver throws', async () => {
45
+ test("returns fallback text when resolver throws", async () => {
44
46
  const resolver: ProxyResolver = async () => {
45
- throw new Error('connection lost');
47
+ throw new Error("connection lost");
46
48
  };
47
49
 
48
- const result = await openAppViaSurface('app-1', resolver);
49
- expect(result).toBe('Failed to auto-open app. Use app_open to open it manually.');
50
+ const result = await openAppViaSurface("app-1", resolver);
51
+ expect(result).toBe(
52
+ "Failed to auto-open app. Use app_open to open it manually.",
53
+ );
50
54
  });
51
55
 
52
- test('omits extraInput fields when not provided', async () => {
56
+ test("omits extraInput fields when not provided", async () => {
53
57
  let capturedInput: Record<string, unknown> | undefined;
54
58
 
55
59
  const resolver: ProxyResolver = async (_name, input) => {
56
60
  capturedInput = input;
57
- return { content: 'ok', isError: false };
61
+ return { content: "ok", isError: false };
58
62
  };
59
63
 
60
- await openAppViaSurface('app-2', resolver);
61
- expect(capturedInput).toEqual({ app_id: 'app-2' });
64
+ await openAppViaSurface("app-2", resolver);
65
+ expect(capturedInput).toEqual({ app_id: "app-2" });
62
66
  });
63
67
  });