@fieldwangai/agentflow 0.1.153 → 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 +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 +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 +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 +1087 -18122
- 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-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-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 +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
|
@@ -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.
|
|
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,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.
|
|
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:
|
|
3
|
+
description: Workspace Graph recipes for AgentFlow canvas tasks (git analysis, display, branching).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Workspace Graph Recipes
|
|
7
7
|
|
|
8
|
-
|
|
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
|
-
|
|
12
|
+
旧的 `Start → … → End` 流水线 recipe 已下线;不得生成 `control_start` / `control_end`
|
|
13
|
+
或其它已退役的节点类型(recipes.md 末尾列出了完整清单)。
|
|
@@ -1,63 +1,117 @@
|
|
|
1
|
-
# AgentFlow
|
|
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
|
-
|
|
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
|
-
|
|
28
|
+
const skills = control.loadSkills("加载 Skills", {
|
|
29
|
+
skillKeys: `["global-codex:code-reading"]`,
|
|
30
|
+
});
|
|
8
31
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
42
|
+
What the data edges do:
|
|
20
43
|
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
23
|
-
- `
|
|
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
|
-
|
|
48
|
+
Watch out:
|
|
30
49
|
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
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
|
-
|
|
57
|
+
## Show A Result
|
|
42
58
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
59
|
+
Feed the producing pin into a `display.*` node:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const shown = display.markdown("结论", { content: analyse.result });
|
|
63
|
+
```
|
|
46
64
|
|
|
47
|
-
|
|
65
|
+
Pick the type that matches the payload: `display.markdown`, `.html`, `.table`, `.chart`,
|
|
66
|
+
`.mermaid`, `.ascii`, `.image`, `.reactApp`.
|
|
48
67
|
|
|
49
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
71
|
+
```js
|
|
72
|
+
const { storyId } = breakdown;
|
|
73
|
+
const notify = tool.wecomSendAppMarkdown("通知", { markdown: breakdown.result, toUser: storyId });
|
|
74
|
+
```
|
|
54
75
|
|
|
55
|
-
##
|
|
76
|
+
## Branching
|
|
56
77
|
|
|
57
|
-
|
|
78
|
+
`control.if` is the branch primitive. Its `prediction` input is a `bool`:
|
|
58
79
|
|
|
59
|
-
```
|
|
60
|
-
|
|
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
|
-
|
|
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
|
|
8
|
+
旧的 `flow.yaml` + `/api/flow-editor-sync` 刷新链路不再用于新功能。Workspace 图请直接编辑 `workspace.flow.js`(见 **agentflow-workspace-graph**),或使用 Workspace Graph 页面/API 的保存机制;需要所见即所得预览时使用 `agentflow-cli workspace-preview --file <flowDir>`。
|