@travisliu/open-dynamic-workflow 0.3.1 → 0.3.5

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 (128) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +43 -17
  3. package/dist/agents/codex-exec.js +3 -1
  4. package/dist/agents/codex-exec.js.map +1 -1
  5. package/dist/agents/cursor-agent.d.ts +21 -0
  6. package/dist/agents/cursor-agent.js +171 -0
  7. package/dist/agents/cursor-agent.js.map +1 -0
  8. package/dist/agents/execute-agent.js +1 -1
  9. package/dist/agents/execute-agent.js.map +1 -1
  10. package/dist/agents/registry.js +2 -0
  11. package/dist/agents/registry.js.map +1 -1
  12. package/dist/artifacts/call-cache.d.ts +27 -3
  13. package/dist/artifacts/call-cache.js +160 -59
  14. package/dist/artifacts/call-cache.js.map +1 -1
  15. package/dist/artifacts/run-store.js.map +1 -1
  16. package/dist/cli/commands/doctor.js +0 -4
  17. package/dist/cli/commands/doctor.js.map +1 -1
  18. package/dist/cli/commands/init.js.map +1 -1
  19. package/dist/cli/commands/run.js +2 -1
  20. package/dist/cli/commands/run.js.map +1 -1
  21. package/dist/cli/commands/validate.js +2 -1
  22. package/dist/cli/commands/validate.js.map +1 -1
  23. package/dist/cli/init/prompts.d.ts +1 -1
  24. package/dist/cli/init/prompts.js +4 -4
  25. package/dist/cli/init/prompts.js.map +1 -1
  26. package/dist/cli/init/renderer.js +2 -1
  27. package/dist/cli/init/renderer.js.map +1 -1
  28. package/dist/config/defaults.js +2 -1
  29. package/dist/config/defaults.js.map +1 -1
  30. package/dist/config/load.js +1 -1
  31. package/dist/config/load.js.map +1 -1
  32. package/dist/config/schema.js +3 -0
  33. package/dist/config/schema.js.map +1 -1
  34. package/dist/config/types.d.ts +1 -0
  35. package/dist/discovery/collect-files.js +2 -2
  36. package/dist/discovery/collect-files.js.map +1 -1
  37. package/dist/discovery/definition-call.js +1 -1
  38. package/dist/discovery/definition-call.js.map +1 -1
  39. package/dist/discovery/file-patterns.js +1 -1
  40. package/dist/discovery/file-patterns.js.map +1 -1
  41. package/dist/discovery/schema-summary.js.map +1 -1
  42. package/dist/loop/artifacts.d.ts +39 -0
  43. package/dist/loop/artifacts.js +58 -0
  44. package/dist/loop/artifacts.js.map +1 -0
  45. package/dist/loop/context.d.ts +55 -0
  46. package/dist/loop/context.js +134 -0
  47. package/dist/loop/context.js.map +1 -0
  48. package/dist/loop/events.d.ts +62 -0
  49. package/dist/loop/events.js +68 -0
  50. package/dist/loop/events.js.map +1 -0
  51. package/dist/loop/id.d.ts +24 -0
  52. package/dist/loop/id.js +65 -0
  53. package/dist/loop/id.js.map +1 -0
  54. package/dist/loop/index.d.ts +8 -0
  55. package/dist/loop/index.js +9 -0
  56. package/dist/loop/index.js.map +1 -0
  57. package/dist/loop/replay.d.ts +47 -0
  58. package/dist/loop/replay.js +104 -0
  59. package/dist/loop/replay.js.map +1 -0
  60. package/dist/loop/results.d.ts +74 -0
  61. package/dist/loop/results.js +101 -0
  62. package/dist/loop/results.js.map +1 -0
  63. package/dist/loop/run.d.ts +22 -0
  64. package/dist/loop/run.js +671 -0
  65. package/dist/loop/run.js.map +1 -0
  66. package/dist/loop/summary.d.ts +5 -0
  67. package/dist/loop/summary.js +16 -0
  68. package/dist/loop/summary.js.map +1 -0
  69. package/dist/loop/types.d.ts +120 -0
  70. package/dist/loop/types.js +2 -0
  71. package/dist/loop/types.js.map +1 -0
  72. package/dist/loop/validate.d.ts +9 -0
  73. package/dist/loop/validate.js +122 -0
  74. package/dist/loop/validate.js.map +1 -0
  75. package/dist/orchestration/scheduler.js +1 -1
  76. package/dist/orchestration/scheduler.js.map +1 -1
  77. package/dist/output/events.d.ts +49 -1
  78. package/dist/output/events.js.map +1 -1
  79. package/dist/output/failed-artifacts.js +5 -0
  80. package/dist/output/failed-artifacts.js.map +1 -1
  81. package/dist/output/json-reporter.d.ts +2 -2
  82. package/dist/output/json-reporter.js +1 -1
  83. package/dist/output/json-reporter.js.map +1 -1
  84. package/dist/output/jsonl-reporter.d.ts +3 -4
  85. package/dist/output/jsonl-reporter.js +2 -2
  86. package/dist/output/jsonl-reporter.js.map +1 -1
  87. package/dist/output/pretty-renderer.js +15 -0
  88. package/dist/output/pretty-renderer.js.map +1 -1
  89. package/dist/output/pretty-reporter.js +35 -4
  90. package/dist/output/pretty-reporter.js.map +1 -1
  91. package/dist/output/pretty-view-builder.js +70 -1
  92. package/dist/output/pretty-view-builder.js.map +1 -1
  93. package/dist/output/pretty-view.d.ts +12 -2
  94. package/dist/output/verbose-formatter.d.ts +4 -1
  95. package/dist/output/verbose-formatter.js +67 -0
  96. package/dist/output/verbose-formatter.js.map +1 -1
  97. package/dist/pipeline/stage-barrier.js.map +1 -1
  98. package/dist/pipeline/validate.js +1 -1
  99. package/dist/pipeline/validate.js.map +1 -1
  100. package/dist/shared-agents/load.js +0 -2
  101. package/dist/shared-agents/load.js.map +1 -1
  102. package/dist/tools/load.js.map +1 -1
  103. package/dist/types/config.d.ts +1 -0
  104. package/dist/types/workflow.d.ts +13 -0
  105. package/dist/workflow/discovery.d.ts +1 -0
  106. package/dist/workflow/discovery.js +6 -4
  107. package/dist/workflow/discovery.js.map +1 -1
  108. package/dist/workflow/dsl.d.ts +1 -0
  109. package/dist/workflow/dsl.js +281 -137
  110. package/dist/workflow/dsl.js.map +1 -1
  111. package/dist/workflow/errors.js +1 -1
  112. package/dist/workflow/errors.js.map +1 -1
  113. package/dist/workflow/invocation-manager.js +14 -2
  114. package/dist/workflow/invocation-manager.js.map +1 -1
  115. package/dist/workflow/resolve-target.js +1 -1
  116. package/dist/workflow/resolve-target.js.map +1 -1
  117. package/dist/workflow/runtime.js +6 -1
  118. package/dist/workflow/runtime.js.map +1 -1
  119. package/dist/workflow/sandbox.js +1 -0
  120. package/dist/workflow/sandbox.js.map +1 -1
  121. package/dist/workflow/scope.d.ts +1 -1
  122. package/dist/workflow/scope.js +2 -15
  123. package/dist/workflow/scope.js.map +1 -1
  124. package/dist/workflow/types.d.ts +3 -0
  125. package/dist/workflow/validate.d.ts +2 -0
  126. package/dist/workflow/validate.js +369 -46
  127. package/dist/workflow/validate.js.map +1 -1
  128. package/package.json +5 -2
