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.

Potentially problematic release.


This version of precis-cli might be problematic. Click here for more details.

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,237 @@
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
+ - 采集操作系统、CPU、内存、磁盘、GPU 等硬件信息
20
+ - 提供 HardwareSnapshot 数据类用于性能优化和错误报告
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import logging
26
+ import os
27
+ import platform
28
+ import shutil
29
+ import subprocess
30
+ import sys
31
+ from dataclasses import dataclass
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+
36
+ @dataclass(frozen=True)
37
+ class HardwareSnapshot:
38
+ """
39
+ @classdesc 硬件快照数据类
40
+
41
+ 使用 frozen=True 确保实例不可变,线程安全。
42
+
43
+ 字段说明:
44
+ - os_name: 操作系统名称(如 'Windows', 'Linux')
45
+ - os_version: 操作系统版本号
46
+ - arch: 系统架构(如 'x86_64', 'AMD64')
47
+ - cpu_cores: CPU 逻辑核心数
48
+ - memory_total_bytes: 物理内存总量(字节)
49
+ - disk_free_bytes: 磁盘可用空间(字节)
50
+ - has_nvidia_gpu: 是否存在 NVIDIA GPU
51
+ """
52
+
53
+ os_name: str
54
+ os_version: str
55
+ arch: str
56
+ cpu_cores: int
57
+ memory_total_bytes: int
58
+ disk_free_bytes: int
59
+ has_nvidia_gpu: bool
60
+
61
+
62
+ def _cpu_cores() -> int:
63
+ """
64
+ @methoddesc 获取 CPU 逻辑核心数
65
+
66
+ 实现逻辑:
67
+ 1. 尝试使用 os.cpu_count() 获取核心数
68
+ 2. 异常处理:若获取失败,返回默认值 1
69
+
70
+ 返回:
71
+ CPU 逻辑核心数,至少为 1
72
+ """
73
+ try:
74
+ v = int(os.cpu_count() or 0)
75
+ except Exception:
76
+ logger.debug("获取 CPU 核心数失败", exc_info=True)
77
+ v = 0
78
+ return v if v > 0 else 1
79
+
80
+
81
+ def _memory_total_bytes() -> int:
82
+ """
83
+ @methoddesc 获取系统物理内存总量
84
+
85
+ 平台实现:
86
+ - Windows: 使用 ctypes 调用 kernel32.GlobalMemoryStatusEx
87
+ - Linux/Unix: 使用 os.sysconf 获取页大小和物理页数
88
+
89
+ 返回:
90
+ 物理内存总量(字节),获取失败返回 0
91
+ """
92
+ # Windows 平台实现
93
+ if os.name == "nt":
94
+ try:
95
+ import ctypes
96
+
97
+ # 定义 Windows MEMORYSTATUSEX 结构体
98
+ class _MEMORYSTATUSEX(ctypes.Structure):
99
+ _fields_ = [
100
+ ("dwLength", ctypes.c_ulong), # 结构体大小
101
+ ("dwMemoryLoad", ctypes.c_ulong), # 内存使用率
102
+ ("ullTotalPhys", ctypes.c_ulonglong), # 物理内存总量
103
+ ("ullAvailPhys", ctypes.c_ulonglong), # 物理内存可用量
104
+ ("ullTotalPageFile", ctypes.c_ulonglong), # 页面文件总量
105
+ ("ullAvailPageFile", ctypes.c_ulonglong), # 页面文件可用量
106
+ ("ullTotalVirtual", ctypes.c_ulonglong), # 虚拟内存总量
107
+ ("ullAvailVirtual", ctypes.c_ulonglong), # 虚拟内存可用量
108
+ ("sullAvailExtendedVirtual", ctypes.c_ulonglong), # 扩展虚拟内存
109
+ ]
110
+
111
+ stat = _MEMORYSTATUSEX()
112
+ stat.dwLength = ctypes.sizeof(_MEMORYSTATUSEX)
113
+ # 调用 Windows API 获取内存状态
114
+ # windll 是 Windows 专属属性,非 Windows 平台 typeshed 无此定义
115
+ if ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat)) == 0: # type: ignore[attr-defined]
116
+ return 0
117
+ return int(stat.ullTotalPhys)
118
+ except Exception:
119
+ logger.debug("Windows 平台获取内存总量失败", exc_info=True)
120
+ return 0
121
+
122
+ # Linux/Unix 平台实现
123
+ if hasattr(os, "sysconf"):
124
+ try:
125
+ # 获取系统页大小(字节)
126
+ page = int(os.sysconf("SC_PAGE_SIZE"))
127
+ # 获取物理内存页数
128
+ pages = int(os.sysconf("SC_PHYS_PAGES"))
129
+ total = page * pages
130
+ return int(total) if total > 0 else 0
131
+ except Exception:
132
+ logger.debug("Linux/Unix 平台获取内存总量失败", exc_info=True)
133
+ return 0
134
+
135
+ return 0
136
+
137
+
138
+ def _disk_free_bytes(path: str | None = None) -> int:
139
+ r"""
140
+ @methoddesc 获取指定路径所在磁盘的可用空间
141
+
142
+ 路径解析逻辑:
143
+ - 若指定 path 参数:使用该路径
144
+ - 若未指定:
145
+ - Windows: 使用系统驱动器(默认 C:\)
146
+ - Linux/Unix: 使用用户主目录
147
+
148
+ 参数:
149
+ path: 可选的磁盘路径
150
+
151
+ 返回:
152
+ 可用空间(字节),获取失败返回 0
153
+ """
154
+ p = path
155
+ if not p:
156
+ if os.name == "nt":
157
+ # Windows: 使用系统驱动器
158
+ p = os.environ.get("SystemDrive", "C:") + "\\"
159
+ else:
160
+ # Linux/Unix: 使用用户主目录
161
+ p = os.path.expanduser("~")
162
+ try:
163
+ usage = shutil.disk_usage(p)
164
+ return int(usage.free)
165
+ except Exception:
166
+ logger.debug(f"获取磁盘可用空间失败: path={p}", exc_info=True)
167
+ return 0
168
+
169
+
170
+ def _has_nvidia_gpu(timeout_seconds: float = 1.2) -> bool:
171
+ """
172
+ @methoddesc 检测系统是否装有 NVIDIA GPU
173
+
174
+ 实现机制:
175
+ 通过执行 nvidia-smi -L 命令检测 GPU 存在性。
176
+ 使用较短的超时时间(默认 1.2 秒)避免长时间阻塞。
177
+
178
+ 参数:
179
+ timeout_seconds: 命令执行超时时间(秒)
180
+
181
+ 返回:
182
+ 存在 NVIDIA GPU 返回 True,否则返回 False
183
+ """
184
+ try:
185
+ # 执行 nvidia-smi -L 命令检测GPU
186
+ res = subprocess.run(
187
+ ["nvidia-smi", "-L"],
188
+ stdout=subprocess.DEVNULL,
189
+ stderr=subprocess.DEVNULL,
190
+ timeout=timeout_seconds,
191
+ check=False,
192
+ )
193
+ # 返回码为0表示命令成功执行,即存在GPU
194
+ return res.returncode == 0
195
+ except Exception:
196
+ logger.debug("NVIDIA GPU 检测失败", exc_info=True)
197
+ return False
198
+
199
+
200
+ def snapshot() -> HardwareSnapshot:
201
+ """
202
+ @methoddesc 获取当前系统的硬件信息快照
203
+
204
+ 采集的信息:
205
+ 1. 操作系统信息:
206
+ - os_name: platform.system() 或 os.name
207
+ - os_version: platform.version() 或 platform.release()
208
+ 2. 系统架构:platform.machine() 或 platform.architecture()
209
+ 3. CPU 核心数:_cpu_cores()
210
+ 4. 内存总量:_memory_total_bytes()
211
+ 5. 磁盘可用空间:_disk_free_bytes()
212
+ 6. GPU 检测:_has_nvidia_gpu()
213
+
214
+ 返回:
215
+ HardwareSnapshot 实例,包含所有硬件信息
216
+ """
217
+ # 采集操作系统信息
218
+ os_name = platform.system() or os.name
219
+ os_version = platform.version() or platform.release() or ""
220
+ arch = platform.machine() or platform.architecture()[0] or sys.platform
221
+
222
+ # 采集各项硬件指标
223
+ cpu_cores = _cpu_cores()
224
+ memory_total = _memory_total_bytes()
225
+ disk_free = _disk_free_bytes()
226
+ has_gpu = _has_nvidia_gpu()
227
+
228
+ # 构建并返回硬件快照
229
+ return HardwareSnapshot(
230
+ os_name=os_name,
231
+ os_version=os_version,
232
+ arch=arch,
233
+ cpu_cores=cpu_cores,
234
+ memory_total_bytes=memory_total,
235
+ disk_free_bytes=disk_free,
236
+ has_nvidia_gpu=has_gpu,
237
+ )
@@ -0,0 +1,62 @@
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 LLM 服务模块聚合导出
18
+
19
+ 功能概述:
20
+ - 聚合导出 AI Provider 配置、Provider 实现、服务发现、配置生成等子模块
21
+ - 为上层业务提供统一的 LLM 服务入口
22
+
23
+ 架构设计:
24
+ - 通过 __init__.py 聚合子模块公共接口,降低外部导入复杂度
25
+ - 遵循显式导出原则,使用 __all__ 控制公开 API
26
+ - 各子模块职责分离:config 负责配置,providers 负责调用,discovery 负责发现,generation 负责生成
27
+
28
+ 输入示例:
29
+ from app.shared.services.llm import AIConfig, BaseProvider, ConfigGenerationService
30
+
31
+ 输出示例:
32
+ AIConfig 实例可用于配置管理
33
+ BaseProvider 子类可用于执行对话
34
+ ConfigGenerationService 可用于生成项目配置
35
+ """
36
+
37
+ from .config import AIConfig, AIProvider, DeploymentType, ProviderType, loader
38
+ from .discovery import DiscoveredService, scanner
39
+ from .generation import ConfigGenerationService, GenerationOptions, ProfilingOptions
40
+ from .providers import BaseProvider, ChatMessage, ChatRequest, ChatResponse, create
41
+
42
+ __all__ = [
43
+ # 配置
44
+ "AIConfig",
45
+ "AIProvider",
46
+ "ProviderType",
47
+ "DeploymentType",
48
+ "loader",
49
+ # Provider
50
+ "BaseProvider",
51
+ "ChatMessage",
52
+ "ChatRequest",
53
+ "ChatResponse",
54
+ "create",
55
+ # 发现
56
+ "scanner",
57
+ "DiscoveredService",
58
+ # 配置生成
59
+ "ConfigGenerationService",
60
+ "GenerationOptions",
61
+ "ProfilingOptions",
62
+ ]
@@ -0,0 +1,42 @@
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 动作解析与执行子包
18
+
19
+ 功能概述:
20
+ - registry: 动作类型与约束别名的单一事实源(无依赖叶子模块)
21
+ - action_parser: 动作类型映射 + 向后兼容导出
22
+ - action_processor: process_actions() 批量处理
23
+ - action_handlers: update_yaml_config() + 协调函数
24
+ - action_validator: ActionValidator 预验证器
25
+
26
+ 架构设计:
27
+ - 管道模式: 解析 → 验证 → 执行
28
+ - 批量优化: 内联约束按 schema 分组合并 IO
29
+
30
+ 导入说明:
31
+ 本 __init__.py 故意不做包级 re-export。原因:action_handlers 依赖
32
+ constraints.constraint_builder/frontend_instructions,而这些模块从 registry 派生常量——
33
+ 若在此处包级 import 会形成循环(actions/__init__ → action_handlers →
34
+ constraint_builder → actions 包),导致 test_constraint_builder_behavior.py 等独立
35
+ 运行时 ImportError。
36
+
37
+ 调用方请直接 import 具体子模块,例如:
38
+ from app.shared.services.llm.actions.action_processor import process_actions
39
+ from app.shared.services.llm.actions.action_handlers import update_yaml_config
40
+ from app.shared.services.llm.actions.action_parser import CONSTRAINT_TYPE_MAP
41
+ from app.shared.services.llm.actions.registry import CONSTRAINT_TYPE_ALIASES
42
+ """
@@ -0,0 +1,147 @@
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 ADD_TO_CANVAS 动作验证器
18
+
19
+ 验证 AI 生成 ADD_TO_CANVAS 动作的合法性:
20
+ - canvasSpec.resourceKind 必须是 schema/regex/constraint/transform 之一
21
+ - resourceId 或 resourceName 至少有一个
22
+ - 目标资源在项目配置中必须真实存在(避免把不存在的资源"显示"到画布)
23
+
24
+ 与其它验证器不同:本验证器是纯读校验(ADD_TO_CANVAS 不写盘),
25
+ 但仍接入预验证链以拦截"显示不存在的资源"这类语义错误,把错误回灌给 LLM 自我修正。
26
+ """
27
+
28
+ from __future__ import annotations
29
+
30
+ from pathlib import Path
31
+ from typing import Any
32
+
33
+ import yaml
34
+
35
+ from app.shared.services.llm.actions.registry import CANVAS_RESOURCE_KINDS
36
+ from app.shared.services.llm.actions.validation_types import ValidationError
37
+
38
+ # 支持的资源类型从注册表派生(单一事实源,与前端 ProjectResourceKind 对齐)
39
+ VALID_CANVAS_RESOURCE_KINDS = CANVAS_RESOURCE_KINDS
40
+
41
+
42
+ def _list_existing_resource_ids(workspace_path: str, kind: str) -> set[str]:
43
+ """扫描项目配置目录,返回指定 kind 的已存在资源 ID 集合。
44
+
45
+ 用于校验 ADD_TO_CANVAS 的目标资源是否真实存在。
46
+ 扫描逻辑与 get_project_overview / 各 handler 的文件定位保持一致。
47
+ """
48
+ root = Path(workspace_path)
49
+ ids: set[str] = set()
50
+
51
+ dir_map = {
52
+ "schema": ("schemas", "*.schema.yaml"),
53
+ "regex": ("regex", "*.regex.yaml"),
54
+ "constraint": ("constraints", "*.constraint.yaml"),
55
+ "transform": ("transforms", "*.transform.yaml"),
56
+ }
57
+ if kind not in dir_map:
58
+ return ids
59
+
60
+ subdir, pattern = dir_map[kind]
61
+ target_dir = root / subdir
62
+ if not target_dir.exists():
63
+ return ids
64
+
65
+ for f in target_dir.glob(pattern):
66
+ try:
67
+ with open(f, encoding="utf-8") as fh:
68
+ data = yaml.safe_load(fh) or {}
69
+ rid = data.get("id") or data.get("name")
70
+ if rid:
71
+ ids.add(str(rid))
72
+ # 同时收录 name 作为兜底匹配键(resourceName 常用 name)
73
+ name = data.get("name")
74
+ if name and str(name) != str(rid):
75
+ ids.add(str(name))
76
+ except Exception:
77
+ continue
78
+
79
+ return ids
80
+
81
+
82
+ def validate_canvas_action(action: dict[str, Any], index: int, workspace_path: str) -> list[ValidationError]:
83
+ """验证 ADD_TO_CANVAS 操作
84
+
85
+ 检查 canvasSpec 的 resourceKind 合法性、resourceId/resourceName 存在性,
86
+ 以及目标资源在项目配置中是否真实存在。
87
+ """
88
+ errors: list[ValidationError] = []
89
+ action_type = action.get("actionType", "")
90
+ spec = action.get("canvasSpec", {})
91
+
92
+ if not isinstance(spec, dict):
93
+ errors.append(
94
+ ValidationError(
95
+ action_index=index,
96
+ action_type=action_type,
97
+ error_type="missing_canvas_spec",
98
+ message="ADD_TO_CANVAS 需要 canvasSpec 字段",
99
+ )
100
+ )
101
+ return errors
102
+
103
+ kind = spec.get("resourceKind", "")
104
+ resource_id = spec.get("resourceId", "")
105
+ resource_name = spec.get("resourceName") or spec.get("name", "")
106
+
107
+ # 1. resourceKind 必须合法
108
+ if kind not in VALID_CANVAS_RESOURCE_KINDS:
109
+ errors.append(
110
+ ValidationError(
111
+ action_index=index,
112
+ action_type=action_type,
113
+ error_type="invalid_resource_kind",
114
+ message=f"不支持的资源类型: '{kind}'",
115
+ suggestion=f"可用类型: {', '.join(sorted(VALID_CANVAS_RESOURCE_KINDS))}",
116
+ )
117
+ )
118
+ return errors
119
+
120
+ # 2. resourceId 或 resourceName 至少有一个
121
+ if not resource_id and not resource_name:
122
+ errors.append(
123
+ ValidationError(
124
+ action_index=index,
125
+ action_type=action_type,
126
+ error_type="missing_resource_identifier",
127
+ message="ADD_TO_CANVAS 需要指定 resourceId 或 resourceName",
128
+ suggestion="可用 read_project 查询资源 ID/名称",
129
+ )
130
+ )
131
+ return errors
132
+
133
+ # 3. 目标资源必须真实存在(避免"显示不存在的资源")
134
+ existing_ids = _list_existing_resource_ids(workspace_path, kind)
135
+ target_keys = {str(resource_id), str(resource_name)} - {""}
136
+ if existing_ids and not (target_keys & existing_ids):
137
+ errors.append(
138
+ ValidationError(
139
+ action_index=index,
140
+ action_type=action_type,
141
+ error_type="resource_not_found",
142
+ message=f"资源不存在: {kind} '{resource_id or resource_name}'",
143
+ suggestion="该资源未在项目配置中找到,请先创建(如用 ADD_SCHEMA)或检查名称拼写",
144
+ )
145
+ )
146
+
147
+ return errors