docs: sync release credit surfaces

This commit is contained in:
Hunter B
2026-05-31 17:43:46 -07:00
parent 7eb740bd86
commit 6f295e9961
15 changed files with 255 additions and 98 deletions
+8
View File
@@ -112,6 +112,14 @@ Thanks to contributors whose PRs landed or were harvested in this release:
**@hoclaptrinh33** (#2358), **@hoclaptrinh33** (#2358),
and **@BryonGo** (#2437). and **@BryonGo** (#2437).
Thanks also to reporters and verification helpers whose issues, patches,
screenshots, logs, or retest requests shaped this release: **@buko** (#2359,
#2360, #2369, #2469), **@yyyCode**, **@gaslebinh-glitch**, **@Dr3259**,
**@lpeng1711694086-lang**, **@VerrPower**, **@yan-zay**, **@jretz**,
**@Neo-millunnium**, **@caeserchen**, **@T-Phuong-Nguyen**, **@zhyuzhyu**,
**@0gl20shk0sbt36**, **@hatakes**, **@goodvecn-dev**, **@bevis-wong**,
**@PurplePulse**, and **@nbiish**.
## [0.8.47] - 2026-05-26 ## [0.8.47] - 2026-05-26
### Added ### Added
+4
View File
@@ -422,6 +422,10 @@ description: DeepSeek にカスタムワークフローを実行させたいと
このプロジェクトは、増え続けるコントリビューターのコミュニティから助けを得て出荷されています: このプロジェクトは、増え続けるコントリビューターのコミュニティから助けを得て出荷されています:
v0.8.48 でマージまたは取り込まれた貢献者: **[@cy2311](https://github.com/cy2311)**、**[@LING71671](https://github.com/LING71671)**、**[@axobase001](https://github.com/axobase001)**、**[@dzyuan](https://github.com/dzyuan)**、**[@mvanhorn](https://github.com/mvanhorn)**、**[@malsony](https://github.com/malsony)**、**[@gaord](https://github.com/gaord)**、**[@yuanchenglu](https://github.com/yuanchenglu)**、**[@idling11](https://github.com/idling11)**、**[@h3c-hexin](https://github.com/h3c-hexin)**、**[@AdityaVG13](https://github.com/AdityaVG13)**、**[@Sskift](https://github.com/Sskift)**、**[@cyq1017](https://github.com/cyq1017)**、**[@HUQIANTAO](https://github.com/HUQIANTAO)**、**[@New2Niu](https://github.com/New2Niu)**、**[@AiurArtanis](https://github.com/AiurArtanis)**、**[@Lee-take](https://github.com/Lee-take)**、**[@nightt5879](https://github.com/nightt5879)**、**[@AresNing](https://github.com/AresNing)**、**[@AccMoment](https://github.com/AccMoment)**、**[@reidliu41](https://github.com/reidliu41)**、**[@aboimpinto](https://github.com/aboimpinto)**、**[@zhuangbiaowei](https://github.com/zhuangbiaowei)**、**[@donglovejava](https://github.com/donglovejava)**、**[@hongqitai](https://github.com/hongqitai)**、**[@zlh124](https://github.com/zlh124)**、**[@encyc](https://github.com/encyc)**、**[@Implementist](https://github.com/Implementist)**、**[@lihuan215](https://github.com/lihuan215)**、**[@LeoAlex0](https://github.com/LeoAlex0)**、**[@jimmyzhuu](https://github.com/jimmyzhuu)**、**[@rockyzhang](https://github.com/rockyzhang)**、**[@mo-vic](https://github.com/mo-vic)**、**[@hufanexplore](https://github.com/hufanexplore)**、**[@hoclaptrinh33](https://github.com/hoclaptrinh33)**、**[@BryonGo](https://github.com/BryonGo)**。
報告、再現手順、検証で v0.8.48 を支えてくれた **[@buko](https://github.com/buko)**、**[@yyyCode](https://github.com/yyyCode)**、**[@gaslebinh-glitch](https://github.com/gaslebinh-glitch)**、**[@Dr3259](https://github.com/Dr3259)**、**[@lpeng1711694086-lang](https://github.com/lpeng1711694086-lang)**、**[@VerrPower](https://github.com/VerrPower)**、**[@yan-zay](https://github.com/yan-zay)**、**[@jretz](https://github.com/jretz)**、**[@Neo-millunnium](https://github.com/Neo-millunnium)**、**[@caeserchen](https://github.com/caeserchen)**、**[@T-Phuong-Nguyen](https://github.com/T-Phuong-Nguyen)**、**[@zhyuzhyu](https://github.com/zhyuzhyu)**、**[@0gl20shk0sbt36](https://github.com/0gl20shk0sbt36)**、**[@hatakes](https://github.com/hatakes)**、**[@goodvecn-dev](https://github.com/goodvecn-dev)**、**[@bevis-wong](https://github.com/bevis-wong)**、**[@PurplePulse](https://github.com/PurplePulse)**、**[@nbiish](https://github.com/nbiish)** にも感謝します。
- **[merchloubna70-dot](https://github.com/merchloubna70-dot)** — 機能、修正、VS Code 拡張のスキャフォールドにまたがる 28 件の PR (#645#681) - **[merchloubna70-dot](https://github.com/merchloubna70-dot)** — 機能、修正、VS Code 拡張のスキャフォールドにまたがる 28 件の PR (#645#681)
- **[WyxBUPT-22](https://github.com/WyxBUPT-22)** — 表、太字/斜体、水平線の Markdown レンダリング (#579) - **[WyxBUPT-22](https://github.com/WyxBUPT-22)** — 表、太字/斜体、水平線の Markdown レンダリング (#579)
- **[loongmiaow-pixel](https://github.com/loongmiaow-pixel)** — Windows と中国向けインストールドキュメント (#578) - **[loongmiaow-pixel](https://github.com/loongmiaow-pixel)** — Windows と中国向けインストールドキュメント (#578)
+11
View File
@@ -705,6 +705,17 @@ This project ships with help from a growing community of contributors:
- **[hongqitai](https://github.com/hongqitai)** — state schema parent-entry support and clippy/fmt cleanup (#2308, #2432) - **[hongqitai](https://github.com/hongqitai)** — state schema parent-entry support and clippy/fmt cleanup (#2308, #2432)
- **[BryonGo](https://github.com/BryonGo)** — effective-model compaction budgeting fix (#2437) - **[BryonGo](https://github.com/BryonGo)** — effective-model compaction budgeting fix (#2437)
Reports, repros, and verification that shaped v0.8.48 also deserve visible
credit: **[@buko](https://github.com/buko)**, **[@yyyCode](https://github.com/yyyCode)**,
**[@gaslebinh-glitch](https://github.com/gaslebinh-glitch)**, **[@Dr3259](https://github.com/Dr3259)**,
**[@lpeng1711694086-lang](https://github.com/lpeng1711694086-lang)**, **[@VerrPower](https://github.com/VerrPower)**,
**[@yan-zay](https://github.com/yan-zay)**, **[@jretz](https://github.com/jretz)**,
**[@Neo-millunnium](https://github.com/Neo-millunnium)**, **[@caeserchen](https://github.com/caeserchen)**,
**[@T-Phuong-Nguyen](https://github.com/T-Phuong-Nguyen)**, **[@zhyuzhyu](https://github.com/zhyuzhyu)**,
**[@0gl20shk0sbt36](https://github.com/0gl20shk0sbt36)**, **[@hatakes](https://github.com/hatakes)**,
**[@goodvecn-dev](https://github.com/goodvecn-dev)**, **[@bevis-wong](https://github.com/bevis-wong)**,
**[@PurplePulse](https://github.com/PurplePulse)**, and **[@nbiish](https://github.com/nbiish)**.
--- ---
## Contributing ## Contributing
+4
View File
@@ -509,6 +509,10 @@ Lịch sử cập nhật chi tiết: [CHANGELOG.md](CHANGELOG.md).
Dự án này được phát triển và vận hành trơn tru với sự đóng góp của cộng đồng các nhà phát triển ngày càng lớn mạnh: Dự án này được phát triển và vận hành trơn tru với sự đóng góp của cộng đồng các nhà phát triển ngày càng lớn mạnh:
Các đóng góp đã được merge hoặc được harvest trong v0.8.48: **[@cy2311](https://github.com/cy2311)**, **[@LING71671](https://github.com/LING71671)**, **[@axobase001](https://github.com/axobase001)**, **[@dzyuan](https://github.com/dzyuan)**, **[@mvanhorn](https://github.com/mvanhorn)**, **[@malsony](https://github.com/malsony)**, **[@gaord](https://github.com/gaord)**, **[@yuanchenglu](https://github.com/yuanchenglu)**, **[@idling11](https://github.com/idling11)**, **[@h3c-hexin](https://github.com/h3c-hexin)**, **[@AdityaVG13](https://github.com/AdityaVG13)**, **[@Sskift](https://github.com/Sskift)**, **[@cyq1017](https://github.com/cyq1017)**, **[@HUQIANTAO](https://github.com/HUQIANTAO)**, **[@New2Niu](https://github.com/New2Niu)**, **[@AiurArtanis](https://github.com/AiurArtanis)**, **[@Lee-take](https://github.com/Lee-take)**, **[@nightt5879](https://github.com/nightt5879)**, **[@AresNing](https://github.com/AresNing)**, **[@AccMoment](https://github.com/AccMoment)**, **[@reidliu41](https://github.com/reidliu41)**, **[@aboimpinto](https://github.com/aboimpinto)**, **[@zhuangbiaowei](https://github.com/zhuangbiaowei)**, **[@donglovejava](https://github.com/donglovejava)**, **[@hongqitai](https://github.com/hongqitai)**, **[@zlh124](https://github.com/zlh124)**, **[@encyc](https://github.com/encyc)**, **[@Implementist](https://github.com/Implementist)**, **[@lihuan215](https://github.com/lihuan215)**, **[@LeoAlex0](https://github.com/LeoAlex0)**, **[@jimmyzhuu](https://github.com/jimmyzhuu)**, **[@rockyzhang](https://github.com/rockyzhang)**, **[@mo-vic](https://github.com/mo-vic)**, **[@hufanexplore](https://github.com/hufanexplore)**, **[@hoclaptrinh33](https://github.com/hoclaptrinh33)** và **[@BryonGo](https://github.com/BryonGo)**.
Xin cảm ơn các báo cáo, bước tái hiện lỗi và xác minh từ **[@buko](https://github.com/buko)**, **[@yyyCode](https://github.com/yyyCode)**, **[@gaslebinh-glitch](https://github.com/gaslebinh-glitch)**, **[@Dr3259](https://github.com/Dr3259)**, **[@lpeng1711694086-lang](https://github.com/lpeng1711694086-lang)**, **[@VerrPower](https://github.com/VerrPower)**, **[@yan-zay](https://github.com/yan-zay)**, **[@jretz](https://github.com/jretz)**, **[@Neo-millunnium](https://github.com/Neo-millunnium)**, **[@caeserchen](https://github.com/caeserchen)**, **[@T-Phuong-Nguyen](https://github.com/T-Phuong-Nguyen)**, **[@zhyuzhyu](https://github.com/zhyuzhyu)**, **[@0gl20shk0sbt36](https://github.com/0gl20shk0sbt36)**, **[@hatakes](https://github.com/hatakes)**, **[@goodvecn-dev](https://github.com/goodvecn-dev)**, **[@bevis-wong](https://github.com/bevis-wong)**, **[@PurplePulse](https://github.com/PurplePulse)** và **[@nbiish](https://github.com/nbiish)** đã giúp định hình v0.8.48.
- **[merchloubna70-dot](https://github.com/merchloubna70-dot)** — Đóng góp 28 PR bao gồm tính năng mới, sửa lỗi và dựng sẵn extension cho VS Code (#645#681) - **[merchloubna70-dot](https://github.com/merchloubna70-dot)** — Đóng góp 28 PR bao gồm tính năng mới, sửa lỗi và dựng sẵn extension cho VS Code (#645#681)
- **[WyxBUPT-22](https://github.com/WyxBUPT-22)** — Xây dựng trình kết xuất Markdown hỗ trợ bảng biểu, chữ đậm/nghiêng và đường kẻ ngang (#579) - **[WyxBUPT-22](https://github.com/WyxBUPT-22)** — Xây dựng trình kết xuất Markdown hỗ trợ bảng biểu, chữ đậm/nghiêng và đường kẻ ngang (#579)
- **[loongmiaow-pixel](https://github.com/loongmiaow-pixel)** — Tài liệu cài đặt cho Windows và Trung Quốc (#578) - **[loongmiaow-pixel](https://github.com/loongmiaow-pixel)** — Tài liệu cài đặt cho Windows và Trung Quốc (#578)
+4
View File
@@ -537,6 +537,10 @@ description: 当 DeepSeek 需要遵循我的自定义工作流时使用这个技
本项目由不断壮大的贡献者社区共同打造: 本项目由不断壮大的贡献者社区共同打造:
v0.8.48 合并或吸收的贡献者包括:**[@cy2311](https://github.com/cy2311)**、**[@LING71671](https://github.com/LING71671)**、**[@axobase001](https://github.com/axobase001)**、**[@dzyuan](https://github.com/dzyuan)**、**[@mvanhorn](https://github.com/mvanhorn)**、**[@malsony](https://github.com/malsony)**、**[@gaord](https://github.com/gaord)**、**[@yuanchenglu](https://github.com/yuanchenglu)**、**[@idling11](https://github.com/idling11)**、**[@h3c-hexin](https://github.com/h3c-hexin)**、**[@AdityaVG13](https://github.com/AdityaVG13)**、**[@Sskift](https://github.com/Sskift)**、**[@cyq1017](https://github.com/cyq1017)**、**[@HUQIANTAO](https://github.com/HUQIANTAO)**、**[@New2Niu](https://github.com/New2Niu)**、**[@AiurArtanis](https://github.com/AiurArtanis)**、**[@Lee-take](https://github.com/Lee-take)**、**[@nightt5879](https://github.com/nightt5879)**、**[@AresNing](https://github.com/AresNing)**、**[@AccMoment](https://github.com/AccMoment)**、**[@reidliu41](https://github.com/reidliu41)**、**[@aboimpinto](https://github.com/aboimpinto)**、**[@zhuangbiaowei](https://github.com/zhuangbiaowei)**、**[@donglovejava](https://github.com/donglovejava)**、**[@hongqitai](https://github.com/hongqitai)**、**[@zlh124](https://github.com/zlh124)**、**[@encyc](https://github.com/encyc)**、**[@Implementist](https://github.com/Implementist)**、**[@lihuan215](https://github.com/lihuan215)**、**[@LeoAlex0](https://github.com/LeoAlex0)**、**[@jimmyzhuu](https://github.com/jimmyzhuu)**、**[@rockyzhang](https://github.com/rockyzhang)**、**[@mo-vic](https://github.com/mo-vic)**、**[@hufanexplore](https://github.com/hufanexplore)**、**[@hoclaptrinh33](https://github.com/hoclaptrinh33)** 和 **[@BryonGo](https://github.com/BryonGo)**。
同样感谢提供报告、复现和验证的 **[@buko](https://github.com/buko)**、**[@yyyCode](https://github.com/yyyCode)**、**[@gaslebinh-glitch](https://github.com/gaslebinh-glitch)**、**[@Dr3259](https://github.com/Dr3259)**、**[@lpeng1711694086-lang](https://github.com/lpeng1711694086-lang)**、**[@VerrPower](https://github.com/VerrPower)**、**[@yan-zay](https://github.com/yan-zay)**、**[@jretz](https://github.com/jretz)**、**[@Neo-millunnium](https://github.com/Neo-millunnium)**、**[@caeserchen](https://github.com/caeserchen)**、**[@T-Phuong-Nguyen](https://github.com/T-Phuong-Nguyen)**、**[@zhyuzhyu](https://github.com/zhyuzhyu)**、**[@0gl20shk0sbt36](https://github.com/0gl20shk0sbt36)**、**[@hatakes](https://github.com/hatakes)**、**[@goodvecn-dev](https://github.com/goodvecn-dev)**、**[@bevis-wong](https://github.com/bevis-wong)**、**[@PurplePulse](https://github.com/PurplePulse)** 和 **[@nbiish](https://github.com/nbiish)**。
- **[merchloubna70-dot](https://github.com/merchloubna70-dot)** — 28 个 PR,涵盖功能、修复和 VS Code 扩展基础架构 (#645#681) - **[merchloubna70-dot](https://github.com/merchloubna70-dot)** — 28 个 PR,涵盖功能、修复和 VS Code 扩展基础架构 (#645#681)
- **[WyxBUPT-22](https://github.com/WyxBUPT-22)** — Markdown 表格、粗体/斜体和水平线渲染 (#579) - **[WyxBUPT-22](https://github.com/WyxBUPT-22)** — Markdown 表格、粗体/斜体和水平线渲染 (#579)
- **[loongmiaow-pixel](https://github.com/loongmiaow-pixel)** — Windows + 中国安装文档 (#578) - **[loongmiaow-pixel](https://github.com/loongmiaow-pixel)** — Windows + 中国安装文档 (#578)
+8
View File
@@ -112,6 +112,14 @@ Thanks to contributors whose PRs landed or were harvested in this release:
**@hoclaptrinh33** (#2358), **@hoclaptrinh33** (#2358),
and **@BryonGo** (#2437). and **@BryonGo** (#2437).
Thanks also to reporters and verification helpers whose issues, patches,
screenshots, logs, or retest requests shaped this release: **@buko** (#2359,
#2360, #2369, #2469), **@yyyCode**, **@gaslebinh-glitch**, **@Dr3259**,
**@lpeng1711694086-lang**, **@VerrPower**, **@yan-zay**, **@jretz**,
**@Neo-millunnium**, **@caeserchen**, **@T-Phuong-Nguyen**, **@zhyuzhyu**,
**@0gl20shk0sbt36**, **@hatakes**, **@goodvecn-dev**, **@bevis-wong**,
**@PurplePulse**, and **@nbiish**.
## [0.8.47] - 2026-05-26 ## [0.8.47] - 2026-05-26
### Added ### Added
+14 -3
View File
@@ -10,14 +10,17 @@ publish-crates), see [`RELEASE_RUNBOOK.md`](RELEASE_RUNBOOK.md).
## 1. CHANGELOG entry exists for the version ## 1. CHANGELOG entry exists for the version
- [ ] `CHANGELOG.md` has a `## [X.Y.Z] - YYYY-MM-DD` heading at the top - [ ] `CHANGELOG.md` has a `## [X.Y.Z] - YYYY-MM-DD` heading at the top
- [ ] The entry credits every external contributor whose commit lands in this - [ ] The entry credits every external contributor, harvested PR author,
version. Get the list with: linked issue reporter, reproduction/log provider, reviewer, and
verification helper whose work materially shaped this version. Get the
commit list with:
``` ```
git log vPREV..HEAD --no-merges --format="%h %an <%ae> %s" \ git log vPREV..HEAD --no-merges --format="%h %an <%ae> %s" \
| grep -v '<your-email@…>' | grep -v '<your-email@…>'
``` ```
For each contributor, link both their display name and (when known) For each contributor, link both their display name and (when known)
`@github-handle`. `@github-handle`. Then inspect linked issues and harvested PRs so
reporters/helpers are not lost just because they did not author commits.
- [ ] The entry uses the Keep a Changelog headers — `Added`, `Changed`, - [ ] The entry uses the Keep a Changelog headers — `Added`, `Changed`,
`Fixed`, `Security`, `Removed`, `Deprecated`. Add `Known issues` only `Fixed`, `Security`, `Removed`, `Deprecated`. Add `Known issues` only
if there is something material the user must work around. if there is something material the user must work around.
@@ -84,6 +87,12 @@ Run, in order, from the repo root:
- [ ] `git push origin vX.Y.Z` - [ ] `git push origin vX.Y.Z`
- [ ] The `release.yml` workflow has built and uploaded artifacts to the - [ ] The `release.yml` workflow has built and uploaded artifacts to the
GitHub release for this tag. GitHub release for this tag.
- [ ] The live GitHub Release body has its own `## Contributors` or
`## Credits` section; do not rely on "see CHANGELOG" alone. Verify with:
```
gh release view vX.Y.Z --repo Hmbown/CodeWhale --json body \
--jq '.body | test("## (Contributors|Credits)")'
```
- [ ] `npm view codewhale@X.Y.Z version codewhaleBinaryVersion --json` - [ ] `npm view codewhale@X.Y.Z version codewhaleBinaryVersion --json`
reports the new version on the npm registry. reports the new version on the npm registry.
- [ ] `crates.io` has the new version (or the `publish-crates.sh` job has - [ ] `crates.io` has the new version (or the `publish-crates.sh` job has
@@ -94,6 +103,8 @@ Run, in order, from the repo root:
- [ ] Edit the GitHub release notes to expand any CVE-style or attack - [ ] Edit the GitHub release notes to expand any CVE-style or attack
details that were intentionally omitted from the PR title/body. details that were intentionally omitted from the PR title/body.
- [ ] Re-run the GitHub Release body check after any release-workflow rerun;
workflows can overwrite notes and accidentally remove contributor credit.
- [ ] Note any deferred items in the next release's tracking issue. - [ ] Note any deferred items in the next release's tracking issue.
- [ ] Close any issues that this release fixed. - [ ] Close any issues that this release fixed.
+22 -20
View File
@@ -39,6 +39,7 @@ npm install -g codewhale
# Cargo (needs Rust 1.88+) # Cargo (needs Rust 1.88+)
cargo install codewhale-cli --locked cargo install codewhale-cli --locked
cargo install codewhale-tui --locked
# Homebrew (macOS) # Homebrew (macOS)
brew tap Hmbown/deepseek-tui && brew install deepseek-tui brew tap Hmbown/deepseek-tui && brew install deepseek-tui
@@ -47,7 +48,7 @@ brew tap Hmbown/deepseek-tui && brew install deepseek-tui
# https://github.com/Hmbown/CodeWhale/releases`} # https://github.com/Hmbown/CodeWhale/releases`}
</pre> </pre>
<p> <p>
Run <code className="inline">codewhale</code> to start. First run creates <code className="inline">~/.deepseek/</code> automatically. Run <code className="inline">codewhale</code> to start. First run creates <code className="inline">~/.codewhale/</code> automatically. Legacy <code className="inline">~/.deepseek/</code> is still read as a compatibility fallback.
See the <Link href="/install" className="body-link">full install guide</Link> for China mirrors, Docker, and troubleshooting. See the <Link href="/install" className="body-link">full install guide</Link> for China mirrors, Docker, and troubleshooting.
</p> </p>
</> </>
@@ -72,7 +73,7 @@ brew tap Hmbown/deepseek-tui && brew install deepseek-tui
<> <>
Yes. CodeWhale is the new name for what was previously called DeepSeek TUI. Yes. CodeWhale is the new name for what was previously called DeepSeek TUI.
The canonical command is now <code className="inline">codewhale</code>. Legacy <code className="inline">deepseek</code> and <code className="inline">deepseek-tui</code> commands remain as compatibility shims they still work. The canonical command is now <code className="inline">codewhale</code>. Legacy <code className="inline">deepseek</code> and <code className="inline">deepseek-tui</code> commands remain as compatibility shims they still work.
Config lives at <code className="inline">~/.deepseek/</code>. <code className="inline">DEEPSEEK_*</code> env vars continue to work. Config lives at <code className="inline">~/.codewhale/</code>. Legacy <code className="inline">~/.deepseek/</code> config is still read as a compatibility fallback, and <code className="inline">DEEPSEEK_*</code> env vars continue to work.
DeepSeek is not deprecated. The rename reflects CodeWhale's broader mission as the agentic terminal for open models across providers, not a narrowing away from DeepSeek. DeepSeek is not deprecated. The rename reflects CodeWhale's broader mission as the agentic terminal for open models across providers, not a narrowing away from DeepSeek.
</> </>
), ),
@@ -90,7 +91,7 @@ export DEEPSEEK_API_KEY=sk-...
codewhale auth set --provider deepseek --api-key sk-... codewhale auth set --provider deepseek --api-key sk-...
# Method 3: config.toml # Method 3: config.toml
# Add to ~/.deepseek/config.toml: # Add to ~/.codewhale/config.toml:
api_key = "sk-..." api_key = "sk-..."
# Check what's active: # Check what's active:
@@ -113,11 +114,11 @@ codewhale doctor # full connectivity check`}
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft mb-3"> <ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft mb-3">
<li><strong>DeepSeek</strong> — first-class, native API. Reasoning streaming, cache metrics, thinking effort control.</li> <li><strong>DeepSeek</strong> — first-class, native API. Reasoning streaming, cache metrics, thinking effort control.</li>
<li><strong>OpenRouter</strong> — unified API for DeepSeek models and more.</li> <li><strong>OpenRouter</strong> — unified API for DeepSeek models and more.</li>
<li><strong>OpenAI</strong>, <strong>NVIDIA NIM</strong>, <strong>Novita</strong>, <strong>Fireworks</strong>, <strong>sglang</strong>, <strong>vLLM</strong>, <strong>Ollama</strong></li> <li><strong>OpenAI</strong>, <strong>NVIDIA NIM</strong>, <strong>Volcengine Ark</strong>, <strong>Xiaomi MiMo</strong>, <strong>SiliconFlow</strong>, <strong>Novita</strong>, <strong>Fireworks</strong>, <strong>sglang</strong>, <strong>vLLM</strong>, <strong>Ollama</strong></li>
</ul> </ul>
<p> <p>
Set the corresponding env var (e.g. <code className="inline">OPENROUTER_API_KEY</code>) and your provider in <code className="inline">~/.deepseek/config.toml</code>. Set the corresponding env var (e.g. <code className="inline">OPENROUTER_API_KEY</code>) and your provider in <code className="inline">~/.codewhale/config.toml</code>.
Hugging Face, ZenMux, and self-hosted OpenAI-compatible endpoints are on the roadmap. Self-hosted OpenAI-compatible endpoints are supported through the provider config.
</p> </p>
</> </>
), ),
@@ -131,7 +132,7 @@ codewhale doctor # full connectivity check`}
{`# 1. Set your OpenRouter key {`# 1. Set your OpenRouter key
export OPENROUTER_API_KEY=sk-or-v1-... export OPENROUTER_API_KEY=sk-or-v1-...
# 2. In ~/.deepseek/config.toml: # 2. In ~/.codewhale/config.toml:
[providers.openrouter] [providers.openrouter]
api_key = "sk-or-v1-..." api_key = "sk-or-v1-..."
@@ -213,7 +214,7 @@ default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
CodeWhale runs entirely on your machine. No telemetry, no cloud processing of your code. CodeWhale runs entirely on your machine. No telemetry, no cloud processing of your code.
Sandbox backends: <strong>seatbelt</strong> (macOS), <strong>landlock</strong> (Linux), restricted tokens (Windows). Sandbox backends: <strong>seatbelt</strong> (macOS), <strong>landlock</strong> (Linux), restricted tokens (Windows).
Workspace boundaries default to <code className="inline">--workspace</code>. <code className="inline">/trust</code> lifts them. Workspace boundaries default to <code className="inline">--workspace</code>. <code className="inline">/trust</code> lifts them.
Approval mode is configurable per session. All credential/approval/elevation events are written to <code className="inline">~/.deepseek/audit.log</code>. Approval mode is configurable per session. All credential/approval/elevation events are written to <code className="inline">~/.codewhale/audit.log</code>.
</> </>
), ),
sources: ["SECURITY.md", "docs/ARCHITECTURE.md"], sources: ["SECURITY.md", "docs/ARCHITECTURE.md"],
@@ -222,7 +223,7 @@ default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
q: "How do MCP servers work?", q: "How do MCP servers work?",
a: ( a: (
<> <>
CodeWhale is a bidirectional MCP client and server. Define servers in <code className="inline">~/.deepseek/mcp.json</code>. CodeWhale is a bidirectional MCP client and server. Define servers in <code className="inline">~/.codewhale/mcp.json</code>.
Tools appear as <code className="inline">mcp_&lt;server&gt;_&lt;tool&gt;</code>. You can also expose CodeWhale as an MCP server with <code className="inline">codewhale mcp</code>. Tools appear as <code className="inline">mcp_&lt;server&gt;_&lt;tool&gt;</code>. You can also expose CodeWhale as an MCP server with <code className="inline">codewhale mcp</code>.
See the <Link href="/docs#mcp" className="body-link">docs page</Link> for configuration examples. See the <Link href="/docs#mcp" className="body-link">docs page</Link> for configuration examples.
</> </>
@@ -269,7 +270,7 @@ registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`}
q: "My API key was rejected or I get auth errors on first run.", q: "My API key was rejected or I get auth errors on first run.",
a: ( a: (
<> <>
<p className="mb-2">Run <code className="inline">codewhale doctor</code> — it checks API key, network, sandbox, and MCP servers. Full report is written to <code className="inline">~/.deepseek/doctor.log</code>.</p> <p className="mb-2">Run <code className="inline">codewhale doctor</code> — it checks API key, network, sandbox, and MCP servers. Full report is written to <code className="inline">~/.codewhale/doctor.log</code>.</p>
<p className="mb-2">Common causes:</p> <p className="mb-2">Common causes:</p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft"> <ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft">
<li>Stale <code className="inline">DEEPSEEK_API_KEY</code> in shell startup file — open a fresh shell or use <code className="inline">codewhale auth set</code></li> <li>Stale <code className="inline">DEEPSEEK_API_KEY</code> in shell startup file — open a fresh shell or use <code className="inline">codewhale auth set</code></li>
@@ -352,6 +353,7 @@ npm install -g codewhale
# Cargo Rust 1.88+ # Cargo Rust 1.88+
cargo install codewhale-cli --locked cargo install codewhale-cli --locked
cargo install codewhale-tui --locked
# HomebrewmacOS # HomebrewmacOS
brew tap Hmbown/deepseek-tui && brew install deepseek-tui brew tap Hmbown/deepseek-tui && brew install deepseek-tui
@@ -360,7 +362,7 @@ brew tap Hmbown/deepseek-tui && brew install deepseek-tui
# https://github.com/Hmbown/CodeWhale/releases`} # https://github.com/Hmbown/CodeWhale/releases`}
</pre> </pre>
<p> <p>
<code className="inline">codewhale</code> <code className="inline">~/.deepseek/</code> <code className="inline">codewhale</code> <code className="inline">~/.codewhale/</code> <code className="inline">~/.deepseek/</code> 退
<Link href="/zh/install" className="body-link"></Link> Docker <Link href="/zh/install" className="body-link"></Link> Docker
</p> </p>
</> </>
@@ -384,7 +386,7 @@ brew tap Hmbown/deepseek-tui && brew install deepseek-tui
a: ( a: (
<> <>
CodeWhale DeepSeek TUI <code className="inline">codewhale</code> <code className="inline">deepseek</code> <code className="inline">deepseek-tui</code> CodeWhale DeepSeek TUI <code className="inline">codewhale</code> <code className="inline">deepseek</code> <code className="inline">deepseek-tui</code>
<code className="inline">~/.deepseek/</code><code className="inline">DEEPSEEK_*</code> <code className="inline">~/.codewhale/</code> <code className="inline">~/.deepseek/</code> 退<code className="inline">DEEPSEEK_*</code>
DeepSeek CodeWhale 广使 DeepSeek DeepSeek CodeWhale 广使 DeepSeek
</> </>
), ),
@@ -402,7 +404,7 @@ export DEEPSEEK_API_KEY=sk-...
codewhale auth set --provider deepseek --api-key sk-... codewhale auth set --provider deepseek --api-key sk-...
# 方法 3config.toml # 方法 3config.toml
# 在 ~/.deepseek/config.toml 中添加: # 在 ~/.codewhale/config.toml 中添加:
api_key = "sk-..." api_key = "sk-..."
# 查看当前状态: # 查看当前状态:
@@ -425,11 +427,11 @@ codewhale doctor # 完整连接检查`}
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft mb-3"> <ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft mb-3">
<li><strong>DeepSeek</strong> API</li> <li><strong>DeepSeek</strong> API</li>
<li><strong>OpenRouter</strong> API访 DeepSeek </li> <li><strong>OpenRouter</strong> API访 DeepSeek </li>
<li><strong>OpenAI</strong><strong>NVIDIA NIM</strong><strong>Novita</strong><strong>Fireworks</strong><strong>sglang</strong><strong>vLLM</strong><strong>Ollama</strong></li> <li><strong>OpenAI</strong><strong>NVIDIA NIM</strong><strong>Volcengine Ark</strong><strong>Xiaomi MiMo</strong><strong>SiliconFlow</strong><strong>Novita</strong><strong>Fireworks</strong><strong>sglang</strong><strong>vLLM</strong><strong>Ollama</strong></li>
</ul> </ul>
<p> <p>
<code className="inline">OPENROUTER_API_KEY</code> <code className="inline">~/.deepseek/config.toml</code> <code className="inline">OPENROUTER_API_KEY</code> <code className="inline">~/.codewhale/config.toml</code>
Hugging FaceZenMux OpenAI 线 OpenAI provider
</p> </p>
</> </>
), ),
@@ -443,7 +445,7 @@ codewhale doctor # 完整连接检查`}
{`# 1. 设置 OpenRouter 密钥 {`# 1. 设置 OpenRouter 密钥
export OPENROUTER_API_KEY=sk-or-v1-... export OPENROUTER_API_KEY=sk-or-v1-...
# 2. 在 ~/.deepseek/config.toml 中: # 2. 在 ~/.codewhale/config.toml 中:
[providers.openrouter] [providers.openrouter]
api_key = "sk-or-v1-..." api_key = "sk-or-v1-..."
@@ -525,7 +527,7 @@ default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
CodeWhale CodeWhale
<strong>seatbelt</strong>macOS<strong>landlock</strong>LinuxWindows <strong>seatbelt</strong>macOS<strong>landlock</strong>LinuxWindows
<code className="inline">--workspace</code><code className="inline">/trust</code> <code className="inline">--workspace</code><code className="inline">/trust</code>
// <code className="inline">~/.deepseek/audit.log</code> // <code className="inline">~/.codewhale/audit.log</code>
</> </>
), ),
sources: ["SECURITY.md", "docs/ARCHITECTURE.md"], sources: ["SECURITY.md", "docs/ARCHITECTURE.md"],
@@ -534,7 +536,7 @@ default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
q: "MCP 服务器如何工作?", q: "MCP 服务器如何工作?",
a: ( a: (
<> <>
CodeWhale MCP <code className="inline">~/.deepseek/mcp.json</code> CodeWhale MCP <code className="inline">~/.codewhale/mcp.json</code>
<code className="inline">mcp_&lt;server&gt;_&lt;tool&gt;</code> <code className="inline">codewhale mcp</code> CodeWhale MCP <code className="inline">mcp_&lt;server&gt;_&lt;tool&gt;</code> <code className="inline">codewhale mcp</code> CodeWhale MCP
<Link href="/zh/docs#mcp" className="body-link"></Link> <Link href="/zh/docs#mcp" className="body-link"></Link>
</> </>
@@ -581,7 +583,7 @@ registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`}
q: "首次运行时提示 API 密钥被拒绝或认证错误?", q: "首次运行时提示 API 密钥被拒绝或认证错误?",
a: ( a: (
<> <>
<p className="mb-2"> <code className="inline">codewhale doctor</code> API MCP <code className="inline">~/.deepseek/doctor.log</code></p> <p className="mb-2"> <code className="inline">codewhale doctor</code> API MCP <code className="inline">~/.codewhale/doctor.log</code></p>
<p className="mb-2"></p> <p className="mb-2"></p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft"> <ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft">
<li>Shell <code className="inline">DEEPSEEK_API_KEY</code> Shell 使 <code className="inline">codewhale auth set</code></li> <li>Shell <code className="inline">DEEPSEEK_API_KEY</code> Shell 使 <code className="inline">codewhale auth set</code></li>
+32 -32
View File
@@ -9,12 +9,13 @@ export async function generateMetadata({ params }: { params: Promise<{ locale: s
return { return {
title: isZh ? "安装 · CodeWhale" : "Install · CodeWhale", title: isZh ? "安装 · CodeWhale" : "Install · CodeWhale",
description: isZh description: isZh
? "通过 Cargo 安装 codewhale-cli。其他方式:npm、Homebrew、预编译二进制、Docker、国内镜像。" ? "安装 CodeWhale 的 codewhale / codewhale-tui 二进制对。其他方式:npm、Homebrew、预编译二进制、Docker、国内镜像。"
: "Install codewhale-cli via Cargo. Other ways: npm, Homebrew, prebuilt binary, Docker, source.", : "Install the matched codewhale / codewhale-tui binary pair. Other ways: npm, Homebrew, prebuilt binary, Docker, source.",
}; };
} }
const CARGO_INSTALL = `cargo install codewhale-cli --locked`; const CARGO_INSTALL = `cargo install codewhale-cli --locked
cargo install codewhale-tui --locked`;
const FIRST_RUN = `codewhale`; const FIRST_RUN = `codewhale`;
const VERIFY = `codewhale --version const VERIFY = `codewhale --version
codewhale doctor`; codewhale doctor`;
@@ -32,22 +33,20 @@ replace-with = "tuna"
[source.tuna] [source.tuna]
registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`; registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`;
const TUNA_INSTALL = `cargo install codewhale-cli --locked`; const TUNA_INSTALL = `cargo install codewhale-cli --locked
cargo install codewhale-tui --locked`;
const NPMMIRROR = `npm config set registry https://registry.npmmirror.com const NPMMIRROR = `npm config set registry https://registry.npmmirror.com
npm install -g codewhale`; npm install -g codewhale`;
const BREW = `brew tap Hmbown/deepseek-tui const BREW = `brew tap Hmbown/deepseek-tui
brew install deepseek-tui`; brew install deepseek-tui`;
const DOCKER = `git clone https://github.com/Hmbown/CodeWhale const DOCKER = `docker volume create codewhale-home
cd codewhale
docker build -t codewhale .
docker run --rm -it \\ docker run --rm -it \\
-e DEEPSEEK_API_KEY=$DEEPSEEK_API_KEY \\ -e DEEPSEEK_API_KEY=$DEEPSEEK_API_KEY \\
-v ~/.deepseek:/home/codewhale/.deepseek \\ -v codewhale-home:/home/codewhale/.codewhale \\
-v "$PWD:/work" -w /work \\ -v "$PWD:/workspace" -w /workspace \\
codewhale`; ghcr.io/hmbown/codewhale:latest`;
const FROM_SOURCE = `git clone https://github.com/Hmbown/CodeWhale const FROM_SOURCE = `git clone https://github.com/Hmbown/CodeWhale
cd codewhale cd codewhale
@@ -57,7 +56,7 @@ cargo build --release --locked
cargo install --path crates/cli --locked # codewhale cargo install --path crates/cli --locked # codewhale
cargo install --path crates/tui --locked # codewhale-tui`; cargo install --path crates/tui --locked # codewhale-tui`;
const CONFIG_TREE = `~/.deepseek/ const CONFIG_TREE = `~/.codewhale/
├── config.toml api keys, model, hooks, profiles ├── config.toml api keys, model, hooks, profiles
├── mcp.json MCP server definitions ├── mcp.json MCP server definitions
├── skills/ user skills (each with SKILL.md) ├── skills/ user skills (each with SKILL.md)
@@ -65,9 +64,9 @@ const CONFIG_TREE = `~/.deepseek/
├── tasks/ background task store ├── tasks/ background task store
└── audit.log credential / approval / elevation audit trail └── audit.log credential / approval / elevation audit trail
./.deepseek/ project-scoped config (optional, per-repo)`; ./.codewhale/ project-scoped config (optional, per-repo)`;
const CONFIG_TREE_ZH = `~/.deepseek/ const CONFIG_TREE_ZH = `~/.codewhale/
├── config.toml API 密钥、模型、钩子、配置集 ├── config.toml API 密钥、模型、钩子、配置集
├── mcp.json MCP 服务器定义 ├── mcp.json MCP 服务器定义
├── skills/ 用户技能(每个含 SKILL.md) ├── skills/ 用户技能(每个含 SKILL.md)
@@ -75,7 +74,7 @@ const CONFIG_TREE_ZH = `~/.deepseek/
├── tasks/ 后台任务存储 ├── tasks/ 后台任务存储
└── audit.log 凭证 / 审批 / 提权审计日志 └── audit.log 凭证 / 审批 / 提权审计日志
./.deepseek/ 项目级配置(可选,每个仓库)`; ./.codewhale/ 项目级配置(可选,每个仓库)`;
export default async function InstallPage({ params }: { params: Promise<{ locale: string }> }) { export default async function InstallPage({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params; const { locale } = await params;
@@ -108,14 +107,15 @@ export default async function InstallPage({ params }: { params: Promise<{ locale
<p className="mt-4 text-sm text-ink-soft leading-relaxed max-w-2xl"> <p className="mt-4 text-sm text-ink-soft leading-relaxed max-w-2xl">
{isZh ? ( {isZh ? (
<> <>
<code className="inline">codewhale</code> <code className="inline">~/.cargo/bin</code> <code className="inline">codewhale</code> <code className="inline">codewhale-tui</code> <code className="inline">~/.cargo/bin</code>
Rust 1.88+访{" "} Rust 1.88+访{" "}
<a href="https://rustup.rs" className="body-link">rustup.rs</a> <a href="https://rustup.rs" className="body-link">rustup.rs</a>
Rust Homebrew Rust Homebrew
</> </>
) : ( ) : (
<> <>
Compiles and installs <code className="inline">codewhale</code> to{" "} Compiles and installs <code className="inline">codewhale</code> and{" "}
<code className="inline">codewhale-tui</code> to{" "}
<code className="inline">~/.cargo/bin</code>. Requires Rust 1.88+ install via{" "} <code className="inline">~/.cargo/bin</code>. Requires Rust 1.88+ install via{" "}
<a href="https://rustup.rs" className="body-link">rustup.rs</a> if you don&apos;t have it. <a href="https://rustup.rs" className="body-link">rustup.rs</a> if you don&apos;t have it.
See <a href="#other-ways" className="body-link">Other ways to install</a> below for See <a href="#other-ways" className="body-link">Other ways to install</a> below for
@@ -139,13 +139,13 @@ export default async function InstallPage({ params }: { params: Promise<{ locale
<> <>
<code className="inline">codewhale doctor</code> API <code className="inline">codewhale doctor</code> API
MCP {" "} MCP {" "}
<code className="inline">~/.deepseek/doctor.log</code> <code className="inline">~/.codewhale/doctor.log</code>
</> </>
) : ( ) : (
<> <>
<code className="inline">codewhale doctor</code> checks your API key, network, <code className="inline">codewhale doctor</code> checks your API key, network,
sandbox availability, and MCP servers. Full report is written to{" "} sandbox availability, and MCP servers. Full report is written to{" "}
<code className="inline">~/.deepseek/doctor.log</code>. <code className="inline">~/.codewhale/doctor.log</code>.
</> </>
)} )}
</p> </p>
@@ -167,16 +167,15 @@ export default async function InstallPage({ params }: { params: Promise<{ locale
Homebrew npm 使 Homebrew npm 使
<code className="inline">brew upgrade deepseek-tui</code> {" "} <code className="inline">brew upgrade deepseek-tui</code> {" "}
<code className="inline">npm update -g codewhale</code> <code className="inline">npm update -g codewhale</code>
Cargo {" "} Cargo <code className="inline">cargo install</code> <code className="inline">--force</code>
<code className="inline">cargo install codewhale-cli --locked --force</code>
</> </>
) : ( ) : (
<> <>
Checks GitHub Releases for a newer version and replaces the binary in place. If you Checks GitHub Releases for a newer version and replaces the binary in place. If you
installed via Homebrew or npm, prefer the package manager instead:{" "} installed via Homebrew or npm, prefer the package manager instead:{" "}
<code className="inline">brew upgrade deepseek-tui</code> or{" "} <code className="inline">brew upgrade deepseek-tui</code> or{" "}
<code className="inline">npm update -g codewhale</code>. Cargo users can re-run{" "} <code className="inline">npm update -g codewhale</code>. Cargo users can re-run both{" "}
<code className="inline">cargo install codewhale-cli --locked --force</code>. <code className="inline">cargo install</code> commands with <code className="inline">--force</code>.
</> </>
)} )}
</p> </p>
@@ -222,7 +221,7 @@ export default async function InstallPage({ params }: { params: Promise<{ locale
<div className="space-y-2"> <div className="space-y-2">
<InstallCodeBlock cmd={SET_KEY_BASH} copyLabel={copyLabel} copiedLabel={copiedLabel} /> <InstallCodeBlock cmd={SET_KEY_BASH} copyLabel={copyLabel} copiedLabel={copiedLabel} />
<p className="text-xs text-ink-mute"> <p className="text-xs text-ink-mute">
{isZh ? "或保存到 ~/.deepseek/config.toml" : "Or persist it to ~/.deepseek/config.toml:"} {isZh ? "或保存到 ~/.codewhale/config.toml" : "Or persist it to ~/.codewhale/config.toml:"}
</p> </p>
<InstallCodeBlock cmd={SET_KEY_AUTH} copyLabel={copyLabel} copiedLabel={copiedLabel} /> <InstallCodeBlock cmd={SET_KEY_AUTH} copyLabel={copyLabel} copiedLabel={copiedLabel} />
</div> </div>
@@ -265,8 +264,8 @@ export default async function InstallPage({ params }: { params: Promise<{ locale
</h2> </h2>
<p className="text-sm text-ink-soft max-w-2xl mb-10"> <p className="text-sm text-ink-soft max-w-2xl mb-10">
{isZh {isZh
? "如果上面的 Cargo 路径不适合你,从下面找到匹配你情况的一条。每条都安装同一 codewhale 二进制。" ? "如果上面的 Cargo 路径不适合你,从下面找到匹配你情况的一条。每条都安装同一 codewhale / codewhale-tui 二进制。"
: "If the Cargo path above doesn't fit your setup, pick the row that matches your situation. Every path installs the same codewhale binary."} : "If the Cargo path above doesn't fit your setup, pick the row that matches your situation. Every path installs the same codewhale / codewhale-tui binary pair."}
</p> </p>
<div className="space-y-10"> <div className="space-y-10">
@@ -372,8 +371,8 @@ export default async function InstallPage({ params }: { params: Promise<{ locale
<InstallCodeBlock cmd={DOCKER} copyLabel={copyLabel} copiedLabel={copiedLabel} /> <InstallCodeBlock cmd={DOCKER} copyLabel={copyLabel} copiedLabel={copiedLabel} />
<p className="mt-3 text-sm text-ink-soft leading-relaxed max-w-2xl"> <p className="mt-3 text-sm text-ink-soft leading-relaxed max-w-2xl">
{isZh {isZh
? "支持 multi-arch buildx。目前没有发布镜像仓库,需要本地构建。" ? "发布镜像位于 GHCR。需要固定版本时,把 latest 替换成具体的发布标签。"
: "Multi-arch buildx is supported. No image is published to a registry yet, so you build locally."} : "The release image is published to GHCR. Replace latest with a release tag when you need a pinned version."}
</p> </p>
</div> </div>
@@ -403,16 +402,17 @@ export default async function InstallPage({ params }: { params: Promise<{ locale
<p className="mt-4 text-sm text-ink-soft leading-relaxed max-w-2xl"> <p className="mt-4 text-sm text-ink-soft leading-relaxed max-w-2xl">
{isZh ? ( {isZh ? (
<> <>
<code className="inline">./.deepseek/</code> MCP <code className="inline">./.codewhale/</code> MCP
<code className="inline">~/.deepseek</code> <code className="inline">./.deepseek</code> 退
</> </>
) : ( ) : (
<> <>
The project-scoped <code className="inline">./.deepseek/</code> directory is optional The project-scoped <code className="inline">./.codewhale/</code> directory is optional
each repo can carry its own MCP servers, hooks, skills, and config overrides (e.g. each repo can carry its own MCP servers, hooks, skills, and config overrides (e.g.
provider keys). On first run the app asks whether to interactively create a config provider keys). On first run the app asks whether to interactively create a config
file if one is missing. file if one is missing. Legacy <code className="inline">~/.deepseek</code> and{" "}
<code className="inline">./.deepseek</code> paths are still read as compatibility fallbacks.
</> </>
)} )}
</p> </p>
+116 -1
View File
@@ -15,10 +15,70 @@ const FALLBACK_STATS: RepoStats = {
forks: 0, forks: 0,
openIssues: 0, openIssues: 0,
openPulls: 0, openPulls: 0,
contributors: 98, contributors: 141,
fetchedAt: new Date().toISOString(), fetchedAt: new Date().toISOString(),
}; };
const RELEASE_CONTRIBUTORS = [
"@cy2311",
"@LING71671",
"@axobase001",
"@dzyuan",
"@mvanhorn",
"@malsony",
"@gaord",
"@yuanchenglu",
"@idling11",
"@h3c-hexin",
"@AdityaVG13",
"@Sskift",
"@cyq1017",
"@HUQIANTAO",
"@New2Niu",
"@AiurArtanis",
"@Lee-take",
"@nightt5879",
"@AresNing",
"@AccMoment",
"@reidliu41",
"@aboimpinto",
"@zhuangbiaowei",
"@donglovejava",
"@hongqitai",
"@zlh124",
"@encyc",
"@Implementist",
"@lihuan215",
"@LeoAlex0",
"@jimmyzhuu",
"@rockyzhang",
"@mo-vic",
"@hufanexplore",
"@hoclaptrinh33",
"@BryonGo",
];
const RELEASE_HELPERS = [
"@buko",
"@yyyCode",
"@gaslebinh-glitch",
"@Dr3259",
"@lpeng1711694086-lang",
"@VerrPower",
"@yan-zay",
"@jretz",
"@Neo-millunnium",
"@caeserchen",
"@T-Phuong-Nguyen",
"@zhyuzhyu",
"@0gl20shk0sbt36",
"@hatakes",
"@goodvecn-dev",
"@bevis-wong",
"@PurplePulse",
"@nbiish",
];
const FALLBACK_DISPATCH_EN: CuratedDispatch = { const FALLBACK_DISPATCH_EN: CuratedDispatch = {
generatedAt: new Date().toISOString(), generatedAt: new Date().toISOString(),
headline: "Quiet release week — install paths and contributor guides up to date.", headline: "Quiet release week — install paths and contributor guides up to date.",
@@ -417,6 +477,61 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
</div> </div>
</section> </section>
{/* RELEASE CREDITS */}
<section className="mx-auto max-w-[1400px] px-6 py-14">
<div className="flex items-baseline gap-4 mb-5 hairline-b pb-4">
<Seal char="谢" />
<div>
<div className="eyebrow mb-2">{isZh ? "v0.8.48 致谢" : "v0.8.48 credits"}</div>
<h2 className="font-display text-3xl">
{isZh ? "每个补丁和报告都算数" : "Every patch and report counts"}
</h2>
</div>
</div>
<div className="grid lg:grid-cols-12 gap-10">
<div className="lg:col-span-5">
<p className={`text-ink-soft ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
{isZh
? "这一版合并和吸收了来自社区的大量工作。完整条目在 CHANGELOG 中;这里保留最新发布的公开致谢入口。"
: "This release merged and harvested a large community tranche. The full notes live in the changelog; this keeps the latest public credit surface easy to find."}
</p>
<Link href="https://github.com/Hmbown/CodeWhale/blob/main/CHANGELOG.md#0848---2026-05-31" className="inline-block mt-4 font-mono text-xs uppercase tracking-wider text-indigo hover:underline">
{isZh ? "查看完整 changelog →" : "Full changelog →"}
</Link>
</div>
<div className="lg:col-span-7 grid gap-6">
<div>
<div className="eyebrow mb-3">{isZh ? "已合并 / 已吸收贡献" : "Merged and harvested contributions"}</div>
<div className="flex flex-wrap gap-2">
{RELEASE_CONTRIBUTORS.map((handle) => (
<Link
key={handle}
href={`https://github.com/${handle.slice(1)}`}
className="font-mono text-xs px-2 py-1 hairline-t hairline-b hairline-l hairline-r text-ink-soft hover:text-indigo hover:bg-paper-deep"
>
{handle}
</Link>
))}
</div>
</div>
<div>
<div className="eyebrow mb-3">{isZh ? "报告、复现和验证" : "Reports, repros, and verification"}</div>
<div className="flex flex-wrap gap-2">
{RELEASE_HELPERS.map((handle) => (
<Link
key={handle}
href={`https://github.com/${handle.slice(1)}`}
className="font-mono text-xs px-2 py-1 hairline-t hairline-b hairline-l hairline-r text-ink-soft hover:text-indigo hover:bg-paper-deep"
>
{handle}
</Link>
))}
</div>
</div>
</div>
</div>
</section>
{/* JOIN IN */} {/* JOIN IN */}
<section className="bg-ink text-paper"> <section className="bg-ink text-paper">
<div className="mx-auto max-w-[1400px] px-6 py-16 grid lg:grid-cols-12 gap-10 items-center"> <div className="mx-auto max-w-[1400px] px-6 py-16 grid lg:grid-cols-12 gap-10 items-center">
+6 -6
View File
@@ -27,9 +27,9 @@ const tracksEn = [
{ title: "RLM batched processing", note: "Persistent sandboxed Python REPL with 116 cheap parallel children for long-input analysis" }, { title: "RLM batched processing", note: "Persistent sandboxed Python REPL with 116 cheap parallel children for long-input analysis" },
{ title: "Three operating modes", note: "Plan (read-only), Agent (default), YOLO (auto-approved); orthogonal suggest / auto / never approval" }, { title: "Three operating modes", note: "Plan (read-only), Agent (default), YOLO (auto-approved); orthogonal suggest / auto / never approval" },
{ title: "Per-platform sandbox", note: "seatbelt (macOS), landlock (Linux); Windows containment via restricted tokens (limited)" }, { title: "Per-platform sandbox", note: "seatbelt (macOS), landlock (Linux); Windows containment via restricted tokens (limited)" },
{ title: "Durable sessions + tasks", note: "Save, resume, rollback; background task queue with replayable timelines under ~/.deepseek/tasks/" }, { title: "Durable sessions + tasks", note: "Save, resume, rollback; background task queue with replayable timelines under ~/.codewhale/tasks/" },
{ title: "Bidirectional MCP", note: "Consume tools from external servers; expose as server via `deepseek mcp`; ~/.deepseek/mcp.json" }, { title: "Bidirectional MCP", note: "Consume tools from external servers; expose as server via `codewhale mcp`; ~/.codewhale/mcp.json" },
{ title: "Skills + unified slash palette", note: "~/.deepseek/skills/ auto-loading; /help, /mode, /status, /config, /trust, /feedback" }, { title: "Skills + unified slash palette", note: "~/.codewhale/skills/ auto-loading; /help, /mode, /status, /config, /trust, /feedback" },
{ title: "OpenRouter provider", note: "First-class OpenRouter integration with 300+ models across dozens of providers" }, { title: "OpenRouter provider", note: "First-class OpenRouter integration with 300+ models across dozens of providers" },
{ title: "Multi-provider support", note: "Hot-swap between providers (DeepSeek, OpenAI, Anthropic, OpenRouter) per session" }, { title: "Multi-provider support", note: "Hot-swap between providers (DeepSeek, OpenAI, Anthropic, OpenRouter) per session" },
], ],
@@ -93,9 +93,9 @@ const tracksZh = [
{ title: "RLM 批量处理", note: "持久沙箱 Python REPL,支持 1–16 路廉价并行子调用,处理长文本分析" }, { title: "RLM 批量处理", note: "持久沙箱 Python REPL,支持 1–16 路廉价并行子调用,处理长文本分析" },
{ title: "三种运行模式", note: "Plan(只读)、Agent(默认)、YOLO(自动批准);审批模式正交(建议/自动/拒绝)" }, { title: "三种运行模式", note: "Plan(只读)、Agent(默认)、YOLO(自动批准);审批模式正交(建议/自动/拒绝)" },
{ title: "跨平台沙箱", note: "seatbeltmacOS)、landlockLinux);Windows 通过受限令牌实现基础隔离(功能有限)" }, { title: "跨平台沙箱", note: "seatbeltmacOS)、landlockLinux);Windows 通过受限令牌实现基础隔离(功能有限)" },
{ title: "持久化会话 + 后台任务", note: "保存、恢复、回滚;后台任务队列,可回放时间线,位于 ~/.deepseek/tasks/" }, { title: "持久化会话 + 后台任务", note: "保存、恢复、回滚;后台任务队列,可回放时间线,位于 ~/.codewhale/tasks/" },
{ title: "双向 MCP 协议", note: "消费外部服务器工具;通过 `deepseek mcp` 暴露为服务器;~/.deepseek/mcp.json" }, { title: "双向 MCP 协议", note: "消费外部服务器工具;通过 `codewhale mcp` 暴露为服务器;~/.codewhale/mcp.json" },
{ title: "技能 + 统一命令面板", note: "~/.deepseek/skills/ 自动加载;/help、/mode、/status、/config、/trust、/feedback" }, { title: "技能 + 统一命令面板", note: "~/.codewhale/skills/ 自动加载;/help、/mode、/status、/config、/trust、/feedback" },
{ title: "OpenRouter 提供商", note: "原生集成 OpenRouter,支持 300+ 模型,覆盖数十个提供商" }, { title: "OpenRouter 提供商", note: "原生集成 OpenRouter,支持 300+ 模型,覆盖数十个提供商" },
{ title: "多提供商支持", note: "按会话动态切换提供商(DeepSeek、OpenAI、Anthropic、OpenRouter" }, { title: "多提供商支持", note: "按会话动态切换提供商(DeepSeek、OpenAI、Anthropic、OpenRouter" },
], ],
+19 -3
View File
@@ -18,8 +18,8 @@ export interface RepoFacts {
} }
export const FACTS: RepoFacts = { export const FACTS: RepoFacts = {
"generatedAt": "2026-05-26T17:03:21.939Z", "generatedAt": "2026-06-01T00:40:33.053Z",
"version": "0.8.46", "version": "0.8.48",
"crates": [ "crates": [
"agent", "agent",
"app-server", "app-server",
@@ -30,6 +30,7 @@ export const FACTS: RepoFacts = {
"hooks", "hooks",
"mcp", "mcp",
"protocol", "protocol",
"release",
"secrets", "secrets",
"state", "state",
"tools", "tools",
@@ -69,11 +70,21 @@ export const FACTS: RepoFacts = {
"label": "Wanjie Ark", "label": "Wanjie Ark",
"env": "WANJIE_ARK_API_KEY / WANJIE_API_KEY / WANJIE_MAAS_API_KEY" "env": "WANJIE_ARK_API_KEY / WANJIE_API_KEY / WANJIE_MAAS_API_KEY"
}, },
{
"id": "volcengine",
"label": "Volcengine Ark",
"env": "VOLCENGINE_API_KEY / VOLCENGINE_ARK_API_KEY / ARK_API_KEY"
},
{ {
"id": "openrouter", "id": "openrouter",
"label": "OpenRouter", "label": "OpenRouter",
"env": "OPENROUTER_API_KEY" "env": "OPENROUTER_API_KEY"
}, },
{
"id": "xiaomi-mimo",
"label": "Xiaomi MiMo",
"env": "XIAOMI_MIMO_API_KEY / XIAOMI_API_KEY / MIMO_API_KEY"
},
{ {
"id": "novita", "id": "novita",
"label": "Novita AI", "label": "Novita AI",
@@ -84,6 +95,11 @@ export const FACTS: RepoFacts = {
"label": "Fireworks AI", "label": "Fireworks AI",
"env": "FIREWORKS_API_KEY" "env": "FIREWORKS_API_KEY"
}, },
{
"id": "siliconflow",
"label": "SiliconFlow",
"env": "SILICONFLOW_API_KEY"
},
{ {
"id": "moonshot", "id": "moonshot",
"label": "Moonshot/Kimi", "label": "Moonshot/Kimi",
@@ -107,7 +123,7 @@ export const FACTS: RepoFacts = {
], ],
"defaultModel": "deepseek-v4-pro", "defaultModel": "deepseek-v4-pro",
"nodeEngines": ">=18", "nodeEngines": ">=18",
"toolCount": 70, "toolCount": 75,
"license": "MIT", "license": "MIT",
"latestRelease": null "latestRelease": null
}; };
+3 -32
View File
@@ -1,24 +1,11 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { lastPageFromLink, relativeTime } from "./github";
// We test the pure helper functions directly. // We test the pure helper functions directly.
// The async fetch functions require mocking the global fetch. // The async fetch functions require mocking the global fetch.
// ── relativeTime ────────────────────────────────────────────────────── // ── relativeTime ──────────────────────────────────────────────────────
function relativeTime(iso: string): string {
const diff = Date.now() - +new Date(iso);
const mins = Math.round(diff / 60000);
if (mins < 1) return "just now";
if (mins < 60) return `${mins}m`;
const hrs = Math.round(mins / 60);
if (hrs < 24) return `${hrs}h`;
const days = Math.round(hrs / 24);
if (days < 30) return `${days}d`;
const months = Math.round(days / 30);
if (months < 12) return `${months}mo`;
return `${Math.round(months / 12)}y`;
}
describe("relativeTime", () => { describe("relativeTime", () => {
beforeEach(() => { beforeEach(() => {
vi.useFakeTimers(); vi.useFakeTimers();
@@ -45,7 +32,7 @@ describe("relativeTime", () => {
it("returns days for < 30 days", () => { it("returns days for < 30 days", () => {
expect(relativeTime("2026-05-25T12:00:00Z")).toBe("7d"); expect(relativeTime("2026-05-25T12:00:00Z")).toBe("7d");
expect(relativeTime("2026-05-02T12:00:00Z")).toBe("30d"); expect(relativeTime("2026-05-03T12:00:00Z")).toBe("29d");
}); });
it("returns months for < 12 months", () => { it("returns months for < 12 months", () => {
@@ -55,28 +42,12 @@ describe("relativeTime", () => {
it("returns years for >= 12 months", () => { it("returns years for >= 12 months", () => {
expect(relativeTime("2024-06-01T12:00:00Z")).toBe("2y"); expect(relativeTime("2024-06-01T12:00:00Z")).toBe("2y");
expect(relativeTime("2025-01-01T00:00:00Z")).toBe("2y"); expect(relativeTime("2025-01-01T00:00:00Z")).toBe("1y");
}); });
}); });
// ── lastPageFromLink (via re-export test) ────────────────────────────── // ── lastPageFromLink (via re-export test) ──────────────────────────────
function lastPageFromLink(link: string | null): number | undefined {
if (!link) return undefined;
for (const part of link.split(",")) {
const [rawUrl, rawRel] = part
.split(";")
.map((segment: string) => segment.trim());
if (rawRel !== 'rel="last"') continue;
const match = rawUrl.match(/^<(.+)>$/);
if (!match) continue;
const page = new URL(match[1]).searchParams.get("page");
const parsed = page ? Number.parseInt(page, 10) : NaN;
if (Number.isFinite(parsed) && parsed > 0) return parsed;
}
return undefined;
}
describe("lastPageFromLink", () => { describe("lastPageFromLink", () => {
it("returns undefined for null input", () => { it("returns undefined for null input", () => {
expect(lastPageFromLink(null)).toBeUndefined(); expect(lastPageFromLink(null)).toBeUndefined();
+1 -1
View File
@@ -2,7 +2,7 @@ import type { FeedItem, RepoStats } from "./types";
const REPO = process.env.GITHUB_REPO ?? "Hmbown/CodeWhale"; const REPO = process.env.GITHUB_REPO ?? "Hmbown/CodeWhale";
const GH = "https://api.github.com"; const GH = "https://api.github.com";
const MIN_KNOWN_CONTRIBUTORS = 99; const MIN_KNOWN_CONTRIBUTORS = 141;
function headers(token?: string): HeadersInit { function headers(token?: string): HeadersInit {
const h: Record<string, string> = { const h: Record<string, string> = {
+3
View File
@@ -70,9 +70,12 @@ function deriveProviders() {
Openai: { id: "openai", label: "OpenAI-compatible", env: "OPENAI_API_KEY" }, Openai: { id: "openai", label: "OpenAI-compatible", env: "OPENAI_API_KEY" },
Atlascloud: { id: "atlascloud", label: "AtlasCloud", env: "ATLASCLOUD_API_KEY" }, Atlascloud: { id: "atlascloud", label: "AtlasCloud", env: "ATLASCLOUD_API_KEY" },
WanjieArk: { id: "wanjie-ark", label: "Wanjie Ark", env: "WANJIE_ARK_API_KEY / WANJIE_API_KEY / WANJIE_MAAS_API_KEY" }, WanjieArk: { id: "wanjie-ark", label: "Wanjie Ark", env: "WANJIE_ARK_API_KEY / WANJIE_API_KEY / WANJIE_MAAS_API_KEY" },
Volcengine: { id: "volcengine", label: "Volcengine Ark", env: "VOLCENGINE_API_KEY / VOLCENGINE_ARK_API_KEY / ARK_API_KEY" },
Openrouter: { id: "openrouter", label: "OpenRouter", env: "OPENROUTER_API_KEY" }, Openrouter: { id: "openrouter", label: "OpenRouter", env: "OPENROUTER_API_KEY" },
XiaomiMimo: { id: "xiaomi-mimo", label: "Xiaomi MiMo", env: "XIAOMI_MIMO_API_KEY / XIAOMI_API_KEY / MIMO_API_KEY" },
Novita: { id: "novita", label: "Novita AI", env: "NOVITA_API_KEY" }, Novita: { id: "novita", label: "Novita AI", env: "NOVITA_API_KEY" },
Fireworks: { id: "fireworks", label: "Fireworks AI", env: "FIREWORKS_API_KEY" }, Fireworks: { id: "fireworks", label: "Fireworks AI", env: "FIREWORKS_API_KEY" },
Siliconflow: { id: "siliconflow", label: "SiliconFlow", env: "SILICONFLOW_API_KEY" },
Moonshot: { id: "moonshot", label: "Moonshot/Kimi", env: "MOONSHOT_API_KEY / KIMI_API_KEY" }, Moonshot: { id: "moonshot", label: "Moonshot/Kimi", env: "MOONSHOT_API_KEY / KIMI_API_KEY" },
Sglang: { id: "sglang", label: "SGLang", env: "SGLANG_API_KEY" }, Sglang: { id: "sglang", label: "SGLang", env: "SGLANG_API_KEY" },
Vllm: { id: "vllm", label: "vLLM", env: "VLLM_API_KEY" }, Vllm: { id: "vllm", label: "vLLM", env: "VLLM_API_KEY" },