harnessed 3.9.8 → 3.9.10
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/cli.mjs +87 -27
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/manifests/skill-packs/mattpocock-skills.yaml +5 -4
- package/package.json +1 -1
- package/routing/decision_rules.yaml +1 -10
- package/manifests/skill-packs/anthropics-skills-pptx.yaml +0 -46
- package/manifests/skill-packs/anthropics-skills-slide-deck.yaml +0 -46
package/dist/cli.mjs
CHANGED
|
@@ -1222,7 +1222,7 @@ var init_auto_install = __esm({
|
|
|
1222
1222
|
|
|
1223
1223
|
// package.json
|
|
1224
1224
|
var package_default = {
|
|
1225
|
-
version: "3.9.
|
|
1225
|
+
version: "3.9.10"};
|
|
1226
1226
|
|
|
1227
1227
|
// src/manifest/errors.ts
|
|
1228
1228
|
function instancePathToKeyPath(instancePath) {
|
|
@@ -4379,6 +4379,9 @@ var installCcHookAdd = async (ctx) => {
|
|
|
4379
4379
|
await updateInstalled(ctx.cwd, ctx.manifest.metadata.name, "", "");
|
|
4380
4380
|
return { ok: true, backupId: bk.backupId, appliedFiles: [settingsPath3] };
|
|
4381
4381
|
};
|
|
4382
|
+
|
|
4383
|
+
// src/installers/lib/idempotent.ts
|
|
4384
|
+
init_readClaudeConfig();
|
|
4382
4385
|
function expandTildeForWindows(cmd) {
|
|
4383
4386
|
const home = homedir().replace(/\\/g, "/");
|
|
4384
4387
|
return cmd.replace(/(^|[\s"'`(])~\//g, `$1${home}/`);
|
|
@@ -4466,18 +4469,92 @@ async function spawnCmd(ctx, cmd, args, timeoutMs) {
|
|
|
4466
4469
|
|
|
4467
4470
|
// src/installers/lib/idempotent.ts
|
|
4468
4471
|
var IDEMPOTENT_CHECK_TIMEOUT_MS = 1e4;
|
|
4472
|
+
function extractSkillName(cmd, fallback) {
|
|
4473
|
+
const m = cmd.match(/\bskills(?:@\S+)?\s+add\s+(\S+)/i);
|
|
4474
|
+
if (!m?.[1]) return fallback;
|
|
4475
|
+
const seg = m[1].split("/");
|
|
4476
|
+
return seg[seg.length - 1] ?? fallback;
|
|
4477
|
+
}
|
|
4478
|
+
function extractGitCloneTarget(cmd) {
|
|
4479
|
+
const idx = cmd.indexOf("git clone");
|
|
4480
|
+
if (idx < 0) return null;
|
|
4481
|
+
const tail = cmd.slice(idx + "git clone".length).trim();
|
|
4482
|
+
const tokens = tail.split(/\s+/);
|
|
4483
|
+
let i = 0;
|
|
4484
|
+
while (i < tokens.length && tokens[i]?.startsWith("-")) {
|
|
4485
|
+
i += tokens[i]?.includes("=") ? 1 : 2;
|
|
4486
|
+
}
|
|
4487
|
+
const dest = tokens[i + 1];
|
|
4488
|
+
if (!dest || dest === "&&" || dest === ";" || dest === "|") return null;
|
|
4489
|
+
if (dest.startsWith("~/")) return join(homedir(), dest.slice(2));
|
|
4490
|
+
if (dest.startsWith("/") || /^[A-Z]:[\\/]/i.test(dest)) return dest;
|
|
4491
|
+
return null;
|
|
4492
|
+
}
|
|
4493
|
+
async function detectNative(ctx) {
|
|
4494
|
+
const method = ctx.manifest.spec.install.method;
|
|
4495
|
+
const cmd = ctx.manifest.spec.install.cmd;
|
|
4496
|
+
const name = ctx.manifest.metadata.name;
|
|
4497
|
+
if (method === "cc-plugin-marketplace") {
|
|
4498
|
+
const m = cmd.match(/(?:claude\s+)?plugin\s+install\s+(\S+)/i);
|
|
4499
|
+
const pluginName = m?.[1]?.split("@")[0] ?? name;
|
|
4500
|
+
try {
|
|
4501
|
+
return await isPluginRegistered(pluginName);
|
|
4502
|
+
} catch {
|
|
4503
|
+
return false;
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4506
|
+
if (method === "npx-skill-installer") {
|
|
4507
|
+
const skillName = extractSkillName(cmd, name);
|
|
4508
|
+
for (const base of [".claude", ".agents"]) {
|
|
4509
|
+
const skillMd = join(homedir(), base, "skills", skillName, "SKILL.md");
|
|
4510
|
+
try {
|
|
4511
|
+
await access(skillMd);
|
|
4512
|
+
return true;
|
|
4513
|
+
} catch {
|
|
4514
|
+
}
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
if (method === "git-clone-with-setup") {
|
|
4518
|
+
const target = extractGitCloneTarget(cmd);
|
|
4519
|
+
if (!target) return false;
|
|
4520
|
+
try {
|
|
4521
|
+
await access(target);
|
|
4522
|
+
return true;
|
|
4523
|
+
} catch {
|
|
4524
|
+
return false;
|
|
4525
|
+
}
|
|
4526
|
+
}
|
|
4527
|
+
if (method === "npm-cli") {
|
|
4528
|
+
const skillDir = join(homedir(), ".claude", "skills", name);
|
|
4529
|
+
try {
|
|
4530
|
+
await access(skillDir);
|
|
4531
|
+
return true;
|
|
4532
|
+
} catch {
|
|
4533
|
+
return false;
|
|
4534
|
+
}
|
|
4535
|
+
}
|
|
4536
|
+
const pluginNames = [name];
|
|
4537
|
+
if (name === "ctx7") pluginNames.push("context7");
|
|
4538
|
+
for (const pn of pluginNames) {
|
|
4539
|
+
try {
|
|
4540
|
+
if (await isPluginRegistered(pn)) return true;
|
|
4541
|
+
} catch {
|
|
4542
|
+
}
|
|
4543
|
+
}
|
|
4544
|
+
return false;
|
|
4545
|
+
}
|
|
4469
4546
|
async function isAlreadyInstalled(ctx, opts = {}) {
|
|
4470
4547
|
const honorUpdateFlag = opts.honorUpdateFlag !== false;
|
|
4471
4548
|
if (honorUpdateFlag && ctx.opts.updateInstalled === true) return false;
|
|
4472
4549
|
if (ctx.opts.dryRun) return false;
|
|
4550
|
+
const native = await detectNative(ctx);
|
|
4551
|
+
if (native) return true;
|
|
4473
4552
|
const idempotentCmd = ctx.manifest.spec.install.idempotent_check;
|
|
4474
4553
|
if (typeof idempotentCmd !== "string" || idempotentCmd.length === 0) {
|
|
4475
4554
|
return false;
|
|
4476
4555
|
}
|
|
4477
4556
|
const r = await spawnCmd(ctx, idempotentCmd, [], IDEMPOTENT_CHECK_TIMEOUT_MS);
|
|
4478
|
-
if (!("exitCode" in r))
|
|
4479
|
-
return false;
|
|
4480
|
-
}
|
|
4557
|
+
if (!("exitCode" in r)) return false;
|
|
4481
4558
|
return r.exitCode === 0;
|
|
4482
4559
|
}
|
|
4483
4560
|
|
|
@@ -4615,7 +4692,7 @@ ${newEntry}
|
|
|
4615
4692
|
const r1 = await runArgs(["plugin", "marketplace", "add", parsed.marketplaceRef], spawnCwd);
|
|
4616
4693
|
stepOneStderr = r1.stderr;
|
|
4617
4694
|
}
|
|
4618
|
-
const r2 = await runArgs(installArgs, spawnCwd);
|
|
4695
|
+
const r2 = await runArgs(installArgs, spawnCwd, 6e4);
|
|
4619
4696
|
if (r2.exitCode !== 0) {
|
|
4620
4697
|
return {
|
|
4621
4698
|
ok: false,
|
|
@@ -5221,7 +5298,7 @@ var installNpmCli = async (ctx) => {
|
|
|
5221
5298
|
await updateInstalled(ctx.cwd, ctx.manifest.metadata.name, install.npm_version, "");
|
|
5222
5299
|
return { ok: true, backupId: bk.backupId, appliedFiles: [] };
|
|
5223
5300
|
};
|
|
5224
|
-
function
|
|
5301
|
+
function extractSkillName2(cmd, fallback) {
|
|
5225
5302
|
const m = cmd.match(/\bskills(?:@\S+)?\s+add\s+(\S+)/i);
|
|
5226
5303
|
if (!m || m[1] === void 0) return fallback;
|
|
5227
5304
|
const ref = m[1];
|
|
@@ -5252,21 +5329,6 @@ var installNpxSkillInstaller = async (ctx) => {
|
|
|
5252
5329
|
if (await isAlreadyInstalled(ctx)) {
|
|
5253
5330
|
return { ok: true, alreadyInstalled: true, backupId: "noop-idempotent" };
|
|
5254
5331
|
}
|
|
5255
|
-
if (!/\bskills@(?!latest\b)\S+/.test(install.cmd)) {
|
|
5256
|
-
return {
|
|
5257
|
-
ok: false,
|
|
5258
|
-
phase: "preflight",
|
|
5259
|
-
error: {
|
|
5260
|
-
...err(
|
|
5261
|
-
ctx,
|
|
5262
|
-
"/spec/install/cmd",
|
|
5263
|
-
`npx-skill-installer cmd must reference a pinned skills@<version> (got: '${install.cmd.slice(0, 100)}'); @latest is forbidden for reproducibility (ADR 0001)`,
|
|
5264
|
-
"skills-pin-required"
|
|
5265
|
-
),
|
|
5266
|
-
suggest: "change `skills@latest` \u2192 `skills@1.5.7` (current research-pinned stable)"
|
|
5267
|
-
}
|
|
5268
|
-
};
|
|
5269
|
-
}
|
|
5270
5332
|
if (!/\B--copy\b/.test(install.cmd) || !/\B--global\b/.test(install.cmd)) {
|
|
5271
5333
|
return {
|
|
5272
5334
|
ok: false,
|
|
@@ -5283,7 +5345,7 @@ var installNpxSkillInstaller = async (ctx) => {
|
|
|
5283
5345
|
};
|
|
5284
5346
|
}
|
|
5285
5347
|
const name = ctx.manifest.metadata.name;
|
|
5286
|
-
const skillSegment =
|
|
5348
|
+
const skillSegment = extractSkillName2(install.cmd, name);
|
|
5287
5349
|
const skillDir = join(homedir(), ".claude", "skills", skillSegment);
|
|
5288
5350
|
const skillMdPath = join(skillDir, "SKILL.md");
|
|
5289
5351
|
const plan = {
|
|
@@ -6342,9 +6404,7 @@ function registerSetup(program2) {
|
|
|
6342
6404
|
);
|
|
6343
6405
|
for (const n of b.installed) console.log(` [B] installed ${n}`);
|
|
6344
6406
|
for (const n of b.alreadyInstalled)
|
|
6345
|
-
console.log(
|
|
6346
|
-
` [B] already-installed ${n} \u2014 run \`/mcp\` in Claude Code to verify connection`
|
|
6347
|
-
);
|
|
6407
|
+
console.log(` [B] already-installed ${n}`);
|
|
6348
6408
|
for (const s of b.skipped) console.log(` [B] skipped ${s.name} \u2014 ${s.reason}`);
|
|
6349
6409
|
for (const n of b.failed) console.error(` [B] failed ${n}`);
|
|
6350
6410
|
if (!forceFirstPass && !dryRun && raw.nonInteractive !== true && b.alreadyInstalled.length > 0) {
|
|
@@ -6647,7 +6707,7 @@ var uninstallNpmCli = async (ctx) => {
|
|
|
6647
6707
|
}
|
|
6648
6708
|
return { ok: true, removedPaths: [pkg] };
|
|
6649
6709
|
};
|
|
6650
|
-
function
|
|
6710
|
+
function extractSkillName3(cmd, fallback) {
|
|
6651
6711
|
const m = cmd.match(/\bskills(?:@\S+)?\s+add\s+(\S+)/i);
|
|
6652
6712
|
if (!m || m[1] === void 0) return fallback;
|
|
6653
6713
|
const ref = m[1];
|
|
@@ -6662,7 +6722,7 @@ var uninstallNpxSkillInstaller = async (ctx) => {
|
|
|
6662
6722
|
const abort = dryRunGate(ctx);
|
|
6663
6723
|
if (abort) return abort;
|
|
6664
6724
|
const name = ctx.manifest.metadata.name;
|
|
6665
|
-
const skillName =
|
|
6725
|
+
const skillName = extractSkillName3(install.cmd, name);
|
|
6666
6726
|
const skillDir = join(homedir(), ".claude", "skills", skillName);
|
|
6667
6727
|
await rm(skillDir, { recursive: true, force: true, maxRetries: 3 });
|
|
6668
6728
|
return { ok: true, removedPaths: [skillDir] };
|