Files
2026-02-11 22:02:47 +08:00

166 lines
5.3 KiB
Python

#!/usr/bin/env python3
"""
A2A 测试服务器 - 简单的 Echo Agent
HTTP 服务,提供 Agent Card 和 JSON-RPC 端点
"""
import json
import uuid
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse
PORT = 8100
class A2AHandler(BaseHTTPRequestHandler):
tasks = {}
def log_message(self, format, *args):
pass
def send_json(self, data: dict, status: int = 200):
body = json.dumps(data, ensure_ascii=False).encode()
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", len(body))
self.end_headers()
self.wfile.write(body)
def do_GET(self):
path = urlparse(self.path).path
if path == "/.well-known/agent.json":
self.send_json({
"name": "Test A2A Agent",
"description": "A simple echo agent for testing",
"url": f"http://localhost:{PORT}/rpc",
"version": "1.0.0",
"capabilities": {
"streaming": False,
"pushNotifications": False
},
"skills": [
{
"id": "echo",
"name": "Echo",
"description": "Echo back the message",
"inputSchema": {
"type": "object",
"properties": {
"message": {"type": "string"}
}
}
},
{
"id": "greet",
"name": "Greet",
"description": "Greet the user",
"inputSchema": {
"type": "object",
"properties": {
"name": {"type": "string"}
}
}
}
],
"authentication": {
"schemes": ["none"]
}
})
else:
self.send_json({"error": "Not found"}, 404)
def do_POST(self):
path = urlparse(self.path).path
content_length = int(self.headers.get("Content-Length", 0))
body = self.rfile.read(content_length)
try:
request = json.loads(body)
except json.JSONDecodeError:
self.send_json({"error": "Invalid JSON"}, 400)
return
if path == "/rpc":
self.handle_rpc(request)
else:
self.send_json({"error": "Not found"}, 404)
def handle_rpc(self, request: dict):
method = request.get("method", "")
params = request.get("params", {})
req_id = request.get("id", str(uuid.uuid4()))
if method == "tasks/send":
task_id = params.get("id", str(uuid.uuid4()))
message = params.get("message", {})
content = message.get("parts", [{}])[0].get("text", "") if "parts" in message else message.get("content", "")
response_text = f"Echo: {content}"
A2AHandler.tasks[task_id] = {
"id": task_id,
"status": {"state": "completed"},
"history": [
message,
{"role": "agent", "parts": [{"type": "text", "text": response_text}]}
]
}
self.send_json({
"jsonrpc": "2.0",
"id": req_id,
"result": A2AHandler.tasks[task_id]
})
elif method == "tasks/get":
task_id = params.get("id", "")
if task_id in A2AHandler.tasks:
self.send_json({
"jsonrpc": "2.0",
"id": req_id,
"result": A2AHandler.tasks[task_id]
})
else:
self.send_json({
"jsonrpc": "2.0",
"id": req_id,
"error": {"code": -32000, "message": "Task not found"}
})
elif method == "tasks/cancel":
task_id = params.get("id", "")
if task_id in A2AHandler.tasks:
A2AHandler.tasks[task_id]["status"]["state"] = "canceled"
self.send_json({
"jsonrpc": "2.0",
"id": req_id,
"result": {"success": True}
})
else:
self.send_json({
"jsonrpc": "2.0",
"id": req_id,
"error": {"code": -32000, "message": "Task not found"}
})
else:
self.send_json({
"jsonrpc": "2.0",
"id": req_id,
"error": {"code": -32601, "message": f"Unknown method: {method}"}
})
def main():
server = HTTPServer(("localhost", PORT), A2AHandler)
print(f"A2A Test Server running on http://localhost:{PORT}")
print(f"Agent Card: http://localhost:{PORT}/.well-known/agent.json")
server.serve_forever()
if __name__ == "__main__":
main()