""" Agent 核心框架 定义 Command 和 Skill 的基础类和接口 支持 Claude Code 和 OpenCode """ import json import logging from abc import ABC, abstractmethod from dataclasses import dataclass, field, asdict from datetime import datetime from enum import Enum from typing import Dict, Any, List, Optional, Tuple class SkillType(Enum): """Skill 类型枚举""" READ = "read" # 读取操作 WRITE = "write" # 写入操作 ANALYZE = "analyze" # 分析操作 TRANSFORM = "transform" # 转换操作 INTEGRATE = "integrate" # 集成操作 @dataclass class SkillResult: """Skill 执行结果""" success: bool data: Optional[Any] = None error: Optional[str] = None message: str = "" timestamp: str = field(default_factory=lambda: datetime.now().isoformat()) def __post_init__(self) -> None: """Validate SkillResult consistency after initialization""" if not self.success and not self.error: raise ValueError("Failed results must include error message") if self.success and self.error: raise ValueError("Successful results should not include error message") def to_dict(self) -> Dict[str, Any]: """转换为字典""" return asdict(self) def to_json(self) -> str: """转换为 JSON 字符串""" return json.dumps(self.to_dict(), ensure_ascii=False, indent=2) @dataclass class CommandContext: """命令执行上下文""" command_name: str args: Dict[str, Any] = field(default_factory=dict) options: Dict[str, Any] = field(default_factory=dict) config: Optional[Dict[str, Any]] = None metadata: Dict[str, Any] = field(default_factory=dict) def to_dict(self) -> Dict[str, Any]: """转换为字典""" return asdict(self) class Skill(ABC): """Skill 基础类""" def __init__(self, name: str, skill_type: SkillType, description: str = "") -> None: """ 初始化 Skill Args: name: Skill 名称 skill_type: Skill 类型 description: Skill 描述 """ self.name = name self.skill_type = skill_type self.description = description self.logger = logging.getLogger(f"Skill.{name}") @abstractmethod async def execute(self, context: CommandContext, **kwargs: Any) -> SkillResult: """ 执行 Skill Args: context: 命令执行上下文 **kwargs: 额外参数 Returns: SkillResult: 执行结果 """ pass def get_info(self) -> Dict[str, Any]: """获取 Skill 信息""" return { "name": self.name, "type": self.skill_type.value, "description": self.description, } class SkillChain: """Skill 链 - 用于按顺序执行多个 Skill""" def __init__(self, name: str, description: str = "") -> None: """ 初始化 Skill 链 Args: name: 链名称 description: 链描述 """ self.name = name self.description = description self.skills: List[Tuple[Skill, Dict[str, Any]]] = [] self.logger = logging.getLogger(f"SkillChain.{name}") def add_skill( self, skill: Skill, params: Optional[Dict[str, Any]] = None ) -> "SkillChain": """ 添加 Skill 到链中 Args: skill: 要添加的 Skill params: Skill 参数 Returns: self 用于链式调用 """ self.skills.append((skill, params or {})) return self async def execute(self, context: CommandContext) -> SkillResult: """ 执行 Skill 链 Args: context: 命令执行上下文 Returns: SkillResult: 最后一个 Skill 的结果 """ result: Optional[SkillResult] = None for skill, params in self.skills: try: self.logger.info(f"执行 Skill: {skill.name}") result = await skill.execute(context, **params) if not result.success: self.logger.error(f"Skill {skill.name} 执行失败: {result.error}") return result # 将结果传递给下一个 Skill if result.data: context.metadata[f"{skill.name}_result"] = result.data except Exception as e: self.logger.error(f"执行 Skill {skill.name} 时出错: {str(e)}") return SkillResult( success=False, error=str(e), message=f"Skill {skill.name} 执行异常" ) return result or SkillResult(success=True, message="Skill 链执行完成") def get_info(self) -> Dict[str, Any]: """获取 Skill 链信息""" return { "name": self.name, "description": self.description, "skills": [skill.get_info() for skill, _ in self.skills], } class Command(ABC): """Command 基础类""" def __init__( self, name: str, description: str = "", aliases: Optional[List[str]] = None ) -> None: """ 初始化 Command Args: name: 命令名称 description: 命令描述 aliases: 命令别名 """ self.name = name self.description = description self.aliases = aliases or [] self.skills: Dict[str, Skill] = {} self.skill_chains: Dict[str, SkillChain] = {} self.logger = logging.getLogger(f"Command.{name}") def register_skill(self, skill: Skill) -> "Command": """ 注册 Skill Args: skill: 要注册的 Skill Returns: self 用于链式调用 """ self.skills[skill.name] = skill return self def register_skill_chain(self, chain: SkillChain) -> "Command": """ 注册 Skill 链 Args: chain: 要注册的 Skill 链 Returns: self 用于链式调用 """ self.skill_chains[chain.name] = chain return self @abstractmethod async def execute(self, context: CommandContext) -> SkillResult: """ 执行命令 Args: context: 命令执行上下文 Returns: SkillResult: 执行结果 """ pass def get_info(self) -> Dict[str, Any]: """获取命令信息""" return { "name": self.name, "description": self.description, "aliases": self.aliases, "skills": {name: skill.get_info() for name, skill in self.skills.items()}, "skill_chains": { name: chain.get_info() for name, chain in self.skill_chains.items() }, } class Agent: """Agent 核心类""" def __init__(self, name: str, config: Optional[Dict[str, Any]] = None) -> None: """ 初始化 Agent Args: name: Agent 名称 config: 配置字典 """ self.name = name self.config = config or {} self.commands: Dict[str, Command] = {} self.command_aliases: Dict[str, str] = {} self.logger = logging.getLogger(f"Agent.{name}") self._setup_logging() def _setup_logging(self) -> None: """设置日志""" log_level = self.config.get("log_level", "INFO") logging.basicConfig( level=getattr(logging, log_level), format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) def register_command(self, command: Command) -> "Agent": """ 注册命令 Args: command: 要注册的命令 Returns: self 用于链式调用 """ self.commands[command.name] = command # 注册别名 for alias in command.aliases: self.command_aliases[alias] = command.name self.logger.info(f"注册命令: {command.name}") return self async def execute_command( self, command_name: str, args: Optional[Dict[str, Any]] = None, options: Optional[Dict[str, Any]] = None, ) -> SkillResult: """ 执行命令 Args: command_name: 命令名称或别名 args: 命令参数 options: 命令选项 Returns: SkillResult: 执行结果 """ # 解析命令名称(处理别名) actual_command_name = self.command_aliases.get(command_name, command_name) if actual_command_name not in self.commands: return SkillResult( success=False, error=f"未知命令: {command_name}", message=f"命令 '{command_name}' 不存在", ) command = self.commands[actual_command_name] context = CommandContext( command_name=actual_command_name, args=args or {}, options=options or {}, config=self.config, ) self.logger.info(f"执行命令: {actual_command_name}, 参数: {args}, 选项: {options}") try: result = await command.execute(context) self.logger.info(f"命令 {actual_command_name} 执行完成: {result.success}") return result except Exception as e: self.logger.error(f"执行命令 {actual_command_name} 时出错: {str(e)}") return SkillResult(success=False, error=str(e), message=f"命令执行异常: {str(e)}") def get_commands_info(self) -> Dict[str, Any]: """获取所有命令信息""" return { "agent_name": self.name, "commands": {name: cmd.get_info() for name, cmd in self.commands.items()}, "aliases": self.command_aliases, } def list_commands(self) -> List[str]: """列出所有可用命令""" return list(self.commands.keys())