@dudousxd/nestjs-agent 1.12.0 → 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.
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit } from '@nestjs/common';
2
- import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, d as AgentSkillsOptions } from './agent-deps.factory-pqv_qTmJ.cjs';
3
- export { e as AGENT_TOOL_BRAND, f as AgentAttachmentsOptions, g as AgentDeps, h as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QuotaLimits, i as QuotaWindowLimits, j as delegateToolName, p as provideAgentTool, k as provideAgentTools, u as utcDay } from './agent-deps.factory-pqv_qTmJ.cjs';
2
+ import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, d as AgentSkillsOptions } from './agent-deps.factory-DkWvoWbD.cjs';
3
+ export { e as AGENT_TOOL_BRAND, f as AgentAttachmentsOptions, g as AgentDeps, h as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QuotaLimits, i as QuotaWindowLimits, j as delegateToolName, p as provideAgentTool, k as provideAgentTools, u as utcDay } from './agent-deps.factory-DkWvoWbD.cjs';
4
4
  import { AgentRunner, AgentStore, AttachmentStagingStore, ModelCatalog, QuotaProvider, Actor, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, AgentApprovalPort, ActorResolver, MessageAttachment, AgentAttachmentConfig, AgentClientConfig, ToolPresentation, AgentHistoryWindow, AgentIntake, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, TokenStreamSink, SinkWriter } from '@dudousxd/nestjs-agent-core';
5
5
  export * from '@dudousxd/nestjs-agent-core';
6
6
  import { Request } from 'express';
@@ -82,7 +82,11 @@ declare class AgentService {
82
82
  * pinned and again at every turn that runs on it (availability can change in between).
83
83
  */
84
84
  private assertModelAllowed;
85
- /** The model a turn runs on: the send's own, else the thread's pinned one, else none. */
85
+ /**
86
+ * The model a turn runs on: the send's own (that turn only — it is never stored on the thread),
87
+ * else the thread's pinned one, else none. An agent the catalog locks to one model runs on it
88
+ * whatever was sent or pinned, and a send naming another model is refused.
89
+ */
86
90
  private resolveModel;
87
91
  private threadModel;
88
92
  chat(params: ChatParams): Promise<{
@@ -134,13 +138,17 @@ declare class AgentService {
134
138
  * "the user picked exactly the defaults" persist as the same answers, and no client has to
135
139
  * re-send what it was shown.
136
140
  */
137
- answer(actor: Actor, toolCallId: string, answers?: Record<string, string[]>): Promise<void>;
141
+ answer(actor: Actor, toolCallId: string, answers?: Record<string, string[]>, opts?: {
142
+ via?: string;
143
+ }): Promise<void>;
138
144
  /**
139
145
  * Decline to answer and let the agent proceed on its own assumptions. NOT the same as confirming
140
146
  * them: the run records this as a rejection, so a reader auditing what the agent was told can
141
147
  * tell a choice the user made from one they refused to make.
142
148
  */
143
- skip(actor: Actor, toolCallId: string): Promise<void>;
149
+ skip(actor: Actor, toolCallId: string, opts?: {
150
+ via?: string;
151
+ }): Promise<void>;
144
152
  /**
145
153
  * The decision core behind approve/reject, WITHOUT an ownership check: resolves the run
146
154
  * currently awaiting `toolCallId` and signals it. `approve`/`reject` above call this after their
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit } from '@nestjs/common';
2
- import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, d as AgentSkillsOptions } from './agent-deps.factory-pqv_qTmJ.js';
3
- export { e as AGENT_TOOL_BRAND, f as AgentAttachmentsOptions, g as AgentDeps, h as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QuotaLimits, i as QuotaWindowLimits, j as delegateToolName, p as provideAgentTool, k as provideAgentTools, u as utcDay } from './agent-deps.factory-pqv_qTmJ.js';
2
+ import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, d as AgentSkillsOptions } from './agent-deps.factory-DkWvoWbD.js';
3
+ export { e as AGENT_TOOL_BRAND, f as AgentAttachmentsOptions, g as AgentDeps, h as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QuotaLimits, i as QuotaWindowLimits, j as delegateToolName, p as provideAgentTool, k as provideAgentTools, u as utcDay } from './agent-deps.factory-DkWvoWbD.js';
4
4
  import { AgentRunner, AgentStore, AttachmentStagingStore, ModelCatalog, QuotaProvider, Actor, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, AgentApprovalPort, ActorResolver, MessageAttachment, AgentAttachmentConfig, AgentClientConfig, ToolPresentation, AgentHistoryWindow, AgentIntake, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, TokenStreamSink, SinkWriter } from '@dudousxd/nestjs-agent-core';
5
5
  export * from '@dudousxd/nestjs-agent-core';
6
6
  import { Request } from 'express';
@@ -82,7 +82,11 @@ declare class AgentService {
82
82
  * pinned and again at every turn that runs on it (availability can change in between).
83
83
  */
84
84
  private assertModelAllowed;
85
- /** The model a turn runs on: the send's own, else the thread's pinned one, else none. */
85
+ /**
86
+ * The model a turn runs on: the send's own (that turn only — it is never stored on the thread),
87
+ * else the thread's pinned one, else none. An agent the catalog locks to one model runs on it
88
+ * whatever was sent or pinned, and a send naming another model is refused.
89
+ */
86
90
  private resolveModel;
87
91
  private threadModel;
88
92
  chat(params: ChatParams): Promise<{
@@ -134,13 +138,17 @@ declare class AgentService {
134
138
  * "the user picked exactly the defaults" persist as the same answers, and no client has to
135
139
  * re-send what it was shown.
136
140
  */
137
- answer(actor: Actor, toolCallId: string, answers?: Record<string, string[]>): Promise<void>;
141
+ answer(actor: Actor, toolCallId: string, answers?: Record<string, string[]>, opts?: {
142
+ via?: string;
143
+ }): Promise<void>;
138
144
  /**
139
145
  * Decline to answer and let the agent proceed on its own assumptions. NOT the same as confirming
140
146
  * them: the run records this as a rejection, so a reader auditing what the agent was told can
141
147
  * tell a choice the user made from one they refused to make.
142
148
  */
143
- skip(actor: Actor, toolCallId: string): Promise<void>;
149
+ skip(actor: Actor, toolCallId: string, opts?: {
150
+ via?: string;
151
+ }): Promise<void>;
144
152
  /**
145
153
  * The decision core behind approve/reject, WITHOUT an ownership check: resolves the run
146
154
  * currently awaiting `toolCallId` and signals it. `approve`/`reject` above call this after their
package/dist/index.js CHANGED
@@ -411,8 +411,22 @@ var AgentService = class {
411
411
  }
412
412
  return entry.id;
413
413
  }
414
- /** The model a turn runs on: the send's own, else the thread's pinned one, else none. */
414
+ /**
415
+ * The model a turn runs on: the send's own (that turn only — it is never stored on the thread),
416
+ * else the thread's pinned one, else none. An agent the catalog locks to one model runs on it
417
+ * whatever was sent or pinned, and a send naming another model is refused.
418
+ */
415
419
  async resolveModel(actor, agent, requested, threadId) {
420
+ const locked = this.models !== void 0 ? (await this.models.list({
421
+ actor,
422
+ agent
423
+ })).locked : void 0;
424
+ if (locked !== void 0) {
425
+ if (requested !== void 0 && requested !== locked.model) {
426
+ throw new BadRequestException(`model "${requested}" cannot be selected: ${locked.reason ?? `this agent always uses "${locked.model}"`}`);
427
+ }
428
+ return locked.model;
429
+ }
416
430
  const model = requested ?? (threadId !== void 0 ? await this.threadModel(threadId) : null);
417
431
  if (model === null || model === void 0) {
418
432
  return void 0;
@@ -561,12 +575,15 @@ var AgentService = class {
561
575
  * "the user picked exactly the defaults" persist as the same answers, and no client has to
562
576
  * re-send what it was shown.
563
577
  */
564
- async answer(actor, toolCallId2, answers2 = {}) {
578
+ async answer(actor, toolCallId2, answers2 = {}, opts = {}) {
565
579
  await this.assertOwnsToolCall(actor, toolCallId2);
566
580
  await this.assertAnswersFit(toolCallId2, answers2);
567
581
  const reply = {
568
582
  answers: answers2,
569
- answeredByRef: actor.id
583
+ answeredByRef: actor.id,
584
+ ...opts.via !== void 0 ? {
585
+ answeredVia: opts.via
586
+ } : {}
570
587
  };
571
588
  return this.signalToolCall(toolCallId2, reply);
572
589
  }
@@ -575,12 +592,15 @@ var AgentService = class {
575
592
  * them: the run records this as a rejection, so a reader auditing what the agent was told can
576
593
  * tell a choice the user made from one they refused to make.
577
594
  */
578
- async skip(actor, toolCallId2) {
595
+ async skip(actor, toolCallId2, opts = {}) {
579
596
  await this.assertOwnsToolCall(actor, toolCallId2);
580
597
  const reply = {
581
598
  answers: {},
582
599
  skipped: true,
583
- answeredByRef: actor.id
600
+ answeredByRef: actor.id,
601
+ ...opts.via !== void 0 ? {
602
+ answeredVia: opts.via
603
+ } : {}
584
604
  };
585
605
  return this.signalToolCall(toolCallId2, reply);
586
606
  }
@@ -2442,7 +2462,9 @@ var ToolCallController = class {
2442
2462
  */
2443
2463
  async answer(req, body) {
2444
2464
  const actor = await this.actorResolver.resolve(req);
2445
- await this.agent.answer(actor, toolCallId(body.toolCallId), answers(body.answers));
2465
+ await this.agent.answer(actor, toolCallId(body.toolCallId), answers(body.answers), {
2466
+ via: via(body.via)
2467
+ });
2446
2468
  return {
2447
2469
  ok: true
2448
2470
  };
@@ -2450,7 +2472,9 @@ var ToolCallController = class {
2450
2472
  /** Decline to answer and let the agent proceed on the answers it pre-picked. */
2451
2473
  async skip(req, body) {
2452
2474
  const actor = await this.actorResolver.resolve(req);
2453
- await this.agent.skip(actor, toolCallId(body.toolCallId));
2475
+ await this.agent.skip(actor, toolCallId(body.toolCallId), {
2476
+ via: via(body.via)
2477
+ });
2454
2478
  return {
2455
2479
  ok: true
2456
2480
  };
@@ -3222,16 +3246,18 @@ var InProcessTokenStreamSink = class {
3222
3246
  };
3223
3247
 
3224
3248
  // src/ledger-quota-provider.ts
3225
- import { exhaustedWindow, quotaPeriodRange } from "@dudousxd/nestjs-agent-core";
3249
+ import { exhaustedWindow, quotaPeriodRange, quotaWarning } from "@dudousxd/nestjs-agent-core";
3226
3250
  var LedgerQuotaProvider = class {
3227
3251
  static {
3228
3252
  __name(this, "LedgerQuotaProvider");
3229
3253
  }
3230
3254
  store;
3231
3255
  limits;
3232
- constructor(store, limits = {}) {
3256
+ options;
3257
+ constructor(store, limits = {}, options = {}) {
3233
3258
  this.store = store;
3234
3259
  this.limits = limits;
3260
+ this.options = options;
3235
3261
  }
3236
3262
  async report(query) {
3237
3263
  const now = query.now ?? /* @__PURE__ */ new Date();
@@ -3245,10 +3271,14 @@ var LedgerQuotaProvider = class {
3245
3271
  windows.push(this.window("month", used.usedTokens, used.costUsd, range.resetsAt));
3246
3272
  }
3247
3273
  const blocked = exhaustedWindow(windows);
3274
+ const warning = quotaWarning(windows);
3248
3275
  return {
3249
3276
  windows,
3250
3277
  ...blocked !== void 0 ? {
3251
3278
  blocked
3279
+ } : {},
3280
+ ...warning !== void 0 ? {
3281
+ warning
3252
3282
  } : {}
3253
3283
  };
3254
3284
  }
@@ -3269,7 +3299,10 @@ var LedgerQuotaProvider = class {
3269
3299
  ...limits.usd !== void 0 ? {
3270
3300
  limitUsd: limits.usd
3271
3301
  } : {},
3272
- resetsAt
3302
+ resetsAt,
3303
+ ...this.options.warnAt !== void 0 && (limits.tokens !== void 0 || limits.usd !== void 0) ? {
3304
+ warnAt: this.options.warnAt
3305
+ } : {}
3273
3306
  };
3274
3307
  }
3275
3308
  };
@@ -3874,7 +3907,9 @@ function sharedProviders(durable) {
3874
3907
  // `quota` is either a provider of the host's own or ceilings for the built-in ledger one;
3875
3908
  // omitted, the ledger provider still reports usage, with no ceiling to block on.
3876
3909
  provide: AGENT_QUOTA_PROVIDER2,
3877
- useFactory: /* @__PURE__ */ __name((o, store) => isQuotaProvider(o.quota) ? o.quota : new LedgerQuotaProvider(store, o.quota?.limits), "useFactory"),
3910
+ useFactory: /* @__PURE__ */ __name((o, store) => isQuotaProvider(o.quota) ? o.quota : new LedgerQuotaProvider(store, o.quota?.limits, o.quota?.warnAt !== void 0 ? {
3911
+ warnAt: o.quota.warnAt
3912
+ } : {}), "useFactory"),
3878
3913
  inject: [
3879
3914
  AGENT_OPTIONS6,
3880
3915
  AGENT_STORE4