Skip to content

Preserve API mode selections after default list changes#1001

Merged
PeterDaveHello merged 1 commit into
ChatGPTBox-dev:masterfrom
PeterDaveHello:fix/general-unmatched-api-mode
Jul 12, 2026
Merged

Preserve API mode selections after default list changes#1001
PeterDaveHello merged 1 commit into
ChatGPTBox-dev:masterfrom
PeterDaveHello:fix/general-unmatched-api-mode

Conversation

@PeterDaveHello

@PeterDaveHello PeterDaveHello commented Jul 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Preserve the configured API mode when it is no longer enabled by default.
  • Show the current mode as a disabled option until another mode is explicitly selected.
  • Cover default-list changes and missing custom providers with regression tests.

This prevents default-list maintenance from making the General settings dropdown appear to select an unrelated fallback model. It does not add models back to the default list.

Follow-up to #1000 (comment).

Validation

  • npm run pretty
  • npm run lint
  • Focused unit tests: 107 passed
  • npm test: 696 passed
  • npm run build
  • Verified the expected Chromium and Firefox build artifacts

Summary by CodeRabbit

  • Bug Fixes
    • Improved “API Mode” selection behavior in General settings.
    • Added a clear “current mode” display when the configured mode doesn’t match available options.
    • Refined custom model handling so selection stays consistent (including when labels are unavailable).
    • Prevented the UI from applying invalid “unmatched” selections.
  • Tests
    • Added unit coverage for API Mode option value selection and display-label fallbacks.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 210d37e1-60e4-4fcd-9e7b-2609d999d4b1

📥 Commits

Reviewing files that changed from the base of the PR and between 9cb60e5 and cf2103e.

📒 Files selected for processing (3)
  • src/popup/sections/GeneralPart.jsx
  • src/popup/sections/api-modes-provider-utils.mjs
  • tests/unit/popup/api-modes-provider-utils.test.mjs
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/popup/sections/GeneralPart.jsx
  • src/popup/sections/api-modes-provider-utils.mjs
  • tests/unit/popup/api-modes-provider-utils.test.mjs

📝 Walkthrough

Walkthrough

The API mode dropdown now uses a shared helper to resolve its selected value, supports unmatched configured modes through a disabled fallback option, and removes per-option selection flags. Unit tests cover matched, custom, ambiguous, unmatched, and missing-provider label cases.

Changes

API mode selection

Layer / File(s) Summary
Selection resolution and coverage
src/popup/sections/api-modes-provider-utils.mjs, tests/unit/popup/api-modes-provider-utils.test.mjs
Adds the unmatched-selection sentinel and selected-option helper, with tests for matched, custom, ambiguous, unmatched, and missing-provider cases.
Dropdown selection integration
src/popup/sections/GeneralPart.jsx
Drives the API mode <select> from a resolved value, renders unmatched current labels as disabled options, ignores the sentinel on change, and removes per-option selected handling.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant GeneralPart
  participant getSelectedApiModeOptionValue
  User->>GeneralPart: open API mode select
  GeneralPart->>getSelectedApiModeOptionValue: resolve current selection
  getSelectedApiModeOptionValue-->>GeneralPart: return index, custom value, or unmatched sentinel
  GeneralPart-->>User: render selected or unmatched option
  User->>GeneralPart: choose an API mode option
  GeneralPart-->>User: ignore unmatched sentinel or apply selected option
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: preserving the selected API mode when the default list changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Preserve API mode selection when default mode list changes

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Keep configured API mode visible even if it is no longer in the default enabled list.
• Render the current mode as a disabled select option until the user picks a valid mode.
• Add unit tests for unmatched/ambiguous selections and missing custom providers.
Diagram

