feat(05-03): implement /next and /stop commands for round progression
Add /next to advance discussion with full context passed to models: - Validates active discussion state - Auto-completes when round limit reached - Shows Round N/M progress indicator Add /stop to end discussion early: - Marks discussion as COMPLETED - Clears session state - Suggests /consensus for summarization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
104eceb246
commit
3ae08e9317
2 changed files with 107 additions and 1 deletions
|
|
@ -7,7 +7,13 @@ project management, discussion commands, and export functionality.
|
||||||
from telegram.ext import Application, CommandHandler
|
from telegram.ext import Application, CommandHandler
|
||||||
|
|
||||||
from moai.bot.handlers.commands import help_command, start_command
|
from moai.bot.handlers.commands import help_command, start_command
|
||||||
from moai.bot.handlers.discussion import ask_command, discuss_command, open_command
|
from moai.bot.handlers.discussion import (
|
||||||
|
ask_command,
|
||||||
|
discuss_command,
|
||||||
|
next_command,
|
||||||
|
open_command,
|
||||||
|
stop_command,
|
||||||
|
)
|
||||||
from moai.bot.handlers.projects import project_command, projects_command
|
from moai.bot.handlers.projects import project_command, projects_command
|
||||||
from moai.bot.handlers.status import status_command
|
from moai.bot.handlers.status import status_command
|
||||||
|
|
||||||
|
|
@ -33,3 +39,5 @@ def register_handlers(app: Application) -> None:
|
||||||
app.add_handler(CommandHandler("ask", ask_command))
|
app.add_handler(CommandHandler("ask", ask_command))
|
||||||
app.add_handler(CommandHandler("open", open_command))
|
app.add_handler(CommandHandler("open", open_command))
|
||||||
app.add_handler(CommandHandler("discuss", discuss_command))
|
app.add_handler(CommandHandler("discuss", discuss_command))
|
||||||
|
app.add_handler(CommandHandler("next", next_command))
|
||||||
|
app.add_handler(CommandHandler("stop", stop_command))
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from moai.core.ai_client import MODEL_MAP, get_ai_client
|
||||||
from moai.core.models import DiscussionType, RoundType
|
from moai.core.models import DiscussionType, RoundType
|
||||||
from moai.core.orchestrator import query_models_parallel, run_discussion_round
|
from moai.core.orchestrator import query_models_parallel, run_discussion_round
|
||||||
from moai.core.services.discussion import (
|
from moai.core.services.discussion import (
|
||||||
|
complete_discussion,
|
||||||
create_discussion,
|
create_discussion,
|
||||||
create_message,
|
create_message,
|
||||||
create_round,
|
create_round,
|
||||||
|
|
@ -245,3 +246,100 @@ async def discuss_command(update: Update, context: ContextTypes.DEFAULT_TYPE) ->
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await update.message.reply_text(f"Error: {e}")
|
await update.message.reply_text(f"Error: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
async def next_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||||
|
"""Handle /next command - advance to the next discussion round.
|
||||||
|
|
||||||
|
Requires an active discussion started with /discuss. Runs the next
|
||||||
|
sequential round with full context from prior rounds.
|
||||||
|
"""
|
||||||
|
# Check for active discussion state
|
||||||
|
state = context.user_data.get("discussion_state")
|
||||||
|
if state is None:
|
||||||
|
await update.message.reply_text("No active discussion. Start one with /open then /discuss.")
|
||||||
|
return
|
||||||
|
|
||||||
|
current_round = state["current_round"]
|
||||||
|
round_limit = state["round_limit"]
|
||||||
|
|
||||||
|
# Check if already at limit
|
||||||
|
if current_round > round_limit:
|
||||||
|
await update.message.reply_text(
|
||||||
|
f"Round limit ({round_limit}) reached. Start a new discussion with /open."
|
||||||
|
)
|
||||||
|
del context.user_data["discussion_state"]
|
||||||
|
return
|
||||||
|
|
||||||
|
# Show typing indicator
|
||||||
|
await update.message.chat.send_action("typing")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Load discussion with full context
|
||||||
|
discussion = await get_discussion(state["discussion_id"])
|
||||||
|
if discussion is None:
|
||||||
|
await update.message.reply_text("Discussion not found.")
|
||||||
|
del context.user_data["discussion_state"]
|
||||||
|
return
|
||||||
|
|
||||||
|
# Run the next round
|
||||||
|
responses = await run_discussion_round(
|
||||||
|
discussion=discussion,
|
||||||
|
models=state["models"],
|
||||||
|
project_name=state["project_name"],
|
||||||
|
round_number=current_round,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build response text
|
||||||
|
response_lines = [f"*Round {current_round}/{round_limit}:*\n"]
|
||||||
|
for model, response in responses.items():
|
||||||
|
response_lines.append(f"*{model.title()}:*\n{response}\n")
|
||||||
|
|
||||||
|
if current_round >= round_limit:
|
||||||
|
# Final round - complete discussion
|
||||||
|
await complete_discussion(state["discussion_id"])
|
||||||
|
response_lines.append(f"\n_Discussion complete ({round_limit} rounds)._")
|
||||||
|
del context.user_data["discussion_state"]
|
||||||
|
else:
|
||||||
|
response_lines.append(
|
||||||
|
f"\n_Round {current_round}/{round_limit} complete. Use /next or /stop._"
|
||||||
|
)
|
||||||
|
# Update state for next round
|
||||||
|
context.user_data["discussion_state"]["current_round"] = current_round + 1
|
||||||
|
|
||||||
|
await update.message.reply_text(
|
||||||
|
"\n".join(response_lines),
|
||||||
|
parse_mode="Markdown",
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
await update.message.reply_text(f"Error: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
async def stop_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||||
|
"""Handle /stop command - stop the current discussion early.
|
||||||
|
|
||||||
|
Completes the discussion at the current round and clears the session state.
|
||||||
|
"""
|
||||||
|
# Check for active discussion state
|
||||||
|
state = context.user_data.get("discussion_state")
|
||||||
|
if state is None:
|
||||||
|
await update.message.reply_text("No active discussion to stop.")
|
||||||
|
return
|
||||||
|
|
||||||
|
current_round = state["current_round"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Complete the discussion in database
|
||||||
|
await complete_discussion(state["discussion_id"])
|
||||||
|
|
||||||
|
# Clear session state
|
||||||
|
del context.user_data["discussion_state"]
|
||||||
|
|
||||||
|
await update.message.reply_text(
|
||||||
|
f"_Discussion stopped at round {current_round - 1}. Use /consensus to summarize._",
|
||||||
|
parse_mode="Markdown",
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
await update.message.reply_text(f"Error: {e}")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue