fix: normalize exact Gemini proxy refs

This commit is contained in:
Peter Steinberger
2026-05-11 22:54:39 +01:00
parent 37d018c6d9
commit 1923db6dac
5 changed files with 81 additions and 8 deletions

View File

@@ -66,6 +66,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Google/Gemini: normalize retired nested Gemini 3 Pro Preview ids when resolving exact configured proxy-provider refs, so `kilocode/google/gemini-3-pro-preview` resolves to `kilocode/google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
- CLI: strip generic OSC terminal escape payloads from sanitized output fields, preventing clipboard/title escape bodies from leaking into commitment tables and other terminal-safe text. Thanks @shakkernerd.
- Codex app-server: match connector-backed plugin approval elicitations by stable connector id so enabled destructive actions no longer fall through to display-name-only rejection.
- Build: replace selected build utility `tsx` preloads with Node native type stripping so Node 26 build paths no longer emit `DEP0205` module loader deprecation warnings. (#78584) Thanks @keshavbotagent.

View File

@@ -316,10 +316,13 @@ function resolveExactConfiguredProviderRef(
const provider = normalizeLowercaseStringOrEmpty(configuredProvider);
return {
provider,
model: normalizeStaticProviderModelId(provider, modelRaw.trim(), {
allowManifestNormalization: params.allowManifestNormalization,
manifestPlugins: params.manifestPlugins,
}),
model: normalizeConfiguredProviderCatalogModelId(
provider,
normalizeStaticProviderModelId(provider, modelRaw.trim(), {
allowManifestNormalization: params.allowManifestNormalization,
manifestPlugins: params.manifestPlugins,
}),
),
};
}

View File

@@ -1768,6 +1768,34 @@ describe("model-selection", () => {
).toEqual({ provider: "modelstudio", model: "qwen3.6-plus" });
});
it("normalizes retired nested Gemini ids in exact configured provider refs", () => {
const cfg = {
agents: {
defaults: {
model: { primary: "kilocode/google/gemini-3-pro-preview" },
},
},
models: {
providers: {
kilocode: {
api: "openai-completions",
baseUrl: "https://kilocode.test/v1",
models: [{ id: "google/gemini-3-pro-preview", name: "Gemini 3 Pro" }],
},
},
},
} as unknown as OpenClawConfig;
expect(
resolveConfiguredModelRef({
cfg,
defaultProvider: "anthropic",
defaultModel: "claude-opus-4-6",
allowPluginNormalization: false,
}),
).toEqual({ provider: "kilocode", model: "google/gemini-3.1-pro-preview" });
});
it("keeps legacy modelstudio aliases when no exact foreign api owner is configured", () => {
const cfg = {
agents: {

View File

@@ -37,4 +37,40 @@ describe("resolveConfiguredEntries", () => {
expect(entries[0]?.aliases).toEqual(["Codex"]);
expect(entries[1]?.tags).toEqual(new Set(["fallback#1", "configured"]));
});
it("normalizes retired nested Gemini ids in configured provider rows", () => {
const { entries } = resolveConfiguredEntries({
agents: {
defaults: {
model: { primary: "kilocode/google/gemini-3-pro-preview" },
models: {
"kilocode/google/gemini-3-pro-preview": { alias: "Kilo Gemini" },
},
},
},
models: {
providers: {
kilocode: {
api: "openai-completions",
baseUrl: "https://kilocode.test/v1",
models: [
{
id: "google/gemini-3-pro-preview",
name: "Gemini 3 Pro",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 1_048_576,
maxTokens: 65_536,
},
],
},
},
},
});
expect(entries.map((entry) => entry.key)).toEqual(["kilocode/google/gemini-3.1-pro-preview"]);
expect(entries[0]?.aliases).toEqual(["Kilo Gemini"]);
expect(entries[0]?.tags).toEqual(new Set(["default", "configured"]));
});
});

View File

@@ -1,6 +1,5 @@
import {
buildModelAliasIndex,
parseModelRef,
resolveConfiguredModelRef,
resolveModelRefFromString,
} from "../../agents/model-selection.js";
@@ -74,11 +73,17 @@ export function resolveConfiguredEntries(cfg: OpenClawConfig) {
});
for (const key of Object.keys(cfg.agents?.defaults?.models ?? {})) {
const parsed = parseModelRef(key, DEFAULT_PROVIDER, DISPLAY_MODEL_PARSE_OPTIONS);
if (!parsed) {
const resolved = resolveModelRefFromString({
cfg,
raw: key,
defaultProvider: DEFAULT_PROVIDER,
aliasIndex,
...DISPLAY_MODEL_PARSE_OPTIONS,
});
if (!resolved) {
continue;
}
addEntry(parsed, "configured");
addEntry(resolved.ref, "configured");
}
const entries: ConfiguredEntry[] = order.map((key) => {