Files
chat/tests/test_threads_state.py
2026-04-26 20:05:09 -04:00

182 lines
5.7 KiB
Python

from __future__ import annotations
from chat.db.connection import open_db
from chat.db.migrate import apply_migrations
from chat.eventlog.log import append_and_apply, append_event
from chat.eventlog.projector import project
import chat.state.entities # registers handlers
import chat.state.world # registers handlers
import chat.state.threads # registers handlers
from chat.state.threads import get_thread, list_open_threads
def _bot_payload(bot_id: str, name: str) -> dict:
return {
"id": bot_id,
"name": name,
"persona": "thoughtful, observant",
"voice_samples": [],
"traits": [],
"backstory": "",
"initial_relationship_to_you": "coworker",
"kickoff_prose": "",
}
def _chat_payload(chat_id: str = "chat_bot_a") -> dict:
return {
"id": chat_id,
"host_bot_id": "bot_a",
"guest_bot_id": "bot_b",
"initial_time": "2026-04-26T20:00:00+00:00",
"narrative_anchor": "Day 1 evening",
"weather": "clear",
}
def test_thread_opened_creates_row(tmp_path):
db = tmp_path / "t.db"
apply_migrations(db)
with open_db(db) as conn:
append_event(conn, kind="bot_authored", payload=_bot_payload("bot_a", "BotA"))
append_event(conn, kind="chat_created", payload=_chat_payload())
append_event(
conn,
kind="thread_opened",
payload={
"thread_id": "thr_abc",
"chat_id": "chat_bot_a",
"title": "Maya's job hunt",
"summary": "Maya is looking for a new job",
},
)
project(conn)
t = get_thread(conn, "thr_abc")
assert t is not None
assert t["thread_id"] == "thr_abc"
assert t["chat_id"] == "chat_bot_a"
assert t["title"] == "Maya's job hunt"
assert t["summary"] == "Maya is looking for a new job"
assert t["status"] == "open"
assert t["closed_at"] is None
assert t["last_referenced_scene_id"] is None
def test_thread_updated_changes_summary_and_last_referenced(tmp_path):
db = tmp_path / "t.db"
apply_migrations(db)
with open_db(db) as conn:
append_event(conn, kind="bot_authored", payload=_bot_payload("bot_a", "BotA"))
append_event(conn, kind="chat_created", payload=_chat_payload())
append_event(
conn,
kind="thread_opened",
payload={
"thread_id": "thr_abc",
"chat_id": "chat_bot_a",
"title": "Maya's job hunt",
"summary": "Maya is looking for a new job",
},
)
append_event(
conn,
kind="thread_updated",
payload={
"thread_id": "thr_abc",
"summary": "Maya landed an interview at a startup",
"last_referenced_scene_id": 42,
},
)
project(conn)
t = get_thread(conn, "thr_abc")
assert t is not None
assert t["summary"] == "Maya landed an interview at a startup"
assert t["last_referenced_scene_id"] == 42
assert t["status"] == "open"
def test_thread_closed_terminal(tmp_path):
db = tmp_path / "t.db"
apply_migrations(db)
with open_db(db) as conn:
append_event(conn, kind="bot_authored", payload=_bot_payload("bot_a", "BotA"))
append_event(conn, kind="chat_created", payload=_chat_payload())
append_event(
conn,
kind="thread_opened",
payload={
"thread_id": "thr_abc",
"chat_id": "chat_bot_a",
"title": "Maya's job hunt",
"summary": "Maya is looking for a new job",
},
)
append_event(
conn,
kind="thread_closed",
payload={
"thread_id": "thr_abc",
"closed_at": "2026-04-26T21:00:00+00:00",
},
)
project(conn)
t = get_thread(conn, "thr_abc")
assert t is not None
assert t["status"] == "closed"
assert t["closed_at"] == "2026-04-26T21:00:00+00:00"
# Subsequent updates to a closed thread are no-ops.
append_and_apply(
conn,
kind="thread_updated",
payload={
"thread_id": "thr_abc",
"summary": "should not be applied",
},
)
t2 = get_thread(conn, "thr_abc")
assert t2 is not None
assert t2["summary"] == "Maya is looking for a new job"
assert t2["status"] == "closed"
def test_list_open_threads_filters_to_open_only(tmp_path):
db = tmp_path / "t.db"
apply_migrations(db)
with open_db(db) as conn:
append_event(conn, kind="bot_authored", payload=_bot_payload("bot_a", "BotA"))
append_event(conn, kind="chat_created", payload=_chat_payload())
for tid, title in [
("thr_1", "Arc 1"),
("thr_2", "Arc 2"),
("thr_3", "Arc 3"),
]:
append_event(
conn,
kind="thread_opened",
payload={
"thread_id": tid,
"chat_id": "chat_bot_a",
"title": title,
"summary": "",
},
)
append_event(
conn,
kind="thread_closed",
payload={
"thread_id": "thr_3",
"closed_at": "2026-04-26T21:00:00+00:00",
},
)
project(conn)
open_threads = list_open_threads(conn, "chat_bot_a")
assert len(open_threads) == 2
ids = {t["thread_id"] for t in open_threads}
assert ids == {"thr_1", "thr_2"}