diff --git a/extensions/arcee/api.ts b/extensions/arcee/api.ts index 887a3d52444..d3a494d3197 100644 --- a/extensions/arcee/api.ts +++ b/extensions/arcee/api.ts @@ -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 { diff --git a/extensions/arcee/index.ts b/extensions/arcee/index.ts index 37fc29e84a5..ed9946356d1 100644 --- a/extensions/arcee/index.ts +++ b/extensions/arcee/index.ts @@ -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 }; } +/** Provider entry for Arcee direct and OpenRouter-backed models. */ export default definePluginEntry({ id: PROVIDER_ID, name: "Arcee AI Provider", diff --git a/extensions/arcee/models.ts b/extensions/arcee/models.ts index 190717ea684..710dd1aa32b 100644 --- a/extensions/arcee/models.ts +++ b/extensions/arcee/models.ts @@ -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 { diff --git a/extensions/arcee/onboard.ts b/extensions/arcee/onboard.ts index 5f96ac6e8df..adef4b9cd00 100644 --- a/extensions/arcee/onboard.ts +++ b/extensions/arcee/onboard.ts @@ -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); } diff --git a/extensions/arcee/provider-catalog.ts b/extensions/arcee/provider-catalog.ts index 5631ad2998d..3c93501cea9 100644 --- a/extensions/arcee/provider-catalog.ts +++ b/extensions/arcee/provider-catalog.ts @@ -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 { return ARCEE_MODEL_CATALOG.map(buildArceeModelDefinition); } +/** Build OpenRouter-routed Arcee catalog models. */ export function buildArceeOpenRouterCatalogModels(): NonNullable { 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, diff --git a/extensions/azure-speech/index.ts b/extensions/azure-speech/index.ts index 2564b70a36c..07956fe4eda 100644 --- a/extensions/azure-speech/index.ts +++ b/extensions/azure-speech/index.ts @@ -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", diff --git a/extensions/azure-speech/speech-provider.ts b/extensions/azure-speech/speech-provider.ts index 7f9fc23f490..d996f2e452f 100644 --- a/extensions/azure-speech/speech-provider.ts +++ b/extensions/azure-speech/speech-provider.ts @@ -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", diff --git a/extensions/azure-speech/tts.ts b/extensions/azure-speech/tts.ts index 7b6550f67ec..1f5eeb1f946 100644 --- a/extensions/azure-speech/tts.ts +++ b/extensions/azure-speech/tts.ts @@ -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; diff --git a/extensions/bonjour/index.ts b/extensions/bonjour/index.ts index b2877a768f7..89d03990e46 100644 --- a/extensions/bonjour/index.ts +++ b/extensions/bonjour/index.ts @@ -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", diff --git a/extensions/bonjour/src/advertiser.ts b/extensions/bonjour/src/advertiser.ts index 5686333543e..fd3549c5989 100644 --- a/extensions/bonjour/src/advertiser.ts +++ b/extensions/bonjour/src/advertiser.ts @@ -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; }; +/** 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 = {}, diff --git a/extensions/bonjour/src/ciao.ts b/extensions/bonjour/src/ciao.ts index 4d461746f2c..92463348fde 100644 --- a/extensions/bonjour/src/ciao.ts +++ b/extensions/bonjour/src/ciao.ts @@ -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; } diff --git a/extensions/bonjour/src/errors.ts b/extensions/bonjour/src/errors.ts index 1703f2696bf..fc2412d441c 100644 --- a/extensions/bonjour/src/errors.ts +++ b/extensions/bonjour/src/errors.ts @@ -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(); diff --git a/extensions/brave/index.ts b/extensions/brave/index.ts index c02c1510e8d..ebe04e09d36 100644 --- a/extensions/brave/index.ts +++ b/extensions/brave/index.ts @@ -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", diff --git a/extensions/brave/src/brave-web-search-provider.runtime.ts b/extensions/brave/src/brave-web-search-provider.runtime.ts index e24b9e45483..1613152fe47 100644 --- a/extensions/brave/src/brave-web-search-provider.runtime.ts +++ b/extensions/brave/src/brave-web-search-provider.runtime.ts @@ -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, searchConfig?: SearchConfigRecord, diff --git a/extensions/brave/src/brave-web-search-provider.shared.ts b/extensions/brave/src/brave-web-search-provider.shared.ts index 9a9fe987e9a..d73a70417f9 100644 --- a/extensions/brave/src/brave-web-search-provider.shared.ts +++ b/extensions/brave/src/brave-web-search-provider.shared.ts @@ -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): 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 }[] { diff --git a/extensions/brave/src/brave-web-search-provider.ts b/extensions/brave/src/brave-web-search-provider.ts index bc0b21dd1a5..5fa52bc7df5 100644 --- a/extensions/brave/src/brave-web-search-provider.ts +++ b/extensions/brave/src/brave-web-search-provider.ts @@ -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(), diff --git a/extensions/brave/test-api.ts b/extensions/brave/test-api.ts index 11a48e895b6..09f5216c551 100644 --- a/extensions/brave/test-api.ts +++ b/extensions/brave/test-api.ts @@ -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, diff --git a/extensions/brave/web-search-contract-api.ts b/extensions/brave/web-search-contract-api.ts index 89ebf172c7c..85bc7ac45a8 100644 --- a/extensions/brave/web-search-contract-api.ts +++ b/extensions/brave/web-search-contract-api.ts @@ -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(), diff --git a/extensions/brave/web-search-provider.ts b/extensions/brave/web-search-provider.ts index 01041edf46b..6e9b6692d4a 100644 --- a/extensions/brave/web-search-provider.ts +++ b/extensions/brave/web-search-provider.ts @@ -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"; diff --git a/extensions/brave/web-search-shared.ts b/extensions/brave/web-search-shared.ts index 882c39bc61d..b69fdc8661f 100644 --- a/extensions/brave/web-search-shared.ts +++ b/extensions/brave/web-search-shared.ts @@ -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 { return { id: "brave",