@dudousxd/nestjs-agent 1.12.1 → 1.13.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
  };
@@ -3859,16 +3883,18 @@ SkillDiscoveryService = _ts_decorate22([
3859
3883
  ], SkillDiscoveryService);
3860
3884
 
3861
3885
  // src/ledger-quota-provider.ts
3862
- import { exhaustedWindow, quotaPeriodRange } from "@dudousxd/nestjs-agent-core";
3886
+ import { exhaustedWindow, quotaPeriodRange, quotaWarning } from "@dudousxd/nestjs-agent-core";
3863
3887
  var LedgerQuotaProvider = class {
3864
3888
  static {
3865
3889
  __name(this, "LedgerQuotaProvider");
3866
3890
  }
3867
3891
  store;
3868
3892
  limits;
3869
- constructor(store, limits = {}) {
3893
+ options;
3894
+ constructor(store, limits = {}, options = {}) {
3870
3895
  this.store = store;
3871
3896
  this.limits = limits;
3897
+ this.options = options;
3872
3898
  }
3873
3899
  async report(query) {
3874
3900
  const now = query.now ?? /* @__PURE__ */ new Date();
@@ -3882,10 +3908,14 @@ var LedgerQuotaProvider = class {
3882
3908
  windows.push(this.window("month", used.usedTokens, used.costUsd, range.resetsAt));
3883
3909
  }
3884
3910
  const blocked = exhaustedWindow(windows);
3911
+ const warning = quotaWarning(windows);
3885
3912
  return {
3886
3913
  windows,
3887
3914
  ...blocked !== void 0 ? {
3888
3915
  blocked
3916
+ } : {},
3917
+ ...warning !== void 0 ? {
3918
+ warning
3889
3919
  } : {}
3890
3920
  };
3891
3921
  }
@@ -3906,7 +3936,10 @@ var LedgerQuotaProvider = class {
3906
3936
  ...limits.usd !== void 0 ? {
3907
3937
  limitUsd: limits.usd
3908
3938
  } : {},
3909
- resetsAt
3939
+ resetsAt,
3940
+ ...this.options.warnAt !== void 0 && (limits.tokens !== void 0 || limits.usd !== void 0) ? {
3941
+ warnAt: this.options.warnAt
3942
+ } : {}
3910
3943
  };
3911
3944
  }
3912
3945
  };
@@ -4511,7 +4544,9 @@ function sharedProviders(durable) {
4511
4544
  // `quota` is either a provider of the host's own or ceilings for the built-in ledger one;
4512
4545
  // omitted, the ledger provider still reports usage, with no ceiling to block on.
4513
4546
  provide: AGENT_QUOTA_PROVIDER2,
4514
- useFactory: /* @__PURE__ */ __name((o, store) => isQuotaProvider(o.quota) ? o.quota : new LedgerQuotaProvider(store, o.quota?.limits), "useFactory"),
4547
+ useFactory: /* @__PURE__ */ __name((o, store) => isQuotaProvider(o.quota) ? o.quota : new LedgerQuotaProvider(store, o.quota?.limits, o.quota?.warnAt !== void 0 ? {
4548
+ warnAt: o.quota.warnAt
4549
+ } : {}), "useFactory"),
4515
4550
  inject: [
4516
4551
  AGENT_OPTIONS6,
4517
4552
  AGENT_STORE6