97 Commits

Author SHA1 Message Date
BaskDuan
0f8b3246ed feat: 内置 stealth-proxy 到 Docker 镜像,一个容器搞定 Vercel Bot Protection
- Dockerfile 从 alpine 切换到 slim (Debian) 以支持 Playwright Chromium
- 新增 start.sh 入口脚本,ENABLE_STEALTH=true 时自动启动内置 stealth-proxy
- docker-compose.yml 简化为单容器方案,默认启用 stealth 模式
- 新增 cookie/stealth_proxy/system_prompt 配置项及环境变量支持
- deploy-all.sh 加入 .gitignore(含敏感服务器信息)
- 更新默认指纹为 macOS Chrome 146

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 15:44:32 +08:00
wsyh4567
0958ca3c2a fix: SSE 事件格式错误导致 Codex CLI v0.117+ 出现 stream closed before response.completed
修复两处导致 Codex CLI v0.117+ 报错 "stream closed before response.completed" 的 bug:

Bug 1:writeResponsesSSE 发送的 data JSON 缺少 "type" 字段
  Codex 的 ResponsesStreamEvent 结构体要求每条事件的 data 必须包含
  "type" 字段,否则整条事件解析失败被跳过。

  修复:将 JSON.stringify(data) 改为 JSON.stringify({ type: eventType, ...data })

Bug 2(主要原因):response 对象未嵌套在 "response" 字段下
  Codex 处理 response.completed / response.created / response.in_progress 时,
  从 event.response 字段读取 response 对象。cursor2api 原本将
  buildResponseObject() 的字段全部展开到顶层,导致 event.response = null,
  整个事件被静默忽略,等流关闭时报 "stream closed before response.completed"。

  修复:所有 buildResponseObject() 调用改为 { response: buildResponseObject(...) }
  共修改 8 处(emitResponsesTextStream、工具调用路径、错误回退路径)

参考:https://github.com/openai/codex/blob/main/codex-rs/codex-api/src/sse/responses.rs
关联 Issue:#114
2026-03-28 00:41:58 +08:00
小海
0716b602ac feat: v2.7.8 - 新增三大防截断机制
- 上下文压力膨胀(context_pressure):虚增 input_tokens 让客户端提前触发自动压缩
- 自适应历史预算(tools.adaptive_budget):工具数量越多,自动预留越多输出空间
- 工具结果智能截断(tools.smart_truncation):按工具类型差异化截断(Read/Bash/Search)
- 三个功能均默认关闭,支持 config.yaml 和环境变量控制
- 更新 config.yaml.example、docker-compose.yml、README 更新日志
2026-03-27 11:48:37 +08:00
huangzhenting
717af46606 feat: Vue UI 增强 — 统计/筛选联动、自动跟随、交互优化
- 新增 getVueStats(since?)/apiGetVueStats/GET /api/vue/stats,供 Vue UI 专用
  SQLite 模式走数据库全量聚合+since过滤,getStats() 保持原样不影响 HTML 版本
