跳转至

Extension Attributes

@extension_attr 把扩展的元数据声明在入口函数上,框架据此做版本门控、数据目录分版与 CLI 注册。

from xun import ExtensionContext, extension_attr

@extension_attr(
    api_min_version="1.4.0",     # 需要的最低 xun 版本
    api_max_version="1.9.9",     # 需要的最高 xun 版本(含)
    data_version="2",            # 数据布局版本
    cli=(build_parser(), run),   # 交给 `xune <名字>` 的解析器与处理函数
)
def setup_extension(ctx: ExtensionContext) -> None: ...

四个参数全可省略;装饰器返回原函数,元数据挂在函数属性 __xun_extension_attr 上。

版本门

参数 语义
api_min_version 当前版本低于它 → 跳过
api_max_version 当前版本高于它 → 跳过

比较只看数字核心:1.2rc3 与 1.2 等价,1.4 与 1.4.0 等价(短的补零), 后缀(dev、rc、post)不参与比较。区间两端都是闭区间。

被门挡下时状态是 skipped 而不是 failed,reason 形如 requires xun >= 1.4.0, running 1.3.0,在 /extensions 里能看到。

源码运行时不做版本检查

xun_version() 读的是包元数据(importlib.metadata.version("xun-agent")), 源码直接跑(未安装发行版)时返回 None,此时版本检查直接通过。 所以本地开发时不会因为版本声明被跳过,装了包之后才会真正生效。

data_version

data_version 不是「数据内容的版本」,而是目录布局的版本:声明后数据目录多一层 data_v_<版本>。

声明 实际目录
未声明 $XUN_HOME/extension_data/<扩展名>/
data_version="2" $XUN_HOME/extension_data/<扩展名>/data_v_2/
  • 取值必须是单个安全路径段:\w[\w.+-]*,不能以点开头、不能带路径分隔符,否则构造 ExtensionAttr 时即报错。
  • 提高版本等于「从零开始」:旧目录不会被删除或迁移,需要自己搬。
  • extension_data_dir(name, data_version) 是同一个规则的公开版本, 外部工具(比如 xune 的 CLI)可以据此在不进入扩展上下文的情况下定位数据目录。

cli

cli=(parser, handler):parser 是 argparse.ArgumentParser,handler 接收解析后的 Namespace,返回 int 即作为进程退出码。由 xune <名字> 运行,详见 扩展 CLI 入口 xune。

ExtensionContext

setup_extension(ctx) 只拿到这一个对象,它每次 initialize() 都是新的:

成员 说明
ctx.agent 尚未初始化的 Agent,扩展的全部作用点都在这里
ctx.name 扩展名,也是 extension_settings 与数据目录用的键
ctx.settings agent.config.extension_settings[ctx.name],未配置时为 {};值已经过环境变量替换
ctx.data_dir(_create=True) 私有数据目录(按 data_version 分层),默认顺带创建;_create=False 只做路径解析不落盘(测试用)
config.json
{
  "extension_settings": {
    "my-extension": {
      "endpoint": "${XUN_MY_ENDPOINT}",
      "verbose": true
    }
  }
}
def setup_extension(ctx: ExtensionContext) -> None:
    endpoint = ctx.settings.get("endpoint", "")
    cache = ctx.data_dir() / "cache.json"

状态一览

/extensions(以及 Web 上的 ShowExtensionsEvent)按扩展列出:

字段 来源
名称 文件名或目录名
描述 入口函数的 docstring
路径 源文件路径
状态 uninitialized / loaded / skipped / failed
原因 skipped 与 failed 时的说明

程序内取同样的数据:ExtensionLoader.infos();只要成功导入的:imported()。

三个内置扩展的声明

扩展 声明
mcp api_min_version="1.3.0"
skills api_min_version="1.4.0"
stat api_min_version="1.4.0", data_version=DATA_VERSION, cli=(build_parser(), cli.run)

抄一个最接近的改成自己的,通常比从零写更快。