@josephyan/qingflow-cli 0.2.0-beta.984 → 0.2.0-beta.986

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 (43) 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 +47 -21
  7. package/src/qingflow_mcp/cli/commands/auth.py +14 -43
  8. package/src/qingflow_mcp/cli/commands/task.py +4 -1
  9. package/src/qingflow_mcp/cli/commands/workspace.py +0 -8
  10. package/src/qingflow_mcp/cli/formatters.py +0 -21
  11. package/src/qingflow_mcp/config.py +39 -0
  12. package/src/qingflow_mcp/errors.py +2 -2
  13. package/src/qingflow_mcp/public_surface.py +2 -6
  14. package/src/qingflow_mcp/response_trim.py +1 -8
  15. package/src/qingflow_mcp/server.py +1 -1
  16. package/src/qingflow_mcp/server_app_builder.py +4 -28
  17. package/src/qingflow_mcp/server_app_user.py +4 -28
  18. package/src/qingflow_mcp/session_store.py +31 -5
  19. package/src/qingflow_mcp/tools/ai_builder_tools.py +117 -1
  20. package/src/qingflow_mcp/tools/app_tools.py +51 -1
  21. package/src/qingflow_mcp/tools/approval_tools.py +82 -1
  22. package/src/qingflow_mcp/tools/auth_tools.py +258 -288
  23. package/src/qingflow_mcp/tools/base.py +204 -4
  24. package/src/qingflow_mcp/tools/code_block_tools.py +21 -0
  25. package/src/qingflow_mcp/tools/custom_button_tools.py +24 -1
  26. package/src/qingflow_mcp/tools/directory_tools.py +28 -1
  27. package/src/qingflow_mcp/tools/feedback_tools.py +8 -0
  28. package/src/qingflow_mcp/tools/file_tools.py +25 -1
  29. package/src/qingflow_mcp/tools/import_tools.py +40 -1
  30. package/src/qingflow_mcp/tools/navigation_tools.py +34 -1
  31. package/src/qingflow_mcp/tools/package_tools.py +37 -1
  32. package/src/qingflow_mcp/tools/portal_tools.py +28 -1
  33. package/src/qingflow_mcp/tools/qingbi_report_tools.py +38 -1
  34. package/src/qingflow_mcp/tools/record_tools.py +255 -2
  35. package/src/qingflow_mcp/tools/repository_dev_tools.py +21 -2
  36. package/src/qingflow_mcp/tools/resource_read_tools.py +23 -1
  37. package/src/qingflow_mcp/tools/role_tools.py +19 -1
  38. package/src/qingflow_mcp/tools/solution_tools.py +56 -1
  39. package/src/qingflow_mcp/tools/task_context_tools.py +205 -6
  40. package/src/qingflow_mcp/tools/task_tools.py +49 -3
  41. package/src/qingflow_mcp/tools/view_tools.py +56 -1
  42. package/src/qingflow_mcp/tools/workflow_tools.py +65 -1
  43. package/src/qingflow_mcp/tools/workspace_tools.py +14 -225
@@ -19,7 +19,7 @@ from ..errors import QingflowApiError, raise_tool_error
19
19
  from ..json_types import JSONObject, JSONValue
20
20
  from ..repository_store import RepositoryMetadataStore
21
21
  from ..session_store import SessionProfile
22
- from .base import ToolBase
22
+ from .base import ToolBase, tool_cn_name
23
23
 
24
24
 
25
25
  _STREAM_EVENT_RE = re.compile(r"^type=(?P<type>[^,]+),timestamp=(?P<timestamp>[^,]+),data=(?P<data>.*)$")
@@ -27,11 +27,23 @@ _STREAM_NEWLINE_TOKEN = "<wingsBr>"
27
27
 
28
28
 
29
29
  class RepositoryDevTools(ToolBase):
30
+ """仓库开发工具(中文名:仓库初始化与绑定)。
31
+
32
+ 类型:开发辅助工具。
33
+ 主要职责:
34
+ 1. 初始化仓库开发元数据;
35
+ 2. 维护仓库模板与分组映射;
36
+ 3. 为 AI Builder 的仓库流程提供状态读写。
37
+ """
38
+
30
39
  def __init__(self, sessions, backend, *, metadata_store: RepositoryMetadataStore | None = None) -> None:
40
+ """执行内部辅助逻辑。"""
31
41
  super().__init__(sessions, backend)
32
42
  self._metadata = metadata_store or RepositoryMetadataStore()
33
43
 
44
+ @tool_cn_name("仓库初始化")
34
45
  def repository_init(self, *, profile: str, group_name: str, repo_template: str) -> JSONObject:
46
+ """执行工具方法逻辑。"""
35
47
  normalized_group = str(group_name or "").strip()
36
48
  normalized_template = str(repo_template or "").strip()
37
49
  if not normalized_group:
@@ -69,6 +81,7 @@ class RepositoryDevTools(ToolBase):
69
81
 
70
82
  return self._run(profile, runner, require_workspace=True)
71
83
 
84
+ @tool_cn_name("仓库生成")
72
85
  def repository_generate(
73
86
  self,
74
87
  *,
@@ -87,6 +100,7 @@ class RepositoryDevTools(ToolBase):
87
100
  session_id: str | None = None,
88
101
  round_version: int | None = None,
89
102
  ) -> JSONObject:
103
+ """执行工具方法逻辑。"""
90
104
  normalized_repo = str(repo_name or "").strip()
91
105
  normalized_query = str(query or "").strip()
92
106
  if not normalized_repo:
@@ -162,6 +176,7 @@ class RepositoryDevTools(ToolBase):
162
176
 
163
177
  return self._run(profile, runner, require_workspace=True)
164
178
 
179
+ @tool_cn_name("仓库发布生产")
165
180
  def repository_publish_prod(
166
181
  self,
167
182
  *,
@@ -169,6 +184,7 @@ class RepositoryDevTools(ToolBase):
169
184
  repo_name: str,
170
185
  confirm: bool = False,
171
186
  ) -> JSONObject:
187
+ """执行工具方法逻辑。"""
172
188
  normalized_repo = str(repo_name or "").strip()
173
189
  if not normalized_repo:
174
190
  raise_tool_error(QingflowApiError.config_error("repo_name is required"))
@@ -200,6 +216,7 @@ class RepositoryDevTools(ToolBase):
200
216
  return self._run(profile, runner, require_workspace=True)
201
217
 
202
218
  def _custom_page_route_warning(self) -> list[JSONObject]:
219
+ """执行内部辅助逻辑。"""
203
220
  if get_repository_internal_base_url() and get_repository_internal_share_token():
204
221
  return []
205
222
  return [
@@ -223,6 +240,7 @@ class RepositoryDevTools(ToolBase):
223
240
  params: JSONObject | None = None,
224
241
  json_body: JSONValue = None,
225
242
  ) -> JSONValue:
243
+ """执行内部辅助逻辑。"""
226
244
  internal_route = _resolve_internal_custom_page_route(session_profile)
227
245
  if internal_route is not None:
228
246
  return self.backend.public_request_with_headers(
@@ -246,6 +264,7 @@ class RepositoryDevTools(ToolBase):
246
264
  params: JSONObject | None = None,
247
265
  json_body: JSONValue = None,
248
266
  ) -> list[str]:
267
+ """执行内部辅助逻辑。"""
249
268
  internal_route = _resolve_internal_custom_page_route(session_profile)
250
269
  if internal_route is not None:
251
270
  return self.backend.public_stream_request(
@@ -302,7 +321,7 @@ def _resolve_internal_custom_page_route(session_profile: SessionProfile) -> dict
302
321
  )
303
322
  if session_profile.selected_ws_id is None:
304
323
  raise_tool_error(
305
- QingflowApiError.config_error("workspace_select is required before using the internal custom-page route")
324
+ QingflowApiError.config_error("auth_use_credential must return a valid wsId before using the internal custom-page route")
306
325
  )
307
326
  return {
308
327
  "base_url": base_url,
@@ -8,17 +8,29 @@ from ..json_types import JSONObject
8
8
  from ..list_type_labels import SYSTEM_VIEW_DEFINITIONS
9
9
  from .app_tools import _analysis_supported_for_view_type
10
10
  from .app_tools import AppTools
11
- from .base import ToolBase
11
+ from .base import ToolBase, tool_cn_name
12
12
  from .qingbi_report_tools import QingbiReportTools
13
13
 
14
14
 
15
15
  class ResourceReadTools(ToolBase):
16
+ """资源读取工具(中文名:统一只读聚合)。
17
+
18
+ 类型:只读聚合工具。
19
+ 主要职责:
20
+ 1. 聚合应用、视图、图表等读取能力;
21
+ 2. 为上层流程提供统一资源读取入口;
22
+ 3. 避免多工具重复初始化造成的调用复杂度。
23
+ """
24
+
16
25
  def __init__(self, sessions, backend) -> None:
26
+ """执行内部辅助逻辑。"""
17
27
  super().__init__(sessions, backend)
18
28
  self.apps = AppTools(sessions, backend)
19
29
  self.charts = QingbiReportTools(sessions, backend)
20
30
 
31
+ @tool_cn_name("资源读取-门户列表")
21
32
  def portal_list(self, *, profile: str) -> JSONObject:
33
+ """执行门户相关逻辑。"""
22
34
  def runner(session_profile, context):
23
35
  raw_items = self.backend.request("GET", context, "/dash")
24
36
  items = _normalize_portal_list_items(raw_items)
@@ -36,7 +48,9 @@ class ResourceReadTools(ToolBase):
36
48
 
37
49
  return self._run(profile, runner)
38
50
 
51
+ @tool_cn_name("资源读取-门户详情")
39
52
  def portal_get(self, *, profile: str, dash_key: str) -> JSONObject:
53
+ """执行门户相关逻辑。"""
40
54
  self._require_dash_key(dash_key)
41
55
 
42
56
  def runner(session_profile, context):
@@ -71,7 +85,9 @@ class ResourceReadTools(ToolBase):
71
85
 
72
86
  return self._run(profile, runner)
73
87
 
88
+ @tool_cn_name("资源读取-视图详情")
74
89
  def view_get(self, *, profile: str, view_id: str) -> JSONObject:
90
+ """执行视图相关逻辑。"""
75
91
  self._require_view_id(view_id)
76
92
  view_key = _extract_custom_view_key(view_id)
77
93
  system_view = _lookup_system_view_descriptor(view_id)
@@ -175,7 +191,9 @@ class ResourceReadTools(ToolBase):
175
191
 
176
192
  return self._run(profile, runner)
177
193
 
194
+ @tool_cn_name("资源读取-报表详情")
178
195
  def chart_get(self, *, profile: str, chart_id: str) -> JSONObject:
196
+ """执行图表相关逻辑。"""
179
197
  self._require_chart_id(chart_id)
180
198
 
181
199
  def runner(session_profile, _context):
@@ -204,18 +222,22 @@ class ResourceReadTools(ToolBase):
204
222
  return self._run(profile, runner)
205
223
 
206
224
  def _require_dash_key(self, dash_key: str) -> None:
225
+ """执行内部辅助逻辑。"""
207
226
  if not dash_key:
208
227
  raise_tool_error(QingflowApiError.config_error("dash_key is required"))
209
228
 
210
229
  def _require_view_id(self, view_id: str) -> None:
230
+ """执行内部辅助逻辑。"""
211
231
  if not view_id:
212
232
  raise_tool_error(QingflowApiError.config_error("view_id is required"))
213
233
 
214
234
  def _require_chart_id(self, chart_id: str) -> None:
235
+ """执行内部辅助逻辑。"""
215
236
  if not chart_id:
216
237
  raise_tool_error(QingflowApiError.config_error("chart_id is required"))
217
238
 
218
239
  def _resolve_app_key_from_form_id(self, *, profile: str, form_id: int | None) -> str | None:
240
+ """执行内部辅助逻辑。"""
219
241
  if form_id is None:
220
242
  return None
221
243
  try:
@@ -5,11 +5,21 @@ from mcp.server.fastmcp import FastMCP
5
5
  from ..config import DEFAULT_PROFILE
6
6
  from ..errors import QingflowApiError, raise_tool_error
7
7
  from ..json_types import JSONObject
8
- from .base import ToolBase
8
+ from .base import ToolBase, tool_cn_name
9
9
 
10
10
 
11
11
  class RoleTools(ToolBase):
12
+ """角色工具(中文名:角色检索与创建)。
13
+
14
+ 类型:组织权限工具。
15
+ 主要职责:
16
+ 1. 搜索角色并提供候选列表;
17
+ 2. 创建角色并返回标准角色信息;
18
+ 3. 服务流程节点与权限配置场景。
19
+ """
20
+
12
21
  def register(self, mcp: FastMCP) -> None:
22
+ """注册当前工具到 MCP 服务。"""
13
23
  @mcp.tool()
14
24
  def role_search(
15
25
  profile: str = DEFAULT_PROFILE,
@@ -35,7 +45,9 @@ class RoleTools(ToolBase):
35
45
  def role_delete(profile: str = DEFAULT_PROFILE, role_ids: list[int] | None = None) -> JSONObject:
36
46
  return self.role_delete(profile=profile, role_ids=role_ids or [])
37
47
 
48
+ @tool_cn_name("角色搜索")
38
49
  def role_search(self, *, profile: str, keyword: str, page_num: int, page_size: int) -> JSONObject:
50
+ """执行角色相关逻辑。"""
39
51
  if page_num <= 0 or page_size <= 0:
40
52
  raise_tool_error(QingflowApiError.config_error("page_num and page_size must be positive"))
41
53
 
@@ -55,7 +67,9 @@ class RoleTools(ToolBase):
55
67
 
56
68
  return self._run(profile, runner)
57
69
 
70
+ @tool_cn_name("创建角色")
58
71
  def role_create(self, *, profile: str, payload: JSONObject) -> JSONObject:
72
+ """执行角色相关逻辑。"""
59
73
  body = self._require_dict(payload)
60
74
 
61
75
  def runner(session_profile, context):
@@ -64,7 +78,9 @@ class RoleTools(ToolBase):
64
78
 
65
79
  return self._run(profile, runner)
66
80
 
81
+ @tool_cn_name("更新角色")
67
82
  def role_update(self, *, profile: str, role_id: int, payload: JSONObject) -> JSONObject:
83
+ """执行角色相关逻辑。"""
68
84
  if role_id <= 0:
69
85
  raise_tool_error(QingflowApiError.config_error("role_id must be positive"))
70
86
  body = self._require_dict(payload)
@@ -79,7 +95,9 @@ class RoleTools(ToolBase):
79
95
 
80
96
  return self._run(profile, runner)
81
97
 
98
+ @tool_cn_name("删除角色")
82
99
  def role_delete(self, *, profile: str, role_ids: list[int]) -> JSONObject:
100
+ """执行角色相关逻辑。"""
83
101
  if not role_ids or any(role_id <= 0 for role_id in role_ids):
84
102
  raise_tool_error(QingflowApiError.config_error("role_ids must be a non-empty array of positive integers"))
85
103
 
@@ -30,7 +30,7 @@ from ..solution.spec_models import (
30
30
  ViewsBuildSpec,
31
31
  )
32
32
  from .app_tools import AppTools
33
- from .base import ToolBase
33
+ from .base import ToolBase, tool_cn_name
34
34
  from .navigation_tools import NavigationTools
35
35
  from .package_tools import PackageTools
36
36
  from .portal_tools import PortalTools
@@ -126,7 +126,17 @@ SOLUTION_SCHEMA_INTENT_ALIASES = {
126
126
 
127
127
 
128
128
  class SolutionTools(ToolBase):
129
+ """解决方案工具(中文名:方案会话与安装执行)。
130
+
131
+ 类型:解决方案编排工具。
132
+ 主要职责:
133
+ 1. 管理设计会话与运行会话;
134
+ 2. 安装与应用 SolutionSpec;
135
+ 3. 输出安装结果、阶段状态与故障信息。
136
+ """
137
+
129
138
  def register(self, mcp: FastMCP) -> None:
139
+ """注册当前工具到 MCP 服务。"""
130
140
  @mcp.tool()
131
141
  def solution_design_session(
132
142
  action: str = "get",
@@ -347,6 +357,7 @@ class SolutionTools(ToolBase):
347
357
  def solution_build_status(build_id: str = "") -> dict[str, Any]:
348
358
  return self.solution_build_status(build_id=build_id)
349
359
 
360
+ @tool_cn_name("方案设计会话")
350
361
  def solution_design_session(
351
362
  self,
352
363
  *,
@@ -356,6 +367,7 @@ class SolutionTools(ToolBase):
356
367
  design_patch: dict[str, Any],
357
368
  metadata: dict[str, Any],
358
369
  ) -> dict[str, Any]:
370
+ """执行方案相关逻辑。"""
359
371
  try:
360
372
  if action == "start" and not session_id:
361
373
  session_id = _generate_session_id(metadata=metadata, stage=stage)
@@ -416,6 +428,7 @@ class SolutionTools(ToolBase):
416
428
  except Exception as exc: # noqa: BLE001
417
429
  return self._design_failure_response(session_id, action, "runtime", str(exc))
418
430
 
431
+ @tool_cn_name("方案启动搭建")
419
432
  def solution_bootstrap(
420
433
  self,
421
434
  *,
@@ -428,6 +441,7 @@ class SolutionTools(ToolBase):
428
441
  target: dict[str, Any],
429
442
  repair_patch: dict[str, Any],
430
443
  ) -> dict[str, Any]:
444
+ """执行方案相关逻辑。"""
431
445
  mode = _normalize_staged_build_mode(mode)
432
446
  if mode not in {"preflight", "plan", "apply", "repair"}:
433
447
  return self._failure_response(mode, idempotency_key, "config", "mode must be one of: preflight, plan, apply, repair")
@@ -515,6 +529,7 @@ class SolutionTools(ToolBase):
515
529
  return runner()
516
530
  return self._run(profile, lambda _session_profile, _context: runner())
517
531
 
532
+ @tool_cn_name("搭建应用流程")
518
533
  def solution_build_app_flow(
519
534
  self,
520
535
  *,
@@ -527,6 +542,7 @@ class SolutionTools(ToolBase):
527
542
  target: dict[str, Any],
528
543
  repair_patch: dict[str, Any],
529
544
  ) -> dict[str, Any]:
545
+ """执行方案相关逻辑。"""
530
546
  mode = _normalize_staged_build_mode(mode)
531
547
  return self._stage_build(
532
548
  profile=profile,
@@ -541,6 +557,7 @@ class SolutionTools(ToolBase):
541
557
  repair_patch=repair_patch,
542
558
  )
543
559
 
560
+ @tool_cn_name("搭建应用")
544
561
  def solution_build_app(
545
562
  self,
546
563
  *,
@@ -556,6 +573,7 @@ class SolutionTools(ToolBase):
556
573
  target: dict[str, Any],
557
574
  repair_patch: dict[str, Any],
558
575
  ) -> dict[str, Any]:
576
+ """执行方案相关逻辑。"""
559
577
  mode = _normalize_staged_build_mode(mode)
560
578
  resolved_app_spec = deepcopy(app_spec) if isinstance(app_spec, dict) else {}
561
579
  if not resolved_app_spec and build_id:
@@ -582,6 +600,7 @@ class SolutionTools(ToolBase):
582
600
  projection_name="app",
583
601
  )
584
602
 
603
+ @tool_cn_name("从需求搭建应用")
585
604
  def solution_build_app_from_requirements(
586
605
  self,
587
606
  *,
@@ -599,6 +618,7 @@ class SolutionTools(ToolBase):
599
618
  run_label: str | None,
600
619
  include_generated_spec: bool,
601
620
  ) -> dict[str, Any]:
621
+ """执行方案相关逻辑。"""
602
622
  mode = _normalize_staged_build_mode(mode)
603
623
  if mode in {"preflight", "plan"} and not build_id:
604
624
  build_id = _generate_build_id(run_label=run_label, stage_name="app")
@@ -703,6 +723,7 @@ class SolutionTools(ToolBase):
703
723
  include_generated_spec=include_generated_spec,
704
724
  )
705
725
 
726
+ @tool_cn_name("搭建流程")
706
727
  def solution_build_flow(
707
728
  self,
708
729
  *,
@@ -714,6 +735,7 @@ class SolutionTools(ToolBase):
714
735
  run_label: str | None,
715
736
  repair_patch: dict[str, Any],
716
737
  ) -> dict[str, Any]:
738
+ """执行方案相关逻辑。"""
717
739
  mode = _normalize_staged_build_mode(mode)
718
740
  return self._stage_build(
719
741
  profile=profile,
@@ -731,6 +753,7 @@ class SolutionTools(ToolBase):
731
753
  projection_name="flow",
732
754
  )
733
755
 
756
+ @tool_cn_name("一键搭建全部")
734
757
  def solution_build_all(
735
758
  self,
736
759
  *,
@@ -744,6 +767,7 @@ class SolutionTools(ToolBase):
744
767
  repair_patch: dict[str, Any],
745
768
  verify: bool,
746
769
  ) -> dict[str, Any]:
770
+ """执行方案相关逻辑。"""
747
771
  mode = _normalize_staged_build_mode(mode)
748
772
  if mode in {"preflight", "plan"} and not build_id:
749
773
  build_id = _generate_build_id(run_label=run_label, stage_name="all")
@@ -918,6 +942,7 @@ class SolutionTools(ToolBase):
918
942
  return runner()
919
943
  return self._run(profile, lambda _session_profile, _context: runner())
920
944
 
945
+ @tool_cn_name("搭建视图")
921
946
  def solution_build_views(
922
947
  self,
923
948
  *,
@@ -929,6 +954,7 @@ class SolutionTools(ToolBase):
929
954
  run_label: str | None,
930
955
  repair_patch: dict[str, Any],
931
956
  ) -> dict[str, Any]:
957
+ """执行方案相关逻辑。"""
932
958
  mode = _normalize_staged_build_mode(mode)
933
959
  return self._stage_build(
934
960
  profile=profile,
@@ -943,6 +969,7 @@ class SolutionTools(ToolBase):
943
969
  repair_patch=repair_patch,
944
970
  )
945
971
 
972
+ @tool_cn_name("方案 Schema 示例")
946
973
  def solution_schema_example(
947
974
  self,
948
975
  *,
@@ -951,6 +978,7 @@ class SolutionTools(ToolBase):
951
978
  include_examples: bool = False,
952
979
  include_selected_example: bool = False,
953
980
  ) -> dict[str, Any]:
981
+ """执行方案相关逻辑。"""
954
982
  resolved_stage = _normalize_solution_schema_stage(stage)
955
983
  resolved_intent = _normalize_solution_schema_intent(intent)
956
984
  if resolved_stage is None:
@@ -991,6 +1019,7 @@ class SolutionTools(ToolBase):
991
1019
  response["resolved_intent"] = resolved_intent
992
1020
  return response
993
1021
 
1022
+ @tool_cn_name("搭建分析门户")
994
1023
  def solution_build_analytics_portal(
995
1024
  self,
996
1025
  *,
@@ -1002,6 +1031,7 @@ class SolutionTools(ToolBase):
1002
1031
  run_label: str | None,
1003
1032
  repair_patch: dict[str, Any],
1004
1033
  ) -> dict[str, Any]:
1034
+ """执行方案相关逻辑。"""
1005
1035
  mode = _normalize_staged_build_mode(mode)
1006
1036
  return self._stage_build(
1007
1037
  profile=profile,
@@ -1016,6 +1046,7 @@ class SolutionTools(ToolBase):
1016
1046
  repair_patch=repair_patch,
1017
1047
  )
1018
1048
 
1049
+ @tool_cn_name("搭建导航")
1019
1050
  def solution_build_navigation(
1020
1051
  self,
1021
1052
  *,
@@ -1027,6 +1058,7 @@ class SolutionTools(ToolBase):
1027
1058
  run_label: str | None,
1028
1059
  repair_patch: dict[str, Any],
1029
1060
  ) -> dict[str, Any]:
1061
+ """执行方案相关逻辑。"""
1030
1062
  mode = _normalize_staged_build_mode(mode)
1031
1063
  return self._stage_build(
1032
1064
  profile=profile,
@@ -1041,7 +1073,9 @@ class SolutionTools(ToolBase):
1041
1073
  repair_patch=repair_patch,
1042
1074
  )
1043
1075
 
1076
+ @tool_cn_name("搭建状态")
1044
1077
  def solution_build_status(self, *, build_id: str) -> dict[str, Any]:
1078
+ """执行方案相关逻辑。"""
1045
1079
  if not build_id:
1046
1080
  error_fields = _solution_error_fields(
1047
1081
  category="config",
@@ -1077,6 +1111,7 @@ class SolutionTools(ToolBase):
1077
1111
  tool_name: str | None = None,
1078
1112
  projection_name: str | None = None,
1079
1113
  ) -> dict[str, Any]:
1114
+ """执行内部辅助逻辑。"""
1080
1115
  mode = _normalize_staged_build_mode(mode)
1081
1116
  public_stage_name = public_stage_name or stage_name
1082
1117
  tool_name = tool_name or STAGE_TOOL_NAMES.get(stage_name, "solution_build_app_flow")
@@ -1133,6 +1168,7 @@ class SolutionTools(ToolBase):
1133
1168
  tool_name: str,
1134
1169
  projection_name: str,
1135
1170
  ) -> dict[str, Any]:
1171
+ """执行内部辅助逻辑。"""
1136
1172
  try:
1137
1173
  resolved_stage_payload = self._resolve_stage_payload(
1138
1174
  assembly=assembly,
@@ -1320,6 +1356,7 @@ class SolutionTools(ToolBase):
1320
1356
  stage_model: type[BaseModel],
1321
1357
  projection_name: str,
1322
1358
  ) -> dict[str, Any]:
1359
+ """执行内部辅助逻辑。"""
1323
1360
  existing_stage_payload = (assembly.data.get("stage_specs", {}) or {}).get(stage_name, {}) or {}
1324
1361
  base_payload: dict[str, Any] = {}
1325
1362
  if mode == "repair":
@@ -1357,6 +1394,7 @@ class SolutionTools(ToolBase):
1357
1394
  mode: str,
1358
1395
  repair_patch: dict[str, Any],
1359
1396
  ) -> dict[str, Any]:
1397
+ """执行内部辅助逻辑。"""
1360
1398
  base_payload = deepcopy(solution_spec)
1361
1399
  if mode == "repair" and repair_patch:
1362
1400
  base_payload = deep_merge(base_payload, repair_patch)
@@ -1364,6 +1402,7 @@ class SolutionTools(ToolBase):
1364
1402
  return parsed.model_dump(mode="json", exclude_unset=True)
1365
1403
 
1366
1404
  def _build_executor(self) -> SolutionExecutor:
1405
+ """执行内部辅助逻辑。"""
1367
1406
  return SolutionExecutor(
1368
1407
  workspace_tools=WorkspaceTools(self.sessions, self.backend),
1369
1408
  package_tools=PackageTools(self.sessions, self.backend),
@@ -1385,6 +1424,7 @@ class SolutionTools(ToolBase):
1385
1424
  artifacts: dict[str, Any],
1386
1425
  solution_spec: dict[str, Any],
1387
1426
  ) -> dict[str, Any]:
1427
+ """执行内部辅助逻辑。"""
1388
1428
  verification = {
1389
1429
  "build_id": build_id,
1390
1430
  "status": "success",
@@ -1507,6 +1547,7 @@ class SolutionTools(ToolBase):
1507
1547
  solution_spec: dict[str, Any],
1508
1548
  target: dict[str, Any],
1509
1549
  ) -> dict[str, Any] | None:
1550
+ """执行内部辅助逻辑。"""
1510
1551
  if public_stage_name != "app":
1511
1552
  return None
1512
1553
  app_tools = AppTools(self.sessions, self.backend)
@@ -1592,6 +1633,7 @@ class SolutionTools(ToolBase):
1592
1633
  return verification
1593
1634
 
1594
1635
  def _failure_response(self, mode: str, idempotency_key: str, category: str, detail: Any) -> dict[str, Any]:
1636
+ """执行内部辅助逻辑。"""
1595
1637
  error_fields = _solution_error_fields(
1596
1638
  category=category,
1597
1639
  detail=detail,
@@ -1624,6 +1666,7 @@ class SolutionTools(ToolBase):
1624
1666
  *,
1625
1667
  tool_name: str,
1626
1668
  ) -> dict[str, Any]:
1669
+ """执行内部辅助逻辑。"""
1627
1670
  error_fields = _solution_error_fields(
1628
1671
  category=category,
1629
1672
  detail=detail,
@@ -1662,6 +1705,7 @@ class SolutionTools(ToolBase):
1662
1705
  assembly: BuildAssemblyStore,
1663
1706
  tool_name: str,
1664
1707
  ) -> dict[str, Any]:
1708
+ """执行内部辅助逻辑。"""
1665
1709
  return {
1666
1710
  "build_id": build_id,
1667
1711
  "stage": stage_name,
@@ -1701,6 +1745,7 @@ class SolutionTools(ToolBase):
1701
1745
  tool_name: str,
1702
1746
  verification: dict[str, Any] | None = None,
1703
1747
  ) -> dict[str, Any]:
