@dudousxd/nestjs-agent 1.20.0 → 1.21.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 +51 -0
- package/dist/{chat-queue.service-C0hr7dqx.d.ts → chat-queue.service-CGsR40Ct.d.cts} +16 -2
- package/dist/{chat-queue.service-C0hr7dqx.d.cts → chat-queue.service-XG9RQCjU.d.ts} +16 -2
- package/dist/durable/index.cjs +1556 -830
- package/dist/durable/index.cjs.map +1 -1
- package/dist/durable/index.d.cts +3 -1
- package/dist/durable/index.d.ts +3 -1
- package/dist/durable/index.js +1290 -564
- package/dist/durable/index.js.map +1 -1
- package/dist/genui/index.d.cts +1 -1
- package/dist/genui/index.d.ts +1 -1
- package/dist/index.cjs +1487 -825
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -9
- package/dist/index.d.ts +111 -9
- package/dist/index.js +1258 -599
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -405,6 +405,57 @@ In anonymous mode the limits apply per browser (each is its own actor).
|
|
|
405
405
|
|
|
406
406
|
### Who approves an action, and for how long
|
|
407
407
|
|
|
408
|
+
Action handlers can implement an optional read-only `preflight(input, ctx, { phase })`. The
|
|
409
|
+
registry authorizes and validates the input first. `prepare` runs before an approval is requested;
|
|
410
|
+
`execute` rechecks current state inside the tool checkpoint immediately before its side effect.
|
|
411
|
+
Automatic and remembered approvals still run both checks; direct registry and MCP invocations
|
|
412
|
+
run the execution check too.
|
|
413
|
+
|
|
414
|
+
```ts
|
|
415
|
+
class RemoveSessionsTool implements ToolHandler<{ accountId: string }, { removed: number }> {
|
|
416
|
+
constructor(private readonly sessions: SessionsService) {}
|
|
417
|
+
|
|
418
|
+
async preflight(input: { accountId: string }, ctx: AiToolCtx, { phase }: ToolPreflightOptions): Promise<ToolPreflightResult<{ removed: number }>> {
|
|
419
|
+
const count = await this.sessions.countForActor(input.accountId, ctx.actor);
|
|
420
|
+
if (count === 0) return { status: 'completed', output: { removed: 0 } };
|
|
421
|
+
if (await this.sessions.isLocked(input.accountId)) {
|
|
422
|
+
return { status: 'denied', reason: 'This account is locked.' };
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
status: 'ready',
|
|
426
|
+
confirmation: { title: `Remove ${count} sessions?`, verb: 'Remove' },
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
async execute(input: { accountId: string }, ctx: AiToolCtx) {
|
|
431
|
+
return this.sessions.removeForActor(input.accountId, ctx.actor, ctx.idempotencyKey);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
`ready` may supply fully resolved `ToolConfirmation` strings (`title`, `verb`, optional `detail`)
|
|
437
|
+
that override the tool's presentation templates for this call, including after a history reload.
|
|
438
|
+
`denied` returns a domain refusal to the model, and `completed` returns an existing result. Both
|
|
439
|
+
skip approval and execution during preparation. A completed terminal action ends the turn.
|
|
440
|
+
A refusal after a person approves preserves that approval while reporting that the mutation did
|
|
441
|
+
not run. An exception becomes a failed tool result. Read tools ignore this hook.
|
|
442
|
+
|
|
443
|
+
Functional tools use the same handler contract:
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
provideAgentTool({
|
|
447
|
+
spec: removeSessionsSpec,
|
|
448
|
+
handler: { preflight: checkSessions, execute: removeSessions },
|
|
449
|
+
});
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Preflight must not perform writes or emit UI. Its preparation result is journaled with the existing
|
|
453
|
+
call checkpoint (and, for remote execution, first with the model worker's turn); replay uses that
|
|
454
|
+
result without rerunning the check or changing its approval branch. The execution check is
|
|
455
|
+
journaled inside the existing tool checkpoint. Keep domain checks inside `execute` or an atomic
|
|
456
|
+
transaction as needed: a preflight check cannot eliminate concurrent changes between reads and
|
|
457
|
+
writes, and it does not replace idempotency.
|
|
458
|
+
|
|
408
459
|
Every `action` tool call waits on the person chatting by default. `approvalPolicy` changes that per
|
|
409
460
|
call:
|
|
410
461
|
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, QuotaProvider, QuotaQuery, QuotaReport, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason
|
|
1
|
+
import { ResolveToolUiCatalog, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, ActionProposal, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
|
|
2
|
+
import { Catalog } from '@dudousxd/nestjs-agent-core/genui';
|
|
2
3
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
4
|
import { Provider, FactoryProvider, Type, CanActivate, ModuleMetadata, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
|
|
5
|
+
import { GenuiCatalogResolver } from './genui/index.cjs';
|
|
4
6
|
|
|
5
7
|
/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */
|
|
6
8
|
interface AgentDeps {
|
|
9
|
+
resolveUiCatalog?: ResolveToolUiCatalog;
|
|
10
|
+
actionApprovalMode?: 'blocking' | 'independent';
|
|
7
11
|
model: ModelProvider;
|
|
8
12
|
store: AgentStore;
|
|
9
13
|
registry: ToolRegistry;
|
|
@@ -240,6 +244,13 @@ interface AgentMemoryOptions {
|
|
|
240
244
|
maxFactChars?: number;
|
|
241
245
|
}
|
|
242
246
|
interface AgentModuleOptions {
|
|
247
|
+
actionApprovalMode?: ActionApprovalMode;
|
|
248
|
+
backgroundActorResolver?: BackgroundActorResolver;
|
|
249
|
+
actionProposalWorker?: {
|
|
250
|
+
pollIntervalMs?: number;
|
|
251
|
+
leaseMs?: number;
|
|
252
|
+
maxConcurrency?: number;
|
|
253
|
+
};
|
|
243
254
|
/**
|
|
244
255
|
* The LLM provider — `aiSdkModel(openai('gpt-5-mini'))`, or `aiSdkModels({ … })` for a model
|
|
245
256
|
* picker (its catalog is used when `models` is omitted). The only required option.
|
|
@@ -525,7 +536,9 @@ declare class AgentDepsFactory {
|
|
|
525
536
|
private readonly pricingStore;
|
|
526
537
|
private readonly skills;
|
|
527
538
|
private readonly memory;
|
|
528
|
-
|
|
539
|
+
private readonly uiCatalog?;
|
|
540
|
+
private readonly uiCatalogResolver?;
|
|
541
|
+
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, uiCatalog?: Catalog | undefined, uiCatalogResolver?: GenuiCatalogResolver | undefined);
|
|
529
542
|
/** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */
|
|
530
543
|
memoryConfig(): MemoryConfig | undefined;
|
|
531
544
|
/** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */
|
|
@@ -558,6 +571,7 @@ declare class AgentDepsFactory {
|
|
|
558
571
|
requested?: string;
|
|
559
572
|
threadPersona?: string | null;
|
|
560
573
|
}): string | undefined;
|
|
574
|
+
forProposal(proposal: ActionProposal, _actor: Actor): AgentDeps;
|
|
561
575
|
forAgent(agentName?: string): AgentDeps;
|
|
562
576
|
/**
|
|
563
577
|
* A persona baked into an agent's deps — how a run journaled under an agent name that a persona
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, QuotaProvider, QuotaQuery, QuotaReport, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason
|
|
1
|
+
import { ResolveToolUiCatalog, ModelProvider, AgentStore, ToolRegistry, RolesPolicy, ApprovalPolicy, QuotaStore, TokenStreamSink, PromptBuilder, PromptContributor, Persona, ToolTransientRetrySetting, Retriever, AgentPricingStore, HistoryPolicy, InputProcessor, OutputProcessor, AgentIntake, SkillsConfig, MemoryConfig, ToolSpec, ToolHandler, QuotaProvider, QuotaQuery, QuotaReport, ActionApprovalMode, BackgroundActorResolver, ModelCatalog, EmptyRoles, ActorResolver, AgentHistoryWindow, SkillProvider, ScopeResolver, MemoryProvider, AgentRegistry, PersonaCatalogEntry, ActionProposal, Actor, AttachmentStagingStore, ChatQueueStore, ChatQueueState, AgentRunner, AgentRunInput, AgentStreamEvent, QueuePauseReason } from '@dudousxd/nestjs-agent-core';
|
|
2
|
+
import { Catalog } from '@dudousxd/nestjs-agent-core/genui';
|
|
2
3
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
4
|
import { Provider, FactoryProvider, Type, CanActivate, ModuleMetadata, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
|
|
5
|
+
import { GenuiCatalogResolver } from './genui/index.js';
|
|
4
6
|
|
|
5
7
|
/** Everything `runAgentLoop` needs, minus the per-run `day` the runner stamps. */
|
|
6
8
|
interface AgentDeps {
|
|
9
|
+
resolveUiCatalog?: ResolveToolUiCatalog;
|
|
10
|
+
actionApprovalMode?: 'blocking' | 'independent';
|
|
7
11
|
model: ModelProvider;
|
|
8
12
|
store: AgentStore;
|
|
9
13
|
registry: ToolRegistry;
|
|
@@ -240,6 +244,13 @@ interface AgentMemoryOptions {
|
|
|
240
244
|
maxFactChars?: number;
|
|
241
245
|
}
|
|
242
246
|
interface AgentModuleOptions {
|
|
247
|
+
actionApprovalMode?: ActionApprovalMode;
|
|
248
|
+
backgroundActorResolver?: BackgroundActorResolver;
|
|
249
|
+
actionProposalWorker?: {
|
|
250
|
+
pollIntervalMs?: number;
|
|
251
|
+
leaseMs?: number;
|
|
252
|
+
maxConcurrency?: number;
|
|
253
|
+
};
|
|
243
254
|
/**
|
|
244
255
|
* The LLM provider — `aiSdkModel(openai('gpt-5-mini'))`, or `aiSdkModels({ … })` for a model
|
|
245
256
|
* picker (its catalog is used when `models` is omitted). The only required option.
|
|
@@ -525,7 +536,9 @@ declare class AgentDepsFactory {
|
|
|
525
536
|
private readonly pricingStore;
|
|
526
537
|
private readonly skills;
|
|
527
538
|
private readonly memory;
|
|
528
|
-
|
|
539
|
+
private readonly uiCatalog?;
|
|
540
|
+
private readonly uiCatalogResolver?;
|
|
541
|
+
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, uiCatalog?: Catalog | undefined, uiCatalogResolver?: GenuiCatalogResolver | undefined);
|
|
529
542
|
/** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */
|
|
530
543
|
memoryConfig(): MemoryConfig | undefined;
|
|
531
544
|
/** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */
|
|
@@ -558,6 +571,7 @@ declare class AgentDepsFactory {
|
|
|
558
571
|
requested?: string;
|
|
559
572
|
threadPersona?: string | null;
|
|
560
573
|
}): string | undefined;
|
|
574
|
+
forProposal(proposal: ActionProposal, _actor: Actor): AgentDeps;
|
|
561
575
|
forAgent(agentName?: string): AgentDeps;
|
|
562
576
|
/**
|
|
563
577
|
* A persona baked into an agent's deps — how a run journaled under an agent name that a persona
|