124 lines
3.7 KiB
Python
124 lines
3.7 KiB
Python
from __future__ import annotations
|
|
from sqlite3 import Connection
|
|
|
|
from chat.eventlog.projector import on
|
|
from chat.eventlog.log import Event
|
|
|
|
|
|
@on("thread_opened")
|
|
def _apply_thread_opened(conn: Connection, e: Event) -> None:
|
|
p = e.payload
|
|
conn.execute(
|
|
"INSERT OR IGNORE INTO threads "
|
|
"(thread_id, chat_id, title, summary, status) "
|
|
"VALUES (?, ?, ?, ?, 'open')",
|
|
(
|
|
p["thread_id"],
|
|
p["chat_id"],
|
|
p["title"],
|
|
p.get("summary", ""),
|
|
),
|
|
)
|
|
|
|
|
|
@on("thread_updated")
|
|
def _apply_thread_updated(conn: Connection, e: Event) -> None:
|
|
p = e.payload
|
|
# Idempotent: closed threads ignore subsequent updates.
|
|
conn.execute(
|
|
"UPDATE threads SET summary = ?, last_referenced_scene_id = ?, "
|
|
"updated_at = datetime('now') "
|
|
"WHERE thread_id = ? AND status = 'open'",
|
|
(
|
|
p.get("summary", ""),
|
|
p.get("last_referenced_scene_id"),
|
|
p["thread_id"],
|
|
),
|
|
)
|
|
|
|
|
|
@on("thread_closed")
|
|
def _apply_thread_closed(conn: Connection, e: Event) -> None:
|
|
p = e.payload
|
|
conn.execute(
|
|
"UPDATE threads SET status = 'closed', closed_at = ?, "
|
|
"updated_at = datetime('now') "
|
|
"WHERE thread_id = ? AND status = 'open'",
|
|
(p.get("closed_at"), p["thread_id"]),
|
|
)
|
|
|
|
|
|
def get_thread(conn: Connection, thread_id: str) -> dict | None:
|
|
row = conn.execute(
|
|
"SELECT thread_id, chat_id, title, summary, status, "
|
|
"opened_at, closed_at, last_referenced_scene_id, "
|
|
"created_at, updated_at "
|
|
"FROM threads WHERE thread_id = ?",
|
|
(thread_id,),
|
|
).fetchone()
|
|
if not row:
|
|
return None
|
|
return {
|
|
"thread_id": row[0],
|
|
"chat_id": row[1],
|
|
"title": row[2],
|
|
"summary": row[3],
|
|
"status": row[4],
|
|
"opened_at": row[5],
|
|
"closed_at": row[6],
|
|
"last_referenced_scene_id": row[7],
|
|
"created_at": row[8],
|
|
"updated_at": row[9],
|
|
}
|
|
|
|
|
|
def list_open_threads(conn: Connection, chat_id: str) -> list[dict]:
|
|
rows = conn.execute(
|
|
"SELECT thread_id, chat_id, title, summary, status, "
|
|
"opened_at, closed_at, last_referenced_scene_id, "
|
|
"created_at, updated_at "
|
|
"FROM threads WHERE chat_id = ? AND status = 'open' "
|
|
"ORDER BY id ASC",
|
|
(chat_id,),
|
|
).fetchall()
|
|
return [
|
|
{
|
|
"thread_id": r[0], "chat_id": r[1], "title": r[2],
|
|
"summary": r[3], "status": r[4],
|
|
"opened_at": r[5], "closed_at": r[6],
|
|
"last_referenced_scene_id": r[7],
|
|
"created_at": r[8], "updated_at": r[9],
|
|
}
|
|
for r in rows
|
|
]
|
|
|
|
|
|
def list_threads(conn: Connection, chat_id: str, status: str | None = None) -> list[dict]:
|
|
if status is None:
|
|
rows = conn.execute(
|
|
"SELECT thread_id, chat_id, title, summary, status, "
|
|
"opened_at, closed_at, last_referenced_scene_id, "
|
|
"created_at, updated_at "
|
|
"FROM threads WHERE chat_id = ? ORDER BY id ASC",
|
|
(chat_id,),
|
|
).fetchall()
|
|
else:
|
|
rows = conn.execute(
|
|
"SELECT thread_id, chat_id, title, summary, status, "
|
|
"opened_at, closed_at, last_referenced_scene_id, "
|
|
"created_at, updated_at "
|
|
"FROM threads WHERE chat_id = ? AND status = ? "
|
|
"ORDER BY id ASC",
|
|
(chat_id, status),
|
|
).fetchall()
|
|
return [
|
|
{
|
|
"thread_id": r[0], "chat_id": r[1], "title": r[2],
|
|
"summary": r[3], "status": r[4],
|
|
"opened_at": r[5], "closed_at": r[6],
|
|
"last_referenced_scene_id": r[7],
|
|
"created_at": r[8], "updated_at": r[9],
|
|
}
|
|
for r in rows
|
|
]
|