@qingflow-tech/qingflow-cli 1.1.33 → 1.1.35
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 +2 -2
- package/docs/local-agent-install.md +10 -0
- package/npm/lib/runtime.mjs +100 -18
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/skills/qingflow-cli/SKILL.md +5 -5
- package/skills/qingflow-cli/reference/builder/90-workflow.md +6 -12
- package/skills/qingflow-cli/reference/builder/README.md +1 -1
- package/skills/qingflow-cli/reference/builder/reference/app-delivery-sop.md +3 -6
- package/skills/qingflow-cli/reference/builder/workflow/01-overview.md +6 -5
- package/skills/qingflow-cli/reference/builder/workflow/03-flow-patterns.md +1 -1
- package/skills/qingflow-cli/reference/builder/workflow/06-stage3-build-spec.md +33 -39
- package/skills/qingflow-cli/reference/builder/workflow/07-stage4-validate-spec.md +4 -10
- package/skills/qingflow-cli/reference/builder/workflow/08-stage5-apply-verify.md +2 -3
- package/skills/qingflow-cli/reference/builder/workflow/11-troubleshooting.md +2 -1
- package/skills/qingflow-cli/reference/builder/workflow/README.md +3 -3
- package/skills/qingflow-cli/scripts/workflow/validate_flow_spec.py +24 -2
- package/src/qingflow_mcp/builder_facade/service.py +41 -4
- package/src/qingflow_mcp/cli/commands/builder.py +15 -17
- package/src/qingflow_mcp/server_app_builder.py +1 -7
- package/src/qingflow_mcp/tools/ai_builder_tools.py +32 -51
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/README.md +0 -308
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/build-complete-system.md +0 -819
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/build-single-app.md +0 -836
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/complete-system-development-guide.md +0 -137
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/create-app.md +0 -203
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/environments.md +0 -63
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/flow-actors-and-permissions.md +0 -142
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/gotchas.md +0 -116
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/match-rules.md +0 -114
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/public-surface-sync.md +0 -75
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/single-app-development-guide.md +0 -69
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/solution-playbooks.md +0 -52
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/tool-selection.md +0 -113
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/update-flow.md +0 -7
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/update-layout.md +0 -7
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/update-schema.md +0 -7
- package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/update-views.md +0 -7
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Install:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npm install @qingflow-tech/qingflow-cli@1.1.
|
|
6
|
+
npm install @qingflow-tech/qingflow-cli@1.1.35
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
Run:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y -p @qingflow-tech/qingflow-cli@1.1.
|
|
12
|
+
npx -y -p @qingflow-tech/qingflow-cli@1.1.35 qingflow
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
|
@@ -84,6 +84,7 @@ npm run pack:npm
|
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
86
|
dist/npm/qingflow-tech-qingflow-cli-<version>.tgz
|
|
87
|
+
dist/npm/qingflow-cli-<version>.tgz
|
|
87
88
|
dist/npm/qingflow-tech-qingflow-app-user-mcp-<version>.tgz
|
|
88
89
|
dist/npm/qingflow-tech-qingflow-app-builder-mcp-<version>.tgz
|
|
89
90
|
```
|
|
@@ -91,11 +92,20 @@ dist/npm/qingflow-tech-qingflow-app-builder-mcp-<version>.tgz
|
|
|
91
92
|
然后在目标机器安装:
|
|
92
93
|
|
|
93
94
|
```bash
|
|
95
|
+
npx -y -p /absolute/path/to/dist/npm/qingflow-cli-<version>.tgz qingflow-cli install --package /absolute/path/to/dist/npm/qingflow-tech-qingflow-cli-<version>.tgz
|
|
94
96
|
npm install /absolute/path/to/dist/npm/qingflow-tech-qingflow-cli-<version>.tgz
|
|
95
97
|
npm install /absolute/path/to/dist/npm/qingflow-tech-qingflow-app-user-mcp-<version>.tgz
|
|
96
98
|
npm install /absolute/path/to/dist/npm/qingflow-tech-qingflow-app-builder-mcp-<version>.tgz
|
|
97
99
|
```
|
|
98
100
|
|
|
101
|
+
线上官网入口对应:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx qingflow-cli@latest install
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
安装器只安装真实 CLI 包 `@qingflow-tech/qingflow-cli`。它会先检查 Node.js、npm 和 Python 3.11+;如果 `npm install -g` 因本机全局目录权限失败,安装器会自动 fallback 到用户目录(macOS/Linux 为 `~/.local`,Windows 为当前用户 AppData npm 目录),但不会修改 shell 配置文件;PATH 缺失时会打印需要执行的 shell / PowerShell 命令。排障可加 `--verbose`;如需禁止 fallback 可加 `--no-fallback`。
|
|
108
|
+
|
|
99
109
|
安装时会自动:
|
|
100
110
|
|
|
101
111
|
1. 创建 `.npm-python/`
|
package/npm/lib/runtime.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { spawn, spawnSync } from "node:child_process";
|
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
|
|
6
6
|
const WINDOWS = process.platform === "win32";
|
|
7
|
+
const MIN_PYTHON_VERSION = [3, 11, 0];
|
|
7
8
|
|
|
8
9
|
const PKG_BY_BIN = {
|
|
9
10
|
qingflow: "qingflow-cli",
|
|
@@ -26,11 +27,41 @@ function runChecked(command, args, options = {}) {
|
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
function
|
|
30
|
+
function commandResult(command, args) {
|
|
30
31
|
const result = spawnSync(command, args, {
|
|
31
|
-
|
|
32
|
+
encoding: "utf8",
|
|
33
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
32
34
|
});
|
|
33
|
-
return
|
|
35
|
+
return {
|
|
36
|
+
status: result.status ?? 1,
|
|
37
|
+
error: result.error,
|
|
38
|
+
stdout: result.stdout ?? "",
|
|
39
|
+
stderr: result.stderr ?? "",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function parseVersion(text) {
|
|
44
|
+
const match = /(\d+)\.(\d+)\.(\d+)/.exec(text);
|
|
45
|
+
if (!match) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function versionAtLeast(current, minimum) {
|
|
52
|
+
for (let index = 0; index < minimum.length; index += 1) {
|
|
53
|
+
if ((current[index] ?? 0) > minimum[index]) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if ((current[index] ?? 0) < minimum[index]) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function formatVersion(version) {
|
|
64
|
+
return version.join(".");
|
|
34
65
|
}
|
|
35
66
|
|
|
36
67
|
export function getPackageRoot(metaUrl) {
|
|
@@ -449,6 +480,40 @@ export function inspectPythonEnv(packageRoot, commandName = "qingflow-mcp") {
|
|
|
449
480
|
};
|
|
450
481
|
}
|
|
451
482
|
|
|
483
|
+
function getRuntimeProbeModule(commandName) {
|
|
484
|
+
if (commandName === "qingflow") {
|
|
485
|
+
return "qingflow_mcp.cli.main";
|
|
486
|
+
}
|
|
487
|
+
if (commandName === "qingflow-app-user-mcp") {
|
|
488
|
+
return "qingflow_mcp.server_app_user";
|
|
489
|
+
}
|
|
490
|
+
if (commandName === "qingflow-app-builder-mcp") {
|
|
491
|
+
return "qingflow_mcp.server_app_builder";
|
|
492
|
+
}
|
|
493
|
+
return "qingflow_mcp";
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function probePythonRuntime(packageRoot, commandName) {
|
|
497
|
+
const python = getVenvPython(packageRoot);
|
|
498
|
+
if (!fs.existsSync(python)) {
|
|
499
|
+
return { ok: false, details: `missing Python executable: ${python}` };
|
|
500
|
+
}
|
|
501
|
+
const moduleName = getRuntimeProbeModule(commandName);
|
|
502
|
+
const result = spawnSync(python, ["-c", `import ${moduleName}`], {
|
|
503
|
+
cwd: packageRoot,
|
|
504
|
+
encoding: "utf8",
|
|
505
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
506
|
+
});
|
|
507
|
+
if (result.error) {
|
|
508
|
+
return { ok: false, details: result.error.message };
|
|
509
|
+
}
|
|
510
|
+
if (result.status !== 0) {
|
|
511
|
+
const details = [result.stderr, result.stdout].filter((value) => typeof value === "string" && value.trim()).join("\n");
|
|
512
|
+
return { ok: false, details: details || `import ${moduleName} failed` };
|
|
513
|
+
}
|
|
514
|
+
return { ok: true, details: "" };
|
|
515
|
+
}
|
|
516
|
+
|
|
452
517
|
function formatRuntimeProblem(runtime, commandName, { allowRuntimeBootstrap = false } = {}) {
|
|
453
518
|
const problemLines = [];
|
|
454
519
|
for (const problem of runtime.problems) {
|
|
@@ -511,30 +576,38 @@ function findOfflineProjectWheel(findLinksDir) {
|
|
|
511
576
|
export function findPython() {
|
|
512
577
|
const preferred = process.env.QINGFLOW_MCP_PYTHON?.trim();
|
|
513
578
|
const candidates = preferred
|
|
514
|
-
? [{ command: preferred,
|
|
579
|
+
? [{ command: preferred, checkArgs: ["-V"], runArgs: [], label: preferred }]
|
|
515
580
|
: WINDOWS
|
|
516
581
|
? [
|
|
517
|
-
{ command: "py",
|
|
518
|
-
{ command: "python",
|
|
519
|
-
{ command: "python3",
|
|
582
|
+
{ command: "py", checkArgs: ["-3", "-V"], runArgs: ["-3"], label: "py -3" },
|
|
583
|
+
{ command: "python", checkArgs: ["-V"], runArgs: [], label: "python" },
|
|
584
|
+
{ command: "python3", checkArgs: ["-V"], runArgs: [], label: "python3" },
|
|
520
585
|
]
|
|
521
586
|
: [
|
|
522
|
-
{ command: "python3",
|
|
523
|
-
{ command: "python",
|
|
587
|
+
{ command: "python3", checkArgs: ["-V"], runArgs: [], label: "python3" },
|
|
588
|
+
{ command: "python", checkArgs: ["-V"], runArgs: [], label: "python" },
|
|
524
589
|
];
|
|
525
590
|
|
|
591
|
+
const rejected = [];
|
|
526
592
|
for (const candidate of candidates) {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
593
|
+
const result = commandResult(candidate.command, candidate.checkArgs);
|
|
594
|
+
if (result.status !== 0) {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
const version = parseVersion(`${result.stdout}\n${result.stderr}`);
|
|
598
|
+
if (!version) {
|
|
599
|
+
rejected.push(`${candidate.label}: version could not be parsed`);
|
|
600
|
+
continue;
|
|
532
601
|
}
|
|
602
|
+
if (!versionAtLeast(version, MIN_PYTHON_VERSION)) {
|
|
603
|
+
rejected.push(`${candidate.label}: ${formatVersion(version)}`);
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
return { command: candidate.command, args: candidate.runArgs, label: `${candidate.label} (${formatVersion(version)})` };
|
|
533
607
|
}
|
|
534
608
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
);
|
|
609
|
+
const rejectedText = rejected.length ? ` Detected but rejected: ${rejected.join(", ")}.` : "";
|
|
610
|
+
throw new Error(`Python ${formatVersion(MIN_PYTHON_VERSION)}+ was not found.${rejectedText} Set QINGFLOW_MCP_PYTHON to a Python 3.11+ executable before running npm install.`);
|
|
538
611
|
}
|
|
539
612
|
|
|
540
613
|
export function ensurePythonEnv(packageRoot, { force = false, commandName = "qingflow-mcp" } = {}) {
|
|
@@ -544,7 +617,11 @@ export function ensurePythonEnv(packageRoot, { force = false, commandName = "qin
|
|
|
544
617
|
const { packageVersion, serverCommand, stampPath, venvDir, stampVersion } = runtime;
|
|
545
618
|
|
|
546
619
|
if (!force && fs.existsSync(serverCommand) && fs.existsSync(stampPath) && stampVersion && stampVersion === packageVersion) {
|
|
547
|
-
|
|
620
|
+
const probe = probePythonRuntime(packageRoot, commandName);
|
|
621
|
+
if (probe.ok) {
|
|
622
|
+
return serverCommand;
|
|
623
|
+
}
|
|
624
|
+
fs.rmSync(venvDir, { recursive: true, force: true });
|
|
548
625
|
}
|
|
549
626
|
|
|
550
627
|
if (force && fs.existsSync(venvDir)) {
|
|
@@ -571,6 +648,11 @@ export function ensurePythonEnv(packageRoot, { force = false, commandName = "qin
|
|
|
571
648
|
}
|
|
572
649
|
runChecked(pip, pipArgs, { cwd: packageRoot });
|
|
573
650
|
|
|
651
|
+
const probe = probePythonRuntime(packageRoot, commandName);
|
|
652
|
+
if (!probe.ok) {
|
|
653
|
+
throw new Error(`Bootstrap finished but Python runtime import probe failed:\n${probe.details}`);
|
|
654
|
+
}
|
|
655
|
+
|
|
574
656
|
fs.writeFileSync(
|
|
575
657
|
stampPath,
|
|
576
658
|
JSON.stringify(
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -9,7 +9,7 @@ description: |
|
|
|
9
9
|
|
|
10
10
|
# Qingflow CLI 使用技能
|
|
11
11
|
|
|
12
|
-
> **Skill 版本**:`qingflow-skills-2026.07.01.
|
|
12
|
+
> **Skill 版本**:`qingflow-skills-2026.07.01.04`(入口文档版本;CLI 包版本用 `qingflow --version`;需要定位版本漂移时用 `qingflow --json version` 读取 `version/package/command_path/executable_path/package_root/skill_version`)。
|
|
13
13
|
|
|
14
14
|
**硬约束(必读)**:正文各节与文末「命令速查」中的命令**只作子命令形态索引**,不覆盖 JSON 结构、`--*-file` 键名、枚举全集、执行顺序与排障细节。凡工作**偏复杂**(多步串联、大块 payload、导入全链、**Builder 搭建向**(应用/schema/流程/布局/视图/门户/报表/按钮/关联资源的配置与发布、系统列与字段 `type`)、契约型 `apply`、按 schema 组织写入 payload、任务下钻与 `task action` 等),或你判断当前任务与「关联文件」里某篇所描述的内容**需求一致、场景相同或大体同类**,都应**先 Read 对应 `reference/...` 文档**,再结合 `qingflow … --help` 与 **[EXPLORATION_REPORT](./reference/core/QINGFLOW_CLI_EXPLORATION_REPORT.md)**。**禁止**仅凭索引、习惯或类比去补参数、臆造字段名或推断服务端行为。**CLI 自动化场景只通过 `qingflow` 命令工作**;相关说明已按主题合并为本文档下的 `reference/` 子目录。**最终统计结论、分析报告、趋势/排名/比例/分布**统一走 **[record/analysis](./reference/record/analysis/README.md)** 的 `qingflow record access -> Python/pandas`。
|
|
15
15
|
|
|
@@ -36,13 +36,13 @@ description: |
|
|
|
36
36
|
| [reference/builder/60-charts.md](./reference/builder/60-charts.md) | **报表 / QingBI**:指标卡、图表、语义聚合、筛选、排序、更新 |
|
|
37
37
|
| [reference/builder/70-portal.md](./reference/builder/70-portal.md) | **门户**:标准工作台、业务入口、指标、图表、视图组件、发布 |
|
|
38
38
|
| [reference/builder/80-buttons-associated-resources.md](./reference/builder/80-buttons-associated-resources.md) | **关联资源 / 非主链路按钮维护**:关联视图/报表、`match_mappings`、上下文传参;按钮配置看视图文档 `action_buttons` |
|
|
39
|
-
| [reference/builder/90-workflow.md](./reference/builder/90-workflow.md) |
|
|
39
|
+
| [reference/builder/90-workflow.md](./reference/builder/90-workflow.md) | **流程**:WorkflowSpec、`patch_nodes`、角色/成员、流程回读 |
|
|
40
40
|
| [reference/builder/99-publish-verify.md](./reference/builder/99-publish-verify.md) | **发布与回读**:`publish verify`、partial/readback 处理、最终汇报口径 |
|
|
41
41
|
| [reference/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md](./reference/record/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md) | **新建记录**:`record schema insert -> record insert --items-file`;成员/部门/关联优先自然语言输入;细节见 [record/insert](./reference/record/insert/README.md) |
|
|
42
42
|
| [reference/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md](./reference/record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md) | **更新记录**:主链路是 `record get` → 智能体按 `fields[]` 组 key/value → **`record update`**;`record schema update` 仅用于失败后诊断可写字段/路径 |
|
|
43
43
|
| [reference/QINGFLOW_CLI_RECORD_DELETE_WORKFLOW.md](./reference/record/QINGFLOW_CLI_RECORD_DELETE_WORKFLOW.md) | **删除记录**:`record list/get` 精确定位 → `record delete --app-key --record-id --view-id system:*`;批量用 `--record-ids-file` |
|
|
44
44
|
| [reference/record/analysis/README.md](./reference/record/analysis/README.md) | **数据分析**:最终统计结论、分析报告、趋势/排名/比例/分布统一走 `record access -> Python/pandas` |
|
|
45
|
-
| [reference/builder/reference/app-delivery-sop.md](./reference/builder/reference/app-delivery-sop.md) | **底层交付参考**:历史完整 SOP
|
|
45
|
+
| [reference/builder/reference/app-delivery-sop.md](./reference/builder/reference/app-delivery-sop.md) | **底层交付参考**:历史完整 SOP、权限、系统列和工具细节;不是主入口 |
|
|
46
46
|
| [reference/builder/reference/workspace-icons.md](./reference/builder/reference/workspace-icons.md) | **图标参考**:`builder icon catalog`;新建应用包、应用、门户必须显式选择非 `template` 的 `icon + color` |
|
|
47
47
|
| [reference/builder/reference/match-rules.md](./reference/builder/reference/match-rules.md) | **统一筛选 / 条件写法**:`filters`、`visible_when`、QingBI 图表筛选、工作流条件、`match_mappings`、`field_mappings` 的 `operator/value` 规则 |
|
|
48
48
|
| [reference/builder/workflow/README.md](./reference/builder/workflow/README.md) | **工作流搭建**:已有应用的流程建模、节点配置、`builder flow apply` 与 `patch_nodes` |
|
|
@@ -70,10 +70,10 @@ description: |
|
|
|
70
70
|
> 仅qingflow命令执行后发现不可用再安装,不需要进行校验动作
|
|
71
71
|
|
|
72
72
|
```bash
|
|
73
|
-
|
|
73
|
+
npx qingflow-cli@latest install
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
安装器会安装真实 CLI 包 `@qingflow-tech/qingflow-cli@latest`;会预检 Node.js、npm、Python 3.11+;若全局 npm 目录权限不足,会 fallback 到用户目录(macOS/Linux 为 `~/.local`,Windows 为用户 AppData npm 目录)并提示 PATH 配置,不会自动改 shell 文件。排障可加 `--verbose`。环境:Node.js v16+、npm、Python 3.11+、可达 npm registry / 轻流 API。
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
@@ -11,7 +11,7 @@ Not responsible for: guessing raw backend fields without first reading `builder
|
|
|
11
11
|
## Main chain
|
|
12
12
|
|
|
13
13
|
```text
|
|
14
|
-
contract -> app get fields -> builder flow schema -> builder flow get -> member/role lookup -> build WorkflowSpec
|
|
14
|
+
contract -> app get fields -> builder flow schema -> builder flow get -> member/role lookup -> build WorkflowSpec -> flow apply --spec-file -> builder flow get readback
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Demo/reference files
|
|
@@ -21,20 +21,14 @@ Workflow examples depend on live `builder flow schema`, field ids, role ids, and
|
|
|
21
21
|
## Recommended write path
|
|
22
22
|
|
|
23
23
|
- Before applying a workflow, verify the app has an explicit business status select field such as `状态`, `处理状态`, `审批状态`, `工单状态`, `计划状态`, `报工状态`, or `单据状态`. Domain result fields are not enough by themselves: for example, `检验结论` should be paired with `处理状态`.
|
|
24
|
-
- For
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
- Patch preset node ids instead of adding duplicate nodes:
|
|
28
|
-
- `basic_approval` -> `approve_1`
|
|
29
|
-
- `basic_fill_then_approve` -> `fill_1`, `approve_1`
|
|
30
|
-
- Use `patch_nodes[]` for targeted updates to an existing flow. Node ids come from `builder flow get` readback, not from the original public `nodes-file` ids after the backend has assigned workflow node ids.
|
|
24
|
+
- For workflow creation or replacement, always use `builder flow get` / `builder flow schema`, then submit a complete WorkflowSpec with `--spec-file`.
|
|
25
|
+
- Do not use `--nodes-file` + `--transitions-file` in skill-led workflow builds. Even simple linear workflows should be represented as WorkflowSpec.
|
|
26
|
+
- Use `patch_nodes[]` only for targeted maintenance of existing nodes. Node ids come from `builder flow get` readback.
|
|
31
27
|
- Do not mix `patch_nodes` and full `spec` in the same call.
|
|
32
28
|
|
|
33
|
-
##
|
|
29
|
+
## Input modes
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Branching or richer routing should use the WorkflowSpec `--spec-file` path after reading the schema.
|
|
31
|
+
All workflow creation and replacement uses WorkflowSpec through `--spec-file`. Existing-node maintenance can use `--patch-nodes-file` after readback. This is the only skill-led workflow write path for linear, branching, Q-Robot, approval, filling, and cc flows.
|
|
38
32
|
|
|
39
33
|
## Detailed workflow docs
|
|
40
34
|
|
|
@@ -52,7 +52,7 @@ Rules:
|
|
|
52
52
|
| [60-charts.md](./60-charts.md) | Standalone QingBI chart maintenance; portal dashboards normally use section `chart` for missing reports |
|
|
53
53
|
| [70-portal.md](./70-portal.md) | Portal apply/delete, standard workbench layout, component config, section `chart` |
|
|
54
54
|
| [80-buttons-associated-resources.md](./80-buttons-associated-resources.md) | Associated views/reports and context mappings; standalone button maintenance only when the user explicitly asks to maintain existing button bodies outside view design |
|
|
55
|
-
| [90-workflow.md](./90-workflow.md) |
|
|
55
|
+
| [90-workflow.md](./90-workflow.md) | WorkflowSpec, patch_nodes, workflow verification |
|
|
56
56
|
| [99-publish-verify.md](./99-publish-verify.md) | Publish verification, partial success, readback-before-retry |
|
|
57
57
|
|
|
58
58
|
## Example files
|
|
@@ -306,14 +306,11 @@ qingflow builder layout apply \
|
|
|
306
306
|
```bash
|
|
307
307
|
qingflow builder flow apply \
|
|
308
308
|
--app-key "<APP_KEY>" \
|
|
309
|
-
--mode replace \
|
|
310
309
|
[--publish | --no-publish] \
|
|
311
|
-
--
|
|
312
|
-
--transitions-file tmp/transitions.json
|
|
310
|
+
--spec-file tmp/flow_spec.json
|
|
313
311
|
```
|
|
314
312
|
|
|
315
|
-
-
|
|
316
|
-
- **限制**(契约 **execution_notes**):公开面 **有意仅支持线性流程**;**分支 / 条件节点不可用**(后端前端组合不稳定)。
|
|
313
|
+
- 公开智能体链路只使用 WorkflowSpec `--spec-file` 或已有节点 `--patch-nodes-file`。
|
|
317
314
|
|
|
318
315
|
---
|
|
319
316
|
|
|
@@ -398,7 +395,7 @@ qingflow builder flow apply \
|
|
|
398
395
|
### 7.2 布局 / 流程中的「系统行为」
|
|
399
396
|
|
|
400
397
|
- **布局**:仅摆放 **`app_get_fields`** 里出现的 **`name`**;不要把上表系统列名放进 **`rows`** 除非读回确认存在对应可摆放控件。
|
|
401
|
-
-
|
|
398
|
+
- **流程**:WorkflowSpec 中的字段权限、条件和自动化映射须引用 **真实业务字段名 / 字段 id**(先读 `fields` 与 `builder flow schema`)。流程需要状态时,创建业务字段 `状态` / `处理状态` 等,不创建平台字段 `当前流程状态`。
|
|
402
399
|
|
|
403
400
|
---
|
|
404
401
|
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
|------|------|
|
|
7
7
|
| `manifest.yaml` | 技能清单 |
|
|
8
8
|
| `SKILL.md` | 主流程入口 |
|
|
9
|
-
| `scripts/validate_flow_spec.py` | 工作流 Spec 验证脚本,基于 JSON Schema + 自定义约束 |
|
|
10
|
-
| `scripts/diff_flow_spec.py` | 新旧 Spec 差异分析脚本,辅助更新模式下最小修改原则判断 |
|
|
9
|
+
| `scripts/workflow/validate_flow_spec.py` | 工作流 Spec 验证脚本,基于 JSON Schema + 自定义约束 |
|
|
10
|
+
| `scripts/workflow/diff_flow_spec.py` | 新旧 Spec 差异分析脚本,辅助更新模式下最小修改原则判断 |
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## 依赖声明
|
|
15
15
|
|
|
16
|
-
本 Skill 关键依赖 **qingflow CLI**(已安装于 PATH
|
|
16
|
+
本 Skill 关键依赖 **qingflow CLI**(已安装于 PATH,详见主入口 `qingflow-cli` Skill)。以下 qingflow 命令为核心操作:
|
|
17
17
|
|
|
18
18
|
| 命令 | 用途 |
|
|
19
19
|
|------|------|
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
| `qingflow builder flow get --app-key <KEY>` | 读取当前工作流 spec |
|
|
22
22
|
| `qingflow --json builder flow apply --app-key <KEY> --spec-file <FILE>` | 主链路:部署/更新 WorkflowSpec |
|
|
23
23
|
| `qingflow --json builder flow apply --app-key <KEY> --patch-nodes-file <PATCH>` | 局部修改现有节点 |
|
|
24
|
-
| `qingflow --json builder flow apply --app-key <KEY> --nodes-file <NODES> --transitions-file <TRANSITIONS>` | 兼容链路:简单线性 public 工作流 |
|
|
25
24
|
| `qingflow builder member search --query <关键词>` | 搜索成员 |
|
|
26
25
|
| `qingflow builder role search --keyword <关键词>` | 搜索角色 |
|
|
27
26
|
| `qingflow --json app get --app-key <KEY>` | 获取应用信息(字段列表等) |
|
|
@@ -35,7 +34,7 @@
|
|
|
35
34
|
| 在范围内 | 超出范围 |
|
|
36
35
|
|----------|----------|
|
|
37
36
|
| 基于已有应用搭建工作流 | 从零创建应用 |
|
|
38
|
-
| WorkflowSpec 生成与 apply
|
|
37
|
+
| WorkflowSpec 生成与 apply;`patch_nodes` 仅用于已有节点局部维护 | 操作复杂命令拼接 |
|
|
39
38
|
| 审批/填写/抄送/分支条件等 WorkflowSpec 支持的流程 | 不读 schema/spec 就猜 raw 后端字段 |
|
|
40
39
|
| 审批/填写/抄送/自动化节点配置 | 修改字段定义 |
|
|
41
40
|
| 成员/角色搜索用于节点负责人 | 组织架构管理 |
|
|
@@ -43,5 +42,7 @@
|
|
|
43
42
|
|
|
44
43
|
---
|
|
45
44
|
|
|
45
|
+
无论线性、分支、Q-Robot、审批、填写还是抄送流程,新建和替换都使用 WorkflowSpec `--spec-file`;已有节点的小修改才使用 `--patch-nodes-file`。不要在技能主链路使用 `--nodes-file` + `--transitions-file`。
|
|
46
|
+
|
|
46
47
|
← 返回主流程:[../SKILL.md](../../../SKILL.md)
|
|
47
48
|
→ 下一步:[02-update-mode.md](02-update-mode.md)
|
|
@@ -16,7 +16,7 @@ n1 → n2 → n3 → n4
|
|
|
16
16
|
|
|
17
17
|
## 分支流程
|
|
18
18
|
|
|
19
|
-
分支流程属于 WorkflowSpec
|
|
19
|
+
分支流程属于 WorkflowSpec 主路径。需要分支时先读 `builder flow schema` / `builder flow get`,再用 `--spec-file` 提交完整 WorkflowSpec。
|
|
20
20
|
|
|
21
21
|
轻流的分支采用**并行分支**模型——通过 `gateway` 节点(`mode: parallel`)分发,所有出边指向的分支**都会进入**,通过每条边上的条件(`condition.autoJudges`)控制分支内的节点逻辑是否执行。
|
|
22
22
|
|
|
@@ -19,48 +19,16 @@ qingflow --json builder flow get --app-key <APP_KEY> > tmp/current_flow.json
|
|
|
19
19
|
**更新模式下**:如果走 `patch_nodes[]`,直接使用读回的 `spec.nodes[].id` 做局部修改;如果提交完整 `--spec-file`,用 diff 脚本确认变更范围是否符合预期:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
python3 scripts/diff_flow_spec.py tmp/current_flow.json tmp/flow_spec.json
|
|
22
|
+
python3 scripts/workflow/diff_flow_spec.py tmp/current_flow.json tmp/flow_spec.json
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
新建场景可跳过此步。
|
|
26
26
|
|
|
27
|
-
## 3.3
|
|
27
|
+
## 3.3 主路径:构建 WorkflowSpec
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
`--spec-file` 用于已经从 `builder flow schema` / `builder flow get` 读回并理解的 WorkflowSpec。节点结构、节点 id、负责人、字段权限和边条件都以 schema/readback 为准。
|
|
30
30
|
|
|
31
|
-
`
|
|
32
|
-
|
|
33
|
-
```json
|
|
34
|
-
[
|
|
35
|
-
{"id": "start", "type": "start", "name": "提交申请"},
|
|
36
|
-
{"id": "approve_1", "type": "approve", "name": "部门经理审批", "role_names": ["部门经理"]},
|
|
37
|
-
{"id": "end", "type": "end", "name": "结束"}
|
|
38
|
-
]
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
`tmp/flow_transitions.json`
|
|
42
|
-
|
|
43
|
-
```json
|
|
44
|
-
[
|
|
45
|
-
{"from": "start", "to": "approve_1"},
|
|
46
|
-
{"from": "approve_1", "to": "end"}
|
|
47
|
-
]
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
提交时使用:
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
qingflow --json builder flow apply \
|
|
54
|
-
--app-key <APP_KEY> \
|
|
55
|
-
--nodes-file tmp/flow_nodes.json \
|
|
56
|
-
--transitions-file tmp/flow_transitions.json \
|
|
57
|
-
--publish \
|
|
58
|
-
> tmp/flow_apply.json
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## 3.4 主路径:构建 WorkflowSpec
|
|
62
|
-
|
|
63
|
-
`--spec-file` 用于已经从 `builder flow schema` / `builder flow get` 读回并理解的 WorkflowSpec。不要把 `start` / `approve` / `fill` / `end` 这类 legacy public node alias 放进 `--spec-file`。
|
|
31
|
+
所有需要继续向下路由的节点都显式写 `sync: true`。Q-Robot 也在 WorkflowSpec 中表达为 `type: "automation"`,由 `attrs.subType` 选择具体能力。
|
|
64
32
|
|
|
65
33
|
WorkflowSpec 示例:
|
|
66
34
|
|
|
@@ -71,12 +39,14 @@ WorkflowSpec 示例:
|
|
|
71
39
|
"id": "n1",
|
|
72
40
|
"type": "applicant",
|
|
73
41
|
"name": "员工提交申请",
|
|
42
|
+
"sync": true,
|
|
74
43
|
"attrs": {}
|
|
75
44
|
},
|
|
76
45
|
{
|
|
77
46
|
"id": "n2",
|
|
78
47
|
"type": "approval",
|
|
79
48
|
"name": "部门经理审批",
|
|
49
|
+
"sync": true,
|
|
80
50
|
"attrs": {
|
|
81
51
|
"responsible": [
|
|
82
52
|
{"type": "role", "roleId": 123}
|
|
@@ -92,17 +62,39 @@ WorkflowSpec 示例:
|
|
|
92
62
|
"id": "g1",
|
|
93
63
|
"type": "gateway",
|
|
94
64
|
"name": "服务类型判断",
|
|
65
|
+
"sync": true,
|
|
95
66
|
"attrs": {"mode": "parallel"}
|
|
96
67
|
},
|
|
97
68
|
{
|
|
98
69
|
"id": "n3",
|
|
99
70
|
"type": "filling",
|
|
100
71
|
"name": "补充信息",
|
|
72
|
+
"sync": true,
|
|
101
73
|
"attrs": {
|
|
102
74
|
"responsible": [
|
|
103
75
|
{"type": "user", "uid": 456}
|
|
104
76
|
]
|
|
105
77
|
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"id": "n4",
|
|
81
|
+
"type": "approval",
|
|
82
|
+
"name": "技术服务审批",
|
|
83
|
+
"sync": true,
|
|
84
|
+
"attrs": {
|
|
85
|
+
"responsible": [
|
|
86
|
+
{"type": "role", "roleId": 456}
|
|
87
|
+
],
|
|
88
|
+
"approveType": "or_signed",
|
|
89
|
+
"auditUserType": "role"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"id": "g2",
|
|
94
|
+
"type": "gateway",
|
|
95
|
+
"name": "分支汇合",
|
|
96
|
+
"sync": true,
|
|
97
|
+
"attrs": {"mode": "join"}
|
|
106
98
|
}
|
|
107
99
|
],
|
|
108
100
|
"edges": {
|
|
@@ -146,7 +138,9 @@ WorkflowSpec 示例:
|
|
|
146
138
|
]
|
|
147
139
|
]
|
|
148
140
|
}
|
|
149
|
-
}
|
|
141
|
+
},
|
|
142
|
+
{"from": "n3", "to": "g2"},
|
|
143
|
+
{"from": "n4", "to": "g2"}
|
|
150
144
|
]
|
|
151
145
|
}
|
|
152
146
|
}
|
|
@@ -165,7 +159,7 @@ WorkflowSpec 示例:
|
|
|
165
159
|
|
|
166
160
|
## 边条件体系
|
|
167
161
|
|
|
168
|
-
本节属于 `--spec-file` WorkflowSpec 路径。不要凭记忆手写 `autoJudges`、`judgeType` 或 raw `fieldId` 条件;先读 `builder flow schema` / `builder flow get
|
|
162
|
+
本节属于 `--spec-file` WorkflowSpec 路径。不要凭记忆手写 `autoJudges`、`judgeType` 或 raw `fieldId` 条件;先读 `builder flow schema` / `builder flow get`,再按读回结构修改。
|
|
169
163
|
|
|
170
164
|
| condition.kind | 含义 | 要求 |
|
|
171
165
|
|---------------|------|------|
|
|
@@ -192,7 +186,7 @@ OR-of-AND 二维数组:
|
|
|
192
186
|
|
|
193
187
|
**judgeType 常用值**:`equals`, `not_equals`, `equals_any`, `includes`, `greater_than` 等(共21种,详见 schema)。
|
|
194
188
|
|
|
195
|
-
## 3.
|
|
189
|
+
## 3.4 局部修改 patch_nodes
|
|
196
190
|
|
|
197
191
|
局部修改现有流程时,先 `builder flow get`,使用读回 `spec.nodes[].id`:
|
|
198
192
|
|
|
@@ -2,22 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
主链路 `--spec-file` 使用本 Skill 自带的 WorkflowSpec 验证脚本;局部修改 `patch_nodes[]` 至少检查节点 id 来自 `builder flow get` 读回,且 `set/unset` 只包含要改的字段。
|
|
4
4
|
|
|
5
|
-
简单线性兼容输入 `--nodes-file + --transitions-file` 由 CLI 模型校验 public node type、边引用和角色/成员解析。提交前至少检查:
|
|
6
|
-
|
|
7
|
-
- `nodes[].id` 唯一;
|
|
8
|
-
- `transitions[].from/to` 都能在 nodes 中找到;
|
|
9
|
-
- 节点类型只用 `start`、`approve`、`fill`、`copy`、`webhook`、`end`;
|
|
10
|
-
- 审批/填写节点有明确 `member_names`、`member_ids`、`role_names` 或 `role_ids`。
|
|
11
|
-
|
|
12
5
|
WorkflowSpec 验证命令:
|
|
13
6
|
|
|
14
7
|
```bash
|
|
15
8
|
# WorkflowSpec 新建模式
|
|
16
|
-
python3 scripts/validate_flow_spec.py \
|
|
9
|
+
python3 scripts/workflow/validate_flow_spec.py \
|
|
17
10
|
tmp/flow_spec.json --schema tmp/flow_schema.json
|
|
18
11
|
|
|
19
12
|
# WorkflowSpec 更新模式(同时校验最小修改原则)
|
|
20
|
-
python3 scripts/validate_flow_spec.py \
|
|
13
|
+
python3 scripts/workflow/validate_flow_spec.py \
|
|
21
14
|
tmp/flow_spec.json --schema tmp/flow_schema.json --previous tmp/current_flow.json
|
|
22
15
|
```
|
|
23
16
|
|
|
@@ -30,10 +23,11 @@ python3 scripts/validate_flow_spec.py \
|
|
|
30
23
|
5. 审批/填写/抄送节点必要字段检查
|
|
31
24
|
6. 自动化节点配置检查
|
|
32
25
|
7. 孤立节点检查
|
|
26
|
+
8. 入口节点和需要继续路由的节点显式 `sync: true`
|
|
33
27
|
|
|
34
28
|
## 验证不通过时的处理
|
|
35
29
|
|
|
36
|
-
WorkflowSpec 根据验证脚本错误修正 spec,重新验证,直到全部通过再进入 apply
|
|
30
|
+
WorkflowSpec 根据验证脚本错误修正 spec,重新验证,直到全部通过再进入 apply。
|
|
37
31
|
|
|
38
32
|
---
|
|
39
33
|
|
|
@@ -12,8 +12,6 @@ qingflow --json builder flow apply \
|
|
|
12
12
|
> tmp/flow_apply.json
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
简单线性兼容流程仍可用 `--nodes-file + --transitions-file`;不要和 `--spec-file` / `--patch-nodes-file` 混用。
|
|
16
|
-
|
|
17
15
|
局部修改已存在节点:
|
|
18
16
|
|
|
19
17
|
```bash
|
|
@@ -41,6 +39,7 @@ qingflow --json builder flow get --app-key <APP_KEY> > tmp/deployed_flow.json
|
|
|
41
39
|
|
|
42
40
|
1. **节点数量与类型**:`nodes` 数量是否一致,每个节点的 `type` 和 `name` 是否正确
|
|
43
41
|
2. **边连通性**:`edges` 数量是否一致,`from`/`to` 关系是否正确
|
|
42
|
+
- 必须确认 `applicant` 入口节点存在出边,不能只停留在“提交申请”
|
|
44
43
|
3. **分支条件**(WorkflowSpec 路径):每个 gateway 出边是否有正确的 `autoJudges`
|
|
45
44
|
- 检查 `condition.kind` 是否为 `rules`
|
|
46
45
|
- 检查 `autoJudges` 中的 `fieldId`、`judgeType`、`values` 是否正确
|
|
@@ -53,7 +52,7 @@ qingflow --json builder flow get --app-key <APP_KEY> > tmp/deployed_flow.json
|
|
|
53
52
|
|
|
54
53
|
若验证发现不一致:
|
|
55
54
|
1. 分析差异原因(条件格式错误、节点缺失、边遗漏等)
|
|
56
|
-
2. 主路径修正 `tmp/flow_spec.json` 或 `tmp/flow_patch_nodes.json
|
|
55
|
+
2. 主路径修正 `tmp/flow_spec.json` 或 `tmp/flow_patch_nodes.json`
|
|
57
56
|
3. 重新验证 → apply → 对比
|
|
58
57
|
4. **最多循环 3 次**;若 3 次后仍有不可修复的差异,告知用户并列出:
|
|
59
58
|
- 已成功配置的部分
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# 常见问题与排障
|
|
2
2
|
|
|
3
|
-
`autoJudges` 属于 WorkflowSpec 路径。公开主链路是先读 `builder flow schema` / `builder flow get`,再提交 `--spec-file` 或 `--patch-nodes-file
|
|
3
|
+
`autoJudges` 属于 WorkflowSpec 路径。公开主链路是先读 `builder flow schema` / `builder flow get`,再提交 `--spec-file` 或 `--patch-nodes-file`。
|
|
4
4
|
|
|
5
5
|
| 问题 | 原因 | 解决 |
|
|
6
6
|
|------|------|------|
|
|
7
7
|
| `autoJudges` apply 后为空 | 使用了一维数组 `[{...}]` 格式 | 改为二维 `[[{...}]]` |
|
|
8
8
|
| 条件分支不生效 | `autoJudges` 中的 `values` 与表单选项 label 不一致 | 核对字段选项文本,确保完全一致 |
|
|
9
9
|
| apply 返回 `missing_input_node_ids` | 新建 flow 首次 apply 的正常提示 | 可忽略,再次 get 验证即可 |
|
|
10
|
+
| 录入数据后只留下“提交申请”日志,不进入下一节点 | WorkflowSpec 入口节点没有出边,或入口/路由节点缺少 `sync: true` | `builder flow get` 读回 spec,确认 applicant 出边和节点 `sync`,修正后用 `--spec-file` 发布 |
|
|
10
11
|
| 回退边(gateway → 前序节点)不生效 | 引擎不支持通过 gateway 实现回退 | 改用审批节点 `revert: true` |
|
|
11
12
|
| 审批节点无审批人 | `responsible` 中的 UID/角色 ID 无效或缺失 | 使用 `builder member search` / `role search` 确认 |
|
|
12
13
|
| `fieldType` 不匹配 | 单选用了 `text` 而非 `single_select` | 确认字段实际类型后更正 |
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
| 在范围内 | 超出范围 |
|
|
49
49
|
|----------|----------|
|
|
50
50
|
| 基于已有应用搭建工作流 | 从零创建应用 |
|
|
51
|
-
| WorkflowSpec 生成与 apply;`patch_nodes`
|
|
51
|
+
| WorkflowSpec 生成与 apply;`patch_nodes` 仅用于已有节点局部维护 | 操作复杂命令拼接 |
|
|
52
52
|
| 审批/填写/抄送/自动化/分支条件等 WorkflowSpec 支持的流程 | 不读 schema/spec 就猜 raw 后端字段 |
|
|
53
53
|
| 审批/填写/抄送/自动化节点配置 | 修改字段定义 |
|
|
54
54
|
| 成员/角色搜索用于节点负责人 | 组织架构管理 |
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
| 阶段 0 | 判断是否为更新模式,确认最小修改原则 | [02-update-mode.md](./02-update-mode.md) |
|
|
69
69
|
| 阶段 1 | 提取业务建模,完成七维度业务自检 | [04-stage1-business-modeling.md](./04-stage1-business-modeling.md) |
|
|
70
70
|
| 阶段 2 | 搜索成员/角色,用于节点负责人配置 | [05-stage2-members-roles.md](./05-stage2-members-roles.md) |
|
|
71
|
-
| 阶段 3 | 获取 Schema、读取现有流程、构建 WorkflowSpec
|
|
72
|
-
| 阶段 4 | 验证 WorkflowSpec / patch_nodes
|
|
71
|
+
| 阶段 3 | 获取 Schema、读取现有流程、构建 WorkflowSpec;已有节点小改才用 patch_nodes | [06-stage3-build-spec.md](./06-stage3-build-spec.md) |
|
|
72
|
+
| 阶段 4 | 验证 WorkflowSpec / patch_nodes | [07-stage4-validate-spec.md](./07-stage4-validate-spec.md) |
|
|
73
73
|
| 阶段 5 | Apply 工作流并验证部署结果 | [08-stage5-apply-verify.md](./08-stage5-apply-verify.md) |
|
|
74
74
|
|
|
75
75
|
构建流程输入前,若对流程模式有疑问,先查阅 [03-flow-patterns.md](./03-flow-patterns.md)。
|