@fieldwangai/agentflow 0.1.153 → 0.1.156
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/README.md +16 -34
- package/README.zh-CN.md +14 -34
- package/agents/agentflow-node-executor-code.md +13 -3
- package/agents/agentflow-node-executor-planning.md +13 -3
- package/agents/agentflow-node-executor-requirement.md +13 -3
- package/agents/agentflow-node-executor-test.md +13 -3
- package/agents/agentflow-node-executor-ui.md +13 -3
- package/agents/agentflow-node-executor.md +13 -3
- package/agents/en/agentflow-node-executor.md +13 -3
- package/agents/zh/agentflow-node-executor.md +13 -3
- package/bin/agentflow.mjs +3 -3
- package/bin/lib/admin-builtin-pipelines.mjs +3 -2
- package/bin/lib/agent-runners.mjs +0 -929
- package/bin/lib/auth.mjs +2 -1
- package/bin/lib/catalog-agents.mjs +2 -1
- package/bin/lib/catalog-flows.mjs +165 -90
- package/bin/lib/composer-agent.mjs +3 -793
- package/bin/lib/composer-skill-router.mjs +3 -323
- package/bin/lib/exec-buffered.mjs +32 -0
- package/bin/lib/flow-dsl/cli.mjs +277 -0
- package/bin/lib/flow-dsl/codegen.mjs +358 -0
- package/bin/lib/flow-dsl/defs.mjs +103 -0
- package/bin/lib/flow-dsl/index.mjs +77 -0
- package/bin/lib/flow-dsl/ir.mjs +305 -0
- package/bin/lib/flow-dsl/layout.mjs +115 -0
- package/bin/lib/flow-dsl/legacy-yaml.mjs +303 -0
- package/bin/lib/flow-dsl/lint.mjs +241 -0
- package/bin/lib/flow-dsl/packages.mjs +251 -0
- package/bin/lib/flow-dsl/parser.mjs +444 -0
- package/bin/lib/flow-import.mjs +96 -26
- package/bin/lib/flow-write.mjs +48 -12
- package/bin/lib/help.mjs +8 -28
- package/bin/lib/html-escape.mjs +19 -0
- package/bin/lib/http-util.mjs +49 -0
- package/bin/lib/legacy-flow-execution.mjs +37 -0
- package/bin/lib/locales/en.json +1 -1
- package/bin/lib/locales/zh.json +1 -1
- package/bin/lib/main.mjs +152 -286
- package/bin/lib/marketplace.mjs +206 -61
- package/bin/lib/model-config.mjs +10 -0
- package/bin/lib/node-package-archive.mjs +240 -0
- package/bin/lib/node-package-bootstrap.mjs +72 -0
- package/bin/lib/node-package-manifest.mjs +174 -0
- package/bin/lib/paths.mjs +42 -19
- package/bin/lib/prd-workflow-routes.mjs +2949 -0
- package/bin/lib/prd-workflow-server.mjs +4884 -0
- package/bin/lib/run-events.mjs +0 -66
- package/bin/lib/schedule-config.mjs +4 -4
- package/bin/lib/skill-runtime.mjs +35 -0
- package/bin/lib/startup-storage-migrations.mjs +274 -0
- package/bin/lib/ui-server.mjs +1092 -18123
- package/bin/lib/user-env.mjs +16 -0
- package/bin/lib/workspace-auto-layout.mjs +234 -0
- package/bin/lib/workspace-flow-store.mjs +478 -0
- package/bin/lib/workspace-graph-merge.mjs +41 -34
- package/bin/lib/workspace-preview.mjs +12 -2
- package/bin/lib/workspace-routes.mjs +3088 -0
- package/bin/lib/workspace-server.mjs +6199 -0
- package/bin/lib/workspace-state.mjs +331 -0
- package/bin/lib/workspace.mjs +2 -1
- package/builtin/nodes/agent_subAgent.md +1 -0
- package/builtin/nodes/control_agent_toBool.md +2 -0
- package/builtin/nodes/control_anyOne.md +2 -0
- package/builtin/nodes/control_cancelled.md +2 -0
- package/builtin/nodes/control_cd_workspace.md +5 -11
- package/builtin/nodes/control_delay.md +2 -0
- package/builtin/nodes/control_end.md +2 -0
- package/builtin/nodes/control_if.md +1 -0
- package/builtin/nodes/control_interval_loop.md +2 -0
- package/builtin/nodes/control_load_mcp.md +24 -0
- package/builtin/nodes/control_load_skills.md +8 -23
- package/builtin/nodes/control_start.md +2 -0
- package/builtin/nodes/control_toBool.md +2 -0
- package/builtin/nodes/control_user_workspace.md +2 -0
- package/builtin/nodes/control_wait_until.md +2 -0
- package/builtin/nodes/display_ascii.md +1 -0
- package/builtin/nodes/display_chart.md +1 -0
- package/builtin/nodes/display_html.md +1 -0
- package/builtin/nodes/display_image.md +1 -0
- package/builtin/nodes/display_markdown.md +1 -0
- package/builtin/nodes/display_mermaid.md +1 -0
- package/builtin/nodes/display_react_app.md +1 -0
- package/builtin/nodes/display_table.md +1 -0
- package/builtin/nodes/provide_bool.md +1 -0
- package/builtin/nodes/provide_file.md +1 -0
- package/builtin/nodes/provide_password.md +1 -0
- package/builtin/nodes/provide_str.md +1 -0
- package/builtin/nodes/tool_display_share_link.md +1 -0
- package/builtin/nodes/tool_get_env.md +2 -0
- package/builtin/nodes/tool_git_checkout.md +1 -0
- package/builtin/nodes/tool_git_worktree_load.md +1 -0
- package/builtin/nodes/tool_git_worktree_unload.md +1 -0
- package/builtin/nodes/tool_gitlab_create_mr.md +1 -0
- package/builtin/nodes/tool_jenkins_build.md +2 -0
- package/builtin/nodes/tool_load_key.md +2 -0
- package/builtin/nodes/tool_nodejs.md +17 -19
- package/builtin/nodes/tool_print.md +2 -0
- package/builtin/nodes/tool_save_key.md +2 -0
- package/builtin/nodes/tool_set_run_env.md +1 -0
- package/builtin/nodes/tool_user_ask.md +2 -0
- package/builtin/nodes/tool_user_check.md +2 -0
- package/builtin/nodes/tool_wecom_send_app_markdown.md +1 -0
- package/builtin/nodes/tool_wecom_send_group_markdown.md +1 -0
- package/builtin/nodes/workspace_one_click_task.md +44 -0
- package/builtin/nodes/workspace_run.md +16 -0
- package/builtin/nodes/workspace_scheduled_run.md +16 -0
- package/builtin/pipelines/module-migrate/scripts/gate.mjs +37 -0
- package/builtin/pipelines/module-migrate/scripts/static-check.mjs +82 -0
- package/builtin/pipelines/module-migrate/workspace.flow.js +172 -0
- package/builtin/pipelines/module-migrate/workspace.layout.json +134 -0
- package/builtin/pipelines/new/scripts/lint-flow.mjs +38 -0
- package/builtin/pipelines/new/workspace.flow.js +91 -0
- package/builtin/pipelines/new/workspace.layout.json +70 -0
- package/builtin/web-ui/dist/assets/{WorkflowAssistantThread-B9xslwI0.js → WorkflowAssistantThread-ClNxY2Wu.js} +1 -1
- package/builtin/web-ui/dist/assets/index-BJzMYRK3.js +870 -0
- package/builtin/web-ui/dist/assets/index-CEXmmwM2.css +1 -0
- package/builtin/web-ui/dist/index.html +2 -2
- package/package.json +3 -1
- package/reference/flow-control-capabilities.md +77 -158
- package/reference/flow-layout.md +1 -1
- package/reference/flow-prompt-handler-check.md +2 -2
- package/skills/agentflow-author-flow/SKILL.md +1 -1
- package/skills/agentflow-cli/SKILL.md +139 -24
- package/skills/agentflow-cli/agents/openai.yaml +2 -2
- package/skills/agentflow-cli/scripts/agentflow-cli.mjs +654 -20
- package/skills/agentflow-cli/scripts/agentflow-runtime.mjs +97 -0
- package/skills/agentflow-flow-add-instances/SKILL.md +1 -1
- package/skills/agentflow-flow-dsl/SKILL.md +206 -0
- package/skills/agentflow-flow-dsl/agents/openai.yaml +4 -0
- package/skills/agentflow-flow-dsl/references/node-calls.md +39 -0
- package/skills/agentflow-flow-edit-node-fields/SKILL.md +1 -1
- package/skills/agentflow-flow-recipes/SKILL.md +7 -4
- package/skills/agentflow-flow-recipes/references/recipes.md +97 -43
- package/skills/agentflow-flow-sync-ui/SKILL.md +1 -1
- package/skills/agentflow-node-dsl/SKILL.md +212 -0
- package/skills/agentflow-node-dsl/agents/openai.yaml +4 -0
- package/skills/agentflow-node-reference/SKILL.md +2 -2
- package/skills/agentflow-node-reference/references/builtin-nodes.md +166 -115
- package/skills/agentflow-runtime-reference/references/runtime.md +1 -1
- package/skills/agentflow-workspace-ascii/SKILL.md +9 -16
- package/skills/agentflow-workspace-graph/SKILL.md +62 -48
- package/skills/agentflow-workspace-html/SKILL.md +7 -2
- package/skills/agentflow-workspace-image/SKILL.md +6 -2
- package/skills/agentflow-workspace-markdown/SKILL.md +14 -21
- package/skills/agentflow-workspace-mermaid/SKILL.md +8 -16
- package/bin/lib/api-runner.mjs +0 -387
- package/bin/lib/apply.mjs +0 -903
- package/bin/lib/composer-flow-instances.mjs +0 -68
- package/bin/lib/composer-flow-skeleton.mjs +0 -334
- package/bin/lib/composer-flow-validate.mjs +0 -47
- package/bin/lib/composer-model-router.mjs +0 -185
- package/bin/lib/composer-node-schema.mjs +0 -303
- package/bin/lib/composer-planner.mjs +0 -751
- package/bin/lib/composer-script-ops.mjs +0 -233
- package/bin/lib/flow-static-preview.mjs +0 -104
- package/bin/lib/hub-login.mjs +0 -54
- package/bin/lib/hub-publish.mjs +0 -159
- package/bin/lib/hub-remote.mjs +0 -189
- package/bin/lib/hub.mjs +0 -299
- package/bin/lib/jenkins.mjs +0 -380
- package/bin/lib/node-execute.mjs +0 -539
- package/bin/lib/normalize-node-tool-command.mjs +0 -97
- package/bin/lib/runtime-context.mjs +0 -243
- package/bin/lib/scheduler.mjs +0 -601
- package/bin/lib/ui-print.mjs +0 -94
- package/bin/pipeline/build-node-prompt.mjs +0 -271
- package/bin/pipeline/check-cache.mjs +0 -191
- package/bin/pipeline/check-flow.mjs +0 -543
- package/bin/pipeline/collect-nodes.mjs +0 -212
- package/bin/pipeline/compute-cache-md5.mjs +0 -177
- package/bin/pipeline/ensure-run-dir.mjs +0 -71
- package/bin/pipeline/gc.mjs +0 -129
- package/bin/pipeline/get-env.mjs +0 -59
- package/bin/pipeline/get-resolved-values.mjs +0 -344
- package/bin/pipeline/load-key.mjs +0 -62
- package/bin/pipeline/parse-flow.mjs +0 -708
- package/bin/pipeline/post-process-control-if.mjs +0 -23
- package/bin/pipeline/post-process-node.mjs +0 -490
- package/bin/pipeline/pre-process-node.mjs +0 -1430
- package/bin/pipeline/resolve-inputs.mjs +0 -201
- package/bin/pipeline/run-tool-nodejs.mjs +0 -167
- package/bin/pipeline/save-key.mjs +0 -93
- package/bin/pipeline/snapshot-prior-round.mjs +0 -70
- package/bin/pipeline/validate-for-ui.mjs +0 -234
- package/bin/pipeline/validate-script-output.mjs +0 -130
- package/bin/pipeline/write-result.mjs +0 -182
- package/builtin/pipelines/module-migrate/flow.yaml +0 -819
- package/builtin/pipelines/new/flow.yaml +0 -545
- package/builtin/pipelines/new/scripts/check-flow.mjs +0 -9
- package/builtin/pipelines/new/scripts/collect-nodes.mjs +0 -211
- package/builtin/web-ui/dist/assets/index-DZ328oSo.css +0 -1
- package/builtin/web-ui/dist/assets/index-DmUV7ZCL.js +0 -888
- package/skills/agentflow-node-authoring/SKILL.md +0 -57
package/bin/lib/main.mjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
4
|
import chalk from "chalk";
|
|
6
|
-
import { apply, replay, resume } from "./apply.mjs";
|
|
7
5
|
import {
|
|
8
6
|
addRoleJson,
|
|
9
7
|
copyBuiltinAgentJson,
|
|
@@ -20,22 +18,16 @@ import {
|
|
|
20
18
|
readFlowJson,
|
|
21
19
|
readNodeJson,
|
|
22
20
|
} from "./catalog-flows.mjs";
|
|
23
|
-
import { writeFlowYaml } from "./flow-write.mjs";
|
|
24
21
|
import { printHelp } from "./help.mjs";
|
|
25
22
|
import { LOG_LEVELS, log, setLogLevel, setMachineReadable } from "./log.mjs";
|
|
26
23
|
import { updateModelLists } from "./model-lists.mjs";
|
|
27
|
-
import {
|
|
24
|
+
import { LEGACY_PIPELINES_DIR, PIPELINES_DIR, USER_AGENTFLOW_PIPELINES_LABEL } from "./paths.mjs";
|
|
28
25
|
import { isValidUuid, runNodeScript } from "./pipeline-scripts.mjs";
|
|
29
26
|
import { Table } from "./table.mjs";
|
|
30
27
|
import { ensureReference, findFlowNameByUuid, getFlowDir, listRunsWithLogs } from "./workspace.mjs";
|
|
31
28
|
import { startUiServer } from "./ui-server.mjs";
|
|
32
|
-
import {
|
|
33
|
-
import { hubPublish } from "./hub-publish.mjs";
|
|
34
|
-
import { hubListRemote, hubDownload } from "./hub-remote.mjs";
|
|
35
|
-
import { cancelScheduledRun, listScheduleStatuses, startScheduler } from "./scheduler.mjs";
|
|
36
|
-
import { installFlowDependency, listMarketplacePackages, publishNodePackage } from "./marketplace.mjs";
|
|
29
|
+
import { listMarketplacePackages, publishNodePackage } from "./marketplace.mjs";
|
|
37
30
|
import { startMcpServer } from "./mcp-server.mjs";
|
|
38
|
-
import { writeStaticFlowPreview } from "./flow-static-preview.mjs";
|
|
39
31
|
import { LEGACY_FLOW_EXECUTION_DISABLED, LEGACY_FLOW_EXECUTION_MESSAGE } from "./legacy-flow-execution.mjs";
|
|
40
32
|
|
|
41
33
|
async function readStdin() {
|
|
@@ -44,6 +36,31 @@ async function readStdin() {
|
|
|
44
36
|
return Buffer.concat(chunks).toString("utf8");
|
|
45
37
|
}
|
|
46
38
|
|
|
39
|
+
/**
|
|
40
|
+
* 把 yaml 迁移的损耗清单打到 stderr。
|
|
41
|
+
*
|
|
42
|
+
* 迁移唯一的卖点就是「丢了什么当场说清楚」,所以这段在成功和拒绝两种结局下都要打——
|
|
43
|
+
* `--allow-loss` 迁过去了不代表没丢东西,只代表用户认了。
|
|
44
|
+
*/
|
|
45
|
+
function writeMigrationLoss(result) {
|
|
46
|
+
for (const r of result.remapped || []) {
|
|
47
|
+
process.stderr.write(`${chalk.cyan("换词")} ${r.id}: ${r.from} -> ${r.to}\n`);
|
|
48
|
+
for (const rn of r.renamedSlots || []) process.stderr.write(` 槽位 ${rn}\n`);
|
|
49
|
+
for (const f of r.droppedFields || []) {
|
|
50
|
+
// 原文照打——新节点装不下,用户得能直接捡走贴到别处
|
|
51
|
+
process.stderr.write(` ${chalk.yellow("丢")} ${f.field}: ${JSON.stringify(f.text)}\n`);
|
|
52
|
+
}
|
|
53
|
+
if (r.caveat) process.stderr.write(` ${chalk.yellow("!")} ${r.caveat}\n`);
|
|
54
|
+
}
|
|
55
|
+
for (const d of result.dropped || []) {
|
|
56
|
+
process.stderr.write(`${chalk.red("丢节点")} ${d.id} (${d.definitionId}):${d.reason}\n`);
|
|
57
|
+
}
|
|
58
|
+
for (const e of result.droppedEdges || []) {
|
|
59
|
+
process.stderr.write(`${chalk.red("丢边")} ${e.source} -> ${e.target}:${e.reason}\n`);
|
|
60
|
+
}
|
|
61
|
+
for (const w of result.warnings || []) process.stderr.write(`${chalk.yellow("warn")} ${w}\n`);
|
|
62
|
+
}
|
|
63
|
+
|
|
47
64
|
export async function main() {
|
|
48
65
|
const argv = process.argv.slice(2);
|
|
49
66
|
let workspaceRoot = process.cwd();
|
|
@@ -61,54 +78,26 @@ export async function main() {
|
|
|
61
78
|
printHelp();
|
|
62
79
|
process.exit(0);
|
|
63
80
|
}
|
|
64
|
-
|
|
65
|
-
if (dryRun) argv.splice(argv.indexOf("--dry-run"), 1);
|
|
81
|
+
if (argv.includes("--dry-run")) argv.splice(argv.indexOf("--dry-run"), 1);
|
|
66
82
|
if (argv.includes("--debug")) {
|
|
67
83
|
setLogLevel(LOG_LEVELS.debug);
|
|
68
84
|
argv.splice(argv.indexOf("--debug"), 1);
|
|
69
85
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
argv.splice(argv.indexOf("--no-force"), 1);
|
|
74
|
-
}
|
|
75
|
-
if (argv.includes("--force")) {
|
|
76
|
-
force = true;
|
|
77
|
-
argv.splice(argv.indexOf("--force"), 1);
|
|
78
|
-
}
|
|
79
|
-
if (argv.includes("--yolo")) {
|
|
80
|
-
force = true;
|
|
81
|
-
argv.splice(argv.indexOf("--yolo"), 1);
|
|
82
|
-
}
|
|
83
|
-
let parallel = false;
|
|
84
|
-
if (argv.includes("--parallel")) {
|
|
85
|
-
parallel = true;
|
|
86
|
-
argv.splice(argv.indexOf("--parallel"), 1);
|
|
87
|
-
}
|
|
88
|
-
if (argv.includes("--no-parallel")) {
|
|
89
|
-
parallel = false;
|
|
90
|
-
argv.splice(argv.indexOf("--no-parallel"), 1);
|
|
86
|
+
// 以下开关只服务已下线的 Start/End 执行,保留解析以免旧脚本把它们当成子命令。
|
|
87
|
+
for (const legacyFlag of ["--no-force", "--force", "--yolo", "--parallel", "--no-parallel"]) {
|
|
88
|
+
while (argv.includes(legacyFlag)) argv.splice(argv.indexOf(legacyFlag), 1);
|
|
91
89
|
}
|
|
92
90
|
if (argv.includes("--machine-readable")) {
|
|
93
91
|
setMachineReadable(true);
|
|
94
92
|
argv.splice(argv.indexOf("--machine-readable"), 1);
|
|
95
93
|
}
|
|
96
94
|
const jsonMode = argv.includes("--json");
|
|
97
|
-
const cliInputs = {};
|
|
98
95
|
while (argv.includes("--input")) {
|
|
99
96
|
const idx = argv.indexOf("--input");
|
|
100
97
|
const pair = argv[idx + 1];
|
|
101
98
|
if (!pair || !pair.includes("=")) {
|
|
102
99
|
throw new Error("Invalid --input format. Use: --input name=value");
|
|
103
100
|
}
|
|
104
|
-
const eqIdx = pair.indexOf("=");
|
|
105
|
-
const name = pair.slice(0, eqIdx);
|
|
106
|
-
const value = pair.slice(eqIdx + 1);
|
|
107
|
-
if (value.startsWith("file:")) {
|
|
108
|
-
cliInputs[name] = { type: "file", path: value.slice(5) };
|
|
109
|
-
} else {
|
|
110
|
-
cliInputs[name] = { type: "str", value };
|
|
111
|
-
}
|
|
112
101
|
argv.splice(idx, 2);
|
|
113
102
|
}
|
|
114
103
|
const sub = shift();
|
|
@@ -129,7 +118,6 @@ export async function main() {
|
|
|
129
118
|
"list-flows",
|
|
130
119
|
"list-nodes",
|
|
131
120
|
"read-flow",
|
|
132
|
-
"write-flow",
|
|
133
121
|
"read-node",
|
|
134
122
|
"copy-builtin",
|
|
135
123
|
"list-agents",
|
|
@@ -140,12 +128,8 @@ export async function main() {
|
|
|
140
128
|
if (jsonMode && jsonOnlySubs.includes(sub)) {
|
|
141
129
|
argv.splice(argv.indexOf("--json"), 1);
|
|
142
130
|
}
|
|
143
|
-
let agentModel = process.env.CURSOR_AGENT_MODEL || null;
|
|
144
131
|
const modelIdx = argv.indexOf("--model");
|
|
145
|
-
if (modelIdx >= 0 && argv[modelIdx + 1])
|
|
146
|
-
agentModel = argv[modelIdx + 1];
|
|
147
|
-
argv.splice(modelIdx, 2);
|
|
148
|
-
}
|
|
132
|
+
if (modelIdx >= 0 && argv[modelIdx + 1]) argv.splice(modelIdx, 2);
|
|
149
133
|
if (sub === "list-flows" && jsonMode) {
|
|
150
134
|
const list = listFlowsJson(workspaceRoot);
|
|
151
135
|
process.stdout.write(JSON.stringify(list) + "\n");
|
|
@@ -243,19 +227,7 @@ export async function main() {
|
|
|
243
227
|
else throw new Error(result.error || "publish-node failed");
|
|
244
228
|
process.exit(result.ok ? 0 : 1);
|
|
245
229
|
}
|
|
246
|
-
|
|
247
|
-
const flowId = shift();
|
|
248
|
-
const spec = shift();
|
|
249
|
-
if (!flowId || !spec) throw new Error("Usage: agentflow marketplace install-node <flow> <nodeSpec> [--json]");
|
|
250
|
-
const flowDir = getFlowDir(workspaceRoot, flowId);
|
|
251
|
-
if (!flowDir) throw new Error(`Flow not found: ${flowId}`);
|
|
252
|
-
const result = installFlowDependency(workspaceRoot, flowDir, spec);
|
|
253
|
-
if (jsonMode) process.stdout.write(JSON.stringify(result) + "\n");
|
|
254
|
-
else if (result.ok) process.stdout.write(`Installed ${result.definitionId} into ${flowId}\n`);
|
|
255
|
-
else throw new Error(result.error || "install-node failed");
|
|
256
|
-
process.exit(result.ok ? 0 : 1);
|
|
257
|
-
}
|
|
258
|
-
throw new Error("Usage: agentflow marketplace <list|publish-node|install-node> [--json]");
|
|
230
|
+
throw new Error("Usage: agentflow marketplace <list|publish-node> [--json]");
|
|
259
231
|
}
|
|
260
232
|
if (sub === "copy-builtin" && jsonMode) {
|
|
261
233
|
const flowId = shift();
|
|
@@ -321,101 +293,105 @@ export async function main() {
|
|
|
321
293
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
322
294
|
process.exit(result.success ? 0 : 1);
|
|
323
295
|
}
|
|
324
|
-
if (sub === "
|
|
325
|
-
let flowSource = "user";
|
|
326
|
-
const flowSourceIdx = argv.indexOf("--flow-source");
|
|
327
|
-
if (flowSourceIdx >= 0 && argv[flowSourceIdx + 1]) {
|
|
328
|
-
flowSource = argv[flowSourceIdx + 1];
|
|
329
|
-
argv.splice(flowSourceIdx, 2);
|
|
330
|
-
}
|
|
331
|
-
if (flowSource === "builtin") {
|
|
332
|
-
process.stderr.write(
|
|
333
|
-
"agentflow: --flow-source builtin 已弃用(包内 builtin 不可写);已按 workspace 写入 .workspace/agentflow/pipelines。\n",
|
|
334
|
-
);
|
|
335
|
-
flowSource = "workspace";
|
|
336
|
-
}
|
|
337
|
-
if (flowSource !== "user" && flowSource !== "workspace") {
|
|
338
|
-
process.stdout.write(
|
|
339
|
-
JSON.stringify({ success: false, error: "Invalid --flow-source (use user or workspace)" }) + "\n",
|
|
340
|
-
);
|
|
341
|
-
process.exit(1);
|
|
342
|
-
}
|
|
343
|
-
const flowId = argv.find((a) => !a.startsWith("--"));
|
|
344
|
-
if (!flowId) {
|
|
345
|
-
process.stdout.write(JSON.stringify({ success: false, error: "Missing flowId" }) + "\n");
|
|
346
|
-
process.exit(1);
|
|
347
|
-
}
|
|
348
|
-
const flowYaml = await readStdin();
|
|
349
|
-
const result = writeFlowYaml(workspaceRoot, flowId, flowSource, flowYaml);
|
|
350
|
-
process.stdout.write(JSON.stringify(result.success ? { success: true } : result) + "\n");
|
|
351
|
-
process.exit(result.success ? 0 : 1);
|
|
352
|
-
}
|
|
353
|
-
if (sub === "flow" && argv[0] === "preview") {
|
|
296
|
+
if (sub === "flow" && argv[0] === "dsl") {
|
|
354
297
|
shift();
|
|
298
|
+
const action = shift();
|
|
355
299
|
const target = shift();
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
300
|
+
const usage = "Usage: agentflow flow dsl <export|import|lint|layout|migrate> <FlowName|dir> [--out <dir>] [--allow-loss] [--all]";
|
|
301
|
+
if (!action || !target) throw new Error(usage);
|
|
302
|
+
let outDir = "";
|
|
303
|
+
const outIdx = argv.indexOf("--out");
|
|
304
|
+
if (outIdx >= 0 && argv[outIdx + 1]) {
|
|
305
|
+
outDir = path.resolve(workspaceRoot, argv[outIdx + 1]);
|
|
306
|
+
argv.splice(outIdx, 2);
|
|
307
|
+
}
|
|
308
|
+
// 不叫 --force:那个名字在上面被当成已下线执行栈的遗留开关提前吃掉了
|
|
309
|
+
const lossIdx = argv.indexOf("--allow-loss");
|
|
310
|
+
const force = lossIdx >= 0;
|
|
311
|
+
if (force) argv.splice(lossIdx, 1);
|
|
312
|
+
const allIdx = argv.indexOf("--all");
|
|
313
|
+
const all = allIdx >= 0;
|
|
314
|
+
if (all) argv.splice(allIdx, 1);
|
|
315
|
+
if (argv.length > 0) throw new Error(`Unknown flow dsl option: ${argv[0]}`);
|
|
316
|
+
if (all && action !== "layout") throw new Error("--all 只用于 flow dsl layout");
|
|
366
317
|
|
|
367
|
-
const
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
marketplaceScope: "all",
|
|
390
|
-
});
|
|
391
|
-
const result = writeStaticFlowPreview({
|
|
392
|
-
flowId,
|
|
393
|
-
flowPath: previewFlowPath,
|
|
394
|
-
nodeCatalog,
|
|
395
|
-
outputPath,
|
|
396
|
-
distDir: path.join(path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url)))), "builtin", "web-ui", "dist"),
|
|
397
|
-
});
|
|
398
|
-
const url = pathToFileURL(result.outputPath).href;
|
|
399
|
-
process.stderr.write(`AgentFlow static preview: ${result.outputPath}\nSource: ${previewFlowPath}\n`);
|
|
400
|
-
if (!noOpen) {
|
|
401
|
-
if (process.platform === "win32") {
|
|
402
|
-
const child = spawn("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" });
|
|
403
|
-
child.unref();
|
|
404
|
-
} else if (process.platform === "darwin") {
|
|
405
|
-
const child = spawn("open", [url], { detached: true, stdio: "ignore" });
|
|
406
|
-
child.unref();
|
|
318
|
+
const direct = path.resolve(workspaceRoot, target);
|
|
319
|
+
const dir = fs.existsSync(direct) && fs.statSync(direct).isDirectory()
|
|
320
|
+
? direct
|
|
321
|
+
: getFlowDir(workspaceRoot, target);
|
|
322
|
+
if (!dir || !fs.existsSync(dir)) throw new Error(`Flow not found: ${target}`);
|
|
323
|
+
|
|
324
|
+
const { exportFlowDsl, importFlowDsl, layoutWorkspaceFlowDir, lintFlowDir, migrateFlowDirToDsl } = await import("./flow-dsl/cli.mjs");
|
|
325
|
+
|
|
326
|
+
if (action === "migrate") {
|
|
327
|
+
const result = migrateFlowDirToDsl(dir, { force, marketplaceRoot: workspaceRoot });
|
|
328
|
+
if (jsonMode) { process.stdout.write(JSON.stringify(result) + "\n"); return; }
|
|
329
|
+
if (result.format === "empty") process.stderr.write(`${chalk.yellow("skip")} ${dir}:没有图\n`);
|
|
330
|
+
else if (!result.migrated && result.format === "dsl") process.stderr.write(`${chalk.green("ok")} ${dir}:已经是代码形态\n`);
|
|
331
|
+
else if (result.migrated) {
|
|
332
|
+
process.stderr.write(`${chalk.green("ok")} ${dir} -> workspace.flow.js(来自 ${result.source})\n`);
|
|
333
|
+
for (const rel of result.externals) process.stderr.write(` ${rel}\n`);
|
|
334
|
+
} else if (result.leftYaml) {
|
|
335
|
+
// 够不着代码形态,但已经离开 yaml——图从此读得出、画得出、跑得动
|
|
336
|
+
process.stderr.write(`${chalk.green("ok")} ${dir} -> workspace.graph.json(来自 flow.yaml)\n`);
|
|
337
|
+
process.stderr.write(` ${chalk.dim(`还差一步到代码:${result.degradedReason}`)}\n`);
|
|
338
|
+
} else if (result.format === "yaml") {
|
|
339
|
+
process.stderr.write(`${chalk.red("keep")} ${dir}:${result.degradedReason}\n`);
|
|
407
340
|
} else {
|
|
408
|
-
|
|
409
|
-
|
|
341
|
+
process.stderr.write(`${chalk.red("keep")} ${dir}:${result.degradedReason},保留 workspace.graph.json\n`);
|
|
342
|
+
process.exitCode = 1;
|
|
410
343
|
}
|
|
344
|
+
// 损耗清单在成功和拒绝两种结局下都要打出来——`--allow-loss` 迁过去了不代表没丢东西
|
|
345
|
+
writeMigrationLoss(result);
|
|
346
|
+
if (result.format === "yaml" && !result.migrated) process.exitCode = 1;
|
|
347
|
+
return;
|
|
411
348
|
}
|
|
412
|
-
|
|
349
|
+
|
|
350
|
+
if (action === "export") {
|
|
351
|
+
const result = exportFlowDsl(dir, outDir);
|
|
352
|
+
if (jsonMode) { process.stdout.write(JSON.stringify(result) + "\n"); return; }
|
|
353
|
+
else {
|
|
354
|
+
process.stderr.write(`Exported to ${result.outDir}\n`);
|
|
355
|
+
for (const rel of result.written) process.stderr.write(` ${rel}\n`);
|
|
356
|
+
}
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (action === "import") {
|
|
360
|
+
const result = importFlowDsl(dir, outDir);
|
|
361
|
+
if (jsonMode) { process.stdout.write(JSON.stringify(result) + "\n"); return; }
|
|
362
|
+
else {
|
|
363
|
+
process.stderr.write(`Wrote ${result.graphPath}\n ${result.nodeCount} 节点 / ${result.edgeCount} 边\n`);
|
|
364
|
+
for (const w of result.warnings) process.stderr.write(` warning: ${w}\n`);
|
|
365
|
+
}
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
if (action === "lint") {
|
|
369
|
+
const result = lintFlowDir(dir, { workspaceRoot });
|
|
370
|
+
if (jsonMode) process.stdout.write(JSON.stringify({ errors: result.errors, warnings: result.warnings }) + "\n");
|
|
371
|
+
else {
|
|
372
|
+
for (const e of result.errors) process.stderr.write(`${chalk.red("error")} ${e}\n`);
|
|
373
|
+
for (const w of result.warnings) process.stderr.write(`${chalk.yellow("warn")} ${w}\n`);
|
|
374
|
+
if (!result.errors.length) process.stderr.write(`${chalk.green("ok")} lint 通过\n`);
|
|
375
|
+
}
|
|
376
|
+
if (result.errors.length) process.exitCode = 1;
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
if (action === "layout") {
|
|
380
|
+
const result = layoutWorkspaceFlowDir(dir, { all, workspaceRoot });
|
|
381
|
+
if (jsonMode) process.stdout.write(JSON.stringify(result) + "\n");
|
|
382
|
+
else process.stderr.write(`${chalk.green("ok")} ${result.positioned}/${result.nodeCount} 个节点已${all ? "重新" : "补充"}排版\n ${result.layoutPath}\n`);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
throw new Error(usage);
|
|
386
|
+
}
|
|
387
|
+
if (sub === "flow") {
|
|
388
|
+
// `flow preview` 曾经在这儿。它把 flow.yaml 原文塞进页面,代码化流程没有 yaml 可塞;
|
|
389
|
+
// Web 的 /api/workspace/preview 接的是图对象,本来就通用,所以删掉而不是重写。
|
|
390
|
+
throw new Error("Usage: agentflow flow dsl <export|import|lint|layout|migrate> <FlowName|dir> [--out <dir>] [--all]");
|
|
413
391
|
}
|
|
414
392
|
if (sub === "ui") {
|
|
415
393
|
let port = 8765;
|
|
416
394
|
let host = process.env.AGENTFLOW_UI_HOST || "127.0.0.1";
|
|
417
|
-
let schedulerEnabled = false;
|
|
418
|
-
let schedulerPollMs;
|
|
419
395
|
let hideCommunityLinks = /^(1|true|yes|on)$/i.test(String(process.env.AGENTFLOW_HIDE_COMMUNITY_LINKS || ""));
|
|
420
396
|
const portIdx = argv.indexOf("--port");
|
|
421
397
|
if (portIdx >= 0 && argv[portIdx + 1]) {
|
|
@@ -427,19 +403,6 @@ export async function main() {
|
|
|
427
403
|
host = argv[hostIdx + 1];
|
|
428
404
|
argv.splice(hostIdx, 2);
|
|
429
405
|
}
|
|
430
|
-
if (argv.includes("--scheduler")) {
|
|
431
|
-
schedulerEnabled = true;
|
|
432
|
-
argv.splice(argv.indexOf("--scheduler"), 1);
|
|
433
|
-
}
|
|
434
|
-
if (argv.includes("--no-scheduler")) {
|
|
435
|
-
schedulerEnabled = false;
|
|
436
|
-
argv.splice(argv.indexOf("--no-scheduler"), 1);
|
|
437
|
-
}
|
|
438
|
-
const schedulerPollIdx = argv.indexOf("--scheduler-poll-ms");
|
|
439
|
-
if (schedulerPollIdx >= 0 && argv[schedulerPollIdx + 1]) {
|
|
440
|
-
schedulerPollMs = parseInt(argv[schedulerPollIdx + 1], 10);
|
|
441
|
-
argv.splice(schedulerPollIdx, 2);
|
|
442
|
-
}
|
|
443
406
|
const noOpen = argv.includes("--no-open");
|
|
444
407
|
if (noOpen) argv.splice(argv.indexOf("--no-open"), 1);
|
|
445
408
|
if (argv.includes("--hide-community-links")) {
|
|
@@ -453,11 +416,6 @@ export async function main() {
|
|
|
453
416
|
throw new Error("Invalid --host");
|
|
454
417
|
}
|
|
455
418
|
await startUiServer({ workspaceRoot, port, host, hideCommunityLinks });
|
|
456
|
-
if (schedulerEnabled) {
|
|
457
|
-
startScheduler(workspaceRoot, { pollMs: schedulerPollMs }).catch((e) => {
|
|
458
|
-
log.error("Scheduler failed: " + ((e && e.message) || String(e)));
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
419
|
const browserHost = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
|
|
462
420
|
const url = "http://" + (browserHost.includes(":") ? `[${browserHost}]` : browserHost) + ":" + port;
|
|
463
421
|
process.stderr.write("AgentFlow UI: " + url + (browserHost === host ? "" : ` (listening on ${host}:${port})`) + "\n");
|
|
@@ -475,130 +433,12 @@ export async function main() {
|
|
|
475
433
|
}
|
|
476
434
|
await new Promise(() => {});
|
|
477
435
|
}
|
|
478
|
-
if (sub === "scheduler") {
|
|
479
|
-
const action = shift();
|
|
480
|
-
if (action === "start") {
|
|
481
|
-
let pollMs;
|
|
482
|
-
const pollIdx = argv.indexOf("--poll-ms");
|
|
483
|
-
if (pollIdx >= 0 && argv[pollIdx + 1]) {
|
|
484
|
-
pollMs = parseInt(argv[pollIdx + 1], 10);
|
|
485
|
-
argv.splice(pollIdx, 2);
|
|
486
|
-
}
|
|
487
|
-
const once = argv.includes("--once");
|
|
488
|
-
if (once) argv.splice(argv.indexOf("--once"), 1);
|
|
489
|
-
await startScheduler(workspaceRoot, { pollMs, once });
|
|
490
|
-
process.exit(0);
|
|
491
|
-
}
|
|
492
|
-
if (action === "status") {
|
|
493
|
-
if (jsonMode) {
|
|
494
|
-
process.stdout.write(JSON.stringify({ schedules: listScheduleStatuses(workspaceRoot) }) + "\n");
|
|
495
|
-
process.exit(0);
|
|
496
|
-
}
|
|
497
|
-
const rows = listScheduleStatuses(workspaceRoot);
|
|
498
|
-
const table = new Table({ head: ["flow", "source", "enabled", "cron", "timezone", "next", "running", "waiting", "lastRun", "error"], style: { head: [] } });
|
|
499
|
-
for (const r of rows) {
|
|
500
|
-
table.push([
|
|
501
|
-
r.flowId,
|
|
502
|
-
r.flowSource,
|
|
503
|
-
r.enabled ? "yes" : "no",
|
|
504
|
-
r.cron || "",
|
|
505
|
-
r.timezone || "",
|
|
506
|
-
r.nextRunAt || "",
|
|
507
|
-
r.running ? "yes" : "no",
|
|
508
|
-
String(r.waiting || 0),
|
|
509
|
-
r.lastRunUuid || "",
|
|
510
|
-
r.lastError || "",
|
|
511
|
-
]);
|
|
512
|
-
}
|
|
513
|
-
process.stdout.write(table.toString() + "\n");
|
|
514
|
-
process.exit(0);
|
|
515
|
-
}
|
|
516
|
-
if (action === "cancel") {
|
|
517
|
-
const flowId = shift();
|
|
518
|
-
const uuid = shift();
|
|
519
|
-
if (!flowId || !uuid) throw new Error("Usage: agentflow scheduler cancel <flow> <uuid> [--json]");
|
|
520
|
-
const result = cancelScheduledRun(workspaceRoot, flowId, uuid);
|
|
521
|
-
if (jsonMode) {
|
|
522
|
-
process.stdout.write(JSON.stringify(result) + "\n");
|
|
523
|
-
} else if (result.ok) {
|
|
524
|
-
process.stdout.write(`Cancelled ${flowId}/${uuid}; updated waits: ${result.updatedWaits}\n`);
|
|
525
|
-
} else {
|
|
526
|
-
throw new Error(result.error || "cancel failed");
|
|
527
|
-
}
|
|
528
|
-
process.exit(result.ok ? 0 : 1);
|
|
529
|
-
}
|
|
530
|
-
throw new Error("Usage: agentflow scheduler <start|status|cancel> [--once] [--poll-ms <ms>] [--json]");
|
|
531
|
-
}
|
|
532
436
|
// ──── Hub commands ────
|
|
533
|
-
if (sub === "login") {
|
|
534
|
-
await hubLogin(argv);
|
|
535
|
-
process.exit(0);
|
|
536
|
-
}
|
|
537
|
-
if (sub === "logout") {
|
|
538
|
-
hubLogout();
|
|
539
|
-
process.exit(0);
|
|
540
|
-
}
|
|
541
|
-
if (sub === "publish") {
|
|
542
|
-
await hubPublish(workspaceRoot, argv);
|
|
543
|
-
process.exit(0);
|
|
544
|
-
}
|
|
545
|
-
if (sub === "list-remote") {
|
|
546
|
-
await hubListRemote(argv);
|
|
547
|
-
process.exit(0);
|
|
548
|
-
}
|
|
549
|
-
if (sub === "download") {
|
|
550
|
-
await hubDownload(argv);
|
|
551
|
-
process.exit(0);
|
|
552
|
-
}
|
|
553
437
|
// ──── Local commands ────
|
|
554
438
|
if (sub === "list") {
|
|
555
439
|
listPipelines(workspaceRoot);
|
|
556
|
-
} else if (sub === "apply") {
|
|
557
|
-
|
|
558
|
-
const aiMode = argv[0] === "-ai" || argv[0] === "--ai";
|
|
559
|
-
if (aiMode) {
|
|
560
|
-
argv.shift();
|
|
561
|
-
const step = argv.shift();
|
|
562
|
-
if (!step || !APPLY_AI_STEPS.includes(step)) {
|
|
563
|
-
throw new Error(
|
|
564
|
-
"Missing or invalid step. Usage: agentflow apply -ai <step> <args...>. Steps: " + APPLY_AI_STEPS.join(", "),
|
|
565
|
-
);
|
|
566
|
-
}
|
|
567
|
-
if (argv.length === 0) {
|
|
568
|
-
throw new Error("Missing args for step " + step + ". Example: agentflow apply -ai ensure-run-dir <workspaceRoot> [uuid] <flowName>");
|
|
569
|
-
}
|
|
570
|
-
const stepWorkspaceRoot = path.resolve(argv[0]);
|
|
571
|
-
ensureReference(stepWorkspaceRoot);
|
|
572
|
-
const scriptName = step + ".mjs";
|
|
573
|
-
const result = runNodeScript(stepWorkspaceRoot, scriptName, argv, { captureStdout: false });
|
|
574
|
-
process.exit(result.status ?? 0);
|
|
575
|
-
}
|
|
576
|
-
const first = shift();
|
|
577
|
-
if (!first) throw new Error("Missing FlowName or uuid. Usage: agentflow apply <FlowName> [uuid] | agentflow apply <uuid>");
|
|
578
|
-
let flowName, uuidArg;
|
|
579
|
-
if (isValidUuid(first)) {
|
|
580
|
-
flowName = findFlowNameByUuid(workspaceRoot, first);
|
|
581
|
-
if (!flowName) throw new Error("No run found for uuid " + first + ". Run apply with FlowName first (e.g. agentflow apply <FlowName>).");
|
|
582
|
-
uuidArg = first;
|
|
583
|
-
} else {
|
|
584
|
-
flowName = first;
|
|
585
|
-
uuidArg = isValidUuid(argv[0]) ? shift() : undefined;
|
|
586
|
-
}
|
|
587
|
-
await apply(workspaceRoot, flowName, uuidArg, dryRun, agentModel, force, parallel, cliInputs);
|
|
588
|
-
} else if (sub === "resume") {
|
|
589
|
-
if (LEGACY_FLOW_EXECUTION_DISABLED) throw new Error(LEGACY_FLOW_EXECUTION_MESSAGE);
|
|
590
|
-
const flowName = shift();
|
|
591
|
-
const uuidArg = shift();
|
|
592
|
-
if (!flowName || !uuidArg) throw new Error("Usage: agentflow resume <FlowName> <uuid> [instanceId]");
|
|
593
|
-
const instanceIdOpt = argv.length > 0 && !argv[0].startsWith("--") ? shift() : undefined;
|
|
594
|
-
await resume(workspaceRoot, flowName, uuidArg, instanceIdOpt, agentModel, force, parallel);
|
|
595
|
-
} else if (sub === "replay") {
|
|
596
|
-
if (LEGACY_FLOW_EXECUTION_DISABLED) throw new Error(LEGACY_FLOW_EXECUTION_MESSAGE);
|
|
597
|
-
const a = shift(),
|
|
598
|
-
b = shift(),
|
|
599
|
-
c = shift();
|
|
600
|
-
if (!a || !b) throw new Error("Usage: agentflow replay <uuid> <instanceId> or agentflow replay <flowName> <uuid> <instanceId>");
|
|
601
|
-
await replay(workspaceRoot, a, b, c, agentModel, force);
|
|
440
|
+
} else if (sub === "apply" || sub === "resume" || sub === "replay") {
|
|
441
|
+
throw new Error(LEGACY_FLOW_EXECUTION_MESSAGE);
|
|
602
442
|
} else if (sub === "run-status") {
|
|
603
443
|
const flowName = shift();
|
|
604
444
|
const uuidArg = shift();
|
|
@@ -663,6 +503,33 @@ export async function main() {
|
|
|
663
503
|
", or builtin)",
|
|
664
504
|
);
|
|
665
505
|
}
|
|
506
|
+
// Workspace 图归 flow dsl lint 管。validate-flow.mjs 校验的是 flow.yaml,而 Workspace
|
|
507
|
+
// 流程的 flow.yaml 只是个空壳,让它去校验只会得到「必须包含 instances 且至少一个节点」
|
|
508
|
+
// 这种必然失败的结论。
|
|
509
|
+
const { lintWorkspaceFlowDir } = await import("./flow-dsl/cli.mjs");
|
|
510
|
+
const workspaceLint = lintWorkspaceFlowDir(flowDir);
|
|
511
|
+
if (workspaceLint.format !== "empty") {
|
|
512
|
+
if (wantJson || process.stdout.isTTY !== true) {
|
|
513
|
+
process.stdout.write(JSON.stringify({
|
|
514
|
+
ok: workspaceLint.errors.length === 0,
|
|
515
|
+
target: "workspace",
|
|
516
|
+
errors: workspaceLint.errors,
|
|
517
|
+
warnings: workspaceLint.warnings,
|
|
518
|
+
}) + "\n");
|
|
519
|
+
} else {
|
|
520
|
+
process.stdout.write(`\n${chalk.bold("校验: ")}${flowName} ${
|
|
521
|
+
workspaceLint.errors.length ? chalk.red("✗ 未通过") : chalk.green("✓ 通过")
|
|
522
|
+
}\n`);
|
|
523
|
+
for (const e of workspaceLint.errors) process.stdout.write(`${chalk.red(" • ")}${e}\n`);
|
|
524
|
+
for (const w of workspaceLint.warnings) process.stdout.write(`${chalk.yellow(" ! ")}${w}\n`);
|
|
525
|
+
if (workspaceLint.format === "json") {
|
|
526
|
+
process.stdout.write(chalk.dim(" (这张图还是 workspace.graph.json;跑 agentflow flow dsl migrate 转成代码)\n"));
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
process.exit(workspaceLint.errors.length ? 1 : 0);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
|
|
666
533
|
const args = [workspaceRoot, flowName, flowDir];
|
|
667
534
|
if (uuidArg) args.push(uuidArg);
|
|
668
535
|
const result = runNodeScript(workspaceRoot, "validate-flow.mjs", args, { captureStdout: true });
|
|
@@ -724,7 +591,6 @@ export async function main() {
|
|
|
724
591
|
} else if (
|
|
725
592
|
sub === "list-flows" ||
|
|
726
593
|
sub === "read-flow" ||
|
|
727
|
-
sub === "write-flow" ||
|
|
728
594
|
sub === "read-node" ||
|
|
729
595
|
sub === "copy-builtin" ||
|
|
730
596
|
sub === "copy-builtin-agent" ||
|
|
@@ -736,7 +602,7 @@ export async function main() {
|
|
|
736
602
|
throw new Error(
|
|
737
603
|
"Unknown command: " +
|
|
738
604
|
sub +
|
|
739
|
-
". Use
|
|
605
|
+
". Use list, ui, validate, run-status, extract-thinking, flow, marketplace, mcp.",
|
|
740
606
|
);
|
|
741
607
|
}
|
|
742
608
|
}
|