@openclaw/firecrawl-plugin 2026.9.1-beta.1 → 2026.9.1
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 +12 -11
- package/dist/{firecrawl-client-DQx3FAys.js → firecrawl-client-BPFpIblh.js} +8 -5
- package/dist/{firecrawl-fetch-provider-C8gB71c0.js → firecrawl-fetch-provider-CIpxLKLq.js} +4 -2
- package/dist/firecrawl-search-provider-80szkO8A.js +108 -0
- package/dist/index.js +3 -3
- package/dist/web-fetch-contract-api.js +1 -1
- package/dist/web-fetch-provider.js +1 -1
- package/dist/web-search-contract-api.js +1 -1
- package/dist/web-search-provider.js +1 -1
- package/node_modules/typebox/build/format/email.mjs +1 -1
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
- package/node_modules/typebox/package.json +1 -1
- package/package.json +5 -5
- package/dist/firecrawl-free-search-provider-5eCE16v7.js +0 -71
- package/dist/web-search-shared.js +0 -77
package/dist/api.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { n as runFirecrawlScrape } from "./firecrawl-client-
|
|
1
|
+
import { n as runFirecrawlScrape } from "./firecrawl-client-BPFpIblh.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) {
|
|
5
|
+
const cfg = { plugins: { entries: { firecrawl: {
|
|
6
|
+
enabled: true,
|
|
7
|
+
config: { webFetch: {
|
|
8
|
+
apiKey: params.apiKey,
|
|
9
|
+
baseUrl: params.baseUrl,
|
|
10
|
+
onlyMainContent: params.onlyMainContent,
|
|
11
|
+
maxAgeMs: params.maxAgeMs,
|
|
12
|
+
timeoutSeconds: params.timeoutSeconds
|
|
13
|
+
} }
|
|
14
|
+
} } } };
|
|
5
15
|
const result = await runFirecrawlScrape({
|
|
6
|
-
cfg
|
|
7
|
-
enabled: true,
|
|
8
|
-
config: { webFetch: {
|
|
9
|
-
apiKey: params.apiKey,
|
|
10
|
-
baseUrl: params.baseUrl,
|
|
11
|
-
onlyMainContent: params.onlyMainContent,
|
|
12
|
-
maxAgeMs: params.maxAgeMs,
|
|
13
|
-
timeoutSeconds: params.timeoutSeconds
|
|
14
|
-
} }
|
|
15
|
-
} } } },
|
|
16
|
+
cfg,
|
|
16
17
|
url: params.url,
|
|
17
18
|
extractMode: params.extractMode,
|
|
18
19
|
maxChars: params.maxChars,
|
|
@@ -77,7 +77,8 @@ function resolveFirecrawlMaxAgeMs(cfg, override) {
|
|
|
77
77
|
return DEFAULT_FIRECRAWL_MAX_AGE_MS;
|
|
78
78
|
}
|
|
79
79
|
function resolveFirecrawlScrapeTimeoutSeconds(cfg, override) {
|
|
80
|
-
|
|
80
|
+
const fetch = resolveFirecrawlFetchConfig(cfg);
|
|
81
|
+
return resolvePositiveTimeoutSeconds(override, resolvePositiveTimeoutSeconds(fetch?.timeoutSeconds, DEFAULT_FIRECRAWL_SCRAPE_TIMEOUT_SECONDS));
|
|
81
82
|
}
|
|
82
83
|
function resolveFirecrawlSearchTimeoutSeconds(override) {
|
|
83
84
|
return resolvePositiveTimeoutSeconds(override, DEFAULT_FIRECRAWL_SEARCH_TIMEOUT_SECONDS);
|
|
@@ -98,7 +99,7 @@ const FIRECRAWL_SEARCH_MAX_CONTENT_CHARS = 2e4;
|
|
|
98
99
|
const DEFAULT_SCRAPE_MAX_CHARS = 5e4;
|
|
99
100
|
const FIRECRAWL_SCRAPE_METADATA_MAX_CHARS = 4e3;
|
|
100
101
|
const FIRECRAWL_RESULT_URL_MAX_CHARS = 2048;
|
|
101
|
-
const FIRECRAWL_SCRAPE_RESPONSE_MAX_BYTES =
|
|
102
|
+
const FIRECRAWL_SCRAPE_RESPONSE_MAX_BYTES = 67108864;
|
|
102
103
|
const ALLOWED_FIRECRAWL_HOSTS = /* @__PURE__ */ new Set(["api.firecrawl.dev"]);
|
|
103
104
|
const FIRECRAWL_PUBLISHED_DATE_RE = /^\d{4}-\d{2}-\d{2}(?:[T ][\d:.+Z-]{0,20})?$/u;
|
|
104
105
|
const FIRECRAWL_SELF_HOSTED_PRIVATE_ERROR = "Firecrawl custom baseUrl must target a private or internal self-hosted endpoint.";
|
|
@@ -337,7 +338,8 @@ async function runFirecrawlSearch(params) {
|
|
|
337
338
|
country,
|
|
338
339
|
scrapeResults
|
|
339
340
|
}));
|
|
340
|
-
const
|
|
341
|
+
const cacheTtlMs = resolveCacheTtlMs(params.cfg?.tools?.web?.search?.cacheTtlMinutes, DEFAULT_CACHE_TTL_MINUTES);
|
|
342
|
+
const cached = readCache(SEARCH_CACHE, cacheKey, cacheTtlMs);
|
|
341
343
|
if (cached) return {
|
|
342
344
|
...cached.value,
|
|
343
345
|
cached: true
|
|
@@ -367,7 +369,8 @@ async function runFirecrawlSearch(params) {
|
|
|
367
369
|
}, async (response) => {
|
|
368
370
|
const payloadValue = await readProviderJsonObjectResponse(response, "Firecrawl Search API error");
|
|
369
371
|
if (payloadValue.success === false) {
|
|
370
|
-
const
|
|
372
|
+
const error = typeof payloadValue.error === "string" ? payloadValue.error : typeof payloadValue.message === "string" ? payloadValue.message : "unknown error";
|
|
373
|
+
const safeError = wrapWebContent(truncateSanitizedExternalContent(error, 1e3).text, "web_search");
|
|
371
374
|
throw new Error(`Firecrawl Search API error: ${safeError}`);
|
|
372
375
|
}
|
|
373
376
|
return payloadValue;
|
|
@@ -379,7 +382,7 @@ async function runFirecrawlSearch(params) {
|
|
|
379
382
|
tookMs: Date.now() - start,
|
|
380
383
|
scrapeResults
|
|
381
384
|
});
|
|
382
|
-
writeCache(SEARCH_CACHE, cacheKey, result,
|
|
385
|
+
writeCache(SEARCH_CACHE, cacheKey, result, cacheTtlMs);
|
|
383
386
|
return result;
|
|
384
387
|
}
|
|
385
388
|
function resolveScrapeData(payload) {
|
|
@@ -51,7 +51,7 @@ const FIRECRAWL_WEB_FETCH_PROVIDER_SHARED = {
|
|
|
51
51
|
};
|
|
52
52
|
//#endregion
|
|
53
53
|
//#region extensions/firecrawl/src/firecrawl-fetch-provider.ts
|
|
54
|
-
const loadFirecrawlClientModule = createLazyRuntimeModule(() => import("./firecrawl-client-
|
|
54
|
+
const loadFirecrawlClientModule = createLazyRuntimeModule(() => import("./firecrawl-client-BPFpIblh.js").then((n) => n.t));
|
|
55
55
|
function createFirecrawlWebFetchProvider() {
|
|
56
56
|
return {
|
|
57
57
|
...FIRECRAWL_WEB_FETCH_PROVIDER_SHARED,
|
|
@@ -59,7 +59,8 @@ function createFirecrawlWebFetchProvider() {
|
|
|
59
59
|
createTool: ({ config }) => ({
|
|
60
60
|
description: "Fetch a page using Firecrawl.",
|
|
61
61
|
parameters: {},
|
|
62
|
-
execute: async (args) => {
|
|
62
|
+
execute: async (args, executionContext) => {
|
|
63
|
+
executionContext?.signal?.throwIfAborted();
|
|
63
64
|
const url = typeof args.url === "string" ? args.url : "";
|
|
64
65
|
const extractMode = args.extractMode === "text" ? "text" : "markdown";
|
|
65
66
|
const maxChars = readPositiveIntegerParam(args, "maxChars");
|
|
@@ -72,6 +73,7 @@ function createFirecrawlWebFetchProvider() {
|
|
|
72
73
|
extractMode,
|
|
73
74
|
access: "keyless",
|
|
74
75
|
maxChars,
|
|
76
|
+
...executionContext?.signal ? { signal: executionContext.signal } : {},
|
|
75
77
|
...proxy ? { proxy } : {},
|
|
76
78
|
...storeInCache !== void 0 ? { storeInCache } : {}
|
|
77
79
|
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
2
|
+
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
|
|
3
|
+
import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
|
+
import { createWebSearchProviderContractFields, enablePluginInConfig } from "openclaw/plugin-sdk/provider-web-search-contract";
|
|
5
|
+
//#region extensions/firecrawl/src/firecrawl-search-provider.ts
|
|
6
|
+
const FIRECRAWL_CREDENTIAL_PATH = "plugins.entries.firecrawl.config.webSearch.apiKey";
|
|
7
|
+
const loadFirecrawlClientModule = createLazyRuntimeModule(() => import("./firecrawl-client-BPFpIblh.js").then((n) => n.t));
|
|
8
|
+
const GenericFirecrawlSearchSchema = {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: {
|
|
11
|
+
query: {
|
|
12
|
+
type: "string",
|
|
13
|
+
description: "Search query string."
|
|
14
|
+
},
|
|
15
|
+
count: {
|
|
16
|
+
type: "integer",
|
|
17
|
+
description: "Number of results to return (1-10).",
|
|
18
|
+
minimum: 1,
|
|
19
|
+
maximum: 10
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
additionalProperties: false
|
|
23
|
+
};
|
|
24
|
+
function getConfiguredFirecrawlFetchCredentialFallback(config) {
|
|
25
|
+
const pluginConfig = asOptionalRecord(config?.plugins?.entries?.firecrawl?.config);
|
|
26
|
+
const value = asOptionalRecord(pluginConfig?.webFetch)?.apiKey;
|
|
27
|
+
return value === void 0 ? void 0 : {
|
|
28
|
+
path: "plugins.entries.firecrawl.config.webFetch.apiKey",
|
|
29
|
+
value
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function createFirecrawlSearchProvider(keyless) {
|
|
33
|
+
const id = keyless ? "firecrawl-free" : "firecrawl";
|
|
34
|
+
const credentialPath = keyless ? "" : FIRECRAWL_CREDENTIAL_PATH;
|
|
35
|
+
return {
|
|
36
|
+
id,
|
|
37
|
+
label: keyless ? "Firecrawl Search (Free)" : "Firecrawl Search",
|
|
38
|
+
hint: keyless ? "Free web search via Firecrawl's hosted starter tier — no API key required" : "Structured results with optional result scraping",
|
|
39
|
+
onboardingScopes: ["text-inference"],
|
|
40
|
+
...keyless ? {
|
|
41
|
+
requiresCredential: false,
|
|
42
|
+
envVars: [],
|
|
43
|
+
placeholder: "(no key needed)"
|
|
44
|
+
} : {
|
|
45
|
+
credentialLabel: "Firecrawl API key",
|
|
46
|
+
envVars: ["FIRECRAWL_API_KEY"],
|
|
47
|
+
placeholder: "fc-..."
|
|
48
|
+
},
|
|
49
|
+
signupUrl: "https://www.firecrawl.dev/",
|
|
50
|
+
docsUrl: "https://docs.openclaw.ai/tools/firecrawl",
|
|
51
|
+
...keyless ? {} : { autoDetectOrder: 60 },
|
|
52
|
+
credentialPath,
|
|
53
|
+
...createWebSearchProviderContractFields({
|
|
54
|
+
credentialPath,
|
|
55
|
+
searchCredential: {
|
|
56
|
+
type: "scoped",
|
|
57
|
+
scopeId: id
|
|
58
|
+
},
|
|
59
|
+
...keyless ? { selectionPluginId: "firecrawl" } : { configuredCredential: { pluginId: "firecrawl" } }
|
|
60
|
+
}),
|
|
61
|
+
...keyless ? {} : {
|
|
62
|
+
applySelectionConfig: (config) => {
|
|
63
|
+
const enabled = enablePluginInConfig(config, "firecrawl");
|
|
64
|
+
if (!enabled.enabled || enabled.config.tools?.web?.fetch?.provider) return enabled.config;
|
|
65
|
+
return {
|
|
66
|
+
...enabled.config,
|
|
67
|
+
tools: {
|
|
68
|
+
...enabled.config.tools,
|
|
69
|
+
web: {
|
|
70
|
+
...enabled.config.tools?.web,
|
|
71
|
+
fetch: {
|
|
72
|
+
...enabled.config.tools?.web?.fetch,
|
|
73
|
+
provider: "firecrawl"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
getConfiguredCredentialFallback: getConfiguredFirecrawlFetchCredentialFallback
|
|
80
|
+
},
|
|
81
|
+
createTool: (ctx) => ({
|
|
82
|
+
description: keyless ? "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." : "Search the web using Firecrawl. Returns structured results with snippets from Firecrawl Search. Use firecrawl_search for Firecrawl-specific knobs like sources or categories.",
|
|
83
|
+
parameters: GenericFirecrawlSearchSchema,
|
|
84
|
+
execute: async (args, executionContext) => {
|
|
85
|
+
executionContext?.signal?.throwIfAborted();
|
|
86
|
+
const { runFirecrawlSearch } = await loadFirecrawlClientModule();
|
|
87
|
+
return await runFirecrawlSearch({
|
|
88
|
+
cfg: ctx.config,
|
|
89
|
+
query: typeof args.query === "string" ? args.query : "",
|
|
90
|
+
count: readPositiveIntegerParam(args, "count", {
|
|
91
|
+
message: "count must be an integer from 1 to 10",
|
|
92
|
+
max: 10
|
|
93
|
+
}),
|
|
94
|
+
...keyless ? { access: "keyless" } : {},
|
|
95
|
+
...executionContext?.signal ? { signal: executionContext.signal } : {}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function createFirecrawlWebSearchProvider() {
|
|
102
|
+
return createFirecrawlSearchProvider(false);
|
|
103
|
+
}
|
|
104
|
+
function createFirecrawlFreeWebSearchProvider() {
|
|
105
|
+
return createFirecrawlSearchProvider(true);
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
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-
|
|
2
|
-
import { t as createFirecrawlWebFetchProvider } from "./firecrawl-fetch-provider-
|
|
3
|
-
import { n as createFirecrawlWebSearchProvider, t as createFirecrawlFreeWebSearchProvider } from "./firecrawl-
|
|
1
|
+
import { n as runFirecrawlScrape, r as runFirecrawlSearch } from "./firecrawl-client-BPFpIblh.js";
|
|
2
|
+
import { t as createFirecrawlWebFetchProvider } from "./firecrawl-fetch-provider-CIpxLKLq.js";
|
|
3
|
+
import { n as createFirecrawlWebSearchProvider, t as createFirecrawlFreeWebSearchProvider } from "./firecrawl-search-provider-80szkO8A.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";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createFirecrawlWebFetchProvider } from "./firecrawl-fetch-provider-
|
|
1
|
+
import { t as createFirecrawlWebFetchProvider } from "./firecrawl-fetch-provider-CIpxLKLq.js";
|
|
2
2
|
export { createFirecrawlWebFetchProvider };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as createFirecrawlWebSearchProvider, t as createFirecrawlFreeWebSearchProvider } from "./firecrawl-
|
|
1
|
+
import { n as createFirecrawlWebSearchProvider, t as createFirecrawlFreeWebSearchProvider } from "./firecrawl-search-provider-80szkO8A.js";
|
|
2
2
|
import "./web-search-provider.js";
|
|
3
3
|
export { createFirecrawlFreeWebSearchProvider, createFirecrawlWebSearchProvider };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createFirecrawlWebSearchProvider, t as createFirecrawlFreeWebSearchProvider } from "./firecrawl-
|
|
1
|
+
import { n as createFirecrawlWebSearchProvider, t as createFirecrawlFreeWebSearchProvider } from "./firecrawl-search-provider-80szkO8A.js";
|
|
2
2
|
export { createFirecrawlFreeWebSearchProvider, createFirecrawlWebSearchProvider };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const Email = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[^"\\]
|
|
1
|
+
const Email = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[^"\\]|\\[\x20-\x7e])*")@(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*|\[(?:IPv6:[a-f0-9:]+|(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})\])$/i;
|
|
2
2
|
/**
|
|
3
3
|
* Returns true if the value is an Email
|
|
4
4
|
* @specification https://datatracker.ietf.org/doc/html/rfc5322
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as FormatBidi from './format/bidi.mjs';
|
|
2
2
|
import * as LabelUnicode from './label/unicode.mjs';
|
|
3
3
|
import * as LabelPuny from './label/puny.mjs';
|
|
4
|
+
// ------------------------------------------------------------------
|
|
5
|
+
// IsLabel
|
|
6
|
+
// ------------------------------------------------------------------
|
|
4
7
|
function IsValidLabelLength(value) {
|
|
5
8
|
return value.length > 0 && value.length <= 63;
|
|
6
9
|
}
|
|
@@ -8,9 +11,24 @@ function IsLabel(value) {
|
|
|
8
11
|
return IsValidLabelLength(value) && (LabelPuny.IsPunyLabel(value) ||
|
|
9
12
|
LabelUnicode.IsUnicodeLabel(value));
|
|
10
13
|
}
|
|
14
|
+
// ------------------------------------------------------------------
|
|
15
|
+
// NormalizeHostname
|
|
16
|
+
//
|
|
17
|
+
// Normalizes a hostname for label validation. Normalizes for NFC
|
|
18
|
+
// such that equivalent codepoint sequences can be uniformly
|
|
19
|
+
// compared. It also removes codepoints that IDNA mapping ignores,
|
|
20
|
+
// and converts full stop variants to ASCII '.' so the hostname can
|
|
21
|
+
// be split into labels.
|
|
22
|
+
// ------------------------------------------------------------------
|
|
11
23
|
function NormalizeHostname(value) {
|
|
12
|
-
return value
|
|
24
|
+
return value
|
|
25
|
+
.normalize('NFC')
|
|
26
|
+
.replace(/[\u00ad\u034f\u180b-\u180d\u200b\ufe00-\ufe0f\u{e0100}-\u{e01ef}]/gu, '') // RE_IGNORED_MAPPING
|
|
27
|
+
.replace(/[\u002E\u3002\uFF0E\uFF61]/g, '.'); // RE_FULL_STOP_MAPPING
|
|
13
28
|
}
|
|
29
|
+
// ------------------------------------------------------------------
|
|
30
|
+
// IsIdnHostname
|
|
31
|
+
// ------------------------------------------------------------------
|
|
14
32
|
export function IsIdnHostname(value) {
|
|
15
33
|
if (value.length === 0 || value.includes(' '))
|
|
16
34
|
return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/firecrawl-plugin",
|
|
3
|
-
"version": "2026.9.1
|
|
3
|
+
"version": "2026.9.1",
|
|
4
4
|
"description": "OpenClaw Firecrawl plugin.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"typebox": "1.3.
|
|
11
|
+
"typebox": "1.3.17",
|
|
12
12
|
"zod": "4.4.3"
|
|
13
13
|
},
|
|
14
14
|
"openclaw": {
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"minHostVersion": ">=2026.6.8"
|
|
23
23
|
},
|
|
24
24
|
"compat": {
|
|
25
|
-
"pluginApi": ">=2026.9.1
|
|
25
|
+
"pluginApi": ">=2026.9.1"
|
|
26
26
|
},
|
|
27
27
|
"build": {
|
|
28
|
-
"openclawVersion": "2026.9.1
|
|
28
|
+
"openclawVersion": "2026.9.1",
|
|
29
29
|
"bundledDist": false
|
|
30
30
|
},
|
|
31
31
|
"release": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"README.md"
|
|
43
43
|
],
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"openclaw": ">=2026.9.1
|
|
45
|
+
"openclaw": ">=2026.9.1"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|
|
48
48
|
"openclaw": {
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { buildFirecrawlFreeWebSearchProviderBase, buildFirecrawlWebSearchProviderBase } from "./web-search-shared.js";
|
|
2
|
-
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
3
|
-
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
|
|
4
|
-
//#region extensions/firecrawl/src/firecrawl-search-provider.ts
|
|
5
|
-
const loadFirecrawlClientModule$1 = createLazyRuntimeModule(() => import("./firecrawl-client-DQx3FAys.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, executionContext) => {
|
|
29
|
-
executionContext?.signal?.throwIfAborted();
|
|
30
|
-
const { runFirecrawlSearch } = await loadFirecrawlClientModule$1();
|
|
31
|
-
return await runFirecrawlSearch({
|
|
32
|
-
cfg: ctx.config,
|
|
33
|
-
query: typeof args.query === "string" ? args.query : "",
|
|
34
|
-
count: readPositiveIntegerParam(args, "count", {
|
|
35
|
-
message: "count must be an integer from 1 to 10",
|
|
36
|
-
max: 10
|
|
37
|
-
}),
|
|
38
|
-
...executionContext?.signal ? { signal: executionContext.signal } : {}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
//#endregion
|
|
45
|
-
//#region extensions/firecrawl/src/firecrawl-free-search-provider.ts
|
|
46
|
-
const loadFirecrawlClientModule = createLazyRuntimeModule(() => import("./firecrawl-client-DQx3FAys.js").then((n) => n.t));
|
|
47
|
-
function createFirecrawlFreeWebSearchProvider() {
|
|
48
|
-
return {
|
|
49
|
-
...buildFirecrawlFreeWebSearchProviderBase(),
|
|
50
|
-
createTool: (ctx) => ({
|
|
51
|
-
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.",
|
|
52
|
-
parameters: GenericFirecrawlSearchSchema,
|
|
53
|
-
execute: async (args, executionContext) => {
|
|
54
|
-
executionContext?.signal?.throwIfAborted();
|
|
55
|
-
const { runFirecrawlSearch } = await loadFirecrawlClientModule();
|
|
56
|
-
return await runFirecrawlSearch({
|
|
57
|
-
cfg: ctx.config,
|
|
58
|
-
query: typeof args.query === "string" ? args.query : "",
|
|
59
|
-
count: readPositiveIntegerParam(args, "count", {
|
|
60
|
-
message: "count must be an integer from 1 to 10",
|
|
61
|
-
max: 10
|
|
62
|
-
}),
|
|
63
|
-
access: "keyless",
|
|
64
|
-
...executionContext?.signal ? { signal: executionContext.signal } : {}
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
})
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
//#endregion
|
|
71
|
-
export { createFirecrawlWebSearchProvider as n, createFirecrawlFreeWebSearchProvider as t };
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { createWebSearchProviderContractFields, enablePluginInConfig } from "openclaw/plugin-sdk/provider-web-search-contract";
|
|
2
|
-
//#region extensions/firecrawl/web-search-shared.ts
|
|
3
|
-
const FIRECRAWL_CREDENTIAL_PATH = "plugins.entries.firecrawl.config.webSearch.apiKey";
|
|
4
|
-
const FIRECRAWL_FETCH_CREDENTIAL_PATH = "plugins.entries.firecrawl.config.webFetch.apiKey";
|
|
5
|
-
function getConfiguredFirecrawlFetchCredentialFallback(config) {
|
|
6
|
-
const apiKey = (config?.plugins?.entries?.firecrawl?.config)?.webFetch?.apiKey;
|
|
7
|
-
return apiKey === void 0 ? void 0 : {
|
|
8
|
-
path: FIRECRAWL_FETCH_CREDENTIAL_PATH,
|
|
9
|
-
value: apiKey
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
function buildFirecrawlWebSearchProviderBase() {
|
|
13
|
-
const contractFields = createWebSearchProviderContractFields({
|
|
14
|
-
credentialPath: FIRECRAWL_CREDENTIAL_PATH,
|
|
15
|
-
searchCredential: {
|
|
16
|
-
type: "scoped",
|
|
17
|
-
scopeId: "firecrawl"
|
|
18
|
-
},
|
|
19
|
-
configuredCredential: { pluginId: "firecrawl" }
|
|
20
|
-
});
|
|
21
|
-
return {
|
|
22
|
-
id: "firecrawl",
|
|
23
|
-
label: "Firecrawl Search",
|
|
24
|
-
hint: "Structured results with optional result scraping",
|
|
25
|
-
onboardingScopes: ["text-inference"],
|
|
26
|
-
credentialLabel: "Firecrawl API key",
|
|
27
|
-
envVars: ["FIRECRAWL_API_KEY"],
|
|
28
|
-
placeholder: "fc-...",
|
|
29
|
-
signupUrl: "https://www.firecrawl.dev/",
|
|
30
|
-
docsUrl: "https://docs.openclaw.ai/tools/firecrawl",
|
|
31
|
-
autoDetectOrder: 60,
|
|
32
|
-
credentialPath: FIRECRAWL_CREDENTIAL_PATH,
|
|
33
|
-
...contractFields,
|
|
34
|
-
applySelectionConfig: (config) => {
|
|
35
|
-
const enabled = enablePluginInConfig(config, "firecrawl");
|
|
36
|
-
if (!enabled.enabled || enabled.config.tools?.web?.fetch?.provider) return enabled.config;
|
|
37
|
-
return {
|
|
38
|
-
...enabled.config,
|
|
39
|
-
tools: {
|
|
40
|
-
...enabled.config.tools,
|
|
41
|
-
web: {
|
|
42
|
-
...enabled.config.tools?.web,
|
|
43
|
-
fetch: {
|
|
44
|
-
...enabled.config.tools?.web?.fetch,
|
|
45
|
-
provider: "firecrawl"
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
},
|
|
51
|
-
getConfiguredCredentialFallback: getConfiguredFirecrawlFetchCredentialFallback
|
|
52
|
-
};
|
|
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
|
-
}
|
|
76
|
-
//#endregion
|
|
77
|
-
export { buildFirecrawlFreeWebSearchProviderBase, buildFirecrawlWebSearchProviderBase };
|