feat(kiro): 增强账号池健康检查配置并优化凭证加载逻辑

为 provider_pools.json 配置文件新增 checkHealth 字段,允许灵活控制各账号的健康检查行为。同时重构 Kiro OAuth 凭证加载机制,统一处理指定文件和目录扫描的逻辑,提升凭证管理的可靠性。

此外,在多语言 README 文档中补充 10.18 版本更新说明,告知用户 Kiro 服务的最新动态。
This commit is contained in:
hex2077 2025-10-18 16:12:13 +08:00
parent 52417dd805
commit 5d4283edc6
6 changed files with 47 additions and 31 deletions

View file

@ -28,6 +28,8 @@
> 8.29 Added account pool mode, which supports multiple accounts for all providers, with built-in polling, failover (requires client retry), and configuration degradation. Requires adding PROVIDER_POOLS_FILE_PATH to config, see the configuration file: provider_pools.json for details.
>
> 9.1 Added Qwen Code CLI support, can use qwen3-coder-plus model
>
> 10.18 Kiro open registration, new accounts get 500 credits, now supports Claude Sonnet4.5
---

View file

@ -29,6 +29,8 @@
> 8.29 アカウントプールモードを追加。すべてのプロバイダーで複数アカウントの設定をサポート。ラウンドロビン、フェイルオーバークライアント再試行必要、設定ダウングレードを内蔵。configでPROVIDER_POOLS_FILE_PATH設定が必要。詳細は設定ファイルprovider_pools.json参照
>
> 9.1 Qwen Code CLIサポートを密かに追加、qwen3-coder-plusモデルが使用可能
>
> 10.18 Kiroはオープン登録、新規アカウントに500クレジット付与、Claude Sonnet4.5に対応
---

View file

@ -29,6 +29,8 @@
> 8.29 新增账号池模式可支持所有provider配置多个账号自带轮询故障转移需要客户端重试和配置降级。需要在 config 新增配置 PROVIDER_POOLS_FILE_PATH 详见配置文件provider_pools.json
>
> 9.1 偷摸的新增 Qwen Code CLI 支持,可使用 qwen3-coder-plus 模型
>
> 10.18 Kiro开放注册新号送500额度已支持Claude Sonnet4.5
---

View file

@ -4,6 +4,7 @@
"OPENAI_API_KEY": "sk-openai-key1",
"OPENAI_BASE_URL": "https://api.openai.com/v1",
"checkModelName": null,
"checkHealth": true,
"uuid": "2f579c65-d3c5-41b1-9985-9f6e3d7bf39c",
"isHealthy": true,
"lastUsed": null,
@ -15,6 +16,7 @@
"OPENAI_API_KEY": "sk-openai-key2",
"OPENAI_BASE_URL": "https://api.openai.com/v1",
"checkModelName": null,
"checkHealth": true,
"uuid": "e284628d-302f-456d-91f3-6095386fb3b8",
"isHealthy": true,
"lastUsed": null,
@ -28,6 +30,7 @@
"OPENAI_API_KEY": "sk-openai-key",
"OPENAI_BASE_URL": "https://api.openai.com/v1",
"checkModelName": null,
"checkHealth": true,
"uuid": "e284628d-302f-456d-91f3-609538678968",
"isHealthy": true,
"lastUsed": null,
@ -41,6 +44,7 @@
"GEMINI_OAUTH_CREDS_FILE_PATH": "./credentials1.json",
"PROJECT_ID": "your-project-id-1",
"checkModelName": null,
"checkHealth": true,
"uuid": "ac200154-26b8-4f5f-8650-e8cc738b06e3",
"isHealthy": true,
"lastUsed": null,
@ -52,6 +56,7 @@
"GEMINI_OAUTH_CREDS_FILE_PATH": "./credentials2.json",
"PROJECT_ID": "your-project-id-2",
"checkModelName": null,
"checkHealth": true,
"uuid": "4f8afcc2-a9bb-4b96-bb50-3b9667a71f54",
"isHealthy": true,
"lastUsed": null,
@ -65,6 +70,7 @@
"CLAUDE_API_KEY": "sk-claude-key1",
"CLAUDE_BASE_URL": "https://api.anthropic.com",
"checkModelName": null,
"checkHealth": true,
"uuid": "bb87047a-3b1d-4249-adbb-1087ecd58128",
"isHealthy": true,
"lastUsed": null,
@ -76,6 +82,7 @@
"CLAUDE_API_KEY": "sk-claude-key2",
"CLAUDE_BASE_URL": "https://api.anthropic.com",
"checkModelName": null,
"checkHealth": true,
"uuid": "7c2002c6-122a-4db0-af06-8a0ff433801a",
"isHealthy": true,
"lastUsed": null,
@ -89,6 +96,7 @@
"KIRO_OAUTH_CREDS_FILE_PATH": "./kiro_creds1.json",
"uuid": "2c69d0ac-b86f-43d8-9d17-0d300afc5cfd",
"checkModelName": null,
"checkHealth": true,
"isHealthy": true,
"lastUsed": null,
"usageCount": 0,
@ -99,6 +107,7 @@
"KIRO_OAUTH_CREDS_FILE_PATH": "./kiro_creds2.json",
"uuid": "7482abe6-8083-4288-bb7d-d8ecb7c461e2",
"checkModelName": null,
"checkHealth": true,
"isHealthy": true,
"lastUsed": null,
"usageCount": 0,
@ -111,6 +120,7 @@
"QWEN_OAUTH_CREDS_FILE_PATH": "./qwen_creds.json",
"uuid": "658a2114-c4c9-d713-b8d4-ceabf0e0bf18",
"checkModelName": null,
"checkHealth": true,
"isHealthy": true,
"lastUsed": null,
"usageCount": 0,

