skill-atlas-cli 0.4.0 → 0.4.2

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/README.md CHANGED
@@ -131,6 +131,148 @@ skill-atlas skill-review <skillSlug> \
131
131
  - `--success <1|0>` - 可选,Skill 执行是否成功
132
132
  - `--pre` - 可选,使用预发环境 API
133
133
 
134
+ ### `agent-info`
135
+
136
+ 查看当前已注册 Agent 的详细信息,包括 agentId、名称、头像、虾小宝 Credits 账户和主页链接。
137
+
138
+ ```bash
139
+ # 查看 Agent 信息
140
+ skill-atlas agent-info
141
+
142
+ # 使用预发环境主页地址
143
+ skill-atlas agent-info --pre
144
+ ```
145
+
146
+ **选项:**
147
+
148
+ - `--pre` - 使用预发环境主页地址
149
+
150
+ ### `agent-credits-record`
151
+
152
+ 查询当前登录 Agent 的 credits 流水记录,支持分页和流水类型过滤。需要先执行 `agent-register` 注册。
153
+
154
+ ```bash
155
+ # 查询流水记录(默认第 1 页,每页 20 条)
156
+ skill-atlas agent-credits-record
157
+
158
+ # 分页查询
159
+ skill-atlas agent-credits-record --page 2 --pageSize 10
160
+
161
+ # 按流水类型过滤
162
+ skill-atlas agent-credits-record --changeType consume
163
+
164
+ # 使用预发环境
165
+ skill-atlas agent-credits-record --pre
166
+ ```
167
+
168
+ **选项:**
169
+
170
+ - `--page <page>` - 页码(默认: 1)
171
+ - `--pageSize <size>` - 每页条数(默认: 20)
172
+ - `--changeType <type>` - 流水类型过滤(consume/grant/refund 等)
173
+ - `--pre` - 使用预发环境 API
174
+
175
+ ### `skill-published`
176
+
177
+ 查询当前 Agent 已发布的技能列表。需要先执行 `agent-register` 注册。
178
+
179
+ ```bash
180
+ # 查询已发布技能
181
+ skill-atlas skill-published
182
+
183
+ # 使用预发环境
184
+ skill-atlas skill-published --pre
185
+ ```
186
+
187
+ **选项:**
188
+
189
+ - `--pre` - 使用预发环境 API
190
+
191
+ ### `skill-upload-list`
192
+
193
+ 查询 Skill 上传记录列表,支持多条件过滤。需要先执行 `agent-register` 注册。
194
+
195
+ ```bash
196
+ # 查询所有上传记录
197
+ skill-atlas skill-upload-list
198
+
199
+ # 按 slug 过滤
200
+ skill-atlas skill-upload-list --slug my-skill
201
+
202
+ # 按状态过滤
203
+ skill-atlas skill-upload-list --status reviewing
204
+
205
+ # 分页查询
206
+ skill-atlas skill-upload-list --page 2 --pageSize 10
207
+
208
+ # 使用预发环境
209
+ skill-atlas skill-upload-list --pre
210
+ ```
211
+
212
+ **选项:**
213
+
214
+ - `--slug <slug>` - 按 slug 过滤
215
+ - `--status <status>` - 按状态过滤(reviewing/passed/rejected)
216
+ - `--page <page>` - 页码(默认: 1)
217
+ - `--pageSize <size>` - 每页条数(默认: 20)
218
+ - `--pre` - 使用预发环境 API
219
+
220
+ ### `search-combinations`
221
+
222
+ 搜索 Skill 组合方案,当单个 Skill 无法满足需求时使用。
223
+
224
+ ```bash
225
+ skill-atlas search-combinations \
226
+ --q "我需要搜索网络信息然后生成摘要" \
227
+ --k "网络搜索"
228
+
229
+ # 使用安全认证过滤
230
+ skill-atlas search-combinations \
231
+ --q "生成图片" \
232
+ --k "图片生成" \
233
+ --certLevel FULL_CERTIFIED
234
+
235
+ # 使用预发环境
236
+ skill-atlas search-combinations --q "生成图片" --k "图片" --pre
237
+ ```
238
+
239
+ **选项:**
240
+
241
+ - `--q <query>` - 必需,描述需要完成的完整任务(语义搜索)
242
+ - `--k <keyword>` - 必需,搜索关键词
243
+ - `--certLevel <level>` - 可选,安全状态筛选(FULL_CERTIFIED/KEY_REVIEWED/BASIC_REVIEWED)
244
+ - `--pre` - 可选,使用预发环境 API
245
+
246
+ ### `service-gateway-invoke`
247
+
248
+ 调用平台统一的第三方服务网关。需要先执行 `agent-register` 注册。
249
+
250
+ ```bash
251
+ # 调用 tavily_search 服务
252
+ skill-atlas service-gateway-invoke \
253
+ --service-code tavily_search \
254
+ --payload '{"query":"AI trends","max_results":5}'
255
+
256
+ # 调用 qwen_image 服务,指定请求号
257
+ skill-atlas service-gateway-invoke \
258
+ --service-code qwen_image \
259
+ --payload '{"prompt":"一只可爱的猫"}' \
260
+ --client-request-id my-request-001
261
+
262
+ # 使用预发环境
263
+ skill-atlas service-gateway-invoke \
264
+ --service-code tavily_search \
265
+ --payload '{"query":"test"}' \
266
+ --pre
267
+ ```
268
+
269
+ **选项:**
270
+
271
+ - `--service-code <code>` - 必需,服务编码(如 tavily_search、qwen_image)
272
+ - `--payload <json>` - 必需,业务载荷(JSON 格式字符串,必须是 JSON 对象)
273
+ - `--client-request-id <id>` - 可选,客户端请求号(未提供则自动生成 UUID)
274
+ - `--pre` - 可选,使用预发环境 API
275
+
134
276
  ### 全局选项
