@oomol-lab/open-flow 0.1.0-beta.67 → 0.1.0-beta.69

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 (72) hide show
  1. package/dist/browser/ContentIcon-CsECY5id.js +11868 -0
  2. package/dist/browser/FlowCanvas-C5X22xQ7.js +22721 -0
  3. package/dist/browser/{createResourceDialog-BQVD8Rqb.js → createResourceDialog-Di5BBrQv.js} +3 -2
  4. package/dist/browser/dialog-Bjo-r9B0.js +8862 -0
  5. package/dist/browser/event-sources.d.ts +4 -2
  6. package/dist/browser/exportSvg-Cj6Spxx-.js +659 -0
  7. package/dist/browser/flow-authoring-node.d.ts +3 -1
  8. package/dist/browser/flow-authoring.js +68 -7
  9. package/dist/browser/flow-change-schema.d.ts +3 -1
  10. package/dist/browser/flow-change.d.ts +17 -2
  11. package/dist/browser/flow-change.js +82 -9
  12. package/dist/browser/{flowChanges-VB9Y4iy7.js → flowChanges-Dp-rcEJ6.js} +4312 -16566
  13. package/dist/browser/{flowRunInputEditorStore-DJqmR6Qh.js → flowRunInputEditorStore-ys1-w9GW.js} +2 -1
  14. package/dist/browser/{flowWorkspace-C1hlTnZq.js → flowWorkspace-CB1QACku.js} +1304 -23538
  15. package/dist/browser/languages-gYzoQqCi.js +68 -0
  16. package/dist/browser/licenses.md +24 -0
  17. package/dist/browser/preview.css +53 -41
  18. package/dist/browser/preview.js +3974 -4094
  19. package/dist/browser/{dialog-CS2Vt2if.js → tooltip-CJjYs_2I.js} +710 -9472
  20. package/dist/browser/{typeScriptSession-D0bjYDeg.js → typeScriptSession-B0hC-C8y.js} +1 -1
  21. package/dist/browser/ui.css +12 -0
  22. package/dist/browser/{value-BADHeZ9I.js → value-BbFQZZ_V.js} +1 -68
  23. package/dist/browser/workbench.css +2840 -2824
  24. package/dist/browser/workbench.js +437 -337
  25. package/dist/browser/{workbenchSelect-CpXhjUou.js → workbenchSelect-C3hxUcYm.js} +2 -1
  26. package/dist/command/index.js +55 -51
  27. package/dist/common/authoring.d.ts +20 -0
  28. package/dist/common/authoringSchema.d.ts +243 -0
  29. package/dist/common/connector-proxy.d.ts +4 -0
  30. package/dist/common/control-api-conformance.js +173 -36
  31. package/dist/common/control-api.d.ts +22 -8
  32. package/dist/common/control-api.js +156 -18
  33. package/dist/common/control-requests.d.ts +32 -19
  34. package/dist/common/control-requests.js +2854 -152
  35. package/dist/common/decision.js +27 -3
  36. package/dist/common/engine-contract.d.ts +2 -2
  37. package/dist/common/event-source-definition.d.ts +34 -16
  38. package/dist/common/event-source.d.ts +63 -5
  39. package/dist/common/event-source.js +5744 -261
  40. package/dist/common/event-sources.d.ts +99 -6
  41. package/dist/common/flow-encoding.js +49 -10
  42. package/dist/common/flow-errorHandling.d.ts +36 -0
  43. package/dist/common/flow-graph.d.ts +4 -2
  44. package/dist/common/flow-retry.d.ts +19 -0
  45. package/dist/common/flow-semantics.js +94 -10
  46. package/dist/common/{fr-Du5gv3kM.js → fr-CNTSedYU.js} +259 -18
  47. package/dist/common/integration-trigger.d.ts +1 -1
  48. package/dist/common/integration-trigger.js +27 -3
  49. package/dist/common/{ja-D2wyPdTF.js → ja-CxQBHr2J.js} +259 -18
  50. package/dist/common/{ko-Cuu2AOaC.js → ko-D1Exiv1h.js} +259 -18
  51. package/dist/common/mcp.d.ts +30 -0
  52. package/dist/common/mcp.js +158 -20
  53. package/dist/common/openapi.js +27 -3
  54. package/dist/common/poll-trigger.js +27 -3
  55. package/dist/common/provider-triggers.d.ts +0 -2
  56. package/dist/common/provider-triggers.js +358 -155
  57. package/dist/common/{ru-BjI_JSsx.js → ru-BzLZv0B7.js} +259 -18
  58. package/dist/common/run-events.d.ts +2 -0
  59. package/dist/common/run-events.js +4 -2
  60. package/dist/common/runtime-contract.d.ts +1 -0
  61. package/dist/common/runtime-contract.js +4 -4
  62. package/dist/common/scheduler.d.ts +13 -2
  63. package/dist/common/scheduler.js +288 -98
  64. package/dist/common/webhook-trigger.js +27 -3
  65. package/dist/common/workflow.js +27 -3
  66. package/dist/common/{zh-CN-CnnXkzLh.js → zh-CN-Dg_xSGde.js} +259 -18
  67. package/dist/common/{zh-TW-CJnR2dgF.js → zh-TW-oxuLwsV0.js} +259 -18
  68. package/dist/index.d.ts +1 -0
  69. package/package.json +1 -1
  70. package/dist/common/event-source-feishu.d.ts +0 -3
  71. package/dist/common/feishu-events.d.ts +0 -19
  72. package/dist/common/feishu-subscriptions.d.ts +0 -6
@@ -5066,7 +5066,7 @@ var ZodString = /*@__PURE__*/ $constructor("ZodString", (inst, def) => {
5066
5066
  return this.check(/* @__PURE__ */ _isoDuration(ZodISODuration, params));
5067
5067
  }
5068
5068
  });
