multicorn-shield 1.4.1 → 1.7.0
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/CHANGELOG.md +37 -0
- package/dist/multicorn-proxy.js +504 -90
- package/dist/multicorn-shield.js +323 -90
- package/dist/proxy.cjs +6 -2
- package/dist/proxy.d.cts +1 -1
- package/dist/proxy.d.ts +1 -1
- package/dist/proxy.js +6 -2
- package/dist/shield-extension.js +9 -4
- package/package.json +2 -1
package/dist/multicorn-proxy.js
CHANGED
|
@@ -8,6 +8,7 @@ import { readFileSync, existsSync, statSync } from 'fs';
|
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
import { createRequire } from 'module';
|
|
10
10
|
import { createInterface } from 'readline';
|
|
11
|
+
import { parse, stringify } from 'yaml';
|
|
11
12
|
import 'stream';
|
|
12
13
|
|
|
13
14
|
var __defProp = Object.defineProperty;
|
|
@@ -1346,9 +1347,6 @@ function getClineMcpSettingsPath() {
|
|
|
1346
1347
|
);
|
|
1347
1348
|
}
|
|
1348
1349
|
}
|
|
1349
|
-
function getContinueConfigJsonPath() {
|
|
1350
|
-
return join(homedir(), ".continue", "config.json");
|
|
1351
|
-
}
|
|
1352
1350
|
function platformMenuLabelForSelection(sel) {
|
|
1353
1351
|
const slug = PLATFORM_BY_SELECTION[sel];
|
|
1354
1352
|
if (slug === void 0) return "Unknown";
|
|
@@ -1411,6 +1409,12 @@ async function promptWindsurfIntegrationMode(ask) {
|
|
|
1411
1409
|
return choice === 1 ? "native" : "hosted";
|
|
1412
1410
|
}
|
|
1413
1411
|
async function arrowSelect(options, ask, fallbackLabel) {
|
|
1412
|
+
if (options.length === 1) {
|
|
1413
|
+
const only = options[0] ?? "";
|
|
1414
|
+
process.stderr.write(`${style.violet("\u276F")} ${style.cyan(only)}
|
|
1415
|
+
`);
|
|
1416
|
+
return 0;
|
|
1417
|
+
}
|
|
1414
1418
|
const canRaw = process.stdin.isTTY && typeof process.stdin.setRawMode === "function";
|
|
1415
1419
|
if (!canRaw) {
|
|
1416
1420
|
for (let i = 0; i < options.length; i++) {
|
|
@@ -1463,7 +1467,7 @@ async function arrowSelect(options, ask, fallbackLabel) {
|
|
|
1463
1467
|
cleanup();
|
|
1464
1468
|
clearLines();
|
|
1465
1469
|
const chosen = options.at(idx);
|
|
1466
|
-
if (chosen !== void 0) {
|
|
1470
|
+
if (chosen !== void 0 && options.length > 1) {
|
|
1467
1471
|
process.stderr.write(`${style.violet("\u276F")} ${style.cyan(chosen)}
|
|
1468
1472
|
`);
|
|
1469
1473
|
}
|
|
@@ -1644,13 +1648,56 @@ function writeMcpAddedLine(shortName, filePath) {
|
|
|
1644
1648
|
style.green("\u2713") + ' MCP server "' + shortName + '" added to ' + style.cyan(filePath) + "\n"
|
|
1645
1649
|
);
|
|
1646
1650
|
}
|
|
1647
|
-
|
|
1651
|
+
function sanitiseYamlValue(value) {
|
|
1652
|
+
if (value.length === 0) {
|
|
1653
|
+
return "''";
|
|
1654
|
+
}
|
|
1655
|
+
const needsQuoting = /[:#\n{}]/.test(value) || value.includes("[") || value.includes("]") || value !== value.trim() || value.includes("'");
|
|
1656
|
+
if (!needsQuoting) {
|
|
1657
|
+
return value;
|
|
1658
|
+
}
|
|
1659
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
1660
|
+
}
|
|
1661
|
+
function gitignoreLikelyCoversPath(relPosixPath, gitignoreBody) {
|
|
1662
|
+
const norm = relPosixPath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
1663
|
+
const lines = gitignoreBody.split(/\r?\n/);
|
|
1664
|
+
for (const raw of lines) {
|
|
1665
|
+
const line = raw.trim();
|
|
1666
|
+
if (!line || line.startsWith("#") || line.startsWith("!")) continue;
|
|
1667
|
+
const pat = line.replace(/^\//, "");
|
|
1668
|
+
if (pat === norm || pat === `./${norm}`) return true;
|
|
1669
|
+
if (!pat.includes("*")) {
|
|
1670
|
+
if (pat.endsWith("/")) {
|
|
1671
|
+
const dir = pat.slice(0, -1);
|
|
1672
|
+
if (norm === dir || norm.startsWith(`${dir}/`)) return true;
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
return false;
|
|
1677
|
+
}
|
|
1678
|
+
async function warnIfApiKeyFileNotGitignored(workspaceRoot, relativePosixPath) {
|
|
1679
|
+
const gitignorePath = join(workspaceRoot, ".gitignore");
|
|
1680
|
+
let content;
|
|
1681
|
+
try {
|
|
1682
|
+
content = await readFile(gitignorePath, "utf8");
|
|
1683
|
+
} catch (e) {
|
|
1684
|
+
if (isErrnoException(e) && e.code === "ENOENT") return;
|
|
1685
|
+
throw e;
|
|
1686
|
+
}
|
|
1687
|
+
const norm = relativePosixPath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
1688
|
+
if (gitignoreLikelyCoversPath(norm, content)) return;
|
|
1689
|
+
process.stderr.write(
|
|
1690
|
+
style.yellow("\u26A0") + " Config contains your API key. Add " + style.cyan(norm) + " to .gitignore to avoid committing credentials.\n"
|
|
1691
|
+
);
|
|
1692
|
+
}
|
|
1693
|
+
async function mergeTopLevelKeyedJsonFile(filePath, topLevelKey, shortName, entry, options) {
|
|
1648
1694
|
let root = {};
|
|
1649
1695
|
try {
|
|
1650
1696
|
const raw = await readFile(filePath, "utf8");
|
|
1697
|
+
const toParse = options.stripJsonComments ? raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "") : raw;
|
|
1651
1698
|
let parsed;
|
|
1652
1699
|
try {
|
|
1653
|
-
parsed = JSON.parse(
|
|
1700
|
+
parsed = JSON.parse(toParse);
|
|
1654
1701
|
} catch {
|
|
1655
1702
|
return "parse-error";
|
|
1656
1703
|
}
|
|
@@ -1666,15 +1713,25 @@ async function mergeMcpServersObjectStyle(filePath, shortName, entry) {
|
|
|
1666
1713
|
throw e;
|
|
1667
1714
|
}
|
|
1668
1715
|
}
|
|
1669
|
-
const
|
|
1670
|
-
const
|
|
1671
|
-
|
|
1672
|
-
|
|
1716
|
+
const bucketRaw = root[topLevelKey];
|
|
1717
|
+
const bucket = typeof bucketRaw === "object" && bucketRaw !== null && !Array.isArray(bucketRaw) ? { ...bucketRaw } : {};
|
|
1718
|
+
if (options.onExisting === "skip" && bucket[shortName] !== void 0) {
|
|
1719
|
+
return "unchanged";
|
|
1720
|
+
}
|
|
1721
|
+
bucket[shortName] = entry;
|
|
1722
|
+
root[topLevelKey] = bucket;
|
|
1673
1723
|
await mkdir(dirname(filePath), { recursive: true });
|
|
1674
1724
|
await writeFile(filePath, JSON.stringify(root, null, 2) + "\n", SECRET_JSON_FILE_OPTIONS);
|
|
1675
1725
|
writeMcpAddedLine(shortName, filePath);
|
|
1676
1726
|
return "ok";
|
|
1677
1727
|
}
|
|
1728
|
+
async function mergeMcpServersObjectStyle(filePath, shortName, entry) {
|
|
1729
|
+
const result = await mergeTopLevelKeyedJsonFile(filePath, "mcpServers", shortName, entry, {
|
|
1730
|
+
stripJsonComments: false,
|
|
1731
|
+
onExisting: "overwrite"
|
|
1732
|
+
});
|
|
1733
|
+
return result === "parse-error" ? "parse-error" : "ok";
|
|
1734
|
+
}
|
|
1678
1735
|
async function mergeClaudeDesktopHostedMcpRemote(shortName, proxyUrl, apiKey) {
|
|
1679
1736
|
const entry = {
|
|
1680
1737
|
command: "npx",
|
|
@@ -1682,8 +1739,30 @@ async function mergeClaudeDesktopHostedMcpRemote(shortName, proxyUrl, apiKey) {
|
|
|
1682
1739
|
};
|
|
1683
1740
|
return mergeMcpServersObjectStyle(getClaudeDesktopConfigPath(), shortName, entry);
|
|
1684
1741
|
}
|
|
1685
|
-
async function mergeContinueHostedMcp(shortName, proxyUrl, apiKey) {
|
|
1686
|
-
const
|
|
1742
|
+
async function mergeContinueHostedMcp(workspacePath, shortName, proxyUrl, apiKey) {
|
|
1743
|
+
const dir = join(workspacePath, ".continue", "mcpServers");
|
|
1744
|
+
const filePath = join(dir, `${shortName}.yaml`);
|
|
1745
|
+
const sn = sanitiseYamlValue(shortName);
|
|
1746
|
+
const urlEsc = sanitiseYamlValue(proxyUrl);
|
|
1747
|
+
const authEsc = sanitiseYamlValue(`Bearer ${apiKey}`);
|
|
1748
|
+
const yaml = `name: ${sn}
|
|
1749
|
+
version: 0.0.1
|
|
1750
|
+
schema: v1
|
|
1751
|
+
mcpServers:
|
|
1752
|
+
- name: ${sn}
|
|
1753
|
+
type: streamable-http
|
|
1754
|
+
url: ${urlEsc}
|
|
1755
|
+
headers:
|
|
1756
|
+
Authorization: ${authEsc}
|
|
1757
|
+
`;
|
|
1758
|
+
await mkdir(dir, { recursive: true });
|
|
1759
|
+
await writeFile(filePath, yaml, SECRET_JSON_FILE_OPTIONS);
|
|
1760
|
+
writeMcpAddedLine(shortName, filePath);
|
|
1761
|
+
await warnIfApiKeyFileNotGitignored(workspacePath, `.continue/mcpServers/${shortName}.yaml`);
|
|
1762
|
+
return "ok";
|
|
1763
|
+
}
|
|
1764
|
+
async function mergeCopilotVscodeMcp(workspacePath, shortName, proxyUrl, apiKey) {
|
|
1765
|
+
const filePath = join(workspacePath, ".vscode", "mcp.json");
|
|
1687
1766
|
let root = {};
|
|
1688
1767
|
try {
|
|
1689
1768
|
const raw = await readFile(filePath, "utf8");
|
|
@@ -1705,43 +1784,49 @@ async function mergeContinueHostedMcp(shortName, proxyUrl, apiKey) {
|
|
|
1705
1784
|
throw e;
|
|
1706
1785
|
}
|
|
1707
1786
|
}
|
|
1708
|
-
const
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
return "parse-error";
|
|
1714
|
-
}
|
|
1715
|
-
}
|
|
1716
|
-
const servers = Array.isArray(rawServers) ? rawServers.map((s) => ({ ...s })) : [];
|
|
1717
|
-
const entry = {
|
|
1718
|
-
name: shortName,
|
|
1719
|
-
type: "streamable-http",
|
|
1787
|
+
const serversRaw = root["servers"];
|
|
1788
|
+
const servers = typeof serversRaw === "object" && serversRaw !== null && !Array.isArray(serversRaw) ? { ...serversRaw } : {};
|
|
1789
|
+
const existed = servers[shortName] !== void 0;
|
|
1790
|
+
servers[shortName] = {
|
|
1791
|
+
type: "http",
|
|
1720
1792
|
url: proxyUrl,
|
|
1721
|
-
headers: {
|
|
1722
|
-
Authorization: `Bearer ${apiKey}`
|
|
1723
|
-
}
|
|
1793
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1724
1794
|
};
|
|
1725
|
-
|
|
1726
|
-
if (idx >= 0) {
|
|
1727
|
-
servers[idx] = entry;
|
|
1728
|
-
} else {
|
|
1729
|
-
servers.push(entry);
|
|
1730
|
-
}
|
|
1731
|
-
root["mcpServers"] = servers;
|
|
1795
|
+
root["servers"] = servers;
|
|
1732
1796
|
await mkdir(dirname(filePath), { recursive: true });
|
|
1733
1797
|
await writeFile(filePath, JSON.stringify(root, null, 2) + "\n", SECRET_JSON_FILE_OPTIONS);
|
|
1734
|
-
|
|
1798
|
+
if (existed) {
|
|
1799
|
+
process.stderr.write(
|
|
1800
|
+
style.dim(`Updated existing server entry for ${shortName} in .vscode/mcp.json`) + "\n"
|
|
1801
|
+
);
|
|
1802
|
+
} else {
|
|
1803
|
+
writeMcpAddedLine(shortName, filePath);
|
|
1804
|
+
}
|
|
1805
|
+
await warnIfApiKeyFileNotGitignored(workspacePath, ".vscode/mcp.json");
|
|
1735
1806
|
return "ok";
|
|
1736
1807
|
}
|
|
1737
1808
|
async function mergeKiloCodeProjectMcp(workspacePath, shortName, proxyUrl, apiKey) {
|
|
1738
|
-
const filePath = join(workspacePath, ".
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1809
|
+
const filePath = join(workspacePath, ".kilo", "kilo.jsonc");
|
|
1810
|
+
const result = await mergeTopLevelKeyedJsonFile(
|
|
1811
|
+
filePath,
|
|
1812
|
+
"mcp",
|
|
1813
|
+
shortName,
|
|
1814
|
+
{
|
|
1815
|
+
type: "remote",
|
|
1816
|
+
url: proxyUrl,
|
|
1817
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
1818
|
+
enabled: true
|
|
1819
|
+
},
|
|
1820
|
+
{
|
|
1821
|
+
stripJsonComments: true,
|
|
1822
|
+
onExisting: "skip"
|
|
1743
1823
|
}
|
|
1744
|
-
|
|
1824
|
+
);
|
|
1825
|
+
if (result === "parse-error") return "parse-error";
|
|
1826
|
+
if (result === "ok") {
|
|
1827
|
+
await warnIfApiKeyFileNotGitignored(workspacePath, ".kilo/kilo.jsonc");
|
|
1828
|
+
}
|
|
1829
|
+
return "ok";
|
|
1745
1830
|
}
|
|
1746
1831
|
function printHostedProxyJsonParseWarning(filePath) {
|
|
1747
1832
|
process.stderr.write(
|
|
@@ -1782,7 +1867,7 @@ function printHostedProxyPostWriteHints(platform, shortName) {
|
|
|
1782
1867
|
}
|
|
1783
1868
|
if (platform === "kilo-code") {
|
|
1784
1869
|
process.stderr.write(
|
|
1785
|
-
style.dim("Restart Kilo Code or reload the window so it picks up .
|
|
1870
|
+
style.dim("Restart Kilo Code or reload the window so it picks up .kilo/kilo.jsonc.") + "\n"
|
|
1786
1871
|
);
|
|
1787
1872
|
}
|
|
1788
1873
|
}
|
|
@@ -1799,15 +1884,40 @@ async function applyHostedProxyMcpConfig(platform, proxyUrl, shortName, apiKey,
|
|
|
1799
1884
|
return;
|
|
1800
1885
|
}
|
|
1801
1886
|
if (platform === "github-copilot") {
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1887
|
+
try {
|
|
1888
|
+
const result = await mergeCopilotVscodeMcp(
|
|
1889
|
+
workspacePath,
|
|
1890
|
+
shortName,
|
|
1891
|
+
proxyUrlWithKeyWhenNeeded,
|
|
1892
|
+
apiKey
|
|
1893
|
+
);
|
|
1894
|
+
if (result === "ok") {
|
|
1895
|
+
printHostedProxyPostWriteHints(platform, shortName);
|
|
1896
|
+
return;
|
|
1897
|
+
}
|
|
1898
|
+
printHostedProxyJsonParseWarning(join(workspacePath, ".vscode", "mcp.json"));
|
|
1899
|
+
} catch (err) {
|
|
1900
|
+
process.stderr.write(
|
|
1901
|
+
`${style.yellow("!")} Could not auto-write config: ${err instanceof Error ? err.message : String(err)}
|
|
1902
|
+
`
|
|
1903
|
+
);
|
|
1904
|
+
}
|
|
1807
1905
|
printPlatformSnippet(platform, proxyUrl, shortName, apiKey);
|
|
1808
1906
|
return;
|
|
1809
1907
|
}
|
|
1810
1908
|
if (platform === "goose") {
|
|
1909
|
+
try {
|
|
1910
|
+
const result = await mergeGooseConfig(shortName, proxyUrlWithKeyWhenNeeded, apiKey);
|
|
1911
|
+
if (result === "ok") {
|
|
1912
|
+
printHostedProxyPostWriteHints(platform, shortName);
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1915
|
+
} catch (err) {
|
|
1916
|
+
process.stderr.write(
|
|
1917
|
+
`${style.yellow("!")} Could not auto-write config: ${err instanceof Error ? err.message : String(err)}
|
|
1918
|
+
`
|
|
1919
|
+
);
|
|
1920
|
+
}
|
|
1811
1921
|
printPlatformSnippet(platform, proxyUrl, shortName, apiKey);
|
|
1812
1922
|
return;
|
|
1813
1923
|
}
|
|
@@ -1854,12 +1964,19 @@ async function applyHostedProxyMcpConfig(platform, proxyUrl, shortName, apiKey,
|
|
|
1854
1964
|
apiKey
|
|
1855
1965
|
);
|
|
1856
1966
|
if (result === "parse-error") {
|
|
1857
|
-
printHostedProxyJsonParseWarning(join(workspacePath, ".
|
|
1967
|
+
printHostedProxyJsonParseWarning(join(workspacePath, ".kilo", "kilo.jsonc"));
|
|
1858
1968
|
}
|
|
1859
1969
|
} else if (platform === "continue-dev") {
|
|
1860
|
-
result = await mergeContinueHostedMcp(
|
|
1970
|
+
result = await mergeContinueHostedMcp(
|
|
1971
|
+
workspacePath,
|
|
1972
|
+
shortName,
|
|
1973
|
+
proxyUrlWithKeyWhenNeeded,
|
|
1974
|
+
apiKey
|
|
1975
|
+
);
|
|
1861
1976
|
if (result === "parse-error") {
|
|
1862
|
-
printHostedProxyJsonParseWarning(
|
|
1977
|
+
printHostedProxyJsonParseWarning(
|
|
1978
|
+
join(workspacePath, ".continue", "mcpServers", `${shortName}.yaml`)
|
|
1979
|
+
);
|
|
1863
1980
|
}
|
|
1864
1981
|
} else {
|
|
1865
1982
|
result = await mergeMcpServersObjectStyle(getCursorMcpJsonPath(), shortName, {
|
|
@@ -1883,17 +2000,96 @@ async function applyHostedProxyMcpConfig(platform, proxyUrl, shortName, apiKey,
|
|
|
1883
2000
|
}
|
|
1884
2001
|
printPlatformSnippet(platform, proxyUrl, shortName, apiKey);
|
|
1885
2002
|
}
|
|
1886
|
-
function
|
|
1887
|
-
|
|
1888
|
-
|
|
2003
|
+
function printGooseConfigYamlParseErrorToStderr() {
|
|
2004
|
+
process.stderr.write(
|
|
2005
|
+
style.yellow("!") + " Could not parse ~/.config/goose/config.yaml - check for syntax errors or invalid YAML\n"
|
|
2006
|
+
);
|
|
2007
|
+
}
|
|
2008
|
+
function gooseExtensionYaml(shortName, proxyUrl, bearerHeader) {
|
|
2009
|
+
const sn = sanitiseYamlValue(shortName);
|
|
2010
|
+
const urlEsc = sanitiseYamlValue(proxyUrl);
|
|
2011
|
+
const authEsc = sanitiseYamlValue(bearerHeader);
|
|
2012
|
+
return ` ${sn}:
|
|
2013
|
+
enabled: true
|
|
1889
2014
|
type: streamable_http
|
|
1890
|
-
|
|
2015
|
+
name: ${sn}
|
|
2016
|
+
description: ''
|
|
2017
|
+
uri: ${urlEsc}
|
|
2018
|
+
envs: {}
|
|
2019
|
+
env_keys: []
|
|
1891
2020
|
headers:
|
|
1892
|
-
Authorization: ${
|
|
1893
|
-
enabled: true
|
|
2021
|
+
Authorization: ${authEsc}
|
|
1894
2022
|
timeout: 300
|
|
2023
|
+
socket: null
|
|
2024
|
+
bundled: null
|
|
2025
|
+
available_tools: []
|
|
1895
2026
|
`;
|
|
1896
2027
|
}
|
|
2028
|
+
function gooseHostedProxyYaml(shortName, proxyUrl, bearerHeader) {
|
|
2029
|
+
return `extensions:
|
|
2030
|
+
` + gooseExtensionYaml(shortName, proxyUrl, bearerHeader);
|
|
2031
|
+
}
|
|
2032
|
+
function isYamlPlainObject(value) {
|
|
2033
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2034
|
+
}
|
|
2035
|
+
async function mergeGooseConfig(shortName, proxyUrl, apiKey) {
|
|
2036
|
+
const filePath = join(homedir(), ".config", "goose", "config.yaml");
|
|
2037
|
+
const bearerHeader = `Bearer ${apiKey}`;
|
|
2038
|
+
let content = "";
|
|
2039
|
+
try {
|
|
2040
|
+
content = await readFile(filePath, "utf8");
|
|
2041
|
+
} catch (e) {
|
|
2042
|
+
if (isErrnoException(e) && e.code === "ENOENT") {
|
|
2043
|
+
content = "";
|
|
2044
|
+
} else {
|
|
2045
|
+
throw e;
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
let root;
|
|
2049
|
+
try {
|
|
2050
|
+
const data = content.trim().length === 0 ? {} : parse(content);
|
|
2051
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
2052
|
+
printGooseConfigYamlParseErrorToStderr();
|
|
2053
|
+
return "parse-error";
|
|
2054
|
+
}
|
|
2055
|
+
root = data;
|
|
2056
|
+
} catch {
|
|
2057
|
+
printGooseConfigYamlParseErrorToStderr();
|
|
2058
|
+
return "parse-error";
|
|
2059
|
+
}
|
|
2060
|
+
const extensionsRaw = root["extensions"];
|
|
2061
|
+
let extensions;
|
|
2062
|
+
if (isYamlPlainObject(extensionsRaw)) {
|
|
2063
|
+
extensions = { ...extensionsRaw };
|
|
2064
|
+
} else if (extensionsRaw === void 0) {
|
|
2065
|
+
extensions = {};
|
|
2066
|
+
} else {
|
|
2067
|
+
printGooseConfigYamlParseErrorToStderr();
|
|
2068
|
+
return "parse-error";
|
|
2069
|
+
}
|
|
2070
|
+
extensions[shortName] = {
|
|
2071
|
+
enabled: true,
|
|
2072
|
+
type: "streamable_http",
|
|
2073
|
+
name: shortName,
|
|
2074
|
+
description: "",
|
|
2075
|
+
uri: proxyUrl,
|
|
2076
|
+
envs: {},
|
|
2077
|
+
env_keys: [],
|
|
2078
|
+
headers: { Authorization: bearerHeader },
|
|
2079
|
+
timeout: 300,
|
|
2080
|
+
socket: null,
|
|
2081
|
+
bundled: null,
|
|
2082
|
+
available_tools: []
|
|
2083
|
+
};
|
|
2084
|
+
root["extensions"] = extensions;
|
|
2085
|
+
const out = stringify(root, { indent: 2, lineWidth: 0 });
|
|
2086
|
+
const body = out.endsWith("\n") ? out : `${out}
|
|
2087
|
+
`;
|
|
2088
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
2089
|
+
await writeFile(filePath, body, SECRET_JSON_FILE_OPTIONS);
|
|
2090
|
+
writeMcpAddedLine(shortName, filePath);
|
|
2091
|
+
return "ok";
|
|
2092
|
+
}
|
|
1897
2093
|
function printPlatformSnippet(platform, routingToken, shortName, apiKey) {
|
|
1898
2094
|
const hostedInlinePlatforms = /* @__PURE__ */ new Set([
|
|
1899
2095
|
"cursor",
|
|
@@ -1913,14 +2109,12 @@ function printPlatformSnippet(platform, routingToken, shortName, apiKey) {
|
|
|
1913
2109
|
if (platform === "github-copilot") {
|
|
1914
2110
|
snippetText = JSON.stringify(
|
|
1915
2111
|
{
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
Authorization: authHeader
|
|
1923
|
-
}
|
|
2112
|
+
servers: {
|
|
2113
|
+
[shortName]: {
|
|
2114
|
+
type: "http",
|
|
2115
|
+
url: urlInSnippet,
|
|
2116
|
+
headers: {
|
|
2117
|
+
Authorization: authHeader
|
|
1924
2118
|
}
|
|
1925
2119
|
}
|
|
1926
2120
|
}
|
|
@@ -1959,18 +2153,32 @@ function printPlatformSnippet(platform, routingToken, shortName, apiKey) {
|
|
|
1959
2153
|
2
|
|
1960
2154
|
);
|
|
1961
2155
|
} else if (platform === "continue-dev") {
|
|
2156
|
+
const sn = sanitiseYamlValue(shortName);
|
|
2157
|
+
const urlEsc = sanitiseYamlValue(urlInSnippet);
|
|
2158
|
+
const authEsc = sanitiseYamlValue(authHeader);
|
|
2159
|
+
snippetText = `name: ${sn}
|
|
2160
|
+
version: 0.0.1
|
|
2161
|
+
schema: v1
|
|
2162
|
+
mcpServers:
|
|
2163
|
+
- name: ${sn}
|
|
2164
|
+
type: streamable-http
|
|
2165
|
+
url: ${urlEsc}
|
|
2166
|
+
headers:
|
|
2167
|
+
Authorization: ${authEsc}
|
|
2168
|
+
`;
|
|
2169
|
+
} else if (platform === "kilo-code") {
|
|
1962
2170
|
snippetText = JSON.stringify(
|
|
1963
2171
|
{
|
|
1964
|
-
|
|
1965
|
-
{
|
|
1966
|
-
|
|
1967
|
-
type: "streamable-http",
|
|
2172
|
+
mcp: {
|
|
2173
|
+
[shortName]: {
|
|
2174
|
+
type: "remote",
|
|
1968
2175
|
url: urlInSnippet,
|
|
1969
2176
|
headers: {
|
|
1970
2177
|
Authorization: authHeader
|
|
1971
|
-
}
|
|
2178
|
+
},
|
|
2179
|
+
enabled: true
|
|
1972
2180
|
}
|
|
1973
|
-
|
|
2181
|
+
}
|
|
1974
2182
|
},
|
|
1975
2183
|
null,
|
|
1976
2184
|
2
|
|
@@ -2010,16 +2218,18 @@ function printPlatformSnippet(platform, routingToken, shortName, apiKey) {
|
|
|
2010
2218
|
);
|
|
2011
2219
|
} else if (platform === "kilo-code") {
|
|
2012
2220
|
process.stderr.write(
|
|
2013
|
-
"\n" + style.dim(`Add this to ${join(resolve(process.cwd()), ".
|
|
2221
|
+
"\n" + style.dim(`Add this to ${join(resolve(process.cwd()), ".kilo", "kilo.jsonc")}:`) + "\n\n"
|
|
2014
2222
|
);
|
|
2015
2223
|
} else if (platform === "github-copilot") {
|
|
2016
2224
|
process.stderr.write(
|
|
2017
2225
|
"\n" + style.dim(
|
|
2018
|
-
"
|
|
2226
|
+
"Create .vscode/mcp.json in your workspace root (create the .vscode folder if it does not exist). After saving, reload VS Code and confirm the server appears in Copilot Agent mode under Tools."
|
|
2019
2227
|
) + "\n\n"
|
|
2020
2228
|
);
|
|
2021
2229
|
} else if (platform === "continue-dev") {
|
|
2022
|
-
process.stderr.write(
|
|
2230
|
+
process.stderr.write(
|
|
2231
|
+
"\n" + style.dim(`Save this as .continue/mcpServers/${shortName}.yaml in your workspace root.`) + "\n\n"
|
|
2232
|
+
);
|
|
2023
2233
|
} else if (platform === "goose") {
|
|
2024
2234
|
process.stderr.write(
|
|
2025
2235
|
"\n" + style.dim("Add this to ~/.config/goose/config.yaml under the extensions key.") + "\n\n"
|
|
@@ -2195,7 +2405,7 @@ async function runInit(explicitBaseUrl, options) {
|
|
|
2195
2405
|
}
|
|
2196
2406
|
await warnIfInstalledShieldIsOutdated();
|
|
2197
2407
|
const configuredAgents = [];
|
|
2198
|
-
let currentAgents = collectAgentsFromConfig(existing);
|
|
2408
|
+
let currentAgents = mergeAgentsForUniqueNames(collectAgentsFromConfig(existing));
|
|
2199
2409
|
let lastConfig = {
|
|
2200
2410
|
apiKey,
|
|
2201
2411
|
baseUrl: resolvedBaseUrl,
|
|
@@ -2813,6 +3023,14 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2813
3023
|
}
|
|
2814
3024
|
rl.close();
|
|
2815
3025
|
if (configuredAgents.length > 0) {
|
|
3026
|
+
let mcpPromptLabel2 = function(platformSlug) {
|
|
3027
|
+
const rows = configuredAgents.filter((a) => a.platform === platformSlug);
|
|
3028
|
+
const last = rows[rows.length - 1];
|
|
3029
|
+
if (last === void 0) return "shield-mcp";
|
|
3030
|
+
const s = typeof last.shortName === "string" ? last.shortName.trim() : "";
|
|
3031
|
+
if (s.length > 0) return s;
|
|
3032
|
+
return last.agentName.trim().length > 0 ? last.agentName.trim() : "shield-mcp";
|
|
3033
|
+
};
|
|
2816
3034
|
process.stderr.write("\n" + style.bold(style.violet("Setup complete")) + "\n\n");
|
|
2817
3035
|
for (const agent of configuredAgents) {
|
|
2818
3036
|
const namePart = agent.agentName.length > 0 ? ` - ${style.cyan(agent.agentName)}` : "";
|
|
@@ -2824,14 +3042,6 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2824
3042
|
}
|
|
2825
3043
|
process.stderr.write("\n");
|
|
2826
3044
|
const configuredPlatforms = new Set(configuredAgents.map((a) => a.platform));
|
|
2827
|
-
const cursorMcpPromptLabel = (() => {
|
|
2828
|
-
const rows = configuredAgents.filter((a) => a.platform === "cursor");
|
|
2829
|
-
const last = rows[rows.length - 1];
|
|
2830
|
-
if (last === void 0) return "shield-mcp";
|
|
2831
|
-
const s = typeof last.shortName === "string" ? last.shortName.trim() : "";
|
|
2832
|
-
if (s.length > 0) return s;
|
|
2833
|
-
return last.agentName.trim().length > 0 ? last.agentName.trim() : "shield-mcp";
|
|
2834
|
-
})();
|
|
2835
3045
|
const blocks = [];
|
|
2836
3046
|
if (configuredPlatforms.has("openclaw")) {
|
|
2837
3047
|
blocks.push(
|
|
@@ -2844,33 +3054,39 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2844
3054
|
);
|
|
2845
3055
|
}
|
|
2846
3056
|
if (configuredPlatforms.has("claude-desktop")) {
|
|
3057
|
+
const cdLabel = mcpPromptLabel2("claude-desktop");
|
|
2847
3058
|
blocks.push(
|
|
2848
|
-
"\n" + style.bold("Claude Desktop") +
|
|
3059
|
+
"\n" + style.bold("Claude Desktop") + '\n \u2192 Restart Claude Desktop to load the updated configuration\n \u2192 Confirm connection: click your profile (bottom-left) \u2192 Settings \u2192 Developer\n Check that "' + cdLabel + '" shows a green "running" status\n \u2192 Try it: paste this into Claude Desktop:\n "Use the ' + cdLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2849
3060
|
);
|
|
2850
3061
|
}
|
|
2851
3062
|
if (configuredPlatforms.has("cursor")) {
|
|
3063
|
+
const cursorLabel = mcpPromptLabel2("cursor");
|
|
2852
3064
|
blocks.push(
|
|
2853
|
-
"\n" + style.bold("Cursor") + "\n \u2192 If needed, download Cursor from " + style.cyan("https://www.cursor.com/downloads") + '\n \u2192 Restart Cursor so it loads the MCP server\n \u2192
|
|
3065
|
+
"\n" + style.bold("Cursor") + "\n \u2192 If needed, download Cursor from " + style.cyan("https://www.cursor.com/downloads") + '\n \u2192 Restart Cursor so it loads the MCP server\n \u2192 Confirm connection: open Settings \u2192 Tools & MCPs\n Check that "' + cursorLabel + '" shows a green status indicator\n \u2192 Try it: paste this into Cursor:\n "Use the ' + cursorLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2854
3066
|
);
|
|
2855
3067
|
}
|
|
2856
3068
|
if (configuredPlatforms.has("kilo-code")) {
|
|
3069
|
+
const kiloLabel = mcpPromptLabel2("kilo-code");
|
|
2857
3070
|
blocks.push(
|
|
2858
|
-
"\n" + style.bold("Kilo Code") +
|
|
3071
|
+
"\n" + style.bold("Kilo Code") + '\n \u2192 Restart the editor or reload the window if the MCP server does not appear\n \u2192 Confirm connection: Settings \u2192 Agent Behaviour \u2192 MCP Servers\n \u2192 Try it: paste this into Kilo Code:\n "Use the ' + kiloLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2859
3072
|
);
|
|
2860
3073
|
}
|
|
2861
3074
|
if (configuredPlatforms.has("github-copilot")) {
|
|
3075
|
+
const copilotLabel = mcpPromptLabel2("github-copilot");
|
|
2862
3076
|
blocks.push(
|
|
2863
|
-
"\n" + style.bold("GitHub Copilot") +
|
|
3077
|
+
"\n" + style.bold("GitHub Copilot") + '\n \u2192 Reload the editor window if the MCP server does not appear\n \u2192 Confirm connection: open Copilot chat in Agent mode and confirm the server appears under Tools\n \u2192 Try it: paste this into GitHub Copilot:\n "Use the ' + copilotLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2864
3078
|
);
|
|
2865
3079
|
}
|
|
2866
3080
|
if (configuredPlatforms.has("continue-dev")) {
|
|
3081
|
+
const continueLabel = mcpPromptLabel2("continue-dev");
|
|
2867
3082
|
blocks.push(
|
|
2868
|
-
"\n" + style.bold("Continue") + "\n \u2192 If needed, install Continue from " + style.cyan("https://docs.continue.dev/ide-extensions/install") +
|
|
3083
|
+
"\n" + style.bold("Continue") + "\n \u2192 If needed, install Continue from " + style.cyan("https://docs.continue.dev/ide-extensions/install") + '\n \u2192 Reload VS Code and open Continue agent mode\n \u2192 Confirm connection: Settings \u2192 Tools \u2192 MCP Servers\n \u2192 Try it: paste this into Continue:\n "Use the ' + continueLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2869
3084
|
);
|
|
2870
3085
|
}
|
|
2871
3086
|
if (configuredPlatforms.has("goose")) {
|
|
3087
|
+
const gooseLabel = mcpPromptLabel2("goose");
|
|
2872
3088
|
blocks.push(
|
|
2873
|
-
"\n" + style.bold("Goose") +
|
|
3089
|
+
"\n" + style.bold("Goose") + '\n \u2192 Start a new Goose session after updating config\n \u2192 Confirm connection: check the Extensions page in the sidebar\n \u2192 Try it: paste this into Goose:\n "Use the ' + gooseLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2874
3090
|
);
|
|
2875
3091
|
}
|
|
2876
3092
|
const windsurfNativeConfigured = configuredAgents.some(
|
|
@@ -3438,9 +3654,13 @@ function extractToolCallParams(request) {
|
|
|
3438
3654
|
if (typeof args !== "object" || args === null) return null;
|
|
3439
3655
|
return { name, arguments: args };
|
|
3440
3656
|
}
|
|
3441
|
-
function buildBlockedResponse(id, service,
|
|
3657
|
+
function buildBlockedResponse(id, service, _permissionLevel, dashboardUrl) {
|
|
3442
3658
|
const displayService = capitalize(service);
|
|
3443
|
-
const message = `Action blocked by
|
|
3659
|
+
const message = `Action blocked by Shield
|
|
3660
|
+
|
|
3661
|
+
This agent cannot use ${displayService}.
|
|
3662
|
+
|
|
3663
|
+
Configure permissions: ${dashboardUrl}`;
|
|
3444
3664
|
return {
|
|
3445
3665
|
jsonrpc: "2.0",
|
|
3446
3666
|
id,
|
|
@@ -3974,6 +4194,193 @@ var init_restore = __esm({
|
|
|
3974
4194
|
}
|
|
3975
4195
|
});
|
|
3976
4196
|
|
|
4197
|
+
// package.json
|
|
4198
|
+
var package_default;
|
|
4199
|
+
var init_package = __esm({
|
|
4200
|
+
"package.json"() {
|
|
4201
|
+
package_default = {
|
|
4202
|
+
name: "multicorn-shield",
|
|
4203
|
+
version: "1.7.0",
|
|
4204
|
+
description: "The control layer for AI agents: permissions, consent, spending limits, and audit logging.",
|
|
4205
|
+
license: "MIT",
|
|
4206
|
+
author: "Multicorn AI Pty Ltd",
|
|
4207
|
+
type: "module",
|
|
4208
|
+
main: "./dist/index.cjs",
|
|
4209
|
+
module: "./dist/index.js",
|
|
4210
|
+
types: "./dist/index.d.ts",
|
|
4211
|
+
exports: {
|
|
4212
|
+
".": {
|
|
4213
|
+
import: {
|
|
4214
|
+
types: "./dist/index.d.ts",
|
|
4215
|
+
default: "./dist/index.js"
|
|
4216
|
+
},
|
|
4217
|
+
require: {
|
|
4218
|
+
types: "./dist/index.d.cts",
|
|
4219
|
+
default: "./dist/index.cjs"
|
|
4220
|
+
}
|
|
4221
|
+
},
|
|
4222
|
+
"./proxy": {
|
|
4223
|
+
import: {
|
|
4224
|
+
types: "./dist/proxy.d.ts",
|
|
4225
|
+
default: "./dist/proxy.js"
|
|
4226
|
+
},
|
|
4227
|
+
require: {
|
|
4228
|
+
types: "./dist/proxy.d.cts",
|
|
4229
|
+
default: "./dist/proxy.cjs"
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
},
|
|
4233
|
+
bin: {
|
|
4234
|
+
"multicorn-shield": "./dist/multicorn-shield.js",
|
|
4235
|
+
"multicorn-proxy": "./dist/multicorn-proxy.js"
|
|
4236
|
+
},
|
|
4237
|
+
files: [
|
|
4238
|
+
"dist",
|
|
4239
|
+
"plugins/multicorn-shield",
|
|
4240
|
+
"plugins/windsurf",
|
|
4241
|
+
"plugins/cline",
|
|
4242
|
+
"plugins/gemini-cli",
|
|
4243
|
+
"LICENSE",
|
|
4244
|
+
"README.md",
|
|
4245
|
+
"CHANGELOG.md"
|
|
4246
|
+
],
|
|
4247
|
+
publishConfig: {
|
|
4248
|
+
access: "public",
|
|
4249
|
+
provenance: true
|
|
4250
|
+
},
|
|
4251
|
+
sideEffects: [
|
|
4252
|
+
"dist/index.js",
|
|
4253
|
+
"dist/index.cjs",
|
|
4254
|
+
"dist/badge.js",
|
|
4255
|
+
"src/badge/multicorn-badge.ts"
|
|
4256
|
+
],
|
|
4257
|
+
engines: {
|
|
4258
|
+
node: ">=20"
|
|
4259
|
+
},
|
|
4260
|
+
scripts: {
|
|
4261
|
+
build: "tsup",
|
|
4262
|
+
dev: "tsup --watch",
|
|
4263
|
+
lint: "eslint . --no-warn-ignored && prettier --check .",
|
|
4264
|
+
"lint:fix": "eslint --fix . --no-warn-ignored && prettier --write .",
|
|
4265
|
+
test: "vitest run",
|
|
4266
|
+
"test:watch": "vitest",
|
|
4267
|
+
"test:coverage": "vitest run --coverage",
|
|
4268
|
+
typecheck: "tsc --noEmit",
|
|
4269
|
+
docs: "typedoc",
|
|
4270
|
+
clean: "rm -rf dist coverage docs/api extension-pack",
|
|
4271
|
+
"stage-extension-pack": "rm -rf extension-pack && mkdir -p extension-pack/server && cp manifest.json extension-pack/ && cp icon.png extension-pack/ && cp dist/shield-extension.js extension-pack/server/index.js",
|
|
4272
|
+
"validate:extension": "pnpm run stage-extension-pack && mcpb validate extension-pack/manifest.json",
|
|
4273
|
+
"build:extension": "tsup",
|
|
4274
|
+
"pack:extension": "pnpm run build && pnpm run stage-extension-pack && mcpb validate extension-pack/manifest.json && mcpb pack extension-pack dist/multicorn-shield.mcpb",
|
|
4275
|
+
size: "size-limit",
|
|
4276
|
+
prepublishOnly: "pnpm run clean && pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build",
|
|
4277
|
+
prepare: "husky || true",
|
|
4278
|
+
"release:patch": "npm version patch && pnpm publish",
|
|
4279
|
+
"release:minor": "npm version minor && pnpm publish",
|
|
4280
|
+
"release:major": "npm version major && pnpm publish"
|
|
4281
|
+
},
|
|
4282
|
+
"lint-staged": {
|
|
4283
|
+
"*.ts": [
|
|
4284
|
+
"eslint --fix --no-warn-ignored",
|
|
4285
|
+
"prettier --write"
|
|
4286
|
+
],
|
|
4287
|
+
"*.{json,md}": [
|
|
4288
|
+
"prettier --write"
|
|
4289
|
+
]
|
|
4290
|
+
},
|
|
4291
|
+
dependencies: {
|
|
4292
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
4293
|
+
lit: "^3.2.0",
|
|
4294
|
+
yaml: "^2.8.2",
|
|
4295
|
+
zod: "^4.3.6"
|
|
4296
|
+
},
|
|
4297
|
+
devDependencies: {
|
|
4298
|
+
"@anthropic-ai/mcpb": "^2.1.2",
|
|
4299
|
+
"@eslint/js": "^9.19.0",
|
|
4300
|
+
"@open-wc/testing-helpers": "^3.0.1",
|
|
4301
|
+
"@size-limit/file": "^11.1.6",
|
|
4302
|
+
"@types/node": "^22.0.0",
|
|
4303
|
+
"@vitest/coverage-v8": "^3.0.5",
|
|
4304
|
+
eslint: "^9.19.0",
|
|
4305
|
+
"eslint-config-prettier": "^10.0.1",
|
|
4306
|
+
"eslint-plugin-unicorn": "^57.0.0",
|
|
4307
|
+
globals: "^15.14.0",
|
|
4308
|
+
husky: "^9.1.7",
|
|
4309
|
+
jiti: "^2.4.2",
|
|
4310
|
+
jsdom: "^25.0.1",
|
|
4311
|
+
"lint-staged": "^16.2.7",
|
|
4312
|
+
prettier: "^3.4.2",
|
|
4313
|
+
"size-limit": "^11.1.6",
|
|
4314
|
+
tsup: "^8.3.6",
|
|
4315
|
+
typedoc: "^0.28.17",
|
|
4316
|
+
typescript: "^5.7.3",
|
|
4317
|
+
"typescript-eslint": "^8.22.0",
|
|
4318
|
+
vite: "^7.3.2",
|
|
4319
|
+
vitest: "^3.0.5"
|
|
4320
|
+
},
|
|
4321
|
+
"size-limit": [
|
|
4322
|
+
{
|
|
4323
|
+
path: "dist/index.js",
|
|
4324
|
+
limit: "50 kB",
|
|
4325
|
+
gzip: true
|
|
4326
|
+
},
|
|
4327
|
+
{
|
|
4328
|
+
path: "dist/index.cjs",
|
|
4329
|
+
limit: "50 kB",
|
|
4330
|
+
gzip: true
|
|
4331
|
+
},
|
|
4332
|
+
{
|
|
4333
|
+
path: "dist/badge.js",
|
|
4334
|
+
limit: "5 kB",
|
|
4335
|
+
gzip: true
|
|
4336
|
+
}
|
|
4337
|
+
],
|
|
4338
|
+
keywords: [
|
|
4339
|
+
"ai",
|
|
4340
|
+
"agents",
|
|
4341
|
+
"permissions",
|
|
4342
|
+
"sdk",
|
|
4343
|
+
"typescript",
|
|
4344
|
+
"consent",
|
|
4345
|
+
"spending-limits",
|
|
4346
|
+
"audit-log",
|
|
4347
|
+
"mcp",
|
|
4348
|
+
"shield",
|
|
4349
|
+
"multicorn"
|
|
4350
|
+
],
|
|
4351
|
+
repository: {
|
|
4352
|
+
type: "git",
|
|
4353
|
+
url: "git+https://github.com/Multicorn-AI/multicorn-shield.git"
|
|
4354
|
+
},
|
|
4355
|
+
bugs: {
|
|
4356
|
+
url: "https://github.com/Multicorn-AI/multicorn-shield/issues"
|
|
4357
|
+
},
|
|
4358
|
+
homepage: "https://multicorn.ai",
|
|
4359
|
+
pnpm: {
|
|
4360
|
+
overrides: {
|
|
4361
|
+
vite: ">=7.3.2",
|
|
4362
|
+
flatted: ">=3.4.2",
|
|
4363
|
+
minimatch: ">=10.2.3",
|
|
4364
|
+
rollup: ">=4.59.0",
|
|
4365
|
+
picomatch: ">=4.0.4",
|
|
4366
|
+
"path-to-regexp": ">=8.4.0",
|
|
4367
|
+
"node-forge": ">=1.4.0",
|
|
4368
|
+
"fast-uri": ">=3.1.2"
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
};
|
|
4372
|
+
}
|
|
4373
|
+
});
|
|
4374
|
+
|
|
4375
|
+
// src/package-meta.ts
|
|
4376
|
+
var PACKAGE_VERSION;
|
|
4377
|
+
var init_package_meta = __esm({
|
|
4378
|
+
"src/package-meta.ts"() {
|
|
4379
|
+
init_package();
|
|
4380
|
+
PACKAGE_VERSION = package_default.version;
|
|
4381
|
+
}
|
|
4382
|
+
});
|
|
4383
|
+
|
|
3977
4384
|
// bin/multicorn-shield.ts
|
|
3978
4385
|
var multicorn_shield_exports = {};
|
|
3979
4386
|
__export(multicorn_shield_exports, {
|
|
@@ -4132,6 +4539,7 @@ function printHelp() {
|
|
|
4132
4539
|
" Shield's permission layer.",
|
|
4133
4540
|
"",
|
|
4134
4541
|
"Options:",
|
|
4542
|
+
" --version, -v Print version and exit",
|
|
4135
4543
|
" --verbose, --debug Print extra diagnostics during init (menu selection, agent counts)",
|
|
4136
4544
|
" --api-key <key> Multicorn API key (overrides MULTICORN_API_KEY env var and config file)",
|
|
4137
4545
|
" --log-level <level> Log level: debug | info | warn | error (default: info)",
|
|
@@ -4156,6 +4564,11 @@ async function runCli() {
|
|
|
4156
4564
|
);
|
|
4157
4565
|
return;
|
|
4158
4566
|
}
|
|
4567
|
+
if (first === "--version" || first === "-v") {
|
|
4568
|
+
process.stdout.write(`${PACKAGE_VERSION}
|
|
4569
|
+
`);
|
|
4570
|
+
process.exit(0);
|
|
4571
|
+
}
|
|
4159
4572
|
const cli = parseArgs(process.argv);
|
|
4160
4573
|
const logger = createLogger(cli.logLevel);
|
|
4161
4574
|
if (cli.subcommand === "help") {
|
|
@@ -4302,6 +4715,7 @@ var init_multicorn_shield = __esm({
|
|
|
4302
4715
|
init_logger();
|
|
4303
4716
|
init_consent();
|
|
4304
4717
|
init_restore();
|
|
4718
|
+
init_package_meta();
|
|
4305
4719
|
isDirectRun = process.argv[1] !== void 0 && (import.meta.url.endsWith(process.argv[1]) || import.meta.url === `file://${process.argv[1]}` || import.meta.url.endsWith("/multicorn-shield.js") || import.meta.url.endsWith("/multicorn-shield.ts"));
|
|
4306
4720
|
if (isDirectRun && process.env["VITEST"] === void 0) {
|
|
4307
4721
|
runCli().catch((error) => {
|