@slashfi/agents-sdk 0.11.1 → 0.12.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 (41) hide show
  1. package/dist/agent-definitions/auth.d.ts +4 -1
  2. package/dist/agent-definitions/auth.d.ts.map +1 -1
  3. package/dist/agent-definitions/auth.js +48 -3
  4. package/dist/agent-definitions/auth.js.map +1 -1
  5. package/dist/agent-definitions/integrations.d.ts +2 -14
  6. package/dist/agent-definitions/integrations.d.ts.map +1 -1
  7. package/dist/agent-definitions/integrations.js +46 -17
  8. package/dist/agent-definitions/integrations.js.map +1 -1
  9. package/dist/agent-definitions/remote-registry.d.ts +19 -14
  10. package/dist/agent-definitions/remote-registry.d.ts.map +1 -1
  11. package/dist/agent-definitions/remote-registry.js +207 -381
  12. package/dist/agent-definitions/remote-registry.js.map +1 -1
  13. package/dist/agent-definitions/users.d.ts.map +1 -1
  14. package/dist/agent-definitions/users.js +29 -1
  15. package/dist/agent-definitions/users.js.map +1 -1
  16. package/dist/define.d.ts +6 -4
  17. package/dist/define.d.ts.map +1 -1
  18. package/dist/define.js +82 -3
  19. package/dist/define.js.map +1 -1
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/jwt.js +1 -1
  24. package/dist/jwt.js.map +1 -1
  25. package/dist/server.d.ts +42 -5
  26. package/dist/server.d.ts.map +1 -1
  27. package/dist/server.js +223 -62
  28. package/dist/server.js.map +1 -1
  29. package/dist/types.d.ts +53 -1
  30. package/dist/types.d.ts.map +1 -1
  31. package/package.json +1 -1
  32. package/src/agent-definitions/auth.ts +57 -5
  33. package/src/agent-definitions/integrations.ts +51 -26
  34. package/src/agent-definitions/remote-registry.ts +210 -513
  35. package/src/agent-definitions/users.ts +35 -1
  36. package/src/define.ts +98 -6
  37. package/src/index.ts +2 -1
  38. package/src/jwt.ts +1 -1
  39. package/src/server.test.ts +284 -0
  40. package/src/server.ts +331 -75
  41. package/src/types.ts +44 -1
@@ -81,7 +81,7 @@ export interface AuthTenant {
81
81
 
82
82
  export interface AuthStore {
83
83
  /** Create a tenant. */
84
- createTenant(name: string): Promise<{ tenantId: string }>;
84
+ createTenant(name: string, externalRef?: { issuer: string; tenantId: string }): Promise<{ tenantId: string }>;
85
85
 
86
86
  /** Get tenant by ID. */
87
87
  getTenant(tenantId: string): Promise<AuthTenant | null>;
@@ -220,7 +220,7 @@ export function createMemoryAuthStore(): AuthStore {
220
220
  const trustedIssuers = new Set<string>();
221
221
 
222
222
  return {
223
- async createTenant(name) {
223
+ async createTenant(name, _externalRef) {
224
224
  const id = `tenant_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
225
225
  tenants.set(id, { id, name, createdAt: Date.now() });
226
226
  return { tenantId: id };
@@ -368,6 +368,7 @@ export interface CreateAuthAgentOptions {
368
368
 
369
369
  /** Custom auth store. Default: in-memory */
370
370
  store?: AuthStore;
371
+
371
372
  }
372
373
 
373
374
  // ============================================
@@ -406,12 +407,22 @@ export function createAuthAgent(
406
407
  type: "object" as const,
407
408
  properties: {
408
409
  name: { type: "string" as const, description: "Tenant name" },
410
+ externalRef: {
411
+ type: "object" as const,
412
+ description: "Link to a tenant on a remote system (for cross-registry trust)",
413
+ properties: {
414
+ issuer: { type: "string" as const, description: "Issuer URL of the remote system" },
415
+ tenantId: { type: "string" as const, description: "Tenant ID on the remote system" },
416
+ },
417
+ required: ["issuer", "tenantId"],
418
+ },
409
419
  },
410
420
  required: ["name"],
411
421
  },
412
- execute: async (input: { name: string }) => {
413
- const result = await store.createTenant(input.name);
414
- return { tenantId: result.tenantId, name: input.name };
422
+ execute: async (input: { name: string; externalRef?: { issuer: string; tenantId: string } }) => {
423
+ const result = await store.createTenant(input.name, input.externalRef);
424
+ return { tenantId: result.tenantId, name: input.name, externalRef: input.externalRef };
425
+
415
426
  },
416
427
  });
417
428
 
@@ -757,6 +768,46 @@ export function createAuthAgent(
757
768
  },
758
769
  });
759
770
 
771
+
772
+ const exchangeTokenTool = defineTool({
773
+ name: "exchange_token",
774
+ description:
775
+ "Exchange a foreign JWT for a local identity. Verifies the JWT via JWKS, " +
776
+ "resolves the tenant and user to local IDs. If the user is not yet linked, " +
777
+ "returns needsAuth=true with a connect URL for OAuth identity linking.",
778
+ visibility: "public" as const,
779
+ inputSchema: {
780
+ type: "object" as const,
781
+ properties: {
782
+ token: {
783
+ type: "string" as const,
784
+ description: "JWT signed by a trusted issuer",
785
+ },
786
+ connectBaseUrl: {
787
+ type: "string" as const,
788
+ description: "Base URL for the OAuth connect flow (returned in needsAuth response)",
789
+ },
790
+ },
791
+ required: ["token"],
792
+ },
793
+ execute: async (
794
+ _input: { token: string; connectBaseUrl?: string },
795
+ ) => {
796
+ // This tool is a stub — the actual implementation needs:
797
+ // 1. JWT verification (via verifyJwtFromIssuer)
798
+ // 2. Tenant resolution (via tenant_identity table)
799
+ // 3. User resolution (via user_identity table)
800
+ // These depend on the store having identity lookup methods.
801
+ //
802
+ // For now, return the structure so the flow can be wired.
803
+ // The atlas-environments CockroachDB implementation overrides this.
804
+ return {
805
+ error: "exchange_token requires a store with identity resolution support",
806
+ hint: "Override this tool in your environment implementation",
807
+ };
808
+ },
809
+ });
810
+
760
811
  const tools = [
761
812
  createTenantTool,
762
813
  tokenTool,
@@ -769,6 +820,7 @@ export function createAuthAgent(
769
820
  rotateKeysTool,
770
821
  trustIssuerTool,
771
822
  apiKeyTool,
823
+ exchangeTokenTool,
772
824
  ];
773
825
 
774
826
  const agent = defineAgent({
@@ -489,21 +489,13 @@ export interface IntegrationsAgentOptions {
489
489
  store: IntegrationStore;
490
490
 
491
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
492
 
498
493
  /** Registry instance for calling other agents' internal tools */
499
494
  registry?: {
495
+ list?(): AgentDefinition[];
500
496
  call(request: any): Promise<any>;
501
497
  };
502
498
 
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
499
 
508
500
  /** Secret store for storing/resolving client credentials and tokens */
509
501
  secretStore: {
@@ -535,7 +527,7 @@ const SYSTEM_OWNER = "__integrations__";
535
527
  export function createIntegrationsAgent(
536
528
  options: IntegrationsAgentOptions,
537
529
  ): AgentDefinition {
538
- const { store, callbackBaseUrl, secretStore, getAgents, integrationsStore } = options;
530
+ const { store, callbackBaseUrl, secretStore } = options;
539
531
 
540
532
  // ---- setup_integration ----
541
533
  const setupTool = defineTool({
@@ -681,15 +673,20 @@ export function createIntegrationsAgent(
681
673
 
682
674
  await store.upsertProvider(config);
683
675
 
684
- // Also track in integrations table
685
- if (integrationsStore) {
676
+ // Delegate to agent's setup_integration tool via registry.call()
677
+ if (config.agentPath && options.registry) {
686
678
  try {
687
- await integrationsStore.create({
688
- agentPath: config.agentPath ?? `@${config.id}`,
689
- config: { providerId: config.id, ...input },
690
- installedBy: _ctx.callerId,
679
+ const setupResult = await options.registry.call({
680
+ action: 'execute_tool',
681
+ path: config.agentPath,
682
+ tool: 'setup_integration',
683
+ params: input.config ?? input,
684
+ callerType: 'system',
691
685
  });
692
- } catch {}
686
+ result.setupResult = (setupResult as any)?.result ?? setupResult;
687
+ } catch (err) {
688
+ result.setupError = err instanceof Error ? err.message : String(err);
689
+ }
693
690
  }
694
691
 
695
692
  result.provider = config;
@@ -736,8 +733,8 @@ export function createIntegrationsAgent(
736
733
  }> = [];
737
734
 
738
735
  // 1. Agent-backed integrations
739
- if (getAgents) {
740
- for (const agent of getAgents()) {
736
+ if (options.registry) {
737
+ for (const agent of (options.registry.list?.() ?? [])) {
741
738
  if (agent.config?.integration) {
742
739
  const ic = agent.config.integration;
743
740
  catalog.push({
@@ -831,11 +828,12 @@ export function createIntegrationsAgent(
831
828
  });
832
829
  }
833
830
 
834
- // 2. Agent-backed integrations (agents with config.integration + integrationMethods)
835
- if (getAgents) {
836
- const agents = getAgents();
831
+ // 2. Agent-backed integrations (agents with config.integration + list_integrations tool)
832
+ if (options.registry) {
833
+ const agents = options.registry.list?.() ?? [];
837
834
  for (const agent of agents) {
838
- if (agent.integrationMethods?.list && agent.config?.integration) {
835
+ const hasListTool = agent.tools?.some((t: any) => t.name === 'list_integrations');
836
+ if (hasListTool && agent.config?.integration) {
839
837
  const meta = {
840
838
  provider: agent.config.integration.provider,
841
839
  agentPath: agent.path,
@@ -845,7 +843,8 @@ export function createIntegrationsAgent(
845
843
  description: agent.config.integration.description,
846
844
  };
847
845
  try {
848
- const result = await agent.integrationMethods.list({}, { ...ctx, provider: agent.config.integration.provider });
846
+ const callResult = options.registry ? await options.registry.call({ action: 'execute_tool', path: agent.path!, tool: 'list_integrations', params: {}, callerType: 'system' }) : null;
847
+ const result = (callResult as any)?.result ?? callResult ?? { success: false };
849
848
  if (result.success && result.data) {
850
849
  // Flatten: if data has an array field, each item becomes an integration
851
850
  const items = Array.isArray(result.data)
@@ -929,6 +928,19 @@ export function createIntegrationsAgent(
929
928
  ) => {
930
929
  const config = await store.getProvider(input.provider);
931
930
  if (!config) return { error: `Provider '${input.provider}' not found` };
931
+
932
+ // Delegate to agent's connect_integration tool via registry.call()
933
+ if (config.agentPath && options.registry) {
934
+ const connectResult = await options.registry.call({
935
+ action: 'execute_tool',
936
+ path: config.agentPath,
937
+ tool: 'connect_integration',
938
+ params: { ...input, registryId: config.id },
939
+ callerType: 'system',
940
+ });
941
+ return (connectResult as any)?.result ?? connectResult;
942
+ }
943
+
932
944
  if (!config.auth)
933
945
  return { error: `Provider '${input.provider}' has no OAuth config` };
934
946
  if (!callbackBaseUrl)
@@ -1158,6 +1170,19 @@ export function createIntegrationsAgent(
1158
1170
  ) => {
1159
1171
  const config = await store.getProvider(input.provider);
1160
1172
  if (!config) return { error: `Provider '${input.provider}' not found` };
1173
+
1174
+ // Delegate to agent's connect_integration tool via registry.call()
1175
+ if (config.agentPath && options.registry) {
1176
+ const connectResult = await options.registry.call({
1177
+ action: 'execute_tool',
1178
+ path: config.agentPath,
1179
+ tool: 'connect_integration',
1180
+ params: { ...input, registryId: config.id },
1181
+ callerType: 'system',
1182
+ });
1183
+ return (connectResult as any)?.result ?? connectResult;
1184
+ }
1185
+
1161
1186
  if (!config.auth)
1162
1187
  return { error: `Provider '${input.provider}' has no OAuth config` };
1163
1188
  if (!callbackBaseUrl) return { error: "No callbackBaseUrl configured" };
@@ -1347,7 +1372,7 @@ export function createIntegrationsAgent(
1347
1372
  visibility: "public" as const,
1348
1373
  inputSchema: { type: "object" as const, properties: {} },
1349
1374
  execute: async () => {
1350
- const agents = getAgents?.() ?? [];
1375
+ const agents = options.registry?.list?.() ?? [];
1351
1376
  const results: any[] = [];
1352
1377
  if (options.registry) {
1353
1378
  for (const agent of agents) {
@@ -1385,7 +1410,7 @@ export function createIntegrationsAgent(
1385
1410
  },
1386
1411
  },
1387
1412
  execute: async (input: { agent_path?: string }) => {
1388
- const agents = getAgents?.() ?? [];
1413
+ const agents = options.registry?.list?.() ?? [];
1389
1414
  const results: any[] = [];
1390
1415
  if (options.registry) {
1391
1416
  const targetAgents = input.agent_path