diff --git a/extensions/byteplus/index.ts b/extensions/byteplus/index.ts index d91fb87f1aa..7c6cf2f08fe 100644 --- a/extensions/byteplus/index.ts +++ b/extensions/byteplus/index.ts @@ -1,6 +1,7 @@ import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core"; import { ensureModelAllowlistEntry } from "../../src/commands/model-allowlist.js"; import { createProviderApiKeyAuthMethod } from "../../src/plugins/provider-api-key-auth.js"; +import { buildPairedProviderApiKeyCatalog } from "../../src/plugins/provider-catalog.js"; import { buildBytePlusCodingProvider, buildBytePlusProvider } from "./provider-catalog.js"; const PROVIDER_ID = "byteplus"; @@ -45,18 +46,15 @@ const byteplusPlugin = { ], catalog: { order: "paired", - run: async (ctx) => { - const apiKey = ctx.resolveProviderApiKey(PROVIDER_ID).apiKey; - if (!apiKey) { - return null; - } - return { - providers: { - byteplus: { ...buildBytePlusProvider(), apiKey }, - "byteplus-plan": { ...buildBytePlusCodingProvider(), apiKey }, - }, - }; - }, + run: (ctx) => + buildPairedProviderApiKeyCatalog({ + ctx, + providerId: PROVIDER_ID, + buildProviders: () => ({ + byteplus: buildBytePlusProvider(), + "byteplus-plan": buildBytePlusCodingProvider(), + }), + }), }, }); }, diff --git a/extensions/volcengine/index.ts b/extensions/volcengine/index.ts index 4fadadb3608..f9e3fb72010 100644 --- a/extensions/volcengine/index.ts +++ b/extensions/volcengine/index.ts @@ -1,6 +1,7 @@ import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core"; import { ensureModelAllowlistEntry } from "../../src/commands/model-allowlist.js"; import { createProviderApiKeyAuthMethod } from "../../src/plugins/provider-api-key-auth.js"; +import { buildPairedProviderApiKeyCatalog } from "../../src/plugins/provider-catalog.js"; import { buildDoubaoCodingProvider, buildDoubaoProvider } from "./provider-catalog.js"; const PROVIDER_ID = "volcengine"; @@ -45,18 +46,15 @@ const volcenginePlugin = { ], catalog: { order: "paired", - run: async (ctx) => { - const apiKey = ctx.resolveProviderApiKey(PROVIDER_ID).apiKey; - if (!apiKey) { - return null; - } - return { - providers: { - volcengine: { ...buildDoubaoProvider(), apiKey }, - "volcengine-plan": { ...buildDoubaoCodingProvider(), apiKey }, - }, - }; - }, + run: (ctx) => + buildPairedProviderApiKeyCatalog({ + ctx, + providerId: PROVIDER_ID, + buildProviders: () => ({ + volcengine: buildDoubaoProvider(), + "volcengine-plan": buildDoubaoCodingProvider(), + }), + }), }, }); }, diff --git a/src/plugins/provider-catalog.test.ts b/src/plugins/provider-catalog.test.ts index c435e1d88b2..e150d021a7b 100644 --- a/src/plugins/provider-catalog.test.ts +++ b/src/plugins/provider-catalog.test.ts @@ -1,6 +1,10 @@ import { describe, expect, it } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; -import { buildSingleProviderApiKeyCatalog, findCatalogTemplate } from "./provider-catalog.js"; +import { + buildPairedProviderApiKeyCatalog, + buildSingleProviderApiKeyCatalog, + findCatalogTemplate, +} from "./provider-catalog.js"; import type { ProviderCatalogContext } from "./types.js"; function createCatalogContext(params: { @@ -90,4 +94,32 @@ describe("buildSingleProviderApiKeyCatalog", () => { }, }); }); + + it("adds api key to each paired provider", async () => { + const result = await buildPairedProviderApiKeyCatalog({ + ctx: createCatalogContext({ + apiKeys: { "test-provider": "secret-key" }, + }), + providerId: "test-provider", + buildProviders: async () => ({ + alpha: { api: "openai-completions", provider: "alpha" }, + beta: { api: "openai-completions", provider: "beta" }, + }), + }); + + expect(result).toEqual({ + providers: { + alpha: { + api: "openai-completions", + provider: "alpha", + apiKey: "secret-key", + }, + beta: { + api: "openai-completions", + provider: "beta", + apiKey: "secret-key", + }, + }, + }); + }); }); diff --git a/src/plugins/provider-catalog.ts b/src/plugins/provider-catalog.ts index 3fcf2f39bcc..1d357887c03 100644 --- a/src/plugins/provider-catalog.ts +++ b/src/plugins/provider-catalog.ts @@ -42,3 +42,23 @@ export async function buildSingleProviderApiKeyCatalog(params: { }, }; } + +export async function buildPairedProviderApiKeyCatalog(params: { + ctx: ProviderCatalogContext; + providerId: string; + buildProviders: () => + | Record + | Promise>; +}): Promise { + const apiKey = params.ctx.resolveProviderApiKey(params.providerId).apiKey; + if (!apiKey) { + return null; + } + + const providers = await params.buildProviders(); + return { + providers: Object.fromEntries( + Object.entries(providers).map(([id, provider]) => [id, { ...provider, apiKey }]), + ), + }; +}