@slashfi/agents-sdk 0.74.0 → 0.76.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/adk.js +35 -71
  2. package/dist/adk.js.map +1 -1
  3. package/dist/cjs/config-store.js +154 -30
  4. package/dist/cjs/config-store.js.map +1 -1
  5. package/dist/cjs/define-config.js.map +1 -1
  6. package/dist/cjs/index.js.map +1 -1
  7. package/dist/cjs/init.js +1 -1
  8. package/dist/cjs/init.js.map +1 -1
  9. package/dist/cjs/registry-consumer.js +22 -13
  10. package/dist/cjs/registry-consumer.js.map +1 -1
  11. package/dist/cjs/server.js +8 -0
  12. package/dist/cjs/server.js.map +1 -1
  13. package/dist/config-store.d.ts +10 -10
  14. package/dist/config-store.d.ts.map +1 -1
  15. package/dist/config-store.js +154 -30
  16. package/dist/config-store.js.map +1 -1
  17. package/dist/define-config.d.ts +29 -17
  18. package/dist/define-config.d.ts.map +1 -1
  19. package/dist/define-config.js.map +1 -1
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/init.js +1 -1
  24. package/dist/init.js.map +1 -1
  25. package/dist/registry-consumer.d.ts +51 -20
  26. package/dist/registry-consumer.d.ts.map +1 -1
  27. package/dist/registry-consumer.js +22 -13
  28. package/dist/registry-consumer.js.map +1 -1
  29. package/dist/server.d.ts +11 -0
  30. package/dist/server.d.ts.map +1 -1
  31. package/dist/server.js +8 -0
  32. package/dist/server.js.map +1 -1
  33. package/package.json +1 -1
  34. package/src/adk.ts +38 -64
  35. package/src/config-store.test.ts +169 -1
  36. package/src/config-store.ts +189 -47
  37. package/src/define-config.ts +31 -23
  38. package/src/index.ts +3 -2
  39. package/src/init.ts +1 -1
  40. package/src/registry-consumer.ts +95 -44
  41. package/src/server.ts +19 -0
@@ -207,23 +207,26 @@ export interface RegistryConfiguration {
207
207
  jwks_uri?: string;
208
208
  token_endpoint?: string;
209
209
  supported_grant_types?: string[];
210
+ /**
211
+ * When the registry advertises proxy support in its `initialize` response,
212
+ * consumers can auto-populate `RegistryEntry.proxy` at add time so ref ops
213
+ * forward to the server-side adk-tools agent automatically.
214
+ */
215
+ proxy?: {
216
+ mode: "required" | "optional";
217
+ /** Agent path to forward to. Defaults to '@config'. */
218
+ agent?: string;
219
+ };
210
220
  }
211
221
 
