feat(ai): added OpenRouter provider with strict mode detection

- Added support for OpenRouter provider with strict mode detection.
This commit is contained in:
can1357
2026-04-08 09:50:29 +02:00
parent bf97331311
commit 7a4ef2b8d6
3 changed files with 13 additions and 1 deletions
+1 -1
View File
@@ -1,13 +1,13 @@
# Changelog
## [Unreleased]
### Breaking Changes
- Removed `coerceNullStrings` function and its automatic null-string coercion behavior from JSON parsing
### Added
- Added support for OpenRouter provider with strict mode detection
- Added automatic cleaning of literal escape sequences (`\n`, `\t`, `\r`) in JSON parsing to handle LLM encoding confusion
- Added support for healing JSON with trailing junk after balanced containers (e.g., `]\n</invoke>`)
- Added `CODEX_STARTUP_EVENT_CHANNEL` constant and `CodexStartupEvent` type for monitoring Codex provider initialization status
@@ -13,6 +13,7 @@ export type ResolvedOpenAICompat = Required<
function detectStrictModeSupport(provider: string, baseUrl: string): boolean {
if (
provider === "openai" ||
provider === "openrouter" ||
provider === "cerebras" ||
provider === "together" ||
provider === "github-copilot" ||
@@ -28,6 +29,7 @@ function detectStrictModeSupport(provider: string, baseUrl: string): boolean {
normalizedBaseUrl.includes("models.inference.ai.azure.com") ||
normalizedBaseUrl.includes("api.cerebras.ai") ||
normalizedBaseUrl.includes("api.together.xyz") ||
normalizedBaseUrl.includes("openrouter.ai") ||
normalizedBaseUrl.includes("api.deepseek.com") ||
normalizedBaseUrl.includes("deepseek.com")
);
@@ -91,6 +91,16 @@ describe("OpenAI tool strict mode", () => {
};
expect(payload.tools?.[0]?.function?.strict).toBe(true);
});
it("sends strict=true for openai-completions tool schemas on OpenRouter", async () => {
const model = getBundledModel("openrouter", "anthropic/claude-sonnet-4") as Model<"openai-completions">;
const payload = (await captureCompletionsPayload(model)) as {
tools?: Array<{ function?: { strict?: boolean } }>;
};
expect(payload.tools?.[0]?.function?.strict).toBe(true);
});
it("omits stream_options usage requests for Cerebras chat completions", async () => {
const model = getBundledModel("cerebras", "gpt-oss-120b") as Model<"openai-completions">;