@josephyan/qingflow-cli 0.2.0-beta.985 → 0.2.0-beta.987

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 (44) hide show
  1. package/README.md +2 -2
  2. package/docs/local-agent-install.md +70 -11
  3. package/package.json +1 -1
  4. package/pyproject.toml +1 -1
  5. package/src/qingflow_mcp/__init__.py +1 -1
  6. package/src/qingflow_mcp/builder_facade/service.py +376 -19
  7. package/src/qingflow_mcp/cli/commands/auth.py +14 -43
  8. package/src/qingflow_mcp/cli/commands/workspace.py +8 -5
  9. package/src/qingflow_mcp/cli/formatters.py +19 -22
  10. package/src/qingflow_mcp/config.py +39 -0
  11. package/src/qingflow_mcp/errors.py +2 -2
  12. package/src/qingflow_mcp/public_surface.py +4 -6
  13. package/src/qingflow_mcp/response_trim.py +1 -8
  14. package/src/qingflow_mcp/server.py +1 -1
  15. package/src/qingflow_mcp/server_app_builder.py +4 -28
  16. package/src/qingflow_mcp/server_app_user.py +4 -28
  17. package/src/qingflow_mcp/session_store.py +31 -5
  18. package/src/qingflow_mcp/solution/compiler/form_compiler.py +2 -2
  19. package/src/qingflow_mcp/solution/executor.py +2 -2
  20. package/src/qingflow_mcp/tools/ai_builder_tools.py +117 -1
  21. package/src/qingflow_mcp/tools/app_tools.py +51 -1
  22. package/src/qingflow_mcp/tools/approval_tools.py +82 -1
  23. package/src/qingflow_mcp/tools/auth_tools.py +306 -288
  24. package/src/qingflow_mcp/tools/base.py +204 -4
  25. package/src/qingflow_mcp/tools/code_block_tools.py +21 -0
  26. package/src/qingflow_mcp/tools/custom_button_tools.py +24 -1
  27. package/src/qingflow_mcp/tools/directory_tools.py +28 -1
  28. package/src/qingflow_mcp/tools/feedback_tools.py +8 -0
  29. package/src/qingflow_mcp/tools/file_tools.py +25 -1
  30. package/src/qingflow_mcp/tools/import_tools.py +40 -1
  31. package/src/qingflow_mcp/tools/navigation_tools.py +34 -1
  32. package/src/qingflow_mcp/tools/package_tools.py +37 -1
  33. package/src/qingflow_mcp/tools/portal_tools.py +28 -1
  34. package/src/qingflow_mcp/tools/qingbi_report_tools.py +38 -1
  35. package/src/qingflow_mcp/tools/record_tools.py +255 -2
  36. package/src/qingflow_mcp/tools/repository_dev_tools.py +21 -2
  37. package/src/qingflow_mcp/tools/resource_read_tools.py +23 -1
  38. package/src/qingflow_mcp/tools/role_tools.py +19 -1
  39. package/src/qingflow_mcp/tools/solution_tools.py +56 -1
  40. package/src/qingflow_mcp/tools/task_context_tools.py +72 -1
  41. package/src/qingflow_mcp/tools/task_tools.py +49 -3
  42. package/src/qingflow_mcp/tools/view_tools.py +56 -1
  43. package/src/qingflow_mcp/tools/workflow_tools.py +65 -1
  44. package/src/qingflow_mcp/tools/workspace_tools.py +100 -217
@@ -21,7 +21,7 @@ from ..list_type_labels import (
21
21
  get_system_view_id,
22
22
  get_system_view_name,
23
23
  )
24
- from .base import ToolBase
24
+ from .base import ToolBase, tool_cn_name
25
25
  from .directory_tools import _directory_has_more, _directory_items
26
26
 
27
27
 
@@ -240,7 +240,17 @@ FIELD_LOOKUP_STRIP_RE = re.compile(r"[\s_()()\[\]【】{}<>·/\\::-]+")
240
240
 
241
241
 
242
242
  class RecordTools(ToolBase):
243
+ """记录工具(中文名:记录读写与分析)。
244
+
245
+ 类型:业务数据操作工具。
246
+ 主要职责:
247
+ 1. 提供记录 Schema、记录查询、记录 CRUD;
248
+ 2. 提供成员/部门候选与代码块相关能力;
249
+ 3. 提供面向分析场景的数据读取与字段归一化能力。
250
+ """
251
+
243
252
  def __init__(self, sessions, backend) -> None: # type: ignore[no-untyped-def]
253
+ """执行内部辅助逻辑。"""
244
254
  super().__init__(sessions, backend)
245
255
  self._form_cache: dict[tuple[str, str, str, int | None], JSONObject] = {}
246
256
  self._applicant_node_cache: dict[tuple[str, str], WorkflowNodeRef] = {}
@@ -250,6 +260,7 @@ class RecordTools(ToolBase):
250
260
  self._relation_base_info_cache: dict[tuple[str, int], JSONObject] = {}
251
261
 
252
262
  def register(self, mcp: FastMCP) -> None:
263
+ """注册当前工具到 MCP 服务。"""
253
264
  @mcp.tool()
254
265
  def record_insert_schema_get(
255
266
  app_key: str = "",
@@ -506,6 +517,7 @@ class RecordTools(ToolBase):
506
517
  output_profile=output_profile,
507
518
  )
508
519
 
520
+ @tool_cn_name("记录 Schema")
509
521
  def record_schema_get(
510
522
  self,
511
523
  *,
@@ -518,6 +530,7 @@ class RecordTools(ToolBase):
518
530
  view_name: str | None = None,
519
531
  output_profile: str = "normal",
520
532
  ) -> JSONObject:
533
+ """执行记录相关逻辑。"""
521
534
  if not app_key:
522
535
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
523
536
  normalized_schema_mode = schema_mode.strip().lower()
@@ -630,6 +643,7 @@ class RecordTools(ToolBase):
630
643
 
631
644
  return self._run_record_tool(profile, runner)
632
645
 
646
+ @tool_cn_name("新增记录 Schema")
633
647
  def record_insert_schema_get_public(
634
648
  self,
635
649
  *,
@@ -637,6 +651,7 @@ class RecordTools(ToolBase):
637
651
  app_key: str,
638
652
  output_profile: str = "normal",
639
653
  ) -> JSONObject:
654
+ """执行记录相关逻辑。"""
640
655
  if not app_key:
641
656
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
642
657
  normalized_output_profile = self._normalize_public_output_profile(output_profile)
@@ -745,6 +760,7 @@ class RecordTools(ToolBase):
745
760
 
746
761
  return self._run_record_tool(profile, runner)
747
762
 
763
+ @tool_cn_name("浏览记录 Schema")
748
764
  def record_browse_schema_get_public(
749
765
  self,
750
766
  *,
@@ -753,6 +769,7 @@ class RecordTools(ToolBase):
753
769
  view_id: str,
754
770
  output_profile: str = "normal",
755
771
  ) -> JSONObject:
772
+ """执行记录相关逻辑。"""
756
773
  return self.record_schema_get(
757
774
  profile=profile,
758
775
  app_key=app_key,
@@ -761,6 +778,7 @@ class RecordTools(ToolBase):
761
778
  output_profile=output_profile,
762
779
  )
763
780
 
781
+ @tool_cn_name("更新记录 Schema")
764
782
  def record_update_schema_get_public(
765
783
  self,
766
784
  *,
@@ -769,6 +787,7 @@ class RecordTools(ToolBase):
769
787
  record_id: int,
770
788
  output_profile: str = "normal",
771
789
  ) -> JSONObject:
790
+ """执行记录相关逻辑。"""
772
791
  if not app_key:
773
792
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
774
793
  if record_id <= 0:
@@ -981,6 +1000,7 @@ class RecordTools(ToolBase):
981
1000
  view_probe_summary: list[JSONObject],
982
1001
  ambiguous_fields: list[JSONObject],
983
1002
  ) -> JSONObject:
1003
+ """执行内部辅助逻辑。"""
984
1004
  response: JSONObject = {
985
1005
  "profile": profile,
986
1006
  "ws_id": ws_id,
@@ -1010,7 +1030,9 @@ class RecordTools(ToolBase):
1010
1030
  ws_id: int | None,
1011
1031
  required_override: bool | None,
1012
1032
  linkage_payloads_by_field_id: dict[str, JSONObject] | None = None,
1033
+ include_field_id: bool = True,
1013
1034
  ) -> JSONObject:
1035
+ """执行内部辅助逻辑。"""
1014
1036
  kind = self._ready_schema_kind(field)
1015
1037
  row_fields: list[JSONObject] = []
1016
1038
  if kind == "subtable":
@@ -1025,11 +1047,12 @@ class RecordTools(ToolBase):
1025
1047
  else:
1026
1048
  required = bool(required_override) if required_override is not None else bool(field.required)
1027
1049
  payload: JSONObject = {
1028
- "field_id": field.que_id,
1029
1050
  "title": field.que_title,
1030
1051
  "kind": kind,
1031
1052
  "required": required,
1032
1053
  }
1054
+ if include_field_id:
1055
+ payload["field_id"] = field.que_id
1033
1056
  if kind in {"single_select", "multi_select"} and field.options:
1034
1057
  payload["options"] = list(field.options)
1035
1058
  if kind in {"member", "department", "relation"}:
@@ -1077,6 +1100,7 @@ class RecordTools(ToolBase):
1077
1100
  reason: str,
1078
1101
  linkage_payloads_by_field_id: dict[str, JSONObject] | None = None,
1079
1102
  ) -> JSONObject:
1103
+ """执行内部辅助逻辑。"""
1080
1104
  payload = self._ready_schema_field_payload(
1081
1105
  profile,
1082
1106
  context,
@@ -1084,6 +1108,7 @@ class RecordTools(ToolBase):
1084
1108
  ws_id=ws_id,
1085
1109
  required_override=True,
1086
1110
  linkage_payloads_by_field_id=linkage_payloads_by_field_id,
1111
+ include_field_id=False,
1087
1112
  )
1088
1113
  payload["reason"] = reason
1089
1114
  self._attach_ready_schema_linkage(
@@ -1102,6 +1127,7 @@ class RecordTools(ToolBase):
1102
1127
  linkage_payloads_by_field_id: dict[str, JSONObject] | None,
1103
1128
  role_override: str | None = None,
1104
1129
  ) -> None:
1130
+ """执行内部辅助逻辑。"""
1105
1131
  if not linkage_payloads_by_field_id:
1106
1132
  return
1107
1133
  linkage_payload = linkage_payloads_by_field_id.get(field_id)
@@ -1118,6 +1144,7 @@ class RecordTools(ToolBase):
1118
1144
  *,
1119
1145
  runtime_linked_field_ids: set[str],
1120
1146
  ) -> bool:
1147
+ """执行内部辅助逻辑。"""
1121
1148
  if not bool(field.required) or bool(field.system) or not bool(field.readonly):
1122
1149
  return False
1123
1150
  if str(field.que_id) not in runtime_linked_field_ids:
@@ -1139,6 +1166,7 @@ class RecordTools(ToolBase):
1139
1166
  ws_id: int | None,
1140
1167
  linkage_payloads_by_field_id: dict[str, JSONObject] | None = None,
1141
1168
  ) -> list[JSONObject]:
1169
+ """执行内部辅助逻辑。"""
1142
1170
  raw = field.raw if isinstance(field.raw, dict) else {}
1143
1171
  columns_source = raw.get("subQuestions")
1144
1172
  if isinstance(columns_source, list):
@@ -1161,11 +1189,13 @@ class RecordTools(ToolBase):
1161
1189
  ws_id=ws_id,
1162
1190
  required_override=bool(subfield.required),
1163
1191
  linkage_payloads_by_field_id=linkage_payloads_by_field_id,
1192
+ include_field_id=False,
1164
1193
  )
1165
1194
  )
1166
1195
  return payloads
1167
1196
 
1168
1197
  def _ready_schema_kind(self, field: FormField) -> str:
1198
+ """执行内部辅助逻辑。"""
1169
1199
  write_format = _write_format_for_field(field)
1170
1200
  write_kind = _normalize_optional_text(write_format.get("kind")) or "scalar_text"
1171
1201
  if write_kind == "subtable_rows":
@@ -1198,6 +1228,7 @@ class RecordTools(ToolBase):
1198
1228
  return "text"
1199
1229
 
1200
1230
  def _ready_schema_template_value(self, field_payload: JSONObject) -> JSONValue:
1231
+ """执行内部辅助逻辑。"""
1201
1232
  kind = _normalize_optional_text(field_payload.get("kind")) or "text"
1202
1233
  if kind == "number":
1203
1234
  return "<number>"
@@ -1243,6 +1274,7 @@ class RecordTools(ToolBase):
1243
1274
  ]
1244
1275
  return "<text>"
1245
1276
 
1277
+ @tool_cn_name("成员候选项")
1246
1278
  def record_member_candidates(
1247
1279
  self,
1248
1280
  *,
@@ -1256,6 +1288,7 @@ class RecordTools(ToolBase):
1256
1288
  page_num: int,
1257
1289
  page_size: int,
1258
1290
  ) -> JSONObject:
1291
+ """执行记录相关逻辑。"""
1259
1292
  if not app_key:
1260
1293
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
1261
1294
  if field_id <= 0:
@@ -1345,6 +1378,7 @@ class RecordTools(ToolBase):
1345
1378
 
1346
1379
  return self._run_record_tool(profile, runner)
1347
1380
 
1381
+ @tool_cn_name("部门候选项")
1348
1382
  def record_department_candidates(
1349
1383
  self,
1350
1384
  *,
@@ -1358,6 +1392,7 @@ class RecordTools(ToolBase):
1358
1392
  page_num: int,
1359
1393
  page_size: int,
1360
1394
  ) -> JSONObject:
