feat(collector): RemoteTransport + CollectorBridge 구현 — Collector↔Gateway HTTP 통신 완성

- bridge.py RemoteTransport: HTTP 클라이언트, API Key auth, Gateway API 매핑
- collector.py CollectorBridge: 3개 async loop (pending 전달, response 폴링, commands 폴링)
- main.py: BOT_MODE=remote → CollectorBridge 실행 (Discord bot 없이)
- config.py: GATEWAY_API_KEY 설정
- .env.example: 모든 설정 항목 업데이트
This commit is contained in:
Variet Worker
2026-03-11 20:10:45 +09:00
parent 95da3e9307
commit 95c2905e14
4 changed files with 256 additions and 21 deletions

43
main.py
View File

@@ -51,15 +51,41 @@ async def main():
# Get the running loop
loop = asyncio.get_running_loop()
# Create transport based on BOT_MODE
transport = None # None → LocalTransport (default)
# ── Collector mode: no Discord bot, just relay local ↔ Gateway ──
if Config.BOT_MODE == "remote":
from bridge import RemoteTransport
from bridge import LocalTransport, RemoteTransport
from collector import CollectorBridge
if not Config.REMOTE_BRIDGE_URL:
logger.error("REMOTE_BRIDGE_URL is required for remote mode")
logger.error("REMOTE_BRIDGE_URL is required for remote (Collector) mode")
sys.exit(1)
transport = RemoteTransport(Config.REMOTE_BRIDGE_URL)
logger.info(f"Remote transport: {Config.REMOTE_BRIDGE_URL}")
bridge_dir = Config.BRAIN_PATH.parent / "bridge"
local = LocalTransport(bridge_dir)
local.ensure_dirs()
remote = RemoteTransport(Config.REMOTE_BRIDGE_URL, api_key=Config.GATEWAY_API_KEY)
collector = CollectorBridge(local, remote, project_name=Config.PROJECT_NAME)
logger.info(f"Collector mode: {Config.REMOTE_BRIDGE_URL}")
# Optionally start watcher for brain events (local display only)
watcher = BrainWatcher(event_queue, loop)
try:
watcher.start()
logger.info(f"Watcher started, {len(watcher.known_sessions)} existing sessions")
await collector.start()
except KeyboardInterrupt:
logger.info("Received keyboard interrupt")
except Exception as e:
logger.error(f"Fatal error: {e}", exc_info=True)
finally:
await collector.stop()
watcher.stop()
logger.info("Collector shutdown complete")
return
# ── Local / Gateway mode ──
# Create components
watcher = None
@@ -67,11 +93,6 @@ async def main():
watcher = BrainWatcher(event_queue, loop)
bot = GravityBot(event_queue)
# Inject transport if specified (otherwise bot uses default LocalTransport)
if transport is not None:
from bridge import BridgeProtocol
bot.bridge = BridgeProtocol(transport)
try:
# Start watcher (local mode only — gateway receives data via HTTP)
if watcher: