mnemo_cards/tools/agent/config.py

135 lines
4.6 KiB
Python
Raw Permalink Normal View History

2025-11-20 21:28:55 +00:00
"""
Configuration module for AI Agent system.
"""
import os
from dataclasses import dataclass
from pathlib import Path
from typing import Optional
@dataclass
class AgentConfig:
"""Configuration for AI agent execution."""
# Project paths
project_root: Path
component: str # 'web_v2', 'backend', 'common'
# Agent limits
max_iterations: int = 10
2025-11-20 23:05:04 +00:00
max_retries: int = 5
2025-11-20 21:28:55 +00:00
timeout_hours: int = 6
# Cursor CLI settings
cursor_api_key: Optional[str] = None
cursor_model: str = "claude-3-5-sonnet-20241022"
2025-11-21 11:13:03 +00:00
# Forgejo/GitHub API settings
forgejo_token: Optional[str] = None
forgejo_api_url: Optional[str] = None # Will be auto-detected from git remote
forgejo_repo: Optional[str] = None # Will be auto-detected from git remote
# Commit mode: 'master' (direct commit with PR fallback) or 'pr' (always create PR)
commit_mode: str = "master"
2025-11-20 21:28:55 +00:00
# State file paths
@property
def agent_dir(self) -> Path:
return self.project_root / "ai_docs" / "agent" / self.component
@property
def task_list_path(self) -> Path:
return self.agent_dir / "task_list.json"
@property
def agent_state_path(self) -> Path:
return self.agent_dir / "agent_state.json"
@property
def global_lock_path(self) -> Path:
return self.project_root / "ai_docs" / "agent" / "global_lock.json"
@property
def prompts_dir(self) -> Path:
return self.project_root / "ai_docs" / "agent" / "prompts"
@property
def component_root(self) -> Path:
"""Root directory of the component being worked on."""
if self.component == "web_v2":
return self.project_root / "mnemo_cards_web_v2"
elif self.component == "backend":
return self.project_root / "mnemo_cards_backend"
elif self.component == "common":
return self.project_root / "mnemo_cards_common"
else:
raise ValueError(f"Unknown component: {self.component}")
@classmethod
def from_env(cls, component: str) -> "AgentConfig":
"""Create configuration from environment variables."""
project_root = Path(os.getenv("PROJECT_ROOT", os.getcwd()))
return cls(
project_root=project_root,
component=component,
max_iterations=int(os.getenv("MAX_ITERATIONS", "10")),
max_retries=int(os.getenv("MAX_RETRIES", "3")),
timeout_hours=int(os.getenv("TIMEOUT_HOURS", "6")),
cursor_api_key=os.getenv("CURSOR_API_KEY"),
2025-11-21 11:50:00 +00:00
cursor_model=os.getenv("CURSOR_MODEL", "auto"),
2025-11-21 11:13:03 +00:00
forgejo_token=os.getenv("FORGEJO_TOKEN"),
forgejo_api_url=os.getenv("FORGEJO_API_URL") or os.getenv("GITHUB_API_URL"),
commit_mode=os.getenv("COMMIT_MODE", "master"),
2025-11-20 21:28:55 +00:00
)
def validate(self) -> None:
"""Validate configuration."""
if not self.project_root.exists():
raise ValueError(f"Project root does not exist: {self.project_root}")
if not self.cursor_api_key:
raise ValueError("CURSOR_API_KEY environment variable is required")
if self.component not in ["web_v2", "backend", "common"]:
raise ValueError(f"Invalid component: {self.component}")
if not self.component_root.exists():
raise ValueError(f"Component root does not exist: {self.component_root}")
# Component-specific configurations
COMPONENT_CONFIGS = {
"web_v2": {
"test_command": "cd mnemo_cards_web_v2 && flutter test",
"lint_command": "cd mnemo_cards_web_v2 && flutter analyze",
"build_command": "cd mnemo_cards_web_v2 && flutter build web",
},
"backend": {
"test_command": "cd mnemo_cards_backend && dart test",
"lint_command": "cd mnemo_cards_backend && dart analyze",
"build_command": "cd mnemo_cards_backend && dart compile exe bin/server.dart",
},
"common": {
"test_command": "cd mnemo_cards_common && dart test",
"lint_command": "cd mnemo_cards_common && dart analyze",
"build_command": None, # No build for common package
},
}
def get_test_command(component: str) -> str:
"""Get test command for component."""
return COMPONENT_CONFIGS[component]["test_command"]
def get_lint_command(component: str) -> str:
"""Get lint command for component."""
return COMPONENT_CONFIGS[component]["lint_command"]
def get_build_command(component: str) -> Optional[str]:
"""Get build command for component."""
return COMPONENT_CONFIGS[component]["build_command"]