@josephyan/qingflow-app-user-mcp 1.1.26 → 1.1.28

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 (47) hide show
  1. package/README.md +4 -6
  2. package/package.json +1 -1
  3. package/pyproject.toml +1 -1
  4. package/skills/qingflow-app-user/SKILL.md +5 -3
  5. package/skills/qingflow-app-user/references/public-surface-sync.md +4 -2
  6. package/src/qingflow_mcp/builder_facade/models.py +167 -71
  7. package/src/qingflow_mcp/builder_facade/service.py +617 -155
  8. package/src/qingflow_mcp/cli/commands/builder.py +3 -1
  9. package/src/qingflow_mcp/cli/main.py +8 -3
  10. package/src/qingflow_mcp/server_app_builder.py +9 -8
  11. package/src/qingflow_mcp/tools/ai_builder_tools.py +231 -180
  12. package/src/qingflow_mcp/version.py +2 -0
  13. package/skills/qingflow-app-builder/SKILL.md +0 -277
  14. package/skills/qingflow-app-builder/agents/openai.yaml +0 -4
  15. package/skills/qingflow-app-builder/references/build-complete-system.md +0 -428
  16. package/skills/qingflow-app-builder/references/build-single-app.md +0 -530
  17. package/skills/qingflow-app-builder/references/create-app.md +0 -149
  18. package/skills/qingflow-app-builder/references/environments.md +0 -63
  19. package/skills/qingflow-app-builder/references/flow-actors-and-permissions.md +0 -123
  20. package/skills/qingflow-app-builder/references/gotchas.md +0 -108
  21. package/skills/qingflow-app-builder/references/match-rules.md +0 -114
  22. package/skills/qingflow-app-builder/references/public-surface-sync.md +0 -75
  23. package/skills/qingflow-app-builder/references/solution-playbooks.md +0 -52
  24. package/skills/qingflow-app-builder/references/tool-selection.md +0 -107
  25. package/skills/qingflow-app-builder/references/update-flow.md +0 -186
  26. package/skills/qingflow-app-builder/references/update-layout.md +0 -68
  27. package/skills/qingflow-app-builder/references/update-schema.md +0 -72
  28. package/skills/qingflow-app-builder/references/update-views.md +0 -291
  29. package/skills/qingflow-app-builder-code-integrations/SKILL.md +0 -137
  30. package/skills/qingflow-app-builder-code-integrations/agents/openai.yaml +0 -4
  31. package/skills/qingflow-app-builder-code-integrations/references/code-block.md +0 -66
  32. package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +0 -77
  33. package/skills/qingflow-workflow-builder/SKILL.md +0 -96
  34. package/skills/qingflow-workflow-builder/manifest.yaml +0 -8
  35. package/skills/qingflow-workflow-builder/references/01-overview.md +0 -45
  36. package/skills/qingflow-workflow-builder/references/02-update-mode.md +0 -53
  37. package/skills/qingflow-workflow-builder/references/03-flow-patterns.md +0 -57
  38. package/skills/qingflow-workflow-builder/references/04-stage1-business-modeling.md +0 -131
  39. package/skills/qingflow-workflow-builder/references/05-stage2-members-roles.md +0 -29
  40. package/skills/qingflow-workflow-builder/references/06-stage3-build-spec.md +0 -165
  41. package/skills/qingflow-workflow-builder/references/07-stage4-validate-spec.md +0 -33
  42. package/skills/qingflow-workflow-builder/references/08-stage5-apply-verify.md +0 -51
  43. package/skills/qingflow-workflow-builder/references/09-stage6-summary.md +0 -88
  44. package/skills/qingflow-workflow-builder/references/10-node-config-reference.md +0 -93
  45. package/skills/qingflow-workflow-builder/references/11-troubleshooting.md +0 -15
  46. package/skills/qingflow-workflow-builder/scripts/diff_flow_spec.py +0 -275
  47. package/skills/qingflow-workflow-builder/scripts/validate_flow_spec.py +0 -605
@@ -295,6 +295,7 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) ->
295
295
  schema_apply_apply.add_argument("--add-fields-file", help="字段 JSON 数组;字段可用 as_data_title/as_data_cover 标记数据标题/封面")
296
296
  schema_apply_apply.add_argument("--update-fields-file", help="字段更新 JSON 数组;set 内可用 as_data_title/as_data_cover 标记数据标题/封面")
297
297
  schema_apply_apply.add_argument("--remove-fields-file")
298
+ schema_apply_apply.add_argument("--form-file", help='表单布局 JSON 对象,例如 {"sections": [{"title": "基础信息", "rows": [["字段A"]]}]}')
298
299
  schema_apply_apply.set_defaults(handler=_handle_schema_apply, format_hint="builder_summary", force_json_output=True)
299
300
 
300
301
  layout_apply = builder_subparsers.add_parser("layout", help="布局")
@@ -686,7 +687,7 @@ def _handle_schema_apply(args: argparse.Namespace, context: CliContext) -> dict:
686
687
  "schema apply multi-app mode requires a non-empty --apps-file.",
687
688
  fix_hint='Pass {"package_id": 123, "apps": [{"client_key": "main", "app_name": "主表", "icon": "database", "color": "blue", "add_fields": []}]}',
688
689
  )
689
- if args.app_key or args.app_name or args.app_title or args.add_fields_file or args.update_fields_file or args.remove_fields_file:
690
+ if args.app_key or args.app_name or args.app_title or args.add_fields_file or args.update_fields_file or args.remove_fields_file or args.form_file:
690
691
  raise_config_error(
691
692
  "schema apply multi-app mode accepts --package-id/--create-if-missing plus --apps-file only.",
692
693
  fix_hint="Use `--apps-file` for batch mode, or remove `--apps-file` and use the single-app arguments.",
@@ -737,6 +738,7 @@ def _handle_schema_apply(args: argparse.Namespace, context: CliContext) -> dict:
737
738
  add_fields=load_list_arg(args.add_fields_file, option_name="--add-fields-file"),
738
739
  update_fields=load_list_arg(args.update_fields_file, option_name="--update-fields-file"),
739
740
  remove_fields=load_list_arg(args.remove_fields_file, option_name="--remove-fields-file"),
741
+ form=load_object_arg(args.form_file, option_name="--form-file"),
740
742
  )
741
743
 
742
744
 
@@ -12,7 +12,6 @@ from ..tools.ai_builder_tools import _attach_builder_apply_envelope
12
12
  from ..version import get_cli_version, get_cli_version_info
13
13
  from .context import CliContext, build_cli_context
14
14
  from .formatters import emit_json_result, emit_text_result
15
- from .commands import register_all_commands
16
15
 
17
16
 
18
17
  Handler = Callable[[argparse.Namespace, CliContext], dict[str, Any]]
@@ -32,6 +31,8 @@ class _QingflowArgumentParser(argparse.ArgumentParser):
32
31
 
33
32
 
34
33
  def build_parser() -> argparse.ArgumentParser:
34
+ from .commands import register_all_commands
35
+
35
36
  parser = _QingflowArgumentParser(prog="qingflow", description="Qingflow CLI")
36
37
  parser.add_argument("--profile", default="default", help="会话 profile,默认 default")
37
38
  parser.add_argument("--json", action="store_true", help="输出 JSON")
@@ -56,10 +57,10 @@ def run(
56
57
  ) -> int:
57
58
  out = stdout or sys.stdout
58
59
  err = stderr or sys.stderr
59
- parser = build_parser()
60
60
  normalized_argv = _normalize_global_args(list(argv) if argv is not None else sys.argv[1:])
61
- if "--version" in normalized_argv:
61
+ if _is_version_argv(normalized_argv):
62
62
  return _emit_version(json_mode=_should_force_json_output_argv_for_version(normalized_argv), stdout=out)
63
+ parser = build_parser()
63
64
  try:
64
65
  args = parser.parse_args(normalized_argv)
65
66
  except _CliArgumentError as exc:
@@ -179,6 +180,10 @@ def _should_force_json_output_argv_for_version(argv: list[str]) -> bool:
179
180
  return "--json" in argv
180
181
 
181
182
 
183
+ def _is_version_argv(argv: list[str]) -> bool:
184
+ return "--version" in argv or [token for token in argv if token != "--json"] == ["version"]
185
+
186
+
182
187
  def _should_force_json_output(args: argparse.Namespace) -> bool:
183
188
  if bool(getattr(args, "force_json_output", False)):
184
189
  return True
@@ -39,14 +39,13 @@ def build_builder_server() -> FastMCP:
39
39
  "Use workspace_icon_catalog_get before creating app packages, apps, or portals when supported icon/color candidates are needed; new workspace resources require explicit non-template icon + color, and the CLI validates choices without inferring business defaults. "
40
40
  "app_get as the default app map read, then app_get_fields/app_repair_code_blocks/app_get_layout/app_get_views/app_get_flow/app_flow_get/app_flow_get_schema/app_get_charts/portal_list/portal_get/view_get/chart_get for focused configuration reads, "
