@vellumai/assistant 0.4.46 → 0.4.49
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/ARCHITECTURE.md +7 -7
- package/README.md +2 -23
- package/docs/architecture/integrations.md +45 -41
- package/docs/architecture/keychain-broker.md +3 -3
- package/docs/architecture/security.md +5 -5
- package/docs/runbook-trusted-contacts.md +3 -8
- package/hook-templates/debug-prompt-logger/hook.json +1 -1
- package/hook-templates/debug-prompt-logger/run.sh +1 -3
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +0 -1
- package/src/__tests__/anthropic-provider.test.ts +156 -0
- package/src/__tests__/approval-cascade.test.ts +810 -0
- package/src/__tests__/approval-primitive.test.ts +0 -1
- package/src/__tests__/approval-routes-http.test.ts +2 -0
- package/src/__tests__/assistant-attachments.test.ts +12 -34
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
- package/src/__tests__/browser-fill-credential.test.ts +5 -2
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -1
- package/src/__tests__/channel-guardian.test.ts +0 -2
- package/src/__tests__/channel-readiness-routes.test.ts +35 -25
- package/src/__tests__/channel-readiness-service.test.ts +10 -9
- package/src/__tests__/checker.test.ts +9 -29
- package/src/__tests__/cli.test.ts +23 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-tools.test.ts +2 -19
- package/src/__tests__/config-watcher.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-image-dimensions.test.ts +332 -0
- package/src/__tests__/context-token-estimator.test.ts +196 -13
- package/src/__tests__/conversation-attention-store.test.ts +0 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +144 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +23 -22
- package/src/__tests__/credential-broker-server-use.test.ts +22 -21
- package/src/__tests__/credential-broker.test.ts +2 -1
- package/src/__tests__/credential-metadata-store.test.ts +239 -26
- package/src/__tests__/credential-resolve.test.ts +5 -4
- package/src/__tests__/credential-security-e2e.test.ts +8 -8
- package/src/__tests__/credential-security-invariants.test.ts +111 -7
- package/src/__tests__/credential-vault-unit.test.ts +287 -54
- package/src/__tests__/credential-vault.test.ts +406 -12
- package/src/__tests__/credentials-cli.test.ts +82 -6
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/ephemeral-permissions.test.ts +3 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +4 -2
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/gemini-image-service.test.ts +75 -45
- package/src/__tests__/gemini-provider.test.ts +9 -6
- package/src/__tests__/guardian-action-conversation-turn.test.ts +1 -33
- package/src/__tests__/guardian-action-copy-generator.test.ts +0 -20
- package/src/__tests__/guardian-action-followup-executor.test.ts +1 -28
- package/src/__tests__/guardian-action-followup-store.test.ts +1 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
- package/src/__tests__/guardian-grant-minting.test.ts +35 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
- package/src/__tests__/heartbeat-service.test.ts +0 -1
- package/src/__tests__/host-cu-proxy.test.ts +629 -0
- package/src/__tests__/host-shell-tool.test.ts +27 -15
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/ingress-url-consistency.test.ts +14 -21
- package/src/__tests__/integration-status.test.ts +38 -25
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/invite-routes-http.test.ts +10 -9
- package/src/__tests__/keychain-broker-client.test.ts +11 -43
- package/src/__tests__/managed-proxy-context.test.ts +5 -3
- package/src/__tests__/media-generate-image.test.ts +63 -2
- package/src/__tests__/media-reuse-story.e2e.test.ts +7 -3
- package/src/__tests__/messaging-send-tool.test.ts +4 -6
- package/src/__tests__/notification-routing-intent.test.ts +0 -1
- package/src/__tests__/oauth-cli.test.ts +373 -14
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
- package/src/__tests__/oauth-scope-policy.test.ts +4 -6
- package/src/__tests__/oauth-store.test.ts +756 -0
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
- package/src/__tests__/provider-error-scenarios.test.ts +0 -1
- package/src/__tests__/provider-fail-open-selection.test.ts +3 -1
- package/src/__tests__/provider-managed-proxy-integration.test.ts +70 -6
- package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
- package/src/__tests__/public-ingress-urls.test.ts +15 -21
- package/src/__tests__/recording-handler.test.ts +3 -4
- package/src/__tests__/registry.test.ts +2 -2
- package/src/__tests__/runtime-events-sse.test.ts +55 -7
- package/src/__tests__/schedule-store.test.ts +0 -1
- package/src/__tests__/scheduler-recurrence.test.ts +0 -1
- package/src/__tests__/schema-transforms.test.ts +226 -0
- package/src/__tests__/scoped-approval-grants.test.ts +0 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
- package/src/__tests__/script-proxy-injection-runtime.test.ts +23 -13
- package/src/__tests__/script-proxy-policy-runtime.test.ts +1 -1
- package/src/__tests__/script-proxy-session-manager.test.ts +1 -1
- package/src/__tests__/secret-ingress-handler.test.ts +0 -1
- package/src/__tests__/secret-onetime-send.test.ts +5 -3
- package/src/__tests__/send-endpoint-busy.test.ts +21 -6
- package/src/__tests__/sequence-store.test.ts +0 -1
- package/src/__tests__/session-init.benchmark.test.ts +4 -5
- package/src/__tests__/session-messaging-secret-redirect.test.ts +5 -4
- package/src/__tests__/skill-include-graph.test.ts +66 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
- package/src/__tests__/skill-load-tool.test.ts +149 -1
- package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
- package/src/__tests__/skills-uninstall.test.ts +3 -3
- package/src/__tests__/skills.test.ts +3 -12
- package/src/__tests__/slack-channel-config.test.ts +76 -11
- package/src/__tests__/slack-share-routes.test.ts +17 -14
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-bot-username-resolution.test.ts +3 -0
- package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
- package/src/__tests__/terminal-tools.test.ts +4 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
- package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
- package/src/__tests__/trust-store.test.ts +1 -22
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/twilio-config.test.ts +2 -1
- package/src/__tests__/twilio-provider.test.ts +4 -2
- package/src/__tests__/twilio-routes.test.ts +5 -20
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/agent/ax-tree-compaction.test.ts +235 -0
- package/src/agent/loop.ts +76 -130
- package/src/calls/call-domain.ts +8 -10
- package/src/calls/relay-server.ts +9 -13
- package/src/calls/twilio-config.ts +4 -8
- package/src/calls/twilio-provider.ts +2 -1
- package/src/calls/twilio-rest.ts +2 -1
- package/src/calls/twilio-routes.ts +1 -2
- package/src/calls/voice-ingress-preflight.ts +1 -1
- package/src/cli/commands/browser-relay.ts +46 -15
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/credentials.ts +110 -23
- package/src/cli/commands/oauth/apps.ts +255 -0
- package/src/cli/commands/oauth/connections.ts +299 -0
- package/src/cli/commands/oauth/index.ts +52 -0
- package/src/cli/commands/oauth/providers.ts +242 -0
- package/src/cli/commands/skills.ts +4 -338
- package/src/cli/program.ts +1 -5
- package/src/cli/reference.ts +1 -3
- package/src/cli.ts +3 -2
- package/src/config/assistant-feature-flags.ts +0 -3
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/claude-code/TOOLS.json +0 -4
- package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
- package/src/config/bundled-skills/computer-use/TOOLS.json +22 -4
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +29 -32
- package/src/config/bundled-skills/gmail/SKILL.md +4 -4
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +54 -61
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +25 -28
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +14 -17
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +39 -44
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +61 -58
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +50 -49
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +11 -13
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +148 -146
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +4 -7
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +175 -173
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +4 -7
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +71 -76
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +32 -38
- package/src/config/bundled-skills/google-calendar/SKILL.md +2 -2
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +90 -44
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +9 -10
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +5 -6
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +4 -5
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +14 -15
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +37 -37
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +4 -9
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +24 -3
- package/src/config/bundled-skills/messaging/SKILL.md +6 -6
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +62 -63
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +15 -16
- package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +6 -7
- package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +14 -15
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +128 -128
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +33 -34
- package/src/config/bundled-skills/messaging/tools/shared.ts +12 -15
- package/src/config/bundled-skills/settings/SKILL.md +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +2 -8
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
- package/src/config/bundled-skills/slack/tools/shared.ts +4 -10
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +15 -16
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +95 -92
- package/src/config/env-registry.ts +14 -83
- package/src/config/env.ts +11 -50
- package/src/config/feature-flag-registry.json +16 -16
- package/src/config/schema.ts +3 -1
- package/src/config/skills.ts +21 -2
- package/src/context/image-dimensions.ts +229 -0
- package/src/context/token-estimator.ts +75 -12
- package/src/context/window-manager.ts +49 -10
- package/src/daemon/assistant-attachments.ts +1 -13
- package/src/daemon/guardian-action-generators.ts +4 -5
- package/src/daemon/handlers/config-ingress.ts +8 -33
- package/src/daemon/handlers/config-slack-channel.ts +76 -56
- package/src/daemon/handlers/config-telegram.ts +53 -24
- package/src/daemon/handlers/sessions.ts +10 -24
- package/src/daemon/handlers/shared.ts +0 -130
- package/src/daemon/host-cu-proxy.ts +401 -0
- package/src/daemon/lifecycle.ts +39 -63
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/computer-use.ts +2 -119
- package/src/daemon/message-types/host-cu.ts +19 -0
- package/src/daemon/message-types/integrations.ts +1 -0
- package/src/daemon/message-types/messages.ts +3 -0
- package/src/daemon/server.ts +14 -21
- package/src/daemon/session-agent-loop-handlers.ts +2 -0
- package/src/daemon/session-attachments.ts +1 -2
- package/src/daemon/session-messaging.ts +3 -1
- package/src/daemon/session-slash.ts +1 -1
- package/src/daemon/session-surfaces.ts +40 -28
- package/src/daemon/session-tool-setup.ts +20 -11
- package/src/daemon/session.ts +139 -16
- package/src/daemon/tool-side-effects.ts +2 -8
- package/src/daemon/watch-handler.ts +2 -2
- package/src/email/providers/index.ts +2 -1
- package/src/events/tool-metrics-listener.ts +2 -2
- package/src/hooks/manager.ts +1 -4
- package/src/inbound/public-ingress-urls.ts +7 -7
- package/src/instrument.ts +15 -1
- package/src/logfire.ts +16 -5
- package/src/media/app-icon-generator.ts +30 -4
- package/src/media/avatar-router.ts +26 -3
- package/src/media/gemini-image-service.ts +28 -2
- package/src/memory/conversation-key-store.ts +21 -0
- package/src/memory/db-init.ts +4 -0
- package/src/memory/guardian-action-store.ts +1 -1
- package/src/memory/migrations/149-oauth-tables.ts +60 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/schema/guardian.ts +1 -1
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/oauth.ts +65 -0
- package/src/messaging/provider.ts +19 -13
- package/src/messaging/providers/gmail/adapter.ts +40 -23
- package/src/messaging/providers/gmail/client.ts +283 -122
- package/src/messaging/providers/gmail/people-client.ts +32 -24
- package/src/messaging/providers/slack/adapter.ts +29 -19
- package/src/messaging/providers/slack/client.ts +265 -78
- package/src/messaging/providers/telegram-bot/adapter.ts +19 -18
- package/src/messaging/providers/whatsapp/adapter.ts +17 -11
- package/src/messaging/registry.ts +2 -31
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/signal.ts +4 -5
- package/src/oauth/byo-connection.test.ts +537 -0
- package/src/oauth/byo-connection.ts +128 -0
- package/src/oauth/connect-orchestrator.ts +139 -56
- package/src/oauth/connect-types.ts +17 -23
- package/src/oauth/connection-resolver.ts +58 -0
- package/src/oauth/connection.ts +38 -0
- package/src/oauth/manual-token-connection.ts +104 -0
- package/src/oauth/oauth-store.ts +496 -0
- package/src/oauth/platform-connection.test.ts +192 -0
- package/src/oauth/platform-connection.ts +111 -0
- package/src/oauth/provider-behaviors.ts +124 -0
- package/src/oauth/scope-policy.ts +9 -2
- package/src/oauth/seed-providers.ts +161 -0
- package/src/oauth/token-persistence.ts +74 -78
- package/src/permissions/checker.ts +8 -4
- package/src/permissions/defaults.ts +0 -1
- package/src/permissions/prompter.ts +10 -1
- package/src/permissions/trust-store.ts +13 -0
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
- package/src/prompts/system-prompt.ts +70 -45
- package/src/providers/anthropic/client.ts +133 -24
- package/src/providers/gemini/client.ts +15 -6
- package/src/providers/managed-proxy/constants.ts +2 -2
- package/src/providers/managed-proxy/context.ts +5 -1
- package/src/providers/ratelimit.ts +17 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +1 -27
- package/src/runtime/AGENTS.md +17 -0
- package/src/runtime/auth/route-policy.ts +0 -3
- package/src/runtime/channel-invite-transports/telegram.ts +2 -1
- package/src/runtime/channel-readiness-service.ts +168 -195
- package/src/runtime/channel-readiness-types.ts +4 -0
- package/src/runtime/channel-reply-delivery.ts +0 -40
- package/src/runtime/gateway-client.ts +0 -7
- package/src/runtime/guardian-action-conversation-turn.ts +1 -3
- package/src/runtime/guardian-action-followup-executor.ts +1 -1
- package/src/runtime/guardian-action-message-composer.ts +3 -23
- package/src/runtime/http-server.ts +17 -10
- package/src/runtime/http-types.ts +2 -3
- package/src/runtime/middleware/rate-limiter.ts +74 -20
- package/src/runtime/middleware/twilio-validation.ts +1 -11
- package/src/runtime/pending-interactions.ts +14 -12
- package/src/runtime/routes/channel-delivery-routes.ts +0 -1
- package/src/runtime/routes/channel-readiness-routes.ts +2 -0
- package/src/runtime/routes/conversation-routes.ts +73 -19
- package/src/runtime/routes/diagnostics-routes.ts +11 -9
- package/src/runtime/routes/events-routes.ts +21 -11
- package/src/runtime/routes/guardian-approval-interception.ts +20 -5
- package/src/runtime/routes/host-cu-routes.ts +97 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
- package/src/runtime/routes/integrations/slack/share.ts +6 -6
- package/src/runtime/routes/integrations/twilio.ts +6 -5
- package/src/runtime/routes/log-export-routes.ts +126 -8
- package/src/runtime/routes/secret-routes.ts +3 -2
- package/src/runtime/routes/settings-routes.ts +113 -48
- package/src/runtime/routes/surface-action-routes.ts +1 -1
- package/src/runtime/routes/watch-routes.ts +128 -0
- package/src/schedule/integration-status.ts +10 -8
- package/src/security/credential-key.ts +14 -0
- package/src/security/keychain-broker-client.ts +5 -6
- package/src/security/oauth2.ts +1 -1
- package/src/security/token-manager.ts +145 -43
- package/src/skills/catalog-install.ts +358 -0
- package/src/skills/include-graph.ts +32 -0
- package/src/telegram/bot-username.ts +2 -3
- package/src/tools/apps/definitions.ts +0 -5
- package/src/tools/assets/materialize.ts +0 -5
- package/src/tools/assets/search.ts +0 -5
- package/src/tools/browser/headless-browser.ts +1 -67
- package/src/tools/browser/network-recorder.ts +1 -1
- package/src/tools/browser/network-recording-types.ts +1 -1
- package/src/tools/claude-code/claude-code.ts +0 -5
- package/src/tools/computer-use/definitions.ts +46 -11
- package/src/tools/computer-use/registry.ts +4 -5
- package/src/tools/credentials/broker.ts +5 -4
- package/src/tools/credentials/metadata-store.ts +22 -74
- package/src/tools/credentials/resolve.ts +2 -1
- package/src/tools/credentials/vault.ts +139 -151
- package/src/tools/filesystem/edit.ts +1 -6
- package/src/tools/filesystem/read.ts +0 -5
- package/src/tools/filesystem/write.ts +1 -6
- package/src/tools/host-filesystem/edit.ts +1 -6
- package/src/tools/host-filesystem/read.ts +1 -6
- package/src/tools/host-filesystem/write.ts +1 -6
- package/src/tools/mcp/mcp-tool-factory.ts +18 -1
- package/src/tools/memory/definitions.ts +0 -5
- package/src/tools/network/web-fetch.ts +0 -5
- package/src/tools/network/web-search.ts +0 -5
- package/src/tools/registry.ts +2 -7
- package/src/tools/schema-transforms.ts +99 -0
- package/src/tools/skills/load.ts +62 -8
- package/src/tools/swarm/delegate.ts +0 -5
- package/src/tools/system/avatar-generator.ts +0 -5
- package/src/tools/ui-surface/definitions.ts +0 -15
- package/src/tools/watch/screen-watch.ts +0 -5
- package/src/tools/watch/watch-state.ts +0 -12
- package/src/util/logger.ts +7 -41
- package/src/util/platform.ts +9 -28
- package/src/version.ts +10 -0
- package/src/watcher/providers/github.ts +51 -52
- package/src/watcher/providers/gmail.ts +88 -80
- package/src/watcher/providers/google-calendar.ts +94 -86
- package/src/watcher/providers/linear.ts +87 -93
- package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
- package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
- package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
- package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
- package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
- package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
- package/src/cli/commands/dev.ts +0 -129
- package/src/cli/commands/map.ts +0 -391
- package/src/cli/commands/oauth.ts +0 -77
- package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +0 -16
- package/src/daemon/computer-use-session.ts +0 -1020
- package/src/daemon/ride-shotgun-handler.ts +0 -567
- package/src/oauth/provider-profiles.ts +0 -192
- package/src/prompts/computer-use-prompt.ts +0 -98
- package/src/runtime/routes/computer-use-routes.ts +0 -641
- package/src/runtime/telegram-streaming-delivery.test.ts +0 -597
- package/src/runtime/telegram-streaming-delivery.ts +0 -383
- package/src/tools/computer-use/request-computer-control.ts +0 -61
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
deleteApp,
|
|
5
|
+
getApp,
|
|
6
|
+
getAppByProviderAndClientId,
|
|
7
|
+
getMostRecentAppByProvider,
|
|
8
|
+
listApps,
|
|
9
|
+
upsertApp,
|
|
10
|
+
} from "../../../oauth/oauth-store.js";
|
|
11
|
+
import { getCliLogger } from "../../logger.js";
|
|
12
|
+
import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
13
|
+
|
|
14
|
+
const log = getCliLogger("cli");
|
|
15
|
+
|
|
16
|
+
/** Format an app row for output, converting timestamps to ISO strings. */
|
|
17
|
+
function formatAppRow(row: {
|
|
18
|
+
id: string;
|
|
19
|
+
providerKey: string;
|
|
20
|
+
clientId: string;
|
|
21
|
+
createdAt: number;
|
|
22
|
+
updatedAt: number;
|
|
23
|
+
}) {
|
|
24
|
+
return {
|
|
25
|
+
id: row.id,
|
|
26
|
+
providerKey: row.providerKey,
|
|
27
|
+
clientId: row.clientId,
|
|
28
|
+
createdAt: new Date(row.createdAt).toISOString(),
|
|
29
|
+
updatedAt: new Date(row.updatedAt).toISOString(),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function registerAppCommands(oauth: Command): void {
|
|
34
|
+
const apps = oauth
|
|
35
|
+
.command("apps")
|
|
36
|
+
.description("Manage OAuth app registrations (client IDs and secrets)");
|
|
37
|
+
|
|
38
|
+
apps.addHelpText(
|
|
39
|
+
"after",
|
|
40
|
+
`
|
|
41
|
+
Apps represent OAuth client registrations — a client_id and optional
|
|
42
|
+
client_secret linked to a provider. Each provider can have multiple apps
|
|
43
|
+
(e.g. different client IDs for different environments).
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
$ assistant oauth apps list
|
|
47
|
+
$ assistant oauth apps get --id <uuid>
|
|
48
|
+
$ assistant oauth apps get --provider integration:gmail
|
|
49
|
+
$ assistant oauth apps upsert --provider integration:gmail --client-id abc123
|
|
50
|
+
$ assistant oauth apps delete <id>`,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// apps list
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
apps
|
|
58
|
+
.command("list")
|
|
59
|
+
.description("List all OAuth app registrations")
|
|
60
|
+
.addHelpText(
|
|
61
|
+
"after",
|
|
62
|
+
`
|
|
63
|
+
Returns all registered OAuth apps with their provider key, client ID, and
|
|
64
|
+
timestamps. Output is an array of app objects.
|
|
65
|
+
|
|
66
|
+
In JSON mode (--json), returns the array directly. In human mode, logs a
|
|
67
|
+
summary count and prints the formatted list.
|
|
68
|
+
|
|
69
|
+
Examples:
|
|
70
|
+
$ assistant oauth apps list
|
|
71
|
+
$ assistant oauth apps list --json`,
|
|
72
|
+
)
|
|
73
|
+
.action((_opts: unknown, cmd: Command) => {
|
|
74
|
+
try {
|
|
75
|
+
const rows = listApps().map(formatAppRow);
|
|
76
|
+
|
|
77
|
+
if (!shouldOutputJson(cmd)) {
|
|
78
|
+
log.info(`Found ${rows.length} app(s)`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
writeOutput(cmd, rows);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
84
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// apps get
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
apps
|
|
94
|
+
.command("get")
|
|
95
|
+
.description(
|
|
96
|
+
"Look up an OAuth app by ID, provider + client-id, or provider",
|
|
97
|
+
)
|
|
98
|
+
.option("--id <id>", "App ID (UUID)")
|
|
99
|
+
.option("--provider <key>", "Provider key (e.g. integration:gmail)")
|
|
100
|
+
.option("--client-id <id>", "OAuth client ID (requires --provider)")
|
|
101
|
+
.addHelpText(
|
|
102
|
+
"after",
|
|
103
|
+
`
|
|
104
|
+
Three lookup modes are supported:
|
|
105
|
+
|
|
106
|
+
1. By app ID:
|
|
107
|
+
$ assistant oauth apps get --id <uuid>
|
|
108
|
+
|
|
109
|
+
2. By provider + client ID (exact match):
|
|
110
|
+
$ assistant oauth apps get --provider integration:gmail --client-id abc123
|
|
111
|
+
|
|
112
|
+
3. By provider only (returns the most recently created app):
|
|
113
|
+
$ assistant oauth apps get --provider integration:gmail
|
|
114
|
+
|
|
115
|
+
At least --id or --provider must be specified.`,
|
|
116
|
+
)
|
|
117
|
+
.action(
|
|
118
|
+
(
|
|
119
|
+
opts: { id?: string; provider?: string; clientId?: string },
|
|
120
|
+
cmd: Command,
|
|
121
|
+
) => {
|
|
122
|
+
try {
|
|
123
|
+
let row;
|
|
124
|
+
|
|
125
|
+
if (opts.id) {
|
|
126
|
+
row = getApp(opts.id);
|
|
127
|
+
} else if (opts.provider && opts.clientId) {
|
|
128
|
+
row = getAppByProviderAndClientId(opts.provider, opts.clientId);
|
|
129
|
+
} else if (opts.provider) {
|
|
130
|
+
row = getMostRecentAppByProvider(opts.provider);
|
|
131
|
+
} else {
|
|
132
|
+
writeOutput(cmd, {
|
|
133
|
+
ok: false,
|
|
134
|
+
error: "Provide --id, --provider, or --provider + --client-id",
|
|
135
|
+
});
|
|
136
|
+
process.exitCode = 1;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!row) {
|
|
141
|
+
writeOutput(cmd, { ok: false, error: "App not found" });
|
|
142
|
+
process.exitCode = 1;
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
writeOutput(cmd, formatAppRow(row));
|
|
147
|
+
} catch (err) {
|
|
148
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
149
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
150
|
+
process.exitCode = 1;
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// apps upsert
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
apps
|
|
160
|
+
.command("upsert")
|
|
161
|
+
.description("Create or return an existing OAuth app registration")
|
|
162
|
+
.requiredOption("--provider <key>", "Provider key (e.g. integration:gmail)")
|
|
163
|
+
.requiredOption("--client-id <id>", "OAuth client ID")
|
|
164
|
+
.option(
|
|
165
|
+
"--client-secret <secret>",
|
|
166
|
+
"OAuth client secret (stored in secure keychain)",
|
|
167
|
+
)
|
|
168
|
+
.addHelpText(
|
|
169
|
+
"after",
|
|
170
|
+
`
|
|
171
|
+
Creates a new app registration or returns the existing one if an app with the
|
|
172
|
+
same provider and client ID already exists. The client secret, if provided, is
|
|
173
|
+
stored in the secure system keychain — not in the database.
|
|
174
|
+
|
|
175
|
+
When an existing app is matched and a --client-secret is provided, the stored
|
|
176
|
+
secret is updated. The app row itself is returned as-is.
|
|
177
|
+
|
|
178
|
+
Examples:
|
|
179
|
+
$ assistant oauth apps upsert --provider integration:gmail --client-id abc123
|
|
180
|
+
$ assistant oauth apps upsert --provider integration:slack --client-id def456 --client-secret s3cret
|
|
181
|
+
$ assistant oauth apps upsert --provider integration:gmail --client-id abc123 --json`,
|
|
182
|
+
)
|
|
183
|
+
.action(
|
|
184
|
+
async (
|
|
185
|
+
opts: { provider: string; clientId: string; clientSecret?: string },
|
|
186
|
+
cmd: Command,
|
|
187
|
+
) => {
|
|
188
|
+
try {
|
|
189
|
+
const row = await upsertApp(
|
|
190
|
+
opts.provider,
|
|
191
|
+
opts.clientId,
|
|
192
|
+
opts.clientSecret,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
if (!shouldOutputJson(cmd)) {
|
|
196
|
+
log.info(`Upserted app: ${row.id} (provider: ${row.providerKey})`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
writeOutput(cmd, formatAppRow(row));
|
|
200
|
+
} catch (err) {
|
|
201
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
202
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
203
|
+
process.exitCode = 1;
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
// apps delete <id>
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
|
|
212
|
+
apps
|
|
213
|
+
.command("delete <id>")
|
|
214
|
+
.description("Delete an OAuth app registration by ID")
|
|
215
|
+
.addHelpText(
|
|
216
|
+
"after",
|
|
217
|
+
`
|
|
218
|
+
Arguments:
|
|
219
|
+
id The app UUID to delete (as returned by "apps list" or "apps get")
|
|
220
|
+
|
|
221
|
+
Permanently removes the app registration and its stored client secret from
|
|
222
|
+
the keychain. Any OAuth connections that reference this app will no longer be
|
|
223
|
+
able to refresh tokens.
|
|
224
|
+
|
|
225
|
+
Exits with code 1 if the app ID is not found.
|
|
226
|
+
|
|
227
|
+
Examples:
|
|
228
|
+
$ assistant oauth apps delete 550e8400-e29b-41d4-a716-446655440000
|
|
229
|
+
$ assistant oauth apps delete 550e8400-e29b-41d4-a716-446655440000 --json`,
|
|
230
|
+
)
|
|
231
|
+
.action(async (id: string, _opts: unknown, cmd: Command) => {
|
|
232
|
+
try {
|
|
233
|
+
const deleted = await deleteApp(id);
|
|
234
|
+
|
|
235
|
+
if (!deleted) {
|
|
236
|
+
writeOutput(cmd, {
|
|
237
|
+
ok: false,
|
|
238
|
+
error: `App not found: ${id}`,
|
|
239
|
+
});
|
|
240
|
+
process.exitCode = 1;
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!shouldOutputJson(cmd)) {
|
|
245
|
+
log.info(`Deleted app: ${id}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
writeOutput(cmd, { ok: true, id });
|
|
249
|
+
} catch (err) {
|
|
250
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
251
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
252
|
+
process.exitCode = 1;
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
disconnectOAuthProvider,
|
|
5
|
+
getConnection,
|
|
6
|
+
getConnectionByProvider,
|
|
7
|
+
listConnections,
|
|
8
|
+
} from "../../../oauth/oauth-store.js";
|
|
9
|
+
import { credentialKey } from "../../../security/credential-key.js";
|
|
10
|
+
import { deleteSecureKeyAsync } from "../../../security/secure-keys.js";
|
|
11
|
+
import { withValidToken } from "../../../security/token-manager.js";
|
|
12
|
+
import {
|
|
13
|
+
assertMetadataWritable,
|
|
14
|
+
deleteCredentialMetadata,
|
|
15
|
+
} from "../../../tools/credentials/metadata-store.js";
|
|
16
|
+
import { getCliLogger } from "../../logger.js";
|
|
17
|
+
import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
18
|
+
|
|
19
|
+
const log = getCliLogger("cli");
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Keys that may contain secrets in an OAuth token endpoint response.
|
|
23
|
+
* These are stripped from the `metadata` field before CLI output to prevent
|
|
24
|
+
* token leakage via shell history, logs, or agent transcript capture.
|
|
25
|
+
*/
|
|
26
|
+
const REDACTED_METADATA_KEYS = new Set([
|
|
27
|
+
"access_token",
|
|
28
|
+
"refresh_token",
|
|
29
|
+
"id_token",
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
/** Recursively strip secret-bearing keys from a parsed metadata object. */
|
|
33
|
+
function redactMetadata(obj: Record<string, unknown>): Record<string, unknown> {
|
|
34
|
+
const result: Record<string, unknown> = {};
|
|
35
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
36
|
+
if (REDACTED_METADATA_KEYS.has(key)) {
|
|
37
|
+
result[key] = "[REDACTED]";
|
|
38
|
+
} else if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
39
|
+
result[key] = redactMetadata(value as Record<string, unknown>);
|
|
40
|
+
} else {
|
|
41
|
+
result[key] = value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Parse stored JSON string fields and convert timestamps for a connection row. */
|
|
48
|
+
function formatConnectionRow(row: ReturnType<typeof getConnection>) {
|
|
49
|
+
if (!row) return row;
|
|
50
|
+
const parsed = row.metadata ? JSON.parse(row.metadata) : null;
|
|
51
|
+
return {
|
|
52
|
+
...row,
|
|
53
|
+
grantedScopes: row.grantedScopes ? JSON.parse(row.grantedScopes) : [],
|
|
54
|
+
metadata: parsed ? redactMetadata(parsed) : null,
|
|
55
|
+
hasRefreshToken: row.hasRefreshToken === 1,
|
|
56
|
+
createdAt: new Date(row.createdAt).toISOString(),
|
|
57
|
+
updatedAt: new Date(row.updatedAt).toISOString(),
|
|
58
|
+
expiresAt: row.expiresAt ? new Date(row.expiresAt).toISOString() : null,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function registerConnectionCommands(oauth: Command): void {
|
|
63
|
+
const connections = oauth
|
|
64
|
+
.command("connections")
|
|
65
|
+
.description("Manage OAuth connections (active tokens and refresh state)");
|
|
66
|
+
|
|
67
|
+
connections.addHelpText(
|
|
68
|
+
"after",
|
|
69
|
+
`
|
|
70
|
+
Connections represent active OAuth sessions — an access token bound to a
|
|
71
|
+
provider through an app registration. Each connection tracks granted scopes,
|
|
72
|
+
token expiry, refresh token availability, account info, and status.
|
|
73
|
+
|
|
74
|
+
Examples:
|
|
75
|
+
$ assistant oauth connections list
|
|
76
|
+
$ assistant oauth connections list --provider integration:gmail
|
|
77
|
+
$ assistant oauth connections get --id <uuid>
|
|
78
|
+
$ assistant oauth connections get --provider integration:gmail
|
|
79
|
+
$ assistant oauth connections token integration:twitter`,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// connections list
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
connections
|
|
87
|
+
.command("list")
|
|
88
|
+
.description("List all OAuth connections")
|
|
89
|
+
.option(
|
|
90
|
+
"--provider <key>",
|
|
91
|
+
"Filter by provider key (e.g. integration:gmail)",
|
|
92
|
+
)
|
|
93
|
+
.addHelpText(
|
|
94
|
+
"after",
|
|
95
|
+
`
|
|
96
|
+
Lists all OAuth connections, optionally filtered by provider key.
|
|
97
|
+
|
|
98
|
+
Each connection shows its ID, provider, account info, granted scopes, token
|
|
99
|
+
expiry, refresh token availability, and status.
|
|
100
|
+
|
|
101
|
+
Examples:
|
|
102
|
+
$ assistant oauth connections list
|
|
103
|
+
$ assistant oauth connections list --provider integration:gmail`,
|
|
104
|
+
)
|
|
105
|
+
.action((opts: { provider?: string }, cmd: Command) => {
|
|
106
|
+
try {
|
|
107
|
+
const rows = listConnections(opts.provider).map(formatConnectionRow);
|
|
108
|
+
|
|
109
|
+
if (!shouldOutputJson(cmd)) {
|
|
110
|
+
log.info(`Found ${rows.length} connection(s)`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
writeOutput(cmd, rows);
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
116
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
117
|
+
process.exitCode = 1;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// connections get
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
connections
|
|
126
|
+
.command("get")
|
|
127
|
+
.description("Look up an OAuth connection by ID or provider")
|
|
128
|
+
.option("--id <id>", "Connection ID (UUID)")
|
|
129
|
+
.option(
|
|
130
|
+
"--provider <key>",
|
|
131
|
+
"Provider key (returns most recent active connection)",
|
|
132
|
+
)
|
|
133
|
+
.addHelpText(
|
|
134
|
+
"after",
|
|
135
|
+
`
|
|
136
|
+
Two lookup modes are supported:
|
|
137
|
+
|
|
138
|
+
1. By connection ID:
|
|
139
|
+
$ assistant oauth connections get --id <uuid>
|
|
140
|
+
|
|
141
|
+
2. By provider (returns the most recent active connection):
|
|
142
|
+
$ assistant oauth connections get --provider integration:gmail
|
|
143
|
+
|
|
144
|
+
At least --id or --provider must be specified.`,
|
|
145
|
+
)
|
|
146
|
+
.action((opts: { id?: string; provider?: string }, cmd: Command) => {
|
|
147
|
+
try {
|
|
148
|
+
let row;
|
|
149
|
+
|
|
150
|
+
if (opts.id) {
|
|
151
|
+
row = getConnection(opts.id);
|
|
152
|
+
} else if (opts.provider) {
|
|
153
|
+
row = getConnectionByProvider(opts.provider);
|
|
154
|
+
} else {
|
|
155
|
+
writeOutput(cmd, {
|
|
156
|
+
ok: false,
|
|
157
|
+
error: "Provide --id or --provider",
|
|
158
|
+
});
|
|
159
|
+
process.exitCode = 1;
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!row) {
|
|
164
|
+
writeOutput(cmd, { ok: false, error: "Connection not found" });
|
|
165
|
+
process.exitCode = 1;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
writeOutput(cmd, formatConnectionRow(row));
|
|
170
|
+
} catch (err) {
|
|
171
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
172
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
173
|
+
process.exitCode = 1;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// connections token <provider-key>
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
|
|
181
|
+
connections
|
|
182
|
+
.command("token <provider-key>")
|
|
183
|
+
.description(
|
|
184
|
+
"Print a valid OAuth access token for a provider, refreshing if expired",
|
|
185
|
+
)
|
|
186
|
+
.addHelpText(
|
|
187
|
+
"after",
|
|
188
|
+
`
|
|
189
|
+
Arguments:
|
|
190
|
+
provider-key Provider key (e.g. integration:gmail, integration:twitter)
|
|
191
|
+
|
|
192
|
+
Returns a valid OAuth access token for the given provider. If the stored token
|
|
193
|
+
is expired or near-expiry, it is refreshed automatically before being returned.
|
|
194
|
+
|
|
195
|
+
In human mode, prints the bare token to stdout (suitable for shell substitution).
|
|
196
|
+
In JSON mode (--json), prints {"ok": true, "token": "..."}.
|
|
197
|
+
|
|
198
|
+
Exits with code 1 if no access token exists or refresh fails.
|
|
199
|
+
|
|
200
|
+
Examples:
|
|
201
|
+
$ assistant oauth connections token integration:twitter
|
|
202
|
+
$ assistant oauth connections token integration:gmail --json`,
|
|
203
|
+
)
|
|
204
|
+
.action(async (providerKey: string, _opts: unknown, cmd: Command) => {
|
|
205
|
+
try {
|
|
206
|
+
const token = await withValidToken(providerKey, async (t) => t);
|
|
207
|
+
if (shouldOutputJson(cmd)) {
|
|
208
|
+
writeOutput(cmd, { ok: true, token });
|
|
209
|
+
} else {
|
|
210
|
+
process.stdout.write(token + "\n");
|
|
211
|
+
}
|
|
212
|
+
} catch (err) {
|
|
213
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
214
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
215
|
+
process.exitCode = 1;
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// ---------------------------------------------------------------------------
|
|
220
|
+
// connections disconnect <provider-key>
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
|
|
223
|
+
connections
|
|
224
|
+
.command("disconnect <provider-key>")
|
|
225
|
+
.description(
|
|
226
|
+
"Disconnect an OAuth integration and remove all associated credentials",
|
|
227
|
+
)
|
|
228
|
+
.addHelpText(
|
|
229
|
+
"after",
|
|
230
|
+
`
|
|
231
|
+
Arguments:
|
|
232
|
+
provider-key The full provider key (e.g. integration:gmail, integration:slack)
|
|
233
|
+
|
|
234
|
+
Removes the OAuth connection, tokens, and any legacy credential metadata for
|
|
235
|
+
the provider. The <provider-key> argument is the full provider key as-is — it
|
|
236
|
+
is not parsed through service:field splitting.
|
|
237
|
+
|
|
238
|
+
Legacy credential keys for common fields (access_token, refresh_token,
|
|
239
|
+
client_id, client_secret) are also cleaned up if present.
|
|
240
|
+
|
|
241
|
+
Examples:
|
|
242
|
+
$ assistant oauth connections disconnect integration:gmail
|
|
243
|
+
$ assistant oauth connections disconnect integration:slack`,
|
|
244
|
+
)
|
|
245
|
+
.action(async (providerKey: string, _opts: unknown, cmd: Command) => {
|
|
246
|
+
try {
|
|
247
|
+
assertMetadataWritable();
|
|
248
|
+
|
|
249
|
+
let cleanedUp = false;
|
|
250
|
+
|
|
251
|
+
// 1. Disconnect the OAuth connection (new-format keys + connection row)
|
|
252
|
+
const oauthResult = await disconnectOAuthProvider(providerKey);
|
|
253
|
+
if (oauthResult === "error") {
|
|
254
|
+
writeOutput(cmd, {
|
|
255
|
+
ok: false,
|
|
256
|
+
error: `Failed to disconnect OAuth provider "${providerKey}" — please try again`,
|
|
257
|
+
});
|
|
258
|
+
process.exitCode = 1;
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (oauthResult === "disconnected") cleanedUp = true;
|
|
262
|
+
|
|
263
|
+
// 2. Clean up legacy credential keys for common fields
|
|
264
|
+
const legacyFields = [
|
|
265
|
+
"access_token",
|
|
266
|
+
"refresh_token",
|
|
267
|
+
"client_id",
|
|
268
|
+
"client_secret",
|
|
269
|
+
];
|
|
270
|
+
for (const field of legacyFields) {
|
|
271
|
+
const key = credentialKey(providerKey, field);
|
|
272
|
+
const result = await deleteSecureKeyAsync(key);
|
|
273
|
+
if (result === "deleted") cleanedUp = true;
|
|
274
|
+
|
|
275
|
+
const metaDeleted = deleteCredentialMetadata(providerKey, field);
|
|
276
|
+
if (metaDeleted) cleanedUp = true;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (!cleanedUp) {
|
|
280
|
+
writeOutput(cmd, {
|
|
281
|
+
ok: false,
|
|
282
|
+
error: `No OAuth connection or credentials found for "${providerKey}"`,
|
|
283
|
+
});
|
|
284
|
+
process.exitCode = 1;
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
writeOutput(cmd, { ok: true, service: providerKey });
|
|
289
|
+
|
|
290
|
+
if (!shouldOutputJson(cmd)) {
|
|
291
|
+
log.info(`Disconnected ${providerKey}`);
|
|
292
|
+
}
|
|
293
|
+
} catch (err) {
|
|
294
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
295
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
296
|
+
process.exitCode = 1;
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
|
|
3
|
+
import { registerAppCommands } from "./apps.js";
|
|
4
|
+
import { registerConnectionCommands } from "./connections.js";
|
|
5
|
+
import { registerProviderCommands } from "./providers.js";
|
|
6
|
+
|
|
7
|
+
export function registerOAuthCommand(program: Command): void {
|
|
8
|
+
const oauth = program
|
|
9
|
+
.command("oauth")
|
|
10
|
+
.description("Manage OAuth providers, apps, connections, and tokens")
|
|
11
|
+
.option("--json", "Machine-readable compact JSON output");
|
|
12
|
+
|
|
13
|
+
oauth.addHelpText(
|
|
14
|
+
"after",
|
|
15
|
+
`
|
|
16
|
+
The oauth command group manages the full OAuth lifecycle:
|
|
17
|
+
|
|
18
|
+
providers Protocol-level configurations (auth URLs, scopes, endpoints)
|
|
19
|
+
apps Client credentials (client ID / secret pairs)
|
|
20
|
+
connections Active token grants per provider (list, get, token)
|
|
21
|
+
|
|
22
|
+
Providers are seeded on startup for built-in integrations. Apps and connections
|
|
23
|
+
are created during the OAuth authorization flow or can be managed manually via
|
|
24
|
+
their respective subcommands.
|
|
25
|
+
|
|
26
|
+
Examples:
|
|
27
|
+
$ assistant oauth connections token integration:twitter
|
|
28
|
+
$ assistant oauth connections list
|
|
29
|
+
$ assistant oauth connections get --provider integration:gmail
|
|
30
|
+
$ assistant oauth providers list
|
|
31
|
+
$ assistant oauth providers get integration:gmail
|
|
32
|
+
$ assistant oauth providers register --provider-key custom:myapi --auth-url https://example.com/auth --token-url https://example.com/token`,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// providers — subcommand group
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
registerProviderCommands(oauth);
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// apps — subcommand group
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
registerAppCommands(oauth);
|
|
46
|
+
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// connections — subcommand group (includes token)
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
registerConnectionCommands(oauth);
|
|
52
|
+
}
|