route-claudecode
Version:
Advanced routing and transformation system for Claude Code outputs to multiple AI providers
404 lines • 14.2 kB
JavaScript
;
/**
* Admin API Handler Module
*
* 处理管理相关的API请求(stats、provider管理、shutdown等)
* 按照细菌式编程原则:小巧、模块化、自包含
*/
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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AdminHandler = void 0;
exports.createAdminHandler = createAdminHandler;
class AdminHandler {
deps;
constructor(deps) {
this.deps = deps;
}
/**
* 处理 /api/stats 请求
*/
async handleApiStats(request, reply) {
try {
const stats = await this.collectSystemStats();
reply.send(stats);
}
catch (error) {
this.deps.logger.error('API stats collection failed', error);
reply.code(500).send({
error: {
type: 'internal_server_error',
message: 'Stats collection failed'
}
});
}
}
/**
* 处理 /stats 请求(简化版本)
*/
async handleStats(request, reply) {
try {
const basicStats = {
timestamp: new Date().toISOString(),
providers: this.deps.providers.size,
uptime: process.uptime(),
memory: process.memoryUsage(),
port: this.deps.config.server.port
};
reply.send(basicStats);
}
catch (error) {
this.deps.logger.error('Basic stats collection failed', error);
reply.code(500).send({
error: 'Stats unavailable'
});
}
}
/**
* 处理 /dual-stats 请求
*/
async handleDualStats(request, reply) {
try {
const [systemStats, providerStats] = await Promise.all([
this.collectSystemStats(),
this.collectProviderStats()
]);
reply.send({
system: systemStats,
providers: providerStats,
timestamp: new Date().toISOString()
});
}
catch (error) {
this.deps.logger.error('Dual stats collection failed', error);
reply.code(500).send({
error: 'Dual stats collection failed'
});
}
}
/**
* 处理 /api/failures 请求
*/
async handleFailures(request, reply) {
try {
const failures = this.deps.errorTracker?.getFailures() || [];
const recentFailures = failures.slice(-50); // 最近50个失败
reply.send({
total: failures.length,
recent: recentFailures.length,
failures: recentFailures,
timestamp: new Date().toISOString()
});
}
catch (error) {
this.deps.logger.error('Failures collection failed', error);
reply.code(500).send({
error: 'Failures data unavailable'
});
}
}
/**
* 处理 /api/providers/:providerId/disable 请求
*/
async handleProviderDisable(request, reply) {
try {
const { providerId } = request.params;
const provider = this.deps.providers.get(providerId);
if (!provider) {
return reply.code(404).send({
error: {
type: 'not_found',
message: `Provider '${providerId}' not found`
}
});
}
// 假设provider有disable方法
if ('disable' in provider && typeof provider.disable === 'function') {
await provider.disable();
}
this.deps.logger.info(`Provider ${providerId} disabled via API`);
reply.send({
message: `Provider ${providerId} disabled successfully`,
providerId,
timestamp: new Date().toISOString()
});
}
catch (error) {
this.deps.logger.error('Provider disable failed', error);
reply.code(500).send({
error: 'Provider disable operation failed'
});
}
}
/**
* 处理 /api/providers/:providerId/enable 请求
*/
async handleProviderEnable(request, reply) {
try {
const { providerId } = request.params;
const provider = this.deps.providers.get(providerId);
if (!provider) {
return reply.code(404).send({
error: {
type: 'not_found',
message: `Provider '${providerId}' not found`
}
});
}
// 假设provider有enable方法
if ('enable' in provider && typeof provider.enable === 'function') {
await provider.enable();
}
this.deps.logger.info(`Provider ${providerId} enabled via API`);
reply.send({
message: `Provider ${providerId} enabled successfully`,
providerId,
timestamp: new Date().toISOString()
});
}
catch (error) {
this.deps.logger.error('Provider enable failed', error);
reply.code(500).send({
error: 'Provider enable operation failed'
});
}
}
/**
* 处理 /api/providers/temporary-disabled 请求
*/
async handleTemporaryDisabled(request, reply) {
try {
const disabledProviders = [];
for (const [providerId, provider] of this.deps.providers) {
const isHealthy = await provider.isHealthy();
if (!isHealthy) {
disabledProviders.push({
providerId,
name: provider.name || providerId,
reason: 'Health check failed'
});
}
}
reply.send({
count: disabledProviders.length,
providers: disabledProviders,
timestamp: new Date().toISOString()
});
}
catch (error) {
this.deps.logger.error('Temporary disabled providers check failed', error);
reply.code(500).send({
error: 'Unable to check disabled providers'
});
}
}
/**
* 处理 /shutdown 请求
*/
async handleShutdown(request, reply) {
try {
this.deps.logger.info('Shutdown requested via API');
reply.send({
message: 'Server shutdown initiated',
timestamp: new Date().toISOString()
});
// 延迟关闭以确保响应发送完成
setTimeout(() => {
this.deps.logger.info('Shutting down server...');
process.exit(0);
}, 1000);
}
catch (error) {
this.deps.logger.error('Shutdown request failed', error);
reply.code(500).send({
error: 'Shutdown operation failed'
});
}
}
/**
* 处理 /v1/messages/count_tokens 请求
*/
async handleCountTokens(request, reply) {
try {
const body = request.body;
if (!body || !body.messages) {
return reply.code(400).send({
error: {
type: 'invalid_request_error',
message: 'Missing required field: messages'
}
});
}
// 使用tokenizer计算tokens
const { calculateTokenCount } = await Promise.resolve().then(() => __importStar(require('@/utils/tokenizer')));
const inputTokens = calculateTokenCount(body.messages);
reply.send({
input_tokens: inputTokens
});
}
catch (error) {
this.deps.logger.error('Token count calculation failed', error);
reply.code(500).send({
error: {
type: 'internal_server_error',
message: 'Failed to count tokens'
}
});
}
}
/**
* 处理 /api/error-diagnostics 请求
*/
async handleErrorDiagnostics(request, reply) {
try {
const diagnostics = {
timestamp: new Date().toISOString(),
errors: {
total: this.deps.errorTracker?.getErrorCount() || 0,
byProvider: this.deps.errorTracker?.getErrorsByProvider() || {},
recent: this.deps.errorTracker?.getRecentErrors(10) || []
},
system: {
uptime: process.uptime(),
memory: process.memoryUsage(),
port: this.deps.config.server.port
},
providers: await this.collectProviderDiagnostics()
};
reply.send(diagnostics);
}
catch (error) {
this.deps.logger.error('Error diagnostics collection failed', error);
reply.code(500).send({
error: 'Diagnostics collection failed'
});
}
}
/**
* 收集系统统计信息
*/
async collectSystemStats() {
return {
timestamp: new Date().toISOString(),
system: {
uptime: process.uptime(),
memory: process.memoryUsage(),
port: this.deps.config.server.port,
nodeVersion: process.version
},
providers: {
total: this.deps.providers.size,
list: Array.from(this.deps.providers.keys())
},
errors: this.deps.errorTracker?.getStats() || {},
requests: this.deps.requestTracker?.getStats() || {}
};
}
/**
* 收集Provider统计信息
*/
async collectProviderStats() {
const providerStats = {};
for (const [providerId, provider] of this.deps.providers) {
try {
const isHealthy = await provider.isHealthy();
providerStats[providerId] = {
name: provider.name || providerId,
healthy: isHealthy,
type: this.getProviderType(providerId)
};
}
catch (error) {
providerStats[providerId] = {
name: provider.name || providerId,
healthy: false,
error: error instanceof Error ? error.message : 'Unknown error',
type: this.getProviderType(providerId)
};
}
}
return providerStats;
}
/**
* 收集Provider诊断信息
*/
async collectProviderDiagnostics() {
const diagnostics = {};
for (const [providerId, provider] of this.deps.providers) {
try {
const isHealthy = await provider.isHealthy();
diagnostics[providerId] = {
name: provider.name || providerId,
healthy: isHealthy,
type: this.getProviderType(providerId),
lastCheck: new Date().toISOString()
};
// 如果provider有额外的诊断信息
if ('getDiagnostics' in provider && typeof provider.getDiagnostics === 'function') {
diagnostics[providerId].details = await provider.getDiagnostics();
}
}
catch (error) {
diagnostics[providerId] = {
name: provider.name || providerId,
healthy: false,
error: error instanceof Error ? error.message : 'Unknown error',
type: this.getProviderType(providerId),
lastCheck: new Date().toISOString()
};
}
}
return diagnostics;
}
/**
* 获取Provider类型
*/
getProviderType(providerId) {
if (providerId.includes('anthropic'))
return 'anthropic';
if (providerId.includes('openai') || providerId.includes('modelscope') || providerId.includes('lmstudio'))
return 'openai';
if (providerId.includes('gemini') || providerId.includes('google'))
return 'gemini';
return 'codewhisperer';
}
}
exports.AdminHandler = AdminHandler;
/**
* 创建Admin Handler实例的工厂函数
*/
function createAdminHandler(deps) {
return new AdminHandler(deps);
}
//# sourceMappingURL=admin-handler.js.map