diff --git a/README-EN.md b/README-EN.md index 7abe7db..e77d664 100644 --- a/README-EN.md +++ b/README-EN.md @@ -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 --- diff --git a/README-JA.md b/README-JA.md index ff2e32d..572394c 100644 --- a/README-JA.md +++ b/README-JA.md @@ -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に対応 --- diff --git a/README.md b/README.md index 9750c7b..ac725ab 100644 --- a/README.md +++ b/README.md @@ -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 --- diff --git a/provider_pools.json.example b/provider_pools.json.example index 9da853c..d10c48d 100644 --- a/provider_pools.json.example +++ b/provider_pools.json.example @@ -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, diff --git a/src/claude/claude-kiro.js b/src/claude/claude-kiro.js index 5e199ef..585a1b5 100644 --- a/src/claude/claude-kiro.js +++ b/src/claude/claude-kiro.js @@ -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); diff --git a/src/provider-pool-manager.js b/src/provider-pool-manager.js index cecd9ff..807c0d6 100644 --- a/src/provider-pool-manager.js +++ b/src/provider-pool-manager.js @@ -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