graph TD
  D[("Config / session state")] --> B["api-modes-provider-utils.mjs"] --> C["GeneralPart.jsx <select>"]
  C --> E["Disabled 'current' option"]
  B --> F["model-name-convert.mjs"]
  C --> G["getApiModeDisplayLabel()"] --> H["modelNameToDesc()"]
  T["Unit tests"] --> B --> C
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Auto-migrate stored selection to a nearest available default mode
  • ➕ Avoids showing a disabled/unselectable value in the dropdown
  • ➕ Users are immediately on a working default without extra interaction
  • ➖ Risky implicit behavior change; can silently switch users to a different provider/model
  • ➖ Hard to define “nearest” consistently across providers and custom entries
2. Keep deprecated modes in the default list (soft-deprecate)
  • ➕ No unmatched state; existing selections continue to appear as active options
  • ➕ Simpler UI logic
  • ➖ Contradicts the goal of default-list maintenance (would effectively re-enable removed modes)
  • ➖ Can keep obsolete providers/models visible longer than intended
3. Persist and select by a stable mode id, with an explicit deprecation flag
  • ➕ More robust than array index selection; supports renames/reorders cleanly
  • ➕ Allows intentional UX for deprecated modes (warning, migration prompt)
  • ➖ Requires a data model/storage migration and more widespread code changes
  • ➖ More review surface and higher regression risk than the current targeted fix

Recommendation: The PR’s approach is the best trade-off: treat the dropdown as a controlled component, compute a stable option value, and represent “unmatched current selection” explicitly as a disabled option until the user chooses a valid mode. This avoids silent behavior changes while making the UI honest about what is configured.

Files changed (3) +136 / -7

Enhancement (1) +14 / -1
api-modes-provider-utils.mjsAdd unmatched-selection sentinel and helper to compute selected option value +14/-1

Add unmatched-selection sentinel and helper to compute selected option value

• Introduces 'UNMATCHED_API_MODE_VALUE' and 'getSelectedApiModeOptionValue()' to consistently map config/session state to a select option value. Uses unique-selection detection and preserves custom model selection while signaling unmatched selections to the UI.

src/popup/sections/api-modes-provider-utils.mjs

Bug fix (1) +23 / -6
GeneralPart.jsxControl API mode select value and show unmatched current mode as disabled option +23/-6

Control API mode select value and show unmatched current mode as disabled option

• Switches the API mode dropdown to a controlled 'value' derived from config via a shared helper. When the configured mode/model is not present in the active/default list, it renders the current selection as a disabled option and prevents selecting it, avoiding misleading fallback selection.

src/popup/sections/GeneralPart.jsx

Tests (1) +99 / -0
api-modes-provider-utils.test.mjsAdd regression tests for unmatched/ambiguous API mode selection and missing provider fallback +99/-0

Add regression tests for unmatched/ambiguous API mode selection and missing provider fallback

• Adds unit tests covering selected index resolution, unmatched modelName/apiMode preservation, no-active-modes and ambiguous-duplicate cases, and ensures label generation falls back when a referenced custom provider is missing.

tests/unit/popup/api-modes-provider-utils.test.mjs

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the API mode selection in the GeneralPart component to use a controlled <select> element by introducing getSelectedApiModeOptionValue and handling unmatched API modes with a disabled option. It also adds corresponding unit tests. Feedback suggests avoiding the React anti-pattern of synchronizing derived state via useLayoutEffect for apiModes and instead calculating it directly during render using useMemo.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/popup/sections/GeneralPart.jsx
@kilo-code-bot

kilo-code-bot Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • src/popup/sections/GeneralPart.jsx
  • src/popup/sections/api-modes-provider-utils.mjs
  • tests/unit/popup/api-modes-provider-utils.test.mjs
Notes
  • The prior string-indexing concern (apiModes[e.target.value]) is resolved by the change to apiModes[Number(e.target.value)] plus the missing-entry guard.
  • The active comment on GeneralPart.jsx:114 from another reviewer concerns the pre-existing apiModes useState/useLayoutEffect, which is outside this PR's changed lines and is not reported here.
Previous Review Summary (commit 9cb60e5)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 9cb60e5)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • src/popup/sections/GeneralPart.jsx
  • src/popup/sections/api-modes-provider-utils.mjs
  • tests/unit/popup/api-modes-provider-utils.test.mjs

