Skip to content

Commit 70230f4

Browse files
committed
refactor: share brave web search metadata
1 parent 44adda3 commit 70230f4

3 files changed

Lines changed: 68 additions & 105 deletions

File tree

extensions/brave/src/brave-web-search-provider.ts

Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
21
import { isDiagnosticFlagEnabled } from "openclaw/plugin-sdk/diagnostic-runtime";
32
import type {
43
SearchConfigRecord,
54
WebSearchProviderPlugin,
65
WebSearchProviderToolDefinition,
76
} from "openclaw/plugin-sdk/provider-web-search";
87
import {
9-
createWebSearchProviderContractFields,
108
mergeScopedSearchConfig,
119
resolveProviderWebSearchPluginConfig,
1210
} from "openclaw/plugin-sdk/provider-web-search-config-contract";
1311
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
14-
15-
const BRAVE_CREDENTIAL_PATH = "plugins.entries.brave.config.webSearch.apiKey";
12+
import { buildBraveWebSearchProviderBase } from "../web-search-shared.js";
1613

1714
type BraveWebSearchRuntime = typeof import("./brave-web-search-provider.runtime.js");
1815

@@ -67,28 +64,6 @@ const BraveSearchSchema = {
6764
},
6865
} satisfies Record<string, unknown>;
6966

70-
function resolveLegacyTopLevelBraveCredential(
71-
config: OpenClawConfig | undefined,
72-
): { path: string; value: unknown } | undefined {
73-
if (!isRecord(config)) {
74-
return undefined;
75-
}
76-
const tools = isRecord(config.tools) ? config.tools : undefined;
77-
const web = isRecord(tools?.web) ? tools.web : undefined;
78-
const search = isRecord(web?.search) ? web.search : undefined;
79-
if (!search || !("apiKey" in search)) {
80-
return undefined;
81-
}
82-
return { path: "tools.web.search.apiKey", value: search.apiKey };
83-
}
84-
85-
function resolveConfiguredBraveCredential(config: OpenClawConfig | undefined): unknown {
86-
return (
87-
resolveProviderWebSearchPluginConfig(config, "brave")?.apiKey ??
88-
resolveLegacyTopLevelBraveCredential(config)?.value
89-
);
90-
}
91-
9267
function resolveBraveMode(searchConfig?: Record<string, unknown>): "web" | "llm-context" {
9368
const brave = isRecord(searchConfig?.brave) ? searchConfig.brave : undefined;
9469
return brave?.mode === "llm-context" ? "llm-context" : "web";
@@ -116,24 +91,7 @@ function createBraveToolDefinition(
11691

11792
export function createBraveWebSearchProvider(): WebSearchProviderPlugin {
11893
return {
119-
id: "brave",
120-
label: "Brave Search",
121-
hint: "Structured results · country/language/time filters",
122-
onboardingScopes: ["text-inference"],
123-
credentialLabel: "Brave Search API key",
124-
envVars: ["BRAVE_API_KEY"],
125-
placeholder: "BSA...",
126-
signupUrl: "https://brave.com/search/api/",
127-
docsUrl: "https://docs.openclaw.ai/tools/brave-search",
128-
autoDetectOrder: 10,
129-
credentialPath: BRAVE_CREDENTIAL_PATH,
130-
...createWebSearchProviderContractFields({
131-
credentialPath: BRAVE_CREDENTIAL_PATH,
132-
searchCredential: { type: "top-level" },
133-
configuredCredential: { pluginId: "brave" },
134-
}),
135-
getConfiguredCredentialValue: resolveConfiguredBraveCredential,
136-
getConfiguredCredentialFallback: resolveLegacyTopLevelBraveCredential,
94+
...buildBraveWebSearchProviderBase(),
13795
createTool: (ctx) =>
13896
createBraveToolDefinition(
13997
mergeScopedSearchConfig(
Lines changed: 3 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,9 @@
1-
import {
2-
createWebSearchProviderContractFields,
3-
type WebSearchProviderPlugin,
4-
} from "openclaw/plugin-sdk/provider-web-search-config-contract";
5-
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
6-
7-
function resolveLegacyTopLevelBraveCredential(
8-
config: unknown,
9-
): { path: string; value: unknown } | undefined {
10-
if (!isRecord(config)) {
11-
return undefined;
12-
}
13-
const tools = isRecord(config.tools) ? config.tools : undefined;
14-
const web = isRecord(tools?.web) ? tools.web : undefined;
15-
const search = isRecord(web?.search) ? web.search : undefined;
16-
if (!search || !("apiKey" in search)) {
17-
return undefined;
18-
}
19-
return { path: "tools.web.search.apiKey", value: search.apiKey };
20-
}
21-
22-
function resolveProviderWebSearchPluginConfig(
23-
config: unknown,
24-
pluginId: string,
25-
): Record<string, unknown> | undefined {
26-
if (!isRecord(config)) {
27-
return undefined;
28-
}
29-
const plugins = isRecord(config.plugins) ? config.plugins : undefined;
30-
const entries = isRecord(plugins?.entries) ? plugins.entries : undefined;
31-
const entry = isRecord(entries?.[pluginId]) ? entries[pluginId] : undefined;
32-
const pluginConfig = isRecord(entry?.config) ? entry.config : undefined;
33-
return isRecord(pluginConfig?.webSearch) ? pluginConfig.webSearch : undefined;
34-
}
35-
36-
function resolveConfiguredBraveCredential(config: unknown): unknown {
37-
return (
38-
resolveProviderWebSearchPluginConfig(config, "brave")?.apiKey ??
39-
resolveLegacyTopLevelBraveCredential(config)?.value
40-
);
41-
}
1+
import { type WebSearchProviderPlugin } from "openclaw/plugin-sdk/provider-web-search-config-contract";
2+
import { buildBraveWebSearchProviderBase } from "./web-search-shared.js";
423

434
export function createBraveWebSearchProvider(): WebSearchProviderPlugin {
44-
const credentialPath = "plugins.entries.brave.config.webSearch.apiKey";
45-
465
return {
47-
id: "brave",
48-
label: "Brave Search",
49-
hint: "Structured results · country/language/time filters",
50-
onboardingScopes: ["text-inference"],
51-
credentialLabel: "Brave Search API key",
52-
envVars: ["BRAVE_API_KEY"],
53-
placeholder: "BSA...",
54-
signupUrl: "https://brave.com/search/api/",
55-
docsUrl: "https://docs.openclaw.ai/tools/brave-search",
56-
autoDetectOrder: 10,
57-
credentialPath,
58-
...createWebSearchProviderContractFields({
59-
credentialPath,
60-
searchCredential: { type: "top-level" },
61-
configuredCredential: { pluginId: "brave" },
62-
}),
63-
getConfiguredCredentialValue: resolveConfiguredBraveCredential,
64-
getConfiguredCredentialFallback: resolveLegacyTopLevelBraveCredential,
6+
...buildBraveWebSearchProviderBase(),
657
createTool: () => null,
668
};
679
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {
2+
createWebSearchProviderContractFields,
3+
type WebSearchProviderPlugin,
4+
} from "openclaw/plugin-sdk/provider-web-search-config-contract";
5+
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
6+
7+
export const BRAVE_CREDENTIAL_PATH = "plugins.entries.brave.config.webSearch.apiKey";
8+
9+
export function resolveLegacyTopLevelBraveCredential(
10+
config: unknown,
11+
): { path: string; value: unknown } | undefined {
12+
if (!isRecord(config)) {
13+
return undefined;
14+
}
15+
const tools = isRecord(config.tools) ? config.tools : undefined;
16+
const web = isRecord(tools?.web) ? tools.web : undefined;
17+
const search = isRecord(web?.search) ? web.search : undefined;
18+
if (!search || !("apiKey" in search)) {
19+
return undefined;
20+
}
21+
return { path: "tools.web.search.apiKey", value: search.apiKey };
22+
}
23+
24+
function resolveBraveWebSearchPluginConfig(config: unknown): Record<string, unknown> | undefined {
25+
if (!isRecord(config)) {
26+
return undefined;
27+
}
28+
const plugins = isRecord(config.plugins) ? config.plugins : undefined;
29+
const entries = isRecord(plugins?.entries) ? plugins.entries : undefined;
30+
const entry = isRecord(entries?.brave) ? entries.brave : undefined;
31+
const pluginConfig = isRecord(entry?.config) ? entry.config : undefined;
32+
return isRecord(pluginConfig?.webSearch) ? pluginConfig.webSearch : undefined;
33+
}
34+
35+
export function resolveConfiguredBraveCredential(config: unknown): unknown {
36+
return (
37+
resolveBraveWebSearchPluginConfig(config)?.apiKey ??
38+
resolveLegacyTopLevelBraveCredential(config)?.value
39+
);
40+
}
41+
42+
export function buildBraveWebSearchProviderBase(): Omit<WebSearchProviderPlugin, "createTool"> {
43+
return {
44+
id: "brave",
45+
label: "Brave Search",
46+
hint: "Structured results · country/language/time filters",
47+
onboardingScopes: ["text-inference"],
48+
credentialLabel: "Brave Search API key",
49+
envVars: ["BRAVE_API_KEY"],
50+
placeholder: "BSA...",
51+
signupUrl: "https://brave.com/search/api/",
52+
docsUrl: "https://docs.openclaw.ai/tools/brave-search",
53+
autoDetectOrder: 10,
54+
credentialPath: BRAVE_CREDENTIAL_PATH,
55+
...createWebSearchProviderContractFields({
56+
credentialPath: BRAVE_CREDENTIAL_PATH,
57+
searchCredential: { type: "top-level" },
58+
configuredCredential: { pluginId: "brave" },
59+
}),
60+
getConfiguredCredentialValue: resolveConfiguredBraveCredential,
61+
getConfiguredCredentialFallback: resolveLegacyTopLevelBraveCredential,
62+
};
63+
}

0 commit comments

Comments
 (0)