212
- /** An agent definition as listed by a registry */
213
- export interface AgentListing {
222
+ /** Fields common to every agent reference a registry can return. */
223
+ export interface AgentBase {
214
224
  /** Agent path (e.g., '@notion') */
215
225
  path: string;
216
226
  /** Description */
217
227
  description?: string;
218
228
  /** Publisher (registry name) */
219
229
  publisher: string;
220
- /** Tools available */
221
- tools?: Array<{
222
- name: string;
223
- description?: string;
224
- }>;
225
- /** Whether it requires auth */
226
- requiresAuth?: boolean;
227
230
  /** Security scheme summary (machine-readable auth type) */
228
231
  security?: SecuritySchemeSummary;
229
232
  /** Available resources (e.g., AUTH.md) */
@@ -232,7 +235,39 @@ export interface AgentListing {
232
235
  name?: string;
233
236
  mimeType?: string;
234
237
  }>;
235
- /** Slim tool summaries (when describe_tools called without full: true) */
238
+ }
239
+
240
+ /**
241
+ * Lightweight agent entry returned by `list_agents` / `consumer.list()` /
242
+ * `consumer.browse()` / `consumer.available()`. Registries emit a `toolCount`
243
+ * instead of the full `tools` array to keep listings small; call `inspect()`
244
+ * to get the per-tool details.
245
+ */
246
+ export interface AgentListEntry extends AgentBase {
247
+ /** Number of tools this agent exposes */
248
+ toolCount?: number;
249
+ /** Whether the agent requires auth (populated only for direct MCP/HTTPS refs) */
250
+ requiresAuth?: boolean;
251
+ /** Integration config if applicable */
252
+ integration?: {
253
+ provider: string;
254
+ displayName: string;
255
+ category?: string;
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Full agent detail returned by `describe_tools` / `consumer.inspect()`.
261
+ * Carries the actual tool definitions (or slim summaries) and extra context
262
+ * the listing endpoint omits.
263
+ */
264
+ export interface AgentInspection extends AgentBase {
265
+ /** Full tool details (returned when `full: true`) */
266
+ tools?: Array<{
267
+ name: string;
268
+ description?: string;
269
+ }>;
270
+ /** Slim tool summaries (returned when `full` is not set) */
236
271
  toolSummaries?: Array<{
237
272
  name: string;
238
273
  description: string;
@@ -242,16 +277,16 @@ export interface AgentListing {
242
277
  context?: string;
243
278
  /** Upstream MCP/API URL for direct connections */
244
279
  upstream?: string;
245
- /** Integration config if applicable */
246
- integration?: {
247
- provider: string;
248
- displayName: string;
249
- category?: string;
250
- };
280
+ /** Agent mode (redirect | proxy | api) */
281
+ mode?: string;
251
282
  }
252
283
 
284
+ /** @deprecated Prefer `AgentListEntry` (for listings) or `AgentInspection` (for inspect results). */
285
+ export type AgentListing = AgentListEntry | AgentInspection;
286
+
253
287
  /** Raw agent entry returned by the list_agents MCP tool (before normalization). */
254
- type ListAgentsEntry = Omit<AgentListing, "publisher" | "tools"> & {
288
+ type ListAgentsEntry = Omit<AgentListEntry, "publisher"> & {
289
+ /** Legacy field — older registries emitted `tools` instead of `toolCount`. */
255
290
  tools?: Array<{ name: string; description?: string } | string>;
256
291
  };
257
292
 
@@ -333,7 +368,7 @@ async function listFromMcpServer(
333
368
  url: string,
334
369
  auth: { token?: string; headers?: Record<string, string> },
335
370
  fetchFn: FetchFn,
336
- ): Promise<AgentListing[]> {
371
+ ): Promise<AgentListEntry[]> {
337
372
  const serverUrl = url.replace(/\/$/, "");
338
373
 
339
374
  const headers: Record<string, string> = {
@@ -383,12 +418,13 @@ async function listFromMcpServer(
383
418
 
384
419
  const serverName = initResult?.serverInfo?.name ?? new URL(serverUrl).hostname;
385
420
 
386
- // Return as a single agent listing with all tools
421
+ // Return as a single agent listing toolCount keeps listings lightweight;
422
+ // callers that need per-tool detail should use `inspect()`.
387
423
  return [{
388
424
  path: serverName,
389
425
  description: `MCP server at ${serverUrl}`,
390
426
  publisher: serverName,
391
- tools: toolsResult?.tools ?? [],
427
+ toolCount: toolsResult?.tools?.length ?? 0,
392
428
  requiresAuth: false,
393
429
  }];
394
430
  }
@@ -446,17 +482,34 @@ async function discoverRegistryViaMcp(
446
482
  clientInfo: { name: "agents-sdk-consumer", version: "1.0.0" },
447
483
  })) as {
448
484
  serverInfo?: { name?: string; version?: string };
485
+ capabilities?: {
486
+ registry?: {
487
+ proxy?: {
488
+ mode?: "required" | "optional";
489
+ agent?: string;
490
+ };
491
+ };
492
+ };
449
493
  };
450
494
 
451
495
  await rpc("notifications/initialized").catch(() => {});
452
496
 
453
497
  const issuer = issuerFromMcpUrlAndServerInfo(serverUrl, initResult?.serverInfo);
454
498
 
499
+ const advertisedProxy = initResult?.capabilities?.registry?.proxy;
500
+ const proxy = advertisedProxy?.mode
501
+ ? {
502
+ mode: advertisedProxy.mode,
503
+ ...(advertisedProxy.agent && { agent: advertisedProxy.agent }),
504
+ }
505
+ : undefined;
506
+
455
507
  return {
456
508
  issuer,
457
509
  jwks_uri: `${issuer}/.well-known/jwks.json`,
458
510
  token_endpoint: `${issuer}/oauth/token`,
459
511
  supported_grant_types: ["client_credentials", "jwt_exchange"],
512
+ ...(proxy && { proxy }),
460
513
  };
461
514
  }
462
515
 
@@ -517,16 +570,14 @@ async function callMcpTool(
517
570
  * Returns a single generic 'call' tool since we can't auto-discover REST endpoints
518
571
  * without an OpenAPI spec.
519
572
  */
520
- function listFromHttpsApi(url: string): AgentListing[] {
573
+ function listFromHttpsApi(url: string): AgentListEntry[] {
521
574
  const hostname = new URL(url).hostname;
522
575
  return [{
523
576
  path: hostname,
524
577
  description: `REST API at ${url}`,
525
578
  publisher: hostname,
526
- tools: [{
527
- name: "call",
528
- description: "Make an HTTP request to the API. Params: method, path, body, headers.",
529
- }],
579
+ // Single generic `call` tool — callers can use `inspect()` for details.
580
+ toolCount: 1,
530
581
  requiresAuth: false,
531
582
  }];
532
583
  }
@@ -598,7 +649,7 @@ export interface RegistryConsumerOptions {
598
649
 
599
650
  export interface RegistryConsumer {
600
651
  /** List all available agents across all connected registries */
601
- list(): Promise<AgentListing[]>;
652
+ list(): Promise<AgentListEntry[]>;
602
653
 
603
654
  /** List configured refs (from the consumer's config) */
604
655
  refs(): ResolvedRef[];
@@ -617,14 +668,14 @@ export interface RegistryConsumer {
617
668
  discover(registryUrl: string): Promise<RegistryConfiguration>;
618
669
 
619
670
  /** Browse agents from a specific registry (or all if url omitted), with optional BM25 search */
620
- browse(registryUrl?: string, query?: string): Promise<AgentListing[]>;
671
+ browse(registryUrl?: string, query?: string): Promise<AgentListEntry[]>;
621
672
 
622
673
  /** Inspect a specific agent — returns tools, auth requirements, resources */
623
674
  inspect(
624
675
  agentPath: string,
625
676
  registryUrl?: string,
626
677
  options?: { full?: boolean },
627
- ): Promise<AgentListing | null>;
678
+ ): Promise<AgentInspection | null>;
628
679
 
629
680
  /** Resolve a secret URL to its value */
630
681
  resolveSecret(url: string): Promise<string>;
@@ -644,7 +695,7 @@ export interface RegistryConsumer {
644
695
  index(): ResolvedConfig;
645
696
 
646
697
  /** Diff: what's available vs what's configured */
647
- available(): Promise<AgentListing[]>;
698
+ available(): Promise<AgentListEntry[]>;
648
699
  }
649
700
 
650
701
  /**
@@ -693,7 +744,7 @@ export async function createRegistryConsumer(
693
744
  async function listFromRegistry(
694
745
  registry: ResolvedRegistry,
695
746
  query?: string,
696
- ): Promise<AgentListing[]> {
747
+ ): Promise<AgentListEntry[]> {
697
748
  const mcpUrl = registry.url.replace(/\/$/, "");
698
749
 
699
750
  const response = await callMcpTool(
@@ -715,15 +766,15 @@ export async function createRegistryConsumer(
715
766
  ) as ListAgentsResponse;
716
767
  const agents = data.agents ?? [];
717
768
 
718
- return agents.map((agent) => ({
719
- ...agent,
720
- ...agent,
721
- // Normalize tools: strings become { name } objects
722
- tools: agent.tools?.map((t) =>
723
- typeof t === "string" ? { name: t } : t,
724
- ),
725
- publisher: registry.publisher,
726
- }));
769
+ return agents.map((agent) => {
770
+ // Legacy registries may still emit `tools` instead of `toolCount`; back-fill.
771
+ const { tools, toolCount, ...rest } = agent;
772
+ return {
773
+ ...rest,
774
+ publisher: registry.publisher,
775
+ toolCount: toolCount ?? tools?.length,
776
+ };
777
+ });
727
778
  }
728
779
 
729
780
  // Send any call_agent request through a registry's MCP endpoint
@@ -821,7 +872,7 @@ export async function createRegistryConsumer(
821
872
 
822
873
  // Build the consumer
823
874
  const consumer: RegistryConsumer = {
824
- async list(): Promise<AgentListing[]> {
875
+ async list(): Promise<AgentListEntry[]> {
825
876
  // Collect from standard registries
826
877
  const registryResults = await Promise.allSettled(
827
878
  resolvedRegistries.map((r) => listFromRegistry(r)),
@@ -925,7 +976,7 @@ export async function createRegistryConsumer(
925
976
  return discover(registryUrl, registry);
926
977
  },
927
978
 
928
- async browse(registryUrl?: string, query?: string): Promise<AgentListing[]> {
979
+ async browse(registryUrl?: string, query?: string): Promise<AgentListEntry[]> {
929
980
  // List agents from a specific registry, or all registries if not specified
930
981
  const targets = registryUrl
931
982
  ? resolvedRegistries.filter(
@@ -945,7 +996,7 @@ export async function createRegistryConsumer(
945
996
  agentPath: string,
946
997
  registryUrl?: string,
947
998
  options?: { full?: boolean },
948
- ): Promise<AgentListing | null> {
999
+ ): Promise<AgentInspection | null> {
949
1000
  const targetRegistries = registryUrl
950
1001
  ? resolvedRegistries.filter((r) => r.url === registryUrl || r.name === registryUrl)
951
1002
  : resolvedRegistries;
@@ -988,7 +1039,7 @@ export async function createRegistryConsumer(
988
1039
  context: data.context,
989
1040
  ...(data.upstream && { upstream: data.upstream }),
990
1041
  ...(data.mode && { mode: data.mode }),
991
- } as AgentListing;
1042
+ } as AgentInspection;
992
1043
  }),
993
1044
  );
994
1045
 
@@ -1018,7 +1069,7 @@ export async function createRegistryConsumer(
1018
1069
  };
1019
1070
  },
1020
1071
 
1021
- async available(): Promise<AgentListing[]> {
1072
+ async available(): Promise<AgentListEntry[]> {
1022
1073
  const all = await consumer.list();
1023
1074
  const configuredRefs = new Set(resolvedRefs.map((r) => r.ref));
1024
1075
  return all.filter((a) => !configuredRefs.has(a.path));
package/src/server.ts CHANGED
@@ -206,6 +206,17 @@ export interface AgentServerOptions {
206
206
  features?: string[];
207
207
  /** OAuth callback URL for shared OAuth flows */
208
208
  oauthCallbackUrl?: string;
209
+ /**
210
+ * Announce that ref operations for agents sourced from this registry
211
+ * should be forwarded to a server-side adk-tools agent instead of
212
+ * running locally. Consumers pick this up during `registry.add` and
213
+ * auto-populate `RegistryEntry.proxy` — no user flag needed.
214
+ */
215
+ proxy?: {
216
+ mode: "required" | "optional";
217
+ /** Agent path to forward to. Defaults to '@config'. */
218
+ agent?: string;
219
+ };
209
220
  };
210
221
  /**
211
222
  * Structured logger for server-side errors (tool-call failures, JWT
@@ -591,6 +602,14 @@ export function createAgentServer(
591
602
  ...(options.registry.oauthCallbackUrl && {
592
603
  oauthCallbackUrl: options.registry.oauthCallbackUrl,
593
604
  }),
605
+ ...(options.registry.proxy && {
606
+ proxy: {
607
+ mode: options.registry.proxy.mode,
608
+ ...(options.registry.proxy.agent && {
609
+ agent: options.registry.proxy.agent,
610
+ }),
611
+ },
612
+ }),
594
613
  },
595
614
  }),
596
615
  },