harnessed 3.9.7 → 3.9.8
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
CHANGED
|
@@ -789,11 +789,33 @@ async function isMcpServerRegistered(name) {
|
|
|
789
789
|
return Object.hasOwn(servers, name);
|
|
790
790
|
}
|
|
791
791
|
async function isPluginRegistered(pluginName) {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
792
|
+
try {
|
|
793
|
+
const path = join(homedir(), ".claude", "plugins", "installed_plugins.json");
|
|
794
|
+
const raw = await readFile(path, "utf8");
|
|
795
|
+
const parsed = JSON.parse(raw);
|
|
796
|
+
const plugins = parsed.plugins;
|
|
797
|
+
if (plugins && typeof plugins === "object") {
|
|
798
|
+
if (Object.hasOwn(plugins, pluginName)) return true;
|
|
799
|
+
if (Object.keys(plugins).some((k) => k.split("@")[0] === pluginName)) return true;
|
|
800
|
+
}
|
|
801
|
+
} catch {
|
|
802
|
+
}
|
|
803
|
+
for (const path of [
|
|
804
|
+
join(homedir(), ".claude", "settings.json"),
|
|
805
|
+
join(homedir(), ".claude.json")
|
|
806
|
+
]) {
|
|
807
|
+
try {
|
|
808
|
+
const raw = await readFile(path, "utf8");
|
|
809
|
+
const parsed = JSON.parse(raw);
|
|
810
|
+
const plugins = parsed.enabledPlugins;
|
|
811
|
+
if (plugins && typeof plugins === "object") {
|
|
812
|
+
if (Object.hasOwn(plugins, pluginName)) return true;
|
|
813
|
+
if (Object.keys(plugins).some((k) => k.split("@")[0] === pluginName)) return true;
|
|
814
|
+
}
|
|
815
|
+
} catch {
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return false;
|
|
797
819
|
}
|
|
798
820
|
var init_readClaudeConfig = __esm({
|
|
799
821
|
"src/installers/lib/readClaudeConfig.ts"() {
|
|
@@ -1200,7 +1222,7 @@ var init_auto_install = __esm({
|
|
|
1200
1222
|
|
|
1201
1223
|
// package.json
|
|
1202
1224
|
var package_default = {
|
|
1203
|
-
version: "3.9.
|
|
1225
|
+
version: "3.9.8"};
|
|
1204
1226
|
|
|
1205
1227
|
// src/manifest/errors.ts
|
|
1206
1228
|
function instancePathToKeyPath(instancePath) {
|
|
@@ -4357,6 +4379,10 @@ var installCcHookAdd = async (ctx) => {
|
|
|
4357
4379
|
await updateInstalled(ctx.cwd, ctx.manifest.metadata.name, "", "");
|
|
4358
4380
|
return { ok: true, backupId: bk.backupId, appliedFiles: [settingsPath3] };
|
|
4359
4381
|
};
|
|
4382
|
+
function expandTildeForWindows(cmd) {
|
|
4383
|
+
const home = homedir().replace(/\\/g, "/");
|
|
4384
|
+
return cmd.replace(/(^|[\s"'`(])~\//g, `$1${home}/`);
|
|
4385
|
+
}
|
|
4360
4386
|
var DEFAULT_VERIFY_TIMEOUT_MS = 15e3;
|
|
4361
4387
|
var DEFAULT_INSTALL_TIMEOUT_MS = 6e4;
|
|
4362
4388
|
async function spawnCmd(ctx, cmd, args, timeoutMs) {
|
|
@@ -4381,7 +4407,13 @@ async function spawnCmd(ctx, cmd, args, timeoutMs) {
|
|
|
4381
4407
|
const cwd = installCfg.cwd ?? ctx.cwd;
|
|
4382
4408
|
let child;
|
|
4383
4409
|
if (process.platform === "win32") {
|
|
4384
|
-
|
|
4410
|
+
const expandedCmd = expandTildeForWindows(cmd);
|
|
4411
|
+
const expandedArgs = args.map(expandTildeForWindows);
|
|
4412
|
+
child = spawn("cmd.exe", ["/c", expandedCmd, ...expandedArgs], {
|
|
4413
|
+
cwd,
|
|
4414
|
+
env,
|
|
4415
|
+
windowsHide: true
|
|
4416
|
+
});
|
|
4385
4417
|
} else {
|
|
4386
4418
|
const joined = args.length > 0 ? `${cmd} ${args.join(" ")}` : cmd;
|
|
4387
4419
|
child = spawn("/bin/sh", ["-c", joined], { cwd, env });
|
|
@@ -4434,8 +4466,10 @@ async function spawnCmd(ctx, cmd, args, timeoutMs) {
|
|
|
4434
4466
|
|
|
4435
4467
|
// src/installers/lib/idempotent.ts
|
|
4436
4468
|
var IDEMPOTENT_CHECK_TIMEOUT_MS = 1e4;
|
|
4437
|
-
async function isAlreadyInstalled(ctx) {
|
|
4438
|
-
|
|
4469
|
+
async function isAlreadyInstalled(ctx, opts = {}) {
|
|
4470
|
+
const honorUpdateFlag = opts.honorUpdateFlag !== false;
|
|
4471
|
+
if (honorUpdateFlag && ctx.opts.updateInstalled === true) return false;
|
|
4472
|
+
if (ctx.opts.dryRun) return false;
|
|
4439
4473
|
const idempotentCmd = ctx.manifest.spec.install.idempotent_check;
|
|
4440
4474
|
if (typeof idempotentCmd !== "string" || idempotentCmd.length === 0) {
|
|
4441
4475
|
return false;
|
|
@@ -4856,6 +4890,9 @@ var installMcpHttpAdd = async (ctx) => {
|
|
|
4856
4890
|
const e = pre.errors[0] ?? err(ctx, "/", "preflight failed (no detail)", "preflight");
|
|
4857
4891
|
return { ok: false, phase: "preflight", error: e };
|
|
4858
4892
|
}
|
|
4893
|
+
if (await isAlreadyInstalled(ctx, { honorUpdateFlag: false })) {
|
|
4894
|
+
return { ok: true, alreadyInstalled: true, backupId: "noop-idempotent" };
|
|
4895
|
+
}
|
|
4859
4896
|
const name = ctx.manifest.metadata.name;
|
|
4860
4897
|
const url = extractUrl(install.cmd);
|
|
4861
4898
|
if (!url) {
|
|
@@ -4992,6 +5029,9 @@ var installMcpStdioAdd = async (ctx) => {
|
|
|
4992
5029
|
const e = pre.errors[0] ?? err(ctx, "/", "preflight failed (no detail)", "preflight");
|
|
4993
5030
|
return { ok: false, phase: "preflight", error: e };
|
|
4994
5031
|
}
|
|
5032
|
+
if (await isAlreadyInstalled(ctx, { honorUpdateFlag: false })) {
|
|
5033
|
+
return { ok: true, alreadyInstalled: true, backupId: "noop-idempotent" };
|
|
5034
|
+
}
|
|
4995
5035
|
const name = ctx.manifest.metadata.name;
|
|
4996
5036
|
const pkg = ctx.manifest.metadata.upstream.source;
|
|
4997
5037
|
const ver = install.npm_version;
|
|
@@ -6110,7 +6150,7 @@ async function runStepBInstall(manifestPaths, runOpts = {}) {
|
|
|
6110
6150
|
}
|
|
6111
6151
|
const name = v.manifest.metadata.name;
|
|
6112
6152
|
const r = await runInstall(v.manifest, opts);
|
|
6113
|
-
if ("aborted" in r) return { status: "skipped", name };
|
|
6153
|
+
if ("aborted" in r) return { status: "skipped", name, reason: r.reason };
|
|
6114
6154
|
if (r.ok && "alreadyInstalled" in r && r.alreadyInstalled)
|
|
6115
6155
|
return { status: "already-installed", name };
|
|
6116
6156
|
if (r.ok) return { status: "installed", name };
|
|
@@ -6129,8 +6169,10 @@ async function runStepBInstall(manifestPaths, runOpts = {}) {
|
|
|
6129
6169
|
};
|
|
6130
6170
|
if (v.status === "installed") installed.push(v.name);
|
|
6131
6171
|
else if (v.status === "already-installed") alreadyInstalled.push(v.name);
|
|
6132
|
-
else if (v.status === "skipped")
|
|
6133
|
-
|
|
6172
|
+
else if (v.status === "skipped") {
|
|
6173
|
+
const skipReason = v.reason ?? "unknown";
|
|
6174
|
+
skipped.push({ name: v.name, reason: skipReason });
|
|
6175
|
+
} else
|
|
6134
6176
|
failed.push(`${v.name}: ${v.reason}`);
|
|
6135
6177
|
}
|
|
6136
6178
|
return { installed, alreadyInstalled, skipped, failed, elapsedMs: Date.now() - start };
|
|
@@ -6303,7 +6345,7 @@ function registerSetup(program2) {
|
|
|
6303
6345
|
console.log(
|
|
6304
6346
|
` [B] already-installed ${n} \u2014 run \`/mcp\` in Claude Code to verify connection`
|
|
6305
6347
|
);
|
|
6306
|
-
for (const
|
|
6348
|
+
for (const s of b.skipped) console.log(` [B] skipped ${s.name} \u2014 ${s.reason}`);
|
|
6307
6349
|
for (const n of b.failed) console.error(` [B] failed ${n}`);
|
|
6308
6350
|
if (!forceFirstPass && !dryRun && raw.nonInteractive !== true && b.alreadyInstalled.length > 0) {
|
|
6309
6351
|
const isTty = process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
@@ -6323,7 +6365,8 @@ Force-update pass complete: ${b2.installed.length} installed / ${b2.alreadyInsta
|
|
|
6323
6365
|
for (const n of b2.installed) console.log(` [B*] installed ${n}`);
|
|
6324
6366
|
for (const n of b2.alreadyInstalled)
|
|
6325
6367
|
console.log(` [B*] already-installed ${n} (MCP / no force-update)`);
|
|
6326
|
-
for (const
|
|
6368
|
+
for (const s of b2.skipped)
|
|
6369
|
+
console.log(` [B*] skipped ${s.name} \u2014 ${s.reason}`);
|
|
6327
6370
|
for (const n of b2.failed) console.error(` [B*] failed ${n}`);
|
|
6328
6371
|
}
|
|
6329
6372
|
}
|