@dudousxd/nestjs-agent 1.7.0 → 1.9.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/README.md +52 -0
- package/dist/{agent-deps.factory-CiC5Va9J.d.cts → agent-deps.factory-DuTy1UyU.d.cts} +49 -2
- package/dist/{agent-deps.factory-CiC5Va9J.d.ts → agent-deps.factory-DuTy1UyU.d.ts} +49 -2
- package/dist/durable/index.cjs +244 -74
- package/dist/durable/index.cjs.map +1 -1
- package/dist/durable/index.d.cts +1 -1
- package/dist/durable/index.d.ts +1 -1
- package/dist/durable/index.js +192 -22
- package/dist/durable/index.js.map +1 -1
- package/dist/genui/index.cjs +186 -0
- package/dist/genui/index.cjs.map +1 -0
- package/dist/genui/index.d.cts +81 -0
- package/dist/genui/index.d.ts +81 -0
- package/dist/genui/index.js +155 -0
- package/dist/genui/index.js.map +1 -0
- package/dist/index.cjs +248 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -4
- package/dist/index.d.ts +17 -4
- package/dist/index.js +194 -21
- package/dist/index.js.map +1 -1
- package/package.json +13 -3
package/README.md
CHANGED
|
@@ -70,6 +70,39 @@ tools THIS actor can reach through that agent (the default agent when omitted; `
|
|
|
70
70
|
one), built by `ToolRegistry.visibleSpecs`, the same gates the model is offered tools through. The
|
|
71
71
|
React package's `useToolCatalog` reads it. The model never sees `presentation`.
|
|
72
72
|
|
|
73
|
+
### Generative UI
|
|
74
|
+
|
|
75
|
+
A tool pushes a component into the answer with `ctx.emitUi(component, props)` — always present; a
|
|
76
|
+
no-op where there is no conversation (MCP). To let the MODEL compose UI from a catalog, import
|
|
77
|
+
`AgentGenuiModule` from `@dudousxd/nestjs-agent/genui` next to `AgentModule`:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
// catalog.ts — isomorphic: the React app imports this same file
|
|
81
|
+
import { defineCatalog, defineComponent } from '@dudousxd/nestjs-agent-core/genui';
|
|
82
|
+
import { BUILTIN_COMPONENTS } from '@dudousxd/nestjs-agent-core/genui/builtins';
|
|
83
|
+
export const catalog = defineCatalog([...BUILTIN_COMPONENTS, DealCard]);
|
|
84
|
+
|
|
85
|
+
// app.module.ts
|
|
86
|
+
AgentGenuiModule.forRoot({ catalog, mode: 'tree', terminal: true });
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
It registers the tools (`ui__show_<component>` per component by default, one `ui__render` in `tree`
|
|
90
|
+
mode, plus a generic `ui__show` taking `{ component, props }` with `showTool: true`), validating
|
|
91
|
+
every call against the catalog. Options: `mode`, `terminal`, `treeToolName`, `treeInstructions`,
|
|
92
|
+
`treeLimits`, `namePrefix`, `showTool`, `showInstructions`, `roles`, `presentation`.
|
|
93
|
+
`forRootAsync({ imports, inject, useFactory })` builds them from config. The catalog is injectable
|
|
94
|
+
(`@InjectGenuiCatalog()`, token `GENUI_CATALOG`) and replaceable in a test with
|
|
95
|
+
`overrideProvider(GENUI_CATALOG)` — the tools are built from the injected one.
|
|
96
|
+
|
|
97
|
+
**Per-request catalogs.** Pass `resolver` (a class, resolved with DI, or an instance) extending
|
|
98
|
+
`GenuiCatalogResolver` — `resolve({ actor, threadId, tenant, agentName }) → Catalog | Promise<Catalog>`
|
|
99
|
+
(`tenant` is `actor.tenantRef`). It is consulted when a call is validated and when a turn's tool list
|
|
100
|
+
is described to the model (the core's `ToolHandler.describe`), so tenant-defined, versioned
|
|
101
|
+
components work without rebuilding tools at boot: the tree tool's and the show tool's descriptions
|
|
102
|
+
and schemas list the tenant's components for that turn, and a pushed component carries the resolved
|
|
103
|
+
definition's `version`. A tenant's own components are reached through the tree tool or
|
|
104
|
+
`showTool: true` — no boot-time tool can name them. Cache inside `resolve` if it costs a round trip.
|
|
105
|
+
|
|
73
106
|
### Message attachments
|
|
74
107
|
|
|
75
108
|
A chat turn attaches a file by **`mediaId` only**:
|
|
@@ -179,6 +212,25 @@ provider's default; the id reaches the provider as `ModelTurnArgs.model` for eve
|
|
|
179
212
|
A model the catalog does not list as available for that actor and agent is refused with `400` —
|
|
180
213
|
when pinned and again on each turn. `staticModelCatalog(view)` wraps a fixed list.
|
|
181
214
|
|
|
215
|
+
### Budgets: `GET /agent/quota`
|
|
216
|
+
|
|
217
|
+
`GET /agent/quota` reports `{ windows: [{ period: 'day' | 'month', usedTokens, limitTokens?,
|
|
218
|
+
usedUsd, limitUsd?, resetsAt? }], blocked? }` from a `QuotaProvider`. The default,
|
|
219
|
+
`LedgerQuotaProvider`, reads the usage ledger (day, plus month when the store has `usageBetween`)
|
|
220
|
+
and only reports. Configure it and it also gates sends — a `blocked` report refuses `POST
|
|
221
|
+
/agent/chat` with `429 { code: 'quota_exceeded', period }` before the turn starts:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
AgentModule.forRoot({
|
|
225
|
+
// ceilings on the default ledger provider
|
|
226
|
+
quotaLimits: { day: { tokens: 200_000 }, month: { usd: 20 } },
|
|
227
|
+
// …or your own budget, e.g. an AI-gateway spend cap:
|
|
228
|
+
// quotaProvider: { report: async ({ actor }) => myGatewayBudget(actor.id) },
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`GET /agent/quota/today` stays as it was.
|
|
233
|
+
|
|
182
234
|
### Who approves an action, and for how long
|
|
183
235
|
|
|
184
236
|
Every `action` tool call waits on the person chatting by default. `approvalPolicy` changes that per
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, ModelCatalog, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry } from '@dudousxd/nestjs-agent-core';
|
|
1
|
+
import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, QuotaProvider, QuotaQuery, QuotaReport, ModelCatalog, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry } from '@dudousxd/nestjs-agent-core';
|
|
2
2
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
3
|
import { Provider, FactoryProvider, Type, CanActivate, ModuleMetadata, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
|
|
4
4
|
|
|
@@ -86,6 +86,42 @@ interface FunctionalTool {
|
|
|
86
86
|
*/
|
|
87
87
|
declare function provideAgentTool(tool: FunctionalTool): Provider;
|
|
88
88
|
declare function provideAgentTool(factory: (...deps: never[]) => FunctionalTool, inject?: FactoryProvider['inject']): Provider;
|
|
89
|
+
/**
|
|
90
|
+
* Registers a LIST of functional tools from one factory — for a producer whose tool count is only
|
|
91
|
+
* known once its dependencies resolve (a catalog loaded from config, one tool per entry). The
|
|
92
|
+
* factory's result is branded element by element; `AiToolDiscoveryService` registers each.
|
|
93
|
+
*/
|
|
94
|
+
declare function provideAgentTools(factory: (...deps: never[]) => readonly FunctionalTool[] | Promise<readonly FunctionalTool[]>, inject?: FactoryProvider['inject']): Provider;
|
|
95
|
+
|
|
96
|
+
/** Ceilings for a {@link LedgerQuotaProvider} window. Either, both, or neither. */
|
|
97
|
+
interface QuotaWindowLimits {
|
|
98
|
+
tokens?: number;
|
|
99
|
+
usd?: number;
|
|
100
|
+
}
|
|
101
|
+
/** Per-window ceilings: `AgentModule.forRoot({ quotaLimits })`. */
|
|
102
|
+
interface QuotaLimits {
|
|
103
|
+
day?: QuotaWindowLimits;
|
|
104
|
+
month?: QuotaWindowLimits;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The default {@link QuotaProvider}: windows read off the usage ledger the loop already writes.
|
|
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.
|
|
111
|
+
* - `month` — when the store implements `usageBetween`.
|
|
112
|
+
*
|
|
113
|
+
* `limits` add ceilings per window (tokens and/or USD). A window that reaches one makes the report
|
|
114
|
+
* `blocked`.
|
|
115
|
+
*/
|
|
116
|
+
declare class LedgerQuotaProvider implements QuotaProvider {
|
|
117
|
+
private readonly store;
|
|
118
|
+
private readonly quota?;
|
|
119
|
+
private readonly limits;
|
|
120
|
+
constructor(store: AgentStore, quota?: QuotaStore | undefined, limits?: QuotaLimits);
|
|
121
|
+
report(query: QuotaQuery): Promise<QuotaReport>;
|
|
122
|
+
private dayWindow;
|
|
123
|
+
private window;
|
|
124
|
+
}
|
|
89
125
|
|
|
90
126
|
/**
|
|
91
127
|
* Which half of the module this process mounts — the split that lets an API pod and a WORKER pod
|
|
@@ -205,6 +241,17 @@ interface AgentModuleOptions {
|
|
|
205
241
|
* `ModelTurnArgs.model`. Omit → an empty catalog, and a request naming a model is refused.
|
|
206
242
|
*/
|
|
207
243
|
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;
|
|
208
255
|
/**
|
|
209
256
|
* Daily per-actor token budget, enforced against the persisted usage ledger by the built-in
|
|
210
257
|
* `LedgerQuotaStore`. A convenience over wiring a {@link QuotaStore} by hand — set this and quotas
|
|
@@ -479,4 +526,4 @@ declare class AgentDepsFactory {
|
|
|
479
526
|
private followUpsCount;
|
|
480
527
|
}
|
|
481
528
|
|
|
482
|
-
export { AgentDepsFactory as A, type FunctionalTool as F, type AgentSurface as a, type AgentModuleOptions as b, type AgentModuleAsyncOptions as c, type AgentSkillsOptions as d, AGENT_TOOL_BRAND as e, type AgentAttachmentsOptions as f, type AgentDeps as g, type AgentMemoryOptions as h,
|
|
529
|
+
export { AgentDepsFactory as A, type FunctionalTool as F, LedgerQuotaProvider as L, type QuotaLimits as Q, type AgentSurface as a, type AgentModuleOptions as b, type AgentModuleAsyncOptions as c, type AgentSkillsOptions as d, AGENT_TOOL_BRAND as e, type AgentAttachmentsOptions as f, type AgentDeps as g, type AgentMemoryOptions as h, type QuotaWindowLimits as i, delegateToolName as j, provideAgentTools as k, provideAgentTool as p, utcDay as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, ModelCatalog, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry } from '@dudousxd/nestjs-agent-core';
|
|
1
|
+
import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, QuotaProvider, QuotaQuery, QuotaReport, ModelCatalog, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry } from '@dudousxd/nestjs-agent-core';
|
|
2
2
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
3
|
import { Provider, FactoryProvider, Type, CanActivate, ModuleMetadata, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
|
|
4
4
|
|
|
@@ -86,6 +86,42 @@ interface FunctionalTool {
|
|
|
86
86
|
*/
|
|
87
87
|
declare function provideAgentTool(tool: FunctionalTool): Provider;
|
|
88
88
|
declare function provideAgentTool(factory: (...deps: never[]) => FunctionalTool, inject?: FactoryProvider['inject']): Provider;
|
|
89
|
+
/**
|
|
90
|
+
* Registers a LIST of functional tools from one factory — for a producer whose tool count is only
|
|
91
|
+
* known once its dependencies resolve (a catalog loaded from config, one tool per entry). The
|
|
92
|
+
* factory's result is branded element by element; `AiToolDiscoveryService` registers each.
|
|
93
|
+
*/
|
|
94
|
+
declare function provideAgentTools(factory: (...deps: never[]) => readonly FunctionalTool[] | Promise<readonly FunctionalTool[]>, inject?: FactoryProvider['inject']): Provider;
|
|
95
|
+
|
|
96
|
+
/** Ceilings for a {@link LedgerQuotaProvider} window. Either, both, or neither. */
|
|
97
|
+
interface QuotaWindowLimits {
|
|
98
|
+
tokens?: number;
|
|
99
|
+
usd?: number;
|
|
100
|
+
}
|
|
101
|
+
/** Per-window ceilings: `AgentModule.forRoot({ quotaLimits })`. */
|
|
102
|
+
interface QuotaLimits {
|
|
103
|
+
day?: QuotaWindowLimits;
|
|
104
|
+
month?: QuotaWindowLimits;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The default {@link QuotaProvider}: windows read off the usage ledger the loop already writes.
|
|
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.
|
|
111
|
+
* - `month` — when the store implements `usageBetween`.
|
|
112
|
+
*
|
|
113
|
+
* `limits` add ceilings per window (tokens and/or USD). A window that reaches one makes the report
|
|
114
|
+
* `blocked`.
|
|
115
|
+
*/
|
|
116
|
+
declare class LedgerQuotaProvider implements QuotaProvider {
|
|
117
|
+
private readonly store;
|
|
118
|
+
private readonly quota?;
|
|
119
|
+
private readonly limits;
|
|
120
|
+
constructor(store: AgentStore, quota?: QuotaStore | undefined, limits?: QuotaLimits);
|
|
121
|
+
report(query: QuotaQuery): Promise<QuotaReport>;
|
|
122
|
+
private dayWindow;
|
|
123
|
+
private window;
|
|
124
|
+
}
|
|
89
125
|
|
|
90
126
|
/**
|
|
91
127
|
* Which half of the module this process mounts — the split that lets an API pod and a WORKER pod
|
|
@@ -205,6 +241,17 @@ interface AgentModuleOptions {
|
|
|
205
241
|
* `ModelTurnArgs.model`. Omit → an empty catalog, and a request naming a model is refused.
|
|
206
242
|
*/
|
|
207
243
|
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;
|
|
208
255
|
/**
|
|
209
256
|
* Daily per-actor token budget, enforced against the persisted usage ledger by the built-in
|
|
210
257
|
* `LedgerQuotaStore`. A convenience over wiring a {@link QuotaStore} by hand — set this and quotas
|
|
@@ -479,4 +526,4 @@ declare class AgentDepsFactory {
|
|
|
479
526
|
private followUpsCount;
|
|
480
527
|
}
|
|
481
528
|
|
|
482
|
-
export { AgentDepsFactory as A, type FunctionalTool as F, type AgentSurface as a, type AgentModuleOptions as b, type AgentModuleAsyncOptions as c, type AgentSkillsOptions as d, AGENT_TOOL_BRAND as e, type AgentAttachmentsOptions as f, type AgentDeps as g, type AgentMemoryOptions as h,
|
|
529
|
+
export { AgentDepsFactory as A, type FunctionalTool as F, LedgerQuotaProvider as L, type QuotaLimits as Q, type AgentSurface as a, type AgentModuleOptions as b, type AgentModuleAsyncOptions as c, type AgentSkillsOptions as d, AGENT_TOOL_BRAND as e, type AgentAttachmentsOptions as f, type AgentDeps as g, type AgentMemoryOptions as h, type QuotaWindowLimits as i, delegateToolName as j, provideAgentTools as k, provideAgentTool as p, utcDay as u };
|