mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-26 08:31:55 +00:00
fix: keep provider discovery on mockable lazy runtime paths
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { ensureAuthProfileStore as ensureAuthProfileStoreImpl } from "./auth-profiles.js";
|
||||
import { ensureAuthProfileStore as ensureAuthProfileStoreImpl } from "./auth-profiles/store.js";
|
||||
|
||||
type EnsureAuthProfileStore = typeof import("./auth-profiles.js").ensureAuthProfileStore;
|
||||
type EnsureAuthProfileStore = typeof import("./auth-profiles/store.js").ensureAuthProfileStore;
|
||||
|
||||
export function ensureAuthProfileStore(
|
||||
...args: Parameters<EnsureAuthProfileStore>
|
||||
|
||||
@@ -2,8 +2,8 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const normalizeProviderModelIdWithPluginMock = vi.fn();
|
||||
|
||||
vi.mock("../plugins/provider-runtime.js", () => ({
|
||||
normalizeProviderModelIdWithPlugin: (params: unknown) =>
|
||||
vi.mock("./provider-model-normalization.runtime.js", () => ({
|
||||
normalizeProviderModelIdWithRuntime: (params: unknown) =>
|
||||
normalizeProviderModelIdWithPluginMock(params),
|
||||
}));
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@ import {
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { normalizeGoogleModelId } from "../plugin-sdk/google.js";
|
||||
import { normalizeXaiModelId } from "../plugin-sdk/xai.js";
|
||||
import { resolveRuntimeCliBackends } from "../plugins/cli-backends.runtime.js";
|
||||
import { normalizeProviderModelIdWithPlugin } from "../plugins/provider-runtime.js";
|
||||
import { sanitizeForLog } from "../terminal/ansi.js";
|
||||
import {
|
||||
resolveAgentConfig,
|
||||
@@ -26,9 +24,34 @@ import {
|
||||
normalizeProviderId,
|
||||
normalizeProviderIdForAuth,
|
||||
} from "./provider-id.js";
|
||||
import { normalizeProviderModelIdWithRuntime } from "./provider-model-normalization.runtime.js";
|
||||
|
||||
let log: ReturnType<typeof createSubsystemLogger> | null = null;
|
||||
|
||||
type CliBackendRuntimeModule = typeof import("../plugins/cli-backends.runtime.js");
|
||||
|
||||
const CLI_BACKEND_RUNTIME_CANDIDATES = [
|
||||
"../plugins/cli-backends.runtime.js",
|
||||
"../plugins/cli-backends.runtime.ts",
|
||||
] as const;
|
||||
|
||||
let cliBackendRuntimeModule: CliBackendRuntimeModule | undefined;
|
||||
|
||||
function loadCliBackendRuntime(): CliBackendRuntimeModule | null {
|
||||
if (cliBackendRuntimeModule) {
|
||||
return cliBackendRuntimeModule;
|
||||
}
|
||||
for (const candidate of CLI_BACKEND_RUNTIME_CANDIDATES) {
|
||||
try {
|
||||
cliBackendRuntimeModule = require(candidate) as CliBackendRuntimeModule;
|
||||
return cliBackendRuntimeModule;
|
||||
} catch {
|
||||
// Try source/runtime candidates in order.
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getLog(): ReturnType<typeof createSubsystemLogger> {
|
||||
log ??= createSubsystemLogger("model-selection");
|
||||
return log;
|
||||
@@ -84,9 +107,8 @@ export {
|
||||
|
||||
export function isCliProvider(provider: string, cfg?: OpenClawConfig): boolean {
|
||||
const normalized = normalizeProviderId(provider);
|
||||
if (
|
||||
resolveRuntimeCliBackends().some((backend) => normalizeProviderId(backend.id) === normalized)
|
||||
) {
|
||||
const cliBackends = loadCliBackendRuntime()?.resolveRuntimeCliBackends() ?? [];
|
||||
if (cliBackends.some((backend) => normalizeProviderId(backend.id) === normalized)) {
|
||||
return true;
|
||||
}
|
||||
const backends = cfg?.agents?.defaults?.cliBackends ?? {};
|
||||
@@ -139,7 +161,7 @@ function normalizeProviderModelId(provider: string, model: string): string {
|
||||
}
|
||||
}
|
||||
return (
|
||||
normalizeProviderModelIdWithPlugin({
|
||||
normalizeProviderModelIdWithRuntime({
|
||||
provider,
|
||||
context: {
|
||||
provider,
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
resolvePluginDiscoveryProviders,
|
||||
runProviderCatalog,
|
||||
} from "../plugins/provider-discovery.js";
|
||||
import { ensureAuthProfileStore } from "./auth-profiles.js";
|
||||
import { ensureAuthProfileStore } from "./auth-profiles/store.js";
|
||||
import type {
|
||||
ProviderApiKeyResolver,
|
||||
ProviderAuthResolver,
|
||||
@@ -107,7 +107,7 @@ async function resolvePluginImplicitProviders(
|
||||
order: import("../plugins/types.js").ProviderDiscoveryOrder,
|
||||
): Promise<Record<string, ProviderConfig> | undefined> {
|
||||
const onlyPluginIds = resolveLiveProviderDiscoveryFilter(ctx.env);
|
||||
const providers = resolvePluginDiscoveryProviders({
|
||||
const providers = await resolvePluginDiscoveryProviders({
|
||||
config: ctx.config,
|
||||
workspaceDir: ctx.workspaceDir,
|
||||
env: ctx.env,
|
||||
|
||||
39
src/agents/provider-model-normalization.runtime.ts
Normal file
39
src/agents/provider-model-normalization.runtime.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { createRequire } from "node:module";
|
||||
|
||||
type ProviderRuntimeModule = Pick<
|
||||
typeof import("../plugins/provider-runtime.js"),
|
||||
"normalizeProviderModelIdWithPlugin"
|
||||
>;
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const PROVIDER_RUNTIME_CANDIDATES = [
|
||||
"../plugins/provider-runtime.js",
|
||||
"../plugins/provider-runtime.ts",
|
||||
] as const;
|
||||
|
||||
let providerRuntimeModule: ProviderRuntimeModule | undefined;
|
||||
|
||||
function loadProviderRuntime(): ProviderRuntimeModule | null {
|
||||
if (providerRuntimeModule) {
|
||||
return providerRuntimeModule;
|
||||
}
|
||||
for (const candidate of PROVIDER_RUNTIME_CANDIDATES) {
|
||||
try {
|
||||
providerRuntimeModule = require(candidate) as ProviderRuntimeModule;
|
||||
return providerRuntimeModule;
|
||||
} catch {
|
||||
// Try source/runtime candidates in order.
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function normalizeProviderModelIdWithRuntime(params: {
|
||||
provider: string;
|
||||
context: {
|
||||
provider: string;
|
||||
modelId: string;
|
||||
};
|
||||
}): string | undefined {
|
||||
return loadProviderRuntime()?.normalizeProviderModelIdWithPlugin(params);
|
||||
}
|
||||
@@ -32,7 +32,10 @@ function modelPricingCacheKey(provider: string, model: string): string {
|
||||
function shouldNormalizeCachedPricingLookup(provider: string): boolean {
|
||||
const normalized = normalizeProviderId(provider);
|
||||
return (
|
||||
normalized === "anthropic" || normalized === "openrouter" || WRAPPER_PROVIDERS.has(normalized)
|
||||
normalized === "anthropic" ||
|
||||
normalized === "openrouter" ||
|
||||
normalized === "xai" ||
|
||||
WRAPPER_PROVIDERS.has(normalized)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ const WRAPPER_PROVIDERS = new Set([
|
||||
"openrouter",
|
||||
"vercel-ai-gateway",
|
||||
]);
|
||||
|
||||
const log = createSubsystemLogger("gateway").child("model-pricing");
|
||||
|
||||
let refreshTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
15
src/plugins/provider-discovery.runtime.ts
Normal file
15
src/plugins/provider-discovery.runtime.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolvePluginProviders } from "./providers.runtime.js";
|
||||
import type { ProviderPlugin } from "./types.js";
|
||||
|
||||
export function resolvePluginDiscoveryProvidersRuntime(params: {
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
onlyPluginIds?: string[];
|
||||
}): ProviderPlugin[] {
|
||||
return resolvePluginProviders({
|
||||
...params,
|
||||
bundledProviderAllowlistCompat: true,
|
||||
});
|
||||
}
|
||||
@@ -1,25 +1,29 @@
|
||||
import { normalizeProviderId } from "../agents/model-selection.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { ModelProviderConfig } from "../config/types.js";
|
||||
import { resolvePluginProviders } from "./providers.runtime.js";
|
||||
import type { ProviderDiscoveryOrder, ProviderPlugin } from "./types.js";
|
||||
|
||||
const DISCOVERY_ORDER: readonly ProviderDiscoveryOrder[] = ["simple", "profile", "paired", "late"];
|
||||
let providerRuntimePromise: Promise<typeof import("./provider-discovery.runtime.js")> | undefined;
|
||||
|
||||
function loadProviderRuntime() {
|
||||
providerRuntimePromise ??= import("./provider-discovery.runtime.js");
|
||||
return providerRuntimePromise;
|
||||
}
|
||||
|
||||
function resolveProviderCatalogHook(provider: ProviderPlugin) {
|
||||
return provider.catalog ?? provider.discovery;
|
||||
}
|
||||
|
||||
export function resolvePluginDiscoveryProviders(params: {
|
||||
export async function resolvePluginDiscoveryProviders(params: {
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
onlyPluginIds?: string[];
|
||||
}): ProviderPlugin[] {
|
||||
return resolvePluginProviders({
|
||||
...params,
|
||||
bundledProviderAllowlistCompat: true,
|
||||
}).filter((provider) => resolveProviderCatalogHook(provider));
|
||||
}): Promise<ProviderPlugin[]> {
|
||||
return (await loadProviderRuntime())
|
||||
.resolvePluginDiscoveryProvidersRuntime(params)
|
||||
.filter((provider) => resolveProviderCatalogHook(provider));
|
||||
}
|
||||
|
||||
export function groupPluginDiscoveryProvidersByOrder(
|
||||
|
||||
Reference in New Issue
Block a user