@qingflow-tech/qingflow-app-user-mcp 1.0.3 → 1.0.5

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 (52) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/pyproject.toml +2 -1
  4. package/skills/qingflow-app-user/SKILL.md +2 -1
  5. package/skills/qingflow-app-user/references/data-gotchas.md +5 -2
  6. package/skills/qingflow-app-user/references/public-surface-sync.md +5 -3
  7. package/skills/qingflow-app-user/references/record-patterns.md +9 -0
  8. package/skills/qingflow-record-analysis/SKILL.md +103 -166
  9. package/skills/qingflow-record-analysis/agents/openai.yaml +2 -2
  10. package/skills/qingflow-record-analysis/references/analysis-gotchas.md +56 -110
  11. package/skills/qingflow-record-analysis/references/analysis-patterns.md +106 -119
  12. package/skills/qingflow-record-analysis/references/business-context.md +74 -0
  13. package/skills/qingflow-record-analysis/references/confidence-reporting.md +49 -72
  14. package/skills/qingflow-record-analysis/references/data-access-playbook.md +106 -0
  15. package/skills/qingflow-record-analysis/references/pandas-recipes.md +172 -0
  16. package/skills/qingflow-record-analysis/references/report-format.md +76 -0
  17. package/skills/qingflow-record-insert/SKILL.md +2 -2
  18. package/skills/qingflow-record-update/SKILL.md +1 -1
  19. package/src/qingflow_mcp/__init__.py +1 -1
  20. package/src/qingflow_mcp/backend_client.py +164 -1
  21. package/src/qingflow_mcp/builder_facade/button_style_catalog.py +282 -0
  22. package/src/qingflow_mcp/builder_facade/models.py +44 -5
  23. package/src/qingflow_mcp/builder_facade/service.py +21 -8
  24. package/src/qingflow_mcp/cli/commands/__init__.py +2 -1
  25. package/src/qingflow_mcp/cli/commands/app.py +47 -1
  26. package/src/qingflow_mcp/cli/commands/builder.py +7 -0
  27. package/src/qingflow_mcp/cli/commands/exports.py +111 -0
  28. package/src/qingflow_mcp/cli/commands/record.py +44 -5
  29. package/src/qingflow_mcp/cli/commands/task.py +644 -22
  30. package/src/qingflow_mcp/cli/commands/workspace.py +64 -2
  31. package/src/qingflow_mcp/cli/context.py +3 -0
  32. package/src/qingflow_mcp/cli/formatters.py +240 -5
  33. package/src/qingflow_mcp/cli/interaction.py +72 -0
  34. package/src/qingflow_mcp/cli/main.py +5 -0
  35. package/src/qingflow_mcp/cli/terminal_ui.py +218 -0
  36. package/src/qingflow_mcp/errors.py +2 -2
  37. package/src/qingflow_mcp/export_store.py +14 -0
  38. package/src/qingflow_mcp/public_surface.py +7 -1
  39. package/src/qingflow_mcp/response_trim.py +188 -10
  40. package/src/qingflow_mcp/server.py +37 -9
  41. package/src/qingflow_mcp/server_app_builder.py +4 -0
  42. package/src/qingflow_mcp/server_app_user.py +115 -10
  43. package/src/qingflow_mcp/session_store.py +57 -6
  44. package/src/qingflow_mcp/tools/ai_builder_tools.py +59 -16
  45. package/src/qingflow_mcp/tools/auth_tools.py +26 -0
  46. package/src/qingflow_mcp/tools/custom_button_tools.py +0 -2
  47. package/src/qingflow_mcp/tools/export_tools.py +1565 -0
  48. package/src/qingflow_mcp/tools/import_tools.py +42 -2
  49. package/src/qingflow_mcp/tools/record_tools.py +12793 -8612
  50. package/src/qingflow_mcp/tools/resource_read_tools.py +40 -1
  51. package/src/qingflow_mcp/tools/task_context_tools.py +26 -8
  52. package/skills/qingflow-record-analysis/references/dsl-templates.md +0 -93
@@ -10,7 +10,11 @@ from .common import load_list_arg, load_object_arg, raise_config_error, require_
10
10
 
11
11
  def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
12
12
  parser = subparsers.add_parser("record", help="记录与表结构")
13
- record_subparsers = parser.add_subparsers(dest="record_command", required=True)
13
+ record_subparsers = parser.add_subparsers(
14
+ dest="record_command",
15
+ required=True,
16
+ metavar="{schema,list,access,get,insert,update,delete,code-block-run}",
17
+ )
14
18
 
15
19
  schema = record_subparsers.add_parser("schema", help="读取记录相关表结构")
16
20
  schema.add_argument("--mode", dest="legacy_mode", help=argparse.SUPPRESS)
@@ -47,9 +51,11 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) ->
47
51
  list_parser.add_argument("--app-key", required=True)
48
52
  list_parser.add_argument("--column", dest="columns", action="append", type=int, default=[])
