@dudousxd/nestjs-agent 1.10.0 → 1.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.
@@ -98,7 +98,7 @@ interface QuotaWindowLimits {
98
98
  tokens?: number;
99
99
  usd?: number;
100
100
  }
101
- /** Per-window ceilings: `AgentModule.forRoot({ quotaLimits })`. */
101
+ /** Per-window ceilings: `AgentModule.forRoot({ quota: { limits } })`. */
102
102
  interface QuotaLimits {
103
103
  day?: QuotaWindowLimits;
104
104
  month?: QuotaWindowLimits;
@@ -106,8 +106,7 @@ interface QuotaLimits {
106
106
  /**
107
107
  * The default {@link QuotaProvider}: windows read off the usage ledger the loop already writes.
108
108
  *
109
- * - `day` — always; `usedTokens`/limit come from the bound {@link QuotaStore} when there is one (so
110
- * the report matches what the loop enforces), spend from the ledger.
109
+ * - `day` — always.
111
110
  * - `month` — when the store implements `usageBetween`.
112
111
  *
113
112
  * `limits` add ceilings per window (tokens and/or USD). A window that reaches one makes the report
@@ -115,9 +114,8 @@ interface QuotaLimits {
115
114
  */
116
115
  declare class LedgerQuotaProvider implements QuotaProvider {
117
116
  private readonly store;
118
- private readonly quota?;
119
117
  private readonly limits;
120
- constructor(store: AgentStore, quota?: QuotaStore | undefined, limits?: QuotaLimits);
118
+ constructor(store: AgentStore, limits?: QuotaLimits);
121
119
  report(query: QuotaQuery): Promise<QuotaReport>;
122
120
  private dayWindow;
123
121
  private window;
@@ -144,8 +142,9 @@ declare class LedgerQuotaProvider implements QuotaProvider {
144
142
  */
145
143
  type AgentSurface = 'http' | 'engine' | 'both';
146
144
  /**
147
- * `AgentModuleOptions.attachments` — bounds and content-type allowlist for the optional
148
- * `POST /agent/attachments` upload controller (see `attachments.upload`).
145
+ * `AgentModuleOptions.attachments` — limits for `POST <base>/attachments`, when the bound
146
+ * `AGENT_ATTACHMENT_STAGING` store does not declare its own (`AgentMediaAttachmentsModule` does, and
147
+ * then it is the only source). Served to clients by `GET <base>/config`.
149
148
  */
150
149
  interface AgentAttachmentsOptions {
151
150
  /** Per-file size cap. Defaults to 20 MiB. */
@@ -155,13 +154,6 @@ interface AgentAttachmentsOptions {
155
154
  * `image/png`, `image/jpeg`, `image/gif`, `image/webp`, `application/pdf`, `text/plain`, `text/csv`.
156
155
  */
157
156
  allowedContentTypes?: string[];
158
- /**
159
- * Mount `POST /agent/attachments`. Defaults to `false` — the controller is build-time (static)
160
- * wiring, so this can't be inferred from whether `AGENT_ATTACHMENT_STAGING` ends up bound (that's
161
- * a DI-time fact); set it explicitly. `true` with no `AGENT_ATTACHMENT_STAGING` provider bound
162
- * fails boot loudly instead of silently mounting a controller that 501s on every request.
163
- */
164
- upload?: boolean;
165
157
  }
166
158
  /**
167
159
  * `AgentModuleOptions.skills` — where a turn's skills come from, and which scopes an actor draws
@@ -219,45 +211,43 @@ interface AgentMemoryOptions {
219
211
  maxFactChars?: number;
220
212
  }
221
213
  interface AgentModuleOptions {
222
- /** The LLM provider (e.g. a Vercel AI SDK wrapper). Required. */
214
+ /**
215
+ * The LLM provider — `aiSdkModel(openai('gpt-5-mini'))`, or `aiSdkModels({ … })` for a model
216
+ * picker (its catalog is used when `models` is omitted). The only required option.
217
+ */
223
218
  model: ModelProvider;
224
219
  /**
225
- * Persistence adapter. Optional — omit it and import a store module (e.g.
226
- * `MikroOrmAgentStoreModule.forFeature()`) that binds `AGENT_STORE` globally instead. When
227
- * provided here it takes precedence within this module's scope.
220
+ * The base prompt of the default agent (and of any `@Agent` that declares none) — a string, or a
221
+ * function of the turn's `{ actor, agentName, pageContext }`. Omit → `'You are a helpful
222
+ * assistant.'`.
223
+ */
224
+ systemPrompt?: string | PromptBuilder;
225
+ /**
226
+ * Persistence adapter. Omit it and either import a store module (e.g.
227
+ * `MikroOrmAgentStoreModule.forFeature()`, which binds `AGENT_STORE` globally — it is found and
228
+ * used), or run on the built-in in-memory store — fine for a demo, logged at boot as not for
229
+ * production: threads vanish on restart and are not shared between processes.
228
230
  */
229
231
  store?: AgentStore;
230
232
  /** Live token transport. Defaults to a single-process in-memory sink. */
231
233
  sink?: TokenStreamSink;
232
234
  /**
233
- * A {@link QuotaStore} for the daily token budget. Optional — omit (and omit `quotaLimitTokens`)
234
- * to disable quotas. Provide this to plug a custom budget; for the common case use the simpler
235
- * `quotaLimitTokens` instead, which binds the built-in ledger-backed store.
235
+ * The caller's budget. `{ limits: { day?: { tokens?, usd? }, month?: { tokens?, usd? } } }` puts
236
+ * ceilings on the built-in ledger provider; a {@link QuotaProvider} of your own replaces it. Either
237
+ * way `GET <base>/quota` reports it and a send whose report comes back `blocked` is refused with
238
+ * `429` before the turn starts. Omit → reported (usage off the ledger), never enforced — for a
239
+ * public (anonymous) deployment that means unbounded model spend, so set limits there; they apply
240
+ * per actor, which is per browser in anonymous mode.
236
241
  */
237
- quota?: QuotaStore;
242
+ quota?: {
243
+ limits: QuotaLimits;
244
+ } | QuotaProvider;
238
245
  /**
239
246
  * Which models a caller may pick — `GET <base>/models`, a send's `model`, a thread's pinned model
240
- * (`PATCH <base>/threads/:id { model }`). The picked id reaches the {@link ModelProvider} as
241
- * `ModelTurnArgs.model`. Omit → an empty catalog, and a request naming a model is refused.
247
+ * (`PATCH <base>/threads/:id { model }`). Omit → the catalog the model provider carries
248
+ * (`aiSdkModels`), else none, and a request naming a model is refused.
242
249
  */
243
250
  models?: ModelCatalog;
244
- /**
245
- * The actor's budget across windows, for `GET <base>/quota` — and, once set, a gate: a send whose
246
- * report comes back `blocked` is refused with `429` before the turn starts. Default: a
247
- * {@link LedgerQuotaProvider} over the usage ledger (reporting only, unless `quotaLimits` is set).
248
- */
249
- quotaProvider?: QuotaProvider;
250
- /**
251
- * Ceilings for the default ledger provider's windows — `{ day?: { tokens?, usd? }, month?: {
252
- * tokens?, usd? } }`. Setting it turns the send gate on. Ignored when `quotaProvider` is given.
253
- */
254
- quotaLimits?: QuotaLimits;
255
- /**
256
- * Daily per-actor token budget, enforced against the persisted usage ledger by the built-in
257
- * `LedgerQuotaStore`. A convenience over wiring a {@link QuotaStore} by hand — set this and quotas
258
- * turn on with no extra store. Ignored when an explicit `quota` is provided. Omit to disable.
259
- */
260
- quotaLimitTokens?: number;
261
251
  /** Tool authorization gate. Defaults to role-in-`defaultRoles`. */
262
252
  rolesPolicy?: RolesPolicy;
263
253
  /**
@@ -267,15 +257,20 @@ interface AgentModuleOptions {
267
257
  * deciding actor must hold that role. See `ApprovalPolicy`.
268
258
  */
269
259
  approvalPolicy?: ApprovalPolicy;
270
- /** Default roles a tool requires when its `roles` is omitted. Defaults to `['ADMIN']`. */
260
+ /**
261
+ * Roles a tool requires when its own `roles` is omitted. Default `[]` — no restriction: every
262
+ * tool is callable by whoever `actorResolver` resolved (an anonymous visitor included, when none is
263
+ * configured). `action` tools still park on approval regardless.
264
+ */
271
265
  defaultRoles?: string[];
272
266
  /**
273
- * Resolves the acting actor for each request (the identity seam). Required — the agent NEVER
274
- * fabricates a caller, so this is a compile-time obligation, not an optional with a throwing
275
- * placeholder. Read your authenticated principal here (session / JWT / `nestjs-context`), or use
276
- * the opt-in `HeaderActorResolver` for demos and header-trusting gateways.
267
+ * Resolves the acting actor for each request (the identity seam). Omit → the endpoints are public
268
+ * and every browser is its own anonymous actor (`AnonymousActorResolver`: an `HttpOnly` cookie,
269
+ * the actor id a digest of it), so visitors never see each other's threads, quota or attachments.
270
+ * A boot notice says so. Require login with `requestUserActorResolver()` (reads `req.user`), or a
271
+ * resolver of your own over your session / JWT / `nestjs-context`.
277
272
  */
278
- actorResolver: ActorResolver;
273
+ actorResolver?: ActorResolver;
279
274
  /** Route prefix the controllers mount under. Defaults to `'agent'` (→ `/agent/chat`, …). */
280
275
  path?: string;
281
276
  /**
@@ -346,7 +341,7 @@ interface AgentModuleOptions {
346
341
  /**
347
342
  * A {@link HistoryPolicy} of your own — for a window the built-in can't express (pinning the
348
343
  * thread's opening brief, keeping every message that carries a tool result, a budget that varies
349
- * by actor). A convenience-vs-custom pair like `quotaLimitTokens`/`quota`: this outranks a
344
+ * by actor). A convenience-vs-custom pair: this outranks a
350
345
  * module-wide `history`, and `@Agent({ history })` outranks both for the agent that declares it.
351
346
  * `select` MUST be pure — see the SPI's determinism contract.
352
347
  */
@@ -411,14 +406,14 @@ interface AgentModuleOptions {
411
406
  defaultAgent?: string;
412
407
  /**
413
408
  * Guard(s) applied uniformly to EVERY controller this module mounts (chat, threads, tool-call,
414
- * quota, agents, and — when `attachments.upload` is set — attachments). Third-party controller
409
+ * quota, agents, attachments, config, …). Third-party controller
415
410
  * classes can't be annotated with `@UseGuards` by consumers, so without this option every route is
416
411
  * open beyond whatever `actorResolver` itself enforces. Guard classes are added to this module's
417
412
  * `providers` so Nest can DI-instantiate them; if a guard has its own dependencies, make sure they
418
413
  * resolve from this module's imports or a global module.
419
414
  */
420
415
  guards?: Type<CanActivate>[];
421
- /** Bounds/allowlist for the optional attachment-upload controller. Omit → 20 MiB, the documented default types, not mounted. */
416
+ /** Upload limits when the staging store declares none. Omit → 20 MiB and the default types. */
422
417
  attachments?: AgentAttachmentsOptions;
423
418
  /**
424
419
  * Which half of the module this process mounts (see {@link AgentSurface}). Omit → `'both'`,
@@ -441,17 +436,6 @@ interface AgentModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
441
436
  * the runner. Requires importing `AgentDurableModule` and a configured `DurableModule`.
442
437
  */
443
438
  durable?: boolean;
444
- /**
445
- * Set when `AGENT_STORE` is bound by a globally-imported store module (e.g.
446
- * `MikroOrmAgentStoreModule.forFeature()`) instead of returned as `store` from `useFactory`.
447
- *
448
- * `forRoot` decides this synchronously (`store` present or not), but the async factory resolves
449
- * too late to inspect — so by default `forRootAsync` binds `AGENT_STORE` from the factory result,
450
- * which would shadow a global store binding with `undefined` when the factory omits `store`. Set
451
- * this to `true` to skip the local binding and defer to the global one. Leave it unset (and return
452
- * `store` from the factory) when the store is constructed inside the factory.
453
- */
454
- externalStore?: boolean;
455
439
  /**
456
440
  * Guard(s) applied uniformly to every controller this module mounts. A STATIC field on the async
457
441
  * config object itself — NOT part of what `useFactory` resolves — because controllers (and the
@@ -461,16 +445,9 @@ interface AgentModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
461
445
  * `useFactory`. Same default-open caveat as `AgentModuleOptions.guards`.
462
446
  */
463
447
  guards?: Type<CanActivate>[];
464
- /**
465
- * Mount `POST /agent/attachments`. Static, build-time control (same reasoning as `durable`/`path`
466
- * above) — `useFactory` resolves too late to decide which controllers exist. The resolved
467
- * `AgentModuleOptions.attachments` (maxBytes/allowedContentTypes) still applies at request time;
468
- * only the yes/no mount decision has to live here.
469
- */
470
- attachmentsUpload?: boolean;
471
448
  /**
472
449
  * Which half of the module this process mounts (see {@link AgentSurface}). Same static-wiring
473
- * reasoning as `attachmentsUpload`/`durable` above — `useFactory` resolves too late to decide
450
+ * reasoning as `durable` above — `useFactory` resolves too late to decide
474
451
  * which controllers exist. Omit → `'both'`, today's behavior with zero change.
475
452
  */
476
453
  surface?: AgentSurface;
@@ -498,11 +475,10 @@ declare class AgentDepsFactory {
498
475
  private readonly registry;
499
476
  private readonly agents;
500
477
  private readonly promptContributors;
501
- private readonly quota;
502
478
  private readonly pricingStore;
503
479
  private readonly skills;
504
480
  private readonly memory;
505
- constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], quota: QuotaStore | undefined, pricingStore: AgentPricingStore | undefined, skills: SkillsConfig | undefined, memory: MemoryConfig | undefined);
481
+ constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], pricingStore: AgentPricingStore | undefined, skills: SkillsConfig | undefined, memory: MemoryConfig | undefined);
506
482
  /** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */
507
483
  memoryConfig(): MemoryConfig | undefined;
508
484
  /** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */