fix: restore provider runtime lazy boundary

This commit is contained in:
Peter Steinberger 2026-03-23 09:23:30 +00:00
parent 7a92d43d9a
commit 75b65c2a35
5 changed files with 73 additions and 41 deletions

View File

@ -1,16 +1,8 @@
import type { OpenClawConfig } from "../../config/config.js";
import { buildProviderAuthDoctorHintWithPlugin } from "../../plugins/provider-runtime.runtime.js";
import { normalizeProviderId } from "../model-selection.js";
import type { AuthProfileStore } from "./types.js";
let providerRuntimePromise:
| Promise<typeof import("../../plugins/provider-runtime.runtime.js")>
| undefined;
function loadProviderRuntime() {
providerRuntimePromise ??= import("../../plugins/provider-runtime.runtime.js");
return providerRuntimePromise;
}
export async function formatAuthDoctorHint(params: {
cfg?: OpenClawConfig;
store: AuthProfileStore;
@ -18,7 +10,6 @@ export async function formatAuthDoctorHint(params: {
profileId?: string;
}): Promise<string> {
const normalizedProvider = normalizeProviderId(params.provider);
const { buildProviderAuthDoctorHintWithPlugin } = await loadProviderRuntime();
const pluginHint = await buildProviderAuthDoctorHintWithPlugin({
provider: normalizedProvider,
context: {

View File

@ -7,6 +7,10 @@ import {
import { loadConfig, type OpenClawConfig } from "../../config/config.js";
import { coerceSecretRef } from "../../config/types.secrets.js";
import { withFileLock } from "../../infra/file-lock.js";
import {
formatProviderAuthProfileApiKeyWithPlugin,
refreshProviderOAuthCredentialWithPlugin,
} from "../../plugins/provider-runtime.runtime.js";
import { resolveSecretRefString, type SecretRefResolveCache } from "../../secrets/resolve.js";
import { refreshChutesTokens } from "../chutes-oauth.js";
import { AUTH_STORE_LOCK_OPTIONS, log } from "./constants.js";
@ -39,15 +43,6 @@ function listOAuthProviderIds(): string[] {
const OAUTH_PROVIDER_IDS = new Set<string>(listOAuthProviderIds());
let providerRuntimePromise:
| Promise<typeof import("../../plugins/provider-runtime.runtime.js")>
| undefined;
function loadProviderRuntime() {
providerRuntimePromise ??= import("../../plugins/provider-runtime.runtime.js");
return providerRuntimePromise;
}
const isOAuthProvider = (provider: string): provider is OAuthProvider =>
OAUTH_PROVIDER_IDS.has(provider);
@ -86,8 +81,7 @@ function isProfileConfigCompatible(params: {
}
async function buildOAuthApiKey(provider: string, credentials: OAuthCredential): Promise<string> {
const { formatProviderAuthProfileApiKeyWithPlugin } = await loadProviderRuntime();
const formatted = formatProviderAuthProfileApiKeyWithPlugin({
const formatted = await formatProviderAuthProfileApiKeyWithPlugin({
provider,
context: credentials,
});
@ -185,7 +179,6 @@ async function refreshOAuthTokenWithLock(params: {
};
}
const { refreshProviderOAuthCredentialWithPlugin } = await loadProviderRuntime();
const pluginRefreshed = await refreshProviderOAuthCredentialWithPlugin({
provider: cred.provider,
context: cred,

View File

@ -369,7 +369,7 @@ export async function resolveApiKeyForProvider(params: {
})
: undefined;
if (owningPluginIds?.length) {
const pluginMissingAuthMessage = buildProviderMissingAuthMessageWithPlugin({
const pluginMissingAuthMessage = await buildProviderMissingAuthMessageWithPlugin({
provider,
config: cfg,
context: {

View File

@ -1,5 +1,6 @@
import { type OpenClawConfig, loadConfig } from "../config/config.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
import { augmentModelCatalogWithProviderPlugins } from "../plugins/provider-runtime.runtime.js";
import { resolveOpenClawAgentDir } from "./agent-paths.js";
import { ensureOpenClawModelsJson } from "./models-config.js";
@ -31,9 +32,6 @@ let modelCatalogPromise: Promise<ModelCatalogEntry[]> | null = null;
let hasLoggedModelCatalogError = false;
const defaultImportPiSdk = () => import("./pi-model-discovery-runtime.js");
let importPiSdk = defaultImportPiSdk;
let providerRuntimePromise:
| Promise<typeof import("../plugins/provider-runtime.runtime.js")>
| undefined;
let modelSuppressionPromise: Promise<typeof import("./model-suppression.runtime.js")> | undefined;
const NON_PI_NATIVE_MODEL_PROVIDERS = new Set(["kilocode"]);
@ -42,11 +40,6 @@ function shouldLogModelCatalogTiming(): boolean {
return process.env.OPENCLAW_DEBUG_INGRESS_TIMING === "1";
}
function loadProviderRuntime() {
providerRuntimePromise ??= import("../plugins/provider-runtime.runtime.js");
return providerRuntimePromise;
}
function loadModelSuppression() {
modelSuppressionPromise ??= import("./model-suppression.runtime.js");
return modelSuppressionPromise;
@ -187,8 +180,7 @@ export async function loadModelCatalog(params?: {
const piSdk = await importPiSdk();
logStage("pi-sdk-imported");
const agentDir = resolveOpenClawAgentDir();
const [{ shouldSuppressBuiltInModel }, { augmentModelCatalogWithProviderPlugins }] =
await Promise.all([loadModelSuppression(), loadProviderRuntime()]);
const { shouldSuppressBuiltInModel } = await loadModelSuppression();
logStage("catalog-deps-ready");
const { join } = await import("node:path");
const authStorage = piSdk.discoverAuthStorage(agentDir);

View File

@ -1,8 +1,64 @@
export {
augmentModelCatalogWithProviderPlugins,
buildProviderAuthDoctorHintWithPlugin,
buildProviderMissingAuthMessageWithPlugin,
formatProviderAuthProfileApiKeyWithPlugin,
prepareProviderRuntimeAuth,
refreshProviderOAuthCredentialWithPlugin,
} from "./provider-runtime.js";
type ProviderRuntimeModule = typeof import("./provider-runtime.js");
type AugmentModelCatalogWithProviderPlugins =
ProviderRuntimeModule["augmentModelCatalogWithProviderPlugins"];
type BuildProviderAuthDoctorHintWithPlugin =
ProviderRuntimeModule["buildProviderAuthDoctorHintWithPlugin"];
type BuildProviderMissingAuthMessageWithPlugin =
ProviderRuntimeModule["buildProviderMissingAuthMessageWithPlugin"];
type FormatProviderAuthProfileApiKeyWithPlugin =
ProviderRuntimeModule["formatProviderAuthProfileApiKeyWithPlugin"];
type PrepareProviderRuntimeAuth = ProviderRuntimeModule["prepareProviderRuntimeAuth"];
type RefreshProviderOAuthCredentialWithPlugin =
ProviderRuntimeModule["refreshProviderOAuthCredentialWithPlugin"];
let providerRuntimePromise: Promise<ProviderRuntimeModule> | undefined;
async function loadProviderRuntime(): Promise<ProviderRuntimeModule> {
// Keep the heavy provider runtime behind an actual async boundary so callers
// can import this wrapper eagerly without collapsing the lazy chunk.
providerRuntimePromise ??= import("./provider-runtime.js");
return providerRuntimePromise;
}
export async function augmentModelCatalogWithProviderPlugins(
...args: Parameters<AugmentModelCatalogWithProviderPlugins>
): Promise<Awaited<ReturnType<AugmentModelCatalogWithProviderPlugins>>> {
const runtime = await loadProviderRuntime();
return runtime.augmentModelCatalogWithProviderPlugins(...args);
}
export async function buildProviderAuthDoctorHintWithPlugin(
...args: Parameters<BuildProviderAuthDoctorHintWithPlugin>
): Promise<Awaited<ReturnType<BuildProviderAuthDoctorHintWithPlugin>>> {
const runtime = await loadProviderRuntime();
return runtime.buildProviderAuthDoctorHintWithPlugin(...args);
}
export async function buildProviderMissingAuthMessageWithPlugin(
...args: Parameters<BuildProviderMissingAuthMessageWithPlugin>
): Promise<Awaited<ReturnType<BuildProviderMissingAuthMessageWithPlugin>>> {
const runtime = await loadProviderRuntime();
return runtime.buildProviderMissingAuthMessageWithPlugin(...args);
}
export async function formatProviderAuthProfileApiKeyWithPlugin(
...args: Parameters<FormatProviderAuthProfileApiKeyWithPlugin>
): Promise<Awaited<ReturnType<FormatProviderAuthProfileApiKeyWithPlugin>>> {
const runtime = await loadProviderRuntime();
return runtime.formatProviderAuthProfileApiKeyWithPlugin(...args);
}
export async function prepareProviderRuntimeAuth(
...args: Parameters<PrepareProviderRuntimeAuth>
): Promise<Awaited<ReturnType<PrepareProviderRuntimeAuth>>> {
const runtime = await loadProviderRuntime();
return runtime.prepareProviderRuntimeAuth(...args);
}
export async function refreshProviderOAuthCredentialWithPlugin(
...args: Parameters<RefreshProviderOAuthCredentialWithPlugin>
): Promise<Awaited<ReturnType<RefreshProviderOAuthCredentialWithPlugin>>> {
const runtime = await loadProviderRuntime();
return runtime.refreshProviderOAuthCredentialWithPlugin(...args);
}