1395
+ """执行记录相关逻辑。"""
1361
1396
  if not app_key:
1362
1397
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
1363
1398
  if field_id <= 0:
@@ -1464,6 +1499,7 @@ class RecordTools(ToolBase):
1464
1499
 
1465
1500
  return self._run_record_tool(profile, runner)
1466
1501
 
1502
+ @tool_cn_name("记录分析")
1467
1503
  def record_analyze(
1468
1504
  self,
1469
1505
  *,
@@ -1481,6 +1517,7 @@ class RecordTools(ToolBase):
1481
1517
  view_name: str | None = None,
1482
1518
  output_profile: str = "normal",
1483
1519
  ) -> JSONObject:
1520
+ """执行记录相关逻辑。"""
1484
1521
  if not app_key:
1485
1522
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
1486
1523
  if limit <= 0:
@@ -1551,6 +1588,7 @@ class RecordTools(ToolBase):
1551
1588
 
1552
1589
  return self._run_record_tool(profile, runner)
1553
1590
 
1591
+ @tool_cn_name("记录列表")
1554
1592
  def record_list(
1555
1593
  self,
1556
1594
  *,
@@ -1567,6 +1605,7 @@ class RecordTools(ToolBase):
1567
1605
  view_name: str | None = None,
1568
1606
  output_profile: str = "normal",
1569
1607
  ) -> JSONObject:
1608
+ """执行记录相关逻辑。"""
1570
1609
  normalized_output_profile = self._normalize_public_output_profile(output_profile, allow_normalized=True)
1571
1610
  if not app_key:
1572
1611
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
@@ -1708,6 +1747,7 @@ class RecordTools(ToolBase):
1708
1747
  }
1709
1748
  return response
1710
1749
 
1750
+ @tool_cn_name("记录详情")
1711
1751
  def record_get_public(
1712
1752
  self,
1713
1753
  *,
@@ -1719,6 +1759,7 @@ class RecordTools(ToolBase):
1719
1759
  workflow_node_id: int | None = None,
1720
1760
  output_profile: str = "normal",
1721
1761
  ) -> JSONObject:
1762
+ """执行记录相关逻辑。"""
1722
1763
  normalized_output_profile = self._normalize_public_output_profile(output_profile, allow_normalized=True)
1723
1764
  if record_id <= 0:
1724
1765
  raise_tool_error(QingflowApiError.config_error("record_id must be positive"))
@@ -1851,6 +1892,7 @@ class RecordTools(ToolBase):
1851
1892
 
1852
1893
  return self._run_record_tool(profile, runner)
1853
1894
 
1895
+ @tool_cn_name("新增记录")
1854
1896
  def record_insert_public(
1855
1897
  self,
1856
1898
  *,
@@ -1860,6 +1902,7 @@ class RecordTools(ToolBase):
1860
1902
  verify_write: bool = True,
1861
1903
  output_profile: str = "normal",
1862
1904
  ) -> JSONObject:
1905
+ """执行记录相关逻辑。"""
1863
1906
  normalized_output_profile = self._normalize_public_output_profile(output_profile)
1864
1907
  if not app_key:
1865
1908
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
@@ -1926,6 +1969,7 @@ class RecordTools(ToolBase):
1926
1969
  preflight=raw_preflight,
1927
1970
  )
1928
1971
 
1972
+ @tool_cn_name("更新记录")
1929
1973
  def record_update_public(
1930
1974
  self,
1931
1975
  *,
@@ -1938,6 +1982,7 @@ class RecordTools(ToolBase):
1938
1982
  verify_write: bool = True,
1939
1983
  output_profile: str = "normal",
1940
1984
  ) -> JSONObject:
1985
+ """执行记录相关逻辑。"""
1941
1986
  normalized_output_profile = self._normalize_public_output_profile(output_profile)
1942
1987
  if not app_key:
1943
1988
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
@@ -1982,6 +2027,7 @@ class RecordTools(ToolBase):
1982
2027
  verify_write: bool,
1983
2028
  output_profile: str,
1984
2029
  ) -> JSONObject:
2030
+ """执行内部辅助逻辑。"""
1985
2031
  raw_preflight = self._preflight_record_update_with_auto_view(
1986
2032
  profile=profile,
1987
2033
  app_key=app_key,
@@ -2047,6 +2093,7 @@ class RecordTools(ToolBase):
2047
2093
  verify_write: bool,
2048
2094
  output_profile: str,
2049
2095
  ) -> JSONObject:
2096
+ """执行内部辅助逻辑。"""
2050
2097
  preflight_responses = [
2051
2098
  self._record_update_public_preflight_response(
2052
2099
  profile=profile,
@@ -2115,6 +2162,7 @@ class RecordTools(ToolBase):
2115
2162
  fields: JSONObject,
2116
2163
  output_profile: str,
2117
2164
  ) -> JSONObject:
2165
+ """执行内部辅助逻辑。"""
2118
2166
  raw_preflight = self._preflight_record_update_with_auto_view(
2119
2167
  profile=profile,
2120
2168
  app_key=app_key,
@@ -2157,6 +2205,7 @@ class RecordTools(ToolBase):
2157
2205
  fields: JSONObject | None,
2158
2206
  items: list[JSONObject] | None,
2159
2207
  ) -> list[JSONObject]:
2208
+ """执行内部辅助逻辑。"""
2160
2209
  if record_id is not None or fields is not None:
2161
2210
  raise_tool_error(
2162
2211
  QingflowApiError.config_error("record_update batch mode does not accept record_id or fields")
@@ -2191,6 +2240,7 @@ class RecordTools(ToolBase):
2191
2240
  output_profile: str,
2192
2241
  dry_run: bool,
2193
2242
  ) -> JSONObject:
2243
+ """执行内部辅助逻辑。"""
2194
2244
  summary = self._record_update_batch_summary(responses)
2195
2245
  batch_items = [self._record_update_batch_item_from_response(response, output_profile=output_profile) for response in responses]
2196
2246
  status, ok, message = self._record_update_batch_envelope_status(summary=summary, dry_run=dry_run)
@@ -2214,6 +2264,7 @@ class RecordTools(ToolBase):
2214
2264
  }
2215
2265
 
2216
2266
  def _record_update_batch_summary(self, responses: list[JSONObject]) -> JSONObject:
2267
+ """执行内部辅助逻辑。"""
2217
2268
  summary: JSONObject = {
2218
2269
  "total": len(responses),
2219
2270
  "ready_count": 0,
@@ -2250,6 +2301,7 @@ class RecordTools(ToolBase):
2250
2301
  return summary
2251
2302
 
2252
2303
  def _record_update_batch_envelope_status(self, *, summary: JSONObject, dry_run: bool) -> tuple[str, bool, str]:
2304
+ """执行内部辅助逻辑。"""
2253
2305
  if int(summary["blocked_count"]) > 0:
2254
2306
  return "blocked", False, "batch update preflight blocked"
2255
2307
  if int(summary["confirmation_count"]) > 0:
@@ -2261,6 +2313,7 @@ class RecordTools(ToolBase):
2261
2313
  return "success", True, "batch update completed"
2262
2314
 
2263
2315
  def _record_update_batch_item_from_response(self, response: JSONObject, *, output_profile: str) -> JSONObject:
2316
+ """执行内部辅助逻辑。"""
2264
2317
  data = cast(JSONObject, response.get("data", {}))
2265
2318
  item: JSONObject = {
2266
2319
  "resource": data.get("resource"),
@@ -2292,6 +2345,7 @@ class RecordTools(ToolBase):
2292
2345
  fields: JSONObject,
2293
2346
  force_refresh_form: bool,
2294
2347
  ) -> JSONObject:
2348
+ """执行内部辅助逻辑。"""
2295
2349
  def runner(session_profile, context):
2296
2350
  request_route = self._request_route_payload(context)
2297
2351
  def build_once(*, effective_force_refresh: bool) -> JSONObject:
@@ -2583,6 +2637,7 @@ class RecordTools(ToolBase):
2583
2637
  matched_routes: list[AccessibleViewRoute],
2584
2638
  force_refresh_form: bool,
2585
2639
  ) -> JSONObject | None:
2640
+ """执行内部辅助逻辑。"""
2586
2641
  if len(matched_routes) < 2:
2587
2642
  return None
2588
2643
 
@@ -2745,6 +2800,7 @@ class RecordTools(ToolBase):
2745
2800
  view_probe_summary: list[JSONObject],
2746
2801
  template: JSONObject | None = None,
2747
2802
  ) -> JSONObject:
2803
+ """执行内部辅助逻辑。"""
2748
2804
  blocked_data: JSONObject = dict(template or {})
2749
2805
  validation = blocked_data.get("validation")
2750
2806
  if not isinstance(validation, dict):
@@ -2788,6 +2844,7 @@ class RecordTools(ToolBase):
2788
2844
  context, # type: ignore[no-untyped-def]
2789
2845
  app_key: str,
2790
2846
  ) -> list[AccessibleViewRoute]:
2847
+ """执行内部辅助逻辑。"""
2791
2848
  candidates: list[AccessibleViewRoute] = []
2792
2849
  for view_id, list_type, name in SYSTEM_VIEW_DEFINITIONS:
2793
2850
  candidates.append(
@@ -2996,6 +3053,7 @@ class RecordTools(ToolBase):
2996
3053
  *,
2997
3054
  resolved_view: AccessibleViewRoute,
2998
3055
  ) -> bool:
3056
+ """执行内部辅助逻辑。"""
2999
3057
  if resolved_view.kind == "system":
3000
3058
  return True
3001
3059
  return self._matches_view_selection(
@@ -3005,6 +3063,7 @@ class RecordTools(ToolBase):
3005
3063
  dept_member_cache={},
3006
3064
  )
3007
3065
 
3066
+ @tool_cn_name("删除记录")
3008
3067
  def record_delete_public(
3009
3068
  self,
3010
3069
  *,
@@ -3014,6 +3073,7 @@ class RecordTools(ToolBase):
3014
3073
  record_ids: list[int] | None = None,
3015
3074
  output_profile: str = "normal",
3016
3075
  ) -> JSONObject:
3076
+ """执行记录相关逻辑。"""
3017
3077
  normalized_output_profile = self._normalize_public_output_profile(output_profile)
3018
3078
  if not app_key:
3019
3079
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
@@ -3038,6 +3098,7 @@ class RecordTools(ToolBase):
3038
3098
  preflight=None,
3039
3099
  )
3040
3100
 
3101
+ @tool_cn_name("写入记录")
3041
3102
  def record_write(
3042
3103
  self,
3043
3104
  *,
@@ -3057,6 +3118,7 @@ class RecordTools(ToolBase):
3057
3118
  output_profile: str = "normal",
3058
3119
  mode: str | None = None,
3059
3120
  ) -> JSONObject:
3121
+ """执行记录相关逻辑。"""
3060
3122
  normalized_output_profile = self._normalize_public_output_profile(output_profile)
3061
3123
  normalized_operation = operation.strip().lower()
3062
3124
  if normalized_operation not in {"insert", "update", "delete"}:
@@ -3261,6 +3323,7 @@ class RecordTools(ToolBase):
3261
3323
  schema_mode: str = "applicant",
3262
3324
  browse_writable: bool | None = None,
3263
3325
  ) -> JSONObject: # type: ignore[no-untyped-def]
3326
+ """执行内部辅助逻辑。"""
3264
3327
  write_hints = self._schema_write_hints(field)
3265
3328
  if schema_mode == "applicant":
3266
3329
  writable = write_hints["writable"]
@@ -3305,6 +3368,7 @@ class RecordTools(ToolBase):
3305
3368
  return payload
3306
3369
 
3307
3370
  def _schema_role_hints(self, field: FormField) -> JSONObject:
3371
+ """执行内部辅助逻辑。"""
3308
3372
  field_family = self._schema_field_family(field)
3309
3373
  time_candidate = field.que_type in DATE_QUE_TYPES
3310
3374
  identifier_like = self._schema_is_identifier_like(field, field_family=field_family)
@@ -3323,6 +3387,7 @@ class RecordTools(ToolBase):
3323
3387
  }
3324
3388
 
3325
3389
  def _schema_write_hints(self, field: FormField) -> JSONObject:
3390
+ """执行内部辅助逻辑。"""
3326
3391
  write_format = _write_format_for_field(field)
3327
3392
  kind = _normalize_optional_text(write_format.get("kind")) or "scalar_text"
3328
3393
  support_level = _normalize_optional_text(write_format.get("support_level")) or "full"
@@ -3350,6 +3415,7 @@ class RecordTools(ToolBase):
3350
3415
  }
3351
3416
 
3352
3417
  def _schema_write_kind(self, kind: str) -> str:
3418
+ """执行内部辅助逻辑。"""
3353
3419
  mapping = {
3354
3420
  "single_select": "select",
3355
3421
  "multi_select": "select",
@@ -3373,6 +3439,7 @@ class RecordTools(ToolBase):
3373
3439
  target_app_key: str,
3374
3440
  ws_id: int | None,
3375
3441
  ) -> str | None:
3442
+ """执行内部辅助逻辑。"""
3376
3443
  cache_key = (profile, ws_id, target_app_key)
3377
3444
  if cache_key in self._app_name_cache:
3378
3445
  return self._app_name_cache[cache_key]
@@ -3391,6 +3458,7 @@ class RecordTools(ToolBase):
3391
3458
  return name
3392
3459
 
3393
3460
  def _lookup_context_answers(self, state: LookupResolutionState) -> list[JSONObject]:
3461
+ """执行内部辅助逻辑。"""
3394
3462
  merged: dict[int, JSONObject] = {}
3395
3463
  ordered_ids: list[int] = []
3396
3464
  for answer in state.base_answers:
@@ -3414,6 +3482,7 @@ class RecordTools(ToolBase):
3414
3482
  return [merged[que_id] for que_id in ordered_ids]
3415
3483
 
3416
3484
  def _answers_to_lookup_key_values(self, answers: list[JSONObject], index: FieldIndex) -> list[JSONObject]:
3485
+ """执行内部辅助逻辑。"""
3417
3486
  values: list[JSONObject] = []
3418
3487
  for answer in answers:
3419
3488
  if not isinstance(answer, dict):
@@ -3425,6 +3494,7 @@ class RecordTools(ToolBase):
3425
3494
  return values
3426
3495
 
3427
3496
  def _answer_to_lookup_key_value(self, answer: JSONObject, index: FieldIndex) -> JSONObject | None:
3497
+ """执行内部辅助逻辑。"""
3428
3498
  que_id = _coerce_count(answer.get("queId", answer.get("que_id")))
3429
3499
  if que_id is None or que_id <= 0:
3430
3500
  return None
@@ -3456,6 +3526,7 @@ class RecordTools(ToolBase):
3456
3526
  }
3457
3527
 
3458
3528
  def _answer_values_to_lookup_values(self, answer: JSONObject, field: FormField) -> list[str]:
3529
+ """执行内部辅助逻辑。"""
3459
3530
  if field.que_type in RELATION_QUE_TYPES:
3460
3531
  return _relation_ids_from_answer(answer)
3461
3532
  raw_values = answer.get("values")
@@ -3492,6 +3563,7 @@ class RecordTools(ToolBase):
3492
3563
  return normalized
3493
3564
 
3494
3565
  def _lookup_key_que_values(self, state: LookupResolutionState) -> list[JSONObject]:
3566
+ """执行内部辅助逻辑。"""
3495
3567
  answers = self._lookup_context_answers(state)
3496
3568
  if not answers:
3497
3569
  return []
@@ -3506,6 +3578,7 @@ class RecordTools(ToolBase):
3506
3578
  page_num: int = 1,
3507
3579
  page_size: int = LOOKUP_RELATION_FILTER_PAGE_SIZE,
3508
3580
  ) -> JSONObject:
3581
+ """执行内部辅助逻辑。"""
3509
3582
  payload: JSONObject = {
3510
3583
  "role": 1,
3511
3584
  "pageNum": page_num,
@@ -3525,6 +3598,7 @@ class RecordTools(ToolBase):
3525
3598
  return payload
3526
3599
 
3527
3600
  def _relation_base_info(self, context, *, app_key: str, field: FormField) -> JSONObject | None: # type: ignore[no-untyped-def]
3601
+ """执行内部辅助逻辑。"""
3528
3602
  cache_key = (app_key, field.que_id)
3529
3603
  if cache_key in self._relation_base_info_cache:
3530
3604
  return self._relation_base_info_cache[cache_key]
@@ -3544,6 +3618,7 @@ class RecordTools(ToolBase):
3544
3618
  app_key: str,
3545
3619
  field: FormField,
3546
3620
  ) -> list[JSONObject]:
3621
+ """执行内部辅助逻辑。"""
3547
3622
  direct = _relation_searchable_fields_for_question(field.raw)
3548
3623
  return direct
3549
3624
 
@@ -3554,6 +3629,7 @@ class RecordTools(ToolBase):
3554
3629
  field: FormField,
3555
3630
  app_key: str,
3556
3631
  ) -> list[tuple[JSONObject, FormField]]:
3632
+ """执行内部辅助逻辑。"""
3557
3633
  searchable_fields = self._relation_searchable_fields_for_field(context, app_key=app_key, field=field)
3558
3634
  if not searchable_fields:
3559
3635
  return []
@@ -3607,6 +3683,7 @@ class RecordTools(ToolBase):
3607
3683
  page_num: int = 1,
3608
3684
  page_size: int = LOOKUP_RELATION_FILTER_PAGE_SIZE,
3609
3685
  ) -> JSONObject:
3686
+ """执行内部辅助逻辑。"""
3610
3687
  payload: JSONObject = {
3611
3688
  "appKey": state.app_key,
3612
3689
  "queId": field.que_id,
@@ -3628,6 +3705,7 @@ class RecordTools(ToolBase):
3628
3705
  return payload
3629
3706
 
3630
3707
  def _normalize_relation_candidate_value(self, value: JSONValue) -> JSONValue:
3708
+ """执行内部辅助逻辑。"""
3631
3709
  if value is None:
3632
3710
  return None
3633
3711
  if isinstance(value, dict):
@@ -3656,6 +3734,7 @@ class RecordTools(ToolBase):
3656
3734
  *,
3657
3735
  field_defs: list[tuple[JSONObject, FormField]],
3658
3736
  ) -> list[JSONObject]:
3737
+ """执行内部辅助逻辑。"""
3659
3738
  if not isinstance(payload, dict):
3660
3739
  return []
3661
3740
  rows = payload.get("list")
@@ -3731,6 +3810,7 @@ class RecordTools(ToolBase):
3731
3810
  return candidates
3732
3811
 
3733
3812
  def _relation_confirmation_candidates(self, candidates: list[JSONObject]) -> list[JSONObject]:
3813
+ """执行内部辅助逻辑。"""
3734
3814
  payloads: list[JSONObject] = []
3735
3815
  for candidate in candidates[:LOOKUP_CONFIRMATION_CANDIDATE_LIMIT]:
3736
3816
  payloads.append(
@@ -3753,6 +3833,7 @@ class RecordTools(ToolBase):
3753
3833
  keyword: str,
3754
3834
  state: LookupResolutionState,
3755
3835
  ) -> tuple[list[JSONObject], list[JSONObject]]:
3836
+ """执行内部辅助逻辑。"""
3756
3837
  field_defs = self._relation_search_field_defs(context, field=field, app_key=state.app_key)
3757
3838
  searchable_fields = [item for item, _ in field_defs]
3758
3839
  try:
@@ -3781,6 +3862,7 @@ class RecordTools(ToolBase):
3781
3862
  return self._normalize_relation_candidates(result, field_defs=field_defs), searchable_fields
3782
3863
 
3783
3864
  def _lookup_context_is_incomplete(self, state: LookupResolutionState | None) -> bool:
3865
+ """执行内部辅助逻辑。"""
3784
3866
  return bool(state is not None and not state.context_complete)
3785
3867
 
3786
3868
  def _candidate_lookup_uses_runtime_scope(
@@ -3790,6 +3872,7 @@ class RecordTools(ToolBase):
3790
3872
  workflow_node_id: int | None,
3791
3873
  fields: JSONObject | None,
3792
3874
  ) -> bool:
3875
+ """执行内部辅助逻辑。"""
3793
3876
  return bool(
3794
3877
  (record_id is not None and record_id > 0)
3795
3878
  or (workflow_node_id is not None and workflow_node_id > 0)
@@ -3806,6 +3889,7 @@ class RecordTools(ToolBase):
3806
3889
  workflow_node_id: int | None,
3807
3890
  fields: JSONObject,
3808
3891
  ) -> LookupResolutionState:
3892
+ """执行内部辅助逻辑。"""
3809
3893
  index = self._get_field_index(profile, context, app_key, force_refresh=False)
3810
3894
  apply_id = record_id if isinstance(record_id, int) and record_id > 0 else None
3811
3895
  base_answers: list[JSONObject] = []
@@ -3851,6 +3935,7 @@ class RecordTools(ToolBase):
3851
3935
  location: str,
3852
3936
  explicit_fix_hint: str,
3853
3937
  ) -> None:
3938
+ """执行内部辅助逻辑。"""
3854
3939
  raise RecordInputError(
3855
3940
  message=(
3856
3941
  f"{kind} auto resolution for field '{field.que_title}' requires the current record context, "
@@ -3866,6 +3951,7 @@ class RecordTools(ToolBase):
3866
3951
  )
3867
3952
 
3868
3953
  def _normalize_backend_member_candidates(self, payload: JSONValue, *, external: bool) -> list[JSONObject]:
3954
+ """执行内部辅助逻辑。"""
3869
3955
  candidates: list[JSONObject] = []
3870
3956
  if not isinstance(payload, dict):
3871
3957
  return candidates
@@ -3882,6 +3968,7 @@ class RecordTools(ToolBase):
3882
3968
  return candidates
3883
3969
 
3884
3970
  def _normalize_backend_department_candidates(self, payload: JSONValue, *, external: bool) -> list[JSONObject]:
3971
+ """执行内部辅助逻辑。"""
3885
3972
  candidates: list[JSONObject] = []
3886
3973
  if not isinstance(payload, dict):
3887
3974
  return candidates
@@ -3900,6 +3987,7 @@ class RecordTools(ToolBase):
3900
3987
  return candidates
3901
3988
 
3902
3989
  def _department_candidate_path(self, value: JSONValue) -> str | None:
3990
+ """执行内部辅助逻辑。"""
3903
3991
  if not isinstance(value, dict):
3904
3992
  return None
3905
3993
  name = _normalize_optional_text(value.get("deptName", value.get("value", value.get("name"))))
@@ -3915,6 +4003,7 @@ class RecordTools(ToolBase):
3915
4003
  return " / ".join(list(reversed(parent_names)) + [name])
3916
4004
 
3917
4005
  def _rank_member_candidates(self, keyword: str, candidates: list[JSONObject]) -> list[JSONObject]:
4006
+ """执行内部辅助逻辑。"""
3918
4007
  requested = _normalize_field_lookup_key(keyword)
3919
4008
  ranked: list[JSONObject] = []
3920
4009
  for candidate in candidates:
@@ -3960,6 +4049,7 @@ class RecordTools(ToolBase):
3960
4049
  return ranked
3961
4050
 
3962
4051
  def _rank_department_candidates(self, keyword: str, candidates: list[JSONObject]) -> list[JSONObject]:
4052
+ """执行内部辅助逻辑。"""
3963
4053
  requested = _normalize_field_lookup_key(keyword)
3964
4054
  ranked: list[JSONObject] = []
3965
4055
  for candidate in candidates:
@@ -4002,6 +4092,7 @@ class RecordTools(ToolBase):
4002
4092
  *,
4003
4093
  searchable_fields: list[JSONObject],
4004
4094
  ) -> list[JSONObject]:
4095
+ """执行内部辅助逻辑。"""
4005
4096
  requested = _normalize_field_lookup_key(keyword)
4006
4097
  primary_titles = {
4007
4098
  _normalize_field_lookup_key(_stringify_json(item.get("title")))
@@ -4046,6 +4137,7 @@ class RecordTools(ToolBase):
4046
4137
  return ranked
4047
4138
 
4048
4139
  def _resolve_ranked_lookup_candidate(self, ranked_candidates: list[JSONObject]) -> JSONObject | None:
4140
+ """执行内部辅助逻辑。"""
4049
4141
  if not ranked_candidates:
4050
4142
  return None
4051
4143
  top = ranked_candidates[0]
@@ -4066,6 +4158,7 @@ class RecordTools(ToolBase):
4066
4158
  method: str,
4067
4159
  confidence: float,
4068
4160
  ) -> None:
4161
+ """执行内部辅助逻辑。"""
4069
4162
  if state is None:
4070
4163
  return
4071
4164
  state.resolved_fields.append(
@@ -4089,6 +4182,7 @@ class RecordTools(ToolBase):
4089
4182
  parent_field: FormField | None = None,
4090
4183
  row_ordinal: int | None = None,
4091
4184
  ) -> JSONObject:
4185
+ """执行内部辅助逻辑。"""
4092
4186
  payload: JSONObject = {
4093
4187
  "field": field.que_title,
4094
4188
  "kind": kind,
@@ -4112,6 +4206,7 @@ class RecordTools(ToolBase):
4112
4206
  parent_field: FormField | None = None,
4113
4207
  row_ordinal: int | None = None,
4114
4208
  ) -> None:
4209
+ """执行内部辅助逻辑。"""
4115
4210
  if state is None:
4116
4211
  return
4117
4212
  state.confirmation_requests.append(request)
@@ -4120,6 +4215,7 @@ class RecordTools(ToolBase):
4120
4215
  state.unresolved_subtable_cells.add((parent_field.que_id, row_ordinal, field.que_id))
4121
4216
 
4122
4217
  def _candidate_resolution_method(self, candidate: JSONObject, *, explicit_method: str | None = None) -> str:
4218
+ """执行内部辅助逻辑。"""
4123
4219
  if explicit_method:
4124
4220
  return explicit_method
4125
4221
  reason = _normalize_optional_text(candidate.get("match_reason")) or "resolved"
@@ -4140,6 +4236,7 @@ class RecordTools(ToolBase):
4140
4236
  state: LookupResolutionState | None,
4141
4237
  explicit_guidance: str,
4142
4238
  ) -> str:
4239
+ """执行内部辅助逻辑。"""
4143
4240
  if state is not None and self._candidate_lookup_uses_runtime_scope(
4144
4241
  record_id=state.apply_id,
4145
4242
  workflow_node_id=state.workflow_node_id,
@@ -4156,6 +4253,7 @@ class RecordTools(ToolBase):
4156
4253
  )
4157
4254
 
4158
4255
  def _resolve_member_candidates(self, context, field: FormField, *, keyword: str) -> list[JSONObject]: # type: ignore[no-untyped-def]
4256
+ """执行内部辅助逻辑。"""
4159
4257
  scope_type = field.member_select_scope_type
4160
4258
  scope = field.member_select_scope if isinstance(field.member_select_scope, dict) else {}
4161
4259
  if _scope_is_default_all(scope_type, scope, keys=("member", "depart", "role")):
@@ -4239,6 +4337,7 @@ class RecordTools(ToolBase):
4239
4337
  return filtered
4240
4338
 
4241
4339
  def _resolve_department_candidates(self, context, field: FormField, *, keyword: str) -> list[JSONObject]: # type: ignore[no-untyped-def]
4340
+ """执行内部辅助逻辑。"""
4242
4341
  scope_type = field.dept_select_scope_type