5069
- function string(params) {
5069
+ function string$1(params) {
5070
5070
  return /* @__PURE__ */ _string(ZodString, params);
5071
5071
  }
5072
5072
  var ZodStringFormat = /*@__PURE__*/ $constructor("ZodStringFormat", (inst, def) => {
@@ -5417,7 +5417,7 @@ var ZodRecord = /*@__PURE__*/ $constructor("ZodRecord", (inst, def) => {
5417
5417
  function record$1(keyType, valueType, params) {
5418
5418
  if (!valueType || !valueType._zod) return new ZodRecord({
5419
5419
  type: "record",
5420
- keyType: string(),
5420
+ keyType: string$1(),
5421
5421
  valueType: keyType,
5422
5422
  ...normalizeParams(valueType)
5423
5423
  });
@@ -5665,12 +5665,12 @@ function superRefine(fn, params) {
5665
5665
  function json$1(params) {
5666
5666
  const jsonSchema = lazy(() => {
5667
5667
  return union([
5668
- string(params),
5668
+ string$1(params),
5669
5669
  number(),
5670
5670
  boolean(),
5671
5671
  _null(),
5672
5672
  array(jsonSchema),
5673
- record$1(string(), jsonSchema)
5673
+ record$1(string$1(), jsonSchema)
5674
5674
  ]);
5675
5675
  });
5676
5676
  return jsonSchema;
@@ -9467,11 +9467,33 @@ function answerSchema(question) {
9467
9467
  };
9468
9468
  }
9469
9469
  //#endregion
9470
+ //#region src/flow/common/retry.ts
9471
+ var retryNodeTypes = [
9472
+ "code",
9473
+ "connector",
9474
+ "openapi",
9475
+ "llm",
9476
+ "decision"
9477
+ ];
9478
+ var nodeRetryLimits = {
9479
+ maxRetries: 5,
9480
+ minIntervalMs: 1e3,
9481
+ maxIntervalMs: 6e4,
9482
+ intervalStepMs: 1e3
9483
+ };
9484
+ var retryConfigurationSchema = strictObject({
9485
+ maxRetries: number().int().min(0).max(nodeRetryLimits.maxRetries),
9486
+ intervalMs: number().int().min(nodeRetryLimits.minIntervalMs).max(nodeRetryLimits.maxIntervalMs).multipleOf(nodeRetryLimits.intervalStepMs)
9487
+ });
9488
+ function supportsNodeRetry(node) {
9489
+ return node.kind == "task" && retryNodeTypes.some((type) => type == ("moduleId" in node.task ? "code" : node.task.executor.kind));
9490
+ }
9491
+ //#endregion
9470
9492
  //#region src/flow/common/triggerScheduleSchema.ts
9471
9493
  var triggerScheduleSchema = array(union([object({
9472
9494
  type: literal("cron"),
9473
- expression: string(),
9474
- timezone: string()
9495
+ expression: string$1(),
9496
+ timezone: string$1()
9475
9497
  }), object({
9476
9498
  type: literal("every"),
9477
9499
  unit: _enum([
@@ -9495,7 +9517,7 @@ var webhookMethods = [
9495
9517
  function webhookSupportsBody(method) {
9496
9518
  return method !== "GET";
9497
9519
  }
9498
- var text = string();
9520
+ var text = string$1();
9499
9521
  var actionConnection = text.describe("Account selection: omit while unconfigured; use an account ID to select it; use \"\" to explicitly defer configuration. Deferred Actions fail if called; deferred Agent tools are excluded from the callable tool set. Not supported by Triggers.");
9500
9522
  var json = json$1();
9501
9523
  var strings = array(text);
@@ -9515,6 +9537,7 @@ var source = union([object({
9515
9537
  kind: literal("node"),
9516
9538
  nodeId: text,
9517
9539
  output: text,
9540
+ system: literal(true).optional(),
9518
9541
  field: text.optional()
9519
9542
  }), object({
9520
9543
  kind: literal("binding"),
@@ -9773,7 +9796,9 @@ var base = {
9773
9796
  name: text.optional(),
9774
9797
  description: text.optional(),
9775
9798
  icon: text.optional(),
9776
- timeoutMs: number().optional()
9799
+ timeoutMs: number().optional(),
9800
+ retry: retryConfigurationSchema.optional(),
9801
+ onError: _enum(["stop", "error"]).optional()
9777
9802
  };
9778
9803
  var node = union([
9779
9804
  strictObject({
@@ -9894,7 +9919,8 @@ object({
9894
9919
  literal(5),
9895
9920
  literal(6),
9896
9921
  literal(7),
9897
- literal(8)
9922
+ literal(8),
9923
+ literal(9)
9898
9924
  ]),
9899
9925
  document,
9900
9926
  modules: record$1(text, module)
@@ -9955,6 +9981,13 @@ var shapes = {
9955
9981
  },
9956
9982
  "graph.node.delete": at,
9957
9983
  "graph.node.field.set": union([
9984
+ object({
9985
+ ...at,
9986
+ kind: literal("graph.node.field.set"),
9987
+ field: literal("retry"),
9988
+ before: retryConfigurationSchema.optional(),
9989
+ value: retryConfigurationSchema.optional()
9990
+ }),
9958
9991
  object({
9959
9992
  ...at,
9960
9993
  kind: literal("graph.node.field.set"),
@@ -9968,7 +10001,8 @@ var shapes = {
9968
10001
  field: _enum([
9969
10002
  "description",
9970
10003
  "icon",
9971
- "name"
10004
+ "name",
10005
+ "onError"
9972
10006
  ]),
9973
10007
  before: text.optional(),
9974
10008
  value: text.optional()
@@ -10266,6 +10300,37 @@ function selectConditionBranches(node, values) {
10266
10300
  return selected.length == 0 ? [otherwiseOutput] : selected;
10267
10301
  }
10268
10302
  //#endregion
10303
+ //#region src/flow/common/errorHandling.ts
10304
+ var nodeErrorSchema = {
10305
+ type: "object",
10306
+ additionalProperties: false,
10307
+ required: [
10308
+ "code",
10309
+ "message",
10310
+ "nodeId",
10311
+ "nodeName",
10312
+ "runId",
10313
+ "executionId"
10314
+ ],
10315
+ properties: {
10316
+ code: { type: "string" },
10317
+ message: { type: "string" },
10318
+ nodeId: { type: "string" },
10319
+ nodeName: { type: "string" },
10320
+ runId: { type: "string" },
10321
+ executionId: { type: "string" }
10322
+ }
10323
+ };
10324
+ function supportsNodeErrorHandling(node) {
10325
+ return supportsNodeRetry(node);
10326
+ }
10327
+ function nodeSystemOutputPorts(node) {
10328
+ return supportsNodeErrorHandling(node) && node.onError == "error" ? { error: {
10329
+ jsonSchema: nodeErrorSchema,
10330
+ nullable: true
10331
+ } } : {};
10332
+ }
10333
+ //#endregion
10269
10334
  //#region src/flow/common/change.ts
10270
10335
  function portsByHandle(ports) {
10271
10336
  return Object.fromEntries(ports.flatMap((port) => "handle" in port ? [[port.handle, port]] : []));
@@ -10309,23 +10374,23 @@ var schema = lazy(() => union([boolean(), strictObject({
10309
10374
  if: schema.optional(),
10310
10375
  then: schema.optional(),
10311
10376
  else: schema.optional(),
10312
- $ref: string().optional(),
10377
+ $ref: string$1().optional(),
10313
10378
  $schema: _enum([
10314
10379
  "http://json-schema.org/draft-07/schema#",
10315
10380
  "https://json-schema.org/draft-07/schema",
10316
10381
  "https://json-schema.org/draft/2019-09/schema",
10317
10382
  "https://json-schema.org/draft/2020-12/schema"
10318
10383
  ]).optional(),
10319
- $defs: record$1(string(), schema).optional(),
10320
- definitions: record$1(string(), schema).optional(),
10321
- pattern: string().refine((value) => {
10384
+ $defs: record$1(string$1(), schema).optional(),
10385
+ definitions: record$1(string$1(), schema).optional(),
10386
+ pattern: string$1().refine((value) => {
10322
10387
  try {
10323
10388
  return new RegExp(value, "u").source.length > 0;
10324
10389
  } catch {
10325
10390
  return false;
10326
10391
  }
10327
10392
  }, "Invalid regular expression.").optional(),
10328
- format: string().refine((value) => Object.hasOwn(format, value), "Unsupported string format.").optional(),
10393
+ format: string$1().refine((value) => Object.hasOwn(format, value), "Unsupported string format.").optional(),
10329
10394
  multipleOf: number().positive().optional(),
10330
10395
  uniqueItems: boolean().optional(),
10331
10396
  contains: schema.optional(),
@@ -10334,31 +10399,31 @@ var schema = lazy(() => union([boolean(), strictObject({
10334
10399
  minProperties: number().int().nonnegative().optional(),
10335
10400
  maxProperties: number().int().nonnegative().optional(),
10336
10401
  propertyNames: schema.optional(),
10337
- patternProperties: record$1(string().refine((value) => {
10402
+ patternProperties: record$1(string$1().refine((value) => {
10338
10403
  try {
10339
10404
  return new RegExp(value, "u").source.length > 0;
10340
10405
  } catch {
10341
10406
  return false;
10342
10407
  }
10343
10408
  }, "Invalid regular expression."), schema).optional(),
10344
- dependentRequired: record$1(string(), array(string())).optional(),
10345
- dependentSchemas: record$1(string(), schema).optional(),
10346
- dependencies: record$1(string(), union([schema, array(string())])).optional(),
10409
+ dependentRequired: record$1(string$1(), array(string$1())).optional(),
10410
+ dependentSchemas: record$1(string$1(), schema).optional(),
10411
+ dependencies: record$1(string$1(), union([schema, array(string$1())])).optional(),
10347
10412
  prefixItems: array(schema).optional(),
10348
10413
  additionalItems: schema.optional(),
10349
10414
  unevaluatedItems: schema.optional(),
10350
10415
  unevaluatedProperties: schema.optional(),
10351
- description: string().optional(),
10352
- title: string().optional(),
10416
+ description: string$1().optional(),
10417
+ title: string$1().optional(),
10353
10418
  default: json$1().optional(),
10354
10419
  examples: array(json$1()).optional(),
10355
10420
  readOnly: boolean().optional(),
10356
10421
  writeOnly: boolean().optional(),
10357
10422
  deprecated: boolean().optional(),
10358
- $comment: string().optional(),
10423
+ $comment: string$1().optional(),
10359
10424
  enum: array(json$1()).min(1).optional(),
10360
- properties: record$1(string(), schema).optional(),
10361
- required: array(string()).optional(),
10425
+ properties: record$1(string$1(), schema).optional(),
10426
+ required: array(string$1()).optional(),
10362
10427
  additionalProperties: schema.optional(),
10363
10428
  items: union([schema, array(schema)]).optional(),
10364
10429
  minItems: number().int().nonnegative().optional(),
@@ -10664,10 +10729,11 @@ function nodeOutputPorts(node) {
10664
10729
  }
10665
10730
  //#endregion
10666
10731
  //#region src/execution/common/dependencies.ts
10667
- var outputsSchema = record$1(string(), json$1());
10668
- var inputSchema = record$1(string(), strictObject({
10732
+ var outputsSchema = record$1(string$1(), json$1());
10733
+ var inputSchema = record$1(string$1(), strictObject({
10669
10734
  execution: number().int().nonnegative(),
10670
- outputs: outputsSchema
10735
+ outputs: outputsSchema,
10736
+ systemOutputs: outputsSchema.optional()
10671
10737
  }));
10672
10738
  function dependencyValues(input) {
10673
10739
  return Object.fromEntries(Object.entries(input).map(([id, result]) => [id, result.outputs]));
@@ -10682,15 +10748,16 @@ var stateSchema = strictObject({
10682
10748
  ]),
10683
10749
  input: inputSchema,
10684
10750
  output: outputsSchema.optional(),
10685
- previous: array(string()),
10686
- released: array(string()),
10687
- jobId: string().optional(),
10751
+ systemOutputs: outputsSchema.optional(),
10752
+ previous: array(string$1()),
10753
+ released: array(string$1()),
10754
+ jobId: string$1().optional(),
10688
10755
  seeded: boolean()
10689
10756
  });
10690
10757
  var dependenciesSchema = strictObject({
10691
10758
  nextId: number().int().nonnegative(),
10692
- iterations: record$1(string(), number().int().nonnegative()),
10693
- nodes: record$1(string(), stateSchema)
10759
+ iterations: record$1(string$1(), number().int().nonnegative()),
10760
+ nodes: record$1(string$1(), stateSchema)
10694
10761
  });
10695
10762
  /** Dependency completion belongs to an invocation, never to a Run-wide latest-result table. */
10696
10763
  var Dependencies = class {
@@ -10786,7 +10853,7 @@ var Dependencies = class {
10786
10853
  if (this.graph.nodes[id] == null || state.id >= nextId || ids.has(state.id)) throw new Error("Checkpoint dependency identity is invalid.");
10787
10854
  ids.add(state.id);
10788
10855
  if (state.status == "running" && state.jobId == null) throw new Error("Checkpoint running dependency has no job.");
10789
- if ((state.status == "pending" || state.status == "skipped") && (state.jobId != null || state.output != null || state.released.length != 0)) throw new Error("Checkpoint inactive dependency contains an execution.");
10856
+ if ((state.status == "pending" || state.status == "skipped") && (state.jobId != null || state.output != null || state.systemOutputs != null || state.released.length != 0)) throw new Error("Checkpoint inactive dependency contains an execution.");
10790
10857
  if (state.status == "skipped" && (state.seeded || state.previous.length != 0 || Object.keys(state.input).length != 0)) throw new Error("Checkpoint skipped dependency contains values.");
10791
10858
  if (state.seeded && (!this.loops.has(id) || state.previous.some((source) => !this.loops.get(id).feedback.some((edge) => edge.source == source)))) throw new Error("Checkpoint recurrence seed is invalid.");
10792
10859
  if (state.released.length != new Set(state.released).size) throw new Error("Checkpoint released handles are duplicated.");
@@ -10826,7 +10893,11 @@ var Dependencies = class {
10826
10893
  outputs: {
10827
10894
  ...previous.outputs,
10828
10895
  ...result.outputs
10829
- }
10896
+ },
10897
+ ...previous.systemOutputs || result.systemOutputs ? { systemOutputs: {
10898
+ ...previous.systemOutputs,
10899
+ ...result.systemOutputs
10900
+ } } : {}
10830
10901
  };
10831
10902
  };
10832
10903
  for (const edge of edges) {
@@ -10835,12 +10906,16 @@ var Dependencies = class {
10835
10906
  const outputs = edge.sourceHandle != null && this.graph.nodes[edge.source].kind != "condition" ? Object.fromEntries(Object.entries(source.output).filter(([handle]) => handle == edge.sourceHandle)) : source.output;
10836
10907
  merge(edge.source, {
10837
10908
  execution: source.id,
10838
- outputs
10909
+ outputs,
10910
+ ...source.systemOutputs == null ? {} : { systemOutputs: source.systemOutputs }
10839
10911
  });
10840
10912
  }
10841
10913
  for (const id of Object.keys(input)) if (this.state.nodes[id].status == "skipped") delete input[id];
10842
10914
  return input;
10843
10915
  }
10916
+ systemInputValues(nodeId) {
10917
+ return Object.fromEntries(Object.entries(this.state.nodes[nodeId].input).flatMap(([id, value]) => value.systemOutputs == null ? [] : [[id, value.systemOutputs]]));
10918
+ }
10844
10919
  inputValues(nodeId) {
10845
10920
  return dependencyValues(this.state.nodes[nodeId].input);
10846
10921
  }
@@ -10931,9 +11006,10 @@ var Dependencies = class {
10931
11006
  state.status = "running";
10932
11007
  state.jobId = jobId;
10933
11008
  }
10934
- release(nodeId, outputs, handles, complete) {
11009
+ release(nodeId, outputs, handles, complete, systemOutputs) {
10935
11010
  const state = this.state.nodes[nodeId];
10936
11011
  state.output = outputs;
11012
+ state.systemOutputs = systemOutputs;
10937
11013
  state.released = [.../* @__PURE__ */ new Set([...state.released, ...handles])];
10938
11014
  if (complete) state.status = "completed";
10939
11015
  }
@@ -10942,9 +11018,33 @@ var Dependencies = class {
10942
11018
  }
10943
11019
  };
10944
11020
  //#endregion
11021
+ //#region src/execution/common/events.ts
11022
+ var encoder = new TextEncoder();
11023
+ function string(value, description) {
11024
+ if (typeof value != "string" || value.length == 0) throw new TypeError(`${description} must be a non-empty string.`);
11025
+ return value;
11026
+ }
11027
+ /** Stable public identity shared by events and durable workflow-call provenance. */
11028
+ function projectExecutionId(platformRunId, rawRunId, jobId) {
11029
+ return opaqueId("execution", platformRunId, rawRunId, jobId);
11030
+ }
11031
+ async function opaqueId(prefix, ...parts) {
11032
+ const bytes = encoder.encode(JSON.stringify([
11033
+ 1,
11034
+ prefix,
11035
+ ...parts
11036
+ ]));
11037
+ const input = new Uint8Array(bytes.byteLength);
11038
+ input.set(bytes);
11039
+ return `${prefix}_${[...new Uint8Array(await crypto.subtle.digest("SHA-256", input))].slice(0, 16).map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
11040
+ }
11041
+ function message(value) {
11042
+ return string(value, "Runtime event message").replace(/Bearer\s+\S+/gi, "Bearer [REDACTED]").replace(/\b(api[-_ ]?key|authorization|password|secret|token)\s*[:=]\s*\S+/gi, "$1=[REDACTED]");
11043
+ }
11044
+ //#endregion
10945
11045
  //#region src/execution/common/wait.ts
10946
11046
  /** Shared by decision entry points, the editor, and durable decision storage. */
10947
- var waitCommentSchema = string().trim().refine((value) => [...value].length <= 2e3, "Wait comment must contain at most 2,000 Unicode code points.").nullable().optional();
11047
+ var waitCommentSchema = string$1().trim().refine((value) => [...value].length <= 2e3, "Wait comment must contain at most 2,000 Unicode code points.").nullable().optional();
10948
11048
  function normalizeWaitComment$1(value) {
10949
11049
  return waitCommentSchema.parse(value) || null;
10950
11050
  }
@@ -10972,12 +11072,46 @@ function usesPending(graph, nodeId) {
10972
11072
  return graph.edges.some((edge) => edge.source == nodeId && edge.sourceHandle == "pending") || Object.values(graph.nodes).some((node) => !isTriggerNode(node) && Object.values(nodeInputMappings(node)).some((mapping) => mapping.kind == "sources" && mapping.sources.some((source) => source.kind == "node" && source.nodeId == nodeId && source.output == "pending")));
10973
11073
  }
10974
11074
  var waitRetentionMs = 12e4;
11075
+ var NodeValidationError = class extends PortValidationError {
11076
+ constructor(code, error) {
11077
+ super(error instanceof Error ? error.message : String(error));
11078
+ this.code = code;
11079
+ }
11080
+ };
10975
11081
  function nodeFailure(error, project) {
11082
+ if (error instanceof NodeValidationError) return {
11083
+ code: error.code,
11084
+ message: error.message,
11085
+ catchable: true
11086
+ };
10976
11087
  return project?.(error) ?? {
10977
11088
  code: "node.failed",
10978
11089
  message: error instanceof Error ? error.message : String(error)
10979
11090
  };
10980
11091
  }
11092
+ function invokeWithRetry(context, node, invocation) {
11093
+ const retry = supportsNodeRetry(node) ? node.retry : void 0;
11094
+ const attempt = (index) => Effect.suspend(() => context.invokeTask(index == 0 ? invocation : {
11095
+ ...invocation,
11096
+ invocationId: context.createId()
11097
+ }).pipe(Effect.catch((error) => {
11098
+ const failure = nodeFailure(error, context.projectFailure);
11099
+ if (retry == null || index >= retry.maxRetries || failure.retryable !== true) return Effect.fail(error);
11100
+ return Effect.gen(function* () {
11101
+ yield* context.emit({
11102
+ type: "node.log",
11103
+ level: "warn",
11104
+ runId: invocation.runId,
11105
+ nodeId: invocation.nodeId,
11106
+ jobId: invocation.jobId,
11107
+ message: `Attempt ${index + 1}/${retry.maxRetries + 1} failed (${failure.code}): ${failure.message}. Retrying attempt ${index + 2}/${retry.maxRetries + 1} in ${retry.intervalMs} ms.`
11108
+ });
11109
+ yield* Effect.sleep(retry.intervalMs);
11110
+ return yield* attempt(index + 1);
11111
+ });
11112
+ })));
11113
+ return attempt(0);
11114
+ }
10981
11115
  function nodeTitle(node) {
10982
11116
  if (node.name != null) return node.name;
10983
11117
  switch (node.kind) {
@@ -11015,9 +11149,9 @@ function checkpointJson(value, description, depth = 0) {
11015
11149
  }
11016
11150
  var agentCheckpointSchema = strictObject({
11017
11151
  state: json$1(),
11018
- callId: string().min(1),
11019
- toolId: string().min(1),
11020
- input: record$1(string(), json$1()),
11152
+ callId: string$1().min(1),
11153
+ toolId: string$1().min(1),
11154
+ input: record$1(string$1(), json$1()),
11021
11155
  rounds: number().int().nonnegative(),
11022
11156
  version: literal(1)
11023
11157
  });
@@ -11041,7 +11175,7 @@ function decodeFlowRunCheckpoint(input) {
11041
11175
  "waits",
11042
11176
  ...source.calls === void 0 ? [] : ["calls"]
11043
11177
  ], "Flow Run checkpoint");
11044
- if (source.version != 5) throw new Error("Flow Run checkpoint version is unsupported.");
11178
+ if (source.version != 6) throw new Error("Flow Run checkpoint version is unsupported.");
11045
11179
  const bindingValues = Object.fromEntries(Object.entries(checkpointRecord(source.bindingValues, "Checkpoint bindings")).map(([id, value]) => {
11046
11180
  if (typeof value != "string") throw new Error("Checkpoint binding must be a string.");
11047
11181
  return [id, value];
@@ -11049,31 +11183,39 @@ function decodeFlowRunCheckpoint(input) {
11049
11183
  const inputs = Object.fromEntries(Object.entries(checkpointRecord(source.inputs, "Checkpoint inputs")).map(([id, value]) => [id, Object.fromEntries(Object.entries(checkpointRecord(value, "Checkpoint node inputs")).map(([handle, item]) => [handle, checkpointJson(item, "Checkpoint input")]))]));
11050
11184
  const results = Object.fromEntries(Object.entries(checkpointRecord(source.results, "Checkpoint results")).map(([id, value]) => {
11051
11185
  const result = checkpointRecord(value, "Checkpoint result");
11052
- checkpointExact(result, ["jobId", "outputs"], "Checkpoint result");
11186
+ if (result.handled !== void 0 && result.handled !== true) throw new Error("Checkpoint handled flag is invalid.");
11187
+ checkpointExact(result, [
11188
+ "jobId",
11189
+ "outputs",
11190
+ ...result.systemOutputs === void 0 ? [] : ["systemOutputs"],
11191
+ ...result.handled === void 0 ? [] : ["handled"]
11192
+ ], "Checkpoint result");
11053
11193
  return [id, {
11054
11194
  jobId: checkpointString(result.jobId, "Checkpoint job ID"),
11195
+ ...result.systemOutputs === void 0 ? {} : { systemOutputs: outputRecord(checkpointJson(result.systemOutputs, "Checkpoint system outputs"), id) },
11196
+ ...result.handled === true ? { handled: true } : {},
11055
11197
  outputs: Object.fromEntries(Object.entries(checkpointRecord(result.outputs, "Checkpoint outputs")).map(([handle, item]) => [handle, checkpointJson(item, "Checkpoint output")]))
11056
11198
  }];
11057
11199
  }));
11058
- const counts = record$1(string(), record$1(string(), number().int().positive().max(Number.MAX_SAFE_INTEGER))).parse(source.counts);
11200
+ const counts = record$1(string$1(), record$1(string$1(), number().int().positive().max(Number.MAX_SAFE_INTEGER))).parse(source.counts);
11059
11201
  const dependencies = dependenciesSchema.parse(source.dependencies);
11060
11202
  const pendingWaits = array(strictObject({
11061
- jobId: string().min(1),
11062
- nodeId: string().min(1),
11203
+ jobId: string$1().min(1),
11204
+ nodeId: string$1().min(1),
11063
11205
  value: json$1(),
11064
- waitId: string().min(1),
11206
+ waitId: string$1().min(1),
11065
11207
  pending: json$1().optional()
11066
11208
  })).parse(source.waits);
11067
11209
  const calls = array(strictObject({
11068
- jobId: string().min(1),
11069
- nodeId: string().min(1),
11070
- childRunId: string().min(1),
11071
- input: record$1(string(), json$1())
11210
+ jobId: string$1().min(1),
11211
+ nodeId: string$1().min(1),
11212
+ childRunId: string$1().min(1),
11213
+ input: record$1(string$1(), json$1())
11072
11214
  })).parse(source.calls ?? []);
11073
11215
  if (pendingWaits.length + calls.length == 0) throw new Error("Checkpoint has no pending execution.");
11074
- const agents = record$1(string(), strictObject({
11075
- invocationId: string().min(1),
11076
- input: record$1(string(), json$1()),
11216
+ const agents = record$1(string$1(), strictObject({
11217
+ invocationId: string$1().min(1),
11218
+ input: record$1(string$1(), json$1()),
11077
11219
  remainingMs: number().positive().optional(),
11078
11220
  checkpoint: agentCheckpointSchema
11079
11221
  })).parse(source.agents);
@@ -11097,7 +11239,7 @@ function decodeFlowRunCheckpoint(input) {
11097
11239
  dependencies,
11098
11240
  inputs,
11099
11241
  results,
11100
- version: 5,
11242
+ version: 6,
11101
11243
  waits: pendingWaits,
11102
11244
  ...source.calls === void 0 ? {} : { calls }
11103
11245
  };
@@ -11182,14 +11324,27 @@ function validateCheckpoint(target, checkpoint, resolveInputs) {
11182
11324
  if (node == null || isTriggerNode(node) || count > (node.maxExecutions ?? 1e3)) throw new Error("Checkpoint execution count is invalid.");
11183
11325
  }
11184
11326
  }
11185
- const validateResults = (results, frame = false) => {
11327
+ const validateResults = (results, frame = false, metadata = checkpoint.results) => {
11186
11328
  for (const [id, outputs] of Object.entries(results)) {
11329
+ const result = metadata[id];
11187
11330
  const node = target.graph.nodes[id];
11188
11331
  if (node == null) throw new Error("Checkpoint result node is missing.");
11332
+ const systemEnabled = nodeSystemOutputPorts(node).error != null;
11333
+ if (systemEnabled && result?.systemOutputs == null) throw new Error("Checkpoint system output is missing.");
11334
+ if (!isTriggerNode(node) && checkpoint.counts[""]?.[id] == null) throw new Error("Checkpoint execution count is missing.");
11335
+ if (result?.systemOutputs != null) {
11336
+ const error = result.systemOutputs.error;
11337
+ if (!systemEnabled || Object.keys(result.systemOutputs).length != 1 || !Object.hasOwn(result.systemOutputs, "error") || error !== null && (!matchesSchema(error, nodeErrorSchema) || typeof error != "object" || !("nodeId" in error) || error.nodeId != id)) throw new Error("Checkpoint system output is invalid.");
11338
+ }
11339
+ const handled = frame ? result?.systemOutputs?.error != null : result?.handled === true;
11340
+ if (handled !== (result?.systemOutputs?.error != null)) throw new Error("Checkpoint failure status is inconsistent.");
11341
+ if (handled) {
11342
+ if (Object.keys(outputs).length || result.systemOutputs?.error == null) throw new Error("Checkpoint handled failure is invalid.");
11343
+ continue;
11344
+ }
11189
11345
  if (isTriggerNode(node)) {
11190
11346
  if (!matchesTriggerOutputs(node, outputs)) throw new Error("Checkpoint Trigger output is invalid.");
11191
11347
  } else {
11192
- if (checkpoint.counts[""]?.[id] == null) throw new Error("Checkpoint execution count is missing.");
11193
11348
  if (!jsonEqual(validateOutputs(id, node, outputs), outputs)) throw new Error("Checkpoint node outputs are incomplete.");
11194
11349
  const count = Object.keys(outputs).length;
11195
11350
  if (node.kind == "condition" && count != 0 || isResolutionNode(node) && (resolutionActions(node).filter((action) => Object.hasOwn(outputs, action)).length > 1 || !resolutionActions(node).some((action) => Object.hasOwn(outputs, action)) && !(frame && Object.hasOwn(outputs, "pending")))) throw new Error("Checkpoint branch result is invalid.");
@@ -11208,7 +11363,7 @@ function validateCheckpoint(target, checkpoint, resolveInputs) {
11208
11363
  }
11209
11364
  for (const [nodeId, state] of Object.entries(checkpoint.dependencies.nodes)) {
11210
11365
  const frame = dependencyValues(state.input);
11211
- validateResults(frame, true);
11366
+ validateResults(frame, true, state.input);
11212
11367
  if (!isTriggerNode(target.graph.nodes[nodeId]) && (state.status == "running" || state.status == "completed")) {
11213
11368
  const triggers = Object.keys(frame).filter((id) => isTriggerNode(target.graph.nodes[id]));
11214
11369
  if (triggers.length != 1 || triggers[0] != triggerIds[0] || !jsonEqual(frame[triggers[0]], checkpoint.results[triggers[0]].outputs)) throw new Error("Checkpoint input Trigger does not match the Run.");
@@ -11216,7 +11371,7 @@ function validateCheckpoint(target, checkpoint, resolveInputs) {
11216
11371
  if (state.output != null) validateResults({ [nodeId]: state.output }, state.status == "running");
11217
11372
  if (state.status == "completed") {
11218
11373
  const result = checkpoint.results[nodeId];
11219
- if (result == null || state.jobId != null && state.jobId != result.jobId || !jsonEqual(state.output, result.outputs)) throw new Error("Checkpoint completed dependency conflicts with its result.");
11374
+ if (result == null || state.jobId != null && state.jobId != result.jobId || !jsonEqual(state.output, result.outputs) || !jsonEqual(state.systemOutputs ?? {}, result.systemOutputs ?? {})) throw new Error("Checkpoint completed dependency conflicts with its result.");
11220
11375
  }
11221
11376
  }
11222
11377
  for (const call of checkpoint.calls ?? []) {
@@ -11290,15 +11445,15 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11290
11445
  let measuredAt = yield* Clock.currentTimeMillis;
11291
11446
  let idleSince;
11292
11447
  const agents = { ...resume?.checkpoint.agents };
11293
- const resolveInput = (mapping, port, supplied, description, valuesByNode, required = false) => {
11448
+ const resolveInput = (mapping, port, supplied, description, valuesByNode, required = false, systemByNode = {}) => {
11294
11449
  let value = inputValue(mapping, supplied === void 0 ? port.value : supplied);
11295
11450
  if (mapping?.kind == "sources") {
11296
11451
  const values = mapping.sources.flatMap((source) => {
11297
11452
  if (source.kind == "binding") return Object.hasOwn(context.bindingValues, source.bindingId) ? [context.bindingValues[source.bindingId]] : [];
11298
- const outputs = valuesByNode[source.nodeId];
11453
+ const outputs = (source.system ? systemByNode : valuesByNode)[source.nodeId];
11299
11454
  if (outputs == null || !Object.hasOwn(outputs, source.output)) return [];
11300
11455
  const output = outputs[source.output];
11301
- if (source.field === void 0) return [output];
11456
+ if (source.field === void 0 || output === null) return [output];
11302
11457
  return output != null && typeof output === "object" && !Array.isArray(output) && Object.hasOwn(output, source.field) ? [output[source.field]] : [];
11303
11458
  });
11304
11459
  if (values.length > 1) throw new Error(`${description} has multiple available sources.`);
@@ -11313,21 +11468,44 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11313
11468
  const resolveInputs = (nodeId, node) => {
11314
11469
  const mappings = nodeInputMappings(node);
11315
11470
  const frame = dependencies.inputValues(nodeId);
11316
- return Object.fromEntries(Object.entries(nodeInputPorts(node)).map(([handle, port]) => [handle, resolveInput(mappings[handle], port, launch[nodeId]?.[handle], `Node "${nodeId}" input "${handle}"`, frame, node.kind == "condition")]));
11471
+ const systemFrame = dependencies.systemInputValues(nodeId);
11472
+ return Object.fromEntries(Object.entries(nodeInputPorts(node)).map(([handle, port]) => [handle, resolveInput(mappings[handle], port, launch[nodeId]?.[handle], `Node "${nodeId}" input "${handle}"`, frame, node.kind == "condition", systemFrame)]));
11317
11473
  };
11318
- const commit = (nodeId, jobId, outputs, releasedHandles = Object.keys(outputs)) => Effect.uninterruptible(Effect.gen(function* () {
11319
- yield* context.emit({
11474
+ const commit = (nodeId, jobId, outputs, releasedHandles = Object.keys(outputs), failure) => Effect.uninterruptible(Effect.gen(function* () {
11475
+ const node = target.graph.nodes[nodeId];
11476
+ const systemOutputs = nodeSystemOutputPorts(node).error == null ? void 0 : { error: failure == null ? null : {
11477
+ code: failure.code,
11478
+ message: message(failure.message),
11479
+ nodeId,
11480
+ nodeName: nodeTitle(node) ?? nodeId,
11481
+ runId,
11482
+ executionId: yield* Effect.tryPromise(() => projectExecutionId(runId, runId, jobId))
11483
+ } };
11484
+ const system = systemOutputs == null ? {} : { systemOutputs };
11485
+ const handled = failure == null ? {} : { handled: true };
11486
+ yield* context.emit(failure == null ? {
11320
11487
  jobId,
11321
11488
  nodeId,
11322
11489
  outputs,
11323
11490
  runId,
11491
+ ...system,
11324
11492
  type: "node.completed"
11493
+ } : {
11494
+ ...failure,
11495
+ jobId,
11496
+ nodeId,
11497
+ runId,
11498
+ ...system,
11499
+ handled: true,
11500
+ type: "node.failed"
11325
11501
  });
11326
11502
  completed.set(nodeId, {
11327
11503
  jobId,
11328
- outputs
11504
+ outputs,
11505
+ ...system,
11506
+ ...handled
11329
11507
  });
11330
- dependencies.release(nodeId, outputs, releasedHandles, true);
11508
+ dependencies.release(nodeId, outputs, releasedHandles, true, systemOutputs);
11331
11509
  }));
11332
11510
  const executeNode = (nodeId, node, jobId, nodeInputs, resolution) => {
11333
11511
  const config = agentConfig(node);
@@ -11366,9 +11544,10 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11366
11544
  break;
11367
11545
  case "task": {
11368
11546
  const frame = dependencies.inputValues(nodeId);
11547
+ const systemFrame = dependencies.systemInputValues(nodeId);
11369
11548
  const previousIds = dependencies.state.nodes[nodeId].previous;
11370
11549
  const additional = new Set((node.additionalInputs ?? []).map((port) => port.handle));
11371
- const result = yield* context.invokeTask({
11550
+ const result = yield* invokeWithRetry(context, node, {
11372
11551
  ...pendingCalls.has(jobId) ? { workflowRunId: pendingCalls.get(jobId).childRunId } : {},
11373
11552
  additionalInputs: Object.fromEntries(Object.entries(nodeInputs).filter(([handle]) => additional.has(handle))),
11374
11553
  blockId: "moduleId" in node.task ? node.task.moduleId : nodeId,
@@ -11394,16 +11573,17 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11394
11573
  getPrevious: () => {
11395
11574
  return previousIds.map((previousId) => {
11396
11575
  const previous = target.graph.nodes[previousId];
11397
- return {
11576
+ const systemOutputs = systemFrame[previousId];
11577
+ return Object.assign({
11398
11578
  id: previousId,
11399
- name: previous.name ?? (!isTriggerNode(previous) ? nodeTitle(previous) : void 0) ?? previousId,
11579
+ name: nodeTitle(previous) ?? previousId,
11400
11580
  outputs: frame[previousId],
11401
11581
  outputDefs: Object.entries(nodeOutputPorts(previous)).map(([handle, definition]) => Object.assign({
11402
11582
  handle,
11403
11583
  jsonSchema: definition.jsonSchema,
11404
11584
  nullable: definition.nullable
11405
11585
  }, definition.description == null ? {} : { description: definition.description }))
11406
- };
11586
+ }, systemOutputs == null ? {} : { systemOutputs });
11407
11587
  });
11408
11588
  }
11409
11589
  } : { kind: "managed" }
@@ -11411,10 +11591,10 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11411
11591
  if ("executor" in node.task && node.task.executor.kind == "workflow") {
11412
11592
  const response = discriminatedUnion("kind", [strictObject({
11413
11593
  kind: literal("calling"),
11414
- childRunId: string().min(1)
11594
+ childRunId: string$1().min(1)
11415
11595
  }), strictObject({
11416
11596
  kind: literal("completed"),
11417
- outputs: record$1(string(), json$1())
11597
+ outputs: record$1(string$1(), json$1())
11418
11598
  })]).parse(result);
11419
11599
  if (response.kind == "calling") return {
11420
11600
  kind: "calling",
@@ -11442,7 +11622,10 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11442
11622
  }
11443
11623
  outputs = { output: response.output };
11444
11624
  } else if ("executor" in node.task && node.task.executor.kind == "connector" && node.task.executor.outputMode == "value") outputs = { output: checkpointJson(result, `Node "${nodeId}" output`) };
11445
- else outputs = outputRecord(result, nodeId);
11625
+ else outputs = yield* Effect.try({
11626
+ try: () => outputRecord(result, nodeId),
11627
+ catch: (error) => new NodeValidationError("node.output-invalid", error)
11628
+ });
11446
11629
  break;
11447
11630
  }
11448
11631
  case "approval":
@@ -11453,7 +11636,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11453
11636
  kind: "completed",
11454
11637
  outputs: validateOutputs(nodeId, node, outputs)
11455
11638
  }),
11456
- catch: (error) => error instanceof Error ? error : new Error(String(error))
11639
+ catch: (error) => new NodeValidationError("node.output-invalid", error)
11457
11640
  });
11458
11641
  });
11459
11642
  return nodeRemainingMs == null ? execution : execution.pipe(Effect.timeoutOrElse({
@@ -11539,28 +11722,34 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11539
11722
  counts[nodeId] = count + 1;
11540
11723
  dependencies.begin(nodeId, jobId);
11541
11724
  runNode(observe(nodeId, jobId, Effect.gen(function* () {
11542
- const nodeInputs = yield* Effect.try({
11543
- try: () => resolveInputs(nodeId, node),
11544
- catch: (error) => error instanceof Error ? error : new Error(String(error))
11545
- });
11546
- if (isResolutionNode(node)) {
11547
- yield* context.emit({
11548
- inputs: Object.fromEntries(Object.entries(nodeInputs).filter(([handle]) => {
11549
- const mapping = nodeInputMappings(node)[handle];
11550
- return mapping?.kind != "sources" || mapping.sources.every((source) => source.kind != "binding");
11551
- })),
11552
- jobId,
11553
- nodeId,
11554
- nodeKind: node.kind,
11555
- ...node.name == null ? {} : { nodeTitle: node.name },
11556
- runId,
11557
- type: "node.started"
11725
+ const result = yield* Effect.gen(function* () {
11726
+ const nodeInputs = yield* Effect.try({
11727
+ try: () => resolveInputs(nodeId, node),
11728
+ catch: (error) => new NodeValidationError("node.input-invalid", error)
11558
11729
  });
11559
- yield* createWait(nodeId, jobId, nodeInputs);
11560
- return;
11561
- }
11562
- const result = yield* executeNode(nodeId, node, jobId, nodeInputs);
11563
- yield* settleNode(nodeId, jobId, result);
11730
+ if (isResolutionNode(node)) {
11731
+ yield* context.emit({
11732
+ inputs: Object.fromEntries(Object.entries(nodeInputs).filter(([handle]) => {
11733
+ const mapping = nodeInputMappings(node)[handle];
11734
+ return mapping?.kind != "sources" || mapping.sources.every((source) => source.kind != "binding");
11735
+ })),
11736
+ jobId,
11737
+ nodeId,
11738
+ nodeKind: node.kind,
11739
+ ...node.name == null ? {} : { nodeTitle: node.name },
11740
+ runId,
11741
+ type: "node.started"
11742
+ });
11743
+ yield* createWait(nodeId, jobId, nodeInputs);
11744
+ return;
11745
+ }
11746
+ return yield* executeNode(nodeId, node, jobId, nodeInputs);
11747
+ }).pipe(Effect.catch((error) => {
11748
+ const failure = nodeFailure(error, context.projectFailure);
11749
+ if (!supportsNodeErrorHandling(node) || node.onError != "error" || failure.catchable !== true) return Effect.fail(error);
11750
+ return commit(nodeId, jobId, {}, [], failure);
11751
+ }));
11752
+ if (result != null) yield* settleNode(nodeId, jobId, result);
11564
11753
  })).pipe(Effect.ensuring(Queue.offer(changes, void 0))));
11565
11754
  };
11566
11755
  if (resume != null) yield* Effect.try({
@@ -11638,7 +11827,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11638
11827
  results: Object.fromEntries(completed),
11639
11828
  counts: context.counts,
11640
11829
  dependencies: dependencies.state,
11641
- version: 5,
11830
+ version: 6,
11642
11831
  agents,
11643
11832
  waits: [...pendingWaits.values()],
11644
11833
  ...pendingCalls.size == 0 ? {} : { calls: [...pendingCalls.values()] }
@@ -11672,9 +11861,10 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11672
11861
  const saved = completed.get(nodeId);
11673
11862
  return saved == null ? [] : [{
11674
11863
  nodeId,
11675
- status: "completed",
11864
+ status: saved.handled ? "error-handled" : "completed",
11676
11865
  jobId: saved.jobId,
11677
- outputs: saved.outputs
11866
+ outputs: saved.outputs,
11867
+ ...saved.systemOutputs == null ? {} : { systemOutputs: saved.systemOutputs }
11678
11868
  }];
11679
11869
  })
11680
11870
  };