@josephyan/qingflow-app-builder-mcp 1.1.30 → 1.1.33

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 (88) hide show
  1. package/README.md +6 -4
  2. package/docs/local-agent-install.md +57 -6
  3. package/entry_point.py +1 -1
  4. package/npm/bin/qingflow-app-builder-mcp.mjs +1 -1
  5. package/npm/bin/qingflow-skills.mjs +5 -0
  6. package/npm/lib/runtime.mjs +20 -59
  7. package/npm/scripts/postinstall.mjs +1 -10
  8. package/package.json +3 -2
  9. package/pyproject.toml +1 -1
  10. package/skills/qingflow-app-builder/SKILL.md +111 -55
  11. package/skills/qingflow-app-builder/references/complete-system-development-guide.md +169 -0
  12. package/skills/qingflow-app-builder/references/create-app.md +31 -24
  13. package/skills/qingflow-app-builder/references/environments.md +1 -1
  14. package/skills/qingflow-app-builder/references/gotchas.md +40 -14
  15. package/skills/qingflow-app-builder/references/match-rules.md +196 -85
  16. package/skills/qingflow-app-builder/references/public-surface-sync.md +2 -2
  17. package/skills/qingflow-app-builder/references/single-app-development-guide.md +84 -0
  18. package/skills/qingflow-app-builder/references/solution-playbooks.md +10 -0
  19. package/skills/qingflow-app-builder/references/tool-selection.md +40 -25
  20. package/skills/qingflow-app-builder/references/update-flow.md +27 -52
  21. package/skills/qingflow-app-builder/references/update-schema.md +14 -0
  22. package/skills/qingflow-app-builder/references/update-views.md +101 -32
  23. package/skills/qingflow-app-builder/scripts/validate_system_build_summary.py +124 -0
  24. package/skills/qingflow-app-builder-code-integrations/SKILL.md +5 -3
  25. package/skills/qingflow-app-builder-code-integrations/references/code-block.md +1 -1
  26. package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +1 -1
  27. package/skills/qingflow-mcp-setup/SKILL.md +13 -9
  28. package/skills/qingflow-mcp-setup/references/claude-desktop.md +1 -1
  29. package/skills/qingflow-mcp-setup/references/environments.md +2 -1
  30. package/skills/qingflow-mcp-setup/references/generic-stdio.md +6 -5
  31. package/skills/qingflow-workflow-builder/SKILL.md +9 -7
  32. package/skills/qingflow-workflow-builder/references/01-overview.md +4 -2
  33. package/skills/qingflow-workflow-builder/references/03-flow-patterns.md +2 -0
  34. package/skills/qingflow-workflow-builder/references/06-stage3-build-spec.md +59 -7
  35. package/skills/qingflow-workflow-builder/references/07-stage4-validate-spec.md +14 -5
  36. package/skills/qingflow-workflow-builder/references/08-stage5-apply-verify.md +19 -3
  37. package/skills/qingflow-workflow-builder/references/11-troubleshooting.md +2 -0
  38. package/src/qingflow_mcp/__main__.py +6 -2
  39. package/src/qingflow_mcp/builder_facade/models.py +473 -138
  40. package/src/qingflow_mcp/builder_facade/service.py +6356 -1866
  41. package/src/qingflow_mcp/cli/commands/builder.py +358 -355
  42. package/src/qingflow_mcp/cli/commands/chart.py +1 -1
  43. package/src/qingflow_mcp/cli/commands/common.py +12 -3
  44. package/src/qingflow_mcp/cli/commands/exports.py +2 -2
  45. package/src/qingflow_mcp/cli/commands/imports.py +3 -3
  46. package/src/qingflow_mcp/cli/commands/portal.py +2 -2
  47. package/src/qingflow_mcp/cli/commands/record.py +101 -27
  48. package/src/qingflow_mcp/cli/commands/task.py +28 -47
  49. package/src/qingflow_mcp/cli/commands/view.py +1 -1
  50. package/src/qingflow_mcp/cli/context.py +0 -3
  51. package/src/qingflow_mcp/cli/formatters.py +784 -16
  52. package/src/qingflow_mcp/cli/main.py +120 -41
  53. package/src/qingflow_mcp/errors.py +43 -2
  54. package/src/qingflow_mcp/public_surface.py +26 -17
  55. package/src/qingflow_mcp/response_trim.py +81 -17
  56. package/src/qingflow_mcp/server.py +14 -12
  57. package/src/qingflow_mcp/server_app_builder.py +83 -39
  58. package/src/qingflow_mcp/server_app_user.py +22 -16
  59. package/src/qingflow_mcp/session_store.py +11 -7
  60. package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
  61. package/src/qingflow_mcp/solution/executor.py +114 -15
  62. package/src/qingflow_mcp/tools/ai_builder_tools.py +3571 -1473
  63. package/src/qingflow_mcp/tools/app_tools.py +184 -43
  64. package/src/qingflow_mcp/tools/approval_tools.py +197 -35
  65. package/src/qingflow_mcp/tools/auth_tools.py +92 -16
  66. package/src/qingflow_mcp/tools/code_block_tools.py +298 -40
  67. package/src/qingflow_mcp/tools/custom_button_tools.py +64 -10
  68. package/src/qingflow_mcp/tools/directory_tools.py +236 -72
  69. package/src/qingflow_mcp/tools/export_tools.py +244 -34
  70. package/src/qingflow_mcp/tools/feedback_tools.py +9 -0
  71. package/src/qingflow_mcp/tools/file_tools.py +9 -3
  72. package/src/qingflow_mcp/tools/import_tools.py +336 -49
  73. package/src/qingflow_mcp/tools/navigation_tools.py +91 -12
  74. package/src/qingflow_mcp/tools/package_tools.py +118 -6
  75. package/src/qingflow_mcp/tools/portal_tools.py +39 -3
  76. package/src/qingflow_mcp/tools/qingbi_report_tools.py +116 -7
  77. package/src/qingflow_mcp/tools/record_tools.py +1141 -356
  78. package/src/qingflow_mcp/tools/resource_read_tools.py +188 -39
  79. package/src/qingflow_mcp/tools/role_tools.py +80 -9
  80. package/src/qingflow_mcp/tools/solution_tools.py +57 -15
  81. package/src/qingflow_mcp/tools/task_context_tools.py +687 -159
  82. package/src/qingflow_mcp/tools/task_tools.py +113 -29
  83. package/src/qingflow_mcp/tools/view_tools.py +106 -3
  84. package/src/qingflow_mcp/tools/workflow_tools.py +17 -1
  85. package/src/qingflow_mcp/tools/workspace_tools.py +71 -3
  86. package/src/qingflow_mcp/version.py +0 -2
  87. package/skills/qingflow-app-builder/references/build-complete-system.md +0 -234
  88. package/skills/qingflow-app-builder/references/build-single-app.md +0 -138
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import json
6
+ import sys
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+
11
+ VALID_PORTAL_STATUSES = {"verified", "unverified", "not_created"}
12
+ VALID_APP_VERIFY_STATUSES = {"verified", "unverified", "failed"}
13
+
14
+
15
+ def main(argv: list[str] | None = None) -> int:
16
+ parser = argparse.ArgumentParser(description="Validate a Qingflow complete-system delivery summary JSON file.")
17
+ parser.add_argument("summary_file", nargs="?", default="tmp/qingflow_system_build_summary.json")
18
+ args = parser.parse_args(argv)
19
+ path = Path(args.summary_file)
20
+ issues = validate_summary_file(path)
21
+ if issues:
22
+ _emit({"status": "failed", "error_code": "SYSTEM_BUILD_SUMMARY_INVALID", "path": str(path), "issues": issues})
23
+ return 1
24
+ payload = json.loads(path.read_text(encoding="utf-8"))
25
+ _emit(
26
+ {
27
+ "status": "success",
28
+ "path": str(path),
29
+ "summary": {
30
+ "package_id": payload.get("package_id"),
31
+ "package_name": payload.get("package_name"),
32
+ "portal_dash_key": payload.get("portal_dash_key"),
33
+ "portal_live_status": payload.get("portal_live_status"),
34
+ "app_count": len(payload.get("apps") or []),
35
+ "partial_count": len(payload.get("partial_items") or []),
36
+ "needs_followup_count": len(payload.get("needs_followup") or []),
37
+ },
38
+ }
39
+ )
40
+ return 0
41
+
42
+
43
+ def validate_summary_file(path: Path) -> list[dict[str, Any]]:
44
+ if not path.exists():
45
+ return [_issue("MISSING_FILE", "$", f"summary file does not exist: {path}")]
46
+ try:
47
+ payload = json.loads(path.read_text(encoding="utf-8"))
48
+ except OSError as exc:
49
+ return [_issue("READ_FAILED", "$", str(exc))]
50
+ except json.JSONDecodeError as exc:
51
+ return [_issue("INVALID_JSON", "$", exc.msg)]
52
+ if not isinstance(payload, dict):
53
+ return [_issue("INVALID_ROOT", "$", "summary root must be a JSON object")]
54
+
55
+ issues: list[dict[str, Any]] = []
56
+ _require_positive_int(payload, "package_id", issues)
57
+ _require_nonempty_string(payload, "package_name", issues)
58
+ _require_bool(payload, "front_end_visible", issues)
59
+ _require_string_enum(payload, "portal_live_status", VALID_PORTAL_STATUSES, issues)
60
+ if payload.get("portal_live_status") == "verified":
61
+ _require_nonempty_string(payload, "portal_dash_key", issues)
62
+ elif "portal_dash_key" in payload and payload.get("portal_dash_key") is not None and not isinstance(payload.get("portal_dash_key"), str):
63
+ issues.append(_issue("INVALID_TYPE", "$.portal_dash_key", "portal_dash_key must be a string when present"))
64
+
65
+ apps = payload.get("apps")
66
+ if not isinstance(apps, list) or not apps:
67
+ issues.append(_issue("INVALID_APPS", "$.apps", "apps must be a non-empty array"))
68
+ else:
69
+ for index, app in enumerate(apps):
70
+ prefix = f"$.apps[{index}]"
71
+ if not isinstance(app, dict):
72
+ issues.append(_issue("INVALID_APP_ITEM", prefix, "app item must be an object"))
73
+ continue
74
+ _require_nonempty_string(app, "app_key", issues, prefix)
75
+ _require_nonempty_string(app, "app_name", issues, prefix)
76
+ for key in ("fields_count", "views_count", "flows_count", "charts_count"):
77
+ _require_nonnegative_int(app, key, issues, prefix)
78
+ _require_string_enum(app, "publish_verify_status", VALID_APP_VERIFY_STATUSES, issues, prefix)
79
+
80
+ for key in ("warnings", "partial_items", "needs_followup"):
81
+ if not isinstance(payload.get(key), list):
82
+ issues.append(_issue("INVALID_TYPE", f"$.{key}", f"{key} must be an array"))
83
+ return issues
84
+
85
+
86
+ def _require_positive_int(payload: dict[str, Any], key: str, issues: list[dict[str, Any]], prefix: str = "$") -> None:
87
+ value = payload.get(key)
88
+ if isinstance(value, bool) or not isinstance(value, int) or value <= 0:
89
+ issues.append(_issue("INVALID_TYPE", f"{prefix}.{key}", f"{key} must be a positive integer"))
90
+
91
+
92
+ def _require_nonnegative_int(payload: dict[str, Any], key: str, issues: list[dict[str, Any]], prefix: str = "$") -> None:
93
+ value = payload.get(key)
94
+ if isinstance(value, bool) or not isinstance(value, int) or value < 0:
95
+ issues.append(_issue("INVALID_TYPE", f"{prefix}.{key}", f"{key} must be a non-negative integer"))
96
+
97
+
98
+ def _require_nonempty_string(payload: dict[str, Any], key: str, issues: list[dict[str, Any]], prefix: str = "$") -> None:
99
+ value = payload.get(key)
100
+ if not isinstance(value, str) or not value.strip():
101
+ issues.append(_issue("INVALID_TYPE", f"{prefix}.{key}", f"{key} must be a non-empty string"))
102
+
103
+
104
+ def _require_bool(payload: dict[str, Any], key: str, issues: list[dict[str, Any]], prefix: str = "$") -> None:
105
+ if not isinstance(payload.get(key), bool):
106
+ issues.append(_issue("INVALID_TYPE", f"{prefix}.{key}", f"{key} must be a boolean"))
107
+
108
+
109
+ def _require_string_enum(payload: dict[str, Any], key: str, allowed: set[str], issues: list[dict[str, Any]], prefix: str = "$") -> None:
110
+ value = payload.get(key)
111
+ if value not in allowed:
112
+ issues.append(_issue("INVALID_VALUE", f"{prefix}.{key}", f"{key} must be one of {sorted(allowed)}"))
113
+
114
+
115
+ def _issue(code: str, path: str, message: str) -> dict[str, Any]:
116
+ return {"code": code, "path": path, "message": message}
117
+
118
+
119
+ def _emit(payload: dict[str, Any]) -> None:
120
+ print(json.dumps(payload, ensure_ascii=False, indent=2))
121
+
122
+
123
+ if __name__ == "__main__":
124
+ sys.exit(main())
@@ -1,12 +1,14 @@
1
1
  ---
