Files
evotraders/backend/agents/agent_workspace.py
2026-03-30 17:46:44 +08:00

76 lines
2.2 KiB
Python

# -*- coding: utf-8 -*-
"""Per-agent run-scoped workspace configuration helpers."""
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Dict, List, Optional
import yaml
@dataclass(frozen=True)
class AgentWorkspaceConfig:
"""Structured agent config loaded from runs/<config>/agents/<agent>/agent.yaml."""
values: Dict[str, Any] = field(default_factory=dict)
@property
def prompt_files(self) -> Optional[List[str]]:
raw = self.values.get("prompt_files")
if not isinstance(raw, list):
return None
files = [
str(item).strip()
for item in raw
if isinstance(item, str) and str(item).strip()
]
return files or None
@property
def enabled_skills(self) -> List[str]:
return _normalized_string_list(self.values.get("enabled_skills"))
@property
def disabled_skills(self) -> List[str]:
return _normalized_string_list(self.values.get("disabled_skills"))
@property
def active_tool_groups(self) -> Optional[List[str]]:
groups = _normalized_string_list(self.values.get("active_tool_groups"))
return groups or None
@property
def disabled_tool_groups(self) -> List[str]:
return _normalized_string_list(self.values.get("disabled_tool_groups"))
def get(self, key: str, default: Any = None) -> Any:
return self.values.get(key, default)
def _normalized_string_list(raw: Any) -> List[str]:
if not isinstance(raw, list):
return []
seen: List[str] = []
for item in raw:
if not isinstance(item, str):
continue
value = item.strip()
if value and value not in seen:
seen.append(value)
return seen
def load_agent_workspace_config(path: Path) -> AgentWorkspaceConfig:
"""Load agent.yaml if present."""
if not path.exists() or not path.is_file():
return AgentWorkspaceConfig()
raw = path.read_text(encoding="utf-8").strip()
if not raw:
return AgentWorkspaceConfig()
parsed = yaml.safe_load(raw) or {}
if not isinstance(parsed, dict):
parsed = {}
return AgentWorkspaceConfig(values=parsed)