4243
4342
  scope = field.dept_select_scope if isinstance(field.dept_select_scope, dict) else {}
4244
4343
  if _scope_has_dynamic_or_external(scope):
@@ -4302,6 +4401,7 @@ class RecordTools(ToolBase):
4302
4401
  return filtered
4303
4402
 
4304
4403
  def _merge_member_candidate(self, merged: dict[str, JSONObject], candidate: JSONObject) -> None:
4404
+ """执行内部辅助逻辑。"""
4305
4405
  key = _member_candidate_key(candidate)
4306
4406
  if not key:
4307
4407
  return
@@ -4335,6 +4435,7 @@ class RecordTools(ToolBase):
4335
4435
  dept_id: int,
4336
4436
  include_sub_departments: bool,
4337
4437
  ) -> list[dict[str, Any]]:
4438
+ """执行内部辅助逻辑。"""
4338
4439
  dept_ids = {dept_id}
4339
4440
  if include_sub_departments:
4340
4441
  dept_ids.update(self._expand_department_ids(context, root_dept_id=dept_id))
@@ -4347,6 +4448,7 @@ class RecordTools(ToolBase):
4347
4448
  return list(merged.values())
4348
4449
 
4349
4450
  def _list_members_by_role(self, context, *, role_id: int) -> list[dict[str, Any]]: # type: ignore[no-untyped-def]
4451
+ """执行内部辅助逻辑。"""
4350
4452
  return self._fetch_internal_members(context, department_id=None, role_id=role_id)
4351
4453
 
4352
4454
  def _list_departments_by_scope(
@@ -4356,6 +4458,7 @@ class RecordTools(ToolBase):
4356
4458
  dept_id: int,
4357
4459
  include_sub_departments: bool,
4358
4460
  ) -> list[dict[str, Any]]:
4461
+ """执行内部辅助逻辑。"""
4359
4462
  dept_ids = {dept_id}
4360
4463
  if include_sub_departments:
4361
4464
  dept_ids.update(self._expand_department_ids(context, root_dept_id=dept_id))
@@ -4369,6 +4472,7 @@ class RecordTools(ToolBase):
4369
4472
  return list(merged.values())
4370
4473
 
4371
4474
  def _list_all_departments(self, context) -> list[dict[str, Any]]: # type: ignore[no-untyped-def]
4475
+ """执行内部辅助逻辑。"""
4372
4476
  queue: list[int | None] = [None]
4373
4477
  seen_ids: set[int] = set()
4374
4478
  requested_parents: set[int | None] = set()
@@ -4401,6 +4505,7 @@ class RecordTools(ToolBase):
4401
4505
  return items
4402
4506
 
4403
4507
  def _merge_department_candidate(self, merged: dict[str, JSONObject], candidate: JSONObject) -> None:
4508
+ """执行内部辅助逻辑。"""
4404
4509
  key = _department_candidate_key(candidate)
4405
4510
  if not key:
4406
4511
  return
@@ -4424,6 +4529,7 @@ class RecordTools(ToolBase):
4424
4529
  seen.add(marker)
4425
4530
 
4426
4531
  def _expand_department_ids(self, context, *, root_dept_id: int) -> set[int]: # type: ignore[no-untyped-def]
4532
+ """执行内部辅助逻辑。"""
4427
4533
  seen: set[int] = set()
4428
4534
  queue: list[int] = [root_dept_id]
4429
4535
  while queue:
@@ -4448,6 +4554,7 @@ class RecordTools(ToolBase):
4448
4554
  department_id: int | None,
4449
4555
  role_id: int | None,
4450
4556
  ) -> list[dict[str, Any]]:
4557
+ """执行内部辅助逻辑。"""
4451
4558
  current_page = 1
4452
4559
  fetched_pages = 0
4453
4560
  seen: dict[str, dict[str, Any]] = {}
@@ -4483,9 +4590,11 @@ class RecordTools(ToolBase):
4483
4590
  return list(seen.values())
4484
4591
 
4485
4592
  def _search_workspace_members(self, context, *, keyword: str) -> list[dict[str, Any]]: # type: ignore[no-untyped-def]
4593
+ """执行内部辅助逻辑。"""
4486
4594
  return self._search_workspace_directory_dimension(context, dimension="MEMBER", bucket_key="member", keyword=keyword)
4487
4595
 
4488
4596
  def _search_workspace_departments(self, context, *, keyword: str) -> list[dict[str, Any]]: # type: ignore[no-untyped-def]
4597
+ """执行内部辅助逻辑。"""
4489
4598
  return self._search_workspace_directory_dimension(context, dimension="DEPT", bucket_key="dept", keyword=keyword)
4490
4599
 
4491
4600
  def _search_workspace_directory_dimension(
@@ -4496,6 +4605,7 @@ class RecordTools(ToolBase):
4496
4605
  bucket_key: str,
4497
4606
  keyword: str,
4498
4607
  ) -> list[dict[str, Any]]:
4608
+ """执行内部辅助逻辑。"""
4499
4609
  current_page = 1
4500
4610
  fetched_pages = 0
4501
4611
  seen: dict[str, dict[str, Any]] = {}
@@ -4533,6 +4643,7 @@ class RecordTools(ToolBase):
4533
4643
  return list(seen.values())
4534
4644
 
4535
4645
  def _schema_field_family(self, field: FormField) -> str:
4646
+ """执行内部辅助逻辑。"""
4536
4647
  if self._schema_is_identifier_like(field):
4537
4648
  return "text"
4538
4649
  que_type = field.que_type
@@ -4555,6 +4666,7 @@ class RecordTools(ToolBase):
4555
4666
  return "text"
4556
4667
 
4557
4668
  def _schema_is_identifier_like(self, field: FormField, *, field_family: str | None = None) -> bool:
4669
+ """执行内部辅助逻辑。"""
4558
4670
  normalized_title = _normalize_field_lookup_key(field.que_title)
4559
4671
  if field.que_id == 0:
4560
4672
  return True
@@ -4565,6 +4677,7 @@ class RecordTools(ToolBase):
4565
4677
  return False
4566
4678
 
4567
4679
  def _schema_supported_metric_ops(self, field: FormField, *, field_family: str) -> list[str]:
4680
+ """执行内部辅助逻辑。"""
4568
4681
  if field.que_type in ATTACHMENT_QUE_TYPES | RELATION_QUE_TYPES | SUBTABLE_QUE_TYPES:
4569
4682
  return []
4570
4683
  if self._schema_is_identifier_like(field, field_family=field_family):
@@ -4576,6 +4689,7 @@ class RecordTools(ToolBase):
4576
4689
  return []
4577
4690
 
4578
4691
  def _schema_semantic_hint(self, field: FormField, *, field_family: str) -> str:
4692
+ """执行内部辅助逻辑。"""
4579
4693
  if self._schema_is_identifier_like(field, field_family=field_family):
4580
4694
  return "unknown"
4581
4695
  if field_family != "number":
@@ -4590,6 +4704,7 @@ class RecordTools(ToolBase):
4590
4704
  return "unknown"
4591
4705
 
4592
4706
  def _resolve_field_by_id(self, field_id: int | None, index: FieldIndex, *, location: str) -> FormField:
4707
+ """执行内部辅助逻辑。"""
4593
4708
  if field_id is None:
4594
4709
  raise RecordInputError(
4595
4710
  message=f"{location} requires field_id",
@@ -4614,6 +4729,7 @@ class RecordTools(ToolBase):
4614
4729
  allowed_keys: set[str],
4615
4730
  example: str,
4616
4731
  ) -> None:
4732
+ """执行内部辅助逻辑。"""
4617
4733
  unexpected_keys = sorted(str(key) for key in item.keys() if str(key) not in allowed_keys)
4618
4734
  if unexpected_keys:
4619
4735
  raise RecordInputError(
@@ -4635,6 +4751,7 @@ class RecordTools(ToolBase):
4635
4751
  value: JSONValue,
4636
4752
  location: str,
4637
4753
  ) -> JSONValue:
4754
+ """执行内部辅助逻辑。"""
4638
4755
  if op in {"is_null", "not_null"}:
4639
4756
  if value is not None:
4640
4757
  raise RecordInputError(
@@ -4765,6 +4882,7 @@ class RecordTools(ToolBase):
4765
4882
  return value
4766
4883
 
4767
4884
  def _validate_strict_date_filter_value(self, value: JSONValue, *, location: str) -> datetime:
4885
+ """执行内部辅助逻辑。"""
4768
4886
  text = _normalize_optional_text(value)
4769
4887
  if text is None:
4770
4888
  raise RecordInputError(
@@ -4784,6 +4902,7 @@ class RecordTools(ToolBase):
4784
4902
  return parsed
4785
4903
 
4786
4904
  def _compile_analyze_dimensions(self, index: FieldIndex, dimensions: list[JSONObject]) -> list[JSONObject]:
4905
+ """执行内部辅助逻辑。"""
4787
4906
  supported_buckets = {None, "day", "week", "month", "quarter", "year"}
4788
4907
  compiled: list[JSONObject] = []
4789
4908
  used_aliases: set[str] = set()
@@ -4828,6 +4947,7 @@ class RecordTools(ToolBase):
4828
4947
  return compiled
4829
4948
 
4830
4949
  def _compile_analyze_metrics(self, index: FieldIndex, metrics: list[JSONObject]) -> list[JSONObject]:
4950
+ """执行内部辅助逻辑。"""
4831
4951
  requested_metrics = metrics or [{"op": "count", "alias": "记录数"}]
4832
4952
  supported_ops = {"count", "sum", "avg", "min", "max", "distinct_count"}
4833
4953
  compiled: list[JSONObject] = []
@@ -4891,6 +5011,7 @@ class RecordTools(ToolBase):
4891
5011
  return compiled
4892
5012
 
4893
5013
  def _compile_analyze_filters(self, index: FieldIndex, filters: list[JSONObject]) -> list[JSONObject]:
5014
+ """执行内部辅助逻辑。"""
4894
5015
  supported_ops = {"eq", "neq", "in", "not_in", "gt", "gte", "lt", "lte", "between", "contains", "is_null", "not_null"}
4895
5016
  compiled: list[JSONObject] = []
4896
5017
  for idx, item in enumerate(filters):
@@ -4925,6 +5046,7 @@ class RecordTools(ToolBase):
4925
5046
  return compiled
4926
5047
 
4927
5048
  def _compile_analyze_sort(self, sort: list[JSONObject], dimensions: list[JSONObject], metrics: list[JSONObject]) -> list[JSONObject]:
5049
+ """执行内部辅助逻辑。"""
4928
5050
  dimension_aliases = {str(item["alias"]) for item in dimensions}
4929
5051
  metric_aliases = {str(item["alias"]) for item in metrics}
4930
5052
  compiled: list[JSONObject] = []
@@ -4986,6 +5108,7 @@ class RecordTools(ToolBase):
4986
5108
  output_profile: str,
4987
5109
  extra_warnings: list[JSONObject] | None = None,
4988
5110
  ) -> JSONObject:
5111
+ """执行内部辅助逻辑。"""
4989
5112
  started_at = time.perf_counter()
4990
5113
  analysis_paging = _fixed_analysis_scan_policy()
4991
5114
  page_size = int(analysis_paging["page_size"])
@@ -5207,6 +5330,7 @@ class RecordTools(ToolBase):
5207
5330
  return response
5208
5331
 
5209
5332
  def _build_analyze_group_payload(self, answer_list: list[JSONValue], dimensions: list[JSONObject]) -> JSONObject:
5333
+ """执行内部辅助逻辑。"""
5210
5334
  if not dimensions:
5211
5335
  return {}
5212
5336
  payload: JSONObject = {}
@@ -5221,6 +5345,7 @@ class RecordTools(ToolBase):
5221
5345
  return payload
5222
5346
 
5223
5347
  def _initialize_metric_states(self, metrics: list[JSONObject]) -> dict[str, JSONObject]:
5348
+ """执行内部辅助逻辑。"""
5224
5349
  states: dict[str, JSONObject] = {}
5225
5350
  for item in metrics:
5226
5351
  states[str(item["alias"])] = {
@@ -5233,9 +5358,11 @@ class RecordTools(ToolBase):
5233
5358
  return states
5234
5359
 
5235
5360
  def _analysis_group_key(self, payload: JSONObject) -> tuple[tuple[str, object], ...]:
5361
+ """执行内部辅助逻辑。"""
5236
5362
  return tuple((key, self._freeze_group_key_value(value)) for key, value in payload.items())
5237
5363
 
5238
5364
  def _freeze_group_key_value(self, value: JSONValue) -> object:
5365
+ """执行内部辅助逻辑。"""
5239
5366
  if isinstance(value, dict):
5240
5367
  return tuple((key, self._freeze_group_key_value(item)) for key, item in sorted(value.items()))
5241
5368
  if isinstance(value, list):
@@ -5243,6 +5370,7 @@ class RecordTools(ToolBase):
5243
5370
  return value
5244
5371
 
5245
5372
  def _apply_metric_states(self, states: dict[str, JSONObject], metrics: list[JSONObject], answer_list: list[JSONValue]) -> None:
5373
+ """执行内部辅助逻辑。"""
5246
5374
  for item in metrics:
5247
5375
  alias = cast(str, item["alias"])
5248
5376
  op = cast(str, item["op"])
@@ -5265,6 +5393,7 @@ class RecordTools(ToolBase):
5265
5393
  state["max"] = amount if state["max"] is None else max(float(state["max"]), amount)
5266
5394
 
5267
5395
  def _render_metric_values(self, states: dict[str, JSONObject], metrics: list[JSONObject]) -> JSONObject:
5396
+ """执行内部辅助逻辑。"""
5268
5397
  rendered: JSONObject = {}
5269
5398
  for item in metrics:
5270
5399
  alias = cast(str, item["alias"])
@@ -5287,6 +5416,7 @@ class RecordTools(ToolBase):
5287
5416
  return rendered
5288
5417
 
5289
5418
  def _matches_analyze_filters(self, answer_list: list[JSONValue], filters: list[JSONObject]) -> bool:
5419
+ """执行内部辅助逻辑。"""
5290
5420
  for item in filters:
5291
5421
  field = cast(FormField, item["field"])
5292
5422
  if not _match_analyze_filter(_extract_field_value(answer_list, field), cast(str, item["op"]), item.get("value")):
@@ -5300,6 +5430,7 @@ class RecordTools(ToolBase):
5300
5430
  dimensions: list[JSONObject],
5301
5431
  metrics: list[JSONObject],
5302
5432
  ) -> list[JSONObject]:
5433
+ """执行内部辅助逻辑。"""
5303
5434
  if not rows or not sort:
5304
5435
  if dimensions and any(item.get("bucket") for item in dimensions):
5305
5436
  return sorted(rows, key=lambda item: json.dumps(item.get("dimensions", {}), ensure_ascii=False, sort_keys=True))
@@ -5324,6 +5455,7 @@ class RecordTools(ToolBase):
5324
5455
  rows_truncated: bool,
5325
5456
  extra_warnings: list[JSONObject],
5326
5457
  ) -> list[JSONObject]:
