Fixed RPG
This commit is contained in:
+48
-5
@@ -2,7 +2,14 @@ from fastapi import APIRouter, File, Form, HTTPException, UploadFile
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
from services.character_card import list_characters, get_character, import_card_file, update_character, update_appearance_tags
|
||||
from services.character_card import (
|
||||
list_characters,
|
||||
get_character,
|
||||
import_card_file,
|
||||
preview_card_file,
|
||||
update_character,
|
||||
update_appearance_tags,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/characters", tags=["characters"])
|
||||
|
||||
@@ -17,6 +24,7 @@ class CardPatch(BaseModel):
|
||||
appearance_tags: Optional[str] = None
|
||||
lora_name: Optional[str] = None
|
||||
lora_weight: Optional[float] = None
|
||||
alternate_greetings_json: Optional[str] = None
|
||||
|
||||
|
||||
@router.get("/")
|
||||
@@ -32,6 +40,15 @@ async def get_one(card_id: str):
|
||||
return card
|
||||
|
||||
|
||||
@router.post("/preview")
|
||||
async def preview_card(file: UploadFile = File(...)):
|
||||
content = await file.read()
|
||||
try:
|
||||
return await preview_card_file(content, file.filename or "card.json")
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
|
||||
@router.patch("/{card_id}")
|
||||
async def patch_card(card_id: str, body: CardPatch):
|
||||
card = await get_character(card_id)
|
||||
@@ -39,20 +56,26 @@ async def patch_card(card_id: str, body: CardPatch):
|
||||
raise HTTPException(status_code=404, detail="Карточка не найдена")
|
||||
fields = {k: v for k, v in body.model_dump().items() if v is not None}
|
||||
await update_character(card_id, fields)
|
||||
# sync appearance_tags and lora to persona
|
||||
from services.personas import update_persona_appearance
|
||||
if "appearance_tags" in fields:
|
||||
await update_persona_appearance(f"card_{card_id}", fields["appearance_tags"])
|
||||
if {"lora_name", "lora_weight"} & fields.keys():
|
||||
from services.personas import update_persona_lora
|
||||
await update_persona_lora(f"card_{card_id}", fields.get("lora_name"), fields.get("lora_weight"))
|
||||
# rebuild system prompt if character fields changed
|
||||
char_fields = {"name", "description", "personality", "scenario", "first_mes", "mes_example"}
|
||||
if char_fields & fields.keys():
|
||||
updated = await get_character(card_id)
|
||||
from services.character_card import build_system_prompt
|
||||
from services.personas import update_persona_prompt
|
||||
await update_persona_prompt(f"card_{card_id}", build_system_prompt(updated))
|
||||
if "first_mes" in fields or "alternate_greetings_json" in fields:
|
||||
from services.personas import patch_persona
|
||||
sync = {}
|
||||
if "first_mes" in fields:
|
||||
sync["first_mes"] = fields["first_mes"]
|
||||
if "alternate_greetings_json" in fields:
|
||||
sync["alternate_greetings_json"] = fields["alternate_greetings_json"]
|
||||
await patch_persona(f"card_{card_id}", sync)
|
||||
return await get_character(card_id)
|
||||
|
||||
|
||||
@@ -67,7 +90,6 @@ async def upload_avatar(card_id: str, file: UploadFile = File(...)):
|
||||
from services.character_card import _save_avatar_bytes
|
||||
rel = _save_avatar_bytes(content, f"card_{card_id}")
|
||||
await update_character(card_id, {"avatar_path": rel})
|
||||
# sync persona
|
||||
from services.personas import patch_persona
|
||||
await patch_persona(f"card_{card_id}", {"avatar_path": rel})
|
||||
return {"avatar_path": f"/static/{rel}"}
|
||||
@@ -78,14 +100,35 @@ async def import_card(
|
||||
file: UploadFile = File(...),
|
||||
lora_name: str = Form(""),
|
||||
lora_weight: float = Form(0.8),
|
||||
card_id: str = Form(""),
|
||||
name: str = Form(""),
|
||||
description: str = Form(""),
|
||||
personality: str = Form(""),
|
||||
scenario: str = Form(""),
|
||||
first_mes: str = Form(""),
|
||||
mes_example: str = Form(""),
|
||||
appearance_tags: str = Form(""),
|
||||
alternate_greetings_json: str = Form("[]"),
|
||||
):
|
||||
content = await file.read()
|
||||
overrides = {
|
||||
"name": name or None,
|
||||
"description": description or None,
|
||||
"personality": personality or None,
|
||||
"scenario": scenario or None,
|
||||
"first_mes": first_mes or None,
|
||||
"mes_example": mes_example or None,
|
||||
"appearance_tags": appearance_tags or None,
|
||||
"alternate_greetings_json": alternate_greetings_json or "[]",
|
||||
}
|
||||
try:
|
||||
card = await import_card_file(
|
||||
content,
|
||||
file.filename or "card.json",
|
||||
lora_name=lora_name,
|
||||
lora_weight=lora_weight,
|
||||
overrides=overrides,
|
||||
card_id=card_id.strip() or None,
|
||||
)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
@@ -94,6 +137,7 @@ async def import_card(
|
||||
"card_id": card["card_id"],
|
||||
"persona_id": f"card_{card['card_id']}",
|
||||
"name": card["name"],
|
||||
"alternate_greetings": card.get("alternate_greetings", []),
|
||||
}
|
||||
|
||||
|
||||
@@ -104,4 +148,3 @@ async def remove_card(card_id: str):
|
||||
if not await delete_persona(f"card_{card_id}"):
|
||||
raise HTTPException(status_code=404, detail="Карточка не найдена")
|
||||
return {"status": "deleted", "card_id": card_id}
|
||||
|
||||
|
||||
+91
-113
@@ -1,4 +1,5 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
|
||||
@@ -26,6 +27,8 @@ from services.memory import (
|
||||
update_session_affinity,
|
||||
update_session_genre,
|
||||
update_session_rpg_settings,
|
||||
update_session_outfit,
|
||||
update_session_plot_arc,
|
||||
upsert_quest,
|
||||
get_quests,
|
||||
add_action_resolution,
|
||||
@@ -35,84 +38,57 @@ from services.memory import (
|
||||
delete_message,
|
||||
)
|
||||
from services.personas import get_persona
|
||||
from services.sd_prompt import (
|
||||
generate_sd_prompt,
|
||||
strip_image_prompt_tag,
|
||||
extract_image_prompt_tag,
|
||||
)
|
||||
from services.sd_prompt import generate_sd_prompt, strip_image_prompt_tag, extract_image_prompt_tag
|
||||
from services.lorebook import get_lorebook_context
|
||||
from services.character_card import get_character
|
||||
from services import sdbackend as sd_service
|
||||
from services.rpg_facts import extract_facts, merge_facts, facts_to_prompt
|
||||
from services.rpg_plot import generate_plot_arc, should_advance_arc, pop_matching_beats
|
||||
from services.rpg_plot import generate_plot_arc, should_advance_arc, pop_matching_beats, advance_phase
|
||||
from services.rpg_narrator import narrator_pre, narrator_post
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/chat", tags=["chat"])
|
||||
|
||||
DEFAULT_PROMPT = "Ты — полезный AI ассистент. Отвечай чётко и по делу."
|
||||
SD_AUTO_GENERATE = os.getenv("SD_AUTO_GENERATE", "false").lower() in ("1", "true", "yes")
|
||||
|
||||
def affinity_prompt_block(affinity: int) -> str:
|
||||
if affinity >= 10:
|
||||
tone = "very warm, trusting, affectionate"
|
||||
elif affinity >= 5:
|
||||
tone = "friendly and open"
|
||||
elif affinity >= 1:
|
||||
tone = "slightly positive"
|
||||
elif affinity <= -5:
|
||||
tone = "hostile or deeply distrustful"
|
||||
elif affinity <= -1:
|
||||
tone = "cold and wary"
|
||||
else:
|
||||
tone = "neutral"
|
||||
return (
|
||||
f"\n\n--- Relationship ---\n"
|
||||
f"Affinity toward player: {affinity} ({tone}). "
|
||||
f"Reflect this in your attitude and word choice.\n---"
|
||||
)
|
||||
|
||||
|
||||
DEFAULT_RPG_SETTINGS = {
|
||||
"dice": True,
|
||||
"narrator": True,
|
||||
"quests": True,
|
||||
"affinity": True,
|
||||
"choices": True,
|
||||
}
|
||||
DEFAULT_RPG_SETTINGS = {"dice": True, "narrator": True, "quests": True, "affinity": True, "choices": True}
|
||||
|
||||
|
||||
def get_rpg_settings(session: dict) -> dict:
|
||||
try:
|
||||
s = json.loads(session.get("rpg_settings_json") or "{}")
|
||||
return {**DEFAULT_RPG_SETTINGS, **s}
|
||||
return {**DEFAULT_RPG_SETTINGS, **json.loads(session.get("rpg_settings_json") or "{}")}
|
||||
except Exception:
|
||||
return DEFAULT_RPG_SETTINGS
|
||||
|
||||
|
||||
def affinity_prompt_block(affinity: int) -> str:
|
||||
if affinity >= 10: tone = "very warm, trusting, affectionate"
|
||||
elif affinity >= 5: tone = "friendly and open"
|
||||
elif affinity >= 1: tone = "slightly positive"
|
||||
elif affinity <= -5: tone = "hostile or deeply distrustful"
|
||||
elif affinity <= -1: tone = "cold and wary"
|
||||
else: tone = "neutral"
|
||||
return f"\n\n--- Relationship ---\nAffinity toward player: {affinity} ({tone}). Reflect this in your attitude and word choice.\n---"
|
||||
|
||||
|
||||
async def get_system_prompt(persona_id: str, history: list, user_message: str = "") -> str:
|
||||
persona = await get_persona(persona_id)
|
||||
if not persona:
|
||||
return DEFAULT_PROMPT
|
||||
|
||||
prompt = persona["prompt"]
|
||||
|
||||
recent = [m for m in history if m["role"] in ("user", "assistant")][-5:]
|
||||
context = recent + [{"role": "user", "content": user_message}]
|
||||
if persona.get("lorebook_json"):
|
||||
recent = [m for m in history if m["role"] in ("user", "assistant")][-5:]
|
||||
context = recent + [{"role": "user", "content": user_message}]
|
||||
lore = get_lorebook_context(persona.get("lorebook_json", "[]"), context)
|
||||
if lore:
|
||||
prompt = prompt + "\n\n" + lore
|
||||
|
||||
prompt += "\n\n" + lore
|
||||
if persona_id.startswith("card_"):
|
||||
card_id = persona_id[5:]
|
||||
card = await get_character(card_id)
|
||||
card = await get_character(persona_id[5:])
|
||||
if card:
|
||||
recent = [m for m in history if m["role"] in ("user", "assistant")][-5:]
|
||||
context = recent + [{"role": "user", "content": user_message}]
|
||||
lore = get_lorebook_context(card.get("lorebook_json", "[]"), context)
|
||||
if lore:
|
||||
prompt = prompt + "\n\n" + lore
|
||||
|
||||
prompt += "\n\n" + lore
|
||||
return prompt
|
||||
|
||||
|
||||
@@ -126,12 +102,18 @@ async def get_system_blob(session_id: str):
|
||||
history = await get_history(session_id)
|
||||
system_msg = next((m for m in history if m.get("role") == "system"), None)
|
||||
session = await get_session(session_id)
|
||||
quests = await get_quests(session_id)
|
||||
return {
|
||||
"system_prompt": system_msg.get("content") if system_msg else "",
|
||||
"facts_json": session.get("facts_json") if session else "[]",
|
||||
"status_quo": session.get("status_quo") if session else "",
|
||||
"facts_json": session.get("facts_json") if session else "[]",
|
||||
"plot_arc_json": session.get("plot_arc_json") if session else "{}",
|
||||
"outfit_json": session.get("outfit_json") if session else "[]",
|
||||
"affinity": session.get("affinity", 0) if session else 0,
|
||||
"genre": session.get("genre", "") if session else "",
|
||||
"rpg_settings_json": session.get("rpg_settings_json") if session else "{}",
|
||||
"rpg_enabled": bool(session.get("rpg_enabled")) if session else False,
|
||||
"quests": quests,
|
||||
}
|
||||
|
||||
|
||||
@@ -147,15 +129,19 @@ async def init_chat(request: ChatRequest):
|
||||
await add_message(request.session_id, "system", system_prompt)
|
||||
|
||||
first_mes = None
|
||||
persona = await get_persona(persona_id)
|
||||
if persona and persona.get("first_mes"):
|
||||
first_mes = persona["first_mes"]
|
||||
if request.first_mes_override and request.first_mes_override.strip():
|
||||
first_mes = request.first_mes_override.strip()
|
||||
await add_message(request.session_id, "assistant", first_mes)
|
||||
elif persona_id.startswith("card_"):
|
||||
card = await get_character(persona_id[5:])
|
||||
if card and card.get("first_mes"):
|
||||
first_mes = card["first_mes"]
|
||||
else:
|
||||
persona = await get_persona(persona_id)
|
||||
if persona and persona.get("first_mes"):
|
||||
first_mes = persona["first_mes"]
|
||||
await add_message(request.session_id, "assistant", first_mes)
|
||||
elif persona_id.startswith("card_"):
|
||||
card = await get_character(persona_id[5:])
|
||||
if card and card.get("first_mes"):
|
||||
first_mes = card["first_mes"]
|
||||
await add_message(request.session_id, "assistant", first_mes)
|
||||
|
||||
return {"first_mes": first_mes}
|
||||
|
||||
@@ -196,9 +182,9 @@ async def rpg_bootstrap(req: RpgBootstrapRequest):
|
||||
|
||||
# Seed quests from beats
|
||||
for beat in arc.get("beats", []):
|
||||
injection = beat.get("injection", "").strip()
|
||||
if injection:
|
||||
await upsert_quest(req.session_id, injection[:120])
|
||||
title = (beat.get("title") or beat.get("injection", "")).strip()
|
||||
if title:
|
||||
await upsert_quest(req.session_id, title[:120])
|
||||
|
||||
quests = await get_quests(req.session_id)
|
||||
return {"plot_arc": arc, "quests": quests}
|
||||
@@ -339,11 +325,21 @@ async def chat_stream(request: ChatRequest):
|
||||
|
||||
async def generate():
|
||||
nonlocal arc
|
||||
async for chunk in stream_message(
|
||||
[{"role": m["role"], "content": m["content"]} for m in messages]
|
||||
):
|
||||
full_reply.append(chunk)
|
||||
yield f"data: {json.dumps({'chunk': chunk})}\n\n"
|
||||
|
||||
# Send narrator BEFORE streaming so it appears above the reply
|
||||
if narrator_msg:
|
||||
yield f"data: {json.dumps({'narrator': narrator_msg})}\n\n"
|
||||
|
||||
try:
|
||||
async for chunk in stream_message(
|
||||
[{"role": m["role"], "content": m["content"]} for m in messages]
|
||||
):
|
||||
full_reply.append(chunk)
|
||||
yield f"data: {json.dumps({'chunk': chunk})}\n\n"
|
||||
except Exception as e:
|
||||
logger.error("stream_message failed: %s", e)
|
||||
yield f"data: {json.dumps({'error': str(e)})}\n\n"
|
||||
return
|
||||
|
||||
complete = "".join(full_reply)
|
||||
display_text = strip_image_prompt_tag(complete)
|
||||
@@ -351,17 +347,14 @@ async def chat_stream(request: ChatRequest):
|
||||
hist_with_reply = await get_history(request.session_id) + [
|
||||
{"role": "assistant", "content": display_text}
|
||||
]
|
||||
sd_result = await generate_sd_prompt(hist_with_reply, persona_id)
|
||||
prompt_str = sd_result[0] if sd_result else None
|
||||
if not prompt_str:
|
||||
prompt_str = extract_image_prompt_tag(complete)
|
||||
|
||||
await add_message(
|
||||
request.session_id,
|
||||
"assistant",
|
||||
display_text or complete,
|
||||
image_prompt=prompt_str,
|
||||
sd_result = await generate_sd_prompt(
|
||||
hist_with_reply, persona_id,
|
||||
outfit_json=session.get("outfit_json", "[]") if session else "[]"
|
||||
)
|
||||
prompt_str = (sd_result[0] if sd_result and sd_result[0] else None) or extract_image_prompt_tag(complete)
|
||||
|
||||
if (display_text or complete).strip():
|
||||
await add_message(request.session_id, "assistant", display_text or complete, image_prompt=prompt_str)
|
||||
|
||||
choices = []
|
||||
debug_blocks = []
|
||||
@@ -370,38 +363,36 @@ async def chat_stream(request: ChatRequest):
|
||||
if session and session.get("rpg_enabled"):
|
||||
if not arc:
|
||||
persona = await get_persona(persona_id) or {}
|
||||
genre = (session.get("genre") or "adventure")
|
||||
arc = await generate_plot_arc(
|
||||
persona.get("name", persona_id),
|
||||
persona.get("description", ""),
|
||||
persona.get("scenario", ""),
|
||||
persona.get("first_mes", ""),
|
||||
facts_block=facts_to_prompt(session.get("facts_json", "[]")),
|
||||
genre=genre,
|
||||
genre=session.get("genre") or "adventure",
|
||||
)
|
||||
if arc:
|
||||
from services.memory import update_session_plot_arc
|
||||
await update_session_plot_arc(request.session_id, json.dumps(arc, ensure_ascii=False))
|
||||
debug_blocks.append({"type": "plot_arc", "text": json.dumps(arc, ensure_ascii=False, indent=2)})
|
||||
if rpg_settings.get("quests", True):
|
||||
for beat in arc.get("beats", []):
|
||||
inj = beat.get("injection", "").strip()
|
||||
if inj:
|
||||
await upsert_quest(request.session_id, inj[:120])
|
||||
t = (beat.get("title") or beat.get("injection", "")).strip()
|
||||
if t:
|
||||
await upsert_quest(request.session_id, t[:120])
|
||||
|
||||
trig = should_advance_arc(request.message)
|
||||
if trig and arc:
|
||||
arc, beats = pop_matching_beats(arc, trig, max_beats=1)
|
||||
if beats:
|
||||
from services.memory import update_session_plot_arc
|
||||
await update_session_plot_arc(request.session_id, json.dumps(arc, ensure_ascii=False))
|
||||
inj = beats[0].get("injection", "")
|
||||
if inj:
|
||||
debug_blocks.append({"type": "narrator_injection", "text": inj})
|
||||
if rpg_settings.get("choices", True):
|
||||
beat_choices = beats[0].get("choices") or []
|
||||
if beat_choices:
|
||||
choices = choices + beat_choices
|
||||
choices += beats[0].get("choices") or []
|
||||
if advance_phase(arc):
|
||||
await update_session_plot_arc(request.session_id, json.dumps(arc, ensure_ascii=False))
|
||||
debug_blocks.append({"type": "phase_advance", "text": arc["phase"]})
|
||||
|
||||
ctx = [m for m in (await get_history(request.session_id)) if m["role"] in ("user", "assistant")][-10:]
|
||||
new_facts = await extract_facts(ctx)
|
||||
@@ -409,55 +400,53 @@ async def chat_stream(request: ChatRequest):
|
||||
merged = merge_facts(session.get("facts_json", "[]"), new_facts)
|
||||
await update_session_facts(request.session_id, merged)
|
||||
session["facts_json"] = merged
|
||||
debug_blocks.append({"type": "facts", "text": facts_to_prompt(merged)})
|
||||
|
||||
persona = await get_persona(persona_id) or {}
|
||||
ctx_txt = "\n".join(
|
||||
f"{m['role']}: {m['content']}" for m in ctx[-8:]
|
||||
if m.get("role") in ("user", "assistant")
|
||||
)
|
||||
ctx_txt = "\n".join(f"{m['role']}: {m['content']}" for m in ctx[-8:] if m.get("role") in ("user", "assistant"))
|
||||
post = await narrator_post(
|
||||
persona.get("name", persona_id),
|
||||
ctx_txt,
|
||||
json.dumps(arc, ensure_ascii=False) if arc else "",
|
||||
facts_to_prompt(session.get("facts_json", "[]")),
|
||||
)
|
||||
|
||||
sq = (post.get("status_quo_update") or "").strip()
|
||||
if sq:
|
||||
await update_session_status_quo(request.session_id, sq)
|
||||
session["status_quo"] = sq
|
||||
debug_blocks.append({"type": "status_quo", "text": f"--- Status quo ---\n{sq}\n---"})
|
||||
debug_blocks.append({"type": "status_quo", "text": sq})
|
||||
|
||||
if rpg_settings.get("choices", True):
|
||||
extra_choices = post.get("choices") or []
|
||||
if extra_choices:
|
||||
choices = choices + extra_choices
|
||||
choices += post.get("choices") or []
|
||||
|
||||
if rpg_settings.get("affinity", True):
|
||||
delta = int(post.get("affinity_delta") or 0)
|
||||
if delta:
|
||||
await update_session_affinity(request.session_id, delta)
|
||||
|
||||
outfit_update = post.get("outfit_update")
|
||||
if isinstance(outfit_update, list) and outfit_update:
|
||||
outfit_str = json.dumps(outfit_update, ensure_ascii=False)
|
||||
await update_session_outfit(request.session_id, outfit_str)
|
||||
session["outfit_json"] = outfit_str
|
||||
|
||||
if rpg_settings.get("quests", True):
|
||||
for qu in (post.get("quest_updates") or []):
|
||||
title = (qu.get("title") or "").strip()
|
||||
status = qu.get("status", "active")
|
||||
if title:
|
||||
await upsert_quest(request.session_id, title[:120], status)
|
||||
t = (qu.get("title") or "").strip()
|
||||
if t:
|
||||
await upsert_quest(request.session_id, t[:120], qu.get("status", "active"))
|
||||
quests_updated = await get_quests(request.session_id)
|
||||
|
||||
count = await get_message_count(request.session_id)
|
||||
if count == 2 and not request.skip_user_add:
|
||||
persona = await get_persona(persona_id) or {}
|
||||
persona_name = persona.get("name", persona_id)
|
||||
preview = request.message[:40] + ("…" if len(request.message) > 40 else "")
|
||||
current = (session or {}).get("title") or "Новый чат"
|
||||
if current in ("", "Новый чат"):
|
||||
await update_session_title(request.session_id, f"{persona_name} — {preview}")
|
||||
if (session or {}).get("title", "Новый чат") in ("", "Новый чат"):
|
||||
await update_session_title(request.session_id, f"{persona.get('name', persona_id)} — {preview}")
|
||||
|
||||
image_path = None
|
||||
image_error = None
|
||||
if prompt_str and SD_AUTO_GENERATE:
|
||||
yield f"data: {json.dumps({'image_generating': True, 'image_prompt': prompt_str})}\n\n"
|
||||
rel, err = await sd_service.generate_from_full_prompt(prompt_str)
|
||||
if rel:
|
||||
image_path = rel
|
||||
@@ -467,21 +456,10 @@ async def chat_stream(request: ChatRequest):
|
||||
else:
|
||||
image_error = err
|
||||
|
||||
# Fetch current affinity for UI
|
||||
updated_session = await get_session(request.session_id)
|
||||
affinity = updated_session.get("affinity", 0) if updated_session else 0
|
||||
|
||||
yield f"data: {json.dumps({
|
||||
'done': True,
|
||||
'image_prompt': prompt_str,
|
||||
'image_path': f'/static/{image_path}' if image_path else None,
|
||||
'image_error': image_error,
|
||||
'choices': choices,
|
||||
'debug': debug_blocks,
|
||||
'narrator': narrator_msg,
|
||||
'affinity': affinity,
|
||||
'quests': quests_updated,
|
||||
})}\n\n"
|
||||
yield f"data: {json.dumps({'done': True, 'image_prompt': prompt_str, 'image_path': f'/static/{image_path}' if image_path else None, 'image_error': image_error, 'choices': choices, 'debug': debug_blocks, 'affinity': affinity, 'quests': quests_updated})}\n\n"
|
||||
|
||||
return StreamingResponse(
|
||||
generate(),
|
||||
|
||||
+4
-11
@@ -1,11 +1,11 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from services.memory import (
|
||||
get_all_sessions,
|
||||
get_session,
|
||||
get_or_create_session,
|
||||
delete_session,
|
||||
update_session_title,
|
||||
update_session_persona,
|
||||
get_history,
|
||||
get_message_count,
|
||||
update_session_rpg,
|
||||
update_session_facts,
|
||||
@@ -16,7 +16,6 @@ from services.memory import (
|
||||
get_quests,
|
||||
get_last_message_preview,
|
||||
fork_session,
|
||||
get_session,
|
||||
)
|
||||
from models.schemas import ForkSessionRequest
|
||||
|
||||
@@ -30,11 +29,7 @@ async def list_sessions():
|
||||
for s in sessions:
|
||||
count = await get_message_count(s["session_id"])
|
||||
preview = await get_last_message_preview(s["session_id"])
|
||||
result.append({
|
||||
**s,
|
||||
"message_count": count,
|
||||
"last_message_preview": preview,
|
||||
})
|
||||
result.append({**s, "message_count": count, "last_message_preview": preview})
|
||||
return result
|
||||
|
||||
|
||||
@@ -44,9 +39,8 @@ async def list_quests(session_id: str):
|
||||
|
||||
|
||||
@router.get("/{session_id}")
|
||||
async def get_session(session_id: str):
|
||||
sessions = await get_all_sessions()
|
||||
s = next((x for x in sessions if x["session_id"] == session_id), None)
|
||||
async def get_session_route(session_id: str):
|
||||
s = await get_session(session_id)
|
||||
if not s:
|
||||
raise HTTPException(status_code=404, detail="Сессия не найдена")
|
||||
return s
|
||||
@@ -86,4 +80,3 @@ async def fork_session_route(session_id: str, req: ForkSessionRequest):
|
||||
async def remove_session(session_id: str):
|
||||
await delete_session(session_id)
|
||||
return {"status": "deleted", "session_id": session_id}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user