惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
博客园_首页
博客园 - 三生石上(FineUI控件)
V
Visual Studio Blog
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
小众软件
小众软件
T
Tailwind CSS Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
月光博客
月光博客
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
罗磊的独立博客
V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell
IT之家
IT之家
量子位
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Announcements
Recent Announcements
M
MIT News - Artificial intelligence
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix: keep auto model fallbacks pinned until reset · openc...
steipete · 2026-04-27 · via Recent Commits to openclaw:main

@@ -15,15 +15,11 @@ const state = vi.hoisted(() => ({

1515

registerAgentRunContextMock: vi.fn(),

1616

clearAgentRunContextMock: vi.fn(),

1717

updateSessionStoreAfterAgentRunMock: vi.fn(),

18-

updateSessionStoreFileMock: vi.fn(),

1918

deliverAgentCommandResultMock: vi.fn(),

2019

clearSessionAuthProfileOverrideMock: vi.fn(),

21-

applyModelOverrideToSessionEntryMock: vi.fn((..._args: unknown[]) => ({ updated: false })),

2220

authProfileStoreMock: { profiles: {} } as { profiles: Record<string, unknown> },

2321

sessionEntryMock: undefined as unknown,

2422

sessionStoreMock: undefined as unknown,

25-

sessionStorePathMock: undefined as string | undefined,

26-

persistedSessionStoreMock: undefined as Record<string, unknown> | undefined,

2723

}));

28242925

