@slashfi/agents-sdk 0.16.0 → 0.18.0

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 (96) hide show
  1. package/dist/agent-definitions/auth.d.ts.map +1 -1
  2. package/dist/agent-definitions/auth.js +44 -11
  3. package/dist/agent-definitions/auth.js.map +1 -1
  4. package/dist/agent-definitions/integrations.d.ts.map +1 -1
  5. package/dist/agent-definitions/integrations.js +106 -45
  6. package/dist/agent-definitions/integrations.js.map +1 -1
  7. package/dist/agent-definitions/remote-registry.d.ts.map +1 -1
  8. package/dist/agent-definitions/remote-registry.js +174 -45
  9. package/dist/agent-definitions/remote-registry.js.map +1 -1
  10. package/dist/agent-definitions/secrets.d.ts.map +1 -1
  11. package/dist/agent-definitions/secrets.js +1 -4
  12. package/dist/agent-definitions/secrets.js.map +1 -1
  13. package/dist/agent-definitions/users.d.ts.map +1 -1
  14. package/dist/agent-definitions/users.js +14 -3
  15. package/dist/agent-definitions/users.js.map +1 -1
  16. package/dist/define-config.d.ts +125 -0
  17. package/dist/define-config.d.ts.map +1 -0
  18. package/dist/define-config.js +75 -0
  19. package/dist/define-config.js.map +1 -0
  20. package/dist/define.d.ts +11 -2
  21. package/dist/define.d.ts.map +1 -1
  22. package/dist/define.js +57 -26
  23. package/dist/define.js.map +1 -1
  24. package/dist/events.d.ts +133 -0
  25. package/dist/events.d.ts.map +1 -0
  26. package/dist/events.js +57 -0
  27. package/dist/events.js.map +1 -0
  28. package/dist/index.d.ts +16 -8
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +21 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/integration-interface.d.ts +3 -3
  33. package/dist/integration-interface.d.ts.map +1 -1
  34. package/dist/integration-interface.js +29 -21
  35. package/dist/integration-interface.js.map +1 -1
  36. package/dist/integrations-store.d.ts +2 -2
  37. package/dist/integrations-store.d.ts.map +1 -1
  38. package/dist/integrations-store.js +3 -3
  39. package/dist/integrations-store.js.map +1 -1
  40. package/dist/jwt.d.ts.map +1 -1
  41. package/dist/jwt.js +7 -5
  42. package/dist/jwt.js.map +1 -1
  43. package/dist/key-manager.d.ts.map +1 -1
  44. package/dist/key-manager.js +5 -3
  45. package/dist/key-manager.js.map +1 -1
  46. package/dist/oidc-signin.d.ts +32 -0
  47. package/dist/oidc-signin.d.ts.map +1 -0
  48. package/dist/oidc-signin.js +138 -0
  49. package/dist/oidc-signin.js.map +1 -0
  50. package/dist/registry-consumer.d.ts +104 -0
  51. package/dist/registry-consumer.d.ts.map +1 -0
  52. package/dist/registry-consumer.js +230 -0
  53. package/dist/registry-consumer.js.map +1 -0
  54. package/dist/registry.d.ts +5 -0
  55. package/dist/registry.d.ts.map +1 -1
  56. package/dist/registry.js +76 -4
  57. package/dist/registry.js.map +1 -1
  58. package/dist/secret-collection.d.ts.map +1 -1
  59. package/dist/secret-collection.js.map +1 -1
  60. package/dist/server.d.ts +3 -0
  61. package/dist/server.d.ts.map +1 -1
  62. package/dist/server.js +222 -27
  63. package/dist/server.js.map +1 -1
  64. package/dist/test-utils/mock-oidc-server.d.ts +36 -0
  65. package/dist/test-utils/mock-oidc-server.d.ts.map +1 -0
  66. package/dist/test-utils/mock-oidc-server.js +96 -0
  67. package/dist/test-utils/mock-oidc-server.js.map +1 -0
  68. package/dist/types.d.ts +106 -0
  69. package/dist/types.d.ts.map +1 -1
  70. package/package.json +6 -1
  71. package/src/agent-definitions/auth.ts +106 -38
  72. package/src/agent-definitions/integrations.ts +201 -73
  73. package/src/agent-definitions/remote-registry.ts +262 -65
  74. package/src/agent-definitions/secrets.ts +22 -8
  75. package/src/agent-definitions/users.ts +16 -4
  76. package/src/cli.ts +293 -0
  77. package/src/codegen.test.ts +527 -0
  78. package/src/codegen.ts +1348 -0
  79. package/src/consumer.test.ts +536 -0
  80. package/src/define-config.ts +205 -0
  81. package/src/define.ts +134 -46
  82. package/src/events.ts +237 -0
  83. package/src/index.ts +107 -8
  84. package/src/integration-interface.ts +52 -28
  85. package/src/integrations-store.ts +9 -5
  86. package/src/jwt.ts +48 -19
  87. package/src/key-manager.test.ts +22 -13
  88. package/src/key-manager.ts +8 -10
  89. package/src/oidc-signin.ts +223 -0
  90. package/src/registry-consumer.ts +413 -0
  91. package/src/registry.ts +115 -9
  92. package/src/secret-collection.ts +2 -1
  93. package/src/server.test.ts +304 -238
  94. package/src/server.ts +371 -69
  95. package/src/test-utils/mock-oidc-server.ts +123 -0
  96. package/src/types.ts +172 -18
