Files
agent-aide/aide-program/docs/commands/env-redesign.md

397 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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) - 需更新