49
53
  list_parser.add_argument("--columns-file")
54
+ list_parser.add_argument("--query")
55
+ list_parser.add_argument("--query-field", dest="query_fields", action="append", type=int, default=[])
56
+ list_parser.add_argument("--query-fields-file")
50
57
  list_parser.add_argument("--where-file")
51
58
  list_parser.add_argument("--order-by-file")
52
- list_parser.add_argument("--limit", type=int, default=20)
53
59
  list_parser.add_argument("--page", type=int, default=1)
54
60
  list_parser.add_argument("--view-id")
55
61
  list_parser.add_argument("--list-type", dest="legacy_list_type", type=int, help=argparse.SUPPRESS)
@@ -57,13 +63,22 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) ->
57
63
  list_parser.add_argument("--view-name", dest="legacy_view_name", help=argparse.SUPPRESS)
58
64
  list_parser.set_defaults(handler=_handle_list, format_hint="record_list")
59
65
 
66
+ access_parser = record_subparsers.add_parser("access", help="访问记录并写入本地 CSV 分片")
67
+ access_parser.add_argument("--app-key", required=True)
68
+ access_parser.add_argument("--column", dest="columns", action="append", type=int, default=[])
69
+ access_parser.add_argument("--columns-file")
70
+ access_parser.add_argument("--where-file")
71
+ access_parser.add_argument("--order-by-file")
72
+ access_parser.add_argument("--view-id", required=True)
73
+ access_parser.set_defaults(handler=_handle_access, format_hint="record_access")
74
+
60
75
  get = record_subparsers.add_parser("get", help="读取单条记录")
61
76
  get.add_argument("--app-key", required=True)
62
77
  get.add_argument("--record-id", required=True)
63
78
  get.add_argument("--column", dest="columns", action="append", type=int, default=[])
64
79
  get.add_argument("--columns-file")
65
80
  get.add_argument("--view-id")
66
- get.set_defaults(handler=_handle_get, format_hint="")
81
+ get.set_defaults(handler=_handle_get, format_hint="record_get")
67
82
 
68
83
  insert = record_subparsers.add_parser("insert", help="新增记录")
69
84
  insert.add_argument("--app-key", required=True)
@@ -86,7 +101,12 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) ->
86
101
  delete.add_argument("--record-ids-file")
87
102
  delete.set_defaults(handler=_handle_delete, format_hint="")
88
103
 
89
- analyze = record_subparsers.add_parser("analyze", help="分析记录数据")
104
+ analyze = record_subparsers.add_parser("analyze", help=argparse.SUPPRESS)
105
+ record_subparsers._choices_actions = [ # type: ignore[attr-defined]
106
+ action
107
+ for action in record_subparsers._choices_actions # type: ignore[attr-defined]
108
+ if getattr(action, "dest", None) != "analyze"
109
+ ]
90
110
  analyze.add_argument("--app-key", required=True)
91
111
  analyze.add_argument("--dimensions-file")
92
112
  analyze.add_argument("--metrics-file")
@@ -122,6 +142,13 @@ def _columns(args: argparse.Namespace) -> list[Any]:
122
142
  return columns
123
143
 
124
144
 
145
+ def _query_fields(args: argparse.Namespace) -> list[Any]:
146
+ query_fields: list[Any] = list(getattr(args, "query_fields", None) or [])
147
+ if getattr(args, "query_fields_file", None):
148
+ query_fields.extend(require_list_arg(args.query_fields_file, option_name="--query-fields-file"))
149
+ return query_fields
150
+
151
+
125
152
  def _handle_schema_root(args: argparse.Namespace, _context: CliContext) -> dict:
126
153
  mode = (args.legacy_mode or "").strip()
127
154
  if mode:
@@ -216,14 +243,26 @@ def _handle_list(args: argparse.Namespace, context: CliContext) -> dict:
216
243
  profile=args.profile,
217
244
  app_key=args.app_key,
218
245
  columns=_columns(args),
246
+ query=args.query,
247
+ query_fields=_query_fields(args),
219
248
  where=load_list_arg(args.where_file, option_name="--where-file"),
220
249
  order_by=load_list_arg(args.order_by_file, option_name="--order-by-file"),
221
- limit=args.limit,
222
250
  page=args.page,
223
251
  view_id=args.view_id,
224
252
  )
225
253
 
226
254
 
255
+ def _handle_access(args: argparse.Namespace, context: CliContext) -> dict:
256
+ return context.record.record_access(
257
+ profile=args.profile,
258
+ app_key=args.app_key,
259
+ columns=_columns(args),
260
+ where=load_list_arg(args.where_file, option_name="--where-file"),
261
+ order_by=load_list_arg(args.order_by_file, option_name="--order-by-file"),
262
+ view_id=args.view_id,
263
+ )
264
+
265
+
227
266
  def _handle_get(args: argparse.Namespace, context: CliContext) -> dict:
228
267
  return context.record.record_get_public(
229
268
  profile=args.profile,