@levr-one/cli 0.11.5 → 0.11.7
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.
|
@@ -642,6 +642,8 @@ const HARNESSES = [
|
|
|
642
642
|
docsUrl: "https://github.com/openai/codex",
|
|
643
643
|
verifiedVersion: "0.154.0",
|
|
644
644
|
verifiedOn: "2026-09-17",
|
|
645
|
+
configDirEnv: "CODEX_HOME",
|
|
646
|
+
configDirReplaces: "~/.codex",
|
|
645
647
|
detectSignals: [
|
|
646
648
|
{
|
|
647
649
|
platform: "darwin",
|
|
@@ -771,6 +773,41 @@ function buildServerEntry(harness, mcpUrl, scope = defaultScope(harness), server
|
|
|
771
773
|
args
|
|
772
774
|
} };
|
|
773
775
|
}
|
|
776
|
+
/** The workspace a scoped MCP URL names (`…/w/<url_key>`), if any. */
|
|
777
|
+
function workspaceKeyOf(url) {
|
|
778
|
+
const m = /\/w\/([^/]+)$/.exec(url.replace(/\/+$/, ""));
|
|
779
|
+
if (!m?.[1]) return void 0;
|
|
780
|
+
try {
|
|
781
|
+
return decodeURIComponent(m[1]);
|
|
782
|
+
} catch {
|
|
783
|
+
return m[1];
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Allowed client entry names: 1-64 of `A-Za-z0-9_-`, and never starting with
|
|
788
|
+
* `-`. The name is passed as an argv element to the client's own CLI
|
|
789
|
+
* (`claude mcp add … <name> <url>`), so a leading `-` would be read there as a
|
|
790
|
+
* flag — the ENG-4159 argument-injection family.
|
|
791
|
+
*/
|
|
792
|
+
const ENTRY_NAME = /^[A-Za-z0-9_-]{1,64}$/;
|
|
793
|
+
function isValidEntryName(name) {
|
|
794
|
+
return ENTRY_NAME.test(name) && !name.startsWith("-");
|
|
795
|
+
}
|
|
796
|
+
/** Claude Code tool names are `mcp__<entry>__<tool>`; keep that well short. */
|
|
797
|
+
const BESIDE_NAME_MAX = 30;
|
|
798
|
+
/**
|
|
799
|
+
* The name for a second entry beside `serverName`: `<serverName>-<url_key>`,
|
|
800
|
+
* so it says which workspace it is. Undefined — and "Add beside it" is not
|
|
801
|
+
* offered — when the target URL names no workspace, or when that name would
|
|
802
|
+
* be too long or not a valid entry name. It is never shortened: a cut name
|
|
803
|
+
* could drop the workspace, or give two workspaces the same entry.
|
|
804
|
+
*/
|
|
805
|
+
function besideName(serverName, url) {
|
|
806
|
+
const key = workspaceKeyOf(url);
|
|
807
|
+
if (!key) return void 0;
|
|
808
|
+
const name = `${serverName}-${key}`;
|
|
809
|
+
return name.length <= BESIDE_NAME_MAX && isValidEntryName(name) ? name : void 0;
|
|
810
|
+
}
|
|
774
811
|
|
|
775
812
|
//#endregion
|
|
776
813
|
//#region ../mcp-harnesses/dist/node/paths.js
|
|
@@ -784,14 +821,20 @@ function defaultEnv() {
|
|
|
784
821
|
};
|
|
785
822
|
}
|
|
786
823
|
/**
|
|
787
|
-
*
|
|
788
|
-
*
|
|
789
|
-
*
|
|
790
|
-
*
|
|
824
|
+
* A config path or signal with `~` expanded. When the harness's `configDirEnv`
|
|
825
|
+
* is set to a non-empty value, the prefix it stands for (`configDirReplaces`,
|
|
826
|
+
* `~` by default) resolves to that directory instead (ENG-6696, ENG-6761). A
|
|
827
|
+
* relative value resolves against `env.cwd`, the directory a spawned client
|
|
828
|
+
* CLI runs in, so the probe and the client read one file.
|
|
791
829
|
*/
|
|
792
|
-
function
|
|
830
|
+
function expandConfigPath(p, harness, env) {
|
|
793
831
|
const dir = harness.configDirEnv ? env.vars?.[harness.configDirEnv] : void 0;
|
|
794
|
-
|
|
832
|
+
if (dir) {
|
|
833
|
+
const prefix = harness.configDirReplaces ?? "~";
|
|
834
|
+
if (p === prefix) return resolve(env.cwd, dir);
|
|
835
|
+
if (p.startsWith(`${prefix}/`) || p.startsWith(`${prefix}\\`)) return join(resolve(env.cwd, dir), p.slice(prefix.length + 1));
|
|
836
|
+
}
|
|
837
|
+
return expandTilde(p, env.homedir);
|
|
795
838
|
}
|
|
796
839
|
/** Expand a leading `~` / `~/…` to the given home directory. */
|
|
797
840
|
function expandTilde(p, home) {
|
|
@@ -822,7 +865,7 @@ function resolveConfigPath(harness, env, scope = defaultScope(harness)) {
|
|
|
822
865
|
if (def.projectPath) return join(resolveProjectRoot(env).root, ...def.projectPath.split("/"));
|
|
823
866
|
const loc = locationFor(harness, env.platform, scope);
|
|
824
867
|
if (!loc) return void 0;
|
|
825
|
-
return
|
|
868
|
+
return expandConfigPath(loc.configPath, harness, env);
|
|
826
869
|
}
|
|
827
870
|
/**
|
|
828
871
|
* Nearest ancestor of `cwd` containing `.git`, or `undefined`.
|
|
@@ -1024,11 +1067,12 @@ function whichSync(bin, env) {
|
|
|
1024
1067
|
return whichPathSync(bin, env) !== void 0;
|
|
1025
1068
|
}
|
|
1026
1069
|
/** Does one `installSignals` entry match on this machine? Supports
|
|
1027
|
-
* `which:<bin>`, `~`-prefixed paths, and absolute (app-bundle) paths.
|
|
1028
|
-
*
|
|
1029
|
-
|
|
1070
|
+
* `which:<bin>`, `~`-prefixed paths, and absolute (app-bundle) paths.
|
|
1071
|
+
* `expand` turns a `~` path into the one this harness reads — see
|
|
1072
|
+
* {@link expandConfigPath}. */
|
|
1073
|
+
function signalMatches(signal, env, expand = (p) => expandTilde(p, env.homedir)) {
|
|
1030
1074
|
if (signal.startsWith("which:")) return whichSync(signal.slice(6), env);
|
|
1031
|
-
return existsSync(signal.startsWith("~") ?
|
|
1075
|
+
return existsSync(signal.startsWith("~") ? expand(signal) : signal);
|
|
1032
1076
|
}
|
|
1033
1077
|
/**
|
|
1034
1078
|
* The value our server key currently holds for this scope, or `undefined`.
|
|
@@ -1541,7 +1585,7 @@ function detectScope(harness, env, def, opts) {
|
|
|
1541
1585
|
function detectOne(harness, env, opts) {
|
|
1542
1586
|
const scopes = harness.scopes.map((def) => detectScope(harness, env, def, opts));
|
|
1543
1587
|
const available = scopes.some((s) => s.available);
|
|
1544
|
-
const installed = detectSignalsFor(harness, env.platform).some((s) => signalMatches(s, env,
|
|
1588
|
+
const installed = detectSignalsFor(harness, env.platform).some((s) => signalMatches(s, env, (p) => expandConfigPath(p, harness, env))) || scopes.some((s) => s.configPath !== "" && existsSync(s.configPath));
|
|
1545
1589
|
const fallback = scopes.find((s) => s.scope === defaultScope(harness));
|
|
1546
1590
|
return {
|
|
1547
1591
|
id: harness.id,
|
|
@@ -1602,47 +1646,44 @@ function needsShell(binPath) {
|
|
|
1602
1646
|
*/
|
|
1603
1647
|
const SHELL_METACHARACTERS = /[&|<>^"%!`]/;
|
|
1604
1648
|
/**
|
|
1605
|
-
*
|
|
1649
|
+
* Everything decided before a command is spawned, shared by both runners: an
|
|
1650
|
+
* outcome when it must not run, else how to run it.
|
|
1606
1651
|
*
|
|
1607
1652
|
* Resolution uses {@link whichPathSync} — a pure `PATH` scan that spawns
|
|
1608
1653
|
* nothing, so the "is this installed" check can never itself be the thing
|
|
1609
1654
|
* that hangs. It returns the resolved path rather than a boolean because the
|
|
1610
1655
|
* extension decides how the command must be launched.
|
|
1611
1656
|
*/
|
|
1612
|
-
function
|
|
1657
|
+
function prepare(argv, opts) {
|
|
1613
1658
|
const env = opts.env ?? defaultEnv();
|
|
1614
1659
|
const dryRun = opts.dryRun ?? false;
|
|
1615
1660
|
const [bin, ...args] = argv;
|
|
1616
|
-
if (!bin) return {
|
|
1661
|
+
if (!bin) return { skip: {
|
|
1617
1662
|
executed: false,
|
|
1618
1663
|
ok: false,
|
|
1619
1664
|
reason: "empty-command"
|
|
1620
|
-
};
|
|
1621
|
-
if (dryRun) return {
|
|
1665
|
+
} };
|
|
1666
|
+
if (dryRun) return { skip: {
|
|
1622
1667
|
executed: false,
|
|
1623
1668
|
ok: true,
|
|
1624
1669
|
reason: "dry-run"
|
|
1625
|
-
};
|
|
1670
|
+
} };
|
|
1626
1671
|
const binPath = whichPathSync(bin, env);
|
|
1627
|
-
if (!binPath) return {
|
|
1672
|
+
if (!binPath) return { skip: {
|
|
1628
1673
|
executed: false,
|
|
1629
1674
|
ok: true,
|
|
1630
1675
|
reason: "binary-not-found"
|
|
1631
|
-
};
|
|
1676
|
+
} };
|
|
1632
1677
|
const useShell = needsShell(binPath);
|
|
1633
|
-
if (useShell && args.some((a) => SHELL_METACHARACTERS.test(a))) return {
|
|
1678
|
+
if (useShell && (binPath.includes("\"") || args.some((a) => SHELL_METACHARACTERS.test(a)))) return { skip: {
|
|
1634
1679
|
executed: false,
|
|
1635
1680
|
ok: false,
|
|
1636
1681
|
reason: "unsafe-argument"
|
|
1637
|
-
};
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
"ignore",
|
|
1643
|
-
"pipe",
|
|
1644
|
-
"pipe"
|
|
1645
|
-
],
|
|
1682
|
+
} };
|
|
1683
|
+
return { spawn: {
|
|
1684
|
+
binPath: useShell ? `"${binPath}"` : binPath,
|
|
1685
|
+
args,
|
|
1686
|
+
options: {
|
|
1646
1687
|
timeout: COMMAND_TIMEOUT_MS,
|
|
1647
1688
|
env: {
|
|
1648
1689
|
...childVars(env),
|
|
@@ -1651,20 +1692,42 @@ function runHarnessCommandSync(argv, opts = {}) {
|
|
|
1651
1692
|
},
|
|
1652
1693
|
cwd: env.cwd,
|
|
1653
1694
|
...useShell ? { shell: true } : {}
|
|
1695
|
+
}
|
|
1696
|
+
} };
|
|
1697
|
+
}
|
|
1698
|
+
/** A command that ran and failed (or could not start), as an outcome. */
|
|
1699
|
+
function failureOutcome(err) {
|
|
1700
|
+
const e = err;
|
|
1701
|
+
const exitCode = typeof e.status === "number" ? e.status : typeof e.code === "number" ? e.code : void 0;
|
|
1702
|
+
const raw = typeof e.stderr === "string" ? e.stderr : e.stderr?.toString("utf8") ?? "";
|
|
1703
|
+
return {
|
|
1704
|
+
executed: true,
|
|
1705
|
+
ok: false,
|
|
1706
|
+
...exitCode === void 0 ? {} : { exitCode },
|
|
1707
|
+
stderr: (raw.trim() || e.message || "command failed").slice(0, MAX_STDERR)
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1710
|
+
/** Run a harness CLI invocation, or explain why it was not run. */
|
|
1711
|
+
function runHarnessCommandSync(argv, opts = {}) {
|
|
1712
|
+
const prepared = prepare(argv, opts);
|
|
1713
|
+
if ("skip" in prepared) return prepared.skip;
|
|
1714
|
+
const { binPath, args, options } = prepared.spawn;
|
|
1715
|
+
try {
|
|
1716
|
+
execFileSync(binPath, args, {
|
|
1717
|
+
...options,
|
|
1718
|
+
encoding: "utf8",
|
|
1719
|
+
stdio: [
|
|
1720
|
+
"ignore",
|
|
1721
|
+
"pipe",
|
|
1722
|
+
"pipe"
|
|
1723
|
+
]
|
|
1654
1724
|
});
|
|
1655
1725
|
return {
|
|
1656
1726
|
executed: true,
|
|
1657
1727
|
ok: true
|
|
1658
1728
|
};
|
|
1659
1729
|
} catch (err) {
|
|
1660
|
-
|
|
1661
|
-
const raw = typeof e.stderr === "string" ? e.stderr : e.stderr?.toString("utf8") ?? "";
|
|
1662
|
-
return {
|
|
1663
|
-
executed: true,
|
|
1664
|
-
ok: false,
|
|
1665
|
-
...typeof e.status === "number" ? { exitCode: e.status } : {},
|
|
1666
|
-
stderr: (raw.trim() || e.message || "command failed").slice(0, MAX_STDERR)
|
|
1667
|
-
};
|
|
1730
|
+
return failureOutcome(err);
|
|
1668
1731
|
}
|
|
1669
1732
|
}
|
|
1670
1733
|
|
|
@@ -1736,8 +1799,16 @@ function canonical(value) {
|
|
|
1736
1799
|
if (value !== null && typeof value === "object") return `{${Object.entries(value).filter(([, v]) => v !== void 0).sort(([x], [y]) => x < y ? -1 : x > y ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(",")}}`;
|
|
1737
1800
|
return JSON.stringify(value) ?? "undefined";
|
|
1738
1801
|
}
|
|
1802
|
+
function drive(steps, run) {
|
|
1803
|
+
let step = steps.next();
|
|
1804
|
+
while (!step.done) step = steps.next(run(step.value.argv, step.value.opts));
|
|
1805
|
+
return step.value;
|
|
1806
|
+
}
|
|
1739
1807
|
/** Merge (or preview) our MCP into a harness config. */
|
|
1740
1808
|
function installHarnessSync(harness, mcpUrl, opts = {}) {
|
|
1809
|
+
return drive(installSteps(harness, mcpUrl, opts), opts.runCommand ?? runHarnessCommandSync);
|
|
1810
|
+
}
|
|
1811
|
+
function* installSteps(harness, mcpUrl, opts) {
|
|
1741
1812
|
const env = opts.env ?? defaultEnv();
|
|
1742
1813
|
const dryRun = opts.dryRun ?? false;
|
|
1743
1814
|
const scope = opts.scope ?? defaultScope(harness);
|
|
@@ -1776,13 +1847,12 @@ function installHarnessSync(harness, mcpUrl, opts = {}) {
|
|
|
1776
1847
|
alreadyConfigured: false,
|
|
1777
1848
|
reason: "unrecognized-entry"
|
|
1778
1849
|
};
|
|
1779
|
-
if (opts.replaceExisting) return
|
|
1850
|
+
if (opts.replaceExisting) return yield* replaceSteps(harness, argv, existing$1.url, {
|
|
1780
1851
|
env,
|
|
1781
1852
|
dryRun,
|
|
1782
1853
|
scope,
|
|
1783
1854
|
serverName,
|
|
1784
|
-
execute: opts.execute ?? true
|
|
1785
|
-
run: opts.runCommand ?? runHarnessCommandSync
|
|
1855
|
+
execute: opts.execute ?? true
|
|
1786
1856
|
});
|
|
1787
1857
|
return {
|
|
1788
1858
|
...base,
|
|
@@ -1793,11 +1863,13 @@ function installHarnessSync(harness, mcpUrl, opts = {}) {
|
|
|
1793
1863
|
...existing$1.url ? { currentUrl: existing$1.url } : {}
|
|
1794
1864
|
};
|
|
1795
1865
|
}
|
|
1796
|
-
const
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1866
|
+
const outcome = opts.execute ?? true ? yield {
|
|
1867
|
+
argv,
|
|
1868
|
+
opts: {
|
|
1869
|
+
env,
|
|
1870
|
+
dryRun
|
|
1871
|
+
}
|
|
1872
|
+
} : {
|
|
1801
1873
|
executed: false,
|
|
1802
1874
|
ok: true,
|
|
1803
1875
|
reason: "not-requested"
|
|
@@ -1806,7 +1878,7 @@ function installHarnessSync(harness, mcpUrl, opts = {}) {
|
|
|
1806
1878
|
...base,
|
|
1807
1879
|
ok: outcome.ok,
|
|
1808
1880
|
executed: outcome.executed,
|
|
1809
|
-
...outcome.ok ? {} : { commandError: outcome
|
|
1881
|
+
...outcome.ok ? {} : { commandError: notRunError(outcome) },
|
|
1810
1882
|
alreadyConfigured: false
|
|
1811
1883
|
};
|
|
1812
1884
|
}
|
|
@@ -1898,7 +1970,14 @@ function installHarnessSync(harness, mcpUrl, opts = {}) {
|
|
|
1898
1970
|
* second command must not leave the user with no entry at all without saying
|
|
1899
1971
|
* so.
|
|
1900
1972
|
*/
|
|
1901
|
-
|
|
1973
|
+
/**
|
|
1974
|
+
* What went wrong with a failed command: its stderr, else why it was never
|
|
1975
|
+
* run — so a refusal never reads as "unknown reason" (ENG-6737).
|
|
1976
|
+
*/
|
|
1977
|
+
function notRunError(outcome) {
|
|
1978
|
+
return outcome.stderr ?? (outcome.reason ? `not run: ${outcome.reason}` : void 0);
|
|
1979
|
+
}
|
|
1980
|
+
function* replaceSteps(harness, addArgv, previousUrl, ctx) {
|
|
1902
1981
|
const removeArgv = removeCommandArgv(ctx.scope, ctx.serverName);
|
|
1903
1982
|
const base = {
|
|
1904
1983
|
wrote: false,
|
|
@@ -1914,11 +1993,15 @@ function replaceViaCommand(harness, addArgv, previousUrl, ctx) {
|
|
|
1914
1993
|
ok: true,
|
|
1915
1994
|
executed: false
|
|
1916
1995
|
};
|
|
1917
|
-
const removed =
|
|
1996
|
+
const removed = yield {
|
|
1997
|
+
argv: removeArgv,
|
|
1998
|
+
opts: { env: ctx.env }
|
|
1999
|
+
};
|
|
1918
2000
|
if (!removed.executed) return {
|
|
1919
2001
|
...base,
|
|
1920
2002
|
ok: removed.ok,
|
|
1921
|
-
executed: false
|
|
2003
|
+
executed: false,
|
|
2004
|
+
...removed.ok ? {} : { commandError: notRunError(removed) }
|
|
1922
2005
|
};
|
|
1923
2006
|
if (!removed.ok) return {
|
|
1924
2007
|
...base,
|
|
@@ -1926,21 +2009,26 @@ function replaceViaCommand(harness, addArgv, previousUrl, ctx) {
|
|
|
1926
2009
|
executed: true,
|
|
1927
2010
|
commandError: `could not remove the existing entry: ${removed.stderr ?? "unknown error"}`
|
|
1928
2011
|
};
|
|
1929
|
-
const added =
|
|
2012
|
+
const added = yield {
|
|
2013
|
+
argv: addArgv,
|
|
2014
|
+
opts: { env: ctx.env }
|
|
2015
|
+
};
|
|
1930
2016
|
if (added.ok) return {
|
|
1931
2017
|
...base,
|
|
1932
2018
|
ok: true,
|
|
1933
2019
|
executed: true
|
|
1934
2020
|
};
|
|
1935
|
-
const
|
|
1936
|
-
|
|
2021
|
+
const restore = yield {
|
|
2022
|
+
argv: renderHarnessCommand(harness, previousUrl, ctx.scope, ctx.serverName),
|
|
2023
|
+
opts: { env: ctx.env }
|
|
2024
|
+
};
|
|
1937
2025
|
return {
|
|
1938
2026
|
...base,
|
|
1939
2027
|
ok: false,
|
|
1940
2028
|
executed: true,
|
|
1941
|
-
commandError: added
|
|
2029
|
+
commandError: notRunError(added) ?? "unknown error",
|
|
1942
2030
|
restored: restore.ok && restore.executed,
|
|
1943
|
-
...restore.ok && restore.executed ? {} : { restoreError: restore
|
|
2031
|
+
...restore.ok && restore.executed ? {} : { restoreError: notRunError(restore) ?? "the restore command did not run" }
|
|
1944
2032
|
};
|
|
1945
2033
|
}
|
|
1946
2034
|
/**
|
|
@@ -2102,16 +2190,6 @@ function servedBySessionApi(mcpUrl) {
|
|
|
2102
2190
|
}
|
|
2103
2191
|
/** `…/v1/mcp/w/<url_key>`: the URL already names one workspace (ENG-6300). */
|
|
2104
2192
|
const SCOPED_SUFFIX = /\/w\/[^/]+$/;
|
|
2105
|
-
/** The workspace a scoped MCP URL names (`…/w/<url_key>`), if any. */
|
|
2106
|
-
function workspaceKeyOf(url) {
|
|
2107
|
-
const m = /\/w\/([^/]+)$/.exec(stripSlash(url));
|
|
2108
|
-
if (!m?.[1]) return void 0;
|
|
2109
|
-
try {
|
|
2110
|
-
return decodeURIComponent(m[1]);
|
|
2111
|
-
} catch {
|
|
2112
|
-
return m[1];
|
|
2113
|
-
}
|
|
2114
|
-
}
|
|
2115
2193
|
/** Does this MCP URL already name a workspace? */
|
|
2116
2194
|
function isScopedMcpUrl(url) {
|
|
2117
2195
|
return SCOPED_SUFFIX.test(stripSlash(url));
|
|
@@ -2179,16 +2257,6 @@ function entryState(s, url) {
|
|
|
2179
2257
|
return s.currentUrl === void 0 ? "unrecognized" : "other-url";
|
|
2180
2258
|
}
|
|
2181
2259
|
/**
|
|
2182
|
-
* Allowed client entry names: 1-64 of `A-Za-z0-9_-`, and never starting with
|
|
2183
|
-
* `-`. The name is passed as an argv element to the client's own CLI
|
|
2184
|
-
* (`claude mcp add … <name> <url>`), so a leading `-` would be read there as a
|
|
2185
|
-
* flag — the ENG-4159 argument-injection family.
|
|
2186
|
-
*/
|
|
2187
|
-
const ENTRY_NAME = /^[A-Za-z0-9_-]{1,64}$/;
|
|
2188
|
-
function isValidEntryName(name) {
|
|
2189
|
-
return ENTRY_NAME.test(name) && !name.startsWith("-");
|
|
2190
|
-
}
|
|
2191
|
-
/**
|
|
2192
2260
|
* The scope an install would land in: the requested one, or, for a harness
|
|
2193
2261
|
* that cannot do it, its own default, which is where the fallback goes.
|
|
2194
2262
|
*/
|
|
@@ -2252,21 +2320,6 @@ function clientChoices(detected, scope, url, serverName = DEFAULT_SERVER_NAME) {
|
|
|
2252
2320
|
};
|
|
2253
2321
|
});
|
|
2254
2322
|
}
|
|
2255
|
-
/** Claude Code tool names are `mcp__<entry>__<tool>`; keep that well short. */
|
|
2256
|
-
const BESIDE_NAME_MAX = 30;
|
|
2257
|
-
/**
|
|
2258
|
-
* The name for a second entry beside `serverName`: `<serverName>-<url_key>`,
|
|
2259
|
-
* so it says which workspace it is. Undefined — and "Add beside it" is not
|
|
2260
|
-
* offered — when the target URL names no workspace, or when that name would
|
|
2261
|
-
* be too long or not a valid entry name. It is never shortened: a cut name
|
|
2262
|
-
* could drop the workspace, or give two workspaces the same entry.
|
|
2263
|
-
*/
|
|
2264
|
-
function besideName(serverName, url) {
|
|
2265
|
-
const key = workspaceKeyOf(url);
|
|
2266
|
-
if (!key) return void 0;
|
|
2267
|
-
const name = `${serverName}-${key}`;
|
|
2268
|
-
return name.length <= BESIDE_NAME_MAX && isValidEntryName(name) ? name : void 0;
|
|
2269
|
-
}
|
|
2270
2323
|
/**
|
|
2271
2324
|
* The selected clients whose entry is not this URL's: each needs a decision —
|
|
2272
2325
|
* switch it, add beside it, or leave it — before anything is installed
|
package/dist/cli.js
CHANGED
|
@@ -209,7 +209,7 @@ Examples:
|
|
|
209
209
|
aliases: { y: "yes" }
|
|
210
210
|
},
|
|
211
211
|
loader: async () => {
|
|
212
|
-
const { mcpAddHandler } = await import("./addHandler-
|
|
212
|
+
const { mcpAddHandler } = await import("./addHandler-BqLLDeKp.js");
|
|
213
213
|
return mcpAddHandler;
|
|
214
214
|
}
|
|
215
215
|
});
|
|
@@ -876,7 +876,7 @@ Examples:
|
|
|
876
876
|
|
|
877
877
|
//#endregion
|
|
878
878
|
//#region package.json
|
|
879
|
-
var version = "0.11.
|
|
879
|
+
var version = "0.11.7";
|
|
880
880
|
|
|
881
881
|
//#endregion
|
|
882
882
|
//#region src/app.ts
|