@vellumai/assistant 0.5.9 → 0.5.11
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/AGENTS.md +9 -1
- package/ARCHITECTURE.md +48 -48
- package/Dockerfile +2 -0
- package/README.md +1 -1
- package/docs/architecture/integrations.md +6 -13
- package/docs/architecture/memory.md +7 -12
- package/docs/architecture/security.md +5 -5
- package/docs/credential-execution-service.md +9 -9
- package/docs/skills.md +1 -1
- package/node_modules/@vellumai/credential-storage/src/index.ts +2 -2
- package/node_modules/@vellumai/credential-storage/src/static-credentials.ts +1 -1
- package/openapi.yaml +7130 -0
- package/package.json +2 -1
- package/scripts/generate-openapi.ts +562 -0
- package/src/__tests__/acp-session.test.ts +239 -44
- package/src/__tests__/assistant-feature-flag-guard.test.ts +8 -8
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +5 -86
- package/src/__tests__/assistant-feature-flags-integration.test.ts +7 -14
- package/src/__tests__/browser-skill-endstate.test.ts +1 -1
- package/src/__tests__/btw-routes.test.ts +8 -0
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +10 -10
- package/src/__tests__/channel-approvals.test.ts +7 -7
- package/src/__tests__/channel-readiness-service.test.ts +41 -0
- package/src/__tests__/config-schema.test.ts +10 -2
- package/src/__tests__/context-memory-e2e.test.ts +2 -6
- package/src/__tests__/conversation-skill-tools.test.ts +1 -3
- package/src/__tests__/conversation-title-service.test.ts +2 -15
- package/src/__tests__/credential-execution-feature-gates.test.ts +4 -8
- package/src/__tests__/credential-execution-managed-contract.test.ts +8 -8
- package/src/__tests__/credential-security-e2e.test.ts +4 -4
- package/src/__tests__/credential-security-invariants.test.ts +3 -3
- package/src/__tests__/credentials-cli.test.ts +3 -3
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -0
- package/src/__tests__/heartbeat-service.test.ts +35 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +3 -3
- package/src/__tests__/llm-request-log-turn-query.test.ts +64 -0
- package/src/__tests__/log-export-workspace.test.ts +1 -1
- package/src/__tests__/mcp-client-auth.test.ts +1 -1
- package/src/__tests__/memory-lifecycle-e2e.test.ts +2 -2
- package/src/__tests__/memory-recall-log-store.test.ts +182 -0
- package/src/__tests__/memory-recall-quality.test.ts +6 -8
- package/src/__tests__/memory-regressions.test.ts +53 -42
- package/src/__tests__/memory-retrieval.benchmark.test.ts +5 -9
- package/src/__tests__/messaging-skill-split.test.ts +2 -17
- package/src/__tests__/oauth-cli.test.ts +98 -551
- package/src/__tests__/platform-callback-registration.test.ts +119 -0
- package/src/__tests__/secret-ingress-channel.test.ts +261 -0
- package/src/__tests__/secret-ingress-cli.test.ts +201 -0
- package/src/__tests__/secret-ingress-http.test.ts +312 -0
- package/src/__tests__/secret-ingress.test.ts +283 -0
- package/src/__tests__/secret-onetime-send.test.ts +4 -4
- package/src/__tests__/skill-feature-flags-integration.test.ts +4 -4
- package/src/__tests__/skill-feature-flags.test.ts +11 -19
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -1
- package/src/__tests__/skill-load-inline-command.test.ts +3 -3
- package/src/__tests__/skill-load-inline-includes.test.ts +2 -2
- package/src/__tests__/skill-memory.test.ts +2 -4
- package/src/__tests__/skill-projection-feature-flag.test.ts +2 -4
- package/src/__tests__/skill-projection.benchmark.test.ts +1 -3
- package/src/__tests__/skills.test.ts +16 -2
- package/src/__tests__/slack-channel-config.test.ts +1 -1
- package/src/__tests__/slack-skill.test.ts +5 -69
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -1
- package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +5 -238
- package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +5 -206
- package/src/__tests__/workspace-migration-018-rekey-compound-credential-keys.test.ts +181 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +15 -7
- package/src/acp/client-handler.ts +113 -31
- package/src/acp/session-manager.ts +29 -27
- package/src/approvals/guardian-request-resolvers.ts +1 -1
- package/src/cli/AGENTS.md +73 -0
- package/src/cli/commands/autonomy.ts +3 -5
- package/src/cli/commands/credential-execution.ts +1 -2
- package/src/cli/commands/credentials.ts +4 -4
- package/src/cli/commands/memory.ts +2 -3
- package/src/cli/commands/oauth/__tests__/connect.test.ts +785 -0
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +760 -0
- package/src/cli/commands/oauth/__tests__/mode.test.ts +672 -0
- package/src/cli/commands/oauth/__tests__/ping.test.ts +690 -0
- package/src/cli/commands/oauth/__tests__/status.test.ts +579 -0
- package/src/cli/commands/oauth/__tests__/token.test.ts +467 -0
- package/src/cli/commands/oauth/apps.ts +29 -11
- package/src/cli/commands/oauth/connect.ts +373 -0
- package/src/cli/commands/oauth/connections.ts +14 -493
- package/src/cli/commands/oauth/disconnect.ts +333 -0
- package/src/cli/commands/oauth/index.ts +62 -10
- package/src/cli/commands/oauth/mode.ts +263 -0
- package/src/cli/commands/oauth/ping.ts +222 -0
- package/src/cli/commands/oauth/providers.ts +30 -3
- package/src/cli/commands/oauth/request.ts +576 -0
- package/src/cli/commands/oauth/shared.ts +132 -0
- package/src/cli/commands/oauth/status.ts +202 -0
- package/src/cli/commands/oauth/token.ts +159 -0
- package/src/cli/commands/platform.ts +20 -14
- package/src/cli.ts +82 -17
- package/src/config/assistant-feature-flags.ts +74 -11
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +13 -36
- package/src/config/bundled-skills/messaging/TOOLS.json +9 -9
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +1 -1
- package/src/config/bundled-skills/notifications/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +2 -2
- package/src/config/bundled-skills/settings/SKILL.md +5 -3
- package/src/config/bundled-skills/settings/TOOLS.json +17 -0
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +50 -0
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +7 -0
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +6 -1
- package/src/config/bundled-skills/settings/tools/identity-avatar.ts +55 -0
- package/src/config/bundled-skills/skills-catalog/SKILL.md +3 -3
- package/src/config/bundled-skills/slack/SKILL.md +58 -44
- package/src/config/bundled-tool-registry.ts +2 -19
- package/src/config/env.ts +5 -1
- package/src/config/feature-flag-registry.json +57 -41
- package/src/config/loader.ts +4 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/security.ts +9 -1
- package/src/config/schemas/services.ts +1 -1
- package/src/config/skill-state.ts +1 -3
- package/src/config/skills.ts +2 -4
- package/src/credential-execution/feature-gates.ts +9 -16
- package/src/credential-execution/process-manager.ts +12 -0
- package/src/daemon/config-watcher.ts +4 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +10 -0
- package/src/daemon/conversation-agent-loop.ts +49 -2
- package/src/daemon/conversation-memory.ts +0 -1
- package/src/daemon/handlers/config-slack-channel.ts +43 -1
- package/src/daemon/handlers/conversations.ts +41 -33
- package/src/daemon/lifecycle.ts +28 -5
- package/src/daemon/message-types/acp.ts +0 -15
- package/src/daemon/message-types/memory.ts +0 -1
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/schedules.ts +9 -0
- package/src/daemon/server.ts +19 -7
- package/src/email/feature-gate.ts +3 -3
- package/src/heartbeat/heartbeat-service.ts +48 -0
- package/src/inbound/platform-callback-registration.ts +61 -7
- package/src/mcp/mcp-oauth-provider.ts +3 -3
- package/src/memory/app-store.ts +3 -3
- package/src/memory/conversation-crud.ts +124 -0
- package/src/memory/conversation-title-service.ts +7 -17
- package/src/memory/db-init.ts +8 -0
- package/src/memory/embedding-local.ts +47 -2
- package/src/memory/indexer.ts +13 -10
- package/src/memory/items-extractor.ts +12 -4
- package/src/memory/job-utils.ts +5 -0
- package/src/memory/jobs-store.ts +10 -2
- package/src/memory/journal-memory.ts +6 -2
- package/src/memory/llm-request-log-store.ts +88 -21
- package/src/memory/memory-recall-log-store.ts +128 -0
- package/src/memory/migrations/194-memory-recall-logs.ts +50 -0
- package/src/memory/migrations/195-oauth-providers-ping-config.ts +23 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/migrations/validate-migration-state.ts +14 -1
- package/src/memory/retriever.test.ts +4 -5
- package/src/memory/schema/infrastructure.ts +31 -0
- package/src/memory/schema/oauth.ts +3 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +1 -1
- package/src/oauth/connect-orchestrator.ts +54 -0
- package/src/oauth/manual-token-connection.ts +5 -5
- package/src/oauth/oauth-store.ts +26 -5
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/checker.ts +2 -2
- package/src/permissions/trust-client.ts +2 -2
- package/src/platform/client.ts +2 -2
- package/src/prompts/journal-context.ts +6 -1
- package/src/providers/anthropic/client.ts +143 -1
- package/src/runtime/auth/__tests__/middleware.test.ts +19 -0
- package/src/runtime/auth/route-policy.ts +0 -1
- package/src/runtime/btw-sidechain.ts +7 -1
- package/src/runtime/channel-approvals.ts +2 -2
- package/src/runtime/channel-readiness-service.ts +30 -7
- package/src/runtime/http-router.ts +31 -0
- package/src/runtime/http-server.ts +21 -4
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/pending-interactions.ts +21 -3
- package/src/runtime/routes/acp-routes.ts +46 -28
- package/src/runtime/routes/app-management-routes.ts +123 -0
- package/src/runtime/routes/app-routes.ts +31 -0
- package/src/runtime/routes/approval-routes.ts +108 -3
- package/src/runtime/routes/attachment-routes.ts +45 -0
- package/src/runtime/routes/avatar-routes.ts +16 -0
- package/src/runtime/routes/brain-graph-routes.ts +18 -0
- package/src/runtime/routes/btw-routes.ts +20 -0
- package/src/runtime/routes/call-routes.ts +81 -0
- package/src/runtime/routes/channel-readiness-routes.ts +48 -7
- package/src/runtime/routes/channel-routes.ts +18 -0
- package/src/runtime/routes/channel-verification-routes.ts +49 -1
- package/src/runtime/routes/contact-routes.ts +77 -0
- package/src/runtime/routes/conversation-attention-routes.ts +37 -0
- package/src/runtime/routes/conversation-management-routes.ts +94 -0
- package/src/runtime/routes/conversation-query-routes.ts +78 -0
- package/src/runtime/routes/conversation-routes.ts +115 -38
- package/src/runtime/routes/conversation-starter-routes.ts +29 -0
- package/src/runtime/routes/debug-routes.ts +23 -0
- package/src/runtime/routes/diagnostics-routes.ts +30 -0
- package/src/runtime/routes/documents-routes.ts +42 -0
- package/src/runtime/routes/events-routes.ts +10 -0
- package/src/runtime/routes/global-search-routes.ts +35 -0
- package/src/runtime/routes/guardian-action-routes.ts +47 -2
- package/src/runtime/routes/guardian-approval-prompt.ts +77 -2
- package/src/runtime/routes/heartbeat-routes.ts +278 -0
- package/src/runtime/routes/host-bash-routes.ts +16 -1
- package/src/runtime/routes/host-cu-routes.ts +23 -1
- package/src/runtime/routes/host-file-routes.ts +18 -1
- package/src/runtime/routes/identity-routes.ts +35 -0
- package/src/runtime/routes/inbound-message-handler.ts +46 -25
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +30 -2
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +1 -2
- package/src/runtime/routes/integrations/twilio.ts +32 -22
- package/src/runtime/routes/invite-routes.ts +83 -0
- package/src/runtime/routes/log-export-routes.ts +14 -0
- package/src/runtime/routes/memory-item-routes.ts +99 -1
- package/src/runtime/routes/migration-rollback-routes.ts +25 -0
- package/src/runtime/routes/migration-routes.ts +40 -0
- package/src/runtime/routes/notification-routes.ts +20 -0
- package/src/runtime/routes/oauth-apps.ts +11 -3
- package/src/runtime/routes/pairing-routes.ts +15 -0
- package/src/runtime/routes/recording-routes.ts +72 -0
- package/src/runtime/routes/schedule-routes.ts +77 -5
- package/src/runtime/routes/secret-routes.ts +63 -1
- package/src/runtime/routes/settings-routes.ts +91 -1
- package/src/runtime/routes/skills-routes.ts +98 -16
- package/src/runtime/routes/subagents-routes.ts +38 -3
- package/src/runtime/routes/surface-action-routes.ts +66 -24
- package/src/runtime/routes/surface-content-routes.ts +20 -0
- package/src/runtime/routes/telemetry-routes.ts +12 -0
- package/src/runtime/routes/trace-event-routes.ts +25 -0
- package/src/runtime/routes/trust-rules-routes.ts +46 -0
- package/src/runtime/routes/tts-routes.ts +15 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +38 -0
- package/src/runtime/routes/usage-routes.ts +59 -0
- package/src/runtime/routes/watch-routes.ts +28 -0
- package/src/runtime/routes/work-items-routes.ts +59 -0
- package/src/runtime/routes/workspace-commit-routes.ts +12 -0
- package/src/runtime/routes/workspace-routes.ts +102 -0
- package/src/schedule/scheduler.ts +7 -1
- package/src/security/AGENTS.md +7 -0
- package/src/security/credential-backend.ts +1 -1
- package/src/security/encrypted-store.ts +3 -3
- package/src/security/oauth2.ts +55 -0
- package/src/security/secret-ingress.ts +174 -0
- package/src/security/secret-patterns.ts +133 -0
- package/src/security/secret-scanner.ts +28 -117
- package/src/signals/confirm.ts +12 -8
- package/src/signals/user-message.ts +18 -3
- package/src/skills/skill-memory.ts +1 -2
- package/src/tasks/task-runner.ts +7 -1
- package/src/tools/credentials/broker.ts +1 -1
- package/src/tools/credentials/metadata-store.ts +1 -1
- package/src/tools/credentials/vault.ts +2 -3
- package/src/tools/memory/definitions.ts +1 -1
- package/src/tools/memory/handlers.test.ts +2 -4
- package/src/tools/skills/load.ts +1 -1
- package/src/tools/terminal/safe-env.ts +7 -0
- package/src/tools/tool-manifest.ts +1 -1
- package/src/util/log-redact.ts +9 -34
- package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +13 -148
- package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +7 -145
- package/src/workspace/migrations/AGENTS.md +11 -0
- package/src/workspace/migrations/runner.ts +16 -6
- package/src/workspace/migrations/types.ts +7 -0
- package/docs/architecture/keychain-broker.md +0 -69
- package/src/__tests__/keychain-broker-client.test.ts +0 -800
- package/src/cli/commands/oauth/platform.ts +0 -525
- package/src/config/bundled-skills/slack/TOOLS.json +0 -272
- package/src/config/bundled-skills/slack/tools/shared.ts +0 -34
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +0 -27
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +0 -38
- package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +0 -146
- package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +0 -105
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +0 -26
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +0 -27
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +0 -25
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +0 -372
- package/src/security/keychain-broker-client.ts +0 -446
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
disconnectOAuthProvider,
|
|
5
|
+
getActiveConnection,
|
|
6
|
+
getConnection,
|
|
7
|
+
getProvider,
|
|
8
|
+
listActiveConnectionsByProvider,
|
|
9
|
+
} from "../../../oauth/oauth-store.js";
|
|
10
|
+
import { deleteCredentialMetadata } from "../../../tools/credentials/metadata-store.js";
|
|
11
|
+
import { deleteSecureKeyViaDaemon } from "../../lib/daemon-credential-client.js";
|
|
12
|
+
import { getCliLogger } from "../../logger.js";
|
|
13
|
+
import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
14
|
+
import {
|
|
15
|
+
fetchActiveConnections,
|
|
16
|
+
isManagedMode,
|
|
17
|
+
requirePlatformClient,
|
|
18
|
+
resolveService,
|
|
19
|
+
toBareProvider,
|
|
20
|
+
} from "./shared.js";
|
|
21
|
+
|
|
22
|
+
const log = getCliLogger("cli");
|
|
23
|
+
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Command registration
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
export function registerDisconnectCommand(oauth: Command): void {
|
|
29
|
+
oauth
|
|
30
|
+
.command("disconnect <provider>")
|
|
31
|
+
.description(
|
|
32
|
+
"Disconnect an OAuth provider and remove associated credentials (auto-detects managed vs BYO mode)",
|
|
33
|
+
)
|
|
34
|
+
.option(
|
|
35
|
+
"--account <identifier>",
|
|
36
|
+
"Account identifier to disconnect (e.g. email address)",
|
|
37
|
+
)
|
|
38
|
+
.option("--connection-id <id>", "Exact connection ID to disconnect")
|
|
39
|
+
.addHelpText(
|
|
40
|
+
"after",
|
|
41
|
+
`
|
|
42
|
+
Arguments:
|
|
43
|
+
provider Provider name or key (e.g. google, integration:google, gmail).
|
|
44
|
+
Run 'assistant oauth providers list' to see available providers.
|
|
45
|
+
|
|
46
|
+
Options:
|
|
47
|
+
--account Recommended way to specify which connection to disconnect.
|
|
48
|
+
Works for both managed and BYO modes. Use the account
|
|
49
|
+
identifier shown by 'assistant oauth status <provider>'
|
|
50
|
+
(e.g. an email address for Google).
|
|
51
|
+
--connection-id Exact match on the connection ID shown by
|
|
52
|
+
'assistant oauth status <provider>'. Useful when account
|
|
53
|
+
labels are ambiguous or absent.
|
|
54
|
+
|
|
55
|
+
At most one of --account or --connection-id may be specified.
|
|
56
|
+
|
|
57
|
+
Disambiguation:
|
|
58
|
+
When a provider has multiple active connections and neither --account nor
|
|
59
|
+
--connection-id is given, the command errors with a list of connections
|
|
60
|
+
(id + account label) and a hint to use --account or --connection-id.
|
|
61
|
+
Run 'assistant oauth status <provider>' to discover available values.
|
|
62
|
+
|
|
63
|
+
Examples:
|
|
64
|
+
$ assistant oauth disconnect google
|
|
65
|
+
$ assistant oauth disconnect google --account user@gmail.com
|
|
66
|
+
$ assistant oauth disconnect google --connection-id conn_abc123`,
|
|
67
|
+
)
|
|
68
|
+
.action(
|
|
69
|
+
async (
|
|
70
|
+
provider: string,
|
|
71
|
+
opts: { account?: string; connectionId?: string },
|
|
72
|
+
cmd: Command,
|
|
73
|
+
) => {
|
|
74
|
+
const jsonMode = shouldOutputJson(cmd);
|
|
75
|
+
|
|
76
|
+
// Helper: write an error and set exit code
|
|
77
|
+
const writeError = (
|
|
78
|
+
error: string,
|
|
79
|
+
extra?: Record<string, unknown>,
|
|
80
|
+
): void => {
|
|
81
|
+
writeOutput(cmd, { ok: false, error, ...extra });
|
|
82
|
+
process.exitCode = 1;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
// -------------------------------------------------------------------
|
|
87
|
+
// 1. Resolve + validate provider
|
|
88
|
+
// -------------------------------------------------------------------
|
|
89
|
+
const providerKey = resolveService(provider);
|
|
90
|
+
|
|
91
|
+
const providerRow = getProvider(providerKey);
|
|
92
|
+
if (!providerRow) {
|
|
93
|
+
writeError(
|
|
94
|
+
`Unknown provider "${provider}".\n\n` +
|
|
95
|
+
`Run 'assistant oauth providers list' to see available providers.\n` +
|
|
96
|
+
`If this is a custom provider, register it first with 'assistant oauth providers register --help'.`,
|
|
97
|
+
);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// -------------------------------------------------------------------
|
|
102
|
+
// 2. Validate mutual exclusivity
|
|
103
|
+
// -------------------------------------------------------------------
|
|
104
|
+
if (opts.account && opts.connectionId) {
|
|
105
|
+
writeError(
|
|
106
|
+
`Cannot specify both --account and --connection-id. Use one or the other.\n\n` +
|
|
107
|
+
`Run 'assistant oauth status ${provider}' to see connected accounts and IDs.`,
|
|
108
|
+
);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// -------------------------------------------------------------------
|
|
113
|
+
// 3. Detect mode
|
|
114
|
+
// -------------------------------------------------------------------
|
|
115
|
+
const managed = isManagedMode(providerKey);
|
|
116
|
+
|
|
117
|
+
if (managed) {
|
|
118
|
+
// -----------------------------------------------------------------
|
|
119
|
+
// Managed path
|
|
120
|
+
// -----------------------------------------------------------------
|
|
121
|
+
const client = await requirePlatformClient(cmd);
|
|
122
|
+
if (!client) return;
|
|
123
|
+
|
|
124
|
+
const entries = await fetchActiveConnections(
|
|
125
|
+
client,
|
|
126
|
+
providerKey,
|
|
127
|
+
cmd,
|
|
128
|
+
);
|
|
129
|
+
if (!entries) return;
|
|
130
|
+
|
|
131
|
+
let connectionId: string | undefined;
|
|
132
|
+
let accountLabel: string | undefined;
|
|
133
|
+
|
|
134
|
+
if (opts.account) {
|
|
135
|
+
// Filter connections by account_label matching the account value
|
|
136
|
+
const matching = entries.filter(
|
|
137
|
+
(c) => c.account_label === opts.account,
|
|
138
|
+
);
|
|
139
|
+
if (matching.length === 0) {
|
|
140
|
+
writeError(
|
|
141
|
+
`No active connection found for "${toBareProvider(providerKey)}" with account "${opts.account}".\n\n` +
|
|
142
|
+
`Run 'assistant oauth status ${provider}' to see connected accounts.`,
|
|
143
|
+
);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
connectionId = matching[0].id;
|
|
147
|
+
accountLabel = matching[0].account_label;
|
|
148
|
+
} else if (opts.connectionId) {
|
|
149
|
+
// Verify the supplied ID belongs to this provider
|
|
150
|
+
const match = entries.find((c) => c.id === opts.connectionId);
|
|
151
|
+
if (!match) {
|
|
152
|
+
writeError(
|
|
153
|
+
`Connection "${opts.connectionId}" is not an active ${toBareProvider(providerKey)} connection.\n\n` +
|
|
154
|
+
`Run 'assistant oauth status ${provider}' to see active connections.`,
|
|
155
|
+
);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
connectionId = match.id;
|
|
159
|
+
accountLabel = match.account_label;
|
|
160
|
+
} else {
|
|
161
|
+
// Neither specified — auto-resolve
|
|
162
|
+
if (entries.length === 0) {
|
|
163
|
+
writeError(
|
|
164
|
+
`No active connections found for "${toBareProvider(providerKey)}".\n\n` +
|
|
165
|
+
`Run 'assistant oauth status ${provider}' to check connection status.`,
|
|
166
|
+
);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (entries.length > 1) {
|
|
171
|
+
const connectionList = entries.map((c) => ({
|
|
172
|
+
id: c.id,
|
|
173
|
+
account: c.account_label ?? null,
|
|
174
|
+
}));
|
|
175
|
+
writeError(
|
|
176
|
+
`Multiple active connections for "${toBareProvider(providerKey)}". ` +
|
|
177
|
+
`Specify which one to disconnect with --account or --connection-id.\n\n` +
|
|
178
|
+
`Run 'assistant oauth status ${provider}' to see connected accounts and IDs.`,
|
|
179
|
+
{ connections: connectionList },
|
|
180
|
+
);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
connectionId = entries[0].id;
|
|
185
|
+
accountLabel = entries[0].account_label;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Call platform /disconnect/ endpoint
|
|
189
|
+
const disconnectPath = `/v1/assistants/${encodeURIComponent(client.platformAssistantId)}/oauth/connections/${encodeURIComponent(connectionId)}/disconnect/`;
|
|
190
|
+
const disconnectResponse = await client.fetch(disconnectPath, {
|
|
191
|
+
method: "POST",
|
|
192
|
+
headers: { "Content-Type": "application/json" },
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
if (!disconnectResponse.ok) {
|
|
196
|
+
const errorText = await disconnectResponse.text().catch(() => "");
|
|
197
|
+
writeError(
|
|
198
|
+
`Platform returned HTTP ${disconnectResponse.status}${errorText ? `: ${errorText}` : ""}`,
|
|
199
|
+
);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const result: Record<string, unknown> = {
|
|
204
|
+
ok: true,
|
|
205
|
+
provider: providerKey,
|
|
206
|
+
connectionId,
|
|
207
|
+
};
|
|
208
|
+
if (accountLabel) result.account = accountLabel;
|
|
209
|
+
writeOutput(cmd, result);
|
|
210
|
+
|
|
211
|
+
if (!jsonMode) {
|
|
212
|
+
log.info(
|
|
213
|
+
`Disconnected ${providerKey} connection ${connectionId}`,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
// -----------------------------------------------------------------
|
|
218
|
+
// BYO path
|
|
219
|
+
// -----------------------------------------------------------------
|
|
220
|
+
let connectionId: string | undefined;
|
|
221
|
+
let accountLabel: string | undefined;
|
|
222
|
+
|
|
223
|
+
if (opts.account) {
|
|
224
|
+
const conn = getActiveConnection(providerKey, {
|
|
225
|
+
account: opts.account,
|
|
226
|
+
});
|
|
227
|
+
if (!conn) {
|
|
228
|
+
writeError(
|
|
229
|
+
`No active connection found for "${providerKey}" with account "${opts.account}".\n\n` +
|
|
230
|
+
`Run 'assistant oauth status ${provider}' to see connected accounts.`,
|
|
231
|
+
);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
connectionId = conn.id;
|
|
235
|
+
accountLabel = conn.accountInfo ?? undefined;
|
|
236
|
+
} else if (opts.connectionId) {
|
|
237
|
+
const conn = getConnection(opts.connectionId);
|
|
238
|
+
if (!conn || conn.providerKey !== providerKey) {
|
|
239
|
+
writeError(
|
|
240
|
+
`Connection "${opts.connectionId}" is not an active ${providerKey} connection.\n\n` +
|
|
241
|
+
`Run 'assistant oauth status ${provider}' to see active connections.`,
|
|
242
|
+
);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
connectionId = conn.id;
|
|
246
|
+
accountLabel = conn.accountInfo ?? undefined;
|
|
247
|
+
} else {
|
|
248
|
+
// Neither specified — auto-resolve
|
|
249
|
+
const active = listActiveConnectionsByProvider(providerKey);
|
|
250
|
+
|
|
251
|
+
if (active.length === 0) {
|
|
252
|
+
writeError(
|
|
253
|
+
`No active connections found for "${providerKey}".\n\n` +
|
|
254
|
+
`Run 'assistant oauth status ${provider}' to check connection status.`,
|
|
255
|
+
);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (active.length > 1) {
|
|
260
|
+
const connectionList = active.map((c) => ({
|
|
261
|
+
id: c.id,
|
|
262
|
+
account: c.accountInfo ?? null,
|
|
263
|
+
}));
|
|
264
|
+
writeError(
|
|
265
|
+
`Multiple active connections for "${providerKey}". ` +
|
|
266
|
+
`Specify which one to disconnect with --account or --connection-id.\n\n` +
|
|
267
|
+
`Run 'assistant oauth status ${provider}' to see connected accounts and IDs.`,
|
|
268
|
+
{ connections: connectionList },
|
|
269
|
+
);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
connectionId = active[0].id;
|
|
274
|
+
accountLabel = active[0].accountInfo ?? undefined;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Disconnect the OAuth connection (tokens + connection row)
|
|
278
|
+
const oauthResult = await disconnectOAuthProvider(
|
|
279
|
+
providerKey,
|
|
280
|
+
undefined,
|
|
281
|
+
connectionId,
|
|
282
|
+
);
|
|
283
|
+
if (oauthResult === "error") {
|
|
284
|
+
writeError(
|
|
285
|
+
`Failed to disconnect OAuth provider "${providerKey}" — please try again.`,
|
|
286
|
+
);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Clean up legacy credential keys
|
|
291
|
+
const legacyFields = [
|
|
292
|
+
"access_token",
|
|
293
|
+
"refresh_token",
|
|
294
|
+
"client_id",
|
|
295
|
+
"client_secret",
|
|
296
|
+
];
|
|
297
|
+
for (const field of legacyFields) {
|
|
298
|
+
try {
|
|
299
|
+
await deleteSecureKeyViaDaemon(
|
|
300
|
+
"credential",
|
|
301
|
+
`${providerKey}:${field}`,
|
|
302
|
+
);
|
|
303
|
+
} catch {
|
|
304
|
+
// Best-effort cleanup — ignore failures
|
|
305
|
+
}
|
|
306
|
+
try {
|
|
307
|
+
deleteCredentialMetadata(providerKey, field);
|
|
308
|
+
} catch {
|
|
309
|
+
// Best-effort cleanup — ignore failures
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const result: Record<string, unknown> = {
|
|
314
|
+
ok: true,
|
|
315
|
+
provider: providerKey,
|
|
316
|
+
connectionId,
|
|
317
|
+
};
|
|
318
|
+
if (accountLabel) result.account = accountLabel;
|
|
319
|
+
writeOutput(cmd, result);
|
|
320
|
+
|
|
321
|
+
if (!jsonMode) {
|
|
322
|
+
log.info(
|
|
323
|
+
`Disconnected ${providerKey} connection ${connectionId}`,
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
} catch (err) {
|
|
328
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
329
|
+
writeError(message);
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
);
|
|
333
|
+
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
|
|
3
3
|
import { registerAppCommands } from "./apps.js";
|
|
4
|
+
import { registerConnectCommand } from "./connect.js";
|
|
4
5
|
import { registerConnectionCommands } from "./connections.js";
|
|
5
|
-
import {
|
|
6
|
+
import { registerDisconnectCommand } from "./disconnect.js";
|
|
7
|
+
import { registerModeCommand } from "./mode.js";
|
|
8
|
+
import { registerPingCommand } from "./ping.js";
|
|
6
9
|
import { registerProviderCommands } from "./providers.js";
|
|
10
|
+
import { registerRequestCommand } from "./request.js";
|
|
11
|
+
import { registerStatusCommand } from "./status.js";
|
|
12
|
+
import { registerTokenCommand } from "./token.js";
|
|
7
13
|
|
|
8
14
|
export function registerOAuthCommand(program: Command): void {
|
|
9
15
|
const oauth = program
|
|
@@ -16,21 +22,31 @@ export function registerOAuthCommand(program: Command): void {
|
|
|
16
22
|
`
|
|
17
23
|
The oauth command group manages the full OAuth lifecycle:
|
|
18
24
|
|
|
25
|
+
connect Initiate an OAuth flow for a provider (managed or BYO)
|
|
26
|
+
disconnect Disconnect an OAuth provider
|
|
27
|
+
status Show OAuth connection status for a provider
|
|
28
|
+
mode Get or set OAuth mode (managed vs your-own) for a provider
|
|
29
|
+
token Print a valid OAuth access token (BYO providers only)
|
|
30
|
+
ping Verify an OAuth token is valid by hitting the provider's health-check endpoint
|
|
31
|
+
request Make authenticated HTTP requests (curl-like interface)
|
|
19
32
|
providers Protocol-level configurations (auth URLs, scopes, endpoints)
|
|
20
33
|
apps Client credentials (client ID / secret pairs)
|
|
21
|
-
connections Active token grants per provider (list, get
|
|
34
|
+
connections Active token grants per provider (list, get)
|
|
22
35
|
|
|
23
36
|
Providers are seeded on startup for built-in integrations. Apps and connections
|
|
24
37
|
are created during the OAuth authorization flow or can be managed manually via
|
|
25
38
|
their respective subcommands.
|
|
26
39
|
|
|
27
40
|
Examples:
|
|
28
|
-
$ assistant oauth
|
|
29
|
-
$ assistant oauth
|
|
30
|
-
$ assistant oauth
|
|
41
|
+
$ assistant oauth connect google --open-browser
|
|
42
|
+
$ assistant oauth status google
|
|
43
|
+
$ assistant oauth ping google
|
|
44
|
+
$ assistant oauth disconnect google
|
|
45
|
+
$ assistant oauth request --provider integration:google /gmail/v1/users/me/messages
|
|
46
|
+
$ assistant oauth request --provider integration:twitter -X POST -d '{"text":"Hello"}' https://api.x.com/2/tweets
|
|
47
|
+
$ assistant oauth token integration:twitter
|
|
31
48
|
$ assistant oauth providers list
|
|
32
|
-
$ assistant oauth providers get integration:google
|
|
33
|
-
$ assistant oauth providers register --provider-key custom:myapi --auth-url https://example.com/auth --token-url https://example.com/token`,
|
|
49
|
+
$ assistant oauth providers get integration:google`,
|
|
34
50
|
);
|
|
35
51
|
|
|
36
52
|
// ---------------------------------------------------------------------------
|
|
@@ -46,14 +62,50 @@ Examples:
|
|
|
46
62
|
registerAppCommands(oauth);
|
|
47
63
|
|
|
48
64
|
// ---------------------------------------------------------------------------
|
|
49
|
-
// connections — subcommand group (
|
|
65
|
+
// connections — subcommand group (list, get)
|
|
50
66
|
// ---------------------------------------------------------------------------
|
|
51
67
|
|
|
52
68
|
registerConnectionCommands(oauth);
|
|
53
69
|
|
|
54
70
|
// ---------------------------------------------------------------------------
|
|
55
|
-
//
|
|
71
|
+
// request — curl-like authenticated request command
|
|
56
72
|
// ---------------------------------------------------------------------------
|
|
57
73
|
|
|
58
|
-
|
|
74
|
+
registerRequestCommand(oauth);
|
|
75
|
+
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// connect — unified connect command (auto-detects managed vs BYO)
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
registerConnectCommand(oauth);
|
|
81
|
+
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// disconnect — unified disconnect with auto-detected managed/BYO routing
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
registerDisconnectCommand(oauth);
|
|
87
|
+
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// status — unified connection status (auto-detects managed vs BYO)
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
|
|
92
|
+
registerStatusCommand(oauth);
|
|
93
|
+
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// mode — get or set OAuth mode (managed vs your-own) for a provider
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
registerModeCommand(oauth);
|
|
99
|
+
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// ping — unified ping command (auto-detects managed vs BYO)
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
registerPingCommand(oauth);
|
|
105
|
+
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// token — unified token retrieval (BYO only, managed-mode guard)
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
registerTokenCommand(oauth);
|
|
59
111
|
}
|