feat(server): enhance workflow step execution and JSONata integration

- Refactored step execution logic to introduce runCompiledStep for improved clarity and functionality.
- Added support for "set" steps, allowing context manipulation using JSONata expressions.
- Implemented evaluateJsonata and isJsonataTruthy functions for evaluating conditions and expressions.
- Updated workflow parsing to handle new step types and validation rules.
- Enhanced logging and error handling for skipped steps and invalid configurations.
- Modified UI components to reflect new step types and statuses, including "skipped".
This commit is contained in:
2026-08-14 21:13:40 +07:00
parent fdb1c0a8a6
commit d4381d2943
8 changed files with 248 additions and 39 deletions
+3 -1
View File
@@ -13,7 +13,9 @@ export function StatusBadge({ status }) {
? "badge-error"
: status === "running"
? "badge-warning"
: "badge-ghost";
: status === "skipped"
? "badge-info"
: "badge-ghost";
return <span className={`badge badge-sm ${cls}`}>{status ?? "—"}</span>;
}
+31 -4
View File
@@ -1,12 +1,26 @@
function parseStep(step) {
if (typeof step === "string") {
return { script: step, id: null, needs: null };
return { kind: "script", script: step, id: null, needs: null, when: null, as: null };
}
if (step?.set) {
const as = typeof step.set?.as === "string" && step.set.as ? step.set.as : "set";
return {
kind: "set",
script: null,
as,
id: typeof step.id === "string" && step.id ? step.id : null,
needs: null,
when: typeof step.when === "string" && step.when ? step.when : null,
};
}
if (step?.script) {
return {
kind: "script",
script: step.script,
as: null,
id: typeof step.id === "string" && step.id ? step.id : null,
needs: step.needs ?? null,
when: typeof step.when === "string" && step.when ? step.when : null,
};
}
return null;
@@ -38,6 +52,15 @@ function triggerLabel(t) {
return `${method} ${path}`.trim();
}
function stepLabel(s) {
if (s.kind === "set") {
const base = s.id ? `${s.id}: set ${s.as}` : `set ${s.as}`;
return s.when ? `${base} when: ${s.when}` : base;
}
const base = s.id ? `${s.id}: ${s.script}` : s.script;
return s.when ? `${base} when: ${s.when}` : base;
}
export function workflowToFlowchart(parsed) {
/** @type {Record<string, string>} */
const scriptIds = {};
@@ -72,9 +95,13 @@ export function workflowToFlowchart(parsed) {
}
for (const s of parsedSteps) {
scriptIds[s.mermaidId] = s.script;
const label = s.id ? `${s.id}: ${s.script}` : s.script;
lines.push(` ${s.mermaidId}["${mermaidLabel(label)}"]`);
const label = mermaidLabel(stepLabel(s));
if (s.kind === "set") {
lines.push(` ${s.mermaidId}(["${label}"])`);
} else {
scriptIds[s.mermaidId] = s.script;
lines.push(` ${s.mermaidId}["${label}"]`);
}
}
if (dagMode) {