Skip to content

Commit 01d9963

Browse files
committed
fix(models): default non-finite catalog browse timeout
1 parent c237de5 commit 01d9963

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

src/agents/model-catalog-browse.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { describe, expect, it, vi } from "vitest";
1+
import { afterEach, describe, expect, it, vi } from "vitest";
22
import type { OpenClawConfig } from "../config/types.openclaw.js";
33
import { loadModelCatalogForBrowse } from "./model-catalog-browse.js";
44
import type { ModelCatalogEntry } from "./model-catalog.types.js";
@@ -23,6 +23,10 @@ function config(params: { providerWildcard?: boolean } = {}): OpenClawConfig {
2323
}
2424

2525
describe("loadModelCatalogForBrowse", () => {
26+
afterEach(() => {
27+
vi.useRealTimers();
28+
});
29+
2630
it("uses the read-only catalog for default browse views", async () => {
2731
const loadCatalog = vi.fn(async ({ readOnly }: { readOnly: boolean }) =>
2832
readOnly ? readOnlyCatalog : fullCatalog,
@@ -79,4 +83,27 @@ describe("loadModelCatalogForBrowse", () => {
7983
expect(onTimeout).toHaveBeenCalledExactlyOnceWith(5);
8084
await new Promise((resolve) => setTimeout(resolve, 15));
8185
});
86+
87+
it("uses the default timeout when timeoutMs is non-finite", async () => {
88+
vi.useFakeTimers();
89+
const onTimeout = vi.fn();
90+
const loadCatalog = vi.fn(
91+
() =>
92+
new Promise<ModelCatalogEntry[]>((resolve) => {
93+
setTimeout(() => resolve(readOnlyCatalog), 5);
94+
}),
95+
);
96+
97+
const resultPromise = loadModelCatalogForBrowse({
98+
cfg: config(),
99+
loadCatalog,
100+
timeoutMs: Number.NaN,
101+
onTimeout,
102+
});
103+
104+
await vi.advanceTimersByTimeAsync(5);
105+
106+
await expect(resultPromise).resolves.toBe(readOnlyCatalog);
107+
expect(onTimeout).not.toHaveBeenCalled();
108+
});
82109
});

src/agents/model-catalog-browse.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import type { OpenClawConfig } from "../config/types.openclaw.js";
2+
import { parseFiniteNumber } from "../shared/number-coercion.js";
23
import type { ModelCatalogEntry } from "./model-catalog.types.js";
34
import { parseConfiguredModelVisibilityEntries } from "./model-selection-shared.js";
45

56
export const DEFAULT_MODEL_CATALOG_BROWSE_TIMEOUT_MS = 750;
67

78
export type ModelCatalogBrowseView = "default" | "configured" | "all";
89

10+
function resolveModelCatalogBrowseTimeoutMs(value: number | undefined): number {
11+
return Math.max(
12+
1,
13+
Math.floor(parseFiniteNumber(value) ?? DEFAULT_MODEL_CATALOG_BROWSE_TIMEOUT_MS),
14+
);
15+
}
16+
917
export async function loadModelCatalogForBrowse(params: {
1018
cfg: OpenClawConfig;
1119
view?: ModelCatalogBrowseView;
@@ -22,7 +30,7 @@ export async function loadModelCatalogForBrowse(params: {
2230
}
2331

2432
let timeout: NodeJS.Timeout | undefined;
25-
const timeoutMs = params.timeoutMs ?? DEFAULT_MODEL_CATALOG_BROWSE_TIMEOUT_MS;
33+
const timeoutMs = resolveModelCatalogBrowseTimeoutMs(params.timeoutMs);
2634
const timedOut = Symbol("model-catalog-browse-timeout");
2735
const catalogPromise = params.loadCatalog({ readOnly: true });
2836
const timeoutPromise = new Promise<typeof timedOut>((resolve) => {

0 commit comments

Comments
 (0)