mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-30 17:16:52 +00:00
fix: force supportsDeveloperRole=false for non-native OpenAI endpoints (#29479)
Merged via squash.
Prepared head SHA: 1416c584ac
Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
@@ -19,6 +19,10 @@ const baseModel = (): Model<Api> =>
|
||||
maxTokens: 1024,
|
||||
}) as Model<Api>;
|
||||
|
||||
function supportsDeveloperRole(model: Model<Api>): boolean | undefined {
|
||||
return (model.compat as { supportsDeveloperRole?: boolean } | undefined)?.supportsDeveloperRole;
|
||||
}
|
||||
|
||||
function createTemplateModel(provider: string, id: string): Model<Api> {
|
||||
return {
|
||||
id,
|
||||
@@ -105,9 +109,7 @@ describe("normalizeModelCompat", () => {
|
||||
const model = baseModel();
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(
|
||||
(normalized.compat as { supportsDeveloperRole?: boolean } | undefined)?.supportsDeveloperRole,
|
||||
).toBe(false);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("forces supportsDeveloperRole off for moonshot models", () => {
|
||||
@@ -118,9 +120,7 @@ describe("normalizeModelCompat", () => {
|
||||
};
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(
|
||||
(normalized.compat as { supportsDeveloperRole?: boolean } | undefined)?.supportsDeveloperRole,
|
||||
).toBe(false);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("forces supportsDeveloperRole off for custom moonshot-compatible endpoints", () => {
|
||||
@@ -131,9 +131,7 @@ describe("normalizeModelCompat", () => {
|
||||
};
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(
|
||||
(normalized.compat as { supportsDeveloperRole?: boolean } | undefined)?.supportsDeveloperRole,
|
||||
).toBe(false);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("forces supportsDeveloperRole off for DashScope provider ids", () => {
|
||||
@@ -144,9 +142,7 @@ describe("normalizeModelCompat", () => {
|
||||
};
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(
|
||||
(normalized.compat as { supportsDeveloperRole?: boolean } | undefined)?.supportsDeveloperRole,
|
||||
).toBe(false);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("forces supportsDeveloperRole off for DashScope-compatible endpoints", () => {
|
||||
@@ -157,12 +153,10 @@ describe("normalizeModelCompat", () => {
|
||||
};
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(
|
||||
(normalized.compat as { supportsDeveloperRole?: boolean } | undefined)?.supportsDeveloperRole,
|
||||
).toBe(false);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("leaves non-zai models untouched", () => {
|
||||
it("leaves native api.openai.com model untouched", () => {
|
||||
const model = {
|
||||
...baseModel(),
|
||||
provider: "openai",
|
||||
@@ -173,13 +167,89 @@ describe("normalizeModelCompat", () => {
|
||||
expect(normalized.compat).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not override explicit z.ai compat false", () => {
|
||||
it("forces supportsDeveloperRole off for Azure OpenAI (Chat Completions, not Responses API)", () => {
|
||||
const model = {
|
||||
...baseModel(),
|
||||
provider: "azure-openai",
|
||||
baseUrl: "https://my-deployment.openai.azure.com/openai",
|
||||
};
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
it("forces supportsDeveloperRole off for generic custom openai-completions provider", () => {
|
||||
const model = {
|
||||
...baseModel(),
|
||||
provider: "custom-cpa",
|
||||
baseUrl: "https://cpa.example.com/v1",
|
||||
};
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("forces supportsDeveloperRole off for Qwen proxy via openai-completions", () => {
|
||||
const model = {
|
||||
...baseModel(),
|
||||
provider: "qwen-proxy",
|
||||
baseUrl: "https://qwen-api.example.org/compatible-mode/v1",
|
||||
};
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("leaves openai-completions model with empty baseUrl untouched", () => {
|
||||
const model = {
|
||||
...baseModel(),
|
||||
provider: "openai",
|
||||
};
|
||||
delete (model as { baseUrl?: unknown }).baseUrl;
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model as Model<Api>);
|
||||
expect(normalized.compat).toBeUndefined();
|
||||
});
|
||||
|
||||
it("forces supportsDeveloperRole off for malformed baseUrl values", () => {
|
||||
const model = {
|
||||
...baseModel(),
|
||||
provider: "custom-cpa",
|
||||
baseUrl: "://api.openai.com malformed",
|
||||
};
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("overrides explicit supportsDeveloperRole true on non-native endpoints", () => {
|
||||
const model = {
|
||||
...baseModel(),
|
||||
provider: "custom-cpa",
|
||||
baseUrl: "https://proxy.example.com/v1",
|
||||
compat: { supportsDeveloperRole: true },
|
||||
};
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("does not mutate caller model when forcing supportsDeveloperRole off", () => {
|
||||
const model = {
|
||||
...baseModel(),
|
||||
provider: "custom-cpa",
|
||||
baseUrl: "https://proxy.example.com/v1",
|
||||
};
|
||||
delete (model as { compat?: unknown }).compat;
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(normalized).not.toBe(model);
|
||||
expect(supportsDeveloperRole(model)).toBeUndefined();
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
|
||||
it("does not override explicit compat false", () => {
|
||||
const model = baseModel();
|
||||
model.compat = { supportsDeveloperRole: false };
|
||||
const normalized = normalizeModelCompat(model);
|
||||
expect(
|
||||
(normalized.compat as { supportsDeveloperRole?: boolean } | undefined)?.supportsDeveloperRole,
|
||||
).toBe(false);
|
||||
expect(supportsDeveloperRole(normalized)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user