fix(agent): default missing model cost metadata

This commit is contained in:
Peter Steinberger
2026-05-01 11:51:41 +01:00
parent dddf871ad9
commit 702e23835d
2 changed files with 67 additions and 0 deletions

View File

@@ -254,6 +254,38 @@ describe("resolveModel", () => {
expect(result.model?.input).toEqual(["text"]);
});
it("defaults missing model cost before handing models to PI", () => {
const cfg = {
models: {
providers: {
openai: {
api: "openai-responses",
models: [
{
id: "gpt-5.5",
name: "GPT-5.5",
api: "openai-responses",
reasoning: true,
input: ["text"],
contextWindow: 400_000,
maxTokens: 128_000,
},
],
},
},
},
} as unknown as OpenClawConfig;
const result = resolveModelForTest("openai", "gpt-5.5", "/tmp/agent", cfg);
expect(result.error).toBeUndefined();
expect(result.model).toMatchObject({
provider: "openai",
id: "gpt-5.5",
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
});
});
it("includes provider baseUrl in fallback model", () => {
const cfg = {
models: {

View File

@@ -190,6 +190,40 @@ function normalizeResolvedModel(params: {
agentDir?: string;
runtimeHooks?: ProviderRuntimeHooks;
}): Model<Api> {
const normalizeModelCost = (cost: unknown): Model<Api>["cost"] => {
if (!cost || typeof cost !== "object" || Array.isArray(cost)) {
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
}
const record = cost as Partial<Model<Api>["cost"]>;
const input =
typeof record.input === "number" && Number.isFinite(record.input) ? record.input : 0;
const output =
typeof record.output === "number" && Number.isFinite(record.output) ? record.output : 0;
const cacheRead =
typeof record.cacheRead === "number" && Number.isFinite(record.cacheRead)
? record.cacheRead
: 0;
const cacheWrite =
typeof record.cacheWrite === "number" && Number.isFinite(record.cacheWrite)
? record.cacheWrite
: 0;
if (
input === record.input &&
output === record.output &&
cacheRead === record.cacheRead &&
cacheWrite === record.cacheWrite
) {
return record as Model<Api>["cost"];
}
return {
...cost,
input,
output,
cacheRead,
cacheWrite,
};
};
const normalizedInputModel = {
...params.model,
input: resolveProviderModelInput({
@@ -198,6 +232,7 @@ function normalizeResolvedModel(params: {
modelName: params.model.name,
input: params.model.input,
}),
cost: normalizeModelCost((params.model as { cost?: unknown }).cost),
} as Model<Api>;
const runtimeHooks = params.runtimeHooks ?? DEFAULT_PROVIDER_RUNTIME_HOOKS;
const pluginNormalized = runtimeHooks.normalizeProviderResolvedModelWithPlugin({