@openclaw/brave-plugin 2026.8.1-beta.2 → 2026.8.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/{brave-web-search-provider-BFrhKp8F.js → brave-web-search-provider-B1n-hEjq.js} +2 -2
- package/dist/{brave-web-search-provider.runtime-DqLOemiz.js → brave-web-search-provider.runtime-Bal1W8k7.js} +148 -182
- package/dist/index.js +1 -1
- package/dist/web-search-contract-api.js +2 -10
- package/dist/web-search-provider.js +1 -1
- package/package.json +4 -4
package/dist/{brave-web-search-provider-BFrhKp8F.js → brave-web-search-provider-B1n-hEjq.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { buildBraveWebSearchProviderBase } from "./web-search-shared.js";
|
|
2
|
-
import { isDiagnosticFlagEnabled } from "openclaw/plugin-sdk/diagnostic-
|
|
2
|
+
import { isDiagnosticFlagEnabled } from "openclaw/plugin-sdk/diagnostic-flags";
|
|
3
3
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
4
4
|
import { mergeScopedSearchConfig, resolveProviderWebSearchPluginConfig } from "openclaw/plugin-sdk/provider-web-search-config-contract";
|
|
5
5
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
@@ -8,7 +8,7 @@ import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
|
8
8
|
* Brave web-search provider factory. It builds the agent tool definition and
|
|
9
9
|
* lazy-loads HTTP execution only when a search is run.
|
|
10
10
|
*/
|
|
11
|
-
const loadBraveWebSearchRuntime = createLazyRuntimeModule(() => import("./brave-web-search-provider.runtime-
|
|
11
|
+
const loadBraveWebSearchRuntime = createLazyRuntimeModule(() => import("./brave-web-search-provider.runtime-Bal1W8k7.js"));
|
|
12
12
|
const BraveSearchSchema = {
|
|
13
13
|
type: "object",
|
|
14
14
|
properties: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
+
import { buildTimeoutAbortSignal } from "openclaw/plugin-sdk/extension-shared";
|
|
2
3
|
import { assertOkOrThrowProviderError, readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
|
|
3
|
-
import { DEFAULT_SEARCH_COUNT, MAX_SEARCH_COUNT, buildSearchCacheKey, formatCliCommand, parseWebSearchTimeFilters, readCachedSearchPayload, readConfiguredSecretString, readPositiveIntegerParam, readProviderEnvValue, readStringParam, resolveSearchCacheTtlMs, resolveSearchCount, resolveSearchTimeoutSeconds, resolveSiteName,
|
|
4
|
+
import { DEFAULT_SEARCH_COUNT, MAX_SEARCH_COUNT, buildSearchCacheKey, formatCliCommand, parseWebSearchTimeFilters, readCachedSearchPayload, readConfiguredSecretString, readPositiveIntegerParam, readProviderEnvValue, readStringParam, resolveSearchCacheTtlMs, resolveSearchCount, resolveSearchTimeoutSeconds, resolveSiteName, withSelfHostedWebToolsEndpoint, withTrustedWebToolsEndpoint, wrapWebContent, writeCachedSearchPayload } from "openclaw/plugin-sdk/provider-web-search";
|
|
4
5
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
5
6
|
import { assertHttpUrlTargetsPrivateNetwork, isBlockedHostnameOrIp, isPrivateIpAddress, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
6
7
|
//#region extensions/brave/src/brave-web-search-provider.shared.ts
|
|
@@ -165,21 +166,13 @@ function normalizeBraveLanguageParams(params) {
|
|
|
165
166
|
ui_lang
|
|
166
167
|
};
|
|
167
168
|
}
|
|
168
|
-
function resolveSiteName$1(url) {
|
|
169
|
-
if (!url) return;
|
|
170
|
-
try {
|
|
171
|
-
return new URL(url).hostname;
|
|
172
|
-
} catch {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
169
|
/** Map Brave LLM Context API grounding results into web-search result rows. */
|
|
177
170
|
function mapBraveLlmContextResults(data) {
|
|
178
171
|
return (Array.isArray(data.grounding?.generic) ? data.grounding.generic : []).map((entry) => ({
|
|
179
172
|
url: entry.url ?? "",
|
|
180
173
|
title: entry.title ?? "",
|
|
181
174
|
snippets: (entry.snippets ?? []).filter((snippet) => typeof snippet === "string" && snippet.length > 0),
|
|
182
|
-
siteName: resolveSiteName
|
|
175
|
+
siteName: resolveSiteName(entry.url) || void 0
|
|
183
176
|
}));
|
|
184
177
|
}
|
|
185
178
|
//#endregion
|
|
@@ -196,13 +189,6 @@ function logBraveHttp(diagnostics, event, meta) {
|
|
|
196
189
|
if (!diagnostics?.enabled) return;
|
|
197
190
|
braveHttpLogger.info(`brave http ${event}`, meta);
|
|
198
191
|
}
|
|
199
|
-
function describeBraveRequestUrl(url) {
|
|
200
|
-
return {
|
|
201
|
-
url: url.toString(),
|
|
202
|
-
query: url.searchParams.get("q") ?? "",
|
|
203
|
-
params: Object.fromEntries(url.searchParams.entries())
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
192
|
function resolveBraveApiKey(searchConfig) {
|
|
207
193
|
return readConfiguredSecretString(searchConfig?.apiKey, "plugins.entries.brave.config.webSearch.apiKey") ?? readProviderEnvValue(["BRAVE_API_KEY"]);
|
|
208
194
|
}
|
|
@@ -215,18 +201,22 @@ function buildBraveEndpointUrl(params) {
|
|
|
215
201
|
url.search = "";
|
|
216
202
|
return url;
|
|
217
203
|
}
|
|
218
|
-
async function braveEndpointTargetsPrivateNetwork(url) {
|
|
204
|
+
async function braveEndpointTargetsPrivateNetwork(url, signal) {
|
|
219
205
|
if (isBlockedHostnameOrIp(url.hostname)) return true;
|
|
220
206
|
try {
|
|
221
|
-
return (await resolvePinnedHostnameWithPolicy(url.hostname, {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
207
|
+
return (await resolvePinnedHostnameWithPolicy(url.hostname, {
|
|
208
|
+
signal,
|
|
209
|
+
policy: {
|
|
210
|
+
allowPrivateNetwork: true,
|
|
211
|
+
allowRfc2544BenchmarkRange: true
|
|
212
|
+
}
|
|
213
|
+
})).addresses.every((address) => isPrivateIpAddress(address));
|
|
225
214
|
} catch {
|
|
215
|
+
signal?.throwIfAborted();
|
|
226
216
|
return false;
|
|
227
217
|
}
|
|
228
218
|
}
|
|
229
|
-
async function validateBraveBaseUrl(baseUrl) {
|
|
219
|
+
async function validateBraveBaseUrl(baseUrl, signal) {
|
|
230
220
|
let parsed;
|
|
231
221
|
try {
|
|
232
222
|
parsed = new URL(baseUrl);
|
|
@@ -236,12 +226,13 @@ async function validateBraveBaseUrl(baseUrl) {
|
|
|
236
226
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new Error("Brave Search base URL must use http:// or https://.");
|
|
237
227
|
if (parsed.protocol === "http:") {
|
|
238
228
|
await assertHttpUrlTargetsPrivateNetwork(parsed.toString(), {
|
|
229
|
+
signal,
|
|
239
230
|
dangerouslyAllowPrivateNetwork: true,
|
|
240
231
|
errorMessage: "Brave Search HTTP base URL must target a trusted private or loopback host. Use https:// for public hosts."
|
|
241
232
|
});
|
|
242
233
|
return "selfHosted";
|
|
243
234
|
}
|
|
244
|
-
return await braveEndpointTargetsPrivateNetwork(parsed) ? "selfHosted" : "strict";
|
|
235
|
+
return await braveEndpointTargetsPrivateNetwork(parsed, signal) ? "selfHosted" : "strict";
|
|
245
236
|
}
|
|
246
237
|
function missingBraveKeyPayload() {
|
|
247
238
|
return {
|
|
@@ -267,12 +258,13 @@ async function runBraveJsonRequest(params, errorLabel) {
|
|
|
267
258
|
params.configureUrl(url);
|
|
268
259
|
logBraveHttp(params.diagnostics, "request", {
|
|
269
260
|
mode: params.mode,
|
|
270
|
-
|
|
261
|
+
url: url.toString(),
|
|
262
|
+
query: url.searchParams.get("q") ?? "",
|
|
263
|
+
params: Object.fromEntries(url.searchParams.entries())
|
|
271
264
|
});
|
|
272
265
|
const startedAt = Date.now();
|
|
273
|
-
return (params.endpointMode === "selfHosted" ?
|
|
266
|
+
return (params.endpointMode === "selfHosted" ? withSelfHostedWebToolsEndpoint : withTrustedWebToolsEndpoint)({
|
|
274
267
|
url: url.toString(),
|
|
275
|
-
timeoutSeconds: params.timeoutSeconds,
|
|
276
268
|
signal: params.signal,
|
|
277
269
|
init: {
|
|
278
270
|
method: "GET",
|
|
@@ -281,7 +273,7 @@ async function runBraveJsonRequest(params, errorLabel) {
|
|
|
281
273
|
"X-Subscription-Token": params.apiKey
|
|
282
274
|
}
|
|
283
275
|
}
|
|
284
|
-
}, async (response) => {
|
|
276
|
+
}, async ({ response }) => {
|
|
285
277
|
logBraveHttp(params.diagnostics, "response", {
|
|
286
278
|
mode: params.mode,
|
|
287
279
|
status: response.status,
|
|
@@ -294,14 +286,9 @@ async function runBraveJsonRequest(params, errorLabel) {
|
|
|
294
286
|
}
|
|
295
287
|
async function runBraveLlmContextSearch(params) {
|
|
296
288
|
const data = await runBraveJsonRequest({
|
|
297
|
-
|
|
289
|
+
...params,
|
|
298
290
|
endpointPath: BRAVE_LLM_CONTEXT_ENDPOINT_PATH,
|
|
299
291
|
mode: "llm-context",
|
|
300
|
-
endpointMode: params.endpointMode,
|
|
301
|
-
apiKey: params.apiKey,
|
|
302
|
-
timeoutSeconds: params.timeoutSeconds,
|
|
303
|
-
diagnostics: params.diagnostics,
|
|
304
|
-
signal: params.signal,
|
|
305
292
|
configureUrl: (url) => {
|
|
306
293
|
setBraveSearchUrlParams(url, params);
|
|
307
294
|
}
|
|
@@ -313,14 +300,9 @@ async function runBraveLlmContextSearch(params) {
|
|
|
313
300
|
}
|
|
314
301
|
async function runBraveWebSearch(params) {
|
|
315
302
|
const data = await runBraveJsonRequest({
|
|
316
|
-
|
|
303
|
+
...params,
|
|
317
304
|
endpointPath: BRAVE_SEARCH_ENDPOINT_PATH,
|
|
318
305
|
mode: "web",
|
|
319
|
-
endpointMode: params.endpointMode,
|
|
320
|
-
apiKey: params.apiKey,
|
|
321
|
-
timeoutSeconds: params.timeoutSeconds,
|
|
322
|
-
diagnostics: params.diagnostics,
|
|
323
|
-
signal: params.signal,
|
|
324
306
|
configureUrl: (url) => {
|
|
325
307
|
setBraveSearchUrlParams(url, {
|
|
326
308
|
...params,
|
|
@@ -350,123 +332,146 @@ async function executeBraveSearch(args, searchConfig, options) {
|
|
|
350
332
|
const braveConfig = resolveBraveConfig(searchConfig);
|
|
351
333
|
const braveMode = resolveBraveMode(braveConfig);
|
|
352
334
|
const braveBaseUrl = resolveBraveBaseUrl(braveConfig);
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}) ?? searchConfig?.maxResults ?? void 0;
|
|
359
|
-
const country = normalizeBraveCountry(readStringParam(args, "country"));
|
|
360
|
-
const language = readStringParam(args, "language");
|
|
361
|
-
const search_lang = readStringParam(args, "search_lang");
|
|
362
|
-
const ui_lang = readStringParam(args, "ui_lang");
|
|
363
|
-
const normalizedLanguage = normalizeBraveLanguageParams({
|
|
364
|
-
search_lang: search_lang || language,
|
|
365
|
-
ui_lang
|
|
366
|
-
});
|
|
367
|
-
if (normalizedLanguage.invalidField === "search_lang") return {
|
|
368
|
-
error: "invalid_search_lang",
|
|
369
|
-
message: "search_lang must be a Brave-supported language code like 'en', 'en-gb', 'zh-hans', or 'zh-hant'.",
|
|
370
|
-
docs: "https://docs.openclaw.ai/tools/web"
|
|
371
|
-
};
|
|
372
|
-
if (normalizedLanguage.invalidField === "ui_lang") return {
|
|
373
|
-
error: "invalid_ui_lang",
|
|
374
|
-
message: "ui_lang must be a language-region locale like 'en-US'.",
|
|
375
|
-
docs: "https://docs.openclaw.ai/tools/web"
|
|
376
|
-
};
|
|
377
|
-
if (normalizedLanguage.ui_lang && braveMode === "llm-context") return {
|
|
378
|
-
error: "unsupported_ui_lang",
|
|
379
|
-
message: "ui_lang is not supported by Brave llm-context mode. Remove ui_lang or use Brave web mode for locale-based UI hints.",
|
|
380
|
-
docs: "https://docs.openclaw.ai/tools/web"
|
|
381
|
-
};
|
|
382
|
-
const rawFreshness = readStringParam(args, "freshness");
|
|
383
|
-
const parsedTimeFilters = parseWebSearchTimeFilters({
|
|
384
|
-
rawDateAfter: readStringParam(args, "date_after"),
|
|
385
|
-
rawDateBefore: readStringParam(args, "date_before"),
|
|
386
|
-
rawFreshness,
|
|
387
|
-
freshnessProvider: "brave",
|
|
388
|
-
invalidFreshnessMessage: "freshness must be day, week, month, or year.",
|
|
389
|
-
invalidDateAfterMessage: "date_after must be YYYY-MM-DD format.",
|
|
390
|
-
invalidDateBeforeMessage: "date_before must be YYYY-MM-DD format.",
|
|
391
|
-
invalidDateRangeMessage: "date_after must be before date_before."
|
|
335
|
+
const { signal, cleanup } = buildTimeoutAbortSignal({
|
|
336
|
+
timeoutMs: resolveSearchTimeoutSeconds(searchConfig) * 1e3,
|
|
337
|
+
signal: options?.signal,
|
|
338
|
+
operation: "brave.web_search",
|
|
339
|
+
url: braveBaseUrl
|
|
392
340
|
});
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
341
|
+
try {
|
|
342
|
+
signal?.throwIfAborted();
|
|
343
|
+
const braveEndpointMode = await validateBraveBaseUrl(braveBaseUrl, signal);
|
|
344
|
+
signal?.throwIfAborted();
|
|
345
|
+
const query = readStringParam(args, "query", { required: true });
|
|
346
|
+
const count = readPositiveIntegerParam(args, "count", {
|
|
347
|
+
max: MAX_SEARCH_COUNT,
|
|
348
|
+
message: `count must be an integer from 1 to ${MAX_SEARCH_COUNT}.`
|
|
349
|
+
}) ?? searchConfig?.maxResults ?? void 0;
|
|
350
|
+
const country = normalizeBraveCountry(readStringParam(args, "country"));
|
|
351
|
+
const language = readStringParam(args, "language");
|
|
352
|
+
const search_lang = readStringParam(args, "search_lang");
|
|
353
|
+
const ui_lang = readStringParam(args, "ui_lang");
|
|
354
|
+
const normalizedLanguage = normalizeBraveLanguageParams({
|
|
355
|
+
search_lang: search_lang || language,
|
|
356
|
+
ui_lang
|
|
357
|
+
});
|
|
358
|
+
if (normalizedLanguage.invalidField === "search_lang") return {
|
|
359
|
+
error: "invalid_search_lang",
|
|
360
|
+
message: "search_lang must be a Brave-supported language code like 'en', 'en-gb', 'zh-hans', or 'zh-hant'.",
|
|
400
361
|
docs: "https://docs.openclaw.ai/tools/web"
|
|
401
362
|
};
|
|
402
|
-
if (
|
|
403
|
-
error: "
|
|
404
|
-
message: "
|
|
363
|
+
if (normalizedLanguage.invalidField === "ui_lang") return {
|
|
364
|
+
error: "invalid_ui_lang",
|
|
365
|
+
message: "ui_lang must be a language-region locale like 'en-US'.",
|
|
405
366
|
docs: "https://docs.openclaw.ai/tools/web"
|
|
406
367
|
};
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
368
|
+
if (normalizedLanguage.ui_lang && braveMode === "llm-context") return {
|
|
369
|
+
error: "unsupported_ui_lang",
|
|
370
|
+
message: "ui_lang is not supported by Brave llm-context mode. Remove ui_lang or use Brave web mode for locale-based UI hints.",
|
|
371
|
+
docs: "https://docs.openclaw.ai/tools/web"
|
|
372
|
+
};
|
|
373
|
+
const rawFreshness = readStringParam(args, "freshness");
|
|
374
|
+
const parsedTimeFilters = parseWebSearchTimeFilters({
|
|
375
|
+
rawDateAfter: readStringParam(args, "date_after"),
|
|
376
|
+
rawDateBefore: readStringParam(args, "date_before"),
|
|
377
|
+
rawFreshness,
|
|
378
|
+
freshnessProvider: "brave",
|
|
379
|
+
invalidFreshnessMessage: "freshness must be day, week, month, or year.",
|
|
380
|
+
invalidDateAfterMessage: "date_after must be YYYY-MM-DD format.",
|
|
381
|
+
invalidDateBeforeMessage: "date_before must be YYYY-MM-DD format.",
|
|
382
|
+
invalidDateRangeMessage: "date_after must be before date_before."
|
|
383
|
+
});
|
|
384
|
+
if ("error" in parsedTimeFilters) return parsedTimeFilters;
|
|
385
|
+
const { freshness, dateAfter, dateBefore } = parsedTimeFilters;
|
|
386
|
+
if (braveMode === "llm-context") {
|
|
387
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
388
|
+
if (dateAfter && !dateBefore && dateAfter > today) return {
|
|
389
|
+
error: "invalid_date_range",
|
|
390
|
+
message: "date_after cannot be in the future for Brave llm-context mode.",
|
|
391
|
+
docs: "https://docs.openclaw.ai/tools/web"
|
|
392
|
+
};
|
|
393
|
+
if (dateBefore && !dateAfter) return {
|
|
394
|
+
error: "unsupported_date_filter",
|
|
395
|
+
message: "Brave llm-context mode requires date_after when date_before is set. Use a bounded date range or freshness.",
|
|
396
|
+
docs: "https://docs.openclaw.ai/tools/web"
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
const llmContextDateEnd = braveMode === "llm-context" && dateAfter ? dateBefore ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10) : dateBefore;
|
|
400
|
+
const cacheKey = buildSearchCacheKey(braveMode === "llm-context" ? [
|
|
401
|
+
"brave",
|
|
402
|
+
braveMode,
|
|
403
|
+
braveBaseUrl,
|
|
404
|
+
query,
|
|
405
|
+
country,
|
|
406
|
+
normalizedLanguage.search_lang,
|
|
407
|
+
freshness,
|
|
408
|
+
dateAfter,
|
|
409
|
+
llmContextDateEnd
|
|
410
|
+
] : [
|
|
411
|
+
"brave",
|
|
412
|
+
braveMode,
|
|
413
|
+
braveBaseUrl,
|
|
414
|
+
query,
|
|
415
|
+
resolveSearchCount(count, DEFAULT_SEARCH_COUNT),
|
|
416
|
+
country,
|
|
417
|
+
normalizedLanguage.search_lang,
|
|
418
|
+
normalizedLanguage.ui_lang,
|
|
419
|
+
freshness,
|
|
420
|
+
dateAfter,
|
|
421
|
+
dateBefore
|
|
422
|
+
]);
|
|
423
|
+
const diagnostics = { enabled: options?.diagnosticsEnabled === true };
|
|
424
|
+
const cacheTtlMs = resolveSearchCacheTtlMs(searchConfig);
|
|
425
|
+
const cached = readCachedSearchPayload(cacheKey, cacheTtlMs);
|
|
426
|
+
if (cached) {
|
|
427
|
+
logBraveHttp(diagnostics, "cache hit", {
|
|
428
|
+
mode: braveMode,
|
|
429
|
+
query,
|
|
430
|
+
cacheKey
|
|
431
|
+
});
|
|
432
|
+
return cached;
|
|
433
|
+
}
|
|
434
|
+
logBraveHttp(diagnostics, "cache miss", {
|
|
436
435
|
mode: braveMode,
|
|
437
436
|
query,
|
|
438
437
|
cacheKey
|
|
439
438
|
});
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
logBraveHttp(diagnostics, "cache miss", {
|
|
443
|
-
mode: braveMode,
|
|
444
|
-
query,
|
|
445
|
-
cacheKey
|
|
446
|
-
});
|
|
447
|
-
const start = Date.now();
|
|
448
|
-
const timeoutSeconds = resolveSearchTimeoutSeconds(searchConfig);
|
|
449
|
-
const cacheTtlMs = resolveSearchCacheTtlMs(searchConfig);
|
|
450
|
-
if (braveMode === "llm-context") {
|
|
451
|
-
const { results, sources } = await runBraveLlmContextSearch({
|
|
439
|
+
const start = Date.now();
|
|
440
|
+
const request = {
|
|
452
441
|
baseUrl: braveBaseUrl,
|
|
453
442
|
endpointMode: braveEndpointMode,
|
|
454
443
|
query,
|
|
455
444
|
apiKey,
|
|
456
|
-
timeoutSeconds,
|
|
457
445
|
diagnostics,
|
|
458
|
-
signal
|
|
446
|
+
signal,
|
|
459
447
|
country: country ?? void 0,
|
|
460
448
|
search_lang: normalizedLanguage.search_lang,
|
|
461
449
|
freshness,
|
|
462
450
|
dateAfter,
|
|
463
451
|
dateBefore
|
|
464
|
-
}
|
|
465
|
-
|
|
452
|
+
};
|
|
453
|
+
const response = braveMode === "llm-context" ? {
|
|
454
|
+
...await runBraveLlmContextSearch(request),
|
|
455
|
+
mode: "llm-context"
|
|
456
|
+
} : {
|
|
457
|
+
results: await runBraveWebSearch({
|
|
458
|
+
...request,
|
|
459
|
+
count: resolveSearchCount(count, DEFAULT_SEARCH_COUNT),
|
|
460
|
+
ui_lang: normalizedLanguage.ui_lang
|
|
461
|
+
}),
|
|
462
|
+
mode: "web"
|
|
463
|
+
};
|
|
464
|
+
signal?.throwIfAborted();
|
|
465
|
+
const results = response.mode === "llm-context" ? response.results.map((entry) => ({
|
|
466
|
+
title: entry.title ? wrapWebContent(entry.title, "web_search") : "",
|
|
467
|
+
url: entry.url,
|
|
468
|
+
snippets: entry.snippets.map((snippet) => wrapWebContent(snippet, "web_search")),
|
|
469
|
+
siteName: entry.siteName
|
|
470
|
+
})) : response.results;
|
|
466
471
|
const payload = {
|
|
467
472
|
query,
|
|
468
473
|
provider: "brave",
|
|
469
|
-
mode
|
|
474
|
+
...response.mode === "llm-context" ? { mode: response.mode } : {},
|
|
470
475
|
count: results.length,
|
|
471
476
|
tookMs: Date.now() - start,
|
|
472
477
|
externalContent: {
|
|
@@ -475,63 +480,24 @@ async function executeBraveSearch(args, searchConfig, options) {
|
|
|
475
480
|
provider: "brave",
|
|
476
481
|
wrapped: true
|
|
477
482
|
},
|
|
478
|
-
results
|
|
479
|
-
|
|
480
|
-
url: entry.url,
|
|
481
|
-
snippets: entry.snippets.map((snippet) => wrapWebContent(snippet, "web_search")),
|
|
482
|
-
siteName: entry.siteName
|
|
483
|
-
})),
|
|
484
|
-
sources
|
|
483
|
+
results,
|
|
484
|
+
...response.mode === "llm-context" ? { sources: response.sources } : {}
|
|
485
485
|
};
|
|
486
486
|
writeCachedSearchPayload(cacheKey, payload, cacheTtlMs);
|
|
487
487
|
logBraveHttp(diagnostics, "cache write", {
|
|
488
|
-
mode:
|
|
488
|
+
mode: response.mode,
|
|
489
489
|
query,
|
|
490
490
|
cacheKey,
|
|
491
491
|
ttlMs: cacheTtlMs,
|
|
492
492
|
count: results.length
|
|
493
493
|
});
|
|
494
494
|
return payload;
|
|
495
|
+
} catch (error) {
|
|
496
|
+
signal?.throwIfAborted();
|
|
497
|
+
throw error;
|
|
498
|
+
} finally {
|
|
499
|
+
cleanup();
|
|
495
500
|
}
|
|
496
|
-
const results = await runBraveWebSearch({
|
|
497
|
-
baseUrl: braveBaseUrl,
|
|
498
|
-
endpointMode: braveEndpointMode,
|
|
499
|
-
query,
|
|
500
|
-
count: resolveSearchCount(count, DEFAULT_SEARCH_COUNT),
|
|
501
|
-
apiKey,
|
|
502
|
-
timeoutSeconds,
|
|
503
|
-
diagnostics,
|
|
504
|
-
signal: options?.signal,
|
|
505
|
-
country: country ?? void 0,
|
|
506
|
-
search_lang: normalizedLanguage.search_lang,
|
|
507
|
-
ui_lang: normalizedLanguage.ui_lang,
|
|
508
|
-
freshness,
|
|
509
|
-
dateAfter,
|
|
510
|
-
dateBefore
|
|
511
|
-
});
|
|
512
|
-
options?.signal?.throwIfAborted();
|
|
513
|
-
const payload = {
|
|
514
|
-
query,
|
|
515
|
-
provider: "brave",
|
|
516
|
-
count: results.length,
|
|
517
|
-
tookMs: Date.now() - start,
|
|
518
|
-
externalContent: {
|
|
519
|
-
untrusted: true,
|
|
520
|
-
source: "web_search",
|
|
521
|
-
provider: "brave",
|
|
522
|
-
wrapped: true
|
|
523
|
-
},
|
|
524
|
-
results
|
|
525
|
-
};
|
|
526
|
-
writeCachedSearchPayload(cacheKey, payload, cacheTtlMs);
|
|
527
|
-
logBraveHttp(diagnostics, "cache write", {
|
|
528
|
-
mode: "web",
|
|
529
|
-
query,
|
|
530
|
-
cacheKey,
|
|
531
|
-
ttlMs: cacheTtlMs,
|
|
532
|
-
count: results.length
|
|
533
|
-
});
|
|
534
|
-
return payload;
|
|
535
501
|
}
|
|
536
502
|
//#endregion
|
|
537
503
|
export { executeBraveSearch };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createBraveWebSearchProvider } from "./brave-web-search-provider-
|
|
1
|
+
import { t as createBraveWebSearchProvider } from "./brave-web-search-provider-B1n-hEjq.js";
|
|
2
2
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
3
3
|
//#region extensions/brave/index.ts
|
|
4
4
|
/**
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/** Create the Brave provider descriptor for contract checks. */
|
|
4
|
-
function createBraveWebSearchProvider() {
|
|
5
|
-
return {
|
|
6
|
-
...buildBraveWebSearchProviderBase(),
|
|
7
|
-
createTool: () => null
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
//#endregion
|
|
1
|
+
import { t as createBraveWebSearchProvider } from "./brave-web-search-provider-B1n-hEjq.js";
|
|
2
|
+
import "./web-search-provider.js";
|
|
11
3
|
export { createBraveWebSearchProvider };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createBraveWebSearchProvider } from "./brave-web-search-provider-
|
|
1
|
+
import { t as createBraveWebSearchProvider } from "./brave-web-search-provider-B1n-hEjq.js";
|
|
2
2
|
export { createBraveWebSearchProvider };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/brave-plugin",
|
|
3
|
-
"version": "2026.8.1
|
|
3
|
+
"version": "2026.8.1",
|
|
4
4
|
"description": "OpenClaw Brave Search provider plugin for web search.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
"allowInvalidConfigRecovery": true
|
|
19
19
|
},
|
|
20
20
|
"compat": {
|
|
21
|
-
"pluginApi": ">=2026.8.1
|
|
21
|
+
"pluginApi": ">=2026.8.1"
|
|
22
22
|
},
|
|
23
23
|
"build": {
|
|
24
|
-
"openclawVersion": "2026.8.1
|
|
24
|
+
"openclawVersion": "2026.8.1"
|
|
25
25
|
},
|
|
26
26
|
"release": {
|
|
27
27
|
"publishToClawHub": true,
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"README.md"
|
|
38
38
|
],
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"openclaw": ">=2026.8.1
|
|
40
|
+
"openclaw": ">=2026.8.1"
|
|
41
41
|
},
|
|
42
42
|
"peerDependenciesMeta": {
|
|
43
43
|
"openclaw": {
|