feat(providers): add AtlasCloud as a first-class provider

AtlasCloud (https://atlascloud.ai) hosts the V4 family on its own
DeepSeek-compatible endpoint at `https://api.atlascloud.ai/v1`, and
several contributors had been running it through the
OpenAI-compatible passthrough with manual `base_url` / model
overrides. Selecting `provider = "atlascloud"` in
`~/.deepseek/config.toml` (or via `DEEPSEEK_PROVIDER=atlascloud`)
now wires up:

- documented `DEFAULT_ATLASCLOUD_BASE_URL` /
  `DEFAULT_ATLASCLOUD_MODEL` defaults so a fresh install needs
  only the api_key
- a `[providers.atlascloud]` config block with the same fields
  every other named provider exposes (api_key / base_url / model
  / http_headers)
- `ATLASCLOUD_API_KEY` env var path, including the secrets test
  cleanup loop so per-test env hygiene continues to work
- the provider-picker / `/provider` slash command entries so the
  provider is reachable from the runtime UI, not just config
- the env-driven `*_BASE_URL` override branch so users who pin a
  proxy can still flip it without editing config.toml

Trust-boundary pins held: AtlasCloud is opt-in (default remains
DeepSeek), no API keys are hardcoded, the api_key resolution flows
through the same `secrets` crate path every other provider uses,
and the provider-config base_url stays settable per environment.

Resolved 3-way merge conflicts in `crates/secrets/src/lib.rs` (env
cleanup loop) and `crates/tui/src/config.rs` (per-provider
base_url match arm + `provider_passes_model_through` predicate)
so the contributor's AtlasCloud branch coexists with the v0.8.x
provider expansion already on `main`. Added the missing match arm
in `validate_provider_base_url` so the non-exhaustive-pattern
check passes after the new variant lands.

Harvested from PR #1436 by @lucaszhu-hue

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hunter Bown
2026-05-12 00:40:43 -05:00
parent 40df46c73d
commit 8f33e4bd48
13 changed files with 292 additions and 21 deletions
+15 -3
View File
@@ -26,6 +26,7 @@ enum ProviderArg {
Deepseek,
NvidiaNim,
Openai,
Atlascloud,
Openrouter,
Novita,
Fireworks,
@@ -40,6 +41,7 @@ impl From<ProviderArg> for ProviderKind {
ProviderArg::Deepseek => ProviderKind::Deepseek,
ProviderArg::NvidiaNim => ProviderKind::NvidiaNim,
ProviderArg::Openai => ProviderKind::Openai,
ProviderArg::Atlascloud => ProviderKind::Atlascloud,
ProviderArg::Openrouter => ProviderKind::Openrouter,
ProviderArg::Novita => ProviderKind::Novita,
ProviderArg::Fireworks => ProviderKind::Fireworks,
@@ -673,6 +675,7 @@ fn provider_slot(provider: ProviderKind) -> &'static str {
ProviderKind::Deepseek => "deepseek",
ProviderKind::NvidiaNim => "nvidia-nim",
ProviderKind::Openai => "openai",
ProviderKind::Atlascloud => "atlascloud",
ProviderKind::Openrouter => "openrouter",
ProviderKind::Novita => "novita",
ProviderKind::Fireworks => "fireworks",
@@ -683,16 +686,17 @@ fn provider_slot(provider: ProviderKind) -> &'static str {
}
/// Provider order used by the `auth list` and `auth status` outputs.
const PROVIDER_LIST: [ProviderKind; 9] = [
const PROVIDER_LIST: [ProviderKind; 10] = [
ProviderKind::Deepseek,
ProviderKind::NvidiaNim,
ProviderKind::Openai,
ProviderKind::Atlascloud,
ProviderKind::Openrouter,
ProviderKind::Novita,
ProviderKind::Fireworks,
ProviderKind::Sglang,
ProviderKind::Vllm,
ProviderKind::Ollama,
ProviderKind::Openai,
];
#[cfg(test)]
@@ -748,6 +752,7 @@ fn provider_env_vars(provider: ProviderKind) -> &'static [&'static str] {
ProviderKind::Vllm => &["VLLM_API_KEY"],
ProviderKind::Ollama => &["OLLAMA_API_KEY"],
ProviderKind::Openai => &["OPENAI_API_KEY"],
ProviderKind::Atlascloud => &["ATLASCLOUD_API_KEY"],
}
}
@@ -1390,6 +1395,7 @@ fn build_tui_command(
ProviderKind::Deepseek
| ProviderKind::NvidiaNim
| ProviderKind::Openai
| ProviderKind::Atlascloud
| ProviderKind::Openrouter
| ProviderKind::Novita
| ProviderKind::Fireworks
@@ -1398,7 +1404,7 @@ fn build_tui_command(
| ProviderKind::Ollama
) {
bail!(
"The interactive TUI supports DeepSeek, NVIDIA NIM, OpenAI-compatible, OpenRouter, Novita, Fireworks, SGLang, vLLM, and Ollama providers. Remove --provider {} or use `deepseek model ...` for provider registry inspection.",
"The interactive TUI supports DeepSeek, NVIDIA NIM, OpenAI-compatible, AtlasCloud, OpenRouter, Novita, Fireworks, SGLang, vLLM, and Ollama providers. Remove --provider {} or use `deepseek model ...` for provider registry inspection.",
resolved_runtime.provider.as_str()
);
}
@@ -1420,6 +1426,9 @@ fn build_tui_command(
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);
}
let source = resolved_runtime
.api_key_source
.unwrap_or(RuntimeApiKeySource::Env)
@@ -1453,6 +1462,9 @@ fn build_tui_command(
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);
}
cmd.env("DEEPSEEK_API_KEY_SOURCE", "cli");
}
if let Some(base_url) = cli.base_url.as_ref() {