@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.
Files changed (193) hide show
  1. package/README.md +16 -34
  2. package/README.zh-CN.md +14 -34
  3. package/agents/agentflow-node-executor-code.md +13 -3
  4. package/agents/agentflow-node-executor-planning.md +13 -3
  5. package/agents/agentflow-node-executor-requirement.md +13 -3
  6. package/agents/agentflow-node-executor-test.md +13 -3
  7. package/agents/agentflow-node-executor-ui.md +13 -3
  8. package/agents/agentflow-node-executor.md +13 -3
  9. package/agents/en/agentflow-node-executor.md +13 -3
  10. package/agents/zh/agentflow-node-executor.md +13 -3
  11. package/bin/agentflow.mjs +3 -3
  12. package/bin/lib/admin-builtin-pipelines.mjs +3 -2
  13. package/bin/lib/agent-runners.mjs +0 -929
  14. package/bin/lib/auth.mjs +2 -1
  15. package/bin/lib/catalog-agents.mjs +2 -1
  16. package/bin/lib/catalog-flows.mjs +165 -90
  17. package/bin/lib/composer-agent.mjs +3 -793
  18. package/bin/lib/composer-skill-router.mjs +3 -323
  19. package/bin/lib/exec-buffered.mjs +32 -0
  20. package/bin/lib/flow-dsl/cli.mjs +277 -0
  21. package/bin/lib/flow-dsl/codegen.mjs +358 -0
  22. package/bin/lib/flow-dsl/defs.mjs +103 -0
  23. package/bin/lib/flow-dsl/index.mjs +77 -0
  24. package/bin/lib/flow-dsl/ir.mjs +305 -0
  25. package/bin/lib/flow-dsl/layout.mjs +115 -0
  26. package/bin/lib/flow-dsl/legacy-yaml.mjs +303 -0
  27. package/bin/lib/flow-dsl/lint.mjs +241 -0
  28. package/bin/lib/flow-dsl/packages.mjs +251 -0
  29. package/bin/lib/flow-dsl/parser.mjs +444 -0
  30. package/bin/lib/flow-import.mjs +96 -26
  31. package/bin/lib/flow-write.mjs +48 -12
  32. package/bin/lib/help.mjs +8 -28
  33. package/bin/lib/html-escape.mjs +19 -0
  34. package/bin/lib/http-util.mjs +49 -0
  35. package/bin/lib/legacy-flow-execution.mjs +37 -0
  36. package/bin/lib/locales/en.json +1 -1
  37. package/bin/lib/locales/zh.json +1 -1
  38. package/bin/lib/main.mjs +152 -286
  39. package/bin/lib/marketplace.mjs +206 -61
  40. package/bin/lib/model-config.mjs +10 -0
  41. package/bin/lib/node-package-archive.mjs +240 -0
  42. package/bin/lib/node-package-bootstrap.mjs +72 -0
  43. package/bin/lib/node-package-manifest.mjs +174 -0
  44. package/bin/lib/paths.mjs +42 -19
  45. package/bin/lib/prd-workflow-routes.mjs +2949 -0
  46. package/bin/lib/prd-workflow-server.mjs +4884 -0
  47. package/bin/lib/run-events.mjs +0 -66
  48. package/bin/lib/schedule-config.mjs +4 -4
  49. package/bin/lib/skill-runtime.mjs +35 -0
  50. package/bin/lib/startup-storage-migrations.mjs +274 -0
  51. package/bin/lib/ui-server.mjs +1092 -18123
  52. package/bin/lib/user-env.mjs +16 -0
  53. package/bin/lib/workspace-auto-layout.mjs +234 -0
  54. package/bin/lib/workspace-flow-store.mjs +478 -0
  55. package/bin/lib/workspace-graph-merge.mjs +41 -34
  56. package/bin/lib/workspace-preview.mjs +12 -2
  57. package/bin/lib/workspace-routes.mjs +3088 -0
  58. package/bin/lib/workspace-server.mjs +6199 -0
  59. package/bin/lib/workspace-state.mjs +331 -0
  60. package/bin/lib/workspace.mjs +2 -1
  61. package/builtin/nodes/agent_subAgent.md +1 -0
  62. package/builtin/nodes/control_agent_toBool.md +2 -0
  63. package/builtin/nodes/control_anyOne.md +2 -0
  64. package/builtin/nodes/control_cancelled.md +2 -0
  65. package/builtin/nodes/control_cd_workspace.md +5 -11
  66. package/builtin/nodes/control_delay.md +2 -0
  67. package/builtin/nodes/control_end.md +2 -0
  68. package/builtin/nodes/control_if.md +1 -0
  69. package/builtin/nodes/control_interval_loop.md +2 -0
  70. package/builtin/nodes/control_load_mcp.md +24 -0
  71. package/builtin/nodes/control_load_skills.md +8 -23
  72. package/builtin/nodes/control_start.md +2 -0
  73. package/builtin/nodes/control_toBool.md +2 -0
  74. package/builtin/nodes/control_user_workspace.md +2 -0
  75. package/builtin/nodes/control_wait_until.md +2 -0
  76. package/builtin/nodes/display_ascii.md +1 -0
  77. package/builtin/nodes/display_chart.md +1 -0
  78. package/builtin/nodes/display_html.md +1 -0
  79. package/builtin/nodes/display_image.md +1 -0
  80. package/builtin/nodes/display_markdown.md +1 -0
  81. package/builtin/nodes/display_mermaid.md +1 -0
  82. package/builtin/nodes/display_react_app.md +1 -0
  83. package/builtin/nodes/display_table.md +1 -0
  84. package/builtin/nodes/provide_bool.md +1 -0
  85. package/builtin/nodes/provide_file.md +1 -0
  86. package/builtin/nodes/provide_password.md +1 -0
  87. package/builtin/nodes/provide_str.md +1 -0
  88. package/builtin/nodes/tool_display_share_link.md +1 -0
  89. package/builtin/nodes/tool_get_env.md +2 -0
  90. package/builtin/nodes/tool_git_checkout.md +1 -0
  91. package/builtin/nodes/tool_git_worktree_load.md +1 -0
  92. package/builtin/nodes/tool_git_worktree_unload.md +1 -0
  93. package/builtin/nodes/tool_gitlab_create_mr.md +1 -0
  94. package/builtin/nodes/tool_jenkins_build.md +2 -0
  95. package/builtin/nodes/tool_load_key.md +2 -0
  96. package/builtin/nodes/tool_nodejs.md +17 -19
  97. package/builtin/nodes/tool_print.md +2 -0
  98. package/builtin/nodes/tool_save_key.md +2 -0
  99. package/builtin/nodes/tool_set_run_env.md +1 -0
  100. package/builtin/nodes/tool_user_ask.md +2 -0
  101. package/builtin/nodes/tool_user_check.md +2 -0
  102. package/builtin/nodes/tool_wecom_send_app_markdown.md +1 -0
  103. package/builtin/nodes/tool_wecom_send_group_markdown.md +1 -0
  104. package/builtin/nodes/workspace_one_click_task.md +44 -0
  105. package/builtin/nodes/workspace_run.md +16 -0
  106. package/builtin/nodes/workspace_scheduled_run.md +16 -0
  107. package/builtin/pipelines/module-migrate/scripts/gate.mjs +37 -0
  108. package/builtin/pipelines/module-migrate/scripts/static-check.mjs +82 -0
  109. package/builtin/pipelines/module-migrate/workspace.flow.js +172 -0
  110. package/builtin/pipelines/module-migrate/workspace.layout.json +134 -0
  111. package/builtin/pipelines/new/scripts/lint-flow.mjs +38 -0
  112. package/builtin/pipelines/new/workspace.flow.js +91 -0
  113. package/builtin/pipelines/new/workspace.layout.json +70 -0
  114. package/builtin/web-ui/dist/assets/{WorkflowAssistantThread-B9xslwI0.js → WorkflowAssistantThread-ClNxY2Wu.js} +1 -1
  115. package/builtin/web-ui/dist/assets/index-BJzMYRK3.js +870 -0
  116. package/builtin/web-ui/dist/assets/index-CEXmmwM2.css +1 -0
  117. package/builtin/web-ui/dist/index.html +2 -2
  118. package/package.json +3 -1
  119. package/reference/flow-control-capabilities.md +77 -158
  120. package/reference/flow-layout.md +1 -1
  121. package/reference/flow-prompt-handler-check.md +2 -2
  122. package/skills/agentflow-author-flow/SKILL.md +1 -1
  123. package/skills/agentflow-cli/SKILL.md +139 -24
  124. package/skills/agentflow-cli/agents/openai.yaml +2 -2
  125. package/skills/agentflow-cli/scripts/agentflow-cli.mjs +654 -20
  126. package/skills/agentflow-cli/scripts/agentflow-runtime.mjs +97 -0
  127. package/skills/agentflow-flow-add-instances/SKILL.md +1 -1
  128. package/skills/agentflow-flow-dsl/SKILL.md +206 -0
  129. package/skills/agentflow-flow-dsl/agents/openai.yaml +4 -0
  130. package/skills/agentflow-flow-dsl/references/node-calls.md +39 -0
  131. package/skills/agentflow-flow-edit-node-fields/SKILL.md +1 -1
  132. package/skills/agentflow-flow-recipes/SKILL.md +7 -4
  133. package/skills/agentflow-flow-recipes/references/recipes.md +97 -43
  134. package/skills/agentflow-flow-sync-ui/SKILL.md +1 -1
  135. package/skills/agentflow-node-dsl/SKILL.md +212 -0
  136. package/skills/agentflow-node-dsl/agents/openai.yaml +4 -0
  137. package/skills/agentflow-node-reference/SKILL.md +2 -2
  138. package/skills/agentflow-node-reference/references/builtin-nodes.md +166 -115
  139. package/skills/agentflow-runtime-reference/references/runtime.md +1 -1
  140. package/skills/agentflow-workspace-ascii/SKILL.md +9 -16
  141. package/skills/agentflow-workspace-graph/SKILL.md +62 -48
  142. package/skills/agentflow-workspace-html/SKILL.md +7 -2
  143. package/skills/agentflow-workspace-image/SKILL.md +6 -2
  144. package/skills/agentflow-workspace-markdown/SKILL.md +14 -21
  145. package/skills/agentflow-workspace-mermaid/SKILL.md +8 -16
  146. package/bin/lib/api-runner.mjs +0 -387
  147. package/bin/lib/apply.mjs +0 -903
  148. package/bin/lib/composer-flow-instances.mjs +0 -68
  149. package/bin/lib/composer-flow-skeleton.mjs +0 -334
  150. package/bin/lib/composer-flow-validate.mjs +0 -47
  151. package/bin/lib/composer-model-router.mjs +0 -185
  152. package/bin/lib/composer-node-schema.mjs +0 -303
  153. package/bin/lib/composer-planner.mjs +0 -751
  154. package/bin/lib/composer-script-ops.mjs +0 -233
  155. package/bin/lib/flow-static-preview.mjs +0 -104
  156. package/bin/lib/hub-login.mjs +0 -54
  157. package/bin/lib/hub-publish.mjs +0 -159
  158. package/bin/lib/hub-remote.mjs +0 -189
  159. package/bin/lib/hub.mjs +0 -299
  160. package/bin/lib/jenkins.mjs +0 -380
  161. package/bin/lib/node-execute.mjs +0 -539
  162. package/bin/lib/normalize-node-tool-command.mjs +0 -97
  163. package/bin/lib/runtime-context.mjs +0 -243
  164. package/bin/lib/scheduler.mjs +0 -601
  165. package/bin/lib/ui-print.mjs +0 -94
  166. package/bin/pipeline/build-node-prompt.mjs +0 -271
  167. package/bin/pipeline/check-cache.mjs +0 -191
  168. package/bin/pipeline/check-flow.mjs +0 -543
  169. package/bin/pipeline/collect-nodes.mjs +0 -212
  170. package/bin/pipeline/compute-cache-md5.mjs +0 -177
  171. package/bin/pipeline/ensure-run-dir.mjs +0 -71
  172. package/bin/pipeline/gc.mjs +0 -129
  173. package/bin/pipeline/get-env.mjs +0 -59
  174. package/bin/pipeline/get-resolved-values.mjs +0 -344
  175. package/bin/pipeline/load-key.mjs +0 -62
  176. package/bin/pipeline/parse-flow.mjs +0 -708
  177. package/bin/pipeline/post-process-control-if.mjs +0 -23
  178. package/bin/pipeline/post-process-node.mjs +0 -490
  179. package/bin/pipeline/pre-process-node.mjs +0 -1430
  180. package/bin/pipeline/resolve-inputs.mjs +0 -201
  181. package/bin/pipeline/run-tool-nodejs.mjs +0 -167
  182. package/bin/pipeline/save-key.mjs +0 -93
  183. package/bin/pipeline/snapshot-prior-round.mjs +0 -70
  184. package/bin/pipeline/validate-for-ui.mjs +0 -234
  185. package/bin/pipeline/validate-script-output.mjs +0 -130
  186. package/bin/pipeline/write-result.mjs +0 -182
  187. package/builtin/pipelines/module-migrate/flow.yaml +0 -819
  188. package/builtin/pipelines/new/flow.yaml +0 -545
  189. package/builtin/pipelines/new/scripts/check-flow.mjs +0 -9
  190. package/builtin/pipelines/new/scripts/collect-nodes.mjs +0 -211
  191. package/builtin/web-ui/dist/assets/index-DZ328oSo.css +0 -1
  192. package/builtin/web-ui/dist/assets/index-DmUV7ZCL.js +0 -888
  193. package/skills/agentflow-node-authoring/SKILL.md +0 -57