5458
+ """执行内部辅助逻辑。"""
5327
5459
  warnings: list[JSONObject] = []
5328
5460
  warnings.extend(extra_warnings)
5329
5461
  if local_filtering:
@@ -5347,6 +5479,7 @@ class RecordTools(ToolBase):
5347
5479
  view_key: str | None,
5348
5480
  view_name: str | None,
5349
5481
  ) -> JSONObject:
5482
+ """执行内部辅助逻辑。"""
5350
5483
  if not app_key:
5351
5484
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
5352
5485
 
@@ -5410,6 +5543,7 @@ class RecordTools(ToolBase):
5410
5543
  existing_answers_override: list[JSONObject] | None = None,
5411
5544
  field_index_override: FieldIndex | None = None,
5412
5545
  ) -> JSONObject:
5546
+ """执行内部辅助逻辑。"""
5413
5547
  schema = self._get_form_schema(profile, context, app_key, force_refresh=force_refresh_form)
5414
5548
  base_index = field_index_override or _build_applicant_top_level_field_index(schema)
5415
5549
  question_relations = _collect_question_relations(schema)
@@ -5727,6 +5861,7 @@ class RecordTools(ToolBase):
5727
5861
  app_key: str,
5728
5862
  apply_id: int,
5729
5863
  ) -> list[JSONObject]:
5864
+ """执行内部辅助逻辑。"""
5730
5865
  record = self.backend.request(
5731
5866
  "GET",
5732
5867
  context,
@@ -5744,6 +5879,7 @@ class RecordTools(ToolBase):
5744
5879
  selector_index: FieldIndex,
5745
5880
  visible_question_ids: set[int],
5746
5881
  ) -> list[JSONObject]:
5882
+ """执行内部辅助逻辑。"""
5747
5883
  invalid_fields: list[JSONObject] = []
5748
5884
  if not visible_question_ids:
5749
5885
  return invalid_fields
@@ -5787,6 +5923,7 @@ class RecordTools(ToolBase):
5787
5923
  full_index: FieldIndex,
5788
5924
  skip_cells: set[tuple[int, int, int]] | None = None,
5789
5925
  ) -> list[JSONObject]:
5926
+ """执行内部辅助逻辑。"""
5790
5927
  missing_required_fields: list[JSONObject] = []
5791
5928
  skipped = skip_cells or set()
5792
5929
  answers_by_field_id = {
@@ -5884,6 +6021,7 @@ class RecordTools(ToolBase):
5884
6021
  existing_answers: list[JSONObject],
5885
6022
  patch_answers: list[JSONObject],
5886
6023
  ) -> list[JSONObject]:
6024
+ """执行内部辅助逻辑。"""
5887
6025
  merged_by_id: dict[int, JSONObject] = {}
5888
6026
  order: list[int] = []
5889
6027
  for source in (existing_answers, patch_answers):
@@ -5896,6 +6034,7 @@ class RecordTools(ToolBase):
5896
6034
  merged_by_id[que_id] = item
5897
6035
  return [merged_by_id[que_id] for que_id in order]
5898
6036
 
6037
+ @tool_cn_name("查询记录")
5899
6038
  def record_query(
5900
6039
  self,
5901
6040
  *,
@@ -5923,6 +6062,7 @@ class RecordTools(ToolBase):
5923
6062
  view_key: str | None = None,
5924
6063
  view_name: str | None = None,
5925
6064
  ) -> JSONObject:
6065
+ """执行记录相关逻辑。"""
5926
6066
  resolved_mode = _resolve_query_mode(query_mode, apply_id=apply_id, amount_column=amount_column, time_range=time_range, stat_policy=stat_policy)
5927
6067
  if resolved_mode == "summary":
5928
6068
  raise_tool_error(
@@ -5972,6 +6112,7 @@ class RecordTools(ToolBase):
5972
6112
  view_name=view_name,
5973
6113
  )
5974
6114
 
6115
+ @tool_cn_name("创建记录")
5975
6116
  def record_create(
5976
6117
  self,
5977
6118
  *,
@@ -5983,6 +6124,7 @@ class RecordTools(ToolBase):
5983
6124
  verify_write: bool = False,
5984
6125
  force_refresh_form: bool = False,
5985
6126
  ) -> JSONObject:
6127
+ """执行记录相关逻辑。"""
5986
6128
  if submit_type not in (0, 1):
5987
6129
  raise_tool_error(QingflowApiError.config_error("submit_type must be 0 or 1"))
5988
6130
 
@@ -6030,6 +6172,7 @@ class RecordTools(ToolBase):
6030
6172
  # listType 降级顺序(内部 record_get)
6031
6173
  _INTERNAL_GET_LIST_TYPE_FALLBACKS = [DEFAULT_RECORD_LIST_TYPE, 14, 1, 2, 12]
6032
6174
 
6175
+ @tool_cn_name("获取记录")
6033
6176
  def record_get(
6034
6177
  self,
6035
6178
  *,
@@ -6040,6 +6183,7 @@ class RecordTools(ToolBase):
6040
6183
  list_type: int | None,
6041
6184
  audit_node_id: int | None,
6042
6185
  ) -> JSONObject:
6186
+ """执行记录相关逻辑。"""
6043
6187
  normalized_apply_id = self._validate_app_and_record(app_key, apply_id)
6044
6188
 
6045
6189
  def runner(session_profile, context):
@@ -6088,6 +6232,7 @@ class RecordTools(ToolBase):
6088
6232
 
6089
6233
  return self._run_record_tool(profile, runner)
6090
6234
 
6235
+ @tool_cn_name("搜索记录")
6091
6236
  def record_search(
6092
6237
  self,
6093
6238
  *,
@@ -6103,6 +6248,7 @@ class RecordTools(ToolBase):
6103
6248
  view_key: str | None = None,
6104
6249
  view_name: str | None = None,
6105
6250
  ) -> JSONObject:
6251
+ """执行记录相关逻辑。"""
6106
6252
  if not app_key:
6107
6253
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
6108
6254
 
@@ -6165,6 +6311,7 @@ class RecordTools(ToolBase):
6165
6311
 
6166
6312
  return self._run_record_tool(profile, runner)
6167
6313
 
6314
+ @tool_cn_name("修改记录")
6168
6315
  def record_update(
6169
6316
  self,
6170
6317
  *,
@@ -6177,6 +6324,7 @@ class RecordTools(ToolBase):
6177
6324
  verify_write: bool = False,
6178
6325
  force_refresh_form: bool = False,
6179
6326
  ) -> JSONObject:
6327
+ """执行记录相关逻辑。"""
6180
6328
  normalized_apply_id = self._validate_app_and_record(app_key, apply_id)
6181
6329
 
6182
6330
  def runner(session_profile, context):
@@ -6227,7 +6375,9 @@ class RecordTools(ToolBase):
6227
6375
 
6228
6376
  return self._run_record_tool(profile, runner)
6229
6377
 
6378
+ @tool_cn_name("删除记录(兼容)")
6230
6379
  def record_delete(self, *, profile: str, app_key: str, apply_id: int, list_type: int) -> JSONObject:
6380
+ """执行记录相关逻辑。"""
6231
6381
  normalized_apply_id = self._validate_app_and_record(app_key, apply_id)
6232
6382
 
6233
6383
  def runner(session_profile, context):
@@ -6263,6 +6413,7 @@ class RecordTools(ToolBase):
6263
6413
  output_profile: str,
6264
6414
  list_type: int,
6265
6415
  ) -> JSONObject:
6416
+ """执行内部辅助逻辑。"""
6266
6417
  if not app_key:
6267
6418
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
6268
6419
  if apply_id is None or apply_id <= 0:
@@ -6362,6 +6513,7 @@ class RecordTools(ToolBase):
6362
6513
  view_key: str | None = None,
6363
6514
  view_name: str | None = None,
6364
6515
  ) -> JSONObject:
6516
+ """执行内部辅助逻辑。"""
6365
6517
  if not app_key:
6366
6518
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
6367
6519
  if not select_columns:
@@ -6624,6 +6776,7 @@ class RecordTools(ToolBase):
6624
6776
  return self._run_record_tool(profile, runner)
6625
6777
 
6626
6778
  def _get_form_schema(self, profile: str, context, app_key: str, *, force_refresh: bool) -> JSONObject: # type: ignore[no-untyped-def]
6779
+ """执行内部辅助逻辑。"""
6627
6780
  cache_key = (profile, app_key, "applicant_node", None)
6628
6781
  if not force_refresh and cache_key in self._form_cache:
6629
6782
  return self._form_cache[cache_key]
@@ -6638,6 +6791,7 @@ class RecordTools(ToolBase):
6638
6791
  return normalized
6639
6792
 
6640
6793
  def _get_field_index(self, profile: str, context, app_key: str, *, force_refresh: bool) -> FieldIndex: # type: ignore[no-untyped-def]
6794
+ """执行内部辅助逻辑。"""
6641
6795
  return _build_field_index(self._get_form_schema(profile, context, app_key, force_refresh=force_refresh))
6642
6796
 
6643
6797
  def _get_applicant_top_level_field_index(
@@ -6648,11 +6802,13 @@ class RecordTools(ToolBase):
6648
6802
  *,
6649
6803
  force_refresh: bool,
6650
6804
  ) -> FieldIndex:
6805
+ """执行内部辅助逻辑。"""
6651
6806
  return _build_applicant_top_level_field_index(
6652
6807
  self._get_form_schema(profile, context, app_key, force_refresh=force_refresh)
6653
6808
  )
6654
6809
 
6655
6810
  def _resolve_applicant_node(self, profile: str, context, app_key: str, *, force_refresh: bool) -> WorkflowNodeRef: # type: ignore[no-untyped-def]
6811
+ """执行内部辅助逻辑。"""
6656
6812
  cache_key = (profile, app_key)
6657
6813
  if not force_refresh and cache_key in self._applicant_node_cache:
6658
6814
  return self._applicant_node_cache[cache_key]
@@ -6673,6 +6829,7 @@ class RecordTools(ToolBase):
6673
6829
  return applicant_node
6674
6830
 
6675
6831
  def _get_view_list(self, profile: str, context, app_key: str) -> list[JSONObject]: # type: ignore[no-untyped-def]
6832
+ """执行内部辅助逻辑。"""
6676
6833
  cache_key = (profile, app_key)
6677
6834
  if cache_key in self._view_list_cache:
6678
6835
  return self._view_list_cache[cache_key]
@@ -6682,6 +6839,7 @@ class RecordTools(ToolBase):
6682
6839
  return normalized
6683
6840
 
6684
6841
  def _get_view_form_schema(self, profile: str, context, view_key: str, *, force_refresh: bool) -> JSONObject: # type: ignore[no-untyped-def]
6842
+ """执行内部辅助逻辑。"""
6685
6843
  cache_key = (profile, f"view:{view_key}", "browse_view", None)
6686
6844
  if not force_refresh and cache_key in self._form_cache:
6687
6845
  return self._form_cache[cache_key]
@@ -6698,6 +6856,7 @@ class RecordTools(ToolBase):
6698
6856
  *,
6699
6857
  force_refresh: bool = False,
6700
6858
  ) -> JSONObject | None:
6859
+ """执行内部辅助逻辑。"""
6701
6860
  cache_key = (profile, view_key)
6702
6861
  if not force_refresh and cache_key in self._view_config_cache:
6703
6862
  return self._view_config_cache[cache_key]
@@ -6730,6 +6889,7 @@ class RecordTools(ToolBase):
6730
6889
  resolved_view: AccessibleViewRoute | None = None,
6731
6890
  clear_view_caches: bool = False,
6732
6891
  ) -> None:
6892
+ """执行内部辅助逻辑。"""
6733
6893
  view_key = (
6734
6894
  resolved_view.view_selection.view_key
6735
6895
  if resolved_view is not None and resolved_view.view_selection is not None
@@ -6756,10 +6916,12 @@ class RecordTools(ToolBase):
6756
6916
  self._view_config_cache.pop(cache_key, None)
6757
6917
 
6758
6918
  def _record_preflight_used_force_refresh(self, raw_preflight: JSONObject) -> bool:
6919
+ """执行内部辅助逻辑。"""
6759
6920
  data = raw_preflight.get("data")
6760
6921
  return bool(isinstance(data, dict) and data.get("schema_force_refreshed"))
6761
6922
 
6762
6923
  def _record_preflight_suggests_stale_schema(self, plan_data: JSONObject) -> bool:
6924
+ """执行内部辅助逻辑。"""
6763
6925
  validation = plan_data.get("validation")
6764
6926
  invalid_fields = validation.get("invalid_fields") if isinstance(validation, dict) else None
6765
6927
  if not isinstance(invalid_fields, list):
@@ -6767,6 +6929,7 @@ class RecordTools(ToolBase):
6767
6929
  return any(self._field_error_suggests_stale_schema(entry) for entry in invalid_fields if isinstance(entry, dict))
6768
6930
 
6769
6931
  def _field_error_suggests_stale_schema(self, entry: JSONObject) -> bool:
6932
+ """执行内部辅助逻辑。"""
6770
6933
  error_code = _normalize_optional_text(entry.get("error_code"))
6771
6934
  if error_code == "VIEW_SCOPE_FIELD_HIDDEN":
6772
6935
  return False
@@ -6786,6 +6949,7 @@ class RecordTools(ToolBase):
6786
6949
  record: JSONObject,
6787
6950
  normalized_record: JSONObject,
6788
6951
  ) -> bool:
6952
+ """执行内部辅助逻辑。"""
6789
6953
  for field in selected_fields:
6790
6954
  if field.que_type not in SUBTABLE_QUE_TYPES:
6791
6955
  continue
@@ -6809,6 +6973,7 @@ class RecordTools(ToolBase):
6809
6973
  list_type: int,
6810
6974
  force_refresh: bool,
6811
6975
  ) -> JSONObject:
6976
+ """执行内部辅助逻辑。"""
6812
6977
  cache_key = (profile, app_key, "browse_system", list_type)
6813
6978
  if not force_refresh and cache_key in self._form_cache:
6814
6979
  return self._form_cache[cache_key]
@@ -6825,6 +6990,7 @@ class RecordTools(ToolBase):
6825
6990
  return normalized
6826
6991
 
6827
6992
  def _get_view_field_index(self, profile: str, context, view_key: str, *, force_refresh: bool) -> FieldIndex: # type: ignore[no-untyped-def]
6993
+ """执行内部辅助逻辑。"""
6828
6994
  return _build_field_index(self._get_view_form_schema(profile, context, view_key, force_refresh=force_refresh))
6829
6995
 
6830
6996
  def _get_system_browse_field_index(
@@ -6836,6 +7002,7 @@ class RecordTools(ToolBase):
6836
7002
  list_type: int,
6837
7003
  force_refresh: bool,
6838
7004
  ) -> FieldIndex:
7005
+ """执行内部辅助逻辑。"""
6839
7006
  return _build_field_index(
6840
7007
  self._get_system_browse_schema(
6841
7008
  profile,
@@ -6855,6 +7022,7 @@ class RecordTools(ToolBase):
6855
7022
  *,
6856
7023
  force_refresh: bool,
6857
7024
  ) -> FieldIndex:
7025
+ """执行内部辅助逻辑。"""
6858
7026
  return self._build_browse_write_scope(
6859
7027
  profile,
6860
7028
  context,
@@ -6872,6 +7040,7 @@ class RecordTools(ToolBase):
6872
7040
  *,
6873
7041
  force_refresh: bool,
6874
7042
  ) -> JSONObject:
7043
+ """执行内部辅助逻辑。"""
6875
7044
  applicant_index: FieldIndex | None
6876
7045
  applicant_writable_field_ids: set[int]
6877
7046
  try:
@@ -6969,6 +7138,7 @@ class RecordTools(ToolBase):
6969
7138
  app_key: str,
6970
7139
  resolved_view: AccessibleViewRoute,
6971
7140
  ) -> list[int]:
7141
+ """执行内部辅助逻辑。"""
6972
7142
  def runner(_session_profile, context):
6973
7143
  return self._derive_public_list_columns(profile, context, app_key, resolved_view)
6974
7144
 
@@ -6981,6 +7151,7 @@ class RecordTools(ToolBase):
6981
7151
  app_key: str,
6982
7152
  resolved_view: AccessibleViewRoute,
6983
7153
  ) -> list[int]:
7154
+ """执行内部辅助逻辑。"""
6984
7155
  browse_scope = self._build_browse_write_scope(
6985
7156
  profile,
6986
7157
  context,
@@ -7018,6 +7189,7 @@ class RecordTools(ToolBase):
7018
7189
  return field_ids
7019
7190
 
7020
7191
  def _get_view_question_ids(self, profile: str, context, view_key: str) -> set[int]: # type: ignore[no-untyped-def]
7192
+ """执行内部辅助逻辑。"""
7021
7193
  try:
7022
7194
  payload = self.backend.request("GET", context, f"/view/{view_key}/question")
7023
7195
  except QingflowApiError as exc:
@@ -7045,6 +7217,7 @@ class RecordTools(ToolBase):
7045
7217
  schema_mode: str,
7046
7218
  resolved_view: AccessibleViewRoute | None,
7047
7219
  ) -> list[FormField]:
7220
+ """执行内部辅助逻辑。"""
7048
7221
  return list(index.by_id.values())
7049
7222
 
7050
7223
  def _probe_list_type_access(
@@ -7054,6 +7227,7 @@ class RecordTools(ToolBase):
7054
7227
  app_key: str,
7055
7228
  list_type: int,
7056
7229
  ) -> bool:
7230
+ """执行内部辅助逻辑。"""
7057
7231
  try:
7058
7232
  self.backend.request(
7059
7233
  "POST",
@@ -7078,6 +7252,7 @@ class RecordTools(ToolBase):
7078
7252
  view_name: str | None,
7079
7253
  allow_default: bool,
7080
7254
  ) -> tuple[AccessibleViewRoute, list[JSONObject]]:
7255
+ """执行内部辅助逻辑。"""
7081
7256
  def runner(_session_profile, context):
7082
7257
  return self._resolve_accessible_view_route(
7083
7258
  profile,
@@ -7104,6 +7279,7 @@ class RecordTools(ToolBase):
7104
7279
  view_name: str | None,
7105
7280
  allow_default: bool,
7106
7281
  ) -> tuple[AccessibleViewRoute, list[JSONObject]]:
7282
+ """执行内部辅助逻辑。"""
7107
7283
  warnings: list[JSONObject] = []
7108
7284
  normalized_view_id = _normalize_optional_text(view_id)
7109
7285
  if normalized_view_id:
@@ -7209,6 +7385,7 @@ class RecordTools(ToolBase):
7209
7385
  view_key: str | None,
7210
7386
  view_name: str | None,
7211
7387
  ) -> ViewSelection | None:
7388
+ """执行内部辅助逻辑。"""
7212
7389
  requested_key = _normalize_optional_text(view_key)
7213
7390
  requested_name = _normalize_optional_text(view_name)
7214
7391
  if requested_key is None and requested_name is None:
@@ -7253,6 +7430,7 @@ class RecordTools(ToolBase):
7253
7430
  )
7254
7431
 
7255
7432
  def _get_department_member_ids(self, context, dept_id: int) -> set[int]: # type: ignore[no-untyped-def]
7433
+ """执行内部辅助逻辑。"""
7256
7434
  page_num = 1
7257
7435
  page_size = 200
7258
7436
  member_ids: set[int] = set()
@@ -7288,6 +7466,7 @@ class RecordTools(ToolBase):
7288
7466
  view_selection: ViewSelection | None,
7289
7467
  dept_member_cache: dict[int, set[int]],
7290
7468
  ) -> bool:
7469
+ """执行内部辅助逻辑。"""
7291
7470
  if view_selection is None or not view_selection.conditions:
7292
7471
  return True
7293
7472
  for group in view_selection.conditions:
@@ -7312,6 +7491,7 @@ class RecordTools(ToolBase):
7312
7491
  arguments: JSONObject,
7313
7492
  view_selection: ViewSelection | None,
7314
7493
  ) -> JSONObject:
7494
+ """执行内部辅助逻辑。"""
7315
7495
  routed_mode = _resolve_query_mode(
7316
7496
  str(arguments.get("query_mode", "auto")),
7317
7497
  apply_id=_coerce_count(arguments.get("apply_id")),
@@ -7376,6 +7556,7 @@ class RecordTools(ToolBase):
7376
7556
  search_que_ids: list[int] | None,
7377
7557
  list_type: int,
7378
7558
  ) -> JSONObject:
7559
+ """执行内部辅助逻辑。"""
7379
7560
  if view_selection is not None and _is_board_view_type(view_selection.view_type):
7380
7561
  return self._search_board_view_page(
7381
7562
  context,
@@ -7406,6 +7587,7 @@ class RecordTools(ToolBase):
7406
7587
  return result if isinstance(result, dict) else {}
7407
7588
 
7408
7589
  def _should_retry_list_type_fallback(self, error: QingflowApiError) -> bool:
7590
+ """执行内部辅助逻辑。"""
7409
7591
  if error.backend_code in {40002, 40027, 404}:
7410
7592
  return True
7411
7593
  if error.http_status in {404, 500}:
@@ -7424,6 +7606,7 @@ class RecordTools(ToolBase):
7424
7606
  list_type: int,
7425
7607
  include_list_type: bool,
7426
7608
  ) -> JSONObject:
7609
+ """执行内部辅助逻辑。"""
7427
7610
  body: JSONObject = {"pageNum": page_num, "pageSize": page_size}
7428
7611
  if include_list_type:
7429
7612
  body["type"] = list_type
@@ -7453,6 +7636,7 @@ class RecordTools(ToolBase):
7453
7636
  return body
7454
7637
 
7455
7638
  def _get_board_lane_ids(self, context, *, view_key: str) -> list[int]: # type: ignore[no-untyped-def]
7639
+ """执行内部辅助逻辑。"""
7456
7640
  payload = self.backend.request(
7457
7641
  "GET",
7458
7642
  context,
@@ -7485,6 +7669,7 @@ class RecordTools(ToolBase):
7485
7669
  offset: int,
7486
7670
  limit: int,
7487
7671
  ) -> list[JSONObject]:
7672
+ """执行内部辅助逻辑。"""
7488
7673
  if limit <= 0:
7489
7674
  return []
7490
7675
  request_page_size = max(_coerce_count(filter_payload.get("pageSize")) or 1, 1)
@@ -7532,6 +7717,7 @@ class RecordTools(ToolBase):
7532
7717
  sorts: list[JSONObject],
7533
7718
  search_que_ids: list[int] | None,
7534
7719
  ) -> JSONObject:
7720
+ """执行内部辅助逻辑。"""
7535
7721
  filter_payload = self._build_view_filter_payload(
7536
7722
  page_num=page_num,
7537
7723
  page_size=page_size,
@@ -7628,6 +7814,7 @@ class RecordTools(ToolBase):
7628
7814
  resolution_state: LookupResolutionState | None = None,
7629
7815
  field_index_override: FieldIndex | None = None,
7630
7816
  ) -> list[JSONObject]:
7817
+ """执行内部辅助逻辑。"""
7631
7818
  if not app_key:
7632
7819
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
7633
7820
  if not answers and not fields:
@@ -7674,6 +7861,7 @@ class RecordTools(ToolBase):
7674
7861
  *,
7675
7862
  resolution_state: LookupResolutionState | None = None,
7676
7863
  ) -> JSONObject | None: # type: ignore[no-untyped-def]
7864
+ """执行内部辅助逻辑。"""
7677
7865
  field = self._resolve_field_from_answer_item(item, index)
7678
7866
  if field.que_type in SUBTABLE_QUE_TYPES:
7679
7867
  table_values_input: JSONValue = item.get("tableValues")
@@ -7747,6 +7935,7 @@ class RecordTools(ToolBase):
7747
7935
  *,
7748
7936
  resolution_state: LookupResolutionState | None = None,
7749
7937
  ) -> JSONObject | None: # type: ignore[no-untyped-def]
7938
+ """执行内部辅助逻辑。"""
7750
7939
  field = self._resolve_field_selector(field_selector, index, location="fields")
7751
7940
  if field.que_type in SUBTABLE_QUE_TYPES:
7752
7941
  return {
@@ -7802,6 +7991,7 @@ class RecordTools(ToolBase):
7802
7991
  parent_field: FormField | None = None,
7803
7992
  row_ordinal: int | None = None,
7804
7993
  ) -> JSONObject | None:
7994
+ """执行内部辅助逻辑。"""
7805
7995
  values: list[JSONObject] = []
7806
7996
  refer_values: list[JSONObject] = []
7807
7997
  for raw_value in _expand_values(raw_values):
@@ -7830,6 +8020,7 @@ class RecordTools(ToolBase):
7830
8020
  }
7831
8021
 
7832
8022
  def _raise_if_verify_unsupported_write_field(self, field: FormField, raw_value: JSONValue, *, location: str) -> None:
8023
+ """执行内部辅助逻辑。"""
7833
8024
  if field.que_type not in VERIFY_UNSUPPORTED_WRITE_QUE_TYPES:
7834
8025
  return
7835
8026
  raise RecordInputError(
@@ -7854,6 +8045,7 @@ class RecordTools(ToolBase):
7854
8045
  resolution_state: LookupResolutionState | None = None,
7855
8046
  location: str = "field",
7856
8047
  ) -> list[JSONObject]:
8048
+ """执行内部辅助逻辑。"""
7857
8049
  if field.que_type in SINGLE_SELECT_QUE_TYPES:
7858
8050
  return [_option_value(raw_values[0], field)]
7859
8051
  if field.que_type in MULTI_SELECT_QUE_TYPES:
@@ -7906,6 +8098,7 @@ class RecordTools(ToolBase):
7906
8098
  location: str,
7907
8099
  resolution_state: LookupResolutionState | None = None,
7908
8100
  ) -> list[list[JSONObject]]:
8101
+ """执行内部辅助逻辑。"""
7909
8102
  row_values = raw_rows
7910
8103
  if isinstance(raw_rows, dict):
7911
8104
  if "rows" in raw_rows:
@@ -7950,6 +8143,7 @@ class RecordTools(ToolBase):
7950
8143
  location: str,