2
2
  name: qingflow-app-builder-code-integrations
3
- description: Configure Qingflow code block and Q-Linker fields through the builder surface when the task involves input field insertion, alias parsing, target field binding, or troubleshooting broken code/q-linker form configurations. Use after MCP is connected and authenticated, especially for CRM-style scoring, lookup, and enrichment forms.
3
+ description: Configure Qingflow code block and Q-Linker fields through the builder surface when the task involves input field insertion, alias parsing, target field binding, or troubleshooting broken code/q-linker form configurations. In Wingent Momo runtime, use the injected MCP session and recover auth/workspace only after a tool error.
4
4
  metadata:
5
5
  short-description: Configure Qingflow code blocks and Q-Linkers safely
6
6
  ---
7
7
 
8
8
  # Qingflow App Builder Code Integrations
9
9
 
10
+ > **Skill 版本**:`qingflow-skills-2026.06.24.2`(入口文档版本;如需确认 CLI 包版本,使用 `qingflow --version` 或 `qingflow --json version`)。
11
+
10
12
  Use this skill when the user wants to build or repair:
11
13
  - `code_block` fields
12
14
  - `q_linker` fields
@@ -58,7 +60,7 @@ For code block or Q-Linker work, use this order:
58
60
 
59
61
  1. Resolve the app and read fields:
