fix: clamp web provider subsecond timeouts

This commit is contained in:
Peter Steinberger
2026-05-28 22:04:12 -04:00
parent 60392a1136
commit 0d189102f5
7 changed files with 22 additions and 23 deletions

View File

@@ -1,5 +1,6 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import { canResolveEnvSecretRefInReadOnlyPath } from "openclaw/plugin-sdk/extension-shared";
import { resolvePositiveTimeoutSeconds } from "openclaw/plugin-sdk/provider-web-fetch";
import { resolveSecretInputString, normalizeSecretInput } from "openclaw/plugin-sdk/secret-input";
export const DEFAULT_FIRECRAWL_BASE_URL = "https://api.firecrawl.dev";
@@ -225,23 +226,13 @@ export function resolveFirecrawlScrapeTimeoutSeconds(
cfg?: OpenClawConfig,
override?: number,
): number {
if (typeof override === "number" && Number.isFinite(override) && override > 0) {
return Math.floor(override);
}
const fetch = resolveFirecrawlFetchConfig(cfg);
if (
typeof fetch?.timeoutSeconds === "number" &&
Number.isFinite(fetch.timeoutSeconds) &&
fetch.timeoutSeconds > 0
) {
return Math.floor(fetch.timeoutSeconds);
}
return DEFAULT_FIRECRAWL_SCRAPE_TIMEOUT_SECONDS;
return resolvePositiveTimeoutSeconds(
override,
resolvePositiveTimeoutSeconds(fetch?.timeoutSeconds, DEFAULT_FIRECRAWL_SCRAPE_TIMEOUT_SECONDS),
);
}
export function resolveFirecrawlSearchTimeoutSeconds(override?: number): number {
if (typeof override === "number" && Number.isFinite(override) && override > 0) {
return Math.floor(override);
}
return DEFAULT_FIRECRAWL_SEARCH_TIMEOUT_SECONDS;
return resolvePositiveTimeoutSeconds(override, DEFAULT_FIRECRAWL_SEARCH_TIMEOUT_SECONDS);
}

View File

@@ -936,6 +936,9 @@ describe("firecrawl tools", () => {
expect(resolveFirecrawlScrapeTimeoutSeconds(cfg)).toBe(42);
expect(resolveFirecrawlScrapeTimeoutSeconds(cfg, 19.8)).toBe(19);
expect(resolveFirecrawlSearchTimeoutSeconds(9.7)).toBe(9);
expect(resolveFirecrawlScrapeTimeoutSeconds(cfg, 0.5)).toBe(1);
expect(resolveFirecrawlScrapeTimeoutSeconds(cfg, 0)).toBe(42);
expect(resolveFirecrawlSearchTimeoutSeconds(0.5)).toBe(1);
});
it("normalizes mixed search payload shapes into search items", () => {

View File

@@ -1,4 +1,5 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import { resolvePositiveTimeoutSeconds } from "openclaw/plugin-sdk/provider-web-search";
import {
normalizeResolvedSecretInputString,
normalizeSecretInput,
@@ -60,15 +61,9 @@ export function resolveTavilyBaseUrl(cfg?: OpenClawConfig): string {
}
export function resolveTavilySearchTimeoutSeconds(override?: number): number {
if (typeof override === "number" && Number.isFinite(override) && override > 0) {
return Math.floor(override);
}
return DEFAULT_TAVILY_SEARCH_TIMEOUT_SECONDS;
return resolvePositiveTimeoutSeconds(override, DEFAULT_TAVILY_SEARCH_TIMEOUT_SECONDS);
}
export function resolveTavilyExtractTimeoutSeconds(override?: number): number {
if (typeof override === "number" && Number.isFinite(override) && override > 0) {
return Math.floor(override);
}
return DEFAULT_TAVILY_EXTRACT_TIMEOUT_SECONDS;
return resolvePositiveTimeoutSeconds(override, DEFAULT_TAVILY_EXTRACT_TIMEOUT_SECONDS);
}

View File

@@ -400,6 +400,8 @@ describe("tavily tools", () => {
it("accepts positive numeric timeout overrides and floors them", () => {
expect(resolveTavilySearchTimeoutSeconds(19.9)).toBe(19);
expect(resolveTavilyExtractTimeoutSeconds(42.7)).toBe(42);
expect(resolveTavilySearchTimeoutSeconds(0.5)).toBe(1);
expect(resolveTavilyExtractTimeoutSeconds(0.5)).toBe(1);
expect(resolveTavilySearchTimeoutSeconds(0)).toBe(DEFAULT_TAVILY_SEARCH_TIMEOUT_SECONDS);
expect(resolveTavilyExtractTimeoutSeconds(Number.NaN)).toBe(
DEFAULT_TAVILY_EXTRACT_TIMEOUT_SECONDS,

View File

@@ -15,6 +15,12 @@ export function resolveTimeoutSeconds(value: unknown, fallback: number): number
return Math.max(1, Math.floor(parsed));
}
export function resolvePositiveTimeoutSeconds(value: unknown, fallback: number): number {
const parsed =
typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
return Math.max(1, Math.floor(parsed));
}
export function resolveCacheTtlMs(value: unknown, fallbackMinutes: number): number {
const minutes =
typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : fallbackMinutes;

View File

@@ -19,6 +19,7 @@ export {
readCache,
readResponseText,
resolveCacheTtlMs,
resolvePositiveTimeoutSeconds,
resolveTimeoutSeconds,
writeCache,
} from "../agents/tools/web-shared.js";

View File

@@ -62,6 +62,7 @@ export {
readCache,
readResponseText,
resolveCacheTtlMs,
resolvePositiveTimeoutSeconds,
resolveTimeoutSeconds,
writeCache,
} from "../agents/tools/web-shared.js";