- Vue UI 所有 /api/stats 调用改为 /api/vue/stats
- SSE stats 事件改为调 statsStore.load() 从 /api/vue/stats 拉最新数据
- 时间筛选增加 1小时/6小时选项,状态筛选改为 emoji 图标风格
- 状态筛选选中态:全部用蓝紫渐变底色,图标按钮用对应颜色边框+文字
- AppHeader/RequestList 缩写处全面补充 title tooltip
- 新增「自动跟随」功能:选中记录后可开启,SSE 推送新请求时自动切换并滚动到顶部
- 修复 ConfigDrawer draft 可能为 null 的 TS 错误
- 修复 CSS typo:.rfmt.responses background 颜色值多余空格
- upsertRequest 改用 Object.assign 避免 SSE 推送时替换对象引用打断 hover
2026-03-23 17:35:13 +08:00
小海
2933df2697 fix: improve truncation recovery and diagnostics for v2.7.7
- mark degraded requests in logs and viewer when execution quality drops
- record Anthropic toolCallsDetected correctly in summaries
- continue semantically incomplete long Write/Edit tool payloads
- restore truncated OpenAI stream long Write tool_calls
- update release docs, sample config, docker notes, and README guidance
2026-03-23 11:39:00 +08:00
huangzhenting
a84dfd6d03 feat: 实现 db_enabled/db_path 热重载支持,修复文档格式
- logger-db.ts: 新增 closeDb(),修复 initDb() 支持安全重复调用
- logger.ts: 注册 onConfigReload 回调,db_enabled/db_path 变更后无需重启
- config.yaml.example: 删除「需重启」警告注释,补充热重载说明
- README.md: 修复环境变量表格被 blockquote 截断的格式问题,更新热重载说明
- vue-ui/README.md: 删除「需重启服务」错误说明
- ConfigDrawer.vue: 删除「需重启」提示
2026-03-23 08:45:21 +08:00
huangzhenting
1bc91cac24 feat: 新增 SQLite 持久化支持 + Vue UI 后端过滤与分页优化
- 新增 src/logger-db.ts:SQLite 封装层(WAL 模式,支持写入/分页/状态计数/按需 payload 查询)
- logger.ts:双写 SQLite+JSONL,启动时 db_enabled 模式跳过 JSONL 读取避免 OOM,新增游标分页和后端过滤函数
- config.ts/config-api.ts:新增 db_enabled/db_path 配置字段及 LOG_DB_ENABLED/LOG_DB_PATH 环境变量
- log-viewer.ts/index.ts:新增 /api/requests/more 支持 status/keyword/since 后端过滤
- Vue UI:搜索框 400ms 防抖,状态/时间筛选立即触发后端查询,statusCounts 不受状态筛选影响,SSE 实时推送时增量更新计数
- 新增迁移工具 test/migrate-jsonl-to-sqlite.mjs 和单元测试 test/unit-logger-db.mjs
- 完善 README.md、config.yaml.example、docker-compose.yml、vue-ui/README.md 文档
2026-03-22 21:10:26 +08:00
huangzhenting
f317dc04b0 fix: 修复 thinking 截断时内容泄漏到正文的问题
问题:当模型 thinking 内容超出单次输出上限时,<thinking> 标签未闭合,
导致 thinking 内容被当作正文泄漏给客户端;续写请求中 assistantContext
含未闭合标签,模型不知道思考阶段已结束,继续输出 thinking 而非正文。

修复:
1. splitLeadingThinkingBlocks:未闭合时返回已积累的部分 thinkingContent
   而非空字符串,供调用方正确提取
2. handler.ts / openai-handler.ts:流结束 flush 新增 !complete 分支,
   提取截断的 thinkingContent,不将 thinking 内容 flush 为正文
3. 新增 closeUnclosedThinking:续写前补全缺失的 </thinking> 标签,
   应用于所有 4 处续写 assistantContext 构建,让模型正确从正文续写
4. shouldAutoContinueTruncatedToolResponse:json action 块未闭合时
   跳过 200-char 检查,修复 thinking 剥离后正文过短导致续写不触发的问题

测试:新增 unit-thinking-truncation.mjs(11个单元测试)、
e2e-thinking-truncation.mjs(3个实际 API 请求测试),全部通过
2026-03-22 14:10:58 +08:00
huangzhenting
c4b81f33d1 fix: improve token budget accuracy and add TokenDiff logging
- converter: replace rough overhead formula (tools*70+350) with actual
  estimateTokens on built few-shot messages + Cursor hidden overhead
  (1300 base + perTool by schema_mode); remove 16000 output reservation
- cursor-client: sendCursorRequestFull now returns {text, usage?} to
  capture real Cursor inputTokens/outputTokens from messageMetadata
- handler: add estimateCursorReqTokens() and [TokenDiff] log to compare
  tiktoken estimate vs actual Cursor usage; fix non-stream retry paths
  to update usage from retry result; skip auto-continue when response < 200 chars
- openai-handler: update 4 call sites for new sendCursorRequestFull return type
- config: raise default maxHistoryTokens from 130000 to 150000
- docs/config: remove incorrect 'tiktoken underestimates 10~20%' claim;
  update overhead description and reference range to 130000~170000
2026-03-22 02:35:04 +08:00
huangzhenting
a153dad4de feat: record and display real Cursor API token usage
Capture the actual input/output token counts from Cursor API's finish
event (messageMetadata.usage) and use them in place of tiktoken
estimates where available. Fall back to tiktoken if not present.

