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

216 lines
7.4 KiB
Python
Raw Permalink 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.
"""
LMOS (Language Model Operating System) 适配器
Eclipse 基金会孵化的企业级多 Agent 平台
参考: https://eclipse.dev/lmos/
"""
import json
import uuid
from pathlib import Path
from typing import Any, Dict, List, Optional
import aiohttp
from .base import ProtocolAdapter, Connection, AgentInfo
class LMOSAdapter(ProtocolAdapter):
"""LMOS 协议适配器"""
protocol_name = "lmos"
def __init__(self, config_dir: Optional[Path] = None):
self.config_dir = config_dir or Path(__file__).parent.parent / "config"
self._registry_cache: Dict[str, List[dict]] = {}
async def _discover_via_mdns(self) -> List[dict]:
"""通过 mDNS 发现本地 Agent简化实现"""
return []
async def _query_registry(self, registry_url: str, capability: str = "") -> List[dict]:
"""查询 Agent 注册中心"""
if registry_url in self._registry_cache:
return self._registry_cache[registry_url]
async with aiohttp.ClientSession() as session:
params = {}
if capability:
params["capability"] = capability
async with session.get(
f"{registry_url}/agents",
params=params,
timeout=aiohttp.ClientTimeout(total=15)
) as resp:
if resp.status == 200:
result = await resp.json()
agents = result.get("agents", [])
self._registry_cache[registry_url] = agents
return agents
return []
async def connect(self, agent_config: dict) -> Connection:
"""建立连接"""
endpoint = agent_config.get("endpoint")
registry_url = agent_config.get("registry_url")
if not endpoint and not registry_url:
raise ValueError("LMOS Agent 配置必须包含 endpoint 或 registry_url")
if registry_url and not endpoint:
agent_id = agent_config.get("id")
agents = await self._query_registry(registry_url)
for agent in agents:
if agent.get("id") == agent_id:
endpoint = agent.get("endpoint")
break
if not endpoint:
raise ValueError(f"在注册中心未找到 Agent: {agent_id}")
return Connection(
agent_id=agent_config.get("id", ""),
protocol=self.protocol_name,
endpoint=endpoint,
session=None,
metadata={
"registry_url": registry_url,
"group": agent_config.get("group"),
}
)
async def call(
self,
connection: Connection,
method: str,
params: dict,
timeout: float = 30.0
) -> dict:
"""调用 LMOS Agent"""
endpoint = connection.endpoint
headers = {
"Content-Type": "application/json",
}
if method == "invoke":
payload = {
"capability": params.get("capability"),
"input": params.get("input", {}),
"context": params.get("context", {}),
}
elif method == "route":
payload = {
"query": params.get("query"),
"context": params.get("context", {}),
}
elif method == "describe":
async with aiohttp.ClientSession() as session:
async with session.get(
f"{endpoint}/capabilities",
headers=headers,
timeout=aiohttp.ClientTimeout(total=timeout)
) as resp:
if resp.status == 200:
result = await resp.json()
return {"success": True, "result": result}
else:
return {"success": False, "error": f"HTTP {resp.status}"}
else:
payload = {
"method": method,
"params": params,
}
async with aiohttp.ClientSession() as session:
async with session.post(
f"{endpoint}/invoke",
json=payload,
headers=headers,
timeout=aiohttp.ClientTimeout(total=timeout)
) as resp:
if resp.status == 200:
result = await resp.json()
return {"success": True, "result": result}
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)
all_agents = []
for agent in config.get("agents", []):
if agent.get("protocol") != "lmos":
continue
if capability and capability.lower() not in agent.get("id", "").lower():
continue
all_agents.append(AgentInfo(
id=f"{agent['id']}@lmos",
protocol="lmos",
name=agent.get("name", agent["id"]),
endpoint=agent.get("endpoint", ""),
metadata=agent
))
for agent in config.get("agents", []):
if agent.get("protocol") != "lmos":
continue
registry_url = agent.get("registry_url")
if registry_url:
try:
remote_agents = await self._query_registry(registry_url, capability)
for ra in remote_agents:
all_agents.append(AgentInfo(
id=f"{ra['id']}@lmos",
protocol="lmos",
name=ra.get("name", ra["id"]),
endpoint=ra.get("endpoint", ""),
metadata=ra
))
except Exception:
pass
return all_agents
async def close(self, connection: Connection):
"""关闭连接"""
pass
async def get_methods(self, connection: Connection) -> List[dict]:
"""获取支持的方法"""
result = await self.call(connection, "describe", {})
if result.get("success"):
capabilities = result.get("result", {}).get("capabilities", [])
return [
{
"name": cap.get("id", cap.get("name")),
"description": cap.get("description", ""),
"inputSchema": cap.get("inputSchema", {}),
}
for cap in capabilities
]
return [
{"name": "invoke", "description": "调用 Agent 能力"},
{"name": "route", "description": "智能路由到最佳 Agent"},
{"name": "describe", "description": "获取 Agent 能力描述"},
]
def validate_config(self, agent_config: dict) -> bool:
"""验证配置"""
return "endpoint" in agent_config or "registry_url" in agent_config