@slashfi/agents-sdk 0.7.0 → 0.9.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 +17 -0
- package/dist/agent-definitions/auth.d.ts.map +1 -1
- package/dist/agent-definitions/auth.js +135 -1
- package/dist/agent-definitions/auth.js.map +1 -1
- package/dist/agent-definitions/integrations.d.ts +28 -12
- package/dist/agent-definitions/integrations.d.ts.map +1 -1
- package/dist/agent-definitions/integrations.js +239 -41
- package/dist/agent-definitions/integrations.js.map +1 -1
- package/dist/agent-definitions/remote-registry.d.ts +32 -0
- package/dist/agent-definitions/remote-registry.d.ts.map +1 -0
- package/dist/agent-definitions/remote-registry.js +460 -0
- package/dist/agent-definitions/remote-registry.js.map +1 -0
- package/dist/index.d.ts +12 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/integration-interface.d.ts +37 -0
- package/dist/integration-interface.d.ts.map +1 -0
- package/dist/integration-interface.js +94 -0
- package/dist/integration-interface.js.map +1 -0
- package/dist/integrations-store.d.ts +33 -0
- package/dist/integrations-store.d.ts.map +1 -0
- package/dist/integrations-store.js +50 -0
- package/dist/integrations-store.js.map +1 -0
- package/dist/jwt.d.ts +86 -17
- package/dist/jwt.d.ts.map +1 -1
- package/dist/jwt.js +140 -17
- package/dist/jwt.js.map +1 -1
- package/dist/registry.d.ts +7 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +14 -21
- package/dist/registry.js.map +1 -1
- package/dist/secret-collection.d.ts +37 -0
- package/dist/secret-collection.d.ts.map +1 -0
- package/dist/secret-collection.js +37 -0
- package/dist/secret-collection.js.map +1 -0
- package/dist/server.d.ts +41 -42
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +232 -555
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +24 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -2
- package/src/agent-definitions/auth.ts +187 -1
- package/src/agent-definitions/integrations.ts +287 -55
- package/src/agent-definitions/remote-registry.ts +621 -0
- package/src/index.ts +22 -5
- package/src/integration-interface.ts +118 -0
- package/src/integrations-store.ts +84 -0
- package/src/jwt.ts +233 -65
- package/src/registry.ts +23 -2
- package/src/secret-collection.ts +66 -0
- package/src/server.ts +268 -647
- package/src/types.ts +28 -2
- package/dist/slack-oauth.d.ts +0 -27
- package/dist/slack-oauth.d.ts.map +0 -1
- package/dist/slack-oauth.js +0 -48
- package/dist/slack-oauth.js.map +0 -1
- package/dist/web-pages.d.ts +0 -8
- package/dist/web-pages.d.ts.map +0 -1
- package/dist/web-pages.js +0 -169
- package/dist/web-pages.js.map +0 -1
- package/src/slack-oauth.ts +0 -66
- package/src/web-pages.ts +0 -178
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
* const registry = createAgentRegistry();
|
|
19
19
|
* registry.register(createIntegrationsAgent({
|
|
20
20
|
* store: myIntegrationStore,
|
|
21
|
-
* callbackBaseUrl: 'https://myapp.com/
|
|
21
|
+
* callbackBaseUrl: 'https://myapp.com/oauth/callback',
|
|
22
22
|
* }));
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import { defineAgent, defineTool } from "../define.js";
|
|
27
|
-
import { pendingCollections, generateCollectionToken } from "../
|
|
27
|
+
import { pendingCollections, generateCollectionToken } from "../secret-collection.js";
|
|
28
28
|
import type { AgentDefinition, ToolContext, ToolDefinition } from "../types.js";
|
|
29
29
|
|
|
30
30
|
// ============================================
|
|
@@ -99,7 +99,11 @@ export interface IntegrationApiConfig {
|
|
|
99
99
|
export interface ProviderConfig {
|
|
100
100
|
id: string;
|
|
101
101
|
name: string;
|
|
102
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Agent path that handles this integration type.
|
|
104
|
+
* @integrations dispatches setup/connect/call to that agent's integrationMethods.
|
|
105
|
+
*/
|
|
106
|
+
agentPath: string;
|
|
103
107
|
/**
|
|
104
108
|
* Scope of the integration:
|
|
105
109
|
* - 'user': per-user tokens (Slack, Notion, Linear)
|
|
@@ -108,7 +112,7 @@ export interface ProviderConfig {
|
|
|
108
112
|
scope?: "user" | "tenant";
|
|
109
113
|
docs?: { llmsTxt?: string; human?: string[] };
|
|
110
114
|
auth?: IntegrationOAuthConfig;
|
|
111
|
-
api
|
|
115
|
+
api?: IntegrationApiConfig;
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
// ============================================
|
|
@@ -131,18 +135,9 @@ export interface GraphqlCallInput {
|
|
|
131
135
|
variables?: Record<string, unknown>;
|
|
132
136
|
}
|
|
133
137
|
|
|
134
|
-
export interface AgentRegistryCallInput {
|
|
135
|
-
provider: string;
|
|
136
|
-
type: "agent-registry";
|
|
137
|
-
agent: string;
|
|
138
|
-
tool: string;
|
|
139
|
-
params?: Record<string, unknown>;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
138
|
export type IntegrationCallInput =
|
|
143
139
|
| RestCallInput
|
|
144
|
-
| GraphqlCallInput
|
|
145
|
-
| AgentRegistryCallInput;
|
|
140
|
+
| GraphqlCallInput;
|
|
146
141
|
|
|
147
142
|
// ============================================
|
|
148
143
|
// User Connection (stored token)
|
|
@@ -273,6 +268,7 @@ function buildAuthHeaders(
|
|
|
273
268
|
config: ProviderConfig,
|
|
274
269
|
accessToken: string,
|
|
275
270
|
): Record<string, string> {
|
|
271
|
+
if (!config.api) return {};
|
|
276
272
|
const { auth } = config.api;
|
|
277
273
|
const headerName = auth.headerName ?? "Authorization";
|
|
278
274
|
const prefix = auth.prefix ?? "Bearer";
|
|
@@ -433,7 +429,7 @@ async function executeRestCall(
|
|
|
433
429
|
input: RestCallInput,
|
|
434
430
|
accessToken: string,
|
|
435
431
|
): Promise<unknown> {
|
|
436
|
-
const url = new URL(input.path, config.api
|
|
432
|
+
const url = new URL(input.path, config.api?.baseUrl);
|
|
437
433
|
if (input.query) {
|
|
438
434
|
for (const [k, v] of Object.entries(input.query)) {
|
|
439
435
|
url.searchParams.set(k, v);
|
|
@@ -442,7 +438,7 @@ async function executeRestCall(
|
|
|
442
438
|
|
|
443
439
|
const headers: Record<string, string> = {
|
|
444
440
|
...buildAuthHeaders(config, accessToken),
|
|
445
|
-
...(config.api
|
|
441
|
+
...(config.api?.defaultHeaders ?? {}),
|
|
446
442
|
};
|
|
447
443
|
|
|
448
444
|
if (input.body) {
|
|
@@ -471,9 +467,10 @@ async function executeGraphqlCall(
|
|
|
471
467
|
const headers: Record<string, string> = {
|
|
472
468
|
"Content-Type": "application/json",
|
|
473
469
|
...buildAuthHeaders(config, accessToken),
|
|
474
|
-
...(config.api
|
|
470
|
+
...(config.api?.defaultHeaders ?? {}),
|
|
475
471
|
};
|
|
476
472
|
|
|
473
|
+
if (!config.api?.baseUrl) throw new Error("No baseUrl configured for this provider");
|
|
477
474
|
const response = await fetch(config.api.baseUrl, {
|
|
478
475
|
method: "POST",
|
|
479
476
|
headers,
|
|
@@ -491,6 +488,23 @@ export interface IntegrationsAgentOptions {
|
|
|
491
488
|
/** Integration store backend */
|
|
492
489
|
store: IntegrationStore;
|
|
493
490
|
|
|
491
|
+
/**
|
|
492
|
+
* Callback to list all registered agents.
|
|
493
|
+
* Used by list_integrations to discover agents with integrationMethods.
|
|
494
|
+
* Typically wired to registry.list().
|
|
495
|
+
*/
|
|
496
|
+
getAgents?: () => AgentDefinition[];
|
|
497
|
+
|
|
498
|
+
/** Registry instance for calling other agents' internal tools */
|
|
499
|
+
registry?: {
|
|
500
|
+
call(request: any): Promise<any>;
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
/** Integrations store for tracking installed integrations */
|
|
504
|
+
integrationsStore?: {
|
|
505
|
+
create(input: { agentPath: string; config: Record<string, unknown>; installedBy?: string; tenantId?: string }): Promise<any>;
|
|
506
|
+
};
|
|
507
|
+
|
|
494
508
|
/** Secret store for storing/resolving client credentials and tokens */
|
|
495
509
|
secretStore: {
|
|
496
510
|
store(value: string, ownerId: string): Promise<string>;
|
|
@@ -500,7 +514,7 @@ export interface IntegrationsAgentOptions {
|
|
|
500
514
|
|
|
501
515
|
/**
|
|
502
516
|
* Base URL for OAuth callbacks.
|
|
503
|
-
* The
|
|
517
|
+
* The OAuth redirect_uri. Provider is encoded in the state param.
|
|
504
518
|
*/
|
|
505
519
|
callbackBaseUrl?: string;
|
|
506
520
|
}
|
|
@@ -521,7 +535,7 @@ const SYSTEM_OWNER = "__integrations__";
|
|
|
521
535
|
export function createIntegrationsAgent(
|
|
522
536
|
options: IntegrationsAgentOptions,
|
|
523
537
|
): AgentDefinition {
|
|
524
|
-
const { store, callbackBaseUrl, secretStore } = options;
|
|
538
|
+
const { store, callbackBaseUrl, secretStore, getAgents, integrationsStore } = options;
|
|
525
539
|
|
|
526
540
|
// ---- setup_integration ----
|
|
527
541
|
const setupTool = defineTool({
|
|
@@ -539,10 +553,9 @@ export function createIntegrationsAgent(
|
|
|
539
553
|
description: "Provider ID (e.g. 'linear', 'notion')",
|
|
540
554
|
},
|
|
541
555
|
name: { type: "string", description: "Display name" },
|
|
542
|
-
|
|
556
|
+
agentPath: {
|
|
543
557
|
type: "string",
|
|
544
|
-
|
|
545
|
-
description: "Integration type",
|
|
558
|
+
description: "Agent path that handles this integration (e.g. '@remote-registry', '@databases'). Omit for simple REST/GraphQL integrations.",
|
|
546
559
|
},
|
|
547
560
|
scope: {
|
|
548
561
|
type: "string",
|
|
@@ -647,7 +660,7 @@ export function createIntegrationsAgent(
|
|
|
647
660
|
const config: ProviderConfig = {
|
|
648
661
|
id: input.id,
|
|
649
662
|
name: input.name,
|
|
650
|
-
|
|
663
|
+
agentPath: input.agentPath,
|
|
651
664
|
scope: input.scope,
|
|
652
665
|
docs: input.docs,
|
|
653
666
|
auth: input.auth,
|
|
@@ -667,11 +680,121 @@ export function createIntegrationsAgent(
|
|
|
667
680
|
}
|
|
668
681
|
|
|
669
682
|
await store.upsertProvider(config);
|
|
683
|
+
|
|
684
|
+
// Also track in integrations table
|
|
685
|
+
if (integrationsStore) {
|
|
686
|
+
try {
|
|
687
|
+
await integrationsStore.create({
|
|
688
|
+
agentPath: config.agentPath ?? `@${config.id}`,
|
|
689
|
+
config: { providerId: config.id, ...input },
|
|
690
|
+
installedBy: _ctx.callerId,
|
|
691
|
+
});
|
|
692
|
+
} catch {}
|
|
693
|
+
}
|
|
694
|
+
|
|
670
695
|
result.provider = config;
|
|
671
696
|
return result;
|
|
672
697
|
},
|
|
673
698
|
});
|
|
674
699
|
|
|
700
|
+
|
|
701
|
+
// ---- discover_integrations ----
|
|
702
|
+
const discoverTool = defineTool({
|
|
703
|
+
name: "discover_integrations",
|
|
704
|
+
description:
|
|
705
|
+
"Discover available integration types that can be set up. " +
|
|
706
|
+
"Returns a catalog of integrations with their setup/connect schemas " +
|
|
707
|
+
"so you know what parameters to pass to setup_integration.",
|
|
708
|
+
visibility: "public" as const,
|
|
709
|
+
inputSchema: {
|
|
710
|
+
type: "object" as const,
|
|
711
|
+
properties: {
|
|
712
|
+
query: {
|
|
713
|
+
type: "string",
|
|
714
|
+
description: "Search query to filter integrations by name or description",
|
|
715
|
+
},
|
|
716
|
+
category: {
|
|
717
|
+
type: "string",
|
|
718
|
+
description: "Filter by category (e.g. 'infrastructure', 'communication')",
|
|
719
|
+
},
|
|
720
|
+
},
|
|
721
|
+
},
|
|
722
|
+
execute: async (
|
|
723
|
+
input: { query?: string; category?: string },
|
|
724
|
+
_ctx: ToolContext,
|
|
725
|
+
) => {
|
|
726
|
+
const catalog: Array<{
|
|
727
|
+
provider: string;
|
|
728
|
+
agentPath?: string;
|
|
729
|
+
displayName: string;
|
|
730
|
+
icon?: string;
|
|
731
|
+
category?: string;
|
|
732
|
+
description?: string;
|
|
733
|
+
setupSchema?: Record<string, unknown>;
|
|
734
|
+
connectSchema?: Record<string, unknown>;
|
|
735
|
+
hasOAuth?: boolean;
|
|
736
|
+
}> = [];
|
|
737
|
+
|
|
738
|
+
// 1. Agent-backed integrations
|
|
739
|
+
if (getAgents) {
|
|
740
|
+
for (const agent of getAgents()) {
|
|
741
|
+
if (agent.config?.integration) {
|
|
742
|
+
const ic = agent.config.integration;
|
|
743
|
+
catalog.push({
|
|
744
|
+
provider: ic.provider,
|
|
745
|
+
agentPath: agent.path,
|
|
746
|
+
displayName: ic.displayName,
|
|
747
|
+
icon: ic.icon,
|
|
748
|
+
category: ic.category,
|
|
749
|
+
description: ic.description,
|
|
750
|
+
setupSchema: ic.setupSchema,
|
|
751
|
+
connectSchema: ic.connectSchema,
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// 2. DB-stored providers (legacy OAuth)
|
|
758
|
+
const providers = await store.listProviders();
|
|
759
|
+
for (const p of providers) {
|
|
760
|
+
// Skip if already in catalog from agent scan
|
|
761
|
+
if (catalog.some((c) => c.provider === p.id)) continue;
|
|
762
|
+
catalog.push({
|
|
763
|
+
provider: p.id,
|
|
764
|
+
displayName: p.name,
|
|
765
|
+
agentPath: p.agentPath,
|
|
766
|
+
hasOAuth: !!p.auth,
|
|
767
|
+
connectSchema: p.auth
|
|
768
|
+
? {
|
|
769
|
+
type: "object",
|
|
770
|
+
description: "OAuth flow — use connect_integration to start",
|
|
771
|
+
properties: {
|
|
772
|
+
provider: { type: "string", const: p.id },
|
|
773
|
+
},
|
|
774
|
+
}
|
|
775
|
+
: undefined,
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// 3. Filter
|
|
780
|
+
let results = catalog;
|
|
781
|
+
if (input.query) {
|
|
782
|
+
const q = input.query.toLowerCase();
|
|
783
|
+
results = results.filter(
|
|
784
|
+
(r) =>
|
|
785
|
+
r.provider.toLowerCase().includes(q) ||
|
|
786
|
+
r.displayName.toLowerCase().includes(q) ||
|
|
787
|
+
(r.description?.toLowerCase().includes(q) ?? false),
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
if (input.category) {
|
|
791
|
+
results = results.filter((r) => r.category === input.category);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
return { integrations: results };
|
|
795
|
+
},
|
|
796
|
+
});
|
|
797
|
+
|
|
675
798
|
// ---- list_integrations ----
|
|
676
799
|
const listTool = defineTool({
|
|
677
800
|
name: "list_integrations",
|
|
@@ -692,15 +815,64 @@ export function createIntegrationsAgent(
|
|
|
692
815
|
const userId = input.userId ?? ctx.callerId;
|
|
693
816
|
const connections = userId ? await store.listConnections(userId) : [];
|
|
694
817
|
|
|
695
|
-
|
|
696
|
-
|
|
818
|
+
// Build unified integrations list
|
|
819
|
+
const integrations: Array<Record<string, unknown>> = [];
|
|
820
|
+
|
|
821
|
+
// 1. DB-stored providers (legacy OAuth integrations)
|
|
822
|
+
for (const p of providers) {
|
|
823
|
+
integrations.push({
|
|
697
824
|
id: p.id,
|
|
698
825
|
name: p.name,
|
|
699
|
-
|
|
826
|
+
provider: p.id,
|
|
827
|
+
agentPath: p.agentPath,
|
|
700
828
|
scope: p.scope ?? "user",
|
|
701
829
|
hasOAuth: !!p.auth,
|
|
702
830
|
connected: connections.some((c) => c.providerId === p.id),
|
|
703
|
-
})
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// 2. Agent-backed integrations (agents with config.integration + integrationMethods)
|
|
835
|
+
if (getAgents) {
|
|
836
|
+
const agents = getAgents();
|
|
837
|
+
for (const agent of agents) {
|
|
838
|
+
if (agent.integrationMethods?.list && agent.config?.integration) {
|
|
839
|
+
const meta = {
|
|
840
|
+
provider: agent.config.integration.provider,
|
|
841
|
+
agentPath: agent.path,
|
|
842
|
+
displayName: agent.config.integration.displayName,
|
|
843
|
+
icon: agent.config.integration.icon,
|
|
844
|
+
category: agent.config.integration.category,
|
|
845
|
+
description: agent.config.integration.description,
|
|
846
|
+
};
|
|
847
|
+
try {
|
|
848
|
+
const result = await agent.integrationMethods.list({}, { ...ctx, provider: agent.config.integration.provider });
|
|
849
|
+
if (result.success && result.data) {
|
|
850
|
+
// Flatten: if data has an array field, each item becomes an integration
|
|
851
|
+
const items = Array.isArray(result.data)
|
|
852
|
+
? result.data
|
|
853
|
+
: Object.values(result.data as Record<string, unknown>).find(Array.isArray) as unknown[] ?? [];
|
|
854
|
+
for (const item of items) {
|
|
855
|
+
integrations.push({
|
|
856
|
+
...meta,
|
|
857
|
+
...(typeof item === "object" && item !== null ? item as Record<string, unknown> : { value: item }),
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
// If no items found but agent exists, include it as a provider entry
|
|
861
|
+
if (items.length === 0) {
|
|
862
|
+
integrations.push({ ...meta, id: meta.provider });
|
|
863
|
+
}
|
|
864
|
+
} else {
|
|
865
|
+
integrations.push({ ...meta, id: meta.provider });
|
|
866
|
+
}
|
|
867
|
+
} catch {
|
|
868
|
+
integrations.push({ ...meta, id: meta.provider });
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
return {
|
|
875
|
+
integrations,
|
|
704
876
|
connections: connections.map((c) => ({
|
|
705
877
|
providerId: c.providerId,
|
|
706
878
|
connectedAt: c.connectedAt,
|
|
@@ -763,7 +935,7 @@ export function createIntegrationsAgent(
|
|
|
763
935
|
return { error: "No callbackBaseUrl configured for OAuth flows" };
|
|
764
936
|
|
|
765
937
|
const oauth = config.auth;
|
|
766
|
-
const redirectUri =
|
|
938
|
+
const redirectUri = callbackBaseUrl;
|
|
767
939
|
const userId = input.userId ?? ctx.callerId;
|
|
768
940
|
|
|
769
941
|
// Resolve client ID from secret store
|
|
@@ -806,7 +978,7 @@ export function createIntegrationsAgent(
|
|
|
806
978
|
redirect_uri: redirectUri,
|
|
807
979
|
response_type: "code",
|
|
808
980
|
...(scopeStr ? { scope: scopeStr } : {}),
|
|
809
|
-
state: input.state ?? JSON.stringify({ userId, providerId: config.id, redirectUrl: input.redirectUrl ?? "/" }),
|
|
981
|
+
state: input.state ?? btoa(JSON.stringify({ userId, providerId: config.id, redirectUrl: input.redirectUrl ?? "/" })),
|
|
810
982
|
...(oauth.authUrlExtraParams ?? {}),
|
|
811
983
|
});
|
|
812
984
|
|
|
@@ -831,8 +1003,8 @@ export function createIntegrationsAgent(
|
|
|
831
1003
|
provider: { type: "string", description: "Provider ID" },
|
|
832
1004
|
type: {
|
|
833
1005
|
type: "string",
|
|
834
|
-
enum: ["rest", "graphql"
|
|
835
|
-
description: "Call type",
|
|
1006
|
+
enum: ["rest", "graphql"],
|
|
1007
|
+
description: "Call type (rest or graphql)",
|
|
836
1008
|
},
|
|
837
1009
|
// REST fields
|
|
838
1010
|
method: {
|
|
@@ -924,7 +1096,7 @@ export function createIntegrationsAgent(
|
|
|
924
1096
|
}
|
|
925
1097
|
}
|
|
926
1098
|
|
|
927
|
-
// Execute the call
|
|
1099
|
+
// Execute the call based on type
|
|
928
1100
|
switch (input.type) {
|
|
929
1101
|
case "rest":
|
|
930
1102
|
return executeRestCall(
|
|
@@ -952,27 +1124,8 @@ export function createIntegrationsAgent(
|
|
|
952
1124
|
accessToken,
|
|
953
1125
|
);
|
|
954
1126
|
|
|
955
|
-
case "agent-registry": {
|
|
956
|
-
// For agent-registry, forward the call to the remote agent server
|
|
957
|
-
const baseUrl = config.api.baseUrl;
|
|
958
|
-
const response = await fetch(`${baseUrl}/call`, {
|
|
959
|
-
method: "POST",
|
|
960
|
-
headers: {
|
|
961
|
-
"Content-Type": "application/json",
|
|
962
|
-
...buildAuthHeaders(config, accessToken),
|
|
963
|
-
},
|
|
964
|
-
body: JSON.stringify({
|
|
965
|
-
action: "execute_tool",
|
|
966
|
-
path: input.agent,
|
|
967
|
-
tool: input.tool,
|
|
968
|
-
params: input.params ?? {},
|
|
969
|
-
}),
|
|
970
|
-
});
|
|
971
|
-
return response.json();
|
|
972
|
-
}
|
|
973
|
-
|
|
974
1127
|
default:
|
|
975
|
-
return { error: `Unknown
|
|
1128
|
+
return { error: `Unknown call type: ${input.type}. Use 'rest' or 'graphql'.` };
|
|
976
1129
|
}
|
|
977
1130
|
},
|
|
978
1131
|
});
|
|
@@ -1013,7 +1166,7 @@ export function createIntegrationsAgent(
|
|
|
1013
1166
|
let userId = ctx.callerId;
|
|
1014
1167
|
if (input.state) {
|
|
1015
1168
|
try {
|
|
1016
|
-
const parsed = JSON.parse(input.state);
|
|
1169
|
+
const parsed = JSON.parse(atob(input.state));
|
|
1017
1170
|
if (parsed.userId) userId = parsed.userId;
|
|
1018
1171
|
} catch {}
|
|
1019
1172
|
}
|
|
@@ -1030,7 +1183,7 @@ export function createIntegrationsAgent(
|
|
|
1030
1183
|
return { error: "Failed to resolve client credentials." };
|
|
1031
1184
|
}
|
|
1032
1185
|
|
|
1033
|
-
const redirectUri =
|
|
1186
|
+
const redirectUri = callbackBaseUrl;
|
|
1034
1187
|
const result = await exchangeCodeForToken(
|
|
1035
1188
|
config,
|
|
1036
1189
|
input.code,
|
|
@@ -1059,6 +1212,7 @@ export function createIntegrationsAgent(
|
|
|
1059
1212
|
provider: config.id,
|
|
1060
1213
|
userId,
|
|
1061
1214
|
connectedAt: connection.connectedAt,
|
|
1215
|
+
accessToken: result.accessToken,
|
|
1062
1216
|
};
|
|
1063
1217
|
},
|
|
1064
1218
|
});
|
|
@@ -1175,7 +1329,7 @@ export function createIntegrationsAgent(
|
|
|
1175
1329
|
});
|
|
1176
1330
|
|
|
1177
1331
|
// Build callback URL from callbackBaseUrl
|
|
1178
|
-
const baseUrl = callbackBaseUrl?.replace(/\/integrations\/callback$/, "") ?? "";
|
|
1332
|
+
const baseUrl = callbackBaseUrl?.replace(/\/oauth\/callback$/, "").replace(/\/integrations\/callback$/, "") ?? "";
|
|
1179
1333
|
|
|
1180
1334
|
return {
|
|
1181
1335
|
url: `${baseUrl}/secrets/form/${token}`,
|
|
@@ -1185,6 +1339,81 @@ export function createIntegrationsAgent(
|
|
|
1185
1339
|
},
|
|
1186
1340
|
});
|
|
1187
1341
|
|
|
1342
|
+
|
|
1343
|
+
// ---- Facade: discover_integrations (aggregates from all agents) ----
|
|
1344
|
+
const discoverFacadeTool = defineTool({
|
|
1345
|
+
name: "discover_integrations",
|
|
1346
|
+
description: "Discover all available integrations across all registered agents.",
|
|
1347
|
+
visibility: "public" as const,
|
|
1348
|
+
inputSchema: { type: "object" as const, properties: {} },
|
|
1349
|
+
execute: async () => {
|
|
1350
|
+
const agents = getAgents?.() ?? [];
|
|
1351
|
+
const results: any[] = [];
|
|
1352
|
+
if (options.registry) {
|
|
1353
|
+
for (const agent of agents) {
|
|
1354
|
+
const hasDiscoverTool = agent.tools?.some((t: any) => t.name === 'discover_integrations');
|
|
1355
|
+
if (hasDiscoverTool) {
|
|
1356
|
+
try {
|
|
1357
|
+
const res = await options.registry.call({
|
|
1358
|
+
action: 'execute_tool',
|
|
1359
|
+
path: agent.path,
|
|
1360
|
+
tool: 'discover_integrations',
|
|
1361
|
+
params: {},
|
|
1362
|
+
callerId: '@integrations',
|
|
1363
|
+
callerType: 'system',
|
|
1364
|
+
});
|
|
1365
|
+
if (res?.result && Array.isArray(res.result)) {
|
|
1366
|
+
results.push(...res.result);
|
|
1367
|
+
}
|
|
1368
|
+
} catch {}
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
return results;
|
|
1373
|
+
},
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1376
|
+
// ---- Facade: list_integrations (aggregates from all agents) ----
|
|
1377
|
+
const listFacadeTool = defineTool({
|
|
1378
|
+
name: "list_integrations",
|
|
1379
|
+
description: "List all installed integrations across all agents.",
|
|
1380
|
+
visibility: "public" as const,
|
|
1381
|
+
inputSchema: {
|
|
1382
|
+
type: "object" as const,
|
|
1383
|
+
properties: {
|
|
1384
|
+
agent_path: { type: "string", description: "Filter by agent path" },
|
|
1385
|
+
},
|
|
1386
|
+
},
|
|
1387
|
+
execute: async (input: { agent_path?: string }) => {
|
|
1388
|
+
const agents = getAgents?.() ?? [];
|
|
1389
|
+
const results: any[] = [];
|
|
1390
|
+
if (options.registry) {
|
|
1391
|
+
const targetAgents = input.agent_path
|
|
1392
|
+
? agents.filter((a: any) => a.path === input.agent_path)
|
|
1393
|
+
: agents;
|
|
1394
|
+
for (const agent of targetAgents) {
|
|
1395
|
+
const hasListTool = agent.tools?.some((t: any) => t.name === 'list_integrations');
|
|
1396
|
+
if (hasListTool) {
|
|
1397
|
+
try {
|
|
1398
|
+
const res = await options.registry.call({
|
|
1399
|
+
action: 'execute_tool',
|
|
1400
|
+
path: agent.path,
|
|
1401
|
+
tool: 'list_integrations',
|
|
1402
|
+
params: {},
|
|
1403
|
+
callerId: '@integrations',
|
|
1404
|
+
callerType: 'system',
|
|
1405
|
+
});
|
|
1406
|
+
if (res?.result && Array.isArray(res.result)) {
|
|
1407
|
+
results.push(...res.result);
|
|
1408
|
+
}
|
|
1409
|
+
} catch {}
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
return results;
|
|
1414
|
+
},
|
|
1415
|
+
});
|
|
1416
|
+
|
|
1188
1417
|
return defineAgent({
|
|
1189
1418
|
path: "@integrations",
|
|
1190
1419
|
entrypoint:
|
|
@@ -1198,12 +1427,15 @@ export function createIntegrationsAgent(
|
|
|
1198
1427
|
visibility: "public",
|
|
1199
1428
|
tools: [
|
|
1200
1429
|
setupTool,
|
|
1430
|
+
discoverTool,
|
|
1201
1431
|
listTool,
|
|
1202
1432
|
getTool,
|
|
1203
1433
|
connectTool,
|
|
1204
1434
|
callTool,
|
|
1205
1435
|
callbackTool,
|
|
1206
1436
|
collectSecretsTool,
|
|
1437
|
+
discoverFacadeTool,
|
|
1438
|
+
listFacadeTool,
|
|
1207
1439
|
] as ToolDefinition[],
|
|
1208
1440
|
});
|
|
1209
1441
|
}
|