rrce-workflow 0.2.35 → 0.2.37

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.
Files changed (2) hide show
  1. package/dist/index.js +731 -514
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -935,6 +935,10 @@ function parseMCPConfig(content) {
935
935
  continue;
936
936
  }
937
937
  if (currentProject) {
938
+ const pathMatch = trimmed.match(/^path:\s*["']?([^"'\n]+)["']?/);
939
+ if (pathMatch) {
940
+ currentProject.path = pathMatch[1].trim();
941
+ }
938
942
  const exposeMatch = trimmed.match(/^expose:\s*(true|false)/);
939
943
  if (exposeMatch) {
940
944
  currentProject.expose = exposeMatch[1] === "true";
@@ -981,7 +985,12 @@ projects:
981
985
  } else {
982
986
  for (const project of config.projects) {
983
987
  content += ` - name: "${project.name}"
984
- expose: ${project.expose}
988
+ `;
989
+ if (project.path) {
990
+ content += ` path: "${project.path}"
991
+ `;
992
+ }
993
+ content += ` expose: ${project.expose}
985
994
  permissions:
986
995
  knowledge: ${project.permissions.knowledge}
987
996
  tasks: ${project.permissions.tasks}
@@ -991,16 +1000,31 @@ projects:
991
1000
  }
992
1001
  return content;
993
1002
  }
994
- function setProjectConfig(config, name, expose, permissions) {
995
- const existing = config.projects.find((p) => p.name === name);
1003
+ function setProjectConfig(config, name, expose, permissions, projectPath) {
1004
+ let existing = config.projects.find((p) => {
1005
+ if (projectPath && p.path) {
1006
+ return p.path === projectPath;
1007
+ }
1008
+ if (!projectPath && !p.path) {
1009
+ return p.name === name;
1010
+ }
1011
+ if (projectPath && !p.path && p.name === name) {
1012
+ return true;
1013
+ }
1014
+ return false;
1015
+ });
996
1016
  if (existing) {
997
1017
  existing.expose = expose;
1018
+ if (projectPath && !existing.path) {
1019
+ existing.path = projectPath;
1020
+ }
998
1021
  if (permissions) {
999
1022
  existing.permissions = { ...existing.permissions, ...permissions };
1000
1023
  }
1001
1024
  } else {
1002
1025
  config.projects.push({
1003
1026
  name,
1027
+ path: projectPath,
1004
1028
  expose,
1005
1029
  permissions: permissions ? { ...DEFAULT_PERMISSIONS, ...permissions } : { ...DEFAULT_PERMISSIONS }
1006
1030
  });
@@ -1011,15 +1035,25 @@ function removeProjectConfig(config, name) {
1011
1035
  config.projects = config.projects.filter((p) => p.name !== name);
1012
1036
  return config;
1013
1037
  }
1014
- function isProjectExposed(config, name) {
1015
- const project = config.projects.find((p) => p.name === name);
1038
+ function isProjectExposed(config, name, projectPath) {
1039
+ const project = config.projects.find((p) => {
1040
+ if (projectPath && p.path) return p.path === projectPath;
1041
+ if (!projectPath && !p.path) return p.name === name;
1042
+ if (projectPath && !p.path) return p.name === name;
1043
+ return false;
1044
+ });
1016
1045
  if (project) {
1017
1046
  return project.expose;
1018
1047
  }
1019
1048
  return config.defaults.includeNew;
1020
1049
  }
1021
- function getProjectPermissions(config, name) {
1022
- const project = config.projects.find((p) => p.name === name);
1050
+ function getProjectPermissions(config, name, projectPath) {
1051
+ const project = config.projects.find((p) => {
1052
+ if (projectPath && p.path) return p.path === projectPath;
1053
+ if (!projectPath && !p.path) return p.name === name;
1054
+ if (projectPath && !p.path) return p.name === name;
1055
+ return false;
1056
+ });
1023
1057
  return project?.permissions ?? config.defaults.permissions;
1024
1058
  }
1025
1059
  var init_config = __esm({
@@ -1031,11 +1065,6 @@ var init_config = __esm({
1031
1065
  });
1032
1066
 
1033
1067
  // src/mcp/logger.ts
1034
- var logger_exports = {};
1035
- __export(logger_exports, {
1036
- getLogFilePath: () => getLogFilePath,
1037
- logger: () => logger
1038
- });
1039
1068
  import * as fs8 from "fs";
1040
1069
  import * as path9 from "path";
1041
1070
  function getLogFilePath() {
@@ -1105,27 +1134,73 @@ import * as path10 from "path";
1105
1134
  function getExposedProjects() {
1106
1135
  const config = loadMCPConfig();
1107
1136
  const allProjects = scanForProjects();
1108
- return allProjects.filter((project) => isProjectExposed(config, project.name));
1137
+ const globalProjects = allProjects.filter((project) => isProjectExposed(config, project.name, project.dataPath));
1138
+ const activeProject = detectActiveProject(globalProjects);
1139
+ let linkedProjects = [];
1140
+ if (activeProject) {
1141
+ const localConfigPath = path10.join(activeProject.dataPath, "config.yaml");
1142
+ let cfgContent = null;
1143
+ if (fs9.existsSync(path10.join(activeProject.dataPath, ".rrce-workflow", "config.yaml"))) {
1144
+ cfgContent = fs9.readFileSync(path10.join(activeProject.dataPath, ".rrce-workflow", "config.yaml"), "utf-8");
1145
+ } else if (fs9.existsSync(path10.join(activeProject.dataPath, ".rrce-workflow.yaml"))) {
1146
+ cfgContent = fs9.readFileSync(path10.join(activeProject.dataPath, ".rrce-workflow.yaml"), "utf-8");
1147
+ }
1148
+ if (cfgContent) {
1149
+ if (cfgContent.includes("linked_projects:")) {
1150
+ const lines = cfgContent.split("\n");
1151
+ let inLinked = false;
1152
+ for (const line of lines) {
1153
+ const trimmed = line.trim();
1154
+ if (trimmed.startsWith("linked_projects:")) {
1155
+ inLinked = true;
1156
+ continue;
1157
+ }
1158
+ if (inLinked) {
1159
+ if (trimmed.startsWith("-") || trimmed.startsWith("linked_projects")) {
1160
+ } else if (trimmed !== "" && !trimmed.startsWith("#")) {
1161
+ inLinked = false;
1162
+ }
1163
+ if (inLinked && trimmed.startsWith("-")) {
1164
+ const val = trimmed.replace(/^-\s*/, "").trim();
1165
+ const [pName] = val.split(":");
1166
+ if (!globalProjects.some((p) => p.name === pName) && !linkedProjects.some((p) => p.name === pName)) {
1167
+ const found = allProjects.find((p) => p.name === pName);
1168
+ if (found) {
1169
+ linkedProjects.push(found);
1170
+ }
1171
+ }
1172
+ }
1173
+ }
1174
+ }
1175
+ }
1176
+ }
1177
+ }
1178
+ return [...globalProjects, ...linkedProjects];
1109
1179
  }
1110
- function detectActiveProject() {
1111
- const exposed = getExposedProjects();
1180
+ function detectActiveProject(knownProjects) {
1181
+ let scanList = knownProjects;
1182
+ if (!scanList) {
1183
+ const config = loadMCPConfig();
1184
+ const all = scanForProjects();
1185
+ scanList = all.filter((project) => isProjectExposed(config, project.name, project.dataPath));
1186
+ }
1112
1187
  const cwd = process.cwd();
1113
- const matches = exposed.filter((p) => cwd.startsWith(p.path));
1188
+ const matches = scanList.filter((p) => cwd.startsWith(p.path));
1114
1189
  matches.sort((a, b) => b.path.length - a.path.length);
1115
1190
  return matches[0];
1116
1191
  }
1117
1192
  function getProjectContext(projectName) {
1118
1193
  const config = loadMCPConfig();
1119
- if (!isProjectExposed(config, projectName)) {
1194
+ const projects = scanForProjects();
1195
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.dataPath));
1196
+ if (!project) {
1120
1197
  return null;
1121
1198
  }
1122
- const permissions = getProjectPermissions(config, projectName);
1199
+ const permissions = getProjectPermissions(config, projectName, project.dataPath);
1123
1200
  if (!permissions.knowledge) {
1124
1201
  return null;
1125
1202
  }
1126
- const projects = scanForProjects();
1127
- const project = projects.find((p) => p.name === projectName);
1128
- if (!project?.knowledgePath) {
1203
+ if (!project.knowledgePath) {
1129
1204
  return null;
1130
1205
  }
1131
1206
  const contextPath = path10.join(project.knowledgePath, "project-context.md");
@@ -1136,16 +1211,16 @@ function getProjectContext(projectName) {
1136
1211
  }
1137
1212
  function getProjectTasks(projectName) {
1138
1213
  const config = loadMCPConfig();
1139
- if (!isProjectExposed(config, projectName)) {
1214
+ const projects = scanForProjects();
1215
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.dataPath));
1216
+ if (!project) {
1140
1217
  return [];
1141
1218
  }
1142
- const permissions = getProjectPermissions(config, projectName);
1219
+ const permissions = getProjectPermissions(config, projectName, project.dataPath);
1143
1220
  if (!permissions.tasks) {
1144
1221
  return [];
1145
1222
  }
1146
- const projects = scanForProjects();
1147
- const project = projects.find((p) => p.name === projectName);
1148
- if (!project?.tasksPath || !fs9.existsSync(project.tasksPath)) {
1223
+ if (!project.tasksPath || !fs9.existsSync(project.tasksPath)) {
1149
1224
  return [];
1150
1225
  }
1151
1226
  const tasks = [];
@@ -1172,7 +1247,7 @@ function searchKnowledge(query) {
1172
1247
  const results = [];
1173
1248
  const queryLower = query.toLowerCase();
1174
1249
  for (const project of projects) {
1175
- const permissions = getProjectPermissions(config, project.name);
1250
+ const permissions = getProjectPermissions(config, project.name, project.dataPath);
1176
1251
  if (!permissions.knowledge || !project.knowledgePath) continue;
1177
1252
  try {
1178
1253
  const files = fs9.readdirSync(project.knowledgePath);
@@ -1209,102 +1284,12 @@ var init_resources = __esm({
1209
1284
  }
1210
1285
  });
1211
1286
 
1212
- // src/mcp/prompts.ts
1213
- function getAllPrompts() {
1214
- const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
1215
- return prompts.map((p) => {
1216
- const args = [];
1217
- if (p.frontmatter["required-args"]) {
1218
- args.push(...p.frontmatter["required-args"].map((a) => ({
1219
- name: a.name,
1220
- description: a.prompt || a.name,
1221
- required: true
1222
- })));
1223
- }
1224
- if (p.frontmatter["optional-args"]) {
1225
- args.push(...p.frontmatter["optional-args"].map((a) => ({
1226
- name: a.name,
1227
- description: a.prompt || a.name,
1228
- required: false
1229
- })));
1230
- }
1231
- return {
1232
- name: p.frontmatter.name,
1233
- description: p.frontmatter.description,
1234
- arguments: args,
1235
- content: p.content
1236
- };
1237
- });
1238
- }
1239
- function getPromptDef(name) {
1240
- return getAllPrompts().find((p) => p.name === name);
1241
- }
1242
- function renderPrompt(content, args) {
1243
- let rendered = content;
1244
- for (const [key, val] of Object.entries(args)) {
1245
- rendered = rendered.replace(new RegExp(`{{${key}}}`, "g"), val);
1246
- }
1247
- return rendered;
1248
- }
1249
- var init_prompts2 = __esm({
1250
- "src/mcp/prompts.ts"() {
1251
- "use strict";
1252
- init_prompts();
1253
- }
1254
- });
1255
-
1256
- // src/mcp/server.ts
1257
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
1258
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1287
+ // src/mcp/handlers/resources.ts
1288
+ import "@modelcontextprotocol/sdk/server/index.js";
1259
1289
  import {
1260
- CallToolRequestSchema,
1261
1290
  ListResourcesRequestSchema,
1262
- ListToolsRequestSchema,
1263
- ReadResourceRequestSchema,
1264
- ListPromptsRequestSchema,
1265
- GetPromptRequestSchema
1291
+ ReadResourceRequestSchema
1266
1292
  } from "@modelcontextprotocol/sdk/types.js";
1267
- async function startMCPServer(options = {}) {
1268
- try {
1269
- logger.info("Starting MCP Server...");
1270
- process.on("uncaughtException", (error) => {
1271
- logger.error("Uncaught Exception", error);
1272
- console.error("Uncaught Exception:", error);
1273
- });
1274
- process.on("unhandledRejection", (reason) => {
1275
- logger.error("Unhandled Rejection", reason);
1276
- console.error("Unhandled Rejection:", reason);
1277
- });
1278
- const config = loadMCPConfig();
1279
- mcpServer = new Server(
1280
- { name: "rrce-mcp-hub", version: "1.0.0" },
1281
- { capabilities: { resources: {}, tools: {}, prompts: {} } }
1282
- );
1283
- mcpServer.onerror = (error) => {
1284
- logger.error("MCP Server Error", error);
1285
- };
1286
- registerResourceHandlers(mcpServer);
1287
- registerToolHandlers(mcpServer);
1288
- registerPromptHandlers(mcpServer);
1289
- if (!options.interactive) {
1290
- const transport = new StdioServerTransport();
1291
- await mcpServer.connect(transport);
1292
- } else {
1293
- logger.info("Running in interactive mode (Stdio transport detached)");
1294
- }
1295
- serverState = { running: true, port: config.server.port, pid: process.pid };
1296
- const exposed = getExposedProjects().map((p) => p.name).join(", ");
1297
- logger.info(`RRCE MCP Hub started (pid: ${process.pid})`, { exposedProjects: exposed });
1298
- if (!options.interactive) {
1299
- console.error(`RRCE MCP Hub started (pid: ${process.pid})`);
1300
- console.error(`Exposed projects: ${exposed}`);
1301
- }
1302
- return { port: config.server.port, pid: process.pid };
1303
- } catch (error) {
1304
- logger.error("Failed to start MCP server", error);
1305
- throw error;
1306
- }
1307
- }
1308
1293
  function registerResourceHandlers(server) {
1309
1294
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
1310
1295
  logger.debug("Listing resources");
@@ -1318,7 +1303,7 @@ function registerResourceHandlers(server) {
1318
1303
  });
1319
1304
  for (const project of projects) {
1320
1305
  const config = loadMCPConfig();
1321
- const permissions = getProjectPermissions(config, project.name);
1306
+ const permissions = getProjectPermissions(config, project.name, project.dataPath);
1322
1307
  if (permissions.knowledge) {
1323
1308
  resources.push({
1324
1309
  uri: `rrce://projects/${project.name}/context`,
@@ -1373,6 +1358,65 @@ function registerResourceHandlers(server) {
1373
1358
  }
1374
1359
  });
1375
1360
  }
