feat(api): 添加指定--project-id

为gemini和openai API服务器添加--project-id参数,允许在多项目环境中指定GCP项目ID
更新相关文档和核心服务类以支持此功能
This commit is contained in:
hex2077 2025-07-20 22:17:49 +08:00
parent 4c2c9bde33
commit 3ae54773ee
5 changed files with 57 additions and 7 deletions

View file

@ -123,6 +123,10 @@ This project consists of three core files, each with its own specific function:
```bash
node gemini-api-server.js --oauth-creds-file "/path/to/your/oauth_creds.json"
```
* **Start with Specified Project ID** (e.g., for multi-project environments)
```bash
node gemini-api-server.js --project-id your-gcp-project-id
```
#### 💻 Call the API (Default API Key: `123456`)
* **List Models**

View file

@ -123,6 +123,10 @@
```bash
node gemini-api-server.js --oauth-creds-file "/path/to/your/oauth_creds.json"
```
* **通过指定项目ID启动** (例如,用于多项目环境)
```bash
node gemini-api-server.js --project-id your-gcp-project-id
```
#### 💻 调用 API (默认 API Key: `123456`)
* **列出模型**

View file

@ -57,6 +57,9 @@
* // 通过指定凭证文件路径启动 (例如,用于自定义凭证位置)
* node gemini-api-server.js --oauth-creds-file "/path/to/your/oauth_creds.json"
*
* // 通过指定项目ID启动 (例如,用于多项目环境)
* node gemini-api-server.js --project-id your-gcp-project-id
*
* 3. 调用 API 接口 (默认 API Key: 123456):
*
* // a) 列出可用模型 (GET 请求,密钥在 URL 参数中)
@ -106,6 +109,7 @@ let REQUIRED_API_KEY = '123456'; // Default API Key
let SERVER_PORT = 3000; // Default Port
let OAUTH_CREDS_BASE64 = null; // New variable for base64 encoded OAuth credentials
let OAUTH_CREDS_FILE_PATH = null; // New variable for OAuth credentials file path
let PROJECT_ID = null; // New variable for project ID
const args = process.argv.slice(2);
const remainingArgs = [];
@ -151,6 +155,13 @@ for (let i = 0; i < args.length; i++) {
} else {
console.warn(`[Config Warning] --oauth-creds-file flag requires a value.`);
}
} else if (args[i] === '--project-id') { // New argument for project ID
if (i + 1 < args.length) {
PROJECT_ID = args[i + 1];
i++; // Skip the value
} else {
console.warn(`[Config Warning] --project-id flag requires a value.`);
}
} else {
remainingArgs.push(args[i]);
}
@ -186,7 +197,7 @@ function isAuthorized(req, requestUrl) {
let apiServiceInstance = null;
async function getApiService() {
if (!apiServiceInstance) {
apiServiceInstance = new GeminiApiService(HOST, OAUTH_CREDS_BASE64, OAUTH_CREDS_FILE_PATH);
apiServiceInstance = new GeminiApiService(HOST, OAUTH_CREDS_BASE64, OAUTH_CREDS_FILE_PATH, PROJECT_ID);
await apiServiceInstance.initialize();
} else if (!apiServiceInstance.isInitialized) {
await apiServiceInstance.initialize();
@ -291,6 +302,7 @@ server.listen(SERVER_PORT, HOST, () => {
console.log(` Required API Key: ${REQUIRED_API_KEY}`);
console.log(` Prompt Logging: ${PROMPT_LOG_MODE}${PROMPT_LOG_MODE === 'file' ? ` (to ${PROMPT_LOG_FILENAME})` : ''}`);
console.log(` OAuth Creds File Path: ${OAUTH_CREDS_FILE_PATH || 'Default'}`);
console.log(` Project ID: ${PROJECT_ID || 'Auto-discovered'}`); // Log the project ID
console.log(`--------------------------`);
console.log(`\nGemini API Server (Final) running on http://${HOST}:${SERVER_PORT}`);
console.log('Initializing service... This may take a moment.');

View file

@ -124,9 +124,9 @@ export async function getRequestBody(req) {
// --- Main Service Class ---
export class GeminiApiService {
constructor(host = 'localhost', oauthCredsBase64 = null, oauthCredsFilePath = null) {
constructor(host = 'localhost', oauthCredsBase64 = null, oauthCredsFilePath = null, projectId = null) {
this.authClient = new OAuth2Client(OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET);
this.projectId = null;
this.projectId = projectId; // Set projectId from constructor argument
this.availableModels = [];
this.isInitialized = false;
this.host = host;
@ -138,7 +138,15 @@ export class GeminiApiService {
if (this.isInitialized) return;
console.log('[Service] Initializing Gemini API Service...');
await this.initializeAuth();
this.projectId = await this.discoverProjectAndModels();
// Only discover project ID if it's not already provided
if (!this.projectId) {
this.projectId = await this.discoverProjectAndModels();
} else {
console.log(`[Service] Using provided Project ID: ${this.projectId}`);
// Still need to ensure models are set up even if project ID is provided
this.availableModels = ['gemini-2.5-pro', 'gemini-2.5-flash'];
console.log(`[Service] Using fixed models: [${this.availableModels.join(', ')}]`);
}
this.isInitialized = true;
console.log(`[Service] Initialization complete. Project ID: ${this.projectId}`);
}
@ -239,7 +247,12 @@ export class GeminiApiService {
}
async discoverProjectAndModels() {
if (this.projectId) return this.projectId;
// If projectId is already set, return it directly
if (this.projectId) {
console.log(`[Service] Using pre-configured Project ID: ${this.projectId}`);
return this.projectId;
}
console.log('[Service] Discovering Project ID...');
this.availableModels = ['gemini-2.5-pro', 'gemini-2.5-flash'];
console.log(`[Service] Using fixed models: [${this.availableModels.join(', ')}]`);
@ -249,7 +262,7 @@ export class GeminiApiService {
return loadResponse.cloudaicompanionProject;
}
const defaultTier = loadResponse.allowedTiers?.find(tier => tier.isDefault);
const onboardRequest = { tierId: defaultTier?.id || 'free-tier', metadata: { pluginType: 'GEMINI' } };
const onboardRequest = { tierId: defaultTier?.id || 'free-tier', metadata: { pluginType: 'GEMINI' } , cloudaicompanionProject: 'default',};
let lro = await this.callApi('onboardUser', onboardRequest);
while (!lro.done) {
await new Promise(resolve => setTimeout(resolve, 2000));
@ -278,11 +291,14 @@ export class GeminiApiService {
async callApi(method, body, isRetry = false) {
try {
console.log(`${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:${method}`);
console.log(body);
const res = await this.authClient.request({
url: `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:${method}`,
method: "POST", headers: { "Content-Type": "application/json" },
responseType: "json", body: JSON.stringify(body),
});
console.log(res.data);
return res.data;
} catch (error) {
if (error.response?.status === 401 && !isRetry) {

View file

@ -71,6 +71,11 @@
* node openai-api-server.js --oauth-creds-file "/path/to/your/oauth_creds.json"
* ```
*
* - **通过指定项目ID启动** (例如用于多项目环境)
* ```bash
* node openai-api-server.js --project-id your-gcp-project-id
* ```
*
* 4. 调用 API 接口 (假设 API Key: `your_secret_key`, 服务运行在 `localhost:8000`):
*
* - **a) 列出可用模型**
@ -127,6 +132,7 @@ let REQUIRED_API_KEY = '123456'; // Default API Key
let SERVER_PORT = 8000; // Default Port
let OAUTH_CREDS_BASE64 = null; // New variable for base64 encoded OAuth credentials
let OAUTH_CREDS_FILE_PATH = null; // New variable for OAuth credentials file path
let PROJECT_ID = null; // New variable for project ID
const args = process.argv.slice(2);
const remainingArgs = [];
@ -172,6 +178,13 @@ for (let i = 0; i < args.length; i++) {
} else {
console.warn(`[Config Warning] --oauth-creds-file flag requires a value.`);
}
} else if (args[i] === '--project-id') { // New argument for project ID
if (i + 1 < args.length) {
PROJECT_ID = args[i + 1];
i++; // Skip the value
} else {
console.warn(`[Config Warning] --project-id flag requires a value.`);
}
} else {
remainingArgs.push(args[i]);
}
@ -398,7 +411,7 @@ function isAuthorized(req, requestUrl) {
let apiServiceInstance = null;
async function getApiService() {
if (!apiServiceInstance) {
apiServiceInstance = new GeminiApiService(HOST, OAUTH_CREDS_BASE64, OAUTH_CREDS_FILE_PATH);
apiServiceInstance = new GeminiApiService(HOST, OAUTH_CREDS_BASE64, OAUTH_CREDS_FILE_PATH, PROJECT_ID);
await apiServiceInstance.initialize();
} else if (!apiServiceInstance.isInitialized) { // Ensure re-initialization if not already initialized
await apiServiceInstance.initialize();
@ -522,6 +535,7 @@ server.listen(SERVER_PORT, HOST, () => {
console.log(` Required API Key: ${REQUIRED_API_KEY}`);
console.log(` Prompt Logging: ${PROMPT_LOG_MODE}${PROMPT_LOG_MODE === 'file' ? ` (to ${PROMPT_LOG_FILENAME})` : ''}`);
console.log(` OAuth Creds File Path: ${OAUTH_CREDS_FILE_PATH || 'Default'}`);
console.log(` Project ID: ${PROJECT_ID || 'Auto-discovered'}`); // Log the project ID
console.log(`---------------------------------------------`);
console.log(`\nServer running on http://${HOST}:${SERVER_PORT}`);
console.log('Initializing backend service... This may take a moment.');