@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.
- package/Dockerfile +6 -6
- package/README.md +1 -2
- package/eslint.config.mjs +2 -2
- package/package.json +1 -1
- package/src/__tests__/access-request-decision.test.ts +128 -120
- package/src/__tests__/account-registry.test.ts +121 -110
- package/src/__tests__/active-skill-tools.test.ts +200 -172
- package/src/__tests__/actor-token-service.test.ts +341 -274
- package/src/__tests__/agent-loop-thinking.test.ts +28 -19
- package/src/__tests__/agent-loop.test.ts +798 -378
- package/src/__tests__/anthropic-provider.test.ts +405 -247
- package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
- package/src/__tests__/app-bundler.test.ts +112 -79
- package/src/__tests__/app-executors.test.ts +205 -178
- package/src/__tests__/app-git-history.test.ts +90 -73
- package/src/__tests__/app-git-service.test.ts +67 -53
- package/src/__tests__/app-open-proxy.test.ts +29 -25
- package/src/__tests__/approval-conversation-turn.test.ts +100 -81
- package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
- package/src/__tests__/approval-message-composer.test.ts +119 -119
- package/src/__tests__/approval-primitive.test.ts +264 -233
- package/src/__tests__/approval-routes-http.test.ts +4 -3
- package/src/__tests__/asset-materialize-tool.test.ts +250 -178
- package/src/__tests__/asset-search-tool.test.ts +251 -191
- package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
- package/src/__tests__/assistant-attachments.test.ts +254 -186
- package/src/__tests__/assistant-event-hub.test.ts +105 -63
- package/src/__tests__/assistant-event.test.ts +66 -58
- package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
- package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
- package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
- package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
- package/src/__tests__/attachments-store.test.ts +240 -183
- package/src/__tests__/attachments.test.ts +70 -62
- package/src/__tests__/audit-log-rotation.test.ts +50 -35
- package/src/__tests__/browser-fill-credential.test.ts +169 -101
- package/src/__tests__/browser-manager.test.ts +97 -75
- package/src/__tests__/browser-runtime-check.test.ts +16 -15
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
- package/src/__tests__/browser-skill-endstate.test.ts +97 -72
- package/src/__tests__/bundle-scanner.test.ts +47 -22
- package/src/__tests__/bundled-asset.test.ts +74 -47
- package/src/__tests__/call-constants.test.ts +19 -19
- package/src/__tests__/call-controller.test.ts +1073 -751
- package/src/__tests__/call-conversation-messages.test.ts +90 -65
- package/src/__tests__/call-domain.test.ts +149 -121
- package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
- package/src/__tests__/call-pointer-messages.test.ts +213 -154
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
- package/src/__tests__/call-recovery.test.ts +232 -212
- package/src/__tests__/call-routes-http.test.ts +328 -279
- package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
- package/src/__tests__/call-state-machine.test.ts +62 -51
- package/src/__tests__/call-state.test.ts +89 -75
- package/src/__tests__/call-store.test.ts +387 -316
- package/src/__tests__/callback-handoff-copy.test.ts +84 -82
- package/src/__tests__/canonical-guardian-store.test.ts +331 -280
- package/src/__tests__/channel-approval-routes.test.ts +1643 -1126
- package/src/__tests__/channel-approval.test.ts +139 -137
- package/src/__tests__/channel-approvals.test.ts +226 -182
- package/src/__tests__/channel-delivery-store.test.ts +232 -194
- package/src/__tests__/channel-guardian.test.ts +6 -3
- package/src/__tests__/channel-invite-transport.test.ts +107 -92
- package/src/__tests__/channel-policy.test.ts +42 -38
- package/src/__tests__/channel-readiness-service.test.ts +119 -102
- package/src/__tests__/channel-reply-delivery.test.ts +147 -118
- package/src/__tests__/channel-retry-sweep.test.ts +153 -110
- package/src/__tests__/checker.test.ts +3309 -1850
- package/src/__tests__/clarification-resolver.test.ts +91 -79
- package/src/__tests__/classifier.test.ts +64 -54
- package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
- package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
- package/src/__tests__/clawhub.test.ts +92 -82
- package/src/__tests__/cli.test.ts +30 -30
- package/src/__tests__/clipboard.test.ts +53 -46
- package/src/__tests__/commit-guarantee.test.ts +59 -52
- package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
- package/src/__tests__/compaction.benchmark.test.ts +33 -31
- package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
- package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
- package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
- package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
- package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
- package/src/__tests__/computer-use-tools.test.ts +121 -98
- package/src/__tests__/config-schema.test.ts +443 -347
- package/src/__tests__/config-watcher.test.ts +96 -81
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
- package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
- package/src/__tests__/conflict-policy.test.ts +151 -80
- package/src/__tests__/conflict-store.test.ts +203 -157
- package/src/__tests__/connection-policy.test.ts +89 -59
- package/src/__tests__/contacts-tools.test.ts +247 -178
- package/src/__tests__/context-memory-e2e.test.ts +306 -214
- package/src/__tests__/context-token-estimator.test.ts +114 -74
- package/src/__tests__/context-window-manager.test.ts +269 -167
- package/src/__tests__/contradiction-checker.test.ts +161 -135
- package/src/__tests__/conversation-attention-store.test.ts +350 -290
- package/src/__tests__/conversation-attention-telegram.test.ts +156 -114
- package/src/__tests__/conversation-pairing.test.ts +220 -113
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +164 -104
- package/src/__tests__/conversation-routes.test.ts +71 -41
- package/src/__tests__/conversation-store.test.ts +390 -235
- package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
- package/src/__tests__/credential-broker-server-use.test.ts +283 -243
- package/src/__tests__/credential-broker.test.ts +128 -74
- package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
- package/src/__tests__/credential-metadata-store.test.ts +360 -311
- package/src/__tests__/credential-policy-validate.test.ts +81 -65
- package/src/__tests__/credential-resolve.test.ts +212 -145
- package/src/__tests__/credential-security-e2e.test.ts +144 -103
- package/src/__tests__/credential-security-invariants.test.ts +253 -208
- package/src/__tests__/credential-selection.test.ts +254 -146
- package/src/__tests__/credential-vault-unit.test.ts +531 -341
- package/src/__tests__/credential-vault.test.ts +761 -484
- package/src/__tests__/daemon-assistant-events.test.ts +91 -66
- package/src/__tests__/daemon-lifecycle.test.ts +258 -190
- package/src/__tests__/daemon-server-session-init.test.ts +257 -191
- package/src/__tests__/date-context.test.ts +314 -249
- package/src/__tests__/db-migration-rollback.test.ts +259 -130
- package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
- package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
- package/src/__tests__/deterministic-verification-control-plane.test.ts +183 -135
- package/src/__tests__/dictation-mode-detection.test.ts +77 -55
- package/src/__tests__/dictation-profile-store.test.ts +70 -56
- package/src/__tests__/dictation-text-processing.test.ts +53 -35
- package/src/__tests__/diff.test.ts +102 -98
- package/src/__tests__/domain-normalize.test.ts +54 -54
- package/src/__tests__/domain-policy.test.ts +71 -55
- package/src/__tests__/dynamic-page-surface.test.ts +31 -33
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
- package/src/__tests__/edit-engine.test.ts +56 -56
- package/src/__tests__/elevenlabs-client.test.ts +117 -91
- package/src/__tests__/elevenlabs-config.test.ts +32 -31
- package/src/__tests__/email-classifier.test.ts +15 -12
- package/src/__tests__/email-cli.test.ts +121 -108
- package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
- package/src/__tests__/encrypted-store.test.ts +180 -154
- package/src/__tests__/entity-extractor.test.ts +108 -87
- package/src/__tests__/entity-search.test.ts +664 -258
- package/src/__tests__/ephemeral-permissions.test.ts +224 -188
- package/src/__tests__/event-bus.test.ts +81 -77
- package/src/__tests__/extract-email.test.ts +51 -0
- package/src/__tests__/file-edit-tool.test.ts +62 -44
- package/src/__tests__/file-ops-service.test.ts +131 -114
- package/src/__tests__/file-read-tool.test.ts +48 -31
- package/src/__tests__/file-write-tool.test.ts +43 -37
- package/src/__tests__/filesystem-tools.test.ts +238 -209
- package/src/__tests__/followup-tools.test.ts +237 -162
- package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
- package/src/__tests__/frontmatter.test.ts +96 -81
- package/src/__tests__/fuzzy-match-property.test.ts +75 -81
- package/src/__tests__/fuzzy-match.test.ts +71 -65
- package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
- package/src/__tests__/gateway-only-enforcement.test.ts +467 -369
- package/src/__tests__/gateway-only-guard.test.ts +54 -56
- package/src/__tests__/gemini-image-service.test.ts +113 -100
- package/src/__tests__/gemini-provider.test.ts +297 -220
- package/src/__tests__/get-weather.test.ts +188 -114
- package/src/__tests__/gmail-integration.test.ts +47 -46
- package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
- package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
- package/src/__tests__/guardian-action-followup-executor.test.ts +215 -151
- package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
- package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
- package/src/__tests__/guardian-action-store.test.ts +158 -109
- package/src/__tests__/guardian-action-sweep.test.ts +114 -100
- package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
- package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
- package/src/__tests__/guardian-dispatch.test.ts +316 -256
- package/src/__tests__/guardian-grant-minting.test.ts +247 -178
- package/src/__tests__/guardian-outbound-http.test.ts +337 -209
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
- package/src/__tests__/guardian-question-copy.test.ts +17 -17
- package/src/__tests__/guardian-question-mode.test.ts +134 -100
- package/src/__tests__/guardian-routing-invariants.test.ts +679 -613
- package/src/__tests__/guardian-routing-state.test.ts +256 -209
- package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
- package/src/__tests__/guardian-verification-voice-binding.test.ts +47 -41
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
- package/src/__tests__/handle-user-message-secret-resume.test.ts +43 -21
- package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
- package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
- package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
- package/src/__tests__/handlers-slack-config.test.ts +63 -54
- package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
- package/src/__tests__/handlers-telegram-config.test.ts +662 -329
- package/src/__tests__/handlers-twitter-config.test.ts +525 -298
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +270 -195
- package/src/__tests__/headless-browser-interactions.test.ts +444 -280
- package/src/__tests__/headless-browser-navigate.test.ts +116 -79
- package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
- package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
- package/src/__tests__/heartbeat-service.test.ts +76 -58
- package/src/__tests__/history-repair-observability.test.ts +14 -14
- package/src/__tests__/history-repair.test.ts +171 -167
- package/src/__tests__/home-base-bootstrap.test.ts +30 -27
- package/src/__tests__/hooks-blocking.test.ts +86 -37
- package/src/__tests__/hooks-cli.test.ts +104 -68
- package/src/__tests__/hooks-config.test.ts +81 -43
- package/src/__tests__/hooks-discovery.test.ts +106 -96
- package/src/__tests__/hooks-integration.test.ts +78 -72
- package/src/__tests__/hooks-manager.test.ts +99 -61
- package/src/__tests__/hooks-runner.test.ts +94 -71
- package/src/__tests__/hooks-settings.test.ts +69 -64
- package/src/__tests__/hooks-templates.test.ts +85 -54
- package/src/__tests__/hooks-ts-runner.test.ts +82 -45
- package/src/__tests__/hooks-watch.test.ts +32 -22
- package/src/__tests__/host-file-edit-tool.test.ts +190 -148
- package/src/__tests__/host-file-read-tool.test.ts +86 -63
- package/src/__tests__/host-file-write-tool.test.ts +98 -64
- package/src/__tests__/host-shell-tool.test.ts +342 -233
- package/src/__tests__/inbound-invite-redemption.test.ts +194 -152
- package/src/__tests__/ingress-member-store.test.ts +163 -159
- package/src/__tests__/ingress-reconcile.test.ts +183 -142
- package/src/__tests__/ingress-routes-http.test.ts +441 -356
- package/src/__tests__/ingress-url-consistency.test.ts +125 -64
- package/src/__tests__/integration-status.test.ts +93 -73
- package/src/__tests__/intent-routing.test.ts +148 -118
- package/src/__tests__/invite-redemption-service.test.ts +163 -121
- package/src/__tests__/ipc-blob-store.test.ts +104 -91
- package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
- package/src/__tests__/ipc-contract.test.ts +24 -23
- package/src/__tests__/ipc-protocol.test.ts +52 -46
- package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
- package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
- package/src/__tests__/ipc-validate.test.ts +240 -179
- package/src/__tests__/key-migration.test.ts +123 -90
- package/src/__tests__/keychain.test.ts +150 -123
- package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
- package/src/__tests__/llm-usage-store.test.ts +112 -87
- package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
- package/src/__tests__/managed-store.test.ts +411 -360
- package/src/__tests__/mcp-cli.test.ts +189 -123
- package/src/__tests__/mcp-health-check.test.ts +26 -21
- package/src/__tests__/media-generate-image.test.ts +122 -99
- package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
- package/src/__tests__/media-visibility-policy.test.ts +86 -38
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
- package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
- package/src/__tests__/memory-query-builder.test.ts +32 -33
- package/src/__tests__/memory-recall-quality.test.ts +761 -407
- package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
- package/src/__tests__/memory-regressions.test.ts +3725 -2642
- package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
- package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
- package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
- package/src/__tests__/messaging-send-tool.test.ts +36 -29
- package/src/__tests__/migration-cli-flows.test.ts +69 -53
- package/src/__tests__/migration-ordering.test.ts +103 -86
- package/src/__tests__/mime-builder.test.ts +55 -32
- package/src/__tests__/mock-signup-server.test.ts +384 -246
- package/src/__tests__/model-intents.test.ts +61 -37
- package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
- package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
- package/src/__tests__/non-member-access-request.test.ts +294 -249
- package/src/__tests__/notification-broadcaster.test.ts +99 -81
- package/src/__tests__/notification-decision-fallback.test.ts +223 -178
- package/src/__tests__/notification-decision-strategy.test.ts +375 -337
- package/src/__tests__/notification-deep-link.test.ts +67 -61
- package/src/__tests__/notification-guardian-path.test.ts +248 -206
- package/src/__tests__/notification-routing-intent.test.ts +166 -93
- package/src/__tests__/notification-telegram-adapter.test.ts +60 -46
- package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
- package/src/__tests__/notification-thread-candidates.test.ts +64 -61
- package/src/__tests__/oauth-callback-registry.test.ts +40 -30
- package/src/__tests__/oauth-connect-handler.test.ts +109 -89
- package/src/__tests__/oauth-scope-policy.test.ts +63 -55
- package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
- package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
- package/src/__tests__/onboarding-template-contract.test.ts +93 -94
- package/src/__tests__/openai-provider.test.ts +366 -274
- package/src/__tests__/pairing-concurrent.test.ts +18 -12
- package/src/__tests__/pairing-routes.test.ts +45 -41
- package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
- package/src/__tests__/parser.test.ts +316 -226
- package/src/__tests__/path-classifier.test.ts +24 -25
- package/src/__tests__/path-policy.test.ts +187 -147
- package/src/__tests__/phone.test.ts +36 -36
- package/src/__tests__/platform-move-helper.test.ts +48 -40
- package/src/__tests__/platform-socket-path.test.ts +23 -24
- package/src/__tests__/platform-workspace-migration.test.ts +464 -414
- package/src/__tests__/platform.test.ts +61 -53
- package/src/__tests__/playbook-execution.test.ts +397 -265
- package/src/__tests__/playbook-tools.test.ts +267 -196
- package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
- package/src/__tests__/pricing.test.ts +316 -136
- package/src/__tests__/profile-compiler.test.ts +206 -188
- package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
- package/src/__tests__/provider-error-scenarios.test.ts +212 -158
- package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
- package/src/__tests__/provider-registry-ollama.test.ts +13 -9
- package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
- package/src/__tests__/proxy-approval-callback.test.ts +180 -119
- package/src/__tests__/public-ingress-urls.test.ts +112 -94
- package/src/__tests__/qdrant-manager.test.ts +147 -98
- package/src/__tests__/ratelimit.test.ts +152 -82
- package/src/__tests__/recording-handler.test.ts +273 -151
- package/src/__tests__/recording-intent-fallback.test.ts +94 -75
- package/src/__tests__/recording-intent-handler.test.ts +422 -292
- package/src/__tests__/recording-intent.test.ts +578 -379
- package/src/__tests__/recording-state-machine.test.ts +530 -316
- package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
- package/src/__tests__/recurrence-engine.test.ts +81 -41
- package/src/__tests__/recurrence-types.test.ts +63 -44
- package/src/__tests__/relay-server.test.ts +2131 -1602
- package/src/__tests__/reminder-store.test.ts +158 -80
- package/src/__tests__/reminder.test.ts +113 -109
- package/src/__tests__/remote-skill-policy.test.ts +96 -72
- package/src/__tests__/request-file-tool.test.ts +74 -67
- package/src/__tests__/response-tier.test.ts +131 -74
- package/src/__tests__/runtime-attachment-metadata.test.ts +107 -70
- package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
- package/src/__tests__/runtime-events-sse.test.ts +67 -51
- package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
- package/src/__tests__/sandbox-host-parity.test.ts +377 -301
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
- package/src/__tests__/schedule-store.test.ts +268 -205
- package/src/__tests__/schedule-tools.test.ts +702 -524
- package/src/__tests__/scheduler-recurrence.test.ts +240 -130
- package/src/__tests__/scoped-approval-grants.test.ts +258 -168
- package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
- package/src/__tests__/script-proxy-certs.test.ts +38 -35
- package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
- package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
- package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
- package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
- package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
- package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
- package/src/__tests__/script-proxy-policy.test.ts +308 -153
- package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
- package/src/__tests__/script-proxy-router.test.ts +111 -77
- package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
- package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
- package/src/__tests__/secret-allowlist.test.ts +105 -90
- package/src/__tests__/secret-ingress-handler.test.ts +41 -30
- package/src/__tests__/secret-onetime-send.test.ts +67 -50
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
- package/src/__tests__/secret-response-routing.test.ts +50 -41
- package/src/__tests__/secret-scanner-executor.test.ts +152 -111
- package/src/__tests__/secret-scanner.test.ts +495 -413
- package/src/__tests__/secure-keys.test.ts +132 -121
- package/src/__tests__/send-endpoint-busy.test.ts +313 -232
- package/src/__tests__/send-notification-tool.test.ts +43 -42
- package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
- package/src/__tests__/sequence-store.test.ts +335 -167
- package/src/__tests__/server-history-render.test.ts +341 -202
- package/src/__tests__/session-abort-tool-results.test.ts +133 -70
- package/src/__tests__/session-approval-overrides.test.ts +93 -91
- package/src/__tests__/session-confirmation-signals.test.ts +252 -160
- package/src/__tests__/session-conflict-gate.test.ts +775 -585
- package/src/__tests__/session-error.test.ts +222 -191
- package/src/__tests__/session-evictor.test.ts +79 -62
- package/src/__tests__/session-init.benchmark.test.ts +170 -108
- package/src/__tests__/session-load-history-repair.test.ts +273 -139
- package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
- package/src/__tests__/session-pre-run-repair.test.ts +106 -59
- package/src/__tests__/session-profile-injection.test.ts +198 -130
- package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
- package/src/__tests__/session-queue.test.ts +624 -321
- package/src/__tests__/session-runtime-assembly.test.ts +425 -329
- package/src/__tests__/session-runtime-workspace.test.ts +69 -61
- package/src/__tests__/session-skill-tools.test.ts +973 -678
- package/src/__tests__/session-slash-known.test.ts +185 -133
- package/src/__tests__/session-slash-queue.test.ts +147 -81
- package/src/__tests__/session-slash-unknown.test.ts +135 -90
- package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
- package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
- package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
- package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
- package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
- package/src/__tests__/session-undo.test.ts +43 -30
- package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
- package/src/__tests__/session-workspace-injection.test.ts +245 -117
- package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
- package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
- package/src/__tests__/shell-credential-ref.test.ts +126 -90
- package/src/__tests__/shell-identity.test.ts +134 -111
- package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
- package/src/__tests__/shell-parser-property.test.ts +435 -288
- package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
- package/src/__tests__/size-guard.test.ts +42 -44
- package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
- package/src/__tests__/skill-feature-flags.test.ts +75 -47
- package/src/__tests__/skill-include-graph.test.ts +143 -148
- package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
- package/src/__tests__/skill-load-tool.test.ts +371 -199
- package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
- package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
- package/src/__tests__/skill-script-runner-host.test.ts +460 -250
- package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
- package/src/__tests__/skill-script-runner.test.ts +115 -74
- package/src/__tests__/skill-tool-factory.test.ts +140 -96
- package/src/__tests__/skill-tool-manifest.test.ts +306 -210
- package/src/__tests__/skill-version-hash.test.ts +70 -56
- package/src/__tests__/skills.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +127 -84
- package/src/__tests__/slack-skill.test.ts +60 -47
- package/src/__tests__/slash-commands-catalog.test.ts +37 -31
- package/src/__tests__/slash-commands-parser.test.ts +71 -64
- package/src/__tests__/slash-commands-resolver.test.ts +143 -107
- package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
- package/src/__tests__/sms-messaging-provider.test.ts +74 -47
- package/src/__tests__/speaker-identification.test.ts +28 -25
- package/src/__tests__/starter-bundle.test.ts +27 -23
- package/src/__tests__/starter-task-flow.test.ts +67 -52
- package/src/__tests__/subagent-manager-notify.test.ts +154 -108
- package/src/__tests__/subagent-tools.test.ts +311 -270
- package/src/__tests__/subagent-types.test.ts +40 -40
- package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
- package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
- package/src/__tests__/swarm-orchestrator.test.ts +135 -101
- package/src/__tests__/swarm-plan-validator.test.ts +125 -73
- package/src/__tests__/swarm-recursion.test.ts +58 -46
- package/src/__tests__/swarm-router-planner.test.ts +99 -74
- package/src/__tests__/swarm-session-integration.test.ts +148 -91
- package/src/__tests__/swarm-tool.test.ts +65 -45
- package/src/__tests__/swarm-worker-backend.test.ts +59 -45
- package/src/__tests__/swarm-worker-runner.test.ts +133 -118
- package/src/__tests__/system-prompt.test.ts +290 -256
- package/src/__tests__/task-compiler.test.ts +176 -120
- package/src/__tests__/task-management-tools.test.ts +561 -456
- package/src/__tests__/task-memory-cleanup.test.ts +627 -362
- package/src/__tests__/task-runner.test.ts +117 -94
- package/src/__tests__/task-scheduler.test.ts +113 -84
- package/src/__tests__/task-tools.test.ts +349 -264
- package/src/__tests__/terminal-sandbox.test.ts +138 -108
- package/src/__tests__/terminal-tools.test.ts +350 -305
- package/src/__tests__/thread-seed-composer.test.ts +307 -180
- package/src/__tests__/tool-approval-handler.test.ts +238 -137
- package/src/__tests__/tool-audit-listener.test.ts +69 -69
- package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +153 -146
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
- package/src/__tests__/tool-executor-redaction.test.ts +112 -109
- package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
- package/src/__tests__/tool-executor.test.ts +1274 -674
- package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
- package/src/__tests__/tool-metrics-listener.test.ts +97 -85
- package/src/__tests__/tool-notification-listener.test.ts +42 -25
- package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
- package/src/__tests__/tool-policy.test.ts +44 -25
- package/src/__tests__/tool-profiling-listener.test.ts +99 -93
- package/src/__tests__/tool-result-truncation.test.ts +5 -4
- package/src/__tests__/tool-trace-listener.test.ts +131 -111
- package/src/__tests__/top-level-renderer.test.ts +62 -58
- package/src/__tests__/top-level-scanner.test.ts +68 -64
- package/src/__tests__/trace-emitter.test.ts +56 -56
- package/src/__tests__/trust-context-guards.test.ts +65 -65
- package/src/__tests__/trust-store.test.ts +1239 -806
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +339 -275
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +484 -373
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +264 -241
- package/src/__tests__/trusted-contact-multichannel.test.ts +182 -142
- package/src/__tests__/trusted-contact-verification.test.ts +251 -231
- package/src/__tests__/turn-commit.test.ts +259 -200
- package/src/__tests__/twilio-config.test.ts +49 -41
- package/src/__tests__/twilio-provider.test.ts +140 -126
- package/src/__tests__/twilio-rest.test.ts +22 -18
- package/src/__tests__/twilio-routes-elevenlabs.test.ts +188 -162
- package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
- package/src/__tests__/twilio-routes.test.ts +389 -281
- package/src/__tests__/twitter-auth-handler.test.ts +184 -139
- package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
- package/src/__tests__/twitter-cli-routing.test.ts +146 -99
- package/src/__tests__/twitter-oauth-client.test.ts +82 -65
- package/src/__tests__/update-bulletin-format.test.ts +69 -66
- package/src/__tests__/update-bulletin-state.test.ts +66 -60
- package/src/__tests__/update-bulletin.test.ts +150 -114
- package/src/__tests__/update-template-contract.test.ts +15 -10
- package/src/__tests__/url-safety.test.ts +288 -265
- package/src/__tests__/user-reference.test.ts +32 -32
- package/src/__tests__/view-image-tool.test.ts +118 -96
- package/src/__tests__/voice-invite-redemption.test.ts +111 -106
- package/src/__tests__/voice-quality.test.ts +117 -102
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
- package/src/__tests__/voice-session-bridge.test.ts +351 -216
- package/src/__tests__/weather-skill-regression.test.ts +170 -120
- package/src/__tests__/web-fetch.test.ts +664 -526
- package/src/__tests__/web-search.test.ts +379 -213
- package/src/__tests__/work-item-output.test.ts +90 -53
- package/src/__tests__/workspace-git-service.test.ts +437 -356
- package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
- package/src/__tests__/workspace-lifecycle.test.ts +98 -64
- package/src/__tests__/workspace-policy.test.ts +139 -71
- package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +44 -4
- package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
- package/src/config/bundled-skills/messaging/SKILL.md +9 -7
- package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
- package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
- package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +11 -7
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/env.ts +38 -29
- package/src/daemon/handlers/skills.ts +18 -10
- package/src/daemon/ipc-contract/messages.ts +1 -0
- package/src/daemon/ipc-contract/surfaces.ts +7 -1
- package/src/daemon/session-agent-loop-handlers.ts +5 -0
- package/src/daemon/session-agent-loop.ts +1 -1
- package/src/daemon/session-process.ts +1 -1
- package/src/daemon/session-surfaces.ts +42 -2
- package/src/memory/db-connection.ts +16 -10
- package/src/messaging/providers/gmail/adapter.ts +10 -3
- package/src/messaging/providers/gmail/client.ts +280 -72
- package/src/runtime/auth/__tests__/context.test.ts +75 -65
- package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
- package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
- package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
- package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
- package/src/runtime/auth/__tests__/policy.test.ts +9 -9
- package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
- package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
- package/src/runtime/auth/__tests__/subject.test.ts +54 -54
- package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
- package/src/runtime/auth/scopes.ts +3 -0
- package/src/runtime/auth/token-service.ts +78 -48
- package/src/runtime/auth/types.ts +2 -1
- package/src/runtime/http-server.ts +2 -1
- package/src/security/secure-keys.ts +103 -53
- package/src/sequence/reply-matcher.ts +10 -6
- package/src/skills/frontmatter.ts +9 -6
- package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
- package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
- package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
- package/src/tools/ui-surface/definitions.ts +2 -1
- package/src/util/platform.ts +0 -12
- package/docs/architecture/http-token-refresh.md +0 -274
|
@@ -1,28 +1,39 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync,rmSync } from
|
|
2
|
-
import { tmpdir } from
|
|
3
|
-
import { join } from
|
|
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 {
|
|
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(
|
|
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 } =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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(
|
|
25
|
-
|
|
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(
|
|
47
|
+
test("getAppHistory returns commits for a specific app", async () => {
|
|
37
48
|
const app = createApp({
|
|
38
|
-
name:
|
|
39
|
-
schemaJson:
|
|
40
|
-
htmlDefinition:
|
|
49
|
+
name: "History App",
|
|
50
|
+
schemaJson: "{}",
|
|
51
|
+
htmlDefinition: "<h1>v1</h1>",
|
|
41
52
|
});
|
|
42
|
-
await commitAppTurnChanges(
|
|
53
|
+
await commitAppTurnChanges("session-1", 1);
|
|
43
54
|
|
|
44
|
-
updateApp(app.id, { htmlDefinition:
|
|
45
|
-
await commitAppTurnChanges(
|
|
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(
|
|
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(
|
|
65
|
+
test("getAppHistory does not return commits for other apps", async () => {
|
|
55
66
|
const app1 = createApp({
|
|
56
|
-
name:
|
|
57
|
-
schemaJson:
|
|
58
|
-
htmlDefinition:
|
|
67
|
+
name: "App One",
|
|
68
|
+
schemaJson: "{}",
|
|
69
|
+
htmlDefinition: "<p>one</p>",
|
|
59
70
|
});
|
|
60
|
-
await commitAppTurnChanges(
|
|
71
|
+
await commitAppTurnChanges("session-1", 1);
|
|
61
72
|
|
|
62
73
|
const app2 = createApp({
|
|
63
|
-
name:
|
|
64
|
-
schemaJson:
|
|
65
|
-
htmlDefinition:
|
|
74
|
+
name: "App Two",
|
|
75
|
+
schemaJson: "{}",
|
|
76
|
+
htmlDefinition: "<p>two</p>",
|
|
66
77
|
});
|
|
67
|
-
await commitAppTurnChanges(
|
|
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(
|
|
91
|
+
test("getAppHistory respects limit", async () => {
|
|
81
92
|
const app = createApp({
|
|
82
|
-
name:
|
|
83
|
-
schemaJson:
|
|
84
|
-
htmlDefinition:
|
|
93
|
+
name: "Limited App",
|
|
94
|
+
schemaJson: "{}",
|
|
95
|
+
htmlDefinition: "<p>v1</p>",
|
|
85
96
|
});
|
|
86
|
-
await commitAppTurnChanges(
|
|
97
|
+
await commitAppTurnChanges("session-1", 1);
|
|
87
98
|
|
|
88
|
-
updateApp(app.id, { htmlDefinition:
|
|
89
|
-
await commitAppTurnChanges(
|
|
99
|
+
updateApp(app.id, { htmlDefinition: "<p>v2</p>" });
|
|
100
|
+
await commitAppTurnChanges("session-1", 2);
|
|
90
101
|
|
|
91
|
-
updateApp(app.id, { htmlDefinition:
|
|
92
|
-
await commitAppTurnChanges(
|
|
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(
|
|
109
|
+
test("getAppDiff shows changes between versions", async () => {
|
|
99
110
|
const app = createApp({
|
|
100
|
-
name:
|
|
101
|
-
schemaJson:
|
|
102
|
-
htmlDefinition:
|
|
111
|
+
name: "Diff App",
|
|
112
|
+
schemaJson: "{}",
|
|
113
|
+
htmlDefinition: "<p>original</p>",
|
|
103
114
|
});
|
|
104
|
-
await commitAppTurnChanges(
|
|
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:
|
|
110
|
-
await commitAppTurnChanges(
|
|
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(
|
|
117
|
-
expect(diff).toContain(
|
|
127
|
+
expect(diff).toContain("original");
|
|
128
|
+
expect(diff).toContain("modified");
|
|
118
129
|
});
|
|
119
130
|
|
|
120
|
-
test(
|
|
131
|
+
test("getAppFileAtVersion returns file content at a specific commit", async () => {
|
|
121
132
|
const app = createApp({
|
|
122
|
-
name:
|
|
123
|
-
schemaJson:
|
|
124
|
-
htmlDefinition:
|
|
133
|
+
name: "File Version App",
|
|
134
|
+
schemaJson: "{}",
|
|
135
|
+
htmlDefinition: "<p>version one</p>",
|
|
125
136
|
});
|
|
126
|
-
await commitAppTurnChanges(
|
|
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:
|
|
132
|
-
await commitAppTurnChanges(
|
|
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,
|
|
136
|
-
expect(v1Content).toContain(
|
|
137
|
-
expect(v1Content).not.toContain(
|
|
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(
|
|
141
|
-
|
|
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(
|
|
158
|
+
test("restoreAppVersion restores files and creates a new commit", async () => {
|
|
145
159
|
const app = createApp({
|
|
146
|
-
name:
|
|
147
|
-
schemaJson:
|
|
148
|
-
htmlDefinition:
|
|
160
|
+
name: "Restore App",
|
|
161
|
+
schemaJson: "{}",
|
|
162
|
+
htmlDefinition: "<p>original content</p>",
|
|
149
163
|
});
|
|
150
|
-
await commitAppTurnChanges(
|
|
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:
|
|
156
|
-
await commitAppTurnChanges(
|
|
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(
|
|
160
|
-
|
|
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,
|
|
167
|
-
expect(current).toContain(
|
|
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(
|
|
188
|
+
expect(history2[0].message).toContain("Restore app");
|
|
172
189
|
});
|
|
173
190
|
});
|
|
@@ -1,28 +1,40 @@
|
|
|
1
|
-
import { execFileSync } from
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync,rmSync } from
|
|
3
|
-
import { tmpdir } from
|
|
4
|
-
import { join } from
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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(
|
|
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 {
|
|
21
|
-
|
|
22
|
-
|
|
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(
|
|
25
|
-
|
|
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(
|
|
50
|
+
const output = execFileSync("git", ["log", "--oneline", "--format=%s"], {
|
|
39
51
|
cwd: dir,
|
|
40
|
-
encoding:
|
|
52
|
+
encoding: "utf-8",
|
|
41
53
|
});
|
|
42
|
-
return output.trim().split(
|
|
54
|
+
return output.trim().split("\n").filter(Boolean);
|
|
43
55
|
} catch {
|
|
44
56
|
return [];
|
|
45
57
|
}
|
|
46
58
|
}
|
|
47
59
|
|
|
48
|
-
test(
|
|
60
|
+
test(".gitignore excludes preview files and records", async () => {
|
|
49
61
|
const appsDir = getAppsDir();
|
|
50
|
-
await commitAppTurnChanges(
|
|
62
|
+
await commitAppTurnChanges("test-session", 1);
|
|
51
63
|
|
|
52
|
-
const gitignore = readFileSync(join(appsDir,
|
|
53
|
-
expect(gitignore).toContain(
|
|
54
|
-
expect(gitignore).toContain(
|
|
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(
|
|
69
|
+
test("mutations do not auto-commit", async () => {
|
|
58
70
|
createApp({
|
|
59
|
-
name:
|
|
60
|
-
schemaJson:
|
|
61
|
-
htmlDefinition:
|
|
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,
|
|
81
|
+
expect(existsSync(join(appsDir, ".git"))).toBe(false);
|
|
70
82
|
});
|
|
71
83
|
|
|
72
|
-
test(
|
|
84
|
+
test("commitAppTurnChanges creates a single commit for multiple mutations", async () => {
|
|
73
85
|
const app = createApp({
|
|
74
|
-
name:
|
|
75
|
-
schemaJson:
|
|
76
|
-
htmlDefinition:
|
|
86
|
+
name: "Multi Edit App",
|
|
87
|
+
schemaJson: "{}",
|
|
88
|
+
htmlDefinition: "<p>v1</p>",
|
|
77
89
|
});
|
|
78
90
|
|
|
79
|
-
updateApp(app.id, { htmlDefinition:
|
|
80
|
-
writeAppFile(app.id,
|
|
81
|
-
editAppFile(app.id,
|
|
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(
|
|
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(
|
|
106
|
+
expect(
|
|
107
|
+
commits.some((c) => c.includes("Turn 1") || c.includes("Initial commit")),
|
|
108
|
+
).toBe(true);
|
|
95
109
|
});
|
|
96
110
|
|
|
97
|
-
test(
|
|
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:
|
|
101
|
-
schemaJson:
|
|
102
|
-
htmlDefinition:
|
|
114
|
+
name: "Static App",
|
|
115
|
+
schemaJson: "{}",
|
|
116
|
+
htmlDefinition: "<p>hi</p>",
|
|
103
117
|
});
|
|
104
|
-
await commitAppTurnChanges(
|
|
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(
|
|
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(
|
|
130
|
+
test("commitAppTurnChanges swallows errors gracefully", async () => {
|
|
117
131
|
_resetAppGitState();
|
|
118
132
|
// This should not throw
|
|
119
|
-
await commitAppTurnChanges(
|
|
133
|
+
await commitAppTurnChanges("test", 1);
|
|
120
134
|
});
|
|
121
135
|
|
|
122
|
-
test(
|
|
136
|
+
test("deleteApp changes are captured by turn commit", async () => {
|
|
123
137
|
const app = createApp({
|
|
124
|
-
name:
|
|
125
|
-
schemaJson:
|
|
126
|
-
htmlDefinition:
|
|
138
|
+
name: "Doomed App",
|
|
139
|
+
schemaJson: "{}",
|
|
140
|
+
htmlDefinition: "<p>bye</p>",
|
|
127
141
|
});
|
|
128
|
-
await commitAppTurnChanges(
|
|
142
|
+
await commitAppTurnChanges("session-1", 1);
|
|
129
143
|
|
|
130
144
|
deleteApp(app.id);
|
|
131
|
-
await commitAppTurnChanges(
|
|
145
|
+
await commitAppTurnChanges("session-1", 2);
|
|
132
146
|
|
|
133
147
|
const appsDir = getAppsDir();
|
|
134
148
|
const commits = getGitLog(appsDir);
|
|
135
|
-
expect(commits[0]).toContain(
|
|
149
|
+
expect(commits[0]).toContain("Turn 2: app changes");
|
|
136
150
|
});
|
|
137
151
|
});
|
|
@@ -1,63 +1,67 @@
|
|
|
1
|
-
import { describe, expect,test } from
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import type { ProxyResolver } from
|
|
4
|
-
import { openAppViaSurface } from
|
|
3
|
+
import type { ProxyResolver } from "../tools/apps/executors.js";
|
|
4
|
+
import { openAppViaSurface } from "../tools/apps/open-proxy.js";
|
|
5
5
|
|
|
6
|
-
describe(
|
|
7
|
-
test(
|
|
6
|
+
describe("openAppViaSurface", () => {
|
|
7
|
+
test("returns proxy result content on success", async () => {
|
|
8
8
|
const resolver: ProxyResolver = async (_name, _input) => ({
|
|
9
|
-
content:
|
|
9
|
+
content: "opened-surface-123",
|
|
10
10
|
isError: false,
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
const result = await openAppViaSurface(
|
|
14
|
-
expect(result).toBe(
|
|
13
|
+
const result = await openAppViaSurface("app-1", resolver);
|
|
14
|
+
expect(result).toBe("opened-surface-123");
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
test(
|
|
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:
|
|
24
|
+
return { content: "ok", isError: false };
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
await openAppViaSurface(
|
|
27
|
+
await openAppViaSurface("my-app", resolver, {
|
|
28
|
+
preview: { title: "Hello" },
|
|
29
|
+
});
|
|
28
30
|
|
|
29
|
-
expect(capturedName).toBe(
|
|
31
|
+
expect(capturedName).toBe("app_open");
|
|
30
32
|
expect(capturedInput).toEqual({
|
|
31
|
-
app_id:
|
|
32
|
-
preview: { title:
|
|
33
|
+
app_id: "my-app",
|
|
34
|
+
preview: { title: "Hello" },
|
|
33
35
|
});
|
|
34
36
|
});
|
|
35
37
|
|
|
36
|
-
test(
|
|
37
|
-
const result = await openAppViaSurface(
|
|
38
|
+
test("returns informational message when resolver is undefined", async () => {
|
|
39
|
+
const result = await openAppViaSurface("app-1", undefined);
|
|
38
40
|
expect(result).toBe(
|
|
39
|
-
|
|
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(
|
|
45
|
+
test("returns fallback text when resolver throws", async () => {
|
|
44
46
|
const resolver: ProxyResolver = async () => {
|
|
45
|
-
throw new Error(
|
|
47
|
+
throw new Error("connection lost");
|
|
46
48
|
};
|
|
47
49
|
|
|
48
|
-
const result = await openAppViaSurface(
|
|
49
|
-
expect(result).toBe(
|
|
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(
|
|
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:
|
|
61
|
+
return { content: "ok", isError: false };
|
|
58
62
|
};
|
|
59
63
|
|
|
60
|
-
await openAppViaSurface(
|
|
61
|
-
expect(capturedInput).toEqual({ app_id:
|
|
64
|
+
await openAppViaSurface("app-2", resolver);
|
|
65
|
+
expect(capturedInput).toEqual({ app_id: "app-2" });
|
|
62
66
|
});
|
|
63
67
|
});
|