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

16
statements/2.md Normal file
View File

@@ -0,0 +1,16 @@
1. 用--modules
2. 扁平结构
3. 作为独立模块默认启用因为有可能后续项目稳定后会把所有程序编译为无需额外环境依赖的二进制可执行文件甚至是使用rust重写程序
4. 参数用逗号分隔
我的新想法:
1. 弃用check仅保留ensure
- 因为不论是有明确的配置文件指定了具体环境模块配置的情况,
- 或者是单独使用模块参数忽略掉配置是否启用,
- 都说明有明确的对指定模块的使用意图,
- 我希望只要执行了就默认为预期是目标环境可用,
- 所以仅保留ensure若检测到不可用就自动尝试修复修复成功后可用正常输出反馈告知LLM环境可用即可
2. 但是使用list时依然显示其模块能力情况有些模块可能没办法支持ensure
3. 只有使用--all选项时不进行ensure操作仅检测
- 使用all时对所有已启用的模块仅执行check操作报告其可用性

10
statements/3.md Normal file
View File

@@ -0,0 +1,10 @@
1. 默认all的范围是所有配置文件中已配置为启用的模块
- 若环境配置文件中没有配置启用列表则输出警告然后对所有aid env支持的可用模块进行检测即使环境配置文件中没有任何相关配置
- 若环境配置文件中设置了启用列表想要对所有模块进行检测就必须先用list获取支持的模型的信息然后用指定模块列表参数执行检测
2. 若模块ensure失败或是仅支持check无法ensure却检测到环境不可用
- 如果该模块是环境配置文件中指定了启用的模块,输出错误,应停下并报告用户需要解决环境问题
- 如果是没有在启用列表中的不论是all参数还是指定模块参数触发的都只输出警告信息
3. 使用指定模块参数时,不需要考虑是否配置启用,都执行即可(不过输出的是警告还是错误取决于是否启用)
- 所以环境检测模块要考虑到仅有自己的模块名可知的情况,真实配置不可知全靠检测,
- 比如gcc、java、python、flutter、android这样的看命令是否可用还有一些相关的环境变量是否已正确配置即可
- 但如果是py的虚拟环境这种必须指定虚拟环境目录路径的nodejs这种要先在工作目录有些项目中需要运行npm但不在项目根目录而是在某个子目录下此时没有具体目录路径无法检测做了npm install有了node_modules才能正常运行的在没有具体配置数据指该模块独立配置数据例如[env.venv]而非该模块是否启用但指定了其模块进行check/ensure时应输出警告然后不执行检测等任何其他该模块行为