@vellumai/assistant 0.5.6 → 0.5.8
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/.env.example +16 -2
- package/ARCHITECTURE.md +6 -75
- package/Dockerfile +3 -2
- package/README.md +0 -2
- package/bun.lock +0 -414
- package/docker-entrypoint.sh +9 -0
- package/docs/architecture/keychain-broker.md +45 -240
- package/docs/architecture/memory.md +13 -11
- package/docs/architecture/security.md +0 -17
- package/docs/credential-execution-service.md +2 -2
- package/node_modules/@vellumai/ces-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-contracts/src/error.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/grants.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/index.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +120 -1
- package/node_modules/@vellumai/credential-storage/package.json +1 -0
- package/node_modules/@vellumai/egress-proxy/package.json +1 -0
- package/package.json +2 -3
- package/src/__tests__/actor-token-service.test.ts +0 -114
- package/src/__tests__/approval-cascade.test.ts +0 -1
- package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/browser-skill-endstate.test.ts +6 -5
- package/src/__tests__/btw-routes.test.ts +0 -39
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/call-domain.test.ts +0 -128
- package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
- package/src/__tests__/ces-startup-timeout.test.ts +40 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -5
- package/src/__tests__/channel-readiness-service.test.ts +1 -60
- package/src/__tests__/checker.test.ts +4 -2
- package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -2
- package/src/__tests__/config-schema.test.ts +3 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop.test.ts +2 -4
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -1
- package/src/__tests__/conversation-error.test.ts +15 -1
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-messaging-secret-redirect.test.ts +1 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +0 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -1
- package/src/__tests__/conversation-queue.test.ts +0 -1
- package/src/__tests__/conversation-skill-tools.test.ts +0 -54
- package/src/__tests__/conversation-slash-queue.test.ts +0 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -1
- package/src/__tests__/conversation-title-service.test.ts +87 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -1
- package/src/__tests__/credential-execution-client.test.ts +5 -2
- package/src/__tests__/credential-execution-feature-gates.test.ts +59 -30
- package/src/__tests__/credential-execution-managed-contract.test.ts +35 -20
- package/src/__tests__/credential-security-e2e.test.ts +1 -67
- package/src/__tests__/credential-security-invariants.test.ts +6 -50
- package/src/__tests__/credentials-cli.test.ts +82 -3
- package/src/__tests__/daemon-credential-client.test.ts +123 -0
- package/src/__tests__/db-migration-rollback.test.ts +2015 -1
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +34 -143
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
- package/src/__tests__/gateway-client-managed-outbound.test.ts +79 -1
- package/src/__tests__/guardian-routing-state.test.ts +0 -5
- package/src/__tests__/host-shell-tool.test.ts +6 -7
- package/src/__tests__/http-user-message-parity.test.ts +3 -103
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
- package/src/__tests__/intent-routing.test.ts +0 -13
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
- package/src/__tests__/journal-context.test.ts +335 -0
- package/src/__tests__/keychain-broker-client.test.ts +161 -22
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -3
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
- package/src/__tests__/memory-lifecycle-e2e.test.ts +70 -25
- package/src/__tests__/memory-recall-quality.test.ts +48 -17
- package/src/__tests__/memory-regressions.test.ts +408 -363
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -3
- package/src/__tests__/migration-export-http.test.ts +2 -2
- package/src/__tests__/migration-import-commit-http.test.ts +2 -2
- package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
- package/src/__tests__/migration-validate-http.test.ts +2 -2
- package/src/__tests__/non-member-access-request.test.ts +2 -7
- package/src/__tests__/notification-decision-fallback.test.ts +4 -0
- package/src/__tests__/notification-decision-identity.test.ts +4 -0
- package/src/__tests__/notification-decision-strategy.test.ts +71 -0
- package/src/__tests__/oauth-cli.test.ts +5 -1
- package/src/__tests__/permission-types.test.ts +1 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -37
- package/src/__tests__/provider-error-scenarios.test.ts +0 -267
- package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
- package/src/__tests__/provider-streaming.benchmark.test.ts +2 -81
- package/src/__tests__/qdrant-manager.test.ts +28 -2
- package/src/__tests__/registry.test.ts +0 -6
- package/src/__tests__/relay-server.test.ts +1 -2
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
- package/src/__tests__/script-proxy-injection-runtime.test.ts +1 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -1
- package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
- package/src/__tests__/secure-keys.test.ts +95 -272
- package/src/__tests__/shell-identity.test.ts +96 -6
- package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
- package/src/__tests__/skill-feature-flags.test.ts +46 -45
- package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
- package/src/__tests__/skill-load-inline-command.test.ts +8 -12
- package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
- package/src/__tests__/skill-load-tool.test.ts +0 -2
- package/src/__tests__/skill-memory.test.ts +17 -3
- package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
- package/src/__tests__/skills.test.ts +0 -2
- package/src/__tests__/slack-inbound-verification.test.ts +0 -4
- package/src/__tests__/stale-approval-dedup.test.ts +171 -0
- package/src/__tests__/stt-hints.test.ts +437 -0
- package/src/__tests__/suggestion-routes.test.ts +1 -32
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/task-memory-cleanup.test.ts +14 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
- package/src/__tests__/twilio-routes-twiml.test.ts +139 -1
- package/src/__tests__/update-bulletin.test.ts +0 -2
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
- package/src/__tests__/voice-quality.test.ts +58 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -7
- package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
- package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +220 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
- package/src/acp/agent-process.ts +9 -1
- package/src/agent/loop.ts +1 -1
- package/src/approvals/guardian-request-resolvers.ts +164 -38
- package/src/calls/__tests__/tts-text-sanitizer.test.ts +254 -0
- package/src/calls/audio-store.test.ts +97 -0
- package/src/calls/audio-store.ts +205 -0
- package/src/calls/call-controller.ts +90 -8
- package/src/calls/call-domain.ts +3 -0
- package/src/calls/call-store.ts +10 -3
- package/src/calls/fish-audio-client.ts +129 -0
- package/src/calls/relay-server.ts +27 -0
- package/src/calls/stt-hints.ts +189 -0
- package/src/calls/tts-text-sanitizer.ts +61 -0
- package/src/calls/twilio-routes.ts +34 -5
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-ingress-preflight.ts +0 -42
- package/src/calls/voice-quality.ts +38 -5
- package/src/calls/voice-session-bridge.ts +7 -12
- package/src/cli/commands/avatar.ts +2 -2
- package/src/cli/commands/config.ts +1 -4
- package/src/cli/commands/credentials.ts +128 -82
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/keys.ts +7 -7
- package/src/cli/commands/memory.ts +1 -1
- package/src/cli/commands/oauth/connections.ts +11 -29
- package/src/cli/commands/oauth/index.ts +7 -0
- package/src/cli/commands/oauth/platform.ts +525 -0
- package/src/cli/commands/platform.ts +3 -3
- package/src/cli/lib/daemon-credential-client.ts +284 -0
- package/src/cli.ts +1 -1
- package/src/config/assistant-feature-flags.ts +186 -5
- package/src/config/bundled-skills/AGENTS.md +34 -0
- package/src/config/bundled-skills/acp/SKILL.md +10 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +0 -4
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
- package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -0
- package/src/config/bundled-skills/settings/SKILL.md +15 -2
- package/src/config/bundled-skills/settings/TOOLS.json +47 -2
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +59 -0
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +80 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
- package/src/config/bundled-skills/slack/SKILL.md +1 -1
- package/src/config/bundled-tool-registry.ts +5 -11
- package/src/config/defaults.ts +0 -2
- package/src/config/env-registry.ts +5 -5
- package/src/config/env.ts +21 -14
- package/src/config/feature-flag-registry.json +49 -9
- package/src/config/loader.ts +106 -42
- package/src/config/schema.ts +9 -29
- package/src/config/schemas/calls.ts +30 -0
- package/src/config/schemas/fish-audio.ts +39 -0
- package/src/config/schemas/inference.ts +2 -2
- package/src/config/schemas/journal.ts +16 -0
- package/src/config/schemas/memory-processing.ts +2 -2
- package/src/config/schemas/security.ts +0 -4
- package/src/config/types.ts +1 -1
- package/src/contacts/contact-store.ts +39 -0
- package/src/contacts/types.ts +2 -0
- package/src/credential-execution/approval-bridge.ts +1 -0
- package/src/credential-execution/executable-discovery.ts +28 -4
- package/src/credential-execution/feature-gates.ts +16 -0
- package/src/credential-execution/process-manager.ts +38 -0
- package/src/credential-execution/startup-timeout.ts +36 -0
- package/src/daemon/approval-generators.ts +3 -9
- package/src/daemon/assistant-attachments.ts +9 -0
- package/src/daemon/config-watcher.ts +5 -0
- package/src/daemon/conversation-error.ts +13 -1
- package/src/daemon/conversation-memory.ts +1 -2
- package/src/daemon/conversation-process.ts +18 -1
- package/src/daemon/conversation-surfaces.ts +30 -1
- package/src/daemon/conversation-tool-setup.ts +0 -105
- package/src/daemon/conversation.ts +21 -1
- package/src/daemon/guardian-action-generators.ts +3 -9
- package/src/daemon/handlers/config-vercel.ts +92 -0
- package/src/daemon/handlers/skills.ts +2 -15
- package/src/daemon/install-symlink.ts +195 -0
- package/src/daemon/lifecycle.ts +234 -51
- package/src/daemon/message-types/conversations.ts +4 -4
- package/src/daemon/message-types/diagnostics.ts +3 -22
- package/src/daemon/message-types/messages.ts +0 -2
- package/src/daemon/message-types/upgrades.ts +8 -0
- package/src/daemon/server.ts +32 -95
- package/src/events/domain-events.ts +2 -1
- package/src/inbound/platform-callback-registration.ts +3 -3
- package/src/instrument.ts +8 -5
- package/src/memory/app-store.ts +31 -0
- package/src/memory/conversation-title-service.ts +50 -1
- package/src/memory/db-init.ts +16 -0
- package/src/memory/indexer.ts +19 -10
- package/src/memory/items-extractor.ts +328 -321
- package/src/memory/job-handlers/conversation-starters.ts +4 -1
- package/src/memory/job-handlers/summarization.ts +26 -16
- package/src/memory/jobs-store.ts +63 -6
- package/src/memory/jobs-worker.ts +31 -7
- package/src/memory/journal-memory.ts +214 -0
- package/src/memory/migrations/001-job-deferrals.ts +19 -0
- package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
- package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
- package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
- package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
- package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
- package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
- package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
- package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
- package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
- package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
- package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
- package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
- package/src/memory/migrations/116-messages-fts.ts +106 -1
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
- package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
- package/src/memory/migrations/141-rename-verification-table.ts +54 -0
- package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
- package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
- package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
- package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
- package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
- package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
- package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
- package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
- package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
- package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
- package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
- package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
- package/src/memory/migrations/193-add-source-type-columns.ts +81 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/migrations/registry.ts +98 -0
- package/src/memory/migrations/validate-migration-state.ts +137 -11
- package/src/memory/qdrant-circuit-breaker.ts +9 -0
- package/src/memory/qdrant-manager.ts +64 -7
- package/src/memory/retriever.test.ts +37 -25
- package/src/memory/retriever.ts +24 -49
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/contacts.ts +1 -0
- package/src/memory/schema/memory-core.ts +2 -0
- package/src/memory/search/formatting.ts +7 -44
- package/src/memory/search/staleness.ts +4 -0
- package/src/memory/search/tier-classifier.ts +10 -2
- package/src/memory/search/types.ts +2 -5
- package/src/memory/task-memory-cleanup.ts +4 -3
- package/src/notifications/adapters/slack.ts +168 -6
- package/src/notifications/broadcaster.ts +1 -0
- package/src/notifications/copy-composer.ts +59 -2
- package/src/notifications/decision-engine.ts +4 -1
- package/src/notifications/signal.ts +2 -0
- package/src/notifications/types.ts +2 -0
- package/src/oauth/connection-resolver.ts +6 -4
- package/src/permissions/checker.ts +0 -38
- package/src/permissions/shell-identity.ts +76 -22
- package/src/permissions/types.ts +4 -2
- package/src/platform/client.ts +35 -7
- package/src/prompts/journal-context.ts +133 -0
- package/src/prompts/persona-resolver.ts +194 -0
- package/src/prompts/system-prompt.ts +44 -4
- package/src/prompts/templates/SOUL.md +10 -0
- package/src/prompts/templates/users/default.md +1 -0
- package/src/providers/provider-send-message.ts +3 -32
- package/src/providers/registry.ts +29 -179
- package/src/providers/types.ts +1 -1
- package/src/runtime/access-request-helper.ts +4 -0
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
- package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
- package/src/runtime/auth/__tests__/guard-tests.test.ts +9 -50
- package/src/runtime/auth/external-assistant-id.ts +13 -59
- package/src/runtime/auth/route-policy.ts +17 -1
- package/src/runtime/auth/token-service.ts +43 -138
- package/src/runtime/channel-readiness-service.ts +1 -16
- package/src/runtime/gateway-client.ts +47 -4
- package/src/runtime/guardian-decision-types.ts +45 -4
- package/src/runtime/http-server.ts +31 -3
- package/src/runtime/middleware/error-handler.ts +1 -9
- package/src/runtime/routes/access-request-decision.ts +2 -2
- package/src/runtime/routes/app-management-routes.ts +2 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +219 -30
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +37 -14
- package/src/runtime/routes/audio-routes.ts +40 -0
- package/src/runtime/routes/btw-routes.ts +0 -17
- package/src/runtime/routes/channel-readiness-routes.ts +9 -4
- package/src/runtime/routes/conversation-query-routes.ts +63 -1
- package/src/runtime/routes/conversation-routes.ts +4 -44
- package/src/runtime/routes/debug-routes.ts +12 -9
- package/src/runtime/routes/diagnostics-routes.ts +1 -477
- package/src/runtime/routes/guardian-approval-interception.ts +168 -11
- package/src/runtime/routes/guardian-approval-prompt.ts +6 -1
- package/src/runtime/routes/guardian-approval-reply-helpers.ts +103 -21
- package/src/runtime/routes/identity-routes.ts +19 -30
- package/src/runtime/routes/inbound-message-handler.ts +31 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +64 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +52 -40
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
- package/src/runtime/routes/integrations/twilio.ts +52 -10
- package/src/runtime/routes/integrations/vercel.ts +89 -0
- package/src/runtime/routes/log-export-routes.ts +5 -0
- package/src/runtime/routes/memory-item-routes.test.ts +3 -3
- package/src/runtime/routes/memory-item-routes.ts +46 -14
- package/src/runtime/routes/migration-rollback-routes.ts +209 -0
- package/src/runtime/routes/migration-routes.ts +17 -1
- package/src/runtime/routes/notification-routes.ts +58 -0
- package/src/runtime/routes/schedule-routes.ts +65 -0
- package/src/runtime/routes/secret-routes.ts +141 -10
- package/src/runtime/routes/settings-routes.ts +41 -1
- package/src/runtime/routes/tts-routes.ts +96 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +26 -2
- package/src/runtime/routes/workspace-commit-routes.ts +62 -0
- package/src/runtime/routes/workspace-routes.test.ts +22 -1
- package/src/runtime/routes/workspace-routes.ts +1 -1
- package/src/runtime/routes/workspace-utils.ts +86 -2
- package/src/security/ces-credential-client.ts +75 -29
- package/src/security/ces-rpc-credential-backend.ts +86 -0
- package/src/security/credential-backend.ts +22 -92
- package/src/security/keychain-broker-client.ts +10 -2
- package/src/security/secure-keys.ts +113 -115
- package/src/skills/catalog-install.ts +6 -32
- package/src/skills/skill-memory.ts +1 -0
- package/src/subagent/manager.ts +2 -5
- package/src/telemetry/usage-telemetry-reporter.ts +4 -2
- package/src/tools/acp/spawn.ts +78 -1
- package/src/tools/calls/call-start.ts +1 -0
- package/src/tools/credentials/vault.ts +5 -3
- package/src/tools/executor.ts +0 -4
- package/src/tools/memory/definitions.ts +3 -2
- package/src/tools/memory/handlers.ts +10 -7
- package/src/tools/network/script-proxy/session-manager.ts +19 -4
- package/src/tools/network/web-fetch.ts +3 -1
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/types.ts +0 -8
- package/src/util/browser.ts +15 -0
- package/src/util/errors.ts +0 -12
- package/src/util/platform.ts +4 -51
- package/src/workspace/git-service.ts +5 -2
- package/src/workspace/migrations/001-avatar-rename.ts +15 -0
- package/src/workspace/migrations/003-seed-device-id.ts +17 -1
- package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
- package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
- package/src/workspace/migrations/006-services-config.ts +49 -0
- package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
- package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
- package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
- package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
- package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
- package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
- package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
- package/src/workspace/migrations/017-seed-persona-dirs.ts +96 -0
- package/src/workspace/migrations/018-rekey-compound-credential-keys.ts +184 -0
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +103 -0
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +27 -5
- package/src/workspace/migrations/registry.ts +12 -0
- package/src/workspace/migrations/runner.ts +106 -2
- package/src/workspace/migrations/types.ts +4 -0
- package/src/workspace/provider-commit-message-generator.ts +12 -21
- package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
- package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
- package/src/__tests__/diagnostics-export.test.ts +0 -288
- package/src/__tests__/local-gateway-health.test.ts +0 -209
- package/src/__tests__/provider-fail-open-selection.test.ts +0 -271
- package/src/__tests__/provider-failover-actual-provider.test.ts +0 -66
- package/src/__tests__/secret-ingress-handler.test.ts +0 -120
- package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
- package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
- package/src/__tests__/swarm-orchestrator.test.ts +0 -463
- package/src/__tests__/swarm-plan-validator.test.ts +0 -384
- package/src/__tests__/swarm-recursion.test.ts +0 -197
- package/src/__tests__/swarm-router-planner.test.ts +0 -234
- package/src/__tests__/swarm-tool.test.ts +0 -185
- package/src/__tests__/swarm-worker-backend.test.ts +0 -144
- package/src/__tests__/swarm-worker-runner.test.ts +0 -288
- package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
- package/src/commands/cc-command-registry.ts +0 -248
- package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
- package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
- package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
- package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
- package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
- package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
- package/src/config/schemas/swarm.ts +0 -82
- package/src/logfire.ts +0 -135
- package/src/memory/search/lexical.ts +0 -48
- package/src/providers/failover.ts +0 -186
- package/src/runtime/local-gateway-health.ts +0 -275
- package/src/security/secret-ingress.ts +0 -68
- package/src/swarm/backend-claude-code.ts +0 -225
- package/src/swarm/checkpoint.ts +0 -137
- package/src/swarm/graph-utils.ts +0 -53
- package/src/swarm/index.ts +0 -55
- package/src/swarm/limits.ts +0 -66
- package/src/swarm/orchestrator.ts +0 -424
- package/src/swarm/plan-validator.ts +0 -117
- package/src/swarm/router-planner.ts +0 -162
- package/src/swarm/router-prompts.ts +0 -39
- package/src/swarm/synthesizer.ts +0 -81
- package/src/swarm/types.ts +0 -72
- package/src/swarm/worker-backend.ts +0 -131
- package/src/swarm/worker-prompts.ts +0 -80
- package/src/swarm/worker-runner.ts +0 -170
- package/src/tools/claude-code/claude-code.ts +0 -610
- package/src/tools/swarm/delegate.ts +0 -205
|
@@ -209,11 +209,9 @@ mock.module("../util/logger.js", () => ({
|
|
|
209
209
|
mock.module("../config/loader.js", () => ({
|
|
210
210
|
getConfig: () => ({
|
|
211
211
|
skills: { entries: {}, allowBundled: null },
|
|
212
|
-
assistantFeatureFlagValues: {},
|
|
213
212
|
}),
|
|
214
213
|
loadConfig: () => ({
|
|
215
214
|
skills: { entries: {}, allowBundled: null },
|
|
216
|
-
assistantFeatureFlagValues: {},
|
|
217
215
|
}),
|
|
218
216
|
invalidateConfigCache: () => {},
|
|
219
217
|
}));
|
|
@@ -1721,58 +1719,6 @@ describe("bundled skill: gmail", () => {
|
|
|
1721
1719
|
});
|
|
1722
1720
|
});
|
|
1723
1721
|
|
|
1724
|
-
describe("bundled skill: claude-code", () => {
|
|
1725
|
-
let sessionState: Map<string, string>;
|
|
1726
|
-
|
|
1727
|
-
beforeEach(() => {
|
|
1728
|
-
mockCatalog = [];
|
|
1729
|
-
mockManifests = {};
|
|
1730
|
-
mockRegisteredTools = new Map();
|
|
1731
|
-
mockUnregisteredSkillIds = [];
|
|
1732
|
-
mockSkillRefCount = new Map();
|
|
1733
|
-
mockSkillRefCount = new Map();
|
|
1734
|
-
mockVersionHashes = {};
|
|
1735
|
-
mockVersionHashErrors = new Set();
|
|
1736
|
-
sessionState = new Map<string, string>();
|
|
1737
|
-
});
|
|
1738
|
-
|
|
1739
|
-
test("claude-code skill activation registers claude_code in allowedToolNames", () => {
|
|
1740
|
-
mockCatalog = [
|
|
1741
|
-
makeSkill("claude-code", "/path/to/bundled-skills/claude-code"),
|
|
1742
|
-
];
|
|
1743
|
-
mockManifests = { "claude-code": makeManifest(["claude_code"]) };
|
|
1744
|
-
|
|
1745
|
-
const history: Message[] = [
|
|
1746
|
-
...skillLoadMessages('<loaded_skill id="claude-code" />'),
|
|
1747
|
-
];
|
|
1748
|
-
|
|
1749
|
-
const result = projectSkillTools(history, {
|
|
1750
|
-
previouslyActiveSkillIds: sessionState,
|
|
1751
|
-
});
|
|
1752
|
-
|
|
1753
|
-
expect(result.toolDefinitions).toEqual([]);
|
|
1754
|
-
expect(result.allowedToolNames).toEqual(new Set(["claude_code"]));
|
|
1755
|
-
});
|
|
1756
|
-
|
|
1757
|
-
test("claude_code tool is absent when claude-code skill is not active", () => {
|
|
1758
|
-
mockCatalog = [
|
|
1759
|
-
makeSkill("claude-code", "/path/to/bundled-skills/claude-code"),
|
|
1760
|
-
];
|
|
1761
|
-
mockManifests = { "claude-code": makeManifest(["claude_code"]) };
|
|
1762
|
-
|
|
1763
|
-
const history: Message[] = [
|
|
1764
|
-
{ role: "user", content: [{ type: "text", text: "Hello" }] },
|
|
1765
|
-
];
|
|
1766
|
-
|
|
1767
|
-
const result = projectSkillTools(history, {
|
|
1768
|
-
previouslyActiveSkillIds: sessionState,
|
|
1769
|
-
});
|
|
1770
|
-
|
|
1771
|
-
expect(result.toolDefinitions).toHaveLength(0);
|
|
1772
|
-
expect(result.allowedToolNames.has("claude_code")).toBe(false);
|
|
1773
|
-
});
|
|
1774
|
-
});
|
|
1775
|
-
|
|
1776
1722
|
// ---------------------------------------------------------------------------
|
|
1777
1723
|
// Bundled skill: app-builder
|
|
1778
1724
|
// ---------------------------------------------------------------------------
|
|
@@ -107,6 +107,93 @@ describe("conversation-title-service", () => {
|
|
|
107
107
|
);
|
|
108
108
|
});
|
|
109
109
|
|
|
110
|
+
test("regeneration extracts text from JSON content blocks", async () => {
|
|
111
|
+
mockGetMessages.mockReturnValueOnce([
|
|
112
|
+
{
|
|
113
|
+
role: "user",
|
|
114
|
+
content: JSON.stringify([
|
|
115
|
+
{ type: "text", text: "Help me plan the kickoff" },
|
|
116
|
+
]),
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
role: "assistant",
|
|
120
|
+
content: JSON.stringify([
|
|
121
|
+
{ type: "text", text: "Sure, here's a plan" },
|
|
122
|
+
{ type: "tool_use", id: "toolu_1", name: "web_search", input: {} },
|
|
123
|
+
]),
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
role: "user",
|
|
127
|
+
content: JSON.stringify([{ type: "text", text: "Looks good" }]),
|
|
128
|
+
},
|
|
129
|
+
]);
|
|
130
|
+
|
|
131
|
+
const provider = {
|
|
132
|
+
name: "test-provider",
|
|
133
|
+
sendMessage: mock(async () => {
|
|
134
|
+
throw new Error("should not call directly");
|
|
135
|
+
}),
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
await regenerateConversationTitle({ conversationId: "conv-1", provider });
|
|
139
|
+
|
|
140
|
+
// The prompt sent to the sidechain should contain plain text, not raw JSON
|
|
141
|
+
const prompt = (mockRunBtwSidechain.mock.calls[0] as any)?.[0]
|
|
142
|
+
?.content as string;
|
|
143
|
+
expect(prompt).not.toContain('"type":"text"');
|
|
144
|
+
expect(prompt).not.toContain('"type":"tool_use"');
|
|
145
|
+
// Tool metadata should NOT appear in the title prompt
|
|
146
|
+
expect(prompt).not.toContain("Tool use");
|
|
147
|
+
expect(prompt).not.toContain("web_search");
|
|
148
|
+
expect(prompt).toContain("Help me plan the kickoff");
|
|
149
|
+
expect(prompt).toContain("Sure, here's a plan");
|
|
150
|
+
expect(prompt).toContain("Looks good");
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("regeneration extracts text from tool_result content blocks", async () => {
|
|
154
|
+
mockGetMessages.mockReturnValueOnce([
|
|
155
|
+
{
|
|
156
|
+
role: "user",
|
|
157
|
+
content: JSON.stringify([
|
|
158
|
+
{ type: "text", text: "Search for restaurants" },
|
|
159
|
+
]),
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
role: "assistant",
|
|
163
|
+
content: JSON.stringify([
|
|
164
|
+
{ type: "tool_use", id: "toolu_1", name: "web_search", input: {} },
|
|
165
|
+
]),
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
role: "user",
|
|
169
|
+
content: JSON.stringify([
|
|
170
|
+
{
|
|
171
|
+
type: "tool_result",
|
|
172
|
+
tool_use_id: "toolu_1",
|
|
173
|
+
content: "Found 3 restaurants nearby",
|
|
174
|
+
},
|
|
175
|
+
]),
|
|
176
|
+
},
|
|
177
|
+
]);
|
|
178
|
+
|
|
179
|
+
const provider = {
|
|
180
|
+
name: "test-provider",
|
|
181
|
+
sendMessage: mock(async () => {
|
|
182
|
+
throw new Error("should not call directly");
|
|
183
|
+
}),
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
await regenerateConversationTitle({ conversationId: "conv-1", provider });
|
|
187
|
+
|
|
188
|
+
const prompt = (mockRunBtwSidechain.mock.calls[0] as any)?.[0]
|
|
189
|
+
?.content as string;
|
|
190
|
+
expect(prompt).not.toContain('"type":"tool_result"');
|
|
191
|
+
// Tool-only assistant message should be skipped entirely
|
|
192
|
+
expect(prompt).not.toContain("Tool use");
|
|
193
|
+
expect(prompt).toContain("Search for restaurants");
|
|
194
|
+
expect(prompt).toContain("Found 3 restaurants nearby");
|
|
195
|
+
});
|
|
196
|
+
|
|
110
197
|
test("uses the BTW side-chain helper for title regeneration", async () => {
|
|
111
198
|
const provider = {
|
|
112
199
|
name: "test-provider",
|
|
@@ -84,6 +84,9 @@ describe("local CES discovery", () => {
|
|
|
84
84
|
if (result.mode === "unavailable") {
|
|
85
85
|
expect(result.reason).toContain("CES executable not found");
|
|
86
86
|
expect(result.mode).toBe("unavailable");
|
|
87
|
+
} else if (result.mode === "local-source") {
|
|
88
|
+
// Source entry point exists in the monorepo — verify the success shape.
|
|
89
|
+
expect(result.sourcePath).toBeTruthy();
|
|
87
90
|
} else {
|
|
88
91
|
// Binary exists in this environment — verify the success shape.
|
|
89
92
|
expect(result.mode).toBe("local");
|
|
@@ -95,9 +98,9 @@ describe("local CES discovery", () => {
|
|
|
95
98
|
|
|
96
99
|
test("never returns a fallback or in-process mode", () => {
|
|
97
100
|
const result = discoverLocalCes();
|
|
98
|
-
// The result must be
|
|
101
|
+
// The result must be "local", "local-source", or "unavailable".
|
|
99
102
|
// There must never be a fallback mode like "in-process" or "degraded".
|
|
100
|
-
expect(["local", "unavailable"]).toContain(result.mode);
|
|
103
|
+
expect(["local", "local-source", "unavailable"]).toContain(result.mode);
|
|
101
104
|
});
|
|
102
105
|
});
|
|
103
106
|
|
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
* Tests for CES (Credential Execution Service) feature gates.
|
|
3
3
|
*
|
|
4
4
|
* Verifies:
|
|
5
|
-
* -
|
|
6
|
-
* - Each flag can be
|
|
5
|
+
* - Each CES flag defaults to its registry-declared value.
|
|
6
|
+
* - Each flag can be toggled independently via config overrides.
|
|
7
7
|
* - Enabling CES flags does not implicitly change unrelated approval
|
|
8
8
|
* behavior or existing feature flags.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { describe, expect, test } from "bun:test";
|
|
11
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
_setOverridesForTesting,
|
|
15
|
+
isAssistantFeatureFlagEnabled,
|
|
16
|
+
} from "../config/assistant-feature-flags.js";
|
|
14
17
|
import type { AssistantConfig } from "../config/schema.js";
|
|
15
18
|
import {
|
|
16
19
|
CES_GRANT_AUDIT_FLAG_KEY,
|
|
@@ -25,15 +28,21 @@ import {
|
|
|
25
28
|
isCesToolsEnabled,
|
|
26
29
|
} from "../credential-execution/feature-gates.js";
|
|
27
30
|
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
_setOverridesForTesting({});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
_setOverridesForTesting({});
|
|
37
|
+
});
|
|
38
|
+
|
|
28
39
|
// ---------------------------------------------------------------------------
|
|
29
40
|
// Helpers
|
|
30
41
|
// ---------------------------------------------------------------------------
|
|
31
42
|
|
|
32
|
-
/** Create a minimal AssistantConfig
|
|
33
|
-
function makeConfig(
|
|
34
|
-
return {
|
|
35
|
-
...(flagOverrides ? { assistantFeatureFlagValues: flagOverrides } : {}),
|
|
36
|
-
} as AssistantConfig;
|
|
43
|
+
/** Create a minimal AssistantConfig (flag overrides are now set via _setOverridesForTesting). */
|
|
44
|
+
function makeConfig(): AssistantConfig {
|
|
45
|
+
return {} as AssistantConfig;
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
/** All CES flag keys for iteration. */
|
|
@@ -45,28 +54,37 @@ const ALL_CES_FLAG_KEYS = [
|
|
|
45
54
|
CES_MANAGED_SIDECAR_FLAG_KEY,
|
|
46
55
|
] as const;
|
|
47
56
|
|
|
48
|
-
/** All CES predicate functions paired with their flag keys. */
|
|
57
|
+
/** All CES predicate functions paired with their flag keys and expected defaults. */
|
|
49
58
|
const ALL_CES_PREDICATES = [
|
|
50
|
-
{
|
|
59
|
+
{
|
|
60
|
+
name: "isCesToolsEnabled",
|
|
61
|
+
fn: isCesToolsEnabled,
|
|
62
|
+
key: CES_TOOLS_FLAG_KEY,
|
|
63
|
+
defaultEnabled: false,
|
|
64
|
+
},
|
|
51
65
|
{
|
|
52
66
|
name: "isCesShellLockdownEnabled",
|
|
53
67
|
fn: isCesShellLockdownEnabled,
|
|
54
68
|
key: CES_SHELL_LOCKDOWN_FLAG_KEY,
|
|
69
|
+
defaultEnabled: false,
|
|
55
70
|
},
|
|
56
71
|
{
|
|
57
72
|
name: "isCesSecureInstallEnabled",
|
|
58
73
|
fn: isCesSecureInstallEnabled,
|
|
59
74
|
key: CES_SECURE_INSTALL_FLAG_KEY,
|
|
75
|
+
defaultEnabled: false,
|
|
60
76
|
},
|
|
61
77
|
{
|
|
62
78
|
name: "isCesGrantAuditEnabled",
|
|
63
79
|
fn: isCesGrantAuditEnabled,
|
|
64
80
|
key: CES_GRANT_AUDIT_FLAG_KEY,
|
|
81
|
+
defaultEnabled: false,
|
|
65
82
|
},
|
|
66
83
|
{
|
|
67
84
|
name: "isCesManagedSidecarEnabled",
|
|
68
85
|
fn: isCesManagedSidecarEnabled,
|
|
69
86
|
key: CES_MANAGED_SIDECAR_FLAG_KEY,
|
|
87
|
+
defaultEnabled: true,
|
|
70
88
|
},
|
|
71
89
|
] as const;
|
|
72
90
|
|
|
@@ -83,21 +101,23 @@ describe("CES flag key format", () => {
|
|
|
83
101
|
});
|
|
84
102
|
|
|
85
103
|
// ---------------------------------------------------------------------------
|
|
86
|
-
//
|
|
104
|
+
// Defaults: each CES flag matches its registry-declared default
|
|
87
105
|
// ---------------------------------------------------------------------------
|
|
88
106
|
|
|
89
|
-
describe("CES flags
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
expect(fn(config)).toBe(false);
|
|
107
|
+
describe("CES flags match registry defaults", () => {
|
|
108
|
+
for (const { name, fn, defaultEnabled } of ALL_CES_PREDICATES) {
|
|
109
|
+
test(`${name} returns ${defaultEnabled} with no config overrides`, () => {
|
|
110
|
+
const config = makeConfig();
|
|
111
|
+
expect(fn(config)).toBe(defaultEnabled);
|
|
95
112
|
});
|
|
96
113
|
}
|
|
97
114
|
|
|
98
|
-
for (const
|
|
99
|
-
test(`isAssistantFeatureFlagEnabled('${key}') returns
|
|
100
|
-
|
|
115
|
+
for (const pred of ALL_CES_PREDICATES) {
|
|
116
|
+
test(`isAssistantFeatureFlagEnabled('${pred.key}') returns ${pred.defaultEnabled} with no overrides`, () => {
|
|
117
|
+
const config = makeConfig();
|
|
118
|
+
expect(isAssistantFeatureFlagEnabled(pred.key, config)).toBe(
|
|
119
|
+
pred.defaultEnabled,
|
|
120
|
+
);
|
|
101
121
|
});
|
|
102
122
|
}
|
|
103
123
|
});
|
|
@@ -106,18 +126,24 @@ describe("CES flags default safely (all disabled)", () => {
|
|
|
106
126
|
// Independent enablement: each flag can be enabled without affecting others
|
|
107
127
|
// ---------------------------------------------------------------------------
|
|
108
128
|
|
|
109
|
-
describe("CES flags can be
|
|
129
|
+
describe("CES flags can be toggled independently", () => {
|
|
110
130
|
for (const { name, fn, key } of ALL_CES_PREDICATES) {
|
|
111
131
|
test(`enabling ${key} makes ${name} return true`, () => {
|
|
112
|
-
|
|
132
|
+
_setOverridesForTesting({ [key]: true });
|
|
133
|
+
const config = makeConfig();
|
|
113
134
|
expect(fn(config)).toBe(true);
|
|
114
135
|
});
|
|
115
136
|
|
|
116
|
-
test(`enabling ${key} does not
|
|
117
|
-
|
|
118
|
-
|
|
137
|
+
test(`enabling ${key} does not change other CES flags from their defaults`, () => {
|
|
138
|
+
_setOverridesForTesting({ [key]: true });
|
|
139
|
+
const config = makeConfig();
|
|
140
|
+
for (const {
|
|
141
|
+
fn: otherFn,
|
|
142
|
+
key: otherKey,
|
|
143
|
+
defaultEnabled,
|
|
144
|
+
} of ALL_CES_PREDICATES) {
|
|
119
145
|
if (otherKey === key) continue;
|
|
120
|
-
expect(otherFn(config)).toBe(
|
|
146
|
+
expect(otherFn(config)).toBe(defaultEnabled);
|
|
121
147
|
}
|
|
122
148
|
});
|
|
123
149
|
}
|
|
@@ -130,7 +156,8 @@ describe("CES flags can be enabled independently", () => {
|
|
|
130
156
|
describe("CES flags respect explicit false overrides", () => {
|
|
131
157
|
for (const { name, fn, key } of ALL_CES_PREDICATES) {
|
|
132
158
|
test(`${name} returns false when explicitly set to false`, () => {
|
|
133
|
-
|
|
159
|
+
_setOverridesForTesting({ [key]: false });
|
|
160
|
+
const config = makeConfig();
|
|
134
161
|
expect(fn(config)).toBe(false);
|
|
135
162
|
});
|
|
136
163
|
}
|
|
@@ -146,7 +173,8 @@ describe("CES flags do not affect unrelated flags", () => {
|
|
|
146
173
|
for (const key of ALL_CES_FLAG_KEYS) {
|
|
147
174
|
overrides[key] = true;
|
|
148
175
|
}
|
|
149
|
-
|
|
176
|
+
_setOverridesForTesting(overrides);
|
|
177
|
+
const config = makeConfig();
|
|
150
178
|
|
|
151
179
|
// browser defaults to true in the registry and should stay true
|
|
152
180
|
expect(
|
|
@@ -159,7 +187,8 @@ describe("CES flags do not affect unrelated flags", () => {
|
|
|
159
187
|
for (const key of ALL_CES_FLAG_KEYS) {
|
|
160
188
|
overrides[key] = true;
|
|
161
189
|
}
|
|
162
|
-
|
|
190
|
+
_setOverridesForTesting(overrides);
|
|
191
|
+
const config = makeConfig();
|
|
163
192
|
|
|
164
193
|
// contacts defaults to true in the registry and should stay true
|
|
165
194
|
expect(
|
|
@@ -26,7 +26,17 @@
|
|
|
26
26
|
* contracts — no real CES process or socket dependencies are needed.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
import { describe, expect, test } from "bun:test";
|
|
29
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
30
|
+
|
|
31
|
+
import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
|
|
32
|
+
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
_setOverridesForTesting({});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
_setOverridesForTesting({});
|
|
39
|
+
});
|
|
30
40
|
|
|
31
41
|
import {
|
|
32
42
|
CES_PROTOCOL_VERSION,
|
|
@@ -58,11 +68,9 @@ import {
|
|
|
58
68
|
// Helpers
|
|
59
69
|
// ---------------------------------------------------------------------------
|
|
60
70
|
|
|
61
|
-
/** Create a minimal AssistantConfig
|
|
62
|
-
function makeConfig(
|
|
63
|
-
return {
|
|
64
|
-
...(flagOverrides ? { assistantFeatureFlagValues: flagOverrides } : {}),
|
|
65
|
-
} as AssistantConfig;
|
|
71
|
+
/** Create a minimal AssistantConfig (flag overrides are now set via _setOverridesForTesting). */
|
|
72
|
+
function makeConfig(): AssistantConfig {
|
|
73
|
+
return {} as AssistantConfig;
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
// ---------------------------------------------------------------------------
|
|
@@ -438,38 +446,42 @@ describe("managed OAuth materialization through CES sidecar", () => {
|
|
|
438
446
|
// ---------------------------------------------------------------------------
|
|
439
447
|
|
|
440
448
|
describe("feature-flag rollback safety", () => {
|
|
441
|
-
test("managed sidecar flag defaults to
|
|
449
|
+
test("managed sidecar flag defaults to true (enabled by default)", () => {
|
|
442
450
|
const config = makeConfig();
|
|
443
|
-
expect(isCesManagedSidecarEnabled(config)).toBe(
|
|
451
|
+
expect(isCesManagedSidecarEnabled(config)).toBe(true);
|
|
444
452
|
});
|
|
445
453
|
|
|
446
454
|
test("managed sidecar flag can be explicitly enabled", () => {
|
|
447
|
-
|
|
455
|
+
_setOverridesForTesting({
|
|
448
456
|
"feature_flags.ces-managed-sidecar.enabled": true,
|
|
449
457
|
});
|
|
458
|
+
const config = makeConfig();
|
|
450
459
|
expect(isCesManagedSidecarEnabled(config)).toBe(true);
|
|
451
460
|
});
|
|
452
461
|
|
|
453
462
|
test("managed sidecar flag can be explicitly disabled", () => {
|
|
454
|
-
|
|
463
|
+
_setOverridesForTesting({
|
|
455
464
|
"feature_flags.ces-managed-sidecar.enabled": false,
|
|
456
465
|
});
|
|
466
|
+
const config = makeConfig();
|
|
457
467
|
expect(isCesManagedSidecarEnabled(config)).toBe(false);
|
|
458
468
|
});
|
|
459
469
|
|
|
460
470
|
test("enabling managed sidecar does not enable CES tools", () => {
|
|
461
|
-
|
|
471
|
+
_setOverridesForTesting({
|
|
462
472
|
"feature_flags.ces-managed-sidecar.enabled": true,
|
|
463
473
|
});
|
|
474
|
+
const config = makeConfig();
|
|
464
475
|
// CES tools flag should remain independently controlled
|
|
465
476
|
expect(isCesToolsEnabled(config)).toBe(false);
|
|
466
477
|
});
|
|
467
478
|
|
|
468
479
|
test("disabling managed sidecar does not affect other CES flags", () => {
|
|
469
|
-
|
|
480
|
+
_setOverridesForTesting({
|
|
470
481
|
"feature_flags.ces-managed-sidecar.enabled": false,
|
|
471
482
|
"feature_flags.ces-tools.enabled": true,
|
|
472
483
|
});
|
|
484
|
+
const config = makeConfig();
|
|
473
485
|
expect(isCesToolsEnabled(config)).toBe(true);
|
|
474
486
|
});
|
|
475
487
|
});
|
|
@@ -480,10 +492,11 @@ describe("feature-flag rollback safety", () => {
|
|
|
480
492
|
|
|
481
493
|
describe("process manager config wiring", () => {
|
|
482
494
|
test("CesProcessManagerConfig accepts assistantConfig for flag gating", () => {
|
|
495
|
+
_setOverridesForTesting({
|
|
496
|
+
"feature_flags.ces-managed-sidecar.enabled": true,
|
|
497
|
+
});
|
|
483
498
|
const config: CesProcessManagerConfig = {
|
|
484
|
-
assistantConfig: makeConfig(
|
|
485
|
-
"feature_flags.ces-managed-sidecar.enabled": true,
|
|
486
|
-
}),
|
|
499
|
+
assistantConfig: makeConfig(),
|
|
487
500
|
};
|
|
488
501
|
expect(config.assistantConfig).toBeDefined();
|
|
489
502
|
expect(isCesManagedSidecarEnabled(config.assistantConfig!)).toBe(true);
|
|
@@ -491,16 +504,17 @@ describe("process manager config wiring", () => {
|
|
|
491
504
|
|
|
492
505
|
test("CesProcessManagerConfig requires assistantConfig for feature-flag gate", () => {
|
|
493
506
|
const config: CesProcessManagerConfig = {
|
|
494
|
-
assistantConfig: makeConfig(
|
|
507
|
+
assistantConfig: makeConfig(),
|
|
495
508
|
};
|
|
496
509
|
expect(config.assistantConfig).toBeDefined();
|
|
497
510
|
});
|
|
498
511
|
|
|
499
512
|
test("when flag is off, managed discovery is skipped", () => {
|
|
513
|
+
_setOverridesForTesting({
|
|
514
|
+
"feature_flags.ces-managed-sidecar.enabled": false,
|
|
515
|
+
});
|
|
500
516
|
const config: CesProcessManagerConfig = {
|
|
501
|
-
assistantConfig: makeConfig(
|
|
502
|
-
"feature_flags.ces-managed-sidecar.enabled": false,
|
|
503
|
-
}),
|
|
517
|
+
assistantConfig: makeConfig(),
|
|
504
518
|
};
|
|
505
519
|
// The managed path should be gated
|
|
506
520
|
expect(isCesManagedSidecarEnabled(config.assistantConfig!)).toBe(false);
|
|
@@ -513,9 +527,10 @@ describe("process manager config wiring", () => {
|
|
|
513
527
|
|
|
514
528
|
describe("non-CES internal consumers intact when flag is off", () => {
|
|
515
529
|
test("existing non-agent flows are unaffected by managed sidecar flag", () => {
|
|
516
|
-
|
|
530
|
+
_setOverridesForTesting({
|
|
517
531
|
"feature_flags.ces-managed-sidecar.enabled": false,
|
|
518
532
|
});
|
|
533
|
+
const config = makeConfig();
|
|
519
534
|
expect(isCesManagedSidecarEnabled(config)).toBe(false);
|
|
520
535
|
});
|
|
521
536
|
|
|
@@ -10,7 +10,6 @@ const mockConfig = {
|
|
|
10
10
|
action: "block" as "redact" | "warn" | "block",
|
|
11
11
|
entropyThreshold: 4.0,
|
|
12
12
|
allowOneTimeSend: false,
|
|
13
|
-
blockIngress: true,
|
|
14
13
|
},
|
|
15
14
|
timeouts: { permissionTimeoutSec: 300 },
|
|
16
15
|
};
|
|
@@ -67,7 +66,7 @@ mock.module("../security/secure-keys.js", () => {
|
|
|
67
66
|
setSecureKeyAsync: async (key: string, value: string) =>
|
|
68
67
|
syncSet(key, value),
|
|
69
68
|
deleteSecureKeyAsync: async (key: string) => syncDelete(key),
|
|
70
|
-
listSecureKeysAsync: async () => [...storedKeys.keys()],
|
|
69
|
+
listSecureKeysAsync: async () => ({ accounts: [...storedKeys.keys()], unreachable: false }),
|
|
71
70
|
};
|
|
72
71
|
});
|
|
73
72
|
|
|
@@ -118,8 +117,6 @@ mock.module("../tools/credentials/policy-validate.js", () => ({
|
|
|
118
117
|
|
|
119
118
|
// Import modules under test
|
|
120
119
|
const { credentialStoreTool } = await import("../tools/credentials/vault.js");
|
|
121
|
-
const { checkIngressForSecrets } =
|
|
122
|
-
await import("../security/secret-ingress.js");
|
|
123
120
|
const { isToolAllowed } = await import("../tools/credentials/tool-policy.js");
|
|
124
121
|
const { isDomainAllowed } =
|
|
125
122
|
await import("../tools/credentials/domain-policy.js");
|
|
@@ -203,61 +200,6 @@ describe("E2E: secure store and list lifecycle", () => {
|
|
|
203
200
|
});
|
|
204
201
|
});
|
|
205
202
|
|
|
206
|
-
// ---------------------------------------------------------------------------
|
|
207
|
-
// E2E Scenario 2 — Secret-in-chat blocked and redirected
|
|
208
|
-
// ---------------------------------------------------------------------------
|
|
209
|
-
|
|
210
|
-
describe("E2E: secret ingress blocking", () => {
|
|
211
|
-
beforeEach(() => {
|
|
212
|
-
mockConfig.secretDetection.enabled = true;
|
|
213
|
-
mockConfig.secretDetection.action = "block";
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
test("blocks message containing AWS access key", () => {
|
|
217
|
-
const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
|
|
218
|
-
const check = checkIngressForSecrets(`Here is my key: ${awsKey}`);
|
|
219
|
-
expect(check.blocked).toBe(true);
|
|
220
|
-
expect(check.detectedTypes.length).toBeGreaterThan(0);
|
|
221
|
-
// Notice must never contain the actual secret
|
|
222
|
-
expect(check.userNotice).toBeDefined();
|
|
223
|
-
expect(check.userNotice).not.toContain(awsKey);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
test("blocks message containing GitHub token", () => {
|
|
227
|
-
const ghToken = ["ghp_", "ABCDEFghijklMN01234567", "89abcdef"].join("");
|
|
228
|
-
const check = checkIngressForSecrets(`Use this token: ${ghToken}`);
|
|
229
|
-
expect(check.blocked).toBe(true);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test("allows normal text through", () => {
|
|
233
|
-
const check = checkIngressForSecrets("Please help me configure my project");
|
|
234
|
-
expect(check.blocked).toBe(false);
|
|
235
|
-
expect(check.detectedTypes).toEqual([]);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
test("bypasses when detection is disabled", () => {
|
|
239
|
-
mockConfig.secretDetection.enabled = false;
|
|
240
|
-
const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
|
|
241
|
-
const check = checkIngressForSecrets(awsKey);
|
|
242
|
-
expect(check.blocked).toBe(false);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
test("bypasses when blockIngress is false", () => {
|
|
246
|
-
mockConfig.secretDetection.blockIngress = false;
|
|
247
|
-
const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
|
|
248
|
-
const check = checkIngressForSecrets(awsKey);
|
|
249
|
-
expect(check.blocked).toBe(false);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
test("still blocks when action is warn but blockIngress is true", () => {
|
|
253
|
-
mockConfig.secretDetection.action = "warn";
|
|
254
|
-
mockConfig.secretDetection.blockIngress = true;
|
|
255
|
-
const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
|
|
256
|
-
const check = checkIngressForSecrets(awsKey);
|
|
257
|
-
expect(check.blocked).toBe(true);
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
|
|
261
203
|
// ---------------------------------------------------------------------------
|
|
262
204
|
// E2E Scenario 3 — One-time send override path
|
|
263
205
|
// ---------------------------------------------------------------------------
|
|
@@ -411,12 +353,4 @@ describe("E2E: cross-cutting secret leak prevention", () => {
|
|
|
411
353
|
);
|
|
412
354
|
expect(result.content).not.toContain(secret);
|
|
413
355
|
});
|
|
414
|
-
|
|
415
|
-
test("ingress notice never contains the detected secret", () => {
|
|
416
|
-
const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
|
|
417
|
-
const check = checkIngressForSecrets(awsKey);
|
|
418
|
-
expect(check.blocked).toBe(true);
|
|
419
|
-
expect(check.userNotice).toBeDefined();
|
|
420
|
-
expect(check.userNotice).not.toContain(awsKey);
|
|
421
|
-
});
|
|
422
356
|
});
|