@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
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import { mkdirSync, mkdtempSync, rmSync,writeFileSync } from
|
|
2
|
-
import { tmpdir } from
|
|
3
|
-
import { join } from
|
|
4
|
-
|
|
5
|
-
import { afterEach,beforeEach, describe, expect, test } from 'bun:test';
|
|
1
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
6
5
|
|
|
7
6
|
import {
|
|
8
7
|
discoverCCCommands,
|
|
9
8
|
getCCCommand,
|
|
10
9
|
invalidateCCCommandCache,
|
|
11
10
|
loadCCCommandTemplate,
|
|
12
|
-
} from
|
|
11
|
+
} from "../cc-command-registry.js";
|
|
13
12
|
|
|
14
13
|
let tmpDir: string;
|
|
15
14
|
|
|
16
15
|
beforeEach(() => {
|
|
17
|
-
tmpDir = mkdtempSync(join(tmpdir(),
|
|
16
|
+
tmpDir = mkdtempSync(join(tmpdir(), "cc-cmd-test-"));
|
|
18
17
|
invalidateCCCommandCache();
|
|
19
18
|
});
|
|
20
19
|
|
|
@@ -25,118 +24,118 @@ afterEach(() => {
|
|
|
25
24
|
|
|
26
25
|
/** Helper to create a .claude/commands/ directory with markdown files. */
|
|
27
26
|
function createCommandsDir(base: string, files: Record<string, string>): void {
|
|
28
|
-
const commandsDir = join(base,
|
|
27
|
+
const commandsDir = join(base, ".claude", "commands");
|
|
29
28
|
mkdirSync(commandsDir, { recursive: true });
|
|
30
29
|
for (const [name, content] of Object.entries(files)) {
|
|
31
|
-
writeFileSync(join(commandsDir, name), content,
|
|
30
|
+
writeFileSync(join(commandsDir, name), content, "utf-8");
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
describe(
|
|
36
|
-
test(
|
|
34
|
+
describe("discoverCCCommands", () => {
|
|
35
|
+
test("discovers commands in .claude/commands/", () => {
|
|
37
36
|
createCommandsDir(tmpDir, {
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
"hello.md": "# Hello World\nThis is the hello command.",
|
|
38
|
+
"deploy.md": "Deploy the application to production.",
|
|
40
39
|
});
|
|
41
40
|
|
|
42
41
|
const registry = discoverCCCommands(tmpDir);
|
|
43
42
|
expect(registry.entries.size).toBe(2);
|
|
44
43
|
|
|
45
|
-
const hello = registry.entries.get(
|
|
44
|
+
const hello = registry.entries.get("hello");
|
|
46
45
|
expect(hello).toBeDefined();
|
|
47
|
-
expect(hello!.name).toBe(
|
|
48
|
-
expect(hello!.summary).toBe(
|
|
46
|
+
expect(hello!.name).toBe("hello");
|
|
47
|
+
expect(hello!.summary).toBe("Hello World");
|
|
49
48
|
expect(hello!.source).toBe(tmpDir);
|
|
50
49
|
|
|
51
|
-
const deploy = registry.entries.get(
|
|
50
|
+
const deploy = registry.entries.get("deploy");
|
|
52
51
|
expect(deploy).toBeDefined();
|
|
53
|
-
expect(deploy!.name).toBe(
|
|
54
|
-
expect(deploy!.summary).toBe(
|
|
52
|
+
expect(deploy!.name).toBe("deploy");
|
|
53
|
+
expect(deploy!.summary).toBe("Deploy the application to production.");
|
|
55
54
|
});
|
|
56
55
|
|
|
57
|
-
test(
|
|
56
|
+
test("child directory commands override parent on name collisions", () => {
|
|
58
57
|
// Create parent commands
|
|
59
58
|
createCommandsDir(tmpDir, {
|
|
60
|
-
|
|
59
|
+
"shared.md": "Parent version of shared command.",
|
|
61
60
|
});
|
|
62
61
|
|
|
63
62
|
// Create child directory with overriding command
|
|
64
|
-
const childDir = join(tmpDir,
|
|
63
|
+
const childDir = join(tmpDir, "project");
|
|
65
64
|
mkdirSync(childDir, { recursive: true });
|
|
66
65
|
createCommandsDir(childDir, {
|
|
67
|
-
|
|
66
|
+
"shared.md": "Child version of shared command.",
|
|
68
67
|
});
|
|
69
68
|
|
|
70
69
|
const registry = discoverCCCommands(childDir);
|
|
71
|
-
const shared = registry.entries.get(
|
|
70
|
+
const shared = registry.entries.get("shared");
|
|
72
71
|
expect(shared).toBeDefined();
|
|
73
|
-
expect(shared!.summary).toBe(
|
|
72
|
+
expect(shared!.summary).toBe("Child version of shared command.");
|
|
74
73
|
expect(shared!.source).toBe(childDir);
|
|
75
74
|
});
|
|
76
75
|
|
|
77
|
-
test(
|
|
76
|
+
test("invalid filenames are skipped", () => {
|
|
78
77
|
createCommandsDir(tmpDir, {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
"valid-name.md": "A valid command.",
|
|
79
|
+
".hidden.md": "Hidden file should be skipped.",
|
|
80
|
+
"-starts-with-dash.md": "Invalid start character.",
|
|
82
81
|
});
|
|
83
82
|
|
|
84
83
|
const registry = discoverCCCommands(tmpDir);
|
|
85
84
|
expect(registry.entries.size).toBe(1);
|
|
86
|
-
expect(registry.entries.has(
|
|
87
|
-
expect(registry.entries.has(
|
|
88
|
-
expect(registry.entries.has(
|
|
85
|
+
expect(registry.entries.has("valid-name")).toBe(true);
|
|
86
|
+
expect(registry.entries.has(".hidden")).toBe(false);
|
|
87
|
+
expect(registry.entries.has("-starts-with-dash")).toBe(false);
|
|
89
88
|
});
|
|
90
89
|
|
|
91
|
-
test(
|
|
90
|
+
test("non-.md files are ignored", () => {
|
|
92
91
|
createCommandsDir(tmpDir, {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
"readme.txt": "Not a markdown file.",
|
|
93
|
+
"command.md": "A real command.",
|
|
94
|
+
"notes.json": "{}",
|
|
96
95
|
});
|
|
97
96
|
|
|
98
97
|
const registry = discoverCCCommands(tmpDir);
|
|
99
98
|
expect(registry.entries.size).toBe(1);
|
|
100
|
-
expect(registry.entries.has(
|
|
99
|
+
expect(registry.entries.has("command")).toBe(true);
|
|
101
100
|
});
|
|
102
101
|
|
|
103
|
-
test(
|
|
104
|
-
const commandsDir = join(tmpDir,
|
|
102
|
+
test("empty directory returns empty registry", () => {
|
|
103
|
+
const commandsDir = join(tmpDir, ".claude", "commands");
|
|
105
104
|
mkdirSync(commandsDir, { recursive: true });
|
|
106
105
|
|
|
107
106
|
const registry = discoverCCCommands(tmpDir);
|
|
108
107
|
expect(registry.entries.size).toBe(0);
|
|
109
108
|
});
|
|
110
109
|
|
|
111
|
-
test(
|
|
110
|
+
test("no .claude/commands/ directory returns empty registry", () => {
|
|
112
111
|
const registry = discoverCCCommands(tmpDir);
|
|
113
112
|
expect(registry.entries.size).toBe(0);
|
|
114
113
|
});
|
|
115
114
|
|
|
116
|
-
test(
|
|
115
|
+
test("commands from multiple ancestor levels are merged", () => {
|
|
117
116
|
// Parent has a unique command
|
|
118
117
|
createCommandsDir(tmpDir, {
|
|
119
|
-
|
|
118
|
+
"parent-only.md": "Only in parent.",
|
|
120
119
|
});
|
|
121
120
|
|
|
122
121
|
// Child has a different command
|
|
123
|
-
const childDir = join(tmpDir,
|
|
122
|
+
const childDir = join(tmpDir, "child");
|
|
124
123
|
mkdirSync(childDir, { recursive: true });
|
|
125
124
|
createCommandsDir(childDir, {
|
|
126
|
-
|
|
125
|
+
"child-only.md": "Only in child.",
|
|
127
126
|
});
|
|
128
127
|
|
|
129
128
|
const registry = discoverCCCommands(childDir);
|
|
130
129
|
expect(registry.entries.size).toBe(2);
|
|
131
|
-
expect(registry.entries.has(
|
|
132
|
-
expect(registry.entries.has(
|
|
130
|
+
expect(registry.entries.has("parent-only")).toBe(true);
|
|
131
|
+
expect(registry.entries.has("child-only")).toBe(true);
|
|
133
132
|
});
|
|
134
133
|
});
|
|
135
134
|
|
|
136
|
-
describe(
|
|
137
|
-
test(
|
|
135
|
+
describe("caching", () => {
|
|
136
|
+
test("cache returns same instance within TTL", () => {
|
|
138
137
|
createCommandsDir(tmpDir, {
|
|
139
|
-
|
|
138
|
+
"test.md": "Test command.",
|
|
140
139
|
});
|
|
141
140
|
|
|
142
141
|
const first = discoverCCCommands(tmpDir);
|
|
@@ -144,9 +143,9 @@ describe('caching', () => {
|
|
|
144
143
|
expect(first).toBe(second); // same object reference
|
|
145
144
|
});
|
|
146
145
|
|
|
147
|
-
test(
|
|
146
|
+
test("invalidateCCCommandCache forces re-discovery", () => {
|
|
148
147
|
createCommandsDir(tmpDir, {
|
|
149
|
-
|
|
148
|
+
"test.md": "Test command.",
|
|
150
149
|
});
|
|
151
150
|
|
|
152
151
|
const first = discoverCCCommands(tmpDir);
|
|
@@ -158,9 +157,9 @@ describe('caching', () => {
|
|
|
158
157
|
expect(second.entries.size).toBe(1);
|
|
159
158
|
});
|
|
160
159
|
|
|
161
|
-
test(
|
|
160
|
+
test("expired TTL forces re-discovery", () => {
|
|
162
161
|
createCommandsDir(tmpDir, {
|
|
163
|
-
|
|
162
|
+
"test.md": "Test command.",
|
|
164
163
|
});
|
|
165
164
|
|
|
166
165
|
// Use a very short TTL
|
|
@@ -170,40 +169,41 @@ describe('caching', () => {
|
|
|
170
169
|
});
|
|
171
170
|
});
|
|
172
171
|
|
|
173
|
-
describe(
|
|
174
|
-
test(
|
|
172
|
+
describe("getCCCommand", () => {
|
|
173
|
+
test("looks up command by name (case-insensitive)", () => {
|
|
175
174
|
createCommandsDir(tmpDir, {
|
|
176
|
-
|
|
175
|
+
"MyCommand.md": "My command description.",
|
|
177
176
|
});
|
|
178
177
|
|
|
179
|
-
const entry = getCCCommand(tmpDir,
|
|
178
|
+
const entry = getCCCommand(tmpDir, "mycommand");
|
|
180
179
|
expect(entry).toBeDefined();
|
|
181
|
-
expect(entry!.name).toBe(
|
|
180
|
+
expect(entry!.name).toBe("MyCommand");
|
|
182
181
|
|
|
183
|
-
const entryUpper = getCCCommand(tmpDir,
|
|
182
|
+
const entryUpper = getCCCommand(tmpDir, "MYCOMMAND");
|
|
184
183
|
expect(entryUpper).toBeDefined();
|
|
185
|
-
expect(entryUpper!.name).toBe(
|
|
184
|
+
expect(entryUpper!.name).toBe("MyCommand");
|
|
186
185
|
});
|
|
187
186
|
|
|
188
|
-
test(
|
|
187
|
+
test("returns undefined for non-existent command", () => {
|
|
189
188
|
createCommandsDir(tmpDir, {
|
|
190
|
-
|
|
189
|
+
"exists.md": "I exist.",
|
|
191
190
|
});
|
|
192
191
|
|
|
193
|
-
const entry = getCCCommand(tmpDir,
|
|
192
|
+
const entry = getCCCommand(tmpDir, "nonexistent");
|
|
194
193
|
expect(entry).toBeUndefined();
|
|
195
194
|
});
|
|
196
195
|
});
|
|
197
196
|
|
|
198
|
-
describe(
|
|
199
|
-
test(
|
|
200
|
-
const fullContent =
|
|
197
|
+
describe("loadCCCommandTemplate", () => {
|
|
198
|
+
test("reads full file content at execution time", () => {
|
|
199
|
+
const fullContent =
|
|
200
|
+
"---\ntitle: Test\n---\n\n# Test Command\n\nThis is the full template body.\n\n## Arguments\n- arg1: required\n- arg2: optional\n";
|
|
201
201
|
createCommandsDir(tmpDir, {
|
|
202
|
-
|
|
202
|
+
"test.md": fullContent,
|
|
203
203
|
});
|
|
204
204
|
|
|
205
205
|
const registry = discoverCCCommands(tmpDir);
|
|
206
|
-
const entry = registry.entries.get(
|
|
206
|
+
const entry = registry.entries.get("test")!;
|
|
207
207
|
expect(entry).toBeDefined();
|
|
208
208
|
|
|
209
209
|
const template = loadCCCommandTemplate(entry);
|
|
@@ -211,101 +211,106 @@ describe('loadCCCommandTemplate', () => {
|
|
|
211
211
|
});
|
|
212
212
|
});
|
|
213
213
|
|
|
214
|
-
describe(
|
|
215
|
-
test(
|
|
214
|
+
describe("summary extraction", () => {
|
|
215
|
+
test("skips YAML frontmatter", () => {
|
|
216
216
|
createCommandsDir(tmpDir, {
|
|
217
|
-
|
|
217
|
+
"with-frontmatter.md":
|
|
218
|
+
"---\ntitle: My Command\nauthor: test\n---\n\nActual summary line.",
|
|
218
219
|
});
|
|
219
220
|
|
|
220
221
|
const registry = discoverCCCommands(tmpDir);
|
|
221
|
-
const entry = registry.entries.get(
|
|
222
|
+
const entry = registry.entries.get("with-frontmatter");
|
|
222
223
|
expect(entry).toBeDefined();
|
|
223
|
-
expect(entry!.summary).toBe(
|
|
224
|
+
expect(entry!.summary).toBe("Actual summary line.");
|
|
224
225
|
});
|
|
225
226
|
|
|
226
|
-
test(
|
|
227
|
+
test("strips heading markers", () => {
|
|
227
228
|
createCommandsDir(tmpDir, {
|
|
228
|
-
|
|
229
|
+
"heading.md": "## This is a heading",
|
|
229
230
|
});
|
|
230
231
|
|
|
231
232
|
const registry = discoverCCCommands(tmpDir);
|
|
232
|
-
const entry = registry.entries.get(
|
|
233
|
+
const entry = registry.entries.get("heading");
|
|
233
234
|
expect(entry).toBeDefined();
|
|
234
|
-
expect(entry!.summary).toBe(
|
|
235
|
+
expect(entry!.summary).toBe("This is a heading");
|
|
235
236
|
});
|
|
236
237
|
|
|
237
|
-
test(
|
|
238
|
+
test("strips multiple heading levels", () => {
|
|
238
239
|
createCommandsDir(tmpDir, {
|
|
239
|
-
|
|
240
|
-
|
|
240
|
+
"h1.md": "# H1 Heading",
|
|
241
|
+
"h3.md": "### H3 Heading",
|
|
241
242
|
});
|
|
242
243
|
|
|
243
244
|
const registry = discoverCCCommands(tmpDir);
|
|
244
|
-
expect(registry.entries.get(
|
|
245
|
-
expect(registry.entries.get(
|
|
245
|
+
expect(registry.entries.get("h1")!.summary).toBe("H1 Heading");
|
|
246
|
+
expect(registry.entries.get("h3")!.summary).toBe("H3 Heading");
|
|
246
247
|
});
|
|
247
248
|
|
|
248
|
-
test(
|
|
249
|
+
test("skips empty lines before summary", () => {
|
|
249
250
|
createCommandsDir(tmpDir, {
|
|
250
|
-
|
|
251
|
+
"empty-lines.md": "\n\n\nFirst real line.",
|
|
251
252
|
});
|
|
252
253
|
|
|
253
254
|
const registry = discoverCCCommands(tmpDir);
|
|
254
|
-
expect(registry.entries.get(
|
|
255
|
+
expect(registry.entries.get("empty-lines")!.summary).toBe(
|
|
256
|
+
"First real line.",
|
|
257
|
+
);
|
|
255
258
|
});
|
|
256
259
|
|
|
257
|
-
test(
|
|
258
|
-
const longLine =
|
|
260
|
+
test("truncates summary to 100 characters", () => {
|
|
261
|
+
const longLine = "A".repeat(150);
|
|
259
262
|
createCommandsDir(tmpDir, {
|
|
260
|
-
|
|
263
|
+
"long.md": longLine,
|
|
261
264
|
});
|
|
262
265
|
|
|
263
266
|
const registry = discoverCCCommands(tmpDir);
|
|
264
|
-
const entry = registry.entries.get(
|
|
267
|
+
const entry = registry.entries.get("long");
|
|
265
268
|
expect(entry).toBeDefined();
|
|
266
269
|
expect(entry!.summary.length).toBe(100);
|
|
267
|
-
expect(entry!.summary).toBe(
|
|
270
|
+
expect(entry!.summary).toBe("A".repeat(100));
|
|
268
271
|
});
|
|
269
272
|
|
|
270
|
-
test(
|
|
273
|
+
test("handles file with only frontmatter and no content", () => {
|
|
271
274
|
createCommandsDir(tmpDir, {
|
|
272
|
-
|
|
275
|
+
"empty-body.md": "---\ntitle: Empty\n---\n",
|
|
273
276
|
});
|
|
274
277
|
|
|
275
278
|
const registry = discoverCCCommands(tmpDir);
|
|
276
|
-
const entry = registry.entries.get(
|
|
279
|
+
const entry = registry.entries.get("empty-body");
|
|
277
280
|
expect(entry).toBeDefined();
|
|
278
|
-
expect(entry!.summary).toBe(
|
|
281
|
+
expect(entry!.summary).toBe("");
|
|
279
282
|
});
|
|
280
283
|
|
|
281
|
-
test(
|
|
284
|
+
test("returns empty summary when frontmatter is truncated by partial read", () => {
|
|
282
285
|
// Simulate frontmatter that exceeds SUMMARY_READ_BYTES (1024).
|
|
283
286
|
// The closing --- delimiter will be cut off, causing FRONTMATTER_REGEX to
|
|
284
287
|
// fail. extractSummary should return '' instead of '---'.
|
|
285
|
-
const largeFrontmatter =
|
|
288
|
+
const largeFrontmatter =
|
|
289
|
+
"---\n" + "key: " + "x".repeat(1100) + "\n---\n\nActual summary.";
|
|
286
290
|
createCommandsDir(tmpDir, {
|
|
287
|
-
|
|
291
|
+
"big-frontmatter.md": largeFrontmatter,
|
|
288
292
|
});
|
|
289
293
|
|
|
290
294
|
const registry = discoverCCCommands(tmpDir);
|
|
291
|
-
const entry = registry.entries.get(
|
|
295
|
+
const entry = registry.entries.get("big-frontmatter");
|
|
292
296
|
expect(entry).toBeDefined();
|
|
293
|
-
expect(entry!.summary).toBe(
|
|
297
|
+
expect(entry!.summary).toBe("");
|
|
294
298
|
});
|
|
295
299
|
|
|
296
|
-
test(
|
|
297
|
-
const largeFrontmatter =
|
|
300
|
+
test("returns empty summary when frontmatter is truncated (CRLF)", () => {
|
|
301
|
+
const largeFrontmatter =
|
|
302
|
+
"---\r\n" + "key: " + "x".repeat(1100) + "\r\n---\r\n\r\nActual summary.";
|
|
298
303
|
createCommandsDir(tmpDir, {
|
|
299
|
-
|
|
304
|
+
"big-frontmatter-crlf.md": largeFrontmatter,
|
|
300
305
|
});
|
|
301
306
|
|
|
302
307
|
const registry = discoverCCCommands(tmpDir);
|
|
303
|
-
const entry = registry.entries.get(
|
|
308
|
+
const entry = registry.entries.get("big-frontmatter-crlf");
|
|
304
309
|
expect(entry).toBeDefined();
|
|
305
|
-
expect(entry!.summary).toBe(
|
|
310
|
+
expect(entry!.summary).toBe("");
|
|
306
311
|
});
|
|
307
312
|
|
|
308
|
-
test(
|
|
313
|
+
test("returns empty summary when frontmatter is truncated with multibyte UTF-8 characters", () => {
|
|
309
314
|
// When frontmatter contains multibyte UTF-8 characters (e.g., CJK text),
|
|
310
315
|
// the JavaScript string length (UTF-16 code units) is smaller than the
|
|
311
316
|
// byte length. The truncation guard must compare byte length, not
|
|
@@ -314,72 +319,75 @@ describe('summary extraction', () => {
|
|
|
314
319
|
// Each CJK character is 3 bytes in UTF-8 but 1 code unit in UTF-16.
|
|
315
320
|
// We need the total byte count to reach 1024 while string length stays
|
|
316
321
|
// well below 1024 to exercise the bug.
|
|
317
|
-
const cjkChars =
|
|
322
|
+
const cjkChars = "\u4e00".repeat(340); // 340 chars * 3 bytes = 1020 bytes
|
|
318
323
|
// '---\n' is 4 bytes, so total = 4 + 1020 = 1024 bytes, but string
|
|
319
324
|
// length = 4 + 340 = 344 chars — well under 1024.
|
|
320
|
-
const truncatedContent =
|
|
325
|
+
const truncatedContent = "---\n" + cjkChars;
|
|
321
326
|
createCommandsDir(tmpDir, {
|
|
322
|
-
|
|
327
|
+
"multibyte-frontmatter.md": truncatedContent,
|
|
323
328
|
});
|
|
324
329
|
|
|
325
330
|
const registry = discoverCCCommands(tmpDir);
|
|
326
|
-
const entry = registry.entries.get(
|
|
331
|
+
const entry = registry.entries.get("multibyte-frontmatter");
|
|
327
332
|
expect(entry).toBeDefined();
|
|
328
333
|
// Should return '' because the frontmatter opening delimiter is present
|
|
329
334
|
// but the closing delimiter is missing and the byte length reached the
|
|
330
335
|
// read limit — indicating truncation.
|
|
331
|
-
expect(entry!.summary).toBe(
|
|
336
|
+
expect(entry!.summary).toBe("");
|
|
332
337
|
});
|
|
333
338
|
|
|
334
|
-
test(
|
|
339
|
+
test("returns summary for small file starting with thematic break ---", () => {
|
|
335
340
|
// A small markdown file that starts with "---" as a thematic break (not
|
|
336
341
|
// frontmatter) should still have its first content line extracted as a
|
|
337
342
|
// summary, rather than being treated as truncated frontmatter.
|
|
338
343
|
createCommandsDir(tmpDir, {
|
|
339
|
-
|
|
344
|
+
"thematic-break.md":
|
|
345
|
+
"---\nThis is a valid summary after a thematic break.",
|
|
340
346
|
});
|
|
341
347
|
|
|
342
348
|
const registry = discoverCCCommands(tmpDir);
|
|
343
|
-
const entry = registry.entries.get(
|
|
349
|
+
const entry = registry.entries.get("thematic-break");
|
|
344
350
|
expect(entry).toBeDefined();
|
|
345
|
-
expect(entry!.summary).toBe(
|
|
351
|
+
expect(entry!.summary).toBe(
|
|
352
|
+
"This is a valid summary after a thematic break.",
|
|
353
|
+
);
|
|
346
354
|
});
|
|
347
355
|
|
|
348
|
-
test(
|
|
356
|
+
test("handles frontmatter with Windows-style line endings", () => {
|
|
349
357
|
createCommandsDir(tmpDir, {
|
|
350
|
-
|
|
358
|
+
"crlf.md": "---\r\ntitle: Test\r\n---\r\n\r\nSummary with CRLF.",
|
|
351
359
|
});
|
|
352
360
|
|
|
353
361
|
const registry = discoverCCCommands(tmpDir);
|
|
354
|
-
const entry = registry.entries.get(
|
|
362
|
+
const entry = registry.entries.get("crlf");
|
|
355
363
|
expect(entry).toBeDefined();
|
|
356
|
-
expect(entry!.summary).toBe(
|
|
364
|
+
expect(entry!.summary).toBe("Summary with CRLF.");
|
|
357
365
|
});
|
|
358
366
|
});
|
|
359
367
|
|
|
360
|
-
describe(
|
|
361
|
-
test(
|
|
368
|
+
describe("command name validation", () => {
|
|
369
|
+
test("accepts valid names with dots, dashes, underscores", () => {
|
|
362
370
|
createCommandsDir(tmpDir, {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
371
|
+
"my-command.md": "Dashed name.",
|
|
372
|
+
"my_command.md": "Underscored name.",
|
|
373
|
+
"my.command.md": "Dotted name.",
|
|
374
|
+
"Command123.md": "Alphanumeric.",
|
|
375
|
+
"a.md": "Single char.",
|
|
368
376
|
});
|
|
369
377
|
|
|
370
378
|
const registry = discoverCCCommands(tmpDir);
|
|
371
|
-
expect(registry.entries.has(
|
|
372
|
-
expect(registry.entries.has(
|
|
373
|
-
expect(registry.entries.has(
|
|
374
|
-
expect(registry.entries.has(
|
|
375
|
-
expect(registry.entries.has(
|
|
379
|
+
expect(registry.entries.has("my-command")).toBe(true);
|
|
380
|
+
expect(registry.entries.has("my_command")).toBe(true);
|
|
381
|
+
expect(registry.entries.has("my.command")).toBe(true);
|
|
382
|
+
expect(registry.entries.has("command123")).toBe(true);
|
|
383
|
+
expect(registry.entries.has("a")).toBe(true);
|
|
376
384
|
});
|
|
377
385
|
|
|
378
|
-
test(
|
|
386
|
+
test("rejects names starting with special characters", () => {
|
|
379
387
|
createCommandsDir(tmpDir, {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
388
|
+
"_start.md": "Starts with underscore.",
|
|
389
|
+
".start.md": "Starts with dot.",
|
|
390
|
+
"-start.md": "Starts with dash.",
|
|
383
391
|
});
|
|
384
392
|
|
|
385
393
|
const registry = discoverCCCommands(tmpDir);
|