* fix#692: decouple agent and analysis primary model selection
* fix#692: preserve yaml alias for agent primary model
* docs #692: sync agent primary model in EN/CHT readmes
* feat(llm): multi-channel LLM config with WebUI editor, protocol/model normalization, and connectivity test
- Add env-based multi-channel LLM configuration (LLM_CHANNELS, per-channel
PROTOCOL/BASE_URL/API_KEY/MODELS/ENABLED) with automatic protocol inference
and model name normalization for LiteLLM Router
- Add full-featured LLM Channel Editor in WebUI with inline channel
management, model selection, temperature control, and one-click
connectivity testing per channel
- Add POST /api/v1/system-config/test-llm-channel endpoint for real-time
LLM channel validation with latency reporting
- Add comprehensive validation for channel definitions, model references,
and runtime selection in SystemConfigService
- Add unified LLM_TEMPERATURE with backward-compatible fallback to legacy
provider-specific temperature vars (GEMINI/OPENAI/ANTHROPIC_TEMPERATURE)
- Default localhost channels to openai protocol (not ollama) for
compatibility with vLLM/LM Studio/LocalAI; Ollama requires explicit
PROTOCOL=ollama
- Allow direct-env LiteLLM providers (groq/*, bedrock/*, etc.) to bypass
channel-only model validation on both backend and frontend
- Skip channel validation when LITELLM_CONFIG YAML is the active model source
- Normalize slash-prefixed model IDs (e.g. Qwen/Qwen3-8B on SiliconFlow)
consistently between frontend and backend
- Prevent WebUI from resetting unsaved channel edits when unrelated AI
settings in the same category are modified
- Protect against invalid temperature env values with try/except fallback
- Add regression tests for channel parsing, temperature fallback, protocol
inference, YAML priority, and direct-env provider passthrough
Refs #544, Refs #507
* fix: resolve CI test failures and address PR review feedback
- Fix 3 failing validate_structured tests by aligning litellm_model with model lists
- Add direct-env provider bypass for primary and fallback model validation
- Add ValueError/TypeError -> 422 handling in test-llm-channel endpoint
- Add Space key preventDefault for accessible channel header toggle
- Canonicalize alias prefixes in normalizeModelForRuntime to prevent double-prefixing
* fix(ui): align temperature resolver and API_KEYS priority with backend
- Replace hard-coded temperature fallback chain with resolveTemperatureFromItems()
that mirrors backend resolve_unified_llm_temperature: reads LLM_TEMPERATURE first,
then the active model's provider-specific env, then any legacy *_TEMPERATURE
- Swap LLM_{NAME}_API_KEYS / LLM_{NAME}_API_KEY hydration order so multi-key
configs (rotation/load-balancing) are not silently dropped on save
* fix(security): SSRF guard on base_url + validate parsed API key segments
- Add _is_safe_base_url() to block link-local/cloud metadata addresses
(169.254.0.0/16, metadata.google.internal, 100.100.100.200) while
preserving legitimate localhost/LAN endpoints like Ollama
- Apply ssrf_blocked validation error in _validate_llm_channel_definition
- Replace api_key_value truthy-string check with parsed-segment check so
',' / ' , ' inputs are caught as missing_api_key instead of silently
producing zero-key channels at runtime
- Add regression tests: rejects_comma_only_api_key (3 subtests),
rejects_ssrf_metadata_base_url (3 subtests), allows_localhost_base_url
* fix: direct-env models bypass Router when channel mode is active
In channel/YAML mode, Router.completion() is called for all models but
the Router model_list only contains channel/YAML-declared entries. Direct-
env providers (groq/, bedrock/, etc.) are never added to it, so they caused
'model not found' errors at inference time even though validate_structured()
correctly exempted them from membership checks.
Fix: before dispatching to the Router, check whether the model is actually
in the Router model_list (via get_configured_llm_models). Models absent from
the list fall through to litellm.completion() with env-based credentials,
matching the existing legacy-path behavior. Applied consistently in both
src/analyzer.py and src/agent/llm_adapter.py.
* fix: add missing get_configured_llm_models import in analyzer.py
* feat: complete PR2 config and system API work
* fix(api): align agent model source detection
* fix(agent): collapse legacy fallback deployments
* fix: expose direct env providers in agent model discovery
---------
Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>