rrce-workflow 0.2.36 → 0.2.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +158 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1134,12 +1134,58 @@ import * as path10 from "path";
1134
1134
  function getExposedProjects() {
1135
1135
  const config = loadMCPConfig();
1136
1136
  const allProjects = scanForProjects();
1137
- return allProjects.filter((project) => isProjectExposed(config, project.name, project.dataPath));
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];
1138
1179
  }
1139
- function detectActiveProject() {
1140
- 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
+ }
1141
1187
  const cwd = process.cwd();
1142
- const matches = exposed.filter((p) => cwd.startsWith(p.path));
1188
+ const matches = scanList.filter((p) => cwd.startsWith(p.path));
1143
1189
  matches.sort((a, b) => b.path.length - a.path.length);
1144
1190
  return matches[0];
1145
1191
  }
@@ -2075,9 +2121,12 @@ var StatusBoard;
2075
2121
  var init_StatusBoard = __esm({
2076
2122
  "src/mcp/ui/StatusBoard.tsx"() {
2077
2123
  "use strict";
2078
- StatusBoard = ({ exposedLabel, port, pid }) => {
2124
+ StatusBoard = ({ exposedLabel, port, pid, running }) => {
2079
2125
  return /* @__PURE__ */ jsx2(Box2, { borderStyle: "single", borderColor: "cyan", paddingX: 1, children: /* @__PURE__ */ jsxs(Text2, { children: [
2080
- "\u{1F4CB} ",
2126
+ running ? /* @__PURE__ */ jsx2(Text2, { color: "green", children: "\u25CF RUNNING" }) : /* @__PURE__ */ jsx2(Text2, { color: "red", children: "\u25CF STOPPED" }),
2127
+ " ",
2128
+ "\u2502",
2129
+ " \u{1F4CB} ",
2081
2130
  /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: exposedLabel }),
2082
2131
  " ",
2083
2132
  "\u2502",
@@ -2139,10 +2188,62 @@ var init_CommandBar = __esm({
2139
2188
  }
2140
2189
  });
2141
2190
 
2142
- // src/mcp/ui/Dashboard.tsx
2191
+ // src/mcp/ui/HelpModal.tsx
2143
2192
  import "react";
2144
- import { Box as Box5 } from "ink";
2193
+ import { Box as Box5, Text as Text5 } from "ink";
2145
2194
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2195
+ var HelpModal;
2196
+ var init_HelpModal = __esm({
2197
+ "src/mcp/ui/HelpModal.tsx"() {
2198
+ "use strict";
2199
+ HelpModal = ({ onClose }) => {
2200
+ return /* @__PURE__ */ jsxs4(Box5, { borderStyle: "double", borderColor: "yellow", padding: 1, flexDirection: "column", children: [
2201
+ /* @__PURE__ */ jsx5(Text5, { bold: true, color: "yellow", children: "\u2328\uFE0F Keyboard Shortcuts" }),
2202
+ /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 1, children: [
2203
+ /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { bold: true, color: "cyan", children: "Configuration:" }) }),
2204
+ /* @__PURE__ */ jsxs4(Text5, { children: [
2205
+ " ",
2206
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "p" }),
2207
+ " - Configure Projects (Opens Wizard)"
2208
+ ] }),
2209
+ /* @__PURE__ */ jsxs4(Text5, { children: [
2210
+ " ",
2211
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "i" }),
2212
+ " - Install to IDEs (Opens Wizard)"
2213
+ ] }),
2214
+ /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { bold: true, color: "cyan", children: "Server Control:" }) }),
2215
+ /* @__PURE__ */ jsxs4(Text5, { children: [
2216
+ " ",
2217
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "r" }),
2218
+ " - Reload Configuration"
2219
+ ] }),
2220
+ /* @__PURE__ */ jsxs4(Text5, { children: [
2221
+ " ",
2222
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "c" }),
2223
+ " - Clear Logs"
2224
+ ] }),
2225
+ /* @__PURE__ */ jsxs4(Text5, { children: [
2226
+ " ",
2227
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "q" }),
2228
+ " - Stop Server & Exit"
2229
+ ] }),
2230
+ /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { bold: true, color: "cyan", children: "Other:" }) }),
2231
+ /* @__PURE__ */ jsxs4(Text5, { children: [
2232
+ " ",
2233
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "?" }),
2234
+ " - Toggle this Help"
2235
+ ] })
2236
+ ] }),
2237
+ /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { color: "gray", children: "Press '?' again to close" }) })
2238
+ ] });
2239
+ };
2240
+ }
2241
+ });
2242
+
2243
+ // src/mcp/ui/Dashboard.tsx
2244
+ import "react";
2245
+ import { Box as Box6 } from "ink";
2246
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2146
2247
  var Dashboard;
