Fix : Qwen provider
This commit is contained in:
@@ -79,10 +79,6 @@ export const PROVIDERS = {
|
|||||||
qwen: {
|
qwen: {
|
||||||
baseUrl: "https://portal.qwen.ai/v1/chat/completions",
|
baseUrl: "https://portal.qwen.ai/v1/chat/completions",
|
||||||
format: "openai",
|
format: "openai",
|
||||||
headers: {
|
|
||||||
"User-Agent": "google-api-nodejs-client/9.15.1",
|
|
||||||
"X-Goog-Api-Client": "gl-node/22.17.0"
|
|
||||||
},
|
|
||||||
clientId: "f0304373b74a44d2b584a3fb70ca9e56",
|
clientId: "f0304373b74a44d2b584a3fb70ca9e56",
|
||||||
tokenUrl: "https://chat.qwen.ai/api/v1/oauth2/token",
|
tokenUrl: "https://chat.qwen.ai/api/v1/oauth2/token",
|
||||||
authUrl: "https://chat.qwen.ai/api/v1/oauth2/device/code"
|
authUrl: "https://chat.qwen.ai/api/v1/oauth2/device/code"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { KiroExecutor } from "./kiro.js";
|
|||||||
import { CodexExecutor } from "./codex.js";
|
import { CodexExecutor } from "./codex.js";
|
||||||
import { CursorExecutor } from "./cursor.js";
|
import { CursorExecutor } from "./cursor.js";
|
||||||
import { VertexExecutor } from "./vertex.js";
|
import { VertexExecutor } from "./vertex.js";
|
||||||
|
import { QwenExecutor } from "./qwen.js";
|
||||||
import { DefaultExecutor } from "./default.js";
|
import { DefaultExecutor } from "./default.js";
|
||||||
|
|
||||||
const executors = {
|
const executors = {
|
||||||
@@ -21,6 +22,7 @@ const executors = {
|
|||||||
cu: new CursorExecutor(), // Alias for cursor
|
cu: new CursorExecutor(), // Alias for cursor
|
||||||
vertex: new VertexExecutor("vertex"),
|
vertex: new VertexExecutor("vertex"),
|
||||||
"vertex-partner": new VertexExecutor("vertex-partner"),
|
"vertex-partner": new VertexExecutor("vertex-partner"),
|
||||||
|
qwen: new QwenExecutor(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultCache = new Map();
|
const defaultCache = new Map();
|
||||||
@@ -46,3 +48,4 @@ export { CodexExecutor } from "./codex.js";
|
|||||||
export { CursorExecutor } from "./cursor.js";
|
export { CursorExecutor } from "./cursor.js";
|
||||||
export { VertexExecutor } from "./vertex.js";
|
export { VertexExecutor } from "./vertex.js";
|
||||||
export { DefaultExecutor } from "./default.js";
|
export { DefaultExecutor } from "./default.js";
|
||||||
|
export { QwenExecutor } from "./qwen.js";
|
||||||
|
|||||||
81
open-sse/executors/qwen.js
Normal file
81
open-sse/executors/qwen.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { platform, arch } from "os";
|
||||||
|
import { DefaultExecutor } from "./default.js";
|
||||||
|
|
||||||
|
/** portal.qwen.ai — aligned with CLIProxyAPI qwen_executor */
|
||||||
|
const qwenCodeVersion = "0.13.2";
|
||||||
|
const qwenStainless = {
|
||||||
|
runtimeVersion: "v22.17.0",
|
||||||
|
lang: "js",
|
||||||
|
packageVersion: "5.11.0",
|
||||||
|
retryCount: "0",
|
||||||
|
runtime: "node"
|
||||||
|
};
|
||||||
|
const qwenDefaultSystemMessage = {
|
||||||
|
role: "system",
|
||||||
|
content: [{ type: "text", text: "", cache_control: { type: "ephemeral" } }]
|
||||||
|
};
|
||||||
|
|
||||||
|
function qwenStainlessOsLabel() {
|
||||||
|
const p = platform();
|
||||||
|
if (p === "darwin") return "MacOS";
|
||||||
|
if (p === "win32") return "Windows";
|
||||||
|
if (p === "linux") return "Linux";
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
function qwenUserAgent() {
|
||||||
|
return `QwenCode/${qwenCodeVersion} (${platform()}; ${arch()})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureQwenSystemMessage(body) {
|
||||||
|
if (!body || typeof body !== "object") return body;
|
||||||
|
const next = { ...body };
|
||||||
|
if (Array.isArray(next.messages)) {
|
||||||
|
next.messages = [qwenDefaultSystemMessage, ...next.messages];
|
||||||
|
} else {
|
||||||
|
next.messages = [qwenDefaultSystemMessage];
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildQwenUpstreamHeaders(credentials, stream = true) {
|
||||||
|
const token = credentials?.apiKey || credentials?.accessToken || "";
|
||||||
|
const ua = qwenUserAgent();
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
"User-Agent": ua,
|
||||||
|
"X-DashScope-UserAgent": ua,
|
||||||
|
"X-Stainless-Runtime-Version": qwenStainless.runtimeVersion,
|
||||||
|
"X-Stainless-Lang": qwenStainless.lang,
|
||||||
|
"X-Stainless-Arch": arch(),
|
||||||
|
"X-Stainless-Package-Version": qwenStainless.packageVersion,
|
||||||
|
"X-DashScope-CacheControl": "enable",
|
||||||
|
"X-Stainless-Retry-Count": qwenStainless.retryCount,
|
||||||
|
"X-Stainless-Os": qwenStainlessOsLabel(),
|
||||||
|
"X-DashScope-AuthType": "qwen-oauth",
|
||||||
|
"X-Stainless-Runtime": qwenStainless.runtime
|
||||||
|
};
|
||||||
|
headers.Accept = stream ? "text/event-stream" : "application/json";
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class QwenExecutor extends DefaultExecutor {
|
||||||
|
constructor() {
|
||||||
|
super("qwen");
|
||||||
|
}
|
||||||
|
|
||||||
|
buildHeaders(credentials, stream = true) {
|
||||||
|
return buildQwenUpstreamHeaders(credentials, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
transformRequest(model, body, stream, credentials) {
|
||||||
|
const next = body && typeof body === "object" ? { ...body } : body;
|
||||||
|
if (stream && next?.messages && !next.stream_options) {
|
||||||
|
next.stream_options = { include_usage: true };
|
||||||
|
}
|
||||||
|
return ensureQwenSystemMessage(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default QwenExecutor;
|
||||||
Reference in New Issue
Block a user