@dudousxd/nestjs-agent 1.19.1 → 1.19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/durable/index.cjs +144 -10
- package/dist/durable/index.cjs.map +1 -1
- package/dist/durable/index.d.cts +40 -4
- package/dist/durable/index.d.ts +40 -4
- package/dist/durable/index.js +150 -16
- package/dist/durable/index.js.map +1 -1
- package/dist/index.cjs +7 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/durable/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AgentStore, AgentRunInput, AgentLoopResult, LlmStepEnvelope, BufferedModelTurnResult, ToolStepEnvelope, AgentRunner, TokenStreamSink, AgentRunStartOptions, HumanReply } from '@dudousxd/nestjs-agent-core';
|
|
2
|
+
import { WorkflowService } from '@dudousxd/nestjs-durable';
|
|
2
3
|
import { RunGateway, WorkflowCtx } from '@dudousxd/nestjs-durable-core';
|
|
3
4
|
import { A as AgentDepsFactory, C as ChatQueueService, a as AgentSurface, b as AgentModuleOptions } from '../chat-queue.service-CKZkjlMK.cjs';
|
|
4
|
-
import { WorkflowService } from '@dudousxd/nestjs-durable';
|
|
5
5
|
import { DynamicModule } from '@nestjs/common';
|
|
6
6
|
import '@standard-schema/spec';
|
|
7
7
|
|
|
@@ -23,8 +23,30 @@ declare class AgentRunWorkflow {
|
|
|
23
23
|
private readonly store;
|
|
24
24
|
private readonly runs?;
|
|
25
25
|
private readonly queue?;
|
|
26
|
+
private readonly workflows?;
|
|
26
27
|
private readonly logger;
|
|
27
|
-
constructor(factory: AgentDepsFactory, store: AgentStore, runs?: RunGateway | undefined, queue?: ChatQueueService | undefined);
|
|
28
|
+
constructor(factory: AgentDepsFactory, store: AgentStore, runs?: RunGateway | undefined, queue?: ChatQueueService | undefined, workflows?: WorkflowService | undefined);
|
|
29
|
+
/**
|
|
30
|
+
* Start a detached delegation as a TOP-LEVEL run, under an id derived from this run and the call.
|
|
31
|
+
*
|
|
32
|
+
* Not `ctx.startChild`, because the runtime treats a `spawn:` child as part of its parent: a Stop
|
|
33
|
+
* on the parent cascades to every run it spawned. A detached run is exactly the one the person did
|
|
34
|
+
* NOT ask to stop — they stopped the turn they were watching, and the work it handed off is meant
|
|
35
|
+
* to outlive that turn (it is meant to outlive it finishing, after all). Cascaded, it died parked
|
|
36
|
+
* on its approval, where its body never runs again, so nothing settled the delegation and the card
|
|
37
|
+
* said "started" for ever. The agent-level edge stays: the child's input still carries
|
|
38
|
+
* `parentRunId`, which is what the run rows record.
|
|
39
|
+
*
|
|
40
|
+
* Journaled as one `detach:<toolCallId>` localStep whose body runs outside the ambient workflow
|
|
41
|
+
* ctx (so the start goes to the engine and writes no position in this run). Its recorded result
|
|
42
|
+
* keeps a replay from starting it again, and a body re-run after a crash between the start and
|
|
43
|
+
* the checkpoint asks for the same id, which the runtime answers with the run it already has.
|
|
44
|
+
* The child is stamped with this run's namespace, as `ctx.startChild` would have stamped it, so an
|
|
45
|
+
* operator re-driving a tenant's turn does not move its delegate off that tenant's workers.
|
|
46
|
+
*/
|
|
47
|
+
private startDetached;
|
|
48
|
+
/** The namespace this run is stamped with, where the runtime can say. */
|
|
49
|
+
private namespaceOf;
|
|
28
50
|
/**
|
|
29
51
|
* Move the thread past this settling turn — to the next queued message, started here as a
|
|
30
52
|
* fire-and-forget `ctx.startChild` under the message's own id, or to a paused/empty queue — and
|
|
@@ -188,7 +210,21 @@ declare class DurableAgentRunner implements AgentRunner {
|
|
|
188
210
|
*/
|
|
189
211
|
cancel(runId: string): Promise<void>;
|
|
190
212
|
/**
|
|
191
|
-
*
|
|
213
|
+
* Settle the delegation a DETACHED run was started for, once it has been stopped. A run parked on
|
|
214
|
+
* a human never runs its body again — the runtime settles it from outside — so the body's own
|
|
215
|
+
* `deliver:detached:unsettled` is not reached, and without this the card in the calling thread says
|
|
216
|
+
* "started" for ever. Settles once (see `settleUnsettledDelegation`), so a body that did observe
|
|
217
|
+
* the Stop and a run that had already answered are both left as they are. A no-op for any run
|
|
218
|
+
* that does not deliver into another thread.
|
|
219
|
+
*/
|
|
220
|
+
private settleCancelledDelegation;
|
|
221
|
+
/**
|
|
222
|
+
* A detached child the runtime cancelled along with its parent (a `spawn:` journaled before
|
|
223
|
+
* detached runs were started on their own): end it the way a Stop on its own id would have.
|
|
224
|
+
*/
|
|
225
|
+
private settleCascadedDetached;
|
|
226
|
+
/**
|
|
227
|
+
* What the runtime recorded for a run — the input it was started with (which thread it was streaming), its status and the runs it spawned — or `undefined` where the gateway cannot say.
|
|
192
228
|
*
|
|
193
229
|
* A read failure answers `undefined` instead of propagating, the same posture `AgentRunWorkflow`
|
|
194
230
|
* takes for its own cancel observation: failing to ask is not an answer worth failing a cancel
|
|
@@ -197,7 +233,7 @@ declare class DurableAgentRunner implements AgentRunner {
|
|
|
197
233
|
* with a subscriber holding a stream that never settles, from the one call whose entire job is to
|
|
198
234
|
* make a run stop.
|
|
199
235
|
*/
|
|
200
|
-
private
|
|
236
|
+
private detailOf;
|
|
201
237
|
}
|
|
202
238
|
|
|
203
239
|
/**
|
package/dist/durable/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AgentStore, AgentRunInput, AgentLoopResult, LlmStepEnvelope, BufferedModelTurnResult, ToolStepEnvelope, AgentRunner, TokenStreamSink, AgentRunStartOptions, HumanReply } from '@dudousxd/nestjs-agent-core';
|
|
2
|
+
import { WorkflowService } from '@dudousxd/nestjs-durable';
|
|
2
3
|
import { RunGateway, WorkflowCtx } from '@dudousxd/nestjs-durable-core';
|
|
3
4
|
import { A as AgentDepsFactory, C as ChatQueueService, a as AgentSurface, b as AgentModuleOptions } from '../chat-queue.service-CKZkjlMK.js';
|
|
4
|
-
import { WorkflowService } from '@dudousxd/nestjs-durable';
|
|
5
5
|
import { DynamicModule } from '@nestjs/common';
|
|
6
6
|
import '@standard-schema/spec';
|
|
7
7
|
|
|
@@ -23,8 +23,30 @@ declare class AgentRunWorkflow {
|
|
|
23
23
|
private readonly store;
|
|
24
24
|
private readonly runs?;
|
|
25
25
|
private readonly queue?;
|
|
26
|
+
private readonly workflows?;
|
|
26
27
|
private readonly logger;
|
|
27
|
-
constructor(factory: AgentDepsFactory, store: AgentStore, runs?: RunGateway | undefined, queue?: ChatQueueService | undefined);
|
|
28
|
+
constructor(factory: AgentDepsFactory, store: AgentStore, runs?: RunGateway | undefined, queue?: ChatQueueService | undefined, workflows?: WorkflowService | undefined);
|
|
29
|
+
/**
|
|
30
|
+
* Start a detached delegation as a TOP-LEVEL run, under an id derived from this run and the call.
|
|
31
|
+
*
|
|
32
|
+
* Not `ctx.startChild`, because the runtime treats a `spawn:` child as part of its parent: a Stop
|
|
33
|
+
* on the parent cascades to every run it spawned. A detached run is exactly the one the person did
|
|
34
|
+
* NOT ask to stop — they stopped the turn they were watching, and the work it handed off is meant
|
|
35
|
+
* to outlive that turn (it is meant to outlive it finishing, after all). Cascaded, it died parked
|
|
36
|
+
* on its approval, where its body never runs again, so nothing settled the delegation and the card
|
|
37
|
+
* said "started" for ever. The agent-level edge stays: the child's input still carries
|
|
38
|
+
* `parentRunId`, which is what the run rows record.
|
|
39
|
+
*
|
|
40
|
+
* Journaled as one `detach:<toolCallId>` localStep whose body runs outside the ambient workflow
|
|
41
|
+
* ctx (so the start goes to the engine and writes no position in this run). Its recorded result
|
|
42
|
+
* keeps a replay from starting it again, and a body re-run after a crash between the start and
|
|
43
|
+
* the checkpoint asks for the same id, which the runtime answers with the run it already has.
|
|
44
|
+
* The child is stamped with this run's namespace, as `ctx.startChild` would have stamped it, so an
|
|
45
|
+
* operator re-driving a tenant's turn does not move its delegate off that tenant's workers.
|
|
46
|
+
*/
|
|
47
|
+
private startDetached;
|
|
48
|
+
/** The namespace this run is stamped with, where the runtime can say. */
|
|
49
|
+
private namespaceOf;
|
|
28
50
|
/**
|
|
29
51
|
* Move the thread past this settling turn — to the next queued message, started here as a
|
|
30
52
|
* fire-and-forget `ctx.startChild` under the message's own id, or to a paused/empty queue — and
|
|
@@ -188,7 +210,21 @@ declare class DurableAgentRunner implements AgentRunner {
|
|
|
188
210
|
*/
|
|
189
211
|
cancel(runId: string): Promise<void>;
|
|
190
212
|
/**
|
|
191
|
-
*
|
|
213
|
+
* Settle the delegation a DETACHED run was started for, once it has been stopped. A run parked on
|
|
214
|
+
* a human never runs its body again — the runtime settles it from outside — so the body's own
|
|
215
|
+
* `deliver:detached:unsettled` is not reached, and without this the card in the calling thread says
|
|
216
|
+
* "started" for ever. Settles once (see `settleUnsettledDelegation`), so a body that did observe
|
|
217
|
+
* the Stop and a run that had already answered are both left as they are. A no-op for any run
|
|
218
|
+
* that does not deliver into another thread.
|
|
219
|
+
*/
|
|
220
|
+
private settleCancelledDelegation;
|
|
221
|
+
/**
|
|
222
|
+
* A detached child the runtime cancelled along with its parent (a `spawn:` journaled before
|
|
223
|
+
* detached runs were started on their own): end it the way a Stop on its own id would have.
|
|
224
|
+
*/
|
|
225
|
+
private settleCascadedDetached;
|
|
226
|
+
/**
|
|
227
|
+
* What the runtime recorded for a run — the input it was started with (which thread it was streaming), its status and the runs it spawned — or `undefined` where the gateway cannot say.
|
|
192
228
|
*
|
|
193
229
|
* A read failure answers `undefined` instead of propagating, the same posture `AgentRunWorkflow`
|
|
194
230
|
* takes for its own cancel observation: failing to ask is not an answer worth failing a cancel
|
|
@@ -197,7 +233,7 @@ declare class DurableAgentRunner implements AgentRunner {
|
|
|
197
233
|
* with a subscriber holding a stream that never settles, from the one call whose entire job is to
|
|
198
234
|
* make a run stop.
|
|
199
235
|
*/
|
|
200
|
-
private
|
|
236
|
+
private detailOf;
|
|
201
237
|
}
|
|
202
238
|
|
|
203
239
|
/**
|
package/dist/durable/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
3
3
|
|
|
4
4
|
// src/durable/agent-run.workflow.ts
|
|
5
5
|
import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY2, AGENT_STORE, RUN_ENDED_BEFORE_TOOL_CALL, RunCancelledError, agentFailureCode, encodeStreamEvent as encodeStreamEvent2, isReplayIntegrityError, publishAgentRunFailed, releaseThreadRun, runAgentLoop, settleAll, settleDeadRun, settleUnsettledDelegation, streamFailure } from "@dudousxd/nestjs-agent-core";
|
|
6
|
-
import { RUN_GATEWAY, Workflow } from "@dudousxd/nestjs-durable";
|
|
6
|
+
import { RUN_GATEWAY, Workflow, WorkflowService } from "@dudousxd/nestjs-durable";
|
|
7
7
|
import { isWorkflowControlFlowSignal } from "@dudousxd/nestjs-durable-core";
|
|
8
8
|
import { Inject as Inject2, Injectable as Injectable2, Logger, Optional } from "@nestjs/common";
|
|
9
9
|
|
|
@@ -15,10 +15,16 @@ __name(utcDay, "utcDay");
|
|
|
15
15
|
function childSinkWriter(writer) {
|
|
16
16
|
return {
|
|
17
17
|
write: /* @__PURE__ */ __name((chunk) => writer.write(chunk), "write"),
|
|
18
|
+
// The top-level run owns end/fail — but what the child wrote must not be held back past it.
|
|
18
19
|
end: /* @__PURE__ */ __name(async () => {
|
|
20
|
+
await writer.flush?.();
|
|
19
21
|
}, "end"),
|
|
20
22
|
fail: /* @__PURE__ */ __name(async () => {
|
|
21
|
-
|
|
23
|
+
await writer.flush?.();
|
|
24
|
+
}, "fail"),
|
|
25
|
+
flush: /* @__PURE__ */ __name(async () => {
|
|
26
|
+
await writer.flush?.();
|
|
27
|
+
}, "flush")
|
|
22
28
|
};
|
|
23
29
|
}
|
|
24
30
|
__name(childSinkWriter, "childSinkWriter");
|
|
@@ -248,12 +254,60 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
|
|
|
248
254
|
store;
|
|
249
255
|
runs;
|
|
250
256
|
queue;
|
|
257
|
+
workflows;
|
|
251
258
|
logger = new Logger(_AgentRunWorkflow.name);
|
|
252
|
-
constructor(factory, store, runs, queue) {
|
|
259
|
+
constructor(factory, store, runs, queue, workflows) {
|
|
253
260
|
this.factory = factory;
|
|
254
261
|
this.store = store;
|
|
255
262
|
this.runs = runs;
|
|
256
263
|
this.queue = queue;
|
|
264
|
+
this.workflows = workflows;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Start a detached delegation as a TOP-LEVEL run, under an id derived from this run and the call.
|
|
268
|
+
*
|
|
269
|
+
* Not `ctx.startChild`, because the runtime treats a `spawn:` child as part of its parent: a Stop
|
|
270
|
+
* on the parent cascades to every run it spawned. A detached run is exactly the one the person did
|
|
271
|
+
* NOT ask to stop — they stopped the turn they were watching, and the work it handed off is meant
|
|
272
|
+
* to outlive that turn (it is meant to outlive it finishing, after all). Cascaded, it died parked
|
|
273
|
+
* on its approval, where its body never runs again, so nothing settled the delegation and the card
|
|
274
|
+
* said "started" for ever. The agent-level edge stays: the child's input still carries
|
|
275
|
+
* `parentRunId`, which is what the run rows record.
|
|
276
|
+
*
|
|
277
|
+
* Journaled as one `detach:<toolCallId>` localStep whose body runs outside the ambient workflow
|
|
278
|
+
* ctx (so the start goes to the engine and writes no position in this run). Its recorded result
|
|
279
|
+
* keeps a replay from starting it again, and a body re-run after a crash between the start and
|
|
280
|
+
* the checkpoint asks for the same id, which the runtime answers with the run it already has.
|
|
281
|
+
* The child is stamped with this run's namespace, as `ctx.startChild` would have stamped it, so an
|
|
282
|
+
* operator re-driving a tenant's turn does not move its delegate off that tenant's workers.
|
|
283
|
+
*/
|
|
284
|
+
startDetached(ctx, toolCallId2, childInput) {
|
|
285
|
+
return stepOf(ctx)(`detach:${toolCallId2}`, async () => {
|
|
286
|
+
const workflows = this.workflows;
|
|
287
|
+
if (workflows === void 0) {
|
|
288
|
+
throw new Error("A detached delegation needs WorkflowService (DurableModule) to start its run, and none is bound.");
|
|
289
|
+
}
|
|
290
|
+
const childRunId = `${ctx.runId}.detached.${toolCallId2}`;
|
|
291
|
+
const namespace = await this.namespaceOf(ctx.runId);
|
|
292
|
+
try {
|
|
293
|
+
await workflows.start(_AgentRunWorkflow, childInput, childRunId, namespace !== void 0 ? {
|
|
294
|
+
namespace
|
|
295
|
+
} : void 0);
|
|
296
|
+
} catch (error) {
|
|
297
|
+
if (!isWorkflowControlFlowSignal(error)) {
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return childRunId;
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
/** The namespace this run is stamped with, where the runtime can say. */
|
|
305
|
+
async namespaceOf(runId) {
|
|
306
|
+
try {
|
|
307
|
+
return (await this.runs?.getRunDetail(runId))?.run.namespace;
|
|
308
|
+
} catch {
|
|
309
|
+
return void 0;
|
|
310
|
+
}
|
|
257
311
|
}
|
|
258
312
|
/**
|
|
259
313
|
* Move the thread past this settling turn — to the next queued message, started here as a
|
|
@@ -454,6 +508,10 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
|
|
|
454
508
|
// OWN runId, and that is what `runForToolCall` answers with.
|
|
455
509
|
// - `deliverTo` instead. The parent's tool result is a receipt, so the answer needs an
|
|
456
510
|
// address of its own, and by the time it exists nobody is holding one.
|
|
511
|
+
// - no runtime parent. A Stop on this turn must not reach the work it handed off, so the
|
|
512
|
+
// run is started on its own (`startDetached`), not as a `spawn:` child. A run that
|
|
513
|
+
// journaled the `spawn:` before this release replays it: `ctx.patched` answers false at a
|
|
514
|
+
// position that already holds one.
|
|
457
515
|
startAgent: /* @__PURE__ */ __name(async ({ agentName, task, toolCallId: toolCallId2 }) => {
|
|
458
516
|
const subThreadId = await stepOf(ctx)(`subthread:${agentName}`, async () => {
|
|
459
517
|
const thread = await this.store.createThread({
|
|
@@ -462,7 +520,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
|
|
|
462
520
|
});
|
|
463
521
|
return thread.id;
|
|
464
522
|
});
|
|
465
|
-
const
|
|
523
|
+
const childInput = {
|
|
466
524
|
agentName,
|
|
467
525
|
threadId: subThreadId,
|
|
468
526
|
actor: input.actor,
|
|
@@ -475,9 +533,14 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
|
|
|
475
533
|
threadId: input.threadId,
|
|
476
534
|
toolCallId: toolCallId2
|
|
477
535
|
}
|
|
478
|
-
}
|
|
536
|
+
};
|
|
537
|
+
if (!await ctx.patched("agent:detached-unlinked")) {
|
|
538
|
+
return {
|
|
539
|
+
runId: await ctx.startChild(_AgentRunWorkflow, childInput)
|
|
540
|
+
};
|
|
541
|
+
}
|
|
479
542
|
return {
|
|
480
|
-
runId:
|
|
543
|
+
runId: await this.startDetached(ctx, toolCallId2, childInput)
|
|
481
544
|
};
|
|
482
545
|
}, "startAgent"),
|
|
483
546
|
// The two long steps as engine-dispatched `ctx.step`s, so a turn isn't pinned to this
|
|
@@ -590,12 +653,14 @@ AgentRunWorkflow = _ts_decorate2([
|
|
|
590
653
|
_ts_param2(2, Inject2(RUN_GATEWAY)),
|
|
591
654
|
_ts_param2(3, Optional()),
|
|
592
655
|
_ts_param2(3, Inject2(AGENT_CHAT_QUEUE)),
|
|
656
|
+
_ts_param2(4, Optional()),
|
|
593
657
|
_ts_metadata2("design:type", Function),
|
|
594
658
|
_ts_metadata2("design:paramtypes", [
|
|
595
659
|
typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
|
|
596
660
|
typeof AgentStore === "undefined" ? Object : AgentStore,
|
|
597
661
|
typeof RunGateway === "undefined" ? Object : RunGateway,
|
|
598
|
-
typeof ChatQueueService === "undefined" ? Object : ChatQueueService
|
|
662
|
+
typeof ChatQueueService === "undefined" ? Object : ChatQueueService,
|
|
663
|
+
typeof WorkflowService === "undefined" ? Object : WorkflowService
|
|
599
664
|
])
|
|
600
665
|
], AgentRunWorkflow);
|
|
601
666
|
function isSignalTimeout(error) {
|
|
@@ -605,8 +670,8 @@ __name(isSignalTimeout, "isSignalTimeout");
|
|
|
605
670
|
|
|
606
671
|
// src/durable/durable-agent-runner.ts
|
|
607
672
|
import { randomUUID } from "crypto";
|
|
608
|
-
import { AGENT_SINK, AGENT_STORE as AGENT_STORE2, encodeStreamEvent as encodeStreamEvent3, releaseThreadRun as releaseThreadRun2 } from "@dudousxd/nestjs-agent-core";
|
|
609
|
-
import { RUN_GATEWAY as RUN_GATEWAY2, WorkflowService } from "@dudousxd/nestjs-durable";
|
|
673
|
+
import { AGENT_SINK, AGENT_STORE as AGENT_STORE2, encodeStreamEvent as encodeStreamEvent3, releaseThreadRun as releaseThreadRun2, settleUnsettledDelegation as settleUnsettledDelegation2 } from "@dudousxd/nestjs-agent-core";
|
|
674
|
+
import { RUN_GATEWAY as RUN_GATEWAY2, WorkflowService as WorkflowService2 } from "@dudousxd/nestjs-durable";
|
|
610
675
|
import { isWorkflowControlFlowSignal as isWorkflowControlFlowSignal2 } from "@dudousxd/nestjs-durable-core";
|
|
611
676
|
import { Inject as Inject3, Injectable as Injectable3, Logger as Logger2, Optional as Optional2 } from "@nestjs/common";
|
|
612
677
|
|
|
@@ -716,6 +781,20 @@ function isThreadTurn(input) {
|
|
|
716
781
|
return typeof input === "object" && input !== null && input.sinkRunId === void 0 && input.deliverTo === void 0;
|
|
717
782
|
}
|
|
718
783
|
__name(isThreadTurn, "isThreadTurn");
|
|
784
|
+
function deliveryOf(input) {
|
|
785
|
+
if (typeof input !== "object" || input === null) {
|
|
786
|
+
return void 0;
|
|
787
|
+
}
|
|
788
|
+
const { deliverTo, agentName } = input;
|
|
789
|
+
if (typeof deliverTo !== "object" || deliverTo === null || typeof deliverTo.threadId !== "string" || typeof deliverTo.toolCallId !== "string") {
|
|
790
|
+
return void 0;
|
|
791
|
+
}
|
|
792
|
+
return {
|
|
793
|
+
delivery: deliverTo,
|
|
794
|
+
agent: typeof agentName === "string" ? agentName : "default"
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
__name(deliveryOf, "deliveryOf");
|
|
719
798
|
var DurableAgentRunner = class _DurableAgentRunner {
|
|
720
799
|
static {
|
|
721
800
|
__name(this, "DurableAgentRunner");
|
|
@@ -795,11 +874,16 @@ var DurableAgentRunner = class _DurableAgentRunner {
|
|
|
795
874
|
*/
|
|
796
875
|
async cancel(runId) {
|
|
797
876
|
this.logger.log(`cancelling agent run ${runId}`);
|
|
798
|
-
const
|
|
877
|
+
const detail = await this.detailOf(runId);
|
|
878
|
+
const input = detail?.run.input;
|
|
799
879
|
const threadId = threadOfRun(input);
|
|
800
880
|
await this.runs.cancel(runId, {
|
|
801
881
|
compensate: true
|
|
802
882
|
});
|
|
883
|
+
await this.settleCancelledDelegation(runId, input);
|
|
884
|
+
for (const childId of detail?.children ?? []) {
|
|
885
|
+
await this.settleCascadedDetached(childId);
|
|
886
|
+
}
|
|
803
887
|
const writer = await this.sink.open(runId);
|
|
804
888
|
if (threadId !== void 0) {
|
|
805
889
|
if (this.queue?.supported === true && isThreadTurn(input)) {
|
|
@@ -830,7 +914,57 @@ var DurableAgentRunner = class _DurableAgentRunner {
|
|
|
830
914
|
});
|
|
831
915
|
}
|
|
832
916
|
/**
|
|
833
|
-
*
|
|
917
|
+
* Settle the delegation a DETACHED run was started for, once it has been stopped. A run parked on
|
|
918
|
+
* a human never runs its body again — the runtime settles it from outside — so the body's own
|
|
919
|
+
* `deliver:detached:unsettled` is not reached, and without this the card in the calling thread says
|
|
920
|
+
* "started" for ever. Settles once (see `settleUnsettledDelegation`), so a body that did observe
|
|
921
|
+
* the Stop and a run that had already answered are both left as they are. A no-op for any run
|
|
922
|
+
* that does not deliver into another thread.
|
|
923
|
+
*/
|
|
924
|
+
async settleCancelledDelegation(runId, input) {
|
|
925
|
+
const target = deliveryOf(input);
|
|
926
|
+
if (target === void 0) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
try {
|
|
930
|
+
await settleUnsettledDelegation2({
|
|
931
|
+
store: this.store,
|
|
932
|
+
delivery: target.delivery,
|
|
933
|
+
agent: target.agent,
|
|
934
|
+
runId,
|
|
935
|
+
status: "cancelled"
|
|
936
|
+
});
|
|
937
|
+
} catch (error) {
|
|
938
|
+
this.logger.error(`could not settle the delegation of cancelled run ${runId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* A detached child the runtime cancelled along with its parent (a `spawn:` journaled before
|
|
943
|
+
* detached runs were started on their own): end it the way a Stop on its own id would have.
|
|
944
|
+
*/
|
|
945
|
+
async settleCascadedDetached(childId) {
|
|
946
|
+
const child = await this.detailOf(childId);
|
|
947
|
+
const status = child?.run.status;
|
|
948
|
+
if (child === void 0 || deliveryOf(child.run.input) === void 0 || status !== "cancelled" && status !== "cancelling") {
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
const subThreadId = threadOfRun(child.run.input);
|
|
952
|
+
if (subThreadId !== void 0) {
|
|
953
|
+
await releaseThreadRun2(this.store, subThreadId, childId);
|
|
954
|
+
}
|
|
955
|
+
await this.settleCancelledDelegation(childId, child.run.input);
|
|
956
|
+
const writer = await this.sink.open(childId);
|
|
957
|
+
await writer.write(encodeStreamEvent3({
|
|
958
|
+
kind: "cancelled"
|
|
959
|
+
}));
|
|
960
|
+
await writer.end();
|
|
961
|
+
await this.store.recordRunEnd?.({
|
|
962
|
+
runId: childId,
|
|
963
|
+
status: "cancelled"
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* What the runtime recorded for a run — the input it was started with (which thread it was streaming), its status and the runs it spawned — or `undefined` where the gateway cannot say.
|
|
834
968
|
*
|
|
835
969
|
* A read failure answers `undefined` instead of propagating, the same posture `AgentRunWorkflow`
|
|
836
970
|
* takes for its own cancel observation: failing to ask is not an answer worth failing a cancel
|
|
@@ -839,9 +973,9 @@ var DurableAgentRunner = class _DurableAgentRunner {
|
|
|
839
973
|
* with a subscriber holding a stream that never settles, from the one call whose entire job is to
|
|
840
974
|
* make a run stop.
|
|
841
975
|
*/
|
|
842
|
-
async
|
|
976
|
+
async detailOf(runId) {
|
|
843
977
|
try {
|
|
844
|
-
return
|
|
978
|
+
return await this.runs.getRunDetail(runId) ?? void 0;
|
|
845
979
|
} catch {
|
|
846
980
|
return void 0;
|
|
847
981
|
}
|
|
@@ -856,7 +990,7 @@ DurableAgentRunner = _ts_decorate3([
|
|
|
856
990
|
_ts_param3(4, Inject3(AGENT_CHAT_QUEUE)),
|
|
857
991
|
_ts_metadata3("design:type", Function),
|
|
858
992
|
_ts_metadata3("design:paramtypes", [
|
|
859
|
-
typeof
|
|
993
|
+
typeof WorkflowService2 === "undefined" ? Object : WorkflowService2,
|
|
860
994
|
typeof RunGateway === "undefined" ? Object : RunGateway,
|
|
861
995
|
typeof AgentStore === "undefined" ? Object : AgentStore,
|
|
862
996
|
typeof TokenStreamSink === "undefined" ? Object : TokenStreamSink,
|
|
@@ -5094,7 +5228,7 @@ var LedgerQuotaProvider = class {
|
|
|
5094
5228
|
};
|
|
5095
5229
|
|
|
5096
5230
|
// src/runner/inline-agent-runner.ts
|
|
5097
|
-
import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY6, AGENT_STORE as AGENT_STORE6, RUN_ENDED_BEFORE_TOOL_CALL as RUN_ENDED_BEFORE_TOOL_CALL2, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, encodeStreamEvent as encodeStreamEvent5, publishAgentRunFailed as publishAgentRunFailed2, releaseThreadRun as releaseThreadRun3, runAgentLoop as runAgentLoop2, settleAll as settleAll2, settleUnsettledDelegation as
|
|
5231
|
+
import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY6, AGENT_STORE as AGENT_STORE6, RUN_ENDED_BEFORE_TOOL_CALL as RUN_ENDED_BEFORE_TOOL_CALL2, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, encodeStreamEvent as encodeStreamEvent5, publishAgentRunFailed as publishAgentRunFailed2, releaseThreadRun as releaseThreadRun3, runAgentLoop as runAgentLoop2, settleAll as settleAll2, settleUnsettledDelegation as settleUnsettledDelegation3, streamFailure as streamFailure3 } from "@dudousxd/nestjs-agent-core";
|
|
5098
5232
|
import { Inject as Inject23, Injectable as Injectable11, Logger as Logger7, Optional as Optional10 } from "@nestjs/common";
|
|
5099
5233
|
function _ts_decorate25(decorators, target, key, desc) {
|
|
5100
5234
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -5479,7 +5613,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
|
|
|
5479
5613
|
}
|
|
5480
5614
|
});
|
|
5481
5615
|
await Promise.resolve(this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL2)).catch(() => 0);
|
|
5482
|
-
await
|
|
5616
|
+
await settleUnsettledDelegation3({
|
|
5483
5617
|
store: this.store,
|
|
5484
5618
|
delivery: deliverTo,
|
|
5485
5619
|
agent: agentName,
|