1748
+ """执行内部辅助逻辑。"""
1704
1749
  response = {
1705
1750
  "build_id": build_id,
1706
1751
  "stage": stage_name,
@@ -1729,6 +1774,7 @@ class SolutionTools(ToolBase):
1729
1774
  return response
1730
1775
 
1731
1776
  def _design_failure_response(self, session_id: str, action: str, category: str, detail: Any) -> dict[str, Any]:
1777
+ """执行内部辅助逻辑。"""
1732
1778
  error_fields = _solution_error_fields(
1733
1779
  category=category,
1734
1780
  detail=detail,
@@ -1750,6 +1796,7 @@ class SolutionTools(ToolBase):
1750
1796
  }
1751
1797
 
1752
1798
  def _design_summary(self, store: DesignSessionStore) -> dict[str, Any]:
1799
+ """执行内部辅助逻辑。"""
1753
1800
  summary = store.summary()
1754
1801
  current_stage = summary["current_stage"]
1755
1802
  summary["next_stage"] = None if summary["status"] == "finalized" else current_stage
@@ -1758,6 +1805,7 @@ class SolutionTools(ToolBase):
1758
1805
  return summary
1759
1806
 
1760
1807
  def _all_failure_response(self, build_id: str, mode: str, category: str, detail: Any) -> dict[str, Any]:
1808
+ """执行内部辅助逻辑。"""
1761
1809
  error_fields = _solution_error_fields(
1762
1810
  category=category,
1763
1811
  detail=detail,
@@ -1780,6 +1828,7 @@ class SolutionTools(ToolBase):
1780
1828
  }
1781
1829
 
1782
1830
  def _load_generated_app_spec(self, build_id: str) -> dict[str, Any] | None:
1831
+ """执行内部辅助逻辑。"""
1783
1832
  if not build_id:
1784
1833
  return None
1785
1834
  try:
@@ -1802,6 +1851,7 @@ class SolutionTools(ToolBase):
1802
1851
  requirement_text: str,
1803
1852
  layout_style: str,
1804
1853
  ) -> None:
