route-claudecode
Version:
Advanced routing and transformation system for Claude Code outputs to multiple AI providers
252 lines • 8.2 kB
JavaScript
;
/**
* Finish Reason Debug Logger
* 专门记录finish reason和stop reason的调试信息
* 按端口号分组管理日志文件
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDebugLogDir = getDebugLogDir;
exports.logFinishReasonDebug = logFinishReasonDebug;
exports.logStopReasonDebug = logStopReasonDebug;
exports.getDebugLogDirLegacy = getDebugLogDirLegacy;
exports.logToolCallCompletion = logToolCallCompletion;
exports.logApiError = logApiError;
exports.logPollingRetry = logPollingRetry;
exports.cleanupDebugLogs = cleanupDebugLogs;
exports.readDebugLogs = readDebugLogs;
const fs_1 = require("fs");
const path_1 = require("path");
const os_1 = require("os");
/**
* 获取调试日志目录路径 - 按端口号分组
* @param port 端口号,默认为 3456
*/
function getDebugLogDir(port) {
return (0, path_1.join)((0, os_1.homedir)(), '.route-claude-code', 'logs', `port-${port}`);
}
/**
* 确保调试日志目录存在 - 按端口号创建
* @param port 端口号,默认为 3456
*/
function ensureDebugLogDir(port) {
const debugLogDir = getDebugLogDir(port);
if (!(0, fs_1.existsSync)(debugLogDir)) {
(0, fs_1.mkdirSync)(debugLogDir, { recursive: true });
}
}
/**
* 记录finish reason调试信息
* @param requestId 请求ID
* @param finishReason 完成原因
* @param provider 提供商名称
* @param model 模型名称
* @param port 端口号,默认为 3456
* @param additionalData 额外数据
*/
function logFinishReasonDebug(requestId, finishReason, provider, model, port, additionalData) {
try {
ensureDebugLogDir(port);
const logEntry = {
timestamp: new Date().toISOString(),
requestId,
finishReason,
provider,
model,
port,
...(additionalData || {})
};
const debugLogDir = getDebugLogDir(port);
const logFilePath = (0, path_1.join)(debugLogDir, 'finish-reason-debug.log');
const logLine = JSON.stringify(logEntry) + '\n';
(0, fs_1.appendFileSync)(logFilePath, logLine);
}
catch (error) {
console.error('Failed to write finish reason debug log:', error);
}
}
/**
* 记录stop reason调试信息
* @param requestId 请求ID
* @param stopReason 停止原因
* @param provider 提供商名称
* @param model 模型名称
* @param port 端口号,默认为 3456
* @param additionalData 额外数据
*/
function logStopReasonDebug(requestId, stopReason, provider, model, port, additionalData) {
try {
ensureDebugLogDir(port);
const logEntry = {
timestamp: new Date().toISOString(),
requestId,
stopReason,
provider,
model,
port,
...(additionalData || {})
};
const debugLogDir = getDebugLogDir(port);
const logFilePath = (0, path_1.join)(debugLogDir, 'stop-reason-debug.log');
const logLine = JSON.stringify(logEntry) + '\n';
(0, fs_1.appendFileSync)(logFilePath, logLine);
}
catch (error) {
console.error('Failed to write stop reason debug log:', error);
}
}
/**
* 获取调试日志目录路径 (已废弃,请使用带端口参数的版本)
* @deprecated 请使用 getDebugLogDir(port)
*/
function getDebugLogDirLegacy() {
// 🔧 修复硬编码:需要明确指定端口
throw new Error('Port must be explicitly specified for getDefaultFinishReasonDir() - no hardcoded defaults allowed');
}
/**
* 记录工具调用完成状态
* @param requestId 请求ID
* @param toolCallId 工具调用ID
* @param status 状态
* @param port 端口号,默认为 3456
* @param result 结果
*/
function logToolCallCompletion(requestId, toolCallId, status, port, result) {
try {
ensureDebugLogDir(port);
const logEntry = {
timestamp: new Date().toISOString(),
requestId,
toolCallId,
status,
port,
result
};
const debugLogDir = getDebugLogDir(port);
const logFilePath = (0, path_1.join)(debugLogDir, 'tool-call-completion.log');
const logLine = JSON.stringify(logEntry) + '\n';
(0, fs_1.appendFileSync)(logFilePath, logLine);
}
catch (error) {
console.error('Failed to write tool call completion log:', error);
}
}
/**
* 记录API错误信息
* @param requestId 请求ID
* @param provider 提供商名称
* @param error 错误信息
* @param port 端口号,默认为 3456
* @param retryCount 重试次数
*/
function logApiError(requestId, provider, error, port, retryCount = 0) {
try {
ensureDebugLogDir(port);
const logEntry = {
timestamp: new Date().toISOString(),
requestId,
provider,
port,
error: error instanceof Error ? {
name: error.name,
message: error.message,
stack: error.stack
} : error,
retryCount
};
const debugLogDir = getDebugLogDir(port);
const logFilePath = (0, path_1.join)(debugLogDir, 'api-errors.log');
const logLine = JSON.stringify(logEntry) + '\n';
(0, fs_1.appendFileSync)(logFilePath, logLine);
}
catch (error) {
console.error('Failed to write API error log:', error);
}
}
/**
* 记录轮询重试信息
* @param requestId 请求ID
* @param provider 提供商名称
* @param attempt 重试次数
* @param reason 重试原因
* @param port 端口号,默认为 3456
*/
function logPollingRetry(requestId, provider, attempt, reason, port) {
try {
ensureDebugLogDir(port);
const logEntry = {
timestamp: new Date().toISOString(),
requestId,
provider,
port,
attempt,
reason
};
const debugLogDir = getDebugLogDir(port);
const logFilePath = (0, path_1.join)(debugLogDir, 'polling-retries.log');
const logLine = JSON.stringify(logEntry) + '\n';
(0, fs_1.appendFileSync)(logFilePath, logLine);
}
catch (error) {
console.error('Failed to write polling retry log:', error);
}
}
/**
* 清理旧的调试日志文件
* @param port 端口号,默认为 3456
* @param maxAge 最大保留时间,默认为7天
*/
function cleanupDebugLogs(port, maxAge = 7 * 24 * 60 * 60 * 1000) {
try {
const debugLogDir = getDebugLogDir(port);
if (!(0, fs_1.existsSync)(debugLogDir)) {
return;
}
const now = Date.now();
const files = (0, fs_1.readdirSync)(debugLogDir);
for (const file of files) {
const filePath = (0, path_1.join)(debugLogDir, file);
const stats = (0, fs_1.statSync)(filePath);
if (now - stats.mtime.getTime() > maxAge) {
(0, fs_1.unlinkSync)(filePath);
}
}
}
catch (error) {
console.error('Failed to cleanup debug logs:', error);
}
}
/**
* 读取调试日志文件
* @param logType 日志类型
* @param port 端口号,默认为 3456
* @param limit 读取条数限制
*/
function readDebugLogs(logType = 'finish-reason', port, limit) {
try {
ensureDebugLogDir(port);
const debugLogDir = getDebugLogDir(port);
const logFilePath = (0, path_1.join)(debugLogDir, `${logType}-debug.log`);
if (!(0, fs_1.existsSync)(logFilePath)) {
return [];
}
const content = (0, fs_1.readFileSync)(logFilePath, 'utf-8');
const lines = content.trim().split('\n').filter(line => line.length > 0);
const logs = lines.map((line) => {
try {
return JSON.parse(line);
}
catch {
return null;
}
}).filter((log) => log !== null);
if (limit && limit > 0) {
return logs.slice(-limit);
}
return logs;
}
catch (error) {
console.error('Failed to read debug logs:', error);
return [];
}
}
//# sourceMappingURL=finish-reason-debug.js.map