fix(agents): cap model scan timeouts

This commit is contained in:
Peter Steinberger
2026-05-29 16:42:56 -04:00
parent 0b86decf94
commit b7e9272dbe
2 changed files with 25 additions and 2 deletions
+23 -1
View File
@@ -1,8 +1,10 @@
import { describe, expect, it } from "vitest";
import { afterEach, describe, expect, it, vi } from "vitest";
import { withEnvAsync } from "../test-utils/env.js";
import { withFetchPreconnect } from "../test-utils/fetch-mock.js";
import { scanOpenRouterModels } from "./model-scan.js";
const MAX_TIMER_TIMEOUT_MS = 2_147_000_000;
function createFetchFixture(payload: unknown): typeof fetch {
return withFetchPreconnect(
async () =>
@@ -14,6 +16,10 @@ function createFetchFixture(payload: unknown): typeof fetch {
}
describe("scanOpenRouterModels", () => {
afterEach(() => {
vi.restoreAllMocks();
});
it("lists free models without probing", async () => {
const fetchImpl = createFetchFixture({
data: [
@@ -102,6 +108,22 @@ describe("scanOpenRouterModels", () => {
).rejects.toThrow(/catalog aborted/);
});
it("caps oversized scan timeouts before scheduling catalog aborts", async () => {
const timeoutSpy = vi
.spyOn(globalThis, "setTimeout")
.mockReturnValue(1 as unknown as ReturnType<typeof setTimeout>);
vi.spyOn(globalThis, "clearTimeout").mockImplementation(() => undefined);
const fetchImpl = createFetchFixture({ data: [] });
await scanOpenRouterModels({
fetchImpl,
probe: false,
timeoutMs: MAX_TIMER_TIMEOUT_MS + 1_000_000,
});
expect(timeoutSpy).toHaveBeenCalledWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS);
});
it("does not match provider filters across provider id variants", async () => {
const fetchImpl = createFetchFixture({
data: [
+2 -1
View File
@@ -5,6 +5,7 @@ import type { OpenAICompletionsOptions } from "../llm/providers/openai-completio
import { complete } from "../llm/stream.js";
import { type Context, type Model, type Tool } from "../llm/types.js";
import { inferParamBFromIdOrName } from "../shared/model-param-b.js";
import { resolveTimerTimeoutMs } from "../shared/number-coercion.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
@@ -413,7 +414,7 @@ export async function scanOpenRouterModels(
);
}
const timeoutMs = Math.max(1, Math.floor(options.timeoutMs ?? DEFAULT_TIMEOUT_MS));
const timeoutMs = resolveTimerTimeoutMs(options.timeoutMs, DEFAULT_TIMEOUT_MS);
const concurrency = Math.max(1, Math.floor(options.concurrency ?? DEFAULT_CONCURRENCY));
const minParamB = Math.max(0, Math.floor(options.minParamB ?? 0));
const maxAgeDays = Math.max(0, Math.floor(options.maxAgeDays ?? 0));