fix(zai): fall back to manifest baseUrl for synthesized GLM-5 models

When resolveGlm5ForwardCompatModel synthesizes a GLM-5 model and both
providerConfig and the template model (glm-4.7) are unavailable, the
resolved model was missing baseUrl. This caused the OpenAI SDK to fall
back to api.openai.com instead of api.z.ai, producing confusing 401
errors.

The fix adds a third fallback to ZAI_MANIFEST_BASE_URL — the
provider-level baseUrl from the bundled manifest JSON — so the model
always carries a baseUrl regardless of runtime state.

Fixes #94269
This commit is contained in:
黄剑雄0668001315
2026-06-18 14:22:52 +08:00
committed by Peter Steinberger
parent 9750d887f5
commit 48220df218
3 changed files with 28 additions and 2 deletions

View File

@@ -189,6 +189,28 @@ describe("zai provider plugin", () => {
).toEqual(registered);
});
// FIX #94269: synthesized model must include baseUrl even when the template model
// is not in the registry and no provider config is set.
it("falls back to manifest baseUrl when both providerConfig and template model are unavailable", async () => {
const provider = await registerSingleProviderPlugin(plugin);
const resolved = provider.resolveDynamicModel?.({
provider: "zai",
modelId: "glm-5-turbo",
modelRegistry: {
find: () => null,
},
} as never) as Record<string, unknown> | undefined;
expectModelFields(resolved, {
id: "glm-5-turbo",
provider: "zai",
api: "openai-completions",
baseUrl: "https://api.z.ai/api/paas/v4",
reasoning: true,
input: ["text"],
});
});
it("still synthesizes unknown GLM-5 variants from the GLM-4.7 template", async () => {
const provider = await registerSingleProviderPlugin(plugin);
const template = createGlm47Template();

View File

@@ -34,7 +34,7 @@ import { fetchZaiUsage } from "openclaw/plugin-sdk/provider-usage";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
import { detectZaiEndpoint, type ZaiEndpointId } from "./detect.js";
import { zaiMediaUnderstandingProvider } from "./media-understanding-provider.js";
import { buildZaiModelDefinition } from "./model-definitions.js";
import { buildZaiModelDefinition, ZAI_MANIFEST_BASE_URL } from "./model-definitions.js";
import { applyZaiConfig, applyZaiProviderConfig, resolveZaiModelId } from "./onboard.js";
const PROVIDER_ID = "zai";
@@ -104,7 +104,9 @@ function resolveGlm5ForwardCompatModel(
...template,
id: def.id,
name: def.name,
baseUrl: ctx.providerConfig?.baseUrl ?? template?.baseUrl,
// FIX #94269: fall back to manifest provider-level baseUrl when neither
// provider config nor template model in registry has one.
baseUrl: ctx.providerConfig?.baseUrl ?? template?.baseUrl ?? ZAI_MANIFEST_BASE_URL,
api: "openai-completions",
provider: PROVIDER_ID,
reasoning: def.reasoning,

View File

@@ -11,6 +11,8 @@ export const ZAI_DEFAULT_MODEL_ID = "glm-5.1";
export const ZAI_CODING_DEFAULT_MODEL_ID = "glm-5.2";
const ZAI_MANIFEST_CATALOG = manifest.modelCatalog.providers.zai;
/** Provider-level default baseUrl from the bundled manifest. Used as runtime fallback. */
export const ZAI_MANIFEST_BASE_URL = ZAI_MANIFEST_CATALOG.baseUrl;
const ZAI_MANIFEST_PROVIDER = buildManifestModelProviderConfig({
providerId: "zai",
catalog: ZAI_MANIFEST_CATALOG,