ADK-agents/my_agent/agent.py
2026-07-29 15:14:45 +08:00

147 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from google.adk.agents import LlmAgent
from google.adk.models.lite_llm import LiteLlm
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams
from google.adk.tools.function_tool import FunctionTool
from mcp.client.stdio import StdioServerParameters
import os
import asyncio
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# --- 使用 vLLM 端点的智能体 ---
api_base_url = os.getenv("VLLM_API_BASE", "https://9router.aqroid.cn/v1")
model_name = os.getenv("VLLM_MODEL", "")
api_key = os.getenv("VLLM_API_KEY", "")
# Agent 可访问的工作目录
WORKSPACE_DIR = os.getenv("AGENT_WORKSPACE_DIR", r"D:\nzy\workspace_git")
# --- 文件系统 MCP 工具 ---
filesystem_mcp = McpToolset(
connection_params=StdioConnectionParams(
server_params=StdioServerParameters(
command="npx",
args=[
"-y",
"@modelcontextprotocol/server-filesystem",
os.path.abspath(WORKSPACE_DIR),
],
),
timeout=30.0,
),
)
# --- 终端命令执行工具Python 原生,绕开 MCP 通信问题)---
async def run_command(command: str, cwd: str = None, timeout: int = 300) -> str:
"""
在终端中执行一条命令,返回输出结果。
Args:
command: 要执行的命令,如 'npm run build''python -m pytest'
cwd: 命令执行的工作目录,默认使用 AGENT_WORKSPACE_DIR
timeout: 超时时间(秒),默认 300
Returns:
命令执行结果stdout + stderr + 状态)
"""
if not command:
return "错误:命令不能为空"
work_dir = cwd or os.path.abspath(WORKSPACE_DIR)
if not os.path.isdir(work_dir):
return f"错误:工作目录不存在 {work_dir}"
try:
proc = await asyncio.create_subprocess_shell(
command,
cwd=work_dir,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
stdout_bytes, stderr_bytes = await asyncio.wait_for(
proc.communicate(), timeout=timeout
)
except asyncio.TimeoutError:
proc.kill()
await proc.wait()
return f"命令执行超时({timeout}秒): {command}"
except Exception as e:
return f"命令执行出错: {e}"
stdout = stdout_bytes.decode("utf-8", errors="replace")
stderr = stderr_bytes.decode("utf-8", errors="replace")
parts = []
if stdout:
parts.append(f"[stdout]\n{stdout}")
if stderr:
parts.append(f"[stderr]\n{stderr}")
output = "\n".join(parts) if parts else "(无输出)"
max_len = 10000
if len(output) > max_len:
output = output[:max_len] + f"\n\n...(输出已截断,共 {len(output)} 字符)"
status = "成功" if proc.returncode == 0 else f"失败 (退出码 {proc.returncode})"
return f"命令执行{status}\n{output}"
# 注册为 ADK 工具
run_command_tool = FunctionTool(run_command)
root_agent = LlmAgent(
model=LiteLlm(
model=model_name,
api_base=api_base_url,
api_key=api_key if api_key else None,
custom_llm_provider="openai",
),
name="dev_agent",
description="全栈开发子 Agent可以读写文件、浏览目录、执行开发任务。",
instruction=(
"你是一个全栈开发子 AgentDev Agent由主控调度执行具体的开发任务。\n"
"\n"
"## 工作流程\n"
"1. 先理解任务需求和项目上下文\n"
"2. 使用文件系统工具浏览项目结构、读取相关文件\n"
"3. 编写或修改代码\n"
"4. 使用 run_command 工具运行编译/构建/测试,确保代码可正常工作\n"
"5. 验证结果后,按指定格式报告完成情况\n"
"\n"
"## 工作边界\n"
"- 所有文件操作限定在分配的工作目录范围内\n"
"- 你拥有的工具:文件系统操作(读/写/列目录)、终端命令执行\n"
"- 你可以自主完成代码编写、bug 修复、样式调整、接口修改、简单重构\n"
"- 需要上报的情况:\n"
" • 架构设计或重大技术选型决策\n"
" • 依赖包版本不兼容导致的编译/运行时错误(需要升级/降级依赖时)\n"
" • 工具调用异常、环境配置问题、命令超时等非代码问题\n"
" • 超出你能力范围或不确定的问题\n"
"\n"
"## 编译/构建守则\n"
"- 写完代码后,优先运行编译或构建命令验证\n"
"- 编译报错时,先判断错误类型:\n"
" • 代码语法/逻辑错误 → 自行修复后重试\n"
" • 依赖缺失或版本不兼容 → 上报,由主控决定处理方式\n"
" • 环境/工具问题 → 上报\n"
"- 连续修复 3 次仍无法通过编译时,上报当前状态和所有错误信息\n"
"- 只有编译通过后才算任务完成\n"
"\n"
"## 报告格式\n"
"完成任务后,结构化报告:\n"
"**状态**:成功 / 部分完成 / 失败(需上报)\n"
"**修改的文件**:列出所有修改的文件路径\n"
"**变更摘要**:简述做了什么\n"
"**验证结果**:编译/测试是否通过,如有警告需列出\n"
"**需要主控关注**:如有需要上报的问题,详细说明"
),
tools=[filesystem_mcp, run_command_tool],
)