fix(provider): 修复健康检查逻辑并添加checkModelName字段

实现实际的健康检查逻辑,通过临时服务适配器进行API调用验证
为所有provider配置添加checkModelName字段用于健康检查
修正初始化日志中的服务名称错误
This commit is contained in:
hex2077 2025-08-30 17:29:55 +08:00
parent 7ca3763d33
commit bd30a5f8d3
3 changed files with 88 additions and 11 deletions

View file

@ -3,6 +3,7 @@
{
"OPENAI_API_KEY": "sk-openai-key1",
"OPENAI_BASE_URL": "https://api.openai.com/v1",
"checkModelName": null,
"uuid": "2f579c65-d3c5-41b1-9985-9f6e3d7bf39c",
"isHealthy": true,
"lastUsed": null,
@ -13,6 +14,7 @@
{
"OPENAI_API_KEY": "sk-openai-key2",
"OPENAI_BASE_URL": "https://api.openai.com/v1",
"checkModelName": null,
"uuid": "e284628d-302f-456d-91f3-6095386fb3b8",
"isHealthy": true,
"lastUsed": null,
@ -25,6 +27,7 @@
{
"GEMINI_OAUTH_CREDS_FILE_PATH": "./credentials1.json",
"PROJECT_ID": "your-project-id-1",
"checkModelName": null,
"uuid": "ac200154-26b8-4f5f-8650-e8cc738b06e3",
"isHealthy": true,
"lastUsed": null,
@ -35,6 +38,7 @@
{
"GEMINI_OAUTH_CREDS_FILE_PATH": "./credentials2.json",
"PROJECT_ID": "your-project-id-2",
"checkModelName": null,
"uuid": "4f8afcc2-a9bb-4b96-bb50-3b9667a71f54",
"isHealthy": true,
"lastUsed": null,
@ -47,6 +51,7 @@
{
"CLAUDE_API_KEY": "sk-claude-key1",
"CLAUDE_BASE_URL": "https://api.anthropic.com",
"checkModelName": null,
"uuid": "bb87047a-3b1d-4249-adbb-1087ecd58128",
"isHealthy": true,
"lastUsed": null,
@ -57,6 +62,7 @@
{
"CLAUDE_API_KEY": "sk-claude-key2",
"CLAUDE_BASE_URL": "https://api.anthropic.com",
"checkModelName": null,
"uuid": "7c2002c6-122a-4db0-af06-8a0ff433801a",
"isHealthy": true,
"lastUsed": null,
@ -69,6 +75,7 @@
{
"KIRO_OAUTH_CREDS_FILE_PATH": "./kiro_creds1.json",
"uuid": "2c69d0ac-b86f-43d8-9d17-0d300afc5cfd",
"checkModelName": null,
"isHealthy": true,
"lastUsed": null,
"usageCount": 0,
@ -78,6 +85,7 @@
{
"KIRO_OAUTH_CREDS_FILE_PATH": "./kiro_creds2.json",
"uuid": "7482abe6-8083-4288-bb7d-d8ecb7c461e2",
"checkModelName": null,
"isHealthy": true,
"lastUsed": null,
"usageCount": 0,

View file

@ -260,7 +260,7 @@ export class KiroApiService {
async initialize() {
if (this.isInitialized) return;
console.log('[Kiro] Initializing Gemini API Service...');
console.log('[Kiro] Initializing Kiro API Service...');
await this.initializeAuth();
const macSha256 = await getMacAddressSha256();
this.axiosInstance = axios.create({

View file

@ -1,4 +1,6 @@
import * as fs from 'fs'; // Import fs module
import { getServiceAdapter } from './adapter.js';
import { MODEL_PROVIDER } from './common.js';
/**
* Manages a pool of API service providers, handling their health and selection.
@ -146,17 +148,22 @@ export class ProviderPoolManager {
}
try {
// TODO: Implement actual health check logic for each provider type
// For now, if a provider was unhealthy and enough time has passed,
// we optimistically mark it healthy and reset error count.
// A more robust system would involve actual API calls or pings here.
if (!providerStatus.config.isHealthy) {
// Only reset and mark healthy if it was unhealthy and we are attempting a check after interval
this.markProviderHealthy(providerType, providerConfig);
console.log(`[ProviderPoolManager] Health check for ${JSON.stringify(providerConfig)} (${providerType}): Marked Healthy (re-evaluation)`);
// Perform actual health check based on provider type
const isHealthy = await this._checkProviderHealth(providerType, providerConfig);
if (isHealthy) {
if (!providerStatus.config.isHealthy) {
// Provider was unhealthy but is now healthy
this.markProviderHealthy(providerType, providerConfig);
console.log(`[ProviderPoolManager] Health check for ${JSON.stringify(providerConfig)} (${providerType}): Marked Healthy (actual check)`);
} else {
// Provider was already healthy and still is
console.log(`[ProviderPoolManager] Health check for ${JSON.stringify(providerConfig)} (${providerType}): Still Healthy`);
}
} else {
// For already healthy providers, just log or perform a lighter check if needed
console.log(`[ProviderPoolManager] Health check for ${JSON.stringify(providerConfig)} (${providerType}): Still Healthy`);
// Provider is not healthy
console.warn(`[ProviderPoolManager] Health check for ${JSON.stringify(providerConfig)} (${providerType}) failed: Provider is not responding correctly.`);
this.markProviderUnhealthy(providerType, providerConfig);
}
} catch (error) {
@ -167,6 +174,68 @@ export class ProviderPoolManager {
}
}
}
/**
* Performs an actual health check for a specific provider.
* @param {string} providerType - The type of the provider.
* @param {object} providerConfig - The configuration of the provider to check.
* @returns {Promise<boolean>} - True if the provider is healthy, false otherwise.
*/
async _checkProviderHealth(providerType, providerConfig) {
try {
// Create a temporary service adapter for health check
const tempConfig = { ...providerConfig, MODEL_PROVIDER: providerType };
const serviceAdapter = getServiceAdapter(tempConfig);
// Determine a suitable model name for health check
// First, try to get it from the provider configuration
let modelName = providerConfig.checkModelName;
// If not specified in config, use default model names based on provider type
if (!modelName) {
switch (providerType) {
case MODEL_PROVIDER.GEMINI_CLI:
modelName = 'gemini-2.5-flash'; // Example model name for Gemini
break;
case MODEL_PROVIDER.OPENAI_CUSTOM:
modelName = 'gpt-3.5-turbo'; // Example model name for OpenAI
break;
case MODEL_PROVIDER.CLAUDE_CUSTOM:
modelName = 'claude-3-7-sonnet-20250219'; // Example model name for Claude
break;
case MODEL_PROVIDER.KIRO_API:
modelName = 'claude-3-7-sonnet-20250219'; // Example model name for Kiro API
break;
default:
console.warn(`[ProviderPoolManager] Unknown provider type for health check: ${providerType}`);
return false;
}
}
// Perform a lightweight API call to check health
const healthCheckRequest = {
contents: [{
role: 'user',
parts: [{ text: 'Hello, are you ok?' }]
}]
};
// For OpenAI and Claude providers, we need a different request format
if (providerType === MODEL_PROVIDER.OPENAI_CUSTOM || providerType === MODEL_PROVIDER.CLAUDE_CUSTOM || providerType === MODEL_PROVIDER.KIRO_API) {
healthCheckRequest.messages = [{ role: 'user', content: 'Hello, are you ok?' }];
healthCheckRequest.model = modelName;
delete healthCheckRequest.contents;
}
// console.log(`[ProviderPoolManager] Health check request for ${modelName}: ${JSON.stringify(healthCheckRequest)}`);
await serviceAdapter.generateContent(modelName, healthCheckRequest);
return true;
} catch (error) {
console.error(`[ProviderPoolManager] Health check failed for ${providerType}: ${error.message}`);
return false;
}
}
/**
* Saves the current provider pools configuration to the JSON file.
* @private