Fixed RPG
This commit is contained in:
+290
-1
@@ -36,6 +36,17 @@ async def get_all_sessions() -> list:
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
|
||||
async def get_session(session_id: str) -> dict | None:
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
db.row_factory = aiosqlite.Row
|
||||
async with db.execute(
|
||||
"SELECT * FROM sessions WHERE session_id = ?",
|
||||
(session_id,),
|
||||
) as cursor:
|
||||
row = await cursor.fetchone()
|
||||
return dict(row) if row else None
|
||||
|
||||
|
||||
async def update_session_title(session_id: str, title: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
@@ -47,16 +58,118 @@ async def update_session_title(session_id: str, title: str):
|
||||
|
||||
async def update_session_persona(session_id: str, persona_id: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
db.row_factory = aiosqlite.Row
|
||||
async with db.execute(
|
||||
"SELECT persona_id FROM sessions WHERE session_id = ?",
|
||||
(session_id,),
|
||||
) as cur:
|
||||
row = await cur.fetchone()
|
||||
prev = row["persona_id"] if row else None
|
||||
|
||||
await db.execute(
|
||||
"UPDATE sessions SET persona_id = ?, updated_at = CURRENT_TIMESTAMP WHERE session_id = ?",
|
||||
(persona_id, session_id),
|
||||
)
|
||||
|
||||
# If persona changed, reset RPG state bound to the persona/arc.
|
||||
if prev is not None and prev != persona_id:
|
||||
await db.execute(
|
||||
"""UPDATE sessions
|
||||
SET facts_json = '[]',
|
||||
global_plot = '',
|
||||
status_quo = '',
|
||||
plot_arc_json = '{}'
|
||||
WHERE session_id = ?""",
|
||||
(session_id,),
|
||||
)
|
||||
await db.execute(
|
||||
"DELETE FROM action_resolutions WHERE session_id = ?",
|
||||
(session_id,),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def update_session_rpg(session_id: str, rpg_enabled: bool):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE sessions SET rpg_enabled = ?, updated_at = CURRENT_TIMESTAMP WHERE session_id = ?",
|
||||
(1 if rpg_enabled else 0, session_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def update_session_facts(session_id: str, facts_json: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE sessions SET facts_json = ?, updated_at = CURRENT_TIMESTAMP WHERE session_id = ?",
|
||||
(facts_json, session_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def update_session_global_plot(session_id: str, global_plot: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE sessions SET global_plot = ?, updated_at = CURRENT_TIMESTAMP WHERE session_id = ?",
|
||||
(global_plot, session_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def update_session_status_quo(session_id: str, status_quo: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE sessions SET status_quo = ?, updated_at = CURRENT_TIMESTAMP WHERE session_id = ?",
|
||||
(status_quo, session_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def update_session_plot_arc(session_id: str, plot_arc_json: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE sessions SET plot_arc_json = ?, updated_at = CURRENT_TIMESTAMP WHERE session_id = ?",
|
||||
(plot_arc_json, session_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def add_action_resolution(
|
||||
session_id: str,
|
||||
intent_text: str,
|
||||
roll: int,
|
||||
outcome: str,
|
||||
resolution_text: str,
|
||||
message_id: int | None = None,
|
||||
):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"""INSERT INTO action_resolutions
|
||||
(session_id, message_id, intent_text, roll, outcome, resolution_text)
|
||||
VALUES (?, ?, ?, ?, ?, ?)""",
|
||||
(session_id, message_id, intent_text, roll, outcome, resolution_text),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def get_last_action_resolution(session_id: str) -> dict | None:
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
db.row_factory = aiosqlite.Row
|
||||
async with db.execute(
|
||||
"""SELECT * FROM action_resolutions
|
||||
WHERE session_id = ?
|
||||
ORDER BY id DESC LIMIT 1""",
|
||||
(session_id,),
|
||||
) as cur:
|
||||
row = await cur.fetchone()
|
||||
return dict(row) if row else None
|
||||
|
||||
|
||||
async def delete_session(session_id: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute("DELETE FROM messages WHERE session_id = ?", (session_id,))
|
||||
await db.execute("DELETE FROM rpg_quests WHERE session_id = ?", (session_id,))
|
||||
await db.execute("DELETE FROM action_resolutions WHERE session_id = ?", (session_id,))
|
||||
await db.execute("DELETE FROM sessions WHERE session_id = ?", (session_id,))
|
||||
await db.commit()
|
||||
|
||||
@@ -65,13 +178,14 @@ async def get_history(session_id: str) -> list:
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
db.row_factory = aiosqlite.Row
|
||||
async with db.execute(
|
||||
"""SELECT role, content, image_prompt, image_path
|
||||
"""SELECT id, role, content, image_prompt, image_path
|
||||
FROM messages WHERE session_id = ? ORDER BY id""",
|
||||
(session_id,),
|
||||
) as cursor:
|
||||
rows = await cursor.fetchall()
|
||||
return [
|
||||
{
|
||||
"id": r["id"],
|
||||
"role": r["role"],
|
||||
"content": r["content"],
|
||||
"image_prompt": r["image_prompt"],
|
||||
@@ -81,6 +195,114 @@ async def get_history(session_id: str) -> list:
|
||||
]
|
||||
|
||||
|
||||
async def get_message(message_id: int) -> dict | None:
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
db.row_factory = aiosqlite.Row
|
||||
async with db.execute(
|
||||
"SELECT id, session_id, role, content FROM messages WHERE id = ?",
|
||||
(message_id,),
|
||||
) as cursor:
|
||||
row = await cursor.fetchone()
|
||||
return dict(row) if row else None
|
||||
|
||||
|
||||
async def update_message_content(message_id: int, content: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE messages SET content = ? WHERE id = ?",
|
||||
(content, message_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def delete_messages_after(session_id: str, message_id: int):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"DELETE FROM messages WHERE session_id = ? AND id > ?",
|
||||
(session_id, message_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def delete_message(message_id: int):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute("DELETE FROM messages WHERE id = ?", (message_id,))
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def get_last_message_preview(session_id: str, max_len: int = 80) -> str:
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
db.row_factory = aiosqlite.Row
|
||||
async with db.execute(
|
||||
"""SELECT content, role FROM messages
|
||||
WHERE session_id = ? AND role IN ('user', 'assistant')
|
||||
ORDER BY id DESC LIMIT 1""",
|
||||
(session_id,),
|
||||
) as cursor:
|
||||
row = await cursor.fetchone()
|
||||
if not row:
|
||||
return ""
|
||||
prefix = "Вы: " if row["role"] == "user" else "AI: "
|
||||
text = (row["content"] or "").replace("\n", " ").strip()
|
||||
if len(text) > max_len:
|
||||
text = text[:max_len] + "…"
|
||||
return prefix + text
|
||||
|
||||
|
||||
async def fork_session(source_session_id: str, until_message_id: int) -> str | None:
|
||||
source = await get_session(source_session_id)
|
||||
if not source:
|
||||
return None
|
||||
|
||||
import uuid
|
||||
new_id = "sess_" + uuid.uuid4().hex[:8]
|
||||
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"""INSERT INTO sessions
|
||||
(session_id, persona_id, title, rpg_enabled, facts_json, global_plot,
|
||||
status_quo, plot_arc_json, genre, rpg_settings_json, affinity)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(
|
||||
new_id,
|
||||
source["persona_id"],
|
||||
(source.get("title") or "Новый чат") + " (ветка)",
|
||||
source.get("rpg_enabled", 0),
|
||||
source.get("facts_json", "[]"),
|
||||
source.get("global_plot", ""),
|
||||
source.get("status_quo", ""),
|
||||
source.get("plot_arc_json", "{}"),
|
||||
source.get("genre", "adventure"),
|
||||
source.get("rpg_settings_json", "{}"),
|
||||
source.get("affinity", 0),
|
||||
),
|
||||
)
|
||||
async with db.execute(
|
||||
"""SELECT role, content, image_prompt, image_path FROM messages
|
||||
WHERE session_id = ? AND id <= ? ORDER BY id""",
|
||||
(source_session_id, until_message_id),
|
||||
) as cur:
|
||||
rows = await cur.fetchall()
|
||||
for r in rows:
|
||||
await db.execute(
|
||||
"""INSERT INTO messages (session_id, role, content, image_prompt, image_path)
|
||||
VALUES (?, ?, ?, ?, ?)""",
|
||||
(new_id, r[0], r[1], r[2], r[3]),
|
||||
)
|
||||
async with db.execute(
|
||||
"SELECT title, status FROM rpg_quests WHERE session_id = ?",
|
||||
(source_session_id,),
|
||||
) as cur:
|
||||
quests = await cur.fetchall()
|
||||
for q in quests:
|
||||
await db.execute(
|
||||
"INSERT INTO rpg_quests (session_id, title, status) VALUES (?, ?, ?)",
|
||||
(new_id, q[0], q[1]),
|
||||
)
|
||||
await db.commit()
|
||||
return new_id
|
||||
|
||||
|
||||
async def add_message(
|
||||
session_id: str,
|
||||
role: str,
|
||||
@@ -131,6 +353,73 @@ async def clear_history(session_id: str):
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def update_session_affinity(session_id: str, delta: int):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE sessions SET affinity = affinity + ?, updated_at = CURRENT_TIMESTAMP WHERE session_id = ?",
|
||||
(delta, session_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def update_session_genre(session_id: str, genre: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE sessions SET genre = ?, updated_at = CURRENT_TIMESTAMP WHERE session_id = ?",
|
||||
(genre, session_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def update_session_rpg_settings(session_id: str, settings_json: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE sessions SET rpg_settings_json = ?, updated_at = CURRENT_TIMESTAMP WHERE session_id = ?",
|
||||
(settings_json, session_id),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def upsert_quest(session_id: str, title: str, status: str = "active"):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
async with db.execute(
|
||||
"SELECT id FROM rpg_quests WHERE session_id = ? AND title = ?",
|
||||
(session_id, title),
|
||||
) as cur:
|
||||
row = await cur.fetchone()
|
||||
if row:
|
||||
await db.execute(
|
||||
"UPDATE rpg_quests SET status = ? WHERE id = ?",
|
||||
(status, row[0]),
|
||||
)
|
||||
else:
|
||||
await db.execute(
|
||||
"INSERT INTO rpg_quests (session_id, title, status) VALUES (?, ?, ?)",
|
||||
(session_id, title, status),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def get_quests(session_id: str) -> list:
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
db.row_factory = aiosqlite.Row
|
||||
async with db.execute(
|
||||
"SELECT id, title, status FROM rpg_quests WHERE session_id = ? ORDER BY id",
|
||||
(session_id,),
|
||||
) as cur:
|
||||
rows = await cur.fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
|
||||
async def update_quest_status(session_id: str, title: str, status: str):
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
await db.execute(
|
||||
"UPDATE rpg_quests SET status = ? WHERE session_id = ? AND title = ?",
|
||||
(status, session_id, title),
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
|
||||
async def get_message_count(session_id: str) -> int:
|
||||
async with aiosqlite.connect(DB_PATH) as db:
|
||||
db.row_factory = aiosqlite.Row
|
||||
|
||||
Reference in New Issue
Block a user