@openclaw/firecrawl-plugin 2026.7.1 → 2026.7.2-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as runFirecrawlScrape } from "./firecrawl-client-xZqyVUBg.js";
1
+ import { n as runFirecrawlScrape } from "./firecrawl-client-CPw_AuJR.js";
2
2
  import { readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  //#region extensions/firecrawl/api.ts
4
4
  async function fetchFirecrawlContent(params) {
@@ -3,6 +3,8 @@ import { DEFAULT_CACHE_TTL_MINUTES, markdownToText, normalizeCacheKey, readCache
3
3
  import { normalizeSecretInput, resolveSecretInputString } from "openclaw/plugin-sdk/secret-input";
4
4
  import { wrapExternalContent, wrapWebContent } from "openclaw/plugin-sdk/security-runtime";
5
5
  import { SsrFBlockedError, isBlockedHostnameOrIp, isPrivateIpAddress, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
6
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
+ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
6
8
  import { canResolveEnvSecretRefInReadOnlyPath } from "openclaw/plugin-sdk/extension-shared";
7
9
  //#region \0rolldown/runtime.js
8
10
  var __defProp = Object.defineProperty;
@@ -15,6 +17,8 @@ var __exportAll = (all, no_symbols) => {
15
17
  if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
16
18
  return target;
17
19
  };
20
+ const DEFAULT_FIRECRAWL_SEARCH_TIMEOUT_SECONDS = 30;
21
+ const DEFAULT_FIRECRAWL_SCRAPE_TIMEOUT_SECONDS = 60;
18
22
  const DEFAULT_FIRECRAWL_MAX_AGE_MS = 1728e5;
19
23
  const FIRECRAWL_API_KEY_ENV_VAR = "FIRECRAWL_API_KEY";
20
24
  function resolveSearchConfig(cfg) {
@@ -123,10 +127,10 @@ function resolveFirecrawlMaxAgeMs(cfg, override) {
123
127
  return DEFAULT_FIRECRAWL_MAX_AGE_MS;
124
128
  }
125
129
  function resolveFirecrawlScrapeTimeoutSeconds(cfg, override) {
126
- return resolvePositiveTimeoutSeconds(override, resolvePositiveTimeoutSeconds(resolveFirecrawlFetchConfig(cfg)?.timeoutSeconds, 60));
130
+ return resolvePositiveTimeoutSeconds(override, resolvePositiveTimeoutSeconds(resolveFirecrawlFetchConfig(cfg)?.timeoutSeconds, DEFAULT_FIRECRAWL_SCRAPE_TIMEOUT_SECONDS));
127
131
  }
128
132
  function resolveFirecrawlSearchTimeoutSeconds(override) {
129
- return resolvePositiveTimeoutSeconds(override, 30);
133
+ return resolvePositiveTimeoutSeconds(override, DEFAULT_FIRECRAWL_SEARCH_TIMEOUT_SECONDS);
130
134
  }
131
135
  //#endregion
132
136
  //#region extensions/firecrawl/src/firecrawl-client.ts
@@ -232,7 +236,7 @@ async function postFirecrawlJson(params, parse) {
232
236
  const errorBody = await readResponseText(response, { maxBytes: 64e3 });
233
237
  if (errorBody.text) detail = errorBody.text;
234
238
  }
235
- const safeDetail = wrapWebContent(detail.slice(0, 1e3), "web_fetch");
239
+ const safeDetail = wrapWebContent(truncateUtf16Safe(detail, 1e3), "web_fetch");
236
240
  throw new Error(`${params.errorLabel} API error (${response.status}): ${safeDetail}`);
237
241
  }
238
242
  return await parse(response);
@@ -300,21 +304,35 @@ function buildSearchPayload(params) {
300
304
  };
301
305
  }
302
306
  async function runFirecrawlSearch(params) {
303
- const apiKey = resolveFirecrawlApiKey(params.cfg);
304
- if (!apiKey) throw new Error("web_search (firecrawl) needs a Firecrawl API key. Set FIRECRAWL_API_KEY in the Gateway environment, or configure plugins.entries.firecrawl.config.webSearch.apiKey.");
305
- const count = typeof params.count === "number" && Number.isFinite(params.count) ? Math.max(1, Math.min(10, Math.floor(params.count))) : DEFAULT_SEARCH_COUNT;
307
+ const keyless = params.access === "keyless";
308
+ const providerId = keyless ? "firecrawl-free" : "firecrawl";
309
+ const apiKey = keyless ? void 0 : resolveFirecrawlApiKey(params.cfg);
310
+ if (!apiKey && !keyless) throw new Error("web_search (firecrawl) needs a Firecrawl API key. Set FIRECRAWL_API_KEY in the Gateway environment, or configure plugins.entries.firecrawl.config.webSearch.apiKey.");
311
+ const count = typeof params.count === "number" && Number.isFinite(params.count) ? Math.max(1, Math.min(100, Math.floor(params.count))) : DEFAULT_SEARCH_COUNT;
306
312
  const timeoutSeconds = resolveFirecrawlSearchTimeoutSeconds(params.timeoutSeconds);
307
313
  const scrapeResults = params.scrapeResults === true;
308
314
  const sources = Array.isArray(params.sources) ? params.sources.filter(Boolean) : [];
309
315
  const categories = Array.isArray(params.categories) ? params.categories.filter(Boolean) : [];
316
+ const includeDomains = Array.isArray(params.includeDomains) ? params.includeDomains.filter(Boolean) : [];
317
+ const excludeDomains = Array.isArray(params.excludeDomains) ? params.excludeDomains.filter(Boolean) : [];
318
+ if (includeDomains.length > 0 && excludeDomains.length > 0) throw new Error("Firecrawl search accepts includeDomains or excludeDomains, not both.");
319
+ const tbs = normalizeOptionalString(params.tbs);
320
+ const location = normalizeOptionalString(params.location);
321
+ const country = normalizeOptionalString(params.country);
310
322
  const baseUrl = resolveFirecrawlBaseUrl(params.cfg);
311
323
  const cacheKey = normalizeCacheKey(JSON.stringify({
312
324
  type: "firecrawl-search",
325
+ provider: providerId,
313
326
  q: params.query,
314
327
  count,
315
328
  baseUrl,
316
329
  sources,
317
330
  categories,
331
+ includeDomains,
332
+ excludeDomains,
333
+ tbs,
334
+ location,
335
+ country,
318
336
  scrapeResults
319
337
  }));
320
338
  const cached = readCache(SEARCH_CACHE, cacheKey);
@@ -328,6 +346,11 @@ async function runFirecrawlSearch(params) {
328
346
  };
329
347
  if (sources.length > 0) body.sources = sources;
330
348
  if (categories.length > 0) body.categories = categories;
349
+ if (includeDomains.length > 0) body.includeDomains = includeDomains;
350
+ if (excludeDomains.length > 0) body.excludeDomains = excludeDomains;
351
+ if (tbs) body.tbs = tbs;
352
+ if (location) body.location = location;
353
+ if (country) body.country = country;
331
354
  if (scrapeResults) body.scrapeOptions = { formats: ["markdown"] };
332
355
  const start = Date.now();
333
356
  const endpoint = await resolveEndpoint(baseUrl, "/v2/search");
@@ -348,7 +371,7 @@ async function runFirecrawlSearch(params) {
348
371
  });
349
372
  const result = buildSearchPayload({
350
373
  query: params.query,
351
- provider: "firecrawl",
374
+ provider: providerId,
352
375
  items: resolveSearchItems(payload),
353
376
  tookMs: Date.now() - start,
354
377
  scrapeResults
@@ -4,7 +4,7 @@ import { enablePluginInConfig } from "openclaw/plugin-sdk/provider-web-fetch-con
4
4
  //#region extensions/firecrawl/src/firecrawl-fetch-provider.ts
5
5
  let firecrawlClientModulePromise;
6
6
  function loadFirecrawlClientModule() {
7
- firecrawlClientModulePromise ??= import("./firecrawl-client-xZqyVUBg.js").then((n) => n.t);
7
+ firecrawlClientModulePromise ??= import("./firecrawl-client-CPw_AuJR.js").then((n) => n.t);
8
8
  return firecrawlClientModulePromise;
9
9
  }
10
10
  function createFirecrawlWebFetchProvider() {
@@ -0,0 +1,71 @@
1
+ import { buildFirecrawlFreeWebSearchProviderBase, buildFirecrawlWebSearchProviderBase } from "./web-search-shared.js";
2
+ import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
3
+ import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
4
+ //#region extensions/firecrawl/src/firecrawl-search-provider.ts
5
+ const loadFirecrawlClientModule$1 = createLazyRuntimeModule(() => import("./firecrawl-client-CPw_AuJR.js").then((n) => n.t));
6
+ const GenericFirecrawlSearchSchema = {
7
+ type: "object",
8
+ properties: {
9
+ query: {
10
+ type: "string",
11
+ description: "Search query string."
12
+ },
13
+ count: {
14
+ type: "integer",
15
+ description: "Number of results to return (1-10).",
16
+ minimum: 1,
17
+ maximum: 10
18
+ }
19
+ },
20
+ additionalProperties: false
21
+ };
22
+ function createFirecrawlWebSearchProvider() {
23
+ return {
24
+ ...buildFirecrawlWebSearchProviderBase(),
25
+ createTool: (ctx) => ({
26
+ description: "Search the web using Firecrawl. Returns structured results with snippets from Firecrawl Search. Use firecrawl_search for Firecrawl-specific knobs like sources or categories.",
27
+ parameters: GenericFirecrawlSearchSchema,
28
+ execute: async (args) => {
29
+ const { runFirecrawlSearch } = await loadFirecrawlClientModule$1();
30
+ return await runFirecrawlSearch({
31
+ cfg: ctx.config,
32
+ query: typeof args.query === "string" ? args.query : "",
33
+ count: readPositiveIntegerParam(args, "count", {
34
+ message: "count must be an integer from 1 to 10",
35
+ max: 10
36
+ })
37
+ });
38
+ }
39
+ })
40
+ };
41
+ }
42
+ //#endregion
43
+ //#region extensions/firecrawl/src/firecrawl-free-search-provider.ts
44
+ let firecrawlClientModulePromise;
45
+ function loadFirecrawlClientModule() {
46
+ firecrawlClientModulePromise ??= import("./firecrawl-client-CPw_AuJR.js").then((n) => n.t);
47
+ return firecrawlClientModulePromise;
48
+ }
49
+ function createFirecrawlFreeWebSearchProvider() {
50
+ return {
51
+ ...buildFirecrawlFreeWebSearchProviderBase(),
52
+ createTool: (ctx) => ({
53
+ description: "Search the web using Firecrawl's free hosted starter tier (no API key required). Returns structured results with snippets. Use firecrawl_search for Firecrawl-specific knobs like sources or categories.",
54
+ parameters: GenericFirecrawlSearchSchema,
55
+ execute: async (args) => {
56
+ const { runFirecrawlSearch } = await loadFirecrawlClientModule();
57
+ return await runFirecrawlSearch({
58
+ cfg: ctx.config,
59
+ query: typeof args.query === "string" ? args.query : "",
60
+ count: readPositiveIntegerParam(args, "count", {
61
+ message: "count must be an integer from 1 to 10",
62
+ max: 10
63
+ }),
64
+ access: "keyless"
65
+ });
66
+ }
67
+ })
68
+ };
69
+ }
70
+ //#endregion
71
+ export { createFirecrawlWebSearchProvider as n, createFirecrawlFreeWebSearchProvider as t };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { n as runFirecrawlScrape, r as runFirecrawlSearch } from "./firecrawl-client-xZqyVUBg.js";
2
- import { t as createFirecrawlWebFetchProvider } from "./firecrawl-fetch-provider-CasPevAg.js";
3
- import { t as createFirecrawlWebSearchProvider } from "./firecrawl-search-provider-C_iN9LEC.js";
1
+ import { n as runFirecrawlScrape, r as runFirecrawlSearch } from "./firecrawl-client-CPw_AuJR.js";
2
+ import { t as createFirecrawlWebFetchProvider } from "./firecrawl-fetch-provider-D6Rj8lqo.js";
3
+ import { n as createFirecrawlWebSearchProvider, t as createFirecrawlFreeWebSearchProvider } from "./firecrawl-free-search-provider-E4DXHcwh.js";
4
4
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
5
5
  import { optionalStringEnum } from "openclaw/plugin-sdk/channel-actions";
6
6
  import { jsonResult, readNonNegativeIntegerParam, readPositiveIntegerParam, readStringArrayParam, readStringParam } from "openclaw/plugin-sdk/provider-web-search";
@@ -64,12 +64,17 @@ function createFirecrawlScrapeTool(api) {
64
64
  const FirecrawlSearchToolSchema = Type.Object({
65
65
  query: Type.String({ description: "Search query string." }),
66
66
  count: Type.Optional(Type.Integer({
67
- description: "Number of results to return (1-10).",
67
+ description: "Number of results to return (1-100).",
68
68
  minimum: 1,
69
- maximum: 10
69
+ maximum: 100
70
70
  })),
71
71
  sources: Type.Optional(Type.Array(Type.String(), { description: "Optional sources list, for example [\"web\"], [\"news\"], or [\"images\"]." })),
72
72
  categories: Type.Optional(Type.Array(Type.String(), { description: "Optional Firecrawl categories, for example [\"github\"] or [\"research\"]." })),
73
+ includeDomains: Type.Optional(Type.Array(Type.String(), { description: "Restrict results to these hostnames (no protocol or path). Cannot be combined with excludeDomains." })),
74
+ excludeDomains: Type.Optional(Type.Array(Type.String(), { description: "Exclude these hostnames from results (no protocol or path). Cannot be combined with includeDomains." })),
75
+ tbs: Type.Optional(Type.String({ description: "Time-based filter, for example \"qdr:d\" (day), \"qdr:w\" (week), \"qdr:m\", \"qdr:y\", or \"sbd:1\" to sort by date." })),
76
+ location: Type.Optional(Type.String({ description: "Geo-target location, for example \"Germany\" or \"San Francisco,California,United States\"." })),
77
+ country: Type.Optional(Type.String({ description: "ISO country code for geo-targeting, for example \"US\", \"DE\", or \"JP\"." })),
73
78
  scrapeResults: Type.Optional(Type.Boolean({ description: "Include scraped result content when Firecrawl returns it." })),
74
79
  timeoutSeconds: Type.Optional(Type.Integer({
75
80
  description: "Timeout in seconds for the Firecrawl Search request.",
@@ -85,12 +90,17 @@ function createFirecrawlSearchTool(api) {
85
90
  execute: async (_toolCallId, rawParams) => {
86
91
  const query = readStringParam(rawParams, "query", { required: true });
87
92
  const count = readPositiveIntegerParam(rawParams, "count", {
88
- max: 10,
89
- message: "count must be an integer from 1 to 10"
93
+ max: 100,
94
+ message: "count must be an integer from 1 to 100"
90
95
  });
91
96
  const timeoutSeconds = readPositiveIntegerParam(rawParams, "timeoutSeconds");
92
97
  const sources = readStringArrayParam(rawParams, "sources");
93
98
  const categories = readStringArrayParam(rawParams, "categories");
99
+ const includeDomains = readStringArrayParam(rawParams, "includeDomains");
100
+ const excludeDomains = readStringArrayParam(rawParams, "excludeDomains");
101
+ const tbs = readStringParam(rawParams, "tbs");
102
+ const location = readStringParam(rawParams, "location");
103
+ const country = readStringParam(rawParams, "country");
94
104
  const scrapeResults = rawParams.scrapeResults === true;
95
105
  return jsonResult(await runFirecrawlSearch({
96
106
  cfg: api.config,
@@ -99,6 +109,11 @@ function createFirecrawlSearchTool(api) {
99
109
  timeoutSeconds,
100
110
  sources,
101
111
  categories,
112
+ includeDomains,
113
+ excludeDomains,
114
+ tbs,
115
+ location,
116
+ country,
102
117
  scrapeResults
103
118
  }));
104
119
  }
@@ -113,6 +128,7 @@ var firecrawl_default = definePluginEntry({
113
128
  register(api) {
114
129
  api.registerWebFetchProvider(createFirecrawlWebFetchProvider());
115
130
  api.registerWebSearchProvider(createFirecrawlWebSearchProvider());
131
+ api.registerWebSearchProvider(createFirecrawlFreeWebSearchProvider());
116
132
  api.registerTool(createFirecrawlSearchTool(api));
117
133
  api.registerTool(createFirecrawlScrapeTool(api));
118
134
  }
@@ -1,2 +1,2 @@
1
- import { t as createFirecrawlWebFetchProvider } from "./firecrawl-fetch-provider-CasPevAg.js";
1
+ import { t as createFirecrawlWebFetchProvider } from "./firecrawl-fetch-provider-D6Rj8lqo.js";
2
2
  export { createFirecrawlWebFetchProvider };
@@ -1,4 +1,4 @@
1
- import { buildFirecrawlWebSearchProviderBase } from "./web-search-shared.js";
1
+ import { buildFirecrawlFreeWebSearchProviderBase, buildFirecrawlWebSearchProviderBase } from "./web-search-shared.js";
2
2
  //#region extensions/firecrawl/web-search-contract-api.ts
3
3
  function createFirecrawlWebSearchProvider() {
4
4
  return {
@@ -6,5 +6,11 @@ function createFirecrawlWebSearchProvider() {
6
6
  createTool: () => null
7
7
  };
8
8
  }
9
+ function createFirecrawlFreeWebSearchProvider() {
10
+ return {
11
+ ...buildFirecrawlFreeWebSearchProviderBase(),
12
+ createTool: () => null
13
+ };
14
+ }
9
15
  //#endregion
10
- export { createFirecrawlWebSearchProvider };
16
+ export { createFirecrawlFreeWebSearchProvider, createFirecrawlWebSearchProvider };
@@ -1,2 +1,2 @@
1
- import { t as createFirecrawlWebSearchProvider } from "./firecrawl-search-provider-C_iN9LEC.js";
2
- export { createFirecrawlWebSearchProvider };
1
+ import { n as createFirecrawlWebSearchProvider, t as createFirecrawlFreeWebSearchProvider } from "./firecrawl-free-search-provider-E4DXHcwh.js";
2
+ export { createFirecrawlFreeWebSearchProvider, createFirecrawlWebSearchProvider };
@@ -51,5 +51,27 @@ function buildFirecrawlWebSearchProviderBase() {
51
51
  getConfiguredCredentialFallback: getConfiguredFirecrawlFetchCredentialFallback
52
52
  };
53
53
  }
54
+ function buildFirecrawlFreeWebSearchProviderBase() {
55
+ return {
56
+ id: "firecrawl-free",
57
+ label: "Firecrawl Search (Free)",
58
+ hint: "Free web search via Firecrawl's hosted starter tier — no API key required",
59
+ onboardingScopes: ["text-inference"],
60
+ requiresCredential: false,
61
+ envVars: [],
62
+ placeholder: "(no key needed)",
63
+ signupUrl: "https://www.firecrawl.dev/",
64
+ docsUrl: "https://docs.openclaw.ai/tools/firecrawl",
65
+ credentialPath: "",
66
+ ...createWebSearchProviderContractFields({
67
+ credentialPath: "",
68
+ searchCredential: {
69
+ type: "scoped",
70
+ scopeId: "firecrawl-free"
71
+ },
72
+ selectionPluginId: "firecrawl"
73
+ })
74
+ };
75
+ }
54
76
  //#endregion
55
- export { buildFirecrawlWebSearchProviderBase };
77
+ export { buildFirecrawlFreeWebSearchProviderBase, buildFirecrawlWebSearchProviderBase };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/firecrawl-plugin",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/firecrawl-plugin",
9
- "version": "2026.7.1",
9
+ "version": "2026.7.2-beta.2",
10
10
  "dependencies": {
11
11
  "typebox": "1.3.3"
12
12
  }
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "contracts": {
37
37
  "webFetchProviders": ["firecrawl"],
38
- "webSearchProviders": ["firecrawl"],
38
+ "webSearchProviders": ["firecrawl", "firecrawl-free"],
39
39
  "tools": ["firecrawl_search", "firecrawl_scrape"]
40
40
  },
41
41
  "configContracts": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/firecrawl-plugin",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.2",
4
4
  "description": "OpenClaw Firecrawl plugin.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,10 +21,10 @@
21
21
  "minHostVersion": ">=2026.6.8"
22
22
  },
23
23
  "compat": {
24
- "pluginApi": ">=2026.7.1"
24
+ "pluginApi": ">=2026.7.2-beta.2"
25
25
  },
26
26
  "build": {
27
- "openclawVersion": "2026.7.1",
27
+ "openclawVersion": "2026.7.2-beta.2",
28
28
  "bundledDist": false
29
29
  },
30
30
  "release": {
@@ -42,7 +42,7 @@
42
42
  "README.md"
43
43
  ],
44
44
  "peerDependencies": {
45
- "openclaw": ">=2026.7.1"
45
+ "openclaw": ">=2026.7.2-beta.2"
46
46
  },
47
47
  "peerDependenciesMeta": {
48
48
  "openclaw": {
@@ -1,43 +0,0 @@
1
- import { buildFirecrawlWebSearchProviderBase } from "./web-search-shared.js";
2
- import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
3
- import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
4
- //#region extensions/firecrawl/src/firecrawl-search-provider.ts
5
- const loadFirecrawlClientModule = createLazyRuntimeModule(() => import("./firecrawl-client-xZqyVUBg.js").then((n) => n.t));
6
- const GenericFirecrawlSearchSchema = {
7
- type: "object",
8
- properties: {
9
- query: {
10
- type: "string",
11
- description: "Search query string."
12
- },
13
- count: {
14
- type: "integer",
15
- description: "Number of results to return (1-10).",
16
- minimum: 1,
17
- maximum: 10
18
- }
19
- },
20
- additionalProperties: false
21
- };
22
- function createFirecrawlWebSearchProvider() {
23
- return {
24
- ...buildFirecrawlWebSearchProviderBase(),
25
- createTool: (ctx) => ({
26
- description: "Search the web using Firecrawl. Returns structured results with snippets from Firecrawl Search. Use firecrawl_search for Firecrawl-specific knobs like sources or categories.",
27
- parameters: GenericFirecrawlSearchSchema,
28
- execute: async (args) => {
29
- const { runFirecrawlSearch } = await loadFirecrawlClientModule();
30
- return await runFirecrawlSearch({
31
- cfg: ctx.config,
32
- query: typeof args.query === "string" ? args.query : "",
33
- count: readPositiveIntegerParam(args, "count", {
34
- message: "count must be an integer from 1 to 10",
35
- max: 10
36
- })
37
- });
38
- }
39
- })
40
- };
41
- }
42
- //#endregion
43
- export { createFirecrawlWebSearchProvider as t };