route-claudecode
Version:
Advanced routing and transformation system for Claude Code outputs to multiple AI providers
193 lines • 7.52 kB
JavaScript
;
/**
* 增强版Max Tokens错误处理器
* 集成智能处理模块,提供滚动截断和压缩等高级功能
* Project Owner: Jason Zhang
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnhancedMaxTokensErrorHandler = void 0;
const logger_1 = require("./logger");
const max_tokens_error_handling_module_1 = require("./max-tokens-error-handling-module");
class EnhancedMaxTokensErrorHandler {
handlingModule;
options;
constructor(options = {}) {
this.options = {
enableAutoRetry: true,
maxRetryAttempts: 2,
...options
};
this.handlingModule = new max_tokens_error_handling_module_1.MaxTokensErrorHandlingModule(options.handlingModulePath);
}
/**
* 检查finish_reason是否表示达到了token限制
*/
static isMaxTokensReached(finishReason) {
const maxTokensReasons = [
'max_tokens', // OpenAI格式
'length', // OpenAI length limit
'max_tokens', // Anthropic格式
];
return maxTokensReasons.includes(finishReason?.toLowerCase());
}
/**
* 检查Anthropic格式的stop_reason是否表示达到了token限制
*/
static isMaxTokensStopReason(stopReason) {
const maxTokensStopReasons = [
'max_tokens', // Anthropic max tokens
];
return maxTokensStopReasons.includes(stopReason?.toLowerCase());
}
/**
* 智能处理max tokens错误 - 主入口
* @param response API响应对象
* @param provider 提供商名称
* @param model 模型名称
* @param requestId 请求ID
* @param originalRequest 原始请求(用于智能处理)
* @returns 处理后的请求或抛出错误
*/
async handleMaxTokensResponse(response, provider, model, requestId, originalRequest) {
// 检查是否达到token限制
const isMaxTokensReached = this.detectMaxTokensCondition(response);
if (!isMaxTokensReached) {
return { shouldRetry: false };
}
logger_1.logger.warn('🚨 [MAX-TOKENS] Token limit reached', {
provider,
model,
requestId,
finishReason: this.extractFinishReason(response),
autoRetryEnabled: this.options.enableAutoRetry
});
// 如果启用自动处理且有原始请求
if (this.options.enableAutoRetry && originalRequest) {
try {
const truncationResult = await this.handlingModule.handleMaxTokensError(originalRequest, { response, provider, model }, requestId);
if (truncationResult.success) {
logger_1.logger.info('🔧 [MAX-TOKENS] Auto-truncation successful', {
originalTokens: truncationResult.originalTokens,
reducedTokens: truncationResult.reducedTokens,
reductionPercent: Math.round((1 - truncationResult.reducedTokens / truncationResult.originalTokens) * 100),
strategy: truncationResult.strategy,
requestId
});
return {
shouldRetry: true,
truncatedRequest: truncationResult.truncatedRequest
};
}
}
catch (error) {
logger_1.logger.error('🚨 [MAX-TOKENS] Auto-handling failed', error, requestId);
}
}
// 创建增强的错误对象
const enhancedError = this.createEnhancedMaxTokensError(this.extractFinishReason(response), provider, model, requestId, response.usage, originalRequest ? true : false);
return {
shouldRetry: false,
error: enhancedError
};
}
/**
* 检测max tokens条件
*/
detectMaxTokensCondition(response) {
// 检查OpenAI格式的finish_reason
if (response.choices?.[0]?.finish_reason) {
return EnhancedMaxTokensErrorHandler.isMaxTokensReached(response.choices[0].finish_reason);
}
// 检查Anthropic格式的stop_reason
if (response.stop_reason) {
return EnhancedMaxTokensErrorHandler.isMaxTokensStopReason(response.stop_reason);
}
// 检查unified格式
if (response.finishReason) {
return EnhancedMaxTokensErrorHandler.isMaxTokensReached(response.finishReason);
}
return false;
}
/**
* 提取finish reason
*/
extractFinishReason(response) {
if (response.choices?.[0]?.finish_reason) {
return response.choices[0].finish_reason;
}
if (response.stop_reason) {
return response.stop_reason;
}
if (response.finishReason) {
return response.finishReason;
}
return 'unknown';
}
/**
* 创建增强版max tokens错误
*/
createEnhancedMaxTokensError(finishReason, provider, model, requestId, usage, autoRetryAvailable) {
const message = autoRetryAvailable
? `Request exceeded maximum token limit. Auto-retry with intelligent truncation is available.`
: `Request exceeded maximum token limit. Please reduce input length or increase max_tokens parameter.`;
const error = new Error(message);
error.status = 429; // 使用429表示可以重试
error.code = 'MAX_TOKENS_EXCEEDED';
error.details = {
finishReason,
provider,
model,
requestId,
usage,
autoRetryAvailable
};
return error;
}
/**
* 兼容性方法 - 检查响应并抛出错误(向后兼容)
*/
static checkAndThrowMaxTokensError(response, provider, model, requestId) {
const handler = new EnhancedMaxTokensErrorHandler({ enableAutoRetry: false });
if (handler.detectMaxTokensCondition(response)) {
throw handler.createEnhancedMaxTokensError(handler.extractFinishReason(response), provider, model, requestId, response.usage, false);
}
}
/**
* 格式化错误响应
*/
static formatErrorResponse(error) {
return {
error: {
type: 'max_tokens_exceeded',
message: error.message,
code: error.code,
details: {
finish_reason: error.details.finishReason,
provider: error.details.provider,
model: error.details.model,
request_id: error.details.requestId,
usage: error.details.usage,
auto_retry_available: error.details.autoRetryAvailable,
suggestion: error.details.autoRetryAvailable
? 'Request can be automatically retried with intelligent truncation'
: 'Reduce input length or increase max_tokens parameter'
}
}
};
}
/**
* 获取处理模块配置
*/
getHandlingConfig() {
return this.handlingModule.getConfig();
}
/**
* 更新处理模块配置
*/
updateHandlingConfig(updates) {
this.handlingModule.updateConfig(updates);
}
}
exports.EnhancedMaxTokensErrorHandler = EnhancedMaxTokensErrorHandler;
exports.default = EnhancedMaxTokensErrorHandler;
//# sourceMappingURL=enhanced-max-tokens-error-handler.js.map