1361
+ var init_resources2 = __esm({
1362
+ "src/mcp/handlers/resources.ts"() {
1363
+ "use strict";
1364
+ init_logger();
1365
+ init_config();
1366
+ init_resources();
1367
+ }
1368
+ });
1369
+
1370
+ // src/mcp/prompts.ts
1371
+ function getAllPrompts() {
1372
+ const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
1373
+ return prompts.map((p) => {
1374
+ const args = [];
1375
+ if (p.frontmatter["required-args"]) {
1376
+ args.push(...p.frontmatter["required-args"].map((a) => ({
1377
+ name: a.name,
1378
+ description: a.prompt || a.name,
1379
+ required: true
1380
+ })));
1381
+ }
1382
+ if (p.frontmatter["optional-args"]) {
1383
+ args.push(...p.frontmatter["optional-args"].map((a) => ({
1384
+ name: a.name,
1385
+ description: a.prompt || a.name,
1386
+ required: false
1387
+ })));
1388
+ }
1389
+ return {
1390
+ name: p.frontmatter.name,
1391
+ description: p.frontmatter.description,
1392
+ arguments: args,
1393
+ content: p.content
1394
+ };
1395
+ });
1396
+ }
1397
+ function getPromptDef(name) {
1398
+ return getAllPrompts().find((p) => p.name === name);
1399
+ }
1400
+ function renderPrompt(content, args) {
1401
+ let rendered = content;
1402
+ for (const [key, val] of Object.entries(args)) {
1403
+ rendered = rendered.replace(new RegExp(`{{${key}}}`, "g"), val);
1404
+ }
1405
+ return rendered;
1406
+ }
1407
+ var init_prompts2 = __esm({
1408
+ "src/mcp/prompts.ts"() {
1409
+ "use strict";
1410
+ init_prompts();
1411
+ }
1412
+ });
1413
+
1414
+ // src/mcp/handlers/tools.ts
1415
+ import "@modelcontextprotocol/sdk/server/index.js";
1416
+ import {
1417
+ ListToolsRequestSchema,
1418
+ CallToolRequestSchema
1419
+ } from "@modelcontextprotocol/sdk/types.js";
1376
1420
  function registerToolHandlers(server) {
1377
1421
  server.setRequestHandler(ListToolsRequestSchema, async () => {
1378
1422
  const tools = [
@@ -1525,6 +1569,21 @@ To fix this:
1525
1569
  }
1526
1570
  });
1527
1571
  }
1572
+ var init_tools = __esm({
1573
+ "src/mcp/handlers/tools.ts"() {
1574
+ "use strict";
1575
+ init_logger();
1576
+ init_resources();
1577
+ init_prompts2();
1578
+ }
1579
+ });
1580
+
1581
+ // src/mcp/handlers/prompts.ts
1582
+ import "@modelcontextprotocol/sdk/server/index.js";
1583
+ import {
1584
+ ListPromptsRequestSchema,
1585
+ GetPromptRequestSchema
1586
+ } from "@modelcontextprotocol/sdk/types.js";
1528
1587
  function registerPromptHandlers(server) {
1529
1588
  server.setRequestHandler(ListPromptsRequestSchema, async () => {
1530
1589
  logger.debug("Listing prompts");
@@ -1606,6 +1665,65 @@ Note: If the user's request refers to a project not listed here, ask them to exp
1606
1665
  }
1607
1666
  });
1608
1667
  }
