Skip to content

Commit 4e68684

Browse files
fix: restore web fetch firecrawl config in runtime zod schema (openclaw#42583)
Merged via squash. Prepared head SHA: e37f965 Co-authored-by: stim64045-spec <[email protected]> Co-authored-by: altaywtf <[email protected]> Reviewed-by: @altaywtf
1 parent 45721d5 commit 4e68684

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai
2121
- Agents/Azure OpenAI startup prompts: rephrase the built-in `/new`, `/reset`, and post-compaction startup instruction so Azure OpenAI deployments no longer hit HTTP 400 false positives from the content filter. (#43403) Thanks @xingsy97.
2222
- Config/validation: accept documented `agents.list[].params` per-agent overrides in strict config validation so `openclaw config validate` no longer rejects runtime-supported `cacheRetention`, `temperature`, and `maxTokens` settings. (#41171) Thanks @atian8179.
2323
- Android/onboarding QR scan: switch setup QR scanning to Google Code Scanner so onboarding uses a more reliable scanner instead of the legacy embedded ZXing flow. (#45021) Thanks @obviyus.
24+
- Config/web fetch: restore runtime validation for documented `tools.web.fetch.readability` and `tools.web.fetch.firecrawl` settings so valid web fetch configs no longer fail with unrecognized-key errors. (#42583) Thanks @stim64045-spec.
2425

2526
## 2026.3.12
2627

src/config/schema.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { beforeAll, describe, expect, it } from "vitest";
22
import { buildConfigSchema, lookupConfigSchema } from "./schema.js";
33
import { applyDerivedTags, CONFIG_TAGS, deriveTagsForPath } from "./schema.tags.js";
4+
import { ToolsSchema } from "./zod-schema.agent-runtime.js";
45

56
describe("config schema", () => {
67
type SchemaInput = NonNullable<Parameters<typeof buildConfigSchema>[0]>;
@@ -200,6 +201,51 @@ describe("config schema", () => {
200201
expect(tags).toContain("performance");
201202
});
202203

204+
it("accepts web fetch readability and firecrawl config in the runtime zod schema", () => {
205+
const parsed = ToolsSchema.parse({
206+
web: {
207+
fetch: {
208+
readability: true,
209+
firecrawl: {
210+
enabled: true,
211+
apiKey: "firecrawl-test-key",
212+
baseUrl: "https://api.firecrawl.dev",
213+
onlyMainContent: true,
214+
maxAgeMs: 60_000,
215+
timeoutSeconds: 15,
216+
},
217+
},
218+
},
219+
});
220+
221+
expect(parsed?.web?.fetch?.readability).toBe(true);
222+
expect(parsed?.web?.fetch).toMatchObject({
223+
firecrawl: {
224+
enabled: true,
225+
apiKey: "firecrawl-test-key",
226+
baseUrl: "https://api.firecrawl.dev",
227+
onlyMainContent: true,
228+
maxAgeMs: 60_000,
229+
timeoutSeconds: 15,
230+
},
231+
});
232+
});
233+
234+
it("rejects unknown keys inside web fetch firecrawl config", () => {
235+
expect(() =>
236+
ToolsSchema.parse({
237+
web: {
238+
fetch: {
239+
firecrawl: {
240+
enabled: true,
241+
nope: true,
242+
},
243+
},
244+
},
245+
}),
246+
).toThrow();
247+
});
248+
203249
it("keeps tags in the allowed taxonomy", () => {
204250
const withTags = applyDerivedTags({
205251
"gateway.auth.token": {},

src/config/zod-schema.agent-runtime.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,18 @@ export const ToolsWebFetchSchema = z
327327
cacheTtlMinutes: z.number().nonnegative().optional(),
328328
maxRedirects: z.number().int().nonnegative().optional(),
329329
userAgent: z.string().optional(),
330+
readability: z.boolean().optional(),
331+
firecrawl: z
332+
.object({
333+
enabled: z.boolean().optional(),
334+
apiKey: SecretInputSchema.optional().register(sensitive),
335+
baseUrl: z.string().optional(),
336+
onlyMainContent: z.boolean().optional(),
337+
maxAgeMs: z.number().int().nonnegative().optional(),
338+
timeoutSeconds: z.number().int().positive().optional(),
339+
})
340+
.strict()
341+
.optional(),
330342
})
331343
.strict()
332344
.optional();

0 commit comments

Comments
 (0)