@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.
@@ -1,6 +1,6 @@
1
1
  import { AgentStore, AgentRunInput, AgentLoopResult, LlmStepEnvelope, BufferedModelTurnResult, ToolStepEnvelope, AgentRunner, TokenStreamSink, HumanReply } from '@dudousxd/nestjs-agent-core';
2
2
  import { RunGateway, WorkflowCtx } from '@dudousxd/nestjs-durable-core';
3
- import { A as AgentDepsFactory, a as AgentSurface, b as AgentModuleOptions } from '../agent-deps.factory-pqv_qTmJ.cjs';
3
+ import { A as AgentDepsFactory, a as AgentSurface, b as AgentModuleOptions } from '../agent-deps.factory-DkWvoWbD.cjs';
4
4
  import { WorkflowService } from '@dudousxd/nestjs-durable';
5
5
  import { DynamicModule } from '@nestjs/common';
6
6
  import '@standard-schema/spec';
@@ -1,6 +1,6 @@
1
1
  import { AgentStore, AgentRunInput, AgentLoopResult, LlmStepEnvelope, BufferedModelTurnResult, ToolStepEnvelope, AgentRunner, TokenStreamSink, HumanReply } from '@dudousxd/nestjs-agent-core';
2
2
  import { RunGateway, WorkflowCtx } from '@dudousxd/nestjs-durable-core';
3
- import { A as AgentDepsFactory, a as AgentSurface, b as AgentModuleOptions } from '../agent-deps.factory-pqv_qTmJ.js';
3
+ import { A as AgentDepsFactory, a as AgentSurface, b as AgentModuleOptions } from '../agent-deps.factory-DkWvoWbD.js';
4
4
  import { WorkflowService } from '@dudousxd/nestjs-durable';
5
5
  import { DynamicModule } from '@nestjs/common';
6
6
  import '@standard-schema/spec';
@@ -1191,8 +1191,22 @@ var AgentService = class {
1191
1191
  }
1192
1192
  return entry.id;
1193
1193
  }