60
62
  - `app_resolve`
61
- - `app_read_fields`
63
+ - `app_get_fields`
62
64
  2. Confirm the target field set already exists.
63
65
  3. Apply schema updates with `app_schema_apply`.
64
66
  4. Read fields again and verify:
@@ -115,7 +117,7 @@ Hard rules:
115
117
 
116
118
  After each code block or Q-Linker change, verify all of these:
117
119
 
118
- - `app_read_fields` shows the intended field type
120
+ - `app_get_fields` shows the intended field type
119
121
  - the high-level config is readable and stable
120
122
  - target fields still have valid types
121
123
  - insert schema can be opened
@@ -59,7 +59,7 @@ Do not bind code block outputs to:
59
59
 
60
60
  ## Safe Verification
61
61
 
62
- - `app_read_fields`
62
+ - `app_get_fields`
63
63
  - `record_insert_schema_get`
64
64
  - optional `record_code_block_run`
65
65
 
@@ -70,7 +70,7 @@ Avoid:
70
70
 
71
71
  ## Safe Verification
72
72
 
73
- - `app_read_fields`
73
+ - `app_get_fields`
74
74
  - `record_insert_schema_get`
75
75
  - `record_insert`
76
76
 
@@ -7,6 +7,8 @@ metadata:
7
7
 
