import { describe, expect, it } from
"vitest" ;
import type { OpenClawConfig } from
"../config/config.js" ;
import type { AgentModelEntryConfig } from
"../config/types.agent-defaults.js" ;
import type { ModelDefinitionConfig } from
"../config/types.models.js" ;
import {
applyProviderConfigWithDefaultModelPreset,
applyProviderConfigWithModelCatalogPreset,
applyProviderConfigWithDefaultModel,
applyProviderConfigWithDefaultModels,
applyProviderConfigWithModelCatalog,
withAgentModelAliases,
} from
"../plugin-sdk/provider-onboard.js" ;
function makeModel(id: string): ModelDefinitionConfig {
return {
id,
name: id,
contextWindow:
4096 ,
maxTokens:
1024 ,
input: [
"text" ],
cost: { input:
0 , output:
0 , cacheRead:
0 , cacheWrite:
0 },
reasoning:
false ,
};
}
describe(
"onboard auth provider config merges" , () => {
const agentModels: Record<string, AgentModelEntryConfig> = {
"custom/model-a" : {},
};
it(
"appends missing default models to existing provider models" , () => {
const cfg: OpenClawConfig = {
models: {
providers: {
custom: {
api:
"openai-completions" ,
baseUrl:
"https://old.example.com/v1 ",
apiKey:
" test-key " ,
models: [makeModel(
"model-a" )],
},
},
},
};
const next = applyProviderConfigWithDefaultModels(cfg, {
agentModels,
providerId:
"custom" ,
api:
"openai-completions" ,
baseUrl:
"https://new.example.com/v1 ",
defaultModels: [makeModel(
"model-b" )],
defaultModelId:
"model-b" ,
});
expect(next.models?.providers?.custom?.models?.map((m) => m.id)).toEqual([
"model-a" ,
"model-b" ,
]);
expect(next.models?.providers?.custom?.apiKey).toBe(
"test-key" );
expect(next.agents?.defaults?.models).toEqual(agentModels);
});
it(
"preserves existing agent model entries when adding provider models" , () => {
const cfg: OpenClawConfig = {
agents: {
defaults: {
models: {
"openai/gpt-5.5" : { alias:
"GPT" },
},
},
},
models: {
providers: {
custom: {
api:
"openai-completions" ,
baseUrl:
"https://old.example.com/v1 ",
models: [makeModel(
"model-a" )],
},
},
},
};
const next = applyProviderConfigWithDefaultModels(cfg, {
agentModels,
providerId:
"custom" ,
api:
"openai-completions" ,
baseUrl:
"https://new.example.com/v1 ",
defaultModels: [makeModel(
"model-b" )],
defaultModelId:
"model-b" ,
});
expect(next.agents?.defaults?.models).toEqual({
"openai/gpt-5.5" : { alias:
"GPT" },
...agentModels,
});
});
it(
"merges model catalogs without duplicating existing model ids" , () => {
const cfg: OpenClawConfig = {
models: {
providers: {
custom: {
api:
"openai-completions" ,
baseUrl:
"https://example.com/v1 ",
models: [makeModel(
"model-a" )],
},
},
},
};
const next = applyProviderConfigWithModelCatalog(cfg, {
agentModels,
providerId:
"custom" ,
api:
"openai-completions" ,
baseUrl:
"https://example.com/v1 ",
catalogModels: [makeModel(
"model-a" ), makeModel(
"model-c" )],
});
expect(next.models?.providers?.custom?.models?.map((m) => m.id)).toEqual([
"model-a" ,
"model-c" ,
]);
});
it(
"supports single default model convenience wrapper" , () => {
const next = applyProviderConfigWithDefaultModel(
{},
{
agentModels,
providerId:
"custom" ,
api:
"openai-completions" ,
baseUrl:
"https://example.com/v1 ",
defaultModel: makeModel(
"model-z" ),
},
);
expect(next.models?.providers?.custom?.models?.map((m) => m.id)).toEqual([
"model-z" ]);
});
it("preserves explicit aliases when adding provider alias presets" , () => {
expect(
withAgentModelAliases(
{
"custom/model-a" : { alias: "Pinned" },
},
[{ modelRef: "custom/model-a" , alias: "Preset" }, "custom/model-b" ],
),
).toEqual({
"custom/model-a" : { alias: "Pinned" },
"custom/model-b" : {},
});
});
it("applies default-model presets with alias and primary model" , () => {
const next = applyProviderConfigWithDefaultModelPreset(
{
agents: {
defaults: {
models: {
"custom/model-z" : { alias: "Pinned" },
},
},
},
},
{
providerId: "custom" ,
api: "openai-completions" ,
baseUrl: "https://example.com/v1 ",
defaultModel: makeModel("model-z" ),
aliases: [{ modelRef: "custom/model-z" , alias: "Preset" }],
primaryModelRef: "custom/model-z" ,
},
);
expect(next.agents?.defaults?.models?.["custom/model-z" ]).toEqual({ alias: "Pinned" });
expect(next.agents?.defaults?.model).toEqual({ primary: "custom/model-z" });
});
it("applies catalog presets with alias and merged catalog models" , () => {
const next = applyProviderConfigWithModelCatalogPreset(
{
models: {
providers: {
custom: {
api: "openai-completions" ,
baseUrl: "https://example.com/v1 ",
models: [makeModel("model-a" )],
},
},
},
},
{
providerId: "custom" ,
api: "openai-completions" ,
baseUrl: "https://example.com/v1 ",
catalogModels: [makeModel("model-a" ), makeModel("model-b" )],
aliases: [{ modelRef: "custom/model-b" , alias: "Catalog Alias" }],
primaryModelRef: "custom/model-b" ,
},
);
expect(next.models?.providers?.custom?.models?.map((model) => model.id)).toEqual([
"model-a" ,
"model-b" ,
]);
expect(next.agents?.defaults?.models?.["custom/model-b" ]).toEqual({
alias: "Catalog Alias" ,
});
expect(next.agents?.defaults?.model).toEqual({ primary: "custom/model-b" });
});
});
Messung V0.5 in Prozent C=96 H=100 G=97
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-09)
¤
*© Formatika GbR, Deutschland