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,220 @@
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
+ 功能概述:
19
+ - ReportService 统一管理和调度所有激活的报告者策略
20
+ - 支持本地文件、邮件、企业微信、飞书、钉钉等多种报告渠道
21
+ - 从 YAML 配置文件读取报告器配置,动态加载和初始化
22
+
23
+ 架构设计:
24
+ - 注册表模式: _reporter_registry 将配置名称映射到具体报告器类
25
+ - 配置驱动: 通过 reporting_config.yaml 控制启用哪些报告器
26
+ - 全局配置注入: 自动将全局配置(如 log_dir)合并到各报告器的配置中
27
+ - 故障隔离: 单个报告器配置失败不影响其他报告器的正常工作
28
+
29
+ 输入示例:
30
+ YAML 配置文件 (reporting_config.yaml):
31
+ reporters:
32
+ local_file:
33
+ enabled: true
34
+ email:
35
+ enabled: true
36
+ smtp_server: "smtp.example.com"
37
+ smtp_port: 587
38
+ sender_email: "precis@example.com"
39
+ sender_password: "secret"
40
+ receiver_email: "admin@example.com"
41
+
42
+ 调用代码:
43
+ report_service = ReportService(base_dir="/path/to/project")
44
+ report_service.report(errors)
45
+
46
+ 输出示例:
47
+ 控制台输出:
48
+ 报告服务已初始化。
49
+ 正在配置报告者: 'local_file'...
50
+ [LocalFileReporter] 日志目录已创建: /path/to/project/logs
51
+ 正在配置报告者: 'email'...
52
+ [EmailReporter] ✓ 邮件服务配置验证成功,发件人: precis@example.com
53
+ 报告服务配置完成,共激活 2 个报告者。
54
+ --- 开始报告 5 个错误 ---
55
+ [LocalFileReporter] ✓ 成功将错误报告写入本地日志: ...
56
+ [EmailReporter] ✓ 成功发送错误报告邮件至 admin@example.com。
57
+ --- 报告流程结束 ---
58
+ """
59
+
60
+ import json
61
+ import logging
62
+ import os
63
+ from collections.abc import Callable
64
+
65
+ import yaml
66
+
67
+ from .reporters import (
68
+ DingTalkAppReporter,
69
+ EmailReporter,
70
+ FeishuReporter,
71
+ LocalFileReporter,
72
+ Reporter,
73
+ WeComAppReporter,
74
+ )
75
+
76
+ logger = logging.getLogger(__name__)
77
+
78
+ # ==============================================================================
79
+ # 报告服务中心
80
+ # ==============================================================================
81
+
82
+
83
+ class ReportService:
84
+ """
85
+ @classdesc 报告服务中心类。
86
+
87
+ 负责管理和调度所有激活的报告者策略。
88
+ 在初始化时从配置文件加载需要启用的报告者,
89
+ 在报告时将错误信息发送给所有激活的报告者。
90
+
91
+ 【属性说明】
92
+ - base_dir: 项目根目录路径
93
+ - config_path: 报告配置文件完整路径
94
+ - _reporter_registry: 报告者注册表(名称到类的映射)
95
+ - _active_reporters: 已激活的报告者实例列表
96
+
97
+ 【使用示例】
98
+ >>> report_service = ReportService(base_dir='/path/to/project')
99
+ >>> errors = [{'error_type': 'ValidationError', 'message': '数据校验失败'}]
100
+ >>> report_service.report(errors)
101
+ """
102
+
103
+ def __init__(self, base_dir: str, config_filename: str = "reporting_config.yaml"):
104
+ """
105
+ 初始化报告服务中心。
106
+
107
+ 【初始化流程】
108
+ 1. 设置项目根目录和配置文件路径
109
+ 2. 初始化报告者注册表
110
+ 3. 调用 _load_and_configure_reporters 加载配置
111
+
112
+ :param base_dir: 项目根目录路径
113
+ :param config_filename: 配置文件名,默认 'reporting_config.yaml'
114
+ """
115
+ self.base_dir = base_dir
116
+ self.config_path = os.path.join(base_dir, config_filename)
117
+
118
+ # 报告者注册表:将配置中的名称映射到对应的报告者类
119
+ self._reporter_registry: dict[str, Callable[[], Reporter]] = {
120
+ "local_file": LocalFileReporter,
121
+ "email": EmailReporter,
122
+ "wecom": WeComAppReporter,
123
+ "feishu": FeishuReporter,
124
+ "dingtalk": DingTalkAppReporter,
125
+ }
126
+
127
+ # 激活的报告者实例列表
128
+ self._active_reporters: list[Reporter] = []
129
+ logger.info("报告服务已初始化。")
130
+ self._load_and_configure_reporters()
131
+
132
+ def _load_and_configure_reporters(self) -> None:
133
+ """
134
+ @methoddesc 从配置文件加载并配置所有需要启用的报告者。
135
+
136
+ 【处理流程】
137
+ 1. 检查配置文件是否存在
138
+ 2. 读取并解析 YAML 配置文件
139
+ 3. 遍历配置中的 reporters 节点
140
+ 4. 对每个启用的报告者进行实例化和配置
141
+ 5. 将配置成功的报告者添加到激活列表
142
+
143
+ 【配置合并规则】
144
+ - 全局配置(如 log_dir)会被自动注入
145
+ - 报告者特定配置会覆盖全局配置
146
+ """
147
+ # 检查配置文件是否存在
148
+ if not os.path.exists(self.config_path):
149
+ logger.warning("报告配置文件 '%s' 未找到, 将不启用任何报告服务。", self.config_path)
150
+ return
151
+
152
+ try:
153
+ # 读取并解析 YAML 配置文件
154
+ with open(self.config_path, encoding="utf-8") as f:
155
+ config = yaml.safe_load(f) or {}
156
+ except Exception as e:
157
+ logger.error("读取报告配置文件失败: %s", e)
158
+ return
159
+
160
+ # 全局配置,可被所有报告者共享
161
+ global_config = {"log_dir": os.path.join(self.base_dir, "logs")}
162
+
163
+ # 遍历配置文件中定义的 reporters(§1.29: reporters 键为 null 时 `or {}` 兜底,
164
+ # 单条目为 null 时跳过并警告——报告是"坏了就跳过"的可选件,不拖崩校验流程)
165
+ reporters = config.get("reporters") or {}
166
+ for reporter_name, reporter_config in reporters.items():
167
+ if reporter_config is None:
168
+ logger.warning("报告者 '%s' 配置为空,跳过。", reporter_name)
169
+ continue
170
+ # 检查报告者是否启用
171
+ if not reporter_config.get("enabled", False):
172
+ logger.info("报告者 '%s' 未启用,跳过。", reporter_name)
173
+ continue
174
+
175
+ # 检查报告者是否在注册表中
176
+ if reporter_name in self._reporter_registry:
177
+ reporter_class = self._reporter_registry[reporter_name]
178
+ reporter_instance = reporter_class()
179
+
180
+ # 合并全局配置和特定配置
181
+ full_config = {**global_config, **reporter_config}
182
+
183
+ logger.info("正在配置报告者: '%s'...", reporter_name)
184
+ if reporter_instance.configure(**full_config):
185
+ self._active_reporters.append(reporter_instance)
186
+ else:
187
+ logger.warning("报告者 '%s' 配置失败,将不被激活。", reporter_name)
188
+ else:
189
+ logger.warning("在报告者注册表中未找到名为 '%s' 的报告者。", reporter_name)
190
+
191
+ logger.info("报告服务配置完成,共激活 %d 个报告者。", len(self._active_reporters))
192
+
193
+ def report(self, errors: list[dict]) -> None:
194
+ """
195
+ @methoddesc 执行总报告流程。
196
+ 遍历所有激活的报告者并调用它们的 report 方法。
197
+
198
+ 【处理逻辑】
199
+ 1. 如果错误列表为空,直接返回(无需报告)
200
+ 2. 如果没有激活的报告者,将错误打印到控制台
201
+ 3. 否则,遍历所有激活的报告者发送报告
202
+
203
+ :param errors: 错误信息字典列表
204
+ """
205
+ # 无错误时直接返回
206
+ if not errors:
207
+ logger.info("未发现错误,无需报告。")
208
+ return
209
+
210
+ # 无激活报告者时,打印到控制台作为后备(保留 print 确保错误在低日志级别下仍可见)
211
+ if not self._active_reporters:
212
+ logger.warning("无激活的报告者,错误将不会被报告。仅在控制台显示:")
213
+ print(json.dumps(errors, indent=2, ensure_ascii=False))
214
+ return
215
+
216
+ # 遍历所有激活的报告者发送报告
217
+ logger.info("--- 开始报告 %d 个错误 ---", len(errors))
218
+ for reporter in self._active_reporters:
219
+ reporter.report(errors)
220
+ logger.info("--- 报告流程结束 ---")
@@ -0,0 +1,65 @@
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
+ """
17
+ @fileoverview 报告器实现统一导出模块
18
+
19
+ 功能概述:
20
+ - 聚合导出所有内置报告器实现(本地文件、邮件、企业微信、飞书、钉钉)
21
+ - 提供 Reporter 抽象基类统一入口
22
+
23
+ 架构设计:
24
+ - 注册表模式: 各报告器实现继承自 Reporter 基类
25
+ - 统一导出: 通过 __all__ 控制对外可见的报告器列表
26
+ - 便于扩展: 新增报告器时只需在此添加导入和 __all__ 列表
27
+
28
+ 输入示例:
29
+ 从外部导入所需的报告器:
30
+ from backend.app.shared.core.reporter.reporters import (
31
+ Reporter, # 抽象基类,用于自定义报告器
32
+ LocalFileReporter, # 本地文件报告器
33
+ EmailReporter, # 邮件报告器
34
+ WeComAppReporter, # 企业微信报告器
35
+ FeishuReporter, # 飞书报告器
36
+ DingTalkAppReporter # 钉钉报告器
37
+ )
38
+
39
+ 输出示例:
40
+ 导出的报告器列表:
41
+ __all__ = [
42
+ "Reporter",
43
+ "LocalFileReporter",
44
+ "EmailReporter",
45
+ "WeComAppReporter",
46
+ "FeishuReporter",
47
+ "DingTalkAppReporter",
48
+ ]
49
+ """
50
+
51
+ from .base import Reporter
52
+ from .dingtalk_app_reporter import DingTalkAppReporter
53
+ from .email_reporter import EmailReporter
54
+ from .feishu_app_reporter import FeishuReporter
55
+ from .local_file_reporter import LocalFileReporter
56
+ from .wecom_app_reporter import WeComAppReporter
57
+
58
+ __all__ = [
59
+ "Reporter",
60
+ "LocalFileReporter",
61
+ "EmailReporter",
62
+ "WeComAppReporter",
63
+ "FeishuReporter",
64
+ "DingTalkAppReporter",
65
+ ]
@@ -0,0 +1,188 @@
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
+ 功能概述:
19
+ - 定义所有报告器的统一接口(Strategy 模式)
20
+ - 提供 configure() 和 report() 抽象方法
21
+ - 强制子类实现配置和报告的标准化流程
22
+
23
+ 架构设计:
24
+ - 策略模式 (Strategy Pattern): 将不同的报告渠道封装为可互换的算法
25
+ - 模板方法模式: 定义 report() 和 configure() 的标准接口,子类负责具体实现
26
+ - 依赖倒置: 高层模块(ReportService)依赖抽象(Reporter),而非具体实现
27
+
28
+ 输入示例:
29
+ 子类实现示例:
30
+ class MyReporter(Reporter):
31
+ def configure(self, **config) -> bool:
32
+ # 验证并保存配置
33
+ self.webhook_url = config.get("webhook_url")
34
+ return bool(self.webhook_url)
35
+
36
+ def report(self, errors: list[dict]):
37
+ # 发送错误报告到自定义渠道
38
+ requests.post(self.webhook_url, json=errors)
39
+
40
+ 输出示例:
41
+ 客户端代码无需关心具体实现:
42
+ reporter: Reporter = EmailReporter() # 或任何其他报告器
43
+ if reporter.configure(**config):
44
+ reporter.report(errors)
45
+ """
46
+
47
+ from abc import ABC, abstractmethod
48
+ from typing import Any
49
+ from urllib.parse import urlparse
50
+
51
+ # 截断后追加的省略标记(各报告器共用,保证提示语义一致)
52
+ TRUNCATION_SUFFIX = "\n... (内容过长,已截断)"
53
+
54
+ # 各报告器的消息模板在 error_details 之外还含标题/时间戳/代码块围栏等固定文本,
55
+ # 截断上限需为其预留字节余量,保证整条消息编码后不超过平台限额
56
+ TEMPLATE_HEADROOM_BYTES = 256
57
+
58
+
59
+ def sanitize_url_for_log(url: str) -> str:
60
+ """脱敏 URL 用于日志输出:只保留 scheme://host/path,丢弃 query/fragment。
61
+
62
+ Webhook/Token 类 URL 的凭证(token、corpsecret 等)几乎都在 query 中,
63
+ 异常日志打印完整 URL 会把密钥写进日志文件。此函数只保留主机与路径。
64
+
65
+ Args:
66
+ url: 原始 URL(可能含敏感 query)
67
+
68
+ Returns:
69
+ 形如 "https://open.feishu.cn/open-apis/bot/v2/hook/xxx" 的脱敏 URL;
70
+ 解析失败时返回 "<invalid-url>"(不抛异常,日志路径不允许二次失败)。
71
+ """
72
+ try:
73
+ parsed = urlparse(url)
74
+ if parsed.scheme and parsed.netloc:
75
+ return f"{parsed.scheme}://{parsed.netloc}{parsed.path}"
76
+ return "<invalid-url>"
77
+ except Exception: # noqa: BLE001 日志脱敏兜底,任何解析异常都降级为占位符
78
+ return "<invalid-url>"
79
+
80
+
81
+ def truncate_to_byte_limit(text: str, max_bytes: int, suffix: str = TRUNCATION_SUFFIX) -> str:
82
+ """按 UTF-8 字节数上限截断文本,超限时追加省略标记。
83
+
84
+ 平台(飞书/钉钉/企业微信)的消息限额按字节数计算。过去"按字节检查、按字符截断"
85
+ 的做法对中文内容无效:每个汉字 UTF-8 占 3 字节,按字符截掉一半后实际字节数
86
+ 仍可能超限,消息会被平台拒收。
87
+
88
+ 规则:
89
+ - 原文未超限则原样返回;
90
+ - 超限时按编码后字节累积截断,并回退到 UTF-8 字符边界(不截在多字节字符中间),
91
+ 追加省略标记后总长(含标记)仍不超过 max_bytes。
92
+
93
+ Args:
94
+ text: 原始文本
95
+ max_bytes: 允许的最大 UTF-8 字节数
96
+ suffix: 截断时追加的省略标记
97
+
98
+ Returns:
99
+ 截断后的字符串(UTF-8 编码后不超过 max_bytes 字节)
100
+ """
101
+ encoded = text.encode("utf-8")
102
+ if len(encoded) <= max_bytes:
103
+ return text
104
+
105
+ suffix_bytes = suffix.encode("utf-8")
106
+ limit = max_bytes - len(suffix_bytes)
107
+ if limit <= 0:
108
+ # 防御:上限比省略标记还小,直接返回空串,保证总长不超限
109
+ return ""
110
+
111
+ # 从末尾回退,跳过 UTF-8 多字节序列的续字节(0b10xxxxxx),避免截在字符中间
112
+ while limit > 0 and (encoded[limit] & 0xC0) == 0x80:
113
+ limit -= 1
114
+
115
+ return encoded[:limit].decode("utf-8", errors="ignore") + suffix
116
+
117
+
118
+ class Reporter(ABC):
119
+ """
120
+ @classdesc 报告器抽象基类
121
+
122
+ 该类定义了所有报告器必须实现的接口规范。
123
+ 采用策略模式,任何需要报告数据验证错误的模块都可以通过统一的接口调用不同的报告策略。
124
+
125
+ 属性说明:
126
+ name: 报告器实例的名称,用于日志和调试标识
127
+
128
+ 使用示例:
129
+ # 客户端代码不关心具体使用哪种报告器
130
+ reporter: Reporter = EmailReporter()
131
+ reporter.configure(**email_config)
132
+ reporter.report(errors)
133
+ """
134
+
135
+ def __init__(self, name: str):
136
+ """
137
+ 初始化报告器实例
138
+
139
+ :param name: 报告器的名称,用于日志输出和调试追踪
140
+ """
141
+ self.name = name
142
+
143
+ @abstractmethod
144
+ def configure(self, **config: Any) -> bool:
145
+ """
146
+ @methoddesc 配置当前报告器
147
+
148
+ 这是一个抽象方法,每个子类必须实现自己的配置逻辑。
149
+ 配置通常包括连接信息、认证凭证、目标路径等。
150
+
151
+ :param config: 关键字参数,包含特定报告器的配置选项
152
+ 不同的报告器子类有不同的配置要求
153
+ :return: 配置是否成功。返回 True 表示配置生效,可以调用 report();
154
+ 返回 False 表示配置失败,需要检查配置参数或日志
155
+
156
+ 子类实现注意事项:
157
+ - 应该验证所有必需的配置参数
158
+ - 应该在失败时打印详细的错误信息
159
+ - 可以选择在配置阶段建立连接(如邮件SMTP连接)进行验证
160
+ """
161
+ pass
162
+
163
+ @abstractmethod
164
+ def report(self, errors: list[dict]) -> None:
165
+ """
166
+ @methoddesc 执行报告操作,将错误信息发送或写入指定目标
167
+
168
+ 这是一个抽象方法,每个子类必须实现自己的报告逻辑。
169
+ 在调用此方法之前,必须确保 configure() 已经成功调用。
170
+
171
+ :param errors: 错误信息的字典列表
172
+ 每个字典代表一个独立的验证错误
173
+ 标准格式包含:row_index, column, value, error_type, error_message
174
+ 不同报告器可能对格式有特定要求
175
+
176
+ 错误字典的推荐字段:
177
+ - row_index: 错误发生的行号(可选,列级别错误可能为 None)
178
+ - column: 涉及的数据列名
179
+ - value: 导致错误的原始值
180
+ - error_type: 错误类型标识(如 'TypeValidationError')
181
+ - error_message: 人类可读的错误描述
182
+
183
+ 子类实现注意事项:
184
+ - 应该检查是否已正确配置(如检查 is_configured 标志)
185
+ - 应该处理空列表的情况(空列表通常不需要报告)
186
+ - 应该在失败时打印错误日志,但不应抛出异常
187
+ """
188
+ pass