2147
2248
  var init_Dashboard = __esm({
2148
2249
  "src/mcp/ui/Dashboard.tsx"() {
@@ -2151,12 +2252,14 @@ var init_Dashboard = __esm({
2151
2252
  init_StatusBoard();
2152
2253
  init_LogViewer();
2153
2254
  init_CommandBar();
2154
- Dashboard = ({ logs, exposedLabel, port, pid, logHeight }) => {
2155
- return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", padding: 0, children: [
2156
- /* @__PURE__ */ jsx5(Header, {}),
2157
- /* @__PURE__ */ jsx5(LogViewer, { logs, height: logHeight }),
2158
- /* @__PURE__ */ jsx5(StatusBoard, { exposedLabel, port, pid }),
2159
- /* @__PURE__ */ jsx5(CommandBar, {})
2255
+ init_HelpModal();
2256
+ Dashboard = ({ logs, exposedLabel, port, pid, running, logHeight, showHelp: showHelp2 }) => {
2257
+ return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", padding: 0, children: [
2258
+ /* @__PURE__ */ jsx6(Header, {}),
2259
+ showHelp2 ? /* @__PURE__ */ jsx6(HelpModal, { onClose: () => {
2260
+ } }) : /* @__PURE__ */ jsx6(LogViewer, { logs, height: logHeight }),
2261
+ /* @__PURE__ */ jsx6(StatusBoard, { exposedLabel, port, pid, running }),
2262
+ /* @__PURE__ */ jsx6(CommandBar, {})
2160
2263
  ] });
2161
2264
  };
2162
2265
  }
@@ -2170,7 +2273,7 @@ __export(App_exports, {
2170
2273
  import { useState, useEffect as useEffect2 } from "react";
2171
2274
  import { useInput, useApp } from "ink";
2172
2275
  import fs11 from "fs";
2173
- import { jsx as jsx6 } from "react/jsx-runtime";
2276
+ import { jsx as jsx7 } from "react/jsx-runtime";
2174
2277
  var App;
2175
2278
  var init_App = __esm({
2176
2279
  "src/mcp/ui/App.tsx"() {
@@ -2188,10 +2291,13 @@ var init_App = __esm({
2188
2291
  pid: process.pid,
2189
2292
  running: false
2190
2293
  });
2294
+ const [showHelp2, setShowHelp] = useState(false);
2191
2295
  const config = loadMCPConfig();
2192
2296
  const projects = scanForProjects();
2193
2297
  const exposedProjects = projects.filter((p) => {
2194
- const cfg = config.projects.find((c) => c.name === p.name);
2298
+ const cfg = config.projects.find(
2299
+ (c) => c.path && c.path === p.dataPath || !c.path && c.name === p.name
2300
+ );
2195
2301
  return cfg?.expose ?? config.defaults.includeNew;
2196
2302
  });
2197
2303
  const exposedNames = exposedProjects.map((p) => p.name).slice(0, 5);
@@ -2248,10 +2354,12 @@ var init_App = __esm({
2248
2354
  exit();
2249
2355
  }
2250
2356
  if (input === "p") {
2357
+ setLogs((prev) => [...prev, "Switching to configuration wizard..."]);
2251
2358
  onConfigure();
2252
2359
  exit();
2253
2360
  }
2254
2361
  if (input === "i") {
2362
+ setLogs((prev) => [...prev, "Switching to install wizard..."]);
2255
2363
  onInstall();
2256
2364
  exit();
2257
2365
  }
@@ -2261,17 +2369,22 @@ var init_App = __esm({
2261
2369
  if (input === "r") {
2262
2370
  setLogs((prev) => [...prev, "[INFO] Config reload requested..."]);
2263
2371
  }
2372
+ if (input === "?") {
2373
+ setShowHelp((prev) => !prev);
2374
+ }
2264
2375
  }, { isActive: true });
2265
2376
  const termHeight = process.stdout.rows || 24;
2266
2377
  const logHeight = Math.max(5, termHeight - 12);
2267
- return /* @__PURE__ */ jsx6(
2378
+ return /* @__PURE__ */ jsx7(
2268
2379
  Dashboard,
2269
2380
  {
2270
2381
  logs,
2271
2382
  exposedLabel,
2272
2383
  port: serverInfo.port,
2273
2384
  pid: serverInfo.pid,
2274
- logHeight
2385
+ running: serverInfo.running,
2386
+ logHeight,
2387
+ showHelp: showHelp2
2275
2388
  }
2276
2389
  );
2277
2390
  };
@@ -2281,7 +2394,7 @@ var init_App = __esm({
2281
2394
  // src/mcp/commands/start.ts
2282
2395
  import { confirm, isCancel as isCancel4, text } from "@clack/prompts";
2283
2396
  async function handleStartServer() {
2284
- const React7 = await import("react");
2397
+ const React8 = await import("react");
2285
2398
  const { render } = await import("ink");
2286
2399
  const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
2287
2400
  const config = loadMCPConfig();
@@ -2326,7 +2439,7 @@ async function handleStartServer() {
2326
2439
  while (keepRunning) {
2327
2440
  let nextAction = "exit";
2328
2441
  process.stdin.resume();
2329
- const app = render(React7.createElement(App2, {
2442
+ const app = render(React8.createElement(App2, {
2330
2443
  initialPort,
2331
2444
  onExit: () => {
2332
2445
  nextAction = "exit";
@@ -2921,7 +3034,7 @@ var init_setup_flow = __esm({
2921
3034
  });
2922
3035
 
2923
3036
  // src/commands/wizard/link-flow.ts
2924
- import { multiselect as multiselect4, spinner as spinner4, note as note8, outro as outro3, cancel as cancel3, isCancel as isCancel7 } from "@clack/prompts";
3037
+ 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";
2925
3038
  import pc9 from "picocolors";
2926
3039
  import * as fs13 from "fs";
2927
3040
  async function runLinkProjectsFlow(workspacePath, workspaceName) {
@@ -3000,6 +3113,23 @@ linked_projects:
3000
3113
  ];
3001
3114
  note8(summary.join("\n"), "Link Summary");
3002
3115
  outro3(pc9.green(`\u2713 Projects linked! Open ${pc9.bold(workspaceFile)} in VSCode to access linked data.`));
3116
+ const shouldExpose = await confirm4({
3117
+ message: "Also expose these linked projects to the MCP server (for Agent access)?",
3118
+ initialValue: true
3119
+ });
3120
+ if (shouldExpose && !isCancel7(shouldExpose)) {
3121
+ try {
3122
+ const { loadMCPConfig: loadMCPConfig2, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
3123
+ const mcpConfig = loadMCPConfig2();
3124
+ for (const project of selectedProjects) {
3125
+ setProjectConfig2(mcpConfig, project.name, true, void 0, project.dataPath);
3126
+ }
3127
+ saveMCPConfig2(mcpConfig);
3128
+ note8("Projects have been added to the global MCP configuration.", "MCP Updated");
3129
+ } catch (err) {
3130
+ note8(`Failed to update MCP config: ${err}`, "MCP Update Failed");
3131
+ }
3132
+ }
3003
3133
  }
3004
3134
  var init_link_flow = __esm({
3005
3135
  "src/commands/wizard/link-flow.ts"() {
@@ -3011,7 +3141,7 @@ var init_link_flow = __esm({
3011
3141
  });
3012
3142
 
3013
3143
  // src/commands/wizard/sync-flow.ts
3014
- import { confirm as confirm4, spinner as spinner5, note as note9, outro as outro4, cancel as cancel4, isCancel as isCancel8 } from "@clack/prompts";
3144
+ import { confirm as confirm5, spinner as spinner5, note as note9, outro as outro4, cancel as cancel4, isCancel as isCancel8 } from "@clack/prompts";
3015
3145
  import pc10 from "picocolors";
3016
3146
  import * as fs14 from "fs";
3017
3147
  import * as path13 from "path";
@@ -3034,7 +3164,7 @@ ${existingDirs.map((d) => ` \u2022 ${d}/`).join("\n")}
3034
3164
  Destination: ${pc10.cyan(globalPath)}`,
3035
3165
  "Sync Preview"
3036
3166
  );
3037
- const shouldSync = await confirm4({
3167
+ const shouldSync = await confirm5({
3038
3168
  message: "Proceed with sync to global storage?",
3039
3169
  initialValue: true
3040
3170
  });
@@ -3078,7 +3208,7 @@ var init_sync_flow = __esm({
3078
3208
  });
3079
3209
 
3080
3210
  // src/commands/wizard/update-flow.ts
3081
- import { confirm as confirm5, spinner as spinner6, note as note10, outro as outro5, cancel as cancel5, isCancel as isCancel9 } from "@clack/prompts";
3211
+ import { confirm as confirm6, spinner as spinner6, note as note10, outro as outro5, cancel as cancel5, isCancel as isCancel9 } from "@clack/prompts";
3082
3212
  import pc11 from "picocolors";
3083
3213
  import * as fs15 from "fs";
3084
3214
  import * as path14 from "path";
@@ -3101,7 +3231,7 @@ Target locations:
3101
3231
  ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
3102
3232
  "Update Preview"
3103
3233
  );
3104
- const shouldUpdate = await confirm5({
3234
+ const shouldUpdate = await confirm6({
3105
3235
  message: "Proceed with update?",
3106
3236
  initialValue: true
3107
3237
  });
@@ -3223,6 +3353,7 @@ Workspace: ${pc12.bold(workspaceName)}`,
3223
3353
  });
3224
3354
  }
3225
3355
  menuOptions.push({ value: "update", label: "\u{1F4E6} Update from package", hint: "Get latest prompts & templates" });
3356
+ menuOptions.push({ value: "reconfigure", label: "\u{1F527} Reconfigure project", hint: "Change storage mode, tools, etc." });
3226
3357
  menuOptions.push({ value: "exit", label: "\u21A9 Exit" });
3227
3358
  const action = await select4({
3228
3359
  message: "This workspace is already configured. What would you like to do?",
@@ -3248,6 +3379,8 @@ Workspace: ${pc12.bold(workspaceName)}`,
3248
3379
  await runUpdateFlow(workspacePath, workspaceName, currentStorageMode);
3249
3380
  return;
3250
3381
  }
3382
+ if (action === "reconfigure") {
3383
+ }
3251
3384
  }
3252
3385
  await runSetupFlow(workspacePath, workspaceName, detectedProjects);
3253
3386
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.36",
3
+ "version": "0.2.38",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",