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 更新日志
v2.7.8
2026-03-27 11:48:37 +08:00
小海
55a679fb2c
docs: 添加赞助感谢板块
2026-03-27 10:28:54 +08:00
Xu Kang
7a929c9c44
Merge pull request #102 from huangzt/feature/vue-logs-ui
...
feat: Vue UI 增强 — 统计/筛选联动、自动跟随、交互优化
2026-03-23 21:20:42 +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
v2.7.7
2026-03-23 11:39:00 +08:00
Xu Kang
70fa4074e8
Merge pull request #93 from huangzt/feature/vue-logs-ui
...
feat: 新增 SQLite 日志持久化 + Vue UI 后端过滤分页(完全兼容,不影响主流程)
2026-03-23 09:05:18 +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
Xu Kang
9a69e66a7e
Merge pull request #90 from huangzt/feature/vue-logs-ui
...
fix: 修复 thinking 截断时内容泄漏到正文的问题
2026-03-22 18:24:54 +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
Xu Kang
bb86c1a66e
Merge pull request #88 from huangzt/feature/vue-logs-ui
...
fix: 优化 token 预算精度,新增 TokenDiff 日志对比功能
2026-03-22 10:49:40 +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
Xu Kang
3e0ceb2227
Merge pull request #87 from huangzt/feature/vue-logs-ui
...
feat: 新增 max_history_tokens 按 token 数裁剪历史 + 记录 Cursor API 真实 token 用量
2026-03-21 19:09:55 +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
Xu Kang
b70f787aef
Merge pull request #84 from huangzt/feature/vue-logs-ui
...
fix: HTML token 重复检测 + CodeBlock 语法高亮修复
2026-03-21 01:19:20 +08:00
huangzhenting
a3bd993d15
fix: CodeBlock 仅对指定 lang 做语法高亮,markdown 类型非 MD 预览时显示原始文本
...
- 移除 highlightAuto,避免纯文本内容被误判染色
- lang=markdown 仅在 mdPreview 开启时渲染,否则显示原始文本
- toolCalls 区块补充 lang=json 以保留 JSON 高亮
2026-03-21 00:47:13 +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>、 等被拆散发送或无换行的场景
2026-03-21 00:30:01 +08:00
Xu Kang
d519338ba1
Merge pull request #79 from huangzt/feature/vue-logs-ui
...
feat: Vue UI 配置抽屉、行级重复检测修复、Docker 部署文档完善
2026-03-20 18:11:40 +08:00
huangzhenting
35e2c56855
docs: update vue-ui README with Docker deploy notes, fix config.yaml ro mount
...
Remove :ro from config.yaml volume mount in docker-compose.yml so the
config drawer can write back changes at runtime. Add deployment section
to vue-ui/README.md covering: build-before-docker requirement, config.yaml
read-write mount, first-time setup steps, and config drawer field reference.
2026-03-20 17:54:51 +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
Xu Kang
3ad8be7d33
Merge pull request #78 from majorcheng/main
...
fix: complete OpenAI logs and default persisted logs to summary
2026-03-20 14:29:27 +08:00
majorcheng
310fd8672d
fix: complete OpenAI logs and default persisted logs to summary
2026-03-20 14:06:46 +08:00
小海
d293d272ad
release: v2.7.6 - tool passthrough/disabled modes, identity leak fix, tool_choice guidance
...
New features:
- tools.passthrough: bypass few-shot injection, embed raw tool defs (for Roo Code/Cline)
- tools.disabled: skip all tool injection for max context savings
- Enhanced Cursor identity leak sanitization (new regex patterns)
- Improved tool_choice=any guidance with collaborative tone
- TOOLS_PASSTHROUGH / TOOLS_DISABLED env var support
- Startup & request logs show tool mode (disabled/passthrough/standard)
v2.7.6
2026-03-20 09:28:49 +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
小海
70d077b27a
docs: add passthrough option to config.yaml.example
2026-03-20 09:16:33 +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
Xu Kang
127f635592
Merge pull request #73 from huangzt/feature/vue-logs-ui
...
feat: 添加 Vue3 日志 UI(/vuelogs 路由 + 前端全面优化)
2026-03-20 08:58:37 +08:00
huangzhenting
54cb89c11a
feat: Vue UI 全面优化 — 暗色主题、搜索、交互、动效
2026-03-20 03:42:32 +08:00
huangzhenting
c868bf3074
feat: 添加 /vuelogs 路由(服务端)
2026-03-20 03:42:27 +08:00
Xu Kang
17a1633617
Merge pull request #72 from huangzt/feature/vue-logs-ui
...
feat: 新增 Vue3 日志查看界面 (/vuelogs)
2026-03-19 23:09:02 +08:00
huangzhenting
349c729d38
docs: 新增 vue-ui 开发说明文档
...
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com >
2026-03-19 23:00:20 +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。
v2.7.5
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 导致内容丢失。
v2.7.4
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
小海
e6f3a06416
chore: 从版本控制中移除 .claude 本地配置
2026-03-18 10:37:04 +08:00