1668
+ var init_prompts3 = __esm({
1669
+ "src/mcp/handlers/prompts.ts"() {
1670
+ "use strict";
1671
+ init_logger();
1672
+ init_resources();
1673
+ init_prompts2();
1674
+ }
1675
+ });
1676
+
1677
+ // src/mcp/server.ts
1678
+ var server_exports = {};
1679
+ __export(server_exports, {
1680
+ getMCPServerStatus: () => getMCPServerStatus,
1681
+ startMCPServer: () => startMCPServer,
1682
+ stopMCPServer: () => stopMCPServer
1683
+ });
1684
+ import { Server as Server4 } from "@modelcontextprotocol/sdk/server/index.js";
1685
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1686
+ async function startMCPServer(options = {}) {
1687
+ try {
1688
+ logger.info("Starting MCP Server...");
1689
+ process.on("uncaughtException", (error) => {
1690
+ logger.error("Uncaught Exception", error);
1691
+ console.error("Uncaught Exception:", error);
1692
+ });
1693
+ process.on("unhandledRejection", (reason) => {
1694
+ logger.error("Unhandled Rejection", reason);
1695
+ console.error("Unhandled Rejection:", reason);
1696
+ });
1697
+ const config = loadMCPConfig();
1698
+ mcpServer = new Server4(
1699
+ { name: "rrce-mcp-hub", version: "1.0.0" },
1700
+ { capabilities: { resources: {}, tools: {}, prompts: {} } }
1701
+ );
1702
+ mcpServer.onerror = (error) => {
1703
+ logger.error("MCP Server Error", error);
1704
+ };
1705
+ registerResourceHandlers(mcpServer);
1706
+ registerToolHandlers(mcpServer);
1707
+ registerPromptHandlers(mcpServer);
1708
+ if (!options.interactive) {
1709
+ const transport = new StdioServerTransport();
1710
+ await mcpServer.connect(transport);
1711
+ } else {
1712
+ logger.info("Running in interactive mode (Stdio transport detached)");
1713
+ }
1714
+ serverState = { running: true, port: config.server.port, pid: process.pid };
1715
+ const exposed = getExposedProjects().map((p) => p.name).join(", ");
1716
+ logger.info(`RRCE MCP Hub started (pid: ${process.pid})`, { exposedProjects: exposed });
1717
+ if (!options.interactive) {
1718
+ console.error(`RRCE MCP Hub started (pid: ${process.pid})`);
1719
+ console.error(`Exposed projects: ${exposed}`);
1720
+ }
1721
+ return { port: config.server.port, pid: process.pid };
1722
+ } catch (error) {
1723
+ logger.error("Failed to start MCP server", error);
1724
+ throw error;
1725
+ }
1726
+ }
1609
1727
  function stopMCPServer() {
1610
1728
  if (mcpServer) {
1611
1729
  logger.info("Stopping MCP Server...");
@@ -1625,8 +1743,9 @@ var init_server = __esm({
1625
1743
  init_logger();
1626
1744
  init_config();
1627
1745
  init_resources();
1628
- init_prompts2();
1629
- init_prompts();
1746
+ init_resources2();
1747
+ init_tools();
1748
+ init_prompts3();
1630
1749
  serverState = { running: false };
1631
1750
  mcpServer = null;
1632
1751
  }
@@ -1820,17 +1939,179 @@ var init_install = __esm({
1820
1939
  }
1821
1940
  });
1822
1941
 
1823
- // src/mcp/ui/Header.tsx
1824
- import "react";
1825
- import { Box, Text } from "ink";
1826
- import { jsx } from "react/jsx-runtime";
1827
- var Header;
1828
- var init_Header = __esm({
1829
- "src/mcp/ui/Header.tsx"() {
1830
- "use strict";
1831
- Header = () => /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingBottom: 1, children: /* @__PURE__ */ jsx(Box, { borderStyle: "double", borderColor: "cyan", paddingX: 2, justifyContent: "center", children: /* @__PURE__ */ jsx(Text, { bold: true, color: "white", children: " RRCE MCP Hub " }) }) });
1942
+ // src/mcp/commands/configure.ts
1943
+ import { spinner, note as note2, multiselect, isCancel as isCancel2 } from "@clack/prompts";
1944
+ import pc3 from "picocolors";
1945
+ async function handleConfigure() {
1946
+ const s = spinner();
1947
+ s.start("Scanning for projects...");
1948
+ const config = loadMCPConfig();
1949
+ const projects = scanForProjects();
1950
+ logger.info("Configure: Loaded config", { projects: config.projects, defaultMode: config.defaults.includeNew });
1951
+ s.stop("Projects found");
1952
+ if (projects.length === 0) {
1953
+ note2('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
1954
+ return;
1832
1955
  }
1833
- });
1956
+ const options = projects.map((project) => {
1957
+ const projectConfig = config.projects.find(
1958
+ (p) => p.path && p.path === project.dataPath || !p.path && p.name === project.name
1959
+ );
1960
+ const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
1961
+ return {
1962
+ value: project.dataPath,
1963
+ // Use precise data path as unique identifier
1964
+ label: `${project.name} ${pc3.dim(`(${project.source})`)}`,
1965
+ hint: project.dataPath
1966
+ };
1967
+ });
1968
+ const currentlyExposed = projects.filter((p) => {
1969
+ const cfg = config.projects.find(
1970
+ (c) => c.path && c.path === p.dataPath || !c.path && c.name === p.name
1971
+ );
1972
+ return cfg?.expose ?? config.defaults.includeNew;
1973
+ }).map((p) => p.dataPath);
1974
+ const selected = await multiselect({
1975
+ message: "Select projects to expose via MCP:",
1976
+ options,
1977
+ initialValues: currentlyExposed,
1978
+ required: false
1979
+ });
1980
+ if (isCancel2(selected)) {
1981
+ return;
1982
+ }
1983
+ const selectedPaths = selected;
1984
+ logger.info("Configure: User selected projects by path", selectedPaths);
1985
+ for (const project of projects) {
1986
+ const shouldExpose = selectedPaths.includes(project.dataPath);
1987
+ setProjectConfig(config, project.name, shouldExpose, void 0, project.dataPath);
1988
+ }
1989
+ saveMCPConfig(config);
1990
+ logger.info("Configure: Config saved", config);
1991
+ const exposedCount = selectedPaths.length;
1992
+ note2(
1993
+ `${pc3.green("\u2713")} Configuration saved!
1994
+
1995
+ Exposed projects: ${exposedCount}
1996
+ Hidden projects: ${projects.length - exposedCount}`,
1997
+ "Configuration Updated"
1998
+ );
1999
+ }
2000
+ async function handleConfigureGlobalPath() {
2001
+ const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
2002
+ const fs17 = await import("fs");
2003
+ const path16 = await import("path");
2004
+ note2(
2005
+ `MCP Hub requires a ${pc3.bold("global storage path")} to store its configuration
2006
+ and coordinate across projects.
2007
+
2008
+ Your current setup uses ${pc3.cyan("workspace")} mode, which stores data
2009
+ locally in each project. MCP needs a central location.`,
2010
+ "Global Path Required"
2011
+ );
2012
+ const resolvedPath = await resolveGlobalPath2();
2013
+ if (!resolvedPath) {
2014
+ return false;
2015
+ }
2016
+ try {
2017
+ if (!fs17.existsSync(resolvedPath)) {
2018
+ fs17.mkdirSync(resolvedPath, { recursive: true });
2019
+ }
2020
+ const config = loadMCPConfig();
2021
+ saveMCPConfig(config);
2022
+ note2(
2023
+ `${pc3.green("\u2713")} Global path configured: ${pc3.cyan(resolvedPath)}
2024
+
2025
+ MCP config will be stored at:
2026
+ ${path16.join(resolvedPath, "mcp.yaml")}`,
2027
+ "Configuration Saved"
2028
+ );
2029
+ return true;
2030
+ } catch (error) {
2031
+ note2(
2032
+ `${pc3.red("\u2717")} Failed to create directory: ${error instanceof Error ? error.message : String(error)}`,
2033
+ "Error"
2034
+ );
2035
+ return false;
2036
+ }
2037
+ }
2038
+ var init_configure = __esm({
2039
+ "src/mcp/commands/configure.ts"() {
2040
+ "use strict";
2041
+ init_config();
2042
+ init_detection();
2043
+ init_logger();
2044
+ }
2045
+ });
2046
+
2047
+ // src/mcp/commands/install-wizard.ts
2048
+ import { multiselect as multiselect2, note as note3, isCancel as isCancel3 } from "@clack/prompts";
2049
+ import pc4 from "picocolors";
2050
+ async function runInstallWizard(workspacePath) {
2051
+ const status = checkInstallStatus(workspacePath);
2052
+ const options = [
2053
+ {
2054
+ value: "antigravity",
2055
+ label: "Antigravity IDE",
2056
+ hint: status.antigravity ? pc4.green("\u2713 Installed") : pc4.dim("Not installed")
2057
+ },
2058
+ {
2059
+ value: "vscode-global",
2060
+ label: "VSCode (Global Settings)",
2061
+ hint: status.vscodeGlobal ? pc4.green("\u2713 Installed") : pc4.dim("Not installed")
2062
+ },
2063
+ {
2064
+ value: "vscode-workspace",
2065
+ label: "VSCode (Workspace Config)",
2066
+ hint: status.vscodeWorkspace ? pc4.green("\u2713 Installed") : pc4.dim("Not installed")
2067
+ },
2068
+ {
2069
+ value: "claude",
2070
+ label: "Claude Desktop",
2071
+ hint: status.claude ? pc4.green("\u2713 Installed") : pc4.dim("Not installed")
2072
+ }
2073
+ ];
2074
+ const selected = await multiselect2({
2075
+ message: "Select where to install RRCE MCP Server:",
2076
+ options,
2077
+ initialValues: [
2078
+ ...status.antigravity ? ["antigravity"] : [],
2079
+ ...status.vscodeGlobal ? ["vscode-global"] : [],
2080
+ ...status.vscodeWorkspace ? ["vscode-workspace"] : [],
2081
+ ...status.claude ? ["claude"] : []
2082
+ ],
2083
+ required: false
2084
+ });
2085
+ if (isCancel3(selected)) return;
2086
+ const targets = selected;
2087
+ const results = [];
2088
+ for (const target of targets) {
2089
+ const success = installToConfig(target, workspacePath);
2090
+ const label = getTargetLabel(target);
2091
+ results.push(`${label}: ${success ? pc4.green("\u2713 Success") : pc4.red("\u2717 Failed")}`);
2092
+ }
2093
+ if (results.length > 0) {
2094
+ note3(results.join("\n"), "Installation Results");
2095
+ }
2096
+ }
2097
+ var init_install_wizard = __esm({
2098
+ "src/mcp/commands/install-wizard.ts"() {
2099
+ "use strict";
2100
+ init_install();
2101
+ }
2102
+ });
2103
+
2104
+ // src/mcp/ui/Header.tsx
2105
+ import "react";
2106
+ import { Box, Text } from "ink";
2107
+ import { jsx } from "react/jsx-runtime";
2108
+ var Header;
2109
+ var init_Header = __esm({
2110
+ "src/mcp/ui/Header.tsx"() {
2111
+ "use strict";
2112
+ Header = () => /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingBottom: 1, children: /* @__PURE__ */ jsx(Box, { borderStyle: "double", borderColor: "cyan", paddingX: 2, justifyContent: "center", children: /* @__PURE__ */ jsx(Text, { bold: true, color: "white", children: " RRCE MCP Hub " }) }) });
2113
+ }
2114
+ });
1834
2115
 
1835
2116
  // src/mcp/ui/StatusBoard.tsx
1836
2117
  import "react";
