feat(agent): persist per-session token and cost accounting
Adds the agent_sessions table (migration) and a session_store module that owns its lifecycle: - ensure_session: idempotently creates the session row on first chat. - record_turn: accumulates input/output/total tokens, cost and turn count after each completed turn, bumping updated_at. - get_session: user-scoped fetch so a tenant can only read its own session. Backed by SQLite via SQLx, matching the existing service style. Unit-tested against an in-memory database (idempotency, accumulation, user scoping).
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
-- Agent Workbench sessions: per-session token / cost accounting and metadata.
|
||||
--
|
||||
-- One row per agent conversation session. Token counts and cost accumulate
|
||||
-- across the turns of a session; `updated_at` advances on every `/api/agent/chat`
|
||||
-- round-trip. `user_id` is nullable so admin (global-token) sessions are allowed
|
||||
-- without a user row, but every session is still isolated by its own sandbox
|
||||
-- directory keyed on `id`.
|
||||
CREATE TABLE IF NOT EXISTS agent_sessions (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
user_id INTEGER,
|
||||
title TEXT,
|
||||
model TEXT NOT NULL DEFAULT '',
|
||||
permission_mode TEXT NOT NULL DEFAULT 'default',
|
||||
input_tokens INTEGER NOT NULL DEFAULT 0,
|
||||
output_tokens INTEGER NOT NULL DEFAULT 0,
|
||||
total_tokens INTEGER NOT NULL DEFAULT 0,
|
||||
cost_usd REAL NOT NULL DEFAULT 0,
|
||||
num_turns INTEGER NOT NULL DEFAULT 0,
|
||||
message_count INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS agent_sessions_user_id_idx
|
||||
ON agent_sessions (user_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS agent_sessions_updated_at_idx
|
||||
ON agent_sessions (updated_at);
|
||||
Reference in New Issue
Block a user