@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.
- package/dist/agent-definitions/auth.d.ts.map +1 -1
- package/dist/agent-definitions/auth.js +44 -11
- package/dist/agent-definitions/auth.js.map +1 -1
- package/dist/agent-definitions/integrations.d.ts.map +1 -1
- package/dist/agent-definitions/integrations.js +106 -45
- package/dist/agent-definitions/integrations.js.map +1 -1
- package/dist/agent-definitions/remote-registry.d.ts.map +1 -1
- package/dist/agent-definitions/remote-registry.js +174 -45
- package/dist/agent-definitions/remote-registry.js.map +1 -1
- package/dist/agent-definitions/secrets.d.ts.map +1 -1
- package/dist/agent-definitions/secrets.js +1 -4
- package/dist/agent-definitions/secrets.js.map +1 -1
- package/dist/agent-definitions/users.d.ts.map +1 -1
- package/dist/agent-definitions/users.js +14 -3
- package/dist/agent-definitions/users.js.map +1 -1
- package/dist/define-config.d.ts +125 -0
- package/dist/define-config.d.ts.map +1 -0
- package/dist/define-config.js +75 -0
- package/dist/define-config.js.map +1 -0
- package/dist/define.d.ts +11 -2
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +57 -26
- package/dist/define.js.map +1 -1
- package/dist/events.d.ts +133 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +57 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/dist/integration-interface.d.ts +3 -3
- package/dist/integration-interface.d.ts.map +1 -1
- package/dist/integration-interface.js +29 -21
- package/dist/integration-interface.js.map +1 -1
- package/dist/integrations-store.d.ts +2 -2
- package/dist/integrations-store.d.ts.map +1 -1
- package/dist/integrations-store.js +3 -3
- package/dist/integrations-store.js.map +1 -1
- package/dist/jwt.d.ts.map +1 -1
- package/dist/jwt.js +7 -5
- package/dist/jwt.js.map +1 -1
- package/dist/key-manager.d.ts.map +1 -1
- package/dist/key-manager.js +5 -3
- package/dist/key-manager.js.map +1 -1
- package/dist/oidc-signin.d.ts +32 -0
- package/dist/oidc-signin.d.ts.map +1 -0
- package/dist/oidc-signin.js +138 -0
- package/dist/oidc-signin.js.map +1 -0
- package/dist/registry-consumer.d.ts +104 -0
- package/dist/registry-consumer.d.ts.map +1 -0
- package/dist/registry-consumer.js +230 -0
- package/dist/registry-consumer.js.map +1 -0
- package/dist/registry.d.ts +5 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +76 -4
- package/dist/registry.js.map +1 -1
- package/dist/secret-collection.d.ts.map +1 -1
- package/dist/secret-collection.js.map +1 -1
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +222 -27
- package/dist/server.js.map +1 -1
- package/dist/test-utils/mock-oidc-server.d.ts +36 -0
- package/dist/test-utils/mock-oidc-server.d.ts.map +1 -0
- package/dist/test-utils/mock-oidc-server.js +96 -0
- package/dist/test-utils/mock-oidc-server.js.map +1 -0
- package/dist/types.d.ts +106 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/agent-definitions/auth.ts +106 -38
- package/src/agent-definitions/integrations.ts +201 -73
- package/src/agent-definitions/remote-registry.ts +262 -65
- package/src/agent-definitions/secrets.ts +22 -8
- package/src/agent-definitions/users.ts +16 -4
- package/src/cli.ts +293 -0
- package/src/codegen.test.ts +527 -0
- package/src/codegen.ts +1348 -0
- package/src/consumer.test.ts +536 -0
- package/src/define-config.ts +205 -0
- package/src/define.ts +134 -46
- package/src/events.ts +237 -0
- package/src/index.ts +107 -8
- package/src/integration-interface.ts +52 -28
- package/src/integrations-store.ts +9 -5
- package/src/jwt.ts +48 -19
- package/src/key-manager.test.ts +22 -13
- package/src/key-manager.ts +8 -10
- package/src/oidc-signin.ts +223 -0
- package/src/registry-consumer.ts +413 -0
- package/src/registry.ts +115 -9
- package/src/secret-collection.ts +2 -1
- package/src/server.test.ts +304 -238
- package/src/server.ts +371 -69
- package/src/test-utils/mock-oidc-server.ts +123 -0
- package/src/types.ts +172 -18
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import { defineAgent, defineTool } from "../define.js";
|
|
27
|
-
import {
|
|
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(
|
|
347
|
+
console.log(
|
|
348
|
+
"[token-exchange] Slack response:",
|
|
349
|
+
responseText.substring(0, 500),
|
|
350
|
+
);
|
|
347
351
|
let data: Record<string, unknown>;
|
|
348
|
-
try {
|
|
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(
|
|
423
|
+
console.log(
|
|
424
|
+
"[token-exchange] Slack response:",
|
|
425
|
+
responseText.substring(0, 500),
|
|
426
|
+
);
|
|
416
427
|
let data: Record<string, unknown>;
|
|
417
|
-
try {
|
|
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)
|
|
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:
|
|
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:
|
|
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(
|
|
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:
|
|
703
|
+
action: "execute_tool",
|
|
687
704
|
path: config.agentPath,
|
|
688
|
-
tool:
|
|
705
|
+
tool: "setup_integration",
|
|
689
706
|
params: input.config ?? input,
|
|
690
|
-
callerType:
|
|
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:
|
|
733
|
+
description:
|
|
734
|
+
"Search query to filter integrations by name or description",
|
|
718
735
|
},
|
|
719
736
|
category: {
|
|
720
737
|
type: "string",
|
|
721
|
-
description:
|
|
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
|
|
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(
|
|
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
|
|
853
|
-
|
|
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(
|
|
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
|
|
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: {
|
|
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:
|
|
979
|
+
action: "execute_tool",
|
|
942
980
|
path: config.agentPath,
|
|
943
|
-
tool:
|
|
981
|
+
tool: "connect_integration",
|
|
944
982
|
params: { ...input, registryId: config.id },
|
|
945
|
-
callerType:
|
|
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 (
|
|
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 (
|
|
980
|
-
|
|
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:
|
|
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(
|
|
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(
|
|
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 {
|
|
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:
|
|
1246
|
+
action: "execute_tool",
|
|
1184
1247
|
path: config.agentPath,
|
|
1185
|
-
tool:
|
|
1248
|
+
tool: "connect_integration",
|
|
1186
1249
|
params: { ...input, registryId: config.id },
|
|
1187
|
-
callerType:
|
|
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: {
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
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:
|
|
1344
|
+
description:
|
|
1345
|
+
"Where to render the form. Determines form delivery method.",
|
|
1270
1346
|
properties: {
|
|
1271
|
-
type: {
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
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: {
|
|
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: {
|
|
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
|
|
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",
|
|
1406
|
+
jsonrpc: "2.0",
|
|
1407
|
+
id: 1,
|
|
1299
1408
|
method: "tools/call",
|
|
1300
1409
|
params: {
|
|
1301
1410
|
name: "call_agent",
|
|
1302
|
-
arguments: {
|
|
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;
|
|
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 {
|
|
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,
|
|
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 =
|
|
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:
|
|
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(
|
|
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:
|
|
1515
|
+
action: "execute_tool",
|
|
1390
1516
|
path: agent.path,
|
|
1391
|
-
tool:
|
|
1517
|
+
tool: "discover_integrations",
|
|
1392
1518
|
params: {},
|
|
1393
|
-
callerId:
|
|
1394
|
-
callerType:
|
|
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(
|
|
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:
|
|
1558
|
+
action: "execute_tool",
|
|
1431
1559
|
path: agent.path,
|
|
1432
|
-
tool:
|
|
1560
|
+
tool: "list_integrations",
|
|
1433
1561
|
params: {},
|
|
1434
|
-
callerId:
|
|
1435
|
-
callerType:
|
|
1562
|
+
callerId: "@integrations",
|
|
1563
|
+
callerType: "system",
|
|
1436
1564
|
});
|
|
1437
1565
|
if (res?.result && Array.isArray(res.result)) {
|
|
1438
1566
|
results.push(...res.result);
|