feat(setup): separate env namespace for custom OpenAI-compat provider - #3248
feat(setup): separate env namespace for custom OpenAI-compat provider#3248TheArchitectit wants to merge 3 commits into
Conversation
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)
6bf0cf3 to
0c339e7
Compare
|
Good approach — separating the env namespace prevents custom provider config from leaking into or conflicting with the default OpenAI env vars. This also makes it easier to support multiple custom providers simultaneously. Checks are all passing, LGTM. |
|
Good separation of concerns — having a dedicated env namespace avoids collisions with standard OpenAI vars. The migration path for existing users looks clean. Thanks @TheArchitectit! |
|
Ready for review ✅
Once this lands, #3250 will be rebased to drop commits 1-3 and should be ready to merge as well. @ultraworkers/maintainers — requesting review when you get a chance. |
|
The custom-openai namespace separation is clean and well-tested. The custom/ prefix routing is a nice touch that keeps model IDs unambiguous. The migration path for existing users (re-run /setup) is documented. All checks passing, good to merge. |
Problem
The
/setupwizard's "Custom (OpenAI-compat)" option savedkind: "openai"and injectedOPENAI_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-openaiCLAWCUSTOMOPENAI_API_KEYCLAWCUSTOMOPENAI_BASE_URLcustom/selects the OpenAI-compatible client with those env vars and is stripped on the wire, so the proxy receives the bare model id./setupwizard updatedkind: "custom-openai".CLAWCUSTOMOPENAI_API_KEY/CLAWCUSTOMOPENAI_BASE_URL./setupare normalized tocustom/<model>.Saved settings are applied at startup
inject_config_as_env_fallbacks()is called once inrun()before any runtime threads are spawned..envfile > stored config.API routing
metadata_for_modelanddetect_provider_kindrecognizecustom/.OpenAiCompatConfig::custom_openai()reads the new env vars.wire_model_for_base_urlstripscustom/prefix.Tests
custom/prefix routes toCLAWCUSTOMOPENAI_*env vars.custom/is stripped on the wire.inject_config_as_env_fallbackssets both standard and custom env vars.custom/.Docs
USAGE.mdprovider matrix and prefix-routing section./setupwizard section explaining the custom provider.Verification
cargo test -p apipasses.cargo test -p rusty-claude-cli --bin claw config_modelpasses.cargo test -p rusty-claude-cli --bin claw inject_configpasses.http://100.96.49.42:4001/v1with modelopenclaw_3750succeeded.Notes
upstream/mainwhere the TUI changes are not present.kind: "openai"with a custom base URL can re-run/setupto migrate to the new namespace.🤖 Generated with Claude Code
Co-Authored-By: Claude Fable 5 noreply@anthropic.com