7951
8144
  resolution_state: LookupResolutionState | None = None,
7952
8145
  ) -> list[JSONObject]:
8146
+ """执行内部辅助逻辑。"""
7953
8147
  row_id: int | None = None
7954
8148
  normalized_cells: list[JSONObject] = []
7955
8149
  if isinstance(row, dict):
@@ -8068,6 +8262,7 @@ class RecordTools(ToolBase):
8068
8262
  parent_field: FormField | None = None,
8069
8263
  row_ordinal: int | None = None,
8070
8264
  ) -> JSONObject | None:
8265
+ """执行内部辅助逻辑。"""
8071
8266
  field = self._resolve_field_from_answer_item(item, subtable_index)
8072
8267
  if field.que_type in SUBTABLE_QUE_TYPES:
8073
8268
  raise RecordInputError(
@@ -8132,6 +8327,7 @@ class RecordTools(ToolBase):
8132
8327
  parent_field: FormField | None = None,
8133
8328
  row_ordinal: int | None = None,
8134
8329
  ) -> JSONObject | None:
8330
+ """执行内部辅助逻辑。"""
8135
8331
  field = self._resolve_field_selector(field_selector, subtable_index, location=location)
8136
8332
  if field.que_type in SUBTABLE_QUE_TYPES:
8137
8333
  raise RecordInputError(
@@ -8171,6 +8367,7 @@ class RecordTools(ToolBase):
8171
8367
  }
8172
8368
 
8173
8369
  def _subtable_field_index(self, table_field: FormField) -> FieldIndex:
8370
+ """执行内部辅助逻辑。"""
8174
8371
  raw = table_field.raw if isinstance(table_field.raw, dict) else {}
8175
8372
  schema: JSONObject = {}
8176
8373
  if isinstance(raw.get("subQuestions"), list):
@@ -8188,6 +8385,7 @@ class RecordTools(ToolBase):
8188
8385
  return index
8189
8386
 
8190
8387
  def _subtable_field_index_optional(self, table_field: FormField | None) -> FieldIndex | None:
8388
+ """执行内部辅助逻辑。"""
8191
8389
  if table_field is None:
8192
8390
  return None
8193
8391
  try:
@@ -8196,6 +8394,7 @@ class RecordTools(ToolBase):
8196
8394
  return None
8197
8395
 
8198
8396
  def _run_record_tool(self, profile: str, func, *, require_workspace: bool = True): # type: ignore[no-untyped-def]
8397
+ """执行内部辅助逻辑。"""
8199
8398
  try:
8200
8399
  return self._run(profile, func, require_workspace=require_workspace)
8201
8400
  except RecordInputError as error:
@@ -8213,6 +8412,7 @@ class RecordTools(ToolBase):
8213
8412
  )
8214
8413
 
8215
8414
  def _request_route_payload(self, context) -> JSONObject: # type: ignore[no-untyped-def]
8415
+ """执行内部辅助逻辑。"""
8216
8416
  describe_route = getattr(self.backend, "describe_route", None)
8217
8417
  if callable(describe_route):
8218
8418
  payload = describe_route(context)
@@ -8225,6 +8425,7 @@ class RecordTools(ToolBase):
8225
8425
  }
8226
8426
 
8227
8427
  def _normalize_public_output_profile(self, output_profile: str, *, allow_normalized: bool = False) -> str:
8428
+ """执行内部辅助逻辑。"""
8228
8429
  normalized = (output_profile or "normal").strip().lower()
8229
8430
  allowed = {"normal", "verbose"}
8230
8431
  if allow_normalized:
@@ -8235,6 +8436,7 @@ class RecordTools(ToolBase):
8235
8436
  return normalized
8236
8437
 
8237
8438
  def _normalize_record_list_where(self, where: list[JSONObject]) -> list[JSONObject]:
8439
+ """执行内部辅助逻辑。"""
8238
8440
  normalized: list[JSONObject] = []
8239
8441
  for idx, item in enumerate(where):
8240
8442
  if not isinstance(item, dict):
@@ -8260,6 +8462,7 @@ class RecordTools(ToolBase):
8260
8462
  return normalized
8261
8463
 
8262
8464
  def _normalize_record_list_order_by(self, order_by: list[JSONObject]) -> list[JSONObject]:
8465
+ """执行内部辅助逻辑。"""
8263
8466
  normalized: list[JSONObject] = []
8264
8467
  for idx, item in enumerate(order_by):
8265
8468
  if not isinstance(item, dict):
@@ -8280,6 +8483,7 @@ class RecordTools(ToolBase):
8280
8483
  return normalized
8281
8484
 
8282
8485
  def _normalize_record_write_submit_type(self, submit_type: str | int) -> int:
8486
+ """执行内部辅助逻辑。"""
8283
8487
  if isinstance(submit_type, int):
8284
8488
  if submit_type in {0, 1}:
8285
8489
  return submit_type
@@ -8292,6 +8496,7 @@ class RecordTools(ToolBase):
8292
8496
  raise_tool_error(QingflowApiError.config_error("submit_type must be save or submit"))
8293
8497
 
8294
8498
  def _normalize_record_write_clauses(self, clauses: list[JSONObject], *, location: str) -> list[JSONObject]:
8499
+ """执行内部辅助逻辑。"""
8295
8500
  normalized: list[JSONObject] = []
8296
8501
  for idx, item in enumerate(clauses):
8297
8502
  if not isinstance(item, dict):
@@ -8319,6 +8524,7 @@ class RecordTools(ToolBase):
8319
8524
  submit_type: int,
8320
8525
  selection: JSONObject | None = None,
8321
8526
  ) -> JSONObject:
8527
+ """执行内部辅助逻辑。"""
8322
8528
  payload: JSONObject = {
8323
8529
  "operation": operation,
8324
8530
  "record_id": record_id,
@@ -8337,6 +8543,7 @@ class RecordTools(ToolBase):
8337
8543
  fields: JSONObject,
8338
8544
  selector_index: FieldIndex,
8339
8545
  ) -> tuple[list[JSONObject], JSONObject]:
8546
+ """执行内部辅助逻辑。"""
8340
8547
  canonical_answers: list[JSONObject] = []
8341
8548
  for item in answers:
8342
8549
  if not isinstance(item, dict):
@@ -8358,6 +8565,7 @@ class RecordTools(ToolBase):
8358
8565
  return canonical_answers, canonical_fields
8359
8566
 
8360
8567
  def _record_write_human_review_payload(self, operation: str, *, enabled: bool) -> JSONObject | None:
8568
+ """执行内部辅助逻辑。"""
8361
8569
  if not enabled:
8362
8570
  return None
8363
8571
  return {
@@ -8375,6 +8583,7 @@ class RecordTools(ToolBase):
8375
8583
  record_id: int | None,
8376
8584
  selection: JSONObject | None,
8377
8585
  ) -> None:
8586
+ """执行内部辅助逻辑。"""
8378
8587
  if exc.backend_code != 40002:
8379
8588
  raise exc
8380
8589
  raise_tool_error(
@@ -8409,6 +8618,7 @@ class RecordTools(ToolBase):
8409
8618
  human_review: bool,
8410
8619
  target_resource: JSONObject,
8411
8620
  ) -> JSONObject:
8621
+ """执行内部辅助逻辑。"""
8412
8622
  plan_data = cast(JSONObject, raw_preflight.get("data", {}))
8413
8623
  validation = cast(JSONObject, plan_data.get("validation", {}))
8414
8624
  field_errors = self._record_write_public_field_errors(plan_data)
@@ -8454,6 +8664,7 @@ class RecordTools(ToolBase):
8454
8664
  human_review: bool,
8455
8665
  target_resource: JSONObject,
8456
8666
  ) -> JSONObject:
8667
+ """执行内部辅助逻辑。"""
8457
8668
  plan_data = cast(JSONObject, raw_preflight.get("data", {}))
8458
8669
  validation = cast(JSONObject, plan_data.get("validation", {}))
8459
8670
  resolved_fields = cast(list[JSONObject], plan_data.get("lookup_resolved_fields", []))
@@ -8496,6 +8707,7 @@ class RecordTools(ToolBase):
8496
8707
  human_review: bool,
8497
8708
  preflight: JSONObject | None,
8498
8709
  ) -> JSONObject:
8710
+ """执行内部辅助逻辑。"""
8499
8711
  preflight_data = cast(JSONObject, preflight.get("data", {})) if isinstance(preflight, dict) else {}
8500
8712
  validation = cast(JSONObject, preflight_data.get("validation", {}))
8501
8713
  warnings_payload = validation.get("warnings", [])
@@ -8547,6 +8759,7 @@ class RecordTools(ToolBase):
8547
8759
  output_profile: str,
8548
8760
  human_review: bool,
8549
8761
  ) -> JSONObject:
8762
+ """执行内部辅助逻辑。"""
8550
8763
  error_payload: JSONObject = {
8551
8764
  "error_code": "RECORD_WRITE_EXECUTION_FAILED",
8552
8765
  "message": str(exc),
@@ -8598,6 +8811,7 @@ class RecordTools(ToolBase):
8598
8811
  return response
8599
8812
 
8600
8813
  def _record_write_public_field_errors(self, plan_data: JSONObject) -> list[JSONObject]:
8814
+ """执行内部辅助逻辑。"""
8601
8815
  existing = plan_data.get("field_errors")
8602
8816
  if isinstance(existing, list):
8603
8817
  return [cast(JSONObject, item) for item in existing if isinstance(item, dict)]
@@ -8618,6 +8832,7 @@ class RecordTools(ToolBase):
8618
8832
  missing_required_fields: list[JSONObject],
8619
8833
  readonly_or_system_fields: list[JSONObject],
8620
8834
  ) -> list[JSONObject]:
8835
+ """执行内部辅助逻辑。"""
8621
8836
  errors: list[JSONObject] = []
8622
8837
  for item in invalid_fields:
8623
8838
  payload: JSONObject = {
@@ -8686,6 +8901,7 @@ class RecordTools(ToolBase):
8686
8901
  return errors
8687
8902
 
8688
8903
  def _record_delete_many(self, *, profile: str, app_key: str, record_ids: list[int]) -> JSONObject:
8904
+ """执行内部辅助逻辑。"""
8689
8905
  if not app_key:
8690
8906
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
8691
8907
  normalized_ids = [item for item in record_ids if isinstance(item, int) and item > 0]
@@ -8711,6 +8927,7 @@ class RecordTools(ToolBase):
8711
8927
  return self._run_record_tool(profile, runner)
8712
8928
 
8713
8929
  def _resolve_field_selector(self, selector: str | int | None, index: FieldIndex, *, location: str) -> FormField:
8930
+ """执行内部辅助逻辑。"""
8714
8931
  if selector is None:
8715
8932
  raise RecordInputError(
8716
8933
  message=f"{location} requires a field selector",
@@ -8796,6 +9013,7 @@ class RecordTools(ToolBase):
8796
9013
  matches: list[SubtableLeafRef],
8797
9014
  matched_via: str,
8798
9015
  ) -> RecordInputError:
9016
+ """执行内部辅助逻辑。"""
8799
9017
  if len(matches) > 1:
8800
9018
  return RecordInputError(
8801
9019
  message=f"{location} field '{requested}' matches subtable leaf fields under multiple parent tables",
@@ -8840,6 +9058,7 @@ class RecordTools(ToolBase):
8840
9058
  )
8841
9059
 
8842
9060
  def _resolve_field_from_answer_item(self, item: JSONObject, index: FieldIndex) -> FormField:
9061
+ """执行内部辅助逻辑。"""
8843
9062
  for key in ("queId", "que_id", "queTitle", "que_title", "field_id", "fieldId"):
8844
9063
  if key in item:
8845
9064
  return self._resolve_field_selector(cast(str | int, item[key]), index, location="answers")
@@ -8857,6 +9076,7 @@ class RecordTools(ToolBase):
8857
9076
  max_columns: int | None,
8858
9077
  default_limit: int,
8859
9078
  ) -> list[FormField]:
9079
+ """执行内部辅助逻辑。"""
8860
9080
  if not selectors:
8861
9081
  raise_tool_error(QingflowApiError.config_error("select_columns is required"))
8862
9082
  limit = _bounded_column_limit(max_columns, default_limit=default_limit, hard_limit=default_limit)
@@ -8881,6 +9101,7 @@ class RecordTools(ToolBase):
8881
9101
  *,
8882
9102
  max_columns: int | None,
8883
9103
  ) -> list[FormField]:
9104
+ """执行内部辅助逻辑。"""
8884
9105
  if selectors:
