From 3facad82a46b7b7eaf0c3fc59113b23f6813f0bc Mon Sep 17 00:00:00 2001 From: wdh-home <243823965@qq.com> Date: Wed, 13 May 2026 15:55:45 +0800 Subject: [PATCH] docs: add ai skill manager design spec --- .../2026-05-13-ai-skill-manager-design.md | 461 ++++++++++++++++++ 1 file changed, 461 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-13-ai-skill-manager-design.md diff --git a/docs/superpowers/specs/2026-05-13-ai-skill-manager-design.md b/docs/superpowers/specs/2026-05-13-ai-skill-manager-design.md new file mode 100644 index 0000000..d458c35 --- /dev/null +++ b/docs/superpowers/specs/2026-05-13-ai-skill-manager-design.md @@ -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 `。 + +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 元数据解析和分类。