mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
fix(custom-model): show a status toast during Claude's native-boot-then-restart window
Claude stays on the launch-then-restart path (see runCustomModelEntry's own comment for why), but with nothing on screen during that window, a native boot that briefly talks to the cloud model read as "the endpoint didn't apply" rather than "the switch hasn't happened yet". A sticky "Claude started - switching to <endpoint>..." toast now covers the whole window from the native launch through the apply call, updated in place (never stacked) as the outcome resolves: dismissed on cancel or failure (replaced by the existing cancellation/error toast), handed off to _watchLlamaSwapLoading's own sticky toast when a model swap is in progress, or updated to the existing "Pointed at ... - restarting" message and auto-dismissed after 3s on a plain success. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RqZeHrRS6DYcGcGX2p9EwG
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
f865f74a0f
commit
83033b4299
@@ -398,6 +398,73 @@ describe('Custom Model Endpoint Profiles: applying a picked entry', () => {
|
||||
expect(toastType).toBe('error');
|
||||
});
|
||||
|
||||
it('shows a status toast for the native-boot-then-restart window, so it never reads as the endpoint failing to apply', async () => {
|
||||
// Claude still goes through this two-step launch (see runCustomModelEntry's own
|
||||
// comment for why) — without something saying so, the native boot it starts with
|
||||
// (which can genuinely talk to the cloud model for a moment) reads as "the
|
||||
// endpoint didn't apply" rather than "the switch hasn't happened yet".
|
||||
const { app } = bootApp({});
|
||||
app.activeSessionId = 'old-session';
|
||||
app.run = async () => {
|
||||
app.activeSessionId = 'new-session';
|
||||
};
|
||||
app._api = async () => ({
|
||||
ok: true,
|
||||
json: async () => ({ success: true, data: { customModel: { endpointId: 'llama-box' }, restarted: true } }),
|
||||
});
|
||||
const toasts: Array<{ message: string; dismissed: boolean }> = [];
|
||||
const messageHistory: string[] = [];
|
||||
app.showToast = (message: string) => {
|
||||
const entry = { message, dismissed: false };
|
||||
toasts.push(entry);
|
||||
messageHistory.push(message);
|
||||
return {
|
||||
dismiss: () => {
|
||||
entry.dismissed = true;
|
||||
},
|
||||
setMessage: (next: string) => {
|
||||
entry.message = next;
|
||||
messageHistory.push(next);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
await app.runCustomModelEntry('claude', 'llama-box', 'qwen3');
|
||||
|
||||
expect(toasts).toHaveLength(1); // updated in place, not stacked with a second toast
|
||||
expect(messageHistory[0]).toContain('Claude started — switching to llama-box');
|
||||
expect(messageHistory.at(-1)).toContain('Pointed at llama-box — restarting');
|
||||
});
|
||||
|
||||
it('dismisses the status toast on a failed apply rather than leaving it stuck on "switching"', async () => {
|
||||
const { app } = bootApp({});
|
||||
app.activeSessionId = 'old-session';
|
||||
app.run = async () => {
|
||||
app.activeSessionId = 'new-session';
|
||||
};
|
||||
app._api = async () => ({
|
||||
ok: false,
|
||||
status: 500,
|
||||
json: async () => ({ success: false, error: 'boom' }),
|
||||
});
|
||||
const toasts: Array<{ message: string; dismissed: boolean }> = [];
|
||||
app.showToast = (message: string) => {
|
||||
const entry = { message, dismissed: false };
|
||||
toasts.push(entry);
|
||||
return {
|
||||
dismiss: () => {
|
||||
entry.dismissed = true;
|
||||
},
|
||||
setMessage: () => {},
|
||||
};
|
||||
};
|
||||
|
||||
await app.runCustomModelEntry('claude', 'llama-box', 'qwen3');
|
||||
|
||||
expect(toasts[0].dismissed).toBe(true); // the "switching..." toast, cleaned up
|
||||
expect(toasts.at(-1)?.message).toContain('boom'); // the error toast, separate from it
|
||||
});
|
||||
|
||||
it('routes through run() itself, so the Run in-flight lock actually engages', async () => {
|
||||
// CLAUDE.md, Run launch synchronization: the lock exists so a double click
|
||||
// cannot create duplicate sessions. A hardcoded dispatch table bypassing
|
||||
|
||||
Reference in New Issue
Block a user