@dudousxd/nestjs-agent-core 0.16.0 → 0.18.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/README.md +2 -0
- package/dist/guardrails/index.d.cts +1 -1
- package/dist/guardrails/index.d.ts +1 -1
- package/dist/index.cjs +124 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -102
- package/dist/index.d.ts +41 -102
- package/dist/index.js +122 -5
- package/dist/index.js.map +1 -1
- package/dist/{tool-CL9oEytW.d.cts → tool-CHIw-aTx.d.cts} +202 -1
- package/dist/{tool-CL9oEytW.d.ts → tool-CHIw-aTx.d.ts} +202 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,6 +35,8 @@ import type { ModelProvider, AgentStore, ToolSpec, RolesPolicy } from '@dudousxd
|
|
|
35
35
|
- `RunCancelledError` / `AgentLoopHooks.cancelled()` — real cancellation. The loop asks `hooks.cancelled()` at the points where stopping is safe and cheap (between steps, before the next model call, before a turn's tools are dispatched), ALWAYS from inside a checkpoint, so the answer is journaled and a cancel arriving between two replays can never change a branch a replayed position already took; the positions themselves sit behind `hooks.patched('agent:cancellation')`, so a run already in flight keeps its recorded shape. A tool already executing is never interrupted — there is no un-executing a side effect, and abandoning a dispatched step leaves a journal holding a dispatch whose result never lands. Observing a cancel throws `RunCancelledError`, which unwinds through the path a suspend already uses; the RUNNER settles it, recording the run `cancelled` (`AgentStore.recordRunEnd`'s third terminal, never `failed`) and ending the stream on a `{ kind: 'cancelled' }` frame rather than failing it, so a user pressing Stop is not in anybody's error rate.
|
|
36
36
|
- `isControlFlowSignal(error)` / `isReplayIntegrityError(error)` — recognize a durable suspend and a checkpoint refusal without importing the durable packages (a `Symbol.for` marker and a class name, respectively). Rethrow both untouched from any `catch` in a workflow body.
|
|
37
37
|
- `settleAll(tasks)` / `SettledTask<T>` — the implementation behind the optional `AgentLoopHooks.parallel`, which is how a turn's `read` tool calls run concurrently. It invokes every task synchronously, in list order, before awaiting any of them (so a runner that takes checkpoint positions on the call keeps them in call order), and resolves only once all of them have settled (so a runner that unwinds a turn by throwing never abandons a sibling mid-dispatch). A runner that assigns positions anywhere else simply omits the hook and the loop stays sequential.
|
|
38
|
+
- `AgentStreamEvent` / `encodeStreamEvent` / `decodeStreamEvent` — the live-stream vocabulary (text, reasoning, tool calls with optional `parentId` nesting, `elicitation`, `approval-requested` with `approver`/`expiresAt`, server-pushed `ui` components, `title`, `cancelled`). It is also the contract a runner that is not this loop writes to get the React client for free: see [docs/stream-protocol.md](../../docs/stream-protocol.md). `AgentUiComponent` and `AgentApprovalRequest` are the payload types.
|
|
39
|
+
- `observeTurnFrames` / `withTurnFrames` — what a model turn streamed that its result does not carry: the model's thinking (`reasoning` text, and `reasoningMs` summed over each burst of consecutive reasoning frames) and pushed `ui` components (first-seen order, last props per id). The loop and the dispatched `llm` step wrap the provider's sink with it inside the model checkpoint, so every provider that streams the vocabulary gets reasoning persisted (`StoredMessage.reasoning` / `reasoningMs` / `ui`) and a replay reads the journaled numbers back. A provider may set `ModelTurnResult.reasoning` / `reasoningMs` / `ui` itself; its values win. The step's `reasoningMs` also rides the `step-finish` frame.
|
|
38
40
|
- `runAgentLoop(deps, input, hooks)` — the loop; the NestJS package drives it from both runners
|
|
39
41
|
|
|
40
42
|
## Guardrails — `@dudousxd/nestjs-agent-core/guardrails`
|
package/dist/index.cjs
CHANGED
|
@@ -119,6 +119,7 @@ __export(src_exports, {
|
|
|
119
119
|
memoryWriteVerdict: () => memoryWriteVerdict,
|
|
120
120
|
normalizeDelegation: () => normalizeDelegation,
|
|
121
121
|
normalizeElicitationReply: () => normalizeElicitationReply,
|
|
122
|
+
observeTurnFrames: () => observeTurnFrames,
|
|
122
123
|
offerMemories: () => offerMemories,
|
|
123
124
|
offerSkills: () => offerSkills,
|
|
124
125
|
publishAgentDelegated: () => publishAgentDelegated,
|
|
@@ -168,6 +169,7 @@ __export(src_exports, {
|
|
|
168
169
|
withMemoryTool: () => withMemoryTool,
|
|
169
170
|
withSkillTool: () => withSkillTool,
|
|
170
171
|
withToolTimeout: () => withToolTimeout,
|
|
172
|
+
withTurnFrames: () => withTurnFrames,
|
|
171
173
|
writeMemory: () => writeMemory
|
|
172
174
|
});
|
|
173
175
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -229,6 +231,105 @@ function decodeStreamEvent(line) {
|
|
|
229
231
|
}
|
|
230
232
|
__name(decodeStreamEvent, "decodeStreamEvent");
|
|
231
233
|
|
|
234
|
+
// src/turn-frames.ts
|
|
235
|
+
function observeTurnFrames(writer, now = Date.now) {
|
|
236
|
+
const decoder2 = new TextDecoder();
|
|
237
|
+
let pending = "";
|
|
238
|
+
let reasoning = "";
|
|
239
|
+
let reasoningMs = 0;
|
|
240
|
+
let burstStartedAt;
|
|
241
|
+
const ui = /* @__PURE__ */ new Map();
|
|
242
|
+
function closeBurst() {
|
|
243
|
+
if (burstStartedAt !== void 0) {
|
|
244
|
+
reasoningMs += Math.max(0, now() - burstStartedAt);
|
|
245
|
+
burstStartedAt = void 0;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
__name(closeBurst, "closeBurst");
|
|
249
|
+
function observeLine(line) {
|
|
250
|
+
if (line.trim().length === 0) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const event = decodeStreamEvent(line);
|
|
254
|
+
if (event === null) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (event.kind === "reasoning") {
|
|
258
|
+
burstStartedAt ??= now();
|
|
259
|
+
reasoning += event.text;
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
closeBurst();
|
|
263
|
+
if (event.kind === "ui") {
|
|
264
|
+
ui.set(event.id, {
|
|
265
|
+
id: event.id,
|
|
266
|
+
component: event.component,
|
|
267
|
+
props: event.props,
|
|
268
|
+
...event.version !== void 0 ? {
|
|
269
|
+
version: event.version
|
|
270
|
+
} : {}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
__name(observeLine, "observeLine");
|
|
275
|
+
function observe(chunk) {
|
|
276
|
+
pending += decoder2.decode(chunk, {
|
|
277
|
+
stream: true
|
|
278
|
+
});
|
|
279
|
+
let newline = pending.indexOf("\n");
|
|
280
|
+
while (newline !== -1) {
|
|
281
|
+
observeLine(pending.slice(0, newline));
|
|
282
|
+
pending = pending.slice(newline + 1);
|
|
283
|
+
newline = pending.indexOf("\n");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
__name(observe, "observe");
|
|
287
|
+
return {
|
|
288
|
+
writer: {
|
|
289
|
+
write(chunk) {
|
|
290
|
+
observe(chunk);
|
|
291
|
+
return writer.write(chunk);
|
|
292
|
+
},
|
|
293
|
+
end: /* @__PURE__ */ __name(() => writer.end(), "end"),
|
|
294
|
+
fail: /* @__PURE__ */ __name((error) => writer.fail(error), "fail")
|
|
295
|
+
},
|
|
296
|
+
summary() {
|
|
297
|
+
if (pending.length > 0) {
|
|
298
|
+
observeLine(pending);
|
|
299
|
+
pending = "";
|
|
300
|
+
}
|
|
301
|
+
closeBurst();
|
|
302
|
+
return {
|
|
303
|
+
...reasoning.length > 0 ? {
|
|
304
|
+
reasoning,
|
|
305
|
+
reasoningMs: Math.round(reasoningMs)
|
|
306
|
+
} : {},
|
|
307
|
+
...ui.size > 0 ? {
|
|
308
|
+
ui: [
|
|
309
|
+
...ui.values()
|
|
310
|
+
]
|
|
311
|
+
} : {}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
__name(observeTurnFrames, "observeTurnFrames");
|
|
317
|
+
function withTurnFrames(result, frames) {
|
|
318
|
+
return {
|
|
319
|
+
...result,
|
|
320
|
+
...result.reasoning === void 0 && frames.reasoning !== void 0 ? {
|
|
321
|
+
reasoning: frames.reasoning
|
|
322
|
+
} : {},
|
|
323
|
+
...result.reasoningMs === void 0 && frames.reasoningMs !== void 0 ? {
|
|
324
|
+
reasoningMs: frames.reasoningMs
|
|
325
|
+
} : {},
|
|
326
|
+
...result.ui === void 0 && frames.ui !== void 0 ? {
|
|
327
|
+
ui: frames.ui
|
|
328
|
+
} : {}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
__name(withTurnFrames, "withTurnFrames");
|
|
332
|
+
|
|
232
333
|
// src/spi/pricing-store.ts
|
|
233
334
|
async function seedModelPrices(store, prices) {
|
|
234
335
|
for (const price of prices) {
|
|
@@ -3534,12 +3635,13 @@ ${block}`;
|
|
|
3534
3635
|
writer
|
|
3535
3636
|
}) : void 0;
|
|
3536
3637
|
const buffer = gateMode === "whole" ? createFrameBuffer() : void 0;
|
|
3537
|
-
const
|
|
3638
|
+
const frames = observeTurnFrames(incremental?.writer ?? buffer?.writer ?? writer);
|
|
3639
|
+
const result = stampToolKinds(withTurnFrames(await traceLlmTurn(hooks.runId, i, () => deps.model.runTurn({
|
|
3538
3640
|
system: prompt.system,
|
|
3539
3641
|
messages: prompt.messages,
|
|
3540
3642
|
tools,
|
|
3541
|
-
sink:
|
|
3542
|
-
})), deps);
|
|
3643
|
+
sink: frames.writer
|
|
3644
|
+
})), frames.summary()), deps);
|
|
3543
3645
|
if (incremental !== void 0) {
|
|
3544
3646
|
await incremental.settled();
|
|
3545
3647
|
const refusal = incremental.rejection();
|
|
@@ -3727,6 +3829,15 @@ ${block}`;
|
|
|
3727
3829
|
...input.agentName !== void 0 ? {
|
|
3728
3830
|
agentName: input.agentName
|
|
3729
3831
|
} : {},
|
|
3832
|
+
...turn.reasoning !== void 0 ? {
|
|
3833
|
+
reasoning: turn.reasoning
|
|
3834
|
+
} : {},
|
|
3835
|
+
...turn.reasoningMs !== void 0 ? {
|
|
3836
|
+
reasoningMs: turn.reasoningMs
|
|
3837
|
+
} : {},
|
|
3838
|
+
...turn.ui !== void 0 && turn.ui.length > 0 ? {
|
|
3839
|
+
ui: turn.ui
|
|
3840
|
+
} : {},
|
|
3730
3841
|
...messageCalls.length > 0 ? {
|
|
3731
3842
|
toolCalls: messageCalls
|
|
3732
3843
|
} : {},
|
|
@@ -3784,7 +3895,10 @@ ${block}`;
|
|
|
3784
3895
|
await writer.write(encodeStreamEvent({
|
|
3785
3896
|
kind: "step-finish",
|
|
3786
3897
|
usage: turn.usage,
|
|
3787
|
-
costUsd
|
|
3898
|
+
costUsd,
|
|
3899
|
+
...turn.reasoningMs !== void 0 ? {
|
|
3900
|
+
reasoningMs: turn.reasoningMs
|
|
3901
|
+
} : {}
|
|
3788
3902
|
}));
|
|
3789
3903
|
});
|
|
3790
3904
|
break;
|
|
@@ -3837,7 +3951,10 @@ ${block}`;
|
|
|
3837
3951
|
await writer.write(encodeStreamEvent({
|
|
3838
3952
|
kind: "step-finish",
|
|
3839
3953
|
usage: turn.usage,
|
|
3840
|
-
costUsd
|
|
3954
|
+
costUsd,
|
|
3955
|
+
...turn.reasoningMs !== void 0 ? {
|
|
3956
|
+
reasoningMs: turn.reasoningMs
|
|
3957
|
+
} : {}
|
|
3841
3958
|
}));
|
|
3842
3959
|
});
|
|
3843
3960
|
}
|
|
@@ -3992,6 +4109,7 @@ __name(runAgentLoop, "runAgentLoop");
|
|
|
3992
4109
|
memoryWriteVerdict,
|
|
3993
4110
|
normalizeDelegation,
|
|
3994
4111
|
normalizeElicitationReply,
|
|
4112
|
+
observeTurnFrames,
|
|
3995
4113
|
offerMemories,
|
|
3996
4114
|
offerSkills,
|
|
3997
4115
|
publishAgentDelegated,
|
|
@@ -4041,6 +4159,7 @@ __name(runAgentLoop, "runAgentLoop");
|
|
|
4041
4159
|
withMemoryTool,
|
|
4042
4160
|
withSkillTool,
|
|
4043
4161
|
withToolTimeout,
|
|
4162
|
+
withTurnFrames,
|
|
4044
4163
|
writeMemory
|
|
4045
4164
|
});
|
|
4046
4165
|
//# sourceMappingURL=index.cjs.map
|