@dudousxd/nestjs-agent 1.1.2 → 1.3.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 +59 -0
- package/dist/{agent-deps.factory-OjrLyAZo.d.cts → agent-deps.factory-CUyVPsa1.d.cts} +10 -1
- package/dist/{agent-deps.factory-OjrLyAZo.d.ts → agent-deps.factory-CUyVPsa1.d.ts} +10 -1
- package/dist/durable/index.cjs +378 -147
- 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 +309 -78
- package/dist/durable/index.js.map +1 -1
- package/dist/index.cjs +365 -150
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -6
- package/dist/index.d.ts +80 -6
- package/dist/index.js +291 -77
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -41,6 +41,35 @@ The module mounts SSE + REST endpoints under `/agent` (`POST /agent/chat`, tool-
|
|
|
41
41
|
threads, quota). Add `durable: true` + `AgentDurableModule` for the durable runner;
|
|
42
42
|
`AgentModule.forFeature([…])` for multi-agent orchestration.
|
|
43
43
|
|
|
44
|
+
### How a chat talks about a tool
|
|
45
|
+
|
|
46
|
+
A tool's name is an identifier, not copy. Declare how a person-facing surface narrates it beside its
|
|
47
|
+
input schema, so whoever renames an input field is the one who re-words the sentence that mentions
|
|
48
|
+
it:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
@AiTool({
|
|
52
|
+
name: 'purgeCache',
|
|
53
|
+
kind: 'action',
|
|
54
|
+
description: 'Purge a cache key.',
|
|
55
|
+
input: z.object({ key: z.string() }),
|
|
56
|
+
presentation: {
|
|
57
|
+
label: 'Cache purge',
|
|
58
|
+
running: 'Purging {key}', // templates over the call's INPUT
|
|
59
|
+
done: 'Purged {key}',
|
|
60
|
+
icon: 'cache', // a key into the client's own glyph map
|
|
61
|
+
tone: 'destructive',
|
|
62
|
+
confirm: { title: 'Purge {key}?', verb: 'Purge' },
|
|
63
|
+
result: { kind: 'metrics', fields: [{ path: 'evicted', label: 'Evicted' }] }, // over the OUTPUT
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`GET /agent/tools?agent=<name>` returns `ToolCatalogEntry[]` — `{ name, kind, presentation? }` for the
|
|
69
|
+
tools THIS actor can reach through that agent (the default agent when omitted; `404` for an unknown
|
|
70
|
+
one), built by `ToolRegistry.visibleSpecs`, the same gates the model is offered tools through. The
|
|
71
|
+
React package's `useToolCatalog` reads it. The model never sees `presentation`.
|
|
72
|
+
|
|
44
73
|
### Message attachments
|
|
45
74
|
|
|
46
75
|
A chat turn attaches a file by **`mediaId` only**:
|
|
@@ -101,6 +130,36 @@ nobody is streaming (including one that has already finished). In-process caller
|
|
|
101
130
|
authorized elsewhere use `AgentService.subscribe(runId)`; anything reachable from a request must go
|
|
102
131
|
through `AgentService.subscribeAs(actor, runId)`.
|
|
103
132
|
|
|
133
|
+
### Who approves an action, and for how long
|
|
134
|
+
|
|
135
|
+
Every `action` tool call waits on the person chatting by default. `approvalPolicy` changes that per
|
|
136
|
+
call:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
AgentModule.forRoot({
|
|
140
|
+
// …
|
|
141
|
+
approvalPolicy: {
|
|
142
|
+
requirementFor: (tool, actor) =>
|
|
143
|
+
tool.name === 'issueRefund'
|
|
144
|
+
? { required: true, approver: 'finance', ttlMs: 15 * 60_000 }
|
|
145
|
+
: { required: true, approver: 'requester' },
|
|
146
|
+
// Optional. Default: 'requester' = the thread's own actor, anything else = a role the decider holds.
|
|
147
|
+
// canDecide: (actor, { approver, requesterRef }) => gate.forUser(actor).allows('approve', approver),
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- `POST /agent/tool-call/approve` `{ toolCallId, remember?, via? }` and `…/reject` `{ toolCallId,
|
|
153
|
+
reason?, via? }` enforce the recorded approver (`403` otherwise) and refuse a request that has
|
|
154
|
+
lapsed (`410`). The decider is recorded as `executedByRef`, `via` as `decided_via` (`'web'` when
|
|
155
|
+
omitted; the console approvals port takes `decidedVia` too).
|
|
156
|
+
- `remember: true` approves later calls of the same tool in the same thread without asking.
|
|
157
|
+
- A `ttlMs` becomes the approval wait's timeout — `ctx.waitForSignal(…, { timeoutMs })` on the
|
|
158
|
+
durable runner, a timer inline. On expiry the call settles `expired`, the model is told nobody
|
|
159
|
+
approved it in time, and the stream carries `tool-output-denied` + `approval-settled`.
|
|
160
|
+
- The tool-call row gains `approver`, `expires_at`, `remember` and `decided_via`; a reloaded thread
|
|
161
|
+
carries them as `StoredMessage.approvals`.
|
|
162
|
+
|
|
104
163
|
### A durable turn's model call and tools run in a worker
|
|
105
164
|
|
|
106
165
|
Under `durable: true` the turn's model call and each of its tool executions are **dispatched steps**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, 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, 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
|
|
|
@@ -8,6 +8,8 @@ interface AgentDeps {
|
|
|
8
8
|
store: AgentStore;
|
|
9
9
|
registry: ToolRegistry;
|
|
10
10
|
rolesPolicy: RolesPolicy;
|
|
11
|
+
/** Who approves an action call, and for how long (from `forRoot({ approvalPolicy })`). Undefined → the requester, no expiry. */
|
|
12
|
+
approvalPolicy?: ApprovalPolicy;
|
|
11
13
|
quota?: QuotaStore;
|
|
12
14
|
sink: TokenStreamSink;
|
|
13
15
|
/** Fallback accounting label; the provider's turn result overrides it when set. */
|
|
@@ -205,6 +207,13 @@ interface AgentModuleOptions {
|
|
|
205
207
|
quotaLimitTokens?: number;
|
|
206
208
|
/** Tool authorization gate. Defaults to role-in-`defaultRoles`. */
|
|
207
209
|
rolesPolicy?: RolesPolicy;
|
|
210
|
+
/**
|
|
211
|
+
* Who has to approve an `action` tool call, and how long the request stays open. Defaults to the
|
|
212
|
+
* requester (the thread's own actor) with no expiry. A requirement naming another approver (a
|
|
213
|
+
* role) is enforced by `POST tool-call/approve|reject` through `canDecide` — by default, the
|
|
214
|
+
* deciding actor must hold that role. See `ApprovalPolicy`.
|
|
215
|
+
*/
|
|
216
|
+
approvalPolicy?: ApprovalPolicy;
|
|
208
217
|
/** Default roles a tool requires when its `roles` is omitted. Defaults to `['ADMIN']`. */
|
|
209
218
|
defaultRoles?: string[];
|
|
210
219
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, 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, 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
|
|
|
@@ -8,6 +8,8 @@ interface AgentDeps {
|
|
|
8
8
|
store: AgentStore;
|
|
9
9
|
registry: ToolRegistry;
|
|
10
10
|
rolesPolicy: RolesPolicy;
|
|
11
|
+
/** Who approves an action call, and for how long (from `forRoot({ approvalPolicy })`). Undefined → the requester, no expiry. */
|
|
12
|
+
approvalPolicy?: ApprovalPolicy;
|
|
11
13
|
quota?: QuotaStore;
|
|
12
14
|
sink: TokenStreamSink;
|
|
13
15
|
/** Fallback accounting label; the provider's turn result overrides it when set. */
|
|
@@ -205,6 +207,13 @@ interface AgentModuleOptions {
|
|
|
205
207
|
quotaLimitTokens?: number;
|
|
206
208
|
/** Tool authorization gate. Defaults to role-in-`defaultRoles`. */
|
|
207
209
|
rolesPolicy?: RolesPolicy;
|
|
210
|
+
/**
|
|
211
|
+
* Who has to approve an `action` tool call, and how long the request stays open. Defaults to the
|
|
212
|
+
* requester (the thread's own actor) with no expiry. A requirement naming another approver (a
|
|
213
|
+
* role) is enforced by `POST tool-call/approve|reject` through `canDecide` — by default, the
|
|
214
|
+
* deciding actor must hold that role. See `ApprovalPolicy`.
|
|
215
|
+
*/
|
|
216
|
+
approvalPolicy?: ApprovalPolicy;
|
|
208
217
|
/** Default roles a tool requires when its `roles` is omitted. Defaults to `['ADMIN']`. */
|
|
209
218
|
defaultRoles?: string[];
|
|
210
219
|
/**
|