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.
- app/__init__.py +16 -0
- app/api/__init__.py +32 -0
- app/api/dependencies.py +185 -0
- app/api/main.py +301 -0
- app/api/middleware/__init__.py +34 -0
- app/api/middleware/exception_handler.py +126 -0
- app/api/middleware/request_logging.py +97 -0
- app/api/middleware/token_auth.py +215 -0
- app/api/models/__init__.py +151 -0
- app/api/models/connection_rules.py +98 -0
- app/api/models/files.py +99 -0
- app/api/models/full_validation.py +554 -0
- app/api/models/project.py +117 -0
- app/api/models/projects.py +80 -0
- app/api/models/schema.py +121 -0
- app/api/models/v2_responses.py +46 -0
- app/api/models/validation.py +303 -0
- app/api/models/workspace.py +118 -0
- app/api/routers/__init__.py +56 -0
- app/api/routers/ai/__init__.py +36 -0
- app/api/routers/ai/chat.py +243 -0
- app/api/routers/ai/generate.py +156 -0
- app/api/routers/ai/hardware.py +199 -0
- app/api/routers/ai/jobs.py +544 -0
- app/api/routers/ai/migrate.py +471 -0
- app/api/routers/ai/models.py +352 -0
- app/api/routers/ai/ollama.py +108 -0
- app/api/routers/ai/providers.py +491 -0
- app/api/routers/ai/router.py +44 -0
- app/api/routers/ai/stream.py +281 -0
- app/api/routers/ai/utils.py +182 -0
- app/api/routers/core/__init__.py +34 -0
- app/api/routers/core/connection_rules.py +188 -0
- app/api/routers/core/data_sources.py +374 -0
- app/api/routers/core/regex.py +333 -0
- app/api/routers/core/reporting.py +263 -0
- app/api/routers/files/__init__.py +24 -0
- app/api/routers/files/ops.py +179 -0
- app/api/routers/files/transfer.py +101 -0
- app/api/routers/preview/__init__.py +35 -0
- app/api/routers/preview/content_mode.py +264 -0
- app/api/routers/preview/header_row.py +154 -0
- app/api/routers/preview/models.py +81 -0
- app/api/routers/preview/path_mode.py +440 -0
- app/api/routers/preview/router.py +30 -0
- app/api/routers/project/__init__.py +61 -0
- app/api/routers/project/base.py +111 -0
- app/api/routers/project/constraint.py +345 -0
- app/api/routers/project/full_config.py +411 -0
- app/api/routers/project/full_config_writer.py +327 -0
- app/api/routers/project/helpers.py +167 -0
- app/api/routers/project/inspection_fix.py +330 -0
- app/api/routers/project/manifest.py +605 -0
- app/api/routers/project/models.py +177 -0
- app/api/routers/project/pattern.py +268 -0
- app/api/routers/project/regex.py +358 -0
- app/api/routers/project/scanner.py +157 -0
- app/api/routers/project/schema.py +567 -0
- app/api/routers/project/schema_helpers.py +149 -0
- app/api/routers/project/settings.py +399 -0
- app/api/routers/project/template.py +325 -0
- app/api/routers/project/validation.py +227 -0
- app/api/routers/project/view.py +177 -0
- app/api/routers/project/workspaces.py +167 -0
- app/api/routers/projects/__init__.py +25 -0
- app/api/routers/projects/create.py +121 -0
- app/api/routers/projects/open.py +103 -0
- app/api/routers/projects/scan.py +100 -0
- app/api/routers/validation/__init__.py +39 -0
- app/api/routers/validation/common.py +263 -0
- app/api/routers/validation/content_mode.py +401 -0
- app/api/routers/validation/history.py +235 -0
- app/api/routers/validation/inline_mode.py +196 -0
- app/api/routers/validation/path_mode.py +314 -0
- app/api/routers/validation/router.py +51 -0
- app/api/services/full_validation_response_builder.py +412 -0
- app/api/services/io_error_messages.py +41 -0
- app/api/services/preview_service.py +248 -0
- app/cli/__init__.py +18 -0
- app/cli/__main__.py +30 -0
- app/cli/shared_services/__init__.py +42 -0
- app/cli/shared_services/config_ops.py +581 -0
- app/cli/shared_services/generation_ops.py +160 -0
- app/cli/shared_services/project_ops.py +288 -0
- app/cli/shell/__init__.py +48 -0
- app/cli/shell/commands/__init__.py +63 -0
- app/cli/shell/commands/ai/__init__.py +260 -0
- app/cli/shell/commands/ai/chat.py +331 -0
- app/cli/shell/commands/ai/delete.py +165 -0
- app/cli/shell/commands/ai/diff.py +70 -0
- app/cli/shell/commands/ai/display.py +428 -0
- app/cli/shell/commands/ai/executor.py +225 -0
- app/cli/shell/commands/ai/executor_utils.py +271 -0
- app/cli/shell/commands/ai/generate.py +285 -0
- app/cli/shell/commands/ai/interaction.py +262 -0
- app/cli/shell/commands/ai/migrate.py +281 -0
- app/cli/shell/commands/ai/resolver.py +224 -0
- app/cli/shell/commands/ai/status.py +101 -0
- app/cli/shell/commands/ai/switch.py +158 -0
- app/cli/shell/commands/ai/utils.py +52 -0
- app/cli/shell/commands/base.py +343 -0
- app/cli/shell/commands/config/__init__.py +131 -0
- app/cli/shell/commands/config/base.py +80 -0
- app/cli/shell/commands/config/check.py +246 -0
- app/cli/shell/commands/config/edit.py +148 -0
- app/cli/shell/commands/config/get.py +111 -0
- app/cli/shell/commands/config/init.py +123 -0
- app/cli/shell/commands/config/inspect.py +164 -0
- app/cli/shell/commands/config/list.py +104 -0
- app/cli/shell/commands/config/set.py +119 -0
- app/cli/shell/commands/config/show.py +150 -0
- app/cli/shell/commands/exit.py +67 -0
- app/cli/shell/commands/help.py +104 -0
- app/cli/shell/commands/infer_schema.py +156 -0
- app/cli/shell/commands/open.py +201 -0
- app/cli/shell/commands/project.py +215 -0
- app/cli/shell/commands/provider.py +619 -0
- app/cli/shell/commands/system.py +170 -0
- app/cli/shell/commands/validate.py +455 -0
- app/cli/shell/completer.py +231 -0
- app/cli/shell/config_storage.py +191 -0
- app/cli/shell/exceptions.py +90 -0
- app/cli/shell/formatter.py +371 -0
- app/cli/shell/interactive_menu.py +348 -0
- app/cli/shell/main.py +286 -0
- app/cli/shell/parser.py +266 -0
- app/cli/start.py +180 -0
- app/cli_main.py +52 -0
- app/mcp_server.py +311 -0
- app/shared/core/__init__.py +18 -0
- app/shared/core/app_version.py +59 -0
- app/shared/core/config/__init__.py +119 -0
- app/shared/core/config/server.py +193 -0
- app/shared/core/data_source/__init__.py +106 -0
- app/shared/core/data_source/loader.py +348 -0
- app/shared/core/data_source/loaders/__init__.py +213 -0
- app/shared/core/data_source/loaders/base.py +215 -0
- app/shared/core/data_source/loaders/converter.py +337 -0
- app/shared/core/data_source/loaders/csv_loader.py +252 -0
- app/shared/core/data_source/loaders/excel_loader.py +666 -0
- app/shared/core/data_source/loaders/extractor.py +268 -0
- app/shared/core/data_source/loaders/json_loader.py +354 -0
- app/shared/core/data_source/loaders/registry.py +88 -0
- app/shared/core/data_source/loaders/sql_loader.py +313 -0
- app/shared/core/data_source/loaders/strategies/__init__.py +100 -0
- app/shared/core/data_source/loaders/strategies/array_parser.py +277 -0
- app/shared/core/data_source/loaders/strategies/lines_parser.py +355 -0
- app/shared/core/data_source/loaders/strategies/object_parser.py +278 -0
- app/shared/core/data_source/schema_info.py +50 -0
- app/shared/core/data_source/specs/__init__.py +128 -0
- app/shared/core/data_source/specs/base.py +258 -0
- app/shared/core/data_source/specs/csv_source.py +137 -0
- app/shared/core/data_source/specs/excel_source.py +141 -0
- app/shared/core/data_source/specs/file_base.py +252 -0
- app/shared/core/data_source/specs/json_source.py +226 -0
- app/shared/core/data_source/specs/sql_source.py +161 -0
- app/shared/core/encoding.py +36 -0
- app/shared/core/io/__init__.py +24 -0
- app/shared/core/io/yaml.py +379 -0
- app/shared/core/manifest_schema/__init__.py +52 -0
- app/shared/core/manifest_schema/types.py +99 -0
- app/shared/core/manifest_schema/version.py +175 -0
- app/shared/core/patterns/__init__.py +24 -0
- app/shared/core/patterns/loader.py +134 -0
- app/shared/core/patterns/writer.py +244 -0
- app/shared/core/project/__init__.py +47 -0
- app/shared/core/project/constraint/builders/__init__.py +50 -0
- app/shared/core/project/constraint/builders/base.py +100 -0
- app/shared/core/project/constraint/builders/composite.py +77 -0
- app/shared/core/project/constraint/builders/conditional.py +67 -0
- app/shared/core/project/constraint/builders/foreign_key.py +53 -0
- app/shared/core/project/constraint/builders/registry.py +64 -0
- app/shared/core/project/constraint/builders/scripted.py +51 -0
- app/shared/core/project/constraint/builders/single_column.py +86 -0
- app/shared/core/project/constraint/builders/unique.py +53 -0
- app/shared/core/project/constraint/factory.py +170 -0
- app/shared/core/project/constraint/reader.py +214 -0
- app/shared/core/project/constraint/registry.py +233 -0
- app/shared/core/project/constraint/types/__init__.py +63 -0
- app/shared/core/project/constraint/types/constraint_file.py +261 -0
- app/shared/core/project/constraint/types/refs.py +460 -0
- app/shared/core/project/constraint/types.py +28 -0
- app/shared/core/project/constraint/writer.py +181 -0
- app/shared/core/project/loader/__init__.py +56 -0
- app/shared/core/project/loader/loader.py +30 -0
- app/shared/core/project/loader/loader_parts/config_inspector.py +137 -0
- app/shared/core/project/loader/loader_parts/embedded_constraints.py +224 -0
- app/shared/core/project/loader/loader_parts/file_loaders.py +58 -0
- app/shared/core/project/loader/loader_parts/inspection_ids.py +85 -0
- app/shared/core/project/loader/loader_parts/inspector_helpers.py +312 -0
- app/shared/core/project/loader/loader_parts/inspector_id_checks.py +274 -0
- app/shared/core/project/loader/loader_parts/inspector_reference_checks.py +690 -0
- app/shared/core/project/loader/loader_parts/inspector_uniqueness_checks.py +286 -0
- app/shared/core/project/loader/loader_parts/loading_error_messages.py +298 -0
- app/shared/core/project/loader/loader_parts/main.py +432 -0
- app/shared/core/project/loader/loader_parts/path_validation.py +117 -0
- app/shared/core/project/loader/loader_parts/runtime.py +125 -0
- app/shared/core/project/loader/types.py +246 -0
- app/shared/core/project/manifest/coverage.py +391 -0
- app/shared/core/project/manifest/reader.py +260 -0
- app/shared/core/project/manifest/types.py +91 -0
- app/shared/core/project/manifest/types_parts/__init__.py +60 -0
- app/shared/core/project/manifest/types_parts/constants.py +40 -0
- app/shared/core/project/manifest/types_parts/data_source.py +68 -0
- app/shared/core/project/manifest/types_parts/info.py +59 -0
- app/shared/core/project/manifest/types_parts/manifest.py +294 -0
- app/shared/core/project/manifest/types_parts/refs.py +153 -0
- app/shared/core/project/manifest/types_parts/settings.py +92 -0
- app/shared/core/project/manifest/types_parts/settings_file_processing.py +64 -0
- app/shared/core/project/manifest/types_parts/settings_script_security.py +78 -0
- app/shared/core/project/manifest/types_parts/settings_validation.py +83 -0
- app/shared/core/project/manifest/types_parts/template.py +66 -0
- app/shared/core/project/manifest/writer.py +262 -0
- app/shared/core/project/manual_data/__init__.py +27 -0
- app/shared/core/project/manual_data/types.py +75 -0
- app/shared/core/project/regex/reader.py +197 -0
- app/shared/core/project/regex/types.py +405 -0
- app/shared/core/project/regex/writer.py +123 -0
- app/shared/core/project/schema/reader.py +170 -0
- app/shared/core/project/schema/types.py +47 -0
- app/shared/core/project/schema/types_parts/__init__.py +36 -0
- app/shared/core/project/schema/types_parts/column.py +174 -0
- app/shared/core/project/schema/types_parts/column_utils.py +72 -0
- app/shared/core/project/schema/types_parts/constraint.py +165 -0
- app/shared/core/project/schema/types_parts/schema_id.py +66 -0
- app/shared/core/project/schema/types_parts/source.py +255 -0
- app/shared/core/project/schema/types_parts/source_options.py +347 -0
- app/shared/core/project/schema/types_parts/table.py +230 -0
- app/shared/core/project/schema/writer.py +139 -0
- app/shared/core/project/schema_ref_check.py +95 -0
- app/shared/core/project/template/__init__.py +27 -0
- app/shared/core/project/template/expander.py +263 -0
- app/shared/core/project/template/reader.py +120 -0
- app/shared/core/project/template/types.py +114 -0
- app/shared/core/project/transform/reader.py +76 -0
- app/shared/core/project/transform/types.py +116 -0
- app/shared/core/project/transform/writer.py +84 -0
- app/shared/core/pydantic_messages.py +59 -0
- app/shared/core/reporter/__init__.py +46 -0
- app/shared/core/reporter/reporter.py +220 -0
- app/shared/core/reporter/reporters/__init__.py +65 -0
- app/shared/core/reporter/reporters/base.py +188 -0
- app/shared/core/reporter/reporters/dingtalk_app_reporter.py +274 -0
- app/shared/core/reporter/reporters/email_reporter.py +271 -0
- app/shared/core/reporter/reporters/feishu_app_reporter.py +467 -0
- app/shared/core/reporter/reporters/local_file_reporter.py +208 -0
- app/shared/core/reporter/reporters/wecom_app_reporter.py +268 -0
- app/shared/core/utils/__init__.py +18 -0
- app/shared/core/utils/path_utils.py +60 -0
- app/shared/core/utils/regex_extract.py +113 -0
- app/shared/domain/__init__.py +114 -0
- app/shared/domain/constraints/__init__.py +76 -0
- app/shared/domain/constraints/allowed_values.py +211 -0
- app/shared/domain/constraints/base.py +141 -0
- app/shared/domain/constraints/charset.py +337 -0
- app/shared/domain/constraints/composite.py +174 -0
- app/shared/domain/constraints/condition_registry.py +130 -0
- app/shared/domain/constraints/conditional.py +629 -0
- app/shared/domain/constraints/date_logic.py +731 -0
- app/shared/domain/constraints/foreign_key.py +261 -0
- app/shared/domain/constraints/key_normalization.py +56 -0
- app/shared/domain/constraints/not_null.py +185 -0
- app/shared/domain/constraints/range.py +360 -0
- app/shared/domain/constraints/regex.py +218 -0
- app/shared/domain/constraints/scripted.py +276 -0
- app/shared/domain/constraints/unique.py +233 -0
- app/shared/domain/data_engine.py +384 -0
- app/shared/domain/data_types.py +113 -0
- app/shared/domain/data_types_parts/__init__.py +67 -0
- app/shared/domain/data_types_parts/base.py +204 -0
- app/shared/domain/data_types_parts/composite.py +250 -0
- app/shared/domain/data_types_parts/expression.py +202 -0
- app/shared/domain/data_types_parts/extracted.py +106 -0
- app/shared/domain/data_types_parts/json_types.py +234 -0
- app/shared/domain/data_types_parts/scalars.py +719 -0
- app/shared/domain/data_types_parts/sequence.py +129 -0
- app/shared/domain/dataset_schema.py +48 -0
- app/shared/domain/eval_sandbox.py +63 -0
- app/shared/domain/expression_system.py +366 -0
- app/shared/domain/regex_flags.py +53 -0
- app/shared/domain/schema/builder.py +223 -0
- app/shared/domain/schema/models.py +339 -0
- app/shared/domain/transforms/__init__.py +28 -0
- app/shared/domain/transforms/aggregate.py +141 -0
- app/shared/domain/transforms/base.py +171 -0
- app/shared/domain/transforms/cast_type.py +120 -0
- app/shared/domain/transforms/concat.py +103 -0
- app/shared/domain/transforms/conditional_assign.py +114 -0
- app/shared/domain/transforms/date_format.py +81 -0
- app/shared/domain/transforms/digits.py +77 -0
- app/shared/domain/transforms/drop_duplicates.py +94 -0
- app/shared/domain/transforms/fill_na.py +94 -0
- app/shared/domain/transforms/filter_rows.py +97 -0
- app/shared/domain/transforms/lookup.py +78 -0
- app/shared/domain/transforms/lower_case.py +70 -0
- app/shared/domain/transforms/map_value.py +90 -0
- app/shared/domain/transforms/math_expr.py +112 -0
- app/shared/domain/transforms/modulo.py +82 -0
- app/shared/domain/transforms/regex_extract.py +103 -0
- app/shared/domain/transforms/registry.py +95 -0
- app/shared/domain/transforms/replace.py +88 -0
- app/shared/domain/transforms/sort_rows.py +94 -0
- app/shared/domain/transforms/string_split.py +84 -0
- app/shared/domain/transforms/strip.py +73 -0
- app/shared/domain/transforms/substring.py +92 -0
- app/shared/domain/transforms/upper_case.py +70 -0
- app/shared/domain/transforms/weighted_sum.py +104 -0
- app/shared/domain/validation_constraints.py +69 -0
- app/shared/services/__init__.py +62 -0
- app/shared/services/ai/__init__.py +48 -0
- app/shared/services/ai/agent/__init__.py +40 -0
- app/shared/services/ai/agent/chat_tools/__init__.py +47 -0
- app/shared/services/ai/agent/chat_tools/apply_actions.py +592 -0
- app/shared/services/ai/agent/chat_tools/ask_user.py +237 -0
- app/shared/services/ai/agent/chat_tools/read_canvas.py +140 -0
- app/shared/services/ai/agent/chat_tools/read_project.py +160 -0
- app/shared/services/ai/agent/chat_tools/read_table.py +301 -0
- app/shared/services/ai/agent/chat_tools/schemas.py +105 -0
- app/shared/services/ai/agent/chat_tools/validate_table.py +131 -0
- app/shared/services/ai/agent/executor.py +554 -0
- app/shared/services/ai/agent/memory.py +256 -0
- app/shared/services/ai/agent/planner.py +282 -0
- app/shared/services/ai/agent/tool_registry.py +296 -0
- app/shared/services/ai/agent/tools/__init__.py +32 -0
- app/shared/services/ai/agent/tools/config_generate.py +133 -0
- app/shared/services/ai/agent/tools/config_refine.py +109 -0
- app/shared/services/ai/agent/tools/config_validate.py +403 -0
- app/shared/services/ai/agent/tools/merge_results.py +136 -0
- app/shared/services/ai/agent/tools/plan_chunks.py +79 -0
- app/shared/services/ai/agent/tools/script_parse.py +359 -0
- app/shared/services/ai/agent/types.py +138 -0
- app/shared/services/ai/chat_agent_runner.py +596 -0
- app/shared/services/ai/chat_orchestrator.py +725 -0
- app/shared/services/ai/failure_messages.py +65 -0
- app/shared/services/ai/job_storage.py +274 -0
- app/shared/services/ai/migrate_service.py +550 -0
- app/shared/services/ai/streaming/__init__.py +65 -0
- app/shared/services/ai/streaming/event_journal.py +197 -0
- app/shared/services/ai/streaming/orchestrator.py +262 -0
- app/shared/services/ai/streaming/pending_interaction_store.py +227 -0
- app/shared/services/ai/streaming/sse_response.py +148 -0
- app/shared/services/ai/streaming/types.py +73 -0
- app/shared/services/ai/types.py +213 -0
- app/shared/services/ai/utils.py +322 -0
- app/shared/services/diff/config_diff.py +320 -0
- app/shared/services/hardware.py +237 -0
- app/shared/services/llm/__init__.py +62 -0
- app/shared/services/llm/actions/__init__.py +42 -0
- app/shared/services/llm/actions/_canvas_validator.py +147 -0
- app/shared/services/llm/actions/_constraint_validator.py +401 -0
- app/shared/services/llm/actions/_regex_validator.py +85 -0
- app/shared/services/llm/actions/_schema_validator.py +82 -0
- app/shared/services/llm/actions/_settings_validator.py +76 -0
- app/shared/services/llm/actions/_transform_validator.py +78 -0
- app/shared/services/llm/actions/action_handlers.py +400 -0
- app/shared/services/llm/actions/action_parser.py +63 -0
- app/shared/services/llm/actions/action_processor.py +468 -0
- app/shared/services/llm/actions/action_validator.py +311 -0
- app/shared/services/llm/actions/diff_compute.py +195 -0
- app/shared/services/llm/actions/regex_handlers.py +284 -0
- app/shared/services/llm/actions/registry.py +336 -0
- app/shared/services/llm/actions/schema_handlers.py +335 -0
- app/shared/services/llm/actions/settings_handlers.py +180 -0
- app/shared/services/llm/actions/specs.py +259 -0
- app/shared/services/llm/actions/transform_handlers.py +279 -0
- app/shared/services/llm/actions/validation_types.py +147 -0
- app/shared/services/llm/cache/__init__.py +18 -0
- app/shared/services/llm/cache/response_cache.py +80 -0
- app/shared/services/llm/chat/__init__.py +35 -0
- app/shared/services/llm/chat/chat_system_prompt.py +561 -0
- app/shared/services/llm/chat/response_parser.py +296 -0
- app/shared/services/llm/config/__init__.py +45 -0
- app/shared/services/llm/config/crypto.py +135 -0
- app/shared/services/llm/config/loader.py +258 -0
- app/shared/services/llm/config/models.py +202 -0
- app/shared/services/llm/config/presets.py +128 -0
- app/shared/services/llm/config_generator.py +163 -0
- app/shared/services/llm/constraints/__init__.py +41 -0
- app/shared/services/llm/constraints/constraint_builder.py +177 -0
- app/shared/services/llm/constraints/constraint_deletion.py +84 -0
- app/shared/services/llm/constraints/constraint_id.py +174 -0
- app/shared/services/llm/constraints/frontend_instructions.py +333 -0
- app/shared/services/llm/constraints/inline_batch.py +279 -0
- app/shared/services/llm/discovery/__init__.py +35 -0
- app/shared/services/llm/discovery/scanner.py +181 -0
- app/shared/services/llm/generation/__init__.py +42 -0
- app/shared/services/llm/generation/agent_wiring.py +156 -0
- app/shared/services/llm/generation/config_builder.py +386 -0
- app/shared/services/llm/generation/errors.py +36 -0
- app/shared/services/llm/generation/existing_config.py +99 -0
- app/shared/services/llm/generation/profiler.py +279 -0
- app/shared/services/llm/generation/prompt_builder.py +199 -0
- app/shared/services/llm/generation/response_parser.py +144 -0
- app/shared/services/llm/generation/service.py +622 -0
- app/shared/services/llm/models.py +104 -0
- app/shared/services/llm/providers/__init__.py +48 -0
- app/shared/services/llm/providers/base.py +310 -0
- app/shared/services/llm/providers/cached_provider.py +90 -0
- app/shared/services/llm/providers/ollama.py +498 -0
- app/shared/services/llm/providers/openai.py +334 -0
- app/shared/services/llm/providers/registry.py +108 -0
- app/shared/services/llm/schema_resolver.py +141 -0
- app/shared/services/llm/suggestion_utils.py +219 -0
- app/shared/services/llm/validate_executor.py +163 -0
- app/shared/services/llm/yaml_io.py +406 -0
- app/shared/services/preview/__init__.py +18 -0
- app/shared/services/preview/loader.py +145 -0
- app/shared/services/preview/path_validation.py +138 -0
- app/shared/services/project_loader.py +57 -0
- app/shared/services/schema_inference.py +260 -0
- app/shared/services/schema_runtime_builder.py +120 -0
- app/shared/services/validation/__init__.py +52 -0
- app/shared/services/validation/chunked_loader.py +509 -0
- app/shared/services/validation/dag/__init__.py +35 -0
- app/shared/services/validation/dag/builder.py +141 -0
- app/shared/services/validation/dag/executor.py +225 -0
- app/shared/services/validation/dag/sorter.py +77 -0
- app/shared/services/validation/data_loader.py +231 -0
- app/shared/services/validation/engine.py +446 -0
- app/shared/services/validation/executor.py +1030 -0
- app/shared/services/validation/extractors.py +266 -0
- app/shared/services/validation/history.py +209 -0
- app/shared/services/validation/json_payload.py +136 -0
- app/shared/services/validation/loader.py +152 -0
- app/shared/services/validation/memory_monitor.py +179 -0
- app/shared/services/validation/postprocess.py +208 -0
- app/shared/services/validation/progress.py +64 -0
- app/shared/services/validation/report_export.py +222 -0
- app/shared/services/validation/resolver.py +180 -0
- app/shared/services/validation/service.py +418 -0
- app/shared/services/validation/types.py +238 -0
- app/shared/services/validation/validators/__init__.py +36 -0
- app/shared/services/validation/validators/adapter.py +182 -0
- app/shared/services/validation/validators/base.py +332 -0
- app/shared/services/validation/validators/composite.py +233 -0
- app/shared/services/validation/validators/date_logic.py +276 -0
- app/start_server.py +133 -0
- precis_cli-0.1.3.dist-info/METADATA +180 -0
- precis_cli-0.1.3.dist-info/RECORD +442 -0
- precis_cli-0.1.3.dist-info/WHEEL +5 -0
- precis_cli-0.1.3.dist-info/entry_points.txt +4 -0
- precis_cli-0.1.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,181 @@
|
|
|
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
|
+
- 自动发现本地运行的 AI 服务(Ollama、OpenAI 兼容服务)
|
|
21
|
+
- 扫描常用端口:Ollama(11434)、OpenAI 兼容(1234, 8080, 8000)
|
|
22
|
+
- 检测服务健康状态并获取可用模型列表
|
|
23
|
+
- 返回结构化的服务发现结果
|
|
24
|
+
|
|
25
|
+
架构设计:
|
|
26
|
+
- 配置驱动扫描:SCANS 字典定义各服务类型的检测规则
|
|
27
|
+
- 异步 IO:使用 aiohttp 并发检测多个端口
|
|
28
|
+
- 单例模式:全局 scanner 实例供 API 层调用
|
|
29
|
+
|
|
30
|
+
输入示例:
|
|
31
|
+
services = await scanner.scan()
|
|
32
|
+
# 或指定主机
|
|
33
|
+
services = await scanner.scan(["localhost", "192.168.1.100"])
|
|
34
|
+
|
|
35
|
+
输出示例:
|
|
36
|
+
[
|
|
37
|
+
DiscoveredService(
|
|
38
|
+
id="detected-ollama-11434",
|
|
39
|
+
name="Ollama @ :11434",
|
|
40
|
+
type="ollama",
|
|
41
|
+
base_url="http://localhost:11434",
|
|
42
|
+
models=["llama3.2", "qwen2.5"],
|
|
43
|
+
status="available"
|
|
44
|
+
)
|
|
45
|
+
]
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
import asyncio
|
|
49
|
+
from dataclasses import dataclass
|
|
50
|
+
from typing import Any
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class DiscoveredService:
|
|
55
|
+
"""
|
|
56
|
+
@classdesc 发现的服务数据类
|
|
57
|
+
|
|
58
|
+
封装本地扫描到的 AI 服务信息,包括服务类型、URL、可用模型和状态。
|
|
59
|
+
|
|
60
|
+
字段:
|
|
61
|
+
id: 服务唯一标识
|
|
62
|
+
name: 服务显示名称
|
|
63
|
+
type: 服务类型(openai / ollama)
|
|
64
|
+
base_url: API 基础 URL
|
|
65
|
+
models: 可用模型列表
|
|
66
|
+
status: 服务状态(available / unavailable)
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
id: str
|
|
70
|
+
name: str
|
|
71
|
+
type: str # openai / ollama
|
|
72
|
+
base_url: str
|
|
73
|
+
models: list[str]
|
|
74
|
+
status: str # available / unavailable
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class ServiceScanner:
|
|
78
|
+
"""
|
|
79
|
+
@classdesc 本地服务扫描器
|
|
80
|
+
|
|
81
|
+
自动发现本地运行的 AI 服务(Ollama、OpenAI 兼容服务)。
|
|
82
|
+
扫描常用端口:Ollama(11434)、OpenAI 兼容(1234, 8080, 8000)。
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
# 服务类型 -> 检测配置
|
|
86
|
+
SCANS: dict[str, dict[str, Any]] = {
|
|
87
|
+
"ollama": {"ports": [11434], "health_path": "/api/tags", "model_field": "models", "model_name_field": "name"},
|
|
88
|
+
"openai": {
|
|
89
|
+
"ports": [1234, 8080, 8000],
|
|
90
|
+
"health_path": "/v1/models",
|
|
91
|
+
"model_field": "data",
|
|
92
|
+
"model_name_field": "id",
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async def scan(self, hosts: list[str] | None = None) -> list[DiscoveredService]:
|
|
97
|
+
"""
|
|
98
|
+
@methoddesc 扫描本地运行的 AI 服务
|
|
99
|
+
|
|
100
|
+
遍历预定义的端口列表,尝试连接并识别 Ollama 和 OpenAI 兼容服务。
|
|
101
|
+
|
|
102
|
+
参数:
|
|
103
|
+
hosts: 要扫描的主机列表,默认扫描 localhost 和 127.0.0.1
|
|
104
|
+
|
|
105
|
+
返回:
|
|
106
|
+
发现的服务列表(DiscoveredService 对象列表)
|
|
107
|
+
"""
|
|
108
|
+
if hosts is None:
|
|
109
|
+
hosts = ["localhost", "127.0.0.1"]
|
|
110
|
+
|
|
111
|
+
# 收集所有 (svc_type, host, port) 探测任务,并发执行(替代串行三层嵌套循环)
|
|
112
|
+
tasks = []
|
|
113
|
+
for svc_type, cfg in self.SCANS.items():
|
|
114
|
+
for host in hosts:
|
|
115
|
+
for port in cfg["ports"]:
|
|
116
|
+
tasks.append(
|
|
117
|
+
self._detect(
|
|
118
|
+
svc_type, host, port, cfg["health_path"], cfg["model_field"], cfg["model_name_field"]
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# 并发探测所有地址,过滤掉未发现的(None)
|
|
123
|
+
raw_results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
124
|
+
results = [r for r in raw_results if isinstance(r, DiscoveredService)]
|
|
125
|
+
|
|
126
|
+
return results
|
|
127
|
+
|
|
128
|
+
async def _detect(
|
|
129
|
+
self, svc_type: str, host: str, port: int, path: str, model_field: str, name_field: str
|
|
130
|
+
) -> DiscoveredService | None:
|
|
131
|
+
"""
|
|
132
|
+
@methoddesc 检测单个地址是否运行着指定的 AI 服务
|
|
133
|
+
|
|
134
|
+
通过发送 GET 请求到健康检查路径,根据响应格式判断服务类型并提取模型列表。
|
|
135
|
+
|
|
136
|
+
参数:
|
|
137
|
+
svc_type: 服务类型标识("ollama" 或 "openai")
|
|
138
|
+
host: 主机名或 IP 地址
|
|
139
|
+
port: 端口号
|
|
140
|
+
path: 健康检查路径(如 /api/tags 或 /v1/models)
|
|
141
|
+
model_field: 响应 JSON 中模型列表的字段名
|
|
142
|
+
name_field: 模型对象中名称的字段名
|
|
143
|
+
|
|
144
|
+
返回:
|
|
145
|
+
如果发现服务返回 DiscoveredService,否则 None
|
|
146
|
+
"""
|
|
147
|
+
url = f"http://{host}:{port}"
|
|
148
|
+
try:
|
|
149
|
+
# aiohttp 是 [ai]/[full] 可选依赖,按需延迟导入
|
|
150
|
+
import aiohttp
|
|
151
|
+
|
|
152
|
+
# 使用 aiohttp 发送异步 GET 请求,超时 5 秒
|
|
153
|
+
timeout = aiohttp.ClientTimeout(total=5)
|
|
154
|
+
async with aiohttp.ClientSession() as session:
|
|
155
|
+
async with session.get(f"{url}{path}", timeout=timeout) as resp:
|
|
156
|
+
if resp.status != 200:
|
|
157
|
+
return None
|
|
158
|
+
|
|
159
|
+
data = await resp.json()
|
|
160
|
+
# 从响应中提取模型名称列表
|
|
161
|
+
models = [m[name_field] for m in data.get(model_field, [])]
|
|
162
|
+
|
|
163
|
+
# 根据类型生成友好名称
|
|
164
|
+
name_map = {"ollama": "Ollama", "openai": "OpenAI-Compatible"}
|
|
165
|
+
base_name = name_map.get(svc_type, svc_type)
|
|
166
|
+
|
|
167
|
+
return DiscoveredService(
|
|
168
|
+
id=f"detected-{svc_type}-{port}",
|
|
169
|
+
name=f"{base_name} @ :{port}",
|
|
170
|
+
type=svc_type,
|
|
171
|
+
base_url=url,
|
|
172
|
+
models=models,
|
|
173
|
+
status="available",
|
|
174
|
+
)
|
|
175
|
+
except Exception:
|
|
176
|
+
# 连接失败、超时或响应格式不对,都视为未检测到服务
|
|
177
|
+
return None
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# 全局实例
|
|
181
|
+
scanner = ServiceScanner()
|
|
@@ -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
|
+
"""@fileoverview LLM 配置生成服务模块入口
|
|
17
|
+
|
|
18
|
+
功能概述:
|
|
19
|
+
- 导出配置生成服务(ConfigGenerationService)及选项类
|
|
20
|
+
- 供上层业务调用以生成 Precis 项目配置
|
|
21
|
+
|
|
22
|
+
架构设计:
|
|
23
|
+
- 聚合导出 service.py 中的公共类和异常
|
|
24
|
+
- 通过 __all__ 控制对外暴露的接口
|
|
25
|
+
|
|
26
|
+
输入示例:
|
|
27
|
+
from app.shared.services.llm.generation import ConfigGenerationService, GenerationOptions
|
|
28
|
+
|
|
29
|
+
输出示例:
|
|
30
|
+
service = ConfigGenerationService(provider_id="openai")
|
|
31
|
+
result = await service.generate(...)
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from .service import CancelledError, ConfigGenerationService, GenerationOptions, GenerationParseError, ProfilingOptions
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"ConfigGenerationService",
|
|
38
|
+
"GenerationOptions",
|
|
39
|
+
"ProfilingOptions",
|
|
40
|
+
"CancelledError",
|
|
41
|
+
"GenerationParseError",
|
|
42
|
+
]
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2026 Precis Team
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
"""@fileoverview Agent 模式装配(工具注册表 + 提示词构建)
|
|
17
|
+
|
|
18
|
+
把 ConfigGenerationService 中与 AgentExecutor 装配相关的纯构建逻辑
|
|
19
|
+
抽出为无状态函数:工具注册表创建、系统提示词与任务消息构建。
|
|
20
|
+
注册表中的 generate/refine 工具持有 service 实例引用(工具内部回调
|
|
21
|
+
service 的生成/精修能力),故 create_agent_registry 以 service 为参数。
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from typing import TYPE_CHECKING
|
|
27
|
+
|
|
28
|
+
from .profiler import format_profiling_for_agent
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from app.shared.services.ai.agent.tool_registry import ToolRegistry
|
|
32
|
+
|
|
33
|
+
from .service import ConfigGenerationService
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def create_agent_registry(
|
|
37
|
+
service: ConfigGenerationService,
|
|
38
|
+
validation_sample_size: int,
|
|
39
|
+
chunk_max_columns: int,
|
|
40
|
+
chunk_max_files: int,
|
|
41
|
+
) -> ToolRegistry:
|
|
42
|
+
"""创建 Agent 工具注册表。
|
|
43
|
+
|
|
44
|
+
参数:
|
|
45
|
+
service: 配置生成服务实例(generate/refine 工具的执行宿主)
|
|
46
|
+
validation_sample_size: validate_config 工具的抽样行数
|
|
47
|
+
chunk_max_columns: 分块列数上限(plan_chunks 工具)
|
|
48
|
+
chunk_max_files: 分块文件数上限(plan_chunks 工具)
|
|
49
|
+
|
|
50
|
+
返回:
|
|
51
|
+
已注册全部五个工具的 ToolRegistry
|
|
52
|
+
"""
|
|
53
|
+
from app.shared.services.ai.agent.tool_registry import ToolRegistry
|
|
54
|
+
from app.shared.services.ai.agent.tools import (
|
|
55
|
+
ConfigGenerateTool,
|
|
56
|
+
ConfigRefineTool,
|
|
57
|
+
ConfigValidateTool,
|
|
58
|
+
MergeResultsTool,
|
|
59
|
+
PlanChunksTool,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
registry = ToolRegistry()
|
|
63
|
+
|
|
64
|
+
# 工具注册统一走 register_tool(name/description/parameters/handler 自动提取)
|
|
65
|
+
registry.register_tool(
|
|
66
|
+
PlanChunksTool(
|
|
67
|
+
profiling_data=service._profiling_data,
|
|
68
|
+
file_paths=service._file_paths,
|
|
69
|
+
chunk_max_columns=chunk_max_columns,
|
|
70
|
+
chunk_max_files=chunk_max_files,
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
registry.register_tool(MergeResultsTool())
|
|
74
|
+
# generate/refine 工具持有 service 引用(工具内部回调 service 的生成/精修能力)
|
|
75
|
+
registry.register_tool(ConfigGenerateTool(service))
|
|
76
|
+
registry.register_tool(
|
|
77
|
+
ConfigValidateTool(
|
|
78
|
+
file_paths=service._file_paths,
|
|
79
|
+
profiling_data=service._profiling_data,
|
|
80
|
+
sample_size=validation_sample_size,
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
registry.register_tool(ConfigRefineTool(service))
|
|
84
|
+
|
|
85
|
+
return registry
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def build_agent_system_prompt() -> str:
|
|
89
|
+
"""构建 Agent 系统提示词。"""
|
|
90
|
+
return """你是一个数据治理专家 Agent,擅长分析数据文件并生成 Precis V2 数据验证配置。
|
|
91
|
+
|
|
92
|
+
你的任务是根据用户提供的数据文件画像,生成高质量的 schemas、constraints、regex_nodes 配置。
|
|
93
|
+
|
|
94
|
+
可用工具:
|
|
95
|
+
1. plan_chunks: 根据数据画像生成分块计划(大数据量时先调用)。
|
|
96
|
+
2. generate_config: 根据画像生成完整配置。这是最终输出工具,工具返回的 config 会被作为 Agent 最终结果,调用后任务即结束。
|
|
97
|
+
3. merge_results: 合并多个局部配置为一个完整配置(分块生成后使用)。
|
|
98
|
+
4. validate_config: 对配置做抽样校验,返回问题列表(中间工具)。
|
|
99
|
+
5. refine_config: 根据校验问题修正配置(中间工具)。
|
|
100
|
+
|
|
101
|
+
工作原则:
|
|
102
|
+
- 最终必须通过调用 generate_config 工具输出配置,不要直接输出 JSON 文本。
|
|
103
|
+
- 如果数据量小,直接调用 generate_config 生成完整配置。
|
|
104
|
+
- 如果用户开启了 auto_chunking 且数据量大(文件数 > chunk_max_files 或列数 > chunk_max_columns),先调用 plan_chunks,然后按 chunk 多次调用 generate_config,最后用 merge_results 合并,再调用一次 generate_config 输出最终配置。
|
|
105
|
+
- 可选流程:generate_config → validate_config → refine_config → generate_config(最终)。
|
|
106
|
+
- 你最多只能调用有限次工具,不要把大量时间浪费在反复校验上。"""
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def build_agent_task_message(
|
|
110
|
+
profiling_data: list[dict],
|
|
111
|
+
project_name: str,
|
|
112
|
+
project_id: str,
|
|
113
|
+
keep_existing: bool,
|
|
114
|
+
auto_chunking: bool,
|
|
115
|
+
chunk_max_columns: int,
|
|
116
|
+
chunk_max_files: int,
|
|
117
|
+
) -> str:
|
|
118
|
+
"""构建 Agent 任务消息。
|
|
119
|
+
|
|
120
|
+
参数:
|
|
121
|
+
profiling_data: 数据画像结果
|
|
122
|
+
project_name: 项目显示名
|
|
123
|
+
project_id: 项目标识符
|
|
124
|
+
keep_existing: 是否保留既有配置
|
|
125
|
+
auto_chunking: 是否开启自动分块
|
|
126
|
+
chunk_max_columns: 分块列数上限
|
|
127
|
+
chunk_max_files: 分块文件数上限
|
|
128
|
+
|
|
129
|
+
返回:
|
|
130
|
+
拼装完成的任务消息文本
|
|
131
|
+
"""
|
|
132
|
+
parts = [
|
|
133
|
+
f"为项目 '{project_name}' (id={project_id}) 生成数据验证配置。",
|
|
134
|
+
"",
|
|
135
|
+
"## 数据画像",
|
|
136
|
+
format_profiling_for_agent(profiling_data),
|
|
137
|
+
"",
|
|
138
|
+
"## 要求",
|
|
139
|
+
"- 生成 schemas、constraints、regex_nodes",
|
|
140
|
+
f"- keep_existing={'true' if keep_existing else 'false'}",
|
|
141
|
+
f"- auto_chunking={'true' if auto_chunking else 'false'}",
|
|
142
|
+
]
|
|
143
|
+
if auto_chunking:
|
|
144
|
+
parts.extend(
|
|
145
|
+
[
|
|
146
|
+
f"- chunk_max_columns={chunk_max_columns}",
|
|
147
|
+
f"- chunk_max_files={chunk_max_files}",
|
|
148
|
+
]
|
|
149
|
+
)
|
|
150
|
+
parts.extend(
|
|
151
|
+
[
|
|
152
|
+
"- 工作流建议:直接调用 generate_config 生成完整配置;如果希望更可靠,可以生成后调用 validate_config 校验,再调用 refine_config 修正,最后再次调用 generate_config 输出最终配置。",
|
|
153
|
+
"- 最终必须调用 generate_config 工具,其返回的 config 即为最终结果。",
|
|
154
|
+
]
|
|
155
|
+
)
|
|
156
|
+
return "\n".join(parts)
|