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