docs: add ai skill manager design spec
This commit is contained in:
461
docs/superpowers/specs/2026-05-13-ai-skill-manager-design.md
Normal file
461
docs/superpowers/specs/2026-05-13-ai-skill-manager-design.md
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
# AI Skill Manager Windows 设计规格
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
本项目是一个基于 Wails 的 Windows 桌面应用,用于从 Gitea 组织仓库中发现、下载、更新和安装 AI skill。首版面向 Codex 和 Claude 两个目标应用,后续可以扩展到其他应用。
|
||||||
|
|
||||||
|
项目约束:
|
||||||
|
|
||||||
|
- 不使用 git worktree。
|
||||||
|
- 一个 Gitea 仓库对应一个 skill。
|
||||||
|
- 只有仓库根目录存在 `SKILL.md` 时,才认为该仓库是有效 skill。
|
||||||
|
- 本地只保留一份 skill 仓库,安装到目标应用时使用 Windows 目录 Junction,不复制完整目录。
|
||||||
|
|
||||||
|
## 首版范围
|
||||||
|
|
||||||
|
首版包含三类页面:
|
||||||
|
|
||||||
|
1. 配置页
|
||||||
|
2. 远程市场页
|
||||||
|
3. 本地管理页
|
||||||
|
|
||||||
|
首版支持:
|
||||||
|
|
||||||
|
- 配置 Gitea `baseURL`、认证方式、账号密码或 Token、组织名。
|
||||||
|
- 默认使用账号密码认证,同时支持 Token 认证。
|
||||||
|
- 从指定 Gitea 组织读取仓库列表。
|
||||||
|
- 只展示根目录存在 `SKILL.md` 的仓库。
|
||||||
|
- 将 skill 仓库 clone 到本地应用数据目录。
|
||||||
|
- 对已下载仓库执行手动更新和自动更新。
|
||||||
|
- 将本地 skill 通过 Junction 安装到 Codex 和 Claude。
|
||||||
|
- 从 Codex 和 Claude 卸载本软件创建的 Junction。
|
||||||
|
- 删除本地 skill 仓库。
|
||||||
|
- 使用 VS Code 打开 skill 目录。
|
||||||
|
- 使用资源管理器打开 skill 目录。
|
||||||
|
|
||||||
|
首版不包含:
|
||||||
|
|
||||||
|
- 多 Gitea 实例或多组织同时管理。
|
||||||
|
- GitHub、GitLab 或其他代码托管源。
|
||||||
|
- skill 版本选择、回滚和发布管理。
|
||||||
|
- 自动解决本地未提交改动。
|
||||||
|
- 批量安装、批量卸载和批量删除。
|
||||||
|
|
||||||
|
## 路径约定
|
||||||
|
|
||||||
|
应用数据目录:
|
||||||
|
|
||||||
|
```text
|
||||||
|
%APPDATA%\sgg-ai-skill-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
配置文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
%APPDATA%\sgg-ai-skill-manager\config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
状态文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
%APPDATA%\sgg-ai-skill-manager\state.json
|
||||||
|
```
|
||||||
|
|
||||||
|
本地仓库目录:
|
||||||
|
|
||||||
|
```text
|
||||||
|
%APPDATA%\sgg-ai-skill-manager\repos\{org}\{repo}
|
||||||
|
```
|
||||||
|
|
||||||
|
Codex skill 目录:
|
||||||
|
|
||||||
|
```text
|
||||||
|
C:\Users\{user}\.codex\skills
|
||||||
|
```
|
||||||
|
|
||||||
|
Claude skill 目录:
|
||||||
|
|
||||||
|
```text
|
||||||
|
C:\Users\{user}\.claude\skills
|
||||||
|
```
|
||||||
|
|
||||||
|
## 认证设计
|
||||||
|
|
||||||
|
配置页提供两种认证方式:
|
||||||
|
|
||||||
|
- 账号密码认证,作为默认方式。
|
||||||
|
- Token 认证,作为可选方式。
|
||||||
|
|
||||||
|
敏感信息不明文写入 `config.json`。配置文件只保存认证方式和凭据引用标识,真实密码或 Token 优先保存到 Windows Credential Manager。
|
||||||
|
如果 Windows Credential Manager 写入失败,保存配置失败并提示用户,不降级为明文保存。
|
||||||
|
|
||||||
|
Gitea API 调用规则:
|
||||||
|
|
||||||
|
- 账号密码模式使用 Basic Auth。
|
||||||
|
- Token 模式使用 `Authorization: token <token>`。
|
||||||
|
|
||||||
|
Git clone 和 pull 的认证规则:
|
||||||
|
|
||||||
|
- 首版优先调用系统 `git`。
|
||||||
|
- 账号密码或 Token 仅在执行 git 命令时从 Credential Manager 读取到内存中使用,不写入 `config.json`、`state.json` 或仓库 remote URL。
|
||||||
|
- clone 后仓库 remote URL 保存为不含密码和 Token 的普通 HTTPS URL。
|
||||||
|
- 如果认证失败,错误显示在对应仓库状态上,不阻塞整个应用。
|
||||||
|
|
||||||
|
## Gitea 仓库发现
|
||||||
|
|
||||||
|
远程市场页通过 Gitea API 读取组织仓库:
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/v1/orgs/{org}/repos
|
||||||
|
```
|
||||||
|
|
||||||
|
列表需要分页加载。每个仓库再检查根目录是否存在 `SKILL.md`。只有检查通过的仓库出现在远程市场页。
|
||||||
|
|
||||||
|
远程市场页展示字段:
|
||||||
|
|
||||||
|
- 仓库名
|
||||||
|
- 描述
|
||||||
|
- 默认分支
|
||||||
|
- 最近更新时间
|
||||||
|
- 本地状态:未下载、已下载、可更新、检查失败
|
||||||
|
|
||||||
|
搜索行为:
|
||||||
|
|
||||||
|
- 首版在已加载的远程仓库结果中按名称和描述进行本地过滤。
|
||||||
|
- 后续可以扩展为服务端搜索。
|
||||||
|
|
||||||
|
## 页面设计
|
||||||
|
|
||||||
|
### 配置页
|
||||||
|
|
||||||
|
配置项:
|
||||||
|
|
||||||
|
- Gitea baseURL
|
||||||
|
- 认证方式:账号密码或 Token
|
||||||
|
- 用户名
|
||||||
|
- 密码
|
||||||
|
- Token
|
||||||
|
- 组织名
|
||||||
|
- 自动更新开关,默认开启
|
||||||
|
- 启动时检查更新开关,默认开启
|
||||||
|
- 定时检查间隔,默认 60 分钟
|
||||||
|
|
||||||
|
操作:
|
||||||
|
|
||||||
|
- 保存配置
|
||||||
|
- 测试连接
|
||||||
|
|
||||||
|
测试连接需要验证:
|
||||||
|
|
||||||
|
- baseURL 可访问
|
||||||
|
- 凭据有效
|
||||||
|
- 当前账号能访问指定组织
|
||||||
|
|
||||||
|
### 远程市场页
|
||||||
|
|
||||||
|
远程市场页用于发现和下载 skill。
|
||||||
|
|
||||||
|
主要控件:
|
||||||
|
|
||||||
|
- 搜索框
|
||||||
|
- 刷新按钮
|
||||||
|
- 仓库列表
|
||||||
|
|
||||||
|
仓库操作:
|
||||||
|
|
||||||
|
- 下载:本地不存在时执行 `git clone`
|
||||||
|
- 更新:本地存在时执行更新检查和 `git pull`
|
||||||
|
- 打开本地:本地存在时打开目录
|
||||||
|
|
||||||
|
下载目标:
|
||||||
|
|
||||||
|
```text
|
||||||
|
%APPDATA%\sgg-ai-skill-manager\repos\{org}\{repo}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 本地管理页
|
||||||
|
|
||||||
|
本地管理页用于管理已下载 skill 和目标应用安装状态。
|
||||||
|
|
||||||
|
建议使用表格布局,字段包括:
|
||||||
|
|
||||||
|
- 名称
|
||||||
|
- 本地路径
|
||||||
|
- 当前 commit
|
||||||
|
- 更新状态
|
||||||
|
- Codex 安装状态
|
||||||
|
- Claude 安装状态
|
||||||
|
- 操作
|
||||||
|
|
||||||
|
操作包括:
|
||||||
|
|
||||||
|
- 手动更新
|
||||||
|
- 安装到 Codex
|
||||||
|
- 卸载 Codex
|
||||||
|
- 安装到 Claude
|
||||||
|
- 卸载 Claude
|
||||||
|
- VS Code 打开
|
||||||
|
- 文件夹打开
|
||||||
|
- 删除本地
|
||||||
|
|
||||||
|
VS Code 打开使用:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
code . -n
|
||||||
|
```
|
||||||
|
|
||||||
|
命令执行目录为对应 skill 本地仓库目录。
|
||||||
|
|
||||||
|
文件夹打开使用 Windows 资源管理器打开对应目录。
|
||||||
|
|
||||||
|
## Junction 安装语义
|
||||||
|
|
||||||
|
安装到 Codex 或 Claude 时,不复制 skill 文件,而是在目标 skills 目录创建同名 Junction。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```text
|
||||||
|
C:\Users\{user}\.codex\skills\{repo}
|
||||||
|
-> %APPDATA%\sgg-ai-skill-manager\repos\{org}\{repo}
|
||||||
|
|
||||||
|
C:\Users\{user}\.claude\skills\{repo}
|
||||||
|
-> %APPDATA%\sgg-ai-skill-manager\repos\{org}\{repo}
|
||||||
|
```
|
||||||
|
|
||||||
|
安装规则:
|
||||||
|
|
||||||
|
- 如果目标 skills 目录不存在,安装时创建该目录。
|
||||||
|
- 如果目标路径不存在,创建 Junction。
|
||||||
|
- 如果目标路径是本软件记录的 Junction,且指向当前 skill 本地路径,可以重建或保持不变。
|
||||||
|
- 如果目标路径是普通目录、文件、或指向其他位置的 Junction,标记为冲突,不自动删除。
|
||||||
|
- 安装成功后写入 `state.json`。
|
||||||
|
|
||||||
|
卸载规则:
|
||||||
|
|
||||||
|
- 只卸载本软件记录的目标。
|
||||||
|
- 删除前再次确认目标是 Junction,且指向当前 skill 本地路径。
|
||||||
|
- 确认通过后,只删除 Junction 本身,不删除本地 skill 仓库。
|
||||||
|
- 如果目标不是预期 Junction,卸载失败并提示冲突。
|
||||||
|
|
||||||
|
删除本地 skill 规则:
|
||||||
|
|
||||||
|
- 如果 skill 已安装到 Codex 或 Claude,先卸载对应 Junction。
|
||||||
|
- 如果任一 Junction 无法安全卸载,则阻止删除本地仓库。
|
||||||
|
- Junction 清理完成后,再删除本地仓库目录。
|
||||||
|
|
||||||
|
## 后端模块
|
||||||
|
|
||||||
|
### config
|
||||||
|
|
||||||
|
职责:
|
||||||
|
|
||||||
|
- 读取和保存 `config.json`。
|
||||||
|
- 管理自动更新设置。
|
||||||
|
- 管理 Credential Manager 中的密码或 Token 引用。
|
||||||
|
|
||||||
|
### gitea
|
||||||
|
|
||||||
|
职责:
|
||||||
|
|
||||||
|
- 测试连接。
|
||||||
|
- 读取组织仓库。
|
||||||
|
- 检查仓库根目录 `SKILL.md`。
|
||||||
|
- 获取仓库默认分支和远程最新 commit。
|
||||||
|
|
||||||
|
### gitops
|
||||||
|
|
||||||
|
职责:
|
||||||
|
|
||||||
|
- 检查系统 `git` 是否可用。
|
||||||
|
- 执行 clone。
|
||||||
|
- 执行 fetch 和 pull。
|
||||||
|
- 获取当前 commit。
|
||||||
|
- 获取远程 commit。
|
||||||
|
- 检测工作区是否存在未提交改动。
|
||||||
|
|
||||||
|
### skillstore
|
||||||
|
|
||||||
|
职责:
|
||||||
|
|
||||||
|
- 管理本地仓库目录。
|
||||||
|
- 读取和保存 `state.json`。
|
||||||
|
- 记录本地 skill 元数据。
|
||||||
|
- 根据本地路径扫描已下载 skill。
|
||||||
|
|
||||||
|
### targets
|
||||||
|
|
||||||
|
职责:
|
||||||
|
|
||||||
|
- 管理 Codex 和 Claude 两个目标应用。
|
||||||
|
- 检测目标 skills 目录是否存在。
|
||||||
|
- 创建 Junction。
|
||||||
|
- 识别 Junction 目标。
|
||||||
|
- 卸载 Junction。
|
||||||
|
- 识别安装冲突。
|
||||||
|
|
||||||
|
### updater
|
||||||
|
|
||||||
|
职责:
|
||||||
|
|
||||||
|
- 启动后执行更新检查。
|
||||||
|
- 按配置间隔执行定时检查。
|
||||||
|
- 对无本地改动的已下载 skill 自动 pull。
|
||||||
|
- 记录更新失败原因。
|
||||||
|
|
||||||
|
## 状态文件设计
|
||||||
|
|
||||||
|
`config.json` 示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"gitea": {
|
||||||
|
"baseURL": "https://gitea.example.com",
|
||||||
|
"org": "ai-skills",
|
||||||
|
"authType": "password",
|
||||||
|
"username": "user",
|
||||||
|
"credentialKey": "sgg-ai-skill-manager:gitea"
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"autoUpdate": true,
|
||||||
|
"checkOnStartup": true,
|
||||||
|
"intervalMinutes": 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`state.json` 示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"skills": [
|
||||||
|
{
|
||||||
|
"org": "ai-skills",
|
||||||
|
"repo": "lark-base",
|
||||||
|
"localPath": "C:\\Users\\wdh\\AppData\\Roaming\\sgg-ai-skill-manager\\repos\\ai-skills\\lark-base",
|
||||||
|
"remoteURL": "https://gitea.example.com/ai-skills/lark-base.git",
|
||||||
|
"defaultBranch": "main",
|
||||||
|
"currentCommit": "abc123",
|
||||||
|
"lastCheckedAt": "2026-05-13T14:00:00+08:00",
|
||||||
|
"lastError": "",
|
||||||
|
"installedTargets": {
|
||||||
|
"codex": {
|
||||||
|
"path": "C:\\Users\\wdh\\.codex\\skills\\lark-base",
|
||||||
|
"linkType": "junction",
|
||||||
|
"targetPath": "C:\\Users\\wdh\\AppData\\Roaming\\sgg-ai-skill-manager\\repos\\ai-skills\\lark-base"
|
||||||
|
},
|
||||||
|
"claude": {
|
||||||
|
"path": "C:\\Users\\wdh\\.claude\\skills\\lark-base",
|
||||||
|
"linkType": "junction",
|
||||||
|
"targetPath": "C:\\Users\\wdh\\AppData\\Roaming\\sgg-ai-skill-manager\\repos\\ai-skills\\lark-base"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 自动更新策略
|
||||||
|
|
||||||
|
默认开启自动更新。
|
||||||
|
|
||||||
|
启动时:
|
||||||
|
|
||||||
|
1. 读取 `state.json`。
|
||||||
|
2. 对已下载 skill 执行更新检查。
|
||||||
|
3. 如果远程 commit 比本地新,且本地没有未提交改动,执行 `git pull`。
|
||||||
|
4. 如果 skill 已安装到 Codex 或 Claude,因为目标应用读取的是 Junction,pull 完成本身即完成同步。
|
||||||
|
5. 如果更新失败,记录错误并在本地管理页显示。
|
||||||
|
|
||||||
|
定时检查:
|
||||||
|
|
||||||
|
- 按配置的分钟间隔执行。
|
||||||
|
- 同一时刻只允许一个更新任务运行。
|
||||||
|
- 用户手动更新时,如果后台正在更新同一个 skill,需要返回“正在更新”状态。
|
||||||
|
|
||||||
|
本地改动处理:
|
||||||
|
|
||||||
|
- 如果发现本地仓库有未提交改动,不执行自动更新。
|
||||||
|
- 状态显示为“本地有改动”。
|
||||||
|
- 首版允许用户打开目录或 VS Code 手动处理。
|
||||||
|
- 首版不自动 stash、reset 或覆盖本地改动。
|
||||||
|
|
||||||
|
## 错误处理
|
||||||
|
|
||||||
|
错误状态应落到具体对象上,避免一个仓库失败影响其他仓库。
|
||||||
|
|
||||||
|
常见错误:
|
||||||
|
|
||||||
|
- Gitea baseURL 不可访问。
|
||||||
|
- 凭据无效。
|
||||||
|
- 当前账号无组织访问权限。
|
||||||
|
- 仓库没有 `SKILL.md`。
|
||||||
|
- 系统未安装 `git` 或 `git` 不在 PATH。
|
||||||
|
- clone 或 pull 认证失败。
|
||||||
|
- 本地仓库存在未提交改动。
|
||||||
|
- 目标 skills 目录不存在。
|
||||||
|
- 目标路径存在同名普通目录。
|
||||||
|
- 目标路径存在未知 Junction。
|
||||||
|
- Junction 删除前校验失败。
|
||||||
|
|
||||||
|
用户可见错误需要包含:
|
||||||
|
|
||||||
|
- 失败对象,例如仓库名或目标应用名。
|
||||||
|
- 简短原因。
|
||||||
|
- 可执行建议,例如“检查配置”“打开本地目录处理改动”“手动处理同名目录”。
|
||||||
|
|
||||||
|
## 安全规则
|
||||||
|
|
||||||
|
- 不自动删除用户已有普通目录。
|
||||||
|
- 不自动删除未知 Junction。
|
||||||
|
- 不自动覆盖本地仓库未提交改动。
|
||||||
|
- 不明文保存 Gitea 密码或 Token。
|
||||||
|
- 删除本地 skill 前必须先安全清理本软件创建的 Junction。
|
||||||
|
- 所有路径操作使用绝对路径。
|
||||||
|
- 删除操作限定在应用管理目录或记录中的目标 Junction 路径内。
|
||||||
|
|
||||||
|
## 验收标准
|
||||||
|
|
||||||
|
配置:
|
||||||
|
|
||||||
|
- 能保存 Gitea baseURL、认证方式、账号密码或 Token、组织名。
|
||||||
|
- 能测试连接并识别组织访问权限。
|
||||||
|
- 敏感信息不出现在 `config.json` 明文中。
|
||||||
|
|
||||||
|
远程市场:
|
||||||
|
|
||||||
|
- 能读取组织仓库列表。
|
||||||
|
- 只展示根目录存在 `SKILL.md` 的仓库。
|
||||||
|
- 能按名称和描述搜索。
|
||||||
|
- 能下载未下载 skill。
|
||||||
|
- 能更新已下载 skill。
|
||||||
|
|
||||||
|
本地管理:
|
||||||
|
|
||||||
|
- 能展示已下载 skill 的路径、commit 和安装状态。
|
||||||
|
- 能安装到 Codex。
|
||||||
|
- 能安装到 Claude。
|
||||||
|
- 安装结果是 Junction,不是目录复制。
|
||||||
|
- 能卸载 Codex 和 Claude 的 Junction。
|
||||||
|
- 卸载不会删除本地仓库。
|
||||||
|
- 能删除本地 skill,并先清理本软件创建的 Junction。
|
||||||
|
- 遇到同名普通目录或未知 Junction 时不会自动覆盖。
|
||||||
|
- 能用 VS Code 打开 skill 目录。
|
||||||
|
- 能用资源管理器打开 skill 目录。
|
||||||
|
|
||||||
|
自动更新:
|
||||||
|
|
||||||
|
- 启动时能检查已下载 skill 是否有更新。
|
||||||
|
- 无本地改动时能自动 pull。
|
||||||
|
- 已安装 skill 更新后,Codex 和 Claude 通过 Junction 能读取最新内容。
|
||||||
|
- 有本地未提交改动时不会自动覆盖。
|
||||||
|
|
||||||
|
## 后续扩展方向
|
||||||
|
|
||||||
|
首版采用轻量 MVP,但保留模块边界,后续可以扩展:
|
||||||
|
|
||||||
|
- 更多目标应用。
|
||||||
|
- 多个 Gitea 组织。
|
||||||
|
- 多个代码托管源。
|
||||||
|
- 批量操作。
|
||||||
|
- 更新日志和版本回滚。
|
||||||
|
- skill 元数据解析和分类。
|
||||||
Reference in New Issue
Block a user