feat(server): enhance script execution and workflow management

- Introduced compileWorkflowScripts function to parse and validate workflow scripts, supporting both linear and DAG execution modes.
- Added runLinearSteps and runDagSteps functions for executing compiled workflows based on their structure.
- Updated createRegistry function to utilize the new workflow compilation and execution logic.
- Enhanced script sandbox with meta extraction and instantiation capabilities for better script management.
- Improved API endpoints to return script metadata and handle errors more effectively.
- Removed deprecated scripts and updated workflows to reflect new structure and functionality.
This commit is contained in:
2026-08-14 19:14:44 +07:00
parent ddff33cf49
commit 049f5c56e3
21 changed files with 809 additions and 87 deletions
+25 -5
View File
@@ -1,4 +1,8 @@
import { clearScriptCache, runScriptSource } from "../../script-sandbox.js";
import {
clearScriptCache,
inspectScriptSource,
instantiateScriptSource,
} from "../../script-sandbox.js";
import * as fsStore from "../../fs-store.js";
import { createDryRunLogger, safeSerialize } from "./dry-run-logger.js";
@@ -11,7 +15,15 @@ export default function scriptsPluginFactory(registry) {
*/
return async function scriptsPlugin(fastify) {
fastify.get("/scripts", async () => {
return { scripts: fsStore.listScriptFiles() };
const scripts = fsStore.listScriptFiles().map((name) => {
const content = fsStore.readScript(name);
const inspected =
content == null
? { meta: null, metaError: "script not found" }
: inspectScriptSource(name, content);
return { name, ...inspected };
});
return { scripts };
});
fastify.get("/scripts/:name", async (req, reply) => {
@@ -23,7 +35,7 @@ export default function scriptsPluginFactory(registry) {
}
const content = fsStore.readScript(name);
if (content == null) return reply.code(404).send({ error: "script not found" });
return { name, content };
return { name, content, ...inspectScriptSource(name, content) };
});
fastify.put("/scripts/:name", async (req, reply) => {
@@ -40,7 +52,10 @@ export default function scriptsPluginFactory(registry) {
const existed = fsStore.readScript(name) != null;
fsStore.writeScript(name, body.content);
clearScriptCache();
return reply.code(existed ? 200 : 201).send({ name });
return reply.code(existed ? 200 : 201).send({
name,
...inspectScriptSource(name, body.content),
});
});
fastify.delete("/scripts/:name", async (req, reply) => {
@@ -86,24 +101,29 @@ export default function scriptsPluginFactory(registry) {
const started = Date.now();
try {
const output = await runScriptSource(name, body.content, ctx, {
const { fn, meta, metaError } = instantiateScriptSource(name, body.content, {
log,
workflowName: "dry-run",
});
const output = await fn(ctx);
return {
status: "success",
output: safeSerialize(output),
error: null,
logs,
durationMs: Date.now() - started,
meta,
metaError,
};
} catch (err) {
const inspected = inspectScriptSource(name, body.content);
return {
status: "failed",
output: null,
error: err instanceof Error ? err.message : String(err),
logs,
durationMs: Date.now() - started,
...inspected,
};
}
});