Spaces:
Sleeping
Sleeping
| """Server-owned runtime policy for hosted SAGE runs. | |
| The local service historically accepted the complete :class:`RunRequest` | |
| surface so developers could select providers, stages, artifacts, and tuning | |
| parameters from scripts. Hosted callers must not have that authority. This | |
| module provides an opt-in boundary that replaces every operational field with | |
| server environment configuration while retaining only the cohort text and the | |
| internal human-confirmation choice. | |
| """ | |
| from __future__ import annotations | |
| import os | |
| from pydantic import BaseModel, Field | |
| from .models import RunRequest | |
| LOCK_RUNTIME_CONFIG_ENV = "SAGE_LOCK_RUNTIME_CONFIG" | |
| HOSTED_MODE_ENV = "SAGE_HOSTED_MODE" | |
| _TRUE_VALUES = frozenset({"1", "true", "yes", "on"}) | |
| def env_flag(name: str) -> bool: | |
| """Return whether an opt-in environment flag is explicitly enabled.""" | |
| return str(os.getenv(name) or "").strip().casefold() in _TRUE_VALUES | |
| def hosted_mode_enabled() -> bool: | |
| """Whether the backend is running without its legacy local HTML surface.""" | |
| return env_flag(HOSTED_MODE_ENV) | |
| def runtime_config_locked() -> bool: | |
| """Whether request-controlled operational configuration is disabled. | |
| Hosted mode implies the lock so a deployment cannot hide the legacy UI | |
| while accidentally leaving its model/path controls available through the | |
| raw API. The dedicated flag also permits locked local proxy testing. | |
| """ | |
| return hosted_mode_enabled() or env_flag(LOCK_RUNTIME_CONFIG_ENV) | |
| class LockedRuntimeConfig(BaseModel): | |
| """Validated non-secret policy values read only from the backend env.""" | |
| max_llm_calls: int = Field(default=1000, ge=1, le=5000) | |
| temperature: float = Field(default=0.0, ge=0.0, le=2.0) | |
| llm_max_retries: int = Field(default=2, ge=0, le=10) | |
| timeout_seconds: float = Field(default=90.0, ge=1.0, le=600.0) | |
| stage2_top_k: int = Field(default=10, ge=1, le=100) | |
| stage2_mode: str = "adopt_suggestions" | |
| stage2_llm_verify_results: bool = False | |
| stage2_llm_filter_noise: bool = False | |
| stage2_llm_retry_limit: int = Field(default=1, ge=0, le=5) | |
| def from_environment(cls) -> "LockedRuntimeConfig": | |
| mapping = { | |
| "max_llm_calls": "SAGE_MAX_LLM_CALLS", | |
| "temperature": "SAGE_LLM_TEMPERATURE", | |
| "llm_max_retries": "SAGE_LLM_MAX_RETRIES", | |
| "timeout_seconds": "SAGE_LLM_TIMEOUT", | |
| "stage2_top_k": "SAGE_STAGE2_TOP_K", | |
| "stage2_mode": "SAGE_STAGE2_MODE", | |
| "stage2_llm_verify_results": "SAGE_STAGE2_LLM_VERIFY_RESULTS", | |
| "stage2_llm_filter_noise": "SAGE_STAGE2_LLM_FILTER_NOISE", | |
| "stage2_llm_retry_limit": "SAGE_STAGE2_LLM_RETRY_LIMIT", | |
| } | |
| values = { | |
| field_name: os.environ[environment_name] | |
| for field_name, environment_name in mapping.items() | |
| if environment_name in os.environ and os.environ[environment_name].strip() | |
| } | |
| return cls.model_validate(values) | |
| def apply_runtime_config_policy(request: RunRequest) -> RunRequest: | |
| """Return a server-owned request when the hosted runtime lock is enabled. | |
| Provider, model, response-format, endpoint, and credential selection remain | |
| in their existing provider-specific environment variables. Setting their | |
| request fields to ``None`` makes the provider factory consult only that | |
| backend configuration and prevents a raw client from overriding it. | |
| """ | |
| if not runtime_config_locked(): | |
| return request | |
| configured = LockedRuntimeConfig.from_environment() | |
| updates = { | |
| # Hosted runs are always end-to-end from inline text. HITL is the one | |
| # safe workflow choice retained for the internal frontend. | |
| "input_path": None, | |
| "case_id": None, | |
| "run_id": None, | |
| "start_stage": 1, | |
| "end_stage": 2 if request.require_human_confirmation else 3, | |
| "ir_json_path": None, | |
| "retrieval_context_path": None, | |
| # Do not load a repository .env file in a container. Provider/model | |
| # values and secrets come from the process environment only. | |
| "llm_dotenv_path": None, | |
| "llm_provider": None, | |
| "llm_model": None, | |
| "llm_response_format": None, | |
| "max_llm_calls": configured.max_llm_calls, | |
| "temperature": configured.temperature, | |
| "llm_max_retries": configured.llm_max_retries, | |
| "timeout_seconds": configured.timeout_seconds, | |
| "stage2_top_k": configured.stage2_top_k, | |
| "stage2_mode": configured.stage2_mode, | |
| "stage2_llm_verify_results": configured.stage2_llm_verify_results, | |
| "stage2_llm_filter_noise": configured.stage2_llm_filter_noise, | |
| "stage2_llm_retry_limit": configured.stage2_llm_retry_limit, | |
| } | |
| return RunRequest.model_validate({**request.model_dump(mode="python"), **updates}) | |