@vellumai/assistant 0.5.11 → 0.5.13
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/Dockerfile +42 -9
- package/docs/architecture/integrations.md +34 -32
- package/node_modules/@vellumai/ces-contracts/src/__tests__/grants.test.ts +7 -7
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +5 -4
- package/node_modules/@vellumai/ces-contracts/src/index.ts +7 -0
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +5 -0
- package/node_modules/@vellumai/credential-storage/src/index.ts +1 -1
- package/openapi.yaml +87 -9
- package/package.json +1 -1
- package/src/__tests__/catalog-cache.test.ts +164 -0
- package/src/__tests__/catalog-search.test.ts +61 -0
- package/src/__tests__/cli-command-risk-guard.test.ts +181 -6
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +396 -0
- package/src/__tests__/conversation-error.test.ts +3 -2
- package/src/__tests__/credential-security-invariants.test.ts +9 -15
- package/src/__tests__/credential-vault-unit.test.ts +32 -34
- package/src/__tests__/credential-vault.test.ts +25 -33
- package/src/__tests__/credentials-cli.test.ts +3 -3
- package/src/__tests__/daemon-credential-client.test.ts +2 -2
- package/src/__tests__/first-greeting.test.ts +7 -0
- package/src/__tests__/host-bash-proxy.test.ts +79 -0
- package/src/__tests__/host-cu-proxy.test.ts +90 -0
- package/src/__tests__/host-file-proxy.test.ts +89 -0
- package/src/__tests__/integration-status.test.ts +5 -5
- package/src/__tests__/list-messages-attachments.test.ts +171 -0
- package/src/__tests__/mcp-abort-signal.test.ts +205 -0
- package/src/__tests__/messaging-send-tool.test.ts +5 -5
- package/src/__tests__/navigate-settings-tab.test.ts +6 -2
- package/src/__tests__/notification-telegram-adapter.test.ts +125 -0
- package/src/__tests__/oauth-cli.test.ts +126 -119
- package/src/__tests__/oauth-provider-profiles.test.ts +55 -20
- package/src/__tests__/oauth-scope-policy.test.ts +4 -6
- package/src/__tests__/onboarding-template-contract.test.ts +2 -2
- package/src/__tests__/platform.test.ts +3 -168
- package/src/__tests__/secret-routes-managed-proxy.test.ts +78 -0
- package/src/__tests__/secure-keys-managed-failover.test.ts +73 -0
- package/src/__tests__/skill-feature-flags.test.ts +8 -0
- package/src/__tests__/skill-secret-handling-guard.test.ts +212 -0
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/slack-messaging-token-resolution.test.ts +22 -24
- package/src/__tests__/slack-share-routes.test.ts +5 -5
- package/src/__tests__/system-prompt.test.ts +39 -0
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -1
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +5 -4
- package/src/cli/AGENTS.md +47 -7
- package/src/cli/commands/browser-relay.ts +2 -17
- package/src/cli/commands/contacts.ts +6 -4
- package/src/cli/commands/conversations.ts +13 -1
- package/src/cli/commands/credential-execution.ts +16 -1
- package/src/cli/commands/credentials.ts +2 -8
- package/src/cli/commands/oauth/__tests__/connect.test.ts +29 -108
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +13 -87
- package/src/cli/commands/oauth/__tests__/mode.test.ts +22 -69
- package/src/cli/commands/oauth/__tests__/ping.test.ts +20 -79
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +574 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +416 -0
- package/src/cli/commands/oauth/__tests__/status.test.ts +12 -40
- package/src/cli/commands/oauth/__tests__/token.test.ts +3 -50
- package/src/cli/commands/oauth/apps.ts +63 -44
- package/src/cli/commands/oauth/connect.ts +187 -155
- package/src/cli/commands/oauth/disconnect.ts +27 -75
- package/src/cli/commands/oauth/index.ts +36 -46
- package/src/cli/commands/oauth/mode.ts +22 -34
- package/src/cli/commands/oauth/ping.ts +19 -45
- package/src/cli/commands/oauth/providers.ts +569 -62
- package/src/cli/commands/oauth/request.ts +36 -48
- package/src/cli/commands/oauth/shared.ts +1 -19
- package/src/cli/commands/oauth/status.ts +14 -25
- package/src/cli/commands/oauth/token.ts +25 -34
- package/src/cli/commands/platform/__tests__/connect.test.ts +224 -0
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +237 -0
- package/src/cli/commands/platform/__tests__/status.test.ts +246 -0
- package/src/cli/commands/platform/connect.ts +104 -0
- package/src/cli/commands/platform/disconnect.ts +118 -0
- package/src/cli/commands/{platform.ts → platform/index.ts} +108 -38
- package/src/cli/commands/sequence.ts +5 -4
- package/src/cli/commands/shotgun.ts +16 -0
- package/src/cli/commands/skills.ts +173 -41
- package/src/cli/commands/usage.ts +5 -11
- package/src/cli/lib/daemon-credential-client.ts +22 -38
- package/src/cli/program.ts +1 -1
- package/src/config/assistant-feature-flags.ts +3 -7
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +1 -1
- package/src/config/bundled-skills/conversations/SKILL.md +20 -0
- package/src/config/bundled-skills/conversations/TOOLS.json +23 -0
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +66 -0
- package/src/config/bundled-skills/gmail/SKILL.md +13 -13
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +3 -3
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +2 -2
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +2 -2
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +1 -1
- package/src/config/bundled-skills/google-calendar/SKILL.md +10 -4
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +7 -7
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +5 -6
- package/src/config/bundled-skills/settings/TOOLS.json +5 -3
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +4 -2
- package/src/config/bundled-tool-registry.ts +5 -0
- package/src/config/feature-flag-registry.json +2 -2
- package/src/credential-execution/client.ts +15 -3
- package/src/daemon/conversation-agent-loop.ts +2 -0
- package/src/daemon/conversation-error.ts +36 -6
- package/src/daemon/conversation-messaging.ts +9 -0
- package/src/daemon/conversation-runtime-assembly.ts +33 -0
- package/src/daemon/conversation-surfaces.ts +120 -14
- package/src/daemon/conversation.ts +5 -0
- package/src/daemon/first-greeting.ts +6 -1
- package/src/daemon/handlers/skills.ts +148 -3
- package/src/daemon/host-bash-proxy.ts +16 -0
- package/src/daemon/host-cu-proxy.ts +16 -0
- package/src/daemon/host-file-proxy.ts +16 -0
- package/src/daemon/lifecycle.ts +56 -5
- package/src/daemon/message-types/conversations.ts +1 -0
- package/src/daemon/message-types/guardian-actions.ts +2 -0
- package/src/daemon/message-types/host-bash.ts +6 -1
- package/src/daemon/message-types/host-cu.ts +6 -1
- package/src/daemon/message-types/host-file.ts +6 -1
- package/src/daemon/message-types/integrations.ts +0 -1
- package/src/daemon/server.ts +29 -2
- package/src/hooks/cli.ts +74 -0
- package/src/inbound/platform-callback-registration.ts +7 -12
- package/src/index.ts +0 -12
- package/src/mcp/client.ts +6 -1
- package/src/mcp/manager.ts +2 -1
- package/src/memory/conversation-crud.ts +92 -3
- package/src/memory/conversation-key-store.ts +26 -0
- package/src/memory/conversation-queries.ts +6 -6
- package/src/memory/db-init.ts +16 -0
- package/src/memory/journal-memory.ts +8 -2
- package/src/memory/migrations/196-messages-conversation-created-at-index.ts +9 -0
- package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +186 -0
- package/src/memory/migrations/197-oauth-providers-behavior-columns.ts +29 -0
- package/src/memory/migrations/198-drop-setup-skill-id-column.ts +11 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/oauth.ts +11 -0
- package/src/messaging/provider.ts +13 -12
- package/src/messaging/providers/gmail/adapter.ts +44 -35
- package/src/messaging/providers/slack/adapter.ts +63 -33
- package/src/messaging/providers/telegram-bot/adapter.ts +6 -8
- package/src/messaging/providers/whatsapp/adapter.ts +6 -8
- package/src/notifications/adapters/telegram.ts +78 -2
- package/src/oauth/__tests__/identity-verifier.test.ts +464 -0
- package/src/oauth/byo-connection.test.ts +22 -24
- package/src/oauth/connect-orchestrator.ts +37 -76
- package/src/oauth/connect-types.ts +7 -65
- package/src/oauth/connection-resolver.test.ts +13 -13
- package/src/oauth/connection-resolver.ts +3 -4
- package/src/oauth/identity-verifier.ts +177 -0
- package/src/oauth/oauth-store.ts +228 -3
- package/src/oauth/platform-connection.test.ts +56 -6
- package/src/oauth/platform-connection.ts +8 -1
- package/src/oauth/seed-providers.ts +247 -34
- package/src/permissions/checker.ts +127 -1
- package/src/prompts/journal-context.ts +4 -1
- package/src/prompts/system-prompt.ts +54 -9
- package/src/prompts/templates/BOOTSTRAP.md +16 -5
- package/src/providers/anthropic/client.ts +2 -33
- package/src/runtime/guardian-action-service.ts +7 -2
- package/src/runtime/http-server.ts +12 -18
- package/src/runtime/http-types.ts +8 -1
- package/src/runtime/migrations/rebind-secrets-screen.ts +2 -2
- package/src/runtime/routes/conversation-management-routes.ts +31 -0
- package/src/runtime/routes/conversation-routes.ts +79 -4
- package/src/runtime/routes/guardian-action-routes.ts +15 -2
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -8
- package/src/runtime/routes/integrations/slack/share.ts +1 -1
- package/src/runtime/routes/oauth-apps.ts +2 -1
- package/src/runtime/routes/secret-routes.ts +45 -15
- package/src/runtime/routes/settings-routes.ts +12 -19
- package/src/runtime/routes/skills-routes.ts +45 -4
- package/src/schedule/integration-status.ts +2 -2
- package/src/security/ces-rpc-credential-backend.ts +19 -16
- package/src/security/oauth-completion-page.ts +153 -0
- package/src/security/oauth2.ts +3 -17
- package/src/security/secure-keys.ts +207 -7
- package/src/security/token-manager.ts +3 -6
- package/src/signals/bash.ts +6 -1
- package/src/skills/catalog-cache.ts +44 -0
- package/src/skills/catalog-search.ts +18 -0
- package/src/tools/browser/browser-manager.ts +2 -2
- package/src/tools/credentials/post-connect-hooks.ts +1 -1
- package/src/tools/credentials/vault.ts +34 -45
- package/src/tools/host-terminal/host-shell.ts +16 -3
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/skills/sandbox-runner.ts +16 -3
- package/src/tools/terminal/shell.ts +16 -3
- package/src/util/logger.ts +11 -1
- package/src/util/platform.ts +1 -91
- package/src/util/sentry-log-stream.ts +51 -0
- package/src/watcher/providers/github.ts +2 -2
- package/src/watcher/providers/gmail.ts +1 -1
- package/src/watcher/providers/google-calendar.ts +1 -1
- package/src/watcher/providers/linear.ts +2 -2
- package/src/workspace/migrations/011-backfill-installation-id.ts +5 -3
- package/src/workspace/migrations/020-rename-oauth-skill-dirs.ts +119 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/cli/commands/oauth/connections.ts +0 -255
- package/src/oauth/provider-behaviors.ts +0 -634
|
@@ -7,16 +7,12 @@ import {
|
|
|
7
7
|
getProvider,
|
|
8
8
|
listActiveConnectionsByProvider,
|
|
9
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
10
|
import { getCliLogger } from "../../logger.js";
|
|
13
11
|
import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
14
12
|
import {
|
|
15
13
|
fetchActiveConnections,
|
|
16
14
|
isManagedMode,
|
|
17
15
|
requirePlatformClient,
|
|
18
|
-
resolveService,
|
|
19
|
-
toBareProvider,
|
|
20
16
|
} from "./shared.js";
|
|
21
17
|
|
|
22
18
|
const log = getCliLogger("cli");
|
|
@@ -29,7 +25,7 @@ export function registerDisconnectCommand(oauth: Command): void {
|
|
|
29
25
|
oauth
|
|
30
26
|
.command("disconnect <provider>")
|
|
31
27
|
.description(
|
|
32
|
-
"Disconnect an OAuth provider and remove associated credentials
|
|
28
|
+
"Disconnect an OAuth provider and remove associated credentials",
|
|
33
29
|
)
|
|
34
30
|
.option(
|
|
35
31
|
"--account <identifier>",
|
|
@@ -40,25 +36,14 @@ export function registerDisconnectCommand(oauth: Command): void {
|
|
|
40
36
|
"after",
|
|
41
37
|
`
|
|
42
38
|
Arguments:
|
|
43
|
-
provider Provider name
|
|
39
|
+
provider Provider name (e.g. google, slack, notion).
|
|
44
40
|
Run 'assistant oauth providers list' to see available providers.
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
|
|
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.
|
|
42
|
+
At most one of --account or --connection-id may be specified. Use the values
|
|
43
|
+
shown by 'assistant oauth status <provider>' to find the right identifier.
|
|
54
44
|
|
|
55
|
-
|
|
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.
|
|
45
|
+
When a provider has multiple active connections and neither flag is given,
|
|
46
|
+
the command errors with a list of connections and a hint to disambiguate.
|
|
62
47
|
|
|
63
48
|
Examples:
|
|
64
49
|
$ assistant oauth disconnect google
|
|
@@ -84,11 +69,9 @@ Examples:
|
|
|
84
69
|
|
|
85
70
|
try {
|
|
86
71
|
// -------------------------------------------------------------------
|
|
87
|
-
// 1.
|
|
72
|
+
// 1. Validate provider
|
|
88
73
|
// -------------------------------------------------------------------
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
const providerRow = getProvider(providerKey);
|
|
74
|
+
const providerRow = getProvider(provider);
|
|
92
75
|
if (!providerRow) {
|
|
93
76
|
writeError(
|
|
94
77
|
`Unknown provider "${provider}".\n\n` +
|
|
@@ -112,7 +95,7 @@ Examples:
|
|
|
112
95
|
// -------------------------------------------------------------------
|
|
113
96
|
// 3. Detect mode
|
|
114
97
|
// -------------------------------------------------------------------
|
|
115
|
-
const managed = isManagedMode(
|
|
98
|
+
const managed = isManagedMode(provider);
|
|
116
99
|
|
|
117
100
|
if (managed) {
|
|
118
101
|
// -----------------------------------------------------------------
|
|
@@ -121,11 +104,7 @@ Examples:
|
|
|
121
104
|
const client = await requirePlatformClient(cmd);
|
|
122
105
|
if (!client) return;
|
|
123
106
|
|
|
124
|
-
const entries = await fetchActiveConnections(
|
|
125
|
-
client,
|
|
126
|
-
providerKey,
|
|
127
|
-
cmd,
|
|
128
|
-
);
|
|
107
|
+
const entries = await fetchActiveConnections(client, provider, cmd);
|
|
129
108
|
if (!entries) return;
|
|
130
109
|
|
|
131
110
|
let connectionId: string | undefined;
|
|
@@ -138,7 +117,7 @@ Examples:
|
|
|
138
117
|
);
|
|
139
118
|
if (matching.length === 0) {
|
|
140
119
|
writeError(
|
|
141
|
-
`No active connection found for "${
|
|
120
|
+
`No active connection found for "${provider}" with account "${opts.account}".\n\n` +
|
|
142
121
|
`Run 'assistant oauth status ${provider}' to see connected accounts.`,
|
|
143
122
|
);
|
|
144
123
|
return;
|
|
@@ -150,7 +129,7 @@ Examples:
|
|
|
150
129
|
const match = entries.find((c) => c.id === opts.connectionId);
|
|
151
130
|
if (!match) {
|
|
152
131
|
writeError(
|
|
153
|
-
`Connection "${opts.connectionId}" is not an active ${
|
|
132
|
+
`Connection "${opts.connectionId}" is not an active ${provider} connection.\n\n` +
|
|
154
133
|
`Run 'assistant oauth status ${provider}' to see active connections.`,
|
|
155
134
|
);
|
|
156
135
|
return;
|
|
@@ -161,7 +140,7 @@ Examples:
|
|
|
161
140
|
// Neither specified — auto-resolve
|
|
162
141
|
if (entries.length === 0) {
|
|
163
142
|
writeError(
|
|
164
|
-
`No active connections found for "${
|
|
143
|
+
`No active connections found for "${provider}".\n\n` +
|
|
165
144
|
`Run 'assistant oauth status ${provider}' to check connection status.`,
|
|
166
145
|
);
|
|
167
146
|
return;
|
|
@@ -173,7 +152,7 @@ Examples:
|
|
|
173
152
|
account: c.account_label ?? null,
|
|
174
153
|
}));
|
|
175
154
|
writeError(
|
|
176
|
-
`Multiple active connections for "${
|
|
155
|
+
`Multiple active connections for "${provider}". ` +
|
|
177
156
|
`Specify which one to disconnect with --account or --connection-id.\n\n` +
|
|
178
157
|
`Run 'assistant oauth status ${provider}' to see connected accounts and IDs.`,
|
|
179
158
|
{ connections: connectionList },
|
|
@@ -202,16 +181,14 @@ Examples:
|
|
|
202
181
|
|
|
203
182
|
const result: Record<string, unknown> = {
|
|
204
183
|
ok: true,
|
|
205
|
-
provider:
|
|
184
|
+
provider: provider,
|
|
206
185
|
connectionId,
|
|
207
186
|
};
|
|
208
187
|
if (accountLabel) result.account = accountLabel;
|
|
209
188
|
writeOutput(cmd, result);
|
|
210
189
|
|
|
211
190
|
if (!jsonMode) {
|
|
212
|
-
log.info(
|
|
213
|
-
`Disconnected ${providerKey} connection ${connectionId}`,
|
|
214
|
-
);
|
|
191
|
+
log.info(`Disconnected ${provider} connection ${connectionId}`);
|
|
215
192
|
}
|
|
216
193
|
} else {
|
|
217
194
|
// -----------------------------------------------------------------
|
|
@@ -221,12 +198,12 @@ Examples:
|
|
|
221
198
|
let accountLabel: string | undefined;
|
|
222
199
|
|
|
223
200
|
if (opts.account) {
|
|
224
|
-
const conn = getActiveConnection(
|
|
201
|
+
const conn = getActiveConnection(provider, {
|
|
225
202
|
account: opts.account,
|
|
226
203
|
});
|
|
227
204
|
if (!conn) {
|
|
228
205
|
writeError(
|
|
229
|
-
`No active connection found for "${
|
|
206
|
+
`No active connection found for "${provider}" with account "${opts.account}".\n\n` +
|
|
230
207
|
`Run 'assistant oauth status ${provider}' to see connected accounts.`,
|
|
231
208
|
);
|
|
232
209
|
return;
|
|
@@ -235,9 +212,9 @@ Examples:
|
|
|
235
212
|
accountLabel = conn.accountInfo ?? undefined;
|
|
236
213
|
} else if (opts.connectionId) {
|
|
237
214
|
const conn = getConnection(opts.connectionId);
|
|
238
|
-
if (!conn || conn.providerKey !==
|
|
215
|
+
if (!conn || conn.providerKey !== provider) {
|
|
239
216
|
writeError(
|
|
240
|
-
`Connection "${opts.connectionId}" is not an active ${
|
|
217
|
+
`Connection "${opts.connectionId}" is not an active ${provider} connection.\n\n` +
|
|
241
218
|
`Run 'assistant oauth status ${provider}' to see active connections.`,
|
|
242
219
|
);
|
|
243
220
|
return;
|
|
@@ -246,11 +223,11 @@ Examples:
|
|
|
246
223
|
accountLabel = conn.accountInfo ?? undefined;
|
|
247
224
|
} else {
|
|
248
225
|
// Neither specified — auto-resolve
|
|
249
|
-
const active = listActiveConnectionsByProvider(
|
|
226
|
+
const active = listActiveConnectionsByProvider(provider);
|
|
250
227
|
|
|
251
228
|
if (active.length === 0) {
|
|
252
229
|
writeError(
|
|
253
|
-
`No active connections found for "${
|
|
230
|
+
`No active connections found for "${provider}".\n\n` +
|
|
254
231
|
`Run 'assistant oauth status ${provider}' to check connection status.`,
|
|
255
232
|
);
|
|
256
233
|
return;
|
|
@@ -262,7 +239,7 @@ Examples:
|
|
|
262
239
|
account: c.accountInfo ?? null,
|
|
263
240
|
}));
|
|
264
241
|
writeError(
|
|
265
|
-
`Multiple active connections for "${
|
|
242
|
+
`Multiple active connections for "${provider}". ` +
|
|
266
243
|
`Specify which one to disconnect with --account or --connection-id.\n\n` +
|
|
267
244
|
`Run 'assistant oauth status ${provider}' to see connected accounts and IDs.`,
|
|
268
245
|
{ connections: connectionList },
|
|
@@ -276,52 +253,27 @@ Examples:
|
|
|
276
253
|
|
|
277
254
|
// Disconnect the OAuth connection (tokens + connection row)
|
|
278
255
|
const oauthResult = await disconnectOAuthProvider(
|
|
279
|
-
|
|
256
|
+
provider,
|
|
280
257
|
undefined,
|
|
281
258
|
connectionId,
|
|
282
259
|
);
|
|
283
260
|
if (oauthResult === "error") {
|
|
284
261
|
writeError(
|
|
285
|
-
`Failed to disconnect OAuth provider "${
|
|
262
|
+
`Failed to disconnect OAuth provider "${provider}" — please try again.`,
|
|
286
263
|
);
|
|
287
264
|
return;
|
|
288
265
|
}
|
|
289
266
|
|
|
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
267
|
const result: Record<string, unknown> = {
|
|
314
268
|
ok: true,
|
|
315
|
-
provider:
|
|
269
|
+
provider: provider,
|
|
316
270
|
connectionId,
|
|
317
271
|
};
|
|
318
272
|
if (accountLabel) result.account = accountLabel;
|
|
319
273
|
writeOutput(cmd, result);
|
|
320
274
|
|
|
321
275
|
if (!jsonMode) {
|
|
322
|
-
log.info(
|
|
323
|
-
`Disconnected ${providerKey} connection ${connectionId}`,
|
|
324
|
-
);
|
|
276
|
+
log.info(`Disconnected ${provider} connection ${connectionId}`);
|
|
325
277
|
}
|
|
326
278
|
}
|
|
327
279
|
} catch (err) {
|
|
@@ -2,7 +2,6 @@ import type { Command } from "commander";
|
|
|
2
2
|
|
|
3
3
|
import { registerAppCommands } from "./apps.js";
|
|
4
4
|
import { registerConnectCommand } from "./connect.js";
|
|
5
|
-
import { registerConnectionCommands } from "./connections.js";
|
|
6
5
|
import { registerDisconnectCommand } from "./disconnect.js";
|
|
7
6
|
import { registerModeCommand } from "./mode.js";
|
|
8
7
|
import { registerPingCommand } from "./ping.js";
|
|
@@ -14,39 +13,36 @@ import { registerTokenCommand } from "./token.js";
|
|
|
14
13
|
export function registerOAuthCommand(program: Command): void {
|
|
15
14
|
const oauth = program
|
|
16
15
|
.command("oauth")
|
|
17
|
-
.description(
|
|
16
|
+
.description(
|
|
17
|
+
"Manage the full OAuth lifecycle — registering providers, creating apps, connecting accounts, and making authenticated requests",
|
|
18
|
+
)
|
|
18
19
|
.option("--json", "Machine-readable compact JSON output");
|
|
19
20
|
|
|
20
21
|
oauth.addHelpText(
|
|
21
22
|
"after",
|
|
22
23
|
`
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Providers are seeded on startup for built-in integrations. Apps and connections
|
|
37
|
-
are created during the OAuth authorization flow or can be managed manually via
|
|
38
|
-
their respective subcommands.
|
|
24
|
+
OAuth providers may support up to two modes – "managed" and "your-own".
|
|
25
|
+
managed:
|
|
26
|
+
Requires a Vellum Platform account. For providers that support it, managed mode offloads the burden of needing to create and register an oauth app.
|
|
27
|
+
Vellum Platform manages oauth token management and refresh and proxies requests to the provier.
|
|
28
|
+
you-own:
|
|
29
|
+
Provides ultimate control and removes dependency on Vellum Platform, but requires that you set up your own oauth app and register it
|
|
30
|
+
via \`assistant oauth apps upsert\`.
|
|
31
|
+
All commands are intended to work regardless of the provider's mode. Check and set the mode for a given provider with \`assistant oauth mode\`.
|
|
32
|
+
|
|
33
|
+
You can define entirely new oauth providers to integrate with even if they do not show up using \`assistant oauth providers list\` using
|
|
34
|
+
\`assistant oauth providers register\`. Custom-registered providers only support "your-own" mode.
|
|
35
|
+
|
|
39
36
|
|
|
40
37
|
Examples:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
$ assistant oauth providers get integration:google`,
|
|
38
|
+
assistant oauth providers list
|
|
39
|
+
assistant oauth providers get google
|
|
40
|
+
assistant oauth mode google --set=managed
|
|
41
|
+
assistant oauth connect google --open-browser
|
|
42
|
+
assistant oauth status google
|
|
43
|
+
assistant oauth ping google
|
|
44
|
+
assistant oauth request --provider google /gmail/v1/users/me/messages
|
|
45
|
+
assistant oauth disconnect google`,
|
|
50
46
|
);
|
|
51
47
|
|
|
52
48
|
// ---------------------------------------------------------------------------
|
|
@@ -56,22 +52,16 @@ Examples:
|
|
|
56
52
|
registerProviderCommands(oauth);
|
|
57
53
|
|
|
58
54
|
// ---------------------------------------------------------------------------
|
|
59
|
-
//
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
|
|
62
|
-
registerAppCommands(oauth);
|
|
63
|
-
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
|
-
// connections — subcommand group (list, get)
|
|
55
|
+
// mode — get or set OAuth mode (managed vs your-own) for a provider
|
|
66
56
|
// ---------------------------------------------------------------------------
|
|
67
57
|
|
|
68
|
-
|
|
58
|
+
registerModeCommand(oauth);
|
|
69
59
|
|
|
70
60
|
// ---------------------------------------------------------------------------
|
|
71
|
-
//
|
|
61
|
+
// apps — subcommand group
|
|
72
62
|
// ---------------------------------------------------------------------------
|
|
73
63
|
|
|
74
|
-
|
|
64
|
+
registerAppCommands(oauth);
|
|
75
65
|
|
|
76
66
|
// ---------------------------------------------------------------------------
|
|
77
67
|
// connect — unified connect command (auto-detects managed vs BYO)
|
|
@@ -80,31 +70,31 @@ Examples:
|
|
|
80
70
|
registerConnectCommand(oauth);
|
|
81
71
|
|
|
82
72
|
// ---------------------------------------------------------------------------
|
|
83
|
-
//
|
|
73
|
+
// status — unified connection status
|
|
84
74
|
// ---------------------------------------------------------------------------
|
|
85
75
|
|
|
86
|
-
|
|
76
|
+
registerStatusCommand(oauth);
|
|
87
77
|
|
|
88
78
|
// ---------------------------------------------------------------------------
|
|
89
|
-
//
|
|
79
|
+
// ping — ping to see if a provider is connected and healthy
|
|
90
80
|
// ---------------------------------------------------------------------------
|
|
91
81
|
|
|
92
|
-
|
|
82
|
+
registerPingCommand(oauth);
|
|
93
83
|
|
|
94
84
|
// ---------------------------------------------------------------------------
|
|
95
|
-
//
|
|
85
|
+
// request — curl-like authenticated request command
|
|
96
86
|
// ---------------------------------------------------------------------------
|
|
97
87
|
|
|
98
|
-
|
|
88
|
+
registerRequestCommand(oauth);
|
|
99
89
|
|
|
100
90
|
// ---------------------------------------------------------------------------
|
|
101
|
-
//
|
|
91
|
+
// disconnect — unified disconnect with auto-detected managed/BYO routing
|
|
102
92
|
// ---------------------------------------------------------------------------
|
|
103
93
|
|
|
104
|
-
|
|
94
|
+
registerDisconnectCommand(oauth);
|
|
105
95
|
|
|
106
96
|
// ---------------------------------------------------------------------------
|
|
107
|
-
// token —
|
|
97
|
+
// token — retrieve a valid oauth token (your-own mode only)
|
|
108
98
|
// ---------------------------------------------------------------------------
|
|
109
99
|
|
|
110
100
|
registerTokenCommand(oauth);
|
|
@@ -17,8 +17,6 @@ import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
|
17
17
|
import {
|
|
18
18
|
fetchActiveConnections,
|
|
19
19
|
getManagedServiceConfigKey,
|
|
20
|
-
resolveService,
|
|
21
|
-
toBareProvider,
|
|
22
20
|
} from "./shared.js";
|
|
23
21
|
|
|
24
22
|
/**
|
|
@@ -30,13 +28,13 @@ import {
|
|
|
30
28
|
* command output or set a non-zero exit code.
|
|
31
29
|
*/
|
|
32
30
|
async function countManagedConnections(
|
|
33
|
-
|
|
31
|
+
provider: string,
|
|
34
32
|
cmd: Command,
|
|
35
33
|
): Promise<number> {
|
|
36
34
|
try {
|
|
37
35
|
const client = await VellumPlatformClient.create();
|
|
38
36
|
if (!client || !client.platformAssistantId) return 0;
|
|
39
|
-
const entries = await fetchActiveConnections(client,
|
|
37
|
+
const entries = await fetchActiveConnections(client, provider, cmd, {
|
|
40
38
|
silent: true,
|
|
41
39
|
});
|
|
42
40
|
return entries?.length ?? 0;
|
|
@@ -63,14 +61,9 @@ export function registerModeCommand(oauth: Command): void {
|
|
|
63
61
|
"after",
|
|
64
62
|
`
|
|
65
63
|
Arguments:
|
|
66
|
-
provider Provider
|
|
64
|
+
provider Provider name (e.g. google, slack).
|
|
67
65
|
Run "assistant oauth providers list" to see available providers.
|
|
68
66
|
|
|
69
|
-
Options:
|
|
70
|
-
--set <mode> Set the mode to "managed" (platform-handled credentials) or
|
|
71
|
-
"your-own" (bring-your-own client ID and secret). Omit to
|
|
72
|
-
show the current mode.
|
|
73
|
-
|
|
74
67
|
Modes:
|
|
75
68
|
managed OAuth credentials are managed by the Vellum platform. The
|
|
76
69
|
assistant connects via a platform-hosted authorization flow.
|
|
@@ -86,10 +79,9 @@ Examples:
|
|
|
86
79
|
.action(async (provider: string, opts: { set?: string }, cmd: Command) => {
|
|
87
80
|
try {
|
|
88
81
|
// -----------------------------------------------------------------
|
|
89
|
-
//
|
|
82
|
+
// Validate provider
|
|
90
83
|
// -----------------------------------------------------------------
|
|
91
|
-
const
|
|
92
|
-
const providerRow = getProvider(providerKey);
|
|
84
|
+
const providerRow = getProvider(provider);
|
|
93
85
|
|
|
94
86
|
if (!providerRow) {
|
|
95
87
|
writeOutput(cmd, {
|
|
@@ -102,7 +94,7 @@ Examples:
|
|
|
102
94
|
return;
|
|
103
95
|
}
|
|
104
96
|
|
|
105
|
-
const managedKey = getManagedServiceConfigKey(
|
|
97
|
+
const managedKey = getManagedServiceConfigKey(provider);
|
|
106
98
|
|
|
107
99
|
// -----------------------------------------------------------------
|
|
108
100
|
// GET mode (no --set flag)
|
|
@@ -113,13 +105,13 @@ Examples:
|
|
|
113
105
|
if (shouldOutputJson(cmd)) {
|
|
114
106
|
writeOutput(cmd, {
|
|
115
107
|
ok: true,
|
|
116
|
-
provider:
|
|
108
|
+
provider: provider,
|
|
117
109
|
mode: "your-own",
|
|
118
110
|
managedModeSupported: false,
|
|
119
111
|
});
|
|
120
112
|
} else {
|
|
121
113
|
log.info(
|
|
122
|
-
`${
|
|
114
|
+
`${provider} mode: your-own (managed mode not available for this provider)`,
|
|
123
115
|
);
|
|
124
116
|
}
|
|
125
117
|
return;
|
|
@@ -132,12 +124,12 @@ Examples:
|
|
|
132
124
|
if (shouldOutputJson(cmd)) {
|
|
133
125
|
writeOutput(cmd, {
|
|
134
126
|
ok: true,
|
|
135
|
-
provider:
|
|
127
|
+
provider: provider,
|
|
136
128
|
mode: currentMode,
|
|
137
129
|
managedModeSupported: true,
|
|
138
130
|
});
|
|
139
131
|
} else {
|
|
140
|
-
log.info(`${
|
|
132
|
+
log.info(`${provider} mode: ${currentMode}`);
|
|
141
133
|
}
|
|
142
134
|
return;
|
|
143
135
|
}
|
|
@@ -164,14 +156,14 @@ Examples:
|
|
|
164
156
|
if (shouldOutputJson(cmd)) {
|
|
165
157
|
writeOutput(cmd, {
|
|
166
158
|
ok: true,
|
|
167
|
-
provider:
|
|
159
|
+
provider: provider,
|
|
168
160
|
mode: "your-own",
|
|
169
161
|
changed: false,
|
|
170
162
|
managedModeSupported: false,
|
|
171
163
|
});
|
|
172
164
|
} else {
|
|
173
165
|
log.info(
|
|
174
|
-
`${
|
|
166
|
+
`${provider} is already set to your-own (managed mode not available for this provider)`,
|
|
175
167
|
);
|
|
176
168
|
}
|
|
177
169
|
return;
|
|
@@ -181,7 +173,7 @@ Examples:
|
|
|
181
173
|
writeOutput(cmd, {
|
|
182
174
|
ok: false,
|
|
183
175
|
error:
|
|
184
|
-
`Managed mode is not available for ${
|
|
176
|
+
`Managed mode is not available for ${provider}. ` +
|
|
185
177
|
`Only providers with platform-managed OAuth support can be switched to managed mode.`,
|
|
186
178
|
});
|
|
187
179
|
process.exitCode = 1;
|
|
@@ -197,13 +189,13 @@ Examples:
|
|
|
197
189
|
if (shouldOutputJson(cmd)) {
|
|
198
190
|
writeOutput(cmd, {
|
|
199
191
|
ok: true,
|
|
200
|
-
provider:
|
|
192
|
+
provider: provider,
|
|
201
193
|
mode: newMode,
|
|
202
194
|
changed: false,
|
|
203
195
|
managedModeSupported: true,
|
|
204
196
|
});
|
|
205
197
|
} else {
|
|
206
|
-
log.info(`${
|
|
198
|
+
log.info(`${provider} is already set to ${newMode}`);
|
|
207
199
|
}
|
|
208
200
|
return;
|
|
209
201
|
}
|
|
@@ -216,32 +208,28 @@ Examples:
|
|
|
216
208
|
// Best-effort check for active connections on old and new modes
|
|
217
209
|
let oldModeConnections = 0;
|
|
218
210
|
let newModeConnections = 0;
|
|
219
|
-
const bareProvider = toBareProvider(providerKey);
|
|
220
|
-
|
|
221
211
|
if (currentMode === "managed") {
|
|
222
212
|
// Old mode was managed — check platform connections
|
|
223
|
-
oldModeConnections = await countManagedConnections(
|
|
213
|
+
oldModeConnections = await countManagedConnections(provider, cmd);
|
|
224
214
|
// New mode is your-own — check local connections
|
|
225
|
-
newModeConnections =
|
|
226
|
-
listActiveConnectionsByProvider(providerKey).length;
|
|
215
|
+
newModeConnections = listActiveConnectionsByProvider(provider).length;
|
|
227
216
|
} else {
|
|
228
217
|
// Old mode was your-own — check local connections
|
|
229
|
-
oldModeConnections =
|
|
230
|
-
listActiveConnectionsByProvider(providerKey).length;
|
|
218
|
+
oldModeConnections = listActiveConnectionsByProvider(provider).length;
|
|
231
219
|
// New mode is managed — check platform connections
|
|
232
|
-
newModeConnections = await countManagedConnections(
|
|
220
|
+
newModeConnections = await countManagedConnections(provider, cmd);
|
|
233
221
|
}
|
|
234
222
|
|
|
235
223
|
// Build hint if there are connections on the old mode but none on the new
|
|
236
224
|
let hint: string | undefined;
|
|
237
225
|
if (oldModeConnections > 0 && newModeConnections === 0) {
|
|
238
|
-
hint = `No active connections in ${newMode} mode. Run 'assistant oauth connect ${
|
|
226
|
+
hint = `No active connections in ${newMode} mode. Run 'assistant oauth connect ${provider}' to connect.`;
|
|
239
227
|
}
|
|
240
228
|
|
|
241
229
|
if (shouldOutputJson(cmd)) {
|
|
242
230
|
const result: Record<string, unknown> = {
|
|
243
231
|
ok: true,
|
|
244
|
-
provider:
|
|
232
|
+
provider: provider,
|
|
245
233
|
mode: newMode,
|
|
246
234
|
changed: true,
|
|
247
235
|
managedModeSupported: true,
|
|
@@ -249,7 +237,7 @@ Examples:
|
|
|
249
237
|
if (hint) result.hint = hint;
|
|
250
238
|
writeOutput(cmd, result);
|
|
251
239
|
} else {
|
|
252
|
-
log.info(`${
|
|
240
|
+
log.info(`${provider} mode changed to ${newMode}`);
|
|
253
241
|
if (hint) {
|
|
254
242
|
process.stderr.write(hint + "\n");
|
|
255
243
|
}
|