feat: chat capture (@bridge participant, onDidChangeTextDocument), !stop command, chat snapshot scanner

This commit is contained in:
2026-03-07 14:45:44 +09:00
parent d44b4c2f77
commit 35ee916440
3 changed files with 230 additions and 5 deletions

54
bot.py
View File

@@ -114,6 +114,7 @@ class GravityBot(commands.Bot):
async def setup_hook(self):
self.loop.create_task(self._process_events())
self.pending_approval_scanner.start()
self.chat_snapshot_scanner.start()
logger.info("Bot setup complete")
async def on_ready(self):
@@ -417,6 +418,17 @@ class GravityBot(commands.Bot):
text = message.content.strip()
# Special command: !stop — cancel AI work
if text == "!stop":
self.bridge.write_command(project, "!stop", project_name=project)
embed = discord.Embed(
title="⏹️ AI 작업 중지",
description=f"프로젝트: **{project}**\n중지 요청을 Extension에 전달했습니다.",
color=discord.Color.orange(),
)
await message.channel.send(embed=embed)
return
# Special command: !auto on/off
if text in ("!auto on", "!auto off"):
self.bridge.write_command(project, text, project_name=project)
@@ -439,3 +451,45 @@ class GravityBot(commands.Bot):
await message.add_reaction("📨")
await self.process_commands(message)
# ─── Chat Snapshot Scanner ─────────────────────────────────────────
@tasks.loop(seconds=5)
async def chat_snapshot_scanner(self):
"""Scan bridge/chat_snapshots/ for AI response dumps."""
try:
snapshot_dir = self.bridge.bridge_dir / "chat_snapshots"
if not snapshot_dir.exists():
return
for f in snapshot_dir.glob("*.json"):
try:
data = json.loads(f.read_text(encoding="utf-8-sig"))
project = data.get("project_name", Config.PROJECT_NAME)
content = data.get("content", "")
if content:
channel = await self._get_channel(project)
if channel:
# Split long content
CHUNK = 4000
chunks = [content[i:i+CHUNK] for i in range(0, len(content), CHUNK)]
for i, chunk in enumerate(chunks):
title = "💬 AI 대화 내용" if i == 0 else f"💬 (계속 {i+1}/{len(chunks)})"
embed = discord.Embed(
title=title,
description=chunk,
color=discord.Color.purple(),
timestamp=datetime.now(timezone.utc),
)
await channel.send(embed=embed)
f.unlink() # Cleanup
except (json.JSONDecodeError, OSError) as e:
logger.warning(f"Bad chat snapshot {f.name}: {e}")
except Exception as e:
logger.error(f"Error scanning chat snapshots: {e}")
@chat_snapshot_scanner.before_loop
async def before_chat_scanner(self):
await self.wait_until_ready()