@josephyan/qingflow-app-builder-mcp 1.1.4 → 1.1.6

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 (98) hide show
  1. package/README.md +6 -5
  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 +2 -33
  5. package/npm/bin/qingflow-skills.mjs +5 -0
  6. package/npm/lib/runtime.mjs +21 -101
  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 +51 -34
  11. package/skills/qingflow-app-builder/references/complete-system-development-guide.md +123 -0
  12. package/skills/qingflow-app-builder/references/create-app.md +19 -6
  13. package/skills/qingflow-app-builder/references/environments.md +1 -1
  14. package/skills/qingflow-app-builder/references/gotchas.md +14 -6
  15. package/skills/qingflow-app-builder/references/match-rules.md +15 -0
  16. package/skills/qingflow-app-builder/references/single-app-development-guide.md +58 -0
  17. package/skills/qingflow-app-builder/references/solution-playbooks.md +10 -0
  18. package/skills/qingflow-app-builder/references/tool-selection.md +21 -22
  19. package/skills/qingflow-app-builder/references/update-flow.md +22 -38
  20. package/skills/qingflow-app-builder/references/update-schema.md +3 -0
  21. package/skills/qingflow-app-builder/references/update-views.md +34 -14
  22. package/skills/qingflow-app-builder/scripts/validate_system_build_summary.py +124 -0
  23. package/skills/qingflow-app-builder-code-integrations/SKILL.md +5 -3
  24. package/skills/qingflow-app-builder-code-integrations/references/code-block.md +1 -1
  25. package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +1 -1
  26. package/src/qingflow_mcp/__init__.py +1 -1
  27. package/src/qingflow_mcp/__main__.py +6 -2
  28. package/src/qingflow_mcp/builder_facade/models.py +282 -102
  29. package/src/qingflow_mcp/builder_facade/service.py +4192 -935
  30. package/src/qingflow_mcp/cli/commands/builder.py +316 -298
  31. package/src/qingflow_mcp/cli/commands/chart.py +1 -1
  32. package/src/qingflow_mcp/cli/commands/common.py +12 -3
  33. package/src/qingflow_mcp/cli/commands/exports.py +2 -2
  34. package/src/qingflow_mcp/cli/commands/imports.py +3 -3
  35. package/src/qingflow_mcp/cli/commands/portal.py +2 -2
  36. package/src/qingflow_mcp/cli/commands/record.py +101 -27
  37. package/src/qingflow_mcp/cli/commands/task.py +28 -47
  38. package/src/qingflow_mcp/cli/commands/view.py +1 -1
  39. package/src/qingflow_mcp/cli/context.py +0 -3
  40. package/src/qingflow_mcp/cli/formatters.py +784 -16
  41. package/src/qingflow_mcp/cli/main.py +117 -33
  42. package/src/qingflow_mcp/errors.py +43 -2
  43. package/src/qingflow_mcp/public_surface.py +26 -17
  44. package/src/qingflow_mcp/response_trim.py +81 -17
  45. package/src/qingflow_mcp/server.py +14 -12
  46. package/src/qingflow_mcp/server_app_builder.py +65 -21
  47. package/src/qingflow_mcp/server_app_user.py +22 -16
  48. package/src/qingflow_mcp/session_store.py +11 -7
  49. package/src/qingflow_mcp/solution/compiler/__init__.py +3 -1
  50. package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
  51. package/src/qingflow_mcp/solution/executor.py +245 -18
  52. package/src/qingflow_mcp/tools/ai_builder_tools.py +1780 -406
  53. package/src/qingflow_mcp/tools/app_tools.py +184 -43
  54. package/src/qingflow_mcp/tools/approval_tools.py +197 -35
  55. package/src/qingflow_mcp/tools/auth_tools.py +92 -16
  56. package/src/qingflow_mcp/tools/code_block_tools.py +298 -40
  57. package/src/qingflow_mcp/tools/custom_button_tools.py +64 -10
  58. package/src/qingflow_mcp/tools/directory_tools.py +236 -72
  59. package/src/qingflow_mcp/tools/export_tools.py +244 -34
  60. package/src/qingflow_mcp/tools/feedback_tools.py +9 -0
  61. package/src/qingflow_mcp/tools/file_tools.py +9 -3
  62. package/src/qingflow_mcp/tools/import_tools.py +336 -49
  63. package/src/qingflow_mcp/tools/navigation_tools.py +91 -12
  64. package/src/qingflow_mcp/tools/package_tools.py +118 -6
  65. package/src/qingflow_mcp/tools/portal_tools.py +39 -3
  66. package/src/qingflow_mcp/tools/qingbi_report_tools.py +116 -7
  67. package/src/qingflow_mcp/tools/record_tools.py +1141 -356
  68. package/src/qingflow_mcp/tools/resource_read_tools.py +188 -39
  69. package/src/qingflow_mcp/tools/role_tools.py +80 -9
  70. package/src/qingflow_mcp/tools/solution_tools.py +59 -45
  71. package/src/qingflow_mcp/tools/task_context_tools.py +662 -158
  72. package/src/qingflow_mcp/tools/task_tools.py +113 -29
  73. package/src/qingflow_mcp/tools/view_tools.py +106 -3
  74. package/src/qingflow_mcp/tools/workflow_tools.py +48 -4
  75. package/src/qingflow_mcp/tools/workspace_tools.py +71 -3
  76. package/skills/qingflow-app-builder/references/build-complete-system.md +0 -428
  77. package/skills/qingflow-app-builder/references/build-single-app.md +0 -530
  78. package/skills/qingflow-mcp-setup/SKILL.md +0 -111
  79. package/skills/qingflow-mcp-setup/agents/openai.yaml +0 -4
  80. package/skills/qingflow-mcp-setup/references/claude-desktop.md +0 -34
  81. package/skills/qingflow-mcp-setup/references/environments.md +0 -61
  82. package/skills/qingflow-mcp-setup/references/generic-stdio.md +0 -31
  83. package/skills/qingflow-mcp-setup/scripts/check_local_server.sh +0 -38
  84. package/skills/qingflow-workflow-builder/SKILL.md +0 -96
  85. package/skills/qingflow-workflow-builder/manifest.yaml +0 -8
  86. package/skills/qingflow-workflow-builder/references/01-overview.md +0 -45
  87. package/skills/qingflow-workflow-builder/references/02-update-mode.md +0 -53
  88. package/skills/qingflow-workflow-builder/references/03-flow-patterns.md +0 -57
  89. package/skills/qingflow-workflow-builder/references/04-stage1-business-modeling.md +0 -131
  90. package/skills/qingflow-workflow-builder/references/05-stage2-members-roles.md +0 -29
  91. package/skills/qingflow-workflow-builder/references/06-stage3-build-spec.md +0 -165
  92. package/skills/qingflow-workflow-builder/references/07-stage4-validate-spec.md +0 -33
  93. package/skills/qingflow-workflow-builder/references/08-stage5-apply-verify.md +0 -51
  94. package/skills/qingflow-workflow-builder/references/09-stage6-summary.md +0 -88
  95. package/skills/qingflow-workflow-builder/references/10-node-config-reference.md +0 -93
  96. package/skills/qingflow-workflow-builder/references/11-troubleshooting.md +0 -15
  97. package/skills/qingflow-workflow-builder/scripts/diff_flow_spec.py +0 -275
  98. package/skills/qingflow-workflow-builder/scripts/validate_flow_spec.py +0 -605
@@ -1,275 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- 对比两个工作流 spec 的差异,输出新增/删除/修改的节点和边。
4
- 用于更新模式下辅助 agent 判断是否遵循最小修改原则。
5
-
6
- 用法:
7
- python3 diff_flow_spec.py <old_spec.json> <new_spec.json>
8
- python3 diff_flow_spec.py <old_spec.json> <new_spec.json> --json # JSON 输出
9
- """
10
-
11
- import json
12
- import sys
13
-
14
-
15
- def load_json(path):
16
- with open(path, 'r', encoding='utf-8') as f:
17
- return json.load(f)
18
-
19
-
20
- def extract_edges(spec):
21
- """从 spec 中提取边列表,兼容 edges 在不同层级的情况"""
22
- e = spec.get('edges', [])
23
- if isinstance(e, dict) and 'edges' in e:
24
- return e['edges']
25
- if isinstance(e, list):
26
- return e
27
- return []
28
-
29
-
30
- def node_key(n):
31
- """节点的唯一标识"""
32
- return n.get('id', '')
33
-
34
-
35
- def edge_key(e):
36
- """边的唯一标识:from→to"""
37
- return (e.get('from', ''), e.get('to', ''))
38
-
39
-
40
- def node_identity(n):
41
- """节点的完整内容(不含 id,用于判断是否修改)"""
42
- return {
43
- 'type': n.get('type', ''),
44
- 'name': n.get('name', ''),
45
- 'attrs': n.get('attrs', {}),
46
- }
47
-
48
-
49
- def edge_identity(e):
50
- """边的完整内容(不含 from/to,用于判断是否修改)"""
51
- return {
52
- 'label': e.get('label', ''),
53
- 'condition': e.get('condition', {}),
54
- }
55
-
56
-
57
- def diff_nodes(old_nodes, new_nodes):
58
- """对比节点差异"""
59
- old_by_id = {node_key(n): n for n in old_nodes}
60
- new_by_id = {node_key(n): n for n in new_nodes}
61
-
62
- old_ids = set(old_by_id.keys())
63
- new_ids = set(new_by_id.keys())
64
-
65
- deleted_ids = sorted(old_ids - new_ids)
66
- added_ids = sorted(new_ids - old_ids)
67
- common_ids = sorted(old_ids & new_ids)
68
-
69
- modified = []
70
- id_changes = []
71
- for nid in common_ids:
72
- old_ident = node_identity(old_by_id[nid])
73
- new_ident = node_identity(new_by_id[nid])
74
- if old_ident != new_ident:
75
- modified.append({
76
- 'id': nid,
77
- 'old': {'type': old_ident['type'], 'name': old_ident['name']},
78
- 'new': {'type': new_ident['type'], 'name': new_ident['name']},
79
- 'attrs_changed': old_ident['attrs'] != new_ident['attrs'],
80
- 'type_changed': old_ident['type'] != new_ident['type'],
81
- 'name_changed': old_ident['name'] != new_ident['name'],
82
- })
83
-
84
- # 检测可能的不必要 ID 变更(内容相同但 ID 不同)
85
- old_by_identity = {}
86
- for n in old_nodes:
87
- ident = json.dumps(node_identity(n), sort_keys=True, ensure_ascii=False)
88
- old_by_identity.setdefault(ident, []).append(n)
89
-
90
- for n in new_nodes:
91
- if node_key(n) in added_ids:
92
- ident = json.dumps(node_identity(n), sort_keys=True, ensure_ascii=False)
93
- if ident in old_by_identity and old_by_identity[ident]:
94
- old_match = old_by_identity[ident][0]
95
- if node_key(old_match) in deleted_ids:
96
- id_changes.append({
97
- 'old_id': node_key(old_match),
98
- 'new_id': node_key(n),
99
- 'identity': node_identity(n),
100
- 'warning': '节点内容未变但 ID 已变更,可能导致后端不支持配置丢失',
101
- })
102
-
103
- return {
104
- 'deleted': [{'id': nid, 'name': old_by_id[nid].get('name', ''), 'type': old_by_id[nid].get('type', '')} for nid in deleted_ids],
105
- 'added': [{'id': nid, 'name': new_by_id[nid].get('name', ''), 'type': new_by_id[nid].get('type', '')} for nid in added_ids],
106
- 'modified': modified,
107
- 'id_changes': id_changes,
108
- 'unchanged': len(common_ids) - len(modified),
109
- }
110
-
111
-
112
- def diff_edges(old_edges, new_edges):
113
- """对比边差异"""
114
- old_by_key = {edge_key(e): e for e in old_edges}
115
- new_by_key = {edge_key(e): e for e in new_edges}
116
-
117
- old_keys = set(old_by_key.keys())
118
- new_keys = set(new_by_key.keys())
119
-
120
- deleted_keys = sorted(old_keys - new_keys)
121
- added_keys = sorted(new_keys - old_keys)
122
- common_keys = sorted(old_keys & new_keys)
123
-
124
- modified = []
125
- for key in common_keys:
126
- old_ident = edge_identity(old_by_key[key])
127
- new_ident = edge_identity(new_by_key[key])
128
- if old_ident != new_ident:
129
- modified.append({
130
- 'from': key[0],
131
- 'to': key[1],
132
- 'old_condition': old_ident['condition'],
133
- 'new_condition': new_ident['condition'],
134
- 'label_changed': old_ident['label'] != new_ident['label'],
135
- 'condition_changed': old_ident['condition'] != new_ident['condition'],
136
- })
137
-
138
- return {
139
- 'deleted': [{'from': k[0], 'to': k[1]} for k in deleted_keys],
140
- 'added': [{'from': k[0], 'to': k[1]} for k in added_keys],
141
- 'modified': modified,
142
- 'unchanged': len(common_keys) - len(modified),
143
- }
144
-
145
-
146
- def print_human(result):
147
- """人类可读输出"""
148
- nodes = result['nodes']
149
- edges = result['edges']
150
-
151
- print("=" * 60)
152
- print("工作流 Spec 差异分析")
153
- print("=" * 60)
154
-
155
- # 节点汇总
156
- print(f"\n📊 节点汇总:")
157
- print(f" 删除: {len(nodes['deleted'])} | 新增: {len(nodes['added'])} | "
158
- f"修改: {len(nodes['modified'])} | 未变: {nodes['unchanged']}")
159
-
160
- if nodes['id_changes']:
161
- print(f"\n⚠️ 检测到 {len(nodes['id_changes'])} 个可能的 ID 变更(内容相同但 ID 不同):")
162
- for ic in nodes['id_changes']:
163
- print(f" {ic['old_id']} → {ic['new_id']} ({ic['identity']['name']})")
164
- print(f" ⚠ {ic['warning']}")
165
-
166
- if nodes['deleted']:
167
- print(f"\n🗑 删除的节点 ({len(nodes['deleted'])}):")
168
- for d in nodes['deleted']:
169
- print(f" - [{d['type']}] {d['id']} ({d['name']})")
170
-
171
- if nodes['added']:
172
- print(f"\n➕ 新增的节点 ({len(nodes['added'])}):")
173
- for a in nodes['added']:
174
- print(f" - [{a['type']}] {a['id']} ({a['name']})")
175
-
176
- if nodes['modified']:
177
- print(f"\n✏️ 修改的节点 ({len(nodes['modified'])}):")
178
- for m in nodes['modified']:
179
- changes = []
180
- if m['type_changed']:
181
- changes.append(f"type: {m['old']['type']} → {m['new']['type']}")
182
- if m['name_changed']:
183
- changes.append(f"name: {m['old']['name']} → {m['new']['name']}")
184
- if m['attrs_changed']:
185
- changes.append("attrs 已变更")
186
- print(f" - {m['id']}: {', '.join(changes) if changes else '无实质变更'}")
187
-
188
- # 边汇总
189
- print(f"\n📊 边汇总:")
190
- print(f" 删除: {len(edges['deleted'])} | 新增: {len(edges['added'])} | "
191
- f"修改: {len(edges['modified'])} | 未变: {edges['unchanged']}")
192
-
193
- if edges['deleted']:
194
- print(f"\n🗑 删除的边 ({len(edges['deleted'])}):")
195
- for d in edges['deleted']:
196
- print(f" - {d['from']} → {d['to']}")
197
-
198
- if edges['added']:
199
- print(f"\n➕ 新增的边 ({len(edges['added'])}):")
200
- for a in edges['added']:
201
- print(f" - {a['from']} → {a['to']}")
202
-
203
- if edges['modified']:
204
- print(f"\n✏️ 修改的边 ({len(edges['modified'])}):")
205
- for m in edges['modified']:
206
- changes = []
207
- if m['label_changed']:
208
- changes.append("label 已变更")
209
- if m['condition_changed']:
210
- changes.append("condition 已变更")
211
- if changes:
212
- print(f" - {m['from']} → {m['to']}: {', '.join(changes)}")
213
- else:
214
- print(f" - {m['from']} → {m['to']}: 无实质变更")
215
-
216
- # 最小修改原则评估
217
- print(f"\n📋 最小修改原则评估:")
218
- issues = 0
219
- if nodes['id_changes']:
220
- print(f" ❌ 存在 ID 变更({len(nodes['id_changes'])} 个节点),可能导致后端不支持配置丢失")
221
- issues += 1
222
- if nodes['deleted']:
223
- print(f" ⚠️ 删除了 {len(nodes['deleted'])} 个节点,请确认是否为业务需要")
224
- issues += 1
225
- if not nodes['deleted'] and not nodes['id_changes'] and nodes['modified']:
226
- print(f" ✅ 仅修改已有节点,未删除或变更 ID,符合最小修改原则")
227
- if not nodes['deleted'] and not nodes['modified'] and not nodes['added'] and not nodes['id_changes']:
228
- print(f" ✅ 无任何变更")
229
-
230
- print(f"\n总结: 错误 {issues} 项")
231
-
232
-
233
- def main():
234
- if len(sys.argv) < 3:
235
- print("用法: python3 diff_flow_spec.py <old_spec.json> <new_spec.json> [--json]")
236
- sys.exit(1)
237
-
238
- old_file = sys.argv[1]
239
- new_file = sys.argv[2]
240
- output_json = '--json' in sys.argv
241
-
242
- try:
243
- old_spec = load_json(old_file)
244
- except Exception as e:
245
- print(f"FATAL: 无法读取旧 spec 文件 {old_file}: {e}")
246
- sys.exit(1)
247
-
248
- try:
249
- new_spec = load_json(new_file)
250
- except Exception as e:
251
- print(f"FATAL: 无法读取新 spec 文件 {new_file}: {e}")
252
- sys.exit(1)
253
-
254
- old_nodes = old_spec.get('nodes', [])
255
- new_nodes = new_spec.get('nodes', [])
256
- old_edges = extract_edges(old_spec)
257
- new_edges = extract_edges(new_spec)
258
-
259
- result = {
260
- 'nodes': diff_nodes(old_nodes, new_nodes),
261
- 'edges': diff_edges(old_edges, new_edges),
262
- }
263
-
264
- if output_json:
265
- print(json.dumps(result, indent=2, ensure_ascii=False))
266
- else:
267
- print_human(result)
268
-
269
- # 如果有 ID 变更,返回非零以便脚本判断
270
- has_id_changes = len(result['nodes']['id_changes']) > 0
271
- sys.exit(1 if has_id_changes else 0)
272
-
273
-
274
- if __name__ == '__main__':
275
- main()