@dudousxd/nestjs-agent 1.24.2 → 1.25.1

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
@@ -2,7 +2,7 @@ import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit, ConflictExce
2
2
  import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter, e as AgentSkillsOptions } from './chat-queue.service-Crf9uwum.cjs';
3
3
  export { f as AGENT_TOOL_BRAND, g as AgentAttachmentsOptions, h as AgentDeps, i as AgentEngine, j as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QueuePlan, k as QueueSettleOutcome, l as QueuedTurn, m as QueuedTurnStarter, n as QuotaLimits, o as QuotaWindowLimits, p as defineTool, q as delegateToolName, r as provideAgentTool, s as provideAgentTools, u as utcDay } from './chat-queue.service-Crf9uwum.cjs';
4
4
  import * as _dudousxd_nestjs_agent_core from '@dudousxd/nestjs-agent-core';
5
- import { AgentAttachmentConfig, AttachmentStagingStore, AgentStore, Actor, ListActionProposals, ActionProposalMutationView, TextActionProposalVocabulary, AgentRunner, ModelCatalog, QuotaProvider, ActionApprovalMode, ActionProposalView, MessageAttachment, QuotaReport, ModelCatalogView, AgentHostContext, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver, AgentApprovalPort, AgentClientConfig, ToolSpec, ToolPresentation, AgentHistoryWindow, AgentIntake, Persona, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, AgentRunStartOptions, TokenStreamSink, SinkWriter, ActionProposal } from '@dudousxd/nestjs-agent-core';
5
+ import { AgentAttachmentConfig, AttachmentStagingStore, AgentStore, Actor, ListActionProposals, ActionProposalView, ActionProposalMutationView, TextActionProposalVocabulary, AgentRunner, ModelCatalog, QuotaProvider, ActionApprovalMode, MessageAttachment, QuotaReport, ModelCatalogView, AgentHostContext, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver, AgentApprovalPort, AgentClientConfig, ToolSpec, ToolPresentation, AgentHistoryWindow, AgentIntake, Persona, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, AgentRunStartOptions, TokenStreamSink, SinkWriter, ActionProposal } from '@dudousxd/nestjs-agent-core';
6
6
  export * from '@dudousxd/nestjs-agent-core';
7
7
  export { FunctionalToolDefinition } from '@dudousxd/nestjs-agent-core';
8
8
  import { Request, Response } from 'express';
