registry.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. """
  2. agent67v2.skills.registry — 微代理技能注册
  3. 将 5 个微代理注册为可复用的 Skill,
  4. 任何编排器都能通过 SkillRegistry 发现和调用它们。
  5. Lambda 语义:
  6. register_all() =
  7. let code = Skill("code-agent", from_config("code-agent.yml")) in
  8. let shell = Skill("shell-agent", from_config("shell-agent.yml")) in
  9. let web = Skill("web-agent", from_config("web-agent.yml")) in
  10. let mem = Skill("memory-agent", from_config("memory-agent.yml")) in
  11. let sys = Skill("system-agent", from_config("system-agent.yml")) in
  12. Γ_skills = {code, shell, web, mem, sys}
  13. 复用场景:
  14. - agent67v2 协调者通过 Handoff 调用
  15. - research67 编排器可以复用 code-agent 做代码实验
  16. - agentbuilder67 可以复用 web-agent 搜索参考配置
  17. - 新的编排器只需 SkillRegistry().get("code-agent") 即可使用
  18. """
  19. from __future__ import annotations
  20. import sys
  21. from pathlib import Path
  22. from typing import Dict, Optional
  23. # 路径设置
  24. AGENT_DIR = Path(__file__).resolve().parent.parent # agent67v2/
  25. AGENTS_DIR = AGENT_DIR / "agents"
  26. PROJECT_ROOT = AGENT_DIR.parent.parent # lambdagentpaas/
  27. sys.path.insert(0, str(PROJECT_ROOT))
  28. from lambdagent.skills import Skill, SkillSignature, SkillPack, SkillRegistry
  29. from lambdagent.core import Term, Context
  30. # ════════════════════════════════════════════════════════════
  31. # SubAgentTerm: 子代理作为 Lambda Term
  32. # ════════════════════════════════════════════════════════════
  33. class SubAgentTerm(Term):
  34. """
  35. 子代理的 Lambda 封装。
  36. 将 YAML 配置定义的子代理包装为一个可被 Skill/Handoff 调用的 Term。
  37. 实际执行时通过 from_config() 编译 YAML → 执行 ReAct 循环。
  38. Lambda 语义:
  39. SubAgentTerm(config_path) = λtask. from_config(config_path)(task)
  40. """
  41. def __init__(self, name: str, config_path: Path):
  42. super().__init__(name)
  43. self.config_path = config_path
  44. self._compiled = None # 延迟编译
  45. def _ensure_compiled(self):
  46. """延迟编译: 只在第一次调用时加载 YAML"""
  47. if self._compiled is None:
  48. try:
  49. from lambdagent.fromconfig.compiler import from_config
  50. self._compiled = from_config(str(self.config_path))
  51. except Exception as e:
  52. # 编译失败时 fallback: 返回错误信息
  53. self._compiled = None
  54. self._compile_error = str(e)
  55. def apply(self, input_val: any, ctx: Context | None = None) -> any:
  56. ctx = ctx or Context()
  57. # 解析输入
  58. if isinstance(input_val, str):
  59. try:
  60. import json
  61. data = json.loads(input_val)
  62. task = data.get("task", input_val)
  63. except (json.JSONDecodeError, AttributeError):
  64. task = input_val
  65. elif isinstance(input_val, dict):
  66. task = input_val.get("task", str(input_val))
  67. else:
  68. task = str(input_val)
  69. import time
  70. t0 = time.time()
  71. self._ensure_compiled()
  72. if self._compiled is not None:
  73. result = self._compiled.apply(task, ctx)
  74. else:
  75. # 编译失败,直接返回错误
  76. result = f"[{self._name}] 编译失败: {getattr(self, '_compile_error', 'unknown')}"
  77. elapsed = (time.time() - t0) * 1000
  78. ctx.log(f"SubAgent:{self._name}", self._trace_id, str(task)[:100],
  79. str(result)[:100], elapsed)
  80. return result
  81. # ════════════════════════════════════════════════════════════
  82. # 微代理定义
  83. # ════════════════════════════════════════════════════════════
  84. AGENT_DEFINITIONS = {
  85. "code-agent": {
  86. "config": "code-agent.yml",
  87. "description": "代码文件操作与 Git 版本控制专家",
  88. "tags": ["code", "file", "git", "test", "编程", "代码"],
  89. },
  90. "shell-agent": {
  91. "config": "shell-agent.yml",
  92. "description": "终端命令执行专家,安全可控的 Shell 操作",
  93. "tags": ["shell", "bash", "terminal", "命令", "终端", "脚本"],
  94. },
  95. "web-agent": {
  96. "config": "web-agent.yml",
  97. "description": "网络搜索、知识库管理与文档生成专家",
  98. "tags": ["web", "search", "knowledge", "doc", "网络", "搜索", "知识库"],
  99. },
  100. "memory-agent": {
  101. "config": "memory-agent.yml",
  102. "description": "记忆存储、任务管理、定时调度与用户画像专家",
  103. "tags": ["memory", "task", "schedule", "notify", "记忆", "任务", "调度"],
  104. },
  105. "system-agent": {
  106. "config": "system-agent.yml",
  107. "description": "macOS 系统控制: 浏览器、应用、系统信息、截图",
  108. "tags": ["system", "browser", "app", "screenshot", "macOS", "系统"],
  109. },
  110. }
  111. # 自动注册 research skill pack (如果可用)
  112. def _register_research_skills():
  113. """注册 research skill pack 到 SkillRegistry"""
  114. try:
  115. from lambdagent.skillpacks.research import register_all as register_research
  116. register_research()
  117. except ImportError:
  118. pass # research skill pack 不可用时静默跳过
  119. # ════════════════════════════════════════════════════════════
  120. # 注册函数
  121. # ════════════════════════════════════════════════════════════
  122. def create_agent_skill(name: str, definition: dict) -> Skill:
  123. """创建一个微代理的 Skill"""
  124. config_path = AGENTS_DIR / definition["config"]
  125. term = SubAgentTerm(name, config_path)
  126. return Skill(
  127. name=name,
  128. term=term,
  129. description=definition["description"],
  130. signature=SkillSignature(input_type="Str", output_type="Str"),
  131. tags=definition["tags"],
  132. version="2.0.0",
  133. author="agent67v2",
  134. )
  135. def register_all() -> SkillPack:
  136. """
  137. 注册所有微代理为 Skill,返回 SkillPack。
  138. 调用后,任何地方都可以通过以下方式使用:
  139. registry = SkillRegistry()
  140. code_agent = registry.get("code-agent")
  141. result = code_agent.apply("读取 main.py")
  142. """
  143. pack = SkillPack(
  144. name="agent67v2",
  145. description="agent67v2 多智能体协作系统的 5 个专业微代理",
  146. version="2.0.0",
  147. author="agent67v2",
  148. )
  149. for name, definition in AGENT_DEFINITIONS.items():
  150. skill = create_agent_skill(name, definition)
  151. pack.add(skill)
  152. # 注册到全局 Registry
  153. registry = SkillRegistry()
  154. registry.register_pack(pack)
  155. # 同时注册 research skill pack
  156. _register_research_skills()
  157. return pack
  158. def get_agent_skill(name: str) -> Optional[Skill]:
  159. """获取单个微代理的 Skill"""
  160. registry = SkillRegistry()
  161. skill = registry.get(name)
  162. if skill is None:
  163. # 尝试注册后获取
  164. register_all()
  165. skill = registry.get(name)
  166. return skill
  167. def build_handoff_registry() -> Dict[str, Term]:
  168. """
  169. 构建 Handoff 路由表。
  170. 返回 {agent_name: Term} 字典,可直接传给 Handoff 构造。
  171. """
  172. register_all()
  173. registry = SkillRegistry()
  174. return {
  175. name: registry.get(name)
  176. for name in AGENT_DEFINITIONS.keys()
  177. if registry.get(name) is not None
  178. }
  179. # ════════════════════════════════════════════════════════════
  180. # 自动注册 (import 时执行)
  181. # ════════════════════════════════════════════════════════════
  182. _pack = None
  183. def ensure_registered() -> SkillPack:
  184. """确保微代理已注册 (幂等)"""
  185. global _pack
  186. if _pack is None:
  187. _pack = register_all()
  188. return _pack