@slashfi/agents-sdk 0.34.1 → 0.36.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/README.md +2 -1
- package/dist/agent-definitions/auth.d.ts +3 -3
- package/dist/agent-definitions/auth.d.ts.map +1 -1
- package/dist/agent-definitions/auth.js +10 -4
- package/dist/agent-definitions/auth.js.map +1 -1
- package/dist/agent-definitions/config.d.ts.map +1 -1
- package/dist/agent-definitions/config.js.map +1 -1
- package/dist/agent-definitions/integrations.d.ts +12 -3
- package/dist/agent-definitions/integrations.d.ts.map +1 -1
- package/dist/agent-definitions/integrations.js +35 -16
- package/dist/agent-definitions/integrations.js.map +1 -1
- package/dist/agent-definitions/remote-registry.d.ts.map +1 -1
- package/dist/agent-definitions/remote-registry.js +17 -22
- package/dist/agent-definitions/remote-registry.js.map +1 -1
- package/dist/agent-definitions/users.d.ts.map +1 -1
- package/dist/agent-definitions/users.js.map +1 -1
- package/dist/auth-governance.js.map +1 -1
- package/dist/call-agent-schema.d.ts.map +1 -1
- package/dist/call-agent-schema.js +1 -2
- package/dist/call-agent-schema.js.map +1 -1
- package/dist/cjs/agent-definitions/auth.js +10 -4
- package/dist/cjs/agent-definitions/auth.js.map +1 -1
- package/dist/cjs/agent-definitions/config.js.map +1 -1
- package/dist/cjs/agent-definitions/integrations.js +35 -16
- package/dist/cjs/agent-definitions/integrations.js.map +1 -1
- package/dist/cjs/agent-definitions/remote-registry.js +17 -22
- package/dist/cjs/agent-definitions/remote-registry.js.map +1 -1
- package/dist/cjs/agent-definitions/users.js.map +1 -1
- package/dist/cjs/auth-governance.js.map +1 -1
- package/dist/cjs/call-agent-schema.js +1 -2
- package/dist/cjs/call-agent-schema.js.map +1 -1
- package/dist/cjs/define.js.map +1 -1
- package/dist/cjs/events.js.map +1 -1
- package/dist/cjs/index.js +6 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/key-manager.js.map +1 -1
- package/dist/cjs/registry-consumer.js +60 -15
- package/dist/cjs/registry-consumer.js.map +1 -1
- package/dist/cjs/registry.js +61 -11
- package/dist/cjs/registry.js.map +1 -1
- package/dist/cjs/server.js +143 -192
- package/dist/cjs/server.js.map +1 -1
- package/dist/cjs/types.js +13 -0
- package/dist/cjs/types.js.map +1 -1
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js.map +1 -1
- package/dist/events.d.ts +85 -9
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/key-manager.d.ts.map +1 -1
- package/dist/key-manager.js +1 -1
- package/dist/key-manager.js.map +1 -1
- package/dist/registry-consumer.d.ts +8 -8
- package/dist/registry-consumer.d.ts.map +1 -1
- package/dist/registry-consumer.js +60 -15
- package/dist/registry-consumer.js.map +1 -1
- package/dist/registry.d.ts +16 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +61 -11
- package/dist/registry.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +136 -185
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/src/agent-definitions/auth.ts +31 -14
- package/src/agent-definitions/config.ts +4 -4
- package/src/agent-definitions/integrations.ts +119 -63
- package/src/agent-definitions/remote-registry.ts +65 -38
- package/src/agent-definitions/users.ts +36 -3
- package/src/auth-governance.ts +2 -2
- package/src/call-agent-schema.test.ts +4 -1
- package/src/call-agent-schema.ts +4 -3
- package/src/consumer.test.ts +4 -1
- package/src/define.ts +18 -12
- package/src/events.ts +83 -9
- package/src/hooks.test.ts +439 -0
- package/src/index.ts +14 -1
- package/src/key-manager.ts +9 -2
- package/src/registry-consumer.ts +85 -24
- package/src/registry.ts +88 -13
- package/src/server.ts +215 -239
- package/src/types.ts +62 -0
package/dist/cjs/server.js
CHANGED
|
@@ -33,9 +33,14 @@ exports.createAgentServer = createAgentServer;
|
|
|
33
33
|
const secrets_js_1 = require("./agent-definitions/secrets.js");
|
|
34
34
|
const bm25_js_1 = require("./bm25.js");
|
|
35
35
|
const jwt_js_1 = require("./jwt.js");
|
|
36
|
-
const jwt_js_2 = require("./jwt.js");
|
|
37
36
|
const oidc_signin_js_1 = require("./oidc-signin.js");
|
|
38
37
|
const call_agent_schema_js_1 = require("./call-agent-schema.js");
|
|
38
|
+
const types_js_1 = require("./types.js");
|
|
39
|
+
function parseProxyCallerType(raw) {
|
|
40
|
+
if (raw === "agent" || raw === "user" || raw === "system")
|
|
41
|
+
return raw;
|
|
42
|
+
return "agent";
|
|
43
|
+
}
|
|
39
44
|
// Auth governance — single source of truth for visibility/access control
|
|
40
45
|
var auth_governance_js_1 = require("./auth-governance.js");
|
|
41
46
|
Object.defineProperty(exports, "hasAdminScope", { enumerable: true, get: function () { return auth_governance_js_1.hasAdminScope; } });
|
|
@@ -115,7 +120,7 @@ async function resolveAuth(req, authConfig, jwksOptions) {
|
|
|
115
120
|
if (parts.length === 3 && jwksOptions?.signingKeys?.length) {
|
|
116
121
|
for (const key of jwksOptions.signingKeys) {
|
|
117
122
|
try {
|
|
118
|
-
const verified = await (0,
|
|
123
|
+
const verified = await (0, jwt_js_1.verifyJwtLocal)(credential, key.publicKey);
|
|
119
124
|
if (verified) {
|
|
120
125
|
return {
|
|
121
126
|
callerId: verified.sub ?? verified.name ?? "unknown",
|
|
@@ -138,7 +143,7 @@ async function resolveAuth(req, authConfig, jwksOptions) {
|
|
|
138
143
|
if (unverified.iss) {
|
|
139
144
|
const issuerConfig = jwksOptions.trustedIssuers.find((i) => i.issuer === unverified.iss);
|
|
140
145
|
if (issuerConfig) {
|
|
141
|
-
const verified = await (0,
|
|
146
|
+
const verified = await (0, jwt_js_1.verifyJwtFromIssuer)(credential, issuerConfig.issuer);
|
|
142
147
|
if (verified) {
|
|
143
148
|
const scopes = issuerConfig.scopes;
|
|
144
149
|
const isSystem = scopes.includes("*") || scopes.includes("agents:admin");
|
|
@@ -260,8 +265,12 @@ function createAgentServer(registry, options = {}) {
|
|
|
260
265
|
...(options.registry && {
|
|
261
266
|
registry: {
|
|
262
267
|
version: options.registry.version ?? "1.0",
|
|
263
|
-
...(options.registry.features && {
|
|
264
|
-
|
|
268
|
+
...(options.registry.features && {
|
|
269
|
+
features: options.registry.features,
|
|
270
|
+
}),
|
|
271
|
+
...(options.registry.oauthCallbackUrl && {
|
|
272
|
+
oauthCallbackUrl: options.registry.oauthCallbackUrl,
|
|
273
|
+
}),
|
|
265
274
|
},
|
|
266
275
|
}),
|
|
267
276
|
},
|
|
@@ -297,7 +306,7 @@ function createAgentServer(registry, options = {}) {
|
|
|
297
306
|
// Validate + strip nulls (OpenAI convention: null = absent)
|
|
298
307
|
const parsed = callAgentValidate.safeParse(args);
|
|
299
308
|
const req = (parsed.success
|
|
300
|
-
? parsed.data.request ?? parsed.data
|
|
309
|
+
? (parsed.data.request ?? parsed.data)
|
|
301
310
|
: (args.request ?? args));
|
|
302
311
|
// Inject auth context
|
|
303
312
|
if (auth) {
|
|
@@ -313,94 +322,97 @@ function createAgentServer(registry, options = {}) {
|
|
|
313
322
|
req.callerType = "system";
|
|
314
323
|
}
|
|
315
324
|
// Process secret params: resolve refs, store raw secrets
|
|
316
|
-
if (req.params && secretStore) {
|
|
325
|
+
if (req.action === "execute_tool" && req.params && secretStore) {
|
|
326
|
+
const execReq = req;
|
|
317
327
|
const ownerId = auth?.callerId ?? "anonymous";
|
|
318
|
-
const agent = registry.get(
|
|
319
|
-
const tool = agent?.tools.find((t) => t.name ===
|
|
328
|
+
const agent = registry.get(execReq.path);
|
|
329
|
+
const tool = agent?.tools.find((t) => t.name === execReq.tool);
|
|
320
330
|
const schema = tool?.inputSchema;
|
|
321
|
-
const { resolved } = await (0, secrets_js_1.processSecretParams)(
|
|
322
|
-
|
|
331
|
+
const { resolved } = await (0, secrets_js_1.processSecretParams)(execReq.params, schema, secretStore, ownerId);
|
|
332
|
+
execReq.params = resolved;
|
|
323
333
|
}
|
|
324
334
|
const result = await registry.call(req);
|
|
325
335
|
return mcpResult(result);
|
|
326
336
|
}
|
|
327
337
|
case "list_agents": {
|
|
328
|
-
const { query: listQuery, limit: listLimit, cursor: listCursor } = listAgentsValidate.parse(args);
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
// Alphabetical listing — sorted by path
|
|
370
|
-
visible.sort((a, b) => a.path.localeCompare(b.path));
|
|
371
|
-
// Apply cursor: skip past afterPath
|
|
372
|
-
if (after) {
|
|
373
|
-
visible = visible.filter((a) => a.path > after.path);
|
|
338
|
+
const { query: listQuery, limit: listLimit, cursor: listCursor, } = listAgentsValidate.parse(args);
|
|
339
|
+
const result = await registry.listAgents({ query: listQuery, limit: listLimit, cursor: listCursor }, async (allAgents) => {
|
|
340
|
+
let visible = allAgents.filter((agent) => (0, auth_governance_js_2.canSeeAgent)(agent, auth));
|
|
341
|
+
// Decode cursor if provided
|
|
342
|
+
const after = listCursor
|
|
343
|
+
? JSON.parse(Buffer.from(listCursor, "base64url").toString())
|
|
344
|
+
: undefined;
|
|
345
|
+
const pageSize = listLimit ?? 20;
|
|
346
|
+
let page;
|
|
347
|
+
let nextCursor;
|
|
348
|
+
if (listQuery) {
|
|
349
|
+
// BM25 search — ranked by score desc, path asc for tie-breaking
|
|
350
|
+
const docs = visible.map((agent, i) => ({
|
|
351
|
+
id: String(i),
|
|
352
|
+
text: [
|
|
353
|
+
agent.path,
|
|
354
|
+
agent.config?.name ?? "",
|
|
355
|
+
agent.config?.description ?? "",
|
|
356
|
+
...agent.tools
|
|
357
|
+
.filter((t) => (0, auth_governance_js_2.canSeeTool)(t, auth))
|
|
358
|
+
.map((t) => `${t.name} ${t.description}`),
|
|
359
|
+
].join(" "),
|
|
360
|
+
}));
|
|
361
|
+
const index = (0, bm25_js_1.createBM25Index)(docs);
|
|
362
|
+
const ranked = index.search(listQuery);
|
|
363
|
+
let scored = ranked.map((r) => ({
|
|
364
|
+
...visible[Number(r.id)],
|
|
365
|
+
_score: r.score,
|
|
366
|
+
}));
|
|
367
|
+
// Apply cursor: skip past the after position
|
|
368
|
+
if (after?.score !== undefined) {
|
|
369
|
+
scored = scored.filter((a) => a._score < after.score ||
|
|
370
|
+
(a._score === after.score && a.path > after.path));
|
|
371
|
+
}
|
|
372
|
+
page = scored.slice(0, pageSize);
|
|
373
|
+
if (scored.length > pageSize) {
|
|
374
|
+
const last = scored[pageSize - 1];
|
|
375
|
+
nextCursor = Buffer.from(JSON.stringify({ path: last.path, score: last._score })).toString("base64url");
|
|
376
|
+
}
|
|
374
377
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
378
|
+
else {
|
|
379
|
+
// Alphabetical listing — sorted by path
|
|
380
|
+
visible.sort((a, b) => a.path.localeCompare(b.path));
|
|
381
|
+
// Apply cursor: skip past afterPath
|
|
382
|
+
if (after) {
|
|
383
|
+
visible = visible.filter((a) => a.path > after.path);
|
|
384
|
+
}
|
|
385
|
+
page = visible.slice(0, pageSize);
|
|
386
|
+
if (visible.length > pageSize) {
|
|
387
|
+
const last = page[page.length - 1];
|
|
388
|
+
nextCursor = Buffer.from(JSON.stringify({ path: last.path })).toString("base64url");
|
|
389
|
+
}
|
|
379
390
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
:
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
391
|
+
return {
|
|
392
|
+
success: true,
|
|
393
|
+
total: allAgents.filter((a) => (0, auth_governance_js_2.canSeeAgent)(a, auth)).length,
|
|
394
|
+
nextCursor,
|
|
395
|
+
agents: page.map((agent) => ({
|
|
396
|
+
path: agent.path,
|
|
397
|
+
name: agent.config?.name,
|
|
398
|
+
description: agent.config?.description,
|
|
399
|
+
supportedActions: agent.config?.supportedActions,
|
|
400
|
+
integration: agent.config?.integration || null,
|
|
401
|
+
security: agent.config?.security
|
|
402
|
+
? { type: agent.config.security.type }
|
|
403
|
+
: undefined,
|
|
404
|
+
resources: agent.config?.resources?.map((r) => ({
|
|
405
|
+
uri: r.uri,
|
|
406
|
+
name: r.name,
|
|
407
|
+
mimeType: r.mimeType,
|
|
408
|
+
})),
|
|
409
|
+
tools: agent.tools
|
|
410
|
+
.filter((t) => (0, auth_governance_js_2.canSeeTool)(t, auth))
|
|
411
|
+
.map((t) => t.name),
|
|
398
412
|
})),
|
|
399
|
-
|
|
400
|
-
.filter((t) => (0, auth_governance_js_2.canSeeTool)(t, auth))
|
|
401
|
-
.map((t) => t.name),
|
|
402
|
-
})),
|
|
413
|
+
};
|
|
403
414
|
});
|
|
415
|
+
return mcpResult(result);
|
|
404
416
|
}
|
|
405
417
|
default:
|
|
406
418
|
throw new Error(`Unknown tool: ${toolName}`);
|
|
@@ -459,15 +471,20 @@ function createAgentServer(registry, options = {}) {
|
|
|
459
471
|
params: { token: assertion },
|
|
460
472
|
callerType: "system",
|
|
461
473
|
});
|
|
462
|
-
|
|
463
|
-
// If the tool call failed, forward the error
|
|
464
|
-
if (result?.success === false) {
|
|
474
|
+
if ((0, types_js_1.isCallAgentErrorResponse)(result)) {
|
|
465
475
|
return jsonResponse({
|
|
466
476
|
error: "server_error",
|
|
467
|
-
error_description: result
|
|
477
|
+
error_description: result.error ?? "Exchange tool failed",
|
|
468
478
|
raw: JSON.stringify(result)?.slice(0, 300),
|
|
469
479
|
}, 500);
|
|
470
480
|
}
|
|
481
|
+
if (!("result" in result)) {
|
|
482
|
+
return jsonResponse({
|
|
483
|
+
error: "server_error",
|
|
484
|
+
error_description: `Unexpected exchange response: ${JSON.stringify(result)?.slice(0, 300)}`,
|
|
485
|
+
}, 500);
|
|
486
|
+
}
|
|
487
|
+
const exchangeResult = result.result;
|
|
471
488
|
// ── Reverse registration: if caller is an agent-registry, auto-store connection ──
|
|
472
489
|
try {
|
|
473
490
|
const assertionParts = assertion.split(".");
|
|
@@ -508,7 +525,7 @@ function createAgentServer(registry, options = {}) {
|
|
|
508
525
|
}, 500);
|
|
509
526
|
}
|
|
510
527
|
// User not linked yet — needs OAuth identity linking
|
|
511
|
-
if (
|
|
528
|
+
if ((0, types_js_1.isExchangeTokenNeedsIdentity)(exchangeResult)) {
|
|
512
529
|
const baseUrl = resolveBaseUrl(req);
|
|
513
530
|
const authorizeUrl = new URL(`${baseUrl}${basePath}/oauth/authorize`);
|
|
514
531
|
authorizeUrl.searchParams.set("token", assertion);
|
|
@@ -526,9 +543,10 @@ function createAgentServer(registry, options = {}) {
|
|
|
526
543
|
}, 403);
|
|
527
544
|
}
|
|
528
545
|
// User found — sign a local access token
|
|
529
|
-
if (
|
|
546
|
+
if ((0, types_js_1.isExchangeTokenLinkedSuccess)(exchangeResult) &&
|
|
547
|
+
serverSigningKeys.length > 0) {
|
|
530
548
|
const sigKey = serverSigningKeys[0];
|
|
531
|
-
const token = await (0,
|
|
549
|
+
const token = await (0, jwt_js_1.signJwtES256)({
|
|
532
550
|
sub: exchangeResult.userId,
|
|
533
551
|
name: exchangeResult.userId,
|
|
534
552
|
scopes: ["*"],
|
|
@@ -570,8 +588,20 @@ function createAgentServer(registry, options = {}) {
|
|
|
570
588
|
params: { clientId, clientSecret },
|
|
571
589
|
callerType: "system",
|
|
572
590
|
});
|
|
573
|
-
|
|
574
|
-
|
|
591
|
+
if ((0, types_js_1.isCallAgentErrorResponse)(result)) {
|
|
592
|
+
return jsonResponse({
|
|
593
|
+
error: "invalid_client",
|
|
594
|
+
error_description: result.error ?? "Authentication failed",
|
|
595
|
+
}, 401);
|
|
596
|
+
}
|
|
597
|
+
if (!("result" in result)) {
|
|
598
|
+
return jsonResponse({
|
|
599
|
+
error: "invalid_client",
|
|
600
|
+
error_description: "Authentication failed",
|
|
601
|
+
}, 401);
|
|
602
|
+
}
|
|
603
|
+
const tokenResult = result.result;
|
|
604
|
+
if (tokenResult.accessToken == null) {
|
|
575
605
|
return jsonResponse({
|
|
576
606
|
error: "invalid_client",
|
|
577
607
|
error_description: "Authentication failed",
|
|
@@ -622,7 +652,7 @@ function createAgentServer(registry, options = {}) {
|
|
|
622
652
|
if (actorId) {
|
|
623
653
|
return {
|
|
624
654
|
callerId: actorId,
|
|
625
|
-
callerType: actorType
|
|
655
|
+
callerType: parseProxyCallerType(actorType),
|
|
626
656
|
scopes: ["*"],
|
|
627
657
|
claims: {},
|
|
628
658
|
};
|
|
@@ -685,7 +715,7 @@ function createAgentServer(registry, options = {}) {
|
|
|
685
715
|
console.log("[oauth/authorize] storeIssuers:", storeIssuers.length, "configIssuers:", configIssuerUrls.length, "total:", allIssuerUrls.length, "urls:", allIssuerUrls);
|
|
686
716
|
for (const issuerUrl of allIssuerUrls) {
|
|
687
717
|
try {
|
|
688
|
-
const result = await (0,
|
|
718
|
+
const result = await (0, jwt_js_1.verifyJwtFromIssuer)(token, issuerUrl);
|
|
689
719
|
console.log("[oauth/authorize] verify", issuerUrl, "->", result ? "OK" : "null");
|
|
690
720
|
if (result) {
|
|
691
721
|
claims = result;
|
|
@@ -693,7 +723,7 @@ function createAgentServer(registry, options = {}) {
|
|
|
693
723
|
}
|
|
694
724
|
}
|
|
695
725
|
catch (e) {
|
|
696
|
-
console.log("[oauth/authorize] verify", issuerUrl, "-> ERROR:", e.message);
|
|
726
|
+
console.log("[oauth/authorize] verify", issuerUrl, "-> ERROR:", e instanceof Error ? e.message : String(e));
|
|
697
727
|
}
|
|
698
728
|
}
|
|
699
729
|
if (!claims) {
|
|
@@ -740,28 +770,11 @@ function createAgentServer(registry, options = {}) {
|
|
|
740
770
|
// ── GET /.well-known/jwks.json → JWKS public keys ──
|
|
741
771
|
if (path === "/.well-known/jwks.json" && req.method === "GET") {
|
|
742
772
|
const jwks = serverSigningKeys.length > 0
|
|
743
|
-
? await (0,
|
|
773
|
+
? await (0, jwt_js_1.buildJwks)(serverSigningKeys)
|
|
744
774
|
: { keys: [] };
|
|
745
775
|
const res = jsonResponse(jwks);
|
|
746
776
|
return cors ? addCors(res) : res;
|
|
747
777
|
}
|
|
748
|
-
// ── GET /.well-known/configuration → Server discovery (deprecated, use MCP initialize capabilities) ──
|
|
749
|
-
if (path === "/.well-known/configuration" && req.method === "GET") {
|
|
750
|
-
const baseUrl = resolveBaseUrl(req);
|
|
751
|
-
const res = jsonResponse({
|
|
752
|
-
issuer: baseUrl,
|
|
753
|
-
jwks_uri: `${baseUrl}/.well-known/jwks.json`,
|
|
754
|
-
token_endpoint: `${baseUrl}/oauth/token`,
|
|
755
|
-
agents_endpoint: `${baseUrl}/list`,
|
|
756
|
-
call_endpoint: baseUrl,
|
|
757
|
-
supported_grant_types: ["client_credentials", "jwt_exchange"],
|
|
758
|
-
authorization_endpoint: `${baseUrl}/oauth/authorize`,
|
|
759
|
-
...(oidcSignIn
|
|
760
|
-
? { signin_endpoint: `${baseUrl}/signin/authorize` }
|
|
761
|
-
: {}),
|
|
762
|
-
});
|
|
763
|
-
return cors ? addCors(res) : res;
|
|
764
|
-
}
|
|
765
778
|
// ── GET /.well-known/oauth-authorization-server → OAuth Server Metadata (RFC 8414) ──
|
|
766
779
|
// Only exposed when the server requires auth (private registries).
|
|
767
780
|
// Public registries (e.g. registry.slash.com) skip this entirely.
|
|
@@ -778,7 +791,11 @@ function createAgentServer(registry, options = {}) {
|
|
|
778
791
|
token_endpoint: `${baseUrl}/oauth/token`,
|
|
779
792
|
jwks_uri: `${baseUrl}/.well-known/jwks.json`,
|
|
780
793
|
response_types_supported: ["code"],
|
|
781
|
-
grant_types_supported: [
|
|
794
|
+
grant_types_supported: [
|
|
795
|
+
"authorization_code",
|
|
796
|
+
"client_credentials",
|
|
797
|
+
"jwt_exchange",
|
|
798
|
+
],
|
|
782
799
|
code_challenge_methods_supported: ["S256"],
|
|
783
800
|
token_endpoint_auth_methods_supported: ["client_secret_post", "none"],
|
|
784
801
|
...(options.registry?.oauthCallbackUrl && {
|
|
@@ -787,78 +804,6 @@ function createAgentServer(registry, options = {}) {
|
|
|
787
804
|
});
|
|
788
805
|
return cors ? addCors(res) : res;
|
|
789
806
|
}
|
|
790
|
-
// ── GET /list → List agents (──
|
|
791
|
-
if (path === "/list" && req.method === "GET") {
|
|
792
|
-
const agents = registry.list();
|
|
793
|
-
let visible = agents.filter((agent) => (0, auth_governance_js_2.canSeeAgent)(agent, effectiveAuth));
|
|
794
|
-
const searchQuery = url.searchParams.get("q");
|
|
795
|
-
const searchLimit = url.searchParams.get("limit");
|
|
796
|
-
const searchCursor = url.searchParams.get("cursor");
|
|
797
|
-
// Decode cursor
|
|
798
|
-
const httpAfter = searchCursor
|
|
799
|
-
? JSON.parse(Buffer.from(searchCursor, "base64url").toString())
|
|
800
|
-
: undefined;
|
|
801
|
-
const httpPageSize = searchLimit ? Number(searchLimit) : 20;
|
|
802
|
-
let httpPage;
|
|
803
|
-
let httpNextCursor;
|
|
804
|
-
if (searchQuery) {
|
|
805
|
-
const docs = visible.map((agent, i) => ({
|
|
806
|
-
id: String(i),
|
|
807
|
-
text: [
|
|
808
|
-
agent.path,
|
|
809
|
-
agent.config?.name ?? "",
|
|
810
|
-
agent.config?.description ?? "",
|
|
811
|
-
...agent.tools
|
|
812
|
-
.filter((t) => (0, auth_governance_js_2.canSeeTool)(t, effectiveAuth))
|
|
813
|
-
.map((t) => `${t.name} ${t.description}`),
|
|
814
|
-
].join(" "),
|
|
815
|
-
}));
|
|
816
|
-
const index = (0, bm25_js_1.createBM25Index)(docs);
|
|
817
|
-
const ranked = index.search(searchQuery);
|
|
818
|
-
let scored = ranked.map((r) => ({
|
|
819
|
-
...visible[Number(r.id)],
|
|
820
|
-
_score: r.score,
|
|
821
|
-
}));
|
|
822
|
-
if (httpAfter?.score !== undefined) {
|
|
823
|
-
scored = scored.filter((a) => a._score < httpAfter.score ||
|
|
824
|
-
(a._score === httpAfter.score && a.path > httpAfter.path));
|
|
825
|
-
}
|
|
826
|
-
httpPage = scored.slice(0, httpPageSize);
|
|
827
|
-
if (scored.length > httpPageSize) {
|
|
828
|
-
const last = scored[httpPageSize - 1];
|
|
829
|
-
httpNextCursor = Buffer.from(JSON.stringify({ path: last.path, score: last._score })).toString("base64url");
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
else {
|
|
833
|
-
visible.sort((a, b) => a.path.localeCompare(b.path));
|
|
834
|
-
if (httpAfter) {
|
|
835
|
-
visible = visible.filter((a) => a.path > httpAfter.path);
|
|
836
|
-
}
|
|
837
|
-
httpPage = visible.slice(0, httpPageSize);
|
|
838
|
-
if (visible.length > httpPageSize) {
|
|
839
|
-
const last = httpPage[httpPage.length - 1];
|
|
840
|
-
httpNextCursor = Buffer.from(JSON.stringify({ path: last.path })).toString("base64url");
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
const res = jsonResponse({
|
|
844
|
-
total: agents.filter((a) => (0, auth_governance_js_2.canSeeAgent)(a, effectiveAuth)).length,
|
|
845
|
-
nextCursor: httpNextCursor,
|
|
846
|
-
agents: httpPage.map((agent) => ({
|
|
847
|
-
path: agent.path,
|
|
848
|
-
name: agent.config?.name,
|
|
849
|
-
description: agent.config?.description,
|
|
850
|
-
supportedActions: agent.config?.supportedActions,
|
|
851
|
-
integration: agent.config?.integration || null,
|
|
852
|
-
tools: agent.tools
|
|
853
|
-
.filter((t) => (0, auth_governance_js_2.canSeeTool)(t, effectiveAuth))
|
|
854
|
-
.map((t) => ({
|
|
855
|
-
name: t.name,
|
|
856
|
-
description: t.description,
|
|
857
|
-
})),
|
|
858
|
-
})),
|
|
859
|
-
});
|
|
860
|
-
return cors ? addCors(res) : res;
|
|
861
|
-
}
|
|
862
807
|
// ── GET /agents → List public agents (discovery endpoint) ──
|
|
863
808
|
if (path === "/agents" && req.method === "GET") {
|
|
864
809
|
const agents = registry.list();
|
|
@@ -872,7 +817,7 @@ function createAgentServer(registry, options = {}) {
|
|
|
872
817
|
path: agent.path,
|
|
873
818
|
name: agent.config?.name,
|
|
874
819
|
description: agent.config?.description ?? agent.entrypoint?.slice(0, 200),
|
|
875
|
-
mode: agent.mode ??
|
|
820
|
+
mode: agent.mode ?? "direct",
|
|
876
821
|
...(agent.upstream && { upstream: agent.upstream }),
|
|
877
822
|
tools: (0, auth_governance_js_2.getVisibleTools)(agent, effectiveAuth).map((t) => ({
|
|
878
823
|
name: t.name,
|
|
@@ -893,7 +838,7 @@ function createAgentServer(registry, options = {}) {
|
|
|
893
838
|
path: agent.path,
|
|
894
839
|
name: agent.config?.name,
|
|
895
840
|
description: agent.config?.description ?? agent.entrypoint?.slice(0, 200),
|
|
896
|
-
mode: agent.mode ??
|
|
841
|
+
mode: agent.mode ?? "direct",
|
|
897
842
|
...(agent.upstream && { upstream: agent.upstream }),
|
|
898
843
|
tools: (0, auth_governance_js_2.getVisibleTools)(agent, effectiveAuth).map((t) => ({
|
|
899
844
|
name: t.name,
|
|
@@ -1045,14 +990,14 @@ function createAgentServer(registry, options = {}) {
|
|
|
1045
990
|
else if (authConfig?.store && serverSigningKeys.length === 0) {
|
|
1046
991
|
const stored = (await authConfig.store.getSigningKeys()) ?? [];
|
|
1047
992
|
for (const exported of stored) {
|
|
1048
|
-
serverSigningKeys.push(await (0,
|
|
993
|
+
serverSigningKeys.push(await (0, jwt_js_1.importSigningKey)(exported));
|
|
1049
994
|
}
|
|
1050
995
|
}
|
|
1051
996
|
if (serverSigningKeys.length === 0) {
|
|
1052
|
-
const key = await (0,
|
|
997
|
+
const key = await (0, jwt_js_1.generateSigningKey)();
|
|
1053
998
|
serverSigningKeys.push(key);
|
|
1054
999
|
if (authConfig?.store) {
|
|
1055
|
-
await authConfig.store.storeSigningKey(await (0,
|
|
1000
|
+
await authConfig.store.storeSigningKey(await (0, jwt_js_1.exportSigningKey)(key));
|
|
1056
1001
|
}
|
|
1057
1002
|
}
|
|
1058
1003
|
},
|
|
@@ -1079,7 +1024,13 @@ function createAgentServer(registry, options = {}) {
|
|
|
1079
1024
|
throw new Error("No signing keys available. Call start() or initKeys() first.");
|
|
1080
1025
|
}
|
|
1081
1026
|
const key = serverSigningKeys[0];
|
|
1082
|
-
|
|
1027
|
+
const payload = {
|
|
1028
|
+
sub: "system",
|
|
1029
|
+
name: "atlas-os",
|
|
1030
|
+
scopes: ["*"],
|
|
1031
|
+
...claims,
|
|
1032
|
+
};
|
|
1033
|
+
return (0, jwt_js_1.signJwtES256)(payload, key.privateKey, key.kid, options.serverName ?? "agents-sdk", claims.exp != null ? undefined : "1h");
|
|
1083
1034
|
},
|
|
1084
1035
|
async resolveAuth(req) {
|
|
1085
1036
|
const customAuth = options.resolveAuth
|