- src/types.ts: extend CursorSSEEvent with finishReason/messageMetadata
- src/handler.ts: capture finish event usage in streaming paths, pass
  real counts to updateSummary with tiktoken fallback
- src/logger.ts: add inputTokens/outputTokens fields to RequestSummary
- vue-ui: show ↑/↓ Cursor tokens in RequestList, DetailPanel, PayloadView
- public/logs.js: show ↑/↓ Cursor tokens in scard and prompts summary
2026-03-21 18:42:12 +08:00
huangzhenting
b542d554c6 feat: add max_history_tokens to trim context by token budget
Introduce js-tiktoken (cl100k_base) based token estimation to replace
the naive chars/3 approach. Add max_history_tokens config option that
trims oldest messages when the estimated token budget is exceeded.

- src/tokenizer.ts: new module wrapping js-tiktoken getEncoding
- src/config.ts/config-api.ts: YAML parse, env var, hot-reload, default 130000
- src/converter.ts: token budget trimming after max_history_messages pass
- src/handler.ts: replace estimateInputTokens with tiktoken-based version
- config.yaml.example/docker-compose.yml/README.md: docs and examples
- vue-ui: ConfigDrawer field, HotConfig type, README table row
2026-03-21 18:41:45 +08:00
huangzhenting
feab833fbd fix: replace line-repeat detection with HTML token repeat detection
- 用跨 delta 拼接的 HTML token 重复检测替换依赖 \n 的行级检测
- 新增 streaming-text warmup HTML guard,阻止纯 HTML token 在 warmup 阶段提前 unlock 推流
- 覆盖 <br>、</s>、&nbsp; 等被拆散发送或无换行的场景
2026-03-21 00:30:01 +08:00
huangzhenting
45f192a381 feat: add Vue config drawer for hot-reloadable settings
Add /api/config GET+POST endpoints to read and write config.yaml fields
that support hot-reload. Frontend: config button in AppHeader opens a
650px side drawer with grouped fields, SegSelect/Toggle components,
YAML key names as labels, and descriptions sourced from config.yaml.example.
thinking.enabled supports a 3-way selector (auto/off/on) where auto
deletes the yaml key so the default kicks in.
2026-03-20 17:50:49 +08:00
huangzhenting
203de92228 fix: detect and abort line-level repetition loops in cursor stream
Adds line-by-line repeat detection alongside the existing delta-level
degenerate loop guard. When the same non-empty line appears 8+ consecutive
times, the stream is cancelled and a retryable error is thrown.
2026-03-20 17:50:38 +08:00
majorcheng
310fd8672d fix: complete OpenAI logs and default persisted logs to summary 2026-03-20 14:06:46 +08:00
小海
db5d3fb1f7 feat: show tools mode (disabled/passthrough) in startup and request logs
- Startup log: Tools: disabled / passthrough / schema=full
- Request log: tools=98(跳过) / tools=98(透传) / tools=98
2026-03-20 09:26:23 +08:00
小海
4a026b6b98 feat: add tools.disabled mode to skip all tool injection for max context savings
- tools.disabled: true completely skips tool definitions + few-shot injection
- Response-side parseToolCalls still works if model outputs action blocks
- Env var: TOOLS_DISABLED=true|false
- Updated config.yaml.example and docker-compose.yml
2026-03-20 09:23:15 +08:00
小海
7c2422ce60 feat: add TOOLS_PASSTHROUGH env var override for Docker support 2026-03-20 09:18:13 +08:00
小海
90be75ff9f feat: add tool passthrough mode, identity leak sanitization & enhanced tool_choice=any
1. Tool passthrough mode (config: tools.passthrough: true)
   - Bypasses multi-namespace few-shot injection
   - Embeds raw tool definitions in <tools> tags with minimal 1-shot example
   - Cleans conflicting client prompts (provider-native tool calling, XML markup)
   - Ideal for Roo Code / Cline clients

2. Enhanced Cursor identity leak sanitization
   - New refusal detection patterns for "currently in Cursor context" leaks
   - 4 new sanitizeResponse regexes targeting full context leak paragraphs
   - Covers "I apologize - it appears I'm in Cursor support assistant context"

