-
Notifications
You must be signed in to change notification settings - Fork 3k
fix(core): preserve the selected model when re-applying a provider install plan #5835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d125484
b7f1948
fa08544
794f07c
901c6fa
0cebdec
82522ea
7fc1bbf
dd6818a
383a6e2
35ed5e4
2410e73
51de03d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4872,8 +4872,12 @@ class QwenAgent implements Agent { | |||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| const persistScope = readProviderConnectScope(params['scope']); | ||||||||||||||||||||||||||
| const plan = buildInstallPlan(providerConfig, inputs); | ||||||||||||||||||||||||||
| const adapter = createLoadedSettingsAdapter( | ||||||||||||||||||||||||||
| this.settings, | ||||||||||||||||||||||||||
| persistScope, | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| await applyProviderInstallPlan(plan, { | ||||||||||||||||||||||||||
| settings: createLoadedSettingsAdapter(this.settings, persistScope), | ||||||||||||||||||||||||||
| settings: adapter, | ||||||||||||||||||||||||||
| reloadModelProviders: (modelProviders) => | ||||||||||||||||||||||||||
| this.config.reloadModelProvidersConfig(modelProviders), | ||||||||||||||||||||||||||
| syncAuthState: (authType, modelId, baseUrl) => | ||||||||||||||||||||||||||
|
|
@@ -4882,16 +4886,19 @@ class QwenAgent implements Agent { | |||||||||||||||||||||||||
| .syncAfterAuthRefresh(authType, modelId, baseUrl), | ||||||||||||||||||||||||||
| refreshAuth: (authType) => this.config.refreshAuth(authType), | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const effectiveModelId = | ||||||||||||||||||||||||||
| (adapter.getValue('model.name') as string | undefined) ?? | ||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Critical] The new Verified: base branch passes 155/155, this PR fails 3/155.
Suggested change
Or better: update the mock in createLoadedSettingsAdapter: vi.fn((settings: unknown) => ({
...settings,
getValue: vi.fn(),
})),— qwen3.7-max via Qwen Code /review
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Critical] The new The PR fixed two sibling test files ( Failing tests:
Either upgrade
Suggested change
matching the pattern used in the two fixed test files. — qwen3.7-max via Qwen Code /review
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Critical] The Add a test where — qwen3.7-max via Qwen Code /review |
||||||||||||||||||||||||||
| plan.modelSelection?.modelId; | ||||||||||||||||||||||||||
| const effectiveBaseUrl = | ||||||||||||||||||||||||||
| (adapter.getValue('model.baseUrl') as string | undefined) ?? | ||||||||||||||||||||||||||
| plan.modelSelection?.baseUrl; | ||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||
| success: true, | ||||||||||||||||||||||||||
| providerId: providerConfig.id, | ||||||||||||||||||||||||||
| providerLabel: providerConfig.label, | ||||||||||||||||||||||||||
| authType: plan.authType, | ||||||||||||||||||||||||||
| modelId: plan.modelSelection?.modelId, | ||||||||||||||||||||||||||
| ...(plan.modelSelection?.baseUrl | ||||||||||||||||||||||||||
| ? { baseUrl: plan.modelSelection.baseUrl } | ||||||||||||||||||||||||||
| : {}), | ||||||||||||||||||||||||||
| ...(effectiveModelId ? { modelId: effectiveModelId } : {}), | ||||||||||||||||||||||||||
| ...(effectiveBaseUrl ? { baseUrl: effectiveBaseUrl } : {}), | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| case 'qwen/skills/install': { | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -211,11 +211,38 @@ export async function applyProviderInstallPlan( | |||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Model selection | ||||||||||||||||||||
| // Re-applying a plan (manual /auth, ACP reconnect, token refresh, or an | ||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Critical] The The core fix for #5819 has no safety net — a regression would silently re-introduce the bug and no test would catch it. The PR description references a drop-in regression test but intentionally excludes it from the diff. Add at least two tests to
— qwen3.7-max via Qwen Code /review |
||||||||||||||||||||
| // upgrade that reordered the model list) must not silently move the user | ||||||||||||||||||||
| // off a model they chose. If the plan still offers the current model, keep | ||||||||||||||||||||
| // it; a genuine first-time setup still adopts the provider default. (#5819) | ||||||||||||||||||||
| currentStep = 'modelSelection'; | ||||||||||||||||||||
| if (plan.modelSelection?.modelId) { | ||||||||||||||||||||
| settings.setValue('model.name', plan.modelSelection.modelId); | ||||||||||||||||||||
| if (plan.modelSelection.baseUrl) { | ||||||||||||||||||||
| settings.setValue('model.baseUrl', plan.modelSelection.baseUrl); | ||||||||||||||||||||
| let effectiveModelSelection = plan.modelSelection; | ||||||||||||||||||||
| if (effectiveModelSelection?.modelId) { | ||||||||||||||||||||
| const currentModelId = settings.getValue('model.name'); | ||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Critical] This only preserves a model that was persisted in — gpt-5 via Qwen Code /review |
||||||||||||||||||||
| const currentBaseUrl = settings.getValue('model.baseUrl') as | ||||||||||||||||||||
| | string | ||||||||||||||||||||
| | undefined; | ||||||||||||||||||||
| const planOffersCurrentModel = | ||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] This new The PR description includes a comprehensive drop-in regression test (the — qwen3.7-max via Qwen Code /review
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The new Consider adding at least two test cases:
The PR description includes a drop-in regression test (in the details block) that could be committed alongside this change. — qwen3.7-max via Qwen Code /review
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The drop-in test in the PR description covers all 5 scenarios and can be run against this branch. Committing it will be a follow-up PR to keep this fix minimal. |
||||||||||||||||||||
| typeof currentModelId === 'string' && | ||||||||||||||||||||
| currentModelId.length > 0 && | ||||||||||||||||||||
| (plan.modelProviders ?? []).some((patch) => | ||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] With ID-only matching, a cross-provider model ID collision (e.g., two custom providers both offering
Suggested change
— qwen3.7-max via Qwen Code /review |
||||||||||||||||||||
| patch.models.some((model) => | ||||||||||||||||||||
| currentBaseUrl === '' || currentBaseUrl === undefined | ||||||||||||||||||||
| ? model.id === currentModelId | ||||||||||||||||||||
| : isSameModelIdentity( | ||||||||||||||||||||
| { id: currentModelId, baseUrl: currentBaseUrl }, | ||||||||||||||||||||
| model, | ||||||||||||||||||||
| ), | ||||||||||||||||||||
| ), | ||||||||||||||||||||
| ); | ||||||||||||||||||||
| if (planOffersCurrentModel) { | ||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] When Consider still applying the plan's if (planOffersCurrentModel) {
// Preserve the model name, but still apply the plan's baseUrl decision
if (plan.modelSelection?.baseUrl) {
settings.setValue('model.baseUrl', plan.modelSelection.baseUrl);
} else {
settings.setValue('model.baseUrl', '');
}
effectiveModelSelection = undefined;
}— qwen3.7-max via Qwen Code /review
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] There is no log or diagnostic signal at this decision point. When investigating "why did the user's model change" or "why was the model NOT changed" in production, there is no trace indicating whether Consider adding a debug log: log?.debug?.('applyProviderInstallPlan: model retention check', {
currentModelId,
planOffersCurrentModel,
planDefaultModelId: plan.modelSelection?.modelId,
});— qwen3.7-max via Qwen Code /review
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reasonable suggestion, out of scope for this fix. Will handle in a follow-up. |
||||||||||||||||||||
| effectiveModelSelection = undefined; | ||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] When Consider extending — qwen3.7-max via Qwen Code /review
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Already fixed: both |
||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
| if (effectiveModelSelection?.modelId) { | ||||||||||||||||||||
| settings.setValue('model.name', effectiveModelSelection.modelId); | ||||||||||||||||||||
| if (effectiveModelSelection.baseUrl) { | ||||||||||||||||||||
| settings.setValue('model.baseUrl', effectiveModelSelection.baseUrl); | ||||||||||||||||||||
| } else { | ||||||||||||||||||||
| // The plan selects by model id only, so clear any baseUrl disambiguator | ||||||||||||||||||||
| // left by a previous model-picker selection — otherwise the next launch | ||||||||||||||||||||
|
|
@@ -241,12 +268,12 @@ export async function applyProviderInstallPlan( | |||||||||||||||||||
| // Reload runtime config | ||||||||||||||||||||
| currentStep = 'reloadModelProviders'; | ||||||||||||||||||||
| reloadModelProviders?.(updatedModelProviders); | ||||||||||||||||||||
| if (plan.modelSelection?.modelId) { | ||||||||||||||||||||
| if (effectiveModelSelection?.modelId) { | ||||||||||||||||||||
| currentStep = 'syncAuthState'; | ||||||||||||||||||||
| syncAuthState?.( | ||||||||||||||||||||
| plan.authType, | ||||||||||||||||||||
| plan.modelSelection.modelId, | ||||||||||||||||||||
| plan.modelSelection.baseUrl, | ||||||||||||||||||||
| effectiveModelSelection.modelId, | ||||||||||||||||||||
| effectiveModelSelection.baseUrl, | ||||||||||||||||||||
| ); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| if (doRefreshAuth && refreshAuth) { | ||||||||||||||||||||
|
|
||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] This new test asserts
modelIdreadback but notbaseUrl. The production code introduces a paralleleffectiveBaseUrl = adapter.getValue('model.baseUrl') ?? plan.modelSelection?.baseUrlcomputation that is not exercised here.Consider extending this test (or adding a companion case) to also configure
getValueto return abaseUrland assert it appears in the response:— qwen3.7-max via Qwen Code /review