@dudousxd/nestjs-agent 1.19.3 → 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/dist/index.d.cts CHANGED
@@ -1,17 +1,58 @@
1
- import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit, ConflictException } from '@nestjs/common';
2
- import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter, e as AgentSkillsOptions } from './chat-queue.service-CKZkjlMK.cjs';
3
- export { f as AGENT_TOOL_BRAND, g as AgentAttachmentsOptions, h as AgentDeps, i as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QueuePlan, j as QueueSettleOutcome, k as QueuedTurn, l as QueuedTurnStarter, m as QuotaLimits, n as QuotaWindowLimits, o as delegateToolName, p as provideAgentTool, q as provideAgentTools, u as utcDay } from './chat-queue.service-CKZkjlMK.cjs';
4
- import { AgentRunner, AgentStore, AttachmentStagingStore, ModelCatalog, QuotaProvider, Actor, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver, AgentApprovalPort, MessageAttachment, AgentAttachmentConfig, AgentClientConfig, ToolPresentation, AgentHistoryWindow, AgentIntake, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, AgentRunStartOptions, TokenStreamSink, SinkWriter } from '@dudousxd/nestjs-agent-core';
1
+ import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit, ConflictException, OnModuleDestroy } from '@nestjs/common';
2
+ import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter, e as AgentSkillsOptions } from './chat-queue.service-CGsR40Ct.cjs';
3
+ export { f as AGENT_TOOL_BRAND, g as AgentAttachmentsOptions, h as AgentDeps, i as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QueuePlan, j as QueueSettleOutcome, k as QueuedTurn, l as QueuedTurnStarter, m as QuotaLimits, n as QuotaWindowLimits, o as delegateToolName, p as provideAgentTool, q as provideAgentTools, u as utcDay } from './chat-queue.service-CGsR40Ct.cjs';
4
+ import * as _dudousxd_nestjs_agent_core from '@dudousxd/nestjs-agent-core';
5
+ import { AgentStore, Actor, ListActionProposals, ActionProposalMutationResult, AgentRunner, AttachmentStagingStore, ModelCatalog, QuotaProvider, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver, AgentApprovalPort, MessageAttachment, AgentAttachmentConfig, AgentClientConfig, ToolSpec, ToolPresentation, AgentHistoryWindow, AgentIntake, Persona, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, AgentRunStartOptions, TokenStreamSink, SinkWriter } from '@dudousxd/nestjs-agent-core';
5
6
  export * from '@dudousxd/nestjs-agent-core';
6
7
  import { Request, Response } from 'express';
8
+ import { UiCapabilities } from '@dudousxd/nestjs-agent-core/genui';
7
9
  import { StandardSchemaV1 } from '@standard-schema/spec';
8
10
  import { DiscoveryService, MetadataScanner } from '@nestjs/core';
11
+ import './genui/index.cjs';
9
12
 
10
13
  declare class AgentModule {
11
14
  static forRoot(options: AgentModuleOptions): DynamicModule;
12
15
  static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule;
13
16
  }
14
17
 
18
+ declare class ActionProposalService {
19
+ private readonly store;
20
+ private readonly options;
21
+ constructor(store: AgentStore, options: Pick<AgentModuleOptions, 'approvalPolicy'>);
22
+ private capability;
23
+ private scope;
24
+ private mayDecide;
25
+ listPage(threadId: string, actor: Actor, query?: Pick<ListActionProposals, 'after'>): Promise<{
26
+ next?: {
27
+ createdAt: number;
28
+ id: string;
29
+ };
30
+ items: _dudousxd_nestjs_agent_core.ActionProposal[];
31
+ }>;
32
+ list(threadId: string, actor: Actor): Promise<_dudousxd_nestjs_agent_core.ActionProposal[]>;
33
+ decide(threadId: string, proposalId: string, actor: Actor, command: {
34
+ decision: 'approved' | 'rejected';
35
+ remember?: boolean;
36
+ reason?: string;
37
+ via?: string;
38
+ }): Promise<ActionProposalMutationResult>;
39
+ handleTextDecision(threadId: string, actor: Actor, text: string): Promise<{
40
+ status: "unmatched";
41
+ } | {
42
+ threadId: string;
43
+ proposalDecision: ActionProposalMutationResult;
44
+ text: string;
45
+ } | {
46
+ threadId: string;
47
+ proposalDecision: {
48
+ status: "ambiguous";
49
+ proposalIds: string[];
50
+ };
51
+ text: string;
52
+ }>;
53
+ private textReceipt;
54
+ }
55
+
15
56
  /**
16
57
  * What a send does when its thread already has a turn running:
17
58
  * - `'auto'` (default) — run now when the thread is idle, else wait in the thread's queue.
@@ -39,12 +80,24 @@ type ChatSendResult = {
39
80
  runId: string;
40
81
  threadId: string;
41
82
  queued?: undefined;
42
- } | QueuedSend;
83
+ } | QueuedSend | {
84
+ threadId: string;
85
+ proposalDecision: unknown;
86
+ text: string;
87
+ queued?: undefined;
88
+ };
43
89
  interface ChatParams {
90
+ uiCapabilities?: UiCapabilities;
44
91
  actor: Actor;
45
92
  message: string;
46
93
  threadId?: string;
47
94
  agentName?: string;
95
+ /**
96
+ * Run this turn under one of the agent's personas (`@Agent({ personas })`), and pin it on the
97
+ * thread so later sends that name none keep it. Refused (400 `persona_not_found`) unless the agent
98
+ * declares it. Omitted → the thread's pinned persona, else the agent's `defaultPersona`, else none.
99
+ */
100
+ personaId?: string;
48
101
  /**
49
102
  * Files attached to this message (image/PDF) for a vision-capable model, named by the `mediaId`
50
103
  * the upload returned. Only the id is read: the url, content type and name are resolved from the
@@ -97,7 +150,22 @@ declare class AgentService {
97
150
  private readonly quotaProvider?;
98
151
  private readonly options?;
99
152
  private readonly queue?;
100
- constructor(runner: AgentRunner, store: AgentStore, deps: AgentDepsFactory, staging?: AttachmentStagingStore | undefined, models?: ModelCatalog | undefined, quotaProvider?: QuotaProvider | undefined, options?: Pick<AgentModuleOptions, "quota"> | undefined, queue?: ChatQueueService | undefined);
153
+ private readonly proposals?;
154
+ constructor(runner: AgentRunner, store: AgentStore, deps: AgentDepsFactory, staging?: AttachmentStagingStore | undefined, models?: ModelCatalog | undefined, quotaProvider?: QuotaProvider | undefined, options?: Pick<AgentModuleOptions, "quota" | "actionApprovalMode"> | undefined, queue?: ChatQueueService | undefined, proposals?: ActionProposalService | undefined);
155
+ handleTextDecision(threadId: string, actor: Actor, text: string): Promise<{
156
+ status: "unmatched";
157
+ } | {
158
+ threadId: string;
159
+ proposalDecision: _dudousxd_nestjs_agent_core.ActionProposalMutationResult;
160
+ text: string;
161
+ } | {
162
+ threadId: string;
163
+ proposalDecision: {
164
+ status: "ambiguous";
165
+ proposalIds: string[];
166
+ };
167
+ text: string;
168
+ }>;
101
169
  /** The queue service when the bound store can hold a queue, else `undefined`. */
102
170
  private queueing;
103
171
  /** The queue service, or a 501 naming what is missing. */
