fix(ralph): "Planifică" deschide modal/ForceReply când descrierea lipsește

Înainte: click pe 🧠 Planifică (Discord/Telegram) sau /plan <slug> fără descriere
pe un proiect din workspace fără entry în approved-tasks.json → mesaj eroare
"Adaugă mai întâi cu /p <slug> <descriere>" și user-ul trebuia să facă două
operații.

Acum:
- Discord button "Planifică" cu descriere goală → deschide RalphPlanModal cu
  TextInput pentru descriere; on_submit pornește direct start_planning_session
- Discord /plan <slug> fără description param și fără entry → același modal
  (response.send_modal ÎNAINTE de defer — Discord constraint)
- Telegram callback "Planifică" cu descriere goală → set state
  STEP_INPUT_DESCRIPTION_THEN_PLAN + ForceReply; handle_message detectează
  step și pornește planning cu textul user-ului
- ralph_flow.py: nou STEP_INPUT_DESCRIPTION_THEN_PLAN (alături de cel existent
  pentru propose-only)

start_planning_session deja auto-creează entry în approved-tasks.json dacă
proiectul lipsește, deci flow-ul e end-to-end: workspace → click → descriere
→ planning agent activ.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-26 18:51:09 +00:00
parent bf9380f2ad
commit dedeedf024
4 changed files with 87 additions and 21 deletions

View File

@@ -1007,8 +1007,8 @@ def create_bot(config: Config) -> discord.Client:
slug: str,
description: str | None = None,
) -> None:
await interaction.response.defer(ephemeral=True)
# Resolve description: explicit param wins, else look up in approved-tasks.
# Done BEFORE defer so we can fall back to a modal if missing.
desc = (description or "").strip()
if not desc:
try:
@@ -1020,13 +1020,12 @@ def create_bot(config: Config) -> discord.Client:
except Exception:
logger.exception("approved-tasks lookup failed")
if not desc:
await interaction.followup.send(
f"Nu am descriere pentru `{slug}`. Adaugă cu `/p {slug} <descriere>` "
"sau pasează `description` la `/plan`.",
ephemeral=True,
)
# No description anywhere — ask via modal and start planning on submit.
from src.adapters.discord_views import RalphPlanModal
await interaction.response.send_modal(RalphPlanModal(slug))
return
await interaction.response.defer(ephemeral=True)
channel_id = str(interaction.channel_id)
await interaction.followup.send(
f"🧠 Pornesc planning pentru `{slug}`… (durează ~60s)", ephemeral=True