@qingflow-tech/qingflow-cli 1.1.49 → 1.1.50

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 (65) hide show
  1. package/README.md +4 -4
  2. package/npm/lib/runtime.mjs +29 -13
  3. package/package.json +1 -1
  4. package/pyproject.toml +1 -1
  5. package/skills/qingflow-cli/SKILL.md +91 -410
  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_DATA_RETRIEVAL_WORKFLOW.md +3 -137
  10. package/skills/qingflow-cli/reference/QINGFLOW_CLI_EXPLORATION_REPORT.md +6 -4
  11. package/skills/qingflow-cli/reference/QINGFLOW_CLI_FIELD_DATA_TYPES.md +14 -14
  12. package/skills/qingflow-cli/reference/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +20 -19
  13. package/skills/qingflow-cli/reference/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +18 -14
  14. package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md +7 -12
  15. package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +2 -1
  16. package/skills/qingflow-cli/reference/builder/workflow/03-flow-patterns.md +13 -5
  17. package/skills/qingflow-cli/reference/builder/workflow/07-stage4-validate-spec.md +5 -3
  18. package/skills/qingflow-cli/reference/builder/workflow/08-stage5-apply-verify.md +1 -1
  19. package/skills/qingflow-cli/reference/builder/workflow/11-troubleshooting.md +1 -1
  20. package/skills/qingflow-cli/reference/builder/workflow/workflow-schema.json +1665 -1738
  21. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +1 -1
  22. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +76 -95
  23. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_EXPLORATION_REPORT.md +6 -4
  24. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_FIELD_DATA_TYPES.md +13 -13
  25. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +20 -19
  26. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +18 -14
  27. package/skills/qingflow-cli/reference/data/README.md +32 -0
  28. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_SPECIALIZED_WORKFLOW.md +50 -0
  29. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +2 -1
  30. package/skills/qingflow-cli/reference/record/analysis/README.md +21 -113
  31. package/skills/qingflow-cli/reference/record/analysis/analysis-gotchas.md +10 -10
  32. package/skills/qingflow-cli/reference/record/analysis/analysis-patterns.md +9 -9
  33. package/skills/qingflow-cli/reference/record/analysis/business-context.md +1 -1
  34. package/skills/qingflow-cli/reference/record/analysis/confidence-reporting.md +10 -10
  35. package/skills/qingflow-cli/reference/record/analysis/data-access-playbook.md +52 -80
  36. package/skills/qingflow-cli/reference/record/analysis/pandas-recipes.md +2 -2
  37. package/skills/qingflow-cli/scripts/workflow/validate_flow_spec.py +48 -46
  38. package/skills/qingflow-common/SKILL.md +10 -17
  39. package/src/qingflow_mcp/__init__.py +1 -1
  40. package/src/qingflow_mcp/backend_client.py +142 -12
  41. package/src/qingflow_mcp/builder_facade/flow_validation.py +569 -0
  42. package/src/qingflow_mcp/builder_facade/service.py +749 -6
  43. package/src/qingflow_mcp/builder_facade/workflow_spec.py +155 -3
  44. package/src/qingflow_mcp/cli/commands/__init__.py +2 -1
  45. package/src/qingflow_mcp/cli/commands/auth.py +1 -1
  46. package/src/qingflow_mcp/cli/commands/builder.py +57 -41
  47. package/src/qingflow_mcp/cli/commands/data.py +134 -0
  48. package/src/qingflow_mcp/cli/commands/record.py +1 -1
  49. package/src/qingflow_mcp/cli/context.py +4 -1
  50. package/src/qingflow_mcp/cli/formatters.py +159 -4
  51. package/src/qingflow_mcp/cli/main.py +4 -1
  52. package/src/qingflow_mcp/config.py +60 -0
  53. package/src/qingflow_mcp/public_surface.py +9 -0
  54. package/src/qingflow_mcp/resource_uri.py +241 -0
  55. package/src/qingflow_mcp/response_trim.py +53 -5
  56. package/src/qingflow_mcp/server.py +2 -0
  57. package/src/qingflow_mcp/server_app_builder.py +57 -2
  58. package/src/qingflow_mcp/server_app_user.py +10 -3
  59. package/src/qingflow_mcp/tools/ai_builder_tools.py +374 -41
  60. package/src/qingflow_mcp/tools/app_tools.py +52 -13
  61. package/src/qingflow_mcp/tools/csv_export.py +168 -0
  62. package/src/qingflow_mcp/tools/data_tools.py +284 -0
  63. package/src/qingflow_mcp/tools/login_link_tools.py +34 -6
  64. package/src/qingflow_mcp/tools/record_tools.py +11 -46
  65. package/src/qingflow_mcp/tools/resource_read_tools.py +13 -0
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import csv
4
3
  import html
5
4
  import mimetypes
6
5
  import json
@@ -34,6 +33,7 @@ from ..list_type_labels import (
34
33
  )
35
34
  from .base import ToolBase
36
35
  from .directory_tools import _directory_has_more, _directory_items
36
+ from .csv_export import CsvShardWriter
37
37
 
38
38
 
39
39
  DEFAULT_QUERY_PAGE_SIZE = 50
@@ -2284,57 +2284,22 @@ class RecordTools(ToolBase):
2284
2284
  }
2285
2285
 
2286
2286
  run_dir = _record_access_run_dir()
2287
- run_dir.mkdir(parents=True, exist_ok=True)
2288
2287
  header = ["record_id"] + [str(field["column_name"]) for field in fields_payload]
2289
- files: list[JSONObject] = []
2290
- shard_part = 0
2291
- shard_rows = 0
2292
- row_count = 0
2293
- file_handle: Any | None = None
2294
- writer: Any | None = None
2295
-
2296
- def close_shard() -> None:
2297
- nonlocal file_handle, writer, shard_rows
2298
- if file_handle is None:
2299
- return
2300
- path = Path(file_handle.name)
2301
- file_handle.close()
2302
- files.append(
2303
- {
2304
- "local_path": str(path),
2305
- "row_count": shard_rows,
2306
- "part": len(files) + 1,
2307
- }
2308
- )
2309
- file_handle = None
2310
- writer = None
2311
- shard_rows = 0
2312
-
2313
- def ensure_writer() -> Any:
2314
- nonlocal file_handle, writer, shard_part
2315
- if writer is not None:
2316
- return writer
2317
- shard_part += 1
2318
- path = run_dir / f"records-{shard_part:04d}.csv"
2319
- file_handle = path.open("w", newline="", encoding="utf-8-sig")
2320
- writer = csv.writer(file_handle)
2321
- writer.writerow(header)
2322
- return writer
2288
+ shard_writer = CsvShardWriter(
2289
+ output_dir=run_dir,
2290
+ file_prefix="records",
2291
+ header=header,
2292
+ shard_rows=DEFAULT_RECORD_ACCESS_SHARD_ROWS,
2293
+ )
2323
2294
 
2324
2295
  def write_record(apply_id: int | None, answer_list: list[JSONValue]) -> None:
2325
- nonlocal row_count, shard_rows
2326
2296
  if apply_id is None:
2327
2297
  return
2328
- if shard_rows >= DEFAULT_RECORD_ACCESS_SHARD_ROWS:
2329
- close_shard()
2330
- csv_writer = ensure_writer()
2331
2298
  values: list[str] = [_public_record_id_text(apply_id) or ""]
2332
2299
  for field in selected_fields:
2333
2300
  answer = _find_answer_for_field(answer_list, field)
2334
2301
  values.append(_record_access_csv_cell(_normalize_answer_field_value_for_output(answer, field)))
2335
- csv_writer.writerow(values)
2336
- row_count += 1
2337
- shard_rows += 1
2302
+ shard_writer.write(values)
2338
2303
 
2339
2304
  current_page = 1
2340
2305
  has_more = False
@@ -2374,7 +2339,7 @@ class RecordTools(ToolBase):
2374
2339
  break
2375
2340
  page = fetch_page(current_page, BACKEND_RECORD_ACCESS_PAGE_SIZE)
2376
2341
  finally:
2377
- close_shard()
2342
+ shard_writer.close_shard()
2378
2343
 
2379
2344
  if stopped_reason == "TIME_BUDGET_EXCEEDED":
2380
2345
  warnings.append(_record_access_time_budget_warning(reported_total=reported_total, fetched_pages=fetched_pages))
@@ -2399,11 +2364,11 @@ class RecordTools(ToolBase):
2399
2364
  "view_id": view_route.view_id,
2400
2365
  "format": "csv",
2401
2366
  "local_dir": str(run_dir),
2402
- "row_count": row_count,
2367
+ "row_count": shard_writer.row_count,
2403
2368
  "complete": complete,
2404
2369
  "truncated": not complete,
2405
2370
  "safe_for_final_conclusion": safe_for_final_conclusion,
2406
- "files": files,
2371
+ "files": shard_writer.files,
2407
2372
  "fields": fields_payload,
2408
2373
  "warnings": warnings,
2409
2374
  "verification": verification_payload,
@@ -6,6 +6,7 @@ from typing import Any
6
6
  from ..errors import QingflowApiError, backend_code_int, is_auth_like_error, raise_tool_error
7
7
  from ..json_types import JSONObject
8
8
  from ..list_type_labels import SYSTEM_VIEW_DEFINITIONS
9
+ from ..resource_uri import try_build_resource_uri
9
10
  from ..solution.compiler.icon_utils import workspace_icon_config
10
11
  from .app_tools import _analysis_supported_for_view_type
11
12
  from .base import ToolBase
@@ -227,6 +228,17 @@ class ResourceReadTools(ToolBase):
227
228
  "message": f"view_get supports exporting `{view_id}`, but the export call still needs an explicit `app_key` from the parent app context.",
228
229
  }
229
230
  )
231
+ uri = None
232
+ if resolved_app_key:
233
+ uri, uri_warning = try_build_resource_uri(
234
+ ws_id=session_profile.selected_ws_id,
235
+ resource_type="view",
236
+ app_key=resolved_app_key,
237
+ view_kind="custom",
238
+ view_key=view_key,
239
+ )
240
+ if uri_warning:
241
+ warnings.append(uri_warning)
230
242
  return {
231
243
  "profile": profile,
232
244
  "ws_id": session_profile.selected_ws_id,
@@ -249,6 +261,7 @@ class ResourceReadTools(ToolBase):
249
261
  ],
250
262
  "analysis_supported": _analysis_supported_for_view_type(raw_view_type or None),
251
263
  "export_capability": export_capability,
264
+ **({"uri": uri} if uri else {}),
252
265
  },
253
266
  }
254
267