Skip to content

feat: add Volcengine provider with DeepSeek-V4-Pro/Flash support#1993

Open
dzyuan wants to merge 2 commits into
Hmbown:mainfrom
dzyuan:feature/volcengine
Open

feat: add Volcengine provider with DeepSeek-V4-Pro/Flash support#1993
dzyuan wants to merge 2 commits into
Hmbown:mainfrom
dzyuan:feature/volcengine

Conversation

@dzyuan
Copy link
Copy Markdown

@dzyuan dzyuan commented May 24, 2026

Add Volcengine (Volcano Engine Ark) provider for DeepSeek-V4-Pro/Flash via Coding API.

Add a new Volcengine (Volcano Engine Ark) provider for accessing
DeepSeek-V4-Pro and DeepSeek-V4-Flash via the Volcengine Coding API.

Changes:
- Add ProviderKind::Volcengine to config crate with default base_url
  pointing to Volcengine Coding API (api/coding/v3)
- Add DeepSeek-V4-Pro and DeepSeek-V4-Flash models to the agent
  model registry under Volcengine provider
- Add ApiProvider::Volcengine to TUI with full picker/dropdown support
- Wire up CLI --provider, config get/set/unset, and secrets resolution
- Add environment variable aliases: VOLCENGINE_API_KEY, ARK_API_KEY
- Ignore local dev scripts (*.cmd, backup/)
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for the Volcengine (Volcano Engine Ark) provider across the agent, CLI, and TUI crates. Key changes include adding Volcengine to the model registry, configuration structures, and environment variable mappings, as well as updating the TUI to support Volcengine authentication and model selection. Feedback highlights a critical issue where Volcengine was incorrectly categorized as a provider not requiring authentication, which would lead to authorization failures. Additionally, reviewers noted potential issues with model aliasing for reasoning models, unnecessary cross-contamination of environment variables between providers, and minor inconsistencies in CLI output messages and configuration key ordering.

Comment thread crates/tui/src/config.rs
// Self-hosted deployments commonly run without auth on localhost.
// Return an empty key and let the client omit the Authorization header.
ApiProvider::Sglang | ApiProvider::Vllm | ApiProvider::Ollama => Ok(String::new()),
ApiProvider::Sglang | ApiProvider::Vllm | ApiProvider::Ollama | ApiProvider::Volcengine => Ok(String::new()),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Volcengine (Volcano Engine Ark) is a cloud provider that requires authentication. Including it in this list—which is intended for self-hosted or local deployments that run without authentication—will cause the client to omit the Authorization header, resulting in authentication failures.

            ApiProvider::Sglang | ApiProvider::Vllm | ApiProvider::Ollama => Ok(String::new()),

