@hcmai/cli 0.1.0 → 0.2.1
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/dist/index.js +680 -47
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4186,11 +4186,16 @@ import {
|
|
|
4186
4186
|
fromAxiosError as fromAxiosError12,
|
|
4187
4187
|
uploadDocument as uploadDocument2
|
|
4188
4188
|
} from "@hcmai/sdk";
|
|
4189
|
+
var DEFAULT_UPLOAD_CATEGORY = "attachment";
|
|
4189
4190
|
async function uploadCommand(filePath, args) {
|
|
4190
4191
|
try {
|
|
4191
4192
|
const ctx = await getActiveAuthContextFromCli(args);
|
|
4192
4193
|
const client3 = HcmClient14.fromAuthContext(ctx);
|
|
4193
|
-
const meta2 = await uploadDocument2(
|
|
4194
|
+
const meta2 = await uploadDocument2(
|
|
4195
|
+
client3.raw(),
|
|
4196
|
+
filePath,
|
|
4197
|
+
args.category ?? DEFAULT_UPLOAD_CATEGORY
|
|
4198
|
+
);
|
|
4194
4199
|
const fmt = args.output ?? "json";
|
|
4195
4200
|
if (fmt !== "json") {
|
|
4196
4201
|
process.stdout.write(
|
|
@@ -4220,10 +4225,21 @@ init_exit();
|
|
|
4220
4225
|
import { promises as fsp } from "fs";
|
|
4221
4226
|
import os2 from "os";
|
|
4222
4227
|
import path2 from "path";
|
|
4228
|
+
import { createHash } from "crypto";
|
|
4223
4229
|
import {
|
|
4224
4230
|
createHttpClient as createHttpClient2,
|
|
4225
4231
|
fetchSkillCatalog,
|
|
4226
4232
|
fetchSkillMarkdown,
|
|
4233
|
+
fetchSkillReference,
|
|
4234
|
+
resolveChironBase,
|
|
4235
|
+
assertSafeSkillId,
|
|
4236
|
+
assertSafeReferencePath,
|
|
4237
|
+
normalizeReferences,
|
|
4238
|
+
parseSkillRequirements,
|
|
4239
|
+
parseSkillFrontmatter,
|
|
4240
|
+
resolveSkillInstallOrder,
|
|
4241
|
+
resolveAllSkillsInstallOrder,
|
|
4242
|
+
flattenSkills,
|
|
4227
4243
|
matchSkills,
|
|
4228
4244
|
filterByStage,
|
|
4229
4245
|
formatObject as formatObject13,
|
|
@@ -4234,6 +4250,10 @@ import {
|
|
|
4234
4250
|
CliError as CliError14,
|
|
4235
4251
|
CliErrorCode as CliErrorCode13
|
|
4236
4252
|
} from "@hcmai/sdk";
|
|
4253
|
+
var SKILLS_STATE_FILE = ".hcm-skills.json";
|
|
4254
|
+
function sha256(text) {
|
|
4255
|
+
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
4256
|
+
}
|
|
4237
4257
|
async function resolveEndpoint(args) {
|
|
4238
4258
|
if (args.endpoint) return args.endpoint.replace(/\/+$/, "");
|
|
4239
4259
|
const g = await loadGlobalConfig6();
|
|
@@ -4247,13 +4267,45 @@ async function resolveEndpoint(args) {
|
|
|
4247
4267
|
}
|
|
4248
4268
|
return env2.endpoint.replace(/\/+$/, "");
|
|
4249
4269
|
}
|
|
4250
|
-
function
|
|
4251
|
-
|
|
4270
|
+
async function exists(target) {
|
|
4271
|
+
try {
|
|
4272
|
+
await fsp.stat(target);
|
|
4273
|
+
return true;
|
|
4274
|
+
} catch {
|
|
4275
|
+
return false;
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
async function detectTarget(cwd) {
|
|
4279
|
+
if (await exists(path2.join(cwd, ".claude"))) return "claude";
|
|
4280
|
+
if (await exists(path2.join(cwd, "AGENTS.md"))) return "codex";
|
|
4281
|
+
if (await exists(path2.join(cwd, ".codex"))) return "codex";
|
|
4282
|
+
return void 0;
|
|
4283
|
+
}
|
|
4284
|
+
async function resolveInstallLayout(args, cwd = process.cwd()) {
|
|
4285
|
+
const requested = args.target && args.target !== "auto" ? args.target : void 0;
|
|
4286
|
+
const target = requested ?? await detectTarget(cwd) ?? "claude";
|
|
4287
|
+
if (target === "codex") {
|
|
4288
|
+
const root = args.global ? path2.join(os2.homedir(), ".codex") : cwd;
|
|
4289
|
+
return {
|
|
4290
|
+
target,
|
|
4291
|
+
baseDir: args.dir ? path2.resolve(args.dir) : path2.join(root, "hcm-skills"),
|
|
4292
|
+
agentsFile: path2.join(root, "AGENTS.md")
|
|
4293
|
+
};
|
|
4294
|
+
}
|
|
4295
|
+
return {
|
|
4296
|
+
target,
|
|
4297
|
+
baseDir: args.dir ? path2.resolve(args.dir) : args.global ? path2.join(os2.homedir(), ".claude", "skills") : path2.join(cwd, ".claude", "skills")
|
|
4298
|
+
};
|
|
4299
|
+
}
|
|
4300
|
+
async function chironClient(args) {
|
|
4301
|
+
const endpoint = await resolveEndpoint(args);
|
|
4302
|
+
const http = createHttpClient2({
|
|
4252
4303
|
endpoint,
|
|
4253
4304
|
getAccessToken: async () => null,
|
|
4254
4305
|
onRefresh: async () => {
|
|
4255
4306
|
}
|
|
4256
4307
|
});
|
|
4308
|
+
return { http, endpoint, base: await resolveChironBase(http) };
|
|
4257
4309
|
}
|
|
4258
4310
|
function fail3(e, args) {
|
|
4259
4311
|
const err = e;
|
|
@@ -4266,8 +4318,9 @@ function fail3(e, args) {
|
|
|
4266
4318
|
}
|
|
4267
4319
|
async function skillsListCommand(keyword, args) {
|
|
4268
4320
|
try {
|
|
4269
|
-
|
|
4270
|
-
const
|
|
4321
|
+
if (args.installed) return await listInstalledSkills(keyword, args);
|
|
4322
|
+
const { http, endpoint, base } = await chironClient(args);
|
|
4323
|
+
const manifest2 = await fetchSkillCatalog(http, base);
|
|
4271
4324
|
const fmt = args.output ?? "table";
|
|
4272
4325
|
let cats = manifest2.categories ?? [];
|
|
4273
4326
|
if (args.category) cats = cats.filter((c) => c.key === args.category);
|
|
@@ -4335,10 +4388,82 @@ async function skillsListCommand(keyword, args) {
|
|
|
4335
4388
|
fail3(e, args);
|
|
4336
4389
|
}
|
|
4337
4390
|
}
|
|
4391
|
+
async function listInstalledSkills(keyword, args) {
|
|
4392
|
+
const layout = await resolveInstallLayout(args);
|
|
4393
|
+
const state = await readSkillsState(layout.baseDir);
|
|
4394
|
+
const fmt = args.output ?? "table";
|
|
4395
|
+
if (!state || Object.keys(state.skills).length === 0) {
|
|
4396
|
+
if (fmt === "json" || fmt === "yaml") {
|
|
4397
|
+
process.stdout.write(formatObject13({ baseDir: layout.baseDir, target: layout.target, all: false, skills: [] }, { format: fmt }) + "\n");
|
|
4398
|
+
process.exit(0);
|
|
4399
|
+
}
|
|
4400
|
+
process.stdout.write(`${path2.join(layout.baseDir, SKILLS_STATE_FILE)} \u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A \u2014\u2014 \u8FD9\u4E2A\u76EE\u5F55\u4E0B\u8FD8\u6CA1\u7528\u672C CLI \u88C5\u8FC7\u6280\u80FD\u3002
|
|
4401
|
+
`);
|
|
4402
|
+
process.stdout.write(" \u88C5\u5168\u90E8\uFF1Ahcm skills install --all\n");
|
|
4403
|
+
process.exit(0);
|
|
4404
|
+
}
|
|
4405
|
+
const rows = [];
|
|
4406
|
+
for (const [id, record] of Object.entries(state.skills).sort(([a], [b]) => a.localeCompare(b))) {
|
|
4407
|
+
const markdown = await readInstalled(layout.baseDir, id);
|
|
4408
|
+
let title = id;
|
|
4409
|
+
if (markdown !== void 0) {
|
|
4410
|
+
const raw = parseSkillFrontmatter(markdown, id).title;
|
|
4411
|
+
if (typeof raw === "string" && raw.trim()) title = raw.trim();
|
|
4412
|
+
}
|
|
4413
|
+
rows.push({
|
|
4414
|
+
id,
|
|
4415
|
+
title,
|
|
4416
|
+
direct: record.direct,
|
|
4417
|
+
installedAt: record.installedAt,
|
|
4418
|
+
// 三种状态互斥:文件没了 / 本地改过 / 和装的时候一致
|
|
4419
|
+
status: markdown === void 0 ? "missing" : sha256(markdown) !== record.sha256 ? "locally-modified" : "installed"
|
|
4420
|
+
});
|
|
4421
|
+
}
|
|
4422
|
+
const shown = keyword ? rows.filter((row) => row.id.includes(keyword) || row.title.includes(keyword)) : rows;
|
|
4423
|
+
if (fmt === "json" || fmt === "yaml") {
|
|
4424
|
+
process.stdout.write(formatObject13({
|
|
4425
|
+
baseDir: layout.baseDir,
|
|
4426
|
+
target: layout.target,
|
|
4427
|
+
endpoint: state.endpoint,
|
|
4428
|
+
all: Boolean(state.all),
|
|
4429
|
+
updatedAt: state.updatedAt,
|
|
4430
|
+
skills: shown
|
|
4431
|
+
}, { format: fmt }) + "\n");
|
|
4432
|
+
process.exit(0);
|
|
4433
|
+
}
|
|
4434
|
+
process.stdout.write(`\u5DF2\u5B89\u88C5\u7684\u777F\u620E\u6280\u80FD \u2014 ${layout.baseDir}\uFF08${layout.target}\uFF09
|
|
4435
|
+
`);
|
|
4436
|
+
process.stdout.write(`\u6765\u6E90 ${state.endpoint ?? "\uFF08\u672A\u8BB0\u5F55\uFF09"}` + (state.all ? " \u8DDF\u968F\u5168\u96C6\uFF1A\u662F\n\n" : "\n\n"));
|
|
4437
|
+
if (shown.length === 0) {
|
|
4438
|
+
process.stdout.write(` \u6CA1\u6709\u5339\u914D\u300C${keyword}\u300D\u7684\u6280\u80FD\uFF08\u5171\u88C5\u4E86 ${rows.length} \u4E2A\uFF09
|
|
4439
|
+
`);
|
|
4440
|
+
process.exit(0);
|
|
4441
|
+
}
|
|
4442
|
+
for (const row of shown) {
|
|
4443
|
+
const mark = row.status === "missing" ? "?" : row.status === "locally-modified" ? "!" : row.direct ? "\u25CF" : "\u25CB";
|
|
4444
|
+
const note = row.status === "missing" ? "\u6587\u4EF6\u4E0D\u89C1\u4E86\uFF08update \u4F1A\u88C5\u56DE\uFF09" : row.status === "locally-modified" ? "\u672C\u5730\u6539\u8FC7" : row.direct ? "" : "\u4F9D\u8D56\u5E26\u5165";
|
|
4445
|
+
process.stdout.write(` ${mark} ${row.id.padEnd(30)} ${row.title.padEnd(24)} ${note}
|
|
4446
|
+
`);
|
|
4447
|
+
}
|
|
4448
|
+
const modified = shown.filter((row) => row.status === "locally-modified").length;
|
|
4449
|
+
const missing = shown.filter((row) => row.status === "missing").length;
|
|
4450
|
+
const indirect = shown.filter((row) => row.direct === false).length;
|
|
4451
|
+
process.stdout.write("\n");
|
|
4452
|
+
process.stdout.write(` \u25CF \u76F4\u63A5\u5B89\u88C5 \u25CB \u4F9D\u8D56\u5E26\u5165 ! \u672C\u5730\u6539\u8FC7 ? \u6587\u4EF6\u7F3A\u5931
|
|
4453
|
+
`);
|
|
4454
|
+
process.stdout.write(` \u5171 ${shown.length} \u4E2A` + [
|
|
4455
|
+
indirect > 0 ? `${indirect} \u4E2A\u662F\u4F9D\u8D56\u5E26\u5165` : "",
|
|
4456
|
+
modified > 0 ? `${modified} \u4E2A\u672C\u5730\u6539\u8FC7` : "",
|
|
4457
|
+
missing > 0 ? `${missing} \u4E2A\u6587\u4EF6\u7F3A\u5931` : ""
|
|
4458
|
+
].filter(Boolean).map((t) => `\uFF0C${t}`).join("") + "\n");
|
|
4459
|
+
process.stdout.write(` \u5347\u7EA7\uFF1Ahcm skills update${state.all ? "" : "\uFF08\u60F3\u8DDF\u968F\u5168\u96C6\u52A0 --all\uFF09"}
|
|
4460
|
+
`);
|
|
4461
|
+
process.exit(0);
|
|
4462
|
+
}
|
|
4338
4463
|
async function skillsShowCommand(id, args) {
|
|
4339
4464
|
try {
|
|
4340
|
-
const
|
|
4341
|
-
const md = await fetchSkillMarkdown(
|
|
4465
|
+
const { http, base } = await chironClient(args);
|
|
4466
|
+
const md = await fetchSkillMarkdown(http, id, base);
|
|
4342
4467
|
process.stdout.write(md.endsWith("\n") ? md : md + "\n");
|
|
4343
4468
|
process.exit(0);
|
|
4344
4469
|
} catch (e) {
|
|
@@ -4347,52 +4472,555 @@ async function skillsShowCommand(id, args) {
|
|
|
4347
4472
|
}
|
|
4348
4473
|
async function skillsInstallCommand(id, args) {
|
|
4349
4474
|
try {
|
|
4350
|
-
|
|
4475
|
+
const all = Boolean(args.all);
|
|
4476
|
+
if (all && id) throw invalid("`--all` \u662F\u88C5\u6574\u4E2A\u6280\u80FD\u5E93\uFF0C\u4E0D\u8981\u518D\u5E26\u6280\u80FD id\uFF1B\u53EA\u88C5\u4E00\u4E2A\u5C31\u53BB\u6389 --all");
|
|
4477
|
+
if (!all && !id) throw invalid("\u8981\u88C5\u54EA\u4E2A\u6280\u80FD\uFF1F\u7ED9\u4E2A id\uFF08`hcm skills list` \u770B\u76EE\u5F55\uFF09\uFF0C\u6216\u7528 `--all` \u88C5\u5168\u90E8");
|
|
4478
|
+
if (id) assertSafeSkillId(id);
|
|
4479
|
+
const layout = await resolveInstallLayout(args);
|
|
4480
|
+
let documents;
|
|
4481
|
+
let requestedIds;
|
|
4482
|
+
let endpoint;
|
|
4483
|
+
let base;
|
|
4484
|
+
let manifest2;
|
|
4485
|
+
if (args.from) {
|
|
4486
|
+
const root = path2.resolve(args.from);
|
|
4487
|
+
requestedIds = all ? await listLocalSkillIds(root) : [id];
|
|
4488
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4489
|
+
documents = [];
|
|
4490
|
+
for (const one of requestedIds) {
|
|
4491
|
+
for (const document of await resolveLocalSkillDocuments(root, one)) {
|
|
4492
|
+
if (seen.has(document.id)) continue;
|
|
4493
|
+
seen.add(document.id);
|
|
4494
|
+
documents.push(document);
|
|
4495
|
+
}
|
|
4496
|
+
}
|
|
4497
|
+
} else {
|
|
4498
|
+
const client3 = await chironClient(args);
|
|
4499
|
+
endpoint = client3.endpoint;
|
|
4500
|
+
base = client3.base;
|
|
4501
|
+
manifest2 = await fetchSkillCatalog(client3.http, base);
|
|
4502
|
+
const order = all ? resolveAllSkillsInstallOrder(manifest2) : resolveSkillInstallOrder(manifest2, id);
|
|
4503
|
+
if (all && order.length === 0) throw invalid(`${endpoint} \u7684\u6280\u80FD\u76EE\u5F55\u662F\u7A7A\u7684\uFF0C\u6CA1\u6709\u53EF\u88C5\u7684\u6280\u80FD`);
|
|
4504
|
+
requestedIds = all ? order.map((skill) => skill.id) : [id];
|
|
4505
|
+
documents = await mapWithConcurrency(
|
|
4506
|
+
order,
|
|
4507
|
+
FETCH_CONCURRENCY,
|
|
4508
|
+
(skill) => fetchSkillDocument(client3.http, skill, endpoint, base)
|
|
4509
|
+
);
|
|
4510
|
+
}
|
|
4511
|
+
const result = await installSkillDocuments(documents, requestedIds, layout.baseDir, Boolean(args.force), {
|
|
4512
|
+
endpoint,
|
|
4513
|
+
base,
|
|
4514
|
+
target: layout.target,
|
|
4515
|
+
all
|
|
4516
|
+
});
|
|
4517
|
+
const agents = layout.agentsFile ? await syncAgentsIndex(layout, manifest2) : void 0;
|
|
4518
|
+
const fmt = args.output ?? "table";
|
|
4519
|
+
if (fmt === "json" || fmt === "yaml") {
|
|
4520
|
+
process.stdout.write(formatObject13({ ...result, all, target_agent: layout.target, agentsFile: layout.agentsFile, agents }, { format: fmt }) + "\n");
|
|
4521
|
+
} else {
|
|
4522
|
+
const headline = all ? `\u2705 \u5168\u90E8 ${requestedIds.length} \u4E2A\u6280\u80FD \u2192 ${result.baseDir}` : `\u2705 ${id} \u2192 ${path2.join(result.baseDir, id, "SKILL.md")}`;
|
|
4523
|
+
process.stdout.write(`${headline}
|
|
4524
|
+
`);
|
|
4525
|
+
if (result.installed.length > 0) {
|
|
4526
|
+
process.stdout.write(all ? ` \u65B0\u5199\u5165 ${result.installed.length} \u4E2A
|
|
4527
|
+
` : ` \u5DF2\u5B89\u88C5 ${result.installed.join(" \u2192 ")}
|
|
4528
|
+
`);
|
|
4529
|
+
}
|
|
4530
|
+
if (result.unchanged.length > 0) {
|
|
4531
|
+
process.stdout.write(all ? ` \u5DF2\u662F\u8FD9\u4E00\u7248\u3001\u672A\u6539\u52A8 ${result.unchanged.length} \u4E2A
|
|
4532
|
+
` : ` \u5DF2\u5B58\u5728\u4E14\u7248\u672C\u4E00\u81F4 ${result.unchanged.join(", ")}
|
|
4533
|
+
`);
|
|
4534
|
+
}
|
|
4535
|
+
const referenceCount = documents.reduce((n, d) => n + (d.references?.length ?? 0), 0);
|
|
4536
|
+
if (referenceCount > 0) {
|
|
4537
|
+
process.stdout.write(` \u53C2\u8003\u6587\u4EF6 ${referenceCount} \u4E2A\uFF08references/ \u4E0B\uFF09
|
|
4538
|
+
`);
|
|
4539
|
+
}
|
|
4540
|
+
if (layout.agentsFile) {
|
|
4541
|
+
process.stdout.write(` \u5DF2${agents === "created" ? "\u521B\u5EFA" : "\u66F4\u65B0"} ${layout.agentsFile} \u91CC\u7684\u6280\u80FD\u7D22\u5F15\uFF08Codex \u8BFB\u8FD9\u91CC\uFF09
|
|
4542
|
+
`);
|
|
4543
|
+
}
|
|
4544
|
+
process.stdout.write(` \u6765\u6E90 ${endpoint ?? path2.resolve(args.from)}
|
|
4545
|
+
`);
|
|
4546
|
+
process.stdout.write(all ? " \u5DF2\u8BB0\u4E3A\u300C\u8DDF\u968F\u5168\u96C6\u300D\uFF1A\u4EE5\u540E\u8DD1 hcm skills update\uFF0C\u4EA7\u54C1\u65B0\u589E\u7684\u6280\u80FD\u4F1A\u81EA\u52A8\u8865\u4E0A\n" : " \u4EA7\u54C1\u66F4\u65B0\u540E\u8DD1 hcm skills update \u5347\u7EA7\n");
|
|
4547
|
+
}
|
|
4548
|
+
process.exit(0);
|
|
4549
|
+
} catch (e) {
|
|
4550
|
+
fail3(e, args);
|
|
4551
|
+
}
|
|
4552
|
+
}
|
|
4553
|
+
var FETCH_CONCURRENCY = 6;
|
|
4554
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
4555
|
+
const results = new Array(items.length);
|
|
4556
|
+
let cursor = 0;
|
|
4557
|
+
const worker = async () => {
|
|
4558
|
+
for (; ; ) {
|
|
4559
|
+
const index = cursor++;
|
|
4560
|
+
if (index >= items.length) return;
|
|
4561
|
+
results[index] = await fn(items[index]);
|
|
4562
|
+
}
|
|
4563
|
+
};
|
|
4564
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));
|
|
4565
|
+
return results;
|
|
4566
|
+
}
|
|
4567
|
+
async function listLocalSkillIds(root) {
|
|
4568
|
+
let entries;
|
|
4569
|
+
try {
|
|
4570
|
+
entries = await fsp.readdir(root, { withFileTypes: true });
|
|
4571
|
+
} catch {
|
|
4572
|
+
throw invalid(`\u8BFB\u4E0D\u5230\u672C\u5730\u6280\u80FD\u76EE\u5F55\uFF1A${root}`);
|
|
4573
|
+
}
|
|
4574
|
+
const ids = [];
|
|
4575
|
+
for (const entry of entries) {
|
|
4576
|
+
if (!entry.isDirectory()) continue;
|
|
4577
|
+
if (await exists(path2.join(root, entry.name, "SKILL.md"))) ids.push(entry.name);
|
|
4578
|
+
}
|
|
4579
|
+
if (ids.length === 0) throw invalid(`\u672C\u5730\u76EE\u5F55\u91CC\u6CA1\u6709\u4EFB\u4F55 <id>/SKILL.md\uFF1A${root}`);
|
|
4580
|
+
return ids.sort();
|
|
4581
|
+
}
|
|
4582
|
+
async function fetchSkillDocument(http, skill, endpoint, base) {
|
|
4583
|
+
const relatives = normalizeReferences(skill.references, skill.id);
|
|
4584
|
+
const references = await Promise.all(relatives.map(async (relative2) => ({
|
|
4585
|
+
path: relative2,
|
|
4586
|
+
content: await fetchSkillReference(http, skill.id, relative2, base)
|
|
4587
|
+
})));
|
|
4588
|
+
return {
|
|
4589
|
+
id: skill.id,
|
|
4590
|
+
markdown: await fetchSkillMarkdown(http, skill.id, base),
|
|
4591
|
+
source: `${endpoint}${base}/skills/${skill.id}.md`,
|
|
4592
|
+
references
|
|
4593
|
+
};
|
|
4594
|
+
}
|
|
4595
|
+
async function syncAgentsIndex(layout, manifest2) {
|
|
4596
|
+
if (!layout.agentsFile) return void 0;
|
|
4597
|
+
const state = await readSkillsState(layout.baseDir);
|
|
4598
|
+
if (!state) return void 0;
|
|
4599
|
+
const catalog = /* @__PURE__ */ new Map();
|
|
4600
|
+
for (const category of manifest2?.categories ?? []) {
|
|
4601
|
+
for (const skill of category.skills ?? []) catalog.set(skill.id, skill);
|
|
4602
|
+
}
|
|
4603
|
+
const agentsDir = path2.dirname(layout.agentsFile);
|
|
4604
|
+
const entries = Object.keys(state.skills).sort().map((id) => {
|
|
4605
|
+
const known = catalog.get(id);
|
|
4606
|
+
const absolute = path2.join(layout.baseDir, id, "SKILL.md");
|
|
4607
|
+
let relative2 = path2.relative(agentsDir, absolute);
|
|
4608
|
+
if (!relative2.startsWith(".")) relative2 = `./${relative2}`;
|
|
4609
|
+
return {
|
|
4610
|
+
id,
|
|
4611
|
+
title: known?.title ?? id,
|
|
4612
|
+
description: known?.description ?? "",
|
|
4613
|
+
relativePath: relative2.split(path2.sep).join("/")
|
|
4614
|
+
};
|
|
4615
|
+
});
|
|
4616
|
+
return upsertAgentsBlock(layout.agentsFile, renderAgentsBlock(entries));
|
|
4617
|
+
}
|
|
4618
|
+
async function resolveLocalSkillDocuments(sourceRoot, targetId) {
|
|
4619
|
+
assertSafeSkillId(targetId);
|
|
4620
|
+
const state = /* @__PURE__ */ new Map();
|
|
4621
|
+
const pathStack = [];
|
|
4622
|
+
const order = [];
|
|
4623
|
+
const visit = async (id, requiredBy) => {
|
|
4624
|
+
const current = state.get(id);
|
|
4625
|
+
if (current === "done") return;
|
|
4626
|
+
if (current === "visiting") {
|
|
4627
|
+
const start = pathStack.indexOf(id);
|
|
4628
|
+
throw invalid(`\u6280\u80FD\u4F9D\u8D56\u5B58\u5728\u73AF: ${[...pathStack.slice(Math.max(0, start)), id].join(" -> ")}`);
|
|
4629
|
+
}
|
|
4630
|
+
assertSafeSkillId(id);
|
|
4631
|
+
const local = path2.join(sourceRoot, id, "SKILL.md");
|
|
4632
|
+
let markdown;
|
|
4633
|
+
try {
|
|
4634
|
+
markdown = await fsp.readFile(local, "utf8");
|
|
4635
|
+
} catch (cause) {
|
|
4636
|
+
if (cause?.code === "ENOENT") {
|
|
4637
|
+
throw invalid(requiredBy ? `\u672C\u5730\u6280\u80FD ${requiredBy} \u4F9D\u8D56\u4E0D\u5B58\u5728: ${id}\uFF08${local}\uFF09` : `\u672C\u5730\u76EE\u5F55\u91CC\u6CA1\u6709 ${id}/SKILL.md\uFF1A${path2.join(sourceRoot, id)}`);
|
|
4638
|
+
}
|
|
4639
|
+
throw cause;
|
|
4640
|
+
}
|
|
4641
|
+
if (!markdown.trim()) throw invalid(`\u6280\u80FD ${id} \u5185\u5BB9\u4E3A\u7A7A`);
|
|
4642
|
+
state.set(id, "visiting");
|
|
4643
|
+
pathStack.push(id);
|
|
4644
|
+
const document = {
|
|
4645
|
+
id,
|
|
4646
|
+
markdown,
|
|
4647
|
+
source: local,
|
|
4648
|
+
references: await readLocalReferences(path2.join(sourceRoot, id))
|
|
4649
|
+
};
|
|
4650
|
+
for (const required of parseSkillRequirements(markdown, id)) {
|
|
4651
|
+
await visit(required, id);
|
|
4652
|
+
}
|
|
4653
|
+
pathStack.pop();
|
|
4654
|
+
state.set(id, "done");
|
|
4655
|
+
order.push(document);
|
|
4656
|
+
};
|
|
4657
|
+
await visit(targetId);
|
|
4658
|
+
return order;
|
|
4659
|
+
}
|
|
4660
|
+
async function readSkillsState(baseDir) {
|
|
4661
|
+
try {
|
|
4662
|
+
const raw = await fsp.readFile(path2.join(baseDir, SKILLS_STATE_FILE), "utf8");
|
|
4663
|
+
const parsed = JSON.parse(raw);
|
|
4664
|
+
if (!parsed || typeof parsed !== "object" || !parsed.skills) return void 0;
|
|
4665
|
+
return parsed;
|
|
4666
|
+
} catch {
|
|
4667
|
+
return void 0;
|
|
4668
|
+
}
|
|
4669
|
+
}
|
|
4670
|
+
async function writeSkillsState(baseDir, state) {
|
|
4671
|
+
await fsp.mkdir(baseDir, { recursive: true });
|
|
4672
|
+
const file = path2.join(baseDir, SKILLS_STATE_FILE);
|
|
4673
|
+
const temp = `${file}.${process.pid}.tmp`;
|
|
4674
|
+
await fsp.writeFile(temp, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
4675
|
+
await fsp.rename(temp, file);
|
|
4676
|
+
}
|
|
4677
|
+
var AGENTS_BLOCK_BEGIN = "<!-- hcm-skills:begin -->";
|
|
4678
|
+
var AGENTS_BLOCK_END = "<!-- hcm-skills:end -->";
|
|
4679
|
+
function renderAgentsBlock(entries) {
|
|
4680
|
+
const lines = [
|
|
4681
|
+
AGENTS_BLOCK_BEGIN,
|
|
4682
|
+
"## HCMnext \u4EA4\u4ED8\u6280\u80FD\uFF08\u7531 `hcm skills install` \u7EF4\u62A4\uFF0C\u52FF\u624B\u5DE5\u7F16\u8F91\u672C\u5757\uFF09",
|
|
4683
|
+
"",
|
|
4684
|
+
"\u9047\u5230\u4E0B\u9762\u8FD9\u4E9B\u6D3B\u513F\uFF0C**\u5148\u8BFB\u5BF9\u5E94\u6587\u4EF6\u518D\u52A8\u624B**\u2014\u2014\u91CC\u9762\u662F\u8FD9\u5957\u4EA7\u54C1\u7684\u6B63\u786E\u505A\u6CD5\uFF0C",
|
|
4685
|
+
"\u7167\u7740\u505A\u4E0D\u7528\u7FFB\u6E90\u7801\uFF0C\u4E5F\u4E0D\u7528\u731C API\u3002",
|
|
4686
|
+
""
|
|
4687
|
+
];
|
|
4688
|
+
for (const e of entries) {
|
|
4689
|
+
lines.push(`- \`${e.relativePath}\` \u2014 **${e.title}**`);
|
|
4690
|
+
if (e.description) lines.push(` ${e.description}`);
|
|
4691
|
+
}
|
|
4692
|
+
lines.push("", AGENTS_BLOCK_END);
|
|
4693
|
+
return lines.join("\n");
|
|
4694
|
+
}
|
|
4695
|
+
async function upsertAgentsBlock(agentsFile, block) {
|
|
4696
|
+
let existing = "";
|
|
4697
|
+
try {
|
|
4698
|
+
existing = await fsp.readFile(agentsFile, "utf8");
|
|
4699
|
+
} catch (cause) {
|
|
4700
|
+
if (cause?.code !== "ENOENT") throw cause;
|
|
4701
|
+
await fsp.mkdir(path2.dirname(agentsFile), { recursive: true });
|
|
4702
|
+
await fsp.writeFile(agentsFile, block + "\n", "utf8");
|
|
4703
|
+
return "created";
|
|
4704
|
+
}
|
|
4705
|
+
const begin = existing.indexOf(AGENTS_BLOCK_BEGIN);
|
|
4706
|
+
const end = existing.indexOf(AGENTS_BLOCK_END);
|
|
4707
|
+
if (begin >= 0 && end > begin) {
|
|
4708
|
+
const next = existing.slice(0, begin) + block + existing.slice(end + AGENTS_BLOCK_END.length);
|
|
4709
|
+
await fsp.writeFile(agentsFile, next, "utf8");
|
|
4710
|
+
return "replaced";
|
|
4711
|
+
}
|
|
4712
|
+
const separator = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
4713
|
+
await fsp.writeFile(agentsFile, existing + separator + block + "\n", "utf8");
|
|
4714
|
+
return "appended";
|
|
4715
|
+
}
|
|
4716
|
+
async function installSkillDocuments(documents, requestedIds, baseDir, force, meta2) {
|
|
4717
|
+
if (requestedIds.length === 0) throw invalid("\u6CA1\u6709\u6307\u5B9A\u8981\u88C5\u7684\u6280\u80FD");
|
|
4718
|
+
for (const id of requestedIds) assertSafeSkillId(id);
|
|
4719
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4720
|
+
const candidates = documents.map((document) => {
|
|
4721
|
+
assertSafeSkillId(document.id);
|
|
4722
|
+
if (seen.has(document.id)) throw invalid(`\u5B89\u88C5\u95ED\u5305\u5305\u542B\u91CD\u590D\u6280\u80FD: ${document.id}`);
|
|
4723
|
+
seen.add(document.id);
|
|
4724
|
+
if (!document.markdown.trim()) throw invalid(`\u6280\u80FD ${document.id} \u5185\u5BB9\u4E3A\u7A7A`);
|
|
4725
|
+
return {
|
|
4726
|
+
...document,
|
|
4727
|
+
target: path2.join(baseDir, document.id, "SKILL.md"),
|
|
4728
|
+
bytes: Buffer.byteLength(document.markdown)
|
|
4729
|
+
};
|
|
4730
|
+
});
|
|
4731
|
+
for (const id of requestedIds) {
|
|
4732
|
+
if (!seen.has(id)) throw invalid(`\u5B89\u88C5\u95ED\u5305\u4E0D\u5305\u542B\u76EE\u6807\u6280\u80FD: ${id}`);
|
|
4733
|
+
}
|
|
4734
|
+
const unchanged = /* @__PURE__ */ new Set();
|
|
4735
|
+
for (const candidate of candidates) {
|
|
4736
|
+
if (force) continue;
|
|
4737
|
+
const same = await sameOnDisk(baseDir, candidate);
|
|
4738
|
+
if (same === void 0) continue;
|
|
4739
|
+
if (same) {
|
|
4740
|
+
unchanged.add(candidate.id);
|
|
4741
|
+
continue;
|
|
4742
|
+
}
|
|
4743
|
+
throw invalid(
|
|
4744
|
+
`${candidate.target} \u5DF2\u5B58\u5728\uFF0C\u4E14\u548C\u76EE\u6807\u73AF\u5883\u8FD9\u4E00\u7248\u4E0D\u4E00\u81F4\u3002\u7528 --force \u8986\u76D6\uFF08\u4F1A\u4E22\u6389\u672C\u5730\u6539\u52A8\uFF09\uFF0C\u6216 --dir <path> \u88C5\u5230\u522B\u5904\uFF1B\u53EA\u60F3\u8DDF\u4E0A\u4EA7\u54C1\u7248\u672C\u7528 hcm skills update`
|
|
4745
|
+
);
|
|
4746
|
+
}
|
|
4747
|
+
const pending = candidates.filter((candidate) => !unchanged.has(candidate.id));
|
|
4748
|
+
await writeSkillDocuments(pending, baseDir);
|
|
4749
|
+
await recordInstalled(baseDir, candidates, {
|
|
4750
|
+
...meta2,
|
|
4751
|
+
directIds: new Set(requestedIds),
|
|
4752
|
+
keepInstalledAt: unchanged
|
|
4753
|
+
});
|
|
4754
|
+
return {
|
|
4755
|
+
ids: [...requestedIds],
|
|
4756
|
+
baseDir,
|
|
4757
|
+
installed: pending.map((candidate) => candidate.id),
|
|
4758
|
+
unchanged: candidates.filter((candidate) => unchanged.has(candidate.id)).map((candidate) => candidate.id),
|
|
4759
|
+
files: candidates.map((candidate) => ({
|
|
4760
|
+
id: candidate.id,
|
|
4761
|
+
target: candidate.target,
|
|
4762
|
+
source: candidate.source,
|
|
4763
|
+
bytes: candidate.bytes,
|
|
4764
|
+
status: unchanged.has(candidate.id) ? "unchanged" : "installed"
|
|
4765
|
+
}))
|
|
4766
|
+
};
|
|
4767
|
+
}
|
|
4768
|
+
async function sameOnDisk(baseDir, candidate) {
|
|
4769
|
+
const existing = await readInstalled(baseDir, candidate.id);
|
|
4770
|
+
if (existing === void 0) return void 0;
|
|
4771
|
+
if (existing !== candidate.markdown) return false;
|
|
4772
|
+
for (const reference of candidate.references ?? []) {
|
|
4773
|
+
if (await readInstalledReference(baseDir, candidate.id, reference.path) !== reference.content) return false;
|
|
4774
|
+
}
|
|
4775
|
+
return true;
|
|
4776
|
+
}
|
|
4777
|
+
async function readLocalReferences(skillDir) {
|
|
4778
|
+
const root = path2.join(skillDir, "references");
|
|
4779
|
+
const out = [];
|
|
4780
|
+
const walk = async (dir, prefix) => {
|
|
4781
|
+
let items;
|
|
4782
|
+
try {
|
|
4783
|
+
items = await fsp.readdir(dir, { withFileTypes: true });
|
|
4784
|
+
} catch (cause) {
|
|
4785
|
+
if (cause?.code === "ENOENT") return;
|
|
4786
|
+
throw cause;
|
|
4787
|
+
}
|
|
4788
|
+
for (const item of items.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
4789
|
+
const relative2 = prefix ? `${prefix}/${item.name}` : item.name;
|
|
4790
|
+
if (item.isDirectory()) {
|
|
4791
|
+
await walk(path2.join(dir, item.name), relative2);
|
|
4792
|
+
continue;
|
|
4793
|
+
}
|
|
4794
|
+
if (!item.isFile()) continue;
|
|
4795
|
+
assertSafeReferencePath(relative2);
|
|
4796
|
+
out.push({ path: relative2, content: await fsp.readFile(path2.join(dir, item.name), "utf8") });
|
|
4797
|
+
}
|
|
4798
|
+
};
|
|
4799
|
+
await walk(root, "");
|
|
4800
|
+
return out;
|
|
4801
|
+
}
|
|
4802
|
+
async function writeSkillDocuments(documents, baseDir) {
|
|
4803
|
+
const staged = [];
|
|
4804
|
+
try {
|
|
4805
|
+
for (const document of documents) {
|
|
4806
|
+
const target = path2.join(baseDir, document.id, "SKILL.md");
|
|
4807
|
+
await fsp.mkdir(path2.dirname(target), { recursive: true });
|
|
4808
|
+
const temp = path2.join(path2.dirname(target), `.SKILL.md.${process.pid}.${Date.now()}.tmp`);
|
|
4809
|
+
await fsp.writeFile(temp, document.markdown, "utf8");
|
|
4810
|
+
staged.push({ temp, target });
|
|
4811
|
+
for (const reference of document.references ?? []) {
|
|
4812
|
+
assertSafeReferencePath(reference.path);
|
|
4813
|
+
const referenceTarget = path2.join(baseDir, document.id, "references", reference.path);
|
|
4814
|
+
await fsp.mkdir(path2.dirname(referenceTarget), { recursive: true });
|
|
4815
|
+
const referenceTemp = `${referenceTarget}.${process.pid}.${Date.now()}.tmp`;
|
|
4816
|
+
await fsp.writeFile(referenceTemp, reference.content, "utf8");
|
|
4817
|
+
staged.push({ temp: referenceTemp, target: referenceTarget });
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
for (const file of staged) await fsp.rename(file.temp, file.target);
|
|
4821
|
+
} catch (cause) {
|
|
4822
|
+
await Promise.all(staged.map((file) => fsp.unlink(file.temp).catch(() => void 0)));
|
|
4823
|
+
throw cause;
|
|
4824
|
+
}
|
|
4825
|
+
}
|
|
4826
|
+
async function recordInstalled(baseDir, documents, meta2) {
|
|
4827
|
+
const state = await readSkillsState(baseDir) ?? {
|
|
4828
|
+
version: 1,
|
|
4829
|
+
target: meta2.target ?? "claude",
|
|
4830
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4831
|
+
skills: {}
|
|
4832
|
+
};
|
|
4833
|
+
state.version = 1;
|
|
4834
|
+
if (meta2.target) state.target = meta2.target;
|
|
4835
|
+
if (meta2.endpoint) state.endpoint = meta2.endpoint;
|
|
4836
|
+
if (meta2.base !== void 0) state.base = meta2.base;
|
|
4837
|
+
if (meta2.all) state.all = true;
|
|
4838
|
+
state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4839
|
+
for (const document of documents) {
|
|
4840
|
+
const previous = state.skills[document.id];
|
|
4841
|
+
state.skills[document.id] = {
|
|
4842
|
+
source: document.source,
|
|
4843
|
+
sha256: sha256(document.markdown),
|
|
4844
|
+
installedAt: meta2.keepInstalledAt?.has(document.id) && previous ? previous.installedAt : state.updatedAt,
|
|
4845
|
+
// 已经是直接安装的,不因为这次作为依赖被带进来就降级
|
|
4846
|
+
direct: meta2.directIds.has(document.id) || Boolean(previous?.direct),
|
|
4847
|
+
references: Object.fromEntries(
|
|
4848
|
+
(document.references ?? []).map((reference) => [reference.path, sha256(reference.content)])
|
|
4849
|
+
)
|
|
4850
|
+
};
|
|
4851
|
+
}
|
|
4852
|
+
await writeSkillsState(baseDir, state);
|
|
4853
|
+
return state;
|
|
4854
|
+
}
|
|
4855
|
+
function invalid(message) {
|
|
4856
|
+
return new CliError14({ code: CliErrorCode13.INVALID_ARGUMENT, message });
|
|
4857
|
+
}
|
|
4858
|
+
async function readInstalled(baseDir, id) {
|
|
4859
|
+
try {
|
|
4860
|
+
return await fsp.readFile(path2.join(baseDir, id, "SKILL.md"), "utf8");
|
|
4861
|
+
} catch (cause) {
|
|
4862
|
+
if (cause?.code === "ENOENT") return void 0;
|
|
4863
|
+
throw cause;
|
|
4864
|
+
}
|
|
4865
|
+
}
|
|
4866
|
+
async function readInstalledReference(baseDir, id, relative2) {
|
|
4867
|
+
try {
|
|
4868
|
+
return await fsp.readFile(path2.join(baseDir, id, "references", relative2), "utf8");
|
|
4869
|
+
} catch (cause) {
|
|
4870
|
+
if (cause?.code === "ENOENT") return void 0;
|
|
4871
|
+
throw cause;
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4874
|
+
async function planSkillUpdate(options) {
|
|
4875
|
+
const { state, manifest: manifest2, baseDir, force, fetchDocument } = options;
|
|
4876
|
+
const all = options.all ?? Boolean(state.all);
|
|
4877
|
+
const recorded = Object.entries(state.skills);
|
|
4878
|
+
const directIds = recorded.some(([, r]) => r.direct) ? recorded.filter(([, r]) => r.direct).map(([id]) => id) : recorded.map(([id]) => id);
|
|
4879
|
+
const wanted = all ? [.../* @__PURE__ */ new Set([...directIds, ...flattenSkills(manifest2).map((skill) => skill.id)])] : directIds;
|
|
4880
|
+
const entries = [];
|
|
4881
|
+
const closure = /* @__PURE__ */ new Map();
|
|
4882
|
+
for (const id of wanted.sort()) {
|
|
4883
|
+
try {
|
|
4884
|
+
for (const skill of resolveSkillInstallOrder(manifest2, id)) {
|
|
4885
|
+
if (!closure.has(skill.id)) closure.set(skill.id, skill);
|
|
4886
|
+
}
|
|
4887
|
+
} catch {
|
|
4888
|
+
entries.push({
|
|
4889
|
+
id,
|
|
4890
|
+
status: "removed-upstream",
|
|
4891
|
+
note: "\u4EA7\u54C1\u8FD9\u4E00\u7248\u7684\u6280\u80FD\u76EE\u5F55\u91CC\u5DF2\u7ECF\u6CA1\u6709\u5B83\u4E86\uFF1B\u672C\u5730\u6587\u4EF6\u4FDD\u7559\u4E0D\u52A8"
|
|
4892
|
+
});
|
|
4893
|
+
}
|
|
4894
|
+
}
|
|
4895
|
+
const documents = [];
|
|
4896
|
+
for (const skill of closure.values()) {
|
|
4897
|
+
const record = state.skills[skill.id];
|
|
4898
|
+
const onDisk = await readInstalled(baseDir, skill.id);
|
|
4899
|
+
if (onDisk === void 0) {
|
|
4900
|
+
documents.push(await fetchDocument(skill));
|
|
4901
|
+
entries.push({
|
|
4902
|
+
id: skill.id,
|
|
4903
|
+
status: "added",
|
|
4904
|
+
note: record ? "\u672C\u5730\u6587\u4EF6\u7F3A\u5931\uFF0C\u91CD\u65B0\u88C5\u56DE" : all ? "\u4EA7\u54C1\u8FD9\u4E00\u7248\u65B0\u589E\u7684\u6280\u80FD" : "\u4EA7\u54C1\u65B0\u589E\u7684\u524D\u7F6E\u6280\u80FD"
|
|
4905
|
+
});
|
|
4906
|
+
continue;
|
|
4907
|
+
}
|
|
4908
|
+
const remote = await fetchDocument(skill);
|
|
4909
|
+
const remoteReferences = remote.references ?? [];
|
|
4910
|
+
let differsFromRemote = remote.markdown !== onDisk;
|
|
4911
|
+
let editedLocally = record !== void 0 && sha256(onDisk) !== record.sha256;
|
|
4912
|
+
for (const reference of remoteReferences) {
|
|
4913
|
+
const installed = await readInstalledReference(baseDir, skill.id, reference.path);
|
|
4914
|
+
if (installed !== reference.content) differsFromRemote = true;
|
|
4915
|
+
const recordedSha = record?.references?.[reference.path];
|
|
4916
|
+
if (installed !== void 0 && recordedSha && sha256(installed) !== recordedSha) editedLocally = true;
|
|
4917
|
+
}
|
|
4918
|
+
if (!differsFromRemote) {
|
|
4919
|
+
entries.push({ id: skill.id, status: "unchanged" });
|
|
4920
|
+
continue;
|
|
4921
|
+
}
|
|
4922
|
+
if (editedLocally && !force) {
|
|
4923
|
+
entries.push({
|
|
4924
|
+
id: skill.id,
|
|
4925
|
+
status: "locally-modified",
|
|
4926
|
+
note: "\u672C\u5730\u6539\u8FC7\uFF0C\u6CA1\u6709\u8986\u76D6\uFF1B\u786E\u5B9A\u8981\u7528\u4EA7\u54C1\u8FD9\u4E00\u7248\u5C31\u52A0 --force"
|
|
4927
|
+
});
|
|
4928
|
+
continue;
|
|
4929
|
+
}
|
|
4930
|
+
documents.push(remote);
|
|
4931
|
+
entries.push({
|
|
4932
|
+
id: skill.id,
|
|
4933
|
+
status: "updated",
|
|
4934
|
+
note: editedLocally ? "\u672C\u5730\u6539\u8FC7\uFF0C--force \u5DF2\u8986\u76D6" : void 0
|
|
4935
|
+
});
|
|
4936
|
+
}
|
|
4937
|
+
entries.sort((a, b) => a.id.localeCompare(b.id));
|
|
4938
|
+
return { entries, documents };
|
|
4939
|
+
}
|
|
4940
|
+
var UPDATE_STATUS_LABEL = {
|
|
4941
|
+
updated: "\u5DF2\u66F4\u65B0",
|
|
4942
|
+
added: "\u5DF2\u8865\u88C5",
|
|
4943
|
+
unchanged: "\u5DF2\u662F\u6700\u65B0",
|
|
4944
|
+
"locally-modified": "\u672C\u5730\u6539\u8FC7\xB7\u8DF3\u8FC7",
|
|
4945
|
+
"removed-upstream": "\u4EA7\u54C1\u5DF2\u79FB\u9664"
|
|
4946
|
+
};
|
|
4947
|
+
async function skillsUpdateCommand(args) {
|
|
4948
|
+
try {
|
|
4949
|
+
const layout = await resolveInstallLayout(args);
|
|
4950
|
+
const state = await readSkillsState(layout.baseDir);
|
|
4951
|
+
if (!state || Object.keys(state.skills).length === 0) {
|
|
4351
4952
|
throw new CliError14({
|
|
4352
4953
|
code: CliErrorCode13.INVALID_ARGUMENT,
|
|
4353
|
-
message:
|
|
4954
|
+
message: `${path2.join(layout.baseDir, SKILLS_STATE_FILE)} \u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A \u2014\u2014 \u8FD9\u4E2A\u76EE\u5F55\u4E0B\u8FD8\u6CA1\u6709\u7528\u672C CLI \u88C5\u8FC7\u6280\u80FD\u3002\u5148 \`hcm skills install <id>\`\uFF1B\u5982\u679C\u6280\u80FD\u662F\u624B\u5DE5\u62F7\u8FDB\u6765\u7684\uFF0C\u91CD\u88C5\u4E00\u6B21\u5373\u53EF\u63A5\u7BA1\u5347\u7EA7\u3002`
|
|
4354
4955
|
});
|
|
4355
4956
|
}
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
const
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4957
|
+
const endpoint = args.endpoint ? args.endpoint.replace(/\/+$/, "") : await resolveEndpoint(args).catch((e) => {
|
|
4958
|
+
if (state.endpoint) return state.endpoint;
|
|
4959
|
+
throw e;
|
|
4960
|
+
});
|
|
4961
|
+
const { http, base } = await chironClient({ ...args, endpoint });
|
|
4962
|
+
const manifest2 = await fetchSkillCatalog(http, base);
|
|
4963
|
+
const all = Boolean(args.all) || Boolean(state.all);
|
|
4964
|
+
const plan = await planSkillUpdate({
|
|
4965
|
+
state,
|
|
4966
|
+
manifest: manifest2,
|
|
4967
|
+
baseDir: layout.baseDir,
|
|
4968
|
+
force: Boolean(args.force),
|
|
4969
|
+
all,
|
|
4970
|
+
fetchDocument: (skill) => fetchSkillDocument(http, skill, endpoint, base)
|
|
4971
|
+
});
|
|
4972
|
+
const subscriptionChanged = all && !state.all;
|
|
4973
|
+
if (!args.check && (plan.documents.length > 0 || subscriptionChanged)) {
|
|
4974
|
+
await writeSkillDocuments(plan.documents, layout.baseDir);
|
|
4975
|
+
await recordInstalled(layout.baseDir, plan.documents, {
|
|
4976
|
+
endpoint,
|
|
4977
|
+
base,
|
|
4978
|
+
target: layout.target,
|
|
4979
|
+
all,
|
|
4980
|
+
directIds: all ? new Set(plan.documents.map((document) => document.id)) : /* @__PURE__ */ new Set()
|
|
4981
|
+
});
|
|
4982
|
+
if (layout.agentsFile) await syncAgentsIndex(layout, manifest2);
|
|
4378
4983
|
}
|
|
4379
|
-
|
|
4380
|
-
await fsp.writeFile(target, md, "utf8");
|
|
4984
|
+
const changed = plan.entries.filter((e) => e.status === "updated" || e.status === "added");
|
|
4381
4985
|
const fmt = args.output ?? "table";
|
|
4382
4986
|
if (fmt === "json" || fmt === "yaml") {
|
|
4383
|
-
process.stdout.write(
|
|
4384
|
-
|
|
4385
|
-
|
|
4987
|
+
process.stdout.write(formatObject13({
|
|
4988
|
+
endpoint,
|
|
4989
|
+
baseDir: layout.baseDir,
|
|
4990
|
+
target: layout.target,
|
|
4991
|
+
dryRun: Boolean(args.check),
|
|
4992
|
+
all,
|
|
4993
|
+
changed: changed.length,
|
|
4994
|
+
entries: plan.entries
|
|
4995
|
+
}, { format: fmt }) + "\n");
|
|
4996
|
+
process.exit(0);
|
|
4997
|
+
}
|
|
4998
|
+
process.stdout.write(`\u777F\u620E\u6280\u80FD\u5347\u7EA7 \u2014 ${endpoint}
|
|
4999
|
+
`);
|
|
5000
|
+
process.stdout.write(`\u843D\u70B9 ${layout.baseDir}\uFF08${layout.target}\uFF09` + (all ? " \u8DDF\u968F\u5168\u96C6\uFF1A\u4EA7\u54C1\u65B0\u589E\u7684\u6280\u80FD\u4F1A\u81EA\u52A8\u8865\u4E0A\n\n" : "\n\n"));
|
|
5001
|
+
for (const entry of plan.entries) {
|
|
5002
|
+
const mark = entry.status === "unchanged" ? " " : entry.status === "locally-modified" ? "!" : "\xB7";
|
|
5003
|
+
process.stdout.write(` ${mark} ${entry.id.padEnd(30)} ${UPDATE_STATUS_LABEL[entry.status]}
|
|
5004
|
+
`);
|
|
5005
|
+
if (entry.note) process.stdout.write(` ${entry.note}
|
|
5006
|
+
`);
|
|
5007
|
+
}
|
|
5008
|
+
process.stdout.write("\n");
|
|
5009
|
+
const skipped = plan.entries.filter((e) => e.status === "locally-modified").length;
|
|
5010
|
+
const removed = plan.entries.filter((e) => e.status === "removed-upstream").length;
|
|
5011
|
+
const tail = [
|
|
5012
|
+
skipped > 0 ? `${skipped} \u4E2A\u672C\u5730\u6539\u8FC7\u88AB\u8DF3\u8FC7\uFF08--force \u8986\u76D6\uFF09` : "",
|
|
5013
|
+
removed > 0 ? `${removed} \u4E2A\u4EA7\u54C1\u5DF2\u79FB\u9664\uFF08\u672C\u5730\u6587\u4EF6\u4FDD\u7559\uFF09` : ""
|
|
5014
|
+
].filter(Boolean).join("\uFF0C");
|
|
5015
|
+
if (changed.length === 0 && skipped === 0 && removed === 0) {
|
|
5016
|
+
process.stdout.write(args.check ? " \u5168\u90E8\u5DF2\u662F\u6700\u65B0\uFF08--check \u53EA\u770B\u4E0D\u52A8\uFF09\n" : " \u5168\u90E8\u5DF2\u662F\u6700\u65B0\uFF0C\u6CA1\u6709\u6539\u52A8\n");
|
|
4386
5017
|
} else {
|
|
4387
|
-
|
|
4388
|
-
|
|
5018
|
+
const head = args.check ? changed.length > 0 ? `\u6709 ${changed.length} \u4E2A\u53EF\u4EE5\u66F4\u65B0\uFF0C\u53BB\u6389 --check \u5C31\u4F1A\u5199\u5165` : "\u6CA1\u6709\u53EF\u5199\u5165\u7684\u66F4\u65B0" : changed.length > 0 ? `\u5DF2\u66F4\u65B0 ${changed.length} \u4E2A` : "\u6CA1\u6709\u5199\u5165\u4EFB\u4F55\u6539\u52A8";
|
|
5019
|
+
process.stdout.write(` ${[head, tail].filter(Boolean).join("\uFF1B")}
|
|
4389
5020
|
`);
|
|
4390
5021
|
}
|
|
4391
5022
|
process.exit(0);
|
|
4392
5023
|
} catch (e) {
|
|
4393
|
-
if (e?.code === "ENOENT" && args.from) {
|
|
4394
|
-
exitWithError(new Error(`\u672C\u5730\u76EE\u5F55\u91CC\u6CA1\u6709 ${id}/SKILL.md\uFF1A${path2.resolve(args.from, id)}`));
|
|
4395
|
-
}
|
|
4396
5024
|
fail3(e, args);
|
|
4397
5025
|
}
|
|
4398
5026
|
}
|
|
@@ -5289,7 +5917,7 @@ async function walkWorkspaceRawFiles(rootDir, relativeDir, files) {
|
|
|
5289
5917
|
localPath,
|
|
5290
5918
|
absolutePath,
|
|
5291
5919
|
content,
|
|
5292
|
-
sha256:
|
|
5920
|
+
sha256: sha2562(content),
|
|
5293
5921
|
size: Buffer.byteLength(content, "utf-8")
|
|
5294
5922
|
});
|
|
5295
5923
|
}
|
|
@@ -5356,7 +5984,7 @@ function buildWorkspaceRawPushPlan(manifest2, localFiles, remoteFiles) {
|
|
|
5356
5984
|
for (const entry of status) {
|
|
5357
5985
|
const remote = remoteByLocal.get(entry.localPath);
|
|
5358
5986
|
const base = baseByLocal.get(entry.localPath);
|
|
5359
|
-
const remoteSha = remote ?
|
|
5987
|
+
const remoteSha = remote ? sha2562(remote.content) : void 0;
|
|
5360
5988
|
if (entry.status === "added") {
|
|
5361
5989
|
if (remote) {
|
|
5362
5990
|
conflicts.push(workspaceRawConflict(entry, "remote file already exists but was not in local snapshot"));
|
|
@@ -5621,7 +6249,7 @@ function normalizeRelativePath(value) {
|
|
|
5621
6249
|
function toPosix(value) {
|
|
5622
6250
|
return value.split(path3.sep).join("/");
|
|
5623
6251
|
}
|
|
5624
|
-
function
|
|
6252
|
+
function sha2562(content) {
|
|
5625
6253
|
return crypto.createHash("sha256").update(content, "utf-8").digest("hex");
|
|
5626
6254
|
}
|
|
5627
6255
|
function stringRequired(value, field) {
|
|
@@ -6059,7 +6687,11 @@ var cache = program.command("cache").description("\u6A21\u578B\u7F13\u5B58\u8FD0
|
|
|
6059
6687
|
cache.command("stats <Model>").description("\u67E5\u770B\u6A21\u578B\u7F13\u5B58\u7EDF\u8BA1").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((model, opts) => cacheStatsCommand(model, opts));
|
|
6060
6688
|
cache.command("clear <Model>").description("\u6E05\u6A21\u578B\u5B9E\u4F53\u7F13\u5B58\uFF08\u5E42\u7B49\uFF0C\u4E0D\u7834\u574F\u6570\u636E\uFF09").option("--id <id>", "\u53EA\u6E05\u5355\u6761\uFF08\u9ED8\u8BA4\u6E05\u5168\u90E8\uFF09").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((model, opts) => cacheClearCommand(model, opts));
|
|
6061
6689
|
cache.command("clear-meta <Model>").description("\u6E05\u5143\u6570\u636E\u7F13\u5B58\uFF08Code \u7EA7 YAML + Action \u5B9A\u4E49\uFF09\u2014\u2014\u6539 meta YAML \u540E\u5FC5\u8DD1").option("--type <type>", "\u5143\u6570\u636E\u7C7B\u578B\uFF1Alist | info | view | filter | page\u2026\uFF08\u9ED8\u8BA4\u5168\u6E05\uFF09").option("--state <state>", "\u72B6\u6001\u53D8\u4F53\uFF08\u5982 self\uFF09\uFF0C\u914D\u5408 --type").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((model, opts) => cacheClearMetaCommand(model, opts));
|
|
6062
|
-
program.command("upload <file>").description("\u4E0A\u4F20\u672C\u5730\u6587\u4EF6\u5230 HCM \u6587\u6863\u670D\u52A1\uFF0C\u8FD4\u56DE documentId").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").
|
|
6690
|
+
program.command("upload <file>").description("\u4E0A\u4F20\u672C\u5730\u6587\u4EF6\u5230 HCM \u6587\u6863\u670D\u52A1\uFF0C\u8FD4\u56DE documentId").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").option(
|
|
6691
|
+
"--category <name>",
|
|
6692
|
+
"\u5B58\u50A8\u5206\u7C7B\uFF08\u987B\u662F\u76EE\u6807\u73AF\u5883\u91CC\u771F\u5B9E\u5B58\u5728\u7684\u5206\u7C7B\uFF0C\u5982 flex-report / template / attachment\uFF09",
|
|
6693
|
+
"attachment"
|
|
6694
|
+
).action((file, opts) => uploadCommand(file, opts));
|
|
6063
6695
|
var tenant = program.command("tenant").description("\u79DF\u6237\u5F00\u901A\u4E0E\u751F\u547D\u5468\u671F");
|
|
6064
6696
|
tenant.command("bootstrap").description("\u5F00\u901A\u65B0\u79DF\u6237\uFF08\u5EFA\u79DF\u6237 + admin \u7528\u6237 + \u7ED3\u6784 reconcile\uFF09\u2014\u2014\u4E0D\u53EF\u9006\uFF0C\u9ED8\u8BA4\u8FC7\u786E\u8BA4\u95F8").requiredOption("--tenant-id <id>", "\u79DF\u6237 ID").requiredOption("--admin-username <user>", "\u7BA1\u7406\u5458\u7528\u6237\u540D").option("--admin-password <pwd>", "\u7BA1\u7406\u5458\u5BC6\u7801\uFF08\u4F1A\u6CC4\u6F0F\u5230 history/ps\uFF0C\u5EFA\u8BAE --admin-password-stdin\uFF09").option("--admin-password-stdin", "\u4ECE\u6807\u51C6\u8F93\u5165\u8BFB\u7BA1\u7406\u5458\u5BC6\u7801\uFF08\u63A8\u8350\uFF09").option("--tenant-name <name>", "\u79DF\u6237\u540D\u79F0\uFF08\u9ED8\u8BA4\u53D6 tenantId\uFF09").option("--bootstrap-key <key>", "bootstrap \u5BC6\u94A5\uFF08\u5EFA\u8BAE\u7528 HCM_BOOTSTRAP_KEY \u73AF\u5883\u53D8\u91CF\uFF09").option("--bootstrap-key-stdin", "\u4ECE\u6807\u51C6\u8F93\u5165\u8BFB bootstrap \u5BC6\u94A5").option("--endpoint <url>", "\u540E\u7AEF\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("-y, --yes", "\u8DF3\u8FC7\u786E\u8BA4\uFF08CI \u7528\uFF09").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((opts) => tenantBootstrapCommand(opts));
|
|
6065
6697
|
var meta = program.command("meta").description("\u79DF\u6237\u5143\u6570\u636E\u8BFB\u5199\uFF08\u9875\u9762/\u5B57\u6BB5/\u5217\u8868\u914D\u7F6E\uFF09");
|
|
@@ -6068,9 +6700,10 @@ meta.command("get <path>").description("\u6253\u5370 meta \u539F\u6587\uFF08\u59
|
|
|
6068
6700
|
meta.command("set <path>").description("\u5199\u5165 meta \u539F\u6587\uFF1B\u5199\u5B8C\u987B hcm cache clear-meta <Model> \u624D\u751F\u6548").requiredOption("--file <file>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6\u539F\u6587\uFF08- \u8868\u793A stdin\uFF09").option("--dry-run", "\u53EA\u663E\u793A\u5C06\u5199\u5165\u7684\u5185\u5BB9\uFF0C\u4E0D\u5B9E\u9645\u5199\u5165").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((p, opts) => metaSetCommand(p, opts));
|
|
6069
6701
|
meta.command("delete <path>").description("\u5220\u9664 meta\uFF08\u4E0D\u53EF\u9006\uFF0C\u9ED8\u8BA4\u8FC7\u786E\u8BA4\u95F8\uFF09").option("-y, --yes", "\u8DF3\u8FC7\u786E\u8BA4").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((p, opts) => metaDeleteCommand(p, opts));
|
|
6070
6702
|
var skills = program.command("skills").description("\u777F\u620E Chiron \u4EA4\u4ED8\u6280\u80FD\u5E93\uFF1A\u5217\u51FA / \u67E5\u770B / \u5B89\u88C5\u4EA4\u4ED8\u6280\u80FD\uFF08\u514D\u8BA4\u8BC1\uFF0C\u65E0\u9700\u5148 login\uFF09");
|
|
6071
|
-
skills.command("list [keyword]").description("\u5217\u51FA\u76EE\u6807\u73AF\u5883\u8FD9\u4E00\u7248\u7684\u4EA4\u4ED8\u6280\u80FD").option("--category <key>", "\u53EA\u770B\u67D0\u4E2A\u5206\u7C7B").option("--stage <key>", "\u53EA\u770B\u67D0\u4E2A\u4EA4\u4ED8\u9636\u6BB5\uFF1Ahandover | baseline | configure | migrate | integrate | golive | operate").option("--by-stage", "\u6309\u4EA4\u4ED8\u751F\u547D\u5468\u671F\u5206\u7EC4\u5C55\u793A\uFF08\u9ED8\u8BA4\u6309\u529F\u80FD\u5206\u7C7B\uFF09").option("--endpoint <url>", "\u6280\u80FD\u5E93\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((kw, opts) => skillsListCommand(kw, opts));
|
|
6703
|
+
skills.command("list [keyword]").description("\u5217\u51FA\u76EE\u6807\u73AF\u5883\u8FD9\u4E00\u7248\u7684\u4EA4\u4ED8\u6280\u80FD\uFF1B--installed \u6539\u770B\u672C\u5730\u88C5\u4E86\u54EA\u4E9B\uFF08\u4E0D\u8FDE\u7F51\uFF09").option("--installed", "\u53EA\u770B\u672C\u5730\u5DF2\u88C5\u7684\u6280\u80FD\uFF08\u8BFB .hcm-skills.json\uFF0C\u4E0D\u8FDE\u7F51\uFF09").option("--target <agent>", "\u914D\u5408 --installed\uFF1Aclaude | codex | auto", "auto").option("--global", "\u914D\u5408 --installed\uFF1A\u770B\u7528\u6237\u7EA7\u76EE\u5F55").option("--dir <path>", "\u914D\u5408 --installed\uFF1A\u770B\u6307\u5B9A\u76EE\u5F55").option("--category <key>", "\u53EA\u770B\u67D0\u4E2A\u5206\u7C7B").option("--stage <key>", "\u53EA\u770B\u67D0\u4E2A\u4EA4\u4ED8\u9636\u6BB5\uFF1Ahandover | baseline | configure | migrate | integrate | golive | operate").option("--by-stage", "\u6309\u4EA4\u4ED8\u751F\u547D\u5468\u671F\u5206\u7EC4\u5C55\u793A\uFF08\u9ED8\u8BA4\u6309\u529F\u80FD\u5206\u7C7B\uFF09").option("--endpoint <url>", "\u6280\u80FD\u5E93\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((kw, opts) => skillsListCommand(kw, opts));
|
|
6072
6704
|
skills.command("show <id>").description("\u6253\u5370\u6280\u80FD\u539F\u6587\uFF08\u7BA1\u9053\u53CB\u597D\uFF09").option("--endpoint <url>", "\u6280\u80FD\u5E93\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").action((id, opts) => skillsShowCommand(id, opts));
|
|
6073
|
-
skills.command("install
|
|
6705
|
+
skills.command("install [id]").description("\u8FDE\u540C requires \u524D\u7F6E\u6280\u80FD\u4E0E\u53C2\u8003\u6587\u4EF6\u88C5\u5230 agent \u6280\u80FD\u76EE\u5F55\uFF1B--all \u88C5\u6574\u4E2A\u6280\u80FD\u5E93").option("--all", "\u88C5\u6574\u4E2A\u6280\u80FD\u5E93\uFF0C\u5E76\u8BB0\u4E3A\u300C\u8DDF\u968F\u5168\u96C6\u300D\uFF08\u5F80\u540E update \u4F1A\u81EA\u52A8\u8865\u4E0A\u4EA7\u54C1\u65B0\u589E\u7684\u6280\u80FD\uFF09").option("--target <agent>", "\u88C5\u7ED9\u54EA\u4E2A agent\uFF1Aclaude\uFF08.claude/skills/\uFF09| codex\uFF08hcm-skills/ + AGENTS.md\uFF09| auto", "auto").option("--global", "\u88C5\u5230\u7528\u6237\u7EA7\u76EE\u5F55\u800C\u975E\u5F53\u524D\u9879\u76EE").option("--dir <path>", "\u88C5\u5230\u6307\u5B9A\u76EE\u5F55").option("--from <dir>", "\u4ECE\u672C\u5730\u76EE\u5F55\u88C5\uFF08\u73B0\u573A\u6539\u8FC7\u7684\u7248\u672C\uFF09\uFF0C\u4E0D\u8D70\u7F51\u7EDC").option("--force", "\u8986\u76D6\u5DF2\u5B58\u5728\u7684\u540C\u540D\u6280\u80FD").option("--endpoint <url>", "\u6280\u80FD\u5E93\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((id, opts) => skillsInstallCommand(id, opts));
|
|
6706
|
+
skills.command("update").description("\u628A\u88C5\u8FC7\u7684\u6280\u80FD\u5347\u5230\u76EE\u6807\u73AF\u5883\u8FD9\u4E00\u7248\uFF08\u4EA7\u54C1\u5347\u7EA7\u540E\u8DD1\u5B83\uFF09").option("--all", "\u8FDE\u4EA7\u54C1\u65B0\u589E\u7684\u6280\u80FD\u4E00\u8D77\u88C5\u4E0A\uFF0C\u5E76\u8BB0\u4E3A\u300C\u8DDF\u968F\u5168\u96C6\u300D").option("--check", "\u53EA\u770B\u4F1A\u53D8\u4EC0\u4E48\uFF0C\u4E0D\u5199\u76D8").option("--target <agent>", "claude | codex | auto\uFF08\u9ED8\u8BA4\u6309\u5DF2\u5B89\u88C5\u76EE\u5F55\u63A2\uFF09", "auto").option("--global", "\u5347\u7EA7\u7528\u6237\u7EA7\u76EE\u5F55\u91CC\u7684\u6280\u80FD").option("--dir <path>", "\u5347\u7EA7\u6307\u5B9A\u76EE\u5F55\u91CC\u7684\u6280\u80FD").option("--force", "\u8FDE\u672C\u5730\u6539\u8FC7\u7684\u6280\u80FD\u4E00\u8D77\u8986\u76D6\u6210\u4EA7\u54C1\u8FD9\u4E00\u7248").option("--endpoint <url>", "\u6280\u80FD\u5E93\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6\u5B89\u88C5\u65F6\u8BB0\u5F55\u7684\u5730\u5740\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((opts) => skillsUpdateCommand(opts));
|
|
6074
6707
|
program.command("update <Model>").description("\u66F4\u65B0\u4E00\u6761 Model \u8BB0\u5F55\uFF08\u8D70\u540E\u7AEF\u5B8C\u6574\u6821\u9A8C\uFF09").requiredOption("--id <id>", "\u8BB0\u5F55 ID").requiredOption("--data <JSON>", `\u8981\u66F4\u65B0\u7684\u5B57\u6BB5 JSON\uFF0C\u4F8B\u5982 '{"name":"\u65B0\u540D\u79F0"}'`).option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD\uFF08\u8986\u76D6 env defaultIdentity\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((model, opts) => updateCommand(model, opts));
|
|
6075
6708
|
program.command("version").description("\u67E5\u540E\u7AEF\u7248\u672C\uFF08commit / tag / \u6784\u5EFA\u65F6\u95F4\uFF09\u2014\u2014\u514D\u8BA4\u8BC1\uFF0C\u65E0\u9700\u5148 login").option("--endpoint <url>", "\u540E\u7AEF\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((opts) => versionCommand(opts));
|
|
6076
6709
|
var setting = program.command("setting").description("\u79DF\u6237\u7CFB\u7EDF\u53C2\u6570\uFF08\u767B\u5F55\u7B56\u7565 / \u5BC6\u7801\u7B56\u7565 / \u529F\u80FD\u5F00\u5173 / \u96C6\u6210\u53C2\u6570\uFF09");
|