@@ -37,17 +37,21 @@ declare class ActionProposalService {
37
37
  /** The words a text decision is made of, and what the agent answers — English unless configured. */
38
38
  private readonly vocabulary;
39
39
  private readonly replies;
40
+ private hasCapability;
40
41
  private capability;
41
42
  private scope;
42
43
  private mayDecide;
44
+ /**
45
+ * One page of a thread's proposals this actor may see. A store without the proposal capability
46
+ * can only run blocking approvals, so a thread there has no proposals: an empty, final page rather
47
+ * than `501` — a client that lists by default (React's `useAgentChat`) needs no flag. Deciding one
48
+ * still answers `501`.
49
+ */
43
50
  listPage(threadId: string, actor: Actor, query?: Pick<ListActionProposals, 'after'>): Promise<{
44
- next?: {
45
- createdAt: number;
46
- id: string;
47
- };
48
- items: _dudousxd_nestjs_agent_core.ActionProposalView[];
51
+ items: ActionProposalView[];
52
+ next?: NonNullable<ListActionProposals['after']>;
49
53
  }>;
50
- list(threadId: string, actor: Actor): Promise<_dudousxd_nestjs_agent_core.ActionProposalView[]>;
54
+ list(threadId: string, actor: Actor): Promise<ActionProposalView[]>;
51
55
  decide(threadId: string, proposalId: string, actor: Actor, command: {
52
56
  decision: 'approved' | 'rejected';
53
57
  remember?: boolean;
@@ -108,6 +112,8 @@ type ChatSendResult = {
108
112
  text: string;
109
113
  queued?: undefined;
110
114
  };
115
+ /** The code of the `400` a send with nothing to answer gets (also AG-UI's, for the same case). */
116
+ declare const NO_USER_MESSAGE_CODE = "no_user_message";
111
117
  interface ChatParams {
112
118
  uiCapabilities?: UiCapabilities;
113
119
  actor: Actor;
@@ -221,8 +227,9 @@ declare class AgentService {
221
227
  actionProposalReply(result: Pick<ActionProposalMutationView, 'status' | 'proposal'>, decision: 'approved' | 'rejected'): string;
222
228
  /**
223
229
  * The proposals of a thread this actor may see — the thread's own actor, or one the policy lets
224
- * decide them; what `GET <base>/threads/:threadId/action-proposals` serves (its first page). `404`
225
- * when independent approvals are not on.
230
+ * decide them; what `GET <base>/threads/:threadId/action-proposals` serves (its first page).
231
+ * Without independent approvals (the default blocking mode) there are none, so the read answers an
232
+ * empty list rather than refusing; deciding one still refuses.
226
233
  */
227
234
  listActionProposals(actor: Actor, threadId: string): Promise<ActionProposalView[]>;
228
235
  /**
@@ -286,7 +293,7 @@ declare class AgentService {
286
293
  * Send a message: start a turn, or — when its thread already has one running — queue the message
287
294
  * to run after it (see {@link ChatSendMode}). What `POST <base>/chat` calls.
288
295
  */
289
- send(params: ChatParams, sendOptions?: {
296
+ send(claimed: ChatParams, sendOptions?: {
290
297
  textDecisions?: boolean;
291
298
  }): Promise<ChatSendResult>;
292
299
  /**
@@ -1248,6 +1255,11 @@ declare class InlineAgentRunner implements AgentRunner {
1248
1255
  * running it. A cancelled id is dropped once the run settles, so the set tracks live runs only.
1249
1256
  */
1250
1257
  private readonly cancelled;
1258
+ /**
1259
+ * Aborted by {@link cancel}: what cuts short the model call or tool a stopped run is in (the
1260
+ * loop's `abortSignal` hook). Keyed like {@link cancelled}, and dropped with it.
1261
+ */
1262
+ private readonly aborts;
1251
1263
  /** Top-level runs this process is running now — what {@link isRunActive} answers from. */
1252
1264
  private readonly live;
1253
1265
  constructor(factory: AgentDepsFactory, store: AgentStore, queue?: ChatQueueService | undefined);
@@ -1264,8 +1276,10 @@ declare class InlineAgentRunner implements AgentRunner {
1264
1276
  * Ask a run to stop, and settle whatever it was parked on.
1265
1277
  *
1266
1278
  * The loop observes the request at its next safe point (between steps, before the turn's tools) and
1267
- * unwinds from there — so a tool already executing is left to finish, and its result is recorded
1268
- * exactly as it would have been. What this cannot wait for is a turn parked on a human: that wait
1279
+ * unwinds from there. What the run is in right now is aborted (its `abortSignal`): the model call
1280
+ * streaming the answer ends at once and the step it was writing is not persisted, and a tool that
1281
+ * passes `ctx.abortSignal` on is cut short and recorded failed; a tool that ignores the signal is
1282
+ * left to finish, and its result is recorded exactly as it would have been. What this cannot wait for is a turn parked on a human: that wait
1269
1283
  * is a promise nobody is going to resolve, so it is REJECTED here with the same
1270
1284
  * {@link RunCancelledError} the loop would have thrown, and the run unwinds through the identical
1271
1285
  * path.
@@ -1275,6 +1289,10 @@ declare class InlineAgentRunner implements AgentRunner {
1275
1289
  * each and can never both write.
1276
1290
  */
1277
1291
  cancel(runId: string): Promise<void>;
1292
+ /** The signal {@link cancel} aborts for `runId` — one per run, shared by its awaited delegates. */
1293
+ private abortSignalFor;
1294
+ /** Drop a settled run's Stop: its flag and its abort controller. */
1295
+ private forgetCancel;
1278
1296
  /**
1279
1297
  * The single place a cancelled run's state is settled: recorded as its own terminal (never
1280
1298
  * `failed` — a user pressing Stop must not land in someone's error rate), the thread released, and
@@ -1520,4 +1538,4 @@ declare class ActionProposalWorkerService implements OnModuleInit, OnModuleDestr
1520
1538
  onModuleDestroy(): Promise<void>;
1521
1539
  }
1522
1540
 
1523
- export { AGENT_CHAT_QUEUE, AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, ActionProposalController, ActionProposalService, type ActionProposalSettledListener, 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 };
1541
+ export { AGENT_CHAT_QUEUE, AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, ActionProposalController, ActionProposalService, type ActionProposalSettledListener, 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, NO_USER_MESSAGE_CODE, 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
@@ -2,7 +2,7 @@ import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit, ConflictExce
2
2
  import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentProtocolAdapter, e as AgentSkillsOptions } from './chat-queue.service-ZQkqb1Yw.js';
3
3
  export { f as AGENT_TOOL_BRAND, g as AgentAttachmentsOptions, h as AgentDeps, i as AgentEngine, j as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QueuePlan, k as QueueSettleOutcome, l as QueuedTurn, m as QueuedTurnStarter, n as QuotaLimits, o as QuotaWindowLimits, p as defineTool, q as delegateToolName, r as provideAgentTool, s as provideAgentTools, u as utcDay } from './chat-queue.service-ZQkqb1Yw.js';
4
4
  import * as _dudousxd_nestjs_agent_core from '@dudousxd/nestjs-agent-core';
5
- import { AgentAttachmentConfig, AttachmentStagingStore, AgentStore, Actor, ListActionProposals, ActionProposalMutationView, TextActionProposalVocabulary, AgentRunner, ModelCatalog, QuotaProvider, ActionApprovalMode, ActionProposalView, MessageAttachment, QuotaReport, ModelCatalogView, AgentHostContext, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver, AgentApprovalPort, AgentClientConfig, ToolSpec, ToolPresentation, AgentHistoryWindow, AgentIntake, Persona, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, AgentRunStartOptions, TokenStreamSink, SinkWriter, ActionProposal } from '@dudousxd/nestjs-agent-core';
5
+ import { AgentAttachmentConfig, AttachmentStagingStore, AgentStore, Actor, ListActionProposals, ActionProposalView, ActionProposalMutationView, TextActionProposalVocabulary, AgentRunner, ModelCatalog, QuotaProvider, ActionApprovalMode, MessageAttachment, QuotaReport, ModelCatalogView, AgentHostContext, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, ActorResolver, AgentApprovalPort, AgentClientConfig, ToolSpec, ToolPresentation, AgentHistoryWindow, AgentIntake, Persona, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, AgentRunStartOptions, TokenStreamSink, SinkWriter, ActionProposal } from '@dudousxd/nestjs-agent-core';
6
6
  export * from '@dudousxd/nestjs-agent-core';
7
7
  export { FunctionalToolDefinition } from '@dudousxd/nestjs-agent-core';
8
8
  import { Request, Response } from 'express';
@@ -37,17 +37,21 @@ declare class ActionProposalService {
37
37
  /** The words a text decision is made of, and what the agent answers — English unless configured. */
38
38
  private readonly vocabulary;
39
39
  private readonly replies;
40
+ private hasCapability;
40
41
  private capability;
41
42
  private scope;
42
43
  private mayDecide;
44
+ /**
45
+ * One page of a thread's proposals this actor may see. A store without the proposal capability
46
+ * can only run blocking approvals, so a thread there has no proposals: an empty, final page rather
47
+ * than `501` — a client that lists by default (React's `useAgentChat`) needs no flag. Deciding one
48
+ * still answers `501`.
49
+ */
43
50
  listPage(threadId: string, actor: Actor, query?: Pick<ListActionProposals, 'after'>): Promise<{
44
- next?: {
45
- createdAt: number;
46
- id: string;
47
- };
48
- items: _dudousxd_nestjs_agent_core.ActionProposalView[];
51
+ items: ActionProposalView[];
52
+ next?: NonNullable<ListActionProposals['after']>;
49
53
  }>;
50
- list(threadId: string, actor: Actor): Promise<_dudousxd_nestjs_agent_core.ActionProposalView[]>;
54
+ list(threadId: string, actor: Actor): Promise<ActionProposalView[]>;
51
55
  decide(threadId: string, proposalId: string, actor: Actor, command: {
52
56
  decision: 'approved' | 'rejected';
53
57
  remember?: boolean;
@@ -108,6 +112,8 @@ type ChatSendResult = {
108
112
  text: string;
109
113
  queued?: undefined;
110
114
  };
115
+ /** The code of the `400` a send with nothing to answer gets (also AG-UI's, for the same case). */
116
+ declare const NO_USER_MESSAGE_CODE = "no_user_message";
111
117
  interface ChatParams {
112
118
  uiCapabilities?: UiCapabilities;
113
119
  actor: Actor;
@@ -221,8 +227,9 @@ declare class AgentService {
221
227
  actionProposalReply(result: Pick<ActionProposalMutationView, 'status' | 'proposal'>, decision: 'approved' | 'rejected'): string;
222
228
  /**
223
229
  * The proposals of a thread this actor may see — the thread's own actor, or one the policy lets
224
- * decide them; what `GET <base>/threads/:threadId/action-proposals` serves (its first page). `404`
225
- * when independent approvals are not on.
230
+ * decide them; what `GET <base>/threads/:threadId/action-proposals` serves (its first page).
231
+ * Without independent approvals (the default blocking mode) there are none, so the read answers an
232
+ * empty list rather than refusing; deciding one still refuses.
226
233
  */
227
234
  listActionProposals(actor: Actor, threadId: string): Promise<ActionProposalView[]>;
228
235
  /**
@@ -286,7 +293,7 @@ declare class AgentService {
286
293
  * Send a message: start a turn, or — when its thread already has one running — queue the message
287
294
  * to run after it (see {@link ChatSendMode}). What `POST <base>/chat` calls.
288
295
  */
289
- send(params: ChatParams, sendOptions?: {
296
+ send(claimed: ChatParams, sendOptions?: {
290
297
  textDecisions?: boolean;
291
298
  }): Promise<ChatSendResult>;
292
299
  /**
@@ -1248,6 +1255,11 @@ declare class InlineAgentRunner implements AgentRunner {
1248
1255
  * running it. A cancelled id is dropped once the run settles, so the set tracks live runs only.
1249
1256
  */
1250
1257
  private readonly cancelled;
1258
+ /**
1259
+ * Aborted by {@link cancel}: what cuts short the model call or tool a stopped run is in (the
1260
+ * loop's `abortSignal` hook). Keyed like {@link cancelled}, and dropped with it.
1261
+ */
1262
+ private readonly aborts;
1251
1263
  /** Top-level runs this process is running now — what {@link isRunActive} answers from. */
1252
1264
  private readonly live;
1253
1265
  constructor(factory: AgentDepsFactory, store: AgentStore, queue?: ChatQueueService | undefined);
@@ -1264,8 +1276,10 @@ declare class InlineAgentRunner implements AgentRunner {
1264
1276
  * Ask a run to stop, and settle whatever it was parked on.
1265
1277
  *
1266
1278
  * The loop observes the request at its next safe point (between steps, before the turn's tools) and
1267
- * unwinds from there — so a tool already executing is left to finish, and its result is recorded
1268
- * exactly as it would have been. What this cannot wait for is a turn parked on a human: that wait
1279
+ * unwinds from there. What the run is in right now is aborted (its `abortSignal`): the model call
1280
+ * streaming the answer ends at once and the step it was writing is not persisted, and a tool that
1281
+ * passes `ctx.abortSignal` on is cut short and recorded failed; a tool that ignores the signal is
1282
+ * left to finish, and its result is recorded exactly as it would have been. What this cannot wait for is a turn parked on a human: that wait
1269
1283
  * is a promise nobody is going to resolve, so it is REJECTED here with the same
1270
1284
  * {@link RunCancelledError} the loop would have thrown, and the run unwinds through the identical
1271
1285
  * path.
@@ -1275,6 +1289,10 @@ declare class InlineAgentRunner implements AgentRunner {
1275
1289
  * each and can never both write.
1276
1290
  */
1277
1291
  cancel(runId: string): Promise<void>;
1292
+ /** The signal {@link cancel} aborts for `runId` — one per run, shared by its awaited delegates. */
1293
+ private abortSignalFor;
1294
+ /** Drop a settled run's Stop: its flag and its abort controller. */
1295
+ private forgetCancel;
1278
1296
  /**
1279
1297
  * The single place a cancelled run's state is settled: recorded as its own terminal (never
1280
1298
  * `failed` — a user pressing Stop must not land in someone's error rate), the thread released, and
@@ -1520,4 +1538,4 @@ declare class ActionProposalWorkerService implements OnModuleInit, OnModuleDestr
1520
1538
  onModuleDestroy(): Promise<void>;
1521
1539
  }
1522
1540
 
1523
- export { AGENT_CHAT_QUEUE, AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, ActionProposalController, ActionProposalService, type ActionProposalSettledListener, 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 };
1541
+ export { AGENT_CHAT_QUEUE, AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, ActionProposalController, ActionProposalService, type ActionProposalSettledListener, 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, NO_USER_MESSAGE_CODE, 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.js CHANGED
@@ -666,9 +666,13 @@ var ActionProposalService = class {
666
666
  /** The words a text decision is made of, and what the agent answers — English unless configured. */
667
667
  vocabulary;
668
668
  replies;
669
+ hasCapability() {
670
+ const store = this.store;
671
+ return typeof store.getThreadActionProposalScope === "function" && typeof store.listActionProposals === "function";
672
+ }
669
673
  capability() {
670
674
  const store = this.store;
671
- if (typeof store.getThreadActionProposalScope !== "function" || typeof store.listActionProposals !== "function") throw new NotImplementedException("Action proposals are unavailable");
675
+ if (!this.hasCapability()) throw new NotImplementedException("Action proposals are unavailable");
672
676
  return store;
673
677
  }
674
678
  async scope(threadId, actor) {
@@ -684,7 +688,16 @@ var ActionProposalService = class {
684
688
  requesterRef: proposal.actorRef
685
689
  });
686
690
  }
691
+ /**
692
+ * One page of a thread's proposals this actor may see. A store without the proposal capability
693
+ * can only run blocking approvals, so a thread there has no proposals: an empty, final page rather
694
+ * than `501` — a client that lists by default (React's `useAgentChat`) needs no flag. Deciding one
695
+ * still answers `501`.
696
+ */
687
697
  async listPage(threadId, actor, query = {}) {
698
+ if (!this.hasCapability()) return {
699
+ items: []
700
+ };
688
701
  const scope = await this.scope(threadId, actor);
689
702
  const rows = await this.capability().listActionProposals(scope, {
690
703
  limit: 1e3,
@@ -1356,6 +1369,30 @@ function _ts_param4(paramIndex, decorator) {
1356
1369
  };
1357
1370
  }
1358
1371
  __name(_ts_param4, "_ts_param");
1372
+ var NO_USER_MESSAGE_CODE = "no_user_message";
1373
+ function sendableParams(params) {
1374
+ const message = params.message;
1375
+ if (message !== void 0 && message !== null && typeof message !== "string") {
1376
+ throw new BadRequestException2({
1377
+ statusCode: 400,
1378
+ code: "invalid_message",
1379
+ message: "message must be a string"
1380
+ });
1381
+ }
1382
+ const text = typeof message === "string" ? message : "";
1383
+ if (text.trim().length === 0 && (params.attachments?.length ?? 0) === 0 && params.regenerate !== true) {
1384
+ throw new BadRequestException2({
1385
+ statusCode: 400,
1386
+ code: NO_USER_MESSAGE_CODE,
1387
+ message: "nothing to answer: send a non-empty message, an attachment, or regenerate"
1388
+ });
1389
+ }
1390
+ return text === message ? params : {
1391
+ ...params,
1392
+ message: text
1393
+ };
1394
+ }
1395
+ __name(sendableParams, "sendableParams");
1359
1396
  var AgentService = class {
1360
1397
  static {
1361
1398
  __name(this, "AgentService");
@@ -1418,12 +1455,13 @@ var AgentService = class {
1418
1455
  }
1419
1456
  /**
1420
1457
  * The proposals of a thread this actor may see — the thread's own actor, or one the policy lets
1421
- * decide them; what `GET <base>/threads/:threadId/action-proposals` serves (its first page). `404`
1422
- * when independent approvals are not on.
1458
+ * decide them; what `GET <base>/threads/:threadId/action-proposals` serves (its first page).
1459
+ * Without independent approvals (the default blocking mode) there are none, so the read answers an
1460
+ * empty list rather than refusing; deciding one still refuses.
1423
1461
  */
1424
1462
  async listActionProposals(actor, threadId) {
1425
1463
  if (this.options?.actionApprovalMode !== "independent" || !this.proposals) {
1426
- throw new NotFoundException2("Proposal not found");
1464
+ return [];
1427
1465
  }
1428
1466
  return this.proposals.list(threadId, actor);
1429
1467
  }
@@ -1623,7 +1661,8 @@ var AgentService = class {
1623
1661
  * Send a message: start a turn, or — when its thread already has one running — queue the message
1624
1662
  * to run after it (see {@link ChatSendMode}). What `POST <base>/chat` calls.
1625
1663
  */
1626
- async send(params, sendOptions = {}) {
1664
+ async send(claimed, sendOptions = {}) {
1665
+ const params = sendableParams(claimed);
1627
1666
  if (sendOptions.textDecisions !== false && this.options?.actionApprovalMode === "independent" && params.threadId !== void 0 && params.regenerate !== true && this.proposals) {
1628
1667
  const decision = await this.proposals.handleTextDecision(params.threadId, params.actor, params.message);
1629
1668
  if ("proposalDecision" in decision) return decision;
@@ -5417,6 +5456,11 @@ var InlineAgentRunner = class _InlineAgentRunner {
5417
5456
  * running it. A cancelled id is dropped once the run settles, so the set tracks live runs only.
5418
5457
  */
5419
5458
  cancelled = /* @__PURE__ */ new Set();
5459
+ /**
5460
+ * Aborted by {@link cancel}: what cuts short the model call or tool a stopped run is in (the
5461
+ * loop's `abortSignal` hook). Keyed like {@link cancelled}, and dropped with it.
5462
+ */
5463
+ aborts = /* @__PURE__ */ new Map();
5420
5464
  /** Top-level runs this process is running now — what {@link isRunActive} answers from. */
5421
5465
  live = /* @__PURE__ */ new Set();
5422
5466
  constructor(factory, store, queue) {
@@ -5486,7 +5530,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
5486
5530
  await releaseThreadRun(this.store, input.threadId, runId);
5487
5531
  await writer.fail(streamFailure2(error));
5488
5532
  }).finally(() => {
5489
- this.cancelled.delete(runId);
5533
+ this.forgetCancel(runId);
5490
5534
  this.live.delete(runId);
5491
5535
  });
5492
5536
  return {
@@ -5505,8 +5549,10 @@ var InlineAgentRunner = class _InlineAgentRunner {
5505
5549
  * Ask a run to stop, and settle whatever it was parked on.
5506
5550
  *
5507
5551
  * The loop observes the request at its next safe point (between steps, before the turn's tools) and
5508
- * unwinds from there — so a tool already executing is left to finish, and its result is recorded
5509
- * exactly as it would have been. What this cannot wait for is a turn parked on a human: that wait
5552
+ * unwinds from there. What the run is in right now is aborted (its `abortSignal`): the model call
5553
+ * streaming the answer ends at once and the step it was writing is not persisted, and a tool that
5554
+ * passes `ctx.abortSignal` on is cut short and recorded failed; a tool that ignores the signal is
5555
+ * left to finish, and its result is recorded exactly as it would have been. What this cannot wait for is a turn parked on a human: that wait
5510
5556
  * is a promise nobody is going to resolve, so it is REJECTED here with the same
5511
5557
  * {@link RunCancelledError} the loop would have thrown, and the run unwinds through the identical
5512
5558
  * path.
@@ -5517,6 +5563,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
5517
5563
  */
5518
5564
  async cancel(runId) {
5519
5565
  this.cancelled.add(runId);
5566
+ this.aborts.get(runId)?.abort(new RunCancelledError());
5520
5567
  for (const [key, waiter] of this.pending) {
5521
5568
  if (key.startsWith(`${runId}:`)) {
5522
5569
  this.pending.delete(key);
@@ -5525,6 +5572,20 @@ var InlineAgentRunner = class _InlineAgentRunner {
5525
5572
  }
5526
5573
  await Promise.resolve();
5527
5574
  }
5575
+ /** The signal {@link cancel} aborts for `runId` — one per run, shared by its awaited delegates. */
5576
+ abortSignalFor(runId) {
5577
+ let controller = this.aborts.get(runId);
5578
+ if (controller === void 0) {
5579
+ controller = new AbortController();
5580
+ this.aborts.set(runId, controller);
5581
+ }
5582
+ return controller.signal;
5583
+ }
5584
+ /** Drop a settled run's Stop: its flag and its abort controller. */
5585
+ forgetCancel(runId) {
5586
+ this.cancelled.delete(runId);
5587
+ this.aborts.delete(runId);
5588
+ }
5528
5589
  /**
5529
5590
  * The single place a cancelled run's state is settled: recorded as its own terminal (never
5530
5591
  * `failed` — a user pressing Stop must not land in someone's error rate), the thread released, and
@@ -5644,6 +5705,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
5644
5705
  step: /* @__PURE__ */ __name((_name, fn) => fn(), "step"),
5645
5706
  parallel: settleAll,
5646
5707
  cancelled: /* @__PURE__ */ __name(async () => this.cancelled.has(runId), "cancelled"),
5708
+ abortSignal: this.abortSignalFor(runId),
5647
5709
  runAgent: /* @__PURE__ */ __name((agentName, task) => this.runNested({
5648
5710
  agentName,
5649
5711
  task,
@@ -5695,6 +5757,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
5695
5757
  step: /* @__PURE__ */ __name((_name, fn) => fn(), "step"),
5696
5758
  parallel: settleAll,
5697
5759
  cancelled: /* @__PURE__ */ __name(async () => this.cancelled.has(runId), "cancelled"),
5760
+ abortSignal: this.abortSignalFor(runId),
5698
5761
  runAgent: /* @__PURE__ */ __name((childName, childTask) => this.runNested({
5699
5762
  agentName: childName,
5700
5763
  task: childTask,
@@ -5770,7 +5833,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
5770
5833
  }
5771
5834
  });
5772
5835
  }).finally(async () => {
5773
- this.cancelled.delete(runId);
5836
+ this.forgetCancel(runId);
5774
5837
  await this.store.setActiveStream(subThread.id, null);
5775
5838
  });
5776
5839
  return {
@@ -5802,6 +5865,8 @@ var InlineAgentRunner = class _InlineAgentRunner {
5802
5865
  // A child stops when it is cancelled OR when the run a human is actually watching is: the
5803
5866
  // canceller names the top-level run, which is the only id that ever left the server.
5804
5867
  cancelled: /* @__PURE__ */ __name(async () => this.cancelled.has(runId) || this.cancelled.has(sinkRunId), "cancelled"),
5868
+ // Aborted by a Stop on the run the human is watching, which is the id a canceller names.
5869
+ abortSignal: this.abortSignalFor(sinkRunId),
5805
5870
  runAgent: /* @__PURE__ */ __name((childName, childTask) => this.runNested({
5806
5871
  agentName: childName,
5807
5872
  task: childTask,
@@ -6452,7 +6517,7 @@ var AgUiRunHandler = class {
6452
6517
  }
6453
6518
  const turn = readUserTurn(input.messages);
6454
6519
  if (turn === null) {
6455
- throw invalid("no_user_message", "messages carries no user message to answer");
6520
+ throw invalid(NO_USER_MESSAGE_CODE, "messages carries no user message to answer");
6456
6521
  }
6457
6522
  warnings.push(...turn.dropped);
6458
6523
  const owner = await this.agent.threadOwner(input.threadId);
@@ -6478,8 +6543,8 @@ var AgUiRunHandler = class {
6478
6543
  }
6479
6544
  }
6480
6545
  const refs = await this.stage(actor, turn.media, warnings, turn.staged);
6481
- if (turn.text.trim().length === 0 && refs.length === 0) {
6482
- throw invalid("no_user_message", "the user message to answer is empty");
6546
+ if (turn.text.trim().length === 0 && refs.length === 0 && forwarded.regenerate !== true) {
6547
+ throw invalid(NO_USER_MESSAGE_CODE, "the user message to answer is empty");
6483
6548
  }
6484
6549
  const context = readContext(input.context);
6485
6550
  const pageContext = forwarded.pageContext !== void 0 || context !== void 0 ? {
@@ -6868,6 +6933,7 @@ export {
6868
6933
  MemoriesController,
6869
6934
  MessagesController,
6870
6935
  ModelsController,
6936
+ NO_USER_MESSAGE_CODE,
6871
6937
  QueueController,
6872
6938
  RunNotActiveException,
6873
6939
  SKILL_METADATA,