@viudes/windsurf-api 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,337 @@
1
+ {
2
+ "contributors": [
3
+ {
4
+ "login": "dwgx",
5
+ "pr": 0,
6
+ "weight": "GOD",
7
+ "weightLabel": "项目作者 · 反代架构 / 协议翻译 / 部署 / 全部 release",
8
+ "mergedAt": "2026-04-01",
9
+ "title": "feat: WindsurfAPI — 零 npm 依赖反代",
10
+ "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 都在这里。"
11
+ },
12
+ {
13
+ "login": "aict666",
14
+ "pr": 54,
15
+ "weight": "MR",
16
+ "weightLabel": "四次出手累计:fingerprint + tier 识别 + redact + Claude Code 工具流(多次 S+ 累积)",
17
+ "mergedAt": "2026-04-25",
18
+ "title": "fix: bring Claude Code tool-call flow back to Anthropic-equivalent behaviour",
19
+ "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 一次性铲掉。"
20
+ },
21
+ {
22
+ "login": "baily-zhang",
23
+ "pr": 61,
24
+ "weight": "LR",
25
+ "weightLabel": "四次出手 + Opus 4.7 多模态体验救星(项目级架构跳跃)",
26
+ "mergedAt": "2026-04-25",
27
+ "title": "fix: 修复 Opus 4.7 Claude Code 上下文爆炸",
28
+ "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) 反映项目级架构跳跃。"
29
+ },
30
+ {
31
+ "login": "baily-zhang",
32
+ "pr": 64,
33
+ "weight": "S",
34
+ "weightLabel": "Cascade transport 坏会话恢复 · 又一次根因修复",
35
+ "mergedAt": "2026-04-25",
36
+ "title": "fix: recover from canceled cascade panel transport",
37
+ "summary": "baily-zhang 在 #36 / #45 / #61 / #62 之后又一次根因修复。Claude Code / OpenCode 这类重客户端的部分请求会在 InitializeCascadePanelState 阶段收到 \"The pending stream has been canceled\",随后代理持续 502 —— 账号本身健康,token / 额度 / 模型权限都没问题,坏的是 Cascade / 本地 LS 的 HTTP/2 transport 会话进了坏状态。新加 isCascadeTransportError() 识别 pending stream has been canceled / ECONNRESET / ERR_HTTP2 / session closed / stream closed / panel state;warmup 或聊天阶段一旦命中,resetCascadeTransportState() 主动 closeSessionForPort + 清掉复用中的 workspaceInit 和 sessionId,避免后续请求继续写坏会话;不再吞掉 warmupCascade() 的 transport 失败,避免日志显示初始化成功、实际会话已坏的误导态;把这类错误统一归类成 upstream_transient_error,在多账号重试链路里按瞬态上游错误退避,而不是误判成限流或模型不可用。补了回归测试验证流式错误能保留 upstream_transient_error。108 行新增跨 client.js / chat.js / stream-error.test.js。"
38
+ },
39
+ {
40
+ "login": "sandleft",
41
+ "pr": 72,
42
+ "weight": "S",
43
+ "weightLabel": "Codex Responses native tools 完整翻译层",
44
+ "mergedAt": "2026-04-27",
45
+ "title": "fix: add Codex Responses tool compatibility",
46
+ "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。"
47
+ },
48
+ {
49
+ "login": "ZLin98",
50
+ "pr": 80,
51
+ "weight": "A",
52
+ "weightLabel": "安全加固先行者:LS env allowlist + 跨平台 workspace + dashboard auth 收紧",
53
+ "mergedAt": "2026-04-27",
54
+ "title": "Harden defaults and add secure startup launcher",
55
+ "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 部署,但思路完全合理。"
56
+ },
57
+ {
58
+ "login": "Yuuqq",
59
+ "pr": 73,
60
+ "weight": "B+",
61
+ "weightLabel": "Windows 兼容性首位实测人 + 三处稳定性修复",
62
+ "mergedAt": "2026-04-26",
63
+ "title": "fix: Windows compatibility + 6 bug fixes",
64
+ "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 路径重排)是因为跟现网部署有交互需要单独验证才没并,不是否定。"
65
+ },
66
+ {
67
+ "login": "abwuge",
68
+ "pr": 65,
69
+ "weight": "A",
70
+ "weightLabel": "GHCR + GitHub Release 自动发布流水线",
71
+ "mergedAt": "2026-04-25",
72
+ "title": "ci: add release workflow (Docker + GitHub Release)",
73
+ "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 的关键一跳。"
74
+ },
75
+ {
76
+ "login": "baily-zhang",
77
+ "pr": 62,
78
+ "weight": "S+",
79
+ "weightLabel": "第四次出手 · dashboard inline-script 静态解析 regression 防御",
80
+ "mergedAt": "2026-04-25",
81
+ "title": "fix(dashboard): 修复 Credits 文案导致控制台空白",
82
+ "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 砖掉强。"
83
+ },
84
+ {
85
+ "login": "baily-zhang",
86
+ "pr": 61,
87
+ "weight": "S+",
88
+ "weightLabel": "第三次出手 + Opus 4.7 多模态体验救星",
89
+ "mergedAt": "2026-04-25",
90
+ "title": "fix: 修复 Opus 4.7 Claude Code 上下文爆炸",
91
+ "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。"
92
+ },
93
+ {
94
+ "login": "abwuge",
95
+ "pr": 58,
96
+ "weight": "B+",
97
+ "weightLabel": "Docker 部署关键修复 · 首次贡献",
98
+ "mergedAt": "2026-04-25",
99
+ "title": "fix: nginx shared memory zone + 缺失的 join import",
100
+ "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 吗?~~\" 本人勿删。"
101
+ },
102
+ {
103
+ "login": "aict666",
104
+ "pr": 54,
105
+ "weight": "S+",
106
+ "weightLabel": "第四次出手 · 三件事打包修",
107
+ "mergedAt": "2026-04-25",
108
+ "title": "fix: bring Claude Code tool-call flow back to Anthropic-equivalent behaviour",
109
+ "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。"
110
+ },
111
+ {
112
+ "login": "aict666",
113
+ "pr": 53,
114
+ "weight": "S+",
115
+ "weightLabel": "第二次出手 · redact marker shell 安全",
116
+ "mergedAt": "2026-04-24",
117
+ "title": "fix(#24): redact marker must have no shell metacharacters",
118
+ "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 会卡住。"
119
+ },
120
+ {
121
+ "login": "aict666",
122
+ "pr": 51,
123
+ "weight": "S+",
124
+ "weightLabel": "最高信任级别:root-cause 精准、测试齐全、诊断可追溯",
125
+ "mergedAt": "2026-04-24",
126
+ "title": "fix: 重写 tool preamble 去 jailbreak 措辞,绕过 Opus 4.7 injection guard",
127
+ "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 论坛。"
128
+ },
129
+ {
130
+ "login": "baily-zhang",
131
+ "pr": 45,
132
+ "weight": "S",
133
+ "weightLabel": "根因修复:上下文重放 / usage 累加",
134
+ "mergedAt": "2026-04-24",
135
+ "title": "fix: 切断 Cascade 复用时的旧 step 重放(alpha→alphabeta→alphabeta…)",
136
+ "summary": "复用 cascade_id 时 GetCascadeTrajectorySteps 每次都从 step 0 拉,结果旧 step 的 assistant text 被重放到新轮里,输出变成 \"alpha\" → \"alphabeta\" → \"alphabetabeta\";usage 也累加成整条 cascade 的总量。修法是把 stepOffset / generatorOffset 随 pool entry 持久化,每次复用时从上次的 offset 继续拉。给 PR #36 之后仍报胡言乱语的用户找回最后一块拼图。"
137
+ },
138
+ {
139
+ "login": "aict666",
140
+ "pr": 44,
141
+ "weight": "S+",
142
+ "weightLabel": "账号 tier 识别的关键修复",
143
+ "mergedAt": "2026-04-24",
144
+ "title": "fix(auth): 阻止 non-premium 调用把 Pro/Trial 降级为 free",
145
+ "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 调用都在偷偷降级账号。"
146
+ },
147
+ {
148
+ "login": "smeinecke",
149
+ "pr": 43,
150
+ "weight": "A",
151
+ "weightLabel": "国际化基础设施贡献者",
152
+ "mergedAt": "2026-04-24",
153
+ "title": "feat: Dashboard 完整 i18n 国际化",
154
+ "summary": "14 个 commit 把所有硬编码中文改成 I18n.t() 调用,补齐 en.json / zh-CN.json 缺键,加 check-i18n.js 扫 JavaScript 里的 I18n.t() key 确保 locale 里都有对应翻译。让 Dashboard 真正能中英双语切换,不是翻了一半的半成品。"
155
+ },
156
+ {
157
+ "login": "smeinecke",
158
+ "pr": 90,
159
+ "weight": "B+",
160
+ "weightLabel": "添加账号表单内联代理 · 与批量导入对齐",
161
+ "mergedAt": "2026-04-29",
162
+ "title": "Add proxy support for add account by token",
163
+ "summary": "Account Pool 的\"添加账号\"表单加了可选 proxy 字段(protocol://[user:pass@]host:port 格式),API Key / Auth Token 两种加号方式都能用。之前单账号添加只能先用全局代理建号、再单独给这个号配 per-account proxy,管理多个不同代理的账号时很烦;批量导入早就支持 inline proxy,这次把单账号添加补到 feature parity。复用现有校验链:格式错返 ERR_PROXY_FORMAT_INVALID,私有 IP 默认拦 ERR_PROXY_PRIVATE_IP(除非开了 ALLOW_PRIVATE_PROXY_HOSTS),SOCKS5 带 auth 也能正确解析;空字段则省略 proxy 走全局代理。账号建好即设代理、立刻为该代理 spawn LS。dashboard/api.js + 中英 i18n + index.html,加完即清。"
164
+ },
165
+ {
166
+ "login": "smeinecke",
167
+ "pr": 88,
168
+ "weight": "B+",
169
+ "weightLabel": "本地代理测试开关 · ALLOW_PRIVATE_PROXY_HOSTS",
170
+ "mergedAt": "2026-04-29",
171
+ "title": "feat: add ALLOW_PRIVATE_PROXY_HOSTS config for local proxy testing",
172
+ "summary": "smeinecke 在 #43 i18n 基础设施(A)之后又出手,这次是个 security-aware 的 opt-in 配置。Dashboard 测代理默认走 assertPublicUrlHost() 只允许公网地址 + 全套 SSRF 防护,本地跑 192.168.x.x / 10.x.x.x / localhost 的私有代理就过不去。新加 validateHostFormat() helper 镜像 resolvePublicAddresses() 的结构但去掉私有段拒绝 —— 仍然校验 DNS/IP 格式,只是跳过 SSRF guard;ALLOW_PRIVATE_PROXY_HOSTS=1 时 testProxy() 切到它,默认仍是公网 only 保持安全。config.js + .env.example + setup.sh + 中英 README 一条线全部接上。给跑本地代理的人开了一道明确的、需要显式打开的口子,而不是默认放开。"
173
+ },
174
+ {
175
+ "login": "smeinecke",
176
+ "pr": 89,
177
+ "weight": "B",
178
+ "weightLabel": "登录流 i18n 修复 + 错误码命名标准化",
179
+ "mergedAt": "2026-04-29",
180
+ "title": "Fix missing/broken i18n",
181
+ "summary": "修掉 Dashboard 登录流里 error code 直接以裸串显示的问题 —— 像 ERR_NO_PASSWORD_SET 这类直接糊在 toast 和登录历史里,没翻成人话。这个 PR 把 toasts / result 显示 / login history 三处的错误码全接上 i18n,登录历史表显示翻译后消息 + tooltip 保留原始 code。同时统一错误码命名向已有的 ERR_PROXY_PRIVATE_IP 看齐:ERR_PRIVATE_IP → ERR_PROXY_PRIVATE_IP、ERR_PRIVATE_HOST → ERR_PROXY_PRIVATE_HOST,net-safety.js 和 ssrf.test.js 同步改名,补上缺失的 ERR_PROXY_PRIVATE_HOST 翻译键到 en.json / zh-CN.json。顺手把语言切换按钮的 tooltip 改成动态显示目标语言(Switch to English / 切换到中文)。"
182
+ },
183
+ {
184
+ "login": "baily-zhang",
185
+ "pr": 36,
186
+ "weight": "S",
187
+ "weightLabel": "上下文丢失根因修复者",
188
+ "mergedAt": "2026-04-22",
189
+ "title": "fix: fingerprint 只 hash 稳定轮,消除 0% 复用命中",
190
+ "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 合起来算这条线上最彻底的修复。"
191
+ },
192
+ {
193
+ "login": "youfak",
194
+ "pr": 26,
195
+ "weight": "A+",
196
+ "weightLabel": "部署体验贡献者:Docker 零依赖适配",
197
+ "mergedAt": "2026-04-22",
198
+ "title": "feat: Docker 全套部署 + DATA_DIR + LS 重启兜底",
199
+ "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 进程打崩。"
200
+ },
201
+ {
202
+ "login": "motto1",
203
+ "pr": 20,
204
+ "weight": "A",
205
+ "weightLabel": "登录取号链路还原",
206
+ "mergedAt": "2026-04-21",
207
+ "title": "fix(dashboard): 补上 Windsurf 官网实际使用的 Auth1 登录链路",
208
+ "summary": "官网可以登但 Dashboard 登录失败 —— 原因是旧 Firebase 路径已不是主链路。逆向补出 /_devin-auth/connections → /_devin-auth/password/login → WindsurfPostAuth → GetOneTimeAuthToken 四步流程,保留旧 Firebase 作为兜底,再顺手加了邮箱/密码批量导入 + 剪贴板读取。"
209
+ },
210
+ {
211
+ "login": "dd373156",
212
+ "pr": 1,
213
+ "weight": "B+",
214
+ "weightLabel": "首位外部 PR 贡献者",
215
+ "mergedAt": "2026-04-20",
216
+ "title": "fix(models): 让 pro tier 识别到云端动态合并的模型",
217
+ "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 复现写得教科书级。"
218
+ },
219
+ {
220
+ "login": "colin1112a",
221
+ "pr": 13,
222
+ "weight": "B+",
223
+ "weightLabel": "早期代码审查先行者(PR 未合但方向正确)",
224
+ "mergedAt": "2026-04-21",
225
+ "title": "fix: 一次性审计并提交 15 个安全 / 并发 / 资源管理 bug",
226
+ "summary": "系统性扫了一遍仓库提了 CRITICAL/HIGH/MEDIUM 15 条修复建议:XSS 转义、shell 注入防护、10MB body 上限、auth 路由顺序、gRPC 双回调保护、LS pool 并发竞态、HTTP/2 frame 16MB 上限、varint BigInt 支持。PR 因改动面过大未直接合并,但其中多项被后续独立重做。"
227
+ },
228
+ {
229
+ "login": "you922",
230
+ "pr": 162,
231
+ "weight": "S",
232
+ "weightLabel": "Sticky Session 架构师 + LS 自愈机制",
233
+ "mergedAt": "2026-05-12",
234
+ "title": "feat: sticky session + auto-restart crashed LS",
235
+ "summary": "两个 PR 一起出手。#162 从零搭建了 sticky session 机制:(callerKey, modelKey) → accountId 绑定 + 可配 TTL + LRU eviction,让多轮对话留在同一个上游账号上避免 cascade_id 跨账号失效。#163 给 LS 崩溃加了指数退避自动重启,process exit / SIGTERM / unresponsive 三种场景都兜住,防止单个 LS 挂掉拖垮整个账号池。另外在 #164 提供了源码级根因分析指出 SectionOverrideConfig 在 NO_TOOL 模式下抑制 tool_calling_section 的架构性问题。"
236
+ },
237
+ {
238
+ "login": "you922",
239
+ "pr": 163,
240
+ "weight": "A",
241
+ "weightLabel": "LS 崩溃自愈机制 · 指数退避自动重启",
242
+ "mergedAt": "2026-05-12",
243
+ "title": "feat: auto-restart crashed language server with exponential backoff",
244
+ "summary": "和 #162 sticky session 一起出手的第二个 PR(#162 那条已经把 you922 标过 S)。LS 二进制偶发因内存压力 / 上游协议变更 / 瞬态错误崩掉,老逻辑只 log 崩溃 + 清理,后续所有打到这个 LS 的请求一路 ECONNRESET / ERR_HTTP2_CONNECT 挂着,直到手动重启或下个请求触发 ensureLs()(#157 报的就是这个)。新加 scheduleLsRestart() 挂进 proc.on('exit'):指数退避 1s→2s→4s→8s(base delay 可配),max 3 次重试封死 permanent error 的无限循环,per-key _restartAttempts Map 防重复定时器,setTimeout 用 .unref() 不阻塞 Node 进程退出,再加 _intentionalShutdown Set 让 stopLanguageServer / restartLsForProxy 的主动关闭不会误触自动重启,getRestartStats() 暴露重启计数给监控。LS_AUTO_RESTART=0 可回退旧行为。让单个 LS 挂掉不再拖垮整个账号池。"
245
+ },
246
+ {
247
+ "login": "Fermiz",
248
+ "pr": 181,
249
+ "weight": "A+",
250
+ "weightLabel": "Cascade 复用优化 + HTTPS 代理层",
251
+ "mergedAt": "2026-05-22",
252
+ "title": "feat: Cascade reuse optimization + HTTPS proxy + configurable pool size",
253
+ "summary": "三件事一个 PR:① 单用户场景下 Cascade 复用优化 — 跳过多余的账号轮询直接命中唯一账号;② HTTPS 代理中间层 (https-proxy.js) 让反代本身也能跑 TLS;③ conversation-pool 大小可配置化。323 行新增,改动集中在 chat.js 和 conversation-pool.js 核心路径。"
254
+ },
255
+ {
256
+ "login": "linqichenggg",
257
+ "pr": 175,
258
+ "weight": "A",
259
+ "weightLabel": "跨平台 LS 路径统一",
260
+ "mergedAt": "2026-05-12",
261
+ "title": "fix: align language server paths across platforms",
262
+ "summary": "Windows / macOS / Linux 三平台的 LS 二进制路径、数据目录、安装脚本全部对齐。之前 macOS 用 ~/Library 路径但 install-ls.sh 写的是 Linux 路径,Windows 更是直接找不到 LS。统一到 config.js 集中管理 + platform-ls-paths.test.js 覆盖三平台断言。"
263
+ },
264
+ {
265
+ "login": "lauvww",
266
+ "pr": 182,
267
+ "weight": "A",
268
+ "weightLabel": "Dashboard 批量导入重构",
269
+ "mergedAt": "2026-05-21",
270
+ "title": "feat: improve dashboard batch import parsing",
271
+ "summary": "重写了 Dashboard 的账号批量导入解析器 (import-parser.js):支持 JSON / CSV / 纯文本多种格式混合粘贴,自动检测分隔符,容错处理格式不一致的行。588 行新增含完整测试覆盖和中英双语 i18n。"
272
+ },
273
+ {
274
+ "login": "ucloudnb666",
275
+ "pr": 184,
276
+ "weight": "B+",
277
+ "weightLabel": "Astraflow 第三方提供商接入",
278
+ "mergedAt": "2026-05-21",
279
+ "title": "feat: add Astraflow provider support",
280
+ "summary": "让 WindsurfAPI 支持 Astraflow 作为第三方提供商路由。config.js 新增 ASTRAFLOW_API_KEY 配置项,models.js 注册 astraflow/* 模型前缀,30 行精准修改。"
281
+ },
282
+ {
283
+ "login": "datfooldive",
284
+ "pr": 173,
285
+ "weight": "A",
286
+ "weightLabel": "Dashboard UI 大扫除",
287
+ "mergedAt": "2026-05-12",
288
+ "title": "refactor(dashboard): UI cleanup",
289
+ "summary": "Dashboard 前端大重构:1177 行新增 / 465 行删除,全部集中在 index.html。清理了冗余样式、统一了组件风格、优化了卡片布局和响应式适配。"
290
+ },
291
+ {
292
+ "login": "The-five-stooges",
293
+ "pr": 188,
294
+ "weight": "S",
295
+ "weightLabel": "Sticky Session 流式路径修复 + 多用户隔离",
296
+ "mergedAt": "2026-06-02",
297
+ "title": "fix: sticky session binding breaks on streaming path + multi-user isolation with body.user",
298
+ "summary": "修复 sticky session 在流式路径的两个关键问题:① waitForAccount 在流式 retry 路径缺少 callerKey 参数,导致 sticky 绑定在流式请求中不生效;② 新增 body.user 多用户隔离机制,允许不同用户在共享 API key 下保持独立的 session 绑定。配套添加了 stickyNoFallback 开关(绑定账号失败时不回退到其他账号)、stickyBindByUserOnly 开关(忽略模型维度按 user 绑定)、以及 Dashboard 配置面板。320 行新增,涉及 sticky-session / auth / chat / messages / runtime-config / dashboard 六个子系统。"
299
+ },
300
+ {
301
+ "login": "andya1lan",
302
+ "pr": 192,
303
+ "weight": "B+",
304
+ "weightLabel": "升级脚本 LS 下载链修复 + macOS 兼容性",
305
+ "mergedAt": "2026-06-05",
306
+ "title": "fix(update): install LS via install-ls sources",
307
+ "summary": "PR #192 把 update.sh 的 LS binary 更新路径从旧的硬编码 WindsurfAPI release URL 收敛到 install-ls.sh:WindsurfAPI release → Windsurf 桌面 LS release → Exafunction fallback。这样一键更新、Dashboard LS 更新、手动 install-ls.sh 三条路径使用同一套下载链和 atomic rename 行为,避免旧 release asset 漂移和 live binary file-busy 问题。同时把 update.sh 读取 .env 里的 LS_BINARY_PATH 从 GNU-only grep -P 改成 awk,macOS BSD grep 环境也能跑。"
308
+ },
309
+ {
310
+ "login": "MatrixNeoKozak",
311
+ "pr": 195,
312
+ "weight": "B",
313
+ "weightLabel": "Dashboard API 错误语义修复",
314
+ "mergedAt": "2026-06-22",
315
+ "title": "fix: return 400 for malformed JSON in dashboard API",
316
+ "summary": "PR #195 修掉 dashboard API malformed JSON 仍按 200 返回的问题。改动很小,但错误语义重要:前端、脚本和自动化调用方现在能用 HTTP status 正确区分请求体格式错误,而不是从一个成功响应里猜 `ok:false`。配套跑过 dashboard API 和 cache-control 测试,适合作为小型、聚焦、可验证 bugfix 的样板。"
317
+ },
318
+ {
319
+ "login": "brandonedley",
320
+ "pr": 201,
321
+ "weight": "A",
322
+ "weightLabel": "模型目录更新 + 文档/测试同步",
323
+ "mergedAt": "2026-06-22",
324
+ "title": "feat: add GLM 5.2 and Kimi K2.7 catalog entries",
325
+ "summary": "PR #201 把 GLM 5.2 和 Kimi K2.7 补进模型 catalog,同时同步 README、英文 README、package description、模型文档生成检查和 catalog correctness 测试。模型新增最怕只改一处导致 dashboard、docs、测试互相漂移,这个 PR 把代码、文档和校验一起补齐,是后续普通模型 catalog 更新可以参考的提交形态。"
326
+ },
327
+ {
328
+ "login": "lovivi",
329
+ "pr": 204,
330
+ "weight": "B+",
331
+ "weightLabel": "glm-5.2 工具协议方言探针 · 首次贡献",
332
+ "mergedAt": "2026-06-28",
333
+ "title": "fix(tool-emulation): use gpt_native dialect for glm-5.2",
334
+ "summary": "首次贡献就解了 glm-5.2 的工具调用哑火。glm 系列默认走 glm47 那套 XML tool-call 标记,但 glm-5.2 直接无视标记、用纯文本作答,工具调用根本 emit 不出来。lovivi 在 pickToolDialect 里给 glm-5.2 和它的 glm-5-2-* SKU 别名单独切到 gpt_native 的 function_call JSON dialect —— 这套是模型稳定 emit、parser 也能正确解析的;老 GLM 维持 glm47 不动,没经验证不乱动。顺手加了 WINDSURFAPI_FORCE_TOOL_DIALECT 环境变量(限定 glm47/openai_json_xml/kimi_k2/gpt_native 四值)方便测试时强制方言。10 行精准改动,是新模型上线后\"工具协议方言对不上\"这类长尾问题的标准排查范式。"
335
+ }
336
+ ]
337
+ }