@openclaw/firecrawl-plugin 2026.7.2-beta.7 → 2026.7.34
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/{firecrawl-client-DZohiNQK.js → .setup/firecrawl-client-4aub4Iqn.mjs} +60 -53
- package/dist/{firecrawl-fetch-provider-DXmd_5yB.js → .setup/firecrawl-fetch-provider-BPIkituf.mjs} +2 -2
- package/dist/{firecrawl-fetch-provider-shared-BhzfHFkE.js → .setup/firecrawl-fetch-provider-shared-BQUWpKAv.mjs} +1 -1
- package/dist/.setup/firecrawl-search-provider-DQhIEDTY.mjs +43 -0
- package/dist/api.js +12 -11
- package/dist/index.js +8 -24
- package/dist/web-fetch-contract-api.js +1 -1
- package/dist/web-fetch-provider.js +1 -1
- package/dist/web-search-contract-api.js +2 -8
- package/dist/web-search-provider.js +2 -2
- package/dist/web-search-shared.js +1 -23
- package/node_modules/typebox/build/compile/validator.d.mts +4 -1
- package/node_modules/typebox/build/guard/guard.d.mts +1 -1
- package/node_modules/typebox/build/guard/guard.mjs +2 -5
- package/node_modules/typebox/build/guard/string.mjs +4 -16
- package/node_modules/typebox/build/schema/engine/_functions.mjs +15 -34
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +0 -5
- package/node_modules/typebox/build/type/action/readonly_object.mjs +0 -8
- package/node_modules/typebox/build/typebox.d.mts +1 -1
- package/node_modules/typebox/build/typebox.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +32 -29
- package/openclaw.plugin.json +4 -1
- package/package.json +5 -5
- package/dist/firecrawl-free-search-provider-D_QqmJGK.js +0 -71
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
|
|
2
2
|
import { DEFAULT_CACHE_TTL_MINUTES, markdownToText, normalizeCacheKey, readCache, readResponseText, resolveCacheTtlMs, resolvePositiveTimeoutSeconds, truncateText, withSelfHostedWebToolsEndpoint, withStrictWebToolsEndpoint, writeCache } from "openclaw/plugin-sdk/provider-web-fetch";
|
|
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";
|
|
8
6
|
import { canResolveEnvSecretRefInReadOnlyPath } from "openclaw/plugin-sdk/extension-shared";
|
|
9
7
|
//#region \0rolldown/runtime.js
|
|
10
8
|
var __defProp = Object.defineProperty;
|
|
@@ -17,17 +15,35 @@ var __exportAll = (all, no_symbols) => {
|
|
|
17
15
|
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
18
16
|
return target;
|
|
19
17
|
};
|
|
20
|
-
const DEFAULT_FIRECRAWL_SEARCH_TIMEOUT_SECONDS = 30;
|
|
21
|
-
const DEFAULT_FIRECRAWL_SCRAPE_TIMEOUT_SECONDS = 60;
|
|
22
18
|
const DEFAULT_FIRECRAWL_MAX_AGE_MS = 1728e5;
|
|
23
19
|
const FIRECRAWL_API_KEY_ENV_VAR = "FIRECRAWL_API_KEY";
|
|
20
|
+
function resolveSearchConfig(cfg) {
|
|
21
|
+
const search = cfg?.tools?.web?.search;
|
|
22
|
+
if (!search || typeof search !== "object") return;
|
|
23
|
+
return search;
|
|
24
|
+
}
|
|
25
|
+
function resolveFetchConfig(cfg) {
|
|
26
|
+
const fetch = cfg?.tools?.web?.fetch;
|
|
27
|
+
if (!fetch || typeof fetch !== "object") return;
|
|
28
|
+
return fetch;
|
|
29
|
+
}
|
|
24
30
|
function resolveFirecrawlSearchConfig(cfg) {
|
|
25
31
|
const pluginWebSearch = (cfg?.plugins?.entries?.firecrawl?.config)?.webSearch;
|
|
26
32
|
if (pluginWebSearch && typeof pluginWebSearch === "object" && !Array.isArray(pluginWebSearch)) return pluginWebSearch;
|
|
33
|
+
const search = resolveSearchConfig(cfg);
|
|
34
|
+
if (!search || typeof search !== "object") return;
|
|
35
|
+
const firecrawl = "firecrawl" in search ? search.firecrawl : void 0;
|
|
36
|
+
if (!firecrawl || typeof firecrawl !== "object") return;
|
|
37
|
+
return firecrawl;
|
|
27
38
|
}
|
|
28
39
|
function resolveFirecrawlFetchConfig(cfg) {
|
|
29
40
|
const pluginWebFetch = (cfg?.plugins?.entries?.firecrawl?.config)?.webFetch;
|
|
30
41
|
if (pluginWebFetch && typeof pluginWebFetch === "object" && !Array.isArray(pluginWebFetch)) return pluginWebFetch;
|
|
42
|
+
const fetch = resolveFetchConfig(cfg);
|
|
43
|
+
if (!fetch || typeof fetch !== "object") return;
|
|
44
|
+
const firecrawl = "firecrawl" in fetch ? fetch.firecrawl : void 0;
|
|
45
|
+
if (!firecrawl || typeof firecrawl !== "object") return;
|
|
46
|
+
return firecrawl;
|
|
31
47
|
}
|
|
32
48
|
function resolveConfiguredSecret(value, path, cfg) {
|
|
33
49
|
const resolved = resolveSecretInputString({
|
|
@@ -61,13 +77,25 @@ function resolveConfiguredSecret(value, path, cfg) {
|
|
|
61
77
|
function resolveFirecrawlApiKey(cfg) {
|
|
62
78
|
const pluginConfig = cfg?.plugins?.entries?.firecrawl?.config;
|
|
63
79
|
const search = resolveFirecrawlSearchConfig(cfg);
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
const fetch = resolveFirecrawlFetchConfig(cfg);
|
|
81
|
+
const configuredCandidates = [
|
|
82
|
+
{
|
|
83
|
+
value: pluginConfig?.webFetch?.apiKey,
|
|
84
|
+
path: "plugins.entries.firecrawl.config.webFetch.apiKey"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
value: search?.apiKey,
|
|
88
|
+
path: "plugins.entries.firecrawl.config.webSearch.apiKey"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
value: search?.apiKey,
|
|
92
|
+
path: "tools.web.search.firecrawl.apiKey"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
value: fetch?.apiKey,
|
|
96
|
+
path: "tools.web.fetch.firecrawl.apiKey"
|
|
97
|
+
}
|
|
98
|
+
];
|
|
71
99
|
let blockedConfiguredSecret = false;
|
|
72
100
|
for (const candidate of configuredCandidates) {
|
|
73
101
|
const resolved = resolveConfiguredSecret(candidate.value, candidate.path, cfg);
|
|
@@ -95,10 +123,11 @@ function resolveFirecrawlMaxAgeMs(cfg, override) {
|
|
|
95
123
|
return DEFAULT_FIRECRAWL_MAX_AGE_MS;
|
|
96
124
|
}
|
|
97
125
|
function resolveFirecrawlScrapeTimeoutSeconds(cfg, override) {
|
|
98
|
-
|
|
126
|
+
const fetch = resolveFirecrawlFetchConfig(cfg);
|
|
127
|
+
return resolvePositiveTimeoutSeconds(override, resolvePositiveTimeoutSeconds(fetch?.timeoutSeconds, 60));
|
|
99
128
|
}
|
|
100
129
|
function resolveFirecrawlSearchTimeoutSeconds(override) {
|
|
101
|
-
return resolvePositiveTimeoutSeconds(override,
|
|
130
|
+
return resolvePositiveTimeoutSeconds(override, 30);
|
|
102
131
|
}
|
|
103
132
|
//#endregion
|
|
104
133
|
//#region extensions/firecrawl/src/firecrawl-client.ts
|
|
@@ -114,12 +143,12 @@ const SEARCH_CACHE = /* @__PURE__ */ new Map();
|
|
|
114
143
|
const SCRAPE_CACHE = /* @__PURE__ */ new Map();
|
|
115
144
|
const DEFAULT_SEARCH_COUNT = 5;
|
|
116
145
|
const DEFAULT_SCRAPE_MAX_CHARS = 5e4;
|
|
117
|
-
const FIRECRAWL_SCRAPE_RESPONSE_MAX_BYTES =
|
|
146
|
+
const FIRECRAWL_SCRAPE_RESPONSE_MAX_BYTES = 67108864;
|
|
118
147
|
const ALLOWED_FIRECRAWL_HOSTS = /* @__PURE__ */ new Set(["api.firecrawl.dev"]);
|
|
119
148
|
const FIRECRAWL_SELF_HOSTED_PRIVATE_ERROR = "Firecrawl custom baseUrl must target a private or internal self-hosted endpoint.";
|
|
120
149
|
const FIRECRAWL_HTTP_PRIVATE_ERROR = "Firecrawl HTTP baseUrl must target a private or internal self-hosted endpoint. Use https:// for public hosts.";
|
|
121
150
|
async function readFirecrawlJsonResponse(response, label, opts) {
|
|
122
|
-
return await
|
|
151
|
+
return await readProviderJsonResponse(response, label, opts);
|
|
123
152
|
}
|
|
124
153
|
function assertFirecrawlScrapeTargetAllowed(url) {
|
|
125
154
|
let parsed;
|
|
@@ -204,7 +233,7 @@ async function postFirecrawlJson(params, parse) {
|
|
|
204
233
|
const errorBody = await readResponseText(response, { maxBytes: 64e3 });
|
|
205
234
|
if (errorBody.text) detail = errorBody.text;
|
|
206
235
|
}
|
|
207
|
-
const safeDetail = wrapWebContent(
|
|
236
|
+
const safeDetail = wrapWebContent(detail.slice(0, 1e3), "web_fetch");
|
|
208
237
|
throw new Error(`${params.errorLabel} API error (${response.status}): ${safeDetail}`);
|
|
209
238
|
}
|
|
210
239
|
return await parse(response);
|
|
@@ -272,35 +301,21 @@ function buildSearchPayload(params) {
|
|
|
272
301
|
};
|
|
273
302
|
}
|
|
274
303
|
async function runFirecrawlSearch(params) {
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
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.");
|
|
279
|
-
const count = typeof params.count === "number" && Number.isFinite(params.count) ? Math.max(1, Math.min(100, Math.floor(params.count))) : DEFAULT_SEARCH_COUNT;
|
|
304
|
+
const apiKey = resolveFirecrawlApiKey(params.cfg);
|
|
305
|
+
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.");
|
|
306
|
+
const count = typeof params.count === "number" && Number.isFinite(params.count) ? Math.max(1, Math.min(10, Math.floor(params.count))) : DEFAULT_SEARCH_COUNT;
|
|
280
307
|
const timeoutSeconds = resolveFirecrawlSearchTimeoutSeconds(params.timeoutSeconds);
|
|
281
308
|
const scrapeResults = params.scrapeResults === true;
|
|
282
309
|
const sources = Array.isArray(params.sources) ? params.sources.filter(Boolean) : [];
|
|
283
310
|
const categories = Array.isArray(params.categories) ? params.categories.filter(Boolean) : [];
|
|
284
|
-
const includeDomains = Array.isArray(params.includeDomains) ? params.includeDomains.filter(Boolean) : [];
|
|
285
|
-
const excludeDomains = Array.isArray(params.excludeDomains) ? params.excludeDomains.filter(Boolean) : [];
|
|
286
|
-
if (includeDomains.length > 0 && excludeDomains.length > 0) throw new Error("Firecrawl search accepts includeDomains or excludeDomains, not both.");
|
|
287
|
-
const tbs = normalizeOptionalString(params.tbs);
|
|
288
|
-
const location = normalizeOptionalString(params.location);
|
|
289
|
-
const country = normalizeOptionalString(params.country);
|
|
290
311
|
const baseUrl = resolveFirecrawlBaseUrl(params.cfg);
|
|
291
312
|
const cacheKey = normalizeCacheKey(JSON.stringify({
|
|
292
313
|
type: "firecrawl-search",
|
|
293
|
-
provider: providerId,
|
|
294
314
|
q: params.query,
|
|
295
315
|
count,
|
|
296
316
|
baseUrl,
|
|
297
317
|
sources,
|
|
298
318
|
categories,
|
|
299
|
-
includeDomains,
|
|
300
|
-
excludeDomains,
|
|
301
|
-
tbs,
|
|
302
|
-
location,
|
|
303
|
-
country,
|
|
304
319
|
scrapeResults
|
|
305
320
|
}));
|
|
306
321
|
const cached = readCache(SEARCH_CACHE, cacheKey);
|
|
@@ -314,11 +329,6 @@ async function runFirecrawlSearch(params) {
|
|
|
314
329
|
};
|
|
315
330
|
if (sources.length > 0) body.sources = sources;
|
|
316
331
|
if (categories.length > 0) body.categories = categories;
|
|
317
|
-
if (includeDomains.length > 0) body.includeDomains = includeDomains;
|
|
318
|
-
if (excludeDomains.length > 0) body.excludeDomains = excludeDomains;
|
|
319
|
-
if (tbs) body.tbs = tbs;
|
|
320
|
-
if (location) body.location = location;
|
|
321
|
-
if (country) body.country = country;
|
|
322
332
|
if (scrapeResults) body.scrapeOptions = { formats: ["markdown"] };
|
|
323
333
|
const start = Date.now();
|
|
324
334
|
const endpoint = await resolveEndpoint(baseUrl, "/v2/search");
|
|
@@ -339,7 +349,7 @@ async function runFirecrawlSearch(params) {
|
|
|
339
349
|
});
|
|
340
350
|
const result = buildSearchPayload({
|
|
341
351
|
query: params.query,
|
|
342
|
-
provider:
|
|
352
|
+
provider: "firecrawl",
|
|
343
353
|
items: resolveSearchItems(payload),
|
|
344
354
|
tookMs: Date.now() - start,
|
|
345
355
|
scrapeResults
|
|
@@ -363,20 +373,14 @@ function parseFirecrawlScrapePayload(params) {
|
|
|
363
373
|
source: "web_fetch",
|
|
364
374
|
includeWarning: false
|
|
365
375
|
});
|
|
366
|
-
const status = typeof metadata?.statusCode === "number" && metadata.statusCode || typeof data.statusCode === "number" && data.statusCode || void 0;
|
|
367
|
-
const title = typeof metadata?.title === "string" && metadata.title ? wrapExternalContent(metadata.title, {
|
|
368
|
-
source: "web_fetch",
|
|
369
|
-
includeWarning: false
|
|
370
|
-
}) : void 0;
|
|
371
|
-
const warning = typeof params.payload.warning === "string" && params.payload.warning ? wrapExternalContent(params.payload.warning, {
|
|
372
|
-
source: "web_fetch",
|
|
373
|
-
includeWarning: false
|
|
374
|
-
}) : void 0;
|
|
375
376
|
return {
|
|
376
377
|
url: params.url,
|
|
377
378
|
finalUrl: typeof metadata?.sourceURL === "string" && metadata.sourceURL || typeof data.url === "string" && data.url || params.url,
|
|
378
|
-
|
|
379
|
-
|
|
379
|
+
status: typeof metadata?.statusCode === "number" && metadata.statusCode || typeof data.statusCode === "number" && data.statusCode || void 0,
|
|
380
|
+
title: typeof metadata?.title === "string" && metadata.title ? wrapExternalContent(metadata.title, {
|
|
381
|
+
source: "web_fetch",
|
|
382
|
+
includeWarning: false
|
|
383
|
+
}) : void 0,
|
|
380
384
|
extractor: "firecrawl",
|
|
381
385
|
extractMode: params.extractMode,
|
|
382
386
|
externalContent: {
|
|
@@ -386,9 +390,12 @@ function parseFirecrawlScrapePayload(params) {
|
|
|
386
390
|
},
|
|
387
391
|
truncated: truncated.truncated,
|
|
388
392
|
rawLength: rawText.length,
|
|
389
|
-
|
|
393
|
+
wrappedLength: wrappedText.length,
|
|
390
394
|
text: wrappedText,
|
|
391
|
-
|
|
395
|
+
warning: typeof params.payload.warning === "string" && params.payload.warning ? wrapExternalContent(params.payload.warning, {
|
|
396
|
+
source: "web_fetch",
|
|
397
|
+
includeWarning: false
|
|
398
|
+
}) : void 0
|
|
392
399
|
};
|
|
393
400
|
}
|
|
394
401
|
async function runFirecrawlScrape(params) {
|
package/dist/{firecrawl-fetch-provider-DXmd_5yB.js → .setup/firecrawl-fetch-provider-BPIkituf.mjs}
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { t as FIRECRAWL_WEB_FETCH_PROVIDER_SHARED } from "./firecrawl-fetch-provider-shared-
|
|
1
|
+
import { t as FIRECRAWL_WEB_FETCH_PROVIDER_SHARED } from "./firecrawl-fetch-provider-shared-BQUWpKAv.mjs";
|
|
2
2
|
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
|
|
3
3
|
import { enablePluginInConfig } from "openclaw/plugin-sdk/provider-web-fetch-contract";
|
|
4
4
|
//#region extensions/firecrawl/src/firecrawl-fetch-provider.ts
|
|
5
5
|
let firecrawlClientModulePromise;
|
|
6
6
|
function loadFirecrawlClientModule() {
|
|
7
|
-
firecrawlClientModulePromise ??= import("./firecrawl-client-
|
|
7
|
+
firecrawlClientModulePromise ??= import("./firecrawl-client-4aub4Iqn.mjs").then((n) => n.t);
|
|
8
8
|
return firecrawlClientModulePromise;
|
|
9
9
|
}
|
|
10
10
|
function createFirecrawlWebFetchProvider() {
|
|
@@ -18,7 +18,7 @@ const FIRECRAWL_WEB_FETCH_PROVIDER_SHARED = {
|
|
|
18
18
|
docsUrl: "https://docs.firecrawl.dev",
|
|
19
19
|
autoDetectOrder: 50,
|
|
20
20
|
credentialPath: "plugins.entries.firecrawl.config.webFetch.apiKey",
|
|
21
|
-
inactiveSecretPaths: ["plugins.entries.firecrawl.config.webFetch.apiKey"],
|
|
21
|
+
inactiveSecretPaths: ["plugins.entries.firecrawl.config.webFetch.apiKey", "tools.web.fetch.firecrawl.apiKey"],
|
|
22
22
|
getCredentialValue: (fetchConfig) => {
|
|
23
23
|
if (!fetchConfig || typeof fetchConfig !== "object") return;
|
|
24
24
|
const legacy = fetchConfig.firecrawl;
|
|
@@ -0,0 +1,43 @@
|
|
|
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-4aub4Iqn.mjs").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 };
|
package/dist/api.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { n as runFirecrawlScrape } from "
|
|
1
|
+
import { n as runFirecrawlScrape } from "./.setup/firecrawl-client-4aub4Iqn.mjs";
|
|
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,
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as runFirecrawlScrape, r as runFirecrawlSearch } from "
|
|
2
|
-
import { t as createFirecrawlWebFetchProvider } from "
|
|
3
|
-
import {
|
|
1
|
+
import { n as runFirecrawlScrape, r as runFirecrawlSearch } from "./.setup/firecrawl-client-4aub4Iqn.mjs";
|
|
2
|
+
import { t as createFirecrawlWebFetchProvider } from "./.setup/firecrawl-fetch-provider-BPIkituf.mjs";
|
|
3
|
+
import { t as createFirecrawlWebSearchProvider } from "./.setup/firecrawl-search-provider-DQhIEDTY.mjs";
|
|
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,17 +64,12 @@ 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-
|
|
67
|
+
description: "Number of results to return (1-10).",
|
|
68
68
|
minimum: 1,
|
|
69
|
-
maximum:
|
|
69
|
+
maximum: 10
|
|
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\"." })),
|
|
78
73
|
scrapeResults: Type.Optional(Type.Boolean({ description: "Include scraped result content when Firecrawl returns it." })),
|
|
79
74
|
timeoutSeconds: Type.Optional(Type.Integer({
|
|
80
75
|
description: "Timeout in seconds for the Firecrawl Search request.",
|
|
@@ -85,22 +80,17 @@ function createFirecrawlSearchTool(api) {
|
|
|
85
80
|
return {
|
|
86
81
|
name: "firecrawl_search",
|
|
87
82
|
label: "Firecrawl Search",
|
|
88
|
-
description: "Search the web using Firecrawl v2/search.
|
|
83
|
+
description: "Search the web using Firecrawl v2/search. Can optionally include scraped content from result pages.",
|
|
89
84
|
parameters: FirecrawlSearchToolSchema,
|
|
90
85
|
execute: async (_toolCallId, rawParams) => {
|
|
91
86
|
const query = readStringParam(rawParams, "query", { required: true });
|
|
92
87
|
const count = readPositiveIntegerParam(rawParams, "count", {
|
|
93
|
-
max:
|
|
94
|
-
message: "count must be an integer from 1 to
|
|
88
|
+
max: 10,
|
|
89
|
+
message: "count must be an integer from 1 to 10"
|
|
95
90
|
});
|
|
96
91
|
const timeoutSeconds = readPositiveIntegerParam(rawParams, "timeoutSeconds");
|
|
97
92
|
const sources = readStringArrayParam(rawParams, "sources");
|
|
98
93
|
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");
|
|
104
94
|
const scrapeResults = rawParams.scrapeResults === true;
|
|
105
95
|
return jsonResult(await runFirecrawlSearch({
|
|
106
96
|
cfg: api.config,
|
|
@@ -109,11 +99,6 @@ function createFirecrawlSearchTool(api) {
|
|
|
109
99
|
timeoutSeconds,
|
|
110
100
|
sources,
|
|
111
101
|
categories,
|
|
112
|
-
includeDomains,
|
|
113
|
-
excludeDomains,
|
|
114
|
-
tbs,
|
|
115
|
-
location,
|
|
116
|
-
country,
|
|
117
102
|
scrapeResults
|
|
118
103
|
}));
|
|
119
104
|
}
|
|
@@ -128,7 +113,6 @@ var firecrawl_default = definePluginEntry({
|
|
|
128
113
|
register(api) {
|
|
129
114
|
api.registerWebFetchProvider(createFirecrawlWebFetchProvider());
|
|
130
115
|
api.registerWebSearchProvider(createFirecrawlWebSearchProvider());
|
|
131
|
-
api.registerWebSearchProvider(createFirecrawlFreeWebSearchProvider());
|
|
132
116
|
api.registerTool(createFirecrawlSearchTool(api));
|
|
133
117
|
api.registerTool(createFirecrawlScrapeTool(api));
|
|
134
118
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as FIRECRAWL_WEB_FETCH_PROVIDER_SHARED } from "
|
|
1
|
+
import { t as FIRECRAWL_WEB_FETCH_PROVIDER_SHARED } from "./.setup/firecrawl-fetch-provider-shared-BQUWpKAv.mjs";
|
|
2
2
|
import { enablePluginInConfig } from "openclaw/plugin-sdk/provider-web-fetch-contract";
|
|
3
3
|
//#region extensions/firecrawl/web-fetch-contract-api.ts
|
|
4
4
|
function createFirecrawlWebFetchProvider() {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createFirecrawlWebFetchProvider } from "
|
|
1
|
+
import { t as createFirecrawlWebFetchProvider } from "./.setup/firecrawl-fetch-provider-BPIkituf.mjs";
|
|
2
2
|
export { createFirecrawlWebFetchProvider };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildFirecrawlWebSearchProviderBase } from "./web-search-shared.js";
|
|
2
2
|
//#region extensions/firecrawl/web-search-contract-api.ts
|
|
3
3
|
function createFirecrawlWebSearchProvider() {
|
|
4
4
|
return {
|
|
@@ -6,11 +6,5 @@ function createFirecrawlWebSearchProvider() {
|
|
|
6
6
|
createTool: () => null
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
|
-
function createFirecrawlFreeWebSearchProvider() {
|
|
10
|
-
return {
|
|
11
|
-
...buildFirecrawlFreeWebSearchProviderBase(),
|
|
12
|
-
createTool: () => null
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
9
|
//#endregion
|
|
16
|
-
export {
|
|
10
|
+
export { createFirecrawlWebSearchProvider };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { t as createFirecrawlWebSearchProvider } from "./.setup/firecrawl-search-provider-DQhIEDTY.mjs";
|
|
2
|
+
export { createFirecrawlWebSearchProvider };
|
|
@@ -51,27 +51,5 @@ 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
|
-
}
|
|
76
54
|
//#endregion
|
|
77
|
-
export {
|
|
55
|
+
export { buildFirecrawlWebSearchProviderBase };
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { type TLocalizedValidationError } from '../error/index.mjs';
|
|
2
2
|
import { type StaticDecode, type StaticEncode, type TProperties, type TSchema } from '../type/index.mjs';
|
|
3
|
+
import { BuildResult, EvaluateResult } from '../schema/index.mjs';
|
|
3
4
|
export declare class Validator<Context extends TProperties = TProperties, Type extends TSchema = TSchema, Encode extends unknown = StaticEncode<Type, Context>, Decode extends unknown = StaticDecode<Type, Context>> {
|
|
4
5
|
private readonly hasCodec;
|
|
5
6
|
private readonly buildResult;
|
|
6
7
|
private readonly evaluateResult;
|
|
7
|
-
/** Constructs a Validator. */
|
|
8
|
+
/** Constructs a Validator with the given Context and Type. */
|
|
8
9
|
constructor(context: Context, type: Type);
|
|
10
|
+
/** Constructs a Validator with the given arguments. */
|
|
11
|
+
constructor(hasCodec: boolean, buildResult: BuildResult, evaluateResult: EvaluateResult);
|
|
9
12
|
/** Returns true if this Validator is using JIT acceleration. */
|
|
10
13
|
IsAccelerated(): boolean;
|
|
11
14
|
/** Returns the Context for this validator. */
|
|
@@ -61,5 +61,5 @@ export declare function Keys(value: Record<PropertyKey, unknown>): string[];
|
|
|
61
61
|
export declare function Symbols(value: Record<PropertyKey, unknown>): symbol[];
|
|
62
62
|
/** Returns the property values for the given object via `Object.values()` */
|
|
63
63
|
export declare function Values(value: Record<PropertyKey, unknown>): unknown[];
|
|
64
|
-
/**
|
|
64
|
+
/** Tests values for deep equality */
|
|
65
65
|
export declare function IsDeepEqual(left: unknown, right: unknown): boolean;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// deno-fmt-ignore-file
|
|
2
1
|
import * as String from './string.mjs';
|
|
3
2
|
// --------------------------------------------------------------------------
|
|
4
3
|
// Guards
|
|
@@ -204,9 +203,7 @@ function DeepEqualArray(left, right) {
|
|
|
204
203
|
return IsArray(right) && IsEqual(left.length, right.length) &&
|
|
205
204
|
left.every((_, index) => IsDeepEqual(left[index], right[index]));
|
|
206
205
|
}
|
|
207
|
-
/**
|
|
206
|
+
/** Tests values for deep equality */
|
|
208
207
|
export function IsDeepEqual(left, right) {
|
|
209
|
-
return (IsArray(left) ? DeepEqualArray(left, right) :
|
|
210
|
-
IsObject(left) ? DeepEqualObject(left, right) :
|
|
211
|
-
IsEqual(left, right));
|
|
208
|
+
return (IsArray(left) ? DeepEqualArray(left, right) : IsObject(left) ? DeepEqualObject(left, right) : IsEqual(left, right));
|
|
212
209
|
}
|
|
@@ -5,18 +5,6 @@ function IsBetween(value, min, max) {
|
|
|
5
5
|
return value >= min && value <= max;
|
|
6
6
|
}
|
|
7
7
|
// --------------------------------------------------------------------------
|
|
8
|
-
// IsZeroWidthJoiner
|
|
9
|
-
// --------------------------------------------------------------------------
|
|
10
|
-
function IsZeroWidthJoiner(value) {
|
|
11
|
-
return (value === 0x200D);
|
|
12
|
-
}
|
|
13
|
-
// --------------------------------------------------------------------------
|
|
14
|
-
// IsHighSurrogate
|
|
15
|
-
// --------------------------------------------------------------------------
|
|
16
|
-
function IsHighSurrogate(value) {
|
|
17
|
-
return IsBetween(value, 0xD800, 0xDBFF);
|
|
18
|
-
}
|
|
19
|
-
// --------------------------------------------------------------------------
|
|
20
8
|
// IsRegionalIndicator
|
|
21
9
|
// --------------------------------------------------------------------------
|
|
22
10
|
function IsRegionalIndicator(value) {
|
|
@@ -84,10 +72,10 @@ function NextGraphemeClusterIndex(value, clusterStart) {
|
|
|
84
72
|
// IsGraphemeCodePoint
|
|
85
73
|
// --------------------------------------------------------------------------
|
|
86
74
|
function IsGraphemeCodePoint(value) {
|
|
87
|
-
return (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
75
|
+
return (IsBetween(value, 0xD800, 0xDBFF) || // High surrogate
|
|
76
|
+
IsBetween(value, 0x0300, 0x036F) || // Combining diacritical marks
|
|
77
|
+
(value === 0x200D) // Zero-width joiner
|
|
78
|
+
);
|
|
91
79
|
}
|
|
92
80
|
// --------------------------------------------------------------------------
|
|
93
81
|
// GraphemeCount
|
|
@@ -1,66 +1,47 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
+
import * as Schema from '../types/index.mjs';
|
|
2
3
|
import { Hashing } from '../../system/hashing/index.mjs';
|
|
3
4
|
import { EmitGuard as E } from '../../guard/index.mjs';
|
|
4
5
|
import { BuildSchema } from './schema.mjs';
|
|
5
|
-
const
|
|
6
|
-
const names = new Map;
|
|
7
|
-
const funcs = new Map();
|
|
8
|
-
// ------------------------------------------------------------------
|
|
9
|
-
// CreateName
|
|
10
|
-
// ------------------------------------------------------------------
|
|
11
|
-
function NextName() {
|
|
12
|
-
return Hashing.Hash(index[0]++);
|
|
13
|
-
}
|
|
14
|
-
function CreateName(schema, href) {
|
|
15
|
-
if (!names.has(schema))
|
|
16
|
-
names.set(schema, new Map());
|
|
17
|
-
const hrefs = names.get(schema);
|
|
18
|
-
if (hrefs.has(href))
|
|
19
|
-
return hrefs.get(href);
|
|
20
|
-
const name = NextName();
|
|
21
|
-
hrefs.set(href, name);
|
|
22
|
-
return name;
|
|
23
|
-
}
|
|
6
|
+
const functions = new Map();
|
|
24
7
|
// ------------------------------------------------------------------
|
|
25
8
|
// CreateCallExpression
|
|
26
9
|
// ------------------------------------------------------------------
|
|
27
|
-
function CreateCallExpression(context, _schema,
|
|
10
|
+
function CreateCallExpression(context, _schema, hash, value) {
|
|
28
11
|
return context.UseUnevaluated()
|
|
29
|
-
? E.Call(`check_${
|
|
30
|
-
: E.Call(`check_${
|
|
12
|
+
? E.Call(`check_${hash}`, ['context', value])
|
|
13
|
+
: E.Call(`check_${hash}`, [value]);
|
|
31
14
|
}
|
|
32
15
|
// ------------------------------------------------------------------
|
|
33
16
|
// CreateFunctionExpression
|
|
34
17
|
// ------------------------------------------------------------------
|
|
35
|
-
function CreateFunctionExpression(stack, context, schema,
|
|
18
|
+
function CreateFunctionExpression(stack, context, schema, hash) {
|
|
36
19
|
const expression = BuildSchema(stack, context, schema, 'value');
|
|
37
20
|
return context.UseUnevaluated()
|
|
38
|
-
? E.ConstDeclaration(`check_${
|
|
39
|
-
: E.ConstDeclaration(`check_${
|
|
21
|
+
? E.ConstDeclaration(`check_${hash}`, E.ArrowFunction(['context', 'value'], expression))
|
|
22
|
+
: E.ConstDeclaration(`check_${hash}`, E.ArrowFunction(['value'], expression));
|
|
40
23
|
}
|
|
41
24
|
// ------------------------------------------------------------------
|
|
42
25
|
// ResetFunctions
|
|
43
26
|
// ------------------------------------------------------------------
|
|
44
27
|
export function ResetFunctions() {
|
|
45
|
-
|
|
46
|
-
names.clear();
|
|
47
|
-
funcs.clear();
|
|
28
|
+
functions.clear();
|
|
48
29
|
}
|
|
49
30
|
// ------------------------------------------------------------------
|
|
50
31
|
// GetFunctions
|
|
51
32
|
// ------------------------------------------------------------------
|
|
52
33
|
export function GetFunctions() {
|
|
53
|
-
return [...
|
|
34
|
+
return [...functions.values()];
|
|
54
35
|
}
|
|
55
36
|
// ------------------------------------------------------------------
|
|
56
37
|
// CreateFunction
|
|
57
38
|
// ------------------------------------------------------------------
|
|
58
39
|
export function CreateFunction(stack, context, schema, value) {
|
|
59
|
-
const
|
|
60
|
-
const call = CreateCallExpression(context, schema,
|
|
61
|
-
if (
|
|
40
|
+
const hash = Schema.IsSchemaObject(schema) ? Hashing.Hash({ __baseURL: stack.BaseURL().href, ...schema }) : Hashing.Hash(schema);
|
|
41
|
+
const call = CreateCallExpression(context, schema, hash, value);
|
|
42
|
+
if (functions.has(hash))
|
|
62
43
|
return call;
|
|
63
|
-
|
|
64
|
-
|
|
44
|
+
functions.set(hash, '');
|
|
45
|
+
functions.set(hash, CreateFunctionExpression(stack, context, schema, hash));
|
|
65
46
|
return call;
|
|
66
47
|
}
|
|
@@ -9,8 +9,3 @@ export declare function ReadonlyObjectDeferred<Type extends TSchema>(type: Type,
|
|
|
9
9
|
export type TReadonlyObject<Type extends TSchema> = (TReadonlyObjectAction<Type>);
|
|
10
10
|
/** This type is an alias for TypeScript's `Readonly<T>` utility type. It will make all properties of a TObject readonly or marks an TArray or TTuple as immutable `readonly T[]`. */
|
|
11
11
|
export declare function ReadonlyObject<Type extends TSchema>(type: Type, options?: TSchemaOptions): TReadonlyObject<Type>;
|
|
12
|
-
/**
|
|
13
|
-
* This type has been renamed to ReadonlyObject.
|
|
14
|
-
* @deprecated
|
|
15
|
-
*/
|
|
16
|
-
export declare const ReadonlyType: typeof ReadonlyObject;
|
|
@@ -9,11 +9,3 @@ export function ReadonlyObjectDeferred(type, options = {}) {
|
|
|
9
9
|
export function ReadonlyObject(type, options = {}) {
|
|
10
10
|
return ReadonlyObjectAction(type, options);
|
|
11
11
|
}
|
|
12
|
-
// ------------------------------------------------------------------
|
|
13
|
-
// Alias
|
|
14
|
-
// ------------------------------------------------------------------
|
|
15
|
-
/**
|
|
16
|
-
* This type has been renamed to ReadonlyObject.
|
|
17
|
-
* @deprecated
|
|
18
|
-
*/
|
|
19
|
-
export const ReadonlyType = ReadonlyObject;
|
|
@@ -19,7 +19,7 @@ export { Omit, type TOmit, type TOmitDeferred } from './type/action/omit.mjs';
|
|
|
19
19
|
export { Parameters, type TParameters, type TParametersDeferred } from './type/action/parameters.mjs';
|
|
20
20
|
export { Partial, type TPartial, type TPartialDeferred } from './type/action/partial.mjs';
|
|
21
21
|
export { Pick, type TPick, type TPickDeferred } from './type/action/pick.mjs';
|
|
22
|
-
export { ReadonlyObject,
|
|
22
|
+
export { ReadonlyObject, type TReadonlyObject, type TReadonlyObjectDeferred } from './type/action/readonly_object.mjs';
|
|
23
23
|
export { Required, type TRequired, type TRequiredDeferred } from './type/action/required.mjs';
|
|
24
24
|
export { ReturnType, type TReturnType, type TReturnTypeDeferred } from './type/action/return_type.mjs';
|
|
25
25
|
export { type TUncapitalize, type TUncapitalizeDeferred, Uncapitalize } from './type/action/uncapitalize.mjs';
|
|
@@ -31,7 +31,7 @@ export { Omit } from './type/action/omit.mjs';
|
|
|
31
31
|
export { Parameters } from './type/action/parameters.mjs';
|
|
32
32
|
export { Partial } from './type/action/partial.mjs';
|
|
33
33
|
export { Pick } from './type/action/pick.mjs';
|
|
34
|
-
export { ReadonlyObject
|
|
34
|
+
export { ReadonlyObject } from './type/action/readonly_object.mjs';
|
|
35
35
|
export { Required } from './type/action/required.mjs';
|
|
36
36
|
export { ReturnType } from './type/action/return_type.mjs';
|
|
37
37
|
export { Uncapitalize } from './type/action/uncapitalize.mjs';
|
|
@@ -111,24 +111,27 @@ type User = Type.Static<typeof User> // type User = {
|
|
|
111
111
|
|
|
112
112
|
## Script
|
|
113
113
|
|
|
114
|
-
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview) | [Example 1](https://www.typescriptlang.org/play/?target=99&module=7#code/
|
|
114
|
+
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview) | [Example 1](https://www.typescriptlang.org/play/?target=99&module=7#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFonmXW32POv3b7k0AdAGUAxlGBgYACjwC5eAJS9G3VWvXdqdOADkAhiFQBnMHpGpKIiADsj8ALJ6YACzgBeREWFiJ0gAaUcHCEaHAAaqgiMNAATO5wAN5wZABccNYAriDEqFAANHBIaZnZuXAAvoHBROGR0VAAzPEAogBuegA2GU6oADwRUbFwAGSJcABexVk5UBUAfFUh6AP1ACwt7V09-XXQTaNJAO5TpbPlC35KygAiqGjWACao1vD6hiZmFla28En2xq5yvF+KhvOJJFIknIBI4XBUCn4gosahFYKgyPEElUgpAjMAYMAbGkVtBVnlseloCBOsTdo1yUEghlWrTBlAYlVKkElnAAOKoHCoGBQJCYimtXIE8xGWlosgAbQAugzGcBHsBpScZkrOcjQrDcsBOmLGXADMRgM8YKy1iqgg9gBgMBkjKgbaS7XATJEMh09FB3VBVrruTV-kZXB4saaAOYCwzCop8+NCkWe6kwQ00uAG8SdXWXLT0ABKGReoHQxdQGA6dUJ1ko4ecAjA2DQsEtRgEccFiZbbclnYEEo70oE+NQIC7rYg7YJxhbEDxBJs-dng4XZEbALXc6HPYTIt3G67I6lC4nU+PHYX1ipnWv867W6bj-3Kb7M73C7PGovmavL8TwEZk303bcIzArsMyzDooIEB0nRdUEgJvZ8IObVCnwEGC8zgrCh3NS0Xngl8dwIhdcKNfCBzQgRvREX1-VIos4CEGAnA1OAAElrAwXJnnMShnWsKJ6zgKBnieKApHeZw0hBYQOKlXolggDAcwBOYFESKo5O7D8j1-aV5QABkVRdl3rAQtyCfSD1TJBh0HEzzIEO8oGpODbLgezDKc4zjDMizQJ8-SqIfRDnVdGy9J3CK4KIq1Yrs+Kejw+i0EYv0oFi8ogA) | [Example 2](https://www.typescriptlang.org/play/?target=99&module=7#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFonmXW32POv3b7k0AdACpejbuImTu1OnAByAQxCoAzmAUBjVJQB2S1eq1wAsgpgALOAG9KcOKjKRYcDRB0r4ANVQaY0AExwALyIRAIA8sQAVj4wABRWcGQAXKGCcgCuIMSoUHEAlAA0cEip-KgCmdm5BXAAvvm29o7Q8K7uXrHQAMzBaRUAogBuCgA2GWaoceUCAJI6MLkqsXEA2t6+AcUzkTG+CXAAXmVhVTl5+fX5ALr5jXYOTm1uHnAbflAALH0zw2MTi2mYXmiygy326y6UG62zCuxWiQA7id0llzrUGrdGnUZPQACKoNA6AAmqAW8n0ak02nar28sAcPzh0QRTUgKmAMGAblSpgsAne0E+hSaOmgIDGvLM5gFUJhTQyQyl-MFUH8lAalFp8AA4qgcKgYFAkEzBPD9jY7ENclytCoURUAIJQKAKJBxemLMhFJrAEnAO0OgTO13umZnGp3DWNbUmSZQYBjU0Vc3xS1wJTEYBkmDKmWq4VNYnADAYDLLPOyzZfEV2NQ+DKjBRQSsF6Nal7wYyqSwhHYsi1NADm+uURtKcD1BvHtbgEtBidGytyi-bogAShkFqB0OvUBhRrFuTpKN2VDKwNg0LBsyoBCPp8aBJeINeuaoBNab3aBJzUCA7xfN9b2fCAOS5NxnyvG0QLIU8eyg18YI-B8xyfIDkLvL9bQ-P8AMQ4CPzFKAJVGAjMIEOCzwvaCbxQ0dDXQ2j3ywmCfzwwDmJAxVyLou8qIQjC+IEecVzGXiWIEYtS3LCohMkgTzwkkDRITcT5JAzNswWZSP0UmikOE1TF10u96w0Rtm1MyjcTgABlGAzADOB5gwXIyS0Sgyx0XxjzgKAyVJPJlHPIMHKcjQAB5CDQCAMBMHsAD5LnTEKZVQxikE-NjVFWAAGa5QPA48bLsNL7wY8dsu-XKCoEYjSNKucEIyqrsIDWrCp4uCyoQ4zxOkstlia8r+rIrScxGvr4xM8zLKgGy6iAA) | [Challenge](test/typescript/readme.md)
|
|
115
|
+
|
|
116
|
+
TypeBox includes a syntax engine that can transform TypeScript declarations into JSON Schema. The engine is a full syntactic frontend to Type.* and supports many advanced type-level constructs such as Conditional, Mapped, Indexed, Infer, Generics, Distributed types and more. This feature is implemented symmetrically at runtime and statically via TypeScript Template Literal types.
|
|
117
|
+
|
|
118
|
+
Syntax highlighting is available via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=sinclairzx81.typebox-script)
|
|
115
119
|
|
|
116
|
-
TypeBox includes a runtime scripting engine that can transform TypeScript definitions into JSON Schema. The engine is implemented symmetrically at runtime and inside TypeScript's type system. It supports many programmable type-level constructs such as Conditional, Mapped, Indexed, Generic, Distributive Conditional, and more. The engine is designed for TypeScript 7 but is supported in TypeScript 5 and above.
|
|
117
120
|
|
|
118
121
|
### Example
|
|
119
122
|
|
|
120
|
-
|
|
123
|
+
The following uses Script to parse TypeScript declarations into JSON Schema.
|
|
121
124
|
|
|
122
125
|
```typescript
|
|
123
126
|
// Module
|
|
124
127
|
const Math = Type.Script(`
|
|
125
128
|
type Vector2 = { x: number, y: number }
|
|
126
|
-
type Vector3 =
|
|
127
|
-
type Vector4 =
|
|
129
|
+
type Vector3 = Evaluate<Vector2 & { z: number }>
|
|
130
|
+
type Vector4 = Evaluate<Vector3 & { w: number }>
|
|
128
131
|
`)
|
|
129
132
|
|
|
130
133
|
// Dependent Module
|
|
131
|
-
const { Mesh } = Type.Script(Math, `
|
|
134
|
+
const { Mesh } = Type.Script({ ...Math }, `
|
|
132
135
|
type Vertex = {
|
|
133
136
|
position: Vector4,
|
|
134
137
|
normal: Vector3,
|
|
@@ -295,29 +298,29 @@ The following table shows compile performance for various JSON Schema structures
|
|
|
295
298
|
┌──────────────────────┬─────────────┬─────────────┐
|
|
296
299
|
│ Compile │ TB1X │ AJV8 │
|
|
297
300
|
├──────────────────────┼─────────────┼─────────────┤
|
|
298
|
-
│ Boolean │
|
|
299
|
-
│ Number │
|
|
300
|
-
│ String │
|
|
301
|
-
│ Null │
|
|
302
|
-
│ Literal_String │
|
|
303
|
-
│ Literal_Number │
|
|
304
|
-
│ Literal_Boolean │
|
|
305
|
-
│ Pattern │
|
|
306
|
-
│ Object_Open │
|
|
307
|
-
│ Object_Close │
|
|
308
|
-
│ Object_Vector3 │
|
|
309
|
-
│ Object_Basis3 │
|
|
310
|
-
│ Intersect_And │
|
|
311
|
-
│ Intersect_Structural │
|
|
312
|
-
│ Union_Or │
|
|
313
|
-
│ Union_Structural │
|
|
314
|
-
│ Tuple_Values │
|
|
315
|
-
│ Tuple_Objects │
|
|
316
|
-
│ Array_Numbers_4 │
|
|
317
|
-
│ Array_Numbers_8 │
|
|
318
|
-
│ Array_Numbers_16 │
|
|
319
|
-
│ Array_Objects_Open │
|
|
320
|
-
│ Array_Objects_Close │
|
|
301
|
+
│ Boolean │ 29.2K ops/s │ 7.1K ops/s │
|
|
302
|
+
│ Number │ 34.5K ops/s │ 7.6K ops/s │
|
|
303
|
+
│ String │ 48.9K ops/s │ 8.7K ops/s │
|
|
304
|
+
│ Null │ 39.6K ops/s │ 7.6K ops/s │
|
|
305
|
+
│ Literal_String │ 46.8K ops/s │ 6.8K ops/s │
|
|
306
|
+
│ Literal_Number │ 48.3K ops/s │ 7.4K ops/s │
|
|
307
|
+
│ Literal_Boolean │ 48.8K ops/s │ 7.3K ops/s │
|
|
308
|
+
│ Pattern │ 32.5K ops/s │ 6.1K ops/s │
|
|
309
|
+
│ Object_Open │ 6.6K ops/s │ 1.4K ops/s │
|
|
310
|
+
│ Object_Close │ 7.6K ops/s │ 1K ops/s │
|
|
311
|
+
│ Object_Vector3 │ 20.8K ops/s │ 2.8K ops/s │
|
|
312
|
+
│ Object_Basis3 │ 7.5K ops/s │ 1K ops/s │
|
|
313
|
+
│ Intersect_And │ 23K ops/s │ 3.9K ops/s │
|
|
314
|
+
│ Intersect_Structural │ 8.7K ops/s │ 1.2K ops/s │
|
|
315
|
+
│ Union_Or │ 17.9K ops/s │ 3.4K ops/s │
|
|
316
|
+
│ Union_Structural │ 11.3K ops/s │ 2.1K ops/s │
|
|
317
|
+
│ Tuple_Values │ 9.6K ops/s │ 2.1K ops/s │
|
|
318
|
+
│ Tuple_Objects │ 2.1K ops/s │ 350 ops/s │
|
|
319
|
+
│ Array_Numbers_4 │ 33.6K ops/s │ 4.2K ops/s │
|
|
320
|
+
│ Array_Numbers_8 │ 39K ops/s │ 3.7K ops/s │
|
|
321
|
+
│ Array_Numbers_16 │ 29.6K ops/s │ 3.8K ops/s │
|
|
322
|
+
│ Array_Objects_Open │ 7.7K ops/s │ 833 ops/s │
|
|
323
|
+
│ Array_Objects_Close │ 7.6K ops/s │ 860 ops/s │
|
|
321
324
|
└──────────────────────┴─────────────┴─────────────┘
|
|
322
325
|
```
|
|
323
326
|
|
package/openclaw.plugin.json
CHANGED
|
@@ -35,9 +35,12 @@
|
|
|
35
35
|
},
|
|
36
36
|
"contracts": {
|
|
37
37
|
"webFetchProviders": ["firecrawl"],
|
|
38
|
-
"webSearchProviders": ["firecrawl"
|
|
38
|
+
"webSearchProviders": ["firecrawl"],
|
|
39
39
|
"tools": ["firecrawl_search", "firecrawl_scrape"]
|
|
40
40
|
},
|
|
41
|
+
"configContracts": {
|
|
42
|
+
"compatibilityRuntimePaths": ["tools.web.search.apiKey"]
|
|
43
|
+
},
|
|
41
44
|
"configSchema": {
|
|
42
45
|
"type": "object",
|
|
43
46
|
"additionalProperties": false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/firecrawl-plugin",
|
|
3
|
-
"version": "2026.7.
|
|
3
|
+
"version": "2026.7.34",
|
|
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.3"
|
|
12
12
|
},
|
|
13
13
|
"openclaw": {
|
|
14
14
|
"extensions": [
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"minHostVersion": ">=2026.6.8"
|
|
22
22
|
},
|
|
23
23
|
"compat": {
|
|
24
|
-
"pluginApi": ">=2026.7.
|
|
24
|
+
"pluginApi": ">=2026.7.34"
|
|
25
25
|
},
|
|
26
26
|
"build": {
|
|
27
|
-
"openclawVersion": "2026.7.
|
|
27
|
+
"openclawVersion": "2026.7.34",
|
|
28
28
|
"bundledDist": false
|
|
29
29
|
},
|
|
30
30
|
"release": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"README.md"
|
|
42
42
|
],
|
|
43
43
|
"peerDependencies": {
|
|
44
|
-
"openclaw": ">=2026.7.
|
|
44
|
+
"openclaw": ">=2026.7.34"
|
|
45
45
|
},
|
|
46
46
|
"peerDependenciesMeta": {
|
|
47
47
|
"openclaw": {
|
|
@@ -1,71 +0,0 @@
|
|
|
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-DZohiNQK.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-DZohiNQK.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 };
|