@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
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
|
|
3
|
+
import { getConfig } from "../../../config/loader.js";
|
|
4
|
+
import {
|
|
5
|
+
type Services,
|
|
6
|
+
ServicesSchema,
|
|
7
|
+
} from "../../../config/schemas/services.js";
|
|
8
|
+
import { getProvider } from "../../../oauth/oauth-store.js";
|
|
9
|
+
import { VellumPlatformClient } from "../../../platform/client.js";
|
|
10
|
+
import { openInBrowser } from "../../../util/browser.js";
|
|
11
|
+
import { getCliLogger } from "../../logger.js";
|
|
12
|
+
import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
13
|
+
|
|
14
|
+
const log = getCliLogger("cli");
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Shared types
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
interface PlatformConnectionEntry {
|
|
21
|
+
id: string;
|
|
22
|
+
account_label?: string;
|
|
23
|
+
scopes_granted?: string[];
|
|
24
|
+
status?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Shared helpers
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Normalize a bare provider name (e.g. "google") into the canonical provider
|
|
33
|
+
* key used internally (e.g. "integration:google").
|
|
34
|
+
*/
|
|
35
|
+
function toProviderKey(provider: string): string {
|
|
36
|
+
return provider.startsWith("integration:")
|
|
37
|
+
? provider
|
|
38
|
+
: `integration:${provider}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Extract the bare provider slug (e.g. "google") from either a raw CLI
|
|
43
|
+
* argument or a canonical provider key (e.g. "integration:google").
|
|
44
|
+
* Platform API paths expect the bare slug, not the internal key.
|
|
45
|
+
*/
|
|
46
|
+
function toBareProvider(provider: string): string {
|
|
47
|
+
return provider.startsWith("integration:")
|
|
48
|
+
? provider.slice("integration:".length)
|
|
49
|
+
: provider;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Validate that a provider supports managed OAuth (has a managedServiceConfigKey).
|
|
54
|
+
* Does NOT check whether managed mode is currently enabled — use this for
|
|
55
|
+
* operations that should work regardless of the current mode (e.g. disconnect).
|
|
56
|
+
* Returns the managed config key on success, or writes an error and returns null.
|
|
57
|
+
*/
|
|
58
|
+
function requireManagedCapableProvider(
|
|
59
|
+
provider: string,
|
|
60
|
+
cmd: Command,
|
|
61
|
+
): string | null {
|
|
62
|
+
const providerKey = toProviderKey(provider);
|
|
63
|
+
const providerRow = getProvider(providerKey);
|
|
64
|
+
|
|
65
|
+
const managedKey = providerRow?.managedServiceConfigKey;
|
|
66
|
+
if (!managedKey || !(managedKey in ServicesSchema.shape)) {
|
|
67
|
+
writeOutput(cmd, {
|
|
68
|
+
ok: false,
|
|
69
|
+
error: `Provider "${provider}" does not support platform-managed OAuth`,
|
|
70
|
+
});
|
|
71
|
+
process.exitCode = 1;
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return managedKey;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Validate that a provider supports managed OAuth AND that managed mode is
|
|
80
|
+
* currently enabled. Use this for operations that require active managed
|
|
81
|
+
* mode (e.g. connect). Returns the managed config key on success, or writes
|
|
82
|
+
* an error and returns null.
|
|
83
|
+
*/
|
|
84
|
+
function requireManagedProvider(provider: string, cmd: Command): string | null {
|
|
85
|
+
const managedKey = requireManagedCapableProvider(provider, cmd);
|
|
86
|
+
if (!managedKey) return null;
|
|
87
|
+
|
|
88
|
+
const services: Services = getConfig().services;
|
|
89
|
+
const managedEnabled =
|
|
90
|
+
services[managedKey as keyof Services].mode === "managed";
|
|
91
|
+
|
|
92
|
+
if (!managedEnabled) {
|
|
93
|
+
writeOutput(cmd, {
|
|
94
|
+
ok: false,
|
|
95
|
+
error: `Provider "${provider}" supports managed OAuth but is set to "your-own" mode`,
|
|
96
|
+
});
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return managedKey;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Create an authenticated platform client, or write an error and return null.
|
|
106
|
+
*/
|
|
107
|
+
async function requirePlatformClient(
|
|
108
|
+
cmd: Command,
|
|
109
|
+
): Promise<VellumPlatformClient | null> {
|
|
110
|
+
const client = await VellumPlatformClient.create();
|
|
111
|
+
if (!client || !client.platformAssistantId) {
|
|
112
|
+
writeOutput(cmd, {
|
|
113
|
+
ok: false,
|
|
114
|
+
error:
|
|
115
|
+
"Platform prerequisites not met (not logged in or missing assistant ID)",
|
|
116
|
+
});
|
|
117
|
+
process.exitCode = 1;
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return client;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Fetch active platform connections for a provider. Returns the parsed entries
|
|
125
|
+
* or writes an error and returns null.
|
|
126
|
+
*/
|
|
127
|
+
async function fetchActiveConnections(
|
|
128
|
+
client: VellumPlatformClient,
|
|
129
|
+
provider: string,
|
|
130
|
+
cmd: Command,
|
|
131
|
+
): Promise<PlatformConnectionEntry[] | null> {
|
|
132
|
+
const params = new URLSearchParams();
|
|
133
|
+
params.set("provider", toBareProvider(provider));
|
|
134
|
+
params.set("status", "ACTIVE");
|
|
135
|
+
|
|
136
|
+
const path = `/v1/assistants/${encodeURIComponent(client.platformAssistantId)}/oauth/connections/?${params.toString()}`;
|
|
137
|
+
const response = await client.fetch(path);
|
|
138
|
+
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
writeOutput(cmd, {
|
|
141
|
+
ok: false,
|
|
142
|
+
error: `Platform returned HTTP ${response.status}`,
|
|
143
|
+
});
|
|
144
|
+
process.exitCode = 1;
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const body = (await response.json()) as unknown;
|
|
149
|
+
|
|
150
|
+
// The platform returns either a flat array or a {results: [...]} wrapper.
|
|
151
|
+
return (
|
|
152
|
+
Array.isArray(body)
|
|
153
|
+
? body
|
|
154
|
+
: ((body as Record<string, unknown>).results ?? [])
|
|
155
|
+
) as PlatformConnectionEntry[];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// Command registration
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
|
|
162
|
+
export function registerPlatformCommands(oauth: Command): void {
|
|
163
|
+
const platform = oauth
|
|
164
|
+
.command("platform")
|
|
165
|
+
.description(
|
|
166
|
+
"Manage platform-managed OAuth provider status and connections",
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
registerStatusCommand(platform);
|
|
170
|
+
registerConnectCommand(platform);
|
|
171
|
+
registerDisconnectCommand(platform);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
// platform status <provider>
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
|
|
178
|
+
function registerStatusCommand(platform: Command): void {
|
|
179
|
+
platform
|
|
180
|
+
.command("status <provider>")
|
|
181
|
+
.description(
|
|
182
|
+
"Check whether a provider supports managed OAuth and list the user's active connections",
|
|
183
|
+
)
|
|
184
|
+
.addHelpText(
|
|
185
|
+
"after",
|
|
186
|
+
`
|
|
187
|
+
Arguments:
|
|
188
|
+
provider Provider name (e.g. google, slack, twitter)
|
|
189
|
+
|
|
190
|
+
Checks whether the platform offers managed OAuth for the given provider,
|
|
191
|
+
whether managed mode is currently enabled, and lists any active connections
|
|
192
|
+
the user has set up on the platform.
|
|
193
|
+
|
|
194
|
+
Examples:
|
|
195
|
+
$ assistant oauth platform status google
|
|
196
|
+
$ assistant oauth platform status slack --json`,
|
|
197
|
+
)
|
|
198
|
+
.action(
|
|
199
|
+
async (
|
|
200
|
+
provider: string,
|
|
201
|
+
_opts: Record<string, unknown>,
|
|
202
|
+
cmd: Command,
|
|
203
|
+
) => {
|
|
204
|
+
try {
|
|
205
|
+
const providerKey = toProviderKey(provider);
|
|
206
|
+
const providerRow = getProvider(providerKey);
|
|
207
|
+
|
|
208
|
+
// 1. Check if the provider even supports managed mode
|
|
209
|
+
const managedKey = providerRow?.managedServiceConfigKey;
|
|
210
|
+
if (!managedKey || !(managedKey in ServicesSchema.shape)) {
|
|
211
|
+
writeOutput(cmd, {
|
|
212
|
+
ok: true,
|
|
213
|
+
provider,
|
|
214
|
+
managedAvailable: false,
|
|
215
|
+
managedEnabled: false,
|
|
216
|
+
connections: [],
|
|
217
|
+
});
|
|
218
|
+
if (!shouldOutputJson(cmd)) {
|
|
219
|
+
log.info(
|
|
220
|
+
`Provider "${provider}" does not support platform-managed OAuth`,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// 2. Check if managed mode is enabled in the services config
|
|
227
|
+
const services: Services = getConfig().services;
|
|
228
|
+
const managedEnabled =
|
|
229
|
+
services[managedKey as keyof Services].mode === "managed";
|
|
230
|
+
|
|
231
|
+
if (!managedEnabled) {
|
|
232
|
+
writeOutput(cmd, {
|
|
233
|
+
ok: true,
|
|
234
|
+
provider,
|
|
235
|
+
managedAvailable: true,
|
|
236
|
+
managedEnabled: false,
|
|
237
|
+
connections: [],
|
|
238
|
+
});
|
|
239
|
+
if (!shouldOutputJson(cmd)) {
|
|
240
|
+
log.info(
|
|
241
|
+
`Provider "${provider}" supports managed OAuth but is set to "your-own" mode`,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// 3. Fetch active connections from the platform
|
|
248
|
+
const client = await requirePlatformClient(cmd);
|
|
249
|
+
if (!client) return;
|
|
250
|
+
|
|
251
|
+
const rawEntries = await fetchActiveConnections(
|
|
252
|
+
client,
|
|
253
|
+
provider,
|
|
254
|
+
cmd,
|
|
255
|
+
);
|
|
256
|
+
if (!rawEntries) return;
|
|
257
|
+
|
|
258
|
+
const connections = rawEntries.map((c) => ({
|
|
259
|
+
id: c.id,
|
|
260
|
+
accountLabel: c.account_label ?? null,
|
|
261
|
+
scopesGranted: c.scopes_granted ?? [],
|
|
262
|
+
status: c.status ?? "ACTIVE",
|
|
263
|
+
}));
|
|
264
|
+
|
|
265
|
+
writeOutput(cmd, {
|
|
266
|
+
ok: true,
|
|
267
|
+
provider,
|
|
268
|
+
managedAvailable: true,
|
|
269
|
+
managedEnabled: true,
|
|
270
|
+
connections,
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
if (!shouldOutputJson(cmd)) {
|
|
274
|
+
if (connections.length === 0) {
|
|
275
|
+
log.info(
|
|
276
|
+
`Provider "${provider}" is managed but has no active connections`,
|
|
277
|
+
);
|
|
278
|
+
} else {
|
|
279
|
+
log.info(
|
|
280
|
+
`Provider "${provider}": ${connections.length} active connection(s)`,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
} catch (err) {
|
|
285
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
286
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
287
|
+
process.exitCode = 1;
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ---------------------------------------------------------------------------
|
|
294
|
+
// platform connect <provider>
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
|
|
297
|
+
function registerConnectCommand(platform: Command): void {
|
|
298
|
+
platform
|
|
299
|
+
.command("connect <provider>")
|
|
300
|
+
.description(
|
|
301
|
+
"Initiate a platform-managed OAuth flow for a provider and open the browser",
|
|
302
|
+
)
|
|
303
|
+
.option(
|
|
304
|
+
"--scopes <scopes...>",
|
|
305
|
+
"Exact OAuth scopes to request (must be a subset of the provider's allowed scopes)",
|
|
306
|
+
)
|
|
307
|
+
.addHelpText(
|
|
308
|
+
"after",
|
|
309
|
+
`
|
|
310
|
+
Arguments:
|
|
311
|
+
provider Provider name (e.g. google, slack, twitter)
|
|
312
|
+
|
|
313
|
+
Starts a platform-managed OAuth authorization flow by calling the platform's
|
|
314
|
+
/start/ endpoint, then opens the returned authorization URL in the user's
|
|
315
|
+
browser. The user completes consent in the browser; the platform handles the
|
|
316
|
+
callback, token exchange, and credential storage.
|
|
317
|
+
|
|
318
|
+
The provider must support managed OAuth and managed mode must be enabled in
|
|
319
|
+
the services config.
|
|
320
|
+
|
|
321
|
+
Scope behavior:
|
|
322
|
+
Without --scopes, the platform requests ALL of the provider's allowed scopes.
|
|
323
|
+
With --scopes, only the specified scopes are requested (no merging with
|
|
324
|
+
defaults). Each scope must be in the provider's allowed set or the platform
|
|
325
|
+
will reject it. Use full scope URLs where required (e.g. Google scopes use
|
|
326
|
+
https://www.googleapis.com/auth/... format).
|
|
327
|
+
|
|
328
|
+
Examples:
|
|
329
|
+
$ assistant oauth platform connect google
|
|
330
|
+
$ assistant oauth platform connect google --scopes https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events
|
|
331
|
+
$ assistant oauth platform connect google --json`,
|
|
332
|
+
)
|
|
333
|
+
.action(
|
|
334
|
+
async (provider: string, opts: { scopes?: string[] }, cmd: Command) => {
|
|
335
|
+
try {
|
|
336
|
+
if (!requireManagedProvider(provider, cmd)) return;
|
|
337
|
+
|
|
338
|
+
const client = await requirePlatformClient(cmd);
|
|
339
|
+
if (!client) return;
|
|
340
|
+
|
|
341
|
+
// Call the platform's OAuth start endpoint
|
|
342
|
+
const startPath = `/v1/assistants/${encodeURIComponent(client.platformAssistantId)}/oauth/${encodeURIComponent(toBareProvider(provider))}/start/`;
|
|
343
|
+
|
|
344
|
+
const body: Record<string, unknown> = {};
|
|
345
|
+
if (opts.scopes && opts.scopes.length > 0) {
|
|
346
|
+
body.requested_scopes = opts.scopes;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const response = await client.fetch(startPath, {
|
|
350
|
+
method: "POST",
|
|
351
|
+
headers: { "Content-Type": "application/json" },
|
|
352
|
+
body: JSON.stringify(body),
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
if (!response.ok) {
|
|
356
|
+
const errorText = await response.text().catch(() => "");
|
|
357
|
+
writeOutput(cmd, {
|
|
358
|
+
ok: false,
|
|
359
|
+
error: `Platform returned HTTP ${response.status}${errorText ? `: ${errorText}` : ""}`,
|
|
360
|
+
});
|
|
361
|
+
process.exitCode = 1;
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const result = (await response.json()) as {
|
|
366
|
+
connect_url?: string;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
if (!result.connect_url) {
|
|
370
|
+
writeOutput(cmd, {
|
|
371
|
+
ok: false,
|
|
372
|
+
error:
|
|
373
|
+
"Platform did not return a connect URL — the OAuth flow could not be started",
|
|
374
|
+
});
|
|
375
|
+
process.exitCode = 1;
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
openInBrowser(result.connect_url);
|
|
380
|
+
|
|
381
|
+
writeOutput(cmd, {
|
|
382
|
+
ok: true,
|
|
383
|
+
deferred: true,
|
|
384
|
+
provider,
|
|
385
|
+
connectUrl: result.connect_url,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
if (!shouldOutputJson(cmd)) {
|
|
389
|
+
log.info(
|
|
390
|
+
`Opening browser to connect ${provider}. Complete the authorization in your browser.`,
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
} catch (err) {
|
|
394
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
395
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
396
|
+
process.exitCode = 1;
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// ---------------------------------------------------------------------------
|
|
403
|
+
// platform disconnect <provider>
|
|
404
|
+
// ---------------------------------------------------------------------------
|
|
405
|
+
|
|
406
|
+
function registerDisconnectCommand(platform: Command): void {
|
|
407
|
+
platform
|
|
408
|
+
.command("disconnect <provider>")
|
|
409
|
+
.description(
|
|
410
|
+
"Disconnect a platform-managed OAuth connection for a provider",
|
|
411
|
+
)
|
|
412
|
+
.option(
|
|
413
|
+
"--connection-id <id>",
|
|
414
|
+
"Specific connection ID to disconnect (required when multiple active connections exist)",
|
|
415
|
+
)
|
|
416
|
+
.addHelpText(
|
|
417
|
+
"after",
|
|
418
|
+
`
|
|
419
|
+
Arguments:
|
|
420
|
+
provider Provider name (e.g. google, slack, twitter)
|
|
421
|
+
|
|
422
|
+
Disconnects a platform-managed OAuth connection by calling the platform's
|
|
423
|
+
/disconnect/ endpoint, which revokes the connection.
|
|
424
|
+
|
|
425
|
+
If the provider has multiple active connections, use --connection-id to specify
|
|
426
|
+
which one to disconnect. Without --connection-id, the command disconnects the
|
|
427
|
+
sole active connection or fails with a list of active connections if there are
|
|
428
|
+
multiple.
|
|
429
|
+
|
|
430
|
+
Examples:
|
|
431
|
+
$ assistant oauth platform disconnect google
|
|
432
|
+
$ assistant oauth platform disconnect google --connection-id conn_abc123
|
|
433
|
+
$ assistant oauth platform disconnect google --json`,
|
|
434
|
+
)
|
|
435
|
+
.action(
|
|
436
|
+
async (
|
|
437
|
+
provider: string,
|
|
438
|
+
opts: { connectionId?: string },
|
|
439
|
+
cmd: Command,
|
|
440
|
+
) => {
|
|
441
|
+
try {
|
|
442
|
+
if (!requireManagedCapableProvider(provider, cmd)) return;
|
|
443
|
+
|
|
444
|
+
const client = await requirePlatformClient(cmd);
|
|
445
|
+
if (!client) return;
|
|
446
|
+
|
|
447
|
+
// Always fetch active connections for the provider so we can
|
|
448
|
+
// verify --connection-id belongs to it (prevents cross-provider
|
|
449
|
+
// disconnects from typos or stale IDs).
|
|
450
|
+
const entries = await fetchActiveConnections(client, provider, cmd);
|
|
451
|
+
if (!entries) return;
|
|
452
|
+
|
|
453
|
+
let connectionId = opts.connectionId;
|
|
454
|
+
|
|
455
|
+
if (connectionId) {
|
|
456
|
+
// Verify the supplied ID belongs to this provider
|
|
457
|
+
if (!entries.some((c) => c.id === connectionId)) {
|
|
458
|
+
writeOutput(cmd, {
|
|
459
|
+
ok: false,
|
|
460
|
+
error: `Connection "${connectionId}" is not an active ${provider} connection`,
|
|
461
|
+
});
|
|
462
|
+
process.exitCode = 1;
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
if (entries.length === 0) {
|
|
467
|
+
writeOutput(cmd, {
|
|
468
|
+
ok: false,
|
|
469
|
+
error: `No active connections found for provider "${provider}"`,
|
|
470
|
+
});
|
|
471
|
+
process.exitCode = 1;
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (entries.length > 1) {
|
|
476
|
+
const connectionList = entries.map((c) => ({
|
|
477
|
+
id: c.id,
|
|
478
|
+
accountLabel: c.account_label ?? null,
|
|
479
|
+
}));
|
|
480
|
+
writeOutput(cmd, {
|
|
481
|
+
ok: false,
|
|
482
|
+
error: `Multiple active connections for "${provider}". Use --connection-id to specify which one to disconnect.`,
|
|
483
|
+
connections: connectionList,
|
|
484
|
+
});
|
|
485
|
+
process.exitCode = 1;
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
connectionId = entries[0].id;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Disconnect the connection
|
|
493
|
+
const disconnectPath = `/v1/assistants/${encodeURIComponent(client.platformAssistantId)}/oauth/connections/${encodeURIComponent(connectionId)}/disconnect/`;
|
|
494
|
+
const disconnectResponse = await client.fetch(disconnectPath, {
|
|
495
|
+
method: "POST",
|
|
496
|
+
headers: { "Content-Type": "application/json" },
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
if (!disconnectResponse.ok) {
|
|
500
|
+
const errorText = await disconnectResponse.text().catch(() => "");
|
|
501
|
+
writeOutput(cmd, {
|
|
502
|
+
ok: false,
|
|
503
|
+
error: `Platform returned HTTP ${disconnectResponse.status}${errorText ? `: ${errorText}` : ""}`,
|
|
504
|
+
});
|
|
505
|
+
process.exitCode = 1;
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
writeOutput(cmd, {
|
|
510
|
+
ok: true,
|
|
511
|
+
provider,
|
|
512
|
+
connectionId,
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
if (!shouldOutputJson(cmd)) {
|
|
516
|
+
log.info(`Disconnected ${provider} connection ${connectionId}`);
|
|
517
|
+
}
|
|
518
|
+
} catch (err) {
|
|
519
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
520
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
521
|
+
process.exitCode = 1;
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
);
|
|
525
|
+
}
|
|
@@ -24,7 +24,7 @@ export function registerPlatformCommand(program: Command): void {
|
|
|
24
24
|
`
|
|
25
25
|
The platform subsystem manages callback routing, containerized deployment
|
|
26
26
|
context, and webhook forwarding for assistants running inside platform
|
|
27
|
-
containers. When IS_CONTAINERIZED=true with a configured
|
|
27
|
+
containers. When IS_CONTAINERIZED=true with a configured VELLUM_PLATFORM_URL
|
|
28
28
|
and PLATFORM_ASSISTANT_ID, external service callbacks (Telegram webhooks,
|
|
29
29
|
Twilio webhooks, OAuth redirects) route through the platform's gateway proxy
|
|
30
30
|
instead of hitting the assistant directly.
|
|
@@ -51,7 +51,7 @@ running.
|
|
|
51
51
|
|
|
52
52
|
Fields:
|
|
53
53
|
containerized Whether IS_CONTAINERIZED is set (boolean)
|
|
54
|
-
baseUrl
|
|
54
|
+
baseUrl VELLUM_PLATFORM_URL — the platform gateway base URL
|
|
55
55
|
assistantId PLATFORM_ASSISTANT_ID — this assistant's platform UUID
|
|
56
56
|
hasInternalApiKey Whether PLATFORM_INTERNAL_API_KEY is set (boolean,
|
|
57
57
|
value not disclosed)
|
|
@@ -136,7 +136,7 @@ Known callback path/type combinations:
|
|
|
136
136
|
--path oauth/callback --type oauth
|
|
137
137
|
|
|
138
138
|
Requires a containerized environment (IS_CONTAINERIZED=true) with
|
|
139
|
-
|
|
139
|
+
VELLUM_PLATFORM_URL and PLATFORM_ASSISTANT_ID configured. Returns the
|
|
140
140
|
platform-provided stable callback URL that external services should use.
|
|
141
141
|
|
|
142
142
|
Examples:
|