fervis 0.1.0__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.
- fervis/__init__.py +51 -0
- fervis/django/__init__.py +6 -0
- fervis/django/urls.py +5 -0
- fervis/error_codes.py +24 -0
- fervis/errors.py +388 -0
- fervis/evaluation/__init__.py +1 -0
- fervis/fastapi/__init__.py +11 -0
- fervis/flask/__init__.py +11 -0
- fervis/host_api/__init__.py +0 -0
- fervis/host_api/adapters/__init__.py +0 -0
- fervis/host_api/adapters/django/__init__.py +1 -0
- fervis/host_api/adapters/django/adapter.py +99 -0
- fervis/host_api/adapters/django/catalog.py +913 -0
- fervis/host_api/adapters/django/executor.py +94 -0
- fervis/host_api/adapters/django/principal.py +36 -0
- fervis/host_api/adapters/django/schema_introspection.py +362 -0
- fervis/host_api/adapters/fastapi/__init__.py +1 -0
- fervis/host_api/adapters/fastapi/adapter.py +147 -0
- fervis/host_api/adapters/fastapi/catalog.py +50 -0
- fervis/host_api/adapters/fastapi/executor.py +207 -0
- fervis/host_api/adapters/fastapi/loading.py +52 -0
- fervis/host_api/adapters/flask/__init__.py +5 -0
- fervis/host_api/adapters/flask/adapter.py +109 -0
- fervis/host_api/adapters/flask/apispec.py +116 -0
- fervis/host_api/adapters/flask/catalog.py +339 -0
- fervis/host_api/adapters/flask/executor.py +113 -0
- fervis/host_api/adapters/flask/flask_appbuilder.py +91 -0
- fervis/host_api/adapters/flask/loading.py +69 -0
- fervis/host_api/adapters/flask/principal.py +140 -0
- fervis/host_api/adapters/flask/transport.py +92 -0
- fervis/host_api/adapters/get_execution.py +163 -0
- fervis/host_api/adapters/http.py +242 -0
- fervis/host_api/adapters/jsonapi_schema.py +89 -0
- fervis/host_api/adapters/marshmallow_schema.py +86 -0
- fervis/host_api/adapters/openapi/__init__.py +5 -0
- fervis/host_api/adapters/openapi/document.py +266 -0
- fervis/host_api/adapters/openapi/model.py +26 -0
- fervis/host_api/adapters/openapi/translate.py +242 -0
- fervis/host_api/adapters/response_body.py +61 -0
- fervis/host_api/adapters/runtime_output.py +14 -0
- fervis/host_api/compilation/__init__.py +5 -0
- fervis/host_api/compilation/read_request.py +161 -0
- fervis/host_api/context.py +78 -0
- fervis/host_api/contracts/__init__.py +36 -0
- fervis/host_api/contracts/authority.py +133 -0
- fervis/host_api/contracts/capabilities.py +141 -0
- fervis/host_api/contracts/credentials.py +54 -0
- fervis/host_api/contracts/endpoint.py +243 -0
- fervis/host_api/contracts/execution.py +23 -0
- fervis/host_api/contracts/ports.py +56 -0
- fervis/host_api/contracts/read.py +37 -0
- fervis/host_api/contracts/response_envelope.py +24 -0
- fervis/host_api/credentials.py +244 -0
- fervis/interfaces/agent/__init__.py +0 -0
- fervis/interfaces/agent/actions.py +275 -0
- fervis/interfaces/agent/commands.py +202 -0
- fervis/interfaces/cli/__init__.py +6 -0
- fervis/interfaces/cli/commands/__init__.py +1 -0
- fervis/interfaces/cli/commands/auth.py +60 -0
- fervis/interfaces/cli/commands/catalog.py +33 -0
- fervis/interfaces/cli/commands/common.py +63 -0
- fervis/interfaces/cli/commands/config.py +66 -0
- fervis/interfaces/cli/commands/doctor.py +58 -0
- fervis/interfaces/cli/commands/explain.py +173 -0
- fervis/interfaces/cli/commands/goldset.py +57 -0
- fervis/interfaces/cli/commands/init.py +51 -0
- fervis/interfaces/cli/commands/inspect.py +87 -0
- fervis/interfaces/cli/commands/migrate.py +59 -0
- fervis/interfaces/cli/commands/models.py +47 -0
- fervis/interfaces/cli/commands/project.py +56 -0
- fervis/interfaces/cli/commands/runtime.py +44 -0
- fervis/interfaces/cli/commands/scopes.py +79 -0
- fervis/interfaces/cli/commands/sources.py +57 -0
- fervis/interfaces/cli/commands/usage.py +78 -0
- fervis/interfaces/cli/commands/worker.py +36 -0
- fervis/interfaces/cli/contracts.py +112 -0
- fervis/interfaces/cli/dispatch.py +388 -0
- fervis/interfaces/cli/django.py +50 -0
- fervis/interfaces/cli/envelope.py +63 -0
- fervis/interfaces/cli/main.py +155 -0
- fervis/interfaces/cli/parsers.py +479 -0
- fervis/interfaces/cli/principals.py +33 -0
- fervis/interfaces/cli/rendering.py +206 -0
- fervis/interfaces/cli/runtime_ask.py +381 -0
- fervis/interfaces/common/__init__.py +1 -0
- fervis/interfaces/common/admission.py +84 -0
- fervis/interfaces/common/events.py +89 -0
- fervis/interfaces/common/questions.py +561 -0
- fervis/interfaces/common/read_contexts.py +45 -0
- fervis/interfaces/django/__init__.py +1 -0
- fervis/interfaces/django/apps.py +32 -0
- fervis/interfaces/django/composition.py +115 -0
- fervis/interfaces/django/management/__init__.py +1 -0
- fervis/interfaces/django/management/commands/__init__.py +1 -0
- fervis/interfaces/django/management/commands/process_fervis_runs.py +95 -0
- fervis/interfaces/django/models.py +5 -0
- fervis/interfaces/django/principal.py +26 -0
- fervis/interfaces/django/question_interface.py +19 -0
- fervis/interfaces/django/question_run_ports.py +666 -0
- fervis/interfaces/django/run_views.py +302 -0
- fervis/interfaces/django/runs.py +61 -0
- fervis/interfaces/django/security.py +38 -0
- fervis/interfaces/django/throttles.py +11 -0
- fervis/interfaces/django/urls.py +43 -0
- fervis/interfaces/django/views.py +189 -0
- fervis/interfaces/django/worker.py +81 -0
- fervis/interfaces/fastapi/__init__.py +5 -0
- fervis/interfaces/fastapi/principal.py +72 -0
- fervis/interfaces/fastapi/router.py +190 -0
- fervis/interfaces/flask/__init__.py +5 -0
- fervis/interfaces/flask/blueprint.py +179 -0
- fervis/interfaces/flask/principal.py +55 -0
- fervis/lineage/__init__.py +1 -0
- fervis/lineage/apps.py +7 -0
- fervis/lineage/django/__init__.py +1 -0
- fervis/lineage/django/recorder.py +11 -0
- fervis/lineage/django/runtime_failures.py +52 -0
- fervis/lineage/django/runtime_spine.py +67 -0
- fervis/lineage/django/store.py +125 -0
- fervis/lineage/django/terminal_results.py +34 -0
- fervis/lineage/enums.py +200 -0
- fervis/lineage/ids.py +16 -0
- fervis/lineage/memory_artifacts.py +22 -0
- fervis/lineage/migrations/0001_initial.py +893 -0
- fervis/lineage/migrations/0002_answer_answerpresentation_clarificationrequest_and_more.py +576 -0
- fervis/lineage/migrations/0003_remove_clarificationrequest_fervis_clar_req_scope_ck_and_more.py +35 -0
- fervis/lineage/migrations/0004_alter_runtimeerrordetail_error_kind.py +35 -0
- fervis/lineage/migrations/0005_modelcall_tool_spec_chars.py +17 -0
- fervis/lineage/migrations/0006_memoryartifact.py +97 -0
- fervis/lineage/migrations/0007_modelcall_model_subcalls_json.py +17 -0
- fervis/lineage/migrations/0008_alter_runtimeerrordetail_error_kind.py +34 -0
- fervis/lineage/migrations/0009_catalog_endpoint_source_read_fk.py +118 -0
- fervis/lineage/migrations/0010_run_scoped_catalog_endpoints.py +11 -0
- fervis/lineage/migrations/0011_catalog_endpoint_source_read_same_run.py +37 -0
- fervis/lineage/migrations/0012_conversation_read_context_ref.py +20 -0
- fervis/lineage/migrations/__init__.py +1 -0
- fervis/lineage/model_calls.py +312 -0
- fervis/lineage/models.py +928 -0
- fervis/lineage/payloads/__init__.py +1 -0
- fervis/lineage/payloads/execution_proof_graph.py +190 -0
- fervis/lineage/ports.py +128 -0
- fervis/lineage/proof_projection.py +68 -0
- fervis/lineage/proof_summary.py +174 -0
- fervis/lineage/recorder.py +655 -0
- fervis/lineage/recorder_core.py +671 -0
- fervis/lineage/records.py +786 -0
- fervis/lineage/run_chain.py +61 -0
- fervis/lineage/run_spine.py +140 -0
- fervis/lineage/step_summary.py +140 -0
- fervis/lineage/views/__init__.py +1 -0
- fervis/lineage/views/agent.py +591 -0
- fervis/lineage/views/detail.py +29 -0
- fervis/lineage/views/django.py +466 -0
- fervis/lineage/views/explain.py +446 -0
- fervis/lineage/views/explanation.py +36 -0
- fervis/lineage/views/input_lineage.py +179 -0
- fervis/lineage/views/json_payload.py +24 -0
- fervis/lineage/views/model.py +435 -0
- fervis/lineage/views/query.py +239 -0
- fervis/lineage/views/render.py +490 -0
- fervis/lineage/views/service.py +819 -0
- fervis/lineage/views/step_presenters.py +186 -0
- fervis/lineage/views/timeline.py +208 -0
- fervis/lookup/__init__.py +1 -0
- fervis/lookup/answer_rendering/__init__.py +15 -0
- fervis/lookup/answer_rendering/model.py +21 -0
- fervis/lookup/answer_rendering/renderer.py +198 -0
- fervis/lookup/conversation_resolution/__init__.py +65 -0
- fervis/lookup/conversation_resolution/clarifications.py +30 -0
- fervis/lookup/conversation_resolution/model.py +381 -0
- fervis/lookup/conversation_resolution/overlay.py +445 -0
- fervis/lookup/conversation_resolution/parser.py +852 -0
- fervis/lookup/conversation_resolution/prompt.py +334 -0
- fervis/lookup/conversation_resolution/schema.py +289 -0
- fervis/lookup/conversation_resolution/tools.py +4 -0
- fervis/lookup/conversation_resolution/turn.py +167 -0
- fervis/lookup/errors.py +26 -0
- fervis/lookup/fact_plan/__init__.py +1 -0
- fervis/lookup/fact_plan/fact_plan.py +125 -0
- fervis/lookup/fact_plan/field_types.py +17 -0
- fervis/lookup/fact_plan/operations.py +235 -0
- fervis/lookup/fact_plan/relations.py +155 -0
- fervis/lookup/fact_plan/render_spec.py +28 -0
- fervis/lookup/fact_plan/row_sources/__init__.py +82 -0
- fervis/lookup/fact_plan/row_sources/builder.py +614 -0
- fervis/lookup/fact_plan/row_sources/evidence.py +69 -0
- fervis/lookup/fact_plan/row_sources/field_paths.py +208 -0
- fervis/lookup/fact_plan/row_sources/lookup.py +31 -0
- fervis/lookup/fact_plan/row_sources/model.py +117 -0
- fervis/lookup/fact_plan/row_sources/payload.py +194 -0
- fervis/lookup/fact_plan/row_sources/source_groups.py +51 -0
- fervis/lookup/fact_plan/values.py +285 -0
- fervis/lookup/fact_planning/__init__.py +1 -0
- fervis/lookup/fact_planning/aggregate_choice_parts.py +80 -0
- fervis/lookup/fact_planning/available_relations.py +581 -0
- fervis/lookup/fact_planning/blocked_evidence.py +144 -0
- fervis/lookup/fact_planning/executable_support.py +234 -0
- fervis/lookup/fact_planning/fact_planning_family_schema.py +82 -0
- fervis/lookup/fact_planning/fact_requirements.py +188 -0
- fervis/lookup/fact_planning/fulfillment_evidence.py +151 -0
- fervis/lookup/fact_planning/grounded_params.py +89 -0
- fervis/lookup/fact_planning/grouped_ranked_choices.py +641 -0
- fervis/lookup/fact_planning/lineage_summary.py +60 -0
- fervis/lookup/fact_planning/metric_options.py +460 -0
- fervis/lookup/fact_planning/parser.py +234 -0
- fervis/lookup/fact_planning/pattern_plan/__init__.py +5 -0
- fervis/lookup/fact_planning/pattern_plan/aggregate_operations.py +124 -0
- fervis/lookup/fact_planning/pattern_plan/aggregate_outputs.py +247 -0
- fervis/lookup/fact_planning/pattern_plan/aggregate_patterns.py +531 -0
- fervis/lookup/fact_planning/pattern_plan/compiler.py +183 -0
- fervis/lookup/fact_planning/pattern_plan/relation_patterns.py +329 -0
- fervis/lookup/fact_planning/pattern_plan/render_ids.py +25 -0
- fervis/lookup/fact_planning/pattern_plan/row_patterns.py +246 -0
- fervis/lookup/fact_planning/pattern_plan/scalar_patterns.py +86 -0
- fervis/lookup/fact_planning/pattern_plan/shared.py +762 -0
- fervis/lookup/fact_planning/pattern_plan/value_inputs.py +29 -0
- fervis/lookup/fact_planning/plan_shapes.py +27 -0
- fervis/lookup/fact_planning/prompt_sections.py +233 -0
- fervis/lookup/fact_planning/request.py +639 -0
- fervis/lookup/fact_planning/required_inputs.py +75 -0
- fervis/lookup/fact_planning/row_set_filters.py +277 -0
- fervis/lookup/fact_planning/schema.py +319 -0
- fervis/lookup/fact_planning/schema_helpers.py +44 -0
- fervis/lookup/fact_planning/source_binding_basis.py +35 -0
- fervis/lookup/fact_planning/turn.py +241 -0
- fervis/lookup/fact_planning/value_components.py +71 -0
- fervis/lookup/fact_planning/value_validation.py +72 -0
- fervis/lookup/grounding/__init__.py +1 -0
- fervis/lookup/grounding/model.py +216 -0
- fervis/lookup/grounding/parser.py +140 -0
- fervis/lookup/grounding/prompt.py +337 -0
- fervis/lookup/grounding/resolution/__init__.py +6 -0
- fervis/lookup/grounding/resolution/deterministic.py +310 -0
- fervis/lookup/grounding/resolution/model.py +19 -0
- fervis/lookup/grounding/resolution/pipeline.py +208 -0
- fervis/lookup/grounding/resolution/references.py +1260 -0
- fervis/lookup/grounding/resolution/values.py +33 -0
- fervis/lookup/grounding/schema.py +205 -0
- fervis/lookup/grounding/time_intents.py +274 -0
- fervis/lookup/grounding/time_resolution/__init__.py +17 -0
- fervis/lookup/grounding/time_resolution/contract.py +78 -0
- fervis/lookup/grounding/time_resolution/date_values.py +72 -0
- fervis/lookup/grounding/time_resolution/expression_parser.py +270 -0
- fervis/lookup/grounding/time_resolution/intent_validation.py +148 -0
- fervis/lookup/grounding/time_resolution/resolver.py +593 -0
- fervis/lookup/grounding/turn.py +151 -0
- fervis/lookup/lineage/__init__.py +1 -0
- fervis/lookup/lineage/errors.py +5 -0
- fervis/lookup/lineage/explanation_metadata.py +127 -0
- fervis/lookup/lineage/model_turns.py +45 -0
- fervis/lookup/lineage/results.py +926 -0
- fervis/lookup/lineage/source_reads.py +228 -0
- fervis/lookup/lineage/step_summaries.py +515 -0
- fervis/lookup/lineage/steps.py +448 -0
- fervis/lookup/memory/__init__.py +1 -0
- fervis/lookup/memory/available_values.py +181 -0
- fervis/lookup/memory/lineage_artifacts.py +454 -0
- fervis/lookup/memory/outcomes.py +396 -0
- fervis/lookup/memory/projection.py +1651 -0
- fervis/lookup/operation_families/__init__.py +1 -0
- fervis/lookup/operation_families/common/__init__.py +1 -0
- fervis/lookup/operation_families/common/source_binding_metric_fit.py +412 -0
- fervis/lookup/operation_families/comparison_check/__init__.py +1 -0
- fervis/lookup/operation_families/comparison_check/plan_selection.py +16 -0
- fervis/lookup/operation_families/computed_scalar/__init__.py +1 -0
- fervis/lookup/operation_families/computed_scalar/fact_planning.py +72 -0
- fervis/lookup/operation_families/computed_scalar/plan_selection.py +16 -0
- fervis/lookup/operation_families/coverage_check/__init__.py +1 -0
- fervis/lookup/operation_families/coverage_check/plan_selection.py +16 -0
- fervis/lookup/operation_families/existence_check/__init__.py +1 -0
- fervis/lookup/operation_families/existence_check/plan_selection.py +16 -0
- fervis/lookup/operation_families/fact_planning_schema_registry.py +406 -0
- fervis/lookup/operation_families/grouped_aggregate/__init__.py +1 -0
- fervis/lookup/operation_families/grouped_aggregate/plan_selection.py +20 -0
- fervis/lookup/operation_families/grouped_ranked/__init__.py +1 -0
- fervis/lookup/operation_families/grouped_ranked/canonical_groups.py +65 -0
- fervis/lookup/operation_families/grouped_ranked/fact_planning.py +156 -0
- fervis/lookup/operation_families/grouped_ranked/plan_selection.py +336 -0
- fervis/lookup/operation_families/joined_rows/__init__.py +1 -0
- fervis/lookup/operation_families/joined_rows/fact_planning.py +229 -0
- fervis/lookup/operation_families/list_rows/__init__.py +1 -0
- fervis/lookup/operation_families/list_rows/fact_planning.py +53 -0
- fervis/lookup/operation_families/list_rows/plan_selection.py +28 -0
- fervis/lookup/operation_families/plan_selection_registry.py +83 -0
- fervis/lookup/operation_families/ranked_selection/__init__.py +1 -0
- fervis/lookup/operation_families/ranked_selection/plan_selection.py +20 -0
- fervis/lookup/operation_families/scalar_aggregate/__init__.py +1 -0
- fervis/lookup/operation_families/scalar_aggregate/fact_planning.py +147 -0
- fervis/lookup/operation_families/scalar_aggregate/plan_selection.py +16 -0
- fervis/lookup/operation_families/scalar_value/__init__.py +1 -0
- fervis/lookup/operation_families/scalar_value/fact_planning.py +29 -0
- fervis/lookup/operation_families/scalar_value/plan_selection.py +16 -0
- fervis/lookup/operation_families/set_difference/__init__.py +1 -0
- fervis/lookup/operation_families/set_difference/fact_planning.py +204 -0
- fervis/lookup/operation_families/set_difference/plan_selection.py +16 -0
- fervis/lookup/operation_families/source_binding_registry.py +13 -0
- fervis/lookup/orchestration/__init__.py +1 -0
- fervis/lookup/orchestration/limits.py +163 -0
- fervis/lookup/orchestration/model_turn_events.py +88 -0
- fervis/lookup/orchestration/pipeline.py +1972 -0
- fervis/lookup/orchestration/question_lookup_port.py +86 -0
- fervis/lookup/orchestration/request.py +49 -0
- fervis/lookup/orchestration/result.py +67 -0
- fervis/lookup/orchestration/result_synthesis.py +164 -0
- fervis/lookup/orchestration/service.py +274 -0
- fervis/lookup/orchestration/terminal_results.py +240 -0
- fervis/lookup/outcomes/__init__.py +1 -0
- fervis/lookup/outcomes/answerability.py +100 -0
- fervis/lookup/outcomes/clarifications.py +54 -0
- fervis/lookup/outcomes/classification.py +299 -0
- fervis/lookup/outcomes/errors.py +72 -0
- fervis/lookup/outcomes/model.py +133 -0
- fervis/lookup/outcomes/operation_semantics.py +86 -0
- fervis/lookup/outcomes/terminal_details.py +134 -0
- fervis/lookup/plan_execution/__init__.py +1 -0
- fervis/lookup/plan_execution/authorized_sources.py +96 -0
- fervis/lookup/plan_execution/compiled_execution.py +636 -0
- fervis/lookup/plan_execution/errors.py +9 -0
- fervis/lookup/plan_execution/generated_relations.py +66 -0
- fervis/lookup/plan_execution/operation_engine/__init__.py +5 -0
- fervis/lookup/plan_execution/operation_engine/aggregate_operations.py +133 -0
- fervis/lookup/plan_execution/operation_engine/compute_operations.py +58 -0
- fervis/lookup/plan_execution/operation_engine/engine.py +193 -0
- fervis/lookup/plan_execution/operation_engine/predicates.py +69 -0
- fervis/lookup/plan_execution/operation_engine/relation_operations.py +357 -0
- fervis/lookup/plan_execution/operation_engine/shared.py +573 -0
- fervis/lookup/plan_execution/operation_runtime.py +42 -0
- fervis/lookup/plan_execution/relations.py +175 -0
- fervis/lookup/plan_execution/runner.py +857 -0
- fervis/lookup/plan_execution/value_compiler.py +548 -0
- fervis/lookup/plan_execution/verification/__init__.py +80 -0
- fervis/lookup/plan_execution/verification/_shared.py +89 -0
- fervis/lookup/plan_execution/verification/answer_plan.py +212 -0
- fervis/lookup/plan_execution/verification/blocked.py +57 -0
- fervis/lookup/plan_execution/verification/contract_types.py +140 -0
- fervis/lookup/plan_execution/verification/contracts.py +148 -0
- fervis/lookup/plan_execution/verification/execution_proof.py +30 -0
- fervis/lookup/plan_execution/verification/normalization.py +150 -0
- fervis/lookup/plan_execution/verification/operation_contracts.py +488 -0
- fervis/lookup/plan_execution/verification/operation_invariants.py +299 -0
- fervis/lookup/plan_execution/verification/operations.py +338 -0
- fervis/lookup/plan_execution/verification/question_contract.py +75 -0
- fervis/lookup/plan_execution/verification/render.py +162 -0
- fervis/lookup/plan_execution/verification/scalars.py +19 -0
- fervis/lookup/plan_execution/verification/sources.py +399 -0
- fervis/lookup/plan_execution/verification/terminals.py +312 -0
- fervis/lookup/plan_selection/__init__.py +41 -0
- fervis/lookup/plan_selection/family_specs.py +187 -0
- fervis/lookup/plan_selection/model.py +296 -0
- fervis/lookup/plan_selection/parser.py +237 -0
- fervis/lookup/plan_selection/prompt.py +180 -0
- fervis/lookup/plan_selection/role_semantics.py +82 -0
- fervis/lookup/plan_selection/schema.py +87 -0
- fervis/lookup/plan_selection/source_strategies.py +652 -0
- fervis/lookup/plan_selection/support_options.py +192 -0
- fervis/lookup/plan_selection/turn.py +144 -0
- fervis/lookup/query_enrichment/__init__.py +25 -0
- fervis/lookup/query_enrichment/model.py +60 -0
- fervis/lookup/query_enrichment/parser.py +266 -0
- fervis/lookup/query_enrichment/prompt.py +225 -0
- fervis/lookup/query_enrichment/schema.py +100 -0
- fervis/lookup/query_enrichment/turn.py +155 -0
- fervis/lookup/question_contract/__init__.py +101 -0
- fervis/lookup/question_contract/_normalization.py +7 -0
- fervis/lookup/question_contract/answer_output_support.py +26 -0
- fervis/lookup/question_contract/model.py +940 -0
- fervis/lookup/question_contract/parser.py +947 -0
- fervis/lookup/question_contract/prompt.py +217 -0
- fervis/lookup/question_contract/schema.py +362 -0
- fervis/lookup/question_contract/tools.py +9 -0
- fervis/lookup/question_contract/turn.py +196 -0
- fervis/lookup/read_eligibility/__init__.py +53 -0
- fervis/lookup/read_eligibility/candidate_identity.py +71 -0
- fervis/lookup/read_eligibility/candidate_scope.py +127 -0
- fervis/lookup/read_eligibility/cards.py +220 -0
- fervis/lookup/read_eligibility/filtering.py +64 -0
- fervis/lookup/read_eligibility/model.py +82 -0
- fervis/lookup/read_eligibility/parser.py +349 -0
- fervis/lookup/read_eligibility/prompt.py +182 -0
- fervis/lookup/read_eligibility/recall.py +121 -0
- fervis/lookup/read_eligibility/row_paths.py +56 -0
- fervis/lookup/read_eligibility/schema.py +170 -0
- fervis/lookup/read_eligibility/source_groups.py +34 -0
- fervis/lookup/read_eligibility/support_projection.py +27 -0
- fervis/lookup/read_eligibility/surface.py +35 -0
- fervis/lookup/read_eligibility/turn.py +159 -0
- fervis/lookup/relation_catalog/__init__.py +53 -0
- fervis/lookup/relation_catalog/facts.py +56 -0
- fervis/lookup/relation_catalog/from_host_api.py +347 -0
- fervis/lookup/relation_catalog/identity.py +68 -0
- fervis/lookup/relation_catalog/interface_tokens.py +70 -0
- fervis/lookup/relation_catalog/model.py +165 -0
- fervis/lookup/relation_catalog/ports.py +17 -0
- fervis/lookup/relation_catalog/row_paths.py +24 -0
- fervis/lookup/relation_catalog/selection/__init__.py +47 -0
- fervis/lookup/relation_catalog/selection/model.py +98 -0
- fervis/lookup/relation_catalog/selection/results.py +47 -0
- fervis/lookup/relation_catalog/selection/selector/__init__.py +12 -0
- fervis/lookup/relation_catalog/selection/selector/constants.py +224 -0
- fervis/lookup/relation_catalog/selection/selector/fact_selection.py +654 -0
- fervis/lookup/relation_catalog/selection/selector/resolver.py +205 -0
- fervis/lookup/relation_catalog/selection/selector/terms.py +134 -0
- fervis/lookup/relation_catalog/validation.py +172 -0
- fervis/lookup/source_binding/__init__.py +57 -0
- fervis/lookup/source_binding/candidates/__init__.py +33 -0
- fervis/lookup/source_binding/candidates/_shared.py +46 -0
- fervis/lookup/source_binding/candidates/api_sources.py +140 -0
- fervis/lookup/source_binding/candidates/bindings.py +22 -0
- fervis/lookup/source_binding/candidates/bound_payload.py +228 -0
- fervis/lookup/source_binding/candidates/candidate_tree.py +93 -0
- fervis/lookup/source_binding/candidates/compact.py +336 -0
- fervis/lookup/source_binding/candidates/eligibility.py +164 -0
- fervis/lookup/source_binding/candidates/evidence.py +211 -0
- fervis/lookup/source_binding/candidates/fulfillment_slots.py +403 -0
- fervis/lookup/source_binding/candidates/handles.py +211 -0
- fervis/lookup/source_binding/candidates/indexes.py +120 -0
- fervis/lookup/source_binding/candidates/memory.py +89 -0
- fervis/lookup/source_binding/candidates/model.py +26 -0
- fervis/lookup/source_binding/candidates/model_visible_evidence.py +104 -0
- fervis/lookup/source_binding/candidates/params.py +511 -0
- fervis/lookup/source_binding/candidates/plan_selection_filter.py +140 -0
- fervis/lookup/source_binding/candidates/population.py +48 -0
- fervis/lookup/source_binding/candidates/population_roles.py +148 -0
- fervis/lookup/source_binding/candidates/raw_payload.py +533 -0
- fervis/lookup/source_binding/candidates/registry.py +273 -0
- fervis/lookup/source_binding/candidates/registry_builder.py +346 -0
- fervis/lookup/source_binding/candidates/row_population.py +26 -0
- fervis/lookup/source_binding/candidates/row_predicates.py +70 -0
- fervis/lookup/source_binding/candidates/same_scope.py +287 -0
- fervis/lookup/source_binding/candidates/scope_values.py +47 -0
- fervis/lookup/source_binding/candidates/values.py +87 -0
- fervis/lookup/source_binding/evidence_types.py +15 -0
- fervis/lookup/source_binding/lineage_summary.py +203 -0
- fervis/lookup/source_binding/membership_tests.py +32 -0
- fervis/lookup/source_binding/memory_context.py +132 -0
- fervis/lookup/source_binding/metric_fit.py +7 -0
- fervis/lookup/source_binding/model.py +214 -0
- fervis/lookup/source_binding/normal_instance_roles.py +126 -0
- fervis/lookup/source_binding/param_surface.py +63 -0
- fervis/lookup/source_binding/param_values.py +13 -0
- fervis/lookup/source_binding/parser.py +2289 -0
- fervis/lookup/source_binding/parser_common.py +51 -0
- fervis/lookup/source_binding/population_bindings.py +304 -0
- fervis/lookup/source_binding/prompt.py +503 -0
- fervis/lookup/source_binding/schema.py +972 -0
- fervis/lookup/source_binding/terminal_outcomes.py +164 -0
- fervis/lookup/source_binding/terminal_parser.py +129 -0
- fervis/lookup/source_binding/turn.py +307 -0
- fervis/lookup/source_reads/__init__.py +1 -0
- fervis/lookup/source_reads/response.py +231 -0
- fervis/lookup/turn_prompts/__init__.py +55 -0
- fervis/lookup/turn_prompts/approval.py +30 -0
- fervis/lookup/turn_prompts/builder.py +158 -0
- fervis/lookup/turn_prompts/context.py +136 -0
- fervis/lookup/turn_prompts/invocation.py +58 -0
- fervis/lookup/turn_prompts/projections/__init__.py +17 -0
- fervis/lookup/turn_prompts/projections/response_shape.py +1047 -0
- fervis/lookup/turn_prompts/rendering.py +14 -0
- fervis/lookup/turn_prompts/sections.py +38 -0
- fervis/lookup/turn_prompts/turn_prompt.py +69 -0
- fervis/memory/__init__.py +1 -0
- fervis/memory/_serialization.py +13 -0
- fervis/memory/activation.py +182 -0
- fervis/memory/addresses.py +397 -0
- fervis/memory/answer_outputs.py +214 -0
- fervis/memory/artifacts.py +79 -0
- fervis/memory/conversation_context/__init__.py +23 -0
- fervis/memory/conversation_context/activation.py +355 -0
- fervis/memory/conversation_context/model.py +157 -0
- fervis/memory/identities.py +309 -0
- fervis/memory/lineage.py +123 -0
- fervis/memory/projection.py +210 -0
- fervis/memory/prompt_contract.py +35 -0
- fervis/model_io/__init__.py +1 -0
- fervis/model_io/backbone/__init__.py +1 -0
- fervis/model_io/backbone/contracts.py +71 -0
- fervis/model_io/backbone/dto.py +69 -0
- fervis/model_io/backbone/factory.py +94 -0
- fervis/model_io/backbone/model_routing.py +60 -0
- fervis/model_io/backbone/registry.py +67 -0
- fervis/model_io/backbone/tool_codec.py +65 -0
- fervis/model_io/models.py +23 -0
- fervis/model_io/pricing/__init__.py +5 -0
- fervis/model_io/pricing/models_dev.py +100 -0
- fervis/model_io/providers/__init__.py +1 -0
- fervis/model_io/providers/anthropic_adapter/__init__.py +57 -0
- fervis/model_io/providers/anthropic_adapter/conversation_resolution_transport.py +26 -0
- fervis/model_io/providers/anthropic_adapter/loop_adapter.py +276 -0
- fervis/model_io/providers/bootstrap.py +28 -0
- fervis/model_io/providers/chat_runtime.py +674 -0
- fervis/model_io/providers/openai_compatible_adapter/__init__.py +78 -0
- fervis/model_io/providers/openai_compatible_adapter/loop_adapter.py +353 -0
- fervis/model_io/providers/schema_projection.py +24 -0
- fervis/model_io/providers/session_runtime.py +48 -0
- fervis/model_io/providers/shared_runtime.py +97 -0
- fervis/model_io/providers/specs.py +97 -0
- fervis/model_io/routing/__init__.py +13 -0
- fervis/model_io/routing/router.py +165 -0
- fervis/model_io/structured_output/__init__.py +1 -0
- fervis/model_io/structured_output/errors.py +88 -0
- fervis/model_io/structured_output/generation.py +99 -0
- fervis/model_io/structured_output/parsing.py +19 -0
- fervis/model_io/structured_output/provider_budget.py +22 -0
- fervis/model_io/structured_output/specs.py +27 -0
- fervis/model_io/structured_output/validation.py +111 -0
- fervis/model_io/telemetry.py +76 -0
- fervis/model_io/turn_artifacts.py +53 -0
- fervis/model_io/turns.py +16 -0
- fervis/observability/__init__.py +1 -0
- fervis/observability/django.py +184 -0
- fervis/observability/django_prompt_captures.py +77 -0
- fervis/observability/event_contracts.py +77 -0
- fervis/observability/model_calls.py +22 -0
- fervis/observability/prompt_captures.py +64 -0
- fervis/observability/prompt_viewer/__init__.py +1 -0
- fervis/observability/prompt_viewer/render_prompts.py +966 -0
- fervis/observability/query.py +112 -0
- fervis/observability/render.py +90 -0
- fervis/observability/usage.py +318 -0
- fervis/observability/usage_types.py +23 -0
- fervis/project/__init__.py +50 -0
- fervis/project/auth_config/__init__.py +14 -0
- fervis/project/auth_config/checks.py +195 -0
- fervis/project/auth_config/commands.py +318 -0
- fervis/project/auth_config/loading.py +42 -0
- fervis/project/auth_config/validation.py +235 -0
- fervis/project/catalog_checks.py +176 -0
- fervis/project/catalog_command.py +269 -0
- fervis/project/catalog_errors.py +54 -0
- fervis/project/config_commands.py +470 -0
- fervis/project/config_io.py +157 -0
- fervis/project/config_schema.py +456 -0
- fervis/project/config_versions/__init__.py +11 -0
- fervis/project/config_versions/auth.py +244 -0
- fervis/project/config_versions/common.py +57 -0
- fervis/project/config_versions/main.py +282 -0
- fervis/project/configuration.py +527 -0
- fervis/project/discovery.py +361 -0
- fervis/project/django_runtime.py +41 -0
- fervis/project/doctor.py +304 -0
- fervis/project/edit_result.py +36 -0
- fervis/project/host_api_context.py +75 -0
- fervis/project/host_runtime.py +18 -0
- fervis/project/importing.py +226 -0
- fervis/project/init.py +253 -0
- fervis/project/integration.py +249 -0
- fervis/project/model_commands.py +208 -0
- fervis/project/mounting/__init__.py +81 -0
- fervis/project/mounting/bindings.py +435 -0
- fervis/project/mounting/common.py +207 -0
- fervis/project/mounting/django.py +1062 -0
- fervis/project/mounting/fastapi.py +725 -0
- fervis/project/mounting/fastapi_sources.py +73 -0
- fervis/project/mounting/flask.py +472 -0
- fervis/project/mounting/source.py +163 -0
- fervis/project/persistence/__init__.py +100 -0
- fervis/project/persistence/alembic_runner.py +55 -0
- fervis/project/persistence/contracts.py +84 -0
- fervis/project/persistence/database_url.py +124 -0
- fervis/project/persistence/revisions.py +7 -0
- fervis/project/persistence/schema.py +110 -0
- fervis/project/persistence/schema_snapshots/__init__.py +0 -0
- fervis/project/persistence/schema_snapshots/v0001.py +1455 -0
- fervis/project/persistence/schema_snapshots/v0002.py +22 -0
- fervis/project/persistence/sql_backend.py +512 -0
- fervis/project/persistence/sqlite.py +98 -0
- fervis/project/persistence/sqlite_engine.py +20 -0
- fervis/project/persistence_migrations/env.py +22 -0
- fervis/project/persistence_migrations/script.py.mako +28 -0
- fervis/project/persistence_migrations/versions/0001_initial.py +21 -0
- fervis/project/persistence_migrations/versions/0002_read_context_ref.py +39 -0
- fervis/project/source_detection.py +59 -0
- fervis/project/source_paths.py +44 -0
- fervis/project/source_scope.py +64 -0
- fervis/questions/__init__.py +19 -0
- fervis/questions/contracts.py +231 -0
- fervis/questions/ports.py +285 -0
- fervis/questions/result_data.py +20 -0
- fervis/questions/service.py +456 -0
- fervis/run_work/__init__.py +9 -0
- fervis/run_work/contracts.py +30 -0
- fervis/run_work/events.py +174 -0
- fervis/run_work/queue/django/__init__.py +27 -0
- fervis/run_work/queue/django/apps.py +7 -0
- fervis/run_work/queue/django/migrations/0001_initial.py +131 -0
- fervis/run_work/queue/django/migrations/0002_runtime_context.py +15 -0
- fervis/run_work/queue/django/migrations/0003_remove_max_turns.py +14 -0
- fervis/run_work/queue/django/migrations/0004_read_context_ref.py +20 -0
- fervis/run_work/queue/django/migrations/__init__.py +1 -0
- fervis/run_work/queue/django/models.py +87 -0
- fervis/run_work/queue/django/queue.py +436 -0
- fervis/run_work/queue/django/runner.py +65 -0
- fervis/run_work/queued_execution.py +92 -0
- fervis/run_work/service.py +255 -0
- fervis/run_work/worker.py +207 -0
- fervis/storage/__init__.py +1 -0
- fervis/storage/sql/__init__.py +5 -0
- fervis/storage/sql/authority_scope.py +71 -0
- fervis/storage/sql/bundle.py +103 -0
- fervis/storage/sql/checks.py +162 -0
- fervis/storage/sql/engine.py +71 -0
- fervis/storage/sql/lineage_query.py +538 -0
- fervis/storage/sql/lineage_store.py +141 -0
- fervis/storage/sql/lookup_runtime.py +48 -0
- fervis/storage/sql/observability_query.py +276 -0
- fervis/storage/sql/prompt_captures.py +147 -0
- fervis/storage/sql/question_interface.py +16 -0
- fervis/storage/sql/question_run_ports.py +817 -0
- fervis/storage/sql/rows.py +46 -0
- fervis/storage/sql/terminal.py +130 -0
- fervis/storage/sql/transaction.py +53 -0
- fervis/storage/sql/work_items.py +584 -0
- fervis-0.1.0.dist-info/METADATA +87 -0
- fervis-0.1.0.dist-info/RECORD +617 -0
- fervis-0.1.0.dist-info/WHEEL +4 -0
- fervis-0.1.0.dist-info/entry_points.txt +2 -0
- fervis-0.1.0.dist-info/licenses/LICENSE +202 -0
fervis/__init__.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from fervis.project import (
|
|
6
|
+
DatabaseUrlPersistence,
|
|
7
|
+
DjangoAppSource,
|
|
8
|
+
DjangoDatabasePersistence,
|
|
9
|
+
DjangoIntegration,
|
|
10
|
+
FastAPIAppSource,
|
|
11
|
+
FastAPIIntegration,
|
|
12
|
+
FervisConfig,
|
|
13
|
+
FlaskAppSource,
|
|
14
|
+
FlaskIntegration,
|
|
15
|
+
HostConfig,
|
|
16
|
+
ModelConfig,
|
|
17
|
+
PersistenceTarget,
|
|
18
|
+
ProviderConfig,
|
|
19
|
+
RuntimeRoutes,
|
|
20
|
+
SQLitePersistence,
|
|
21
|
+
discover_project,
|
|
22
|
+
)
|
|
23
|
+
from fervis.project.configuration import ConfigProblem, load_fervis_project_config
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def configured_fervis(*, root: Path | str | None = None):
|
|
27
|
+
project = discover_project(Path(root) if root is not None else Path.cwd())
|
|
28
|
+
loaded = load_fervis_project_config(project)
|
|
29
|
+
if isinstance(loaded, ConfigProblem):
|
|
30
|
+
raise RuntimeError(loaded.message)
|
|
31
|
+
return loaded.integration
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"DatabaseUrlPersistence",
|
|
36
|
+
"DjangoAppSource",
|
|
37
|
+
"DjangoDatabasePersistence",
|
|
38
|
+
"DjangoIntegration",
|
|
39
|
+
"FastAPIAppSource",
|
|
40
|
+
"FastAPIIntegration",
|
|
41
|
+
"FervisConfig",
|
|
42
|
+
"FlaskAppSource",
|
|
43
|
+
"FlaskIntegration",
|
|
44
|
+
"HostConfig",
|
|
45
|
+
"ModelConfig",
|
|
46
|
+
"PersistenceTarget",
|
|
47
|
+
"ProviderConfig",
|
|
48
|
+
"RuntimeRoutes",
|
|
49
|
+
"SQLitePersistence",
|
|
50
|
+
"configured_fervis",
|
|
51
|
+
]
|
fervis/django/urls.py
ADDED
fervis/error_codes.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Fervis error codes used by framework and provider adapters."""
|
|
2
|
+
|
|
3
|
+
VALIDATION_ERROR = "validation_error"
|
|
4
|
+
MISSING_REQUIRED_PARAMETER = "missing_required_parameter"
|
|
5
|
+
INVALID_MODEL_KEY = "invalid_model_key"
|
|
6
|
+
|
|
7
|
+
INSUFFICIENT_PERMISSIONS = "insufficient_permissions"
|
|
8
|
+
READ_CONTEXT_REQUIRED = "read_context_required"
|
|
9
|
+
|
|
10
|
+
RATE_LIMIT_EXCEEDED = "rate_limit_exceeded"
|
|
11
|
+
|
|
12
|
+
INTERNAL_ERROR = "internal_error"
|
|
13
|
+
CONFIGURATION_ERROR = "configuration_error"
|
|
14
|
+
LLM_API_ERROR = "llm_api_error"
|
|
15
|
+
LLM_API_CONNECTION_ERROR = "llm_api_connection_error"
|
|
16
|
+
LLM_API_TIMEOUT = "llm_api_timeout"
|
|
17
|
+
LLM_API_BAD_REQUEST = "llm_api_bad_request"
|
|
18
|
+
LLM_API_AUTHENTICATION_ERROR = "llm_api_authentication_error"
|
|
19
|
+
LLM_API_PERMISSION_ERROR = "llm_api_permission_error"
|
|
20
|
+
LLM_API_NOT_FOUND = "llm_api_not_found"
|
|
21
|
+
LLM_API_CONFLICT = "llm_api_conflict"
|
|
22
|
+
LLM_API_RATE_LIMITED = "llm_api_rate_limited"
|
|
23
|
+
LLM_API_INTERNAL_ERROR = "llm_api_internal_error"
|
|
24
|
+
LLM_API_RESPONSE_INVALID = "llm_api_response_invalid"
|
fervis/errors.py
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
"""Fervis-owned API error hierarchy.
|
|
2
|
+
|
|
3
|
+
This module intentionally has no Django/FastAPI/Flask dependency. Framework
|
|
4
|
+
adapters may translate these errors into host responses, but provider and core
|
|
5
|
+
runtime code should not import host application error modules.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from . import error_codes as codes
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class APIError(Exception):
|
|
16
|
+
"""Base exception for structured Fervis errors."""
|
|
17
|
+
|
|
18
|
+
error_type = "system"
|
|
19
|
+
status_code: int | None = None
|
|
20
|
+
retryable = False
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
code: str,
|
|
25
|
+
message: str,
|
|
26
|
+
*,
|
|
27
|
+
developer_message: str | None = None,
|
|
28
|
+
context: dict[str, Any] | None = None,
|
|
29
|
+
details: list[dict[str, Any]] | None = None,
|
|
30
|
+
retry_after: int | None = None,
|
|
31
|
+
) -> None:
|
|
32
|
+
self.code = code
|
|
33
|
+
self.message = message
|
|
34
|
+
self.developer_message = developer_message or message
|
|
35
|
+
self.context = dict(context or {})
|
|
36
|
+
self.details = list(details or [])
|
|
37
|
+
self.retry_after = retry_after
|
|
38
|
+
super().__init__(message)
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def configuration_error(
|
|
42
|
+
cls, message: str = "Service configuration is invalid."
|
|
43
|
+
) -> "APIError":
|
|
44
|
+
return build_error(cls, codes.CONFIGURATION_ERROR, message)
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def internal_error(cls) -> "APIError":
|
|
48
|
+
return build_error(cls, codes.INTERNAL_ERROR, "An unexpected error occurred.")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Validation(APIError):
|
|
52
|
+
error_type = "validation"
|
|
53
|
+
status_code = 400
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def request_validation_failed(
|
|
57
|
+
cls,
|
|
58
|
+
*,
|
|
59
|
+
message: str = "Request validation failed.",
|
|
60
|
+
details: list[dict[str, Any]] | None = None,
|
|
61
|
+
) -> "Validation":
|
|
62
|
+
return build_error(
|
|
63
|
+
cls,
|
|
64
|
+
codes.VALIDATION_ERROR,
|
|
65
|
+
message,
|
|
66
|
+
details=details or [],
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def invalid_model_key(
|
|
71
|
+
cls, *, allowed_models: list[str], message: str = "Invalid model key."
|
|
72
|
+
) -> "Validation":
|
|
73
|
+
return build_error(
|
|
74
|
+
cls,
|
|
75
|
+
codes.INVALID_MODEL_KEY,
|
|
76
|
+
message,
|
|
77
|
+
context={"allowed_models": list(allowed_models)},
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class Authorization(APIError):
|
|
82
|
+
error_type = "authorization"
|
|
83
|
+
status_code = 403
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def insufficient_permissions(cls) -> "Authorization":
|
|
87
|
+
return build_error(
|
|
88
|
+
cls,
|
|
89
|
+
codes.INSUFFICIENT_PERMISSIONS,
|
|
90
|
+
"You do not have permission to perform this action.",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class Authentication(APIError):
|
|
95
|
+
error_type = "authorization"
|
|
96
|
+
status_code = 401
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def read_context_required(
|
|
100
|
+
cls,
|
|
101
|
+
message: str = "Fervis could not capture an authenticated read context.",
|
|
102
|
+
) -> "Authentication":
|
|
103
|
+
return build_error(cls, codes.READ_CONTEXT_REQUIRED, message)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class NotFound(APIError):
|
|
107
|
+
error_type = "not_found"
|
|
108
|
+
status_code = 404
|
|
109
|
+
|
|
110
|
+
@classmethod
|
|
111
|
+
def for_resource(
|
|
112
|
+
cls,
|
|
113
|
+
resource_type: str,
|
|
114
|
+
resource_id: str | int | None = "unknown",
|
|
115
|
+
*,
|
|
116
|
+
message: str | None = None,
|
|
117
|
+
) -> "NotFound":
|
|
118
|
+
return build_error(
|
|
119
|
+
cls,
|
|
120
|
+
f"{resource_type}_not_found",
|
|
121
|
+
message or f"{resource_type.replace('_', ' ').title()} not found.",
|
|
122
|
+
developer_message=f"{resource_type} {resource_id} does not exist",
|
|
123
|
+
context={"resource_type": resource_type, "resource_id": str(resource_id)},
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class RateLimit(APIError):
|
|
128
|
+
error_type = "rate_limit"
|
|
129
|
+
status_code = 429
|
|
130
|
+
retryable = True
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def llm_api_rate_limited(
|
|
134
|
+
cls,
|
|
135
|
+
*,
|
|
136
|
+
provider: str,
|
|
137
|
+
reason: str | None = None,
|
|
138
|
+
error_class: str | None = None,
|
|
139
|
+
context: dict[str, Any] | None = None,
|
|
140
|
+
retry_after: int | None = None,
|
|
141
|
+
) -> "RateLimit":
|
|
142
|
+
return build_error(
|
|
143
|
+
cls,
|
|
144
|
+
codes.LLM_API_RATE_LIMITED,
|
|
145
|
+
"LLM provider rate limit exceeded.",
|
|
146
|
+
context=_provider_context(provider, reason, error_class, context),
|
|
147
|
+
retry_after=retry_after,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class Unavailable(APIError):
|
|
152
|
+
error_type = "system"
|
|
153
|
+
status_code = 502
|
|
154
|
+
retryable = True
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def llm_api_error(
|
|
158
|
+
cls,
|
|
159
|
+
*,
|
|
160
|
+
provider: str,
|
|
161
|
+
reason: str | None = None,
|
|
162
|
+
error_class: str | None = None,
|
|
163
|
+
context: dict[str, Any] | None = None,
|
|
164
|
+
) -> "Unavailable":
|
|
165
|
+
return cls._llm_error(
|
|
166
|
+
code=codes.LLM_API_ERROR,
|
|
167
|
+
message="LLM provider is currently unavailable.",
|
|
168
|
+
provider=provider,
|
|
169
|
+
reason=reason,
|
|
170
|
+
error_class=error_class,
|
|
171
|
+
context=context,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
@classmethod
|
|
175
|
+
def llm_api_connection_error(
|
|
176
|
+
cls,
|
|
177
|
+
*,
|
|
178
|
+
provider: str,
|
|
179
|
+
reason: str | None = None,
|
|
180
|
+
error_class: str | None = None,
|
|
181
|
+
context: dict[str, Any] | None = None,
|
|
182
|
+
) -> "Unavailable":
|
|
183
|
+
return cls._llm_error(
|
|
184
|
+
code=codes.LLM_API_CONNECTION_ERROR,
|
|
185
|
+
message="Could not connect to the LLM provider.",
|
|
186
|
+
provider=provider,
|
|
187
|
+
reason=reason,
|
|
188
|
+
error_class=error_class,
|
|
189
|
+
context=context,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
@classmethod
|
|
193
|
+
def llm_api_timeout(
|
|
194
|
+
cls,
|
|
195
|
+
*,
|
|
196
|
+
provider: str,
|
|
197
|
+
reason: str | None = None,
|
|
198
|
+
error_class: str | None = None,
|
|
199
|
+
context: dict[str, Any] | None = None,
|
|
200
|
+
) -> "Unavailable":
|
|
201
|
+
return cls._llm_error(
|
|
202
|
+
code=codes.LLM_API_TIMEOUT,
|
|
203
|
+
message="LLM provider timed out.",
|
|
204
|
+
provider=provider,
|
|
205
|
+
reason=reason,
|
|
206
|
+
error_class=error_class,
|
|
207
|
+
context=context,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
@classmethod
|
|
211
|
+
def llm_api_bad_request(
|
|
212
|
+
cls,
|
|
213
|
+
*,
|
|
214
|
+
provider: str,
|
|
215
|
+
reason: str | None = None,
|
|
216
|
+
error_class: str | None = None,
|
|
217
|
+
context: dict[str, Any] | None = None,
|
|
218
|
+
) -> "Unavailable":
|
|
219
|
+
return cls._llm_error(
|
|
220
|
+
code=codes.LLM_API_BAD_REQUEST,
|
|
221
|
+
message="LLM request was rejected by the provider.",
|
|
222
|
+
provider=provider,
|
|
223
|
+
reason=reason,
|
|
224
|
+
error_class=error_class,
|
|
225
|
+
context=context,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
@classmethod
|
|
229
|
+
def llm_api_authentication_error(
|
|
230
|
+
cls,
|
|
231
|
+
*,
|
|
232
|
+
provider: str,
|
|
233
|
+
reason: str | None = None,
|
|
234
|
+
error_class: str | None = None,
|
|
235
|
+
context: dict[str, Any] | None = None,
|
|
236
|
+
) -> "Unavailable":
|
|
237
|
+
return cls._llm_error(
|
|
238
|
+
code=codes.LLM_API_AUTHENTICATION_ERROR,
|
|
239
|
+
message="LLM provider authentication failed.",
|
|
240
|
+
provider=provider,
|
|
241
|
+
reason=reason,
|
|
242
|
+
error_class=error_class,
|
|
243
|
+
context=context,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
@classmethod
|
|
247
|
+
def llm_api_permission_error(
|
|
248
|
+
cls,
|
|
249
|
+
*,
|
|
250
|
+
provider: str,
|
|
251
|
+
reason: str | None = None,
|
|
252
|
+
error_class: str | None = None,
|
|
253
|
+
context: dict[str, Any] | None = None,
|
|
254
|
+
) -> "Unavailable":
|
|
255
|
+
return cls._llm_error(
|
|
256
|
+
code=codes.LLM_API_PERMISSION_ERROR,
|
|
257
|
+
message="LLM provider denied access to the requested resource.",
|
|
258
|
+
provider=provider,
|
|
259
|
+
reason=reason,
|
|
260
|
+
error_class=error_class,
|
|
261
|
+
context=context,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
@classmethod
|
|
265
|
+
def llm_api_not_found(
|
|
266
|
+
cls,
|
|
267
|
+
*,
|
|
268
|
+
provider: str,
|
|
269
|
+
reason: str | None = None,
|
|
270
|
+
error_class: str | None = None,
|
|
271
|
+
context: dict[str, Any] | None = None,
|
|
272
|
+
) -> "Unavailable":
|
|
273
|
+
return cls._llm_error(
|
|
274
|
+
code=codes.LLM_API_NOT_FOUND,
|
|
275
|
+
message="LLM provider resource was not found.",
|
|
276
|
+
provider=provider,
|
|
277
|
+
reason=reason,
|
|
278
|
+
error_class=error_class,
|
|
279
|
+
context=context,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
@classmethod
|
|
283
|
+
def llm_api_conflict(
|
|
284
|
+
cls,
|
|
285
|
+
*,
|
|
286
|
+
provider: str,
|
|
287
|
+
reason: str | None = None,
|
|
288
|
+
error_class: str | None = None,
|
|
289
|
+
context: dict[str, Any] | None = None,
|
|
290
|
+
) -> "Unavailable":
|
|
291
|
+
return cls._llm_error(
|
|
292
|
+
code=codes.LLM_API_CONFLICT,
|
|
293
|
+
message="LLM provider reported a request conflict.",
|
|
294
|
+
provider=provider,
|
|
295
|
+
reason=reason,
|
|
296
|
+
error_class=error_class,
|
|
297
|
+
context=context,
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
@classmethod
|
|
301
|
+
def llm_api_internal_error(
|
|
302
|
+
cls,
|
|
303
|
+
*,
|
|
304
|
+
provider: str,
|
|
305
|
+
reason: str | None = None,
|
|
306
|
+
error_class: str | None = None,
|
|
307
|
+
context: dict[str, Any] | None = None,
|
|
308
|
+
) -> "Unavailable":
|
|
309
|
+
return cls._llm_error(
|
|
310
|
+
code=codes.LLM_API_INTERNAL_ERROR,
|
|
311
|
+
message="LLM provider encountered an internal error.",
|
|
312
|
+
provider=provider,
|
|
313
|
+
reason=reason,
|
|
314
|
+
error_class=error_class,
|
|
315
|
+
context=context,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
@classmethod
|
|
319
|
+
def llm_api_response_invalid(
|
|
320
|
+
cls,
|
|
321
|
+
*,
|
|
322
|
+
provider: str,
|
|
323
|
+
reason: str | None = None,
|
|
324
|
+
error_class: str | None = None,
|
|
325
|
+
context: dict[str, Any] | None = None,
|
|
326
|
+
) -> "Unavailable":
|
|
327
|
+
return cls._llm_error(
|
|
328
|
+
code=codes.LLM_API_RESPONSE_INVALID,
|
|
329
|
+
message="LLM provider returned an invalid response payload.",
|
|
330
|
+
provider=provider,
|
|
331
|
+
reason=reason,
|
|
332
|
+
error_class=error_class,
|
|
333
|
+
context=context,
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
@classmethod
|
|
337
|
+
def _llm_error(
|
|
338
|
+
cls,
|
|
339
|
+
*,
|
|
340
|
+
code: str,
|
|
341
|
+
message: str,
|
|
342
|
+
provider: str,
|
|
343
|
+
reason: str | None = None,
|
|
344
|
+
error_class: str | None = None,
|
|
345
|
+
context: dict[str, Any] | None = None,
|
|
346
|
+
) -> "Unavailable":
|
|
347
|
+
return build_error(
|
|
348
|
+
cls,
|
|
349
|
+
code,
|
|
350
|
+
message,
|
|
351
|
+
context=_provider_context(provider, reason, error_class, context),
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def build_error(
|
|
356
|
+
exception_cls: type[APIError],
|
|
357
|
+
code: str,
|
|
358
|
+
message: str,
|
|
359
|
+
*,
|
|
360
|
+
context: dict[str, Any] | None = None,
|
|
361
|
+
developer_message: str | None = None,
|
|
362
|
+
details: list[dict[str, Any]] | None = None,
|
|
363
|
+
retry_after: int | None = None,
|
|
364
|
+
) -> APIError:
|
|
365
|
+
return exception_cls(
|
|
366
|
+
code=code,
|
|
367
|
+
message=message,
|
|
368
|
+
developer_message=developer_message,
|
|
369
|
+
context=context,
|
|
370
|
+
details=details,
|
|
371
|
+
retry_after=retry_after,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _provider_context(
|
|
376
|
+
provider: str,
|
|
377
|
+
reason: str | None,
|
|
378
|
+
error_class: str | None,
|
|
379
|
+
context: dict[str, Any] | None,
|
|
380
|
+
) -> dict[str, Any]:
|
|
381
|
+
payload = {
|
|
382
|
+
"provider": provider,
|
|
383
|
+
"reason": reason,
|
|
384
|
+
"error_class": error_class,
|
|
385
|
+
}
|
|
386
|
+
if context:
|
|
387
|
+
payload.update(context)
|
|
388
|
+
return payload
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Evaluation tooling for portable Fervis runtime checks."""
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from fervis import configured_fervis
|
|
4
|
+
from fervis.interfaces.fastapi import fervis_fastapi_router
|
|
5
|
+
from fervis.project import FastAPIIntegration
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"FastAPIIntegration",
|
|
9
|
+
"configured_fervis",
|
|
10
|
+
"fervis_fastapi_router",
|
|
11
|
+
]
|
fervis/flask/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from fervis import configured_fervis
|
|
4
|
+
from fervis.interfaces.flask import fervis_flask_blueprint
|
|
5
|
+
from fervis.project import FlaskIntegration
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"FlaskIntegration",
|
|
9
|
+
"configured_fervis",
|
|
10
|
+
"fervis_flask_blueprint",
|
|
11
|
+
]
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Django + DRF host API adapter package."""
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Django framework adapter for Fervis endpoint access."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from fervis.host_api.contracts import EndpointContract
|
|
8
|
+
from fervis.host_api.adapters.http import (
|
|
9
|
+
execute_http_read,
|
|
10
|
+
http_read_config_from_auth_schema,
|
|
11
|
+
)
|
|
12
|
+
from fervis.host_api.contracts.authority import ReadAuthority, ReadContextRef
|
|
13
|
+
from fervis.host_api.contracts.credentials import DelegatedReadCredential
|
|
14
|
+
from fervis.host_api.contracts.read import ReadInvocation
|
|
15
|
+
from fervis.host_api.credentials import (
|
|
16
|
+
credential_overlay_from_auth_schema,
|
|
17
|
+
delegated_credential_from_request,
|
|
18
|
+
)
|
|
19
|
+
from fervis.host_api.contracts.ports import (
|
|
20
|
+
EndpointExecutionError,
|
|
21
|
+
EndpointExecutionResult,
|
|
22
|
+
)
|
|
23
|
+
from fervis.lookup.relation_catalog.from_host_api import (
|
|
24
|
+
relation_catalog_from_endpoint_contracts,
|
|
25
|
+
)
|
|
26
|
+
from fervis.lookup.relation_catalog import RelationCatalog
|
|
27
|
+
from fervis.project.source_scope import DjangoSourceScope
|
|
28
|
+
|
|
29
|
+
from .catalog import get_endpoint_contracts
|
|
30
|
+
from .catalog import get_endpoint_contract
|
|
31
|
+
from .principal import capture_django_read_context, resolve_django_read_context_ref
|
|
32
|
+
from .executor import execute_get_endpoint
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class DjangoHostApiAdapter:
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
*,
|
|
39
|
+
sources: tuple[DjangoSourceScope, ...],
|
|
40
|
+
auth_schema: dict[str, object] | None = None,
|
|
41
|
+
):
|
|
42
|
+
self.sources = tuple(sources)
|
|
43
|
+
self.auth_schema = auth_schema
|
|
44
|
+
|
|
45
|
+
def describe_sources(self) -> tuple[EndpointContract, ...]:
|
|
46
|
+
return get_endpoint_contracts(sources=self.sources)
|
|
47
|
+
|
|
48
|
+
def build_relation_catalog(self) -> RelationCatalog:
|
|
49
|
+
return relation_catalog_from_endpoint_contracts(self.describe_sources())
|
|
50
|
+
|
|
51
|
+
def capture_read_context(self, request: Any) -> ReadContextRef:
|
|
52
|
+
return capture_django_read_context(request)
|
|
53
|
+
|
|
54
|
+
def capture_delegated_credential(
|
|
55
|
+
self,
|
|
56
|
+
request: Any,
|
|
57
|
+
) -> DelegatedReadCredential | None:
|
|
58
|
+
return delegated_credential_from_request(
|
|
59
|
+
schema=self.auth_schema,
|
|
60
|
+
request=request,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def execute_read(
|
|
64
|
+
self,
|
|
65
|
+
*,
|
|
66
|
+
authority: ReadAuthority,
|
|
67
|
+
invocation: ReadInvocation,
|
|
68
|
+
) -> EndpointExecutionResult:
|
|
69
|
+
http_config = http_read_config_from_auth_schema(self.auth_schema)
|
|
70
|
+
if http_config is not None:
|
|
71
|
+
contract = get_endpoint_contract(
|
|
72
|
+
invocation.endpoint_name,
|
|
73
|
+
sources=self.sources,
|
|
74
|
+
)
|
|
75
|
+
if contract is None:
|
|
76
|
+
raise EndpointExecutionError(
|
|
77
|
+
f"Unknown endpoint: {invocation.endpoint_name}"
|
|
78
|
+
)
|
|
79
|
+
return execute_http_read(
|
|
80
|
+
contract=contract,
|
|
81
|
+
authority=authority,
|
|
82
|
+
invocation=invocation,
|
|
83
|
+
config=http_config,
|
|
84
|
+
)
|
|
85
|
+
user = resolve_django_read_context_ref(authority.read_context_ref)
|
|
86
|
+
return execute_get_endpoint(
|
|
87
|
+
endpoint_name=invocation.endpoint_name,
|
|
88
|
+
user=user,
|
|
89
|
+
sources=self.sources,
|
|
90
|
+
path_params=dict(invocation.path_params),
|
|
91
|
+
query_params=dict(invocation.query_params),
|
|
92
|
+
page_policy=(
|
|
93
|
+
None if invocation.page_policy is None else dict(invocation.page_policy)
|
|
94
|
+
),
|
|
95
|
+
transport_overlay=credential_overlay_from_auth_schema(
|
|
96
|
+
schema=self.auth_schema,
|
|
97
|
+
credential=authority.delegated_credential,
|
|
98
|
+
),
|
|
99
|
+
)
|