@slashfi/agents-sdk 0.83.0 → 0.85.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.
@@ -1841,8 +1841,15 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
1841
1841
  } else {
1842
1842
  throw new AdkError({
1843
1843
  code: "REF_INVALID",
1844
- message: `Cannot add ref "${entry.ref}": could not determine connection type`,
1845
- hint: "Use --registry <name> to install from a registry, or --url <url> for a direct connection",
1844
+ message:
1845
+ `Cannot add ref "${entry.ref}": could not determine connection type. ` +
1846
+ `Provide one of:\n` +
1847
+ ` - sourceRegistry: { url: <registry URL>, agentPath?: <agent path on that registry> } (registry-backed ref)\n` +
1848
+ ` - url: "https://..." (direct https/mcp ref)\n` +
1849
+ `For registry-backed refs, run \`registry list\` to find available registry URLs.`,
1850
+ hint:
1851
+ "CLI: pass --registry <name> or --url <url>. " +
1852
+ "Tool input: pass `sourceRegistry: { url, agentPath }` or `url: 'https://...'`.",
1846
1853
  details: { ref: entry.ref },
1847
1854
  });
1848
1855
  }
@@ -1852,18 +1859,42 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
1852
1859
  if (entry.scheme === "registry" && !entry.sourceRegistry?.url) {
1853
1860
  throw new AdkError({
1854
1861
  code: "REF_INVALID",
1855
- message: `Cannot add ref "${entry.ref}": registry scheme requires a source registry`,
1856
- hint: "Use --registry <name> (e.g. adk ref add notion --registry public)",
1857
- details: { ref: entry.ref, scheme: entry.scheme },
1862
+ message:
1863
+ `Cannot add ref "${entry.ref}": scheme="registry" requires sourceRegistry.url. ` +
1864
+ `Required shape:\n` +
1865
+ ` {\n` +
1866
+ ` operation: "add",\n` +
1867
+ ` ref: "${entry.ref}",\n` +
1868
+ ` scheme: "registry",\n` +
1869
+ ` sourceRegistry: { url: <registry URL>, agentPath?: <agent path on that registry> }\n` +
1870
+ ` }\n` +
1871
+ `Run \`registry list\` to find the URL of a registered registry by name.`,
1872
+ hint:
1873
+ "CLI: adk ref add <ref> --registry <name>. " +
1874
+ "Tool input: pass sourceRegistry.url alongside agentPath (auto-resolution by registry name only happens when calling addRef() directly with a `registry` field, not via the @config tool).",
1875
+ details: {
1876
+ ref: entry.ref,
1877
+ scheme: entry.scheme,
1878
+ received: { sourceRegistry: entry.sourceRegistry },
1879
+ requiredShape: {
1880
+ sourceRegistry: { url: "<registry URL>", agentPath: "<optional agent path>" },
1881
+ },
1882
+ },
1858
1883
  });
1859
1884
  }
1860
1885
 
1861
1886
  if ((entry.scheme === "mcp" || entry.scheme === "https") && !entry.url) {
1862
1887
  throw new AdkError({
1863
1888
  code: "REF_INVALID",
1864
- message: `Cannot add ref "${entry.ref}": scheme '${entry.scheme}' requires url`,
1865
- hint: "Provide the direct agent URL with: url: 'https://...'",
1866
- details: { ref: entry.ref, scheme: entry.scheme },
1889
+ message:
1890
+ `Cannot add ref "${entry.ref}": scheme="${entry.scheme}" requires url. ` +
1891
+ `Required shape: { operation: "add", ref: "${entry.ref}", scheme: "${entry.scheme}", url: "https://..." }`,
1892
+ hint: "Provide the direct agent URL with `url: 'https://...'`.",
1893
+ details: {
1894
+ ref: entry.ref,
1895
+ scheme: entry.scheme,
1896
+ requiredShape: { url: "<agent URL>" },
1897
+ },
1867
1898
  });
1868
1899
  }
1869
1900
 
@@ -1872,7 +1903,13 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
1872
1903
  try {
1873
1904
  const consumer = await buildConsumerForRef(entry);
1874
1905
  const agentToInspect = entry.sourceRegistry?.agentPath ?? entry.ref;
1875
- const info = await consumer.inspect(agentToInspect);
1906
+ // Same multi-registry hazard as authStatus — target the ref's
1907
+ // own sourceRegistry so an unrelated registry can't shadow the
1908
+ // real lookup with an empty/error response.
1909
+ const info = await consumer.inspect(
1910
+ agentToInspect,
1911
+ entry.sourceRegistry?.url,
1912
+ );
1876
1913
 
1877
1914
  const requiresValidation = !!entry.sourceRegistry;
1878
1915
  if (requiresValidation) {
@@ -2155,8 +2192,15 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
2155
2192
  let security: SecuritySchemeSummary | null = null;
2156
2193
  try {
2157
2194
  const consumer = await buildConsumerForRef(entry);
2195
+ // Pass `sourceRegistry.url` so inspect targets the registry the ref
2196
+ // came from. Without this, multi-registry consumers race every
2197
+ // configured registry and the first fulfilled response wins —
2198
+ // including {success:false} bodies from unrelated registries that
2199
+ // don't host this agent — which silently nulls out `security` and
2200
+ // makes `auth()` short-circuit to {type:"none", complete:true}.
2158
2201
  const info = await consumer.inspect(
2159
2202
  entry.sourceRegistry?.agentPath ?? entry.ref,
2203
+ entry.sourceRegistry?.url,
2160
2204
  );
2161
2205
  if (info?.security) security = info.security;
2162
2206
  } catch {
@@ -1047,6 +1047,12 @@ export async function createRegistryConsumer(
1047
1047
  })) as unknown as Record<string, unknown> | null;
1048
1048
  if (!raw) return null;
1049
1049
 
1050
+ // `callRegistry` returns {success:false, ...} for upstream 401s
1051
+ // (and other recoverable failures) instead of throwing — treat
1052
+ // these as "this registry doesn't host the agent" so the next
1053
+ // registry gets a chance to answer.
1054
+ if (raw.success === false) return null;
1055
+
1050
1056
  // Some endpoints (e.g. twin MCP) wrap the response in { success, result },
1051
1057
  // while registries return fields flat. Unwrap if needed.
1052
1058
  const data = (
@@ -1063,6 +1069,15 @@ export async function createRegistryConsumer(
1063
1069
  upstream?: string;
1064
1070
  mode?: string;
1065
1071
  };
1072
+
1073
+ // Skip "agent not found" responses (no tools AND no description)
1074
+ // so they don't shadow a registry that actually hosts the agent.
1075
+ const hasContent =
1076
+ (data.tools && data.tools.length > 0) ||
1077
+ (data.toolSummaries && data.toolSummaries.length > 0) ||
1078
+ !!data.description;
1079
+ if (!hasContent) return null;
1080
+
1066
1081
  return {
1067
1082
  path: agentPath,
1068
1083
  publisher: registry.publisher,