// Generated, do not edit. sha256:9505c124878c8b5af0571c1b4757d6fc332a4d6d342508d9c8ff717ce279c7db import * as db from '../db.js'; import { CONFIG, ENUMS } from '../../shared/config.js'; import { assertEnum, nowIso } from './_shared.js'; import { emitChange } from './_events.js'; import { limitText } from '../ai/limits.js'; function uitRij(r) { if (!r) return r; let velden = null; if (r.fieldsShared != null) { try { velden = JSON.parse(r.fieldsShared); } catch { velden = []; } if (!Array.isArray(velden)) velden = []; } return { ...r, fieldsShared: velden }; } export async function logAiToolCall(entry) { assertEnum('outcome', ENUMS.AI_CALL_OUTCOME, entry.outcome); if (!entry.sessionId) throw new Error('An audit entry without a session cannot be traced.'); if (!entry.tool) throw new Error('An audit entry without a tool name cannot be traced.'); const momenten = entry.messages == null ? [] : [...entry.messages]; for (const m of momenten) assertEnum('kind', ENUMS.AI_MESSAGE_KIND, m?.kind); const velden = entry.fieldsShared == null ? null : JSON.stringify([...entry.fieldsShared]); db.run(`INSERT INTO AiToolCall (sessionId, client, tool, arguments, fieldsShared, charactersOut, outcome, detail, occurredAt, serverVersion) VALUES (?,?,?,?,?,?,?,?,?,?)`, [entry.sessionId, entry.client ?? null, entry.tool, entry.arguments != null ? JSON.stringify(entry.arguments) : null, velden, entry.charactersOut ?? null, entry.outcome, entry.detail ?? null, entry.occurredAt ?? nowIso(), entry.serverVersion ?? null]); const id = db.lastId(); for (const m of momenten) { const { text } = limitText(String(m.text ?? ''), CONFIG.AI.LIMITS.MAX_LOG_CHARS); db.run(`INSERT INTO AiToolCallMessage (callId, kind, text, occurredAt) VALUES (?,?,?,?)`, [id, m.kind, text, m.occurredAt ?? nowIso()]); } await db.persist(); emitChange('ai-activity-changed'); return id; } export function countAiToolCallsSince(sinds) { const vanaf = Number.isInteger(sinds) && sinds >= 0 ? sinds : 0; const r = db.one(`SELECT COUNT(*) AS n, MAX(id) AS laatste FROM AiToolCall WHERE id > ?`, [vanaf]); const alles = db.one(`SELECT MAX(id) AS laatste FROM AiToolCall`); return { count: r ? r.n : 0, newestId: (alles && alles.laatste != null) ? alles.laatste : 0, }; } export function aiToolCallMessages(callId) { const n = Number(callId); if (!Number.isInteger(n) || n <= 0) return []; return db.all(`SELECT id, callId, kind, text, occurredAt FROM AiToolCallMessage WHERE callId = ? ORDER BY id`, [n]); } export function aiSessions(uren = 24) { const grens = new Date(Date.now() - Math.max(1, Number(uren) || 24) * 3600_000).toISOString(); return db.all( `SELECT sessionId, client, serverVersion, COUNT(*) AS calls, MIN(occurredAt) AS firstAt, MAX(occurredAt) AS lastAt FROM AiToolCall WHERE occurredAt >= ? GROUP BY sessionId, client, serverVersion ORDER BY lastAt DESC`, [grens]) .map(r => ({ ...r, zonderVersie: r.serverVersion == null })); } export function listAiToolCalls(limit = CONFIG.AI.AUDIT_PAGE_SIZE) { const n = Math.min(Math.max(Number(limit) || CONFIG.AI.AUDIT_PAGE_SIZE, 1), 1000); return db.all(`SELECT * FROM AiToolCall ORDER BY occurredAt DESC, id DESC LIMIT ?`, [n]).map(uitRij); } export function countAiToolCalls() { const totaal = db.one(`SELECT COUNT(*) AS n FROM AiToolCall`); const perUitkomst = db.all(`SELECT outcome, COUNT(*) AS n FROM AiToolCall GROUP BY outcome`); const uitkomsten = {}; for (const k of ENUMS.AI_CALL_OUTCOME) uitkomsten[k] = 0; for (const r of perUitkomst) uitkomsten[r.outcome] = r.n; return { total: totaal ? totaal.n : 0, byOutcome: uitkomsten }; } export function lastAiToolCallAt() { const r = db.one(`SELECT occurredAt FROM AiToolCall ORDER BY occurredAt DESC, id DESC LIMIT 1`); return r ? r.occurredAt : null; }