@fieldwangai/agentflow 0.1.149 → 0.1.154
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 +20 -33
- 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 +167 -88
- 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 +276 -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 +268 -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 +10 -30
- package/bin/lib/html-escape.mjs +19 -0
- package/bin/lib/http-util.mjs +49 -0
- package/bin/lib/legacy-flow-execution.mjs +43 -0
- package/bin/lib/locales/en.json +1 -1
- package/bin/lib/locales/zh.json +1 -1
- package/bin/lib/main.mjs +153 -283
- 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 +1106 -18013
- 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 +74 -0
- 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-DPbR2UaN.js → WorkflowAssistantThread-CKClwj96.js} +1 -1
- package/builtin/web-ui/dist/assets/index-BZ5KqLur.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 +2 -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 +8 -47
- package/skills/agentflow-cli/SKILL.md +158 -25
- package/skills/agentflow-cli/agents/openai.yaml +2 -2
- package/skills/agentflow-cli/scripts/agentflow-cli.mjs +668 -18
- package/skills/agentflow-cli/scripts/agentflow-runtime.mjs +97 -0
- package/skills/agentflow-flow-add-instances/SKILL.md +7 -248
- 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 +4 -73
- package/skills/agentflow-flow-recipes/SKILL.md +7 -18
- package/skills/agentflow-flow-recipes/references/recipes.md +97 -43
- package/skills/agentflow-flow-sync-ui/SKILL.md +3 -54
- 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 +5 -4
- package/skills/agentflow-node-reference/references/builtin-nodes.md +166 -115
- package/skills/agentflow-placeholder-reference/SKILL.md +2 -2
- package/skills/agentflow-runtime-reference/SKILL.md +2 -2
- 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-BSCpd5la.js +0 -889
- package/builtin/web-ui/dist/assets/index-DZ328oSo.css +0 -1
- package/skills/agentflow-node-authoring/SKILL.md +0 -57
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 代码节点包的执行入口。
|
|
4
|
+
*
|
|
5
|
+
* 由 `workspaceMarketplaceRuntimeCommand` 生成的命令调用:
|
|
6
|
+
*
|
|
7
|
+
* node <此文件> <entryAbs>
|
|
8
|
+
*
|
|
9
|
+
* 节点包的 `index.mjs` 是个 **模块**,不是脚本——直接 `node index.mjs` 只会定义完就退出。
|
|
10
|
+
* 这里负责把 Workspace 运行时的环境契约翻译成 `run()` 的三个参数:
|
|
11
|
+
*
|
|
12
|
+
* inputs 来自 AGENTFLOW_INPUTS_JSON,按槽位名取值
|
|
13
|
+
* outputs 来自 AGENTFLOW_OUTPUTS_ABS_JSON,槽位名 -> 该写入的绝对路径
|
|
14
|
+
* dirs workspaceRoot / nodeRunDir / nodeTmpDir / outputsDir
|
|
15
|
+
*
|
|
16
|
+
* 约定与 tool_nodejs 一致:退出码即成败,stdout 即节点 result,不做 JSON 包装。
|
|
17
|
+
*/
|
|
18
|
+
import path from "node:path";
|
|
19
|
+
import { pathToFileURL } from "node:url";
|
|
20
|
+
|
|
21
|
+
function parseJsonEnv(name) {
|
|
22
|
+
const raw = process.env[name];
|
|
23
|
+
if (!raw) return {};
|
|
24
|
+
try {
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
27
|
+
} catch {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const entry = process.argv[2];
|
|
33
|
+
if (!entry) {
|
|
34
|
+
console.error("node-package-bootstrap: 缺少入口文件参数");
|
|
35
|
+
process.exit(2);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const entryAbs = path.resolve(entry);
|
|
39
|
+
let mod;
|
|
40
|
+
try {
|
|
41
|
+
mod = await import(pathToFileURL(entryAbs).href);
|
|
42
|
+
} catch (e) {
|
|
43
|
+
console.error(`节点包入口加载失败 ${entryAbs}: ${(e && e.stack) || e}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const run = typeof mod.run === "function"
|
|
48
|
+
? mod.run
|
|
49
|
+
: typeof mod.default?.run === "function"
|
|
50
|
+
? mod.default.run
|
|
51
|
+
: null;
|
|
52
|
+
if (!run) {
|
|
53
|
+
console.error(`节点包 ${entryAbs} 没有导出 run();请 \`export async function run(inputs, outputs, dirs)\``);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const inputs = parseJsonEnv("AGENTFLOW_INPUTS_JSON");
|
|
58
|
+
const outputs = parseJsonEnv("AGENTFLOW_OUTPUTS_ABS_JSON");
|
|
59
|
+
const dirs = {
|
|
60
|
+
workspaceRoot: process.env.AGENTFLOW_WORKSPACE_ROOT || process.cwd(),
|
|
61
|
+
nodeRunDir: process.env.AGENTFLOW_NODE_RUN_DIR || process.cwd(),
|
|
62
|
+
nodeTmpDir: process.env.AGENTFLOW_NODE_TMP_DIR || process.cwd(),
|
|
63
|
+
outputsDir: process.env.AGENTFLOW_OUTPUTS_DIR || process.cwd(),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
await run(inputs, outputs, dirs);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
// 节点靠抛错来失败;把栈打到 stderr,退出码非零
|
|
70
|
+
console.error((e && e.stack) || String(e));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 代码节点包的清单提取。
|
|
3
|
+
*
|
|
4
|
+
* 一个节点包 = 一个目录,`index.mjs` 同时是「声明」和「实现」:
|
|
5
|
+
*
|
|
6
|
+
* ```js
|
|
7
|
+
* export default {
|
|
8
|
+
* id: "collect_metrics",
|
|
9
|
+
* version: "1.0.0",
|
|
10
|
+
* name: "统计流程语料",
|
|
11
|
+
* inputs: { date: { type: "text", description: "查询日期" } },
|
|
12
|
+
* outputs: { result: { type: "text" } },
|
|
13
|
+
* };
|
|
14
|
+
*
|
|
15
|
+
* export async function run(inputs, outputs, dirs) { ... }
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* 声明部分由 acorn **静态解析**得到——列节点面板、校验槽位、渲染画布都不会执行包里的
|
|
19
|
+
* 代码。这是硬约束:目录扫描期执行第三方代码既慢又不安全。
|
|
20
|
+
*
|
|
21
|
+
* 代价是 `export default` 必须是纯字面量。任何变量引用、函数调用、展开运算都会被拒绝,
|
|
22
|
+
* 并给出明确报错,而不是悄悄退化成空清单。
|
|
23
|
+
*/
|
|
24
|
+
import fs from "fs";
|
|
25
|
+
import path from "path";
|
|
26
|
+
import { parse as acornParse } from "acorn";
|
|
27
|
+
|
|
28
|
+
export const NODE_PACKAGE_ENTRY = "index.mjs";
|
|
29
|
+
|
|
30
|
+
/** 槽位类型;与 builtin/nodes/*.md 的 `type:` 取值一致。 */
|
|
31
|
+
const SLOT_TYPES = new Set(["text", "file", "bool", "node", "image", "json"]);
|
|
32
|
+
|
|
33
|
+
function staticEval(node, where) {
|
|
34
|
+
if (!node) throw new Error(`${where}: 空表达式`);
|
|
35
|
+
switch (node.type) {
|
|
36
|
+
case "Literal":
|
|
37
|
+
return node.value;
|
|
38
|
+
case "TemplateLiteral":
|
|
39
|
+
if (node.expressions.length) throw new Error(`${where}: 模板字符串不能有插值`);
|
|
40
|
+
return node.quasis.map((q) => q.value.cooked).join("");
|
|
41
|
+
case "ArrayExpression":
|
|
42
|
+
return node.elements.map((el, i) => staticEval(el, `${where}[${i}]`));
|
|
43
|
+
case "ObjectExpression": {
|
|
44
|
+
const out = {};
|
|
45
|
+
for (const prop of node.properties) {
|
|
46
|
+
if (prop.type !== "Property") throw new Error(`${where}: 对象里不允许展开运算符`);
|
|
47
|
+
if (prop.computed) throw new Error(`${where}: 对象里不允许计算属性名`);
|
|
48
|
+
const key = prop.key.type === "Identifier" ? prop.key.name : prop.key.value;
|
|
49
|
+
out[key] = staticEval(prop.value, `${where}.${key}`);
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
case "UnaryExpression":
|
|
54
|
+
if (node.operator === "-") return -staticEval(node.argument, where);
|
|
55
|
+
if (node.operator === "+") return +staticEval(node.argument, where);
|
|
56
|
+
throw new Error(`${where}: 不允许的一元运算 ${node.operator}`);
|
|
57
|
+
default:
|
|
58
|
+
throw new Error(`${where}: 只允许字面量,不允许 ${node.type}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 从节点包入口静态提取 `export default` 声明。
|
|
64
|
+
* @returns {object|null} 解析不出声明时返回 null;语法/字面量违规时抛错。
|
|
65
|
+
*/
|
|
66
|
+
export function readNodePackageDeclaration(entryPath) {
|
|
67
|
+
const src = fs.readFileSync(entryPath, "utf-8");
|
|
68
|
+
let ast;
|
|
69
|
+
try {
|
|
70
|
+
ast = acornParse(src, { ecmaVersion: 2022, sourceType: "module" });
|
|
71
|
+
} catch (e) {
|
|
72
|
+
throw new Error(`${path.basename(entryPath)} 解析失败:${(e && e.message) || e}`);
|
|
73
|
+
}
|
|
74
|
+
for (const stmt of ast.body) {
|
|
75
|
+
if (stmt.type !== "ExportDefaultDeclaration") continue;
|
|
76
|
+
return staticEval(stmt.declaration, "export default");
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** 入口是否导出了 `run`(命名导出或 `export default { run }` 之外的函数声明)。 */
|
|
82
|
+
export function nodePackageExportsRun(entryPath) {
|
|
83
|
+
const src = fs.readFileSync(entryPath, "utf-8");
|
|
84
|
+
let ast;
|
|
85
|
+
try {
|
|
86
|
+
ast = acornParse(src, { ecmaVersion: 2022, sourceType: "module" });
|
|
87
|
+
} catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
for (const stmt of ast.body) {
|
|
91
|
+
if (stmt.type !== "ExportNamedDeclaration") continue;
|
|
92
|
+
const decl = stmt.declaration;
|
|
93
|
+
if (decl?.type === "FunctionDeclaration" && decl.id?.name === "run") return true;
|
|
94
|
+
if (decl?.type === "VariableDeclaration") {
|
|
95
|
+
for (const d of decl.declarations) if (d.id?.type === "Identifier" && d.id.name === "run") return true;
|
|
96
|
+
}
|
|
97
|
+
for (const spec of stmt.specifiers || []) {
|
|
98
|
+
const exported = spec.exported?.name ?? spec.exported?.value;
|
|
99
|
+
if (exported === "run") return true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 声明里的 `inputs` / `outputs` 是对象映射(顺序即槽位顺序);平台要的是槽位数组,
|
|
107
|
+
* 且首位固定是控制槽 prev / next。
|
|
108
|
+
*/
|
|
109
|
+
export function slotMapToList(map, kind) {
|
|
110
|
+
const first = kind === "input"
|
|
111
|
+
? { type: "node", name: "prev", default: "" }
|
|
112
|
+
: { type: "node", name: "next", default: "" };
|
|
113
|
+
const out = [first];
|
|
114
|
+
if (!map || typeof map !== "object" || Array.isArray(map)) return out;
|
|
115
|
+
for (const [name, rawSpec] of Object.entries(map)) {
|
|
116
|
+
const spec = typeof rawSpec === "string" ? { type: rawSpec } : (rawSpec && typeof rawSpec === "object" ? rawSpec : {});
|
|
117
|
+
const type = String(spec.type || "text").trim();
|
|
118
|
+
if (!SLOT_TYPES.has(type)) {
|
|
119
|
+
throw new Error(`${kind} 槽位 ${name}: 未知类型 ${type}(可选 ${[...SLOT_TYPES].join(" / ")})`);
|
|
120
|
+
}
|
|
121
|
+
const slot = { type, name: String(name), default: spec.default == null ? "" : String(spec.default) };
|
|
122
|
+
if (spec.description != null) slot.description = String(spec.description);
|
|
123
|
+
if (spec.required != null) slot.required = Boolean(spec.required);
|
|
124
|
+
out.push(slot);
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 把节点包声明转成 marketplace manifest 的形状(`node.yaml` 解析后的等价物)。
|
|
131
|
+
* @returns {object|null}
|
|
132
|
+
*/
|
|
133
|
+
export function nodePackageDeclarationToManifest(decl, packageDir) {
|
|
134
|
+
if (!decl || typeof decl !== "object" || Array.isArray(decl)) return null;
|
|
135
|
+
const id = decl.id != null ? String(decl.id).trim() : path.basename(packageDir);
|
|
136
|
+
const version = decl.version != null ? String(decl.version).trim() : "";
|
|
137
|
+
if (!id || !version) return null;
|
|
138
|
+
return {
|
|
139
|
+
id,
|
|
140
|
+
version,
|
|
141
|
+
displayName: decl.name != null ? String(decl.name) : id,
|
|
142
|
+
description: decl.description != null ? String(decl.description) : "",
|
|
143
|
+
input: slotMapToList(decl.inputs, "input"),
|
|
144
|
+
output: slotMapToList(decl.outputs, "output"),
|
|
145
|
+
baseDefinitionId: "tool_nodejs",
|
|
146
|
+
runtime: { type: "tool_nodejs", entry: NODE_PACKAGE_ENTRY, mode: "module" },
|
|
147
|
+
...(decl.ownerUserId != null ? { ownerUserId: String(decl.ownerUserId) } : {}),
|
|
148
|
+
...(decl.createdBy != null ? { createdBy: String(decl.createdBy) } : {}),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 读取一个节点包目录的清单:优先 `index.mjs` 静态声明,读不出再回退调用方给的
|
|
154
|
+
* `node.yaml` 读取器。
|
|
155
|
+
* @param {string} dir
|
|
156
|
+
* @param {(yamlPath: string) => object|null} readYaml
|
|
157
|
+
* @returns {object|null}
|
|
158
|
+
*/
|
|
159
|
+
export function readNodePackageManifest(dir, readYaml) {
|
|
160
|
+
const entry = path.join(dir, NODE_PACKAGE_ENTRY);
|
|
161
|
+
if (fs.existsSync(entry) && fs.statSync(entry).isFile()) {
|
|
162
|
+
const manifest = nodePackageDeclarationToManifest(readNodePackageDeclaration(entry), dir);
|
|
163
|
+
if (manifest) return manifest;
|
|
164
|
+
}
|
|
165
|
+
return typeof readYaml === "function" ? readYaml(path.join(dir, "node.yaml")) : null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** 目录是否是一个可识别的节点包。 */
|
|
169
|
+
export function isNodePackageDir(dir) {
|
|
170
|
+
if (!dir || !fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) return false;
|
|
171
|
+
const entry = path.join(dir, NODE_PACKAGE_ENTRY);
|
|
172
|
+
if (fs.existsSync(entry) && fs.statSync(entry).isFile()) return true;
|
|
173
|
+
return fs.existsSync(path.join(dir, "node.yaml"));
|
|
174
|
+
}
|
package/bin/lib/paths.mjs
CHANGED
|
@@ -14,6 +14,44 @@ export const PACKAGE_ROOT = path.resolve(BIN_DIR, "..");
|
|
|
14
14
|
/** 节点执行区域分割线(开始/结束标识用) */
|
|
15
15
|
export const NODE_SEP = "════════════════════════════════════════════════════════════════";
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* 「这个目录是不是一个流程」的**唯一**判据。
|
|
19
|
+
*
|
|
20
|
+
* 历史上这条规则在十来处各写了一遍 `existsSync(dir + "/flow.yaml")`,于是 `flow.yaml`
|
|
21
|
+
* 从执行格式悄悄退化成了目录哨兵:内容早就是死的,存在却是承重的——没有它,目录在列表、
|
|
22
|
+
* 路径解析、复制改名里全都不存在。
|
|
23
|
+
*
|
|
24
|
+
* 顺序即权威顺序:代码 > 只读的遗留 JSON > 已退休的 flow.yaml。
|
|
25
|
+
*/
|
|
26
|
+
export const FLOW_MARKER_FILENAMES = ["workspace.flow.js", "workspace.graph.json", "flow.yaml"];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 命中的标记文件绝对路径;都没有则空字符串。
|
|
30
|
+
* @param {string} dir
|
|
31
|
+
* @returns {string}
|
|
32
|
+
*/
|
|
33
|
+
export function flowMarkerPath(dir) {
|
|
34
|
+
const base = dir == null ? "" : String(dir).trim();
|
|
35
|
+
if (!base) return "";
|
|
36
|
+
for (const name of FLOW_MARKER_FILENAMES) {
|
|
37
|
+
const p = path.join(base, name);
|
|
38
|
+
try {
|
|
39
|
+
if (fs.existsSync(p)) return p;
|
|
40
|
+
} catch {
|
|
41
|
+
/* 不可读的目录当作没有 */
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return "";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {string} dir
|
|
49
|
+
* @returns {boolean}
|
|
50
|
+
*/
|
|
51
|
+
export function isFlowDir(dir) {
|
|
52
|
+
return flowMarkerPath(dir) !== "";
|
|
53
|
+
}
|
|
54
|
+
|
|
17
55
|
/** agentflow 包根目录(CLI 所在包的 node_modules 用于解析脚本依赖,如 js-yaml) */
|
|
18
56
|
export const PACKAGE_AGENTS_DIR = path.join(PACKAGE_ROOT, "agents");
|
|
19
57
|
/** 包内 agents 元数据 JSON */
|
|
@@ -142,7 +180,7 @@ export function resolveUniqueUserPipelineDir(flowName) {
|
|
|
142
180
|
for (const userId of listAgentflowUserIds()) {
|
|
143
181
|
const dir = path.join(getAgentflowDataRoot(), "users", userId, "pipelines", name);
|
|
144
182
|
try {
|
|
145
|
-
if (
|
|
183
|
+
if (isFlowDir(dir)) matches.push(dir);
|
|
146
184
|
} catch {
|
|
147
185
|
/* ignore unreadable user dirs */
|
|
148
186
|
}
|
|
@@ -178,11 +216,11 @@ export function getFlowRuntimeRoot(workspaceRoot, flowName, opts = {}) {
|
|
|
178
216
|
: process.cwd();
|
|
179
217
|
const userRoot = getUserPipelinesRoot(opts.userId);
|
|
180
218
|
const userDir = path.join(userRoot, flowName);
|
|
181
|
-
if (
|
|
219
|
+
if (isFlowDir(userDir)) return userDir;
|
|
182
220
|
const inferredUserDir = resolveUniqueUserPipelineDir(flowName);
|
|
183
221
|
if (inferredUserDir) return inferredUserDir;
|
|
184
222
|
const wsDir = path.join(root, PIPELINES_DIR, flowName);
|
|
185
|
-
if (
|
|
223
|
+
if (isFlowDir(wsDir)) return wsDir;
|
|
186
224
|
// builtin / legacy / 尚未落盘 → 默认 user 目录,runBuild 首次写入时创建
|
|
187
225
|
return userDir;
|
|
188
226
|
}
|
|
@@ -260,23 +298,8 @@ export const USER_AGENTFLOW_AGENTS_LABEL = "~/agentflow/agents";
|
|
|
260
298
|
/** agents.json 中 user 角色 filepath 展示前缀(相对数据根) */
|
|
261
299
|
export const USER_AGENTS_FILEPATH_PREFIX = "agentflow/agents";
|
|
262
300
|
|
|
263
|
-
/**
|
|
301
|
+
/** 随包发布的 CLI 单步脚本目录(validate-flow / get-ready-nodes / extract-thinking) */
|
|
264
302
|
export const PIPELINE_SCRIPTS_DIR = path.join(BIN_DIR, "pipeline");
|
|
265
|
-
/** apply -ai 允许调用的单步脚本名(不含 .mjs) */
|
|
266
|
-
export const APPLY_AI_STEPS = [
|
|
267
|
-
"ensure-run-dir",
|
|
268
|
-
"parse-flow",
|
|
269
|
-
"get-ready-nodes",
|
|
270
|
-
"pre-process-node",
|
|
271
|
-
"post-process-node",
|
|
272
|
-
"write-result",
|
|
273
|
-
"run-tool-nodejs",
|
|
274
|
-
"get-env",
|
|
275
|
-
"validate-flow",
|
|
276
|
-
"collect-nodes",
|
|
277
|
-
"gc",
|
|
278
|
-
"extract-thinking",
|
|
279
|
-
];
|
|
280
303
|
/** 项目内流水线根目录(写入与主读取路径) */
|
|
281
304
|
export const PIPELINES_DIR = ".workspace/agentflow/pipelines";
|
|
282
305
|
/** 用户目录或工作区 pipelines 下存放已归档流水线的子目录名 */
|