diff --git a/src/index.ts b/src/index.ts index 0b120aa..e2adb51 100644 --- a/src/index.ts +++ b/src/index.ts @@ -115,7 +115,7 @@ async function run(options: RunOptions = {}) { path: HOME_DIR, maxFiles: 3, interval: "1d", - compress: 'gzip', + compress: false, maxSize: "50M" }), } diff --git a/src/server.ts b/src/server.ts index 47a3663..7483913 100644 --- a/src/server.ts +++ b/src/server.ts @@ -65,16 +65,16 @@ export const createServer = (config: any): Server => { server.app.get("/ui", async (_, reply) => { return reply.redirect("/ui/"); }); - + // 版本检查端点 server.app.get("/api/update/check", async (req, reply) => { try { // 获取当前版本 const currentVersion = require("../package.json").version; const { hasUpdate, latestVersion, changelog } = await checkForUpdates(currentVersion); - - return { - hasUpdate, + + return { + hasUpdate, latestVersion: hasUpdate ? latestVersion : undefined, changelog: hasUpdate ? changelog : undefined }; @@ -83,7 +83,7 @@ export const createServer = (config: any): Server => { reply.status(500).send({ error: "Failed to check for updates" }); } }); - + // 执行更新端点 server.app.post("/api/update/perform", async (req, reply) => { try { @@ -93,10 +93,10 @@ export const createServer = (config: any): Server => { reply.status(403).send("Full access required to perform updates"); return; } - + // 执行更新逻辑 const result = await performUpdate(); - + return result; } catch (error) { console.error("Failed to perform update:", error); @@ -112,12 +112,12 @@ export const createServer = (config: any): Server => { if (existsSync(logDir)) { const files = readdirSync(logDir); - + for (const file of files) { if (file.endsWith('.log')) { const filePath = join(logDir, file); const stats = statSync(filePath); - + logFiles.push({ name: file, path: filePath, @@ -126,7 +126,7 @@ export const createServer = (config: any): Server => { }); } } - + // 按修改时间倒序排列 logFiles.sort((a, b) => new Date(b.lastModified).getTime() - new Date(a.lastModified).getTime()); } @@ -143,7 +143,7 @@ export const createServer = (config: any): Server => { try { const filePath = (req.query as any).file as string; let logFilePath: string; - + if (filePath) { // 如果指定了文件路径,使用指定的路径 logFilePath = filePath; @@ -157,7 +157,7 @@ export const createServer = (config: any): Server => { } const logContent = readFileSync(logFilePath, 'utf8'); - const logLines = logContent.split('\n').filter(line => line.trim()); + const logLines = logContent.split('\n').filter(line => line.trim()) return logLines; } catch (error) { @@ -171,7 +171,7 @@ export const createServer = (config: any): Server => { try { const filePath = (req.query as any).file as string; let logFilePath: string; - + if (filePath) { // 如果指定了文件路径,使用指定的路径 logFilePath = filePath; diff --git a/src/utils/codeCommand.ts b/src/utils/codeCommand.ts index 19017c1..46d6714 100644 --- a/src/utils/codeCommand.ts +++ b/src/utils/codeCommand.ts @@ -11,11 +11,15 @@ import {join} from "path"; export async function executeCodeCommand(args: string[] = []) { // Set environment variables const config = await readConfigFile(); + const port = config.PORT || 3456; const env: Record = { ...process.env, ANTHROPIC_AUTH_TOKEN: config?.APIKEY || "test", ANTHROPIC_API_KEY: '', - ANTHROPIC_BASE_URL: `http://127.0.0.1:${config.PORT || 3456}`, + ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}`, + NO_PROXY: `127.0.0.1`, + DISABLE_TELEMETRY: 'true', + DISABLE_COST_WARNINGS: 'true', API_TIMEOUT_MS: String(config.API_TIMEOUT_MS ?? 600000), // Default to 10 minutes if not set }; let settingsFlag: Record | undefined; diff --git a/ui/src/components/LogViewer.tsx b/ui/src/components/LogViewer.tsx index fc8bdac..5401964 100644 --- a/ui/src/components/LogViewer.tsx +++ b/ui/src/components/LogViewer.tsx @@ -85,19 +85,8 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { const groupedLogs = {}; logs.forEach((log, index) => { - let reqId = log.reqId; - - // 如果没有reqId,尝试从message字段中的JSON解析 - if (!reqId && log.message && log.message.startsWith('{')) { - try { - const messageObj = JSON.parse(log.message); - reqId = messageObj.reqId; - } catch (e) { - // 解析失败,忽略 - } - } - - reqId = reqId || 'no-req-id'; + log = JSON.parse(log); + let reqId = log.reqId || 'no-req-id'; if (!groupedLogs[reqId]) { groupedLogs[reqId] = []; @@ -107,7 +96,7 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { // 按时间戳排序每个组的日志 Object.keys(groupedLogs).forEach(reqId => { - groupedLogs[reqId].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()); + groupedLogs[reqId].sort((a, b) => a.time - b.time); }); // 提取model信息 @@ -116,11 +105,8 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { for (const log of logGroup) { try { // 尝试从message字段解析JSON - if (log.message && log.message.startsWith('{')) { - const messageObj = JSON.parse(log.message); - if (messageObj.body && messageObj.body.model) { - return messageObj.body.model; - } + if (log.type === 'request body' && log.data && log.data.model) { + return log.data.model; } } catch (e) { // 解析失败,继续尝试下一条日志 @@ -136,8 +122,8 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { requests: Object.keys(groupedLogs).map(reqId => ({ reqId, logCount: groupedLogs[reqId].length, - firstLog: groupedLogs[reqId][0]?.timestamp, - lastLog: groupedLogs[reqId][groupedLogs[reqId].length - 1]?.timestamp, + firstLog: groupedLogs[reqId][0]?.time, + lastLog: groupedLogs[reqId][groupedLogs[reqId].length - 1]?.time, model: extractModelInfo(reqId) })) }; @@ -179,7 +165,7 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { // 监听Worker消息 workerRef.current.onmessage = (event) => { const { type, data, error } = event.data; - + if (type === 'groupLogsResult') { setGroupedLogs(data); } else if (type === 'error') { @@ -260,7 +246,7 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { try { setIsLoading(true); const response = await api.getLogFiles(); - + if (response && Array.isArray(response)) { setLogFiles(response); setSelectedFile(null); @@ -283,32 +269,32 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { const loadLogs = async () => { if (!selectedFile) return; - + try { setIsLoading(true); setGroupedLogs(null); setSelectedReqId(null); - + // 始终加载原始日志数据 const response = await api.getLogs(selectedFile.path); - + if (response && Array.isArray(response)) { // 现在接口返回的是原始日志字符串数组,直接存储 setLogs(response); - + // 如果启用了分组,使用Web Worker进行聚合(需要转换为LogEntry格式供Worker使用) if (groupByReqId && workerRef.current) { - const workerLogs: LogEntry[] = response.map((logLine, index) => ({ - timestamp: new Date().toISOString(), - level: 'info', - message: logLine, - source: undefined, - reqId: undefined - })); - + // const workerLogs: LogEntry[] = response.map((logLine, index) => ({ + // timestamp: new Date().toISOString(), + // level: 'info', + // message: logLine, + // source: undefined, + // reqId: undefined + // })); + workerRef.current.postMessage({ type: 'groupLogsByReqId', - data: { logs: workerLogs } + data: { logs: response } }); } else { setGroupedLogs(null); @@ -332,7 +318,7 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { const clearLogs = async () => { if (!selectedFile) return; - + try { await api.clearLogs(selectedFile.path); setLogs([]); @@ -352,11 +338,11 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { setAutoRefresh(false); // Reset auto refresh when changing files }; - + const toggleGroupByReqId = () => { const newValue = !groupByReqId; setGroupByReqId(newValue); - + if (newValue && selectedFile && logs.length > 0) { // 启用聚合时,如果已有日志,则使用Worker进行聚合 if (workerRef.current) { @@ -376,7 +362,7 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { setSelectedReqId(reqId); }; - + const getDisplayLogs = () => { if (groupByReqId && groupedLogs) { if (selectedReqId && groupedLogs.groups[selectedReqId]) { @@ -403,7 +389,7 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { const downloadLogs = () => { if (!selectedFile || logs.length === 0) return; - + // 直接下载原始日志字符串,每行一个日志 const logText = logs.join('\n'); @@ -416,7 +402,7 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); - + if (showToast) { showToast(t('log_viewer.logs_downloaded'), 'success'); } @@ -512,10 +498,11 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { // 如果在分组模式且选中了具体请求,显示该请求的日志 if (groupByReqId && groupedLogs && selectedReqId && groupedLogs.groups[selectedReqId]) { const requestLogs = groupedLogs.groups[selectedReqId]; + console.log(requestLogs) // 提取原始JSON字符串并每行一个 - return requestLogs.map(log => log.message).join('\n'); + return requestLogs.map(log => JSON.stringify(log)).join('\n'); } - + // 其他情况,直接显示原始日志字符串数组,每行一个 return logs.join('\n'); }; @@ -527,20 +514,20 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) { return ( <> {(isVisible || open) && ( -
onOpenChange(false)} /> )} - -
)} - + {/* 面包屑导航 */}
- +
{isLoading ? (
@@ -646,7 +633,7 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) {

{t('log_viewer.request_groups')}

- {t('log_viewer.total_requests')}: {groupedLogs.summary.totalRequests} | + {t('log_viewer.total_requests')}: {groupedLogs.summary.totalRequests} | {t('log_viewer.total_logs')}: {groupedLogs.summary.totalLogs}

@@ -736,4 +723,4 @@ export function LogViewer({ open, onOpenChange, showToast }: LogViewerProps) {
); -} \ No newline at end of file +}