@doclo/flows 0.1.2 → 0.1.4

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.
@@ -537,6 +554,7 @@ type ParseConfig = {
537
554
  strategy?: 'majority' | 'unanimous';
538
555
  onTie?: 'random' | 'fail' | 'retry';
539
556
  };
557
+ maxTokens?: number;
540
558
  };
541
559
  type ExtractConfig = {
542
560
  type: 'extract';
@@ -552,6 +570,7 @@ type ExtractConfig = {
552
570
  effort?: 'low' | 'medium' | 'high';
553
571
  max_tokens?: number;
554
572
  };
573
+ maxTokens?: number;
555
574
  };
556
575
  type SplitConfig = {
557
576
  type: 'split';
@@ -564,6 +583,7 @@ type SplitConfig = {
564
583
  onTie?: 'random' | 'fail' | 'retry';
565
584
  };
566
585
  schemaRef?: string;
586
+ maxTokens?: number;
567
587
  };
568
588
  type CategorizeConfig = {
569
589
  type: 'categorize';
@@ -575,6 +595,7 @@ type CategorizeConfig = {
575
595
  onTie?: 'random' | 'fail' | 'retry';
576
596
  };
577
597
  promptRef?: string;
598
+ maxTokens?: number;
578
599
  };
579
600
  type TriggerConfig = {
580
601
  type: 'trigger';
@@ -929,4 +950,4 @@ declare function buildTwoProviderFlow(opts: {
929
950
  }>;
930
951
  };
931
952
 
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 };
953
+ 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
  }
@@ -1743,7 +1807,8 @@ function createNodeFromConfig(nodeType, config, providers, flows) {
1743
1807
  const cfg = config;
1744
1808
  return parse({
1745
1809
  provider,
1746
- consensus: cfg.consensus
1810
+ consensus: cfg.consensus,
1811
+ maxTokens: cfg.maxTokens
1747
1812
  });
1748
1813
  }
1749
1814
  case "extract": {
@@ -1752,7 +1817,8 @@ function createNodeFromConfig(nodeType, config, providers, flows) {
1752
1817
  provider,
1753
1818
  schema: cfg.schema,
1754
1819
  consensus: cfg.consensus,
1755
- reasoning: cfg.reasoning
1820
+ reasoning: cfg.reasoning,
1821
+ maxTokens: cfg.maxTokens
1756
1822
  });
1757
1823
  }
1758
1824
  case "split": {
@@ -1761,7 +1827,8 @@ function createNodeFromConfig(nodeType, config, providers, flows) {
1761
1827
  provider,
1762
1828
  schemas: cfg.schemas,
1763
1829
  includeOther: cfg.includeOther,
1764
- consensus: cfg.consensus
1830
+ consensus: cfg.consensus,
1831
+ maxTokens: cfg.maxTokens
1765
1832
  });
1766
1833
  }
1767
1834
  case "categorize": {
@@ -1769,7 +1836,8 @@ function createNodeFromConfig(nodeType, config, providers, flows) {
1769
1836
  return categorize2({
1770
1837
  provider,
1771
1838
  categories: cfg.categories,
1772
- consensus: cfg.consensus
1839
+ consensus: cfg.consensus,
1840
+ maxTokens: cfg.maxTokens
1773
1841
  });
1774
1842
  }
1775
1843
  default:
@@ -2519,7 +2587,9 @@ export {
2519
2587
  getFlow,
2520
2588
  getFlowCount,
2521
2589
  hasFlow,
2590
+ isBatchFlowResult,
2522
2591
  isFlowReference,
2592
+ isSingleFlowResult,
2523
2593
  listFlows,
2524
2594
  parse2 as parse,
2525
2595
  registerFlow,