Merge branch 'feat/opencode-go-models'
feat(opencode-go): add newly published Go models fix(codex): restore Version header and single-source the CLI version
This commit is contained in:
@@ -7,6 +7,9 @@ import { createRequire } from "module";
|
||||
export const GEMINI_CLI_VERSION = PROVIDERS["gemini-cli"]?.cliVersion;
|
||||
export const GEMINI_CLI_API_CLIENT = PROVIDERS["gemini-cli"]?.apiClient;
|
||||
|
||||
// === Codex CLI === derive từ registry codex.transport
|
||||
export const CODEX_CLI_VERSION = PROVIDERS["codex"]?.cliVersion;
|
||||
|
||||
// Map Node arch to Gemini CLI arch string (x64/x86/arm64/...)
|
||||
function geminiCLIArch() {
|
||||
const a = arch();
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { nowSec } from "./_base.js";
|
||||
import { PROVIDERS } from "../../config/providers.js";
|
||||
import { CODEX_CLI_VERSION } from "../../config/appConstants.js";
|
||||
|
||||
const CODEX_RESPONSES_URL = PROVIDERS["codex"].baseUrl;
|
||||
const CODEX_USER_AGENT = "codex_cli_rs/0.136.0";
|
||||
const CODEX_VERSION = "0.136.0";
|
||||
const CODEX_USER_AGENT = `codex_cli_rs/${CODEX_CLI_VERSION}`;
|
||||
const CODEX_ORIGINATOR = "codex_cli_rs";
|
||||
const CODEX_MODEL_SUFFIX = "-image";
|
||||
const CODEX_REF_DETAIL = "high";
|
||||
@@ -157,7 +157,7 @@ export default {
|
||||
"originator": CODEX_ORIGINATOR,
|
||||
"session_id": randomUUID(),
|
||||
"user-agent": CODEX_USER_AGENT,
|
||||
"version": CODEX_VERSION,
|
||||
"version": CODEX_CLI_VERSION,
|
||||
"x-client-request-id": randomUUID(),
|
||||
};
|
||||
},
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { withCodexReviewModels } from "../models/helpers.js";
|
||||
|
||||
// Codex CLI version seen by OpenAI's backend — single source for the Version /
|
||||
// User-Agent identity headers. Bump when the installed codex CLI is upgraded.
|
||||
const CODEX_CLI_VERSION = "0.154.0";
|
||||
|
||||
export default {
|
||||
id: "codex",
|
||||
priority: 30,
|
||||
@@ -34,9 +38,10 @@ export default {
|
||||
baseUrl: "https://chatgpt.com/backend-api/codex/responses",
|
||||
format: "openai-responses",
|
||||
forceStream: true,
|
||||
cliVersion: CODEX_CLI_VERSION,
|
||||
headers: {
|
||||
originator: "codex_cli_rs",
|
||||
"User-Agent": "codex_cli_rs/0.136.0",
|
||||
"User-Agent": `codex_cli_rs/${CODEX_CLI_VERSION}`,
|
||||
},
|
||||
usage: {
|
||||
url: "https://chatgpt.com/backend-api/wham/usage",
|
||||
|
||||
@@ -33,25 +33,36 @@ export default {
|
||||
{ format: "claude", baseUrl: "https://opencode.ai/zen/go/v1/messages", auth: { combined: true, header: "x-api-key", scheme: "raw", anthropicVersion: true } },
|
||||
{ format: "openai-responses", baseUrl: "https://opencode.ai/zen/go/v1/responses", auth: { combined: true, header: "Authorization", scheme: "bearer" } },
|
||||
],
|
||||
// supportedFormats follow the endpoint table in https://opencode.ai/docs/go/
|
||||
models: [
|
||||
{ id: "glm-5.3-flash", name: "GLM 5.3 Flash (Vision)", supportedFormats: ["openai"] },
|
||||
{ id: "glm-5.3", name: "GLM 5.3", supportedFormats: ["openai"] },
|
||||
{ id: "glm-5.2", name: "GLM 5.2", supportedFormats: ["openai"] },
|
||||
{ id: "glm-5.1", name: "GLM 5.1", supportedFormats: ["openai"] },
|
||||
{ id: "kimi-k2.7-code", name: "Kimi K2.7 Code", supportedFormats: ["openai"] },
|
||||
{ id: "kimi-k2.6", name: "Kimi K2.6", supportedFormats: ["openai"] },
|
||||
{ id: "kimi-k3", name: "Kimi K3", supportedFormats: ["openai"] },
|
||||
{ id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", supportedFormats: ["openai", "claude", "openai-responses"] },
|
||||
{ id: "deepseek-v4-flash", name: "DeepSeek V4 Flash", supportedFormats: ["openai", "claude", "openai-responses"] },
|
||||
{ id: "deepseek-v4-flash-vision-exp", name: "DeepSeek V4 Flash Vision (Exp)", supportedFormats: ["openai", "claude", "openai-responses"] },
|
||||
{ id: "deepseek-flash", name: "DeepSeek V4.1 Flash", supportedFormats: ["openai"] },
|
||||
{ id: "longcat-2.0", name: "LongCat 2.0", supportedFormats: ["openai"] },
|
||||
{ id: "mimo-v2.5", name: "MiMo V2.5", supportedFormats: ["openai"] },
|
||||
{ id: "mimo-v2.5-pro", name: "MiMo V2.5 Pro", supportedFormats: ["openai"] },
|
||||
{ id: "minimax-m3", name: "MiniMax M3", supportedFormats: ["openai", "claude"] },
|
||||
{ id: "minimax-m2.7", name: "MiniMax M2.7", supportedFormats: ["openai", "claude"] },
|
||||
{ id: "minimax-m2.5", name: "MiniMax M2.5", supportedFormats: ["openai", "claude"] },
|
||||
{ id: "qwen3.8-max", name: "Qwen 3.8 Max", supportedFormats: ["openai", "claude"] },
|
||||
{ id: "qwen3.8-flash", name: "Qwen 3.8 Flash", supportedFormats: ["openai", "claude"] },
|
||||
{ id: "qwen3.7-max", name: "Qwen 3.7 Max", supportedFormats: ["openai", "claude"] },
|
||||
{ id: "qwen3.7-plus", name: "Qwen 3.7 Plus", supportedFormats: ["openai", "claude"] },
|
||||
{ id: "qwen3.6-plus", name: "Qwen 3.6 Plus", supportedFormats: ["openai", "claude"] },
|
||||
// Muse Spark is served by /zen/go/v1/responses only — responses-only entry forces
|
||||
// chatCore past the sourceFormat-matched transports into translation (see chatCore guard).
|
||||
{ id: "hy4-preview", name: "Hy4 Preview", supportedFormats: ["openai"] },
|
||||
{ id: "hy3", name: "Hy3", supportedFormats: ["openai"] },
|
||||
// Served by /zen/go/v1/responses only — the responses-only entry forces chatCore
|
||||
// past the sourceFormat-matched transports into translation (see chatCore guard).
|
||||
{ id: "grok-4.6", name: "Grok 4.6", targetFormat: "openai-responses", supportedFormats: ["openai-responses"] },
|
||||
{ id: "gpt-5.6-luna", name: "GPT 5.6 Luna", targetFormat: "openai-responses", supportedFormats: ["openai-responses"] },
|
||||
{ id: "muse-spark-1.2-contributor", name: "Muse Spark 1.2 Contributor", targetFormat: "openai-responses", supportedFormats: ["openai-responses"] },
|
||||
{ id: "muse-spark-1.3-contributor", name: "Muse Spark 1.3 Contributor", targetFormat: "openai-responses", supportedFormats: ["openai-responses"] },
|
||||
],
|
||||
|
||||
@@ -4,6 +4,7 @@ import { testProxyUrl } from "@/lib/network/proxyTest";
|
||||
import { isOpenAICompatibleProvider, isAnthropicCompatibleProvider } from "@/shared/constants/providers";
|
||||
import { getDefaultModel } from "open-sse/config/providerModels.js";
|
||||
import { resolveOllamaLocalHost, PROVIDERS } from "open-sse/config/providers.js";
|
||||
import { CODEX_CLI_VERSION } from "open-sse/config/appConstants.js";
|
||||
import {
|
||||
refreshProviderCredentials,
|
||||
shouldRefreshCredentials,
|
||||
@@ -27,7 +28,7 @@ const OAUTH_TEST_CONFIG = {
|
||||
method: "POST",
|
||||
authHeader: "Authorization",
|
||||
authPrefix: "Bearer ",
|
||||
extraHeaders: { "Content-Type": "application/json", "originator": "codex_cli_rs", "User-Agent": "codex_cli_rs/0.136.0" },
|
||||
extraHeaders: { "Content-Type": "application/json", "originator": "codex_cli_rs", "User-Agent": `codex_cli_rs/${CODEX_CLI_VERSION}` },
|
||||
// Minimal invalid body — triggers fast 400 without consuming quota
|
||||
body: JSON.stringify({ model: "gpt-5.3-codex", input: [], stream: false, store: false }),
|
||||
// 400 (bad request) means auth succeeded; only 401/403 means token is bad
|
||||
|
||||
@@ -192,9 +192,10 @@
|
||||
"baseUrl": "https://chatgpt.com/backend-api/codex/responses",
|
||||
"format": "openai-responses",
|
||||
"forceStream": true,
|
||||
"cliVersion": "0.154.0",
|
||||
"headers": {
|
||||
"originator": "codex_cli_rs",
|
||||
"User-Agent": "codex_cli_rs/0.136.0"
|
||||
"User-Agent": "codex_cli_rs/0.154.0"
|
||||
},
|
||||
"usage": {
|
||||
"url": "https://chatgpt.com/backend-api/wham/usage",
|
||||
|
||||
@@ -351,7 +351,7 @@ describe("handleImageGenerationCore", () => {
|
||||
headers: expect.objectContaining({
|
||||
authorization: "Bearer codex-token",
|
||||
"chatgpt-account-id": "account-123",
|
||||
version: "0.136.0",
|
||||
version: "0.154.0",
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
@@ -4,9 +4,11 @@ import { PROVIDERS } from "../../open-sse/config/providers.js";
|
||||
import { resolveTransport } from "../../open-sse/services/provider.js";
|
||||
|
||||
// Chat-only models (no /messages, no /responses support on opencode-go)
|
||||
const CHAT_ONLY = ["glm-5.2", "glm-5.1", "kimi-k2.7-code", "kimi-k2.6", "mimo-v2.5", "mimo-v2.5-pro"];
|
||||
const CHAT_ONLY = ["glm-5.3", "glm-5.2", "glm-5.1", "kimi-k2.7-code", "kimi-k2.6", "kimi-k3",
|
||||
"deepseek-flash", "longcat-2.0", "mimo-v2.5", "mimo-v2.5-pro", "hy4-preview", "hy3"];
|
||||
// Models that also expose the Anthropic /messages endpoint
|
||||
const CLAUDE_CAPABLE = ["minimax-m3", "minimax-m2.7", "minimax-m2.5", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus"];
|
||||
const CLAUDE_CAPABLE = ["minimax-m3", "minimax-m2.7", "minimax-m2.5",
|
||||
"qwen3.8-max", "qwen3.8-flash", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus"];
|
||||
// Models that also expose the OpenAI /responses endpoint
|
||||
const RESPONSES_CAPABLE = ["deepseek-v4-pro", "deepseek-v4-flash"];
|
||||
|
||||
@@ -22,11 +24,13 @@ describe("OpenCode Go model catalog", () => {
|
||||
it("matches the documented model IDs", () => {
|
||||
const ids = (PROVIDER_MODELS["opencode-go"] || []).map((m) => m.id);
|
||||
expect(ids).toEqual([
|
||||
"glm-5.3-flash", "glm-5.2", "glm-5.1", "kimi-k2.7-code", "kimi-k2.6",
|
||||
"deepseek-v4-pro", "deepseek-v4-flash", "deepseek-v4-flash-vision-exp",
|
||||
"mimo-v2.5", "mimo-v2.5-pro",
|
||||
"glm-5.3-flash", "glm-5.3", "glm-5.2", "glm-5.1", "kimi-k2.7-code", "kimi-k2.6", "kimi-k3",
|
||||
"deepseek-v4-pro", "deepseek-v4-flash", "deepseek-v4-flash-vision-exp", "deepseek-flash",
|
||||
"longcat-2.0", "mimo-v2.5", "mimo-v2.5-pro",
|
||||
"minimax-m3", "minimax-m2.7", "minimax-m2.5",
|
||||
"qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus",
|
||||
"qwen3.8-max", "qwen3.8-flash", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus",
|
||||
"hy4-preview", "hy3",
|
||||
"grok-4.6", "gpt-5.6-luna",
|
||||
"muse-spark-1.2-contributor", "muse-spark-1.3-contributor",
|
||||
]);
|
||||
});
|
||||
@@ -91,7 +95,7 @@ describe("OpenCode Go per-model transport guard (chatCore logic)", () => {
|
||||
});
|
||||
|
||||
it("routes Muse Spark (responses-only) to /responses, never to /messages", () => {
|
||||
for (const m of ["muse-spark-1.2-contributor", "muse-spark-1.3-contributor"]) {
|
||||
for (const m of ["muse-spark-1.2-contributor", "muse-spark-1.3-contributor", "grok-4.6", "gpt-5.6-luna"]) {
|
||||
expect(getModelSupportedFormats("opencode-go", m)).toEqual(["openai-responses"]);
|
||||
expect(pickTransport("opencode-go", "openai-responses", "opencode-go", m)?.baseUrl).toBe("https://opencode.ai/zen/go/v1/responses");
|
||||
expect(pickTransport("opencode-go", "claude", "opencode-go", m)).toBeNull();
|
||||
|
||||
Reference in New Issue
Block a user