@doclo/flows 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -45,10 +45,27 @@ type BatchFlowResult = {
45
45
  /**
46
46
  * Type representing the built flow object returned by Flow.build()
47
47
  */
48
+ /**
49
+ * Options for running a built flow
50
+ */
51
+ interface FlowRunOptions {
52
+ /** Progress callbacks for step execution */
53
+ callbacks?: FlowProgressCallbacks;
54
+ /** Initial artifacts to merge into the flow context (for forEach child flows) */
55
+ initialArtifacts?: Record<string, any>;
56
+ }
48
57
  type BuiltFlow<TInput = any, TOutput = any> = {
49
- run: (input: TInput, callbacks?: FlowProgressCallbacks) => Promise<FlowResult<TOutput> | BatchFlowResult>;
58
+ run: (input: TInput, callbacksOrOptions?: FlowProgressCallbacks | FlowRunOptions) => Promise<FlowResult<TOutput> | BatchFlowResult>;
50
59
  validate: () => FlowValidationResult;
51
60
  };
61
+ /**
62
+ * Type guard to check if a flow result is a single result (not batch)
63
+ */
64
+ declare function isSingleFlowResult<T>(result: FlowResult<T> | BatchFlowResult): result is FlowResult<T>;
65
+ /**
66
+ * Type guard to check if a flow result is a batch result
67
+ */
68
+ declare function isBatchFlowResult(result: FlowResult<unknown> | BatchFlowResult): result is BatchFlowResult;
52
69
  /**
53
70
  * Type helper to extract the unwrapped input type from a wrapped type.
54
71
  * If T has an 'input' property, returns the type of that property.
@@ -929,4 +946,4 @@ declare function buildTwoProviderFlow(opts: {
929
946
  }>;
930
947
  };
931
948
 
932
- export { type BuiltFlow, type CategorizeConfig, type ConditionalCompositeConfig, type ExtractConfig, FLOW_REGISTRY, type FieldMapping, type FlowBuilder, type FlowOptions, type FlowProgressCallbacks, type FlowReference, type FlowRegistry$1 as FlowRegistry, FlowSerializationError, type FlowValidationResult, type ForEachCompositeConfig, type InputMappingConfig, type NodeConfig, type OutputConfig, type ParseConfig, type ProviderRegistry, type SerializableConditionalStep, type SerializableFlow, type SerializableForEachStep, type SerializableInputValidation, type SerializableStandardStep, type SerializableStep, type SplitConfig, type TriggerConfig, type ValidationError, type ValidationOptions, type ValidationResult, type ValidationWarning, buildFlowFromConfig, buildMultiProviderFlow, buildTwoProviderFlow, buildVLMDirectFlow, clearRegistry, createConditionalCompositeNode, createFlow, createForEachCompositeNode, defineFlowConfig, extractNodeMetadata, getFlow, getFlowCount, hasFlow, isFlowReference, listFlows, registerFlow, resolveFlowReference, unregisterFlow, validateFlow, validateFlowOrThrow };
949
+ export { type BatchFlowResult, type BuiltFlow, type CategorizeConfig, type ConditionalCompositeConfig, type ExtractConfig, FLOW_REGISTRY, type FieldMapping, type FlowBuilder, type FlowOptions, type FlowProgressCallbacks, type FlowReference, type FlowRegistry$1 as FlowRegistry, type FlowRunOptions, FlowSerializationError, type FlowValidationResult, type ForEachCompositeConfig, type InputMappingConfig, type NodeConfig, type OutputConfig, type ParseConfig, type ProviderRegistry, type SerializableConditionalStep, type SerializableFlow, type SerializableForEachStep, type SerializableInputValidation, type SerializableStandardStep, type SerializableStep, type SplitConfig, type TriggerConfig, type ValidationError, type ValidationOptions, type ValidationResult, type ValidationWarning, buildFlowFromConfig, buildMultiProviderFlow, buildTwoProviderFlow, buildVLMDirectFlow, clearRegistry, createConditionalCompositeNode, createFlow, createForEachCompositeNode, defineFlowConfig, extractNodeMetadata, getFlow, getFlowCount, hasFlow, isBatchFlowResult, isFlowReference, isSingleFlowResult, listFlows, registerFlow, resolveFlowReference, unregisterFlow, validateFlow, validateFlowOrThrow };
package/dist/index.js CHANGED
@@ -32,6 +32,9 @@ import {
32
32
  function isSingleFlowResult(result) {
33
33
  return "output" in result && "artifacts" in result;
34
34
  }
35
+ function isBatchFlowResult(result) {
36
+ return "results" in result && Array.isArray(result.results);
37
+ }
35
38
  function normalizeFlowInput(input) {
36
39
  if (input == null) {
37
40
  return input;
@@ -257,8 +260,18 @@ var Flow = class {
257
260
  */
258
261
  build() {
259
262
  return {
260
- run: async (input, callbacks) => {
261
- return this.execute(input, callbacks);
263
+ run: async (input, callbacksOrOptions) => {
264
+ let callbacks;
265
+ let initialArtifacts;
266
+ if (callbacksOrOptions) {
267
+ if ("callbacks" in callbacksOrOptions || "initialArtifacts" in callbacksOrOptions) {
268
+ callbacks = callbacksOrOptions.callbacks;
269
+ initialArtifacts = callbacksOrOptions.initialArtifacts;
270
+ } else {
271
+ callbacks = callbacksOrOptions;
272
+ }
273
+ }
274
+ return this.execute(input, callbacks, initialArtifacts);
262
275
  },
263
276
  validate: () => {
264
277
  return this.validate();
@@ -483,9 +496,9 @@ var Flow = class {
483
496
  /**
484
497
  * Execute the flow with optional progress callbacks
485
498
  */
486
- async execute(input, callbacks) {
499
+ async execute(input, callbacks, initialArtifacts) {
487
500
  const flowStartTime = Date.now();
488
- const artifacts = {};
501
+ const artifacts = initialArtifacts ? { ...initialArtifacts } : {};
489
502
  const metrics = [];
490
503
  const completedSteps = [];
491
504
  const outputs = {};
@@ -532,6 +545,7 @@ var Flow = class {
532
545
  }
533
546
  }
534
547
  let currentData = normalizeFlowInput(input);
548
+ artifacts.__flowInput = currentData;
535
549
  if (this.inputValidation?.acceptedFormats?.length) {
536
550
  const dataUrl = currentData?.base64 || currentData?.url;
537
551
  if (dataUrl) {
@@ -641,7 +655,7 @@ var Flow = class {
641
655
  } : {
642
656
  // Always pass stepId for metrics tracking, even without observability
643
657
  stepId: step.id
644
- });
658
+ }, artifacts);
645
659
  artifacts[step.id] = result2.output;
646
660
  metrics.push(...result2.metrics);
647
661
  completedSteps.push(step.id);
@@ -913,7 +927,11 @@ Correct: .conditional('step', () => parse({ provider }))`
913
927
  const childFlow = step.childFlow(item);
914
928
  const builtFlow = childFlow.build();
915
929
  const flowInput = item && typeof item === "object" && "input" in item ? item.input : item;
916
- const result2 = await builtFlow.run(flowInput);
930
+ const childInitialArtifacts = {
931
+ __originalFlowInput: artifacts.__flowInput
932
+ // Original source before split
933
+ };
934
+ const result2 = await builtFlow.run(flowInput, { initialArtifacts: childInitialArtifacts });
917
935
  let itemResult;
918
936
  if ("results" in result2 && Array.isArray(result2.results)) {
919
937
  const aggregatedMetrics = (result2.results || []).flatMap((r) => r && r.metrics || []);
@@ -1063,20 +1081,26 @@ Correct: .conditional('step', () => parse({ provider }))`
1063
1081
  context: stepErrorContext
1064
1082
  });
1065
1083
  }
1066
- const completedStepsStr = completedSteps.length > 0 ? `
1084
+ const isNestedFlowError = err instanceof FlowExecutionError;
1085
+ const completedStepsStr = isNestedFlowError ? "" : completedSteps.length > 0 ? `
1067
1086
  Completed steps: ${completedSteps.join(" \u2192 ")}` : "\n No steps completed before failure";
1068
1087
  const artifactsStr = Object.keys(artifacts).length > 0 ? `
1069
1088
  Partial results available in: ${Object.keys(artifacts).join(", ")}` : "";
1089
+ const allCompleted = isNestedFlowError ? [...err.allCompletedSteps || err.completedSteps, ...completedSteps] : completedSteps;
1090
+ const flowPath = isNestedFlowError && err.flowPath ? [...err.flowPath, { stepId: step.id, stepIndex, stepType: step.type }] : [{ stepId: step.id, stepIndex, stepType: step.type }];
1091
+ const errorMessage = isNestedFlowError ? err.getRootCause().message : err.message;
1070
1092
  throw new FlowExecutionError(
1071
1093
  `Flow execution failed at step "${step.id}" (index ${stepIndex}, type: ${step.type})
1072
- Error: ${err.message}` + completedStepsStr + artifactsStr,
1094
+ Error: ${errorMessage}` + completedStepsStr + artifactsStr,
1073
1095
  step.id,
1074
1096
  stepIndex,
1075
1097
  step.type,
1076
1098
  completedSteps,
1077
- err,
1078
- artifacts
1099
+ isNestedFlowError ? err.originalError : err,
1100
+ artifacts,
1079
1101
  // Include partial artifacts for debugging
1102
+ flowPath,
1103
+ allCompleted
1080
1104
  );
1081
1105
  }
1082
1106
  }
