@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
|
@@ -89,20 +89,6 @@ mock.module("../../../../oauth/oauth-store.js", () => ({
|
|
|
89
89
|
deleteConnection: () => false,
|
|
90
90
|
}));
|
|
91
91
|
|
|
92
|
-
mock.module("../../../../oauth/provider-behaviors.js", () => ({
|
|
93
|
-
resolveService: (service: string) => {
|
|
94
|
-
const aliases: Record<string, string> = {
|
|
95
|
-
gmail: "integration:google",
|
|
96
|
-
google: "integration:google",
|
|
97
|
-
slack: "integration:slack",
|
|
98
|
-
};
|
|
99
|
-
if (aliases[service]) return aliases[service];
|
|
100
|
-
if (!service.includes(":")) return `integration:${service}`;
|
|
101
|
-
return service;
|
|
102
|
-
},
|
|
103
|
-
getProviderBehavior: () => undefined,
|
|
104
|
-
}));
|
|
105
|
-
|
|
106
92
|
mock.module("../../../../platform/client.js", () => ({
|
|
107
93
|
VellumPlatformClient: {
|
|
108
94
|
create: async () => mockPlatformClientResult,
|
|
@@ -131,16 +117,6 @@ mock.module("../../../lib/daemon-credential-client.js", () => ({
|
|
|
131
117
|
|
|
132
118
|
// Mock shared.js helpers
|
|
133
119
|
mock.module("../shared.js", () => ({
|
|
134
|
-
resolveService: (service: string) => {
|
|
135
|
-
const aliases: Record<string, string> = {
|
|
136
|
-
gmail: "integration:google",
|
|
137
|
-
google: "integration:google",
|
|
138
|
-
slack: "integration:slack",
|
|
139
|
-
};
|
|
140
|
-
if (aliases[service]) return aliases[service];
|
|
141
|
-
if (!service.includes(":")) return `integration:${service}`;
|
|
142
|
-
return service;
|
|
143
|
-
},
|
|
144
120
|
isManagedMode: () => false,
|
|
145
121
|
getManagedServiceConfigKey: (key: string) =>
|
|
146
122
|
mockGetManagedServiceConfigKey(key),
|
|
@@ -193,10 +169,6 @@ mock.module("../shared.js", () => ({
|
|
|
193
169
|
if (!result.ok) return null;
|
|
194
170
|
return result.body as Array<Record<string, unknown>>;
|
|
195
171
|
},
|
|
196
|
-
toBareProvider: (provider: string): string =>
|
|
197
|
-
provider.startsWith("integration:")
|
|
198
|
-
? provider.slice("integration:".length)
|
|
199
|
-
: provider,
|
|
200
172
|
}));
|
|
201
173
|
|
|
202
174
|
// ---------------------------------------------------------------------------
|
|
@@ -295,28 +267,9 @@ describe("assistant oauth mode", () => {
|
|
|
295
267
|
expect(parsed.error).toContain("providers list");
|
|
296
268
|
});
|
|
297
269
|
|
|
298
|
-
test("provider alias resolution: gmail resolves to integration:google", async () => {
|
|
299
|
-
let capturedProviderKey: string | undefined;
|
|
300
|
-
|
|
301
|
-
mockGetProvider = (key: string) => {
|
|
302
|
-
capturedProviderKey = key;
|
|
303
|
-
return {
|
|
304
|
-
providerKey: key,
|
|
305
|
-
managedServiceConfigKey: "google-oauth",
|
|
306
|
-
};
|
|
307
|
-
};
|
|
308
|
-
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
309
|
-
mockConfigServices = {
|
|
310
|
-
"google-oauth": { mode: "managed" },
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
await runCommand(["mode", "gmail", "--json"]);
|
|
314
|
-
expect(capturedProviderKey).toBe("integration:google");
|
|
315
|
-
});
|
|
316
|
-
|
|
317
270
|
test("provider without managedServiceConfigKey returns your-own with managedModeSupported: false", async () => {
|
|
318
271
|
mockGetProvider = () => ({
|
|
319
|
-
providerKey: "
|
|
272
|
+
providerKey: "slack",
|
|
320
273
|
managedServiceConfigKey: null,
|
|
321
274
|
});
|
|
322
275
|
mockGetManagedServiceConfigKey = () => null;
|
|
@@ -329,14 +282,14 @@ describe("assistant oauth mode", () => {
|
|
|
329
282
|
expect(exitCode).toBe(0);
|
|
330
283
|
const parsed = JSON.parse(stdout);
|
|
331
284
|
expect(parsed.ok).toBe(true);
|
|
332
|
-
expect(parsed.provider).toBe("
|
|
285
|
+
expect(parsed.provider).toBe("slack");
|
|
333
286
|
expect(parsed.mode).toBe("your-own");
|
|
334
287
|
expect(parsed.managedModeSupported).toBe(false);
|
|
335
288
|
});
|
|
336
289
|
|
|
337
290
|
test("provider in managed mode returns mode: managed with managedModeSupported: true", async () => {
|
|
338
291
|
mockGetProvider = () => ({
|
|
339
|
-
providerKey: "
|
|
292
|
+
providerKey: "google",
|
|
340
293
|
managedServiceConfigKey: "google-oauth",
|
|
341
294
|
});
|
|
342
295
|
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
@@ -352,14 +305,14 @@ describe("assistant oauth mode", () => {
|
|
|
352
305
|
expect(exitCode).toBe(0);
|
|
353
306
|
const parsed = JSON.parse(stdout);
|
|
354
307
|
expect(parsed.ok).toBe(true);
|
|
355
|
-
expect(parsed.provider).toBe("
|
|
308
|
+
expect(parsed.provider).toBe("google");
|
|
356
309
|
expect(parsed.mode).toBe("managed");
|
|
357
310
|
expect(parsed.managedModeSupported).toBe(true);
|
|
358
311
|
});
|
|
359
312
|
|
|
360
313
|
test("provider in your-own mode returns mode: your-own with managedModeSupported: true", async () => {
|
|
361
314
|
mockGetProvider = () => ({
|
|
362
|
-
providerKey: "
|
|
315
|
+
providerKey: "google",
|
|
363
316
|
managedServiceConfigKey: "google-oauth",
|
|
364
317
|
});
|
|
365
318
|
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
@@ -375,7 +328,7 @@ describe("assistant oauth mode", () => {
|
|
|
375
328
|
expect(exitCode).toBe(0);
|
|
376
329
|
const parsed = JSON.parse(stdout);
|
|
377
330
|
expect(parsed.ok).toBe(true);
|
|
378
|
-
expect(parsed.provider).toBe("
|
|
331
|
+
expect(parsed.provider).toBe("google");
|
|
379
332
|
expect(parsed.mode).toBe("your-own");
|
|
380
333
|
expect(parsed.managedModeSupported).toBe(true);
|
|
381
334
|
});
|
|
@@ -388,7 +341,7 @@ describe("assistant oauth mode", () => {
|
|
|
388
341
|
describe("set mode", () => {
|
|
389
342
|
test("invalid mode value returns error listing valid values", async () => {
|
|
390
343
|
mockGetProvider = () => ({
|
|
391
|
-
providerKey: "
|
|
344
|
+
providerKey: "google",
|
|
392
345
|
managedServiceConfigKey: "google-oauth",
|
|
393
346
|
});
|
|
394
347
|
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
@@ -410,7 +363,7 @@ describe("assistant oauth mode", () => {
|
|
|
410
363
|
|
|
411
364
|
test("provider without managedServiceConfigKey returns error about managed mode not available when --set managed", async () => {
|
|
412
365
|
mockGetProvider = () => ({
|
|
413
|
-
providerKey: "
|
|
366
|
+
providerKey: "slack",
|
|
414
367
|
managedServiceConfigKey: null,
|
|
415
368
|
});
|
|
416
369
|
mockGetManagedServiceConfigKey = () => null;
|
|
@@ -426,12 +379,12 @@ describe("assistant oauth mode", () => {
|
|
|
426
379
|
const parsed = JSON.parse(stdout);
|
|
427
380
|
expect(parsed.ok).toBe(false);
|
|
428
381
|
expect(parsed.error).toContain("Managed mode is not available");
|
|
429
|
-
expect(parsed.error).toContain("
|
|
382
|
+
expect(parsed.error).toContain("slack");
|
|
430
383
|
});
|
|
431
384
|
|
|
432
385
|
test("provider without managedServiceConfigKey treats --set your-own as successful no-op", async () => {
|
|
433
386
|
mockGetProvider = () => ({
|
|
434
|
-
providerKey: "
|
|
387
|
+
providerKey: "slack",
|
|
435
388
|
managedServiceConfigKey: null,
|
|
436
389
|
});
|
|
437
390
|
mockGetManagedServiceConfigKey = () => null;
|
|
@@ -446,7 +399,7 @@ describe("assistant oauth mode", () => {
|
|
|
446
399
|
expect(exitCode).toBe(0);
|
|
447
400
|
const parsed = JSON.parse(stdout);
|
|
448
401
|
expect(parsed.ok).toBe(true);
|
|
449
|
-
expect(parsed.provider).toBe("
|
|
402
|
+
expect(parsed.provider).toBe("slack");
|
|
450
403
|
expect(parsed.mode).toBe("your-own");
|
|
451
404
|
expect(parsed.changed).toBe(false);
|
|
452
405
|
expect(parsed.managedModeSupported).toBe(false);
|
|
@@ -454,7 +407,7 @@ describe("assistant oauth mode", () => {
|
|
|
454
407
|
|
|
455
408
|
test("set to same mode returns changed: false", async () => {
|
|
456
409
|
mockGetProvider = () => ({
|
|
457
|
-
providerKey: "
|
|
410
|
+
providerKey: "google",
|
|
458
411
|
managedServiceConfigKey: "google-oauth",
|
|
459
412
|
});
|
|
460
413
|
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
@@ -472,7 +425,7 @@ describe("assistant oauth mode", () => {
|
|
|
472
425
|
expect(exitCode).toBe(0);
|
|
473
426
|
const parsed = JSON.parse(stdout);
|
|
474
427
|
expect(parsed.ok).toBe(true);
|
|
475
|
-
expect(parsed.provider).toBe("
|
|
428
|
+
expect(parsed.provider).toBe("google");
|
|
476
429
|
expect(parsed.mode).toBe("managed");
|
|
477
430
|
expect(parsed.changed).toBe(false);
|
|
478
431
|
expect(parsed.managedModeSupported).toBe(true);
|
|
@@ -480,7 +433,7 @@ describe("assistant oauth mode", () => {
|
|
|
480
433
|
|
|
481
434
|
test("switch managed -> your-own with active managed connections and no BYO connections includes hint", async () => {
|
|
482
435
|
mockGetProvider = () => ({
|
|
483
|
-
providerKey: "
|
|
436
|
+
providerKey: "google",
|
|
484
437
|
managedServiceConfigKey: "google-oauth",
|
|
485
438
|
});
|
|
486
439
|
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
@@ -512,7 +465,7 @@ describe("assistant oauth mode", () => {
|
|
|
512
465
|
expect(exitCode).toBe(0);
|
|
513
466
|
const parsed = JSON.parse(stdout);
|
|
514
467
|
expect(parsed.ok).toBe(true);
|
|
515
|
-
expect(parsed.provider).toBe("
|
|
468
|
+
expect(parsed.provider).toBe("google");
|
|
516
469
|
expect(parsed.mode).toBe("your-own");
|
|
517
470
|
expect(parsed.changed).toBe(true);
|
|
518
471
|
expect(parsed.managedModeSupported).toBe(true);
|
|
@@ -523,7 +476,7 @@ describe("assistant oauth mode", () => {
|
|
|
523
476
|
|
|
524
477
|
test("switch your-own -> managed with active BYO connections and no managed connections includes hint", async () => {
|
|
525
478
|
mockGetProvider = () => ({
|
|
526
|
-
providerKey: "
|
|
479
|
+
providerKey: "google",
|
|
527
480
|
managedServiceConfigKey: "google-oauth",
|
|
528
481
|
});
|
|
529
482
|
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
@@ -536,7 +489,7 @@ describe("assistant oauth mode", () => {
|
|
|
536
489
|
mockListActiveConnectionsByProvider = () => [
|
|
537
490
|
{
|
|
538
491
|
id: "conn-local-1",
|
|
539
|
-
providerKey: "
|
|
492
|
+
providerKey: "google",
|
|
540
493
|
status: "active",
|
|
541
494
|
},
|
|
542
495
|
];
|
|
@@ -555,7 +508,7 @@ describe("assistant oauth mode", () => {
|
|
|
555
508
|
expect(exitCode).toBe(0);
|
|
556
509
|
const parsed = JSON.parse(stdout);
|
|
557
510
|
expect(parsed.ok).toBe(true);
|
|
558
|
-
expect(parsed.provider).toBe("
|
|
511
|
+
expect(parsed.provider).toBe("google");
|
|
559
512
|
expect(parsed.mode).toBe("managed");
|
|
560
513
|
expect(parsed.changed).toBe(true);
|
|
561
514
|
expect(parsed.managedModeSupported).toBe(true);
|
|
@@ -566,7 +519,7 @@ describe("assistant oauth mode", () => {
|
|
|
566
519
|
|
|
567
520
|
test("switch mode with connections on both sides has no hint", async () => {
|
|
568
521
|
mockGetProvider = () => ({
|
|
569
|
-
providerKey: "
|
|
522
|
+
providerKey: "google",
|
|
570
523
|
managedServiceConfigKey: "google-oauth",
|
|
571
524
|
});
|
|
572
525
|
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
@@ -589,7 +542,7 @@ describe("assistant oauth mode", () => {
|
|
|
589
542
|
mockListActiveConnectionsByProvider = () => [
|
|
590
543
|
{
|
|
591
544
|
id: "conn-local-1",
|
|
592
|
-
providerKey: "
|
|
545
|
+
providerKey: "google",
|
|
593
546
|
status: "active",
|
|
594
547
|
},
|
|
595
548
|
];
|
|
@@ -611,7 +564,7 @@ describe("assistant oauth mode", () => {
|
|
|
611
564
|
|
|
612
565
|
test("switch mode with no connections on either side has no hint", async () => {
|
|
613
566
|
mockGetProvider = () => ({
|
|
614
|
-
providerKey: "
|
|
567
|
+
providerKey: "google",
|
|
615
568
|
managedServiceConfigKey: "google-oauth",
|
|
616
569
|
});
|
|
617
570
|
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
@@ -644,7 +597,7 @@ describe("assistant oauth mode", () => {
|
|
|
644
597
|
|
|
645
598
|
test("saveRawConfig is called with the correct nested path", async () => {
|
|
646
599
|
mockGetProvider = () => ({
|
|
647
|
-
providerKey: "
|
|
600
|
+
providerKey: "google",
|
|
648
601
|
managedServiceConfigKey: "google-oauth",
|
|
649
602
|
});
|
|
650
603
|
mockGetManagedServiceConfigKey = () => "google-oauth";
|
|
@@ -51,20 +51,6 @@ mock.module("../../../../oauth/oauth-store.js", () => ({
|
|
|
51
51
|
deleteConnection: () => false,
|
|
52
52
|
}));
|
|
53
53
|
|
|
54
|
-
mock.module("../../../../oauth/provider-behaviors.js", () => ({
|
|
55
|
-
resolveService: (service: string) => {
|
|
56
|
-
const aliases: Record<string, string> = {
|
|
57
|
-
gmail: "integration:google",
|
|
58
|
-
google: "integration:google",
|
|
59
|
-
slack: "integration:slack",
|
|
60
|
-
};
|
|
61
|
-
if (aliases[service]) return aliases[service];
|
|
62
|
-
if (!service.includes(":")) return `integration:${service}`;
|
|
63
|
-
return service;
|
|
64
|
-
},
|
|
65
|
-
getProviderBehavior: () => undefined,
|
|
66
|
-
}));
|
|
67
|
-
|
|
68
54
|
mock.module("../../../../oauth/connection-resolver.js", () => ({
|
|
69
55
|
resolveOAuthConnection: async (
|
|
70
56
|
providerKey: string,
|
|
@@ -101,23 +87,9 @@ mock.module("../../../../util/logger.js", () => ({
|
|
|
101
87
|
|
|
102
88
|
// Mock shared.js helpers
|
|
103
89
|
mock.module("../shared.js", () => ({
|
|
104
|
-
resolveService: (service: string) => {
|
|
105
|
-
const aliases: Record<string, string> = {
|
|
106
|
-
gmail: "integration:google",
|
|
107
|
-
google: "integration:google",
|
|
108
|
-
slack: "integration:slack",
|
|
109
|
-
};
|
|
110
|
-
if (aliases[service]) return aliases[service];
|
|
111
|
-
if (!service.includes(":")) return `integration:${service}`;
|
|
112
|
-
return service;
|
|
113
|
-
},
|
|
114
90
|
isManagedMode: () => false,
|
|
115
91
|
requirePlatformClient: async () => null,
|
|
116
92
|
fetchActiveConnections: async () => [],
|
|
117
|
-
toBareProvider: (provider: string): string =>
|
|
118
|
-
provider.startsWith("integration:")
|
|
119
|
-
? provider.slice("integration:".length)
|
|
120
|
-
: provider,
|
|
121
93
|
}));
|
|
122
94
|
|
|
123
95
|
// ---------------------------------------------------------------------------
|
|
@@ -214,7 +186,7 @@ describe("assistant oauth ping", () => {
|
|
|
214
186
|
|
|
215
187
|
test("no ping URL configured returns error", async () => {
|
|
216
188
|
mockGetProvider = () => ({
|
|
217
|
-
providerKey: "
|
|
189
|
+
providerKey: "google",
|
|
218
190
|
pingUrl: null,
|
|
219
191
|
});
|
|
220
192
|
|
|
@@ -226,37 +198,6 @@ describe("assistant oauth ping", () => {
|
|
|
226
198
|
expect(parsed.error).toContain("providers register --ping-url");
|
|
227
199
|
});
|
|
228
200
|
|
|
229
|
-
// -------------------------------------------------------------------------
|
|
230
|
-
// Provider alias resolution
|
|
231
|
-
// -------------------------------------------------------------------------
|
|
232
|
-
|
|
233
|
-
test("resolves provider alias (gmail -> integration:google)", async () => {
|
|
234
|
-
mockGetProvider = () => ({
|
|
235
|
-
providerKey: "integration:google",
|
|
236
|
-
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
mockResolveOAuthConnectionResult = {
|
|
240
|
-
request: async () => ({
|
|
241
|
-
status: 200,
|
|
242
|
-
headers: {},
|
|
243
|
-
body: { ok: true },
|
|
244
|
-
}),
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
const { exitCode, stdout } = await runCommand(["ping", "gmail", "--json"]);
|
|
248
|
-
expect(exitCode).toBe(0);
|
|
249
|
-
const parsed = JSON.parse(stdout);
|
|
250
|
-
expect(parsed.ok).toBe(true);
|
|
251
|
-
expect(parsed.provider).toBe("integration:google");
|
|
252
|
-
|
|
253
|
-
// Verify resolveOAuthConnection was called with resolved key
|
|
254
|
-
expect(mockResolveOAuthConnectionCalls).toHaveLength(1);
|
|
255
|
-
expect(mockResolveOAuthConnectionCalls[0].providerKey).toBe(
|
|
256
|
-
"integration:google",
|
|
257
|
-
);
|
|
258
|
-
});
|
|
259
|
-
|
|
260
201
|
// =========================================================================
|
|
261
202
|
// BYO mode tests
|
|
262
203
|
// =========================================================================
|
|
@@ -264,7 +205,7 @@ describe("assistant oauth ping", () => {
|
|
|
264
205
|
describe("BYO mode", () => {
|
|
265
206
|
beforeEach(() => {
|
|
266
207
|
mockGetProvider = () => ({
|
|
267
|
-
providerKey: "
|
|
208
|
+
providerKey: "google",
|
|
268
209
|
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
269
210
|
managedServiceConfigKey: null,
|
|
270
211
|
});
|
|
@@ -287,7 +228,7 @@ describe("assistant oauth ping", () => {
|
|
|
287
228
|
expect(exitCode).toBe(0);
|
|
288
229
|
const parsed = JSON.parse(stdout);
|
|
289
230
|
expect(parsed.ok).toBe(true);
|
|
290
|
-
expect(parsed.provider).toBe("
|
|
231
|
+
expect(parsed.provider).toBe("google");
|
|
291
232
|
expect(parsed.status).toBe(200);
|
|
292
233
|
});
|
|
293
234
|
|
|
@@ -308,7 +249,7 @@ describe("assistant oauth ping", () => {
|
|
|
308
249
|
expect(exitCode).toBe(1);
|
|
309
250
|
const parsed = JSON.parse(stdout);
|
|
310
251
|
expect(parsed.ok).toBe(false);
|
|
311
|
-
expect(parsed.provider).toBe("
|
|
252
|
+
expect(parsed.provider).toBe("google");
|
|
312
253
|
expect(parsed.status).toBe(500);
|
|
313
254
|
expect(parsed.error).toContain("Ping failed with HTTP 500");
|
|
314
255
|
});
|
|
@@ -366,7 +307,7 @@ describe("assistant oauth ping", () => {
|
|
|
366
307
|
describe("managed mode", () => {
|
|
367
308
|
beforeEach(() => {
|
|
368
309
|
mockGetProvider = () => ({
|
|
369
|
-
providerKey: "
|
|
310
|
+
providerKey: "google",
|
|
370
311
|
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
371
312
|
managedServiceConfigKey: "google-oauth",
|
|
372
313
|
});
|
|
@@ -389,7 +330,7 @@ describe("assistant oauth ping", () => {
|
|
|
389
330
|
expect(exitCode).toBe(0);
|
|
390
331
|
const parsed = JSON.parse(stdout);
|
|
391
332
|
expect(parsed.ok).toBe(true);
|
|
392
|
-
expect(parsed.provider).toBe("
|
|
333
|
+
expect(parsed.provider).toBe("google");
|
|
393
334
|
expect(parsed.status).toBe(200);
|
|
394
335
|
});
|
|
395
336
|
|
|
@@ -410,7 +351,7 @@ describe("assistant oauth ping", () => {
|
|
|
410
351
|
expect(exitCode).toBe(1);
|
|
411
352
|
const parsed = JSON.parse(stdout);
|
|
412
353
|
expect(parsed.ok).toBe(false);
|
|
413
|
-
expect(parsed.provider).toBe("
|
|
354
|
+
expect(parsed.provider).toBe("google");
|
|
414
355
|
expect(parsed.status).toBe(502);
|
|
415
356
|
expect(parsed.error).toContain("Ping failed with HTTP 502");
|
|
416
357
|
});
|
|
@@ -422,12 +363,12 @@ describe("assistant oauth ping", () => {
|
|
|
422
363
|
|
|
423
364
|
test("connection resolution failure (no active connection) with recovery hint", async () => {
|
|
424
365
|
mockGetProvider = () => ({
|
|
425
|
-
providerKey: "
|
|
366
|
+
providerKey: "google",
|
|
426
367
|
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
427
368
|
});
|
|
428
369
|
|
|
429
370
|
mockResolveOAuthConnectionResult = new Error(
|
|
430
|
-
'No active OAuth connection found for "
|
|
371
|
+
'No active OAuth connection found for "google". Connect the service first with oauth2_connect.',
|
|
431
372
|
);
|
|
432
373
|
|
|
433
374
|
const { exitCode, stdout } = await runCommand(["ping", "google", "--json"]);
|
|
@@ -445,7 +386,7 @@ describe("assistant oauth ping", () => {
|
|
|
445
386
|
|
|
446
387
|
test("--account option passed through to connection resolution", async () => {
|
|
447
388
|
mockGetProvider = () => ({
|
|
448
|
-
providerKey: "
|
|
389
|
+
providerKey: "google",
|
|
449
390
|
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
450
391
|
});
|
|
451
392
|
|
|
@@ -478,7 +419,7 @@ describe("assistant oauth ping", () => {
|
|
|
478
419
|
|
|
479
420
|
test("--client-id option passed through to connection resolution", async () => {
|
|
480
421
|
mockGetProvider = () => ({
|
|
481
|
-
providerKey: "
|
|
422
|
+
providerKey: "google",
|
|
482
423
|
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
483
424
|
});
|
|
484
425
|
|
|
@@ -511,7 +452,7 @@ describe("assistant oauth ping", () => {
|
|
|
511
452
|
|
|
512
453
|
test("JSON output mode returns structured response", async () => {
|
|
513
454
|
mockGetProvider = () => ({
|
|
514
|
-
providerKey: "
|
|
455
|
+
providerKey: "google",
|
|
515
456
|
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
516
457
|
});
|
|
517
458
|
|
|
@@ -529,7 +470,7 @@ describe("assistant oauth ping", () => {
|
|
|
529
470
|
|
|
530
471
|
// Verify JSON structure
|
|
531
472
|
expect(parsed).toHaveProperty("ok", true);
|
|
532
|
-
expect(parsed).toHaveProperty("provider", "
|
|
473
|
+
expect(parsed).toHaveProperty("provider", "google");
|
|
533
474
|
expect(parsed).toHaveProperty("status", 200);
|
|
534
475
|
});
|
|
535
476
|
|
|
@@ -539,7 +480,7 @@ describe("assistant oauth ping", () => {
|
|
|
539
480
|
|
|
540
481
|
test("human output mode logs to stderr on success", async () => {
|
|
541
482
|
mockGetProvider = () => ({
|
|
542
|
-
providerKey: "
|
|
483
|
+
providerKey: "google",
|
|
543
484
|
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
544
485
|
});
|
|
545
486
|
|
|
@@ -558,7 +499,7 @@ describe("assistant oauth ping", () => {
|
|
|
558
499
|
// In human mode, output is still written via writeOutput
|
|
559
500
|
const parsed = JSON.parse(stdout);
|
|
560
501
|
expect(parsed.ok).toBe(true);
|
|
561
|
-
expect(parsed.provider).toBe("
|
|
502
|
+
expect(parsed.provider).toBe("google");
|
|
562
503
|
});
|
|
563
504
|
|
|
564
505
|
// =========================================================================
|
|
@@ -567,7 +508,7 @@ describe("assistant oauth ping", () => {
|
|
|
567
508
|
|
|
568
509
|
test("uses configured pingMethod for POST providers", async () => {
|
|
569
510
|
mockGetProvider = () => ({
|
|
570
|
-
providerKey: "
|
|
511
|
+
providerKey: "dropbox",
|
|
571
512
|
pingUrl: "https://api.dropboxapi.com/2/users/get_current_account",
|
|
572
513
|
pingMethod: "POST",
|
|
573
514
|
pingHeaders: null,
|
|
@@ -589,7 +530,7 @@ describe("assistant oauth ping", () => {
|
|
|
589
530
|
|
|
590
531
|
test("uses configured pingHeaders", async () => {
|
|
591
532
|
mockGetProvider = () => ({
|
|
592
|
-
providerKey: "
|
|
533
|
+
providerKey: "notion",
|
|
593
534
|
pingUrl: "https://api.notion.com/v1/users/me",
|
|
594
535
|
pingMethod: null,
|
|
595
536
|
pingHeaders: '{"Notion-Version":"2022-06-28"}',
|
|
@@ -613,7 +554,7 @@ describe("assistant oauth ping", () => {
|
|
|
613
554
|
|
|
614
555
|
test("uses configured pingBody for GraphQL providers", async () => {
|
|
615
556
|
mockGetProvider = () => ({
|
|
616
|
-
providerKey: "
|
|
557
|
+
providerKey: "linear",
|
|
617
558
|
pingUrl: "https://api.linear.app/graphql",
|
|
618
559
|
pingMethod: "POST",
|
|
619
560
|
pingHeaders: '{"Content-Type":"application/json"}',
|
|
@@ -641,7 +582,7 @@ describe("assistant oauth ping", () => {
|
|
|
641
582
|
|
|
642
583
|
test("defaults to GET with no extra headers/body when ping config is null", async () => {
|
|
643
584
|
mockGetProvider = () => ({
|
|
644
|
-
providerKey: "
|
|
585
|
+
providerKey: "google",
|
|
645
586
|
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
646
587
|
pingMethod: null,
|
|
647
588
|
pingHeaders: null,
|
|
@@ -669,7 +610,7 @@ describe("assistant oauth ping", () => {
|
|
|
669
610
|
|
|
670
611
|
test("network failure returns error with recovery hint", async () => {
|
|
671
612
|
mockGetProvider = () => ({
|
|
672
|
-
providerKey: "
|
|
613
|
+
providerKey: "google",
|
|
673
614
|
pingUrl: "https://www.googleapis.com/oauth2/v1/tokeninfo",
|
|
674
615
|
});
|
|
675
616
|
|