@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.
Files changed (209) hide show
  1. package/Dockerfile +42 -9
  2. package/docs/architecture/integrations.md +34 -32
  3. package/node_modules/@vellumai/ces-contracts/src/__tests__/grants.test.ts +7 -7
  4. package/node_modules/@vellumai/ces-contracts/src/handles.ts +5 -4
  5. package/node_modules/@vellumai/ces-contracts/src/index.ts +7 -0
  6. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +5 -0
  7. package/node_modules/@vellumai/credential-storage/src/index.ts +1 -1
  8. package/openapi.yaml +87 -9
  9. package/package.json +1 -1
  10. package/src/__tests__/catalog-cache.test.ts +164 -0
  11. package/src/__tests__/catalog-search.test.ts +61 -0
  12. package/src/__tests__/cli-command-risk-guard.test.ts +181 -6
  13. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +396 -0
  14. package/src/__tests__/conversation-error.test.ts +3 -2
  15. package/src/__tests__/credential-security-invariants.test.ts +9 -15
  16. package/src/__tests__/credential-vault-unit.test.ts +32 -34
  17. package/src/__tests__/credential-vault.test.ts +25 -33
  18. package/src/__tests__/credentials-cli.test.ts +3 -3
  19. package/src/__tests__/daemon-credential-client.test.ts +2 -2
  20. package/src/__tests__/first-greeting.test.ts +7 -0
  21. package/src/__tests__/host-bash-proxy.test.ts +79 -0
  22. package/src/__tests__/host-cu-proxy.test.ts +90 -0
  23. package/src/__tests__/host-file-proxy.test.ts +89 -0
  24. package/src/__tests__/integration-status.test.ts +5 -5
  25. package/src/__tests__/list-messages-attachments.test.ts +171 -0
  26. package/src/__tests__/mcp-abort-signal.test.ts +205 -0
  27. package/src/__tests__/messaging-send-tool.test.ts +5 -5
  28. package/src/__tests__/navigate-settings-tab.test.ts +6 -2
  29. package/src/__tests__/notification-telegram-adapter.test.ts +125 -0
  30. package/src/__tests__/oauth-cli.test.ts +126 -119
  31. package/src/__tests__/oauth-provider-profiles.test.ts +55 -20
  32. package/src/__tests__/oauth-scope-policy.test.ts +4 -6
  33. package/src/__tests__/onboarding-template-contract.test.ts +2 -2
  34. package/src/__tests__/platform.test.ts +3 -168
  35. package/src/__tests__/secret-routes-managed-proxy.test.ts +78 -0
  36. package/src/__tests__/secure-keys-managed-failover.test.ts +73 -0
  37. package/src/__tests__/skill-feature-flags.test.ts +8 -0
  38. package/src/__tests__/skill-secret-handling-guard.test.ts +212 -0
  39. package/src/__tests__/skills-uninstall.test.ts +2 -2
  40. package/src/__tests__/slack-messaging-token-resolution.test.ts +22 -24
  41. package/src/__tests__/slack-share-routes.test.ts +5 -5
  42. package/src/__tests__/system-prompt.test.ts +39 -0
  43. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -1
  44. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +5 -4
  45. package/src/cli/AGENTS.md +47 -7
  46. package/src/cli/commands/browser-relay.ts +2 -17
  47. package/src/cli/commands/contacts.ts +6 -4
  48. package/src/cli/commands/conversations.ts +13 -1
  49. package/src/cli/commands/credential-execution.ts +16 -1
  50. package/src/cli/commands/credentials.ts +2 -8
  51. package/src/cli/commands/oauth/__tests__/connect.test.ts +29 -108
  52. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +13 -87
  53. package/src/cli/commands/oauth/__tests__/mode.test.ts +22 -69
  54. package/src/cli/commands/oauth/__tests__/ping.test.ts +20 -79
  55. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +574 -0
  56. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +416 -0
  57. package/src/cli/commands/oauth/__tests__/status.test.ts +12 -40
  58. package/src/cli/commands/oauth/__tests__/token.test.ts +3 -50
  59. package/src/cli/commands/oauth/apps.ts +63 -44
  60. package/src/cli/commands/oauth/connect.ts +187 -155
  61. package/src/cli/commands/oauth/disconnect.ts +27 -75
  62. package/src/cli/commands/oauth/index.ts +36 -46
  63. package/src/cli/commands/oauth/mode.ts +22 -34
  64. package/src/cli/commands/oauth/ping.ts +19 -45
  65. package/src/cli/commands/oauth/providers.ts +569 -62
  66. package/src/cli/commands/oauth/request.ts +36 -48
  67. package/src/cli/commands/oauth/shared.ts +1 -19
  68. package/src/cli/commands/oauth/status.ts +14 -25
  69. package/src/cli/commands/oauth/token.ts +25 -34
  70. package/src/cli/commands/platform/__tests__/connect.test.ts +224 -0
  71. package/src/cli/commands/platform/__tests__/disconnect.test.ts +237 -0
  72. package/src/cli/commands/platform/__tests__/status.test.ts +246 -0
  73. package/src/cli/commands/platform/connect.ts +104 -0
  74. package/src/cli/commands/platform/disconnect.ts +118 -0
  75. package/src/cli/commands/{platform.ts → platform/index.ts} +108 -38
  76. package/src/cli/commands/sequence.ts +5 -4
  77. package/src/cli/commands/shotgun.ts +16 -0
  78. package/src/cli/commands/skills.ts +173 -41
  79. package/src/cli/commands/usage.ts +5 -11
  80. package/src/cli/lib/daemon-credential-client.ts +22 -38
  81. package/src/cli/program.ts +1 -1
  82. package/src/config/assistant-feature-flags.ts +3 -7
  83. package/src/config/bundled-skills/contacts/tools/google-contacts.ts +1 -1
  84. package/src/config/bundled-skills/conversations/SKILL.md +20 -0
  85. package/src/config/bundled-skills/conversations/TOOLS.json +23 -0
  86. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +66 -0
  87. package/src/config/bundled-skills/gmail/SKILL.md +13 -13
  88. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +3 -3
  89. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +2 -2
  90. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +1 -1
  91. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +1 -1
  92. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +1 -1
  93. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +1 -1
  94. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +2 -2
  95. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +1 -1
  96. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +1 -1
  97. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
  98. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +1 -1
  99. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +1 -1
  100. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +1 -1
  101. package/src/config/bundled-skills/google-calendar/SKILL.md +10 -4
  102. package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
  103. package/src/config/bundled-skills/messaging/SKILL.md +7 -7
  104. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -2
  105. package/src/config/bundled-skills/messaging/tools/shared.ts +5 -6
  106. package/src/config/bundled-skills/settings/TOOLS.json +5 -3
  107. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +4 -2
  108. package/src/config/bundled-tool-registry.ts +5 -0
  109. package/src/config/feature-flag-registry.json +2 -2
  110. package/src/credential-execution/client.ts +15 -3
  111. package/src/daemon/conversation-agent-loop.ts +2 -0
  112. package/src/daemon/conversation-error.ts +36 -6
  113. package/src/daemon/conversation-messaging.ts +9 -0
  114. package/src/daemon/conversation-runtime-assembly.ts +33 -0
  115. package/src/daemon/conversation-surfaces.ts +120 -14
  116. package/src/daemon/conversation.ts +5 -0
  117. package/src/daemon/first-greeting.ts +6 -1
  118. package/src/daemon/handlers/skills.ts +148 -3
  119. package/src/daemon/host-bash-proxy.ts +16 -0
  120. package/src/daemon/host-cu-proxy.ts +16 -0
  121. package/src/daemon/host-file-proxy.ts +16 -0
  122. package/src/daemon/lifecycle.ts +56 -5
  123. package/src/daemon/message-types/conversations.ts +1 -0
  124. package/src/daemon/message-types/guardian-actions.ts +2 -0
  125. package/src/daemon/message-types/host-bash.ts +6 -1
  126. package/src/daemon/message-types/host-cu.ts +6 -1
  127. package/src/daemon/message-types/host-file.ts +6 -1
  128. package/src/daemon/message-types/integrations.ts +0 -1
  129. package/src/daemon/server.ts +29 -2
  130. package/src/hooks/cli.ts +74 -0
  131. package/src/inbound/platform-callback-registration.ts +7 -12
  132. package/src/index.ts +0 -12
  133. package/src/mcp/client.ts +6 -1
  134. package/src/mcp/manager.ts +2 -1
  135. package/src/memory/conversation-crud.ts +92 -3
  136. package/src/memory/conversation-key-store.ts +26 -0
  137. package/src/memory/conversation-queries.ts +6 -6
  138. package/src/memory/db-init.ts +16 -0
  139. package/src/memory/journal-memory.ts +8 -2
  140. package/src/memory/migrations/196-messages-conversation-created-at-index.ts +9 -0
  141. package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +186 -0
  142. package/src/memory/migrations/197-oauth-providers-behavior-columns.ts +29 -0
  143. package/src/memory/migrations/198-drop-setup-skill-id-column.ts +11 -0
  144. package/src/memory/migrations/index.ts +4 -0
  145. package/src/memory/migrations/registry.ts +8 -0
  146. package/src/memory/schema/oauth.ts +11 -0
  147. package/src/messaging/provider.ts +13 -12
  148. package/src/messaging/providers/gmail/adapter.ts +44 -35
  149. package/src/messaging/providers/slack/adapter.ts +63 -33
  150. package/src/messaging/providers/telegram-bot/adapter.ts +6 -8
  151. package/src/messaging/providers/whatsapp/adapter.ts +6 -8
  152. package/src/notifications/adapters/telegram.ts +78 -2
  153. package/src/oauth/__tests__/identity-verifier.test.ts +464 -0
  154. package/src/oauth/byo-connection.test.ts +22 -24
  155. package/src/oauth/connect-orchestrator.ts +37 -76
  156. package/src/oauth/connect-types.ts +7 -65
  157. package/src/oauth/connection-resolver.test.ts +13 -13
  158. package/src/oauth/connection-resolver.ts +3 -4
  159. package/src/oauth/identity-verifier.ts +177 -0
  160. package/src/oauth/oauth-store.ts +228 -3
  161. package/src/oauth/platform-connection.test.ts +56 -6
  162. package/src/oauth/platform-connection.ts +8 -1
  163. package/src/oauth/seed-providers.ts +247 -34
  164. package/src/permissions/checker.ts +127 -1
  165. package/src/prompts/journal-context.ts +4 -1
  166. package/src/prompts/system-prompt.ts +54 -9
  167. package/src/prompts/templates/BOOTSTRAP.md +16 -5
  168. package/src/providers/anthropic/client.ts +2 -33
  169. package/src/runtime/guardian-action-service.ts +7 -2
  170. package/src/runtime/http-server.ts +12 -18
  171. package/src/runtime/http-types.ts +8 -1
  172. package/src/runtime/migrations/rebind-secrets-screen.ts +2 -2
  173. package/src/runtime/routes/conversation-management-routes.ts +31 -0
  174. package/src/runtime/routes/conversation-routes.ts +79 -4
  175. package/src/runtime/routes/guardian-action-routes.ts +15 -2
  176. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -8
  177. package/src/runtime/routes/integrations/slack/share.ts +1 -1
  178. package/src/runtime/routes/oauth-apps.ts +2 -1
  179. package/src/runtime/routes/secret-routes.ts +45 -15
  180. package/src/runtime/routes/settings-routes.ts +12 -19
  181. package/src/runtime/routes/skills-routes.ts +45 -4
  182. package/src/schedule/integration-status.ts +2 -2
  183. package/src/security/ces-rpc-credential-backend.ts +19 -16
  184. package/src/security/oauth-completion-page.ts +153 -0
  185. package/src/security/oauth2.ts +3 -17
  186. package/src/security/secure-keys.ts +207 -7
  187. package/src/security/token-manager.ts +3 -6
  188. package/src/signals/bash.ts +6 -1
  189. package/src/skills/catalog-cache.ts +44 -0
  190. package/src/skills/catalog-search.ts +18 -0
  191. package/src/tools/browser/browser-manager.ts +2 -2
  192. package/src/tools/credentials/post-connect-hooks.ts +1 -1
  193. package/src/tools/credentials/vault.ts +34 -45
  194. package/src/tools/host-terminal/host-shell.ts +16 -3
  195. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  196. package/src/tools/skills/sandbox-runner.ts +16 -3
  197. package/src/tools/terminal/shell.ts +16 -3
  198. package/src/util/logger.ts +11 -1
  199. package/src/util/platform.ts +1 -91
  200. package/src/util/sentry-log-stream.ts +51 -0
  201. package/src/watcher/providers/github.ts +2 -2
  202. package/src/watcher/providers/gmail.ts +1 -1
  203. package/src/watcher/providers/google-calendar.ts +1 -1
  204. package/src/watcher/providers/linear.ts +2 -2
  205. package/src/workspace/migrations/011-backfill-installation-id.ts +5 -3
  206. package/src/workspace/migrations/020-rename-oauth-skill-dirs.ts +119 -0
  207. package/src/workspace/migrations/registry.ts +2 -0
  208. package/src/cli/commands/oauth/connections.ts +0 -255
  209. package/src/oauth/provider-behaviors.ts +0 -634
