File size: 18,725 Bytes
2b64d42 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | {
"contributors": [
{
"login": "dwgx",
"pr": 0,
"weight": "GOD",
"weightLabel": "项目作者 · 反代架构 / 协议翻译 / 部署 / 全部 release",
"mergedAt": "2026-04-01",
"title": "feat: WindsurfAPI — 零 npm 依赖反代",
"summary": "项目作者。从 0 到 v2.0.x 一路把 Windsurf 的 Cascade gRPC 反代成 OpenAI / Anthropic / Responses 三协议、零 npm 依赖、双皮 dashboard、多账号池 + tier 管理 + 工具协议翻译 + 路径 sanitize / identity neutralize / cascade reuse / drought mode / 后台改密码 / brute-force lockout / 封号检测 + GHCR 自动 release。所有架构决策、安全审计 follow-up、上游迁移跟进、issue triage、PR review 都在这里。"
},
{
"login": "aict666",
"pr": 54,
"weight": "MR",
"weightLabel": "四次出手累计:fingerprint + tier 识别 + redact + Claude Code 工具流(多次 S+ 累积)",
"mergedAt": "2026-04-25",
"title": "fix: bring Claude Code tool-call flow back to Anthropic-equivalent behaviour",
"summary": "aict666 从 #44 到 #54 连续四次出手 #44 #51 #53 #54,每条都是 S+ 级别的根因修复 — 单次贡献已经满 S+,累积四次跨 fingerprint + tier 识别 + sanitize marker + Claude Code 工具流四个不同子系统,质量稳定,是反代架构稳定期最重要的外部贡献者。这条记录(基于 PR #54)整体升级到 MR (Mythic Rare) 反映累积影响。Claude Code 走 Anthropic 协议时 tool_use → tool_result 的 ID 关联、stream 事件序列、工具参数 streaming 拼接全部对齐 Anthropic 原生行为,把之前 \"工具调用偶发 ID mismatch / args 串味\" 一类长尾 bug 一次性铲掉。"
},
{
"login": "baily-zhang",
"pr": 61,
"weight": "LR",
"weightLabel": "四次出手 + Opus 4.7 多模态体验救星(项目级架构跳跃)",
"mergedAt": "2026-04-25",
"title": "fix: 修复 Opus 4.7 Claude Code 上下文爆炸",
"summary": "baily-zhang 累计 #36 #45 #61 #62 四个 PR 跨 fingerprint / dashboard / Opus 多模态 / inline-script regression 四个领域,每条都质量过硬。其中 #61 单条把 Opus 4.7 多模态调用从不可用救回来 — 图片 / 二进制 block 历史只留占位符不嵌 base64、Claude Code 长 SP 压缩去 billing header、Opus 4.7 多模态工具请求禁用 user-message tool fallback、窄范围 cascade reuse + 严格账号绑定避免 retry 全量重放、fingerprint 不再 hash 图片 base64 五件事一次办完。配合 #36 #45 #62 累积已是反代复用机制的实质 maintainer。这条记录升级到 LR (Legendary Rare) 反映项目级架构跳跃。"
},
{
"login": "sandleft",
"pr": 72,
"weight": "S",
"weightLabel": "Codex Responses native tools 完整翻译层",
"mergedAt": "2026-04-27",
"title": "fix: add Codex Responses tool compatibility",
"summary": "我之前那条 #63 已经把 sandleft 标过 S 级,#72 是第二次出手,质量稳。Codex Responses API 的四种非 function tool(custom / namespace / web_search / tool_search)反代之前直接 throw `Unsupported Responses tool type` 把整个请求干 500。这个 PR 不只是丢弃—— flattenResponseTool 把 namespace 用 `__` 分隔扁平化展开成 function,custom 转成单 string `input` 函数,web_search/tool_search 给到 `query` 函数;同时回程通过 `__response_tool` metadata 把原 type / namespace / originalName 还原回 `custom_tool_call` / `web_search_call` / 带 namespace 的 `function_call`。流式分支里 tool name 后到的 chunk 也兜住了。第一轮 PR review 我点出 tool_choice 没翻译 + 流式回转 metadata 透传不全 + 0 测试三个问题,sandleft 全补了,加了 4 条最小测试覆盖关键路径。我 cherry-pick 时叠了一层 UNBRIDGED 集合让 file_search / computer_use_preview / mcp 走 silent drop,web_search_preview 走和 web_search 一样的翻译,最后 fallback 是 warn-and-drop 不再 throw。"
},
{
"login": "ZLin98",
"pr": 80,
"weight": "A",
"weightLabel": "安全加固先行者:LS env allowlist + 跨平台 workspace + dashboard auth 收紧",
"mergedAt": "2026-04-27",
"title": "Harden defaults and add secure startup launcher",
"summary": "#80 一次塞了 16 个文件 700 行的安全加固大改,原 PR 因为面太大不便逐项 review 被关掉,这是当时处置不到位的一条 —— v2.0.12 单独把安全方向最稳的三件事 cherry-pick 进主线,作者署名通过 Co-authored-by trailer 保留。① LS env allowlist:以前直接把整份 process.env 喂给 LS 子进程,AWS_SECRET / GITHUB_TOKEN / 任何 CI secret 都漏出去;新加 `buildLanguageServerEnv` 只白名单 HOME / PATH / LANG / TMPDIR / proxy / SSL trust 八类,剩下全部丢弃,并保留 proxy override 与 /root fallback 两条原行为。② 跨平台 workspace 重置:以前用 `execSync('mkdir -p /tmp/... && rm -rf')` 走 POSIX shell,Windows 直接炸;改用 Node fs `mkdirSync + readdirSync + rmSync`,三大平台一致行为。③ Dashboard auth 收紧:移除 `?pwd=` query string fallback —— logs/stream 早就从 EventSource 迁到 fetch + ReadableStream,query 路径已无客户端在用,留着只会让 password 进 URL 访问日志和浏览器历史。其余 6 项(HOST 默认 127.0.0.1 + ensurePublicAuth、ENABLE_SELF_UPDATE/BATCH_LOGIN/LS_RESTART feature flag 默认全关、`getAccountList` 默认不返完整 apiKey、sessionStorage 替代 localStorage、FORWARD_CALLER_ENV opt-in、scripts/start.js launcher)都是行为变化或 UX 倒退,没并是怕一次性破坏现有 docker / dashboard 部署,但思路完全合理。"
},
{
"login": "Yuuqq",
"pr": 73,
"weight": "B+",
"weightLabel": "Windows 兼容性首位实测人 + 三处稳定性修复",
"mergedAt": "2026-04-26",
"title": "fix: Windows compatibility + 6 bug fixes",
"summary": "Windows 上跑 WindsurfAPI 的第一手反馈。#73 一次扫了 7 处 bug,处置时挑了三处方向干净的落进 commit `44ad502`,作者署名走 Co-authored-by trailer:① `src/sanitize.js` 用 `fileURLToPath(import.meta.url)` 替代手撸 `file://` 转换 —— Windows 上 URL pathname 是 `/e:/path` 形式,老正则把 repo root 解析成空串,所有 sanitize 标记都失效;② `src/server.js` 让 OPTIONS preflight 真返 204 No Content + 显式 CORS 头(含 `anthropic-version`),不再让 OPTIONS fall through 到 JSON 200/404 body;③ `src/conversation-pool.js` 动态扩 META_TAG_NAMES 时给名字做 regex escape,防止用户消息里的 `<example.*>` 之类 tag 名注入元字符破坏整张 strip 表。其余四处(LS health watchdog、HTTP 明文 SEC warning、Windows langserver 路径重排)是因为跟现网部署有交互需要单独验证才没并,不是否定。"
},
{
"login": "abwuge",
"pr": 65,
"weight": "A",
"weightLabel": "GHCR + GitHub Release 自动发布流水线",
"mergedAt": "2026-04-25",
"title": "ci: add release workflow (Docker + GitHub Release)",
"summary": "abwuge 在 #58 nginx + Node import 修复之后又出手 —— 这次直接把 release pipeline 搭起来。`.github/workflows/release.yml` 一条 workflow 触发 git tag 时同步做三件事:构建 multi-arch Docker 镜像 push 到 GHCR、生成 GitHub Release(带自动从 commits 提取的 changelog body)、把 release notes 文件作为 attachment 上传。docker-compose 默认 image 改指 `ghcr.io/dwgx/windsurf-api:latest`,零 npm 依赖的部署链就此打通。后续 v2.0.6 ~ 2.0.11 全部按这个 workflow 在跑,每次 bump 一推 tag 镜像就到位 —— 这是项目从手工 build 到 CI/CD 的关键一跳。"
},
{
"login": "baily-zhang",
"pr": 62,
"weight": "S+",
"weightLabel": "第四次出手 · dashboard inline-script 静态解析 regression 防御",
"mergedAt": "2026-04-25",
"title": "fix(dashboard): 修复 Credits 文案导致控制台空白",
"summary": "commit 60fcd5a 写新 Credits 文案时 Codeium 那个所有格在 inline single-quoted JS string 里被过度转义,整个 dashboard 主脚本 parse fail —— 页面能开但 stats / accounts 等 panel 全空白。几小时内发现修字面 + 新加 test/dashboard-syntax.test.js 用 V8 静态解析 inline script blocks,未来同类 escape / copy 错误下次直接卡 npm test 阶段,比 live UI 砖掉强。"
},
{
"login": "baily-zhang",
"pr": 61,
"weight": "S+",
"weightLabel": "第三次出手 + Opus 4.7 多模态体验救星",
"mergedAt": "2026-04-25",
"title": "fix: 修复 Opus 4.7 Claude Code 上下文爆炸",
"summary": "Claude Code 走 Opus 4.7 + 图片 + tools 时反代把整个 Claude Code system prompt(含 billing header)+ 工具 fallback + 图片 base64 全塞进 user 文本通道,连续图片轮历史指数膨胀触发 Opus 4.7 prompt-injection 拒答。修法五件事:图片 / 二进制 block 在历史里只留占位符不再嵌 base64;Claude Code 长 system prompt 压缩去除 billing header;Opus 4.7 多模态工具请求禁用 user-message tool fallback(proto 层 SectionOverride 已经 carry 工具);Opus 4.7 工具请求启用窄范围 cascade reuse + 严格账号绑定避免 retry 全量重放;fingerprint 不再 hash 图片 base64。回归测试覆盖每一条。和 PR #36 / #45 合起来 baily-zhang 已是反代复用机制的实质 maintainer。"
},
{
"login": "abwuge",
"pr": 58,
"weight": "B+",
"weightLabel": "Docker 部署关键修复 · 首次贡献",
"mergedAt": "2026-04-25",
"title": "fix: nginx shared memory zone + 缺失的 join import",
"summary": "新人首次贡献就解了部署死锁。docker-compose 起来后所有 windsurf 容器(windsurf-lb + 三个 API 副本)持续 Restart:nginx upstream 用了 `server windsurf-api:3003 resolve` 动态解析但没配 `zone`,nginx 直接拒绝启动;Node 这边 src/config.js:38 实际调用 `join()` 但顶部 import 漏写,replica-data-dir 路径 hit 时 ReferenceError 进程崩。两处单行修,docker compose 立刻能起。PR 描述里那句\"~~这么简单的问题,难道没人用 docker 吗?~~\" 本人勿删。"
},
{
"login": "aict666",
"pr": 54,
"weight": "S+",
"weightLabel": "第四次出手 · 三件事打包修",
"mergedAt": "2026-04-25",
"title": "fix: bring Claude Code tool-call flow back to Anthropic-equivalent behaviour",
"summary": "一个 PR 解了三个独立 regression。① tool preamble 从 1600 字符瘦身到 330 字符 —— 老版本的 ### Tool / parameters schema: / ```json {…} 形态正是 Claude Code 自家 system prompt 的指纹,出现在 user 槽位时 Opus 4.7 会判 \"pasted system prompt\" 拒答。② redact 标记升到第 6 代单字符 U+2026 省略号 `…`:第 5 代 redacted internal path 仍被 Opus 塞进 cd redacted internal path && git ... 浪费 2-3 turn;新 marker 0 ASCII word char + 0 shell 元字符 + 训练数据里没 cd … 当真路径的样本,模型不会再当参数用。③ neutralizeCascadeIdentity 加 5 个新 pattern(Cascade is an? AI assistant / As Cascade / Codeium's Cascade / built by Codeium / Cascade's workspace),漏网的 Cascade 自称口吻全部封死。回归套装含 banned-shape regex 锁死未来不会再倒退到含 ASCII 字符的 marker。"
},
{
"login": "aict666",
"pr": 53,
"weight": "S+",
"weightLabel": "第二次出手 · redact marker shell 安全",
"mergedAt": "2026-04-24",
"title": "fix(#24): redact marker must have no shell metacharacters",
"summary": "第 4 代 redact marker `(internal path redacted)` 被 Opus 4.7 塞进 `cd (internal path redacted) && git branch -a`,zsh 把 `(…)` 解析成 glob-qualifier 报 `unknown file attribute: i`,模型见到这种诡异错误就 derail。aict666 的根因诊断细到 zsh 的 glob qualifier 词法 —— 一个文件 API 安全的 marker 不一定是 shell 安全的。换成 `redacted internal path`(无 shell 元字符 / 无路径形状),加两条 banned regex 锁死 marker 形状,未来若再出新 marker test 会卡住。"
},
{
"login": "aict666",
"pr": 51,
"weight": "S+",
"weightLabel": "最高信任级别:root-cause 精准、测试齐全、诊断可追溯",
"mergedAt": "2026-04-24",
"title": "fix: 重写 tool preamble 去 jailbreak 措辞,绕过 Opus 4.7 injection guard",
"summary": "Opus-class 模型走 /v1/messages 时完全不 emit <tool_call>,直接回复\"The pasted content appears to be a prompt-injection attempt\"。root cause 精确到 TOOL_PROTOCOL_HEADER 里三段越狱措辞(IGNORE any earlier / For THIS request only / [Tool-calling context] 栅栏)被 Opus 自己的 injection detector 反杀。重写成中性的 \"The following functions are available for this turn\",保留 <tool_call> 协议合同与 parser 不动,附带 3 条 banned-regex 回归测试防止未来倒退。PR body 可以直接发 Anthropic 论坛。"
},
{
"login": "baily-zhang",
"pr": 45,
"weight": "S",
"weightLabel": "根因修复:上下文重放 / usage 累加",
"mergedAt": "2026-04-24",
"title": "fix: 切断 Cascade 复用时的旧 step 重放(alpha→alphabeta→alphabeta…)",
"summary": "复用 cascade_id 时 GetCascadeTrajectorySteps 每次都从 step 0 拉,结果旧 step 的 assistant text 被重放到新轮里,输出变成 \"alpha\" → \"alphabeta\" → \"alphabetabeta\";usage 也累加成整条 cascade 的总量。修法是把 stepOffset / generatorOffset 随 pool entry 持久化,每次复用时从上次的 offset 继续拉。给 PR #36 之后仍报胡言乱语的用户找回最后一块拼图。"
},
{
"login": "aict666",
"pr": 44,
"weight": "S+",
"weightLabel": "账号 tier 识别的关键修复",
"mergedAt": "2026-04-24",
"title": "fix(auth): 阻止 non-premium 调用把 Pro/Trial 降级为 free",
"summary": "updateCapability 在每次成功 chat 后无条件 inferTier() 覆写 account.tier。inferTier 只认 claude-opus-4.6 / sonnet-4.6 作为 Pro 证据,Pro 账号只要调用 gemini-2.5-flash 或 gpt-4o-mini 一次就被悄悄降级到 free,后续请求按 free 限制,Dashboard 显示 FREE。修法是当 GetUserStatus 已经给过权威 tier(userStatusLastFetched > 0 或 tierManual=true)时跳过 inferTier 回退。probeAccount 原本有手动 restore 工作绕过,chat handler 路径没有,每个真实 API 调用都在偷偷降级账号。"
},
{
"login": "smeinecke",
"pr": 43,
"weight": "A",
"weightLabel": "国际化基础设施贡献者",
"mergedAt": "2026-04-24",
"title": "feat: Dashboard 完整 i18n 国际化",
"summary": "14 个 commit 把所有硬编码中文改成 I18n.t() 调用,补齐 en.json / zh-CN.json 缺键,加 check-i18n.js 扫 JavaScript 里的 I18n.t() key 确保 locale 里都有对应翻译。让 Dashboard 真正能中英双语切换,不是翻了一半的半成品。"
},
{
"login": "baily-zhang",
"pr": 36,
"weight": "S",
"weightLabel": "上下文丢失根因修复者",
"mergedAt": "2026-04-22",
"title": "fix: fingerprint 只 hash 稳定轮,消除 0% 复用命中",
"summary": "Claude Code 每次重构 assistant content(数组 ↔ 字符串 ↔ 含 tool_use blocks)而 system prompt 又含动态项目状态,老 fingerprint 把这两者 hash 进去导致永不匹配。改成只 hash user + tool_result 两类稳定轮,system prompt 通过 CASCADE_REUSE_HASH_SYSTEM=1 opt-in。外加可配置历史 budget(1m 模型更大默认)+ LS_DATA_DIR override。#24 \"胡言乱语\"爆发后的第一块拼图,和 PR #45 合起来算这条线上最彻底的修复。"
},
{
"login": "youfak",
"pr": 26,
"weight": "A+",
"weightLabel": "部署体验贡献者:Docker 零依赖适配",
"mergedAt": "2026-04-22",
"title": "feat: Docker 全套部署 + DATA_DIR + LS 重启兜底",
"summary": "Dockerfile / docker-compose.yml / .dockerignore / .gitattributes 一整套,配 DATA_DIR 配置项把 accounts.json / stats.json / logs/ 等持久化文件统一收敛到可挂载的数据目录。附带修两个 LS 稳定性问题:Windows 宿主机构建时 install-ls.sh 的 CRLF 会导致容器内 set: pipefail 报错;Dashboard 点重启 LS 时若启动失败会把整个 Node 进程打崩。"
},
{
"login": "motto1",
"pr": 20,
"weight": "A",
"weightLabel": "登录取号链路还原",
"mergedAt": "2026-04-21",
"title": "fix(dashboard): 补上 Windsurf 官网实际使用的 Auth1 登录链路",
"summary": "官网可以登但 Dashboard 登录失败 —— 原因是旧 Firebase 路径已不是主链路。逆向补出 /_devin-auth/connections → /_devin-auth/password/login → WindsurfPostAuth → GetOneTimeAuthToken 四步流程,保留旧 Firebase 作为兜底,再顺手加了邮箱/密码批量导入 + 剪贴板读取。"
},
{
"login": "dd373156",
"pr": 1,
"weight": "B+",
"weightLabel": "首位外部 PR 贡献者",
"mergedAt": "2026-04-20",
"title": "fix(models): 让 pro tier 识别到云端动态合并的模型",
"summary": "MODEL_TIER_ACCESS.pro 引用的是 ALL_MODEL_KEYS —— 模块加载时的 Object.keys(MODELS) 快照。mergeCloudModels 启动后加进来的五个 claude-opus-4-7-* 永远不在这个冻结数组里,每个请求都 403 model_not_entitled。一行改成 getter 让每次访问都重新枚举 live MODELS dict。三步 curl 复现写得教科书级。"
},
{
"login": "colin1112a",
"pr": 13,
"weight": "B+",
"weightLabel": "早期代码审查先行者(PR 未合但方向正确)",
"mergedAt": "2026-04-21",
"title": "fix: 一次性审计并提交 15 个安全 / 并发 / 资源管理 bug",
"summary": "系统性扫了一遍仓库提了 CRITICAL/HIGH/MEDIUM 15 条修复建议:XSS 转义、shell 注入防护、10MB body 上限、auth 路由顺序、gRPC 双回调保护、LS pool 并发竞态、HTTP/2 frame 16MB 上限、varint BigInt 支持。PR 因改动面过大未直接合并,但其中多项被后续独立重做。"
}
]
}
|