@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
@@ -0,0 +1,97 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+
5
+ const PACKAGE_NAME = "@fieldwangai/agentflow";
6
+ const RUNTIME_ENTRY = path.join("bin", "lib", "skill-runtime.mjs");
7
+ let explicitRoot = "";
8
+ let resolvedRoot = "";
9
+ let runtimePromise = null;
10
+
11
+ function packageLooksUsable(root) {
12
+ if (!root) return false;
13
+ try {
14
+ const manifest = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
15
+ return manifest?.name === PACKAGE_NAME && fs.statSync(path.join(root, RUNTIME_ENTRY)).isFile();
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ function ancestors(start) {
22
+ const out = [];
23
+ let current = path.resolve(start);
24
+ while (true) {
25
+ out.push(current);
26
+ const parent = path.dirname(current);
27
+ if (parent === current) break;
28
+ current = parent;
29
+ }
30
+ return out;
31
+ }
32
+
33
+ function rootsNear(start) {
34
+ const out = [];
35
+ for (const ancestor of ancestors(start)) {
36
+ out.push(ancestor, path.join(ancestor, "node_modules", "@fieldwangai", "agentflow"));
37
+ }
38
+ return out;
39
+ }
40
+
41
+ function executableCandidates() {
42
+ const names = process.platform === "win32" ? ["agentflow.cmd", "agentflow.exe", "agentflow"] : ["agentflow"];
43
+ const dirs = String(process.env.PATH || "").split(path.delimiter).filter(Boolean);
44
+ return dirs.flatMap((dir) => names.map((name) => path.join(dir, name)));
45
+ }
46
+
47
+ function rootsFromExecutable(candidate) {
48
+ try {
49
+ if (!fs.statSync(candidate).isFile() && !fs.lstatSync(candidate).isSymbolicLink()) return [];
50
+ const real = fs.realpathSync(candidate);
51
+ return rootsNear(path.dirname(real));
52
+ } catch {
53
+ return [];
54
+ }
55
+ }
56
+
57
+ export function configureAgentFlowRuntime(options = {}) {
58
+ const requested = String(options.packageRoot || "").trim();
59
+ if (!requested || requested === explicitRoot) return;
60
+ explicitRoot = path.resolve(requested);
61
+ resolvedRoot = "";
62
+ runtimePromise = null;
63
+ }
64
+
65
+ export function resolveAgentFlowPackageRoot() {
66
+ if (resolvedRoot) return resolvedRoot;
67
+ const scriptDir = path.dirname(fileURLToPath(import.meta.url));
68
+ const candidates = [
69
+ explicitRoot,
70
+ String(process.env.AGENTFLOW_PACKAGE_ROOT || "").trim(),
71
+ ...rootsNear(process.cwd()),
72
+ ...rootsNear(scriptDir),
73
+ ...executableCandidates().flatMap(rootsFromExecutable),
74
+ ].filter(Boolean);
75
+ const seen = new Set();
76
+ for (const candidate of candidates) {
77
+ const root = path.resolve(candidate);
78
+ if (seen.has(root)) continue;
79
+ seen.add(root);
80
+ if (packageLooksUsable(root)) {
81
+ resolvedRoot = root;
82
+ return root;
83
+ }
84
+ }
85
+ throw new Error(
86
+ "Cannot locate a compatible @fieldwangai/agentflow runtime. Install/update the agentflow CLI, "
87
+ + "put its executable on PATH, or set AGENTFLOW_PACKAGE_ROOT/--agentflow-package-root.",
88
+ );
89
+ }
90
+
91
+ export function loadAgentFlowRuntime() {
92
+ if (!runtimePromise) {
93
+ const entry = path.join(resolveAgentFlowPackageRoot(), RUNTIME_ENTRY);
94
+ runtimePromise = import(pathToFileURL(entry).href);
95
+ }
96
+ return runtimePromise;
97
+ }
@@ -10,7 +10,7 @@ description: Legacy Pipeline node authoring is retired. Redirect requests to add
10
10
  用户要在画布中加节点时,请改用 `agentflow-workspace-graph`,编辑:
11
11
 
12
12
  ```text
13
- .workspace/agentflow/pipelines/<id>/workspace.graph.json
13
+ .workspace/agentflow/pipelines/<id>/workspace.flow.js
14
14
  ```
15
15
 
16
16
  Workspace 图的入口使用 `workspace_run` 或 `workspace_scheduled_run`,不要创建 `control_start`、`control_end`,也不要修改旧 Pipeline 拓扑来实现新需求。
@@ -0,0 +1,206 @@
1
+ ---
2
+ name: agentflow-flow-dsl
3
+ description: >-
4
+ 用 workspace.flow.js(受限 ESM)编写 AgentFlow Workspace 流程图。适用于新建流程、
5
+ 修改流程结构、添加或删除节点、修改连线、控制顺序、分支和定时入口;自定义代码节点包
6
+ 改用 agentflow-node-dsl。
7
+ ---
8
+
9
+ # AgentFlow Flow DSL
10
+
11
+ 流程图就是代码:`flow()` 是 main,节点是 func,连线是传参。
12
+
13
+ ## 目录结构
14
+
15
+ ```
16
+ <flowDir>/
17
+ workspace.flow.js 图结构。受限 JS,永不执行,只被静态解析
18
+ nodes/<name>/index.mjs 代码节点。普通 JS,会被真执行
19
+ prompts/*.md docs/*.html 超过 3000 字符的长文本
20
+ workspace.layout.json 画布坐标,由 layout 命令生成,不手写
21
+ workspace.nodes.json 图片和机器管理属性,别碰
22
+ workspace.state.json 运行产出,别碰
23
+ ```
24
+
25
+ **两类文件规则完全不同**:本 skill 负责 `workspace.flow.js`,并在完成后调用排版命令;需要
26
+ 编写 `nodes/*/index.mjs` 时读取 `agentflow-node-dsl`。
27
+
28
+ 写完必须依次执行:
29
+
30
+ ```bash
31
+ agentflow flow dsl lint <flowDir>
32
+ agentflow flow dsl layout <flowDir>
33
+ ```
34
+
35
+ lint 不通过先修结构,不要排版。`layout` 默认只给缺坐标的新节点补位置,保留用户手工布局。
36
+ 新建流程,或用户明确要求整理整张图时,使用 `agentflow flow dsl layout <flowDir> --all`。
37
+ 不要直接编辑 `workspace.layout.json` 里的 x/y。
38
+
39
+ ## 自动排版是交付步骤
40
+
41
+ 只生成正确连线还不算完成。AI 新建或改完流程后,必须保证节点在 UI 中可读:
42
+
43
+ 1. `lint` 校验节点、引脚和拓扑
44
+ 2. `layout` 生成或补齐坐标
45
+ 3. 如果本地 UI 已打开,再刷新或按 UI 同步 skill 通知画布加载磁盘结果
46
+
47
+ 自动排版按依赖从左到右放置,控制主链保持同一视觉轴,数据源放在上方,展示节点与同层主链
48
+ 错开,分支纵向展开。不要为了“看起来差不多”自行猜坐标。
49
+
50
+ ## 图结构:workspace.flow.js
51
+
52
+ ```js
53
+ import { agent, control, display, file, flow, provide, tool } from "agentflow/flow";
54
+ import collectMetrics from "./nodes/collect-metrics"; // 代码节点
55
+
56
+ const dateStr = provide.str("查询日期", { value: "2026-08-06" });
57
+ const collect = collectMetrics("统计语料", { date: dateStr.value });
58
+ const analyse = agent.subAgent("解读", { metrics: collect.result }, `读 metrics 指出趋势与异常。`);
59
+ const chart = display.chart("规模分布", { content: analyse.result });
60
+
61
+ export const run = flow("Run", collect, analyse, chart);
62
+ ```
63
+
64
+ | 位置 | 含义 |
65
+ |------|------|
66
+ | 第 1 个参数(字符串) | 节点显示名。可省略 |
67
+ | 第 2 个参数(对象) | **输入引脚**。每个键都是引脚名,没有例外 |
68
+ | 第 3 个参数(字符串) | body:agent 是 prompt,`tool.nodejs` 是 shell 命令 |
69
+ | `const 变量名` | **节点 id**。改名 = 重命名节点 |
70
+ | `x.slotName` | 引用上游输出引脚 = 连一条数据线 |
71
+
72
+ `provide.*` 只是数据源,没有 prev/next 槽,**不要放进 `flow(...)` 链**——被谁引用就跟谁跑。
73
+
74
+ ## 四条铁律
75
+
76
+ 1. 节点全部声明在**模块顶层**,不要写进函数
77
+ 2. `flow(...)` 里的顺序 = 控制流顺序;声明顺序不代表执行顺序
78
+ 3. **结构文件禁一切控制流**:`if` / `for` / `while` / `?:` / `.map()` / `await` /
79
+ 箭头函数 / `new` / 动态属性。要写逻辑就建代码节点
80
+ 4. 一个输出可接多个输入(fan-out 允许);**一个输入只能接一条边**(fan-in 禁止);
81
+ 不能成环,没有循环原语
82
+
83
+ ## 控制流
84
+
85
+ ```js
86
+ export const run1 = flow("Run", a, b, c); // 顺序
87
+
88
+ export const nightly = flow.schedule("每日", // 定时
89
+ `{"enabled":true,"cron":"0 8 * * *","timezone":"Asia/Shanghai","overlapPolicy":"skip"}`,
90
+ fetchData, sendReport,
91
+ );
92
+
93
+ const ok = control.agentToBool("判断", { value: review.result }, `合格返回 true`);
94
+ const gate = control.if("是否通过", { prediction: ok.prediction }, // 分支
95
+ flow(publish, notifySuccess), // then
96
+ flow(rollback, notifyFail), // else
97
+ );
98
+ export const run2 = flow("Run", review, ok, gate);
99
+
100
+ export const run3 = flow("Run", build, flow.fork(flow(testA), flow(testB, report))); // 控制边扇出
101
+
102
+ flow.resume(showPlan, stage2); // 闸门:跑到这停,人点第二个 run 才继续
103
+ flow.detached(draftA, draftB); // 有控制链但没 run 入口
104
+ ```
105
+
106
+ **`flow.fork` 不是并行。** 它是「一个 `next` 接多个下游」的写法——`flow(a, b, c)` 是线性的,
107
+ 没法在链里写出扇出,所以有了它。编译出来就是两条边,图里不存在 fork 这个东西:
108
+
109
+ ```
110
+ build.next → testA.prev
111
+ build.next → testB.prev
112
+ ```
113
+
114
+ 运行时把两条分支的节点都收进计划,然后**按拓扑序串行执行**。两个各睡 3 秒的分支跑完要
115
+ 6 秒,不是 3 秒。分支之间也没有隔离:任何一个节点失败,整个 run 就结束,另一支不会跑。
116
+
117
+ 用它的理由是画布结构(两件事都挂在 build 后面、互不依赖),不是省时间。
118
+
119
+ **分支不能汇合**——fan-in 禁止,`control.anyOne` 运行时没实现。两条分支各自收尾。
120
+
121
+ **没有循环**。「改到通过为止」只能展开成固定轮次的嵌套 gate。
122
+
123
+ `control.agentToBool` 是 `runtime: degraded`:它靠通用 agent 路径工作,没有任何东西
124
+ 约束模型输出,而 `parse-bool` 只认 `true` / `1` / `yes` / `on`。prompt 里必须写死
125
+ 「只回 true 或 false,多一个字都会被判成 false」。
126
+
127
+ ## 引脚值与正文插值
128
+
129
+ 引脚值可以写字符串、`file(...)`、上游引用,也可以写 `true` / `42`——非字符串会规范成
130
+ 字符串存图;只有定义表里声明为 `bool` 的槽(以及你自己用 `true`/`false` 建的槽)写回时
131
+ 还是裸的 `true`。
132
+
133
+ 正文(第 3 个参数)里的 `${...}` 有两种含义,按这个顺序判定:
134
+
135
+ ```js
136
+ // 1) 本节点已有同名引脚 -> 运行时占位符,跑的时候换成该槽的值
137
+ const a = agent.subAgent("解读", { metrics: collect.result }, `读 ${metrics} 指出趋势`);
138
+
139
+ // 2) 引用上游 -> 自动建一个同名引脚并连线,等价于上面那种写法
140
+ const b = agent.subAgent("解读", {}, `分析 ${dateStr.value} 的数据`);
141
+ // => 引脚 dateStr 接到 dateStr.value,正文存成 `分析 ${dateStr} 的数据`
142
+ ```
143
+
144
+ 第 2 种的槽名取**引用表达式的根标识符**(`dateStr.value` -> `dateStr`)。想让槽叫别的名字,
145
+ 就用第 1 种写法显式写引脚。插值只在正文里生效,引脚值里的 `${}` 运行时不会替换。
146
+
147
+ ## 自定义代码节点
148
+
149
+ 行为完全由输入决定、不需要 AI 推理时,创建代码节点。不要在本 skill 中推断节点包协议;
150
+ 读取 `agentflow-node-dsl`,由它负责 `nodes/<name>/index.mjs` 的声明、实现、测试和发布规则。
151
+
152
+ ## 自定义输出槽(agent 节点)
153
+
154
+ `agent.subAgent` 想多吐一个值,两件事都要做:
155
+
156
+ ```js
157
+ const breakdown = agent.subAgent("需求拆解", { tapdId: story.result },
158
+ `拆解需求……
159
+
160
+ 因为本节点有额外输出槽,回复必须只包含一个信封,不要有其它内容:
161
+ ---agentflow
162
+ result: |
163
+ <完整结果,每行缩进两个空格>
164
+ outParams:
165
+ storyId: <值>
166
+ ---end`,
167
+ );
168
+ const { storyId } = breakdown; // 声明额外输出槽,下游直接用
169
+
170
+ const notify = tool.wecomSendAppMarkdown("通知", { markdown: breakdown.result, toUser: storyId });
171
+ ```
172
+
173
+ 没有额外输出槽的 agent **不要**写信封,直接回正文。
174
+
175
+ `agent.subAgent` 可以自由加自定义**输入**槽,当实参写就行。声明了但暂时不接线的
176
+ 写 `{ url: null }`,否则这个槽不会存在。
177
+
178
+ ## 超长文本外置
179
+
180
+ body 或引脚值超过 3000 字符,抽成文件:
181
+
182
+ ```js
183
+ const plan = agent.subAgent("规划", { skillsContext }, file("prompts/plan.md"));
184
+ const doc = display.html("使用说明", { content: file("docs/guide.html") });
185
+ ```
186
+
187
+ ## 节点选型
188
+
189
+ | 场景 | 用 |
190
+ |------|----|
191
+ | 要 AI 理解 / 判断 / 生成 | `agent.subAgent` |
192
+ | 行为由输入完全决定,逻辑复杂 | **建代码节点** `nodes/<name>/index.mjs` |
193
+ | 一行 shell 就能搞定 | `tool.nodejs("名字", {}, \`node -e "..."\`)` |
194
+ | 给用户看结果 | `display.markdown` / `.html` / `.chart` / `.table` |
195
+ | 加载 skills 给下游 agent | `control.loadSkills` → `skillsContext` |
196
+ | 加载知识库 / 代码仓 | `control.cdWorkspace` → `knowledgeContext` |
197
+ | 固定文本 / 密钥 | `provide.str` / `provide.password` |
198
+ | 文本转 bool 做分支 | `control.agentToBool` → `prediction` |
199
+
200
+ `display.*` 的内容一般来自连线;写字面量则是手写文档节点(也合法,且不会被运行覆盖)。
201
+
202
+ ## 全部可用节点
203
+
204
+ 见 [node-calls.md](references/node-calls.md)。该表由
205
+ `scripts/generate-agentflow-skill-references.mjs` 从 `builtin/nodes/*.md` 生成,
206
+ 只列运行时真正支持的类型——用了表外的类型 lint 会直接报错。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "AgentFlow Flow DSL"
3
+ short_description: "Author AgentFlow workspace graphs and connections in DSL"
4
+ default_prompt: "Use $agentflow-flow-dsl to create or modify an AgentFlow workspace.flow.js graph."
@@ -0,0 +1,39 @@
1
+ # AgentFlow Flow DSL — 内置节点调用表
2
+
3
+ > Generated from `builtin/nodes/*.md` by `scripts/generate-agentflow-skill-references.mjs`.
4
+ > 只列 `runtime: native` 的节点——其余类型 lint 会直接报错。
5
+
6
+ `prev` / `next` / `next1` / `next2` 是控制引脚,由 `flow()` 自动接,**不要手写**。
7
+
8
+ | 调用 | 输入引脚 | 输出引脚 |
9
+ |------|----------|----------|
10
+ | `agent.subAgent` | workspaceContext:text, skillsContext:text, mcpContext:text, knowledgeContext:text | result:text |
11
+ | `control.cdWorkspace` | path:text, label:text, knowledgeContext:text, workspaceContext:text | knowledgeContext:text, workspaceContext:text, cwd:file |
12
+ | `control.if` | prediction:bool | — |
13
+ | `control.loadMcp` | serverNames:text | mcpContext:text |
14
+ | `control.loadSkills` | skillKeys:text | skillsContext:text |
15
+ | `control.userWorkspace` | — | workspaceContext:text, cwd:file |
16
+ | `display.ascii` | content:text | content:text |
17
+ | `display.chart` | content:text, filePath:file, workspaceContext:text | content:text |
18
+ | `display.html` | content:text, filePath:file, workspaceContext:text | content:text |
19
+ | `display.image` | src:text, filePath:file, alt:text, workspaceContext:text | src:text |
20
+ | `display.markdown` | content:text | content:text |
21
+ | `display.mermaid` | content:text | content:text |
22
+ | `display.reactApp` | content:text, filePath:file, workspaceContext:text | content:text |
23
+ | `display.table` | content:text, filePath:file, workspaceContext:text | content:text |
24
+ | `provide.bool` | — | value:bool |
25
+ | `provide.file` | — | value:file |
26
+ | `provide.password` | — | value:text |
27
+ | `provide.str` | — | value:text |
28
+ | `tool.displayShareLink` | title:text, layout:text, nodeIds:text, baseUrl:text | url:text, shareId:text, expiresAt:text |
29
+ | `tool.gitCheckout` | repoUrl:text, branch:text, targetDir:text, pullIfExists:bool, includeSubmodules:bool, remote:text, workspaceContext:text | repoPath:file, branch:text, commit:text, changed:bool, workspaceContext:text, gitContext:text |
30
+ | `tool.gitlabCreateMr` | repoPath:file, gitContext:text, workspaceContext:text, sourceBranch:text, targetBranch:text, title:text, description:text, draft:bool, labels:text, push:bool, remote:text, tokenEnv:text, gitlabApiBase:text, removeSourceBranch:bool, squash:bool | mrUrl:text, created:bool, mrIid:text, projectId:text, sourceBranch:text, targetBranch:text, title:text, message:text |
31
+ | `tool.gitWorktreeLoad` | repoPath:file, branch:text, worktreePath:file, pruneMissing:bool, force:bool, gitContext:text, workspaceContext:text | worktreePath:file, branch:text, commit:text, workspaceContext:text, gitContext:text |
32
+ | `tool.gitWorktreeUnload` | repoPath:file, worktreePath:file, gitContext:text, workspaceContext:text, force:bool, prune:bool | removed:bool, workspaceContext:text, message:text |
33
+ | `tool.nodejs` | workspaceContext:text, skillsContext:text, mcpContext:text | result:text |
34
+ | `tool.setRunEnv` | key:text, value:text, variables:text | keys:text, count:text |
35
+ | `tool.wecomSendAppMarkdown` | markdown:text, toUser:text, corpId:text, corpSecret:text, agentId:text, accessToken:text | sent:bool, message:text, response:text |
36
+ | `tool.wecomSendGroupMarkdown` | markdown:text, webhookUrl:text, webhookKey:text | sent:bool, message:text, response:text |
37
+ | `workspace.oneClickTask` | skillKeys:text, includeWorkspaceContext:bool, displayType:text, knowledgeContext:text, workspaceContext:text | content:text, displayType:text |
38
+ | `workspace.run` | — | — |
39
+ | `workspace.scheduledRun` | — | — |
@@ -5,6 +5,6 @@ description: Legacy Pipeline field editing is retired. Use the Workspace Graph s
5
5
 
6
6
  # Legacy Flow Node Field Editing(已下线)
7
7
 
8
- 此 skill 原用于修改 `flow.yaml` 的实例字段。当前新建和操作统一发生在 Workspace 图中,节点字段应修改 `workspace.graph.json` `instances`,并通过 Workspace 保存/预览链路同步。
8
+ 此 skill 原用于修改 `flow.yaml` 的实例字段。当前新建和操作统一发生在 Workspace 图中,节点字段应修改 `workspace.flow.js` 的节点调用(见 **agentflow-workspace-graph**),并通过 Workspace 保存/预览链路同步。
9
9
 
10
10
  不要修改 `flow.yaml`、`control_start/control_end` 或调用旧 Pipeline 执行接口来完成新需求。请改用 `agentflow-workspace-graph`。
@@ -1,10 +1,13 @@
1
1
  ---
2
2
  name: agentflow-flow-recipes
3
- description: Legacy Pipeline recipes are retired. Use Workspace Graph recipes for new AgentFlow canvas tasks.
3
+ description: Workspace Graph recipes for AgentFlow canvas tasks (git analysis, display, branching).
4
4
  ---
5
5
 
6
- # Legacy Flow Recipes(已下线)
6
+ # Workspace Graph Recipes
7
7
 
8
- 旧的 `Start → … → End` 流水线 recipe 不再用于新任务。需要组合 Git Checkout、CD Workspace、Load Skills、Agent、Print 时,请在 `workspace.graph.json` 中以 `workspace_run` 为入口组织节点,并使用 `agentflow-workspace-graph` 校验槽位和连线。
8
+ 组合 Git Checkout、CD Workspace、Load Skills、Agent、Display 等节点时,先读
9
+ [recipes.md](references/recipes.md),在 `workspace.flow.js` 中以 `flow(...)` 为入口组织节点,
10
+ 再用 `agentflow-workspace-graph` 校验槽位和连线。
9
11
 
10
- 历史 recipes 仅供迁移参考,不得生成 `control_start` `control_end`。
12
+ 旧的 `Start … → End` 流水线 recipe 已下线;不得生成 `control_start` / `control_end`
13
+ 或其它已退役的节点类型(recipes.md 末尾列出了完整清单)。
@@ -1,63 +1,117 @@
1
- # AgentFlow Flow Recipes
1
+ # AgentFlow Workspace Graph Recipes
2
+
3
+ These recipes are written in `workspace.flow.js` form — the authoritative representation of a
4
+ Workspace graph. Syntax reference: **agentflow-flow-dsl**. The old
5
+ `control_start → … → control_end` pipeline recipes are retired; see the note at the end.
6
+
7
+ Every pin name below comes from `builtin/nodes/*.md`; the full call table is
8
+ [node-calls.md](../../agentflow-flow-dsl/references/node-calls.md). Run
9
+ `agentflow flow dsl lint <flowDir>` after editing — a wrong pin name is an error, not a warning.
2
10
 
3
11
  ## Git Project Analysis
4
12
 
5
- Use when the user asks to clone/pull a repository, enter it, ask an agent what it does, and print the result.
13
+ Clone/pull a repository, enter it, ask an agent what it does, show the result.
14
+
15
+ ```js
16
+ import { agent, control, display, flow, tool } from "agentflow/flow";
17
+
18
+ const checkout = tool.gitCheckout("拉取仓库", {
19
+ repoUrl: "https://example.com/team/repo.git",
20
+ pullIfExists: "true",
21
+ });
22
+
23
+ const cd = control.cdWorkspace("进入仓库", {
24
+ path: ".",
25
+ workspaceContext: checkout.workspaceContext,
26
+ });
6
27
 
7
- Recommended graph:
28
+ const skills = control.loadSkills("加载 Skills", {
29
+ skillKeys: `["global-codex:code-reading"]`,
30
+ });
8
31
 
9
- ```text
10
- control_start
11
- -> tool_git_checkout
12
- -> control_cd_workspace
13
- -> control_load_skills
14
- -> agent_subAgent
15
- -> tool_print
16
- -> control_end
32
+ const analyse = agent.subAgent("解读仓库", {
33
+ workspaceContext: cd.workspaceContext,
34
+ skillsContext: skills.skillsContext,
35
+ }, `读 README、构建文件、源码目录和入口,说明这个仓库是做什么的、怎么跑起来。`);
36
+
37
+ const report = display.markdown("分析结果", { content: analyse.result });
38
+
39
+ export const run = flow("Run", checkout, cd, skills, analyse, report);
17
40
  ```
18
41
 
19
- Minimum required values:
42
+ What the data edges do:
20
43
 
21
- - `tool_git_checkout.repoUrl`: repository URL.
22
- - `tool_git_checkout.pullIfExists`: `true`.
23
- - `tool_git_checkout.includeSubmodules`: `true` only when the user asks to pull submodules.
24
- - `control_cd_workspace.target`: `.`.
25
- - `control_load_skills.source`: `all` or `current-workspace`.
26
- - `agent_subAgent.body`: ask the agent to inspect README, package/build files, source directories, and entry points.
27
- - `tool_print.content`: connect from the agent output content.
44
+ - `checkout.workspaceContext cd.workspaceContext` — hands the checked-out path to CD
45
+ - `cd.workspaceContext → analyse.workspaceContext` — tells the agent which directory it is in
46
+ - `skills.skillsContext → analyse.skillsContext` injects the selected skills
28
47
 
29
- Required context edges:
48
+ Watch out:
30
49
 
31
- - Git Checkout `next` -> CD Workspace `prev`
32
- - Git Checkout `workspaceContext` -> CD Workspace `workspaceContext`
33
- - CD Workspace `next` -> Load Skills `prev`
34
- - CD Workspace `workspaceContext` -> Load Skills `workspaceContext`
35
- - Load Skills `next` -> Agent `prev`
36
- - CD Workspace `workspaceContext` -> Agent `workspaceContext`
37
- - Load Skills `skillsContext` -> Agent `skillsContext`
38
- - Agent content output -> Print `content`
39
- - Print `next` -> End `prev`
50
+ - `control.cdWorkspace` takes `path`, not `target`; `control.loadSkills` takes `skillKeys`
51
+ (a JSON array of `collection:skill`), not `source`
52
+ - `control.loadSkills` has no `workspaceContext` input do not try to chain context through
53
+ it; feed the agent from `cd` directly
54
+ - Do not wire `checkout.repoPath` (a `file`) into `cd.path` (a `text`)
55
+ - Private repositories need working local credentials
40
56
 
41
- Notes:
57
+ ## Show A Result
42
58
 
43
- - Do not connect `repoPath:file` to CD `target:text`.
44
- - If the agent node has no custom file output slot, use its result body and let Print fallback, or add a text/file output slot intentionally.
45
- - For private/internal Git repositories, local credentials must already work.
59
+ Feed the producing pin into a `display.*` node:
60
+
61
+ ```js
62
+ const shown = display.markdown("结论", { content: analyse.result });
63
+ ```
46
64
 
47
- ## Edit Current Flow
65
+ Pick the type that matches the payload: `display.markdown`, `.html`, `.table`, `.chart`,
66
+ `.mermaid`, `.ascii`, `.image`, `.reactApp`.
48
67
 
49
- Use existing flow editing skills:
68
+ An agent with an extra output pin must be declared by destructuring, and its prompt must emit
69
+ the output envelope:
50
70
 
51
- - New nodes/edges: `agentflow-flow-add-instances`
52
- - Existing node text/value edits only: `agentflow-flow-edit-node-fields`
53
- - After saving in UI Composer: `agentflow-flow-sync-ui`
71
+ ```js
72
+ const { storyId } = breakdown;
73
+ const notify = tool.wecomSendAppMarkdown("通知", { markdown: breakdown.result, toUser: storyId });
74
+ ```
54
75
 
55
- ## Print Result
76
+ ## Branching
56
77
 
57
- Prefer explicit content:
78
+ `control.if` is the branch primitive. Its `prediction` input is a `bool`:
58
79
 
59
- ```text
60
- agent.output.summary -> tool_print.input.content
80
+ ```js
81
+ const passed = provide.bool("是否发布", { value: "true" });
82
+ const gate = control.if("是否发布", { prediction: passed.value },
83
+ flow(publish, notifySuccess),
84
+ flow(rollback, notifyFail),
85
+ );
86
+ export const run = flow("Run", passed, gate);
61
87
  ```
62
88
 
63
- Fallback behavior exists, but explicit content keeps the graph self-documenting.
89
+ The taken branch runs and the other is skipped. **Branches cannot rejoin** — fan-in is
90
+ forbidden and `control_anyOne` has no runtime implementation. Let each branch finish on its own.
91
+
92
+ `control.agentToBool` also produces a `prediction`, but it is `runtime: degraded`: nothing
93
+ constrains the model's answer and `parse-bool` accepts only exactly `true` / `1` / `yes` / `on`.
94
+ If you use it, the prompt must say "只回 true 或 false,多一个字都会被判成 false".
95
+
96
+ ## No Loops
97
+
98
+ The run planner rejects cyclic graphs (`Workspace run graph contains a cycle`). Express
99
+ "check → fix → re-check" as forward steps, or put the retry loop **inside** one node — the
100
+ agent's body, a `tool.nodejs` script, or a code node under `nodes/<name>/index.mjs`. Never
101
+ draw an edge from a downstream node back to an upstream one.
102
+
103
+ ## Edit The Graph
104
+
105
+ - Structure, nodes, edges: **agentflow-workspace-graph**
106
+ - Full syntax and the node call table: **agentflow-flow-dsl**
107
+ - Node implementations in code: `nodes/<name>/index.mjs`, see **agentflow-flow-dsl**
108
+
109
+ Saving is handled by the Workspace API; there is no separate canvas-sync step.
110
+
111
+ ## Retired
112
+
113
+ `control_start`, `control_end`, `control_anyOne`, `control_toBool`, `control_interval_loop`,
114
+ `control_delay`, `control_wait_until`, `control_cancelled`, `tool_user_check`, `tool_user_ask`,
115
+ `tool_print`, `tool_load_key`, `tool_save_key`, `tool_get_env` and `tool_jenkins_build` only
116
+ ever ran under the retired Start/End runtime. They are not in the node palette and lint
117
+ rejects them — do not generate them.
@@ -5,4 +5,4 @@ description: Legacy flow.yaml canvas sync is retired. Workspace Graph saves are
5
5
 
6
6
  # Legacy Flow Canvas Sync(已下线)
7
7
 
8
- 旧的 `flow.yaml` + `/api/flow-editor-sync` 刷新链路不再用于新功能。Workspace 图请直接保存 `workspace.graph.json`,或使用 Workspace Graph 页面/API 的保存机制;需要所见即所得预览时使用 `agentflow-cli workspace-preview`。
8
+ 旧的 `flow.yaml` + `/api/flow-editor-sync` 刷新链路不再用于新功能。Workspace 图请直接编辑 `workspace.flow.js`(见 **agentflow-workspace-graph**),或使用 Workspace Graph 页面/API 的保存机制;需要所见即所得预览时使用 `agentflow-cli workspace-preview --file <flowDir>`。