config.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. """配置管理 - Code Agent CLI 统一配置"""
  2. import os
  3. from typing import Optional, Dict, Any, List
  4. from pathlib import Path
  5. from pydantic import BaseModel, Field
  6. class Config(BaseModel):
  7. """Code Agent CLI 统一配置类
  8. 集中管理所有配置项,支持:
  9. - 环境变量加载
  10. - 默认值设置
  11. - 类型验证
  12. """
  13. # ==================== 基础配置 ====================
  14. project_name: str = Field(default="code_agent", description="项目名称")
  15. debug: bool = Field(default=False, description="调试模式")
  16. log_level: str = Field(default="INFO", description="日志级别")
  17. # ==================== LLM 配置 ====================
  18. default_model: str = Field(default="gpt-3.5-turbo", description="默认模型")
  19. default_provider: str = Field(default="openai", description="默认提供商")
  20. temperature: float = Field(default=0.7, ge=0.0, le=2.0, description="温度参数")
  21. max_tokens: Optional[int] = Field(default=None, description="最大 token 数")
  22. llm_timeout: int = Field(default=60, gt=0, description="LLM 请求超时(秒)")
  23. # ==================== Agent 配置 ====================
  24. max_react_steps: int = Field(default=20, gt=0, le=50, description="ReAct 最大步数")
  25. max_history_turns: int = Field(default=50, gt=0, description="最大历史对话轮数")
  26. observation_summary_threshold: int = Field(default=2000, gt=0, description="工具输出摘要阈值")
  27. # ==================== 上下文配置 ====================
  28. context_max_tokens: int = Field(default=8000, gt=0, description="上下文最大 token 数")
  29. context_reserve_ratio: float = Field(default=0.15, ge=0.0, le=0.5, description="生成预留比例")
  30. context_enable_compression: bool = Field(default=True, description="启用上下文压缩")
  31. context_lazy_fetch: bool = Field(default=True, description="按需获取上下文")
  32. # ==================== 工具配置 ====================
  33. terminal_timeout: int = Field(default=60, gt=0, description="终端命令超时(秒)")
  34. terminal_max_output_size: int = Field(default=10 * 1024 * 1024, gt=0, description="终端输出最大大小")
  35. terminal_confirm_dangerous: bool = Field(default=True, description="危险命令需要确认")
  36. terminal_allow_shell_mode: bool = Field(default=True, description="允许 Shell 模式")
  37. context_fetch_max_tokens: int = Field(default=800, gt=0, description="单个数据源最大 token")
  38. context_fetch_context_lines: int = Field(default=5, ge=0, description="代码上下文行数")
  39. # ==================== 补丁执行器配置 ====================
  40. patch_max_files: int = Field(default=10, gt=0, description="单个补丁最大文件数")
  41. patch_max_total_lines: int = Field(default=800, gt=0, description="单个补丁最大总行数")
  42. patch_allowed_suffixes: List[str] = Field(
  43. default=[".py", ".md", ".toml", ".json", ".yml", ".yaml", ".txt", ".html", ".css", ".js", ".ts"],
  44. description="允许修改的文件后缀"
  45. )
  46. # ==================== 存储配置 ====================
  47. helloagents_dir: str = Field(default=".helloagents", description="状态存储目录")
  48. # ==================== 安全配置 ====================
  49. confirm_delete_files: bool = Field(default=True, description="删除文件需要确认")
  50. confirm_large_changes: bool = Field(default=True, description="大规模变更需要确认")
  51. large_change_threshold_files: int = Field(default=6, gt=0, description="大规模变更文件数阈值")
  52. large_change_threshold_lines: int = Field(default=400, gt=0, description="大规模变更行数阈值")
  53. @classmethod
  54. def from_env(cls, **overrides) -> "Config":
  55. """从环境变量创建配置
  56. 环境变量命名规则:
  57. - CODE_AGENT_<配置项大写> 或传统命名
  58. Args:
  59. **overrides: 手动覆盖的配置项
  60. """
  61. env_config = {
  62. "debug": os.getenv("DEBUG", "false").lower() == "true" or os.getenv("CODE_AGENT_DEBUG", "false").lower() == "true",
  63. "log_level": os.getenv("LOG_LEVEL", "INFO"),
  64. "temperature": float(os.getenv("TEMPERATURE", "0.7")),
  65. "helloagents_dir": os.getenv("HELLOAGENTS_DIR", os.getenv("CODE_AGENT_STATE_DIR", ".helloagents")),
  66. "max_react_steps": int(os.getenv("CODE_AGENT_MAX_REACT_STEPS", os.getenv("CODE_AGENT_MAX_STEPS", "20"))),
  67. "llm_timeout": int(os.getenv("LLM_TIMEOUT", "60")),
  68. "terminal_timeout": int(os.getenv("CODE_AGENT_TERMINAL_TIMEOUT", "60")),
  69. "patch_max_files": int(os.getenv("CODE_AGENT_PATCH_MAX_FILES", "10")),
  70. "patch_max_total_lines": int(os.getenv("CODE_AGENT_PATCH_MAX_LINES", "800")),
  71. }
  72. if os.getenv("MAX_TOKENS"):
  73. env_config["max_tokens"] = int(os.getenv("MAX_TOKENS"))
  74. # 合并覆盖配置
  75. env_config.update(overrides)
  76. return cls(**env_config)
  77. def get_state_dir(self, repo_root: Path) -> Path:
  78. """获取状态存储目录的绝对路径"""
  79. state_path = Path(self.helloagents_dir)
  80. if state_path.is_absolute():
  81. return state_path
  82. return repo_root / state_path
  83. def get_notes_dir(self, repo_root: Path) -> Path:
  84. """获取笔记目录"""
  85. return self.get_state_dir(repo_root) / "notes"
  86. def get_sessions_dir(self, repo_root: Path) -> Path:
  87. """获取会话目录"""
  88. return self.get_state_dir(repo_root) / "sessions"
  89. def get_backups_dir(self, repo_root: Path) -> Path:
  90. """获取备份目录"""
  91. return self.get_state_dir(repo_root) / "backups"
  92. def get_todos_dir(self, repo_root: Path) -> Path:
  93. """获取待办目录"""
  94. return self.get_state_dir(repo_root) / "todos"
  95. def to_dict(self) -> Dict[str, Any]:
  96. """转换为字典"""
  97. return self.dict()
  98. def print_summary(self):
  99. """打印配置摘要"""
  100. print("=" * 50)
  101. print("Code Agent CLI 配置")
  102. print("=" * 50)
  103. print(f"调试模式: {self.debug}")
  104. print(f"ReAct 步数: {self.max_react_steps}")
  105. print(f"历史轮数: {self.max_history_turns}")
  106. print(f"终端超时: {self.terminal_timeout}s")
  107. print(f"补丁限制: {self.patch_max_files} 文件, {self.patch_max_total_lines} 行")
  108. print(f"状态目录: {self.helloagents_dir}")
  109. print("=" * 50)