@@ -2010,12 +2291,15 @@ var init_App = __esm({
2010
2291
  if (input === "q" || key.ctrl && input === "c") {
2011
2292
  stopMCPServer();
2012
2293
  onExit();
2294
+ exit();
2013
2295
  }
2014
2296
  if (input === "p") {
2015
2297
  onConfigure();
2298
+ exit();
2016
2299
  }
2017
2300
  if (input === "i") {
2018
2301
  onInstall();
2302
+ exit();
2019
2303
  }
2020
2304
  if (input === "c") {
2021
2305
  setLogs([]);
@@ -2040,183 +2324,18 @@ var init_App = __esm({
2040
2324
  }
2041
2325
  });
2042
2326
 
2043
- // src/mcp/index.ts
2044
- var mcp_exports = {};
2045
- __export(mcp_exports, {
2046
- runMCP: () => runMCP
2047
- });
2048
- import { intro, outro, select as select2, multiselect, confirm, spinner, note as note2, cancel, isCancel as isCancel2, text } from "@clack/prompts";
2049
- import pc3 from "picocolors";
2050
- async function runMCP(subcommand2) {
2051
- if (subcommand2) {
2052
- switch (subcommand2) {
2053
- case "start":
2054
- if (process.stdout.isTTY) {
2055
- await handleStartServer();
2056
- } else {
2057
- await startMCPServer();
2058
- await new Promise(() => {
2059
- });
2060
- }
2061
- return;
2062
- case "stop":
2063
- await handleStopServer();
2064
- return;
2065
- case "status":
2066
- await handleShowStatus();
2067
- return;
2068
- case "help":
2069
- showHelp();
2070
- return;
2071
- }
2072
- }
2073
- intro(pc3.bgCyan(pc3.black(" RRCE MCP Hub ")));
2074
- const workspacePath = detectWorkspaceRoot();
2075
- const globalPathCheck = await ensureMCPGlobalPath();
2076
- if (!globalPathCheck.configured) {
2077
- const configured = await handleConfigureGlobalPath();
2078
- if (!configured) {
2079
- outro(pc3.yellow("MCP requires a global storage path. Setup cancelled."));
2080
- return;
2081
- }
2082
- }
2083
- const installed = isInstalledAnywhere(workspacePath);
2084
- if (!installed) {
2085
- note2(
2086
- `${pc3.bold("Welcome to RRCE MCP Hub!")}
2087
-
2088
- MCP (Model Context Protocol) allows AI assistants to access your
2089
- project knowledge in real-time. Let's get you set up.`,
2090
- "Getting Started"
2091
- );
2092
- const shouldInstall = await confirm({
2093
- message: "Install MCP server to your IDE(s)?",
2094
- initialValue: true
2095
- });
2096
- if (shouldInstall && !isCancel2(shouldInstall)) {
2097
- await handleInstallWizard(workspacePath);
2098
- const config2 = loadMCPConfig();
2099
- const exposedCount2 = config2.projects.filter((p) => p.expose).length;
2100
- if (exposedCount2 === 0) {
2101
- await handleConfigure();
2102
- }
2103
- const shouldStart = await confirm({
2104
- message: "Start the MCP server now?",
2105
- initialValue: true
2106
- });
2107
- if (shouldStart && !isCancel2(shouldStart)) {
2108
- await handleStartServer();
2109
- }
2110
- }
2111
- outro(pc3.green("MCP Hub setup complete!"));
2112
- return;
2113
- }
2114
- const config = loadMCPConfig();
2115
- const exposedCount = config.projects.filter((p) => p.expose).length;
2116
- if (exposedCount === 0 && !config.defaults.includeNew) {
2117
- note2("MCP is installed but no projects are exposed. Let's configure that.", "Configuration Needed");
2118
- await handleConfigure();
2119
- }
2120
- let running = true;
2121
- while (running) {
2122
- const serverStatus = getMCPServerStatus();
2123
- const serverLabel = serverStatus.running ? pc3.green("\u25CF Running") : pc3.dim("\u25CB Stopped");
2124
- const currentStatus = checkInstallStatus(workspacePath);
2125
- const installedCount = [currentStatus.antigravity, currentStatus.claude, currentStatus.vscodeGlobal, currentStatus.vscodeWorkspace].filter(Boolean).length;
2126
- const action = await select2({
2127
- message: "What would you like to do?",
2128
- options: [
2129
- { value: "start", label: `\u25B6\uFE0F Start MCP server`, hint: serverLabel },
2130
- { value: "configure", label: "\u2699\uFE0F Configure projects", hint: "Choose which projects to expose" },
2131
- { value: "install", label: "\u{1F4E5} Install to IDE", hint: `${installedCount} IDE(s) configured` },
2132
- { value: "status", label: "\u{1F4CB} View status", hint: "See details" },
2133
- { value: "help", label: "\u2753 Help", hint: "Learn about MCP Hub" },
2134
- { value: "exit", label: "\u21A9 Exit", hint: "Return to shell" }
2135
- ]
2136
- });
2137
- if (isCancel2(action)) {
2138
- cancel("MCP Hub closed.");
2139
- return;
2140
- }
2141
- switch (action) {
2142
- case "start":
2143
- await handleStartServer();
2144
- break;
2145
- case "configure":
2146
- await handleConfigure();
2147
- break;
2148
- case "install":
2149
- await handleInstallWizard(workspacePath);
2150
- break;
2151
- case "status":
2152
- await handleShowStatus();
2153
- break;
2154
- case "help":
2155
- showHelp();
2156
- break;
2157
- case "exit":
2158
- running = false;
2159
- break;
2160
- }
2161
- }
2162
- outro(pc3.green("MCP Hub closed."));
2163
- }
2164
- async function handleInstallWizard(workspacePath) {
2165
- const status = checkInstallStatus(workspacePath);
2166
- const options = [
2167
- {
2168
- value: "antigravity",
2169
- label: "Antigravity IDE",
2170
- hint: status.antigravity ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")
2171
- },
2172
- {
2173
- value: "vscode-global",
2174
- label: "VSCode (Global Settings)",
2175
- hint: status.vscodeGlobal ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")
2176
- },
2177
- {
2178
- value: "vscode-workspace",
2179
- label: "VSCode (Workspace Config)",
2180
- hint: status.vscodeWorkspace ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")
2181
- },
2182
- {
2183
- value: "claude",
2184
- label: "Claude Desktop",
2185
- hint: status.claude ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")
2186
- }
2187
- ];
2188
- const selected = await multiselect({
2189
- message: "Select where to install RRCE MCP Server:",
2190
- options,
2191
- initialValues: [
2192
- ...status.antigravity ? ["antigravity"] : [],
2193
- ...status.vscodeGlobal ? ["vscode-global"] : [],
2194
- ...status.vscodeWorkspace ? ["vscode-workspace"] : [],
2195
- ...status.claude ? ["claude"] : []
2196
- ],
2197
- required: false
2198
- });
2199
- if (isCancel2(selected)) return;
2200
- const targets = selected;
2201
- const results = [];
2202
- for (const target of targets) {
2203
- const success = installToConfig(target, workspacePath);
2204
- const label = getTargetLabel(target);
2205
- results.push(`${label}: ${success ? pc3.green("\u2713 Success") : pc3.red("\u2717 Failed")}`);
2206
- }
2207
- if (results.length > 0) {
2208
- note2(results.join("\n"), "Installation Results");
2209
- }
2210
- }
2327
+ // src/mcp/commands/start.ts
2328
+ import { confirm, isCancel as isCancel4, text } from "@clack/prompts";
2211
2329
  async function handleStartServer() {
2212
2330
  const React7 = await import("react");
2213
2331
  const { render } = await import("ink");
2214
2332
  const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
2215
- const { loadMCPConfig: loadMCPConfig2, saveMCPConfig: saveMCPConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
2216
- const config = loadMCPConfig2();
2333
+ const config = loadMCPConfig();
2217
2334
  const projects = scanForProjects();
2218
2335
  const exposedProjects = projects.filter((p) => {
2219
- const cfg = config.projects.find((c) => c.name === p.name);
2336
+ const cfg = config.projects.find(
2337
+ (c) => c.path && c.path === p.dataPath || !c.path && c.name === p.name
2338
+ );
2220
2339
  return cfg?.expose ?? config.defaults.includeNew;
2221
2340
  });
2222
2341
  if (exposedProjects.length === 0) {
@@ -2224,7 +2343,7 @@ async function handleStartServer() {
2224
2343
  message: "No projects are currently exposed. Configure now?",
2225
2344
  initialValue: true
2226
2345
  });
2227
- if (shouldConfig && !isCancel2(shouldConfig)) {
2346
+ if (shouldConfig && !isCancel4(shouldConfig)) {
2228
2347
  await handleConfigure();
2229
2348
  return handleStartServer();
2230
2349
  }
@@ -2240,11 +2359,11 @@ async function handleStartServer() {
2240
2359
  if (isNaN(Number(value))) return "Port must be a number";
2241
2360
  }
2242
2361
  });
2243
- if (isCancel2(portInput)) return;
2362
+ if (isCancel4(portInput)) return;
2244
2363
  const newPort = parseInt(portInput, 10);
2245
2364
  if (newPort !== config.server.port) {
2246
2365
  config.server.port = newPort;
2247
- saveMCPConfig2(config);
2366
+ saveMCPConfig(config);
2248
2367
  initialPort = newPort;
2249
2368
  }
2250
2369
  }
@@ -2277,50 +2396,27 @@ async function handleStartServer() {
2277
2396
  } else if (nextAction === "install") {
2278
2397
  console.clear();
2279
2398
  const workspacePath = detectWorkspaceRoot();
2280
- await handleInstallWizard(workspacePath);
2399
+ await runInstallWizard(workspacePath);
2281
2400
  }
2282
2401
  }
2283
2402
  }
