@qingflow-tech/qingflow-cli 1.1.50-beta.5 → 1.1.51

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 (110) hide show
  1. package/README.md +4 -4
  2. package/npm/lib/runtime.mjs +13 -29
  3. package/package.json +1 -1
  4. package/pyproject.toml +2 -8
  5. package/skills/qingflow-cli/SKILL.md +322 -93
  6. package/skills/qingflow-cli/manifest.yaml +1 -1
  7. package/skills/qingflow-cli/reference/00-INDEX.md +4 -4
  8. package/skills/qingflow-cli/reference/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +1 -1
  9. package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_VIEWS_WORKFLOW.md +9 -3
  10. package/skills/qingflow-cli/reference/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +137 -3
  11. package/skills/qingflow-cli/reference/QINGFLOW_CLI_EXPLORATION_REPORT.md +4 -6
  12. package/skills/qingflow-cli/reference/QINGFLOW_CLI_FIELD_DATA_TYPES.md +14 -14
  13. package/skills/qingflow-cli/reference/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +19 -20
  14. package/skills/qingflow-cli/reference/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +14 -18
  15. package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md +12 -7
  16. package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +1 -2
  17. package/skills/qingflow-cli/reference/builder/20-build-complete-system.md +2 -3
  18. package/skills/qingflow-cli/reference/builder/30-schema-fields.md +5 -9
  19. package/skills/qingflow-cli/reference/builder/50-views.md +191 -192
  20. package/skills/qingflow-cli/reference/builder/80-buttons-associated-resources.md +0 -2
  21. package/skills/qingflow-cli/reference/builder/README.md +1 -1
  22. package/skills/qingflow-cli/reference/builder/reference/app-delivery-sop.md +6 -6
  23. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +1 -1
  24. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +95 -76
  25. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_EXPLORATION_REPORT.md +4 -6
  26. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_FIELD_DATA_TYPES.md +13 -13
  27. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +19 -20
  28. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +14 -18
  29. package/skills/qingflow-cli/reference/examples/README.md +1 -1
  30. package/skills/qingflow-cli/reference/examples/views/views_batch_full.example.json +159 -0
  31. package/skills/qingflow-cli/reference/examples/views/views_upsert_table_minimal.example.json +36 -30
  32. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +1 -2
  33. package/skills/qingflow-cli/reference/record/analysis/README.md +113 -21
  34. package/skills/qingflow-cli/reference/record/analysis/analysis-gotchas.md +10 -10
  35. package/skills/qingflow-cli/reference/record/analysis/analysis-patterns.md +9 -9
  36. package/skills/qingflow-cli/reference/record/analysis/business-context.md +1 -1
  37. package/skills/qingflow-cli/reference/record/analysis/confidence-reporting.md +10 -10
  38. package/skills/qingflow-cli/reference/record/analysis/data-access-playbook.md +80 -52
  39. package/skills/qingflow-cli/reference/record/analysis/pandas-recipes.md +2 -2
  40. package/skills/qingflow-cli/reference/views_upsert_table_minimal.example.json +42 -0
  41. package/skills/qingflow-common/SKILL.md +4 -7
  42. package/src/qingflow_mcp/__init__.py +1 -1
  43. package/src/qingflow_mcp/app_form_compat.py +0 -3
  44. package/src/qingflow_mcp/app_form_validator.py +17 -69
  45. package/src/qingflow_mcp/builder_facade/app_form.py +100 -497
  46. package/src/qingflow_mcp/builder_facade/models.py +17 -227
  47. package/src/qingflow_mcp/builder_facade/schemas/app_form/manifest.json +0 -1
  48. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/complete.json +30 -64
  49. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/address.json +8 -4
  50. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/amount.json +8 -4
  51. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/attachment.json +10 -6
  52. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/code_block.json +10 -6
  53. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/data_relation.json +18 -11
  54. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/date.json +8 -4
  55. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/datetime.json +8 -4
  56. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/department.json +10 -6
  57. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/email.json +8 -4
  58. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/link.json +8 -4
  59. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/long_text.json +8 -4
  60. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/member.json +10 -6
  61. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/multi_select.json +8 -4
  62. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/number.json +8 -4
  63. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/phone.json +8 -4
  64. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/q_linker.json +10 -6
  65. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/relation.json +15 -46
  66. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_choice.json +8 -4
  67. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_select.json +8 -4
  68. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/subtable.json +27 -61
  69. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/text.json +8 -4
  70. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/formula.json +0 -43
  71. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/summary.json +12 -7
  72. package/src/qingflow_mcp/builder_facade/service.py +539 -1671
  73. package/src/qingflow_mcp/builder_facade/workflow_spec.py +1 -1
  74. package/src/qingflow_mcp/cli/commands/__init__.py +1 -2
  75. package/src/qingflow_mcp/cli/commands/builder.py +55 -76
  76. package/src/qingflow_mcp/cli/commands/record.py +1 -1
  77. package/src/qingflow_mcp/cli/context.py +0 -3
  78. package/src/qingflow_mcp/cli/formatters.py +1 -97
  79. package/src/qingflow_mcp/config.py +1 -0
  80. package/src/qingflow_mcp/public_surface.py +0 -8
  81. package/src/qingflow_mcp/response_trim.py +2 -11
  82. package/src/qingflow_mcp/server.py +0 -2
  83. package/src/qingflow_mcp/server_app_builder.py +10 -34
  84. package/src/qingflow_mcp/server_app_user.py +0 -4
  85. package/src/qingflow_mcp/solution/compiler/view_compiler.py +1 -2
  86. package/src/qingflow_mcp/solution/executor.py +8 -96
  87. package/src/qingflow_mcp/solution/spec_models.py +0 -1
  88. package/src/qingflow_mcp/tools/ai_builder_tools.py +398 -218
  89. package/src/qingflow_mcp/tools/base.py +42 -10
  90. package/src/qingflow_mcp/tools/record_tools.py +46 -11
  91. package/src/qingflow_mcp/tools/solution_tools.py +0 -2
  92. package/src/qingflow_mcp/tools/view_tools.py +6 -0
  93. package/skills/qingflow-cli/reference/data/README.md +0 -32
  94. package/skills/qingflow-cli/reference/examples/views/views_apply_v1alpha1.example.json +0 -14
  95. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_SPECIALIZED_WORKFLOW.md +0 -50
  96. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/rich_text.json +0 -146
  97. package/src/qingflow_mcp/builder_facade/schemas/views/manifest.json +0 -42
  98. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/complete.json +0 -1245
  99. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/button-config.json +0 -53
  100. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/data-permission.json +0 -60
  101. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/display.json +0 -73
  102. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/operation-permission.json +0 -48
  103. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/query-condition.json +0 -47
  104. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/summary.json +0 -319
  105. package/src/qingflow_mcp/builder_facade/views_extract.py +0 -592
  106. package/src/qingflow_mcp/builder_facade/views_schema.py +0 -400
  107. package/src/qingflow_mcp/cli/commands/data.py +0 -134
  108. package/src/qingflow_mcp/tools/csv_export.py +0 -168
  109. package/src/qingflow_mcp/tools/data_tools.py +0 -284
  110. package/src/qingflow_mcp/tools/view_writer.py +0 -44
