mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-10-25 17:22:27 +08:00
main
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f9db9f7056 |
feat(codex): support GitHub Copilot managed accounts with Responses/Chat routing (#7157)
Add a GitHub Copilot preset for Codex that uses a managed GitHub account. The local route resolves each request's model against the account's live Copilot /models catalogue and picks the upstream protocol the model advertises (native Responses first, Chat Completions as fallback in auto mode), with an optional explicit protocol override. - Response handling, the opaque-state rectifier and Stack web_search stripping follow the transport actually used for each request rather than the stored apiFormat. - Fetching models fills the catalogue from the account's live prompt limit, parallel tool calls and reasoning levels; presets keep conservative fallbacks. - Codex only treats a card as managed Copilot by its provider type, so self-hosted relays keep their own key and endpoint. - Copilot request identity headers are shared between the Claude and Codex paths. Co-authored-by: yuwk <52391318+ump45nose@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jason <farion1231@gmail.com> |
||
|
|
fb56453702 |
feat(gemini,grok): switch Gemini CLI and Grok Build by replacing only key fields
Switching, adding, editing, sync and entering or leaving local routing now write Gemini CLI and Grok Build through the write engine. Whole-file rewrites, backfill before switching and snippet merging are gone. Gemini CLI: - Only the key-field lines in .env change; comments, order and the user's own variables stay. In settings.json only security.auth.selectedType and model.name change. Both files commit as one operation. - selectedType follows the provider type (Google login for official cards, API key otherwise) instead of the row, so a /auth choice an older version stored in a row can no longer send a third-party card through Google login. - Local routing writes the route's model name along with the local address and placeholder key, so switching to a route with another model rewrites the client, as Claude Code does. - Vertex rows pass validation with GOOGLE_API_KEY or GOOGLE_GENAI_USE_VERTEXAI instead of GEMINI_API_KEY. - The common-config snippet is frozen like Claude's and Codex's; its UI and the explainer dialog are removed. New rows keep commonConfigEnabled: true for older versions that sync them. Grok Build: - Only models.default and the [model."<name>"] table CC Switch wrote change; MCP servers and the user's other tables stay. - The written table name is recorded in live-state.json in the same operation, and switching away removes the recorded table rather than whatever models.default points to now, so a default changed in Grok's /settings no longer leaves the old provider's table behind. Without a record (just upgraded), the table is inferred from the current row. Tables holding the proxy placeholder key are always removed. - Local routing writes the route's table pointing at the local /grokbuild/v1 endpoint with the placeholder key through the engine. An official card cannot be a route. Editors: - Both editors show what the client files will look like after switching. On save, key fields go to the row and other edits go to live as global settings with a three-way check. Gemini row fields that never reach live can be added to the global settings; Grok's can be copied, as in Codex. The TOML diffing shared with Codex moves to editor_toml.rs. Also: - First-run import no longer moves key fields (GEMINI_MODEL, Codex model_reasoning_effort and the like) from the default row into the snippet, where a frozen snippet would lose them. - The .env patch can remove keys unconditionally and parse entries. |
||
|
|
0e6430abdb |
feat(codex): switch Codex by replacing only key fields
Switching, adding, editing, sync, universal providers and entering or leaving local routing now write Codex through the write engine. Only routing, credential, model, reasoning, context-window and compatibility fields are replaced; MCP servers, [projects], comments and the user's own provider tables stay byte-for-byte. auth.json, config.toml, the model catalog, the managed-account marker and a device-local login stash commit as one operation, so a crash at any point rolls forward on startup. - Third-party routes are always written as [model_providers.custom] with the key in experimental_bearer_token. Rows that use another id, a top-level openai_base_url or a legacy reserved table are normalized on the way out. Switching to an official card leaves a dormant custom table (local proxy address plus placeholder credential) so older third-party sessions can still resume. - requires_openai_auth follows the route's auth and whether a login is on disk; keyring and ephemeral credential stores are handled separately. - A switch is refused before anything is written when the active profile overrides the route, the selected table is missing or built in, a keyless row would fall back to the official login, or the row has no auth. - Provider tables an older version wrote are removed only when they can be proven to be CC Switch's. Tables a profile references are kept, and reserved ids that cannot be proven are renamed. - Provider-exclusive fields, including web_search and a row's own model_catalog_json, are removed on the way out only when live still holds the previous provider's value. - No more backfill. A native ChatGPT login that CC Switch deletes or overwrites is kept in ~/.cc-switch/codex-login-stash.json (0600, not synced) and restored when switching back to an official card; logging out on an official card discards it. Login snapshots already in official rows seed the stash once. A leftover API key in auth.json is deleted only when it matches a third-party row's key. - Managed accounts fetch their token before taking the lock. If the CLI refreshes the login during a switch, the switch stops before writing anything. Once files are published, a later failure no longer rolls the row back; startup finishes the switch. - Local routing: third-party routes get a fixed local-proxy table and the official route uses cc-switch-official plus the client's own login. The contract covers every field written, so a route switch with the same contract touches no files. - The Codex editor shows what config.toml will look like after switching. On save, key fields go to the row and other edits go to live as global settings with a three-way check. Row fields that never reach live are listed read-only and can be copied. - The Codex common-config snippet is frozen like Claude's; its UI and the TOML snippet command are removed. New Codex rows keep commonConfigEnabled: true for older versions that sync them. - The write engine can delete a file as part of an operation. - Integration-test mutexes tolerate poisoning so one failure no longer cascades into unrelated tests. |
||
|
|
63ed5002e5 |
feat(claude): switch Claude Code by replacing only key fields
Switching, adding the first provider, editing the current provider, sync, universal providers and restoring after the local router all write settings.json through the write engine now. Only endpoint, credential, model and protocol fields plus the provider's own switches are replaced; hooks, plugins, permissions and everything else stay byte-for-byte. The file write and the current-provider pointer commit as one operation, so a crash in between rolls forward on startup. - No more backfill, no common-config snippet and no context-window injection for Claude. Window values left behind by the old injection are cleaned up from a frozen list. - The provider editor shows what settings.json will look like after switching. On save, provider fields go back to the row and other edits go to live as global settings, with a three-way check against external changes and a dialog to resolve conflicts. Row fields that never reach live are listed with a one-click add. - New Claude rows keep commonConfigEnabled: true so older versions that sync the row still merge their snippet. - Presets drop timeout and telemetry keys; a test now requires Claude presets to contain only key or provider-owned fields. |
||
|
|
15884b2038 |
fix(codex): recover stale account bindings during takeover (#7395)
After deleting a managed ChatGPT account and logging in again, a Codex provider can still reference the old local account ID, which made route switching, takeover, startup restoration and rebinding fail permanently. Distinguish a missing outgoing account from an existing account with no matching live token. A missing account only releases its ownership marker after the persisted account store is verified; the target write policy stays in force. A stale target now reports an account-selection instruction instead of a bare not-found error, including when takeover is already enabled. Fixes #7392 |
||
|
|
0455a92c1f |
fix(codex): allow multiple follow-login providers (#6535)
Co-authored-by: Jason <farion1231@gmail.com> |
||
|
|
a2e22f3302 |
Add managed OAuth account selection for providers (#3879)
* Add managed ChatGPT account binding for Codex * Consolidate managed account entry points * Clarify unmanaged Codex login option * fix(provider-form): show Codex FAST mode toggle in account-select mode The FAST mode switch was gated on mode === "manage", but the Claude and Claude Desktop Codex OAuth forms render CodexOAuthSection in select mode while still passing onFastModeChange. The toggle was therefore hidden: new providers couldn't enable FAST mode and existing ones couldn't turn it off, even though the backend still honors meta.codexFastMode. Gate the toggle on onFastModeChange presence instead, restoring the pre-refactor behavior without affecting the manage panel or native Codex form (which do not pass the handler). * fix(i18n): localize Codex managed-account none option label ProviderForm passed a hardcoded Chinese string as codexOauthNoneOptionLabel, so en/ja/zh-TW users saw Chinese text in the Codex account selector's "none" option. Add codexOauth.noneOptionLabel to all four locales and resolve it via t(). * feat(codex): write managed ChatGPT id_token into live auth + reauth prompt Bind the selected ChatGPT account's id_token into the Codex official managed auth.json so it matches a native browser login for the fields that drive behavior (auth_mode, account/plan/email via id_token claims). - Persist id_token on CodexAccountData; capture at login and on refresh (empty string treated as missing). Add get_valid_token_and_id_token_for_account. - codex_managed_oauth_live_auth now writes tokens.id_token when available. - Keep the managed-vs-native safety marker intact: extract_codex_managed_oauth_auth tolerates id_token but still rejects native logins (which carry refresh_token / top-level last_refresh), so cc-switch never clears a real browser login. refresh_token and last_refresh are intentionally NOT written for this reason. - Surface reauth_required (account has no stored id_token) through GitHubAccount -> ManagedAuthAccount -> TS. Legacy accounts get a styled amber prompt + one-click re-login (device flow) in CodexOAuthSection, flagged in both the selector dropdown and the select-mode hint. - i18n: reauth strings added for en / ja / zh / zh-TW. Verified: pnpm typecheck + build:renderer green; cross-model review of Rust correctness, the managed-vs-native safety invariant, and the id_token lifecycle. * style(codex): satisfy prettier format check for reauth UI * fix(i18n): add missing managed-account selector keys The managed OAuth account selector referenced codexOauth.chatgptAccount, codexOauth.manageAccounts, copilot.githubAccount, copilot.manageAccounts and providerForm.providerKeyStatusLoading with Chinese defaultValue fallbacks, so the en/ja/zh-TW UIs rendered Chinese text. Add the translations across all four locales. Addresses review feedback on #3879. * fix(providers): don't clear managed OAuth binding on status-query failure useManagedAuth now exposes isStatusSuccess. The account-clear effect in the Codex/Copilot selector sections only unbinds when the status query has *successfully* loaded and the bound account is genuinely gone. Previously a failed or still-pending query yielded an empty accounts array, which silently cleared the selection; the subsequent save then dropped providerType/authBinding and turned a managed provider into a broken unbound config. Addresses review feedback on #3879. * fix(codex-oauth): make managed accounts safe & usable with the bare CLI Addresses review feedback on #3879. These backend changes are deeply intertwined across shared files, so they are committed together. Refreshable managed auth (bare `codex` support): - Write a full, native-shaped auth.json bundle (tokens.refresh_token + top-level last_refresh) instead of an access-only token, so the Codex CLI can self-refresh and the managed account keeps working past ~1h without a proxy. - last_refresh reflects the access token's real obtained-at time (not write time), so the CLI doesn't treat a cached token as freshly refreshed. - Read back the CLI-rotated refresh_token from ~/.codex/auth.json before writing (account_id-matched, chatgpt-mode guarded) so re-switching doesn't clobber the CLI's valid login with a stale refresh_token. Never persist managed tokens at rest: - Backfill of a managed provider always replaces live auth with the stored placeholder (even on marker mismatch), so native tokens can't leak into the provider's DB config. - Sanitize managed auth out of Live backups on the initial/strict snapshot paths and in update_live_backup_from_provider_inner before serialization. Concurrency / blocking: - Drop the redundant outer Arc<RwLock<CodexOAuthManager>> (all methods are &self) so token refresh no longer holds a coarse lock across the network; give OAuth token/device requests a 30s timeout instead of the shared 600s client default. - Add a persistence lock and linearize the access-token cache under a consistent accounts -> access_tokens order (existence-checked reads/writes; remove/clear clear the cache atomically) to prevent stale or resurrected cache entries. Switch ordering: - Preflight the managed token before committing the current provider on switch/add/update, so a failed token fetch can't leave DB/UI pointing at a provider whose live config was never written. Cleanup: - Remove the now-dead content-fingerprint marker machinery; managed writes are now shape-identical to a native login, so ownership is judged by account_id. Known, documented limitations (B-scheme, narrow & recoverable): a remove+re-login of the same account within an in-flight refresh window (ABA), a login authorized after logout, and switch-away cleanup being unable to distinguish our write from a user's native login of the same account. * fix(codex-oauth): keep managed token in restore backup; fix failing tests CI caught three test failures from the previous commit. Root cause: the Live backup (proxy_live_backup) is local restore state that is replayed to ~/.codex/auth.json when proxy takeover ends, so it must contain the real auth to restore a working login. Stripping it (the earlier "don't leak into backup" change) broke restore and over-stripped a user's native login. - Revert the backup auth stripping: remove sanitize_codex_backup_auth from the initial/strict snapshot paths and the forced auth={} in update_live_backup_from_provider_inner. The managed token belongs in the restore backup (the refresh_token is already persisted by CodexOAuthManager, so this is not a new exposure). - Restore the ownership marker (account_id + access_token fingerprint) so backup cleanup can tell our managed write from a user's native `codex login` of the same account. extract now also tolerates the full-bundle shape (refresh_token + last_refresh) so it fingerprints ①'s refreshable writes. clear_codex_auth_in_backup and clear_codex_live_auth_for_managed_account use the marker again; the account_id-only helper is dropped. - Fix the adopt unit test: adopt now invalidates the cached access token, so the test asserts the stored refresh_token/id_token were updated and the cache was cleared instead of reading it back through get_valid_token_bundle (which would trigger a network refresh). Token stays out of the exported provider settings_config (backfill strip) — only the local restore backup keeps it, matching pre-existing behavior. * fix(codex): harden managed OAuth credential lifecycle * fix: preserve Codex restore auth state * feat(codex): support multiple official accounts * feat(codex): refine official account login selection Keep native Codex login separate from managed ChatGPT accounts, migrate provider identity safely when switching modes, and cover the account-selection states with regression tests. * style(codex): satisfy clippy for login guard --------- Co-authored-by: Jason <farion1231@gmail.com> Co-authored-by: YUZHEthefool <2804776511@qq.com> |