refactor(providers): share paired api-key catalogs

This commit is contained in:
Peter Steinberger 2026-03-17 04:05:24 +00:00
parent 0a6140acfa
commit 39183746ba
4 changed files with 73 additions and 25 deletions

View File

@ -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(),
}),
}),
},
});
},

View File

@ -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(),
}),
}),
},
});
},

View File

@ -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",
},
},
});
});
});

View File

@ -42,3 +42,23 @@ export async function buildSingleProviderApiKeyCatalog(params: {
},
};
}
export async function buildPairedProviderApiKeyCatalog(params: {
ctx: ProviderCatalogContext;
providerId: string;
buildProviders: () =>
| Record<string, ModelProviderConfig>
| Promise<Record<string, ModelProviderConfig>>;
}): Promise<ProviderCatalogResult> {
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 }]),
),
};
}