feat(db): trim stored hook payloads; price the session list like a session
Analytics parity, phase 1 (data hygiene), from the analytics-parity session. events.data is now stored through the SQL function trim_event_data(?) (server/lib/event-payload.js, registered in server/db.js) on every event INSERT and in the duplicate guard: Edit/MultiEdit/NotebookEdit/Write drop the whole-file mirrors (originalFile, oldString/newString, Write content), Read drops file.content/base64, and any string in tool_input/tool_response over 8 KB keeps a 6 KB head + 2 KB tail. structuredPatch and every field outside those two stay whole; _trimmed names what was dropped. The full text stays in the transcript and its snapshot. Rows stored before this are trimmed once in the background (sweepEventPayloads, 200 rows per write transaction, user_version 4). No VACUUM, no row pruned. The session list now prices every token column /api/pricing/cost/:id does (speed, geo, tier, the 1h cache write, server-tool fees) through one tokensForSessions helper, so a row's cost equals the session's own.
This commit is contained in:
+26
-35
@@ -121,6 +121,30 @@ async function readFirstLine(filePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Every priced column, as `stmts.getTokensBySession` reads one session — so a
|
||||
// list row's cost equals the session's own `/api/pricing/cost/:id` (speed, geo,
|
||||
// tier, the 1h cache write and server-tool fees included). ≤ 900 ids per call.
|
||||
function tokensForSessions(ids) {
|
||||
const out = {};
|
||||
if (ids.length === 0) return out;
|
||||
const rows = db
|
||||
.prepare(
|
||||
`SELECT session_id, model, speed, inference_geo, service_tier,
|
||||
input_tokens + baseline_input as input_tokens,
|
||||
output_tokens + baseline_output as output_tokens,
|
||||
cache_read_tokens + baseline_cache_read as cache_read_tokens,
|
||||
cache_write_tokens + baseline_cache_write as cache_write_tokens,
|
||||
cache_write_1h_tokens + baseline_cache_write_1h as cache_write_1h_tokens,
|
||||
web_search_requests + baseline_web_search as web_search_requests,
|
||||
web_fetch_requests + baseline_web_fetch as web_fetch_requests,
|
||||
code_execution_requests + baseline_code_execution as code_execution_requests
|
||||
FROM token_usage WHERE session_id IN (${ids.map(() => "?").join(",")})`
|
||||
)
|
||||
.all(...ids);
|
||||
for (const t of rows) (out[t.session_id] ||= []).push(t);
|
||||
return out;
|
||||
}
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const limit = Math.min(parseInt(req.query.limit) || 50, 10000);
|
||||
const offset = parseInt(req.query.offset) || 0;
|
||||
@@ -201,23 +225,7 @@ router.get("/", (req, res) => {
|
||||
for (let i = 0; i < allRows.length; i += 900) {
|
||||
const chunk = allRows.slice(i, i + 900);
|
||||
const ids = chunk.map((r) => r.id);
|
||||
const placeholders = ids.map(() => "?").join(",");
|
||||
const chunkTokens = db
|
||||
.prepare(
|
||||
`SELECT session_id, model,
|
||||
input_tokens + baseline_input as input_tokens,
|
||||
output_tokens + baseline_output as output_tokens,
|
||||
cache_read_tokens + baseline_cache_read as cache_read_tokens,
|
||||
cache_write_tokens + baseline_cache_write as cache_write_tokens
|
||||
FROM token_usage WHERE session_id IN (${placeholders})`
|
||||
)
|
||||
.all(...ids);
|
||||
|
||||
const tokensBySession = {};
|
||||
for (const t of chunkTokens) {
|
||||
if (!tokensBySession[t.session_id]) tokensBySession[t.session_id] = [];
|
||||
tokensBySession[t.session_id].push(t);
|
||||
}
|
||||
const tokensBySession = tokensForSessions(ids);
|
||||
|
||||
for (const row of chunk) {
|
||||
const sessionTokens = tokensBySession[row.id];
|
||||
@@ -250,25 +258,8 @@ router.get("/", (req, res) => {
|
||||
.all(...params, limit, offset);
|
||||
|
||||
if (rows.length > 0) {
|
||||
const ids = rows.map((r) => r.id);
|
||||
const placeholders = ids.map(() => "?").join(",");
|
||||
const allTokens = db
|
||||
.prepare(
|
||||
`SELECT session_id, model,
|
||||
input_tokens + baseline_input as input_tokens,
|
||||
output_tokens + baseline_output as output_tokens,
|
||||
cache_read_tokens + baseline_cache_read as cache_read_tokens,
|
||||
cache_write_tokens + baseline_cache_write as cache_write_tokens
|
||||
FROM token_usage WHERE session_id IN (${placeholders})`
|
||||
)
|
||||
.all(...ids);
|
||||
|
||||
const rules = stmts.listPricing.all();
|
||||
const tokensBySession = {};
|
||||
for (const t of allTokens) {
|
||||
if (!tokensBySession[t.session_id]) tokensBySession[t.session_id] = [];
|
||||
tokensBySession[t.session_id].push(t);
|
||||
}
|
||||
const tokensBySession = tokensForSessions(rows.map((r) => r.id));
|
||||
|
||||
for (const row of rows) {
|
||||
const sessionTokens = tokensBySession[row.id];
|
||||
|
||||
Reference in New Issue
Block a user