@@ -1,344 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * 获取指定 instance 的 resolvedInputs、resolvedOutputs、systemPrompt,用于占位符替换。
4
- * systemPrompt 来自 instance 或 node 定义的 description,占位符 ${input.xxx}、${output.xxx}、${xxx} 会被替换。
5
- * 用法:node get-resolved-values.mjs <workspaceRoot> <flowName> <uuid> <instanceId>
6
- * 输出(stdout JSON):{ "ok": true, "resolvedInputs": {...}, "resolvedOutputs": {...}, "systemPrompt": "..." }
7
- */
8
-
9
- import fs from "fs";
10
- import path from "path";
11
-
12
- import { getRunDir, LEGACY_NODES_DIR, PIPELINES_DIR, PROJECT_NODES_DIR } from "../lib/paths.mjs";
13
- import { isMarketplaceDefinitionId, resolveMarketplaceNodePackage } from "../lib/marketplace.mjs";
14
- import { getFlowDir } from "../lib/workspace.mjs";
15
- import { fileURLToPath } from "url";
16
-
17
- const __dirnameResolved = path.dirname(fileURLToPath(import.meta.url));
18
- const PACKAGE_BUILTIN_NODES_DIR = path.join(path.resolve(__dirnameResolved, "..", ".."), "builtin", "nodes");
19
-
20
- import { loadFlowDefinition } from "./parse-flow.mjs";
21
- import { loadAllExecIds, outputDirForNode } from "./get-exec-id.mjs";
22
- import { computeResolvedInputsForInstance } from "./resolve-inputs.mjs";
23
-
24
- /** 仅多行标记(无实际内容)时视为空,应回退到节点定义的 description */
25
- function isEmptyDescription(v) {
26
- if (!v || typeof v !== "string") return true;
27
- const t = v.trim();
28
- return t === "|" || t === ">" || /^[|>]\s*$/.test(t);
29
- }
30
-
31
- /** 解析 frontmatter(如 instance .md),支持 description 多行(| / >)。当前仅 flow.yaml instances 生效,此函数保留供复用。 */
32
- function parseFrontmatter(raw) {
33
- const m = raw.match(/^---\s*\n([\s\S]*?)\n---/);
34
- if (!m) return {};
35
- const fm = m[1];
36
- const data = {};
37
- const lines = fm.split("\n");
38
- for (let i = 0; i < lines.length; i++) {
39
- const line = lines[i];
40
- if (/^\s*definitionId:\s*(.*)$/.test(line)) {
41
- const v = line.replace(/^\s*definitionId:\s*/, "").replace(/^["']|["']$/g, "").trim();
42
- data.definitionId = v;
43
- continue;
44
- }
45
- const descMatch = line.match(/^\s*description:\s*(.+)$/);
46
- if (descMatch) {
47
- const rest = descMatch[1].replace(/^["']|["']$/g, "").trim();
48
- if (rest === "|" || rest === ">" || /^[|>]\s*$/.test(rest)) {
49
- const keyIndent = line.search(/\S/);
50
- const contentLines = [];
51
- for (let j = i + 1; j < lines.length; j++) {
52
- const contentLine = lines[j];
53
- if (contentLine.trim() === "") {
54
- contentLines.push("");
55
- continue;
56
- }
57
- const lineIndent = contentLine.search(/\S/);
58
- if (lineIndent <= keyIndent) break;
59
- contentLines.push(lineIndent >= 0 ? contentLine.slice(lineIndent) : contentLine);
60
- }
61
- data.description = contentLines.join("\n").trim();
62
- } else if (rest) {
63
- data.description = rest;
64
- }
65
- continue;
66
- }
67
- }
68
- return data;
69
- }
70
-
71
- /**
72
- * 从 frontmatter 文本中解析 description 字段,支持单行与 YAML 多行(| 或 >)。
73
- * @param {string} frontmatter - --- 与 --- 之间的内容(不含首尾 ---)
74
- * @returns {string}
75
- */
76
- function extractDescriptionFromFrontmatter(frontmatter) {
77
- const lines = frontmatter.split("\n");
78
- for (let i = 0; i < lines.length; i++) {
79
- const line = lines[i];
80
- const singleLineMatch = line.match(/^\s*description:\s*(.+)$/);
81
- if (singleLineMatch) {
82
- const rest = singleLineMatch[1].replace(/^["']|["']$/g, "").trim();
83
- // 多行标记:仅 "|" 或 ">" 或带空格的 "| " / "> "
84
- if (rest === "|" || rest === ">" || /^[|>]\s*$/.test(rest)) {
85
- const keyIndent = line.search(/\S/);
86
- const contentLines = [];
87
- for (let j = i + 1; j < lines.length; j++) {
88
- const contentLine = lines[j];
89
- if (contentLine.trim() === "") {
90
- contentLines.push("");
91
- continue;
92
- }
93
- const lineIndent = contentLine.search(/\S/);
94
- if (lineIndent <= keyIndent && contentLine.trim() !== "") break;
95
- contentLines.push(lineIndent >= 0 ? contentLine.slice(lineIndent) : contentLine);
96
- }
97
- return contentLines.join("\n").trim();
98
- }
99
- if (rest) return rest;
100
- }
101
- }
102
- return "";
103
- }
104
-
105
- function readNodeDescription(workspaceRoot, flowDir, definitionId) {
106
- if (isMarketplaceDefinitionId(definitionId)) {
107
- const flowData = loadFlowDefinition(flowDir);
108
- const resolved = resolveMarketplaceNodePackage(workspaceRoot, flowDir, definitionId, flowData);
109
- if (resolved?.description) return resolved.description;
110
- }
111
- const fileName = definitionId.endsWith(".md") ? definitionId : `${definitionId}.md`;
112
- const flowNodesPath = path.join(flowDir, "nodes", fileName);
113
- const projectNodesNew = path.join(workspaceRoot, PROJECT_NODES_DIR, fileName);
114
- const projectNodesLegacy = path.join(workspaceRoot, LEGACY_NODES_DIR, fileName);
115
- const packageNodesPath = path.join(PACKAGE_BUILTIN_NODES_DIR, fileName);
116
- for (const p of [flowNodesPath, projectNodesNew, projectNodesLegacy, packageNodesPath]) {
117
- try {
118
- const raw = fs.readFileSync(p, "utf-8");
119
- const m = raw.match(/^---\s*\n([\s\S]*?)\n---/);
120
- if (!m) continue;
121
- const v = extractDescriptionFromFrontmatter(m[1]);
122
- if (v) return v;
123
- } catch (_) {}
124
- }
125
- return "";
126
- }
127
-
128
- /**
129
- * 输出槽 slot 名对应的目标输出路径(run 目录内相对路径),固定文件名不含 _execId。
130
- * 约定:output/<instanceId>/node_<instanceId>_<base>.<ext>
131
- */
132
- export function getOutputPathForSlot(instanceId, execId, slotName) {
133
- const base = slotName.replace(/\.(md|txt|json|html?)$/i, "") || slotName;
134
- const ext = (slotName.match(/\.(md|txt|json|html?)$/i) || ["", "md"])[1];
135
- return `${outputDirForNode(instanceId)}/node_${instanceId}_${base}.${ext}`;
136
- }
137
-
138
- function resolvePlaceholdersInText(
139
- text,
140
- resolvedInputs,
141
- resolvedOutputs,
142
- opts = {},
143
- ) {
144
- if (!text || typeof text !== "string") return "";
145
- const { instanceId, runDir } = opts;
146
- const toAbs = (rel) => (runDir && rel ? path.join(runDir, rel) : rel);
147
- return text.replace(/\$\{([^}]+)\}/g, (_, key) => {
148
- const k = key.trim();
149
- if (k.startsWith("input.")) {
150
- const slot = k.slice(6);
151
- return resolvedInputs[slot] ?? resolvedInputs._ ?? "";
152
- }
153
- if (k.startsWith("output.")) {
154
- const slot = k.slice(7);
155
- const v = resolvedOutputs[slot] ?? resolvedOutputs._ ?? "";
156
- if (v) return v;
157
- if (instanceId && slot in resolvedOutputs && opts.currentExecId != null) {
158
- return toAbs(getOutputPathForSlot(instanceId, opts.currentExecId, slot));
159
- }
160
- if (instanceId && slot in resolvedOutputs) {
161
- return toAbs(getOutputPathForSlot(instanceId, 1, slot));
162
- }
163
- return "";
164
- }
165
- let v = resolvedInputs[k] ?? resolvedOutputs[k] ?? "";
166
- // 兼容槽位名带 .md 等后缀:如模板写 ${message},resolved 里可能是 message.md
167
- if (!v && !k.includes(".")) {
168
- v = resolvedInputs[k + ".md"] ?? resolvedOutputs[k + ".md"] ?? "";
169
- }
170
- if (!v && instanceId && (k in resolvedOutputs || (k + ".md") in resolvedOutputs)) {
171
- const slot = k in resolvedOutputs ? k : k + ".md";
172
- v = toAbs(getOutputPathForSlot(instanceId, opts.currentExecId ?? 1, slot));
173
- }
174
- return v;
175
- });
176
- }
177
-
178
- /**
179
- * 获取指定 instance 的 resolvedInputs、resolvedOutputs、systemPrompt。
180
- * @returns {{ ok: boolean, resolvedInputs?: object, resolvedOutputs?: object, systemPrompt?: string, error?: string }}
181
- */
182
- export function getResolvedValues(workspaceRoot, flowName, uuid, instanceId) {
183
- const runDir = getRunDir(workspaceRoot, flowName, uuid);
184
- const flowJsonPath = path.join(runDir, "intermediate", "flow.json");
185
-
186
- if (!fs.existsSync(flowJsonPath)) {
187
- return { ok: false, error: `flow.json not found: ${flowJsonPath}. Run parse-flow.mjs first.` };
188
- }
189
-
190
- try {
191
- const flow = JSON.parse(fs.readFileSync(flowJsonPath, "utf-8"));
192
- if (!flow.ok) {
193
- return { ok: false, error: flow.error || "flow.json indicates error" };
194
- }
195
-
196
- let flowDir = getFlowDir(workspaceRoot, flowName) || path.join(workspaceRoot, PIPELINES_DIR, flowName);
197
- if (flow.flowDir && typeof flow.flowDir === "string" && flow.flowDir.trim()) {
198
- flowDir = path.isAbsolute(flow.flowDir) ? flow.flowDir : path.join(workspaceRoot, flow.flowDir);
199
- }
200
- const raw = computeResolvedInputsForInstance(workspaceRoot, flowName, uuid, instanceId);
201
- if (!raw.ok) {
202
- return { ok: false, error: raw.error || "computeResolvedInputsForInstance failed" };
203
- }
204
- let resolvedInputs = raw.resolvedInputs || {};
205
-
206
- const runDirRel = path.join(".workspace", "agentflow", "runBuild", flowName, uuid);
207
-
208
- const order = flow.order || [];
209
- const execIds = loadAllExecIds(workspaceRoot, flowName, uuid, order);
210
- const currentExecId = execIds[instanceId] ?? 1;
211
-
212
- // 当前节点 output 路径从结构(outputSlotTypes / nodes)得到槽名,固定路径不含 _execId;拼入 prompt 时使用绝对路径
213
- const resolvedOutputs = {};
214
- const outSlotNames = (flow.outputSlotTypes && flow.outputSlotTypes[instanceId])
215
- ? Object.keys(flow.outputSlotTypes[instanceId])
216
- : [];
217
- for (const slotName of outSlotNames) {
218
- const rel = getOutputPathForSlot(instanceId, currentExecId, slotName);
219
- resolvedOutputs[slotName] = path.join(runDir, rel);
220
- }
221
- if (Object.keys(resolvedOutputs).length === 0 && order.includes(instanceId)) {
222
- const node = flow.nodes?.find((n) => n.id === instanceId);
223
- const outSlots = node?.output || flow.outputSlotTypes?.[instanceId];
224
- if (outSlots && typeof outSlots === "object") {
225
- for (const slotName of Object.keys(outSlots)) {
226
- const rel = getOutputPathForSlot(instanceId, currentExecId, slotName);
227
- resolvedOutputs[slotName] = path.join(runDir, rel);
228
- }
229
- }
230
- }
231
-
232
- // 注入运行时常量,供 tool_nodejs 等节点在 instance body / script 中用 ${workspaceRoot} ${flowName} ${runDir} ${flowDir} 引用
233
- // 运行时常量放在后面,确保不会被 input 槽位的空值覆盖
234
- const runtimeConstants = {
235
- workspaceRoot: path.resolve(workspaceRoot),
236
- pipelineWorkspace: path.resolve(workspaceRoot),
237
- flowName,
238
- runDir: runDirRel,
239
- flowDir: path.resolve(flowDir),
240
- };
241
- for (const [key, value] of Object.entries(runtimeConstants)) {
242
- // 仅在 input 槽位的值为空或占位符时才使用运行时常量
243
- const existing = resolvedInputs[key];
244
- if (!existing || existing === "${" + key + "}" || existing.trim() === "") {
245
- resolvedInputs[key] = value;
246
- }
247
- }
248
-
249
- // 对上游 output 路径:若文件已存在且该槽位类型不是「文件」,用文件内容替换路径(便于 cache 一致)。
250
- // 类型为「文件」的 input 槽:保留路径(文件名/引用),不替换为内容,供 prompt 中「引用文件」使用。
251
- const inputSlotTypes = (flow.inputSlotTypes && flow.inputSlotTypes[instanceId]) || {};
252
- for (const slotName of Object.keys(resolvedInputs)) {
253
- if (inputSlotTypes[slotName] === "文件" || inputSlotTypes[slotName] === "file") continue;
254
- const v = resolvedInputs[slotName];
255
- if (typeof v !== "string" || !v) continue;
256
- if (!v.startsWith("output/")) continue;
257
- const absPath = path.join(runDir, v);
258
- try {
259
- if (fs.existsSync(absPath)) {
260
- resolvedInputs[slotName] = fs.readFileSync(absPath, "utf-8").trim();
261
- } else {
262
- // 备份机制(snapshotPriorRoundIfNeeded)会将 foo.md 重命名为 foo_N.md,
263
- // 循环节点第二轮起原始文件不存在时,回退查找最新的 _N 备份文件。
264
- const dir = path.dirname(absPath);
265
- const ext = path.extname(absPath);
266
- const base = path.basename(absPath, ext);
267
- if (fs.existsSync(dir)) {
268
- const candidates = fs.readdirSync(dir).filter(f =>
269
- f.startsWith(base + "_") && f.endsWith(ext) &&
270
- /^\d+$/.test(f.slice(base.length + 1, -ext.length))
271
- );
272
- if (candidates.length > 0) {
273
- candidates.sort((a, b) => {
274
- const na = parseInt(a.slice(base.length + 1, -ext.length), 10);
275
- const nb = parseInt(b.slice(base.length + 1, -ext.length), 10);
276
- return nb - na;
277
- });
278
- resolvedInputs[slotName] = fs.readFileSync(path.join(dir, candidates[0]), "utf-8").trim();
279
- }
280
- }
281
- }
282
- } catch (_) {}
283
- }
284
-
285
- // 拼入 prompt 的 resolveInput/output 统一使用绝对路径,避免相对路径歧义
286
- for (const slotName of Object.keys(resolvedInputs)) {
287
- const v = resolvedInputs[slotName];
288
- if (typeof v === "string" && v && (v.startsWith("output/") || v.startsWith("intermediate/"))) {
289
- resolvedInputs[slotName] = path.join(runDir, v);
290
- }
291
- }
292
-
293
- let description = "";
294
- let definitionId = "";
295
- const flowNode = flow.nodes?.find((n) => n.id === instanceId);
296
- const nameForFile = flowNode?.definitionName ?? flowNode?.definitionId;
297
- const flowData = loadFlowDefinition(flowDir);
298
- if (flowData?.instances?.[instanceId] != null) {
299
- const inst = flowData.instances[instanceId];
300
- definitionId = (flowNode?.definitionId ?? inst.definitionId ?? "").trim();
301
- if (nameForFile || inst.definitionId) {
302
- description = readNodeDescription(workspaceRoot, flowDir, nameForFile || inst.definitionId);
303
- }
304
- } else {
305
- definitionId = (flowNode?.definitionId ?? flowNode?.definitionName ?? "").trim();
306
- if (nameForFile || definitionId) {
307
- description = readNodeDescription(workspaceRoot, flowDir, nameForFile || definitionId);
308
- }
309
- }
310
-
311
- const systemPrompt = resolvePlaceholdersInText(
312
- description,
313
- resolvedInputs,
314
- resolvedOutputs,
315
- { instanceId, currentExecId, runDir },
316
- );
317
-
318
- return { ok: true, resolvedInputs, resolvedOutputs, systemPrompt };
319
- } catch (err) {
320
- return { ok: false, error: err.message };
321
- }
322
- }
323
-
324
- function main() {
325
- const args = process.argv.slice(2);
326
- if (args.length < 4) {
327
- console.error(
328
- JSON.stringify({
329
- ok: false,
330
- error: "Usage: node get-resolved-values.mjs <workspaceRoot> <flowName> <uuid> <instanceId>",
331
- }),
332
- );
333
- process.exit(1);
334
- }
335
-
336
- const [root, flowName, uuid, instanceId] = args;
337
- const workspaceRoot = path.resolve(root);
338
- const result = getResolvedValues(workspaceRoot, flowName, uuid, instanceId);
339
- console.log(JSON.stringify(result));
340
- if (!result.ok) process.exit(1);
341
- }
342
-
343
- const isMain = process.argv[1] && path.resolve(fileURLToPath(import.meta.url)) === path.resolve(process.argv[1]);
344
- if (isMain) main();
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * tool_load_key 执行脚本:从 run 目录下 memory 存储按 key 读取 value,stdout 输出 tool_nodejs 约定 JSON。
4
- * 存储路径与格式由本脚本内部实现,节点不感知。key 由命令行参数传入,不读 flow。
5
- * 用法:node load-key.mjs <workspaceRoot> <flowName> <uuid> <key>
6
- * 输出(stdout 一行 JSON):{ "err_code": 0, "message": { "result": "<value>" } };err_code 0=成功 1=失败,无 next。
7
- */
8
-
9
- import fs from "fs";
10
- import path from "path";
11
-
12
- import { getRunDir } from "../lib/paths.mjs";
13
-
14
- const MEMORY_FILENAME = "memory.md";
15
-
16
- function parseMemory(content) {
17
- const map = new Map();
18
- for (const line of (content || "").split(/\r?\n/)) {
19
- const idx = line.indexOf(": ");
20
- if (idx <= 0) continue;
21
- const k = line.slice(0, idx).trim();
22
- const v = line.slice(idx + 2).trim();
23
- if (k) map.set(k, v);
24
- }
25
- return map;
26
- }
27
-
28
- function main() {
29
- const [root, flowName, uuid, key] = process.argv.slice(2);
30
- if (!root || !flowName || !uuid) {
31
- console.log(
32
- JSON.stringify({
33
- err_code: 1,
34
- message: { result: "" },
35
- }),
36
- );
37
- process.exit(0);
38
- }
39
-
40
- const keyStr = key != null ? String(key).trim() : "";
41
- const workspaceRoot = path.resolve(root);
42
- const runDir = getRunDir(workspaceRoot, flowName, uuid);
43
- const memoryPath = path.join(runDir, MEMORY_FILENAME);
44
-
45
- let value = "";
46
- if (keyStr && fs.existsSync(memoryPath)) {
47
- try {
48
- const content = fs.readFileSync(memoryPath, "utf-8");
49
- const map = parseMemory(content);
50
- value = map.get(keyStr) ?? "";
51
- } catch (_) {}
52
- }
53
-
54
- console.log(
55
- JSON.stringify({
56
- err_code: 0,
57
- message: { result: value },
58
- }),
59
- );
60
- }
61
-
62
- main();