8885
9106
  return self._resolve_select_columns(
8886
9107
  selectors,
@@ -8904,6 +9125,7 @@ class RecordTools(ToolBase):
8904
9125
  return candidates[:limit]
8905
9126
 
8906
9127
  def _resolve_match_rules(self, context, filters: list[JSONObject], index: FieldIndex) -> list[JSONObject]: # type: ignore[no-untyped-def]
9128
+ """执行内部辅助逻辑。"""
8907
9129
  rules: list[JSONObject] = []
8908
9130
  for item in filters:
8909
9131
  if not isinstance(item, dict):
@@ -8972,6 +9194,7 @@ class RecordTools(ToolBase):
8972
9194
  return rules
8973
9195
 
8974
9196
  def _build_department_filter_rule(self, context, field: FormField, item: JSONObject) -> JSONObject | None: # type: ignore[no-untyped-def]
9197
+ """执行内部辅助逻辑。"""
8975
9198
  raw_value: JSONValue | None = None
8976
9199
  for key in ("search_options", "searchOptions", "search_keys", "searchKeys", "search_key", "searchKey", "value", "values"):
8977
9200
  if key in item:
@@ -8986,6 +9209,7 @@ class RecordTools(ToolBase):
8986
9209
  return _department_filter_rule(field.que_id, field.que_type, details, judge_type=judge_type)
8987
9210
 
8988
9211
  def _resolve_department_filter_details(self, context, raw_value: JSONValue) -> list[JSONObject]: # type: ignore[no-untyped-def]
9212
+ """执行内部辅助逻辑。"""
8989
9213
  values = raw_value if isinstance(raw_value, list) else [raw_value]
8990
9214
  details: list[JSONObject] = []
8991
9215
  seen: set[int] = set()
@@ -8999,6 +9223,7 @@ class RecordTools(ToolBase):
8999
9223
  return details
9000
9224
 
9001
9225
  def _resolve_department_filter_detail(self, context, raw_value: JSONValue) -> JSONObject: # type: ignore[no-untyped-def]
9226
+ """执行内部辅助逻辑。"""
9002
9227
  if isinstance(raw_value, dict):
9003
9228
  dept_id = _coerce_count(raw_value.get("id", raw_value.get("deptId")))
9004
9229
  if dept_id is not None:
@@ -9029,9 +9254,11 @@ class RecordTools(ToolBase):
9029
9254
  return self._lookup_department_filter_detail(context, keyword)
9030
9255
 
9031
9256
  def _lookup_department_filter_detail(self, context, keyword: str) -> JSONObject: # type: ignore[no-untyped-def]
9257
+ """执行内部辅助逻辑。"""
9032
9258
  return self._lookup_department_detail(context, keyword, purpose="filter")
9033
9259
 
9034
9260
  def _candidate_lookup_sample(self, candidates: list[JSONObject], *, kind: str) -> list[JSONObject]:
9261
+ """执行内部辅助逻辑。"""
9035
9262
  sample: list[JSONObject] = []
9036
9263
  for item in candidates[:10]:
9037
9264
  if kind == "relation":
@@ -9066,6 +9293,7 @@ class RecordTools(ToolBase):
9066
9293
  value: JSONValue,
9067
9294
  error: QingflowApiError,
9068
9295
  ) -> None:
9296
+ """执行内部辅助逻辑。"""
9069
9297
  field_kind = "member" if kind == "member" else "department"
9070
9298
  raise RecordInputError(
9071
9299
  message=f"{field_kind} candidates for field '{field.que_title}' could not be loaded",
@@ -9088,6 +9316,7 @@ class RecordTools(ToolBase):
9088
9316
  text_keys: tuple[str, ...],
9089
9317
  fallback_id_keys: tuple[str, ...] = (),
9090
9318
  ) -> str:
9319
+ """执行内部辅助逻辑。"""
9091
9320
  if isinstance(value, dict):
9092
9321
  for key in text_keys:
9093
9322
  text = _normalize_optional_text(value.get(key))
@@ -9111,6 +9340,7 @@ class RecordTools(ToolBase):
9111
9340
  keyword: str,
9112
9341
  state: LookupResolutionState,
9113
9342
  ) -> list[JSONObject]:
9343
+ """执行内部辅助逻辑。"""
9114
9344
  scope = field.member_select_scope if isinstance(field.member_select_scope, dict) else {}
9115
9345
  use_external = bool(
9116
9346
  isinstance(scope.get("externalMemberList"), list) and scope.get("externalMemberList")
@@ -9132,6 +9362,7 @@ class RecordTools(ToolBase):
9132
9362
  return self._normalize_backend_member_candidates(result, external=use_external)
9133
9363
 
9134
9364
  def _member_confirmation_candidates(self, candidates: list[JSONObject]) -> list[JSONObject]:
9365
+ """执行内部辅助逻辑。"""
9135
9366
  payloads: list[JSONObject] = []
9136
9367
  for candidate in candidates[:LOOKUP_CONFIRMATION_CANDIDATE_LIMIT]:
9137
9368
  source_labels = []
@@ -9169,6 +9400,7 @@ class RecordTools(ToolBase):
9169
9400
  resolution_state: LookupResolutionState | None = None,
9170
9401
  location: str,
9171
9402
  ) -> JSONObject | None: # type: ignore[no-untyped-def]
9403
+ """执行内部辅助逻辑。"""
9172
9404
  explicit_member_id: int | None = None
9173
9405
  explicit_user_id: str | None = None
9174
9406
  explicit_email: str | None = None
@@ -9298,6 +9530,7 @@ class RecordTools(ToolBase):
9298
9530
  return None
9299
9531
 
9300
9532
  def _match_member_candidates(self, candidates: list[JSONObject], value: JSONValue) -> list[JSONObject]:
9533
+ """执行内部辅助逻辑。"""
9301
9534
  member_id: int | None = None
9302
9535
  user_id: str | None = None
9303
9536
  email: str | None = None
@@ -9339,6 +9572,7 @@ class RecordTools(ToolBase):
9339
9572
  return matches
9340
9573
 
9341
9574
  def _lookup_department_detail(self, context, keyword: str, *, purpose: str) -> JSONObject: # type: ignore[no-untyped-def]
9575
+ """执行内部辅助逻辑。"""
9342
9576
  payload = self.backend.request(
9343
9577
  "GET",
9344
9578
  context,
@@ -9372,6 +9606,7 @@ class RecordTools(ToolBase):
9372
9606
  return {"id": dept_id, "value": _stringify_json(matched.get("deptName", matched.get("value", matched.get("name", dept_id))))}
9373
9607
 
9374
9608
  def _match_department_candidates(self, candidates: list[JSONObject], value: JSONValue) -> list[JSONObject]:
9609
+ """执行内部辅助逻辑。"""
9375
9610
  dept_id: int | None = None
9376
9611
  display: str | None = None
9377
9612
  if isinstance(value, dict):
@@ -9401,6 +9636,7 @@ class RecordTools(ToolBase):
9401
9636
  keyword: str,
9402
9637
  state: LookupResolutionState,
9403
9638
  ) -> list[JSONObject]:
9639
+ """执行内部辅助逻辑。"""
9404
9640
  scope = field.dept_select_scope if isinstance(field.dept_select_scope, dict) else {}
9405
9641
  external = bool(
9406
9642
  isinstance(scope.get("externalDepartList"), list) and scope.get("externalDepartList")
@@ -9411,6 +9647,7 @@ class RecordTools(ToolBase):
9411
9647
  return self._normalize_backend_department_candidates(result, external=external)
9412
9648
 
9413
9649
  def _department_confirmation_candidates(self, candidates: list[JSONObject]) -> list[JSONObject]:
9650
+ """执行内部辅助逻辑。"""
9414
9651
  payloads: list[JSONObject] = []
9415
9652
  for candidate in candidates[:LOOKUP_CONFIRMATION_CANDIDATE_LIMIT]:
9416
9653
  payloads.append(
@@ -9435,6 +9672,7 @@ class RecordTools(ToolBase):
9435
9672
  resolution_state: LookupResolutionState | None = None,
9436
9673
  location: str,
9437
9674
  ) -> JSONObject | None: # type: ignore[no-untyped-def]
9675
+ """执行内部辅助逻辑。"""
9438
9676
  explicit_dept_id: int | None = None
9439
9677
  explicit_label: str | None = None
9440
9678
  if isinstance(value, dict):
@@ -9577,6 +9815,7 @@ class RecordTools(ToolBase):
9577
9815
  parent_field: FormField | None = None,
9578
9816
  row_ordinal: int | None = None,
9579
9817
  ) -> tuple[JSONObject | None, JSONObject | None]:
9818
+ """执行内部辅助逻辑。"""
9580
9819
  explicit_apply_id: str | None = None
9581
9820
  keyword: str | None = None
9582
9821
  if isinstance(value, dict):
@@ -9707,6 +9946,7 @@ class RecordTools(ToolBase):
9707
9946
  return None, None
9708
9947
 
9709
9948
  def _resolve_filter_field_entries(self, filters: list[JSONObject], index: FieldIndex) -> list[JSONObject]:
9949
+ """执行内部辅助逻辑。"""
9710
9950
  entries: list[JSONObject] = []
9711
9951
  for item in filters:
9712
9952
  if not isinstance(item, dict):
@@ -9719,6 +9959,7 @@ class RecordTools(ToolBase):
9719
9959
  return entries
9720
9960
 
9721
9961
  def _resolve_sorts(self, sorts: list[JSONObject], index: FieldIndex) -> list[JSONObject]:
9962
+ """执行内部辅助逻辑。"""
9722
9963
  resolved: list[JSONObject] = []
9723
9964
  for item in sorts:
9724
9965
  if not isinstance(item, dict):
@@ -9732,6 +9973,7 @@ class RecordTools(ToolBase):
9732
9973
  return resolved
9733
9974
 
9734
9975
  def _resolve_time_range_column(self, time_range: JSONObject, index: FieldIndex) -> FormField | None:
9976
+ """执行内部辅助逻辑。"""
9735
9977
  if not time_range or not isinstance(time_range, dict):
9736
9978
  return None
9737
9979
  column = time_range.get("column")
@@ -9740,6 +9982,7 @@ class RecordTools(ToolBase):
9740
9982
  return self._resolve_field_selector(cast(str | int, column), index, location="time_range.column")
9741
9983
 
9742
9984
  def _build_time_range_filter(self, time_range: JSONObject, field: FormField) -> JSONObject | None:
9985
+ """执行内部辅助逻辑。"""
9743
9986
  if not time_range:
9744
9987
  return None
9745
9988
  value_from = time_range.get("from")
@@ -9761,6 +10004,7 @@ class RecordTools(ToolBase):
9761
10004
  time_range: JSONObject,
9762
10005
  field: FormField | None,
9763
10006
  ) -> list[JSONObject]:
10007
+ """执行内部辅助逻辑。"""
9764
10008
  if field is None:
9765
10009
  return match_rules
9766
10010
  time_rule = self._build_time_range_filter(time_range, field)
@@ -9776,6 +10020,7 @@ class RecordTools(ToolBase):
9776
10020
  return [*match_rules, time_rule]
9777
10021
 
9778
10022
  def _collect_write_plan_field_refs(self, *, fields: JSONObject, answers: list[JSONObject], index: FieldIndex) -> list[JSONObject]:
10023
+ """执行内部辅助逻辑。"""
9779
10024
  refs: list[JSONObject] = []
9780
10025
  for field_key in fields.keys():
9781
10026
  refs.append(self._resolve_write_plan_field_ref("fields", field_key, index))
@@ -9792,6 +10037,7 @@ class RecordTools(ToolBase):
9792
10037
  return refs
9793
10038
 
9794
10039
  def _resolve_write_plan_field_ref(self, source: str, requested: str, index: FieldIndex) -> JSONObject:
10040
+ """执行内部辅助逻辑。"""
9795
10041
  try:
9796
10042
  field = self._resolve_field_selector(requested, index, location=source)
9797
10043
  return {
@@ -9823,6 +10069,7 @@ class RecordTools(ToolBase):
9823
10069
  }
9824
10070
 
9825
10071
  def _validate_app_and_record(self, app_key: str, apply_id: int | str) -> int:
10072
+ """执行内部辅助逻辑。"""
9826
10073
  if not app_key:
9827
10074
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
9828
10075
  normalized_apply_id = _coerce_count(apply_id)
@@ -9831,6 +10078,7 @@ class RecordTools(ToolBase):
9831
10078
  return normalized_apply_id
9832
10079
 
9833
10080
  def _validate_record_write(self, app_key: str, answers: list[JSONObject], apply_id: int | None = None) -> None:
10081
+ """执行内部辅助逻辑。"""
9834
10082
  if not app_key:
9835
10083
  raise_tool_error(QingflowApiError.config_error("app_key is required"))
9836
10084
  if apply_id is not None and apply_id <= 0:
@@ -9848,6 +10096,7 @@ class RecordTools(ToolBase):
9848
10096
  index: FieldIndex,
9849
10097
  verify_list_type: int = DEFAULT_RECORD_LIST_TYPE,
9850
10098
  ) -> JSONObject:
10099
+ """执行内部辅助逻辑。"""
9851
10100
  if apply_id is None:
9852
10101
  return {
9853
10102
  "verified": False,
@@ -9942,6 +10191,7 @@ class RecordTools(ToolBase):
9942
10191
  apply_id: int,
9943
10192
  original_error: QingflowApiError,
9944
10193
  ) -> JSONObject:
10194
+ """执行内部辅助逻辑。"""
9945
10195
  for page_num in range(1, VERIFY_TASK_FALLBACK_MAX_PAGES + 1):
9946
10196
  task_page = self.backend.request(
9947
10197
  "POST",
@@ -10013,6 +10263,7 @@ class RecordTools(ToolBase):
10013
10263
  empty_fields: list[JSONObject],
10014
10264
  count_mismatches: list[JSONObject],
10015
10265
  ) -> None:
10266
+ """执行内部辅助逻辑。"""
10016
10267
  field_payload = _field_ref_payload(field) if field is not None else {"que_id": None}
10017
10268
  if not actual_rows:
10018
10269
  empty_fields.append(field_payload)
@@ -10090,6 +10341,7 @@ class RecordTools(ToolBase):
10090
10341
  )
10091
10342
 
10092
10343
  def _score_field_matches(self, requested: str, index: FieldIndex, *, fuzzy: bool, top_k: int) -> list[JSONObject]:
10344
+ """执行内部辅助逻辑。"""
10093
10345
  requested_text = requested.strip()
10094
10346
  requested_key = _normalize_field_lookup_key(requested_text)
10095
10347
  if not requested_key:
@@ -10126,6 +10378,7 @@ class RecordTools(ToolBase):
10126
10378
  return matches[: max(top_k, 1)]
10127
10379
 
10128
10380
  def _raise_need_more_data(self, completeness: JSONObject, evidence: JSONObject, message: str) -> None:
10381
+ """执行内部辅助逻辑。"""
10129
10382
  raise RuntimeError(
10130
10383
  json.dumps(
10131
10384
  {