@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.
Files changed (57) hide show
  1. package/README.md +85 -372
  2. package/dist/{builder-RcTZuYnO.d.ts → builder-BRvqCcIk.d.ts} +2 -2
  3. package/dist/{resolver-DOfZ-xuk.d.ts → capability-resolver-CgRGsWVX.d.ts} +1 -1
  4. package/dist/{chunk-IMGQOTU2.js → chunk-3HNO5SVI.js} +286 -690
  5. package/dist/chunk-5K7AQVOU.js +619 -0
  6. package/dist/{chunk-QAQADS4X.js → chunk-BNSHUWCV.js} +1 -0
  7. package/dist/{chunk-OTUGSCED.js → chunk-CDTV2UYU.js} +159 -1
  8. package/dist/chunk-IEFIQENH.js +73 -0
  9. package/dist/chunk-N7P4PN3O.js +84 -0
  10. package/dist/{chunk-QWFMX226.js → chunk-QGOGIP7T.js} +148 -15
  11. package/dist/chunk-VNQBHPCT.js +398 -0
  12. package/dist/{chunk-X635CM2F.js → chunk-ZPMACVZK.js} +1 -1
  13. package/dist/context/index.js +1 -1
  14. package/dist/host/index.d.ts +45 -0
  15. package/dist/host/index.js +8 -0
  16. package/dist/{index-p0kOsVsE.d.ts → index-C33hlD6H.d.ts} +12 -7
  17. package/dist/{index-tmhaADz5.d.ts → index-CfBGYrpd.d.ts} +121 -2
  18. package/dist/index.d.ts +107 -126
  19. package/dist/index.js +322 -597
  20. package/dist/inference/index.d.ts +59 -0
  21. package/dist/inference/index.js +25 -0
  22. package/dist/middleware/index.d.ts +8 -4
  23. package/dist/middleware/index.js +5 -3
  24. package/dist/models/index.d.ts +104 -2
  25. package/dist/models/index.js +40 -6
  26. package/dist/prompt/index.d.ts +10 -6
  27. package/dist/reasoning/index.d.ts +54 -8
  28. package/dist/reasoning/index.js +2 -3
  29. package/dist/{registry-CuRWWtcT.d.ts → registry-BDLIHOQB.d.ts} +1 -1
  30. package/dist/{runner-C7aMP_x3.d.ts → runner-DSKaEz3z.d.ts} +290 -7
  31. package/dist/runtime/index.d.ts +41 -7
  32. package/dist/runtime/index.js +15 -6
  33. package/dist/scope/index.d.ts +10 -0
  34. package/dist/scope/index.js +14 -0
  35. package/dist/{session-manager-Uawm2Le7.d.ts → session-manager-B_CWGTsl.d.ts} +1 -1
  36. package/dist/skill/index.d.ts +7 -5
  37. package/dist/storage/index.d.ts +2 -2
  38. package/dist/sub-agent/index.d.ts +12 -8
  39. package/dist/tool/index.d.ts +8 -4
  40. package/dist/tool/index.js +4 -3
  41. package/dist/{tool-pFAnJc5Y.d.ts → tool-Db1Ue-1U.d.ts} +1 -1
  42. package/dist/{tool-DYp6-cC3.d.ts → tool-HUtkiVBx.d.ts} +5 -99
  43. package/dist/tracking/index.d.ts +3 -1
  44. package/dist/types-9jGQUjqW.d.ts +29 -0
  45. package/dist/types-CHiPh8U2.d.ts +100 -0
  46. package/dist/types-CqDZTh4d.d.ts +335 -0
  47. package/dist/types-FRpzzg_9.d.ts +355 -0
  48. package/package.json +19 -8
  49. package/dist/capabilities/index.d.ts +0 -97
  50. package/dist/capabilities/index.js +0 -46
  51. package/dist/chunk-6TDTQJ4P.js +0 -116
  52. package/dist/chunk-DWYX7ASF.js +0 -26
  53. package/dist/chunk-FG4MD5MU.js +0 -54
  54. package/dist/config-D2xeGEHK.d.ts +0 -52
  55. package/dist/identifiers-BLUxFqV_.d.ts +0 -12
  56. package/dist/network-D76DS5ot.d.ts +0 -5
  57. 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-QAQADS4X.js";
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
- buildReasoningOptionsSync
9
- } from "./chunk-X635CM2F.js";
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-runner.ts
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-runner.ts
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
- const run = {
246
- payload,
247
- context,
248
- sessionId,
249
- startedAt
250
- };
251
- const toolCalls = [];
252
- let turnState = createAgentTurnState({
253
- sessionId,
254
- startedAt
255
- });
256
- const createSnapshot = () => ({
257
- sessionId,
258
- response: turnState.response,
259
- usage: { ...turnState.usage },
260
- toolCalls: toolCalls.map((toolCall) => ({ ...toolCall })),
261
- eventCount: turnState.eventCount,
262
- activeStep: turnState.step > 0 ? turnState.step : void 0,
263
- lastEvent: turnState.lastEvent,
264
- error: turnState.error,
265
- startedAt: turnState.startedAt,
266
- updatedAt: turnState.updatedAt,
267
- turnState
268
- });
269
- const emitCheckpoint = async (reason, event) => {
270
- if (baseObservers.length === 0) {
271
- return;
272
- }
273
- const checkpoint = {
274
- run,
275
- reason,
276
- snapshot: createSnapshot(),
277
- event,
278
- createdAt: turnState.updatedAt
279
- };
280
- await notifyObservers(baseObservers, async (observer) => {
281
- await observer.onCheckpoint?.(checkpoint);
282
- });
283
- };
284
- await notifyObservers(baseObservers, async (observer) => {
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 snapshot = createSnapshot();
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
- snapshot
297
+ createdAt: turnState.updatedAt
298
+ };
299
+ await notifyObservers(baseObservers, async (observer) => {
300
+ await observer.onCheckpoint?.(checkpoint);
307
301
  });
308
- if (checkpointReason) {
309
- await emitCheckpoint(checkpointReason, event);
310
- }
311
- if (event.type === "error") {
312
- throw event.error;
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
- const result = {
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
- llmInput: {
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
- processor: {
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/execution/llm/toolset.ts
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?.(`[Processor] ${doomError.message}`);
733
+ options.warn?.(`[StepProcessing] ${doomError.message}`);
1179
734
  }
1180
735
 
1181
- // src/execution/processor/overflow.ts
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/execution/processor/process.ts
1209
- async function processStream(stream2, options) {
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 stream2.fullStream) {
780
+ for await (const rawChunk of stream.fullStream) {
1226
781
  const chunk = rawChunk;
1227
782
  if (process.env.DEBUG_PROCESSOR) {
1228
- process.stderr.write(`[processor] Chunk received: ${chunk.type}
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
- const { preparedStep, turnEngine, applyCommitBatch } = options;
1386
- const stream2 = await LLM.streamStep(preparedStep.llmInput);
1387
- const eventQueue = [];
1388
- let resolveNext = null;
1389
- let streamDone = false;
1390
- let streamError;
1391
- const intervention = preparedStep.llmInput.intervention;
1392
- const middleware = preparedStep.llmInput.middleware;
1393
- if (intervention) {
1394
- intervention.onApplied = (item) => {
1395
- eventQueue.push({
1396
- type: "intervention-applied",
1397
- id: item.id,
1398
- message: item.message
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
- if (resolveNext) {
1401
- resolveNext();
1402
- resolveNext = null;
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
- }).then((result2) => {
1427
- streamDone = true;
1428
- if (resolveNext) {
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
- if (!streamDone) {
1457
- await new Promise((resolve) => {
1458
- resolveNext = resolve;
1459
- });
1460
- }
1461
- }
1462
- if (streamError) {
1463
- throw streamError;
1464
- }
1465
- const result = await processPromise;
1466
- if (!result) {
1467
- throw new Error(
1468
- `Agent step ${preparedStep.step} produced no processor result`
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 tool2 = options.tools[toolCall.toolName];
1100
+ const tool = options.tools[toolCall.toolName];
1509
1101
  const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1510
- if (!tool2) {
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: tool2,
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
- if (options.finishReason !== "tool-calls") {
1599
- return false;
1600
- }
1601
- const batch = options.turnEngine.consumeStepCommit(options.step);
1602
- if (!batch) {
1603
- return false;
1604
- }
1605
- yield* options.applyCommitBatch(batch);
1606
- return true;
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
- const batch = options.turnEngine.createOutputCommit({
1610
- text: options.text,
1611
- usage: options.usage
1612
- });
1613
- if (!batch) {
1614
- return false;
1615
- }
1616
- yield* options.applyCommitBatch(batch, { emitMessages: true });
1617
- return true;
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,