stage-6: model selection and advanced commands
/model (show/change), /restart (owner), /logs, set_session_model API, model reset on /clear. 20 new tests (161 total). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,14 @@
|
||||
|
||||
import logging
|
||||
from src.config import Config
|
||||
from src.claude_session import send_message, clear_session, get_active_session, list_sessions
|
||||
from src.claude_session import (
|
||||
send_message,
|
||||
clear_session,
|
||||
get_active_session,
|
||||
list_sessions,
|
||||
set_session_model,
|
||||
VALID_MODELS,
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -28,22 +35,30 @@ def route_message(channel_id: str, user_id: str, text: str, model: str | None =
|
||||
|
||||
# Text-based commands (not slash commands — these work in any adapter)
|
||||
if text.lower() == "/clear":
|
||||
default_model = _get_config().get("bot.default_model", "sonnet")
|
||||
cleared = clear_session(channel_id)
|
||||
if cleared:
|
||||
return "Session cleared.", True
|
||||
return f"Session cleared. Model reset to {default_model}.", True
|
||||
return "No active session.", True
|
||||
|
||||
if text.lower() == "/status":
|
||||
return _status(channel_id), True
|
||||
|
||||
if text.lower().startswith("/model"):
|
||||
return _model_command(channel_id, text), True
|
||||
|
||||
if text.startswith("/"):
|
||||
return f"Unknown command: {text.split()[0]}", True
|
||||
|
||||
# Regular message → Claude
|
||||
if not model:
|
||||
# Get channel default model or global default
|
||||
channel_cfg = _get_channel_config(channel_id)
|
||||
model = (channel_cfg or {}).get("default_model") or _get_config().get("bot.default_model", "sonnet")
|
||||
# Check session model first, then channel default, then global default
|
||||
session = get_active_session(channel_id)
|
||||
if session and session.get("model"):
|
||||
model = session["model"]
|
||||
else:
|
||||
channel_cfg = _get_channel_config(channel_id)
|
||||
model = (channel_cfg or {}).get("default_model") or _get_config().get("bot.default_model", "sonnet")
|
||||
|
||||
try:
|
||||
response = send_message(channel_id, text, model=model)
|
||||
@@ -66,6 +81,43 @@ def _status(channel_id: str) -> str:
|
||||
return f"Model: {model} | Session: {sid}... | Messages: {count}"
|
||||
|
||||
|
||||
def _model_command(channel_id: str, text: str) -> str:
|
||||
"""Handle /model [choice] text command."""
|
||||
parts = text.strip().split()
|
||||
if len(parts) == 1:
|
||||
# /model — show current
|
||||
session = get_active_session(channel_id)
|
||||
if session:
|
||||
current = session.get("model", "unknown")
|
||||
else:
|
||||
channel_cfg = _get_channel_config(channel_id)
|
||||
current = (channel_cfg or {}).get("default_model") or _get_config().get("bot.default_model", "sonnet")
|
||||
available = ", ".join(sorted(VALID_MODELS))
|
||||
return f"Current model: {current}\nAvailable: {available}"
|
||||
|
||||
choice = parts[1].lower()
|
||||
if choice not in VALID_MODELS:
|
||||
return f"Invalid model '{choice}'. Choose from: {', '.join(sorted(VALID_MODELS))}"
|
||||
|
||||
session = get_active_session(channel_id)
|
||||
if session:
|
||||
set_session_model(channel_id, choice)
|
||||
else:
|
||||
# Pre-set for next message
|
||||
from src.claude_session import _load_sessions, _save_sessions
|
||||
from datetime import datetime, timezone
|
||||
sessions = _load_sessions()
|
||||
sessions[channel_id] = {
|
||||
"session_id": "",
|
||||
"model": choice,
|
||||
"created_at": datetime.now(timezone.utc).isoformat(),
|
||||
"last_message_at": datetime.now(timezone.utc).isoformat(),
|
||||
"message_count": 0,
|
||||
}
|
||||
_save_sessions(sessions)
|
||||
return f"Model changed to {choice}."
|
||||
|
||||
|
||||
def _get_channel_config(channel_id: str) -> dict | None:
|
||||
"""Find channel config by ID."""
|
||||
channels = _get_config().get("channels", {})
|
||||
|
||||
Reference in New Issue
Block a user