41
41
  "member_search/role_search/role_create when workflow assignees must come from the directory or role catalog, preferring roles over explicit members unless the user explicitly names members, "
42
- "then app_schema_apply/app_layout_apply/app_flow_apply/app_views_apply/app_custom_buttons_apply/app_associated_resources_apply/app_charts_apply/portal_apply to execute normalized patches; these apply tools perform planning, normalization, and dependency checks internally where applicable. Schema/layout/views noop requests skip publish, app_custom_buttons_apply and app_associated_resources_apply publish after at least one write succeeds and expose no draft-only parameter, charts are immediate-live without publish and resolve targets by chart_id first then exact unique chart name, portal sections should use chart for QingBI blocks so portal_apply can inline create/update app-source charts before saving the portal, portal updates use replace semantics only when sections are supplied and edit-mode base-info-only updates may omit sections, portal pc layout is a 24-column grid and mobile is a 6-column grid so omit position or use layout_preset when unsure, publish=false only guarantees draft/base-info updates for tools that still expose that parameter, and flow should use publish=false whenever you only want draft/precheck behavior. "
42
+ "then app_schema_apply/app_layout_apply/app_flow_apply/app_views_apply/app_associated_resources_apply/app_charts_apply/portal_apply to execute normalized patches; these apply tools perform planning, normalization, and dependency checks internally where applicable. For normal app/system delivery, put new app fields, same-batch relations, and form layout in app_schema_apply apps[].form.sections; use app_layout_apply only for later layout-only maintenance. Schema/layout/views noop requests skip publish, app_associated_resources_apply publishes after at least one write succeeds and exposes no draft-only parameter, charts are immediate-live without publish and resolve targets by chart_id first then exact unique chart name, portal sections should use chart for QingBI blocks so portal_apply can inline create/update app-source charts before saving the portal, portal updates use replace semantics only when sections are supplied and edit-mode base-info-only updates may omit sections, portal pc layout is a 24-column grid and mobile is a 6-column grid so omit position or use layout_preset when unsure, publish=false only guarantees draft/base-info updates for tools that still expose that parameter, and flow should use publish=false whenever you only want draft/precheck behavior. "
43
43
  "Builder apply/write outputs include schema_version, operation, summary, and resources[]; use resources[].id/key/name/ids/parent as the stable UI and agent display entry, and keep legacy fields such as field_diff/views_diff/chart_results only for compatibility or troubleshooting. "
44
- "For existing object parameter replacement, prefer patch_views, patch_buttons, patch_resources, and patch_charts with set/unset; the tool reads current config and full-saves internally, while upsert_* is for creation or full target configuration and should not be used as an incomplete partial update. "
44
+ "For existing object parameter replacement, prefer patch_views, patch_resources, and patch_charts with set/unset; the tool reads current config and full-saves internally, while upsert_* is for creation or full target configuration and should not be used as an incomplete partial update. "
45
45
  "For builder delete/remove apply results, separate delete execution from readback verification: after DELETE is sent, resources expose delete_executed, readback_status, and safe_to_retry_delete=false. If readback_status is unavailable or still_exists, do not blindly repeat the delete; confirm later with app_get/view_get/chart_get or the relevant apply readback. Views/buttons use single-item readback; associated resources use one app-level resource-pool readback because there is no confirmed single-item GET. "
46
- "For app_schema_apply, configure data title and data cover directly in field JSON with as_data_title=true and as_data_cover=true; data title is required and exactly one field may be marked, while data cover is optional and must be a top-level attachment field. For multi-app creation, pass apps[]/--apps-file on app_schema_apply; each item may have client_key, and relation fields may use target_app_ref to point at another same-call client_key. "
47
- "For app_views_apply, keep fixed saved filters in filters and configure the frontend query panel separately with query_conditions; query_conditions.rows is a matrix of field names compiled to backend queryCondition queIds. New views default associated report/view display to visible with limit_type=all; existing views preserve their current associated display unless associated_resources is explicitly patched. "
48
- "For custom button body create/update/delete and view placement, use app_custom_buttons_apply. For addData buttons, prefer trigger_add_data_config.target_app_key + field_mappings/default_values; do not ask agents to write raw que_relation unless maintaining a legacy config. field_mappings.source_field accepts source schema fields and supported system fields: 数据ID/row_record_id/apply_id/_id means current record id (-17), 编号/record_number means visible record number (0). To fill a target relation with the current record, map {'source_field': '数据ID', 'target_field': '目标引用字段'}; default_values is only for static constants. View button bindings merge by default and merge-mode view_configs must include buttons; use view_configs[].mode=replace or explicit buttons=[] only when clearing/replacing existing bindings is intended. Builder view_key arguments are raw keys from app_get.views[].view_key and must not be prefixed with custom:. "
49
- "For portal BI blocks, prefer portal_apply sections[].chart so the portal write can inline create/update app-source QingBI charts and attach the resulting chart_id. Use app_charts_apply for advanced standalone report maintenance such as batch edits, deletes, or reordering; chart dimension/metric/filter/query fields must come from app_get_fields.chart_fields, not record schema or form-only fields; dataset BI reports are not created or edited by app_charts_apply yet and should be created in QingBI first, then attached with app_associated_resources_apply using report_source=dataset. "
46
+ "For app_schema_apply, configure data title and data cover directly in field JSON with as_data_title=true and as_data_cover=true; data title is required and exactly one field may be marked, while data cover is optional and must be a top-level attachment field. For multi-app creation, pass apps[]/--apps-file on app_schema_apply; each item may have client_key and form.sections, and relation fields may use target_app_ref to point at another same-call client_key. "
47
+ "For app_views_apply, keep fixed saved filters in filters and configure the frontend query panel separately with query_conditions; query_conditions.rows is a matrix of field names compiled to backend queryCondition queIds. If a view needs business actions, declare them directly in action_buttons on that view; field_mappings.source_field accepts source schema fields and supported system fields: 数据ID/row_record_id/apply_id/_id means current record id (-17), 编号/record_number means visible record number (0). New views default associated report/view display to visible with limit_type=all; existing views preserve their current associated display unless associated_resources is explicitly patched. Builder view_key arguments are raw keys from app_get.views[].view_key and must not be prefixed with custom:. "
48
+ "For portal BI blocks, prefer portal_apply sections[].chart so the portal write can inline create/update app-source QingBI charts and attach the resulting chart_id; chart dimension/metric/filter/query fields must come from app_get_fields.chart_fields, not record schema or form-only fields. Use app_charts_apply only when the user explicitly asks for standalone chart maintenance such as batch edits, deletes, or reordering; dataset BI reports are not created or edited by app_charts_apply yet and should be created in QingBI first, then attached with app_associated_resources_apply using report_source=dataset. "
50
49
  "For associated views/reports, use app_associated_resources_apply. Use match_mappings for filtering associated resources: dynamic current-record conditions use source_field, static conditions use value. match_mappings also supports 数据ID(-17) and 编号(0). Do not ask agents to write raw match_rules unless preserving a legacy backend config. "
51
50
  "For associated reports/views, use app_associated_resources_apply for both the app-level associated_resources pool and per-view display config; associated_item_id is the app-level form_asos_chart.id, and view_configs/remove/reorder may also pass an existing resource's chart_id/chart_key/view_key because the tool resolves those to the internal id. Before creating an associated resource, read app_get.associated_resources and reuse an existing matching target_app_key + view_key/chart_key through patch_resources; client_key only works inside one apply call and is not persisted. Do not ask agents to pass backend raw sourceType: views infer the internal Qingflow view source, reports default to BI app reports, and dataset reports use report_source=dataset. "
52
51
  "For code_block fields with output bindings, always use qf_output assignment rather than const/let qf_output, and use app_repair_code_blocks when an existing form hangs because output-bound fields stay loading. "
@@ -418,13 +417,14 @@ def build_builder_server() -> FastMCP:
418
417
  add_fields: list[dict] | None = None,
419
418
  update_fields: list[dict] | None = None,
420
419
  remove_fields: list[dict] | None = None,
420
+ form: dict | None = None,
421
421
  apps: list[dict] | None = None,
422
422
  ) -> dict:
423
423
  if apps:
424
- if app_key or app_name or app_title or add_fields or update_fields or remove_fields:
424
+ if app_key or app_name or app_title or add_fields or update_fields or remove_fields or form:
425
425
  return _config_failure(
426
426
  "app_schema_apply multi-app mode accepts package_id/create_if_missing plus apps only.",
427
- fix_hint="Use `apps` for batch mode, or use the single-app arguments without `apps`.",
427
+ fix_hint="Use `apps[].form` for batch mode, or use the single-app arguments including `form` without `apps`.",
428
428
  )
429
429
  if package_id is None:
430
430
  return _config_failure(
@@ -471,6 +471,7 @@ def build_builder_server() -> FastMCP:
471
471
  add_fields=add_fields or [],
472
472
  update_fields=update_fields or [],
473
473
  remove_fields=remove_fields or [],
474
+ form=form,
474
475
  apps=[],
475
476
  )
476
477