@@ -1218,6 +1242,7 @@ function getFlowCount() {
1218
1242
  import { parse, extract, split as split2, categorize as categorize2, trigger, output } from "@doclo/nodes";
1219
1243
 
1220
1244
  // src/composite-nodes.ts
1245
+ import { FlowExecutionError as FlowExecutionError2 } from "@doclo/core";
1221
1246
  import { categorize, split } from "@doclo/nodes";
1222
1247
  function parseProviderName(name) {
1223
1248
  const colonIndex = name.indexOf(":");
@@ -1363,6 +1388,7 @@ function createConditionalCompositeNode(config) {
1363
1388
  return branchResult.output;
1364
1389
  } catch (error) {
1365
1390
  const err = error instanceof Error ? error : new Error(String(error));
1391
+ const isNestedFlowError = err instanceof FlowExecutionError2;
1366
1392
  if (ctx?.metrics) {
1367
1393
  ctx.metrics.push({
1368
1394
  step: stepId,
@@ -1382,8 +1408,27 @@ function createConditionalCompositeNode(config) {
1382
1408
  }
1383
1409
  });
1384
1410
  }
1385
- throw new Error(
1386
- `Conditional step "${stepId}" failed (${selectedCategory ? `category: ${selectedCategory}, ` : ""}phase: ${phase}): ` + err.message
1411
+ const flowPath = [{
1412
+ stepId,
1413
+ stepIndex: 0,
1414
+ stepType: "conditional",
1415
+ branch: selectedCategory || void 0
1416
+ }];
1417
+ if (isNestedFlowError && err.flowPath) {
1418
+ flowPath.push(...err.flowPath);
1419
+ }
1420
+ const rootCauseMessage = isNestedFlowError ? err.getRootCause().message : err.message;
1421
+ throw new FlowExecutionError2(
1422
+ `Conditional step "${stepId}" failed${selectedCategory ? ` (category: ${selectedCategory})` : ""} in phase: ${phase}
1423
+ Error: ${rootCauseMessage}`,
1424
+ stepId,
1425
+ 0,
1426
+ "conditional",
1427
+ [],
1428
+ isNestedFlowError ? err.originalError : err,
1429
+ void 0,
1430
+ flowPath,
1431
+ isNestedFlowError ? err.allCompletedSteps : void 0
1387
1432
  );
1388
1433
  }
1389
1434
  }
@@ -1520,6 +1565,7 @@ function createForEachCompositeNode(config) {
1520
1565
  return results;
1521
1566
  } catch (error) {
1522
1567
  const err = error instanceof Error ? error : new Error(String(error));
1568
+ const isNestedFlowError = err instanceof FlowExecutionError2;
1523
1569
  if (ctx?.metrics) {
1524
1570
  ctx.metrics.push({
1525
1571
  step: stepId,
@@ -1539,8 +1585,26 @@ function createForEachCompositeNode(config) {
1539
1585
  }
1540
1586
  });
1541
1587
  }
1542
- throw new Error(
1543
- `ForEach step "${stepId}" failed (${items ? `itemCount: ${items.length}, ` : ""}phase: ${phase}): ` + err.message
1588
+ const flowPath = [{
1589
+ stepId,
1590
+ stepIndex: 0,
1591
+ stepType: "forEach"
1592
+ }];
1593
+ if (isNestedFlowError && err.flowPath) {
1594
+ flowPath.push(...err.flowPath);
1595
+ }
1596
+ const rootCauseMessage = isNestedFlowError ? err.getRootCause().message : err.message;
1597
+ throw new FlowExecutionError2(
1598
+ `ForEach step "${stepId}" failed${items ? ` (itemCount: ${items.length})` : ""} in phase: ${phase}
1599
+ Error: ${rootCauseMessage}`,
1600
+ stepId,
1601
+ 0,
1602
+ "forEach",
1603
+ [],
1604
+ isNestedFlowError ? err.originalError : err,
1605
+ void 0,
1606
+ flowPath,
1607
+ isNestedFlowError ? err.allCompletedSteps : void 0
1544
1608
  );
1545
1609
  }
1546
1610
  }
@@ -2519,7 +2583,9 @@ export {
2519
2583
  getFlow,
2520
2584
  getFlowCount,
2521
2585
  hasFlow,
2586
+ isBatchFlowResult,
2522
2587
  isFlowReference,
2588
+ isSingleFlowResult,
2523
2589
  listFlows,
2524
2590
  parse2 as parse,
2525
2591
  registerFlow,