@slashfi/agents-sdk 0.89.2 → 0.90.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/cjs/config-store.js +52 -10
- package/dist/cjs/config-store.js.map +1 -1
- package/dist/config-store.d.ts +7 -26
- package/dist/config-store.d.ts.map +1 -1
- package/dist/config-store.js +52 -10
- package/dist/config-store.js.map +1 -1
- package/package.json +1 -1
- package/src/config-store.test.ts +66 -1
- package/src/config-store.ts +118 -23
package/src/config-store.ts
CHANGED
|
@@ -47,7 +47,14 @@ import type {
|
|
|
47
47
|
RegistryConfiguration,
|
|
48
48
|
RegistryConsumer,
|
|
49
49
|
} from "./registry-consumer.js";
|
|
50
|
-
import type {
|
|
50
|
+
import type {
|
|
51
|
+
CallAgentErrorResponse,
|
|
52
|
+
CallAgentExecuteToolResponse,
|
|
53
|
+
CallAgentListResourcesResponse,
|
|
54
|
+
CallAgentReadResourcesResponse,
|
|
55
|
+
CallAgentResponse,
|
|
56
|
+
SecuritySchemeSummary,
|
|
57
|
+
} from "./types.js";
|
|
51
58
|
|
|
52
59
|
const CONFIG_PATH = "consumer-config.json";
|
|
53
60
|
const REGISTRY_CACHE_PATH = "registry-cache.json";
|
|
@@ -159,6 +166,40 @@ export interface RefAuthCompleteOptions {
|
|
|
159
166
|
* force callers to choose a default that's wrong half the time;
|
|
160
167
|
* `null` lets them branch explicitly.
|
|
161
168
|
*/
|
|
169
|
+
function normalizeCredentialKey(key: string): string {
|
|
170
|
+
return key
|
|
171
|
+
.toLowerCase()
|
|
172
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
173
|
+
.replace(/^_|_$/g, "");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function hasCredentialField(
|
|
177
|
+
config: Record<string, unknown>,
|
|
178
|
+
field: string,
|
|
179
|
+
): boolean {
|
|
180
|
+
const wanted = normalizeCredentialKey(field);
|
|
181
|
+
|
|
182
|
+
// Top-level config keys cover legacy entries such as api_key/token and
|
|
183
|
+
// refs whose credentials are stored directly under the cached field name.
|
|
184
|
+
for (const key of Object.keys(config)) {
|
|
185
|
+
if (normalizeCredentialKey(key) === wanted) return true;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// API-key refs store header credentials under config.headers using the
|
|
189
|
+
// original HTTP header name (for example "x-api-key"), while authStatus
|
|
190
|
+
// caches the normalized field name ("x_api_key"). Treat header keys as
|
|
191
|
+
// case-insensitive and delimiter-insensitive so the local connected check
|
|
192
|
+
// matches authStatus/ref.call behavior.
|
|
193
|
+
const headers = config.headers;
|
|
194
|
+
if (headers && typeof headers === "object" && !Array.isArray(headers)) {
|
|
195
|
+
for (const key of Object.keys(headers as Record<string, unknown>)) {
|
|
196
|
+
if (normalizeCredentialKey(key) === wanted) return true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
|
|
162
203
|
export function isRefAuthComplete(
|
|
163
204
|
entry: RefEntry,
|
|
164
205
|
cacheEntry: RegistryCacheEntry | undefined,
|
|
@@ -175,8 +216,8 @@ export function isRefAuthComplete(
|
|
|
175
216
|
for (const [field, info] of Object.entries(authFields)) {
|
|
176
217
|
if (!info.required) continue;
|
|
177
218
|
if (info.automated) continue;
|
|
178
|
-
if (field
|
|
179
|
-
if (resolvable
|
|
219
|
+
if (hasCredentialField(config, field)) continue;
|
|
220
|
+
if (resolvable?.has(field)) continue;
|
|
180
221
|
return false;
|
|
181
222
|
}
|
|
182
223
|
return true;
|
|
@@ -367,6 +408,33 @@ export interface AuthStartResult {
|
|
|
367
408
|
fields?: AuthChallengeField[];
|
|
368
409
|
}
|
|
369
410
|
|
|
411
|
+
export type AdkRefCallResult =
|
|
412
|
+
| CallAgentExecuteToolResponse
|
|
413
|
+
| CallAgentErrorResponse;
|
|
414
|
+
export type AdkRefResourcesResult =
|
|
415
|
+
| CallAgentListResourcesResponse
|
|
416
|
+
| CallAgentErrorResponse;
|
|
417
|
+
export type AdkRefReadResult =
|
|
418
|
+
| CallAgentReadResourcesResponse
|
|
419
|
+
| CallAgentErrorResponse;
|
|
420
|
+
|
|
421
|
+
type AdkRefActionResult =
|
|
422
|
+
| AdkRefCallResult
|
|
423
|
+
| AdkRefResourcesResult
|
|
424
|
+
| AdkRefReadResult;
|
|
425
|
+
|
|
426
|
+
function toAdkRefActionResult<T extends AdkRefActionResult>(
|
|
427
|
+
result: CallAgentResponse,
|
|
428
|
+
expectedKey: "result" | "resources",
|
|
429
|
+
code: string,
|
|
430
|
+
error: string,
|
|
431
|
+
): T {
|
|
432
|
+
if (result.success === false) return result as T;
|
|
433
|
+
if (expectedKey in result) return result as T;
|
|
434
|
+
|
|
435
|
+
return { success: false, error, code } as T;
|
|
436
|
+
}
|
|
437
|
+
|
|
370
438
|
/**
|
|
371
439
|
* Type slot for adk.ref.call() type safety.
|
|
372
440
|
* Empty by default — populated by `adk sync` which generates `adk.d.ts`.
|
|
@@ -391,13 +459,13 @@ type AdkRefCallFn = keyof AdkAgentRegistry extends never
|
|
|
391
459
|
name: string,
|
|
392
460
|
tool: string,
|
|
393
461
|
params?: Record<string, unknown>,
|
|
394
|
-
) => Promise<
|
|
462
|
+
) => Promise<AdkRefCallResult>
|
|
395
463
|
: // Registry populated — strict typed overload
|
|
396
464
|
<A extends AgentPath, T extends ToolsOf<A>>(
|
|
397
465
|
name: A,
|
|
398
466
|
tool: T,
|
|
399
467
|
params: ParamsOf<A, T>,
|
|
400
|
-
) => Promise<
|
|
468
|
+
) => Promise<AdkRefCallResult>;
|
|
401
469
|
|
|
402
470
|
export interface AdkRefApi {
|
|
403
471
|
add(entry: RefAddInput): Promise<{ security: SecuritySchemeSummary | null }>;
|
|
@@ -410,8 +478,8 @@ export interface AdkRefApi {
|
|
|
410
478
|
options?: { full?: boolean },
|
|
411
479
|
): Promise<AgentInspection | null>;
|
|
412
480
|
call: AdkRefCallFn;
|
|
413
|
-
resources(name: string): Promise<
|
|
414
|
-
read(name: string, uris: string[]): Promise<
|
|
481
|
+
resources(name: string): Promise<AdkRefResourcesResult>;
|
|
482
|
+
read(name: string, uris: string[]): Promise<AdkRefReadResult>;
|
|
415
483
|
/** Check auth status — what's needed vs what's stored */
|
|
416
484
|
authStatus(name: string): Promise<RefAuthStatus>;
|
|
417
485
|
/**
|
|
@@ -1935,7 +2003,10 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
1935
2003
|
scheme: entry.scheme,
|
|
1936
2004
|
received: { sourceRegistry: entry.sourceRegistry },
|
|
1937
2005
|
requiredShape: {
|
|
1938
|
-
sourceRegistry: {
|
|
2006
|
+
sourceRegistry: {
|
|
2007
|
+
url: "<registry URL>",
|
|
2008
|
+
agentPath: "<optional agent path>",
|
|
2009
|
+
},
|
|
1939
2010
|
},
|
|
1940
2011
|
},
|
|
1941
2012
|
});
|
|
@@ -2137,7 +2208,7 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
2137
2208
|
name: string,
|
|
2138
2209
|
tool: string,
|
|
2139
2210
|
params?: Record<string, unknown>,
|
|
2140
|
-
): Promise<
|
|
2211
|
+
): Promise<AdkRefCallResult> {
|
|
2141
2212
|
const config = await readConfig();
|
|
2142
2213
|
const entry = findRef(config.refs ?? [], name);
|
|
2143
2214
|
if (!entry) throw new Error(`Ref "${name}" not found`);
|
|
@@ -2181,7 +2252,11 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
2181
2252
|
code: "encryption_key_mismatch",
|
|
2182
2253
|
message: `ref.call(${name}): failed to decrypt header "${k}". The configured encryptionKey does not match the key used to encrypt this value.`,
|
|
2183
2254
|
hint: "Re-encrypt the ref's headers with the current encryptionKey, or restore the previous key. Decrypting an unrelated value would have leaked ciphertext as a header before this fix.",
|
|
2184
|
-
details: {
|
|
2255
|
+
details: {
|
|
2256
|
+
ref: name,
|
|
2257
|
+
header: k,
|
|
2258
|
+
cause: (err as Error)?.message,
|
|
2259
|
+
},
|
|
2185
2260
|
});
|
|
2186
2261
|
}
|
|
2187
2262
|
} else {
|
|
@@ -2231,14 +2306,24 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
2231
2306
|
if (accessToken && isUnauthorized(result)) {
|
|
2232
2307
|
const refreshed = await ref.refreshToken(name);
|
|
2233
2308
|
if (refreshed) {
|
|
2234
|
-
return
|
|
2309
|
+
return toAdkRefActionResult<AdkRefCallResult>(
|
|
2310
|
+
await doCall(refreshed.accessToken),
|
|
2311
|
+
"result",
|
|
2312
|
+
"unexpected_ref_call_response",
|
|
2313
|
+
"Expected execute_tool response from ref.call",
|
|
2314
|
+
);
|
|
2235
2315
|
}
|
|
2236
2316
|
}
|
|
2237
2317
|
|
|
2238
|
-
return
|
|
2318
|
+
return toAdkRefActionResult<AdkRefCallResult>(
|
|
2319
|
+
result,
|
|
2320
|
+
"result",
|
|
2321
|
+
"unexpected_ref_call_response",
|
|
2322
|
+
"Expected execute_tool response from ref.call",
|
|
2323
|
+
);
|
|
2239
2324
|
},
|
|
2240
2325
|
|
|
2241
|
-
async resources(name: string): Promise<
|
|
2326
|
+
async resources(name: string): Promise<AdkRefResourcesResult> {
|
|
2242
2327
|
const config = await readConfig();
|
|
2243
2328
|
const entry = findRef(config.refs ?? [], name);
|
|
2244
2329
|
if (!entry) throw new Error(`Ref "${name}" not found`);
|
|
@@ -2246,13 +2331,18 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
2246
2331
|
const consumer = await buildConsumerForRef(entry);
|
|
2247
2332
|
const reg = resolveRegistryForRef(consumer, entry);
|
|
2248
2333
|
|
|
2249
|
-
return
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2334
|
+
return toAdkRefActionResult<AdkRefResourcesResult>(
|
|
2335
|
+
await consumer.callRegistry(reg, {
|
|
2336
|
+
action: "list_resources",
|
|
2337
|
+
path: entry.sourceRegistry?.agentPath ?? entry.ref,
|
|
2338
|
+
}),
|
|
2339
|
+
"resources",
|
|
2340
|
+
"unexpected_ref_resources_response",
|
|
2341
|
+
"Expected list_resources response from ref.resources",
|
|
2342
|
+
);
|
|
2253
2343
|
},
|
|
2254
2344
|
|
|
2255
|
-
async read(name: string, uris: string[]): Promise<
|
|
2345
|
+
async read(name: string, uris: string[]): Promise<AdkRefReadResult> {
|
|
2256
2346
|
const config = await readConfig();
|
|
2257
2347
|
const entry = findRef(config.refs ?? [], name);
|
|
2258
2348
|
if (!entry) throw new Error(`Ref "${name}" not found`);
|
|
@@ -2260,11 +2350,16 @@ export function createAdk(fs: FsStore, options: AdkOptions = {}): Adk {
|
|
|
2260
2350
|
const consumer = await buildConsumerForRef(entry);
|
|
2261
2351
|
const reg = resolveRegistryForRef(consumer, entry);
|
|
2262
2352
|
|
|
2263
|
-
return
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2353
|
+
return toAdkRefActionResult<AdkRefReadResult>(
|
|
2354
|
+
await consumer.callRegistry(reg, {
|
|
2355
|
+
action: "read_resources",
|
|
2356
|
+
path: entry.sourceRegistry?.agentPath ?? entry.ref,
|
|
2357
|
+
uris,
|
|
2358
|
+
}),
|
|
2359
|
+
"resources",
|
|
2360
|
+
"unexpected_ref_read_response",
|
|
2361
|
+
"Expected read_resources response from ref.read",
|
|
2362
|
+
);
|
|
2268
2363
|
},
|
|
2269
2364
|
|
|
2270
2365
|
async authStatus(name: string): Promise<RefAuthStatus> {
|