Merge pull request #2153 from Hmbown/docs/v0.8.45-communications
docs(v0.8.45): complete changelog, README, and website refresh
This commit is contained in:
@@ -14,6 +14,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- **RLM session objects.** `rlm_open` can now load `session://` refs,
|
||||
exposing the active prompt, history, and session data as symbolic objects
|
||||
inside RLM REPLs (#2047).
|
||||
- **Command palette voice input.** The command palette can launch a configured
|
||||
speech-to-text helper and show footer status while transcription runs
|
||||
(#2047).
|
||||
- **Moonshot/Kimi OAuth provider.** Moonshot/Kimi is now a first-class
|
||||
provider, including Kimi CLI OAuth reuse, secure refresh writes, model
|
||||
completion, CLI auth, and secret-store integration.
|
||||
- **Deterministic whale-species sub-agent names.** Sub-agents now get stable,
|
||||
human-readable whale-species nicknames (e.g. "Beluga", "Orca") while
|
||||
preserving the raw agent ID in the popup (#2035, #2016).
|
||||
@@ -52,6 +58,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
Thanks @reidliu41 (#2143).
|
||||
- **Model picker selection survives Esc.** Dismissing the model picker with Esc
|
||||
no longer loses the highlighted selection. Thanks @reidliu41 (#2056).
|
||||
- **Moonshot/Kimi sessions launch from the dispatcher.** The `codewhale`
|
||||
wrapper now includes Moonshot/Kimi in the TUI provider allowlist, so
|
||||
`codewhale --provider moonshot --model kimi-k2.6` reaches the TUI instead of
|
||||
stopping after config resolution.
|
||||
- **Slash recovery no longer restores command tails in the composer.**
|
||||
Resuming a session or recovering from a crash no longer leaves stale
|
||||
slash-command text (e.g. `/sessions`) in the composer input (#2047, #2032).
|
||||
|
||||
@@ -90,7 +90,7 @@ It is built around DeepSeek V4 (`deepseek-v4-pro` / `deepseek-v4-flash`), includ
|
||||
- **Reasoning-effort tiers** — cycle through `off → high → max` with `Shift + Tab`
|
||||
- **Session save/resume/fork** — checkpoint long-running sessions and fork saved conversations into sibling paths with parent lineage shown in the picker
|
||||
- **Workspace rollback** — side-git pre/post-turn snapshots with `/restore` and `revert_turn`, without touching your repo's `.git`
|
||||
- **OS-level sandbox** — Seatbelt on macOS, Landlock on Linux, Job Objects on Windows; shell commands run with workspace-scoped filesystem access only
|
||||
- **Approval + platform sandbox controls** — Seatbelt on macOS and Landlock on Linux where available; Windows uses the same approval flow and terminal/runtime protections while OS-level filesystem isolation remains a tracked helper contract
|
||||
- **Durable task queue** — background tasks can survive restarts
|
||||
- **HTTP/SSE runtime API** — `codewhale serve --http` for headless agent workflows
|
||||
- **MCP protocol** — connect to Model Context Protocol servers for extended tooling; please see [docs/MCP.md](docs/MCP.md)
|
||||
@@ -210,12 +210,37 @@ codewhale --version
|
||||
|
||||
Prebuilt binaries can also be downloaded from [GitHub Releases](https://github.com/Hmbown/CodeWhale/releases). Use `DEEPSEEK_TUI_RELEASE_BASE_URL` for mirrored release assets.
|
||||
|
||||
### Windows (Scoop)
|
||||
### Windows
|
||||
|
||||
[Scoop](https://scoop.sh) is a Windows package manager. The `codewhale` package is listed
|
||||
in Scoop's main bucket, but that manifest updates independently and can lag the
|
||||
GitHub/npm/Cargo release. Run `scoop update` first, then verify the installed
|
||||
version with `codewhale --version`:
|
||||
Windows x64 is a first-class release target. Use npm or direct GitHub release
|
||||
downloads when you need the newest v0.8.45 binary; Cargo also works when Rust
|
||||
1.88+ and the MSVC toolchain are installed.
|
||||
|
||||
```powershell
|
||||
npm install -g codewhale
|
||||
codewhale --version
|
||||
|
||||
cargo install codewhale-cli --locked --force
|
||||
cargo install codewhale-tui --locked --force
|
||||
```
|
||||
|
||||
Current Windows terminal behavior:
|
||||
|
||||
- interactive sessions always use the TUI-owned alternate screen; the old
|
||||
`--no-alt-screen` flag is accepted for script compatibility but no longer
|
||||
disables the interactive alternate screen
|
||||
- runtime logs stay out of the alternate-screen buffer when `RUST_LOG` or
|
||||
`DEEPSEEK_LOG_LEVEL` is enabled
|
||||
- mouse capture defaults on in Windows Terminal, ConEmu, and Cmder, but stays
|
||||
off in legacy console hosts and JetBrains terminals; use `--mouse-capture` or
|
||||
`--no-mouse-capture` to override
|
||||
- mouse-wheel-as-arrow terminals keep composer history usable by routing empty
|
||||
composer Up/Down to transcript scrolling where appropriate
|
||||
|
||||
[Scoop](https://scoop.sh) is also supported. The `deepseek-tui` package is
|
||||
listed in Scoop's main bucket, but that manifest updates independently and can
|
||||
lag the GitHub/npm/Cargo release. Run `scoop update` first, then verify the
|
||||
installed version with `codewhale --version`:
|
||||
|
||||
```bash
|
||||
scoop update
|
||||
@@ -248,17 +273,27 @@ Both binaries are required. Cross-compilation and platform-specific notes: [docs
|
||||
|
||||
</details>
|
||||
|
||||
### Other API Providers
|
||||
### Providers
|
||||
|
||||
Official DeepSeek remains the default and first-class path. Other providers are
|
||||
additive, with OpenRouter starting from DeepSeek Pro/Flash before broader
|
||||
open-model catalogs are enabled.
|
||||
Official DeepSeek remains the default and first-class path. v0.8.45 supports
|
||||
all 12 provider IDs in this order: `deepseek`, `nvidia-nim`, `openai`,
|
||||
`atlascloud`, `wanjie-ark`, `openrouter`, `novita`, `fireworks`, `moonshot`,
|
||||
`sglang`, `vllm`, and `ollama`. Other providers are additive, with OpenRouter
|
||||
starting from DeepSeek Pro/Flash before broader open-model catalogs are enabled.
|
||||
|
||||
```bash
|
||||
# DeepSeek (default)
|
||||
codewhale auth set --provider deepseek --api-key "YOUR_DEEPSEEK_API_KEY"
|
||||
codewhale --provider deepseek --model deepseek-v4-pro
|
||||
|
||||
# NVIDIA NIM
|
||||
codewhale auth set --provider nvidia-nim --api-key "YOUR_NVIDIA_API_KEY"
|
||||
codewhale --provider nvidia-nim
|
||||
|
||||
# Generic OpenAI-compatible endpoint
|
||||
codewhale auth set --provider openai --api-key "YOUR_OPENAI_COMPATIBLE_API_KEY"
|
||||
OPENAI_BASE_URL="https://openai-compatible.example/v4" codewhale --provider openai --model deepseek-v4-pro
|
||||
|
||||
# AtlasCloud
|
||||
codewhale auth set --provider atlascloud --api-key "YOUR_ATLASCLOUD_API_KEY"
|
||||
codewhale --provider atlascloud
|
||||
@@ -283,9 +318,11 @@ codewhale --provider fireworks --model deepseek-v4-pro
|
||||
codewhale auth set --provider moonshot --api-key "YOUR_MOONSHOT_OR_KIMI_API_KEY"
|
||||
codewhale --provider moonshot --model kimi-k2.6
|
||||
|
||||
# Generic OpenAI-compatible endpoint
|
||||
codewhale auth set --provider openai --api-key "YOUR_OPENAI_COMPATIBLE_API_KEY"
|
||||
OPENAI_BASE_URL="https://openai-compatible.example/v4" codewhale --provider openai --model deepseek-v4-pro
|
||||
# Moonshot/Kimi with Kimi CLI OAuth
|
||||
kimi login
|
||||
mkdir -p ~/.deepseek
|
||||
printf 'provider = "moonshot"\n\n[providers.moonshot]\nauth_mode = "kimi_oauth"\n' >> ~/.deepseek/config.toml
|
||||
codewhale --provider moonshot --model kimi-for-coding
|
||||
|
||||
# Self-hosted SGLang
|
||||
SGLANG_BASE_URL="http://localhost:30000/v1" codewhale --provider sglang --model deepseek-v4-flash
|
||||
@@ -466,15 +503,16 @@ Key environment variables:
|
||||
| `DEEPSEEK_HTTP_HEADERS` | Optional custom model request headers, e.g. `X-Model-Provider-Id=your-model-provider` |
|
||||
| `DEEPSEEK_MODEL` | Default model |
|
||||
| `DEEPSEEK_STREAM_IDLE_TIMEOUT_SECS` | Stream idle timeout in seconds, default `300`, clamped to `1..=3600` |
|
||||
| `DEEPSEEK_PROVIDER` | `codewhale` (default), `nvidia-nim`, `openai`, `atlascloud`, `wanjie-ark`, `openrouter`, `novita`, `fireworks`, `moonshot`, `sglang`, `vllm`, `ollama` |
|
||||
| `DEEPSEEK_PROVIDER` | `deepseek` (default), `nvidia-nim`, `openai`, `atlascloud`, `wanjie-ark`, `openrouter`, `novita`, `fireworks`, `moonshot`, `sglang`, `vllm`, `ollama` |
|
||||
| `DEEPSEEK_PROFILE` | Config profile name |
|
||||
| `DEEPSEEK_MEMORY` | Set to `on` to enable user memory |
|
||||
| `DEEPSEEK_ALLOW_INSECURE_HTTP=1` | Allow non-local `http://` API base URLs on trusted networks |
|
||||
| `NVIDIA_API_KEY` / `OPENAI_API_KEY` / `ATLASCLOUD_API_KEY` / `WANJIE_ARK_API_KEY` / `OPENROUTER_API_KEY` / `NOVITA_API_KEY` / `FIREWORKS_API_KEY` / `MOONSHOT_API_KEY` / `KIMI_API_KEY` / `SGLANG_API_KEY` / `VLLM_API_KEY` / `OLLAMA_API_KEY` | Provider auth |
|
||||
| `NVIDIA_API_KEY` / `NVIDIA_NIM_API_KEY` / `OPENAI_API_KEY` / `ATLASCLOUD_API_KEY` / `WANJIE_ARK_API_KEY` / `WANJIE_API_KEY` / `WANJIE_MAAS_API_KEY` / `OPENROUTER_API_KEY` / `NOVITA_API_KEY` / `FIREWORKS_API_KEY` / `MOONSHOT_API_KEY` / `KIMI_API_KEY` / `SGLANG_API_KEY` / `VLLM_API_KEY` / `OLLAMA_API_KEY` | Provider auth |
|
||||
| `NVIDIA_NIM_BASE_URL` / `NIM_BASE_URL` / `NVIDIA_BASE_URL` | NVIDIA NIM endpoint override |
|
||||
| `OPENAI_BASE_URL` / `OPENAI_MODEL` | Generic OpenAI-compatible endpoint and model ID |
|
||||
| `ATLASCLOUD_BASE_URL` / `ATLASCLOUD_MODEL` | AtlasCloud endpoint and model override |
|
||||
| `WANJIE_ARK_BASE_URL` / `WANJIE_ARK_MODEL` | Wanjie Ark endpoint and model override |
|
||||
| `MOONSHOT_BASE_URL` / `KIMI_BASE_URL` / `MOONSHOT_MODEL` / `KIMI_MODEL` | Moonshot/Kimi endpoint and model override |
|
||||
| `WANJIE_ARK_BASE_URL` / `WANJIE_BASE_URL` / `WANJIE_MAAS_BASE_URL` / `WANJIE_ARK_MODEL` / `WANJIE_MODEL` / `WANJIE_MAAS_MODEL` | Wanjie Ark endpoint and model override |
|
||||
| `MOONSHOT_BASE_URL` / `KIMI_BASE_URL` / `MOONSHOT_MODEL` / `KIMI_MODEL_NAME` / `KIMI_MODEL` | Moonshot/Kimi endpoint and model override |
|
||||
| `OPENROUTER_BASE_URL` | OpenRouter endpoint override |
|
||||
| `NOVITA_BASE_URL` | Novita endpoint override |
|
||||
| `FIREWORKS_BASE_URL` | Fireworks endpoint override |
|
||||
|
||||
+159
-9
@@ -1453,12 +1453,13 @@ fn build_tui_command(
|
||||
| ProviderKind::Openrouter
|
||||
| ProviderKind::Novita
|
||||
| ProviderKind::Fireworks
|
||||
| ProviderKind::Moonshot
|
||||
| ProviderKind::Sglang
|
||||
| ProviderKind::Vllm
|
||||
| ProviderKind::Ollama
|
||||
) {
|
||||
bail!(
|
||||
"The interactive TUI supports DeepSeek, NVIDIA NIM, OpenAI-compatible, AtlasCloud, Wanjie Ark, OpenRouter, Novita, Fireworks, SGLang, vLLM, and Ollama providers. Remove --provider {} or use `codewhale model ...` for provider registry inspection.",
|
||||
"The interactive TUI supports DeepSeek, NVIDIA NIM, OpenAI-compatible, AtlasCloud, Wanjie Ark, OpenRouter, Novita, Fireworks, Moonshot/Kimi, SGLang, vLLM, and Ollama providers. Remove --provider {} or use `codewhale model ...` for provider registry inspection.",
|
||||
resolved_runtime.provider.as_str()
|
||||
);
|
||||
}
|
||||
@@ -1480,14 +1481,10 @@ fn build_tui_command(
|
||||
}
|
||||
if let Some(api_key) = resolved_runtime.api_key.as_ref() {
|
||||
cmd.env("DEEPSEEK_API_KEY", api_key);
|
||||
if resolved_runtime.provider == ProviderKind::Openai {
|
||||
cmd.env("OPENAI_API_KEY", api_key);
|
||||
}
|
||||
if resolved_runtime.provider == ProviderKind::Atlascloud {
|
||||
cmd.env("ATLASCLOUD_API_KEY", api_key);
|
||||
}
|
||||
if resolved_runtime.provider == ProviderKind::WanjieArk {
|
||||
cmd.env("WANJIE_ARK_API_KEY", api_key);
|
||||
for var in provider_env_vars(resolved_runtime.provider) {
|
||||
if *var != "DEEPSEEK_API_KEY" {
|
||||
cmd.env(var, api_key);
|
||||
}
|
||||
}
|
||||
let source = resolved_runtime
|
||||
.api_key_source
|
||||
@@ -2668,6 +2665,159 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_tui_command_allows_moonshot_and_forwards_kimi_key() {
|
||||
let _lock = env_lock();
|
||||
let dir = tempfile::TempDir::new().expect("tempdir");
|
||||
let custom = dir
|
||||
.path()
|
||||
.join(format!("custom-tui{}", std::env::consts::EXE_SUFFIX));
|
||||
std::fs::write(&custom, b"").unwrap();
|
||||
let custom_str = custom.to_string_lossy().into_owned();
|
||||
let _bin = ScopedEnvVar::set("DEEPSEEK_TUI_BIN", &custom_str);
|
||||
|
||||
let cli = parse_ok(&[
|
||||
"codewhale",
|
||||
"--provider",
|
||||
"moonshot",
|
||||
"--model",
|
||||
"kimi-k2.6",
|
||||
"--workspace",
|
||||
"/tmp/codewhale-workspace",
|
||||
]);
|
||||
let resolved = ResolvedRuntimeOptions {
|
||||
provider: ProviderKind::Moonshot,
|
||||
model: "kimi-k2.6".to_string(),
|
||||
api_key: Some("resolved-kimi-key".to_string()),
|
||||
api_key_source: Some(RuntimeApiKeySource::Env),
|
||||
base_url: "https://api.moonshot.ai/v1".to_string(),
|
||||
auth_mode: Some("api_key".to_string()),
|
||||
output_mode: None,
|
||||
log_level: None,
|
||||
telemetry: false,
|
||||
approval_policy: None,
|
||||
sandbox_mode: None,
|
||||
yolo: None,
|
||||
http_headers: std::collections::BTreeMap::new(),
|
||||
};
|
||||
|
||||
let cmd = build_tui_command(&cli, &resolved, Vec::new()).expect("command");
|
||||
assert_eq!(
|
||||
command_env(&cmd, "DEEPSEEK_PROVIDER").as_deref(),
|
||||
Some("moonshot")
|
||||
);
|
||||
assert_eq!(
|
||||
command_env(&cmd, "DEEPSEEK_MODEL").as_deref(),
|
||||
Some("kimi-k2.6")
|
||||
);
|
||||
assert_eq!(
|
||||
command_env(&cmd, "DEEPSEEK_BASE_URL").as_deref(),
|
||||
Some("https://api.moonshot.ai/v1")
|
||||
);
|
||||
assert_eq!(
|
||||
command_env(&cmd, "DEEPSEEK_API_KEY").as_deref(),
|
||||
Some("resolved-kimi-key")
|
||||
);
|
||||
assert_eq!(
|
||||
command_env(&cmd, "MOONSHOT_API_KEY").as_deref(),
|
||||
Some("resolved-kimi-key")
|
||||
);
|
||||
assert_eq!(
|
||||
command_env(&cmd, "KIMI_API_KEY").as_deref(),
|
||||
Some("resolved-kimi-key")
|
||||
);
|
||||
assert_eq!(
|
||||
command_env(&cmd, "DEEPSEEK_API_KEY_SOURCE").as_deref(),
|
||||
Some("env")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_tui_command_forwards_provider_env_vars_for_all_providers() {
|
||||
let _lock = env_lock();
|
||||
let dir = tempfile::TempDir::new().expect("tempdir");
|
||||
let custom = dir
|
||||
.path()
|
||||
.join(format!("custom-tui{}", std::env::consts::EXE_SUFFIX));
|
||||
std::fs::write(&custom, b"").unwrap();
|
||||
let custom_str = custom.to_string_lossy().into_owned();
|
||||
let _bin = ScopedEnvVar::set("DEEPSEEK_TUI_BIN", &custom_str);
|
||||
|
||||
// (provider, cli flag, extra env vars that must be forwarded besides DEEPSEEK_API_KEY)
|
||||
let cases: &[(ProviderKind, &str, &[&str])] = &[
|
||||
(
|
||||
ProviderKind::Openrouter,
|
||||
"openrouter",
|
||||
&["OPENROUTER_API_KEY"],
|
||||
),
|
||||
(ProviderKind::Novita, "novita", &["NOVITA_API_KEY"]),
|
||||
(
|
||||
ProviderKind::NvidiaNim,
|
||||
"nvidia-nim",
|
||||
&["NVIDIA_API_KEY", "NVIDIA_NIM_API_KEY"],
|
||||
),
|
||||
(ProviderKind::Fireworks, "fireworks", &["FIREWORKS_API_KEY"]),
|
||||
(ProviderKind::Sglang, "sglang", &["SGLANG_API_KEY"]),
|
||||
(ProviderKind::Vllm, "vllm", &["VLLM_API_KEY"]),
|
||||
(ProviderKind::Ollama, "ollama", &["OLLAMA_API_KEY"]),
|
||||
(
|
||||
ProviderKind::Atlascloud,
|
||||
"atlascloud",
|
||||
&["ATLASCLOUD_API_KEY"],
|
||||
),
|
||||
(
|
||||
ProviderKind::WanjieArk,
|
||||
"wanjie-ark",
|
||||
&[
|
||||
"WANJIE_ARK_API_KEY",
|
||||
"WANJIE_API_KEY",
|
||||
"WANJIE_MAAS_API_KEY",
|
||||
],
|
||||
),
|
||||
];
|
||||
|
||||
for &(provider, flag, expected_vars) in cases {
|
||||
let cli = parse_ok(&[
|
||||
"codewhale",
|
||||
"--provider",
|
||||
flag,
|
||||
"--workspace",
|
||||
"/tmp/codewhale-workspace",
|
||||
]);
|
||||
let resolved = ResolvedRuntimeOptions {
|
||||
provider,
|
||||
model: "test-model".to_string(),
|
||||
api_key: Some("test-key".to_string()),
|
||||
api_key_source: Some(RuntimeApiKeySource::Env),
|
||||
base_url: "http://localhost:8000/v1".to_string(),
|
||||
auth_mode: Some("api_key".to_string()),
|
||||
output_mode: None,
|
||||
log_level: None,
|
||||
telemetry: false,
|
||||
approval_policy: None,
|
||||
sandbox_mode: None,
|
||||
yolo: None,
|
||||
http_headers: std::collections::BTreeMap::new(),
|
||||
};
|
||||
|
||||
let cmd = build_tui_command(&cli, &resolved, Vec::new())
|
||||
.unwrap_or_else(|e| panic!("{flag}: {e}"));
|
||||
|
||||
assert_eq!(
|
||||
command_env(&cmd, "DEEPSEEK_API_KEY").as_deref(),
|
||||
Some("test-key"),
|
||||
"{flag}: DEEPSEEK_API_KEY not forwarded"
|
||||
);
|
||||
for var in expected_vars {
|
||||
assert_eq!(
|
||||
command_env(&cmd, var).as_deref(),
|
||||
Some("test-key"),
|
||||
"{flag}: {var} not forwarded"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_top_level_prompt_flag_for_canonical_one_shot() {
|
||||
let cli = parse_ok(&["deepseek", "-p", "Reply with exactly OK."]);
|
||||
|
||||
@@ -484,9 +484,7 @@ impl Secrets {
|
||||
|
||||
/// Resolve a secret with `secret store → env → none` precedence.
|
||||
///
|
||||
/// `name` is the canonical provider name (`"deepseek"`,
|
||||
/// `"openrouter"`, `"novita"`, `"nvidia"`/`"nvidia-nim"`, `"openai"`,
|
||||
/// or `"atlascloud"`).
|
||||
/// `name` is the canonical provider name or a supported provider alias.
|
||||
/// Empty strings on either layer are treated as "not set".
|
||||
#[must_use]
|
||||
pub fn resolve(&self, name: &str) -> Option<String> {
|
||||
@@ -779,6 +777,21 @@ mod tests {
|
||||
unsafe { std::env::remove_var("FIREWORKS_API_KEY") };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn moonshot_kimi_env_aliases_resolve() {
|
||||
let _lock = env_lock();
|
||||
clear_known_envs();
|
||||
// Safety: env mutation guarded by env_lock().
|
||||
unsafe { std::env::set_var("KIMI_API_KEY", "kimi-key") };
|
||||
|
||||
assert_eq!(env_for("moonshot").as_deref(), Some("kimi-key"));
|
||||
assert_eq!(env_for("moonshot-ai").as_deref(), Some("kimi-key"));
|
||||
assert_eq!(env_for("kimi").as_deref(), Some("kimi-key"));
|
||||
assert_eq!(env_for("kimi-k2").as_deref(), Some("kimi-key"));
|
||||
// Safety: env mutation guarded by env_lock().
|
||||
unsafe { std::env::remove_var("KIMI_API_KEY") };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sglang_env_aliases_resolve() {
|
||||
let _lock = env_lock();
|
||||
|
||||
@@ -14,6 +14,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- **RLM session objects.** `rlm_open` can now load `session://` refs,
|
||||
exposing the active prompt, history, and session data as symbolic objects
|
||||
inside RLM REPLs (#2047).
|
||||
- **Command palette voice input.** The command palette can launch a configured
|
||||
speech-to-text helper and show footer status while transcription runs
|
||||
(#2047).
|
||||
- **Moonshot/Kimi OAuth provider.** Moonshot/Kimi is now a first-class
|
||||
provider, including Kimi CLI OAuth reuse, secure refresh writes, model
|
||||
completion, CLI auth, and secret-store integration.
|
||||
- **Deterministic whale-species sub-agent names.** Sub-agents now get stable,
|
||||
human-readable whale-species nicknames (e.g. "Beluga", "Orca") while
|
||||
preserving the raw agent ID in the popup (#2035, #2016).
|
||||
@@ -52,6 +58,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
Thanks @reidliu41 (#2143).
|
||||
- **Model picker selection survives Esc.** Dismissing the model picker with Esc
|
||||
no longer loses the highlighted selection. Thanks @reidliu41 (#2056).
|
||||
- **Moonshot/Kimi sessions launch from the dispatcher.** The `codewhale`
|
||||
wrapper now includes Moonshot/Kimi in the TUI provider allowlist, so
|
||||
`codewhale --provider moonshot --model kimi-k2.6` reaches the TUI instead of
|
||||
stopping after config resolution.
|
||||
- **Slash recovery no longer restores command tails in the composer.**
|
||||
Resuming a session or recovering from a crash no longer leaves stale
|
||||
slash-command text (e.g. `/sessions`) in the composer input (#2047, #2032).
|
||||
|
||||
@@ -121,7 +121,7 @@ export default async function DocsPage({ params }: { params: Promise<{ locale: s
|
||||
{ group: "Git / 诊断 / 测试", tools: "git_status · git_diff · diagnostics · run_tests" },
|
||||
{ group: "子 Agent", tools: "agent_open · agent_eval · agent_close —— 持久会话,并行执行,通过 var_handle 读取大结果" },
|
||||
{ group: "递归 LM (RLM)", tools: "rlm_open · rlm_eval · rlm_configure · rlm_close —— 沙箱 Python REPL,内置 peek/search/chunk/sub_query_batch 等辅助函数" },
|
||||
{ group: "MCP", tools: "mcp_<server>_<tool>——从 ~/.codewhale/mcp.json 自动注册" },
|
||||
{ group: "MCP", tools: "mcp_<server>_<tool>——从 ~/.deepseek/mcp.json 自动注册" },
|
||||
].map((row) => (
|
||||
<div key={row.group} className="grid md:grid-cols-12 gap-0 hairline-t py-3 px-4 hover:bg-paper-deep transition-colors min-w-0">
|
||||
<div className="md:col-span-3 font-display text-sm font-semibold">{row.group}</div>
|
||||
@@ -152,8 +152,8 @@ export default async function DocsPage({ params }: { params: Promise<{ locale: s
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-5 text-ink-soft leading-[1.9] tracking-wide">
|
||||
沙箱:{facts.sandboxBackends.join("、")}。工作区边界默认为 <code className="inline">--workspace</code>。
|
||||
<code className="inline">/trust</code> 可解除边界限制。
|
||||
沙箱:{facts.sandboxBackends.join("、")}。Windows 当前不宣称 OS 级文件系统沙箱,但保留同样的审批、工作区边界和终端运行时保护。
|
||||
<code className="inline">/trust</code> 可解除工作区边界限制。
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@@ -163,7 +163,7 @@ export default async function DocsPage({ params }: { params: Promise<{ locale: s
|
||||
配置 <span className="font-cjk text-indigo text-2xl ml-2">Configuration</span>
|
||||
</h2>
|
||||
<pre className="code-block mt-5">
|
||||
{`# ~/.codewhale/config.toml
|
||||
{`# ~/.deepseek/config.toml
|
||||
api_key = "sk-..."
|
||||
base_url = "https://api.deepseek.com"
|
||||
default_text_model = "${facts.defaultModel ?? "deepseek-v4-pro"}" # 默认模型;deepseek-v4-flash 用于快速 / 子智能体
|
||||
@@ -179,7 +179,7 @@ default_timeout_secs = 30
|
||||
|
||||
[[hooks.hooks]]
|
||||
event = "session_start" # 也支持: tool_call_before / tool_call_after
|
||||
command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change / on_error / shell_env`}
|
||||
command = "~/.deepseek/hooks/pre.sh" # / message_submit / mode_change / on_error / shell_env`}
|
||||
</pre>
|
||||
<p className="mt-4 text-sm text-ink-soft">
|
||||
完整参考:<Link className="body-link" href="https://github.com/Hmbown/CodeWhale/blob/main/config.example.toml">config.example.toml</Link>。
|
||||
@@ -193,7 +193,7 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
</h2>
|
||||
<p className="text-ink-soft mt-3 leading-[1.9] tracking-wide">
|
||||
<code className="inline">codewhale</code> 双向支持模型上下文协议(Model Context Protocol):作为客户端从
|
||||
<code className="inline">~/.codewhale/mcp.json</code> 加载服务器,同时也可作为服务器暴露工具
|
||||
<code className="inline">~/.deepseek/mcp.json</code> 加载服务器,同时也可作为服务器暴露工具
|
||||
(<code className="inline">codewhale mcp</code>)。工具以 <code className="inline">mcp_<server>_<tool></code> 形式呈现。
|
||||
</p>
|
||||
<pre className="code-block mt-5">
|
||||
@@ -218,7 +218,7 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
技能 <span className="font-cjk text-indigo text-2xl ml-2">Skills</span>
|
||||
</h2>
|
||||
<p className="text-ink-soft mt-3 leading-[1.9] tracking-wide">
|
||||
技能是 <code className="inline">~/.codewhale/skills/<name>/</code> 下的一个文件夹,
|
||||
技能是 <code className="inline">~/.deepseek/skills/<name>/</code> 下的一个文件夹,
|
||||
根目录包含 <code className="inline">SKILL.md</code>。Agent 启动时加载技能名称和描述,
|
||||
在需要时通过 Skill 工具拉取完整内容。
|
||||
</p>
|
||||
@@ -253,7 +253,7 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
<p className="text-ink-soft mt-3 leading-[1.9] tracking-wide">
|
||||
使用 <code className="inline">codewhale auth set --provider <id></code> 切换。下表为
|
||||
<code className="inline">crates/tui/src/config.rs</code> 中 <code className="inline">ApiProvider</code> 枚举的实时投影
|
||||
,目前共 {facts.providers.length} 个。
|
||||
,v0.8.45 当前共 {facts.providers.length} 个。
|
||||
</p>
|
||||
<div className="hairline-t hairline-b mt-5">
|
||||
{facts.providers.map((p) => (
|
||||
@@ -265,9 +265,8 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-5 text-ink-soft leading-[1.9] tracking-wide">
|
||||
开放模型平台方向:CodeWhale 正在扩展对
|
||||
<strong> OpenRouter</strong>、<strong> Hugging Face</strong> 和<strong> 自托管</strong> 模型的支持,
|
||||
为您提供完全自主的模型选择——从云端 API 到本地部署均可覆盖。
|
||||
开放模型平台方向:CodeWhale 保持 DeepSeek 优先,同时内置 Moonshot/Kimi、OpenRouter、NVIDIA NIM、
|
||||
AtlasCloud、Wanjie Ark、Novita、Fireworks 和自托管 SGLang/vLLM/Ollama 路径。
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@@ -373,7 +372,7 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
{ group: "Git / diag / test", tools: "git_status · git_diff · diagnostics · run_tests" },
|
||||
{ group: "Sub-agents", tools: "agent_open · agent_eval · agent_close — persistent sessions, parallel execution, bounded result retrieval via var_handle" },
|
||||
{ group: "Recursive LM (RLM)", tools: "rlm_open · rlm_eval · rlm_configure · rlm_close — sandboxed Python REPL with peek/search/chunk/sub_query_batch helpers" },
|
||||
{ group: "MCP", tools: "mcp_<server>_<tool> — auto-registered from ~/.codewhale/mcp.json" },
|
||||
{ group: "MCP", tools: "mcp_<server>_<tool> — auto-registered from ~/.deepseek/mcp.json" },
|
||||
].map((row) => (
|
||||
<div key={row.group} className="grid md:grid-cols-12 gap-0 hairline-t py-3 px-4 hover:bg-paper-deep transition-colors min-w-0">
|
||||
<div className="md:col-span-3 font-display text-sm font-semibold">{row.group}</div>
|
||||
@@ -403,8 +402,9 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-5 text-ink-soft leading-relaxed">
|
||||
Sandbox: {facts.sandboxBackends.join(", ")}. Workspace boundary defaults to{" "}
|
||||
<code className="inline">--workspace</code>. <code className="inline">/trust</code> lifts the boundary.
|
||||
Sandbox: {facts.sandboxBackends.join(", ")}. On Windows, CodeWhale does not advertise
|
||||
OS-level filesystem isolation yet, but keeps the same approvals, workspace boundary,
|
||||
and terminal runtime protections. <code className="inline">/trust</code> lifts the workspace boundary.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@@ -413,7 +413,7 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
Configuration <span className="font-cjk text-indigo text-2xl ml-2">配置</span>
|
||||
</h2>
|
||||
<pre className="code-block mt-5">
|
||||
{`# ~/.codewhale/config.toml
|
||||
{`# ~/.deepseek/config.toml
|
||||
api_key = "sk-..."
|
||||
base_url = "https://api.deepseek.com"
|
||||
default_text_model = "${facts.defaultModel ?? "deepseek-v4-pro"}" # default; deepseek-v4-flash is the fast / sub-agent option
|
||||
@@ -429,7 +429,7 @@ default_timeout_secs = 30
|
||||
|
||||
[[hooks.hooks]]
|
||||
event = "session_start" # or: tool_call_before / tool_call_after
|
||||
command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change / on_error / shell_env`}
|
||||
command = "~/.deepseek/hooks/pre.sh" # / message_submit / mode_change / on_error / shell_env`}
|
||||
</pre>
|
||||
<p className="mt-4 text-sm text-ink-soft">
|
||||
Full reference: <Link className="body-link" href="https://github.com/Hmbown/CodeWhale/blob/main/config.example.toml">config.example.toml</Link>.
|
||||
@@ -442,7 +442,7 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
</h2>
|
||||
<p className="text-ink-soft mt-3 leading-relaxed">
|
||||
<code className="inline">codewhale</code> speaks the Model Context Protocol both ways: as a client (loads
|
||||
servers from <code className="inline">~/.codewhale/mcp.json</code>) and as a server
|
||||
servers from <code className="inline">~/.deepseek/mcp.json</code>) and as a server
|
||||
(<code className="inline">codewhale mcp</code>). Tools surface as <code className="inline">mcp_<server>_<tool></code>.
|
||||
</p>
|
||||
<pre className="code-block mt-5">
|
||||
@@ -466,7 +466,7 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
Skills <span className="font-cjk text-indigo text-2xl ml-2">技能</span>
|
||||
</h2>
|
||||
<p className="text-ink-soft mt-3 leading-relaxed">
|
||||
A skill is a folder under <code className="inline">~/.codewhale/skills/<name>/</code>
|
||||
A skill is a folder under <code className="inline">~/.deepseek/skills/<name>/</code>
|
||||
with a <code className="inline">SKILL.md</code> at the root. The agent loads skill names + descriptions on
|
||||
startup and can pull in the full body via the Skill tool when relevant.
|
||||
</p>
|
||||
@@ -500,7 +500,7 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
<p className="text-ink-soft mt-3 leading-relaxed">
|
||||
Switch with <code className="inline">codewhale auth set --provider <id></code>. The
|
||||
table below is a live projection of the <code className="inline">ApiProvider</code> enum
|
||||
in <code className="inline">crates/tui/src/config.rs</code> — currently {facts.providers.length} providers.
|
||||
in <code className="inline">crates/tui/src/config.rs</code> — v0.8.45 currently has {facts.providers.length} providers.
|
||||
</p>
|
||||
<div className="hairline-t hairline-b mt-5">
|
||||
{facts.providers.map((p) => (
|
||||
@@ -512,9 +512,9 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-5 text-ink-soft leading-relaxed">
|
||||
Open-model platform direction: CodeWhale is expanding support for
|
||||
<strong> OpenRouter</strong>, <strong> Hugging Face</strong>, and <strong> self-hosted</strong> models,
|
||||
giving you full sovereignty over model choice — from cloud APIs to local deployments.
|
||||
Open-model platform direction: CodeWhale stays DeepSeek-first while shipping Moonshot/Kimi,
|
||||
OpenRouter, NVIDIA NIM, AtlasCloud, Wanjie Ark, Novita, Fireworks, and self-hosted
|
||||
SGLang/vLLM/Ollama paths.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@@ -547,4 +547,4 @@ command = "~/.codewhale/hooks/pre.sh" # / message_submit / mode_change /
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ const faqEn: FaqItem[] = [
|
||||
q: "What is CodeWhale?",
|
||||
a: (
|
||||
<>
|
||||
CodeWhale is a terminal-native coding agent for open-source and open-weight models. It runs from the <code className="inline">codewhale</code> command, streams reasoning blocks, edits local workspaces with approval gates, and can auto-route each turn to the right model and thinking level. DeepSeek V4 is the first-class model path; OpenRouter is ready. Hugging Face, self-hosted, and other open-model surfaces are on the roadmap.
|
||||
CodeWhale is a terminal-native coding agent for open-source and open-weight models. It runs from the <code className="inline">codewhale</code> command, streams reasoning blocks, edits local workspaces with approval gates, and can auto-route each turn to the right model and thinking level. DeepSeek V4 is the first-class model path; v0.8.45 also ships Moonshot/Kimi, OpenRouter, NVIDIA NIM, OpenAI-compatible, AtlasCloud, Wanjie Ark, Novita, Fireworks, SGLang, vLLM, and Ollama paths.
|
||||
</>
|
||||
),
|
||||
sources: ["README.md", "docs/ARCHITECTURE.md"],
|
||||
@@ -112,12 +112,13 @@ codewhale doctor # full connectivity check`}
|
||||
<p className="mb-2">CodeWhale ships with these built-in providers:</p>
|
||||
<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>Moonshot/Kimi</strong> — Kimi API key mode or local Kimi CLI OAuth reuse.</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-compatible</strong>, <strong>NVIDIA NIM</strong>, <strong>AtlasCloud</strong>, <strong>Wanjie Ark</strong>, <strong>Novita</strong>, <strong>Fireworks</strong>, <strong>SGLang</strong>, <strong>vLLM</strong>, <strong>Ollama</strong></li>
|
||||
</ul>
|
||||
<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>.
|
||||
Hugging Face, ZenMux, and self-hosted OpenAI-compatible endpoints are on the roadmap.
|
||||
SGLang, vLLM, and Ollama can also run against self-hosted OpenAI-compatible endpoints.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@@ -156,7 +157,7 @@ default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
|
||||
Yes. Use the <code className="inline">vllm</code>, <code className="inline">sglang</code>, or <code className="inline">ollama</code> providers with your local endpoint.
|
||||
For OpenAI-compatible endpoints (llama.cpp server, text-generation-webui, Aphrodite, etc.), you can use the <code className="inline">openai</code> provider with a custom <code className="inline">base_url</code>.
|
||||
CodeWhale also respects <code className="inline">DEEPSEEK_ALLOW_INSECURE_HTTP=true</code> for local HTTP endpoints.
|
||||
Full Hugging Face TGI/vLLM integration is on the roadmap.
|
||||
Direct Hugging Face TGI discovery remains roadmap work.
|
||||
</>
|
||||
),
|
||||
sources: ["#574", "#1303", "docs/CONFIGURATION.md"],
|
||||
@@ -211,7 +212,7 @@ default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
|
||||
a: (
|
||||
<>
|
||||
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). Windows keeps the same approval and terminal runtime protections, but does not advertise OS-level filesystem isolation yet.
|
||||
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>.
|
||||
</>
|
||||
@@ -336,7 +337,7 @@ const faqZh: FaqItem[] = [
|
||||
q: "CodeWhale 是什么?",
|
||||
a: (
|
||||
<>
|
||||
CodeWhale 是一个面向开源模型的终端原生编程智能体。通过 <code className="inline">codewhale</code> 命令启动,流式输出推理块,在有审批门槛的情况下编辑本地工作区,并可为每个回合自动选择最合适的模型和推理深度。DeepSeek V4 是一级模型路径;OpenRouter 已就绪。Hugging Face、自托管等开放模型接口已在路线图中。
|
||||
CodeWhale 是一个面向开源模型的终端原生编程智能体。通过 <code className="inline">codewhale</code> 命令启动,流式输出推理块,在有审批门槛的情况下编辑本地工作区,并可为每个回合自动选择最合适的模型和推理深度。DeepSeek V4 是一级模型路径;v0.8.45 也内置 Moonshot/Kimi、OpenRouter、NVIDIA NIM、OpenAI 兼容、AtlasCloud、Wanjie Ark、Novita、Fireworks、SGLang、vLLM 和 Ollama 路径。
|
||||
</>
|
||||
),
|
||||
sources: ["README.md", "docs/ARCHITECTURE.md"],
|
||||
@@ -424,12 +425,13 @@ codewhale doctor # 完整连接检查`}
|
||||
<p className="mb-2">CodeWhale 内建以下提供商:</p>
|
||||
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft mb-3">
|
||||
<li><strong>DeepSeek</strong> — 一级支持,原生 API。推理流、缓存指标、思考力度控制。</li>
|
||||
<li><strong>Moonshot/Kimi</strong> — Kimi API key 模式或复用本地 Kimi CLI OAuth。</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>AtlasCloud</strong>、<strong>Wanjie Ark</strong>、<strong>Novita</strong>、<strong>Fireworks</strong>、<strong>SGLang</strong>、<strong>vLLM</strong>、<strong>Ollama</strong></li>
|
||||
</ul>
|
||||
<p>
|
||||
设置对应的环境变量(如 <code className="inline">OPENROUTER_API_KEY</code>)并在 <code className="inline">~/.deepseek/config.toml</code> 中配置你的提供商。
|
||||
Hugging Face、ZenMux 和自托管 OpenAI 兼容端点正在路线图中。
|
||||
SGLang、vLLM 和 Ollama 也可以连接自托管 OpenAI 兼容端点。
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@@ -468,7 +470,7 @@ default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
|
||||
可以。使用 <code className="inline">vllm</code>、<code className="inline">sglang</code> 或 <code className="inline">ollama</code> 提供商连接本地端点。
|
||||
对于 OpenAI 兼容端点(llama.cpp server、text-generation-webui 等),可以使用 <code className="inline">openai</code> 提供商并设置自定义 <code className="inline">base_url</code>。
|
||||
CodeWhale 也支持 <code className="inline">DEEPSEEK_ALLOW_INSECURE_HTTP=true</code> 用于本地 HTTP 端点。
|
||||
完整的 Hugging Face TGI/vLLM 集成正在路线图中。
|
||||
Hugging Face TGI 的直接发现仍在路线图中。
|
||||
</>
|
||||
),
|
||||
sources: ["#574", "#1303", "docs/CONFIGURATION.md"],
|
||||
@@ -523,7 +525,7 @@ default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
|
||||
a: (
|
||||
<>
|
||||
CodeWhale 完全在你的机器上运行。无遥测,不会将你的代码上传到云端处理。
|
||||
沙箱后端:<strong>seatbelt</strong>(macOS)、<strong>landlock</strong>(Linux)、受限令牌(Windows)。
|
||||
沙箱后端:<strong>seatbelt</strong>(macOS)、<strong>landlock</strong>(Linux)。Windows 保留同样的审批与终端运行时保护,但当前不宣称 OS 级文件系统沙箱。
|
||||
工作区边界默认为 <code className="inline">--workspace</code>。<code className="inline">/trust</code> 可解除边界。
|
||||
审批模式可按会话配置。所有凭证/审批/提权事件写入 <code className="inline">~/.deepseek/audit.log</code>。
|
||||
</>
|
||||
|
||||
+11
-11
@@ -15,7 +15,7 @@ const FALLBACK_STATS: RepoStats = {
|
||||
forks: 0,
|
||||
openIssues: 0,
|
||||
openPulls: 0,
|
||||
contributors: 98,
|
||||
contributors: 99,
|
||||
fetchedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
@@ -94,8 +94,8 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
||||
<p className="mt-6 text-lg text-ink-soft leading-relaxed max-w-2xl">
|
||||
<span className="font-cjk text-indigo font-semibold">CodeWhale</span>
|
||||
{isZh
|
||||
? " 是面向 DeepSeek V4 及其他开放权重模型的终端原生编程智能体。它读改文件、跑测试、调用 MCP 服务器,全程在你的文件系统沙箱内运行。"
|
||||
: " is a terminal-native coding agent for DeepSeek V4 and other open-weight models. It reads and edits files, runs tests, calls MCP servers — all inside your filesystem sandbox."}
|
||||
? " 是面向 DeepSeek V4 及其他开放权重模型的终端原生编程智能体。它读改文件、跑测试、调用 MCP 服务器,并通过审批、工作区边界和平台沙箱控制风险。"
|
||||
: " is a terminal-native coding agent for DeepSeek V4 and other open-weight models. It reads and edits files, runs tests, calls MCP servers, and controls risk through approvals, workspace boundaries, and platform sandboxes."}
|
||||
</p>
|
||||
|
||||
<div className="mt-8 flex flex-wrap items-stretch sm:items-center gap-3">
|
||||
@@ -155,7 +155,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
||||
)}
|
||||
</pre>
|
||||
<div className="mt-3 flex items-center justify-between text-[0.7rem] font-mono text-ink-mute">
|
||||
<span>{isZh ? "需要 Node 或 Rust 1.88+" : "needs Node or Rust 1.88+"}</span>
|
||||
<span>{isZh ? "Linux / macOS / Windows x64" : "Linux / macOS / Windows x64"}</span>
|
||||
<Link href={isZh ? "/zh/install" : "/install"} className="text-indigo hover:underline">{isZh ? "其他方式 →" : "other ways →"}</Link>
|
||||
</div>
|
||||
</div>
|
||||
@@ -188,14 +188,14 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
||||
<div className="eyebrow mb-3">02 · 开源模型优先</div>
|
||||
<h3 className="font-display text-xl mb-3">DeepSeek V4 深度集成</h3>
|
||||
<p className="text-sm text-ink-soft leading-[1.9]">
|
||||
原生 DeepSeek API:推理流、缓存指标、思考力度控制。OpenRouter、NVIDIA NIM、vLLM、sglang 同时可选。
|
||||
原生 DeepSeek API:推理流、缓存指标、思考力度控制。Moonshot/Kimi、OpenRouter、NVIDIA NIM、vLLM、SGLang 等同时可选。
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="eyebrow mb-3">03 · 沙箱边界</div>
|
||||
<h3 className="font-display text-xl mb-3">Plan、Agent、YOLO</h3>
|
||||
<p className="text-sm text-ink-soft leading-[1.9]">
|
||||
Plan 只读;Agent 风险操作前确认;YOLO 全自动。沙箱:seatbelt(macOS)、landlock(Linux)、受限令牌(Windows)。
|
||||
Plan 只读;Agent 风险操作前确认;YOLO 全自动。macOS 使用 seatbelt,Linux 使用 landlock;Windows 保留同样的审批与终端保护。
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
@@ -212,14 +212,14 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
||||
<div className="eyebrow mb-3">02 · open models first</div>
|
||||
<h3 className="font-display text-xl mb-3">DeepSeek V4, deeply integrated</h3>
|
||||
<p className="text-sm text-ink-soft leading-relaxed">
|
||||
Native DeepSeek API: reasoning streaming, cache metrics, thinking-effort control. OpenRouter, NVIDIA NIM, vLLM, and sglang also supported.
|
||||
Native DeepSeek API: reasoning streaming, cache metrics, thinking-effort control. Moonshot/Kimi, OpenRouter, NVIDIA NIM, vLLM, and SGLang are also supported.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="eyebrow mb-3">03 · sandboxed</div>
|
||||
<div className="eyebrow mb-3">03 · controlled</div>
|
||||
<h3 className="font-display text-xl mb-3">Plan, Agent, YOLO</h3>
|
||||
<p className="text-sm text-ink-soft leading-relaxed">
|
||||
Plan reads only. Agent asks before risky ops. YOLO auto-approves. Sandboxed via seatbelt (macOS), landlock (Linux), restricted tokens (Windows).
|
||||
Plan reads only. Agent asks before risky ops. YOLO auto-approves. macOS uses seatbelt, Linux uses landlock; Windows keeps the same approval and terminal protections.
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
@@ -325,7 +325,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
||||
B -->|tool call| T["read_file · edit_file · grep<br/>apply_patch · exec_shell<br/>mcp_<server>_<tool>"]
|
||||
T -->|approval Y/N| P["审批对话框<br/>approval dialog"]
|
||||
P --> B
|
||||
T -->|exec| S["沙箱<br/>seatbelt · landlock · win32"]
|
||||
T -->|exec| S["平台控制<br/>seatbelt · landlock · approvals"]
|
||||
classDef accent fill:#e9eefe,stroke:#0e0e10,stroke-width:1px;
|
||||
classDef api fill:#0e0e10,stroke:#0e0e10,color:#ffffff;
|
||||
class C api;
|
||||
@@ -337,7 +337,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
|
||||
B -->|tool call| T["read_file · edit_file · grep<br/>apply_patch · exec_shell<br/>mcp_<server>_<tool>"]
|
||||
T -->|approval Y/N| P["Approval<br/>dialog"]
|
||||
P --> B
|
||||
T -->|exec| S["Sandbox<br/>seatbelt · landlock · win32"]
|
||||
T -->|exec| S["Platform controls<br/>seatbelt · landlock · approvals"]
|
||||
classDef accent fill:#e9eefe,stroke:#0e0e10,stroke-width:1px;
|
||||
classDef api fill:#0e0e10,stroke:#0e0e10,color:#ffffff;
|
||||
class C api;
|
||||
|
||||
@@ -26,12 +26,12 @@ const tracksEn = [
|
||||
{ title: "Sub-agent parallel execution", note: "agent_open / agent_eval / agent_close; up to 10 concurrent sessions with bounded result handles" },
|
||||
{ title: "RLM batched processing", note: "Persistent sandboxed Python REPL with 1–16 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: "Per-platform sandbox", note: "seatbelt (macOS), landlock (Linux); Windows containment via restricted tokens (limited)" },
|
||||
{ title: "Per-platform controls", note: "seatbelt (macOS), landlock (Linux); Windows keeps approvals and terminal/runtime protections while OS sandbox work remains tracked" },
|
||||
{ title: "Durable sessions + tasks", note: "Save, resume, rollback; background task queue with replayable timelines under ~/.deepseek/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`; ~/.deepseek/mcp.json" },
|
||||
{ title: "Skills + unified slash palette", note: "~/.deepseek/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: "Multi-provider support", note: "Hot-swap between providers (DeepSeek, OpenAI, Anthropic, OpenRouter) per session" },
|
||||
{ title: "v0.8.45 provider surface", note: "DeepSeek, NVIDIA NIM, OpenAI-compatible, AtlasCloud, Wanjie Ark, OpenRouter, Novita, Fireworks, Moonshot/Kimi, SGLang, vLLM, and Ollama" },
|
||||
{ title: "Moonshot/Kimi OAuth", note: "Kimi CLI OAuth reuse plus API-key mode for Moonshot/Kimi sessions" },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -43,8 +43,8 @@ const tracksEn = [
|
||||
{ title: "Memory typed store", note: "SQLite + FTS5 backend with graph-structured agent memory and multi-signal recall (#534–#536)" },
|
||||
{ title: "Feishu / Lark bot", note: "Chat-platform frontend over the existing runtime API (#757)" },
|
||||
{ title: "Chinese-market & i18n", note: "Locale-aware UI, platform refinements, region-specific search backends (#755)" },
|
||||
{ title: "Hugging Face model discovery + Model Lab", note: "Browse, download, and manage models from Hugging Face Hub directly in the TUI" },
|
||||
{ title: "ZenMux / OpenAI-compatible providers", note: "Bring any OpenAI-compatible endpoint (vLLM, LiteLLM, Ollama, local) as a first-class provider" },
|
||||
{ title: "Model Lab", note: "Curated model discovery and benchmarking for open-weight and self-hosted workflows" },
|
||||
{ title: "Provider billing and catalogs", note: "/balance capability layer plus richer live model catalogs for providers that expose listing endpoints" },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -92,12 +92,12 @@ const tracksZh = [
|
||||
{ title: "子 Agent 并行执行", note: "agent_open / agent_eval / agent_close;最多 10 个并发会话,通过 var_handle 有界读取结果" },
|
||||
{ title: "RLM 批量处理", note: "持久沙箱 Python REPL,支持 1–16 路廉价并行子调用,处理长文本分析" },
|
||||
{ title: "三种运行模式", note: "Plan(只读)、Agent(默认)、YOLO(自动批准);审批模式正交(建议/自动/拒绝)" },
|
||||
{ title: "跨平台沙箱", note: "seatbelt(macOS)、landlock(Linux);Windows 通过受限令牌实现基础隔离(功能有限)" },
|
||||
{ title: "跨平台控制", note: "seatbelt(macOS)、landlock(Linux);Windows 保留审批与终端运行时保护,OS 沙箱仍在跟踪中" },
|
||||
{ title: "持久化会话 + 后台任务", note: "保存、恢复、回滚;后台任务队列,可回放时间线,位于 ~/.deepseek/tasks/" },
|
||||
{ title: "双向 MCP 协议", note: "消费外部服务器工具;通过 `deepseek mcp` 暴露为服务器;~/.deepseek/mcp.json" },
|
||||
{ title: "双向 MCP 协议", note: "消费外部服务器工具;通过 `codewhale mcp` 暴露为服务器;~/.deepseek/mcp.json" },
|
||||
{ title: "技能 + 统一命令面板", note: "~/.deepseek/skills/ 自动加载;/help、/mode、/status、/config、/trust、/feedback" },
|
||||
{ title: "OpenRouter 提供商", note: "原生集成 OpenRouter,支持 300+ 模型,覆盖数十个提供商" },
|
||||
{ title: "多提供商支持", note: "按会话动态切换提供商(DeepSeek、OpenAI、Anthropic、OpenRouter)" },
|
||||
{ title: "v0.8.45 提供商表面", note: "DeepSeek、NVIDIA NIM、OpenAI 兼容、AtlasCloud、Wanjie Ark、OpenRouter、Novita、Fireworks、Moonshot/Kimi、SGLang、vLLM、Ollama" },
|
||||
{ title: "Moonshot/Kimi OAuth", note: "复用 Kimi CLI OAuth,也支持 Moonshot/Kimi API key 模式" },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -109,8 +109,8 @@ const tracksZh = [
|
||||
{ title: "记忆类型化存储", note: "SQLite + FTS5 后端,图结构 Agent 记忆,多信号召回(#534–#536)" },
|
||||
{ title: "飞书 / Lark 机器人", note: "基于现有 runtime API 的聊天平台前端(#757)" },
|
||||
{ title: "中国市场与国际化改进", note: "本地化 UI、平台优化、区域搜索引擎(#755)" },
|
||||
{ title: "Hugging Face 模型发现 + 模型实验室", note: "在 TUI 中直接浏览、下载和管理 Hugging Face Hub 上的模型" },
|
||||
{ title: "ZenMux / OpenAI 兼容提供商", note: "将任意 OpenAI 兼容端点(vLLM、LiteLLM、Ollama、本地模型)作为一级提供商接入" },
|
||||
{ title: "模型实验室", note: "面向开放权重和自托管工作流的模型发现与基准测试" },
|
||||
{ title: "提供商账单与目录", note: "/balance 能力层,以及对支持列表接口的提供商提供更完整的实时模型目录" },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -339,4 +339,4 @@ export default async function RoadmapPage({ params }: { params: Promise<{ locale
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,12 +77,15 @@ function deriveProvidersFromConfig(cfg: string): ProviderFact[] {
|
||||
// so the binary rejects it — keep it out of the docs. Issue #1104.
|
||||
const labelMap: Record<string, ProviderFact> = {
|
||||
Deepseek: { id: "deepseek", label: "DeepSeek", env: "DEEPSEEK_API_KEY" },
|
||||
NvidiaNim: { id: "nvidia-nim", label: "NVIDIA NIM", env: "NVIDIA_API_KEY" },
|
||||
Openai: { id: "openai", label: "OpenAI", env: "OPENAI_API_KEY" },
|
||||
NvidiaNim: { id: "nvidia-nim", label: "NVIDIA NIM", env: "NVIDIA_API_KEY / NVIDIA_NIM_API_KEY" },
|
||||
Openai: { id: "openai", label: "OpenAI-compatible", env: "OPENAI_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" },
|
||||
Openrouter: { id: "openrouter", label: "OpenRouter", env: "OPENROUTER_API_KEY" },
|
||||
Novita: { id: "novita", label: "Novita", env: "NOVITA_API_KEY" },
|
||||
Fireworks: { id: "fireworks", label: "Fireworks", env: "FIREWORKS_API_KEY" },
|
||||
Sglang: { id: "sglang", label: "sglang", env: "SGLANG_API_KEY" },
|
||||
Novita: { id: "novita", label: "Novita AI", env: "NOVITA_API_KEY" },
|
||||
Fireworks: { id: "fireworks", label: "Fireworks AI", env: "FIREWORKS_API_KEY" },
|
||||
Moonshot: { id: "moonshot", label: "Moonshot/Kimi", env: "MOONSHOT_API_KEY / KIMI_API_KEY" },
|
||||
Sglang: { id: "sglang", label: "SGLang", env: "SGLANG_API_KEY" },
|
||||
Vllm: { id: "vllm", label: "vLLM", env: "VLLM_API_KEY" },
|
||||
Ollama: { id: "ollama", label: "Ollama", env: "OLLAMA_API_KEY" },
|
||||
};
|
||||
@@ -98,7 +101,6 @@ function deriveSandboxBackends(files: string[]): string[] {
|
||||
const map: Record<string, string> = {
|
||||
seatbelt: "seatbelt (macOS)",
|
||||
landlock: "landlock (Linux)",
|
||||
windows: "AppContainer / restricted tokens (Windows)",
|
||||
};
|
||||
return files
|
||||
.map((f) => f.replace(/\.rs$/, ""))
|
||||
|
||||
+24
-10
@@ -18,8 +18,8 @@ export interface RepoFacts {
|
||||
}
|
||||
|
||||
export const FACTS: RepoFacts = {
|
||||
"generatedAt": "2026-05-24T16:01:45.189Z",
|
||||
"version": "0.8.43",
|
||||
"generatedAt": "2026-05-26T03:03:01.383Z",
|
||||
"version": "0.8.45",
|
||||
"crates": [
|
||||
"agent",
|
||||
"app-server",
|
||||
@@ -38,8 +38,7 @@ export const FACTS: RepoFacts = {
|
||||
],
|
||||
"sandboxBackends": [
|
||||
"landlock (Linux)",
|
||||
"seatbelt (macOS)",
|
||||
"AppContainer / restricted tokens (Windows)"
|
||||
"seatbelt (macOS)"
|
||||
],
|
||||
"providers": [
|
||||
{
|
||||
@@ -50,13 +49,23 @@ export const FACTS: RepoFacts = {
|
||||
{
|
||||
"id": "nvidia-nim",
|
||||
"label": "NVIDIA NIM",
|
||||
"env": "NVIDIA_API_KEY"
|
||||
"env": "NVIDIA_API_KEY / NVIDIA_NIM_API_KEY"
|
||||
},
|
||||
{
|
||||
"id": "openai",
|
||||
"label": "OpenAI",
|
||||
"label": "OpenAI-compatible",
|
||||
"env": "OPENAI_API_KEY"
|
||||
},
|
||||
{
|
||||
"id": "atlascloud",
|
||||
"label": "AtlasCloud",
|
||||
"env": "ATLASCLOUD_API_KEY"
|
||||
},
|
||||
{
|
||||
"id": "wanjie-ark",
|
||||
"label": "Wanjie Ark",
|
||||
"env": "WANJIE_ARK_API_KEY / WANJIE_API_KEY / WANJIE_MAAS_API_KEY"
|
||||
},
|
||||
{
|
||||
"id": "openrouter",
|
||||
"label": "OpenRouter",
|
||||
@@ -64,17 +73,22 @@ export const FACTS: RepoFacts = {
|
||||
},
|
||||
{
|
||||
"id": "novita",
|
||||
"label": "Novita",
|
||||
"label": "Novita AI",
|
||||
"env": "NOVITA_API_KEY"
|
||||
},
|
||||
{
|
||||
"id": "fireworks",
|
||||
"label": "Fireworks",
|
||||
"label": "Fireworks AI",
|
||||
"env": "FIREWORKS_API_KEY"
|
||||
},
|
||||
{
|
||||
"id": "moonshot",
|
||||
"label": "Moonshot/Kimi",
|
||||
"env": "MOONSHOT_API_KEY / KIMI_API_KEY"
|
||||
},
|
||||
{
|
||||
"id": "sglang",
|
||||
"label": "sglang",
|
||||
"label": "SGLang",
|
||||
"env": "SGLANG_API_KEY"
|
||||
},
|
||||
{
|
||||
@@ -90,7 +104,7 @@ export const FACTS: RepoFacts = {
|
||||
],
|
||||
"defaultModel": "deepseek-v4-pro",
|
||||
"nodeEngines": ">=18",
|
||||
"toolCount": 69,
|
||||
"toolCount": 70,
|
||||
"license": "MIT",
|
||||
"latestRelease": null
|
||||
};
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import type { FeedItem, RepoStats } from "./types";
|
||||
|
||||
const REPO = process.env.GITHUB_REPO ?? "Hmbown/CodeWhale";
|
||||
const GH = "https://api.github.com";
|
||||
const MIN_KNOWN_CONTRIBUTORS = 98;
|
||||
const MIN_KNOWN_CONTRIBUTORS = 99;
|
||||
|
||||
function headers(token?: string): HeadersInit {
|
||||
const h: Record<string, string> = {
|
||||
|
||||
+23
-4
@@ -55,6 +55,20 @@ async function gh<T>(url: string, ghToken?: string): Promise<T | null> {
|
||||
interface GhRelease { tag_name: string; name: string | null; body: string | null; html_url: string; prerelease: boolean; draft: boolean }
|
||||
interface GhIssue { number: number; title: string; html_url: string; body: string | null; state: string; pull_request?: unknown }
|
||||
|
||||
const FALLBACK_SHIPPED: RoadmapItem[] = [
|
||||
{
|
||||
title: "v0.8.45",
|
||||
note: "Moonshot/Kimi OAuth, provider-surface sync, and current Windows install/runtime guidance",
|
||||
href: "https://github.com/Hmbown/CodeWhale/releases/tag/v0.8.45",
|
||||
},
|
||||
];
|
||||
|
||||
function withPinnedShipped(items: RoadmapItem[]): RoadmapItem[] {
|
||||
const seen = new Set(items.map((item) => item.title));
|
||||
const pinned = FALLBACK_SHIPPED.filter((item) => !seen.has(item.title));
|
||||
return [...pinned, ...items];
|
||||
}
|
||||
|
||||
function summarizeReleaseBody(body: string | null): string {
|
||||
if (!body) return "";
|
||||
// First non-empty line, stripped of markdown headers / bullets / links
|
||||
@@ -100,17 +114,19 @@ export async function fetchRoadmap(ghToken?: string): Promise<RoadmapFeed> {
|
||||
fetchByLabel("roadmap:ruled-out", ghToken, "all"),
|
||||
]);
|
||||
|
||||
const shipped: RoadmapItem[] = (releases ?? [])
|
||||
const shipped: RoadmapItem[] = releases
|
||||
? releases
|
||||
.filter((r) => !r.draft)
|
||||
.map((r) => ({
|
||||
title: r.name?.trim() || r.tag_name,
|
||||
note: summarizeReleaseBody(r.body) || r.tag_name,
|
||||
href: r.html_url,
|
||||
}));
|
||||
}))
|
||||
: FALLBACK_SHIPPED;
|
||||
|
||||
return {
|
||||
generatedAt: new Date().toISOString(),
|
||||
shipped,
|
||||
shipped: withPinnedShipped(shipped),
|
||||
underway,
|
||||
considered,
|
||||
ruledOut,
|
||||
@@ -121,7 +137,10 @@ export async function getCachedRoadmap(kv: KVNamespace | undefined, ghToken: str
|
||||
try {
|
||||
if (kv) {
|
||||
const cached = await kv.get(KV_KEY);
|
||||
if (cached) return JSON.parse(cached) as RoadmapFeed;
|
||||
if (cached) {
|
||||
const parsed = JSON.parse(cached) as RoadmapFeed;
|
||||
return { ...parsed, shipped: withPinnedShipped(parsed.shipped ?? []) };
|
||||
}
|
||||
}
|
||||
const fresh = await fetchRoadmap(ghToken);
|
||||
if (kv) {
|
||||
|
||||
@@ -46,10 +46,10 @@ function deriveSandboxBackends() {
|
||||
const files = readdirSync(dir)
|
||||
.filter((f) => f.endsWith(".rs"))
|
||||
.map((f) => f.replace(/\.rs$/, ""))
|
||||
.filter((f) => !["mod", "policy", "backend", "opensandbox"].includes(f))
|
||||
.filter((f) => !["mod", "policy", "backend", "opensandbox", "windows"].includes(f))
|
||||
.sort();
|
||||
// canonicalize platform names
|
||||
const map = { seatbelt: "seatbelt (macOS)", landlock: "landlock (Linux)", windows: "AppContainer / restricted tokens (Windows)" };
|
||||
const map = { seatbelt: "seatbelt (macOS)", landlock: "landlock (Linux)" };
|
||||
return files.map((f) => map[f] ?? f);
|
||||
}
|
||||
|
||||
@@ -66,12 +66,15 @@ function deriveProviders() {
|
||||
// shared ProviderKind, so we exclude it until that lands. Issue #1104.
|
||||
const labelMap = {
|
||||
Deepseek: { id: "deepseek", label: "DeepSeek", env: "DEEPSEEK_API_KEY" },
|
||||
NvidiaNim: { id: "nvidia-nim", label: "NVIDIA NIM", env: "NVIDIA_API_KEY" },
|
||||
Openai: { id: "openai", label: "OpenAI", env: "OPENAI_API_KEY" },
|
||||
NvidiaNim: { id: "nvidia-nim", label: "NVIDIA NIM", env: "NVIDIA_API_KEY / NVIDIA_NIM_API_KEY" },
|
||||
Openai: { id: "openai", label: "OpenAI-compatible", env: "OPENAI_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" },
|
||||
Openrouter: { id: "openrouter", label: "OpenRouter", env: "OPENROUTER_API_KEY" },
|
||||
Novita: { id: "novita", label: "Novita", env: "NOVITA_API_KEY" },
|
||||
Fireworks: { id: "fireworks", label: "Fireworks", env: "FIREWORKS_API_KEY" },
|
||||
Sglang: { id: "sglang", label: "sglang", env: "SGLANG_API_KEY" },
|
||||
Novita: { id: "novita", label: "Novita AI", env: "NOVITA_API_KEY" },
|
||||
Fireworks: { id: "fireworks", label: "Fireworks AI", env: "FIREWORKS_API_KEY" },
|
||||
Moonshot: { id: "moonshot", label: "Moonshot/Kimi", env: "MOONSHOT_API_KEY / KIMI_API_KEY" },
|
||||
Sglang: { id: "sglang", label: "SGLang", env: "SGLANG_API_KEY" },
|
||||
Vllm: { id: "vllm", label: "vLLM", env: "VLLM_API_KEY" },
|
||||
Ollama: { id: "ollama", label: "Ollama", env: "OLLAMA_API_KEY" },
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user