@dudousxd/nestjs-agent 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/durable/index.cjs +40 -3
- package/dist/durable/index.cjs.map +1 -1
- package/dist/durable/index.d.cts +7 -0
- package/dist/durable/index.d.ts +7 -0
- package/dist/durable/index.js +46 -9
- package/dist/durable/index.js.map +1 -1
- package/dist/index.cjs +25 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +26 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/durable/index.d.cts
CHANGED
|
@@ -83,6 +83,13 @@ interface DispatchedLlmInput extends LlmStepEnvelope {
|
|
|
83
83
|
interface DispatchedToolInput extends ToolStepEnvelope {
|
|
84
84
|
toolCallId: string;
|
|
85
85
|
toolType: 'read' | 'action';
|
|
86
|
+
/**
|
|
87
|
+
* Where a component the tool pushes (`ctx.emitUi`) streams live — the same routing as
|
|
88
|
+
* {@link DispatchedLlmInput}. Absent on a task enqueued by a workflow that predates it: the
|
|
89
|
+
* components are then still collected and persisted, just not streamed.
|
|
90
|
+
*/
|
|
91
|
+
sinkRunId?: string;
|
|
92
|
+
childSink?: boolean;
|
|
86
93
|
}
|
|
87
94
|
/**
|
|
88
95
|
* The two long steps every turn dispatches as routed remote steps (`AgentRunSteps.llm` /
|
package/dist/durable/index.d.ts
CHANGED
|
@@ -83,6 +83,13 @@ interface DispatchedLlmInput extends LlmStepEnvelope {
|
|
|
83
83
|
interface DispatchedToolInput extends ToolStepEnvelope {
|
|
84
84
|
toolCallId: string;
|
|
85
85
|
toolType: 'read' | 'action';
|
|
86
|
+
/**
|
|
87
|
+
* Where a component the tool pushes (`ctx.emitUi`) streams live — the same routing as
|
|
88
|
+
* {@link DispatchedLlmInput}. Absent on a task enqueued by a workflow that predates it: the
|
|
89
|
+
* components are then still collected and persisted, just not streamed.
|
|
90
|
+
*/
|
|
91
|
+
sinkRunId?: string;
|
|
92
|
+
childSink?: boolean;
|
|
86
93
|
}
|
|
87
94
|
/**
|
|
88
95
|
* The two long steps every turn dispatches as routed remote steps (`AgentRunSteps.llm` /
|
package/dist/durable/index.js
CHANGED
|
@@ -24,7 +24,7 @@ function childSinkWriter(writer) {
|
|
|
24
24
|
__name(childSinkWriter, "childSinkWriter");
|
|
25
25
|
|
|
26
26
|
// src/durable/agent-run.steps.ts
|
|
27
|
-
import { AGENT_DEPS_FACTORY, createFrameBuffer, invokeWithTransientRetry, observeTurnFrames, publishAgentToolRetry, stampToolKinds, traceLlmTurn, traceToolExecution, withAskTool, withMemoryTool, withSkillTool, withToolTimeout, withTurnFrames } from "@dudousxd/nestjs-agent-core";
|
|
27
|
+
import { AGENT_DEPS_FACTORY, createFrameBuffer, createUiCollector, encodeStreamEvent, invokeWithTransientRetry, observeTurnFrames, publishAgentToolRetry, stampToolKinds, traceLlmTurn, traceToolExecution, withAskTool, withMemoryTool, withSkillTool, withToolTimeout, withTurnFrames, wrapToolStepOutput } from "@dudousxd/nestjs-agent-core";
|
|
28
28
|
import { Step } from "@dudousxd/nestjs-durable";
|
|
29
29
|
import { Inject, Injectable } from "@nestjs/common";
|
|
30
30
|
function _ts_decorate(decorators, target, key, desc) {
|
|
@@ -115,8 +115,15 @@ var AgentRunSteps = class {
|
|
|
115
115
|
if (deps.registry.spec(input.toolName)?.kind === "action" && input.toolType !== "action") {
|
|
116
116
|
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`);
|
|
117
117
|
}
|
|
118
|
+
const sinkRunId = input.sinkRunId;
|
|
119
|
+
let opened;
|
|
120
|
+
const ui = createUiCollector(input.toolCallId, sinkRunId === void 0 ? void 0 : async (event) => {
|
|
121
|
+
opened ??= Promise.resolve(deps.sink.open(sinkRunId)).then((writer) => input.childSink === true ? childSinkWriter(writer) : writer);
|
|
122
|
+
await (await opened).write(encodeStreamEvent(event));
|
|
123
|
+
});
|
|
118
124
|
const ctx = {
|
|
119
|
-
...input.ctx
|
|
125
|
+
...input.ctx,
|
|
126
|
+
emitUi: ui.emit
|
|
120
127
|
};
|
|
121
128
|
const localClassify = deps.toolTransientRetry !== false ? deps.toolTransientRetry?.classify : void 0;
|
|
122
129
|
const transientRetry = input.transientRetry === false ? false : {
|
|
@@ -126,11 +133,12 @@ var AgentRunSteps = class {
|
|
|
126
133
|
classify: localClassify
|
|
127
134
|
} : {}
|
|
128
135
|
};
|
|
129
|
-
|
|
136
|
+
const output = await traceToolExecution(input.ctx.runId, {
|
|
130
137
|
toolCallId: input.toolCallId,
|
|
131
138
|
toolName: input.toolName,
|
|
132
139
|
toolType: input.toolType
|
|
133
140
|
}, () => invokeWithTransientRetry(() => {
|
|
141
|
+
ui.restart();
|
|
134
142
|
const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy);
|
|
135
143
|
return input.timeoutMs !== void 0 ? withToolTimeout(invocation, input.timeoutMs, input.toolName) : invocation;
|
|
136
144
|
}, transientRetry, {
|
|
@@ -143,6 +151,7 @@ var AgentRunSteps = class {
|
|
|
143
151
|
});
|
|
144
152
|
}, "onRetry")
|
|
145
153
|
}));
|
|
154
|
+
return input.collectUi === true ? wrapToolStepOutput(output, ui.components()) : output;
|
|
146
155
|
}
|
|
147
156
|
};
|
|
148
157
|
_ts_decorate([
|
|
@@ -386,7 +395,10 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
|
|
|
386
395
|
dispatchTool: /* @__PURE__ */ __name((call, envelope) => ctx.step(AgentRunSteps.prototype.tool, {
|
|
387
396
|
...envelope,
|
|
388
397
|
toolCallId: call.id,
|
|
389
|
-
toolType: call.kind === "action" ? "action" : "read"
|
|
398
|
+
toolType: call.kind === "action" ? "action" : "read",
|
|
399
|
+
// Where `ctx.emitUi` streams from the worker — the llm step's routing.
|
|
400
|
+
sinkRunId,
|
|
401
|
+
childSink: input.sinkRunId !== void 0
|
|
390
402
|
}), "dispatchTool")
|
|
391
403
|
} : {}
|
|
392
404
|
};
|
|
@@ -471,7 +483,7 @@ __name(isSignalTimeout, "isSignalTimeout");
|
|
|
471
483
|
|
|
472
484
|
// src/durable/durable-agent-runner.ts
|
|
473
485
|
import { randomUUID } from "crypto";
|
|
474
|
-
import { AGENT_SINK, AGENT_STORE as AGENT_STORE2, encodeStreamEvent } from "@dudousxd/nestjs-agent-core";
|
|
486
|
+
import { AGENT_SINK, AGENT_STORE as AGENT_STORE2, encodeStreamEvent as encodeStreamEvent2 } from "@dudousxd/nestjs-agent-core";
|
|
475
487
|
import { RUN_GATEWAY as RUN_GATEWAY2, WorkflowService } from "@dudousxd/nestjs-durable";
|
|
476
488
|
import { isWorkflowControlFlowSignal as isWorkflowControlFlowSignal2 } from "@dudousxd/nestjs-durable-core";
|
|
477
489
|
import { Inject as Inject3, Injectable as Injectable3, Logger } from "@nestjs/common";
|
|
@@ -650,7 +662,7 @@ var DurableAgentRunner = class _DurableAgentRunner {
|
|
|
650
662
|
await this.store.setActiveStream(threadId, null);
|
|
651
663
|
}
|
|
652
664
|
const writer = await this.sink.open(runId);
|
|
653
|
-
await writer.write(
|
|
665
|
+
await writer.write(encodeStreamEvent2({
|
|
654
666
|
kind: "cancelled"
|
|
655
667
|
}));
|
|
656
668
|
await writer.end();
|
|
@@ -1048,7 +1060,7 @@ AgentDepsFactory2 = _ts_decorate5([
|
|
|
1048
1060
|
], AgentDepsFactory2);
|
|
1049
1061
|
|
|
1050
1062
|
// src/agent.service.ts
|
|
1051
|
-
import { AGENT_ATTACHMENT_STAGING, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY3, AGENT_QUOTA_STORE as AGENT_QUOTA_STORE2, AGENT_RUNNER, AGENT_STORE as AGENT_STORE4, REQUESTER_APPROVER, mayDecideApproval } from "@dudousxd/nestjs-agent-core";
|
|
1063
|
+
import { AGENT_ATTACHMENT_STAGING, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY3, AGENT_QUOTA_STORE as AGENT_QUOTA_STORE2, AGENT_RUNNER, AGENT_STORE as AGENT_STORE4, REQUESTER_APPROVER, mayDecideApproval, readElicitationQuestions, validateElicitationAnswer } from "@dudousxd/nestjs-agent-core";
|
|
1052
1064
|
import { BadRequestException, ForbiddenException, GoneException, Inject as Inject5, Injectable as Injectable5, NotFoundException, NotImplementedException, Optional as Optional3 } from "@nestjs/common";
|
|
1053
1065
|
function _ts_decorate6(decorators, target, key, desc) {
|
|
1054
1066
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -1224,6 +1236,7 @@ var AgentService = class {
|
|
|
1224
1236
|
*/
|
|
1225
1237
|
async answer(actor, toolCallId2, answers2 = {}) {
|
|
1226
1238
|
await this.assertOwnsToolCall(actor, toolCallId2);
|
|
1239
|
+
await this.assertAnswersFit(toolCallId2, answers2);
|
|
1227
1240
|
const reply = {
|
|
1228
1241
|
answers: answers2,
|
|
1229
1242
|
answeredByRef: actor.id
|
|
@@ -1492,6 +1505,27 @@ var AgentService = class {
|
|
|
1492
1505
|
}
|
|
1493
1506
|
}
|
|
1494
1507
|
/**
|
|
1508
|
+
* Check a reply against the questions it answers before it is signalled: every submitted value a
|
|
1509
|
+
* question's own rules accept (a typed input's type, bounds and pattern; a pick from the offered
|
|
1510
|
+
* options), and every `required` question answered — by the reply, or by the defaults an omitted
|
|
1511
|
+
* question falls back to. A reply the loop would have to drop parts of is refused here instead, so
|
|
1512
|
+
* the person who typed it hears why. Needs the store to hand back the call's recorded questions;
|
|
1513
|
+
* without that seam the loop's own filtering is the only check.
|
|
1514
|
+
*/
|
|
1515
|
+
async assertAnswersFit(toolCallId2, answers2) {
|
|
1516
|
+
if (this.store.toolCallInput === void 0) {
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
const questions = readElicitationQuestions(await this.store.toolCallInput(toolCallId2));
|
|
1520
|
+
for (const question of questions) {
|
|
1521
|
+
const submitted = Object.hasOwn(answers2, question.id) ? answers2[question.id] : void 0;
|
|
1522
|
+
const problem = validateElicitationAnswer(question, submitted ?? question.defaults ?? []);
|
|
1523
|
+
if (problem !== null) {
|
|
1524
|
+
throw new BadRequestException(`answers["${question.id}"] ${problem}`);
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1495
1529
|
* Authorization seam for approve/reject. The call's recorded approver decides who may settle it:
|
|
1496
1530
|
* the requester (the default, and every call recorded before approvers existed) is the thread's
|
|
1497
1531
|
* own actor — the ownership check this always was; any other approver goes through the policy's
|
|
@@ -3096,6 +3130,9 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
|
|
|
3096
3130
|
} : {},
|
|
3097
3131
|
...meta.presentation !== void 0 ? {
|
|
3098
3132
|
presentation: meta.presentation
|
|
3133
|
+
} : {},
|
|
3134
|
+
...meta.terminal === true ? {
|
|
3135
|
+
terminal: true
|
|
3099
3136
|
} : {}
|
|
3100
3137
|
}, {
|
|
3101
3138
|
execute: /* @__PURE__ */ __name((input, ctx) => instance.execute(input, ctx), "execute"),
|
|
@@ -3305,7 +3342,7 @@ var LedgerQuotaStore = class {
|
|
|
3305
3342
|
};
|
|
3306
3343
|
|
|
3307
3344
|
// src/runner/inline-agent-runner.ts
|
|
3308
|
-
import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY6, AGENT_STORE as AGENT_STORE5, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, encodeStreamEvent as
|
|
3345
|
+
import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY6, AGENT_STORE as AGENT_STORE5, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, encodeStreamEvent as encodeStreamEvent3, publishAgentRunFailed as publishAgentRunFailed2, runAgentLoop as runAgentLoop2, settleAll as settleAll2, settleUnsettledDelegation as settleUnsettledDelegation2 } from "@dudousxd/nestjs-agent-core";
|
|
3309
3346
|
import { Inject as Inject18, Injectable as Injectable10, Logger as Logger5 } from "@nestjs/common";
|
|
3310
3347
|
function _ts_decorate20(decorators, target, key, desc) {
|
|
3311
3348
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -3443,7 +3480,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
|
|
|
3443
3480
|
this.logger.log(`agent run ${runId} cancelled`);
|
|
3444
3481
|
await this.store.setActiveStream(threadId, null);
|
|
3445
3482
|
const writer = await deps.sink.open(runId);
|
|
3446
|
-
await writer.write(
|
|
3483
|
+
await writer.write(encodeStreamEvent3({
|
|
3447
3484
|
kind: "cancelled"
|
|
3448
3485
|
}));
|
|
3449
3486
|
await writer.end();
|