1194
- /** The model a turn runs on: the send's own, else the thread's pinned one, else none. */
1194
+ /**
1195
+ * The model a turn runs on: the send's own (that turn only — it is never stored on the thread),
1196
+ * else the thread's pinned one, else none. An agent the catalog locks to one model runs on it
1197
+ * whatever was sent or pinned, and a send naming another model is refused.
1198
+ */
1195
1199
  async resolveModel(actor, agent, requested, threadId) {
1200
+ const locked = this.models !== void 0 ? (await this.models.list({
1201
+ actor,
1202
+ agent
1203
+ })).locked : void 0;
1204
+ if (locked !== void 0) {
1205
+ if (requested !== void 0 && requested !== locked.model) {
1206
+ throw new BadRequestException(`model "${requested}" cannot be selected: ${locked.reason ?? `this agent always uses "${locked.model}"`}`);
1207
+ }
1208
+ return locked.model;
1209
+ }
1196
1210
  const model = requested ?? (threadId !== void 0 ? await this.threadModel(threadId) : null);
1197
1211
  if (model === null || model === void 0) {
1198
1212
  return void 0;
@@ -1341,12 +1355,15 @@ var AgentService = class {
1341
1355
  * "the user picked exactly the defaults" persist as the same answers, and no client has to
1342
1356
  * re-send what it was shown.
1343
1357
  */
1344
- async answer(actor, toolCallId2, answers2 = {}) {
1358
+ async answer(actor, toolCallId2, answers2 = {}, opts = {}) {
1345
1359
  await this.assertOwnsToolCall(actor, toolCallId2);
1346
1360
  await this.assertAnswersFit(toolCallId2, answers2);
1347
1361
  const reply = {
1348
1362
  answers: answers2,
1349
- answeredByRef: actor.id
1363
+ answeredByRef: actor.id,
1364
+ ...opts.via !== void 0 ? {
1365
+ answeredVia: opts.via
1366
+ } : {}
1350
1367
  };
1351
1368
  return this.signalToolCall(toolCallId2, reply);
1352
1369
  }
@@ -1355,12 +1372,15 @@ var AgentService = class {
1355
1372
  * them: the run records this as a rejection, so a reader auditing what the agent was told can
1356
1373
  * tell a choice the user made from one they refused to make.
1357
1374
  */
1358
- async skip(actor, toolCallId2) {
1375
+ async skip(actor, toolCallId2, opts = {}) {
1359
1376
  await this.assertOwnsToolCall(actor, toolCallId2);
1360
1377
  const reply = {
1361
1378
  answers: {},
1362
1379
  skipped: true,
1363
- answeredByRef: actor.id
1380
+ answeredByRef: actor.id,
1381
+ ...opts.via !== void 0 ? {
1382
+ answeredVia: opts.via
1383
+ } : {}
1364
1384
  };
1365
1385
  return this.signalToolCall(toolCallId2, reply);
1366
1386
  }
@@ -3222,7 +3242,9 @@ var ToolCallController = class {
3222
3242
  */
3223
3243
  async answer(req, body) {
3224
3244
  const actor = await this.actorResolver.resolve(req);
3225
- await this.agent.answer(actor, toolCallId(body.toolCallId), answers(body.answers));
3245
+ await this.agent.answer(actor, toolCallId(body.toolCallId), answers(body.answers), {
3246
+ via: via(body.via)
3247
+ });
3226
3248
  return {
3227
3249
  ok: true
3228
3250
  };
@@ -3230,7 +3252,9 @@ var ToolCallController = class {
3230
3252
  /** Decline to answer and let the agent proceed on the answers it pre-picked. */
3231
3253
  async skip(req, body) {
3232
3254
  const actor = await this.actorResolver.resolve(req);
3233
- await this.agent.skip(actor, toolCallId(body.toolCallId));
3255
+ await this.agent.skip(actor, toolCallId(body.toolCallId), {
3256
+ via: via(body.via)
3257
+ });
3234
3258
  return {
3235
3259
  ok: true
3236
3260
  };
@@ -3291,7 +3315,7 @@ ToolCallController = _ts_decorate18([
3291
3315
  ], ToolCallController);
3292
3316
 
3293
3317
  // src/controller/tools.controller.ts
3294
- import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER11, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY5, AGENT_REGISTRY as AGENT_REGISTRY3, AgentRegistry as AgentRegistry4 } from "@dudousxd/nestjs-agent-core";
3318
+ import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER11, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY5, AGENT_REGISTRY as AGENT_REGISTRY3, ALL_AGENTS, AgentRegistry as AgentRegistry4 } from "@dudousxd/nestjs-agent-core";
3295
3319
  import { Controller as Controller12, Get as Get10, Inject as Inject17, NotFoundException as NotFoundException3, Query as Query5, Req as Req11 } from "@nestjs/common";
3296
3320
  function _ts_decorate19(decorators, target, key, desc) {
3297
3321
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -3332,19 +3356,34 @@ var ToolsController = class {
3332
3356
  this.agents = agents;
3333
3357
  }
3334
3358
  async list(req, agent) {
3335
- if (agent !== void 0 && this.agents.get(agent) === void 0) {
3359
+ if (agent !== void 0 && agent !== ALL_AGENTS && this.agents.get(agent) === void 0) {
3336
3360
  throw new NotFoundException3(`No agent named "${agent}"`);
3337
3361
  }
3338
3362
  const actor = await this.actorResolver.resolve(req);
3339
- const deps = this.depsFactory.forAgent(agent);
3340
- const specs = await deps.registry.visibleSpecs(actor, deps.rolesPolicy, deps.toolAllowList);
3341
- return specs.map((spec) => ({
3342
- name: spec.name,
3343
- kind: spec.kind,
3344
- ...spec.presentation !== void 0 ? {
3345
- presentation: spec.presentation
3346
- } : {}
3347
- }));
3363
+ const names = agent === ALL_AGENTS ? [
3364
+ void 0,
3365
+ ...this.agents.list().map((definition) => definition.name)
3366
+ ] : [
3367
+ agent
3368
+ ];
3369
+ const entries = /* @__PURE__ */ new Map();
3370
+ for (const name of names) {
3371
+ const deps = this.depsFactory.forAgent(name);
3372
+ const specs = await deps.registry.visibleSpecs(actor, deps.rolesPolicy, deps.toolAllowList);
3373
+ for (const spec of specs) {
3374
+ if (entries.has(spec.name)) continue;
3375
+ entries.set(spec.name, {
3376
+ name: spec.name,
3377
+ kind: spec.kind,
3378
+ ...spec.presentation !== void 0 ? {
3379
+ presentation: spec.presentation
3380
+ } : {}
3381
+ });
3382
+ }
3383
+ }
3384
+ return [
3385
+ ...entries.values()
3386
+ ];
3348
3387
  }
3349
3388
  };
3350
3389
  _ts_decorate19([
@@ -3859,16 +3898,18 @@ SkillDiscoveryService = _ts_decorate22([
3859
3898
  ], SkillDiscoveryService);
3860
3899
 
3861
3900
  // src/ledger-quota-provider.ts
3862
- import { exhaustedWindow, quotaPeriodRange } from "@dudousxd/nestjs-agent-core";
3901
+ import { exhaustedWindow, quotaPeriodRange, quotaWarning } from "@dudousxd/nestjs-agent-core";
3863
3902
  var LedgerQuotaProvider = class {
3864
3903
  static {
3865
3904
  __name(this, "LedgerQuotaProvider");
3866
3905
  }
3867
3906
  store;
3868
3907
  limits;
3869
- constructor(store, limits = {}) {
3908
+ options;
3909
+ constructor(store, limits = {}, options = {}) {
3870
3910
  this.store = store;
3871
3911
  this.limits = limits;
3912
+ this.options = options;
3872
3913
  }
3873
3914
  async report(query) {
3874
3915
  const now = query.now ?? /* @__PURE__ */ new Date();
@@ -3882,10 +3923,14 @@ var LedgerQuotaProvider = class {
3882
3923
  windows.push(this.window("month", used.usedTokens, used.costUsd, range.resetsAt));
3883
3924
  }
3884
3925
  const blocked = exhaustedWindow(windows);
3926
+ const warning = quotaWarning(windows);
3885
3927
  return {
3886
3928
  windows,
3887
3929
  ...blocked !== void 0 ? {
3888
3930
  blocked
3931
+ } : {},
3932
+ ...warning !== void 0 ? {
3933
+ warning
3889
3934
  } : {}
3890
3935
  };
3891
3936
  }
@@ -3906,7 +3951,10 @@ var LedgerQuotaProvider = class {
3906
3951
  ...limits.usd !== void 0 ? {
3907
3952
  limitUsd: limits.usd
3908
3953
  } : {},
3909
- resetsAt
3954
+ resetsAt,
3955
+ ...this.options.warnAt !== void 0 && (limits.tokens !== void 0 || limits.usd !== void 0) ? {
3956
+ warnAt: this.options.warnAt
3957
+ } : {}
3910
3958
  };
3911
3959
  }
3912
3960
  };
@@ -4511,7 +4559,9 @@ function sharedProviders(durable) {
4511
4559
  // `quota` is either a provider of the host's own or ceilings for the built-in ledger one;
4512
4560
  // omitted, the ledger provider still reports usage, with no ceiling to block on.
4513
4561
  provide: AGENT_QUOTA_PROVIDER2,
4514
- useFactory: /* @__PURE__ */ __name((o, store) => isQuotaProvider(o.quota) ? o.quota : new LedgerQuotaProvider(store, o.quota?.limits), "useFactory"),
4562
+ useFactory: /* @__PURE__ */ __name((o, store) => isQuotaProvider(o.quota) ? o.quota : new LedgerQuotaProvider(store, o.quota?.limits, o.quota?.warnAt !== void 0 ? {
4563
+ warnAt: o.quota.warnAt
4564
+ } : {}), "useFactory"),
4515
4565
  inject: [
4516
4566
  AGENT_OPTIONS6,
4517
4567
  AGENT_STORE6