feat(provider): complete the custom API provider feature on dev (#68–#73) - #74
Closed
xjoker wants to merge 15 commits into
Closed
feat(provider): complete the custom API provider feature on dev (#68–#73)#74xjoker wants to merge 15 commits into
xjoker wants to merge 15 commits into
Conversation
First slice of custom-provider support (方案 A). Adds a provider-profile type that lets codex-switch target a third-party OpenAI-compatible endpoint (OpenRouter, an LLM proxy, ...) instead of a ChatGPT OAuth account. - src/provider.rs: ProviderProfile model + private storage under $CODEX_SWITCH_HOME/providers/<alias>/provider.toml (dir 0700, file 0600), validation (reserved-id/name/base_url/env_key/model checks), key redaction, and env_key derived from the codex-switch alias (CODEX_SWITCH_<ALIAS>_KEY) so the injected key never collides with a provider's own variable. - CLI: codex-switch provider add/list/show/remove. The API key is read from a hidden prompt (rpassword) or --api-key-stdin, never from argv, and is redacted in list/show/--json output. Storage only; launch integration is PR-2. Nothing is written to ~/.codex yet. Unit tests cover env_key derivation, id sanitization, validation, redaction, 0600 permissions, and save/load/list/remove round-trip. Adds rpassword. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
Wire provider profiles into `codex-switch launch`. When the alias names a provider profile, launch takes a separate path from the ChatGPT one: - translate the profile into `codex -c model_providers.<id>.* / model_provider / model` overrides (layered over the user's base config, so ~/.codex and its MCP servers are untouched), and - inject the API key into the Codex child process under the profile's env_key, never onto the command line. No auth.json staging/backup/restore happens for providers (there is no OAuth token), so that whole window is skipped. Auto-select (no alias) stays ChatGPT-only. Extracted ensure_codex_available() and child_exit_code() shared by both launch paths. provider.rs gains codex_config_args()/launch_env()/toml_string() (pure, unit-tested: overrides present and TOML-quoted, key absent from argv, env pair correct, escaping). Verified end-to-end with a stub codex (args + env, key not in argv) and real codex 0.149.1 (base MCP server still lists through a provider launch). Co-authored-by: xJoker <xjoker@users.noreply.github.com>
Load custom API provider profiles into the TUI and render them in a separate "Custom providers" panel below the account table. Providers carry no OAuth/usage, so they stay out of the account table, scoring, and refresh; the panel lists alias / name / model / base_url and never renders the key. Interactive add/remove of providers in the TUI is PR-4. Adds a TestBackend render test asserting the panel lists a provider and does not leak the API key. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
Rework the custom-providers UI from a stacked panel into a top-level tab layout (per design 方案③), isolating codex-native ChatGPT accounts from third-party API+key providers: - Tab bar with Accounts (N) / Providers (N); Tab / BackTab switches. - Accounts tab: the existing account table + detail panel, unchanged. - Providers tab: a full-height read-only table of custom providers (alias / name / model / base_url) with a selection highlight; the API key is never rendered. - Event loop routes keys per active tab: account keys (a/r/t/i/s/space///Esc, and W auto-warmup) only fire on the Accounts tab; j/k move the provider selection on the Providers tab; q/h/Tab are global. Interactive add/remove within the Providers tab is PR-4. Test updated to render the Providers tab; still asserts the key never renders. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
On the Providers tab: - 'a' opens a multi-step add wizard (alias -> base URL -> model -> API key) reusing the single-line input pattern; the API-key step is masked in the status bar and the key is never echoed. Each step validates (alias rules + collision with providers/accounts, http(s) base URL, non-empty model/key); on completion it derives env_key/provider_id, saves via provider::save, and reloads. - 'd' removes the selected provider after a y/n confirmation (ConfirmAction::RemoveProvider). - Keys route per tab; the wizard consumes raw case-sensitive input. A tab-aware footer shows the Providers key hints. Unit tests: wizard collects fields and saves (with hermetic CODEX_SWITCH_HOME/ CODEX_HOME), stays on-step for a bad base URL, and request+confirm removes a provider. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
Document provider add/list/show/remove, launch overlay, TUI two-tab add/remove, OpenRouter and DeepSeek-via-gateway, and the no-argv key contract. Wiki page plus README, command reference, architecture, and changelog. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
…models End-to-end testing against OpenRouter showed Codex enables its built-in web_search server tool by default, which most third-party models reject with HTTP 400 'Server tool request failed'. Document the top-level web_search='disabled' config (and -c override), plus the note that some reasoning models impose their own request requirements. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
…etting Smoke-tested DeepSeek and Kimi (thinking + non-thinking) over OpenRouter. web_search rejection is model-specific, not universal: deepseek-v3.2, kimi-k2, and minimax-m3:free accept it (HTTP 200); gpt-oss-20b rejects it (400). Thinking models (deepseek-r1, kimi-k2-thinking) need model_reasoning_effort set or they 400 with 'Reasoning is mandatory'. Reword from 'most models' to model-specific, and document the reasoning effort override. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
Providers can now carry extra `codex -c KEY=VALUE` overrides (`provider add --set`, repeatable) that launch applies automatically, so model-specific Codex settings like `web_search=disabled` or `model_reasoning_effort=medium` no longer have to be retyped on every launch. Overrides are stored verbatim in provider.toml and layered on top of the model selection at launch. Codex, not codex-switch, remains the source of truth for valid keys/values: only KEY=VALUE shape is validated, values pass through untouched. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
Co-authored-by: xJoker <xjoker@users.noreply.github.com>
`provider add --reasoning <effort>` saves model_reasoning_effort=<effort> and `--no-web-search` saves web_search=disabled, lowering the barrier for the two most common model-specific settings. They are shortcuts over --set: any value passes through to Codex unchecked (the effort set is Codex's to define), and an explicit --set for the same key still wins. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
After the model step the wizard offers a reasoning-effort single choice (default "(skip)") and a web_search on/off toggle, both saved into the provider's codex_config. Presets cover the common efforts; the CLI --set stays the escape hatch for any other value. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
…steps Co-authored-by: xJoker <xjoker@users.noreply.github.com>
Brings the whole custom-API-provider stack (#67-#73) up to date with dev (webbrowser 1.2.4, pay-per-use credits column, etc). The only conflict was src/tui/ui.rs: kept both dev's credits_table_* helpers and the provider tab/panel renderers, and merged the test-module imports. Full suite: 1019 passed. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
Real dev already carries #67 (provider store) and #72 (env config). Re-merged the true dev HEAD and resolved the add/add conflicts in provider.rs / cli.rs / commands/provider.rs by keeping the provider-docs full-feature versions (verified supersets of dev's #67). environment.json (#72) merged in cleanly. This PR now cleanly adds #68-#73 (launch / TUI / docs / codex overrides) that are not yet in dev. Full suite: 1019 passed. Co-authored-by: xJoker <xjoker@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background (verified)
The custom API provider feature was split into a stack of PRs #67→#73. After re-checking against the real
dev:devalready contains #67 (provider data model + storage + CLI) and #72 (Cloud Agent environment). What is not yet indevis #68–#73 (codex_config/launch_provider/Providers taball count 0 ondev) — those had only been merged into their in-stack parent branches.This PR uses
cursor/provider-docs-5a91, which holds the complete stack code, and, based on the realdev(ad7326c), lands the missing #68–#73.Net additions in this PR (#68–#73)
launch <provider>: applies the provider viacodex -coverrides and injects the API key through the child-process env (never~/.codex/auth.json, never argv).docs/wiki/Providers.md, etc.).--set KEY=VALUE, convenience--reasoning/--no-web-search, and two extra wizard steps in the TUI. Values pass through to Codex verbatim — Codex, not codex-switch, decides which keys/values are valid (no hard-coded enum validation).Merge safety
devis an ancestor of this branch (merge-base == dev HEAD) → fast-forward, zero conflicts.dev(provider.rs/cli.rs/commands/provider.rs, because feat(provider): custom API provider profiles store + CLI (PR-1) #67 already landed ondevseparately) were resolved by keeping the provider-docs full-feature versions, verified file-by-file to be supersets of dev's feat(provider): custom API provider profiles store + CLI (PR-1) #67 version. chore: add Cloud Agent development environment config #72'senvironment.jsonmerged in cleanly.Validation
cargo fmt --checkandcargo clippy --all-targets --all-features -- -D warningsare green.cargo test --all: 1019 passed / 0 failed, no regressions.--reasoning, the--no-web-search+--reasoningcombo, and a tool operation that actually created a file — all exited 0.After this PR merges, #68–#73 are fully in
devand the custom API provider feature is complete. The original #67–#73 are already MERGED (into in-stack branches) and those branches can be deleted.