diff --git a/CHANGELOG.md b/CHANGELOG.md index eb75439c69b..af662e9b6d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -145,6 +145,7 @@ Docs: https://docs.openclaw.ai - Onboarding/Providers: update MiniMax API default/recommended models from M2.1 to M2.5, add M2.5/M2.5-Lightning model entries, and include `minimax-m2.5` in modern model filtering. (#14865) Thanks @adao-max. - Ollama: use configured `models.providers.ollama.baseUrl` for model discovery and normalize `/v1` endpoints to the native Ollama API root. (#14131) Thanks @shtse8. - Voice Call: pass Twilio stream auth token via `` instead of query string. (#14029) Thanks @mcwigglesmcgee. +- Config/Models: allow full `models.providers.*.models[*].compat` keys used by `openai-completions` (`thinkingFormat`, `supportsStrictMode`, and streaming/tool-result compatibility flags) so valid provider overrides no longer fail strict config validation. (#11063) Thanks @ikari-pl. - Feishu: pass `Buffer` directly to the Feishu SDK upload APIs instead of `Readable.from(...)` to avoid form-data upload failures. (#10345) Thanks @youngerstyle. - Feishu: trigger mention-gated group handling only when the bot itself is mentioned (not just any mention). (#11088) Thanks @openperf. - Feishu: probe status uses the resolved account context for multi-account credential checks. (#11233) Thanks @onevcat. diff --git a/src/config/config.model-compat-schema.test.ts b/src/config/config.model-compat-schema.test.ts new file mode 100644 index 00000000000..7039e44f34c --- /dev/null +++ b/src/config/config.model-compat-schema.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from "vitest"; +import { validateConfigObject } from "./validation.js"; + +describe("model compat config schema", () => { + it("accepts full openai-completions compat fields", () => { + const res = validateConfigObject({ + models: { + providers: { + local: { + baseUrl: "http://127.0.0.1:1234/v1", + api: "openai-completions", + models: [ + { + id: "qwen3-32b", + name: "Qwen3 32B", + compat: { + supportsUsageInStreaming: true, + supportsStrictMode: false, + thinkingFormat: "qwen", + requiresToolResultName: true, + requiresAssistantAfterToolResult: false, + requiresThinkingAsText: false, + requiresMistralToolIds: false, + }, + }, + ], + }, + }, + }, + }); + + expect(res.ok).toBe(true); + }); +}); diff --git a/src/config/types.models.ts b/src/config/types.models.ts index 3d993cbf610..ebc81f54bdd 100644 --- a/src/config/types.models.ts +++ b/src/config/types.models.ts @@ -11,7 +11,14 @@ export type ModelCompatConfig = { supportsStore?: boolean; supportsDeveloperRole?: boolean; supportsReasoningEffort?: boolean; + supportsUsageInStreaming?: boolean; + supportsStrictMode?: boolean; maxTokensField?: "max_completion_tokens" | "max_tokens"; + thinkingFormat?: "openai" | "zai" | "qwen"; + requiresToolResultName?: boolean; + requiresAssistantAfterToolResult?: boolean; + requiresThinkingAsText?: boolean; + requiresMistralToolIds?: boolean; }; export type ModelProviderAuthMode = "api-key" | "aws-sdk" | "oauth" | "token"; diff --git a/src/config/zod-schema.core.ts b/src/config/zod-schema.core.ts index 2da5c357cb6..b0562fee40c 100644 --- a/src/config/zod-schema.core.ts +++ b/src/config/zod-schema.core.ts @@ -17,9 +17,16 @@ export const ModelCompatSchema = z supportsStore: z.boolean().optional(), supportsDeveloperRole: z.boolean().optional(), supportsReasoningEffort: z.boolean().optional(), + supportsUsageInStreaming: z.boolean().optional(), + supportsStrictMode: z.boolean().optional(), maxTokensField: z .union([z.literal("max_completion_tokens"), z.literal("max_tokens")]) .optional(), + thinkingFormat: z.union([z.literal("openai"), z.literal("zai"), z.literal("qwen")]).optional(), + requiresToolResultName: z.boolean().optional(), + requiresAssistantAfterToolResult: z.boolean().optional(), + requiresThinkingAsText: z.boolean().optional(), + requiresMistralToolIds: z.boolean().optional(), }) .strict() .optional();