Skip to content

fix(ui): key the live-config snapshot to the provider being edited - #6474

Open
ntdatt812 wants to merge 1 commit into
farion1231:mainfrom
ntdatt812:fix/edit-dialog-live-settings-6445
Open

ntdatt812 wants to merge 1 commit into
farion1231:mainfrom
ntdatt812:fix/edit-dialog-live-settings-6445

Conversation

@ntdatt812

@ntdatt812 ntdatt812 commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary / 概述

Editing a provider could show another provider's API key. EditProviderDialog loads the live config for whichever provider is currently applied, and guarded that load with a plain hasLoadedLive boolean. The flag records that a snapshot was loaded but not which provider it belongs to.

App.tsx derives the panel's open state from the selection itself:

open={Boolean(editingProvider)}

So picking a different provider swaps provider while open stays true. The effect re-runs, hits if (hasLoadedLive) return, and the previous provider's live snapshot stays in state — initialSettingsConfig prefers liveSettings over provider.settingsConfig, so the form renders the wrong key.

The fix keys the snapshot by (appId, provider.id) and derives liveSettings from it:

const liveLoadKey = open && provider ? `${appId}::${provider.id}` : null;
const liveSettings = loadedLive.key === liveLoadKey ? loadedLive.settings : null;

A stale key now yields null, so the form falls back to the SSOT config until the new load settles — there is no frame where one provider's live config is shown under another's name. This is the same shape as formReadyToken twenty lines above in the same file, which already keys its state on [appId, open, provider?.id].

While collapsing the four setLiveSettings/setHasLoadedLive pairs into one settle() helper, the outer try around providersApi.getCurrent turned out to have a finally but no catch, so a failure there left the previous snapshot in place and never settled. It now falls back to SSOT like the inner handler already did.

Related Issue / 关联 Issue

Refs #6445 — partially.

#6445 reports two symptoms and this only accounts for the second one:

  • "启用另外一个供应商后,点击编辑,其 api key 显示的也不对" — covered, and reproduced in a test below.
  • "启用 deepseek 的时候,点击其编辑 显示的是中转站的 api key" — not covered. If deepseek is the applied provider, the live read is supposed to return deepseek's own config, so why the relay's key ends up there is a separate question I could not settle from the renderer. I have deliberately not written Fixes so the issue stays open for that half.

Verification

Added a regression test that renders the active provider, waits for its live snapshot, then swaps in a different provider without closing — exactly what Boolean(editingProvider) produces.

without the fix:  × does not show the previous provider's live settings after switching providers while open
                    expected '{"auth":{"OPENAI_API_KEY":"relay-live…' to contain 'deepseek-db-key'
with the fix:     Test Files 122 passed (122)
                  Tests      877 passed (877)

One note on the numbers: an earlier baseline run on a clean checkout showed 2 unrelated failures that did not reproduce on re-run, so the suite looks mildly flaky somewhere. Without this change the only failure is the new test; with it the full run is green.

Unrelated observation, not changed here

isProxyTakeover is passed to this dialog without the isProxyRunning conjunct that every other call site uses:

// App.tsx:1109 — ProviderList
isProxyTakeover={isProxyRunning && isCurrentAppTakeoverActive}
// App.tsx:1326
active={isProxyRunning && isCurrentAppTakeoverActive}
// App.tsx:1771 — EditProviderDialog
isProxyTakeover={isCurrentAppTakeoverActive}

With the proxy stopped but a takeover still recorded, the dialog therefore skips the live read and shows the SSOT config, which is the opposite of what the comment on that branch intends. It fails safe rather than showing a wrong key, so it is not the cause of either symptom above — flagging it rather than folding it into this PR. Happy to send it separately if you agree it is wrong.

Checklist / 检查清单

  • pnpm typecheck passes / 通过 TypeScript 类型检查
  • pnpm format:check passes / 通过代码格式检查
  • cargo clippy passes (if Rust code changed) — no Rust changed
  • Updated i18n files if user-facing text changed — no user-facing text changed

@ntdatt812
ntdatt812 requested a review from farion1231 as a code owner August 15, 2026 06:39
@github-actions github-actions Bot added the frontend Frontend (React/TypeScript) label Aug 15, 2026
@ntdatt812
ntdatt812 force-pushed the fix/edit-dialog-live-settings-6445 branch from 9c82ad7 to f7049de Compare August 15, 2026 06:43
@farion1231

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: f7049def31

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ntdatt812
ntdatt812 force-pushed the fix/edit-dialog-live-settings-6445 branch from f7049de to d7f26b8 Compare September 1, 2026 04:34
EditProviderDialog reads the live config for the currently applied provider
and guarded that read with a hasLoadedLive boolean, which records that a
snapshot was loaded but not which provider it belongs to.

App.tsx sets open={Boolean(editingProvider)}, so selecting a different
provider swaps `provider` while the panel stays open. The effect re-ran, hit
the guard, and kept the previous snapshot — and since initialSettingsConfig
prefers liveSettings over provider.settingsConfig, the form showed the wrong
API key.

Keys the snapshot by (appId, provider.id) and derives liveSettings from that
key, mirroring formReadyToken in the same file. A stale key falls back to the
SSOT config, so no frame renders one provider's live config under another's
name.

Also gives the getCurrent call a catch: it had a finally but no catch, so a
failure there left the previous snapshot in place and never settled.

Refs farion1231#6445 — covers the "switching providers shows the wrong key" symptom
only. The reported case of the applied provider itself showing a relay key is
not accounted for here, so the issue should stay open.
@ntdatt812
ntdatt812 force-pushed the fix/edit-dialog-live-settings-6445 branch from d7f26b8 to 2ed9fc7 Compare September 19, 2026 02:16
@ntdatt812

Copy link
Copy Markdown
Contributor Author

Rebased onto main. It had gone CONFLICTING after #7383. The only overlap was the exclusion check that #7383 extended with mcode: the check now covers all three apps and calls settle(null) like the other branches. The fix itself is unchanged (same added and removed lines as before). EditProviderDialog.test.tsx passes 11/11 and tsc --noEmit is clean.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend Frontend (React/TypeScript)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants