refactor(tui): unify API format representation across all apps#236
Open
heliar-k wants to merge 6 commits into
Open
refactor(tui): unify API format representation across all apps#236heliar-k wants to merge 6 commits into
heliar-k wants to merge 6 commits into
Conversation
Why this change was needed: The proxy layer already supported converting between Responses API and Chat Completions API for Codex providers, but the TUI had no direct way to configure which upstream API format to use. Users could only indirectly control this through the Local Routing sub-page. What changed: - Added CodexApiFormat enum (Chat/Responses) and codex_api_format state field as the authoritative source of truth for Codex routing - Added CodexApiFormat field to the main Codex provider form, positioned between Model and Local Routing - Renamed ClaudeApiFormatPicker to ApiFormatPicker with handler dispatch by app_type (Claude writes claude_api_format, Codex writes codex_api_format) - Migrated all Codex-specific claude_api_format references to codex_api_format (toggle, loading, serialization, templates) - Renamed i18n functions for consistency (tui_claude_api_format_requires_proxy_title -> tui_api_format_requires_proxy_title) Problem solved: Users can now directly select the upstream API format for Codex providers (OpenAI Chat Completions vs OpenAI Responses API) from the main provider form, enabling use of Chat Completions-only providers with the latest Codex CLI through the local proxy.
Align CLI template seed with TUI serializer by passing app_type to template_default_meta so Codex sponsor templates emit apiFormat meta. Add Default derive to CodexApiFormat, rename popup title function for naming consistency, and remove unreachable Codex branch from ClaudeApiFormat render arm.
…Format Why this change was needed: `CodexApiFormat::Chat` and `CodexApiFormat::Responses` were ambiguous next to `ClaudeApiFormat::OpenAiChat` and `ClaudeApiFormat::OpenAiResponses`. The two enums represent the same wire protocols and should share naming. What changed: - Renamed `CodexApiFormat::Chat` → `OpenAiChat` - Renamed `CodexApiFormat::Responses` → `OpenAiResponses` - Updated all 10 usage sites across 5 files Problem solved: Readers no longer need to mentally map `Chat` → `OpenAiChat` when comparing the two enums; the naming is now self-documenting.
…audeApiFormat to ApiFormat
221cd7c to
0f612c6
Compare
Why this change was needed: The previous refactor over-renamed Claude-specific API format functions to generic names, losing the symmetry with their codex_ counterparts. What changed: - Restored 7 CLI function names: normalize_claude_api_format, effective_claude_api_format, strip_claude_api_format_legacy_settings, apply_claude_api_format, apply_fixed_claude_api_format_if_needed, prompt_claude_api_format, prompt_and_apply_claude_api_format - Restored 9 test function names to claude_api_format_* prefix - Kept prompt_api_format_select generic (shared helper) - Kept API_FORMAT_* constants generic (used by both paths) Problem solved: Claude and Codex API format functions now have symmetric naming (claude_* vs codex_*), making it clear which path each function serves.
Why this change was needed:
Users reported that changing a Claude provider's api_format from "openai_chat"
to Anthropic native in the TUI would appear to save successfully, but the value
would revert to "openai_chat" after restarting the application.
What changed:
- Modified update_provider_meta() to keep the "meta" key in JSON output even
when the meta object is empty (produces "meta": {} instead of omitting it)
- Added comprehensive regression test exercising the full TUI form edit flow
from ProviderAddFormState through ProviderService::update() and AppState reload
Problem solved:
The root cause was a two-part bug chain:
1. update_provider_meta() removed the entire "meta" key when meta became empty
2. ProviderService::update() merge logic preserved old meta when incoming
provider had meta: None (JSON deserialization of missing key = None)
By keeping "meta": {} in the JSON, deserialization now produces
Some(ProviderMeta::default()) instead of None, ensuring the merge logic treats
the form output as authoritative rather than falling back to old meta values.
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.
Summary
Add a Codex API format picker to the TUI provider form, unify API format representation across all apps under a single
ApiFormatenum, and fix a bug where provider meta would revert to old values after editing.Key Changes
1. Codex API Format Picker
2. Enum Unification
ClaudeApiFormat→ApiFormat(describes generic wire protocols, not Claude-specific)claude_api_format+codex_api_formatfields with a singleapi_formatfieldProviderAddField::ClaudeApiFormat+::CodexApiFormat→::ApiFormat3. Naming Consistency
get_claude_api_format→get_provider_api_formatCLAUDE_API_FORMAT_*→API_FORMAT_*(shared by both paths)tui_label_claude_api_format→tui_label_api_formatclaude_*↔codex_*4. Codex Sponsor Templates
apiFormatmeta, aligning CLI output with TUI serializer5. Code Cleanup
ApiFormatenum fromproxy/types.rs6. Bug Fix: Provider Meta Revert After Edit
apiFormat(e.g., fromopenai_chatto Anthropic) in the TUI would appear to save, but revert to the old value after restartupdate_provider_meta()removed the entiremetakey when the meta object became empty, producing JSON withoutmeta. On deserialization this yieldedmeta: None, which triggered the merge logic inProviderService::update()to preserve the old meta (including the oldapiFormat)"meta": {}in the JSON output even when empty, so deserialization producesSome(ProviderMeta::default())and the merge logic correctly treats the form output as authoritativeImpact
Tests
api_formattests pass (including newtest_exact_tui_form_api_format_roundtripregression test)codex_local_routingtests passprovider_add_form_codextests passcli_provider_templates_match_tui_serializer_output(previously failing, now fixed)Verification