From 91d37ccfc309fe4bd87bbdc5017a0273be64b63a Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Wed, 18 Mar 2026 13:40:28 -0700 Subject: [PATCH] fix(auth): lazy-load provider oauth helpers --- extensions/google/gemini-cli-provider.ts | 2 +- extensions/google/oauth.runtime.ts | 1 + extensions/minimax/index.ts | 3 +- extensions/minimax/oauth.runtime.ts | 1 + .../openai/openai-codex-provider.runtime.ts | 1 + extensions/openai/openai-codex-provider.ts | 2 +- extensions/qwen-portal-auth/index.ts | 2 +- extensions/qwen-portal-auth/oauth.runtime.ts | 1 + extensions/telegram/src/bot-deps.ts | 28 ++++++++++++++----- src/plugin-sdk/provider-auth-login.runtime.ts | 3 ++ src/plugin-sdk/provider-auth-login.ts | 17 +++++++++-- src/plugins/loader.ts | 7 ++++- 12 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 extensions/google/oauth.runtime.ts create mode 100644 extensions/minimax/oauth.runtime.ts create mode 100644 extensions/openai/openai-codex-provider.runtime.ts create mode 100644 extensions/qwen-portal-auth/oauth.runtime.ts create mode 100644 src/plugin-sdk/provider-auth-login.runtime.ts diff --git a/extensions/google/gemini-cli-provider.ts b/extensions/google/gemini-cli-provider.ts index ae10da9b2ab..412d02dd85f 100644 --- a/extensions/google/gemini-cli-provider.ts +++ b/extensions/google/gemini-cli-provider.ts @@ -5,7 +5,6 @@ import type { } from "openclaw/plugin-sdk/plugin-entry"; import { buildOauthProviderAuthResult } from "openclaw/plugin-sdk/provider-auth"; import { fetchGeminiUsage } from "openclaw/plugin-sdk/provider-usage"; -import { loginGeminiCliOAuth } from "./oauth.js"; import { isModernGoogleModel, resolveGoogle31ForwardCompatModel } from "./provider-models.js"; const PROVIDER_ID = "google-gemini-cli"; @@ -82,6 +81,7 @@ export function registerGoogleGeminiCliProvider(api: OpenClawPluginApi) { const spin = ctx.prompter.progress("Starting Gemini CLI OAuth…"); try { + const { loginGeminiCliOAuth } = await import("./oauth.runtime.js"); const result = await loginGeminiCliOAuth({ isRemote: ctx.isRemote, openUrl: ctx.openUrl, diff --git a/extensions/google/oauth.runtime.ts b/extensions/google/oauth.runtime.ts new file mode 100644 index 00000000000..4de8039e2b4 --- /dev/null +++ b/extensions/google/oauth.runtime.ts @@ -0,0 +1 @@ +export { loginGeminiCliOAuth } from "./oauth.js"; diff --git a/extensions/minimax/index.ts b/extensions/minimax/index.ts index 5cb40be22b2..e219ceec6a0 100644 --- a/extensions/minimax/index.ts +++ b/extensions/minimax/index.ts @@ -16,7 +16,7 @@ import { minimaxMediaUnderstandingProvider, minimaxPortalMediaUnderstandingProvider, } from "./media-understanding-provider.js"; -import { loginMiniMaxPortalOAuth, type MiniMaxRegion } from "./oauth.js"; +import type { MiniMaxRegion } from "./oauth.js"; import { applyMinimaxApiConfig, applyMinimaxApiConfigCn } from "./onboard.js"; import { buildMinimaxPortalProvider, buildMinimaxProvider } from "./provider-catalog.js"; @@ -97,6 +97,7 @@ function createOAuthHandler(region: MiniMaxRegion) { return async (ctx: ProviderAuthContext): Promise => { const progress = ctx.prompter.progress(`Starting MiniMax OAuth (${regionLabel})…`); try { + const { loginMiniMaxPortalOAuth } = await import("./oauth.runtime.js"); const result = await loginMiniMaxPortalOAuth({ openUrl: ctx.openUrl, note: ctx.prompter.note, diff --git a/extensions/minimax/oauth.runtime.ts b/extensions/minimax/oauth.runtime.ts new file mode 100644 index 00000000000..9659b3f7310 --- /dev/null +++ b/extensions/minimax/oauth.runtime.ts @@ -0,0 +1 @@ +export { loginMiniMaxPortalOAuth } from "./oauth.js"; diff --git a/extensions/openai/openai-codex-provider.runtime.ts b/extensions/openai/openai-codex-provider.runtime.ts new file mode 100644 index 00000000000..fdb5ef8a9bc --- /dev/null +++ b/extensions/openai/openai-codex-provider.runtime.ts @@ -0,0 +1 @@ +export { getOAuthApiKey } from "@mariozechner/pi-ai/oauth"; diff --git a/extensions/openai/openai-codex-provider.ts b/extensions/openai/openai-codex-provider.ts index 9263bf8043c..66d182a341f 100644 --- a/extensions/openai/openai-codex-provider.ts +++ b/extensions/openai/openai-codex-provider.ts @@ -1,4 +1,3 @@ -import { getOAuthApiKey } from "@mariozechner/pi-ai/oauth"; import type { ProviderAuthContext, ProviderResolveDynamicModelContext, @@ -142,6 +141,7 @@ function resolveCodexForwardCompatModel( async function refreshOpenAICodexOAuthCredential(cred: OAuthCredential) { try { + const { getOAuthApiKey } = await import("./openai-codex-provider.runtime.js"); const refreshed = await getOAuthApiKey("openai-codex", { "openai-codex": cred, }); diff --git a/extensions/qwen-portal-auth/index.ts b/extensions/qwen-portal-auth/index.ts index c5789e6cc08..e32eb8ef791 100644 --- a/extensions/qwen-portal-auth/index.ts +++ b/extensions/qwen-portal-auth/index.ts @@ -1,6 +1,5 @@ import { ensureAuthProfileStore, listProfilesForProvider } from "openclaw/plugin-sdk/agent-runtime"; import { QWEN_OAUTH_MARKER } from "openclaw/plugin-sdk/agent-runtime"; -import { loginQwenPortalOAuth } from "./oauth.js"; import { buildQwenPortalProvider, QWEN_PORTAL_BASE_URL } from "./provider-catalog.js"; import { buildOauthProviderAuthResult, @@ -77,6 +76,7 @@ export default definePluginEntry({ run: async (ctx: ProviderAuthContext) => { const progress = ctx.prompter.progress("Starting Qwen OAuth…"); try { + const { loginQwenPortalOAuth } = await import("./oauth.runtime.js"); const result = await loginQwenPortalOAuth({ openUrl: ctx.openUrl, note: ctx.prompter.note, diff --git a/extensions/qwen-portal-auth/oauth.runtime.ts b/extensions/qwen-portal-auth/oauth.runtime.ts new file mode 100644 index 00000000000..8e2e3a0d5c7 --- /dev/null +++ b/extensions/qwen-portal-auth/oauth.runtime.ts @@ -0,0 +1 @@ +export { loginQwenPortalOAuth } from "./oauth.js"; diff --git a/extensions/telegram/src/bot-deps.ts b/extensions/telegram/src/bot-deps.ts index 49193bebdc1..0acf79740ba 100644 --- a/extensions/telegram/src/bot-deps.ts +++ b/extensions/telegram/src/bot-deps.ts @@ -18,11 +18,25 @@ export type TelegramBotDeps = { }; export const defaultTelegramBotDeps: TelegramBotDeps = { - loadConfig, - resolveStorePath, - readChannelAllowFromStore, - enqueueSystemEvent, - dispatchReplyWithBufferedBlockDispatcher, - listSkillCommandsForAgents, - wasSentByBot, + get loadConfig() { + return loadConfig; + }, + get resolveStorePath() { + return resolveStorePath; + }, + get readChannelAllowFromStore() { + return readChannelAllowFromStore; + }, + get enqueueSystemEvent() { + return enqueueSystemEvent; + }, + get dispatchReplyWithBufferedBlockDispatcher() { + return dispatchReplyWithBufferedBlockDispatcher; + }, + get listSkillCommandsForAgents() { + return listSkillCommandsForAgents; + }, + get wasSentByBot() { + return wasSentByBot; + }, }; diff --git a/src/plugin-sdk/provider-auth-login.runtime.ts b/src/plugin-sdk/provider-auth-login.runtime.ts new file mode 100644 index 00000000000..17316952b7e --- /dev/null +++ b/src/plugin-sdk/provider-auth-login.runtime.ts @@ -0,0 +1,3 @@ +export { loginChutes } from "../commands/chutes-oauth.js"; +export { loginOpenAICodexOAuth } from "../plugins/provider-openai-codex-oauth.js"; +export { githubCopilotLoginCommand } from "../providers/github-copilot-auth.js"; diff --git a/src/plugin-sdk/provider-auth-login.ts b/src/plugin-sdk/provider-auth-login.ts index 4d6f55902ab..f4848ef6207 100644 --- a/src/plugin-sdk/provider-auth-login.ts +++ b/src/plugin-sdk/provider-auth-login.ts @@ -1,5 +1,16 @@ // Public interactive auth/login helpers for provider plugins. -export { githubCopilotLoginCommand } from "../providers/github-copilot-auth.js"; -export { loginChutes } from "../commands/chutes-oauth.js"; -export { loginOpenAICodexOAuth } from "../plugins/provider-openai-codex-oauth.js"; +import { createLazyRuntimeMethodBinder, createLazyRuntimeModule } from "../shared/lazy-runtime.js"; + +const loadProviderAuthLoginRuntime = createLazyRuntimeModule( + () => import("./provider-auth-login.runtime.js"), +); +const bindProviderAuthLoginRuntime = createLazyRuntimeMethodBinder(loadProviderAuthLoginRuntime); + +export const githubCopilotLoginCommand = bindProviderAuthLoginRuntime( + (runtime) => runtime.githubCopilotLoginCommand, +); +export const loginChutes = bindProviderAuthLoginRuntime((runtime) => runtime.loginChutes); +export const loginOpenAICodexOAuth = bindProviderAuthLoginRuntime( + (runtime) => runtime.loginOpenAICodexOAuth, +); diff --git a/src/plugins/loader.ts b/src/plugins/loader.ts index 7be252d68e6..10cd4b52e27 100644 --- a/src/plugins/loader.ts +++ b/src/plugins/loader.ts @@ -535,7 +535,12 @@ function recordPluginError(params: { logPrefix: string; diagnosticMessagePrefix: string; }) { - const errorText = String(params.error); + const errorText = + process.env.OPENCLAW_PLUGIN_LOADER_DEBUG_STACKS === "1" && + params.error instanceof Error && + typeof params.error.stack === "string" + ? params.error.stack + : String(params.error); const deprecatedApiHint = errorText.includes("api.registerHttpHandler") && errorText.includes("is not a function") ? "deprecated api.registerHttpHandler(...) was removed; use api.registerHttpRoute(...) for plugin-owned routes or registerPluginHttpRoute(...) for dynamic lifecycle routes"