- globals.py: add collections.deque(maxlen=10) PROMPT_HISTORY with _prompt_id_counter
- globals.py: add legacy accessor functions _get_last_fallback_prompt() and _get_last_cat_interaction()
- bot.py: append to PROMPT_HISTORY instead of setting LAST_CAT_INTERACTION, remove 500-char truncation, add guild/channel/model fields
- image_handling.py: same pattern for Cat media responses
- llm.py: append fallback prompts to PROMPT_HISTORY with response filled after LLM reply
- routes/core.py: new GET /prompts and GET /prompts/{id} endpoints, legacy /prompt and /prompt/cat use accessor functions
167 lines
6.0 KiB
Python
167 lines
6.0 KiB
Python
"""Core routes: index, logs, prompts, status, conversation."""
|
|
|
|
from fastapi import APIRouter
|
|
from fastapi.responses import FileResponse, JSONResponse
|
|
import globals
|
|
from server_manager import server_manager
|
|
from utils.conversation_history import conversation_history
|
|
from utils.logger import get_logger
|
|
|
|
logger = get_logger('api')
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/")
|
|
def read_index():
|
|
return FileResponse("static/index.html")
|
|
|
|
|
|
@router.get("/logs")
|
|
def get_logs():
|
|
try:
|
|
# Read last 100 lines of the log file
|
|
with open("/app/bot.log", "r", encoding="utf-8") as f:
|
|
lines = f.readlines()
|
|
last_100 = lines[-100:] if len(lines) >= 100 else lines
|
|
return "".join(last_100)
|
|
except Exception as e:
|
|
return JSONResponse(status_code=500, content={"status": "error", "message": f"Error reading log file: {e}"})
|
|
|
|
|
|
@router.get("/prompt")
|
|
def get_last_prompt():
|
|
"""Legacy endpoint: returns the most recent fallback prompt (backward compat)."""
|
|
prompt_text = globals._get_last_fallback_prompt()
|
|
return {"prompt": prompt_text or "No prompt has been issued yet."}
|
|
|
|
|
|
@router.get("/prompt/cat")
|
|
def get_last_cat_prompt():
|
|
"""Legacy endpoint: returns the most recent Cat interaction (backward compat)."""
|
|
interaction = globals._get_last_cat_interaction()
|
|
if not interaction.get("full_prompt"):
|
|
return {"full_prompt": "No Cheshire Cat interaction has occurred yet.",
|
|
"response": "", "user": "", "mood": "", "timestamp": ""}
|
|
return interaction
|
|
|
|
|
|
@router.get("/prompts")
|
|
def get_prompt_history(source: str = None):
|
|
"""
|
|
Return the unified prompt history.
|
|
Optional query param ?source=cat or ?source=fallback to filter.
|
|
"""
|
|
history = list(globals.PROMPT_HISTORY)
|
|
if source and source in ("cat", "fallback"):
|
|
history = [e for e in history if e.get("source") == source]
|
|
return {"history": history}
|
|
|
|
|
|
@router.get("/prompts/{prompt_id}")
|
|
def get_prompt_by_id(prompt_id: int):
|
|
"""Return a single prompt history entry by ID."""
|
|
for entry in globals.PROMPT_HISTORY:
|
|
if entry.get("id") == prompt_id:
|
|
return entry
|
|
return JSONResponse(
|
|
status_code=404,
|
|
content={"status": "error", "message": f"Prompt #{prompt_id} not found"}
|
|
)
|
|
|
|
|
|
@router.get("/status")
|
|
def status():
|
|
# Get per-server mood summary
|
|
server_moods = {}
|
|
for guild_id in server_manager.servers:
|
|
mood_name, _ = server_manager.get_server_mood(guild_id)
|
|
server_moods[str(guild_id)] = mood_name
|
|
|
|
# Return evil mood when in evil mode
|
|
current_mood = globals.EVIL_DM_MOOD if globals.EVIL_MODE else globals.DM_MOOD
|
|
|
|
return {
|
|
"status": "online",
|
|
"mood": current_mood,
|
|
"evil_mode": globals.EVIL_MODE,
|
|
"servers": len(server_manager.servers),
|
|
"active_schedulers": len(server_manager.schedulers),
|
|
"server_moods": server_moods
|
|
}
|
|
|
|
|
|
@router.get("/autonomous/stats")
|
|
def get_autonomous_stats():
|
|
"""Get autonomous engine stats for all servers"""
|
|
from utils.autonomous import autonomous_engine
|
|
|
|
stats = {}
|
|
for guild_id in server_manager.servers:
|
|
server_info = server_manager.servers[guild_id]
|
|
mood_name, _ = server_manager.get_server_mood(guild_id)
|
|
|
|
# Get context signals for this server
|
|
if guild_id in autonomous_engine.server_contexts:
|
|
ctx = autonomous_engine.server_contexts[guild_id]
|
|
|
|
# Get mood profile
|
|
mood_profile = autonomous_engine.mood_profiles.get(mood_name, {
|
|
"energy": 0.5,
|
|
"sociability": 0.5,
|
|
"impulsiveness": 0.5
|
|
})
|
|
|
|
# Sanitize float values for JSON serialization (replace inf with large number)
|
|
time_since_action = ctx.time_since_last_action
|
|
if time_since_action == float('inf'):
|
|
time_since_action = 999999
|
|
|
|
time_since_interaction = ctx.time_since_last_interaction
|
|
if time_since_interaction == float('inf'):
|
|
time_since_interaction = 999999
|
|
|
|
stats[str(guild_id)] = {
|
|
"guild_name": server_info.guild_name,
|
|
"mood": mood_name,
|
|
"mood_profile": mood_profile,
|
|
"context": {
|
|
"messages_last_5min": ctx.messages_last_5min,
|
|
"messages_last_hour": ctx.messages_last_hour,
|
|
"unique_users_active": ctx.unique_users_active,
|
|
"conversation_momentum": round(ctx.conversation_momentum, 2),
|
|
"users_joined_recently": ctx.users_joined_recently,
|
|
"users_status_changed": ctx.users_status_changed,
|
|
"users_started_activity": ctx.users_started_activity,
|
|
"time_since_last_action": round(time_since_action, 1),
|
|
"time_since_last_interaction": round(time_since_interaction, 1),
|
|
"messages_since_last_appearance": ctx.messages_since_last_appearance,
|
|
"hour_of_day": ctx.hour_of_day,
|
|
"is_weekend": ctx.is_weekend,
|
|
"mood_energy_level": round(ctx.mood_energy_level, 2)
|
|
}
|
|
}
|
|
else:
|
|
# Server not yet initialized in autonomous engine
|
|
mood_profile = autonomous_engine.mood_profiles.get(mood_name, {
|
|
"energy": 0.5,
|
|
"sociability": 0.5,
|
|
"impulsiveness": 0.5
|
|
})
|
|
|
|
stats[str(guild_id)] = {
|
|
"guild_name": server_info.guild_name,
|
|
"mood": mood_name,
|
|
"mood_profile": mood_profile,
|
|
"context": None
|
|
}
|
|
|
|
return {"servers": stats}
|
|
|
|
|
|
@router.get("/conversation/{user_id}")
|
|
def get_conversation(user_id: str):
|
|
"""Get conversation history for a user/channel (uses centralized ConversationHistory)."""
|
|
messages = conversation_history.get_recent_messages(user_id)
|
|
return {"conversation": [{"author": author, "content": content, "is_bot": is_bot} for author, content, is_bot in messages]}
|