fix: validate web fetch max chars

This commit is contained in:
Peter Steinberger
2026-05-28 19:06:35 -04:00
parent 3029326a56
commit 44dc29f397
2 changed files with 20 additions and 3 deletions

View File

@@ -15,7 +15,7 @@ import { extractReadableContent } from "../../web-fetch/content-extractors.runti
import { resolveWebProviderConfig } from "../../web/provider-runtime-shared.js";
import { stringEnum } from "../schema/string-enum.js";
import type { AnyAgentTool } from "./common.js";
import { jsonResult, readNumberParam, readStringParam } from "./common.js";
import { jsonResult, readPositiveIntegerParam, readStringParam } from "./common.js";
import {
extractBasicHtmlContent,
htmlToMarkdown,
@@ -59,7 +59,7 @@ const WebFetchSchema = Type.Object({
}),
),
maxChars: Type.Optional(
Type.Number({
Type.Integer({
description: "Max chars returned; truncates.",
minimum: 100,
}),
@@ -674,7 +674,7 @@ export function createWebFetchTool(options?: {
const params = args as Record<string, unknown>;
const url = readStringParam(params, "url", { required: true });
const extractMode = readStringParam(params, "extractMode") === "text" ? "text" : "markdown";
const maxChars = readNumberParam(params, "maxChars", { integer: true });
const maxChars = readPositiveIntegerParam(params, "maxChars");
const maxCharsCap = resolveFetchMaxCharsCap(executionFetch);
const result = await runWebFetch({
url,

View File

@@ -534,6 +534,23 @@ describe("web_fetch extraction fallbacks", () => {
expect(details.truncated).toBe(true);
});
it("rejects fractional maxChars before fetching", async () => {
const fetchMock = installMockFetch(
(input: RequestInfo | URL) =>
Promise.resolve(textResponse("unused", resolveRequestUrl(input))) as Promise<Response>,
);
const tool = createFetchTool({ firecrawl: { enabled: false } });
await expect(
tool?.execute?.("call", {
url: "https://example.com/fractional",
maxChars: 100.5,
}),
).rejects.toThrow("maxChars must be a positive integer");
expect(fetchMock).not.toHaveBeenCalled();
});
it("strips and truncates HTML from error responses", async () => {
const long = "x".repeat(12_000);
const html =