@neta-art/neta-search-cli 0.2.14 → 0.2.16
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 +5 -1
- package/neta-search.mjs +185 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,10 +7,14 @@ npx -y @neta-art/neta-search-cli@0.2 skills find "generate video" # search (
|
|
|
7
7
|
npx -y @neta-art/neta-search-cli@0.2 skills find "browser automation" --json
|
|
8
8
|
npx -y @neta-art/neta-search-cli@0.2 skills use <id> # print the SKILL.md (pulled into a temp dir; no project files written)
|
|
9
9
|
npx -y @neta-art/neta-search-cli@0.2 skills add <id> # install into .agents/skills/
|
|
10
|
+
npx -y @neta-art/neta-search-cli@0.2 skills list # what's in .agents/skills/, and which installed ones have updates
|
|
11
|
+
npx -y @neta-art/neta-search-cli@0.2 skills update # update installed skills to their current release
|
|
10
12
|
npx -y @neta-art/neta-search-cli@0.2 skills init <name> # scaffold your own skill
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
`<id>` comes from `find` results, e.g. `cohub:<spaceId>/<name
|
|
15
|
+
`<id>` comes from `find` results, e.g. `cohub:<spaceId>/<name>`; a handle such as `neta-skills/holo-pack-opening` works too.
|
|
16
|
+
|
|
17
|
+
`skills remove <name>` deletes an installed skill from `.agents/skills/`. Skills you wrote yourself (no install record) are left alone unless you pass `--force`.
|
|
14
18
|
|
|
15
19
|
`use` prints the skill directory and the full SKILL.md, so an agent can follow it right away; relative paths in SKILL.md resolve against that directory. If the local entry is a pointer (frontmatter `metadata.neta-skill-id`), `use` fetches the full skill it points to.
|
|
16
20
|
|
package/neta-search.mjs
CHANGED
|
@@ -2660,7 +2660,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2660
2660
|
const negativeNumberArg = (arg) => {
|
|
2661
2661
|
if (!/^-(\d+|\d*\.\d+)(e[+-]?\d+)?$/.test(arg)) return false;
|
|
2662
2662
|
return !this._getCommandAndAncestors().some(
|
|
2663
|
-
(cmd) => cmd.options.map((opt) => opt.short).some((
|
|
2663
|
+
(cmd) => cmd.options.map((opt) => opt.short).some((short2) => /^-\d$/.test(short2))
|
|
2664
2664
|
);
|
|
2665
2665
|
};
|
|
2666
2666
|
let activeVariadicOption = null;
|
|
@@ -27077,6 +27077,14 @@ async function fetchArchive(env, id) {
|
|
|
27077
27077
|
if (got !== digest) throw new Error(`\u4E0B\u8F7D\u7684 ${id} \u5185\u5BB9\u6821\u9A8C\u5931\u8D25\uFF08\u671F\u671B ${digest}\uFF0C\u5B9E\u9645 ${got}\uFF09`);
|
|
27078
27078
|
return { id, name, digest, files };
|
|
27079
27079
|
}
|
|
27080
|
+
async function archiveHead(env, id) {
|
|
27081
|
+
const url = `${env.apiBase}${ARCHIVE_PATH}?id=${encodeURIComponent(id)}`;
|
|
27082
|
+
const res = await fetch(url, { method: "HEAD", redirect: "manual", signal: AbortSignal.timeout(1e4) });
|
|
27083
|
+
if (res.status === 404) return null;
|
|
27084
|
+
const digest = res.headers.get("x-skill-digest") ?? "";
|
|
27085
|
+
if (res.status < 300 || res.status >= 400 || !digest) throw new Error(`\u67E5\u8BE2 ${id} \u5931\u8D25\uFF1AHTTP ${res.status}`);
|
|
27086
|
+
return { id: res.headers.get("x-skill-id") ?? id, name: res.headers.get("x-skill-name") ?? id.split("/").pop(), digest };
|
|
27087
|
+
}
|
|
27080
27088
|
async function download(url, id) {
|
|
27081
27089
|
for (let attempt = 1; ; attempt++) {
|
|
27082
27090
|
const res = await fetch(url, { signal: AbortSignal.timeout(TIMEOUT_MS) });
|
|
@@ -27156,6 +27164,21 @@ function parseId(s) {
|
|
|
27156
27164
|
const m = ID_RE.exec(s);
|
|
27157
27165
|
return m ? { spaceId: m[1], name: m[2] } : null;
|
|
27158
27166
|
}
|
|
27167
|
+
var HANDLE_RE = /^(@[a-z0-9_.-]{1,64}|[a-z0-9][a-z0-9-]{0,31})\/[a-z0-9][a-z0-9-]{0,63}$/i;
|
|
27168
|
+
function isHandle(s) {
|
|
27169
|
+
return !parseId(s) && HANDLE_RE.test(s);
|
|
27170
|
+
}
|
|
27171
|
+
async function resolveRef(env, input) {
|
|
27172
|
+
if (!isHandle(input)) return input;
|
|
27173
|
+
try {
|
|
27174
|
+
const r = await fetch(`${env.apiBase}/v1/skills/resolve?handle=${encodeURIComponent(input)}`, { signal: AbortSignal.timeout(5e3) });
|
|
27175
|
+
if (!r.ok) return input;
|
|
27176
|
+
const out = await r.json();
|
|
27177
|
+
return typeof out.id === "string" && parseId(out.id) ? out.id : input;
|
|
27178
|
+
} catch {
|
|
27179
|
+
return input;
|
|
27180
|
+
}
|
|
27181
|
+
}
|
|
27159
27182
|
function ownId(env, name) {
|
|
27160
27183
|
return `cohub:${env.spaceId}/${name}`;
|
|
27161
27184
|
}
|
|
@@ -27228,6 +27251,7 @@ function shareNotice(id, dir, draft, reported) {
|
|
|
27228
27251
|
// cli/src/skills/add.ts
|
|
27229
27252
|
async function cmdAdd(idOrName, opts) {
|
|
27230
27253
|
const env = detectEnv();
|
|
27254
|
+
idOrName = await resolveRef(env, idOrName);
|
|
27231
27255
|
const parsed = parseId(idOrName);
|
|
27232
27256
|
const name = parsed?.name ?? idOrName;
|
|
27233
27257
|
const target = join3(opts.dir, name);
|
|
@@ -27279,19 +27303,9 @@ import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as
|
|
|
27279
27303
|
import { randomUUID } from "node:crypto";
|
|
27280
27304
|
import { join as join4 } from "node:path";
|
|
27281
27305
|
var FETCH_ROOT = process.env["NETASEARCH_FETCH_ROOT"] ?? join4("/tmp", "neta-skills");
|
|
27282
|
-
var HANDLE_RE = /^(@[a-z0-9_.-]{1,64}|[a-z0-9][a-z0-9-]{0,31})\/[a-z0-9][a-z0-9-]{0,63}$/i;
|
|
27283
|
-
async function resolveHandle(env, input) {
|
|
27284
|
-
const r = await fetch(`${env.apiBase}/v1/skills/resolve?handle=${encodeURIComponent(input)}`, { signal: AbortSignal.timeout(5e3) });
|
|
27285
|
-
if (!r.ok) return null;
|
|
27286
|
-
const out = await r.json();
|
|
27287
|
-
return typeof out.id === "string" && parseId(out.id) ? out.id : null;
|
|
27288
|
-
}
|
|
27289
27306
|
async function cmdUse(idOrName, opts) {
|
|
27290
27307
|
const env = detectEnv();
|
|
27291
|
-
|
|
27292
|
-
const resolved = await resolveHandle(env, idOrName).catch(() => null);
|
|
27293
|
-
if (resolved) idOrName = resolved;
|
|
27294
|
-
}
|
|
27308
|
+
idOrName = await resolveRef(env, idOrName);
|
|
27295
27309
|
const parsed = parseId(idOrName);
|
|
27296
27310
|
const name = parsed?.name ?? idOrName;
|
|
27297
27311
|
const mine = !parsed || parsed.spaceId === env.spaceId;
|
|
@@ -27443,6 +27457,153 @@ metadata:
|
|
|
27443
27457
|
`;
|
|
27444
27458
|
}
|
|
27445
27459
|
|
|
27460
|
+
// cli/src/skills/manage.ts
|
|
27461
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3, rmSync as rmSync2 } from "node:fs";
|
|
27462
|
+
import { join as join6 } from "node:path";
|
|
27463
|
+
function scanLocal(dir) {
|
|
27464
|
+
if (!existsSync5(dir)) return [];
|
|
27465
|
+
const out = [];
|
|
27466
|
+
for (const e of readdirSync3(dir, { withFileTypes: true })) {
|
|
27467
|
+
if (!e.isDirectory() || e.name.startsWith(".")) continue;
|
|
27468
|
+
const path = join6(dir, e.name);
|
|
27469
|
+
if (!skillDirExists(path)) continue;
|
|
27470
|
+
const src = readSource(path);
|
|
27471
|
+
if (src) {
|
|
27472
|
+
out.push({ name: e.name, path, kind: "installed", id: src.id, digest: src.digest });
|
|
27473
|
+
continue;
|
|
27474
|
+
}
|
|
27475
|
+
const ptr = pointerTarget(path);
|
|
27476
|
+
out.push(ptr ? { name: e.name, path, kind: "pointer", id: ptr } : { name: e.name, path, kind: "own" });
|
|
27477
|
+
}
|
|
27478
|
+
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
27479
|
+
}
|
|
27480
|
+
async function statusOf(env, s) {
|
|
27481
|
+
if (s.kind !== "installed" || !s.id) return { status: "unknown" };
|
|
27482
|
+
try {
|
|
27483
|
+
const head = await archiveHead(env, s.id);
|
|
27484
|
+
if (!head) return { status: "unavailable" };
|
|
27485
|
+
return { status: head.digest === s.digest ? "latest" : "outdated", latest: head.digest };
|
|
27486
|
+
} catch (e) {
|
|
27487
|
+
return { status: "unknown", error: e instanceof Error ? e.message : String(e) };
|
|
27488
|
+
}
|
|
27489
|
+
}
|
|
27490
|
+
var KIND_LABEL = { installed: "\u88C5\u6765\u7684", pointer: "\u6307\u9488", own: "\u81EA\u5DF1\u5199\u7684" };
|
|
27491
|
+
var STATUS_LABEL = { latest: "\u6700\u65B0", outdated: "\u6709\u66F4\u65B0", unavailable: "\u5DF2\u4E0B\u67B6", unknown: "" };
|
|
27492
|
+
async function cmdList(opts) {
|
|
27493
|
+
const env = detectEnv();
|
|
27494
|
+
const local = scanLocal(opts.dir);
|
|
27495
|
+
const rows = await Promise.all(
|
|
27496
|
+
local.map(async (s) => ({ ...s, ...opts.offline ? { status: "unknown" } : await statusOf(env, s) }))
|
|
27497
|
+
);
|
|
27498
|
+
if (opts.json) {
|
|
27499
|
+
console.log(JSON.stringify({ dir: opts.dir, count: rows.length, skills: rows }));
|
|
27500
|
+
return 0;
|
|
27501
|
+
}
|
|
27502
|
+
if (rows.length === 0) {
|
|
27503
|
+
console.log(`${opts.dir}/ \u91CC\u6CA1\u6709 skill\u3002\u7528 neta-search skills find <\u610F\u56FE> \u627E\uFF0C\u518D add \u5B89\u88C5\u3002`);
|
|
27504
|
+
return 0;
|
|
27505
|
+
}
|
|
27506
|
+
console.log(`${opts.dir}/\uFF08${rows.length} \u4E2A\uFF09\uFF1A`);
|
|
27507
|
+
for (const r of rows) {
|
|
27508
|
+
const st = STATUS_LABEL[r.status] ? ` [${STATUS_LABEL[r.status]}]` : "";
|
|
27509
|
+
const from = r.id ? ` ${r.id}` : "";
|
|
27510
|
+
console.log(` ${r.name.padEnd(28)} ${KIND_LABEL[r.kind]}${st}${from}`);
|
|
27511
|
+
}
|
|
27512
|
+
const outdated = rows.filter((r) => r.status === "outdated").length;
|
|
27513
|
+
if (outdated > 0) console.log(`
|
|
27514
|
+
${outdated} \u4E2A\u6709\u66F4\u65B0\uFF1Aneta-search skills update`);
|
|
27515
|
+
return 0;
|
|
27516
|
+
}
|
|
27517
|
+
async function cmdUpdate(names, opts) {
|
|
27518
|
+
const env = detectEnv();
|
|
27519
|
+
const local = scanLocal(opts.dir);
|
|
27520
|
+
const byName = new Map(local.map((s) => [s.name, s]));
|
|
27521
|
+
const targets = [];
|
|
27522
|
+
const results = [];
|
|
27523
|
+
let failed = 0;
|
|
27524
|
+
if (names.length === 0) {
|
|
27525
|
+
targets.push(...local.filter((s) => s.kind === "installed"));
|
|
27526
|
+
} else {
|
|
27527
|
+
for (const n of names) {
|
|
27528
|
+
const s = byName.get(n);
|
|
27529
|
+
if (!s) {
|
|
27530
|
+
results.push({ name: n, result: "not_found" });
|
|
27531
|
+
failed++;
|
|
27532
|
+
} else if (s.kind !== "installed") {
|
|
27533
|
+
results.push({ name: n, result: s.kind === "own" ? "own_skipped" : "pointer_skipped" });
|
|
27534
|
+
} else targets.push(s);
|
|
27535
|
+
}
|
|
27536
|
+
}
|
|
27537
|
+
for (const s of targets) {
|
|
27538
|
+
const st = await statusOf(env, s);
|
|
27539
|
+
if (st.status === "latest") {
|
|
27540
|
+
results.push({ name: s.name, result: "latest" });
|
|
27541
|
+
continue;
|
|
27542
|
+
}
|
|
27543
|
+
if (st.status === "unavailable") {
|
|
27544
|
+
results.push({ name: s.name, result: "unavailable" });
|
|
27545
|
+
continue;
|
|
27546
|
+
}
|
|
27547
|
+
if (st.status === "unknown") {
|
|
27548
|
+
results.push({ name: s.name, result: "error", from: st.error });
|
|
27549
|
+
failed++;
|
|
27550
|
+
continue;
|
|
27551
|
+
}
|
|
27552
|
+
try {
|
|
27553
|
+
const a = await fetchArchive(env, s.id);
|
|
27554
|
+
writeSkill(s.path, a.files, { id: s.id, digest: a.digest });
|
|
27555
|
+
await reportSkillEvent(env, "install", s.id, a.digest, s.name);
|
|
27556
|
+
results.push({ name: s.name, result: "updated", from: s.digest, to: a.digest });
|
|
27557
|
+
} catch (e) {
|
|
27558
|
+
results.push({ name: s.name, result: e instanceof ArchiveNotFound ? "unavailable" : "error", from: e instanceof Error ? e.message : String(e) });
|
|
27559
|
+
if (!(e instanceof ArchiveNotFound)) failed++;
|
|
27560
|
+
}
|
|
27561
|
+
}
|
|
27562
|
+
if (opts.json) {
|
|
27563
|
+
console.log(JSON.stringify({ results }));
|
|
27564
|
+
return failed > 0 ? 1 : 0;
|
|
27565
|
+
}
|
|
27566
|
+
if (results.length === 0) console.log(`${opts.dir}/ \u91CC\u6CA1\u6709\u88C5\u6765\u7684 skill\uFF0C\u4E0D\u7528\u66F4\u65B0\u3002`);
|
|
27567
|
+
const say = {
|
|
27568
|
+
updated: (r) => `\u5DF2\u66F4\u65B0 ${r.name}\uFF08${short(r.from)} \u2192 ${short(r.to)}\uFF09`,
|
|
27569
|
+
latest: (r) => `${r.name} \u5DF2\u662F\u6700\u65B0`,
|
|
27570
|
+
unavailable: (r) => `${r.name} \u6765\u6E90\u5DF2\u4E0B\u67B6\u6216\u64A4\u56DE\uFF0C\u4FDD\u7559\u672C\u5730\u526F\u672C`,
|
|
27571
|
+
own_skipped: (r) => `${r.name} \u662F\u4F60\u81EA\u5DF1\u5199\u7684\uFF0C\u4E0D\u7528\u66F4\u65B0`,
|
|
27572
|
+
pointer_skipped: (r) => `${r.name} \u662F\u6307\u9488\uFF0Cuse \u65F6\u603B\u662F\u53D6\u6700\u65B0\uFF0C\u4E0D\u7528\u66F4\u65B0`,
|
|
27573
|
+
not_found: (r) => `${opts.dir}/${r.name} \u4E0D\u5B58\u5728`,
|
|
27574
|
+
error: (r) => `${r.name} \u66F4\u65B0\u5931\u8D25\uFF1A${r.from ?? ""}`
|
|
27575
|
+
};
|
|
27576
|
+
for (const r of results) console.log(say[r.result](r));
|
|
27577
|
+
return failed > 0 ? 1 : 0;
|
|
27578
|
+
}
|
|
27579
|
+
function short(d) {
|
|
27580
|
+
return (d ?? "").replace(/^sha256:/, "").slice(0, 12) || "?";
|
|
27581
|
+
}
|
|
27582
|
+
async function cmdRemove(names, opts) {
|
|
27583
|
+
const byName = new Map(scanLocal(opts.dir).map((s) => [s.name, s]));
|
|
27584
|
+
const results = [];
|
|
27585
|
+
for (const n of names) {
|
|
27586
|
+
const s = byName.get(n);
|
|
27587
|
+
if (!s || n.includes("/") || n.startsWith(".")) {
|
|
27588
|
+
results.push({ name: n, result: "not_found" });
|
|
27589
|
+
} else if (s.kind === "own" && !opts.force) {
|
|
27590
|
+
results.push({ name: n, result: "own_refused" });
|
|
27591
|
+
} else {
|
|
27592
|
+
rmSync2(s.path, { recursive: true, force: true });
|
|
27593
|
+
results.push({ name: n, result: "removed" });
|
|
27594
|
+
}
|
|
27595
|
+
}
|
|
27596
|
+
const failed = results.filter((r) => r.result !== "removed").length;
|
|
27597
|
+
if (opts.json) console.log(JSON.stringify({ results }));
|
|
27598
|
+
else
|
|
27599
|
+
for (const r of results) {
|
|
27600
|
+
if (r.result === "removed") console.log(`\u5DF2\u5220\u9664 ${join6(opts.dir, r.name)}`);
|
|
27601
|
+
else if (r.result === "not_found") console.error(`${join6(opts.dir, r.name)} \u4E0D\u5B58\u5728`);
|
|
27602
|
+
else console.error(`${r.name} \u662F\u4F60\u81EA\u5DF1\u5199\u7684 skill\uFF08\u6CA1\u6709\u5B89\u88C5\u6765\u6E90\uFF09\uFF0C\u6CA1\u5220\u3002\u786E\u5B9A\u8981\u5220\u5C31\u52A0 --force\u3002`);
|
|
27603
|
+
}
|
|
27604
|
+
return failed > 0 ? 1 : 0;
|
|
27605
|
+
}
|
|
27606
|
+
|
|
27446
27607
|
// cli/src/version.ts
|
|
27447
27608
|
import { createRequire } from "node:module";
|
|
27448
27609
|
var OUR_NAMES = /* @__PURE__ */ new Set(["@neta-search/cli", "@neta-art/neta-search-cli"]);
|
|
@@ -27461,16 +27622,25 @@ function cliVersion() {
|
|
|
27461
27622
|
// cli/src/cli.ts
|
|
27462
27623
|
var program2 = new Command();
|
|
27463
27624
|
program2.name("neta-search").description("neta-search\u2014\u2014Cohub \u751F\u6001\u68C0\u7D22 CLI\uFF08\u8D44\u6E90\u5B50\u547D\u4EE4\uFF1Askills\uFF1B\u667A\u80FD\u5728 search-api\uFF0CCLI \u662F\u8584\u58F3\uFF09").version(cliVersion());
|
|
27464
|
-
var skills = program2.command("skills").description("skill \u57DF\uFF1Afind/add/use/init");
|
|
27625
|
+
var skills = program2.command("skills").description("skill \u57DF\uFF1Afind/add/use/list/update/remove/init");
|
|
27465
27626
|
skills.command("find").description("\u627E skill\uFF08\u751F\u6001\u8D26\u672C+\u5916\u90E8\u6E90\u6DF7\u6392\u68C0\u7D22\uFF09").argument("<query>", "\u68C0\u7D22\u610F\u56FE\uFF08\u81EA\u7136\u8BED\u8A00/\u5173\u952E\u8BCD\uFF09").option("-n, --limit <n>", "\u5019\u9009\u6570\u4E0A\u9650", "20").option("--json", "\u7D27\u51D1 JSON \u8F93\u51FA\uFF08agent \u6D88\u8D39\uFF09").action(async (query, opts) => {
|
|
27466
27627
|
await run(cmdFind(query, { limit: Number(opts.limit) || 20, json: opts.json }));
|
|
27467
27628
|
});
|
|
27468
|
-
skills.command("add").description("\u88C5 skill\uFF08find \u7ED3\u679C\u7684 id\uFF1A\u4E0B\u8F7D\
|
|
27629
|
+
skills.command("add").description("\u88C5 skill\uFF08find \u7ED3\u679C\u7684 id \u6216 handle\uFF1A\u4E0B\u8F7D\u5F53\u524D\u4E0A\u67B6\u7684\u7248\u672C\uFF1B\u6216\u81EA\u5DF1\u8349\u7A3F\u533A\u7684\u540D\u5B57\uFF1A\u79FB\u5230 .agents/skills/\uFF09").argument("<id-or-name>", "find \u8FD4\u56DE\u7684 skill id \u6216 handle\uFF08\u5982 neta-skills/holo-pack-opening\uFF09\uFF0C\u6216\u81EA\u5DF1\u8349\u7A3F\u533A\u7684 skill \u540D").option("--dir <dir>", "\u5B89\u88C5\u76EE\u5F55\uFF08\u9ED8\u8BA4 .agents/skills/\uFF09", ".agents/skills").option("--json", "\u7D27\u51D1 JSON \u8F93\u51FA\uFF08agent \u6D88\u8D39\uFF09").action(async (idOrName, opts) => {
|
|
27469
27630
|
await run(cmdAdd(idOrName, opts));
|
|
27470
27631
|
});
|
|
27471
|
-
skills.command("use").description("\u7528 skill\uFF08\u4E0D\u88C5\uFF1A\u6253\u5370 SKILL.md \u5168\u6587\u548C skill \u76EE\u5F55\uFF1B\u672C\u5730\u6709\u2192\u7528\u672C\u5730\u7684\uFF1B\u672C\u5730\u662F\u6307\u9488\u6216\u6CA1\u6709\u2192\u6309 id \u4E0B\u8F7D\u5230\u4E34\u65F6\u76EE\u5F55\uFF09").argument("<id-or-name>", "skill id \u6216
|
|
27632
|
+
skills.command("use").description("\u7528 skill\uFF08\u4E0D\u88C5\uFF1A\u6253\u5370 SKILL.md \u5168\u6587\u548C skill \u76EE\u5F55\uFF1B\u672C\u5730\u6709\u2192\u7528\u672C\u5730\u7684\uFF1B\u672C\u5730\u662F\u6307\u9488\u6216\u6CA1\u6709\u2192\u6309 id \u4E0B\u8F7D\u5230\u4E34\u65F6\u76EE\u5F55\uFF09").argument("<id-or-name>", "skill id\u3001handle\uFF08\u5982 neta-skills/holo-pack-opening\uFF09\u6216\u672C\u5730 skill \u540D").option("--json", "\u7D27\u51D1 JSON \u8F93\u51FA\uFF08agent \u6D88\u8D39\uFF09").option("--via <channel>", "\u4ECE\u54EA\u4E2A\u6E20\u9053\u6765\u7684\uFF08\u8BB0\u8FDB\u4F7F\u7528\u8BB0\u5F55\uFF1Bhub mod \u7684\u6307\u9488\u5199 pointer\uFF09").action(async (idOrName, opts) => {
|
|
27472
27633
|
await run(cmdUse(idOrName, opts));
|
|
27473
27634
|
});
|
|
27635
|
+
skills.command("list").alias("ls").description("\u5217\u51FA\u672C\u5730\u7684 skill\uFF08\u88C5\u6765\u7684 / \u6307\u9488 / \u81EA\u5DF1\u5199\u7684\uFF09\uFF0C\u88C5\u6765\u7684\u987A\u5E26\u67E5\u6709\u6CA1\u6709\u66F4\u65B0").option("--dir <dir>", "\u76EE\u5F55\uFF08\u9ED8\u8BA4 .agents/skills/\uFF09", ".agents/skills").option("--offline", "\u4E0D\u8054\u7F51\u67E5\u66F4\u65B0").option("--json", "\u7D27\u51D1 JSON \u8F93\u51FA\uFF08agent \u6D88\u8D39\uFF09").action(async (opts) => {
|
|
27636
|
+
await run(cmdList({ dir: opts.dir, offline: !!opts.offline, json: !!opts.json }));
|
|
27637
|
+
});
|
|
27638
|
+
skills.command("update").description("\u66F4\u65B0\u88C5\u6765\u7684 skill \u5230\u5F53\u524D\u4E0A\u67B6\u7684\u7248\u672C\uFF08\u4E0D\u7ED9\u540D\u5B57 = \u5168\u90E8\uFF1B\u81EA\u5DF1\u5199\u7684\u548C\u6307\u9488\u4E0D\u78B0\uFF09").argument("[names...]", "\u8981\u66F4\u65B0\u7684 skill \u540D\uFF08\u76EE\u5F55\u540D\uFF09").option("--dir <dir>", "\u76EE\u5F55\uFF08\u9ED8\u8BA4 .agents/skills/\uFF09", ".agents/skills").option("--json", "\u7D27\u51D1 JSON \u8F93\u51FA\uFF08agent \u6D88\u8D39\uFF09").action(async (names, opts) => {
|
|
27639
|
+
await run(cmdUpdate(names, { dir: opts.dir, json: !!opts.json }));
|
|
27640
|
+
});
|
|
27641
|
+
skills.command("remove").alias("rm").description("\u5220\u9664\u672C\u5730 skill\uFF08\u88C5\u6765\u7684 / \u6307\u9488\uFF1B\u81EA\u5DF1\u5199\u7684\u8981 --force\uFF09").argument("<names...>", "\u8981\u5220\u7684 skill \u540D\uFF08\u76EE\u5F55\u540D\uFF09").option("--dir <dir>", "\u76EE\u5F55\uFF08\u9ED8\u8BA4 .agents/skills/\uFF09", ".agents/skills").option("--force", "\u8FDE\u81EA\u5DF1\u5199\u7684\u4E5F\u5220").option("--json", "\u7D27\u51D1 JSON \u8F93\u51FA\uFF08agent \u6D88\u8D39\uFF09").action(async (names, opts) => {
|
|
27642
|
+
await run(cmdRemove(names, { dir: opts.dir, force: !!opts.force, json: !!opts.json }));
|
|
27643
|
+
});
|
|
27474
27644
|
skills.command("init").description("\u521B\u5EFA skill \u811A\u624B\u67B6\uFF08SKILL.md + frontmatter \u89C4\u8303\uFF09").argument("[name]", "skill \u540D\uFF08kebab-case\uFF09").option("--here", "\u5728\u5F53\u524D\u76EE\u5F55\u751F\u6210\uFF08\u9ED8\u8BA4\u751F\u6210\u5230 ./<name>/ \u5B50\u76EE\u5F55\uFF09").action(async (name, opts) => {
|
|
27475
27645
|
await run(cmdInit(name, opts));
|
|
27476
27646
|
});
|