@@ -24,7 +24,10 @@
24
24
  */
25
25
 
26
26
  import { defineAgent, defineTool } from "../define.js";
27
- import { pendingCollections, generateCollectionToken } from "../secret-collection.js";
27
+ import {
28
+ generateCollectionToken,
29
+ pendingCollections,
30
+ } from "../secret-collection.js";
28
31
  import type { AgentDefinition, ToolContext, ToolDefinition } from "../types.js";
29
32
 
30
33
  // ============================================
@@ -135,9 +138,7 @@ export interface GraphqlCallInput {
135
138
  variables?: Record<string, unknown>;
136
139
  }
137
140
 
138
- export type IntegrationCallInput =
139
- | RestCallInput
140
- | GraphqlCallInput;
141
+ export type IntegrationCallInput = RestCallInput | GraphqlCallInput;
141
142
 
142
143
  // ============================================
143
144
  // User Connection (stored token)
@@ -343,9 +344,16 @@ export async function exchangeCodeForToken(
343
344
  }
344
345
 
345
346
  const responseText = await response.text();
346
- console.log("[token-exchange] Slack response:", responseText.substring(0, 500));
347
+ console.log(
348
+ "[token-exchange] Slack response:",
349
+ responseText.substring(0, 500),
350
+ );
347
351
  let data: Record<string, unknown>;
348
- try { data = JSON.parse(responseText); } catch (e) { throw new Error(`Failed to parse JSON: ${responseText.substring(0, 200)}`); }
352
+ try {
353
+ data = JSON.parse(responseText);
354
+ } catch (e) {
355
+ throw new Error(`Failed to parse JSON: ${responseText.substring(0, 200)}`);
356
+ }
349
357
 
