@dudousxd/nestjs-agent 1.14.0 → 1.16.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,7 +1,7 @@
1
1
  import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit } from '@nestjs/common';
2
- import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, d as AgentSkillsOptions } from './agent-deps.factory-DkWvoWbD.cjs';
3
- export { e as AGENT_TOOL_BRAND, f as AgentAttachmentsOptions, g as AgentDeps, h as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QuotaLimits, i as QuotaWindowLimits, j as delegateToolName, p as provideAgentTool, k as provideAgentTools, u as utcDay } from './agent-deps.factory-DkWvoWbD.cjs';
4
- import { AgentRunner, AgentStore, AttachmentStagingStore, ModelCatalog, QuotaProvider, Actor, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, AgentApprovalPort, ActorResolver, MessageAttachment, AgentAttachmentConfig, AgentClientConfig, ToolPresentation, AgentHistoryWindow, AgentIntake, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, TokenStreamSink, SinkWriter } from '@dudousxd/nestjs-agent-core';
2
+ import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentSkillsOptions } from './chat-queue.service-Bqq00NN1.cjs';
3
+ export { e as AGENT_TOOL_BRAND, f as AgentAttachmentsOptions, g as AgentDeps, h as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QueuePlan, i as QueueSettleOutcome, j as QueuedTurn, k as QueuedTurnStarter, l as QuotaLimits, m as QuotaWindowLimits, n as delegateToolName, p as provideAgentTool, o as provideAgentTools, u as utcDay } from './chat-queue.service-Bqq00NN1.cjs';
4
+ import { AgentRunner, AgentStore, AttachmentStagingStore, ModelCatalog, QuotaProvider, Actor, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, AgentApprovalPort, ActorResolver, 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';
5
5
  export * from '@dudousxd/nestjs-agent-core';
6
6
  import { Request } from 'express';
7
7
  import { StandardSchemaV1 } from '@standard-schema/spec';
@@ -12,6 +12,34 @@ declare class AgentModule {
12
12
  static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule;
13
13
  }
14
14
 
15
+ /**
16
+ * What a send does when its thread already has a turn running:
17
+ * - `'auto'` (default) — run now when the thread is idle, else wait in the thread's queue.
18
+ * - `'queue'` — always wait in the queue, behind whatever is already waiting (it still starts at
19
+ * once when nothing is running and nothing is ahead of it).
20
+ * - `'interrupt'` — cancel the running turn and run this one next, ahead of the queue.
21
+ */
22
+ type ChatSendMode = 'auto' | 'queue' | 'interrupt';
23
+ /** A send that is waiting in its thread's queue instead of running. */
24
+ interface QueuedSend {
25
+ threadId: string;
26
+ queued: true;
27
+ /** The queued message's id — also the run id it will start under. */
28
+ messageId: string;
29
+ /** 0-based place in the queue at the time it was queued (`0` → next). */
30
+ position: number;
31
+ queue: ChatQueueState;
32
+ /** The turn it started under, when it started straight away (an idle thread). */
33
+ runId?: string;
34
+ /** The run an interrupt cancelled to make room for it. */
35
+ interrupting?: string;
36
+ }
37
+ /** What {@link AgentService.send} did: started a turn, or queued the message. */
38
+ type ChatSendResult = {
39
+ runId: string;
40
+ threadId: string;
41
+ queued?: undefined;
42
+ } | QueuedSend;
15
43
  interface ChatParams {
16
44
  actor: Actor;
17
45
  message: string;
@@ -36,6 +64,8 @@ interface ChatParams {
36
64
  * the thread list until the caller promotes it. Ignored when `threadId` is set.
37
65
  */
38
66
  transient?: boolean;
67
+ /** What to do when the thread already has a turn running — see {@link ChatSendMode}. */
68
+ mode?: ChatSendMode;
39
69
  }
40
70
  /**
41
71
  * A store that can answer a thread's default agent on its own, without materializing the thread.
@@ -60,7 +90,12 @@ declare class AgentService {
60
90
  private readonly models?;
61
91
  private readonly quotaProvider?;
62
92
  private readonly options?;
63
- constructor(runner: AgentRunner, store: AgentStore, deps: AgentDepsFactory, staging?: AttachmentStagingStore | undefined, models?: ModelCatalog | undefined, quotaProvider?: QuotaProvider | undefined, options?: Pick<AgentModuleOptions, "quota"> | undefined);
93
+ private readonly queue?;
94
+ constructor(runner: AgentRunner, store: AgentStore, deps: AgentDepsFactory, staging?: AttachmentStagingStore | undefined, models?: ModelCatalog | undefined, quotaProvider?: QuotaProvider | undefined, options?: Pick<AgentModuleOptions, "quota"> | undefined, queue?: ChatQueueService | undefined);
95
+ /** The queue service when the bound store can hold a queue, else `undefined`. */
96
+ private queueing;
97
+ /** The queue service, or a 501 naming what is missing. */
98
+ private requireQueue;
64
99
  /**
65
100
  * The actor's budget across windows (`GET <base>/quota`) — the bound {@link QuotaProvider}'s
66
101
  * report. Without one (a service built outside the module), a day window from the ledger.
@@ -89,10 +124,66 @@ declare class AgentService {
89
124
  */
90
125
  private resolveModel;
91
126
  private threadModel;
127
+ /**
128
+ * Start a turn — for in-process callers that need a run id back. A send that would have to wait
129
+ * (its thread already has a turn running) is refused with `409` instead; {@link send} is the form
130
+ * that queues it.
131
+ */
92
132
  chat(params: ChatParams): Promise<{
93
133
  runId: string;
94
134
  threadId: string;
95
135
  }>;
136
+ /**
137
+ * Send a message: start a turn, or — when its thread already has one running — queue the message
138
+ * to run after it (see {@link ChatSendMode}). What `POST <base>/chat` calls.
139
+ */
140
+ send(params: ChatParams): Promise<ChatSendResult>;
141
+ /**
142
+ * Start a turn the thread is already claimed for, under the claimed id. A runner that minted an
143
+ * id of its own anyway gets the thread re-pointed at it; one that fails to start frees the thread.
144
+ */
145
+ private startClaimed;
146
+ /** Put a send in its thread's queue, then drain it if the thread turned out to be free. */
147
+ private enqueue;
148
+ /** `GET <base>/threads/:id/queue` — the thread's waiting messages and whether it drains. */
149
+ getQueue(actor: Actor, threadId: string): Promise<ChatQueueState>;
150
+ /**
151
+ * `PATCH <base>/queue/:messageId` — change a waiting message's text and/or attachments, and/or move
152
+ * it to `position` in the queue. Answers the thread's queue.
153
+ */
154
+ updateQueuedMessage(actor: Actor, messageId: string, patch: {
155
+ message?: string;
156
+ attachments?: AttachmentRef[] | null;
157
+ position?: number;
158
+ }): Promise<ChatQueueState>;
159
+ /** `DELETE <base>/queue/:messageId` — drop a waiting message. Answers the thread's queue. */
160
+ removeQueuedMessage(actor: Actor, messageId: string): Promise<ChatQueueState>;
161
+ /**
162
+ * `POST <base>/queue/:messageId/interrupt` — run a message that is already waiting NOW: it moves
163
+ * to the head of its queue marked as an interrupt, any pause is lifted, and the running turn is
164
+ * cancelled (its settle starts this message — the same path a `mode: 'interrupt'` send takes).
165
+ * With nothing running, the message starts at once.
166
+ *
167
+ * One request, and the message never leaves the queue: a client that removed it and sent it again
168
+ * would lose it if the second call failed, and would run it twice if another tab's drain started
169
+ * it in between. Answers the queue, plus `interrupting` (the run that was cancelled) or `runId`
170
+ * (the run this message started).
171
+ */
172
+ interruptQueuedMessage(actor: Actor, messageId: string): Promise<ChatQueueState & {
173
+ runId?: string;
174
+ interrupting?: string;
175
+ }>;
176
+ /** `DELETE <base>/threads/:id/queue` — drop every waiting message (and any pause). */
177
+ clearQueue(actor: Actor, threadId: string): Promise<ChatQueueState>;
178
+ /**
179
+ * `POST <base>/threads/:id/queue/resume` — lift a pause and start the head when nothing is
180
+ * running. Answers the queue, and the run the head started under, if it did.
181
+ */
182
+ resumeQueue(actor: Actor, threadId: string): Promise<ChatQueueState & {
183
+ runId?: string;
184
+ }>;
185
+ /** The thread a queued message waits on, once the caller is shown to own it. */
186
+ private assertOwnsQueuedMessage;
96
187
  /**
97
188
  * Rebuild this turn's attachments from the staging store, keyed by the ids the caller claimed.
98
189
  * The model provider fetches {@link MessageAttachment.url} verbatim, so that url is only ever
@@ -866,6 +957,7 @@ declare function resolveSkillsConfig(options: AgentSkillsOptions | undefined, de
866
957
  declare class InlineAgentRunner implements AgentRunner {
867
958
  private readonly factory;
868
959
  private readonly store;
960
+ private readonly queue?;
869
961
  private readonly logger;
870
962
  private readonly pending;
871
963
  /**
@@ -874,8 +966,15 @@ declare class InlineAgentRunner implements AgentRunner {
874
966
  * running it. A cancelled id is dropped once the run settles, so the set tracks live runs only.
875
967
  */
876
968
  private readonly cancelled;
877
- constructor(factory: AgentDepsFactory, store: AgentStore);
878
- start(input: AgentRunInput): Promise<{
969
+ /** Top-level runs this process is running now — what {@link isRunActive} answers from. */
970
+ private readonly live;
971
+ constructor(factory: AgentDepsFactory, store: AgentStore, queue?: ChatQueueService | undefined);
972
+ /**
973
+ * In-process, so exact: a run this process is not running is not running anywhere — the process
974
+ * that was running it is gone (a restart), and a thread it still holds is a stale claim.
975
+ */
976
+ isRunActive(runId: string): Promise<boolean>;
977
+ start(input: AgentRunInput, options?: AgentRunStartOptions): Promise<{
879
978
  runId: string;
880
979
  }>;
881
980
  signal(runId: string, toolCallId: string, reply: HumanReply): Promise<void>;
@@ -901,6 +1000,15 @@ declare class InlineAgentRunner implements AgentRunner {
901
1000
  * streams does not retry this one.
902
1001
  */
903
1002
  private settleCancelled;
1003
+ /**
1004
+ * Move the thread past a settling TOP-LEVEL run — to the next queued message, which starts here,
1005
+ * or to a paused/empty queue — and write the resulting `queue` frame into this run's stream. A
1006
+ * no-op without a queue-capable store, and for a run that is not a thread's own turn.
1007
+ *
1008
+ * Never throws: the run is settling either way, and a queue that could not be advanced is picked
1009
+ * up by the next send or resume on the thread.
1010
+ */
1011
+ private settleQueue;
904
1012
  /**
905
1013
  * Park a run on a human, keyed by run + tool call. One map for approvals and for question-set
906
1014
  * answers alike: both wait on the same key, and `signal` cannot tell (or need to tell) which
@@ -933,6 +1041,43 @@ declare class InlineAgentRunner implements AgentRunner {
933
1041
  private runNested;
934
1042
  }
935
1043
 
1044
+ interface UpdateQueuedMessageBody {
1045
+ /** The new text. */
1046
+ message?: unknown;
1047
+ /** `[{ mediaId }]` refs replacing the message's attachments; `null` or `[]` drops them. */
1048
+ attachments?: unknown;
1049
+ /** Move the message to this 0-based place in the queue. */
1050
+ position?: unknown;
1051
+ }
1052
+ /**
1053
+ * The thread message queue: messages sent while a turn was running, waiting to run after it. Every
1054
+ * route is ownership-gated like the thread routes, and answers the thread's queue as it now stands
1055
+ * (`{ items, paused }`). A change is also announced to whoever is streaming the thread, as a `queue`
1056
+ * frame in the running turn's stream.
1057
+ */
1058
+ declare class QueueController {
1059
+ private readonly agent;
1060
+ private readonly actorResolver;
1061
+ constructor(agent: AgentService, actorResolver: ActorResolver);
1062
+ list(req: Request, id: string): Promise<ChatQueueState>;
1063
+ clear(req: Request, id: string): Promise<ChatQueueState>;
1064
+ /** Lift a pause; the head starts when nothing is running. Carries `runId` when it started. */
1065
+ resume(req: Request, id: string): Promise<ChatQueueState & {
1066
+ runId?: string;
1067
+ }>;
1068
+ update(req: Request, messageId: string, body: UpdateQueuedMessageBody): Promise<ChatQueueState>;
1069
+ /**
1070
+ * Run a waiting message now: it moves to the head as an interrupt and the running turn is
1071
+ * cancelled for it. Carries `interrupting` (the cancelled run), or `runId` when nothing was
1072
+ * running and it started at once.
1073
+ */
1074
+ interrupt(req: Request, messageId: string): Promise<ChatQueueState & {
1075
+ runId?: string;
1076
+ interrupting?: string;
1077
+ }>;
1078
+ remove(req: Request, messageId: string): Promise<ChatQueueState>;
1079
+ }
1080
+
936
1081
  /**
937
1082
  * The default `TokenStreamSink`: buffers chunks per run in-process so a reconnecting subscriber
938
1083
  * replays everything so far, then follows live.
@@ -1040,4 +1185,4 @@ declare function defaultRequestUserMapper(user: Record<string, unknown>): Actor;
1040
1185
  */
1041
1186
  declare function requestUserActorResolver<TUser = Record<string, unknown>>(map?: RequestUserMapper<TUser>): ActorResolver;
1042
1187
 
1043
- export { AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, Agent, AgentApprovalPortAdapter, AgentDepsFactory, AgentDiscoveryService, AgentModule, AgentModuleAsyncOptions, AgentModuleOptions, type AgentOptions, AgentService, AgentSkillsOptions, AiTool, AiToolDiscoveryService, type AiToolOptions, type AnonymousActorOptions, AnonymousActorResolver, type AttachmentLimits, AttachmentsController, type ChatParams, ConfigController, DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES, DEFAULT_MAX_ATTACHMENT_BYTES, type DeclaredSkill, HeaderActorResolver, InProcessTokenStreamSink, InlineAgentRunner, MAX_ATTACHMENTS_PER_MESSAGE, MemoriesController, MessagesController, ModelsController, type RequestUserMapper, type ResolvedAiToolOptions, SKILL_METADATA, SYSTEM_PROMPT_CONTRIBUTOR_METADATA, SYSTEM_PROMPT_METADATA, Skill, type SkillBody, SkillDiscoveryService, type SkillOptions, SkillsController, SystemPrompt, SystemPromptContributor, type ThreadDefaultAgentReader, type ThreadModelReader, ToolsController, attachmentLimits, declaredSkillProvider, defaultRequestUserMapper, readAgentMetadata, readAiToolMetadata, readSkillMetadata, requestUserActorResolver, resolveSkillsConfig, skillScope, toolNameFromClass };
1188
+ export { AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, Agent, AgentApprovalPortAdapter, AgentDepsFactory, AgentDiscoveryService, AgentModule, AgentModuleAsyncOptions, AgentModuleOptions, type AgentOptions, 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, SKILL_METADATA, SYSTEM_PROMPT_CONTRIBUTOR_METADATA, SYSTEM_PROMPT_METADATA, Skill, type SkillBody, SkillDiscoveryService, type SkillOptions, SkillsController, SystemPrompt, SystemPromptContributor, type ThreadDefaultAgentReader, type ThreadModelReader, ToolsController, attachmentLimits, declaredSkillProvider, defaultRequestUserMapper, readAgentMetadata, readAiToolMetadata, readSkillMetadata, requestUserActorResolver, resolveSkillsConfig, skillScope, toolNameFromClass };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { DynamicModule, Type, OnApplicationBootstrap, OnModuleInit } from '@nestjs/common';
2
- import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, d as AgentSkillsOptions } from './agent-deps.factory-DkWvoWbD.js';
3
- export { e as AGENT_TOOL_BRAND, f as AgentAttachmentsOptions, g as AgentDeps, h as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QuotaLimits, i as QuotaWindowLimits, j as delegateToolName, p as provideAgentTool, k as provideAgentTools, u as utcDay } from './agent-deps.factory-DkWvoWbD.js';
4
- import { AgentRunner, AgentStore, AttachmentStagingStore, ModelCatalog, QuotaProvider, Actor, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, AgentApprovalPort, ActorResolver, MessageAttachment, AgentAttachmentConfig, AgentClientConfig, ToolPresentation, AgentHistoryWindow, AgentIntake, SkillContext, ToolRegistry, AgentRegistry, PromptContributor, SkillsConfig, SkillCatalogEntry, ToolCatalogEntry, MemoryConfig, MemoryDigestEntry, SkillProvider, AgentRunInput, TokenStreamSink, SinkWriter } from '@dudousxd/nestjs-agent-core';
2
+ import { b as AgentModuleOptions, c as AgentModuleAsyncOptions, A as AgentDepsFactory, C as ChatQueueService, d as AgentSkillsOptions } from './chat-queue.service-Bqq00NN1.js';
3
+ export { e as AGENT_TOOL_BRAND, f as AgentAttachmentsOptions, g as AgentDeps, h as AgentMemoryOptions, a as AgentSurface, F as FunctionalTool, L as LedgerQuotaProvider, Q as QueuePlan, i as QueueSettleOutcome, j as QueuedTurn, k as QueuedTurnStarter, l as QuotaLimits, m as QuotaWindowLimits, n as delegateToolName, p as provideAgentTool, o as provideAgentTools, u as utcDay } from './chat-queue.service-Bqq00NN1.js';
4
+ import { AgentRunner, AgentStore, AttachmentStagingStore, ModelCatalog, QuotaProvider, Actor, QuotaReport, ModelCatalogView, AttachmentRef, PageContext, ChatQueueState, HumanReply, ThreadSummary, ThreadDetail, UpdateThreadInput, MessageFeedbackValue, MessageFeedback, StagedAttachment, AgentApprovalPort, ActorResolver, 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';
5
5
  export * from '@dudousxd/nestjs-agent-core';
6
6
  import { Request } from 'express';
7
7
  import { StandardSchemaV1 } from '@standard-schema/spec';
@@ -12,6 +12,34 @@ declare class AgentModule {
12
12
  static forRootAsync(options: AgentModuleAsyncOptions): DynamicModule;
13
13
  }
14
14
 
15
+ /**
16
+ * What a send does when its thread already has a turn running:
17
+ * - `'auto'` (default) — run now when the thread is idle, else wait in the thread's queue.
18
+ * - `'queue'` — always wait in the queue, behind whatever is already waiting (it still starts at
19
+ * once when nothing is running and nothing is ahead of it).
20
+ * - `'interrupt'` — cancel the running turn and run this one next, ahead of the queue.
21
+ */
22
+ type ChatSendMode = 'auto' | 'queue' | 'interrupt';
23
+ /** A send that is waiting in its thread's queue instead of running. */
24
+ interface QueuedSend {
25
+ threadId: string;
26
+ queued: true;
27
+ /** The queued message's id — also the run id it will start under. */
28
+ messageId: string;
29
+ /** 0-based place in the queue at the time it was queued (`0` → next). */
30
+ position: number;
31
+ queue: ChatQueueState;
32
+ /** The turn it started under, when it started straight away (an idle thread). */
33
+ runId?: string;
34
+ /** The run an interrupt cancelled to make room for it. */
35
+ interrupting?: string;
36
+ }
37
+ /** What {@link AgentService.send} did: started a turn, or queued the message. */
38
+ type ChatSendResult = {
39
+ runId: string;
40
+ threadId: string;
41
+ queued?: undefined;
42
+ } | QueuedSend;
15
43
  interface ChatParams {
16
44
  actor: Actor;
17
45
  message: string;
@@ -36,6 +64,8 @@ interface ChatParams {
36
64
  * the thread list until the caller promotes it. Ignored when `threadId` is set.
37
65
  */
38
66
  transient?: boolean;
67
+ /** What to do when the thread already has a turn running — see {@link ChatSendMode}. */
68
+ mode?: ChatSendMode;
39
69
  }
40
70
  /**
41
71
  * A store that can answer a thread's default agent on its own, without materializing the thread.
@@ -60,7 +90,12 @@ declare class AgentService {
60
90
  private readonly models?;
61
91
  private readonly quotaProvider?;
62
92
  private readonly options?;
63
- constructor(runner: AgentRunner, store: AgentStore, deps: AgentDepsFactory, staging?: AttachmentStagingStore | undefined, models?: ModelCatalog | undefined, quotaProvider?: QuotaProvider | undefined, options?: Pick<AgentModuleOptions, "quota"> | undefined);
93
+ private readonly queue?;
94
+ constructor(runner: AgentRunner, store: AgentStore, deps: AgentDepsFactory, staging?: AttachmentStagingStore | undefined, models?: ModelCatalog | undefined, quotaProvider?: QuotaProvider | undefined, options?: Pick<AgentModuleOptions, "quota"> | undefined, queue?: ChatQueueService | undefined);
95
+ /** The queue service when the bound store can hold a queue, else `undefined`. */
96
+ private queueing;
97
+ /** The queue service, or a 501 naming what is missing. */
98
+ private requireQueue;
64
99
  /**
65
100
  * The actor's budget across windows (`GET <base>/quota`) — the bound {@link QuotaProvider}'s
66
101
  * report. Without one (a service built outside the module), a day window from the ledger.
@@ -89,10 +124,66 @@ declare class AgentService {
89
124
  */
90
125
  private resolveModel;
91
126
  private threadModel;
127
+ /**
128
+ * Start a turn — for in-process callers that need a run id back. A send that would have to wait
129
+ * (its thread already has a turn running) is refused with `409` instead; {@link send} is the form
130
+ * that queues it.
131
+ */
92
132
  chat(params: ChatParams): Promise<{
93
133
  runId: string;
94
134
  threadId: string;
95
135
  }>;
136
+ /**
137
+ * Send a message: start a turn, or — when its thread already has one running — queue the message
138
+ * to run after it (see {@link ChatSendMode}). What `POST <base>/chat` calls.
139
+ */
140
+ send(params: ChatParams): Promise<ChatSendResult>;
141
+ /**
142
+ * Start a turn the thread is already claimed for, under the claimed id. A runner that minted an
143
+ * id of its own anyway gets the thread re-pointed at it; one that fails to start frees the thread.
144
+ */
145
+ private startClaimed;
146
+ /** Put a send in its thread's queue, then drain it if the thread turned out to be free. */
147
+ private enqueue;
148
+ /** `GET <base>/threads/:id/queue` — the thread's waiting messages and whether it drains. */
149
+ getQueue(actor: Actor, threadId: string): Promise<ChatQueueState>;
150
+ /**
151
+ * `PATCH <base>/queue/:messageId` — change a waiting message's text and/or attachments, and/or move
152
+ * it to `position` in the queue. Answers the thread's queue.
153
+ */
154
+ updateQueuedMessage(actor: Actor, messageId: string, patch: {
155
+ message?: string;
156
+ attachments?: AttachmentRef[] | null;
157
+ position?: number;
158
+ }): Promise<ChatQueueState>;
159
+ /** `DELETE <base>/queue/:messageId` — drop a waiting message. Answers the thread's queue. */
160
+ removeQueuedMessage(actor: Actor, messageId: string): Promise<ChatQueueState>;
161
+ /**
162
+ * `POST <base>/queue/:messageId/interrupt` — run a message that is already waiting NOW: it moves
163
+ * to the head of its queue marked as an interrupt, any pause is lifted, and the running turn is
164
+ * cancelled (its settle starts this message — the same path a `mode: 'interrupt'` send takes).
165
+ * With nothing running, the message starts at once.
166
+ *
167
+ * One request, and the message never leaves the queue: a client that removed it and sent it again
168
+ * would lose it if the second call failed, and would run it twice if another tab's drain started
169
+ * it in between. Answers the queue, plus `interrupting` (the run that was cancelled) or `runId`
170
+ * (the run this message started).
171
+ */
172
+ interruptQueuedMessage(actor: Actor, messageId: string): Promise<ChatQueueState & {
173
+ runId?: string;
174
+ interrupting?: string;
175
+ }>;
176
+ /** `DELETE <base>/threads/:id/queue` — drop every waiting message (and any pause). */
177
+ clearQueue(actor: Actor, threadId: string): Promise<ChatQueueState>;
178
+ /**
179
+ * `POST <base>/threads/:id/queue/resume` — lift a pause and start the head when nothing is
180
+ * running. Answers the queue, and the run the head started under, if it did.
181
+ */
182
+ resumeQueue(actor: Actor, threadId: string): Promise<ChatQueueState & {
183
+ runId?: string;
184
+ }>;
185
+ /** The thread a queued message waits on, once the caller is shown to own it. */
186
+ private assertOwnsQueuedMessage;
96
187
  /**
97
188
  * Rebuild this turn's attachments from the staging store, keyed by the ids the caller claimed.
98
189
  * The model provider fetches {@link MessageAttachment.url} verbatim, so that url is only ever
@@ -866,6 +957,7 @@ declare function resolveSkillsConfig(options: AgentSkillsOptions | undefined, de
866
957
  declare class InlineAgentRunner implements AgentRunner {
867
958
  private readonly factory;
868
959
  private readonly store;
960
+ private readonly queue?;
869
961
  private readonly logger;
870
962
  private readonly pending;
871
963
  /**
@@ -874,8 +966,15 @@ declare class InlineAgentRunner implements AgentRunner {
874
966
  * running it. A cancelled id is dropped once the run settles, so the set tracks live runs only.
875
967
  */
876
968
  private readonly cancelled;
877
- constructor(factory: AgentDepsFactory, store: AgentStore);
878
- start(input: AgentRunInput): Promise<{
969
+ /** Top-level runs this process is running now — what {@link isRunActive} answers from. */
970
+ private readonly live;
971
+ constructor(factory: AgentDepsFactory, store: AgentStore, queue?: ChatQueueService | undefined);
972
+ /**
973
+ * In-process, so exact: a run this process is not running is not running anywhere — the process
974
+ * that was running it is gone (a restart), and a thread it still holds is a stale claim.
975
+ */
976
+ isRunActive(runId: string): Promise<boolean>;
977
+ start(input: AgentRunInput, options?: AgentRunStartOptions): Promise<{
879
978
  runId: string;
880
979
  }>;
881
980
  signal(runId: string, toolCallId: string, reply: HumanReply): Promise<void>;
@@ -901,6 +1000,15 @@ declare class InlineAgentRunner implements AgentRunner {
901
1000
  * streams does not retry this one.
902
1001
  */
903
1002
  private settleCancelled;
1003
+ /**
1004
+ * Move the thread past a settling TOP-LEVEL run — to the next queued message, which starts here,
1005
+ * or to a paused/empty queue — and write the resulting `queue` frame into this run's stream. A
1006
+ * no-op without a queue-capable store, and for a run that is not a thread's own turn.
1007
+ *
1008
+ * Never throws: the run is settling either way, and a queue that could not be advanced is picked
1009
+ * up by the next send or resume on the thread.
1010
+ */
1011
+ private settleQueue;
904
1012
  /**
905
1013
  * Park a run on a human, keyed by run + tool call. One map for approvals and for question-set
906
1014
  * answers alike: both wait on the same key, and `signal` cannot tell (or need to tell) which
@@ -933,6 +1041,43 @@ declare class InlineAgentRunner implements AgentRunner {
933
1041
  private runNested;
934
1042
  }
935
1043
 
1044
+ interface UpdateQueuedMessageBody {
1045
+ /** The new text. */
1046
+ message?: unknown;
1047
+ /** `[{ mediaId }]` refs replacing the message's attachments; `null` or `[]` drops them. */
1048
+ attachments?: unknown;
1049
+ /** Move the message to this 0-based place in the queue. */
1050
+ position?: unknown;
1051
+ }
1052
+ /**
1053
+ * The thread message queue: messages sent while a turn was running, waiting to run after it. Every
1054
+ * route is ownership-gated like the thread routes, and answers the thread's queue as it now stands
1055
+ * (`{ items, paused }`). A change is also announced to whoever is streaming the thread, as a `queue`
1056
+ * frame in the running turn's stream.
1057
+ */
1058
+ declare class QueueController {
1059
+ private readonly agent;
1060
+ private readonly actorResolver;
1061
+ constructor(agent: AgentService, actorResolver: ActorResolver);
1062
+ list(req: Request, id: string): Promise<ChatQueueState>;
1063
+ clear(req: Request, id: string): Promise<ChatQueueState>;
1064
+ /** Lift a pause; the head starts when nothing is running. Carries `runId` when it started. */
1065
+ resume(req: Request, id: string): Promise<ChatQueueState & {
1066
+ runId?: string;
1067
+ }>;
1068
+ update(req: Request, messageId: string, body: UpdateQueuedMessageBody): Promise<ChatQueueState>;
1069
+ /**
1070
+ * Run a waiting message now: it moves to the head as an interrupt and the running turn is
1071
+ * cancelled for it. Carries `interrupting` (the cancelled run), or `runId` when nothing was
1072
+ * running and it started at once.
1073
+ */
1074
+ interrupt(req: Request, messageId: string): Promise<ChatQueueState & {
1075
+ runId?: string;
1076
+ interrupting?: string;
1077
+ }>;
1078
+ remove(req: Request, messageId: string): Promise<ChatQueueState>;
1079
+ }
1080
+
936
1081
  /**
937
1082
  * The default `TokenStreamSink`: buffers chunks per run in-process so a reconnecting subscriber
938
1083
  * replays everything so far, then follows live.
@@ -1040,4 +1185,4 @@ declare function defaultRequestUserMapper(user: Record<string, unknown>): Actor;
1040
1185
  */
1041
1186
  declare function requestUserActorResolver<TUser = Record<string, unknown>>(map?: RequestUserMapper<TUser>): ActorResolver;
1042
1187
 
1043
- export { AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, Agent, AgentApprovalPortAdapter, AgentDepsFactory, AgentDiscoveryService, AgentModule, AgentModuleAsyncOptions, AgentModuleOptions, type AgentOptions, AgentService, AgentSkillsOptions, AiTool, AiToolDiscoveryService, type AiToolOptions, type AnonymousActorOptions, AnonymousActorResolver, type AttachmentLimits, AttachmentsController, type ChatParams, ConfigController, DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES, DEFAULT_MAX_ATTACHMENT_BYTES, type DeclaredSkill, HeaderActorResolver, InProcessTokenStreamSink, InlineAgentRunner, MAX_ATTACHMENTS_PER_MESSAGE, MemoriesController, MessagesController, ModelsController, type RequestUserMapper, type ResolvedAiToolOptions, SKILL_METADATA, SYSTEM_PROMPT_CONTRIBUTOR_METADATA, SYSTEM_PROMPT_METADATA, Skill, type SkillBody, SkillDiscoveryService, type SkillOptions, SkillsController, SystemPrompt, SystemPromptContributor, type ThreadDefaultAgentReader, type ThreadModelReader, ToolsController, attachmentLimits, declaredSkillProvider, defaultRequestUserMapper, readAgentMetadata, readAiToolMetadata, readSkillMetadata, requestUserActorResolver, resolveSkillsConfig, skillScope, toolNameFromClass };
1188
+ export { AGENT_METADATA, AI_TOOL_METADATA, ATTACHMENT_PAGE_SIZE, Agent, AgentApprovalPortAdapter, AgentDepsFactory, AgentDiscoveryService, AgentModule, AgentModuleAsyncOptions, AgentModuleOptions, type AgentOptions, 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, SKILL_METADATA, SYSTEM_PROMPT_CONTRIBUTOR_METADATA, SYSTEM_PROMPT_METADATA, Skill, type SkillBody, SkillDiscoveryService, type SkillOptions, SkillsController, SystemPrompt, SystemPromptContributor, type ThreadDefaultAgentReader, type ThreadModelReader, ToolsController, attachmentLimits, declaredSkillProvider, defaultRequestUserMapper, readAgentMetadata, readAiToolMetadata, readSkillMetadata, requestUserActorResolver, resolveSkillsConfig, skillScope, toolNameFromClass };