3. Enhanced tool_choice=any force message
   - Lists available tool names (up to 15) with format example
   - Uses collaborative guidance tone to avoid triggering refusal
   - Stream and non-stream paths aligned
2026-03-20 09:14:28 +08:00
huangzhenting
c868bf3074 feat: 添加 /vuelogs 路由(服务端) 2026-03-20 03:42:27 +08:00
huangzhenting
8e50c7bf9b Merge remote-tracking branch 'origin/main' into feature/vue-logs-ui 2026-03-19 22:43:18 +08:00
huangzhenting
69983e3996 feat: 添加 Vue3 日志 UI — 新增 /vuelogs 路由及 vue-ui 前端目录
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 22:42:33 +08:00
chinadoiphin
f17353e05b fix: 修复 Cursor 身份泄漏 — 模型声称只有 read_file/read_dir 工具 (#68)
问题:模型回复"在当前环境中我只有读取 Cursor 文档的工具
(read_file / read_dir),无法访问你的本地文件系统",
暴露了 Cursor 文档助手身份。

修复:
1. handleDirectTextStream 的 warmupChars 从 96 → 300,
   与工具模式对齐,确保拒绝检测窗口覆盖完整的中文拒绝句式
2. constants.ts 新增 9 条中文拒绝检测规则,覆盖
   "只有读取 Cursor/文档的工具"、"无法访问本地文件"、
   "无法执行命令"、"需要在 Claude Code CLI 环境" 等新措辞
3. sanitizeResponse 新增 5 条清洗规则作为最后防线
2026-03-19 22:12:14 +08:00
小海
f6ad4292f8 fix: 会话隔离 — 基于内容哈希派生确定性会话 ID (#56)
修复 CC 执行 /clear 或 /new 后旧会话上下文残留的问题。
将 CursorChatRequest.id 从随机 shortId() 改为基于
system prompt + 首条用户消息的 SHA-256 哈希派生,
确保不同逻辑会话获得不同的 Cursor 会话 ID。
2026-03-19 10:53:11 +08:00
小海
14aa65349c feat: v2.7.5 — 常量集中管理 + 自定义拒绝规则 + 响应清洗开关
🏗️ 常量集中管理
- 新增 constants.ts,提取 REFUSAL_PATTERNS、IDENTITY_PROBE_PATTERNS、
  TOOL_CAPABILITY_PATTERNS、CLAUDE_IDENTITY_RESPONSE、CLAUDE_TOOLS_RESPONSE
- isRefusal() 统一导出,内置 + 自定义规则合并检测

🔧 自定义拒绝检测规则 (config.yaml: refusal_patterns)
- 用户可添加自定义正则匹配规则,追加到内置列表
- 无效正则自动退化为字面量匹配
- 缓存编译 + 热重载支持

🔀 响应内容清洗开关 (config.yaml: sanitize_response)
- 控制 sanitizeResponse() 是否替换 Cursor 身份引用为 Claude
- 默认关闭,关闭时零开销
- 支持环境变量 SANITIZE_RESPONSE 覆盖
2026-03-19 09:44:21 +08:00
小海
e15dd5af33 fix: 压缩上下文后首条消息返回"你有什么问题吗"的问题 (#68)
CC 压缩后,消息主体全是 XML 标签(压缩的上下文摘要),
剥离标签后 actualQuery 为空,回退保留了完整 XML 内容,
但追加的 suffix 是通用的"Respond with structured format",
模型看不到具体任务 → 回答"你有什么问题吗?"

修复:检测到压缩回退场景时,改用上下文感知的引导指令:
"Based on the context above, determine the next step and
proceed..." + "Do NOT ask the user what they want",
让模型直接根据压缩上下文继续工作,而非等待新指令。
2026-03-19 09:26:15 +08:00
小海
1dd24ca84d feat: 多类别 few-shot 示范,提升 MCP/Skills/Plugins 工具调用率 (#67)
问题:模型只模仿 few-shot 中见过的工具(Read/Bash),
导致 MCP 工具、Skills、Plugins 等第三方工具从不被调用。

修复:
- 按命名空间/来源自动分组第三方工具(MCP 双下划线、
  驼峰前缀、蛇形前缀等规则)
- 每个命名空间选一个代表性工具加入 few-shot 示范
- 核心工具(Read/Bash) + 最多 4 个第三方工具代表
- 在单个 assistant 回复中展示多工具调用格式
- 第三方工具的示例参数从 schema 中自动提取

示例:如果用户有 mcp__context7、SuperPowers、claude_mem
等不同来源的工具,few-shot 会各选一个代表进行示范,
让模型知道所有类别的工具都可以调用。
2026-03-19 09:23:38 +08:00
小海
4bd6066dda fix: 检测模型退化循环输出并自动中止流 (#66)
当 Cursor 后端模型陷入退化循环时(不断重复输出 </s>、</br> 等
短文本标记),会导致内容输出一点就停止、后台日志充斥大量
重复标记的现象。

修复方案:在 cursor-client.ts SSE 解析层加入退化重复检测器:
- 跟踪连续相同的 text-delta(仅检测 ≤20 字符的短 token)
- 同一 delta 连续出现 ≥8 次时判定为退化循环
- 立即中止流(reader.cancel),保留已收到的有效内容
- 外层 sendCursorRequest 识别 DEGENERATE_LOOP_ABORTED 后
  不再重试(重试也会重蹈覆辙)

所有流式路径(Anthropic handler、OpenAI handler、续写)
自动受保护,无需逐个修改。
2026-03-19 09:14:29 +08:00
小海
53335aeeab fix: 修复 SVG 图片导致 tesseract.js 崩溃的问题 (#69)
SVG 是基于 XML 的矢量图格式,tesseract.js 无法处理。
尝试对 SVG 进行 OCR 会在 tesseract Worker 内部通过 process.nextTick
抛出未捕获的 TypeError (fetch failed),导致整个进程异常终止。

修复方案:在三层防御点过滤 SVG 图片:
1. converter.ts preprocessImages(): 下载/读取后检测 content-type
   或文件扩展名为 SVG 时,替换为文本描述
2. vision.ts applyVisionInterceptor(): 在分发到 OCR/Vision API
   之前过滤 SVG 类型的 image block
3. vision.ts processWithLocalOCR(): 在调用 worker.recognize()
   之前检查 UNSUPPORTED_OCR_TYPES 集合(纵深防御)
2026-03-19 09:06:40 +08:00
chinadoiphin
23c9f16dff perf: 视觉拦截器仅处理最后一条 user 消息的图片
历史消息中的图片已在前几轮被转换为文本描述,无需重复送入
OCR/Vision API 处理。此优化避免多轮对话中重复消耗 API 配额
并减少每次请求的延迟。
2026-03-18 21:17:50 +08:00
chinadoiphin
c2dae870ca feat: config.yaml 热重载支持(修改后无需重启服务)
- 重构 config.ts:提取 parseYamlConfig / applyEnvOverrides 为可复用函数
- 新增 initConfigWatcher:fs.watch + 500ms 防抖监听 config.yaml
- 端口变更仅警告(需重启),其余字段下一次请求即生效
- 中间件改用 getConfig() 实时读取,确保 auth_tokens 等热更新生效
- 新增 onConfigReload 回调机制、detectChanges 变更检测
- 优雅关闭:SIGTERM/SIGINT 时停止文件监听
- 环境变量覆盖始终保持最高优先级
2026-03-18 21:16:11 +08:00
小海
f9bebeb4b5 fix: thinking 检测位置约束,防止正文字面量误触发 (Issue #64)
将所有 includes('<thinking>') 替换为 hasLeadingThinking(),
只在 <thinking> 出现在响应开头时才触发提取,
防止用户消息或模型正文中的字面量标签误触发 extractThinking 导致内容丢失。
2026-03-18 14:06:53 +08:00
小海
8a5117bbb1 v2.7.4: 截断安全 + 代理续写禁用 + 日志提示词对比视图
- 截断时跳过工具解析,防止损坏的工具调用(写入半截文件)
- maxAutoContinue 默认 0,交由 Claude Code 原生续写
- 系统提示词身份声明清除(防 prompt injection 拒绝)
- 流式热身窗口 96→300 chars(拒绝检测前不释放文本)
- 日志查看器「提示词对比」视图:原始 vs Cursor 转换后
- 转换摘要面板:工具数/消息数/上下文大小一目了然
- 标题提取增强:通用 XML 标签清除 + 更多引导语过滤
2026-03-18 11:56:26 +08:00
小海
8a6b11a4c7 perf: optimize prompt efficiency via A/B tested behaviorRules
- behaviorRules: append action-first directive reducing narration 37% (32%→20%)
  \"Each response must be maximally efficient: omit preamble and planning text
  when the next step is clear—go straight to the action block.\"
- Continuation suffix: shorten from ~180 chars to ~30 chars (83% token saving)
  \"Based on the output above, continue working...\" → \"Continue with the next action.\"
- Add A/B test harnesses (e2e-prompt-ab.mjs, e2e-prompt-ab2.mjs) for future prompt tuning

Tested 4 variants × 17 scenarios. Candidate B won with:
  - Narration ratio: 32% → 20%
  - Response latency: 2372ms → 1795ms (↓24%)
  - Zero over-action side effects
  - 9/9 continuation scenarios passed
2026-03-18 10:34:38 +08:00
Xu Kang
af6449300f Merge pull request #62 from majorcheng/main
Fix OpenAI stream usage in final chunk
2026-03-18 09:48:47 +08:00
小海
c06755c46c perf: 早期中止拒绝检测 + 降低重试/续写上限 + 续写上下文截断
性能优化:
- sendCursorRequest 支持外部 AbortSignal,允许调用方提前中止流
- 工具模式 executeStream 在前 200-400 字符即检测拒绝,立即中止流
  (原先等完整响应再检测,浪费 2-5s/次)
- MAX_REFUSAL_RETRIES 2→1,减少最差情况 API 调用次数
- maxAutoContinue 默认 3→2,减少续写开销
- 续写请求只发最后 2000 字符作为上下文(原先发完整响应,可能 10K+)

测试:
- 重写 perf-diag.mjs 公平对比:直连也使用相同 reframing 提示词
- 公平测试结果:代理平均 0.78x(比直连更快),无性能瓶颈
2026-03-18 09:46:36 +08:00
majorcheng
0768c52790 Merge branch '7836246:main' into main 2026-03-18 09:34:40 +08:00
majorcheng
ee8a7135dd Fix OpenAI stream usage in final chunk 2026-03-18 09:19:37 +08:00
小海
18c90e0720 feat: 续写次数可配置 + 历史消息条数硬限制 (#61)
采纳社区建议,新增两个配置项:

1. max_auto_continue(默认 3,设 0 禁用)
   - 替换了 handler.ts 中 4 处硬编码的 MAX_AUTO_CONTINUE = 3
   - 设为 0 时 while 循环直接短路,完全禁用自动续写
   - 用户可在对话中自行要求续写,往往更精准

2. max_history_messages(默认 100,-1 不限制)
   - 在 converter.ts 消息转换后、压缩步骤前执行裁剪
   - 保留 few-shot 示例(工具模式前 2 条),删除最早的非 few-shot 消息
   - 防止 800+ 条消息导致请求体积过大、响应变慢

两项配置均支持 config.yaml 和环境变量(MAX_AUTO_CONTINUE / MAX_HISTORY_MESSAGES)
2026-03-18 09:10:08 +08:00
小海
5e0c9a3ce7 fix: 修复工具模式误续写导致的截断终止
避免短参数 tool_use 在已可恢复时继续隐式续写,减少 OpenClaw/Telegram 场景下的长时间挂起与 terminated。
同时统一 Anthropic 与 OpenAI 兼容接口的截断续写判定,并补充对应回归测试。

Made-with: Cursor
2026-03-17 15:11:22 +08:00
小海
ed6181a5a9 fix: harden OpenAI multimodal compatibility and image handling
Tighten image path normalization, preserve multimodal request content across OpenAI-compatible endpoints, and fail fast on unsupported image_file inputs so clients get predictable behavior instead of silent degradation.

Made-with: Cursor
2026-03-17 15:03:39 +08:00
小海
447dad8c03 fix: thinking 未配置时不再自动注入,跟随客户端请求
Made-with: Cursor
2026-03-17 14:42:33 +08:00
小海
fd9d17a49e release: v2.7.3 — 统一 thinking 剥离 + 拒绝检测增强 + Docker 部署优化
Made-with: Cursor
2026-03-17 14:28:31 +08:00
小海
70d8da273d feat: implement proper OpenAI Responses API streaming format for Codex compatibility
Fix "stream disconnected before completion: stream closed before response.completed"
error when using Codex CLI. The /v1/responses endpoint was outputting Chat Completions
SSE format (data-only) instead of the Responses API SSE format with event: prefixes.

Codex expects specific SSE events:
- response.created / response.in_progress
- response.output_text.delta (incremental text)
- response.function_call_arguments.delta (tool calls)
- response.completed (★ the critical event Codex waits for)

Changes:
- Rewrite handleOpenAIResponses() with dedicated stream/non-stream handlers
- Add writeResponsesSSE() for event: + data: format
- Support function_call output items for tool calls
- Add error recovery that always emits response.completed
- Add identity probe mock responses in Responses API format
2026-03-17 13:52:05 +08:00
小海
85d8666eeb fix: 修复纯字符串 content 中的图片路径无法提取的根因 (#39)
核心修复:
- Phase 1.5 现在同时处理 string content 和 array content
  (之前仅处理 Array.isArray 的情况,跳过了纯字符串)
- 重写正则引擎:使用 [^\\s\"')\\]] 替代 [\\w.\\/-]
  匹配含 UUID/连字符的路径 (如 file_362---eb90f5a2-xxx.jpg)
- 新增图片诊断日志:记录客户端发送的 content 格式
  帮助定位不同客户端的图片格式差异
2026-03-17 12:27:51 +08:00
小海
292c8c4557 fix: 修复 CC 自动压缩后模型丢失任务上下文的问题
- 检测 XML 标签剥离后 actualQuery 为空的情况(压缩产物),
  回退到不分离模式,保留完整消息内容
- 增强 tool_result 续航指令,明确引导模型继续执行上下文中的任务
2026-03-17 11:54:38 +08:00
小海
e2acdd186d fix: 修复 OpenClaw/Telegram 等客户端图片处理失败问题 (#39)
- 新增本地文件路径图片读取支持 (readFileSync)
- 新增文本消息中嵌入图片 URL/路径自动提取
- 新增 file:// URL 解析支持
- OpenAI handler 新增 image_file、扁平 url、通用兜底等格式兼容
- 修复 OpenClaw {{MediaPath}} 本地路径无法被 fetch() 处理的根因
2026-03-17 10:56:38 +08:00
小海
a0af1c8934 feat: 可配置工具处理 + 修复 URL 图片兼容性
tools 配置:
- schema_mode: compact/full/names_only 三种 Schema 呈现模式
- description_max_length: 工具描述截断长度 (0=不截断)
- include_only/exclude: 工具白名单/黑名单过滤
- 启动 banner 显示 tools 配置摘要
- 日志记录完整工具描述(不再截断200字符)

图片 URL 修复:
- 归一化 Anthropic API source.url → source.data
- 支持 image/input_image 等多种客户端格式
- 图片下载添加 User-Agent 头(解决 Telegram 403)
- 增强日志:记录每张图片下载过程和结果
2026-03-17 10:13:09 +08:00
小海
f40bfaee64 refactor: 移除 WELL_KNOWN_TOOLS 工具白名单
所有工具现在统一保留描述(截取前50字符),不再对特定工具名跳过描述。
2026-03-17 09:40:10 +08:00
小海
d388fefa21 feat(log-viewer): 日夜主题切换 + 标题提取修复
- 新增日/夜主题切换按钮(☀️/🌙),支持 localStorage 持久化,首次自动检测系统偏好
- 完整暗色主题 CSS 变量覆盖,所有 UI 元素适配
- 修复标题提取:过滤 <system-reminder> 注入内容和 Claude Code 引导语
- 日志页面前端重构为独立 HTML/CSS/JS 静态文件
- 登录页面样式同步更新为现代玻璃态主题
- Express 静态文件服务配置修复(兼容 v5 path-to-regexp)
2026-03-17 09:33:00 +08:00