@slashfi/agents-sdk 0.77.3 → 0.79.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.
@@ -51,14 +51,58 @@ var __importStar = (this && this.__importStar) || (function () {
51
51
  };
52
52
  })();
53
53
  Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.isRefAuthComplete = isRefAuthComplete;
54
55
  exports.createAdk = createAdk;
55
- const define_config_js_1 = require("./define-config.js");
56
- const registry_consumer_js_1 = require("./registry-consumer.js");
57
- const crypto_js_1 = require("./crypto.js");
58
56
  const adk_error_js_1 = require("./adk-error.js");
57
+ const crypto_js_1 = require("./crypto.js");
58
+ const define_config_js_1 = require("./define-config.js");
59
59
  const mcp_client_js_1 = require("./mcp-client.js");
60
+ const registry_consumer_js_1 = require("./registry-consumer.js");
60
61
  const CONFIG_PATH = "consumer-config.json";
62
+ const REGISTRY_CACHE_PATH = "registry-cache.json";
61
63
  const SECRET_PREFIX = "secret:";
64
+ /**
65
+ * "Is this ref ready to call?" answered locally using the cached
66
+ * security-scheme requirements. Mirrors the `complete` boolean
67
+ * `auth-status` returns, but doesn't need a network round-trip — the
68
+ * cached `authFields` capture what the registry said is required, and
69
+ * we evaluate satisfaction against the entry's current `config`.
70
+ *
71
+ * Behavior:
72
+ * - `mode: 'proxy'` refs → always true. Auth lives server-side; the
73
+ * proxy is the source of truth, no entry-side fields involved.
74
+ * - Cache miss (no `authFields` for this ref yet) → returns `null`,
75
+ * signaling "I don't know — caller should fall back to its own
76
+ * heuristic or call `auth-status` to populate the cache".
77
+ * - Cache hit → for every required, non-automated field, checks
78
+ * presence in `entry.config`. Mirrors the `present || resolvable`
79
+ * check in `auth-status` but evaluates against current config.
80
+ * `automated` fields (e.g. dynamic OAuth client_id) count as
81
+ * satisfied even when absent — adk supplies them at call time.
82
+ *
83
+ * Returning `null` for cache miss is intentional. A boolean would
84
+ * force callers to choose a default that's wrong half the time;
85
+ * `null` lets them branch explicitly.
86
+ */
87
+ function isRefAuthComplete(entry, cacheEntry) {
88
+ if (typeof entry === "string")
89
+ return false;
90
+ if (entry.mode === "proxy")
91
+ return true;
92
+ const authFields = cacheEntry?.authFields;
93
+ if (!authFields)
94
+ return null;
95
+ const config = entry.config ?? {};
96
+ for (const [field, info] of Object.entries(authFields)) {
97
+ if (!info.required)
98
+ continue;
99
+ if (info.automated)
100
+ continue;
101
+ if (!(field in config))
102
+ return false;
103
+ }
104
+ return true;
105
+ }
62
106
  // ============================================
63
107
  // Internal helpers
64
108
  // ============================================
@@ -110,7 +154,9 @@ async function decryptConfigSecrets(obj, encryptionKey) {
110
154
  if (typeof value === "string" && value.startsWith(SECRET_PREFIX)) {
111
155
  result[key] = await (0, crypto_js_1.decryptSecret)(value.slice(SECRET_PREFIX.length), encryptionKey);
112
156
  }
113
- else if (value !== null && typeof value === "object" && !Array.isArray(value)) {
157
+ else if (value !== null &&
158
+ typeof value === "object" &&
159
+ !Array.isArray(value)) {
114
160
  result[key] = await decryptConfigSecrets(value, encryptionKey);
115
161
  }
116
162
  else {
@@ -128,7 +174,7 @@ async function decryptConfigSecrets(obj, encryptionKey) {
128
174
  * Fallback: _httpStatus from tool result body
129
175
  */
130
176
  function isUnauthorized(result) {
131
- if (!result || typeof result !== 'object')
177
+ if (!result || typeof result !== "object")
132
178
  return false;
133
179
  const r = result;
134
180
  // Primary: HTTP status forwarded by the registry and set by callRegistry
@@ -143,17 +189,21 @@ function isUnauthorized(result) {
143
189
  // ============================================
144
190
  // Local auth form HTML
145
191
  // ============================================
146
- const esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
192
+ const esc = (s) => s
193
+ .replace(/&/g, "&amp;")
194
+ .replace(/</g, "&lt;")
195
+ .replace(/>/g, "&gt;")
196
+ .replace(/"/g, "&quot;");
147
197
  function renderCredentialForm(name, fields, error) {
148
- const fieldHtml = fields.map((f) => `
198
+ const fieldHtml = fields
199
+ .map((f) => `
149
200
  <div class="field">
150
201
  <label for="${esc(f.name)}">${esc(f.label)}</label>
151
202
  ${f.description ? `<p class="desc">${esc(f.description)}</p>` : ""}
152
203
  <input id="${esc(f.name)}" name="${esc(f.name)}" type="${f.secret ? "password" : "text"}" required autocomplete="off" spellcheck="false" />
153
- </div>`).join("");
154
- const errorHtml = error
155
- ? `<div class="error">${esc(error)}</div>`
156
- : "";
204
+ </div>`)
205
+ .join("");
206
+ const errorHtml = error ? `<div class="error">${esc(error)}</div>` : "";
157
207
  return `<!DOCTYPE html>
158
208
  <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
159
209
  <title>Authenticate \u2014 ${esc(name)}</title>
@@ -216,6 +266,113 @@ function createAdk(fs, options = {}) {
216
266
  async function writeConfig(config) {
217
267
  await fs.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2));
218
268
  }
269
+ // -------------------------------------------------------------------------
270
+ // Registry cache helpers
271
+ //
272
+ // The cache is purely an internal optimization for the adk's read paths
273
+ // (`ref.list()`, `ref.get()`). Writes happen as side-effects of methods
274
+ // that already call the registry (`ref.add()`, `ref.inspect()`); the
275
+ // public surface never grows new methods. Cache failures (missing file,
276
+ // malformed JSON, fs errors during write) are swallowed so the registry
277
+ // cache can never break a registry operation.
278
+ // -------------------------------------------------------------------------
279
+ async function readRegistryCache() {
280
+ try {
281
+ const content = await fs.readFile(REGISTRY_CACHE_PATH);
282
+ if (!content)
283
+ return { refs: {} };
284
+ const parsed = JSON.parse(content);
285
+ return { refs: parsed.refs ?? {} };
286
+ }
287
+ catch {
288
+ return { refs: {} };
289
+ }
290
+ }
291
+ async function writeRegistryCache(cache) {
292
+ try {
293
+ await fs.writeFile(REGISTRY_CACHE_PATH, JSON.stringify(cache, null, 2));
294
+ }
295
+ catch {
296
+ // Best-effort. A failed cache write should never break the operation
297
+ // that triggered it.
298
+ }
299
+ }
300
+ /**
301
+ * Project an inspect/list response into the slim shape we cache. Drops
302
+ * `inputSchema` (too large) and `fullTokens` (registry-internal). Returns
303
+ * undefined if the response carries nothing worth caching.
304
+ */
305
+ function buildCacheEntry(ref, info) {
306
+ if (!info)
307
+ return undefined;
308
+ const toolSource = info.tools ?? info.toolSummaries;
309
+ const tools = toolSource?.map((t) => {
310
+ const slim = { name: t.name };
311
+ if (t.description !== undefined)
312
+ slim.description = t.description;
313
+ return slim;
314
+ });
315
+ if (info.description === undefined && (!tools || tools.length === 0)) {
316
+ return undefined;
317
+ }
318
+ const entry = {
319
+ ref,
320
+ fetchedAt: new Date().toISOString(),
321
+ };
322
+ if (info.description !== undefined)
323
+ entry.description = info.description;
324
+ if (tools && tools.length > 0)
325
+ entry.tools = tools;
326
+ return entry;
327
+ }
328
+ async function upsertRegistryCacheEntry(name, entry) {
329
+ if (!entry)
330
+ return;
331
+ const cache = await readRegistryCache();
332
+ cache.refs[name] = entry;
333
+ await writeRegistryCache(cache);
334
+ }
335
+ /**
336
+ * Merge `authFields` into an existing cache entry without clobbering
337
+ * description/tools, or create a minimal entry if one doesn't exist
338
+ * yet. Called from `authStatus` so the slim {required, automated}
339
+ * shape is always available for `isRefAuthComplete` to answer
340
+ * locally on subsequent calls.
341
+ */
342
+ async function upsertRegistryCacheAuthFields(name, ref, authFields) {
343
+ const cache = await readRegistryCache();
344
+ const existing = cache.refs[name];
345
+ cache.refs[name] = {
346
+ ...(existing ?? { ref, fetchedAt: new Date().toISOString() }),
347
+ authFields,
348
+ // Refresh fetchedAt so freshness telemetry stays accurate.
349
+ fetchedAt: new Date().toISOString(),
350
+ };
351
+ await writeRegistryCache(cache);
352
+ }
353
+ async function removeRegistryCacheEntry(name) {
354
+ const cache = await readRegistryCache();
355
+ if (!(name in cache.refs))
356
+ return;
357
+ delete cache.refs[name];
358
+ await writeRegistryCache(cache);
359
+ }
360
+ /**
361
+ * Hydrate a `ResolvedRef` with cached registry metadata when available.
362
+ * Pure: never mutates input. Leaves `description` / `tools` undefined when
363
+ * the cache has no entry, so callers can apply their own UX fallback.
364
+ */
365
+ function hydrateFromCache(ref, cache) {
366
+ const cached = cache.refs[ref.name];
367
+ if (!cached)
368
+ return ref;
369
+ const next = { ...ref };
370
+ if (cached.description !== undefined)
371
+ next.description = cached.description;
372
+ if (cached.tools !== undefined)
373
+ next.tools = cached.tools;
374
+ return next;
375
+ }
219
376
  /**
220
377
  * Store a secret value in a ref's config, encrypted if encryptionKey is set.
221
378
  * The value is stored inline as "secret:<encrypted>" in consumer-config.json.
@@ -326,7 +483,10 @@ function createAdk(fs, options = {}) {
326
483
  let reqId = 0;
327
484
  let sessionId;
328
485
  async function rpc(method, rpcParams) {
329
- const reqHeaders = { ...headers, ...(sessionId ? { "Mcp-Session-Id": sessionId } : {}) };
486
+ const reqHeaders = {
487
+ ...headers,
488
+ ...(sessionId ? { "Mcp-Session-Id": sessionId } : {}),
489
+ };
330
490
  const res = await globalThis.fetch(url, {
331
491
  method: "POST",
332
492
  headers: reqHeaders,
@@ -367,7 +527,7 @@ function createAdk(fs, options = {}) {
367
527
  }
368
528
  return undefined;
369
529
  }
370
- const json = await res.json();
530
+ const json = (await res.json());
371
531
  if (json.error)
372
532
  throw new Error(`MCP RPC error: ${json.error.message}`);
373
533
  return json.result;
@@ -379,20 +539,32 @@ function createAdk(fs, options = {}) {
379
539
  clientInfo: { name: "adk", version: "1.0.0" },
380
540
  });
381
541
  await rpc("notifications/initialized").catch(() => { });
382
- const result = await rpc("tools/call", { name: toolName, arguments: params });
542
+ const result = (await rpc("tools/call", {
543
+ name: toolName,
544
+ arguments: params,
545
+ }));
383
546
  const textContent = result?.content?.find((c) => c.type === "text");
384
547
  if (textContent?.text) {
385
548
  try {
386
- return { success: true, result: JSON.parse(textContent.text) };
549
+ return {
550
+ success: true,
551
+ result: JSON.parse(textContent.text),
552
+ };
387
553
  }
388
554
  catch {
389
- return { success: true, result: textContent.text };
555
+ return {
556
+ success: true,
557
+ result: textContent.text,
558
+ };
390
559
  }
391
560
  }
392
561
  return { success: true, result };
393
562
  }
394
563
  catch (err) {
395
- return { success: false, error: err instanceof Error ? err.message : String(err) };
564
+ return {
565
+ success: false,
566
+ error: err instanceof Error ? err.message : String(err),
567
+ };
396
568
  }
397
569
  }
398
570
  function callbackUrl() {
@@ -405,7 +577,7 @@ function createAdk(fs, options = {}) {
405
577
  const res = await globalThis.fetch(url);
406
578
  if (!res.ok)
407
579
  return null;
408
- const data = await res.json();
580
+ const data = (await res.json());
409
581
  if (data.authorization_endpoint && data.token_endpoint) {
410
582
  return data;
411
583
  }
@@ -775,7 +947,9 @@ function createAdk(fs, options = {}) {
775
947
  ...final,
776
948
  proxy: {
777
949
  mode: discovered.proxy.mode,
778
- ...(discovered.proxy.agent && { agent: discovered.proxy.agent }),
950
+ ...(discovered.proxy.agent && {
951
+ agent: discovered.proxy.agent,
952
+ }),
779
953
  },
780
954
  };
781
955
  }
@@ -902,7 +1076,12 @@ function createAdk(fs, options = {}) {
902
1076
  }));
903
1077
  return results.map((r) => r.status === "fulfilled"
904
1078
  ? r.value
905
- : { name: "unknown", url: "unknown", status: "error", error: "unknown" });
1079
+ : {
1080
+ name: "unknown",
1081
+ url: "unknown",
1082
+ status: "error",
1083
+ error: "unknown",
1084
+ });
906
1085
  },
907
1086
  async auth(nameOrUrl, credential) {
908
1087
  // Encrypt the secret value up-front so the write path is uniform;
@@ -1182,7 +1361,10 @@ function createAdk(fs, options = {}) {
1182
1361
  entry = { ...entry, scheme: "registry" };
1183
1362
  }
1184
1363
  else if (entry.url) {
1185
- entry = { ...entry, scheme: entry.url.startsWith("http") ? "https" : "mcp" };
1364
+ entry = {
1365
+ ...entry,
1366
+ scheme: entry.url.startsWith("http") ? "https" : "mcp",
1367
+ };
1186
1368
  }
1187
1369
  else {
1188
1370
  throw new adk_error_js_1.AdkError({
@@ -1210,6 +1392,7 @@ function createAdk(fs, options = {}) {
1210
1392
  details: { ref: entry.ref, scheme: entry.scheme },
1211
1393
  });
1212
1394
  }
1395
+ let cacheEntry;
1213
1396
  if (hasRegistries || entry.sourceRegistry?.url) {
1214
1397
  try {
1215
1398
  const consumer = await buildConsumerForRef(entry);
@@ -1217,9 +1400,10 @@ function createAdk(fs, options = {}) {
1217
1400
  const info = await consumer.inspect(agentToInspect);
1218
1401
  const requiresValidation = !!entry.sourceRegistry;
1219
1402
  if (requiresValidation) {
1220
- const hasContent = info && (info.description ||
1221
- (info.tools && info.tools.length > 0) ||
1222
- (info.toolSummaries && info.toolSummaries.length > 0));
1403
+ const hasContent = info &&
1404
+ (info.description ||
1405
+ (info.tools && info.tools.length > 0) ||
1406
+ (info.toolSummaries && info.toolSummaries.length > 0));
1223
1407
  if (!hasContent) {
1224
1408
  // Inspect returned empty — fall back to browse to check if agent exists
1225
1409
  const registryUrl = entry.sourceRegistry?.url;
@@ -1241,7 +1425,11 @@ function createAdk(fs, options = {}) {
1241
1425
  code: "REF_NOT_FOUND",
1242
1426
  message: `Agent "${entry.ref}" not found on ${registryHint}`,
1243
1427
  hint: "Check available agents with: adk registry browse",
1244
- details: { ref: entry.ref, sourceRegistry: entry.sourceRegistry, scheme: entry.scheme },
1428
+ details: {
1429
+ ref: entry.ref,
1430
+ sourceRegistry: entry.sourceRegistry,
1431
+ scheme: entry.scheme,
1432
+ },
1245
1433
  });
1246
1434
  }
1247
1435
  }
@@ -1251,10 +1439,11 @@ function createAdk(fs, options = {}) {
1251
1439
  const agentMode = info?.mode;
1252
1440
  if (agentMode)
1253
1441
  entry.mode = agentMode;
1254
- if (info?.upstream && !entry.url && agentMode !== 'api') {
1442
+ if (info?.upstream && !entry.url && agentMode !== "api") {
1255
1443
  entry.url = info.upstream;
1256
1444
  entry.scheme = entry.scheme ?? "mcp";
1257
1445
  }
1446
+ cacheEntry = buildCacheEntry(entry.ref, info);
1258
1447
  }
1259
1448
  catch (err) {
1260
1449
  if (err instanceof adk_error_js_1.AdkError)
@@ -1263,13 +1452,17 @@ function createAdk(fs, options = {}) {
1263
1452
  code: "REGISTRY_UNREACHABLE",
1264
1453
  message: `Could not reach registry to validate "${entry.ref}"`,
1265
1454
  hint: "Check your registry connection with: adk registry test",
1266
- details: { ref: entry.ref, error: err instanceof Error ? err.message : String(err) },
1455
+ details: {
1456
+ ref: entry.ref,
1457
+ error: err instanceof Error ? err.message : String(err),
1458
+ },
1267
1459
  cause: err,
1268
1460
  });
1269
1461
  }
1270
1462
  }
1271
1463
  const refs = [...(config.refs ?? []), entry];
1272
1464
  await writeConfig({ ...config, refs });
1465
+ await upsertRegistryCacheEntry(name, cacheEntry);
1273
1466
  return { security };
1274
1467
  },
1275
1468
  async remove(name) {
@@ -1281,15 +1474,27 @@ function createAdk(fs, options = {}) {
1281
1474
  if (refs.length === before)
1282
1475
  return false;
1283
1476
  await writeConfig({ ...config, refs });
1477
+ await removeRegistryCacheEntry(name);
1284
1478
  return true;
1285
1479
  },
1286
1480
  async list() {
1287
- const config = await readConfig();
1288
- return (config.refs ?? []).map(define_config_js_1.normalizeRef);
1481
+ const [config, cache] = await Promise.all([
1482
+ readConfig(),
1483
+ readRegistryCache(),
1484
+ ]);
1485
+ return (config.refs ?? [])
1486
+ .map(define_config_js_1.normalizeRef)
1487
+ .map((r) => hydrateFromCache(r, cache));
1289
1488
  },
1290
1489
  async get(name) {
1291
- const config = await readConfig();
1292
- return findRef(config.refs ?? [], name) ?? null;
1490
+ const [config, cache] = await Promise.all([
1491
+ readConfig(),
1492
+ readRegistryCache(),
1493
+ ]);
1494
+ const found = findRef(config.refs ?? [], name);
1495
+ if (!found)
1496
+ return null;
1497
+ return hydrateFromCache(found, cache);
1293
1498
  },
1294
1499
  async update(name, updates) {
1295
1500
  const config = await readConfig();
@@ -1335,27 +1540,35 @@ function createAdk(fs, options = {}) {
1335
1540
  if (!entry)
1336
1541
  throw new Error(`Ref "${name}" not found`);
1337
1542
  const consumer = await buildConsumerForRef(entry);
1338
- return consumer.inspect(entry.sourceRegistry?.agentPath ?? entry.ref, entry.sourceRegistry?.url, opts);
1543
+ const result = await consumer.inspect(entry.sourceRegistry?.agentPath ?? entry.ref, entry.sourceRegistry?.url, opts);
1544
+ // Side-effect: refresh the registry cache so subsequent ref.list()
1545
+ // / ref.get() calls see the latest description and tool summaries
1546
+ // without another network round-trip. Strips inputSchema (caller's
1547
+ // `result` is unaffected — it still carries the full data).
1548
+ await upsertRegistryCacheEntry(name, buildCacheEntry(entry.ref, result));
1549
+ return result;
1339
1550
  },
1340
1551
  async call(name, tool, params) {
1341
1552
  const config = await readConfig();
1342
1553
  const entry = findRef(config.refs ?? [], name);
1343
1554
  if (!entry)
1344
1555
  throw new Error(`Ref "${name}" not found`);
1345
- let accessToken = await readRefSecret(name, "access_token")
1346
- ?? await readRefSecret(name, "api_key")
1347
- ?? await readRefSecret(name, "token");
1556
+ const accessToken = (await readRefSecret(name, "access_token")) ??
1557
+ (await readRefSecret(name, "api_key")) ??
1558
+ (await readRefSecret(name, "token"));
1348
1559
  // Resolve custom headers from config (e.g. { "X-API-Key": "secret:..." })
1349
1560
  const refConfig = (entry.config ?? {});
1350
1561
  const rawHeaders = refConfig.headers;
1351
1562
  let resolvedHeaders;
1352
- if (rawHeaders && typeof rawHeaders === 'object') {
1563
+ if (rawHeaders && typeof rawHeaders === "object") {
1353
1564
  resolvedHeaders = {};
1354
1565
  for (const [k, v] of Object.entries(rawHeaders)) {
1355
- if (typeof v === 'string' && v.startsWith(SECRET_PREFIX) && options.encryptionKey) {
1566
+ if (typeof v === "string" &&
1567
+ v.startsWith(SECRET_PREFIX) &&
1568
+ options.encryptionKey) {
1356
1569
  resolvedHeaders[k] = await (0, crypto_js_1.decryptSecret)(v.slice(SECRET_PREFIX.length), options.encryptionKey);
1357
1570
  }
1358
- else if (typeof v === 'string') {
1571
+ else if (typeof v === "string") {
1359
1572
  resolvedHeaders[k] = v;
1360
1573
  }
1361
1574
  }
@@ -1363,8 +1576,8 @@ function createAdk(fs, options = {}) {
1363
1576
  const doCall = async (token) => {
1364
1577
  // Direct MCP only for redirect/proxy agents with an MCP upstream.
1365
1578
  // API-mode agents must go through the registry (it does REST translation).
1366
- const agentMode = entry.mode ?? 'redirect';
1367
- if (token && entry.url && agentMode !== 'api') {
1579
+ const agentMode = entry.mode ?? "redirect";
1580
+ if (token && entry.url && agentMode !== "api") {
1368
1581
  return callMcpDirect(entry.url, tool, params ?? {}, token, resolvedHeaders);
1369
1582
  }
1370
1583
  const consumer = await buildConsumerForRef(entry);
@@ -1480,10 +1693,15 @@ function createAdk(fs, options = {}) {
1480
1693
  }
1481
1694
  else if (security.type === "apiKey") {
1482
1695
  const apiKeySec = security;
1483
- const toStorageKey = (headerName) => headerName.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
1696
+ const toStorageKey = (headerName) => headerName
1697
+ .toLowerCase()
1698
+ .replace(/[^a-z0-9]+/g, "_")
1699
+ .replace(/^_|_$/g, "");
1484
1700
  // config.headers: { "Header-Name": "value" } — check by header name (case-insensitive)
1485
1701
  const configHeaders = entry?.config?.headers;
1486
- const configHeaderKeys = configHeaders ? Object.keys(configHeaders) : [];
1702
+ const configHeaderKeys = configHeaders
1703
+ ? Object.keys(configHeaders)
1704
+ : [];
1487
1705
  const hasConfigHeader = (name) => configHeaderKeys.some((k) => k.toLowerCase() === name.toLowerCase());
1488
1706
  // Collect all declared header names from the security scheme
1489
1707
  const declaredHeaders = apiKeySec.headers
@@ -1521,6 +1739,20 @@ function createAdk(fs, options = {}) {
1521
1739
  };
1522
1740
  }
1523
1741
  const complete = Object.values(fields).every((f) => !f.required || f.present || f.resolvable);
1742
+ // Persist the slim {required, automated} per-field shape into the
1743
+ // registry cache so `isRefAuthComplete` can answer subsequent
1744
+ // host-side "is this ref ready?" checks without re-fetching the
1745
+ // security scheme. We deliberately omit `present`/`resolvable`
1746
+ // because those are computed against the current entry.config and
1747
+ // host environment — caching them would go stale immediately.
1748
+ const authFields = {};
1749
+ for (const [field, info] of Object.entries(fields)) {
1750
+ authFields[field] = {
1751
+ required: info.required,
1752
+ automated: info.automated,
1753
+ };
1754
+ }
1755
+ await upsertRegistryCacheAuthFields(name, entry.ref, authFields);
1524
1756
  return { name, security, complete, fields };
1525
1757
  },
1526
1758
  async auth(name, opts) {
@@ -1532,7 +1764,9 @@ function createAdk(fs, options = {}) {
1532
1764
  // agent. The registry owns the client_id/secret and returns an authorize
1533
1765
  // URL pointing at the registry's OAuth callback domain, so the user
1534
1766
  // completes the flow against the registry instead of localhost.
1535
- const proxy = await resolveProxyForRef(entry, { preferLocal: opts?.preferLocal });
1767
+ const proxy = await resolveProxyForRef(entry, {
1768
+ preferLocal: opts?.preferLocal,
1769
+ });
1536
1770
  if (proxy) {
1537
1771
  const params = { name };
1538
1772
  if (opts?.apiKey !== undefined)
@@ -1553,12 +1787,18 @@ function createAdk(fs, options = {}) {
1553
1787
  }
1554
1788
  if (security.type === "apiKey") {
1555
1789
  const apiKeySec = security;
1556
- const toStorageKey = (headerName) => headerName.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
1790
+ const toStorageKey = (headerName) => headerName
1791
+ .toLowerCase()
1792
+ .replace(/[^a-z0-9]+/g, "_")
1793
+ .replace(/^_|_$/g, "");
1557
1794
  // Check existing config.headers
1558
1795
  const existingHeaders = (entry.config ?? {}).headers;
1559
1796
  // Collect declared headers: from security.headers or security.name
1560
1797
  const declaredHeaders = apiKeySec.headers
1561
- ? Object.entries(apiKeySec.headers).map(([h, meta]) => ({ headerName: h, description: meta.description }))
1798
+ ? Object.entries(apiKeySec.headers).map(([h, meta]) => ({
1799
+ headerName: h,
1800
+ description: meta.description,
1801
+ }))
1562
1802
  : apiKeySec.name
1563
1803
  ? [{ headerName: apiKeySec.name }]
1564
1804
  : [];
@@ -1568,12 +1808,13 @@ function createAdk(fs, options = {}) {
1568
1808
  for (const { headerName, description } of declaredHeaders) {
1569
1809
  const storageKey = toStorageKey(headerName);
1570
1810
  // Check: credentials param → existing config.headers → legacy config key → resolve callback
1571
- const value = opts?.credentials?.[storageKey]
1572
- ?? opts?.credentials?.[headerName]
1573
- ?? (existingHeaders && Object.entries(existingHeaders).find(([k]) => k.toLowerCase() === headerName.toLowerCase())?.[1])
1574
- ?? opts?.apiKey
1575
- ?? await readRefSecret(name, storageKey)
1576
- ?? await tryResolve(storageKey);
1811
+ const value = opts?.credentials?.[storageKey] ??
1812
+ opts?.credentials?.[headerName] ??
1813
+ (existingHeaders &&
1814
+ Object.entries(existingHeaders).find(([k]) => k.toLowerCase() === headerName.toLowerCase())?.[1]) ??
1815
+ opts?.apiKey ??
1816
+ (await readRefSecret(name, storageKey)) ??
1817
+ (await tryResolve(storageKey));
1577
1818
  if (value) {
1578
1819
  resolvedHeaders[headerName] = value;
1579
1820
  }
@@ -1593,22 +1834,28 @@ function createAdk(fs, options = {}) {
1593
1834
  const encKey = options.encryptionKey;
1594
1835
  const headersToStore = {};
1595
1836
  for (const [h, v] of Object.entries(resolvedHeaders)) {
1596
- headersToStore[h] = encKey ? `${SECRET_PREFIX}${await (0, crypto_js_1.encryptSecret)(v, encKey)}` : v;
1837
+ headersToStore[h] = encKey
1838
+ ? `${SECRET_PREFIX}${await (0, crypto_js_1.encryptSecret)(v, encKey)}`
1839
+ : v;
1597
1840
  }
1598
1841
  await ref.update(name, { config: { headers: headersToStore } });
1599
1842
  return { type: "apiKey", complete: true };
1600
1843
  }
1601
1844
  // Fallback: no headers declared → generic api_key
1602
- const key = opts?.credentials?.["api_key"] ?? opts?.apiKey ?? await tryResolve("api_key");
1845
+ const key = opts?.credentials?.["api_key"] ??
1846
+ opts?.apiKey ??
1847
+ (await tryResolve("api_key"));
1603
1848
  if (!key) {
1604
1849
  return {
1605
1850
  type: "apiKey",
1606
1851
  complete: false,
1607
- fields: [{
1852
+ fields: [
1853
+ {
1608
1854
  name: "api_key",
1609
1855
  label: "API Key",
1610
1856
  secret: true,
1611
- }],
1857
+ },
1858
+ ],
1612
1859
  };
1613
1860
  }
1614
1861
  await storeRefSecret(name, "api_key", key);
@@ -1618,14 +1865,22 @@ function createAdk(fs, options = {}) {
1618
1865
  const httpSec = security;
1619
1866
  const isBasic = httpSec.scheme === "basic";
1620
1867
  if (isBasic) {
1621
- const username = opts?.credentials?.["username"] ?? await tryResolve("username");
1622
- const password = opts?.credentials?.["password"] ?? await tryResolve("password");
1868
+ const username = opts?.credentials?.["username"] ?? (await tryResolve("username"));
1869
+ const password = opts?.credentials?.["password"] ?? (await tryResolve("password"));
1623
1870
  if (!username || !password) {
1624
1871
  const missingFields = [];
1625
1872
  if (!username)
1626
- missingFields.push({ name: "username", label: "Username", secret: false });
1873
+ missingFields.push({
1874
+ name: "username",
1875
+ label: "Username",
1876
+ secret: false,
1877
+ });
1627
1878
  if (!password)
1628
- missingFields.push({ name: "password", label: "Password", secret: true });
1879
+ missingFields.push({
1880
+ name: "password",
1881
+ label: "Password",
1882
+ secret: true,
1883
+ });
1629
1884
  return { type: "http", complete: false, fields: missingFields };
1630
1885
  }
1631
1886
  // Store as base64 encoded basic auth token
@@ -1634,7 +1889,9 @@ function createAdk(fs, options = {}) {
1634
1889
  return { type: "http", complete: true };
1635
1890
  }
1636
1891
  // Bearer token
1637
- const token = opts?.credentials?.["token"] ?? opts?.apiKey ?? await tryResolve("token");
1892
+ const token = opts?.credentials?.["token"] ??
1893
+ opts?.apiKey ??
1894
+ (await tryResolve("token"));
1638
1895
  if (!token) {
1639
1896
  return {
1640
1897
  type: "http",
@@ -1691,8 +1948,9 @@ function createAdk(fs, options = {}) {
1691
1948
  const supportedAuthMethods = metadata.token_endpoint_auth_methods_supported ?? ["none"];
1692
1949
  const preferredMethod = supportedAuthMethods.includes("none")
1693
1950
  ? "none"
1694
- : supportedAuthMethods[0] ?? "client_secret_post";
1695
- const securityClientName = security.clientName;
1951
+ : (supportedAuthMethods[0] ?? "client_secret_post");
1952
+ const securityClientName = security
1953
+ .clientName;
1696
1954
  const reg = await (0, mcp_client_js_1.dynamicClientRegistration)(metadata.registration_endpoint, {
1697
1955
  clientName: securityClientName ?? options.oauthClientName ?? "adk",
1698
1956
  redirectUris: [redirectUri],
@@ -1710,10 +1968,18 @@ function createAdk(fs, options = {}) {
1710
1968
  // Return fields telling the caller what OAuth credentials to provide
1711
1969
  const missingFields = [];
1712
1970
  if (!clientId) {
1713
- missingFields.push({ name: "client_id", label: "Client ID", secret: false });
1971
+ missingFields.push({
1972
+ name: "client_id",
1973
+ label: "Client ID",
1974
+ secret: false,
1975
+ });
1714
1976
  }
1715
1977
  // Always ask for client_secret alongside client_id — most providers need it
1716
- missingFields.push({ name: "client_secret", label: "Client Secret", secret: true });
1978
+ missingFields.push({
1979
+ name: "client_secret",
1980
+ label: "Client Secret",
1981
+ secret: true,
1982
+ });
1717
1983
  return { type: "oauth2", complete: false, fields: missingFields };
1718
1984
  }
1719
1985
  // State ties the callback back to this ref. Encode as base64 JSON
@@ -1735,7 +2001,9 @@ function createAdk(fs, options = {}) {
1735
2001
  const scopes = agentScopes.length > 0
1736
2002
  ? [
1737
2003
  ...agentScopes,
1738
- ...(metadata.scopes_supported?.includes('openid') ? ['openid'] : []),
2004
+ ...(metadata.scopes_supported?.includes("openid")
2005
+ ? ["openid"]
2006
+ : []),
1739
2007
  ]
1740
2008
  : metadata.scopes_supported;
1741
2009
  // Read provider-specific authorization params from the agent's security section
@@ -1784,7 +2052,9 @@ function createAdk(fs, options = {}) {
1784
2052
  // owns the credential store, so the user needs to submit via
1785
2053
  // whatever UI the registry exposes. Supporting this through the
1786
2054
  // proxy would need a remote form endpoint — out of scope here.
1787
- if (result.fields && result.fields.length > 0 && result.type !== "oauth2") {
2055
+ if (result.fields &&
2056
+ result.fields.length > 0 &&
2057
+ result.type !== "oauth2") {
1788
2058
  if (proxy) {
1789
2059
  throw new Error(`Ref "${name}" is sourced from a proxied registry; submit credentials through ${proxy.agent} instead of a local form.`);
1790
2060
  }
@@ -1944,7 +2214,7 @@ function createAdk(fs, options = {}) {
1944
2214
  });
1945
2215
  if (!res.ok)
1946
2216
  return null;
1947
- const data = await res.json();
2217
+ const data = (await res.json());
1948
2218
  const newAccessToken = data.access_token;
1949
2219
  if (!newAccessToken)
1950
2220
  return null;
@@ -1979,7 +2249,9 @@ function createAdk(fs, options = {}) {
1979
2249
  try {
1980
2250
  stateContext = JSON.parse(atob(params.state));
1981
2251
  }
1982
- catch { /* state wasn't base64 JSON — legacy format */ }
2252
+ catch {
2253
+ /* state wasn't base64 JSON — legacy format */
2254
+ }
1983
2255
  return { refName: pending.refName, complete: true, stateContext };
1984
2256
  }
1985
2257
  return { registry, ref, readConfig, writeConfig, handleCallback };