- extension.ts 3,446→1,289줄 (-63%) - step-probe.ts (1,435줄): setupMonitor, processResponseFile, tryApprovalStrategies - observer-script.ts (687줄): DOM observer script - ws-client.ts (390줄): WSBridgeClient - step-utils.ts (114줄): step 파싱 유틸 - auth.py (115줄): JWT + registration code - hub.py (581줄): WSHub + per-client queue - Hub WS 연동 테스트 통과 (auth, chat, register) - VSIX v0.4.0 빌드
67 lines
2.3 KiB
Python
67 lines
2.3 KiB
Python
"""Configuration module — loads settings from .env file or environment variables."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from dotenv import load_dotenv
|
|
|
|
# Load .env from project root
|
|
load_dotenv(Path(__file__).parent / ".env")
|
|
|
|
|
|
class Config:
|
|
"""Bridge configuration."""
|
|
|
|
# Discord
|
|
DISCORD_TOKEN: str = os.getenv("DISCORD_TOKEN", "")
|
|
DISCORD_GUILD_ID: int = int(os.getenv("DISCORD_GUILD_ID") or "0")
|
|
|
|
# Antigravity Brain path
|
|
# NOTE: os.getenv returns "" (not None) when .env has BRAIN_PATH= (empty value).
|
|
# Path("") resolves to "." (CWD), which is WRONG. Use `or` to handle both None and "".
|
|
BRAIN_PATH: Path = Path(
|
|
os.getenv("BRAIN_PATH") or os.path.expanduser("~/.gemini/antigravity/brain")
|
|
)
|
|
|
|
# Watcher settings
|
|
DEBOUNCE_SECONDS: float = float(os.getenv("DEBOUNCE_SECONDS", "5"))
|
|
|
|
# Files to monitor within each conversation directory (PRIMARY ONLY)
|
|
WATCHED_FILES: set = {
|
|
"task.md",
|
|
"implementation_plan.md",
|
|
"walkthrough.md",
|
|
}
|
|
|
|
# Extension-based monitoring: any file with these extensions in brain/{conv}/ is watched
|
|
WATCHED_EXTENSIONS: set = {".md"}
|
|
|
|
# Discord message limits
|
|
DISCORD_MSG_LIMIT: int = 2000
|
|
DISCORD_EMBED_DESC_LIMIT: int = 4096
|
|
|
|
# Channel naming
|
|
CHANNEL_PREFIX: str = "AG"
|
|
PROJECT_NAME: str = os.getenv("PROJECT_NAME", "gravity_control")
|
|
|
|
# Bot mode: 'local' (file-based bridge) or 'remote' (HTTP polling — future)
|
|
BOT_MODE: str = os.getenv("BOT_MODE", "local")
|
|
REMOTE_BRIDGE_URL: str = os.getenv("REMOTE_BRIDGE_URL", "")
|
|
GATEWAY_API_KEY: str = os.getenv("GATEWAY_API_KEY", "")
|
|
|
|
# WebSocket Hub
|
|
GRAVITY_HUB_SECRET: str = os.getenv("GRAVITY_HUB_SECRET", "") # JWT signing secret
|
|
GRAVITY_REGISTRATION_CODE: str = os.getenv("GRAVITY_REGISTRATION_CODE", "") # Extension auth
|
|
|
|
@classmethod
|
|
def validate(cls) -> list[str]:
|
|
"""Return list of configuration errors."""
|
|
errors = []
|
|
if not cls.DISCORD_TOKEN:
|
|
errors.append("DISCORD_TOKEN is not set")
|
|
if not cls.DISCORD_GUILD_ID:
|
|
errors.append("DISCORD_GUILD_ID is not set")
|
|
# Gateway mode doesn't need local BRAIN_PATH
|
|
if cls.BOT_MODE != 'gateway' and not cls.BRAIN_PATH.exists():
|
|
errors.append(f"BRAIN_PATH does not exist: {cls.BRAIN_PATH}")
|
|
return errors
|