@dudousxd/nestjs-agent 0.3.2 → 0.4.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,5 +1,5 @@
1
- import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Retriever, ToolSpec, ToolHandler, ActorResolver, AgentRegistry } from '@dudousxd/nestjs-agent-core';
2
- import { Provider, FactoryProvider, ModuleMetadata, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
1
+ import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Retriever, AgentPricingStore, ToolSpec, ToolHandler, ActorResolver, AgentRegistry } from '@dudousxd/nestjs-agent-core';
2
+ import { Provider, FactoryProvider, Type, CanActivate, ModuleMetadata, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
3
3
 
4
4
  /** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */
5
5
  interface AgentDeps {
@@ -25,6 +25,8 @@ interface AgentDeps {
25
25
  retriever?: Retriever;
26
26
  /** Passages inject-mode retrieval requests. Undefined → loop default (5). */
27
27
  retrievalTopK?: number;
28
+ /** Bound `AGENT_PRICING_STORE`, when a module (e.g. a store's) provides one. Undefined → no pricing. */
29
+ pricingStore?: AgentPricingStore;
28
30
  }
29
31
  declare function utcDay(date?: Date): string;
30
32
 
@@ -49,6 +51,26 @@ interface FunctionalTool {
49
51
  declare function provideAgentTool(tool: FunctionalTool): Provider;
50
52
  declare function provideAgentTool(factory: (...deps: never[]) => FunctionalTool, inject?: FactoryProvider['inject']): Provider;
51
53
 
54
+ /**
55
+ * `AgentModuleOptions.attachments` — bounds and content-type allowlist for the optional
56
+ * `POST /agent/attachments` upload controller (see `attachments.upload`).
57
+ */
58
+ interface AgentAttachmentsOptions {
59
+ /** Per-file size cap. Defaults to 20 MiB. */
60
+ maxBytes?: number;
61
+ /**
62
+ * Allowed multipart content types. Defaults to what multimodal model providers commonly accept:
63
+ * `image/png`, `image/jpeg`, `image/gif`, `image/webp`, `application/pdf`, `text/plain`, `text/csv`.
64
+ */
65
+ allowedContentTypes?: string[];
66
+ /**
67
+ * Mount `POST /agent/attachments`. Defaults to `false` — the controller is build-time (static)
68
+ * wiring, so this can't be inferred from whether `AGENT_ATTACHMENT_STAGING` ends up bound (that's
69
+ * a DI-time fact); set it explicitly. `true` with no `AGENT_ATTACHMENT_STAGING` provider bound
70
+ * fails boot loudly instead of silently mounting a controller that 501s on every request.
71
+ */
72
+ upload?: boolean;
73
+ }
52
74
  interface AgentModuleOptions {
53
75
  /** The LLM provider (e.g. a Vercel AI SDK wrapper). Required. */
54
76
  model: ModelProvider;
@@ -125,6 +147,17 @@ interface AgentModuleOptions {
125
147
  * `@Agent` is registered). Agents themselves are declared as `@Agent`-decorated providers, not here.
126
148
  */
127
149
  defaultAgent?: string;
150
+ /**
151
+ * Guard(s) applied uniformly to EVERY controller this module mounts (chat, threads, tool-call,
152
+ * quota, agents, and — when `attachments.upload` is set — attachments). Third-party controller
153
+ * classes can't be annotated with `@UseGuards` by consumers, so without this option every route is
154
+ * open beyond whatever `actorResolver` itself enforces. Guard classes are added to this module's
155
+ * `providers` so Nest can DI-instantiate them; if a guard has its own dependencies, make sure they
156
+ * resolve from this module's imports or a global module.
157
+ */
158
+ guards?: Type<CanActivate>[];
159
+ /** Bounds/allowlist for the optional attachment-upload controller. Omit → 20 MiB, the documented default types, not mounted. */
160
+ attachments?: AgentAttachmentsOptions;
128
161
  }
129
162
  interface AgentModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
130
163
  inject?: Array<InjectionToken | OptionalFactoryDependency>;
@@ -140,6 +173,33 @@ interface AgentModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
140
173
  * the runner. Requires importing `AgentDurableModule` and a configured `DurableModule`.
141
174
  */
142
175
  durable?: boolean;
176
+ /**
177
+ * Set when `AGENT_STORE` is bound by a globally-imported store module (e.g.
178
+ * `MikroOrmAgentStoreModule.forFeature()`) instead of returned as `store` from `useFactory`.
179
+ *
180
+ * `forRoot` decides this synchronously (`store` present or not), but the async factory resolves
181
+ * too late to inspect — so by default `forRootAsync` binds `AGENT_STORE` from the factory result,
182
+ * which would shadow a global store binding with `undefined` when the factory omits `store`. Set
183
+ * this to `true` to skip the local binding and defer to the global one. Leave it unset (and return
184
+ * `store` from the factory) when the store is constructed inside the factory.
185
+ */
186
+ externalStore?: boolean;
187
+ /**
188
+ * Guard(s) applied uniformly to every controller this module mounts. A STATIC field on the async
189
+ * config object itself — NOT part of what `useFactory` resolves — because controllers (and the
190
+ * enhancers bound to them) are wired at module build time, before any async factory has run. If a
191
+ * guard needs async-resolved config (e.g. a secret from a `ConfigService`), have the guard inject
192
+ * that service via DI (see `imports`/`inject` above) rather than trying to thread it through
193
+ * `useFactory`. Same default-open caveat as `AgentModuleOptions.guards`.
194
+ */
195
+ guards?: Type<CanActivate>[];
196
+ /**
197
+ * Mount `POST /agent/attachments`. Static, build-time control (same reasoning as `durable`/`path`
198
+ * above) — `useFactory` resolves too late to decide which controllers exist. The resolved
199
+ * `AgentModuleOptions.attachments` (maxBytes/allowedContentTypes) still applies at request time;
200
+ * only the yes/no mount decision has to live here.
201
+ */
202
+ attachmentsUpload?: boolean;
143
203
  }
144
204
 
145
205
  /** The synthesized `agent`-kind tool name an orchestrator uses to hand off to `target`. */
@@ -155,7 +215,8 @@ declare class AgentDepsFactory {
155
215
  private readonly agents;
156
216
  private readonly promptContributors;
157
217
  private readonly quota;
158
- constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], quota: QuotaStore | undefined);
218
+ private readonly pricingStore;
219
+ constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], quota: QuotaStore | undefined, pricingStore: AgentPricingStore | undefined);
159
220
  /**
160
221
  * The agent a turn uses when the caller names none: the explicit `defaultAgent` option, else the
161
222
  * sole registered `@Agent` when there is exactly one, else `'default'` (a bare assistant).
@@ -167,4 +228,4 @@ declare class AgentDepsFactory {
167
228
  private followUpsCount;
168
229
  }
169
230
 
170
- export { AgentDepsFactory as A, type FunctionalTool as F, type AgentModuleOptions as a, type AgentModuleAsyncOptions as b, AGENT_TOOL_BRAND as c, type AgentDeps as d, delegateToolName as e, provideAgentTool as p, utcDay as u };
231
+ export { AgentDepsFactory as A, type FunctionalTool as F, type AgentModuleOptions as a, type AgentModuleAsyncOptions as b, AGENT_TOOL_BRAND as c, type AgentAttachmentsOptions as d, type AgentDeps as e, delegateToolName as f, provideAgentTool as p, utcDay as u };
@@ -1,5 +1,5 @@
1
- import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Retriever, ToolSpec, ToolHandler, ActorResolver, AgentRegistry } from '@dudousxd/nestjs-agent-core';
2
- import { Provider, FactoryProvider, ModuleMetadata, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
1
+ import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Retriever, AgentPricingStore, ToolSpec, ToolHandler, ActorResolver, AgentRegistry } from '@dudousxd/nestjs-agent-core';
2
+ import { Provider, FactoryProvider, Type, CanActivate, ModuleMetadata, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
3
3
 
4
4
  /** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */
5
5
  interface AgentDeps {
@@ -25,6 +25,8 @@ interface AgentDeps {
25
25
  retriever?: Retriever;
26
26
  /** Passages inject-mode retrieval requests. Undefined → loop default (5). */
27
27
  retrievalTopK?: number;
28
+ /** Bound `AGENT_PRICING_STORE`, when a module (e.g. a store's) provides one. Undefined → no pricing. */
29
+ pricingStore?: AgentPricingStore;
28
30
  }
29
31
  declare function utcDay(date?: Date): string;
30
32
 
@@ -49,6 +51,26 @@ interface FunctionalTool {
49
51
  declare function provideAgentTool(tool: FunctionalTool): Provider;
50
52
  declare function provideAgentTool(factory: (...deps: never[]) => FunctionalTool, inject?: FactoryProvider['inject']): Provider;
51
53
 
54
+ /**
55
+ * `AgentModuleOptions.attachments` — bounds and content-type allowlist for the optional
56
+ * `POST /agent/attachments` upload controller (see `attachments.upload`).
57
+ */
58
+ interface AgentAttachmentsOptions {
59
+ /** Per-file size cap. Defaults to 20 MiB. */
60
+ maxBytes?: number;
61
+ /**
62
+ * Allowed multipart content types. Defaults to what multimodal model providers commonly accept:
63
+ * `image/png`, `image/jpeg`, `image/gif`, `image/webp`, `application/pdf`, `text/plain`, `text/csv`.
64
+ */
65
+ allowedContentTypes?: string[];
66
+ /**
67
+ * Mount `POST /agent/attachments`. Defaults to `false` — the controller is build-time (static)
68
+ * wiring, so this can't be inferred from whether `AGENT_ATTACHMENT_STAGING` ends up bound (that's
69
+ * a DI-time fact); set it explicitly. `true` with no `AGENT_ATTACHMENT_STAGING` provider bound
70
+ * fails boot loudly instead of silently mounting a controller that 501s on every request.
71
+ */
72
+ upload?: boolean;
73
+ }
52
74
  interface AgentModuleOptions {
53
75
  /** The LLM provider (e.g. a Vercel AI SDK wrapper). Required. */
54
76
  model: ModelProvider;
@@ -125,6 +147,17 @@ interface AgentModuleOptions {
125
147
  * `@Agent` is registered). Agents themselves are declared as `@Agent`-decorated providers, not here.
126
148
  */
127
149
  defaultAgent?: string;
150
+ /**
151
+ * Guard(s) applied uniformly to EVERY controller this module mounts (chat, threads, tool-call,
152
+ * quota, agents, and — when `attachments.upload` is set — attachments). Third-party controller
153
+ * classes can't be annotated with `@UseGuards` by consumers, so without this option every route is
154
+ * open beyond whatever `actorResolver` itself enforces. Guard classes are added to this module's
155
+ * `providers` so Nest can DI-instantiate them; if a guard has its own dependencies, make sure they
156
+ * resolve from this module's imports or a global module.
157
+ */
158
+ guards?: Type<CanActivate>[];
159
+ /** Bounds/allowlist for the optional attachment-upload controller. Omit → 20 MiB, the documented default types, not mounted. */
160
+ attachments?: AgentAttachmentsOptions;
128
161
  }
129
162
  interface AgentModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
130
163
  inject?: Array<InjectionToken | OptionalFactoryDependency>;
@@ -140,6 +173,33 @@ interface AgentModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
140
173
  * the runner. Requires importing `AgentDurableModule` and a configured `DurableModule`.
141
174
  */
142
175
  durable?: boolean;
176
+ /**
177
+ * Set when `AGENT_STORE` is bound by a globally-imported store module (e.g.
178
+ * `MikroOrmAgentStoreModule.forFeature()`) instead of returned as `store` from `useFactory`.
179
+ *
180
+ * `forRoot` decides this synchronously (`store` present or not), but the async factory resolves
181
+ * too late to inspect — so by default `forRootAsync` binds `AGENT_STORE` from the factory result,
182
+ * which would shadow a global store binding with `undefined` when the factory omits `store`. Set
183
+ * this to `true` to skip the local binding and defer to the global one. Leave it unset (and return
184
+ * `store` from the factory) when the store is constructed inside the factory.
185
+ */
186
+ externalStore?: boolean;
187
+ /**
188
+ * Guard(s) applied uniformly to every controller this module mounts. A STATIC field on the async
189
+ * config object itself — NOT part of what `useFactory` resolves — because controllers (and the
190
+ * enhancers bound to them) are wired at module build time, before any async factory has run. If a
191
+ * guard needs async-resolved config (e.g. a secret from a `ConfigService`), have the guard inject
192
+ * that service via DI (see `imports`/`inject` above) rather than trying to thread it through
193
+ * `useFactory`. Same default-open caveat as `AgentModuleOptions.guards`.
194
+ */
195
+ guards?: Type<CanActivate>[];
196
+ /**
197
+ * Mount `POST /agent/attachments`. Static, build-time control (same reasoning as `durable`/`path`
198
+ * above) — `useFactory` resolves too late to decide which controllers exist. The resolved
199
+ * `AgentModuleOptions.attachments` (maxBytes/allowedContentTypes) still applies at request time;
200
+ * only the yes/no mount decision has to live here.
201
+ */
202
+ attachmentsUpload?: boolean;
143
203
  }
144
204
 
145
205
  /** The synthesized `agent`-kind tool name an orchestrator uses to hand off to `target`. */
@@ -155,7 +215,8 @@ declare class AgentDepsFactory {
155
215
  private readonly agents;
156
216
  private readonly promptContributors;
157
217
  private readonly quota;
158
- constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], quota: QuotaStore | undefined);
218
+ private readonly pricingStore;
219
+ constructor(options: AgentModuleOptions, model: ModelProvider, store: AgentStore, sink: TokenStreamSink, rolesPolicy: RolesPolicy, registry: ToolRegistry, agents: AgentRegistry, promptContributors: PromptContributor[], quota: QuotaStore | undefined, pricingStore: AgentPricingStore | undefined);
159
220
  /**
160
221
  * The agent a turn uses when the caller names none: the explicit `defaultAgent` option, else the
161
222
  * sole registered `@Agent` when there is exactly one, else `'default'` (a bare assistant).
@@ -167,4 +228,4 @@ declare class AgentDepsFactory {
167
228
  private followUpsCount;
168
229
  }
169
230
 
170
- export { AgentDepsFactory as A, type FunctionalTool as F, type AgentModuleOptions as a, type AgentModuleAsyncOptions as b, AGENT_TOOL_BRAND as c, type AgentDeps as d, delegateToolName as e, provideAgentTool as p, utcDay as u };
231
+ export { AgentDepsFactory as A, type FunctionalTool as F, type AgentModuleOptions as a, type AgentModuleAsyncOptions as b, AGENT_TOOL_BRAND as c, type AgentAttachmentsOptions as d, type AgentDeps as e, delegateToolName as f, provideAgentTool as p, utcDay as u };