fix(local-model): a switch ends on the list of models, not on the one-button screen

Seen on a MacBook (M5 Pro, 2026-11-12): pressing Use on a model in "Models on this Mac"
ran the switch and then showed the screen that ends an install, "X is ready on this Mac"
with Start a session alone. The list was gone, so deleting the model just switched away
from meant closing the window and opening it again.

That screen is right after a download: the person installed a model and wants a session.
A switch is pressed IN the list by someone who is tidying it. A switch is a job without a
`model` step, so the window now tells the two apart from the job it just watched and ends a
switch on the whole installed screen: the list with "In use" on the other row, Add a model,
Stop and Remove.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-11-12 00:10:55 +01:00
1 parent db81d55fc9
commit 9c2ba35f38
3 files changed
+56 -6

No files matched your search

+43
View File
@@ -2679,6 +2679,49 @@ describe('the models on this Mac', () => {
expect(buttons(page.body)).toEqual(['Start a session']);
});
// Seen on a Mac: Use, then the list was gone, and deleting the other model meant closing the
// window and opening it again.
it('a switch that ends in the open window comes back to the list, the other model in use', async () => {
const page = mount();
const switching = status(
{},
{
...TWO.install,
state: 'installing',
step: 'verify',
steps: ['verify', 'connect'],
model: { id: 'gpt-oss:20b', label: 'GPT-OSS 20B' },
library: [
{ ...QWEN_ROW, active: false },
{ ...GPT_ROW, actions: [] },
],
actions: ['cancel'],
}
);
const switched = status(
{},
{
...TWO.install,
model: { id: 'gpt-oss:20b', label: 'GPT-OSS 20B' },
library: [
{ ...GPT_ROW, active: true, actions: [] },
{ ...QWEN_ROW, active: false, actions: ['use', 'delete'] },
],
}
);
const { app, serve } = await opened(page, switching);
expect(page.body.dataset.screen).toBe('progress');
serve(switched);
await app.loadLocalModel({ force: true });
expect(page.body.dataset.screen).toBe('installed');
expect(texts(page.body, '.lm-lib-label')).toEqual(['GPT-OSS 20B', 'Qwen3.6 35B-A3B']);
expect(texts(page.body, '.lm-lib-tag .lm-tag')).toEqual(['In use', 'Ready']);
expect(rowButtons(page)).toEqual(['Use', 'Delete']);
// The whole installed screen, not the one-button screen that ends an install.
expect(buttons(page.body)).toEqual(['Remove', 'Stop', 'Start a session']);
expect(texts(page.body, '.lm-lib-foot button')).toEqual(['Add a model']);
});
it('"Add a model" opens the chooser on an installed model, and Back returns to it', async () => {
const page = mount();
const { app } = await opened(page, TWO);