@@ -36,7 +36,6 @@ class SolutionExecutor:
36
36
  app_tools: AppTools,
37
37
  record_tools: RecordTools,
38
38
  view_tools: ViewTools,
39
- view_writer: "ViewWriter | None" = None,
40
39
  chart_tools: QingbiReportTools,
41
40
  portal_tools: PortalTools,
42
41
  navigation_tools: NavigationTools,
@@ -48,7 +47,6 @@ class SolutionExecutor:
48
47
  self.app_tools = app_tools
49
48
  self.record_tools = record_tools
50
49
  self.view_tools = view_tools
51
- self.view_writer = view_writer
52
50
  self.chart_tools = chart_tools
53
51
  self.portal_tools = portal_tools
54
52
  self.navigation_tools = navigation_tools
@@ -462,20 +460,6 @@ class SolutionExecutor:
462
460
  "Pass {app_key, spec} to solution_build_flow or use qingflow builder flow apply."
463
461
  )
464
462
 
465
- def _create_view_via_writer(self, *, profile: str, payload: dict[str, Any]) -> dict[str, Any]:
466
- """视图创建唯一落点:共享 ViewWriter(POST /view/viewConfig)。
467
-
468
- solution DSL 内部创建路径不再直接调用 ViewTools.view_create(该方法已删除);
469
- 未注入 writer 的旧调用方退化为直接经 ViewTools 同一会话执行同一端点。
470
- """
471
- if self.view_writer is not None:
472
- return self.view_writer.create_view(profile=profile, payload=payload)
473
- from ..tools.view_writer import ViewWriter as _FallbackViewWriter
474
-
475
- return _FallbackViewWriter(self.view_tools.sessions, self.view_tools.backend).create_view(
476
- profile=profile, payload=payload
477
- )
478
-
479
463
  def _build_views(self, profile: str, entity: CompiledEntity, store: RunArtifactStore) -> None:
480
464
  app_key = self._get_app_key(store, entity.entity_id)
481
465
  field_meta = store.get_artifact("field_maps", entity.entity_id, {})
@@ -490,7 +474,7 @@ class SolutionExecutor:
490
474
  schema=schema,
491
475
  group_by_field_id=view_plan["group_by_field_id"],
492
476
  )
493
- result = self._create_view_via_writer(profile=profile, payload=create_payload)
477
+ result = self.view_tools.view_create(profile=profile, payload=create_payload)
494
478
  view_result = result.get("result")
495
479
  view_key = ((view_result or {}) if isinstance(view_result, dict) else {}).get("viewgraphKey")
496
480
  if not view_key and isinstance(view_result, str):
@@ -911,14 +895,13 @@ class SolutionExecutor:
911
895
  data.setdefault("asosChartConfig", {"limitType": 1, "asosChartIdList": []})
912
896
  data.setdefault("viewgraphGanttConfigVO", None)
913
897
  data.setdefault("viewgraphHierarchyConfigVO", None)
914
- data.setdefault("viewgraphCalendarConfigVO", None)
915
898
  data.setdefault("viewgraphLimitFormula", "")
916
899
  data.setdefault("buttonConfigDTOList", [])
917
900
  if not data.get("viewgraphQuestions"):
918
901
  data["viewgraphQuestions"] = _build_viewgraph_questions(schema, visible_que_ids)
919
902
  if not data.get("viewgraphSorts"):
920
903
  data["viewgraphSorts"] = [{"queId": 0, "beingSortAscend": True, "queType": 8}]
921
- if data.get("viewgraphType") in {"cardView", "boardView", "ganttView", "hierarchyView", "calendarView"}:
904
+ if data.get("viewgraphType") in {"cardView", "boardView", "ganttView", "hierarchyView"}:
922
905
  data["titleQue"] = visible_que_ids[0] if visible_que_ids else None
923
906
  else:
924
907
  data.setdefault("titleQue", None)
@@ -2235,7 +2218,6 @@ def _portal_view_type(store: RunArtifactStore, entity_id: str, view_id: str) ->
2235
2218
  "board": "boardView",
2236
2219
  "gantt": "ganttView",
2237
2220
  "hierarchy": "hierarchyView",
2238
- "calendar": "calendarView",
2239
2221
  }
2240
2222
  for entity in store.data.get("normalized_solution_spec", {}).get("entities", []):
2241
2223
  if entity["entity_id"] != entity_id:
