@neta-art/neta-search-cli 0.2.10 → 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 +207 -17
- 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;
|
|
@@ -26912,9 +26912,10 @@ function detectEnv() {
|
|
|
26912
26912
|
const spaceId = process.env["COHUB_SPACE_ID"] ?? "";
|
|
26913
26913
|
const apiBase = process.env["NETASEARCH_API"] ?? // sandbox 内(平台注入 COHUB_*):默认 prod Service——真实用户的事件该写
|
|
26914
26914
|
// prod 账本;否则 prod sandbox 的事件会全部写进 dev 账本(review #76 抓过的
|
|
26915
|
-
// 隐患)。sandbox
|
|
26915
|
+
// 隐患)。sandbox 外:默认 prod 公网地址(2026-10-09 起;此前是 dev,公网 npm 版发布前改),
|
|
26916
|
+
// 本地验收用 NETASEARCH_API 指 dev。
|
|
26916
26917
|
// 不依赖平台注入 NETASEARCH_API——COHUB_SPACE_ID 就是平台已给的信号。
|
|
26917
|
-
(spaceId !== "" ? "http://neta-search-api.recsys.svc.cluster.local" : "https://
|
|
26918
|
+
(spaceId !== "" ? "http://neta-search-api.recsys.svc.cluster.local" : "https://search.neta.art");
|
|
26918
26919
|
return {
|
|
26919
26920
|
apiBase,
|
|
26920
26921
|
actorId,
|
|
@@ -27063,21 +27064,37 @@ var ArchiveNotFound = class extends Error {
|
|
|
27063
27064
|
};
|
|
27064
27065
|
async function fetchArchive(env, id) {
|
|
27065
27066
|
const url = `${env.apiBase}${ARCHIVE_PATH}?id=${encodeURIComponent(id)}`;
|
|
27067
|
+
const res = await fetch(url, { redirect: "manual", signal: AbortSignal.timeout(TIMEOUT_MS) });
|
|
27068
|
+
if (res.status === 404) throw new ArchiveNotFound(`${id} \u4E0D\u5B58\u5728\uFF0C\u6216\u8FD8\u6CA1\u6709\u4E0A\u67B6\u7684\u7248\u672C`);
|
|
27069
|
+
const location = res.headers.get("location");
|
|
27070
|
+
if (res.status < 300 || res.status >= 400 || !location) throw new Error(`\u4E0B\u8F7D ${id} \u5931\u8D25\uFF1AHTTP ${res.status}`);
|
|
27071
|
+
const digest = res.headers.get("x-skill-digest") ?? "";
|
|
27072
|
+
const name = res.headers.get("x-skill-name") ?? id.split("/").pop();
|
|
27073
|
+
if (!digest) throw new Error(`\u4E0B\u8F7D ${id} \u5931\u8D25\uFF1A\u670D\u52A1\u7AEF\u6CA1\u6709\u7ED9\u51FA\u7248\u672C\uFF08x-skill-digest\uFF09`);
|
|
27074
|
+
const body = await download(new URL(location, url).toString(), id);
|
|
27075
|
+
const files = untarGz(body);
|
|
27076
|
+
const got = digestOf(new Map(files.map((f) => [f.path, f.data])));
|
|
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
|
+
return { id, name, digest, files };
|
|
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
|
+
}
|
|
27088
|
+
async function download(url, id) {
|
|
27066
27089
|
for (let attempt = 1; ; attempt++) {
|
|
27067
27090
|
const res = await fetch(url, { signal: AbortSignal.timeout(TIMEOUT_MS) });
|
|
27068
|
-
if (res.status ===
|
|
27069
|
-
|
|
27070
|
-
|
|
27071
|
-
await new Promise((r) => setTimeout(r, wait * 1e3));
|
|
27091
|
+
if (res.status === 202 && attempt < MAX_TRIES) {
|
|
27092
|
+
const body = await res.json().catch(() => ({}));
|
|
27093
|
+
await new Promise((r) => setTimeout(r, Math.min(Math.max(body.retryAfterMs ?? 2e3, 250), 5e3)));
|
|
27072
27094
|
continue;
|
|
27073
27095
|
}
|
|
27074
|
-
if (!res.ok) throw new Error(`\u4E0B\u8F7D ${id} \u5931\u8D25\
|
|
27075
|
-
|
|
27076
|
-
const name = res.headers.get("x-skill-name") ?? id.split("/").pop();
|
|
27077
|
-
const files = untarGz(Buffer.from(await res.arrayBuffer()));
|
|
27078
|
-
const got = digestOf(new Map(files.map((f) => [f.path, f.data])));
|
|
27079
|
-
if (!digest || got !== digest) throw new Error(`\u4E0B\u8F7D\u7684 ${id} \u5185\u5BB9\u6821\u9A8C\u5931\u8D25\uFF08\u671F\u671B ${digest}\uFF0C\u5B9E\u9645 ${got}\uFF09`);
|
|
27080
|
-
return { id, name, digest, files };
|
|
27096
|
+
if (!res.ok) throw new Error(`\u4E0B\u8F7D ${id} \u5931\u8D25\uFF1Aregistry \u8FD4\u56DE HTTP ${res.status}`);
|
|
27097
|
+
return Buffer.from(await res.arrayBuffer());
|
|
27081
27098
|
}
|
|
27082
27099
|
}
|
|
27083
27100
|
function untarGz(gz) {
|
|
@@ -27147,6 +27164,21 @@ function parseId(s) {
|
|
|
27147
27164
|
const m = ID_RE.exec(s);
|
|
27148
27165
|
return m ? { spaceId: m[1], name: m[2] } : null;
|
|
27149
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
|
+
}
|
|
27150
27182
|
function ownId(env, name) {
|
|
27151
27183
|
return `cohub:${env.spaceId}/${name}`;
|
|
27152
27184
|
}
|
|
@@ -27219,6 +27251,7 @@ function shareNotice(id, dir, draft, reported) {
|
|
|
27219
27251
|
// cli/src/skills/add.ts
|
|
27220
27252
|
async function cmdAdd(idOrName, opts) {
|
|
27221
27253
|
const env = detectEnv();
|
|
27254
|
+
idOrName = await resolveRef(env, idOrName);
|
|
27222
27255
|
const parsed = parseId(idOrName);
|
|
27223
27256
|
const name = parsed?.name ?? idOrName;
|
|
27224
27257
|
const target = join3(opts.dir, name);
|
|
@@ -27272,6 +27305,7 @@ import { join as join4 } from "node:path";
|
|
|
27272
27305
|
var FETCH_ROOT = process.env["NETASEARCH_FETCH_ROOT"] ?? join4("/tmp", "neta-skills");
|
|
27273
27306
|
async function cmdUse(idOrName, opts) {
|
|
27274
27307
|
const env = detectEnv();
|
|
27308
|
+
idOrName = await resolveRef(env, idOrName);
|
|
27275
27309
|
const parsed = parseId(idOrName);
|
|
27276
27310
|
const name = parsed?.name ?? idOrName;
|
|
27277
27311
|
const mine = !parsed || parsed.spaceId === env.spaceId;
|
|
@@ -27423,6 +27457,153 @@ metadata:
|
|
|
27423
27457
|
`;
|
|
27424
27458
|
}
|
|
27425
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
|
+
|
|
27426
27607
|
// cli/src/version.ts
|
|
27427
27608
|
import { createRequire } from "node:module";
|
|
27428
27609
|
var OUR_NAMES = /* @__PURE__ */ new Set(["@neta-search/cli", "@neta-art/neta-search-cli"]);
|
|
@@ -27441,16 +27622,25 @@ function cliVersion() {
|
|
|
27441
27622
|
// cli/src/cli.ts
|
|
27442
27623
|
var program2 = new Command();
|
|
27443
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());
|
|
27444
|
-
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");
|
|
27445
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) => {
|
|
27446
27627
|
await run(cmdFind(query, { limit: Number(opts.limit) || 20, json: opts.json }));
|
|
27447
27628
|
});
|
|
27448
|
-
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) => {
|
|
27449
27630
|
await run(cmdAdd(idOrName, opts));
|
|
27450
27631
|
});
|
|
27451
|
-
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) => {
|
|
27452
27633
|
await run(cmdUse(idOrName, opts));
|
|
27453
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
|
+
});
|
|
27454
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) => {
|
|
27455
27645
|
await run(cmdInit(name, opts));
|
|
27456
27646
|
});
|