@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.
Files changed (57) hide show
  1. package/README.md +5 -1
  2. package/dist/{builder-BKkipazh.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-3C4VKG4P.js → chunk-3HNO5SVI.js} +273 -807
  5. package/dist/chunk-5K7AQVOU.js +619 -0
  6. package/dist/{chunk-QAQADS4X.js → chunk-BNSHUWCV.js} +1 -0
  7. package/dist/{chunk-O2ZCFQL6.js → chunk-CDTV2UYU.js} +86 -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-DZQJD_hp.d.ts → index-C33hlD6H.d.ts} +12 -7
  17. package/dist/{index-ipP3_ztp.d.ts → index-CfBGYrpd.d.ts} +121 -2
  18. package/dist/index.d.ts +107 -126
  19. package/dist/index.js +321 -601
  20. package/dist/inference/index.d.ts +59 -0
  21. package/dist/inference/index.js +25 -0
  22. package/dist/middleware/index.d.ts +7 -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 +9 -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-G1wxEgac.d.ts → runner-DSKaEz3z.d.ts} +35 -8
  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 +7 -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-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-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
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
- 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,7 +623,7 @@ 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,
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
- processor: {
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/execution/llm/toolset.ts
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?.(`[Processor] ${doomError.message}`);
733
+ options.warn?.(`[StepProcessing] ${doomError.message}`);
1284
734
  }
1285
735
 
1286
- // src/execution/processor/overflow.ts
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/execution/processor/process.ts
1314
- async function processStream(stream2, options) {
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 stream2.fullStream) {
780
+ for await (const rawChunk of stream.fullStream) {
1331
781
  const chunk = rawChunk;
1332
782
  if (process.env.DEBUG_PROCESSOR) {
1333
- process.stderr.write(`[processor] Chunk received: ${chunk.type}
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 buildModelCallContext2(options) {
1490
- const input = options.preparedStep.llmInput;
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
- const { preparedStep, turnEngine, applyCommitBatch } = options;
1503
- const stream2 = await LLM.streamStep(preparedStep.llmInput);
1504
- const eventQueue = [];
1505
- let resolveNext = null;
1506
- let streamDone = false;
1507
- let streamError;
1508
- const intervention = preparedStep.llmInput.intervention;
1509
- const middleware = preparedStep.llmInput.middleware;
1510
- if (intervention) {
1511
- intervention.onApplied = (item) => {
1512
- eventQueue.push({
1513
- type: "intervention-applied",
1514
- id: item.id,
1515
- 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;
1516
1018
  });
1517
- if (resolveNext) {
1518
- resolveNext();
1519
- 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
+ }
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
- }).then((result2) => {
1544
- streamDone = true;
1545
- if (resolveNext) {
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
- if (!streamDone) {
1574
- await new Promise((resolve) => {
1575
- resolveNext = resolve;
1576
- });
1577
- }
1578
- }
1579
- if (streamError) {
1580
- throw streamError;
1581
- }
1582
- const result = await processPromise;
1583
- if (!result) {
1584
- throw new Error(
1585
- `Agent step ${preparedStep.step} produced no processor result`
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 tool2 = options.tools[toolCall.toolName];
1100
+ const tool = options.tools[toolCall.toolName];
1639
1101
  const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1640
- if (!tool2) {
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: tool2,
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
- if (options.finishReason !== "tool-calls") {
1729
- return false;
1730
- }
1731
- const batch = options.turnEngine.consumeStepCommit(options.step);
1732
- if (!batch) {
1733
- return false;
1734
- }
1735
- yield* options.applyCommitBatch(batch);
1736
- 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
+ );
1737
1208
  }
1738
1209
  async function* commitOutput(options) {
1739
- const batch = options.turnEngine.createOutputCommit({
1740
- text: options.text,
1741
- usage: options.usage
1742
- });
1743
- if (!batch) {
1744
- return false;
1745
- }
1746
- yield* options.applyCommitBatch(batch, { emitMessages: true });
1747
- 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
+ );
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,