fix(ui): show disabled codex model tiles
This commit is contained in:
parent
c1a2ccc0a7
commit
e185f1f686
2 changed files with 96 additions and 2 deletions
|
|
@ -306,6 +306,32 @@ function getVisibleRuntimeModels(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function withSupplementalDisabledRuntimeModels(
|
||||||
|
providerId: SupportedProviderId,
|
||||||
|
models: readonly string[],
|
||||||
|
providerStatus?: TeamModelRuntimeProviderStatus | null
|
||||||
|
): string[] {
|
||||||
|
if (providerId !== 'codex') {
|
||||||
|
return [...models];
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelSet = new Set(models);
|
||||||
|
const supplementalDisabledModels = getTeamProviderModelOptions(providerId)
|
||||||
|
.map((option) => option.value.trim())
|
||||||
|
.filter(
|
||||||
|
(model) =>
|
||||||
|
model.length > 0 &&
|
||||||
|
!modelSet.has(model) &&
|
||||||
|
getTeamModelUiDisabledReason(providerId, model, providerStatus) !== null
|
||||||
|
);
|
||||||
|
|
||||||
|
return sortTeamProviderModels(
|
||||||
|
providerId,
|
||||||
|
[...models, ...supplementalDisabledModels],
|
||||||
|
providerStatus
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function getModelAvailabilityMap(
|
function getModelAvailabilityMap(
|
||||||
providerStatus?: TeamModelRuntimeProviderStatus | null
|
providerStatus?: TeamModelRuntimeProviderStatus | null
|
||||||
): Map<string, CliProviderModelAvailability> {
|
): Map<string, CliProviderModelAvailability> {
|
||||||
|
|
@ -416,7 +442,11 @@ export function getAvailableTeamProviderModelOptions(
|
||||||
return getFallbackTeamProviderModelOptions(providerId, providerStatus);
|
return getFallbackTeamProviderModelOptions(providerId, providerStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
const visibleModels = getRuntimeSelectorModels(providerId, providerStatus);
|
const visibleModels = withSupplementalDisabledRuntimeModels(
|
||||||
|
providerId,
|
||||||
|
getRuntimeSelectorModels(providerId, providerStatus),
|
||||||
|
providerStatus
|
||||||
|
);
|
||||||
return [
|
return [
|
||||||
{ value: '', label: 'Default', badgeLabel: 'Default' },
|
{ value: '', label: 'Default', badgeLabel: 'Default' },
|
||||||
...visibleModels.map((model) => {
|
...visibleModels.map((model) => {
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,11 @@ describe('TeamModelSelector disabled Codex models', () => {
|
||||||
expect(onValueChange).toHaveBeenCalledWith('');
|
expect(onValueChange).toHaveBeenCalledWith('');
|
||||||
expect(host.textContent).toContain('5.4');
|
expect(host.textContent).toContain('5.4');
|
||||||
expect(host.textContent).toContain('5.3 Codex');
|
expect(host.textContent).toContain('5.3 Codex');
|
||||||
expect(host.textContent).not.toContain('5.2 Codex');
|
const disabledCodexButton = Array.from(host.querySelectorAll('button')).find((button) =>
|
||||||
|
button.textContent?.includes('5.2 Codex')
|
||||||
|
);
|
||||||
|
expect(disabledCodexButton).not.toBeNull();
|
||||||
|
expect(disabledCodexButton?.getAttribute('aria-disabled')).toBe('true');
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
root.unmount();
|
root.unmount();
|
||||||
|
|
@ -703,6 +707,66 @@ describe('TeamModelSelector disabled Codex models', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps known disabled Codex tiles visible when the runtime omits them', async () => {
|
||||||
|
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||||
|
storeState.cliStatus = {
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
providerId: 'codex',
|
||||||
|
models: ['gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex', 'gpt-5.2'],
|
||||||
|
modelVerificationState: 'idle',
|
||||||
|
modelAvailability: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const host = document.createElement('div');
|
||||||
|
document.body.appendChild(host);
|
||||||
|
const root = createRoot(host);
|
||||||
|
const onValueChange = vi.fn();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
root.render(
|
||||||
|
React.createElement(TeamModelSelector, {
|
||||||
|
providerId: 'codex',
|
||||||
|
onProviderChange: () => undefined,
|
||||||
|
value: '',
|
||||||
|
onValueChange,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
await Promise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
const disabledButtons = ['5.3 Codex Spark', '5.2 Codex', '5.1 Codex Mini'].map((label) => {
|
||||||
|
const button = Array.from(host.querySelectorAll('button')).find((candidate) =>
|
||||||
|
candidate.textContent?.includes(label)
|
||||||
|
);
|
||||||
|
expect(button, `${label} should stay visible as a disabled option`).not.toBeNull();
|
||||||
|
expect(button?.getAttribute('aria-disabled')).toBe('true');
|
||||||
|
expect(button?.textContent).toContain('Disabled');
|
||||||
|
expect(button?.getAttribute('title')).toContain('Temporarily disabled for team agents');
|
||||||
|
return button;
|
||||||
|
});
|
||||||
|
|
||||||
|
const activeButton = Array.from(host.querySelectorAll('button')).find((button) =>
|
||||||
|
button.textContent?.includes('5.2')
|
||||||
|
);
|
||||||
|
expect(activeButton?.textContent).toContain('Recommended');
|
||||||
|
expect(activeButton?.getAttribute('aria-disabled')).toBe('false');
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
disabledButtons[0]?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||||
|
await Promise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(onValueChange).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
root.unmount();
|
||||||
|
await Promise.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('keeps 5.1 Codex Max selectable on the native Codex path', async () => {
|
it('keeps 5.1 Codex Max selectable on the native Codex path', async () => {
|
||||||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||||
storeState.cliStatus = {
|
storeState.cliStatus = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue