diff --git a/telegram/bot.py b/telegram/bot.py index 0f7dc51..ebf12ad 100755 --- a/telegram/bot.py +++ b/telegram/bot.py @@ -1025,6 +1025,98 @@ async def model_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE): await update.message.reply_text(f"Model set to {resolved} for session '{active_session}'.") logger.info(f"Model changed to {resolved} for session '{active_session}'") +async def timeout_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE): + """Set idle timeout for current session.""" + if not is_authorized(update.effective_user.id): + return + + active_session = session_manager.get_active_session() + if not active_session: + await update.message.reply_text("No active session. Use /new to start one.") + return + + if not context.args: + # Show current timeout + timeout_secs = session_manager.get_session_timeout(active_session) + minutes = timeout_secs // 60 + await update.message.reply_text( + f"Idle timeout: {minutes} minutes\n\nUsage: /timeout (1-120)" + ) + return + + # Parse and validate timeout value + try: + minutes = int(context.args[0]) + if minutes < 1 or minutes > 120: + await update.message.reply_text("Timeout must be between 1 and 120 minutes") + return + except ValueError: + await update.message.reply_text("Invalid number. Usage: /timeout ") + return + + # Convert to seconds and update + timeout_seconds = minutes * 60 + session_manager.update_session(active_session, idle_timeout=timeout_seconds) + + # Update existing idle timer if present + if active_session in idle_timers: + idle_timers[active_session].timeout_seconds = timeout_seconds + idle_timers[active_session].reset() + + await update.message.reply_text( + f"Idle timeout set to {minutes} minutes for session '{active_session}'." + ) + logger.info(f"Idle timeout set to {minutes} minutes for session '{active_session}'") + +async def sessions_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE): + """List all sessions with status.""" + if not is_authorized(update.effective_user.id): + return + + sessions = session_manager.list_sessions() + if not sessions: + await update.message.reply_text("No sessions. Use /new to create one.") + return + + active_session = session_manager.get_active_session() + + def format_relative_time(iso_str): + """Format ISO timestamp as relative time (e.g., '2m ago').""" + dt = datetime.fromisoformat(iso_str) + delta = datetime.now(timezone.utc) - dt + secs = delta.total_seconds() + if secs < 60: + return "just now" + if secs < 3600: + return f"{int(secs/60)}m ago" + if secs < 86400: + return f"{int(secs/3600)}h ago" + return f"{int(secs/86400)}d ago" + + lines = [] + for s in sessions: + name = s['name'] + persona = s.get('persona', 'default') + + # Determine status + if name in subprocesses and subprocesses[name].is_alive: + status = "🟢 LIVE" + elif s.get('status') == 'suspended': + status = "⚪ IDLE" + else: + status = s.get('status', 'unknown').upper() + + # Format last active time + last_active = s.get('last_active', '') + rel_time = format_relative_time(last_active) if last_active else "unknown" + + # Mark current active session + marker = "→ " if name == active_session else " " + + lines.append(f"{marker}{status} `{name}` ({persona}) - {rel_time}") + + await update.message.reply_text("\n".join(lines), parse_mode='Markdown') + async def unknown(update: Update, context: ContextTypes.DEFAULT_TYPE): """Handle unknown commands.""" if not is_authorized(update.effective_user.id): @@ -1113,8 +1205,10 @@ def main(): app.add_handler(CommandHandler("chatid", chatid)) app.add_handler(CommandHandler("new", new_session)) app.add_handler(CommandHandler("session", switch_session_cmd)) + app.add_handler(CommandHandler("sessions", sessions_cmd)) app.add_handler(CommandHandler("archive", archive_session_cmd)) app.add_handler(CommandHandler("model", model_cmd)) + app.add_handler(CommandHandler("timeout", timeout_cmd)) app.add_handler(CommandHandler("status", status)) app.add_handler(CommandHandler("pbs", pbs)) app.add_handler(CommandHandler("pbs_status", pbs_status))