@@ -77,6 +77,7 @@ export interface WorkflowDiscoveryConfig {
77
77
  export interface WorkflowConfig {
78
78
  discovery: WorkflowDiscoveryConfig;
79
79
  maxDepth: number;
80
+ maxLoopRounds: number;
80
81
  }
81
82
  export interface OrchestrationConfig {
82
83
  concurrency?: number;
@@ -3,6 +3,7 @@ import type { JsonObject, JsonValue, WorkflowStatus } from "./common.js";
3
3
  import type { SerializedError } from "./errors.js";
4
4
  import type { PipelineStage, PipelineOptions, PipelineResult, PipelineSummary } from "../pipeline/types.js";
5
5
  import type { ToolSummary, ToolCallInput, ToolSettledResult } from "./tool.js";
6
+ import type { LoopInput, LoopSettledResult, LoopSummary } from "../loop/types.js";
6
7
  export type { PipelineStage, PipelineOptions, PipelineResult, PipelineSummary };
7
8
  export interface WorkflowMeta {
8
9
  name: string;
@@ -90,6 +91,17 @@ export interface WorkflowRuntimeContext {
90
91
  workflow<T = JsonValue>(input: WorkflowThrowCallInput): Promise<T>;
91
92
  workflow<T = JsonValue>(input: WorkflowSettledCallInput): Promise<WorkflowSettledResult<T>>;
92
93
  workflow<T = JsonValue>(input: WorkflowCallInput): Promise<T | WorkflowSettledResult<T>>;
94
+ loop<TState>(input: LoopInput<TState> & {
95
+ options: {
96
+ failureMode?: "throw";
97
+ };
98
+ }): Promise<TState>;
99
+ loop<TState>(input: LoopInput<TState> & {
100
+ options: {
101
+ failureMode: "settled";
102
+ };
103
+ }): Promise<LoopSettledResult<TState>>;
104
+ loop<TState>(input: LoopInput<TState>): Promise<TState | LoopSettledResult<TState>>;
93
105
  }
94
106
  export interface WorkflowIdentity {
95
107
  name: string;
@@ -117,6 +129,7 @@ export interface WorkflowRunResult {
117
129
  pipelines?: PipelineSummary[] | undefined;
118
130
  workflows?: WorkflowInvocationSummary[] | undefined;
119
131
  tools?: ToolSummary[] | undefined;
132
+ loops?: LoopSummary[] | undefined;
120
133
  startedAt: string;
121
134
  finishedAt: string;
122
135
  durationMs: number;
@@ -11,5 +11,6 @@ export interface DiscoverWorkflowRegistryInput {
11
11
  candidatePaths?: string[] | undefined;
12
12
  allowDynamicSharedAgentIds?: boolean;
13
13
  toolRegistry?: ToolRegistry;
14
+ maxLoopRounds?: number;
14
15
  }
15
16
  export declare function discoverWorkflowRegistry(input: DiscoverWorkflowRegistryInput): Promise<WorkflowRegistry>;
@@ -9,7 +9,7 @@ import { ErrorCode } from "../errors/codes.js";
9
9
  import { walk, matchGlob, getGlobBaseDir } from "../discovery/file-patterns.js";
10
10
  export { walk, matchGlob, getGlobBaseDir };
11
11
  export async function discoverWorkflowRegistry(input) {
12
- const { rootWorkflowPath, cwd, include, sharedAgentRegistry, candidatePaths } = input;
12
+ const { rootWorkflowPath, cwd, include, sharedAgentRegistry, candidatePaths, maxLoopRounds } = input;
13
13
  const absoluteCwd = resolve(cwd);
14
14
  const absoluteRootPath = resolve(absoluteCwd, rootWorkflowPath);
15
15
  const canonicalCwd = await fs.realpath(absoluteCwd).catch(() => absoluteCwd);
@@ -48,7 +48,7 @@ export async function discoverWorkflowRegistry(input) {
48
48
  try {
49
49
  canonicalPath = await fs.realpath(absolutePath);
50
50
  }
51
- catch (err) {
51
+ catch {
52
52
  canonicalPath = absolutePath;
53
53
  }
54
54
  // Safety check: ensure path is within CWD
@@ -81,7 +81,8 @@ export async function discoverWorkflowRegistry(input) {
81
81
  allowImports: false,
82
82
  sharedAgentRegistry,
83
83
  allowDynamicSharedAgentIds: input.allowDynamicSharedAgentIds,
84
- toolRegistry: input.toolRegistry
84
+ toolRegistry: input.toolRegistry,
85
+ maxLoopRounds
85
86
  });
86
87
  }
87
88
  const def = {
@@ -127,7 +128,8 @@ export async function discoverWorkflowRegistry(input) {
127
128
  sharedAgentRegistry,
128
129
  allowDynamicSharedAgentIds: input.allowDynamicSharedAgentIds,
129
130
  toolRegistry: input.toolRegistry,
130
- rootWorkflowPath: absoluteRootPath
131
+ rootWorkflowPath: absoluteRootPath,
132
+ maxLoopRounds
131
133
  });
132
134
  return registry;
133
135
  }
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/workflow/discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/workflow/discovery.ts"],"names":[],"mappings":"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"}
@@ -10,4 +10,5 @@ export declare function createDsl(runtime: RuntimeState): {
10
10
  parallel: <T>(tasks: Record<string, () => Promise<T>> | Array<() => Promise<T>>) => Promise<Record<string, T> | T[]>;
11
11
  pipeline: <I, O>(items: I[], stages: PipelineStage<any, any>[], options?: PipelineOptions) => Promise<PipelineResult<O>>;
12
12
  workflow: <T>(input: WorkflowCallInput) => Promise<T | WorkflowSettledResult<T>>;
13
+ loop: (input: any) => Promise<unknown>;
13
14
  };
@@ -12,6 +12,9 @@ import { serializeError } from "../errors/serialize.js";
12
12
  import { cloneJsonValue } from "./json.js";
13
13
  import { getActiveWorkflowInvocation } from "./invocation-types.js";
14
14
  import { assertToolAllowed, withToolForbidden } from "./scope.js";
15
+ import { runLoop } from "../loop/run.js";
16
+ import { getActiveLoopContext, recordLoopChildAgentId } from "../loop/context.js";
17
+ import { createLoopAgentId, normalizeLoopLabel } from "../loop/id.js";
15
18
  function normalizeToolCallInput(input, runtime) {
16
19
  if (!input || typeof input !== "object" || Array.isArray(input)) {
17
20
  throw new InvalidDslCallError("tool() requires an input object.");
@@ -166,6 +169,13 @@ export function createDsl(runtime) {
166
169
  normalizedId = runtime.idGenerator ? runtime.idGenerator.nextId("agent") : `agent-${++runtime.agentCounter}`;
167
170
  }
168
171
  }
172
+ const activeLoop = getActiveLoopContext();
173
+ if (activeLoop) {
174
+ const activeInvocation = getActiveWorkflowInvocation();
175
+ const isChildWorkflow = !!(activeInvocation && activeLoop.workflowInvocationId && activeInvocation.workflowInvocationId !== activeLoop.workflowInvocationId);
176
+ normalizedId = resolveLoopAgentId(normalizedId, input, activeLoop, isChildWorkflow, runtime);
177
+ recordLoopChildAgentId(normalizedId);
178
+ }
169
179
  if (activePipeline) {
170
180
  recordChildAgentId(normalizedId);
171
181
  }
@@ -180,7 +190,7 @@ export function createDsl(runtime) {
180
190
  });
181
191
  const sequence = (runtime.callSequence ?? 0) + 1;
182
192
  runtime.callSequence = sequence;
183
- const callId = resolveCallId(input);
193
+ const callId = resolveCallId(input, normalizedId);
184
194
  const fingerprint = computeAgentFingerprint({
185
195
  call: input,
186
196
  provider: normalizedProvider,
@@ -208,7 +218,8 @@ export function createDsl(runtime) {
208
218
  model: resolved.model,
209
219
  permissions: resolvedPermissions
210
220
  });
211
- runtime.agentResults.push(cachedResult);
221
+ const artifactResult = cachedResult.__artifactResult || cachedResult;
222
+ runtime.agentResults.push(artifactResult);
212
223
  runtime.eventSink?.emit("agent.cache_hit", {
213
224
  agentId: normalizedId,
214
225
  label: input.label,
@@ -218,7 +229,7 @@ export function createDsl(runtime) {
218
229
  callId,
219
230
  previousRunId: runtime.callCache.previousRunId,
220
231
  previousAgentId: cachedEntry.agentId,
221
- artifacts: cachedResult.artifacts
232
+ artifacts: artifactResult.artifacts
222
233
  });
223
234
  await recordAgentCall({
224
235
  store: runtime.artifactStore,
@@ -226,7 +237,7 @@ export function createDsl(runtime) {
226
237
  sequence,
227
238
  callId,
228
239
  fingerprint,
229
- result: cachedResult
240
+ result: artifactResult
230
241
  });
231
242
  return cachedResult;
232
243
  }
@@ -244,10 +255,16 @@ export function createDsl(runtime) {
244
255
  let finalSignal = schedulerSignal;
245
256
  let onAbort;
246
257
  const invocationSignal = activeInvocation?.signal;
247
- if ((activePipeline && activePipeline.stageSignal) || invocationSignal) {
258
+ const activeLoop = getActiveLoopContext();
259
+ const loopSignal = activeLoop?.signal;
260
+ if ((activePipeline && activePipeline.stageSignal) || invocationSignal || loopSignal) {
248
261
  const combinedController = new AbortController();
249
262
  onAbort = () => {
250
- combinedController.abort(schedulerSignal.reason || activePipeline?.stageSignal?.reason || invocationSignal?.reason || "Aborted");
263
+ combinedController.abort(schedulerSignal.reason ||
264
+ activePipeline?.stageSignal?.reason ||
265
+ invocationSignal?.reason ||
266
+ loopSignal?.reason ||
267
+ "Aborted");
251
268
  };
252
269
  if (schedulerSignal.aborted) {
253
270
  combinedController.abort(schedulerSignal.reason);
@@ -258,12 +275,20 @@ export function createDsl(runtime) {
258
275
  else if (invocationSignal?.aborted) {
259
276
  combinedController.abort(invocationSignal.reason);
260
277
  }
278
+ else if (loopSignal?.aborted) {
279
+ combinedController.abort(loopSignal.reason);
280
+ }
261
281
  else {
262
282
  schedulerSignal.addEventListener("abort", onAbort);
263
283
  if (activePipeline?.stageSignal) {
264
284
  activePipeline.stageSignal.addEventListener("abort", onAbort);
265
285
  }
266
- invocationSignal?.addEventListener("abort", onAbort);
286
+ if (invocationSignal) {
287
+ invocationSignal.addEventListener("abort", onAbort);
288
+ }
289
+ if (loopSignal) {
290
+ loopSignal.addEventListener("abort", onAbort);
291
+ }
267
292
  }
268
293
  finalSignal = combinedController.signal;
269
294
  }
@@ -299,6 +324,7 @@ export function createDsl(runtime) {
299
324
  activePipeline.stageSignal.removeEventListener("abort", onAbort);
300
325
  }
301
326
  invocationSignal?.removeEventListener("abort", onAbort);
327
+ loopSignal?.removeEventListener("abort", onAbort);
302
328
  }
303
329
  }
304
330
  }
@@ -342,6 +368,10 @@ export function createDsl(runtime) {
342
368
  if (!input || typeof input !== "object") {
343
369
  throw new InvalidDslCallError("agent() requires an input object.");
344
370
  }
371
+ const activeLoop = getActiveLoopContext();
372
+ if (activeLoop?.signal.aborted) {
373
+ throw activeLoop.signal.reason;
374
+ }
345
375
  if ("definition" in input && input.definition !== undefined) {
346
376
  if (!runtime.sharedAgentRegistry) {
347
377
  throw new OpenDynamicWorkflowError(ErrorCode.SHARED_AGENT_NOT_FOUND, "Shared agent registry is not available.");
@@ -434,8 +464,93 @@ export function createDsl(runtime) {
434
464
  }
435
465
  return runDirectAgent(input);
436
466
  };
467
+ const workflowFunction = async (input) => {
468
+ const activeInvocation = getActiveWorkflowInvocation();
469
+ if (!activeInvocation) {
470
+ throw new OpenDynamicWorkflowError(ErrorCode.WORKFLOW_FAILED, "workflow() can only be called from within a workflow invocation.");
471
+ }
472
+ if (!runtime.invocationManager) {
473
+ throw new OpenDynamicWorkflowError(ErrorCode.WORKFLOW_FAILED, "Workflow invocation manager is not available.");
474
+ }
475
+ const activeLoop = getActiveLoopContext();
476
+ if (activeLoop?.signal.aborted) {
477
+ throw activeLoop.signal.reason;
478
+ }
479
+ let effectiveParent = activeInvocation;
480
+ let onAbort;
481
+ if (activeLoop?.signal) {
482
+ const combinedController = new AbortController();
483
+ onAbort = () => {
484
+ combinedController.abort(activeLoop.signal.reason || activeInvocation.signal.reason || "Aborted");
485
+ };
486
+ if (activeLoop.signal.aborted) {
487
+ combinedController.abort(activeLoop.signal.reason);
488
+ }
489
+ else if (activeInvocation.signal.aborted) {
490
+ combinedController.abort(activeInvocation.signal.reason);
491
+ }
492
+ else {
493
+ activeLoop.signal.addEventListener("abort", onAbort);
494
+ activeInvocation.signal.addEventListener("abort", onAbort);
495
+ }
496
+ effectiveParent = {
497
+ ...activeInvocation,
498
+ signal: combinedController.signal,
499
+ abortController: combinedController,
500
+ };
501
+ }
502
+ try {
503
+ const result = await runtime.invocationManager.invokeChild(effectiveParent, input);
504
+ return result;
505
+ }
506
+ finally {
507
+ if (onAbort) {
508
+ activeLoop?.signal.removeEventListener("abort", onAbort);
509
+ activeInvocation.signal.removeEventListener("abort", onAbort);
510
+ }
511
+ }
512
+ };
513
+ const parallelFunction = async (tasks) => {
514
+ if (!tasks || typeof tasks !== "object") {
515
+ throw new InvalidDslCallError("parallel() requires an array or an object of task thunks.");
516
+ }
517
+ const activeLoop = getActiveLoopContext();
518
+ if (activeLoop?.signal.aborted) {
519
+ throw activeLoop.signal.reason;
520
+ }
521
+ if (Array.isArray(tasks)) {
522
+ const promises = tasks.map((task, idx) => {
523
+ if (typeof task !== "function") {
524
+ throw new InvalidDslCallError(`parallel() task at index ${idx} must be a function.`);
525
+ }
526
+ return withToolForbidden("parallel-task", () => task());
527
+ });
528
+ return Promise.all(promises);
529
+ }
530
+ else {
531
+ const keys = Object.keys(tasks);
532
+ const promises = keys.map((key) => {
533
+ const task = tasks[key];
534
+ if (typeof task !== "function") {
535
+ throw new InvalidDslCallError(`parallel() task '${key}' must be a function.`);
536
+ }
537
+ return withToolForbidden("parallel-task", () => task());
538
+ });
539
+ const results = await Promise.all(promises);
540
+ const resultObj = {};
541
+ for (let i = 0; i < keys.length; i++) {
542
+ const key = keys[i];
543
+ resultObj[key] = results[i];
544
+ }
545
+ return resultObj;
546
+ }
547
+ };
437
548
  const runTool = async (input) => {
438
549
  const scope = assertToolAllowed();
550
+ const activeLoop = getActiveLoopContext();
551
+ if (activeLoop?.signal.aborted) {
552
+ throw activeLoop.signal.reason;
553
+ }
439
554
  const normalizedInput = normalizeToolCallInput(input, runtime);
440
555
  if (!runtime.toolRegistry || !runtime.toolExecutor) {
441
556
  throw new OpenDynamicWorkflowError(ErrorCode.TOOL_INVALID_CONTEXT, "tool() is not configured for this run.");
@@ -451,113 +566,139 @@ export function createDsl(runtime) {
451
566
  toolCallId = nextToolCallId(runtime, normalizedInput.definition);
452
567
  }
453
568
  runtime.toolCallIds?.add(toolCallId);
454
- const failureMode = normalizedInput.failureMode || "throw";
455
569
  const activeInvocation = getActiveWorkflowInvocation();
456
- const preparedCall = {
457
- toolCallId,
458
- definition,
459
- args: cloneJsonValue(normalizedInput.args, "tool args"),
460
- label: normalizedInput.label,
461
- failureMode,
462
- timeoutMs: normalizedInput.timeoutMs || definition.definition.defaultTimeoutMs,
463
- deadline: activeInvocation?.deadlineAt,
464
- metadata: normalizedInput.metadata ? cloneJsonValue(normalizedInput.metadata, "tool metadata") : undefined,
465
- workflowInvocationId: scope.workflowInvocationId,
466
- parentWorkflowInvocationId: scope.parentWorkflowInvocationId,
467
- queuedAt: new Date().toISOString(),
468
- artifactPath: `tools/${toolCallId}/output.json`,
469
- invocationSignal: activeInvocation?.signal || runtime.abortController.signal
470
- };
471
- const isCacheable = !!definition.definition.cacheable;
472
- let sequence;
473
- let fingerprint;
474
- let callId;
475
- if (isCacheable) {
476
- sequence = (runtime.callSequence ?? 0) + 1;
477
- runtime.callSequence = sequence;
478
- callId = normalizedInput.id ?? normalizedInput.label;
479
- fingerprint = computeToolFingerprint({
480
- definitionId: definition.definition.id,
481
- args: preparedCall.args,
482
- timeoutMs: preparedCall.timeoutMs,
483
- metadata: preparedCall.metadata,
484
- sourcePath: definition.sourcePath,
485
- definitionVersion: definition.definition.metadata?.version
486
- });
487
- const cachedEntry = findPrefixCacheHit({
488
- cache: runtime.callCache,
489
- kind: "tool",
490
- sequence,
491
- callId,
492
- fingerprint
493
- });
494
- if (cachedEntry && runtime.artifactStore && runtime.callCache?.previousRunRoot) {
495
- const cachedResult = await materializeCachedToolResult({
496
- store: runtime.artifactStore,
497
- previousRunRoot: runtime.callCache.previousRunRoot,
498
- previousRunId: runtime.callCache.previousRunId,
499
- entry: cachedEntry,
500
- currentToolCallId: toolCallId,
570
+ const failureMode = normalizedInput.failureMode || "throw";
571
+ let invocationSignal = activeInvocation?.signal || runtime.abortController.signal;
572
+ let onAbort;
573
+ if (activeLoop?.signal) {
574
+ const combinedController = new AbortController();
575
+ onAbort = () => combinedController.abort(activeLoop.signal.reason || invocationSignal.reason);
576
+ if (activeLoop.signal.aborted) {
577
+ combinedController.abort(activeLoop.signal.reason);
578
+ }
579
+ else if (invocationSignal.aborted) {
580
+ combinedController.abort(invocationSignal.reason);
581
+ }
582
+ else {
583
+ activeLoop.signal.addEventListener("abort", onAbort);
584
+ invocationSignal.addEventListener("abort", onAbort);
585
+ }
586
+ invocationSignal = combinedController.signal;
587
+ }
588
+ try {
589
+ const preparedCall = {
590
+ toolCallId,
591
+ definition,
592
+ args: cloneJsonValue(normalizedInput.args, "tool args"),
593
+ label: normalizedInput.label,
594
+ failureMode,
595
+ timeoutMs: normalizedInput.timeoutMs || definition.definition.defaultTimeoutMs,
596
+ deadline: activeInvocation?.deadlineAt,
597
+ metadata: normalizedInput.metadata ? cloneJsonValue(normalizedInput.metadata, "tool metadata") : undefined,
598
+ workflowInvocationId: scope.workflowInvocationId,
599
+ parentWorkflowInvocationId: scope.parentWorkflowInvocationId,
600
+ queuedAt: new Date().toISOString(),
601
+ artifactPath: `tools/${toolCallId}/output.json`,
602
+ invocationSignal
603
+ };
604
+ const isCacheable = !!definition.definition.cacheable;
605
+ let sequence;
606
+ let fingerprint;
607
+ let callId;
608
+ if (isCacheable) {
609
+ sequence = (runtime.callSequence ?? 0) + 1;
610
+ runtime.callSequence = sequence;
611
+ callId = normalizedInput.id ?? normalizedInput.label;
612
+ fingerprint = computeToolFingerprint({
501
613
  definitionId: definition.definition.id,
502
- failureMode,
503
- label: normalizedInput.label,
504
- workflowInvocationId: scope.workflowInvocationId,
505
- parentWorkflowInvocationId: scope.parentWorkflowInvocationId
614
+ args: preparedCall.args,
615
+ timeoutMs: preparedCall.timeoutMs,
616
+ metadata: preparedCall.metadata,
617
+ sourcePath: definition.sourcePath,
618
+ definitionVersion: definition.definition.metadata?.version
506
619
  });
507
- runtime.eventSink?.emit("tool.cache_hit", {
508
- toolCallId,
509
- definition: definition.definition.id,
510
- label: normalizedInput.label,
620
+ const cachedEntry = findPrefixCacheHit({
621
+ cache: runtime.callCache,
622
+ kind: "tool",
511
623
  sequence,
512
624
  callId,
513
- previousRunId: runtime.callCache.previousRunId,
514
- previousToolCallId: cachedEntry.toolCallId,
515
- artifactPath: cachedResult.artifactPath
625
+ fingerprint
516
626
  });
627
+ if (cachedEntry && runtime.artifactStore && runtime.callCache?.previousRunRoot) {
628
+ const cachedResult = await materializeCachedToolResult({
629
+ store: runtime.artifactStore,
630
+ previousRunRoot: runtime.callCache.previousRunRoot,
631
+ previousRunId: runtime.callCache.previousRunId,
632
+ entry: cachedEntry,
633
+ currentToolCallId: toolCallId,
634
+ definitionId: definition.definition.id,
635
+ failureMode,
636
+ label: normalizedInput.label,
637
+ workflowInvocationId: scope.workflowInvocationId,
638
+ parentWorkflowInvocationId: scope.parentWorkflowInvocationId
639
+ });
640
+ runtime.eventSink?.emit("tool.cache_hit", {
641
+ toolCallId,
642
+ definition: definition.definition.id,
643
+ label: normalizedInput.label,
644
+ sequence,
645
+ callId,
646
+ previousRunId: runtime.callCache.previousRunId,
647
+ previousToolCallId: cachedEntry.toolCallId,
648
+ artifactPath: cachedResult.artifactPath
649
+ });
650
+ await recordToolCall({
651
+ store: runtime.artifactStore,
652
+ cache: runtime.callCache,
653
+ sequence,
654
+ callId,
655
+ fingerprint,
656
+ result: cachedResult
657
+ });
658
+ const toolResult = returnToolResult(cachedResult, failureMode);
659
+ runtime.toolResults.push(cachedResult);
660
+ if (runtime.toolExecutor) {
661
+ runtime.toolExecutor.addSummary({
662
+ toolCallId: cachedResult.toolCallId,
663
+ definition: cachedResult.definitionId,
664
+ status: cachedResult.status,
665
+ ok: cachedResult.ok,
666
+ workflowInvocationId: cachedResult.workflowInvocationId,
667
+ parentWorkflowInvocationId: cachedResult.parentWorkflowInvocationId,
668
+ durationMs: cachedResult.durationMs,
669
+ artifactPath: cachedResult.artifactPath,
670
+ cache: cachedResult.cache
671
+ });
672
+ }
673
+ return toolResult;
674
+ }
675
+ }
676
+ else {
677
+ if (runtime.callCache) {
678
+ runtime.callCache.prefixCacheUsable = false;
679
+ }
680
+ }
681
+ const result = await runtime.toolExecutor.execute(preparedCall);
682
+ if (isCacheable && sequence !== undefined && fingerprint !== undefined) {
517
683
  await recordToolCall({
518
684
  store: runtime.artifactStore,
519
685
  cache: runtime.callCache,
520
686
  sequence,
521
687
  callId,
522
688
  fingerprint,
523
- result: cachedResult
689
+ result
524
690
  });
525
- const toolResult = returnToolResult(cachedResult, failureMode);
526
- runtime.toolResults.push(cachedResult);
527
- if (runtime.toolExecutor) {
528
- runtime.toolExecutor.addSummary({
529
- toolCallId: cachedResult.toolCallId,
530
- definition: cachedResult.definitionId,
531
- status: cachedResult.status,
532
- ok: cachedResult.ok,
533
- workflowInvocationId: cachedResult.workflowInvocationId,
534
- parentWorkflowInvocationId: cachedResult.parentWorkflowInvocationId,
535
- durationMs: cachedResult.durationMs,
536
- artifactPath: cachedResult.artifactPath,
537
- cache: cachedResult.cache
538
- });
539
- }
540
- return toolResult;
541
691
  }
692
+ runtime.toolResults.push(result);
693
+ return returnToolResult(result, failureMode);
542
694
  }
543
- else {
544
- if (runtime.callCache) {
545
- runtime.callCache.prefixCacheUsable = false;
695
+ finally {
696
+ if (onAbort) {
697
+ activeLoop?.signal.removeEventListener("abort", onAbort);
698
+ const originalInvocationSignal = activeInvocation?.signal || runtime.abortController.signal;
699
+ originalInvocationSignal.removeEventListener("abort", onAbort);
546
700
  }
547
701
  }
548
- const result = await runtime.toolExecutor.execute(preparedCall);
549
- if (isCacheable && sequence !== undefined && fingerprint !== undefined) {
550
- await recordToolCall({
551
- store: runtime.artifactStore,
552
- cache: runtime.callCache,
553
- sequence,
554
- callId,
555
- fingerprint,
556
- result
557
- });
558
- }
559
- runtime.toolResults.push(result);
560
- return returnToolResult(result, failureMode);
561
702
  };
562
703
  function returnToolResult(result, failureMode) {
563
704
  if (failureMode === "throw") {
@@ -626,37 +767,7 @@ export function createDsl(runtime) {
626
767
  log: logWorkflow,
627
768
  agent: runAgentCall,
628
769
  tool: runTool,
629
- parallel: async (tasks) => {
630
- if (!tasks || typeof tasks !== "object") {
631
- throw new InvalidDslCallError("parallel() requires an array or an object of task thunks.");
632
- }
633
- if (Array.isArray(tasks)) {
634
- const promises = tasks.map((task, idx) => {
635
- if (typeof task !== "function") {
636
- throw new InvalidDslCallError(`parallel() task at index ${idx} must be a function.`);
637
- }
638
- return withToolForbidden("parallel-task", () => task());
639
- });
640
- return Promise.all(promises);
641
- }
642
- else {
643
- const keys = Object.keys(tasks);
644
- const promises = keys.map((key) => {
645
- const task = tasks[key];
646
- if (typeof task !== "function") {
647
- throw new InvalidDslCallError(`parallel() task '${key}' must be a function.`);
648
- }
649
- return withToolForbidden("parallel-task", () => task());
650
- });
651
- const results = await Promise.all(promises);
652
- const resultObj = {};
653
- for (let i = 0; i < keys.length; i++) {
654
- const key = keys[i];
655
- resultObj[key] = results[i];
656
- }
657
- return resultObj;
658
- }
659
- },
770
+ parallel: parallelFunction,
660
771
  pipeline: async (items, stages, options) => {
661
772
  const activeInvocation = getActiveWorkflowInvocation();
662
773
  return runPipeline({
@@ -667,17 +778,50 @@ export function createDsl(runtime) {
667
778
  signal: activeInvocation?.signal || runtime.abortController.signal
668
779
  });
669
780
  },
670
- workflow: async (input) => {
781
+ workflow: workflowFunction,
782
+ loop: async (input) => {
671
783
  const activeInvocation = getActiveWorkflowInvocation();
672
- if (!activeInvocation) {
673
- throw new OpenDynamicWorkflowError(ErrorCode.WORKFLOW_FAILED, "workflow() can only be called from within a workflow invocation.");
674
- }
675
- if (!runtime.invocationManager) {
676
- throw new OpenDynamicWorkflowError(ErrorCode.WORKFLOW_FAILED, "Workflow invocation manager is not available.");
677
- }
678
- const result = await runtime.invocationManager.invokeChild(activeInvocation, input);
679
- return result;
784
+ return runLoop({
785
+ loopInput: input,
786
+ runtime,
787
+ signal: activeInvocation?.signal || runtime.abortController.signal,
788
+ dsl: {
789
+ agent: runAgentCall,
790
+ workflow: workflowFunction,
791
+ log: logWorkflow
792
+ }
793
+ });
680
794
  }
681
795
  };
682
796
  }
797
+ function isSafeAgentId(id) {
798
+ if (!id)
799
+ return false;
800
+ const trimmed = id.trim();
801
+ const pattern = /^[A-Za-z0-9_.:-]+$/;
802
+ return (trimmed !== "" &&
803
+ trimmed !== "." &&
804
+ trimmed !== ".." &&
805
+ !trimmed.includes("/") &&
806
+ !trimmed.includes("\\") &&
807
+ !trimmed.includes("..") &&
808
+ pattern.test(trimmed));
809
+ }
810
+ function resolveLoopAgentId(currentId, input, activeLoop, isChildWorkflow, runtime) {
811
+ const normalizedLabel = normalizeLoopLabel(activeLoop.label);
812
+ const loopPrefix = `${normalizedLabel}:round-${activeLoop.roundNumber}`;
813
+ if (currentId === loopPrefix || currentId.startsWith(loopPrefix + ":")) {
814
+ return currentId;
815
+ }
816
+ let suffix;
817
+ if (isChildWorkflow && input.id) {
818
+ suffix = input.id;
819
+ }
820
+ else if (!input.id) {
821
+ suffix = isSafeAgentId(input.label) ? input.label.trim() : `agent-${++runtime.agentCounter}`;
822
+ }
823
+ return suffix !== undefined
824
+ ? createLoopAgentId({ label: activeLoop.label, roundNumber: activeLoop.roundNumber, suffix })
825
+ : currentId;
826
+ }
683
827
  //# sourceMappingURL=dsl.js.map