full-stack-coding-assistant-agent 0.1.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.
agents/__init__.py ADDED
File without changes
agents/audit_agent.py ADDED
@@ -0,0 +1,223 @@
1
+ """
2
+ 代码审计智能体
3
+ 异步执行安全扫描、代码质量检查
4
+ """
5
+
6
+ import json
7
+ import re
8
+ from datetime import datetime
9
+ from typing import Dict, List
10
+
11
+ from agents.base_agent import BaseAgent
12
+
13
+
14
+ class AuditAgent(BaseAgent):
15
+ """代码审计专家 Agent"""
16
+
17
+ def get_system_prompt(self) -> str:
18
+ return """你是一位资深代码安全审计专家,精通 OWASP Top 10、代码质量分析。
19
+ 你的职责是:
20
+ 1. 检查代码安全漏洞(SQL 注入、XSS、CSRF 等)
21
+ 2. 分析代码质量和最佳实践
22
+ 3. 检查敏感信息泄露(API Key、密码等)
23
+ 4. 生成结构化审计报告
24
+
25
+ 输出格式(JSON):
26
+ 每个问题一行 JSON 对象,包含字段:
27
+ {
28
+ "severity": "high|medium|low",
29
+ "category": "安全|质量|性能",
30
+ "message": "问题描述",
31
+ "suggestion": "修复建议",
32
+ "line_number": 可选的行号
33
+ }
34
+ """
35
+
36
+ def _get_sub_dir(self) -> str:
37
+ return "audits"
38
+
39
+ def execute(self, task_id: str, context: Dict) -> Dict:
40
+ """
41
+ 执行代码审计任务(异步)
42
+
43
+ 流程:
44
+ 1. 获取待审计的代码
45
+ 2. 调用 LLM 进行审计
46
+ 3. 解析审计结果
47
+ 4. 保存到数据库
48
+ 5. 将审计报告写入文件系统
49
+ """
50
+ # 1. 获取待审计代码
51
+ code = context.get("code", "")
52
+ file_path = context.get("file_path", "unknown")
53
+ agent_type = context.get("agent_type", "unknown")
54
+
55
+ if not code:
56
+ return {"status": "skipped", "reason": "no code to audit"}
57
+
58
+ # 2. 调用 LLM 审计
59
+ system_prompt = self.get_system_prompt()
60
+ prompt = f"""请审计以下代码,找出安全漏洞和代码质量问题:
61
+
62
+ ## 代码
63
+ ```
64
+ {code}
65
+ ```
66
+
67
+ ## 文件路径
68
+ {file_path}
69
+
70
+ 请以 JSON 格式输出审计结果,每个问题一个 JSON 对象,包含字段:
71
+ - severity: 严重程度 (high/medium/low)
72
+ - category: 问题类别 (安全/质量/性能)
73
+ - message: 问题描述
74
+ - suggestion: 修复建议
75
+ - line_number: 问题所在行号(如果可确定)
76
+
77
+ 如果有多个问题,每行输出一个 JSON 对象。
78
+ """
79
+ audit_result = self._call_llm(prompt, temperature=0.2)
80
+
81
+ # 3. 解析审计结果
82
+ reports = self._parse_audit_result(audit_result)
83
+
84
+ # 4. 保存到数据库
85
+ for report in reports:
86
+ self.db.add_audit_report(
87
+ task_id=task_id,
88
+ agent_type=agent_type,
89
+ severity=report.get("severity", "low"),
90
+ message=report.get("message", ""),
91
+ file_path=file_path,
92
+ line_number=report.get("line_number"),
93
+ )
94
+
95
+ # 5. 将审计报告写入文件系统
96
+ audit_md = self._format_audit_report(reports, file_path, audit_result)
97
+ audit_filename = f"audits/audit_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
98
+ self._write_file(audit_filename, audit_md)
99
+
100
+ # 6. 返回结果
101
+ result = {
102
+ "status": "success",
103
+ "reports_count": len(reports),
104
+ "high_severity": sum(1 for r in reports if r.get("severity") == "high"),
105
+ "reports": reports,
106
+ "audit_file": audit_filename,
107
+ }
108
+ self._save_result(task_id, str(result))
109
+
110
+ # 7. 保存 Agent 执行 trace(完整 I/O 审计)
111
+ self._save_trace(
112
+ task_id=task_id,
113
+ system_prompt=system_prompt,
114
+ user_prompt=prompt,
115
+ llm_response=audit_result,
116
+ parsed_result=result,
117
+ )
118
+
119
+ return result
120
+
121
+ def _format_audit_report(
122
+ self, reports: List[Dict], file_path: str, raw_result: str
123
+ ) -> str:
124
+ """将审计结果格式化为 Markdown 报告"""
125
+ lines = [
126
+ "# 代码审计报告",
127
+ "",
128
+ f"- 审计时间: {datetime.now().isoformat()}",
129
+ f"- 审计文件: {file_path}",
130
+ f"- 发现问题数: {len(reports)}",
131
+ "",
132
+ "## 问题列表",
133
+ "",
134
+ ]
135
+ for i, r in enumerate(reports, 1):
136
+ lines.append(
137
+ f"### {i}. [{r.get('severity', 'low').upper()}] {r.get('category', '未知')}"
138
+ )
139
+ lines.append(f"- **描述**: {r.get('message', '')}")
140
+ lines.append(f"- **建议**: {r.get('suggestion', '')}")
141
+ if r.get("line_number"):
142
+ lines.append(f"- **行号**: {r.get('line_number')}")
143
+ lines.append("")
144
+
145
+ lines += ["## 原始审计输出", "", "```", raw_result, "```", ""]
146
+ return "\n".join(lines)
147
+
148
+ def _parse_audit_result(self, audit_text: str) -> List[Dict]:
149
+ """
150
+ 解析 LLM 返回的审计结果
151
+ 支持多种格式:
152
+ 1. ```json 代码块中的 JSON 数组或对象
153
+ 2. 裸 JSON 数组 [{{}}, {{}}]
154
+ 3. 每行一个 JSON 对象
155
+ """
156
+ reports = []
157
+
158
+ # 尝试 1: json 代码块(支持 ```json 和 ``` 两种格式)
159
+ json_match = re.search(r"```(?:json)?\s*\n?(.*?)\n?```", audit_text, re.DOTALL)
160
+ if json_match:
161
+ try:
162
+ data = json.loads(json_match.group(1).strip())
163
+ if isinstance(data, list):
164
+ return [r for r in data if isinstance(r, dict)]
165
+ elif isinstance(data, dict):
166
+ return [data]
167
+ except json.JSONDecodeError:
168
+ pass
169
+
170
+ # 尝试 2: 裸 JSON 数组或对象(整个文本就是 JSON)
171
+ stripped = audit_text.strip()
172
+ if stripped.startswith("[") or stripped.startswith("{"):
173
+ try:
174
+ data = json.loads(stripped)
175
+ if isinstance(data, list):
176
+ return [r for r in data if isinstance(r, dict)]
177
+ elif isinstance(data, dict):
178
+ return [data]
179
+ except json.JSONDecodeError:
180
+ pass
181
+
182
+ # 尝试 3: 逐行解析 JSON 对象
183
+ for line in audit_text.split("\n"):
184
+ line = line.strip()
185
+ if not line or not line.startswith("{"):
186
+ continue
187
+ try:
188
+ report = json.loads(line)
189
+ if "severity" in report and "message" in report:
190
+ reports.append(report)
191
+ except json.JSONDecodeError:
192
+ continue
193
+
194
+ return reports
195
+
196
+ def run_security_scan(self, task_id: str, code: str) -> Dict:
197
+ """
198
+ 执行安全扫描(同步,用于关键代码)
199
+
200
+ 检查常见安全漏洞:
201
+ - SQL 注入
202
+ - XSS
203
+ - 敏感信息泄露
204
+ - 不安全的依赖
205
+ """
206
+ prompt = f"""请对以下代码进行安全扫描,重点检查:
207
+
208
+ 1. SQL 注入漏洞
209
+ 2. XSS 跨站脚本
210
+ 3. CSRF 漏洞
211
+ 4. 敏感信息泄露(硬编码密码、API Key 等)
212
+ 5. 不安全的加密算法
213
+ 6. 权限绕过风险
214
+
215
+ 代码:
216
+ ```
217
+ {code}
218
+ ```
219
+
220
+ 只输出发现的安全问题,格式:
221
+ [SEVERITY] 问题描述 - 修复建议
222
+ """
223
+ return {"scan_result": self._call_llm(prompt, temperature=0.1)}
@@ -0,0 +1,179 @@
1
+ """
2
+ 后端专家智能体
3
+ 负责生成后端代码、API 接口,并提取 API 契约供前端使用
4
+ """
5
+
6
+ import json
7
+ import re
8
+ from typing import Dict, List, Optional
9
+
10
+ from agents.base_agent import BaseAgent
11
+
12
+
13
+ class BackendAgent(BaseAgent):
14
+ """后端专家 Agent"""
15
+
16
+ def get_system_prompt(self) -> str:
17
+ return """你是一位资深后端开发专家,精通 Python/Java/Node.js 后端开发。
18
+ 你的职责是:
19
+ 1. 根据需求生成高质量的后端代码
20
+ 2. 设计 RESTful API 接口
21
+ 3. 编写数据库模型和数据访问层
22
+ 4. 确保代码的安全性、性能和可维护性
23
+
24
+ 输出格式要求:
25
+ - 每个文件用 ### FILE: 标记,格式如下:
26
+ ### FILE: backend/main.py
27
+ ```python
28
+ # code here
29
+ ```
30
+ - 代码必须可直接运行
31
+ - API 接口必须包含完整的请求/响应 Schema
32
+ - 在代码注释中标注 API 契约信息(endpoint, method, request_schema, response_schema)
33
+ """
34
+
35
+ def execute(self, task_id: str, context: Dict) -> Dict:
36
+ """
37
+ 执行后端开发任务
38
+
39
+ 流程:
40
+ 1. 检查依赖
41
+ 2. 如果是迭代模式,读取已有代码注入 prompt
42
+ 3. 调用 LLM 生成后端代码
43
+ 4. 解析多文件输出并写入文件系统
44
+ 5. 提取 API 契约并保存到数据库
45
+ 6. 更新任务状态
46
+ """
47
+ # 1. 检查依赖
48
+ if not self._check_dependencies(context, ["description"]):
49
+ raise ValueError("缺少必需的任务描述")
50
+
51
+ description = context["description"]
52
+ requirements = context.get("requirements", "")
53
+ is_iteration = context.get("is_iteration", False)
54
+
55
+ # 2. 构建 prompt
56
+ prompt = f"""请根据以下需求生成后端代码:
57
+
58
+ ## 需求描述
59
+ {description}
60
+
61
+ ## 详细要求
62
+ {requirements}
63
+ """
64
+
65
+ # 迭代模式:注入已有代码
66
+ if is_iteration:
67
+ existing_code = self._collect_existing_code()
68
+ if existing_code:
69
+ prompt += f"""
70
+ ## 已有代码(请基于以下代码进行修改,不要重复生成已有文件)
71
+ {existing_code}
72
+
73
+ 重要:请只输出需要新增或修改的文件,不要重复输出未修改的文件。
74
+ """
75
+
76
+ prompt += """
77
+ 请生成完整的后端代码,每个文件用 ### FILE: 标记,格式如下:
78
+
79
+ ### FILE: backend/main.py
80
+ ```python
81
+ # code here
82
+ ```
83
+
84
+ ### FILE: backend/api.py
85
+ ```python
86
+ # code here
87
+ ```
88
+
89
+ 在代码中用注释标注 API 契约,格式如下:
90
+ ### API_CONTRACT_START
91
+ endpoint: /api/xxx
92
+ method: GET/POST/...
93
+ request_schema: {{...}}
94
+ response_schema: {{...}}
95
+ ### API_CONTRACT_END
96
+ """
97
+
98
+ # 3. 调用 LLM 生成代码
99
+ system_prompt = self.get_system_prompt()
100
+ code_result = self._call_llm(prompt, temperature=0.3)
101
+
102
+ # 4. 解析多文件输出并写入文件系统
103
+ files = self._parse_llm_code_output(code_result)
104
+ change_type = "update" if is_iteration else "create"
105
+ for file_path, content in files.items():
106
+ self._write_file(file_path, content)
107
+ self._log_change(
108
+ task_id=task_id,
109
+ file_path=file_path,
110
+ change_type=change_type,
111
+ diff=content,
112
+ )
113
+
114
+ # 5. 提取 API 契约
115
+ contracts = self._extract_api_contracts(code_result)
116
+ for contract in contracts:
117
+ self.db.save_api_contract(
118
+ task_id=task_id,
119
+ endpoint=contract["endpoint"],
120
+ method=contract["method"],
121
+ request_schema=contract.get("request_schema"),
122
+ response_schema=contract.get("response_schema"),
123
+ created_by="backend",
124
+ )
125
+
126
+ # 6. 保存结果
127
+ result = {
128
+ "status": "success",
129
+ "files": list(files.keys()),
130
+ "contracts": contracts,
131
+ }
132
+
133
+ # 7. 保存 Agent 执行 trace(完整 I/O 审计)
134
+ self._save_trace(
135
+ task_id=task_id,
136
+ system_prompt=system_prompt,
137
+ user_prompt=prompt,
138
+ llm_response=code_result,
139
+ parsed_result=result,
140
+ )
141
+ self._save_result(task_id, json.dumps(result))
142
+
143
+ return result
144
+
145
+ def _extract_api_contracts(self, code: str) -> List[Dict]:
146
+ """
147
+ 从生成的代码中提取 API 契约
148
+
149
+ 匹配格式:
150
+ ### API_CONTRACT_START
151
+ endpoint: /api/xxx
152
+ method: GET
153
+ request_schema: {...}
154
+ response_schema: {...}
155
+ ### API_CONTRACT_END
156
+ """
157
+ contracts = []
158
+ pattern = r"### API_CONTRACT_START(.*?)### API_CONTRACT_END"
159
+ matches = re.findall(pattern, code, re.DOTALL)
160
+
161
+ for match in matches:
162
+ contract = {}
163
+ lines = match.strip().split("\n")
164
+ for line in lines:
165
+ if ":" in line:
166
+ key, value = line.split(":", 1)
167
+ key = key.strip()
168
+ value = value.strip()
169
+ if key in ["endpoint", "method"]:
170
+ contract[key] = value
171
+ elif key in ["request_schema", "response_schema"]:
172
+ try:
173
+ contract[key] = json.loads(value)
174
+ except json.JSONDecodeError:
175
+ contract[key] = {"raw": value}
176
+ if "endpoint" in contract and "method" in contract:
177
+ contracts.append(contract)
178
+
179
+ return contracts