@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.
Files changed (38) hide show
  1. package/README.md +2 -2
  2. package/docs/local-agent-install.md +10 -0
  3. package/npm/lib/runtime.mjs +100 -18
  4. package/package.json +1 -1
  5. package/pyproject.toml +1 -1
  6. package/skills/qingflow-cli/SKILL.md +5 -5
  7. package/skills/qingflow-cli/reference/builder/90-workflow.md +6 -12
  8. package/skills/qingflow-cli/reference/builder/README.md +1 -1
  9. package/skills/qingflow-cli/reference/builder/reference/app-delivery-sop.md +3 -6
  10. package/skills/qingflow-cli/reference/builder/workflow/01-overview.md +6 -5
  11. package/skills/qingflow-cli/reference/builder/workflow/03-flow-patterns.md +1 -1
  12. package/skills/qingflow-cli/reference/builder/workflow/06-stage3-build-spec.md +33 -39
  13. package/skills/qingflow-cli/reference/builder/workflow/07-stage4-validate-spec.md +4 -10
  14. package/skills/qingflow-cli/reference/builder/workflow/08-stage5-apply-verify.md +2 -3
  15. package/skills/qingflow-cli/reference/builder/workflow/11-troubleshooting.md +2 -1
  16. package/skills/qingflow-cli/reference/builder/workflow/README.md +3 -3
  17. package/skills/qingflow-cli/scripts/workflow/validate_flow_spec.py +24 -2
  18. package/src/qingflow_mcp/builder_facade/service.py +41 -4
  19. package/src/qingflow_mcp/cli/commands/builder.py +15 -17
  20. package/src/qingflow_mcp/server_app_builder.py +1 -7
  21. package/src/qingflow_mcp/tools/ai_builder_tools.py +32 -51
  22. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/README.md +0 -308
  23. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/build-complete-system.md +0 -819
  24. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/build-single-app.md +0 -836
  25. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/complete-system-development-guide.md +0 -137
  26. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/create-app.md +0 -203
  27. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/environments.md +0 -63
  28. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/flow-actors-and-permissions.md +0 -142
  29. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/gotchas.md +0 -116
  30. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/match-rules.md +0 -114
  31. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/public-surface-sync.md +0 -75
  32. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/single-app-development-guide.md +0 -69
  33. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/solution-playbooks.md +0 -52
  34. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/tool-selection.md +0 -113
  35. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/update-flow.md +0 -7
  36. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/update-layout.md +0 -7
  37. package/skills/qingflow-cli/reference/builder/reference/legacy-playbooks/update-schema.md +0 -7
  38. 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.33
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.33 qingflow
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/`
@@ -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 commandWorks(command, args) {
30
+ function commandResult(command, args) {
30
31
  const result = spawnSync(command, args, {
31
- stdio: "ignore",
32
+ encoding: "utf8",
33
+ stdio: ["ignore", "pipe", "pipe"],
32
34
  });
33
- return result.status === 0;
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, args: [], label: preferred }]
579
+ ? [{ command: preferred, checkArgs: ["-V"], runArgs: [], label: preferred }]
515
580
  : WINDOWS
516
581
  ? [
517
- { command: "py", args: ["-3", "-V"], label: "py -3" },
518
- { command: "python", args: ["-V"], label: "python" },
519
- { command: "python3", args: ["-V"], label: "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", args: ["-V"], label: "python3" },
523
- { command: "python", args: ["-V"], label: "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
- if (commandWorks(candidate.command, candidate.args)) {
528
- if (candidate.command === "py") {
529
- return { command: "py", args: ["-3"], label: candidate.label };
530
- }
531
- return { command: candidate.command, args: [], label: candidate.label };
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
- throw new Error(
536
- "Python 3.11+ was not found. Set QINGFLOW_MCP_PYTHON to a Python 3 executable before running npm install."
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
- return serverCommand;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qingflow-tech/qingflow-cli",
3
- "version": "1.1.33",
3
+ "version": "1.1.35",
4
4
  "description": "Human-friendly Qingflow command line interface for auth, record operations, import, tasks, and stable builder flows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qingflow-mcp"
7
- version = "1.1.33"
7
+ version = "1.1.35"
8
8
  description = "User-authenticated MCP server for Qingflow"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -9,7 +9,7 @@ description: |
9
9
 
10
10
  # Qingflow CLI 使用技能
11
11
 
12
- > **Skill 版本**:`qingflow-skills-2026.07.01.03`(入口文档版本;CLI 包版本用 `qingflow --version`;需要定位版本漂移时用 `qingflow --json version` 读取 `version/package/command_path/executable_path/package_root/skill_version`)。
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) | **流程**:流程预设、`patch_nodes`、角色/成员、流程回读 |
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、权限、旧 fallback、系统列和工具细节;不是主入口 |
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
- npm install -g @qingflow-tech/qingflow-cli@latest
73
+ npx qingflow-cli@latest install
74
74
  ```
75
75
 
76
- 环境:Node.js v16+、npm、可达轻流 API。
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 or patch_nodes -> flow apply --spec-file/--patch-nodes-file -> builder flow get readback
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 full workflow replacement, prefer `builder flow get` / `builder flow schema`, then submit a complete WorkflowSpec with `--spec-file`.
25
- - Use legacy `--nodes-file` + `--transitions-file` only for deliberately simple linear compatibility flows; it is not the main workflow path.
26
- - Start from a preset when possible: `basic_approval` or `basic_fill_then_approve`.
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
- ## Legacy public node types
29
+ ## Input modes
34
30
 
35
- Legacy `--nodes-file` supports only `start`, `approve`, `fill`, `copy`, `webhook`, and `end`.
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) | Flow presets, patch_nodes, workflow verification |
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
- --nodes-file tmp/nodes.json \
312
- --transitions-file tmp/transitions.json
310
+ --spec-file tmp/flow_spec.json
313
311
  ```
314
312
 
315
- - **`mode`**:CLI 当前仅 **`replace`**。
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
- - **流程**:**`app_flow_apply` 的 `permissions.editable_fields`** 等须引用 **真实业务字段名**(读 `fields`)。流程需要状态时,创建业务字段 `状态` / `处理状态` 等,不创建平台字段 `当前流程状态`。
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,详见 `qingflow_cli` Skill)。以下 qingflow 命令为核心操作:
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;public nodes/transitions 兼容简单线性流程 | 操作复杂命令拼接 |
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 主路径,不是简单线性兼容 `builder flow apply --nodes-file --transitions-file` 的能力范围。需要分支时先读 `builder flow schema` / `builder flow get`,再用 `--spec-file` 提交完整 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 兼容:构建 public nodes / transitions(仅简单线性)
27
+ ## 3.3 主路径:构建 WorkflowSpec
28
28
 
29
- 完整流程主链路是 `WorkflowSpec --spec-file` 或现有流程的 `patch_nodes`。只有明确是简单线性审批/填写/抄送流程时,才继续写两个 public alias 数组文件:
29
+ `--spec-file` 用于已经从 `builder flow schema` / `builder flow get` 读回并理解的 WorkflowSpec。节点结构、节点 id、负责人、字段权限和边条件都以 schema/readback 为准。
30
30
 
31
- `tmp/flow_nodes.json`
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`,再按读回结构修改。简单线性兼容链路才使用 `builder flow apply --nodes-file --transitions-file`。
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.5 局部修改 patch_nodes
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。简单线性兼容输入根据 CLI 错误修正 nodes/transitions。
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`;只有简单线性兼容输入才修正 `tmp/flow_nodes.json` / `tmp/flow_transitions.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`;简单线性兼容链路 `nodes-file + transitions-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` 局部修改;public nodes/transitions 仅作简单线性兼容 | 操作复杂命令拼接 |
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 或 patch_nodes | [06-stage3-build-spec.md](./06-stage3-build-spec.md) |
72
- | 阶段 4 | 验证 WorkflowSpec / patch_nodes;简单线性兼容输入由 CLI 校验 | [07-stage4-validate-spec.md](./07-stage4-validate-spec.md) |
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)。