@duckflux/runner 0.6.8 → 0.7.1
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/main.js +2513 -603
- package/package.json +7 -7
- package/src/lint.ts +1 -1
- package/src/main.ts +10 -2
- package/src/run.ts +3 -1
- package/src/server.ts +67 -0
- package/src/validate.ts +1 -1
package/dist/main.js
CHANGED
|
@@ -23,10 +23,10 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
23
23
|
var exports_eventhub = {};
|
|
24
24
|
__export(exports_eventhub, {
|
|
25
25
|
createHub: () => createHub,
|
|
26
|
-
MemoryHub: () =>
|
|
26
|
+
MemoryHub: () => MemoryHub2
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
class
|
|
29
|
+
class MemoryHub2 {
|
|
30
30
|
listeners = new Map;
|
|
31
31
|
buffer = new Map;
|
|
32
32
|
closed = false;
|
|
@@ -114,7 +114,7 @@ class MemoryHub {
|
|
|
114
114
|
async function createHub(config) {
|
|
115
115
|
switch (config.backend) {
|
|
116
116
|
case "memory":
|
|
117
|
-
return new
|
|
117
|
+
return new MemoryHub2;
|
|
118
118
|
case "nats":
|
|
119
119
|
throw new Error("NATS backend has been moved to @duckflux/hub-nats. " + "Install it and pass a NatsHub instance via ExecuteOptions.hub instead.");
|
|
120
120
|
case "redis":
|
|
@@ -126,25 +126,27 @@ async function createHub(config) {
|
|
|
126
126
|
var init_eventhub = () => {};
|
|
127
127
|
|
|
128
128
|
// src/main.ts
|
|
129
|
-
import { readFileSync
|
|
129
|
+
import { readFileSync } from "fs";
|
|
130
130
|
import { parseArgs } from "util";
|
|
131
|
-
import { dirname as
|
|
131
|
+
import { dirname as dirname5, resolve as resolve5 } from "path";
|
|
132
132
|
|
|
133
|
-
// src/
|
|
134
|
-
import {
|
|
133
|
+
// src/lint.ts
|
|
134
|
+
import { dirname as dirname2 } from "node:path";
|
|
135
135
|
|
|
136
|
-
// ../core/dist/
|
|
136
|
+
// ../core/dist/index.js
|
|
137
137
|
import { createRequire as createRequire2 } from "node:module";
|
|
138
138
|
import { readFile } from "node:fs/promises";
|
|
139
|
-
import { readFileSync } from "node:fs";
|
|
140
139
|
import { constants } from "node:fs";
|
|
141
140
|
import { access } from "node:fs/promises";
|
|
142
141
|
import { resolve } from "node:path";
|
|
142
|
+
import { writeFile } from "node:fs/promises";
|
|
143
|
+
import { join } from "node:path";
|
|
144
|
+
import { appendFile, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
145
|
+
import { join as join2 } from "node:path";
|
|
146
|
+
import { join as join3 } from "node:path";
|
|
143
147
|
import { spawn } from "node:child_process";
|
|
144
148
|
import { dirname, resolve as resolve2 } from "node:path";
|
|
145
149
|
import { resolve as resolvePath, isAbsolute } from "node:path";
|
|
146
|
-
import { dirname as dirname2, resolve as resolve3 } from "node:path";
|
|
147
|
-
import { env } from "node:process";
|
|
148
150
|
var __create = Object.create;
|
|
149
151
|
var __getProtoOf = Object.getPrototypeOf;
|
|
150
152
|
var __defProp2 = Object.defineProperty;
|
|
@@ -21520,20 +21522,20 @@ var require_compile = __commonJS((exports) => {
|
|
|
21520
21522
|
var validate_1 = require_validate();
|
|
21521
21523
|
|
|
21522
21524
|
class SchemaEnv {
|
|
21523
|
-
constructor(
|
|
21525
|
+
constructor(env) {
|
|
21524
21526
|
var _a;
|
|
21525
21527
|
this.refs = {};
|
|
21526
21528
|
this.dynamicAnchors = {};
|
|
21527
21529
|
let schema;
|
|
21528
|
-
if (typeof
|
|
21529
|
-
schema =
|
|
21530
|
-
this.schema =
|
|
21531
|
-
this.schemaId =
|
|
21532
|
-
this.root =
|
|
21533
|
-
this.baseId = (_a =
|
|
21534
|
-
this.schemaPath =
|
|
21535
|
-
this.localRefs =
|
|
21536
|
-
this.meta =
|
|
21530
|
+
if (typeof env.schema == "object")
|
|
21531
|
+
schema = env.schema;
|
|
21532
|
+
this.schema = env.schema;
|
|
21533
|
+
this.schemaId = env.schemaId;
|
|
21534
|
+
this.root = env.root || this;
|
|
21535
|
+
this.baseId = (_a = env.baseId) !== null && _a !== undefined ? _a : (0, resolve_1.normalizeId)(schema === null || schema === undefined ? undefined : schema[env.schemaId || "$id"]);
|
|
21536
|
+
this.schemaPath = env.schemaPath;
|
|
21537
|
+
this.localRefs = env.localRefs;
|
|
21538
|
+
this.meta = env.meta;
|
|
21537
21539
|
this.$async = schema === null || schema === undefined ? undefined : schema.$async;
|
|
21538
21540
|
this.refs = {};
|
|
21539
21541
|
}
|
|
@@ -21630,7 +21632,7 @@ var require_compile = __commonJS((exports) => {
|
|
|
21630
21632
|
const schOrFunc = root2.refs[ref];
|
|
21631
21633
|
if (schOrFunc)
|
|
21632
21634
|
return schOrFunc;
|
|
21633
|
-
let _sch =
|
|
21635
|
+
let _sch = resolve3.call(this, root2, ref);
|
|
21634
21636
|
if (_sch === undefined) {
|
|
21635
21637
|
const schema = (_a = root2.localRefs) === null || _a === undefined ? undefined : _a[ref];
|
|
21636
21638
|
const { schemaId } = this.opts;
|
|
@@ -21657,7 +21659,7 @@ var require_compile = __commonJS((exports) => {
|
|
|
21657
21659
|
function sameSchemaEnv(s1, s2) {
|
|
21658
21660
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
21659
21661
|
}
|
|
21660
|
-
function
|
|
21662
|
+
function resolve3(root2, ref) {
|
|
21661
21663
|
let sch;
|
|
21662
21664
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
21663
21665
|
ref = sch;
|
|
@@ -21716,15 +21718,15 @@ var require_compile = __commonJS((exports) => {
|
|
|
21716
21718
|
baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
|
|
21717
21719
|
}
|
|
21718
21720
|
}
|
|
21719
|
-
let
|
|
21721
|
+
let env;
|
|
21720
21722
|
if (typeof schema != "boolean" && schema.$ref && !(0, util_1.schemaHasRulesButRef)(schema, this.RULES)) {
|
|
21721
21723
|
const $ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schema.$ref);
|
|
21722
|
-
|
|
21724
|
+
env = resolveSchema.call(this, root2, $ref);
|
|
21723
21725
|
}
|
|
21724
21726
|
const { schemaId } = this.opts;
|
|
21725
|
-
|
|
21726
|
-
if (
|
|
21727
|
-
return
|
|
21727
|
+
env = env || new SchemaEnv({ schema, schemaId, root: root2, baseId });
|
|
21728
|
+
if (env.schema !== env.root.schema)
|
|
21729
|
+
return env;
|
|
21728
21730
|
return;
|
|
21729
21731
|
}
|
|
21730
21732
|
});
|
|
@@ -22179,7 +22181,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
22179
22181
|
}
|
|
22180
22182
|
return uri;
|
|
22181
22183
|
}
|
|
22182
|
-
function
|
|
22184
|
+
function resolve3(baseURI, relativeURI, options) {
|
|
22183
22185
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
22184
22186
|
const resolved = resolveComponent(parse2(baseURI, schemelessOptions), parse2(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
22185
22187
|
schemelessOptions.skipEscape = true;
|
|
@@ -22407,7 +22409,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
22407
22409
|
var fastUri = {
|
|
22408
22410
|
SCHEMES,
|
|
22409
22411
|
normalize,
|
|
22410
|
-
resolve:
|
|
22412
|
+
resolve: resolve3,
|
|
22411
22413
|
resolveComponent,
|
|
22412
22414
|
equal,
|
|
22413
22415
|
serialize,
|
|
@@ -23038,8 +23040,8 @@ var require_ref = __commonJS((exports) => {
|
|
|
23038
23040
|
schemaType: "string",
|
|
23039
23041
|
code(cxt) {
|
|
23040
23042
|
const { gen, schema: $ref, it } = cxt;
|
|
23041
|
-
const { baseId, schemaEnv:
|
|
23042
|
-
const { root: root2 } =
|
|
23043
|
+
const { baseId, schemaEnv: env, validateName, opts, self: self2 } = it;
|
|
23044
|
+
const { root: root2 } = env;
|
|
23043
23045
|
if (($ref === "#" || $ref === "#/") && baseId === root2.baseId)
|
|
23044
23046
|
return callRootRef();
|
|
23045
23047
|
const schOrEnv = compile_1.resolveRef.call(self2, root2, baseId, $ref);
|
|
@@ -23049,8 +23051,8 @@ var require_ref = __commonJS((exports) => {
|
|
|
23049
23051
|
return callValidate(schOrEnv);
|
|
23050
23052
|
return inlineRefSchema(schOrEnv);
|
|
23051
23053
|
function callRootRef() {
|
|
23052
|
-
if (
|
|
23053
|
-
return callRef(cxt, validateName,
|
|
23054
|
+
if (env === root2)
|
|
23055
|
+
return callRef(cxt, validateName, env, env.$async);
|
|
23054
23056
|
const rootName = gen.scopeValue("root", { ref: root2 });
|
|
23055
23057
|
return callRef(cxt, (0, codegen_1._)`${rootName}.validate`, root2, root2.$async);
|
|
23056
23058
|
}
|
|
@@ -23080,14 +23082,14 @@ var require_ref = __commonJS((exports) => {
|
|
|
23080
23082
|
exports.getValidate = getValidate;
|
|
23081
23083
|
function callRef(cxt, v, sch, $async) {
|
|
23082
23084
|
const { gen, it } = cxt;
|
|
23083
|
-
const { allErrors, schemaEnv:
|
|
23085
|
+
const { allErrors, schemaEnv: env, opts } = it;
|
|
23084
23086
|
const passCxt = opts.passContext ? names_1.default.this : codegen_1.nil;
|
|
23085
23087
|
if ($async)
|
|
23086
23088
|
callAsyncRef();
|
|
23087
23089
|
else
|
|
23088
23090
|
callSyncRef();
|
|
23089
23091
|
function callAsyncRef() {
|
|
23090
|
-
if (!
|
|
23092
|
+
if (!env.$async)
|
|
23091
23093
|
throw new Error("async schema referenced by sync schema");
|
|
23092
23094
|
const valid = gen.let("valid");
|
|
23093
23095
|
gen.try(() => {
|
|
@@ -25796,6 +25798,549 @@ var require_dist2 = __commonJS((exports, module) => {
|
|
|
25796
25798
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25797
25799
|
exports.default = formatsPlugin;
|
|
25798
25800
|
});
|
|
25801
|
+
var duckflux_schema_default;
|
|
25802
|
+
var init_duckflux_schema = __esm2(() => {
|
|
25803
|
+
duckflux_schema_default = {
|
|
25804
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
25805
|
+
$id: "https://raw.githubusercontent.com/duckflux/spec/main/duckflux.schema.json",
|
|
25806
|
+
title: "duckflux Workflow",
|
|
25807
|
+
description: "Schema for duckflux — a minimal, deterministic, runtime-agnostic workflow DSL.",
|
|
25808
|
+
type: "object",
|
|
25809
|
+
required: ["flow"],
|
|
25810
|
+
additionalProperties: false,
|
|
25811
|
+
properties: {
|
|
25812
|
+
id: {
|
|
25813
|
+
type: "string",
|
|
25814
|
+
description: "Unique identifier for the workflow."
|
|
25815
|
+
},
|
|
25816
|
+
name: {
|
|
25817
|
+
type: "string",
|
|
25818
|
+
description: "Human-readable workflow name."
|
|
25819
|
+
},
|
|
25820
|
+
version: {
|
|
25821
|
+
description: "Version identifier for the workflow definition.",
|
|
25822
|
+
oneOf: [
|
|
25823
|
+
{ type: "string" },
|
|
25824
|
+
{ type: "integer" }
|
|
25825
|
+
]
|
|
25826
|
+
},
|
|
25827
|
+
defaults: {
|
|
25828
|
+
$ref: "#/$defs/defaults"
|
|
25829
|
+
},
|
|
25830
|
+
inputs: {
|
|
25831
|
+
$ref: "#/$defs/inputs"
|
|
25832
|
+
},
|
|
25833
|
+
participants: {
|
|
25834
|
+
type: "object",
|
|
25835
|
+
description: "Named steps that can be referenced in the flow.",
|
|
25836
|
+
additionalProperties: {
|
|
25837
|
+
$ref: "#/$defs/participant"
|
|
25838
|
+
},
|
|
25839
|
+
not: {
|
|
25840
|
+
anyOf: [
|
|
25841
|
+
{ required: ["workflow"] },
|
|
25842
|
+
{ required: ["execution"] },
|
|
25843
|
+
{ required: ["input"] },
|
|
25844
|
+
{ required: ["output"] },
|
|
25845
|
+
{ required: ["env"] },
|
|
25846
|
+
{ required: ["loop"] },
|
|
25847
|
+
{ required: ["event"] }
|
|
25848
|
+
]
|
|
25849
|
+
}
|
|
25850
|
+
},
|
|
25851
|
+
flow: {
|
|
25852
|
+
$ref: "#/$defs/flowSequence"
|
|
25853
|
+
},
|
|
25854
|
+
output: {
|
|
25855
|
+
$ref: "#/$defs/workflowOutput"
|
|
25856
|
+
}
|
|
25857
|
+
},
|
|
25858
|
+
$defs: {
|
|
25859
|
+
duration: {
|
|
25860
|
+
type: "string",
|
|
25861
|
+
pattern: "^[0-9]+(ms|s|m|h|d)$",
|
|
25862
|
+
description: "Duration string, e.g. '30s', '5m', '2h', '1d'."
|
|
25863
|
+
},
|
|
25864
|
+
celExpression: {
|
|
25865
|
+
type: "string",
|
|
25866
|
+
description: "A Google CEL expression."
|
|
25867
|
+
},
|
|
25868
|
+
defaults: {
|
|
25869
|
+
type: "object",
|
|
25870
|
+
description: "Global defaults applied to all participants.",
|
|
25871
|
+
additionalProperties: false,
|
|
25872
|
+
properties: {
|
|
25873
|
+
timeout: {
|
|
25874
|
+
$ref: "#/$defs/duration"
|
|
25875
|
+
},
|
|
25876
|
+
cwd: {
|
|
25877
|
+
type: "string",
|
|
25878
|
+
description: "Default working directory for exec participants. Supports CEL expressions."
|
|
25879
|
+
}
|
|
25880
|
+
}
|
|
25881
|
+
},
|
|
25882
|
+
inputs: {
|
|
25883
|
+
type: "object",
|
|
25884
|
+
description: "Workflow input parameters. Accessed in CEL as workflow.inputs.<field>. Each key is a parameter name. Value can be null (string, no schema), or a JSON Schema object for validation.",
|
|
25885
|
+
additionalProperties: {
|
|
25886
|
+
oneOf: [
|
|
25887
|
+
{ type: "null" },
|
|
25888
|
+
{ $ref: "#/$defs/inputField" }
|
|
25889
|
+
]
|
|
25890
|
+
}
|
|
25891
|
+
},
|
|
25892
|
+
inputField: {
|
|
25893
|
+
type: "object",
|
|
25894
|
+
description: "JSON Schema field definition with optional 'required: true' shortcut.",
|
|
25895
|
+
properties: {
|
|
25896
|
+
type: {
|
|
25897
|
+
type: "string",
|
|
25898
|
+
enum: ["string", "integer", "number", "boolean", "array", "object"]
|
|
25899
|
+
},
|
|
25900
|
+
description: { type: "string" },
|
|
25901
|
+
default: {},
|
|
25902
|
+
required: { type: "boolean" },
|
|
25903
|
+
format: { type: "string" },
|
|
25904
|
+
enum: { type: "array" },
|
|
25905
|
+
minimum: { type: "number" },
|
|
25906
|
+
maximum: { type: "number" },
|
|
25907
|
+
minLength: { type: "integer" },
|
|
25908
|
+
maxLength: { type: "integer" },
|
|
25909
|
+
pattern: { type: "string" },
|
|
25910
|
+
items: {
|
|
25911
|
+
$ref: "#/$defs/inputField"
|
|
25912
|
+
}
|
|
25913
|
+
},
|
|
25914
|
+
additionalProperties: false
|
|
25915
|
+
},
|
|
25916
|
+
retryConfig: {
|
|
25917
|
+
type: "object",
|
|
25918
|
+
description: "Retry configuration. Only applies when onError is 'retry'.",
|
|
25919
|
+
additionalProperties: false,
|
|
25920
|
+
required: ["max"],
|
|
25921
|
+
properties: {
|
|
25922
|
+
max: {
|
|
25923
|
+
type: "integer",
|
|
25924
|
+
minimum: 1,
|
|
25925
|
+
description: "Maximum number of retry attempts."
|
|
25926
|
+
},
|
|
25927
|
+
backoff: {
|
|
25928
|
+
$ref: "#/$defs/duration",
|
|
25929
|
+
description: "Interval between attempts. Default: 0s."
|
|
25930
|
+
},
|
|
25931
|
+
factor: {
|
|
25932
|
+
type: "number",
|
|
25933
|
+
minimum: 1,
|
|
25934
|
+
description: "Backoff multiplier. Default: 1 (no escalation)."
|
|
25935
|
+
}
|
|
25936
|
+
}
|
|
25937
|
+
},
|
|
25938
|
+
onError: {
|
|
25939
|
+
type: "string",
|
|
25940
|
+
description: "Error handling strategy: 'fail' (default), 'skip', 'retry', or a participant name for redirect.",
|
|
25941
|
+
minLength: 1
|
|
25942
|
+
},
|
|
25943
|
+
onTimeout: {
|
|
25944
|
+
type: "string",
|
|
25945
|
+
description: "Timeout handling strategy: 'fail' (default), 'skip', or a participant name for redirect.",
|
|
25946
|
+
minLength: 1
|
|
25947
|
+
},
|
|
25948
|
+
participantInput: {
|
|
25949
|
+
description: "Explicit input mapping. String for direct passthrough, object for structured mapping. Values are CEL expressions. Merged with implicit I/O chain input at runtime.",
|
|
25950
|
+
oneOf: [
|
|
25951
|
+
{ type: "string" },
|
|
25952
|
+
{
|
|
25953
|
+
type: "object",
|
|
25954
|
+
additionalProperties: {
|
|
25955
|
+
type: "string"
|
|
25956
|
+
}
|
|
25957
|
+
}
|
|
25958
|
+
]
|
|
25959
|
+
},
|
|
25960
|
+
participantOutputSchema: {
|
|
25961
|
+
type: "object",
|
|
25962
|
+
description: "Output schema (JSON Schema fields). Opt-in validation.",
|
|
25963
|
+
additionalProperties: {
|
|
25964
|
+
$ref: "#/$defs/inputField"
|
|
25965
|
+
}
|
|
25966
|
+
},
|
|
25967
|
+
payload: {
|
|
25968
|
+
description: "Event payload. String (CEL expression) or object with CEL expressions as values.",
|
|
25969
|
+
oneOf: [
|
|
25970
|
+
{ type: "string" },
|
|
25971
|
+
{
|
|
25972
|
+
type: "object",
|
|
25973
|
+
additionalProperties: {}
|
|
25974
|
+
}
|
|
25975
|
+
]
|
|
25976
|
+
},
|
|
25977
|
+
participant: {
|
|
25978
|
+
type: "object",
|
|
25979
|
+
required: ["type"],
|
|
25980
|
+
description: "A named, reusable building block of the workflow.",
|
|
25981
|
+
properties: {
|
|
25982
|
+
type: {
|
|
25983
|
+
type: "string",
|
|
25984
|
+
enum: ["exec", "http", "mcp", "workflow", "emit"],
|
|
25985
|
+
description: "Participant type."
|
|
25986
|
+
},
|
|
25987
|
+
as: {
|
|
25988
|
+
type: "string",
|
|
25989
|
+
description: "Human-readable display name."
|
|
25990
|
+
},
|
|
25991
|
+
timeout: {
|
|
25992
|
+
$ref: "#/$defs/duration"
|
|
25993
|
+
},
|
|
25994
|
+
onError: {
|
|
25995
|
+
$ref: "#/$defs/onError"
|
|
25996
|
+
},
|
|
25997
|
+
retry: {
|
|
25998
|
+
$ref: "#/$defs/retryConfig"
|
|
25999
|
+
},
|
|
26000
|
+
input: {
|
|
26001
|
+
$ref: "#/$defs/participantInput"
|
|
26002
|
+
},
|
|
26003
|
+
output: {
|
|
26004
|
+
$ref: "#/$defs/participantOutputSchema"
|
|
26005
|
+
},
|
|
26006
|
+
run: {
|
|
26007
|
+
type: "string",
|
|
26008
|
+
description: "[exec] Shell command to execute."
|
|
26009
|
+
},
|
|
26010
|
+
cwd: {
|
|
26011
|
+
type: "string",
|
|
26012
|
+
description: "[exec] Working directory. Supports CEL expressions."
|
|
26013
|
+
},
|
|
26014
|
+
url: {
|
|
26015
|
+
type: "string",
|
|
26016
|
+
description: "[http] Target URL. Supports CEL expressions."
|
|
26017
|
+
},
|
|
26018
|
+
method: {
|
|
26019
|
+
type: "string",
|
|
26020
|
+
enum: ["GET", "POST", "PUT", "PATCH", "DELETE"],
|
|
26021
|
+
description: "[http] HTTP method."
|
|
26022
|
+
},
|
|
26023
|
+
headers: {
|
|
26024
|
+
type: "object",
|
|
26025
|
+
additionalProperties: { type: "string" },
|
|
26026
|
+
description: "[http] HTTP headers. Values support CEL expressions."
|
|
26027
|
+
},
|
|
26028
|
+
body: {
|
|
26029
|
+
description: "[http] Request body. String or object. Supports CEL expressions.",
|
|
26030
|
+
oneOf: [
|
|
26031
|
+
{ type: "string" },
|
|
26032
|
+
{ type: "object" }
|
|
26033
|
+
]
|
|
26034
|
+
},
|
|
26035
|
+
path: {
|
|
26036
|
+
type: "string",
|
|
26037
|
+
description: "[workflow] Path to the sub-workflow YAML file."
|
|
26038
|
+
},
|
|
26039
|
+
server: {
|
|
26040
|
+
type: "string",
|
|
26041
|
+
description: "[mcp] MCP server identifier."
|
|
26042
|
+
},
|
|
26043
|
+
tool: {
|
|
26044
|
+
type: "string",
|
|
26045
|
+
description: "[mcp] MCP tool name to invoke."
|
|
26046
|
+
},
|
|
26047
|
+
event: {
|
|
26048
|
+
type: "string",
|
|
26049
|
+
description: "[emit] Event name to emit."
|
|
26050
|
+
},
|
|
26051
|
+
payload: {
|
|
26052
|
+
$ref: "#/$defs/payload",
|
|
26053
|
+
description: "[emit] Event payload. CEL expression or object with CEL expressions."
|
|
26054
|
+
},
|
|
26055
|
+
ack: {
|
|
26056
|
+
type: "boolean",
|
|
26057
|
+
description: "[emit] If true, wait for delivery acknowledgment. Default: false.",
|
|
26058
|
+
default: false
|
|
26059
|
+
}
|
|
26060
|
+
},
|
|
26061
|
+
additionalProperties: false
|
|
26062
|
+
},
|
|
26063
|
+
inlineParticipant: {
|
|
26064
|
+
type: "object",
|
|
26065
|
+
required: ["type"],
|
|
26066
|
+
description: "An inline participant definition in the flow. 'as' is optional — if omitted, the participant is anonymous and its output is only accessible via the implicit I/O chain.",
|
|
26067
|
+
properties: {
|
|
26068
|
+
as: {
|
|
26069
|
+
type: "string",
|
|
26070
|
+
description: "Optional name for inline participants. If provided, must be unique across all participant names. Enables output reference by name."
|
|
26071
|
+
},
|
|
26072
|
+
type: {
|
|
26073
|
+
type: "string",
|
|
26074
|
+
enum: ["exec", "http", "mcp", "workflow", "emit"],
|
|
26075
|
+
description: "Participant type."
|
|
26076
|
+
},
|
|
26077
|
+
when: {
|
|
26078
|
+
$ref: "#/$defs/celExpression",
|
|
26079
|
+
description: "Guard condition. If false, step is skipped."
|
|
26080
|
+
},
|
|
26081
|
+
timeout: {
|
|
26082
|
+
$ref: "#/$defs/duration"
|
|
26083
|
+
},
|
|
26084
|
+
onError: {
|
|
26085
|
+
$ref: "#/$defs/onError"
|
|
26086
|
+
},
|
|
26087
|
+
retry: {
|
|
26088
|
+
$ref: "#/$defs/retryConfig"
|
|
26089
|
+
},
|
|
26090
|
+
input: {
|
|
26091
|
+
$ref: "#/$defs/participantInput"
|
|
26092
|
+
},
|
|
26093
|
+
output: {
|
|
26094
|
+
$ref: "#/$defs/participantOutputSchema"
|
|
26095
|
+
},
|
|
26096
|
+
run: { type: "string" },
|
|
26097
|
+
cwd: { type: "string" },
|
|
26098
|
+
url: { type: "string" },
|
|
26099
|
+
method: { type: "string", enum: ["GET", "POST", "PUT", "PATCH", "DELETE"] },
|
|
26100
|
+
headers: { type: "object", additionalProperties: { type: "string" } },
|
|
26101
|
+
body: { oneOf: [{ type: "string" }, { type: "object" }] },
|
|
26102
|
+
path: { type: "string" },
|
|
26103
|
+
server: { type: "string" },
|
|
26104
|
+
tool: { type: "string" },
|
|
26105
|
+
event: { type: "string" },
|
|
26106
|
+
payload: { $ref: "#/$defs/payload" },
|
|
26107
|
+
ack: { type: "boolean" }
|
|
26108
|
+
},
|
|
26109
|
+
additionalProperties: false
|
|
26110
|
+
},
|
|
26111
|
+
flowSequence: {
|
|
26112
|
+
type: "array",
|
|
26113
|
+
description: "Ordered list of flow steps. Each step's output is implicitly chained as input to the next step.",
|
|
26114
|
+
minItems: 1,
|
|
26115
|
+
items: {
|
|
26116
|
+
$ref: "#/$defs/flowStep"
|
|
26117
|
+
}
|
|
26118
|
+
},
|
|
26119
|
+
flowStep: {
|
|
26120
|
+
description: "A single step in the flow: participant reference (string), control construct, inline participant (named or anonymous), or participant override.",
|
|
26121
|
+
oneOf: [
|
|
26122
|
+
{
|
|
26123
|
+
type: "string",
|
|
26124
|
+
description: "Simple participant reference by name."
|
|
26125
|
+
},
|
|
26126
|
+
{ $ref: "#/$defs/loopStep" },
|
|
26127
|
+
{ $ref: "#/$defs/parallelStep" },
|
|
26128
|
+
{ $ref: "#/$defs/ifStep" },
|
|
26129
|
+
{ $ref: "#/$defs/setStep" },
|
|
26130
|
+
{ $ref: "#/$defs/waitStep" },
|
|
26131
|
+
{ $ref: "#/$defs/inlineParticipant" },
|
|
26132
|
+
{ $ref: "#/$defs/participantOverrideStep" }
|
|
26133
|
+
]
|
|
26134
|
+
},
|
|
26135
|
+
loopStep: {
|
|
26136
|
+
type: "object",
|
|
26137
|
+
required: ["loop"],
|
|
26138
|
+
additionalProperties: false,
|
|
26139
|
+
properties: {
|
|
26140
|
+
loop: {
|
|
26141
|
+
type: "object",
|
|
26142
|
+
additionalProperties: false,
|
|
26143
|
+
required: ["steps"],
|
|
26144
|
+
properties: {
|
|
26145
|
+
as: {
|
|
26146
|
+
type: "string",
|
|
26147
|
+
description: "Renames the loop context variable. Access as <as>.index, <as>.iteration, etc. instead of loop.*"
|
|
26148
|
+
},
|
|
26149
|
+
until: {
|
|
26150
|
+
$ref: "#/$defs/celExpression",
|
|
26151
|
+
description: "CEL condition to break out of the loop."
|
|
26152
|
+
},
|
|
26153
|
+
max: {
|
|
26154
|
+
description: "Maximum iterations. Integer or CEL expression.",
|
|
26155
|
+
oneOf: [
|
|
26156
|
+
{ type: "integer", minimum: 1 },
|
|
26157
|
+
{ type: "string" }
|
|
26158
|
+
]
|
|
26159
|
+
},
|
|
26160
|
+
steps: {
|
|
26161
|
+
$ref: "#/$defs/flowSequence"
|
|
26162
|
+
}
|
|
26163
|
+
},
|
|
26164
|
+
anyOf: [
|
|
26165
|
+
{ required: ["until"] },
|
|
26166
|
+
{ required: ["max"] }
|
|
26167
|
+
]
|
|
26168
|
+
}
|
|
26169
|
+
}
|
|
26170
|
+
},
|
|
26171
|
+
parallelStep: {
|
|
26172
|
+
type: "object",
|
|
26173
|
+
required: ["parallel"],
|
|
26174
|
+
additionalProperties: false,
|
|
26175
|
+
properties: {
|
|
26176
|
+
parallel: {
|
|
26177
|
+
$ref: "#/$defs/flowSequence",
|
|
26178
|
+
description: "Steps to run concurrently. The chained output after a parallel block is an array of all branch outputs in declaration order."
|
|
26179
|
+
}
|
|
26180
|
+
}
|
|
26181
|
+
},
|
|
26182
|
+
ifStep: {
|
|
26183
|
+
type: "object",
|
|
26184
|
+
required: ["if"],
|
|
26185
|
+
additionalProperties: false,
|
|
26186
|
+
properties: {
|
|
26187
|
+
if: {
|
|
26188
|
+
type: "object",
|
|
26189
|
+
required: ["condition", "then"],
|
|
26190
|
+
additionalProperties: false,
|
|
26191
|
+
properties: {
|
|
26192
|
+
condition: {
|
|
26193
|
+
$ref: "#/$defs/celExpression",
|
|
26194
|
+
description: "CEL expression that determines which branch to take."
|
|
26195
|
+
},
|
|
26196
|
+
then: {
|
|
26197
|
+
$ref: "#/$defs/flowSequence"
|
|
26198
|
+
},
|
|
26199
|
+
else: {
|
|
26200
|
+
$ref: "#/$defs/flowSequence"
|
|
26201
|
+
}
|
|
26202
|
+
}
|
|
26203
|
+
}
|
|
26204
|
+
}
|
|
26205
|
+
},
|
|
26206
|
+
setStep: {
|
|
26207
|
+
type: "object",
|
|
26208
|
+
required: ["set"],
|
|
26209
|
+
additionalProperties: false,
|
|
26210
|
+
properties: {
|
|
26211
|
+
set: {
|
|
26212
|
+
type: "object",
|
|
26213
|
+
description: "Writes values into execution.context. Each key becomes execution.context.<key>. Values are CEL expressions.",
|
|
26214
|
+
minProperties: 1,
|
|
26215
|
+
additionalProperties: {
|
|
26216
|
+
$ref: "#/$defs/celExpression"
|
|
26217
|
+
},
|
|
26218
|
+
not: {
|
|
26219
|
+
anyOf: [
|
|
26220
|
+
{ required: ["workflow"] },
|
|
26221
|
+
{ required: ["execution"] },
|
|
26222
|
+
{ required: ["input"] },
|
|
26223
|
+
{ required: ["output"] },
|
|
26224
|
+
{ required: ["env"] },
|
|
26225
|
+
{ required: ["loop"] },
|
|
26226
|
+
{ required: ["event"] }
|
|
26227
|
+
]
|
|
26228
|
+
}
|
|
26229
|
+
}
|
|
26230
|
+
}
|
|
26231
|
+
},
|
|
26232
|
+
waitStep: {
|
|
26233
|
+
type: "object",
|
|
26234
|
+
required: ["wait"],
|
|
26235
|
+
additionalProperties: false,
|
|
26236
|
+
properties: {
|
|
26237
|
+
wait: {
|
|
26238
|
+
type: "object",
|
|
26239
|
+
additionalProperties: false,
|
|
26240
|
+
properties: {
|
|
26241
|
+
event: {
|
|
26242
|
+
type: "string",
|
|
26243
|
+
description: "Event name to wait for (event mode)."
|
|
26244
|
+
},
|
|
26245
|
+
match: {
|
|
26246
|
+
$ref: "#/$defs/celExpression",
|
|
26247
|
+
description: "CEL condition to match against event payload. 'event' variable contains the payload."
|
|
26248
|
+
},
|
|
26249
|
+
until: {
|
|
26250
|
+
$ref: "#/$defs/celExpression",
|
|
26251
|
+
description: "CEL condition to wait for (polling mode)."
|
|
26252
|
+
},
|
|
26253
|
+
poll: {
|
|
26254
|
+
$ref: "#/$defs/duration",
|
|
26255
|
+
description: "Polling interval for 'until' condition. Default: runtime decides."
|
|
26256
|
+
},
|
|
26257
|
+
timeout: {
|
|
26258
|
+
$ref: "#/$defs/duration",
|
|
26259
|
+
description: "Maximum wait time."
|
|
26260
|
+
},
|
|
26261
|
+
onTimeout: {
|
|
26262
|
+
$ref: "#/$defs/onTimeout",
|
|
26263
|
+
description: "Strategy when timeout is reached: 'fail' (default), 'skip', or participant name."
|
|
26264
|
+
}
|
|
26265
|
+
}
|
|
26266
|
+
}
|
|
26267
|
+
}
|
|
26268
|
+
},
|
|
26269
|
+
participantOverrideStep: {
|
|
26270
|
+
type: "object",
|
|
26271
|
+
description: "A participant reference with flow-level overrides (timeout, onError, when, input, workflow, etc.).",
|
|
26272
|
+
minProperties: 1,
|
|
26273
|
+
maxProperties: 1,
|
|
26274
|
+
not: {
|
|
26275
|
+
anyOf: [
|
|
26276
|
+
{ required: ["loop"] },
|
|
26277
|
+
{ required: ["parallel"] },
|
|
26278
|
+
{ required: ["if"] },
|
|
26279
|
+
{ required: ["wait"] },
|
|
26280
|
+
{ required: ["set"] },
|
|
26281
|
+
{ required: ["type"] }
|
|
26282
|
+
]
|
|
26283
|
+
},
|
|
26284
|
+
additionalProperties: {
|
|
26285
|
+
type: "object",
|
|
26286
|
+
properties: {
|
|
26287
|
+
when: {
|
|
26288
|
+
$ref: "#/$defs/celExpression",
|
|
26289
|
+
description: "Guard condition. If false, step is skipped."
|
|
26290
|
+
},
|
|
26291
|
+
timeout: {
|
|
26292
|
+
$ref: "#/$defs/duration"
|
|
26293
|
+
},
|
|
26294
|
+
onError: {
|
|
26295
|
+
$ref: "#/$defs/onError"
|
|
26296
|
+
},
|
|
26297
|
+
retry: {
|
|
26298
|
+
$ref: "#/$defs/retryConfig"
|
|
26299
|
+
},
|
|
26300
|
+
input: {
|
|
26301
|
+
$ref: "#/$defs/participantInput"
|
|
26302
|
+
},
|
|
26303
|
+
workflow: {
|
|
26304
|
+
type: "string",
|
|
26305
|
+
description: "Inline sub-workflow path (alternative to defining as participant)."
|
|
26306
|
+
}
|
|
26307
|
+
},
|
|
26308
|
+
additionalProperties: false
|
|
26309
|
+
}
|
|
26310
|
+
},
|
|
26311
|
+
workflowOutput: {
|
|
26312
|
+
description: "Workflow output. Accessed in CEL as workflow.output. String (single CEL expression), object (structured mapping), or object with schema+map.",
|
|
26313
|
+
oneOf: [
|
|
26314
|
+
{
|
|
26315
|
+
type: "string",
|
|
26316
|
+
description: "Single CEL expression mapping."
|
|
26317
|
+
},
|
|
26318
|
+
{
|
|
26319
|
+
type: "object",
|
|
26320
|
+
description: "Structured output mapping (key → CEL expression) or schema+map.",
|
|
26321
|
+
properties: {
|
|
26322
|
+
schema: {
|
|
26323
|
+
type: "object",
|
|
26324
|
+
additionalProperties: {
|
|
26325
|
+
$ref: "#/$defs/inputField"
|
|
26326
|
+
}
|
|
26327
|
+
},
|
|
26328
|
+
map: {
|
|
26329
|
+
type: "object",
|
|
26330
|
+
additionalProperties: {
|
|
26331
|
+
type: "string"
|
|
26332
|
+
}
|
|
26333
|
+
}
|
|
26334
|
+
},
|
|
26335
|
+
additionalProperties: {
|
|
26336
|
+
type: "string"
|
|
26337
|
+
}
|
|
26338
|
+
}
|
|
26339
|
+
]
|
|
26340
|
+
}
|
|
26341
|
+
}
|
|
26342
|
+
};
|
|
26343
|
+
});
|
|
25799
26344
|
function validateSchema(workflow) {
|
|
25800
26345
|
const valid = validate(workflow);
|
|
25801
26346
|
if (valid) {
|
|
@@ -25809,15 +26354,14 @@ function validateSchema(workflow) {
|
|
|
25809
26354
|
}
|
|
25810
26355
|
var import__2020;
|
|
25811
26356
|
var import_ajv_formats;
|
|
25812
|
-
var rawSchema;
|
|
25813
26357
|
var schema;
|
|
25814
26358
|
var ajv;
|
|
25815
26359
|
var validate;
|
|
25816
26360
|
var init_schema = __esm2(() => {
|
|
26361
|
+
init_duckflux_schema();
|
|
25817
26362
|
import__2020 = __toESM(require_2020(), 1);
|
|
25818
26363
|
import_ajv_formats = __toESM(require_dist2(), 1);
|
|
25819
|
-
|
|
25820
|
-
schema = JSON.parse(rawSchema);
|
|
26364
|
+
schema = { ...duckflux_schema_default };
|
|
25821
26365
|
delete schema.$schema;
|
|
25822
26366
|
ajv = new import__2020.default({ allErrors: true, strict: false });
|
|
25823
26367
|
import_ajv_formats.default(ajv);
|
|
@@ -26219,6 +26763,234 @@ var init_validate = __esm2(() => {
|
|
|
26219
26763
|
RESERVED_NAMES = new Set(["workflow", "execution", "input", "output", "env", "loop", "event"]);
|
|
26220
26764
|
BUILTIN_ONERROR = new Set(["fail", "skip", "retry"]);
|
|
26221
26765
|
});
|
|
26766
|
+
var exports_json = {};
|
|
26767
|
+
__export2(exports_json, {
|
|
26768
|
+
JsonTraceWriter: () => JsonTraceWriter
|
|
26769
|
+
});
|
|
26770
|
+
|
|
26771
|
+
class JsonTraceWriter {
|
|
26772
|
+
dir;
|
|
26773
|
+
filePath = "";
|
|
26774
|
+
trace = {
|
|
26775
|
+
execution: {
|
|
26776
|
+
id: "",
|
|
26777
|
+
startedAt: "",
|
|
26778
|
+
finishedAt: "",
|
|
26779
|
+
duration: 0,
|
|
26780
|
+
status: "running",
|
|
26781
|
+
inputs: null,
|
|
26782
|
+
output: null
|
|
26783
|
+
},
|
|
26784
|
+
steps: []
|
|
26785
|
+
};
|
|
26786
|
+
constructor(dir) {
|
|
26787
|
+
this.dir = dir;
|
|
26788
|
+
}
|
|
26789
|
+
async open(meta) {
|
|
26790
|
+
this.filePath = join(this.dir, `${meta.id}.json`);
|
|
26791
|
+
this.trace = {
|
|
26792
|
+
execution: {
|
|
26793
|
+
id: meta.id,
|
|
26794
|
+
workflowId: meta.workflowId,
|
|
26795
|
+
workflowName: meta.workflowName,
|
|
26796
|
+
workflowVersion: meta.workflowVersion,
|
|
26797
|
+
startedAt: meta.startedAt,
|
|
26798
|
+
finishedAt: "",
|
|
26799
|
+
duration: 0,
|
|
26800
|
+
status: "running",
|
|
26801
|
+
inputs: meta.inputs,
|
|
26802
|
+
output: null
|
|
26803
|
+
},
|
|
26804
|
+
steps: []
|
|
26805
|
+
};
|
|
26806
|
+
await this.flush();
|
|
26807
|
+
}
|
|
26808
|
+
writeStep(step) {
|
|
26809
|
+
this.trace.steps.push(step);
|
|
26810
|
+
this.flushSync();
|
|
26811
|
+
}
|
|
26812
|
+
async finalize(meta) {
|
|
26813
|
+
this.trace.execution.status = meta.status;
|
|
26814
|
+
this.trace.execution.output = meta.output;
|
|
26815
|
+
this.trace.execution.finishedAt = meta.finishedAt;
|
|
26816
|
+
this.trace.execution.duration = meta.duration;
|
|
26817
|
+
await this.flush();
|
|
26818
|
+
}
|
|
26819
|
+
flushSync() {
|
|
26820
|
+
this.flush().catch(() => {});
|
|
26821
|
+
}
|
|
26822
|
+
async flush() {
|
|
26823
|
+
if (!this.filePath)
|
|
26824
|
+
return;
|
|
26825
|
+
await writeFile(this.filePath, JSON.stringify(this.trace, null, 2), "utf-8");
|
|
26826
|
+
}
|
|
26827
|
+
}
|
|
26828
|
+
var exports_txt = {};
|
|
26829
|
+
__export2(exports_txt, {
|
|
26830
|
+
TxtTraceWriter: () => TxtTraceWriter
|
|
26831
|
+
});
|
|
26832
|
+
function serializeValue(value) {
|
|
26833
|
+
if (value === undefined || value === null)
|
|
26834
|
+
return "none";
|
|
26835
|
+
if (typeof value === "string")
|
|
26836
|
+
return value;
|
|
26837
|
+
return JSON.stringify(value, null, 2);
|
|
26838
|
+
}
|
|
26839
|
+
function formatStep(step) {
|
|
26840
|
+
const lines = [
|
|
26841
|
+
`## [${step.seq}] ${step.name} (${step.type})`,
|
|
26842
|
+
`startedAt: ${step.startedAt}`
|
|
26843
|
+
];
|
|
26844
|
+
if (step.finishedAt)
|
|
26845
|
+
lines.push(`finishedAt: ${step.finishedAt}`);
|
|
26846
|
+
if (step.duration !== undefined)
|
|
26847
|
+
lines.push(`duration: ${step.duration}ms`);
|
|
26848
|
+
lines.push(`status: ${step.status}`);
|
|
26849
|
+
if (step.loopIndex !== undefined)
|
|
26850
|
+
lines.push(`loopIndex: ${step.loopIndex}`);
|
|
26851
|
+
if (step.retries !== undefined && step.retries > 0)
|
|
26852
|
+
lines.push(`retries: ${step.retries}`);
|
|
26853
|
+
lines.push(`input: ${serializeValue(step.input)}`);
|
|
26854
|
+
lines.push(`output: ${serializeValue(step.output)}`);
|
|
26855
|
+
if (step.error)
|
|
26856
|
+
lines.push(`error: ${step.error}`);
|
|
26857
|
+
lines.push("");
|
|
26858
|
+
return lines.join(`
|
|
26859
|
+
`);
|
|
26860
|
+
}
|
|
26861
|
+
|
|
26862
|
+
class TxtTraceWriter {
|
|
26863
|
+
dir;
|
|
26864
|
+
filePath = "";
|
|
26865
|
+
constructor(dir) {
|
|
26866
|
+
this.dir = dir;
|
|
26867
|
+
}
|
|
26868
|
+
async open(meta) {
|
|
26869
|
+
this.filePath = join2(this.dir, `${meta.id}.txt`);
|
|
26870
|
+
const versionStr = meta.workflowVersion !== undefined ? ` (v${meta.workflowVersion})` : "";
|
|
26871
|
+
const workflowLabel = meta.workflowName ?? meta.workflowId ?? "unnamed";
|
|
26872
|
+
const header = [
|
|
26873
|
+
"# execution",
|
|
26874
|
+
`id: ${meta.id}`,
|
|
26875
|
+
`workflow: ${workflowLabel}${versionStr}`,
|
|
26876
|
+
`startedAt: ${meta.startedAt}`,
|
|
26877
|
+
"status: running",
|
|
26878
|
+
"",
|
|
26879
|
+
"# inputs",
|
|
26880
|
+
serializeValue(meta.inputs),
|
|
26881
|
+
"",
|
|
26882
|
+
"# steps",
|
|
26883
|
+
""
|
|
26884
|
+
].join(`
|
|
26885
|
+
`);
|
|
26886
|
+
await writeFile2(this.filePath, header, "utf-8");
|
|
26887
|
+
}
|
|
26888
|
+
async writeStep(step) {
|
|
26889
|
+
if (!this.filePath)
|
|
26890
|
+
return;
|
|
26891
|
+
await appendFile(this.filePath, formatStep(step), "utf-8");
|
|
26892
|
+
}
|
|
26893
|
+
async finalize(meta) {
|
|
26894
|
+
if (!this.filePath)
|
|
26895
|
+
return;
|
|
26896
|
+
const outputSection = [
|
|
26897
|
+
"# output",
|
|
26898
|
+
serializeValue(meta.output),
|
|
26899
|
+
""
|
|
26900
|
+
].join(`
|
|
26901
|
+
`);
|
|
26902
|
+
await appendFile(this.filePath, outputSection, "utf-8");
|
|
26903
|
+
const content = await readFile2(this.filePath, "utf-8");
|
|
26904
|
+
const updated = content.replace(/^status: running$/m, `status: ${meta.status}
|
|
26905
|
+
finishedAt: ${meta.finishedAt}
|
|
26906
|
+
duration: ${meta.duration}ms`);
|
|
26907
|
+
await writeFile2(this.filePath, updated, "utf-8");
|
|
26908
|
+
}
|
|
26909
|
+
}
|
|
26910
|
+
var exports_sqlite = {};
|
|
26911
|
+
__export2(exports_sqlite, {
|
|
26912
|
+
SqliteTraceWriter: () => SqliteTraceWriter
|
|
26913
|
+
});
|
|
26914
|
+
function toJson(value) {
|
|
26915
|
+
if (value === undefined || value === null)
|
|
26916
|
+
return null;
|
|
26917
|
+
if (typeof value === "string")
|
|
26918
|
+
return value;
|
|
26919
|
+
return JSON.stringify(value);
|
|
26920
|
+
}
|
|
26921
|
+
|
|
26922
|
+
class SqliteTraceWriter {
|
|
26923
|
+
dir;
|
|
26924
|
+
db = null;
|
|
26925
|
+
executionId = "";
|
|
26926
|
+
constructor(dir) {
|
|
26927
|
+
this.dir = dir;
|
|
26928
|
+
}
|
|
26929
|
+
async open(meta) {
|
|
26930
|
+
this.executionId = meta.id;
|
|
26931
|
+
const filePath = join3(this.dir, `${meta.id}.sqlite`);
|
|
26932
|
+
const { Database } = await import("bun:sqlite");
|
|
26933
|
+
this.db = new Database(filePath);
|
|
26934
|
+
this.db.exec(`
|
|
26935
|
+
CREATE TABLE IF NOT EXISTS executions (
|
|
26936
|
+
id TEXT PRIMARY KEY,
|
|
26937
|
+
workflow_id TEXT,
|
|
26938
|
+
workflow_name TEXT,
|
|
26939
|
+
workflow_version TEXT,
|
|
26940
|
+
started_at TEXT NOT NULL,
|
|
26941
|
+
finished_at TEXT,
|
|
26942
|
+
duration_ms INTEGER,
|
|
26943
|
+
status TEXT NOT NULL,
|
|
26944
|
+
inputs TEXT,
|
|
26945
|
+
output TEXT
|
|
26946
|
+
);
|
|
26947
|
+
|
|
26948
|
+
CREATE TABLE IF NOT EXISTS steps (
|
|
26949
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
26950
|
+
execution_id TEXT NOT NULL REFERENCES executions(id),
|
|
26951
|
+
seq INTEGER NOT NULL,
|
|
26952
|
+
name TEXT NOT NULL,
|
|
26953
|
+
type TEXT NOT NULL,
|
|
26954
|
+
started_at TEXT,
|
|
26955
|
+
finished_at TEXT,
|
|
26956
|
+
duration_ms INTEGER,
|
|
26957
|
+
status TEXT NOT NULL,
|
|
26958
|
+
input TEXT,
|
|
26959
|
+
output TEXT,
|
|
26960
|
+
error TEXT,
|
|
26961
|
+
retries INTEGER,
|
|
26962
|
+
loop_index INTEGER
|
|
26963
|
+
);
|
|
26964
|
+
`);
|
|
26965
|
+
const insert = this.db.prepare(`
|
|
26966
|
+
INSERT INTO executions (id, workflow_id, workflow_name, workflow_version, started_at, status, inputs)
|
|
26967
|
+
VALUES (?, ?, ?, ?, ?, 'running', ?)
|
|
26968
|
+
`);
|
|
26969
|
+
insert.run(meta.id, meta.workflowId ?? null, meta.workflowName ?? null, meta.workflowVersion !== undefined ? String(meta.workflowVersion) : null, meta.startedAt, toJson(meta.inputs));
|
|
26970
|
+
}
|
|
26971
|
+
writeStep(step) {
|
|
26972
|
+
if (!this.db)
|
|
26973
|
+
return;
|
|
26974
|
+
const insert = this.db.prepare(`
|
|
26975
|
+
INSERT INTO steps
|
|
26976
|
+
(execution_id, seq, name, type, started_at, finished_at, duration_ms, status, input, output, error, retries, loop_index)
|
|
26977
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
26978
|
+
`);
|
|
26979
|
+
insert.run(this.executionId, step.seq, step.name, step.type, step.startedAt ?? null, step.finishedAt ?? null, step.duration ?? null, step.status, toJson(step.input), toJson(step.output), step.error ?? null, step.retries ?? null, step.loopIndex ?? null);
|
|
26980
|
+
}
|
|
26981
|
+
async finalize(meta) {
|
|
26982
|
+
if (!this.db)
|
|
26983
|
+
return;
|
|
26984
|
+
const update = this.db.prepare(`
|
|
26985
|
+
UPDATE executions
|
|
26986
|
+
SET status = ?, output = ?, finished_at = ?, duration_ms = ?
|
|
26987
|
+
WHERE id = ?
|
|
26988
|
+
`);
|
|
26989
|
+
update.run(meta.status, toJson(meta.output), meta.finishedAt, Math.round(meta.duration), this.executionId);
|
|
26990
|
+
this.db.close();
|
|
26991
|
+
this.db = null;
|
|
26992
|
+
}
|
|
26993
|
+
}
|
|
26222
26994
|
function sleep(ms) {
|
|
26223
26995
|
return new Promise((resolve22) => setTimeout(resolve22, ms));
|
|
26224
26996
|
}
|
|
@@ -26345,13 +27117,13 @@ function isMap3(value) {
|
|
|
26345
27117
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26346
27118
|
}
|
|
26347
27119
|
function mapToEnvVars(input) {
|
|
26348
|
-
const
|
|
27120
|
+
const env = {};
|
|
26349
27121
|
for (const [key, value] of Object.entries(input)) {
|
|
26350
|
-
|
|
27122
|
+
env[key] = typeof value === "string" ? value : String(value);
|
|
26351
27123
|
}
|
|
26352
|
-
return
|
|
27124
|
+
return env;
|
|
26353
27125
|
}
|
|
26354
|
-
async function executeExec(participant, input,
|
|
27126
|
+
async function executeExec(participant, input, env = {}, signal) {
|
|
26355
27127
|
const command = participant.run ?? "";
|
|
26356
27128
|
const participantEnv = participant.env ?? {};
|
|
26357
27129
|
const cwd = participant.cwd ?? process.cwd();
|
|
@@ -26362,7 +27134,7 @@ async function executeExec(participant, input, env2 = {}, signal) {
|
|
|
26362
27134
|
return new Promise((resolve22) => {
|
|
26363
27135
|
try {
|
|
26364
27136
|
const proc = spawn("sh", ["-c", command], {
|
|
26365
|
-
env: { ...process.env, ...
|
|
27137
|
+
env: { ...process.env, ...env, ...participantEnv, ...inputEnvVars },
|
|
26366
27138
|
cwd,
|
|
26367
27139
|
stdio: ["pipe", "pipe", "pipe"]
|
|
26368
27140
|
});
|
|
@@ -26510,7 +27282,7 @@ async function executeHttp(participant, input) {
|
|
|
26510
27282
|
};
|
|
26511
27283
|
}
|
|
26512
27284
|
async function executeMcp(participant, _input) {
|
|
26513
|
-
throw new Error(`mcp participant is not yet implemented (server: ${participant.server ?? "unspecified"}, tool: ${participant.tool ?? "unspecified"}).
|
|
27285
|
+
throw new Error(`mcp participant is not yet implemented (server: ${participant.server ?? "unspecified"}, tool: ${participant.tool ?? "unspecified"}). Use onError to handle this gracefully.`);
|
|
26514
27286
|
}
|
|
26515
27287
|
function toWorkflowInputs(input) {
|
|
26516
27288
|
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
@@ -26555,12 +27327,12 @@ var init_workflow = __esm2(() => {
|
|
|
26555
27327
|
init_schema();
|
|
26556
27328
|
init_validate();
|
|
26557
27329
|
});
|
|
26558
|
-
async function executeParticipant(participant, input,
|
|
27330
|
+
async function executeParticipant(participant, input, env = {}, basePath, engineExecutor, hub, celContext, ancestorPaths) {
|
|
26559
27331
|
const executor = executors[participant.type];
|
|
26560
27332
|
if (!executor) {
|
|
26561
27333
|
throw new Error(`participant type '${participant.type}' is not yet implemented`);
|
|
26562
27334
|
}
|
|
26563
|
-
return executor(participant, input,
|
|
27335
|
+
return executor(participant, input, env, basePath, engineExecutor, hub, celContext, ancestorPaths);
|
|
26564
27336
|
}
|
|
26565
27337
|
var executors;
|
|
26566
27338
|
var init_participant = __esm2(() => {
|
|
@@ -26568,7 +27340,7 @@ var init_participant = __esm2(() => {
|
|
|
26568
27340
|
init_exec();
|
|
26569
27341
|
init_workflow();
|
|
26570
27342
|
executors = {
|
|
26571
|
-
exec: async (participant, input,
|
|
27343
|
+
exec: async (participant, input, env) => executeExec(participant, input, env),
|
|
26572
27344
|
http: async (participant, input) => executeHttp(participant, input),
|
|
26573
27345
|
workflow: async (participant, input, _env, basePath, engineExecutor, _hub, _celContext, ancestorPaths) => {
|
|
26574
27346
|
if (!basePath) {
|
|
@@ -26796,6 +27568,10 @@ async function executeStep(workflow, state, step, basePath = process.cwd(), engi
|
|
|
26796
27568
|
output: "",
|
|
26797
27569
|
duration: 0
|
|
26798
27570
|
});
|
|
27571
|
+
const loopIndex2 = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
27572
|
+
const skippedSeq = state.tracer?.startStep(stepName, participant.type, undefined, loopIndex2);
|
|
27573
|
+
if (skippedSeq !== undefined)
|
|
27574
|
+
state.tracer?.endStep(skippedSeq, "skipped");
|
|
26799
27575
|
}
|
|
26800
27576
|
return chain;
|
|
26801
27577
|
}
|
|
@@ -26804,6 +27580,8 @@ async function executeStep(workflow, state, step, basePath = process.cwd(), engi
|
|
|
26804
27580
|
const overrideInput = override?.input !== undefined ? resolveParticipantInput(override.input, state) : undefined;
|
|
26805
27581
|
const mergedWithBase = mergeChainedInput(chain, baseInput);
|
|
26806
27582
|
const mergedInput = mergeChainedInput(mergedWithBase, overrideInput);
|
|
27583
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
27584
|
+
const traceSeq = state.tracer?.startStep(stepName ?? "<anonymous>", participant.type, mergedInput, loopIndex);
|
|
26807
27585
|
state.currentInput = mergedInput;
|
|
26808
27586
|
const strategy = resolveErrorStrategy(override ?? null, participant, workflow.defaults ?? null);
|
|
26809
27587
|
const timeoutMs = resolveTimeout(override ?? null, participant, workflow.defaults ?? null);
|
|
@@ -26881,6 +27659,8 @@ async function executeStep(workflow, state, step, basePath = process.cwd(), engi
|
|
|
26881
27659
|
}
|
|
26882
27660
|
const outputValue = result.parsedOutput ?? result.output;
|
|
26883
27661
|
state.currentOutput = outputValue;
|
|
27662
|
+
if (traceSeq !== undefined)
|
|
27663
|
+
state.tracer?.endStep(traceSeq, result.status, outputValue, undefined, retries);
|
|
26884
27664
|
return outputValue;
|
|
26885
27665
|
} catch (error) {
|
|
26886
27666
|
const message = String(error?.message ?? error);
|
|
@@ -26906,6 +27686,8 @@ async function executeStep(workflow, state, step, basePath = process.cwd(), engi
|
|
|
26906
27686
|
if (stepName) {
|
|
26907
27687
|
state.setResult(stepName, skipResult);
|
|
26908
27688
|
}
|
|
27689
|
+
if (traceSeq !== undefined)
|
|
27690
|
+
state.tracer?.endStep(traceSeq, "skipped", undefined, message);
|
|
26909
27691
|
return chain;
|
|
26910
27692
|
}
|
|
26911
27693
|
if (strategy !== "fail" && strategy !== "retry") {
|
|
@@ -26924,6 +27706,8 @@ async function executeStep(workflow, state, step, basePath = process.cwd(), engi
|
|
|
26924
27706
|
...httpMeta
|
|
26925
27707
|
});
|
|
26926
27708
|
}
|
|
27709
|
+
if (traceSeq !== undefined)
|
|
27710
|
+
state.tracer?.endStep(traceSeq, "failure", undefined, message);
|
|
26927
27711
|
const fallbackResult = await executeStep(workflow, state, fallbackName, basePath, engineExecutor, [...fallbackStack, stepName ?? "<anonymous>"], chain, hub);
|
|
26928
27712
|
return fallbackResult;
|
|
26929
27713
|
}
|
|
@@ -26938,6 +27722,8 @@ async function executeStep(workflow, state, step, basePath = process.cwd(), engi
|
|
|
26938
27722
|
...httpMeta
|
|
26939
27723
|
});
|
|
26940
27724
|
}
|
|
27725
|
+
if (traceSeq !== undefined)
|
|
27726
|
+
state.tracer?.endStep(traceSeq, "failure", undefined, message);
|
|
26941
27727
|
throw error;
|
|
26942
27728
|
}
|
|
26943
27729
|
}
|
|
@@ -26960,7 +27746,7 @@ __export2(exports_wait, {
|
|
|
26960
27746
|
executeWait: () => executeWait
|
|
26961
27747
|
});
|
|
26962
27748
|
function sleep2(ms) {
|
|
26963
|
-
return new Promise((
|
|
27749
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
26964
27750
|
}
|
|
26965
27751
|
async function executeWait(state, waitDef, chain, hub, signal) {
|
|
26966
27752
|
const timeoutMs = waitDef.timeout ? parseDuration(waitDef.timeout) : undefined;
|
|
@@ -27046,21 +27832,38 @@ async function executeControlStep(workflow, state, step, basePath = process.cwd(
|
|
|
27046
27832
|
}
|
|
27047
27833
|
const obj = step;
|
|
27048
27834
|
if ("wait" in obj && Object.keys(obj).length === 1) {
|
|
27049
|
-
const
|
|
27050
|
-
|
|
27835
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
27836
|
+
const traceSeq = state.tracer?.startStep("wait", "wait", undefined, loopIndex);
|
|
27837
|
+
try {
|
|
27838
|
+
const { executeWait: executeWait2 } = await Promise.resolve().then(() => (init_wait(), exports_wait));
|
|
27839
|
+
const result = await executeWait2(state, obj.wait, chain, hub, signal);
|
|
27840
|
+
if (traceSeq !== undefined)
|
|
27841
|
+
state.tracer?.endStep(traceSeq, "success", result);
|
|
27842
|
+
return result;
|
|
27843
|
+
} catch (err) {
|
|
27844
|
+
if (traceSeq !== undefined)
|
|
27845
|
+
state.tracer?.endStep(traceSeq, "failure", undefined, String(err?.message ?? err));
|
|
27846
|
+
throw err;
|
|
27847
|
+
}
|
|
27051
27848
|
}
|
|
27052
27849
|
if ("set" in obj && Object.keys(obj).length === 1) {
|
|
27053
27850
|
const setDef = obj.set;
|
|
27054
27851
|
const ctx = state.toCelContext();
|
|
27852
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
27853
|
+
const traceSeq = state.tracer?.startStep("set", "set", setDef, loopIndex);
|
|
27055
27854
|
if (!state.executionMeta.context) {
|
|
27056
27855
|
state.executionMeta.context = {};
|
|
27057
27856
|
}
|
|
27058
27857
|
for (const [key, expr] of Object.entries(setDef)) {
|
|
27059
27858
|
if (RESERVED_SET_KEYS.has(key)) {
|
|
27859
|
+
if (traceSeq !== undefined)
|
|
27860
|
+
state.tracer?.endStep(traceSeq, "failure", undefined, `set key '${key}' uses a reserved name`);
|
|
27060
27861
|
throw new Error(`set key '${key}' uses a reserved name`);
|
|
27061
27862
|
}
|
|
27062
27863
|
state.executionMeta.context[key] = evaluateCel(expr, ctx);
|
|
27063
27864
|
}
|
|
27865
|
+
if (traceSeq !== undefined)
|
|
27866
|
+
state.tracer?.endStep(traceSeq, "success", state.executionMeta.context);
|
|
27064
27867
|
return chain;
|
|
27065
27868
|
}
|
|
27066
27869
|
if ("loop" in obj && Object.keys(obj).length === 1) {
|
|
@@ -27077,6 +27880,8 @@ async function executeControlStep(workflow, state, step, basePath = process.cwd(
|
|
|
27077
27880
|
maxIterations = loopDef.max ?? Number.POSITIVE_INFINITY;
|
|
27078
27881
|
}
|
|
27079
27882
|
const hasMax = loopDef.max !== undefined;
|
|
27883
|
+
const outerLoopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
27884
|
+
const loopTraceSeq = state.tracer?.startStep(loopAs ?? "loop", "loop", undefined, outerLoopIndex);
|
|
27080
27885
|
state.pushLoop(loopAs);
|
|
27081
27886
|
let loopChain = chain;
|
|
27082
27887
|
try {
|
|
@@ -27100,6 +27905,12 @@ async function executeControlStep(workflow, state, step, basePath = process.cwd(
|
|
|
27100
27905
|
iterations += 1;
|
|
27101
27906
|
state.incrementLoop();
|
|
27102
27907
|
}
|
|
27908
|
+
if (loopTraceSeq !== undefined)
|
|
27909
|
+
state.tracer?.endStep(loopTraceSeq, "success", loopChain);
|
|
27910
|
+
} catch (err) {
|
|
27911
|
+
if (loopTraceSeq !== undefined)
|
|
27912
|
+
state.tracer?.endStep(loopTraceSeq, "failure", undefined, String(err?.message ?? err));
|
|
27913
|
+
throw err;
|
|
27103
27914
|
} finally {
|
|
27104
27915
|
state.popLoop();
|
|
27105
27916
|
}
|
|
@@ -27108,29 +27919,54 @@ async function executeControlStep(workflow, state, step, basePath = process.cwd(
|
|
|
27108
27919
|
if ("parallel" in obj && Object.keys(obj).length === 1) {
|
|
27109
27920
|
const parallelSteps = obj.parallel;
|
|
27110
27921
|
const controller = new AbortController;
|
|
27922
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
27923
|
+
const parallelTraceSeq = state.tracer?.startStep("parallel", "parallel", undefined, loopIndex);
|
|
27111
27924
|
const branchSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
|
|
27112
|
-
|
|
27113
|
-
|
|
27114
|
-
|
|
27115
|
-
|
|
27116
|
-
|
|
27117
|
-
|
|
27118
|
-
|
|
27119
|
-
|
|
27120
|
-
|
|
27925
|
+
try {
|
|
27926
|
+
const results = await Promise.all(parallelSteps.map(async (parallelStep) => {
|
|
27927
|
+
try {
|
|
27928
|
+
return await executeControlStep(workflow, state, parallelStep, basePath, engineExecutor, chain, hub, branchSignal);
|
|
27929
|
+
} catch (error) {
|
|
27930
|
+
controller.abort();
|
|
27931
|
+
throw error;
|
|
27932
|
+
}
|
|
27933
|
+
}));
|
|
27934
|
+
if (parallelTraceSeq !== undefined)
|
|
27935
|
+
state.tracer?.endStep(parallelTraceSeq, "success", results);
|
|
27936
|
+
return results;
|
|
27937
|
+
} catch (err) {
|
|
27938
|
+
if (parallelTraceSeq !== undefined)
|
|
27939
|
+
state.tracer?.endStep(parallelTraceSeq, "failure", undefined, String(err?.message ?? err));
|
|
27940
|
+
throw err;
|
|
27941
|
+
}
|
|
27121
27942
|
}
|
|
27122
27943
|
if ("if" in obj && Object.keys(obj).length === 1) {
|
|
27123
27944
|
const ifDef = obj.if;
|
|
27124
27945
|
const condition = evaluateCel(ifDef.condition, state.toCelContext());
|
|
27946
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
27947
|
+
const ifTraceSeq = state.tracer?.startStep("if", "if", { condition: ifDef.condition }, loopIndex);
|
|
27125
27948
|
if (typeof condition !== "boolean") {
|
|
27949
|
+
if (ifTraceSeq !== undefined)
|
|
27950
|
+
state.tracer?.endStep(ifTraceSeq, "failure", undefined, `if.condition must evaluate to boolean, got ${typeof condition}`);
|
|
27126
27951
|
throw new Error(`if.condition must evaluate to boolean, got ${typeof condition}`);
|
|
27127
27952
|
}
|
|
27128
|
-
|
|
27129
|
-
|
|
27130
|
-
|
|
27131
|
-
|
|
27953
|
+
try {
|
|
27954
|
+
let result;
|
|
27955
|
+
if (condition) {
|
|
27956
|
+
result = await executeSequential(workflow, state, ifDef.then, basePath, engineExecutor, chain, hub, signal);
|
|
27957
|
+
} else if (ifDef.else) {
|
|
27958
|
+
result = await executeSequential(workflow, state, ifDef.else, basePath, engineExecutor, chain, hub, signal);
|
|
27959
|
+
} else {
|
|
27960
|
+
result = chain;
|
|
27961
|
+
}
|
|
27962
|
+
if (ifTraceSeq !== undefined)
|
|
27963
|
+
state.tracer?.endStep(ifTraceSeq, "success", result);
|
|
27964
|
+
return result;
|
|
27965
|
+
} catch (err) {
|
|
27966
|
+
if (ifTraceSeq !== undefined)
|
|
27967
|
+
state.tracer?.endStep(ifTraceSeq, "failure", undefined, String(err?.message ?? err));
|
|
27968
|
+
throw err;
|
|
27132
27969
|
}
|
|
27133
|
-
return chain;
|
|
27134
27970
|
}
|
|
27135
27971
|
return executeStep(workflow, state, step, basePath, engineExecutor, [], chain, hub, signal);
|
|
27136
27972
|
}
|
|
@@ -27140,7 +27976,92 @@ var init_control = __esm2(() => {
|
|
|
27140
27976
|
init_sequential();
|
|
27141
27977
|
RESERVED_SET_KEYS = new Set(["workflow", "execution", "input", "output", "env", "loop", "event"]);
|
|
27142
27978
|
});
|
|
27143
|
-
|
|
27979
|
+
|
|
27980
|
+
class MemoryHub {
|
|
27981
|
+
listeners = new Map;
|
|
27982
|
+
buffer = new Map;
|
|
27983
|
+
closed = false;
|
|
27984
|
+
async publish(event, payload) {
|
|
27985
|
+
if (this.closed)
|
|
27986
|
+
throw new Error("hub is closed");
|
|
27987
|
+
const envelope = { name: event, payload };
|
|
27988
|
+
let buf = this.buffer.get(event);
|
|
27989
|
+
if (!buf) {
|
|
27990
|
+
buf = [];
|
|
27991
|
+
this.buffer.set(event, buf);
|
|
27992
|
+
}
|
|
27993
|
+
buf.push(envelope);
|
|
27994
|
+
const listeners = this.listeners.get(event);
|
|
27995
|
+
if (listeners) {
|
|
27996
|
+
for (const listener of listeners) {
|
|
27997
|
+
listener(envelope);
|
|
27998
|
+
}
|
|
27999
|
+
}
|
|
28000
|
+
}
|
|
28001
|
+
async publishAndWaitAck(event, payload, _timeoutMs) {
|
|
28002
|
+
await this.publish(event, payload);
|
|
28003
|
+
}
|
|
28004
|
+
async* subscribe(event, signal) {
|
|
28005
|
+
if (this.closed)
|
|
28006
|
+
return;
|
|
28007
|
+
const buffered = this.buffer.get(event);
|
|
28008
|
+
if (buffered) {
|
|
28009
|
+
for (const envelope of buffered) {
|
|
28010
|
+
if (signal?.aborted)
|
|
28011
|
+
return;
|
|
28012
|
+
yield envelope;
|
|
28013
|
+
}
|
|
28014
|
+
}
|
|
28015
|
+
const queue = [];
|
|
28016
|
+
let resolve3 = null;
|
|
28017
|
+
const listener = (envelope) => {
|
|
28018
|
+
queue.push(envelope);
|
|
28019
|
+
if (resolve3) {
|
|
28020
|
+
resolve3();
|
|
28021
|
+
resolve3 = null;
|
|
28022
|
+
}
|
|
28023
|
+
};
|
|
28024
|
+
let listeners = this.listeners.get(event);
|
|
28025
|
+
if (!listeners) {
|
|
28026
|
+
listeners = new Set;
|
|
28027
|
+
this.listeners.set(event, listeners);
|
|
28028
|
+
}
|
|
28029
|
+
listeners.add(listener);
|
|
28030
|
+
const onAbort = () => {
|
|
28031
|
+
listeners.delete(listener);
|
|
28032
|
+
if (resolve3) {
|
|
28033
|
+
resolve3();
|
|
28034
|
+
resolve3 = null;
|
|
28035
|
+
}
|
|
28036
|
+
};
|
|
28037
|
+
if (signal) {
|
|
28038
|
+
signal.addEventListener("abort", onAbort);
|
|
28039
|
+
}
|
|
28040
|
+
try {
|
|
28041
|
+
while (!this.closed && !signal?.aborted) {
|
|
28042
|
+
if (queue.length > 0) {
|
|
28043
|
+
yield queue.shift();
|
|
28044
|
+
} else {
|
|
28045
|
+
await new Promise((r) => {
|
|
28046
|
+
resolve3 = r;
|
|
28047
|
+
});
|
|
28048
|
+
}
|
|
28049
|
+
}
|
|
28050
|
+
} finally {
|
|
28051
|
+
listeners.delete(listener);
|
|
28052
|
+
if (signal) {
|
|
28053
|
+
signal.removeEventListener("abort", onAbort);
|
|
28054
|
+
}
|
|
28055
|
+
}
|
|
28056
|
+
}
|
|
28057
|
+
async close() {
|
|
28058
|
+
this.closed = true;
|
|
28059
|
+
for (const listeners of this.listeners.values()) {
|
|
28060
|
+
listeners.clear();
|
|
28061
|
+
}
|
|
28062
|
+
this.listeners.clear();
|
|
28063
|
+
}
|
|
28064
|
+
}
|
|
27144
28065
|
init_parser3();
|
|
27145
28066
|
init_schema();
|
|
27146
28067
|
init_validate();
|
|
@@ -27304,357 +28225,219 @@ function validateInputs(inputDefs, provided) {
|
|
|
27304
28225
|
resolved
|
|
27305
28226
|
};
|
|
27306
28227
|
}
|
|
27307
|
-
|
|
28228
|
+
init_cel();
|
|
28229
|
+
init_cel();
|
|
28230
|
+
init_parser3();
|
|
28231
|
+
init_schema();
|
|
28232
|
+
init_validate();
|
|
27308
28233
|
|
|
27309
|
-
class
|
|
27310
|
-
|
|
27311
|
-
|
|
27312
|
-
|
|
27313
|
-
|
|
27314
|
-
|
|
27315
|
-
|
|
27316
|
-
|
|
27317
|
-
|
|
27318
|
-
|
|
27319
|
-
|
|
27320
|
-
|
|
27321
|
-
|
|
27322
|
-
this.inputs = { ...inputs };
|
|
27323
|
-
this.workflowInputs = { ...inputs };
|
|
27324
|
-
this.workflowMeta = {};
|
|
27325
|
-
this.executionMeta = {
|
|
27326
|
-
id: crypto.randomUUID(),
|
|
28234
|
+
class TraceCollector {
|
|
28235
|
+
openSteps = new Map;
|
|
28236
|
+
seq = 0;
|
|
28237
|
+
truncateAt;
|
|
28238
|
+
writer;
|
|
28239
|
+
constructor(truncateAt = 1e6) {
|
|
28240
|
+
this.truncateAt = truncateAt;
|
|
28241
|
+
}
|
|
28242
|
+
startStep(name, type3, input, loopIndex) {
|
|
28243
|
+
this.seq += 1;
|
|
28244
|
+
this.openSteps.set(this.seq, {
|
|
28245
|
+
name,
|
|
28246
|
+
type: type3,
|
|
27327
28247
|
startedAt: new Date().toISOString(),
|
|
27328
|
-
|
|
27329
|
-
|
|
27330
|
-
|
|
27331
|
-
this.currentInput = undefined;
|
|
27332
|
-
this.currentOutput = undefined;
|
|
27333
|
-
this.chainValue = undefined;
|
|
27334
|
-
this.eventPayload = undefined;
|
|
27335
|
-
this.ancestorPaths = new Set;
|
|
27336
|
-
this.results = new Map;
|
|
27337
|
-
this.loopStack = [];
|
|
27338
|
-
}
|
|
27339
|
-
setResult(stepName, result) {
|
|
27340
|
-
this.results.set(stepName, result);
|
|
27341
|
-
}
|
|
27342
|
-
getResult(stepName) {
|
|
27343
|
-
return this.results.get(stepName);
|
|
27344
|
-
}
|
|
27345
|
-
getAllResults() {
|
|
27346
|
-
const out = {};
|
|
27347
|
-
for (const [k, v] of this.results.entries())
|
|
27348
|
-
out[k] = v;
|
|
27349
|
-
return out;
|
|
27350
|
-
}
|
|
27351
|
-
pushLoop(as) {
|
|
27352
|
-
this.loopStack.push({ index: 0, as });
|
|
27353
|
-
}
|
|
27354
|
-
incrementLoop() {
|
|
27355
|
-
const top = this.loopStack[this.loopStack.length - 1];
|
|
27356
|
-
if (top)
|
|
27357
|
-
top.index += 1;
|
|
27358
|
-
}
|
|
27359
|
-
popLoop() {
|
|
27360
|
-
this.loopStack.pop();
|
|
27361
|
-
}
|
|
27362
|
-
currentLoopIndex() {
|
|
27363
|
-
const top = this.loopStack[this.loopStack.length - 1];
|
|
27364
|
-
return top ? top.index : 0;
|
|
27365
|
-
}
|
|
27366
|
-
setLoopLast(last2) {
|
|
27367
|
-
const top = this.loopStack[this.loopStack.length - 1];
|
|
27368
|
-
if (top)
|
|
27369
|
-
top.last = last2;
|
|
27370
|
-
}
|
|
27371
|
-
currentLoopContext() {
|
|
27372
|
-
const top = this.loopStack[this.loopStack.length - 1];
|
|
27373
|
-
if (!top)
|
|
27374
|
-
return { index: 0, iteration: 1, first: true, last: false };
|
|
27375
|
-
return {
|
|
27376
|
-
index: top.index,
|
|
27377
|
-
iteration: top.index + 1,
|
|
27378
|
-
first: top.index === 0,
|
|
27379
|
-
last: top.last ?? false,
|
|
27380
|
-
as: top.as
|
|
27381
|
-
};
|
|
27382
|
-
}
|
|
27383
|
-
toCelContext() {
|
|
27384
|
-
const ctx = {};
|
|
27385
|
-
for (const [name, res] of this.results.entries()) {
|
|
27386
|
-
ctx[name] = {
|
|
27387
|
-
output: res.parsedOutput ?? res.output,
|
|
27388
|
-
status: res.status,
|
|
27389
|
-
startedAt: res.startedAt,
|
|
27390
|
-
finishedAt: res.finishedAt,
|
|
27391
|
-
duration: res.duration,
|
|
27392
|
-
retries: res.retries ?? 0,
|
|
27393
|
-
error: res.error,
|
|
27394
|
-
cwd: res.cwd
|
|
27395
|
-
};
|
|
27396
|
-
}
|
|
27397
|
-
ctx["workflow"] = {
|
|
27398
|
-
id: this.workflowMeta.id,
|
|
27399
|
-
name: this.workflowMeta.name,
|
|
27400
|
-
version: this.workflowMeta.version,
|
|
27401
|
-
inputs: this.workflowInputs,
|
|
27402
|
-
output: null
|
|
27403
|
-
};
|
|
27404
|
-
ctx["execution"] = { ...this.executionMeta };
|
|
27405
|
-
ctx["input"] = this.currentInput ?? {};
|
|
27406
|
-
ctx["output"] = this.currentOutput ?? {};
|
|
27407
|
-
ctx["env"] = { ...env };
|
|
27408
|
-
const loopCtx = this.currentLoopContext();
|
|
27409
|
-
const loopObj = {
|
|
27410
|
-
index: loopCtx.index,
|
|
27411
|
-
iteration: loopCtx.iteration,
|
|
27412
|
-
first: loopCtx.first,
|
|
27413
|
-
last: loopCtx.last
|
|
27414
|
-
};
|
|
27415
|
-
if (loopCtx.as) {
|
|
27416
|
-
ctx[`_${loopCtx.as}`] = loopObj;
|
|
27417
|
-
}
|
|
27418
|
-
ctx["_loop"] = loopObj;
|
|
27419
|
-
ctx["loop"] = loopObj;
|
|
27420
|
-
ctx["event"] = this.eventPayload ?? {};
|
|
27421
|
-
ctx["now"] = Math.floor(Date.now() / 1000);
|
|
27422
|
-
return ctx;
|
|
27423
|
-
}
|
|
27424
|
-
resolveOutput(outputDef, celEvaluator) {
|
|
27425
|
-
const ctx = this.toCelContext();
|
|
27426
|
-
if (typeof outputDef === "object" && "map" in outputDef && "schema" in outputDef) {
|
|
27427
|
-
const result2 = {};
|
|
27428
|
-
for (const [k, expr] of Object.entries(outputDef.map)) {
|
|
27429
|
-
result2[k] = celEvaluator(expr, ctx);
|
|
27430
|
-
}
|
|
27431
|
-
return result2;
|
|
27432
|
-
}
|
|
27433
|
-
if (typeof outputDef === "string") {
|
|
27434
|
-
return celEvaluator(outputDef, ctx);
|
|
27435
|
-
}
|
|
27436
|
-
const result = {};
|
|
27437
|
-
for (const k of Object.keys(outputDef)) {
|
|
27438
|
-
const expr = outputDef[k];
|
|
27439
|
-
result[k] = celEvaluator(expr, ctx);
|
|
27440
|
-
}
|
|
27441
|
-
return result;
|
|
27442
|
-
}
|
|
27443
|
-
}
|
|
27444
|
-
async function executeWorkflow(workflow, inputs = {}, basePath = process.cwd(), options = {}) {
|
|
27445
|
-
const { result: inputResult, resolved } = validateInputs(workflow.inputs, inputs);
|
|
27446
|
-
if (!inputResult.valid) {
|
|
27447
|
-
throw new Error(`input validation failed: ${JSON.stringify(inputResult.errors)}`);
|
|
27448
|
-
}
|
|
27449
|
-
const state = new WorkflowState(resolved);
|
|
27450
|
-
state.workflowMeta = {
|
|
27451
|
-
id: workflow.id,
|
|
27452
|
-
name: workflow.name,
|
|
27453
|
-
version: workflow.version
|
|
27454
|
-
};
|
|
27455
|
-
state.executionMeta.number = options.executionNumber ?? 1;
|
|
27456
|
-
if (options.cwd) {
|
|
27457
|
-
state.executionMeta.cwd = options.cwd;
|
|
27458
|
-
}
|
|
27459
|
-
const startedAt = performance.now();
|
|
27460
|
-
if (options._ancestorPaths) {
|
|
27461
|
-
state.ancestorPaths = options._ancestorPaths;
|
|
27462
|
-
}
|
|
27463
|
-
const engineExecutor = async (subWorkflow, subInputs, subBasePath) => {
|
|
27464
|
-
return executeWorkflow(subWorkflow, subInputs, subBasePath, {
|
|
27465
|
-
...options,
|
|
27466
|
-
_ancestorPaths: state.ancestorPaths
|
|
28248
|
+
startMs: performance.now(),
|
|
28249
|
+
input: input !== undefined ? this.truncate(input) : undefined,
|
|
28250
|
+
loopIndex
|
|
27467
28251
|
});
|
|
27468
|
-
|
|
27469
|
-
let chain;
|
|
27470
|
-
for (const step of workflow.flow) {
|
|
27471
|
-
chain = await executeControlStep(workflow, state, step, basePath, engineExecutor, chain, options.hub);
|
|
27472
|
-
}
|
|
27473
|
-
let output;
|
|
27474
|
-
if (workflow.output !== undefined) {
|
|
27475
|
-
output = state.resolveOutput(workflow.output, evaluateCel);
|
|
27476
|
-
if (typeof workflow.output === "object" && "schema" in workflow.output && "map" in workflow.output && typeof output === "object" && output !== null) {
|
|
27477
|
-
validateOutputSchema(workflow.output.schema, output);
|
|
27478
|
-
}
|
|
27479
|
-
} else {
|
|
27480
|
-
output = chain;
|
|
28252
|
+
return this.seq;
|
|
27481
28253
|
}
|
|
27482
|
-
|
|
27483
|
-
|
|
27484
|
-
|
|
27485
|
-
|
|
27486
|
-
|
|
27487
|
-
|
|
27488
|
-
|
|
27489
|
-
|
|
27490
|
-
|
|
27491
|
-
|
|
27492
|
-
|
|
27493
|
-
|
|
27494
|
-
|
|
27495
|
-
|
|
27496
|
-
|
|
28254
|
+
endStep(seq, status, output, error, retries) {
|
|
28255
|
+
const open = this.openSteps.get(seq);
|
|
28256
|
+
if (!open)
|
|
28257
|
+
return;
|
|
28258
|
+
this.openSteps.delete(seq);
|
|
28259
|
+
const finishedAt = new Date().toISOString();
|
|
28260
|
+
const duration = Math.max(0, performance.now() - open.startMs);
|
|
28261
|
+
const step = {
|
|
28262
|
+
seq,
|
|
28263
|
+
name: open.name,
|
|
28264
|
+
type: open.type,
|
|
28265
|
+
startedAt: open.startedAt,
|
|
28266
|
+
finishedAt,
|
|
28267
|
+
duration: Math.round(duration),
|
|
28268
|
+
status,
|
|
28269
|
+
...open.input !== undefined ? { input: open.input } : {},
|
|
28270
|
+
...output !== undefined ? { output: this.truncate(output) } : {},
|
|
28271
|
+
...error !== undefined ? { error } : {},
|
|
28272
|
+
...retries !== undefined && retries > 0 ? { retries } : {},
|
|
28273
|
+
...open.loopIndex !== undefined ? { loopIndex: open.loopIndex } : {}
|
|
28274
|
+
};
|
|
28275
|
+
this.writer?.writeStep(step);
|
|
27497
28276
|
}
|
|
27498
|
-
|
|
27499
|
-
|
|
27500
|
-
|
|
27501
|
-
|
|
28277
|
+
truncate(value) {
|
|
28278
|
+
if (value == null)
|
|
28279
|
+
return value;
|
|
28280
|
+
const str = typeof value === "string" ? value : JSON.stringify(value);
|
|
28281
|
+
const bytes = new TextEncoder().encode(str);
|
|
28282
|
+
if (bytes.length <= this.truncateAt)
|
|
28283
|
+
return value;
|
|
28284
|
+
const cut = new TextDecoder().decode(bytes.slice(0, this.truncateAt));
|
|
28285
|
+
return cut + "...[truncated]";
|
|
27502
28286
|
}
|
|
27503
|
-
return executeWorkflow(workflow, inputs, workflowBasePath, options);
|
|
27504
28287
|
}
|
|
27505
28288
|
init_control();
|
|
27506
28289
|
init_sequential();
|
|
27507
|
-
init_errors();
|
|
27508
|
-
init_timeout();
|
|
27509
28290
|
init_wait();
|
|
28291
|
+
init_emit();
|
|
27510
28292
|
|
|
27511
|
-
// src/
|
|
27512
|
-
|
|
27513
|
-
const
|
|
27514
|
-
|
|
27515
|
-
|
|
27516
|
-
|
|
27517
|
-
|
|
27518
|
-
|
|
27519
|
-
|
|
27520
|
-
|
|
27521
|
-
|
|
27522
|
-
|
|
28293
|
+
// src/lint.ts
|
|
28294
|
+
function collectLintWarnings(workflow) {
|
|
28295
|
+
const warnings = [];
|
|
28296
|
+
const participants = workflow.participants ?? {};
|
|
28297
|
+
collectFlowWarnings(workflow.flow ?? [], participants, warnings);
|
|
28298
|
+
return warnings;
|
|
28299
|
+
}
|
|
28300
|
+
function collectFlowWarnings(flow, participants, warnings, basePath = "flow") {
|
|
28301
|
+
for (const [index, step] of flow.entries()) {
|
|
28302
|
+
const stepPath = `${basePath}[${index}]`;
|
|
28303
|
+
if (!step || typeof step !== "object")
|
|
28304
|
+
continue;
|
|
28305
|
+
const obj = step;
|
|
28306
|
+
if (obj.loop && Object.keys(obj).length === 1) {
|
|
28307
|
+
const loopDef = obj.loop;
|
|
28308
|
+
if (loopDef.until == null && loopDef.max == null) {
|
|
28309
|
+
warnings.push({
|
|
28310
|
+
path: `${stepPath}.loop`,
|
|
28311
|
+
message: "loop has no 'until' and no 'max' — this will be rejected at runtime"
|
|
28312
|
+
});
|
|
28313
|
+
}
|
|
28314
|
+
collectFlowWarnings(loopDef.steps ?? [], participants, warnings, `${stepPath}.loop.steps`);
|
|
28315
|
+
continue;
|
|
27523
28316
|
}
|
|
27524
|
-
|
|
27525
|
-
|
|
27526
|
-
const
|
|
27527
|
-
|
|
27528
|
-
|
|
27529
|
-
|
|
27530
|
-
|
|
27531
|
-
|
|
28317
|
+
if (obj.parallel && Object.keys(obj).length === 1) {
|
|
28318
|
+
const parallelSteps = obj.parallel;
|
|
28319
|
+
const branchSetKeys = new Map;
|
|
28320
|
+
for (const [branchIdx, branch] of parallelSteps.entries()) {
|
|
28321
|
+
const setKeys = collectSetKeys(branch);
|
|
28322
|
+
for (const key of setKeys) {
|
|
28323
|
+
const branches = branchSetKeys.get(key) ?? [];
|
|
28324
|
+
branches.push(branchIdx);
|
|
28325
|
+
branchSetKeys.set(key, branches);
|
|
28326
|
+
}
|
|
27532
28327
|
}
|
|
27533
|
-
|
|
28328
|
+
for (const [key, branches] of branchSetKeys) {
|
|
28329
|
+
if (branches.length > 1) {
|
|
28330
|
+
warnings.push({
|
|
28331
|
+
path: `${stepPath}.parallel`,
|
|
28332
|
+
message: `branches [${branches.join(", ")}] both write to '${key}' via set — race condition risk`
|
|
28333
|
+
});
|
|
28334
|
+
}
|
|
28335
|
+
}
|
|
28336
|
+
collectFlowWarnings(parallelSteps, participants, warnings, `${stepPath}.parallel`);
|
|
28337
|
+
continue;
|
|
27534
28338
|
}
|
|
27535
|
-
|
|
27536
|
-
|
|
27537
|
-
|
|
27538
|
-
|
|
27539
|
-
|
|
27540
|
-
|
|
27541
|
-
|
|
27542
|
-
|
|
27543
|
-
|
|
27544
|
-
|
|
27545
|
-
|
|
28339
|
+
if ("type" in obj && !obj.as) {
|
|
28340
|
+
warnings.push({
|
|
28341
|
+
path: stepPath,
|
|
28342
|
+
message: "inline participant without 'as' — its output cannot be referenced by name"
|
|
28343
|
+
});
|
|
28344
|
+
continue;
|
|
28345
|
+
}
|
|
28346
|
+
if (obj.if && Object.keys(obj).length === 1) {
|
|
28347
|
+
const ifDef = obj.if;
|
|
28348
|
+
collectFlowWarnings(ifDef.then ?? [], participants, warnings, `${stepPath}.if.then`);
|
|
28349
|
+
if (ifDef.else) {
|
|
28350
|
+
collectFlowWarnings(ifDef.else, participants, warnings, `${stepPath}.if.else`);
|
|
27546
28351
|
}
|
|
27547
|
-
throw err;
|
|
27548
28352
|
}
|
|
27549
28353
|
}
|
|
27550
|
-
console.error(`Error: unknown event backend "${backend}". Supported: memory, nats, redis`);
|
|
27551
|
-
throw new Error(`unknown event backend: ${backend}`);
|
|
27552
28354
|
}
|
|
27553
|
-
function
|
|
27554
|
-
|
|
27555
|
-
|
|
27556
|
-
|
|
27557
|
-
|
|
27558
|
-
|
|
27559
|
-
|
|
27560
|
-
|
|
27561
|
-
|
|
27562
|
-
|
|
27563
|
-
|
|
27564
|
-
|
|
27565
|
-
|
|
27566
|
-
|
|
27567
|
-
|
|
28355
|
+
function collectSetKeys(step) {
|
|
28356
|
+
if (!step || typeof step !== "object")
|
|
28357
|
+
return [];
|
|
28358
|
+
const obj = step;
|
|
28359
|
+
if ("set" in obj && Object.keys(obj).length === 1) {
|
|
28360
|
+
return Object.keys(obj.set);
|
|
28361
|
+
}
|
|
28362
|
+
const keys3 = [];
|
|
28363
|
+
if (obj.loop) {
|
|
28364
|
+
const loopDef = obj.loop;
|
|
28365
|
+
for (const s of loopDef.steps ?? []) {
|
|
28366
|
+
keys3.push(...collectSetKeys(s));
|
|
28367
|
+
}
|
|
28368
|
+
}
|
|
28369
|
+
if (obj.if) {
|
|
28370
|
+
const ifDef = obj.if;
|
|
28371
|
+
for (const s of ifDef.then ?? []) {
|
|
28372
|
+
keys3.push(...collectSetKeys(s));
|
|
28373
|
+
}
|
|
28374
|
+
if (ifDef.else) {
|
|
28375
|
+
for (const s of ifDef.else) {
|
|
28376
|
+
keys3.push(...collectSetKeys(s));
|
|
27568
28377
|
}
|
|
27569
28378
|
}
|
|
27570
28379
|
}
|
|
27571
|
-
return
|
|
28380
|
+
return keys3;
|
|
27572
28381
|
}
|
|
27573
|
-
async function
|
|
28382
|
+
async function lintCommand(filePath) {
|
|
27574
28383
|
if (!filePath) {
|
|
27575
|
-
console.error("Usage:
|
|
28384
|
+
console.error("Usage: quack lint <workflow.yaml>");
|
|
27576
28385
|
return 1;
|
|
27577
28386
|
}
|
|
27578
|
-
let inputs = {};
|
|
27579
28387
|
try {
|
|
27580
|
-
|
|
27581
|
-
|
|
27582
|
-
|
|
27583
|
-
|
|
27584
|
-
|
|
27585
|
-
|
|
27586
|
-
if (stdin.length > 0) {
|
|
27587
|
-
try {
|
|
27588
|
-
const parsed = JSON.parse(stdin);
|
|
27589
|
-
if (typeof parsed === "object" && parsed !== null)
|
|
27590
|
-
inputs = { ...inputs, ...parsed };
|
|
27591
|
-
} catch {}
|
|
28388
|
+
const workflow = await parseWorkflowFile(filePath);
|
|
28389
|
+
const schemaRes = validateSchema(workflow);
|
|
28390
|
+
if (!schemaRes.valid) {
|
|
28391
|
+
console.error("Schema validation failed:");
|
|
28392
|
+
for (const e of schemaRes.errors) {
|
|
28393
|
+
console.error(` - ${e.path}: ${e.message}`);
|
|
27592
28394
|
}
|
|
28395
|
+
return 1;
|
|
27593
28396
|
}
|
|
27594
|
-
|
|
27595
|
-
|
|
27596
|
-
if (
|
|
27597
|
-
|
|
27598
|
-
|
|
27599
|
-
|
|
27600
|
-
if (typeof parsed === "object" && parsed !== null)
|
|
27601
|
-
inputs = { ...inputs, ...parsed };
|
|
27602
|
-
} catch (err) {
|
|
27603
|
-
console.error("Failed to read input file:", err);
|
|
27604
|
-
return 1;
|
|
28397
|
+
const basePath = dirname2(filePath);
|
|
28398
|
+
const semanticRes = await validateSemantic(workflow, basePath);
|
|
28399
|
+
if (!semanticRes.valid) {
|
|
28400
|
+
console.error("Semantic validation failed:");
|
|
28401
|
+
for (const e of semanticRes.errors) {
|
|
28402
|
+
console.error(` - ${e.path}: ${e.message}`);
|
|
27605
28403
|
}
|
|
28404
|
+
return 1;
|
|
27606
28405
|
}
|
|
27607
|
-
|
|
27608
|
-
|
|
27609
|
-
|
|
27610
|
-
|
|
27611
|
-
}
|
|
27612
|
-
|
|
27613
|
-
try {
|
|
27614
|
-
hub = await createHubFromFlags(cliValues);
|
|
27615
|
-
} catch {
|
|
27616
|
-
return 1;
|
|
27617
|
-
}
|
|
27618
|
-
const options = {
|
|
27619
|
-
hub,
|
|
27620
|
-
cwd: cliValues?.cwd,
|
|
27621
|
-
verbose: cliValues?.verbose,
|
|
27622
|
-
quiet: cliValues?.quiet
|
|
27623
|
-
};
|
|
27624
|
-
try {
|
|
27625
|
-
const res = await runWorkflowFromFile(filePath, inputs, options);
|
|
27626
|
-
const output = res.output;
|
|
27627
|
-
if (output === undefined || output === null) {} else if (typeof output === "string") {
|
|
27628
|
-
process.stdout.write(output);
|
|
27629
|
-
} else {
|
|
27630
|
-
console.log(JSON.stringify(output, null, 2));
|
|
28406
|
+
const warnings = collectLintWarnings(workflow);
|
|
28407
|
+
if (warnings.length > 0) {
|
|
28408
|
+
console.warn("Warnings:");
|
|
28409
|
+
for (const w of warnings) {
|
|
28410
|
+
console.warn(` - ${w.path}: ${w.message}`);
|
|
28411
|
+
}
|
|
27631
28412
|
}
|
|
27632
|
-
|
|
28413
|
+
console.log("valid");
|
|
28414
|
+
return 0;
|
|
27633
28415
|
} catch (err) {
|
|
27634
|
-
|
|
27635
|
-
console.error("Error:", msg);
|
|
27636
|
-
if (cliValues?.verbose && err instanceof Error && err.stack) {
|
|
27637
|
-
console.error(err.stack);
|
|
27638
|
-
}
|
|
28416
|
+
console.error("Error during lint:", err && err.message ? err.message : err);
|
|
27639
28417
|
return 1;
|
|
27640
|
-
} finally {
|
|
27641
|
-
await hub?.close();
|
|
27642
28418
|
}
|
|
27643
28419
|
}
|
|
27644
28420
|
|
|
27645
|
-
// src/
|
|
27646
|
-
import {
|
|
28421
|
+
// src/run.ts
|
|
28422
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
27647
28423
|
|
|
27648
|
-
// ../core/dist/index.js
|
|
28424
|
+
// ../core/dist/engine/index.js
|
|
27649
28425
|
import { createRequire as createRequire3 } from "node:module";
|
|
27650
28426
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
27651
|
-
import { readFileSync as readFileSync2 } from "node:fs";
|
|
27652
28427
|
import { constants as constants2 } from "node:fs";
|
|
27653
28428
|
import { access as access2 } from "node:fs/promises";
|
|
27654
|
-
import { resolve as
|
|
28429
|
+
import { resolve as resolve3 } from "node:path";
|
|
28430
|
+
import { writeFile as writeFile3 } from "node:fs/promises";
|
|
28431
|
+
import { join as join4 } from "node:path";
|
|
28432
|
+
import { appendFile as appendFile2, readFile as readFile22, writeFile as writeFile22 } from "node:fs/promises";
|
|
28433
|
+
import { join as join22 } from "node:path";
|
|
28434
|
+
import { join as join32 } from "node:path";
|
|
27655
28435
|
import { spawn as spawn2 } from "node:child_process";
|
|
27656
28436
|
import { dirname as dirname3, resolve as resolve22 } from "node:path";
|
|
27657
28437
|
import { resolve as resolvePath2, isAbsolute as isAbsolute2 } from "node:path";
|
|
28438
|
+
import { dirname as dirname22, resolve as resolve32 } from "node:path";
|
|
28439
|
+
import { mkdir } from "node:fs/promises";
|
|
28440
|
+
import { env } from "node:process";
|
|
27658
28441
|
var __create2 = Object.create;
|
|
27659
28442
|
var __getProtoOf2 = Object.getPrototypeOf;
|
|
27660
28443
|
var __defProp3 = Object.defineProperty;
|
|
@@ -49140,7 +49923,7 @@ var require_compile2 = __commonJS2((exports) => {
|
|
|
49140
49923
|
const schOrFunc = root22.refs[ref];
|
|
49141
49924
|
if (schOrFunc)
|
|
49142
49925
|
return schOrFunc;
|
|
49143
|
-
let _sch =
|
|
49926
|
+
let _sch = resolve4.call(this, root22, ref);
|
|
49144
49927
|
if (_sch === undefined) {
|
|
49145
49928
|
const schema2 = (_a = root22.localRefs) === null || _a === undefined ? undefined : _a[ref];
|
|
49146
49929
|
const { schemaId } = this.opts;
|
|
@@ -49167,7 +49950,7 @@ var require_compile2 = __commonJS2((exports) => {
|
|
|
49167
49950
|
function sameSchemaEnv(s1, s2) {
|
|
49168
49951
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
49169
49952
|
}
|
|
49170
|
-
function
|
|
49953
|
+
function resolve4(root22, ref) {
|
|
49171
49954
|
let sch;
|
|
49172
49955
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
49173
49956
|
ref = sch;
|
|
@@ -49689,7 +50472,7 @@ var require_fast_uri2 = __commonJS2((exports, module) => {
|
|
|
49689
50472
|
}
|
|
49690
50473
|
return uri;
|
|
49691
50474
|
}
|
|
49692
|
-
function
|
|
50475
|
+
function resolve4(baseURI, relativeURI, options) {
|
|
49693
50476
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
49694
50477
|
const resolved = resolveComponent(parse22(baseURI, schemelessOptions), parse22(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
49695
50478
|
schemelessOptions.skipEscape = true;
|
|
@@ -49917,7 +50700,7 @@ var require_fast_uri2 = __commonJS2((exports, module) => {
|
|
|
49917
50700
|
var fastUri = {
|
|
49918
50701
|
SCHEMES,
|
|
49919
50702
|
normalize,
|
|
49920
|
-
resolve:
|
|
50703
|
+
resolve: resolve4,
|
|
49921
50704
|
resolveComponent,
|
|
49922
50705
|
equal,
|
|
49923
50706
|
serialize,
|
|
@@ -53306,6 +54089,549 @@ var require_dist22 = __commonJS2((exports, module) => {
|
|
|
53306
54089
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53307
54090
|
exports.default = formatsPlugin;
|
|
53308
54091
|
});
|
|
54092
|
+
var duckflux_schema_default2;
|
|
54093
|
+
var init_duckflux_schema2 = __esm3(() => {
|
|
54094
|
+
duckflux_schema_default2 = {
|
|
54095
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
54096
|
+
$id: "https://raw.githubusercontent.com/duckflux/spec/main/duckflux.schema.json",
|
|
54097
|
+
title: "duckflux Workflow",
|
|
54098
|
+
description: "Schema for duckflux — a minimal, deterministic, runtime-agnostic workflow DSL.",
|
|
54099
|
+
type: "object",
|
|
54100
|
+
required: ["flow"],
|
|
54101
|
+
additionalProperties: false,
|
|
54102
|
+
properties: {
|
|
54103
|
+
id: {
|
|
54104
|
+
type: "string",
|
|
54105
|
+
description: "Unique identifier for the workflow."
|
|
54106
|
+
},
|
|
54107
|
+
name: {
|
|
54108
|
+
type: "string",
|
|
54109
|
+
description: "Human-readable workflow name."
|
|
54110
|
+
},
|
|
54111
|
+
version: {
|
|
54112
|
+
description: "Version identifier for the workflow definition.",
|
|
54113
|
+
oneOf: [
|
|
54114
|
+
{ type: "string" },
|
|
54115
|
+
{ type: "integer" }
|
|
54116
|
+
]
|
|
54117
|
+
},
|
|
54118
|
+
defaults: {
|
|
54119
|
+
$ref: "#/$defs/defaults"
|
|
54120
|
+
},
|
|
54121
|
+
inputs: {
|
|
54122
|
+
$ref: "#/$defs/inputs"
|
|
54123
|
+
},
|
|
54124
|
+
participants: {
|
|
54125
|
+
type: "object",
|
|
54126
|
+
description: "Named steps that can be referenced in the flow.",
|
|
54127
|
+
additionalProperties: {
|
|
54128
|
+
$ref: "#/$defs/participant"
|
|
54129
|
+
},
|
|
54130
|
+
not: {
|
|
54131
|
+
anyOf: [
|
|
54132
|
+
{ required: ["workflow"] },
|
|
54133
|
+
{ required: ["execution"] },
|
|
54134
|
+
{ required: ["input"] },
|
|
54135
|
+
{ required: ["output"] },
|
|
54136
|
+
{ required: ["env"] },
|
|
54137
|
+
{ required: ["loop"] },
|
|
54138
|
+
{ required: ["event"] }
|
|
54139
|
+
]
|
|
54140
|
+
}
|
|
54141
|
+
},
|
|
54142
|
+
flow: {
|
|
54143
|
+
$ref: "#/$defs/flowSequence"
|
|
54144
|
+
},
|
|
54145
|
+
output: {
|
|
54146
|
+
$ref: "#/$defs/workflowOutput"
|
|
54147
|
+
}
|
|
54148
|
+
},
|
|
54149
|
+
$defs: {
|
|
54150
|
+
duration: {
|
|
54151
|
+
type: "string",
|
|
54152
|
+
pattern: "^[0-9]+(ms|s|m|h|d)$",
|
|
54153
|
+
description: "Duration string, e.g. '30s', '5m', '2h', '1d'."
|
|
54154
|
+
},
|
|
54155
|
+
celExpression: {
|
|
54156
|
+
type: "string",
|
|
54157
|
+
description: "A Google CEL expression."
|
|
54158
|
+
},
|
|
54159
|
+
defaults: {
|
|
54160
|
+
type: "object",
|
|
54161
|
+
description: "Global defaults applied to all participants.",
|
|
54162
|
+
additionalProperties: false,
|
|
54163
|
+
properties: {
|
|
54164
|
+
timeout: {
|
|
54165
|
+
$ref: "#/$defs/duration"
|
|
54166
|
+
},
|
|
54167
|
+
cwd: {
|
|
54168
|
+
type: "string",
|
|
54169
|
+
description: "Default working directory for exec participants. Supports CEL expressions."
|
|
54170
|
+
}
|
|
54171
|
+
}
|
|
54172
|
+
},
|
|
54173
|
+
inputs: {
|
|
54174
|
+
type: "object",
|
|
54175
|
+
description: "Workflow input parameters. Accessed in CEL as workflow.inputs.<field>. Each key is a parameter name. Value can be null (string, no schema), or a JSON Schema object for validation.",
|
|
54176
|
+
additionalProperties: {
|
|
54177
|
+
oneOf: [
|
|
54178
|
+
{ type: "null" },
|
|
54179
|
+
{ $ref: "#/$defs/inputField" }
|
|
54180
|
+
]
|
|
54181
|
+
}
|
|
54182
|
+
},
|
|
54183
|
+
inputField: {
|
|
54184
|
+
type: "object",
|
|
54185
|
+
description: "JSON Schema field definition with optional 'required: true' shortcut.",
|
|
54186
|
+
properties: {
|
|
54187
|
+
type: {
|
|
54188
|
+
type: "string",
|
|
54189
|
+
enum: ["string", "integer", "number", "boolean", "array", "object"]
|
|
54190
|
+
},
|
|
54191
|
+
description: { type: "string" },
|
|
54192
|
+
default: {},
|
|
54193
|
+
required: { type: "boolean" },
|
|
54194
|
+
format: { type: "string" },
|
|
54195
|
+
enum: { type: "array" },
|
|
54196
|
+
minimum: { type: "number" },
|
|
54197
|
+
maximum: { type: "number" },
|
|
54198
|
+
minLength: { type: "integer" },
|
|
54199
|
+
maxLength: { type: "integer" },
|
|
54200
|
+
pattern: { type: "string" },
|
|
54201
|
+
items: {
|
|
54202
|
+
$ref: "#/$defs/inputField"
|
|
54203
|
+
}
|
|
54204
|
+
},
|
|
54205
|
+
additionalProperties: false
|
|
54206
|
+
},
|
|
54207
|
+
retryConfig: {
|
|
54208
|
+
type: "object",
|
|
54209
|
+
description: "Retry configuration. Only applies when onError is 'retry'.",
|
|
54210
|
+
additionalProperties: false,
|
|
54211
|
+
required: ["max"],
|
|
54212
|
+
properties: {
|
|
54213
|
+
max: {
|
|
54214
|
+
type: "integer",
|
|
54215
|
+
minimum: 1,
|
|
54216
|
+
description: "Maximum number of retry attempts."
|
|
54217
|
+
},
|
|
54218
|
+
backoff: {
|
|
54219
|
+
$ref: "#/$defs/duration",
|
|
54220
|
+
description: "Interval between attempts. Default: 0s."
|
|
54221
|
+
},
|
|
54222
|
+
factor: {
|
|
54223
|
+
type: "number",
|
|
54224
|
+
minimum: 1,
|
|
54225
|
+
description: "Backoff multiplier. Default: 1 (no escalation)."
|
|
54226
|
+
}
|
|
54227
|
+
}
|
|
54228
|
+
},
|
|
54229
|
+
onError: {
|
|
54230
|
+
type: "string",
|
|
54231
|
+
description: "Error handling strategy: 'fail' (default), 'skip', 'retry', or a participant name for redirect.",
|
|
54232
|
+
minLength: 1
|
|
54233
|
+
},
|
|
54234
|
+
onTimeout: {
|
|
54235
|
+
type: "string",
|
|
54236
|
+
description: "Timeout handling strategy: 'fail' (default), 'skip', or a participant name for redirect.",
|
|
54237
|
+
minLength: 1
|
|
54238
|
+
},
|
|
54239
|
+
participantInput: {
|
|
54240
|
+
description: "Explicit input mapping. String for direct passthrough, object for structured mapping. Values are CEL expressions. Merged with implicit I/O chain input at runtime.",
|
|
54241
|
+
oneOf: [
|
|
54242
|
+
{ type: "string" },
|
|
54243
|
+
{
|
|
54244
|
+
type: "object",
|
|
54245
|
+
additionalProperties: {
|
|
54246
|
+
type: "string"
|
|
54247
|
+
}
|
|
54248
|
+
}
|
|
54249
|
+
]
|
|
54250
|
+
},
|
|
54251
|
+
participantOutputSchema: {
|
|
54252
|
+
type: "object",
|
|
54253
|
+
description: "Output schema (JSON Schema fields). Opt-in validation.",
|
|
54254
|
+
additionalProperties: {
|
|
54255
|
+
$ref: "#/$defs/inputField"
|
|
54256
|
+
}
|
|
54257
|
+
},
|
|
54258
|
+
payload: {
|
|
54259
|
+
description: "Event payload. String (CEL expression) or object with CEL expressions as values.",
|
|
54260
|
+
oneOf: [
|
|
54261
|
+
{ type: "string" },
|
|
54262
|
+
{
|
|
54263
|
+
type: "object",
|
|
54264
|
+
additionalProperties: {}
|
|
54265
|
+
}
|
|
54266
|
+
]
|
|
54267
|
+
},
|
|
54268
|
+
participant: {
|
|
54269
|
+
type: "object",
|
|
54270
|
+
required: ["type"],
|
|
54271
|
+
description: "A named, reusable building block of the workflow.",
|
|
54272
|
+
properties: {
|
|
54273
|
+
type: {
|
|
54274
|
+
type: "string",
|
|
54275
|
+
enum: ["exec", "http", "mcp", "workflow", "emit"],
|
|
54276
|
+
description: "Participant type."
|
|
54277
|
+
},
|
|
54278
|
+
as: {
|
|
54279
|
+
type: "string",
|
|
54280
|
+
description: "Human-readable display name."
|
|
54281
|
+
},
|
|
54282
|
+
timeout: {
|
|
54283
|
+
$ref: "#/$defs/duration"
|
|
54284
|
+
},
|
|
54285
|
+
onError: {
|
|
54286
|
+
$ref: "#/$defs/onError"
|
|
54287
|
+
},
|
|
54288
|
+
retry: {
|
|
54289
|
+
$ref: "#/$defs/retryConfig"
|
|
54290
|
+
},
|
|
54291
|
+
input: {
|
|
54292
|
+
$ref: "#/$defs/participantInput"
|
|
54293
|
+
},
|
|
54294
|
+
output: {
|
|
54295
|
+
$ref: "#/$defs/participantOutputSchema"
|
|
54296
|
+
},
|
|
54297
|
+
run: {
|
|
54298
|
+
type: "string",
|
|
54299
|
+
description: "[exec] Shell command to execute."
|
|
54300
|
+
},
|
|
54301
|
+
cwd: {
|
|
54302
|
+
type: "string",
|
|
54303
|
+
description: "[exec] Working directory. Supports CEL expressions."
|
|
54304
|
+
},
|
|
54305
|
+
url: {
|
|
54306
|
+
type: "string",
|
|
54307
|
+
description: "[http] Target URL. Supports CEL expressions."
|
|
54308
|
+
},
|
|
54309
|
+
method: {
|
|
54310
|
+
type: "string",
|
|
54311
|
+
enum: ["GET", "POST", "PUT", "PATCH", "DELETE"],
|
|
54312
|
+
description: "[http] HTTP method."
|
|
54313
|
+
},
|
|
54314
|
+
headers: {
|
|
54315
|
+
type: "object",
|
|
54316
|
+
additionalProperties: { type: "string" },
|
|
54317
|
+
description: "[http] HTTP headers. Values support CEL expressions."
|
|
54318
|
+
},
|
|
54319
|
+
body: {
|
|
54320
|
+
description: "[http] Request body. String or object. Supports CEL expressions.",
|
|
54321
|
+
oneOf: [
|
|
54322
|
+
{ type: "string" },
|
|
54323
|
+
{ type: "object" }
|
|
54324
|
+
]
|
|
54325
|
+
},
|
|
54326
|
+
path: {
|
|
54327
|
+
type: "string",
|
|
54328
|
+
description: "[workflow] Path to the sub-workflow YAML file."
|
|
54329
|
+
},
|
|
54330
|
+
server: {
|
|
54331
|
+
type: "string",
|
|
54332
|
+
description: "[mcp] MCP server identifier."
|
|
54333
|
+
},
|
|
54334
|
+
tool: {
|
|
54335
|
+
type: "string",
|
|
54336
|
+
description: "[mcp] MCP tool name to invoke."
|
|
54337
|
+
},
|
|
54338
|
+
event: {
|
|
54339
|
+
type: "string",
|
|
54340
|
+
description: "[emit] Event name to emit."
|
|
54341
|
+
},
|
|
54342
|
+
payload: {
|
|
54343
|
+
$ref: "#/$defs/payload",
|
|
54344
|
+
description: "[emit] Event payload. CEL expression or object with CEL expressions."
|
|
54345
|
+
},
|
|
54346
|
+
ack: {
|
|
54347
|
+
type: "boolean",
|
|
54348
|
+
description: "[emit] If true, wait for delivery acknowledgment. Default: false.",
|
|
54349
|
+
default: false
|
|
54350
|
+
}
|
|
54351
|
+
},
|
|
54352
|
+
additionalProperties: false
|
|
54353
|
+
},
|
|
54354
|
+
inlineParticipant: {
|
|
54355
|
+
type: "object",
|
|
54356
|
+
required: ["type"],
|
|
54357
|
+
description: "An inline participant definition in the flow. 'as' is optional — if omitted, the participant is anonymous and its output is only accessible via the implicit I/O chain.",
|
|
54358
|
+
properties: {
|
|
54359
|
+
as: {
|
|
54360
|
+
type: "string",
|
|
54361
|
+
description: "Optional name for inline participants. If provided, must be unique across all participant names. Enables output reference by name."
|
|
54362
|
+
},
|
|
54363
|
+
type: {
|
|
54364
|
+
type: "string",
|
|
54365
|
+
enum: ["exec", "http", "mcp", "workflow", "emit"],
|
|
54366
|
+
description: "Participant type."
|
|
54367
|
+
},
|
|
54368
|
+
when: {
|
|
54369
|
+
$ref: "#/$defs/celExpression",
|
|
54370
|
+
description: "Guard condition. If false, step is skipped."
|
|
54371
|
+
},
|
|
54372
|
+
timeout: {
|
|
54373
|
+
$ref: "#/$defs/duration"
|
|
54374
|
+
},
|
|
54375
|
+
onError: {
|
|
54376
|
+
$ref: "#/$defs/onError"
|
|
54377
|
+
},
|
|
54378
|
+
retry: {
|
|
54379
|
+
$ref: "#/$defs/retryConfig"
|
|
54380
|
+
},
|
|
54381
|
+
input: {
|
|
54382
|
+
$ref: "#/$defs/participantInput"
|
|
54383
|
+
},
|
|
54384
|
+
output: {
|
|
54385
|
+
$ref: "#/$defs/participantOutputSchema"
|
|
54386
|
+
},
|
|
54387
|
+
run: { type: "string" },
|
|
54388
|
+
cwd: { type: "string" },
|
|
54389
|
+
url: { type: "string" },
|
|
54390
|
+
method: { type: "string", enum: ["GET", "POST", "PUT", "PATCH", "DELETE"] },
|
|
54391
|
+
headers: { type: "object", additionalProperties: { type: "string" } },
|
|
54392
|
+
body: { oneOf: [{ type: "string" }, { type: "object" }] },
|
|
54393
|
+
path: { type: "string" },
|
|
54394
|
+
server: { type: "string" },
|
|
54395
|
+
tool: { type: "string" },
|
|
54396
|
+
event: { type: "string" },
|
|
54397
|
+
payload: { $ref: "#/$defs/payload" },
|
|
54398
|
+
ack: { type: "boolean" }
|
|
54399
|
+
},
|
|
54400
|
+
additionalProperties: false
|
|
54401
|
+
},
|
|
54402
|
+
flowSequence: {
|
|
54403
|
+
type: "array",
|
|
54404
|
+
description: "Ordered list of flow steps. Each step's output is implicitly chained as input to the next step.",
|
|
54405
|
+
minItems: 1,
|
|
54406
|
+
items: {
|
|
54407
|
+
$ref: "#/$defs/flowStep"
|
|
54408
|
+
}
|
|
54409
|
+
},
|
|
54410
|
+
flowStep: {
|
|
54411
|
+
description: "A single step in the flow: participant reference (string), control construct, inline participant (named or anonymous), or participant override.",
|
|
54412
|
+
oneOf: [
|
|
54413
|
+
{
|
|
54414
|
+
type: "string",
|
|
54415
|
+
description: "Simple participant reference by name."
|
|
54416
|
+
},
|
|
54417
|
+
{ $ref: "#/$defs/loopStep" },
|
|
54418
|
+
{ $ref: "#/$defs/parallelStep" },
|
|
54419
|
+
{ $ref: "#/$defs/ifStep" },
|
|
54420
|
+
{ $ref: "#/$defs/setStep" },
|
|
54421
|
+
{ $ref: "#/$defs/waitStep" },
|
|
54422
|
+
{ $ref: "#/$defs/inlineParticipant" },
|
|
54423
|
+
{ $ref: "#/$defs/participantOverrideStep" }
|
|
54424
|
+
]
|
|
54425
|
+
},
|
|
54426
|
+
loopStep: {
|
|
54427
|
+
type: "object",
|
|
54428
|
+
required: ["loop"],
|
|
54429
|
+
additionalProperties: false,
|
|
54430
|
+
properties: {
|
|
54431
|
+
loop: {
|
|
54432
|
+
type: "object",
|
|
54433
|
+
additionalProperties: false,
|
|
54434
|
+
required: ["steps"],
|
|
54435
|
+
properties: {
|
|
54436
|
+
as: {
|
|
54437
|
+
type: "string",
|
|
54438
|
+
description: "Renames the loop context variable. Access as <as>.index, <as>.iteration, etc. instead of loop.*"
|
|
54439
|
+
},
|
|
54440
|
+
until: {
|
|
54441
|
+
$ref: "#/$defs/celExpression",
|
|
54442
|
+
description: "CEL condition to break out of the loop."
|
|
54443
|
+
},
|
|
54444
|
+
max: {
|
|
54445
|
+
description: "Maximum iterations. Integer or CEL expression.",
|
|
54446
|
+
oneOf: [
|
|
54447
|
+
{ type: "integer", minimum: 1 },
|
|
54448
|
+
{ type: "string" }
|
|
54449
|
+
]
|
|
54450
|
+
},
|
|
54451
|
+
steps: {
|
|
54452
|
+
$ref: "#/$defs/flowSequence"
|
|
54453
|
+
}
|
|
54454
|
+
},
|
|
54455
|
+
anyOf: [
|
|
54456
|
+
{ required: ["until"] },
|
|
54457
|
+
{ required: ["max"] }
|
|
54458
|
+
]
|
|
54459
|
+
}
|
|
54460
|
+
}
|
|
54461
|
+
},
|
|
54462
|
+
parallelStep: {
|
|
54463
|
+
type: "object",
|
|
54464
|
+
required: ["parallel"],
|
|
54465
|
+
additionalProperties: false,
|
|
54466
|
+
properties: {
|
|
54467
|
+
parallel: {
|
|
54468
|
+
$ref: "#/$defs/flowSequence",
|
|
54469
|
+
description: "Steps to run concurrently. The chained output after a parallel block is an array of all branch outputs in declaration order."
|
|
54470
|
+
}
|
|
54471
|
+
}
|
|
54472
|
+
},
|
|
54473
|
+
ifStep: {
|
|
54474
|
+
type: "object",
|
|
54475
|
+
required: ["if"],
|
|
54476
|
+
additionalProperties: false,
|
|
54477
|
+
properties: {
|
|
54478
|
+
if: {
|
|
54479
|
+
type: "object",
|
|
54480
|
+
required: ["condition", "then"],
|
|
54481
|
+
additionalProperties: false,
|
|
54482
|
+
properties: {
|
|
54483
|
+
condition: {
|
|
54484
|
+
$ref: "#/$defs/celExpression",
|
|
54485
|
+
description: "CEL expression that determines which branch to take."
|
|
54486
|
+
},
|
|
54487
|
+
then: {
|
|
54488
|
+
$ref: "#/$defs/flowSequence"
|
|
54489
|
+
},
|
|
54490
|
+
else: {
|
|
54491
|
+
$ref: "#/$defs/flowSequence"
|
|
54492
|
+
}
|
|
54493
|
+
}
|
|
54494
|
+
}
|
|
54495
|
+
}
|
|
54496
|
+
},
|
|
54497
|
+
setStep: {
|
|
54498
|
+
type: "object",
|
|
54499
|
+
required: ["set"],
|
|
54500
|
+
additionalProperties: false,
|
|
54501
|
+
properties: {
|
|
54502
|
+
set: {
|
|
54503
|
+
type: "object",
|
|
54504
|
+
description: "Writes values into execution.context. Each key becomes execution.context.<key>. Values are CEL expressions.",
|
|
54505
|
+
minProperties: 1,
|
|
54506
|
+
additionalProperties: {
|
|
54507
|
+
$ref: "#/$defs/celExpression"
|
|
54508
|
+
},
|
|
54509
|
+
not: {
|
|
54510
|
+
anyOf: [
|
|
54511
|
+
{ required: ["workflow"] },
|
|
54512
|
+
{ required: ["execution"] },
|
|
54513
|
+
{ required: ["input"] },
|
|
54514
|
+
{ required: ["output"] },
|
|
54515
|
+
{ required: ["env"] },
|
|
54516
|
+
{ required: ["loop"] },
|
|
54517
|
+
{ required: ["event"] }
|
|
54518
|
+
]
|
|
54519
|
+
}
|
|
54520
|
+
}
|
|
54521
|
+
}
|
|
54522
|
+
},
|
|
54523
|
+
waitStep: {
|
|
54524
|
+
type: "object",
|
|
54525
|
+
required: ["wait"],
|
|
54526
|
+
additionalProperties: false,
|
|
54527
|
+
properties: {
|
|
54528
|
+
wait: {
|
|
54529
|
+
type: "object",
|
|
54530
|
+
additionalProperties: false,
|
|
54531
|
+
properties: {
|
|
54532
|
+
event: {
|
|
54533
|
+
type: "string",
|
|
54534
|
+
description: "Event name to wait for (event mode)."
|
|
54535
|
+
},
|
|
54536
|
+
match: {
|
|
54537
|
+
$ref: "#/$defs/celExpression",
|
|
54538
|
+
description: "CEL condition to match against event payload. 'event' variable contains the payload."
|
|
54539
|
+
},
|
|
54540
|
+
until: {
|
|
54541
|
+
$ref: "#/$defs/celExpression",
|
|
54542
|
+
description: "CEL condition to wait for (polling mode)."
|
|
54543
|
+
},
|
|
54544
|
+
poll: {
|
|
54545
|
+
$ref: "#/$defs/duration",
|
|
54546
|
+
description: "Polling interval for 'until' condition. Default: runtime decides."
|
|
54547
|
+
},
|
|
54548
|
+
timeout: {
|
|
54549
|
+
$ref: "#/$defs/duration",
|
|
54550
|
+
description: "Maximum wait time."
|
|
54551
|
+
},
|
|
54552
|
+
onTimeout: {
|
|
54553
|
+
$ref: "#/$defs/onTimeout",
|
|
54554
|
+
description: "Strategy when timeout is reached: 'fail' (default), 'skip', or participant name."
|
|
54555
|
+
}
|
|
54556
|
+
}
|
|
54557
|
+
}
|
|
54558
|
+
}
|
|
54559
|
+
},
|
|
54560
|
+
participantOverrideStep: {
|
|
54561
|
+
type: "object",
|
|
54562
|
+
description: "A participant reference with flow-level overrides (timeout, onError, when, input, workflow, etc.).",
|
|
54563
|
+
minProperties: 1,
|
|
54564
|
+
maxProperties: 1,
|
|
54565
|
+
not: {
|
|
54566
|
+
anyOf: [
|
|
54567
|
+
{ required: ["loop"] },
|
|
54568
|
+
{ required: ["parallel"] },
|
|
54569
|
+
{ required: ["if"] },
|
|
54570
|
+
{ required: ["wait"] },
|
|
54571
|
+
{ required: ["set"] },
|
|
54572
|
+
{ required: ["type"] }
|
|
54573
|
+
]
|
|
54574
|
+
},
|
|
54575
|
+
additionalProperties: {
|
|
54576
|
+
type: "object",
|
|
54577
|
+
properties: {
|
|
54578
|
+
when: {
|
|
54579
|
+
$ref: "#/$defs/celExpression",
|
|
54580
|
+
description: "Guard condition. If false, step is skipped."
|
|
54581
|
+
},
|
|
54582
|
+
timeout: {
|
|
54583
|
+
$ref: "#/$defs/duration"
|
|
54584
|
+
},
|
|
54585
|
+
onError: {
|
|
54586
|
+
$ref: "#/$defs/onError"
|
|
54587
|
+
},
|
|
54588
|
+
retry: {
|
|
54589
|
+
$ref: "#/$defs/retryConfig"
|
|
54590
|
+
},
|
|
54591
|
+
input: {
|
|
54592
|
+
$ref: "#/$defs/participantInput"
|
|
54593
|
+
},
|
|
54594
|
+
workflow: {
|
|
54595
|
+
type: "string",
|
|
54596
|
+
description: "Inline sub-workflow path (alternative to defining as participant)."
|
|
54597
|
+
}
|
|
54598
|
+
},
|
|
54599
|
+
additionalProperties: false
|
|
54600
|
+
}
|
|
54601
|
+
},
|
|
54602
|
+
workflowOutput: {
|
|
54603
|
+
description: "Workflow output. Accessed in CEL as workflow.output. String (single CEL expression), object (structured mapping), or object with schema+map.",
|
|
54604
|
+
oneOf: [
|
|
54605
|
+
{
|
|
54606
|
+
type: "string",
|
|
54607
|
+
description: "Single CEL expression mapping."
|
|
54608
|
+
},
|
|
54609
|
+
{
|
|
54610
|
+
type: "object",
|
|
54611
|
+
description: "Structured output mapping (key → CEL expression) or schema+map.",
|
|
54612
|
+
properties: {
|
|
54613
|
+
schema: {
|
|
54614
|
+
type: "object",
|
|
54615
|
+
additionalProperties: {
|
|
54616
|
+
$ref: "#/$defs/inputField"
|
|
54617
|
+
}
|
|
54618
|
+
},
|
|
54619
|
+
map: {
|
|
54620
|
+
type: "object",
|
|
54621
|
+
additionalProperties: {
|
|
54622
|
+
type: "string"
|
|
54623
|
+
}
|
|
54624
|
+
}
|
|
54625
|
+
},
|
|
54626
|
+
additionalProperties: {
|
|
54627
|
+
type: "string"
|
|
54628
|
+
}
|
|
54629
|
+
}
|
|
54630
|
+
]
|
|
54631
|
+
}
|
|
54632
|
+
}
|
|
54633
|
+
};
|
|
54634
|
+
});
|
|
53309
54635
|
function validateSchema2(workflow) {
|
|
53310
54636
|
const valid = validate2(workflow);
|
|
53311
54637
|
if (valid) {
|
|
@@ -53319,15 +54645,14 @@ function validateSchema2(workflow) {
|
|
|
53319
54645
|
}
|
|
53320
54646
|
var import__20202;
|
|
53321
54647
|
var import_ajv_formats2;
|
|
53322
|
-
var rawSchema2;
|
|
53323
54648
|
var schema2;
|
|
53324
54649
|
var ajv2;
|
|
53325
54650
|
var validate2;
|
|
53326
54651
|
var init_schema2 = __esm3(() => {
|
|
54652
|
+
init_duckflux_schema2();
|
|
53327
54653
|
import__20202 = __toESM2(require_20202(), 1);
|
|
53328
54654
|
import_ajv_formats2 = __toESM2(require_dist22(), 1);
|
|
53329
|
-
|
|
53330
|
-
schema2 = JSON.parse(rawSchema2);
|
|
54655
|
+
schema2 = { ...duckflux_schema_default2 };
|
|
53331
54656
|
delete schema2.$schema;
|
|
53332
54657
|
ajv2 = new import__20202.default({ allErrors: true, strict: false });
|
|
53333
54658
|
import_ajv_formats2.default(ajv2);
|
|
@@ -53711,7 +55036,7 @@ async function validateSemantic2(workflow, basePath) {
|
|
|
53711
55036
|
for (const [name, participant] of Object.entries(participants)) {
|
|
53712
55037
|
if (participant.type !== "workflow")
|
|
53713
55038
|
continue;
|
|
53714
|
-
const resolvedPath =
|
|
55039
|
+
const resolvedPath = resolve3(basePath, participant.path);
|
|
53715
55040
|
const exists = await access2(resolvedPath, constants2.F_OK).then(() => true, () => false);
|
|
53716
55041
|
if (!exists) {
|
|
53717
55042
|
errors.push({
|
|
@@ -53729,6 +55054,237 @@ var init_validate2 = __esm3(() => {
|
|
|
53729
55054
|
RESERVED_NAMES2 = new Set(["workflow", "execution", "input", "output", "env", "loop", "event"]);
|
|
53730
55055
|
BUILTIN_ONERROR2 = new Set(["fail", "skip", "retry"]);
|
|
53731
55056
|
});
|
|
55057
|
+
var exports_json2 = {};
|
|
55058
|
+
__export3(exports_json2, {
|
|
55059
|
+
JsonTraceWriter: () => JsonTraceWriter2
|
|
55060
|
+
});
|
|
55061
|
+
|
|
55062
|
+
class JsonTraceWriter2 {
|
|
55063
|
+
dir;
|
|
55064
|
+
filePath = "";
|
|
55065
|
+
trace = {
|
|
55066
|
+
execution: {
|
|
55067
|
+
id: "",
|
|
55068
|
+
startedAt: "",
|
|
55069
|
+
finishedAt: "",
|
|
55070
|
+
duration: 0,
|
|
55071
|
+
status: "running",
|
|
55072
|
+
inputs: null,
|
|
55073
|
+
output: null
|
|
55074
|
+
},
|
|
55075
|
+
steps: []
|
|
55076
|
+
};
|
|
55077
|
+
constructor(dir) {
|
|
55078
|
+
this.dir = dir;
|
|
55079
|
+
}
|
|
55080
|
+
async open(meta) {
|
|
55081
|
+
this.filePath = join4(this.dir, `${meta.id}.json`);
|
|
55082
|
+
this.trace = {
|
|
55083
|
+
execution: {
|
|
55084
|
+
id: meta.id,
|
|
55085
|
+
workflowId: meta.workflowId,
|
|
55086
|
+
workflowName: meta.workflowName,
|
|
55087
|
+
workflowVersion: meta.workflowVersion,
|
|
55088
|
+
startedAt: meta.startedAt,
|
|
55089
|
+
finishedAt: "",
|
|
55090
|
+
duration: 0,
|
|
55091
|
+
status: "running",
|
|
55092
|
+
inputs: meta.inputs,
|
|
55093
|
+
output: null
|
|
55094
|
+
},
|
|
55095
|
+
steps: []
|
|
55096
|
+
};
|
|
55097
|
+
await this.flush();
|
|
55098
|
+
}
|
|
55099
|
+
writeStep(step) {
|
|
55100
|
+
this.trace.steps.push(step);
|
|
55101
|
+
this.flushSync();
|
|
55102
|
+
}
|
|
55103
|
+
async finalize(meta) {
|
|
55104
|
+
this.trace.execution.status = meta.status;
|
|
55105
|
+
this.trace.execution.output = meta.output;
|
|
55106
|
+
this.trace.execution.finishedAt = meta.finishedAt;
|
|
55107
|
+
this.trace.execution.duration = meta.duration;
|
|
55108
|
+
await this.flush();
|
|
55109
|
+
}
|
|
55110
|
+
flushSync() {
|
|
55111
|
+
this.flush().catch(() => {});
|
|
55112
|
+
}
|
|
55113
|
+
async flush() {
|
|
55114
|
+
if (!this.filePath)
|
|
55115
|
+
return;
|
|
55116
|
+
await writeFile3(this.filePath, JSON.stringify(this.trace, null, 2), "utf-8");
|
|
55117
|
+
}
|
|
55118
|
+
}
|
|
55119
|
+
var init_json = () => {};
|
|
55120
|
+
var exports_txt2 = {};
|
|
55121
|
+
__export3(exports_txt2, {
|
|
55122
|
+
TxtTraceWriter: () => TxtTraceWriter2
|
|
55123
|
+
});
|
|
55124
|
+
function serializeValue2(value) {
|
|
55125
|
+
if (value === undefined || value === null)
|
|
55126
|
+
return "none";
|
|
55127
|
+
if (typeof value === "string")
|
|
55128
|
+
return value;
|
|
55129
|
+
return JSON.stringify(value, null, 2);
|
|
55130
|
+
}
|
|
55131
|
+
function formatStep2(step) {
|
|
55132
|
+
const lines = [
|
|
55133
|
+
`## [${step.seq}] ${step.name} (${step.type})`,
|
|
55134
|
+
`startedAt: ${step.startedAt}`
|
|
55135
|
+
];
|
|
55136
|
+
if (step.finishedAt)
|
|
55137
|
+
lines.push(`finishedAt: ${step.finishedAt}`);
|
|
55138
|
+
if (step.duration !== undefined)
|
|
55139
|
+
lines.push(`duration: ${step.duration}ms`);
|
|
55140
|
+
lines.push(`status: ${step.status}`);
|
|
55141
|
+
if (step.loopIndex !== undefined)
|
|
55142
|
+
lines.push(`loopIndex: ${step.loopIndex}`);
|
|
55143
|
+
if (step.retries !== undefined && step.retries > 0)
|
|
55144
|
+
lines.push(`retries: ${step.retries}`);
|
|
55145
|
+
lines.push(`input: ${serializeValue2(step.input)}`);
|
|
55146
|
+
lines.push(`output: ${serializeValue2(step.output)}`);
|
|
55147
|
+
if (step.error)
|
|
55148
|
+
lines.push(`error: ${step.error}`);
|
|
55149
|
+
lines.push("");
|
|
55150
|
+
return lines.join(`
|
|
55151
|
+
`);
|
|
55152
|
+
}
|
|
55153
|
+
|
|
55154
|
+
class TxtTraceWriter2 {
|
|
55155
|
+
dir;
|
|
55156
|
+
filePath = "";
|
|
55157
|
+
constructor(dir) {
|
|
55158
|
+
this.dir = dir;
|
|
55159
|
+
}
|
|
55160
|
+
async open(meta) {
|
|
55161
|
+
this.filePath = join22(this.dir, `${meta.id}.txt`);
|
|
55162
|
+
const versionStr = meta.workflowVersion !== undefined ? ` (v${meta.workflowVersion})` : "";
|
|
55163
|
+
const workflowLabel = meta.workflowName ?? meta.workflowId ?? "unnamed";
|
|
55164
|
+
const header = [
|
|
55165
|
+
"# execution",
|
|
55166
|
+
`id: ${meta.id}`,
|
|
55167
|
+
`workflow: ${workflowLabel}${versionStr}`,
|
|
55168
|
+
`startedAt: ${meta.startedAt}`,
|
|
55169
|
+
"status: running",
|
|
55170
|
+
"",
|
|
55171
|
+
"# inputs",
|
|
55172
|
+
serializeValue2(meta.inputs),
|
|
55173
|
+
"",
|
|
55174
|
+
"# steps",
|
|
55175
|
+
""
|
|
55176
|
+
].join(`
|
|
55177
|
+
`);
|
|
55178
|
+
await writeFile22(this.filePath, header, "utf-8");
|
|
55179
|
+
}
|
|
55180
|
+
async writeStep(step) {
|
|
55181
|
+
if (!this.filePath)
|
|
55182
|
+
return;
|
|
55183
|
+
await appendFile2(this.filePath, formatStep2(step), "utf-8");
|
|
55184
|
+
}
|
|
55185
|
+
async finalize(meta) {
|
|
55186
|
+
if (!this.filePath)
|
|
55187
|
+
return;
|
|
55188
|
+
const outputSection = [
|
|
55189
|
+
"# output",
|
|
55190
|
+
serializeValue2(meta.output),
|
|
55191
|
+
""
|
|
55192
|
+
].join(`
|
|
55193
|
+
`);
|
|
55194
|
+
await appendFile2(this.filePath, outputSection, "utf-8");
|
|
55195
|
+
const content = await readFile22(this.filePath, "utf-8");
|
|
55196
|
+
const updated = content.replace(/^status: running$/m, `status: ${meta.status}
|
|
55197
|
+
finishedAt: ${meta.finishedAt}
|
|
55198
|
+
duration: ${meta.duration}ms`);
|
|
55199
|
+
await writeFile22(this.filePath, updated, "utf-8");
|
|
55200
|
+
}
|
|
55201
|
+
}
|
|
55202
|
+
var init_txt = () => {};
|
|
55203
|
+
var exports_sqlite2 = {};
|
|
55204
|
+
__export3(exports_sqlite2, {
|
|
55205
|
+
SqliteTraceWriter: () => SqliteTraceWriter2
|
|
55206
|
+
});
|
|
55207
|
+
function toJson2(value) {
|
|
55208
|
+
if (value === undefined || value === null)
|
|
55209
|
+
return null;
|
|
55210
|
+
if (typeof value === "string")
|
|
55211
|
+
return value;
|
|
55212
|
+
return JSON.stringify(value);
|
|
55213
|
+
}
|
|
55214
|
+
|
|
55215
|
+
class SqliteTraceWriter2 {
|
|
55216
|
+
dir;
|
|
55217
|
+
db = null;
|
|
55218
|
+
executionId = "";
|
|
55219
|
+
constructor(dir) {
|
|
55220
|
+
this.dir = dir;
|
|
55221
|
+
}
|
|
55222
|
+
async open(meta) {
|
|
55223
|
+
this.executionId = meta.id;
|
|
55224
|
+
const filePath = join32(this.dir, `${meta.id}.sqlite`);
|
|
55225
|
+
const { Database } = await import("bun:sqlite");
|
|
55226
|
+
this.db = new Database(filePath);
|
|
55227
|
+
this.db.exec(`
|
|
55228
|
+
CREATE TABLE IF NOT EXISTS executions (
|
|
55229
|
+
id TEXT PRIMARY KEY,
|
|
55230
|
+
workflow_id TEXT,
|
|
55231
|
+
workflow_name TEXT,
|
|
55232
|
+
workflow_version TEXT,
|
|
55233
|
+
started_at TEXT NOT NULL,
|
|
55234
|
+
finished_at TEXT,
|
|
55235
|
+
duration_ms INTEGER,
|
|
55236
|
+
status TEXT NOT NULL,
|
|
55237
|
+
inputs TEXT,
|
|
55238
|
+
output TEXT
|
|
55239
|
+
);
|
|
55240
|
+
|
|
55241
|
+
CREATE TABLE IF NOT EXISTS steps (
|
|
55242
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
55243
|
+
execution_id TEXT NOT NULL REFERENCES executions(id),
|
|
55244
|
+
seq INTEGER NOT NULL,
|
|
55245
|
+
name TEXT NOT NULL,
|
|
55246
|
+
type TEXT NOT NULL,
|
|
55247
|
+
started_at TEXT,
|
|
55248
|
+
finished_at TEXT,
|
|
55249
|
+
duration_ms INTEGER,
|
|
55250
|
+
status TEXT NOT NULL,
|
|
55251
|
+
input TEXT,
|
|
55252
|
+
output TEXT,
|
|
55253
|
+
error TEXT,
|
|
55254
|
+
retries INTEGER,
|
|
55255
|
+
loop_index INTEGER
|
|
55256
|
+
);
|
|
55257
|
+
`);
|
|
55258
|
+
const insert = this.db.prepare(`
|
|
55259
|
+
INSERT INTO executions (id, workflow_id, workflow_name, workflow_version, started_at, status, inputs)
|
|
55260
|
+
VALUES (?, ?, ?, ?, ?, 'running', ?)
|
|
55261
|
+
`);
|
|
55262
|
+
insert.run(meta.id, meta.workflowId ?? null, meta.workflowName ?? null, meta.workflowVersion !== undefined ? String(meta.workflowVersion) : null, meta.startedAt, toJson2(meta.inputs));
|
|
55263
|
+
}
|
|
55264
|
+
writeStep(step) {
|
|
55265
|
+
if (!this.db)
|
|
55266
|
+
return;
|
|
55267
|
+
const insert = this.db.prepare(`
|
|
55268
|
+
INSERT INTO steps
|
|
55269
|
+
(execution_id, seq, name, type, started_at, finished_at, duration_ms, status, input, output, error, retries, loop_index)
|
|
55270
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
55271
|
+
`);
|
|
55272
|
+
insert.run(this.executionId, step.seq, step.name, step.type, step.startedAt ?? null, step.finishedAt ?? null, step.duration ?? null, step.status, toJson2(step.input), toJson2(step.output), step.error ?? null, step.retries ?? null, step.loopIndex ?? null);
|
|
55273
|
+
}
|
|
55274
|
+
async finalize(meta) {
|
|
55275
|
+
if (!this.db)
|
|
55276
|
+
return;
|
|
55277
|
+
const update = this.db.prepare(`
|
|
55278
|
+
UPDATE executions
|
|
55279
|
+
SET status = ?, output = ?, finished_at = ?, duration_ms = ?
|
|
55280
|
+
WHERE id = ?
|
|
55281
|
+
`);
|
|
55282
|
+
update.run(meta.status, toJson2(meta.output), meta.finishedAt, Math.round(meta.duration), this.executionId);
|
|
55283
|
+
this.db.close();
|
|
55284
|
+
this.db = null;
|
|
55285
|
+
}
|
|
55286
|
+
}
|
|
55287
|
+
var init_sqlite = () => {};
|
|
53732
55288
|
function sleep3(ms) {
|
|
53733
55289
|
return new Promise((resolve23) => setTimeout(resolve23, ms));
|
|
53734
55290
|
}
|
|
@@ -54020,7 +55576,7 @@ async function executeHttp2(participant, input) {
|
|
|
54020
55576
|
};
|
|
54021
55577
|
}
|
|
54022
55578
|
async function executeMcp2(participant, _input) {
|
|
54023
|
-
throw new Error(`mcp participant is not yet implemented (server: ${participant.server ?? "unspecified"}, tool: ${participant.tool ?? "unspecified"}).
|
|
55579
|
+
throw new Error(`mcp participant is not yet implemented (server: ${participant.server ?? "unspecified"}, tool: ${participant.tool ?? "unspecified"}). Use onError to handle this gracefully.`);
|
|
54024
55580
|
}
|
|
54025
55581
|
function toWorkflowInputs2(input) {
|
|
54026
55582
|
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
@@ -54306,6 +55862,10 @@ async function executeStep2(workflow, state, step, basePath = process.cwd(), eng
|
|
|
54306
55862
|
output: "",
|
|
54307
55863
|
duration: 0
|
|
54308
55864
|
});
|
|
55865
|
+
const loopIndex2 = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
55866
|
+
const skippedSeq = state.tracer?.startStep(stepName, participant.type, undefined, loopIndex2);
|
|
55867
|
+
if (skippedSeq !== undefined)
|
|
55868
|
+
state.tracer?.endStep(skippedSeq, "skipped");
|
|
54309
55869
|
}
|
|
54310
55870
|
return chain;
|
|
54311
55871
|
}
|
|
@@ -54314,6 +55874,8 @@ async function executeStep2(workflow, state, step, basePath = process.cwd(), eng
|
|
|
54314
55874
|
const overrideInput = override?.input !== undefined ? resolveParticipantInput2(override.input, state) : undefined;
|
|
54315
55875
|
const mergedWithBase = mergeChainedInput2(chain, baseInput);
|
|
54316
55876
|
const mergedInput = mergeChainedInput2(mergedWithBase, overrideInput);
|
|
55877
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
55878
|
+
const traceSeq = state.tracer?.startStep(stepName ?? "<anonymous>", participant.type, mergedInput, loopIndex);
|
|
54317
55879
|
state.currentInput = mergedInput;
|
|
54318
55880
|
const strategy = resolveErrorStrategy2(override ?? null, participant, workflow.defaults ?? null);
|
|
54319
55881
|
const timeoutMs = resolveTimeout2(override ?? null, participant, workflow.defaults ?? null);
|
|
@@ -54391,6 +55953,8 @@ async function executeStep2(workflow, state, step, basePath = process.cwd(), eng
|
|
|
54391
55953
|
}
|
|
54392
55954
|
const outputValue = result.parsedOutput ?? result.output;
|
|
54393
55955
|
state.currentOutput = outputValue;
|
|
55956
|
+
if (traceSeq !== undefined)
|
|
55957
|
+
state.tracer?.endStep(traceSeq, result.status, outputValue, undefined, retries);
|
|
54394
55958
|
return outputValue;
|
|
54395
55959
|
} catch (error) {
|
|
54396
55960
|
const message = String(error?.message ?? error);
|
|
@@ -54416,6 +55980,8 @@ async function executeStep2(workflow, state, step, basePath = process.cwd(), eng
|
|
|
54416
55980
|
if (stepName) {
|
|
54417
55981
|
state.setResult(stepName, skipResult);
|
|
54418
55982
|
}
|
|
55983
|
+
if (traceSeq !== undefined)
|
|
55984
|
+
state.tracer?.endStep(traceSeq, "skipped", undefined, message);
|
|
54419
55985
|
return chain;
|
|
54420
55986
|
}
|
|
54421
55987
|
if (strategy !== "fail" && strategy !== "retry") {
|
|
@@ -54434,6 +56000,8 @@ async function executeStep2(workflow, state, step, basePath = process.cwd(), eng
|
|
|
54434
56000
|
...httpMeta
|
|
54435
56001
|
});
|
|
54436
56002
|
}
|
|
56003
|
+
if (traceSeq !== undefined)
|
|
56004
|
+
state.tracer?.endStep(traceSeq, "failure", undefined, message);
|
|
54437
56005
|
const fallbackResult = await executeStep2(workflow, state, fallbackName, basePath, engineExecutor, [...fallbackStack, stepName ?? "<anonymous>"], chain, hub);
|
|
54438
56006
|
return fallbackResult;
|
|
54439
56007
|
}
|
|
@@ -54448,6 +56016,8 @@ async function executeStep2(workflow, state, step, basePath = process.cwd(), eng
|
|
|
54448
56016
|
...httpMeta
|
|
54449
56017
|
});
|
|
54450
56018
|
}
|
|
56019
|
+
if (traceSeq !== undefined)
|
|
56020
|
+
state.tracer?.endStep(traceSeq, "failure", undefined, message);
|
|
54451
56021
|
throw error;
|
|
54452
56022
|
}
|
|
54453
56023
|
}
|
|
@@ -54470,7 +56040,7 @@ __export3(exports_wait2, {
|
|
|
54470
56040
|
executeWait: () => executeWait2
|
|
54471
56041
|
});
|
|
54472
56042
|
function sleep22(ms) {
|
|
54473
|
-
return new Promise((
|
|
56043
|
+
return new Promise((resolve33) => setTimeout(resolve33, ms));
|
|
54474
56044
|
}
|
|
54475
56045
|
async function executeWait2(state, waitDef, chain, hub, signal) {
|
|
54476
56046
|
const timeoutMs = waitDef.timeout ? parseDuration2(waitDef.timeout) : undefined;
|
|
@@ -54556,21 +56126,38 @@ async function executeControlStep2(workflow, state, step, basePath = process.cwd
|
|
|
54556
56126
|
}
|
|
54557
56127
|
const obj = step;
|
|
54558
56128
|
if ("wait" in obj && Object.keys(obj).length === 1) {
|
|
54559
|
-
const
|
|
54560
|
-
|
|
56129
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
56130
|
+
const traceSeq = state.tracer?.startStep("wait", "wait", undefined, loopIndex);
|
|
56131
|
+
try {
|
|
56132
|
+
const { executeWait: executeWait22 } = await Promise.resolve().then(() => (init_wait2(), exports_wait2));
|
|
56133
|
+
const result = await executeWait22(state, obj.wait, chain, hub, signal);
|
|
56134
|
+
if (traceSeq !== undefined)
|
|
56135
|
+
state.tracer?.endStep(traceSeq, "success", result);
|
|
56136
|
+
return result;
|
|
56137
|
+
} catch (err) {
|
|
56138
|
+
if (traceSeq !== undefined)
|
|
56139
|
+
state.tracer?.endStep(traceSeq, "failure", undefined, String(err?.message ?? err));
|
|
56140
|
+
throw err;
|
|
56141
|
+
}
|
|
54561
56142
|
}
|
|
54562
56143
|
if ("set" in obj && Object.keys(obj).length === 1) {
|
|
54563
56144
|
const setDef = obj.set;
|
|
54564
56145
|
const ctx = state.toCelContext();
|
|
56146
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
56147
|
+
const traceSeq = state.tracer?.startStep("set", "set", setDef, loopIndex);
|
|
54565
56148
|
if (!state.executionMeta.context) {
|
|
54566
56149
|
state.executionMeta.context = {};
|
|
54567
56150
|
}
|
|
54568
56151
|
for (const [key, expr] of Object.entries(setDef)) {
|
|
54569
56152
|
if (RESERVED_SET_KEYS2.has(key)) {
|
|
56153
|
+
if (traceSeq !== undefined)
|
|
56154
|
+
state.tracer?.endStep(traceSeq, "failure", undefined, `set key '${key}' uses a reserved name`);
|
|
54570
56155
|
throw new Error(`set key '${key}' uses a reserved name`);
|
|
54571
56156
|
}
|
|
54572
56157
|
state.executionMeta.context[key] = evaluateCel2(expr, ctx);
|
|
54573
56158
|
}
|
|
56159
|
+
if (traceSeq !== undefined)
|
|
56160
|
+
state.tracer?.endStep(traceSeq, "success", state.executionMeta.context);
|
|
54574
56161
|
return chain;
|
|
54575
56162
|
}
|
|
54576
56163
|
if ("loop" in obj && Object.keys(obj).length === 1) {
|
|
@@ -54587,6 +56174,8 @@ async function executeControlStep2(workflow, state, step, basePath = process.cwd
|
|
|
54587
56174
|
maxIterations = loopDef.max ?? Number.POSITIVE_INFINITY;
|
|
54588
56175
|
}
|
|
54589
56176
|
const hasMax = loopDef.max !== undefined;
|
|
56177
|
+
const outerLoopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
56178
|
+
const loopTraceSeq = state.tracer?.startStep(loopAs ?? "loop", "loop", undefined, outerLoopIndex);
|
|
54590
56179
|
state.pushLoop(loopAs);
|
|
54591
56180
|
let loopChain = chain;
|
|
54592
56181
|
try {
|
|
@@ -54610,6 +56199,12 @@ async function executeControlStep2(workflow, state, step, basePath = process.cwd
|
|
|
54610
56199
|
iterations += 1;
|
|
54611
56200
|
state.incrementLoop();
|
|
54612
56201
|
}
|
|
56202
|
+
if (loopTraceSeq !== undefined)
|
|
56203
|
+
state.tracer?.endStep(loopTraceSeq, "success", loopChain);
|
|
56204
|
+
} catch (err) {
|
|
56205
|
+
if (loopTraceSeq !== undefined)
|
|
56206
|
+
state.tracer?.endStep(loopTraceSeq, "failure", undefined, String(err?.message ?? err));
|
|
56207
|
+
throw err;
|
|
54613
56208
|
} finally {
|
|
54614
56209
|
state.popLoop();
|
|
54615
56210
|
}
|
|
@@ -54618,29 +56213,54 @@ async function executeControlStep2(workflow, state, step, basePath = process.cwd
|
|
|
54618
56213
|
if ("parallel" in obj && Object.keys(obj).length === 1) {
|
|
54619
56214
|
const parallelSteps = obj.parallel;
|
|
54620
56215
|
const controller = new AbortController;
|
|
56216
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
56217
|
+
const parallelTraceSeq = state.tracer?.startStep("parallel", "parallel", undefined, loopIndex);
|
|
54621
56218
|
const branchSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
|
|
54622
|
-
|
|
54623
|
-
|
|
54624
|
-
|
|
54625
|
-
|
|
54626
|
-
|
|
54627
|
-
|
|
54628
|
-
|
|
54629
|
-
|
|
54630
|
-
|
|
56219
|
+
try {
|
|
56220
|
+
const results = await Promise.all(parallelSteps.map(async (parallelStep) => {
|
|
56221
|
+
try {
|
|
56222
|
+
return await executeControlStep2(workflow, state, parallelStep, basePath, engineExecutor, chain, hub, branchSignal);
|
|
56223
|
+
} catch (error) {
|
|
56224
|
+
controller.abort();
|
|
56225
|
+
throw error;
|
|
56226
|
+
}
|
|
56227
|
+
}));
|
|
56228
|
+
if (parallelTraceSeq !== undefined)
|
|
56229
|
+
state.tracer?.endStep(parallelTraceSeq, "success", results);
|
|
56230
|
+
return results;
|
|
56231
|
+
} catch (err) {
|
|
56232
|
+
if (parallelTraceSeq !== undefined)
|
|
56233
|
+
state.tracer?.endStep(parallelTraceSeq, "failure", undefined, String(err?.message ?? err));
|
|
56234
|
+
throw err;
|
|
56235
|
+
}
|
|
54631
56236
|
}
|
|
54632
56237
|
if ("if" in obj && Object.keys(obj).length === 1) {
|
|
54633
56238
|
const ifDef = obj.if;
|
|
54634
56239
|
const condition = evaluateCel2(ifDef.condition, state.toCelContext());
|
|
56240
|
+
const loopIndex = state.isInsideLoop() ? state.currentLoopIndex() : undefined;
|
|
56241
|
+
const ifTraceSeq = state.tracer?.startStep("if", "if", { condition: ifDef.condition }, loopIndex);
|
|
54635
56242
|
if (typeof condition !== "boolean") {
|
|
56243
|
+
if (ifTraceSeq !== undefined)
|
|
56244
|
+
state.tracer?.endStep(ifTraceSeq, "failure", undefined, `if.condition must evaluate to boolean, got ${typeof condition}`);
|
|
54636
56245
|
throw new Error(`if.condition must evaluate to boolean, got ${typeof condition}`);
|
|
54637
56246
|
}
|
|
54638
|
-
|
|
54639
|
-
|
|
54640
|
-
|
|
54641
|
-
|
|
56247
|
+
try {
|
|
56248
|
+
let result;
|
|
56249
|
+
if (condition) {
|
|
56250
|
+
result = await executeSequential2(workflow, state, ifDef.then, basePath, engineExecutor, chain, hub, signal);
|
|
56251
|
+
} else if (ifDef.else) {
|
|
56252
|
+
result = await executeSequential2(workflow, state, ifDef.else, basePath, engineExecutor, chain, hub, signal);
|
|
56253
|
+
} else {
|
|
56254
|
+
result = chain;
|
|
56255
|
+
}
|
|
56256
|
+
if (ifTraceSeq !== undefined)
|
|
56257
|
+
state.tracer?.endStep(ifTraceSeq, "success", result);
|
|
56258
|
+
return result;
|
|
56259
|
+
} catch (err) {
|
|
56260
|
+
if (ifTraceSeq !== undefined)
|
|
56261
|
+
state.tracer?.endStep(ifTraceSeq, "failure", undefined, String(err?.message ?? err));
|
|
56262
|
+
throw err;
|
|
54642
56263
|
}
|
|
54643
|
-
return chain;
|
|
54644
56264
|
}
|
|
54645
56265
|
return executeStep2(workflow, state, step, basePath, engineExecutor, [], chain, hub, signal);
|
|
54646
56266
|
}
|
|
@@ -54650,92 +56270,7 @@ var init_control2 = __esm3(() => {
|
|
|
54650
56270
|
init_sequential2();
|
|
54651
56271
|
RESERVED_SET_KEYS2 = new Set(["workflow", "execution", "input", "output", "env", "loop", "event"]);
|
|
54652
56272
|
});
|
|
54653
|
-
|
|
54654
|
-
class MemoryHub2 {
|
|
54655
|
-
listeners = new Map;
|
|
54656
|
-
buffer = new Map;
|
|
54657
|
-
closed = false;
|
|
54658
|
-
async publish(event, payload) {
|
|
54659
|
-
if (this.closed)
|
|
54660
|
-
throw new Error("hub is closed");
|
|
54661
|
-
const envelope = { name: event, payload };
|
|
54662
|
-
let buf = this.buffer.get(event);
|
|
54663
|
-
if (!buf) {
|
|
54664
|
-
buf = [];
|
|
54665
|
-
this.buffer.set(event, buf);
|
|
54666
|
-
}
|
|
54667
|
-
buf.push(envelope);
|
|
54668
|
-
const listeners = this.listeners.get(event);
|
|
54669
|
-
if (listeners) {
|
|
54670
|
-
for (const listener of listeners) {
|
|
54671
|
-
listener(envelope);
|
|
54672
|
-
}
|
|
54673
|
-
}
|
|
54674
|
-
}
|
|
54675
|
-
async publishAndWaitAck(event, payload, _timeoutMs) {
|
|
54676
|
-
await this.publish(event, payload);
|
|
54677
|
-
}
|
|
54678
|
-
async* subscribe(event, signal) {
|
|
54679
|
-
if (this.closed)
|
|
54680
|
-
return;
|
|
54681
|
-
const buffered = this.buffer.get(event);
|
|
54682
|
-
if (buffered) {
|
|
54683
|
-
for (const envelope of buffered) {
|
|
54684
|
-
if (signal?.aborted)
|
|
54685
|
-
return;
|
|
54686
|
-
yield envelope;
|
|
54687
|
-
}
|
|
54688
|
-
}
|
|
54689
|
-
const queue = [];
|
|
54690
|
-
let resolve5 = null;
|
|
54691
|
-
const listener = (envelope) => {
|
|
54692
|
-
queue.push(envelope);
|
|
54693
|
-
if (resolve5) {
|
|
54694
|
-
resolve5();
|
|
54695
|
-
resolve5 = null;
|
|
54696
|
-
}
|
|
54697
|
-
};
|
|
54698
|
-
let listeners = this.listeners.get(event);
|
|
54699
|
-
if (!listeners) {
|
|
54700
|
-
listeners = new Set;
|
|
54701
|
-
this.listeners.set(event, listeners);
|
|
54702
|
-
}
|
|
54703
|
-
listeners.add(listener);
|
|
54704
|
-
const onAbort = () => {
|
|
54705
|
-
listeners.delete(listener);
|
|
54706
|
-
if (resolve5) {
|
|
54707
|
-
resolve5();
|
|
54708
|
-
resolve5 = null;
|
|
54709
|
-
}
|
|
54710
|
-
};
|
|
54711
|
-
if (signal) {
|
|
54712
|
-
signal.addEventListener("abort", onAbort);
|
|
54713
|
-
}
|
|
54714
|
-
try {
|
|
54715
|
-
while (!this.closed && !signal?.aborted) {
|
|
54716
|
-
if (queue.length > 0) {
|
|
54717
|
-
yield queue.shift();
|
|
54718
|
-
} else {
|
|
54719
|
-
await new Promise((r) => {
|
|
54720
|
-
resolve5 = r;
|
|
54721
|
-
});
|
|
54722
|
-
}
|
|
54723
|
-
}
|
|
54724
|
-
} finally {
|
|
54725
|
-
listeners.delete(listener);
|
|
54726
|
-
if (signal) {
|
|
54727
|
-
signal.removeEventListener("abort", onAbort);
|
|
54728
|
-
}
|
|
54729
|
-
}
|
|
54730
|
-
}
|
|
54731
|
-
async close() {
|
|
54732
|
-
this.closed = true;
|
|
54733
|
-
for (const listeners of this.listeners.values()) {
|
|
54734
|
-
listeners.clear();
|
|
54735
|
-
}
|
|
54736
|
-
this.listeners.clear();
|
|
54737
|
-
}
|
|
54738
|
-
}
|
|
56273
|
+
init_cel2();
|
|
54739
56274
|
init_parser32();
|
|
54740
56275
|
init_schema2();
|
|
54741
56276
|
init_validate2();
|
|
@@ -54899,147 +56434,514 @@ function validateInputs2(inputDefs, provided) {
|
|
|
54899
56434
|
resolved
|
|
54900
56435
|
};
|
|
54901
56436
|
}
|
|
54902
|
-
init_cel2();
|
|
54903
|
-
init_cel2();
|
|
54904
|
-
init_parser32();
|
|
54905
|
-
init_schema2();
|
|
54906
|
-
init_validate2();
|
|
54907
|
-
init_control2();
|
|
54908
|
-
init_sequential2();
|
|
54909
|
-
init_wait2();
|
|
54910
|
-
init_emit2();
|
|
54911
56437
|
|
|
54912
|
-
|
|
54913
|
-
|
|
54914
|
-
|
|
54915
|
-
|
|
54916
|
-
|
|
54917
|
-
|
|
56438
|
+
class TraceCollector2 {
|
|
56439
|
+
openSteps = new Map;
|
|
56440
|
+
seq = 0;
|
|
56441
|
+
truncateAt;
|
|
56442
|
+
writer;
|
|
56443
|
+
constructor(truncateAt = 1e6) {
|
|
56444
|
+
this.truncateAt = truncateAt;
|
|
56445
|
+
}
|
|
56446
|
+
startStep(name, type3, input, loopIndex) {
|
|
56447
|
+
this.seq += 1;
|
|
56448
|
+
this.openSteps.set(this.seq, {
|
|
56449
|
+
name,
|
|
56450
|
+
type: type3,
|
|
56451
|
+
startedAt: new Date().toISOString(),
|
|
56452
|
+
startMs: performance.now(),
|
|
56453
|
+
input: input !== undefined ? this.truncate(input) : undefined,
|
|
56454
|
+
loopIndex
|
|
56455
|
+
});
|
|
56456
|
+
return this.seq;
|
|
56457
|
+
}
|
|
56458
|
+
endStep(seq, status, output, error, retries) {
|
|
56459
|
+
const open = this.openSteps.get(seq);
|
|
56460
|
+
if (!open)
|
|
56461
|
+
return;
|
|
56462
|
+
this.openSteps.delete(seq);
|
|
56463
|
+
const finishedAt = new Date().toISOString();
|
|
56464
|
+
const duration = Math.max(0, performance.now() - open.startMs);
|
|
56465
|
+
const step = {
|
|
56466
|
+
seq,
|
|
56467
|
+
name: open.name,
|
|
56468
|
+
type: open.type,
|
|
56469
|
+
startedAt: open.startedAt,
|
|
56470
|
+
finishedAt,
|
|
56471
|
+
duration: Math.round(duration),
|
|
56472
|
+
status,
|
|
56473
|
+
...open.input !== undefined ? { input: open.input } : {},
|
|
56474
|
+
...output !== undefined ? { output: this.truncate(output) } : {},
|
|
56475
|
+
...error !== undefined ? { error } : {},
|
|
56476
|
+
...retries !== undefined && retries > 0 ? { retries } : {},
|
|
56477
|
+
...open.loopIndex !== undefined ? { loopIndex: open.loopIndex } : {}
|
|
56478
|
+
};
|
|
56479
|
+
this.writer?.writeStep(step);
|
|
56480
|
+
}
|
|
56481
|
+
truncate(value) {
|
|
56482
|
+
if (value == null)
|
|
56483
|
+
return value;
|
|
56484
|
+
const str = typeof value === "string" ? value : JSON.stringify(value);
|
|
56485
|
+
const bytes = new TextEncoder().encode(str);
|
|
56486
|
+
if (bytes.length <= this.truncateAt)
|
|
56487
|
+
return value;
|
|
56488
|
+
const cut = new TextDecoder().decode(bytes.slice(0, this.truncateAt));
|
|
56489
|
+
return cut + "...[truncated]";
|
|
56490
|
+
}
|
|
54918
56491
|
}
|
|
54919
|
-
function
|
|
54920
|
-
|
|
54921
|
-
|
|
54922
|
-
|
|
54923
|
-
|
|
54924
|
-
|
|
54925
|
-
|
|
54926
|
-
|
|
54927
|
-
|
|
54928
|
-
|
|
54929
|
-
|
|
54930
|
-
|
|
54931
|
-
|
|
54932
|
-
|
|
54933
|
-
|
|
54934
|
-
|
|
56492
|
+
async function createTraceWriter(dir, format) {
|
|
56493
|
+
await mkdir(dir, { recursive: true });
|
|
56494
|
+
if (format === "json") {
|
|
56495
|
+
const { JsonTraceWriter: JsonTraceWriter22 } = await Promise.resolve().then(() => (init_json(), exports_json2));
|
|
56496
|
+
return new JsonTraceWriter22(dir);
|
|
56497
|
+
}
|
|
56498
|
+
if (format === "txt") {
|
|
56499
|
+
const { TxtTraceWriter: TxtTraceWriter22 } = await Promise.resolve().then(() => (init_txt(), exports_txt2));
|
|
56500
|
+
return new TxtTraceWriter22(dir);
|
|
56501
|
+
}
|
|
56502
|
+
if (format === "sqlite") {
|
|
56503
|
+
const { SqliteTraceWriter: SqliteTraceWriter22 } = await Promise.resolve().then(() => (init_sqlite(), exports_sqlite2));
|
|
56504
|
+
return new SqliteTraceWriter22(dir);
|
|
56505
|
+
}
|
|
56506
|
+
throw new Error(`unknown trace format: ${format}`);
|
|
56507
|
+
}
|
|
56508
|
+
init_control2();
|
|
56509
|
+
|
|
56510
|
+
class WorkflowState {
|
|
56511
|
+
inputs;
|
|
56512
|
+
results;
|
|
56513
|
+
loopStack;
|
|
56514
|
+
workflowInputs;
|
|
56515
|
+
workflowMeta;
|
|
56516
|
+
executionMeta;
|
|
56517
|
+
currentInput;
|
|
56518
|
+
currentOutput;
|
|
56519
|
+
chainValue;
|
|
56520
|
+
eventPayload;
|
|
56521
|
+
ancestorPaths;
|
|
56522
|
+
tracer;
|
|
56523
|
+
constructor(inputs = {}) {
|
|
56524
|
+
this.inputs = { ...inputs };
|
|
56525
|
+
this.workflowInputs = { ...inputs };
|
|
56526
|
+
this.workflowMeta = {};
|
|
56527
|
+
this.executionMeta = {
|
|
56528
|
+
id: crypto.randomUUID(),
|
|
56529
|
+
startedAt: new Date().toISOString(),
|
|
56530
|
+
status: "running",
|
|
56531
|
+
cwd: process.cwd()
|
|
56532
|
+
};
|
|
56533
|
+
this.currentInput = undefined;
|
|
56534
|
+
this.currentOutput = undefined;
|
|
56535
|
+
this.chainValue = undefined;
|
|
56536
|
+
this.eventPayload = undefined;
|
|
56537
|
+
this.ancestorPaths = new Set;
|
|
56538
|
+
this.results = new Map;
|
|
56539
|
+
this.loopStack = [];
|
|
56540
|
+
}
|
|
56541
|
+
setResult(stepName, result) {
|
|
56542
|
+
this.results.set(stepName, result);
|
|
56543
|
+
}
|
|
56544
|
+
getResult(stepName) {
|
|
56545
|
+
return this.results.get(stepName);
|
|
56546
|
+
}
|
|
56547
|
+
getAllResults() {
|
|
56548
|
+
const out = {};
|
|
56549
|
+
for (const [k, v] of this.results.entries())
|
|
56550
|
+
out[k] = v;
|
|
56551
|
+
return out;
|
|
56552
|
+
}
|
|
56553
|
+
pushLoop(as) {
|
|
56554
|
+
this.loopStack.push({ index: 0, as });
|
|
56555
|
+
}
|
|
56556
|
+
incrementLoop() {
|
|
56557
|
+
const top = this.loopStack[this.loopStack.length - 1];
|
|
56558
|
+
if (top)
|
|
56559
|
+
top.index += 1;
|
|
56560
|
+
}
|
|
56561
|
+
popLoop() {
|
|
56562
|
+
this.loopStack.pop();
|
|
56563
|
+
}
|
|
56564
|
+
currentLoopIndex() {
|
|
56565
|
+
const top = this.loopStack[this.loopStack.length - 1];
|
|
56566
|
+
return top ? top.index : 0;
|
|
56567
|
+
}
|
|
56568
|
+
setLoopLast(last22) {
|
|
56569
|
+
const top = this.loopStack[this.loopStack.length - 1];
|
|
56570
|
+
if (top)
|
|
56571
|
+
top.last = last22;
|
|
56572
|
+
}
|
|
56573
|
+
isInsideLoop() {
|
|
56574
|
+
return this.loopStack.length > 0;
|
|
56575
|
+
}
|
|
56576
|
+
currentLoopContext() {
|
|
56577
|
+
const top = this.loopStack[this.loopStack.length - 1];
|
|
56578
|
+
if (!top)
|
|
56579
|
+
return { index: 0, iteration: 1, first: true, last: false };
|
|
56580
|
+
return {
|
|
56581
|
+
index: top.index,
|
|
56582
|
+
iteration: top.index + 1,
|
|
56583
|
+
first: top.index === 0,
|
|
56584
|
+
last: top.last ?? false,
|
|
56585
|
+
as: top.as
|
|
56586
|
+
};
|
|
56587
|
+
}
|
|
56588
|
+
toCelContext() {
|
|
56589
|
+
const ctx = {};
|
|
56590
|
+
for (const [name, res] of this.results.entries()) {
|
|
56591
|
+
ctx[name] = {
|
|
56592
|
+
output: res.parsedOutput ?? res.output,
|
|
56593
|
+
status: res.status,
|
|
56594
|
+
startedAt: res.startedAt,
|
|
56595
|
+
finishedAt: res.finishedAt,
|
|
56596
|
+
duration: res.duration,
|
|
56597
|
+
retries: res.retries ?? 0,
|
|
56598
|
+
error: res.error,
|
|
56599
|
+
cwd: res.cwd
|
|
56600
|
+
};
|
|
54935
56601
|
}
|
|
54936
|
-
|
|
54937
|
-
|
|
54938
|
-
|
|
54939
|
-
|
|
54940
|
-
|
|
54941
|
-
|
|
54942
|
-
|
|
54943
|
-
|
|
54944
|
-
|
|
54945
|
-
|
|
54946
|
-
|
|
54947
|
-
|
|
54948
|
-
|
|
54949
|
-
|
|
54950
|
-
|
|
54951
|
-
|
|
54952
|
-
|
|
54953
|
-
|
|
56602
|
+
ctx["workflow"] = {
|
|
56603
|
+
id: this.workflowMeta.id,
|
|
56604
|
+
name: this.workflowMeta.name,
|
|
56605
|
+
version: this.workflowMeta.version,
|
|
56606
|
+
inputs: this.workflowInputs,
|
|
56607
|
+
output: null
|
|
56608
|
+
};
|
|
56609
|
+
ctx["execution"] = { ...this.executionMeta };
|
|
56610
|
+
ctx["input"] = this.currentInput ?? {};
|
|
56611
|
+
ctx["output"] = this.currentOutput ?? {};
|
|
56612
|
+
ctx["env"] = { ...env };
|
|
56613
|
+
const loopCtx = this.currentLoopContext();
|
|
56614
|
+
const loopObj = {
|
|
56615
|
+
index: loopCtx.index,
|
|
56616
|
+
iteration: loopCtx.iteration,
|
|
56617
|
+
first: loopCtx.first,
|
|
56618
|
+
last: loopCtx.last
|
|
56619
|
+
};
|
|
56620
|
+
if (loopCtx.as) {
|
|
56621
|
+
ctx[`_${loopCtx.as}`] = loopObj;
|
|
56622
|
+
}
|
|
56623
|
+
ctx["_loop"] = loopObj;
|
|
56624
|
+
ctx["loop"] = loopObj;
|
|
56625
|
+
ctx["event"] = this.eventPayload ?? {};
|
|
56626
|
+
ctx["now"] = Math.floor(Date.now() / 1000);
|
|
56627
|
+
return ctx;
|
|
56628
|
+
}
|
|
56629
|
+
resolveOutput(outputDef, celEvaluator) {
|
|
56630
|
+
const ctx = this.toCelContext();
|
|
56631
|
+
if (typeof outputDef === "object" && "map" in outputDef && "schema" in outputDef) {
|
|
56632
|
+
const result2 = {};
|
|
56633
|
+
for (const [k, expr] of Object.entries(outputDef.map)) {
|
|
56634
|
+
result2[k] = celEvaluator(expr, ctx);
|
|
54954
56635
|
}
|
|
54955
|
-
|
|
54956
|
-
continue;
|
|
56636
|
+
return result2;
|
|
54957
56637
|
}
|
|
54958
|
-
if (
|
|
54959
|
-
|
|
54960
|
-
path: stepPath,
|
|
54961
|
-
message: "inline participant without 'as' — its output cannot be referenced by name"
|
|
54962
|
-
});
|
|
54963
|
-
continue;
|
|
56638
|
+
if (typeof outputDef === "string") {
|
|
56639
|
+
return celEvaluator(outputDef, ctx);
|
|
54964
56640
|
}
|
|
54965
|
-
|
|
54966
|
-
|
|
54967
|
-
|
|
54968
|
-
|
|
54969
|
-
|
|
56641
|
+
const result = {};
|
|
56642
|
+
for (const k of Object.keys(outputDef)) {
|
|
56643
|
+
const expr = outputDef[k];
|
|
56644
|
+
result[k] = celEvaluator(expr, ctx);
|
|
56645
|
+
}
|
|
56646
|
+
return result;
|
|
56647
|
+
}
|
|
56648
|
+
}
|
|
56649
|
+
async function executeWorkflow(workflow, inputs = {}, basePath = process.cwd(), options = {}) {
|
|
56650
|
+
const { result: inputResult, resolved } = validateInputs2(workflow.inputs, inputs);
|
|
56651
|
+
if (!inputResult.valid) {
|
|
56652
|
+
throw new Error(`input validation failed: ${JSON.stringify(inputResult.errors)}`);
|
|
56653
|
+
}
|
|
56654
|
+
const state = new WorkflowState(resolved);
|
|
56655
|
+
state.workflowMeta = {
|
|
56656
|
+
id: workflow.id,
|
|
56657
|
+
name: workflow.name,
|
|
56658
|
+
version: workflow.version
|
|
56659
|
+
};
|
|
56660
|
+
state.executionMeta.number = options.executionNumber ?? 1;
|
|
56661
|
+
if (options.cwd) {
|
|
56662
|
+
state.executionMeta.cwd = options.cwd;
|
|
56663
|
+
}
|
|
56664
|
+
const startedAtMs = performance.now();
|
|
56665
|
+
const startedAtIso = state.executionMeta.startedAt;
|
|
56666
|
+
if (options._ancestorPaths) {
|
|
56667
|
+
state.ancestorPaths = options._ancestorPaths;
|
|
56668
|
+
}
|
|
56669
|
+
if (options.traceDir && !options._ancestorPaths) {
|
|
56670
|
+
const collector = new TraceCollector2;
|
|
56671
|
+
const writer = await createTraceWriter(options.traceDir, options.traceFormat ?? "json");
|
|
56672
|
+
collector.writer = writer;
|
|
56673
|
+
state.tracer = collector;
|
|
56674
|
+
await writer.open({
|
|
56675
|
+
id: state.executionMeta.id,
|
|
56676
|
+
workflowId: workflow.id,
|
|
56677
|
+
workflowName: workflow.name,
|
|
56678
|
+
workflowVersion: workflow.version,
|
|
56679
|
+
startedAt: startedAtIso,
|
|
56680
|
+
inputs: resolved
|
|
56681
|
+
});
|
|
56682
|
+
}
|
|
56683
|
+
const engineExecutor = async (subWorkflow, subInputs, subBasePath) => {
|
|
56684
|
+
return executeWorkflow(subWorkflow, subInputs, subBasePath, {
|
|
56685
|
+
...options,
|
|
56686
|
+
_ancestorPaths: state.ancestorPaths
|
|
56687
|
+
});
|
|
56688
|
+
};
|
|
56689
|
+
let output;
|
|
56690
|
+
let success = false;
|
|
56691
|
+
try {
|
|
56692
|
+
let chain;
|
|
56693
|
+
for (const step of workflow.flow) {
|
|
56694
|
+
chain = await executeControlStep2(workflow, state, step, basePath, engineExecutor, chain, options.hub);
|
|
56695
|
+
}
|
|
56696
|
+
if (workflow.output !== undefined) {
|
|
56697
|
+
output = state.resolveOutput(workflow.output, evaluateCel2);
|
|
56698
|
+
if (typeof workflow.output === "object" && "schema" in workflow.output && "map" in workflow.output && typeof output === "object" && output !== null) {
|
|
56699
|
+
validateOutputSchema2(workflow.output.schema, output);
|
|
54970
56700
|
}
|
|
56701
|
+
} else {
|
|
56702
|
+
output = chain;
|
|
56703
|
+
}
|
|
56704
|
+
const steps = state.getAllResults();
|
|
56705
|
+
success = !Object.values(steps).some((step) => step.status === "failure");
|
|
56706
|
+
state.executionMeta.status = success ? "success" : "failure";
|
|
56707
|
+
return {
|
|
56708
|
+
success,
|
|
56709
|
+
output,
|
|
56710
|
+
steps,
|
|
56711
|
+
duration: Math.max(0, performance.now() - startedAtMs)
|
|
56712
|
+
};
|
|
56713
|
+
} finally {
|
|
56714
|
+
if (state.tracer?.writer) {
|
|
56715
|
+
const duration = Math.max(0, performance.now() - startedAtMs);
|
|
56716
|
+
await state.tracer.writer.finalize({
|
|
56717
|
+
status: success ? "success" : "failure",
|
|
56718
|
+
output: output ?? null,
|
|
56719
|
+
finishedAt: new Date().toISOString(),
|
|
56720
|
+
duration
|
|
56721
|
+
}).catch(() => {});
|
|
54971
56722
|
}
|
|
54972
56723
|
}
|
|
54973
56724
|
}
|
|
54974
|
-
function
|
|
54975
|
-
|
|
54976
|
-
|
|
54977
|
-
|
|
54978
|
-
|
|
54979
|
-
return Object.keys(obj.set);
|
|
56725
|
+
async function runWorkflowFromFile(filePath, inputs = {}, options = {}) {
|
|
56726
|
+
const workflow = await parseWorkflowFile2(filePath);
|
|
56727
|
+
const schemaValidation = validateSchema2(workflow);
|
|
56728
|
+
if (!schemaValidation.valid) {
|
|
56729
|
+
throw new Error(`schema validation failed: ${JSON.stringify(schemaValidation.errors)}`);
|
|
54980
56730
|
}
|
|
54981
|
-
const
|
|
54982
|
-
|
|
54983
|
-
|
|
54984
|
-
|
|
54985
|
-
|
|
56731
|
+
const workflowBasePath = dirname22(resolve32(filePath));
|
|
56732
|
+
const semanticValidation = await validateSemantic2(workflow, workflowBasePath);
|
|
56733
|
+
if (!semanticValidation.valid) {
|
|
56734
|
+
throw new Error(`semantic validation failed: ${JSON.stringify(semanticValidation.errors)}`);
|
|
56735
|
+
}
|
|
56736
|
+
return executeWorkflow(workflow, inputs, workflowBasePath, options);
|
|
56737
|
+
}
|
|
56738
|
+
init_control2();
|
|
56739
|
+
init_sequential2();
|
|
56740
|
+
init_errors2();
|
|
56741
|
+
init_timeout2();
|
|
56742
|
+
init_wait2();
|
|
56743
|
+
|
|
56744
|
+
// src/run.ts
|
|
56745
|
+
async function createHubFromFlags(values3) {
|
|
56746
|
+
const backend = values3?.["event-backend"] ?? "memory";
|
|
56747
|
+
if (backend === "memory") {
|
|
56748
|
+
const { MemoryHub: MemoryHub3 } = await Promise.resolve().then(() => (init_eventhub(), exports_eventhub));
|
|
56749
|
+
return new MemoryHub3;
|
|
56750
|
+
}
|
|
56751
|
+
if (backend === "nats") {
|
|
56752
|
+
const url = values3?.["nats-url"];
|
|
56753
|
+
if (!url) {
|
|
56754
|
+
console.error("Error: --nats-url is required when using the NATS backend");
|
|
56755
|
+
throw new Error("missing --nats-url");
|
|
56756
|
+
}
|
|
56757
|
+
const stream = values3?.["nats-stream"] ?? "duckflux-events";
|
|
56758
|
+
try {
|
|
56759
|
+
const { NatsHub } = await import("@duckflux/hub-nats");
|
|
56760
|
+
return await NatsHub.create({ url, stream });
|
|
56761
|
+
} catch (err) {
|
|
56762
|
+
if (err instanceof Error && (err.message.includes("Cannot find module") || err.message.includes("Cannot find package"))) {
|
|
56763
|
+
console.error("Error: install @duckflux/hub-nats to use the NATS backend");
|
|
56764
|
+
throw new Error("@duckflux/hub-nats not installed");
|
|
56765
|
+
}
|
|
56766
|
+
throw err;
|
|
54986
56767
|
}
|
|
54987
56768
|
}
|
|
54988
|
-
if (
|
|
54989
|
-
const
|
|
54990
|
-
|
|
54991
|
-
|
|
56769
|
+
if (backend === "redis") {
|
|
56770
|
+
const addr = values3?.["redis-addr"] ?? "localhost:6379";
|
|
56771
|
+
const db = Number(values3?.["redis-db"] ?? "0");
|
|
56772
|
+
try {
|
|
56773
|
+
const { RedisHub } = await import("@duckflux/hub-redis");
|
|
56774
|
+
return await RedisHub.create({ addr, db });
|
|
56775
|
+
} catch (err) {
|
|
56776
|
+
if (err instanceof Error && (err.message.includes("Cannot find module") || err.message.includes("Cannot find package"))) {
|
|
56777
|
+
console.error("Error: install @duckflux/hub-redis to use the Redis backend");
|
|
56778
|
+
throw new Error("@duckflux/hub-redis not installed");
|
|
56779
|
+
}
|
|
56780
|
+
throw err;
|
|
54992
56781
|
}
|
|
54993
|
-
|
|
54994
|
-
|
|
54995
|
-
|
|
56782
|
+
}
|
|
56783
|
+
console.error(`Error: unknown event backend "${backend}". Supported: memory, nats, redis`);
|
|
56784
|
+
throw new Error(`unknown event backend: ${backend}`);
|
|
56785
|
+
}
|
|
56786
|
+
function parseInputFlags(arr) {
|
|
56787
|
+
const out = {};
|
|
56788
|
+
if (!arr)
|
|
56789
|
+
return out;
|
|
56790
|
+
for (const item of arr) {
|
|
56791
|
+
const idx = item.indexOf("=");
|
|
56792
|
+
if (idx === -1) {
|
|
56793
|
+
out[item] = true;
|
|
56794
|
+
} else {
|
|
56795
|
+
const k = item.slice(0, idx);
|
|
56796
|
+
const v = item.slice(idx + 1);
|
|
56797
|
+
try {
|
|
56798
|
+
out[k] = JSON.parse(v);
|
|
56799
|
+
} catch {
|
|
56800
|
+
out[k] = v;
|
|
54996
56801
|
}
|
|
54997
56802
|
}
|
|
54998
56803
|
}
|
|
54999
|
-
return
|
|
56804
|
+
return out;
|
|
55000
56805
|
}
|
|
55001
|
-
async function
|
|
56806
|
+
async function runCommand(filePath, cliValues) {
|
|
55002
56807
|
if (!filePath) {
|
|
55003
|
-
console.error("Usage:
|
|
56808
|
+
console.error("Usage: quack run <workflow.yaml> [--input k=v] [--input-file file.json] [--cwd dir]");
|
|
55004
56809
|
return 1;
|
|
55005
56810
|
}
|
|
56811
|
+
let inputs = {};
|
|
55006
56812
|
try {
|
|
55007
|
-
|
|
55008
|
-
|
|
55009
|
-
|
|
55010
|
-
|
|
55011
|
-
for (const e of schemaRes.errors) {
|
|
55012
|
-
console.error(` - ${e.path}: ${e.message}`);
|
|
56813
|
+
if (process.stdin && !process.stdin.isTTY) {
|
|
56814
|
+
let stdin = "";
|
|
56815
|
+
for await (const chunk of process.stdin) {
|
|
56816
|
+
stdin += chunk;
|
|
55013
56817
|
}
|
|
55014
|
-
|
|
55015
|
-
|
|
55016
|
-
|
|
55017
|
-
|
|
55018
|
-
|
|
55019
|
-
|
|
55020
|
-
|
|
55021
|
-
console.error(` - ${e.path}: ${e.message}`);
|
|
56818
|
+
stdin = stdin.trim();
|
|
56819
|
+
if (stdin.length > 0) {
|
|
56820
|
+
try {
|
|
56821
|
+
const parsed = JSON.parse(stdin);
|
|
56822
|
+
if (typeof parsed === "object" && parsed !== null)
|
|
56823
|
+
inputs = { ...inputs, ...parsed };
|
|
56824
|
+
} catch {}
|
|
55022
56825
|
}
|
|
55023
|
-
return 1;
|
|
55024
56826
|
}
|
|
55025
|
-
|
|
55026
|
-
|
|
55027
|
-
|
|
55028
|
-
|
|
55029
|
-
|
|
56827
|
+
} catch {}
|
|
56828
|
+
if (cliValues) {
|
|
56829
|
+
if (cliValues["input-file"]) {
|
|
56830
|
+
try {
|
|
56831
|
+
const content = await readFile5(String(cliValues["input-file"]), "utf-8");
|
|
56832
|
+
const parsed = JSON.parse(content);
|
|
56833
|
+
if (typeof parsed === "object" && parsed !== null)
|
|
56834
|
+
inputs = { ...inputs, ...parsed };
|
|
56835
|
+
} catch (err) {
|
|
56836
|
+
console.error("Failed to read input file:", err);
|
|
56837
|
+
return 1;
|
|
55030
56838
|
}
|
|
55031
56839
|
}
|
|
55032
|
-
|
|
55033
|
-
|
|
56840
|
+
if (cliValues.input) {
|
|
56841
|
+
const parsed = Array.isArray(cliValues.input) ? cliValues.input : [cliValues.input];
|
|
56842
|
+
inputs = { ...inputs, ...parseInputFlags(parsed) };
|
|
56843
|
+
}
|
|
56844
|
+
}
|
|
56845
|
+
let hub;
|
|
56846
|
+
try {
|
|
56847
|
+
hub = await createHubFromFlags(cliValues);
|
|
56848
|
+
} catch {
|
|
56849
|
+
return 1;
|
|
56850
|
+
}
|
|
56851
|
+
const options = {
|
|
56852
|
+
hub,
|
|
56853
|
+
cwd: cliValues?.cwd,
|
|
56854
|
+
verbose: cliValues?.verbose,
|
|
56855
|
+
quiet: cliValues?.quiet,
|
|
56856
|
+
traceDir: cliValues?.["trace-dir"],
|
|
56857
|
+
traceFormat: cliValues?.["trace-format"] ?? "json"
|
|
56858
|
+
};
|
|
56859
|
+
try {
|
|
56860
|
+
const res = await runWorkflowFromFile(filePath, inputs, options);
|
|
56861
|
+
const output = res.output;
|
|
56862
|
+
if (output === undefined || output === null) {} else if (typeof output === "string") {
|
|
56863
|
+
process.stdout.write(output);
|
|
56864
|
+
} else {
|
|
56865
|
+
console.log(JSON.stringify(output, null, 2));
|
|
56866
|
+
}
|
|
56867
|
+
return res.success ? 0 : 2;
|
|
55034
56868
|
} catch (err) {
|
|
55035
|
-
|
|
56869
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
56870
|
+
console.error("Error:", msg);
|
|
56871
|
+
if (cliValues?.verbose && err instanceof Error && err.stack) {
|
|
56872
|
+
console.error(err.stack);
|
|
56873
|
+
}
|
|
55036
56874
|
return 1;
|
|
56875
|
+
} finally {
|
|
56876
|
+
await hub?.close();
|
|
55037
56877
|
}
|
|
55038
56878
|
}
|
|
55039
56879
|
|
|
56880
|
+
// src/server.ts
|
|
56881
|
+
import { existsSync } from "node:fs";
|
|
56882
|
+
import { join as join6 } from "node:path";
|
|
56883
|
+
import { spawn as spawn3, execSync } from "node:child_process";
|
|
56884
|
+
import { createInterface } from "node:readline";
|
|
56885
|
+
async function ensureServerPackage(cwd) {
|
|
56886
|
+
const serverBin = join6(cwd, "node_modules", ".bin", "duckflux-server");
|
|
56887
|
+
const serverPkg = join6(cwd, "node_modules", "@duckflux", "server");
|
|
56888
|
+
if (existsSync(serverBin) || existsSync(serverPkg))
|
|
56889
|
+
return true;
|
|
56890
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
56891
|
+
const answer = await new Promise((resolve4) => {
|
|
56892
|
+
rl.question(`
|
|
56893
|
+
@duckflux/server is not installed. Install it now? [Y/n] `, resolve4);
|
|
56894
|
+
});
|
|
56895
|
+
rl.close();
|
|
56896
|
+
if (answer.trim().toLowerCase() === "n") {
|
|
56897
|
+
console.error("Cancelled. Run `bun add @duckflux/server -D` to install manually.");
|
|
56898
|
+
return false;
|
|
56899
|
+
}
|
|
56900
|
+
console.error("Installing @duckflux/server...");
|
|
56901
|
+
try {
|
|
56902
|
+
execSync("bun add @duckflux/server -D", { cwd, stdio: "inherit" });
|
|
56903
|
+
return true;
|
|
56904
|
+
} catch {
|
|
56905
|
+
try {
|
|
56906
|
+
execSync("npm install @duckflux/server --save-dev", { cwd, stdio: "inherit" });
|
|
56907
|
+
return true;
|
|
56908
|
+
} catch {
|
|
56909
|
+
console.error("Failed to install @duckflux/server. Please install it manually.");
|
|
56910
|
+
return false;
|
|
56911
|
+
}
|
|
56912
|
+
}
|
|
56913
|
+
}
|
|
56914
|
+
async function serverCommand(values3) {
|
|
56915
|
+
const cwd = values3["cwd"] ?? process.cwd();
|
|
56916
|
+
const installed = await ensureServerPackage(cwd);
|
|
56917
|
+
if (!installed)
|
|
56918
|
+
return 1;
|
|
56919
|
+
const args = [];
|
|
56920
|
+
if (values3["trace-dir"])
|
|
56921
|
+
args.push("--trace-dir", values3["trace-dir"]);
|
|
56922
|
+
if (values3["workflow-dir"])
|
|
56923
|
+
args.push("--workflow-dir", values3["workflow-dir"]);
|
|
56924
|
+
if (values3["port"])
|
|
56925
|
+
args.push("--port", values3["port"]);
|
|
56926
|
+
const child = spawn3("bunx", ["@duckflux/server", ...args], {
|
|
56927
|
+
cwd,
|
|
56928
|
+
stdio: "inherit",
|
|
56929
|
+
env: process.env
|
|
56930
|
+
});
|
|
56931
|
+
return new Promise((resolve4) => {
|
|
56932
|
+
child.on("error", (err) => {
|
|
56933
|
+
console.error("Failed to start duckflux server:", err.message);
|
|
56934
|
+
resolve4(1);
|
|
56935
|
+
});
|
|
56936
|
+
child.on("exit", (code) => resolve4(code ?? 0));
|
|
56937
|
+
process.on("SIGINT", () => child.kill("SIGINT"));
|
|
56938
|
+
process.on("SIGTERM", () => child.kill("SIGTERM"));
|
|
56939
|
+
});
|
|
56940
|
+
}
|
|
56941
|
+
|
|
55040
56942
|
// src/validate.ts
|
|
55041
|
-
import { readFile as
|
|
55042
|
-
import { dirname as
|
|
56943
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
56944
|
+
import { dirname as dirname4 } from "node:path";
|
|
55043
56945
|
|
|
55044
56946
|
// src/run.ts
|
|
55045
56947
|
function parseInputFlags2(arr) {
|
|
@@ -55066,7 +56968,7 @@ function parseInputFlags2(arr) {
|
|
|
55066
56968
|
// src/validate.ts
|
|
55067
56969
|
async function validateCommand(filePath, cliValues) {
|
|
55068
56970
|
if (!filePath) {
|
|
55069
|
-
console.error("Usage:
|
|
56971
|
+
console.error("Usage: quack validate <workflow.yaml> [--input k=v] [--input-file file.json]");
|
|
55070
56972
|
return 1;
|
|
55071
56973
|
}
|
|
55072
56974
|
let inputs = {};
|
|
@@ -55077,7 +56979,7 @@ async function validateCommand(filePath, cliValues) {
|
|
|
55077
56979
|
}
|
|
55078
56980
|
if (cliValues["input-file"]) {
|
|
55079
56981
|
try {
|
|
55080
|
-
const content = await
|
|
56982
|
+
const content = await readFile6(String(cliValues["input-file"]), "utf-8");
|
|
55081
56983
|
const parsed = JSON.parse(content);
|
|
55082
56984
|
if (typeof parsed === "object" && parsed !== null)
|
|
55083
56985
|
inputs = { ...inputs, ...parsed };
|
|
@@ -55104,8 +57006,8 @@ async function validateCommand(filePath, cliValues) {
|
|
|
55104
57006
|
}
|
|
55105
57007
|
} catch {}
|
|
55106
57008
|
try {
|
|
55107
|
-
const workflow = await
|
|
55108
|
-
const schemaRes =
|
|
57009
|
+
const workflow = await parseWorkflowFile(filePath);
|
|
57010
|
+
const schemaRes = validateSchema(workflow);
|
|
55109
57011
|
if (!schemaRes.valid) {
|
|
55110
57012
|
console.error("Schema validation failed:");
|
|
55111
57013
|
for (const e of schemaRes.errors) {
|
|
@@ -55113,8 +57015,8 @@ async function validateCommand(filePath, cliValues) {
|
|
|
55113
57015
|
}
|
|
55114
57016
|
return 1;
|
|
55115
57017
|
}
|
|
55116
|
-
const basePath =
|
|
55117
|
-
const semanticRes = await
|
|
57018
|
+
const basePath = dirname4(filePath);
|
|
57019
|
+
const semanticRes = await validateSemantic(workflow, basePath);
|
|
55118
57020
|
if (!semanticRes.valid) {
|
|
55119
57021
|
console.error("Semantic validation failed:");
|
|
55120
57022
|
for (const e of semanticRes.errors) {
|
|
@@ -55122,7 +57024,7 @@ async function validateCommand(filePath, cliValues) {
|
|
|
55122
57024
|
}
|
|
55123
57025
|
return 1;
|
|
55124
57026
|
}
|
|
55125
|
-
const { result: inputsResult, resolved } =
|
|
57027
|
+
const { result: inputsResult, resolved } = validateInputs(workflow.inputs, inputs);
|
|
55126
57028
|
if (!inputsResult.valid) {
|
|
55127
57029
|
console.error("Input validation failed:");
|
|
55128
57030
|
for (const e of inputsResult.errors) {
|
|
@@ -55141,7 +57043,7 @@ async function validateCommand(filePath, cliValues) {
|
|
|
55141
57043
|
// src/main.ts
|
|
55142
57044
|
function getVersion() {
|
|
55143
57045
|
try {
|
|
55144
|
-
const pkg = JSON.parse(
|
|
57046
|
+
const pkg = JSON.parse(readFileSync(resolve5(dirname5(new URL(import.meta.url).pathname), "../package.json"), "utf-8"));
|
|
55145
57047
|
return pkg.version ?? "0.0.0";
|
|
55146
57048
|
} catch {
|
|
55147
57049
|
return "0.0.0";
|
|
@@ -55161,7 +57063,11 @@ if (__require.main == __require.module) {
|
|
|
55161
57063
|
"nats-url": { type: "string" },
|
|
55162
57064
|
"nats-stream": { type: "string", default: "duckflux-events" },
|
|
55163
57065
|
"redis-addr": { type: "string", default: "localhost:6379" },
|
|
55164
|
-
"redis-db": { type: "string", default: "0" }
|
|
57066
|
+
"redis-db": { type: "string", default: "0" },
|
|
57067
|
+
"trace-dir": { type: "string" },
|
|
57068
|
+
"trace-format": { type: "string", default: "json" },
|
|
57069
|
+
"workflow-dir": { type: "string" },
|
|
57070
|
+
port: { type: "string", default: "3000" }
|
|
55165
57071
|
},
|
|
55166
57072
|
allowPositionals: true
|
|
55167
57073
|
});
|
|
@@ -55183,9 +57089,13 @@ if (__require.main == __require.module) {
|
|
|
55183
57089
|
const exitCode = await validateCommand(file, values3);
|
|
55184
57090
|
if (typeof exitCode === "number" && exitCode !== 0)
|
|
55185
57091
|
process.exit(exitCode);
|
|
57092
|
+
} else if (cmd === "server") {
|
|
57093
|
+
const exitCode = await serverCommand(values3);
|
|
57094
|
+
if (typeof exitCode === "number" && exitCode !== 0)
|
|
57095
|
+
process.exit(exitCode);
|
|
55186
57096
|
} else {
|
|
55187
57097
|
console.error("Unknown command:", cmd);
|
|
55188
|
-
console.error("Available commands: run, lint, validate, version");
|
|
57098
|
+
console.error("Available commands: run, lint, validate, version, server");
|
|
55189
57099
|
process.exit(1);
|
|
55190
57100
|
}
|
|
55191
57101
|
}
|