@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.
- package/README.md +6 -4
- package/docs/local-agent-install.md +57 -6
- package/entry_point.py +1 -1
- package/npm/bin/qingflow-app-builder-mcp.mjs +1 -1
- package/npm/bin/qingflow-skills.mjs +5 -0
- package/npm/lib/runtime.mjs +20 -59
- package/npm/scripts/postinstall.mjs +1 -10
- package/package.json +3 -2
- package/pyproject.toml +1 -1
- package/skills/qingflow-app-builder/SKILL.md +111 -55
- package/skills/qingflow-app-builder/references/complete-system-development-guide.md +169 -0
- package/skills/qingflow-app-builder/references/create-app.md +31 -24
- package/skills/qingflow-app-builder/references/environments.md +1 -1
- package/skills/qingflow-app-builder/references/gotchas.md +40 -14
- package/skills/qingflow-app-builder/references/match-rules.md +196 -85
- package/skills/qingflow-app-builder/references/public-surface-sync.md +2 -2
- package/skills/qingflow-app-builder/references/single-app-development-guide.md +84 -0
- package/skills/qingflow-app-builder/references/solution-playbooks.md +10 -0
- package/skills/qingflow-app-builder/references/tool-selection.md +40 -25
- package/skills/qingflow-app-builder/references/update-flow.md +27 -52
- package/skills/qingflow-app-builder/references/update-schema.md +14 -0
- package/skills/qingflow-app-builder/references/update-views.md +101 -32
- package/skills/qingflow-app-builder/scripts/validate_system_build_summary.py +124 -0
- package/skills/qingflow-app-builder-code-integrations/SKILL.md +5 -3
- package/skills/qingflow-app-builder-code-integrations/references/code-block.md +1 -1
- package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +1 -1
- package/skills/qingflow-mcp-setup/SKILL.md +13 -9
- package/skills/qingflow-mcp-setup/references/claude-desktop.md +1 -1
- package/skills/qingflow-mcp-setup/references/environments.md +2 -1
- package/skills/qingflow-mcp-setup/references/generic-stdio.md +6 -5
- package/skills/qingflow-workflow-builder/SKILL.md +9 -7
- package/skills/qingflow-workflow-builder/references/01-overview.md +4 -2
- package/skills/qingflow-workflow-builder/references/03-flow-patterns.md +2 -0
- package/skills/qingflow-workflow-builder/references/06-stage3-build-spec.md +59 -7
- package/skills/qingflow-workflow-builder/references/07-stage4-validate-spec.md +14 -5
- package/skills/qingflow-workflow-builder/references/08-stage5-apply-verify.md +19 -3
- package/skills/qingflow-workflow-builder/references/11-troubleshooting.md +2 -0
- package/src/qingflow_mcp/__main__.py +6 -2
- package/src/qingflow_mcp/builder_facade/models.py +473 -138
- package/src/qingflow_mcp/builder_facade/service.py +6356 -1866
- package/src/qingflow_mcp/cli/commands/builder.py +358 -355
- package/src/qingflow_mcp/cli/commands/chart.py +1 -1
- package/src/qingflow_mcp/cli/commands/common.py +12 -3
- package/src/qingflow_mcp/cli/commands/exports.py +2 -2
- package/src/qingflow_mcp/cli/commands/imports.py +3 -3
- package/src/qingflow_mcp/cli/commands/portal.py +2 -2
- package/src/qingflow_mcp/cli/commands/record.py +101 -27
- package/src/qingflow_mcp/cli/commands/task.py +28 -47
- package/src/qingflow_mcp/cli/commands/view.py +1 -1
- package/src/qingflow_mcp/cli/context.py +0 -3
- package/src/qingflow_mcp/cli/formatters.py +784 -16
- package/src/qingflow_mcp/cli/main.py +120 -41
- package/src/qingflow_mcp/errors.py +43 -2
- package/src/qingflow_mcp/public_surface.py +26 -17
- package/src/qingflow_mcp/response_trim.py +81 -17
- package/src/qingflow_mcp/server.py +14 -12
- package/src/qingflow_mcp/server_app_builder.py +83 -39
- package/src/qingflow_mcp/server_app_user.py +22 -16
- package/src/qingflow_mcp/session_store.py +11 -7
- package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
- package/src/qingflow_mcp/solution/executor.py +114 -15
- package/src/qingflow_mcp/tools/ai_builder_tools.py +3571 -1473
- package/src/qingflow_mcp/tools/app_tools.py +184 -43
- package/src/qingflow_mcp/tools/approval_tools.py +197 -35
- package/src/qingflow_mcp/tools/auth_tools.py +92 -16
- package/src/qingflow_mcp/tools/code_block_tools.py +298 -40
- package/src/qingflow_mcp/tools/custom_button_tools.py +64 -10
- package/src/qingflow_mcp/tools/directory_tools.py +236 -72
- package/src/qingflow_mcp/tools/export_tools.py +244 -34
- package/src/qingflow_mcp/tools/feedback_tools.py +9 -0
- package/src/qingflow_mcp/tools/file_tools.py +9 -3
- package/src/qingflow_mcp/tools/import_tools.py +336 -49
- package/src/qingflow_mcp/tools/navigation_tools.py +91 -12
- package/src/qingflow_mcp/tools/package_tools.py +118 -6
- package/src/qingflow_mcp/tools/portal_tools.py +39 -3
- package/src/qingflow_mcp/tools/qingbi_report_tools.py +116 -7
- package/src/qingflow_mcp/tools/record_tools.py +1141 -356
- package/src/qingflow_mcp/tools/resource_read_tools.py +188 -39
- package/src/qingflow_mcp/tools/role_tools.py +80 -9
- package/src/qingflow_mcp/tools/solution_tools.py +57 -15
- package/src/qingflow_mcp/tools/task_context_tools.py +687 -159
- package/src/qingflow_mcp/tools/task_tools.py +113 -29
- package/src/qingflow_mcp/tools/view_tools.py +106 -3
- package/src/qingflow_mcp/tools/workflow_tools.py +17 -1
- package/src/qingflow_mcp/tools/workspace_tools.py +71 -3
- package/src/qingflow_mcp/version.py +0 -2
- package/skills/qingflow-app-builder/references/build-complete-system.md +0 -234
- 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.
|
|
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
|
-
- `
|
|
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
|
-
- `
|
|
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
|
|
@@ -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:
|
|
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
|
-
|
|
82
|
+
For a standalone local MCP client that has no injected session, use this setup order:
|
|
79
83
|
|
|
80
|
-
1. `
|
|
84
|
+
1. `auth_use_credential` or `auth_login`
|
|
81
85
|
2. `workspace_list`
|
|
82
86
|
3. `workspace_select`
|
|
83
|
-
4.
|
|
87
|
+
4. Run a small read-only business tool
|
|
84
88
|
|
|
85
|
-
If the user
|
|
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
|
-
`
|
|
88
|
-
Do not
|
|
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 `
|
|
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
|
-
-
|
|
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
|
|
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
|
|
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.
|
|
23
|
-
4.
|
|
24
|
-
5.
|
|
25
|
-
6.
|
|
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 +
|
|
21
|
-
| 阶段 4
|
|
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
|
-
|
|
|
60
|
-
|
|
|
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
|
|
80
|
-
| 阶段 4 | 验证
|
|
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
|
-
|
|
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
|
-
|
|
|
37
|
-
|
|
|
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 +
|
|
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
|
-
|
|
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
|
|
27
|
+
## 3.3 兼容:构建 public nodes / transitions(仅简单线性)
|
|
28
28
|
|
|
29
|
-
|
|
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.
|
|
195
|
+
## 3.5 局部修改 patch_nodes
|
|
196
|
+
|
|
197
|
+
局部修改现有流程时,先 `builder flow get`,使用读回 `spec.nodes[].id`:
|
|
158
198
|
|
|
159
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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()
|