7.5 KiB
Skill 来源模型
背景
skiff 当前使用 owned 表示本仓库 skills/ 中维护的 Skill,同时还支持
registry 外部仓库和用户配置的 custom source。
这些名称混合了不同维度:
owned表示所有权。registry表示来源配置存放在哪里。external表示内容不在当前仓库。collection表示一个来源中包含多个 Skill。
它们不能作为同一层级的互斥类型。例如 custom source 既可能来自外部 Git 仓库,
也可能是 collection;因此 custom 与 external 并不互斥。
本文建议将用户可见的来源注册方式统一为三类:
builtin:随当前 skiff 仓库提供的 Skill。catalog:<name>:由 skiff 自带目录预先登记的来源。custom:<name>:用户在本机显式配置的命名来源。
来源注册方式与获取方式、仓库布局相互独立。builtin、catalog 和 custom 中的任意 来源都可以包含一个或多个 Skill;除 builtin 外,catalog 和 custom 都可以使用 Git 仓库或本地目录。
迁移前模型
flowchart TD
S[skiff 可发现的 Skills]
S --> O["owned<br/>~/.skills/skills/*"]
S --> C["custom source<br/>~/.config/skiff/config.yaml"]
S --> R["registry<br/>registry.yaml"]
O --> O1["本仓库维护<br/>随 skiff 一起分发"]
C --> C1["本地目录<br/>--local PATH"]
C --> C2["指定 Git 仓库<br/>repo + skills_path"]
R --> R1["外部单 Skill 仓库"]
R --> R2["外部 Skill Collection"]
R1 --> E["~/.local/share/skills/externals/"]
R2 --> E
迁移前实现中:
list和status支持 owned、registry 和 custom source。resolve_skill_source可以解析三种来源并处理同名歧义。select只组装 owned 和 registry 条目,尚未展示 custom source。.skills.yaml默认将未声明来源的 Skill 解释为owned。- custom source 的
skills_path已经可以包含多个 Skill,本质上也是 collection。
现行模型
flowchart TD
A[Skill Provider]
A --> B["builtin<br/>仓库内隐式注册"]
A --> C["catalog:waza<br/>skiff 预置目录"]
A --> D["custom:company<br/>用户本机配置"]
B --> B1["skills/ack"]
B --> B2["skills/skiff"]
B --> B3["skills/deb-publisher"]
C --> C1["Git 或本地目录"]
C1 --> C2["单 Skill"]
C1 --> C3["Collection"]
C3 --> C4["waza/think"]
C3 --> C5["waza/check"]
D --> D1["Git 或本地目录"]
D1 --> D2["单 Skill"]
D1 --> D3["Collection"]
D3 --> D4["company/security-review"]
D3 --> D5["company/release"]
来源注册方式
| 类型 | 含义 | 配置来源 | 用户界面展示 |
|---|---|---|---|
builtin |
随当前 skiff 仓库提供 | skills/ |
builtin |
catalog |
skiff 预先登记、所有用户可发现的来源 | catalog.yaml |
catalog:<name> |
custom |
用户在本机显式注册的命名来源 | ~/.config/skiff/config.yaml |
custom:<name> |
builtin 比 owned 更适合作为用户可见名称,因为它表达 Skill 的分发位置和可用
方式,而不是仓库的所有权关系。
catalog 比 registry 更准确:当前文件只是 skiff 随仓库维护的预置来源目录,
并不是远程注册中心,也不是一种 Skill 来源协议。
三个正交维度
每个 provider 应由三个维度描述:
registration: builtin | catalog | custom
transport: bundled | local | git
layout: single | collection
custom source 示例:
registration: custom
name: company
transport: local | git
layout: single | collection
catalog entry 示例:
registration: catalog
name: waza
transport: local | git
layout: single | collection
external 只适合描述物理位置,可作为 catalog 和部分 custom provider 的统称,
不应成为与 builtin、custom 并列的持久化类型。
select 展示
skiff select 应同时展示 builtin、catalog 和 custom Skill:
[ ] ack builtin
[ ] deb-publisher builtin
[-] company custom source
[ ] company/release custom:company
[ ] company/security-review custom:company
[-] waza catalog source
[ ] waza/check catalog:waza
[ ] waza/think catalog:waza
建议遵循以下规则:
- builtin Skill 直接显示 Skill 名称。
- catalog 和 custom collection 都使用来源名称作为父节点。
- catalog 和 custom Skill 都使用
<source>/<skill>作为选择器键。 - 单 Skill 来源可以省略父节点,但仍显示注册方式和来源名称。
- 不同来源安装后名称相同时,继续拒绝同时选择,避免覆盖同一安装路径。
配置表示
新写入的 .skills.yaml 使用以下形式:
skills:
- name: ack
source: builtin
- name: security-review
source: company
- name: think
source: catalog:waza
custom source 在 manifest 中继续保存其逻辑名称,例如 company。这样不同机器可以
独立配置仓库地址,而项目只依赖稳定的来源名称。
兼容策略
用户可见术语已经调整,并保留以下读取兼容,避免已有项目立即失效:
- 对外文档、CLI 输出和 selector 统一使用
builtin、catalog:<name>和custom:<name>。 - 新生成的
.skills.yaml对内置 Skill 写入source: builtin。 - 读取旧 manifest 时继续接受
source: owned,并在解析时归一化为builtin。 - CLI 参数在过渡期继续接受
--source owned,但帮助和输出只推荐builtin。 - 读取旧 manifest 中的
source: registry和registry: <name>,归一化为catalog:<name>。 - 主文件使用
catalog.yaml;不存在时兼容读取旧registry.yaml。 - custom source 的逻辑名称和现有
config.yaml结构保持不变。 - 将
builtin、catalog和兼容别名owned、registry设为 custom source 保留字。 select同步接入 custom Skill,并让 custom collection 与 catalog collection 使用相同的父子展示逻辑。
实现范围
当前实现覆盖:
skiff/skills.py:来源解析、归一化和 builtin 命名。skiff/project.py:manifest 默认值、序列化与旧值兼容。skiff/sources.py:来源保留字。skiff/catalog.py:catalog 配置、checkout 与 Skill 发现。skiff/cli.py:list、status、add、select和输出文案。skiff/selector.py:统一 catalog/custom collection 的父子展示。- CLI 与来源解析测试。
- 根 README、
skiff/README.md、skills/skiff/SKILL.md和相关示例。
验证要求
实施完成后至少覆盖:
- builtin Skill 可以通过新名称列出、选择、安装和写入 manifest。
- 旧的
source: ownedmanifest 仍可同步。 - custom local source 和 custom Git source 都出现在 selector 中。
- catalog 单 Skill 和 Collection 都保持可选择。
- custom 单 Skill 和 Collection 都保持可选择。
- 多来源同名 Skill 必须显式指定来源。
- 两个选择最终安装为同一个名称时,selector 拒绝冲突。
list、status、select对同一来源使用一致术语。
设计前提
迁移前 registry.yaml 的真实职责只是维护 skiff 预置的来源目录,而不是提供远程
发布、版本解析或可信签名等注册中心能力,因此现已改为 catalog.yaml。如果未来
实现真正的远程 registry,应单独定义其协议和与 catalog 的同步关系,不复用旧名称。