8
8
  # Qingflow MCP Setup
9
9
 
10
+ > **Skill 版本**:`qingflow-skills-2026.06.24.2`(入口文档版本;如需确认 CLI 包版本,使用 `qingflow --version` 或 `qingflow --json version`)。
11
+
10
12
  ## Overview
11
13
 
12
14
  This skill sets up the local Qingflow MCP server, connects it to a local AI client, and verifies authentication and workspace selection. Use it for installation, client configuration, token login, and connection troubleshooting.
@@ -73,24 +75,26 @@ cd <repo_root>/qingflow-support/mcp-server
73
75
 
74
76
  Prefer validating through the client after config is added.
75
77
 
76
- ### Step 5: Authenticate and select workspace
78
+ ### Step 5: Use injected session first; authenticate only for setup or recovery
79
+
80
+ For Wingent Momo runtime conversations, the session normally already carries the credential-derived token, workspace, and route context. Do not run `auth_use_credential`, `auth_login`, `workspace_list`, or `workspace_select` before ordinary business tools. Start with the smallest read-only business call that fits the task; if it succeeds, continue.
77
81
 
78
- Recommended order inside the client:
82
+ For a standalone local MCP client that has no injected session, use this setup order:
79
83
 
80
- 1. `auth_use_token` or `auth_login`
84
+ 1. `auth_use_credential` or `auth_login`
81
85
  2. `workspace_list`
82
86
  3. `workspace_select`
83
- 4. Only then use business tools
87
+ 4. Run a small read-only business tool
84
88
 
85
- If the user already knows the target workspace, prefer `auth_use_token(..., ws_id=<id>)`.
89
+ `auth_use_credential` gets the selected workspace from the credential context. If the user needs a different workspace after authentication, use `workspace_list` and then `workspace_select`.
86
90
  After auth, prefer one read-only tool call that returns `request_route` so you can confirm the live `base_url` and `qf_version` before proceeding.
87
- `auth_use_token` is a tool call, not a custom HTTP header. The runtime injects `token`, `wsId`, and when needed `Cookie: qfVersion=...` after the session is established.
88
- Do not skip `workspace_select` on production paths. If `/user` does not return a version lane, the session now falls back to the workspace `systemVersion`.
91
+ `auth_use_credential` is a tool call, not a custom HTTP header. It exchanges the createClaw credential for a Qingflow token, `wsId`, and when needed `Cookie: qfVersion=...` after the session is established.
92
+ Do not run `workspace_select` on production paths unless the user explicitly asks to switch workspace or a business tool clearly reports that no workspace is selected. If `/user` does not return a version lane, the session now falls back to the workspace `systemVersion`.
89
93
 
90
94
  ### Step 6: Troubleshoot in the right layer
91
95
 
92
96
  - If the client cannot launch the server, check path, execute permission, and `.venv`
93
- - If tools return `auth required`, re-run `auth_use_token` or `auth_login`
97
+ - If tools return `auth required`, re-run `auth_use_credential` or `auth_login`
94
98
  - If tools return `workspace not selected`, call `workspace_list` and `workspace_select`
95
99
  - If calls fail after a working session, assume token expiry and re-authenticate
96
100
  - If the browser shows data but MCP does not, compare `request_route` against the browser environment and check whether `qf_version` should be `canary`
@@ -98,7 +102,7 @@ Do not skip `workspace_select` on production paths. If `/user` does not return a
98
102
  ## Guardrails
99
103
 
100
104
  - Never write tokens into the skill files
101
- - Never assume a workspace is selected until `auth_whoami` or `workspace_select` confirms it
105
+ - In Wingent Momo runtime, trust injected workspace context until a business tool proves otherwise; for standalone clients, confirm workspace with `auth_whoami`, `workspace_select`, or a successful read-only business call.
102
106
  - When debugging, distinguish server startup issues from Qingflow auth issues
103
107
  - When the user mentions production, restate the exact `base_url`, `qf_version`, and workspace before any live validation
104
108
  - If setup is complete but the current MCP capability is still unsupported or the user's need still cannot be satisfied, summarize the gap, ask whether to submit feedback, and call `feedback_submit` only after explicit user confirmation
@@ -31,4 +31,4 @@ Keep separate snippets for `test` and `prod` so switching environments does not
31
31
  - Replace `<ABSOLUTE_PATH_TO_REPO>` with the real checkout path on the current machine
32
32
  - If the server path changes, update the `command` field
33
33
  - The server is local stdio MCP, so no remote URL is required
34
- - Do not store Qingflow token in Claude Desktop config; pass it through `auth_use_token` inside the chat
34
+ - Do not store Qingflow credentials in Claude Desktop config; pass the createClaw credential through `auth_use_credential` inside the chat, or use `auth_login` when credential exchange is unavailable
@@ -28,7 +28,8 @@ Known values in the current workspace:
28
28
  Setup behavior:
29
29
 
30
30
  - prefer this environment for Claude Desktop or local MCP client onboarding
31
- - use `auth_use_token` or `auth_login`, then `workspace_list`, then `workspace_select`
31
+ - for Wingent Momo runtime, use the injected session and skip auth/workspace preflight
32
+ - for standalone MCP client setup, use `auth_use_credential` or `auth_login`, then `workspace_list`, then `workspace_select`
32
33
  - if the user asks to verify installation, a real read-only smoke path is acceptable
33
34
 
34
35
  ## Production Environment
@@ -19,13 +19,14 @@ Keep separate client entries or separate config snippets for `test` and `prod`.
19
19
 
20
20
  1. Start the client
21
21
  2. Confirm the `qingflow` MCP server is visible
22
- 3. Run `auth_use_token`
23
- 4. Run `workspace_list`
24
- 5. Run `workspace_select`
25
- 6. Run a read-only tool such as `app_list`
22
+ 3. In Wingent Momo runtime, skip auth/workspace preflight and run a read-only tool such as `app_list`
23
+ 4. In a standalone client without injected credentials, run `auth_use_credential` or `auth_login`
24
+ 5. Then run `workspace_list`
25
+ 6. Then run `workspace_select`
26
+ 7. Run a read-only tool such as `app_list`
26
27
 
27
28
  ## Common failures
28
29
 
29
30
  - Launch failure: bad `command` path or missing `.venv`
30
- - Auth failure: invalid or expired token
31
+ - Auth failure: invalid or expired credential/token
31
32
  - Business tool failure before setup: workspace not selected
@@ -8,6 +8,8 @@ description: |
8
8
 
9
9
  # 轻流工作流搭建 Skill
10
10
 
11
+ > **Skill 版本**:`qingflow-skills-2026.06.24.2`(入口文档版本;如需确认 CLI 包版本,使用 `qingflow --version` 或 `qingflow --json version`)。
12
+
11
13
  ## 快速索引
12
14
 
13
15
  | 主题 | 文件 |
@@ -17,8 +19,8 @@ description: |
17
19
  | 流程模式速查(线性/分支/回退) | [references/03-flow-patterns.md](references/03-flow-patterns.md) |
18
20
  | 阶段 1:业务建模与自检 | [references/04-stage1-business-modeling.md](references/04-stage1-business-modeling.md) |
19
21
  | 阶段 2:成员/角色搜索 | [references/05-stage2-members-roles.md](references/05-stage2-members-roles.md) |
20
- | 阶段 3:Schema + 构建 Spec | [references/06-stage3-build-spec.md](references/06-stage3-build-spec.md) |
21
- | 阶段 4:验证 Spec | [references/07-stage4-validate-spec.md](references/07-stage4-validate-spec.md) |
22
+ | 阶段 3:Schema + 构建流程输入 | [references/06-stage3-build-spec.md](references/06-stage3-build-spec.md) |
23
+ | 阶段 4:验证流程输入 | [references/07-stage4-validate-spec.md](references/07-stage4-validate-spec.md) |
22
24
  | 阶段 5:Apply + 验证循环 | [references/08-stage5-apply-verify.md](references/08-stage5-apply-verify.md) |
23
25
  | 阶段 6:总结报告与回退 | [references/09-stage6-summary.md](references/09-stage6-summary.md) |
24
26
  | 节点配置参考 | [references/10-node-config-reference.md](references/10-node-config-reference.md) |
@@ -56,8 +58,8 @@ description: |
56
58
  | 在范围内 | 超出范围 |
57
59
  |----------|----------|
58
60
  | 基于已有应用搭建工作流 | 从零创建应用 |
59
- | 声明式 WorkflowSpec 生成与 apply | 操作复杂命令拼接 |
60
- | 分支条件(gateway + autoJudges)配置 | 后端不支持的高级特性 |
61
+ | WorkflowSpec 生成与 apply;`patch_nodes` 局部修改;public nodes/transitions 仅作简单线性兼容 | 操作复杂命令拼接 |
62
+ | 审批/填写/抄送/自动化/分支条件等 WorkflowSpec 支持的流程 | 不读 schema/spec 就猜 raw 后端字段 |
61
63
  | 审批/填写/抄送/自动化节点配置 | 修改字段定义 |
62
64
  | 成员/角色搜索用于节点负责人 | 组织架构管理 |
63
65
  | 验证 → apply → 校验循环 | 前端 UI 拖拽操作 |
@@ -76,11 +78,11 @@ description: |
76
78
  | 阶段 0 | 判断是否为更新模式,确认最小修改原则 | [references/02-update-mode.md](references/02-update-mode.md) |
77
79
  | 阶段 1 | 提取业务建模,完成七维度业务自检 | [references/04-stage1-business-modeling.md](references/04-stage1-business-modeling.md) |
78
80
  | 阶段 2 | 搜索成员/角色,用于节点负责人配置 | [references/05-stage2-members-roles.md](references/05-stage2-members-roles.md) |
79
- | 阶段 3 | 获取 Schema、读取现有 Spec、构建新 Spec | [references/06-stage3-build-spec.md](references/06-stage3-build-spec.md) |
80
- | 阶段 4 | 验证 Spec(JSON Schema + 自定义约束) | [references/07-stage4-validate-spec.md](references/07-stage4-validate-spec.md) |
81
+ | 阶段 3 | 获取 Schema、读取现有流程、构建 WorkflowSpec patch_nodes | [references/06-stage3-build-spec.md](references/06-stage3-build-spec.md) |
82
+ | 阶段 4 | 验证 WorkflowSpec / patch_nodes;简单线性兼容输入由 CLI 校验 | [references/07-stage4-validate-spec.md](references/07-stage4-validate-spec.md) |
81
83
  | 阶段 5 | Apply 工作流并验证部署结果 | [references/08-stage5-apply-verify.md](references/08-stage5-apply-verify.md) |
82
84
 
83
- 构建 Spec 前,若对流程模式有疑问,先查阅 [references/03-flow-patterns.md](references/03-flow-patterns.md)。
85
+ 构建流程输入前,若对流程模式有疑问,先查阅 [references/03-flow-patterns.md](references/03-flow-patterns.md)。
84
86
 
85
87
  ---
86
88
 
@@ -20,6 +20,8 @@
20
20
  | `qingflow builder flow schema --json` | 获取最新 WorkflowSpecDTO JSON Schema |
21
21
  | `qingflow builder flow get --app-key <KEY>` | 读取当前工作流 spec |
22
22
  | `qingflow builder flow apply --app-key <KEY> --spec-file <FILE>` | 部署/更新工作流 |
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 工作流 |
23
25
  | `qingflow builder member search --query <关键词>` | 搜索成员 |
24
26
  | `qingflow builder role search --keyword <关键词>` | 搜索角色 |
25
27
  | `qingflow --json app get --app-key <KEY>` | 获取应用信息(字段列表等) |
@@ -33,8 +35,8 @@
33
35
  | 在范围内 | 超出范围 |
34
36
  |----------|----------|
35
37
  | 基于已有应用搭建工作流 | 从零创建应用 |
36
- | 声明式 WorkflowSpec 生成与 apply | 操作复杂命令拼接 |
37
- | 分支条件(gateway + autoJudges)配置 | 后端不支持的高级特性 |
38
+ | WorkflowSpec 生成与 apply;public nodes/transitions 兼容简单线性流程 | 操作复杂命令拼接 |
39
+ | 审批/填写/抄送/分支条件等 WorkflowSpec 支持的流程 | 不读 schema/spec 就猜 raw 后端字段 |
38
40
  | 审批/填写/抄送/自动化节点配置 | 修改字段定义 |
39
41
  | 成员/角色搜索用于节点负责人 | 组织架构管理 |
40
42
  | 验证 → apply → 校验循环 | 前端 UI 拖拽操作 |
@@ -16,6 +16,8 @@ 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。
20
+
19
21
  轻流的分支采用**并行分支**模型——通过 `gateway` 节点(`mode: parallel`)分发,所有出边指向的分支**都会进入**,通过每条边上的条件(`condition.autoJudges`)控制分支内的节点逻辑是否执行。
20
22
 
21
23
  ```
@@ -1,4 +1,4 @@
1
- # 阶段 3:获取 Schema + 构建 Spec
1
+ # 阶段 3:获取 Schema + 构建流程输入
2
2
 
3
3
  ## 3.1 获取当前工作流 Schema
4
4
 
@@ -16,7 +16,7 @@ qingflow --json builder flow get --app-key <APP_KEY> > tmp/current_flow.json
16
16
 
17
17
  从返回的 `spec` 中提取 `nodes` 和 `edges` 作为修改基础。
18
18
 
19
- **更新模式下**:构建新 spec 后,用 diff 脚本确认变更范围是否符合预期:
19
+ **更新模式下**:如果走 `patch_nodes[]`,直接使用读回的 `spec.nodes[].id` 做局部修改;如果提交完整 `--spec-file`,用 diff 脚本确认变更范围是否符合预期:
20
20
 
21
21
  ```bash
22
22
  python3 scripts/diff_flow_spec.py tmp/current_flow.json tmp/flow_spec.json
@@ -24,9 +24,45 @@ python3 scripts/diff_flow_spec.py tmp/current_flow.json tmp/flow_spec.json
24
24
 
25
25
  新建场景可跳过此步。
26
26
 
27
- ## 3.3 构建 WorkflowSpec
27
+ ## 3.3 兼容:构建 public nodes / transitions(仅简单线性)
28
28
 
29
- 按照以下结构构建 `spec.json`:
29
+ 完整流程主链路是 `WorkflowSpec --spec-file` 或现有流程的 `patch_nodes`。只有明确是简单线性审批/填写/抄送流程时,才继续写两个 public alias 数组文件:
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`。
64
+
65
+ WorkflowSpec 示例:
30
66
 
31
67
  ```json
32
68
  {
@@ -116,7 +152,7 @@ python3 scripts/diff_flow_spec.py tmp/current_flow.json tmp/flow_spec.json
116
152
  }
117
153
  ```
118
154
 
119
- ## 节点类型速查
155
+ ## WorkflowSpec 节点类型速查
120
156
 
121
157
  | type | 说明 | 必要 attrs |
122
158
  |------|------|-----------|
@@ -129,6 +165,8 @@ python3 scripts/diff_flow_spec.py tmp/current_flow.json tmp/flow_spec.json
129
165
 
130
166
  ## 边条件体系
131
167
 
168
+ 本节属于 `--spec-file` WorkflowSpec 路径。不要凭记忆手写 `autoJudges`、`judgeType` 或 raw `fieldId` 条件;先读 `builder flow schema` / `builder flow get`,再按读回结构修改。简单线性兼容链路才使用 `builder flow apply --nodes-file --transitions-file`。
169
+
132
170
  | condition.kind | 含义 | 要求 |
133
171
  |---------------|------|------|
134
172
  | `rules` | 条件选路 | 必须含 `autoJudges`(OR-of-AND 二维数组) |
@@ -154,9 +192,23 @@ OR-of-AND 二维数组:
154
192
 
155
193
  **judgeType 常用值**:`equals`, `not_equals`, `equals_any`, `includes`, `greater_than` 等(共21种,详见 schema)。
156
194
 
157
- ## 3.4 保存 Spec 到文件
195
+ ## 3.5 局部修改 patch_nodes
196
+
197
+ 局部修改现有流程时,先 `builder flow get`,使用读回 `spec.nodes[].id`:
158
198
 
159
- 将构建好的完整 Spec 以 JSON 格式保存到文件 `tmp/flow_spec.json`,确保使用 UTF-8 编码、缩进格式化,以便后续验证和 apply 使用。
199
+ ```json
200
+ [
201
+ {"id": "89160906", "set": {"name": "需求评审(局部改)"}}
202
+ ]
203
+ ```
204
+
205
+ ```bash
206
+ qingflow --json builder flow apply \
207
+ --app-key <APP_KEY> \
208
+ --patch-nodes-file tmp/flow_patch_nodes.json \
209
+ --publish \
210
+ > tmp/flow_patch_apply.json
211
+ ```
160
212
 
161
213
  ---
162
214
 
@@ -1,13 +1,22 @@
1
- # 阶段 4:验证 Spec
1
+ # 阶段 4:验证流程输入
2
2
 
3
- 使用本 Skill 自带的验证脚本:
3
+ 主链路 `--spec-file` 使用本 Skill 自带的 WorkflowSpec 验证脚本;局部修改 `patch_nodes[]` 至少检查节点 id 来自 `builder flow get` 读回,且 `set/unset` 只包含要改的字段。
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
+ WorkflowSpec 验证命令:
4
13
 
5
14
  ```bash
