mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix: validate firecrawl numeric options
This commit is contained in:
@@ -15,7 +15,7 @@ const FirecrawlScrapeToolSchema = Type.Object(
|
||||
description: 'Extraction mode ("markdown" or "text"). Default: markdown.',
|
||||
}),
|
||||
maxChars: Type.Optional(
|
||||
Type.Number({
|
||||
Type.Integer({
|
||||
description: "Maximum characters to return.",
|
||||
minimum: 100,
|
||||
}),
|
||||
@@ -26,7 +26,7 @@ const FirecrawlScrapeToolSchema = Type.Object(
|
||||
}),
|
||||
),
|
||||
maxAgeMs: Type.Optional(
|
||||
Type.Number({
|
||||
Type.Integer({
|
||||
description: "Maximum Firecrawl cache age in milliseconds.",
|
||||
minimum: 0,
|
||||
}),
|
||||
@@ -40,7 +40,7 @@ const FirecrawlScrapeToolSchema = Type.Object(
|
||||
}),
|
||||
),
|
||||
timeoutSeconds: Type.Optional(
|
||||
Type.Number({
|
||||
Type.Integer({
|
||||
description: "Timeout in seconds for the Firecrawl scrape request.",
|
||||
minimum: 1,
|
||||
}),
|
||||
@@ -60,10 +60,10 @@ export function createFirecrawlScrapeTool(api: OpenClawPluginApi) {
|
||||
const url = readStringParam(rawParams, "url", { required: true });
|
||||
const extractMode =
|
||||
readStringParam(rawParams, "extractMode") === "text" ? "text" : "markdown";
|
||||
const maxChars = readNumberParam(rawParams, "maxChars", { integer: true });
|
||||
const maxAgeMs = readNumberParam(rawParams, "maxAgeMs", { integer: true });
|
||||
const maxChars = readNumberParam(rawParams, "maxChars", { positiveInteger: true });
|
||||
const maxAgeMs = readNumberParam(rawParams, "maxAgeMs", { nonNegativeInteger: true });
|
||||
const timeoutSeconds = readNumberParam(rawParams, "timeoutSeconds", {
|
||||
integer: true,
|
||||
positiveInteger: true,
|
||||
});
|
||||
const proxyRaw = readStringParam(rawParams, "proxy");
|
||||
const proxy =
|
||||
|
||||
@@ -12,7 +12,7 @@ const FirecrawlSearchToolSchema = Type.Object(
|
||||
{
|
||||
query: Type.String({ description: "Search query string." }),
|
||||
count: Type.Optional(
|
||||
Type.Number({
|
||||
Type.Integer({
|
||||
description: "Number of results to return (1-10).",
|
||||
minimum: 1,
|
||||
maximum: 10,
|
||||
@@ -34,7 +34,7 @@ const FirecrawlSearchToolSchema = Type.Object(
|
||||
}),
|
||||
),
|
||||
timeoutSeconds: Type.Optional(
|
||||
Type.Number({
|
||||
Type.Integer({
|
||||
description: "Timeout in seconds for the Firecrawl Search request.",
|
||||
minimum: 1,
|
||||
}),
|
||||
@@ -52,9 +52,9 @@ export function createFirecrawlSearchTool(api: OpenClawPluginApi) {
|
||||
parameters: FirecrawlSearchToolSchema,
|
||||
execute: async (_toolCallId: string, rawParams: Record<string, unknown>) => {
|
||||
const query = readStringParam(rawParams, "query", { required: true });
|
||||
const count = readNumberParam(rawParams, "count", { integer: true });
|
||||
const count = readNumberParam(rawParams, "count", { positiveInteger: true });
|
||||
const timeoutSeconds = readNumberParam(rawParams, "timeoutSeconds", {
|
||||
integer: true,
|
||||
positiveInteger: true,
|
||||
});
|
||||
const sources = readStringArrayParam(rawParams, "sources");
|
||||
const categories = readStringArrayParam(rawParams, "categories");
|
||||
|
||||
@@ -489,6 +489,49 @@ describe("firecrawl tools", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("drops malformed numeric Firecrawl tool options", async () => {
|
||||
const searchTool = createFirecrawlSearchTool({
|
||||
config: { env: "test" },
|
||||
} as never);
|
||||
await searchTool.execute("call-search", {
|
||||
query: "web search",
|
||||
count: 6.5,
|
||||
timeoutSeconds: Number.POSITIVE_INFINITY,
|
||||
});
|
||||
|
||||
expect(runFirecrawlSearch).toHaveBeenLastCalledWith({
|
||||
cfg: { env: "test" },
|
||||
query: "web search",
|
||||
count: undefined,
|
||||
timeoutSeconds: undefined,
|
||||
sources: undefined,
|
||||
categories: undefined,
|
||||
scrapeResults: false,
|
||||
});
|
||||
|
||||
const scrapeTool = createFirecrawlScrapeTool({
|
||||
config: { env: "test" },
|
||||
} as never);
|
||||
await scrapeTool.execute("call-scrape", {
|
||||
url: "https://docs.openclaw.ai",
|
||||
maxChars: 1500.5,
|
||||
maxAgeMs: -1,
|
||||
timeoutSeconds: 22.5,
|
||||
});
|
||||
|
||||
expect(runFirecrawlScrape).toHaveBeenLastCalledWith({
|
||||
cfg: { env: "test" },
|
||||
url: "https://docs.openclaw.ai",
|
||||
extractMode: "markdown",
|
||||
maxChars: undefined,
|
||||
onlyMainContent: undefined,
|
||||
maxAgeMs: undefined,
|
||||
proxy: undefined,
|
||||
storeInCache: undefined,
|
||||
timeoutSeconds: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("passes text mode through and ignores invalid proxy values", async () => {
|
||||
const tool = createFirecrawlScrapeTool({
|
||||
config: { env: "test" },
|
||||
|
||||
@@ -74,6 +74,22 @@ describe("readNumberParam", () => {
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("accepts only nonnegative safe integers when nonNegativeInteger is true", () => {
|
||||
expect(readNumberParam({ cacheAge: 0 }, "cacheAge", { nonNegativeInteger: true })).toBe(0);
|
||||
expect(readNumberParam({ cacheAge: "42" }, "cacheAge", { nonNegativeInteger: true })).toBe(42);
|
||||
expect(
|
||||
readNumberParam({ cacheAge: "42.9" }, "cacheAge", { nonNegativeInteger: true }),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
readNumberParam({ cacheAge: -1 }, "cacheAge", { nonNegativeInteger: true }),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
readNumberParam({ cacheAge: Number.POSITIVE_INFINITY }, "cacheAge", {
|
||||
nonNegativeInteger: true,
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("snake_case aliases", () => {
|
||||
|
||||
@@ -163,6 +163,7 @@ export function readNumberParam(
|
||||
integer?: boolean;
|
||||
strict?: boolean;
|
||||
positiveInteger?: boolean;
|
||||
nonNegativeInteger?: boolean;
|
||||
} = {},
|
||||
): number | undefined {
|
||||
const {
|
||||
@@ -171,6 +172,7 @@ export function readNumberParam(
|
||||
integer = false,
|
||||
strict = false,
|
||||
positiveInteger = false,
|
||||
nonNegativeInteger = false,
|
||||
} = options;
|
||||
const raw = readParamRaw(params, key);
|
||||
let value: number | undefined;
|
||||
@@ -194,6 +196,9 @@ export function readNumberParam(
|
||||
if (positiveInteger) {
|
||||
return Number.isSafeInteger(value) && value > 0 ? value : undefined;
|
||||
}
|
||||
if (nonNegativeInteger) {
|
||||
return Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
||||
}
|
||||
return integer ? Math.trunc(value) : value;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user