"""Input validation, shared by the UI and the public API.""" from __future__ import annotations import models from steering.scenarios import BY_ID, ScenarioSpec #: Generous enough for a sentence, small enough that one run stays inside a single GPU allocation. MAX_PROMPT_CHARS = 300 MAX_PREFIX_CHARS = 100 def collapse(text: str | None) -> str: """Whitespace collapsed to single spaces, the way the model will see the text.""" return " ".join(str(text or "").split()).strip() def clean(model: str | None, scenario: str | None, prompt: str | None, prefix: str | None ) -> tuple[models.ModelSpec, ScenarioSpec, str, str]: """Validated (model, scenario, prompt, opening words). Empty text falls back to the scenario's.""" spec = BY_ID.get((scenario or "").strip()) if spec is None: raise ValueError(f"Unknown scenario {scenario!r}. Known: {', '.join(sorted(BY_ID))}.") prompt = collapse(prompt) or spec.prompt prefix = collapse(prefix) or spec.prefix if len(prompt) > MAX_PROMPT_CHARS: raise ValueError(f"The prompt is longer than {MAX_PROMPT_CHARS} characters.") if len(prefix) > MAX_PREFIX_CHARS: raise ValueError(f"The opening words are longer than {MAX_PREFIX_CHARS} characters.") return models.resolve(model), spec, prompt, prefix