Files
platform/src/servers/api/task-logger.ts
T

102 lines
2.6 KiB
TypeScript

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<string, unknown>;
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<string, LogEntry>();
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);
}