@dudousxd/nestjs-agent 1.12.1 → 1.14.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 CHANGED
@@ -483,8 +483,22 @@ var AgentService = class {
483
483
  }
484
484
  return entry.id;
485
485
  }
486
- /** The model a turn runs on: the send's own, else the thread's pinned one, else none. */
486
+ /**
487
+ * The model a turn runs on: the send's own (that turn only — it is never stored on the thread),
488
+ * else the thread's pinned one, else none. An agent the catalog locks to one model runs on it
489
+ * whatever was sent or pinned, and a send naming another model is refused.
490
+ */
487
491
  async resolveModel(actor, agent, requested, threadId) {
492
+ const locked = this.models !== void 0 ? (await this.models.list({
493
+ actor,
494
+ agent
495
+ })).locked : void 0;
496
+ if (locked !== void 0) {
497
+ if (requested !== void 0 && requested !== locked.model) {
498
+ throw new import_common2.BadRequestException(`model "${requested}" cannot be selected: ${locked.reason ?? `this agent always uses "${locked.model}"`}`);
499
+ }
500
+ return locked.model;
501
+ }
488
502
  const model = requested ?? (threadId !== void 0 ? await this.threadModel(threadId) : null);
489
503
  if (model === null || model === void 0) {
490
504
  return void 0;
@@ -633,12 +647,15 @@ var AgentService = class {
633
647
  * "the user picked exactly the defaults" persist as the same answers, and no client has to
634
648
  * re-send what it was shown.
635
649
  */
636
- async answer(actor, toolCallId2, answers2 = {}) {
650
+ async answer(actor, toolCallId2, answers2 = {}, opts = {}) {
637
651
  await this.assertOwnsToolCall(actor, toolCallId2);
638
652
  await this.assertAnswersFit(toolCallId2, answers2);
639
653
  const reply = {
640
654
  answers: answers2,
641
- answeredByRef: actor.id
655
+ answeredByRef: actor.id,
656
+ ...opts.via !== void 0 ? {
657
+ answeredVia: opts.via
658
+ } : {}
642
659
  };
643
660
  return this.signalToolCall(toolCallId2, reply);
644
661
  }
@@ -647,12 +664,15 @@ var AgentService = class {
647
664
  * them: the run records this as a rejection, so a reader auditing what the agent was told can
648
665
  * tell a choice the user made from one they refused to make.
649
666
  */
650
- async skip(actor, toolCallId2) {
667
+ async skip(actor, toolCallId2, opts = {}) {
651
668
  await this.assertOwnsToolCall(actor, toolCallId2);
652
669
  const reply = {
653
670
  answers: {},
654
671
  skipped: true,
655
- answeredByRef: actor.id
672
+ answeredByRef: actor.id,
673
+ ...opts.via !== void 0 ? {
674
+ answeredVia: opts.via
675
+ } : {}
656
676
  };
657
677
  return this.signalToolCall(toolCallId2, reply);
658
678
  }
@@ -2514,7 +2534,9 @@ var ToolCallController = class {
2514
2534
  */
2515
2535
  async answer(req, body) {
2516
2536
  const actor = await this.actorResolver.resolve(req);
2517
- await this.agent.answer(actor, toolCallId(body.toolCallId), answers(body.answers));
2537
+ await this.agent.answer(actor, toolCallId(body.toolCallId), answers(body.answers), {
2538
+ via: via(body.via)
2539
+ });
2518
2540
  return {
2519
2541
  ok: true
2520
2542
  };
@@ -2522,7 +2544,9 @@ var ToolCallController = class {
2522
2544
  /** Decline to answer and let the agent proceed on the answers it pre-picked. */
2523
2545
  async skip(req, body) {
2524
2546
  const actor = await this.actorResolver.resolve(req);
2525
- await this.agent.skip(actor, toolCallId(body.toolCallId));
2547
+ await this.agent.skip(actor, toolCallId(body.toolCallId), {
2548
+ via: via(body.via)
2549
+ });
2526
2550
  return {
2527
2551
  ok: true
2528
2552
  };
@@ -2624,19 +2648,34 @@ var ToolsController = class {
2624
2648
  this.agents = agents;
2625
2649
  }
2626
2650
  async list(req, agent) {
2627
- if (agent !== void 0 && this.agents.get(agent) === void 0) {
2651
+ if (agent !== void 0 && agent !== import_nestjs_agent_core15.ALL_AGENTS && this.agents.get(agent) === void 0) {
2628
2652
  throw new import_common15.NotFoundException(`No agent named "${agent}"`);
2629
2653
  }
2630
2654
  const actor = await this.actorResolver.resolve(req);
2631
- const deps = this.depsFactory.forAgent(agent);
2632
- const specs = await deps.registry.visibleSpecs(actor, deps.rolesPolicy, deps.toolAllowList);
2633
- return specs.map((spec) => ({
2634
- name: spec.name,
2635
- kind: spec.kind,
2636
- ...spec.presentation !== void 0 ? {
2637
- presentation: spec.presentation
2638
- } : {}
2639
- }));
2655
+ const names = agent === import_nestjs_agent_core15.ALL_AGENTS ? [
2656
+ void 0,
2657
+ ...this.agents.list().map((definition) => definition.name)
2658
+ ] : [
2659
+ agent
2660
+ ];
2661
+ const entries = /* @__PURE__ */ new Map();
2662
+ for (const name of names) {
2663
+ const deps = this.depsFactory.forAgent(name);
2664
+ const specs = await deps.registry.visibleSpecs(actor, deps.rolesPolicy, deps.toolAllowList);
2665
+ for (const spec of specs) {
2666
+ if (entries.has(spec.name)) continue;
2667
+ entries.set(spec.name, {
2668
+ name: spec.name,
2669
+ kind: spec.kind,
2670
+ ...spec.presentation !== void 0 ? {
2671
+ presentation: spec.presentation
2672
+ } : {}
2673
+ });
2674
+ }
2675
+ }
2676
+ return [
2677
+ ...entries.values()
2678
+ ];
2640
2679
  }
2641
2680
  };
2642
2681
  _ts_decorate15([
@@ -3301,9 +3340,11 @@ var LedgerQuotaProvider = class {
3301
3340
  }
3302
3341
  store;
3303
3342
  limits;
3304
- constructor(store, limits = {}) {
3343
+ options;
3344
+ constructor(store, limits = {}, options = {}) {
3305
3345
  this.store = store;
3306
3346
  this.limits = limits;
3347
+ this.options = options;
3307
3348
  }
3308
3349
  async report(query) {
3309
3350
  const now = query.now ?? /* @__PURE__ */ new Date();
@@ -3317,10 +3358,14 @@ var LedgerQuotaProvider = class {
3317
3358
  windows.push(this.window("month", used.usedTokens, used.costUsd, range.resetsAt));
3318
3359
  }
3319
3360
  const blocked = (0, import_nestjs_agent_core21.exhaustedWindow)(windows);
3361
+ const warning = (0, import_nestjs_agent_core21.quotaWarning)(windows);
3320
3362
  return {
3321
3363
  windows,
3322
3364
  ...blocked !== void 0 ? {
3323
3365
  blocked
3366
+ } : {},
3367
+ ...warning !== void 0 ? {
3368
+ warning
3324
3369
  } : {}
3325
3370
  };
3326
3371
  }
@@ -3341,7 +3386,10 @@ var LedgerQuotaProvider = class {
3341
3386
  ...limits.usd !== void 0 ? {
3342
3387
  limitUsd: limits.usd
3343
3388
  } : {},
3344
- resetsAt
3389
+ resetsAt,
3390
+ ...this.options.warnAt !== void 0 && (limits.tokens !== void 0 || limits.usd !== void 0) ? {
3391
+ warnAt: this.options.warnAt
3392
+ } : {}
3345
3393
  };
3346
3394
  }
3347
3395
  };
@@ -3946,7 +3994,9 @@ function sharedProviders(durable) {
3946
3994
  // `quota` is either a provider of the host's own or ceilings for the built-in ledger one;
3947
3995
  // omitted, the ledger provider still reports usage, with no ceiling to block on.
3948
3996
  provide: import_nestjs_agent_core24.AGENT_QUOTA_PROVIDER,
3949
- useFactory: /* @__PURE__ */ __name((o, store) => isQuotaProvider(o.quota) ? o.quota : new LedgerQuotaProvider(store, o.quota?.limits), "useFactory"),
3997
+ useFactory: /* @__PURE__ */ __name((o, store) => isQuotaProvider(o.quota) ? o.quota : new LedgerQuotaProvider(store, o.quota?.limits, o.quota?.warnAt !== void 0 ? {
3998
+ warnAt: o.quota.warnAt
3999
+ } : {}), "useFactory"),
3950
4000
  inject: [
3951
4001
  import_nestjs_agent_core24.AGENT_OPTIONS,
3952
4002
  import_nestjs_agent_core24.AGENT_STORE