Initial commit to git.yoin

This commit is contained in:
hmo
2026-02-11 22:02:47 +08:00
commit cf10ab6473
153 changed files with 14581 additions and 0 deletions

217
uni-agent/adapters/aitp.py Normal file
View File

@@ -0,0 +1,217 @@
"""
AITP (Agent Interaction & Transaction Protocol) 适配器
NEAR 基金会提出的 Agent 交互与交易协议
参考: https://aitp.dev
"""
import json
import uuid
from pathlib import Path
from typing import Any, Dict, List, Optional
import aiohttp
from .base import ProtocolAdapter, Connection, AgentInfo
class AITPAdapter(ProtocolAdapter):
"""AITP 协议适配器"""
protocol_name = "aitp"
def __init__(self, config_dir: Optional[Path] = None):
self.config_dir = config_dir or Path(__file__).parent.parent / "config"
self._threads: Dict[str, dict] = {}
async def connect(self, agent_config: dict) -> Connection:
"""建立连接 - 创建 Thread"""
endpoint = agent_config.get("endpoint")
if not endpoint:
raise ValueError("AITP Agent 配置必须包含 endpoint")
thread_id = str(uuid.uuid4())
self._threads[thread_id] = {
"id": thread_id,
"messages": [],
"status": "open",
}
return Connection(
agent_id=agent_config.get("id", ""),
protocol=self.protocol_name,
endpoint=endpoint,
session=thread_id,
metadata={
"thread_id": thread_id,
"wallet": agent_config.get("wallet", {}),
}
)
async def call(
self,
connection: Connection,
method: str,
params: dict,
timeout: float = 30.0
) -> dict:
"""调用 AITP Agent"""
endpoint = connection.endpoint
thread_id = connection.session
wallet_config = connection.metadata.get("wallet", {})
headers = {
"Content-Type": "application/json",
}
if method == "message":
payload = {
"thread_id": thread_id,
"message": {
"role": "user",
"content": params.get("content", ""),
"parts": params.get("parts", []),
}
}
elif method == "payment":
payload = {
"thread_id": thread_id,
"capability": "aitp-01",
"payment_request": {
"amount": params.get("amount"),
"currency": params.get("currency", "NEAR"),
"recipient": params.get("recipient"),
"memo": params.get("memo", ""),
}
}
if wallet_config.get("type") == "near":
payload["wallet"] = {
"type": "near",
"account_id": wallet_config.get("account_id"),
}
elif method == "decision":
payload = {
"thread_id": thread_id,
"capability": "aitp-02",
"decision_request": {
"question": params.get("question"),
"options": params.get("options", []),
"allow_custom": params.get("allow_custom", False),
}
}
elif method == "data_request":
payload = {
"thread_id": thread_id,
"capability": "aitp-03",
"data_request": {
"schema": params.get("schema", {}),
"description": params.get("description", ""),
}
}
else:
payload = {
"thread_id": thread_id,
"method": method,
"params": params,
}
async with aiohttp.ClientSession() as session:
async with session.post(
f"{endpoint}/threads/{thread_id}/messages",
json=payload,
headers=headers,
timeout=aiohttp.ClientTimeout(total=timeout)
) as resp:
if resp.status == 200:
result = await resp.json()
if thread_id in self._threads:
self._threads[thread_id]["messages"].append(payload)
self._threads[thread_id]["messages"].append(result)
return {
"success": True,
"result": result,
"thread_id": thread_id,
}
else:
error_text = await resp.text()
return {
"success": False,
"error": f"HTTP {resp.status}: {error_text}",
}
async def discover(self, capability: str = "") -> List[AgentInfo]:
"""发现 Agent"""
agents_file = self.config_dir / "agents.yaml"
if not agents_file.exists():
return []
import yaml
with open(agents_file) as f:
config = yaml.safe_load(f)
agents = []
for agent in config.get("agents", []):
if agent.get("protocol") != "aitp":
continue
if capability and capability.lower() not in agent.get("id", "").lower():
continue
agents.append(AgentInfo(
id=f"{agent['id']}@aitp",
protocol="aitp",
name=agent.get("name", agent["id"]),
endpoint=agent.get("endpoint", ""),
metadata=agent
))
return agents
async def close(self, connection: Connection):
"""关闭连接 - 关闭 Thread"""
thread_id = connection.session
if thread_id in self._threads:
self._threads[thread_id]["status"] = "closed"
async def get_methods(self, connection: Connection) -> List[dict]:
"""获取支持的方法AITP 能力)"""
return [
{
"name": "message",
"description": "发送对话消息",
"inputSchema": {"content": "string"},
},
{
"name": "payment",
"description": "AITP-01: 发起支付请求",
"inputSchema": {
"amount": "number",
"currency": "string",
"recipient": "string",
},
},
{
"name": "decision",
"description": "AITP-02: 请求用户决策",
"inputSchema": {
"question": "string",
"options": "array",
},
},
{
"name": "data_request",
"description": "AITP-03: 请求结构化数据",
"inputSchema": {
"schema": "object",
"description": "string",
},
},
]
def validate_config(self, agent_config: dict) -> bool:
"""验证配置"""
return "endpoint" in agent_config