






















@@ -19,6 +19,20 @@ const resolveModelMock = vi.fn<
1919api: "openai-codex-responses",
2020},
2121}));
22+const resolveModelAsyncMock = vi.fn<
23+(
24+provider: unknown,
25+modelId: unknown,
26+agentDir: unknown,
27+cfg: unknown,
28+) => Promise<{ model?: { id: string; provider: string; api: string }; error?: string }>
29+>(async () => ({
30+model: {
31+id: "gpt-5.4",
32+provider: "openai-codex",
33+api: "openai-codex-responses",
34+},
35+}));
2236const selectAgentHarnessMock = vi.fn((_params: unknown) => ({ id: "pi" }));
2337const resolveEmbeddedAgentRuntimeMock = vi.fn(() => "auto");
2438@@ -43,6 +57,8 @@ vi.mock("../agents/pi-embedded-runner/model.js", () => ({
4357cfg: unknown,
4458options?: unknown,
4559) => resolveModelMock(provider, modelId, agentDir, cfg, options),
60+resolveModelAsync: (provider: unknown, modelId: unknown, agentDir: unknown, cfg: unknown) =>
61+resolveModelAsyncMock(provider, modelId, agentDir, cfg),
4662}));
47634864vi.mock("../agents/pi-embedded-runner/runtime.js", () => ({
@@ -61,6 +77,7 @@ describe("gateway startup primary model warmup", () => {
6177beforeEach(() => {
6278ensureOpenClawModelsJsonMock.mockClear();
6379resolveModelMock.mockClear();
80+resolveModelAsyncMock.mockClear();
6481selectAgentHarnessMock.mockClear();
6582selectAgentHarnessMock.mockReturnValue({ id: "pi" });
6683resolveEmbeddedAgentRuntimeMock.mockClear();
@@ -194,4 +211,53 @@ describe("gateway startup primary model warmup", () => {
194211expect(ensureOpenClawModelsJsonMock).toHaveBeenCalledWith(cfg, "/tmp/agent");
195212expect(resolveModelMock).toHaveBeenCalled();
196213});
214+215+it("falls back to async model resolution before warning", async () => {
216+resolveModelMock.mockReturnValueOnce({ model: undefined } as never);
217+resolveModelAsyncMock.mockResolvedValueOnce({
218+model: {
219+id: "gpt-5.4",
220+provider: "codex",
221+api: "openai-codex-responses",
222+},
223+});
224+const warn = vi.fn();
225+const cfg = {
226+agents: {
227+defaults: {
228+model: {
229+primary: "codex/gpt-5.4",
230+},
231+},
232+},
233+} as OpenClawConfig;
234+235+await prewarmConfiguredPrimaryModel({ cfg, log: { warn } });
236+237+expect(resolveModelAsyncMock).toHaveBeenCalledWith("codex", "gpt-5.4", "/tmp/agent", cfg);
238+expect(warn).not.toHaveBeenCalled();
239+});
240+241+it("warns only when both static and async model resolution miss", async () => {
242+resolveModelMock.mockReturnValueOnce({ model: undefined, error: "static miss" } as never);
243+resolveModelAsyncMock.mockResolvedValueOnce({ error: "async miss" });
244+const warn = vi.fn();
245+246+await prewarmConfiguredPrimaryModel({
247+cfg: {
248+agents: {
249+defaults: {
250+model: {
251+primary: "codex/gpt-5.4",
252+},
253+},
254+},
255+} as OpenClawConfig,
256+log: { warn },
257+});
258+259+expect(warn).toHaveBeenCalledWith(
260+expect.stringContaining("startup model warmup failed for codex/gpt-5.4"),
261+);
262+});
197263});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。