diff --git a/README.md b/README.md
index 67f9b26e..e83857f0 100644
--- a/README.md
+++ b/README.md
@@ -203,7 +203,8 @@ cow install-browser
"agent_workspace": "~/cow", # Agent 的工作空间路径,用于存储 memory、skills、系统设定等
"agent_max_context_tokens": 50000, # Agent 模式下最大上下文 tokens,超出将自动智能压缩处理
"agent_max_context_turns": 20, # Agent 模式下最大上下文记忆轮次,一问一答为一轮,超出后智能压缩处理
- "agent_max_steps": 20 # Agent 模式下单次任务的最大决策步数,超出后将停止继续调用工具
+ "agent_max_steps": 20, # Agent 模式下单次任务的最大决策步数,超出后将停止继续调用工具
+ "enable_thinking": true # 是否启用深度思考,开启后 Web 端展示模型推理过程,关闭后可加速响应
}
```
diff --git a/agent/protocol/agent_stream.py b/agent/protocol/agent_stream.py
index 45f7d8a5..1b37fea9 100644
--- a/agent/protocol/agent_stream.py
+++ b/agent/protocol/agent_stream.py
@@ -78,6 +78,11 @@ class AgentStreamExecutor:
except Exception as e:
logger.error(f"Event callback error: {e}")
+ def _is_thinking_enabled(self) -> bool:
+ from config import conf
+ channel_type = getattr(self.model, 'channel_type', '') or ''
+ return conf().get("enable_thinking", True) and channel_type == 'web'
+
def _filter_think_tags(self, text: str) -> str:
"""
Remove
diff --git a/docs/intro/architecture.mdx b/docs/intro/architecture.mdx
index b83dd65a..2cb5a8f0 100644
--- a/docs/intro/architecture.mdx
+++ b/docs/intro/architecture.mdx
@@ -69,7 +69,8 @@ Agent 的工作空间默认位于 `~/cow` 目录,用于存储系统提示词
"agent_workspace": "~/cow",
"agent_max_context_tokens": 40000,
"agent_max_context_turns": 30,
- "agent_max_steps": 15
+ "agent_max_steps": 15,
+ "enable_thinking": true
}
```
@@ -80,4 +81,5 @@ Agent 的工作空间默认位于 `~/cow` 目录,用于存储系统提示词
| `agent_max_context_tokens` | 最大上下文 token 数 | `50000` |
| `agent_max_context_turns` | 最大上下文记忆轮次 | `20` |
| `agent_max_steps` | 单次任务最大决策步数 | `20` |
+| `enable_thinking` | 是否启用深度思考,开启后 Web 端展示推理过程,关闭可加速响应 | `true` |
| `knowledge` | 是否启用个人知识库 | `true` |
diff --git a/models/dashscope/dashscope_bot.py b/models/dashscope/dashscope_bot.py
index 4d4d628f..651ec80b 100644
--- a/models/dashscope/dashscope_bot.py
+++ b/models/dashscope/dashscope_bot.py
@@ -262,20 +262,17 @@ class DashscopeBot(Bot):
if kwargs.get("tool_choice"):
parameters["tool_choice"] = kwargs["tool_choice"]
- # Add thinking parameters for Qwen3 models (disabled by default for stability)
+ # Add thinking parameters for Qwen3/QwQ models
if "qwen3" in model_name.lower() or "qwq" in model_name.lower():
- # Only enable thinking mode if explicitly requested
- enable_thinking = kwargs.get("enable_thinking", False)
- if enable_thinking:
+ thinking = kwargs.get("thinking", {"type": "enabled"})
+ if thinking.get("type") == "enabled":
parameters["enable_thinking"] = True
-
- # Set thinking budget if specified
if kwargs.get("thinking_budget"):
parameters["thinking_budget"] = kwargs["thinking_budget"]
-
- # Qwen3 requires incremental_output=true in thinking mode
if stream:
parameters["incremental_output"] = True
+ else:
+ parameters["enable_thinking"] = False
# Always use incremental_output for streaming (for better token-by-token streaming)
# This is especially important for tool calling to avoid incomplete responses
diff --git a/models/doubao/doubao_bot.py b/models/doubao/doubao_bot.py
index b31516ec..f8ccfff7 100644
--- a/models/doubao/doubao_bot.py
+++ b/models/doubao/doubao_bot.py
@@ -249,9 +249,7 @@ class DoubaoBot(Bot):
request_body["tools"] = converted_tools
request_body["tool_choice"] = "auto"
- # Explicitly disable thinking to avoid reasoning_content issues
- # in multi-turn tool calls
- request_body["thinking"] = {"type": "disabled"}
+ request_body["thinking"] = kwargs.get("thinking", {"type": "enabled"})
logger.debug(f"[DOUBAO] API call: model={model}, "
f"tools={len(converted_tools) if converted_tools else 0}, stream={stream}")
@@ -324,8 +322,17 @@ class DoubaoBot(Bot):
choice = chunk["choices"][0]
delta = choice.get("delta", {})
- # Skip reasoning_content (thinking) - don't log or forward
if delta.get("reasoning_content"):
+ yield {
+ "choices": [{
+ "index": 0,
+ "delta": {
+ "role": "assistant",
+ "reasoning_content": delta["reasoning_content"]
+ },
+ "finish_reason": None
+ }]
+ }
continue
# Handle text content
diff --git a/models/linkai/link_ai_bot.py b/models/linkai/link_ai_bot.py
index dd91f3db..212cbbd7 100644
--- a/models/linkai/link_ai_bot.py
+++ b/models/linkai/link_ai_bot.py
@@ -560,6 +560,10 @@ def _linkai_call_with_tools(self, messages, tools=None, stream=False, **kwargs):
body["tools"] = tools
body["tool_choice"] = kwargs.get("tool_choice", "auto")
+ thinking = kwargs.get("thinking")
+ if thinking:
+ body["thinking"] = thinking
+
# Prepare headers
headers = {"Authorization": "Bearer " + conf().get("linkai_api_key")}
base_url = conf().get("linkai_api_base", "https://api.link-ai.tech")
diff --git a/models/moonshot/moonshot_bot.py b/models/moonshot/moonshot_bot.py
index 4d35400e..55698e45 100644
--- a/models/moonshot/moonshot_bot.py
+++ b/models/moonshot/moonshot_bot.py
@@ -249,10 +249,7 @@ class MoonshotBot(Bot):
request_body["tools"] = converted_tools
request_body["tool_choice"] = "auto"
- # Explicitly disable thinking to avoid reasoning_content issues in multi-turn tool calls.
- # kimi-k2.5 may enable thinking by default; without preserving reasoning_content
- # in conversation history the API will reject subsequent requests.
- request_body["thinking"] = {"type": "disabled"}
+ request_body["thinking"] = kwargs.get("thinking", {"type": "enabled"})
logger.debug(f"[MOONSHOT] API call: model={model}, "
f"tools={len(converted_tools) if converted_tools else 0}, stream={stream}")
@@ -325,8 +322,17 @@ class MoonshotBot(Bot):
choice = chunk["choices"][0]
delta = choice.get("delta", {})
- # Skip reasoning_content (thinking) – don't log or forward
if delta.get("reasoning_content"):
+ yield {
+ "choices": [{
+ "index": 0,
+ "delta": {
+ "role": "assistant",
+ "reasoning_content": delta["reasoning_content"]
+ },
+ "finish_reason": None
+ }]
+ }
continue
# Handle text content
diff --git a/run.sh b/run.sh
index 74b09665..07c0753d 100755
--- a/run.sh
+++ b/run.sh
@@ -193,6 +193,16 @@ clone_project() {
rm CowAgent.zip
else
local clone_ok=false
+ # Detect and temporarily disable invalid git proxy settings
+ local _git_proxy_unset=false
+ local _http_proxy=$(git config --global http.proxy 2>/dev/null)
+ local _https_proxy=$(git config --global https.proxy 2>/dev/null)
+ if [ -n "$_http_proxy" ] && ! curl -s --connect-timeout 3 --max-time 5 --proxy "$_http_proxy" https://github.com > /dev/null 2>&1; then
+ echo -e "${YELLOW}⚠️ Invalid git proxy detected: $_http_proxy, temporarily disabling...${NC}"
+ git config --global --unset http.proxy
+ [ -n "$_https_proxy" ] && git config --global --unset https.proxy
+ _git_proxy_unset=true
+ fi
# Test GitHub connectivity before attempting clone
if curl -sI --connect-timeout 5 --max-time 10 https://github.com > /dev/null 2>&1; then
echo -e "${YELLOW}🌐 GitHub is reachable, cloning from GitHub...${NC}"
@@ -204,6 +214,12 @@ clone_project() {
fi
if [ "$clone_ok" = false ]; then
echo -e "${RED}❌ Project clone failed. Please check network connection.${NC}"
+ if git config --global http.proxy &> /dev/null || git config --global https.proxy &> /dev/null || [ -n "$http_proxy" ] || [ -n "$https_proxy" ] || [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then
+ echo -e "${YELLOW}💡 Detected proxy settings. If proxy is misconfigured, try removing it with:${NC}"
+ echo -e "${YELLOW} git config --global --unset http.proxy${NC}"
+ echo -e "${YELLOW} git config --global --unset https.proxy${NC}"
+ echo -e "${YELLOW} unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY${NC}"
+ fi
exit 1
fi
fi