ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OpenChamber Skills Catalog 模块解析:git 仓库技能发现、扫描、安装与缓存架构

OpenChamber Skills Catalog 模块解析:git 仓库技能发现、扫描、安装与缓存架构 AI Agent人工智能代码智能体交互助手【免费下载链接】openchamberAgentic Development Environment based on OpenCode AI agent项目地址https://gitcode.com/gh_mirrors/op/openchamber点击查看免费下载本篇文章以 OpenChamber 仓库中packages/web/server/lib/skills-catalog/DOCUMENTATION.md为核心结合模块源码与路由实现系统性讲解 Skills Catalog 模块如何实现基于 git 仓库的技能Skill发现、扫描与安装。读完本文你将掌握源字符串解析规则、扫描与安装的完整调用链、三层缓存架构、冲突解决策略以及安全边界并可直接据此理解或扩展该模块。模块定位OpenChamber 中的技能分发中枢在 OpenChamber基于 OpenCode AI Agent 的 Agentic Development Environment中技能Skill是赋予 Agent 特定能力的可复用单元。Skills Catalog 模块位于packages/web/server/lib/skills-catalog/承担三类核心职责发现Discovery维护一份预置技能源列表并在 Web 界面上展示每个源仓库的 Star 数、最近推送时间等元信息扫描Scanning克隆远程 git 仓库解析其中的SKILL.md文件将每个技能目录整理为结构化的候选清单安装Installation按用户或项目作用域将选中的技能目录复制到 OpenCode/Agent 约定的技能目录中并处理目标目录已存在时的冲突。从 技能路由注册文件 可以看到模块的 8 个导出函数getCuratedSkillsSources、getCacheKey、scanWithCache、parseSkillRepoSource、scanSkillsRepository、installSkillsFromRepository、fetchGitHubRepoMetas等被统一注入到路由依赖中通过/api/config/skills/catalog、/api/config/skills/scan、/api/config/skills/install等 HTTP 接口对外提供服务。模块文件结构文件职责cache.js扫描结果的内存缓存 TTL 磁盘持久化 并发控制curated-sources.js预置技能源常量与访问函数github-meta.jsGitHub 仓库元信息Star、最近推送的尽力而为抓取git.jsgit 命令封装、认证错误识别、git 可用性检查install.js从 git 仓库安装技能scan.js从 git 仓库扫描技能source.js技能源字符串解析disk-cache.js磁盘缓存读写原子写入技能源字符串解析三种格式的统一入口parseSkillRepoSource(source, options)是模块的门面负责把用户输入的各种源字符串统一为结构化对象。从 source.js 源码看它支持三种格式1. HTTPS URL 格式https://host/owner/repo(.git)解析后同时生成 SSH 与 HTTPS 两种克隆地址// 输入: https://github.com/anthropics/skills.git // 输出: { ok: true, host: github.com, owner: anthropics, repo: skills, cloneUrlSsh: gitgithub.com:anthropics/skills.git, cloneUrlHttps: https://github.com/anthropics/skills.git, effectiveSubpath: null, normalizedRepo: anthropics/skills }2. SSH URL 格式githost:owner/repo(.git)其子路径只能通过options.subpath传入源码注释明确说明 For SSH URLs, subpath is only accepted via options.subpath。3. 简写格式Shorthandowner/repo[/subpath...]这是预置源与配置中最常用的形式。子路径既可以直接拼在字符串末尾也可以通过options.subpath显式传入最终以显式参数优先// 输入: anthropics/skills/skills // effectiveSubpath skills来自字符串 // 输入: anthropics/skills { subpath: skills } // effectiveSubpath skills来自 options解析失败时统一返回{ ok: false, error: { kind: invalidSource, message } }例如空字符串、缺少 owner/repo、无法识别的格式等。预置技能源curated-sources.js 中定义了 4 个预置源CURATED_SKILLS_SOURCESgetCuratedSkillsSources()返回其副本idlabelsourcedefaultSubpathanthropicAnthropicanthropics/skillsskillsopenaiOpenAIopenai/skillsskills/.curatedcursorCursorcursor/pluginspstack/skillsmattpocockMatt Pocockmattpocock/skills无扫描整个仓库除预置源外技能目录路由 还会从磁盘设置中读取settings.skillCatalogs将其中的自定义条目含id、label、source、subpath、gitIdentityId合并进目录列表最终在/api/config/skills/catalog接口中一并返回给前端。扫描流水线从克隆到 SKILL.md 结构化scanSkillsRepository({ source, subpath, defaultSubpath, identity })是扫描入口完整流程如下对应 scan.js前置检查assertGitAvailable()确认 git 在 PATH 中可用不可用则直接返回gitUnavailable错误。源解析调用parseSkillRepoSourceeffectiveSubpath的优先级为parsed.effectiveSubpath → defaultSubpath。克隆策略根据identity?.sshKey是否存在决定使用 SSH 还是 HTTPS 克隆地址。克隆采用--depth1 --filterblob:none --no-checkout的部分克隆partial clone优先方案失败后回退到--depth1install.js 中克隆超时为 90 秒scan.js 中为 60 秒。稀疏检出执行sparse-checkout init --no-conesparse-checkout set patternscheckout --force HEAD只检出SKILL.md相关文件。有子路径时 patterns 为${subpath}/SKILL.md与${subpath}/**/SKILL.md无子路径时覆盖仓库根与任意层级。定位 SKILL.md优先用git ls-files列出文件失败则回退到git ls-tree -r --name-only HEAD。若子路径不存在视为空扫描直接返回{ ok: true, items: [] }。解析 frontmatter对每个技能目录读取SKILL.md用正则提取---分隔的 YAML frontmatter通过yaml.parse解析出name与description字段缺少分隔符或 YAML 解析失败会生成对应 warning。技能名校验技能名取目录 basename必须匹配/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/1-64 个字符、小写字母数字加连字符不合法则installable: false并附 warning。并行与排序最多 10 个 worker 并行解析最终按skillName.localeCompare排序保证 UI 展示顺序稳定。清理finally块中调用safeRm删除临时克隆目录。注意一个细节仓库根目录的SKILL.md会被过滤掉p ! SKILL.md源码注释说明这是因为根级 SKILL.md 无法映射到 OpenCode 的『技能名 目录名』约定。安装流水线作用域、冲突解决与稀疏检出installSkillsFromRepository(...)的参数比扫描更丰富scopeuser/project、targetSourceopencode/agents、workingDirectory、userSkillDir、selections、conflictPolicy、conflictDecisions。核心流程对应 install.js目标目录规则getTargetSkillDir按scope与targetSource组合决定安装位置scopetargetSource目标目录useropencodeuserSkillDir/skillNameuseragents~/.agents/skills/skillNameprojectopencodeworkingDirectory/.opencode/skills/skillNameprojectagentsworkingDirectory/.agents/skills/skillNameuserSkillDir会先经过normalizeUserSkillDir归一化若传入的是旧的skill单数目录且旧目录存在而skills复数不存在则沿用旧目录否则指向~/.config/opencode/skills下的复数目录。校验与冲突预检scope只能是user/projecttargetSource只能是opencode/agentsproject作用域必须携带workingDirectory否则返回invalidSourceselections为空时直接返回错误安装前先对每个待装技能计算目标目录若已存在且既无 per-skill 决策、也无自动策略skipAll/overwriteAll则收集为冲突并返回{ kind: conflicts, conflicts }——这一步保证在克隆/下载之前就提示用户避免浪费网络请求。克隆与选择性检出克隆策略与扫描一致随后执行sparse-checkout init --conesparse-checkout set requestedDirs只检出用户实际选择的技能目录是控制克隆体积的关键手段。逐技能安装与冲突决策对每个技能目录名不合法 → 记入skippedreason:Invalid skill name (directory basename)检出目录中缺少SKILL.md→ 记入skipped冲突决策优先级conflictDecisions[skillName]per-skillconflictPolicyskipAll跳过 /overwriteAll覆盖 无冲突时默认覆盖覆盖前调用safeRm(targetDir)清空旧目录通过copyDirectoryNoSymlinks复制文件复制失败则回滚删除目标目录并记入skipped成功后记入installed含{ skillName, scope, source }。三层缓存内存、去重、磁盘扫描与元信息抓取都有成本克隆仓库、请求 GitHub API因此模块实现了三层缓存机制集中在 cache.js 与 github-meta.js缓存键与 TTL扫描缓存键由getCacheKey({ normalizedRepo, subpath, identityId })生成形如repo::subpath::identity三个维度隔离不同源、不同子路径、不同 git 身份默认 TTL 为3 小时DEFAULT_TTL_MS 3 * 60 * 60 * 1000扫描结果与 GitHub 元信息一致GitHub 元信息抓取失败时采用更短的 5 分钟失败缓存FAILURE_CACHE_TTL_MS避免频繁重试已失败/限流的 API。scanWithCache并发控制核心scanWithCache(key, loader, { refresh })实现了三级防护读缓存refresh: false默认时命中未过期缓存直接返回in-flight 去重同一 key 的并发请求共享同一次 loader 运行inFlightMap避免重复克隆全局并发上限信号量acquireScanSlot/releaseScanSlot保证同时最多2 个扫描任务MAX_CONCURRENT_SCANS 2超出者排队等待。只有ok: true的结果才会写入缓存setCachedScan内部再次校验 TTL 数值合法性。磁盘持久化内存缓存通过 disk-cache.js 持久化到 OpenChamber 数据目录OPENCHAMBER_DATA_DIR环境变量或~/.config/openchamber下的skills-catalog-cache.json与skills-github-meta.json写入采用防抖 原子重命名setTimeout1000ms 后统一落盘先写*.tmp临时文件再renameSync原子替换避免并发写坏文件重启后loadDiskEntries会过滤掉已过期的条目重新载入内存因此应用重启与页面刷新都能复用历史扫描结果而不是重新访问 GitHub写入失败被静默忽略内存缓存保持权威下次成功写入会重试持久化。元信息抓取的尽力而为原则fetchGitHubRepoMetas(normalizedRepos)通过 GitHub REST APIhttps://api.github.com/repos/owner/repo抓取stargazers_count与pushed_at映射为{ stars, repoUpdatedAt }。源码注释强调其设计意图单请求超时1500ms严格低于目录接口的客户端请求期限确保可选的元信息增强永远不会拖垮目录加载失败 resolve 为null同一仓库的并发请求去重失败结果短时缓存5 分钟。在 技能目录路由 中目录接口只对host github.com的源发起元信息抓取并把stars、repoUpdatedAt附加到每个源对象上供前端展示。HTTP 接口与响应契约路由层 skill-routes.js 把模块能力暴露为以下接口接口方法说明/api/config/skills/catalogGET返回技能源目录含自定义源与 GitHub 元信息/api/config/skills/catalog/source?sourceIdGET按源 ID 扫描并返回技能清单refreshtrue强制绕过缓存/api/config/skills/scanPOST对任意源字符串执行扫描/api/config/skills/installPOST安装所选技能/api/config/skills/:nameGET读取单个技能详情各层统一采用{ ok, ... }结果对象而非抛异常错误分类保持一致authRequired认证失败SSH/HTTPS接口返回 401并附带identities列表供前端引导用户配置 git 身份networkError克隆等网络操作失败conflicts目标目录已存在且无自动决策接口返回409invalidSource源字符串或参数不合法返回 400unknown其他未知错误返回 500。扫描响应Scan Response{ ok: true, normalizedRepo: anthropics/skills, // owner/repo effectiveSubpath: skills, // 实际生效的子路径 items: [{ repoSource: anthropics/skills, // 原始源字符串 repoSubpath: skills, // 子路径 skillDir: skills/foo, // 仓库内目录POSIX skillName: foo, // 目录 basename frontmatterName: Foo Skill, // SKILL.md frontmatter 的 name description: ..., // frontmatter 的 description installable: true, // 是否可通过命名校验 warnings: undefined // 解析警告如有 }] }安装响应Install Response{ ok: true, installed: [{ skillName: foo, scope: user, source: opencode }], skipped: [{ skillName: bar, reason: Invalid skill name (directory basename) }] }安装成功后路由层会进一步返回requiresReload与message字段安装成功时提示Skills installed successfully.全部跳过时提示 No skills were installed驱动前端刷新技能状态。安全与健壮性设计模块在安全方面有明确设计文档与源码相互印证路径穿越防护copyDirectoryNoSymlinks先realpath解析源目录复制过程中对每个子目录再次realpath并校验其位于源目录之内startsWith(srcReal)越界即抛错拒绝符号链接复制时lstat检查到SymbolicLink直接抛Symlinks are not supported in skills防止技能通过软链逃逸出技能目录非交互式 gitrunGit始终注入GIT_TERMINAL_PROMPT0防止克隆私有仓库时因交互式密码提示而挂起注入 SSH 身份时使用ssh -i key -o BatchModeyes -o StrictHostKeyCheckingaccept-new避免主机密钥交互临时目录兜底清理扫描与安装都在finally中safeRm临时目录安装失败时还会回滚已创建的目标目录认证错误识别looksLikeAuthError通过正则permission denied、publickey、could not read from remote repository、authentication failed等识别认证失败从而给用户更友好的提示磁盘缓存文件权限写盘时使用mode: 0o600避免缓存文件被其他用户读取。扩展与贡献指引若要在该模块中新增一类技能源例如公司内部 git 服务文档给出了清晰的五步流程在packages/web/server/lib/skills-catalog/下新建子目录如newsource/实现scan.js导出返回{ ok, items, error? }符合 SkillsCatalogItem 契约的函数实现install.js导出接受 selections 并返回{ ok, installed, skipped, error? }的函数如需出现在默认目录中将新源加入curated-sources.js的CURATED_SKILLS_SOURCES在packages/web/server/index.js中 import 并接线新源。提交前建议运行验证命令仓库根目录执行bun run type-check # 类型检查 bun run lint # 静态检查 bun run build # 构建同时注意文档提醒的边界情况不存在的仓库、无认证的私有仓库、缺失 SKILL.md、非法技能名、冲突与网络失败等这些在 cache.test.js、github-meta.test.js、skill-routes.test.js 等测试文件中均有覆盖是理解模块行为边界的最佳参考。小结OpenChamber 的 Skills Catalog 模块是一个小而精的工程范例通过统一的源解析、高效的稀疏检出克隆策略、三层缓存与并发控制把从 git 仓库安装技能这一高频操作做得既快又稳同时通过严格的结果对象契约、分类错误与安全校验保证 Web 服务层的健壮性。理解它的扫描/安装流水线与缓存设计不仅有助于使用和扩展 OpenChamber 的技能体系也能为同类远程内容 → 本地可执行资产的分发类模块提供可复用的设计参考。赞分享AI Agent人工智能代码智能体交互助手【免费下载链接】openchamberAgentic Development Environment based on OpenCode AI agent项目地址https://gitcode.com/gh_mirrors/op/openchamber点击查看免费下载相关推荐OpenChamber 1.3.9 版本解析Skills 技能管理与技能目录Skills Catalog能力上线OpenChamber 1.3.9 版本解析Skills 技能管理与技能目录Skills Catalog能力上线 本文基于 changelog/1.3.9AI Agent人工智能代码智能体交互助手Agent Skills 的发现、验证与安装实战Meshery 仓库 find-skills 技能全解析Agent Skills 的发现、验证与安装实战Meshery 仓库 find skills 技能全解析 导读 本文以 Meshery 仓库内建技能 .age云原生微服务运维DevOps如何永久保存你的QQ空间青春记忆GetQzonehistory工具终极指南如何永久保存你的QQ空间青春记忆GetQzonehistory工具终极指南 你是否曾经想要找回多年前在QQ空间发布的心情说说却发现部分内容已经消失不见Ge网页爬虫数据分析上一篇提升Python开发效率pytest-watch让测试结果即时反馈的终极技巧下一篇终极OpenSpeedy调试指南5个关键设置提升你的调试效率创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表