@slashfi/agents-sdk 0.81.0 → 0.83.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.
@@ -32,8 +32,6 @@ const SECRET_PREFIX = "secret:";
32
32
  * we evaluate satisfaction against the entry's current `config`.
33
33
  *
34
34
  * Behavior:
35
- * - `mode: 'proxy'` refs → always true. Auth lives server-side; the
36
- * proxy is the source of truth, no entry-side fields involved.
37
35
  * - Cache miss (no `authFields` for this ref yet) → returns `null`,
38
36
  * signaling "I don't know — caller should fall back to its own
39
37
  * heuristic or call `auth-status` to populate the cache".
@@ -51,8 +49,6 @@ const SECRET_PREFIX = "secret:";
51
49
  export function isRefAuthComplete(entry, cacheEntry, opts) {
52
50
  if (typeof entry === "string")
53
51
  return false;
54
- if (entry.mode === "proxy")
55
- return true;
56
52
  const authFields = cacheEntry?.authFields;
57
53
  if (!authFields)
58
54
  return null;
@@ -624,78 +620,6 @@ export function createAdk(fs, options = {}) {
624
620
  return fallback;
625
621
  }
626
622
  // ==========================================
627
- // Proxy Routing
628
- // ==========================================
629
- /**
630
- * Find the configured RegistryEntry for a ref, consulting `sourceRegistry`
631
- * first and falling back to the first registry in config. Returns `null` when
632
- * the ref is sourced from a raw URL (no registry), in which case proxy routing
633
- * does not apply.
634
- */
635
- async function findRegistryEntryForRef(entry) {
636
- const sourceUrl = entry.sourceRegistry?.url;
637
- if (!sourceUrl)
638
- return null;
639
- const config = await readConfig();
640
- const match = (config.registries ?? []).find((r) => {
641
- if (typeof r === "string")
642
- return r === sourceUrl;
643
- return r.url === sourceUrl;
644
- });
645
- if (!match || typeof match === "string")
646
- return null;
647
- return match;
648
- }
649
- /**
650
- * Returns the proxy settings for a ref when its source registry has
651
- * `proxy` configured. `null` means "run locally".
652
- *
653
- * Callers pass `{ preferLocal: true }` to opt out of `mode: 'optional'`
654
- * proxying when they already hold credentials locally. `mode: 'required'`
655
- * cannot be bypassed — the registry owns auth server-side and there is
656
- * nothing useful the local SDK can do.
657
- */
658
- async function resolveProxyForRef(entry, opts) {
659
- const reg = await findRegistryEntryForRef(entry);
660
- if (!reg?.proxy)
661
- return null;
662
- if (reg.proxy.mode === "optional" && opts?.preferLocal)
663
- return null;
664
- return { reg, agent: reg.proxy.agent ?? "@config" };
665
- }
666
- /**
667
- * Forward an `@config ref` operation to the proxy agent on a remote registry.
668
- *
669
- * The remote side speaks the standard adk-tools surface, so the call shape is
670
- * identical to what the local `ref` API would do — the only difference is
671
- * that tokens and secrets live server-side. `callRegistry` returns the
672
- * standard CallAgentResponse envelope: `{ success: true, result }` on
673
- * success or `{ success: false, error }` on failure. We unwrap once and
674
- * throw on error so callers get a result that matches the local signature.
675
- */
676
- async function forwardRefOpToProxy(reg, agent, operation, params) {
677
- const consumer = await buildConsumerForRef({
678
- ref: "",
679
- name: "",
680
- sourceRegistry: { url: reg.url, agentPath: agent },
681
- });
682
- const resolved = consumer.registries().find((r) => r.url === reg.url);
683
- if (!resolved)
684
- throw new Error(`Registry ${reg.url} not resolvable for proxy forwarding`);
685
- const response = await consumer.callRegistry(resolved, {
686
- action: "execute_tool",
687
- path: agent,
688
- tool: "ref",
689
- params: { operation, ...params },
690
- });
691
- if (!response.success) {
692
- const errResponse = response;
693
- const msg = errResponse.error ?? `Proxy ${agent}.ref(${operation}) failed`;
694
- throw new Error(msg);
695
- }
696
- return response.result;
697
- }
698
- // ==========================================
699
623
  // Registry API
700
624
  // ==========================================
701
625
  /**
@@ -708,42 +632,6 @@ export function createAdk(fs, options = {}) {
708
632
  return value;
709
633
  return `${SECRET_PREFIX}${await encryptSecret(value, options.encryptionKey)}`;
710
634
  }
711
- /**
712
- * Re-probe a registry with the current stored credentials to see whether it
713
- * advertises `capabilities.registry.proxy` in its MCP `initialize` response,
714
- * and persist the proxy config when it does. Safe to call after a successful
715
- * `auth()` / `authLocal()` — on the add path we skip the proxy probe when
716
- * auth is required, so this is the second chance to back-fill it.
717
- *
718
- * Respects explicit user config: if `proxy` is already set, we leave it
719
- * alone. Any discovery failure is swallowed — proxy is an optimization,
720
- * not a correctness requirement.
721
- */
722
- async function discoverProxyAfterAuth(nameOrUrl) {
723
- const config = await readConfig();
724
- const target = findRegistry(config.registries ?? [], nameOrUrl);
725
- if (!target || typeof target === "string")
726
- return;
727
- if (target.proxy)
728
- return;
729
- try {
730
- const consumer = await buildConsumer(nameOrUrl);
731
- const discovered = await consumer.discover(target.url);
732
- if (!discovered.proxy?.mode)
733
- return;
734
- await updateRegistryEntry(nameOrUrl, (existing) => {
735
- if (existing.proxy)
736
- return;
737
- existing.proxy = {
738
- mode: discovered.proxy.mode,
739
- ...(discovered.proxy.agent && { agent: discovered.proxy.agent }),
740
- };
741
- });
742
- }
743
- catch {
744
- // Proxy probe is best-effort — auth itself already succeeded.
745
- }
746
- }
747
635
  /**
748
636
  * Atomic read-modify-write on a registry entry by name or URL. Used by
749
637
  * `authLocal` to persist both `auth` and `oauth` together, which `auth()`
@@ -884,14 +772,10 @@ export function createAdk(fs, options = {}) {
884
772
  const config = await readConfig();
885
773
  const alias = entry.name ?? entry.url;
886
774
  const registries = (config.registries ?? []).filter((r) => registryDisplayName(r) !== alias);
887
- // Probe the registry before saving. Two things fall out of the probe:
888
- // 1. Auth challenge — 401 + WWW-Authenticate points at RFC 9728
889
- // resource metadata; we persist it on `authRequirement` so
890
- // subsequent ops can refuse early with a friendly message.
891
- // 2. Proxy capability — the MCP `initialize` response may advertise
892
- // `capabilities.registry.proxy`, which auto-populates `proxy`.
893
- // Users who set `proxy` or `auth` explicitly on the entry always win:
894
- // discovery only fills in blanks.
775
+ // Probe the registry before saving. If it returns 401 with a
776
+ // WWW-Authenticate / RFC 9728 resource metadata pointer, persist
777
+ // that on `authRequirement` so subsequent ops can refuse early
778
+ // with a friendly message.
895
779
  let final = entry;
896
780
  let authRequirement;
897
781
  const hasUsableAuth = entry.auth && entry.auth.type !== "none"
@@ -906,30 +790,6 @@ export function createAdk(fs, options = {}) {
906
790
  final = { ...final, authRequirement };
907
791
  }
908
792
  }
909
- if (!entry.proxy && !authRequirement) {
910
- try {
911
- const probeConsumer = await createRegistryConsumer({ registries: [entry], refs: [] }, { token: options.token, fetch: options.fetch });
912
- const resolved = probeConsumer.registries()[0];
913
- if (resolved) {
914
- const discovered = await probeConsumer.discover(resolved.url);
915
- if (discovered.proxy?.mode) {
916
- final = {
917
- ...final,
918
- proxy: {
919
- mode: discovered.proxy.mode,
920
- ...(discovered.proxy.agent && {
921
- agent: discovered.proxy.agent,
922
- }),
923
- },
924
- };
925
- }
926
- }
927
- }
928
- catch {
929
- // Discovery is best-effort — offline, unreachable, or non-adk
930
- // registries simply skip proxy auto-configuration.
931
- }
932
- }
933
793
  registries.push(final);
934
794
  await writeConfig({ ...config, registries });
935
795
  return authRequirement ? { authRequirement } : {};
@@ -975,8 +835,6 @@ export function createAdk(fs, options = {}) {
975
835
  existing.auth = updates.auth;
976
836
  if (updates.headers)
977
837
  existing.headers = { ...existing.headers, ...updates.headers };
978
- if (updates.proxy !== undefined)
979
- existing.proxy = updates.proxy;
980
838
  return existing;
981
839
  });
982
840
  if (!found)
@@ -1076,8 +934,6 @@ export function createAdk(fs, options = {}) {
1076
934
  }
1077
935
  delete existing.authRequirement;
1078
936
  });
1079
- if (updated)
1080
- await discoverProxyAfterAuth(nameOrUrl);
1081
937
  return updated;
1082
938
  },
1083
939
  async authLocal(nameOrUrl, opts) {
@@ -1224,7 +1080,6 @@ export function createAdk(fs, options = {}) {
1224
1080
  };
1225
1081
  delete existing.authRequirement;
1226
1082
  });
1227
- await discoverProxyAfterAuth(displayName);
1228
1083
  resOut.writeHead(200, { "Content-Type": "text/html" });
1229
1084
  resOut.end(renderAuthSuccess(displayName));
1230
1085
  server.close();
@@ -1603,12 +1458,6 @@ export function createAdk(fs, options = {}) {
1603
1458
  const entry = findRef(config.refs ?? [], name);
1604
1459
  if (!entry)
1605
1460
  throw new Error(`Ref "${name}" not found`);
1606
- // Registry-proxied refs: ask the remote @config for state (secrets live
1607
- // server-side so local inspection would always return "missing").
1608
- const proxy = await resolveProxyForRef(entry);
1609
- if (proxy) {
1610
- return forwardRefOpToProxy(proxy.reg, proxy.agent, "auth-status", { name });
1611
- }
1612
1461
  let security = null;
1613
1462
  try {
1614
1463
  const consumer = await buildConsumerForRef(entry);
@@ -1730,25 +1579,6 @@ export function createAdk(fs, options = {}) {
1730
1579
  const entry = findRef(config.refs ?? [], name);
1731
1580
  if (!entry)
1732
1581
  throw new Error(`Ref "${name}" not found`);
1733
- // Registry-proxied auth: forward the start-of-flow to the remote @config
1734
- // agent. The registry owns the client_id/secret and returns an authorize
1735
- // URL pointing at the registry's OAuth callback domain, so the user
1736
- // completes the flow against the registry instead of localhost.
1737
- const proxy = await resolveProxyForRef(entry, {
1738
- preferLocal: opts?.preferLocal,
1739
- });
1740
- if (proxy) {
1741
- const params = { name };
1742
- if (opts?.apiKey !== undefined)
1743
- params.apiKey = opts.apiKey;
1744
- if (opts?.credentials)
1745
- params.credentials = opts.credentials;
1746
- if (opts?.scopes)
1747
- params.scopes = opts.scopes;
1748
- if (opts?.stateContext)
1749
- params.stateContext = opts.stateContext;
1750
- return forwardRefOpToProxy(proxy.reg, proxy.agent, "auth", params);
1751
- }
1752
1582
  const status = await ref.authStatus(name);
1753
1583
  const security = status.security;
1754
1584
  const tryResolve = makeTryResolve({ name, entry, security });
@@ -2002,32 +1832,16 @@ export function createAdk(fs, options = {}) {
2002
1832
  return { type: security.type, complete: false };
2003
1833
  },
2004
1834
  async authLocal(name, opts) {
2005
- // `ref.auth` is already proxy-aware — for proxied refs it returns
2006
- // the authorizeUrl that the registry minted against its own
2007
- // callback domain. Everything below is identical for local and
2008
- // proxied refs except the last step (polling for the callback),
2009
- // which only makes sense when we own the redirect URI.
2010
1835
  const result = await ref.auth(name);
2011
1836
  if (result.complete)
2012
1837
  return { complete: true };
2013
- const config = await readConfig();
2014
- const entry = findRef(config.refs ?? [], name);
2015
- const proxy = entry ? await resolveProxyForRef(entry) : null;
2016
1838
  const port = options.oauthCallbackPort ?? 8919;
2017
1839
  const timeout = opts?.timeoutMs ?? 300_000;
2018
1840
  const { createServer } = await import("node:http");
2019
1841
  // API key / HTTP auth — local credential form.
2020
- //
2021
- // We refuse to serve the form for a proxied ref: the registry
2022
- // owns the credential store, so the user needs to submit via
2023
- // whatever UI the registry exposes. Supporting this through the
2024
- // proxy would need a remote form endpoint — out of scope here.
2025
1842
  if (result.fields &&
2026
1843
  result.fields.length > 0 &&
2027
1844
  result.type !== "oauth2") {
2028
- if (proxy) {
2029
- throw new Error(`Ref "${name}" is sourced from a proxied registry; submit credentials through ${proxy.agent} instead of a local form.`);
2030
- }
2031
1845
  return new Promise((resolve, reject) => {
2032
1846
  const server = createServer(async (req, res) => {
2033
1847
  const reqUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
@@ -2089,13 +1903,8 @@ export function createAdk(fs, options = {}) {
2089
1903
  if (opts?.onAuthorizeUrl) {
2090
1904
  opts.onAuthorizeUrl(result.authorizeUrl);
2091
1905
  }
2092
- // Proxied refs: the registry owns the callback endpoint, so there's
2093
- // nothing to poll here. Callers poll `ref.authStatus` on their own
2094
- // schedule once the user finishes the remote consent screen.
2095
- if (proxy)
2096
- return { complete: false };
2097
- // Local refs: spin up the callback server on oauthCallbackPort and
2098
- // block until the OAuth provider redirects back.
1906
+ // Spin up the callback server on oauthCallbackPort and block
1907
+ // until the OAuth provider redirects back.
2099
1908
  return new Promise((resolve, reject) => {
2100
1909
  const server = createServer(async (req, res) => {
2101
1910
  const reqUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
@@ -2134,14 +1943,6 @@ export function createAdk(fs, options = {}) {
2134
1943
  });
2135
1944
  },
2136
1945
  async refreshToken(name) {
2137
- // Registry-proxied refs: the remote @config holds the refresh_token.
2138
- const entryForProxy = await ref.get(name);
2139
- if (entryForProxy) {
2140
- const proxy = await resolveProxyForRef(entryForProxy);
2141
- if (proxy) {
2142
- return forwardRefOpToProxy(proxy.reg, proxy.agent, "refresh-token", { name });
2143
- }
2144
- }
2145
1946
  // Read stored refresh_token
2146
1947
  const refreshToken = await readRefSecret(name, "refresh_token");
2147
1948
  if (!refreshToken)