@openclaw/brave-plugin 2026.5.27 → 2026.5.28-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{brave-web-search-provider-Dt95Xy8Y.js → brave-web-search-provider-CjlXA4SO.js} +5 -36
- package/dist/{brave-web-search-provider.runtime-CV-2KCaT.js → brave-web-search-provider.runtime-DqjJHSR5.js} +179 -12
- package/dist/index.js +1 -1
- package/dist/web-search-contract-api.js +3 -43
- package/dist/web-search-provider.js +1 -1
- package/dist/web-search-shared.js +50 -0
- package/npm-shrinkwrap.json +2 -2
- package/openclaw.plugin.json +0 -3
- package/package.json +4 -4
- package/dist/brave-web-search-provider.shared-BeZZVXbj.js +0 -172
- package/dist/test-api.js +0 -10
package/dist/{brave-web-search-provider-Dt95Xy8Y.js → brave-web-search-provider-CjlXA4SO.js}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { buildBraveWebSearchProviderBase } from "./web-search-shared.js";
|
|
1
2
|
import { isDiagnosticFlagEnabled } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
2
|
-
import {
|
|
3
|
+
import { mergeScopedSearchConfig, resolveProviderWebSearchPluginConfig } from "openclaw/plugin-sdk/provider-web-search-config-contract";
|
|
3
4
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
5
|
//#region extensions/brave/src/brave-web-search-provider.ts
|
|
5
|
-
const BRAVE_CREDENTIAL_PATH = "plugins.entries.brave.config.webSearch.apiKey";
|
|
6
6
|
let braveWebSearchRuntimePromise;
|
|
7
7
|
function loadBraveWebSearchRuntime() {
|
|
8
|
-
braveWebSearchRuntimePromise ??= import("./brave-web-search-provider.runtime-
|
|
8
|
+
braveWebSearchRuntimePromise ??= import("./brave-web-search-provider.runtime-DqjJHSR5.js");
|
|
9
9
|
return braveWebSearchRuntimePromise;
|
|
10
10
|
}
|
|
11
11
|
const BraveSearchSchema = {
|
|
@@ -16,7 +16,7 @@ const BraveSearchSchema = {
|
|
|
16
16
|
description: "Search query string."
|
|
17
17
|
},
|
|
18
18
|
count: {
|
|
19
|
-
type: "
|
|
19
|
+
type: "integer",
|
|
20
20
|
description: "Number of results to return (1-10).",
|
|
21
21
|
minimum: 1,
|
|
22
22
|
maximum: 10
|
|
@@ -51,20 +51,6 @@ const BraveSearchSchema = {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
|
-
function resolveLegacyTopLevelBraveCredential(config) {
|
|
55
|
-
if (!isRecord(config)) return;
|
|
56
|
-
const tools = isRecord(config.tools) ? config.tools : void 0;
|
|
57
|
-
const web = isRecord(tools?.web) ? tools.web : void 0;
|
|
58
|
-
const search = isRecord(web?.search) ? web.search : void 0;
|
|
59
|
-
if (!search || !("apiKey" in search)) return;
|
|
60
|
-
return {
|
|
61
|
-
path: "tools.web.search.apiKey",
|
|
62
|
-
value: search.apiKey
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
function resolveConfiguredBraveCredential(config) {
|
|
66
|
-
return resolveProviderWebSearchPluginConfig(config, "brave")?.apiKey ?? resolveLegacyTopLevelBraveCredential(config)?.value;
|
|
67
|
-
}
|
|
68
54
|
function resolveBraveMode(searchConfig) {
|
|
69
55
|
return (isRecord(searchConfig?.brave) ? searchConfig.brave : void 0)?.mode === "llm-context" ? "llm-context" : "web";
|
|
70
56
|
}
|
|
@@ -82,24 +68,7 @@ function createBraveToolDefinition(searchConfig, config) {
|
|
|
82
68
|
}
|
|
83
69
|
function createBraveWebSearchProvider() {
|
|
84
70
|
return {
|
|
85
|
-
|
|
86
|
-
label: "Brave Search",
|
|
87
|
-
hint: "Structured results · country/language/time filters",
|
|
88
|
-
onboardingScopes: ["text-inference"],
|
|
89
|
-
credentialLabel: "Brave Search API key",
|
|
90
|
-
envVars: ["BRAVE_API_KEY"],
|
|
91
|
-
placeholder: "BSA...",
|
|
92
|
-
signupUrl: "https://brave.com/search/api/",
|
|
93
|
-
docsUrl: "https://docs.openclaw.ai/tools/brave-search",
|
|
94
|
-
autoDetectOrder: 10,
|
|
95
|
-
credentialPath: BRAVE_CREDENTIAL_PATH,
|
|
96
|
-
...createWebSearchProviderContractFields({
|
|
97
|
-
credentialPath: BRAVE_CREDENTIAL_PATH,
|
|
98
|
-
searchCredential: { type: "top-level" },
|
|
99
|
-
configuredCredential: { pluginId: "brave" }
|
|
100
|
-
}),
|
|
101
|
-
getConfiguredCredentialValue: resolveConfiguredBraveCredential,
|
|
102
|
-
getConfiguredCredentialFallback: resolveLegacyTopLevelBraveCredential,
|
|
71
|
+
...buildBraveWebSearchProviderBase(),
|
|
103
72
|
createTool: (ctx) => createBraveToolDefinition(mergeScopedSearchConfig(ctx.searchConfig, "brave", resolveProviderWebSearchPluginConfig(ctx.config, "brave"), { mirrorApiKeyToTopLevel: true }), ctx.config)
|
|
104
73
|
};
|
|
105
74
|
}
|
|
@@ -1,8 +1,178 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
|
|
3
|
-
import { DEFAULT_SEARCH_COUNT, buildSearchCacheKey, formatCliCommand, normalizeFreshness, parseIsoDateRange, readCachedSearchPayload, readConfiguredSecretString,
|
|
1
|
+
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
+
import { assertOkOrThrowProviderError, readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
|
|
3
|
+
import { DEFAULT_SEARCH_COUNT, MAX_SEARCH_COUNT, buildSearchCacheKey, formatCliCommand, normalizeFreshness, parseIsoDateRange, readCachedSearchPayload, readConfiguredSecretString, readPositiveIntegerParam, readProviderEnvValue, readStringParam, resolveSearchCacheTtlMs, resolveSearchCount, resolveSearchTimeoutSeconds, resolveSiteName, withSelfHostedWebSearchEndpoint, withTrustedWebSearchEndpoint, wrapWebContent, writeCachedSearchPayload } from "openclaw/plugin-sdk/provider-web-search";
|
|
4
4
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
5
5
|
import { assertHttpUrlTargetsPrivateNetwork, isBlockedHostnameOrIp, isPrivateIpAddress, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
6
|
+
//#region extensions/brave/src/brave-web-search-provider.shared.ts
|
|
7
|
+
const BRAVE_COUNTRY_CODES = new Set([
|
|
8
|
+
"AR",
|
|
9
|
+
"AU",
|
|
10
|
+
"AT",
|
|
11
|
+
"BE",
|
|
12
|
+
"BR",
|
|
13
|
+
"CA",
|
|
14
|
+
"CL",
|
|
15
|
+
"DK",
|
|
16
|
+
"FI",
|
|
17
|
+
"FR",
|
|
18
|
+
"DE",
|
|
19
|
+
"GR",
|
|
20
|
+
"HK",
|
|
21
|
+
"IN",
|
|
22
|
+
"ID",
|
|
23
|
+
"IT",
|
|
24
|
+
"JP",
|
|
25
|
+
"KR",
|
|
26
|
+
"MY",
|
|
27
|
+
"MX",
|
|
28
|
+
"NL",
|
|
29
|
+
"NZ",
|
|
30
|
+
"NO",
|
|
31
|
+
"CN",
|
|
32
|
+
"PL",
|
|
33
|
+
"PT",
|
|
34
|
+
"PH",
|
|
35
|
+
"RU",
|
|
36
|
+
"SA",
|
|
37
|
+
"ZA",
|
|
38
|
+
"ES",
|
|
39
|
+
"SE",
|
|
40
|
+
"CH",
|
|
41
|
+
"TW",
|
|
42
|
+
"TR",
|
|
43
|
+
"GB",
|
|
44
|
+
"US",
|
|
45
|
+
"ALL"
|
|
46
|
+
]);
|
|
47
|
+
const BRAVE_SEARCH_LANG_CODES = new Set([
|
|
48
|
+
"ar",
|
|
49
|
+
"eu",
|
|
50
|
+
"bn",
|
|
51
|
+
"bg",
|
|
52
|
+
"ca",
|
|
53
|
+
"zh-hans",
|
|
54
|
+
"zh-hant",
|
|
55
|
+
"hr",
|
|
56
|
+
"cs",
|
|
57
|
+
"da",
|
|
58
|
+
"nl",
|
|
59
|
+
"en",
|
|
60
|
+
"en-gb",
|
|
61
|
+
"et",
|
|
62
|
+
"fi",
|
|
63
|
+
"fr",
|
|
64
|
+
"gl",
|
|
65
|
+
"de",
|
|
66
|
+
"el",
|
|
67
|
+
"gu",
|
|
68
|
+
"he",
|
|
69
|
+
"hi",
|
|
70
|
+
"hu",
|
|
71
|
+
"is",
|
|
72
|
+
"it",
|
|
73
|
+
"jp",
|
|
74
|
+
"kn",
|
|
75
|
+
"ko",
|
|
76
|
+
"lv",
|
|
77
|
+
"lt",
|
|
78
|
+
"ms",
|
|
79
|
+
"ml",
|
|
80
|
+
"mr",
|
|
81
|
+
"nb",
|
|
82
|
+
"pl",
|
|
83
|
+
"pt-br",
|
|
84
|
+
"pt-pt",
|
|
85
|
+
"pa",
|
|
86
|
+
"ro",
|
|
87
|
+
"ru",
|
|
88
|
+
"sr",
|
|
89
|
+
"sk",
|
|
90
|
+
"sl",
|
|
91
|
+
"es",
|
|
92
|
+
"sv",
|
|
93
|
+
"ta",
|
|
94
|
+
"te",
|
|
95
|
+
"th",
|
|
96
|
+
"tr",
|
|
97
|
+
"uk",
|
|
98
|
+
"vi"
|
|
99
|
+
]);
|
|
100
|
+
const BRAVE_SEARCH_LANG_ALIASES = {
|
|
101
|
+
ja: "jp",
|
|
102
|
+
zh: "zh-hans",
|
|
103
|
+
"zh-cn": "zh-hans",
|
|
104
|
+
"zh-hk": "zh-hant",
|
|
105
|
+
"zh-sg": "zh-hans",
|
|
106
|
+
"zh-tw": "zh-hant"
|
|
107
|
+
};
|
|
108
|
+
const BRAVE_UI_LANG_LOCALE = /^([a-z]{2})-([a-z]{2})$/i;
|
|
109
|
+
function normalizeBraveSearchLang(value) {
|
|
110
|
+
if (!value) return;
|
|
111
|
+
const trimmed = value.trim();
|
|
112
|
+
if (!trimmed) return;
|
|
113
|
+
const lower = normalizeLowercaseStringOrEmpty(trimmed);
|
|
114
|
+
const canonical = BRAVE_SEARCH_LANG_ALIASES[lower] ?? lower;
|
|
115
|
+
if (!BRAVE_SEARCH_LANG_CODES.has(canonical)) return;
|
|
116
|
+
return canonical;
|
|
117
|
+
}
|
|
118
|
+
function normalizeBraveCountry(value) {
|
|
119
|
+
if (!value) return;
|
|
120
|
+
const trimmed = value.trim();
|
|
121
|
+
if (!trimmed) return;
|
|
122
|
+
const canonical = trimmed.toUpperCase();
|
|
123
|
+
return BRAVE_COUNTRY_CODES.has(canonical) ? canonical : "ALL";
|
|
124
|
+
}
|
|
125
|
+
function normalizeBraveUiLang(value) {
|
|
126
|
+
if (!value) return;
|
|
127
|
+
const trimmed = value.trim();
|
|
128
|
+
if (!trimmed) return;
|
|
129
|
+
const match = trimmed.match(BRAVE_UI_LANG_LOCALE);
|
|
130
|
+
if (!match) return;
|
|
131
|
+
const [, language, region] = match;
|
|
132
|
+
return `${normalizeLowercaseStringOrEmpty(language)}-${region.toUpperCase()}`;
|
|
133
|
+
}
|
|
134
|
+
function resolveBraveConfig(searchConfig) {
|
|
135
|
+
const brave = searchConfig?.brave;
|
|
136
|
+
return brave && typeof brave === "object" && !Array.isArray(brave) ? brave : {};
|
|
137
|
+
}
|
|
138
|
+
function resolveBraveMode(brave) {
|
|
139
|
+
return brave?.mode === "llm-context" ? "llm-context" : "web";
|
|
140
|
+
}
|
|
141
|
+
function normalizeBraveLanguageParams(params) {
|
|
142
|
+
const rawSearchLang = normalizeOptionalString(params.search_lang);
|
|
143
|
+
const rawUiLang = normalizeOptionalString(params.ui_lang);
|
|
144
|
+
let searchLangCandidate = rawSearchLang;
|
|
145
|
+
let uiLangCandidate = rawUiLang;
|
|
146
|
+
if (normalizeBraveUiLang(rawSearchLang) && normalizeBraveSearchLang(rawUiLang)) {
|
|
147
|
+
searchLangCandidate = rawUiLang;
|
|
148
|
+
uiLangCandidate = rawSearchLang;
|
|
149
|
+
}
|
|
150
|
+
const search_lang = normalizeBraveSearchLang(searchLangCandidate);
|
|
151
|
+
if (searchLangCandidate && !search_lang) return { invalidField: "search_lang" };
|
|
152
|
+
const ui_lang = normalizeBraveUiLang(uiLangCandidate);
|
|
153
|
+
if (uiLangCandidate && !ui_lang) return { invalidField: "ui_lang" };
|
|
154
|
+
return {
|
|
155
|
+
search_lang,
|
|
156
|
+
ui_lang
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function resolveSiteName$1(url) {
|
|
160
|
+
if (!url) return;
|
|
161
|
+
try {
|
|
162
|
+
return new URL(url).hostname;
|
|
163
|
+
} catch {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function mapBraveLlmContextResults(data) {
|
|
168
|
+
return (Array.isArray(data.grounding?.generic) ? data.grounding.generic : []).map((entry) => ({
|
|
169
|
+
url: entry.url ?? "",
|
|
170
|
+
title: entry.title ?? "",
|
|
171
|
+
snippets: (entry.snippets ?? []).filter((snippet) => typeof snippet === "string" && snippet.length > 0),
|
|
172
|
+
siteName: resolveSiteName$1(entry.url) || void 0
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
6
176
|
//#region extensions/brave/src/brave-web-search-provider.runtime.ts
|
|
7
177
|
const DEFAULT_BRAVE_BASE_URL = "https://api.search.brave.com";
|
|
8
178
|
const BRAVE_SEARCH_ENDPOINT_PATH = "/res/v1/web/search";
|
|
@@ -99,10 +269,7 @@ async function runBraveLlmContextSearch(params) {
|
|
|
99
269
|
ok: response.ok,
|
|
100
270
|
durationMs: Date.now() - startedAt
|
|
101
271
|
});
|
|
102
|
-
|
|
103
|
-
const detail = await response.text();
|
|
104
|
-
throw new Error(`Brave LLM Context API error (${response.status}): ${detail || response.statusText}`);
|
|
105
|
-
}
|
|
272
|
+
await assertOkOrThrowProviderError(response, "Brave LLM Context API error");
|
|
106
273
|
const data = await readProviderJsonResponse(response, "Brave LLM Context API error");
|
|
107
274
|
return {
|
|
108
275
|
results: mapBraveLlmContextResults(data),
|
|
@@ -146,10 +313,7 @@ async function runBraveWebSearch(params) {
|
|
|
146
313
|
ok: response.ok,
|
|
147
314
|
durationMs: Date.now() - startedAt
|
|
148
315
|
});
|
|
149
|
-
|
|
150
|
-
const detail = await response.text();
|
|
151
|
-
throw new Error(`Brave Search API error (${response.status}): ${detail || response.statusText}`);
|
|
152
|
-
}
|
|
316
|
+
await assertOkOrThrowProviderError(response, "Brave Search API error");
|
|
153
317
|
const data = await readProviderJsonResponse(response, "Brave Search API error");
|
|
154
318
|
return (Array.isArray(data.web?.results) ? data.web?.results ?? [] : []).map((entry) => {
|
|
155
319
|
const description = entry.description ?? "";
|
|
@@ -173,7 +337,10 @@ async function executeBraveSearch(args, searchConfig, options) {
|
|
|
173
337
|
const braveBaseUrl = resolveBraveBaseUrl(braveConfig);
|
|
174
338
|
const braveEndpointMode = await validateBraveBaseUrl(braveBaseUrl);
|
|
175
339
|
const query = readStringParam(args, "query", { required: true });
|
|
176
|
-
const count =
|
|
340
|
+
const count = readPositiveIntegerParam(args, "count", {
|
|
341
|
+
max: MAX_SEARCH_COUNT,
|
|
342
|
+
message: `count must be an integer from 1 to ${MAX_SEARCH_COUNT}.`
|
|
343
|
+
}) ?? searchConfig?.maxResults ?? void 0;
|
|
177
344
|
const country = normalizeBraveCountry(readStringParam(args, "country"));
|
|
178
345
|
const language = readStringParam(args, "language");
|
|
179
346
|
const search_lang = readStringParam(args, "search_lang");
|
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-CjlXA4SO.js";
|
|
2
2
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
3
3
|
//#region extensions/brave/index.ts
|
|
4
4
|
var brave_default = definePluginEntry({
|
|
@@ -1,49 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { buildBraveWebSearchProviderBase } from "./web-search-shared.js";
|
|
2
|
+
import "openclaw/plugin-sdk/provider-web-search-config-contract";
|
|
3
3
|
//#region extensions/brave/web-search-contract-api.ts
|
|
4
|
-
function resolveLegacyTopLevelBraveCredential(config) {
|
|
5
|
-
if (!isRecord(config)) return;
|
|
6
|
-
const tools = isRecord(config.tools) ? config.tools : void 0;
|
|
7
|
-
const web = isRecord(tools?.web) ? tools.web : void 0;
|
|
8
|
-
const search = isRecord(web?.search) ? web.search : void 0;
|
|
9
|
-
if (!search || !("apiKey" in search)) return;
|
|
10
|
-
return {
|
|
11
|
-
path: "tools.web.search.apiKey",
|
|
12
|
-
value: search.apiKey
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
function resolveProviderWebSearchPluginConfig$1(config, pluginId) {
|
|
16
|
-
if (!isRecord(config)) return;
|
|
17
|
-
const plugins = isRecord(config.plugins) ? config.plugins : void 0;
|
|
18
|
-
const entries = isRecord(plugins?.entries) ? plugins.entries : void 0;
|
|
19
|
-
const entry = isRecord(entries?.[pluginId]) ? entries[pluginId] : void 0;
|
|
20
|
-
const pluginConfig = isRecord(entry?.config) ? entry.config : void 0;
|
|
21
|
-
return isRecord(pluginConfig?.webSearch) ? pluginConfig.webSearch : void 0;
|
|
22
|
-
}
|
|
23
|
-
function resolveConfiguredBraveCredential(config) {
|
|
24
|
-
return resolveProviderWebSearchPluginConfig$1(config, "brave")?.apiKey ?? resolveLegacyTopLevelBraveCredential(config)?.value;
|
|
25
|
-
}
|
|
26
4
|
function createBraveWebSearchProvider() {
|
|
27
|
-
const credentialPath = "plugins.entries.brave.config.webSearch.apiKey";
|
|
28
5
|
return {
|
|
29
|
-
|
|
30
|
-
label: "Brave Search",
|
|
31
|
-
hint: "Structured results · country/language/time filters",
|
|
32
|
-
onboardingScopes: ["text-inference"],
|
|
33
|
-
credentialLabel: "Brave Search API key",
|
|
34
|
-
envVars: ["BRAVE_API_KEY"],
|
|
35
|
-
placeholder: "BSA...",
|
|
36
|
-
signupUrl: "https://brave.com/search/api/",
|
|
37
|
-
docsUrl: "https://docs.openclaw.ai/tools/brave-search",
|
|
38
|
-
autoDetectOrder: 10,
|
|
39
|
-
credentialPath,
|
|
40
|
-
...createWebSearchProviderContractFields({
|
|
41
|
-
credentialPath,
|
|
42
|
-
searchCredential: { type: "top-level" },
|
|
43
|
-
configuredCredential: { pluginId: "brave" }
|
|
44
|
-
}),
|
|
45
|
-
getConfiguredCredentialValue: resolveConfiguredBraveCredential,
|
|
46
|
-
getConfiguredCredentialFallback: resolveLegacyTopLevelBraveCredential,
|
|
6
|
+
...buildBraveWebSearchProviderBase(),
|
|
47
7
|
createTool: () => null
|
|
48
8
|
};
|
|
49
9
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createBraveWebSearchProvider } from "./brave-web-search-provider-
|
|
1
|
+
import { t as createBraveWebSearchProvider } from "./brave-web-search-provider-CjlXA4SO.js";
|
|
2
2
|
export { createBraveWebSearchProvider };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createWebSearchProviderContractFields } from "openclaw/plugin-sdk/provider-web-search-config-contract";
|
|
2
|
+
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
+
//#region extensions/brave/web-search-shared.ts
|
|
4
|
+
const BRAVE_CREDENTIAL_PATH = "plugins.entries.brave.config.webSearch.apiKey";
|
|
5
|
+
function resolveLegacyTopLevelBraveCredential(config) {
|
|
6
|
+
if (!isRecord(config)) return;
|
|
7
|
+
const tools = isRecord(config.tools) ? config.tools : void 0;
|
|
8
|
+
const web = isRecord(tools?.web) ? tools.web : void 0;
|
|
9
|
+
const search = isRecord(web?.search) ? web.search : void 0;
|
|
10
|
+
if (!search || !("apiKey" in search)) return;
|
|
11
|
+
return {
|
|
12
|
+
path: "tools.web.search.apiKey",
|
|
13
|
+
value: search.apiKey
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function resolveBraveWebSearchPluginConfig(config) {
|
|
17
|
+
if (!isRecord(config)) return;
|
|
18
|
+
const plugins = isRecord(config.plugins) ? config.plugins : void 0;
|
|
19
|
+
const entries = isRecord(plugins?.entries) ? plugins.entries : void 0;
|
|
20
|
+
const entry = isRecord(entries?.brave) ? entries.brave : void 0;
|
|
21
|
+
const pluginConfig = isRecord(entry?.config) ? entry.config : void 0;
|
|
22
|
+
return isRecord(pluginConfig?.webSearch) ? pluginConfig.webSearch : void 0;
|
|
23
|
+
}
|
|
24
|
+
function resolveConfiguredBraveCredential(config) {
|
|
25
|
+
return resolveBraveWebSearchPluginConfig(config)?.apiKey ?? resolveLegacyTopLevelBraveCredential(config)?.value;
|
|
26
|
+
}
|
|
27
|
+
function buildBraveWebSearchProviderBase() {
|
|
28
|
+
return {
|
|
29
|
+
id: "brave",
|
|
30
|
+
label: "Brave Search",
|
|
31
|
+
hint: "Structured results · country/language/time filters",
|
|
32
|
+
onboardingScopes: ["text-inference"],
|
|
33
|
+
credentialLabel: "Brave Search API key",
|
|
34
|
+
envVars: ["BRAVE_API_KEY"],
|
|
35
|
+
placeholder: "BSA...",
|
|
36
|
+
signupUrl: "https://brave.com/search/api/",
|
|
37
|
+
docsUrl: "https://docs.openclaw.ai/tools/brave-search",
|
|
38
|
+
autoDetectOrder: 10,
|
|
39
|
+
credentialPath: BRAVE_CREDENTIAL_PATH,
|
|
40
|
+
...createWebSearchProviderContractFields({
|
|
41
|
+
credentialPath: BRAVE_CREDENTIAL_PATH,
|
|
42
|
+
searchCredential: { type: "top-level" },
|
|
43
|
+
configuredCredential: { pluginId: "brave" }
|
|
44
|
+
}),
|
|
45
|
+
getConfiguredCredentialValue: resolveConfiguredBraveCredential,
|
|
46
|
+
getConfiguredCredentialFallback: resolveLegacyTopLevelBraveCredential
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { BRAVE_CREDENTIAL_PATH, buildBraveWebSearchProviderBase, resolveConfiguredBraveCredential, resolveLegacyTopLevelBraveCredential };
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/brave-plugin",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.28-beta.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/brave-plugin",
|
|
9
|
-
"version": "2026.5.
|
|
9
|
+
"version": "2026.5.28-beta.2"
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
}
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/brave-plugin",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.28-beta.2",
|
|
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.5.
|
|
21
|
+
"pluginApi": ">=2026.5.28-beta.2"
|
|
22
22
|
},
|
|
23
23
|
"build": {
|
|
24
|
-
"openclawVersion": "2026.5.
|
|
24
|
+
"openclawVersion": "2026.5.28-beta.2"
|
|
25
25
|
},
|
|
26
26
|
"release": {
|
|
27
27
|
"publishToClawHub": true,
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"npm-shrinkwrap.json"
|
|
38
38
|
],
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"openclaw": ">=2026.5.
|
|
40
|
+
"openclaw": ">=2026.5.28-beta.2"
|
|
41
41
|
},
|
|
42
42
|
"peerDependenciesMeta": {
|
|
43
43
|
"openclaw": {
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
-
//#region extensions/brave/src/brave-web-search-provider.shared.ts
|
|
3
|
-
const BRAVE_COUNTRY_CODES = new Set([
|
|
4
|
-
"AR",
|
|
5
|
-
"AU",
|
|
6
|
-
"AT",
|
|
7
|
-
"BE",
|
|
8
|
-
"BR",
|
|
9
|
-
"CA",
|
|
10
|
-
"CL",
|
|
11
|
-
"DK",
|
|
12
|
-
"FI",
|
|
13
|
-
"FR",
|
|
14
|
-
"DE",
|
|
15
|
-
"GR",
|
|
16
|
-
"HK",
|
|
17
|
-
"IN",
|
|
18
|
-
"ID",
|
|
19
|
-
"IT",
|
|
20
|
-
"JP",
|
|
21
|
-
"KR",
|
|
22
|
-
"MY",
|
|
23
|
-
"MX",
|
|
24
|
-
"NL",
|
|
25
|
-
"NZ",
|
|
26
|
-
"NO",
|
|
27
|
-
"CN",
|
|
28
|
-
"PL",
|
|
29
|
-
"PT",
|
|
30
|
-
"PH",
|
|
31
|
-
"RU",
|
|
32
|
-
"SA",
|
|
33
|
-
"ZA",
|
|
34
|
-
"ES",
|
|
35
|
-
"SE",
|
|
36
|
-
"CH",
|
|
37
|
-
"TW",
|
|
38
|
-
"TR",
|
|
39
|
-
"GB",
|
|
40
|
-
"US",
|
|
41
|
-
"ALL"
|
|
42
|
-
]);
|
|
43
|
-
const BRAVE_SEARCH_LANG_CODES = new Set([
|
|
44
|
-
"ar",
|
|
45
|
-
"eu",
|
|
46
|
-
"bn",
|
|
47
|
-
"bg",
|
|
48
|
-
"ca",
|
|
49
|
-
"zh-hans",
|
|
50
|
-
"zh-hant",
|
|
51
|
-
"hr",
|
|
52
|
-
"cs",
|
|
53
|
-
"da",
|
|
54
|
-
"nl",
|
|
55
|
-
"en",
|
|
56
|
-
"en-gb",
|
|
57
|
-
"et",
|
|
58
|
-
"fi",
|
|
59
|
-
"fr",
|
|
60
|
-
"gl",
|
|
61
|
-
"de",
|
|
62
|
-
"el",
|
|
63
|
-
"gu",
|
|
64
|
-
"he",
|
|
65
|
-
"hi",
|
|
66
|
-
"hu",
|
|
67
|
-
"is",
|
|
68
|
-
"it",
|
|
69
|
-
"jp",
|
|
70
|
-
"kn",
|
|
71
|
-
"ko",
|
|
72
|
-
"lv",
|
|
73
|
-
"lt",
|
|
74
|
-
"ms",
|
|
75
|
-
"ml",
|
|
76
|
-
"mr",
|
|
77
|
-
"nb",
|
|
78
|
-
"pl",
|
|
79
|
-
"pt-br",
|
|
80
|
-
"pt-pt",
|
|
81
|
-
"pa",
|
|
82
|
-
"ro",
|
|
83
|
-
"ru",
|
|
84
|
-
"sr",
|
|
85
|
-
"sk",
|
|
86
|
-
"sl",
|
|
87
|
-
"es",
|
|
88
|
-
"sv",
|
|
89
|
-
"ta",
|
|
90
|
-
"te",
|
|
91
|
-
"th",
|
|
92
|
-
"tr",
|
|
93
|
-
"uk",
|
|
94
|
-
"vi"
|
|
95
|
-
]);
|
|
96
|
-
const BRAVE_SEARCH_LANG_ALIASES = {
|
|
97
|
-
ja: "jp",
|
|
98
|
-
zh: "zh-hans",
|
|
99
|
-
"zh-cn": "zh-hans",
|
|
100
|
-
"zh-hk": "zh-hant",
|
|
101
|
-
"zh-sg": "zh-hans",
|
|
102
|
-
"zh-tw": "zh-hant"
|
|
103
|
-
};
|
|
104
|
-
const BRAVE_UI_LANG_LOCALE = /^([a-z]{2})-([a-z]{2})$/i;
|
|
105
|
-
function normalizeBraveSearchLang(value) {
|
|
106
|
-
if (!value) return;
|
|
107
|
-
const trimmed = value.trim();
|
|
108
|
-
if (!trimmed) return;
|
|
109
|
-
const lower = normalizeLowercaseStringOrEmpty(trimmed);
|
|
110
|
-
const canonical = BRAVE_SEARCH_LANG_ALIASES[lower] ?? lower;
|
|
111
|
-
if (!BRAVE_SEARCH_LANG_CODES.has(canonical)) return;
|
|
112
|
-
return canonical;
|
|
113
|
-
}
|
|
114
|
-
function normalizeBraveCountry(value) {
|
|
115
|
-
if (!value) return;
|
|
116
|
-
const trimmed = value.trim();
|
|
117
|
-
if (!trimmed) return;
|
|
118
|
-
const canonical = trimmed.toUpperCase();
|
|
119
|
-
return BRAVE_COUNTRY_CODES.has(canonical) ? canonical : "ALL";
|
|
120
|
-
}
|
|
121
|
-
function normalizeBraveUiLang(value) {
|
|
122
|
-
if (!value) return;
|
|
123
|
-
const trimmed = value.trim();
|
|
124
|
-
if (!trimmed) return;
|
|
125
|
-
const match = trimmed.match(BRAVE_UI_LANG_LOCALE);
|
|
126
|
-
if (!match) return;
|
|
127
|
-
const [, language, region] = match;
|
|
128
|
-
return `${normalizeLowercaseStringOrEmpty(language)}-${region.toUpperCase()}`;
|
|
129
|
-
}
|
|
130
|
-
function resolveBraveConfig(searchConfig) {
|
|
131
|
-
const brave = searchConfig?.brave;
|
|
132
|
-
return brave && typeof brave === "object" && !Array.isArray(brave) ? brave : {};
|
|
133
|
-
}
|
|
134
|
-
function resolveBraveMode(brave) {
|
|
135
|
-
return brave?.mode === "llm-context" ? "llm-context" : "web";
|
|
136
|
-
}
|
|
137
|
-
function normalizeBraveLanguageParams(params) {
|
|
138
|
-
const rawSearchLang = normalizeOptionalString(params.search_lang);
|
|
139
|
-
const rawUiLang = normalizeOptionalString(params.ui_lang);
|
|
140
|
-
let searchLangCandidate = rawSearchLang;
|
|
141
|
-
let uiLangCandidate = rawUiLang;
|
|
142
|
-
if (normalizeBraveUiLang(rawSearchLang) && normalizeBraveSearchLang(rawUiLang)) {
|
|
143
|
-
searchLangCandidate = rawUiLang;
|
|
144
|
-
uiLangCandidate = rawSearchLang;
|
|
145
|
-
}
|
|
146
|
-
const search_lang = normalizeBraveSearchLang(searchLangCandidate);
|
|
147
|
-
if (searchLangCandidate && !search_lang) return { invalidField: "search_lang" };
|
|
148
|
-
const ui_lang = normalizeBraveUiLang(uiLangCandidate);
|
|
149
|
-
if (uiLangCandidate && !ui_lang) return { invalidField: "ui_lang" };
|
|
150
|
-
return {
|
|
151
|
-
search_lang,
|
|
152
|
-
ui_lang
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function resolveSiteName(url) {
|
|
156
|
-
if (!url) return;
|
|
157
|
-
try {
|
|
158
|
-
return new URL(url).hostname;
|
|
159
|
-
} catch {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
function mapBraveLlmContextResults(data) {
|
|
164
|
-
return (Array.isArray(data.grounding?.generic) ? data.grounding.generic : []).map((entry) => ({
|
|
165
|
-
url: entry.url ?? "",
|
|
166
|
-
title: entry.title ?? "",
|
|
167
|
-
snippets: (entry.snippets ?? []).filter((snippet) => typeof snippet === "string" && snippet.length > 0),
|
|
168
|
-
siteName: resolveSiteName(entry.url) || void 0
|
|
169
|
-
}));
|
|
170
|
-
}
|
|
171
|
-
//#endregion
|
|
172
|
-
export { resolveBraveMode as a, resolveBraveConfig as i, normalizeBraveCountry as n, normalizeBraveLanguageParams as r, mapBraveLlmContextResults as t };
|
package/dist/test-api.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { a as resolveBraveMode, n as normalizeBraveCountry, r as normalizeBraveLanguageParams, t as mapBraveLlmContextResults } from "./brave-web-search-provider.shared-BeZZVXbj.js";
|
|
2
|
-
//#region extensions/brave/test-api.ts
|
|
3
|
-
const testing = {
|
|
4
|
-
normalizeBraveCountry,
|
|
5
|
-
normalizeBraveLanguageParams,
|
|
6
|
-
resolveBraveMode,
|
|
7
|
-
mapBraveLlmContextResults
|
|
8
|
-
};
|
|
9
|
-
//#endregion
|
|
10
|
-
export { testing as __testing, testing };
|