📃 docs: 完成重设计,准备开始实现新env

This commit is contained in:
2025-12-14 04:41:26 +08:00
parent 9f44d87544
commit e68eeb7e46
3 changed files with 422 additions and 0 deletions

View File

@@ -0,0 +1,396 @@
# aide env 重新设计 - 实现计划
## 一、设计概要
### 1.1 命令结构
```
aide env # 等同于 aide env ensure
aide env ensure [options] # 检测并修复
aide env list # 列出所有可用模块
```
### 1.2 参数
| 参数 | 说明 |
|------|------|
| `--runtime` | 仅检测 aide 运行时环境python + uv |
| `--modules M1,M2` | 指定要检测的模块(逗号分隔) |
| `--all` | 检测所有已启用模块,仅检查不修复 |
### 1.3 模块分类
**类型A自包含模块无需配置即可检测**
- python, uv, java, go, rust, gcc, cmake, node, flutter
**类型B路径依赖模块必须有配置才能检测**
- venv, requirements, npm
---
## 二、目录结构变更
```
aide-program/aide/
├── __init__.py
├── __main__.py
├── main.py # [修改] 更新 CLI 路由
├── core/
│ ├── __init__.py
│ ├── config.py # [修改] 更新默认配置
│ └── output.py
└── env/
├── __init__.py
├── ensure.py # [删除] 旧实现
├── manager.py # [新建] 环境管理器主入口
├── registry.py # [新建] 模块注册表
└── modules/ # [新建] 模块目录
├── __init__.py
├── base.py # [新建] 模块基类
├── python.py # [新建] Python 模块
├── uv.py # [新建] uv 模块
├── venv.py # [新建] venv 模块
├── requirements.py # [新建] requirements 模块
├── node.py # [新建] Node.js 模块
├── npm.py # [新建] npm 模块
└── ... # 其他模块按需添加
```
---
## 三、配置文件变更
### 3.1 新默认配置
```toml
# Aide 默认配置(由 aide init 生成)
[runtime]
python_min = "3.11"
use_uv = true
[task]
source = "task-now.md"
spec = "task-spec.md"
[env]
# 启用的模块列表
modules = ["python", "uv", "venv", "requirements"]
# 类型A模块配置可选指定版本要求
[env.python]
min_version = "3.11"
# 类型B模块配置必需指定路径
[env.venv]
path = ".venv"
[env.requirements]
path = "requirements.txt"
[flow]
phases = ["task-optimize", "flow-design", "impl", "verify", "docs", "finish"]
```
### 3.2 配置兼容性
旧配置格式:
```toml
[env]
venv = ".venv"
requirements = "requirements.txt"
```
新配置格式:
```toml
[env]
modules = ["python", "uv", "venv", "requirements"]
[env.venv]
path = ".venv"
[env.requirements]
path = "requirements.txt"
```
**迁移策略**:读取时兼容旧格式,写入时使用新格式。
---
## 四、核心类设计
### 4.1 模块基类 (`env/modules/base.py`)
```python
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any
from pathlib import Path
@dataclass
class CheckResult:
"""检测结果"""
success: bool
version: str | None = None
message: str | None = None
can_ensure: bool = False # 失败时是否可修复
@dataclass
class ModuleInfo:
"""模块元信息"""
name: str
description: str
capabilities: list[str] # ["check"] 或 ["check", "ensure"]
requires_config: bool # 是否需要配置类型B
config_keys: list[str] # 需要的配置键,如 ["path"]
class BaseModule(ABC):
"""模块基类"""
@property
@abstractmethod
def info(self) -> ModuleInfo:
"""返回模块元信息"""
pass
@abstractmethod
def check(self, config: dict[str, Any], root: Path) -> CheckResult:
"""检测环境"""
pass
def ensure(self, config: dict[str, Any], root: Path) -> CheckResult:
"""修复环境(可选实现)"""
return CheckResult(
success=False,
message="此模块不支持自动修复"
)
```
### 4.2 模块注册表 (`env/registry.py`)
```python
from aide.env.modules.base import BaseModule, ModuleInfo
class ModuleRegistry:
"""模块注册表"""
_modules: dict[str, BaseModule] = {}
@classmethod
def register(cls, module: BaseModule) -> None:
cls._modules[module.info.name] = module
@classmethod
def get(cls, name: str) -> BaseModule | None:
return cls._modules.get(name)
@classmethod
def all(cls) -> dict[str, BaseModule]:
return cls._modules.copy()
@classmethod
def list_info(cls) -> list[ModuleInfo]:
return [m.info for m in cls._modules.values()]
# 自动注册所有模块
def _auto_register():
from aide.env.modules import python, uv, venv, requirements, node, npm
# 每个模块文件导出一个 module 实例
for mod in [python, uv, venv, requirements, node, npm]:
if hasattr(mod, 'module'):
ModuleRegistry.register(mod.module)
_auto_register()
```
### 4.3 环境管理器 (`env/manager.py`)
```python
from pathlib import Path
from typing import Any
from aide.core import output
from aide.core.config import ConfigManager
from aide.env.registry import ModuleRegistry
from aide.env.modules.base import CheckResult
class EnvManager:
"""环境管理器"""
def __init__(self, root: Path, cfg: ConfigManager):
self.root = root
self.cfg = cfg
def list_modules(self) -> None:
"""列出所有可用模块"""
# 实现 aide env list
pass
def ensure(
self,
runtime_only: bool = False,
modules: list[str] | None = None,
check_only: bool = False, # --all 时为 True
) -> bool:
"""检测并修复环境"""
# 主逻辑实现
pass
def _get_enabled_modules(self) -> list[str]:
"""获取已启用的模块列表"""
pass
def _get_module_config(self, name: str) -> dict[str, Any]:
"""获取模块配置"""
pass
def _check_module(self, name: str, is_enabled: bool) -> tuple[bool, CheckResult]:
"""检测单个模块"""
pass
def _ensure_module(self, name: str, is_enabled: bool) -> tuple[bool, CheckResult]:
"""检测并修复单个模块"""
pass
```
---
## 五、执行逻辑详解
### 5.1 `aide env ensure` 流程
```
1. 读取配置
2. 获取 modules 列表(已启用模块)
3. 对每个模块:
a. 获取模块实例
b. 获取模块配置
c. 检查类型B模块是否有必需配置
- 已启用 + 无配置 → ✗ 错误,停止
- 未启用 + 无配置 → ⚠ 警告,跳过
d. 执行 check()
e. 如果失败且可修复:执行 ensure()
f. 根据启用状态决定输出级别
4. 输出最终状态
```
### 5.2 `aide env ensure --all` 流程
```
1. 读取配置
2. 获取 modules 列表
- 有列表 → 使用列表
- 无列表 → ⚠ 警告 + 使用所有已注册模块
3. 对每个模块:
a. 仅执行 check()(不修复)
b. 输出检测结果
4. 输出汇总
```
### 5.3 `aide env ensure --modules X,Y` 流程
```
1. 解析指定的模块列表
2. 读取配置,获取已启用列表
3. 对每个指定模块:
a. 判断是否在启用列表中
b. 检查类型B模块配置
c. 执行 check() + ensure()
d. 根据启用状态决定输出级别
4. 输出最终状态
```
---
## 六、输出级别规则
| 场景 | 在启用列表 | 有配置 | 结果 | 输出 | 行为 |
|------|-----------|--------|------|------|------|
| ensure | ✓ | ✓/NA | 成功 | ✓ | 继续 |
| ensure | ✓ | ✓/NA | 失败+可修复 | → | 修复 |
| ensure | ✓ | ✓/NA | 失败+不可修复 | ✗ | **停止** |
| ensure | ✓ | ✗(B类) | - | ✗ | **停止** |
| --modules | ✗ | ✓/NA | 成功 | ✓ | 继续 |
| --modules | ✗ | ✓/NA | 失败 | ⚠ | 继续 |
| --modules | ✗ | ✗(B类) | - | ⚠ | 跳过 |
| --all | any | any | any | ✓/⚠ | 仅检测 |
---
## 七、实现步骤
### 阶段1基础架构
1. 创建 `env/modules/` 目录结构
2. 实现 `base.py` 模块基类
3. 实现 `registry.py` 模块注册表
4. 更新 `core/config.py` 默认配置
### 阶段2核心模块实现
5. 实现 `python.py` 模块
6. 实现 `uv.py` 模块
7. 实现 `venv.py` 模块
8. 实现 `requirements.py` 模块
### 阶段3管理器与 CLI
9. 实现 `manager.py` 环境管理器
10. 更新 `main.py` CLI 路由
11. 删除旧的 `ensure.py`
### 阶段4扩展模块可选
12. 实现 `node.py` 模块
13. 实现 `npm.py` 模块
14. 其他模块按需添加
### 阶段5文档与测试
15. 更新 `docs/commands/env.md` 设计文档
16. 更新 `docs/formats/config.md` 配置文档
17. 添加测试用例
---
## 八、向后兼容
### 8.1 命令兼容
| 旧命令 | 新行为 |
|--------|--------|
| `aide env ensure` | 保持不变 |
| `aide env ensure --runtime` | 保持不变 |
### 8.2 配置兼容
读取配置时检测旧格式并转换:
```python
def _migrate_config(config: dict) -> dict:
"""兼容旧配置格式"""
env = config.get("env", {})
# 如果没有 modules 字段,使用默认值
if "modules" not in env:
env["modules"] = ["python", "uv", "venv", "requirements"]
# 如果使用旧的 venv/requirements 字段
if "venv" in env and not isinstance(env["venv"], dict):
old_venv = env.pop("venv")
env.setdefault("venv", {})["path"] = old_venv
if "requirements" in env and not isinstance(env["requirements"], dict):
old_req = env.pop("requirements")
env.setdefault("requirements", {})["path"] = old_req
return config
```
---
## 九、相关文档
- [aide env 设计文档](./env.md) - 需更新
- [配置格式文档](../formats/config.md) - 需更新
- [aide skill 设计文档](../../../aide-marketplace/aide-plugin/docs/skill/aide.md) - 需更新