@dudousxd/nestjs-agent-core 0.11.0 → 0.12.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/index.cjs +73 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -3
- package/dist/index.d.ts +93 -3
- package/dist/index.js +68 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -50,6 +50,7 @@ __export(index_exports, {
|
|
|
50
50
|
DefaultRolesPolicy: () => DefaultRolesPolicy,
|
|
51
51
|
QuotaExceededError: () => QuotaExceededError,
|
|
52
52
|
THREAD_DETAIL_CONTENT_CHARS: () => THREAD_DETAIL_CONTENT_CHARS,
|
|
53
|
+
ToolDisabledError: () => ToolDisabledError,
|
|
53
54
|
ToolForbiddenError: () => ToolForbiddenError,
|
|
54
55
|
ToolInputInvalidError: () => ToolInputInvalidError,
|
|
55
56
|
ToolNotFoundError: () => ToolNotFoundError,
|
|
@@ -59,12 +60,16 @@ __export(index_exports, {
|
|
|
59
60
|
bucketByModel: () => bucketByModel,
|
|
60
61
|
bucketByThread: () => bucketByThread,
|
|
61
62
|
bucketUsageTrend: () => bucketUsageTrend,
|
|
63
|
+
canActorUseTool: () => canActorUseTool,
|
|
62
64
|
dayBoundsUtc: () => dayBoundsUtc,
|
|
63
65
|
encodeStreamEvent: () => encodeStreamEvent,
|
|
64
66
|
estimateCost: () => estimateCost,
|
|
65
67
|
filterToolsByAllowList: () => filterToolsByAllowList,
|
|
68
|
+
filterToolsByCanUse: () => filterToolsByCanUse,
|
|
69
|
+
filterToolsByEnabled: () => filterToolsByEnabled,
|
|
66
70
|
filterToolsByRole: () => filterToolsByRole,
|
|
67
71
|
invokeWithTransientRetry: () => invokeWithTransientRetry,
|
|
72
|
+
isToolEnabled: () => isToolEnabled,
|
|
68
73
|
isTransientToolError: () => isTransientToolError,
|
|
69
74
|
publishAgentDelegated: () => publishAgentDelegated,
|
|
70
75
|
publishAgentMessage: () => publishAgentMessage,
|
|
@@ -308,6 +313,34 @@ function dayBoundsUtc(range) {
|
|
|
308
313
|
__name(dayBoundsUtc, "dayBoundsUtc");
|
|
309
314
|
|
|
310
315
|
// src/tool-filters.ts
|
|
316
|
+
async function isToolEnabled(spec, handler) {
|
|
317
|
+
const declared = typeof spec.enabled === "function" ? await spec.enabled() : spec.enabled ?? true;
|
|
318
|
+
if (!declared) {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
return handler?.isEnabled === void 0 ? true : await handler.isEnabled();
|
|
322
|
+
}
|
|
323
|
+
__name(isToolEnabled, "isToolEnabled");
|
|
324
|
+
async function filterToolsByEnabled(entries) {
|
|
325
|
+
const checked = await Promise.all(entries.map(async (entry) => ({
|
|
326
|
+
entry,
|
|
327
|
+
enabled: await isToolEnabled(entry.spec, entry.handler)
|
|
328
|
+
})));
|
|
329
|
+
return checked.filter((row) => row.enabled).map((row) => row.entry);
|
|
330
|
+
}
|
|
331
|
+
__name(filterToolsByEnabled, "filterToolsByEnabled");
|
|
332
|
+
async function canActorUseTool(actor, handler) {
|
|
333
|
+
return handler?.canUse === void 0 ? true : await handler.canUse(actor);
|
|
334
|
+
}
|
|
335
|
+
__name(canActorUseTool, "canActorUseTool");
|
|
336
|
+
async function filterToolsByCanUse(entries, actor) {
|
|
337
|
+
const checked = await Promise.all(entries.map(async (entry) => ({
|
|
338
|
+
entry,
|
|
339
|
+
allowed: await canActorUseTool(actor, entry.handler)
|
|
340
|
+
})));
|
|
341
|
+
return checked.filter((row) => row.allowed).map((row) => row.entry);
|
|
342
|
+
}
|
|
343
|
+
__name(filterToolsByCanUse, "filterToolsByCanUse");
|
|
311
344
|
async function filterToolsByRole(tools, actor, policy) {
|
|
312
345
|
const checked = await Promise.all(tools.map(async (tool) => ({
|
|
313
346
|
tool,
|
|
@@ -358,6 +391,16 @@ var ToolForbiddenError = class extends Error {
|
|
|
358
391
|
this.name = "ToolForbiddenError";
|
|
359
392
|
}
|
|
360
393
|
};
|
|
394
|
+
var ToolDisabledError = class extends Error {
|
|
395
|
+
static {
|
|
396
|
+
__name(this, "ToolDisabledError");
|
|
397
|
+
}
|
|
398
|
+
toolName;
|
|
399
|
+
constructor(toolName) {
|
|
400
|
+
super(`Tool "${toolName}" is disabled in this deployment`), this.toolName = toolName;
|
|
401
|
+
this.name = "ToolDisabledError";
|
|
402
|
+
}
|
|
403
|
+
};
|
|
361
404
|
var ToolNotFoundError = class extends Error {
|
|
362
405
|
static {
|
|
363
406
|
__name(this, "ToolNotFoundError");
|
|
@@ -401,10 +444,21 @@ var ToolRegistry = class {
|
|
|
401
444
|
...this.entries.values()
|
|
402
445
|
].map((entry) => entry.spec);
|
|
403
446
|
}
|
|
404
|
-
/**
|
|
447
|
+
/**
|
|
448
|
+
* The tools to offer the model for this actor+agent, after the four filter layers: what this
|
|
449
|
+
* deployment has enabled, what this actor's role allows, what each tool's own `canUse` allows
|
|
450
|
+
* this actor, and finally what this agent pinned.
|
|
451
|
+
*
|
|
452
|
+
* Every layer only ever removes tools, so no arrangement of them can widen what a turn reaches.
|
|
453
|
+
*/
|
|
405
454
|
async definitionsFor(actor, policy, allowedTools) {
|
|
406
|
-
const
|
|
407
|
-
|
|
455
|
+
const live = await filterToolsByEnabled([
|
|
456
|
+
...this.entries.values()
|
|
457
|
+
]);
|
|
458
|
+
const allowedByRole = new Set((await filterToolsByRole(live.map((entry) => entry.spec), actor, policy)).map((spec) => spec.name));
|
|
459
|
+
const roleScoped = live.filter((entry) => allowedByRole.has(entry.spec.name));
|
|
460
|
+
const actorScoped = await filterToolsByCanUse(roleScoped, actor);
|
|
461
|
+
const allowScoped = filterToolsByAllowList(actorScoped.map((entry) => entry.spec), allowedTools);
|
|
408
462
|
return allowScoped.map((spec) => ({
|
|
409
463
|
name: spec.name,
|
|
410
464
|
kind: spec.kind,
|
|
@@ -412,15 +466,25 @@ var ToolRegistry = class {
|
|
|
412
466
|
inputSchema: spec.inputSchema
|
|
413
467
|
}));
|
|
414
468
|
}
|
|
415
|
-
/**
|
|
469
|
+
/**
|
|
470
|
+
* Run a tool. Re-checks that the tool is enabled and that the role allows it (defense-in-depth —
|
|
471
|
+
* a call can reach here from a replayed durable step or an approval granted before the flag
|
|
472
|
+
* moved, neither of which went through `definitionsFor` again) and re-parses the input via Zod.
|
|
473
|
+
*/
|
|
416
474
|
async invoke(name, input, ctx, policy) {
|
|
417
475
|
const entry = this.entries.get(name);
|
|
418
476
|
if (entry === void 0) {
|
|
419
477
|
throw new ToolNotFoundError(name);
|
|
420
478
|
}
|
|
479
|
+
if (!await isToolEnabled(entry.spec, entry.handler)) {
|
|
480
|
+
throw new ToolDisabledError(name);
|
|
481
|
+
}
|
|
421
482
|
if (!await policy.can(ctx.actor, entry.spec)) {
|
|
422
483
|
throw new ToolForbiddenError(name);
|
|
423
484
|
}
|
|
485
|
+
if (!await canActorUseTool(ctx.actor, entry.handler)) {
|
|
486
|
+
throw new ToolForbiddenError(name);
|
|
487
|
+
}
|
|
424
488
|
const validation = await entry.spec.inputSchema["~standard"].validate(input);
|
|
425
489
|
if (validation.issues !== void 0) {
|
|
426
490
|
throw new ToolInputInvalidError(name, validation.issues);
|
|
@@ -1299,6 +1363,7 @@ __name(runAgentLoop, "runAgentLoop");
|
|
|
1299
1363
|
DefaultRolesPolicy,
|
|
1300
1364
|
QuotaExceededError,
|
|
1301
1365
|
THREAD_DETAIL_CONTENT_CHARS,
|
|
1366
|
+
ToolDisabledError,
|
|
1302
1367
|
ToolForbiddenError,
|
|
1303
1368
|
ToolInputInvalidError,
|
|
1304
1369
|
ToolNotFoundError,
|
|
@@ -1308,12 +1373,16 @@ __name(runAgentLoop, "runAgentLoop");
|
|
|
1308
1373
|
bucketByModel,
|
|
1309
1374
|
bucketByThread,
|
|
1310
1375
|
bucketUsageTrend,
|
|
1376
|
+
canActorUseTool,
|
|
1311
1377
|
dayBoundsUtc,
|
|
1312
1378
|
encodeStreamEvent,
|
|
1313
1379
|
estimateCost,
|
|
1314
1380
|
filterToolsByAllowList,
|
|
1381
|
+
filterToolsByCanUse,
|
|
1382
|
+
filterToolsByEnabled,
|
|
1315
1383
|
filterToolsByRole,
|
|
1316
1384
|
invokeWithTransientRetry,
|
|
1385
|
+
isToolEnabled,
|
|
1317
1386
|
isTransientToolError,
|
|
1318
1387
|
publishAgentDelegated,
|
|
1319
1388
|
publishAgentMessage,
|