2284
- async function handleConfigureGlobalPath() {
2285
- const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
2286
- const fs17 = await import("fs");
2287
- const path16 = await import("path");
2288
- note2(
2289
- `MCP Hub requires a ${pc3.bold("global storage path")} to store its configuration
2290
- and coordinate across projects.
2291
-
2292
- Your current setup uses ${pc3.cyan("workspace")} mode, which stores data
2293
- locally in each project. MCP needs a central location.`,
2294
- "Global Path Required"
2295
- );
2296
- const resolvedPath = await resolveGlobalPath2();
2297
- if (!resolvedPath) {
2298
- return false;
2403
+ var init_start = __esm({
2404
+ "src/mcp/commands/start.ts"() {
2405
+ "use strict";
2406
+ init_config();
2407
+ init_detection();
2408
+ init_server();
2409
+ init_paths();
2410
+ init_configure();
2411
+ init_install_wizard();
2299
2412
  }
2300
- try {
2301
- if (!fs17.existsSync(resolvedPath)) {
2302
- fs17.mkdirSync(resolvedPath, { recursive: true });
2303
- }
2304
- const config = loadMCPConfig();
2305
- saveMCPConfig(config);
2306
- note2(
2307
- `${pc3.green("\u2713")} Global path configured: ${pc3.cyan(resolvedPath)}
2413
+ });
2308
2414
 
2309
- MCP config will be stored at:
2310
- ${path16.join(resolvedPath, "mcp.yaml")}`,
2311
- "Configuration Saved"
2312
- );
2313
- return true;
2314
- } catch (error) {
2315
- note2(
2316
- `${pc3.red("\u2717")} Failed to create directory: ${error instanceof Error ? error.message : String(error)}`,
2317
- "Error"
2318
- );
2319
- return false;
2320
- }
2321
- }
2415
+ // src/mcp/commands/status.ts
2416
+ import { spinner as spinner2, note as note4 } from "@clack/prompts";
2417
+ import pc5 from "picocolors";
2322
2418
  async function handleShowStatus() {
2323
- const s = spinner();
2419
+ const s = spinner2();
2324
2420
  s.start("Loading projects...");
2325
2421
  const config = loadMCPConfig();
2326
2422
  const projects = scanForProjects();
@@ -2328,161 +2424,262 @@ async function handleShowStatus() {
2328
2424
  const installStatus = checkInstallStatus(workspacePath);
2329
2425
  s.stop("Projects loaded");
2330
2426
  if (projects.length === 0) {
2331
- note2('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
2427
+ note4('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
2332
2428
  return;
2333
2429
  }
2334
2430
  const lines = [
2335
- `${pc3.bold("Installation Status")}`,
2431
+ `${pc5.bold("Installation Status")}`,
2336
2432
  "",
2337
- ` Antigravity: ${installStatus.antigravity ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")}`,
2338
- ` VSCode (Global): ${installStatus.vscodeGlobal ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")}`,
2339
- ` VSCode (Workspace): ${installStatus.vscodeWorkspace ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")}`,
2340
- ` Claude Desktop: ${installStatus.claude ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")}`,
2433
+ ` Antigravity: ${installStatus.antigravity ? pc5.green("\u2713 Installed") : pc5.dim("Not installed")}`,
2434
+ ` VSCode (Global): ${installStatus.vscodeGlobal ? pc5.green("\u2713 Installed") : pc5.dim("Not installed")}`,
2435
+ ` VSCode (Workspace): ${installStatus.vscodeWorkspace ? pc5.green("\u2713 Installed") : pc5.dim("Not installed")}`,
2436
+ ` Claude Desktop: ${installStatus.claude ? pc5.green("\u2713 Installed") : pc5.dim("Not installed")}`,
2341
2437
  "",
2342
- `${pc3.bold("Project Status")}`,
2438
+ `${pc5.bold("Project Status")}`,
2343
2439
  ""
2344
2440
  ];
2345
2441
  for (const project of projects) {
2346
2442
  const projectConfig = config.projects.find((p) => p.name === project.name);
2347
2443
  const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
2348
- const status = isExposed ? pc3.green("\u2713 exposed") : pc3.dim("\u25CB hidden");
2349
- const source = pc3.dim(`(${project.source})`);
2444
+ const status = isExposed ? pc5.green("\u2713 exposed") : pc5.dim("\u25CB hidden");
2445
+ const source = pc5.dim(`(${project.source})`);
2350
2446
  lines.push(` ${status} ${project.name} ${source}`);
2351
2447
  }
2352
2448
  lines.push("");
2353
- lines.push(pc3.dim(`Config: ${getMCPConfigPath()}`));
2449
+ lines.push(pc5.dim(`Config: ${getMCPConfigPath()}`));
2354
2450
  const serverStatus = getMCPServerStatus();
2355
2451
  if (serverStatus.running) {
2356
- lines.push(pc3.green(`Server: running on port ${serverStatus.port}`));
2452
+ lines.push(pc5.green(`Server: running on port ${serverStatus.port}`));
2357
2453
  } else {
2358
- lines.push(pc3.dim("Server: not running"));
2454
+ lines.push(pc5.dim("Server: not running"));
2359
2455
  }
2360
- note2(lines.join("\n"), "MCP Hub Status");
2456
+ note4(lines.join("\n"), "MCP Hub Status");
2361
2457
  }
2362
- async function handleConfigure() {
2363
- const { logger: logger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
2364
- const s = spinner();
2365
- s.start("Scanning for projects...");
2366
- const config = loadMCPConfig();
2367
- const projects = scanForProjects();
2368
- logger2.info("Configure: Loaded config", { projects: config.projects, defaultMode: config.defaults.includeNew });
2369
- s.stop("Projects found");
2370
- if (projects.length === 0) {
2371
- note2('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
2372
- return;
2458
+ var init_status = __esm({
2459
+ "src/mcp/commands/status.ts"() {
2460
+ "use strict";
2461
+ init_config();
2462
+ init_detection();
2463
+ init_paths();
2464
+ init_server();
2465
+ init_install();
2373
2466
  }
2374
- const options = projects.map((project) => {
2375
- const projectConfig = config.projects.find((p) => p.name === project.name);
2376
- const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
2377
- return {
2378
- value: project.name,
2379
- label: `${project.name} ${pc3.dim(`(${project.source})`)}`,
2380
- hint: project.dataPath
2381
- };
2382
- });
2383
- const currentlyExposed = projects.filter((p) => {
2384
- const cfg = config.projects.find((c) => c.name === p.name);
2385
- return cfg?.expose ?? config.defaults.includeNew;
2386
- }).map((p) => p.name);
2387
- const selected = await multiselect({
2388
- message: "Select projects to expose via MCP:",
2389
- options,
2390
- initialValues: currentlyExposed,
2391
- required: false
2392
- });
2393
- if (isCancel2(selected)) {
2394
- return;
2467
+ });
2468
+
2469
+ // src/mcp/commands/help.ts
2470
+ import { note as note5 } from "@clack/prompts";
2471
+ import pc6 from "picocolors";
2472
+ function showHelp() {
2473
+ const help = `
2474
+ ${pc6.bold("RRCE MCP Hub")} - Cross-project AI assistant server
2475
+
2476
+ ${pc6.bold("ABOUT")}
2477
+ MCP (Model Context Protocol) allows AI assistants like Claude to
2478
+ access your project knowledge in real-time. The RRCE MCP Hub
2479
+ provides a central server that exposes selected projects.
2480
+
2481
+ ${pc6.bold("MENU OPTIONS")}
2482
+ ${pc6.cyan("Start MCP server")} Start the server for AI access
2483
+ ${pc6.cyan("Configure projects")} Choose which projects to expose
2484
+ ${pc6.cyan("Install to IDE")} Add to Antigravity, VSCode, or Claude
2485
+ ${pc6.cyan("View status")} See which projects are exposed
2486
+
2487
+ ${pc6.bold("DIRECT COMMANDS")}
2488
+ ${pc6.dim("rrce-workflow mcp start")} Start server directly
2489
+ ${pc6.dim("rrce-workflow mcp stop")} Stop server directly
2490
+ ${pc6.dim("rrce-workflow mcp status")} Show status directly
2491
+ ${pc6.dim("rrce-workflow mcp help")} Show this help
2492
+
2493
+ ${pc6.bold("IDE INSTALLATION")}
2494
+ ${pc6.cyan("Antigravity")} ~/.gemini/antigravity/mcp_config.json
2495
+ ${pc6.cyan("VSCode Global")} ~/.config/Code/User/settings.json
2496
+ ${pc6.cyan("VSCode Workspace")} .vscode/mcp.json
2497
+ ${pc6.cyan("Claude Desktop")} ~/.config/claude/claude_desktop_config.json
2498
+
2499
+ ${pc6.bold("SERVER COMMANDS")} (while running)
2500
+ ${pc6.cyan("q")} Stop and quit ${pc6.cyan("p")} Reconfigure projects
2501
+ ${pc6.cyan("i")} Install to IDE ${pc6.cyan("r")} Reload config
2502
+ ${pc6.cyan("c")} Clear logs ${pc6.cyan("?")} Show help
2503
+
2504
+ ${pc6.bold("RESOURCES EXPOSED")}
2505
+ ${pc6.cyan("rrce://projects")} List all exposed projects
2506
+ ${pc6.cyan("rrce://projects/{name}/context")} Get project context
2507
+ ${pc6.cyan("rrce://projects/{name}/tasks")} Get project tasks
2508
+ `;
2509
+ note5(help.trim(), "Help");
2510
+ }
2511
+ var init_help = __esm({
2512
+ "src/mcp/commands/help.ts"() {
2513
+ "use strict";
2395
2514
  }
2396
- const selectedNames = selected;
2397
- logger2.info("Configure: User selected projects", selectedNames);
2398
- for (const project of projects) {
2399
- const shouldExpose = selectedNames.includes(project.name);
2400
- setProjectConfig(config, project.name, shouldExpose);
2515
+ });
2516
+
2517
+ // src/mcp/index.ts
2518
+ var mcp_exports = {};
2519
+ __export(mcp_exports, {
2520
+ handleConfigure: () => handleConfigure,
2521
+ handleConfigureGlobalPath: () => handleConfigureGlobalPath,
2522
+ handleStartServer: () => handleStartServer,
2523
+ runMCP: () => runMCP
2524
+ });
2525
+ import { intro, outro, select as select2, confirm as confirm2, note as note6, cancel, isCancel as isCancel5 } from "@clack/prompts";
2526
+ import pc7 from "picocolors";
2527
+ async function runMCP(subcommand2) {
2528
+ if (subcommand2) {
2529
+ switch (subcommand2) {
2530
+ case "start":
2531
+ if (process.stdout.isTTY) {
2532
+ await handleStartServer();
2533
+ } else {
2534
+ await startMCPServer();
2535
+ await new Promise(() => {
2536
+ });
2537
+ }
2538
+ return;
2539
+ case "stop":
2540
+ await handleStopServer();
2541
+ return;
2542
+ case "status":
2543
+ await handleShowStatus();
2544
+ return;
2545
+ case "help":
2546
+ showHelp();
2547
+ return;
2548
+ case "configure":
2549
+ await handleConfigure();
2550
+ return;
2551
+ }
2401
2552
  }
2402
- saveMCPConfig(config);
2403
- logger2.info("Configure: Config saved", config);
2404
- const exposedCount = selectedNames.length;
2405
- note2(
2406
- `${pc3.green("\u2713")} Configuration saved!
2553
+ intro(pc7.bgCyan(pc7.black(" RRCE MCP Hub ")));
2554
+ const workspacePath = detectWorkspaceRoot();
2555
+ const globalPathCheck = await ensureMCPGlobalPath();
2556
+ if (!globalPathCheck.configured) {
2557
+ const configured = await handleConfigureGlobalPath();
2558
+ if (!configured) {
2559
+ outro(pc7.yellow("MCP requires a global storage path. Setup cancelled."));
2560
+ return;
2561
+ }
2562
+ }
2563
+ const installed = isInstalledAnywhere(workspacePath);
2564
+ if (!installed) {
2565
+ note6(
2566
+ `${pc7.bold("Welcome to RRCE MCP Hub!")}
2407
2567
 
2408
- Exposed projects: ${exposedCount}
2409
- Hidden projects: ${projects.length - exposedCount}`,
2410
- "Configuration Updated"
2411
- );
2568
+ MCP (Model Context Protocol) allows AI assistants to access your
2569
+ project knowledge in real-time. Let's get you set up.`,
2570
+ "Getting Started"
2571
+ );
2572
+ const shouldInstall = await confirm2({
2573
+ message: "Install MCP server to your IDE(s)?",
2574
+ initialValue: true
2575
+ });
2576
+ if (shouldInstall && !isCancel5(shouldInstall)) {
2577
+ await runInstallWizard(workspacePath);
2578
+ const config2 = loadMCPConfig();
2579
+ const exposedCount2 = config2.projects.filter((p) => p.expose).length;
2580
+ if (exposedCount2 === 0) {
2581
+ await handleConfigure();
2582
+ }
2583
+ const shouldStart = await confirm2({
2584
+ message: "Start the MCP server now?",
2585
+ initialValue: true
2586
+ });
2587
+ if (shouldStart && !isCancel5(shouldStart)) {
2588
+ await handleStartServer();
2589
+ }
2590
+ }
2591
+ outro(pc7.green("MCP Hub setup complete!"));
2592
+ return;
2593
+ }
2594
+ const config = loadMCPConfig();
2595
+ const exposedCount = config.projects.filter((p) => p.expose).length;
2596
+ if (exposedCount === 0 && !config.defaults.includeNew) {
2597
+ note6("MCP is installed but no projects are exposed. Let's configure that.", "Configuration Needed");
2598
+ await handleConfigure();
2599
+ }
2600
+ let running = true;
2601
+ while (running) {
2602
+ const serverStatus = getMCPServerStatus();
2603
+ const serverLabel = serverStatus.running ? pc7.green("\u25CF Running") : pc7.dim("\u25CB Stopped");
2604
+ const currentStatus = checkInstallStatus(workspacePath);
2605
+ const installedCount = [currentStatus.antigravity, currentStatus.claude, currentStatus.vscodeGlobal, currentStatus.vscodeWorkspace].filter(Boolean).length;
2606
+ const action = await select2({
2607
+ message: "What would you like to do?",
2608
+ options: [
2609
+ { value: "start", label: `\u25B6\uFE0F Start MCP server`, hint: serverLabel },
2610
+ { value: "configure", label: "\u2699\uFE0F Configure projects", hint: "Choose which projects to expose" },
2611
+ { value: "install", label: "\u{1F4E5} Install to IDE", hint: `${installedCount} IDE(s) configured` },
2612
+ { value: "status", label: "\u{1F4CB} View status", hint: "See details" },
2613
+ { value: "help", label: "\u2753 Help", hint: "Learn about MCP Hub" },
2614
+ { value: "exit", label: "\u21A9 Exit", hint: "Return to shell" }
2615
+ ]
2616
+ });
2617
+ if (isCancel5(action)) {
2618
+ cancel("MCP Hub closed.");
2619
+ return;
2620
+ }
2621
+ switch (action) {
2622
+ case "start":
2623
+ await handleStartServer();
2624
+ break;
2625
+ case "configure":
2626
+ await handleConfigure();
2627
+ break;
2628
+ case "install":
2629
+ await runInstallWizard(workspacePath);
2630
+ break;
2631
+ case "status":
2632
+ await handleShowStatus();
2633
+ break;
2634
+ case "help":
2635
+ showHelp();
2636
+ break;
2637
+ case "exit":
2638
+ running = false;
2639
+ break;
2640
+ }
2641
+ }
2642
+ outro(pc7.green("MCP Hub closed."));
2412
2643
  }
2413
2644
  async function handleStopServer() {
2645
+ const { stopMCPServer: stopMCPServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
2414
2646
  const status = getMCPServerStatus();
2415
2647
  if (!status.running) {
2416
- note2("MCP server is not running.", "Status");
2648
+ note6("MCP server is not running.", "Status");
2417
2649
  return;
2418
2650
  }
2419
- const confirmed = await confirm({
2651
+ const confirmed = await confirm2({
2420
2652
  message: "Stop the MCP server?",
2421
2653
  initialValue: true
2422
2654
  });
2423
- if (isCancel2(confirmed) || !confirmed) {
2655
+ if (isCancel5(confirmed) || !confirmed) {
2424
2656
  return;
2425
2657
  }
2426
- stopMCPServer();
2427
- note2(pc3.green("MCP server stopped."), "Server Stopped");
2428
- }
2429
- function showHelp() {
2430
- const help = `
2431
- ${pc3.bold("RRCE MCP Hub")} - Cross-project AI assistant server
2432
-
2433
- ${pc3.bold("ABOUT")}
2434
- MCP (Model Context Protocol) allows AI assistants like Claude to
2435
- access your project knowledge in real-time. The RRCE MCP Hub
2436
- provides a central server that exposes selected projects.
2437
-
2438
- ${pc3.bold("MENU OPTIONS")}
2439
- ${pc3.cyan("Start MCP server")} Start the server for AI access
2440
- ${pc3.cyan("Configure projects")} Choose which projects to expose
2441
- ${pc3.cyan("Install to IDE")} Add to Antigravity, VSCode, or Claude
2442
- ${pc3.cyan("View status")} See which projects are exposed
2443
-
2444
- ${pc3.bold("DIRECT COMMANDS")}
2445
- ${pc3.dim("rrce-workflow mcp start")} Start server directly
2446
- ${pc3.dim("rrce-workflow mcp stop")} Stop server directly
2447
- ${pc3.dim("rrce-workflow mcp status")} Show status directly
2448
- ${pc3.dim("rrce-workflow mcp help")} Show this help
2449
-
2450
- ${pc3.bold("IDE INSTALLATION")}
2451
- ${pc3.cyan("Antigravity")} ~/.gemini/antigravity/mcp_config.json
2452
- ${pc3.cyan("VSCode Global")} ~/.config/Code/User/settings.json
2453
- ${pc3.cyan("VSCode Workspace")} .vscode/mcp.json
2454
- ${pc3.cyan("Claude Desktop")} ~/.config/claude/claude_desktop_config.json
2455
-
2456
- ${pc3.bold("SERVER COMMANDS")} (while running)
2457
- ${pc3.cyan("q")} Stop and quit ${pc3.cyan("p")} Reconfigure projects
2458
- ${pc3.cyan("i")} Install to IDE ${pc3.cyan("r")} Reload config
2459
- ${pc3.cyan("c")} Clear logs ${pc3.cyan("?")} Show help
2460
-
2461
- ${pc3.bold("RESOURCES EXPOSED")}
2462
- ${pc3.cyan("rrce://projects")} List all exposed projects
2463
- ${pc3.cyan("rrce://projects/{name}/context")} Get project context
2464
- ${pc3.cyan("rrce://projects/{name}/tasks")} Get project tasks
2465
- `;
2466
- note2(help.trim(), "Help");
2658
+ stopMCPServer2();
2659
+ note6(pc7.green("MCP server stopped."), "Server Stopped");
2467
2660
  }
2468
2661
  var init_mcp = __esm({
2469
2662
  "src/mcp/index.ts"() {
2470
2663
  "use strict";
2471
2664
  init_config();
2472
- init_detection();
2473
2665
  init_server();
2474
2666
  init_install();
2475
2667
  init_paths();
2668
+ init_start();
2669
+ init_configure();
2670
+ init_status();
2671
+ init_install_wizard();
2672
+ init_help();
2476
2673
  }
2477
2674
  });
2478
2675
 
2479
2676
  // src/commands/wizard/setup-flow.ts
2480
- import { group, select as select3, multiselect as multiselect2, confirm as confirm2, spinner as spinner2, note as note3, outro as outro2, cancel as cancel2, isCancel as isCancel3 } from "@clack/prompts";
2481
- import pc4 from "picocolors";
2677
+ import { group, select as select3, multiselect as multiselect3, confirm as confirm3, spinner as spinner3, note as note7, outro as outro2, cancel as cancel2, isCancel as isCancel6 } from "@clack/prompts";
2678
+ import pc8 from "picocolors";
2482
2679
  import * as fs12 from "fs";
2483
2680
  import * as path12 from "path";
2484
2681
  async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
2485
- const s = spinner2();
2682
+ const s = spinner3();
2486
2683
  const config = await group(
2487
2684
  {
2488
2685
  storageMode: () => select3({
@@ -2493,7 +2690,7 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
2493
2690
  ],
2494
2691
  initialValue: "global"
2495
2692
  }),
2496
- tools: () => multiselect2({
2693
+ tools: () => multiselect3({
2497
2694
  message: "Which AI tools do you use?",
2498
2695
  options: [
2499
2696
  { value: "copilot", label: "GitHub Copilot", hint: "VSCode" },
@@ -2505,28 +2702,28 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
2505
2702
  if (existingProjects.length === 0) {
2506
2703
  return Promise.resolve([]);
2507
2704
  }
2508
- return multiselect2({
2705
+ return multiselect3({
2509
2706
  message: "Link knowledge from other projects?",
2510
2707
  options: existingProjects.map((project) => ({
2511
2708
  value: `${project.name}:${project.source}`,
2512
2709
  // Unique key
2513
- label: `${project.name} ${pc4.dim(`(${project.source})`)}`,
2514
- hint: pc4.dim(
2710
+ label: `${project.name} ${pc8.dim(`(${project.source})`)}`,
2711
+ hint: pc8.dim(
2515
2712
  project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
2516
2713
  )
2517
2714
  })),
2518
2715
  required: false
2519
2716
  });
2520
2717
  },
2521
- addToGitignore: () => confirm2({
2718
+ addToGitignore: () => confirm3({
2522
2719
  message: "Add generated folders to .gitignore? (as comments - uncomment if needed)",
2523
2720
  initialValue: true
2524
2721
  }),
2525
- confirm: () => confirm2({
2722
+ confirm: () => confirm3({
2526
2723
  message: "Create configuration?",
2527
2724
  initialValue: true
2528
2725
  }),
2529
- exposeToMCP: () => confirm2({
2726
+ exposeToMCP: () => confirm3({
2530
2727
  message: "Expose this project to MCP (AI Agent) server?",
2531
2728
  initialValue: true
2532
2729
  })
@@ -2571,7 +2768,7 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
2571
2768
  `Storage: ${config.storageMode}`
2572
2769
  ];
2573
2770
  if (customGlobalPath && customGlobalPath !== getDefaultRRCEHome()) {
2574
- summary.push(`Global path: ${pc4.cyan(customGlobalPath)}`);
2771
+ summary.push(`Global path: ${pc8.cyan(customGlobalPath)}`);
2575
2772
  }
2576
2773
  if (dataPaths.length > 0) {
2577
2774
  summary.push(`Data paths:`);
@@ -2584,29 +2781,29 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
2584
2781
  const linkedProjects = config.linkedProjects;
2585
2782
  if (linkedProjects.length > 0) {
2586
2783
  summary.push(`Linked projects: ${linkedProjects.join(", ")}`);
2587
- summary.push(`Workspace file: ${pc4.cyan(`${workspaceName}.code-workspace`)}`);
2784
+ summary.push(`Workspace file: ${pc8.cyan(`${workspaceName}.code-workspace`)}`);
2588
2785
  }
2589
- note3(summary.join("\n"), "Setup Summary");
2786
+ note7(summary.join("\n"), "Setup Summary");
2590
2787
  if (config.exposeToMCP) {
2591
- note3(`${pc4.green("\u2713")} Project exposed to MCP Hub`, "MCP Configuration");
2788
+ note7(`${pc8.green("\u2713")} Project exposed to MCP Hub`, "MCP Configuration");
2592
2789
  if (linkedProjects.length > 0) {
2593
- outro2(pc4.green(`\u2713 Setup complete! Open ${pc4.bold(`${workspaceName}.code-workspace`)} in VSCode to access linked knowledge.`));
2790
+ outro2(pc8.green(`\u2713 Setup complete! Open ${pc8.bold(`${workspaceName}.code-workspace`)} in VSCode to access linked knowledge.`));
2594
2791
  } else {
2595
- outro2(pc4.green(`\u2713 Setup complete! Your agents are ready to use.`));
2792
+ outro2(pc8.green(`\u2713 Setup complete! Your agents are ready to use.`));
2596
2793
  }
2597
2794
  } else {
2598
- const shouldConfigureMCP = await confirm2({
2795
+ const shouldConfigureMCP = await confirm3({
2599
2796
  message: "Would you like to configure the MCP server now?",
2600
2797
  initialValue: true
2601
2798
  });
2602
- if (shouldConfigureMCP && !isCancel3(shouldConfigureMCP)) {
2799
+ if (shouldConfigureMCP && !isCancel6(shouldConfigureMCP)) {
2603
2800
  const { runMCP: runMCP2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
2604
2801
  await runMCP2();
2605
2802
  } else {
2606
2803
  if (linkedProjects.length > 0) {
2607
- outro2(pc4.green(`\u2713 Setup complete! Open ${pc4.bold(`${workspaceName}.code-workspace`)} in VSCode to access linked knowledge.`));
2804
+ outro2(pc8.green(`\u2713 Setup complete! Open ${pc8.bold(`${workspaceName}.code-workspace`)} in VSCode to access linked knowledge.`));
2608
2805
  } else {
2609
- outro2(pc4.green(`\u2713 Setup complete! Your agents are ready to use.`));
2806
+ outro2(pc8.green(`\u2713 Setup complete! Your agents are ready to use.`));
2610
2807
  }
2611
2808
  }
2612
2809
  }
@@ -2770,8 +2967,8 @@ var init_setup_flow = __esm({
2770
2967
  });
2771
2968
 
2772
2969
  // src/commands/wizard/link-flow.ts
2773
- import { multiselect as multiselect3, spinner as spinner3, note as note4, outro as outro3, cancel as cancel3, isCancel as isCancel4 } from "@clack/prompts";
2774
- import pc5 from "picocolors";
2970
+ import { multiselect as multiselect4, spinner as spinner4, note as note8, outro as outro3, cancel as cancel3, isCancel as isCancel7, confirm as confirm4 } from "@clack/prompts";
2971
+ import pc9 from "picocolors";
2775
2972
  import * as fs13 from "fs";
2776
2973
  async function runLinkProjectsFlow(workspacePath, workspaceName) {
2777
2974
  const projects = scanForProjects({
@@ -2779,23 +2976,23 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
2779
2976
  workspacePath
2780
2977
  });
2781
2978
  if (projects.length === 0) {
2782
- outro3(pc5.yellow("No other projects found. Try setting up another project first."));
2979
+ outro3(pc9.yellow("No other projects found. Try setting up another project first."));
2783
2980
  return;
2784
2981
  }
2785
2982
  const customGlobalPath = getEffectiveRRCEHome(workspacePath);
2786
- const linkedProjects = await multiselect3({
2983
+ const linkedProjects = await multiselect4({
2787
2984
  message: "Select projects to link:",
2788
2985
  options: projects.map((project) => ({
2789
2986
  value: `${project.name}:${project.source}`,
2790
2987
  // Unique key
2791
- label: `${project.name} ${pc5.dim(`(${project.source})`)}`,
2792
- hint: pc5.dim(
2988
+ label: `${project.name} ${pc9.dim(`(${project.source})`)}`,
2989
+ hint: pc9.dim(
2793
2990
  project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
2794
2991
  )
2795
2992
  })),
2796
2993
  required: true
2797
2994
  });
2798
- if (isCancel4(linkedProjects)) {
2995
+ if (isCancel7(linkedProjects)) {
2799
2996
  cancel3("Cancelled.");
2800
2997
  process.exit(0);
2801
2998
  }
@@ -2807,7 +3004,7 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
2807
3004
  const selectedProjects = projects.filter(
2808
3005
  (p) => selectedKeys.includes(`${p.name}:${p.source}`)
2809
3006
  );
2810
- const s = spinner3();
3007
+ const s = spinner4();
2811
3008
  s.start("Linking projects");
2812
3009
  const configFilePath = getConfigPath(workspacePath);
2813
3010
  let configContent = fs13.readFileSync(configFilePath, "utf-8");
@@ -2843,12 +3040,29 @@ linked_projects:
2843
3040
  const workspaceFile = `${workspaceName}.code-workspace`;
2844
3041
  const summary = [
2845
3042
  `Linked projects:`,
2846
- ...selectedProjects.map((p) => ` \u2713 ${p.name} ${pc5.dim(`(${p.source})`)}`),
3043
+ ...selectedProjects.map((p) => ` \u2713 ${p.name} ${pc9.dim(`(${p.source})`)}`),
2847
3044
  ``,
2848
- `Workspace file: ${pc5.cyan(workspaceFile)}`
3045
+ `Workspace file: ${pc9.cyan(workspaceFile)}`
2849
3046
  ];
2850
- note4(summary.join("\n"), "Link Summary");
2851
- outro3(pc5.green(`\u2713 Projects linked! Open ${pc5.bold(workspaceFile)} in VSCode to access linked data.`));
3047
+ note8(summary.join("\n"), "Link Summary");
3048
+ outro3(pc9.green(`\u2713 Projects linked! Open ${pc9.bold(workspaceFile)} in VSCode to access linked data.`));
3049
+ const shouldExpose = await confirm4({
3050
+ message: "Also expose these linked projects to the MCP server (for Agent access)?",
3051
+ initialValue: true
3052
+ });
3053
+ if (shouldExpose && !isCancel7(shouldExpose)) {
3054
+ try {
3055
+ const { loadMCPConfig: loadMCPConfig2, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
3056
+ const mcpConfig = loadMCPConfig2();
3057
+ for (const project of selectedProjects) {
3058
+ setProjectConfig2(mcpConfig, project.name, true, void 0, project.dataPath);
3059
+ }
3060
+ saveMCPConfig2(mcpConfig);
3061
+ note8("Projects have been added to the global MCP configuration.", "MCP Updated");
3062
+ } catch (err) {
3063
+ note8(`Failed to update MCP config: ${err}`, "MCP Update Failed");
3064
+ }
3065
+ }
2852
3066
  }
2853
3067
  var init_link_flow = __esm({
2854
3068
  "src/commands/wizard/link-flow.ts"() {
@@ -2860,8 +3074,8 @@ var init_link_flow = __esm({
2860
3074
  });
2861
3075
 
2862
3076
  // src/commands/wizard/sync-flow.ts
2863
- import { confirm as confirm3, spinner as spinner4, note as note5, outro as outro4, cancel as cancel4, isCancel as isCancel5 } from "@clack/prompts";
2864
- import pc6 from "picocolors";
3077
+ import { confirm as confirm5, spinner as spinner5, note as note9, outro as outro4, cancel as cancel4, isCancel as isCancel8 } from "@clack/prompts";
3078
+ import pc10 from "picocolors";
2865
3079
  import * as fs14 from "fs";
2866
3080
  import * as path13 from "path";
2867
3081
  async function runSyncToGlobalFlow(workspacePath, workspaceName) {
@@ -2873,25 +3087,25 @@ async function runSyncToGlobalFlow(workspacePath, workspaceName) {
2873
3087
  (dir) => fs14.existsSync(path13.join(localPath, dir))
2874
3088
  );
2875
3089
  if (existingDirs.length === 0) {
2876
- outro4(pc6.yellow("No data found in workspace storage to sync."));
3090
+ outro4(pc10.yellow("No data found in workspace storage to sync."));
2877
3091
  return;
2878
3092
  }
2879
- note5(
3093
+ note9(
2880
3094
  `The following will be copied to global storage:
2881
3095
  ${existingDirs.map((d) => ` \u2022 ${d}/`).join("\n")}
2882
3096
 
2883
- Destination: ${pc6.cyan(globalPath)}`,
3097
+ Destination: ${pc10.cyan(globalPath)}`,
2884
3098
  "Sync Preview"
2885
3099
  );
2886
- const shouldSync = await confirm3({
3100
+ const shouldSync = await confirm5({
2887
3101
  message: "Proceed with sync to global storage?",
2888
3102
  initialValue: true
2889
3103
  });
2890
- if (isCancel5(shouldSync) || !shouldSync) {
3104
+ if (isCancel8(shouldSync) || !shouldSync) {
2891
3105
  outro4("Sync cancelled.");
2892
3106
  return;
2893
3107
  }
2894
- const s = spinner4();
3108
+ const s = spinner5();
2895
3109
  s.start("Syncing to global storage");
2896
3110
  try {
2897
3111
  ensureDir(globalPath);
@@ -2906,12 +3120,12 @@ Destination: ${pc6.cyan(globalPath)}`,
2906
3120
  `Synced directories:`,
2907
3121
  ...existingDirs.map((d) => ` \u2713 ${d}/`),
2908
3122
  ``,
2909
- `Global path: ${pc6.cyan(globalPath)}`,
3123
+ `Global path: ${pc10.cyan(globalPath)}`,
2910
3124
  ``,
2911
3125
  `Other projects can now link this knowledge!`
2912
3126
  ];
2913
- note5(summary.join("\n"), "Sync Summary");
2914
- outro4(pc6.green("\u2713 Workspace knowledge synced to global storage!"));
3127
+ note9(summary.join("\n"), "Sync Summary");
3128
+ outro4(pc10.green("\u2713 Workspace knowledge synced to global storage!"));
2915
3129
  } catch (error) {
2916
3130
  s.stop("Error occurred");
2917
3131
  cancel4(`Failed to sync: ${error instanceof Error ? error.message : String(error)}`);
@@ -2927,12 +3141,12 @@ var init_sync_flow = __esm({
2927
3141
  });
2928
3142
 
2929
3143
  // src/commands/wizard/update-flow.ts
2930
- import { confirm as confirm4, spinner as spinner5, note as note6, outro as outro5, cancel as cancel5, isCancel as isCancel6 } from "@clack/prompts";
2931
- import pc7 from "picocolors";
3144
+ import { confirm as confirm6, spinner as spinner6, note as note10, outro as outro5, cancel as cancel5, isCancel as isCancel9 } from "@clack/prompts";
3145
+ import pc11 from "picocolors";
2932
3146
  import * as fs15 from "fs";
2933
3147
  import * as path14 from "path";
2934
3148
  async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
2935
- const s = spinner5();
3149
+ const s = spinner6();
2936
3150
  s.start("Checking for updates");
2937
3151
  try {
2938
3152
  const agentCoreDir = getAgentCoreDir();
@@ -2941,7 +3155,7 @@ async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
2941
3155
  const customGlobalPath = getEffectiveRRCEHome(workspacePath);
2942
3156
  const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
2943
3157
  s.stop("Updates found");
2944
- note6(
3158
+ note10(
2945
3159
  `The following will be updated from the package:
2946
3160
  \u2022 prompts/ (${prompts.length} agent prompts)
2947
3161
  \u2022 templates/ (output templates)
@@ -2950,11 +3164,11 @@ Target locations:
2950
3164
  ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
2951
3165
  "Update Preview"
2952
3166
  );
2953
- const shouldUpdate = await confirm4({
3167
+ const shouldUpdate = await confirm6({
2954
3168
  message: "Proceed with update?",
2955
3169
  initialValue: true
2956
3170
  });
2957
- if (isCancel6(shouldUpdate) || !shouldUpdate) {
3171
+ if (isCancel9(shouldUpdate) || !shouldUpdate) {
2958
3172
  outro5("Update cancelled.");
2959
3173
  return;
2960
3174
  }
@@ -2982,8 +3196,8 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
2982
3196
  ``,
2983
3197
  `Your configuration and knowledge files were preserved.`
2984
3198
  ];
2985
- note6(summary.join("\n"), "Update Summary");
2986
- outro5(pc7.green("\u2713 Successfully updated from package!"));
3199
+ note10(summary.join("\n"), "Update Summary");
3200
+ outro5(pc11.green("\u2713 Successfully updated from package!"));
2987
3201
  } catch (error) {
2988
3202
  s.stop("Error occurred");
2989
3203
  cancel5(`Failed to update: ${error instanceof Error ? error.message : String(error)}`);
@@ -3016,21 +3230,21 @@ var wizard_exports = {};
3016
3230
  __export(wizard_exports, {
3017
3231
  runWizard: () => runWizard
3018
3232
  });
3019
- import { intro as intro2, select as select4, spinner as spinner6, note as note7, outro as outro6, isCancel as isCancel7 } from "@clack/prompts";
3020
- import pc8 from "picocolors";
3233
+ import { intro as intro2, select as select4, spinner as spinner7, note as note11, outro as outro6, isCancel as isCancel10 } from "@clack/prompts";
3234
+ import pc12 from "picocolors";
3021
3235
  import * as fs16 from "fs";
3022
3236
  async function runWizard() {
3023
- intro2(pc8.cyan(pc8.inverse(" RRCE-Workflow Setup ")));
3024
- const s = spinner6();
3237
+ intro2(pc12.cyan(pc12.inverse(" RRCE-Workflow Setup ")));
3238
+ const s = spinner7();
3025
3239
  s.start("Detecting environment");
3026
3240
  const workspacePath = detectWorkspaceRoot();
3027
3241
  const workspaceName = getWorkspaceName(workspacePath);
3028
3242
  const gitUser = getGitUser();
3029
3243
  await new Promise((r) => setTimeout(r, 800));
3030
3244
  s.stop("Environment detected");
3031
- note7(
3032
- `Git User: ${pc8.bold(gitUser || "(not found)")}
3033
- Workspace: ${pc8.bold(workspaceName)}`,
3245
+ note11(
3246
+ `Git User: ${pc12.bold(gitUser || "(not found)")}
3247
+ Workspace: ${pc12.bold(workspaceName)}`,
3034
3248
  "Context"
3035
3249
  );
3036
3250
  const detectedProjects = scanForProjects({
@@ -3072,12 +3286,13 @@ Workspace: ${pc8.bold(workspaceName)}`,
3072
3286
  });
3073
3287
  }
3074
3288
  menuOptions.push({ value: "update", label: "\u{1F4E6} Update from package", hint: "Get latest prompts & templates" });
3289
+ menuOptions.push({ value: "reconfigure", label: "\u{1F527} Reconfigure project", hint: "Change storage mode, tools, etc." });
3075
3290
  menuOptions.push({ value: "exit", label: "\u21A9 Exit" });
3076
3291
  const action = await select4({
3077
3292
  message: "This workspace is already configured. What would you like to do?",
3078
3293
  options: menuOptions
3079
3294
  });
3080
- if (isCancel7(action) || action === "exit") {
3295
+ if (isCancel10(action) || action === "exit") {
3081
3296
  outro6("Exited.");
3082
3297
  process.exit(0);
3083
3298
  }
@@ -3097,6 +3312,8 @@ Workspace: ${pc8.bold(workspaceName)}`,
3097
3312
  await runUpdateFlow(workspacePath, workspaceName, currentStorageMode);
3098
3313
  return;
3099
3314
  }
3315
+ if (action === "reconfigure") {
3316
+ }
3100
3317
  }
3101
3318
  await runSetupFlow(workspacePath, workspaceName, detectedProjects);
3102
3319
  }
@@ -3119,12 +3336,12 @@ init_wizard();
3119
3336
 
3120
3337
  // src/commands/selector.ts
3121
3338
  init_prompts();
3122
- import { intro as intro3, select as select5, note as note8, cancel as cancel7, isCancel as isCancel8, outro as outro7 } from "@clack/prompts";
3123
- import pc9 from "picocolors";
3339
+ import { intro as intro3, select as select5, note as note12, cancel as cancel7, isCancel as isCancel11, outro as outro7 } from "@clack/prompts";
3340
+ import pc13 from "picocolors";
3124
3341
  import * as path15 from "path";
3125
3342
  async function runSelector() {
3126
3343
  const workspaceName = path15.basename(process.cwd());
3127
- intro3(pc9.cyan(pc9.inverse(` RRCE-Workflow | ${workspaceName} `)));
3344
+ intro3(pc13.cyan(pc13.inverse(` RRCE-Workflow | ${workspaceName} `)));
3128
3345
  const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
3129
3346
  if (prompts.length === 0) {
3130
3347
  cancel7("No agents found. Run `rrce-workflow` to set up.");
@@ -3150,7 +3367,7 @@ async function runSelector() {
3150
3367
  }))
3151
3368
  ]
3152
3369
  });
3153
- if (isCancel8(selection)) {
3370
+ if (isCancel11(selection)) {
3154
3371
  cancel7("Selection cancelled.");
3155
3372
  process.exit(0);
3156
3373
  }
@@ -3165,9 +3382,9 @@ async function runSelector() {
3165
3382
  return;
3166
3383
  }
3167
3384
  const prompt = selection;
3168
- note8(
3385
+ note12(
3169
3386
  `Use this agent in your IDE by invoking:
3170
- ${pc9.bold(pc9.cyan(`@${prompt.frontmatter.name}`))}`,
3387
+ ${pc13.bold(pc13.cyan(`@${prompt.frontmatter.name}`))}`,
3171
3388
  "Agent Selected"
3172
3389
  );
3173
3390
  outro7("Done");