feat(litellm): 添加 reasoning_content 支持并强制禁用思考模式

- 在 LiteLLMProvider 中添加 "reasoning_content" 到允许的消息键集合中
- 修改 _apply_thinking_mode 方法以强制禁用思考模式,不再基于模型名称判断
- 总是设置 enable_thinking 为 False 并添加 thinking.type: disabled 配置
- 更新相关测试用例验证新的思考模式行为

fix(web): 修复非运行状态下的直接处理逻辑

- 创建 _run_web_direct 辅助函数来处理代理服务的直接提交/处理逻辑
- 当代理服务未运行时使用 process_direct 而不是 submit_direct
- 更新 REST 和 WebSocket 接口以使用新的处理逻辑
- 添加相应的单元测试验证非运行状态下使用直接处理

test(config): 添加代理配置重载功能的测试

- 添加 test_reload_agent_config_updates_booted_loop_config 测试函数
- 验证配置文件更新后代理循环能够正确加载新配置
- 测试模型、API 基础地址和 API 密钥的更新

chore(frontend): 默认禁用前端思考模式偏好

- 将前端思考模式存储的默认值从 true 改为 false
- 确保窗口未定义时返回 false 而不是 true
- 更新本地存储缺失时的默认行为为禁用思考模式
This commit is contained in:
2026-05-22 17:43:21 +08:00
parent c671b66043
commit 030bce8a60
6 changed files with 193 additions and 14 deletions

View File

@ -23,7 +23,7 @@ except ModuleNotFoundError: # pragma: no cover
litellm = None # type: ignore[assignment]
acompletion = None # type: ignore[assignment]
_ALLOWED_MSG_KEYS = frozenset({"role", "content", "tool_calls", "tool_call_id", "name"})
_ALLOWED_MSG_KEYS = frozenset({"role", "content", "tool_calls", "tool_call_id", "name", "reasoning_content"})
class LiteLLMProvider(LLMProvider):
@ -175,15 +175,11 @@ class LiteLLMProvider(LLMProvider):
kwargs["provider"] = provider_payload
def _apply_thinking_mode(self, original_model: str, resolved_model: str, kwargs: dict[str, Any], enabled: bool | None) -> None:
if enabled is None:
return
model_key = f"{original_model} {resolved_model}".lower()
if "qwen" not in model_key:
return
extra_body = dict(kwargs.get("extra_body") or {})
chat_template_kwargs = dict(extra_body.get("chat_template_kwargs") or {})
chat_template_kwargs["enable_thinking"] = bool(enabled)
chat_template_kwargs["enable_thinking"] = False
extra_body["chat_template_kwargs"] = chat_template_kwargs
extra_body["thinking"] = {"type": "disabled"}
kwargs["extra_body"] = extra_body
async def chat(

View File

@ -1745,7 +1745,7 @@ def create_app(
}
if payload.thinking_enabled is not None:
direct_kwargs["thinking_enabled"] = payload.thinking_enabled
result = await agent_service.submit_direct(message, **direct_kwargs)
result = await _run_web_direct(agent_service, message, **direct_kwargs)
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except RuntimeError as exc:
@ -1855,7 +1855,7 @@ def create_app(
websocket_thinking_enabled = _bool_or_none(payload.get("thinking_enabled"))
if websocket_thinking_enabled is not None:
direct_kwargs["thinking_enabled"] = websocket_thinking_enabled
result = await agent_service.submit_direct(content, **direct_kwargs)
result = await _run_web_direct(agent_service, content, **direct_kwargs)
except Exception as exc:
await websocket.send_json(
{
@ -1940,6 +1940,12 @@ def _session_detail(session_manager: Any, session_id: str, session: dict[str, An
}
async def _run_web_direct(agent_service: AgentService, message: str, **kwargs: Any) -> Any:
if agent_service.is_running:
return await agent_service.submit_direct(message, **kwargs)
return await agent_service.process_direct(message, **kwargs)
def _create_skill_upload_draft(loaded: Any, filename: str, content: bytes) -> dict[str, Any]:
try:
archive = zipfile.ZipFile(io.BytesIO(content), "r")