Files
gravity_control/main.py
Variet Worker e7631177f8 refactor(cleanup): v0.5.0 Collector 제거 + dead code 정리 + HttpBridgeContext 버그 수정
- DELETE collector.py (523줄)
- main.py: BOT_MODE=remote 분기 제거
- gateway.py: Collector REST 6개 endpoint 제거 (311→168줄)
- bridge.py: RemoteTransport 제거 (480→270줄)
- config.py: REMOTE_BRIDGE_URL 제거
- extension.ts: dead code 4개 + stale module vars 제거
- step-probe.ts: getStepProbeContext() 추가, autoApproveEnabled 제거
- FIX: HttpBridgeContext stale primitive (getter 패턴으로 수정)
- ADD: extension.log rotation (10MB→2MB tail)
- docs: architecture.md, tech-stack.md, known-issues.md 업데이트
2026-03-18 11:08:59 +09:00

115 lines
3.4 KiB
Python

"""Gravity Control — Antigravity Discord Bridge.
Entry point that runs the brain watcher and Discord bot together.
"""
import asyncio
import io
import logging
import os
import sys
from config import Config
from watcher import BrainWatcher
from bot import GravityBot
# Logging setup (UTF-8 forced for Windows cp949 compatibility)
_utf8_stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(name)s] %(levelname)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
handlers=[
logging.StreamHandler(_utf8_stdout),
logging.FileHandler("gravity_control.log", encoding="utf-8"),
],
)
logger = logging.getLogger("gravity_control")
async def main():
"""Run the bridge: watcher + Discord bot."""
# Validate config
errors = Config.validate()
if errors:
for e in errors:
logger.error(f"Config error: {e}")
logger.error("Fix configuration issues and restart.")
sys.exit(1)
logger.info("=" * 50)
logger.info("Gravity Control — Antigravity Discord Bridge")
logger.info("=" * 50)
logger.info(f"Brain path: {Config.BRAIN_PATH}")
logger.info(f"Debounce: {Config.DEBOUNCE_SECONDS}s")
logger.info(f"Bot mode: {Config.BOT_MODE}")
# Shared event queue
event_queue = asyncio.Queue()
# Get the running loop
loop = asyncio.get_running_loop()
# ── Local / Gateway mode ──
# Create components
watcher = None
if Config.BOT_MODE != 'gateway':
watcher = BrainWatcher(event_queue, loop)
bot = GravityBot(event_queue)
try:
# Start watcher (local mode only — gateway receives data via HTTP)
if watcher:
watcher.start()
logger.info(f"Watcher started, {len(watcher.known_sessions)} existing sessions")
else:
logger.info("Gateway mode — watcher disabled (data via HTTP API)")
# Start Gateway HTTP API + WebSocket Hub (gateway mode)
if Config.BOT_MODE == 'gateway':
from gateway import GatewayAPI
from hub import WSHub
from auth import TokenManager
# Initialize Hub
token_mgr = TokenManager(
secret=Config.GRAVITY_HUB_SECRET,
registration_code=Config.GRAVITY_REGISTRATION_CODE,
)
hub = WSHub(token_mgr)
gateway_port = int(os.environ.get('GATEWAY_PORT', '8585'))
gateway = GatewayAPI(
bot, port=gateway_port,
api_key=Config.GATEWAY_API_KEY,
hub=hub,
)
bot.gateway = gateway # Enable _write_command → gateway.push_command
bot.hub = hub # Enable Hub-based message routing
await gateway.start()
logger.info(f"Gateway API + WS Hub running on port {gateway_port}")
# Run Discord bot (blocks until bot disconnects)
await bot.start(Config.DISCORD_TOKEN)
except KeyboardInterrupt:
logger.info("Received keyboard interrupt")
except Exception as e:
logger.error(f"Fatal error: {e}", exc_info=True)
finally:
# Cleanup
if watcher:
watcher.stop()
if not bot.is_closed():
await bot.close()
logger.info("Gravity Control shutdown complete")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass