@slashfi/agents-sdk 0.81.0 → 0.82.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.
- package/dist/adk.js +3 -28
- package/dist/adk.js.map +1 -1
- package/dist/cjs/config-store.js +6 -205
- package/dist/cjs/config-store.js.map +1 -1
- package/dist/cjs/define-config.js.map +1 -1
- package/dist/cjs/materialize.js +3 -4
- package/dist/cjs/materialize.js.map +1 -1
- package/dist/cjs/registry-consumer.js +0 -8
- package/dist/cjs/registry-consumer.js.map +1 -1
- package/dist/cjs/server.js +0 -8
- package/dist/cjs/server.js.map +1 -1
- package/dist/config-store.d.ts +0 -14
- package/dist/config-store.d.ts.map +1 -1
- package/dist/config-store.js +6 -205
- package/dist/config-store.js.map +1 -1
- package/dist/define-config.d.ts +0 -29
- package/dist/define-config.d.ts.map +1 -1
- package/dist/define-config.js.map +1 -1
- package/dist/materialize.d.ts.map +1 -1
- package/dist/materialize.js +3 -4
- package/dist/materialize.js.map +1 -1
- package/dist/registry-consumer.d.ts +0 -10
- package/dist/registry-consumer.d.ts.map +1 -1
- package/dist/registry-consumer.js +0 -8
- package/dist/registry-consumer.js.map +1 -1
- package/dist/server.d.ts +0 -11
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +0 -8
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/adk.ts +3 -31
- package/src/config-store.test.ts +0 -185
- package/src/config-store.ts +6 -254
- package/src/define-config.ts +0 -31
- package/src/materialize.ts +3 -4
- package/src/registry-consumer.ts +0 -27
- package/src/server.ts +0 -19
package/src/config-store.ts
CHANGED
|
@@ -103,12 +103,6 @@ export interface RegistryCacheEntry {
|
|
|
103
103
|
* entry's `config` — no network round-trip needed. Absent when the
|
|
104
104
|
* scheme couldn't be fetched (e.g. registry was offline at add
|
|
105
105
|
* time); fall back to whatever heuristic the caller chooses.
|
|
106
|
-
*
|
|
107
|
-
* Note on proxy refs: when the entry is in `proxy` mode the
|
|
108
|
-
* security scheme is exposed by the *proxy*, and the answer to
|
|
109
|
-
* "is this callable?" lives server-side — `authFields` is omitted
|
|
110
|
-
* locally and hosts should treat proxy refs as authoritative
|
|
111
|
-
* regardless of entry-side fields.
|
|
112
106
|
*/
|
|
113
107
|
authFields?: Record<string, RegistryCacheAuthField>;
|
|
114
108
|
/** ISO timestamp of the most recent registry round-trip that wrote this. */
|
|
@@ -151,8 +145,6 @@ export interface RefAuthCompleteOptions {
|
|
|
151
145
|
* we evaluate satisfaction against the entry's current `config`.
|
|
152
146
|
*
|
|
153
147
|
* Behavior:
|
|
154
|
-
* - `mode: 'proxy'` refs → always true. Auth lives server-side; the
|
|
155
|
-
* proxy is the source of truth, no entry-side fields involved.
|
|
156
148
|
* - Cache miss (no `authFields` for this ref yet) → returns `null`,
|
|
157
149
|
* signaling "I don't know — caller should fall back to its own
|
|
158
150
|
* heuristic or call `auth-status` to populate the cache".
|
|
@@ -173,7 +165,6 @@ export function isRefAuthComplete(
|
|
|
173
165
|
opts?: RefAuthCompleteOptions,
|
|
174
166
|
): boolean | null {
|
|
175
167
|
if (typeof entry === "string") return false;
|
|
176
|
-
if ((entry as { mode?: unknown }).mode === "proxy") return true;
|
|
177
168
|
const authFields = cacheEntry?.authFields;
|
|
178
169
|
if (!authFields) return null;
|
|
179
170
|
const config = entry.config ?? {};
|
|
@@ -432,12 +423,6 @@ export interface AdkRefApi {
|
|
|
432
423
|
stateContext?: Record<string, unknown>;
|
|
433
424
|
/** Additional scopes to request (e.g., optional scopes declared by the agent) */
|
|
434
425
|
scopes?: string[];
|
|
435
|
-
/**
|
|
436
|
-
* Opt out of proxy routing when the ref's source registry has
|
|
437
|
-
* `proxy: { mode: 'optional' }`. Ignored for `mode: 'required'`.
|
|
438
|
-
* Defaults to `false` — if a registry offers a proxy we use it.
|
|
439
|
-
*/
|
|
440
|
-
preferLocal?: boolean;
|
|
441
426
|
},
|
|
442
427
|
): Promise<AuthStartResult>;
|
|
443
428
|
/**
|
|
@@ -1188,96 +1173,6 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
1188
1173
|
return fallback;
|
|
1189
1174
|
}
|
|
1190
1175
|
|
|
1191
|
-
// ==========================================
|
|
1192
|
-
// Proxy Routing
|
|
1193
|
-
// ==========================================
|
|
1194
|
-
|
|
1195
|
-
/**
|
|
1196
|
-
* Find the configured RegistryEntry for a ref, consulting `sourceRegistry`
|
|
1197
|
-
* first and falling back to the first registry in config. Returns `null` when
|
|
1198
|
-
* the ref is sourced from a raw URL (no registry), in which case proxy routing
|
|
1199
|
-
* does not apply.
|
|
1200
|
-
*/
|
|
1201
|
-
async function findRegistryEntryForRef(
|
|
1202
|
-
entry: RefEntry,
|
|
1203
|
-
): Promise<RegistryEntry | null> {
|
|
1204
|
-
const sourceUrl = entry.sourceRegistry?.url;
|
|
1205
|
-
if (!sourceUrl) return null;
|
|
1206
|
-
const config = await readConfig();
|
|
1207
|
-
const match = (config.registries ?? []).find((r) => {
|
|
1208
|
-
if (typeof r === "string") return r === sourceUrl;
|
|
1209
|
-
return r.url === sourceUrl;
|
|
1210
|
-
});
|
|
1211
|
-
if (!match || typeof match === "string") return null;
|
|
1212
|
-
return match;
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
/**
|
|
1216
|
-
* Returns the proxy settings for a ref when its source registry has
|
|
1217
|
-
* `proxy` configured. `null` means "run locally".
|
|
1218
|
-
*
|
|
1219
|
-
* Callers pass `{ preferLocal: true }` to opt out of `mode: 'optional'`
|
|
1220
|
-
* proxying when they already hold credentials locally. `mode: 'required'`
|
|
1221
|
-
* cannot be bypassed — the registry owns auth server-side and there is
|
|
1222
|
-
* nothing useful the local SDK can do.
|
|
1223
|
-
*/
|
|
1224
|
-
async function resolveProxyForRef(
|
|
1225
|
-
entry: RefEntry,
|
|
1226
|
-
opts?: { preferLocal?: boolean },
|
|
1227
|
-
): Promise<{ reg: RegistryEntry; agent: string } | null> {
|
|
1228
|
-
const reg = await findRegistryEntryForRef(entry);
|
|
1229
|
-
if (!reg?.proxy) return null;
|
|
1230
|
-
if (reg.proxy.mode === "optional" && opts?.preferLocal) return null;
|
|
1231
|
-
return { reg, agent: reg.proxy.agent ?? "@config" };
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
/**
|
|
1235
|
-
* Forward an `@config ref` operation to the proxy agent on a remote registry.
|
|
1236
|
-
*
|
|
1237
|
-
* The remote side speaks the standard adk-tools surface, so the call shape is
|
|
1238
|
-
* identical to what the local `ref` API would do — the only difference is
|
|
1239
|
-
* that tokens and secrets live server-side. `callRegistry` returns the
|
|
1240
|
-
* standard CallAgentResponse envelope: `{ success: true, result }` on
|
|
1241
|
-
* success or `{ success: false, error }` on failure. We unwrap once and
|
|
1242
|
-
* throw on error so callers get a result that matches the local signature.
|
|
1243
|
-
*/
|
|
1244
|
-
async function forwardRefOpToProxy<T>(
|
|
1245
|
-
reg: RegistryEntry,
|
|
1246
|
-
agent: string,
|
|
1247
|
-
operation: string,
|
|
1248
|
-
params: Record<string, unknown>,
|
|
1249
|
-
): Promise<T> {
|
|
1250
|
-
const consumer = await buildConsumerForRef({
|
|
1251
|
-
ref: "",
|
|
1252
|
-
name: "",
|
|
1253
|
-
sourceRegistry: { url: reg.url, agentPath: agent },
|
|
1254
|
-
});
|
|
1255
|
-
const resolved = consumer.registries().find((r) => r.url === reg.url);
|
|
1256
|
-
if (!resolved)
|
|
1257
|
-
throw new Error(
|
|
1258
|
-
`Registry ${reg.url} not resolvable for proxy forwarding`,
|
|
1259
|
-
);
|
|
1260
|
-
|
|
1261
|
-
const response = await consumer.callRegistry(resolved, {
|
|
1262
|
-
action: "execute_tool",
|
|
1263
|
-
path: agent,
|
|
1264
|
-
tool: "ref",
|
|
1265
|
-
params: { operation, ...params },
|
|
1266
|
-
});
|
|
1267
|
-
|
|
1268
|
-
if (!response.success) {
|
|
1269
|
-
const errResponse = response as {
|
|
1270
|
-
success: false;
|
|
1271
|
-
error?: string;
|
|
1272
|
-
code?: string;
|
|
1273
|
-
};
|
|
1274
|
-
const msg =
|
|
1275
|
-
errResponse.error ?? `Proxy ${agent}.ref(${operation}) failed`;
|
|
1276
|
-
throw new Error(msg);
|
|
1277
|
-
}
|
|
1278
|
-
return (response as { success: true; result: unknown }).result as T;
|
|
1279
|
-
}
|
|
1280
|
-
|
|
1281
1176
|
// ==========================================
|
|
1282
1177
|
// Registry API
|
|
1283
1178
|
// ==========================================
|
|
@@ -1292,39 +1187,6 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
1292
1187
|
return `${SECRET_PREFIX}${await encryptSecret(value, options.encryptionKey)}`;
|
|
1293
1188
|
}
|
|
1294
1189
|
|
|
1295
|
-
/**
|
|
1296
|
-
* Re-probe a registry with the current stored credentials to see whether it
|
|
1297
|
-
* advertises `capabilities.registry.proxy` in its MCP `initialize` response,
|
|
1298
|
-
* and persist the proxy config when it does. Safe to call after a successful
|
|
1299
|
-
* `auth()` / `authLocal()` — on the add path we skip the proxy probe when
|
|
1300
|
-
* auth is required, so this is the second chance to back-fill it.
|
|
1301
|
-
*
|
|
1302
|
-
* Respects explicit user config: if `proxy` is already set, we leave it
|
|
1303
|
-
* alone. Any discovery failure is swallowed — proxy is an optimization,
|
|
1304
|
-
* not a correctness requirement.
|
|
1305
|
-
*/
|
|
1306
|
-
async function discoverProxyAfterAuth(nameOrUrl: string): Promise<void> {
|
|
1307
|
-
const config = await readConfig();
|
|
1308
|
-
const target = findRegistry(config.registries ?? [], nameOrUrl);
|
|
1309
|
-
if (!target || typeof target === "string") return;
|
|
1310
|
-
if (target.proxy) return;
|
|
1311
|
-
|
|
1312
|
-
try {
|
|
1313
|
-
const consumer = await buildConsumer(nameOrUrl);
|
|
1314
|
-
const discovered = await consumer.discover(target.url);
|
|
1315
|
-
if (!discovered.proxy?.mode) return;
|
|
1316
|
-
await updateRegistryEntry(nameOrUrl, (existing) => {
|
|
1317
|
-
if (existing.proxy) return;
|
|
1318
|
-
existing.proxy = {
|
|
1319
|
-
mode: discovered.proxy!.mode,
|
|
1320
|
-
...(discovered.proxy!.agent && { agent: discovered.proxy!.agent }),
|
|
1321
|
-
};
|
|
1322
|
-
});
|
|
1323
|
-
} catch {
|
|
1324
|
-
// Proxy probe is best-effort — auth itself already succeeded.
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
1190
|
/**
|
|
1329
1191
|
* Atomic read-modify-write on a registry entry by name or URL. Used by
|
|
1330
1192
|
* `authLocal` to persist both `auth` and `oauth` together, which `auth()`
|
|
@@ -1476,14 +1338,10 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
1476
1338
|
(r) => registryDisplayName(r) !== alias,
|
|
1477
1339
|
);
|
|
1478
1340
|
|
|
1479
|
-
// Probe the registry before saving.
|
|
1480
|
-
//
|
|
1481
|
-
//
|
|
1482
|
-
//
|
|
1483
|
-
// 2. Proxy capability — the MCP `initialize` response may advertise
|
|
1484
|
-
// `capabilities.registry.proxy`, which auto-populates `proxy`.
|
|
1485
|
-
// Users who set `proxy` or `auth` explicitly on the entry always win:
|
|
1486
|
-
// discovery only fills in blanks.
|
|
1341
|
+
// Probe the registry before saving. If it returns 401 with a
|
|
1342
|
+
// WWW-Authenticate / RFC 9728 resource metadata pointer, persist
|
|
1343
|
+
// that on `authRequirement` so subsequent ops can refuse early
|
|
1344
|
+
// with a friendly message.
|
|
1487
1345
|
let final: RegistryEntry = entry;
|
|
1488
1346
|
let authRequirement: RegistryAuthRequirement | undefined;
|
|
1489
1347
|
|
|
@@ -1502,33 +1360,6 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
1502
1360
|
}
|
|
1503
1361
|
}
|
|
1504
1362
|
|
|
1505
|
-
if (!entry.proxy && !authRequirement) {
|
|
1506
|
-
try {
|
|
1507
|
-
const probeConsumer = await createRegistryConsumer(
|
|
1508
|
-
{ registries: [entry], refs: [] },
|
|
1509
|
-
{ token: options.token, fetch: options.fetch },
|
|
1510
|
-
);
|
|
1511
|
-
const resolved = probeConsumer.registries()[0];
|
|
1512
|
-
if (resolved) {
|
|
1513
|
-
const discovered = await probeConsumer.discover(resolved.url);
|
|
1514
|
-
if (discovered.proxy?.mode) {
|
|
1515
|
-
final = {
|
|
1516
|
-
...final,
|
|
1517
|
-
proxy: {
|
|
1518
|
-
mode: discovered.proxy.mode,
|
|
1519
|
-
...(discovered.proxy.agent && {
|
|
1520
|
-
agent: discovered.proxy.agent,
|
|
1521
|
-
}),
|
|
1522
|
-
},
|
|
1523
|
-
};
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
} catch {
|
|
1527
|
-
// Discovery is best-effort — offline, unreachable, or non-adk
|
|
1528
|
-
// registries simply skip proxy auto-configuration.
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
1363
|
registries.push(final);
|
|
1533
1364
|
await writeConfig({ ...config, registries });
|
|
1534
1365
|
return authRequirement ? { authRequirement } : {};
|
|
@@ -1579,7 +1410,6 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
1579
1410
|
if (updates.auth) existing.auth = updates.auth;
|
|
1580
1411
|
if (updates.headers)
|
|
1581
1412
|
existing.headers = { ...existing.headers, ...updates.headers };
|
|
1582
|
-
if (updates.proxy !== undefined) existing.proxy = updates.proxy;
|
|
1583
1413
|
return existing;
|
|
1584
1414
|
});
|
|
1585
1415
|
if (!found) return false;
|
|
@@ -1696,7 +1526,6 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
1696
1526
|
}
|
|
1697
1527
|
delete existing.authRequirement;
|
|
1698
1528
|
});
|
|
1699
|
-
if (updated) await discoverProxyAfterAuth(nameOrUrl);
|
|
1700
1529
|
return updated;
|
|
1701
1530
|
},
|
|
1702
1531
|
|
|
@@ -1877,7 +1706,6 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
1877
1706
|
};
|
|
1878
1707
|
delete existing.authRequirement;
|
|
1879
1708
|
});
|
|
1880
|
-
await discoverProxyAfterAuth(displayName);
|
|
1881
1709
|
resOut.writeHead(200, { "Content-Type": "text/html" });
|
|
1882
1710
|
resOut.end(renderAuthSuccess(displayName));
|
|
1883
1711
|
server.close();
|
|
@@ -2324,18 +2152,6 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
2324
2152
|
const entry = findRef(config.refs ?? [], name);
|
|
2325
2153
|
if (!entry) throw new Error(`Ref "${name}" not found`);
|
|
2326
2154
|
|
|
2327
|
-
// Registry-proxied refs: ask the remote @config for state (secrets live
|
|
2328
|
-
// server-side so local inspection would always return "missing").
|
|
2329
|
-
const proxy = await resolveProxyForRef(entry);
|
|
2330
|
-
if (proxy) {
|
|
2331
|
-
return forwardRefOpToProxy<RefAuthStatus>(
|
|
2332
|
-
proxy.reg,
|
|
2333
|
-
proxy.agent,
|
|
2334
|
-
"auth-status",
|
|
2335
|
-
{ name },
|
|
2336
|
-
);
|
|
2337
|
-
}
|
|
2338
|
-
|
|
2339
2155
|
let security: SecuritySchemeSummary | null = null;
|
|
2340
2156
|
try {
|
|
2341
2157
|
const consumer = await buildConsumerForRef(entry);
|
|
@@ -2492,38 +2308,12 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
2492
2308
|
stateContext?: Record<string, unknown>;
|
|
2493
2309
|
/** Additional scopes to request (e.g., optional scopes declared by the agent) */
|
|
2494
2310
|
scopes?: string[];
|
|
2495
|
-
/**
|
|
2496
|
-
* Opt out of proxy routing when the ref's source registry has
|
|
2497
|
-
* `proxy: { mode: 'optional' }`. Ignored for `mode: 'required'`.
|
|
2498
|
-
*/
|
|
2499
|
-
preferLocal?: boolean;
|
|
2500
2311
|
},
|
|
2501
2312
|
): Promise<AuthStartResult> {
|
|
2502
2313
|
const config = await readConfig();
|
|
2503
2314
|
const entry = findRef(config.refs ?? [], name);
|
|
2504
2315
|
if (!entry) throw new Error(`Ref "${name}" not found`);
|
|
2505
2316
|
|
|
2506
|
-
// Registry-proxied auth: forward the start-of-flow to the remote @config
|
|
2507
|
-
// agent. The registry owns the client_id/secret and returns an authorize
|
|
2508
|
-
// URL pointing at the registry's OAuth callback domain, so the user
|
|
2509
|
-
// completes the flow against the registry instead of localhost.
|
|
2510
|
-
const proxy = await resolveProxyForRef(entry, {
|
|
2511
|
-
preferLocal: opts?.preferLocal,
|
|
2512
|
-
});
|
|
2513
|
-
if (proxy) {
|
|
2514
|
-
const params: Record<string, unknown> = { name };
|
|
2515
|
-
if (opts?.apiKey !== undefined) params.apiKey = opts.apiKey;
|
|
2516
|
-
if (opts?.credentials) params.credentials = opts.credentials;
|
|
2517
|
-
if (opts?.scopes) params.scopes = opts.scopes;
|
|
2518
|
-
if (opts?.stateContext) params.stateContext = opts.stateContext;
|
|
2519
|
-
return forwardRefOpToProxy<AuthStartResult>(
|
|
2520
|
-
proxy.reg,
|
|
2521
|
-
proxy.agent,
|
|
2522
|
-
"auth",
|
|
2523
|
-
params,
|
|
2524
|
-
);
|
|
2525
|
-
}
|
|
2526
|
-
|
|
2527
2317
|
const status = await ref.authStatus(name);
|
|
2528
2318
|
const security = status.security;
|
|
2529
2319
|
const tryResolve = makeTryResolve({ name, entry, security });
|
|
@@ -2852,38 +2642,19 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
2852
2642
|
timeoutMs?: number;
|
|
2853
2643
|
},
|
|
2854
2644
|
): Promise<{ complete: boolean }> {
|
|
2855
|
-
// `ref.auth` is already proxy-aware — for proxied refs it returns
|
|
2856
|
-
// the authorizeUrl that the registry minted against its own
|
|
2857
|
-
// callback domain. Everything below is identical for local and
|
|
2858
|
-
// proxied refs except the last step (polling for the callback),
|
|
2859
|
-
// which only makes sense when we own the redirect URI.
|
|
2860
2645
|
const result = await ref.auth(name);
|
|
2861
2646
|
if (result.complete) return { complete: true };
|
|
2862
2647
|
|
|
2863
|
-
const config = await readConfig();
|
|
2864
|
-
const entry = findRef(config.refs ?? [], name);
|
|
2865
|
-
const proxy = entry ? await resolveProxyForRef(entry) : null;
|
|
2866
|
-
|
|
2867
2648
|
const port = options.oauthCallbackPort ?? 8919;
|
|
2868
2649
|
const timeout = opts?.timeoutMs ?? 300_000;
|
|
2869
2650
|
const { createServer } = await import("node:http");
|
|
2870
2651
|
|
|
2871
2652
|
// API key / HTTP auth — local credential form.
|
|
2872
|
-
//
|
|
2873
|
-
// We refuse to serve the form for a proxied ref: the registry
|
|
2874
|
-
// owns the credential store, so the user needs to submit via
|
|
2875
|
-
// whatever UI the registry exposes. Supporting this through the
|
|
2876
|
-
// proxy would need a remote form endpoint — out of scope here.
|
|
2877
2653
|
if (
|
|
2878
2654
|
result.fields &&
|
|
2879
2655
|
result.fields.length > 0 &&
|
|
2880
2656
|
result.type !== "oauth2"
|
|
2881
2657
|
) {
|
|
2882
|
-
if (proxy) {
|
|
2883
|
-
throw new Error(
|
|
2884
|
-
`Ref "${name}" is sourced from a proxied registry; submit credentials through ${proxy.agent} instead of a local form.`,
|
|
2885
|
-
);
|
|
2886
|
-
}
|
|
2887
2658
|
return new Promise<{ complete: boolean }>((resolve, reject) => {
|
|
2888
2659
|
const server = createServer(async (req, res) => {
|
|
2889
2660
|
const reqUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
@@ -2962,13 +2733,8 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
2962
2733
|
opts.onAuthorizeUrl(result.authorizeUrl);
|
|
2963
2734
|
}
|
|
2964
2735
|
|
|
2965
|
-
//
|
|
2966
|
-
//
|
|
2967
|
-
// schedule once the user finishes the remote consent screen.
|
|
2968
|
-
if (proxy) return { complete: false };
|
|
2969
|
-
|
|
2970
|
-
// Local refs: spin up the callback server on oauthCallbackPort and
|
|
2971
|
-
// block until the OAuth provider redirects back.
|
|
2736
|
+
// Spin up the callback server on oauthCallbackPort and block
|
|
2737
|
+
// until the OAuth provider redirects back.
|
|
2972
2738
|
return new Promise<{ complete: boolean }>((resolve, reject) => {
|
|
2973
2739
|
const server = createServer(async (req, res) => {
|
|
2974
2740
|
const reqUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
@@ -3013,20 +2779,6 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
3013
2779
|
},
|
|
3014
2780
|
|
|
3015
2781
|
async refreshToken(name: string): Promise<{ accessToken: string } | null> {
|
|
3016
|
-
// Registry-proxied refs: the remote @config holds the refresh_token.
|
|
3017
|
-
const entryForProxy = await ref.get(name);
|
|
3018
|
-
if (entryForProxy) {
|
|
3019
|
-
const proxy = await resolveProxyForRef(entryForProxy);
|
|
3020
|
-
if (proxy) {
|
|
3021
|
-
return forwardRefOpToProxy<{ accessToken: string } | null>(
|
|
3022
|
-
proxy.reg,
|
|
3023
|
-
proxy.agent,
|
|
3024
|
-
"refresh-token",
|
|
3025
|
-
{ name },
|
|
3026
|
-
);
|
|
3027
|
-
}
|
|
3028
|
-
}
|
|
3029
|
-
|
|
3030
2782
|
// Read stored refresh_token
|
|
3031
2783
|
const refreshToken = await readRefSecret(name, "refresh_token");
|
|
3032
2784
|
if (!refreshToken) return null;
|
package/src/define-config.ts
CHANGED
|
@@ -34,30 +34,6 @@ export type RegistryAuth =
|
|
|
34
34
|
| { type: "api-key"; key?: string; header?: string }
|
|
35
35
|
| { type: "jwt"; issuer?: string };
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
* Proxy configuration for a registry.
|
|
39
|
-
*
|
|
40
|
-
* When set, ref operations (`auth`, `auth-status`, `call`, `inspect`,
|
|
41
|
-
* `resources`, `read`, `refresh-token`) for refs sourced from this
|
|
42
|
-
* registry are forwarded to a server-side agent that implements the
|
|
43
|
-
* adk-tools surface. Use this for cloud-hosted registries that own
|
|
44
|
-
* OAuth client credentials and/or user tokens on behalf of consumers
|
|
45
|
-
* (e.g. `api.twin.slash.com/mcp`).
|
|
46
|
-
*
|
|
47
|
-
* - `mode: 'required'` — all ref ops MUST route through the proxy agent.
|
|
48
|
-
* Local handshake (`ref.authLocal`) is refused for refs from this
|
|
49
|
-
* registry because the local environment has no way to build an
|
|
50
|
-
* authorize URL without the server's client credentials.
|
|
51
|
-
* - `mode: 'optional'` — proxy is the default; callers may opt out via
|
|
52
|
-
* `{ preferLocal: true }` on a per-op basis when they already hold
|
|
53
|
-
* local credentials.
|
|
54
|
-
*/
|
|
55
|
-
export interface RegistryProxy {
|
|
56
|
-
mode: "required" | "optional";
|
|
57
|
-
/** Agent path to forward to. Defaults to `@config`. */
|
|
58
|
-
agent?: string;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
37
|
/**
|
|
62
38
|
* OAuth state captured after `adk registry auth` completes a dynamic-client
|
|
63
39
|
* registration + authorization-code flow against a registry. Stored alongside
|
|
@@ -121,13 +97,6 @@ export interface RegistryEntry {
|
|
|
121
97
|
/** Connection status — set by validation/test, used to filter active entries */
|
|
122
98
|
status?: "active" | "inactive" | "error";
|
|
123
99
|
|
|
124
|
-
/**
|
|
125
|
-
* If set, ref ops for refs sourced from this registry are forwarded
|
|
126
|
-
* to a server-side adk-tools agent (default `@config`) instead of
|
|
127
|
-
* running locally. See {@link RegistryProxy}.
|
|
128
|
-
*/
|
|
129
|
-
proxy?: RegistryProxy;
|
|
130
|
-
|
|
131
100
|
/**
|
|
132
101
|
* Populated by `adk registry add` when the probe returned 401. Cleared
|
|
133
102
|
* by `adk registry auth`. Registry ops refuse to run while this is set
|
package/src/materialize.ts
CHANGED
|
@@ -294,10 +294,9 @@ export async function materializeRef(
|
|
|
294
294
|
// to actually fetch the body. Then the per-resource field is `content`,
|
|
295
295
|
// not `text` (per `CallAgentReadResourcesResponse`).
|
|
296
296
|
//
|
|
297
|
-
//
|
|
298
|
-
// `{success,
|
|
299
|
-
//
|
|
300
|
-
// the inner registry response). Unwrap both shapes the same way.
|
|
297
|
+
// The unwrap below tolerates both `{success, resources}` (direct) and
|
|
298
|
+
// `{success, result: {resources}}` (registries that wrap responses
|
|
299
|
+
// through their MCP `tools/call` envelope) without caring which.
|
|
301
300
|
try {
|
|
302
301
|
type ResourceListEntry = {
|
|
303
302
|
uri?: string;
|
package/src/registry-consumer.ts
CHANGED
|
@@ -209,16 +209,6 @@ export interface RegistryConfiguration {
|
|
|
209
209
|
jwks_uri?: string;
|
|
210
210
|
token_endpoint?: string;
|
|
211
211
|
supported_grant_types?: string[];
|
|
212
|
-
/**
|
|
213
|
-
* When the registry advertises proxy support in its `initialize` response,
|
|
214
|
-
* consumers can auto-populate `RegistryEntry.proxy` at add time so ref ops
|
|
215
|
-
* forward to the server-side adk-tools agent automatically.
|
|
216
|
-
*/
|
|
217
|
-
proxy?: {
|
|
218
|
-
mode: "required" | "optional";
|
|
219
|
-
/** Agent path to forward to. Defaults to '@config'. */
|
|
220
|
-
agent?: string;
|
|
221
|
-
};
|
|
222
212
|
}
|
|
223
213
|
|
|
224
214
|
/** Fields common to every agent reference a registry can return. */
|
|
@@ -498,34 +488,17 @@ async function discoverRegistryViaMcp(
|
|
|
498
488
|
clientInfo: { name: "agents-sdk-consumer", version: "1.0.0" },
|
|
499
489
|
})) as {
|
|
500
490
|
serverInfo?: { name?: string; version?: string };
|
|
501
|
-
capabilities?: {
|
|
502
|
-
registry?: {
|
|
503
|
-
proxy?: {
|
|
504
|
-
mode?: "required" | "optional";
|
|
505
|
-
agent?: string;
|
|
506
|
-
};
|
|
507
|
-
};
|
|
508
|
-
};
|
|
509
491
|
};
|
|
510
492
|
|
|
511
493
|
await rpc("notifications/initialized").catch(() => {});
|
|
512
494
|
|
|
513
495
|
const issuer = issuerFromMcpUrlAndServerInfo(serverUrl, initResult?.serverInfo);
|
|
514
496
|
|
|
515
|
-
const advertisedProxy = initResult?.capabilities?.registry?.proxy;
|
|
516
|
-
const proxy = advertisedProxy?.mode
|
|
517
|
-
? {
|
|
518
|
-
mode: advertisedProxy.mode,
|
|
519
|
-
...(advertisedProxy.agent && { agent: advertisedProxy.agent }),
|
|
520
|
-
}
|
|
521
|
-
: undefined;
|
|
522
|
-
|
|
523
497
|
return {
|
|
524
498
|
issuer,
|
|
525
499
|
jwks_uri: `${issuer}/.well-known/jwks.json`,
|
|
526
500
|
token_endpoint: `${issuer}/oauth/token`,
|
|
527
501
|
supported_grant_types: ["client_credentials", "jwt_exchange"],
|
|
528
|
-
...(proxy && { proxy }),
|
|
529
502
|
};
|
|
530
503
|
}
|
|
531
504
|
|
package/src/server.ts
CHANGED
|
@@ -206,17 +206,6 @@ 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
|
-
};
|
|
220
209
|
};
|
|
221
210
|
/**
|
|
222
211
|
* Structured logger for server-side errors (tool-call failures, JWT
|
|
@@ -602,14 +591,6 @@ export function createAgentServer(
|
|
|
602
591
|
...(options.registry.oauthCallbackUrl && {
|
|
603
592
|
oauthCallbackUrl: options.registry.oauthCallbackUrl,
|
|
604
593
|
}),
|
|
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
|
-
}),
|
|
613
594
|
},
|
|
614
595
|
}),
|
|
615
596
|
},
|