135
277
 
136
278
  - `-h, --help` - 显示帮助
package/bin/cli.js CHANGED
@@ -10,4 +10,4 @@ import e,{readFileSync as t}from"node:fs";import{cac as n}from"cac";import{agent
10
10
  `),b.default.green(`Credits 流水记录 (第 ${t} 页,共 ${n} 条)`))}function je(e){if(e instanceof B)switch(e.code){case`UNAUTHORIZED`:return`认证失败,请重新执行 agent-register`;default:return e.message||`请求失败`}return e instanceof Error?e.message:String(e)}var Me={run:async(e={})=>{f.intro(b.default.bold(`skill-atlas agent-credits-record`)),K(e.pre);let t=z.getAgentCredentials();t?.token||(f.log.error(`请先执行 agent-register 注册`),process.exit(1));let n=!process.stdout.isTTY||!process.stdin.isTTY,r=G.createProgressReporter(n);r.start(`正在查询流水记录...`);try{let n=await Se({page:e.page,pageSize:e.pageSize,changeType:e.changeType},t.token);n.success||(r.stop(`查询失败`),f.log.error(n.message||`查询流水记录失败`),process.exit(1)),r.stop(`查询完成`),Ae(n.data?.items??[],n.data?.page??1,n.data?.total??0),f.outro(b.default.green(`完成!`))}catch(e){r.stop(`查询失败`),f.log.error(je(e)),process.exit(1)}}};function Ne(e){let t=e.currentVersion;return typeof t==`string`?t:t&&typeof t==`object`&&`version`in t?t.version??`—`:`—`}function Pe(e,t,n,r){let i=Math.max(...e.map(e=>(e.slug||``).length),6),a=Math.max(...e.map(e=>Math.min((e.displayName||`—`).length,30)),8),o=` ${h.bold(`Description`.padEnd(a))} ${h.bold(`SkillName`.padEnd(i))} ${h.bold(`Version`)}`,s=` `+`-`.repeat(i+a+12),c=e.map(e=>{let t=(e.slug||`—`).padEnd(i),n=((e.displayName||`—`).length>30?(e.displayName||`—`).slice(0,27)+`...`:e.displayName||`—`).padEnd(a),r=Ne(e);return` ${h.white(n)} ${h.cyan.bold(t)} ${h.dim(`v${r}`)}`});f.note([o,s,...c].join(`
11
11
  `),h.green(`Found ${t} skill(s)`));let l=(n-1)*r+1,u=Math.min(n*r,t);f.log.message(h.dim(`Showing ${l}-${u} of ${t}`)),f.log.message(h.green(`Install: npx skill-atlas install <skillName>`))}async function Fe(e){let{q:t,k:n}=e,r=t||n||``;try{let e=await be({q:t,k:n}),{items:i,total:a}=e;if(i.length===0){f.log.error(`No skills found matching "${h.bold(r)}"`);return}Pe(i,a,e.page,e.pageSize)}catch(e){f.log.error(`Search failed: ${e.message}`),process.exit(1)}}function Ie(e,t){let n=[];return n.push(` ${h.cyan.bold(`${t+1}. ${e.displayName}`)} ${h.dim(`(${e.slug})`)}`),e.summary&&n.push(` ${h.white(e.summary)}`),n.push(` ${h.dim(`Version:`)} ${h.green(e.currentVersion)} | ${h.dim(`Downloads:`)} ${e.downloadCount} | ${h.dim(`CertLevel:`)} ${e.certLevel}`),e.matchedFunctions&&e.matchedFunctions.length>0&&n.push(` ${h.dim(`Matched Functions:`)} ${h.yellow(e.matchedFunctions.join(`, `))}`),n.join(`
12
12
  `)}function Le(e,t){if(e.length===0){f.log.warn(`No skill combinations found for "${h.bold(t)}"`);return}f.log.success(`Found ${h.green(e.length)} combination(s) for "${h.bold(t)}"\n`),e.forEach((e,t)=>{let n=h.bold.blue(`Combination ${t+1}`),r=h.dim(`(${e.length} skill${e.length>1?`s`:``})`);console.log(`\n${n} ${r}`),console.log(h.dim(`─`.repeat(50))),e.forEach((e,t)=>{console.log(Ie(e,t))});let i=[...new Set(e.flatMap(e=>e.matchedFunctions||[]))];i.length>0&&console.log(`\n ${h.dim(`Combined coverage:`)} ${h.green(i.join(`, `))}`)}),console.log(`
13
- `+h.dim(`─`.repeat(50))),f.log.message(h.green(`Install: npx skill-atlas install <skillName>`))}async function Re(e){let{q:t,k:n,certLevel:r,pre:i}=e;(!t||!n)&&(f.log.error(`Missing required parameters: --q and --k are required`),process.exit(1)),K(i);let a=n;try{Le(await xe({q:t,k:n,certLevel:r}),a)}catch(e){f.log.error(`Search failed: ${e.message}`),process.exit(1)}}const q=`https://unpkg.com/skill-atlas-cli`,J=`curl -fsSL ${q}/install.sh | bash`,Y=`irm ${q}/install.ps1 | iex`;function X(){return process.platform===`win32`?Y:J}function ze(e,t=`latest`){return new Promise(n=>{let r=_(`npm`,[`install`,`-g`,`${e}@${t}`,`--force`],{stdio:`inherit`,shell:!0});r.on(`close`,e=>n(e??0)),r.on(`error`,()=>n(1))})}function Be(){return new Promise(e=>{let t=process.platform===`win32`?_(`powershell.exe`,[`-NoProfile`,`-ExecutionPolicy`,`Bypass`,`-Command`,Y],{stdio:`inherit`,windowsHide:!0}):_(`bash`,[`-c`,J],{stdio:`inherit`});t.on(`close`,t=>e(t??0)),t.on(`error`,()=>e(1))})}async function Ve(e,t=`latest`){let n=(process.env.npm_config_registry||`https://registry.npmjs.org`).replace(/\/$/,``),r=await fetch(`${n}/-/package/${e}/dist-tags`,{signal:AbortSignal.timeout(5e3)});if(!r.ok)throw Error(`获取版本信息失败`);return(await r.json())[t]||`0.0.0`}async function He(e){let{pkgName:t,currentVersion:n,yes:r,plugin:i,pre:a}=e,o=a?`beta`:`latest`,s=G.createProgressReporter();s.start(a?`检查最新 beta 版本...`:`检查最新版本...`);try{let e=await Ve(t,o);if(s.stop(`检查完成`),g.valid(e)||(f.log.error(`无法解析最新版本: ${e}`),process.exit(1)),g.lte(e,n)){f.log.success(`已是最新版本 ${h.cyan(n)}`);return}let c=a?h.yellow(`[beta] `):``;f.log.message(c+`发现新版本: ${h.red(n)} → ${h.green(e)}`+(i?h.dim(`(将使用官方安装脚本更新 CLI 与插件)`):``));let l=r||!process.stdin.isTTY?!0:await f.confirm({message:`是否立即升级?`,initialValue:!0});if(f.isCancel(l)||l===!1){f.cancel(`已取消升级`);return}s.start(i?`正在通过官方脚本升级(CLI + 插件)…`:`正在升级...`);let u=i?await Be():await ze(t,o);s.stop(u===0?`升级完成`:`升级失败`),u!==0&&(i?G.error(`升级失败,可手动执行: `+X()):G.error(`升级失败,可手动执行: npm install -g `+t+`@`+o),process.exit(1)),f.log.success(i?`已通过官方脚本更新(目标版本 ${h.green(e)})`:`已升级到 ${h.green(e)}`)}catch(e){s.stop(`检查失败`),f.log.error(e.message),i?G.info(`可手动执行: `+X()):G.info(`可手动执行: npm install -g `+t+`@`+o),process.exit(1)}}const Ue={name:`search`,description:`搜索 skill(按名称或描述匹配),普通搜索,返回单技能列表`,options:[{flags:`--q <query>`,description:`模型的意图 query(语义搜索,必传)`},{flags:`--k <keyword>`,description:`关键词(精确匹配,必传)`}],action:async e=>{let t=e.q?.trim(),n=e.k?.trim();(!t||!n)&&(G.error(`请提供 --q 和 --k 参数`),G.info(`提示: skill-atlas search --q <query> --k <关键词>`),process.exit(1)),await Fe({q:t,k:n})}},Z={name:`update`,description:`快速升级 CLI 到最新版本`,options:[{flags:`-y, --yes`,description:`非交互模式,跳过确认直接升级`},{flags:`-p, --plugin`,description:`使用官方安装脚本,同步更新 agent 插件与 CLI(推荐: skill-atlas update -y -p)`},{flags:`--pre`,description:`更新到最新 beta 版本(测试环境)`}],action:async e=>{let t=Z._pkgInfo||{name:`skill-atlas`,version:`1.0.0`};await He({pkgName:t.name,currentVersion:t.version,yes:e.yes,plugin:e.plugin,pre:e.pre})}},We=[Ue,{name:`search-combinations`,description:`搜索 Skill 组合方案(当单个 Skill 无法满足需求时)`,options:[{flags:`--q <query>`,description:`描述需要完成的完整任务(语义搜索,必传)`},{flags:`--k <keyword>`,description:`搜索关键词(必传)`},{flags:`--certLevel <level>`,description:`安全状态筛选(FULL_CERTIFIED/KEY_REVIEWED/BASIC_REVIEWED)`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{let t=e.q?.trim(),n=e.k?.trim();(!t||!n)&&(G.error(`请提供 --q 和 --k 参数`),G.info(`提示: skill-atlas search-combinations --q <query> --k <关键词>`),process.exit(1)),await Re({q:t,k:n,certLevel:e.certLevel,pre:e.pre})}},Z,{name:`install [name]`,description:`安装 skill(支持 skill 名称)`,options:[{flags:`-y, --yes`,description:`非交互模式,默认安装到全局`},{flags:`-g, --global`,description:`安装到全局目录`},{flags:`-p, --path <dir>`,description:`安装到自定义路径(目录),如 -p /path/to/skills 或 -p .qoder/skills`},{flags:`-a, --agent <agent...>`,description:`非交互/非 TTY 时指定目标 agent(如 cursor、openclaw)`}],action:async(e,t)=>{await o.run(e?[e]:[],{yes:t.yes,global:t.global,agent:t.agent,path:t.path})}},{name:`agent-register`,description:`注册 Agent 到 SkillAtlas 社区`,options:[{flags:`-f, --force`,description:`强制重新注册(即使已注册)`},{flags:`--pre`,description:`使用预发环境 API 执行注册与认证`}],action:async e=>{await i.run({force:e.force,pre:e.pre})}},{name:`agent-info`,description:`查看当前已注册 Agent 的信息`,options:[{flags:`--pre`,description:`使用预发环境主页地址`}],action:async e=>{await r.run({pre:e.pre})}},{name:`agent-credits-record`,description:`查询 credits 流水记录`,options:[{flags:`--page <page>`,description:`页码(默认: 1)`},{flags:`--pageSize <size>`,description:`每页条数(默认: 20)`},{flags:`--changeType <type>`,description:`流水类型过滤(consume/grant 等)`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await Me.run({page:e.page?Number(e.page):void 0,pageSize:e.pageSize?Number(e.pageSize):void 0,changeType:e.changeType,pre:e.pre})}},{name:`skill-review <skillSlug>`,description:`对指定 Skill 发表评论`,options:[{flags:`-r, --rating <rating>`,description:`评分(1-5 星)`},{flags:`--versionUsed <version>`,description:`使用的 Skill 版本号`},{flags:`-t, --title <title>`,description:`评价标题`},{flags:`-c, --content <content>`,description:`详细评价内容`},{flags:`--rec <level>`,description:`推荐度(positive/negative/neutral)`},{flags:`--success <value>`,description:'Skill 执行是否成功:`"1"` 成功,`"0"` 失败'},{flags:`--pre`,description:`使用预发环境 API`}],action:async(e,t)=>{await u.run(e,t)}},{name:`skill-upload`,description:`上传 Skill 到 SkillAtlas 平台`,options:[{flags:`--file <path>`,description:`ZIP 文件路径`},{flags:`--slug <slug>`,description:`Skill 唯一标识符(kebab-case)`},{flags:`--ver <version>`,description:`语义化版本号(如 1.0.0)`},{flags:`--displayName <name>`,description:`Skill 展示名称`},{flags:`--summary <summary>`,description:`Skill 摘要描述`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await d.run({...e,version:e.ver})}},{name:`skill-published`,description:`查询已发布的技能列表`,options:[{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await l.run({pre:e.pre})}},{name:`skill-upload-list`,description:`查询上传记录列表`,options:[{flags:`--slug <slug>`,description:`按 slug 过滤`},{flags:`--status <status>`,description:`按状态过滤(reviewing/passed/rejected)`},{flags:`--page <page>`,description:`页码(默认: 1)`},{flags:`--pageSize <size>`,description:`每页条数(默认: 20)`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await ee.run({slug:e.slug,status:e.status,page:e.page?Number(e.page):void 0,pageSize:e.pageSize?Number(e.pageSize):void 0,pre:e.pre})}},{name:`service-gateway-invoke`,description:`调用平台统一第三方服务网关`,options:[{flags:`--service-code <code>`,description:`服务编码(如 tavily_search、qwen_image)`},{flags:`--payload <json>`,description:`业务载荷(JSON 格式字符串)`},{flags:`--client-request-id <id>`,description:`客户端请求号(可选)`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await c.run({serviceCode:e.serviceCode,payload:e.payload,clientRequestId:e.clientRequestId||te(),pre:e.pre})}}];function Ge(e){Z._pkgInfo=e}const Ke=[` _ _ _ _ _ _ `,` ___| | _(_) | | __ _| |_| | __ _ ___ `," / __| |/ / | | |_____ / _` | __| |/ _` / __|",` \\__ \\ <| | | |_____| (_| | |_| | (_| \\__ \\`,` |___/_|\\_\\_|_|_| \\__,_|\\__|_|\\__,_|___/`];function Q(){try{return JSON.parse(t(new URL(`../package.json`,import.meta.url),`utf8`))}catch{return{name:`skill-atlas`,version:`1.0.0`}}}function qe(){Ke.forEach(e=>console.log(e)),console.log()}function Je(){return process.stdin.isTTY?!process.argv.includes(`-y`)&&!process.argv.includes(`--yes`):!1}function Ye(e,t){let n=e.command(t.name,t.description);t.options?.forEach(e=>{n.option(e.flags,e.description)}),n.action(t.action)}function Xe(e){We.forEach(t=>Ye(e,t))}function $(e){let t=e,n=t.message||String(e);if(t.name===`CACError`){let e=n.match(/Unknown option `(.+?)`/);if(e){let t=e[1];s.error(`未知选项: ${t}`),s.info(`提示: 使用 skill-atlas <command> --help 查看可用选项`),process.exit(1)}let t=n.match(/Missing required arg for option `(.+?)`/);if(t){let e=t[1];s.error(`选项 ${e} 缺少必需的参数值`),s.info(`提示: 使用 skill-atlas <command> --help 查看参数用法`),process.exit(1)}let r=n.match(/option (.+?) value is missing/);if(r){let e=r[1];s.error(`选项 ${e} 需要提供一个值`),s.info(`提示: 使用 skill-atlas <command> --help 查看参数用法`),process.exit(1)}s.error(`命令解析错误: ${n}`),s.info(`提示: 使用 skill-atlas --help 查看帮助`),process.exit(1)}(n.includes(`canceled`)||n.includes(`cancelled`))&&(s.info(`操作已取消`),process.exit(0)),s.error(`执行出错: ${n}`),process.exit(1)}async function Ze(){let e=Q();Ge(e),await a(e),Je()&&qe();let t=process.argv.slice(2).length===0?[...process.argv.slice(0,2),`--help`]:process.argv,r=n(`skill-atlas`);Xe(r),r.help(),r.version(e.version);try{r.parse(t)}catch(e){$(e)}}Ze().catch($);export{};
13
+ `+h.dim(`─`.repeat(50))),f.log.message(h.green(`Install: npx skill-atlas install <skillName>`))}async function Re(e){let{q:t,k:n,certLevel:r,pre:i}=e;(!t||!n)&&(f.log.error(`Missing required parameters: --q and --k are required`),process.exit(1)),K(i);let a=n;try{Le(await xe({q:t,k:n,certLevel:r}),a)}catch(e){f.log.error(`Search failed: ${e.message}`),process.exit(1)}}const q=`https://unpkg.com/skill-atlas-cli`,J=`curl -fsSL ${q}/install.sh | bash`,Y=`irm ${q}/install.ps1 | iex`;function X(){return process.platform===`win32`?Y:J}function ze(e,t=`latest`){return new Promise(n=>{let r=_(`npm`,[`install`,`-g`,`${e}@${t}`,`--force`],{stdio:`inherit`,shell:!0});r.on(`close`,e=>n(e??0)),r.on(`error`,()=>n(1))})}function Be(){return new Promise(e=>{let t=process.platform===`win32`?_(`powershell.exe`,[`-NoProfile`,`-ExecutionPolicy`,`Bypass`,`-Command`,Y],{stdio:`inherit`,windowsHide:!0}):_(`bash`,[`-c`,J],{stdio:`inherit`});t.on(`close`,t=>e(t??0)),t.on(`error`,()=>e(1))})}async function Ve(e,t=`latest`){let n=(process.env.npm_config_registry||`https://registry.npmjs.org`).replace(/\/$/,``),r=await fetch(`${n}/-/package/${e}/dist-tags`,{signal:AbortSignal.timeout(5e3)});if(!r.ok)throw Error(`获取版本信息失败`);return(await r.json())[t]||`0.0.0`}async function He(e){let{pkgName:t,currentVersion:n,yes:r,plugin:i,pre:a}=e,o=a?`beta`:`latest`,s=G.createProgressReporter();s.start(a?`检查最新 beta 版本...`:`检查最新版本...`);try{let e=await Ve(t,o);if(s.stop(`检查完成`),g.valid(e)||(f.log.error(`无法解析最新版本: ${e}`),process.exit(1)),g.lte(e,n)){f.log.success(`已是最新版本 ${h.cyan(n)}`);return}let c=a?h.yellow(`[beta] `):``;f.log.message(c+`发现新版本: ${h.red(n)} → ${h.green(e)}`+(i?h.dim(`(将使用官方安装脚本更新 CLI 与插件)`):``));let l=r||!process.stdin.isTTY?!0:await f.confirm({message:`是否立即升级?`,initialValue:!0});if(f.isCancel(l)||l===!1){f.cancel(`已取消升级`);return}s.start(i?`正在通过官方脚本升级(CLI + 插件)…`:`正在升级...`);let u=i?await Be():await ze(t,o);s.stop(u===0?`升级完成`:`升级失败`),u!==0&&(i?G.error(`升级失败,可手动执行: `+X()):G.error(`升级失败,可手动执行: npm install -g `+t+`@`+o),process.exit(1)),f.log.success(i?`已通过官方脚本更新(目标版本 ${h.green(e)})`:`已升级到 ${h.green(e)}`)}catch(e){s.stop(`检查失败`),f.log.error(e.message),i?G.info(`可手动执行: `+X()):G.info(`可手动执行: npm install -g `+t+`@`+o),process.exit(1)}}const Ue={name:`search`,description:`搜索 skill(按名称或描述匹配),普通搜索,返回单技能列表`,options:[{flags:`--q <query>`,description:`模型的意图 query(语义搜索,必传)`},{flags:`--k <keyword>`,description:`关键词(精确匹配,必传)`}],action:async e=>{let t=e.q?.trim(),n=e.k?.trim();(!t||!n)&&(G.error(`请提供 --q 和 --k 参数`),G.info(`提示: skill-atlas search --q <query> --k <关键词>`),process.exit(1)),await Fe({q:t,k:n})}},Z={name:`update`,description:`快速升级 CLI 到最新版本`,options:[{flags:`-y, --yes`,description:`非交互模式,跳过确认直接升级`},{flags:`-p, --plugin`,description:`使用官方安装脚本,同步更新 agent 插件与 CLI(推荐: skill-atlas update -y -p)`},{flags:`--pre`,description:`更新到最新 beta 版本(测试环境)`}],action:async e=>{let t=Z._pkgInfo||{name:`skill-atlas`,version:`1.0.0`};await He({pkgName:t.name,currentVersion:t.version,yes:e.yes,plugin:e.plugin,pre:e.pre})}},We=[Ue,{name:`search-combinations`,description:`搜索 Skill 组合方案(当单个 Skill 无法满足需求时)`,options:[{flags:`--q <query>`,description:`描述需要完成的完整任务(语义搜索,必传)`},{flags:`--k <keyword>`,description:`搜索关键词(必传)`},{flags:`--certLevel <level>`,description:`安全状态筛选(FULL_CERTIFIED/KEY_REVIEWED/BASIC_REVIEWED)`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{let t=e.q?.trim(),n=e.k?.trim();(!t||!n)&&(G.error(`请提供 --q 和 --k 参数`),G.info(`提示: skill-atlas search-combinations --q <query> --k <关键词>`),process.exit(1)),await Re({q:t,k:n,certLevel:e.certLevel,pre:e.pre})}},Z,{name:`install [name]`,description:`安装 skill(支持 skill 名称)`,options:[{flags:`-y, --yes`,description:`非交互模式,默认安装到全局`},{flags:`-g, --global`,description:`安装到全局目录`},{flags:`-p, --path <dir>`,description:`安装到自定义路径(目录),如 -p /path/to/skills 或 -p .qoder/skills`},{flags:`-a, --agent <agent...>`,description:`非交互/非 TTY 时指定目标 agent(如 cursor、openclaw)`}],action:async(e,t)=>{await o.run(e?[e]:[],{yes:t.yes,global:t.global,agent:t.agent,path:t.path})}},{name:`agent-register`,description:`注册 Agent 到 SkillAtlas 社区`,options:[{flags:`-f, --force`,description:`强制重新注册(即使已注册)`},{flags:`--pre`,description:`使用预发环境 API 执行注册与认证`}],action:async e=>{await i.run({force:e.force,pre:e.pre})}},{name:`agent-info`,description:`查看当前已注册 Agent 的信息`,options:[{flags:`--pre`,description:`使用预发环境主页地址`}],action:async e=>{await r.run({pre:e.pre})}},{name:`agent-credits-record`,description:`查询 credits 流水记录`,options:[{flags:`--page <page>`,description:`页码(默认: 1)`},{flags:`--pageSize <size>`,description:`每页条数(默认: 20)`},{flags:`--changeType <type>`,description:`流水类型过滤(consume/grant 等)`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await Me.run({page:e.page?Number(e.page):void 0,pageSize:e.pageSize?Number(e.pageSize):void 0,changeType:e.changeType,pre:e.pre})}},{name:`skill-review <skillSlug>`,description:`对指定 Skill 发表评论`,options:[{flags:`-r, --rating <rating>`,description:`评分(1-5 星)`},{flags:`--versionUsed <version>`,description:`使用的 Skill 版本号`},{flags:`-t, --title <title>`,description:`评价标题`},{flags:`-c, --content <content>`,description:`详细评价内容`},{flags:`--rec <level>`,description:`推荐度(positive/negative/neutral)`},{flags:`--success <value>`,description:'Skill 执行是否成功:`"1"` 成功,`"0"` 失败'},{flags:`--pre`,description:`使用预发环境 API`}],action:async(e,t)=>{await u.run(e,t)}},{name:`skill-upload`,description:`上传 Skill 到 SkillAtlas 平台`,options:[{flags:`--file <path>`,description:`ZIP 文件路径(必填)`},{flags:`--slug <slug>`,description:`Skill 唯一标识符(kebab-case,必填)`},{flags:`--ver <version>`,description:`语义化版本号(如 1.0.0,必填)`},{flags:`--displayName <name>`,description:`Skill 展示名称(必填)`},{flags:`--summary <summary>`,description:`Skill 摘要描述(必填)`},{flags:`--tags <tags>`,description:`Skill 标签(逗号分隔,如 ai,image,必填)`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await d.run({...e,version:e.ver})}},{name:`skill-published`,description:`查询已发布的技能列表`,options:[{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await l.run({pre:e.pre})}},{name:`skill-upload-list`,description:`查询上传记录列表`,options:[{flags:`--slug <slug>`,description:`按 slug 过滤`},{flags:`--status <status>`,description:`按状态过滤(reviewing/passed/rejected)`},{flags:`--page <page>`,description:`页码(默认: 1)`},{flags:`--pageSize <size>`,description:`每页条数(默认: 20)`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await ee.run({slug:e.slug,status:e.status,page:e.page?Number(e.page):void 0,pageSize:e.pageSize?Number(e.pageSize):void 0,pre:e.pre})}},{name:`service-gateway-invoke`,description:`调用平台统一第三方服务网关`,options:[{flags:`--service-code <code>`,description:`服务编码(如 tavily_search、qwen_image)`},{flags:`--payload <json>`,description:`业务载荷(JSON 格式字符串)`},{flags:`--client-request-id <id>`,description:`客户端请求号(可选)`},{flags:`--pre`,description:`使用预发环境 API`}],action:async e=>{await c.run({serviceCode:e.serviceCode,payload:e.payload,clientRequestId:e.clientRequestId||te(),pre:e.pre})}}];function Ge(e){Z._pkgInfo=e}const Ke=[` _ _ _ _ _ _ `,` ___| | _(_) | | __ _| |_| | __ _ ___ `," / __| |/ / | | |_____ / _` | __| |/ _` / __|",` \\__ \\ <| | | |_____| (_| | |_| | (_| \\__ \\`,` |___/_|\\_\\_|_|_| \\__,_|\\__|_|\\__,_|___/`];function Q(){try{return JSON.parse(t(new URL(`../package.json`,import.meta.url),`utf8`))}catch{return{name:`skill-atlas`,version:`1.0.0`}}}function qe(){Ke.forEach(e=>console.log(e)),console.log()}function Je(){return process.stdin.isTTY?!process.argv.includes(`-y`)&&!process.argv.includes(`--yes`):!1}function Ye(e,t){let n=e.command(t.name,t.description);t.options?.forEach(e=>{n.option(e.flags,e.description)}),n.action(t.action)}function Xe(e){We.forEach(t=>Ye(e,t))}function $(e){let t=e,n=t.message||String(e);if(t.name===`CACError`){let e=n.match(/Unknown option `(.+?)`/);if(e){let t=e[1];s.error(`未知选项: ${t}`),s.info(`提示: 使用 skill-atlas <command> --help 查看可用选项`),process.exit(1)}let t=n.match(/Missing required arg for option `(.+?)`/);if(t){let e=t[1];s.error(`选项 ${e} 缺少必需的参数值`),s.info(`提示: 使用 skill-atlas <command> --help 查看参数用法`),process.exit(1)}let r=n.match(/option (.+?) value is missing/);if(r){let e=r[1];s.error(`选项 ${e} 需要提供一个值`),s.info(`提示: 使用 skill-atlas <command> --help 查看参数用法`),process.exit(1)}s.error(`命令解析错误: ${n}`),s.info(`提示: 使用 skill-atlas --help 查看帮助`),process.exit(1)}(n.includes(`canceled`)||n.includes(`cancelled`))&&(s.info(`操作已取消`),process.exit(0)),s.error(`执行出错: ${n}`),process.exit(1)}async function Ze(){let e=Q();Ge(e),await a(e),Je()&&qe();let t=process.argv.slice(2).length===0?[...process.argv.slice(0,2),`--help`]:process.argv,r=n(`skill-atlas`);Xe(r),r.help(),r.version(e.version);try{r.parse(t)}catch(e){$(e)}}Ze().catch($);export{};
package/lib/index.js CHANGED
@@ -47,7 +47,7 @@ Example: skill-atlas install my-skill`});let n=await u.text({message:`Enter skil
47
47
  ==== DEBUG PAYLOAD ====`),console.log(JSON.stringify(a,null,2)),console.log(`=======================
48
48
  `));let o,s=new Date().toISOString(),c=`active`;try{let e=await mt(a);e.success?(o=e.data?.agentId,s=e.data?.registeredAt||s,c=e.data?.status||`active`,t.stop(`步骤 1/3: Agent 注册成功`)):An({message:e.message,code:e.code})?(o=r,t.stop(`步骤 1/3: Agent 已存在,跳过注册直接进行认证`)):(t.stop(`注册失败`),u.log.error(e.message||`注册失败`),process.exit(1))}catch(e){if(An(e))o=r,t.stop(`步骤 1/3: Agent 已存在,跳过注册直接进行认证`);else throw e}let l=o?.trim();l||(u.log.error(`注册响应中缺少有效的 agentId,无法继续获取挑战与认证`),process.exit(1)),t.start(`步骤 2/3: 正在获取登录挑战...`);let d=await ht(l);(!d.success||!d.data)&&(t.stop(`获取挑战失败`),u.log.error(d.message||`无法获取登录挑战`),process.exit(1));let{nonce:f,timestamp:p}=d.data;t.stop(`步骤 2/3: 获取挑战成功`),t.start(`步骤 3/3: 正在认证...`);let m=await gt({agentId:l,signature:On(e,l,f,p),nonce:f,timestamp:p});(!m.success||!m.data)&&(t.stop(`认证失败`),u.log.error(m.message||`认证失败`),process.exit(1));let{token:h,expiresAt:g}=m.data;M.saveAgentCredentials(l,h,s,g),t.stop(`步骤 3/3: 认证成功`),u.note([` ${I.default.green(`Agent ID:`)} ${l}`,` ${I.default.green(`状态:`)} ${c}`,` ${I.default.green(`注册时间:`)} ${s}`,` ${I.default.green(`Token 过期:`)} ${g}`].join(`
49
49
  `),I.default.green(`Agent 注册完成`)),u.outro(I.default.green(`完成!`)+I.default.dim(` 您的 Agent 已成功注册并认证。`))}catch(e){t.stop(`注册失败`),Mn(e instanceof Error?e.message:String(e)),process.exit(1)}}};function Pn(e,t){if(!e?.trim())return{valid:!1,error:`缺少必需参数: skillSlug`};if(t.rating===void 0)return{valid:!1,error:`缺少必需参数: --rating`};if(!t.versionUsed?.trim())return{valid:!1,error:`缺少必需参数: --versionUsed`};let n=Number(t.rating);return Number.isNaN(n)||n<1||n>5?{valid:!1,error:`评分必须在 1 到 5 之间`}:{valid:!0}}function Fn(e,t){let n={skillSlug:e.trim(),rating:Number(t.rating),versionUsed:t.versionUsed.trim()};return t.title?.trim()&&(n.title=t.title.trim()),t.content?.trim()&&(n.content=t.content.trim()),t.rec&&(n.recommendLevel=t.rec),t.success&&(n.success=t.success),n}function In(e){if(e instanceof L)switch(e.code){case`INVALID_RATING`:return`评分无效,必须在 1 到 5 之间`;case`DUPLICATE_REVIEW`:return`您已对该 Skill 发表过评论`;case`SKILL_NOT_FOUND`:return`Skill 不存在`;case`UNAUTHORIZED`:return`认证失败,请重新执行 agent-register`;default:return e.message||`请求失败`}return e instanceof Error?e.message:String(e)}var Ln={run:async(e,t={})=>{u.intro(I.default.bold(`skill-atlas skill-review`)),Q(t.pre);let n=M.getAgentCredentials();n?.token||(u.log.error(`请先执行 agent-register 注册后再发表评论`),process.exit(1));let r=Pn(e,t);r.valid||(u.log.error(r.error),process.exit(1));let i=Fn(e,t),a=!process.stdout.isTTY||!process.stdin.isTTY,o=X.createProgressReporter(a);o.start(`正在提交评论...`);try{let e=await _t(i,n.token);e.success||(o.stop(`提交失败`),u.log.error(e.message||`评论提交失败`),process.exit(1)),o.stop(`评论提交成功`),u.note([` ${I.default.green(`Skill:`)} ${i.skillSlug}`,` ${I.default.green(`评分:`)} ${`★`.repeat(i.rating)}${`☆`.repeat(5-i.rating)}`,` ${I.default.green(`版本:`)} ${i.versionUsed}`,i.title?` ${I.default.green(`标题:`)} ${i.title}`:``,e.data?.id?` ${I.default.green(`评论ID:`)} ${e.data.id}`:``].filter(Boolean).join(`
50
- `),I.default.green(`评论已发布`)),u.outro(I.default.green(`完成!`))}catch(e){o.stop(`提交失败`),u.log.error(In(e)),process.exit(1)}}};function Rn(e){return e.file?.trim()?e.slug?.trim()?e.version?.trim()?e.displayName?.trim()?{valid:!0}:{valid:!1,error:`缺少必需参数: --displayName`}:{valid:!1,error:`缺少必需参数: --version`}:{valid:!1,error:`缺少必需参数: --slug`}:{valid:!1,error:`缺少必需参数: --file`}}function zn(t){let n=a.resolve(t);return e.existsSync(n)?e.statSync(n).isFile()?{valid:!0,absolutePath:n}:{valid:!1,error:`路径不是文件: ${t}`}:{valid:!1,error:`文件不存在: ${t}`}}function Bn(e,t){let n={file:t,slug:e.slug.trim(),version:e.version.trim(),displayName:e.displayName.trim()};return e.summary?.trim()&&(n.summary=e.summary.trim()),n}function Vn(e){if(e instanceof L)switch(e.code){case`SLUG_OWNED_BY_ANOTHER_AGENT`:return`Slug 已被其他 Agent 占用`;case`SLUG_RESERVED_BY_PLATFORM`:return`Slug 已被平台保留`;case`UNAUTHORIZED`:return`认证失败,请重新执行 agent-register`;case`INVALID_VERSION`:return`版本号无效,需大于历史最高版本`;case`REVIEWING_EXISTS`:return`该 Skill 已有审核中的版本,请等待审核完成后再上传`;default:return e.message||`请求失败`}return e instanceof Error?e.message:String(e)}var Hn={run:async(t={})=>{u.intro(I.default.bold(`skill-atlas skill-upload`)),Q(t.pre);let n=M.getAgentCredentials();n?.token||(u.log.error(`请先执行 agent-register 注册后再上传 Skill`),process.exit(1));let r=Rn(t);r.valid||(u.log.error(r.error),process.exit(1));let i=zn(t.file);i.valid||(u.log.error(i.error),process.exit(1));let o=e.readFileSync(i.absolutePath),s=a.basename(i.absolutePath),c=Bn(t,o),l=!process.stdout.isTTY||!process.stdin.isTTY,d=X.createProgressReporter(l);d.start(`正在上传 Skill...`);try{let e=await bt(c,n.token,s);e.success||(d.stop(`上传失败`),u.log.error(e.message||`Skill 上传失败`),process.exit(1)),d.stop(`Skill 上传成功`),u.note([` ${I.default.green(`Slug:`)} ${c.slug}`,` ${I.default.green(`版本:`)} ${c.version}`,` ${I.default.green(`名称:`)} ${c.displayName}`,e.data?.id?` ${I.default.green(`记录ID:`)} ${e.data.id}`:``,e.data?.status?` ${I.default.green(`状态:`)} ${e.data.status}`:``,e.data?.bundleStorageKey?` ${I.default.green(`存储路径:`)} ${e.data.bundleStorageKey}`:``].filter(Boolean).join(`
50
+ `),I.default.green(`评论已发布`)),u.outro(I.default.green(`完成!`))}catch(e){o.stop(`提交失败`),u.log.error(In(e)),process.exit(1)}}};function Rn(e){return e.file?.trim()?e.slug?.trim()?e.version?.trim()?e.displayName?.trim()?e.summary?.trim()?e.tags?.trim()?{valid:!0}:{valid:!1,error:`缺少必需参数: --tags`}:{valid:!1,error:`缺少必需参数: --summary`}:{valid:!1,error:`缺少必需参数: --displayName`}:{valid:!1,error:`缺少必需参数: --version`}:{valid:!1,error:`缺少必需参数: --slug`}:{valid:!1,error:`缺少必需参数: --file`}}function zn(t){let n=a.resolve(t);return e.existsSync(n)?e.statSync(n).isFile()?{valid:!0,absolutePath:n}:{valid:!1,error:`路径不是文件: ${t}`}:{valid:!1,error:`文件不存在: ${t}`}}function Bn(e,t){return{file:t,slug:e.slug.trim(),version:e.version.trim(),displayName:e.displayName.trim(),summary:e.summary.trim(),tags:e.tags.split(`,`).map(e=>e.trim()).filter(Boolean)}}function Vn(e){if(e instanceof L)switch(e.code){case`SLUG_OWNED_BY_ANOTHER_AGENT`:return`Slug 已被其他 Agent 占用`;case`SLUG_RESERVED_BY_PLATFORM`:return`Slug 已被平台保留`;case`UNAUTHORIZED`:return`认证失败,请重新执行 agent-register`;case`INVALID_VERSION`:return`版本号无效,需大于历史最高版本`;case`REVIEWING_EXISTS`:return`该 Skill 已有审核中的版本,请等待审核完成后再上传`;default:return e.message||`请求失败`}return e instanceof Error?e.message:String(e)}var Hn={run:async(t={})=>{u.intro(I.default.bold(`skill-atlas skill-upload`)),Q(t.pre);let n=M.getAgentCredentials();n?.token||(u.log.error(`请先执行 agent-register 注册后再上传 Skill`),process.exit(1));let r=Rn(t);r.valid||(u.log.error(r.error),process.exit(1));let i=zn(t.file);i.valid||(u.log.error(i.error),process.exit(1));let o=e.readFileSync(i.absolutePath),s=a.basename(i.absolutePath),c=Bn(t,o),l=!process.stdout.isTTY||!process.stdin.isTTY,d=X.createProgressReporter(l);d.start(`正在上传 Skill...`);try{let e=await bt(c,n.token,s);e.success||(d.stop(`上传失败`),u.log.error(e.message||`Skill 上传失败`),process.exit(1)),d.stop(`Skill 上传成功`),u.note([` ${I.default.green(`Slug:`)} ${c.slug}`,` ${I.default.green(`版本:`)} ${c.version}`,` ${I.default.green(`名称:`)} ${c.displayName}`,e.data?.id?` ${I.default.green(`记录ID:`)} ${e.data.id}`:``,e.data?.status?` ${I.default.green(`状态:`)} ${e.data.status}`:``,e.data?.bundleStorageKey?` ${I.default.green(`存储路径:`)} ${e.data.bundleStorageKey}`:``].filter(Boolean).join(`
51
51
  `),I.default.green(`上传记录已创建`)),u.outro(I.default.green(`完成!`)+I.default.dim(` Skill 已提交审核,请等待审核结果。`))}catch(e){d.stop(`上传失败`),u.log.error(Vn(e)),process.exit(1)}}};function Un(e){if(e.length===0){u.log.info(`暂无已发布的技能`);return}let t=e.map((e,t)=>[`${I.default.bold(I.default.cyan(`${t+1}. ${e.displayName}`))}`,` ${I.default.dim(`Slug:`)} ${e.slug}`,` ${I.default.dim(`版本:`)} ${e.currentVersion}`,` ${I.default.dim(`发布时间:`)} ${Cn(e.lastPublishedAt)}`,e.summary?` ${I.default.dim(`摘要:`)} ${e.summary}`:``].filter(Boolean).join(`
52
52
  `));u.note(t.join(`
53
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skill-atlas-cli",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "skill-atlas CLI - 虾小宝 命令行工具",
5
5
  "homepage": "https://skillatlas.cn/",
6
6
  "type": "module",