weijie-codeagent 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- weijie_codeagent-0.1.0/.env.example +10 -0
- weijie_codeagent-0.1.0/.gitignore +40 -0
- weijie_codeagent-0.1.0/PKG-INFO +243 -0
- weijie_codeagent-0.1.0/README.md +212 -0
- weijie_codeagent-0.1.0/codeagent/__init__.py +2 -0
- weijie_codeagent-0.1.0/codeagent/config.py +79 -0
- weijie_codeagent-0.1.0/codeagent/graph/__init__.py +0 -0
- weijie_codeagent-0.1.0/codeagent/graph/builder.py +77 -0
- weijie_codeagent-0.1.0/codeagent/graph/nodes/__init__.py +0 -0
- weijie_codeagent-0.1.0/codeagent/graph/nodes/code_agent.py +152 -0
- weijie_codeagent-0.1.0/codeagent/graph/nodes/context_loader.py +45 -0
- weijie_codeagent-0.1.0/codeagent/graph/nodes/context_qa.py +72 -0
- weijie_codeagent-0.1.0/codeagent/graph/nodes/intent_router.py +66 -0
- weijie_codeagent-0.1.0/codeagent/graph/nodes/memory_writer.py +71 -0
- weijie_codeagent-0.1.0/codeagent/graph/nodes/reflection.py +82 -0
- weijie_codeagent-0.1.0/codeagent/graph/nodes/task_decomposer.py +177 -0
- weijie_codeagent-0.1.0/codeagent/graph/state.py +36 -0
- weijie_codeagent-0.1.0/codeagent/main.py +365 -0
- weijie_codeagent-0.1.0/codeagent/memory/__init__.py +0 -0
- weijie_codeagent-0.1.0/codeagent/memory/compressor.py +74 -0
- weijie_codeagent-0.1.0/codeagent/memory/long_term.py +122 -0
- weijie_codeagent-0.1.0/codeagent/memory/short_term.py +28 -0
- weijie_codeagent-0.1.0/codeagent/memory/vector_store.py +164 -0
- weijie_codeagent-0.1.0/codeagent/tools/__init__.py +33 -0
- weijie_codeagent-0.1.0/codeagent/tools/code_tools.py +57 -0
- weijie_codeagent-0.1.0/codeagent/tools/edit_tools.py +231 -0
- weijie_codeagent-0.1.0/codeagent/tools/file_tools.py +75 -0
- weijie_codeagent-0.1.0/codeagent/tools/mcp_tools.py +129 -0
- weijie_codeagent-0.1.0/codeagent/tools/search_tools.py +163 -0
- weijie_codeagent-0.1.0/codeagent/tools/shell_tools.py +107 -0
- weijie_codeagent-0.1.0/codeagent/tools/task_tools.py +106 -0
- weijie_codeagent-0.1.0/codeagent/ui/__init__.py +0 -0
- weijie_codeagent-0.1.0/codeagent/ui/renderer.py +191 -0
- weijie_codeagent-0.1.0/pyproject.toml +47 -0
- weijie_codeagent-0.1.0/tests/__init__.py +0 -0
- weijie_codeagent-0.1.0/tests/conftest.py +1 -0
- weijie_codeagent-0.1.0/tests/test_edit_tools.py +127 -0
- weijie_codeagent-0.1.0/tests/test_graph.py +188 -0
- weijie_codeagent-0.1.0/tests/test_memory.py +184 -0
- weijie_codeagent-0.1.0/tests/test_router.py +71 -0
- weijie_codeagent-0.1.0/tests/test_search_tools.py +78 -0
- weijie_codeagent-0.1.0/tests/test_task_tools.py +83 -0
- weijie_codeagent-0.1.0/tests/test_tools.py +172 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
LLM_API_KEY=your-api-key-here
|
|
2
|
+
LLM_BASE_URL=https://ark.cn-beijing.volces.com/api/coding/v3
|
|
3
|
+
LLM_MODEL=deepseek-v3.2
|
|
4
|
+
EMBEDDING_MODEL=doubao-embedding-vision-250615
|
|
5
|
+
EMBEDDING_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
|
|
6
|
+
VECTOR_BACKEND=chroma
|
|
7
|
+
DB_URL=sqlite:///./codeagent.db
|
|
8
|
+
WINDOW_SIZE=10
|
|
9
|
+
WORKSPACE_DIR=.
|
|
10
|
+
SHELL_SANDBOX=subprocess
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
.Python
|
|
7
|
+
|
|
8
|
+
# 虚拟环境
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
env/
|
|
12
|
+
|
|
13
|
+
# 打包构建
|
|
14
|
+
dist/
|
|
15
|
+
build/
|
|
16
|
+
*.egg-info/
|
|
17
|
+
*.egg
|
|
18
|
+
|
|
19
|
+
# 运行时数据(不提交)
|
|
20
|
+
.env
|
|
21
|
+
codeagent.db
|
|
22
|
+
qdrant_storage/
|
|
23
|
+
chroma_db/
|
|
24
|
+
.codeagent_todos.json
|
|
25
|
+
|
|
26
|
+
# 测试缓存
|
|
27
|
+
.pytest_cache/
|
|
28
|
+
.coverage
|
|
29
|
+
htmlcov/
|
|
30
|
+
|
|
31
|
+
# IDE
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
*.swp
|
|
35
|
+
|
|
36
|
+
# 规划文件(本地使用,不提交到公开仓库)
|
|
37
|
+
findings.md
|
|
38
|
+
task_plan.md
|
|
39
|
+
progress.md
|
|
40
|
+
.claude/
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: weijie-codeagent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI coding agent powered by LangGraph — intent routing, task decomposition, hierarchical memory, and 11 built-in tools
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: agent,cli,coding-assistant,langgraph,llm
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Requires-Dist: httpx>=0.27.0
|
|
17
|
+
Requires-Dist: langchain-core>=0.2.0
|
|
18
|
+
Requires-Dist: langchain-openai>=0.1.0
|
|
19
|
+
Requires-Dist: langchain>=0.2.0
|
|
20
|
+
Requires-Dist: langgraph>=0.2.0
|
|
21
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
22
|
+
Requires-Dist: qdrant-client>=1.9.0
|
|
23
|
+
Requires-Dist: rich>=13.0.0
|
|
24
|
+
Requires-Dist: typer>=0.12.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest-mock>=3.14; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
28
|
+
Provides-Extra: mcp
|
|
29
|
+
Requires-Dist: mcp>=1.0.0; extra == 'mcp'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# CodeAgent
|
|
33
|
+
|
|
34
|
+
基于 **LangGraph** 的 CLI 编程 Agent 助手,支持意图路由、任务拆解、分层记忆、11 种工具调用和实时推理展示。
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
You: 查看一下当前项目,分析主要功能
|
|
38
|
+
|
|
39
|
+
[CODE] Agent ──────────────────────────────────────
|
|
40
|
+
💭 我来查看项目结构并分析其功能。
|
|
41
|
+
→ 调用 list_dir
|
|
42
|
+
💭 让我查看核心配置文件和入口。
|
|
43
|
+
→ 调用 read_file
|
|
44
|
+
|
|
45
|
+
╭──────────────── [CODE] Agent ─────────────────╮
|
|
46
|
+
│ ## 项目功能分析 │
|
|
47
|
+
│ 这是一个基于 LangGraph 的多 Agent 编程助手… │
|
|
48
|
+
╰────────────────────────────────────────────────╯
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 特性
|
|
52
|
+
|
|
53
|
+
| 能力 | 说明 |
|
|
54
|
+
|------|------|
|
|
55
|
+
| **意图路由** | 自动识别用户意图,路由到合适 Agent(代码 / 任务 / 问答 / 记忆) |
|
|
56
|
+
| **代码生成** | 生成完整可运行代码,Reflection 自动审查与修正 |
|
|
57
|
+
| **任务拆解** | 复杂任务拆解为子步骤,实时展示任务链进度(✓) |
|
|
58
|
+
| **分层记忆** | 短期滑动窗口 + SQLite 长期持久化 + Qdrant 向量语义检索 |
|
|
59
|
+
| **11 种工具** | 文件读写、精确编辑、多策略搜索、Shell 沙箱、任务追踪、MCP 协议 |
|
|
60
|
+
| **推理展示** | 工具调用时展示 💭 推理步骤和 → 工具名,最终答案整块渲染 |
|
|
61
|
+
|
|
62
|
+
## 快速开始
|
|
63
|
+
|
|
64
|
+
### 环境要求
|
|
65
|
+
|
|
66
|
+
- Python 3.11+
|
|
67
|
+
- Qdrant(向量记忆,可选)
|
|
68
|
+
|
|
69
|
+
### 安装
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# 推荐使用虚拟环境
|
|
73
|
+
python -m venv .venv
|
|
74
|
+
.venv\Scripts\activate # Windows
|
|
75
|
+
# source .venv/bin/activate # Linux/Mac
|
|
76
|
+
|
|
77
|
+
pip install codeagent
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
或从源码安装:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
git clone https://github.com/your-username/codeagent
|
|
84
|
+
cd codeagent
|
|
85
|
+
pip install -e .
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 配置
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
cp .env.example .env
|
|
92
|
+
# 编辑 .env,填入 API Key
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
最小配置:
|
|
96
|
+
|
|
97
|
+
```env
|
|
98
|
+
LLM_API_KEY=your_api_key_here
|
|
99
|
+
LLM_BASE_URL=https://ark.cn-beijing.volces.com/api/coding/v3
|
|
100
|
+
LLM_MODEL=deepseek-v3.2
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
也支持全局配置 `~/.codeagent/.env`,适合多项目共用同一 Key。
|
|
104
|
+
|
|
105
|
+
### 启动 Qdrant(向量记忆,可选)
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
docker run -d -p 6333:6333 -v qdrant_storage:/qdrant/storage qdrant/qdrant
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
不启动也可正常使用,向量检索会静默跳过。
|
|
112
|
+
|
|
113
|
+
### 运行
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Windows 建议设置 UTF-8
|
|
117
|
+
set PYTHONUTF8=1
|
|
118
|
+
|
|
119
|
+
# 交互对话模式
|
|
120
|
+
codeagent chat
|
|
121
|
+
|
|
122
|
+
# 单次执行
|
|
123
|
+
codeagent run "帮我写一个快速排序算法"
|
|
124
|
+
|
|
125
|
+
# 切换会话(多项目隔离)
|
|
126
|
+
codeagent chat --thread my-project
|
|
127
|
+
|
|
128
|
+
# 查看当前配置
|
|
129
|
+
codeagent config
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 内置命令
|
|
133
|
+
|
|
134
|
+
在交互模式下输入斜杠命令:
|
|
135
|
+
|
|
136
|
+
| 命令 | 说明 |
|
|
137
|
+
|------|------|
|
|
138
|
+
| `/help` | 显示帮助和工具列表 |
|
|
139
|
+
| `/history` | 查看本次会话对话历史 |
|
|
140
|
+
| `/memory` | 查看长期记忆摘要 |
|
|
141
|
+
| `/tasks` | 查看最近一次任务拆解计划 |
|
|
142
|
+
| `/compress` | 手动触发上下文压缩 |
|
|
143
|
+
| `/config` | 查看当前配置 |
|
|
144
|
+
| `/clear` | 开启新会话(旧记录保留在 SQLite) |
|
|
145
|
+
| `/exit` | 退出 |
|
|
146
|
+
|
|
147
|
+
## 可用工具
|
|
148
|
+
|
|
149
|
+
Agent 会根据需要自动调用:
|
|
150
|
+
|
|
151
|
+
| 分类 | 工具 | 说明 |
|
|
152
|
+
|------|------|------|
|
|
153
|
+
| 文件读写 | `read_file` | 读取工作目录内的文件 |
|
|
154
|
+
| | `write_file` | 写入文件(整体覆盖,自动创建目录) |
|
|
155
|
+
| | `list_dir` | 列出目录内容 |
|
|
156
|
+
| 精确编辑 | `apply_diff` | 应用 unified diff 补丁,精确修改局部内容 |
|
|
157
|
+
| | `search_and_replace` | 在文件中搜索并替换文本 |
|
|
158
|
+
| | `insert_content` | 在指定行号后插入内容 |
|
|
159
|
+
| 搜索 | `search_files` | 多策略搜索(git grep → ripgrep → Python) |
|
|
160
|
+
| | `search_code` | 正则表达式搜索代码文件 |
|
|
161
|
+
| 执行 | `run_shell` | 沙箱执行 Shell 命令(危险命令拦截) |
|
|
162
|
+
| 追踪 | `update_todos` | Agent 内部任务列表(add/list/complete/remove) |
|
|
163
|
+
| MCP | `use_mcp_tool` | 调用外部 MCP 工具服务器 |
|
|
164
|
+
|
|
165
|
+
**Shell 沙箱安全策略**:黑名单拦截 `rm -rf` / `dd` / `mkfs` 等危险命令,30s 超时,环境变量隔离,输出最多 10000 字符。
|
|
166
|
+
|
|
167
|
+
## MCP 工具服务器配置
|
|
168
|
+
|
|
169
|
+
在 `~/.codeagent/mcp_servers.json` 中配置(与 Claude Desktop 格式兼容):
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"mcpServers": {
|
|
174
|
+
"filesystem": {
|
|
175
|
+
"command": "npx",
|
|
176
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
安装 MCP SDK 后即可使用:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
pip install "codeagent[mcp]"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 架构
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
用户输入
|
|
192
|
+
│
|
|
193
|
+
▼
|
|
194
|
+
context_loader ← 加载长期摘要 + Qdrant 向量检索(Top-3)
|
|
195
|
+
│
|
|
196
|
+
▼
|
|
197
|
+
intent_router ← LLM 分类: code / decompose / qa / memory
|
|
198
|
+
│
|
|
199
|
+
├── code ──────► code_agent ← 代码生成 + 11 种工具调用
|
|
200
|
+
├── decompose ► task_decomposer ← 任务拆解 + 工具调用 + 任务链展示
|
|
201
|
+
└── qa/memory ► context_qa ← 上下文问答 / 记忆查询
|
|
202
|
+
│
|
|
203
|
+
▼
|
|
204
|
+
reflection ← 仅 code/decompose 触发,最多修正 1 次
|
|
205
|
+
│
|
|
206
|
+
▼
|
|
207
|
+
memory_writer ← 更新短期窗口 + SQLite + Qdrant
|
|
208
|
+
│
|
|
209
|
+
▼
|
|
210
|
+
终端输出(推理步骤 + 最终答案)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**记忆层**:
|
|
214
|
+
- **短期**:滑动窗口 10 轮消息(In-Memory)
|
|
215
|
+
- **长期**:SQLite 会话摘要持久化(`codeagent.db`)
|
|
216
|
+
- **向量**:Qdrant 语义检索,每次对话前自动召回相关历史
|
|
217
|
+
|
|
218
|
+
## 环境变量参考
|
|
219
|
+
|
|
220
|
+
| 变量 | 默认值 | 说明 |
|
|
221
|
+
|------|--------|------|
|
|
222
|
+
| `LLM_API_KEY` | — | LLM API Key(必填) |
|
|
223
|
+
| `LLM_BASE_URL` | Ark API | OpenAI 兼容 BaseURL |
|
|
224
|
+
| `LLM_MODEL` | `deepseek-v3.2` | 模型名称 |
|
|
225
|
+
| `EMBEDDING_MODEL` | `doubao-embedding-vision-250615` | Embedding 模型 |
|
|
226
|
+
| `EMBEDDING_BASE_URL` | Ark API | Embedding 接口地址 |
|
|
227
|
+
| `QDRANT_URL` | `http://localhost:6333` | Qdrant 地址 |
|
|
228
|
+
| `WORKSPACE_DIR` | `.` | 工具调用的文件操作根目录 |
|
|
229
|
+
| `WINDOW_SIZE` | `10` | 短期记忆滑动窗口轮数 |
|
|
230
|
+
| `LLM_MAX_RETRIES` | `3` | API 限流重试次数 |
|
|
231
|
+
|
|
232
|
+
## 依赖
|
|
233
|
+
|
|
234
|
+
- [LangGraph](https://github.com/langchain-ai/langgraph) — Agent 图编排
|
|
235
|
+
- [LangChain OpenAI](https://github.com/langchain-ai/langchain) — LLM 接口
|
|
236
|
+
- [Typer](https://typer.tiangolo.com/) — CLI 框架
|
|
237
|
+
- [Rich](https://rich.readthedocs.io/) — 终端美化
|
|
238
|
+
- [Qdrant Client](https://qdrant.tech/) — 向量数据库
|
|
239
|
+
- [mcp](https://github.com/modelcontextprotocol/python-sdk)(可选)— MCP 协议
|
|
240
|
+
|
|
241
|
+
## License
|
|
242
|
+
|
|
243
|
+
MIT
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# CodeAgent
|
|
2
|
+
|
|
3
|
+
基于 **LangGraph** 的 CLI 编程 Agent 助手,支持意图路由、任务拆解、分层记忆、11 种工具调用和实时推理展示。
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You: 查看一下当前项目,分析主要功能
|
|
7
|
+
|
|
8
|
+
[CODE] Agent ──────────────────────────────────────
|
|
9
|
+
💭 我来查看项目结构并分析其功能。
|
|
10
|
+
→ 调用 list_dir
|
|
11
|
+
💭 让我查看核心配置文件和入口。
|
|
12
|
+
→ 调用 read_file
|
|
13
|
+
|
|
14
|
+
╭──────────────── [CODE] Agent ─────────────────╮
|
|
15
|
+
│ ## 项目功能分析 │
|
|
16
|
+
│ 这是一个基于 LangGraph 的多 Agent 编程助手… │
|
|
17
|
+
╰────────────────────────────────────────────────╯
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 特性
|
|
21
|
+
|
|
22
|
+
| 能力 | 说明 |
|
|
23
|
+
|------|------|
|
|
24
|
+
| **意图路由** | 自动识别用户意图,路由到合适 Agent(代码 / 任务 / 问答 / 记忆) |
|
|
25
|
+
| **代码生成** | 生成完整可运行代码,Reflection 自动审查与修正 |
|
|
26
|
+
| **任务拆解** | 复杂任务拆解为子步骤,实时展示任务链进度(✓) |
|
|
27
|
+
| **分层记忆** | 短期滑动窗口 + SQLite 长期持久化 + Qdrant 向量语义检索 |
|
|
28
|
+
| **11 种工具** | 文件读写、精确编辑、多策略搜索、Shell 沙箱、任务追踪、MCP 协议 |
|
|
29
|
+
| **推理展示** | 工具调用时展示 💭 推理步骤和 → 工具名,最终答案整块渲染 |
|
|
30
|
+
|
|
31
|
+
## 快速开始
|
|
32
|
+
|
|
33
|
+
### 环境要求
|
|
34
|
+
|
|
35
|
+
- Python 3.11+
|
|
36
|
+
- Qdrant(向量记忆,可选)
|
|
37
|
+
|
|
38
|
+
### 安装
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# 推荐使用虚拟环境
|
|
42
|
+
python -m venv .venv
|
|
43
|
+
.venv\Scripts\activate # Windows
|
|
44
|
+
# source .venv/bin/activate # Linux/Mac
|
|
45
|
+
|
|
46
|
+
pip install codeagent
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
或从源码安装:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git clone https://github.com/your-username/codeagent
|
|
53
|
+
cd codeagent
|
|
54
|
+
pip install -e .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 配置
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cp .env.example .env
|
|
61
|
+
# 编辑 .env,填入 API Key
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
最小配置:
|
|
65
|
+
|
|
66
|
+
```env
|
|
67
|
+
LLM_API_KEY=your_api_key_here
|
|
68
|
+
LLM_BASE_URL=https://ark.cn-beijing.volces.com/api/coding/v3
|
|
69
|
+
LLM_MODEL=deepseek-v3.2
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
也支持全局配置 `~/.codeagent/.env`,适合多项目共用同一 Key。
|
|
73
|
+
|
|
74
|
+
### 启动 Qdrant(向量记忆,可选)
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
docker run -d -p 6333:6333 -v qdrant_storage:/qdrant/storage qdrant/qdrant
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
不启动也可正常使用,向量检索会静默跳过。
|
|
81
|
+
|
|
82
|
+
### 运行
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Windows 建议设置 UTF-8
|
|
86
|
+
set PYTHONUTF8=1
|
|
87
|
+
|
|
88
|
+
# 交互对话模式
|
|
89
|
+
codeagent chat
|
|
90
|
+
|
|
91
|
+
# 单次执行
|
|
92
|
+
codeagent run "帮我写一个快速排序算法"
|
|
93
|
+
|
|
94
|
+
# 切换会话(多项目隔离)
|
|
95
|
+
codeagent chat --thread my-project
|
|
96
|
+
|
|
97
|
+
# 查看当前配置
|
|
98
|
+
codeagent config
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 内置命令
|
|
102
|
+
|
|
103
|
+
在交互模式下输入斜杠命令:
|
|
104
|
+
|
|
105
|
+
| 命令 | 说明 |
|
|
106
|
+
|------|------|
|
|
107
|
+
| `/help` | 显示帮助和工具列表 |
|
|
108
|
+
| `/history` | 查看本次会话对话历史 |
|
|
109
|
+
| `/memory` | 查看长期记忆摘要 |
|
|
110
|
+
| `/tasks` | 查看最近一次任务拆解计划 |
|
|
111
|
+
| `/compress` | 手动触发上下文压缩 |
|
|
112
|
+
| `/config` | 查看当前配置 |
|
|
113
|
+
| `/clear` | 开启新会话(旧记录保留在 SQLite) |
|
|
114
|
+
| `/exit` | 退出 |
|
|
115
|
+
|
|
116
|
+
## 可用工具
|
|
117
|
+
|
|
118
|
+
Agent 会根据需要自动调用:
|
|
119
|
+
|
|
120
|
+
| 分类 | 工具 | 说明 |
|
|
121
|
+
|------|------|------|
|
|
122
|
+
| 文件读写 | `read_file` | 读取工作目录内的文件 |
|
|
123
|
+
| | `write_file` | 写入文件(整体覆盖,自动创建目录) |
|
|
124
|
+
| | `list_dir` | 列出目录内容 |
|
|
125
|
+
| 精确编辑 | `apply_diff` | 应用 unified diff 补丁,精确修改局部内容 |
|
|
126
|
+
| | `search_and_replace` | 在文件中搜索并替换文本 |
|
|
127
|
+
| | `insert_content` | 在指定行号后插入内容 |
|
|
128
|
+
| 搜索 | `search_files` | 多策略搜索(git grep → ripgrep → Python) |
|
|
129
|
+
| | `search_code` | 正则表达式搜索代码文件 |
|
|
130
|
+
| 执行 | `run_shell` | 沙箱执行 Shell 命令(危险命令拦截) |
|
|
131
|
+
| 追踪 | `update_todos` | Agent 内部任务列表(add/list/complete/remove) |
|
|
132
|
+
| MCP | `use_mcp_tool` | 调用外部 MCP 工具服务器 |
|
|
133
|
+
|
|
134
|
+
**Shell 沙箱安全策略**:黑名单拦截 `rm -rf` / `dd` / `mkfs` 等危险命令,30s 超时,环境变量隔离,输出最多 10000 字符。
|
|
135
|
+
|
|
136
|
+
## MCP 工具服务器配置
|
|
137
|
+
|
|
138
|
+
在 `~/.codeagent/mcp_servers.json` 中配置(与 Claude Desktop 格式兼容):
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"mcpServers": {
|
|
143
|
+
"filesystem": {
|
|
144
|
+
"command": "npx",
|
|
145
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
安装 MCP SDK 后即可使用:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
pip install "codeagent[mcp]"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 架构
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
用户输入
|
|
161
|
+
│
|
|
162
|
+
▼
|
|
163
|
+
context_loader ← 加载长期摘要 + Qdrant 向量检索(Top-3)
|
|
164
|
+
│
|
|
165
|
+
▼
|
|
166
|
+
intent_router ← LLM 分类: code / decompose / qa / memory
|
|
167
|
+
│
|
|
168
|
+
├── code ──────► code_agent ← 代码生成 + 11 种工具调用
|
|
169
|
+
├── decompose ► task_decomposer ← 任务拆解 + 工具调用 + 任务链展示
|
|
170
|
+
└── qa/memory ► context_qa ← 上下文问答 / 记忆查询
|
|
171
|
+
│
|
|
172
|
+
▼
|
|
173
|
+
reflection ← 仅 code/decompose 触发,最多修正 1 次
|
|
174
|
+
│
|
|
175
|
+
▼
|
|
176
|
+
memory_writer ← 更新短期窗口 + SQLite + Qdrant
|
|
177
|
+
│
|
|
178
|
+
▼
|
|
179
|
+
终端输出(推理步骤 + 最终答案)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**记忆层**:
|
|
183
|
+
- **短期**:滑动窗口 10 轮消息(In-Memory)
|
|
184
|
+
- **长期**:SQLite 会话摘要持久化(`codeagent.db`)
|
|
185
|
+
- **向量**:Qdrant 语义检索,每次对话前自动召回相关历史
|
|
186
|
+
|
|
187
|
+
## 环境变量参考
|
|
188
|
+
|
|
189
|
+
| 变量 | 默认值 | 说明 |
|
|
190
|
+
|------|--------|------|
|
|
191
|
+
| `LLM_API_KEY` | — | LLM API Key(必填) |
|
|
192
|
+
| `LLM_BASE_URL` | Ark API | OpenAI 兼容 BaseURL |
|
|
193
|
+
| `LLM_MODEL` | `deepseek-v3.2` | 模型名称 |
|
|
194
|
+
| `EMBEDDING_MODEL` | `doubao-embedding-vision-250615` | Embedding 模型 |
|
|
195
|
+
| `EMBEDDING_BASE_URL` | Ark API | Embedding 接口地址 |
|
|
196
|
+
| `QDRANT_URL` | `http://localhost:6333` | Qdrant 地址 |
|
|
197
|
+
| `WORKSPACE_DIR` | `.` | 工具调用的文件操作根目录 |
|
|
198
|
+
| `WINDOW_SIZE` | `10` | 短期记忆滑动窗口轮数 |
|
|
199
|
+
| `LLM_MAX_RETRIES` | `3` | API 限流重试次数 |
|
|
200
|
+
|
|
201
|
+
## 依赖
|
|
202
|
+
|
|
203
|
+
- [LangGraph](https://github.com/langchain-ai/langgraph) — Agent 图编排
|
|
204
|
+
- [LangChain OpenAI](https://github.com/langchain-ai/langchain) — LLM 接口
|
|
205
|
+
- [Typer](https://typer.tiangolo.com/) — CLI 框架
|
|
206
|
+
- [Rich](https://rich.readthedocs.io/) — 终端美化
|
|
207
|
+
- [Qdrant Client](https://qdrant.tech/) — 向量数据库
|
|
208
|
+
- [mcp](https://github.com/modelcontextprotocol/python-sdk)(可选)— MCP 协议
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""
|
|
2
|
+
config.py —— pydantic-settings 配置管理(Phase 4 升级版)
|
|
3
|
+
|
|
4
|
+
env 文件加载优先级(后者覆盖前者):
|
|
5
|
+
1. ~/.codeagent/.env (用户全局配置)
|
|
6
|
+
2. .env (项目本地配置,最高优先级)
|
|
7
|
+
"""
|
|
8
|
+
import os
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
11
|
+
from langchain_openai import ChatOpenAI
|
|
12
|
+
|
|
13
|
+
# 用户全局配置路径
|
|
14
|
+
_USER_ENV = Path.home() / ".codeagent" / ".env"
|
|
15
|
+
_LOCAL_ENV = Path(".env")
|
|
16
|
+
|
|
17
|
+
# 收集存在的 env 文件(按优先级从低到高)
|
|
18
|
+
_ENV_FILES: list[str] = []
|
|
19
|
+
if _USER_ENV.exists():
|
|
20
|
+
_ENV_FILES.append(str(_USER_ENV))
|
|
21
|
+
if _LOCAL_ENV.exists():
|
|
22
|
+
_ENV_FILES.append(str(_LOCAL_ENV))
|
|
23
|
+
if not _ENV_FILES:
|
|
24
|
+
_ENV_FILES = [".env"] # 回退,让 pydantic-settings 自行处理
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Settings(BaseSettings):
|
|
28
|
+
PROJECT_NAME: str = "CodeAgent"
|
|
29
|
+
|
|
30
|
+
# LLM(火山引擎 Ark,OpenAI 兼容)
|
|
31
|
+
LLM_API_KEY: str = os.getenv("LLM_API_KEY", "")
|
|
32
|
+
LLM_BASE_URL: str = os.getenv("LLM_BASE_URL", "https://ark.cn-beijing.volces.com/api/coding/v3")
|
|
33
|
+
LLM_MODEL: str = os.getenv("LLM_MODEL", "deepseek-v3.2")
|
|
34
|
+
|
|
35
|
+
# Embedding(Phase 2 启用)
|
|
36
|
+
EMBEDDING_MODEL: str = os.getenv("EMBEDDING_MODEL", "doubao-embedding-vision-250615")
|
|
37
|
+
EMBEDDING_BASE_URL: str = os.getenv("EMBEDDING_BASE_URL", "https://ark.cn-beijing.volces.com/api/v3")
|
|
38
|
+
EMBEDDING_API_KEY: str = os.getenv("EMBEDDING_API_KEY", "")
|
|
39
|
+
|
|
40
|
+
# 存储
|
|
41
|
+
VECTOR_BACKEND: str = os.getenv("VECTOR_BACKEND", "qdrant")
|
|
42
|
+
DB_URL: str = os.getenv("DB_URL", "sqlite:///./codeagent.db")
|
|
43
|
+
|
|
44
|
+
# 记忆窗口
|
|
45
|
+
WINDOW_SIZE: int = int(os.getenv("WINDOW_SIZE", "10"))
|
|
46
|
+
|
|
47
|
+
# Qdrant
|
|
48
|
+
QDRANT_URL: str = os.getenv("QDRANT_URL", "http://localhost:6333")
|
|
49
|
+
|
|
50
|
+
# Shell 沙箱
|
|
51
|
+
WORKSPACE_DIR: str = os.getenv("WORKSPACE_DIR", ".")
|
|
52
|
+
SHELL_SANDBOX: str = os.getenv("SHELL_SANDBOX", "subprocess")
|
|
53
|
+
|
|
54
|
+
# 重试
|
|
55
|
+
LLM_MAX_RETRIES: int = int(os.getenv("LLM_MAX_RETRIES", "3"))
|
|
56
|
+
|
|
57
|
+
model_config = SettingsConfigDict(
|
|
58
|
+
env_file=_ENV_FILES, # type: ignore[arg-type]
|
|
59
|
+
extra="ignore",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def embedding_api_key(self) -> str:
|
|
64
|
+
return self.EMBEDDING_API_KEY or self.LLM_API_KEY
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
settings = Settings()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_llm(streaming: bool = False) -> ChatOpenAI:
|
|
71
|
+
return ChatOpenAI(
|
|
72
|
+
api_key=settings.LLM_API_KEY,
|
|
73
|
+
base_url=settings.LLM_BASE_URL,
|
|
74
|
+
model=settings.LLM_MODEL,
|
|
75
|
+
temperature=0.3,
|
|
76
|
+
max_tokens=4096,
|
|
77
|
+
streaming=streaming,
|
|
78
|
+
max_retries=settings.LLM_MAX_RETRIES,
|
|
79
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""
|
|
2
|
+
builder.py —— LangGraph 图构建(Phase 3 版)
|
|
3
|
+
|
|
4
|
+
图结构:
|
|
5
|
+
START
|
|
6
|
+
→ context_loader
|
|
7
|
+
→ intent_router
|
|
8
|
+
→(条件) code_agent | task_decomposer | context_qa
|
|
9
|
+
→ (code/decompose 后) reflection
|
|
10
|
+
→(条件) code_agent | task_decomposer | memory_writer ← revision 或直接结束
|
|
11
|
+
→ (context_qa 后) memory_writer
|
|
12
|
+
→ END
|
|
13
|
+
"""
|
|
14
|
+
from langgraph.graph import StateGraph, START, END
|
|
15
|
+
from langgraph.checkpoint.memory import MemorySaver
|
|
16
|
+
|
|
17
|
+
from codeagent.graph.state import AgentState
|
|
18
|
+
from codeagent.graph.nodes.context_loader import context_loader_node
|
|
19
|
+
from codeagent.graph.nodes.intent_router import intent_router_node, route_by_intent
|
|
20
|
+
from codeagent.graph.nodes.code_agent import code_agent_node
|
|
21
|
+
from codeagent.graph.nodes.task_decomposer import task_decomposer_node
|
|
22
|
+
from codeagent.graph.nodes.context_qa import context_qa_node
|
|
23
|
+
from codeagent.graph.nodes.reflection import reflection_node, route_after_reflection
|
|
24
|
+
from codeagent.graph.nodes.memory_writer import memory_writer_node
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def build_graph():
|
|
28
|
+
builder = StateGraph(AgentState)
|
|
29
|
+
|
|
30
|
+
# ── 注册节点 ──────────────────────────────────
|
|
31
|
+
builder.add_node("context_loader", context_loader_node)
|
|
32
|
+
builder.add_node("intent_router", intent_router_node)
|
|
33
|
+
builder.add_node("code_agent", code_agent_node)
|
|
34
|
+
builder.add_node("task_decomposer", task_decomposer_node)
|
|
35
|
+
builder.add_node("context_qa", context_qa_node)
|
|
36
|
+
builder.add_node("reflection", reflection_node)
|
|
37
|
+
builder.add_node("memory_writer", memory_writer_node)
|
|
38
|
+
|
|
39
|
+
# ── 固定边 ────────────────────────────────────
|
|
40
|
+
builder.add_edge(START, "context_loader")
|
|
41
|
+
builder.add_edge("context_loader", "intent_router")
|
|
42
|
+
|
|
43
|
+
# code / decompose → reflection(Reflection 节点内部决定是否真正执行)
|
|
44
|
+
builder.add_edge("code_agent", "reflection")
|
|
45
|
+
builder.add_edge("task_decomposer", "reflection")
|
|
46
|
+
|
|
47
|
+
# context_qa 直接跳过 reflection
|
|
48
|
+
builder.add_edge("context_qa", "memory_writer")
|
|
49
|
+
builder.add_edge("memory_writer", END)
|
|
50
|
+
|
|
51
|
+
# ── 意图路由:intent_router → 各 Agent ─────────
|
|
52
|
+
builder.add_conditional_edges(
|
|
53
|
+
"intent_router",
|
|
54
|
+
route_by_intent,
|
|
55
|
+
{
|
|
56
|
+
"code_agent": "code_agent",
|
|
57
|
+
"task_decomposer": "task_decomposer",
|
|
58
|
+
"context_qa": "context_qa",
|
|
59
|
+
},
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# ── Reflection 后路由:通过/重试/结束 ───────────
|
|
63
|
+
builder.add_conditional_edges(
|
|
64
|
+
"reflection",
|
|
65
|
+
route_after_reflection,
|
|
66
|
+
{
|
|
67
|
+
"code_agent": "code_agent",
|
|
68
|
+
"task_decomposer": "task_decomposer",
|
|
69
|
+
"memory_writer": "memory_writer",
|
|
70
|
+
},
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
checkpointer = MemorySaver()
|
|
74
|
+
return builder.compile(checkpointer=checkpointer)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
graph = build_graph()
|
|
File without changes
|