Skip to content

feat: support configuring ANTHROPIC_BASE_URL in settings#8

Open
neko1990 wants to merge 1 commit intoxuy:mainfrom
neko1990:feat/anthropic-base-url-config
Open

feat: support configuring ANTHROPIC_BASE_URL in settings#8
neko1990 wants to merge 1 commit intoxuy:mainfrom
neko1990:feat/anthropic-base-url-config

Conversation

@neko1990
Copy link
Copy Markdown
Contributor

Motivation

  • Users need to configure custom Anthropic-compatible API endpoints (e.g., proxy servers, local LLM servers, or alternative API gateways).
  • The existing NOAH_API_URL env var requires disabling authentication, which is not suitable for Anthropic-compatible endpoints that still need API key auth.
  • There was no UI to configure the base URL, requiring users to manually edit environment variables.

Description

  • Add ANTHROPIC_BASE_URL environment variable support to override the default Anthropic API endpoint while preserving API key authentication.
  • Implement normalize_messages_url() helper function to handle various URL formats (host-only, /v1, or full /v1/messages paths).
  • Add backend commands get_anthropic_base_url() and set_anthropic_base_url() in apps/desktop/src-tauri/src/commands/settings.rs.
  • Persist the base URL to anthropic_base_url.txt in the app data directory and load it on startup.
  • Add UI section in Settings Panel (apps/desktop/src/components/SettingsPanel.tsx) with:
    • Input field for custom base URL
    • Validation for http:// or https:// protocols
    • Save button with loading/saved states
    • Localized help text in English and Chinese
  • Update clear_auth_files() to also remove the base URL file when clearing authentication.
  • Add unit tests for normalize_messages_url() covering three URL format cases.
  • Add IPC contract test in stage0.test.ts to ensure camelCase parameter naming.

Testing

  • Ran npm test -- stage0.test.ts in apps/desktop and all 12 tests passed, including the new set_anthropic_base_url uses camelCase key test.
  • Ran cargo test --lib agent::llm_client::tests::test_normalize_messages_url and all 3 tests passed:
    • test_normalize_messages_url_from_host: Verifies host-only URLs get /v1/messages appended
    • test_normalize_messages_url_from_v1: Verifies /v1 URLs get /messages appended
    • test_normalize_messages_url_already_messages: Verifies full URLs are unchanged
  • Changes span 8 files across backend (Rust) and frontend (TypeScript/React):
    • Backend: llm_client.rs, settings.rs, lib.rs
    • Frontend: SettingsPanel.tsx, tauri-commands.ts, stage0.test.ts
    • i18n: en.json, zh.json

@xuy
Copy link
Copy Markdown
Owner

xuy commented Mar 11, 2026

@codex review this.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ca6017311

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


// Load persisted ANTHROPIC_BASE_URL into process env.
if let Some(base_url) = load_persisted_anthropic_base_url(&app_dir) {
std::env::set_var(ANTHROPIC_BASE_URL_ENV, base_url);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve env precedence when loading persisted base URL

run() unconditionally calls std::env::set_var(ANTHROPIC_BASE_URL_ENV, base_url) when anthropic_base_url.txt exists, which overwrites any ANTHROPIC_BASE_URL value provided by the launch environment. In the common override scenario (e.g., CI/dev shell sets a one-off endpoint while a previous UI-saved value exists), the app will silently use the stale persisted URL instead of the env override, despite get_anthropic_base_url() documenting env-first behavior.

Useful? React with 👍 / 👎.

.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(if env_api_url().is_some() { 300 } else { 90 })
.unwrap_or(if env_noah_api_url().is_some() { 300 } else { 90 })
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Apply extended timeout to custom Anthropic base URLs

request_timeout_secs() still only switches to the 300s timeout when NOAH_API_URL is set, so requests sent via the new ANTHROPIC_BASE_URL path keep the 90s default. For the local/proxied Anthropic-compatible endpoints this change is meant to support, slower responses can now time out prematurely unless users also discover and set NOAH_TIMEOUT manually.

Useful? React with 👍 / 👎.

@xuy
Copy link
Copy Markdown
Owner

xuy commented Mar 11, 2026

Thanks for the PR! The URL normalization and persistence logic are solid work.

I want to think about this holistically before merging — there are a few design considerations around how endpoint configuration fits into the overall UX (especially for non-technical users) and how it interacts with the existing NOAH_API_URL path.

I may address this with a different approach soon — possibly integrating it into the onboarding/connection flow rather than as a standalone settings section. Will keep this open for reference.

Appreciate the contribution!

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