fix: address PR #163 review findings

- Fix model selection regression: _get_settings_defaults() now checks
  api_model (set by new provider UI) before falling back to legacy
  model setting, ensuring Claude model selection works end-to-end
- Add input validation for provider settings: api_base_url must start
  with http:// or https:// (max 500 chars), api_auth_token max 500
  chars, api_model max 200 chars
- Fix terminal.py misleading import alias: replace
  is_valid_project_name aliased as validate_project_name with direct
  is_valid_project_name import across all 5 call sites

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Auto
2026-02-06 08:10:18 +02:00
parent d15fd37e33
commit 73d6cfcd36
3 changed files with 19 additions and 10 deletions

View File

@@ -32,7 +32,7 @@ def _get_settings_defaults() -> tuple[bool, str, int, bool, int]:
settings = get_all_settings()
yolo_mode = (settings.get("yolo_mode") or "false").lower() == "true"
model = settings.get("model", DEFAULT_MODEL)
model = settings.get("api_model") or settings.get("model", DEFAULT_MODEL)
# Parse testing agent settings with defaults
try:

View File

@@ -26,7 +26,7 @@ from ..services.terminal_manager import (
stop_terminal_session,
)
from ..utils.project_helpers import get_project_path as _get_project_path
from ..utils.validation import is_valid_project_name as validate_project_name
from ..utils.validation import is_valid_project_name
logger = logging.getLogger(__name__)
@@ -89,7 +89,7 @@ async def list_project_terminals(project_name: str) -> list[TerminalInfoResponse
Returns:
List of terminal info objects
"""
if not validate_project_name(project_name):
if not is_valid_project_name(project_name):
raise HTTPException(status_code=400, detail="Invalid project name")
project_dir = _get_project_path(project_name)
@@ -122,7 +122,7 @@ async def create_project_terminal(
Returns:
The created terminal info
"""
if not validate_project_name(project_name):
if not is_valid_project_name(project_name):
raise HTTPException(status_code=400, detail="Invalid project name")
project_dir = _get_project_path(project_name)
@@ -148,7 +148,7 @@ async def rename_project_terminal(
Returns:
The updated terminal info
"""
if not validate_project_name(project_name):
if not is_valid_project_name(project_name):
raise HTTPException(status_code=400, detail="Invalid project name")
if not validate_terminal_id(terminal_id):
@@ -180,7 +180,7 @@ async def delete_project_terminal(project_name: str, terminal_id: str) -> dict:
Returns:
Success message
"""
if not validate_project_name(project_name):
if not is_valid_project_name(project_name):
raise HTTPException(status_code=400, detail="Invalid project name")
if not validate_terminal_id(terminal_id):
@@ -225,7 +225,7 @@ async def terminal_websocket(websocket: WebSocket, project_name: str, terminal_i
await websocket.accept()
# Validate project name
if not validate_project_name(project_name):
if not is_valid_project_name(project_name):
await websocket.send_json({"type": "error", "message": "Invalid project name"})
await websocket.close(
code=TerminalCloseCode.INVALID_PROJECT_NAME, reason="Invalid project name"

View File

@@ -436,9 +436,18 @@ class SettingsUpdate(BaseModel):
playwright_headless: bool | None = None
batch_size: int | None = None # Features per agent batch (1-3)
api_provider: str | None = None
api_base_url: str | None = None
api_auth_token: str | None = None # Write-only, never returned
api_model: str | None = None
api_base_url: str | None = Field(None, max_length=500)
api_auth_token: str | None = Field(None, max_length=500) # Write-only, never returned
api_model: str | None = Field(None, max_length=200)
@field_validator('api_base_url')
@classmethod
def validate_api_base_url(cls, v: str | None) -> str | None:
if v is not None and v.strip():
v = v.strip()
if not v.startswith(("http://", "https://")):
raise ValueError("api_base_url must start with http:// or https://")
return v
@field_validator('model')
@classmethod