@cuylabs/agent-core 0.5.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 +85 -372
- package/dist/{builder-RcTZuYnO.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-IMGQOTU2.js → chunk-3HNO5SVI.js} +286 -690
- package/dist/chunk-5K7AQVOU.js +619 -0
- package/dist/{chunk-QAQADS4X.js → chunk-BNSHUWCV.js} +1 -0
- package/dist/{chunk-OTUGSCED.js → chunk-CDTV2UYU.js} +159 -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-p0kOsVsE.d.ts → index-C33hlD6H.d.ts} +12 -7
- package/dist/{index-tmhaADz5.d.ts → index-CfBGYrpd.d.ts} +121 -2
- package/dist/index.d.ts +107 -126
- package/dist/index.js +322 -597
- package/dist/inference/index.d.ts +59 -0
- package/dist/inference/index.js +25 -0
- package/dist/middleware/index.d.ts +8 -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 +10 -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-C7aMP_x3.d.ts → runner-DSKaEz3z.d.ts} +290 -7
- 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 +8 -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-MM1JoX5T.d.ts +0 -810
|
@@ -1,14 +1,20 @@
|
|
|
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
|
-
// src/runtime/observer.ts
|
|
17
|
+
// src/runtime/task/observer.ts
|
|
12
18
|
function defaultAgentTaskCheckpointStrategy(input) {
|
|
13
19
|
switch (input.event.type) {
|
|
14
20
|
case "step-finish":
|
|
@@ -26,7 +32,7 @@ function defaultAgentTaskCheckpointStrategy(input) {
|
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
// src/runtime/task
|
|
35
|
+
// src/runtime/task/runner.ts
|
|
30
36
|
import { randomUUID } from "crypto";
|
|
31
37
|
|
|
32
38
|
// src/runtime/turn-state.ts
|
|
@@ -197,7 +203,7 @@ function failAgentTurnState(state, error, updatedAt) {
|
|
|
197
203
|
};
|
|
198
204
|
}
|
|
199
205
|
|
|
200
|
-
// src/runtime/task
|
|
206
|
+
// src/runtime/task/runner.ts
|
|
201
207
|
function normalizeNonEmpty(value, label) {
|
|
202
208
|
const normalized = value.trim();
|
|
203
209
|
if (!normalized) {
|
|
@@ -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,8 +623,9 @@ function prepareModelStep(options) {
|
|
|
602
623
|
step: options.step,
|
|
603
624
|
messages: options.messages,
|
|
604
625
|
modelMessages,
|
|
605
|
-
|
|
626
|
+
inferenceInput: {
|
|
606
627
|
sessionID: options.sessionId,
|
|
628
|
+
step: options.step,
|
|
607
629
|
model: options.config.model,
|
|
608
630
|
system: options.systemPrompts,
|
|
609
631
|
messages: modelMessages,
|
|
@@ -624,7 +646,7 @@ function prepareModelStep(options) {
|
|
|
624
646
|
toolExecutionMode: options.toolExecutionMode,
|
|
625
647
|
telemetry: options.config.telemetry
|
|
626
648
|
},
|
|
627
|
-
|
|
649
|
+
stepProcessing: {
|
|
628
650
|
maxSteps: options.config.maxSteps,
|
|
629
651
|
doomLoopThreshold: options.config.doomLoopThreshold,
|
|
630
652
|
enforceDoomLoop: options.config.enforceDoomLoop,
|
|
@@ -634,474 +656,7 @@ function prepareModelStep(options) {
|
|
|
634
656
|
};
|
|
635
657
|
}
|
|
636
658
|
|
|
637
|
-
// src/
|
|
638
|
-
import { tool, zodSchema } from "ai";
|
|
639
|
-
async function buildToolSet(options) {
|
|
640
|
-
const toolSet = {};
|
|
641
|
-
const executionMode = options.executionMode ?? "auto";
|
|
642
|
-
for (const [id, info] of Object.entries(options.tools)) {
|
|
643
|
-
const initialized = await info.init({ cwd: options.cwd });
|
|
644
|
-
toolSet[id] = executionMode === "auto" ? tool({
|
|
645
|
-
description: initialized.description,
|
|
646
|
-
inputSchema: zodSchema(initialized.parameters),
|
|
647
|
-
execute: async (params) => (await executeAgentToolCall({
|
|
648
|
-
toolName: id,
|
|
649
|
-
tool: info,
|
|
650
|
-
params,
|
|
651
|
-
cwd: options.cwd,
|
|
652
|
-
abort: options.abort,
|
|
653
|
-
sessionID: options.sessionID,
|
|
654
|
-
messageID: options.messageID,
|
|
655
|
-
...options.host ? { host: options.host } : {},
|
|
656
|
-
...options.turnTracker ? { turnTracker: options.turnTracker } : {},
|
|
657
|
-
...options.middleware ? { middleware: options.middleware } : {}
|
|
658
|
-
})).output
|
|
659
|
-
}) : tool({
|
|
660
|
-
description: initialized.description,
|
|
661
|
-
inputSchema: zodSchema(initialized.parameters)
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
return toolSet;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// src/execution/llm/stream.ts
|
|
668
|
-
import {
|
|
669
|
-
stepCountIs,
|
|
670
|
-
streamText
|
|
671
|
-
} from "ai";
|
|
672
|
-
|
|
673
|
-
// src/errors/classify.ts
|
|
674
|
-
function isRetryableCategory(category) {
|
|
675
|
-
switch (category) {
|
|
676
|
-
case "rate_limit":
|
|
677
|
-
case "overloaded":
|
|
678
|
-
case "network":
|
|
679
|
-
case "timeout":
|
|
680
|
-
return true;
|
|
681
|
-
case "auth":
|
|
682
|
-
case "invalid_request":
|
|
683
|
-
case "context_overflow":
|
|
684
|
-
case "content_filter":
|
|
685
|
-
case "cancelled":
|
|
686
|
-
case "unknown":
|
|
687
|
-
return false;
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
function classifyFromStatusAndMessage(status, message) {
|
|
691
|
-
const lowerMessage = message.toLowerCase();
|
|
692
|
-
if (status) {
|
|
693
|
-
if (status === 429) return "rate_limit";
|
|
694
|
-
if (status === 401 || status === 403) return "auth";
|
|
695
|
-
if (status === 400) {
|
|
696
|
-
if (lowerMessage.includes("context") || lowerMessage.includes("token")) {
|
|
697
|
-
return "context_overflow";
|
|
698
|
-
}
|
|
699
|
-
return "invalid_request";
|
|
700
|
-
}
|
|
701
|
-
if (status === 503 || status === 502) return "overloaded";
|
|
702
|
-
if (status >= 500) return "network";
|
|
703
|
-
}
|
|
704
|
-
if (lowerMessage.includes("rate") && lowerMessage.includes("limit")) {
|
|
705
|
-
return "rate_limit";
|
|
706
|
-
}
|
|
707
|
-
if (lowerMessage.includes("overload") || lowerMessage.includes("capacity")) {
|
|
708
|
-
return "overloaded";
|
|
709
|
-
}
|
|
710
|
-
if (lowerMessage.includes("too_many_requests")) {
|
|
711
|
-
return "rate_limit";
|
|
712
|
-
}
|
|
713
|
-
if (lowerMessage.includes("unauthorized") || lowerMessage.includes("invalid api key")) {
|
|
714
|
-
return "auth";
|
|
715
|
-
}
|
|
716
|
-
if (lowerMessage.includes("context") && lowerMessage.includes("length")) {
|
|
717
|
-
return "context_overflow";
|
|
718
|
-
}
|
|
719
|
-
if (lowerMessage.includes("content") && lowerMessage.includes("filter")) {
|
|
720
|
-
return "content_filter";
|
|
721
|
-
}
|
|
722
|
-
if (lowerMessage.includes("timeout") || lowerMessage.includes("timed out")) {
|
|
723
|
-
return "timeout";
|
|
724
|
-
}
|
|
725
|
-
if (lowerMessage.includes("network") || lowerMessage.includes("econnrefused") || lowerMessage.includes("econnreset")) {
|
|
726
|
-
return "network";
|
|
727
|
-
}
|
|
728
|
-
return "unknown";
|
|
729
|
-
}
|
|
730
|
-
function parseRetryDelay(headers) {
|
|
731
|
-
const retryAfterMs = headers["retry-after-ms"];
|
|
732
|
-
if (retryAfterMs) {
|
|
733
|
-
const parsed = parseFloat(retryAfterMs);
|
|
734
|
-
if (!Number.isNaN(parsed) && parsed > 0) {
|
|
735
|
-
return parsed;
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
const retryAfter = headers["retry-after"];
|
|
739
|
-
if (retryAfter) {
|
|
740
|
-
const seconds = parseFloat(retryAfter);
|
|
741
|
-
if (!Number.isNaN(seconds) && seconds > 0) {
|
|
742
|
-
return Math.ceil(seconds * 1e3);
|
|
743
|
-
}
|
|
744
|
-
const dateMs = Date.parse(retryAfter);
|
|
745
|
-
if (!Number.isNaN(dateMs)) {
|
|
746
|
-
const delayMs = dateMs - Date.now();
|
|
747
|
-
if (delayMs > 0) {
|
|
748
|
-
return Math.ceil(delayMs);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
return void 0;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
// src/errors/extract.ts
|
|
756
|
-
function extractFromAISDKError(error) {
|
|
757
|
-
const result = {};
|
|
758
|
-
const anyError = error;
|
|
759
|
-
if (typeof anyError.status === "number") {
|
|
760
|
-
result.status = anyError.status;
|
|
761
|
-
} else if (typeof anyError.statusCode === "number") {
|
|
762
|
-
result.status = anyError.statusCode;
|
|
763
|
-
}
|
|
764
|
-
if (anyError.responseHeaders && typeof anyError.responseHeaders === "object") {
|
|
765
|
-
result.headers = anyError.responseHeaders;
|
|
766
|
-
} else if (anyError.headers && typeof anyError.headers === "object") {
|
|
767
|
-
result.headers = anyError.headers;
|
|
768
|
-
}
|
|
769
|
-
if (anyError.data && typeof anyError.data === "object") {
|
|
770
|
-
const data = anyError.data;
|
|
771
|
-
if (data.type === "error" && typeof data.error === "object") {
|
|
772
|
-
const innerError = data.error;
|
|
773
|
-
if (innerError.type === "too_many_requests") {
|
|
774
|
-
result.category = "rate_limit";
|
|
775
|
-
} else if (innerError.type === "overloaded") {
|
|
776
|
-
result.category = "overloaded";
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
if (typeof data.isRetryable === "boolean" && !data.isRetryable && !result.category) {
|
|
780
|
-
result.category = "invalid_request";
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
return result;
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
// src/errors/llm-error.ts
|
|
787
|
-
var LLMError = class _LLMError extends Error {
|
|
788
|
-
category;
|
|
789
|
-
status;
|
|
790
|
-
headers;
|
|
791
|
-
provider;
|
|
792
|
-
model;
|
|
793
|
-
isRetryable;
|
|
794
|
-
retryDelayMs;
|
|
795
|
-
constructor(options) {
|
|
796
|
-
super(options.message, { cause: options.cause });
|
|
797
|
-
this.name = "LLMError";
|
|
798
|
-
this.status = options.status;
|
|
799
|
-
this.headers = options.headers;
|
|
800
|
-
this.provider = options.provider;
|
|
801
|
-
this.model = options.model;
|
|
802
|
-
this.category = options.category ?? classifyFromStatusAndMessage(
|
|
803
|
-
options.status,
|
|
804
|
-
options.message
|
|
805
|
-
);
|
|
806
|
-
this.isRetryable = isRetryableCategory(this.category);
|
|
807
|
-
this.retryDelayMs = this.headers ? parseRetryDelay(this.headers) : void 0;
|
|
808
|
-
}
|
|
809
|
-
static from(error, context) {
|
|
810
|
-
if (error instanceof _LLMError) {
|
|
811
|
-
return error;
|
|
812
|
-
}
|
|
813
|
-
if (error instanceof Error) {
|
|
814
|
-
if (error.name === "AbortError" || error.message.includes("abort")) {
|
|
815
|
-
return new _LLMError({
|
|
816
|
-
message: error.message,
|
|
817
|
-
category: "cancelled",
|
|
818
|
-
cause: error,
|
|
819
|
-
...context
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
return new _LLMError({
|
|
823
|
-
message: error.message,
|
|
824
|
-
cause: error,
|
|
825
|
-
...extractFromAISDKError(error),
|
|
826
|
-
...context
|
|
827
|
-
});
|
|
828
|
-
}
|
|
829
|
-
return new _LLMError({
|
|
830
|
-
message: String(error),
|
|
831
|
-
category: "unknown",
|
|
832
|
-
...context
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
|
-
get description() {
|
|
836
|
-
const parts = [this.message];
|
|
837
|
-
if (this.provider) parts.unshift(`[${this.provider}]`);
|
|
838
|
-
if (this.status) parts.push(`(HTTP ${this.status})`);
|
|
839
|
-
if (this.isRetryable && this.retryDelayMs) {
|
|
840
|
-
parts.push(`retry in ${Math.ceil(this.retryDelayMs / 1e3)}s`);
|
|
841
|
-
}
|
|
842
|
-
return parts.join(" ");
|
|
843
|
-
}
|
|
844
|
-
};
|
|
845
|
-
|
|
846
|
-
// src/errors/utils.ts
|
|
847
|
-
function isRetryable(error) {
|
|
848
|
-
if (error instanceof LLMError) {
|
|
849
|
-
return error.isRetryable;
|
|
850
|
-
}
|
|
851
|
-
return LLMError.from(error).isRetryable;
|
|
852
|
-
}
|
|
853
|
-
function getRetryDelay(error) {
|
|
854
|
-
if (error instanceof LLMError) {
|
|
855
|
-
return error.isRetryable ? error.retryDelayMs : void 0;
|
|
856
|
-
}
|
|
857
|
-
const llmError = LLMError.from(error);
|
|
858
|
-
return llmError.isRetryable ? llmError.retryDelayMs : void 0;
|
|
859
|
-
}
|
|
860
|
-
function getErrorCategory(error) {
|
|
861
|
-
if (error instanceof LLMError) {
|
|
862
|
-
return error.category;
|
|
863
|
-
}
|
|
864
|
-
return LLMError.from(error).category;
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
// src/retry.ts
|
|
868
|
-
var DEFAULT_RETRY_CONFIG = {
|
|
869
|
-
maxAttempts: 3,
|
|
870
|
-
initialDelayMs: 2e3,
|
|
871
|
-
backoffFactor: 2,
|
|
872
|
-
maxDelayMs: 3e4,
|
|
873
|
-
jitter: true
|
|
874
|
-
};
|
|
875
|
-
function createRetryState() {
|
|
876
|
-
return {
|
|
877
|
-
attempt: 0,
|
|
878
|
-
errors: [],
|
|
879
|
-
canRetry: true,
|
|
880
|
-
nextDelayMs: void 0
|
|
881
|
-
};
|
|
882
|
-
}
|
|
883
|
-
function calculateDelay(attempt, error, config) {
|
|
884
|
-
if (error?.retryDelayMs) {
|
|
885
|
-
return error.retryDelayMs;
|
|
886
|
-
}
|
|
887
|
-
const baseDelay = config.initialDelayMs * Math.pow(config.backoffFactor, attempt - 1);
|
|
888
|
-
const cappedDelay = Math.min(baseDelay, config.maxDelayMs);
|
|
889
|
-
if (config.jitter) {
|
|
890
|
-
const jitterRange = cappedDelay * 0.25;
|
|
891
|
-
const jitter = (Math.random() - 0.5) * 2 * jitterRange;
|
|
892
|
-
return Math.max(0, Math.round(cappedDelay + jitter));
|
|
893
|
-
}
|
|
894
|
-
return Math.round(cappedDelay);
|
|
895
|
-
}
|
|
896
|
-
async function sleep(ms, signal) {
|
|
897
|
-
return new Promise((resolve, reject) => {
|
|
898
|
-
if (signal?.aborted) {
|
|
899
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
900
|
-
return;
|
|
901
|
-
}
|
|
902
|
-
const timeoutId = setTimeout(() => {
|
|
903
|
-
cleanup();
|
|
904
|
-
resolve();
|
|
905
|
-
}, ms);
|
|
906
|
-
const abortHandler = () => {
|
|
907
|
-
clearTimeout(timeoutId);
|
|
908
|
-
cleanup();
|
|
909
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
910
|
-
};
|
|
911
|
-
const cleanup = () => {
|
|
912
|
-
signal?.removeEventListener("abort", abortHandler);
|
|
913
|
-
};
|
|
914
|
-
signal?.addEventListener("abort", abortHandler, { once: true });
|
|
915
|
-
});
|
|
916
|
-
}
|
|
917
|
-
async function withRetry(fn, config, signal) {
|
|
918
|
-
const mergedConfig = { ...DEFAULT_RETRY_CONFIG, ...config };
|
|
919
|
-
const state = createRetryState();
|
|
920
|
-
while (true) {
|
|
921
|
-
state.attempt++;
|
|
922
|
-
try {
|
|
923
|
-
return await fn(state.attempt);
|
|
924
|
-
} catch (error) {
|
|
925
|
-
const llmError = LLMError.from(error);
|
|
926
|
-
state.errors.push(llmError);
|
|
927
|
-
const shouldRetry2 = state.attempt < mergedConfig.maxAttempts && isRetryable(llmError) && !signal?.aborted;
|
|
928
|
-
if (!shouldRetry2) {
|
|
929
|
-
throw new LLMError({
|
|
930
|
-
message: `Failed after ${state.attempt} attempt(s): ${llmError.message}`,
|
|
931
|
-
category: llmError.category,
|
|
932
|
-
status: llmError.status,
|
|
933
|
-
headers: llmError.headers,
|
|
934
|
-
provider: llmError.provider,
|
|
935
|
-
model: llmError.model,
|
|
936
|
-
cause: llmError
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
const delayMs = calculateDelay(state.attempt, llmError, mergedConfig);
|
|
940
|
-
state.nextDelayMs = delayMs;
|
|
941
|
-
config?.onRetry?.(state.attempt, delayMs, llmError);
|
|
942
|
-
await sleep(delayMs, signal);
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
function createRetryHandler(options) {
|
|
947
|
-
const config = options ?? {};
|
|
948
|
-
const signal = options?.signal;
|
|
949
|
-
return async (createStream) => {
|
|
950
|
-
return withRetry(createStream, config, signal);
|
|
951
|
-
};
|
|
952
|
-
}
|
|
953
|
-
function shouldRetry(error, attempt, maxAttempts = DEFAULT_RETRY_CONFIG.maxAttempts) {
|
|
954
|
-
if (attempt >= maxAttempts) return false;
|
|
955
|
-
return isRetryable(error);
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
// src/execution/llm/types.ts
|
|
959
|
-
var OUTPUT_TOKEN_MAX = 32e3;
|
|
960
|
-
|
|
961
|
-
// src/execution/llm/stream.ts
|
|
962
|
-
async function createCustomStream(input) {
|
|
963
|
-
const system = input.system.filter(Boolean).join("\n");
|
|
964
|
-
return input.customStreamProvider({
|
|
965
|
-
system,
|
|
966
|
-
messages: input.messages,
|
|
967
|
-
abortSignal: input.abort,
|
|
968
|
-
maxSteps: input.maxSteps
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
function getModelInfo(input) {
|
|
972
|
-
return {
|
|
973
|
-
provider: typeof input.model === "object" && "provider" in input.model ? String(input.model.provider) : void 0,
|
|
974
|
-
model: typeof input.model === "object" && "modelId" in input.model ? String(input.model.modelId) : String(input.model)
|
|
975
|
-
};
|
|
976
|
-
}
|
|
977
|
-
async function callStreamTextWithOtelContext(options) {
|
|
978
|
-
const { input, allTools, system, providerOptions } = options;
|
|
979
|
-
const callStreamText = () => streamText({
|
|
980
|
-
model: input.model,
|
|
981
|
-
system,
|
|
982
|
-
messages: input.messages,
|
|
983
|
-
tools: allTools,
|
|
984
|
-
stopWhen: stepCountIs(input.maxSteps ?? 50),
|
|
985
|
-
maxOutputTokens: input.maxOutputTokens ?? OUTPUT_TOKEN_MAX,
|
|
986
|
-
temperature: input.temperature,
|
|
987
|
-
topP: input.topP,
|
|
988
|
-
abortSignal: input.abort,
|
|
989
|
-
providerOptions,
|
|
990
|
-
experimental_telemetry: input.telemetry,
|
|
991
|
-
prepareStep: input.intervention ? async ({ messages }) => {
|
|
992
|
-
const pending = input.intervention.drainImmediate();
|
|
993
|
-
if (pending.length === 0) {
|
|
994
|
-
return void 0;
|
|
995
|
-
}
|
|
996
|
-
const injected = pending.map((item) => ({
|
|
997
|
-
role: "user",
|
|
998
|
-
content: item.message
|
|
999
|
-
}));
|
|
1000
|
-
for (const item of pending) {
|
|
1001
|
-
input.intervention.onApplied?.(item);
|
|
1002
|
-
}
|
|
1003
|
-
return { messages: [...messages, ...injected] };
|
|
1004
|
-
} : void 0,
|
|
1005
|
-
onStepFinish: async (step) => {
|
|
1006
|
-
if (!input.onStepFinish) {
|
|
1007
|
-
return;
|
|
1008
|
-
}
|
|
1009
|
-
await input.onStepFinish({
|
|
1010
|
-
toolResults: step.toolResults?.map((toolResult) => ({
|
|
1011
|
-
toolName: toolResult.toolName,
|
|
1012
|
-
toolCallId: toolResult.toolCallId,
|
|
1013
|
-
output: toolResult.output
|
|
1014
|
-
})),
|
|
1015
|
-
usage: step.usage,
|
|
1016
|
-
finishReason: step.finishReason
|
|
1017
|
-
});
|
|
1018
|
-
}
|
|
1019
|
-
});
|
|
1020
|
-
const otelCtx = input.middleware?.getOtelContext(input.sessionID);
|
|
1021
|
-
if (!otelCtx) {
|
|
1022
|
-
return callStreamText();
|
|
1023
|
-
}
|
|
1024
|
-
try {
|
|
1025
|
-
const otelApi = await import("@opentelemetry/api");
|
|
1026
|
-
return otelApi.context.with(
|
|
1027
|
-
otelCtx,
|
|
1028
|
-
callStreamText
|
|
1029
|
-
);
|
|
1030
|
-
} catch {
|
|
1031
|
-
return callStreamText();
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
async function stream(input) {
|
|
1035
|
-
const messageID = crypto.randomUUID();
|
|
1036
|
-
const system = input.system.filter(Boolean).join("\n");
|
|
1037
|
-
if (input.customStreamProvider) {
|
|
1038
|
-
const runCustomStream = async () => await createCustomStream(input);
|
|
1039
|
-
if (!input.retry || input.retry.maxAttempts === 0) {
|
|
1040
|
-
return await runCustomStream();
|
|
1041
|
-
}
|
|
1042
|
-
return await withRetry(
|
|
1043
|
-
async () => await runCustomStream(),
|
|
1044
|
-
input.retry,
|
|
1045
|
-
input.abort
|
|
1046
|
-
);
|
|
1047
|
-
}
|
|
1048
|
-
const toolSet = await buildToolSet({
|
|
1049
|
-
tools: input.tools,
|
|
1050
|
-
cwd: input.cwd,
|
|
1051
|
-
sessionID: input.sessionID,
|
|
1052
|
-
messageID,
|
|
1053
|
-
abort: input.abort,
|
|
1054
|
-
turnTracker: input.turnTracker,
|
|
1055
|
-
host: input.host,
|
|
1056
|
-
middleware: input.middleware,
|
|
1057
|
-
executionMode: input.toolExecutionMode
|
|
1058
|
-
});
|
|
1059
|
-
const allTools = {
|
|
1060
|
-
...toolSet,
|
|
1061
|
-
...input.mcpTools ?? {}
|
|
1062
|
-
};
|
|
1063
|
-
const providerOptions = input.reasoningLevel ? buildReasoningOptionsSync(input.model, input.reasoningLevel) : void 0;
|
|
1064
|
-
const modelInfo = getModelInfo(input);
|
|
1065
|
-
const createStream = async () => {
|
|
1066
|
-
try {
|
|
1067
|
-
return await callStreamTextWithOtelContext({
|
|
1068
|
-
input,
|
|
1069
|
-
allTools,
|
|
1070
|
-
system,
|
|
1071
|
-
providerOptions
|
|
1072
|
-
});
|
|
1073
|
-
} catch (error) {
|
|
1074
|
-
throw LLMError.from(error, modelInfo);
|
|
1075
|
-
}
|
|
1076
|
-
};
|
|
1077
|
-
if (!input.retry || input.retry.maxAttempts === 0) {
|
|
1078
|
-
return await createStream();
|
|
1079
|
-
}
|
|
1080
|
-
return await withRetry(
|
|
1081
|
-
async () => await createStream(),
|
|
1082
|
-
input.retry,
|
|
1083
|
-
input.abort
|
|
1084
|
-
);
|
|
1085
|
-
}
|
|
1086
|
-
async function streamOnce(input) {
|
|
1087
|
-
return await stream({ ...input, retry: void 0 });
|
|
1088
|
-
}
|
|
1089
|
-
async function streamStep(input) {
|
|
1090
|
-
return await stream({
|
|
1091
|
-
...input,
|
|
1092
|
-
maxSteps: 1
|
|
1093
|
-
});
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
// src/execution/llm/index.ts
|
|
1097
|
-
var LLM = {
|
|
1098
|
-
buildToolSet,
|
|
1099
|
-
stream,
|
|
1100
|
-
streamOnce,
|
|
1101
|
-
streamStep
|
|
1102
|
-
};
|
|
1103
|
-
|
|
1104
|
-
// src/execution/processor/doom-loop.ts
|
|
659
|
+
// src/runtime/step-processing/doom-loop.ts
|
|
1105
660
|
var DEFAULT_DOOM_LOOP_THRESHOLD = 3;
|
|
1106
661
|
var DoomLoopError = class extends Error {
|
|
1107
662
|
toolName;
|
|
@@ -1175,10 +730,10 @@ async function recordToolCallAndCheckDoomLoop(options) {
|
|
|
1175
730
|
if (processorOptions.enforceDoomLoop ?? true) {
|
|
1176
731
|
throw doomError;
|
|
1177
732
|
}
|
|
1178
|
-
options.warn?.(`[
|
|
733
|
+
options.warn?.(`[StepProcessing] ${doomError.message}`);
|
|
1179
734
|
}
|
|
1180
735
|
|
|
1181
|
-
// src/
|
|
736
|
+
// src/runtime/step-processing/overflow.ts
|
|
1182
737
|
var ContextOverflowError = class extends Error {
|
|
1183
738
|
inputTokens;
|
|
1184
739
|
limit;
|
|
@@ -1205,8 +760,8 @@ async function handleContextOverflow(options) {
|
|
|
1205
760
|
}
|
|
1206
761
|
}
|
|
1207
762
|
|
|
1208
|
-
// src/
|
|
1209
|
-
async function
|
|
763
|
+
// src/runtime/step-processing/process.ts
|
|
764
|
+
async function processStepStream(stream, options) {
|
|
1210
765
|
const { abort, onEvent } = options;
|
|
1211
766
|
const doomLoopThreshold = options.doomLoopThreshold ?? DEFAULT_DOOM_LOOP_THRESHOLD;
|
|
1212
767
|
const maxSteps = options.maxSteps ?? 50;
|
|
@@ -1222,10 +777,10 @@ async function processStream(stream2, options) {
|
|
|
1222
777
|
await onEvent({ type: "step-start", step: stepCount, maxSteps });
|
|
1223
778
|
await onEvent({ type: "status", status: "processing" });
|
|
1224
779
|
try {
|
|
1225
|
-
for await (const rawChunk of
|
|
780
|
+
for await (const rawChunk of stream.fullStream) {
|
|
1226
781
|
const chunk = rawChunk;
|
|
1227
782
|
if (process.env.DEBUG_PROCESSOR) {
|
|
1228
|
-
process.stderr.write(`[
|
|
783
|
+
process.stderr.write(`[step-processing] Chunk received: ${chunk.type}
|
|
1229
784
|
`);
|
|
1230
785
|
}
|
|
1231
786
|
abort.throwIfAborted();
|
|
@@ -1379,96 +934,133 @@ async function processStream(stream2, options) {
|
|
|
1379
934
|
error
|
|
1380
935
|
};
|
|
1381
936
|
}
|
|
937
|
+
var processStream = processStepStream;
|
|
1382
938
|
|
|
1383
939
|
// src/runtime/turn-runner/stream-step.ts
|
|
940
|
+
function buildModelCallContext(options) {
|
|
941
|
+
const input = options.preparedStep.inferenceInput;
|
|
942
|
+
return {
|
|
943
|
+
sessionID: input.sessionID,
|
|
944
|
+
step: input.step ?? options.preparedStep.step,
|
|
945
|
+
cwd: input.cwd,
|
|
946
|
+
abort: input.abort,
|
|
947
|
+
model: input.model,
|
|
948
|
+
toolNames: Object.keys(input.tools),
|
|
949
|
+
mcpToolNames: Object.keys(input.mcpTools ?? {}),
|
|
950
|
+
scope: snapshotScope()
|
|
951
|
+
};
|
|
952
|
+
}
|
|
1384
953
|
async function* runModelStep(options) {
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
eventQueue
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
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;
|
|
1399
1018
|
});
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
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
|
+
}
|
|
1403
1038
|
}
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
const processPromise = processStream(stream2, {
|
|
1407
|
-
sessionID: preparedStep.llmInput.sessionID,
|
|
1408
|
-
abort: preparedStep.llmInput.abort,
|
|
1409
|
-
currentStep: preparedStep.step,
|
|
1410
|
-
maxSteps: preparedStep.processor.maxSteps,
|
|
1411
|
-
doomLoopThreshold: preparedStep.processor.doomLoopThreshold ?? 3,
|
|
1412
|
-
enforceDoomLoop: preparedStep.processor.enforceDoomLoop ?? true,
|
|
1413
|
-
onDoomLoop: preparedStep.processor.onDoomLoop,
|
|
1414
|
-
rememberedDoomLoopTools: options.rememberedDoomLoopTools,
|
|
1415
|
-
contextTokenLimit: preparedStep.processor.contextTokenLimit,
|
|
1416
|
-
onContextOverflow: async () => {
|
|
1417
|
-
},
|
|
1418
|
-
onEvent: async (event) => {
|
|
1419
|
-
middleware?.emitEvent(event);
|
|
1420
|
-
eventQueue.push(event);
|
|
1421
|
-
if (resolveNext) {
|
|
1422
|
-
resolveNext();
|
|
1423
|
-
resolveNext = null;
|
|
1039
|
+
if (streamError) {
|
|
1040
|
+
throw streamError;
|
|
1424
1041
|
}
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
resolveNext();
|
|
1430
|
-
resolveNext = null;
|
|
1431
|
-
}
|
|
1432
|
-
return result2;
|
|
1433
|
-
}).catch((error) => {
|
|
1434
|
-
streamError = error instanceof Error ? error : new Error(String(error));
|
|
1435
|
-
streamDone = true;
|
|
1436
|
-
if (resolveNext) {
|
|
1437
|
-
resolveNext();
|
|
1438
|
-
resolveNext = null;
|
|
1439
|
-
}
|
|
1440
|
-
return null;
|
|
1441
|
-
});
|
|
1442
|
-
while (!streamDone || eventQueue.length > 0) {
|
|
1443
|
-
while (eventQueue.length > 0) {
|
|
1444
|
-
const event = eventQueue.shift();
|
|
1445
|
-
turnEngine.recordEvent(event, (/* @__PURE__ */ new Date()).toISOString());
|
|
1446
|
-
yield event;
|
|
1447
|
-
if (event.type === "intervention-applied") {
|
|
1448
|
-
yield* applyCommitBatch(
|
|
1449
|
-
turnEngine.createInterventionCommit({
|
|
1450
|
-
id: event.id,
|
|
1451
|
-
content: event.message
|
|
1452
|
-
})
|
|
1042
|
+
const result = await processPromise;
|
|
1043
|
+
if (!result) {
|
|
1044
|
+
throw new Error(
|
|
1045
|
+
`Agent step ${preparedStep.step} produced no step-processing result`
|
|
1453
1046
|
);
|
|
1454
1047
|
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
)
|
|
1470
|
-
|
|
1471
|
-
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
|
+
);
|
|
1472
1064
|
}
|
|
1473
1065
|
|
|
1474
1066
|
// src/runtime/turn-runner/tool-batch.ts
|
|
@@ -1505,9 +1097,9 @@ async function runToolBatch(options) {
|
|
|
1505
1097
|
if (toolResultsByCallId.has(toolCall.toolCallId)) {
|
|
1506
1098
|
continue;
|
|
1507
1099
|
}
|
|
1508
|
-
const
|
|
1100
|
+
const tool = options.tools[toolCall.toolName];
|
|
1509
1101
|
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1510
|
-
if (!
|
|
1102
|
+
if (!tool) {
|
|
1511
1103
|
const errorMessage = `Tool '${toolCall.toolName}' is not registered`;
|
|
1512
1104
|
const event = createToolBatchErrorResult({
|
|
1513
1105
|
toolCallId: toolCall.toolCallId,
|
|
@@ -1532,7 +1124,7 @@ async function runToolBatch(options) {
|
|
|
1532
1124
|
try {
|
|
1533
1125
|
const executed = await executeAgentToolCall({
|
|
1534
1126
|
toolName: toolCall.toolName,
|
|
1535
|
-
tool
|
|
1127
|
+
tool,
|
|
1536
1128
|
params: toolCall.args,
|
|
1537
1129
|
cwd: options.cwd,
|
|
1538
1130
|
abort: options.abort,
|
|
@@ -1595,26 +1187,43 @@ async function runToolBatch(options) {
|
|
|
1595
1187
|
|
|
1596
1188
|
// src/runtime/turn-runner/commit.ts
|
|
1597
1189
|
async function* commitStep(options) {
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
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
|
+
);
|
|
1607
1208
|
}
|
|
1608
1209
|
async function* commitOutput(options) {
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
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
|
+
);
|
|
1618
1227
|
}
|
|
1619
1228
|
|
|
1620
1229
|
// src/runtime/workflow-state.ts
|
|
@@ -1980,22 +1589,9 @@ export {
|
|
|
1980
1589
|
AgentTurnEngine,
|
|
1981
1590
|
createAgentTurnEngine,
|
|
1982
1591
|
prepareModelStep,
|
|
1983
|
-
isRetryableCategory,
|
|
1984
|
-
LLMError,
|
|
1985
|
-
isRetryable,
|
|
1986
|
-
getRetryDelay,
|
|
1987
|
-
getErrorCategory,
|
|
1988
|
-
DEFAULT_RETRY_CONFIG,
|
|
1989
|
-
createRetryState,
|
|
1990
|
-
calculateDelay,
|
|
1991
|
-
sleep,
|
|
1992
|
-
withRetry,
|
|
1993
|
-
createRetryHandler,
|
|
1994
|
-
shouldRetry,
|
|
1995
|
-
OUTPUT_TOKEN_MAX,
|
|
1996
|
-
LLM,
|
|
1997
1592
|
DoomLoopError,
|
|
1998
1593
|
ContextOverflowError,
|
|
1594
|
+
processStepStream,
|
|
1999
1595
|
processStream,
|
|
2000
1596
|
runModelStep,
|
|
2001
1597
|
runToolBatch,
|