import { db, schema } from 'officerdb'; import type { TaskInfo } from '@@/api/chat-types'; type ChatMessage = | { role: 'user'; text: string } | { role: 'assistant'; text: string } | { role: 'tool'; toolName: string; toolInput: Record; toolUseId: string; output?: string; isError?: boolean; } | { role: 'result'; costUsd: number; durationMs: number; numTurns: number; isError: boolean } | { role: 'error'; text: string }; type TaskLog = { userId: number; taskName: string; taskDirName: string; entryName: string; entryType: 'file' | 'directory'; provider: string; model: string; startedAt: Date; messages: ChatMessage[]; }; type LogEntry = { userId: number; log: TaskLog; }; const activeLogs = new Map(); let logCounter = 0; export function createTaskLog(userId: number, taskInfo: TaskInfo, provider: string, model: string): string { const logId = `log_${Date.now()}_${++logCounter}`; const log: TaskLog = { userId, taskName: taskInfo.taskName, taskDirName: taskInfo.taskDirName, entryName: taskInfo.entryName, entryType: taskInfo.entryType, provider, model, startedAt: new Date(), messages: [], }; activeLogs.set(logId, { userId, log }); return logId; } export function appendToLog(logId: string, message: ChatMessage) { const entry = activeLogs.get(logId); if (!entry) return; // For tool results, update the existing tool message instead of appending if (message.role === 'tool' && message.output !== undefined) { const existing = entry.log.messages.find((m) => m.role === 'tool' && m.toolUseId === message.toolUseId); if (existing && existing.role === 'tool') { existing.output = message.output; existing.isError = message.isError; return; } } entry.log.messages.push(message); } export async function finalizeLog(logId: string) { const entry = activeLogs.get(logId); if (!entry) return; const { log } = entry; const lastMessage = log.messages[log.messages.length - 1]; const isError = lastMessage?.role === 'result' ? lastMessage.isError : lastMessage?.role === 'error'; try { await db.insert(schema.taskLogs).values({ userId: log.userId, taskName: log.taskName, taskDirName: log.taskDirName, entryName: log.entryName, entryType: log.entryType, provider: log.provider, model: log.model, isError: !!isError, messages: log.messages, startedAt: log.startedAt, completedAt: new Date(), }); } catch (err) { console.error('[task-logger] Failed to write log:', err); } activeLogs.delete(logId); }