1854
+ """执行内部辅助逻辑。"""
1805
1855
  assembly = BuildAssemblyStore.open(build_id=build_id)
1806
1856
  builder_state = assembly.get_builder_state()
1807
1857
  generated_specs = builder_state.get("generated_specs", {})
@@ -1826,6 +1876,7 @@ class SolutionTools(ToolBase):
1826
1876
  stage_payload: dict[str, Any],
1827
1877
  errors: list[dict[str, Any]],
1828
1878
  ) -> tuple[str | None, int]:
1879
+ """执行内部辅助逻辑。"""
1829
1880
  signature = _failure_signature_for_stage(stage_name=stage_name, stage_payload=stage_payload, errors=errors)
1830
1881
  if signature is None:
1831
1882
  return None, 0
@@ -1849,6 +1900,7 @@ class SolutionTools(ToolBase):
1849
1900
  package_tag_id: int,
1850
1901
  package_name: str,
1851
1902
  ) -> dict[str, Any]:
1903
+ """执行内部辅助逻辑。"""
1852
1904
  packages = PackageTools(self.sessions, self.backend)
1853
1905
  normalized_name = package_name.strip()
1854
1906
  if package_tag_id > 0:
@@ -1998,6 +2050,7 @@ class SolutionTools(ToolBase):
1998
2050
  package_resolution: dict[str, Any],
1999
2051
  update_only: bool,
2000
2052
  ) -> dict[str, Any]:
2053
+ """执行内部辅助逻辑。"""
2001
2054
  normalized_app_key = str(app_key or "").strip()
2002
2055
  if not normalized_app_key:
2003
2056
  if update_only:
@@ -2120,6 +2173,7 @@ class SolutionTools(ToolBase):
2120
2173
  invalid_field_types: list[str] | None = None,
2121
2174
  error_details: dict[str, Any] | None = None,
2122
2175
  ) -> dict[str, Any]:
2176
+ """执行内部辅助逻辑。"""
2123
2177
  suggested_next_call = (
2124
2178
  {"tool_name": "solution_build_app", "arguments": {"mode": "plan", "build_id": build_id}}
2125
2179
  if build_id and self._load_generated_app_spec(build_id)
@@ -2185,6 +2239,7 @@ class SolutionTools(ToolBase):
2185
2239
  stage_result: dict[str, Any],
2186
2240
  include_generated_spec: bool,
2187
2241
  ) -> dict[str, Any]:
2242
+ """执行内部辅助逻辑。"""
2188
2243
  next_call = stage_result.get("suggested_next_call")
2189
2244
  response = {
2190
2245
  "status": stage_result.get("status"),