code-graph-builder 0.2.0__py3-none-any.whl
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.
- code_graph_builder/__init__.py +82 -0
- code_graph_builder/builder.py +366 -0
- code_graph_builder/cgb_cli.py +32 -0
- code_graph_builder/cli.py +564 -0
- code_graph_builder/commands_cli.py +1288 -0
- code_graph_builder/config.py +340 -0
- code_graph_builder/constants.py +708 -0
- code_graph_builder/embeddings/__init__.py +40 -0
- code_graph_builder/embeddings/qwen3_embedder.py +573 -0
- code_graph_builder/embeddings/vector_store.py +584 -0
- code_graph_builder/examples/__init__.py +0 -0
- code_graph_builder/examples/example_configuration.py +276 -0
- code_graph_builder/examples/example_kuzu_usage.py +109 -0
- code_graph_builder/examples/example_semantic_search_full.py +347 -0
- code_graph_builder/examples/generate_wiki.py +915 -0
- code_graph_builder/examples/graph_export_example.py +100 -0
- code_graph_builder/examples/rag_example.py +206 -0
- code_graph_builder/examples/test_cli_demo.py +129 -0
- code_graph_builder/examples/test_embedding_api.py +153 -0
- code_graph_builder/examples/test_kuzu_local.py +190 -0
- code_graph_builder/examples/test_rag_redis.py +390 -0
- code_graph_builder/graph_updater.py +605 -0
- code_graph_builder/guidance/__init__.py +1 -0
- code_graph_builder/guidance/agent.py +123 -0
- code_graph_builder/guidance/prompts.py +74 -0
- code_graph_builder/guidance/toolset.py +264 -0
- code_graph_builder/language_spec.py +536 -0
- code_graph_builder/mcp/__init__.py +21 -0
- code_graph_builder/mcp/api_doc_generator.py +764 -0
- code_graph_builder/mcp/file_editor.py +207 -0
- code_graph_builder/mcp/pipeline.py +777 -0
- code_graph_builder/mcp/server.py +161 -0
- code_graph_builder/mcp/tools.py +1800 -0
- code_graph_builder/models.py +115 -0
- code_graph_builder/parser_loader.py +344 -0
- code_graph_builder/parsers/__init__.py +7 -0
- code_graph_builder/parsers/call_processor.py +306 -0
- code_graph_builder/parsers/call_resolver.py +139 -0
- code_graph_builder/parsers/definition_processor.py +796 -0
- code_graph_builder/parsers/factory.py +119 -0
- code_graph_builder/parsers/import_processor.py +293 -0
- code_graph_builder/parsers/structure_processor.py +145 -0
- code_graph_builder/parsers/type_inference.py +143 -0
- code_graph_builder/parsers/utils.py +134 -0
- code_graph_builder/rag/__init__.py +68 -0
- code_graph_builder/rag/camel_agent.py +429 -0
- code_graph_builder/rag/client.py +298 -0
- code_graph_builder/rag/config.py +239 -0
- code_graph_builder/rag/cypher_generator.py +67 -0
- code_graph_builder/rag/llm_backend.py +210 -0
- code_graph_builder/rag/markdown_generator.py +352 -0
- code_graph_builder/rag/prompt_templates.py +440 -0
- code_graph_builder/rag/rag_engine.py +640 -0
- code_graph_builder/rag/review_report.md +172 -0
- code_graph_builder/rag/tests/__init__.py +3 -0
- code_graph_builder/rag/tests/test_camel_agent.py +313 -0
- code_graph_builder/rag/tests/test_client.py +221 -0
- code_graph_builder/rag/tests/test_config.py +177 -0
- code_graph_builder/rag/tests/test_markdown_generator.py +240 -0
- code_graph_builder/rag/tests/test_prompt_templates.py +160 -0
- code_graph_builder/services/__init__.py +39 -0
- code_graph_builder/services/graph_service.py +465 -0
- code_graph_builder/services/kuzu_service.py +665 -0
- code_graph_builder/services/memory_service.py +171 -0
- code_graph_builder/settings.py +75 -0
- code_graph_builder/tests/ACCEPTANCE_CRITERIA_PHASE2.md +401 -0
- code_graph_builder/tests/__init__.py +1 -0
- code_graph_builder/tests/run_acceptance_check.py +378 -0
- code_graph_builder/tests/test_api_find.py +231 -0
- code_graph_builder/tests/test_api_find_integration.py +226 -0
- code_graph_builder/tests/test_basic.py +78 -0
- code_graph_builder/tests/test_c_api_extraction.py +388 -0
- code_graph_builder/tests/test_call_resolution_scenarios.py +504 -0
- code_graph_builder/tests/test_embedder.py +411 -0
- code_graph_builder/tests/test_integration_semantic.py +434 -0
- code_graph_builder/tests/test_mcp_protocol.py +298 -0
- code_graph_builder/tests/test_mcp_user_flow.py +190 -0
- code_graph_builder/tests/test_rag.py +404 -0
- code_graph_builder/tests/test_settings.py +135 -0
- code_graph_builder/tests/test_step1_graph_build.py +264 -0
- code_graph_builder/tests/test_step2_api_docs.py +323 -0
- code_graph_builder/tests/test_step3_embedding.py +278 -0
- code_graph_builder/tests/test_vector_store.py +552 -0
- code_graph_builder/tools/__init__.py +40 -0
- code_graph_builder/tools/graph_query.py +495 -0
- code_graph_builder/tools/semantic_search.py +387 -0
- code_graph_builder/types.py +333 -0
- code_graph_builder/utils/__init__.py +0 -0
- code_graph_builder/utils/path_utils.py +30 -0
- code_graph_builder-0.2.0.dist-info/METADATA +321 -0
- code_graph_builder-0.2.0.dist-info/RECORD +93 -0
- code_graph_builder-0.2.0.dist-info/WHEEL +4 -0
- code_graph_builder-0.2.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# RAG + CAMEL 集成代码审查报告
|
|
2
|
+
|
|
3
|
+
## 审查概述
|
|
4
|
+
|
|
5
|
+
**审查日期**: 2026-02-22
|
|
6
|
+
**审查模块**: `code_graph_builder/rag/`
|
|
7
|
+
**审查人**: QA Reviewer Agent
|
|
8
|
+
|
|
9
|
+
## 文件清单
|
|
10
|
+
|
|
11
|
+
1. `__init__.py` - 模块初始化
|
|
12
|
+
2. `config.py` - 配置管理
|
|
13
|
+
3. `client.py` - LLM API 客户端
|
|
14
|
+
4. `prompt_templates.py` - 提示词模板
|
|
15
|
+
5. `markdown_generator.py` - Markdown 生成器
|
|
16
|
+
6. `rag_engine.py` - RAG 引擎
|
|
17
|
+
7. `camel_agent.py` - CAMEL Agent 封装
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 审查结果
|
|
22
|
+
|
|
23
|
+
### 1. 代码风格 (Code Style)
|
|
24
|
+
|
|
25
|
+
**状态**: 通过
|
|
26
|
+
|
|
27
|
+
**优点**:
|
|
28
|
+
- 遵循项目代码风格,使用 `from __future__ import annotations`
|
|
29
|
+
- 使用 dataclass 定义数据类
|
|
30
|
+
- 文档字符串完整,包含 Args/Returns/Examples
|
|
31
|
+
- 使用类型注解
|
|
32
|
+
|
|
33
|
+
**建议**:
|
|
34
|
+
- 所有文件都符合项目标准
|
|
35
|
+
|
|
36
|
+
### 2. 类型注解 (Type Annotations)
|
|
37
|
+
|
|
38
|
+
**状态**: 通过
|
|
39
|
+
|
|
40
|
+
**优点**:
|
|
41
|
+
- 全面的类型注解
|
|
42
|
+
- 使用 `|` 语法 (Python 3.10+)
|
|
43
|
+
- 正确使用 `TYPE_CHECKING` 避免循环导入
|
|
44
|
+
- Protocol 定义清晰
|
|
45
|
+
|
|
46
|
+
### 3. 错误处理 (Error Handling)
|
|
47
|
+
|
|
48
|
+
**状态**: 通过,有改进建议
|
|
49
|
+
|
|
50
|
+
**优点**:
|
|
51
|
+
- `client.py` 有完善的异常处理 (HTTPError, Timeout)
|
|
52
|
+
- 使用 try-except 包裹 API 调用
|
|
53
|
+
- 使用 loguru 记录错误日志
|
|
54
|
+
|
|
55
|
+
**建议改进**:
|
|
56
|
+
1. `rag_engine.py` 第 527-530 行: 异常处理可以返回更友好的错误信息
|
|
57
|
+
2. `camel_agent.py` 第 154-160 行: 已正确处理异常
|
|
58
|
+
|
|
59
|
+
### 4. API Key 安全性
|
|
60
|
+
|
|
61
|
+
**状态**: 通过
|
|
62
|
+
|
|
63
|
+
**优点**:
|
|
64
|
+
- 使用环境变量加载 API key (`MOONSHOT_API_KEY`)
|
|
65
|
+
- `config.py` 第 51-52 行: `__post_init__` 从环境变量加载
|
|
66
|
+
- 不硬编码敏感信息
|
|
67
|
+
|
|
68
|
+
### 5. 日志记录
|
|
69
|
+
|
|
70
|
+
**状态**: 通过
|
|
71
|
+
|
|
72
|
+
**优点**:
|
|
73
|
+
- 使用 `loguru` 进行日志记录
|
|
74
|
+
- 适当的日志级别 (info, debug, warning, error)
|
|
75
|
+
- 关键操作都有日志记录
|
|
76
|
+
|
|
77
|
+
### 6. 代码结构
|
|
78
|
+
|
|
79
|
+
**状态**: 通过
|
|
80
|
+
|
|
81
|
+
**优点**:
|
|
82
|
+
- 模块化设计清晰
|
|
83
|
+
- 职责分离明确
|
|
84
|
+
- 工厂函数便于创建实例
|
|
85
|
+
- 与现有 code_graph_builder 功能集成良好
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 测试计划
|
|
90
|
+
|
|
91
|
+
### 单元测试
|
|
92
|
+
|
|
93
|
+
需要编写以下测试文件:
|
|
94
|
+
|
|
95
|
+
1. `tests/test_rag_config.py` - 配置类测试
|
|
96
|
+
2. `tests/test_client.py` - LLM 客户端测试 (mock API)
|
|
97
|
+
3. `tests/test_prompt_templates.py` - 提示词模板测试
|
|
98
|
+
4. `tests/test_markdown_generator.py` - Markdown 生成器测试
|
|
99
|
+
5. `tests/test_rag_engine.py` - RAG 引擎测试
|
|
100
|
+
6. `tests/test_camel_agent.py` - CAMEL Agent 测试
|
|
101
|
+
|
|
102
|
+
### 集成测试
|
|
103
|
+
|
|
104
|
+
使用 tinycc 代码库进行端到端测试:
|
|
105
|
+
|
|
106
|
+
1. 构建 tinycc 代码图
|
|
107
|
+
2. 执行语义搜索
|
|
108
|
+
3. 验证 RAG 查询流程
|
|
109
|
+
4. 验证 Markdown 输出
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 问题清单
|
|
114
|
+
|
|
115
|
+
### 已发现问题
|
|
116
|
+
|
|
117
|
+
1. **无重大问题**
|
|
118
|
+
|
|
119
|
+
### 建议改进
|
|
120
|
+
|
|
121
|
+
1. **文档完善**: 建议添加更多使用示例到 README
|
|
122
|
+
2. **配置验证**: `config.py` 中的验证可以更加全面
|
|
123
|
+
3. **测试覆盖**: 需要补充单元测试
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 测试执行
|
|
128
|
+
|
|
129
|
+
### 基础导入测试
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
python -c "from code_graph_builder.rag import RAGConfig, create_rag_engine; print('OK')"
|
|
133
|
+
# 结果: 通过
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 配置测试
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
python -c "from code_graph_builder.rag.config import RAGConfig; c = RAGConfig.from_env(); print('OK')"
|
|
140
|
+
# 结果: 通过
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 单元测试
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pytest code_graph_builder/rag/tests/ -v
|
|
147
|
+
# 结果: 78 passed in 0.11s
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
测试覆盖:
|
|
151
|
+
- `test_config.py`: 17 tests - 配置类测试
|
|
152
|
+
- `test_prompt_templates.py`: 14 tests - 提示词模板测试
|
|
153
|
+
- `test_markdown_generator.py`: 18 tests - Markdown 生成器测试
|
|
154
|
+
- `test_client.py`: 14 tests - LLM 客户端测试 (含 mock)
|
|
155
|
+
- `test_camel_agent.py`: 15 tests - CAMEL Agent 测试
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 总结
|
|
160
|
+
|
|
161
|
+
**总体评价**: 通过
|
|
162
|
+
|
|
163
|
+
**代码质量**: 高
|
|
164
|
+
|
|
165
|
+
**测试状态**: 78/78 通过
|
|
166
|
+
|
|
167
|
+
**完成情况**:
|
|
168
|
+
1. 单元测试 - 已完成 (78 tests)
|
|
169
|
+
2. 集成测试 - 建议后续添加 (需要 tinycc 代码库)
|
|
170
|
+
3. 文档 - 代码文档完整
|
|
171
|
+
|
|
172
|
+
所有核心功能模块都已实现,代码风格符合项目标准,测试全部通过,可以合并到主分支。
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"""Tests for CAMEL agent."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from unittest.mock import Mock, patch
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from code_graph_builder.rag.camel_agent import (
|
|
10
|
+
CamelAgent,
|
|
11
|
+
CamelAgentResponse,
|
|
12
|
+
MultiAgentRAG,
|
|
13
|
+
create_camel_agent,
|
|
14
|
+
)
|
|
15
|
+
from code_graph_builder.rag.client import ChatResponse
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TestCamelAgentResponse:
|
|
19
|
+
"""Tests for CamelAgentResponse."""
|
|
20
|
+
|
|
21
|
+
def test_creation(self):
|
|
22
|
+
"""Test basic creation."""
|
|
23
|
+
response = CamelAgentResponse(
|
|
24
|
+
content="Test response",
|
|
25
|
+
metadata={"key": "value"},
|
|
26
|
+
role="Analyst",
|
|
27
|
+
)
|
|
28
|
+
assert response.content == "Test response"
|
|
29
|
+
assert response.metadata["key"] == "value"
|
|
30
|
+
assert response.role == "Analyst"
|
|
31
|
+
|
|
32
|
+
def test_default_role(self):
|
|
33
|
+
"""Test default role."""
|
|
34
|
+
response = CamelAgentResponse(content="Test")
|
|
35
|
+
assert response.role == "agent"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TestCamelAgent:
|
|
39
|
+
"""Tests for CamelAgent."""
|
|
40
|
+
|
|
41
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
42
|
+
def test_init(self, mock_create_client):
|
|
43
|
+
"""Test initialization."""
|
|
44
|
+
mock_client = Mock()
|
|
45
|
+
mock_create_client.return_value = mock_client
|
|
46
|
+
|
|
47
|
+
agent = CamelAgent(
|
|
48
|
+
role="Code Analyst",
|
|
49
|
+
goal="Analyze code",
|
|
50
|
+
backstory="Expert programmer",
|
|
51
|
+
)
|
|
52
|
+
assert agent.role == "Code Analyst"
|
|
53
|
+
assert agent.goal == "Analyze code"
|
|
54
|
+
assert agent.backstory == "Expert programmer"
|
|
55
|
+
assert "Code Analyst" in agent.system_prompt
|
|
56
|
+
|
|
57
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
58
|
+
def test_build_system_prompt(self, mock_create_client):
|
|
59
|
+
"""Test system prompt building."""
|
|
60
|
+
mock_client = Mock()
|
|
61
|
+
mock_create_client.return_value = mock_client
|
|
62
|
+
|
|
63
|
+
agent = CamelAgent(
|
|
64
|
+
role="Tester",
|
|
65
|
+
goal="Test things",
|
|
66
|
+
backstory="Testing expert",
|
|
67
|
+
)
|
|
68
|
+
prompt = agent.system_prompt
|
|
69
|
+
assert "Tester" in prompt
|
|
70
|
+
assert "Test things" in prompt
|
|
71
|
+
assert "Testing expert" in prompt
|
|
72
|
+
|
|
73
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
74
|
+
def test_analyze(self, mock_create_client):
|
|
75
|
+
"""Test analyze method."""
|
|
76
|
+
mock_client = Mock()
|
|
77
|
+
mock_client.chat_with_messages.return_value = ChatResponse(
|
|
78
|
+
content="Analysis result",
|
|
79
|
+
usage={},
|
|
80
|
+
model="kimi-k2.5",
|
|
81
|
+
finish_reason="stop",
|
|
82
|
+
)
|
|
83
|
+
mock_create_client.return_value = mock_client
|
|
84
|
+
|
|
85
|
+
agent = CamelAgent(
|
|
86
|
+
role="Analyst",
|
|
87
|
+
goal="Analyze",
|
|
88
|
+
backstory="Expert",
|
|
89
|
+
llm_client=mock_client,
|
|
90
|
+
)
|
|
91
|
+
response = agent.analyze("Review this code", code="def foo(): pass")
|
|
92
|
+
|
|
93
|
+
assert isinstance(response, CamelAgentResponse)
|
|
94
|
+
assert response.content == "Analysis result"
|
|
95
|
+
assert response.role == "Analyst"
|
|
96
|
+
|
|
97
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
98
|
+
def test_analyze_error(self, mock_create_client):
|
|
99
|
+
"""Test analyze method with error."""
|
|
100
|
+
mock_client = Mock()
|
|
101
|
+
mock_client.chat_with_messages.side_effect = Exception("API error")
|
|
102
|
+
mock_create_client.return_value = mock_client
|
|
103
|
+
|
|
104
|
+
agent = CamelAgent(
|
|
105
|
+
role="Analyst",
|
|
106
|
+
goal="Analyze",
|
|
107
|
+
backstory="Expert",
|
|
108
|
+
llm_client=mock_client,
|
|
109
|
+
)
|
|
110
|
+
response = agent.analyze("Review this")
|
|
111
|
+
|
|
112
|
+
assert "Error" in response.content
|
|
113
|
+
assert "error" in response.metadata
|
|
114
|
+
|
|
115
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
116
|
+
def test_review_code_general(self, mock_create_client):
|
|
117
|
+
"""Test general code review."""
|
|
118
|
+
mock_client = Mock()
|
|
119
|
+
mock_client.chat_with_messages.return_value = ChatResponse(
|
|
120
|
+
content="Review result",
|
|
121
|
+
usage={},
|
|
122
|
+
model="kimi-k2.5",
|
|
123
|
+
finish_reason="stop",
|
|
124
|
+
)
|
|
125
|
+
mock_create_client.return_value = mock_client
|
|
126
|
+
|
|
127
|
+
agent = CamelAgent(
|
|
128
|
+
role="Reviewer",
|
|
129
|
+
goal="Review code",
|
|
130
|
+
backstory="Code reviewer",
|
|
131
|
+
llm_client=mock_client,
|
|
132
|
+
)
|
|
133
|
+
response = agent.review_code("def foo(): pass", review_type="general")
|
|
134
|
+
|
|
135
|
+
assert isinstance(response, CamelAgentResponse)
|
|
136
|
+
mock_client.chat_with_messages.assert_called_once()
|
|
137
|
+
|
|
138
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
139
|
+
def test_review_code_security(self, mock_create_client):
|
|
140
|
+
"""Test security code review."""
|
|
141
|
+
mock_client = Mock()
|
|
142
|
+
mock_client.chat_with_messages.return_value = ChatResponse(
|
|
143
|
+
content="Security review",
|
|
144
|
+
usage={},
|
|
145
|
+
model="kimi-k2.5",
|
|
146
|
+
finish_reason="stop",
|
|
147
|
+
)
|
|
148
|
+
mock_create_client.return_value = mock_client
|
|
149
|
+
|
|
150
|
+
agent = CamelAgent(
|
|
151
|
+
role="Security Expert",
|
|
152
|
+
goal="Find vulnerabilities",
|
|
153
|
+
backstory="Security specialist",
|
|
154
|
+
llm_client=mock_client,
|
|
155
|
+
)
|
|
156
|
+
response = agent.review_code("def foo(): pass", review_type="security")
|
|
157
|
+
|
|
158
|
+
assert isinstance(response, CamelAgentResponse)
|
|
159
|
+
call_args = mock_client.chat_with_messages.call_args
|
|
160
|
+
messages = call_args[0][0]
|
|
161
|
+
assert any("security" in msg["content"].lower() for msg in messages)
|
|
162
|
+
|
|
163
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
164
|
+
def test_explain_code_brief(self, mock_create_client):
|
|
165
|
+
"""Test brief code explanation."""
|
|
166
|
+
mock_client = Mock()
|
|
167
|
+
mock_client.chat_with_messages.return_value = ChatResponse(
|
|
168
|
+
content="Brief explanation",
|
|
169
|
+
usage={},
|
|
170
|
+
model="kimi-k2.5",
|
|
171
|
+
finish_reason="stop",
|
|
172
|
+
)
|
|
173
|
+
mock_create_client.return_value = mock_client
|
|
174
|
+
|
|
175
|
+
agent = CamelAgent(
|
|
176
|
+
role="Explainer",
|
|
177
|
+
goal="Explain code",
|
|
178
|
+
backstory="Teacher",
|
|
179
|
+
llm_client=mock_client,
|
|
180
|
+
)
|
|
181
|
+
response = agent.explain_code("def foo(): pass", detail_level="brief")
|
|
182
|
+
|
|
183
|
+
assert isinstance(response, CamelAgentResponse)
|
|
184
|
+
call_args = mock_client.chat_with_messages.call_args
|
|
185
|
+
messages = call_args[0][0]
|
|
186
|
+
assert any("brief" in msg["content"].lower() for msg in messages)
|
|
187
|
+
|
|
188
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
189
|
+
def test_suggest_improvements(self, mock_create_client):
|
|
190
|
+
"""Test improvement suggestions."""
|
|
191
|
+
mock_client = Mock()
|
|
192
|
+
mock_client.chat_with_messages.return_value = ChatResponse(
|
|
193
|
+
content="Suggestions",
|
|
194
|
+
usage={},
|
|
195
|
+
model="kimi-k2.5",
|
|
196
|
+
finish_reason="stop",
|
|
197
|
+
)
|
|
198
|
+
mock_create_client.return_value = mock_client
|
|
199
|
+
|
|
200
|
+
agent = CamelAgent(
|
|
201
|
+
role="Improver",
|
|
202
|
+
goal="Suggest improvements",
|
|
203
|
+
backstory="Optimizer",
|
|
204
|
+
llm_client=mock_client,
|
|
205
|
+
)
|
|
206
|
+
response = agent.suggest_improvements(
|
|
207
|
+
"def foo(): pass",
|
|
208
|
+
focus_areas=["readability", "performance"],
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
assert isinstance(response, CamelAgentResponse)
|
|
212
|
+
call_args = mock_client.chat_with_messages.call_args
|
|
213
|
+
messages = call_args[0][0]
|
|
214
|
+
assert any("readability" in msg["content"] for msg in messages)
|
|
215
|
+
|
|
216
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
217
|
+
def test_answer_question(self, mock_create_client):
|
|
218
|
+
"""Test answering questions."""
|
|
219
|
+
mock_client = Mock()
|
|
220
|
+
mock_client.chat_with_messages.return_value = ChatResponse(
|
|
221
|
+
content="Answer",
|
|
222
|
+
usage={},
|
|
223
|
+
model="kimi-k2.5",
|
|
224
|
+
finish_reason="stop",
|
|
225
|
+
)
|
|
226
|
+
mock_create_client.return_value = mock_client
|
|
227
|
+
|
|
228
|
+
agent = CamelAgent(
|
|
229
|
+
role="Helper",
|
|
230
|
+
goal="Answer questions",
|
|
231
|
+
backstory="Assistant",
|
|
232
|
+
llm_client=mock_client,
|
|
233
|
+
)
|
|
234
|
+
response = agent.answer_question("What is this?", code_context="def foo(): pass")
|
|
235
|
+
|
|
236
|
+
assert isinstance(response, CamelAgentResponse)
|
|
237
|
+
assert response.content == "Answer"
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class TestMultiAgentRAG:
|
|
241
|
+
"""Tests for MultiAgentRAG."""
|
|
242
|
+
|
|
243
|
+
@patch("code_graph_builder.rag.camel_agent.CamelAgent")
|
|
244
|
+
def test_init(self, mock_agent_class):
|
|
245
|
+
"""Test initialization."""
|
|
246
|
+
mock_rag_engine = Mock()
|
|
247
|
+
mock_agent_instance = Mock()
|
|
248
|
+
mock_agent_class.return_value = mock_agent_instance
|
|
249
|
+
|
|
250
|
+
multi_agent = MultiAgentRAG(mock_rag_engine)
|
|
251
|
+
|
|
252
|
+
assert multi_agent.rag_engine == mock_rag_engine
|
|
253
|
+
# Should create 4 agents
|
|
254
|
+
assert mock_agent_class.call_count == 4
|
|
255
|
+
|
|
256
|
+
@patch("code_graph_builder.rag.camel_agent.CamelAgent")
|
|
257
|
+
def test_analyze(self, mock_agent_class):
|
|
258
|
+
"""Test multi-agent analysis."""
|
|
259
|
+
mock_rag_engine = Mock()
|
|
260
|
+
mock_rag_engine.query.return_value = Mock(
|
|
261
|
+
contexts=[Mock(format_context=Mock(return_value="context"))],
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
mock_agent = Mock()
|
|
265
|
+
mock_agent.analyze.return_value = CamelAgentResponse(content="Analysis")
|
|
266
|
+
mock_agent_class.return_value = mock_agent
|
|
267
|
+
|
|
268
|
+
multi_agent = MultiAgentRAG(mock_rag_engine)
|
|
269
|
+
results = multi_agent.analyze("Test query", analysis_types=["architecture"])
|
|
270
|
+
|
|
271
|
+
assert "architecture" in results
|
|
272
|
+
mock_rag_engine.query.assert_called_once_with("Test query")
|
|
273
|
+
|
|
274
|
+
@patch("code_graph_builder.rag.camel_agent.CamelAgent")
|
|
275
|
+
def test_comprehensive_review(self, mock_agent_class):
|
|
276
|
+
"""Test comprehensive review."""
|
|
277
|
+
mock_rag_engine = Mock()
|
|
278
|
+
mock_rag_engine.explain_code.return_value = Mock(
|
|
279
|
+
contexts=[Mock(source_code="def foo(): pass")],
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
mock_agent = Mock()
|
|
283
|
+
mock_agent.analyze.return_value = CamelAgentResponse(content="Analysis")
|
|
284
|
+
mock_agent.review_code.return_value = CamelAgentResponse(content="Review")
|
|
285
|
+
mock_agent.explain_code.return_value = CamelAgentResponse(content="Explanation")
|
|
286
|
+
mock_agent_class.return_value = mock_agent
|
|
287
|
+
|
|
288
|
+
multi_agent = MultiAgentRAG(mock_rag_engine)
|
|
289
|
+
results = multi_agent.comprehensive_review("test.foo")
|
|
290
|
+
|
|
291
|
+
assert "architecture" in results
|
|
292
|
+
assert "security" in results
|
|
293
|
+
assert "performance" in results
|
|
294
|
+
assert "documentation" in results
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class TestCreateCamelAgent:
|
|
298
|
+
"""Tests for create_camel_agent factory function."""
|
|
299
|
+
|
|
300
|
+
@patch("code_graph_builder.rag.camel_agent.create_llm_client")
|
|
301
|
+
def test_create_agent(self, mock_create_client):
|
|
302
|
+
"""Test creating agent."""
|
|
303
|
+
mock_client = Mock()
|
|
304
|
+
mock_create_client.return_value = mock_client
|
|
305
|
+
|
|
306
|
+
agent = create_camel_agent(
|
|
307
|
+
role="Tester",
|
|
308
|
+
goal="Test things",
|
|
309
|
+
backstory="Testing expert",
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
assert isinstance(agent, CamelAgent)
|
|
313
|
+
assert agent.role == "Tester"
|