delete Task Logs
A complete read path over a table nothing could write to. task-logger.ts exported createTaskLog, appendToLog and finalizeLog, and none of the three was called anywhere in the tree — so `task_logs` could never gain a row, and the screen was permanently empty for everyone. The read half was fully wired: mounted router, capability claim, dock icon, two routes and a page-title rule. That is why it looked alive. Gone, in the order it was reached: Screens/Dashboard/TaskLogs/ the screen App.tsx /task-logs and /task-logs/:id Dashboard/index.tsx the export Layout/Dock.tsx the 'Logs' icon, and ScrollText with it state/usePageTitle.ts the title rule api/task-logs/task-logs.ts the router, and its mount in hono.ts api/task-logger.ts 101 lines of orphaned writer officer_db/src/operations/ the directory officer_db/src/schema.ts the export line officer_db/src/types.ts TaskLogSelect / TaskLogInsert capabilities/registry.ts loses '/task-logs' from the `tasks` capability's `api` AND `routes`. The api half is not optional: assertCapabilityTotality check 2 refuses to boot on a capability claiming a prefix nothing mounts, so unmounting the router while leaving the claim would have stopped the server starting. db:push now creates 21 tables, down from 43 at the start of the evening. officer_db/src/operations was one of the two lopsided directories the schema/queries merge exposed. integrations/ is the remaining one, and it is legitimate — it spans server and user-data. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { desc, eq } from 'drizzle-orm';
|
||||
import { db, schema } from 'officerdb';
|
||||
import { createRouter } from '../../create-router';
|
||||
|
||||
export const taskLogsRouter = createRouter();
|
||||
|
||||
// GET / — list all logs (metadata only, no messages)
|
||||
taskLogsRouter.get('/', async (ctx) => {
|
||||
const userId = ctx.get('user').id;
|
||||
|
||||
const logs = await db
|
||||
.select({
|
||||
id: schema.taskLogs.id,
|
||||
taskName: schema.taskLogs.taskName,
|
||||
taskDirName: schema.taskLogs.taskDirName,
|
||||
entryName: schema.taskLogs.entryName,
|
||||
entryType: schema.taskLogs.entryType,
|
||||
provider: schema.taskLogs.provider,
|
||||
model: schema.taskLogs.model,
|
||||
isError: schema.taskLogs.isError,
|
||||
startedAt: schema.taskLogs.startedAt,
|
||||
completedAt: schema.taskLogs.completedAt,
|
||||
})
|
||||
.from(schema.taskLogs)
|
||||
.where(eq(schema.taskLogs.userId, userId))
|
||||
.orderBy(desc(schema.taskLogs.startedAt));
|
||||
|
||||
return ctx.json(logs);
|
||||
});
|
||||
|
||||
// GET /:id — return full log with messages
|
||||
taskLogsRouter.get('/:id', async (ctx) => {
|
||||
const userId = ctx.get('user').id;
|
||||
const id = Number(ctx.req.param('id'));
|
||||
|
||||
if (Number.isNaN(id)) {
|
||||
return ctx.text('Invalid id', 400);
|
||||
}
|
||||
|
||||
const [log] = await db.select().from(schema.taskLogs).where(eq(schema.taskLogs.id, id));
|
||||
|
||||
if (!log || log.userId !== userId) {
|
||||
return ctx.text('Not found', 404);
|
||||
}
|
||||
|
||||
return ctx.json(log);
|
||||
});
|
||||
Reference in New Issue
Block a user