UNPKG

route-claudecode

Version:

Advanced routing and transformation system for Claude Code outputs to multiple AI providers

278 lines 10.2 kB
"use strict"; /** * CodeWhisperer Authentication Manager * 完全基于demo2 Go代码移植的认证管理 * 项目所有者: Jason Zhang */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CodeWhispererAuth = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const os = __importStar(require("os")); const axios_1 = __importDefault(require("axios")); const logger_1 = require("@/utils/logger"); class CodeWhispererAuth { static instance; tokenCache = null; lastTokenRead = 0; TOKEN_CACHE_TTL = 5 * 60 * 1000; // 5分钟缓存 constructor() { } static getInstance() { if (!CodeWhispererAuth.instance) { CodeWhispererAuth.instance = new CodeWhispererAuth(); } return CodeWhispererAuth.instance; } /** * 获取跨平台的token文件路径 (完全基于demo2的getTokenFilePath) */ getTokenFilePath() { const homeDir = os.homedir(); return path.join(homeDir, '.aws', 'sso', 'cache', 'kiro-auth-token.json'); } /** * 获取ProfileArn (基于demo2的token.ProfileArn) */ async getProfileArn() { try { // 先获取token以确保缓存更新 await this.getToken(); if (this.tokenCache?.profileArn) { return this.tokenCache.profileArn; } // 如果token文件中没有profileArn,使用默认值 const defaultProfileArn = 'arn:aws:codewhisperer:us-east-1:699475941385:profile/EHGA3GRVQMUK'; logger_1.logger.warn('Token文件中未找到profileArn,使用默认值', { defaultProfileArn }); return defaultProfileArn; } catch (error) { logger_1.logger.error('获取ProfileArn失败', error); throw error; } } /** * 获取AuthMethod - 新增方法,基于demo3的条件判断逻辑 */ async getAuthMethod() { try { // 先获取token以确保缓存更新 await this.getToken(); if (this.tokenCache?.authMethod) { logger_1.logger.debug('从token缓存获取authMethod', { authMethod: this.tokenCache.authMethod, strategy: 'cached-token-data' }); return this.tokenCache.authMethod; } logger_1.logger.debug('Token中未找到authMethod', { strategy: 'fallback-to-undefined' }); return undefined; } catch (error) { logger_1.logger.error('获取AuthMethod失败', error); return undefined; } } /** * 获取完整的认证信息 - 便捷方法 */ async getAuthInfo() { try { const [token, profileArn, authMethod] = await Promise.all([ this.getToken(), this.getProfileArn(), this.getAuthMethod() ]); logger_1.logger.debug('获取完整认证信息成功', { tokenLength: token.length, profileArnLength: profileArn.length, authMethod, strategy: 'parallel-fetch' }); return { token, profileArn, authMethod }; } catch (error) { logger_1.logger.error('获取完整认证信息失败', error); throw error; } } /** * 读取token信息 (基于demo2的readToken逻辑) */ async getToken() { try { // 检查缓存是否有效 const now = Date.now(); if (this.tokenCache && (now - this.lastTokenRead) < this.TOKEN_CACHE_TTL) { return this.tokenCache.accessToken; } const tokenPath = this.getTokenFilePath(); if (!fs.existsSync(tokenPath)) { throw new Error(`Token文件不存在: ${tokenPath}. 请先安装Kiro并登录!`); } const data = fs.readFileSync(tokenPath, 'utf8'); const token = JSON.parse(data); if (!token.accessToken) { throw new Error('Token文件中缺少accessToken'); } // 更新缓存 this.tokenCache = token; this.lastTokenRead = now; logger_1.logger.debug('Token读取成功', { tokenLength: token.accessToken.length, hasRefreshToken: !!token.refreshToken, expiresAt: token.expiresAt, }); return token.accessToken; } catch (error) { logger_1.logger.error('读取token失败', error); throw error; } } /** * 刷新token (完全基于demo2的refreshToken) */ async refreshToken() { try { logger_1.logger.info('开始刷新token...'); const tokenPath = this.getTokenFilePath(); // 读取当前token const data = fs.readFileSync(tokenPath, 'utf8'); const currentToken = JSON.parse(data); if (!currentToken.refreshToken) { throw new Error('当前token中缺少refreshToken,无法刷新'); } // 准备刷新请求 (基于demo2的RefreshRequest) const refreshReq = { refreshToken: currentToken.refreshToken, }; logger_1.logger.debug('发送token刷新请求', { refreshTokenLength: currentToken.refreshToken.length, }); // 发送刷新请求 (基于demo2的HTTP请求) const response = await axios_1.default.post('https://prod.us-east-1.auth.desktop.kiro.dev/refreshToken', refreshReq, { headers: { 'Content-Type': 'application/json', }, timeout: 10000, }); if (response.status !== 200) { throw new Error(`刷新token失败,状态码: ${response.status}`); } // 更新token文件 (基于demo2的写入逻辑) const newToken = response.data; fs.writeFileSync(tokenPath, JSON.stringify(newToken, null, 2), { mode: 0o600 }); // 更新缓存 this.tokenCache = newToken; this.lastTokenRead = Date.now(); logger_1.logger.info('Token刷新成功', { newTokenLength: newToken.accessToken.length, expiresAt: newToken.expiresAt, }); } catch (error) { logger_1.logger.error('刷新token失败', error); // 清除缓存以强制重新读取 this.tokenCache = null; throw error; } } /** * 验证token是否有效 (基于demo2的启动时验证逻辑) */ async validateToken() { try { const token = await this.getToken(); // 简单验证:检查token格式和长度 if (!token || token.length < 10) { return false; } logger_1.logger.debug('Token验证通过', { tokenLength: token.length, }); return true; } catch (error) { logger_1.logger.warn('Token验证失败', error); return false; } } /** * 导出环境变量格式 (基于demo2的exportEnvVars) */ async exportEnvVars() { try { const token = await this.getToken(); const isWindows = process.platform === 'win32'; if (isWindows) { return [ 'REM CMD格式', 'set ANTHROPIC_BASE_URL=http://localhost:8080', `set ANTHROPIC_API_KEY=${token}`, '', 'REM PowerShell格式', '$env:ANTHROPIC_BASE_URL="http://localhost:8080"', `$env:ANTHROPIC_API_KEY="${token}"`, ].join('\n'); } else { return [ 'export ANTHROPIC_BASE_URL=http://localhost:8080', `export ANTHROPIC_API_KEY="${token}"`, ].join('\n'); } } catch (error) { logger_1.logger.error('导出环境变量失败', error); throw error; } } /** * 清除token缓存 */ clearCache() { this.tokenCache = null; this.lastTokenRead = 0; logger_1.logger.debug('Token缓存已清除'); } } exports.CodeWhispererAuth = CodeWhispererAuth; //# sourceMappingURL=auth.js.map