- 新增
degraded状态:将“工具看起来可用但未真正调用”、“max_tokens截断且未自动续写”、“模型自述上一步输出被截断、正在补写”等情况从success中拆分出来 - 补充
statusReason/issueTags:日志落盘、统计接口、Vue 日志页和旧版/logs页面均可显示降级原因并单独筛选 - 修复 Anthropic 工具统计失真:
/v1/messages路径会正确写入toolCallsDetected,不再出现stop_reason=tool_use但统计为 0 的情况
- 新增语义级截断检测:即使
json action代码块本身已经闭合,只要大负载Write/Edit参数尾部明显半截,也会继续判定为需要续写 - OpenAI 流式长工具调用恢复:OpenAI 兼容流式路径现在至少会尝试 1 次内部续写,修复长
Write被截断后无法恢复完整多帧tool_calls的回归 - 补充回归测试:新增并整理
unit-handler-truncation.mjs与unit-openai-stream-truncation.mjs,覆盖长Write/Edit截断、自愈补写和 OpenAI 流式恢复场景
- 新增
constants.ts:将REFUSAL_PATTERNS(50+ 条拒绝检测规则)、IDENTITY_PROBE_PATTERNS、TOOL_CAPABILITY_PATTERNS、CLAUDE_IDENTITY_RESPONSE、CLAUDE_TOOLS_RESPONSE及自定义拒绝规则逻辑从handler.ts提取到独立文件 - 提升可维护性:贡献者修改内置规则时只需查看
constants.ts,无需翻阅 2000 行的 handler 业务逻辑 isRefusal()函数统一导出:内置规则 + 自定义规则合并检测,所有调用点自动生效
config.yaml新增refusal_patterns字段:用户可添加自定义正则匹配规则,追加到内置列表之后(不替换),匹配到即触发重试逻辑- 无效正则容错:无效的正则表达式自动退化为字面量匹配,不会导致服务报错
- 缓存编译:自定义规则只在配置变更时重新编译 RegExp,运行时零开销
- 热重载支持:修改后下一次请求即生效
config.yaml新增sanitize_response字段:控制sanitizeResponse()函数(将 Cursor 身份引用替换为 Claude),默认关闭- 环境变量支持:
SANITIZE_RESPONSE=true可覆盖配置文件 - 零开销设计:关闭时函数入口直接返回原文本,无正则计算
- 热重载支持:修改配置后立即生效
- 截断时跳过工具解析:当响应被截断(
stop_reason=max_tokens)时,不再尝试解析不完整的json action块,避免生成损坏的工具调用(如写入半截文件) - 纯文本回退:截断响应中的不完整工具块被自动剥离,剩余文本作为纯文本返回,由客户端(Claude Code)原生续写
- 默认禁用代理续写:
maxAutoContinue默认值改为0,让 Claude Code 原生处理续写(体验更好、进度可见),配置同步更新至config.yaml、config.yaml.example、docker-compose.yml
- 身份声明清除:自动剥离系统提示词中的 Claude Code / Anthropic 身份声明(
You are Claude Code、I'm Claude, made by Anthropic等),防止模型将其判定为 prompt injection 并拒绝服务 - 流式热身窗口扩大:混合流式模式的
warmupChars从 96 增至 300 字符,确保拒绝检测完成前不释放任何文本给客户端
- 提示词对比视图:「💬 提示词」tab 重命名为「💬 提示词对比」,分区展示原始请求 vs 转换后的 Cursor 消息
- 转换摘要面板:顶部新增 6 格摘要(原始工具数 → Cursor 工具数 0、工具指令占用字符数、消息数变化、总上下文大小)
- 工具去向提示:当有工具时显示黄色提示「Cursor API 不支持原生 tools 参数,N 个工具已转换为文本指令嵌入 user #1」
- 标题提取优化:通用 XML 标签清除(覆盖所有注入标签)+ 清除
Respond with the appropriate action引导语
- 前端重构为独立静态文件:
logs.html/logs.css/logs.js分离到public/目录,告别单文件嵌入,更易维护 - 🌙 日/夜主题切换:一键切换明暗主题(☀️/🌙),自动检测系统偏好,选择持久化到
localStorage - 暗色主题完整适配:深蓝渐变背景,所有 UI 元素(标签、状态灯、代码块、JSON 高亮)均有独立暗色配色
- 标题提取修复:过滤
<system-reminder>...</system-reminder>注入内容和 Claude Code"First, think step by step..."引导语,确保标题显示用户真实提问 - 登录页同步更新:独立
login.html,视觉风格与日志页一致
- 移除
WELL_KNOWN_TOOLS白名单:所有工具统一保留描述(截取前 50 字符),简化逻辑 config.yaml停止追踪:含敏感 token 的配置文件加入.gitignore,不再上传- 新增
config.yaml.example:配置模板,安全默认值,用户只需cp config.yaml.example config.yaml .gitignore清理:去除重复条目,排除开发截图文件- Thinking 默认关闭:
thinking.enabled默认值改为false - Express v5 兼容:修复
path-to-regexp通配符路由报错,改用express.static中间件 - CSS 兼容性:补充标准
background-clip属性
- 新增日志查看器功能介绍(特性列表 + 鉴权说明)
- 新增配置项速查表格
- 新增环境变量参考表
- 项目结构补充
public/目录说明 - 配置说明改为引导用户从
config.yaml.example复制
- 修复 JSON Action 块截断:之前朴素的
substring截断会切断```json action代码块,产生未闭合标记和不完整 JSON,严重误导模型。现在对包含工具调用的 assistant 消息,提取工具名生成摘要(如[Executed: Write, Read]),不再做子串截断 - 工具结果头尾保留:工具结果截断从"只保留头部"改为 60% 头 + 40% 尾,确保错误信息、stack trace 等末尾关键内容不丢失
- 修复非工具模式偏移量:few-shot 消息跳过偏移量从硬编码
+2改为动态计算hasTools ? 2 : 0,修复非工具模式下前2条消息无法参与压缩的问题 - 自然边界截断:普通文本在换行符处截断,避免切断单词或代码
- 新增
compression配置段(config.yaml),支持:enabled:压缩开关(true/false),关闭后所有消息原样保留level:压缩级别 1-3(轻度/中等/激进),每级预设不同的保留消息数和字符限制keep_recent:高级选项,覆盖级别预设的保留消息数early_msg_max_chars:高级选项,覆盖级别预设的早期消息字符上限
- 支持环境变量
COMPRESSION_ENABLED/COMPRESSION_LEVEL,方便 Docker 部署
- 配置了
auth_tokens后,访问/logs及所有/api/logs*端点需要验证身份 - 精美的登录页面,输入 token 后通过
/api/stats验证有效性 - Token 存入
localStorage,刷新页面无需重新输入 - 支持 query 参数
?token=xxx、Authorizationheader、x-api-key三种传入方式 - 页面右上角显示退出按钮,清除缓存并跳回登录页
- 未配置
auth_tokens时保持完全开放(向后兼容)
- 修复 thinking 触发拒绝检测:模型的
<thinking>内容中包含反思性语言(如 "haven't given a specific task"),被拒绝检测正则误判为拒绝响应 - 拒绝检测现在先剥离
<thinking>标签内容,仅对实际输出文本进行检测 - 流式和非流式路径均已修复
- OpenAI Chat Completions 协议不再依赖模型名包含
thinking或传入reasoning_effort才启用 - 所有 OpenAI 格式请求默认启用 thinking,确保 Claude Code 等客户端始终获得推理内容
- 公网部署安全:新增
auth_tokens配置项,支持 Bearer token 鉴权 - 支持多 token(数组格式)、环境变量
AUTH_TOKEN、x-api-key头 - 未配置时全部放行(向后兼容),GET 请求和 /health 端点无需鉴权
- 启动 banner 显示鉴权状态
- Anthropic 协议:请求体传
thinking.type = "enabled"即启用 - OpenAI 协议:模型名含
thinking或传reasoning_effort参数即启用 - 系统提示词注入
<thinking>引导,模型输出自动提取 - Anthropic 返回
thinkingcontent block,OpenAI 返回reasoning_content字段 - 提取在拒绝检测之前执行,防止 thinking 内容触发误判
- 未启用时仍会剥离 thinking 标签(防误判),但内容不返回
WELL_KNOWN_TOOLS集合中的 17 个常用工具(Read、Write、Bash 等)不再生成描述文本- 减少约 30% 工具指令输入,节省上下文空间
getToolResultBudget()替代固定 15K 限制- 根据当前上下文大小动态调整:小上下文 20K → 大上下文 8K
setCurrentContextChars()跟踪实际上下文字符数
- 重新实现截断检测逻辑,正确处理工具调用 JSON 中的反引号
- 优先检查
```json action代码块,避免 JSON 字符串值内的反引号导致误判 - 消除因误判导致的无限重试
OpenAIChatRequest新增response_format字段(json_object/json_schema)- JSON 格式请求自动追加格式指令到最后一条用户消息
stripMarkdownJsonWrapper()自动剥离响应中的 markdown 代码块包装- 流式和非流式路径均支持
- 自动清除系统提示词中的
x-anthropic-billing-header - 防止模型将其判定为恶意伪造并触发注入警告
- 新增
vision.proxy配置项,图片分析 API 单独走代理 - Cursor API 保持直连(国内可用),不因代理影响响应速度
- 未配置时回退到全局
proxy
- 补充 4 个 Cursor 新拒绝措辞:
isn't something I can help with、not something I can help with、scoped to answering questions about Cursor、falls outside
- 新策略:保留最近 6 条消息完整不动,仅压缩早期消息中超过 2000 字符的文本部分
- 不删除任何消息(保留完整对话结构),只截短单条消息的超长文本
- 兼顾上下文完整性与输出空间,替代之前被移除的全删式智能压缩
- 工具描述截断从 200 → 80 字符(Schema 已包含参数信息,短描述节省输入体积)
- 工具结果截断从 30000 → 15000 字符(为输出留更多空间)
- 问题:模型续写时经常重复截断点附近的内容,拼接后出现重复段落
- 新增
deduplicateContinuation():在原内容尾部和续写头部之间搜索最长重叠,自动移除重复部分 - 支持字符级精确匹配和行级模糊匹配两种去重策略
- 去重后无新内容时自动停止续写(防止无限循环)
- 流式和非流式路径均已集成
- 问题:非流式模式下 Write 大文件等长输出被截断后,Claude Code 直接收到不完整的工具调用 JSON,导致
tool_use退化为纯文本 - 修复:非流式路径新增内部截断续写(最多 6 次),与流式路径逻辑完全对齐
- 新增
tool_choice=any强制重试(非流式):模型未输出工具调用时自动追加强制消息重试 - 新增极短响应重试(非流式):响应 < 10 字符时自动重试
- 提取
estimateInputTokens()为独立函数,Anthropic 和 OpenAI handler 共用 - 估算比例从 1/4 调整为 1/3(更适合中英文混合和代码场景)+ 10% 安全边距
- 新增工具定义的 token 估算(每个压缩工具签名 ~200 chars + 1000 chars 指令开销)
- 替代之前
input_tokens: 100的硬编码占位符
- 反斜杠计数精确化:
tolerantParse和parseToolCalls中的字符串状态跟踪从escaped布尔标志改为反向计数连续反斜杠,正确处理\\\"(未转义) vs\\\\\\\"(已转义) 等边界情况 - 新增第五层逆向贪婪提取:当所有 JSON 修复手段失败时,对 Write/Edit 等工具的
content/command/text等大值字段进行逆向贪婪提取,从 JSON 末尾向前搜索值的结束引号 - 小值字段(
file_path、path等)仍用精确正则提取
- 问题:工具模式下,模型输出长文本(如 8654 字符的深度分析报告),正文中碰巧包含
无法提供...信息、工具调用场景、即报错等拒绝检测关键词,导致整个响应被替换为无意义的引导文本"I understand the request...",进而 Claude Code 陷入死循环 - 修复策略:
- 截断响应(
stop_reason=max_tokens)完全跳过拒绝检测 — 8654 字符的响应不可能是拒绝 - 长响应(≥ 500 字符)仅检查前 300 字符是否包含拒绝模式 — 拒绝一定在开头
- 短响应(< 500 字符)保持全文检测 — 真正的拒绝回复通常很短
- 截断响应(
- 流式和非流式处理均已修复
- 模型输出中的普通 JSON 代码块(如含正则
[\s\S]*?的代码示例)不再打印error级别日志 - 仅当内容包含
"tool"/"name"键(疑似工具调用)时才报 error,其余降为warn级别
- 修复
fetch failed:Node.js 原生fetch()不读取HTTP_PROXY/HTTPS_PROXY环境变量,内网用户设置这些变量后请求仍然直连失败 - 新增
proxy-agent.ts:使用undici.ProxyAgent作为 fetch dispatcher,所有外发请求(Cursor API、Vision API)均可通过 HTTP 代理转发 - 配置方式:在
config.yaml中设置proxy字段,或通过PROXY环境变量指定(支持http://用户名:密码@代理:端口格式) - 单元测试:新增 16 个测试用例覆盖代理模块的核心逻辑
- 根本原因定位:90 个工具的完整 JSON Schema 占用 ~135,000 chars,导致 Cursor API 输出预算仅 ~3,000 chars,Write/Edit 工具的 content 参数被严重截断
- compactSchema() 压缩:将完整 JSON Schema 转为紧凑类型签名(如
{file_path!: string, encoding?: utf-8|base64}),输入体积降至 ~15,000 chars - 工具描述截断:每个工具描述最多 200 chars,避免个别工具(如 Agent)的超长描述浪费 token
- 效果:输出预算从 ~3k 提升到 ~8k+ chars,Write 工具可一次写入完整文件
- 修复致命 Bug:旧的 lazy regex
/```json[\s\S]*?```/g会在 JSON 字符串值内部的 ``` 处提前闭合,导致 Write/Edit 工具的 content 参数(如含 markdown 代码块的文档)被截断为仅前几行 - 新实现:手动扫描器跟踪 JSON 字符串状态(
"配对 +\转义),只在字符串外部匹配闭合 ``` - 截断恢复:无闭合 ``` 的代码块也能通过 tolerantParse 恢复工具调用
- 修复空响应问题:旧实现只追加 assistant 消息,Cursor API 看到最后是 assistant 的消息后返回空响应
- 新实现:每次续写添加 user 引导消息 + 最后 300 chars 上下文锚点
- 防膨胀:每次基于原始消息快照重建,而非累积消息
- MAX_AUTO_CONTINUE 从 4 提升至 6
移除上一版本引入的“智能压缩替裁剪”功能。
- 原因:Claude Code等Agent非常依赖完整的工具调用历史(尤其是
Read和Bash的具体输出)来决定下一步行动。将Action output压缩为[30000 chars...]以及将历史命令压缩为[System Note...]会导致大模型“失忆”,进而在多轮对话中陷入死循环、产生幻觉,甚至复读[Called Bash...]等错误格式。 - 替代方案:通过新增的
isTruncated自动检测并返回stop_reason: "max_tokens",已经能有效解决需要频繁点“继续”按钮的问题,因此粗暴的历史压缩不再被需要。
- Proxy-Side 无缝拼接:彻底解决大文件编辑(如
Write工具写了几万字)时被 API 截断,导致 JSON 解析失败、变为普通文本从而丢失工具调用的致命问题! - 自动检测与请求:当模型输出触发截断(如代码块/XML未闭合),Proxy 将在 底层直接自动重试续写,无需任何额外交互。
- 防止工具调用退化为文本:由于 Anthropic API 会在不同消息间打断工具调用块,造成 Claude Code 将
{"tool": "Write", ...}降级为屏幕上的纯文本并崩溃停顿(Crunched 几分钟)。现在,Proxy 会内部拼接 2-4 次请求,始终将一个完整未截断的 JSON 动作一次性抛给 Claude Code,极大提高了多轮复杂任务的成功率!
- 移除隐式重命名
file_path为path行动:修复 Claude Code 2.1.71 中Read工具因为必需参数file_path被强制丢弃而陷入请求验证失败死循环的问题。 - 新增第四层正则兜底:当模型生成的 JSON 工具调用包含未转义双引号(如代码内容参数)导致标准解析和控制字符修复均失败时,使用正则提取
tool名称和parameters字段 - 解决
SyntaxError: Expected ',' or '}'at position 5384 等长参数解析崩溃问题
- 工具模式下拒绝时返回极短文本
"Let me proceed with the task.",避免 Claude Code 误判为任务完成
- OpenAI Responses API (
/v1/responses) 支持 Cursor IDE Agent 模式 - 跨协议防御对齐(Anthropic + OpenAI handler 共享拒绝检测和重试逻辑)
- 统一图片预处理管道(OCR/Vision API)