@qingflow-tech/qingflow-cli 1.1.53 → 1.1.54

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.
package/README.md CHANGED
@@ -7,7 +7,7 @@ Qingflow CLI 是轻流面向开发者和 AI Agent 的命令行工具。它把轻
7
7
  ## 安装
8
8
 
9
9
  ```bash
10
- npm install @qingflow-tech/qingflow-cli@1.1.53
10
+ npm install @qingflow-tech/qingflow-cli@1.1.54
11
11
  ```
12
12
 
13
13
  推荐从官网复制这一条一键安装 Qingflow CLI:
@@ -21,7 +21,7 @@ npx qingflow-cli@latest install
21
21
  ## 运行
22
22
 
23
23
  ```bash
24
- npx -y -p @qingflow-tech/qingflow-cli@1.1.53 qingflow
24
+ npx -y -p @qingflow-tech/qingflow-cli@1.1.54 qingflow
25
25
  ```
26
26
 
27
27
  全局安装后可以直接运行:
@@ -62,7 +62,7 @@ qingflow-skills install --agent codex --scope user
62
62
  如果你通过一次性 `npx -p` 执行 skills 安装,建议加 `--copy`,避免 symlink 指向 npm 临时执行缓存:
63
63
 
64
64
  ```bash
65
- npx -y -p @qingflow-tech/qingflow-cli@1.1.53 qingflow-skills install --agent codex --scope user --copy
65
+ npx -y -p @qingflow-tech/qingflow-cli@1.1.54 qingflow-skills install --agent codex --scope user --copy
66
66
  ```
67
67
 
68
68
  `qingflow-skills install` 默认使用 symlink,且遇到同名 skill 不会覆盖;只有显式传入 `--force` 才会替换。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qingflow-tech/qingflow-cli",
3
- "version": "1.1.53",
3
+ "version": "1.1.54",
4
4
  "description": "Human-friendly Qingflow command line interface for auth, record operations, import, tasks, and stable builder flows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qingflow-mcp"
7
- version = "1.1.53"
7
+ version = "1.1.54"
8
8
  description = "User-authenticated MCP server for Qingflow"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -28278,7 +28278,7 @@ def _build_view_query_conditions_payload(
28278
28278
  if issue:
28279
28279
  issues.append(issue)
28280
28280
  continue
28281
- que_id = _coerce_positive_int(field.get("que_id"))
28281
+ que_id = _coerce_any_int(field.get("que_id"))
28282
28282
  if que_id is not None:
28283
28283
  compiled_row.append(que_id)
28284
28284
  if compiled_row:
@@ -28302,7 +28302,11 @@ def _resolve_query_condition_field(
28302
28302
  selector: Any,
28303
28303
  reason_path: str,
28304
28304
  ) -> tuple[dict[str, Any], dict[str, Any] | None]:
28305
- raw = str(selector or "").strip()
28305
+ # queId 0(编号)是合法选择器,不能用 `selector or ""` 当成空值。
28306
+ if selector is None or (isinstance(selector, str) and not selector.strip()):
28307
+ raw = ""
28308
+ else:
28309
+ raw = str(selector).strip()
28306
28310
  if not raw:
28307
28311
  return {}, {
28308
28312
  "error_code": "QUERY_CONDITION_FIELD_NOT_FOUND",
@@ -28322,6 +28326,9 @@ def _resolve_query_condition_field(
28322
28326
  field = candidate
28323
28327
  break
28324
28328
  if field is None:
28329
+ system_field = _system_query_condition_field(raw)
28330
+ if system_field is not None:
28331
+ return system_field, None
28325
28332
  subfield_parent = _find_subtable_subfield_parent(fields_by_que_id=fields_by_que_id, selector=raw)
28326
28333
  if subfield_parent is not None:
28327
28334
  return {}, {
@@ -28354,8 +28361,8 @@ def _resolve_query_condition_field(
28354
28361
  "supported_field_types": QUERY_CONDITION_SUPPORTED_FIELD_TYPES_PUBLIC,
28355
28362
  "unsupported_field_types": QUERY_CONDITION_UNSUPPORTED_FIELD_TYPES_PUBLIC,
28356
28363
  }
28357
- que_id = _coerce_positive_int(field.get("que_id"))
28358
- if que_id is None:
28364
+ que_id = _coerce_any_int(field.get("que_id"))
28365
+ if que_id is None or (que_id <= 0 and not _is_known_system_view_que_id(que_id)):
28359
28366
  return {}, {
28360
28367
  "error_code": "INVALID_QUERY_CONDITION_FIELD",
28361
28368
  "reason_path": reason_path,
@@ -28368,6 +28375,31 @@ def _resolve_query_condition_field(
28368
28375
  return field, None
28369
28376
 
28370
28377
 
28378
+ _SYSTEM_QUERY_CONDITION_NAME_ALIASES = {
28379
+ "申请时间": 2,
28380
+ "申请人": 1,
28381
+ }
28382
+
28383
+
28384
+ def _system_query_condition_field(selector: str) -> dict[str, Any] | None:
28385
+ """已知系统字段可直接作为查询条件,不必出现在表单业务字段索引里。"""
28386
+ que_id = _coerce_any_int(selector)
28387
+ if que_id is None or not _is_known_system_view_que_id(que_id):
28388
+ que_id = _SYSTEM_QUERY_CONDITION_NAME_ALIASES.get(selector)
28389
+ if que_id is None:
28390
+ for system_id, system_name in _SYSTEM_VIEW_QUE_NAMES.items():
28391
+ if selector == system_name:
28392
+ que_id = system_id
28393
+ break
28394
+ if que_id is None or not _is_known_system_view_que_id(que_id):
28395
+ return None
28396
+ return {
28397
+ "que_id": que_id,
28398
+ "name": _SYSTEM_VIEW_QUE_NAMES.get(que_id, selector),
28399
+ "type": "text",
28400
+ }
28401
+
28402
+
28371
28403
  def _find_subtable_subfield_parent(
28372
28404
  *,
28373
28405
  fields_by_que_id: dict[str, dict[str, Any]],
@@ -28439,11 +28471,13 @@ def _normalize_view_query_conditions_for_compare(config: Any) -> dict[str, Any]:
28439
28471
  raw_row = raw_row.get("queIds") or []
28440
28472
  if not isinstance(raw_row, list):
28441
28473
  continue
28442
- compiled_row = [
28443
- field_id
28444
- for field_id in (_coerce_positive_int(item) for item in raw_row)
28445
- if field_id is not None
28446
- ]
28474
+ compiled_row = []
28475
+ for item in raw_row:
28476
+ field_id = _coerce_any_int(item)
28477
+ if field_id is None:
28478
+ continue
28479
+ if field_id > 0 or _is_known_system_view_que_id(field_id):
28480
+ compiled_row.append(field_id)
28447
28481
  if compiled_row:
28448
28482
  rows.append(compiled_row)
28449
28483
  enabled = bool(config.get("queryConditionStatus", bool(rows)))
@@ -12,6 +12,7 @@ from .service import (
12
12
  ASSOCIATED_RESOURCE_LIMIT_TYPE_ALL,
13
13
  _coerce_any_int,
14
14
  _coerce_positive_int,
15
+ _is_known_system_view_que_id,
15
16
  _extract_view_button_entries,
16
17
  _public_view_filter_groups_from_match_rules,
17
18
  _public_visibility_from_member_auth,
@@ -501,8 +502,10 @@ def extract_complete_view_declaration(
501
502
  continue
502
503
  row_names: list[str] = []
503
504
  for index, que_id in enumerate(raw_row.get("queIds") or []):
504
- parsed = _coerce_positive_int(que_id)
505
- if parsed and parsed in fields_by_que_id:
505
+ parsed = _coerce_any_int(que_id)
506
+ if parsed is None:
507
+ continue
508
+ if _is_known_system_view_que_id(parsed) or parsed in fields_by_que_id:
506
509
  row_names.append(parsed)
507
510
  if row_names:
508
511
  rows.append(row_names)