mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-22 11:58:08 +00:00
docs: document small provider plugins
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Public Arcee API barrel. It exposes model catalogs, provider config builders,
|
||||
* and setup helpers without importing the plugin entry.
|
||||
*/
|
||||
export { buildArceeModelDefinition, ARCEE_BASE_URL, ARCEE_MODEL_CATALOG } from "./models.js";
|
||||
export { buildArceeProvider, buildArceeOpenRouterProvider } from "./provider-catalog.js";
|
||||
export {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Arcee AI provider plugin entry. It supports direct Arcee auth and OpenRouter
|
||||
* routing while normalizing OpenRouter model ids and base URLs.
|
||||
*/
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth-api-key";
|
||||
import {
|
||||
@@ -101,6 +105,7 @@ function normalizeArceeResolvedModel<T extends { baseUrl?: string; id: string }>
|
||||
};
|
||||
}
|
||||
|
||||
/** Provider entry for Arcee direct and OpenRouter-backed models. */
|
||||
export default definePluginEntry({
|
||||
id: PROVIDER_ID,
|
||||
name: "Arcee AI Provider",
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
/**
|
||||
* Arcee model catalog metadata. These definitions back both direct Arcee and
|
||||
* OpenRouter-routed provider catalogs.
|
||||
*/
|
||||
import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
|
||||
/** Default direct Arcee API base URL. */
|
||||
export const ARCEE_BASE_URL = "https://api.arcee.ai/api/v1";
|
||||
|
||||
/** Static Arcee model catalog used for provider registration. */
|
||||
export const ARCEE_MODEL_CATALOG: ModelDefinitionConfig[] = [
|
||||
{
|
||||
id: "trinity-mini",
|
||||
@@ -51,6 +57,7 @@ export const ARCEE_MODEL_CATALOG: ModelDefinitionConfig[] = [
|
||||
},
|
||||
];
|
||||
|
||||
/** Build one OpenAI-compatible Arcee model definition. */
|
||||
export function buildArceeModelDefinition(
|
||||
model: (typeof ARCEE_MODEL_CATALOG)[number],
|
||||
): ModelDefinitionConfig {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Arcee setup preset appliers. They seed model catalog defaults for direct
|
||||
* Arcee API usage and the OpenRouter-backed path.
|
||||
*/
|
||||
import {
|
||||
createModelCatalogPresetAppliers,
|
||||
type OpenClawConfig,
|
||||
@@ -9,7 +13,9 @@ import {
|
||||
OPENROUTER_BASE_URL,
|
||||
} from "./provider-catalog.js";
|
||||
|
||||
/** Default Arcee model ref for direct API setup. */
|
||||
export const ARCEE_DEFAULT_MODEL_REF = "arcee/trinity-large-thinking";
|
||||
/** Default Arcee model ref for OpenRouter setup. */
|
||||
export const ARCEE_OPENROUTER_DEFAULT_MODEL_REF = "arcee/trinity-large-thinking";
|
||||
|
||||
const arceePresetAppliers = createModelCatalogPresetAppliers({
|
||||
@@ -34,10 +40,12 @@ const arceeOpenRouterPresetAppliers = createModelCatalogPresetAppliers({
|
||||
}),
|
||||
});
|
||||
|
||||
/** Apply direct Arcee provider defaults to config. */
|
||||
export function applyArceeConfig(cfg: OpenClawConfig): OpenClawConfig {
|
||||
return arceePresetAppliers.applyConfig(cfg);
|
||||
}
|
||||
|
||||
/** Apply OpenRouter-backed Arcee provider defaults to config. */
|
||||
export function applyArceeOpenRouterConfig(cfg: OpenClawConfig): OpenClawConfig {
|
||||
return arceeOpenRouterPresetAppliers.applyConfig(cfg);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
/**
|
||||
* Arcee provider catalog builders. Direct Arcee uses native ids; OpenRouter
|
||||
* catalogs normalize ids to the `arcee/*` namespace.
|
||||
*/
|
||||
import type { ModelProviderConfig } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
import { buildArceeModelDefinition, ARCEE_BASE_URL, ARCEE_MODEL_CATALOG } from "./models.js";
|
||||
|
||||
/** Canonical OpenRouter API base URL for Arcee-routed models. */
|
||||
export const OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
||||
const OPENROUTER_LEGACY_BASE_URL = "https://openrouter.ai/v1";
|
||||
|
||||
@@ -8,6 +13,7 @@ function normalizeBaseUrl(baseUrl: string | undefined): string {
|
||||
return (baseUrl ?? "").trim().replace(/\/+$/, "");
|
||||
}
|
||||
|
||||
/** Normalize OpenRouter base URLs accepted for Arcee model routing. */
|
||||
export function normalizeArceeOpenRouterBaseUrl(baseUrl: string | undefined): string | undefined {
|
||||
const normalized = normalizeBaseUrl(baseUrl);
|
||||
if (!normalized) {
|
||||
@@ -19,6 +25,7 @@ export function normalizeArceeOpenRouterBaseUrl(baseUrl: string | undefined): st
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** Convert a bare Arcee model id to the OpenRouter `arcee/*` id. */
|
||||
export function toArceeOpenRouterModelId(modelId: string): string {
|
||||
const normalized = modelId.trim();
|
||||
if (!normalized || normalized.startsWith("arcee/")) {
|
||||
@@ -27,16 +34,19 @@ export function toArceeOpenRouterModelId(modelId: string): string {
|
||||
return `arcee/${normalized}`;
|
||||
}
|
||||
|
||||
/** Build direct Arcee catalog models. */
|
||||
export function buildArceeCatalogModels(): NonNullable<ModelProviderConfig["models"]> {
|
||||
return ARCEE_MODEL_CATALOG.map(buildArceeModelDefinition);
|
||||
}
|
||||
|
||||
/** Build OpenRouter-routed Arcee catalog models. */
|
||||
export function buildArceeOpenRouterCatalogModels(): NonNullable<ModelProviderConfig["models"]> {
|
||||
return buildArceeCatalogModels().map((model) =>
|
||||
Object.assign({}, model, { id: toArceeOpenRouterModelId(model.id) }),
|
||||
);
|
||||
}
|
||||
|
||||
/** Build the direct Arcee provider config. */
|
||||
export function buildArceeProvider(): ModelProviderConfig {
|
||||
return {
|
||||
baseUrl: ARCEE_BASE_URL,
|
||||
@@ -45,6 +55,7 @@ export function buildArceeProvider(): ModelProviderConfig {
|
||||
};
|
||||
}
|
||||
|
||||
/** Build the OpenRouter-backed Arcee provider config. */
|
||||
export function buildArceeOpenRouterProvider(): ModelProviderConfig {
|
||||
return {
|
||||
baseUrl: OPENROUTER_BASE_URL,
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
/**
|
||||
* Azure Speech plugin entry. It registers the Azure text-to-speech provider for
|
||||
* message voice output and voice-note generation.
|
||||
*/
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { buildAzureSpeechProvider } from "./speech-provider.js";
|
||||
|
||||
/** Plugin entry for Azure Speech TTS. */
|
||||
export default definePluginEntry({
|
||||
id: "azure-speech",
|
||||
name: "Azure Speech",
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Azure Speech provider descriptor. It reads config/env defaults, parses speech
|
||||
* directives, lists voices, and calls the Azure TTS runtime helper.
|
||||
*/
|
||||
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
||||
import type {
|
||||
SpeechDirectiveTokenParseContext,
|
||||
@@ -189,6 +193,7 @@ function resolveGeneratedAudioMaxBytes(req: {
|
||||
return DEFAULT_GENERATED_AUDIO_MAX_BYTES;
|
||||
}
|
||||
|
||||
/** Build the Azure Speech provider descriptor for the speech-core runtime. */
|
||||
export function buildAzureSpeechProvider(): SpeechProviderPlugin {
|
||||
return {
|
||||
id: "azure-speech",
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Azure Speech REST helpers. They normalize endpoints, build SSML, list voices,
|
||||
* and synthesize speech with response-size and SSRF guards.
|
||||
*/
|
||||
import { assertOkOrThrowProviderError } from "openclaw/plugin-sdk/provider-http";
|
||||
import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
||||
import type { SpeechVoiceOption } from "openclaw/plugin-sdk/speech-core";
|
||||
@@ -7,10 +11,15 @@ import {
|
||||
ssrfPolicyFromHttpBaseUrlAllowedHostname,
|
||||
} from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
|
||||
/** Default Azure Speech neural voice. */
|
||||
export const DEFAULT_AZURE_SPEECH_VOICE = "en-US-JennyNeural";
|
||||
/** Default Azure Speech language. */
|
||||
export const DEFAULT_AZURE_SPEECH_LANG = "en-US";
|
||||
/** Default full-audio output format. */
|
||||
export const DEFAULT_AZURE_SPEECH_AUDIO_FORMAT = "audio-24khz-48kbitrate-mono-mp3";
|
||||
/** Default voice-note output format. */
|
||||
export const DEFAULT_AZURE_SPEECH_VOICE_NOTE_FORMAT = "ogg-24khz-16bit-mono-opus";
|
||||
/** Default telephony output format. */
|
||||
export const DEFAULT_AZURE_SPEECH_TELEPHONY_FORMAT = "raw-8khz-8bit-mono-mulaw";
|
||||
const DEFAULT_AZURE_SPEECH_MAX_BYTES = 16 * 1024 * 1024;
|
||||
|
||||
@@ -28,6 +37,7 @@ type AzureSpeechVoiceEntry = {
|
||||
};
|
||||
};
|
||||
|
||||
/** Resolve and normalize the Azure Speech base URL from endpoint or region. */
|
||||
export function normalizeAzureSpeechBaseUrl(params: {
|
||||
baseUrl?: string;
|
||||
endpoint?: string;
|
||||
@@ -62,6 +72,7 @@ function escapeXmlAttr(value: string): string {
|
||||
return escapeXmlText(value).replace(/"/g, """).replace(/'/g, "'");
|
||||
}
|
||||
|
||||
/** Build escaped SSML for one Azure Speech synthesis request. */
|
||||
export function buildAzureSpeechSsml(params: {
|
||||
text: string;
|
||||
voice: string;
|
||||
@@ -76,6 +87,7 @@ export function buildAzureSpeechSsml(params: {
|
||||
);
|
||||
}
|
||||
|
||||
/** Infer the generated audio file extension from Azure output format. */
|
||||
export function inferAzureSpeechFileExtension(outputFormat: string): string {
|
||||
const normalized = outputFormat.toLowerCase();
|
||||
if (normalized.includes("mp3")) {
|
||||
@@ -99,6 +111,7 @@ export function inferAzureSpeechFileExtension(outputFormat: string): string {
|
||||
return ".audio";
|
||||
}
|
||||
|
||||
/** Return whether an Azure output format is voice-note compatible. */
|
||||
export function isAzureSpeechVoiceCompatible(outputFormat: string): boolean {
|
||||
const normalized = outputFormat.toLowerCase();
|
||||
return normalized.startsWith("ogg-") && normalized.includes("opus");
|
||||
@@ -123,6 +136,7 @@ function isDeprecatedVoice(entry: AzureSpeechVoiceEntry): boolean {
|
||||
return status === "deprecated" || status === "retired" || status === "disabled";
|
||||
}
|
||||
|
||||
/** List non-deprecated voices from the Azure Speech voices API. */
|
||||
export async function listAzureSpeechVoices(params: {
|
||||
apiKey: string;
|
||||
baseUrl?: string;
|
||||
@@ -167,6 +181,7 @@ export async function listAzureSpeechVoices(params: {
|
||||
}
|
||||
}
|
||||
|
||||
/** Synthesize text to audio bytes using Azure Speech TTS. */
|
||||
export async function azureSpeechTTS(params: {
|
||||
text: string;
|
||||
apiKey: string;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Bonjour gateway-discovery plugin entry. It advertises the local gateway over
|
||||
* mDNS and lazily loads the ciao-based advertiser.
|
||||
*/
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
function formatBonjourInstanceName(displayName: string) {
|
||||
@@ -11,6 +15,7 @@ function formatBonjourInstanceName(displayName: string) {
|
||||
return `${trimmed} (OpenClaw)`;
|
||||
}
|
||||
|
||||
/** Plugin entry for Bonjour/mDNS gateway discovery. */
|
||||
export default definePluginEntry({
|
||||
id: "bonjour",
|
||||
name: "Bonjour Gateway Discovery",
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Bonjour advertiser runtime. It publishes gateway/canvas/SSH service records,
|
||||
* watches ciao state, and repairs stuck or conflicting advertisements.
|
||||
*/
|
||||
import type { ChildProcess } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
@@ -12,10 +16,12 @@ const childProcessModule = nodeRequire("node:child_process") as {
|
||||
exec: typeof import("node:child_process").exec;
|
||||
};
|
||||
|
||||
/** Running Bonjour advertiser handle. */
|
||||
export type GatewayBonjourAdvertiser = {
|
||||
stop: () => Promise<void>;
|
||||
};
|
||||
|
||||
/** Input data used to publish OpenClaw gateway Bonjour records. */
|
||||
export type GatewayBonjourAdvertiseOpts = {
|
||||
instanceName?: string;
|
||||
gatewayPort: number;
|
||||
@@ -359,6 +365,7 @@ function installCiaoUnhandledRejectionListener(handler: UnhandledRejectionHandle
|
||||
};
|
||||
}
|
||||
|
||||
/** Start Bonjour advertisements for the local gateway services. */
|
||||
export async function startGatewayBonjourAdvertiser(
|
||||
opts: GatewayBonjourAdvertiseOpts,
|
||||
deps: BonjourAdvertiserDeps = {},
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Ciao process-error classifier. It recognizes known noisy ciao failures so
|
||||
* the Bonjour plugin can suppress or repair expected mDNS lifecycle issues.
|
||||
*/
|
||||
import { collectErrorGraphCandidates } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { formatBonjourError } from "./errors.js";
|
||||
|
||||
@@ -13,6 +17,7 @@ const CIAO_SELF_PROBE_MESSAGE_RE =
|
||||
// Node surfaces this as a SystemError mentioning the libuv syscall by name.
|
||||
const CIAO_INTERFACE_ENUMERATION_FAILURE_RE = /\bUV_INTERFACE_ADDRESSES\b/u;
|
||||
|
||||
/** Known ciao process-level errors that OpenClaw handles specially. */
|
||||
export type CiaoProcessErrorClassification =
|
||||
| { kind: "cancellation"; formatted: string }
|
||||
| { kind: "interface-assertion"; formatted: string }
|
||||
@@ -20,6 +25,7 @@ export type CiaoProcessErrorClassification =
|
||||
| { kind: "self-probe"; formatted: string }
|
||||
| { kind: "interface-enumeration-failure"; formatted: string };
|
||||
|
||||
/** Classify a ciao error/rejection chain into a known category. */
|
||||
export function classifyCiaoProcessError(reason: unknown): CiaoProcessErrorClassification | null {
|
||||
for (const candidate of collectErrorGraphCandidates(reason, (current) => [
|
||||
current.cause,
|
||||
@@ -50,8 +56,10 @@ export function classifyCiaoProcessError(reason: unknown): CiaoProcessErrorClass
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Backward-compatible alias for unhandled-rejection classification. */
|
||||
export const classifyCiaoUnhandledRejection = classifyCiaoProcessError;
|
||||
|
||||
/** Return whether a ciao unhandled rejection is known and ignorable. */
|
||||
export function ignoreCiaoUnhandledRejection(reason: unknown): boolean {
|
||||
return classifyCiaoProcessError(reason) !== null;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Bonjour error formatting helper. It normalizes Error and non-Error values
|
||||
* into concise messages for gateway discovery logs.
|
||||
*/
|
||||
/** Format an unknown Bonjour/ciao error value for logs. */
|
||||
export function formatBonjourError(err: unknown): string {
|
||||
if (err instanceof Error) {
|
||||
const trimmedMessage = err.message.trim();
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
/**
|
||||
* Brave Search plugin entry. It registers the Brave web-search provider and
|
||||
* keeps runtime HTTP execution lazy.
|
||||
*/
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { createBraveWebSearchProvider } from "./src/brave-web-search-provider.js";
|
||||
|
||||
/** Plugin entry for Brave Search. */
|
||||
export default definePluginEntry({
|
||||
id: "brave",
|
||||
name: "Brave Plugin",
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Brave Search HTTP runtime. It resolves credentials, enforces endpoint safety,
|
||||
* applies caching, and maps Brave web/LLM-context API responses.
|
||||
*/
|
||||
import {
|
||||
assertOkOrThrowProviderError,
|
||||
readProviderJsonResponse,
|
||||
@@ -334,6 +338,7 @@ async function runBraveWebSearch(params: {
|
||||
});
|
||||
}
|
||||
|
||||
/** Execute one Brave Search request using web or LLM-context mode. */
|
||||
export async function executeBraveSearch(
|
||||
args: Record<string, unknown>,
|
||||
searchConfig?: SearchConfigRecord,
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Brave Search request normalization and result mapping. It validates Brave
|
||||
* country/language params and converts LLM-context responses into web results.
|
||||
*/
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
@@ -9,6 +13,7 @@ type BraveConfig = {
|
||||
};
|
||||
|
||||
type BraveLlmContextResult = { url: string; title: string; snippets: string[] };
|
||||
/** Brave LLM Context API response subset used by OpenClaw. */
|
||||
export type BraveLlmContextResponse = {
|
||||
grounding: { generic?: BraveLlmContextResult[] };
|
||||
sources?: { url?: string; hostname?: string; date?: string }[];
|
||||
@@ -136,6 +141,7 @@ function normalizeBraveSearchLang(value: string | undefined): string | undefined
|
||||
return canonical;
|
||||
}
|
||||
|
||||
/** Normalize Brave country filter values. */
|
||||
export function normalizeBraveCountry(value: string | undefined): string | undefined {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
@@ -164,15 +170,18 @@ function normalizeBraveUiLang(value: string | undefined): string | undefined {
|
||||
return `${normalizeLowercaseStringOrEmpty(language)}-${region.toUpperCase()}`;
|
||||
}
|
||||
|
||||
/** Resolve Brave-specific web-search config from scoped search config. */
|
||||
export function resolveBraveConfig(searchConfig?: Record<string, unknown>): BraveConfig {
|
||||
const brave = searchConfig?.brave;
|
||||
return brave && typeof brave === "object" && !Array.isArray(brave) ? (brave as BraveConfig) : {};
|
||||
}
|
||||
|
||||
/** Resolve whether Brave should use web search or LLM Context API mode. */
|
||||
export function resolveBraveMode(brave?: BraveConfig): "web" | "llm-context" {
|
||||
return brave?.mode === "llm-context" ? "llm-context" : "web";
|
||||
}
|
||||
|
||||
/** Normalize Brave search and UI language params, detecting swapped fields. */
|
||||
export function normalizeBraveLanguageParams(params: { search_lang?: string; ui_lang?: string }): {
|
||||
search_lang?: string;
|
||||
ui_lang?: string;
|
||||
@@ -212,6 +221,7 @@ function resolveSiteName(url: string | undefined): string | undefined {
|
||||
}
|
||||
}
|
||||
|
||||
/** Map Brave LLM Context API grounding results into web-search result rows. */
|
||||
export function mapBraveLlmContextResults(
|
||||
data: BraveLlmContextResponse,
|
||||
): { url: string; title: string; snippets: string[]; siteName?: string }[] {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Brave web-search provider factory. It builds the agent tool definition and
|
||||
* lazy-loads HTTP execution only when a search is run.
|
||||
*/
|
||||
import { isDiagnosticFlagEnabled } from "openclaw/plugin-sdk/diagnostic-runtime";
|
||||
import type {
|
||||
SearchConfigRecord,
|
||||
@@ -89,6 +93,7 @@ function createBraveToolDefinition(
|
||||
};
|
||||
}
|
||||
|
||||
/** Create the runtime Brave Search provider descriptor. */
|
||||
export function createBraveWebSearchProvider(): WebSearchProviderPlugin {
|
||||
return {
|
||||
...buildBraveWebSearchProviderBase(),
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Brave Search test API barrel. Tests import normalized helpers through this
|
||||
* path instead of deep runtime modules.
|
||||
*/
|
||||
import {
|
||||
mapBraveLlmContextResults,
|
||||
normalizeBraveCountry,
|
||||
@@ -5,6 +9,7 @@ import {
|
||||
resolveBraveMode,
|
||||
} from "./src/brave-web-search-provider.shared.js";
|
||||
|
||||
/** Test-only Brave normalization helpers. */
|
||||
export const testing = {
|
||||
normalizeBraveCountry,
|
||||
normalizeBraveLanguageParams,
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
/**
|
||||
* Brave Search contract provider. It exposes provider metadata without creating
|
||||
* the runtime search tool.
|
||||
*/
|
||||
import type { WebSearchProviderPlugin } from "openclaw/plugin-sdk/provider-web-search-config-contract";
|
||||
import { buildBraveWebSearchProviderBase } from "./web-search-shared.js";
|
||||
|
||||
/** Create the Brave provider descriptor for contract checks. */
|
||||
export function createBraveWebSearchProvider(): WebSearchProviderPlugin {
|
||||
return {
|
||||
...buildBraveWebSearchProviderBase(),
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
/**
|
||||
* Public Brave web-search provider barrel. Runtime consumers import this
|
||||
* lightweight path for the provider factory.
|
||||
*/
|
||||
export { createBraveWebSearchProvider } from "./src/brave-web-search-provider.js";
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
/**
|
||||
* Shared Brave Search provider metadata and credential lookup. Contract tests
|
||||
* and runtime provider creation both use this lightweight descriptor.
|
||||
*/
|
||||
import {
|
||||
createWebSearchProviderContractFields,
|
||||
type WebSearchProviderPlugin,
|
||||
} from "openclaw/plugin-sdk/provider-web-search-config-contract";
|
||||
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
|
||||
/** Canonical config path for the Brave Search API key. */
|
||||
export const BRAVE_CREDENTIAL_PATH = "plugins.entries.brave.config.webSearch.apiKey";
|
||||
|
||||
/** Resolve legacy top-level Brave credentials from old web-search config. */
|
||||
export function resolveLegacyTopLevelBraveCredential(
|
||||
config: unknown,
|
||||
): { path: string; value: unknown } | undefined {
|
||||
@@ -32,6 +38,7 @@ function resolveBraveWebSearchPluginConfig(config: unknown): Record<string, unkn
|
||||
return isRecord(pluginConfig?.webSearch) ? pluginConfig.webSearch : undefined;
|
||||
}
|
||||
|
||||
/** Resolve Brave credentials from current plugin config or legacy fallback. */
|
||||
export function resolveConfiguredBraveCredential(config: unknown): unknown {
|
||||
return (
|
||||
resolveBraveWebSearchPluginConfig(config)?.apiKey ??
|
||||
@@ -39,6 +46,7 @@ export function resolveConfiguredBraveCredential(config: unknown): unknown {
|
||||
);
|
||||
}
|
||||
|
||||
/** Build the common Brave provider metadata without the runtime tool executor. */
|
||||
export function buildBraveWebSearchProviderBase(): Omit<WebSearchProviderPlugin, "createTool"> {
|
||||
return {
|
||||
id: "brave",
|
||||
|
||||
Reference in New Issue
Block a user