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,352 @@
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 AI API 请求/响应 Pydantic 模型定义模块
18
+
19
+ 功能概述:
20
+ - 定义 AI 聊天、Provider 管理、配置生成等 API 的输入输出模型
21
+ - 提供硬件诊断相关的数据模型
22
+ - 支持异步任务的创建、状态、结果模型
23
+
24
+ 架构设计:
25
+ - 按功能区域分块:Provider 管理、配置生成、异步任务、硬件诊断
26
+ - 所有模型继承自 Pydantic BaseModel,支持自动校验和序列化
27
+ - 使用 Field 定义字段描述和默认值
28
+
29
+ 输入示例:
30
+ class ConfigGenerateRequest(BaseModel):
31
+ file_paths: list[str]
32
+ project_name: str
33
+ options: ConfigGenerateOptions = Field(default_factory=ConfigGenerateOptions)
34
+
35
+ 输出示例:
36
+ class ConfigGenerateResponse(BaseModel):
37
+ success: bool
38
+ yaml_preview: str
39
+ manifest: Optional[dict[str, Any]] = None
40
+ """
41
+
42
+ from typing import Any
43
+
44
+ from pydantic import BaseModel, ConfigDict, Field
45
+
46
+ # =============================================================================
47
+ # Provider 管理模型
48
+ # =============================================================================
49
+
50
+
51
+ class ChatMessageInput(BaseModel):
52
+ """聊天消息输入"""
53
+
54
+ role: str
55
+ content: str
56
+
57
+
58
+ class ChatRequestInput(BaseModel):
59
+ """聊天请求输入"""
60
+
61
+ provider_id: str | None = Field(default=None, description="指定 Provider,不指定则使用默认")
62
+ messages: list[ChatMessageInput]
63
+ stream: bool = False
64
+ model: str | None = Field(default=None, description="覆盖默认模型")
65
+ temperature: float = 0.7
66
+
67
+
68
+ class ChatResponseOutput(BaseModel):
69
+ """聊天响应输出"""
70
+
71
+ content: str
72
+ model: str
73
+
74
+
75
+ class AiChatContextNode(BaseModel):
76
+ """AI Chat 上下文节点"""
77
+
78
+ id: str
79
+ type: str
80
+ data: dict[str, Any]
81
+ label: str | None = None
82
+
83
+
84
+ class AiChatContext(BaseModel):
85
+ """AI Chat 上下文"""
86
+
87
+ hasContext: bool
88
+ selectedNodes: list[AiChatContextNode]
89
+ # 画布全部业务节点快照(前端 serializeCanvasForAI 裁剪后携带),
90
+ # 供 read_canvas 工具查询画布真实状态。默认空 list 保证旧请求/CLI 不破坏。
91
+ canvasNodes: list[AiChatContextNode] = Field(default_factory=list)
92
+
93
+
94
+ class AiChatHistoryMessage(BaseModel):
95
+ """AI Chat 历史消息"""
96
+
97
+ role: str
98
+ content: str
99
+
100
+
101
+ class AiChatRequest(BaseModel):
102
+ """AI Chat 请求输入 (对应前端请求)"""
103
+
104
+ message: str
105
+ context: AiChatContext
106
+ history: list[AiChatHistoryMessage] | None = None
107
+ agent_mode: bool = Field(default=True, description="是否启用 Agent 深度模式")
108
+
109
+
110
+ class AiChatConfirmRequest(BaseModel):
111
+ """AI Chat apply_actions 确认/拒绝请求"""
112
+
113
+ decision: str = Field(..., description="confirm(确认并落盘)或 reject(拒绝,不落盘)")
114
+ apply_id: str | None = Field(
115
+ default=None,
116
+ description="本次 apply 的 ID({job_id}#{seq})。为空时回退到该 job 当前唯一挂起项。",
117
+ )
118
+
119
+
120
+ class AiChatRespondRequest(BaseModel):
121
+ """AI Chat ask_user 提问的回答请求"""
122
+
123
+ ask_id: str = Field(..., description="本次 ask 的 ID({job_id}#ask#{seq})")
124
+ response: dict[str, Any] = Field(
125
+ ...,
126
+ description="用户回答。形如 {answer: ...} 或 {skipped: true, reason: ...}",
127
+ )
128
+
129
+
130
+ class AgentMeta(BaseModel):
131
+ """Agent 模式执行元数据(仅 agent_mode=true 时填充)"""
132
+
133
+ iterations: int = 0
134
+ tool_steps: list[dict[str, Any]] = Field(default_factory=list, description="工具调用轨迹")
135
+
136
+
137
+ class AiChatResponse(BaseModel):
138
+ """AI Chat 响应输出 (对应前端期望)"""
139
+
140
+ status: str
141
+ reply: str
142
+ actions: list[Any]
143
+ frontend_instructions: list[Any]
144
+ agent_meta: AgentMeta | None = None
145
+ error: str | None = None
146
+
147
+
148
+ class ProviderResponse(BaseModel):
149
+ """Provider 响应"""
150
+
151
+ model_config = ConfigDict(populate_by_name=True)
152
+
153
+ id: str
154
+ name: str
155
+ provider: str = Field(alias="type")
156
+ deployment: str
157
+ base_url: str
158
+ model: str
159
+ context_window: int | None = Field(default=None, description="用户指定的上下文窗口,None 表示自动探测/回退")
160
+ health: dict[str, Any]
161
+ is_configured: bool = False
162
+
163
+
164
+ class DiscoverResponse(BaseModel):
165
+ """发现服务响应"""
166
+
167
+ services: list[dict[str, Any]]
168
+ count: int
169
+
170
+
171
+ class TestProviderResponse(BaseModel):
172
+ """测试 Provider 响应"""
173
+
174
+ provider_id: str
175
+ health: dict[str, Any]
176
+ available_models: list[str]
177
+
178
+
179
+ class CreateProviderRequest(BaseModel):
180
+ """创建 Provider 请求"""
181
+
182
+ name: str = Field(..., description="显示名称")
183
+ type: str = Field(default="openai", description="Provider 类型(openai 或 ollama)")
184
+ base_url: str = Field(..., description="API 基础 URL")
185
+ api_key: str | None = Field(default=None, description="API 密钥,本地服务可留空")
186
+ model: str = Field(..., description="默认模型名称")
187
+ context_window: int | None = Field(
188
+ default=None,
189
+ ge=1024,
190
+ description="模型上下文窗口(tokens),留空则自动探测或回退到 200k",
191
+ )
192
+
193
+
194
+ class UpdateProviderRequest(BaseModel):
195
+ """更新 Provider 请求(所有字段可选,仅传递需要更新的字段)"""
196
+
197
+ name: str | None = Field(default=None, description="显示名称")
198
+ type: str | None = Field(default=None, description="Provider 类型")
199
+ base_url: str | None = Field(default=None, description="API 基础 URL")
200
+ api_key: str | None = Field(default=None, description="API 密钥,传空字符串表示清空")
201
+ model: str | None = Field(default=None, description="默认模型名称")
202
+ context_window: int | None = Field(
203
+ default=None,
204
+ ge=1024,
205
+ description="模型上下文窗口(tokens),不传则保持原值,传值则更新",
206
+ )
207
+
208
+
209
+ class ProviderPresetResponse(BaseModel):
210
+ """服务商预设响应"""
211
+
212
+ id: str
213
+ name: str
214
+ type: str
215
+ base_url: str
216
+ default_model: str
217
+ models: list[str]
218
+
219
+
220
+ # =============================================================================
221
+ # 配置生成模型 (新架构)
222
+ # =============================================================================
223
+
224
+
225
+ class ConfigGenerateOptions(BaseModel):
226
+ """配置生成选项"""
227
+
228
+ sample_rows: int = Field(default=100, description="每文件采样行数")
229
+ sample_values_per_column: int = Field(default=100, description="每列采样值数量")
230
+ max_files: int = Field(default=50, description="最大处理文件数")
231
+ max_cell_chars: int = Field(default=500, description="单元格最大字符数")
232
+ generate_schemas: bool = Field(default=True, description="生成表结构")
233
+ generate_constraints: bool = Field(default=True, description="生成约束规则")
234
+ generate_regex_nodes: bool = Field(default=False, description="生成正则节点")
235
+ keep_existing: bool = Field(default=True, description="保留现有配置")
236
+ target_files: list[str] | None = Field(default=None, description="指定目标文件")
237
+ agent_mode: bool = Field(default=True, description="启用 Agent 多轮优化模式")
238
+ max_iterations: int = Field(default=2, ge=1, le=5, description="Agent 最大迭代轮数")
239
+ validation_sample_size: int = Field(default=1000, ge=100, le=10000, description="校验采样行数")
240
+ auto_chunking: bool = Field(default=True, description="大数据量自动分块处理")
241
+ chunk_max_columns: int = Field(default=20, ge=5, le=100, description="分块最大列数")
242
+ chunk_max_files: int = Field(default=5, ge=1, le=20, description="分块最大文件数")
243
+
244
+
245
+ class ConfigGenerateRequest(BaseModel):
246
+ """配置生成请求"""
247
+
248
+ file_paths: list[str] = Field(..., description="数据文件路径列表")
249
+ project_name: str = Field(..., description="项目名称")
250
+ project_id: str = Field(..., description="项目标识")
251
+ provider_id: str | None = Field(default=None, description="指定AI Provider,不指定使用默认")
252
+ options: ConfigGenerateOptions = Field(default_factory=ConfigGenerateOptions)
253
+
254
+
255
+ class ConfigGenerateResponse(BaseModel):
256
+ """配置生成响应(同步)"""
257
+
258
+ success: bool
259
+ yaml_preview: str = Field(..., description="生成的配置YAML预览")
260
+ manifest: dict[str, Any] | None = Field(default=None, description="项目清单")
261
+ schemas: dict[str, Any] | None = Field(default=None, description="表结构定义")
262
+ constraints: dict[str, Any] | None = Field(default=None, description="约束规则")
263
+ regex_nodes: dict[str, Any] | None = Field(default=None, description="正则节点")
264
+ warnings: list[str] = Field(default_factory=list)
265
+ error: str | None = None
266
+ iterations: int | None = Field(default=None, description="Agent 迭代轮数")
267
+ metrics: dict[str, Any] | None = Field(default=None, description="Agent 校验指标")
268
+
269
+
270
+ class ConfigMigrateSource(BaseModel):
271
+ """单个迁移脚本来源"""
272
+
273
+ content: str = Field(..., description="脚本内容或自然语言描述")
274
+ language: str = Field(default="python", description="脚本类型: python/natural_language/excel_formula/sql")
275
+ name: str | None = Field(default=None, description="来源名称或文件路径,用于展示")
276
+
277
+
278
+ class ConfigMigrateRequest(BaseModel):
279
+ """配置迁移请求"""
280
+
281
+ script_content: str = Field(default="", description="脚本内容或自然语言描述(兼容单来源)")
282
+ language: str = Field(default="python", description="脚本类型: python/natural_language/excel_formula/sql")
283
+ sources: list[ConfigMigrateSource] | None = Field(default=None, description="批量脚本来源列表")
284
+ file_paths: list[str] = Field(default_factory=list, description="数据文件路径列表")
285
+ project_name: str = Field(..., description="项目名称")
286
+ project_id: str = Field(..., description="项目标识")
287
+ provider_id: str | None = Field(default=None, description="指定AI Provider,不指定使用默认")
288
+ options: ConfigGenerateOptions = Field(default_factory=ConfigGenerateOptions)
289
+
290
+
291
+ # =============================================================================
292
+ # 异步任务模型
293
+ # =============================================================================
294
+
295
+
296
+ class ConfigGenerateJobCreateResponse(BaseModel):
297
+ """配置生成任务创建响应"""
298
+
299
+ job_id: str
300
+
301
+
302
+ class ConfigGenerateJobStatus(BaseModel):
303
+ """配置生成任务状态"""
304
+
305
+ job_id: str
306
+ status: str = Field(..., description="pending/running/completed/failed/cancelled")
307
+ stage: str | None = Field(default=None, description="当前阶段")
308
+ message: str | None = Field(default=None, description="状态消息")
309
+ progress: float | None = Field(default=None, description="进度 0-100")
310
+ iterations: int | None = Field(default=None, description="当前已执行迭代轮数")
311
+ max_iterations: int | None = Field(default=None, description="最大迭代轮数")
312
+ metrics: dict[str, Any] | None = Field(default=None, description="校验指标")
313
+ current_plan: list[dict[str, Any]] | None = Field(default=None, description="当前执行计划")
314
+ checkpoints: list[dict[str, Any]] | None = Field(default=None, description="已保存的 checkpoints")
315
+ created_at: str
316
+ updated_at: str
317
+ warnings: list[str] = Field(default_factory=list)
318
+ error: str | None = None
319
+ result: ConfigGenerateResponse | None = None
320
+
321
+
322
+ # =============================================================================
323
+ # 硬件诊断模型
324
+ # =============================================================================
325
+
326
+
327
+ class HardwareInfo(BaseModel):
328
+ """硬件信息"""
329
+
330
+ name: str
331
+ value: Any
332
+
333
+
334
+ class HardwareRequirement(BaseModel):
335
+ """硬件需求检查项"""
336
+
337
+ name: str
338
+ required: str
339
+ current: str | None = None
340
+ satisfied: bool = False
341
+
342
+
343
+ class HardwareDiagnoseResponse(BaseModel):
344
+ """硬件诊断响应"""
345
+
346
+ platform: str
347
+ cpu: HardwareInfo | None = None
348
+ memory: HardwareInfo | None = None
349
+ disk: HardwareInfo | None = None
350
+ gpu: list[HardwareInfo] | None = None
351
+ requirements: list[HardwareRequirement] = Field(default_factory=list)
352
+ recommendations: list[str] = Field(default_factory=list)
@@ -0,0 +1,108 @@
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 Ollama 服务管理 API 路由模块
18
+
19
+ 功能概述:
20
+ - 获取 Ollama 本地服务的可用模型列表
21
+ - 检查 Ollama 服务的健康状态
22
+ - 从配置的 Ollama Provider 自动发现服务
23
+
24
+ 架构设计:
25
+ - 扫描配置文件中的 ollama 类型 Provider
26
+ - 通过 Provider 抽象层调用 list_models 和 health 方法
27
+ - 失败时优雅降级,返回空列表或错误信息
28
+
29
+ 输入示例:
30
+ GET /ai/ollama/models
31
+
32
+ 输出示例:
33
+ ["llama3.2", "qwen2.5", "deepseek-coder"]
34
+ """
35
+
36
+ import logging
37
+ from typing import Any
38
+
39
+ from app.shared.services.llm.config import loader
40
+ from app.shared.services.llm.providers import create
41
+
42
+ from .router import router
43
+
44
+
45
+ @router.get(
46
+ "/ollama/models",
47
+ response_model=list[str],
48
+ summary="获取 Ollama 可用模型列表",
49
+ responses={
50
+ 500: {"description": "服务器内部错误"},
51
+ },
52
+ )
53
+ async def list_ollama_models() -> list[str]:
54
+ """
55
+ 获取 Ollama 可用模型列表
56
+
57
+ 从配置的 Ollama Provider 获取模型列表
58
+ """
59
+ config = loader.load()
60
+
61
+ # 查找 Ollama Provider
62
+ ollama_provider = None
63
+ for p in config.providers:
64
+ if p.type.value == "ollama":
65
+ ollama_provider = p
66
+ break
67
+
68
+ if not ollama_provider:
69
+ return []
70
+
71
+ try:
72
+ provider = create(ollama_provider)
73
+ models = await provider.list_models()
74
+ return models
75
+ except Exception as exc:
76
+ logging.getLogger(__name__).warning("Failed to list Ollama models: %s", exc)
77
+ return []
78
+
79
+
80
+ @router.get(
81
+ "/ollama/health",
82
+ summary="检查 Ollama 服务健康状态",
83
+ responses={
84
+ 500: {"description": "服务器内部错误"},
85
+ },
86
+ )
87
+ async def ollama_health() -> dict[str, Any]:
88
+ """
89
+ 检查 Ollama 服务健康状态
90
+ """
91
+ config = loader.load()
92
+
93
+ # 查找 Ollama Provider
94
+ ollama_provider = None
95
+ for p in config.providers:
96
+ if p.type.value == "ollama":
97
+ ollama_provider = p
98
+ break
99
+
100
+ if not ollama_provider:
101
+ return {"success": False, "error": "No Ollama provider configured"}
102
+
103
+ try:
104
+ provider = create(ollama_provider)
105
+ health = await provider.health()
106
+ return {"success": health.get("status") == "ok", "data": health}
107
+ except Exception as e:
108
+ return {"success": False, "error": str(e)}