Reviewed by hy3-20260706:free · Input: 59.4K · Output: 6.7K · Cached: 253.6K

@PeterDaveHello
PeterDaveHello requested a review from Copilot July 11, 2026 19:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/popup/sections/GeneralPart.jsx (1)

495-504: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Add a guard for undefined apiMode in the onChange handler.

If apiModes changes between render and the change event, apiModes[e.target.value] could return undefined, leading to updateConfig({ apiMode: undefined }). The downstream ConversationCard guards against this with if (!selectedApiMode) return. Consider adding the same guard for consistency and safety.

🛡️ Proposed fix
             if (e.target.value === '-1') {
               updateConfig({ modelName: 'customModel', apiMode: null })
               return
             }
-            const apiMode = apiModes[e.target.value]
-            updateConfig({ apiMode: apiMode })
+            const apiMode = apiModes[Number(e.target.value)]
+            if (!apiMode) return
+            updateConfig({ apiMode: apiMode })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/popup/sections/GeneralPart.jsx` around lines 495 - 504, Update the
onChange handler for selectedApiModeValue to check whether
apiModes[e.target.value] exists before calling updateConfig. Return early when
apiMode is undefined, while preserving the existing handling for
UNMATCHED_API_MODE_VALUE and '-1'.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/popup/sections/GeneralPart.jsx`:
- Around line 495-504: Update the onChange handler for selectedApiModeValue to
check whether apiModes[e.target.value] exists before calling updateConfig.
Return early when apiMode is undefined, while preserving the existing handling
for UNMATCHED_API_MODE_VALUE and '-1'.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 197d2380-2414-4d32-a668-d06a6b6365f4

📥 Commits

Reviewing files that changed from the base of the PR and between ac4a44b and 9cb60e5.

📒 Files selected for processing (3)
  • src/popup/sections/GeneralPart.jsx
  • src/popup/sections/api-modes-provider-utils.mjs
  • tests/unit/popup/api-modes-provider-utils.test.mjs

@qodo-code-review

qodo-code-review Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Qodo Logo

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the General settings “API Mode” dropdown to preserve and visibly represent the currently configured mode even when it is no longer part of the active/default-enabled API mode list, preventing the UI from silently falling back to a different selection.

Changes:

  • Add getSelectedApiModeOptionValue + UNMATCHED_API_MODE_VALUE to represent “currently configured but unavailable” selections.
  • Convert the General settings API mode <select> to a controlled input and render a disabled “current mode” option when the configured mode is unmatched.
  • Add unit tests covering unmatched selections (legacy modelName, removed API modes, ambiguous matches) and missing custom provider label fallback.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tests/unit/popup/api-modes-provider-utils.test.mjs Adds regression tests for unmatched/ambiguous API mode selection behavior and missing custom provider label fallback.
src/popup/sections/GeneralPart.jsx Makes the API mode dropdown controlled and preserves unmatched selections via a disabled current-mode option.
src/popup/sections/api-modes-provider-utils.mjs Introduces getSelectedApiModeOptionValue and a sentinel value for representing unmatched selections in UI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/popup/sections/GeneralPart.jsx Outdated
Keep the configured API mode visible when it is no longer enabled by
default. This prevents the General settings dropdown from appearing to
select an unrelated fallback model.

Show the current mode as a disabled option until the user explicitly
chooses an available mode.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the API mode selection logic in the popup's GeneralPart section by introducing a controlled select component and a fallback placeholder for unmatched API modes. It also adds corresponding unit tests. Feedback suggests refactoring the apiModes state to a memoized value using useMemo to prevent a visual flash and double render on initial mount.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/popup/sections/GeneralPart.jsx

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment thread src/popup/sections/GeneralPart.jsx
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit cf2103e

@PeterDaveHello
PeterDaveHello merged commit 9934551 into ChatGPTBox-dev:master Jul 12, 2026
4 checks passed
@PeterDaveHello
PeterDaveHello deleted the fix/general-unmatched-api-mode branch July 12, 2026 13:35
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.

2 participants