@memoraone/mcp 0.1.36 → 0.1.38
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.cjs +687 -384
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var require_package = __commonJS({
|
|
|
30
30
|
"package.json"(exports2, module2) {
|
|
31
31
|
module2.exports = {
|
|
32
32
|
name: "@memoraone/mcp",
|
|
33
|
-
version: "0.1.
|
|
33
|
+
version: "0.1.38",
|
|
34
34
|
type: "module",
|
|
35
35
|
main: "dist/index.cjs",
|
|
36
36
|
bin: {
|
|
@@ -366,7 +366,7 @@ async function acquireLocalLock(lockName, options = {}) {
|
|
|
366
366
|
`[memoraone-mcp] Failed to acquire lock ${lockName} after ${maxRetries} retries`
|
|
367
367
|
);
|
|
368
368
|
}
|
|
369
|
-
await new Promise((
|
|
369
|
+
await new Promise((resolve17) => setTimeout(resolve17, retryDelayMs));
|
|
370
370
|
continue;
|
|
371
371
|
}
|
|
372
372
|
throw err;
|
|
@@ -855,9 +855,9 @@ var MemoraOneHttpError = class extends Error {
|
|
|
855
855
|
};
|
|
856
856
|
|
|
857
857
|
// src/localState/localConnectClient.ts
|
|
858
|
-
async function requestJson(baseUrl, method,
|
|
858
|
+
async function requestJson(baseUrl, method, path21, options = {}) {
|
|
859
859
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
860
|
-
const url = `${baseUrl.replace(/\/+$/, "")}${
|
|
860
|
+
const url = `${baseUrl.replace(/\/+$/, "")}${path21.startsWith("/") ? path21 : `/${path21}`}`;
|
|
861
861
|
const res = await fetchImpl(url, {
|
|
862
862
|
method,
|
|
863
863
|
headers: {
|
|
@@ -1528,8 +1528,8 @@ var StdioLineReader = class {
|
|
|
1528
1528
|
if (this.closed) {
|
|
1529
1529
|
return null;
|
|
1530
1530
|
}
|
|
1531
|
-
return new Promise((
|
|
1532
|
-
this.waiters.push(
|
|
1531
|
+
return new Promise((resolve17) => {
|
|
1532
|
+
this.waiters.push(resolve17);
|
|
1533
1533
|
});
|
|
1534
1534
|
}
|
|
1535
1535
|
/** Re-queue lines read during an intermediate protocol step (e.g. roots/list) for the main bridge loop. */
|
|
@@ -1602,17 +1602,17 @@ async function requestClientRootsListUris(options) {
|
|
|
1602
1602
|
}
|
|
1603
1603
|
|
|
1604
1604
|
// src/cleanup.ts
|
|
1605
|
-
var
|
|
1606
|
-
var
|
|
1605
|
+
var fs11 = __toESM(require("fs/promises"), 1);
|
|
1606
|
+
var path15 = __toESM(require("path"), 1);
|
|
1607
1607
|
var readline2 = __toESM(require("readline/promises"), 1);
|
|
1608
1608
|
var import_node_child_process3 = require("child_process");
|
|
1609
1609
|
var import_node_util3 = require("util");
|
|
1610
1610
|
var import_node_process = require("process");
|
|
1611
1611
|
|
|
1612
1612
|
// src/cursorGlobalMcpConfig.ts
|
|
1613
|
-
var
|
|
1613
|
+
var fs10 = __toESM(require("fs/promises"), 1);
|
|
1614
1614
|
var os4 = __toESM(require("os"), 1);
|
|
1615
|
-
var
|
|
1615
|
+
var path14 = __toESM(require("path"), 1);
|
|
1616
1616
|
var import_node_child_process2 = require("child_process");
|
|
1617
1617
|
var import_node_util2 = require("util");
|
|
1618
1618
|
|
|
@@ -1787,19 +1787,194 @@ async function resolveBindingFromInitializeParams(params, options = {}) {
|
|
|
1787
1787
|
});
|
|
1788
1788
|
}
|
|
1789
1789
|
|
|
1790
|
+
// src/packageExecutionMode.ts
|
|
1791
|
+
var path13 = __toESM(require("path"), 1);
|
|
1792
|
+
|
|
1793
|
+
// src/resolveBuiltCliPath.ts
|
|
1794
|
+
var fs9 = __toESM(require("fs/promises"), 1);
|
|
1795
|
+
var path12 = __toESM(require("path"), 1);
|
|
1796
|
+
var MONOREPO_CLI_REL = path12.join("packages", "mcp", "dist", "cli.cjs");
|
|
1797
|
+
async function pathExists(filePath) {
|
|
1798
|
+
try {
|
|
1799
|
+
await fs9.access(filePath);
|
|
1800
|
+
return true;
|
|
1801
|
+
} catch {
|
|
1802
|
+
return false;
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
async function findMonorepoCliFrom(startDir) {
|
|
1806
|
+
let current = path12.resolve(startDir);
|
|
1807
|
+
const root = path12.parse(current).root;
|
|
1808
|
+
while (true) {
|
|
1809
|
+
const candidate = path12.join(current, MONOREPO_CLI_REL);
|
|
1810
|
+
if (await pathExists(candidate)) {
|
|
1811
|
+
return path12.resolve(candidate);
|
|
1812
|
+
}
|
|
1813
|
+
if (current === root) break;
|
|
1814
|
+
current = path12.dirname(current);
|
|
1815
|
+
}
|
|
1816
|
+
return null;
|
|
1817
|
+
}
|
|
1818
|
+
async function resolveFromRunningScript() {
|
|
1819
|
+
if (!process.argv[1]) return null;
|
|
1820
|
+
const script = path12.resolve(process.argv[1]);
|
|
1821
|
+
const base = path12.basename(script);
|
|
1822
|
+
if ((base === "cli.cjs" || base === "cli.ts" || base === "memoraone-mcp.cjs") && await pathExists(script)) {
|
|
1823
|
+
return script;
|
|
1824
|
+
}
|
|
1825
|
+
const here = path12.dirname(script);
|
|
1826
|
+
const candidates = [
|
|
1827
|
+
path12.join(here, "cli.cjs"),
|
|
1828
|
+
path12.join(here, "..", "dist", "cli.cjs"),
|
|
1829
|
+
path12.join(here, "..", "..", "dist", "cli.cjs")
|
|
1830
|
+
];
|
|
1831
|
+
for (const candidate of candidates) {
|
|
1832
|
+
if (await pathExists(candidate)) {
|
|
1833
|
+
return path12.resolve(candidate);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
return null;
|
|
1837
|
+
}
|
|
1838
|
+
async function resolveBuiltCliPathAsync(options) {
|
|
1839
|
+
const preferRunning = options?.preferRunningScript !== false;
|
|
1840
|
+
if (preferRunning) {
|
|
1841
|
+
const fromRunning = await resolveFromRunningScript();
|
|
1842
|
+
if (fromRunning) return fromRunning;
|
|
1843
|
+
}
|
|
1844
|
+
const searchDirs = [];
|
|
1845
|
+
if (options?.searchFrom !== void 0) {
|
|
1846
|
+
const dirs = Array.isArray(options.searchFrom) ? options.searchFrom : [options.searchFrom];
|
|
1847
|
+
searchDirs.push(...dirs);
|
|
1848
|
+
}
|
|
1849
|
+
searchDirs.push(process.cwd());
|
|
1850
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1851
|
+
for (const dir of searchDirs) {
|
|
1852
|
+
const key = path12.resolve(dir);
|
|
1853
|
+
if (seen.has(key)) continue;
|
|
1854
|
+
seen.add(key);
|
|
1855
|
+
const found = await findMonorepoCliFrom(key);
|
|
1856
|
+
if (found) return found;
|
|
1857
|
+
}
|
|
1858
|
+
if (!preferRunning) {
|
|
1859
|
+
return resolveFromRunningScript();
|
|
1860
|
+
}
|
|
1861
|
+
return null;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
// src/packageExecutionMode.ts
|
|
1865
|
+
var PROD_API_URL = "https://api.memoraone.com";
|
|
1866
|
+
var STAGING_API_URL = "https://memora-api-staging-phbtrzocjq-uk.a.run.app";
|
|
1867
|
+
var STAGING_API_URL_PREFIX = "https://memora-api-staging-";
|
|
1868
|
+
function normalizeApiUrl(url) {
|
|
1869
|
+
return url.trim().replace(/\/+$/, "");
|
|
1870
|
+
}
|
|
1871
|
+
function memoraoneNpmPackageSpec(channel) {
|
|
1872
|
+
return channel === "staging" ? "@memoraone/mcp@staging" : "@memoraone/mcp@latest";
|
|
1873
|
+
}
|
|
1874
|
+
function isMemoraoneNpmPackageSpec(value) {
|
|
1875
|
+
return value === "@memoraone/mcp@staging" || value === "@memoraone/mcp@latest";
|
|
1876
|
+
}
|
|
1877
|
+
function npmPackageChannelFromEnvironment(environment) {
|
|
1878
|
+
return environment === "staging" ? "staging" : "latest";
|
|
1879
|
+
}
|
|
1880
|
+
function cursorEnvironmentFromPackageExecutionMode(mode) {
|
|
1881
|
+
if (mode.kind === "local") return "local";
|
|
1882
|
+
return mode.channel === "staging" ? "staging" : "production";
|
|
1883
|
+
}
|
|
1884
|
+
function npmPackageChannelFromApiUrl(apiUrl) {
|
|
1885
|
+
if (!apiUrl) return "latest";
|
|
1886
|
+
const normalized = normalizeApiUrl(apiUrl);
|
|
1887
|
+
if (normalized === STAGING_API_URL || normalized.startsWith(STAGING_API_URL_PREFIX)) {
|
|
1888
|
+
return "staging";
|
|
1889
|
+
}
|
|
1890
|
+
if (normalized === PROD_API_URL) return "latest";
|
|
1891
|
+
return "latest";
|
|
1892
|
+
}
|
|
1893
|
+
function looksLikeLocalMonorepoCliPath(scriptPath) {
|
|
1894
|
+
const normalized = scriptPath.replace(/\\/g, "/");
|
|
1895
|
+
if (normalized.includes("/node_modules/@memoraone/mcp/")) return false;
|
|
1896
|
+
if (normalized.includes("/.npm/_npx/")) return false;
|
|
1897
|
+
if (normalized.includes("/_npx/")) return false;
|
|
1898
|
+
const base = path13.basename(normalized);
|
|
1899
|
+
if (base === "cli.ts" || base === "cli.cjs" || base === "memoraone-mcp.cjs") {
|
|
1900
|
+
if (normalized.includes("/packages/mcp/dist/") || normalized.includes("/packages/mcp/dist-bin/") || normalized.includes("/packages/mcp/src/")) {
|
|
1901
|
+
return true;
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
return false;
|
|
1905
|
+
}
|
|
1906
|
+
function looksLikePublishedPackagePath(scriptPath) {
|
|
1907
|
+
const normalized = scriptPath.replace(/\\/g, "/");
|
|
1908
|
+
return normalized.includes("/node_modules/@memoraone/mcp/") || normalized.includes("/.npm/_npx/") || /\/_npx\//.test(normalized);
|
|
1909
|
+
}
|
|
1910
|
+
function channelFromEnv(env2) {
|
|
1911
|
+
const explicit = env2.MEMORAONE_NPM_CHANNEL?.trim().toLowerCase() || env2.npm_config_tag?.trim().toLowerCase();
|
|
1912
|
+
if (explicit === "staging") return "staging";
|
|
1913
|
+
if (explicit === "latest") return "latest";
|
|
1914
|
+
return void 0;
|
|
1915
|
+
}
|
|
1916
|
+
async function resolvePackageExecutionMode(options = {}) {
|
|
1917
|
+
if (options.executionMode) return options.executionMode;
|
|
1918
|
+
const env2 = options.env ?? process.env;
|
|
1919
|
+
const scriptPath = options.scriptPath !== void 0 ? options.scriptPath : process.argv[1] ? path13.resolve(process.argv[1]) : null;
|
|
1920
|
+
if (scriptPath && looksLikePublishedPackagePath(scriptPath)) {
|
|
1921
|
+
const channel2 = channelFromEnv(env2) ?? npmPackageChannelFromApiUrl(options.apiUrl);
|
|
1922
|
+
return { kind: "published", channel: channel2 };
|
|
1923
|
+
}
|
|
1924
|
+
if (scriptPath && looksLikeLocalMonorepoCliPath(scriptPath)) {
|
|
1925
|
+
return { kind: "local", cliPath: scriptPath };
|
|
1926
|
+
}
|
|
1927
|
+
if (options.cliPath) {
|
|
1928
|
+
return { kind: "local", cliPath: path13.resolve(options.cliPath) };
|
|
1929
|
+
}
|
|
1930
|
+
const resolveCli = options.resolveBuiltCliPath ?? resolveBuiltCliPathAsync;
|
|
1931
|
+
const builtCli = await resolveCli();
|
|
1932
|
+
if (builtCli && looksLikeLocalMonorepoCliPath(builtCli) && !(scriptPath && looksLikePublishedPackagePath(scriptPath))) {
|
|
1933
|
+
return { kind: "local", cliPath: builtCli };
|
|
1934
|
+
}
|
|
1935
|
+
const channel = channelFromEnv(env2) ?? npmPackageChannelFromApiUrl(options.apiUrl);
|
|
1936
|
+
return { kind: "published", channel };
|
|
1937
|
+
}
|
|
1938
|
+
function setupOptionsFromPackageExecutionMode(mode) {
|
|
1939
|
+
if (mode.kind === "local") {
|
|
1940
|
+
return {
|
|
1941
|
+
cursorEnvironment: "local",
|
|
1942
|
+
devMode: true,
|
|
1943
|
+
npmPackageChannel: "latest",
|
|
1944
|
+
cursorLocalCliPathOverride: mode.cliPath,
|
|
1945
|
+
cliPathOverride: mode.cliPath
|
|
1946
|
+
};
|
|
1947
|
+
}
|
|
1948
|
+
return {
|
|
1949
|
+
cursorEnvironment: cursorEnvironmentFromPackageExecutionMode(mode),
|
|
1950
|
+
devMode: false,
|
|
1951
|
+
npmPackageChannel: mode.channel,
|
|
1952
|
+
cursorLocalCliPathOverride: null,
|
|
1953
|
+
cliPathOverride: null
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
function formatIdeSetupRepairHint(workspaceRoot, mode) {
|
|
1957
|
+
if (mode.kind === "local") {
|
|
1958
|
+
return `Repair with (no new connect code): node ${mode.cliPath} setup-ide-files --all --local --dev --force --workspace-root ${workspaceRoot}`;
|
|
1959
|
+
}
|
|
1960
|
+
const spec = memoraoneNpmPackageSpec(mode.channel);
|
|
1961
|
+
const stagingFlag = mode.channel === "staging" ? " --staging" : "";
|
|
1962
|
+
return `Repair with (no new connect code): npx -y ${spec} setup-ide-files --all${stagingFlag} --force --workspace-root ${workspaceRoot}`;
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1790
1965
|
// src/cursorGlobalMcpConfig.ts
|
|
1791
1966
|
var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
|
|
1792
1967
|
var MEMORAONE_PROD_API_URL = "https://api.memoraone.com";
|
|
1793
1968
|
var MEMORAONE_LOCAL_API_URL = "http://localhost:3001";
|
|
1794
1969
|
var MEMORAONE_STAGING_API_URL = "https://memora-api-staging-phbtrzocjq-uk.a.run.app";
|
|
1795
1970
|
var MEMORAONE_STAGING_API_URL_PREFIX = "https://memora-api-staging-";
|
|
1796
|
-
function
|
|
1971
|
+
function normalizeApiUrl2(url) {
|
|
1797
1972
|
return url.trim().replace(/\/+$/, "");
|
|
1798
1973
|
}
|
|
1799
1974
|
function resolveIdeApiUrl(options) {
|
|
1975
|
+
if (options.apiUrl) return normalizeApiUrl2(options.apiUrl);
|
|
1800
1976
|
if (options.environment === "staging") return MEMORAONE_STAGING_API_URL;
|
|
1801
1977
|
if (options.environment === "production") return MEMORAONE_PROD_API_URL;
|
|
1802
|
-
if (options.apiUrl) return normalizeApiUrl(options.apiUrl);
|
|
1803
1978
|
return MEMORAONE_LOCAL_API_URL;
|
|
1804
1979
|
}
|
|
1805
1980
|
function buildMemoraoneCursorMcpServer(options) {
|
|
@@ -1811,7 +1986,7 @@ function buildMemoraoneCursorMcpServer(options) {
|
|
|
1811
1986
|
MEMORAONE_IDE_TYPE: "cursor"
|
|
1812
1987
|
};
|
|
1813
1988
|
if (options.workspaceRoot !== void 0) {
|
|
1814
|
-
env2[MEMORAONE_WORKSPACE_ROOT_ENV] =
|
|
1989
|
+
env2[MEMORAONE_WORKSPACE_ROOT_ENV] = path14.resolve(options.workspaceRoot);
|
|
1815
1990
|
}
|
|
1816
1991
|
if (options.environment === "local") {
|
|
1817
1992
|
if (!options.cliPath) {
|
|
@@ -1826,15 +2001,16 @@ function buildMemoraoneCursorMcpServer(options) {
|
|
|
1826
2001
|
if (!options.npxPath) {
|
|
1827
2002
|
throw new Error("[setup-ide-files] Cursor MCP config requires a resolved npx path.");
|
|
1828
2003
|
}
|
|
2004
|
+
const channel = options.npmPackageChannel ?? npmPackageChannelFromEnvironment(options.environment);
|
|
1829
2005
|
return {
|
|
1830
2006
|
command: options.npxPath,
|
|
1831
|
-
args: ["-y",
|
|
2007
|
+
args: ["-y", memoraoneNpmPackageSpec(channel)],
|
|
1832
2008
|
env: env2
|
|
1833
2009
|
};
|
|
1834
2010
|
}
|
|
1835
|
-
async function
|
|
2011
|
+
async function pathExists2(filePath) {
|
|
1836
2012
|
try {
|
|
1837
|
-
await
|
|
2013
|
+
await fs10.access(filePath);
|
|
1838
2014
|
return true;
|
|
1839
2015
|
} catch {
|
|
1840
2016
|
return false;
|
|
@@ -1844,17 +2020,17 @@ function stripLeadingLineComments(text) {
|
|
|
1844
2020
|
return text.split("\n").filter((line) => !/^\s*\/\//.test(line)).join("\n");
|
|
1845
2021
|
}
|
|
1846
2022
|
function getKnownCursorGlobalMcpConfigCandidates(homeDir) {
|
|
1847
|
-
return [
|
|
2023
|
+
return [path14.join(homeDir, ".cursor", "mcp.json")];
|
|
1848
2024
|
}
|
|
1849
2025
|
async function detectCursorGlobalMcpConfig(options) {
|
|
1850
2026
|
if (options?.explicitPath) {
|
|
1851
|
-
return { ok: true, path: options.explicitPath, detectedExisting: await
|
|
2027
|
+
return { ok: true, path: options.explicitPath, detectedExisting: await pathExists2(options.explicitPath) };
|
|
1852
2028
|
}
|
|
1853
2029
|
const homeDir = options?.homeDir ?? os4.homedir();
|
|
1854
2030
|
const candidates = getKnownCursorGlobalMcpConfigCandidates(homeDir);
|
|
1855
2031
|
const existing = [];
|
|
1856
2032
|
for (const candidate of candidates) {
|
|
1857
|
-
if (await
|
|
2033
|
+
if (await pathExists2(candidate)) existing.push(candidate);
|
|
1858
2034
|
}
|
|
1859
2035
|
if (existing.length > 1) {
|
|
1860
2036
|
return {
|
|
@@ -1882,10 +2058,10 @@ function formatBackupTimestamp(d = /* @__PURE__ */ new Date()) {
|
|
|
1882
2058
|
}
|
|
1883
2059
|
async function isWorkingNpx(npxPath) {
|
|
1884
2060
|
try {
|
|
1885
|
-
if (!await
|
|
2061
|
+
if (!await pathExists2(npxPath)) return false;
|
|
1886
2062
|
if (process.platform !== "win32") {
|
|
1887
2063
|
try {
|
|
1888
|
-
await
|
|
2064
|
+
await fs10.access(npxPath, fs10.constants.X_OK);
|
|
1889
2065
|
} catch {
|
|
1890
2066
|
return false;
|
|
1891
2067
|
}
|
|
@@ -1907,7 +2083,7 @@ async function resolveNpxPath() {
|
|
|
1907
2083
|
const pathSep = process.platform === "win32" ? ";" : ":";
|
|
1908
2084
|
for (const dir of (process.env.PATH ?? "").split(pathSep)) {
|
|
1909
2085
|
if (!dir) continue;
|
|
1910
|
-
candidates.push(
|
|
2086
|
+
candidates.push(path14.join(dir, npxName));
|
|
1911
2087
|
}
|
|
1912
2088
|
try {
|
|
1913
2089
|
const lookupCmd = process.platform === "win32" ? "where" : "which";
|
|
@@ -1918,7 +2094,7 @@ async function resolveNpxPath() {
|
|
|
1918
2094
|
}
|
|
1919
2095
|
const seen = /* @__PURE__ */ new Set();
|
|
1920
2096
|
for (const candidate of candidates) {
|
|
1921
|
-
const abs =
|
|
2097
|
+
const abs = path14.isAbsolute(candidate) ? candidate : path14.resolve(candidate);
|
|
1922
2098
|
const key = process.platform === "win32" ? abs.toLowerCase() : abs;
|
|
1923
2099
|
if (seen.has(key)) continue;
|
|
1924
2100
|
seen.add(key);
|
|
@@ -1930,12 +2106,14 @@ function mergeCursorRepoMcpConfigObject(existing, writeOptions) {
|
|
|
1930
2106
|
const environment = writeOptions.environment ?? "production";
|
|
1931
2107
|
const base = existing && typeof existing === "object" ? { ...existing } : { mcpServers: {} };
|
|
1932
2108
|
const mcpServers = typeof base.mcpServers === "object" && base.mcpServers !== null && !Array.isArray(base.mcpServers) ? { ...base.mcpServers } : {};
|
|
2109
|
+
delete mcpServers.memoraone;
|
|
1933
2110
|
mcpServers.memoraone = buildMemoraoneCursorMcpServer({
|
|
1934
2111
|
environment,
|
|
1935
2112
|
npxPath: writeOptions.npxPath,
|
|
1936
2113
|
cliPath: writeOptions.cliPath,
|
|
1937
2114
|
workspaceRoot: writeOptions.repoRoot,
|
|
1938
|
-
apiUrl: writeOptions.apiUrl
|
|
2115
|
+
apiUrl: writeOptions.apiUrl,
|
|
2116
|
+
npmPackageChannel: writeOptions.npmPackageChannel
|
|
1939
2117
|
});
|
|
1940
2118
|
return { ...base, mcpServers };
|
|
1941
2119
|
}
|
|
@@ -1949,7 +2127,7 @@ function isManagedMemoraoneCursorServer(server) {
|
|
|
1949
2127
|
if (!server || typeof server !== "object") return false;
|
|
1950
2128
|
const s = server;
|
|
1951
2129
|
if (!Array.isArray(s.args) || s.args.length !== 2) return false;
|
|
1952
|
-
if (s.args[0] !== "-y" || s.args[1]
|
|
2130
|
+
if (s.args[0] !== "-y" || !isMemoraoneNpmPackageSpec(s.args[1])) return false;
|
|
1953
2131
|
const env2 = s.env;
|
|
1954
2132
|
if (!env2 || typeof env2 !== "object") return false;
|
|
1955
2133
|
return memoraoneEnvMatchesManagedCleanupShape(env2);
|
|
@@ -1964,11 +2142,11 @@ function memoraoneEnvMatchesManagedCleanupShape(env2) {
|
|
|
1964
2142
|
return env2.MEMORAONE_IDE_TYPE === "cursor" && isMemoraoneManagedApiUrl(env2.MEMORAONE_API_URL);
|
|
1965
2143
|
}
|
|
1966
2144
|
function getCursorRepoMcpConfigPath(repoRoot) {
|
|
1967
|
-
return
|
|
2145
|
+
return path14.join(repoRoot, ".cursor", "mcp.json");
|
|
1968
2146
|
}
|
|
1969
2147
|
async function readCursorMcpConfigObject(configPath) {
|
|
1970
2148
|
try {
|
|
1971
|
-
const raw = await
|
|
2149
|
+
const raw = await fs10.readFile(configPath, "utf8");
|
|
1972
2150
|
return JSON.parse(stripLeadingLineComments(raw));
|
|
1973
2151
|
} catch (err) {
|
|
1974
2152
|
const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
@@ -1986,21 +2164,21 @@ async function removeMemoraoneFromCursorGlobalConfig(options) {
|
|
|
1986
2164
|
return { changed: true, backupPath: `${configPath}.backup-<timestamp>` };
|
|
1987
2165
|
}
|
|
1988
2166
|
const backupPath = `${configPath}.backup-${formatBackupTimestamp()}`;
|
|
1989
|
-
await
|
|
2167
|
+
await fs10.copyFile(configPath, backupPath);
|
|
1990
2168
|
const mcpServers = typeof parsed2.mcpServers === "object" && parsed2.mcpServers !== null && !Array.isArray(parsed2.mcpServers) ? { ...parsed2.mcpServers } : {};
|
|
1991
2169
|
delete mcpServers.memoraone;
|
|
1992
2170
|
const hasOtherServers = Object.keys(mcpServers).length > 0;
|
|
1993
2171
|
if (!hasOtherServers) {
|
|
1994
|
-
await
|
|
2172
|
+
await fs10.unlink(configPath);
|
|
1995
2173
|
return { changed: true, backupPath };
|
|
1996
2174
|
}
|
|
1997
2175
|
const next = { ...parsed2, mcpServers };
|
|
1998
|
-
await
|
|
1999
|
-
await
|
|
2176
|
+
await fs10.mkdir(path14.dirname(configPath), { recursive: true });
|
|
2177
|
+
await fs10.writeFile(configPath, JSON.stringify(next, null, 2) + "\n", "utf8");
|
|
2000
2178
|
return { changed: true, backupPath };
|
|
2001
2179
|
}
|
|
2002
2180
|
async function auditCursorMcpConfig(options) {
|
|
2003
|
-
const repoRoot =
|
|
2181
|
+
const repoRoot = path14.resolve(options?.repoRoot ?? process.cwd());
|
|
2004
2182
|
const repoConfigPath = getCursorRepoMcpConfigPath(repoRoot);
|
|
2005
2183
|
const globalDetection = await detectCursorGlobalMcpConfig({
|
|
2006
2184
|
homeDir: options?.homeDir,
|
|
@@ -2058,45 +2236,46 @@ function logCursorMcpConfigAudit(prefix, audit) {
|
|
|
2058
2236
|
function logCursorMcpCliSummary(info, dryRun, opts) {
|
|
2059
2237
|
const { repoConfigPath, repoOutcome, npxPath, cliPath, repoBackupPath, globalConfigPath, globalMemoraoneRemoved, globalBackupPath } = info;
|
|
2060
2238
|
const interactive = opts?.forInteractivePostSetup === true;
|
|
2061
|
-
|
|
2239
|
+
const println = opts?.println ?? console.log;
|
|
2240
|
+
println(`[setup-ide-files] Cursor repo MCP config: ${repoConfigPath}`);
|
|
2062
2241
|
if (cliPath) {
|
|
2063
|
-
|
|
2242
|
+
println(`[setup-ide-files] Resolved local CLI: ${cliPath}`);
|
|
2064
2243
|
} else if (npxPath) {
|
|
2065
|
-
|
|
2244
|
+
println(`[setup-ide-files] Resolved npx: ${npxPath}`);
|
|
2066
2245
|
}
|
|
2067
2246
|
if (repoBackupPath) {
|
|
2068
|
-
|
|
2247
|
+
println(`[setup-ide-files] Cursor repo MCP config backup: ${repoBackupPath}`);
|
|
2069
2248
|
}
|
|
2070
2249
|
if (!interactive) {
|
|
2071
2250
|
if (repoOutcome === "created") {
|
|
2072
|
-
|
|
2251
|
+
println(
|
|
2073
2252
|
dryRun ? `[setup-ide-files] Cursor repo MCP config would be created: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config created: ${repoConfigPath}`
|
|
2074
2253
|
);
|
|
2075
2254
|
} else if (repoOutcome === "updated") {
|
|
2076
|
-
|
|
2255
|
+
println(
|
|
2077
2256
|
dryRun ? `[setup-ide-files] Cursor repo MCP config would be updated: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config updated: ${repoConfigPath}`
|
|
2078
2257
|
);
|
|
2079
2258
|
} else if (repoOutcome === "skipped") {
|
|
2080
|
-
|
|
2259
|
+
println(`[setup-ide-files] Cursor repo MCP config unchanged: ${repoConfigPath}`);
|
|
2081
2260
|
}
|
|
2082
2261
|
}
|
|
2083
2262
|
if (globalMemoraoneRemoved && globalConfigPath) {
|
|
2084
|
-
|
|
2263
|
+
println(
|
|
2085
2264
|
dryRun ? `[setup-ide-files] Would remove memoraone from Cursor global MCP config: ${globalConfigPath}` : `[setup-ide-files] Removed memoraone from Cursor global MCP config: ${globalConfigPath}`
|
|
2086
2265
|
);
|
|
2087
2266
|
if (globalBackupPath) {
|
|
2088
|
-
|
|
2267
|
+
println(`[setup-ide-files] Cursor global MCP config backup: ${globalBackupPath}`);
|
|
2089
2268
|
}
|
|
2090
2269
|
} else if (globalConfigPath) {
|
|
2091
|
-
|
|
2270
|
+
println(
|
|
2092
2271
|
`[setup-ide-files] Cursor global MCP config unchanged (no managed memoraone to remove): ${globalConfigPath}`
|
|
2093
2272
|
);
|
|
2094
2273
|
}
|
|
2095
|
-
|
|
2274
|
+
println(
|
|
2096
2275
|
"[setup-ide-files] Each Cursor window uses this repo\u2019s .cursor/mcp.json (separate MCP process per repo)."
|
|
2097
2276
|
);
|
|
2098
2277
|
if (!interactive) {
|
|
2099
|
-
|
|
2278
|
+
println(
|
|
2100
2279
|
"[setup-ide-files] Fully quit Cursor and reopen this repo for MCP changes to take effect."
|
|
2101
2280
|
);
|
|
2102
2281
|
}
|
|
@@ -2177,7 +2356,7 @@ async function defaultListSocketPaths(projectId) {
|
|
|
2177
2356
|
const baseDir = getMcpBaseDir();
|
|
2178
2357
|
let entries;
|
|
2179
2358
|
try {
|
|
2180
|
-
entries = await
|
|
2359
|
+
entries = await fs11.readdir(baseDir);
|
|
2181
2360
|
} catch (err) {
|
|
2182
2361
|
const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
2183
2362
|
if (code === "ENOENT") {
|
|
@@ -2190,7 +2369,7 @@ async function defaultListSocketPaths(projectId) {
|
|
|
2190
2369
|
if (!name.endsWith(".sock") || !isMemoraoneSocketFilename(name)) {
|
|
2191
2370
|
continue;
|
|
2192
2371
|
}
|
|
2193
|
-
const socketPath =
|
|
2372
|
+
const socketPath = path15.join(baseDir, name);
|
|
2194
2373
|
if (projectId === null) {
|
|
2195
2374
|
paths.push(socketPath);
|
|
2196
2375
|
continue;
|
|
@@ -2210,11 +2389,11 @@ async function defaultListSocketPaths(projectId) {
|
|
|
2210
2389
|
return paths.sort();
|
|
2211
2390
|
}
|
|
2212
2391
|
async function defaultListSocketPathsForWorkspaceRoot(workspaceRoot) {
|
|
2213
|
-
const resolvedRoot =
|
|
2392
|
+
const resolvedRoot = path15.resolve(workspaceRoot);
|
|
2214
2393
|
const baseDir = getMcpBaseDir();
|
|
2215
2394
|
let entries;
|
|
2216
2395
|
try {
|
|
2217
|
-
entries = await
|
|
2396
|
+
entries = await fs11.readdir(baseDir);
|
|
2218
2397
|
} catch (err) {
|
|
2219
2398
|
const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
2220
2399
|
if (code === "ENOENT") {
|
|
@@ -2227,10 +2406,10 @@ async function defaultListSocketPathsForWorkspaceRoot(workspaceRoot) {
|
|
|
2227
2406
|
if (!name.endsWith(".sock") || !isHashSocketFilename(name)) {
|
|
2228
2407
|
continue;
|
|
2229
2408
|
}
|
|
2230
|
-
const socketPath =
|
|
2409
|
+
const socketPath = path15.join(baseDir, name);
|
|
2231
2410
|
const record = readBindingSidecarRecord(socketPath);
|
|
2232
2411
|
if (!record?.workspaceRoot) continue;
|
|
2233
|
-
if (
|
|
2412
|
+
if (path15.resolve(record.workspaceRoot) === resolvedRoot) {
|
|
2234
2413
|
paths.push(socketPath);
|
|
2235
2414
|
}
|
|
2236
2415
|
}
|
|
@@ -2239,21 +2418,21 @@ async function defaultListSocketPathsForWorkspaceRoot(workspaceRoot) {
|
|
|
2239
2418
|
async function filterSocketPathsByIdeForCleanup(socketPaths, projectId, ide, workspaceRoot) {
|
|
2240
2419
|
if (ide === void 0) return socketPaths;
|
|
2241
2420
|
const normalizedProjectId = projectId.trim().toLowerCase();
|
|
2242
|
-
const resolvedRoot = workspaceRoot ?
|
|
2421
|
+
const resolvedRoot = workspaceRoot ? path15.resolve(workspaceRoot) : null;
|
|
2243
2422
|
const filtered = [];
|
|
2244
2423
|
for (const socketPath of socketPaths) {
|
|
2245
|
-
const
|
|
2246
|
-
if (isLegacySocketFilename(
|
|
2247
|
-
if (isSocketFilenameForProjectAndIde(
|
|
2424
|
+
const basename11 = path15.basename(socketPath);
|
|
2425
|
+
if (isLegacySocketFilename(basename11)) {
|
|
2426
|
+
if (isSocketFilenameForProjectAndIde(basename11, normalizedProjectId, ide)) {
|
|
2248
2427
|
filtered.push(socketPath);
|
|
2249
2428
|
}
|
|
2250
2429
|
continue;
|
|
2251
2430
|
}
|
|
2252
|
-
if (isHashSocketFilename(
|
|
2431
|
+
if (isHashSocketFilename(basename11)) {
|
|
2253
2432
|
const record = readBindingSidecarRecord(socketPath);
|
|
2254
2433
|
if (!record || record.ideType !== ide) continue;
|
|
2255
2434
|
const sameProject = record.projectId.trim().toLowerCase() === normalizedProjectId;
|
|
2256
|
-
const sameWorkspace = resolvedRoot !== null &&
|
|
2435
|
+
const sameWorkspace = resolvedRoot !== null && path15.resolve(record.workspaceRoot) === resolvedRoot;
|
|
2257
2436
|
if (sameProject || sameWorkspace) {
|
|
2258
2437
|
filtered.push(socketPath);
|
|
2259
2438
|
}
|
|
@@ -2265,9 +2444,9 @@ async function defaultKillProcess(pid) {
|
|
|
2265
2444
|
process.kill(pid, "SIGTERM");
|
|
2266
2445
|
}
|
|
2267
2446
|
async function defaultRemoveSocket(socketPath) {
|
|
2268
|
-
await
|
|
2447
|
+
await fs11.unlink(socketPath);
|
|
2269
2448
|
try {
|
|
2270
|
-
await
|
|
2449
|
+
await fs11.unlink(bindingSidecarPath(socketPath));
|
|
2271
2450
|
} catch {
|
|
2272
2451
|
}
|
|
2273
2452
|
}
|
|
@@ -2285,7 +2464,7 @@ async function defaultConfirm(message) {
|
|
|
2285
2464
|
}
|
|
2286
2465
|
async function resolveCleanupTarget(cwd2) {
|
|
2287
2466
|
try {
|
|
2288
|
-
const binding = await resolveAuthoritativeBinding([
|
|
2467
|
+
const binding = await resolveAuthoritativeBinding([path15.resolve(cwd2)]);
|
|
2289
2468
|
return {
|
|
2290
2469
|
workspaceRoot: binding.workspaceRoot,
|
|
2291
2470
|
repositoryBindingId: binding.repositoryBindingId,
|
|
@@ -2463,7 +2642,7 @@ async function runCleanup(opts) {
|
|
|
2463
2642
|
projectIds.add(proc.projectId);
|
|
2464
2643
|
}
|
|
2465
2644
|
for (const socketPath of socketPaths) {
|
|
2466
|
-
const id = extractProjectIdFromSocketFilename(
|
|
2645
|
+
const id = extractProjectIdFromSocketFilename(path15.basename(socketPath));
|
|
2467
2646
|
if (id) {
|
|
2468
2647
|
projectIds.add(id);
|
|
2469
2648
|
continue;
|
|
@@ -2649,9 +2828,9 @@ function summarizeJsonRpcMethod(line) {
|
|
|
2649
2828
|
}
|
|
2650
2829
|
}
|
|
2651
2830
|
function connectWithRetry(socketPath, log, maxRetries, retryDelayMs, connect2) {
|
|
2652
|
-
return new Promise((
|
|
2831
|
+
return new Promise((resolve17, reject) => {
|
|
2653
2832
|
const tryConnect = (attempt) => {
|
|
2654
|
-
connect2(socketPath).then(
|
|
2833
|
+
connect2(socketPath).then(resolve17).catch((err) => {
|
|
2655
2834
|
if (attempt >= maxRetries) {
|
|
2656
2835
|
reject(err);
|
|
2657
2836
|
return;
|
|
@@ -2767,8 +2946,8 @@ var BridgeDaemonRouter = class {
|
|
|
2767
2946
|
this.maxRetries = options.maxRetries ?? 5;
|
|
2768
2947
|
this.retryDelayMs = options.retryDelayMs ?? 200;
|
|
2769
2948
|
this.lineReader = options.lineReader ?? null;
|
|
2770
|
-
this.connectImpl = options.connect ?? ((socketPath) => new Promise((
|
|
2771
|
-
const socket = net.connect(socketPath, () =>
|
|
2949
|
+
this.connectImpl = options.connect ?? ((socketPath) => new Promise((resolve17, reject) => {
|
|
2950
|
+
const socket = net.connect(socketPath, () => resolve17(socket));
|
|
2772
2951
|
socket.on("error", reject);
|
|
2773
2952
|
}));
|
|
2774
2953
|
this.spawnDaemonImpl = options.spawnDaemon ?? (async (binding) => {
|
|
@@ -3032,12 +3211,14 @@ async function runBridgeProxy(options) {
|
|
|
3032
3211
|
// src/setupIdeFiles.ts
|
|
3033
3212
|
var fs13 = __toESM(require("fs/promises"), 1);
|
|
3034
3213
|
var os6 = __toESM(require("os"), 1);
|
|
3035
|
-
var
|
|
3214
|
+
var path17 = __toESM(require("path"), 1);
|
|
3215
|
+
var import_node_crypto5 = require("crypto");
|
|
3036
3216
|
|
|
3037
3217
|
// src/jetbrainsMcpConfig.ts
|
|
3038
|
-
var
|
|
3218
|
+
var fs12 = __toESM(require("fs/promises"), 1);
|
|
3039
3219
|
var os5 = __toESM(require("os"), 1);
|
|
3040
|
-
var
|
|
3220
|
+
var path16 = __toESM(require("path"), 1);
|
|
3221
|
+
var import_node_crypto4 = require("crypto");
|
|
3041
3222
|
var import_node_child_process5 = require("child_process");
|
|
3042
3223
|
|
|
3043
3224
|
// src/configUtils.ts
|
|
@@ -3059,7 +3240,6 @@ function resolveApiUrl(env2) {
|
|
|
3059
3240
|
}
|
|
3060
3241
|
|
|
3061
3242
|
// src/jetbrainsMcpConfig.ts
|
|
3062
|
-
var PROD_API_URL = "https://api.memoraone.com";
|
|
3063
3243
|
var JETBRAINS_DEBUG_ENV_VARS = [
|
|
3064
3244
|
"MEMORAONE_DEBUG_INIT",
|
|
3065
3245
|
"MEMORAONE_DEBUG_MINIMAL_TOOLS",
|
|
@@ -3069,9 +3249,9 @@ var JETBRAINS_DEBUG_ENV_VARS = [
|
|
|
3069
3249
|
function stripLeadingLineComments2(text) {
|
|
3070
3250
|
return text.split("\n").filter((line) => !/^\s*\/\//.test(line)).join("\n");
|
|
3071
3251
|
}
|
|
3072
|
-
async function
|
|
3252
|
+
async function pathExists3(filePath) {
|
|
3073
3253
|
try {
|
|
3074
|
-
await
|
|
3254
|
+
await fs12.access(filePath);
|
|
3075
3255
|
return true;
|
|
3076
3256
|
} catch {
|
|
3077
3257
|
return false;
|
|
@@ -3082,12 +3262,12 @@ function formatJetBrainsBackupTimestamp(d = /* @__PURE__ */ new Date()) {
|
|
|
3082
3262
|
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
3083
3263
|
}
|
|
3084
3264
|
function getJetBrainsGlobalMcpConfigPath(homeDir) {
|
|
3085
|
-
return
|
|
3265
|
+
return path16.join(homeDir, ".ai", "mcp", "mcp.json");
|
|
3086
3266
|
}
|
|
3087
3267
|
function getJetBrainsProjectMcpConfigPaths(repoRoot) {
|
|
3088
3268
|
return [
|
|
3089
|
-
{ kind: "project-ai", path:
|
|
3090
|
-
{ kind: "project-ij", path:
|
|
3269
|
+
{ kind: "project-ai", path: path16.join(repoRoot, ".ai", "mcp", "mcp.json") },
|
|
3270
|
+
{ kind: "project-ij", path: path16.join(repoRoot, ".ij", "mcp", "mcp.json") }
|
|
3091
3271
|
];
|
|
3092
3272
|
}
|
|
3093
3273
|
function getKnownJetBrainsMcpConfigLocations(homeDir, repoRoot) {
|
|
@@ -3097,17 +3277,21 @@ function getKnownJetBrainsMcpConfigLocations(homeDir, repoRoot) {
|
|
|
3097
3277
|
];
|
|
3098
3278
|
}
|
|
3099
3279
|
async function isZeroByteConfigFile(filePath) {
|
|
3100
|
-
if (!await
|
|
3101
|
-
const stat4 = await
|
|
3280
|
+
if (!await pathExists3(filePath)) return false;
|
|
3281
|
+
const stat4 = await fs12.stat(filePath);
|
|
3102
3282
|
return stat4.size === 0;
|
|
3103
3283
|
}
|
|
3104
3284
|
function buildMemoraoneJetBrainsMcpServer(options) {
|
|
3285
|
+
const environment = options.environment ?? (options.devMode ? "local" : "production");
|
|
3105
3286
|
const env2 = {
|
|
3106
|
-
MEMORAONE_API_URL:
|
|
3287
|
+
MEMORAONE_API_URL: resolveIdeApiUrl({
|
|
3288
|
+
environment,
|
|
3289
|
+
apiUrl: options.apiUrl ?? (environment === "local" ? DEV_API_URL : void 0)
|
|
3290
|
+
}),
|
|
3107
3291
|
MEMORAONE_IDE_TYPE: "jetbrains",
|
|
3108
|
-
[MEMORAONE_WORKSPACE_ROOT_ENV]:
|
|
3292
|
+
[MEMORAONE_WORKSPACE_ROOT_ENV]: path16.resolve(options.workspaceRoot)
|
|
3109
3293
|
};
|
|
3110
|
-
if (options.devMode) {
|
|
3294
|
+
if (environment === "local" || options.devMode) {
|
|
3111
3295
|
env2.MEMORAONE_DEV_MODE = "1";
|
|
3112
3296
|
}
|
|
3113
3297
|
if ("MEMORAONE_M1_PATH" in env2 || "MEMORAONE_API_KEY" in env2) {
|
|
@@ -3122,9 +3306,28 @@ function buildMemoraoneJetBrainsMcpServer(options) {
|
|
|
3122
3306
|
function mergeJetBrainsMcpConfigObject(existing, memoraone) {
|
|
3123
3307
|
const base = existing && typeof existing === "object" ? { ...existing } : { mcpServers: {} };
|
|
3124
3308
|
const mcpServers = typeof base.mcpServers === "object" && base.mcpServers !== null && !Array.isArray(base.mcpServers) ? { ...base.mcpServers } : {};
|
|
3309
|
+
delete mcpServers.memoraone;
|
|
3125
3310
|
mcpServers.memoraone = memoraone;
|
|
3126
3311
|
return { ...base, mcpServers };
|
|
3127
3312
|
}
|
|
3313
|
+
async function writeJetBrainsMcpJsonAtomic(filePath, content) {
|
|
3314
|
+
const dir = path16.dirname(filePath);
|
|
3315
|
+
await fs12.mkdir(dir, { recursive: true });
|
|
3316
|
+
const tmpPath = path16.join(
|
|
3317
|
+
dir,
|
|
3318
|
+
`.${path16.basename(filePath)}.${process.pid}.${(0, import_node_crypto4.randomBytes)(8).toString("hex")}.tmp`
|
|
3319
|
+
);
|
|
3320
|
+
try {
|
|
3321
|
+
await fs12.writeFile(tmpPath, content, "utf8");
|
|
3322
|
+
await fs12.rename(tmpPath, filePath);
|
|
3323
|
+
} catch (err) {
|
|
3324
|
+
try {
|
|
3325
|
+
await fs12.unlink(tmpPath);
|
|
3326
|
+
} catch {
|
|
3327
|
+
}
|
|
3328
|
+
throw err;
|
|
3329
|
+
}
|
|
3330
|
+
}
|
|
3128
3331
|
function memoraoneServerMatches(server, expected) {
|
|
3129
3332
|
if (!server || typeof server !== "object") return false;
|
|
3130
3333
|
const s = server;
|
|
@@ -3160,13 +3363,13 @@ function validateJetBrainsMcpConfig(parsed2, expected) {
|
|
|
3160
3363
|
}
|
|
3161
3364
|
}
|
|
3162
3365
|
async function readJsonConfig(filePath) {
|
|
3163
|
-
const raw = await
|
|
3366
|
+
const raw = await fs12.readFile(filePath, "utf8");
|
|
3164
3367
|
if (raw.trim() === "") return null;
|
|
3165
3368
|
return JSON.parse(stripLeadingLineComments2(raw));
|
|
3166
3369
|
}
|
|
3167
3370
|
async function backupConfigFile(filePath) {
|
|
3168
3371
|
const backupPath = `${filePath}.bak-${formatJetBrainsBackupTimestamp()}`;
|
|
3169
|
-
await
|
|
3372
|
+
await fs12.copyFile(filePath, backupPath);
|
|
3170
3373
|
return backupPath;
|
|
3171
3374
|
}
|
|
3172
3375
|
async function repairZeroByteConfigFile(filePath, dryRun) {
|
|
@@ -3177,7 +3380,7 @@ async function repairZeroByteConfigFile(filePath, dryRun) {
|
|
|
3177
3380
|
return { repaired: true, backupPath: `${filePath}.bak-<timestamp>` };
|
|
3178
3381
|
}
|
|
3179
3382
|
const backupPath = await backupConfigFile(filePath);
|
|
3180
|
-
await
|
|
3383
|
+
await fs12.unlink(filePath);
|
|
3181
3384
|
return { repaired: true, backupPath };
|
|
3182
3385
|
}
|
|
3183
3386
|
function configHasMemoraone(parsed2) {
|
|
@@ -3188,7 +3391,7 @@ function configHasMemoraone(parsed2) {
|
|
|
3188
3391
|
}
|
|
3189
3392
|
async function removeMemoraoneFromProjectConfig(options) {
|
|
3190
3393
|
const { configPath, dryRun } = options;
|
|
3191
|
-
if (!await
|
|
3394
|
+
if (!await pathExists3(configPath)) {
|
|
3192
3395
|
return { changed: false };
|
|
3193
3396
|
}
|
|
3194
3397
|
let parsed2 = null;
|
|
@@ -3208,30 +3411,31 @@ async function removeMemoraoneFromProjectConfig(options) {
|
|
|
3208
3411
|
delete mcpServers.memoraone;
|
|
3209
3412
|
const hasOtherServers = Object.keys(mcpServers).length > 0;
|
|
3210
3413
|
if (!hasOtherServers) {
|
|
3211
|
-
await
|
|
3414
|
+
await fs12.unlink(configPath);
|
|
3212
3415
|
return { changed: true, backupPath };
|
|
3213
3416
|
}
|
|
3214
3417
|
const next = { ...parsed2, mcpServers };
|
|
3215
|
-
await
|
|
3216
|
-
await
|
|
3418
|
+
await fs12.mkdir(path16.dirname(configPath), { recursive: true });
|
|
3419
|
+
await fs12.writeFile(configPath, JSON.stringify(next, null, 2) + "\n", "utf8");
|
|
3217
3420
|
return { changed: true, backupPath };
|
|
3218
3421
|
}
|
|
3219
3422
|
async function resolveLocalCliPathAsync() {
|
|
3220
|
-
const here = process.argv[1] ?
|
|
3423
|
+
const here = process.argv[1] ? path16.dirname(path16.resolve(process.argv[1])) : process.cwd();
|
|
3221
3424
|
const candidates = [
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3425
|
+
path16.join(here, "cli.cjs"),
|
|
3426
|
+
path16.join(here, "..", "dist", "cli.cjs"),
|
|
3427
|
+
path16.join(here, "..", "..", "dist", "cli.cjs")
|
|
3225
3428
|
];
|
|
3226
3429
|
for (const candidate of candidates) {
|
|
3227
|
-
if (await
|
|
3228
|
-
return
|
|
3430
|
+
if (await pathExists3(candidate)) {
|
|
3431
|
+
return path16.resolve(candidate);
|
|
3229
3432
|
}
|
|
3230
3433
|
}
|
|
3231
3434
|
return null;
|
|
3232
3435
|
}
|
|
3233
3436
|
async function buildJetBrainsMemoraoneServer(options) {
|
|
3234
|
-
|
|
3437
|
+
const environment = options.environment ?? (options.devMode ? "local" : "production");
|
|
3438
|
+
if (environment === "local" || options.devMode) {
|
|
3235
3439
|
let cliPath = options.cliPathOverride;
|
|
3236
3440
|
if (cliPath === void 0) {
|
|
3237
3441
|
cliPath = await resolveLocalCliPathAsync();
|
|
@@ -3245,6 +3449,7 @@ async function buildJetBrainsMemoraoneServer(options) {
|
|
|
3245
3449
|
command: process.execPath,
|
|
3246
3450
|
args: [cliPath],
|
|
3247
3451
|
workspaceRoot: options.workspaceRoot,
|
|
3452
|
+
environment: "local",
|
|
3248
3453
|
devMode: true,
|
|
3249
3454
|
apiUrl: options.apiUrl
|
|
3250
3455
|
});
|
|
@@ -3258,19 +3463,31 @@ async function buildJetBrainsMemoraoneServer(options) {
|
|
|
3258
3463
|
"[setup-ide-files] Could not resolve a working npx executable. Install Node.js/npm or ensure npx is on PATH before configuring JetBrains MCP."
|
|
3259
3464
|
);
|
|
3260
3465
|
}
|
|
3466
|
+
const channel = options.npmPackageChannel ?? npmPackageChannelFromEnvironment(environment);
|
|
3261
3467
|
return buildMemoraoneJetBrainsMcpServer({
|
|
3262
3468
|
command: npxPath,
|
|
3263
|
-
args: ["-y",
|
|
3469
|
+
args: ["-y", memoraoneNpmPackageSpec(channel)],
|
|
3264
3470
|
workspaceRoot: options.workspaceRoot,
|
|
3265
|
-
|
|
3471
|
+
environment,
|
|
3472
|
+
devMode: false,
|
|
3473
|
+
apiUrl: options.apiUrl
|
|
3266
3474
|
});
|
|
3267
3475
|
}
|
|
3476
|
+
function isOptionalJetBrainsHandshakeUnavailable(detail) {
|
|
3477
|
+
if (!detail) return false;
|
|
3478
|
+
if (detail.includes("-32601")) return true;
|
|
3479
|
+
if (/Method not found/i.test(detail)) return true;
|
|
3480
|
+
return false;
|
|
3481
|
+
}
|
|
3482
|
+
function formatOptionalJetBrainsHandshakeUnavailableDetail(detail) {
|
|
3483
|
+
return "MCP handshake optional verification unavailable while configuration succeeded" + (detail ? ` (${detail})` : "");
|
|
3484
|
+
}
|
|
3268
3485
|
async function verifyJetBrainsMcpHandshake(options) {
|
|
3269
3486
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
3270
3487
|
const { server } = options;
|
|
3271
|
-
return new Promise((
|
|
3488
|
+
return new Promise((resolve17) => {
|
|
3272
3489
|
let settled = false;
|
|
3273
|
-
const finish = (ok, detail) => {
|
|
3490
|
+
const finish = (ok, detail, optionalUnavailable) => {
|
|
3274
3491
|
if (settled) return;
|
|
3275
3492
|
settled = true;
|
|
3276
3493
|
clearTimeout(timer);
|
|
@@ -3278,7 +3495,7 @@ async function verifyJetBrainsMcpHandshake(options) {
|
|
|
3278
3495
|
child.kill();
|
|
3279
3496
|
} catch {
|
|
3280
3497
|
}
|
|
3281
|
-
|
|
3498
|
+
resolve17({ ok, detail, optionalUnavailable });
|
|
3282
3499
|
};
|
|
3283
3500
|
const child = (0, import_node_child_process5.spawn)(server.command, [...server.args], {
|
|
3284
3501
|
env: { ...process.env, ...server.env },
|
|
@@ -3318,7 +3535,12 @@ async function verifyJetBrainsMcpHandshake(options) {
|
|
|
3318
3535
|
finish(true, "initialize OK; tools/list OK");
|
|
3319
3536
|
}
|
|
3320
3537
|
if (msg.error) {
|
|
3321
|
-
|
|
3538
|
+
const errDetail = `JSON-RPC error: ${JSON.stringify(msg.error)}`;
|
|
3539
|
+
if (isOptionalJetBrainsHandshakeUnavailable(errDetail)) {
|
|
3540
|
+
finish(true, errDetail, true);
|
|
3541
|
+
} else {
|
|
3542
|
+
finish(false, errDetail);
|
|
3543
|
+
}
|
|
3322
3544
|
}
|
|
3323
3545
|
}
|
|
3324
3546
|
});
|
|
@@ -3347,11 +3569,11 @@ async function verifyJetBrainsMcpHandshake(options) {
|
|
|
3347
3569
|
async function setupJetBrainsMcpConfig(options) {
|
|
3348
3570
|
const homeDir = options.homeDir ?? os5.homedir();
|
|
3349
3571
|
const globalPath = options.globalConfigPath ?? getJetBrainsGlobalMcpConfigPath(homeDir);
|
|
3350
|
-
const workspaceRoot =
|
|
3572
|
+
const workspaceRoot = path16.resolve(options.repoRoot);
|
|
3351
3573
|
const repairActions = [];
|
|
3352
3574
|
const allLocations = getKnownJetBrainsMcpConfigLocations(homeDir, options.repoRoot);
|
|
3353
3575
|
for (const location of allLocations) {
|
|
3354
|
-
if (await
|
|
3576
|
+
if (await pathExists3(location.path)) {
|
|
3355
3577
|
repairActions.push({ type: "found-config", location });
|
|
3356
3578
|
}
|
|
3357
3579
|
}
|
|
@@ -3368,6 +3590,8 @@ async function setupJetBrainsMcpConfig(options) {
|
|
|
3368
3590
|
const memoraone = await buildJetBrainsMemoraoneServer({
|
|
3369
3591
|
workspaceRoot,
|
|
3370
3592
|
devMode: options.devMode,
|
|
3593
|
+
environment: options.environment,
|
|
3594
|
+
npmPackageChannel: options.npmPackageChannel,
|
|
3371
3595
|
apiUrl: options.apiUrl,
|
|
3372
3596
|
npxPathOverride: options.npxPathOverride,
|
|
3373
3597
|
cliPathOverride: options.cliPathOverride
|
|
@@ -3388,24 +3612,15 @@ async function setupJetBrainsMcpConfig(options) {
|
|
|
3388
3612
|
repairActions.push({ type: "removed-project-memoraone", path: location.path });
|
|
3389
3613
|
}
|
|
3390
3614
|
}
|
|
3391
|
-
const existed = await
|
|
3615
|
+
const existed = await pathExists3(globalPath);
|
|
3392
3616
|
let existing = null;
|
|
3393
3617
|
if (existed) {
|
|
3394
3618
|
try {
|
|
3395
3619
|
existing = await readJsonConfig(globalPath);
|
|
3396
3620
|
} catch {
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
const backupPath2 = await backupConfigFile(globalPath);
|
|
3401
|
-
repairActions.push({
|
|
3402
|
-
type: "repaired-zero-byte",
|
|
3403
|
-
path: globalPath,
|
|
3404
|
-
backupPath: backupPath2
|
|
3405
|
-
});
|
|
3406
|
-
await fs11.unlink(globalPath);
|
|
3407
|
-
existing = null;
|
|
3408
|
-
}
|
|
3621
|
+
throw new Error(
|
|
3622
|
+
`[setup-ide-files] Invalid JSON in shared JetBrains MCP config (file preserved, not modified): ${globalPath}. Fix or remove the file, then re-run setup-ide-files.`
|
|
3623
|
+
);
|
|
3409
3624
|
}
|
|
3410
3625
|
}
|
|
3411
3626
|
const merged = mergeJetBrainsMcpConfigObject(existing, memoraone);
|
|
@@ -3426,9 +3641,8 @@ async function setupJetBrainsMcpConfig(options) {
|
|
|
3426
3641
|
if (existed) {
|
|
3427
3642
|
backupPath = await backupConfigFile(globalPath);
|
|
3428
3643
|
}
|
|
3429
|
-
await
|
|
3430
|
-
await
|
|
3431
|
-
const verifyRaw = await fs11.readFile(globalPath, "utf8");
|
|
3644
|
+
await writeJetBrainsMcpJsonAtomic(globalPath, body);
|
|
3645
|
+
const verifyRaw = await fs12.readFile(globalPath, "utf8");
|
|
3432
3646
|
const verifyParsed = JSON.parse(stripLeadingLineComments2(verifyRaw));
|
|
3433
3647
|
validateJetBrainsMcpConfig(verifyParsed, memoraone);
|
|
3434
3648
|
const outcome = existed ? "updated" : "created";
|
|
@@ -3438,122 +3652,64 @@ async function setupJetBrainsMcpConfig(options) {
|
|
|
3438
3652
|
if (options.verify !== false) {
|
|
3439
3653
|
const verify = await verifyJetBrainsMcpHandshake({ server: memoraone });
|
|
3440
3654
|
verifyOk = verify.ok;
|
|
3441
|
-
verifyDetail = verify.detail;
|
|
3442
|
-
repairActions.push({
|
|
3655
|
+
verifyDetail = verify.optionalUnavailable ? formatOptionalJetBrainsHandshakeUnavailableDetail(verify.detail) : verify.detail;
|
|
3656
|
+
repairActions.push({
|
|
3657
|
+
type: "verify-handshake",
|
|
3658
|
+
ok: verify.ok,
|
|
3659
|
+
detail: verifyDetail ?? verify.detail
|
|
3660
|
+
});
|
|
3443
3661
|
}
|
|
3444
3662
|
return { outcome, backupPath, repairActions, verifyOk, verifyDetail, memoraone };
|
|
3445
3663
|
}
|
|
3446
|
-
function
|
|
3664
|
+
function formatJetBrainsHandshakeLogLine(action) {
|
|
3665
|
+
const optional = /optional verification unavailable/i.test(action.detail) || isOptionalJetBrainsHandshakeUnavailable(action.detail);
|
|
3666
|
+
if (optional) {
|
|
3667
|
+
if (/optional verification unavailable/i.test(action.detail)) {
|
|
3668
|
+
return `[setup-ide-files] ${action.detail}`;
|
|
3669
|
+
}
|
|
3670
|
+
return `[setup-ide-files] ${formatOptionalJetBrainsHandshakeUnavailableDetail(action.detail)}`;
|
|
3671
|
+
}
|
|
3672
|
+
if (action.ok) {
|
|
3673
|
+
return `[setup-ide-files] MCP handshake verification: ${action.detail}`;
|
|
3674
|
+
}
|
|
3675
|
+
return `[setup-ide-files] MCP handshake verification skipped/failed: ${action.detail}`;
|
|
3676
|
+
}
|
|
3677
|
+
function logJetBrainsMcpCliSummary(info, dryRun, println = console.log) {
|
|
3447
3678
|
for (const action of info.repairActions) {
|
|
3448
3679
|
if (action.type === "found-config") {
|
|
3449
|
-
|
|
3680
|
+
println(`[setup-ide-files] Found JetBrains MCP config (${action.location.kind}): ${action.location.path}`);
|
|
3450
3681
|
} else if (action.type === "repaired-zero-byte") {
|
|
3451
|
-
|
|
3452
|
-
|
|
3682
|
+
println(`[setup-ide-files] Repaired zero-byte MCP config: ${action.path}`);
|
|
3683
|
+
println(`[setup-ide-files] Backup: ${action.backupPath}`);
|
|
3453
3684
|
} else if (action.type === "backed-up-conflicting-project-config") {
|
|
3454
|
-
|
|
3455
|
-
|
|
3685
|
+
println(`[setup-ide-files] Backed up conflicting project MCP config: ${action.path}`);
|
|
3686
|
+
println(`[setup-ide-files] Backup: ${action.backupPath}`);
|
|
3456
3687
|
} else if (action.type === "removed-project-memoraone") {
|
|
3457
|
-
|
|
3688
|
+
println(`[setup-ide-files] Removed project-scoped memoraone definition: ${action.path}`);
|
|
3458
3689
|
} else if (action.type === "verify-handshake") {
|
|
3459
|
-
|
|
3460
|
-
console.log(`[setup-ide-files] MCP handshake verification: ${action.detail}`);
|
|
3461
|
-
} else {
|
|
3462
|
-
console.log(`[setup-ide-files] MCP handshake verification skipped/failed: ${action.detail}`);
|
|
3463
|
-
}
|
|
3690
|
+
println(formatJetBrainsHandshakeLogLine(action));
|
|
3464
3691
|
}
|
|
3465
3692
|
}
|
|
3466
3693
|
const prefix = dryRun ? "would be " : "";
|
|
3467
3694
|
if (info.outcome === "created") {
|
|
3468
|
-
|
|
3695
|
+
println(`[setup-ide-files] JetBrains global MCP config ${prefix}created: ${info.activeConfigPath}`);
|
|
3469
3696
|
} else if (info.outcome === "updated") {
|
|
3470
|
-
|
|
3697
|
+
println(`[setup-ide-files] JetBrains global MCP config ${prefix}updated: ${info.activeConfigPath}`);
|
|
3471
3698
|
} else {
|
|
3472
|
-
|
|
3699
|
+
println(`[setup-ide-files] JetBrains global MCP config unchanged: ${info.activeConfigPath}`);
|
|
3473
3700
|
}
|
|
3474
3701
|
if (info.backupPath) {
|
|
3475
|
-
|
|
3702
|
+
println(`[setup-ide-files] JetBrains global MCP config backup: ${info.backupPath}`);
|
|
3476
3703
|
}
|
|
3477
3704
|
if (info.npxPath) {
|
|
3478
|
-
|
|
3705
|
+
println(`[setup-ide-files] Resolved npx: ${info.npxPath}`);
|
|
3479
3706
|
}
|
|
3480
|
-
|
|
3481
|
-
|
|
3707
|
+
println(`[setup-ide-files] Final active JetBrains MCP config: ${info.activeConfigPath}`);
|
|
3708
|
+
println(
|
|
3482
3709
|
"[setup-ide-files] Fully quit JetBrains IDE and reopen this repo for MCP changes to take effect."
|
|
3483
3710
|
);
|
|
3484
3711
|
}
|
|
3485
3712
|
|
|
3486
|
-
// src/resolveBuiltCliPath.ts
|
|
3487
|
-
var fs12 = __toESM(require("fs/promises"), 1);
|
|
3488
|
-
var path15 = __toESM(require("path"), 1);
|
|
3489
|
-
var MONOREPO_CLI_REL = path15.join("packages", "mcp", "dist", "cli.cjs");
|
|
3490
|
-
async function pathExists3(filePath) {
|
|
3491
|
-
try {
|
|
3492
|
-
await fs12.access(filePath);
|
|
3493
|
-
return true;
|
|
3494
|
-
} catch {
|
|
3495
|
-
return false;
|
|
3496
|
-
}
|
|
3497
|
-
}
|
|
3498
|
-
async function findMonorepoCliFrom(startDir) {
|
|
3499
|
-
let current = path15.resolve(startDir);
|
|
3500
|
-
const root = path15.parse(current).root;
|
|
3501
|
-
while (true) {
|
|
3502
|
-
const candidate = path15.join(current, MONOREPO_CLI_REL);
|
|
3503
|
-
if (await pathExists3(candidate)) {
|
|
3504
|
-
return path15.resolve(candidate);
|
|
3505
|
-
}
|
|
3506
|
-
if (current === root) break;
|
|
3507
|
-
current = path15.dirname(current);
|
|
3508
|
-
}
|
|
3509
|
-
return null;
|
|
3510
|
-
}
|
|
3511
|
-
async function resolveFromRunningScript() {
|
|
3512
|
-
if (!process.argv[1]) return null;
|
|
3513
|
-
const script = path15.resolve(process.argv[1]);
|
|
3514
|
-
const base = path15.basename(script);
|
|
3515
|
-
if ((base === "cli.cjs" || base === "cli.ts" || base === "memoraone-mcp.cjs") && await pathExists3(script)) {
|
|
3516
|
-
return script;
|
|
3517
|
-
}
|
|
3518
|
-
const here = path15.dirname(script);
|
|
3519
|
-
const candidates = [
|
|
3520
|
-
path15.join(here, "cli.cjs"),
|
|
3521
|
-
path15.join(here, "..", "dist", "cli.cjs"),
|
|
3522
|
-
path15.join(here, "..", "..", "dist", "cli.cjs")
|
|
3523
|
-
];
|
|
3524
|
-
for (const candidate of candidates) {
|
|
3525
|
-
if (await pathExists3(candidate)) {
|
|
3526
|
-
return path15.resolve(candidate);
|
|
3527
|
-
}
|
|
3528
|
-
}
|
|
3529
|
-
return null;
|
|
3530
|
-
}
|
|
3531
|
-
async function resolveBuiltCliPathAsync(options) {
|
|
3532
|
-
const preferRunning = options?.preferRunningScript !== false;
|
|
3533
|
-
if (preferRunning) {
|
|
3534
|
-
const fromRunning = await resolveFromRunningScript();
|
|
3535
|
-
if (fromRunning) return fromRunning;
|
|
3536
|
-
}
|
|
3537
|
-
const searchDirs = [];
|
|
3538
|
-
if (options?.searchFrom !== void 0) {
|
|
3539
|
-
const dirs = Array.isArray(options.searchFrom) ? options.searchFrom : [options.searchFrom];
|
|
3540
|
-
searchDirs.push(...dirs);
|
|
3541
|
-
}
|
|
3542
|
-
searchDirs.push(process.cwd());
|
|
3543
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3544
|
-
for (const dir of searchDirs) {
|
|
3545
|
-
const key = path15.resolve(dir);
|
|
3546
|
-
if (seen.has(key)) continue;
|
|
3547
|
-
seen.add(key);
|
|
3548
|
-
const found = await findMonorepoCliFrom(key);
|
|
3549
|
-
if (found) return found;
|
|
3550
|
-
}
|
|
3551
|
-
if (!preferRunning) {
|
|
3552
|
-
return resolveFromRunningScript();
|
|
3553
|
-
}
|
|
3554
|
-
return null;
|
|
3555
|
-
}
|
|
3556
|
-
|
|
3557
3713
|
// src/openCursorMcpSettings.ts
|
|
3558
3714
|
var import_node_child_process6 = require("child_process");
|
|
3559
3715
|
var readline4 = __toESM(require("readline/promises"), 1);
|
|
@@ -3622,6 +3778,7 @@ function createTerminalPresentation(opts = {}) {
|
|
|
3622
3778
|
warningSymbol,
|
|
3623
3779
|
nextActionPrefix,
|
|
3624
3780
|
successLine: (message) => paint(color, ANSI.green, `${successSymbol} ${message}`),
|
|
3781
|
+
checkLine: (message) => `${paint(color, ANSI.green, successSymbol)} ${message}`,
|
|
3625
3782
|
warningLine: (message) => paint(color, ANSI.yellow, `${warningSymbol} ${message}`),
|
|
3626
3783
|
nextActionLine: (message) => `${nextActionPrefix} ${message}`,
|
|
3627
3784
|
heading: (text) => paint(color, ANSI.bold, text),
|
|
@@ -3674,44 +3831,6 @@ async function confirmYesDefault(question, deps = {}) {
|
|
|
3674
3831
|
rl.close();
|
|
3675
3832
|
}
|
|
3676
3833
|
}
|
|
3677
|
-
function collectOutcomePaths(outcomes) {
|
|
3678
|
-
const created = [];
|
|
3679
|
-
const updated = [];
|
|
3680
|
-
for (const [file, outcome] of Object.entries(outcomes)) {
|
|
3681
|
-
if (outcome === "created") created.push(file);
|
|
3682
|
-
else if (outcome === "updated") updated.push(file);
|
|
3683
|
-
}
|
|
3684
|
-
return { created, updated };
|
|
3685
|
-
}
|
|
3686
|
-
function formatCursorSetupCompletedSummary(opts, presentation = createTerminalPresentation({ color: false, unicode: false })) {
|
|
3687
|
-
const { created, updated } = collectOutcomePaths(opts.outcomes);
|
|
3688
|
-
const tp = presentation;
|
|
3689
|
-
const lines = [
|
|
3690
|
-
tp.successLine("MemoraOne setup completed for Cursor"),
|
|
3691
|
-
"",
|
|
3692
|
-
tp.heading("Repository"),
|
|
3693
|
-
tp.indent(tp.cyan(opts.repoRoot)),
|
|
3694
|
-
"",
|
|
3695
|
-
tp.heading("Changes")
|
|
3696
|
-
];
|
|
3697
|
-
if (created.length === 0 && updated.length === 0) {
|
|
3698
|
-
lines.push(tp.indent(tp.dim("No file changes needed")));
|
|
3699
|
-
} else {
|
|
3700
|
-
if (created.length) {
|
|
3701
|
-
lines.push(tp.indent(`Created: ${created.join(", ")}`));
|
|
3702
|
-
}
|
|
3703
|
-
if (updated.length) {
|
|
3704
|
-
lines.push(tp.indent(`Updated: ${updated.join(", ")}`));
|
|
3705
|
-
}
|
|
3706
|
-
}
|
|
3707
|
-
return lines;
|
|
3708
|
-
}
|
|
3709
|
-
function printCursorSetupCompletedSummary(opts, println = console.log, presentation) {
|
|
3710
|
-
const tp = presentation ?? createTerminalPresentation();
|
|
3711
|
-
for (const line of formatCursorSetupCompletedSummary(opts, tp)) {
|
|
3712
|
-
println(line);
|
|
3713
|
-
}
|
|
3714
|
-
}
|
|
3715
3834
|
function macosOpenCursorMcpSettingsAppleScript() {
|
|
3716
3835
|
return [
|
|
3717
3836
|
'tell application "Cursor" to activate',
|
|
@@ -3782,6 +3901,39 @@ async function runOpenCursorMcpSettingsFlow(deps = {}) {
|
|
|
3782
3901
|
printManualCursorMcpSettingsSteps(platform2, println);
|
|
3783
3902
|
}
|
|
3784
3903
|
|
|
3904
|
+
// src/setupSuccessOutput.ts
|
|
3905
|
+
var RESTART_LINE = "Restart your IDEs to finish setup.";
|
|
3906
|
+
function formatSetupSuccessLines(opts = {}) {
|
|
3907
|
+
const tp = opts.presentation ?? createTerminalPresentation(opts.presentationOptions ?? { color: false, unicode: true });
|
|
3908
|
+
const targets = opts.targets ?? {};
|
|
3909
|
+
const lines = [];
|
|
3910
|
+
if (opts.repositoryConnected) {
|
|
3911
|
+
lines.push(tp.checkLine("Repository connected"));
|
|
3912
|
+
}
|
|
3913
|
+
if (targets.cursor) {
|
|
3914
|
+
lines.push(tp.checkLine("Cursor configured"));
|
|
3915
|
+
}
|
|
3916
|
+
if (targets.vscode) {
|
|
3917
|
+
lines.push(tp.checkLine("VS Code configured"));
|
|
3918
|
+
}
|
|
3919
|
+
if (targets.jetbrains) {
|
|
3920
|
+
lines.push(tp.checkLine("JetBrains configured"));
|
|
3921
|
+
}
|
|
3922
|
+
const hasIde = Boolean(targets.cursor || targets.vscode || targets.jetbrains);
|
|
3923
|
+
lines.push("");
|
|
3924
|
+
lines.push(tp.checkLine("MemoraOne is ready"));
|
|
3925
|
+
if (hasIde) {
|
|
3926
|
+
lines.push("");
|
|
3927
|
+
lines.push(RESTART_LINE);
|
|
3928
|
+
}
|
|
3929
|
+
return lines;
|
|
3930
|
+
}
|
|
3931
|
+
function printSetupSuccess(opts, println = console.log) {
|
|
3932
|
+
for (const line of formatSetupSuccessLines(opts)) {
|
|
3933
|
+
println(line);
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3785
3937
|
// src/setupIdeFiles.ts
|
|
3786
3938
|
var MANAGED_MARKER = "<!-- MemoraOne managed IDE helper -->";
|
|
3787
3939
|
function buildMemoraoneMcpServer(ideType, options = {}) {
|
|
@@ -3795,7 +3947,7 @@ function buildMemoraoneMcpServer(ideType, options = {}) {
|
|
|
3795
3947
|
throw new Error("[setup-ide-files] Local VS Code MCP config requires a built CLI path.");
|
|
3796
3948
|
}
|
|
3797
3949
|
if (options.workspaceRoot !== void 0) {
|
|
3798
|
-
env2[MEMORAONE_WORKSPACE_ROOT_ENV] =
|
|
3950
|
+
env2[MEMORAONE_WORKSPACE_ROOT_ENV] = path17.resolve(options.workspaceRoot);
|
|
3799
3951
|
}
|
|
3800
3952
|
return {
|
|
3801
3953
|
command: "node",
|
|
@@ -3803,16 +3955,17 @@ function buildMemoraoneMcpServer(ideType, options = {}) {
|
|
|
3803
3955
|
env: env2
|
|
3804
3956
|
};
|
|
3805
3957
|
}
|
|
3958
|
+
const channel = options.npmPackageChannel ?? npmPackageChannelFromEnvironment(environment);
|
|
3806
3959
|
return {
|
|
3807
3960
|
command: options.command ?? "npx",
|
|
3808
|
-
args: ["-y",
|
|
3961
|
+
args: ["-y", memoraoneNpmPackageSpec(channel)],
|
|
3809
3962
|
env: env2
|
|
3810
3963
|
};
|
|
3811
3964
|
}
|
|
3812
3965
|
function assertUnderRepoRoot(repoRoot, absPath) {
|
|
3813
|
-
const normRoot =
|
|
3814
|
-
const normPath =
|
|
3815
|
-
if (normPath !==
|
|
3966
|
+
const normRoot = path17.resolve(repoRoot) + path17.sep;
|
|
3967
|
+
const normPath = path17.resolve(absPath);
|
|
3968
|
+
if (normPath !== path17.resolve(repoRoot) && !normPath.startsWith(normRoot)) {
|
|
3816
3969
|
throw new Error(`[setup-ide-files] Refusing to write outside repo root: ${absPath}`);
|
|
3817
3970
|
}
|
|
3818
3971
|
}
|
|
@@ -3828,18 +3981,18 @@ async function ensureGitignoreMemoraone(_repoRoot, _opts) {
|
|
|
3828
3981
|
return "skipped";
|
|
3829
3982
|
}
|
|
3830
3983
|
async function findRepoRoot(startDir) {
|
|
3831
|
-
let current =
|
|
3832
|
-
const root =
|
|
3984
|
+
let current = path17.resolve(startDir);
|
|
3985
|
+
const root = path17.parse(current).root;
|
|
3833
3986
|
while (true) {
|
|
3834
|
-
const gitPath =
|
|
3835
|
-
const m1Path =
|
|
3987
|
+
const gitPath = path17.join(current, ".git");
|
|
3988
|
+
const m1Path = path17.join(current, "memoraone.m1");
|
|
3836
3989
|
if (await pathExists4(gitPath) || await pathExists4(m1Path)) {
|
|
3837
3990
|
return current;
|
|
3838
3991
|
}
|
|
3839
3992
|
if (current === root) {
|
|
3840
3993
|
return null;
|
|
3841
3994
|
}
|
|
3842
|
-
current =
|
|
3995
|
+
current = path17.dirname(current);
|
|
3843
3996
|
}
|
|
3844
3997
|
}
|
|
3845
3998
|
function stripLeadingLineComments3(text) {
|
|
@@ -3888,16 +4041,44 @@ function mcpJsonHeader() {
|
|
|
3888
4041
|
function buildVscodeMcpJsonBody(existing, options = {}) {
|
|
3889
4042
|
const base = existing && typeof existing === "object" ? { ...existing } : { servers: {} };
|
|
3890
4043
|
const servers = typeof base.servers === "object" && base.servers !== null && !Array.isArray(base.servers) ? { ...base.servers } : {};
|
|
4044
|
+
delete servers.memoraone;
|
|
3891
4045
|
servers.memoraone = buildMemoraoneMcpServer("copilot-vscode", options);
|
|
3892
4046
|
const merged = { ...base, servers };
|
|
3893
4047
|
return mcpJsonHeader() + JSON.stringify(merged, null, 2) + "\n";
|
|
3894
4048
|
}
|
|
4049
|
+
async function writeSharedMcpJsonAtomic(filePath, content) {
|
|
4050
|
+
const dir = path17.dirname(filePath);
|
|
4051
|
+
await fs13.mkdir(dir, { recursive: true });
|
|
4052
|
+
const tmpPath = path17.join(
|
|
4053
|
+
dir,
|
|
4054
|
+
`.${path17.basename(filePath)}.${process.pid}.${(0, import_node_crypto5.randomBytes)(8).toString("hex")}.tmp`
|
|
4055
|
+
);
|
|
4056
|
+
try {
|
|
4057
|
+
await fs13.writeFile(tmpPath, content, "utf8");
|
|
4058
|
+
await fs13.rename(tmpPath, filePath);
|
|
4059
|
+
} catch (err) {
|
|
4060
|
+
try {
|
|
4061
|
+
await fs13.unlink(tmpPath);
|
|
4062
|
+
} catch {
|
|
4063
|
+
}
|
|
4064
|
+
throw err;
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
var SharedMcpJsonParseError = class extends Error {
|
|
4068
|
+
constructor(configPath) {
|
|
4069
|
+
super(
|
|
4070
|
+
`[setup-ide-files] Invalid JSON in shared MCP config (file preserved, not modified): ${configPath}. Fix or remove the file, then re-run setup-ide-files.`
|
|
4071
|
+
);
|
|
4072
|
+
this.name = "SharedMcpJsonParseError";
|
|
4073
|
+
this.configPath = configPath;
|
|
4074
|
+
}
|
|
4075
|
+
};
|
|
3895
4076
|
function buildCursorMcpJsonBody(existing, writeOptions) {
|
|
3896
4077
|
const merged = mergeCursorRepoMcpConfigObject(existing, writeOptions);
|
|
3897
4078
|
return mcpJsonHeader() + JSON.stringify(merged, null, 2) + "\n";
|
|
3898
4079
|
}
|
|
3899
4080
|
async function writeManagedMarkdown(repoRoot, relPath, fullContent, opts) {
|
|
3900
|
-
const abs =
|
|
4081
|
+
const abs = path17.join(repoRoot, relPath);
|
|
3901
4082
|
assertUnderRepoRoot(repoRoot, abs);
|
|
3902
4083
|
let prior = "";
|
|
3903
4084
|
let existed = false;
|
|
@@ -3909,25 +4090,25 @@ async function writeManagedMarkdown(repoRoot, relPath, fullContent, opts) {
|
|
|
3909
4090
|
}
|
|
3910
4091
|
if (!existed) {
|
|
3911
4092
|
if (opts.dryRun) return "created";
|
|
3912
|
-
await fs13.mkdir(
|
|
4093
|
+
await fs13.mkdir(path17.dirname(abs), { recursive: true });
|
|
3913
4094
|
await fs13.writeFile(abs, fullContent, "utf8");
|
|
3914
4095
|
return "created";
|
|
3915
4096
|
}
|
|
3916
4097
|
if (prior.includes(MANAGED_MARKER)) {
|
|
3917
4098
|
if (prior === fullContent) return "skipped";
|
|
3918
4099
|
if (opts.dryRun) return "updated";
|
|
3919
|
-
await fs13.mkdir(
|
|
4100
|
+
await fs13.mkdir(path17.dirname(abs), { recursive: true });
|
|
3920
4101
|
await fs13.writeFile(abs, fullContent, "utf8");
|
|
3921
4102
|
return "updated";
|
|
3922
4103
|
}
|
|
3923
4104
|
if (!opts.force) return "skipped-untracked";
|
|
3924
4105
|
if (opts.dryRun) return "updated";
|
|
3925
|
-
await fs13.mkdir(
|
|
4106
|
+
await fs13.mkdir(path17.dirname(abs), { recursive: true });
|
|
3926
4107
|
await fs13.writeFile(abs, fullContent, "utf8");
|
|
3927
4108
|
return "updated";
|
|
3928
4109
|
}
|
|
3929
4110
|
async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
|
|
3930
|
-
const abs =
|
|
4111
|
+
const abs = path17.join(repoRoot, relPath);
|
|
3931
4112
|
assertUnderRepoRoot(repoRoot, abs);
|
|
3932
4113
|
let raw = "";
|
|
3933
4114
|
let existed = false;
|
|
@@ -3940,24 +4121,24 @@ async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
|
|
|
3940
4121
|
if (!existed) {
|
|
3941
4122
|
const body = buildBody(null);
|
|
3942
4123
|
if (opts.dryRun) return "created";
|
|
3943
|
-
await
|
|
3944
|
-
await fs13.writeFile(abs, body, "utf8");
|
|
4124
|
+
await writeSharedMcpJsonAtomic(abs, body);
|
|
3945
4125
|
return "created";
|
|
3946
4126
|
}
|
|
3947
4127
|
const managed = raw.includes(MANAGED_MARKER);
|
|
3948
4128
|
if (!managed && !opts.force) return "skipped-untracked";
|
|
3949
|
-
let parsed2
|
|
4129
|
+
let parsed2;
|
|
3950
4130
|
try {
|
|
3951
4131
|
parsed2 = JSON.parse(stripLeadingLineComments3(raw));
|
|
3952
4132
|
} catch {
|
|
3953
|
-
|
|
4133
|
+
throw new SharedMcpJsonParseError(abs);
|
|
4134
|
+
}
|
|
4135
|
+
if (!parsed2 || typeof parsed2 !== "object" || Array.isArray(parsed2)) {
|
|
4136
|
+
throw new SharedMcpJsonParseError(abs);
|
|
3954
4137
|
}
|
|
3955
|
-
if (!parsed2 && !opts.force) return "skipped-untracked";
|
|
3956
4138
|
const next = buildBody(parsed2);
|
|
3957
4139
|
if (managed && next === raw) return "skipped";
|
|
3958
4140
|
if (opts.dryRun) return "updated";
|
|
3959
|
-
await
|
|
3960
|
-
await fs13.writeFile(abs, next, "utf8");
|
|
4141
|
+
await writeSharedMcpJsonAtomic(abs, next);
|
|
3961
4142
|
return "updated";
|
|
3962
4143
|
}
|
|
3963
4144
|
function parseSetupIdeFlags(argv) {
|
|
@@ -3973,6 +4154,7 @@ function parseSetupIdeFlags(argv) {
|
|
|
3973
4154
|
let repair = false;
|
|
3974
4155
|
let local = false;
|
|
3975
4156
|
let staging = false;
|
|
4157
|
+
let verbose = false;
|
|
3976
4158
|
let workspaceRoot;
|
|
3977
4159
|
let apiUrl;
|
|
3978
4160
|
const unknown = [];
|
|
@@ -3991,6 +4173,7 @@ function parseSetupIdeFlags(argv) {
|
|
|
3991
4173
|
else if (a === "--repair") repair = true;
|
|
3992
4174
|
else if (a === "--local") local = true;
|
|
3993
4175
|
else if (a === "--staging") staging = true;
|
|
4176
|
+
else if (a === "--verbose") verbose = true;
|
|
3994
4177
|
else if (a === "--workspace-root") {
|
|
3995
4178
|
const value = argv[++i];
|
|
3996
4179
|
if (!value || value.startsWith("-")) {
|
|
@@ -4048,22 +4231,48 @@ function parseSetupIdeFlags(argv) {
|
|
|
4048
4231
|
workspaceRoot,
|
|
4049
4232
|
apiUrl,
|
|
4050
4233
|
explicitCursor: cursor,
|
|
4234
|
+
verbose,
|
|
4051
4235
|
unknown,
|
|
4052
4236
|
flagError
|
|
4053
4237
|
};
|
|
4054
4238
|
}
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
if (
|
|
4239
|
+
function logSetupIdeFilesVerboseSuccess(opts, println = console.log) {
|
|
4240
|
+
const { targets, dryRun, result } = opts;
|
|
4241
|
+
if (result.repoRoot) {
|
|
4242
|
+
println(`[setup-ide-files] Repo root: ${result.repoRoot}`);
|
|
4243
|
+
}
|
|
4244
|
+
if (result.daemonCleanup && !result.daemonCleanup.skipped) {
|
|
4245
|
+
logSetupIdeCleanupSummary(result.daemonCleanup, println);
|
|
4246
|
+
}
|
|
4247
|
+
if (targets.cursor && result.cursorMcp) {
|
|
4248
|
+
logCursorMcpCliSummary(result.cursorMcp, dryRun, {
|
|
4249
|
+
forInteractivePostSetup: opts.forInteractivePostSetup,
|
|
4250
|
+
println
|
|
4251
|
+
});
|
|
4252
|
+
}
|
|
4253
|
+
if (targets.jetbrains && result.jetbrainsMcp) {
|
|
4254
|
+
logJetBrainsMcpCliSummary(result.jetbrainsMcp, dryRun, println);
|
|
4255
|
+
}
|
|
4256
|
+
summarizeOutcomes(result.outcomes, println);
|
|
4257
|
+
if (dryRun) {
|
|
4258
|
+
println("[setup-ide-files] Dry run: no files written.");
|
|
4259
|
+
if (result.daemonCleanup && !result.daemonCleanup.skipped) {
|
|
4260
|
+
println("[setup-ide-files] Dry run: no daemons stopped, no sockets removed.");
|
|
4261
|
+
}
|
|
4262
|
+
}
|
|
4263
|
+
println(`[setup-ide-files] ${restartIdeInstruction(targets)}`);
|
|
4264
|
+
}
|
|
4265
|
+
async function resolveSetupApiUrl(o, repoRoot) {
|
|
4266
|
+
if (o.apiUrl) return normalizeApiUrl2(o.apiUrl);
|
|
4058
4267
|
const binding = await findBindingRecordByWorkspaceRoot(repoRoot, o.homeDir);
|
|
4059
|
-
if (binding?.apiUrl) return
|
|
4268
|
+
if (binding?.apiUrl) return normalizeApiUrl2(binding.apiUrl);
|
|
4060
4269
|
return void 0;
|
|
4061
4270
|
}
|
|
4062
4271
|
async function persistBindingApiUrl(repoRoot, apiUrl, homeDir, dryRun) {
|
|
4063
4272
|
if (dryRun) return;
|
|
4064
4273
|
const binding = await findBindingRecordByWorkspaceRoot(repoRoot, homeDir);
|
|
4065
4274
|
if (!binding) return;
|
|
4066
|
-
const normalized =
|
|
4275
|
+
const normalized = normalizeApiUrl2(apiUrl);
|
|
4067
4276
|
if (binding.apiUrl === normalized) return;
|
|
4068
4277
|
await writeBindingRecord(
|
|
4069
4278
|
{
|
|
@@ -4079,7 +4288,7 @@ function cursorEnvironmentFromFlags(local, staging) {
|
|
|
4079
4288
|
if (staging) return "staging";
|
|
4080
4289
|
return "production";
|
|
4081
4290
|
}
|
|
4082
|
-
function summarizeOutcomes(outcomes) {
|
|
4291
|
+
function summarizeOutcomes(outcomes, println = console.log) {
|
|
4083
4292
|
const created = [];
|
|
4084
4293
|
const updated = [];
|
|
4085
4294
|
const skipped = [];
|
|
@@ -4097,7 +4306,7 @@ function summarizeOutcomes(outcomes) {
|
|
|
4097
4306
|
if (skippedUntracked.length) {
|
|
4098
4307
|
lines.push(` skipped (unmanaged existing file, use --force): ${skippedUntracked.join(", ")}`);
|
|
4099
4308
|
}
|
|
4100
|
-
|
|
4309
|
+
println(lines.join("\n"));
|
|
4101
4310
|
}
|
|
4102
4311
|
function ideTypesFromSetupTargets(targets) {
|
|
4103
4312
|
const ides = [];
|
|
@@ -4138,28 +4347,28 @@ function aggregateCleanupResults(results) {
|
|
|
4138
4347
|
error
|
|
4139
4348
|
};
|
|
4140
4349
|
}
|
|
4141
|
-
function logSetupIdeCleanupSummary(cleanup) {
|
|
4350
|
+
function logSetupIdeCleanupSummary(cleanup, println = console.log) {
|
|
4142
4351
|
if (cleanup.skipped) return;
|
|
4143
|
-
|
|
4352
|
+
println(`[setup-ide-files] Project id: ${cleanup.projectId}`);
|
|
4144
4353
|
if (cleanup.foundDaemonCount > 0) {
|
|
4145
|
-
|
|
4354
|
+
println(`[setup-ide-files] Found ${cleanup.foundDaemonCount} stale daemon(s)`);
|
|
4146
4355
|
if (cleanup.dryRun) {
|
|
4147
|
-
|
|
4356
|
+
println(`[setup-ide-files] Would stop ${cleanup.foundDaemonCount} stale daemon(s)`);
|
|
4148
4357
|
} else if (cleanup.stoppedDaemonCount > 0) {
|
|
4149
|
-
|
|
4358
|
+
println(`[setup-ide-files] Stopped ${cleanup.stoppedDaemonCount} stale daemon(s)`);
|
|
4150
4359
|
}
|
|
4151
4360
|
} else {
|
|
4152
|
-
|
|
4361
|
+
println("[setup-ide-files] No stale daemons found for this project and IDE target(s).");
|
|
4153
4362
|
}
|
|
4154
4363
|
if (cleanup.removedSocketCount > 0) {
|
|
4155
4364
|
if (cleanup.dryRun) {
|
|
4156
|
-
|
|
4365
|
+
println(`[setup-ide-files] Would remove ${cleanup.removedSocketCount} stale socket(s)`);
|
|
4157
4366
|
} else {
|
|
4158
|
-
|
|
4367
|
+
println(`[setup-ide-files] Removed ${cleanup.removedSocketCount} stale socket(s)`);
|
|
4159
4368
|
}
|
|
4160
4369
|
}
|
|
4161
4370
|
if (cleanup.skippedUnrelatedDaemonCount > 0) {
|
|
4162
|
-
|
|
4371
|
+
println(
|
|
4163
4372
|
`[setup-ide-files] Skipped ${cleanup.skippedUnrelatedDaemonCount} unrelated project daemon(s)`
|
|
4164
4373
|
);
|
|
4165
4374
|
}
|
|
@@ -4238,7 +4447,7 @@ async function runSetupIdeFiles(o) {
|
|
|
4238
4447
|
const outcomes = {};
|
|
4239
4448
|
let cursorMcp;
|
|
4240
4449
|
let jetbrainsMcp;
|
|
4241
|
-
const repoRoot = o.workspaceRoot !== void 0 && o.workspaceRoot !== "" ?
|
|
4450
|
+
const repoRoot = o.workspaceRoot !== void 0 && o.workspaceRoot !== "" ? path17.resolve(o.workspaceRoot) : await findRepoRoot(o.cwd);
|
|
4242
4451
|
if (!repoRoot) {
|
|
4243
4452
|
return {
|
|
4244
4453
|
exitCode: 1,
|
|
@@ -4274,12 +4483,13 @@ async function runSetupIdeFiles(o) {
|
|
|
4274
4483
|
});
|
|
4275
4484
|
const cursorEnvironment = o.cursorEnvironment ?? "production";
|
|
4276
4485
|
const localOrDev = cursorEnvironment === "local" || Boolean(o.devMode);
|
|
4277
|
-
const
|
|
4486
|
+
const npmPackageChannel = o.npmPackageChannel ?? npmPackageChannelFromEnvironment(cursorEnvironment);
|
|
4487
|
+
const resolvedApiUrl2 = await resolveSetupApiUrl(o, repoRoot);
|
|
4278
4488
|
const effectiveApiUrl = resolveIdeApiUrl({
|
|
4279
4489
|
environment: localOrDev ? "local" : cursorEnvironment,
|
|
4280
4490
|
apiUrl: resolvedApiUrl2
|
|
4281
4491
|
});
|
|
4282
|
-
if (
|
|
4492
|
+
if (!o.dryRun && resolvedApiUrl2) {
|
|
4283
4493
|
await persistBindingApiUrl(repoRoot, effectiveApiUrl, o.homeDir, o.dryRun);
|
|
4284
4494
|
}
|
|
4285
4495
|
const cursorContent = `---
|
|
@@ -4324,7 +4534,8 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
4324
4534
|
npxPath: npxPath ?? void 0,
|
|
4325
4535
|
cliPath,
|
|
4326
4536
|
repoRoot,
|
|
4327
|
-
apiUrl: resolvedApiUrl2
|
|
4537
|
+
apiUrl: resolvedApiUrl2,
|
|
4538
|
+
npmPackageChannel
|
|
4328
4539
|
};
|
|
4329
4540
|
outcomes[".cursor/rules/memoraone-mcp.mdc"] = await writeManagedMarkdown(
|
|
4330
4541
|
repoRoot,
|
|
@@ -4332,12 +4543,22 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
4332
4543
|
cursorContent,
|
|
4333
4544
|
{ force: o.force, dryRun: o.dryRun }
|
|
4334
4545
|
);
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4546
|
+
try {
|
|
4547
|
+
outcomes[".cursor/mcp.json"] = await writeIdeMcpJson(
|
|
4548
|
+
repoRoot,
|
|
4549
|
+
".cursor/mcp.json",
|
|
4550
|
+
(existing) => buildCursorMcpJsonBody(existing, cursorWriteOptions),
|
|
4551
|
+
{ force: o.force, dryRun: o.dryRun }
|
|
4552
|
+
);
|
|
4553
|
+
} catch (err) {
|
|
4554
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4555
|
+
return {
|
|
4556
|
+
exitCode: 1,
|
|
4557
|
+
repoRoot,
|
|
4558
|
+
outcomes,
|
|
4559
|
+
error: message
|
|
4560
|
+
};
|
|
4561
|
+
}
|
|
4341
4562
|
const repoConfigPath = getCursorRepoMcpConfigPath(repoRoot);
|
|
4342
4563
|
const repoOutcome = outcomes[".cursor/mcp.json"] ?? "skipped";
|
|
4343
4564
|
let globalConfigPath;
|
|
@@ -4386,7 +4607,7 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
4386
4607
|
};
|
|
4387
4608
|
}
|
|
4388
4609
|
if (o.targets.vscode) {
|
|
4389
|
-
const vscodeEnvironment = localOrDev ? "local" : "production";
|
|
4610
|
+
const vscodeEnvironment = localOrDev ? "local" : cursorEnvironment === "staging" ? "staging" : "production";
|
|
4390
4611
|
let vscodeCliPath;
|
|
4391
4612
|
if (vscodeEnvironment === "local") {
|
|
4392
4613
|
let resolvedCliPath = o.cursorLocalCliPathOverride;
|
|
@@ -4407,20 +4628,32 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
4407
4628
|
}
|
|
4408
4629
|
vscodeCliPath = resolvedCliPath;
|
|
4409
4630
|
}
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4631
|
+
try {
|
|
4632
|
+
outcomes[".vscode/mcp.json"] = await writeIdeMcpJson(
|
|
4633
|
+
repoRoot,
|
|
4634
|
+
".vscode/mcp.json",
|
|
4635
|
+
(existing) => buildVscodeMcpJsonBody(existing, {
|
|
4636
|
+
environment: vscodeEnvironment,
|
|
4637
|
+
apiUrl: resolvedApiUrl2,
|
|
4638
|
+
cliPath: vscodeCliPath,
|
|
4639
|
+
workspaceRoot: vscodeEnvironment === "local" ? repoRoot : void 0,
|
|
4640
|
+
npmPackageChannel
|
|
4641
|
+
}),
|
|
4642
|
+
{
|
|
4643
|
+
force: o.force,
|
|
4644
|
+
dryRun: o.dryRun
|
|
4645
|
+
}
|
|
4646
|
+
);
|
|
4647
|
+
} catch (err) {
|
|
4648
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4649
|
+
return {
|
|
4650
|
+
exitCode: 1,
|
|
4651
|
+
repoRoot,
|
|
4652
|
+
outcomes,
|
|
4653
|
+
cursorMcp,
|
|
4654
|
+
error: message
|
|
4655
|
+
};
|
|
4656
|
+
}
|
|
4424
4657
|
outcomes[".github/copilot-instructions.md"] = await writeManagedMarkdown(
|
|
4425
4658
|
repoRoot,
|
|
4426
4659
|
".github/copilot-instructions.md",
|
|
@@ -4443,8 +4676,11 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
4443
4676
|
repoRoot,
|
|
4444
4677
|
globalConfigPath: activePath,
|
|
4445
4678
|
dryRun: o.dryRun,
|
|
4446
|
-
//
|
|
4447
|
-
|
|
4679
|
+
// Local dogfood: --dev / local environment → node + built CLI.
|
|
4680
|
+
// Published staging/production: npx + channel-specific package spec.
|
|
4681
|
+
devMode: localOrDev,
|
|
4682
|
+
environment: localOrDev ? "local" : cursorEnvironment,
|
|
4683
|
+
npmPackageChannel,
|
|
4448
4684
|
apiUrl: resolvedApiUrl2,
|
|
4449
4685
|
repair: o.repair ?? false,
|
|
4450
4686
|
verify: o.verifyHandshake ?? !o.dryRun,
|
|
@@ -4489,6 +4725,7 @@ async function cliSetupIdeFiles(argv, options = {}) {
|
|
|
4489
4725
|
workspaceRoot,
|
|
4490
4726
|
apiUrl,
|
|
4491
4727
|
explicitCursor,
|
|
4728
|
+
verbose,
|
|
4492
4729
|
unknown,
|
|
4493
4730
|
flagError
|
|
4494
4731
|
} = parseSetupIdeFlags(argv);
|
|
@@ -4504,6 +4741,7 @@ async function cliSetupIdeFiles(argv, options = {}) {
|
|
|
4504
4741
|
const openDeps = options.openCursorMcpSettings ?? {};
|
|
4505
4742
|
const stdinIsTty = openDeps.stdinIsTty ?? process.stdin.isTTY === true;
|
|
4506
4743
|
const env2 = openDeps.env ?? process.env;
|
|
4744
|
+
const println = options.println ?? openDeps.println ?? console.log;
|
|
4507
4745
|
const promptOpenCursorSettings = shouldPromptOpenCursorMcpSettings({
|
|
4508
4746
|
explicitCursor,
|
|
4509
4747
|
all,
|
|
@@ -4511,6 +4749,7 @@ async function cliSetupIdeFiles(argv, options = {}) {
|
|
|
4511
4749
|
stdinIsTty,
|
|
4512
4750
|
env: env2
|
|
4513
4751
|
});
|
|
4752
|
+
const cursorEnvironment = cursorEnvironmentFromFlags(local, staging);
|
|
4514
4753
|
const result = await runSetupIdeFiles({
|
|
4515
4754
|
cwd: cwd2,
|
|
4516
4755
|
workspaceRoot,
|
|
@@ -4520,62 +4759,50 @@ async function cliSetupIdeFiles(argv, options = {}) {
|
|
|
4520
4759
|
noGitignore: options.setupOverrides?.noGitignore ?? noGitignore,
|
|
4521
4760
|
devMode,
|
|
4522
4761
|
repair,
|
|
4523
|
-
cursorEnvironment
|
|
4762
|
+
cursorEnvironment,
|
|
4763
|
+
npmPackageChannel: npmPackageChannelFromEnvironment(cursorEnvironment),
|
|
4524
4764
|
apiUrl,
|
|
4525
4765
|
...options.setupOverrides
|
|
4526
4766
|
});
|
|
4527
4767
|
if (result.error) {
|
|
4528
4768
|
console.error(result.error);
|
|
4529
4769
|
if (result.repoRoot) {
|
|
4530
|
-
|
|
4770
|
+
println(`[setup-ide-files] Repo root: ${result.repoRoot}`);
|
|
4531
4771
|
}
|
|
4532
4772
|
summarizeOutcomes(result.outcomes);
|
|
4533
4773
|
return result.exitCode;
|
|
4534
4774
|
}
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
}
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4775
|
+
const presentation = openDeps.presentation ?? createTerminalPresentation({
|
|
4776
|
+
env: env2,
|
|
4777
|
+
stdoutIsTty: openDeps.stdoutIsTty ?? process.stdout.isTTY === true,
|
|
4778
|
+
color: openDeps.color,
|
|
4779
|
+
unicode: openDeps.unicode
|
|
4780
|
+
});
|
|
4781
|
+
const showVerbose = verbose || dryRun;
|
|
4782
|
+
if (showVerbose) {
|
|
4783
|
+
logSetupIdeFilesVerboseSuccess(
|
|
4784
|
+
{
|
|
4785
|
+
targets,
|
|
4786
|
+
dryRun,
|
|
4787
|
+
result,
|
|
4788
|
+
forInteractivePostSetup: promptOpenCursorSettings
|
|
4789
|
+
},
|
|
4790
|
+
println
|
|
4791
|
+
);
|
|
4792
|
+
} else {
|
|
4793
|
+
printSetupSuccess({ targets, presentation }, println);
|
|
4548
4794
|
}
|
|
4549
4795
|
if (promptOpenCursorSettings && result.repoRoot) {
|
|
4550
|
-
const presentation = openDeps.presentation ?? createTerminalPresentation({
|
|
4551
|
-
env: env2,
|
|
4552
|
-
stdoutIsTty: openDeps.stdoutIsTty ?? process.stdout.isTTY === true,
|
|
4553
|
-
color: openDeps.color,
|
|
4554
|
-
unicode: openDeps.unicode
|
|
4555
|
-
});
|
|
4556
|
-
printCursorSetupCompletedSummary(
|
|
4557
|
-
{ repoRoot: result.repoRoot, outcomes: result.outcomes },
|
|
4558
|
-
openDeps.println,
|
|
4559
|
-
presentation
|
|
4560
|
-
);
|
|
4561
4796
|
await runOpenCursorMcpSettingsFlow({
|
|
4562
4797
|
...openDeps,
|
|
4563
4798
|
stdinIsTty,
|
|
4564
4799
|
env: env2,
|
|
4565
|
-
presentation
|
|
4800
|
+
presentation,
|
|
4801
|
+
println
|
|
4566
4802
|
});
|
|
4567
|
-
} else {
|
|
4568
|
-
summarizeOutcomes(result.outcomes);
|
|
4569
|
-
if (dryRun) {
|
|
4570
|
-
console.log("[setup-ide-files] Dry run: no files written.");
|
|
4571
|
-
if (result.daemonCleanup && !result.daemonCleanup.skipped) {
|
|
4572
|
-
console.log("[setup-ide-files] Dry run: no daemons stopped, no sockets removed.");
|
|
4573
|
-
}
|
|
4574
|
-
}
|
|
4575
|
-
console.log(`[setup-ide-files] ${restartIdeInstruction(targets)}`);
|
|
4576
4803
|
}
|
|
4577
4804
|
if (cleanup) {
|
|
4578
|
-
|
|
4805
|
+
println("[setup-ide-files] Running additional full-project cleanup (--cleanup)...");
|
|
4579
4806
|
const cleanupResult = await runCleanup({
|
|
4580
4807
|
cwd: cwd2,
|
|
4581
4808
|
dryRun,
|
|
@@ -4591,16 +4818,16 @@ async function cliSetupIdeFiles(argv, options = {}) {
|
|
|
4591
4818
|
}
|
|
4592
4819
|
|
|
4593
4820
|
// src/localState/connectCommand.ts
|
|
4594
|
-
var
|
|
4821
|
+
var path20 = __toESM(require("path"), 1);
|
|
4595
4822
|
var os7 = __toESM(require("os"), 1);
|
|
4596
4823
|
|
|
4597
4824
|
// src/config.ts
|
|
4598
4825
|
var process2 = __toESM(require("process"), 1);
|
|
4599
4826
|
var fs14 = __toESM(require("fs"), 1);
|
|
4600
|
-
var
|
|
4827
|
+
var path18 = __toESM(require("path"), 1);
|
|
4601
4828
|
var dotenv = __toESM(require("dotenv"), 1);
|
|
4602
4829
|
var import_v4 = require("zod/v4");
|
|
4603
|
-
var dotenvPath =
|
|
4830
|
+
var dotenvPath = path18.resolve(process2.cwd(), ".env");
|
|
4604
4831
|
if (fs14.existsSync(dotenvPath)) {
|
|
4605
4832
|
try {
|
|
4606
4833
|
dotenv.config({ path: dotenvPath });
|
|
@@ -4669,7 +4896,7 @@ var config2 = {
|
|
|
4669
4896
|
|
|
4670
4897
|
// src/repoFingerprint.ts
|
|
4671
4898
|
var fs15 = __toESM(require("fs"), 1);
|
|
4672
|
-
var
|
|
4899
|
+
var path19 = __toESM(require("path"), 1);
|
|
4673
4900
|
var crypto2 = __toESM(require("crypto"), 1);
|
|
4674
4901
|
var parseBooleanFlag3 = (value) => {
|
|
4675
4902
|
if (!value) {
|
|
@@ -4708,7 +4935,7 @@ var resolveGitDir = (gitPath) => {
|
|
|
4708
4935
|
const match = content.match(/^gitdir:\s*(.+)$/m);
|
|
4709
4936
|
if (match) {
|
|
4710
4937
|
const gitDir = match[1].trim();
|
|
4711
|
-
return
|
|
4938
|
+
return path19.resolve(path19.dirname(gitPath), gitDir);
|
|
4712
4939
|
}
|
|
4713
4940
|
}
|
|
4714
4941
|
} catch {
|
|
@@ -4717,16 +4944,16 @@ var resolveGitDir = (gitPath) => {
|
|
|
4717
4944
|
return null;
|
|
4718
4945
|
};
|
|
4719
4946
|
var findGitRoot = (start) => {
|
|
4720
|
-
let current =
|
|
4947
|
+
let current = path19.resolve(start);
|
|
4721
4948
|
while (true) {
|
|
4722
|
-
const gitPath =
|
|
4949
|
+
const gitPath = path19.join(current, ".git");
|
|
4723
4950
|
if (fs15.existsSync(gitPath)) {
|
|
4724
4951
|
const gitDir = resolveGitDir(gitPath);
|
|
4725
4952
|
if (gitDir) {
|
|
4726
4953
|
return { gitRoot: current, gitDir };
|
|
4727
4954
|
}
|
|
4728
4955
|
}
|
|
4729
|
-
const parent =
|
|
4956
|
+
const parent = path19.dirname(current);
|
|
4730
4957
|
if (parent === current) {
|
|
4731
4958
|
break;
|
|
4732
4959
|
}
|
|
@@ -4735,7 +4962,7 @@ var findGitRoot = (start) => {
|
|
|
4735
4962
|
return null;
|
|
4736
4963
|
};
|
|
4737
4964
|
var readOriginRemote = (gitDir) => {
|
|
4738
|
-
const configPath =
|
|
4965
|
+
const configPath = path19.join(gitDir, "config");
|
|
4739
4966
|
try {
|
|
4740
4967
|
const content = fs15.readFileSync(configPath, "utf8");
|
|
4741
4968
|
const lines = content.split(/\r?\n/);
|
|
@@ -4761,7 +4988,7 @@ var readOriginRemote = (gitDir) => {
|
|
|
4761
4988
|
function resolveRepoFingerprint(cwd2) {
|
|
4762
4989
|
const found = findGitRoot(cwd2);
|
|
4763
4990
|
if (!found) {
|
|
4764
|
-
const fallbackPath =
|
|
4991
|
+
const fallbackPath = path19.resolve(cwd2);
|
|
4765
4992
|
const fingerprint2 = sha256(fallbackPath);
|
|
4766
4993
|
debugLog(`repo fingerprint=${fingerprint2} source=path-fallback`);
|
|
4767
4994
|
return {
|
|
@@ -4783,7 +5010,7 @@ function resolveRepoFingerprint(cwd2) {
|
|
|
4783
5010
|
source: "git-remote"
|
|
4784
5011
|
};
|
|
4785
5012
|
}
|
|
4786
|
-
const fingerprint = sha256(
|
|
5013
|
+
const fingerprint = sha256(path19.resolve(gitRoot));
|
|
4787
5014
|
debugLog(`repo fingerprint=${fingerprint} source=path-fallback`);
|
|
4788
5015
|
return {
|
|
4789
5016
|
fingerprint,
|
|
@@ -4809,16 +5036,32 @@ function normalizeGitRemote(remoteUrl) {
|
|
|
4809
5036
|
normalized = normalized.replace(/\/+$/, "");
|
|
4810
5037
|
return normalized.toLowerCase() || null;
|
|
4811
5038
|
}
|
|
4812
|
-
function formatIdeSetupRepairHint(workspaceRoot, cliPath) {
|
|
4813
|
-
const cli = cliPath ?? "<path-to-packages/mcp/dist/cli.cjs>";
|
|
4814
|
-
return `Repair with (no new connect code): node ${cli} setup-ide-files --all --local --dev --force --workspace-root ${workspaceRoot}`;
|
|
4815
|
-
}
|
|
4816
5039
|
async function runConnectCommand(options) {
|
|
4817
5040
|
const code = normalizeConnectCode(options.code);
|
|
4818
|
-
const cwd2 =
|
|
5041
|
+
const cwd2 = path20.resolve(options.cwd ?? process.cwd());
|
|
4819
5042
|
const apiUrl = (options.apiUrl ?? config2.apiUrl).replace(/\/+$/, "");
|
|
4820
5043
|
const homeDir = options.homeDir ?? os7.homedir();
|
|
4821
5044
|
const environment = "local";
|
|
5045
|
+
const executionMode = await resolvePackageExecutionMode({
|
|
5046
|
+
executionMode: options.executionMode,
|
|
5047
|
+
// Only honor an explicit caller cliPath; never auto-resolve before mode detection
|
|
5048
|
+
// (published installs must not be forced into local monorepo mode).
|
|
5049
|
+
cliPath: options.cliPath,
|
|
5050
|
+
apiUrl,
|
|
5051
|
+
scriptPath: options.scriptPath,
|
|
5052
|
+
env: options.env,
|
|
5053
|
+
resolveBuiltCliPath: resolveBuiltCliPathAsync
|
|
5054
|
+
});
|
|
5055
|
+
let resolvedMode = executionMode;
|
|
5056
|
+
if (resolvedMode.kind === "local" && !resolvedMode.cliPath) {
|
|
5057
|
+
const cliPath = await resolveBuiltCliPathAsync();
|
|
5058
|
+
if (!cliPath) {
|
|
5059
|
+
throw new Error(
|
|
5060
|
+
"[memoraone-mcp] Local connect requires a built CLI at packages/mcp/dist/cli.cjs. Run pnpm build first."
|
|
5061
|
+
);
|
|
5062
|
+
}
|
|
5063
|
+
resolvedMode = { kind: "local", cliPath };
|
|
5064
|
+
}
|
|
4822
5065
|
const ensured = await ensureRepositoryBindingForRoot(cwd2, {
|
|
4823
5066
|
homeDir,
|
|
4824
5067
|
identityDeps: options.identityDeps,
|
|
@@ -4826,7 +5069,7 @@ async function runConnectCommand(options) {
|
|
|
4826
5069
|
});
|
|
4827
5070
|
if (ensured.legacyM1WarningPath) {
|
|
4828
5071
|
process.stderr.write(
|
|
4829
|
-
`[memoraone-mcp] warning: ignoring legacy ${
|
|
5072
|
+
`[memoraone-mcp] warning: ignoring legacy ${path20.basename(ensured.legacyM1WarningPath)} at ${ensured.legacyM1WarningPath} (credentials and binding are package-managed)
|
|
4830
5073
|
`
|
|
4831
5074
|
);
|
|
4832
5075
|
}
|
|
@@ -4902,7 +5145,7 @@ async function runConnectCommand(options) {
|
|
|
4902
5145
|
if (options.configureIdes !== false) {
|
|
4903
5146
|
const targets = { cursor: true, vscode: true, jetbrains: true };
|
|
4904
5147
|
const setup = options.setupIdeFiles ?? runSetupIdeFiles;
|
|
4905
|
-
const
|
|
5148
|
+
const modeSetup = setupOptionsFromPackageExecutionMode(resolvedMode);
|
|
4906
5149
|
let setupResult;
|
|
4907
5150
|
try {
|
|
4908
5151
|
setupResult = await setup({
|
|
@@ -4915,12 +5158,9 @@ async function runConnectCommand(options) {
|
|
|
4915
5158
|
noGitignore: true,
|
|
4916
5159
|
skipDaemonCleanup: true,
|
|
4917
5160
|
homeDir,
|
|
4918
|
-
|
|
4919
|
-
devMode: true,
|
|
4920
|
-
// Propagate the same backend endpoint used for redeem into all IDE configs.
|
|
5161
|
+
// Propagate the redeemed binding API URL (backend only — not execution mode).
|
|
4921
5162
|
apiUrl,
|
|
4922
|
-
|
|
4923
|
-
cliPathOverride: cliPath,
|
|
5163
|
+
...modeSetup,
|
|
4924
5164
|
...options.setupIdeOptions
|
|
4925
5165
|
});
|
|
4926
5166
|
} catch (err) {
|
|
@@ -4934,7 +5174,7 @@ async function runConnectCommand(options) {
|
|
|
4934
5174
|
}
|
|
4935
5175
|
if (setupResult.exitCode !== 0) {
|
|
4936
5176
|
const detail = setupResult.error ?? "unknown IDE setup error";
|
|
4937
|
-
const repair = formatIdeSetupRepairHint(cwd2,
|
|
5177
|
+
const repair = formatIdeSetupRepairHint(cwd2, resolvedMode);
|
|
4938
5178
|
return {
|
|
4939
5179
|
exitCode: 1,
|
|
4940
5180
|
repositoryBindingId: ensured.repositoryBindingId,
|
|
@@ -4944,9 +5184,23 @@ async function runConnectCommand(options) {
|
|
|
4944
5184
|
createdBinding: ensured.created,
|
|
4945
5185
|
legacyM1WarningPath: ensured.legacyM1WarningPath,
|
|
4946
5186
|
ideSetupError: detail,
|
|
5187
|
+
executionMode: resolvedMode,
|
|
4947
5188
|
message: `Repository connection exists for binding ${ensured.repositoryBindingId} (project ${redeemed.project_id}), but IDE configuration failed: ${detail}. Credentials and binding were kept. ${repair}`
|
|
4948
5189
|
};
|
|
4949
5190
|
}
|
|
5191
|
+
return {
|
|
5192
|
+
exitCode: 0,
|
|
5193
|
+
repositoryBindingId: ensured.repositoryBindingId,
|
|
5194
|
+
projectId: redeemed.project_id,
|
|
5195
|
+
installationPublicId: redeemed.installation_public_id,
|
|
5196
|
+
recovered: redeemed.recovered,
|
|
5197
|
+
createdBinding: ensured.created,
|
|
5198
|
+
legacyM1WarningPath: ensured.legacyM1WarningPath,
|
|
5199
|
+
executionMode: resolvedMode,
|
|
5200
|
+
configuredTargets: targets,
|
|
5201
|
+
setupResult,
|
|
5202
|
+
message: baseSuccess
|
|
5203
|
+
};
|
|
4950
5204
|
}
|
|
4951
5205
|
return {
|
|
4952
5206
|
exitCode: 0,
|
|
@@ -4956,18 +5210,27 @@ async function runConnectCommand(options) {
|
|
|
4956
5210
|
recovered: redeemed.recovered,
|
|
4957
5211
|
createdBinding: ensured.created,
|
|
4958
5212
|
legacyM1WarningPath: ensured.legacyM1WarningPath,
|
|
5213
|
+
executionMode: resolvedMode,
|
|
4959
5214
|
message: baseSuccess
|
|
4960
5215
|
};
|
|
4961
5216
|
}
|
|
4962
5217
|
function parseConnectArgv(argv) {
|
|
4963
5218
|
let code;
|
|
4964
5219
|
let apiUrl;
|
|
5220
|
+
let verbose = false;
|
|
4965
5221
|
for (let i = 0; i < argv.length; i++) {
|
|
4966
5222
|
const a = argv[i];
|
|
5223
|
+
if (a === "--verbose") {
|
|
5224
|
+
verbose = true;
|
|
5225
|
+
continue;
|
|
5226
|
+
}
|
|
4967
5227
|
if (a === "--api-url") {
|
|
4968
5228
|
const value = argv[++i];
|
|
4969
5229
|
if (!value || value.startsWith("-")) {
|
|
4970
|
-
return {
|
|
5230
|
+
return {
|
|
5231
|
+
verbose,
|
|
5232
|
+
error: "Usage: memoraone-mcp connect <code> [--api-url <url>] [--verbose]"
|
|
5233
|
+
};
|
|
4971
5234
|
}
|
|
4972
5235
|
apiUrl = value;
|
|
4973
5236
|
continue;
|
|
@@ -4975,23 +5238,29 @@ function parseConnectArgv(argv) {
|
|
|
4975
5238
|
if (a.startsWith("--api-url=")) {
|
|
4976
5239
|
const value = a.slice("--api-url=".length);
|
|
4977
5240
|
if (!value) {
|
|
4978
|
-
return {
|
|
5241
|
+
return {
|
|
5242
|
+
verbose,
|
|
5243
|
+
error: "Usage: memoraone-mcp connect <code> [--api-url <url>] [--verbose]"
|
|
5244
|
+
};
|
|
4979
5245
|
}
|
|
4980
5246
|
apiUrl = value;
|
|
4981
5247
|
continue;
|
|
4982
5248
|
}
|
|
4983
5249
|
if (a.startsWith("-")) {
|
|
4984
|
-
return { error: `Unknown connect option: ${a}` };
|
|
5250
|
+
return { verbose, error: `Unknown connect option: ${a}` };
|
|
4985
5251
|
}
|
|
4986
5252
|
if (!code) {
|
|
4987
5253
|
code = a;
|
|
4988
5254
|
continue;
|
|
4989
5255
|
}
|
|
4990
|
-
return {
|
|
5256
|
+
return {
|
|
5257
|
+
verbose,
|
|
5258
|
+
error: "Usage: memoraone-mcp connect <code> [--api-url <url>] [--verbose]"
|
|
5259
|
+
};
|
|
4991
5260
|
}
|
|
4992
|
-
return { code, apiUrl };
|
|
5261
|
+
return { code, apiUrl, verbose };
|
|
4993
5262
|
}
|
|
4994
|
-
async function cliConnect(argv) {
|
|
5263
|
+
async function cliConnect(argv, options = {}) {
|
|
4995
5264
|
const parsed2 = parseConnectArgv(argv);
|
|
4996
5265
|
if (parsed2.error) {
|
|
4997
5266
|
process.stderr.write(`${parsed2.error}
|
|
@@ -4999,19 +5268,53 @@ async function cliConnect(argv) {
|
|
|
4999
5268
|
return 1;
|
|
5000
5269
|
}
|
|
5001
5270
|
if (!parsed2.code) {
|
|
5002
|
-
process.stderr.write("Usage: memoraone-mcp connect <code> [--api-url <url>]\n");
|
|
5271
|
+
process.stderr.write("Usage: memoraone-mcp connect <code> [--api-url <url>] [--verbose]\n");
|
|
5003
5272
|
return 1;
|
|
5004
5273
|
}
|
|
5274
|
+
const println = options.println ?? ((line) => process.stdout.write(`${line}
|
|
5275
|
+
`));
|
|
5005
5276
|
try {
|
|
5006
5277
|
const result = await runConnectCommand({
|
|
5007
5278
|
code: parsed2.code,
|
|
5008
|
-
cwd: process.cwd(),
|
|
5279
|
+
cwd: options.cwd ?? process.cwd(),
|
|
5009
5280
|
apiUrl: parsed2.apiUrl,
|
|
5010
|
-
packageVersion: process.env.npm_package_version ?? null
|
|
5281
|
+
packageVersion: process.env.npm_package_version ?? null,
|
|
5282
|
+
env: options.env,
|
|
5283
|
+
...options.connectOptions
|
|
5011
5284
|
});
|
|
5012
5285
|
if (result.exitCode === 0) {
|
|
5013
|
-
|
|
5014
|
-
|
|
5286
|
+
if (parsed2.verbose) {
|
|
5287
|
+
println(result.message);
|
|
5288
|
+
if (result.projectId) {
|
|
5289
|
+
println(`[memoraone-mcp] Project id: ${result.projectId}`);
|
|
5290
|
+
}
|
|
5291
|
+
println(`[memoraone-mcp] Repository root: ${options.cwd ?? process.cwd()}`);
|
|
5292
|
+
if (result.setupResult && result.configuredTargets) {
|
|
5293
|
+
logSetupIdeFilesVerboseSuccess(
|
|
5294
|
+
{
|
|
5295
|
+
targets: result.configuredTargets,
|
|
5296
|
+
dryRun: false,
|
|
5297
|
+
result: result.setupResult
|
|
5298
|
+
},
|
|
5299
|
+
println
|
|
5300
|
+
);
|
|
5301
|
+
}
|
|
5302
|
+
} else {
|
|
5303
|
+
const presentation = createTerminalPresentation({
|
|
5304
|
+
env: options.env ?? process.env,
|
|
5305
|
+
stdoutIsTty: options.stdoutIsTty ?? process.stdout.isTTY === true,
|
|
5306
|
+
color: options.color,
|
|
5307
|
+
unicode: options.unicode
|
|
5308
|
+
});
|
|
5309
|
+
printSetupSuccess(
|
|
5310
|
+
{
|
|
5311
|
+
repositoryConnected: true,
|
|
5312
|
+
targets: result.configuredTargets,
|
|
5313
|
+
presentation
|
|
5314
|
+
},
|
|
5315
|
+
println
|
|
5316
|
+
);
|
|
5317
|
+
}
|
|
5015
5318
|
} else {
|
|
5016
5319
|
process.stderr.write(`[memoraone-mcp] ${result.message}
|
|
5017
5320
|
`);
|
|
@@ -5033,7 +5336,7 @@ if (args.includes("--version") || args.includes("-v")) {
|
|
|
5033
5336
|
}
|
|
5034
5337
|
if (args.includes("--help") || args.includes("-h")) {
|
|
5035
5338
|
console.log(
|
|
5036
|
-
"Usage: memoraone-mcp [--version] [--help]\n memoraone-mcp connect <code> [--api-url <url>]\n memoraone-mcp [--daemon --binding-id <mrb_\u2026> [--ide cursor|copilot-vscode|jetbrains]]\n memoraone-mcp setup-ide-files [--all|--cursor|--vscode|--jetbrains] [--force] [--dry-run] [--no-gitignore] [--cleanup] [--dev] [--repair] [--workspace-root <path>] [--api-url <url>]\n Cursor API environment (with --cursor or --all): --local (node + built cli.cjs + local API) | --staging (npx + staging API)\n --workspace-root: configure an explicit bound workspace (skips .git discovery; for fileless Local MCP repair)\n --api-url: developer-only local/dev API endpoint (defaults from binding or http://localhost:3001; never Studio :3000)\n memoraone-mcp cleanup [--project-id <uuid>] [--ide cursor|copilot-vscode|jetbrains] [--dry-run] [--all-projects] [--yes]"
|
|
5339
|
+
"Usage: memoraone-mcp [--version] [--help]\n memoraone-mcp connect <code> [--api-url <url>] [--verbose]\n memoraone-mcp [--daemon --binding-id <mrb_\u2026> [--ide cursor|copilot-vscode|jetbrains]]\n memoraone-mcp setup-ide-files [--all|--cursor|--vscode|--jetbrains] [--force] [--dry-run] [--no-gitignore] [--cleanup] [--dev] [--repair] [--workspace-root <path>] [--api-url <url>] [--verbose]\n Cursor API environment (with --cursor or --all): --local (node + built cli.cjs + local API) | --staging (npx + staging API)\n --workspace-root: configure an explicit bound workspace (skips .git discovery; for fileless Local MCP repair)\n --api-url: developer-only local/dev API endpoint (defaults from binding or http://localhost:3001; never Studio :3000)\n --verbose: show developer diagnostics (paths, backups, daemon cleanup, handshake)\n memoraone-mcp cleanup [--project-id <uuid>] [--ide cursor|copilot-vscode|jetbrains] [--dry-run] [--all-projects] [--yes]"
|
|
5037
5340
|
);
|
|
5038
5341
|
process.exit(0);
|
|
5039
5342
|
}
|