Comment thread crates/agent/src/lib.rs Outdated
aliases: vec![
"deepseek-v4-flash".to_string(),
"deepseek-chat".to_string(),
"deepseek-reasoner".to_string(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The deepseek-reasoner alias is mapped to DeepSeek-V4-Flash, but it is typically the canonical alias for high-capability reasoning models (like DeepSeek-V4-Pro). Mapping it to the Flash version may lead to unexpected behavior when users expect the full reasoning model.

Comment thread crates/cli/src/lib.rs Outdated
Comment on lines 1455 to 1458
if resolved_runtime.provider == ProviderKind::WanjieArk || resolved_runtime.provider == ProviderKind::Volcengine {
cmd.env("VOLCENGINE_API_KEY", api_key);
cmd.env("WANJIE_ARK_API_KEY", api_key);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The environment variables for WanjieArk and Volcengine are being set regardless of which provider is active. This cross-contamination is unnecessary and could lead to confusion. Each provider should only have its own relevant environment variables set.

        if resolved_runtime.provider == ProviderKind::WanjieArk {
            cmd.env("WANJIE_ARK_API_KEY", api_key);
        }
        if resolved_runtime.provider == ProviderKind::Volcengine {
            cmd.env("VOLCENGINE_API_KEY", api_key);
        }

Comment thread crates/cli/src/lib.rs Outdated
Comment on lines 1495 to 1498
if resolved_runtime.provider == ProviderKind::WanjieArk || resolved_runtime.provider == ProviderKind::Volcengine {
cmd.env("VOLCENGINE_API_KEY", api_key);
cmd.env("WANJIE_ARK_API_KEY", api_key);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the previous block, environment variables for WanjieArk and Volcengine are being set for both providers. These should be separated to avoid leaking keys into unrelated environment variables.

        if resolved_runtime.provider == ProviderKind::WanjieArk {
            cmd.env("WANJIE_ARK_API_KEY", api_key);
        }
        if resolved_runtime.provider == ProviderKind::Volcengine {
            cmd.env("VOLCENGINE_API_KEY", api_key);
        }

Comment thread crates/config/src/lib.rs
Comment on lines 472 to +477
"providers.wanjie_ark.api_key" => self.providers.wanjie_ark.api_key.clone(),
"providers.volcengine.api_key" => self.providers.volcengine.api_key.clone(),
"providers.wanjie_ark.base_url" => self.providers.wanjie_ark.base_url.clone(),
"providers.volcengine.base_url" => self.providers.volcengine.base_url.clone(),
"providers.wanjie_ark.model" => self.providers.wanjie_ark.model.clone(),
"providers.volcengine.model" => self.providers.volcengine.model.clone(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The configuration keys for wanjie_ark and volcengine are interleaved. Grouping them by provider improves readability and maintainability.

Suggested change
"providers.wanjie_ark.api_key" => self.providers.wanjie_ark.api_key.clone(),
"providers.volcengine.api_key" => self.providers.volcengine.api_key.clone(),
"providers.wanjie_ark.base_url" => self.providers.wanjie_ark.base_url.clone(),
"providers.volcengine.base_url" => self.providers.volcengine.base_url.clone(),
"providers.wanjie_ark.model" => self.providers.wanjie_ark.model.clone(),
"providers.volcengine.model" => self.providers.volcengine.model.clone(),
"providers.wanjie_ark.api_key" => self.providers.wanjie_ark.api_key.clone(),
"providers.wanjie_ark.base_url" => self.providers.wanjie_ark.base_url.clone(),
"providers.wanjie_ark.model" => self.providers.wanjie_ark.model.clone(),
"providers.volcengine.api_key" => self.providers.volcengine.api_key.clone(),
"providers.volcengine.base_url" => self.providers.volcengine.base_url.clone(),
"providers.volcengine.model" => self.providers.volcengine.model.clone(),

Comment thread crates/tui/src/main.rs Outdated
("OLLAMA_API_KEY", "codewhale auth set --provider ollama")
}
crate::config::ApiProvider::Volcengine => {
("VOLCENGINE_API_KEY", "deepseek auth set --provider volcengine")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The suggested command uses deepseek instead of codewhale. This is inconsistent with the other provider setup messages in this file.

Suggested change
("VOLCENGINE_API_KEY", "deepseek auth set --provider volcengine")
("VOLCENGINE_API_KEY", "codewhale auth set --provider volcengine")

…gine

- Remove Volcengine from reasoning_effort 'off' no-auth group (HIGH)
- Add Volcengine to proper reasoning_effort handling (like DeepSeek)
- Remove 'deepseek-reasoner' alias from DeepSeek-V4-Flash (MEDIUM)
- Separate WanjieArk and Volcengine env vars in CLI (MEDIUM)
- Group config keys by provider for readability (MEDIUM)
- Use 'codewhale' instead of 'deepseek' in login hints (MEDIUM)
- Enable cache_telemetry_supported for Volcengine provider
@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented May 27, 2026

Independent review (Devin): merged against origin/main (54151a4) to verify conflicts and correctness.

Unresolved bug — Volcengine silently skips auth (HIGH). config.rs still returns Ok(String::new()) for Volcengine in the no-auth self-hosted group alongside Sglang/Vllm/Ollama. The second commit fixed reasoning_effort branching but left this path untouched. Any user without an explicit VOLCENGINE_API_KEY in env gets a silent empty bearer token and an HTTP 401 with no actionable error message. Needs its own anyhow::bail! arm (same pattern as WanjieArk/Openrouter/Fireworks).

model_completion_names mismatch (MEDIUM). Volcengine is bucketed with OFFICIAL_DEEPSEEK_MODELS (deepseek-v4-pro, deepseek-v4-flash — lowercase), but the registry canonical IDs are DeepSeek-V4-Pro / DeepSeek-V4-Flash (mixed case), and normalize_model_for_provider passes Volcengine through unchanged. The completion list served by the picker won't match what the API accepts.

Alias collision still present (LOW). deepseek-v4-flash and deepseek-chat appear as Volcengine-Flash aliases while also resolving against Deepseek/NvidiaNim/Openrouter entries; first-match wins and the ordering is registry-position-dependent. Consider prefixed-only aliases for the Volcengine entries.

Merge conflicts with origin/main (v0.8.48 surface, 3 files).

  • crates/config/src/lib.rs: v0.8.48 adds CODEWHALE_PROVIDER/CODEWHALE_MODEL env var lookups and a Moonshot provider arm in model_for(); both conflict with the Volcengine arms.
  • crates/cli/src/lib.rs: v0.8.48 refactors secret bridging to provider_env_vars() helper; conflicts with the per-provider cmd.env() blocks added here.
  • crates/tui/src/config.rs: provider_passes_model_through conflict (Moonshot vs Volcengine arm). All three are straightforward and non-destructive — both sides should be kept.

Sibling provider PRs (#1864/#1868 SiliconFlow): touch the same match arms in config.rs, config/src/lib.rs, and client.rs — whoever lands second will need a rebase.

No tests added. No unit or integration tests cover Volcengine key resolution, model normalisation, or reasoning_effort dispatch. Adding a test parallel to the existing WanjieArk/Atlascloud tests would close the auth-regression risk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants