@dudousxd/nestjs-agent 1.17.0 → 1.17.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.
@@ -30,10 +30,10 @@ __export(durable_exports, {
30
30
  module.exports = __toCommonJS(durable_exports);
31
31
 
32
32
  // src/durable/agent-run.workflow.ts
33
- var import_nestjs_agent_core3 = require("@dudousxd/nestjs-agent-core");
33
+ var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
34
34
  var import_nestjs_durable2 = require("@dudousxd/nestjs-durable");
35
35
  var import_nestjs_durable_core2 = require("@dudousxd/nestjs-durable-core");
36
- var import_common3 = require("@nestjs/common");
36
+ var import_common2 = require("@nestjs/common");
37
37
 
38
38
  // src/agent-deps.ts
39
39
  function utcDay(date = /* @__PURE__ */ new Date()) {
@@ -51,9 +51,26 @@ function childSinkWriter(writer) {
51
51
  }
52
52
  __name(childSinkWriter, "childSinkWriter");
53
53
 
54
- // src/queue/chat-queue.service.ts
54
+ // src/queue/chat-queue.token.ts
55
+ var AGENT_CHAT_QUEUE = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:chat-queue");
56
+
57
+ // src/durable/agent-run.steps.ts
55
58
  var import_nestjs_agent_core = require("@dudousxd/nestjs-agent-core");
59
+ var import_nestjs_durable = require("@dudousxd/nestjs-durable");
56
60
  var import_common = require("@nestjs/common");
61
+
62
+ // src/durable/outside-workflow-ctx.ts
63
+ var import_nestjs_durable_core = require("@dudousxd/nestjs-durable-core");
64
+ function outsideWorkflowCtx(fn) {
65
+ return (0, import_nestjs_durable_core.runInWorkflowCtx)(void 0, fn);
66
+ }
67
+ __name(outsideWorkflowCtx, "outsideWorkflowCtx");
68
+ function stepOf(ctx) {
69
+ return (name, fn, ...rest) => ctx.localStep(name, (...args) => outsideWorkflowCtx(() => fn(...args)), ...rest);
70
+ }
71
+ __name(stepOf, "stepOf");
72
+
73
+ // src/durable/agent-run.steps.ts
57
74
  function _ts_decorate(decorators, target, key, desc) {
58
75
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
59
76
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -80,647 +97,206 @@ function _ts_param(paramIndex, decorator) {
80
97
  };
81
98
  }
82
99
  __name(_ts_param, "_ts_param");
83
- var MAX_DRAIN_ATTEMPTS = 8;
84
- var ChatQueueService = class _ChatQueueService {
100
+ var AgentRunSteps = class {
85
101
  static {
86
- __name(this, "ChatQueueService");
102
+ __name(this, "AgentRunSteps");
103
+ }
104
+ factory;
105
+ constructor(factory) {
106
+ this.factory = factory;
87
107
  }
88
- store;
89
- sink;
90
- quotaProvider;
91
- options;
92
- staging;
93
- logger = new import_common.Logger(_ChatQueueService.name);
94
108
  /**
95
- * Runs this process claimed a thread for and has not handed to a runner yet. A holder in here is
96
- * alive whatever the runner says — it simply has not registered the run yet.
109
+ * Retryable: every side effect (persist/quota/stream markers) happens loop-side under
110
+ * `hooks.step`, so a durable retry only re-runs the model call and re-streams its tokens — never
111
+ * double-writes. NEVER call `writer.end()`/`fail()` here: the workflow owns the stream's lifecycle,
112
+ * across however many turns/retries it takes.
97
113
  */
98
- starting = /* @__PURE__ */ new Set();
99
- constructor(store, sink, quotaProvider, options, staging) {
100
- this.store = store;
101
- this.sink = sink;
102
- this.quotaProvider = quotaProvider;
103
- this.options = options;
104
- this.staging = staging;
105
- }
106
- /** Whether the bound store can hold a queue. Without one, a busy thread is not queued. */
107
- get supported() {
108
- return (0, import_nestjs_agent_core.isChatQueueStore)(this.store);
114
+ llm(input) {
115
+ return outsideWorkflowCtx(() => this.runLlm(input));
109
116
  }
110
- /** The bound store as a queue store, or a 501 naming what is missing. */
111
- queueStore() {
112
- if (!(0, import_nestjs_agent_core.isChatQueueStore)(this.store)) {
113
- throw new import_common.NotImplementedException("Queueing messages requires an AgentStore that implements ChatQueueStore (enqueueMessage, listQueue, \u2026, claimActiveStream, releaseActiveStream); the bound store does not.");
117
+ async runLlm(input) {
118
+ const deps = this.factory.forAgent(input.agentName);
119
+ const tools = (0, import_nestjs_agent_core.withMemoryTool)({
120
+ tools: (0, import_nestjs_agent_core.withSkillTool)({
121
+ tools: (0, import_nestjs_agent_core.withAskTool)({
122
+ tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList, {
123
+ ...input.threadId !== void 0 ? {
124
+ threadId: input.threadId
125
+ } : {},
126
+ ...input.agentName !== void 0 ? {
127
+ agentName: input.agentName
128
+ } : {}
129
+ }),
130
+ ask: deps.ask
131
+ }),
132
+ enabled: deps.skills !== void 0
133
+ }),
134
+ enabled: deps.memory?.provider.write !== void 0
135
+ });
136
+ const buffer = input.bufferOutput === true ? (0, import_nestjs_agent_core.createFrameBuffer)() : void 0;
137
+ let writer;
138
+ if (buffer !== void 0) {
139
+ writer = buffer.writer;
140
+ } else {
141
+ const opened = await deps.sink.open(input.sinkRunId);
142
+ writer = input.childSink ? childSinkWriter(opened) : opened;
114
143
  }
115
- return this.store;
116
- }
117
- async state(threadId) {
118
- const store = this.queueStore();
119
- const [items, paused] = await Promise.all([
120
- store.listQueue(threadId),
121
- store.queuePause(threadId)
122
- ]);
123
- return {
124
- items: items.map(import_nestjs_agent_core.queuedMessageView),
125
- paused
144
+ const frames = (0, import_nestjs_agent_core.observeTurnFrames)(writer);
145
+ const turn = (0, import_nestjs_agent_core.withTurnFrames)(await (0, import_nestjs_agent_core.traceLlmTurn)(input.runId, input.step, () => deps.model.runTurn({
146
+ system: input.system,
147
+ messages: input.messages,
148
+ tools,
149
+ sink: frames.writer,
150
+ ...input.model !== void 0 ? {
151
+ model: input.model
152
+ } : {}
153
+ })), frames.summary());
154
+ const stamped = (0, import_nestjs_agent_core.stampToolKinds)(turn, deps);
155
+ return buffer === void 0 ? stamped : {
156
+ ...stamped,
157
+ bufferedFrames: buffer.frames()
126
158
  };
127
159
  }
128
160
  /**
129
- * Whether `holder` is still running. A run this process is about to start is; otherwise the
130
- * runner decides, and a runner that cannot tell says yes.
161
+ * NO DURABLE retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm`
162
+ * above). What it does retry, in place, is a CLASSIFIED-TRANSIENT error from the tool's own
163
+ * invocation (a DB deadlock, a lock-wait timeout — see `isTransientToolError`): the server rolled
164
+ * that work back, so re-invoking it is safe, and doing it here (inside this one step, never a new
165
+ * checkpoint) is exactly how the non-dispatched loop path handles it too. The timeout is applied
166
+ * HERE, handler-side, via `withToolTimeout` — never as a durable dispatch `timeoutMs`, which
167
+ * bounds engine liveness (retryable) rather than the tool's own business outcome — and per
168
+ * ATTEMPT, so a retried invocation gets its own fresh timeout window.
131
169
  */
132
- async isAlive(holder, runner) {
133
- if (this.starting.has(holder)) {
134
- return true;
135
- }
136
- if (typeof runner.isRunActive !== "function") {
137
- return true;
138
- }
139
- try {
140
- return await runner.isRunActive(holder);
141
- } catch {
142
- return true;
143
- }
170
+ tool(input) {
171
+ return outsideWorkflowCtx(() => this.runTool(input));
144
172
  }
145
- /**
146
- * The run holding `threadId`, or `null` when it is free — a holder the runner reports dead counts
147
- * as free, and is returned as `stale` so the caller can claim over it.
148
- */
149
- async holder(threadId, runner) {
150
- const holder = await this.queueStore().activeRunForThread(threadId);
151
- if (holder === null) {
152
- return {
153
- live: null,
154
- stale: null
155
- };
173
+ async runTool(input) {
174
+ const deps = this.factory.forAgent(input.ctx.agentName);
175
+ if (deps.registry.spec(input.toolName)?.kind === "action" && input.toolType !== "action") {
176
+ throw new Error(`tool "${input.toolName}" is an action tool but was dispatched without approval: the dispatching process resolved its kind against a registry that does not have it`);
156
177
  }
157
- return await this.isAlive(holder, runner) ? {
158
- live: holder,
159
- stale: null
160
- } : {
161
- live: null,
162
- stale: holder
178
+ const sinkRunId = input.sinkRunId;
179
+ let opened;
180
+ const ui = (0, import_nestjs_agent_core.createUiCollector)(input.toolCallId, sinkRunId === void 0 ? void 0 : async (event) => {
181
+ opened ??= Promise.resolve(deps.sink.open(sinkRunId)).then((writer) => input.childSink === true ? childSinkWriter(writer) : writer);
182
+ await (await opened).write((0, import_nestjs_agent_core.encodeStreamEvent)(event));
183
+ });
184
+ const ctx = {
185
+ ...(0, import_nestjs_agent_core.toolCallContext)(input.ctx, input.toolCallId),
186
+ emitUi: ui.emit
187
+ };
188
+ const localClassify = deps.toolTransientRetry !== false ? deps.toolTransientRetry?.classify : void 0;
189
+ const transientRetry = input.transientRetry === false ? false : {
190
+ attempts: input.transientRetry.attempts,
191
+ backoffMs: input.transientRetry.backoffMs,
192
+ ...localClassify !== void 0 ? {
193
+ classify: localClassify
194
+ } : {}
163
195
  };
196
+ const output = await (0, import_nestjs_agent_core.traceToolExecution)(input.ctx.runId, {
197
+ toolCallId: input.toolCallId,
198
+ toolName: input.toolName,
199
+ toolType: input.toolType
200
+ }, () => (0, import_nestjs_agent_core.invokeWithTransientRetry)(() => {
201
+ ui.restart();
202
+ const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy);
203
+ return input.timeoutMs !== void 0 ? (0, import_nestjs_agent_core.withToolTimeout)(invocation, input.timeoutMs, input.toolName) : invocation;
204
+ }, transientRetry, {
205
+ onRetry: /* @__PURE__ */ __name((attempt, error) => {
206
+ (0, import_nestjs_agent_core.publishAgentToolRetry)({
207
+ toolName: input.toolName,
208
+ toolCallId: input.toolCallId,
209
+ attempt,
210
+ message: error instanceof Error ? error.message : String(error)
211
+ });
212
+ }, "onRetry")
213
+ }));
214
+ return input.collectUi === true ? (0, import_nestjs_agent_core.wrapToolStepOutput)(output, ui.components()) : output;
215
+ }
216
+ };
217
+ _ts_decorate([
218
+ (0, import_nestjs_durable.Step)({
219
+ retries: 3
220
+ }),
221
+ _ts_metadata("design:type", Function),
222
+ _ts_metadata("design:paramtypes", [
223
+ typeof DispatchedLlmInput === "undefined" ? Object : DispatchedLlmInput
224
+ ]),
225
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
226
+ ], AgentRunSteps.prototype, "llm", null);
227
+ _ts_decorate([
228
+ (0, import_nestjs_durable.Step)(),
229
+ _ts_metadata("design:type", Function),
230
+ _ts_metadata("design:paramtypes", [
231
+ typeof DispatchedToolInput === "undefined" ? Object : DispatchedToolInput
232
+ ]),
233
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
234
+ ], AgentRunSteps.prototype, "tool", null);
235
+ AgentRunSteps = _ts_decorate([
236
+ (0, import_common.Injectable)(),
237
+ _ts_param(0, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_DEPS_FACTORY)),
238
+ _ts_metadata("design:type", Function),
239
+ _ts_metadata("design:paramtypes", [
240
+ typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory
241
+ ])
242
+ ], AgentRunSteps);
243
+
244
+ // src/durable/agent-run.workflow.ts
245
+ function _ts_decorate2(decorators, target, key, desc) {
246
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
247
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
248
+ r = Reflect.decorate(decorators, target, key, desc);
249
+ } else {
250
+ for (var i = decorators.length - 1; i >= 0; i--) {
251
+ if (d = decorators[i]) {
252
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
253
+ }
254
+ }
255
+ }
256
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
257
+ }
258
+ __name(_ts_decorate2, "_ts_decorate");
259
+ function _ts_metadata2(metadataKey, metadataValue) {
260
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
261
+ return Reflect.metadata(metadataKey, metadataValue);
262
+ }
263
+ }
264
+ __name(_ts_metadata2, "_ts_metadata");
265
+ function _ts_param2(paramIndex, decorator) {
266
+ return function(target, key) {
267
+ decorator(target, key, paramIndex);
268
+ };
269
+ }
270
+ __name(_ts_param2, "_ts_param");
271
+ var AgentRunWorkflow = class _AgentRunWorkflow {
272
+ static {
273
+ __name(this, "AgentRunWorkflow");
274
+ }
275
+ factory;
276
+ store;
277
+ runs;
278
+ queue;
279
+ logger = new import_common2.Logger(_AgentRunWorkflow.name);
280
+ constructor(factory, store, runs, queue) {
281
+ this.factory = factory;
282
+ this.store = store;
283
+ this.runs = runs;
284
+ this.queue = queue;
164
285
  }
165
286
  /**
166
- * Decide what follows a TOP-LEVEL run that is settling on `threadId`, and move the thread there:
167
- * hand it to the next queued message (claimed and popped here, started by the caller), or pause
168
- * the queue, or release the thread. Call it BEFORE the run's terminal frame, so a client reading
169
- * the stream learns what comes next from the `queue` frame, and so the thread is already free
170
- * when the client sees the run end.
287
+ * Move the thread past this settling turn — to the next queued message, started here as a
288
+ * fire-and-forget `ctx.startChild` under the message's own id, or to a paused/empty queue — and
289
+ * answer the `queue` frame to write before the turn's terminal.
171
290
  *
172
- * A no-op returning `{}` on a store without a queue.
291
+ * Journaled: the decision (which message, claimed and popped) is one `localStep`, so a replay
292
+ * reads it back instead of popping a second message, and the start is the runtime's own
293
+ * replay-safe spawn. Gated by `ctx.patched`, so a run recorded before the queue existed replays
294
+ * against the history it has. A no-op for a sub-agent's run and on a store without a queue.
173
295
  */
174
- async plan(args) {
175
- if (!(0, import_nestjs_agent_core.isChatQueueStore)(this.store)) {
176
- return {};
177
- }
178
- const store = this.store;
179
- const { threadId, outcome } = args;
180
- if (await store.activeRunForThread(threadId) !== args.runId) {
181
- return {};
182
- }
183
- let holding = args.runId;
184
- for (let attempt = 0; attempt < MAX_DRAIN_ATTEMPTS; attempt += 1) {
185
- const items = await store.listQueue(threadId);
186
- const head = items[0];
187
- if (head === void 0) {
188
- if (holding !== null) {
189
- await store.releaseActiveStream(threadId, holding);
190
- holding = null;
191
- continue;
192
- }
193
- return {};
194
- }
195
- let pause = await store.queuePause(threadId);
196
- if (pause === null) {
197
- const reason = pauseReasonFor(outcome, head);
198
- if (reason !== null) {
199
- pause = {
200
- reason,
201
- ...outcome === "failed" && args.error !== void 0 ? {
202
- message: args.error
203
- } : {},
204
- at: (/* @__PURE__ */ new Date()).toISOString()
205
- };
206
- await store.setQueuePause(threadId, pause);
207
- }
208
- }
209
- if (pause === null) {
210
- const blocked = await this.quotaBlock(head.actor);
211
- if (blocked !== null) {
212
- pause = {
213
- reason: "quota_exceeded",
214
- message: blocked,
215
- at: (/* @__PURE__ */ new Date()).toISOString()
216
- };
217
- await store.setQueuePause(threadId, pause);
218
- }
219
- }
220
- if (pause !== null) {
221
- if (holding !== null) {
222
- await store.releaseActiveStream(threadId, holding);
223
- }
224
- return {
225
- frame: queueFrame(items, pause)
226
- };
227
- }
228
- const claimed = await store.claimActiveStream(threadId, head.id, holding !== null ? {
229
- replacing: holding
230
- } : {});
231
- if (!claimed) {
232
- return {};
233
- }
234
- holding = head.id;
235
- if (!await store.removeQueuedMessage(head.id)) {
236
- await store.releaseActiveStream(threadId, head.id);
237
- holding = null;
238
- continue;
239
- }
240
- const next = {
241
- runId: head.id,
242
- messageId: head.id,
243
- input: await this.inputFor(head)
244
- };
245
- return {
246
- next,
247
- frame: queueFrame(items.slice(1), null, {
248
- messageId: head.id,
249
- runId: head.id
250
- })
251
- };
252
- }
253
- if (holding !== null) {
254
- await store.releaseActiveStream(threadId, holding);
255
- }
256
- return {};
257
- }
258
- /**
259
- * {@link plan}, then start what it picked with `start`. What an in-process settle (the inline
260
- * runner, a durable cancel issued outside a workflow) calls; answers the frame to write.
261
- */
262
- async handoff(args, start) {
263
- const plan = await this.plan(args);
264
- if (plan.next === void 0) {
265
- return plan.frame;
266
- }
267
- return await this.launch(args.threadId, plan.next, start) ? plan.frame : this.pausedFrame(args.threadId);
268
- }
269
- /**
270
- * Start the head of an IDLE thread's queue — after a send queued behind a run that turned out to
271
- * be gone, after a resume, after a stale holder. Does nothing while a live run holds the thread
272
- * (its settle drains) or while the queue is paused. Answers the started run's id, if any.
273
- */
274
- async kick(threadId, runner) {
275
- if (!(0, import_nestjs_agent_core.isChatQueueStore)(this.store)) {
276
- return void 0;
277
- }
278
- const { live, stale } = await this.holder(threadId, runner);
279
- if (live !== null) {
280
- return void 0;
281
- }
282
- if (stale !== null) {
283
- this.logger.warn(`thread ${threadId} was held by run ${stale}, which is no longer running`);
284
- }
285
- const plan = await this.plan({
286
- threadId,
287
- runId: stale,
288
- outcome: "completed"
289
- });
290
- if (plan.next === void 0) {
291
- return void 0;
292
- }
293
- const started = await this.launch(threadId, plan.next, (input, runId) => runner.start(input, {
294
- runId
295
- }));
296
- if (started && plan.frame !== void 0) {
297
- await this.write(plan.next.runId, plan.frame);
298
- }
299
- return started ? plan.next.runId : void 0;
300
- }
301
- /**
302
- * Start a turn the thread is already claimed for. On failure the message goes back to the head of
303
- * the queue, the queue pauses (`start_failed`), and the claim is released — nothing is lost and
304
- * nothing is left holding the thread.
305
- */
306
- async launch(threadId, next, start) {
307
- this.starting.add(next.runId);
308
- try {
309
- await start(next.input, next.runId);
310
- return true;
311
- } catch (error) {
312
- const message = error instanceof Error ? error.message : String(error);
313
- this.logger.error(`queued message ${next.messageId} could not start: ${message}`);
314
- await this.restore(threadId, next, "start_failed", message);
315
- return false;
316
- } finally {
317
- this.starting.delete(next.runId);
318
- }
319
- }
320
- /** Put a turn that never started back at the head of its queue, paused, and free the thread. */
321
- async restore(threadId, next, reason, message) {
322
- const store = this.queueStore();
323
- const { input } = next;
324
- await store.enqueueMessage({
325
- threadId,
326
- actor: input.actor,
327
- content: input.userText,
328
- at: "head",
329
- ...input.attachments !== void 0 ? {
330
- attachments: input.attachments
331
- } : {},
332
- ...input.agentName !== void 0 ? {
333
- agentName: input.agentName
334
- } : {},
335
- ...input.model !== void 0 ? {
336
- model: input.model
337
- } : {},
338
- ...input.pageContext !== void 0 ? {
339
- pageContext: input.pageContext
340
- } : {}
341
- });
342
- await store.setQueuePause(threadId, {
343
- reason,
344
- message,
345
- at: (/* @__PURE__ */ new Date()).toISOString()
346
- });
347
- await store.releaseActiveStream(threadId, next.runId);
348
- }
349
- /** A `queue` frame with the thread's current state. */
350
- async pausedFrame(threadId) {
351
- return {
352
- kind: "queue",
353
- queue: await this.state(threadId)
354
- };
355
- }
356
- /**
357
- * Tell whoever is watching the thread that its queue changed: a `queue` frame into the stream of
358
- * the run holding it. Best-effort — a thread nobody is streaming has no one to tell, and the next
359
- * read of the thread carries the queue anyway.
360
- */
361
- async publish(threadId) {
362
- const state = await this.state(threadId);
363
- const holder = await this.queueStore().activeRunForThread(threadId);
364
- if (holder !== null) {
365
- await this.write(holder, {
366
- kind: "queue",
367
- queue: state
368
- }).catch((error) => {
369
- this.logger.warn(`could not publish the queue of thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`);
370
- });
371
- }
372
- return state;
373
- }
374
- async write(runId, frame) {
375
- const writer = await this.sink.open(runId);
376
- await writer.write((0, import_nestjs_agent_core.encodeStreamEvent)(frame));
377
- }
378
- /** Why `actor` may not start a turn now (the quota message), or `null`. */
379
- async quotaBlock(actor) {
380
- if (this.options?.quota === void 0 || this.quotaProvider === void 0) {
381
- return null;
382
- }
383
- try {
384
- const { blocked } = await this.quotaProvider.report({
385
- actor
386
- });
387
- if (blocked === void 0) {
388
- return null;
389
- }
390
- return blocked.reason ?? `The ${blocked.period === "day" ? "daily" : "monthly"} quota is used up`;
391
- } catch {
392
- return null;
393
- }
394
- }
395
- /**
396
- * The turn a queued message starts: everything it was queued with, today's date, and its
397
- * attachments' urls minted afresh — the ones stored at enqueue time may have expired while it
398
- * waited. An attachment the staging store no longer resolves keeps its stored url.
399
- */
400
- async inputFor(message) {
401
- const attachments = await this.freshAttachments(message.actor, message.attachments ?? []);
402
- return {
403
- threadId: message.threadId,
404
- actor: message.actor,
405
- userText: message.content,
406
- day: utcDay(),
407
- ...message.agentName !== void 0 ? {
408
- agentName: message.agentName
409
- } : {},
410
- ...attachments.length > 0 ? {
411
- attachments
412
- } : {},
413
- ...message.pageContext !== void 0 ? {
414
- pageContext: message.pageContext
415
- } : {},
416
- ...message.model !== void 0 ? {
417
- model: message.model
418
- } : {}
419
- };
420
- }
421
- async freshAttachments(actor, attachments) {
422
- const staging = this.staging;
423
- if (attachments.length === 0 || staging === void 0 || typeof staging.resolve !== "function") {
424
- return attachments;
425
- }
426
- return Promise.all(attachments.map(async (attachment) => {
427
- try {
428
- return await staging.resolve({
429
- mediaId: attachment.mediaId,
430
- actor
431
- }) ?? attachment;
432
- } catch {
433
- return attachment;
434
- }
435
- }));
436
- }
437
- };
438
- ChatQueueService = _ts_decorate([
439
- (0, import_common.Injectable)(),
440
- _ts_param(0, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_STORE)),
441
- _ts_param(1, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_SINK)),
442
- _ts_param(2, (0, import_common.Optional)()),
443
- _ts_param(2, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_QUOTA_PROVIDER)),
444
- _ts_param(3, (0, import_common.Optional)()),
445
- _ts_param(3, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_OPTIONS)),
446
- _ts_param(4, (0, import_common.Optional)()),
447
- _ts_param(4, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_ATTACHMENT_STAGING)),
448
- _ts_metadata("design:type", Function),
449
- _ts_metadata("design:paramtypes", [
450
- typeof AgentStore === "undefined" ? Object : AgentStore,
451
- typeof TokenStreamSink === "undefined" ? Object : TokenStreamSink,
452
- typeof QuotaProvider === "undefined" ? Object : QuotaProvider,
453
- typeof Pick === "undefined" ? Object : Pick,
454
- typeof AttachmentStagingStore === "undefined" ? Object : AttachmentStagingStore
455
- ])
456
- ], ChatQueueService);
457
- function pauseReasonFor(outcome, head) {
458
- if (outcome === "failed") {
459
- return "run_failed";
460
- }
461
- if (outcome === "cancelled" && head.interrupt !== true) {
462
- return "cancelled";
463
- }
464
- return null;
465
- }
466
- __name(pauseReasonFor, "pauseReasonFor");
467
- function queueFrame(items, paused, started) {
468
- return {
469
- kind: "queue",
470
- queue: {
471
- items: items.map(import_nestjs_agent_core.queuedMessageView),
472
- paused
473
- },
474
- ...started !== void 0 ? {
475
- started
476
- } : {}
477
- };
478
- }
479
- __name(queueFrame, "queueFrame");
480
-
481
- // src/durable/agent-run.steps.ts
482
- var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
483
- var import_nestjs_durable = require("@dudousxd/nestjs-durable");
484
- var import_common2 = require("@nestjs/common");
485
-
486
- // src/durable/outside-workflow-ctx.ts
487
- var import_nestjs_durable_core = require("@dudousxd/nestjs-durable-core");
488
- function outsideWorkflowCtx(fn) {
489
- return (0, import_nestjs_durable_core.runInWorkflowCtx)(void 0, fn);
490
- }
491
- __name(outsideWorkflowCtx, "outsideWorkflowCtx");
492
- function stepOf(ctx) {
493
- return (name, fn, ...rest) => ctx.localStep(name, (...args) => outsideWorkflowCtx(() => fn(...args)), ...rest);
494
- }
495
- __name(stepOf, "stepOf");
496
-
497
- // src/durable/agent-run.steps.ts
498
- function _ts_decorate2(decorators, target, key, desc) {
499
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
500
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
501
- r = Reflect.decorate(decorators, target, key, desc);
502
- } else {
503
- for (var i = decorators.length - 1; i >= 0; i--) {
504
- if (d = decorators[i]) {
505
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
506
- }
507
- }
508
- }
509
- return c > 3 && r && Object.defineProperty(target, key, r), r;
510
- }
511
- __name(_ts_decorate2, "_ts_decorate");
512
- function _ts_metadata2(metadataKey, metadataValue) {
513
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
514
- return Reflect.metadata(metadataKey, metadataValue);
515
- }
516
- }
517
- __name(_ts_metadata2, "_ts_metadata");
518
- function _ts_param2(paramIndex, decorator) {
519
- return function(target, key) {
520
- decorator(target, key, paramIndex);
521
- };
522
- }
523
- __name(_ts_param2, "_ts_param");
524
- var AgentRunSteps = class {
525
- static {
526
- __name(this, "AgentRunSteps");
527
- }
528
- factory;
529
- constructor(factory) {
530
- this.factory = factory;
531
- }
532
- /**
533
- * Retryable: every side effect (persist/quota/stream markers) happens loop-side under
534
- * `hooks.step`, so a durable retry only re-runs the model call and re-streams its tokens — never
535
- * double-writes. NEVER call `writer.end()`/`fail()` here: the workflow owns the stream's lifecycle,
536
- * across however many turns/retries it takes.
537
- */
538
- llm(input) {
539
- return outsideWorkflowCtx(() => this.runLlm(input));
540
- }
541
- async runLlm(input) {
542
- const deps = this.factory.forAgent(input.agentName);
543
- const tools = (0, import_nestjs_agent_core2.withMemoryTool)({
544
- tools: (0, import_nestjs_agent_core2.withSkillTool)({
545
- tools: (0, import_nestjs_agent_core2.withAskTool)({
546
- tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList, {
547
- ...input.threadId !== void 0 ? {
548
- threadId: input.threadId
549
- } : {},
550
- ...input.agentName !== void 0 ? {
551
- agentName: input.agentName
552
- } : {}
553
- }),
554
- ask: deps.ask
555
- }),
556
- enabled: deps.skills !== void 0
557
- }),
558
- enabled: deps.memory?.provider.write !== void 0
559
- });
560
- const buffer = input.bufferOutput === true ? (0, import_nestjs_agent_core2.createFrameBuffer)() : void 0;
561
- let writer;
562
- if (buffer !== void 0) {
563
- writer = buffer.writer;
564
- } else {
565
- const opened = await deps.sink.open(input.sinkRunId);
566
- writer = input.childSink ? childSinkWriter(opened) : opened;
567
- }
568
- const frames = (0, import_nestjs_agent_core2.observeTurnFrames)(writer);
569
- const turn = (0, import_nestjs_agent_core2.withTurnFrames)(await (0, import_nestjs_agent_core2.traceLlmTurn)(input.runId, input.step, () => deps.model.runTurn({
570
- system: input.system,
571
- messages: input.messages,
572
- tools,
573
- sink: frames.writer,
574
- ...input.model !== void 0 ? {
575
- model: input.model
576
- } : {}
577
- })), frames.summary());
578
- const stamped = (0, import_nestjs_agent_core2.stampToolKinds)(turn, deps);
579
- return buffer === void 0 ? stamped : {
580
- ...stamped,
581
- bufferedFrames: buffer.frames()
582
- };
583
- }
584
- /**
585
- * NO DURABLE retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm`
586
- * above). What it does retry, in place, is a CLASSIFIED-TRANSIENT error from the tool's own
587
- * invocation (a DB deadlock, a lock-wait timeout — see `isTransientToolError`): the server rolled
588
- * that work back, so re-invoking it is safe, and doing it here (inside this one step, never a new
589
- * checkpoint) is exactly how the non-dispatched loop path handles it too. The timeout is applied
590
- * HERE, handler-side, via `withToolTimeout` — never as a durable dispatch `timeoutMs`, which
591
- * bounds engine liveness (retryable) rather than the tool's own business outcome — and per
592
- * ATTEMPT, so a retried invocation gets its own fresh timeout window.
593
- */
594
- tool(input) {
595
- return outsideWorkflowCtx(() => this.runTool(input));
596
- }
597
- async runTool(input) {
598
- const deps = this.factory.forAgent(input.ctx.agentName);
599
- if (deps.registry.spec(input.toolName)?.kind === "action" && input.toolType !== "action") {
600
- throw new Error(`tool "${input.toolName}" is an action tool but was dispatched without approval: the dispatching process resolved its kind against a registry that does not have it`);
601
- }
602
- const sinkRunId = input.sinkRunId;
603
- let opened;
604
- const ui = (0, import_nestjs_agent_core2.createUiCollector)(input.toolCallId, sinkRunId === void 0 ? void 0 : async (event) => {
605
- opened ??= Promise.resolve(deps.sink.open(sinkRunId)).then((writer) => input.childSink === true ? childSinkWriter(writer) : writer);
606
- await (await opened).write((0, import_nestjs_agent_core2.encodeStreamEvent)(event));
607
- });
608
- const ctx = {
609
- ...(0, import_nestjs_agent_core2.toolCallContext)(input.ctx, input.toolCallId),
610
- emitUi: ui.emit
611
- };
612
- const localClassify = deps.toolTransientRetry !== false ? deps.toolTransientRetry?.classify : void 0;
613
- const transientRetry = input.transientRetry === false ? false : {
614
- attempts: input.transientRetry.attempts,
615
- backoffMs: input.transientRetry.backoffMs,
616
- ...localClassify !== void 0 ? {
617
- classify: localClassify
618
- } : {}
619
- };
620
- const output = await (0, import_nestjs_agent_core2.traceToolExecution)(input.ctx.runId, {
621
- toolCallId: input.toolCallId,
622
- toolName: input.toolName,
623
- toolType: input.toolType
624
- }, () => (0, import_nestjs_agent_core2.invokeWithTransientRetry)(() => {
625
- ui.restart();
626
- const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy);
627
- return input.timeoutMs !== void 0 ? (0, import_nestjs_agent_core2.withToolTimeout)(invocation, input.timeoutMs, input.toolName) : invocation;
628
- }, transientRetry, {
629
- onRetry: /* @__PURE__ */ __name((attempt, error) => {
630
- (0, import_nestjs_agent_core2.publishAgentToolRetry)({
631
- toolName: input.toolName,
632
- toolCallId: input.toolCallId,
633
- attempt,
634
- message: error instanceof Error ? error.message : String(error)
635
- });
636
- }, "onRetry")
637
- }));
638
- return input.collectUi === true ? (0, import_nestjs_agent_core2.wrapToolStepOutput)(output, ui.components()) : output;
639
- }
640
- };
641
- _ts_decorate2([
642
- (0, import_nestjs_durable.Step)({
643
- retries: 3
644
- }),
645
- _ts_metadata2("design:type", Function),
646
- _ts_metadata2("design:paramtypes", [
647
- typeof DispatchedLlmInput === "undefined" ? Object : DispatchedLlmInput
648
- ]),
649
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
650
- ], AgentRunSteps.prototype, "llm", null);
651
- _ts_decorate2([
652
- (0, import_nestjs_durable.Step)(),
653
- _ts_metadata2("design:type", Function),
654
- _ts_metadata2("design:paramtypes", [
655
- typeof DispatchedToolInput === "undefined" ? Object : DispatchedToolInput
656
- ]),
657
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
658
- ], AgentRunSteps.prototype, "tool", null);
659
- AgentRunSteps = _ts_decorate2([
660
- (0, import_common2.Injectable)(),
661
- _ts_param2(0, (0, import_common2.Inject)(import_nestjs_agent_core2.AGENT_DEPS_FACTORY)),
662
- _ts_metadata2("design:type", Function),
663
- _ts_metadata2("design:paramtypes", [
664
- typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory
665
- ])
666
- ], AgentRunSteps);
667
-
668
- // src/durable/agent-run.workflow.ts
669
- function _ts_decorate3(decorators, target, key, desc) {
670
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
671
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
672
- r = Reflect.decorate(decorators, target, key, desc);
673
- } else {
674
- for (var i = decorators.length - 1; i >= 0; i--) {
675
- if (d = decorators[i]) {
676
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
677
- }
678
- }
679
- }
680
- return c > 3 && r && Object.defineProperty(target, key, r), r;
681
- }
682
- __name(_ts_decorate3, "_ts_decorate");
683
- function _ts_metadata3(metadataKey, metadataValue) {
684
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
685
- return Reflect.metadata(metadataKey, metadataValue);
686
- }
687
- }
688
- __name(_ts_metadata3, "_ts_metadata");
689
- function _ts_param3(paramIndex, decorator) {
690
- return function(target, key) {
691
- decorator(target, key, paramIndex);
692
- };
693
- }
694
- __name(_ts_param3, "_ts_param");
695
- var AgentRunWorkflow = class _AgentRunWorkflow {
696
- static {
697
- __name(this, "AgentRunWorkflow");
698
- }
699
- factory;
700
- store;
701
- runs;
702
- queue;
703
- logger = new import_common3.Logger(_AgentRunWorkflow.name);
704
- constructor(factory, store, runs, queue) {
705
- this.factory = factory;
706
- this.store = store;
707
- this.runs = runs;
708
- this.queue = queue;
709
- }
710
- /**
711
- * Move the thread past this settling turn — to the next queued message, started here as a
712
- * fire-and-forget `ctx.startChild` under the message's own id, or to a paused/empty queue — and
713
- * answer the `queue` frame to write before the turn's terminal.
714
- *
715
- * Journaled: the decision (which message, claimed and popped) is one `localStep`, so a replay
716
- * reads it back instead of popping a second message, and the start is the runtime's own
717
- * replay-safe spawn. Gated by `ctx.patched`, so a run recorded before the queue existed replays
718
- * against the history it has. A no-op for a sub-agent's run and on a store without a queue.
719
- */
720
- async advanceQueue(ctx, input, outcome, error) {
721
- const queue = this.queue;
722
- if (queue === void 0 || !queue.supported || input.sinkRunId !== void 0 || input.deliverTo !== void 0) {
723
- return void 0;
296
+ async advanceQueue(ctx, input, outcome, error) {
297
+ const queue = this.queue;
298
+ if (queue === void 0 || !queue.supported || input.sinkRunId !== void 0 || input.deliverTo !== void 0) {
299
+ return void 0;
724
300
  }
725
301
  if (!await ctx.patched("agent:chat-queue")) {
726
302
  return void 0;
@@ -794,7 +370,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
794
370
  if (delivery === void 0) {
795
371
  return;
796
372
  }
797
- await stepOf(ctx)("deliver:detached:unsettled", () => (0, import_nestjs_agent_core3.settleUnsettledDelegation)({
373
+ await stepOf(ctx)("deliver:detached:unsettled", () => (0, import_nestjs_agent_core2.settleUnsettledDelegation)({
798
374
  store: this.store,
799
375
  delivery,
800
376
  agent: input.agentName ?? "default",
@@ -835,7 +411,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
835
411
  end: /* @__PURE__ */ __name(async () => {
836
412
  const frame = await this.advanceQueue(ctx, input, "completed");
837
413
  if (frame !== void 0) {
838
- await writer.write((0, import_nestjs_agent_core3.encodeStreamEvent)(frame));
414
+ await writer.write((0, import_nestjs_agent_core2.encodeStreamEvent)(frame));
839
415
  }
840
416
  await writer.end();
841
417
  }, "end")
@@ -867,7 +443,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
867
443
  // await, so launching a batch in one tick — what `settleAll` does — fixes the block of
868
444
  // positions in call order however the tools then settle. `ctx.patched` keeps a run that
869
445
  // recorded the one-call-at-a-time shape replaying against that shape.
870
- parallel: import_nestjs_agent_core3.settleAll,
446
+ parallel: import_nestjs_agent_core2.settleAll,
871
447
  cancelled: /* @__PURE__ */ __name(() => this.isCancelled(ctx.runId), "cancelled"),
872
448
  patched: /* @__PURE__ */ __name((id) => ctx.patched(id), "patched"),
873
449
  // Dispatched-step suspends must escape the loop's tool catch — control flow, not a tool
@@ -961,33 +537,33 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
961
537
  } : {}
962
538
  };
963
539
  try {
964
- const result = await (0, import_nestjs_agent_core3.runAgentLoop)({
540
+ const result = await (0, import_nestjs_agent_core2.runAgentLoop)({
965
541
  ...deps,
966
542
  day
967
543
  }, input, hooks);
968
- await stepOf(ctx)("deactivate", () => (0, import_nestjs_agent_core3.releaseThreadRun)(this.store, input.threadId, ctx.runId));
544
+ await stepOf(ctx)("deactivate", () => (0, import_nestjs_agent_core2.releaseThreadRun)(this.store, input.threadId, ctx.runId));
969
545
  return result;
970
546
  } catch (error) {
971
547
  if ((0, import_nestjs_durable_core2.isWorkflowControlFlowSignal)(error)) {
972
548
  throw error;
973
549
  }
974
- if (error instanceof import_nestjs_agent_core3.RunCancelledError) {
975
- await stepOf(ctx)("deactivate", () => (0, import_nestjs_agent_core3.releaseThreadRun)(this.store, input.threadId, ctx.runId));
550
+ if (error instanceof import_nestjs_agent_core2.RunCancelledError) {
551
+ await stepOf(ctx)("deactivate", () => (0, import_nestjs_agent_core2.releaseThreadRun)(this.store, input.threadId, ctx.runId));
976
552
  await this.settleDetachedParent(ctx, input, {
977
553
  status: "cancelled"
978
554
  });
979
555
  throw error;
980
556
  }
981
- if ((0, import_nestjs_agent_core3.isReplayIntegrityError)(error)) {
557
+ if ((0, import_nestjs_agent_core2.isReplayIntegrityError)(error)) {
982
558
  const detail = error.message;
983
- const code2 = (0, import_nestjs_agent_core3.agentFailureCode)(error);
559
+ const code2 = (0, import_nestjs_agent_core2.agentFailureCode)(error);
984
560
  this.logger.error(`agent run ${ctx.runId} failed (${code2}): ${detail}`);
985
- (0, import_nestjs_agent_core3.publishAgentRunFailed)({
561
+ (0, import_nestjs_agent_core2.publishAgentRunFailed)({
986
562
  runId: ctx.runId,
987
563
  code: code2,
988
564
  message: detail
989
565
  });
990
- await (0, import_nestjs_agent_core3.settleDeadRun)(this.store, {
566
+ await (0, import_nestjs_agent_core2.settleDeadRun)(this.store, {
991
567
  runId: ctx.runId,
992
568
  threadId: input.threadId,
993
569
  failure: {
@@ -995,13 +571,13 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
995
571
  message: detail
996
572
  }
997
573
  });
998
- await (await hooks.openSink()).fail((0, import_nestjs_agent_core3.streamFailure)(error));
574
+ await (await hooks.openSink()).fail((0, import_nestjs_agent_core2.streamFailure)(error));
999
575
  throw error;
1000
576
  }
1001
577
  const message = error instanceof Error ? error.message : String(error);
1002
- const code = (0, import_nestjs_agent_core3.agentFailureCode)(error);
578
+ const code = (0, import_nestjs_agent_core2.agentFailureCode)(error);
1003
579
  this.logger.error(`agent run ${ctx.runId} failed (${code}): ${message}`);
1004
- (0, import_nestjs_agent_core3.publishAgentRunFailed)({
580
+ (0, import_nestjs_agent_core2.publishAgentRunFailed)({
1005
581
  runId: ctx.runId,
1006
582
  code,
1007
583
  message
@@ -1013,36 +589,37 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
1013
589
  errorCode: code,
1014
590
  errorMessage: message
1015
591
  });
1016
- await Promise.resolve(this.store.failUnsettledToolCalls?.(ctx.runId, import_nestjs_agent_core3.RUN_ENDED_BEFORE_TOOL_CALL)).catch(() => 0);
592
+ await Promise.resolve(this.store.failUnsettledToolCalls?.(ctx.runId, import_nestjs_agent_core2.RUN_ENDED_BEFORE_TOOL_CALL)).catch(() => 0);
1017
593
  });
1018
594
  const queueFrame2 = await this.advanceQueue(ctx, input, "failed", message);
1019
- await stepOf(ctx)("deactivate", () => (0, import_nestjs_agent_core3.releaseThreadRun)(this.store, input.threadId, ctx.runId));
595
+ await stepOf(ctx)("deactivate", () => (0, import_nestjs_agent_core2.releaseThreadRun)(this.store, input.threadId, ctx.runId));
1020
596
  await this.settleDetachedParent(ctx, input, {
1021
597
  status: "failed",
1022
598
  error: message
1023
599
  });
1024
600
  const writer = await hooks.openSink();
1025
601
  if (queueFrame2 !== void 0) {
1026
- await writer.write((0, import_nestjs_agent_core3.encodeStreamEvent)(queueFrame2));
602
+ await writer.write((0, import_nestjs_agent_core2.encodeStreamEvent)(queueFrame2));
1027
603
  }
1028
- await writer.fail((0, import_nestjs_agent_core3.streamFailure)(error));
604
+ await writer.fail((0, import_nestjs_agent_core2.streamFailure)(error));
1029
605
  throw error;
1030
606
  }
1031
607
  }
1032
608
  };
1033
- AgentRunWorkflow = _ts_decorate3([
1034
- (0, import_common3.Injectable)(),
609
+ AgentRunWorkflow = _ts_decorate2([
610
+ (0, import_common2.Injectable)(),
1035
611
  (0, import_nestjs_durable2.Workflow)({
1036
612
  name: "agent.run",
1037
613
  version: "1"
1038
614
  }),
1039
- _ts_param3(0, (0, import_common3.Inject)(import_nestjs_agent_core3.AGENT_DEPS_FACTORY)),
1040
- _ts_param3(1, (0, import_common3.Inject)(import_nestjs_agent_core3.AGENT_STORE)),
1041
- _ts_param3(2, (0, import_common3.Optional)()),
1042
- _ts_param3(2, (0, import_common3.Inject)(import_nestjs_durable2.RUN_GATEWAY)),
1043
- _ts_param3(3, (0, import_common3.Optional)()),
1044
- _ts_metadata3("design:type", Function),
1045
- _ts_metadata3("design:paramtypes", [
615
+ _ts_param2(0, (0, import_common2.Inject)(import_nestjs_agent_core2.AGENT_DEPS_FACTORY)),
616
+ _ts_param2(1, (0, import_common2.Inject)(import_nestjs_agent_core2.AGENT_STORE)),
617
+ _ts_param2(2, (0, import_common2.Optional)()),
618
+ _ts_param2(2, (0, import_common2.Inject)(import_nestjs_durable2.RUN_GATEWAY)),
619
+ _ts_param2(3, (0, import_common2.Optional)()),
620
+ _ts_param2(3, (0, import_common2.Inject)(AGENT_CHAT_QUEUE)),
621
+ _ts_metadata2("design:type", Function),
622
+ _ts_metadata2("design:paramtypes", [
1046
623
  typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
1047
624
  typeof AgentStore === "undefined" ? Object : AgentStore,
1048
625
  typeof RunGateway === "undefined" ? Object : RunGateway,
@@ -1056,13 +633,13 @@ __name(isSignalTimeout, "isSignalTimeout");
1056
633
 
1057
634
  // src/durable/durable-agent-runner.ts
1058
635
  var import_node_crypto = require("crypto");
1059
- var import_nestjs_agent_core5 = require("@dudousxd/nestjs-agent-core");
636
+ var import_nestjs_agent_core4 = require("@dudousxd/nestjs-agent-core");
1060
637
  var import_nestjs_durable3 = require("@dudousxd/nestjs-durable");
1061
638
  var import_nestjs_durable_core3 = require("@dudousxd/nestjs-durable-core");
1062
- var import_common4 = require("@nestjs/common");
639
+ var import_common3 = require("@nestjs/common");
1063
640
 
1064
641
  // src/in-process-sink.ts
1065
- var import_nestjs_agent_core4 = require("@dudousxd/nestjs-agent-core");
642
+ var import_nestjs_agent_core3 = require("@dudousxd/nestjs-agent-core");
1066
643
  var InProcessTokenStreamSink = class {
1067
644
  static {
1068
645
  __name(this, "InProcessTokenStreamSink");
@@ -1117,7 +694,7 @@ var InProcessTokenStreamSink = class {
1117
694
  }
1118
695
  if (buf.ended) {
1119
696
  if (buf.failure !== void 0) {
1120
- throw new import_nestjs_agent_core4.AgentStreamError(buf.failure);
697
+ throw new import_nestjs_agent_core3.AgentStreamError(buf.failure);
1121
698
  }
1122
699
  return;
1123
700
  }
@@ -1130,7 +707,7 @@ var InProcessTokenStreamSink = class {
1130
707
  };
1131
708
 
1132
709
  // src/durable/durable-agent-runner.ts
1133
- function _ts_decorate4(decorators, target, key, desc) {
710
+ function _ts_decorate3(decorators, target, key, desc) {
1134
711
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1135
712
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1136
713
  r = Reflect.decorate(decorators, target, key, desc);
@@ -1143,19 +720,19 @@ function _ts_decorate4(decorators, target, key, desc) {
1143
720
  }
1144
721
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1145
722
  }
1146
- __name(_ts_decorate4, "_ts_decorate");
1147
- function _ts_metadata4(metadataKey, metadataValue) {
723
+ __name(_ts_decorate3, "_ts_decorate");
724
+ function _ts_metadata3(metadataKey, metadataValue) {
1148
725
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1149
726
  return Reflect.metadata(metadataKey, metadataValue);
1150
727
  }
1151
- }
1152
- __name(_ts_metadata4, "_ts_metadata");
1153
- function _ts_param4(paramIndex, decorator) {
728
+ }
729
+ __name(_ts_metadata3, "_ts_metadata");
730
+ function _ts_param3(paramIndex, decorator) {
1154
731
  return function(target, key) {
1155
732
  decorator(target, key, paramIndex);
1156
733
  };
1157
734
  }
1158
- __name(_ts_param4, "_ts_param");
735
+ __name(_ts_param3, "_ts_param");
1159
736
  function threadOfRun(input) {
1160
737
  if (typeof input !== "object" || input === null || !("threadId" in input)) {
1161
738
  return void 0;
@@ -1176,7 +753,7 @@ var DurableAgentRunner = class _DurableAgentRunner {
1176
753
  store;
1177
754
  sink;
1178
755
  queue;
1179
- logger = new import_common4.Logger(_DurableAgentRunner.name);
756
+ logger = new import_common3.Logger(_DurableAgentRunner.name);
1180
757
  constructor(workflows, runs, store, sink, queue) {
1181
758
  this.workflows = workflows;
1182
759
  this.runs = runs;
@@ -1263,15 +840,15 @@ var DurableAgentRunner = class _DurableAgentRunner {
1263
840
  runId: nextRunId
1264
841
  }));
1265
842
  if (frame !== void 0) {
1266
- await writer.write((0, import_nestjs_agent_core5.encodeStreamEvent)(frame));
843
+ await writer.write((0, import_nestjs_agent_core4.encodeStreamEvent)(frame));
1267
844
  }
1268
845
  } catch (error) {
1269
846
  this.logger.error(`could not advance the queue of thread ${threadId} after cancelling ${runId}: ${error instanceof Error ? error.message : String(error)}`);
1270
847
  }
1271
848
  }
1272
- await (0, import_nestjs_agent_core5.releaseThreadRun)(this.store, threadId, runId);
849
+ await (0, import_nestjs_agent_core4.releaseThreadRun)(this.store, threadId, runId);
1273
850
  }
1274
- await writer.write((0, import_nestjs_agent_core5.encodeStreamEvent)({
851
+ await writer.write((0, import_nestjs_agent_core4.encodeStreamEvent)({
1275
852
  kind: "cancelled"
1276
853
  }));
1277
854
  await writer.end();
@@ -1298,14 +875,15 @@ var DurableAgentRunner = class _DurableAgentRunner {
1298
875
  }
1299
876
  }
1300
877
  };
1301
- DurableAgentRunner = _ts_decorate4([
1302
- (0, import_common4.Injectable)(),
1303
- _ts_param4(1, (0, import_common4.Inject)(import_nestjs_durable3.RUN_GATEWAY)),
1304
- _ts_param4(2, (0, import_common4.Inject)(import_nestjs_agent_core5.AGENT_STORE)),
1305
- _ts_param4(3, (0, import_common4.Inject)(import_nestjs_agent_core5.AGENT_SINK)),
1306
- _ts_param4(4, (0, import_common4.Optional)()),
1307
- _ts_metadata4("design:type", Function),
1308
- _ts_metadata4("design:paramtypes", [
878
+ DurableAgentRunner = _ts_decorate3([
879
+ (0, import_common3.Injectable)(),
880
+ _ts_param3(1, (0, import_common3.Inject)(import_nestjs_durable3.RUN_GATEWAY)),
881
+ _ts_param3(2, (0, import_common3.Inject)(import_nestjs_agent_core4.AGENT_STORE)),
882
+ _ts_param3(3, (0, import_common3.Inject)(import_nestjs_agent_core4.AGENT_SINK)),
883
+ _ts_param3(4, (0, import_common3.Optional)()),
884
+ _ts_param3(4, (0, import_common3.Inject)(AGENT_CHAT_QUEUE)),
885
+ _ts_metadata3("design:type", Function),
886
+ _ts_metadata3("design:paramtypes", [
1309
887
  typeof import_nestjs_durable3.WorkflowService === "undefined" ? Object : import_nestjs_durable3.WorkflowService,
1310
888
  typeof RunGateway === "undefined" ? Object : RunGateway,
1311
889
  typeof AgentStore === "undefined" ? Object : AgentStore,
@@ -1315,9 +893,9 @@ DurableAgentRunner = _ts_decorate4([
1315
893
  ], DurableAgentRunner);
1316
894
 
1317
895
  // src/durable/agent-durable.module.ts
1318
- var import_nestjs_agent_core6 = require("@dudousxd/nestjs-agent-core");
1319
- var import_common5 = require("@nestjs/common");
1320
- function _ts_decorate5(decorators, target, key, desc) {
896
+ var import_nestjs_agent_core5 = require("@dudousxd/nestjs-agent-core");
897
+ var import_common4 = require("@nestjs/common");
898
+ function _ts_decorate4(decorators, target, key, desc) {
1321
899
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1322
900
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1323
901
  r = Reflect.decorate(decorators, target, key, desc);
@@ -1330,12 +908,12 @@ function _ts_decorate5(decorators, target, key, desc) {
1330
908
  }
1331
909
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1332
910
  }
1333
- __name(_ts_decorate5, "_ts_decorate");
911
+ __name(_ts_decorate4, "_ts_decorate");
1334
912
  function runnerProviders() {
1335
913
  return [
1336
914
  DurableAgentRunner,
1337
915
  {
1338
- provide: import_nestjs_agent_core6.AGENT_DURABLE_RUNNER,
916
+ provide: import_nestjs_agent_core5.AGENT_DURABLE_RUNNER,
1339
917
  useExisting: DurableAgentRunner
1340
918
  }
1341
919
  ];
@@ -1346,15 +924,15 @@ var AgentDurableHttpModule = class AgentDurableHttpModule2 {
1346
924
  __name(this, "AgentDurableHttpModule");
1347
925
  }
1348
926
  };
1349
- AgentDurableHttpModule = _ts_decorate5([
1350
- (0, import_common5.Global)(),
1351
- (0, import_common5.Module)({
927
+ AgentDurableHttpModule = _ts_decorate4([
928
+ (0, import_common4.Global)(),
929
+ (0, import_common4.Module)({
1352
930
  providers: [
1353
931
  AgentRunWorkflow,
1354
932
  ...runnerProviders()
1355
933
  ],
1356
934
  exports: [
1357
- import_nestjs_agent_core6.AGENT_DURABLE_RUNNER,
935
+ import_nestjs_agent_core5.AGENT_DURABLE_RUNNER,
1358
936
  AgentRunWorkflow
1359
937
  ]
1360
938
  })
@@ -1384,16 +962,16 @@ var AgentDurableModule = class _AgentDurableModule {
1384
962
  };
1385
963
  }
1386
964
  };
1387
- AgentDurableModule = _ts_decorate5([
1388
- (0, import_common5.Global)(),
1389
- (0, import_common5.Module)({
965
+ AgentDurableModule = _ts_decorate4([
966
+ (0, import_common4.Global)(),
967
+ (0, import_common4.Module)({
1390
968
  providers: [
1391
969
  AgentRunWorkflow,
1392
970
  AgentRunSteps,
1393
971
  ...runnerProviders()
1394
972
  ],
1395
973
  exports: [
1396
- import_nestjs_agent_core6.AGENT_DURABLE_RUNNER,
974
+ import_nestjs_agent_core5.AGENT_DURABLE_RUNNER,
1397
975
  AgentRunWorkflow,
1398
976
  AgentRunSteps
1399
977
  ]
@@ -1405,8 +983,269 @@ var import_nestjs_agent_core31 = require("@dudousxd/nestjs-agent-core");
1405
983
  var import_common27 = require("@nestjs/common");
1406
984
  var import_core4 = require("@nestjs/core");
1407
985
 
1408
- // src/agent-deps.factory.ts
1409
- var import_nestjs_agent_core7 = require("@dudousxd/nestjs-agent-core");
986
+ // src/agent-deps.factory.ts
987
+ var import_nestjs_agent_core6 = require("@dudousxd/nestjs-agent-core");
988
+ var import_nestjs_agent_core7 = require("@dudousxd/nestjs-agent-core");
989
+ var import_common5 = require("@nestjs/common");
990
+ function _ts_decorate5(decorators, target, key, desc) {
991
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
992
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
993
+ r = Reflect.decorate(decorators, target, key, desc);
994
+ } else {
995
+ for (var i = decorators.length - 1; i >= 0; i--) {
996
+ if (d = decorators[i]) {
997
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
998
+ }
999
+ }
1000
+ }
1001
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1002
+ }
1003
+ __name(_ts_decorate5, "_ts_decorate");
1004
+ function _ts_metadata4(metadataKey, metadataValue) {
1005
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1006
+ return Reflect.metadata(metadataKey, metadataValue);
1007
+ }
1008
+ }
1009
+ __name(_ts_metadata4, "_ts_metadata");
1010
+ function _ts_param4(paramIndex, decorator) {
1011
+ return function(target, key) {
1012
+ decorator(target, key, paramIndex);
1013
+ };
1014
+ }
1015
+ __name(_ts_param4, "_ts_param");
1016
+ function delegateToolName(args) {
1017
+ const slug = args.target.replace(/[^a-zA-Z0-9]+/g, "_");
1018
+ return args.detached === true ? `start_${slug}` : `ask_${slug}`;
1019
+ }
1020
+ __name(delegateToolName, "delegateToolName");
1021
+ var AgentDepsFactory2 = class {
1022
+ static {
1023
+ __name(this, "AgentDepsFactory");
1024
+ }
1025
+ options;
1026
+ model;
1027
+ store;
1028
+ sink;
1029
+ rolesPolicy;
1030
+ registry;
1031
+ agents;
1032
+ promptContributors;
1033
+ pricingStore;
1034
+ skills;
1035
+ memory;
1036
+ constructor(options, model, store, sink, rolesPolicy, registry, agents, promptContributors, pricingStore, skills, memory) {
1037
+ this.options = options;
1038
+ this.model = model;
1039
+ this.store = store;
1040
+ this.sink = sink;
1041
+ this.rolesPolicy = rolesPolicy;
1042
+ this.registry = registry;
1043
+ this.agents = agents;
1044
+ this.promptContributors = promptContributors;
1045
+ this.pricingStore = pricingStore;
1046
+ this.skills = skills;
1047
+ this.memory = memory;
1048
+ }
1049
+ /** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */
1050
+ memoryConfig() {
1051
+ return this.memory;
1052
+ }
1053
+ /** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */
1054
+ skillsConfig() {
1055
+ return this.skills;
1056
+ }
1057
+ /**
1058
+ * The agent a turn uses when the caller names none: the explicit `defaultAgent` option, else the
1059
+ * sole registered `@Agent` when there is exactly one, else `'default'` (a bare assistant).
1060
+ */
1061
+ defaultAgentName() {
1062
+ if (this.options.defaultAgent !== void 0) {
1063
+ return this.options.defaultAgent;
1064
+ }
1065
+ const registered = this.agents.list();
1066
+ return registered.length === 1 ? registered[0]?.name ?? "default" : "default";
1067
+ }
1068
+ effectiveTools(definition) {
1069
+ if (definition === void 0) {
1070
+ return void 0;
1071
+ }
1072
+ const delegated = (definition.delegatesTo ?? []).map((edge) => {
1073
+ const { agent, detached } = (0, import_nestjs_agent_core6.normalizeDelegation)(edge);
1074
+ return delegateToolName({
1075
+ target: agent,
1076
+ detached
1077
+ });
1078
+ });
1079
+ if (definition.tools === void 0 && delegated.length === 0) {
1080
+ return void 0;
1081
+ }
1082
+ return [
1083
+ ...definition.tools ?? [],
1084
+ ...delegated
1085
+ ];
1086
+ }
1087
+ forAgent(agentName) {
1088
+ const name = agentName ?? this.defaultAgentName();
1089
+ const definition = this.agents.get(name);
1090
+ const toolAllowList = this.effectiveTools(definition);
1091
+ const followUpsCount = this.followUpsCount();
1092
+ const retrieval = this.options.retrieval;
1093
+ const historyPolicy = this.historyPolicy(definition);
1094
+ const ask = definition?.ask ?? this.options.ask;
1095
+ return {
1096
+ model: this.model,
1097
+ store: this.store,
1098
+ sink: this.sink,
1099
+ rolesPolicy: this.rolesPolicy,
1100
+ ...this.options.approvalPolicy !== void 0 ? {
1101
+ approvalPolicy: this.options.approvalPolicy
1102
+ } : {},
1103
+ registry: this.registry,
1104
+ promptContributors: this.promptContributors,
1105
+ systemPrompt: definition?.systemPrompt ?? this.options.systemPrompt ?? "You are a helpful assistant.",
1106
+ maxSteps: definition?.maxSteps ?? 8,
1107
+ ...definition?.maxDelegationDepth !== void 0 ? {
1108
+ maxDelegationDepth: definition.maxDelegationDepth
1109
+ } : {},
1110
+ ...definition?.maxAgentAppearances !== void 0 ? {
1111
+ maxAgentAppearances: definition.maxAgentAppearances
1112
+ } : {},
1113
+ ...definition?.modelId !== void 0 ? {
1114
+ modelId: definition.modelId
1115
+ } : {},
1116
+ ...this.pricingStore !== void 0 ? {
1117
+ pricingStore: this.pricingStore
1118
+ } : {},
1119
+ ...historyPolicy !== void 0 ? {
1120
+ historyPolicy
1121
+ } : {},
1122
+ inputProcessors: this.options.inputProcessors ?? [],
1123
+ outputProcessors: this.options.outputProcessors ?? [],
1124
+ ...definition?.outputSchema !== void 0 ? {
1125
+ outputSchema: definition.outputSchema
1126
+ } : {},
1127
+ ...definition?.outputRepairAttempts !== void 0 ? {
1128
+ outputRepairAttempts: definition.outputRepairAttempts
1129
+ } : {},
1130
+ ...definition?.intake !== void 0 ? {
1131
+ intake: definition.intake
1132
+ } : {},
1133
+ // Most specific wins, exactly as `historyPolicy` resolves: the agent's own `@Agent({ ask })`,
1134
+ // else the module-wide flag. Both are module config, so every process of a deployment agrees.
1135
+ ...ask === true ? {
1136
+ ask: true
1137
+ } : {},
1138
+ // Module-wide, never per-agent: a skill is a procedure, not a persona, and an agent that could
1139
+ // opt out of one would make the catalog depend on which agent a turn happened to select — a
1140
+ // per-turn fact the worker re-deriving the tool list cannot see.
1141
+ ...this.skills !== void 0 ? {
1142
+ skills: this.skills
1143
+ } : {},
1144
+ // Module-wide, never per-agent, for the same reason skills are: which memories a turn carries
1145
+ // cannot depend on which persona answered it, or the worker re-deriving a dispatched turn's
1146
+ // tool list would disagree with the loop about whether `remember` was offered.
1147
+ ...this.memory !== void 0 ? {
1148
+ memory: this.memory
1149
+ } : {},
1150
+ ...toolAllowList !== void 0 ? {
1151
+ toolAllowList
1152
+ } : {},
1153
+ ...this.options.toolTimeoutMs !== void 0 ? {
1154
+ toolTimeoutMs: this.options.toolTimeoutMs
1155
+ } : {},
1156
+ ...this.options.toolTransientRetry !== void 0 ? {
1157
+ toolTransientRetry: this.options.toolTransientRetry
1158
+ } : {},
1159
+ ...followUpsCount !== void 0 ? {
1160
+ followUpsCount
1161
+ } : {},
1162
+ ...retrieval?.mode === "inject" ? {
1163
+ retriever: retrieval.retriever,
1164
+ ...retrieval.topK !== void 0 ? {
1165
+ retrievalTopK: retrieval.topK
1166
+ } : {}
1167
+ } : {}
1168
+ };
1169
+ }
1170
+ /**
1171
+ * The ceiling on how much of a thread this agent's turns carry, most specific wins: the agent's
1172
+ * own `@Agent({ history })`, else a module-wide custom `historyPolicy`, else the module-wide
1173
+ * `history` window. Undefined → unbounded, the behaviour of a module that configures none.
1174
+ */
1175
+ historyPolicy(definition) {
1176
+ if (definition?.history !== void 0) {
1177
+ return this.window(definition.history);
1178
+ }
1179
+ if (this.options.historyPolicy !== void 0) {
1180
+ return this.options.historyPolicy;
1181
+ }
1182
+ return this.options.history === void 0 ? void 0 : this.window(this.options.history);
1183
+ }
1184
+ /** Build the built-in window policy from the declarative `{ maxMessages, maxTokens, summarize }`. */
1185
+ window(config) {
1186
+ return (0, import_nestjs_agent_core6.windowHistory)({
1187
+ ...config.maxMessages !== void 0 ? {
1188
+ maxMessages: config.maxMessages
1189
+ } : {},
1190
+ ...config.maxTokens !== void 0 ? {
1191
+ maxTokens: config.maxTokens
1192
+ } : {},
1193
+ // The shared module model, not a per-agent one: an agent's `modelId` is an accounting label,
1194
+ // and only one provider is ever bound.
1195
+ ...config.summarize === true ? {
1196
+ summarize: (0, import_nestjs_agent_core6.summarizeWithModel)(this.model)
1197
+ } : {}
1198
+ });
1199
+ }
1200
+ /** Normalize the `followUps` option (`true` → 3, `{ count }` → count) to a number, or undefined. */
1201
+ followUpsCount() {
1202
+ const followUps = this.options.followUps;
1203
+ if (followUps === true) {
1204
+ return 3;
1205
+ }
1206
+ if (typeof followUps === "object") {
1207
+ return followUps.count;
1208
+ }
1209
+ return void 0;
1210
+ }
1211
+ };
1212
+ AgentDepsFactory2 = _ts_decorate5([
1213
+ (0, import_common5.Injectable)(),
1214
+ _ts_param4(0, (0, import_common5.Inject)(import_nestjs_agent_core7.AGENT_OPTIONS)),
1215
+ _ts_param4(1, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_MODEL)),
1216
+ _ts_param4(2, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_STORE)),
1217
+ _ts_param4(3, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_SINK)),
1218
+ _ts_param4(4, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_ROLES_POLICY)),
1219
+ _ts_param4(5, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_TOOL_REGISTRY)),
1220
+ _ts_param4(6, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_REGISTRY)),
1221
+ _ts_param4(7, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_PROMPT_CONTRIBUTORS)),
1222
+ _ts_param4(8, (0, import_common5.Optional)()),
1223
+ _ts_param4(8, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_PRICING_STORE)),
1224
+ _ts_param4(9, (0, import_common5.Optional)()),
1225
+ _ts_param4(9, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_SKILLS)),
1226
+ _ts_param4(10, (0, import_common5.Optional)()),
1227
+ _ts_param4(10, (0, import_common5.Inject)(import_nestjs_agent_core6.AGENT_MEMORY)),
1228
+ _ts_metadata4("design:type", Function),
1229
+ _ts_metadata4("design:paramtypes", [
1230
+ typeof AgentModuleOptions === "undefined" ? Object : AgentModuleOptions,
1231
+ typeof ModelProvider === "undefined" ? Object : ModelProvider,
1232
+ typeof AgentStore === "undefined" ? Object : AgentStore,
1233
+ typeof TokenStreamSink === "undefined" ? Object : TokenStreamSink,
1234
+ typeof RolesPolicy === "undefined" ? Object : RolesPolicy,
1235
+ typeof import_nestjs_agent_core6.ToolRegistry === "undefined" ? Object : import_nestjs_agent_core6.ToolRegistry,
1236
+ typeof import_nestjs_agent_core6.AgentRegistry === "undefined" ? Object : import_nestjs_agent_core6.AgentRegistry,
1237
+ Array,
1238
+ Object,
1239
+ Object,
1240
+ Object
1241
+ ])
1242
+ ], AgentDepsFactory2);
1243
+
1244
+ // src/agent.service.ts
1245
+ var import_nestjs_agent_core10 = require("@dudousxd/nestjs-agent-core");
1246
+ var import_common8 = require("@nestjs/common");
1247
+
1248
+ // src/queue/chat-queue.service.ts
1410
1249
  var import_nestjs_agent_core8 = require("@dudousxd/nestjs-agent-core");
1411
1250
  var import_common6 = require("@nestjs/common");
1412
1251
  function _ts_decorate6(decorators, target, key, desc) {
@@ -1435,237 +1274,403 @@ function _ts_param5(paramIndex, decorator) {
1435
1274
  };
1436
1275
  }
1437
1276
  __name(_ts_param5, "_ts_param");
1438
- function delegateToolName(args) {
1439
- const slug = args.target.replace(/[^a-zA-Z0-9]+/g, "_");
1440
- return args.detached === true ? `start_${slug}` : `ask_${slug}`;
1441
- }
1442
- __name(delegateToolName, "delegateToolName");
1443
- var AgentDepsFactory2 = class {
1277
+ var MAX_DRAIN_ATTEMPTS = 8;
1278
+ var ChatQueueService2 = class _ChatQueueService {
1444
1279
  static {
1445
- __name(this, "AgentDepsFactory");
1280
+ __name(this, "ChatQueueService");
1446
1281
  }
1447
- options;
1448
- model;
1449
1282
  store;
1450
1283
  sink;
1451
- rolesPolicy;
1452
- registry;
1453
- agents;
1454
- promptContributors;
1455
- pricingStore;
1456
- skills;
1457
- memory;
1458
- constructor(options, model, store, sink, rolesPolicy, registry, agents, promptContributors, pricingStore, skills, memory) {
1459
- this.options = options;
1460
- this.model = model;
1284
+ quotaProvider;
1285
+ options;
1286
+ staging;
1287
+ logger = new import_common6.Logger(_ChatQueueService.name);
1288
+ /**
1289
+ * Runs this process claimed a thread for and has not handed to a runner yet. A holder in here is
1290
+ * alive whatever the runner says — it simply has not registered the run yet.
1291
+ */
1292
+ starting = /* @__PURE__ */ new Set();
1293
+ constructor(store, sink, quotaProvider, options, staging) {
1461
1294
  this.store = store;
1462
1295
  this.sink = sink;
1463
- this.rolesPolicy = rolesPolicy;
1464
- this.registry = registry;
1465
- this.agents = agents;
1466
- this.promptContributors = promptContributors;
1467
- this.pricingStore = pricingStore;
1468
- this.skills = skills;
1469
- this.memory = memory;
1296
+ this.quotaProvider = quotaProvider;
1297
+ this.options = options;
1298
+ this.staging = staging;
1470
1299
  }
1471
- /** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */
1472
- memoryConfig() {
1473
- return this.memory;
1300
+ /** Whether the bound store can hold a queue. Without one, a busy thread is not queued. */
1301
+ get supported() {
1302
+ return (0, import_nestjs_agent_core8.isChatQueueStore)(this.store);
1474
1303
  }
1475
- /** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */
1476
- skillsConfig() {
1477
- return this.skills;
1304
+ /** The bound store as a queue store, or a 501 naming what is missing. */
1305
+ queueStore() {
1306
+ if (!(0, import_nestjs_agent_core8.isChatQueueStore)(this.store)) {
1307
+ throw new import_common6.NotImplementedException("Queueing messages requires an AgentStore that implements ChatQueueStore (enqueueMessage, listQueue, \u2026, claimActiveStream, releaseActiveStream); the bound store does not.");
1308
+ }
1309
+ return this.store;
1310
+ }
1311
+ async state(threadId) {
1312
+ const store = this.queueStore();
1313
+ const [items, paused] = await Promise.all([
1314
+ store.listQueue(threadId),
1315
+ store.queuePause(threadId)
1316
+ ]);
1317
+ return {
1318
+ items: items.map(import_nestjs_agent_core8.queuedMessageView),
1319
+ paused
1320
+ };
1478
1321
  }
1479
1322
  /**
1480
- * The agent a turn uses when the caller names none: the explicit `defaultAgent` option, else the
1481
- * sole registered `@Agent` when there is exactly one, else `'default'` (a bare assistant).
1323
+ * Whether `holder` is still running. A run this process is about to start is; otherwise the
1324
+ * runner decides, and a runner that cannot tell says yes.
1482
1325
  */
1483
- defaultAgentName() {
1484
- if (this.options.defaultAgent !== void 0) {
1485
- return this.options.defaultAgent;
1326
+ async isAlive(holder, runner) {
1327
+ if (this.starting.has(holder)) {
1328
+ return true;
1329
+ }
1330
+ if (typeof runner.isRunActive !== "function") {
1331
+ return true;
1332
+ }
1333
+ try {
1334
+ return await runner.isRunActive(holder);
1335
+ } catch {
1336
+ return true;
1486
1337
  }
1487
- const registered = this.agents.list();
1488
- return registered.length === 1 ? registered[0]?.name ?? "default" : "default";
1489
1338
  }
1490
- effectiveTools(definition) {
1491
- if (definition === void 0) {
1339
+ /**
1340
+ * The run holding `threadId`, or `null` when it is free — a holder the runner reports dead counts
1341
+ * as free, and is returned as `stale` so the caller can claim over it.
1342
+ */
1343
+ async holder(threadId, runner) {
1344
+ const holder = await this.queueStore().activeRunForThread(threadId);
1345
+ if (holder === null) {
1346
+ return {
1347
+ live: null,
1348
+ stale: null
1349
+ };
1350
+ }
1351
+ return await this.isAlive(holder, runner) ? {
1352
+ live: holder,
1353
+ stale: null
1354
+ } : {
1355
+ live: null,
1356
+ stale: holder
1357
+ };
1358
+ }
1359
+ /**
1360
+ * Decide what follows a TOP-LEVEL run that is settling on `threadId`, and move the thread there:
1361
+ * hand it to the next queued message (claimed and popped here, started by the caller), or pause
1362
+ * the queue, or release the thread. Call it BEFORE the run's terminal frame, so a client reading
1363
+ * the stream learns what comes next from the `queue` frame, and so the thread is already free
1364
+ * when the client sees the run end.
1365
+ *
1366
+ * A no-op returning `{}` on a store without a queue.
1367
+ */
1368
+ async plan(args) {
1369
+ if (!(0, import_nestjs_agent_core8.isChatQueueStore)(this.store)) {
1370
+ return {};
1371
+ }
1372
+ const store = this.store;
1373
+ const { threadId, outcome } = args;
1374
+ if (await store.activeRunForThread(threadId) !== args.runId) {
1375
+ return {};
1376
+ }
1377
+ let holding = args.runId;
1378
+ for (let attempt = 0; attempt < MAX_DRAIN_ATTEMPTS; attempt += 1) {
1379
+ const items = await store.listQueue(threadId);
1380
+ const head = items[0];
1381
+ if (head === void 0) {
1382
+ if (holding !== null) {
1383
+ await store.releaseActiveStream(threadId, holding);
1384
+ holding = null;
1385
+ continue;
1386
+ }
1387
+ return {};
1388
+ }
1389
+ let pause = await store.queuePause(threadId);
1390
+ if (pause === null) {
1391
+ const reason = pauseReasonFor(outcome, head);
1392
+ if (reason !== null) {
1393
+ pause = {
1394
+ reason,
1395
+ ...outcome === "failed" && args.error !== void 0 ? {
1396
+ message: args.error
1397
+ } : {},
1398
+ at: (/* @__PURE__ */ new Date()).toISOString()
1399
+ };
1400
+ await store.setQueuePause(threadId, pause);
1401
+ }
1402
+ }
1403
+ if (pause === null) {
1404
+ const blocked = await this.quotaBlock(head.actor);
1405
+ if (blocked !== null) {
1406
+ pause = {
1407
+ reason: "quota_exceeded",
1408
+ message: blocked,
1409
+ at: (/* @__PURE__ */ new Date()).toISOString()
1410
+ };
1411
+ await store.setQueuePause(threadId, pause);
1412
+ }
1413
+ }
1414
+ if (pause !== null) {
1415
+ if (holding !== null) {
1416
+ await store.releaseActiveStream(threadId, holding);
1417
+ }
1418
+ return {
1419
+ frame: queueFrame(items, pause)
1420
+ };
1421
+ }
1422
+ const claimed = await store.claimActiveStream(threadId, head.id, holding !== null ? {
1423
+ replacing: holding
1424
+ } : {});
1425
+ if (!claimed) {
1426
+ return {};
1427
+ }
1428
+ holding = head.id;
1429
+ if (!await store.removeQueuedMessage(head.id)) {
1430
+ await store.releaseActiveStream(threadId, head.id);
1431
+ holding = null;
1432
+ continue;
1433
+ }
1434
+ const next = {
1435
+ runId: head.id,
1436
+ messageId: head.id,
1437
+ input: await this.inputFor(head)
1438
+ };
1439
+ return {
1440
+ next,
1441
+ frame: queueFrame(items.slice(1), null, {
1442
+ messageId: head.id,
1443
+ runId: head.id
1444
+ })
1445
+ };
1446
+ }
1447
+ if (holding !== null) {
1448
+ await store.releaseActiveStream(threadId, holding);
1449
+ }
1450
+ return {};
1451
+ }
1452
+ /**
1453
+ * {@link plan}, then start what it picked with `start`. What an in-process settle (the inline
1454
+ * runner, a durable cancel issued outside a workflow) calls; answers the frame to write.
1455
+ */
1456
+ async handoff(args, start) {
1457
+ const plan = await this.plan(args);
1458
+ if (plan.next === void 0) {
1459
+ return plan.frame;
1460
+ }
1461
+ return await this.launch(args.threadId, plan.next, start) ? plan.frame : this.pausedFrame(args.threadId);
1462
+ }
1463
+ /**
1464
+ * Start the head of an IDLE thread's queue — after a send queued behind a run that turned out to
1465
+ * be gone, after a resume, after a stale holder. Does nothing while a live run holds the thread
1466
+ * (its settle drains) or while the queue is paused. Answers the started run's id, if any.
1467
+ */
1468
+ async kick(threadId, runner) {
1469
+ if (!(0, import_nestjs_agent_core8.isChatQueueStore)(this.store)) {
1492
1470
  return void 0;
1493
1471
  }
1494
- const delegated = (definition.delegatesTo ?? []).map((edge) => {
1495
- const { agent, detached } = (0, import_nestjs_agent_core7.normalizeDelegation)(edge);
1496
- return delegateToolName({
1497
- target: agent,
1498
- detached
1499
- });
1472
+ const { live, stale } = await this.holder(threadId, runner);
1473
+ if (live !== null) {
1474
+ return void 0;
1475
+ }
1476
+ if (stale !== null) {
1477
+ this.logger.warn(`thread ${threadId} was held by run ${stale}, which is no longer running`);
1478
+ }
1479
+ const plan = await this.plan({
1480
+ threadId,
1481
+ runId: stale,
1482
+ outcome: "completed"
1500
1483
  });
1501
- if (definition.tools === void 0 && delegated.length === 0) {
1484
+ if (plan.next === void 0) {
1502
1485
  return void 0;
1503
1486
  }
1504
- return [
1505
- ...definition.tools ?? [],
1506
- ...delegated
1507
- ];
1487
+ const started = await this.launch(threadId, plan.next, (input, runId) => runner.start(input, {
1488
+ runId
1489
+ }));
1490
+ if (started && plan.frame !== void 0) {
1491
+ await this.write(plan.next.runId, plan.frame);
1492
+ }
1493
+ return started ? plan.next.runId : void 0;
1494
+ }
1495
+ /**
1496
+ * Start a turn the thread is already claimed for. On failure the message goes back to the head of
1497
+ * the queue, the queue pauses (`start_failed`), and the claim is released — nothing is lost and
1498
+ * nothing is left holding the thread.
1499
+ */
1500
+ async launch(threadId, next, start) {
1501
+ this.starting.add(next.runId);
1502
+ try {
1503
+ await start(next.input, next.runId);
1504
+ return true;
1505
+ } catch (error) {
1506
+ const message = error instanceof Error ? error.message : String(error);
1507
+ this.logger.error(`queued message ${next.messageId} could not start: ${message}`);
1508
+ await this.restore(threadId, next, "start_failed", message);
1509
+ return false;
1510
+ } finally {
1511
+ this.starting.delete(next.runId);
1512
+ }
1508
1513
  }
1509
- forAgent(agentName) {
1510
- const name = agentName ?? this.defaultAgentName();
1511
- const definition = this.agents.get(name);
1512
- const toolAllowList = this.effectiveTools(definition);
1513
- const followUpsCount = this.followUpsCount();
1514
- const retrieval = this.options.retrieval;
1515
- const historyPolicy = this.historyPolicy(definition);
1516
- const ask = definition?.ask ?? this.options.ask;
1517
- return {
1518
- model: this.model,
1519
- store: this.store,
1520
- sink: this.sink,
1521
- rolesPolicy: this.rolesPolicy,
1522
- ...this.options.approvalPolicy !== void 0 ? {
1523
- approvalPolicy: this.options.approvalPolicy
1524
- } : {},
1525
- registry: this.registry,
1526
- promptContributors: this.promptContributors,
1527
- systemPrompt: definition?.systemPrompt ?? this.options.systemPrompt ?? "You are a helpful assistant.",
1528
- maxSteps: definition?.maxSteps ?? 8,
1529
- ...definition?.maxDelegationDepth !== void 0 ? {
1530
- maxDelegationDepth: definition.maxDelegationDepth
1531
- } : {},
1532
- ...definition?.maxAgentAppearances !== void 0 ? {
1533
- maxAgentAppearances: definition.maxAgentAppearances
1534
- } : {},
1535
- ...definition?.modelId !== void 0 ? {
1536
- modelId: definition.modelId
1537
- } : {},
1538
- ...this.pricingStore !== void 0 ? {
1539
- pricingStore: this.pricingStore
1540
- } : {},
1541
- ...historyPolicy !== void 0 ? {
1542
- historyPolicy
1543
- } : {},
1544
- inputProcessors: this.options.inputProcessors ?? [],
1545
- outputProcessors: this.options.outputProcessors ?? [],
1546
- ...definition?.outputSchema !== void 0 ? {
1547
- outputSchema: definition.outputSchema
1548
- } : {},
1549
- ...definition?.outputRepairAttempts !== void 0 ? {
1550
- outputRepairAttempts: definition.outputRepairAttempts
1551
- } : {},
1552
- ...definition?.intake !== void 0 ? {
1553
- intake: definition.intake
1554
- } : {},
1555
- // Most specific wins, exactly as `historyPolicy` resolves: the agent's own `@Agent({ ask })`,
1556
- // else the module-wide flag. Both are module config, so every process of a deployment agrees.
1557
- ...ask === true ? {
1558
- ask: true
1559
- } : {},
1560
- // Module-wide, never per-agent: a skill is a procedure, not a persona, and an agent that could
1561
- // opt out of one would make the catalog depend on which agent a turn happened to select — a
1562
- // per-turn fact the worker re-deriving the tool list cannot see.
1563
- ...this.skills !== void 0 ? {
1564
- skills: this.skills
1565
- } : {},
1566
- // Module-wide, never per-agent, for the same reason skills are: which memories a turn carries
1567
- // cannot depend on which persona answered it, or the worker re-deriving a dispatched turn's
1568
- // tool list would disagree with the loop about whether `remember` was offered.
1569
- ...this.memory !== void 0 ? {
1570
- memory: this.memory
1571
- } : {},
1572
- ...toolAllowList !== void 0 ? {
1573
- toolAllowList
1574
- } : {},
1575
- ...this.options.toolTimeoutMs !== void 0 ? {
1576
- toolTimeoutMs: this.options.toolTimeoutMs
1514
+ /** Put a turn that never started back at the head of its queue, paused, and free the thread. */
1515
+ async restore(threadId, next, reason, message) {
1516
+ const store = this.queueStore();
1517
+ const { input } = next;
1518
+ await store.enqueueMessage({
1519
+ threadId,
1520
+ actor: input.actor,
1521
+ content: input.userText,
1522
+ at: "head",
1523
+ ...input.attachments !== void 0 ? {
1524
+ attachments: input.attachments
1577
1525
  } : {},
1578
- ...this.options.toolTransientRetry !== void 0 ? {
1579
- toolTransientRetry: this.options.toolTransientRetry
1526
+ ...input.agentName !== void 0 ? {
1527
+ agentName: input.agentName
1580
1528
  } : {},
1581
- ...followUpsCount !== void 0 ? {
1582
- followUpsCount
1529
+ ...input.model !== void 0 ? {
1530
+ model: input.model
1583
1531
  } : {},
1584
- ...retrieval?.mode === "inject" ? {
1585
- retriever: retrieval.retriever,
1586
- ...retrieval.topK !== void 0 ? {
1587
- retrievalTopK: retrieval.topK
1588
- } : {}
1532
+ ...input.pageContext !== void 0 ? {
1533
+ pageContext: input.pageContext
1589
1534
  } : {}
1535
+ });
1536
+ await store.setQueuePause(threadId, {
1537
+ reason,
1538
+ message,
1539
+ at: (/* @__PURE__ */ new Date()).toISOString()
1540
+ });
1541
+ await store.releaseActiveStream(threadId, next.runId);
1542
+ }
1543
+ /** A `queue` frame with the thread's current state. */
1544
+ async pausedFrame(threadId) {
1545
+ return {
1546
+ kind: "queue",
1547
+ queue: await this.state(threadId)
1590
1548
  };
1591
1549
  }
1592
1550
  /**
1593
- * The ceiling on how much of a thread this agent's turns carry, most specific wins: the agent's
1594
- * own `@Agent({ history })`, else a module-wide custom `historyPolicy`, else the module-wide
1595
- * `history` window. Undefined → unbounded, the behaviour of a module that configures none.
1551
+ * Tell whoever is watching the thread that its queue changed: a `queue` frame into the stream of
1552
+ * the run holding it. Best-effort — a thread nobody is streaming has no one to tell, and the next
1553
+ * read of the thread carries the queue anyway.
1596
1554
  */
1597
- historyPolicy(definition) {
1598
- if (definition?.history !== void 0) {
1599
- return this.window(definition.history);
1555
+ async publish(threadId) {
1556
+ const state = await this.state(threadId);
1557
+ const holder = await this.queueStore().activeRunForThread(threadId);
1558
+ if (holder !== null) {
1559
+ await this.write(holder, {
1560
+ kind: "queue",
1561
+ queue: state
1562
+ }).catch((error) => {
1563
+ this.logger.warn(`could not publish the queue of thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`);
1564
+ });
1600
1565
  }
1601
- if (this.options.historyPolicy !== void 0) {
1602
- return this.options.historyPolicy;
1566
+ return state;
1567
+ }
1568
+ async write(runId, frame) {
1569
+ const writer = await this.sink.open(runId);
1570
+ await writer.write((0, import_nestjs_agent_core8.encodeStreamEvent)(frame));
1571
+ }
1572
+ /** Why `actor` may not start a turn now (the quota message), or `null`. */
1573
+ async quotaBlock(actor) {
1574
+ if (this.options?.quota === void 0 || this.quotaProvider === void 0) {
1575
+ return null;
1576
+ }
1577
+ try {
1578
+ const { blocked } = await this.quotaProvider.report({
1579
+ actor
1580
+ });
1581
+ if (blocked === void 0) {
1582
+ return null;
1583
+ }
1584
+ return blocked.reason ?? `The ${blocked.period === "day" ? "daily" : "monthly"} quota is used up`;
1585
+ } catch {
1586
+ return null;
1603
1587
  }
1604
- return this.options.history === void 0 ? void 0 : this.window(this.options.history);
1605
1588
  }
1606
- /** Build the built-in window policy from the declarative `{ maxMessages, maxTokens, summarize }`. */
1607
- window(config) {
1608
- return (0, import_nestjs_agent_core7.windowHistory)({
1609
- ...config.maxMessages !== void 0 ? {
1610
- maxMessages: config.maxMessages
1589
+ /**
1590
+ * The turn a queued message starts: everything it was queued with, today's date, and its
1591
+ * attachments' urls minted afresh — the ones stored at enqueue time may have expired while it
1592
+ * waited. An attachment the staging store no longer resolves keeps its stored url.
1593
+ */
1594
+ async inputFor(message) {
1595
+ const attachments = await this.freshAttachments(message.actor, message.attachments ?? []);
1596
+ return {
1597
+ threadId: message.threadId,
1598
+ actor: message.actor,
1599
+ userText: message.content,
1600
+ day: utcDay(),
1601
+ ...message.agentName !== void 0 ? {
1602
+ agentName: message.agentName
1611
1603
  } : {},
1612
- ...config.maxTokens !== void 0 ? {
1613
- maxTokens: config.maxTokens
1604
+ ...attachments.length > 0 ? {
1605
+ attachments
1614
1606
  } : {},
1615
- // The shared module model, not a per-agent one: an agent's `modelId` is an accounting label,
1616
- // and only one provider is ever bound.
1617
- ...config.summarize === true ? {
1618
- summarize: (0, import_nestjs_agent_core7.summarizeWithModel)(this.model)
1607
+ ...message.pageContext !== void 0 ? {
1608
+ pageContext: message.pageContext
1609
+ } : {},
1610
+ ...message.model !== void 0 ? {
1611
+ model: message.model
1619
1612
  } : {}
1620
- });
1613
+ };
1621
1614
  }
1622
- /** Normalize the `followUps` option (`true` → 3, `{ count }` → count) to a number, or undefined. */
1623
- followUpsCount() {
1624
- const followUps = this.options.followUps;
1625
- if (followUps === true) {
1626
- return 3;
1627
- }
1628
- if (typeof followUps === "object") {
1629
- return followUps.count;
1615
+ async freshAttachments(actor, attachments) {
1616
+ const staging = this.staging;
1617
+ if (attachments.length === 0 || staging === void 0 || typeof staging.resolve !== "function") {
1618
+ return attachments;
1630
1619
  }
1631
- return void 0;
1620
+ return Promise.all(attachments.map(async (attachment) => {
1621
+ try {
1622
+ return await staging.resolve({
1623
+ mediaId: attachment.mediaId,
1624
+ actor
1625
+ }) ?? attachment;
1626
+ } catch {
1627
+ return attachment;
1628
+ }
1629
+ }));
1632
1630
  }
1633
1631
  };
1634
- AgentDepsFactory2 = _ts_decorate6([
1632
+ ChatQueueService2 = _ts_decorate6([
1635
1633
  (0, import_common6.Injectable)(),
1636
- _ts_param5(0, (0, import_common6.Inject)(import_nestjs_agent_core8.AGENT_OPTIONS)),
1637
- _ts_param5(1, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_MODEL)),
1638
- _ts_param5(2, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_STORE)),
1639
- _ts_param5(3, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_SINK)),
1640
- _ts_param5(4, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_ROLES_POLICY)),
1641
- _ts_param5(5, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_TOOL_REGISTRY)),
1642
- _ts_param5(6, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_REGISTRY)),
1643
- _ts_param5(7, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_PROMPT_CONTRIBUTORS)),
1644
- _ts_param5(8, (0, import_common6.Optional)()),
1645
- _ts_param5(8, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_PRICING_STORE)),
1646
- _ts_param5(9, (0, import_common6.Optional)()),
1647
- _ts_param5(9, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_SKILLS)),
1648
- _ts_param5(10, (0, import_common6.Optional)()),
1649
- _ts_param5(10, (0, import_common6.Inject)(import_nestjs_agent_core7.AGENT_MEMORY)),
1634
+ _ts_param5(0, (0, import_common6.Inject)(import_nestjs_agent_core8.AGENT_STORE)),
1635
+ _ts_param5(1, (0, import_common6.Inject)(import_nestjs_agent_core8.AGENT_SINK)),
1636
+ _ts_param5(2, (0, import_common6.Optional)()),
1637
+ _ts_param5(2, (0, import_common6.Inject)(import_nestjs_agent_core8.AGENT_QUOTA_PROVIDER)),
1638
+ _ts_param5(3, (0, import_common6.Optional)()),
1639
+ _ts_param5(3, (0, import_common6.Inject)(import_nestjs_agent_core8.AGENT_OPTIONS)),
1640
+ _ts_param5(4, (0, import_common6.Optional)()),
1641
+ _ts_param5(4, (0, import_common6.Inject)(import_nestjs_agent_core8.AGENT_ATTACHMENT_STAGING)),
1650
1642
  _ts_metadata5("design:type", Function),
1651
1643
  _ts_metadata5("design:paramtypes", [
1652
- typeof AgentModuleOptions === "undefined" ? Object : AgentModuleOptions,
1653
- typeof ModelProvider === "undefined" ? Object : ModelProvider,
1654
1644
  typeof AgentStore === "undefined" ? Object : AgentStore,
1655
1645
  typeof TokenStreamSink === "undefined" ? Object : TokenStreamSink,
1656
- typeof RolesPolicy === "undefined" ? Object : RolesPolicy,
1657
- typeof import_nestjs_agent_core7.ToolRegistry === "undefined" ? Object : import_nestjs_agent_core7.ToolRegistry,
1658
- typeof import_nestjs_agent_core7.AgentRegistry === "undefined" ? Object : import_nestjs_agent_core7.AgentRegistry,
1659
- Array,
1660
- Object,
1661
- Object,
1662
- Object
1646
+ typeof QuotaProvider === "undefined" ? Object : QuotaProvider,
1647
+ typeof Pick === "undefined" ? Object : Pick,
1648
+ typeof AttachmentStagingStore === "undefined" ? Object : AttachmentStagingStore
1663
1649
  ])
1664
- ], AgentDepsFactory2);
1665
-
1666
- // src/agent.service.ts
1667
- var import_nestjs_agent_core10 = require("@dudousxd/nestjs-agent-core");
1668
- var import_common8 = require("@nestjs/common");
1650
+ ], ChatQueueService2);
1651
+ function pauseReasonFor(outcome, head) {
1652
+ if (outcome === "failed") {
1653
+ return "run_failed";
1654
+ }
1655
+ if (outcome === "cancelled" && head.interrupt !== true) {
1656
+ return "cancelled";
1657
+ }
1658
+ return null;
1659
+ }
1660
+ __name(pauseReasonFor, "pauseReasonFor");
1661
+ function queueFrame(items, paused, started) {
1662
+ return {
1663
+ kind: "queue",
1664
+ queue: {
1665
+ items: items.map(import_nestjs_agent_core8.queuedMessageView),
1666
+ paused
1667
+ },
1668
+ ...started !== void 0 ? {
1669
+ started
1670
+ } : {}
1671
+ };
1672
+ }
1673
+ __name(queueFrame, "queueFrame");
1669
1674
 
1670
1675
  // src/run-not-active.exception.ts
1671
1676
  var import_nestjs_agent_core9 = require("@dudousxd/nestjs-agent-core");
@@ -2722,7 +2727,7 @@ AgentService = _ts_decorate7([
2722
2727
  typeof ModelCatalog === "undefined" ? Object : ModelCatalog,
2723
2728
  typeof QuotaProvider === "undefined" ? Object : QuotaProvider,
2724
2729
  typeof Pick === "undefined" ? Object : Pick,
2725
- typeof ChatQueueService === "undefined" ? Object : ChatQueueService
2730
+ typeof ChatQueueService2 === "undefined" ? Object : ChatQueueService2
2726
2731
  ])
2727
2732
  ], AgentService);
2728
2733
 
@@ -5569,7 +5574,7 @@ InlineAgentRunner = _ts_decorate25([
5569
5574
  _ts_metadata24("design:paramtypes", [
5570
5575
  typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
5571
5576
  typeof AgentStore === "undefined" ? Object : AgentStore,
5572
- typeof ChatQueueService === "undefined" ? Object : ChatQueueService
5577
+ typeof ChatQueueService2 === "undefined" ? Object : ChatQueueService2
5573
5578
  ])
5574
5579
  ], InlineAgentRunner);
5575
5580
  function isThreadTurn2(input) {
@@ -5784,7 +5789,11 @@ function sharedProviders(durable) {
5784
5789
  SkillDiscoveryService,
5785
5790
  // The thread message queue — every surface, since both runners and the durable workflow settle
5786
5791
  // into it, and the chat routes enqueue into it.
5787
- ChatQueueService,
5792
+ ChatQueueService2,
5793
+ {
5794
+ provide: AGENT_CHAT_QUEUE,
5795
+ useExisting: ChatQueueService2
5796
+ },
5788
5797
  InlineAgentRunner,
5789
5798
  AgentService,
5790
5799
  // Bound ALWAYS (durable or inline) — the console's cross-thread approvals inbox routes decisions
@@ -5846,7 +5855,8 @@ function exportsFor() {
5846
5855
  import_nestjs_agent_core31.AGENT_DEPS_FACTORY,
5847
5856
  AgentDepsFactory2,
5848
5857
  AgentService,
5849
- ChatQueueService,
5858
+ ChatQueueService2,
5859
+ AGENT_CHAT_QUEUE,
5850
5860
  InlineAgentRunner,
5851
5861
  import_nestjs_agent_core31.AGENT_APPROVAL_PORT
5852
5862
  ];