diff --git a/src/agents/model-selection.test.ts b/src/agents/model-selection.test.ts index fd59b78710b..a4570bfa67d 100644 --- a/src/agents/model-selection.test.ts +++ b/src/agents/model-selection.test.ts @@ -1,6 +1,8 @@ import { describe, it, expect, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; import { resetLogger, setLoggerOverride } from "../logging/logger.js"; +import { createEmptyPluginRegistry } from "../plugins/registry-empty.js"; +import { setActivePluginRegistry } from "../plugins/runtime.js"; import { buildAllowedModelSet, inferUniqueProviderFromConfiguredModels, @@ -132,7 +134,17 @@ describe("model-selection", () => { }); describe("isCliProvider", () => { - it("treats claude-cli as a CLI provider even without explicit cliBackends config", () => { + it("treats runtime-registered CLI backends as CLI providers", () => { + const registry = createEmptyPluginRegistry(); + registry.cliBackends.push({ + pluginId: "anthropic", + backend: { + id: "claude-cli", + label: "Claude CLI", + command: ["claude"], + }, + }); + setActivePluginRegistry(registry); expect(isCliProvider("claude-cli", {} as OpenClawConfig)).toBe(true); }); }); diff --git a/src/agents/model-selection.ts b/src/agents/model-selection.ts index 313c2251aa5..caf89b61222 100644 --- a/src/agents/model-selection.ts +++ b/src/agents/model-selection.ts @@ -1,4 +1,3 @@ -import { CLAUDE_CLI_BACKEND_ID } from "../../extensions/anthropic/cli-backend-api.js"; import { resolveThinkingDefaultForModel } from "../auto-reply/thinking.shared.js"; import type { OpenClawConfig } from "../config/config.js"; import { @@ -29,8 +28,6 @@ import { normalizeProviderModelIdWithRuntime } from "./provider-model-normalizat let log: ReturnType | null = null; -const BUILTIN_CLI_PROVIDER_IDS = new Set([normalizeProviderId(CLAUDE_CLI_BACKEND_ID)]); - function getLog(): ReturnType { log ??= createSubsystemLogger("model-selection"); return log; @@ -92,9 +89,6 @@ export { export function isCliProvider(provider: string, cfg?: OpenClawConfig): boolean { const normalized = normalizeProviderId(provider); - if (BUILTIN_CLI_PROVIDER_IDS.has(normalized)) { - return true; - } const cliBackends = resolveRuntimeCliBackends(); if (cliBackends.some((backend) => normalizeProviderId(backend.id) === normalized)) { return true; diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index 7ceed1c8a08..c5790d3cd28 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -6,12 +6,6 @@ import { DefaultResourceLoader, SessionManager, } from "@mariozechner/pi-coding-agent"; -import { - isOllamaCompatProvider, - resolveOllamaCompatNumCtxEnabled, - shouldInjectOllamaCompatNumCtx, - wrapOllamaCompatNumCtx, -} from "../../../../extensions/ollama/runtime-api.js"; import { resolveHeartbeatPrompt } from "../../../auto-reply/heartbeat.js"; import { resolveChannelCapabilities } from "../../../config/channel-capabilities.js"; import { getMachineDisplayName } from "../../../infra/machine-name.js"; @@ -20,6 +14,12 @@ import { ensureGlobalUndiciStreamTimeouts, } from "../../../infra/net/undici-global-dispatcher.js"; import { MAX_IMAGE_BYTES } from "../../../media/constants.js"; +import { + isOllamaCompatProvider, + resolveOllamaCompatNumCtxEnabled, + shouldInjectOllamaCompatNumCtx, + wrapOllamaCompatNumCtx, +} from "../../../plugin-sdk/ollama-runtime.js"; import { getGlobalHookRunner } from "../../../plugins/hook-runner-global.js"; import { resolveToolCallArgumentsEncoding } from "../../../plugins/provider-model-compat.js"; import { resolveProviderSystemPromptContribution } from "../../../plugins/provider-runtime.js"; @@ -219,7 +219,7 @@ export { resolveOllamaCompatNumCtxEnabled, shouldInjectOllamaCompatNumCtx, wrapOllamaCompatNumCtx, -} from "../../../../extensions/ollama/runtime-api.js"; +} from "../../../plugin-sdk/ollama-runtime.js"; export { decodeHtmlEntitiesInObject, wrapStreamFnRepairMalformedToolCallArguments, diff --git a/src/commands/doctor-memory-search.ts b/src/commands/doctor-memory-search.ts index e972e5cba1a..66254bdb9d7 100644 --- a/src/commands/doctor-memory-search.ts +++ b/src/commands/doctor-memory-search.ts @@ -1,11 +1,4 @@ import fsSync from "node:fs"; -import { - auditShortTermPromotionArtifacts, - getBuiltinMemoryEmbeddingProviderDoctorMetadata, - listBuiltinAutoSelectMemoryEmbeddingProviderDoctorMetadata, - repairShortTermPromotionArtifacts, - type ShortTermAuditSummary, -} from "../../extensions/memory-core/runtime-api.js"; import { resolveAgentDir, resolveAgentWorkspaceDir, @@ -18,6 +11,13 @@ import type { OpenClawConfig } from "../config/config.js"; import { DEFAULT_LOCAL_MODEL } from "../memory-host-sdk/engine-embeddings.js"; import { checkQmdBinaryAvailability } from "../memory-host-sdk/engine-qmd.js"; import { hasConfiguredMemorySecretInput } from "../memory-host-sdk/secret.js"; +import { + auditShortTermPromotionArtifacts, + getBuiltinMemoryEmbeddingProviderDoctorMetadata, + listBuiltinAutoSelectMemoryEmbeddingProviderDoctorMetadata, + repairShortTermPromotionArtifacts, + type ShortTermAuditSummary, +} from "../plugin-sdk/memory-core-engine-runtime.js"; import { getActiveMemorySearchManager, resolveActiveMemoryBackendConfig, diff --git a/src/plugin-sdk/browser-cdp.ts b/src/plugin-sdk/browser-cdp.ts index f0b6f1878ad..b36df7eb264 100644 --- a/src/plugin-sdk/browser-cdp.ts +++ b/src/plugin-sdk/browser-cdp.ts @@ -1 +1 @@ -export { redactCdpUrl } from "../../extensions/browser/browser-cdp.js"; +export { redactCdpUrl } from "./browser-config.js"; diff --git a/src/plugin-sdk/browser-control-auth.ts b/src/plugin-sdk/browser-control-auth.ts index 66f7b9e2b1c..c0f8392188a 100644 --- a/src/plugin-sdk/browser-control-auth.ts +++ b/src/plugin-sdk/browser-control-auth.ts @@ -1,5 +1,18 @@ -export type { BrowserControlAuth } from "../../extensions/browser/browser-control-auth.js"; -export { - ensureBrowserControlAuth, - resolveBrowserControlAuth, -} from "../../extensions/browser/browser-control-auth.js"; +export type { BrowserControlAuth } from "./browser-config.js"; +export { resolveBrowserControlAuth } from "./browser-config.js"; +type BrowserControlAuthModule = typeof import("@openclaw/browser/browser-control-auth.js"); +import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js"; + +function loadBrowserControlAuthModule(): BrowserControlAuthModule { + return loadBundledPluginPublicSurfaceModuleSync({ + dirName: "browser", + artifactBasename: "browser-control-auth.js", + }); +} + +export const ensureBrowserControlAuth: BrowserControlAuthModule["ensureBrowserControlAuth"] = (( + ...args +) => + loadBrowserControlAuthModule().ensureBrowserControlAuth( + ...args, + )) as BrowserControlAuthModule["ensureBrowserControlAuth"]; diff --git a/src/plugin-sdk/ollama-runtime.ts b/src/plugin-sdk/ollama-runtime.ts index 2a424b5d51f..fb47d1fd714 100644 --- a/src/plugin-sdk/ollama-runtime.ts +++ b/src/plugin-sdk/ollama-runtime.ts @@ -18,3 +18,19 @@ export const createOllamaEmbeddingProvider: FacadeModule["createOllamaEmbeddingP loadFacadeModule().createOllamaEmbeddingProvider( ...args, )) as FacadeModule["createOllamaEmbeddingProvider"]; +export const isOllamaCompatProvider: FacadeModule["isOllamaCompatProvider"] = ((...args) => + loadFacadeModule().isOllamaCompatProvider(...args)) as FacadeModule["isOllamaCompatProvider"]; +export const resolveOllamaCompatNumCtxEnabled: FacadeModule["resolveOllamaCompatNumCtxEnabled"] = (( + ...args +) => + loadFacadeModule().resolveOllamaCompatNumCtxEnabled( + ...args, + )) as FacadeModule["resolveOllamaCompatNumCtxEnabled"]; +export const shouldInjectOllamaCompatNumCtx: FacadeModule["shouldInjectOllamaCompatNumCtx"] = (( + ...args +) => + loadFacadeModule().shouldInjectOllamaCompatNumCtx( + ...args, + )) as FacadeModule["shouldInjectOllamaCompatNumCtx"]; +export const wrapOllamaCompatNumCtx: FacadeModule["wrapOllamaCompatNumCtx"] = ((...args) => + loadFacadeModule().wrapOllamaCompatNumCtx(...args)) as FacadeModule["wrapOllamaCompatNumCtx"]; diff --git a/src/plugin-sdk/tts-runtime.ts b/src/plugin-sdk/tts-runtime.ts new file mode 100644 index 00000000000..fa4f7b6b49a --- /dev/null +++ b/src/plugin-sdk/tts-runtime.ts @@ -0,0 +1,81 @@ +// Manual facade. Keep loader boundary explicit. +type FacadeModule = typeof import("@openclaw/speech-core/runtime-api.js"); +import { + createLazyFacadeObjectValue, + loadActivatedBundledPluginPublicSurfaceModuleSync, +} from "./facade-runtime.js"; + +function loadFacadeModule(): FacadeModule { + return loadActivatedBundledPluginPublicSurfaceModuleSync({ + dirName: "speech-core", + artifactBasename: "runtime-api.js", + }); +} + +export const _test: FacadeModule["_test"] = createLazyFacadeObjectValue( + () => loadFacadeModule()._test, +); +export const buildTtsSystemPromptHint: FacadeModule["buildTtsSystemPromptHint"] = + createLazyFacadeValue("buildTtsSystemPromptHint"); +export const getLastTtsAttempt: FacadeModule["getLastTtsAttempt"] = + createLazyFacadeValue("getLastTtsAttempt"); +export const getResolvedSpeechProviderConfig: FacadeModule["getResolvedSpeechProviderConfig"] = + createLazyFacadeValue("getResolvedSpeechProviderConfig"); +export const getTtsMaxLength: FacadeModule["getTtsMaxLength"] = + createLazyFacadeValue("getTtsMaxLength"); +export const getTtsProvider: FacadeModule["getTtsProvider"] = + createLazyFacadeValue("getTtsProvider"); +export const isSummarizationEnabled: FacadeModule["isSummarizationEnabled"] = + createLazyFacadeValue("isSummarizationEnabled"); +export const isTtsEnabled: FacadeModule["isTtsEnabled"] = createLazyFacadeValue("isTtsEnabled"); +export const isTtsProviderConfigured: FacadeModule["isTtsProviderConfigured"] = + createLazyFacadeValue("isTtsProviderConfigured"); +export const listSpeechVoices: FacadeModule["listSpeechVoices"] = + createLazyFacadeValue("listSpeechVoices"); +export const maybeApplyTtsToPayload: FacadeModule["maybeApplyTtsToPayload"] = + createLazyFacadeValue("maybeApplyTtsToPayload"); +export const resolveTtsAutoMode: FacadeModule["resolveTtsAutoMode"] = + createLazyFacadeValue("resolveTtsAutoMode"); +export const resolveTtsConfig: FacadeModule["resolveTtsConfig"] = + createLazyFacadeValue("resolveTtsConfig"); +export const resolveTtsPrefsPath: FacadeModule["resolveTtsPrefsPath"] = + createLazyFacadeValue("resolveTtsPrefsPath"); +export const resolveTtsProviderOrder: FacadeModule["resolveTtsProviderOrder"] = + createLazyFacadeValue("resolveTtsProviderOrder"); +export const setLastTtsAttempt: FacadeModule["setLastTtsAttempt"] = + createLazyFacadeValue("setLastTtsAttempt"); +export const setSummarizationEnabled: FacadeModule["setSummarizationEnabled"] = + createLazyFacadeValue("setSummarizationEnabled"); +export const setTtsAutoMode: FacadeModule["setTtsAutoMode"] = + createLazyFacadeValue("setTtsAutoMode"); +export const setTtsEnabled: FacadeModule["setTtsEnabled"] = createLazyFacadeValue("setTtsEnabled"); +export const setTtsMaxLength: FacadeModule["setTtsMaxLength"] = + createLazyFacadeValue("setTtsMaxLength"); +export const setTtsProvider: FacadeModule["setTtsProvider"] = + createLazyFacadeValue("setTtsProvider"); +export const synthesizeSpeech: FacadeModule["synthesizeSpeech"] = + createLazyFacadeValue("synthesizeSpeech"); +export const textToSpeech: FacadeModule["textToSpeech"] = createLazyFacadeValue("textToSpeech"); +export const textToSpeechTelephony: FacadeModule["textToSpeechTelephony"] = + createLazyFacadeValue("textToSpeechTelephony"); + +export type ResolvedTtsConfig = import("@openclaw/speech-core/runtime-api.js").ResolvedTtsConfig; +export type ResolvedTtsModelOverrides = + import("@openclaw/speech-core/runtime-api.js").ResolvedTtsModelOverrides; +export type TtsDirectiveOverrides = + import("@openclaw/speech-core/runtime-api.js").TtsDirectiveOverrides; +export type TtsDirectiveParseResult = + import("@openclaw/speech-core/runtime-api.js").TtsDirectiveParseResult; +export type TtsResult = import("@openclaw/speech-core/runtime-api.js").TtsResult; +export type TtsSynthesisResult = import("@openclaw/speech-core/runtime-api.js").TtsSynthesisResult; +export type TtsTelephonyResult = import("@openclaw/speech-core/runtime-api.js").TtsTelephonyResult; + +function createLazyFacadeValue(key: K): FacadeModule[K] { + return ((...args: unknown[]) => { + const value = loadFacadeModule()[key]; + if (typeof value !== "function") { + return value; + } + return (value as (...innerArgs: unknown[]) => unknown)(...args); + }) as FacadeModule[K]; +} diff --git a/src/tts/tts.ts b/src/tts/tts.ts index baf05ea966c..43f098f4504 100644 --- a/src/tts/tts.ts +++ b/src/tts/tts.ts @@ -30,4 +30,4 @@ export { type TtsResult, type TtsSynthesisResult, type TtsTelephonyResult, -} from "../../extensions/speech-core/runtime-api.js"; +} from "../plugin-sdk/tts-runtime.js";