@easbot/skills 0.2.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 houjallen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.en.md ADDED
@@ -0,0 +1,202 @@
1
+ [中文](./README.md) | English
2
+
3
+ # @easbot/skills
4
+
5
+ Skill package management subsystem for the EAS Agent ecosystem. Discovers, installs, removes, searches, updates, syncs and one-shot uses skills (SKILL.md) from GitHub, Well-Known hosts, or local paths.
6
+
7
+ Usable both as a standalone CLI (`easbot skills ...`) and as a library that the `@easbot/agent` host CLI delegates to via Commander.js, so `easbot agent skills ...` and `easbot skills ...` are equivalent.
8
+
9
+ ## Features
10
+
11
+ - **Type Safety**: full TypeScript types + Zod frontmatter validation
12
+ - **Multi-Source**: GitHub shorthand / HTTPS / SSH / Well-Known / local path
13
+ - **Multi-Agent**: Claude Code, Cursor, AiderDesk, Amp, Antigravity, Zed, Codex, Hermes, Vibe, AutoHand, Eve, ...
14
+ - **Dependency Injection**: `setGlobalAdapter / setInstanceAdapter / setAgentAdapter` lets the host (agent / gateway) inject `IGlobal.Path`, `IInstance.directory`, and SubAgentRunner / LocalAgentRunner — all data lives under one tree
15
+ - **Incremental Sync**: lockfile-based add / remove / update / sync with local SHA-256 hashing
16
+ - **i18n**: built-in zh-CN / en-US translations; user-facing strings go through `t()`, with fallback to the English literal when a key is missing
17
+ - **Telemetry + Audit**: built-in `skills.sh` partner-audit reporting and OpenClaw risk gating
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ pnpm add @easbot/skills
23
+ ```
24
+
25
+ Or as a monorepo workspace dependency:
26
+
27
+ ```json
28
+ {
29
+ "dependencies": {
30
+ "@easbot/skills": "workspace:*"
31
+ }
32
+ }
33
+ ```
34
+
35
+ ## CLI Usage
36
+
37
+ ### Standalone CLI
38
+
39
+ ```bash
40
+ # Add a skill
41
+ easbot skills add houjallen/agent-skills
42
+ easbot skills add https://github.com/houjallen/agent-skills -g
43
+
44
+ # Search
45
+ easbot skills find typescript --owner houjallen
46
+
47
+ # List installed
48
+ easbot skills list --json
49
+
50
+ # Remove
51
+ easbot skills remove my-skill -y
52
+
53
+ # Update
54
+ easbot skills update -g
55
+
56
+ # One-shot use (no lockfile mutation)
57
+ easbot skills use houjallen/agent-skills@houjallen
58
+
59
+ # Sync from node_modules / restore from lockfile
60
+ easbot skills experimental_sync
61
+ easbot skills experimental_install
62
+
63
+ # Initialize a new skill
64
+ easbot skills init my-skill
65
+ ```
66
+
67
+ ### Delegated from a host CLI
68
+
69
+ `@easbot/agent` reuses every sub-command through `handleSkillsCli(args, deps)`:
70
+
71
+ ```typescript
72
+ import { handleSkillsCli, setGlobalAdapter, setInstanceAdapter } from '@easbot/skills';
73
+
74
+ setGlobalAdapter({ Path: Global.Path });
75
+ setInstanceAdapter({ directory: ctx.config.directory, worktree: Instance.worktree });
76
+
77
+ await handleSkillsCli(['add', 'houjallen/agent-skills', '-y'], {
78
+ version: ctx.programVersion,
79
+ });
80
+ ```
81
+
82
+ ## API
83
+
84
+ | Module | Exports | Notes |
85
+ |---|---|---|
86
+ | `add` | `runAdd / parseAddOptions / initTelemetry` | Skill add pipeline |
87
+ | `remove` | `removeCommand / parseRemoveOptions` | Skill removal |
88
+ | `list` | `runList / parseListOptions` | List installed skills |
89
+ | `find` | `runFind / parseFindOptions / searchSkillsAPI` | skills.sh search |
90
+ | `update` | `runUpdate / parseUpdateOptions` | Incremental update |
91
+ | `install` | `runInstallFromLock` | Restore from skills-lock.json |
92
+ | `sync` | `runSync / parseSyncOptions` | Sync from node_modules |
93
+ | `use` | `runUse / parseUseOptions / buildUsePrompt` | One-shot use |
94
+ | `cli-handler` | `handleSkillsCli / renderBanner / renderHelp / SkillsCliDeps / SkillsCliResult` | CLI bridge |
95
+ | `interfaces` | `setGlobalAdapter / setInstanceAdapter / setAgentAdapter / getGlobal / getInstance / ...` | Dependency injection |
96
+ | `agents` | `agents / detectInstalledAgents / getUniversalAgents / ...` | Agent metadata |
97
+ | `installer` | `installSkillForAgent / listInstalledSkills / getCanonicalSkillsDir` | Physical install |
98
+ | `skill-lock` | `readSkillLock / writeSkillLock / addSkillToLock / removeSkillFromLock` | Global lockfile |
99
+ | `local-lock` | `readLocalLock / writeLocalLock / computeSkillFolderHash` | Project lockfile |
100
+ | `telemetry` | `track / flushTelemetry / setVersion / fetchAuditData` | Usage stats + security audit |
101
+ | `i18n` | `t / initI18n / registerI18nResources / changeI18nLanguage` | Internationalization |
102
+ | `frontmatter` | `parseFrontmatter` | YAML frontmatter parser |
103
+ | `providers` | `wellKnownProvider / registry / findProvider` | Well-Known & custom host providers |
104
+
105
+ ## Global Path Injection
106
+
107
+ To avoid fighting with the host (agent / gateway) over XDG / home, `@easbot/skills` resolves paths through dependency injection by default:
108
+
109
+ ```typescript
110
+ import {
111
+ setGlobalAdapter, // inject IGlobal.Path
112
+ setInstanceAdapter, // inject IInstance.directory / worktree
113
+ setAgentAdapter, // inject SubAgentRunner / LocalAgentRunner / triggerEvent
114
+ getHomeDir,
115
+ getXdgConfig,
116
+ getXdgData,
117
+ getProjectDirectory,
118
+ } from '@easbot/skills';
119
+
120
+ setGlobalAdapter({
121
+ Path: {
122
+ home: '/Users/me',
123
+ data: '/Users/me/.local/share/easbot',
124
+ config: '/Users/me/.config/easbot',
125
+ state: '/Users/me/.local/state/easbot',
126
+ cache: '/Users/me/.cache/easbot',
127
+ log: '/Users/me/.local/state/easbot/log',
128
+ bin: '/Users/me/.local/bin',
129
+ },
130
+ });
131
+
132
+ setInstanceAdapter({
133
+ directory: '/repo',
134
+ worktree: '/repo',
135
+ });
136
+ ```
137
+
138
+ When no adapter is set, `@easbot/skills` falls back to `xdg-basedir` + `homedir()`, keeping full backward compatibility with the v1 standalone CLI.
139
+
140
+ ## Data Layout
141
+
142
+ | Path | Purpose |
143
+ |---|---|
144
+ | `${Global.Path.data}/skills/` | Skill directory loaded by the agent at runtime |
145
+ | `${Global.Path.data}/state/skills/.skill-lock.json` | Global install lockfile |
146
+ | `<cwd>/.agents/skills/` / `<cwd>/skills/` | Project-level skill directories |
147
+ | `<cwd>/skills-lock.json` | Project-level lockfile |
148
+ | `<home>/.config/easbot/skills/` | XDG config fallback |
149
+
150
+ > When delegated from `@easbot/agent`, everything lands under `${Global.Path.data}` — sibling to Gateway / MCP / Session / Contact modules.
151
+
152
+ ## Development
153
+
154
+ ```bash
155
+ # Install dependencies
156
+ pnpm install
157
+
158
+ # Build (produces dist/ + .d.ts)
159
+ pnpm build
160
+
161
+ # Watch build
162
+ pnpm dev
163
+
164
+ # Tests (vitest; single file: npx vitest run src/__tests__/xxx.test.ts)
165
+ pnpm test
166
+ pnpm test:run
167
+
168
+ # Code quality
169
+ pnpm biome-lint # biome check .
170
+ pnpm biome-fix # biome check --write .
171
+ pnpm biome-format # biome format .
172
+
173
+ # Type check
174
+ pnpm type-check
175
+
176
+ # Clean
177
+ pnpm clean
178
+ ```
179
+
180
+ ## Publishing
181
+
182
+ ```bash
183
+ # Linux / macOS
184
+ pnpm publish:npm # = bash scripts/publish.sh
185
+
186
+ # Windows PowerShell
187
+ pnpm publish:npm:win # = powershell -ExecutionPolicy Bypass -File scripts/publish.ps1
188
+
189
+ # Equivalent manual flow
190
+ pnpm build
191
+ pnpm publish --access public --git-checks false --registry https://registry.npmjs.org
192
+ ```
193
+
194
+ ## Runtime Notes
195
+
196
+ - Uses Node built-ins (`fs/promises`, `node:os`, `node:path`, `node:child_process`); **not** browser-compatible.
197
+ - Pulls in `simple-git`, `@vercel/detect-agent`, `@clack/prompts`, `picocolors`, `xdg-basedir`, `zod`, `yaml` for GitHub access, agent detection, interactive prompts, terminal styling, XDG resolution, and frontmatter validation.
198
+ - `engines.node >= 22.22.3` — Node 22 LTS recommended.
199
+
200
+ ## License
201
+
202
+ MIT
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ [English](./README.en.md) | 中文
2
+
3
+ # @easbot/skills
4
+
5
+ EASBot 技能包管理子系统:负责从 GitHub / Well-Known / 本地路径发现、安装、移除、搜索、更新、同步与一次性使用技能(SKILL.md)。
6
+
7
+ 既可作为独立 CLI(`easbot skills ...`),也可被 `@easbot/agent` 主 CLI 通过 Commander.js 委派调用,实现 `easbot agent skills ...` 与 `easbot skills ...` 等价。
8
+
9
+ ## 特性
10
+
11
+ - **类型安全**:完整 TypeScript 类型 + Zod frontmatter 校验
12
+ - **多源支持**:GitHub 仓库 shorthand / HTTPS / SSH / Well-Known / 本地路径
13
+ - **多 Agent 兼容**:Claude Code、Cursor、AiderDesk、Amp、Antigravity、Zed、Codex、Hermes、Vibe、AutoHand、Eve 等
14
+ - **依赖注入**:`setGlobalAdapter / setInstanceAdapter / setAgentAdapter` 让宿主(agent / gateway)注入 `IGlobal.Path`、`IInstance.directory`、SubAgentRunner / LocalAgentRunner,统一数据树
15
+ - **增量同步**:基于本地 SHA-256 锁文件的 `add / remove / update / sync` 增量操作
16
+ - **i18n**:内置 zh-CN / en-US 两套翻译,所有面向用户文案走 `t()`,未命中 key 时回退原文
17
+ - **遥测与安全审计**:内置 `skills.sh` partner audit 上报与 OpenClaw 风险提示
18
+
19
+ ## 安装
20
+
21
+ ```bash
22
+ pnpm add @easbot/skills
23
+ ```
24
+
25
+ 或作为 monorepo 工作区依赖:
26
+
27
+ ```json
28
+ {
29
+ "dependencies": {
30
+ "@easbot/skills": "workspace:*"
31
+ }
32
+ }
33
+ ```
34
+
35
+ ## CLI 用法
36
+
37
+ ### 独立 CLI
38
+
39
+ ```bash
40
+ # 添加技能
41
+ easbot skills add houjallen/agent-skills
42
+ easbot skills add https://github.com/houjallen/agent-skills -g
43
+
44
+ # 搜索
45
+ easbot skills find typescript --owner houjallen
46
+
47
+ # 列出已安装
48
+ easbot skills list --json
49
+
50
+ # 移除
51
+ easbot skills remove my-skill -y
52
+
53
+ # 更新
54
+ easbot skills update -g
55
+
56
+ # 一次性使用(不修改锁定文件)
57
+ easbot skills use houjallen/agent-skills@houjallen
58
+
59
+ # 从 node_modules 同步 / 从锁定文件还原
60
+ easbot skills experimental_sync
61
+ easbot skills experimental_install
62
+
63
+ # 初始化新技能
64
+ easbot skills init my-skill
65
+ ```
66
+
67
+ ### 被宿主 CLI 委派
68
+
69
+ `@easbot/agent` 通过 `handleSkillsCli(args, deps)` 复用所有子命令:
70
+
71
+ ```typescript
72
+ import { handleSkillsCli, setGlobalAdapter, setInstanceAdapter } from '@easbot/skills';
73
+
74
+ setGlobalAdapter({ Path: Global.Path });
75
+ setInstanceAdapter({ directory: ctx.config.directory, worktree: Instance.worktree });
76
+
77
+ await handleSkillsCli(['add', 'houjallen/agent-skills', '-y'], {
78
+ version: ctx.programVersion,
79
+ });
80
+ ```
81
+
82
+ ## API
83
+
84
+ | 模块 | 导出 | 说明 |
85
+ |---|---|---|
86
+ | `add` | `runAdd / parseAddOptions / initTelemetry` | 技能添加主流程 |
87
+ | `remove` | `removeCommand / parseRemoveOptions` | 技能移除 |
88
+ | `list` | `runList / parseListOptions` | 列出已安装技能 |
89
+ | `find` | `runFind / parseFindOptions / searchSkillsAPI` | skills.sh 搜索 |
90
+ | `update` | `runUpdate / parseUpdateOptions` | 增量更新 |
91
+ | `install` | `runInstallFromLock` | 从 skills-lock.json 还原 |
92
+ | `sync` | `runSync / parseSyncOptions` | 从 node_modules 同步 |
93
+ | `use` | `runUse / parseUseOptions / buildUsePrompt` | 一次性使用 |
94
+ | `cli-handler` | `handleSkillsCli / renderBanner / renderHelp / SkillsCliDeps / SkillsCliResult` | CLI 桥接 |
95
+ | `interfaces` | `setGlobalAdapter / setInstanceAdapter / setAgentAdapter / getGlobal / getInstance / ...` | 依赖注入 |
96
+ | `agents` | `agents / detectInstalledAgents / getUniversalAgents / ...` | Agent 元数据 |
97
+ | `installer` | `installSkillForAgent / listInstalledSkills / getCanonicalSkillsDir` | 物理安装 |
98
+ | `skill-lock` | `readSkillLock / writeSkillLock / addSkillToLock / removeSkillFromLock` | 全局锁定文件 |
99
+ | `local-lock` | `readLocalLock / writeLocalLock / computeSkillFolderHash` | 项目级锁定文件 |
100
+ | `telemetry` | `track / flushTelemetry / setVersion / fetchAuditData` | 使用统计 + 安全审计 |
101
+ | `i18n` | `t / initI18n / registerI18nResources / changeI18nLanguage` | 国际化 |
102
+ | `frontmatter` | `parseFrontmatter` | YAML frontmatter 解析 |
103
+ | `providers` | `wellKnownProvider / registry / findProvider` | Well-Known 等主机提供方 |
104
+
105
+ ## 全局路径注入
106
+
107
+ 为避免与宿主(agent / gateway)抢用 XDG / home 目录,`@easbot/skills` 默认通过依赖注入获取路径:
108
+
109
+ ```typescript
110
+ import {
111
+ setGlobalAdapter, // 注入 IGlobal.Path
112
+ setInstanceAdapter, // 注入 IInstance.directory / worktree
113
+ setAgentAdapter, // 注入 SubAgentRunner / LocalAgentRunner / triggerEvent
114
+ getHomeDir,
115
+ getXdgConfig,
116
+ getXdgData,
117
+ getProjectDirectory,
118
+ } from '@easbot/skills';
119
+
120
+ setGlobalAdapter({
121
+ Path: {
122
+ home: '/Users/me',
123
+ data: '/Users/me/.local/share/easbot',
124
+ config: '/Users/me/.config/easbot',
125
+ state: '/Users/me/.local/state/easbot',
126
+ cache: '/Users/me/.cache/easbot',
127
+ log: '/Users/me/.local/state/easbot/log',
128
+ bin: '/Users/me/.local/bin',
129
+ },
130
+ });
131
+
132
+ setInstanceAdapter({
133
+ directory: '/repo',
134
+ worktree: '/repo',
135
+ });
136
+ ```
137
+
138
+ 未注入时,skills 包回退到 `xdg-basedir` + `homedir()`,保持与 v1 CLI 完全兼容。
139
+
140
+ ## 数据目录约定
141
+
142
+ | 路径 | 用途 |
143
+ |---|---|
144
+ | `${Global.Path.data}/skills/` | Agent 运行时加载的技能目录(运行时扫描) |
145
+ | `${Global.Path.data}/state/skills/.skill-lock.json` | 全局安装锁定文件 |
146
+ | `<cwd>/.agents/skills/` / `<cwd>/skills/` | 项目级技能目录 |
147
+ | `<cwd>/skills-lock.json` | 项目级锁定文件 |
148
+ | `<home>/.config/easbot/skills/` | XDG 配置兜底 |
149
+
150
+ > 当被 `@easbot/agent` 委派时,所有路径会落到 `${Global.Path.data}` 这棵统一数据树下,与 Gateway / MCP / Session / Contact 等模块并列。
151
+
152
+ ## 开发
153
+
154
+ ```bash
155
+ # 安装依赖
156
+ pnpm install
157
+
158
+ # 构建(产出 dist/,同时生成 .d.ts)
159
+ pnpm build
160
+
161
+ # 监听构建
162
+ pnpm dev
163
+
164
+ # 测试(vitest,单跑某个文件:npx vitest run src/__tests__/xxx.test.ts)
165
+ pnpm test
166
+ pnpm test:run
167
+
168
+ # 代码质量
169
+ pnpm biome-lint # biome check .
170
+ pnpm biome-fix # biome check --write .
171
+ pnpm biome-format # biome format .
172
+
173
+ # 类型检查
174
+ pnpm type-check
175
+
176
+ # 清理
177
+ pnpm clean
178
+ ```
179
+
180
+ ## 发布
181
+
182
+ ```bash
183
+ # Linux / macOS
184
+ pnpm publish:npm # = bash scripts/publish.sh
185
+
186
+ # Windows PowerShell
187
+ pnpm publish:npm:win # = powershell -ExecutionPolicy Bypass -File scripts/publish.ps1
188
+
189
+ # 手动等价
190
+ pnpm build
191
+ pnpm publish --access public --git-checks false --registry https://registry.npmjs.org
192
+ ```
193
+
194
+ ## 浏览器 / 跨运行时说明
195
+
196
+ - 内部使用 Node 内置模块(`fs/promises`、`node:os`、`node:path`、`node:child_process`),不能直接在浏览器运行。
197
+ - 通过 `simple-git`、`@vercel/detect-agent`、`@clack/prompts`、`picocolors`、`xdg-basedir`、`zod`、`yaml` 等实现 GitHub 拉取、Agent 环境探测、交互问答、终端着色、XDG 解析与 frontmatter 校验。
198
+ - `engines.node >= 22.22.3`,推荐 Node 22 LTS。
199
+
200
+ ## 许可证
201
+
202
+ MIT
@@ -0,0 +1 @@
1
+ 'use strict';var chunkEOOPF3RI_cjs=require('./chunk-EOOPF3RI.cjs');Object.defineProperty(exports,"BLOB_ALLOWED_REPOS",{enumerable:true,get:function(){return chunkEOOPF3RI_cjs.f}});Object.defineProperty(exports,"fetchRepoTree",{enumerable:true,get:function(){return chunkEOOPF3RI_cjs.i}});Object.defineProperty(exports,"findSkillMdPaths",{enumerable:true,get:function(){return chunkEOOPF3RI_cjs.k}});Object.defineProperty(exports,"getSkillFolderHashFromTree",{enumerable:true,get:function(){return chunkEOOPF3RI_cjs.j}});Object.defineProperty(exports,"resetRepoTreeAuthState",{enumerable:true,get:function(){return chunkEOOPF3RI_cjs.h}});Object.defineProperty(exports,"toSkillSlug",{enumerable:true,get:function(){return chunkEOOPF3RI_cjs.g}});Object.defineProperty(exports,"tryBlobInstall",{enumerable:true,get:function(){return chunkEOOPF3RI_cjs.l}});
@@ -0,0 +1 @@
1
+ export{e as BLOB_ALLOWED_REPOS,h as fetchRepoTree,j as findSkillMdPaths,i as getSkillFolderHashFromTree,g as resetRepoTreeAuthState,f as toSkillSlug,k as tryBlobInstall}from'./chunk-MH2XZDJ5.mjs';
@@ -0,0 +1,2 @@
1
+ 'use strict';var crypto=require('crypto'),yaml=require('yaml');var C=Object.defineProperty;var y=(n,t,e)=>t in n?C(n,t,{enumerable:true,configurable:true,writable:true,value:e}):n[t]=e;var N=(n,t,e)=>y(n,typeof t!="symbol"?t+"":t,e);var P=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,S=P();function b(n){let t=n.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);return t?{data:yaml.parse(t[1])??{},content:t[2]??""}:{data:{},content:n}}var I=/\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g,E=/\x1b\][\s\S]*?(?:\x07|\x1b\\)/g,T=/\x1b[P^_][\s\S]*?(?:\x1b\\)/g,F=/\x1b[\x20-\x7e]/g,U=/[\x80-\x9f]/g,$=/[\x00-\x06\x07\x08\x0b\x0c\x0d-\x1a\x1c-\x1f\x7f]/g;function A(n){return n.replace(E,"").replace(T,"").replace(I,"").replace(F,"").replace(U,"").replace($,"")}function x(n){return A(n).replace(/[\r\n]+/g," ").trim()}var B=process.env.SKILLS_DOWNLOAD_URL||"https://skills.sh",D={"zapier/connectors":{downloadUrl:n=>`https://connectors-skills.zapier.com/download/${encodeURIComponent(n)}/snapshot.json`}},L=1e4;function m(n){return n.toLowerCase().replace(/[\s_]+/g,"-").replace(/[^a-z0-9-]/g,"").replace(/-+/g,"-").replace(/^-|-$/g,"")}var R=false;function et(){R=false;}async function w(n,t,e){try{let i=`https://api.github.com/repos/${n}/git/trees/${encodeURIComponent(t)}?recursive=1`,l={Accept:"application/vnd.github.v3+json","User-Agent":"skills-cli"};e&&(l.Authorization=`Bearer ${e}`);let a=await fetch(i,{headers:l,signal:AbortSignal.timeout(L)});if(a.ok){let c=await a.json();return {tree:{sha:c.sha,branch:t,tree:c.tree},rateLimited:!1}}return {tree:null,rateLimited:a.status===403&&a.headers.get("x-ratelimit-remaining")==="0"}}catch{return {tree:null,rateLimited:false}}}async function O(n,t,e){let i=t?[t]:["HEAD","main","master"];if(R&&e){let o=e();if(!o)return null;for(let c of i){let h=await w(n,c,o);if(h.tree)return h.tree}return null}let l=false;for(let o of i){let c=await w(n,o,null);if(c.tree)return c.tree;if(c.rateLimited){l=true;break}}if(!l||!e)return null;R=true;let a=e();if(!a)return null;for(let o of i){let c=await w(n,o,a);if(c.tree)return c.tree}return null}function nt(n,t){let e=t.replace(/\\/g,"/");return e.toLowerCase().endsWith("/skill.md")?e=e.slice(0,-9):e.toLowerCase().endsWith("skill.md")&&(e=e.slice(0,-8)),e.endsWith("/")&&(e=e.slice(0,-1)),e?n.tree.find(l=>l.type==="tree"&&l.path===e)?.sha??null:n.sha}var W=["","skills/","skills/.curated/","skills/.experimental/","skills/.system/",".agents/skills/",".claude/skills/",".cline/skills/",".codebuddy/skills/",".codex/skills/",".commandcode/skills/",".continue/skills/",".github/skills/",".goose/skills/",".iflow/skills/",".junie/skills/",".kilocode/skills/",".kiro/skills/",".mux/skills/",".neovate/skills/",".opencode/skills/",".openhands/skills/",".pi/skills/",".qoder/skills/",".roo/skills/",".trae/skills/",".windsurf/skills/",".zencoder/skills/"];function H(n,t){let e=n.tree.filter(d=>d.type==="blob"&&d.path.toLowerCase().endsWith("skill.md")).map(d=>d.path),i=t?t.endsWith("/")?t:t+"/":"",l=i?e.filter(d=>d.startsWith(i)||d===i+"SKILL.md"):e;if(l.length===0)return [];let a=[],o=new Set,c=new Set(["node_modules",".git","dist","build","__pycache__"]),h=new Set(l.map(d=>d.toLowerCase()));for(let d of W){let g=i+d,r=d!=="";for(let s of l){if(!s.startsWith(g))continue;let u=s.slice(g.length);if(u.toLowerCase()==="skill.md"){o.has(s)||(a.push(s),o.add(s));continue}let f=u.split("/");if(f.length===2&&f[1].toLowerCase()==="skill.md"){o.has(s)||(a.push(s),o.add(s));continue}if(r&&f.length===3&&f[2].toLowerCase()==="skill.md"&&!c.has(f[0])&&!c.has(f[1])){let p=`${g}${f[0]}/SKILL.md`.toLowerCase();!h.has(p)&&!o.has(s)&&(a.push(s),o.add(s));}}}return a.length>0?a:l.filter(d=>d.split("/").length<=6)}async function z(n,t,e){try{let i=`https://raw.githubusercontent.com/${n}/${t}/${e}`,l=await fetch(i,{signal:AbortSignal.timeout(L)});return l.ok?await l.text():null}catch{return null}}async function v(n,t){try{let[e,i]=n.split("/"),l=`${B}/api/download/${encodeURIComponent(e)}/${encodeURIComponent(i)}/${encodeURIComponent(t)}`,o=D[n.toLowerCase()]?.downloadUrl(t)??l,c=await fetch(o,{signal:AbortSignal.timeout(L)});return c.ok?await c.json():null}catch{return null}}function j(n){let t=crypto.createHash("sha256");for(let e of [...n].sort((i,l)=>i.path.localeCompare(l.path)))t.update(e.path),t.update(e.contents);return t.digest("hex")}async function st(n,t={}){let e=await O(n,t.ref,t.getToken);if(!e)return null;let i=H(e,t.subpath);if(i.length===0)return null;if(t.skillFilter){let r=m(t.skillFilter),s=i.filter(u=>{let f=u.split("/");if(f.length<2)return false;let p=f[f.length-2];return m(p)===r});s.length>0&&(i=s);}let l=await Promise.all(i.map(async r=>{let s=await z(n,e.branch,r);return {mdPath:r,content:s}})),a=[];for(let{mdPath:r,content:s}of l){if(!s)continue;let{data:u}=b(s);if(!u.name||!u.description||typeof u.name!="string"||typeof u.description!="string"||u.metadata?.internal===true&&!t.includeInternal)continue;let p=x(u.name),k=x(u.description);a.push({mdPath:r,name:p,description:k,content:s,slug:m(p),metadata:u.metadata});}if(a.length===0)return null;let o=a;if(t.skillFilter){let r=m(t.skillFilter),s=a.filter(u=>u.slug===r);if(s.length>0&&(o=s),o.length===0)return null}let c=n.toLowerCase(),h=await Promise.all(o.map(async r=>{let s=await v(c,r.slug);return {skill:r,download:s}}));return h.every(r=>r.download!==null)?{skills:h.map(({skill:r,download:s})=>{let u=r.mdPath.toLowerCase(),p=(u.endsWith("/skill.md")?r.mdPath.slice(0,-9):u==="skill.md"?"":r.mdPath.slice(0,-9))?s.files:s.files.filter(k=>k.path.toLowerCase()==="skill.md");return {name:r.name,description:r.description,path:"",rawContent:r.content,metadata:r.metadata,files:p,snapshotHash:p.length===s.files.length?s.hash:j(p),repoPath:r.mdPath}}),tree:e}:null}
2
+ exports.a=N;exports.b=S;exports.c=b;exports.d=A;exports.e=x;exports.f=D;exports.g=m;exports.h=et;exports.i=O;exports.j=nt;exports.k=H;exports.l=st;
@@ -0,0 +1,2 @@
1
+ import {createHash}from'crypto';import {parse}from'yaml';var C=Object.defineProperty;var P=(n,t,e)=>t in n?C(n,t,{enumerable:true,configurable:true,writable:true,value:e}):n[t]=e;var K=(n,t,e)=>P(n,typeof t!="symbol"?t+"":t,e);function y(n){let t=n.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);return t?{data:parse(t[1])??{},content:t[2]??""}:{data:{},content:n}}var I=/\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g,E=/\x1b\][\s\S]*?(?:\x07|\x1b\\)/g,F=/\x1b[P^_][\s\S]*?(?:\x1b\\)/g,T=/\x1b[\x20-\x7e]/g,$=/[\x80-\x9f]/g,A=/[\x00-\x06\x07\x08\x0b\x0c\x0d-\x1a\x1c-\x1f\x7f]/g;function B(n){return n.replace(E,"").replace(F,"").replace(I,"").replace(T,"").replace($,"").replace(A,"")}function S(n){return B(n).replace(/[\r\n]+/g," ").trim()}var U=process.env.SKILLS_DOWNLOAD_URL||"https://skills.sh",M={"zapier/connectors":{downloadUrl:n=>`https://connectors-skills.zapier.com/download/${encodeURIComponent(n)}/snapshot.json`}},L=1e4;function m(n){return n.toLowerCase().replace(/[\s_]+/g,"-").replace(/[^a-z0-9-]/g,"").replace(/-+/g,"-").replace(/^-|-$/g,"")}var w=false;function tt(){w=false;}async function x(n,t,e){try{let l=`https://api.github.com/repos/${n}/git/trees/${encodeURIComponent(t)}?recursive=1`,i={Accept:"application/vnd.github.v3+json","User-Agent":"skills-cli"};e&&(i.Authorization=`Bearer ${e}`);let a=await fetch(l,{headers:i,signal:AbortSignal.timeout(L)});if(a.ok){let c=await a.json();return {tree:{sha:c.sha,branch:t,tree:c.tree},rateLimited:!1}}return {tree:null,rateLimited:a.status===403&&a.headers.get("x-ratelimit-remaining")==="0"}}catch{return {tree:null,rateLimited:false}}}async function O(n,t,e){let l=t?[t]:["HEAD","main","master"];if(w&&e){let o=e();if(!o)return null;for(let c of l){let p=await x(n,c,o);if(p.tree)return p.tree}return null}let i=false;for(let o of l){let c=await x(n,o,null);if(c.tree)return c.tree;if(c.rateLimited){i=true;break}}if(!i||!e)return null;w=true;let a=e();if(!a)return null;for(let o of l){let c=await x(n,o,a);if(c.tree)return c.tree}return null}function et(n,t){let e=t.replace(/\\/g,"/");return e.toLowerCase().endsWith("/skill.md")?e=e.slice(0,-9):e.toLowerCase().endsWith("skill.md")&&(e=e.slice(0,-8)),e.endsWith("/")&&(e=e.slice(0,-1)),e?n.tree.find(i=>i.type==="tree"&&i.path===e)?.sha??null:n.sha}var W=["","skills/","skills/.curated/","skills/.experimental/","skills/.system/",".agents/skills/",".claude/skills/",".cline/skills/",".codebuddy/skills/",".codex/skills/",".commandcode/skills/",".continue/skills/",".github/skills/",".goose/skills/",".iflow/skills/",".junie/skills/",".kilocode/skills/",".kiro/skills/",".mux/skills/",".neovate/skills/",".opencode/skills/",".openhands/skills/",".pi/skills/",".qoder/skills/",".roo/skills/",".trae/skills/",".windsurf/skills/",".zencoder/skills/"];function H(n,t){let e=n.tree.filter(d=>d.type==="blob"&&d.path.toLowerCase().endsWith("skill.md")).map(d=>d.path),l=t?t.endsWith("/")?t:t+"/":"",i=l?e.filter(d=>d.startsWith(l)||d===l+"SKILL.md"):e;if(i.length===0)return [];let a=[],o=new Set,c=new Set(["node_modules",".git","dist","build","__pycache__"]),p=new Set(i.map(d=>d.toLowerCase()));for(let d of W){let g=l+d,r=d!=="";for(let s of i){if(!s.startsWith(g))continue;let u=s.slice(g.length);if(u.toLowerCase()==="skill.md"){o.has(s)||(a.push(s),o.add(s));continue}let f=u.split("/");if(f.length===2&&f[1].toLowerCase()==="skill.md"){o.has(s)||(a.push(s),o.add(s));continue}if(r&&f.length===3&&f[2].toLowerCase()==="skill.md"&&!c.has(f[0])&&!c.has(f[1])){let h=`${g}${f[0]}/SKILL.md`.toLowerCase();!p.has(h)&&!o.has(s)&&(a.push(s),o.add(s));}}}return a.length>0?a:i.filter(d=>d.split("/").length<=6)}async function z(n,t,e){try{let l=`https://raw.githubusercontent.com/${n}/${t}/${e}`,i=await fetch(l,{signal:AbortSignal.timeout(L)});return i.ok?await i.text():null}catch{return null}}async function v(n,t){try{let[e,l]=n.split("/"),i=`${U}/api/download/${encodeURIComponent(e)}/${encodeURIComponent(l)}/${encodeURIComponent(t)}`,o=M[n.toLowerCase()]?.downloadUrl(t)??i,c=await fetch(o,{signal:AbortSignal.timeout(L)});return c.ok?await c.json():null}catch{return null}}function j(n){let t=createHash("sha256");for(let e of [...n].sort((l,i)=>l.path.localeCompare(i.path)))t.update(e.path),t.update(e.contents);return t.digest("hex")}async function nt(n,t={}){let e=await O(n,t.ref,t.getToken);if(!e)return null;let l=H(e,t.subpath);if(l.length===0)return null;if(t.skillFilter){let r=m(t.skillFilter),s=l.filter(u=>{let f=u.split("/");if(f.length<2)return false;let h=f[f.length-2];return m(h)===r});s.length>0&&(l=s);}let i=await Promise.all(l.map(async r=>{let s=await z(n,e.branch,r);return {mdPath:r,content:s}})),a=[];for(let{mdPath:r,content:s}of i){if(!s)continue;let{data:u}=y(s);if(!u.name||!u.description||typeof u.name!="string"||typeof u.description!="string"||u.metadata?.internal===true&&!t.includeInternal)continue;let h=S(u.name),k=S(u.description);a.push({mdPath:r,name:h,description:k,content:s,slug:m(h),metadata:u.metadata});}if(a.length===0)return null;let o=a;if(t.skillFilter){let r=m(t.skillFilter),s=a.filter(u=>u.slug===r);if(s.length>0&&(o=s),o.length===0)return null}let c=n.toLowerCase(),p=await Promise.all(o.map(async r=>{let s=await v(c,r.slug);return {skill:r,download:s}}));return p.every(r=>r.download!==null)?{skills:p.map(({skill:r,download:s})=>{let u=r.mdPath.toLowerCase(),h=(u.endsWith("/skill.md")?r.mdPath.slice(0,-9):u==="skill.md"?"":r.mdPath.slice(0,-9))?s.files:s.files.filter(k=>k.path.toLowerCase()==="skill.md");return {name:r.name,description:r.description,path:"",rawContent:r.content,metadata:r.metadata,files:h,snapshotHash:h.length===s.files.length?s.hash:j(h),repoPath:r.mdPath}}),tree:e}:null}
2
+ export{K as a,y as b,B as c,S as d,M as e,m as f,tt as g,O as h,et as i,H as j,nt as k};