route-claudecode
Version:
Advanced routing and transformation system for Claude Code outputs to multiple AI providers
278 lines • 10.2 kB
JavaScript
;
/**
* 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