350
358
  return {
351
359
  accessToken: String(data[oauth.accessTokenField ?? "access_token"] ?? ""),
@@ -412,9 +420,16 @@ export async function refreshAccessToken(
412
420
  }
413
421
 
414
422
  const responseText = await response.text();
415
- console.log("[token-exchange] Slack response:", responseText.substring(0, 500));
423
+ console.log(
424
+ "[token-exchange] Slack response:",
425
+ responseText.substring(0, 500),
426
+ );
416
427
  let data: Record<string, unknown>;
417
- try { data = JSON.parse(responseText); } catch (e) { throw new Error(`Failed to parse JSON: ${responseText.substring(0, 200)}`); }
428
+ try {
429
+ data = JSON.parse(responseText);
430
+ } catch (e) {
431
+ throw new Error(`Failed to parse JSON: ${responseText.substring(0, 200)}`);
432
+ }
418
433
 
419
434
  return {
420
435
  accessToken: String(data[oauth.accessTokenField ?? "access_token"] ?? ""),
@@ -476,7 +491,8 @@ async function executeGraphqlCall(
476
491
  ...(config.api?.defaultHeaders ?? {}),
477
492
  };
478
493
 
479
- if (!config.api?.baseUrl) throw new Error("No baseUrl configured for this provider");
494
+ if (!config.api?.baseUrl)
495
+ throw new Error("No baseUrl configured for this provider");
480
496
  const response = await fetch(config.api.baseUrl, {
481
497
  method: "POST",
482
498
  headers,
@@ -502,7 +518,6 @@ export interface IntegrationsAgentOptions {
502
518
  call(request: any): Promise<any>;
503
519
  };
504
520
 
505
-
506
521
  /** Secret store for storing/resolving client credentials and tokens */
507
522
  secretStore: {
508
523
  store(value: string, ownerId: string): Promise<string>;
@@ -517,13 +532,10 @@ export interface IntegrationsAgentOptions {
517
532
  callbackBaseUrl?: string;
518
533
  }
519
534
 
520
-
521
535
  // ============================================
522
536
  // Credential Storage Helpers
523
537
  // ============================================
524
538
 
525
-
526
-
527
539
  const SYSTEM_OWNER = "__integrations__";
528
540
 
529
541
  // ============================================
@@ -553,7 +565,8 @@ export function createIntegrationsAgent(
553
565
  name: { type: "string", description: "Display name" },
554
566
  agentPath: {
555
567
  type: "string",
556
- description: "Agent path that handles this integration (e.g. '@remote-registry', '@databases'). Omit for simple REST/GraphQL integrations.",
568
+ description:
569
+ "Agent path that handles this integration (e.g. '@remote-registry', '@databases'). Omit for simple REST/GraphQL integrations.",
557
570
  },
558
571
  scope: {
559
572
  type: "string",
@@ -649,7 +662,8 @@ export function createIntegrationsAgent(
649
662
  clientSecret: {
650
663
  secret: true,
651
664
  type: "string",
652
- description: "OAuth client secret for this provider. Stored encrypted.",
665
+ description:
666
+ "OAuth client secret for this provider. Stored encrypted.",
653
667
  },
654
668
  },
655
669
  required: ["id", "name", "type", "api"],
@@ -672,7 +686,10 @@ export function createIntegrationsAgent(
672
686
  result.clientIdStored = true;
673
687
  }
674
688
  if (input.clientSecret) {
675
- const secretId = await secretStore.store(input.clientSecret, SYSTEM_OWNER);
689
+ const secretId = await secretStore.store(
690
+ input.clientSecret,
691
+ SYSTEM_OWNER,
692
+ );
676
693
  (config as any)._clientSecretSecretId = secretId;
677
694
  result.clientSecretStored = true;
678
695
  }
@@ -683,11 +700,11 @@ export function createIntegrationsAgent(
683
700
  if (config.agentPath && options.registry) {
684
701
  try {
685
702
  const setupResult = await options.registry.call({
686
- action: 'execute_tool',
703
+ action: "execute_tool",
687
704
  path: config.agentPath,
688
- tool: 'setup_integration',
705
+ tool: "setup_integration",
689
706
  params: input.config ?? input,
690
- callerType: 'system',
707
+ callerType: "system",
691
708
  });
692
709
  result.setupResult = (setupResult as any)?.result ?? setupResult;
693
710
  } catch (err) {
@@ -700,7 +717,6 @@ export function createIntegrationsAgent(
700
717
  },
701
718
  });
702
719
 
703
-
704
720
  // ---- discover_integrations ----
705
721
  const discoverTool = defineTool({
706
722
  name: "discover_integrations",
@@ -714,11 +730,13 @@ export function createIntegrationsAgent(
714
730
  properties: {
715
731
  query: {
716
732
  type: "string",
717
- description: "Search query to filter integrations by name or description",
733
+ description:
734
+ "Search query to filter integrations by name or description",
718
735
  },
719
736
  category: {
720
737
  type: "string",
721
- description: "Filter by category (e.g. 'infrastructure', 'communication')",
738
+ description:
739
+ "Filter by category (e.g. 'infrastructure', 'communication')",
722
740
  },
723
741
  },
724
742
  },
@@ -740,7 +758,7 @@ export function createIntegrationsAgent(
740
758
 
741
759
  // 1. Agent-backed integrations
742
760
  if (options.registry) {
743
- for (const agent of (options.registry.list?.() ?? [])) {
761
+ for (const agent of options.registry.list?.() ?? []) {
744
762
  if (agent.config?.integration) {
745
763
  const ic = agent.config.integration;
746
764
  catalog.push({
@@ -838,7 +856,9 @@ export function createIntegrationsAgent(
838
856
  if (options.registry) {
839
857
  const agents = options.registry.list?.() ?? [];
840
858
  for (const agent of agents) {
841
- const hasListTool = agent.tools?.some((t: any) => t.name === 'list_integrations');
859
+ const hasListTool = agent.tools?.some(
860
+ (t: any) => t.name === "list_integrations",
861
+ );
842
862
  if (hasListTool && agent.config?.integration) {
843
863
  const meta = {
844
864
  provider: agent.config.integration.provider,
@@ -849,17 +869,30 @@ export function createIntegrationsAgent(
849
869
  description: agent.config.integration.description,
850
870
  };
851
871
  try {
852
- const callResult = options.registry ? await options.registry.call({ action: 'execute_tool', path: agent.path!, tool: 'list_integrations', params: {}, callerType: 'system' }) : null;
853
- const result = (callResult as any)?.result ?? callResult ?? { success: false };
872
+ const callResult = options.registry
873
+ ? await options.registry.call({
874
+ action: "execute_tool",
875
+ path: agent.path!,
876
+ tool: "list_integrations",
877
+ params: {},
878
+ callerType: "system",
879
+ })
880
+ : null;
881
+ const result = (callResult as any)?.result ??
882
+ callResult ?? { success: false };
854
883
  if (result.success && result.data) {
855
884
  // Flatten: if data has an array field, each item becomes an integration
856
885
  const items = Array.isArray(result.data)
857
886
  ? result.data
858
- : Object.values(result.data as Record<string, unknown>).find(Array.isArray) as unknown[] ?? [];
887
+ : ((Object.values(
888
+ result.data as Record<string, unknown>,
889
+ ).find(Array.isArray) as unknown[]) ?? []);
859
890
  for (const item of items) {
860
891
  integrations.push({
861
892
  ...meta,
862
- ...(typeof item === "object" && item !== null ? item as Record<string, unknown> : { value: item }),
893
+ ...(typeof item === "object" && item !== null
894
+ ? (item as Record<string, unknown>)
895
+ : { value: item }),
863
896
  });
864
897
  }
865
898
  // If no items found but agent exists, include it as a provider entry
@@ -929,7 +962,12 @@ export function createIntegrationsAgent(
929
962
  required: ["provider"],
930
963
  },
931
964
  execute: async (
932
- input: { provider: string; userId?: string; state?: string; redirectUrl?: string },
965
+ input: {
966
+ provider: string;
967
+ userId?: string;
968
+ state?: string;
969
+ redirectUrl?: string;
970
+ },
933
971
  ctx: ToolContext,
934
972
  ) => {
935
973
  const config = await store.getProvider(input.provider);
@@ -938,11 +976,11 @@ export function createIntegrationsAgent(
938
976
  // Delegate to agent's connect_integration tool via registry.call()
939
977
  if (config.agentPath && options.registry) {
940
978
  const connectResult = await options.registry.call({
941
- action: 'execute_tool',
979
+ action: "execute_tool",
942
980
  path: config.agentPath,
943
- tool: 'connect_integration',
981
+ tool: "connect_integration",
944
982
  params: { ...input, registryId: config.id },
945
- callerType: 'system',
983
+ callerType: "system",
946
984
  });
947
985
  return (connectResult as any)?.result ?? connectResult;
948
986
  }
@@ -965,7 +1003,11 @@ export function createIntegrationsAgent(
965
1003
  clientId = await secretStore.resolve(cidSecretId, SYSTEM_OWNER);
966
1004
  }
967
1005
  // Also check if auth config has clientId as a secret:ref
968
- if (!clientId && (oauth as any).clientId && typeof (oauth as any).clientId === "string") {
1006
+ if (
1007
+ !clientId &&
1008
+ (oauth as any).clientId &&
1009
+ typeof (oauth as any).clientId === "string"
1010
+ ) {
969
1011
  if ((oauth as any).clientId.startsWith("secret:") && secretStore) {
970
1012
  const refId = (oauth as any).clientId.slice("secret:".length);
971
1013
  clientId = await secretStore.resolve(refId, SYSTEM_OWNER);
@@ -976,8 +1018,15 @@ export function createIntegrationsAgent(
976
1018
  // Check top-level config too
977
1019
  if (!clientId && (config as any).clientId) {
978
1020
  const cid = (config as any).clientId;
979
- if (typeof cid === "string" && cid.startsWith("secret:") && secretStore) {
980
- clientId = await secretStore.resolve(cid.slice("secret:".length), SYSTEM_OWNER);
1021
+ if (
1022
+ typeof cid === "string" &&
1023
+ cid.startsWith("secret:") &&
1024
+ secretStore
1025
+ ) {
1026
+ clientId = await secretStore.resolve(
1027
+ cid.slice("secret:".length),
1028
+ SYSTEM_OWNER,
1029
+ );
981
1030
  } else if (typeof cid === "string" && !cid.startsWith("secret:")) {
982
1031
  clientId = cid;
983
1032
  }
@@ -996,7 +1045,15 @@ export function createIntegrationsAgent(
996
1045
  redirect_uri: redirectUri,
997
1046
  response_type: "code",
998
1047
  ...(scopeStr ? { scope: scopeStr } : {}),
999
- state: input.state ?? btoa(JSON.stringify({ userId, providerId: config.id, redirectUrl: input.redirectUrl ?? "/" })),
1048
+ state:
1049
+ input.state ??
1050
+ btoa(
1051
+ JSON.stringify({
1052
+ userId,
1053
+ providerId: config.id,
1054
+ redirectUrl: input.redirectUrl ?? "/",
1055
+ }),
1056
+ ),
1000
1057
  ...(oauth.authUrlExtraParams ?? {}),
1001
1058
  });
1002
1059
 
@@ -1081,12 +1138,16 @@ export function createIntegrationsAgent(
1081
1138
  const rCidId = (config as any)._clientIdSecretId;
1082
1139
  const rCsecId = (config as any)._clientSecretSecretId;
1083
1140
  if (!rCidId || !rCsecId) {
1084
- throw new Error("No client credentials stored. Re-run setup_integration with clientId/clientSecret.");
1141
+ throw new Error(
1142
+ "No client credentials stored. Re-run setup_integration with clientId/clientSecret.",
1143
+ );
1085
1144
  }
1086
1145
  const clientId = await secretStore.resolve(rCidId, SYSTEM_OWNER);
1087
1146
  const clientSecret = await secretStore.resolve(rCsecId, SYSTEM_OWNER);
1088
1147
  if (!clientId || !clientSecret) {
1089
- throw new Error("Failed to resolve client credentials from secret store.");
1148
+ throw new Error(
1149
+ "Failed to resolve client credentials from secret store.",
1150
+ );
1090
1151
  }
1091
1152
 
1092
1153
  const refreshed = await refreshAccessToken(
@@ -1143,7 +1204,9 @@ export function createIntegrationsAgent(
1143
1204
  );
1144
1205
 
1145
1206
  default:
1146
- return { error: `Unknown call type: ${input.type}. Use 'rest' or 'graphql'.` };
1207
+ return {
1208
+ error: `Unknown call type: ${input.type}. Use 'rest' or 'graphql'.`,
1209
+ };
1147
1210
  }
1148
1211
  },
1149
1212
  });
@@ -1180,11 +1243,11 @@ export function createIntegrationsAgent(
1180
1243
  // Delegate to agent's connect_integration tool via registry.call()
1181
1244
  if (config.agentPath && options.registry) {
1182
1245
  const connectResult = await options.registry.call({
1183
- action: 'execute_tool',
1246
+ action: "execute_tool",
1184
1247
  path: config.agentPath,
1185
- tool: 'connect_integration',
1248
+ tool: "connect_integration",
1186
1249
  params: { ...input, registryId: config.id },
1187
- callerType: 'system',
1250
+ callerType: "system",
1188
1251
  });
1189
1252
  return (connectResult as any)?.result ?? connectResult;
1190
1253
  }
@@ -1260,19 +1323,48 @@ export function createIntegrationsAgent(
1260
1323
  inputSchema: {
1261
1324
  type: "object" as const,
1262
1325
  properties: {
1263
- agent: { type: "string", description: "Target agent path (e.g. '@databases')" },
1264
- tool: { type: "string", description: "Target tool name (e.g. 'add_connection')" },
1265
- params: { type: "object", description: "Partial params already collected" },
1266
- registry: { type: "string", description: "Remote registry URL. Omit for local." },
1326
+ agent: {
1327
+ type: "string",
1328
+ description: "Target agent path (e.g. '@databases')",
1329
+ },
1330
+ tool: {
1331
+ type: "string",
1332
+ description: "Target tool name (e.g. 'add_connection')",
1333
+ },
1334
+ params: {
1335
+ type: "object",
1336
+ description: "Partial params already collected",
1337
+ },
1338
+ registry: {
1339
+ type: "string",
1340
+ description: "Remote registry URL. Omit for local.",
1341
+ },
1267
1342
  source: {
1268
1343
  type: "object",
1269
- description: "Where to render the form. Determines form delivery method.",
1344
+ description:
1345
+ "Where to render the form. Determines form delivery method.",
1270
1346
  properties: {
1271
- type: { type: "string", enum: ["slack", "web", "cli"], description: "Platform type" },
1272
- workspace: { type: "string", description: "Slack workspace ID (for slack)" },
1273
- channel: { type: "string", description: "Slack channel ID (for slack)" },
1274
- threadTs: { type: "string", description: "Slack thread timestamp (for slack)" },
1275
- redirectUrl: { type: "string", description: "URL to redirect after submission (for web)" },
1347
+ type: {
1348
+ type: "string",
1349
+ enum: ["slack", "web", "cli"],
1350
+ description: "Platform type",
1351
+ },
1352
+ workspace: {
1353
+ type: "string",
1354
+ description: "Slack workspace ID (for slack)",
1355
+ },
1356
+ channel: {
1357
+ type: "string",
1358
+ description: "Slack channel ID (for slack)",
1359
+ },
1360
+ threadTs: {
1361
+ type: "string",
1362
+ description: "Slack thread timestamp (for slack)",
1363
+ },
1364
+ redirectUrl: {
1365
+ type: "string",
1366
+ description: "URL to redirect after submission (for web)",
1367
+ },
1276
1368
  },
1277
1369
  required: ["type"],
1278
1370
  },
@@ -1280,26 +1372,45 @@ export function createIntegrationsAgent(
1280
1372
  required: ["agent", "tool"],
1281
1373
  },
1282
1374
  execute: async (
1283
- input: { agent: string; tool: string; params?: Record<string, unknown>; registry?: string; source?: { type: string; workspace?: string; channel?: string; threadTs?: string; redirectUrl?: string } },
1375
+ input: {
1376
+ agent: string;
1377
+ tool: string;
1378
+ params?: Record<string, unknown>;
1379
+ registry?: string;
1380
+ source?: {
1381
+ type: string;
1382
+ workspace?: string;
1383
+ channel?: string;
1384
+ threadTs?: string;
1385
+ redirectUrl?: string;
1386
+ };
1387
+ },
1284
1388
  ctx: ToolContext,
1285
1389
  ) => {
1286
1390
  // Fetch tool schema from registry
1287
- let toolSchema: { name: string; inputSchema?: any; description?: string } | null = null;
1391
+ let toolSchema: {
1392
+ name: string;
1393
+ inputSchema?: any;
1394
+ description?: string;
1395
+ } | null = null;
1288
1396
  const registryUrl = input.registry;
1289
1397
 
1290
1398
  if (!registryUrl) {
1291
1399
  return { error: "Registry URL required for now. Pass registry param." };
1292
1400
  }
1293
1401
 
1294
- const res = await fetch(registryUrl + "/mcp", {
1402
+ const res = await fetch(`${registryUrl}/mcp`, {
1295
1403
  method: "POST",
1296
1404
  headers: { "Content-Type": "application/json" },
1297
1405
  body: JSON.stringify({
1298
- jsonrpc: "2.0", id: 1,
1406
+ jsonrpc: "2.0",
1407
+ id: 1,
1299
1408
  method: "tools/call",
1300
1409
  params: {
1301
1410
  name: "call_agent",
1302
- arguments: { request: { action: "describe_tools", path: input.agent } },
1411
+ arguments: {
1412
+ request: { action: "describe_tools", path: input.agent },
1413
+ },
1303
1414
  },
1304
1415
  }),
1305
1416
  });
@@ -1319,7 +1430,11 @@ export function createIntegrationsAgent(
1319
1430
 
1320
1431
  // Compute fields: secret fields always, required fields if not provided
1321
1432
  const fields: Array<{
1322
- name: string; type: string; description: string; secret: boolean; required: boolean;
1433
+ name: string;
1434
+ type: string;
1435
+ description: string;
1436
+ secret: boolean;
1437
+ required: boolean;
1323
1438
  }> = [];
1324
1439
 
1325
1440
  for (const [name, def] of Object.entries(properties) as [string, any][]) {
@@ -1338,7 +1453,10 @@ export function createIntegrationsAgent(
1338
1453
  }
1339
1454
 
1340
1455
  if (fields.length === 0) {
1341
- return { message: "All fields provided. Call the tool directly.", canCallDirectly: true };
1456
+ return {
1457
+ message: "All fields provided. Call the tool directly.",
1458
+ canCallDirectly: true,
1459
+ };
1342
1460
  }
1343
1461
 
1344
1462
  // Register pending collection
@@ -1354,13 +1472,19 @@ export function createIntegrationsAgent(
1354
1472
  isRoot: false,
1355
1473
  },
1356
1474
  fields: fields.map((f) => ({
1357
- name: f.name, description: f.description, secret: f.secret, required: f.required,
1475
+ name: f.name,
1476
+ description: f.description,
1477
+ secret: f.secret,
1478
+ required: f.required,
1358
1479
  })),
1359
1480
  createdAt: Date.now(),
1360
1481
  });
1361
1482
 
1362
1483
  // Build callback URL from callbackBaseUrl
1363
- const baseUrl = callbackBaseUrl?.replace(/\/oauth\/callback$/, "").replace(/\/integrations\/callback$/, "") ?? "";
1484
+ const baseUrl =
1485
+ callbackBaseUrl
1486
+ ?.replace(/\/oauth\/callback$/, "")
1487
+ .replace(/\/integrations\/callback$/, "") ?? "";
1364
1488
 
1365
1489
  return {
1366
1490
  url: `${baseUrl}/secrets/form/${token}`,
@@ -1370,11 +1494,11 @@ export function createIntegrationsAgent(
1370
1494
  },
1371
1495
  });
1372
1496
 
1373
-
1374
1497
  // ---- Facade: discover_integrations (aggregates from all agents) ----
1375
1498
  const discoverFacadeTool = defineTool({
1376
1499
  name: "discover_integrations",
1377
- description: "Discover all available integrations across all registered agents.",
1500
+ description:
1501
+ "Discover all available integrations across all registered agents.",
1378
1502
  visibility: "public" as const,
1379
1503
  inputSchema: { type: "object" as const, properties: {} },
1380
1504
  execute: async () => {
@@ -1382,16 +1506,18 @@ export function createIntegrationsAgent(
1382
1506
  const results: any[] = [];
1383
1507
  if (options.registry) {
1384
1508
  for (const agent of agents) {
1385
- const hasDiscoverTool = agent.tools?.some((t: any) => t.name === 'discover_integrations');
1509
+ const hasDiscoverTool = agent.tools?.some(
1510
+ (t: any) => t.name === "discover_integrations",
1511
+ );
1386
1512
  if (hasDiscoverTool) {
1387
1513
  try {
1388
1514
  const res = await options.registry.call({
1389
- action: 'execute_tool',
1515
+ action: "execute_tool",
1390
1516
  path: agent.path,
1391
- tool: 'discover_integrations',
1517
+ tool: "discover_integrations",
1392
1518
  params: {},
1393
- callerId: '@integrations',
1394
- callerType: 'system',
1519
+ callerId: "@integrations",
1520
+ callerType: "system",
1395
1521
  });
1396
1522
  if (res?.result && Array.isArray(res.result)) {
1397
1523
  results.push(...res.result);
@@ -1423,16 +1549,18 @@ export function createIntegrationsAgent(
1423
1549
  ? agents.filter((a: any) => a.path === input.agent_path)
1424
1550
  : agents;
1425
1551
  for (const agent of targetAgents) {
1426
- const hasListTool = agent.tools?.some((t: any) => t.name === 'list_integrations');
1552
+ const hasListTool = agent.tools?.some(
1553
+ (t: any) => t.name === "list_integrations",
1554
+ );
1427
1555
  if (hasListTool) {
1428
1556
  try {
1429
1557
  const res = await options.registry.call({
1430
- action: 'execute_tool',
1558
+ action: "execute_tool",
1431
1559
  path: agent.path,
1432
- tool: 'list_integrations',
1560
+ tool: "list_integrations",
1433
1561
  params: {},
1434
- callerId: '@integrations',
1435
- callerType: 'system',
1562
+ callerId: "@integrations",
1563
+ callerType: "system",
1436
1564
  });
1437
1565
  if (res?.result && Array.isArray(res.result)) {
1438
1566
  results.push(...res.result);