feat(agents): Phase 8.4-10.5 built-in plugins, bundled skills, coordinator

This commit is contained in:
2026-04-04 23:24:34 +08:00
parent 88955ed550
commit d18167826e
105 changed files with 14780 additions and 15685 deletions

View File

@@ -1,8 +1,11 @@
"""Plugin API 路由 - Phase 8.6"""
import os
import tempfile
import zipfile
from typing import Any
import httpx
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
@@ -167,3 +170,53 @@ async def add_to_marketplace(plugin: dict[str, str]) -> dict[str, str]:
_plugin_marketplace = [p for p in _plugin_marketplace if p.get("id") != plugin["id"]]
_plugin_marketplace.append(plugin)
return {"status": "added", "id": plugin["id"]}
@_marketplace_router.post("/plugins/{plugin_id}/download", response_model=dict[str, str])
async def download_plugin(plugin_id: str) -> dict[str, str]:
"""从市场下载并安装插件"""
# Find plugin in marketplace
plugin = None
for p in _plugin_marketplace:
if p.get("id") == plugin_id:
plugin = p
break
if not plugin:
raise HTTPException(
status_code=404, detail=f"Plugin '{plugin_id}' not found in marketplace"
)
download_url = plugin.get("download_url")
if not download_url:
raise HTTPException(status_code=400, detail="Plugin has no download URL")
try:
# Download the plugin archive
async with httpx.AsyncClient() as client:
response = await client.get(download_url, timeout=60.0)
response.raise_for_status()
archive_content = response.content
# Extract to temp directory and install
with tempfile.TemporaryDirectory() as temp_dir:
archive_path = os.path.join(temp_dir, "plugin.zip")
with open(archive_path, "wb") as f:
f.write(archive_content)
extract_dir = os.path.join(temp_dir, "extracted")
with zipfile.ZipFile(archive_path, "r") as zf:
zf.extractall(extract_dir)
# Install the plugin
manager = get_plugin_manager()
if manager.install(extract_dir):
return {"status": "installed", "plugin_id": plugin_id}
raise HTTPException(status_code=500, detail="Failed to install plugin")
except httpx.HTTPError as e:
raise HTTPException(status_code=502, detail=f"Download failed: {str(e)}")
except zipfile.BadZipFile:
raise HTTPException(status_code=502, detail="Invalid plugin archive")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Installation failed: {str(e)}")