@memoraone/mcp 0.1.32 → 0.1.34
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 +514 -94
- 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.34",
|
|
34
34
|
type: "module",
|
|
35
35
|
main: "dist/index.cjs",
|
|
36
36
|
bin: {
|
|
@@ -562,8 +562,8 @@ var StdioLineReader = class {
|
|
|
562
562
|
if (this.closed) {
|
|
563
563
|
return null;
|
|
564
564
|
}
|
|
565
|
-
return new Promise((
|
|
566
|
-
this.waiters.push(
|
|
565
|
+
return new Promise((resolve9) => {
|
|
566
|
+
this.waiters.push(resolve9);
|
|
567
567
|
});
|
|
568
568
|
}
|
|
569
569
|
/** Re-queue lines read during an intermediate protocol step (e.g. roots/list) for the main bridge loop. */
|
|
@@ -822,9 +822,9 @@ function summarizeJsonRpcMethod(line) {
|
|
|
822
822
|
}
|
|
823
823
|
}
|
|
824
824
|
function connectWithRetry(socketPath, log, maxRetries, retryDelayMs, connect2) {
|
|
825
|
-
return new Promise((
|
|
825
|
+
return new Promise((resolve9, reject) => {
|
|
826
826
|
const tryConnect = (attempt) => {
|
|
827
|
-
connect2(socketPath).then(
|
|
827
|
+
connect2(socketPath).then(resolve9).catch((err) => {
|
|
828
828
|
if (attempt >= maxRetries) {
|
|
829
829
|
reject(err);
|
|
830
830
|
return;
|
|
@@ -897,8 +897,8 @@ var BridgeDaemonRouter = class {
|
|
|
897
897
|
this.maxRetries = options.maxRetries ?? 5;
|
|
898
898
|
this.retryDelayMs = options.retryDelayMs ?? 200;
|
|
899
899
|
this.lineReader = options.lineReader ?? null;
|
|
900
|
-
this.connectImpl = options.connect ?? ((socketPath) => new Promise((
|
|
901
|
-
const socket = net.connect(socketPath, () =>
|
|
900
|
+
this.connectImpl = options.connect ?? ((socketPath) => new Promise((resolve9, reject) => {
|
|
901
|
+
const socket = net.connect(socketPath, () => resolve9(socket));
|
|
902
902
|
socket.on("error", reject);
|
|
903
903
|
}));
|
|
904
904
|
this.spawnDaemonImpl = options.spawnDaemon ?? (async (binding) => {
|
|
@@ -1142,9 +1142,9 @@ async function runBridgeProxy(options) {
|
|
|
1142
1142
|
}
|
|
1143
1143
|
|
|
1144
1144
|
// src/setupIdeFiles.ts
|
|
1145
|
-
var
|
|
1145
|
+
var fs8 = __toESM(require("fs/promises"), 1);
|
|
1146
1146
|
var os4 = __toESM(require("os"), 1);
|
|
1147
|
-
var
|
|
1147
|
+
var path10 = __toESM(require("path"), 1);
|
|
1148
1148
|
|
|
1149
1149
|
// src/cleanup.ts
|
|
1150
1150
|
var fs5 = __toESM(require("fs/promises"), 1);
|
|
@@ -1163,17 +1163,36 @@ var import_node_util = require("util");
|
|
|
1163
1163
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
|
|
1164
1164
|
var MEMORAONE_PROD_API_URL = "https://api.memoraone.com";
|
|
1165
1165
|
var MEMORAONE_LOCAL_API_URL = "http://localhost:3001";
|
|
1166
|
+
var MEMORAONE_STAGING_API_URL = "https://memora-api-staging-phbtrzocjq-uk.a.run.app";
|
|
1166
1167
|
var MEMORAONE_STAGING_API_URL_PREFIX = "https://memora-api-staging-";
|
|
1167
|
-
function
|
|
1168
|
+
function cursorMcpApiUrl(environment) {
|
|
1169
|
+
if (environment === "local") return MEMORAONE_LOCAL_API_URL;
|
|
1170
|
+
if (environment === "staging") return MEMORAONE_STAGING_API_URL;
|
|
1171
|
+
return MEMORAONE_PROD_API_URL;
|
|
1172
|
+
}
|
|
1173
|
+
function buildMemoraoneCursorMcpServer(options) {
|
|
1168
1174
|
const env = {
|
|
1169
|
-
MEMORAONE_API_URL:
|
|
1175
|
+
MEMORAONE_API_URL: cursorMcpApiUrl(options.environment),
|
|
1170
1176
|
MEMORAONE_IDE_TYPE: "cursor"
|
|
1171
1177
|
};
|
|
1172
|
-
if (workspaceRoot !== void 0) {
|
|
1173
|
-
env[MEMORAONE_WORKSPACE_ROOT_ENV] = path6.resolve(workspaceRoot);
|
|
1178
|
+
if (options.workspaceRoot !== void 0) {
|
|
1179
|
+
env[MEMORAONE_WORKSPACE_ROOT_ENV] = path6.resolve(options.workspaceRoot);
|
|
1180
|
+
}
|
|
1181
|
+
if (options.environment === "local") {
|
|
1182
|
+
if (!options.cliPath) {
|
|
1183
|
+
throw new Error("[setup-ide-files] Local Cursor MCP config requires a built CLI path.");
|
|
1184
|
+
}
|
|
1185
|
+
return {
|
|
1186
|
+
command: "node",
|
|
1187
|
+
args: [options.cliPath],
|
|
1188
|
+
env
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
if (!options.npxPath) {
|
|
1192
|
+
throw new Error("[setup-ide-files] Cursor MCP config requires a resolved npx path.");
|
|
1174
1193
|
}
|
|
1175
1194
|
return {
|
|
1176
|
-
command: npxPath,
|
|
1195
|
+
command: options.npxPath,
|
|
1177
1196
|
args: ["-y", "@memoraone/mcp@latest"],
|
|
1178
1197
|
env
|
|
1179
1198
|
};
|
|
@@ -1272,10 +1291,16 @@ async function resolveNpxPath() {
|
|
|
1272
1291
|
}
|
|
1273
1292
|
return null;
|
|
1274
1293
|
}
|
|
1275
|
-
function mergeCursorRepoMcpConfigObject(existing,
|
|
1294
|
+
function mergeCursorRepoMcpConfigObject(existing, writeOptions) {
|
|
1295
|
+
const environment = writeOptions.environment ?? "production";
|
|
1276
1296
|
const base = existing && typeof existing === "object" ? { ...existing } : { mcpServers: {} };
|
|
1277
1297
|
const mcpServers = typeof base.mcpServers === "object" && base.mcpServers !== null && !Array.isArray(base.mcpServers) ? { ...base.mcpServers } : {};
|
|
1278
|
-
mcpServers.memoraone = buildMemoraoneCursorMcpServer(
|
|
1298
|
+
mcpServers.memoraone = buildMemoraoneCursorMcpServer({
|
|
1299
|
+
environment,
|
|
1300
|
+
npxPath: writeOptions.npxPath,
|
|
1301
|
+
cliPath: writeOptions.cliPath,
|
|
1302
|
+
workspaceRoot: writeOptions.repoRoot
|
|
1303
|
+
});
|
|
1279
1304
|
return { ...base, mcpServers };
|
|
1280
1305
|
}
|
|
1281
1306
|
function isMemoraoneManagedApiUrl(url) {
|
|
@@ -1394,23 +1419,30 @@ function logCursorMcpConfigAudit(prefix, audit) {
|
|
|
1394
1419
|
);
|
|
1395
1420
|
}
|
|
1396
1421
|
}
|
|
1397
|
-
function logCursorMcpCliSummary(info, dryRun) {
|
|
1398
|
-
const { repoConfigPath, repoOutcome, npxPath, repoBackupPath, globalConfigPath, globalMemoraoneRemoved, globalBackupPath } = info;
|
|
1422
|
+
function logCursorMcpCliSummary(info, dryRun, opts) {
|
|
1423
|
+
const { repoConfigPath, repoOutcome, npxPath, cliPath, repoBackupPath, globalConfigPath, globalMemoraoneRemoved, globalBackupPath } = info;
|
|
1424
|
+
const interactive = opts?.forInteractivePostSetup === true;
|
|
1399
1425
|
console.log(`[setup-ide-files] Cursor repo MCP config: ${repoConfigPath}`);
|
|
1400
|
-
|
|
1426
|
+
if (cliPath) {
|
|
1427
|
+
console.log(`[setup-ide-files] Resolved local CLI: ${cliPath}`);
|
|
1428
|
+
} else if (npxPath) {
|
|
1429
|
+
console.log(`[setup-ide-files] Resolved npx: ${npxPath}`);
|
|
1430
|
+
}
|
|
1401
1431
|
if (repoBackupPath) {
|
|
1402
1432
|
console.log(`[setup-ide-files] Cursor repo MCP config backup: ${repoBackupPath}`);
|
|
1403
1433
|
}
|
|
1404
|
-
if (
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1434
|
+
if (!interactive) {
|
|
1435
|
+
if (repoOutcome === "created") {
|
|
1436
|
+
console.log(
|
|
1437
|
+
dryRun ? `[setup-ide-files] Cursor repo MCP config would be created: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config created: ${repoConfigPath}`
|
|
1438
|
+
);
|
|
1439
|
+
} else if (repoOutcome === "updated") {
|
|
1440
|
+
console.log(
|
|
1441
|
+
dryRun ? `[setup-ide-files] Cursor repo MCP config would be updated: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config updated: ${repoConfigPath}`
|
|
1442
|
+
);
|
|
1443
|
+
} else if (repoOutcome === "skipped") {
|
|
1444
|
+
console.log(`[setup-ide-files] Cursor repo MCP config unchanged: ${repoConfigPath}`);
|
|
1445
|
+
}
|
|
1414
1446
|
}
|
|
1415
1447
|
if (globalMemoraoneRemoved && globalConfigPath) {
|
|
1416
1448
|
console.log(
|
|
@@ -1427,9 +1459,11 @@ function logCursorMcpCliSummary(info, dryRun) {
|
|
|
1427
1459
|
console.log(
|
|
1428
1460
|
"[setup-ide-files] Each Cursor window uses this repo\u2019s .cursor/mcp.json (separate MCP process per repo)."
|
|
1429
1461
|
);
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1462
|
+
if (!interactive) {
|
|
1463
|
+
console.log(
|
|
1464
|
+
"[setup-ide-files] Fully quit Cursor and reopen this repo for MCP changes to take effect."
|
|
1465
|
+
);
|
|
1466
|
+
}
|
|
1433
1467
|
}
|
|
1434
1468
|
|
|
1435
1469
|
// src/cleanup.ts
|
|
@@ -2094,7 +2128,7 @@ async function buildJetBrainsMemoraoneServer(options) {
|
|
|
2094
2128
|
async function verifyJetBrainsMcpHandshake(options) {
|
|
2095
2129
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
2096
2130
|
const { server } = options;
|
|
2097
|
-
return new Promise((
|
|
2131
|
+
return new Promise((resolve9) => {
|
|
2098
2132
|
let settled = false;
|
|
2099
2133
|
const finish = (ok, detail) => {
|
|
2100
2134
|
if (settled) return;
|
|
@@ -2104,7 +2138,7 @@ async function verifyJetBrainsMcpHandshake(options) {
|
|
|
2104
2138
|
child.kill();
|
|
2105
2139
|
} catch {
|
|
2106
2140
|
}
|
|
2107
|
-
|
|
2141
|
+
resolve9({ ok, detail });
|
|
2108
2142
|
};
|
|
2109
2143
|
const child = (0, import_node_child_process4.spawn)(server.command, [...server.args], {
|
|
2110
2144
|
env: { ...process.env, ...server.env },
|
|
@@ -2308,6 +2342,288 @@ function logJetBrainsMcpCliSummary(info, dryRun) {
|
|
|
2308
2342
|
);
|
|
2309
2343
|
}
|
|
2310
2344
|
|
|
2345
|
+
// src/resolveBuiltCliPath.ts
|
|
2346
|
+
var fs7 = __toESM(require("fs/promises"), 1);
|
|
2347
|
+
var path9 = __toESM(require("path"), 1);
|
|
2348
|
+
var MONOREPO_CLI_REL = path9.join("packages", "mcp", "dist", "cli.cjs");
|
|
2349
|
+
async function pathExists3(filePath) {
|
|
2350
|
+
try {
|
|
2351
|
+
await fs7.access(filePath);
|
|
2352
|
+
return true;
|
|
2353
|
+
} catch {
|
|
2354
|
+
return false;
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
async function findMonorepoCliFrom(startDir) {
|
|
2358
|
+
let current = path9.resolve(startDir);
|
|
2359
|
+
const root = path9.parse(current).root;
|
|
2360
|
+
while (true) {
|
|
2361
|
+
const candidate = path9.join(current, MONOREPO_CLI_REL);
|
|
2362
|
+
if (await pathExists3(candidate)) {
|
|
2363
|
+
return path9.resolve(candidate);
|
|
2364
|
+
}
|
|
2365
|
+
if (current === root) break;
|
|
2366
|
+
current = path9.dirname(current);
|
|
2367
|
+
}
|
|
2368
|
+
return null;
|
|
2369
|
+
}
|
|
2370
|
+
async function resolveBuiltCliPathAsync(options) {
|
|
2371
|
+
const searchDirs = [];
|
|
2372
|
+
if (options?.searchFrom !== void 0) {
|
|
2373
|
+
const dirs = Array.isArray(options.searchFrom) ? options.searchFrom : [options.searchFrom];
|
|
2374
|
+
searchDirs.push(...dirs);
|
|
2375
|
+
}
|
|
2376
|
+
searchDirs.push(process.cwd());
|
|
2377
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2378
|
+
for (const dir of searchDirs) {
|
|
2379
|
+
const key = path9.resolve(dir);
|
|
2380
|
+
if (seen.has(key)) continue;
|
|
2381
|
+
seen.add(key);
|
|
2382
|
+
const found = await findMonorepoCliFrom(key);
|
|
2383
|
+
if (found) return found;
|
|
2384
|
+
}
|
|
2385
|
+
const here = process.argv[1] ? path9.dirname(path9.resolve(process.argv[1])) : process.cwd();
|
|
2386
|
+
const candidates = [
|
|
2387
|
+
path9.join(here, "cli.cjs"),
|
|
2388
|
+
path9.join(here, "..", "dist", "cli.cjs"),
|
|
2389
|
+
path9.join(here, "..", "..", "dist", "cli.cjs")
|
|
2390
|
+
];
|
|
2391
|
+
for (const candidate of candidates) {
|
|
2392
|
+
if (await pathExists3(candidate)) {
|
|
2393
|
+
return path9.resolve(candidate);
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
return null;
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
// src/openCursorMcpSettings.ts
|
|
2400
|
+
var import_node_child_process5 = require("child_process");
|
|
2401
|
+
var readline4 = __toESM(require("readline/promises"), 1);
|
|
2402
|
+
var import_node_util3 = require("util");
|
|
2403
|
+
|
|
2404
|
+
// src/terminalPresentation.ts
|
|
2405
|
+
var ANSI = {
|
|
2406
|
+
reset: "\x1B[0m",
|
|
2407
|
+
bold: "\x1B[1m",
|
|
2408
|
+
dim: "\x1B[2m",
|
|
2409
|
+
green: "\x1B[32m",
|
|
2410
|
+
yellow: "\x1B[33m",
|
|
2411
|
+
cyan: "\x1B[36m"
|
|
2412
|
+
};
|
|
2413
|
+
function isCiLikeEnv(env = process.env) {
|
|
2414
|
+
if (env.CI === "true" || env.CI === "1") return true;
|
|
2415
|
+
if (env.GITHUB_ACTIONS === "true" || env.GITHUB_ACTIONS === "1") return true;
|
|
2416
|
+
if (env.GITLAB_CI === "true" || env.GITLAB_CI === "1") return true;
|
|
2417
|
+
if (env.CIRCLECI === "true" || env.CIRCLECI === "1") return true;
|
|
2418
|
+
if (env.BUILDKITE === "true" || env.BUILDKITE === "1") return true;
|
|
2419
|
+
if (typeof env.CI === "string" && env.CI.trim() !== "" && env.CI !== "0" && env.CI !== "false") {
|
|
2420
|
+
return true;
|
|
2421
|
+
}
|
|
2422
|
+
return false;
|
|
2423
|
+
}
|
|
2424
|
+
function shouldEnableAnsiColor(opts = {}) {
|
|
2425
|
+
if (typeof opts.color === "boolean") return opts.color;
|
|
2426
|
+
const env = opts.env ?? process.env;
|
|
2427
|
+
if (env.NO_COLOR !== void 0) return false;
|
|
2428
|
+
if (isCiLikeEnv(env)) return false;
|
|
2429
|
+
const tty = opts.stdoutIsTty ?? process.stdout.isTTY === true;
|
|
2430
|
+
return tty;
|
|
2431
|
+
}
|
|
2432
|
+
function shouldUseUnicodeSymbols(opts = {}) {
|
|
2433
|
+
if (typeof opts.unicode === "boolean") return opts.unicode;
|
|
2434
|
+
const env = opts.env ?? process.env;
|
|
2435
|
+
const tty = opts.stdoutIsTty ?? process.stdout.isTTY === true;
|
|
2436
|
+
if (!tty) return false;
|
|
2437
|
+
if (env.TERM === "dumb") return false;
|
|
2438
|
+
if (process.platform === "win32") {
|
|
2439
|
+
return Boolean(
|
|
2440
|
+
env.WT_SESSION || env.WT_PROFILE_ID || env.ConEmuANSI === "ON" || env.TERM_PROGRAM === "vscode" || env.TERM_PROGRAM === "cursor" || typeof env.TERM === "string" && env.TERM !== "" && env.TERM !== "dumb"
|
|
2441
|
+
);
|
|
2442
|
+
}
|
|
2443
|
+
return true;
|
|
2444
|
+
}
|
|
2445
|
+
function paint(enabled, code, text) {
|
|
2446
|
+
if (!enabled || text === "") return text;
|
|
2447
|
+
return `${code}${text}${ANSI.reset}`;
|
|
2448
|
+
}
|
|
2449
|
+
function createTerminalPresentation(opts = {}) {
|
|
2450
|
+
const color = shouldEnableAnsiColor(opts);
|
|
2451
|
+
const unicode = shouldUseUnicodeSymbols(opts);
|
|
2452
|
+
const successSymbol = unicode ? "\u2713" : "[OK]";
|
|
2453
|
+
const warningSymbol = unicode ? "\u26A0" : "[WARN]";
|
|
2454
|
+
const nextActionPrefix = unicode ? "\u2192" : "Next:";
|
|
2455
|
+
return {
|
|
2456
|
+
color,
|
|
2457
|
+
unicode,
|
|
2458
|
+
bold: (text) => paint(color, ANSI.bold, text),
|
|
2459
|
+
green: (text) => paint(color, ANSI.green, text),
|
|
2460
|
+
cyan: (text) => paint(color, ANSI.cyan, text),
|
|
2461
|
+
yellow: (text) => paint(color, ANSI.yellow, text),
|
|
2462
|
+
dim: (text) => paint(color, ANSI.dim, text),
|
|
2463
|
+
successSymbol,
|
|
2464
|
+
warningSymbol,
|
|
2465
|
+
nextActionPrefix,
|
|
2466
|
+
successLine: (message) => paint(color, ANSI.green, `${successSymbol} ${message}`),
|
|
2467
|
+
warningLine: (message) => paint(color, ANSI.yellow, `${warningSymbol} ${message}`),
|
|
2468
|
+
nextActionLine: (message) => `${nextActionPrefix} ${message}`,
|
|
2469
|
+
heading: (text) => paint(color, ANSI.bold, text),
|
|
2470
|
+
indent: (text) => ` ${text}`
|
|
2471
|
+
};
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
// src/openCursorMcpSettings.ts
|
|
2475
|
+
var execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process5.execFile);
|
|
2476
|
+
var OPEN_CURSOR_MCP_SETTINGS_PROMPT = "Open Cursor MCP settings now? [Y/n] ";
|
|
2477
|
+
function resolvePresentation(deps) {
|
|
2478
|
+
if (deps.presentation) return deps.presentation;
|
|
2479
|
+
const opts = {
|
|
2480
|
+
env: deps.env ?? process.env,
|
|
2481
|
+
stdoutIsTty: deps.stdoutIsTty ?? process.stdout.isTTY === true,
|
|
2482
|
+
color: deps.color,
|
|
2483
|
+
unicode: deps.unicode
|
|
2484
|
+
};
|
|
2485
|
+
return createTerminalPresentation(opts);
|
|
2486
|
+
}
|
|
2487
|
+
function shouldPromptOpenCursorMcpSettings(opts) {
|
|
2488
|
+
if (!opts.explicitCursor) return false;
|
|
2489
|
+
if (opts.all) return false;
|
|
2490
|
+
if (opts.dryRun) return false;
|
|
2491
|
+
if (!opts.stdinIsTty) return false;
|
|
2492
|
+
if (isCiLikeEnv(opts.env ?? process.env)) return false;
|
|
2493
|
+
return true;
|
|
2494
|
+
}
|
|
2495
|
+
function isYesDefaultAnswer(answer) {
|
|
2496
|
+
const trimmed = answer.trim();
|
|
2497
|
+
if (trimmed === "") return true;
|
|
2498
|
+
if (/^y(es)?$/i.test(trimmed)) return true;
|
|
2499
|
+
if (/^n(o)?$/i.test(trimmed)) return false;
|
|
2500
|
+
return false;
|
|
2501
|
+
}
|
|
2502
|
+
async function confirmYesDefault(question, deps = {}) {
|
|
2503
|
+
if (deps.ask) {
|
|
2504
|
+
return isYesDefaultAnswer(await deps.ask(question));
|
|
2505
|
+
}
|
|
2506
|
+
const input2 = deps.input ?? process.stdin;
|
|
2507
|
+
const output2 = deps.output ?? process.stdout;
|
|
2508
|
+
if (!("isTTY" in input2) || !input2.isTTY) {
|
|
2509
|
+
return false;
|
|
2510
|
+
}
|
|
2511
|
+
const rl = readline4.createInterface({ input: input2, output: output2 });
|
|
2512
|
+
try {
|
|
2513
|
+
const answer = await rl.question(question.endsWith(" ") ? question : `${question} `);
|
|
2514
|
+
return isYesDefaultAnswer(answer);
|
|
2515
|
+
} finally {
|
|
2516
|
+
rl.close();
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
function collectOutcomePaths(outcomes) {
|
|
2520
|
+
const created = [];
|
|
2521
|
+
const updated = [];
|
|
2522
|
+
for (const [file, outcome] of Object.entries(outcomes)) {
|
|
2523
|
+
if (outcome === "created") created.push(file);
|
|
2524
|
+
else if (outcome === "updated") updated.push(file);
|
|
2525
|
+
}
|
|
2526
|
+
return { created, updated };
|
|
2527
|
+
}
|
|
2528
|
+
function formatCursorSetupCompletedSummary(opts, presentation = createTerminalPresentation({ color: false, unicode: false })) {
|
|
2529
|
+
const { created, updated } = collectOutcomePaths(opts.outcomes);
|
|
2530
|
+
const tp = presentation;
|
|
2531
|
+
const lines = [
|
|
2532
|
+
tp.successLine("MemoraOne setup completed for Cursor"),
|
|
2533
|
+
"",
|
|
2534
|
+
tp.heading("Repository"),
|
|
2535
|
+
tp.indent(tp.cyan(opts.repoRoot)),
|
|
2536
|
+
"",
|
|
2537
|
+
tp.heading("Changes")
|
|
2538
|
+
];
|
|
2539
|
+
if (created.length === 0 && updated.length === 0) {
|
|
2540
|
+
lines.push(tp.indent(tp.dim("No file changes needed")));
|
|
2541
|
+
} else {
|
|
2542
|
+
if (created.length) {
|
|
2543
|
+
lines.push(tp.indent(`Created: ${created.join(", ")}`));
|
|
2544
|
+
}
|
|
2545
|
+
if (updated.length) {
|
|
2546
|
+
lines.push(tp.indent(`Updated: ${updated.join(", ")}`));
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
return lines;
|
|
2550
|
+
}
|
|
2551
|
+
function printCursorSetupCompletedSummary(opts, println = console.log, presentation) {
|
|
2552
|
+
const tp = presentation ?? createTerminalPresentation();
|
|
2553
|
+
for (const line of formatCursorSetupCompletedSummary(opts, tp)) {
|
|
2554
|
+
println(line);
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
function macosOpenCursorMcpSettingsAppleScript() {
|
|
2558
|
+
return [
|
|
2559
|
+
'tell application "Cursor" to activate',
|
|
2560
|
+
"delay 0.5",
|
|
2561
|
+
'tell application "System Events"',
|
|
2562
|
+
'keystroke "p" using {command down, shift down}',
|
|
2563
|
+
"delay 0.4",
|
|
2564
|
+
'keystroke "View: Open MCP Settings"',
|
|
2565
|
+
"delay 0.4",
|
|
2566
|
+
"key code 36",
|
|
2567
|
+
"end tell"
|
|
2568
|
+
].join("\n");
|
|
2569
|
+
}
|
|
2570
|
+
async function openCursorMcpSettingsViaOsascript(execFileImpl = execFileAsync3) {
|
|
2571
|
+
await execFileImpl("osascript", ["-e", macosOpenCursorMcpSettingsAppleScript()], {
|
|
2572
|
+
timeout: 3e4
|
|
2573
|
+
});
|
|
2574
|
+
}
|
|
2575
|
+
function manualCursorMcpSettingsSteps(platform) {
|
|
2576
|
+
const chord = platform === "darwin" ? "Command + Shift + P" : "Ctrl + Shift + P";
|
|
2577
|
+
return [
|
|
2578
|
+
"To finish setup manually:",
|
|
2579
|
+
"1. Open this repository in Cursor.",
|
|
2580
|
+
`2. Press ${chord}.`,
|
|
2581
|
+
'3. Run "View: Open MCP Settings".',
|
|
2582
|
+
'4. Find "memoraone" and enable it.',
|
|
2583
|
+
"5. Confirm it turns green.",
|
|
2584
|
+
"6. Return to MemoraOne Studio and refresh Sources."
|
|
2585
|
+
];
|
|
2586
|
+
}
|
|
2587
|
+
function printManualCursorMcpSettingsSteps(platform, println = console.log) {
|
|
2588
|
+
for (const line of manualCursorMcpSettingsSteps(platform)) {
|
|
2589
|
+
println(line);
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
function formatOpenCursorMcpSettingsPrompt(presentation = createTerminalPresentation({ color: false, unicode: false })) {
|
|
2593
|
+
return `${presentation.indent(OPEN_CURSOR_MCP_SETTINGS_PROMPT.trimEnd())} `;
|
|
2594
|
+
}
|
|
2595
|
+
async function runOpenCursorMcpSettingsFlow(deps = {}) {
|
|
2596
|
+
const platform = deps.platform ?? process.platform;
|
|
2597
|
+
const println = deps.println ?? console.log;
|
|
2598
|
+
const tp = resolvePresentation(deps);
|
|
2599
|
+
const confirm = deps.confirm ?? ((question) => confirmYesDefault(question));
|
|
2600
|
+
println("");
|
|
2601
|
+
println(tp.heading("Next"));
|
|
2602
|
+
const yes = await confirm(formatOpenCursorMcpSettingsPrompt(tp));
|
|
2603
|
+
if (!yes) {
|
|
2604
|
+
printManualCursorMcpSettingsSteps(platform, println);
|
|
2605
|
+
return;
|
|
2606
|
+
}
|
|
2607
|
+
if (platform === "darwin") {
|
|
2608
|
+
println(tp.warningLine("macOS may request Automation or Accessibility permission."));
|
|
2609
|
+
try {
|
|
2610
|
+
const open = deps.openViaOsascript ?? (() => openCursorMcpSettingsViaOsascript(deps.execFile ?? execFileAsync3));
|
|
2611
|
+
await open();
|
|
2612
|
+
println(tp.successLine('Confirm "memoraone" is enabled and green'));
|
|
2613
|
+
println(tp.nextActionLine("Return to MemoraOne Studio and refresh Sources"));
|
|
2614
|
+
} catch (err) {
|
|
2615
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
2616
|
+
println(tp.warningLine(`Could not open Cursor MCP settings automatically (${detail}).`));
|
|
2617
|
+
println(
|
|
2618
|
+
"Permission may be required at: System Settings \u2192 Privacy & Security \u2192 Accessibility"
|
|
2619
|
+
);
|
|
2620
|
+
printManualCursorMcpSettingsSteps("darwin", println);
|
|
2621
|
+
}
|
|
2622
|
+
return;
|
|
2623
|
+
}
|
|
2624
|
+
printManualCursorMcpSettingsSteps(platform, println);
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2311
2627
|
// src/setupIdeFiles.ts
|
|
2312
2628
|
var MANAGED_MARKER = "<!-- MemoraOne managed IDE helper -->";
|
|
2313
2629
|
var GITIGNORE_MEMORAONE_COMMENT = "# MemoraOne local project binding / API key";
|
|
@@ -2323,15 +2639,15 @@ function buildMemoraoneMcpServer(ideType, command = "npx") {
|
|
|
2323
2639
|
};
|
|
2324
2640
|
}
|
|
2325
2641
|
function assertUnderRepoRoot(repoRoot, absPath) {
|
|
2326
|
-
const normRoot =
|
|
2327
|
-
const normPath =
|
|
2328
|
-
if (normPath !==
|
|
2642
|
+
const normRoot = path10.resolve(repoRoot) + path10.sep;
|
|
2643
|
+
const normPath = path10.resolve(absPath);
|
|
2644
|
+
if (normPath !== path10.resolve(repoRoot) && !normPath.startsWith(normRoot)) {
|
|
2329
2645
|
throw new Error(`[setup-ide-files] Refusing to write outside repo root: ${absPath}`);
|
|
2330
2646
|
}
|
|
2331
2647
|
}
|
|
2332
|
-
async function
|
|
2648
|
+
async function pathExists4(filePath) {
|
|
2333
2649
|
try {
|
|
2334
|
-
await
|
|
2650
|
+
await fs8.access(filePath);
|
|
2335
2651
|
return true;
|
|
2336
2652
|
} catch {
|
|
2337
2653
|
return false;
|
|
@@ -2352,12 +2668,12 @@ ${GITIGNORE_MEMORAONE_ENTRY}
|
|
|
2352
2668
|
}
|
|
2353
2669
|
async function ensureGitignoreMemoraone(repoRoot, opts) {
|
|
2354
2670
|
if (opts.noGitignore) return "skipped";
|
|
2355
|
-
const abs =
|
|
2671
|
+
const abs = path10.join(repoRoot, ".gitignore");
|
|
2356
2672
|
assertUnderRepoRoot(repoRoot, abs);
|
|
2357
2673
|
let prior = "";
|
|
2358
2674
|
let existed = false;
|
|
2359
2675
|
try {
|
|
2360
|
-
prior = await
|
|
2676
|
+
prior = await fs8.readFile(abs, "utf8");
|
|
2361
2677
|
existed = true;
|
|
2362
2678
|
} catch (err) {
|
|
2363
2679
|
const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
@@ -2368,22 +2684,22 @@ async function ensureGitignoreMemoraone(repoRoot, opts) {
|
|
|
2368
2684
|
const separator = existed && prior.length > 0 ? prior.endsWith("\n") ? "\n" : "\n\n" : "";
|
|
2369
2685
|
const next = (existed ? prior : "") + separator + block;
|
|
2370
2686
|
if (opts.dryRun) return existed ? "updated" : "created";
|
|
2371
|
-
await
|
|
2687
|
+
await fs8.writeFile(abs, next, "utf8");
|
|
2372
2688
|
return existed ? "updated" : "created";
|
|
2373
2689
|
}
|
|
2374
2690
|
async function findRepoRoot(startDir) {
|
|
2375
|
-
let current =
|
|
2376
|
-
const root =
|
|
2691
|
+
let current = path10.resolve(startDir);
|
|
2692
|
+
const root = path10.parse(current).root;
|
|
2377
2693
|
while (true) {
|
|
2378
|
-
const gitPath =
|
|
2379
|
-
const m1Path =
|
|
2380
|
-
if (await
|
|
2694
|
+
const gitPath = path10.join(current, ".git");
|
|
2695
|
+
const m1Path = path10.join(current, "memoraone.m1");
|
|
2696
|
+
if (await pathExists4(gitPath) || await pathExists4(m1Path)) {
|
|
2381
2697
|
return current;
|
|
2382
2698
|
}
|
|
2383
2699
|
if (current === root) {
|
|
2384
2700
|
return null;
|
|
2385
2701
|
}
|
|
2386
|
-
current =
|
|
2702
|
+
current = path10.dirname(current);
|
|
2387
2703
|
}
|
|
2388
2704
|
}
|
|
2389
2705
|
function stripLeadingLineComments3(text) {
|
|
@@ -2436,47 +2752,47 @@ function buildVscodeMcpJsonBody(existing) {
|
|
|
2436
2752
|
const merged = { ...base, servers };
|
|
2437
2753
|
return mcpJsonHeader() + JSON.stringify(merged, null, 2) + "\n";
|
|
2438
2754
|
}
|
|
2439
|
-
function buildCursorMcpJsonBody(existing,
|
|
2440
|
-
const merged = mergeCursorRepoMcpConfigObject(existing,
|
|
2755
|
+
function buildCursorMcpJsonBody(existing, writeOptions) {
|
|
2756
|
+
const merged = mergeCursorRepoMcpConfigObject(existing, writeOptions);
|
|
2441
2757
|
return mcpJsonHeader() + JSON.stringify(merged, null, 2) + "\n";
|
|
2442
2758
|
}
|
|
2443
2759
|
async function writeManagedMarkdown(repoRoot, relPath, fullContent, opts) {
|
|
2444
|
-
const abs =
|
|
2760
|
+
const abs = path10.join(repoRoot, relPath);
|
|
2445
2761
|
assertUnderRepoRoot(repoRoot, abs);
|
|
2446
2762
|
let prior = "";
|
|
2447
2763
|
let existed = false;
|
|
2448
2764
|
try {
|
|
2449
|
-
prior = await
|
|
2765
|
+
prior = await fs8.readFile(abs, "utf8");
|
|
2450
2766
|
existed = true;
|
|
2451
2767
|
} catch (err) {
|
|
2452
2768
|
if (err?.code !== "ENOENT") throw err;
|
|
2453
2769
|
}
|
|
2454
2770
|
if (!existed) {
|
|
2455
2771
|
if (opts.dryRun) return "created";
|
|
2456
|
-
await
|
|
2457
|
-
await
|
|
2772
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2773
|
+
await fs8.writeFile(abs, fullContent, "utf8");
|
|
2458
2774
|
return "created";
|
|
2459
2775
|
}
|
|
2460
2776
|
if (prior.includes(MANAGED_MARKER)) {
|
|
2461
2777
|
if (prior === fullContent) return "skipped";
|
|
2462
2778
|
if (opts.dryRun) return "updated";
|
|
2463
|
-
await
|
|
2464
|
-
await
|
|
2779
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2780
|
+
await fs8.writeFile(abs, fullContent, "utf8");
|
|
2465
2781
|
return "updated";
|
|
2466
2782
|
}
|
|
2467
2783
|
if (!opts.force) return "skipped-untracked";
|
|
2468
2784
|
if (opts.dryRun) return "updated";
|
|
2469
|
-
await
|
|
2470
|
-
await
|
|
2785
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2786
|
+
await fs8.writeFile(abs, fullContent, "utf8");
|
|
2471
2787
|
return "updated";
|
|
2472
2788
|
}
|
|
2473
2789
|
async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
|
|
2474
|
-
const abs =
|
|
2790
|
+
const abs = path10.join(repoRoot, relPath);
|
|
2475
2791
|
assertUnderRepoRoot(repoRoot, abs);
|
|
2476
2792
|
let raw = "";
|
|
2477
2793
|
let existed = false;
|
|
2478
2794
|
try {
|
|
2479
|
-
raw = await
|
|
2795
|
+
raw = await fs8.readFile(abs, "utf8");
|
|
2480
2796
|
existed = true;
|
|
2481
2797
|
} catch (err) {
|
|
2482
2798
|
if (err?.code !== "ENOENT") throw err;
|
|
@@ -2484,8 +2800,8 @@ async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
|
|
|
2484
2800
|
if (!existed) {
|
|
2485
2801
|
const body = buildBody(null);
|
|
2486
2802
|
if (opts.dryRun) return "created";
|
|
2487
|
-
await
|
|
2488
|
-
await
|
|
2803
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2804
|
+
await fs8.writeFile(abs, body, "utf8");
|
|
2489
2805
|
return "created";
|
|
2490
2806
|
}
|
|
2491
2807
|
const managed = raw.includes(MANAGED_MARKER);
|
|
@@ -2500,8 +2816,8 @@ async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
|
|
|
2500
2816
|
const next = buildBody(parsed);
|
|
2501
2817
|
if (managed && next === raw) return "skipped";
|
|
2502
2818
|
if (opts.dryRun) return "updated";
|
|
2503
|
-
await
|
|
2504
|
-
await
|
|
2819
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2820
|
+
await fs8.writeFile(abs, next, "utf8");
|
|
2505
2821
|
return "updated";
|
|
2506
2822
|
}
|
|
2507
2823
|
function parseSetupIdeFlags(argv) {
|
|
@@ -2515,6 +2831,8 @@ function parseSetupIdeFlags(argv) {
|
|
|
2515
2831
|
let cleanup = false;
|
|
2516
2832
|
let devMode = false;
|
|
2517
2833
|
let repair = false;
|
|
2834
|
+
let local = false;
|
|
2835
|
+
let staging = false;
|
|
2518
2836
|
const unknown = [];
|
|
2519
2837
|
for (const a of argv) {
|
|
2520
2838
|
if (a === "--cursor") cursor = true;
|
|
@@ -2527,6 +2845,8 @@ function parseSetupIdeFlags(argv) {
|
|
|
2527
2845
|
else if (a === "--cleanup") cleanup = true;
|
|
2528
2846
|
else if (a === "--dev") devMode = true;
|
|
2529
2847
|
else if (a === "--repair") repair = true;
|
|
2848
|
+
else if (a === "--local") local = true;
|
|
2849
|
+
else if (a === "--staging") staging = true;
|
|
2530
2850
|
else if (a.startsWith("-")) unknown.push(a);
|
|
2531
2851
|
}
|
|
2532
2852
|
const specific = cursor || vscode || jetbrains;
|
|
@@ -2536,7 +2856,30 @@ function parseSetupIdeFlags(argv) {
|
|
|
2536
2856
|
} else {
|
|
2537
2857
|
targets = { cursor, vscode, jetbrains };
|
|
2538
2858
|
}
|
|
2539
|
-
|
|
2859
|
+
let flagError;
|
|
2860
|
+
if (local && staging) {
|
|
2861
|
+
flagError = "[setup-ide-files] --local and --staging are mutually exclusive.";
|
|
2862
|
+
}
|
|
2863
|
+
return {
|
|
2864
|
+
targets,
|
|
2865
|
+
force,
|
|
2866
|
+
dryRun,
|
|
2867
|
+
noGitignore,
|
|
2868
|
+
cleanup,
|
|
2869
|
+
devMode,
|
|
2870
|
+
repair,
|
|
2871
|
+
local,
|
|
2872
|
+
staging,
|
|
2873
|
+
all,
|
|
2874
|
+
explicitCursor: cursor,
|
|
2875
|
+
unknown,
|
|
2876
|
+
flagError
|
|
2877
|
+
};
|
|
2878
|
+
}
|
|
2879
|
+
function cursorEnvironmentFromFlags(local, staging) {
|
|
2880
|
+
if (local) return "local";
|
|
2881
|
+
if (staging) return "staging";
|
|
2882
|
+
return "production";
|
|
2540
2883
|
}
|
|
2541
2884
|
function summarizeOutcomes(outcomes) {
|
|
2542
2885
|
const created = [];
|
|
@@ -2737,20 +3080,44 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
2737
3080
|
|
|
2738
3081
|
` + cursorRuleBody();
|
|
2739
3082
|
if (o.targets.cursor) {
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
3083
|
+
const cursorEnvironment = o.cursorEnvironment ?? "production";
|
|
3084
|
+
let npxPath = null;
|
|
3085
|
+
let cliPath;
|
|
3086
|
+
if (cursorEnvironment === "local") {
|
|
3087
|
+
let resolvedCliPath = o.cursorLocalCliPathOverride;
|
|
3088
|
+
if (resolvedCliPath === void 0) {
|
|
3089
|
+
resolvedCliPath = await resolveBuiltCliPathAsync({ searchFrom: [repoRoot, o.cwd] });
|
|
3090
|
+
}
|
|
3091
|
+
if (!resolvedCliPath) {
|
|
3092
|
+
return {
|
|
3093
|
+
exitCode: 1,
|
|
3094
|
+
repoRoot,
|
|
3095
|
+
outcomes,
|
|
3096
|
+
error: "[setup-ide-files] Local mode requires a built CLI at packages/mcp/dist/cli.cjs. Run pnpm build first."
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
cliPath = resolvedCliPath;
|
|
2743
3100
|
} else {
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
3101
|
+
if (o.npxPathOverride !== void 0) {
|
|
3102
|
+
npxPath = o.npxPathOverride;
|
|
3103
|
+
} else {
|
|
3104
|
+
npxPath = await resolveNpxPath();
|
|
3105
|
+
}
|
|
3106
|
+
if (!npxPath) {
|
|
3107
|
+
return {
|
|
3108
|
+
exitCode: 1,
|
|
3109
|
+
repoRoot,
|
|
3110
|
+
outcomes,
|
|
3111
|
+
error: "[setup-ide-files] Could not resolve a working npx executable. Install Node.js/npm or ensure npx is on PATH before configuring Cursor MCP."
|
|
3112
|
+
};
|
|
3113
|
+
}
|
|
2753
3114
|
}
|
|
3115
|
+
const cursorWriteOptions = {
|
|
3116
|
+
environment: cursorEnvironment,
|
|
3117
|
+
npxPath: npxPath ?? void 0,
|
|
3118
|
+
cliPath,
|
|
3119
|
+
repoRoot
|
|
3120
|
+
};
|
|
2754
3121
|
outcomes[".cursor/rules/memoraone-mcp.mdc"] = await writeManagedMarkdown(
|
|
2755
3122
|
repoRoot,
|
|
2756
3123
|
".cursor/rules/memoraone-mcp.mdc",
|
|
@@ -2760,7 +3127,7 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
2760
3127
|
outcomes[".cursor/mcp.json"] = await writeIdeMcpJson(
|
|
2761
3128
|
repoRoot,
|
|
2762
3129
|
".cursor/mcp.json",
|
|
2763
|
-
(existing) => buildCursorMcpJsonBody(existing,
|
|
3130
|
+
(existing) => buildCursorMcpJsonBody(existing, cursorWriteOptions),
|
|
2764
3131
|
{ force: o.force, dryRun: o.dryRun }
|
|
2765
3132
|
);
|
|
2766
3133
|
const repoConfigPath = getCursorRepoMcpConfigPath(repoRoot);
|
|
@@ -2772,7 +3139,7 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
2772
3139
|
homeDir: o.homeDir,
|
|
2773
3140
|
explicitPath: o.cursorGlobalMcpConfigPath
|
|
2774
3141
|
});
|
|
2775
|
-
if (
|
|
3142
|
+
if (globalDetection.ok === false) {
|
|
2776
3143
|
return {
|
|
2777
3144
|
exitCode: 1,
|
|
2778
3145
|
repoRoot,
|
|
@@ -2804,7 +3171,7 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
2804
3171
|
cursorMcp = {
|
|
2805
3172
|
repoConfigPath,
|
|
2806
3173
|
repoOutcome,
|
|
2807
|
-
npxPath,
|
|
3174
|
+
...cursorEnvironment === "local" ? { cliPath } : { npxPath },
|
|
2808
3175
|
globalConfigPath,
|
|
2809
3176
|
globalMemoraoneRemoved,
|
|
2810
3177
|
globalBackupPath
|
|
@@ -2871,20 +3238,51 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
2871
3238
|
}
|
|
2872
3239
|
return { exitCode: 0, repoRoot, outcomes, cursorMcp, jetbrainsMcp, daemonCleanup };
|
|
2873
3240
|
}
|
|
2874
|
-
async function cliSetupIdeFiles(argv) {
|
|
2875
|
-
const {
|
|
3241
|
+
async function cliSetupIdeFiles(argv, options = {}) {
|
|
3242
|
+
const {
|
|
3243
|
+
targets,
|
|
3244
|
+
force,
|
|
3245
|
+
dryRun,
|
|
3246
|
+
noGitignore,
|
|
3247
|
+
cleanup,
|
|
3248
|
+
devMode,
|
|
3249
|
+
repair,
|
|
3250
|
+
local,
|
|
3251
|
+
staging,
|
|
3252
|
+
all,
|
|
3253
|
+
explicitCursor,
|
|
3254
|
+
unknown,
|
|
3255
|
+
flagError
|
|
3256
|
+
} = parseSetupIdeFlags(argv);
|
|
3257
|
+
if (flagError) {
|
|
3258
|
+
console.error(flagError);
|
|
3259
|
+
return 1;
|
|
3260
|
+
}
|
|
2876
3261
|
if (unknown.length) {
|
|
2877
3262
|
console.error(`[setup-ide-files] Unknown option(s): ${unknown.join(", ")}`);
|
|
2878
3263
|
return 1;
|
|
2879
3264
|
}
|
|
3265
|
+
const cwd = options.cwd ?? process.cwd();
|
|
3266
|
+
const openDeps = options.openCursorMcpSettings ?? {};
|
|
3267
|
+
const stdinIsTty = openDeps.stdinIsTty ?? process.stdin.isTTY === true;
|
|
3268
|
+
const env = openDeps.env ?? process.env;
|
|
3269
|
+
const promptOpenCursorSettings = shouldPromptOpenCursorMcpSettings({
|
|
3270
|
+
explicitCursor,
|
|
3271
|
+
all,
|
|
3272
|
+
dryRun,
|
|
3273
|
+
stdinIsTty,
|
|
3274
|
+
env
|
|
3275
|
+
});
|
|
2880
3276
|
const result = await runSetupIdeFiles({
|
|
2881
|
-
cwd
|
|
3277
|
+
cwd,
|
|
2882
3278
|
targets,
|
|
2883
3279
|
force,
|
|
2884
3280
|
dryRun,
|
|
2885
|
-
noGitignore,
|
|
3281
|
+
noGitignore: options.setupOverrides?.noGitignore ?? noGitignore,
|
|
2886
3282
|
devMode,
|
|
2887
|
-
repair
|
|
3283
|
+
repair,
|
|
3284
|
+
cursorEnvironment: cursorEnvironmentFromFlags(local, staging),
|
|
3285
|
+
...options.setupOverrides
|
|
2888
3286
|
});
|
|
2889
3287
|
if (result.error) {
|
|
2890
3288
|
console.error(result.error);
|
|
@@ -2901,23 +3299,45 @@ async function cliSetupIdeFiles(argv) {
|
|
|
2901
3299
|
logSetupIdeCleanupSummary(result.daemonCleanup);
|
|
2902
3300
|
}
|
|
2903
3301
|
if (targets.cursor && result.cursorMcp) {
|
|
2904
|
-
logCursorMcpCliSummary(result.cursorMcp, dryRun
|
|
3302
|
+
logCursorMcpCliSummary(result.cursorMcp, dryRun, {
|
|
3303
|
+
forInteractivePostSetup: promptOpenCursorSettings
|
|
3304
|
+
});
|
|
2905
3305
|
}
|
|
2906
3306
|
if (targets.jetbrains && result.jetbrainsMcp) {
|
|
2907
3307
|
logJetBrainsMcpCliSummary(result.jetbrainsMcp, dryRun);
|
|
2908
3308
|
}
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
3309
|
+
if (promptOpenCursorSettings && result.repoRoot) {
|
|
3310
|
+
const presentation = openDeps.presentation ?? createTerminalPresentation({
|
|
3311
|
+
env,
|
|
3312
|
+
stdoutIsTty: openDeps.stdoutIsTty ?? process.stdout.isTTY === true,
|
|
3313
|
+
color: openDeps.color,
|
|
3314
|
+
unicode: openDeps.unicode
|
|
3315
|
+
});
|
|
3316
|
+
printCursorSetupCompletedSummary(
|
|
3317
|
+
{ repoRoot: result.repoRoot, outcomes: result.outcomes },
|
|
3318
|
+
openDeps.println,
|
|
3319
|
+
presentation
|
|
3320
|
+
);
|
|
3321
|
+
await runOpenCursorMcpSettingsFlow({
|
|
3322
|
+
...openDeps,
|
|
3323
|
+
stdinIsTty,
|
|
3324
|
+
env,
|
|
3325
|
+
presentation
|
|
3326
|
+
});
|
|
3327
|
+
} else {
|
|
3328
|
+
summarizeOutcomes(result.outcomes);
|
|
3329
|
+
if (dryRun) {
|
|
3330
|
+
console.log("[setup-ide-files] Dry run: no files written.");
|
|
3331
|
+
if (result.daemonCleanup && !result.daemonCleanup.skipped) {
|
|
3332
|
+
console.log("[setup-ide-files] Dry run: no daemons stopped, no sockets removed.");
|
|
3333
|
+
}
|
|
2914
3334
|
}
|
|
3335
|
+
console.log(`[setup-ide-files] ${restartIdeInstruction(targets)}`);
|
|
2915
3336
|
}
|
|
2916
|
-
console.log(`[setup-ide-files] ${restartIdeInstruction(targets)}`);
|
|
2917
3337
|
if (cleanup) {
|
|
2918
3338
|
console.log("[setup-ide-files] Running additional full-project cleanup (--cleanup)...");
|
|
2919
3339
|
const cleanupResult = await runCleanup({
|
|
2920
|
-
cwd
|
|
3340
|
+
cwd,
|
|
2921
3341
|
dryRun,
|
|
2922
3342
|
allProjects: false,
|
|
2923
3343
|
assumeYes: true
|
|
@@ -2939,7 +3359,7 @@ if (args.includes("--version") || args.includes("-v")) {
|
|
|
2939
3359
|
}
|
|
2940
3360
|
if (args.includes("--help") || args.includes("-h")) {
|
|
2941
3361
|
console.log(
|
|
2942
|
-
"Usage: memoraone-mcp [--version] [--help] [--daemon --project-id <uuid> [--ide cursor|copilot-vscode|jetbrains]]\n memoraone-mcp setup-ide-files [--all|--cursor|--vscode|--jetbrains] [--force] [--dry-run] [--no-gitignore] [--cleanup] [--dev] [--repair]\n memoraone-mcp cleanup [--project-id <uuid>] [--ide cursor|copilot-vscode|jetbrains] [--dry-run] [--all-projects] [--yes]"
|
|
3362
|
+
"Usage: memoraone-mcp [--version] [--help] [--daemon --project-id <uuid> [--ide cursor|copilot-vscode|jetbrains]]\n memoraone-mcp setup-ide-files [--all|--cursor|--vscode|--jetbrains] [--force] [--dry-run] [--no-gitignore] [--cleanup] [--dev] [--repair]\n Cursor API environment (with --cursor or --all): --local (node + built cli.cjs + localhost) | --staging (npx + staging API)\n memoraone-mcp cleanup [--project-id <uuid>] [--ide cursor|copilot-vscode|jetbrains] [--dry-run] [--all-projects] [--yes]"
|
|
2943
3363
|
);
|
|
2944
3364
|
process.exit(0);
|
|
2945
3365
|
}
|