@@ -2342,106 +2324,36 @@ def _resolve_package_item_insert_index(tag_items: list[dict[str, Any]], ordinal:
2342
2324
  return max(0, min(len(tag_items), ordinal - 1))
2343
2325
 
2344
2326
 
2345
- def _flatten_viewgraph_questions(entries: list[Any] | None) -> dict[int, dict[str, Any]]:
2346
- """把读面的 viewgraphQuestions(含 subQues/innerQues 嵌套)按 queId 展平。"""
2347
- flat: dict[int, dict[str, Any]] = {}
2348
-
2349
- def walk(entry: Any) -> None:
2350
- if not isinstance(entry, dict):
2351
- return
2352
- que_id = entry.get("queId")
2353
- if isinstance(que_id, int) and que_id not in flat:
2354
- flat[que_id] = entry
2355
- for key in ("subQues", "innerQues"):
2356
- for child in entry.get(key) or []:
2357
- if isinstance(child, list):
2358
- for inner in child:
2359
- walk(inner)
2360
- else:
2361
- walk(child)
2362
-
2363
- for entry in entries or []:
2364
- if isinstance(entry, list):
2365
- for inner in entry:
2366
- walk(inner)
2367
- else:
2368
- walk(entry)
2369
- return flat
2370
-
2371
-
2372
- def _build_viewgraph_questions(
2373
- schema: dict[str, Any],
2374
- visible_que_ids: list[int],
2375
- *,
2376
- existing_by_que_id: dict[int, dict[str, Any]] | None = None,
2377
- ) -> list[dict[str, Any]]:
2378
- """重建业务列行;更新时原样保留已配置的系统列。
2379
-
2380
- existing_by_que_id(读面展平行)存在时,以读面行为基底只更新可见性/序号——
2381
- 保留列级权限(queAuth/beingAddRow/beingDeleteRow/beingEditRow/beingDownload 等),
2382
- 否则重建会把这些标志归默认值,破坏既有列权限配置。
2383
- 系统列读面占位对象不写回;existing_by_que_id=None 表示新建。
2384
- """
2327
+ def _build_viewgraph_questions(schema: dict[str, Any], visible_que_ids: list[int]) -> list[dict[str, Any]]:
2385
2328
  visible_map = {que_id: index for index, que_id in enumerate(visible_que_ids, start=1)}
2386
- existing = existing_by_que_id or {}
2387
2329
  questions: list[dict[str, Any]] = []
2388
2330
  for base_question in schema.get("baseQues", []):
2389
- question = _build_viewgraph_question(base_question, visible_map, default_auth=3, existing=existing_by_que_id)
2331
+ question = _build_viewgraph_question(base_question, visible_map, default_auth=3)
2390
2332
  if question is not None:
2391
2333
  questions.append(question)
2392
2334
  for line in schema.get("formQues", []):
2393
2335
  for question in line:
2394
- resolved = _build_viewgraph_question(question, visible_map, default_auth=1, existing=existing_by_que_id)
2336
+ resolved = _build_viewgraph_question(question, visible_map, default_auth=1)
2395
2337
  if resolved is not None:
2396
2338
  questions.append(resolved)
2397
- # 某些系统列只在视图读面出现,不属于表单 schema。
2398
- emitted_que_ids = _flatten_viewgraph_questions(questions)
2399
- for que_id, prior in existing.items():
2400
- if que_id <= 5 and que_id not in emitted_que_ids:
2401
- preserved = _build_viewgraph_question(prior, visible_map, default_auth=3, existing=existing)
2402
- if preserved is not None:
2403
- questions.append(preserved)
2404
2339
  return questions
2405
2340
 
2406
2341
 
2407
- def _build_viewgraph_question(
2408
- question: dict[str, Any],
2409
- visible_map: dict[int, int],
2410
- *,
2411
- default_auth: int,
2412
- existing: dict[int, dict[str, Any]] | None = None,
2413
- ) -> dict[str, Any] | None:
2342
+ def _build_viewgraph_question(question: dict[str, Any], visible_map: dict[int, int], *, default_auth: int) -> dict[str, Any] | None:
2414
2343
  que_id = question.get("queId")
2415
2344
  if que_id is None:
2416
2345
  return None
2417
- if isinstance(que_id, int) and que_id <= 5 and existing is not None:
2418
- prior = existing.get(que_id)
2419
- # 后端会生成未落库的系统字段占位对象;只有落库配置才带这些列状态。
2420
- if prior is None or all(prior.get(key) is None for key in (
2421
- "beingListDisplay", "displayOrdinal", "beingAddRow", "beingEditRow", "beingDeleteRow",
2422
- )):
2423
- return None
2424
- return deepcopy(prior)
2425
2346
  sub_questions = [
2426
2347
  resolved
2427
2348
  for sub_question in question.get("subQuestions", []) or []
2428
- if (resolved := _build_viewgraph_question(sub_question, visible_map, default_auth=1, existing=existing)) is not None
2349
+ if (resolved := _build_viewgraph_question(sub_question, visible_map, default_auth=1)) is not None
2429
2350
  ]
2430
2351
  inner_questions = [
2431
2352
  resolved
2432
2353
  for inner_row in question.get("innerQuestions", []) or []
2433
2354
  for inner_question in inner_row or []
2434
- if (resolved := _build_viewgraph_question(inner_question, visible_map, default_auth=1, existing=existing)) is not None
2355
+ if (resolved := _build_viewgraph_question(inner_question, visible_map, default_auth=1)) is not None
2435
2356
  ]
2436
- prior = (existing or {}).get(que_id) if isinstance(que_id, int) else None
2437
- if prior is not None:
2438
- # 读面行为基底:保留全部列级标志,只更新可见性/序号;嵌套子项同样融合
2439
- merged = deepcopy(prior)
2440
- merged["beingListDisplay"] = que_id in visible_map
2441
- merged["displayOrdinal"] = visible_map.get(que_id, -1)
2442
- merged["subQues"] = sub_questions
2443
- merged["innerQues"] = inner_questions
2444
- return merged
2445
2357
  return {
2446
2358
  "queId": que_id,
2447
2359
  "queTitle": question.get("queTitle"),
@@ -56,7 +56,6 @@ class ViewType(str, Enum):
56
56
  board = "board"
57
57
  gantt = "gantt"
58
58
  hierarchy = "hierarchy"
59
- calendar = "calendar"
60
59
 
61
60
 
62
61
  class ChartType(str, Enum):