feat(gemini-cli): add proper User-Agent and X-Goog-Api-Client headers
Match native GeminiCLI client fingerprint to avoid upstream rejection. Also fix base executor to call transformRequest before buildHeaders so subclasses can store model context for header generation. Made-with: Cursor
This commit is contained in:
parent
10b22d1318
commit
06a5307160
3 changed files with 35 additions and 3 deletions
|
|
@ -19,6 +19,34 @@ function mapStainlessArch() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === Gemini CLI Version Constants ===
|
||||||
|
export const GEMINI_CLI_VERSION = "0.31.0";
|
||||||
|
export const GEMINI_CLI_API_CLIENT = "google-genai-sdk/1.41.0 gl-node/v22.19.0";
|
||||||
|
|
||||||
|
function mapGeminiCLIOs() {
|
||||||
|
switch (platform()) {
|
||||||
|
case "darwin": return "darwin";
|
||||||
|
case "win32": return "windows";
|
||||||
|
case "linux": return "linux";
|
||||||
|
case "freebsd": return "freebsd";
|
||||||
|
default: return platform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapGeminiCLIArch() {
|
||||||
|
switch (arch()) {
|
||||||
|
case "x64": return "x64";
|
||||||
|
case "arm64": return "arm64";
|
||||||
|
case "ia32": return "x86";
|
||||||
|
default: return arch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns User-Agent matching native Gemini CLI format: GeminiCLI/<version>/<model> (<os>; <arch>) */
|
||||||
|
export function geminiCLIUserAgent(model = "unknown") {
|
||||||
|
return `GeminiCLI/${GEMINI_CLI_VERSION}/${model || "unknown"} (${mapGeminiCLIOs()}; ${mapGeminiCLIArch()})`;
|
||||||
|
}
|
||||||
|
|
||||||
// === GitHub Copilot Version Constants ===
|
// === GitHub Copilot Version Constants ===
|
||||||
export const GITHUB_COPILOT = {
|
export const GITHUB_COPILOT = {
|
||||||
VSCODE_VERSION: "1.110.0",
|
VSCODE_VERSION: "1.110.0",
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,8 @@ export class BaseExecutor {
|
||||||
|
|
||||||
for (let urlIndex = 0; urlIndex < fallbackCount; urlIndex++) {
|
for (let urlIndex = 0; urlIndex < fallbackCount; urlIndex++) {
|
||||||
const url = this.buildUrl(model, stream, urlIndex, credentials);
|
const url = this.buildUrl(model, stream, urlIndex, credentials);
|
||||||
const headers = this.buildHeaders(credentials, stream);
|
|
||||||
const transformedBody = this.transformRequest(model, body, stream, credentials);
|
const transformedBody = this.transformRequest(model, body, stream, credentials);
|
||||||
|
const headers = this.buildHeaders(credentials, stream);
|
||||||
|
|
||||||
if (!retryAttemptsByUrl[urlIndex]) retryAttemptsByUrl[urlIndex] = 0;
|
if (!retryAttemptsByUrl[urlIndex]) retryAttemptsByUrl[urlIndex] = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { BaseExecutor } from "./base.js";
|
import { BaseExecutor } from "./base.js";
|
||||||
import { PROVIDERS, OAUTH_ENDPOINTS } from "../config/constants.js";
|
import { PROVIDERS, OAUTH_ENDPOINTS, GEMINI_CLI_API_CLIENT, geminiCLIUserAgent } from "../config/constants.js";
|
||||||
|
|
||||||
export class GeminiCLIExecutor extends BaseExecutor {
|
export class GeminiCLIExecutor extends BaseExecutor {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
@ -15,11 +15,15 @@ export class GeminiCLIExecutor extends BaseExecutor {
|
||||||
return {
|
return {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"Authorization": `Bearer ${credentials.accessToken}`,
|
"Authorization": `Bearer ${credentials.accessToken}`,
|
||||||
...(stream && { "Accept": "text/event-stream" })
|
"User-Agent": geminiCLIUserAgent(this._currentModel),
|
||||||
|
"X-Goog-Api-Client": GEMINI_CLI_API_CLIENT,
|
||||||
|
"Accept": stream ? "text/event-stream" : "application/json"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
transformRequest(model, body, stream, credentials) {
|
transformRequest(model, body, stream, credentials) {
|
||||||
|
// Store model for use in buildHeaders (called by base.execute after transformRequest)
|
||||||
|
this._currentModel = model;
|
||||||
if (!body.project && credentials?.projectId) {
|
if (!body.project && credentials?.projectId) {
|
||||||
body.project = credentials.projectId;
|
body.project = credentials.projectId;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue