16 KiB
16 KiB
配置文件规范
一、概述
1.1 配置文件定位
- 文件路径:
.aide/config.toml - 格式:TOML(Tom's Obvious, Minimal Language)
- 特点:自文档化,包含详细注释
- 创建时机:
aide init命令执行时
1.2 设计原则
- 自文档化:每个配置项都有注释说明
- 合理默认值:开箱即用,无需修改
- 类型安全:明确的数据类型
- 向后兼容:新版本保持旧配置可用
二、配置文件结构
2.1 完整示例
# Aide 项目配置文件
# 由 aide init 自动生成
# 版本: 1.0
[task]
# 任务原文档路径(prep 阶段使用)
source = "task-now.md"
# 任务细则文档路径(exec 阶段使用)
spec = "task-spec.md"
[env]
# 环境配置
[env.python]
# Python 版本要求(语义化版本)
version = ">=3.10"
# 虚拟环境路径(相对于项目根目录)
venv = ".venv"
[env.tools]
# 可选工具配置
# 是否需要 uv(Python 包管理器)
uv = false
# 是否需要 git
git = true
[flow]
# 流程追踪配置(后续实现)
# 环节列表
phases = ["flow-design", "impl", "verify", "docs", "finish"]
# PlantUML 流程图目录
flowchart_dir = "program_flowchart"
[decide]
# 待定项确认配置(后续实现)
# Web 服务端口
port = 3721
# 决策记录保存目录
decisions_dir = ".aide/decisions"
[output]
# 输出配置
# 是否启用颜色输出
color = true
# 输出语言(当前仅支持 zh-CN)
language = "zh-CN"
2.2 配置项说明
2.2.1 [task] 任务配置
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
source |
string | "task-now.md" |
任务原文档路径 |
spec |
string | "task-spec.md" |
任务细则文档路径 |
使用场景:
prep命令未传入参数时,使用task.sourceexec命令未传入参数时,使用task.spec
2.2.2 [env.python] Python 环境配置
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
version |
string | ">=3.10" |
Python 版本要求 |
venv |
string | ".venv" |
虚拟环境路径 |
版本格式:
">=3.10"- 大于等于 3.10">=3.10,<4.0"- 3.10 到 4.0 之间"3.12"- 精确匹配 3.12
2.2.3 [env.tools] 工具配置
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
uv |
boolean | false |
是否需要 uv |
git |
boolean | true |
是否需要 git |
2.2.4 [flow] 流程配置(后续实现)
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
phases |
array | ["flow-design", "impl", "verify", "docs", "finish"] |
环节列表 |
flowchart_dir |
string | "program_flowchart" |
流程图目录 |
2.2.5 [decide] 待定项配置(后续实现)
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
port |
integer | 3721 |
Web 服务端口 |
decisions_dir |
string | ".aide/decisions" |
决策记录目录 |
2.2.6 [output] 输出配置
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
color |
boolean | true |
是否启用颜色 |
language |
string | "zh-CN" |
输出语言 |
三、配置文件操作
3.1 读取配置
Python 实现示例:
import tomllib # Python 3.11+
# 或
import tomli # Python 3.10
from pathlib import Path
def load_config(project_root: Path) -> dict:
"""加载配置文件
Args:
project_root: 项目根目录
Returns:
配置字典
Raises:
FileNotFoundError: 配置文件不存在
tomllib.TOMLDecodeError: 配置文件格式错误
"""
config_path = project_root / ".aide" / "config.toml"
if not config_path.exists():
raise FileNotFoundError(f"配置文件不存在: {config_path}")
with open(config_path, "rb") as f:
return tomllib.load(f)
def get_config_value(config: dict, key: str, default=None):
"""获取配置值(支持点号分隔的键)
Args:
config: 配置字典
key: 配置键(如 "task.source")
default: 默认值
Returns:
配置值
Example:
>>> config = {"task": {"source": "task-now.md"}}
>>> get_config_value(config, "task.source")
'task-now.md'
"""
keys = key.split(".")
value = config
for k in keys:
if isinstance(value, dict) and k in value:
value = value[k]
else:
return default
return value
3.2 写入配置
Python 实现示例:
import tomli_w
from pathlib import Path
def save_config(project_root: Path, config: dict) -> None:
"""保存配置文件
Args:
project_root: 项目根目录
config: 配置字典
"""
config_path = project_root / ".aide" / "config.toml"
with open(config_path, "wb") as f:
tomli_w.dump(config, f)
def set_config_value(config: dict, key: str, value) -> dict:
"""设置配置值(支持点号分隔的键)
Args:
config: 配置字典
key: 配置键(如 "task.source")
value: 配置值
Returns:
更新后的配置字典
Example:
>>> config = {"task": {"source": "task-now.md"}}
>>> set_config_value(config, "task.source", "new-task.md")
{'task': {'source': 'new-task.md'}}
"""
keys = key.split(".")
current = config
# 导航到倒数第二层
for k in keys[:-1]:
if k not in current:
current[k] = {}
current = current[k]
# 设置最后一层的值
current[keys[-1]] = value
return config
3.3 验证配置
验证规则:
from typing import Any
def validate_config(config: dict) -> list[str]:
"""验证配置文件
Args:
config: 配置字典
Returns:
错误列表(空列表表示无错误)
"""
errors = []
# 验证必需的顶层键
required_sections = ["task", "env", "output"]
for section in required_sections:
if section not in config:
errors.append(f"缺少必需的配置节: [{section}]")
# 验证 task 配置
if "task" in config:
if "source" not in config["task"]:
errors.append("缺少配置项: task.source")
if "spec" not in config["task"]:
errors.append("缺少配置项: task.spec")
# 验证 env.python 配置
if "env" in config and "python" in config["env"]:
python_config = config["env"]["python"]
if "version" not in python_config:
errors.append("缺少配置项: env.python.version")
else:
# 验证版本格式
version = python_config["version"]
if not is_valid_version_spec(version):
errors.append(f"无效的版本格式: {version}")
# 验证 output 配置
if "output" in config:
output_config = config["output"]
if "language" in output_config:
lang = output_config["language"]
if lang not in ["zh-CN", "en-US"]:
errors.append(f"不支持的语言: {lang}")
return errors
def is_valid_version_spec(spec: str) -> bool:
"""验证版本规格字符串
Args:
spec: 版本规格(如 ">=3.10")
Returns:
是否有效
"""
import re
# 简化的版本规格验证
pattern = r'^(>=|<=|>|<|==)?\d+\.\d+(\.\d+)?$'
return bool(re.match(pattern, spec))
四、默认配置生成
4.1 生成逻辑
aide init 命令应该生成包含注释的默认配置:
def generate_default_config() -> str:
"""生成默认配置文件内容(带注释)
Returns:
TOML 格式的配置文件内容
"""
return '''# Aide 项目配置文件
# 由 aide init 自动生成
# 文档: https://github.com/your-org/aide
[task]
# 任务原文档路径(prep 阶段使用)
# 可通过 /aide:prep [路径] 覆盖
source = "task-now.md"
# 任务细则文档路径(exec 阶段使用)
# 可通过 /aide:exec [路径] 覆盖
spec = "task-spec.md"
[env]
# 环境配置
[env.python]
# Python 版本要求(语义化版本)
# 格式: ">=3.10" 或 ">=3.10,<4.0"
version = ">=3.10"
# 虚拟环境路径(相对于项目根目录)
venv = ".venv"
[env.tools]
# 可选工具配置
# 是否需要 uv(Python 包管理器)
uv = false
# 是否需要 git
git = true
[flow]
# 流程追踪配置(aide flow 命令使用)
# 环节列表(不建议修改)
phases = ["flow-design", "impl", "verify", "docs", "finish"]
# PlantUML 流程图目录
flowchart_dir = "program_flowchart"
[decide]
# 待定项确认配置(aide decide 命令使用)
# Web 服务端口
port = 3721
# 决策记录保存目录
decisions_dir = ".aide/decisions"
[output]
# 输出配置
# 是否启用颜色输出
# 可通过环境变量 NO_COLOR 禁用
color = true
# 输出语言(当前仅支持 zh-CN)
language = "zh-CN"
'''
4.2 配置文件创建流程
from pathlib import Path
def create_config_file(project_root: Path) -> bool:
"""创建配置文件
Args:
project_root: 项目根目录
Returns:
是否创建成功(False 表示文件已存在)
"""
aide_dir = project_root / ".aide"
config_path = aide_dir / "config.toml"
# 检查是否已存在
if config_path.exists():
return False
# 确保 .aide 目录存在
aide_dir.mkdir(exist_ok=True)
# 写入默认配置
config_content = generate_default_config()
config_path.write_text(config_content, encoding="utf-8")
return True
五、配置访问接口
5.1 Config 类设计
from pathlib import Path
from typing import Any, Optional
class Config:
"""配置管理类"""
def __init__(self, project_root: Path):
"""初始化配置
Args:
project_root: 项目根目录
"""
self.project_root = project_root
self.config_path = project_root / ".aide" / "config.toml"
self._config: Optional[dict] = None
def load(self) -> None:
"""加载配置文件"""
if not self.config_path.exists():
raise FileNotFoundError(f"配置文件不存在: {self.config_path}")
with open(self.config_path, "rb") as f:
self._config = tomllib.load(f)
def get(self, key: str, default: Any = None) -> Any:
"""获取配置值
Args:
key: 配置键(支持点号分隔)
default: 默认值
Returns:
配置值
"""
if self._config is None:
self.load()
return get_config_value(self._config, key, default)
def set(self, key: str, value: Any) -> None:
"""设置配置值
Args:
key: 配置键(支持点号分隔)
value: 配置值
"""
if self._config is None:
self.load()
set_config_value(self._config, key, value)
self.save()
def save(self) -> None:
"""保存配置文件"""
if self._config is None:
return
with open(self.config_path, "wb") as f:
tomli_w.dump(self._config, f)
def validate(self) -> list[str]:
"""验证配置
Returns:
错误列表
"""
if self._config is None:
self.load()
return validate_config(self._config)
5.2 使用示例
# 初始化配置
config = Config(Path.cwd())
# 获取配置值
task_source = config.get("task.source", "task-now.md")
python_version = config.get("env.python.version", ">=3.10")
# 设置配置值
config.set("task.source", "new-task.md")
config.set("env.python.version", ">=3.11")
# 验证配置
errors = config.validate()
if errors:
for error in errors:
print(f"✗ 配置错误: {error}")
六、配置迁移
6.1 版本兼容性
当配置文件格式升级时,需要提供迁移机制:
def migrate_config(config: dict, from_version: str, to_version: str) -> dict:
"""迁移配置文件
Args:
config: 旧配置
from_version: 源版本
to_version: 目标版本
Returns:
新配置
"""
if from_version == "1.0" and to_version == "1.1":
# 示例:添加新的配置项
if "output" not in config:
config["output"] = {
"color": True,
"language": "zh-CN"
}
return config
6.2 配置备份
修改配置前应该备份:
import shutil
from datetime import datetime
def backup_config(config_path: Path) -> Path:
"""备份配置文件
Args:
config_path: 配置文件路径
Returns:
备份文件路径
"""
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = config_path.with_suffix(f".toml.backup.{timestamp}")
shutil.copy2(config_path, backup_path)
return backup_path
七、错误处理
7.1 常见错误
| 错误类型 | 处理方式 |
|---|---|
| 配置文件不存在 | 提示使用 aide init 创建 |
| 配置文件格式错误 | 显示具体错误位置和原因 |
| 配置项缺失 | 使用默认值并警告 |
| 配置值类型错误 | 显示期望类型和实际类型 |
7.2 错误信息示例
def handle_config_error(error: Exception, config_path: Path) -> None:
"""处理配置错误
Args:
error: 异常对象
config_path: 配置文件路径
"""
if isinstance(error, FileNotFoundError):
err(
"配置文件不存在",
[
f"位置: {config_path}",
"建议: 运行 'aide init' 创建配置文件"
]
)
elif isinstance(error, tomllib.TOMLDecodeError):
err(
f"配置文件格式错误 (第{error.lineno}行)",
[
f"位置: {config_path}:{error.lineno}",
f"原因: {error.msg}",
"建议: 检查 TOML 语法,确保格式正确"
]
)
else:
err(
"配置文件读取失败",
[
f"位置: {config_path}",
f"原因: {str(error)}"
]
)
八、测试要求
8.1 测试用例
def test_load_config():
"""测试加载配置"""
# 创建测试配置
# 加载配置
# 验证配置内容
def test_get_config_value():
"""测试获取配置值"""
# 测试简单键
# 测试嵌套键
# 测试不存在的键
# 测试默认值
def test_set_config_value():
"""测试设置配置值"""
# 测试设置简单键
# 测试设置嵌套键
# 测试创建新键
def test_validate_config():
"""测试配置验证"""
# 测试有效配置
# 测试缺少必需项
# 测试无效值类型
# 测试无效版本格式
def test_config_migration():
"""测试配置迁移"""
# 测试版本升级
# 测试向后兼容
九、总结
9.1 核心要点
- 使用 TOML 格式,自文档化
- 提供合理的默认值
- 支持点号分隔的键访问
- 完善的错误处理和验证
- 配置迁移和备份机制
9.2 实现检查清单
- 实现配置文件读取(load_config)
- 实现配置文件写入(save_config)
- 实现配置值获取(get_config_value)
- 实现配置值设置(set_config_value)
- 实现配置验证(validate_config)
- 实现默认配置生成(generate_default_config)
- 实现 Config 类
- 编写配置测试用例
- 验证 TOML 格式正确性
版本:v1.0 更新日期:2025-12-13