| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- #!/usr/bin/env python3
- """
- 安装仓库内置的 AgentPack 到本地 agentpacks 目录。
- 用法(server 必须先运行):
- python scripts/install_builtin_packs.py
- 也可以不启动 server,直接写入 agentpacks_dir:
- python scripts/install_builtin_packs.py --offline
- 内置 pack 位置:agentexample/agentpacks/
- 安装目标: ~/.agentpaas/data/agentpacks/ (desktop 模式)
- ~/LambdAgentDesktop/agentpacks/ (如果是 desktop 模式且未改数据目录)
- """
- from __future__ import annotations
- import argparse
- import json
- import os
- import sys
- import zipfile
- import tempfile
- from pathlib import Path
- REPO_ROOT = Path(__file__).parent.parent.resolve()
- PACKS_SRC = REPO_ROOT / "agentexample" / "agentpacks"
- BUILTIN_PACKS = [
- "research.top-journal-reviewer",
- "research.literature-mapper",
- "research.grant-planner",
- ]
- def _zip_pack(pack_id: str, dest_dir: Path) -> str:
- pack_dir = PACKS_SRC / pack_id
- if not pack_dir.is_dir():
- sys.exit(f"❌ Pack 目录不存在: {pack_dir}")
- zip_path = str(dest_dir / f"{pack_id}.zip")
- with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
- for p in pack_dir.rglob("*"):
- if p.is_file():
- zf.write(p, p.relative_to(pack_dir))
- return zip_path
- def _default_packs_dir() -> str:
- """读取 ~/.agentpaas/config.json 或按 desktop 模式默认值推断 agentpacks_dir。"""
- cfg = Path.home() / ".agentpaas" / "config.json"
- try:
- with open(cfg) as f:
- data = json.load(f) or {}
- data_dir = data.get("data_dir", "")
- except Exception:
- data_dir = ""
- if not data_dir:
- # desktop 默认
- data_dir = str(Path.home() / "LambdAgentDesktop")
- return os.path.join(data_dir, "agentpacks")
- # ── 离线模式:直接调用 install_from_zip ──────────────────────────────────────
- def install_offline(packs_dir: str, packs: list[str]) -> None:
- from agentpaas.engine.agentpack_store import install_from_zip, get_installed
- os.makedirs(packs_dir, exist_ok=True)
- print(f"\n安装目标目录: {packs_dir}\n")
- with tempfile.TemporaryDirectory() as td:
- for pack_id in packs:
- existing = get_installed(packs_dir, pack_id)
- if existing:
- print(f" ✓ {pack_id} v{existing.version} — 已安装,跳过")
- continue
- zip_path = _zip_pack(pack_id, Path(td))
- try:
- pack = install_from_zip(zip_path, packs_dir)
- print(f" ✓ {pack_id} v{pack.version} — 安装完成")
- except Exception as e:
- print(f" ✗ {pack_id} — 失败: {e}", file=sys.stderr)
- # ── 在线模式:通过 HTTP API 安装(需要 server 运行)───────────────────────────
- def install_online(base_url: str, api_key: str, packs: list[str]) -> None:
- try:
- import requests
- except ImportError:
- sys.exit("缺少依赖: pip install requests")
- session = requests.Session()
- if api_key:
- session.headers["Authorization"] = f"Bearer {api_key}"
- print(f"\n连接 server: {base_url}\n")
- # 先列出已安装
- try:
- r = session.get(f"{base_url}/api/v1/agentpacks", timeout=5)
- r.raise_for_status()
- already = {p["id"] for p in r.json().get("agentpacks", [])}
- except Exception as e:
- sys.exit(f"❌ 无法连接 server: {e}\n 请先启动: uvicorn agentpaas.api.app:app --port 8000")
- with tempfile.TemporaryDirectory() as td:
- for pack_id in packs:
- if pack_id in already:
- print(f" ✓ {pack_id} — 已安装,跳过")
- continue
- zip_path = _zip_pack(pack_id, Path(td))
- r = session.post(
- f"{base_url}/api/v1/agentpacks/install",
- json={"zip_path": zip_path},
- timeout=30,
- )
- if r.status_code == 200:
- pack = r.json()["installed"]
- print(f" ✓ {pack['id']} v{pack['version']} — 安装完成")
- else:
- print(f" ✗ {pack_id} — HTTP {r.status_code}: {r.text[:120]}", file=sys.stderr)
- # ── CLI ───────────────────────────────────────────────────────────────────────
- def main() -> None:
- parser = argparse.ArgumentParser(
- description="安装仓库内置 AgentPack (research.* 三个 pack)",
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog="""
- 示例:
- # 离线安装(不需要 server 运行,推荐)
- python scripts/install_builtin_packs.py --offline
- # 在线安装(需要 server 先跑起来)
- python scripts/install_builtin_packs.py
- # 指定安装目录
- python scripts/install_builtin_packs.py --offline --packs-dir /data/agentpacks
- """,
- )
- parser.add_argument(
- "--offline", action="store_true",
- help="直接写入 agentpacks_dir,不需要 server 运行(推荐)",
- )
- parser.add_argument(
- "--packs-dir", default="",
- help="安装目标目录(默认:从 ~/.agentpaas/config.json 推断)",
- )
- parser.add_argument(
- "--url", default="http://127.0.0.1:8000",
- help="Server URL(在线模式,默认 http://127.0.0.1:8000)",
- )
- parser.add_argument(
- "--key", default="",
- help="API key(在线模式,默认从 ~/.agentpaas/config.json 读取)",
- )
- parser.add_argument(
- "--pack", action="append", dest="packs",
- help="只安装指定 pack(可多次指定,默认全部三个)",
- )
- args = parser.parse_args()
- packs = args.packs or BUILTIN_PACKS
- print(f"内置 Pack 源目录: {PACKS_SRC}")
- if args.offline:
- packs_dir = args.packs_dir or _default_packs_dir()
- install_offline(packs_dir, packs)
- else:
- # 读取 api_key
- api_key = args.key
- if not api_key:
- cfg = Path.home() / ".agentpaas" / "config.json"
- try:
- api_key = (json.load(open(cfg)) or {}).get("api_key", "")
- except Exception:
- pass
- install_online(args.url, api_key, packs)
- print('\n完成。在 webui 的"智能体包"页面可以看到已安装的 pack,点击"创建智能体"即可使用。\n')
- if __name__ == "__main__":
- main()
|