d5fb159857
BottleRunner Protocol tightened: start() → str, freeze/resume/destroy → None. RunResult removed. lifecycle.py unpacks the slug directly. FakeRunner and test_runner updated to match. Config.bot_bottle_cli dropped (nothing uses it). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
"""Configuration, loaded from the environment (stdlib `os` only).
|
|
|
|
Everything the orchestrator needs to run is an env var so a deploy is a
|
|
process with an environment, no config file to manage. `FORGE_*` names
|
|
match the bot-bottle forge-native PRD.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
# The label that marks an issue as agent-targeted: `bot-bottle:<agent>`.
|
|
LABEL_PREFIX = "bot-bottle:"
|
|
# Optional bottle override: `bot-bottle-bottle:<name>`.
|
|
BOTTLE_LABEL_PREFIX = "bot-bottle-bottle:"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Config:
|
|
"""Resolved orchestrator configuration."""
|
|
|
|
forge_org: str
|
|
gitea_api: str
|
|
watchdog_timeout_secs: int
|
|
webhook_host: str
|
|
webhook_port: int
|
|
queue_dir: Path
|
|
sidecar_socket: Path
|
|
db_path: Path | None
|
|
|
|
@staticmethod
|
|
def from_env(env: dict[str, str] | None = None) -> "Config":
|
|
e = os.environ if env is None else env
|
|
home = Path(e.get("HOME", str(Path.home())))
|
|
default_root = home / ".bot-bottle"
|
|
db = e.get("FORGE_DB_PATH")
|
|
return Config(
|
|
forge_org=e.get("FORGE_ORG", "bot-bottle"),
|
|
gitea_api=e.get("FORGE_GITEA_API", ""),
|
|
watchdog_timeout_secs=int(e.get("FORGE_WATCHDOG_TIMEOUT", "1800")),
|
|
webhook_host=e.get("FORGE_WEBHOOK_HOST", "127.0.0.1"),
|
|
webhook_port=int(e.get("FORGE_WEBHOOK_PORT", "8477")),
|
|
queue_dir=Path(e.get("FORGE_QUEUE_DIR", str(default_root / "forge-queue"))),
|
|
sidecar_socket=Path(
|
|
e.get("FORGE_SIDECAR_SOCKET", str(default_root / "forge-sidecar.sock"))
|
|
),
|
|
db_path=Path(db) if db else None,
|
|
)
|