|
| 1 | +# oho add 命令超时问题分析报告 |
| 2 | + |
| 3 | +**分析时间**: 2026-03-24 10:30 (CST) |
| 4 | +**分析人**: nanobot 🐈 |
| 5 | + |
| 6 | +--- |
| 7 | + |
| 8 | +## 🔍 问题现象 |
| 9 | + |
| 10 | +用户反馈使用 `oho add` 命令时会超时。 |
| 11 | + |
| 12 | +--- |
| 13 | + |
| 14 | +## 📋 分析结果 |
| 15 | + |
| 16 | +### 1. 代码实现分析 |
| 17 | + |
| 18 | +#### add.go 执行流程 |
| 19 | + |
| 20 | +```go |
| 21 | +func runAdd(cmd *cobra.Command, args []string) error { |
| 22 | + // Step 1: 获取当前工作目录 |
| 23 | + sessionDir := addDirectory |
| 24 | + if sessionDir == "" { |
| 25 | + sessionDir, _ = os.Getwd() |
| 26 | + } |
| 27 | + |
| 28 | + // Step 2: 生成标题 |
| 29 | + sessionTitle := addTitle |
| 30 | + if sessionTitle == "" { |
| 31 | + sessionTitle = fmt.Sprintf("New session - %s", time.Now().Format("2006-01-02T15:04:05")) |
| 32 | + } |
| 33 | + |
| 34 | + // Step 3: 创建会话 ✅ (快速,通常 < 1 秒) |
| 35 | + sessionID, err := createSession(c, ctx, sessionTitle, addParent, sessionDir) |
| 36 | + |
| 37 | + // Step 4: 发送消息 ⚠️ (可能超时) |
| 38 | + messageID, err := sendMessage(c, ctx, sessionID, message, addAgent, addModel, addNoReply, ...) |
| 39 | + |
| 40 | + // Step 5: 输出结果 |
| 41 | + ... |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +#### sendMessage 函数 |
| 46 | + |
| 47 | +```go |
| 48 | +func sendMessage(...) (string, error) { |
| 49 | + // 构建消息请求 |
| 50 | + msgReq := types.MessageRequest{ |
| 51 | + Model: convertModel(model), |
| 52 | + Agent: agent, |
| 53 | + NoReply: noReply, // ⚠️ 关键:默认 false,会等待 AI 响应 |
| 54 | + System: system, |
| 55 | + Tools: tools, |
| 56 | + Parts: parts, |
| 57 | + } |
| 58 | + |
| 59 | + // 发送 POST 请求 |
| 60 | + resp, err := c.Post(ctx, fmt.Sprintf("/session/%s/message", sessionID), msgReq) |
| 61 | + // ⚠️ 这里会等待 AI 响应,可能耗时很长 |
| 62 | + ... |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +#### client.go 超时配置 |
| 67 | + |
| 68 | +```go |
| 69 | +func NewClient() *Client { |
| 70 | + timeoutSec := 300 // 5 分钟 |
| 71 | + if envTimeout := os.Getenv("OPENCODE_CLIENT_TIMEOUT"); envTimeout != "" { |
| 72 | + if parsed, err := strconv.Atoi(envTimeout); err == nil && parsed > 0 { |
| 73 | + timeoutSec = parsed |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + return &Client{ |
| 78 | + httpClient: &http.Client{ |
| 79 | + Timeout: time.Duration(timeoutSec) * time.Second, |
| 80 | + }, |
| 81 | + } |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +## 🐛 问题根源 |
| 88 | + |
| 89 | +### 问题 1: 默认等待 AI 响应 |
| 90 | + |
| 91 | +**代码位置**: `add.go:sendMessage()` |
| 92 | + |
| 93 | +```go |
| 94 | +NoReply: noReply, // 默认值:false |
| 95 | +``` |
| 96 | + |
| 97 | +**问题**: |
| 98 | +- `addNoReply` 默认值为 `false` |
| 99 | +- 这意味着 `oho add` 默认会**等待 AI 响应后才返回** |
| 100 | +- 对于复杂的 AI 任务(分析代码、重构等),5 分钟可能不够 |
| 101 | + |
| 102 | +**对比 `oho message add`**: |
| 103 | +```bash |
| 104 | +# oho message add 也需要 --no-reply 才不等待 |
| 105 | +oho message add -s <session> "任务" # 等待响应 |
| 106 | +oho message add -s <session> "任务" --no-reply # 不等待 |
| 107 | +``` |
| 108 | + |
| 109 | +--- |
| 110 | + |
| 111 | +### 问题 2: 文档未说明超时配置 |
| 112 | + |
| 113 | +**文档位置**: `README.md`, `oho/README.md` |
| 114 | + |
| 115 | +**缺失内容**: |
| 116 | +1. ❌ 未说明 `add` 命令默认会等待 AI 响应 |
| 117 | +2. ❌ 未说明超时时间为 5 分钟 |
| 118 | +3. ❌ 未说明如何通过环境变量调整超时 |
| 119 | +4. ❌ 未建议使用 `--no-reply` 避免超时 |
| 120 | + |
| 121 | +**现有文档**: |
| 122 | +```markdown |
| 123 | +### Quick Start (Session + Message) |
| 124 | + |
| 125 | +```bash |
| 126 | +oho add "帮我分析这个项目" # Create session and send message |
| 127 | +oho add "修复登录 bug" --title "Bug 修复" # Create session with custom title |
| 128 | +oho add "测试功能" --no-reply --agent default # Don't wait for AI response |
| 129 | +``` |
| 130 | +``` |
| 131 | + |
| 132 | +**问题**: 虽然示例中有 `--no-reply`,但**没有解释为什么需要这个参数**。 |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +### 问题 3: 超时错误提示不友好 |
| 137 | + |
| 138 | +**代码位置**: `client.go:Request()` |
| 139 | + |
| 140 | +```go |
| 141 | +resp, err := c.httpClient.Do(req) |
| 142 | +if err != nil { |
| 143 | + return nil, fmt.Errorf("请求失败:%w", err) |
| 144 | +} |
| 145 | +``` |
| 146 | + |
| 147 | +**问题**: |
| 148 | +- 超时错误只显示 "请求失败:context deadline exceeded" |
| 149 | +- 用户不知道可以调整超时时间 |
| 150 | +- 没有建议解决方案 |
| 151 | + |
| 152 | +--- |
| 153 | + |
| 154 | +## ✅ 解决方案 |
| 155 | + |
| 156 | +### 方案 1: 修改文档(推荐,立即生效) |
| 157 | + |
| 158 | +**修改文件**: `oho/README.md`, `README_zh.md` |
| 159 | + |
| 160 | +**添加内容**: |
| 161 | + |
| 162 | +```markdown |
| 163 | +### ⚠️ 超时注意事项 |
| 164 | + |
| 165 | +`oho add` 命令默认会等待 AI 响应后返回。对于复杂任务,AI 可能需要较长时间思考,可能导致超时。 |
| 166 | + |
| 167 | +**避免超时的方法**: |
| 168 | + |
| 169 | +1. **使用 `--no-reply` 参数** (推荐): |
| 170 | + ```bash |
| 171 | + # 发送消息后立即返回,不等待 AI 响应 |
| 172 | + oho add "分析项目结构" --no-reply |
| 173 | + |
| 174 | + # 稍后检查结果 |
| 175 | + oho message list -s <session-id> |
| 176 | + ``` |
| 177 | + |
| 178 | +2. **增加超时时间**: |
| 179 | + ```bash |
| 180 | + # 设置超时为 10 分钟(600 秒) |
| 181 | + export OPENCODE_CLIENT_TIMEOUT=600 |
| 182 | + oho add "复杂任务" |
| 183 | + |
| 184 | + # 或临时设置 |
| 185 | + OPENCODE_CLIENT_TIMEOUT=600 oho add "复杂任务" |
| 186 | + ``` |
| 187 | + |
| 188 | +3. **使用异步命令**: |
| 189 | + ```bash |
| 190 | + # 先创建会话 |
| 191 | + oho session create --title "任务" |
| 192 | + |
| 193 | + # 异步发送消息 |
| 194 | + oho message prompt-async -s <session-id> "任务描述" |
| 195 | + ``` |
| 196 | + |
| 197 | +**超时配置**: |
| 198 | +| 环境变量 | 默认值 | 说明 | |
| 199 | +|----------|--------|------| |
| 200 | +| `OPENCODE_CLIENT_TIMEOUT` | 300 秒 | HTTP 请求超时时间(秒) | |
| 201 | + |
| 202 | +--- |
| 203 | + |
| 204 | +### 方案 2: 修改代码默认行为 |
| 205 | + |
| 206 | +**修改文件**: `oho/cmd/add/add.go` |
| 207 | + |
| 208 | +**选项 A: 默认使用 `--no-reply`** |
| 209 | + |
| 210 | +```go |
| 211 | +var ( |
| 212 | + addNoReply bool = true // 改为默认 true |
| 213 | +) |
| 214 | +``` |
| 215 | + |
| 216 | +**优点**: |
| 217 | +- 避免大多数超时问题 |
| 218 | +- 符合 CLI 工具的最佳实践(快速返回) |
| 219 | + |
| 220 | +**缺点**: |
| 221 | +- 破坏向后兼容性 |
| 222 | +- 用户可能期望立即看到 AI 响应 |
| 223 | + |
| 224 | +**选项 B: 添加超时提示** |
| 225 | + |
| 226 | +```go |
| 227 | +func runAdd(cmd *cobra.Command, args []string) error { |
| 228 | + ... |
| 229 | + |
| 230 | + // 发送消息 |
| 231 | + if !addNoReply { |
| 232 | + fmt.Println("⏳ 等待 AI 响应(按 Ctrl+C 中断,或使用 --no-reply 避免等待)...") |
| 233 | + } |
| 234 | + |
| 235 | + messageID, err := sendMessage(...) |
| 236 | + ... |
| 237 | +} |
| 238 | +``` |
| 239 | + |
| 240 | +--- |
| 241 | + |
| 242 | +### 方案 3: 改进错误提示 |
| 243 | + |
| 244 | +**修改文件**: `oho/internal/client/client.go` |
| 245 | + |
| 246 | +```go |
| 247 | +resp, err := c.httpClient.Do(req) |
| 248 | +if err != nil { |
| 249 | + if strings.Contains(err.Error(), "context deadline exceeded") { |
| 250 | + return nil, fmt.Errorf("请求超时(%d 秒)\n\n建议:\n 1. 使用 --no-reply 参数避免等待\n 2. 设置环境变量增加超时:export OPENCODE_CLIENT_TIMEOUT=600\n 3. 使用异步命令:oho message prompt-async", timeoutSec) |
| 251 | + } |
| 252 | + return nil, fmt.Errorf("请求失败:%w", err) |
| 253 | +} |
| 254 | +``` |
| 255 | + |
| 256 | +--- |
| 257 | + |
| 258 | +### 方案 4: 添加超时配置标志 |
| 259 | + |
| 260 | +**修改文件**: `oho/cmd/add/add.go` |
| 261 | + |
| 262 | +```go |
| 263 | +var ( |
| 264 | + addTimeout int // 新增超时标志 |
| 265 | +) |
| 266 | + |
| 267 | +func init() { |
| 268 | + ... |
| 269 | + Cmd.Flags().IntVar(&addTimeout, "timeout", 0, "请求超时时间(秒),0 使用默认值") |
| 270 | +} |
| 271 | + |
| 272 | +func runAdd(cmd *cobra.Command, args []string) error { |
| 273 | + ... |
| 274 | + |
| 275 | + // 如果指定了超时,临时覆盖 |
| 276 | + if addTimeout > 0 { |
| 277 | + os.Setenv("OPENCODE_CLIENT_TIMEOUT", strconv.Itoa(addTimeout)) |
| 278 | + c = client.NewClient() // 重新创建客户端 |
| 279 | + } |
| 280 | + |
| 281 | + ... |
| 282 | +} |
| 283 | +``` |
| 284 | + |
| 285 | +**使用方式**: |
| 286 | +```bash |
| 287 | +oho add "复杂任务" --timeout 600 |
| 288 | +``` |
| 289 | + |
| 290 | +--- |
| 291 | + |
| 292 | +## 📝 推荐修复顺序 |
| 293 | + |
| 294 | +### 立即修复(今天) |
| 295 | +1. ✅ **修改文档** - 添加超时说明和解决方案 |
| 296 | +2. ✅ **改进错误提示** - 超时错误给出明确建议 |
| 297 | + |
| 298 | +### 短期修复(本周) |
| 299 | +3. ✅ **添加超时标志** - `--timeout` 参数 |
| 300 | +4. ✅ **添加等待提示** - 显示 "等待 AI 响应..." |
| 301 | + |
| 302 | +### 长期考虑(下个版本) |
| 303 | +5. ⏳ **讨论默认行为** - 是否默认 `--no-reply` |
| 304 | +6. ⏳ **添加进度显示** - 显示 AI 思考进度 |
| 305 | + |
| 306 | +--- |
| 307 | + |
| 308 | +## 🔧 快速修复脚本 |
| 309 | + |
| 310 | +### 修复文档 |
| 311 | + |
| 312 | +```bash |
| 313 | +# 1. 更新 oho/README.md |
| 314 | +# 在 "Quick Start (Session + Message)" 部分后添加超时说明 |
| 315 | + |
| 316 | +# 2. 更新 README_zh.md |
| 317 | +# 同步中文文档 |
| 318 | +``` |
| 319 | + |
| 320 | +### 修复错误提示 |
| 321 | + |
| 322 | +```bash |
| 323 | +# 修改 oho/internal/client/client.go |
| 324 | +# 在 Request() 函数中添加超时错误处理 |
| 325 | +``` |
| 326 | + |
| 327 | +--- |
| 328 | + |
| 329 | +## 📊 影响评估 |
| 330 | + |
| 331 | +| 修复方案 | 影响范围 | 风险 | 优先级 | |
| 332 | +|----------|---------|------|--------| |
| 333 | +| 修改文档 | 用户文档 | 低 | P0 | |
| 334 | +| 改进错误提示 | 用户体验 | 低 | P0 | |
| 335 | +| 添加超时标志 | 新增功能 | 低 | P1 | |
| 336 | +| 修改默认行为 | 破坏性变更 | 中 | P2 | |
| 337 | + |
| 338 | +--- |
| 339 | + |
| 340 | +## 🎯 结论 |
| 341 | + |
| 342 | +**主要原因**: |
| 343 | +1. ✅ **文档未说明** - 用户不知道 `add` 默认会等待 AI 响应 |
| 344 | +2. ✅ **文档未说明超时配置** - 用户不知道可以调整超时时间 |
| 345 | +3. ⚠️ 代码设计合理,但缺少用户友好的提示 |
| 346 | + |
| 347 | +**建议修复**: |
| 348 | +1. **立即更新文档**,说明超时配置和 `--no-reply` 用法 |
| 349 | +2. **改进错误提示**,超时给出明确解决方案 |
| 350 | +3. **考虑添加 `--timeout` 参数**,方便临时调整 |
| 351 | + |
| 352 | +**代码本身没有问题**,主要是**文档和用户引导不足**。 |
| 353 | + |
| 354 | +--- |
| 355 | + |
| 356 | +*报告生成时间:2026-03-24 10:30 CST* |
0 commit comments