@cuylabs/agent-core 0.6.0 → 0.7.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 +5 -1
- package/dist/{builder-BKkipazh.d.ts → builder-BRvqCcIk.d.ts} +2 -2
- package/dist/{resolver-DOfZ-xuk.d.ts → capability-resolver-CgRGsWVX.d.ts} +1 -1
- package/dist/{chunk-3C4VKG4P.js → chunk-3HNO5SVI.js} +273 -807
- package/dist/chunk-5K7AQVOU.js +619 -0
- package/dist/{chunk-QAQADS4X.js → chunk-BNSHUWCV.js} +1 -0
- package/dist/{chunk-O2ZCFQL6.js → chunk-CDTV2UYU.js} +86 -1
- package/dist/chunk-IEFIQENH.js +73 -0
- package/dist/chunk-N7P4PN3O.js +84 -0
- package/dist/{chunk-QWFMX226.js → chunk-QGOGIP7T.js} +148 -15
- package/dist/chunk-VNQBHPCT.js +398 -0
- package/dist/{chunk-X635CM2F.js → chunk-ZPMACVZK.js} +1 -1
- package/dist/context/index.js +1 -1
- package/dist/host/index.d.ts +45 -0
- package/dist/host/index.js +8 -0
- package/dist/{index-DZQJD_hp.d.ts → index-C33hlD6H.d.ts} +12 -7
- package/dist/{index-ipP3_ztp.d.ts → index-CfBGYrpd.d.ts} +121 -2
- package/dist/index.d.ts +107 -126
- package/dist/index.js +321 -601
- package/dist/inference/index.d.ts +59 -0
- package/dist/inference/index.js +25 -0
- package/dist/middleware/index.d.ts +7 -4
- package/dist/middleware/index.js +5 -3
- package/dist/models/index.d.ts +104 -2
- package/dist/models/index.js +40 -6
- package/dist/prompt/index.d.ts +9 -6
- package/dist/reasoning/index.d.ts +54 -8
- package/dist/reasoning/index.js +2 -3
- package/dist/{registry-CuRWWtcT.d.ts → registry-BDLIHOQB.d.ts} +1 -1
- package/dist/{runner-G1wxEgac.d.ts → runner-DSKaEz3z.d.ts} +35 -8
- package/dist/runtime/index.d.ts +41 -7
- package/dist/runtime/index.js +15 -6
- package/dist/scope/index.d.ts +10 -0
- package/dist/scope/index.js +14 -0
- package/dist/{session-manager-Uawm2Le7.d.ts → session-manager-B_CWGTsl.d.ts} +1 -1
- package/dist/skill/index.d.ts +7 -5
- package/dist/storage/index.d.ts +2 -2
- package/dist/sub-agent/index.d.ts +12 -8
- package/dist/tool/index.d.ts +7 -4
- package/dist/tool/index.js +4 -3
- package/dist/{tool-pFAnJc5Y.d.ts → tool-Db1Ue-1U.d.ts} +1 -1
- package/dist/{tool-DYp6-cC3.d.ts → tool-HUtkiVBx.d.ts} +5 -99
- package/dist/tracking/index.d.ts +3 -1
- package/dist/types-9jGQUjqW.d.ts +29 -0
- package/dist/types-CHiPh8U2.d.ts +100 -0
- package/dist/types-CqDZTh4d.d.ts +335 -0
- package/dist/types-FRpzzg_9.d.ts +355 -0
- package/package.json +19 -8
- package/dist/capabilities/index.d.ts +0 -97
- package/dist/capabilities/index.js +0 -46
- package/dist/chunk-6TDTQJ4P.js +0 -116
- package/dist/chunk-DWYX7ASF.js +0 -26
- package/dist/chunk-FG4MD5MU.js +0 -54
- package/dist/config-D2xeGEHK.d.ts +0 -52
- package/dist/identifiers-BLUxFqV_.d.ts +0 -12
- package/dist/network-D76DS5ot.d.ts +0 -5
- package/dist/types-BWo810L_.d.ts +0 -648
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
executeAgentToolCall
|
|
3
|
-
} from "./chunk-FG4MD5MU.js";
|
|
4
1
|
import {
|
|
5
2
|
DEFAULT_CONTEXT_LIMITS
|
|
6
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BNSHUWCV.js";
|
|
4
|
+
import {
|
|
5
|
+
Inference
|
|
6
|
+
} from "./chunk-5K7AQVOU.js";
|
|
7
|
+
import {
|
|
8
|
+
executeAgentToolCall
|
|
9
|
+
} from "./chunk-IEFIQENH.js";
|
|
7
10
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
currentScope,
|
|
12
|
+
snapshotScope,
|
|
13
|
+
streamWithinScope,
|
|
14
|
+
withinScope
|
|
15
|
+
} from "./chunk-N7P4PN3O.js";
|
|
10
16
|
|
|
11
17
|
// src/runtime/task/observer.ts
|
|
12
18
|
function defaultAgentTaskCheckpointStrategy(input) {
|
|
@@ -242,101 +248,116 @@ function createAgentTaskRunner(agent, options = {}) {
|
|
|
242
248
|
const resolvedSessionId = payload.sessionId?.trim() || options.resolveSessionId?.(payload, context)?.trim() || buildRuntimeSessionId(prefix, context.fallbackSessionKey);
|
|
243
249
|
const sessionId = normalizeNonEmpty(resolvedSessionId, "sessionId");
|
|
244
250
|
const startedAt = nowIso();
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
await observer.onTaskStart?.(run, createSnapshot());
|
|
286
|
-
});
|
|
287
|
-
await emitCheckpoint("task-start");
|
|
288
|
-
const activateCtx = baseObservers.find((o) => o.activateContext)?.activateContext?.bind(void 0, sessionId);
|
|
289
|
-
try {
|
|
290
|
-
const processChatStream = async () => {
|
|
291
|
-
for await (const event of agent.chat(sessionId, message, {
|
|
292
|
-
abort: context.signal,
|
|
293
|
-
system: payload.system
|
|
294
|
-
})) {
|
|
295
|
-
turnState = advanceAgentTurnState(turnState, event, nowIso());
|
|
296
|
-
if (event.type === "tool-result") {
|
|
297
|
-
toolCalls.push({ name: event.toolName, result: event.result });
|
|
251
|
+
return withinScope(
|
|
252
|
+
{
|
|
253
|
+
kind: "task",
|
|
254
|
+
name: "agent-task",
|
|
255
|
+
sessionId,
|
|
256
|
+
taskId: context.fallbackSessionKey ?? sessionId,
|
|
257
|
+
attributes: {
|
|
258
|
+
...context.trigger ? { trigger: context.trigger } : {}
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
async () => {
|
|
262
|
+
const run = {
|
|
263
|
+
payload,
|
|
264
|
+
context,
|
|
265
|
+
sessionId,
|
|
266
|
+
startedAt,
|
|
267
|
+
scope: snapshotScope()
|
|
268
|
+
};
|
|
269
|
+
const toolCalls = [];
|
|
270
|
+
let turnState = createAgentTurnState({
|
|
271
|
+
sessionId,
|
|
272
|
+
startedAt
|
|
273
|
+
});
|
|
274
|
+
const createSnapshot = () => ({
|
|
275
|
+
sessionId,
|
|
276
|
+
response: turnState.response,
|
|
277
|
+
usage: { ...turnState.usage },
|
|
278
|
+
toolCalls: toolCalls.map((toolCall) => ({ ...toolCall })),
|
|
279
|
+
eventCount: turnState.eventCount,
|
|
280
|
+
activeStep: turnState.step > 0 ? turnState.step : void 0,
|
|
281
|
+
lastEvent: turnState.lastEvent,
|
|
282
|
+
error: turnState.error,
|
|
283
|
+
startedAt: turnState.startedAt,
|
|
284
|
+
updatedAt: turnState.updatedAt,
|
|
285
|
+
turnState,
|
|
286
|
+
scope: currentScope() ?? run.scope
|
|
287
|
+
});
|
|
288
|
+
const emitCheckpoint = async (reason, event) => {
|
|
289
|
+
if (baseObservers.length === 0) {
|
|
290
|
+
return;
|
|
298
291
|
}
|
|
299
|
-
const
|
|
300
|
-
await notifyObservers(baseObservers, async (observer) => {
|
|
301
|
-
await observer.onTaskEvent?.(run, event, snapshot);
|
|
302
|
-
});
|
|
303
|
-
const checkpointReason = checkpointStrategy({
|
|
292
|
+
const checkpoint = {
|
|
304
293
|
run,
|
|
294
|
+
reason,
|
|
295
|
+
snapshot: createSnapshot(),
|
|
305
296
|
event,
|
|
306
|
-
|
|
297
|
+
createdAt: turnState.updatedAt
|
|
298
|
+
};
|
|
299
|
+
await notifyObservers(baseObservers, async (observer) => {
|
|
300
|
+
await observer.onCheckpoint?.(checkpoint);
|
|
307
301
|
});
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
302
|
+
};
|
|
303
|
+
await notifyObservers(baseObservers, async (observer) => {
|
|
304
|
+
await observer.onTaskStart?.(run, createSnapshot());
|
|
305
|
+
});
|
|
306
|
+
await emitCheckpoint("task-start");
|
|
307
|
+
const activateCtx = baseObservers.find((o) => o.activateContext)?.activateContext?.bind(void 0, sessionId);
|
|
308
|
+
try {
|
|
309
|
+
const processChatStream = async () => {
|
|
310
|
+
for await (const event of agent.chat(sessionId, message, {
|
|
311
|
+
abort: context.signal,
|
|
312
|
+
system: payload.system
|
|
313
|
+
})) {
|
|
314
|
+
turnState = advanceAgentTurnState(turnState, event, nowIso());
|
|
315
|
+
if (event.type === "tool-result") {
|
|
316
|
+
toolCalls.push({ name: event.toolName, result: event.result });
|
|
317
|
+
}
|
|
318
|
+
const snapshot = createSnapshot();
|
|
319
|
+
await notifyObservers(baseObservers, async (observer) => {
|
|
320
|
+
await observer.onTaskEvent?.(run, event, snapshot);
|
|
321
|
+
});
|
|
322
|
+
const checkpointReason = checkpointStrategy({
|
|
323
|
+
run,
|
|
324
|
+
event,
|
|
325
|
+
snapshot
|
|
326
|
+
});
|
|
327
|
+
if (checkpointReason) {
|
|
328
|
+
await emitCheckpoint(checkpointReason, event);
|
|
329
|
+
}
|
|
330
|
+
if (event.type === "error") {
|
|
331
|
+
throw event.error;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
if (activateCtx) {
|
|
336
|
+
await activateCtx(processChatStream);
|
|
337
|
+
} else {
|
|
338
|
+
await processChatStream();
|
|
313
339
|
}
|
|
340
|
+
const result = {
|
|
341
|
+
response: turnState.response,
|
|
342
|
+
sessionId,
|
|
343
|
+
usage: { ...turnState.usage },
|
|
344
|
+
toolCalls
|
|
345
|
+
};
|
|
346
|
+
await notifyObservers(baseObservers, async (observer) => {
|
|
347
|
+
await observer.onTaskComplete?.(run, result, createSnapshot());
|
|
348
|
+
});
|
|
349
|
+
return result;
|
|
350
|
+
} catch (error) {
|
|
351
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
352
|
+
turnState = failAgentTurnState(turnState, normalizedError, nowIso());
|
|
353
|
+
await notifyObservers(baseObservers, async (observer) => {
|
|
354
|
+
await observer.onTaskError?.(run, normalizedError, createSnapshot());
|
|
355
|
+
});
|
|
356
|
+
await emitCheckpoint("task-error");
|
|
357
|
+
throw normalizedError;
|
|
314
358
|
}
|
|
315
|
-
};
|
|
316
|
-
if (activateCtx) {
|
|
317
|
-
await activateCtx(processChatStream);
|
|
318
|
-
} else {
|
|
319
|
-
await processChatStream();
|
|
320
359
|
}
|
|
321
|
-
|
|
322
|
-
response: turnState.response,
|
|
323
|
-
sessionId,
|
|
324
|
-
usage: { ...turnState.usage },
|
|
325
|
-
toolCalls
|
|
326
|
-
};
|
|
327
|
-
await notifyObservers(baseObservers, async (observer) => {
|
|
328
|
-
await observer.onTaskComplete?.(run, result, createSnapshot());
|
|
329
|
-
});
|
|
330
|
-
return result;
|
|
331
|
-
} catch (error) {
|
|
332
|
-
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
333
|
-
turnState = failAgentTurnState(turnState, normalizedError, nowIso());
|
|
334
|
-
await notifyObservers(baseObservers, async (observer) => {
|
|
335
|
-
await observer.onTaskError?.(run, normalizedError, createSnapshot());
|
|
336
|
-
});
|
|
337
|
-
await emitCheckpoint("task-error");
|
|
338
|
-
throw normalizedError;
|
|
339
|
-
}
|
|
360
|
+
);
|
|
340
361
|
};
|
|
341
362
|
}
|
|
342
363
|
|
|
@@ -602,7 +623,7 @@ function prepareModelStep(options) {
|
|
|
602
623
|
step: options.step,
|
|
603
624
|
messages: options.messages,
|
|
604
625
|
modelMessages,
|
|
605
|
-
|
|
626
|
+
inferenceInput: {
|
|
606
627
|
sessionID: options.sessionId,
|
|
607
628
|
step: options.step,
|
|
608
629
|
model: options.config.model,
|
|
@@ -625,7 +646,7 @@ function prepareModelStep(options) {
|
|
|
625
646
|
toolExecutionMode: options.toolExecutionMode,
|
|
626
647
|
telemetry: options.config.telemetry
|
|
627
648
|
},
|
|
628
|
-
|
|
649
|
+
stepProcessing: {
|
|
629
650
|
maxSteps: options.config.maxSteps,
|
|
630
651
|
doomLoopThreshold: options.config.doomLoopThreshold,
|
|
631
652
|
enforceDoomLoop: options.config.enforceDoomLoop,
|
|
@@ -635,578 +656,7 @@ function prepareModelStep(options) {
|
|
|
635
656
|
};
|
|
636
657
|
}
|
|
637
658
|
|
|
638
|
-
// src/
|
|
639
|
-
import { tool, zodSchema } from "ai";
|
|
640
|
-
async function buildToolSet(options) {
|
|
641
|
-
const toolSet = {};
|
|
642
|
-
const executionMode = options.executionMode ?? "auto";
|
|
643
|
-
for (const [id, info] of Object.entries(options.tools)) {
|
|
644
|
-
const initialized = await info.init({ cwd: options.cwd });
|
|
645
|
-
toolSet[id] = executionMode === "auto" ? tool({
|
|
646
|
-
description: initialized.description,
|
|
647
|
-
inputSchema: zodSchema(initialized.parameters),
|
|
648
|
-
execute: async (params) => (await executeAgentToolCall({
|
|
649
|
-
toolName: id,
|
|
650
|
-
tool: info,
|
|
651
|
-
params,
|
|
652
|
-
cwd: options.cwd,
|
|
653
|
-
abort: options.abort,
|
|
654
|
-
sessionID: options.sessionID,
|
|
655
|
-
messageID: options.messageID,
|
|
656
|
-
...options.host ? { host: options.host } : {},
|
|
657
|
-
...options.turnTracker ? { turnTracker: options.turnTracker } : {},
|
|
658
|
-
...options.middleware ? { middleware: options.middleware } : {}
|
|
659
|
-
})).output
|
|
660
|
-
}) : tool({
|
|
661
|
-
description: initialized.description,
|
|
662
|
-
inputSchema: zodSchema(initialized.parameters)
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
|
-
return toolSet;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// src/execution/llm/stream.ts
|
|
669
|
-
import {
|
|
670
|
-
stepCountIs,
|
|
671
|
-
streamText
|
|
672
|
-
} from "ai";
|
|
673
|
-
|
|
674
|
-
// src/errors/classify.ts
|
|
675
|
-
function isRetryableCategory(category) {
|
|
676
|
-
switch (category) {
|
|
677
|
-
case "rate_limit":
|
|
678
|
-
case "overloaded":
|
|
679
|
-
case "network":
|
|
680
|
-
case "timeout":
|
|
681
|
-
return true;
|
|
682
|
-
case "auth":
|
|
683
|
-
case "invalid_request":
|
|
684
|
-
case "context_overflow":
|
|
685
|
-
case "content_filter":
|
|
686
|
-
case "cancelled":
|
|
687
|
-
case "unknown":
|
|
688
|
-
return false;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
function classifyFromStatusAndMessage(status, message) {
|
|
692
|
-
const lowerMessage = message.toLowerCase();
|
|
693
|
-
if (status) {
|
|
694
|
-
if (status === 429) return "rate_limit";
|
|
695
|
-
if (status === 401 || status === 403) return "auth";
|
|
696
|
-
if (status === 400) {
|
|
697
|
-
if (lowerMessage.includes("context") || lowerMessage.includes("token")) {
|
|
698
|
-
return "context_overflow";
|
|
699
|
-
}
|
|
700
|
-
return "invalid_request";
|
|
701
|
-
}
|
|
702
|
-
if (status === 503 || status === 502) return "overloaded";
|
|
703
|
-
if (status >= 500) return "network";
|
|
704
|
-
}
|
|
705
|
-
if (lowerMessage.includes("rate") && lowerMessage.includes("limit")) {
|
|
706
|
-
return "rate_limit";
|
|
707
|
-
}
|
|
708
|
-
if (lowerMessage.includes("overload") || lowerMessage.includes("capacity")) {
|
|
709
|
-
return "overloaded";
|
|
710
|
-
}
|
|
711
|
-
if (lowerMessage.includes("too_many_requests")) {
|
|
712
|
-
return "rate_limit";
|
|
713
|
-
}
|
|
714
|
-
if (lowerMessage.includes("unauthorized") || lowerMessage.includes("invalid api key")) {
|
|
715
|
-
return "auth";
|
|
716
|
-
}
|
|
717
|
-
if (lowerMessage.includes("context") && lowerMessage.includes("length")) {
|
|
718
|
-
return "context_overflow";
|
|
719
|
-
}
|
|
720
|
-
if (lowerMessage.includes("content") && lowerMessage.includes("filter")) {
|
|
721
|
-
return "content_filter";
|
|
722
|
-
}
|
|
723
|
-
if (lowerMessage.includes("timeout") || lowerMessage.includes("timed out")) {
|
|
724
|
-
return "timeout";
|
|
725
|
-
}
|
|
726
|
-
if (lowerMessage.includes("network") || lowerMessage.includes("econnrefused") || lowerMessage.includes("econnreset")) {
|
|
727
|
-
return "network";
|
|
728
|
-
}
|
|
729
|
-
return "unknown";
|
|
730
|
-
}
|
|
731
|
-
function parseRetryDelay(headers) {
|
|
732
|
-
const retryAfterMs = headers["retry-after-ms"];
|
|
733
|
-
if (retryAfterMs) {
|
|
734
|
-
const parsed = parseFloat(retryAfterMs);
|
|
735
|
-
if (!Number.isNaN(parsed) && parsed > 0) {
|
|
736
|
-
return parsed;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
const retryAfter = headers["retry-after"];
|
|
740
|
-
if (retryAfter) {
|
|
741
|
-
const seconds = parseFloat(retryAfter);
|
|
742
|
-
if (!Number.isNaN(seconds) && seconds > 0) {
|
|
743
|
-
return Math.ceil(seconds * 1e3);
|
|
744
|
-
}
|
|
745
|
-
const dateMs = Date.parse(retryAfter);
|
|
746
|
-
if (!Number.isNaN(dateMs)) {
|
|
747
|
-
const delayMs = dateMs - Date.now();
|
|
748
|
-
if (delayMs > 0) {
|
|
749
|
-
return Math.ceil(delayMs);
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
return void 0;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
// src/errors/extract.ts
|
|
757
|
-
function extractFromAISDKError(error) {
|
|
758
|
-
const result = {};
|
|
759
|
-
const anyError = error;
|
|
760
|
-
if (typeof anyError.status === "number") {
|
|
761
|
-
result.status = anyError.status;
|
|
762
|
-
} else if (typeof anyError.statusCode === "number") {
|
|
763
|
-
result.status = anyError.statusCode;
|
|
764
|
-
}
|
|
765
|
-
if (anyError.responseHeaders && typeof anyError.responseHeaders === "object") {
|
|
766
|
-
result.headers = anyError.responseHeaders;
|
|
767
|
-
} else if (anyError.headers && typeof anyError.headers === "object") {
|
|
768
|
-
result.headers = anyError.headers;
|
|
769
|
-
}
|
|
770
|
-
if (anyError.data && typeof anyError.data === "object") {
|
|
771
|
-
const data = anyError.data;
|
|
772
|
-
if (data.type === "error" && typeof data.error === "object") {
|
|
773
|
-
const innerError = data.error;
|
|
774
|
-
if (innerError.type === "too_many_requests") {
|
|
775
|
-
result.category = "rate_limit";
|
|
776
|
-
} else if (innerError.type === "overloaded") {
|
|
777
|
-
result.category = "overloaded";
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
if (typeof data.isRetryable === "boolean" && !data.isRetryable && !result.category) {
|
|
781
|
-
result.category = "invalid_request";
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
return result;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
// src/errors/llm-error.ts
|
|
788
|
-
var LLMError = class _LLMError extends Error {
|
|
789
|
-
category;
|
|
790
|
-
status;
|
|
791
|
-
headers;
|
|
792
|
-
provider;
|
|
793
|
-
model;
|
|
794
|
-
isRetryable;
|
|
795
|
-
retryDelayMs;
|
|
796
|
-
constructor(options) {
|
|
797
|
-
super(options.message, { cause: options.cause });
|
|
798
|
-
this.name = "LLMError";
|
|
799
|
-
this.status = options.status;
|
|
800
|
-
this.headers = options.headers;
|
|
801
|
-
this.provider = options.provider;
|
|
802
|
-
this.model = options.model;
|
|
803
|
-
this.category = options.category ?? classifyFromStatusAndMessage(
|
|
804
|
-
options.status,
|
|
805
|
-
options.message
|
|
806
|
-
);
|
|
807
|
-
this.isRetryable = isRetryableCategory(this.category);
|
|
808
|
-
this.retryDelayMs = this.headers ? parseRetryDelay(this.headers) : void 0;
|
|
809
|
-
}
|
|
810
|
-
static from(error, context) {
|
|
811
|
-
if (error instanceof _LLMError) {
|
|
812
|
-
return error;
|
|
813
|
-
}
|
|
814
|
-
if (error instanceof Error) {
|
|
815
|
-
if (error.name === "AbortError" || error.message.includes("abort")) {
|
|
816
|
-
return new _LLMError({
|
|
817
|
-
message: error.message,
|
|
818
|
-
category: "cancelled",
|
|
819
|
-
cause: error,
|
|
820
|
-
...context
|
|
821
|
-
});
|
|
822
|
-
}
|
|
823
|
-
return new _LLMError({
|
|
824
|
-
message: error.message,
|
|
825
|
-
cause: error,
|
|
826
|
-
...extractFromAISDKError(error),
|
|
827
|
-
...context
|
|
828
|
-
});
|
|
829
|
-
}
|
|
830
|
-
return new _LLMError({
|
|
831
|
-
message: String(error),
|
|
832
|
-
category: "unknown",
|
|
833
|
-
...context
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
get description() {
|
|
837
|
-
const parts = [this.message];
|
|
838
|
-
if (this.provider) parts.unshift(`[${this.provider}]`);
|
|
839
|
-
if (this.status) parts.push(`(HTTP ${this.status})`);
|
|
840
|
-
if (this.isRetryable && this.retryDelayMs) {
|
|
841
|
-
parts.push(`retry in ${Math.ceil(this.retryDelayMs / 1e3)}s`);
|
|
842
|
-
}
|
|
843
|
-
return parts.join(" ");
|
|
844
|
-
}
|
|
845
|
-
};
|
|
846
|
-
|
|
847
|
-
// src/errors/utils.ts
|
|
848
|
-
function isRetryable(error) {
|
|
849
|
-
if (error instanceof LLMError) {
|
|
850
|
-
return error.isRetryable;
|
|
851
|
-
}
|
|
852
|
-
return LLMError.from(error).isRetryable;
|
|
853
|
-
}
|
|
854
|
-
function getRetryDelay(error) {
|
|
855
|
-
if (error instanceof LLMError) {
|
|
856
|
-
return error.isRetryable ? error.retryDelayMs : void 0;
|
|
857
|
-
}
|
|
858
|
-
const llmError = LLMError.from(error);
|
|
859
|
-
return llmError.isRetryable ? llmError.retryDelayMs : void 0;
|
|
860
|
-
}
|
|
861
|
-
function getErrorCategory(error) {
|
|
862
|
-
if (error instanceof LLMError) {
|
|
863
|
-
return error.category;
|
|
864
|
-
}
|
|
865
|
-
return LLMError.from(error).category;
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
// src/retry.ts
|
|
869
|
-
var DEFAULT_RETRY_CONFIG = {
|
|
870
|
-
maxAttempts: 3,
|
|
871
|
-
initialDelayMs: 2e3,
|
|
872
|
-
backoffFactor: 2,
|
|
873
|
-
maxDelayMs: 3e4,
|
|
874
|
-
jitter: true
|
|
875
|
-
};
|
|
876
|
-
function createRetryState() {
|
|
877
|
-
return {
|
|
878
|
-
attempt: 0,
|
|
879
|
-
errors: [],
|
|
880
|
-
canRetry: true,
|
|
881
|
-
nextDelayMs: void 0
|
|
882
|
-
};
|
|
883
|
-
}
|
|
884
|
-
function calculateDelay(attempt, error, config) {
|
|
885
|
-
if (error?.retryDelayMs) {
|
|
886
|
-
return error.retryDelayMs;
|
|
887
|
-
}
|
|
888
|
-
const baseDelay = config.initialDelayMs * Math.pow(config.backoffFactor, attempt - 1);
|
|
889
|
-
const cappedDelay = Math.min(baseDelay, config.maxDelayMs);
|
|
890
|
-
if (config.jitter) {
|
|
891
|
-
const jitterRange = cappedDelay * 0.25;
|
|
892
|
-
const jitter = (Math.random() - 0.5) * 2 * jitterRange;
|
|
893
|
-
return Math.max(0, Math.round(cappedDelay + jitter));
|
|
894
|
-
}
|
|
895
|
-
return Math.round(cappedDelay);
|
|
896
|
-
}
|
|
897
|
-
async function sleep(ms, signal) {
|
|
898
|
-
return new Promise((resolve, reject) => {
|
|
899
|
-
if (signal?.aborted) {
|
|
900
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
901
|
-
return;
|
|
902
|
-
}
|
|
903
|
-
const timeoutId = setTimeout(() => {
|
|
904
|
-
cleanup();
|
|
905
|
-
resolve();
|
|
906
|
-
}, ms);
|
|
907
|
-
const abortHandler = () => {
|
|
908
|
-
clearTimeout(timeoutId);
|
|
909
|
-
cleanup();
|
|
910
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
911
|
-
};
|
|
912
|
-
const cleanup = () => {
|
|
913
|
-
signal?.removeEventListener("abort", abortHandler);
|
|
914
|
-
};
|
|
915
|
-
signal?.addEventListener("abort", abortHandler, { once: true });
|
|
916
|
-
});
|
|
917
|
-
}
|
|
918
|
-
async function withRetry(fn, config, signal) {
|
|
919
|
-
const mergedConfig = { ...DEFAULT_RETRY_CONFIG, ...config };
|
|
920
|
-
const state = createRetryState();
|
|
921
|
-
while (true) {
|
|
922
|
-
state.attempt++;
|
|
923
|
-
try {
|
|
924
|
-
return await fn(state.attempt);
|
|
925
|
-
} catch (error) {
|
|
926
|
-
const llmError = LLMError.from(error);
|
|
927
|
-
state.errors.push(llmError);
|
|
928
|
-
const shouldRetry2 = state.attempt < mergedConfig.maxAttempts && isRetryable(llmError) && !signal?.aborted;
|
|
929
|
-
if (!shouldRetry2) {
|
|
930
|
-
throw new LLMError({
|
|
931
|
-
message: `Failed after ${state.attempt} attempt(s): ${llmError.message}`,
|
|
932
|
-
category: llmError.category,
|
|
933
|
-
status: llmError.status,
|
|
934
|
-
headers: llmError.headers,
|
|
935
|
-
provider: llmError.provider,
|
|
936
|
-
model: llmError.model,
|
|
937
|
-
cause: llmError
|
|
938
|
-
});
|
|
939
|
-
}
|
|
940
|
-
const delayMs = calculateDelay(state.attempt, llmError, mergedConfig);
|
|
941
|
-
state.nextDelayMs = delayMs;
|
|
942
|
-
config?.onRetry?.(state.attempt, delayMs, llmError);
|
|
943
|
-
await sleep(delayMs, signal);
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
function createRetryHandler(options) {
|
|
948
|
-
const config = options ?? {};
|
|
949
|
-
const signal = options?.signal;
|
|
950
|
-
return async (createStream) => {
|
|
951
|
-
return withRetry(createStream, config, signal);
|
|
952
|
-
};
|
|
953
|
-
}
|
|
954
|
-
function shouldRetry(error, attempt, maxAttempts = DEFAULT_RETRY_CONFIG.maxAttempts) {
|
|
955
|
-
if (attempt >= maxAttempts) return false;
|
|
956
|
-
return isRetryable(error);
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
// src/execution/llm/types.ts
|
|
960
|
-
var OUTPUT_TOKEN_MAX = 32e3;
|
|
961
|
-
|
|
962
|
-
// src/execution/llm/stream.ts
|
|
963
|
-
function buildModelCallContext(input) {
|
|
964
|
-
return {
|
|
965
|
-
sessionID: input.sessionID,
|
|
966
|
-
step: input.step ?? 1,
|
|
967
|
-
cwd: input.cwd,
|
|
968
|
-
abort: input.abort,
|
|
969
|
-
model: input.model,
|
|
970
|
-
toolNames: Object.keys(input.tools),
|
|
971
|
-
mcpToolNames: Object.keys(input.mcpTools ?? {})
|
|
972
|
-
};
|
|
973
|
-
}
|
|
974
|
-
function buildModelCallInput(input) {
|
|
975
|
-
return {
|
|
976
|
-
model: input.model,
|
|
977
|
-
system: [...input.system],
|
|
978
|
-
messages: [...input.messages],
|
|
979
|
-
temperature: input.temperature,
|
|
980
|
-
topP: input.topP,
|
|
981
|
-
maxOutputTokens: input.maxOutputTokens,
|
|
982
|
-
maxSteps: input.maxSteps,
|
|
983
|
-
reasoningLevel: input.reasoningLevel,
|
|
984
|
-
telemetry: input.telemetry,
|
|
985
|
-
customStreamProvider: input.customStreamProvider,
|
|
986
|
-
toolExecutionMode: input.toolExecutionMode
|
|
987
|
-
};
|
|
988
|
-
}
|
|
989
|
-
function applyModelCallInput(target, modelCall) {
|
|
990
|
-
target.model = modelCall.model;
|
|
991
|
-
target.system = [...modelCall.system];
|
|
992
|
-
target.messages = [...modelCall.messages];
|
|
993
|
-
target.temperature = modelCall.temperature;
|
|
994
|
-
target.topP = modelCall.topP;
|
|
995
|
-
target.maxOutputTokens = modelCall.maxOutputTokens;
|
|
996
|
-
target.maxSteps = modelCall.maxSteps;
|
|
997
|
-
target.reasoningLevel = modelCall.reasoningLevel;
|
|
998
|
-
target.telemetry = modelCall.telemetry;
|
|
999
|
-
target.customStreamProvider = modelCall.customStreamProvider;
|
|
1000
|
-
target.toolExecutionMode = modelCall.toolExecutionMode;
|
|
1001
|
-
target.activeModelCall = modelCall;
|
|
1002
|
-
}
|
|
1003
|
-
function isBlockedModelCall(value) {
|
|
1004
|
-
return "block" in value && value.block === true;
|
|
1005
|
-
}
|
|
1006
|
-
async function resolveModelCallInput(input) {
|
|
1007
|
-
if (!input.middleware?.hasMiddleware) {
|
|
1008
|
-
const current = buildModelCallInput(input);
|
|
1009
|
-
input.activeModelCall = current;
|
|
1010
|
-
return current;
|
|
1011
|
-
}
|
|
1012
|
-
const next = await input.middleware.runModelInput(
|
|
1013
|
-
buildModelCallInput(input),
|
|
1014
|
-
buildModelCallContext(input)
|
|
1015
|
-
);
|
|
1016
|
-
if (isBlockedModelCall(next)) {
|
|
1017
|
-
return next;
|
|
1018
|
-
}
|
|
1019
|
-
applyModelCallInput(input, next);
|
|
1020
|
-
return next;
|
|
1021
|
-
}
|
|
1022
|
-
function wrapModelStream(stream2, input) {
|
|
1023
|
-
const normalizedText = Promise.resolve(stream2.text);
|
|
1024
|
-
const normalizedUsage = Promise.resolve(stream2.usage).then((usage) => ({
|
|
1025
|
-
inputTokens: usage.inputTokens ?? 0,
|
|
1026
|
-
outputTokens: usage.outputTokens ?? 0,
|
|
1027
|
-
totalTokens: usage.totalTokens ?? 0
|
|
1028
|
-
}));
|
|
1029
|
-
const normalizedFinishReason = Promise.resolve(stream2.finishReason).then(
|
|
1030
|
-
(reason) => String(reason)
|
|
1031
|
-
);
|
|
1032
|
-
if (!input.middleware?.hasMiddleware) {
|
|
1033
|
-
return {
|
|
1034
|
-
fullStream: stream2.fullStream,
|
|
1035
|
-
text: normalizedText,
|
|
1036
|
-
usage: normalizedUsage,
|
|
1037
|
-
finishReason: normalizedFinishReason
|
|
1038
|
-
};
|
|
1039
|
-
}
|
|
1040
|
-
return {
|
|
1041
|
-
fullStream: (async function* () {
|
|
1042
|
-
const ctx = buildModelCallContext(input);
|
|
1043
|
-
for await (const rawChunk of stream2.fullStream) {
|
|
1044
|
-
const chunk = await input.middleware.runModelChunk(
|
|
1045
|
-
rawChunk,
|
|
1046
|
-
ctx
|
|
1047
|
-
);
|
|
1048
|
-
if (chunk) {
|
|
1049
|
-
yield chunk;
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
})(),
|
|
1053
|
-
text: normalizedText,
|
|
1054
|
-
usage: normalizedUsage,
|
|
1055
|
-
finishReason: normalizedFinishReason
|
|
1056
|
-
};
|
|
1057
|
-
}
|
|
1058
|
-
async function createCustomStream(input) {
|
|
1059
|
-
const system = input.system.filter(Boolean).join("\n");
|
|
1060
|
-
return input.customStreamProvider({
|
|
1061
|
-
system,
|
|
1062
|
-
messages: input.messages,
|
|
1063
|
-
abortSignal: input.abort,
|
|
1064
|
-
maxSteps: input.maxSteps
|
|
1065
|
-
});
|
|
1066
|
-
}
|
|
1067
|
-
function getModelInfo(input) {
|
|
1068
|
-
return {
|
|
1069
|
-
provider: typeof input.model === "object" && "provider" in input.model ? String(input.model.provider) : void 0,
|
|
1070
|
-
model: typeof input.model === "object" && "modelId" in input.model ? String(input.model.modelId) : String(input.model)
|
|
1071
|
-
};
|
|
1072
|
-
}
|
|
1073
|
-
async function callStreamTextWithOtelContext(options) {
|
|
1074
|
-
const { input, allTools, system, providerOptions } = options;
|
|
1075
|
-
const callStreamText = () => streamText({
|
|
1076
|
-
model: input.model,
|
|
1077
|
-
system,
|
|
1078
|
-
messages: input.messages,
|
|
1079
|
-
tools: allTools,
|
|
1080
|
-
stopWhen: stepCountIs(input.maxSteps ?? 50),
|
|
1081
|
-
maxOutputTokens: input.maxOutputTokens ?? OUTPUT_TOKEN_MAX,
|
|
1082
|
-
temperature: input.temperature,
|
|
1083
|
-
topP: input.topP,
|
|
1084
|
-
abortSignal: input.abort,
|
|
1085
|
-
providerOptions,
|
|
1086
|
-
experimental_telemetry: input.telemetry,
|
|
1087
|
-
prepareStep: input.intervention ? async ({ messages }) => {
|
|
1088
|
-
const pending = input.intervention.drainImmediate();
|
|
1089
|
-
if (pending.length === 0) {
|
|
1090
|
-
return void 0;
|
|
1091
|
-
}
|
|
1092
|
-
const injected = pending.map((item) => ({
|
|
1093
|
-
role: "user",
|
|
1094
|
-
content: item.message
|
|
1095
|
-
}));
|
|
1096
|
-
for (const item of pending) {
|
|
1097
|
-
input.intervention.onApplied?.(item);
|
|
1098
|
-
}
|
|
1099
|
-
return { messages: [...messages, ...injected] };
|
|
1100
|
-
} : void 0,
|
|
1101
|
-
onStepFinish: async (step) => {
|
|
1102
|
-
if (!input.onStepFinish) {
|
|
1103
|
-
return;
|
|
1104
|
-
}
|
|
1105
|
-
await input.onStepFinish({
|
|
1106
|
-
toolResults: step.toolResults?.map((toolResult) => ({
|
|
1107
|
-
toolName: toolResult.toolName,
|
|
1108
|
-
toolCallId: toolResult.toolCallId,
|
|
1109
|
-
output: toolResult.output
|
|
1110
|
-
})),
|
|
1111
|
-
usage: step.usage,
|
|
1112
|
-
finishReason: step.finishReason
|
|
1113
|
-
});
|
|
1114
|
-
}
|
|
1115
|
-
});
|
|
1116
|
-
const otelCtx = input.middleware?.getOtelContext(input.sessionID);
|
|
1117
|
-
if (!otelCtx) {
|
|
1118
|
-
return callStreamText();
|
|
1119
|
-
}
|
|
1120
|
-
try {
|
|
1121
|
-
const otelApi = await import("@opentelemetry/api");
|
|
1122
|
-
return otelApi.context.with(
|
|
1123
|
-
otelCtx,
|
|
1124
|
-
callStreamText
|
|
1125
|
-
);
|
|
1126
|
-
} catch {
|
|
1127
|
-
return callStreamText();
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
async function stream(input) {
|
|
1131
|
-
const messageID = crypto.randomUUID();
|
|
1132
|
-
const resolvedInput = await resolveModelCallInput(input);
|
|
1133
|
-
const modelInfo = getModelInfo(input);
|
|
1134
|
-
if (isBlockedModelCall(resolvedInput)) {
|
|
1135
|
-
throw new LLMError({
|
|
1136
|
-
message: resolvedInput.reason,
|
|
1137
|
-
category: "invalid_request",
|
|
1138
|
-
provider: modelInfo.provider,
|
|
1139
|
-
model: modelInfo.model
|
|
1140
|
-
});
|
|
1141
|
-
}
|
|
1142
|
-
const system = input.system.filter(Boolean).join("\n");
|
|
1143
|
-
if (input.customStreamProvider) {
|
|
1144
|
-
const runCustomStream = async () => await createCustomStream(input);
|
|
1145
|
-
if (!input.retry || input.retry.maxAttempts === 0) {
|
|
1146
|
-
return wrapModelStream(await runCustomStream(), input);
|
|
1147
|
-
}
|
|
1148
|
-
return wrapModelStream(await withRetry(
|
|
1149
|
-
async () => await runCustomStream(),
|
|
1150
|
-
input.retry,
|
|
1151
|
-
input.abort
|
|
1152
|
-
), input);
|
|
1153
|
-
}
|
|
1154
|
-
const toolSet = await buildToolSet({
|
|
1155
|
-
tools: input.tools,
|
|
1156
|
-
cwd: input.cwd,
|
|
1157
|
-
sessionID: input.sessionID,
|
|
1158
|
-
messageID,
|
|
1159
|
-
abort: input.abort,
|
|
1160
|
-
turnTracker: input.turnTracker,
|
|
1161
|
-
host: input.host,
|
|
1162
|
-
middleware: input.middleware,
|
|
1163
|
-
executionMode: input.toolExecutionMode
|
|
1164
|
-
});
|
|
1165
|
-
const allTools = {
|
|
1166
|
-
...toolSet,
|
|
1167
|
-
...input.mcpTools ?? {}
|
|
1168
|
-
};
|
|
1169
|
-
const providerOptions = input.reasoningLevel ? buildReasoningOptionsSync(input.model, input.reasoningLevel) : void 0;
|
|
1170
|
-
const createStream = async () => {
|
|
1171
|
-
try {
|
|
1172
|
-
return await callStreamTextWithOtelContext({
|
|
1173
|
-
input,
|
|
1174
|
-
allTools,
|
|
1175
|
-
system,
|
|
1176
|
-
providerOptions
|
|
1177
|
-
});
|
|
1178
|
-
} catch (error) {
|
|
1179
|
-
throw LLMError.from(error, modelInfo);
|
|
1180
|
-
}
|
|
1181
|
-
};
|
|
1182
|
-
if (!input.retry || input.retry.maxAttempts === 0) {
|
|
1183
|
-
return wrapModelStream(await createStream(), input);
|
|
1184
|
-
}
|
|
1185
|
-
return wrapModelStream(await withRetry(
|
|
1186
|
-
async () => await createStream(),
|
|
1187
|
-
input.retry,
|
|
1188
|
-
input.abort
|
|
1189
|
-
), input);
|
|
1190
|
-
}
|
|
1191
|
-
async function streamOnce(input) {
|
|
1192
|
-
return await stream({ ...input, retry: void 0 });
|
|
1193
|
-
}
|
|
1194
|
-
async function streamStep(input) {
|
|
1195
|
-
return await stream({
|
|
1196
|
-
...input,
|
|
1197
|
-
maxSteps: 1
|
|
1198
|
-
});
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
// src/execution/llm/index.ts
|
|
1202
|
-
var LLM = {
|
|
1203
|
-
buildToolSet,
|
|
1204
|
-
stream,
|
|
1205
|
-
streamOnce,
|
|
1206
|
-
streamStep
|
|
1207
|
-
};
|
|
1208
|
-
|
|
1209
|
-
// src/execution/processor/doom-loop.ts
|
|
659
|
+
// src/runtime/step-processing/doom-loop.ts
|
|
1210
660
|
var DEFAULT_DOOM_LOOP_THRESHOLD = 3;
|
|
1211
661
|
var DoomLoopError = class extends Error {
|
|
1212
662
|
toolName;
|
|
@@ -1280,10 +730,10 @@ async function recordToolCallAndCheckDoomLoop(options) {
|
|
|
1280
730
|
if (processorOptions.enforceDoomLoop ?? true) {
|
|
1281
731
|
throw doomError;
|
|
1282
732
|
}
|
|
1283
|
-
options.warn?.(`[
|
|
733
|
+
options.warn?.(`[StepProcessing] ${doomError.message}`);
|
|
1284
734
|
}
|
|
1285
735
|
|
|
1286
|
-
// src/
|
|
736
|
+
// src/runtime/step-processing/overflow.ts
|
|
1287
737
|
var ContextOverflowError = class extends Error {
|
|
1288
738
|
inputTokens;
|
|
1289
739
|
limit;
|
|
@@ -1310,8 +760,8 @@ async function handleContextOverflow(options) {
|
|
|
1310
760
|
}
|
|
1311
761
|
}
|
|
1312
762
|
|
|
1313
|
-
// src/
|
|
1314
|
-
async function
|
|
763
|
+
// src/runtime/step-processing/process.ts
|
|
764
|
+
async function processStepStream(stream, options) {
|
|
1315
765
|
const { abort, onEvent } = options;
|
|
1316
766
|
const doomLoopThreshold = options.doomLoopThreshold ?? DEFAULT_DOOM_LOOP_THRESHOLD;
|
|
1317
767
|
const maxSteps = options.maxSteps ?? 50;
|
|
@@ -1327,10 +777,10 @@ async function processStream(stream2, options) {
|
|
|
1327
777
|
await onEvent({ type: "step-start", step: stepCount, maxSteps });
|
|
1328
778
|
await onEvent({ type: "status", status: "processing" });
|
|
1329
779
|
try {
|
|
1330
|
-
for await (const rawChunk of
|
|
780
|
+
for await (const rawChunk of stream.fullStream) {
|
|
1331
781
|
const chunk = rawChunk;
|
|
1332
782
|
if (process.env.DEBUG_PROCESSOR) {
|
|
1333
|
-
process.stderr.write(`[
|
|
783
|
+
process.stderr.write(`[step-processing] Chunk received: ${chunk.type}
|
|
1334
784
|
`);
|
|
1335
785
|
}
|
|
1336
786
|
abort.throwIfAborted();
|
|
@@ -1484,10 +934,11 @@ async function processStream(stream2, options) {
|
|
|
1484
934
|
error
|
|
1485
935
|
};
|
|
1486
936
|
}
|
|
937
|
+
var processStream = processStepStream;
|
|
1487
938
|
|
|
1488
939
|
// src/runtime/turn-runner/stream-step.ts
|
|
1489
|
-
function
|
|
1490
|
-
const input = options.preparedStep.
|
|
940
|
+
function buildModelCallContext(options) {
|
|
941
|
+
const input = options.preparedStep.inferenceInput;
|
|
1491
942
|
return {
|
|
1492
943
|
sessionID: input.sessionID,
|
|
1493
944
|
step: input.step ?? options.preparedStep.step,
|
|
@@ -1495,110 +946,121 @@ function buildModelCallContext2(options) {
|
|
|
1495
946
|
abort: input.abort,
|
|
1496
947
|
model: input.model,
|
|
1497
948
|
toolNames: Object.keys(input.tools),
|
|
1498
|
-
mcpToolNames: Object.keys(input.mcpTools ?? {})
|
|
949
|
+
mcpToolNames: Object.keys(input.mcpTools ?? {}),
|
|
950
|
+
scope: snapshotScope()
|
|
1499
951
|
};
|
|
1500
952
|
}
|
|
1501
953
|
async function* runModelStep(options) {
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
eventQueue
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
954
|
+
return yield* streamWithinScope(
|
|
955
|
+
{
|
|
956
|
+
kind: "model",
|
|
957
|
+
name: "model-step",
|
|
958
|
+
sessionId: options.preparedStep.inferenceInput.sessionID,
|
|
959
|
+
step: options.preparedStep.step
|
|
960
|
+
},
|
|
961
|
+
(async function* () {
|
|
962
|
+
const { preparedStep, turnEngine, applyCommitBatch } = options;
|
|
963
|
+
const stream = await Inference.streamStep(preparedStep.inferenceInput);
|
|
964
|
+
const eventQueue = [];
|
|
965
|
+
let resolveNext = null;
|
|
966
|
+
let streamDone = false;
|
|
967
|
+
let streamError;
|
|
968
|
+
const intervention = preparedStep.inferenceInput.intervention;
|
|
969
|
+
const middleware = preparedStep.inferenceInput.middleware;
|
|
970
|
+
if (intervention) {
|
|
971
|
+
intervention.onApplied = (item) => {
|
|
972
|
+
eventQueue.push({
|
|
973
|
+
type: "intervention-applied",
|
|
974
|
+
id: item.id,
|
|
975
|
+
message: item.message
|
|
976
|
+
});
|
|
977
|
+
if (resolveNext) {
|
|
978
|
+
resolveNext();
|
|
979
|
+
resolveNext = null;
|
|
980
|
+
}
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
const processPromise = processStepStream(stream, {
|
|
984
|
+
sessionID: preparedStep.inferenceInput.sessionID,
|
|
985
|
+
abort: preparedStep.inferenceInput.abort,
|
|
986
|
+
currentStep: preparedStep.step,
|
|
987
|
+
maxSteps: preparedStep.stepProcessing.maxSteps,
|
|
988
|
+
doomLoopThreshold: preparedStep.stepProcessing.doomLoopThreshold ?? 3,
|
|
989
|
+
enforceDoomLoop: preparedStep.stepProcessing.enforceDoomLoop ?? true,
|
|
990
|
+
onDoomLoop: preparedStep.stepProcessing.onDoomLoop,
|
|
991
|
+
rememberedDoomLoopTools: options.rememberedDoomLoopTools,
|
|
992
|
+
contextTokenLimit: preparedStep.stepProcessing.contextTokenLimit,
|
|
993
|
+
onContextOverflow: async () => {
|
|
994
|
+
},
|
|
995
|
+
onEvent: async (event) => {
|
|
996
|
+
middleware?.emitEvent(event);
|
|
997
|
+
eventQueue.push(event);
|
|
998
|
+
if (resolveNext) {
|
|
999
|
+
resolveNext();
|
|
1000
|
+
resolveNext = null;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}).then((result2) => {
|
|
1004
|
+
streamDone = true;
|
|
1005
|
+
if (resolveNext) {
|
|
1006
|
+
resolveNext();
|
|
1007
|
+
resolveNext = null;
|
|
1008
|
+
}
|
|
1009
|
+
return result2;
|
|
1010
|
+
}).catch((error) => {
|
|
1011
|
+
streamError = error instanceof Error ? error : new Error(String(error));
|
|
1012
|
+
streamDone = true;
|
|
1013
|
+
if (resolveNext) {
|
|
1014
|
+
resolveNext();
|
|
1015
|
+
resolveNext = null;
|
|
1016
|
+
}
|
|
1017
|
+
return null;
|
|
1516
1018
|
});
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1019
|
+
while (!streamDone || eventQueue.length > 0) {
|
|
1020
|
+
while (eventQueue.length > 0) {
|
|
1021
|
+
const event = eventQueue.shift();
|
|
1022
|
+
turnEngine.recordEvent(event, (/* @__PURE__ */ new Date()).toISOString());
|
|
1023
|
+
yield event;
|
|
1024
|
+
if (event.type === "intervention-applied") {
|
|
1025
|
+
yield* applyCommitBatch(
|
|
1026
|
+
turnEngine.createInterventionCommit({
|
|
1027
|
+
id: event.id,
|
|
1028
|
+
content: event.message
|
|
1029
|
+
})
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
if (!streamDone) {
|
|
1034
|
+
await new Promise((resolve) => {
|
|
1035
|
+
resolveNext = resolve;
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1520
1038
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
const processPromise = processStream(stream2, {
|
|
1524
|
-
sessionID: preparedStep.llmInput.sessionID,
|
|
1525
|
-
abort: preparedStep.llmInput.abort,
|
|
1526
|
-
currentStep: preparedStep.step,
|
|
1527
|
-
maxSteps: preparedStep.processor.maxSteps,
|
|
1528
|
-
doomLoopThreshold: preparedStep.processor.doomLoopThreshold ?? 3,
|
|
1529
|
-
enforceDoomLoop: preparedStep.processor.enforceDoomLoop ?? true,
|
|
1530
|
-
onDoomLoop: preparedStep.processor.onDoomLoop,
|
|
1531
|
-
rememberedDoomLoopTools: options.rememberedDoomLoopTools,
|
|
1532
|
-
contextTokenLimit: preparedStep.processor.contextTokenLimit,
|
|
1533
|
-
onContextOverflow: async () => {
|
|
1534
|
-
},
|
|
1535
|
-
onEvent: async (event) => {
|
|
1536
|
-
middleware?.emitEvent(event);
|
|
1537
|
-
eventQueue.push(event);
|
|
1538
|
-
if (resolveNext) {
|
|
1539
|
-
resolveNext();
|
|
1540
|
-
resolveNext = null;
|
|
1039
|
+
if (streamError) {
|
|
1040
|
+
throw streamError;
|
|
1541
1041
|
}
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
resolveNext();
|
|
1547
|
-
resolveNext = null;
|
|
1548
|
-
}
|
|
1549
|
-
return result2;
|
|
1550
|
-
}).catch((error) => {
|
|
1551
|
-
streamError = error instanceof Error ? error : new Error(String(error));
|
|
1552
|
-
streamDone = true;
|
|
1553
|
-
if (resolveNext) {
|
|
1554
|
-
resolveNext();
|
|
1555
|
-
resolveNext = null;
|
|
1556
|
-
}
|
|
1557
|
-
return null;
|
|
1558
|
-
});
|
|
1559
|
-
while (!streamDone || eventQueue.length > 0) {
|
|
1560
|
-
while (eventQueue.length > 0) {
|
|
1561
|
-
const event = eventQueue.shift();
|
|
1562
|
-
turnEngine.recordEvent(event, (/* @__PURE__ */ new Date()).toISOString());
|
|
1563
|
-
yield event;
|
|
1564
|
-
if (event.type === "intervention-applied") {
|
|
1565
|
-
yield* applyCommitBatch(
|
|
1566
|
-
turnEngine.createInterventionCommit({
|
|
1567
|
-
id: event.id,
|
|
1568
|
-
content: event.message
|
|
1569
|
-
})
|
|
1042
|
+
const result = await processPromise;
|
|
1043
|
+
if (!result) {
|
|
1044
|
+
throw new Error(
|
|
1045
|
+
`Agent step ${preparedStep.step} produced no step-processing result`
|
|
1570
1046
|
);
|
|
1571
1047
|
}
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
)
|
|
1587
|
-
|
|
1588
|
-
if (middleware?.hasMiddleware) {
|
|
1589
|
-
const revised = await middleware.runModelOutput(
|
|
1590
|
-
{
|
|
1591
|
-
text: result.text,
|
|
1592
|
-
usage: result.usage,
|
|
1593
|
-
finishReason: result.finishReason
|
|
1594
|
-
},
|
|
1595
|
-
buildModelCallContext2(options)
|
|
1596
|
-
);
|
|
1597
|
-
result.text = revised.text;
|
|
1598
|
-
result.usage = revised.usage;
|
|
1599
|
-
result.finishReason = revised.finishReason;
|
|
1600
|
-
}
|
|
1601
|
-
return result;
|
|
1048
|
+
if (middleware?.hasMiddleware) {
|
|
1049
|
+
const revised = await middleware.runModelOutput(
|
|
1050
|
+
{
|
|
1051
|
+
text: result.text,
|
|
1052
|
+
usage: result.usage,
|
|
1053
|
+
finishReason: result.finishReason
|
|
1054
|
+
},
|
|
1055
|
+
buildModelCallContext(options)
|
|
1056
|
+
);
|
|
1057
|
+
result.text = revised.text;
|
|
1058
|
+
result.usage = revised.usage;
|
|
1059
|
+
result.finishReason = revised.finishReason;
|
|
1060
|
+
}
|
|
1061
|
+
return result;
|
|
1062
|
+
})()
|
|
1063
|
+
);
|
|
1602
1064
|
}
|
|
1603
1065
|
|
|
1604
1066
|
// src/runtime/turn-runner/tool-batch.ts
|
|
@@ -1635,9 +1097,9 @@ async function runToolBatch(options) {
|
|
|
1635
1097
|
if (toolResultsByCallId.has(toolCall.toolCallId)) {
|
|
1636
1098
|
continue;
|
|
1637
1099
|
}
|
|
1638
|
-
const
|
|
1100
|
+
const tool = options.tools[toolCall.toolName];
|
|
1639
1101
|
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1640
|
-
if (!
|
|
1102
|
+
if (!tool) {
|
|
1641
1103
|
const errorMessage = `Tool '${toolCall.toolName}' is not registered`;
|
|
1642
1104
|
const event = createToolBatchErrorResult({
|
|
1643
1105
|
toolCallId: toolCall.toolCallId,
|
|
@@ -1662,7 +1124,7 @@ async function runToolBatch(options) {
|
|
|
1662
1124
|
try {
|
|
1663
1125
|
const executed = await executeAgentToolCall({
|
|
1664
1126
|
toolName: toolCall.toolName,
|
|
1665
|
-
tool
|
|
1127
|
+
tool,
|
|
1666
1128
|
params: toolCall.args,
|
|
1667
1129
|
cwd: options.cwd,
|
|
1668
1130
|
abort: options.abort,
|
|
@@ -1725,26 +1187,43 @@ async function runToolBatch(options) {
|
|
|
1725
1187
|
|
|
1726
1188
|
// src/runtime/turn-runner/commit.ts
|
|
1727
1189
|
async function* commitStep(options) {
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1190
|
+
return yield* streamWithinScope(
|
|
1191
|
+
{
|
|
1192
|
+
kind: "commit",
|
|
1193
|
+
name: "step-commit",
|
|
1194
|
+
step: options.step
|
|
1195
|
+
},
|
|
1196
|
+
(async function* () {
|
|
1197
|
+
if (options.finishReason !== "tool-calls") {
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
const batch = options.turnEngine.consumeStepCommit(options.step);
|
|
1201
|
+
if (!batch) {
|
|
1202
|
+
return false;
|
|
1203
|
+
}
|
|
1204
|
+
yield* options.applyCommitBatch(batch);
|
|
1205
|
+
return true;
|
|
1206
|
+
})()
|
|
1207
|
+
);
|
|
1737
1208
|
}
|
|
1738
1209
|
async function* commitOutput(options) {
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1210
|
+
return yield* streamWithinScope(
|
|
1211
|
+
{
|
|
1212
|
+
kind: "commit",
|
|
1213
|
+
name: "output-commit"
|
|
1214
|
+
},
|
|
1215
|
+
(async function* () {
|
|
1216
|
+
const batch = options.turnEngine.createOutputCommit({
|
|
1217
|
+
text: options.text,
|
|
1218
|
+
usage: options.usage
|
|
1219
|
+
});
|
|
1220
|
+
if (!batch) {
|
|
1221
|
+
return false;
|
|
1222
|
+
}
|
|
1223
|
+
yield* options.applyCommitBatch(batch, { emitMessages: true });
|
|
1224
|
+
return true;
|
|
1225
|
+
})()
|
|
1226
|
+
);
|
|
1748
1227
|
}
|
|
1749
1228
|
|
|
1750
1229
|
// src/runtime/workflow-state.ts
|
|
@@ -2110,22 +1589,9 @@ export {
|
|
|
2110
1589
|
AgentTurnEngine,
|
|
2111
1590
|
createAgentTurnEngine,
|
|
2112
1591
|
prepareModelStep,
|
|
2113
|
-
isRetryableCategory,
|
|
2114
|
-
LLMError,
|
|
2115
|
-
isRetryable,
|
|
2116
|
-
getRetryDelay,
|
|
2117
|
-
getErrorCategory,
|
|
2118
|
-
DEFAULT_RETRY_CONFIG,
|
|
2119
|
-
createRetryState,
|
|
2120
|
-
calculateDelay,
|
|
2121
|
-
sleep,
|
|
2122
|
-
withRetry,
|
|
2123
|
-
createRetryHandler,
|
|
2124
|
-
shouldRetry,
|
|
2125
|
-
OUTPUT_TOKEN_MAX,
|
|
2126
|
-
LLM,
|
|
2127
1592
|
DoomLoopError,
|
|
2128
1593
|
ContextOverflowError,
|
|
1594
|
+
processStepStream,
|
|
2129
1595
|
processStream,
|
|
2130
1596
|
runModelStep,
|
|
2131
1597
|
runToolBatch,
|