@@ -27,10 +27,6 @@ let mockOrchestrateOAuthConnect: (
27
27
  grantedScopes: [],
28
28
  });
29
29
 
30
- let mockGetProviderBehavior: (
31
- key: string,
32
- ) => Record<string, unknown> | undefined = () => undefined;
33
-
34
30
  let mockGetSecureKeyViaDaemon: (
35
31
  account: string,
36
32
  ) => Promise<string | undefined> = async () => undefined;
@@ -80,20 +76,6 @@ mock.module("../../../../oauth/oauth-store.js", () => ({
80
76
  deleteConnection: () => false,
81
77
  }));
82
78
 
83
- mock.module("../../../../oauth/provider-behaviors.js", () => ({
84
- resolveService: (service: string) => {
85
- const aliases: Record<string, string> = {
86
- gmail: "integration:google",
87
- google: "integration:google",
88
- slack: "integration:slack",
89
- };
90
- if (aliases[service]) return aliases[service];
91
- if (!service.includes(":")) return `integration:${service}`;
92
- return service;
93
- },
94
- getProviderBehavior: (key: string) => mockGetProviderBehavior(key),
95
- }));
96
-
97
79
  mock.module("../../../../oauth/connect-orchestrator.js", () => ({
98
80
  orchestrateOAuthConnect: (opts: Record<string, unknown>) =>
99
81
  mockOrchestrateOAuthConnect(opts),
@@ -134,16 +116,6 @@ mock.module("../../../lib/daemon-credential-client.js", () => ({
134
116
 
135
117
  // Mock shared.js helpers to control managed vs BYO mode routing
136
118
  mock.module("../shared.js", () => ({
137
- resolveService: (service: string) => {
138
- const aliases: Record<string, string> = {
139
- gmail: "integration:google",
140
- google: "integration:google",
141
- slack: "integration:slack",
142
- };
143
- if (aliases[service]) return aliases[service];
144
- if (!service.includes(":")) return `integration:${service}`;
145
- return service;
146
- },
147
119
  isManagedMode: (key: string) => mockIsManagedMode(key),
148
120
  requirePlatformClient: async (_cmd: Command) => {
149
121
  if (
@@ -193,10 +165,6 @@ mock.module("../shared.js", () => ({
193
165
  if (!result.ok) return null;
194
166
  return result.body as Array<Record<string, unknown>>;
195
167
  },
196
- toBareProvider: (provider: string): string =>
197
- provider.startsWith("integration:")
198
- ? provider.slice("integration:".length)
199
- : provider,
200
168
  }));
201
169
 
202
170
  // ---------------------------------------------------------------------------
@@ -262,7 +230,6 @@ describe("assistant oauth connect", () => {
262
230
  deferred: false,
263
231
  grantedScopes: [],
264
232
  });
265
- mockGetProviderBehavior = () => undefined;
266
233
  mockGetSecureKeyViaDaemon = async () => undefined;
267
234
  mockOpenInBrowserCalls = [];
268
235
  mockPlatformClientResult = null;
@@ -291,50 +258,13 @@ describe("assistant oauth connect", () => {
291
258
  expect(parsed.error).toContain("providers list");
292
259
  });
293
260
 
294
- // -------------------------------------------------------------------------
295
- // Provider alias resolution
296
- // -------------------------------------------------------------------------
297
-
298
- test("provider alias '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
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
306
- tokenUrl: "https://oauth2.googleapis.com/token",
307
- managedServiceConfigKey: null,
308
- };
309
- };
310
-
311
- mockGetMostRecentAppByProvider = () => ({
312
- id: "app-1",
313
- clientId: "test-id",
314
- clientSecretCredentialPath: "oauth_app/app-1/client_secret",
315
- providerKey: "integration:google",
316
- createdAt: 0,
317
- updatedAt: 0,
318
- });
319
-
320
- mockOrchestrateOAuthConnect = async () => ({
321
- success: true,
322
- deferred: false,
323
- grantedScopes: ["read"],
324
- accountInfo: "user@example.com",
325
- });
326
-
327
- await runCommand(["connect", "gmail", "--json"]);
328
- expect(capturedProviderKey).toBe("integration:google");
329
- });
330
-
331
261
  // -------------------------------------------------------------------------
332
262
  // Managed mode: prints connect URL without --open-browser
333
263
  // -------------------------------------------------------------------------
334
264
 
335
265
  test("managed mode: prints connect URL without --open-browser", async () => {
336
266
  mockGetProvider = () => ({
337
- providerKey: "integration:google",
267
+ providerKey: "google",
338
268
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
339
269
  tokenUrl: "https://oauth2.googleapis.com/token",
340
270
  managedServiceConfigKey: "google-oauth",
@@ -361,7 +291,7 @@ describe("assistant oauth connect", () => {
361
291
  expect(parsed.connectUrl).toBe(
362
292
  "https://platform.example.com/oauth/connect",
363
293
  );
364
- expect(parsed.provider).toBe("integration:google");
294
+ expect(parsed.provider).toBe("google");
365
295
  });
366
296
 
367
297
  // -------------------------------------------------------------------------
@@ -370,7 +300,7 @@ describe("assistant oauth connect", () => {
370
300
 
371
301
  test("managed mode with --open-browser: opens browser and polls for new connection", async () => {
372
302
  mockGetProvider = () => ({
373
- providerKey: "integration:google",
303
+ providerKey: "google",
374
304
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
375
305
  tokenUrl: "https://oauth2.googleapis.com/token",
376
306
  managedServiceConfigKey: "google-oauth",
@@ -427,7 +357,7 @@ describe("assistant oauth connect", () => {
427
357
 
428
358
  test("BYO mode: prints auth URL without --open-browser", async () => {
429
359
  mockGetProvider = () => ({
430
- providerKey: "integration:google",
360
+ providerKey: "google",
431
361
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
432
362
  tokenUrl: "https://oauth2.googleapis.com/token",
433
363
  managedServiceConfigKey: null,
@@ -438,7 +368,7 @@ describe("assistant oauth connect", () => {
438
368
  id: "app-1",
439
369
  clientId: "byo-client-id",
440
370
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
441
- providerKey: "integration:google",
371
+ providerKey: "google",
442
372
  createdAt: 0,
443
373
  updatedAt: 0,
444
374
  });
@@ -448,12 +378,12 @@ describe("assistant oauth connect", () => {
448
378
  deferred: true,
449
379
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth?state=abc",
450
380
  state: "abc",
451
- service: "integration:google",
381
+ service: "google",
452
382
  });
453
383
 
454
384
  const { exitCode, stdout } = await runCommand([
455
385
  "connect",
456
- "integration:google",
386
+ "google",
457
387
  "--json",
458
388
  ]);
459
389
  expect(exitCode).toBe(0);
@@ -463,7 +393,7 @@ describe("assistant oauth connect", () => {
463
393
  expect(parsed.authUrl).toBe(
464
394
  "https://accounts.google.com/o/oauth2/v2/auth?state=abc",
465
395
  );
466
- expect(parsed.service).toBe("integration:google");
396
+ expect(parsed.service).toBe("google");
467
397
  });
468
398
 
469
399
  // -------------------------------------------------------------------------
@@ -472,7 +402,7 @@ describe("assistant oauth connect", () => {
472
402
 
473
403
  test("BYO mode with --open-browser calls orchestrator with isInteractive: true", async () => {
474
404
  mockGetProvider = () => ({
475
- providerKey: "integration:google",
405
+ providerKey: "google",
476
406
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
477
407
  tokenUrl: "https://oauth2.googleapis.com/token",
478
408
  managedServiceConfigKey: null,
@@ -483,7 +413,7 @@ describe("assistant oauth connect", () => {
483
413
  id: "app-1",
484
414
  clientId: "test-id",
485
415
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
486
- providerKey: "integration:google",
416
+ providerKey: "google",
487
417
  createdAt: 0,
488
418
  updatedAt: 0,
489
419
  });
@@ -501,7 +431,7 @@ describe("assistant oauth connect", () => {
501
431
 
502
432
  const { exitCode, stdout } = await runCommand([
503
433
  "connect",
504
- "integration:google",
434
+ "google",
505
435
  "--client-id",
506
436
  "test-id",
507
437
  "--open-browser",
@@ -525,7 +455,7 @@ describe("assistant oauth connect", () => {
525
455
 
526
456
  test("BYO mode: missing app with --client-id returns error with hint", async () => {
527
457
  mockGetProvider = () => ({
528
- providerKey: "integration:google",
458
+ providerKey: "google",
529
459
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
530
460
  tokenUrl: "https://oauth2.googleapis.com/token",
531
461
  managedServiceConfigKey: null,
@@ -535,7 +465,7 @@ describe("assistant oauth connect", () => {
535
465
 
536
466
  const { exitCode, stdout } = await runCommand([
537
467
  "connect",
538
- "integration:google",
468
+ "google",
539
469
  "--client-id",
540
470
  "nonexistent-id",
541
471
  "--json",
@@ -553,7 +483,7 @@ describe("assistant oauth connect", () => {
553
483
 
554
484
  test("BYO mode: no client_id found returns error with hint", async () => {
555
485
  mockGetProvider = () => ({
556
- providerKey: "integration:google",
486
+ providerKey: "google",
557
487
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
558
488
  tokenUrl: "https://oauth2.googleapis.com/token",
559
489
  managedServiceConfigKey: null,
@@ -563,7 +493,7 @@ describe("assistant oauth connect", () => {
563
493
 
564
494
  const { exitCode, stdout } = await runCommand([
565
495
  "connect",
566
- "integration:google",
496
+ "google",
567
497
  "--json",
568
498
  ]);
569
499
  expect(exitCode).toBe(1);
@@ -579,7 +509,7 @@ describe("assistant oauth connect", () => {
579
509
 
580
510
  test("--client-id is silently ignored in managed mode", async () => {
581
511
  mockGetProvider = () => ({
582
- providerKey: "integration:google",
512
+ providerKey: "google",
583
513
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
584
514
  tokenUrl: "https://oauth2.googleapis.com/token",
585
515
  managedServiceConfigKey: "google-oauth",
@@ -616,7 +546,7 @@ describe("assistant oauth connect", () => {
616
546
 
617
547
  test("JSON output for deferred case includes ok, deferred, authUrl, service", async () => {
618
548
  mockGetProvider = () => ({
619
- providerKey: "integration:slack",
549
+ providerKey: "slack",
620
550
  authUrl: "https://slack.com/oauth/v2/authorize",
621
551
  tokenUrl: "https://slack.com/api/oauth.v2.access",
622
552
  managedServiceConfigKey: null,
@@ -627,7 +557,7 @@ describe("assistant oauth connect", () => {
627
557
  id: "app-slack",
628
558
  clientId: "slack-client-id",
629
559
  clientSecretCredentialPath: "oauth_app/app-slack/client_secret",
630
- providerKey: "integration:slack",
560
+ providerKey: "slack",
631
561
  createdAt: 0,
632
562
  updatedAt: 0,
633
563
  });
@@ -637,7 +567,7 @@ describe("assistant oauth connect", () => {
637
567
  deferred: true,
638
568
  authUrl: "https://slack.com/oauth/v2/authorize?state=xyz",
639
569
  state: "xyz",
640
- service: "integration:slack",
570
+ service: "slack",
641
571
  });
642
572
 
643
573
  const { exitCode, stdout } = await runCommand([
@@ -650,7 +580,7 @@ describe("assistant oauth connect", () => {
650
580
  expect(parsed).toHaveProperty("ok", true);
651
581
  expect(parsed).toHaveProperty("deferred", true);
652
582
  expect(parsed).toHaveProperty("authUrl");
653
- expect(parsed).toHaveProperty("service", "integration:slack");
583
+ expect(parsed).toHaveProperty("service", "slack");
654
584
  });
655
585
 
656
586
  // -------------------------------------------------------------------------
@@ -659,7 +589,7 @@ describe("assistant oauth connect", () => {
659
589
 
660
590
  test("JSON output for completed case includes ok, grantedScopes, accountInfo", async () => {
661
591
  mockGetProvider = () => ({
662
- providerKey: "integration:google",
592
+ providerKey: "google",
663
593
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
664
594
  tokenUrl: "https://oauth2.googleapis.com/token",
665
595
  managedServiceConfigKey: null,
@@ -670,7 +600,7 @@ describe("assistant oauth connect", () => {
670
600
  id: "app-1",
671
601
  clientId: "completed-client-id",
672
602
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
673
- providerKey: "integration:google",
603
+ providerKey: "google",
674
604
  createdAt: 0,
675
605
  updatedAt: 0,
676
606
  });
@@ -703,11 +633,12 @@ describe("assistant oauth connect", () => {
703
633
 
704
634
  test("BYO mode: client_secret required but missing returns error with hint", async () => {
705
635
  mockGetProvider = () => ({
706
- providerKey: "integration:google",
636
+ providerKey: "google",
707
637
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
708
638
  tokenUrl: "https://oauth2.googleapis.com/token",
709
639
  tokenEndpointAuthMethod: "client_secret_post",
710
640
  managedServiceConfigKey: null,
641
+ requiresClientSecret: 1,
711
642
  });
712
643
  mockIsManagedMode = () => false;
713
644
 
@@ -715,7 +646,7 @@ describe("assistant oauth connect", () => {
715
646
  id: "app-1",
716
647
  clientId: "test-id",
717
648
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
718
- providerKey: "integration:google",
649
+ providerKey: "google",
719
650
  createdAt: 0,
720
651
  updatedAt: 0,
721
652
  });
@@ -723,19 +654,9 @@ describe("assistant oauth connect", () => {
723
654
  // No secret stored
724
655
  mockGetSecureKeyViaDaemon = async () => undefined;
725
656
 
726
- // Provider behavior says secret is required
727
- mockGetProviderBehavior = () => ({
728
- setup: {
729
- requiresClientSecret: true,
730
- displayName: "Google",
731
- dashboardUrl: "https://console.cloud.google.com",
732
- appType: "Desktop app",
733
- },
734
- });
735
-
736
657
  const { exitCode, stdout } = await runCommand([
737
658
  "connect",
738
- "integration:google",
659
+ "google",
739
660
  "--json",
740
661
  ]);
741
662
  expect(exitCode).toBe(1);
@@ -751,7 +672,7 @@ describe("assistant oauth connect", () => {
751
672
 
752
673
  test("BYO mode: orchestrator error propagates correctly", async () => {
753
674
  mockGetProvider = () => ({
754
- providerKey: "integration:google",
675
+ providerKey: "google",
755
676
  authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
756
677
  tokenUrl: "https://oauth2.googleapis.com/token",
757
678
  managedServiceConfigKey: null,
@@ -762,7 +683,7 @@ describe("assistant oauth connect", () => {
762
683
  id: "app-1",
763
684
  clientId: "client-id",
764
685
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
765
- providerKey: "integration:google",
686
+ providerKey: "google",
766
687
  createdAt: 0,
767
688
  updatedAt: 0,
768
689
  });
@@ -774,7 +695,7 @@ describe("assistant oauth connect", () => {
774
695
 
775
696
  const { exitCode, stdout } = await runCommand([
776
697
  "connect",
777
- "integration:google",
698
+ "google",
778
699
  "--json",
779
700
  ]);
780
701
  expect(exitCode).toBe(1);
@@ -97,20 +97,6 @@ mock.module("../../../../oauth/oauth-store.js", () => ({
97
97
  deleteConnection: () => false,
98
98
  }));
99
99
 
100
- mock.module("../../../../oauth/provider-behaviors.js", () => ({
101
- resolveService: (service: string) => {
102
- const aliases: Record<string, string> = {
103
- gmail: "integration:google",
104
- google: "integration:google",
105
- slack: "integration:slack",
106
- };
107
- if (aliases[service]) return aliases[service];
108
- if (!service.includes(":")) return `integration:${service}`;
109
- return service;
110
- },
111
- getProviderBehavior: () => undefined,
112
- }));
113
-
114
100
  mock.module("../../../../oauth/connect-orchestrator.js", () => ({
115
101
  orchestrateOAuthConnect: async () => ({
116
102
  success: true,
@@ -165,16 +151,6 @@ mock.module("../../../lib/daemon-credential-client.js", () => ({
165
151
 
166
152
  // Mock shared.js helpers to control managed vs BYO mode routing
167
153
  mock.module("../shared.js", () => ({
168
- resolveService: (service: string) => {
169
- const aliases: Record<string, string> = {
170
- gmail: "integration:google",
171
- google: "integration:google",
172
- slack: "integration:slack",
173
- };
174
- if (aliases[service]) return aliases[service];
175
- if (!service.includes(":")) return `integration:${service}`;
176
- return service;
177
- },
178
154
  isManagedMode: (key: string) => mockIsManagedMode(key),
179
155
  requirePlatformClient: async (_cmd: Command) => {
180
156
  if (
@@ -222,10 +198,6 @@ mock.module("../shared.js", () => ({
222
198
  if (!result.ok) return null;
223
199
  return result.body as Array<Record<string, unknown>>;
224
200
  },
225
- toBareProvider: (provider: string): string =>
226
- provider.startsWith("integration:")
227
- ? provider.slice("integration:".length)
228
- : provider,
229
201
  }));
230
202
 
231
203
  // ---------------------------------------------------------------------------
@@ -323,7 +295,7 @@ describe("assistant oauth disconnect", () => {
323
295
 
324
296
  test("both --account and --connection-id returns error", async () => {
325
297
  mockGetProvider = () => ({
326
- providerKey: "integration:google",
298
+ providerKey: "google",
327
299
  managedServiceConfigKey: null,
328
300
  });
329
301
 
@@ -351,7 +323,7 @@ describe("assistant oauth disconnect", () => {
351
323
  describe("managed mode", () => {
352
324
  beforeEach(() => {
353
325
  mockGetProvider = () => ({
354
- providerKey: "integration:google",
326
+ providerKey: "google",
355
327
  managedServiceConfigKey: "google-oauth",
356
328
  });
357
329
  mockIsManagedMode = () => true;
@@ -384,7 +356,7 @@ describe("assistant oauth disconnect", () => {
384
356
  expect(exitCode).toBe(0);
385
357
  const parsed = JSON.parse(stdout);
386
358
  expect(parsed.ok).toBe(true);
387
- expect(parsed.provider).toBe("integration:google");
359
+ expect(parsed.provider).toBe("google");
388
360
  expect(parsed.connectionId).toBe("conn-1");
389
361
  expect(parsed.account).toBe("user@gmail.com");
390
362
  });
@@ -512,7 +484,7 @@ describe("assistant oauth disconnect", () => {
512
484
  describe("BYO mode", () => {
513
485
  beforeEach(() => {
514
486
  mockGetProvider = () => ({
515
- providerKey: "integration:google",
487
+ providerKey: "google",
516
488
  managedServiceConfigKey: null,
517
489
  });
518
490
  mockIsManagedMode = () => false;
@@ -522,7 +494,7 @@ describe("assistant oauth disconnect", () => {
522
494
  mockListActiveConnectionsByProvider = () => [
523
495
  {
524
496
  id: "conn-1",
525
- providerKey: "integration:google",
497
+ providerKey: "google",
526
498
  accountInfo: "user@gmail.com",
527
499
  status: "active",
528
500
  },
@@ -536,68 +508,22 @@ describe("assistant oauth disconnect", () => {
536
508
  expect(exitCode).toBe(0);
537
509
  const parsed = JSON.parse(stdout);
538
510
  expect(parsed.ok).toBe(true);
539
- expect(parsed.provider).toBe("integration:google");
511
+ expect(parsed.provider).toBe("google");
540
512
  expect(parsed.connectionId).toBe("conn-1");
541
513
  expect(parsed.account).toBe("user@gmail.com");
542
514
 
543
515
  // Verify disconnectOAuthProvider was called
544
516
  expect(mockDisconnectOAuthProviderCalls).toHaveLength(1);
545
- expect(mockDisconnectOAuthProviderCalls[0].providerKey).toBe(
546
- "integration:google",
547
- );
517
+ expect(mockDisconnectOAuthProviderCalls[0].providerKey).toBe("google");
548
518
  expect(mockDisconnectOAuthProviderCalls[0].connectionId).toBe("conn-1");
549
519
  });
550
520
 
551
- test("single connection also cleans up legacy credential keys", async () => {
552
- mockListActiveConnectionsByProvider = () => [
553
- {
554
- id: "conn-1",
555
- providerKey: "integration:google",
556
- accountInfo: "user@gmail.com",
557
- status: "active",
558
- },
559
- ];
560
-
561
- await runCommand(["disconnect", "google", "--json"]);
562
-
563
- // Should have attempted to delete legacy keys
564
- const expectedFields = [
565
- "access_token",
566
- "refresh_token",
567
- "client_id",
568
- "client_secret",
569
- ];
570
- expect(mockDeleteSecureKeyViaDaemonCalls.length).toBe(
571
- expectedFields.length,
572
- );
573
- for (const field of expectedFields) {
574
- expect(
575
- mockDeleteSecureKeyViaDaemonCalls.some(
576
- (c) =>
577
- c.type === "credential" &&
578
- c.name === `integration:google:${field}`,
579
- ),
580
- ).toBe(true);
581
- }
582
-
583
- expect(mockDeleteCredentialMetadataCalls.length).toBe(
584
- expectedFields.length,
585
- );
586
- for (const field of expectedFields) {
587
- expect(
588
- mockDeleteCredentialMetadataCalls.some(
589
- (c) => c.service === "integration:google" && c.field === field,
590
- ),
591
- ).toBe(true);
592
- }
593
- });
594
-
595
521
  test("--account matches accountInfo", async () => {
596
522
  mockGetActiveConnection = (providerKey, opts) => {
597
523
  if (opts?.account === "user@gmail.com") {
598
524
  return {
599
525
  id: "conn-1",
600
- providerKey: "integration:google",
526
+ providerKey: "google",
601
527
  accountInfo: "user@gmail.com",
602
528
  status: "active",
603
529
  };
@@ -641,7 +567,7 @@ describe("assistant oauth disconnect", () => {
641
567
  if (id === "conn-123") {
642
568
  return {
643
569
  id: "conn-123",
644
- providerKey: "integration:google",
570
+ providerKey: "google",
645
571
  accountInfo: "user@gmail.com",
646
572
  status: "active",
647
573
  };
@@ -667,7 +593,7 @@ describe("assistant oauth disconnect", () => {
667
593
  if (id === "conn-slack") {
668
594
  return {
669
595
  id: "conn-slack",
670
- providerKey: "integration:slack",
596
+ providerKey: "slack",
671
597
  accountInfo: null,
672
598
  status: "active",
673
599
  };
@@ -693,13 +619,13 @@ describe("assistant oauth disconnect", () => {
693
619
  mockListActiveConnectionsByProvider = () => [
694
620
  {
695
621
  id: "conn-1",
696
- providerKey: "integration:google",
622
+ providerKey: "google",
697
623
  accountInfo: "user1@gmail.com",
698
624
  status: "active",
699
625
  },
700
626
  {
701
627
  id: "conn-2",
702
- providerKey: "integration:google",
628
+ providerKey: "google",
703
629
  accountInfo: "user2@gmail.com",
704
630
  status: "active",
705
631
  },
@@ -740,7 +666,7 @@ describe("assistant oauth disconnect", () => {
740
666
  mockListActiveConnectionsByProvider = () => [
741
667
  {
742
668
  id: "conn-1",
743
- providerKey: "integration:google",
669
+ providerKey: "google",
744
670
  accountInfo: null,
745
671
  status: "active",
746
672
  },