mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-23 15:11:42 +00:00
fix: stabilize plugin-sdk test loading
This commit is contained in:
@@ -23,6 +23,7 @@ export function createDetectedBinaryStatus(params: {
|
||||
detectBinary?: (path: string) => Promise<boolean>;
|
||||
}): ChannelSetupWizardStatus {
|
||||
const detectBinary = params.detectBinary ?? defaultDetectBinary;
|
||||
|
||||
return {
|
||||
configuredLabel: params.configuredLabel,
|
||||
unconfiguredLabel: params.unconfiguredLabel,
|
||||
@@ -31,7 +32,7 @@ export function createDetectedBinaryStatus(params: {
|
||||
configuredScore: params.configuredScore,
|
||||
unconfiguredScore: params.unconfiguredScore,
|
||||
resolveConfigured: params.resolveConfigured,
|
||||
resolveStatusLines: async ({ cfg, configured }: SetupStatusParams) => {
|
||||
async resolveStatusLines({ cfg, configured }: SetupStatusParams): Promise<string[]> {
|
||||
const binaryPath = params.resolveBinaryPath({ cfg });
|
||||
const detected = await detectBinary(binaryPath);
|
||||
return [
|
||||
@@ -39,14 +40,26 @@ export function createDetectedBinaryStatus(params: {
|
||||
`${params.binaryLabel}: ${detected ? "found" : "missing"} (${binaryPath})`,
|
||||
];
|
||||
},
|
||||
resolveSelectionHint: async ({ cfg }) =>
|
||||
(await detectBinary(params.resolveBinaryPath({ cfg })))
|
||||
async resolveSelectionHint({
|
||||
cfg,
|
||||
}: {
|
||||
cfg: OpenClawConfig;
|
||||
configured: boolean;
|
||||
}): Promise<string | undefined> {
|
||||
return (await detectBinary(params.resolveBinaryPath({ cfg })))
|
||||
? params.configuredHint
|
||||
: params.unconfiguredHint,
|
||||
resolveQuickstartScore: async ({ cfg }) =>
|
||||
(await detectBinary(params.resolveBinaryPath({ cfg })))
|
||||
: params.unconfiguredHint;
|
||||
},
|
||||
async resolveQuickstartScore({
|
||||
cfg,
|
||||
}: {
|
||||
cfg: OpenClawConfig;
|
||||
configured: boolean;
|
||||
}): Promise<number | undefined> {
|
||||
return (await detectBinary(params.resolveBinaryPath({ cfg })))
|
||||
? params.configuredScore
|
||||
: params.unconfiguredScore,
|
||||
: params.unconfiguredScore;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -78,12 +91,15 @@ export function createDelegatedSetupWizardStatusResolvers(
|
||||
"resolveStatusLines" | "resolveSelectionHint" | "resolveQuickstartScore"
|
||||
> {
|
||||
return {
|
||||
resolveStatusLines: async (params) =>
|
||||
(await loadWizard()).status.resolveStatusLines?.(params) ?? [],
|
||||
resolveSelectionHint: async (params) =>
|
||||
await (await loadWizard()).status.resolveSelectionHint?.(params),
|
||||
resolveQuickstartScore: async (params) =>
|
||||
await (await loadWizard()).status.resolveQuickstartScore?.(params),
|
||||
async resolveStatusLines(params) {
|
||||
return (await loadWizard()).status.resolveStatusLines?.(params) ?? [];
|
||||
},
|
||||
async resolveSelectionHint(params) {
|
||||
return await (await loadWizard()).status.resolveSelectionHint?.(params);
|
||||
},
|
||||
async resolveQuickstartScore(params) {
|
||||
return await (await loadWizard()).status.resolveQuickstartScore?.(params);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import type { OpenClawConfig } from "../../../config/config.js";
|
||||
import type { SecretInput } from "../../../config/types.secrets.js";
|
||||
import { applyLitellmConfig } from "../../../plugin-sdk/litellm.js";
|
||||
import { applyAuthProfileConfig } from "../../../plugins/provider-auth-helpers.js";
|
||||
import { setLitellmApiKey } from "../../../plugins/provider-auth-storage.js";
|
||||
import type { RuntimeEnv } from "../../../runtime.js";
|
||||
import type { AuthChoice, OnboardOptions } from "../../onboard-types.js";
|
||||
|
||||
type ApiKeyStorageOptions = {
|
||||
secretInputMode: "plaintext" | "ref";
|
||||
};
|
||||
|
||||
type ResolvedNonInteractiveApiKey = {
|
||||
key: string;
|
||||
source: "profile" | "env" | "flag";
|
||||
};
|
||||
|
||||
export async function applySimpleNonInteractiveApiKeyChoice(params: {
|
||||
authChoice: AuthChoice;
|
||||
nextConfig: OpenClawConfig;
|
||||
baseConfig: OpenClawConfig;
|
||||
opts: OnboardOptions;
|
||||
runtime: RuntimeEnv;
|
||||
apiKeyStorageOptions?: ApiKeyStorageOptions;
|
||||
resolveApiKey: (input: {
|
||||
provider: string;
|
||||
cfg: OpenClawConfig;
|
||||
flagValue?: string;
|
||||
flagName: `--${string}`;
|
||||
envVar: string;
|
||||
runtime: RuntimeEnv;
|
||||
}) => Promise<ResolvedNonInteractiveApiKey | null>;
|
||||
maybeSetResolvedApiKey: (
|
||||
resolved: ResolvedNonInteractiveApiKey,
|
||||
setter: (value: SecretInput) => Promise<void> | void,
|
||||
) => Promise<boolean>;
|
||||
}): Promise<OpenClawConfig | null | undefined> {
|
||||
if (params.authChoice !== "litellm-api-key") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const resolved = await params.resolveApiKey({
|
||||
provider: "litellm",
|
||||
cfg: params.baseConfig,
|
||||
flagValue: params.opts.litellmApiKey,
|
||||
flagName: "--litellm-api-key",
|
||||
envVar: "LITELLM_API_KEY",
|
||||
runtime: params.runtime,
|
||||
});
|
||||
if (!resolved) {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
!(await params.maybeSetResolvedApiKey(resolved, (value) =>
|
||||
setLitellmApiKey(value, undefined, params.apiKeyStorageOptions),
|
||||
))
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return applyLitellmConfig(
|
||||
applyAuthProfileConfig(params.nextConfig, {
|
||||
profileId: "litellm:default",
|
||||
provider: "litellm",
|
||||
mode: "api_key",
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -307,103 +307,345 @@ function logToFile(
|
||||
|
||||
export function createSubsystemLogger(subsystem: string): SubsystemLogger {
|
||||
let fileLogger: TsLogger<LogObj> | null = null;
|
||||
const getFileLogger = (): TsLogger<LogObj> => {
|
||||
if (!fileLogger) {
|
||||
fileLogger = getChildLogger({ subsystem });
|
||||
}
|
||||
return fileLogger;
|
||||
};
|
||||
const emit = (level: LogLevel, message: string, meta?: Record<string, unknown>): void => {
|
||||
const consoleSettings = getConsoleSettings();
|
||||
const consoleEnabled =
|
||||
shouldLogToConsole(level, { level: consoleSettings.level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem);
|
||||
const fileEnabled = isFileLogLevelEnabled(level);
|
||||
if (!consoleEnabled && !fileEnabled) {
|
||||
return;
|
||||
}
|
||||
let consoleMessageOverride: string | undefined;
|
||||
let fileMeta = meta;
|
||||
if (meta && Object.keys(meta).length > 0) {
|
||||
const { consoleMessage, ...rest } = meta as Record<string, unknown> & {
|
||||
consoleMessage?: unknown;
|
||||
};
|
||||
if (typeof consoleMessage === "string") {
|
||||
consoleMessageOverride = consoleMessage;
|
||||
}
|
||||
fileMeta = Object.keys(rest).length > 0 ? rest : undefined;
|
||||
}
|
||||
if (fileEnabled) {
|
||||
logToFile(getFileLogger(), level, message, fileMeta);
|
||||
}
|
||||
if (!consoleEnabled) {
|
||||
return;
|
||||
}
|
||||
const consoleMessage = consoleMessageOverride ?? message;
|
||||
if (
|
||||
shouldSuppressProbeConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleMessage,
|
||||
meta: fileMeta,
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const line = formatConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleSettings.style === "json" ? message : consoleMessage,
|
||||
style: consoleSettings.style,
|
||||
meta: fileMeta,
|
||||
});
|
||||
writeConsoleLine(level, line);
|
||||
};
|
||||
const isConsoleEnabled = (level: LogLevel): boolean => {
|
||||
const consoleSettings = getConsoleSettings();
|
||||
return (
|
||||
shouldLogToConsole(level, { level: consoleSettings.level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem)
|
||||
);
|
||||
};
|
||||
const isFileEnabled = (level: LogLevel): boolean => {
|
||||
return isFileLogLevelEnabled(level);
|
||||
};
|
||||
|
||||
const logger: SubsystemLogger = {
|
||||
subsystem,
|
||||
isEnabled(level, target = "any") {
|
||||
const isConsoleEnabled =
|
||||
shouldLogToConsole(level, { level: getConsoleSettings().level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem);
|
||||
const isFileEnabled = isFileLogLevelEnabled(level);
|
||||
if (target === "console") {
|
||||
return isConsoleEnabled(level);
|
||||
return isConsoleEnabled;
|
||||
}
|
||||
if (target === "file") {
|
||||
return isFileEnabled(level);
|
||||
return isFileEnabled;
|
||||
}
|
||||
return isConsoleEnabled(level) || isFileEnabled(level);
|
||||
return isConsoleEnabled || isFileEnabled;
|
||||
},
|
||||
trace(message, meta) {
|
||||
emit("trace", message, meta);
|
||||
const level: LogLevel = "trace";
|
||||
const consoleSettings = getConsoleSettings();
|
||||
const consoleEnabled =
|
||||
shouldLogToConsole(level, { level: consoleSettings.level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem);
|
||||
const fileEnabled = isFileLogLevelEnabled(level);
|
||||
if (!consoleEnabled && !fileEnabled) {
|
||||
return;
|
||||
}
|
||||
let consoleMessageOverride: string | undefined;
|
||||
let fileMeta = meta;
|
||||
if (meta && Object.keys(meta).length > 0) {
|
||||
const { consoleMessage, ...rest } = meta as Record<string, unknown> & {
|
||||
consoleMessage?: unknown;
|
||||
};
|
||||
if (typeof consoleMessage === "string") {
|
||||
consoleMessageOverride = consoleMessage;
|
||||
}
|
||||
fileMeta = Object.keys(rest).length > 0 ? rest : undefined;
|
||||
}
|
||||
if (fileEnabled) {
|
||||
if (!fileLogger) {
|
||||
fileLogger = getChildLogger({ subsystem });
|
||||
}
|
||||
logToFile(fileLogger, level, message, fileMeta);
|
||||
}
|
||||
if (!consoleEnabled) {
|
||||
return;
|
||||
}
|
||||
const consoleMessage = consoleMessageOverride ?? message;
|
||||
if (
|
||||
shouldSuppressProbeConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleMessage,
|
||||
meta: fileMeta,
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
writeConsoleLine(
|
||||
level,
|
||||
formatConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleSettings.style === "json" ? message : consoleMessage,
|
||||
style: consoleSettings.style,
|
||||
meta: fileMeta,
|
||||
}),
|
||||
);
|
||||
},
|
||||
debug(message, meta) {
|
||||
emit("debug", message, meta);
|
||||
const level: LogLevel = "debug";
|
||||
const consoleSettings = getConsoleSettings();
|
||||
const consoleEnabled =
|
||||
shouldLogToConsole(level, { level: consoleSettings.level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem);
|
||||
const fileEnabled = isFileLogLevelEnabled(level);
|
||||
if (!consoleEnabled && !fileEnabled) {
|
||||
return;
|
||||
}
|
||||
let consoleMessageOverride: string | undefined;
|
||||
let fileMeta = meta;
|
||||
if (meta && Object.keys(meta).length > 0) {
|
||||
const { consoleMessage, ...rest } = meta as Record<string, unknown> & {
|
||||
consoleMessage?: unknown;
|
||||
};
|
||||
if (typeof consoleMessage === "string") {
|
||||
consoleMessageOverride = consoleMessage;
|
||||
}
|
||||
fileMeta = Object.keys(rest).length > 0 ? rest : undefined;
|
||||
}
|
||||
if (fileEnabled) {
|
||||
if (!fileLogger) {
|
||||
fileLogger = getChildLogger({ subsystem });
|
||||
}
|
||||
logToFile(fileLogger, level, message, fileMeta);
|
||||
}
|
||||
if (!consoleEnabled) {
|
||||
return;
|
||||
}
|
||||
const consoleMessage = consoleMessageOverride ?? message;
|
||||
if (
|
||||
shouldSuppressProbeConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleMessage,
|
||||
meta: fileMeta,
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
writeConsoleLine(
|
||||
level,
|
||||
formatConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleSettings.style === "json" ? message : consoleMessage,
|
||||
style: consoleSettings.style,
|
||||
meta: fileMeta,
|
||||
}),
|
||||
);
|
||||
},
|
||||
info(message, meta) {
|
||||
emit("info", message, meta);
|
||||
const level: LogLevel = "info";
|
||||
const consoleSettings = getConsoleSettings();
|
||||
const consoleEnabled =
|
||||
shouldLogToConsole(level, { level: consoleSettings.level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem);
|
||||
const fileEnabled = isFileLogLevelEnabled(level);
|
||||
if (!consoleEnabled && !fileEnabled) {
|
||||
return;
|
||||
}
|
||||
let consoleMessageOverride: string | undefined;
|
||||
let fileMeta = meta;
|
||||
if (meta && Object.keys(meta).length > 0) {
|
||||
const { consoleMessage, ...rest } = meta as Record<string, unknown> & {
|
||||
consoleMessage?: unknown;
|
||||
};
|
||||
if (typeof consoleMessage === "string") {
|
||||
consoleMessageOverride = consoleMessage;
|
||||
}
|
||||
fileMeta = Object.keys(rest).length > 0 ? rest : undefined;
|
||||
}
|
||||
if (fileEnabled) {
|
||||
if (!fileLogger) {
|
||||
fileLogger = getChildLogger({ subsystem });
|
||||
}
|
||||
logToFile(fileLogger, level, message, fileMeta);
|
||||
}
|
||||
if (!consoleEnabled) {
|
||||
return;
|
||||
}
|
||||
const consoleMessage = consoleMessageOverride ?? message;
|
||||
if (
|
||||
shouldSuppressProbeConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleMessage,
|
||||
meta: fileMeta,
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
writeConsoleLine(
|
||||
level,
|
||||
formatConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleSettings.style === "json" ? message : consoleMessage,
|
||||
style: consoleSettings.style,
|
||||
meta: fileMeta,
|
||||
}),
|
||||
);
|
||||
},
|
||||
warn(message, meta) {
|
||||
emit("warn", message, meta);
|
||||
const level: LogLevel = "warn";
|
||||
const consoleSettings = getConsoleSettings();
|
||||
const consoleEnabled =
|
||||
shouldLogToConsole(level, { level: consoleSettings.level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem);
|
||||
const fileEnabled = isFileLogLevelEnabled(level);
|
||||
if (!consoleEnabled && !fileEnabled) {
|
||||
return;
|
||||
}
|
||||
let consoleMessageOverride: string | undefined;
|
||||
let fileMeta = meta;
|
||||
if (meta && Object.keys(meta).length > 0) {
|
||||
const { consoleMessage, ...rest } = meta as Record<string, unknown> & {
|
||||
consoleMessage?: unknown;
|
||||
};
|
||||
if (typeof consoleMessage === "string") {
|
||||
consoleMessageOverride = consoleMessage;
|
||||
}
|
||||
fileMeta = Object.keys(rest).length > 0 ? rest : undefined;
|
||||
}
|
||||
if (fileEnabled) {
|
||||
if (!fileLogger) {
|
||||
fileLogger = getChildLogger({ subsystem });
|
||||
}
|
||||
logToFile(fileLogger, level, message, fileMeta);
|
||||
}
|
||||
if (!consoleEnabled) {
|
||||
return;
|
||||
}
|
||||
const consoleMessage = consoleMessageOverride ?? message;
|
||||
if (
|
||||
shouldSuppressProbeConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleMessage,
|
||||
meta: fileMeta,
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
writeConsoleLine(
|
||||
level,
|
||||
formatConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleSettings.style === "json" ? message : consoleMessage,
|
||||
style: consoleSettings.style,
|
||||
meta: fileMeta,
|
||||
}),
|
||||
);
|
||||
},
|
||||
error(message, meta) {
|
||||
emit("error", message, meta);
|
||||
const level: LogLevel = "error";
|
||||
const consoleSettings = getConsoleSettings();
|
||||
const consoleEnabled =
|
||||
shouldLogToConsole(level, { level: consoleSettings.level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem);
|
||||
const fileEnabled = isFileLogLevelEnabled(level);
|
||||
if (!consoleEnabled && !fileEnabled) {
|
||||
return;
|
||||
}
|
||||
let consoleMessageOverride: string | undefined;
|
||||
let fileMeta = meta;
|
||||
if (meta && Object.keys(meta).length > 0) {
|
||||
const { consoleMessage, ...rest } = meta as Record<string, unknown> & {
|
||||
consoleMessage?: unknown;
|
||||
};
|
||||
if (typeof consoleMessage === "string") {
|
||||
consoleMessageOverride = consoleMessage;
|
||||
}
|
||||
fileMeta = Object.keys(rest).length > 0 ? rest : undefined;
|
||||
}
|
||||
if (fileEnabled) {
|
||||
if (!fileLogger) {
|
||||
fileLogger = getChildLogger({ subsystem });
|
||||
}
|
||||
logToFile(fileLogger, level, message, fileMeta);
|
||||
}
|
||||
if (!consoleEnabled) {
|
||||
return;
|
||||
}
|
||||
const consoleMessage = consoleMessageOverride ?? message;
|
||||
if (
|
||||
shouldSuppressProbeConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleMessage,
|
||||
meta: fileMeta,
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
writeConsoleLine(
|
||||
level,
|
||||
formatConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleSettings.style === "json" ? message : consoleMessage,
|
||||
style: consoleSettings.style,
|
||||
meta: fileMeta,
|
||||
}),
|
||||
);
|
||||
},
|
||||
fatal(message, meta) {
|
||||
emit("fatal", message, meta);
|
||||
const level: LogLevel = "fatal";
|
||||
const consoleSettings = getConsoleSettings();
|
||||
const consoleEnabled =
|
||||
shouldLogToConsole(level, { level: consoleSettings.level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem);
|
||||
const fileEnabled = isFileLogLevelEnabled(level);
|
||||
if (!consoleEnabled && !fileEnabled) {
|
||||
return;
|
||||
}
|
||||
let consoleMessageOverride: string | undefined;
|
||||
let fileMeta = meta;
|
||||
if (meta && Object.keys(meta).length > 0) {
|
||||
const { consoleMessage, ...rest } = meta as Record<string, unknown> & {
|
||||
consoleMessage?: unknown;
|
||||
};
|
||||
if (typeof consoleMessage === "string") {
|
||||
consoleMessageOverride = consoleMessage;
|
||||
}
|
||||
fileMeta = Object.keys(rest).length > 0 ? rest : undefined;
|
||||
}
|
||||
if (fileEnabled) {
|
||||
if (!fileLogger) {
|
||||
fileLogger = getChildLogger({ subsystem });
|
||||
}
|
||||
logToFile(fileLogger, level, message, fileMeta);
|
||||
}
|
||||
if (!consoleEnabled) {
|
||||
return;
|
||||
}
|
||||
const consoleMessage = consoleMessageOverride ?? message;
|
||||
if (
|
||||
shouldSuppressProbeConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleMessage,
|
||||
meta: fileMeta,
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
writeConsoleLine(
|
||||
level,
|
||||
formatConsoleLine({
|
||||
level,
|
||||
subsystem,
|
||||
message: consoleSettings.style === "json" ? message : consoleMessage,
|
||||
style: consoleSettings.style,
|
||||
meta: fileMeta,
|
||||
}),
|
||||
);
|
||||
},
|
||||
raw(message) {
|
||||
if (isFileEnabled("info")) {
|
||||
logToFile(getFileLogger(), "info", message, { raw: true });
|
||||
if (isFileLogLevelEnabled("info")) {
|
||||
if (!fileLogger) {
|
||||
fileLogger = getChildLogger({ subsystem });
|
||||
}
|
||||
logToFile(fileLogger, "info", message, { raw: true });
|
||||
}
|
||||
if (isConsoleEnabled("info")) {
|
||||
if (
|
||||
shouldLogToConsole("info", { level: getConsoleSettings().level }) &&
|
||||
shouldLogSubsystemToConsole(subsystem)
|
||||
) {
|
||||
if (shouldSuppressProbeConsoleLine({ level: "info", subsystem, message })) {
|
||||
return;
|
||||
}
|
||||
@@ -421,16 +663,27 @@ export function runtimeForLogger(
|
||||
logger: SubsystemLogger,
|
||||
exit: RuntimeEnv["exit"] = defaultRuntime.exit,
|
||||
): OutputRuntimeEnv {
|
||||
const formatArgs = (...args: unknown[]) =>
|
||||
args
|
||||
.map((arg) => formatRuntimeArg(arg))
|
||||
.join(" ")
|
||||
.trim();
|
||||
return {
|
||||
log: (...args: unknown[]) => logger.info(formatArgs(...args)),
|
||||
error: (...args: unknown[]) => logger.error(formatArgs(...args)),
|
||||
writeStdout: (value: string) => logger.info(value),
|
||||
writeJson: (value: unknown, space = 2) => {
|
||||
log(...args) {
|
||||
logger.info(
|
||||
args
|
||||
.map((arg) => formatRuntimeArg(arg))
|
||||
.join(" ")
|
||||
.trim(),
|
||||
);
|
||||
},
|
||||
error(...args) {
|
||||
logger.error(
|
||||
args
|
||||
.map((arg) => formatRuntimeArg(arg))
|
||||
.join(" ")
|
||||
.trim(),
|
||||
);
|
||||
},
|
||||
writeStdout(value) {
|
||||
logger.info(value);
|
||||
},
|
||||
writeJson(value: unknown, space = 2) {
|
||||
logger.info(JSON.stringify(value, null, space > 0 ? space : undefined));
|
||||
},
|
||||
exit,
|
||||
|
||||
8
src/plugin-sdk/litellm.ts
Normal file
8
src/plugin-sdk/litellm.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export {
|
||||
applyLitellmConfig,
|
||||
applyLitellmProviderConfig,
|
||||
buildLitellmModelDefinition,
|
||||
LITELLM_BASE_URL,
|
||||
LITELLM_DEFAULT_MODEL_ID,
|
||||
LITELLM_DEFAULT_MODEL_REF,
|
||||
} from "../../extensions/litellm/onboard.js";
|
||||
@@ -1,10 +1,48 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { emptyPluginConfigSchema } from "../plugins/config-schema.js";
|
||||
import type {
|
||||
AnyAgentTool,
|
||||
MediaUnderstandingProviderPlugin,
|
||||
OpenClawPluginApi,
|
||||
OpenClawPluginCommandDefinition,
|
||||
OpenClawPluginConfigSchema,
|
||||
OpenClawPluginDefinition,
|
||||
OpenClawPluginService,
|
||||
OpenClawPluginServiceContext,
|
||||
OpenClawPluginToolContext,
|
||||
OpenClawPluginToolFactory,
|
||||
PluginInteractiveTelegramHandlerContext,
|
||||
PluginLogger,
|
||||
ProviderAugmentModelCatalogContext,
|
||||
ProviderAuthContext,
|
||||
ProviderAuthDoctorHintContext,
|
||||
ProviderAuthMethod,
|
||||
ProviderAuthMethodNonInteractiveContext,
|
||||
ProviderAuthResult,
|
||||
ProviderBuildMissingAuthMessageContext,
|
||||
ProviderBuildUnknownModelHintContext,
|
||||
ProviderBuiltInModelSuppressionContext,
|
||||
ProviderBuiltInModelSuppressionResult,
|
||||
ProviderCacheTtlEligibilityContext,
|
||||
ProviderCatalogContext,
|
||||
ProviderCatalogResult,
|
||||
ProviderDefaultThinkingPolicyContext,
|
||||
ProviderDiscoveryContext,
|
||||
ProviderFetchUsageSnapshotContext,
|
||||
ProviderModernModelPolicyContext,
|
||||
ProviderNormalizeResolvedModelContext,
|
||||
ProviderPrepareDynamicModelContext,
|
||||
ProviderPrepareExtraParamsContext,
|
||||
ProviderPrepareRuntimeAuthContext,
|
||||
ProviderPreparedRuntimeAuth,
|
||||
ProviderResolvedUsageAuth,
|
||||
ProviderResolveDynamicModelContext,
|
||||
ProviderResolveUsageAuthContext,
|
||||
ProviderRuntimeModel,
|
||||
ProviderThinkingPolicyContext,
|
||||
ProviderWrapStreamFnContext,
|
||||
SpeechProviderPlugin,
|
||||
PluginCommandContext,
|
||||
} from "../plugins/types.js";
|
||||
|
||||
export type {
|
||||
@@ -50,8 +88,8 @@ export type {
|
||||
OpenClawPluginDefinition,
|
||||
PluginLogger,
|
||||
PluginInteractiveTelegramHandlerContext,
|
||||
} from "../plugins/types.js";
|
||||
export type { OpenClawConfig } from "../config/config.js";
|
||||
};
|
||||
export type { OpenClawConfig };
|
||||
|
||||
export { emptyPluginConfigSchema } from "../plugins/config-schema.js";
|
||||
|
||||
|
||||
@@ -7,7 +7,12 @@ let monolithicSdk = null;
|
||||
let diagnosticEventsModule = null;
|
||||
const jitiLoaders = new Map();
|
||||
const pluginSdkSubpathsCache = new Map();
|
||||
const shouldPreferSourceInTests = Boolean(process.env.VITEST) || process.env.NODE_ENV === "test";
|
||||
const shouldPreferSourceInTests =
|
||||
process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST === "1"
|
||||
? false
|
||||
: Boolean(process.env.VITEST) ||
|
||||
process.env.NODE_ENV === "test" ||
|
||||
process.env.OPENCLAW_PLUGIN_SDK_SOURCE_IN_TESTS === "1";
|
||||
|
||||
function emptyPluginConfigSchema() {
|
||||
function error(message) {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Command } from "commander";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { afterAll, afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { registerPluginCliCommands } from "./cli.js";
|
||||
import { clearPluginLoaderCache } from "./loader.js";
|
||||
import { clearPluginManifestRegistryCache } from "./manifest-registry.js";
|
||||
import { resetPluginRuntimeStateForTest } from "./runtime.js";
|
||||
|
||||
const previousPreferDistPluginSdk = process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST;
|
||||
process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST = "1";
|
||||
|
||||
function resetPluginState() {
|
||||
clearPluginLoaderCache();
|
||||
clearPluginManifestRegistryCache();
|
||||
@@ -21,6 +24,14 @@ describe("registerPluginCliCommands browser plugin integration", () => {
|
||||
resetPluginState();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
if (previousPreferDistPluginSdk === undefined) {
|
||||
delete process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST;
|
||||
} else {
|
||||
process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST = previousPreferDistPluginSdk;
|
||||
}
|
||||
});
|
||||
|
||||
it("registers the browser command from the bundled browser plugin", () => {
|
||||
const program = new Command();
|
||||
registerPluginCliCommands(program, {
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { webSearchProviderContractRegistry } from "./registry.js";
|
||||
import { installWebSearchProviderContractSuite } from "./suites.js";
|
||||
import { afterAll, describe, expect, it } from "vitest";
|
||||
|
||||
const previousPreferDistPluginSdk = process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST;
|
||||
process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST = "1";
|
||||
|
||||
const { webSearchProviderContractRegistry } = await import("./registry.js");
|
||||
const { installWebSearchProviderContractSuite } = await import("./suites.js");
|
||||
|
||||
afterAll(() => {
|
||||
if (previousPreferDistPluginSdk === undefined) {
|
||||
delete process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST;
|
||||
} else {
|
||||
process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST = previousPreferDistPluginSdk;
|
||||
}
|
||||
});
|
||||
|
||||
describe("web search provider contract registry load", () => {
|
||||
it("loads bundled web search providers", () => {
|
||||
|
||||
@@ -54,6 +54,8 @@ function mkdirSafe(dir: string) {
|
||||
const fixtureRoot = mkdtempSafe(path.join(os.tmpdir(), "openclaw-plugin-"));
|
||||
let tempDirIndex = 0;
|
||||
const prevBundledDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
const prevPreferDistPluginSdk = process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST;
|
||||
process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST = "1";
|
||||
const EMPTY_PLUGIN_SCHEMA = { type: "object", additionalProperties: false, properties: {} };
|
||||
let cachedBundledTelegramDir = "";
|
||||
let cachedBundledMemoryDir = "";
|
||||
@@ -721,6 +723,11 @@ afterAll(() => {
|
||||
} finally {
|
||||
cachedBundledTelegramDir = "";
|
||||
cachedBundledMemoryDir = "";
|
||||
if (prevPreferDistPluginSdk === undefined) {
|
||||
delete process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST;
|
||||
} else {
|
||||
process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST = prevPreferDistPluginSdk;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -161,7 +161,10 @@ export function resolvePluginSdkAliasCandidateOrder(params: {
|
||||
}): PluginSdkAliasCandidateKind[] {
|
||||
const normalizedModulePath = params.modulePath.replace(/\\/g, "/");
|
||||
const isDistRuntime = normalizedModulePath.includes("/dist/");
|
||||
return isDistRuntime || params.isProduction ? ["dist", "src"] : ["src", "dist"];
|
||||
const preferDistInTests = process.env.OPENCLAW_PLUGIN_SDK_PREFER_DIST === "1";
|
||||
return isDistRuntime || params.isProduction || preferDistInTests
|
||||
? ["dist", "src"]
|
||||
: ["src", "dist"];
|
||||
}
|
||||
|
||||
export function listPluginSdkAliasCandidates(params: {
|
||||
|
||||
Reference in New Issue
Block a user