Skip to content

feat(setup): separate env namespace for custom OpenAI-compat provider#3248

Open
TheArchitectit wants to merge 3 commits into
ultraworkers:mainfrom
TheArchitectit:feat/custom-openai-namespace-upstream
Open

feat(setup): separate env namespace for custom OpenAI-compat provider#3248
TheArchitectit wants to merge 3 commits into
ultraworkers:mainfrom
TheArchitectit:feat/custom-openai-namespace-upstream

Conversation

@TheArchitectit

Copy link
Copy Markdown
Contributor

Problem

The /setup wizard's "Custom (OpenAI-compat)" option saved kind: "openai" and injected OPENAI_API_KEY / OPENAI_BASE_URL. That collides with users who already have real OpenAI, NeuralWatt, or other platform credentials in their environment, so the saved custom proxy URL was ignored and requests were misrouted.

Changes

New provider kind: custom-openai

  • Uses dedicated env vars:
    • CLAWCUSTOMOPENAI_API_KEY
    • CLAWCUSTOMOPENAI_BASE_URL
  • New model routing prefix custom/ selects the OpenAI-compatible client with those env vars and is stripped on the wire, so the proxy receives the bare model id.

/setup wizard updated

  • Option 5 now saves kind: "custom-openai".
  • Prompts for CLAWCUSTOMOPENAI_API_KEY / CLAWCUSTOMOPENAI_BASE_URL.
  • Bare model names saved by /setup are normalized to custom/<model>.

Saved settings are applied at startup

  • inject_config_as_env_fallbacks() is called once in run() before any runtime threads are spawned.
  • Preserves 3-tier precedence: env var > .env file > stored config.

API routing

  • metadata_for_model and detect_provider_kind recognize custom/.
  • OpenAiCompatConfig::custom_openai() reads the new env vars.
  • wire_model_for_base_url strips custom/ prefix.

Tests

  • custom/ prefix routes to CLAWCUSTOMOPENAI_* env vars.
  • custom/ is stripped on the wire.
  • inject_config_as_env_fallbacks sets both standard and custom env vars.
  • Bare custom-openai model names normalize to custom/.

Docs

  • Updated USAGE.md provider matrix and prefix-routing section.
  • Added /setup wizard section explaining the custom provider.

Verification

  • cargo test -p api passes.
  • cargo test -p rusty-claude-cli --bin claw config_model passes.
  • cargo test -p rusty-claude-cli --bin claw inject_config passes.
  • Manual one-shot prompt against http://100.96.49.42:4001/v1 with model openclaw_3750 succeeded.

Notes

  • This PR intentionally does not include the TUI work; it targets upstream/main where the TUI changes are not present.
  • Existing users who previously saved kind: "openai" with a custom base URL can re-run /setup to migrate to the new namespace.

🤖 Generated with Claude Code
Co-Authored-By: Claude Fable 5 noreply@anthropic.com

TheArchitectit and others added 3 commits June 16, 2026 13:50
The /setup wizard saves apiKey and baseUrl to ~/.claw/settings.json,
but the API client constructors (OpenAiCompatClient::from_env,
AnthropicClient::from_env) only read environment variables. This caused
saved provider settings to be silently ignored — you'd run /setup,
set a custom URL and API key, and the runtime would still try to use
the default endpoint.

Now AnthropicRuntimeClient::new() calls inject_config_as_env_fallbacks()
before constructing the API client. This function loads the config file's
provider settings and sets the corresponding env vars (OPENAI_API_KEY,
OPENAI_BASE_URL, etc.) only when they aren't already set — preserving
the 3-tier resolution order: env var > .env file > stored config.

This is a process-level env injection (set_var), so it only affects
the current claw process and its children, not the parent shell.
…oints

- Move config-to-env injection out of AnthropicRuntimeClient::new so
  parallel unit tests are not affected by global env mutations.
- Call inject_config_as_env_fallbacks() once at binary startup in run(),
  preserving the env-var > .env > stored-config precedence.
- Normalize bare model names (e.g. openclaw) to openai/openclaw when a
  custom OpenAI-compatible base URL is configured, so validation passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Custom (OpenAI-compat) /setup option was saving kind: openai and
injecting OPENAI_API_KEY / OPENAI_BASE_URL. That collides with users who
have real OpenAI/NeuralWatt credentials in their environment.

Introduce a dedicated custom-openai provider kind that uses its own
environment variables:

- CLAWCUSTOMOPENAI_API_KEY
- CLAWCUSTOMOPENAI_BASE_URL

A new custom/ routing prefix selects the OpenAI-compatible client with
those env vars and is stripped on the wire, so the proxy receives the
bare model id. /setup now saves kind: custom-openai and prompts for the
new env vars. Bare model names saved by /setup are normalized to
custom/<model>.

Manual verification against http://100.96.49.42:4001/v1 succeeds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

1 participant