fix(agents): avoid overload classification for live model switches

This commit is contained in:
Peter Steinberger
2026-04-27 12:27:59 +01:00
parent 82e164c018
commit 3da4b28d1b
3 changed files with 6 additions and 2 deletions

View File

@@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- CLI/doctor: run bundled plugin runtime-dependency repairs through the async npm installer with spinner/line progress and heartbeat updates, so long `openclaw doctor --fix` installs no longer look hung in TTY or piped output. Fixes #72775. Thanks @dfpalhano.
- Agents/fallback: classify internal live-session model switch conflicts as unknown fallback failures instead of provider overloads, preventing local vLLM endpoints from receiving misleading overloaded cooldowns. Refs #63229. Thanks @clawdia-lobster.
- Control UI: keep session-specific assistant identity loads authoritative after WebSocket connect, so non-main agent chat sessions do not show the main agent name in the header after bootstrap refreshes. Fixes #72776. Thanks @rockytian-top.
- Agents/Qwen: preserve exact custom `modelstudio` provider configs with foreign `api` owners so explicit OpenAI-compatible Model Studio endpoints no longer get normalized into the bundled Qwen plugin path. Fixes #64483. Thanks @FiredMosquito831.
- Media-understanding/audio: migrate deprecated `{input}` placeholders in legacy `audio.transcription.command` configs to `{{MediaPath}}`, so custom audio transcribers no longer receive the literal placeholder after doctor repair. Fixes #72760. Thanks @krisfanue3-hash.

View File

@@ -686,6 +686,7 @@ describe("runWithModelFallback", () => {
// Should NOT be a LiveSessionModelSwitchError — the outer retry loop must
// not restart with the conflicting model.
expect(err).not.toBeInstanceOf(LiveSessionModelSwitchError);
expect((err as { reason?: string }).reason).toBe("unknown");
expect(run).toHaveBeenCalledTimes(1);
});
@@ -774,6 +775,7 @@ describe("runWithModelFallback", () => {
expect(result.result).toBe("ok");
expect(result.provider).toBe("anthropic");
expect(result.model).toBe("claude-haiku-3-5");
expect(result.attempts[0]?.reason).toBe("unknown");
expect(run.mock.calls).toEqual([
["openai", "gpt-4.1-mini"],
["anthropic", "claude-haiku-3-5"],

View File

@@ -936,7 +936,8 @@ export async function runWithModelFallback<T>(params: {
// LiveSessionModelSwitchError during fallback may point at a later
// candidate that is already the active live-session selection. Jump
// there directly. Stale same/earlier targets remain a known failover
// so the outer runner cannot loop on the conflicting model.
// so the outer runner cannot loop on the conflicting model, but they
// are not provider overloads.
if (err instanceof LiveSessionModelSwitchError) {
const liveSwitchTargetIndex = findLiveSessionModelSwitchRedirectIndex({
error: err,
@@ -950,7 +951,7 @@ export async function runWithModelFallback<T>(params: {
const switchMsg = err.message;
const switchNormalized = new FailoverError(switchMsg, {
reason: "overloaded",
reason: "unknown",
provider: candidate.provider,
model: candidate.model,
});