vi.mock("./model-fallback.js", () => ({

@@ -77,7 +73,7 @@ vi.mock("./command/session.js", () => ({

7773

skillsSnapshot: { prompt: "", skills: [], version: 0 },

7874

},

7975

sessionStore: state.sessionStoreMock,

80-

storePath: state.sessionStorePathMock,

76+

storePath: undefined,

8177

isNewSession: false,

8278

persistedThinking: undefined,

8379

persistedVerbose: undefined,

@@ -181,10 +177,6 @@ vi.mock("../config/sessions.js", () => ({

181177

),

182178

}));

183179184-

vi.mock("../config/sessions/store.js", () => ({

185-

updateSessionStore: (...args: unknown[]) => state.updateSessionStoreFileMock(...args),

186-

}));

187-188180

vi.mock("../config/sessions/transcript-resolve.runtime.js", () => ({

189181

resolveSessionTranscriptFile: async () => ({

190182

sessionFile: "/tmp/session.jsonl",

@@ -239,8 +231,7 @@ vi.mock("../sessions/level-overrides.js", () => ({

239231

}));

240232241233

vi.mock("../sessions/model-overrides.js", () => ({

242-

applyModelOverrideToSessionEntry: (...args: unknown[]) =>

243-

state.applyModelOverrideToSessionEntryMock(...args),

234+

applyModelOverrideToSessionEntry: () => ({ updated: false }),

244235

}));

245236246237

vi.mock("../sessions/send-policy.js", () => ({

@@ -409,38 +400,6 @@ function expectFallbackOverrideCalls(first: boolean, second: boolean) {

409400

});

410401

}

411402412-

function useRealisticDefaultModelOverrideReset() {

413-

state.applyModelOverrideToSessionEntryMock.mockImplementation((params: unknown) => {

414-

const { entry, selection } = params as {

415-

entry: {

416-

providerOverride?: string;

417-

modelOverride?: string;

418-

modelOverrideSource?: string;

419-

authProfileOverride?: string;

420-

authProfileOverrideSource?: string;

421-

};

422-

selection: { isDefault?: boolean };

423-

};

424-

if (!selection.isDefault) {

425-

return { updated: false };

426-

}

427-

const before = { ...entry };

428-

delete entry.providerOverride;

429-

delete entry.modelOverride;

430-

delete entry.modelOverrideSource;

431-

delete entry.authProfileOverride;

432-

delete entry.authProfileOverrideSource;

433-

return {

434-

updated:

435-

before.providerOverride !== entry.providerOverride ||

436-

before.modelOverride !== entry.modelOverride ||

437-

before.modelOverrideSource !== entry.modelOverrideSource ||

438-

before.authProfileOverride !== entry.authProfileOverride ||

439-

before.authProfileOverrideSource !== entry.authProfileOverrideSource,

440-

};

441-

});

442-

}

443-444403

describe("agentCommand – LiveSessionModelSwitchError retry", () => {

445404

beforeEach(() => {

446405

vi.clearAllMocks();

@@ -471,13 +430,6 @@ describe("agentCommand – LiveSessionModelSwitchError retry", () => {

471430

state.authProfileStoreMock = { profiles: {} };

472431

state.sessionEntryMock = undefined;

473432

state.sessionStoreMock = undefined;

474-

state.sessionStorePathMock = undefined;

475-

state.persistedSessionStoreMock = undefined;

476-

state.applyModelOverrideToSessionEntryMock.mockReturnValue({ updated: false });

477-

state.updateSessionStoreFileMock.mockImplementation(

478-

async (_path: string, fn: (store: Record<string, unknown>) => unknown) =>

479-

fn(state.persistedSessionStoreMock ?? {}),

480-

);

481433

state.deliverAgentCommandResultMock.mockResolvedValue(undefined);

482434

state.updateSessionStoreAfterAgentRunMock.mockResolvedValue(undefined);

483435

});

@@ -690,64 +642,4 @@ describe("agentCommand – LiveSessionModelSwitchError retry", () => {

690642691643

expectFallbackOverrideCalls(false, true);

692644

});

693-694-

it("clears auto-fallback model overrides before the next command retries primary", async () => {

695-

useRealisticDefaultModelOverrideReset();

696-697-

const sessionEntry = {

698-

sessionId: "session-1",

699-

updatedAt: Date.now(),

700-

providerOverride: "openai",

701-

modelOverride: "gpt-5.4",

702-

modelOverrideSource: "auto",

703-

authProfileOverride: "openai:default",

704-

authProfileOverrideSource: "auto",

705-

skillsSnapshot: { prompt: "", skills: [], version: 0 },

706-

};

707-

state.sessionEntryMock = sessionEntry;

708-

state.sessionStoreMock = { "agent:main": sessionEntry };

709-

state.sessionStorePathMock = "/tmp/sessions.json";

710-

state.persistedSessionStoreMock = { "agent:main": { ...sessionEntry } };

711-

state.runWithModelFallbackMock.mockImplementation(async (params: FallbackRunnerParams) => {

712-

const result = await params.run(params.provider, params.model);

713-

return {

714-

result,

715-

provider: params.provider,

716-

model: params.model,

717-

attempts: [],

718-

};

719-

});

720-

state.runAgentAttemptMock.mockResolvedValue(makeSuccessResult("anthropic", "claude"));

721-722-

await agentCommand({

723-

message: "hello",

724-

sessionKey: "agent:main",

725-

senderIsOwner: true,

726-

});

727-728-

const fallbackParams = state.runWithModelFallbackMock.mock.calls[0]?.[0] as

729-

| FallbackRunnerParams

730-

| undefined;

731-

expect(fallbackParams).toMatchObject({

732-

provider: "anthropic",

733-

model: "claude",

734-

});

735-

expect(state.resolveEffectiveModelFallbacksMock).toHaveBeenCalledWith(

736-

expect.objectContaining({ hasSessionModelOverride: false }),

737-

);

738-

const activeStore = state.sessionStoreMock as Record<string, typeof sessionEntry>;

739-

const persistedStore = state.persistedSessionStoreMock as Record<string, typeof sessionEntry>;

740-

expect(activeStore["agent:main"]).toMatchObject({

741-

sessionId: "session-1",

742-

});

743-

expect(activeStore["agent:main"].providerOverride).toBeUndefined();

744-

expect(activeStore["agent:main"].modelOverride).toBeUndefined();

745-

expect(activeStore["agent:main"].modelOverrideSource).toBeUndefined();

746-

expect(persistedStore["agent:main"]).toMatchObject({

747-

sessionId: "session-1",

748-

});

749-

expect(persistedStore["agent:main"].providerOverride).toBeUndefined();

750-

expect(persistedStore["agent:main"].modelOverride).toBeUndefined();

751-

expect(persistedStore["agent:main"].modelOverrideSource).toBeUndefined();

752-

});

753645

});