You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 04 最小复刻清单
目标:一个你能完全讲清楚的小 Agent,不是功能全集。
建议包名 / 命令:自己定,下文用 `myagent` 指代。
## 1. 目录骨架
```text
my-agent/
pyproject.toml
README.md
src/myagent/
__init__.py
cli.py # argparse:--model / --session
config.py # 读环境变量或用户目录 ini/yaml
llm.py # 只创建 ChatOpenAI(base_url, api_key, model)
prompt.py # 静态 system + 动态 cwd/tree
graph.py # StateGraph:llm_call / tool_node
tools/
fs.py # read_file, list_dir, replace_in_file
shell.py # execute_command + 确认回调
session.py # sqlite checkpointer
tests/
test_graph_smoke.py
test_path_sandbox.py
```
第一版**不要**:textual、mcp、skills、subagent、语音、多厂商。
## 2. 配置(最小)
环境变量即可:
```text
MYAGENT_API_KEY=...
MYAGENT_BASE_URL=https://api.agicto.cn/v1
MYAGENT_MODEL=deepseek-v4-flash
```
密钥只放用户目录或系统环境,禁止进 git。
## 3. 图的最小实现要点
```text
State = { messages, llm_calls }
START → llm_call → (有 tool_calls?)
是 → tool_node → llm_call
否 → END
```
硬性要求:
- 工具异常要变成 ToolMessage 文本,不能把整个图打崩
- 一轮多个 tool_calls 可以先串行,跑通再并行
- `thread_id` 用参数传入,默认 `default`
## 4. 工具验收
| 工具 | 必须有的约束 | 怎么测 |
|------|----------------|--------|
| read_file | 只能读 cwd 内;限制行数 | 读 `../` 应拒绝 |
| list_dir | 跳过 `.git` / `node_modules` / `.venv` | 在本项目根目录跑 |
| replace_in_file | old_text 必须唯一匹配 | 改一个函数名再读回来 |
| execute_command | 超时;打印命令等 y/N | 输入 `n` 应取消 |
## 5. CLI 体验(第一版足够)
```text
$ myagent
> 请总结当前目录 README
[think] ...
[tool] read_file README.md
[final] ...
> /clear
> /exit
```
没有气泡也没关系。日志清晰比好看重要。
## 6. 测试底线
- `test_path_sandbox.py`:逃出 cwd 失败
- `test_graph_smoke.py`:mock LLM 返回一次 tool_call 再返回纯文本,断言 tool 被调用、最终 END
没有 mock 测试,不要进入阶段 4。
## 7. 对照 Qoze 时允许借鉴的“形状”
可以借鉴:
- 两节点 ReAct 图
- 静态/动态 prompt 分离
- 文件路径沙箱
- checkpoint 的 thread_id 思路
不要复制:
- 整份 `system_prompt.py` 长文案
- Textual CSS 和像素 logo
- 十几个厂商的 `initialize_llm` 分支
- 被注释掉的浏览器工具堆
## 8. 完成定义(Definition of Done)
当下面全是“是”,阶段 3 才结束:
- [ ] 新仓库能独立 `pip install -e .` 跑起来
- [ ] 只用 DeepSeek 兼容接口
- [ ] 四件套工具都有单测或手工脚本
- [ ] 会话可恢复
- [ ] README 是你自己写的架构说明(不是拷来的)
- [ ] 你能不看代码画出数据流