6
- # 新建模式
15
+ # WorkflowSpec 新建模式
7
16
  python3 scripts/validate_flow_spec.py \
8
17
  tmp/flow_spec.json --schema tmp/flow_schema.json
9
18
 
10
- # 更新模式(同时校验最小修改原则)
19
+ # WorkflowSpec 更新模式(同时校验最小修改原则)
11
20
  python3 scripts/validate_flow_spec.py \
12
21
  tmp/flow_spec.json --schema tmp/flow_schema.json --previous tmp/current_flow.json
13
22
  ```
@@ -24,7 +33,7 @@ python3 scripts/validate_flow_spec.py \
24
33
 
25
34
  ## 验证不通过时的处理
26
35
 
27
- 根据错误信息修正 spec,重新验证,直到全部通过再进入 apply。
36
+ WorkflowSpec 根据验证脚本错误修正 spec,重新验证,直到全部通过再进入 apply。简单线性兼容输入根据 CLI 错误修正 nodes/transitions
28
37
 
29
38
  ---
30
39
 
@@ -2,11 +2,26 @@
2
2
 
3
3
  ## 5.1 部署工作流
4
4
 
5
+ 推荐主链路:
6
+
5
7
  ```bash
6
- qingflow builder flow apply \
8
+ qingflow --json builder flow apply \
7
9
  --app-key <APP_KEY> \
8
10
  --spec-file tmp/flow_spec.json \
9
- --publish
11
+ --publish \
12
+ > tmp/flow_apply.json
13
+ ```
14
+
15
+ 简单线性兼容流程仍可用 `--nodes-file + --transitions-file`;不要和 `--spec-file` / `--patch-nodes-file` 混用。
16
+
17
+ 局部修改已存在节点:
18
+
19
+ ```bash
20
+ qingflow --json builder flow apply \
21
+ --app-key <APP_KEY> \
22
+ --patch-nodes-file tmp/flow_patch_nodes.json \
23
+ --publish \
24
+ > tmp/flow_patch_apply.json
10
25
  ```
11
26
 
12
27
  ### 解读响应
@@ -14,6 +29,7 @@ qingflow builder flow apply \
14
29
  - `status: success` → 进入验证
15
30
  - `status: failed` → 查看 `error_code` / `message` / `blocking_issues`,修正后重试
16
31
  - `missing_input_node_ids` 警告(新建时常见)→ 可忽略,是正常现象
32
+ - 成功写入应读取 `write_executed=true`、`write_succeeded=true`、`safe_to_retry=false`;不要因中间读回 pending 立刻重放。
17
33
 
18
34
  ## 5.2 验证部署结果
19
35
 
@@ -25,7 +41,7 @@ qingflow --json builder flow get --app-key <APP_KEY> > tmp/deployed_flow.json
25
41
 
26
42
  1. **节点数量与类型**:`nodes` 数量是否一致,每个节点的 `type` 和 `name` 是否正确
27
43
  2. **边连通性**:`edges` 数量是否一致,`from`/`to` 关系是否正确
28
- 3. **分支条件**(核心关注点):每个 gateway 出边是否有正确的 `autoJudges`
44
+ 3. **分支条件**(WorkflowSpec 路径):每个 gateway 出边是否有正确的 `autoJudges`
29
45
  - 检查 `condition.kind` 是否为 `rules`
30
46
  - 检查 `autoJudges` 中的 `fieldId`、`judgeType`、`values` 是否正确
31
47
  - **`autoJudges` 必须是非空二维数组 `[[{...}]]`,空数组或一维数组说明条件未生效**
@@ -1,5 +1,7 @@
1
1
  # 常见问题与排障
2
2
 
3
+ `autoJudges` 属于 WorkflowSpec 路径。公开主链路是先读 `builder flow schema` / `builder flow get`,再提交 `--spec-file` 或 `--patch-nodes-file`;简单线性兼容链路 `nodes-file + transitions-file` 不要求智能体手写这些字段。
4
+
3
5
  | 问题 | 原因 | 解决 |
4
6
  |------|------|------|
5
7
  | `autoJudges` apply 后为空 | 使用了一维数组 `[{...}]` 格式 | 改为二维 `[[{...}]]` |
@@ -1,5 +1,9 @@
1
- """Entry point for running qingflow_mcp as a module."""
2
- from qingflow_mcp.server import main
1
+ """Entry point for running qingflow_mcp as a module.
2
+
3
+ Default to the curated user-facing MCP surface. Split package and console
4
+ entrypoints can still start the builder server explicitly.
5
+ """
6
+ from qingflow_mcp.server_app_user import main
3
7
 
4
8
  if __name__ == "__main__":
5
9
  main()