fix(debate): Wiki.js 짧은 제목 생성, AG 작업 종료 이벤트 대기로 변경
This commit is contained in:
@@ -48,6 +48,7 @@ FILE_STABLE_DELAY = 5 # 파일 작성 완료 대기 (초)
|
||||
class DebateSession:
|
||||
topic: str = ""
|
||||
topic_slug: str = "" # Wiki 경로용
|
||||
wiki_title: str = "" # Wiki 페이지 짧은 제목
|
||||
round: int = 0
|
||||
max_rounds: int = MAX_ROUNDS
|
||||
active: bool = False
|
||||
@@ -62,6 +63,7 @@ class DebateHandler:
|
||||
self.bot = bot
|
||||
self.session = DebateSession()
|
||||
self._debate_task: Optional[asyncio.Task] = None
|
||||
self._response_event = asyncio.Event()
|
||||
|
||||
# ═══════════════════════════════════════════
|
||||
# 공개 API
|
||||
@@ -73,17 +75,29 @@ class DebateHandler:
|
||||
await ctx.reply("⚠️ 이미 진행 중. `!debate-stop`으로 먼저 종료.")
|
||||
return
|
||||
|
||||
# slug 생성
|
||||
# slug 및 짧은 제목 생성
|
||||
try:
|
||||
from core.gemini_caller import GeminiCaller
|
||||
caller = GeminiCaller()
|
||||
short_title = await caller.call_simple(
|
||||
f"다음 토론 주제를 3~5단어의 짧고 명확한 제목으로 요약해주세요. 마크다운 기호 없이 텍스트만 출력하세요.\n\n주제: {topic}",
|
||||
timeout=30
|
||||
)
|
||||
short_title = short_title.strip()
|
||||
if len(short_title) > 50:
|
||||
short_title = short_title[:50]
|
||||
|
||||
from tools.wiki_client import WikiClient
|
||||
slug = WikiClient.slugify(topic)
|
||||
slug = WikiClient.slugify(short_title)
|
||||
if len(slug) > 80:
|
||||
slug = slug[:80].rstrip("-")
|
||||
except Exception:
|
||||
slug = topic[:20].replace(" ", "-").lower()
|
||||
except Exception as e:
|
||||
logger.warning(f"짧은 제목 생성 실패: {e}")
|
||||
short_title = topic[:20]
|
||||
slug = short_title.replace(" ", "-").lower()
|
||||
|
||||
self.session = DebateSession(
|
||||
topic=topic, topic_slug=slug,
|
||||
topic=topic, topic_slug=slug, wiki_title=short_title,
|
||||
active=True, max_rounds=MAX_ROUNDS,
|
||||
)
|
||||
|
||||
@@ -145,9 +159,21 @@ class DebateHandler:
|
||||
self.session.pending_question = ""
|
||||
|
||||
async def on_agent_message(self, message: discord.Message):
|
||||
"""AG 채널 메시지 감지 — response.md 체크 트리거."""
|
||||
# 별도 처리 불필요 — auto_loop에서 파일 폴링으로 처리
|
||||
pass
|
||||
"""AG 채널 메시지 감지 — 완료 시그널이면 event set."""
|
||||
if not self.session.active:
|
||||
return
|
||||
|
||||
active_ch_id = DEBATE_AGENTS.get(self.session.current_speaker)
|
||||
if message.channel.id != active_ch_id:
|
||||
return
|
||||
|
||||
content = message.content or ""
|
||||
embed_texts = " ".join([e.description for e in message.embeds if e.description])
|
||||
full_text = content + " " + embed_texts
|
||||
|
||||
if "작업 종료" in full_text or "작성 완료" in full_text:
|
||||
logger.info(f"[{self.session.current_speaker}] 완료 시그널 감지: {full_text[:50]}")
|
||||
self._response_event.set()
|
||||
|
||||
# ═══════════════════════════════════════════
|
||||
# 자동 토론 루프
|
||||
@@ -275,7 +301,7 @@ class DebateHandler:
|
||||
)
|
||||
|
||||
async def _wait_for_response(self, speaker: str) -> str:
|
||||
"""response.md에 내용이 채워질 때까지 폴링."""
|
||||
"""AG의 Discord 완료 메시지 대기 후 response.md 읽기."""
|
||||
resp_path = AGENT_PATHS[speaker] / "response.md"
|
||||
# response.md 비우기
|
||||
resp_path.write_text("", encoding="utf-8")
|
||||
@@ -287,35 +313,27 @@ class DebateHandler:
|
||||
f"`{speaker}` 답변 대기 중..."
|
||||
)
|
||||
|
||||
start = time.time()
|
||||
last_size = 0
|
||||
stable_since = 0
|
||||
self._response_event.clear()
|
||||
|
||||
try:
|
||||
# Discord에서 "작업 종료" 메시지가 올 때까지 대기
|
||||
await asyncio.wait_for(self._response_event.wait(), timeout=RESPONSE_TIMEOUT)
|
||||
|
||||
while time.time() - start < RESPONSE_TIMEOUT:
|
||||
if not self.session.active:
|
||||
return ""
|
||||
|
||||
await asyncio.sleep(FILE_CHECK_INTERVAL)
|
||||
|
||||
if not resp_path.exists():
|
||||
continue
|
||||
|
||||
# 완료 시그널을 받으면 파일 읽기
|
||||
if resp_path.exists():
|
||||
content = resp_path.read_text(encoding="utf-8").strip()
|
||||
if not content:
|
||||
continue
|
||||
|
||||
current_size = len(content)
|
||||
if current_size == last_size and current_size > 0:
|
||||
# 파일 크기 안정 — 작성 완료로 판단
|
||||
if stable_since == 0:
|
||||
stable_since = time.time()
|
||||
elif time.time() - stable_since >= FILE_STABLE_DELAY:
|
||||
if content:
|
||||
return content
|
||||
else:
|
||||
last_size = current_size
|
||||
stable_since = 0
|
||||
if ctrl:
|
||||
await ctrl.send(f"⚠️ `{speaker}` 완료 신호를 받았으나 `response.md`가 비어있습니다.")
|
||||
|
||||
# 타임아웃
|
||||
return ""
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
if ctrl:
|
||||
await ctrl.send(f"⏰ `{speaker}` 응답 시간 초과 ({RESPONSE_TIMEOUT}초)")
|
||||
return ""
|
||||
@@ -503,7 +521,7 @@ class DebateHandler:
|
||||
# Wiki.js에 업로드
|
||||
await self._wiki_upsert(
|
||||
f"debates/{self.session.topic_slug}/working-document",
|
||||
f"{self.session.topic} — Working Document",
|
||||
f"{self.session.wiki_title} — Working Document",
|
||||
updated,
|
||||
)
|
||||
else:
|
||||
@@ -532,7 +550,7 @@ class DebateHandler:
|
||||
# Wiki.js에 업로드
|
||||
await self._wiki_upsert(
|
||||
f"debates/{self.session.topic_slug}/round-log",
|
||||
f"{self.session.topic} — Round Log",
|
||||
f"{self.session.wiki_title} — Round Log",
|
||||
updated_log,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user