@@ -143,7 +211,9 @@ declare class AgentService {
143
211
  * Send a message: start a turn, or — when its thread already has one running — queue the message
144
212
  * to run after it (see {@link ChatSendMode}). What `POST <base>/chat` calls.
145
213
  */
146
- send(params: ChatParams): Promise<ChatSendResult>;
214
+ send(params: ChatParams, sendOptions?: {
215
+ textDecisions?: boolean;
216
+ }): Promise<ChatSendResult>;
147
217
  /**
148
218
  * Start a turn the thread is already claimed for, under the claimed id. A runner that minted an
149
219
  * id of its own anyway gets the thread re-pointed at it; one that fails to start frees the thread.
@@ -293,6 +363,13 @@ declare class AgentService {
293
363
  * dropping the field.
294
364
  */
295
365
  updateThread(actor: Actor, threadId: string, patch: UpdateThreadInput): Promise<void>;
366
+ /**
367
+ * The persona this send runs under — see {@link AgentDepsFactory.resolvePersona}. The thread's
368
+ * pinned persona is read only when the send names none AND the agent has personas to pick from.
369
+ */
370
+ private resolvePersona;
371
+ /** Pin `persona` on the thread when it is not already — a no-op on a store that cannot. */
372
+ private pinThreadPersona;
296
373
  private validateTitle;
297
374
  /**
298
375
  * Agent-selection precedence for a `chat()` call with no explicit `agentName`: the thread's own
@@ -479,7 +556,24 @@ declare function agUiAdapter(options?: AgUiAdapterOptions): AgentProtocolAdapter
479
556
  */
480
557
  declare class AgentApprovalPortAdapter implements AgentApprovalPort {
481
558
  private readonly agent;
482
- constructor(agent: AgentService);
559
+ private readonly proposals?;
560
+ constructor(agent: AgentService, proposals?: ActionProposalService | undefined);
561
+ approveActionProposal(actor: Actor, target: {
562
+ kind: 'proposal';
563
+ threadId: string;
564
+ proposalId: string;
565
+ }, opts?: {
566
+ remember?: boolean;
567
+ decidedVia?: string;
568
+ }): Promise<_dudousxd_nestjs_agent_core.ActionProposalMutationResult>;
569
+ rejectActionProposal(actor: Actor, target: {
570
+ kind: 'proposal';
571
+ threadId: string;
572
+ proposalId: string;
573
+ }, opts?: {
574
+ reason?: string;
575
+ decidedVia?: string;
576
+ }): Promise<_dudousxd_nestjs_agent_core.ActionProposalMutationResult>;
483
577
  approve(toolCallId: string, opts?: {
484
578
  executedByRef?: string;
485
579
  remember?: boolean;
@@ -492,6 +586,19 @@ declare class AgentApprovalPortAdapter implements AgentApprovalPort {
492
586
  }): Promise<void>;
493
587
  }
494
588
 
589
+ /**
590
+ * A store that can answer a thread's pinned persona on its own, without materializing the thread —
591
+ * probed structurally, like `ThreadDefaultAgentReader`.
592
+ */
593
+ interface ThreadPersonaReader {
594
+ personaForThread(threadId: string): Promise<string | null>;
595
+ }
596
+ /**
597
+ * The thread's pinned persona: one column when the store projects it ({@link ThreadPersonaReader}),
598
+ * else through the full read.
599
+ */
600
+ declare function threadPersona(store: AgentStore, threadId: string): Promise<string | null>;
601
+
495
602
  /**
496
603
  * How many entries `GET /agent/attachments` returns. Fixed rather than caller-supplied: this route
497
604
  * exists so a composer can show the files someone has uploaded, and a host that needs real paging
@@ -555,6 +662,7 @@ declare class ConfigController {
555
662
 
556
663
  declare const AI_TOOL_METADATA: unique symbol;
557
664
  interface AiToolOptions {
665
+ replacementKey?: ToolSpec['replacementKey'];
558
666
  /**
559
667
  * What the model calls it. Omit → the class name, camelCased, with a trailing `Tool` dropped
560
668
  * (`GetWeatherTool` → `getWeather`).
@@ -744,6 +852,20 @@ interface AgentOptions {
744
852
  * module-wide setting.
745
853
  */
746
854
  ask?: boolean;
855
+ /**
856
+ * Named variants of THIS agent — a prompt and, optionally, a narrower tool allow-list — that a
857
+ * caller picks per send (`POST <base>/chat { persona }`) and that pin onto the thread. Everything
858
+ * else (model, access rules, handoffs, history) stays this agent's; a variant that needs those to
859
+ * differ is another `@Agent`.
860
+ *
861
+ * A persona's `systemPrompt` is static data. For a prompt built from injected services, leave it
862
+ * out and branch on `ctx.persona` in this class's `@SystemPrompt()` method instead.
863
+ *
864
+ * Omit → no personas, and nothing about a turn changes.
865
+ */
866
+ personas?: Persona[];
867
+ /** The persona a send runs under when neither it nor its thread names one. Omit → none. */
868
+ defaultPersona?: string;
747
869
  }
748
870
  declare const AGENT_METADATA: unique symbol;
749
871
  /** Marks a provider class as an agent. See {@link AgentOptions}. */
@@ -849,6 +971,12 @@ declare class AgentDiscoveryService implements OnModuleInit {
849
971
  onModuleInit(): void;
850
972
  /** Build the internal {@link AgentDefinition} from an `@Agent` instance and its options. */
851
973
  private definitionFrom;
974
+ /**
975
+ * Refuse to boot on a persona declaration that could only fail later, per request: a default that
976
+ * names no persona, an id declared twice, an alias two personas claim, or an alias that is a real
977
+ * agent's name (which would never be reached — a registered agent always wins).
978
+ */
979
+ private assertPersonas;
852
980
  /**
853
981
  * Resolve each handoff entry to an {@link AgentDelegation} — its target's registered name, plus
854
982
  * whether that edge detaches (skipping non-agent classes). A bare name is kept for a plain edge
@@ -1288,4 +1416,24 @@ declare class RunNotActiveException extends ConflictException {
1288
1416
  constructor(runId: string);
1289
1417
  }
1290
1418
 
1291
- export { AGENT_CHAT_QUEUE, AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, type AgUiAdapterOptions, AgUiRunHandler, Agent, AgentApprovalPortAdapter, AgentDepsFactory, AgentDiscoveryService, AgentModule, AgentModuleAsyncOptions, AgentModuleOptions, type AgentOptions, AgentProtocolAdapter, AgentService, AgentSkillsOptions, AiTool, AiToolDiscoveryService, type AiToolOptions, type AnonymousActorOptions, AnonymousActorResolver, type AttachmentLimits, AttachmentsController, type ChatParams, ChatQueueService, type ChatSendMode, type ChatSendResult, ConfigController, DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES, DEFAULT_MAX_ATTACHMENT_BYTES, type DeclaredSkill, HeaderActorResolver, InProcessTokenStreamSink, InlineAgentRunner, MAX_ATTACHMENTS_PER_MESSAGE, MemoriesController, MessagesController, ModelsController, QueueController, type QueuedSend, type RequestUserMapper, type ResolvedAiToolOptions, RunNotActiveException, SKILL_METADATA, SYSTEM_PROMPT_CONTRIBUTOR_METADATA, SYSTEM_PROMPT_METADATA, Skill, type SkillBody, SkillDiscoveryService, type SkillOptions, SkillsController, SystemPrompt, SystemPromptContributor, type ThreadDefaultAgentReader, type ThreadModelReader, ToolsController, agUiAdapter, attachmentLimits, declaredSkillProvider, defaultRequestUserMapper, readAgentMetadata, readAiToolMetadata, readSkillMetadata, requestUserActorResolver, resolveSkillsConfig, skillScope, toolNameFromClass };
1419
+ declare class ActionProposalController {
1420
+ private readonly proposals;
1421
+ private readonly actors;
1422
+ constructor(proposals: ActionProposalService, actors: ActorResolver);
1423
+ list(threadId: string, request: Request, cursor: unknown, response: Response): Promise<_dudousxd_nestjs_agent_core.ActionProposal[]>;
1424
+ approve(threadId: string, proposalId: string, request: Request, body: unknown): Promise<_dudousxd_nestjs_agent_core.ActionProposalMutationResult>;
1425
+ reject(threadId: string, proposalId: string, request: Request, body: unknown): Promise<_dudousxd_nestjs_agent_core.ActionProposalMutationResult>;
1426
+ }
1427
+
1428
+ declare class ActionProposalWorkerService implements OnModuleInit, OnModuleDestroy {
1429
+ private readonly store;
1430
+ private readonly options;
1431
+ private readonly deps;
1432
+ private worker;
1433
+ private readonly logger;
1434
+ constructor(store: AgentStore, options: AgentModuleOptions, deps: AgentDepsFactory);
1435
+ onModuleInit(): void;
1436
+ onModuleDestroy(): Promise<void>;
1437
+ }
1438
+
1439
+ export { AGENT_CHAT_QUEUE, AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, ActionProposalController, ActionProposalService, ActionProposalWorkerService, type AgUiAdapterOptions, AgUiRunHandler, Agent, AgentApprovalPortAdapter, AgentDepsFactory, AgentDiscoveryService, AgentModule, AgentModuleAsyncOptions, AgentModuleOptions, type AgentOptions, AgentProtocolAdapter, AgentService, AgentSkillsOptions, AiTool, AiToolDiscoveryService, type AiToolOptions, type AnonymousActorOptions, AnonymousActorResolver, type AttachmentLimits, AttachmentsController, type ChatParams, ChatQueueService, type ChatSendMode, type ChatSendResult, ConfigController, DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES, DEFAULT_MAX_ATTACHMENT_BYTES, type DeclaredSkill, HeaderActorResolver, InProcessTokenStreamSink, InlineAgentRunner, MAX_ATTACHMENTS_PER_MESSAGE, MemoriesController, MessagesController, ModelsController, QueueController, type QueuedSend, type RequestUserMapper, type ResolvedAiToolOptions, RunNotActiveException, SKILL_METADATA, SYSTEM_PROMPT_CONTRIBUTOR_METADATA, SYSTEM_PROMPT_METADATA, Skill, type SkillBody, SkillDiscoveryService, type SkillOptions, SkillsController, SystemPrompt, SystemPromptContributor, type ThreadDefaultAgentReader, type ThreadModelReader, type ThreadPersonaReader, ToolsController, agUiAdapter, attachmentLimits, declaredSkillProvider, defaultRequestUserMapper, readAgentMetadata, readAiToolMetadata, readSkillMetadata, requestUserActorResolver, resolveSkillsConfig, skillScope, threadPersona, toolNameFromClass };
package/dist/index.d.ts CHANGED
@@ -1,17 +1,58 @@
1
- import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit, ConflictException } from '@nestjs/common';
2
- import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter, e as AgentSkillsOptions } from './chat-queue.service-CKZkjlMK.js';
3
- export { f as AGENT_TOOL_BRAND, g as AgentAttachmentsOptions, h as AgentDeps, i as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QueuePlan, j as QueueSettleOutcome, k as QueuedTurn, l as QueuedTurnStarter, m as QuotaLimits, n as QuotaWindowLimits, o as delegateToolName, p as provideAgentTool, q as provideAgentTools, u as utcDay } from './chat-queue.service-CKZkjlMK.js';
4
- import { AgentRunner, AgentStore, AttachmentStagingStore, ModelCatalog, QuotaProvider, Actor, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver, AgentApprovalPort, MessageAttachment, AgentAttachmentConfig, AgentClientConfig, ToolPresentation, AgentHistoryWindow, AgentIntake, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, AgentRunStartOptions, TokenStreamSink, SinkWriter } from '@dudousxd/nestjs-agent-core';
1
+ import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit, ConflictException, OnModuleDestroy } from '@nestjs/common';
2
+ import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter, e as AgentSkillsOptions } from './chat-queue.service-XG9RQCjU.js';
3
+ export { f as AGENT_TOOL_BRAND, g as AgentAttachmentsOptions, h as AgentDeps, i as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QueuePlan, j as QueueSettleOutcome, k as QueuedTurn, l as QueuedTurnStarter, m as QuotaLimits, n as QuotaWindowLimits, o as delegateToolName, p as provideAgentTool, q as provideAgentTools, u as utcDay } from './chat-queue.service-XG9RQCjU.js';
4
+ import * as _dudousxd_nestjs_agent_core from '@dudousxd/nestjs-agent-core';
5
+ import { AgentStore, Actor, ListActionProposals, ActionProposalMutationResult, AgentRunner, AttachmentStagingStore, ModelCatalog, QuotaProvider, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver, AgentApprovalPort, MessageAttachment, AgentAttachmentConfig, AgentClientConfig, ToolSpec, ToolPresentation, AgentHistoryWindow, AgentIntake, Persona, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, AgentRunStartOptions, TokenStreamSink, SinkWriter } from '@dudousxd/nestjs-agent-core';
5
6
  export * from '@dudousxd/nestjs-agent-core';
6
7
  import { Request, Response } from 'express';
8
+ import { UiCapabilities } from '@dudousxd/nestjs-agent-core/genui';
7
9
  import { StandardSchemaV1 } from '@standard-schema/spec';
8
10
  import { DiscoveryService, MetadataScanner } from '@nestjs/core';
11
+ import './genui/index.js';
9
12
 
10
13
  declare class AgentModule {
11
14
  static forRoot(options: AgentModuleOptions): DynamicModule;
12
15
  static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule;
13
16
  }
14
17
 
18
+ declare class ActionProposalService {
19
+ private readonly store;
20
+ private readonly options;
21
+ constructor(store: AgentStore, options: Pick<AgentModuleOptions, 'approvalPolicy'>);
22
+ private capability;
23
+ private scope;
24
+ private mayDecide;
25
+ listPage(threadId: string, actor: Actor, query?: Pick<ListActionProposals, 'after'>): Promise<{
26
+ next?: {
27
+ createdAt: number;
28
+ id: string;
29
+ };
30
+ items: _dudousxd_nestjs_agent_core.ActionProposal[];
31
+ }>;
32
+ list(threadId: string, actor: Actor): Promise<_dudousxd_nestjs_agent_core.ActionProposal[]>;
33
+ decide(threadId: string, proposalId: string, actor: Actor, command: {
34
+ decision: 'approved' | 'rejected';
35
+ remember?: boolean;
36
+ reason?: string;
37
+ via?: string;
38
+ }): Promise<ActionProposalMutationResult>;
39
+ handleTextDecision(threadId: string, actor: Actor, text: string): Promise<{
40
+ status: "unmatched";
41
+ } | {
42
+ threadId: string;
43
+ proposalDecision: ActionProposalMutationResult;
44
+ text: string;
45
+ } | {
46
+ threadId: string;
47
+ proposalDecision: {
48
+ status: "ambiguous";
49
+ proposalIds: string[];
50
+ };
51
+ text: string;
52
+ }>;
53
+ private textReceipt;
54
+ }
55
+
15
56
  /**
16
57
  * What a send does when its thread already has a turn running:
17
58
  * - `'auto'` (default) — run now when the thread is idle, else wait in the thread's queue.
@@ -39,12 +80,24 @@ type ChatSendResult = {
39
80
  runId: string;
40
81
  threadId: string;
41
82
  queued?: undefined;
42
- } | QueuedSend;
83
+ } | QueuedSend | {
84
+ threadId: string;
85
+ proposalDecision: unknown;
86
+ text: string;
87
+ queued?: undefined;
88
+ };
43
89
  interface ChatParams {
90
+ uiCapabilities?: UiCapabilities;
44
91
  actor: Actor;
45
92
  message: string;
46
93
  threadId?: string;
47
94
  agentName?: string;
95
+ /**
96
+ * Run this turn under one of the agent's personas (`@Agent({ personas })`), and pin it on the
97
+ * thread so later sends that name none keep it. Refused (400 `persona_not_found`) unless the agent
98
+ * declares it. Omitted → the thread's pinned persona, else the agent's `defaultPersona`, else none.
99
+ */
100
+ personaId?: string;
48
101
  /**
49
102
  * Files attached to this message (image/PDF) for a vision-capable model, named by the `mediaId`
50
103
  * the upload returned. Only the id is read: the url, content type and name are resolved from the
@@ -97,7 +150,22 @@ declare class AgentService {
97
150
  private readonly quotaProvider?;
98
151
  private readonly options?;
99
152
  private readonly queue?;
100
- constructor(runner: AgentRunner, store: AgentStore, deps: AgentDepsFactory, staging?: AttachmentStagingStore | undefined, models?: ModelCatalog | undefined, quotaProvider?: QuotaProvider | undefined, options?: Pick<AgentModuleOptions, "quota"> | undefined, queue?: ChatQueueService | undefined);
153
+ private readonly proposals?;
154
+ constructor(runner: AgentRunner, store: AgentStore, deps: AgentDepsFactory, staging?: AttachmentStagingStore | undefined, models?: ModelCatalog | undefined, quotaProvider?: QuotaProvider | undefined, options?: Pick<AgentModuleOptions, "quota" | "actionApprovalMode"> | undefined, queue?: ChatQueueService | undefined, proposals?: ActionProposalService | undefined);
155
+ handleTextDecision(threadId: string, actor: Actor, text: string): Promise<{
156
+ status: "unmatched";
157
+ } | {
158
+ threadId: string;
159
+ proposalDecision: _dudousxd_nestjs_agent_core.ActionProposalMutationResult;
160
+ text: string;
161
+ } | {
162
+ threadId: string;
163
+ proposalDecision: {
164
+ status: "ambiguous";
165
+ proposalIds: string[];
166
+ };
167
+ text: string;
168
+ }>;
101
169
  /** The queue service when the bound store can hold a queue, else `undefined`. */
102
170
  private queueing;
103
171
  /** The queue service, or a 501 naming what is missing. */
@@ -143,7 +211,9 @@ declare class AgentService {
143
211
  * Send a message: start a turn, or — when its thread already has one running — queue the message
144
212
  * to run after it (see {@link ChatSendMode}). What `POST <base>/chat` calls.
145
213
  */
146
- send(params: ChatParams): Promise<ChatSendResult>;
214
+ send(params: ChatParams, sendOptions?: {
215
+ textDecisions?: boolean;
216
+ }): Promise<ChatSendResult>;
147
217
  /**
148
218
  * Start a turn the thread is already claimed for, under the claimed id. A runner that minted an
149
219
  * id of its own anyway gets the thread re-pointed at it; one that fails to start frees the thread.
@@ -293,6 +363,13 @@ declare class AgentService {
293
363
  * dropping the field.
294
364
  */
295
365
  updateThread(actor: Actor, threadId: string, patch: UpdateThreadInput): Promise<void>;
366
+ /**
367
+ * The persona this send runs under — see {@link AgentDepsFactory.resolvePersona}. The thread's
368
+ * pinned persona is read only when the send names none AND the agent has personas to pick from.
369
+ */
370
+ private resolvePersona;
371
+ /** Pin `persona` on the thread when it is not already — a no-op on a store that cannot. */
372
+ private pinThreadPersona;
296
373
  private validateTitle;
297
374
  /**
298
375
  * Agent-selection precedence for a `chat()` call with no explicit `agentName`: the thread's own
@@ -479,7 +556,24 @@ declare function agUiAdapter(options?: AgUiAdapterOptions): AgentProtocolAdapter
479
556
  */
480
557
  declare class AgentApprovalPortAdapter implements AgentApprovalPort {
481
558
  private readonly agent;
482
- constructor(agent: AgentService);
559
+ private readonly proposals?;
560
+ constructor(agent: AgentService, proposals?: ActionProposalService | undefined);
561
+ approveActionProposal(actor: Actor, target: {
562
+ kind: 'proposal';
563
+ threadId: string;
564
+ proposalId: string;
565
+ }, opts?: {
566
+ remember?: boolean;
567
+ decidedVia?: string;
568
+ }): Promise<_dudousxd_nestjs_agent_core.ActionProposalMutationResult>;
569
+ rejectActionProposal(actor: Actor, target: {
570
+ kind: 'proposal';
571
+ threadId: string;
572
+ proposalId: string;
573
+ }, opts?: {
574
+ reason?: string;
575
+ decidedVia?: string;
576
+ }): Promise<_dudousxd_nestjs_agent_core.ActionProposalMutationResult>;
483
577
  approve(toolCallId: string, opts?: {
484
578
  executedByRef?: string;
485
579
  remember?: boolean;
@@ -492,6 +586,19 @@ declare class AgentApprovalPortAdapter implements AgentApprovalPort {
492
586
  }): Promise<void>;
493
587
  }
494
588
 
589
+ /**
590
+ * A store that can answer a thread's pinned persona on its own, without materializing the thread —
591
+ * probed structurally, like `ThreadDefaultAgentReader`.
592
+ */
593
+ interface ThreadPersonaReader {
594
+ personaForThread(threadId: string): Promise<string | null>;
595
+ }
596
+ /**
597
+ * The thread's pinned persona: one column when the store projects it ({@link ThreadPersonaReader}),
598
+ * else through the full read.
599
+ */
600
+ declare function threadPersona(store: AgentStore, threadId: string): Promise<string | null>;
601
+
495
602
  /**
496
603
  * How many entries `GET /agent/attachments` returns. Fixed rather than caller-supplied: this route
497
604
  * exists so a composer can show the files someone has uploaded, and a host that needs real paging
@@ -555,6 +662,7 @@ declare class ConfigController {
555
662
 
556
663
  declare const AI_TOOL_METADATA: unique symbol;
557
664
  interface AiToolOptions {
665
+ replacementKey?: ToolSpec['replacementKey'];
558
666
  /**
559
667
  * What the model calls it. Omit → the class name, camelCased, with a trailing `Tool` dropped
560
668
  * (`GetWeatherTool` → `getWeather`).
@@ -744,6 +852,20 @@ interface AgentOptions {
744
852
  * module-wide setting.
745
853
  */
746
854
  ask?: boolean;
855
+ /**
856
+ * Named variants of THIS agent — a prompt and, optionally, a narrower tool allow-list — that a
857
+ * caller picks per send (`POST <base>/chat { persona }`) and that pin onto the thread. Everything
858
+ * else (model, access rules, handoffs, history) stays this agent's; a variant that needs those to
859
+ * differ is another `@Agent`.
860
+ *
861
+ * A persona's `systemPrompt` is static data. For a prompt built from injected services, leave it
862
+ * out and branch on `ctx.persona` in this class's `@SystemPrompt()` method instead.
863
+ *
864
+ * Omit → no personas, and nothing about a turn changes.
865
+ */
866
+ personas?: Persona[];
867
+ /** The persona a send runs under when neither it nor its thread names one. Omit → none. */
868
+ defaultPersona?: string;
747
869
  }
748
870
  declare const AGENT_METADATA: unique symbol;
749
871
  /** Marks a provider class as an agent. See {@link AgentOptions}. */
@@ -849,6 +971,12 @@ declare class AgentDiscoveryService implements OnModuleInit {
849
971
  onModuleInit(): void;
850
972
  /** Build the internal {@link AgentDefinition} from an `@Agent` instance and its options. */
851
973
  private definitionFrom;
974
+ /**
975
+ * Refuse to boot on a persona declaration that could only fail later, per request: a default that
976
+ * names no persona, an id declared twice, an alias two personas claim, or an alias that is a real
977
+ * agent's name (which would never be reached — a registered agent always wins).
978
+ */
979
+ private assertPersonas;
852
980
  /**
853
981
  * Resolve each handoff entry to an {@link AgentDelegation} — its target's registered name, plus
854
982
  * whether that edge detaches (skipping non-agent classes). A bare name is kept for a plain edge
@@ -1288,4 +1416,24 @@ declare class RunNotActiveException extends ConflictException {
1288
1416
  constructor(runId: string);
1289
1417
  }
1290
1418
 
1291
- export { AGENT_CHAT_QUEUE, AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, type AgUiAdapterOptions, AgUiRunHandler, Agent, AgentApprovalPortAdapter, AgentDepsFactory, AgentDiscoveryService, AgentModule, AgentModuleAsyncOptions, AgentModuleOptions, type AgentOptions, AgentProtocolAdapter, AgentService, AgentSkillsOptions, AiTool, AiToolDiscoveryService, type AiToolOptions, type AnonymousActorOptions, AnonymousActorResolver, type AttachmentLimits, AttachmentsController, type ChatParams, ChatQueueService, type ChatSendMode, type ChatSendResult, ConfigController, DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES, DEFAULT_MAX_ATTACHMENT_BYTES, type DeclaredSkill, HeaderActorResolver, InProcessTokenStreamSink, InlineAgentRunner, MAX_ATTACHMENTS_PER_MESSAGE, MemoriesController, MessagesController, ModelsController, QueueController, type QueuedSend, type RequestUserMapper, type ResolvedAiToolOptions, RunNotActiveException, SKILL_METADATA, SYSTEM_PROMPT_CONTRIBUTOR_METADATA, SYSTEM_PROMPT_METADATA, Skill, type SkillBody, SkillDiscoveryService, type SkillOptions, SkillsController, SystemPrompt, SystemPromptContributor, type ThreadDefaultAgentReader, type ThreadModelReader, ToolsController, agUiAdapter, attachmentLimits, declaredSkillProvider, defaultRequestUserMapper, readAgentMetadata, readAiToolMetadata, readSkillMetadata, requestUserActorResolver, resolveSkillsConfig, skillScope, toolNameFromClass };
1419
+ declare class ActionProposalController {
1420
+ private readonly proposals;
1421
+ private readonly actors;
1422
+ constructor(proposals: ActionProposalService, actors: ActorResolver);
1423
+ list(threadId: string, request: Request, cursor: unknown, response: Response): Promise<_dudousxd_nestjs_agent_core.ActionProposal[]>;
1424
+ approve(threadId: string, proposalId: string, request: Request, body: unknown): Promise<_dudousxd_nestjs_agent_core.ActionProposalMutationResult>;
1425
+ reject(threadId: string, proposalId: string, request: Request, body: unknown): Promise<_dudousxd_nestjs_agent_core.ActionProposalMutationResult>;
1426
+ }
1427
+
1428
+ declare class ActionProposalWorkerService implements OnModuleInit, OnModuleDestroy {
1429
+ private readonly store;
1430
+ private readonly options;
1431
+ private readonly deps;
1432
+ private worker;
1433
+ private readonly logger;
1434
+ constructor(store: AgentStore, options: AgentModuleOptions, deps: AgentDepsFactory);
1435
+ onModuleInit(): void;
1436
+ onModuleDestroy(): Promise<void>;
1437
+ }
1438
+
1439
+ export { AGENT_CHAT_QUEUE, AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, ActionProposalController, ActionProposalService, ActionProposalWorkerService, type AgUiAdapterOptions, AgUiRunHandler, Agent, AgentApprovalPortAdapter, AgentDepsFactory, AgentDiscoveryService, AgentModule, AgentModuleAsyncOptions, AgentModuleOptions, type AgentOptions, AgentProtocolAdapter, AgentService, AgentSkillsOptions, AiTool, AiToolDiscoveryService, type AiToolOptions, type AnonymousActorOptions, AnonymousActorResolver, type AttachmentLimits, AttachmentsController, type ChatParams, ChatQueueService, type ChatSendMode, type ChatSendResult, ConfigController, DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES, DEFAULT_MAX_ATTACHMENT_BYTES, type DeclaredSkill, HeaderActorResolver, InProcessTokenStreamSink, InlineAgentRunner, MAX_ATTACHMENTS_PER_MESSAGE, MemoriesController, MessagesController, ModelsController, QueueController, type QueuedSend, type RequestUserMapper, type ResolvedAiToolOptions, RunNotActiveException, SKILL_METADATA, SYSTEM_PROMPT_CONTRIBUTOR_METADATA, SYSTEM_PROMPT_METADATA, Skill, type SkillBody, SkillDiscoveryService, type SkillOptions, SkillsController, SystemPrompt, SystemPromptContributor, type ThreadDefaultAgentReader, type ThreadModelReader, type ThreadPersonaReader, ToolsController, agUiAdapter, attachmentLimits, declaredSkillProvider, defaultRequestUserMapper, readAgentMetadata, readAiToolMetadata, readSkillMetadata, requestUserActorResolver, resolveSkillsConfig, skillScope, threadPersona, toolNameFromClass };