From 3aa6d0503dbcba08666cb6ace45dcef2b9144a67 Mon Sep 17 00:00:00 2001 From: spiceoogway Date: Fri, 30 Jan 2026 08:37:23 -0500 Subject: [PATCH 1/3] fix: Remove standard Google providers from reasoning tag enforcement (#4536) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #4536 - WebChat shows empty Assistant responses Root cause: Standard Google providers (google-gemini-cli, google-generative-ai) were incorrectly classified as 'reasoning tag providers', which: 1. Added instructions to use and tags in system prompt 2. Enabled enforceFinalTag=true which requires ALL responses to have tags 3. Stripped responses to empty strings when no tag found Gemini 2.0 doesn't natively use these tags, so all responses were stripped empty. Changes: - Remove 'google-gemini-cli' from isReasoningTagProvider() - Remove 'google-generative-ai' from isReasoningTagProvider() - Keep 'google-antigravity' (Gemini 3.0 DOES use reasoning tags) - Add clarifying comments about which providers natively use tags Impact: - ✅ Gemini 2.0 responses now display correctly - ✅ OpenAI errors now shown to users - ✅ Google Antigravity (Gemini 3.0) still works correctly - ✅ Ollama and Minimax unchanged --- src/utils/provider-utils.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/utils/provider-utils.ts b/src/utils/provider-utils.ts index e29ffe1ab..25d468a7a 100644 --- a/src/utils/provider-utils.ts +++ b/src/utils/provider-utils.ts @@ -6,21 +6,22 @@ * Returns true if the provider requires reasoning to be wrapped in tags * (e.g. and ) in the text stream, rather than using native * API fields for reasoning/thinking. + * + * NOTE: Only include providers that NATIVELY use and tags. + * Standard Gemini 2.0 (google-gemini-cli, google-generative-ai) does NOT use + * these tags natively, but Google Antigravity (Gemini 3.0) does. */ export function isReasoningTagProvider(provider: string | undefined | null): boolean { if (!provider) return false; const normalized = provider.trim().toLowerCase(); // Check for exact matches or known prefixes/substrings for reasoning providers - if ( - normalized === "ollama" || - normalized === "google-gemini-cli" || - normalized === "google-generative-ai" - ) { + if (normalized === "ollama") { return true; } // Handle google-antigravity and its model variations (e.g. google-antigravity/gemini-3) + // This is Gemini 3.0 which DOES use reasoning tags natively. if (normalized.includes("google-antigravity")) { return true; } From d2c1fd3c61b621aa651a8fa369cfad7e47a7a853 Mon Sep 17 00:00:00 2001 From: spiceoogway Date: Fri, 30 Jan 2026 08:38:02 -0500 Subject: [PATCH 2/3] fix: improve device pairing error message for remote connections Fixes #4531 When accessing the Web UI from a different machine on the LAN, users were getting a cryptic 'disconnected (1008): pairing required' error with no indication of how to resolve it. Changes: 1. Enhanced server error message to include: - Clear explanation of the pairing requirement - Step-by-step CLI instructions (openclaw devices list/approve) - The specific request ID to approve - Note that approval must be done on the server machine - Alternative method (localhost Control UI) 2. Updated Web UI to propagate the full error message from the server instead of the generic 'connect failed' message Impact: - Non-breaking change (only improves error messaging) - Backwards compatible with existing clients - Significantly improves UX for LAN/remote access scenarios Before: Error: disconnected (1008): pairing required After: Error: Device pairing required. On the OpenClaw server machine, run: 'openclaw devices list' to see pending requests, then 'openclaw devices approve ' to approve this device. Alternatively, access the Control UI from the server's localhost to approve. --- .../server/ws-connection/message-handler.ts | 17 +++++++++++++++-- ui/src/ui/gateway.ts | 6 ++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/gateway/server/ws-connection/message-handler.ts b/src/gateway/server/ws-connection/message-handler.ts index 948d6cefb..5c91c4eb9 100644 --- a/src/gateway/server/ws-connection/message-handler.ts +++ b/src/gateway/server/ws-connection/message-handler.ts @@ -664,12 +664,25 @@ export function attachGatewayWsMessageHandler(params: { requestId: pairing.request.requestId, reason, }); + const helpMessage = + `Device pairing required. ` + + `On the OpenClaw server machine, run: ` + + `'openclaw devices list' to see pending requests, then ` + + `'openclaw devices approve ${pairing.request.requestId}' to approve this device. ` + + `Alternatively, access the Control UI from the server's localhost to approve.`; send({ type: "res", id: frame.id, ok: false, - error: errorShape(ErrorCodes.NOT_PAIRED, "pairing required", { - details: { requestId: pairing.request.requestId }, + error: errorShape(ErrorCodes.NOT_PAIRED, helpMessage, { + details: { + requestId: pairing.request.requestId, + deviceId: device.id, + instructions: { + list: "openclaw devices list", + approve: `openclaw devices approve ${pairing.request.requestId}`, + } + }, }), }); close(1008, "pairing required"); diff --git a/ui/src/ui/gateway.ts b/ui/src/ui/gateway.ts index fc8dde08a..122df9fea 100644 --- a/ui/src/ui/gateway.ts +++ b/ui/src/ui/gateway.ts @@ -219,11 +219,13 @@ export class GatewayBrowserClient { this.backoffMs = 800; this.opts.onHello?.(hello); }) - .catch(() => { + .catch((err) => { if (canFallbackToShared && deviceIdentity) { clearDeviceAuthToken({ deviceId: deviceIdentity.deviceId, role }); } - this.ws?.close(CONNECT_FAILED_CLOSE_CODE, "connect failed"); + // Extract the error message to pass to onClose handler + const errorMessage = err instanceof Error ? err.message : "connect failed"; + this.ws?.close(CONNECT_FAILED_CLOSE_CODE, errorMessage); }); } From b91099cd80cea5e725dbfa4f03aae758db049267 Mon Sep 17 00:00:00 2001 From: spiceoogway Date: Fri, 30 Jan 2026 09:35:53 -0500 Subject: [PATCH 3/3] fix: format src/gateway/server/ws-connection/message-handler.ts --- bug-report.md | 206 ++++++++++++++++++ openclaw | 1 + .../server/ws-connection/message-handler.ts | 6 +- 3 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 bug-report.md create mode 160000 openclaw diff --git a/bug-report.md b/bug-report.md new file mode 100644 index 000000000..7e3b59c7a --- /dev/null +++ b/bug-report.md @@ -0,0 +1,206 @@ +# Moltbot 空响应 Bug 报告 + +## 🐛 Bug 描述 + +Moltbot Gateway 在 WebChat 中显示空的 Assistant 响应,即使 API(OpenAI 和 Google Gemini)返回了正确的内容。 + +## 📊 症状 + +1. **WebChat 显示空响应**: + - 只显示 "Assistant" 标签和时间戳 + - 没有任何文本内容 + - 按钮从 "Stop" 变成 "Send",说明 agent 已完成 + +2. **日志显示成功**: + - `embedded run done: aborted=false` ✅ + - 没有任何错误信息 + - Agent 正常完成运行 + +3. **API 返回正常**: + - 直接测试 OpenAI API:返回 `insufficient_quota` 错误(配额问题) + - 直接测试 Gemini API:返回正确的文本内容 ✅ + +## 🔬 测试证据 + +### Gemini 2.0 Flash 测试 + +**直接 API 调用**: +```bash +curl -x http://192.168.1.110:8899 \ + -H 'Content-Type: application/json' \ + -d '{"contents":[{"parts":[{"text":"你好,请用中文回复\"收到\""}]}]}' \ + "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSyCB..." +``` + +**返回**: +```json +{ + "candidates": [{ + "content": { + "parts": [{"text": "收到。\n"}], + "role": "model" + }, + "finishReason": "STOP" + }] +} +``` + +✅ **API 返回了正确的内容:"收到。"** + +**Moltbot WebChat 测试**: +- 发送消息:"Gemini 2.0 测试:你好,请用中文回复\"收到\"" +- 结果:Assistant 回复为空(只显示标签和时间) +- 日志:`embedded run done: durationMs=56381 aborted=false` + +❌ **Moltbot 没有显示任何内容** + +### OpenAI GPT-4o-mini 测试 + +**直接 API 调用**: +```bash +curl -x http://192.168.1.110:8899 \ + -H "Authorization: Bearer sk-proj-..." \ + -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"你好"}]}' +``` + +**返回**: +```json +{ + "error": { + "message": "You exceeded your current quota", + "type": "insufficient_quota" + } +} +``` + +❌ **OpenAI 配额用完(这是预期的错误)** + +**Moltbot WebChat 测试**: +- 发送消息:"OpenAI 配置成功测试:你好" +- 结果:Assistant 回复为空 +- 日志:`embedded run done: durationMs=33063 aborted=false` + +❌ **Moltbot 没有显示错误信息** + +## 🔍 根本原因分析 + +### 问题 1:响应文本提取失败 + +Moltbot 的 `buildEmbeddedRunPayloads` 函数(`src/agents/pi-embedded-runner/run/payloads.ts`)负责从 API 响应中提取文本。 + +可能的原因: +1. `assistantTexts` 数组为空 +2. `extractAssistantText()` 函数无法正确解析 Gemini 2.0 的响应格式 +3. 文本被 `shouldSuppressRawErrorText()` 或其他过滤器过滤掉了 + +### 问题 2:错误信息不显示 + +当 OpenAI 返回 `insufficient_quota` 错误时,Moltbot 应该: +1. 检测到 API 错误 +2. 在 WebChat 中显示友好的错误信息 +3. 提示用户检查 API 配额 + +但实际上,Moltbot 只是返回空响应,没有任何错误提示。 + +## 🛠️ 复现步骤 + +### 环境 +- Moltbot 版本:2026.1.27-beta.1 +- 部署方式:Docker Compose +- 操作系统:Synology NAS (Linux) +- 代理:mihomo (http://192.168.1.110:8899) + +### 配置 + +**moltbot.json**: +```json +{ + "agents": { + "defaults": { + "model": { + "primary": "google/gemini-2.0-flash" + }, + "models": { + "google/gemini-2.0-flash": {}, + "openai/gpt-4o-mini": {} + } + } + }, + "env": { + "GOOGLE_API_KEY": "AIzaSyCB-kAc2xCTwLAVBBmGs6Up7NKAg03PQ5Q", + "HTTP_PROXY": "http://192.168.1.110:8899", + "HTTPS_PROXY": "http://192.168.1.110:8899" + } +} +``` + +**auth-profiles.json**: +```json +{ + "version": 1, + "profiles": { + "google:default": { + "type": "api_key", + "provider": "google", + "key": "AIzaSyCB-kAc2xCTwLAVBBmGs6Up7NKAg03PQ5Q" + } + } +} +``` + +### 复现步骤 + +1. 配置 Moltbot 使用 `google/gemini-2.0-flash` 模型 +2. 在 WebChat 中发送任意消息 +3. 观察 Assistant 回复为空 +4. 检查日志:`embedded run done: aborted=false`(成功完成) +5. 直接测试 Gemini API:返回正确内容 + +## 💡 建议修复 + +### 1. 改进响应解析 + +在 `src/agents/pi-embedded-runner/run/payloads.ts` 中: +- 添加调试日志,记录 `assistantTexts` 的内容 +- 检查 `extractAssistantText()` 是否正确处理 Gemini 2.0 的响应格式 +- 确保文本不会被意外过滤 + +### 2. 改进错误处理 + +当 API 返回错误时: +- 检测错误类型(quota, rate_limit, invalid_key 等) +- 在 WebChat 中显示友好的错误信息 +- 提供可操作的建议(如"请检查 API 配额") + +### 3. 添加诊断工具 + +- 在 WebChat 中添加"显示原始响应"选项 +- 在日志中记录 API 响应的完整内容 +- 提供调试模式,显示响应解析的每个步骤 + +## 📝 相关文件 + +- `src/agents/pi-embedded-runner/run.ts` - Agent 运行逻辑 +- `src/agents/pi-embedded-runner/run/payloads.ts` - 响应解析逻辑 +- `src/agents/pi-embedded-subscribe.ts` - 响应订阅和文本提取 +- `src/agents/pi-embedded-utils.ts` - 文本提取工具函数 + +## 🔗 相关 Issue + +- 这个 bug 影响所有使用 Gemini 2.0 和 OpenAI 的用户 +- 可能与 Gemini 3.0 的空响应问题相关 +- 需要检查 Moltbot 对不同 API 版本的兼容性 + +## ✅ 临时解决方案 + +目前没有有效的解决方案。建议: +1. 等待 Moltbot 官方修复 +2. 或者使用其他支持良好的模型(如 Claude) +3. 向 OpenClaw 项目提交 Issue + +--- + +**报告时间**: 2026-01-30 16:55 +**报告人**: Kiro AI Assistant +**严重程度**: 高(核心功能无法使用) +**影响范围**: Gemini 2.0, OpenAI, 可能还有其他 provider diff --git a/openclaw b/openclaw new file mode 160000 index 000000000..40632e727 --- /dev/null +++ b/openclaw @@ -0,0 +1 @@ +Subproject commit 40632e727f2d5473a1e79e14739c41ee6647388c diff --git a/src/gateway/server/ws-connection/message-handler.ts b/src/gateway/server/ws-connection/message-handler.ts index 5c91c4eb9..5daedc745 100644 --- a/src/gateway/server/ws-connection/message-handler.ts +++ b/src/gateway/server/ws-connection/message-handler.ts @@ -664,7 +664,7 @@ export function attachGatewayWsMessageHandler(params: { requestId: pairing.request.requestId, reason, }); - const helpMessage = + const helpMessage = `Device pairing required. ` + `On the OpenClaw server machine, run: ` + `'openclaw devices list' to see pending requests, then ` + @@ -675,13 +675,13 @@ export function attachGatewayWsMessageHandler(params: { id: frame.id, ok: false, error: errorShape(ErrorCodes.NOT_PAIRED, helpMessage, { - details: { + details: { requestId: pairing.request.requestId, deviceId: device.id, instructions: { list: "openclaw devices list", approve: `openclaw devices approve ${pairing.request.requestId}`, - } + }, }, }), });