feat(debate): Wiki.js 연동 — Working Document + Round Log 자동 업로드
This commit is contained in:
@@ -47,13 +47,14 @@ FILE_STABLE_DELAY = 5 # 파일 작성 완료 대기 (초)
|
|||||||
@dataclass
|
@dataclass
|
||||||
class DebateSession:
|
class DebateSession:
|
||||||
topic: str = ""
|
topic: str = ""
|
||||||
|
topic_slug: str = "" # Wiki 경로용
|
||||||
round: int = 0
|
round: int = 0
|
||||||
max_rounds: int = MAX_ROUNDS
|
max_rounds: int = MAX_ROUNDS
|
||||||
active: bool = False
|
active: bool = False
|
||||||
paused: bool = False # 사용자 응답 대기 중
|
paused: bool = False
|
||||||
current_speaker: str = ""
|
current_speaker: str = ""
|
||||||
history: list = field(default_factory=list)
|
history: list = field(default_factory=list)
|
||||||
pending_question: str = "" # 사용자에게 보낸 질문
|
pending_question: str = ""
|
||||||
|
|
||||||
|
|
||||||
class DebateHandler:
|
class DebateHandler:
|
||||||
@@ -72,8 +73,16 @@ class DebateHandler:
|
|||||||
await ctx.reply("⚠️ 이미 진행 중. `!debate-stop`으로 먼저 종료.")
|
await ctx.reply("⚠️ 이미 진행 중. `!debate-stop`으로 먼저 종료.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# slug 생성
|
||||||
|
try:
|
||||||
|
from tools.wiki_client import WikiClient
|
||||||
|
slug = WikiClient.slugify(topic)
|
||||||
|
except Exception:
|
||||||
|
slug = topic[:15].replace(" ", "-").lower()
|
||||||
|
|
||||||
self.session = DebateSession(
|
self.session = DebateSession(
|
||||||
topic=topic, active=True, max_rounds=MAX_ROUNDS,
|
topic=topic, topic_slug=slug,
|
||||||
|
active=True, max_rounds=MAX_ROUNDS,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 폴더 초기화
|
# 폴더 초기화
|
||||||
@@ -179,7 +188,10 @@ class DebateHandler:
|
|||||||
"speaker": speaker, "content": response,
|
"speaker": speaker, "content": response,
|
||||||
})
|
})
|
||||||
|
|
||||||
# ⑤ Working Document 통합 편집 (Flash)
|
# ⑤ Round Log에 대화 전문 기록 (로컬 + Wiki.js)
|
||||||
|
await self._append_round_log(speaker, response)
|
||||||
|
|
||||||
|
# ⑥ Working Document 통합 편집 (Flash + Wiki.js)
|
||||||
await self._update_working_document(speaker, response)
|
await self._update_working_document(speaker, response)
|
||||||
|
|
||||||
# ⑥ 양쪽 wiki/ 동기화
|
# ⑥ 양쪽 wiki/ 동기화
|
||||||
@@ -448,8 +460,7 @@ class DebateHandler:
|
|||||||
# ═══════════════════════════════════════════
|
# ═══════════════════════════════════════════
|
||||||
|
|
||||||
async def _update_working_document(self, speaker: str, response: str):
|
async def _update_working_document(self, speaker: str, response: str):
|
||||||
"""Flash가 AG 의견을 Working Document에 통합 편집."""
|
"""Flash가 AG 의견을 Working Document에 통합 편집 + Wiki.js 업로드."""
|
||||||
# 현재 working document 읽기
|
|
||||||
wd_path = AGENT_PATHS["gemini"] / "wiki" / "working_document.md"
|
wd_path = AGENT_PATHS["gemini"] / "wiki" / "working_document.md"
|
||||||
current_doc = ""
|
current_doc = ""
|
||||||
if wd_path.exists():
|
if wd_path.exists():
|
||||||
@@ -485,15 +496,58 @@ class DebateHandler:
|
|||||||
caller = GeminiCaller()
|
caller = GeminiCaller()
|
||||||
updated = await caller.call_simple(merge_prompt, timeout=120)
|
updated = await caller.call_simple(merge_prompt, timeout=120)
|
||||||
if updated and len(updated) > 50:
|
if updated and len(updated) > 50:
|
||||||
# gemini 폴더에 저장 (sync에서 양쪽 복사)
|
|
||||||
wd_path.parent.mkdir(parents=True, exist_ok=True)
|
wd_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
wd_path.write_text(updated, encoding="utf-8")
|
wd_path.write_text(updated, encoding="utf-8")
|
||||||
logger.info(f"Working Document 업데이트: {len(updated)}자")
|
logger.info(f"Working Document 업데이트: {len(updated)}자")
|
||||||
|
# Wiki.js에 업로드
|
||||||
|
await self._wiki_upsert(
|
||||||
|
f"debates/{self.session.topic_slug}/working-document",
|
||||||
|
f"{self.session.topic} — Working Document",
|
||||||
|
updated,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
logger.warning("Working Document 업데이트 실패 — Flash 응답 부족")
|
logger.warning("Working Document 업데이트 실패")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Working Document 업데이트 오류: {e}")
|
logger.error(f"Working Document 업데이트 오류: {e}")
|
||||||
|
|
||||||
|
async def _append_round_log(self, speaker: str, response: str):
|
||||||
|
"""Round Log에 대화 전문 append + Wiki.js 업로드."""
|
||||||
|
log_path = AGENT_PATHS["gemini"] / "wiki" / "round_log.md"
|
||||||
|
# 기존 내용 읽기
|
||||||
|
existing = ""
|
||||||
|
if log_path.exists():
|
||||||
|
existing = log_path.read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
emoji = AGENT_EMOJI.get(speaker, "👤")
|
||||||
|
entry = (
|
||||||
|
f"\n---\n\n"
|
||||||
|
f"## Round {self.session.round} — {emoji} {speaker}\n\n"
|
||||||
|
f"{response}\n"
|
||||||
|
)
|
||||||
|
updated_log = existing + entry
|
||||||
|
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
log_path.write_text(updated_log, encoding="utf-8")
|
||||||
|
|
||||||
|
# Wiki.js에 업로드
|
||||||
|
await self._wiki_upsert(
|
||||||
|
f"debates/{self.session.topic_slug}/round-log",
|
||||||
|
f"{self.session.topic} — Round Log",
|
||||||
|
updated_log,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _wiki_upsert(self, path: str, title: str, content: str):
|
||||||
|
"""Wiki.js에 페이지 upsert."""
|
||||||
|
try:
|
||||||
|
from tools.wiki_client import WikiClient
|
||||||
|
client = WikiClient()
|
||||||
|
await client.upsert_page(
|
||||||
|
path=path, title=title, content=content,
|
||||||
|
tags=["debate", self.session.topic_slug],
|
||||||
|
)
|
||||||
|
logger.info(f"Wiki.js 업로드: {path}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Wiki.js 업로드 실패 ({path}): {e}")
|
||||||
|
|
||||||
def _sync_wiki(self):
|
def _sync_wiki(self):
|
||||||
"""gemini wiki/ 폴더 내용을 opus wiki/에 동기화."""
|
"""gemini wiki/ 폴더 내용을 opus wiki/에 동기화."""
|
||||||
src = AGENT_PATHS["gemini"] / "wiki"
|
src = AGENT_PATHS["gemini"] / "wiki"
|
||||||
|
|||||||
Reference in New Issue
Block a user