feat: add GLM Coding (China) provider and Usage by API Keys statistics

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Blade096
2026-02-11 15:44:08 +07:00
committed by decolua
co-authored by Cursor
parent bd23ab41ee
commit 1ae4e311b7
6 changed files with 835 additions and 199 deletions
+9 -6
View File
@@ -344,8 +344,9 @@ function parseSSEToOpenAIResponse(rawSSE, fallbackModel) {
* @param {function} options.onRequestSuccess - Callback when request succeeds (to clear error status)
* @param {function} options.onDisconnect - Callback when client disconnects
* @param {string} options.connectionId - Connection ID for usage tracking
* @param {string} options.apiKey - API key for usage tracking
*/
export async function handleChatCore({ body, modelInfo, credentials, log, onCredentialsRefreshed, onRequestSuccess, onDisconnect, clientRawRequest, connectionId, userAgent }) {
export async function handleChatCore({ body, modelInfo, credentials, log, onCredentialsRefreshed, onRequestSuccess, onDisconnect, clientRawRequest, connectionId, userAgent, apiKey }) {
const { provider, model } = modelInfo;
const requestStartTime = Date.now();
@@ -587,7 +588,8 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
model: model || "unknown",
tokens: usage,
timestamp: new Date().toISOString(),
connectionId: connectionId || undefined
connectionId: connectionId || undefined,
apiKey: apiKey || undefined
}).catch(err => {
console.error("Failed to save usage stats:", err.message);
});
@@ -704,7 +706,8 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
model: model || "unknown",
tokens: usage,
timestamp: new Date().toISOString(),
connectionId: connectionId || undefined
connectionId: connectionId || undefined,
apiKey: apiKey || undefined
}).catch(err => {
console.error("Failed to save streaming usage stats:", err.message);
});
@@ -719,13 +722,13 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
if (needsCodexTranslation) {
log?.debug?.("STREAM", `Codex translation mode: openai-responses → openai`);
transformStream = createSSETransformStreamWithLogger('openai-responses', 'openai', provider, reqLogger, toolNameMap, model, connectionId, body, onStreamComplete);
transformStream = createSSETransformStreamWithLogger('openai-responses', 'openai', provider, reqLogger, toolNameMap, model, connectionId, body, onStreamComplete, apiKey);
} else if (needsTranslation(targetFormat, sourceFormat)) {
log?.debug?.("STREAM", `Translation mode: ${targetFormat}${sourceFormat}`);
transformStream = createSSETransformStreamWithLogger(targetFormat, sourceFormat, provider, reqLogger, toolNameMap, model, connectionId, body, onStreamComplete);
transformStream = createSSETransformStreamWithLogger(targetFormat, sourceFormat, provider, reqLogger, toolNameMap, model, connectionId, body, onStreamComplete, apiKey);
} else {
log?.debug?.("STREAM", `Standard passthrough mode`);
transformStream = createPassthroughStreamWithLogger(provider, reqLogger, model, connectionId, body, onStreamComplete);
transformStream = createPassthroughStreamWithLogger(provider, reqLogger, model, connectionId, body, onStreamComplete, apiKey);
}
const transformedBody = pipeWithDisconnect(providerResponse, transformStream, streamController);
+11 -7
View File
@@ -29,6 +29,7 @@ const STREAM_MODE = {
* @param {string} options.connectionId - Connection ID for usage tracking
* @param {object} options.body - Request body (for input token estimation)
* @param {function} options.onStreamComplete - Callback when stream completes (content, usage)
* @param {string} options.apiKey - API key for usage tracking
*/
export function createSSEStream(options = {}) {
const {
@@ -41,7 +42,8 @@ export function createSSEStream(options = {}) {
model = null,
connectionId = null,
body = null,
onStreamComplete = null
onStreamComplete = null,
apiKey = null
} = options;
let buffer = "";
@@ -246,7 +248,7 @@ export function createSSEStream(options = {}) {
}
if (hasValidUsage(usage)) {
logUsage(provider, usage, model, connectionId);
logUsage(provider, usage, model, connectionId, apiKey);
} else {
appendRequestLog({ model, provider, connectionId, tokens: null, status: "200 OK" }).catch(() => { });
}
@@ -308,7 +310,7 @@ export function createSSEStream(options = {}) {
}
if (hasValidUsage(state?.usage)) {
logUsage(state.provider || targetFormat, state.usage, model, connectionId);
logUsage(state.provider || targetFormat, state.usage, model, connectionId, apiKey);
} else {
appendRequestLog({ model, provider, connectionId, tokens: null, status: "200 OK" }).catch(() => { });
}
@@ -326,7 +328,7 @@ export function createSSEStream(options = {}) {
});
}
export function createSSETransformStreamWithLogger(targetFormat, sourceFormat, provider = null, reqLogger = null, toolNameMap = null, model = null, connectionId = null, body = null, onStreamComplete = null) {
export function createSSETransformStreamWithLogger(targetFormat, sourceFormat, provider = null, reqLogger = null, toolNameMap = null, model = null, connectionId = null, body = null, onStreamComplete = null, apiKey = null) {
return createSSEStream({
mode: STREAM_MODE.TRANSLATE,
targetFormat,
@@ -337,11 +339,12 @@ export function createSSETransformStreamWithLogger(targetFormat, sourceFormat, p
model,
connectionId,
body,
onStreamComplete
onStreamComplete,
apiKey
});
}
export function createPassthroughStreamWithLogger(provider = null, reqLogger = null, model = null, connectionId = null, body = null, onStreamComplete = null) {
export function createPassthroughStreamWithLogger(provider = null, reqLogger = null, model = null, connectionId = null, body = null, onStreamComplete = null, apiKey = null) {
return createSSEStream({
mode: STREAM_MODE.PASSTHROUGH,
provider,
@@ -349,6 +352,7 @@ export function createPassthroughStreamWithLogger(provider = null, reqLogger = n
model,
connectionId,
body,
onStreamComplete
onStreamComplete,
apiKey
});
}
+2 -2
View File
@@ -279,7 +279,7 @@ export function estimateUsage(body, contentLength, targetFormat = FORMATS.OPENAI
/**
* Log usage with cache info (green color)
*/
export function logUsage(provider, usage, model = null, connectionId = null) {
export function logUsage(provider, usage, model = null, connectionId = null, apiKey = null) {
if (!usage || typeof usage !== "object") return;
const p = provider?.toUpperCase() || "UNKNOWN";
@@ -318,6 +318,6 @@ export function logUsage(provider, usage, model = null, connectionId = null) {
cache_creation_input_tokens: cacheCreation || 0,
reasoning_tokens: reasoning || 0
};
saveRequestUsage({ model, provider, connectionId, tokens }).catch(() => { });
saveRequestUsage({ model, provider, connectionId, tokens, apiKey: apiKey || undefined }).catch(() => { });
appendRequestLog({ model, provider, connectionId, tokens, status: "200 OK" }).catch(() => { });
}