precis-cli 0.1.3__py3-none-any.whl

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 (442) hide show
  1. app/__init__.py +16 -0
  2. app/api/__init__.py +32 -0
  3. app/api/dependencies.py +185 -0
  4. app/api/main.py +301 -0
  5. app/api/middleware/__init__.py +34 -0
  6. app/api/middleware/exception_handler.py +126 -0
  7. app/api/middleware/request_logging.py +97 -0
  8. app/api/middleware/token_auth.py +215 -0
  9. app/api/models/__init__.py +151 -0
  10. app/api/models/connection_rules.py +98 -0
  11. app/api/models/files.py +99 -0
  12. app/api/models/full_validation.py +554 -0
  13. app/api/models/project.py +117 -0
  14. app/api/models/projects.py +80 -0
  15. app/api/models/schema.py +121 -0
  16. app/api/models/v2_responses.py +46 -0
  17. app/api/models/validation.py +303 -0
  18. app/api/models/workspace.py +118 -0
  19. app/api/routers/__init__.py +56 -0
  20. app/api/routers/ai/__init__.py +36 -0
  21. app/api/routers/ai/chat.py +243 -0
  22. app/api/routers/ai/generate.py +156 -0
  23. app/api/routers/ai/hardware.py +199 -0
  24. app/api/routers/ai/jobs.py +544 -0
  25. app/api/routers/ai/migrate.py +471 -0
  26. app/api/routers/ai/models.py +352 -0
  27. app/api/routers/ai/ollama.py +108 -0
  28. app/api/routers/ai/providers.py +491 -0
  29. app/api/routers/ai/router.py +44 -0
  30. app/api/routers/ai/stream.py +281 -0
  31. app/api/routers/ai/utils.py +182 -0
  32. app/api/routers/core/__init__.py +34 -0
  33. app/api/routers/core/connection_rules.py +188 -0
  34. app/api/routers/core/data_sources.py +374 -0
  35. app/api/routers/core/regex.py +333 -0
  36. app/api/routers/core/reporting.py +263 -0
  37. app/api/routers/files/__init__.py +24 -0
  38. app/api/routers/files/ops.py +179 -0
  39. app/api/routers/files/transfer.py +101 -0
  40. app/api/routers/preview/__init__.py +35 -0
  41. app/api/routers/preview/content_mode.py +264 -0
  42. app/api/routers/preview/header_row.py +154 -0
  43. app/api/routers/preview/models.py +81 -0
  44. app/api/routers/preview/path_mode.py +440 -0
  45. app/api/routers/preview/router.py +30 -0
  46. app/api/routers/project/__init__.py +61 -0
  47. app/api/routers/project/base.py +111 -0
  48. app/api/routers/project/constraint.py +345 -0
  49. app/api/routers/project/full_config.py +411 -0
  50. app/api/routers/project/full_config_writer.py +327 -0
  51. app/api/routers/project/helpers.py +167 -0
  52. app/api/routers/project/inspection_fix.py +330 -0
  53. app/api/routers/project/manifest.py +605 -0
  54. app/api/routers/project/models.py +177 -0
  55. app/api/routers/project/pattern.py +268 -0
  56. app/api/routers/project/regex.py +358 -0
  57. app/api/routers/project/scanner.py +157 -0
  58. app/api/routers/project/schema.py +567 -0
  59. app/api/routers/project/schema_helpers.py +149 -0
  60. app/api/routers/project/settings.py +399 -0
  61. app/api/routers/project/template.py +325 -0
  62. app/api/routers/project/validation.py +227 -0
  63. app/api/routers/project/view.py +177 -0
  64. app/api/routers/project/workspaces.py +167 -0
  65. app/api/routers/projects/__init__.py +25 -0
  66. app/api/routers/projects/create.py +121 -0
  67. app/api/routers/projects/open.py +103 -0
  68. app/api/routers/projects/scan.py +100 -0
  69. app/api/routers/validation/__init__.py +39 -0
  70. app/api/routers/validation/common.py +263 -0
  71. app/api/routers/validation/content_mode.py +401 -0
  72. app/api/routers/validation/history.py +235 -0
  73. app/api/routers/validation/inline_mode.py +196 -0
  74. app/api/routers/validation/path_mode.py +314 -0
  75. app/api/routers/validation/router.py +51 -0
  76. app/api/services/full_validation_response_builder.py +412 -0
  77. app/api/services/io_error_messages.py +41 -0
  78. app/api/services/preview_service.py +248 -0
  79. app/cli/__init__.py +18 -0
  80. app/cli/__main__.py +30 -0
  81. app/cli/shared_services/__init__.py +42 -0
  82. app/cli/shared_services/config_ops.py +581 -0
  83. app/cli/shared_services/generation_ops.py +160 -0
  84. app/cli/shared_services/project_ops.py +288 -0
  85. app/cli/shell/__init__.py +48 -0
  86. app/cli/shell/commands/__init__.py +63 -0
  87. app/cli/shell/commands/ai/__init__.py +260 -0
  88. app/cli/shell/commands/ai/chat.py +331 -0
  89. app/cli/shell/commands/ai/delete.py +165 -0
  90. app/cli/shell/commands/ai/diff.py +70 -0
  91. app/cli/shell/commands/ai/display.py +428 -0
  92. app/cli/shell/commands/ai/executor.py +225 -0
  93. app/cli/shell/commands/ai/executor_utils.py +271 -0
  94. app/cli/shell/commands/ai/generate.py +285 -0
  95. app/cli/shell/commands/ai/interaction.py +262 -0
  96. app/cli/shell/commands/ai/migrate.py +281 -0
  97. app/cli/shell/commands/ai/resolver.py +224 -0
  98. app/cli/shell/commands/ai/status.py +101 -0
  99. app/cli/shell/commands/ai/switch.py +158 -0
  100. app/cli/shell/commands/ai/utils.py +52 -0
  101. app/cli/shell/commands/base.py +343 -0
  102. app/cli/shell/commands/config/__init__.py +131 -0
  103. app/cli/shell/commands/config/base.py +80 -0
  104. app/cli/shell/commands/config/check.py +246 -0
  105. app/cli/shell/commands/config/edit.py +148 -0
  106. app/cli/shell/commands/config/get.py +111 -0
  107. app/cli/shell/commands/config/init.py +123 -0
  108. app/cli/shell/commands/config/inspect.py +164 -0
  109. app/cli/shell/commands/config/list.py +104 -0
  110. app/cli/shell/commands/config/set.py +119 -0
  111. app/cli/shell/commands/config/show.py +150 -0
  112. app/cli/shell/commands/exit.py +67 -0
  113. app/cli/shell/commands/help.py +104 -0
  114. app/cli/shell/commands/infer_schema.py +156 -0
  115. app/cli/shell/commands/open.py +201 -0
  116. app/cli/shell/commands/project.py +215 -0
  117. app/cli/shell/commands/provider.py +619 -0
  118. app/cli/shell/commands/system.py +170 -0
  119. app/cli/shell/commands/validate.py +455 -0
  120. app/cli/shell/completer.py +231 -0
  121. app/cli/shell/config_storage.py +191 -0
  122. app/cli/shell/exceptions.py +90 -0
  123. app/cli/shell/formatter.py +371 -0
  124. app/cli/shell/interactive_menu.py +348 -0
  125. app/cli/shell/main.py +286 -0
  126. app/cli/shell/parser.py +266 -0
  127. app/cli/start.py +180 -0
  128. app/cli_main.py +52 -0
  129. app/mcp_server.py +311 -0
  130. app/shared/core/__init__.py +18 -0
  131. app/shared/core/app_version.py +59 -0
  132. app/shared/core/config/__init__.py +119 -0
  133. app/shared/core/config/server.py +193 -0
  134. app/shared/core/data_source/__init__.py +106 -0
  135. app/shared/core/data_source/loader.py +348 -0
  136. app/shared/core/data_source/loaders/__init__.py +213 -0
  137. app/shared/core/data_source/loaders/base.py +215 -0
  138. app/shared/core/data_source/loaders/converter.py +337 -0
  139. app/shared/core/data_source/loaders/csv_loader.py +252 -0
  140. app/shared/core/data_source/loaders/excel_loader.py +666 -0
  141. app/shared/core/data_source/loaders/extractor.py +268 -0
  142. app/shared/core/data_source/loaders/json_loader.py +354 -0
  143. app/shared/core/data_source/loaders/registry.py +88 -0
  144. app/shared/core/data_source/loaders/sql_loader.py +313 -0
  145. app/shared/core/data_source/loaders/strategies/__init__.py +100 -0
  146. app/shared/core/data_source/loaders/strategies/array_parser.py +277 -0
  147. app/shared/core/data_source/loaders/strategies/lines_parser.py +355 -0
  148. app/shared/core/data_source/loaders/strategies/object_parser.py +278 -0
  149. app/shared/core/data_source/schema_info.py +50 -0
  150. app/shared/core/data_source/specs/__init__.py +128 -0
  151. app/shared/core/data_source/specs/base.py +258 -0
  152. app/shared/core/data_source/specs/csv_source.py +137 -0
  153. app/shared/core/data_source/specs/excel_source.py +141 -0
  154. app/shared/core/data_source/specs/file_base.py +252 -0
  155. app/shared/core/data_source/specs/json_source.py +226 -0
  156. app/shared/core/data_source/specs/sql_source.py +161 -0
  157. app/shared/core/encoding.py +36 -0
  158. app/shared/core/io/__init__.py +24 -0
  159. app/shared/core/io/yaml.py +379 -0
  160. app/shared/core/manifest_schema/__init__.py +52 -0
  161. app/shared/core/manifest_schema/types.py +99 -0
  162. app/shared/core/manifest_schema/version.py +175 -0
  163. app/shared/core/patterns/__init__.py +24 -0
  164. app/shared/core/patterns/loader.py +134 -0
  165. app/shared/core/patterns/writer.py +244 -0
  166. app/shared/core/project/__init__.py +47 -0
  167. app/shared/core/project/constraint/builders/__init__.py +50 -0
  168. app/shared/core/project/constraint/builders/base.py +100 -0
  169. app/shared/core/project/constraint/builders/composite.py +77 -0
  170. app/shared/core/project/constraint/builders/conditional.py +67 -0
  171. app/shared/core/project/constraint/builders/foreign_key.py +53 -0
  172. app/shared/core/project/constraint/builders/registry.py +64 -0
  173. app/shared/core/project/constraint/builders/scripted.py +51 -0
  174. app/shared/core/project/constraint/builders/single_column.py +86 -0
  175. app/shared/core/project/constraint/builders/unique.py +53 -0
  176. app/shared/core/project/constraint/factory.py +170 -0
  177. app/shared/core/project/constraint/reader.py +214 -0
  178. app/shared/core/project/constraint/registry.py +233 -0
  179. app/shared/core/project/constraint/types/__init__.py +63 -0
  180. app/shared/core/project/constraint/types/constraint_file.py +261 -0
  181. app/shared/core/project/constraint/types/refs.py +460 -0
  182. app/shared/core/project/constraint/types.py +28 -0
  183. app/shared/core/project/constraint/writer.py +181 -0
  184. app/shared/core/project/loader/__init__.py +56 -0
  185. app/shared/core/project/loader/loader.py +30 -0
  186. app/shared/core/project/loader/loader_parts/config_inspector.py +137 -0
  187. app/shared/core/project/loader/loader_parts/embedded_constraints.py +224 -0
  188. app/shared/core/project/loader/loader_parts/file_loaders.py +58 -0
  189. app/shared/core/project/loader/loader_parts/inspection_ids.py +85 -0
  190. app/shared/core/project/loader/loader_parts/inspector_helpers.py +312 -0
  191. app/shared/core/project/loader/loader_parts/inspector_id_checks.py +274 -0
  192. app/shared/core/project/loader/loader_parts/inspector_reference_checks.py +690 -0
  193. app/shared/core/project/loader/loader_parts/inspector_uniqueness_checks.py +286 -0
  194. app/shared/core/project/loader/loader_parts/loading_error_messages.py +298 -0
  195. app/shared/core/project/loader/loader_parts/main.py +432 -0
  196. app/shared/core/project/loader/loader_parts/path_validation.py +117 -0
  197. app/shared/core/project/loader/loader_parts/runtime.py +125 -0
  198. app/shared/core/project/loader/types.py +246 -0
  199. app/shared/core/project/manifest/coverage.py +391 -0
  200. app/shared/core/project/manifest/reader.py +260 -0
  201. app/shared/core/project/manifest/types.py +91 -0
  202. app/shared/core/project/manifest/types_parts/__init__.py +60 -0
  203. app/shared/core/project/manifest/types_parts/constants.py +40 -0
  204. app/shared/core/project/manifest/types_parts/data_source.py +68 -0
  205. app/shared/core/project/manifest/types_parts/info.py +59 -0
  206. app/shared/core/project/manifest/types_parts/manifest.py +294 -0
  207. app/shared/core/project/manifest/types_parts/refs.py +153 -0
  208. app/shared/core/project/manifest/types_parts/settings.py +92 -0
  209. app/shared/core/project/manifest/types_parts/settings_file_processing.py +64 -0
  210. app/shared/core/project/manifest/types_parts/settings_script_security.py +78 -0
  211. app/shared/core/project/manifest/types_parts/settings_validation.py +83 -0
  212. app/shared/core/project/manifest/types_parts/template.py +66 -0
  213. app/shared/core/project/manifest/writer.py +262 -0
  214. app/shared/core/project/manual_data/__init__.py +27 -0
  215. app/shared/core/project/manual_data/types.py +75 -0
  216. app/shared/core/project/regex/reader.py +197 -0
  217. app/shared/core/project/regex/types.py +405 -0
  218. app/shared/core/project/regex/writer.py +123 -0
  219. app/shared/core/project/schema/reader.py +170 -0
  220. app/shared/core/project/schema/types.py +47 -0
  221. app/shared/core/project/schema/types_parts/__init__.py +36 -0
  222. app/shared/core/project/schema/types_parts/column.py +174 -0
  223. app/shared/core/project/schema/types_parts/column_utils.py +72 -0
  224. app/shared/core/project/schema/types_parts/constraint.py +165 -0
  225. app/shared/core/project/schema/types_parts/schema_id.py +66 -0
  226. app/shared/core/project/schema/types_parts/source.py +255 -0
  227. app/shared/core/project/schema/types_parts/source_options.py +347 -0
  228. app/shared/core/project/schema/types_parts/table.py +230 -0
  229. app/shared/core/project/schema/writer.py +139 -0
  230. app/shared/core/project/schema_ref_check.py +95 -0
  231. app/shared/core/project/template/__init__.py +27 -0
  232. app/shared/core/project/template/expander.py +263 -0
  233. app/shared/core/project/template/reader.py +120 -0
  234. app/shared/core/project/template/types.py +114 -0
  235. app/shared/core/project/transform/reader.py +76 -0
  236. app/shared/core/project/transform/types.py +116 -0
  237. app/shared/core/project/transform/writer.py +84 -0
  238. app/shared/core/pydantic_messages.py +59 -0
  239. app/shared/core/reporter/__init__.py +46 -0
  240. app/shared/core/reporter/reporter.py +220 -0
  241. app/shared/core/reporter/reporters/__init__.py +65 -0
  242. app/shared/core/reporter/reporters/base.py +188 -0
  243. app/shared/core/reporter/reporters/dingtalk_app_reporter.py +274 -0
  244. app/shared/core/reporter/reporters/email_reporter.py +271 -0
  245. app/shared/core/reporter/reporters/feishu_app_reporter.py +467 -0
  246. app/shared/core/reporter/reporters/local_file_reporter.py +208 -0
  247. app/shared/core/reporter/reporters/wecom_app_reporter.py +268 -0
  248. app/shared/core/utils/__init__.py +18 -0
  249. app/shared/core/utils/path_utils.py +60 -0
  250. app/shared/core/utils/regex_extract.py +113 -0
  251. app/shared/domain/__init__.py +114 -0
  252. app/shared/domain/constraints/__init__.py +76 -0
  253. app/shared/domain/constraints/allowed_values.py +211 -0
  254. app/shared/domain/constraints/base.py +141 -0
  255. app/shared/domain/constraints/charset.py +337 -0
  256. app/shared/domain/constraints/composite.py +174 -0
  257. app/shared/domain/constraints/condition_registry.py +130 -0
  258. app/shared/domain/constraints/conditional.py +629 -0
  259. app/shared/domain/constraints/date_logic.py +731 -0
  260. app/shared/domain/constraints/foreign_key.py +261 -0
  261. app/shared/domain/constraints/key_normalization.py +56 -0
  262. app/shared/domain/constraints/not_null.py +185 -0
  263. app/shared/domain/constraints/range.py +360 -0
  264. app/shared/domain/constraints/regex.py +218 -0
  265. app/shared/domain/constraints/scripted.py +276 -0
  266. app/shared/domain/constraints/unique.py +233 -0
  267. app/shared/domain/data_engine.py +384 -0
  268. app/shared/domain/data_types.py +113 -0
  269. app/shared/domain/data_types_parts/__init__.py +67 -0
  270. app/shared/domain/data_types_parts/base.py +204 -0
  271. app/shared/domain/data_types_parts/composite.py +250 -0
  272. app/shared/domain/data_types_parts/expression.py +202 -0
  273. app/shared/domain/data_types_parts/extracted.py +106 -0
  274. app/shared/domain/data_types_parts/json_types.py +234 -0
  275. app/shared/domain/data_types_parts/scalars.py +719 -0
  276. app/shared/domain/data_types_parts/sequence.py +129 -0
  277. app/shared/domain/dataset_schema.py +48 -0
  278. app/shared/domain/eval_sandbox.py +63 -0
  279. app/shared/domain/expression_system.py +366 -0
  280. app/shared/domain/regex_flags.py +53 -0
  281. app/shared/domain/schema/builder.py +223 -0
  282. app/shared/domain/schema/models.py +339 -0
  283. app/shared/domain/transforms/__init__.py +28 -0
  284. app/shared/domain/transforms/aggregate.py +141 -0
  285. app/shared/domain/transforms/base.py +171 -0
  286. app/shared/domain/transforms/cast_type.py +120 -0
  287. app/shared/domain/transforms/concat.py +103 -0
  288. app/shared/domain/transforms/conditional_assign.py +114 -0
  289. app/shared/domain/transforms/date_format.py +81 -0
  290. app/shared/domain/transforms/digits.py +77 -0
  291. app/shared/domain/transforms/drop_duplicates.py +94 -0
  292. app/shared/domain/transforms/fill_na.py +94 -0
  293. app/shared/domain/transforms/filter_rows.py +97 -0
  294. app/shared/domain/transforms/lookup.py +78 -0
  295. app/shared/domain/transforms/lower_case.py +70 -0
  296. app/shared/domain/transforms/map_value.py +90 -0
  297. app/shared/domain/transforms/math_expr.py +112 -0
  298. app/shared/domain/transforms/modulo.py +82 -0
  299. app/shared/domain/transforms/regex_extract.py +103 -0
  300. app/shared/domain/transforms/registry.py +95 -0
  301. app/shared/domain/transforms/replace.py +88 -0
  302. app/shared/domain/transforms/sort_rows.py +94 -0
  303. app/shared/domain/transforms/string_split.py +84 -0
  304. app/shared/domain/transforms/strip.py +73 -0
  305. app/shared/domain/transforms/substring.py +92 -0
  306. app/shared/domain/transforms/upper_case.py +70 -0
  307. app/shared/domain/transforms/weighted_sum.py +104 -0
  308. app/shared/domain/validation_constraints.py +69 -0
  309. app/shared/services/__init__.py +62 -0
  310. app/shared/services/ai/__init__.py +48 -0
  311. app/shared/services/ai/agent/__init__.py +40 -0
  312. app/shared/services/ai/agent/chat_tools/__init__.py +47 -0
  313. app/shared/services/ai/agent/chat_tools/apply_actions.py +592 -0
  314. app/shared/services/ai/agent/chat_tools/ask_user.py +237 -0
  315. app/shared/services/ai/agent/chat_tools/read_canvas.py +140 -0
  316. app/shared/services/ai/agent/chat_tools/read_project.py +160 -0
  317. app/shared/services/ai/agent/chat_tools/read_table.py +301 -0
  318. app/shared/services/ai/agent/chat_tools/schemas.py +105 -0
  319. app/shared/services/ai/agent/chat_tools/validate_table.py +131 -0
  320. app/shared/services/ai/agent/executor.py +554 -0
  321. app/shared/services/ai/agent/memory.py +256 -0
  322. app/shared/services/ai/agent/planner.py +282 -0
  323. app/shared/services/ai/agent/tool_registry.py +296 -0
  324. app/shared/services/ai/agent/tools/__init__.py +32 -0
  325. app/shared/services/ai/agent/tools/config_generate.py +133 -0
  326. app/shared/services/ai/agent/tools/config_refine.py +109 -0
  327. app/shared/services/ai/agent/tools/config_validate.py +403 -0
  328. app/shared/services/ai/agent/tools/merge_results.py +136 -0
  329. app/shared/services/ai/agent/tools/plan_chunks.py +79 -0
  330. app/shared/services/ai/agent/tools/script_parse.py +359 -0
  331. app/shared/services/ai/agent/types.py +138 -0
  332. app/shared/services/ai/chat_agent_runner.py +596 -0
  333. app/shared/services/ai/chat_orchestrator.py +725 -0
  334. app/shared/services/ai/failure_messages.py +65 -0
  335. app/shared/services/ai/job_storage.py +274 -0
  336. app/shared/services/ai/migrate_service.py +550 -0
  337. app/shared/services/ai/streaming/__init__.py +65 -0
  338. app/shared/services/ai/streaming/event_journal.py +197 -0
  339. app/shared/services/ai/streaming/orchestrator.py +262 -0
  340. app/shared/services/ai/streaming/pending_interaction_store.py +227 -0
  341. app/shared/services/ai/streaming/sse_response.py +148 -0
  342. app/shared/services/ai/streaming/types.py +73 -0
  343. app/shared/services/ai/types.py +213 -0
  344. app/shared/services/ai/utils.py +322 -0
  345. app/shared/services/diff/config_diff.py +320 -0
  346. app/shared/services/hardware.py +237 -0
  347. app/shared/services/llm/__init__.py +62 -0
  348. app/shared/services/llm/actions/__init__.py +42 -0
  349. app/shared/services/llm/actions/_canvas_validator.py +147 -0
  350. app/shared/services/llm/actions/_constraint_validator.py +401 -0
  351. app/shared/services/llm/actions/_regex_validator.py +85 -0
  352. app/shared/services/llm/actions/_schema_validator.py +82 -0
  353. app/shared/services/llm/actions/_settings_validator.py +76 -0
  354. app/shared/services/llm/actions/_transform_validator.py +78 -0
  355. app/shared/services/llm/actions/action_handlers.py +400 -0
  356. app/shared/services/llm/actions/action_parser.py +63 -0
  357. app/shared/services/llm/actions/action_processor.py +468 -0
  358. app/shared/services/llm/actions/action_validator.py +311 -0
  359. app/shared/services/llm/actions/diff_compute.py +195 -0
  360. app/shared/services/llm/actions/regex_handlers.py +284 -0
  361. app/shared/services/llm/actions/registry.py +336 -0
  362. app/shared/services/llm/actions/schema_handlers.py +335 -0
  363. app/shared/services/llm/actions/settings_handlers.py +180 -0
  364. app/shared/services/llm/actions/specs.py +259 -0
  365. app/shared/services/llm/actions/transform_handlers.py +279 -0
  366. app/shared/services/llm/actions/validation_types.py +147 -0
  367. app/shared/services/llm/cache/__init__.py +18 -0
  368. app/shared/services/llm/cache/response_cache.py +80 -0
  369. app/shared/services/llm/chat/__init__.py +35 -0
  370. app/shared/services/llm/chat/chat_system_prompt.py +561 -0
  371. app/shared/services/llm/chat/response_parser.py +296 -0
  372. app/shared/services/llm/config/__init__.py +45 -0
  373. app/shared/services/llm/config/crypto.py +135 -0
  374. app/shared/services/llm/config/loader.py +258 -0
  375. app/shared/services/llm/config/models.py +202 -0
  376. app/shared/services/llm/config/presets.py +128 -0
  377. app/shared/services/llm/config_generator.py +163 -0
  378. app/shared/services/llm/constraints/__init__.py +41 -0
  379. app/shared/services/llm/constraints/constraint_builder.py +177 -0
  380. app/shared/services/llm/constraints/constraint_deletion.py +84 -0
  381. app/shared/services/llm/constraints/constraint_id.py +174 -0
  382. app/shared/services/llm/constraints/frontend_instructions.py +333 -0
  383. app/shared/services/llm/constraints/inline_batch.py +279 -0
  384. app/shared/services/llm/discovery/__init__.py +35 -0
  385. app/shared/services/llm/discovery/scanner.py +181 -0
  386. app/shared/services/llm/generation/__init__.py +42 -0
  387. app/shared/services/llm/generation/agent_wiring.py +156 -0
  388. app/shared/services/llm/generation/config_builder.py +386 -0
  389. app/shared/services/llm/generation/errors.py +36 -0
  390. app/shared/services/llm/generation/existing_config.py +99 -0
  391. app/shared/services/llm/generation/profiler.py +279 -0
  392. app/shared/services/llm/generation/prompt_builder.py +199 -0
  393. app/shared/services/llm/generation/response_parser.py +144 -0
  394. app/shared/services/llm/generation/service.py +622 -0
  395. app/shared/services/llm/models.py +104 -0
  396. app/shared/services/llm/providers/__init__.py +48 -0
  397. app/shared/services/llm/providers/base.py +310 -0
  398. app/shared/services/llm/providers/cached_provider.py +90 -0
  399. app/shared/services/llm/providers/ollama.py +498 -0
  400. app/shared/services/llm/providers/openai.py +334 -0
  401. app/shared/services/llm/providers/registry.py +108 -0
  402. app/shared/services/llm/schema_resolver.py +141 -0
  403. app/shared/services/llm/suggestion_utils.py +219 -0
  404. app/shared/services/llm/validate_executor.py +163 -0
  405. app/shared/services/llm/yaml_io.py +406 -0
  406. app/shared/services/preview/__init__.py +18 -0
  407. app/shared/services/preview/loader.py +145 -0
  408. app/shared/services/preview/path_validation.py +138 -0
  409. app/shared/services/project_loader.py +57 -0
  410. app/shared/services/schema_inference.py +260 -0
  411. app/shared/services/schema_runtime_builder.py +120 -0
  412. app/shared/services/validation/__init__.py +52 -0
  413. app/shared/services/validation/chunked_loader.py +509 -0
  414. app/shared/services/validation/dag/__init__.py +35 -0
  415. app/shared/services/validation/dag/builder.py +141 -0
  416. app/shared/services/validation/dag/executor.py +225 -0
  417. app/shared/services/validation/dag/sorter.py +77 -0
  418. app/shared/services/validation/data_loader.py +231 -0
  419. app/shared/services/validation/engine.py +446 -0
  420. app/shared/services/validation/executor.py +1030 -0
  421. app/shared/services/validation/extractors.py +266 -0
  422. app/shared/services/validation/history.py +209 -0
  423. app/shared/services/validation/json_payload.py +136 -0
  424. app/shared/services/validation/loader.py +152 -0
  425. app/shared/services/validation/memory_monitor.py +179 -0
  426. app/shared/services/validation/postprocess.py +208 -0
  427. app/shared/services/validation/progress.py +64 -0
  428. app/shared/services/validation/report_export.py +222 -0
  429. app/shared/services/validation/resolver.py +180 -0
  430. app/shared/services/validation/service.py +418 -0
  431. app/shared/services/validation/types.py +238 -0
  432. app/shared/services/validation/validators/__init__.py +36 -0
  433. app/shared/services/validation/validators/adapter.py +182 -0
  434. app/shared/services/validation/validators/base.py +332 -0
  435. app/shared/services/validation/validators/composite.py +233 -0
  436. app/shared/services/validation/validators/date_logic.py +276 -0
  437. app/start_server.py +133 -0
  438. precis_cli-0.1.3.dist-info/METADATA +180 -0
  439. precis_cli-0.1.3.dist-info/RECORD +442 -0
  440. precis_cli-0.1.3.dist-info/WHEEL +5 -0
  441. precis_cli-0.1.3.dist-info/entry_points.txt +4 -0
  442. precis_cli-0.1.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,296 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ #
3
+ # Copyright 2026 Precis Team
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ """@fileoverview Agent 工具注册表
17
+
18
+ 功能概述:
19
+ - 注册和管理 Agent 可调用的工具
20
+ - 提供工具定义(OpenAI tools 格式)和分发执行
21
+ - 支持同步和异步工具函数
22
+
23
+ 架构设计:
24
+ - 每个工具包含:名称、描述、参数 schema、执行函数、可选的入参校验模型
25
+ - 工具描述和参数 schema 用于构造 OpenAI tools 定义
26
+ - 入参校验模型(Pydantic)在 execute 入口拦截"必填缺失/类型错误",统一回灌结构化错误
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import asyncio
32
+ import inspect
33
+ import json
34
+ import logging
35
+ from collections.abc import Callable
36
+ from typing import Any, Protocol
37
+
38
+ from pydantic import BaseModel, ValidationError
39
+
40
+ from app.shared.services.ai.agent.types import ToolCall, ToolResult
41
+
42
+ logger = logging.getLogger(__name__)
43
+
44
+ ToolHandler = Callable[[dict[str, Any]], Any]
45
+
46
+
47
+ class ToolInstance(Protocol):
48
+ """可注册工具的鸭子类型接口(NAME/get_definition/run 三件套)。
49
+
50
+ generation 工具(tools/)与 chat 工具(chat_tools/)无共同基类,
51
+ 均按此形状实现;register_tool 按本协议接收任意一族工具实例。
52
+ """
53
+
54
+ NAME: str
55
+
56
+ def get_definition(self) -> dict[str, Any]: ...
57
+
58
+ def run(self, arguments: dict[str, Any]) -> Any: ...
59
+
60
+
61
+ def _format_validation_error(err: ValidationError) -> str:
62
+ """把 Pydantic 校验错误格式化为对 LLM 友好的简短文本。
63
+
64
+ 例如:'参数校验失败: table_name 字段缺失; sample_rows 不是合法的 integer'
65
+ 帮助 LLM 在下一轮修正参数重试(配合 P0-1 的错误回灌机制)。
66
+ """
67
+ parts: list[str] = []
68
+ for e in err.errors():
69
+ # loc 形如 ('table_name',) 或 ('actions', 0, 'actionType')
70
+ loc = ".".join(str(x) for x in e["loc"]) if e.get("loc") else "<root>"
71
+ msg = e.get("msg", "校验失败")
72
+ parts.append(f"{loc}: {msg}")
73
+ return "参数校验失败: " + "; ".join(parts)
74
+
75
+
76
+ class ToolRegistry:
77
+ """
78
+ @classdesc Agent 工具注册表
79
+
80
+ 管理工具定义和分发执行。
81
+ """
82
+
83
+ def __init__(self) -> None:
84
+ """初始化空注册表。"""
85
+ self._tools: dict[str, dict[str, Any]] = {}
86
+ self._handlers: dict[str, ToolHandler] = {}
87
+ self._args_models: dict[str, type[BaseModel] | None] = {}
88
+ # P2-3:工具读写标记,用于 execute_many 分流(写盘工具串行、只读工具并发)。
89
+ # 未显式声明的工具默认视为写盘(保守策略,避免误判导致并发写盘竞态)。
90
+ self._read_only_flags: dict[str, bool] = {}
91
+
92
+ def register(
93
+ self,
94
+ name: str,
95
+ description: str,
96
+ parameters: dict[str, Any],
97
+ handler: ToolHandler,
98
+ args_model: type[BaseModel] | None = None,
99
+ read_only: bool = False,
100
+ ) -> None:
101
+ """
102
+ @methoddesc 注册工具
103
+
104
+ 参数:
105
+ name: 工具名称
106
+ description: 工具描述
107
+ parameters: JSON Schema 格式的参数定义
108
+ handler: 工具执行函数,接收 arguments dict,返回 dict 或 str
109
+ args_model: 可选的 Pydantic 入参模型;提供时 execute 入口会先做结构校验,
110
+ 失败则返回带详细错误信息的 ToolResult(不调 handler),驱动 LLM 自我修正。
111
+ 未提供时保持原透传行为,向后兼容。
112
+ read_only: 工具是否为纯只读(不写盘)。execute_many 据此分流——只读工具并发执行,
113
+ 写盘工具串行执行(避免同一轮多个 apply 并发改文件竞态)。默认 False(保守视为写盘)。
114
+ """
115
+ self._tools[name] = {
116
+ "type": "function",
117
+ "function": {
118
+ "name": name,
119
+ "description": description,
120
+ "parameters": parameters,
121
+ },
122
+ }
123
+ self._handlers[name] = handler
124
+ self._args_models[name] = args_model
125
+ self._read_only_flags[name] = read_only
126
+
127
+ def register_tool(
128
+ self,
129
+ tool: ToolInstance,
130
+ *,
131
+ read_only: bool = False,
132
+ args_model: type[BaseModel] | None = None,
133
+ ) -> None:
134
+ """
135
+ @methoddesc 从工具实例注册(name/description/parameters/handler 自动提取)
136
+
137
+ 工具族(tools/ 与 chat_tools/)的统一注册入口:三处装配点
138
+ (chat_agent_runner / migrate_service / generation agent_wiring)
139
+ 此前各自手写"get_definition 拆字段 + lambda 包装 run"的同构样板,
140
+ 收敛到这里防止注册参数漂移。
141
+
142
+ 参数:
143
+ tool: 实现 NAME/get_definition/run 三件套的工具实例
144
+ read_only: 是否纯只读(不写盘)。execute_many 据此分流——只读并发、写盘串行。默认 False(保守视为写盘)
145
+ args_model: 可选的 Pydantic 入参模型,语义同 register
146
+ """
147
+ definition = tool.get_definition()["function"]
148
+ self.register(
149
+ name=tool.NAME,
150
+ description=definition["description"],
151
+ parameters=definition["parameters"],
152
+ handler=lambda arguments: tool.run(arguments),
153
+ args_model=args_model,
154
+ read_only=read_only,
155
+ )
156
+
157
+ def get_definitions(self) -> list[dict[str, Any]]:
158
+ """获取 OpenAI tools 定义列表。"""
159
+ return list(self._tools.values())
160
+
161
+ async def execute(self, call: ToolCall) -> ToolResult:
162
+ """
163
+ @methoddesc 执行工具调用
164
+
165
+ 参数:
166
+ call: 工具调用请求
167
+
168
+ 返回:
169
+ ToolResult 结果对象
170
+ """
171
+ handler = self._handlers.get(call.name)
172
+ if handler is None:
173
+ return ToolResult(
174
+ call_id=call.id,
175
+ name=call.name,
176
+ success=False,
177
+ observation="",
178
+ error=f"未知工具: {call.name}",
179
+ )
180
+
181
+ # P1-1:入参结构校验。若注册时提供了 args_model,先用 Pydantic 校验 LLM 的入参,
182
+ # 拦截必填缺失/类型错误等结构问题,把结构化错误回灌给 LLM(不调 handler)。
183
+ # 注意:校验通过后仍传 *原始* call.arguments 给 handler,避免 model_dump 的
184
+ # 类型转换副作用(如 Any 字段、嵌套 dict 经 dump 后可能变化)。
185
+ args_model = self._args_models.get(call.name)
186
+ if args_model is not None:
187
+ try:
188
+ args_model.model_validate(call.arguments)
189
+ except ValidationError as e:
190
+ logger.warning(f"工具 {call.name} 入参校验失败: {e}")
191
+ return ToolResult(
192
+ call_id=call.id,
193
+ name=call.name,
194
+ success=False,
195
+ observation="",
196
+ error=_format_validation_error(e),
197
+ )
198
+
199
+ try:
200
+ result = handler(call.arguments)
201
+ if inspect.isawaitable(result):
202
+ result = await result
203
+
204
+ if isinstance(result, ToolResult):
205
+ return result
206
+
207
+ if isinstance(result, dict):
208
+ return ToolResult(
209
+ call_id=call.id,
210
+ name=call.name,
211
+ success=result.get("success", True),
212
+ observation=result,
213
+ error=result.get("error"),
214
+ )
215
+
216
+ return ToolResult(
217
+ call_id=call.id,
218
+ name=call.name,
219
+ success=True,
220
+ observation=str(result),
221
+ )
222
+ except Exception as e:
223
+ logger.exception(f"工具执行失败 {call.name}: {e}")
224
+ return ToolResult(
225
+ call_id=call.id,
226
+ name=call.name,
227
+ success=False,
228
+ observation="",
229
+ error=f"工具执行异常: {e}",
230
+ )
231
+
232
+ async def execute_many(self, calls: list[ToolCall]) -> list[ToolResult]:
233
+ """执行多个工具调用,保持结果顺序与 calls 对齐。
234
+
235
+ P2-3 分流策略(避免同轮并发写盘竞态):
236
+ - 只读工具(read_only=True):并发执行(asyncio.gather),互不影响
237
+ - 写盘工具(read_only=False):串行执行,避免同一轮多个 apply 并发改同一/相关文件
238
+ - 两类工具的执行结果按原始 calls 顺序回填,保持 _collect_audit_trail 依赖的顺序对齐契约
239
+
240
+ 单个工具异常仍走 execute 内部的兜底(返回 success=False 的 ToolResult),
241
+ 不影响其他工具;BaseException(asyncio.gather 罕见)兜底为占位 ToolResult。
242
+ """
243
+ if not calls:
244
+ return []
245
+
246
+ # 按读写标记分流,记录原始下标以便最后按序回填
247
+ read_only_indices: list[int] = []
248
+ write_indices: list[int] = []
249
+ for i, call in enumerate(calls):
250
+ if self._read_only_flags.get(call.name, False):
251
+ read_only_indices.append(i)
252
+ else:
253
+ write_indices.append(i)
254
+
255
+ # 预分配结果容器(按下标对齐 calls)
256
+ results: list[ToolResult | None] = [None] * len(calls)
257
+
258
+ # 只读工具并发
259
+ if read_only_indices:
260
+ ro_results = await asyncio.gather(
261
+ *[self.execute(calls[i]) for i in read_only_indices], return_exceptions=True
262
+ )
263
+ for idx, r in zip(read_only_indices, ro_results, strict=True):
264
+ results[idx] = (
265
+ r
266
+ if not isinstance(r, BaseException)
267
+ else ToolResult(call_id="", name="", success=False, observation="", error=str(r))
268
+ )
269
+
270
+ # 写盘工具串行(按原始顺序)
271
+ for i in write_indices:
272
+ try:
273
+ results[i] = await self.execute(calls[i])
274
+ except BaseException as e: # noqa: BLE001 — 兜底,与 gather 分支保持一致
275
+ results[i] = ToolResult(call_id="", name="", success=False, observation="", error=str(e))
276
+
277
+ # 全部填满(读写分流覆盖了所有下标),返回非 None 列表
278
+ return [
279
+ r if r is not None else ToolResult(call_id="", name="", success=False, observation="", error="未执行")
280
+ for r in results
281
+ ]
282
+
283
+ def parse_tool_call(self, raw: dict[str, Any]) -> ToolCall:
284
+ """从 LLM 返回的 tool_call dict 解析为 ToolCall。"""
285
+ func = raw.get("function", {})
286
+ arguments = func.get("arguments")
287
+ if isinstance(arguments, str):
288
+ try:
289
+ arguments = json.loads(arguments)
290
+ except json.JSONDecodeError:
291
+ arguments = {"raw": arguments}
292
+ return ToolCall(
293
+ id=raw.get("id", ""),
294
+ name=func.get("name", ""),
295
+ arguments=arguments or {},
296
+ )
@@ -0,0 +1,32 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ #
3
+ # Copyright 2026 Precis Team
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ """Agent 工具模块"""
17
+
18
+ from app.shared.services.ai.agent.tools.config_generate import ConfigGenerateTool
19
+ from app.shared.services.ai.agent.tools.config_refine import ConfigRefineTool
20
+ from app.shared.services.ai.agent.tools.config_validate import ConfigValidateTool
21
+ from app.shared.services.ai.agent.tools.merge_results import MergeResultsTool
22
+ from app.shared.services.ai.agent.tools.plan_chunks import PlanChunksTool
23
+ from app.shared.services.ai.agent.tools.script_parse import ScriptParseTool
24
+
25
+ __all__ = [
26
+ "ConfigGenerateTool",
27
+ "ConfigRefineTool",
28
+ "ConfigValidateTool",
29
+ "MergeResultsTool",
30
+ "PlanChunksTool",
31
+ "ScriptParseTool",
32
+ ]
@@ -0,0 +1,133 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ #
3
+ # Copyright 2026 Precis Team
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ """@fileoverview 配置生成工具
17
+
18
+ Agent 可调用的工具:根据数据画像生成 Precis V2 配置。
19
+ 支持按 scope 生成局部配置,也支持基于上一轮结果增量生成。
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import logging
25
+ from typing import TYPE_CHECKING, Any
26
+
27
+ if TYPE_CHECKING:
28
+ from app.shared.services.llm.generation.service import ConfigGenerationService
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ class ConfigGenerateTool:
34
+ """
35
+ @classdesc 配置生成工具
36
+
37
+ 封装 build_prompt + LLM 调用 + build_config。
38
+ """
39
+
40
+ NAME = "generate_config"
41
+
42
+ def __init__(self, service: ConfigGenerationService):
43
+ """
44
+ @methoddesc 初始化工具
45
+
46
+ 参数:
47
+ service: ConfigGenerationService 实例
48
+ """
49
+ self.service = service
50
+
51
+ def get_definition(self) -> dict[str, Any]:
52
+ """返回 OpenAI tool 定义。"""
53
+ return {
54
+ "type": "function",
55
+ "function": {
56
+ "name": self.NAME,
57
+ "description": (
58
+ "根据数据画像生成或修正 Precis V2 项目配置(schemas、constraints、regex_nodes)。"
59
+ "这是最终输出工具:调用成功后,返回的 config 会被 Agent 直接作为最终结果返回给用户,"
60
+ "不需要再输出 JSON 文本或调用其他工具。"
61
+ ),
62
+ "parameters": {
63
+ "type": "object",
64
+ "properties": {
65
+ "scope": {
66
+ "type": "object",
67
+ "description": "生成范围,包含 file_paths、columns 等",
68
+ "properties": {
69
+ "file_paths": {
70
+ "type": "array",
71
+ "items": {"type": "string"},
72
+ "description": "要分析的文件路径列表",
73
+ },
74
+ "columns": {
75
+ "type": "array",
76
+ "items": {"type": "string"},
77
+ "description": "可选,仅分析指定列(格式:table.column)",
78
+ },
79
+ "table_names": {
80
+ "type": "array",
81
+ "items": {"type": "string"},
82
+ "description": "可选,仅分析指定表",
83
+ },
84
+ },
85
+ },
86
+ "instructions": {
87
+ "type": "string",
88
+ "description": "生成指令,如'尽量只生成关键规则'、'补充缺失的外键规则'等",
89
+ },
90
+ "previous_config": {
91
+ "type": "object",
92
+ "description": "可选,上一轮生成的配置,用于增量修正",
93
+ },
94
+ },
95
+ "required": ["scope"],
96
+ },
97
+ },
98
+ }
99
+
100
+ async def run(self, arguments: dict[str, Any]) -> dict[str, Any]:
101
+ """
102
+ @methoddesc 执行配置生成
103
+
104
+ 参数:
105
+ arguments: tool 参数
106
+
107
+ 返回:
108
+ {"success": bool, "config": {...}, "warnings": [...], "error": str}
109
+ """
110
+ scope = arguments.get("scope", {})
111
+ instructions = arguments.get("instructions", "")
112
+ previous_config = arguments.get("previous_config")
113
+
114
+ file_paths = scope.get("file_paths", self.service._file_paths)
115
+ if not file_paths:
116
+ return {"success": False, "error": "未指定数据文件路径"}
117
+
118
+ try:
119
+ result = await self.service._generate_config_for_scope(
120
+ file_paths=file_paths,
121
+ instructions=instructions,
122
+ previous_config=previous_config,
123
+ scope=scope,
124
+ )
125
+ return {
126
+ "success": True,
127
+ "config": result,
128
+ "warnings": result.get("warnings", []),
129
+ "is_final_config": True,
130
+ }
131
+ except Exception as e:
132
+ logger.exception("配置生成工具执行失败")
133
+ return {"success": False, "error": f"配置生成失败: {e}"}
@@ -0,0 +1,109 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ #
3
+ # Copyright 2026 Precis Team
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ """@fileoverview 配置精修工具
17
+
18
+ Agent 可调用的工具:根据校验结果让 LLM 修正配置。
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import logging
24
+ from typing import Any
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ class ConfigRefineTool:
30
+ """
31
+ @classdesc 配置精修工具
32
+
33
+ 根据校验问题生成修正建议或修正后的配置。
34
+ """
35
+
36
+ NAME = "refine_config"
37
+
38
+ def __init__(self, service: Any):
39
+ """
40
+ @methoddesc 初始化工具
41
+
42
+ 参数:
43
+ service: ConfigGenerationService 实例
44
+ """
45
+ self.service = service
46
+
47
+ def get_definition(self) -> dict[str, Any]:
48
+ """返回 OpenAI tool 定义。"""
49
+ return {
50
+ "type": "function",
51
+ "function": {
52
+ "name": self.NAME,
53
+ "description": "根据校验结果修正配置,输出修正后的完整配置。",
54
+ "parameters": {
55
+ "type": "object",
56
+ "properties": {
57
+ "config": {
58
+ "type": "object",
59
+ "description": "当前配置",
60
+ },
61
+ "issues": {
62
+ "type": "array",
63
+ "items": {"type": "object"},
64
+ "description": "校验发现的问题列表",
65
+ },
66
+ "strategy": {
67
+ "type": "string",
68
+ "description": "修正策略,如'relax'(放宽)、'remove'(删除)、'adjust'(调整参数)",
69
+ "enum": ["relax", "remove", "adjust", "auto"],
70
+ },
71
+ },
72
+ "required": ["config", "issues"],
73
+ },
74
+ },
75
+ }
76
+
77
+ async def run(self, arguments: dict[str, Any]) -> dict[str, Any]:
78
+ """
79
+ @methoddesc 执行配置精修
80
+
81
+ 参数:
82
+ arguments: tool 参数
83
+
84
+ 返回:
85
+ {"success": bool, "config": {...}, "removed_rules": [...], "warnings": [...], "error": str}
86
+ """
87
+ config = arguments.get("config", {})
88
+ issues = arguments.get("issues", [])
89
+ strategy = arguments.get("strategy", "auto")
90
+
91
+ if not issues:
92
+ return {"success": True, "config": config, "removed_rules": [], "warnings": []}
93
+
94
+ try:
95
+ result = await self.service._refine_config_with_llm(
96
+ config=config,
97
+ issues=issues,
98
+ strategy=strategy,
99
+ )
100
+ return {
101
+ "success": True,
102
+ "config": result.get("config", config),
103
+ "removed_rules": result.get("removed_rules", []),
104
+ "modified_rules": result.get("modified_rules", []),
105
+ "warnings": result.get("warnings", []),
106
+ }
107
+ except Exception as e:
108
+ logger.exception("配置精修工具执行失败")
109
+ return {"success": False, "error": f"配置精修失败: {e}"}