View file

@ -336,41 +336,38 @@ async initializeAuth(forceRefresh = false) {
this.base64Creds = null;
}
// Priority 2: Load from a specific file path if provided and not already loaded from token file
const credPath = this.credsFilePath || path.join(this.credPath, KIRO_AUTH_TOKEN_FILE);
if (credPath) {
console.debug(`[Kiro Auth] Attempting to load credentials from specified file: ${credPath}`);
const credentialsFromFile = await loadCredentialsFromFile(credPath);
if (credentialsFromFile) {
Object.assign(mergedCredentials, credentialsFromFile);
console.info(`[Kiro Auth] Successfully loaded credentials from ${credPath}.`);
} else {
console.warn(`[Kiro Auth] Could not load credentials from specified file path: ${credPath}`);
// Priority 2 & 3 合并: 从指定文件路径或目录加载凭证
// 读取指定的 credPath 文件以及目录下的其他 JSON 文件(排除当前文件)
const targetFilePath = this.credsFilePath || path.join(this.credPath, KIRO_AUTH_TOKEN_FILE);
const dirPath = path.dirname(targetFilePath);
const targetFileName = path.basename(targetFilePath);
console.debug(`[Kiro Auth] Attempting to load credentials from directory: ${dirPath}`);
try {
// 首先尝试读取目标文件
const targetCredentials = await loadCredentialsFromFile(targetFilePath);
if (targetCredentials) {
Object.assign(mergedCredentials, targetCredentials);
console.info(`[Kiro Auth] Successfully loaded OAuth credentials from ${targetFilePath}`);
}
}
// Priority 3: Load from default directory only if no specific file path is configured
if (!this.credsFilePath) {
const dirPath = this.credPath;
console.debug(`[Kiro Auth] Attempting to load credentials from directory: ${dirPath}`);
try {
const files = await fs.readdir(dirPath);
for (const file of files) {
if (file.endsWith('.json') && file !== KIRO_AUTH_TOKEN_FILE) {
const filePath = path.join(dirPath, file);
const credentials = await loadCredentialsFromFile(filePath);
if (credentials) {
credentials.expiresAt = mergedCredentials.expiresAt;
Object.assign(mergedCredentials, credentials);
console.debug(`[Kiro Auth] Loaded credentials from ${file}`);
}
// 然后读取目录下的其他 JSON 文件(排除目标文件本身)
const files = await fs.readdir(dirPath);
for (const file of files) {
if (file.endsWith('.json') && file !== targetFileName) {
const filePath = path.join(dirPath, file);
const credentials = await loadCredentialsFromFile(filePath);
if (credentials) {
// 保留已有的 expiresAt,避免被覆盖
credentials.expiresAt = mergedCredentials.expiresAt;
Object.assign(mergedCredentials, credentials);
console.debug(`[Kiro Auth] Loaded Client credentials from ${file}`);
}
}
} catch (error) {
console.debug(`[Kiro Auth] Could not read credential directory ${dirPath}: ${error.message}`);
}
} else {
console.debug(`[Kiro Auth] Skipping directory scan because specific file path is configured: ${this.credsFilePath}`);
} catch (error) {
console.warn(`[Kiro Auth] Error loading credentials from directory ${dirPath}: ${error.message}`);
}
// console.log('[Kiro Auth] Merged credentials:', mergedCredentials);

View file

@ -189,6 +189,9 @@ export class ProviderPoolManager {
// Create a temporary service adapter for health check
const tempConfig = { ...providerConfig, MODEL_PROVIDER: providerType };
const serviceAdapter = getServiceAdapter(tempConfig);
if(!providerConfig.checkHealth){
return true;
}
// Determine a suitable model name for health check
// First, try to get it from the provider configuration