rrce-workflow 0.2.38 → 0.2.39

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 +230 -49
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2265,15 +2265,213 @@ var init_Dashboard = __esm({
2265
2265
  }
2266
2266
  });
2267
2267
 
2268
+ // src/mcp/ui/components/SimpleSelect.tsx
2269
+ import { useState } from "react";
2270
+ import { Box as Box7, Text as Text6, useInput } from "ink";
2271
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2272
+ function SimpleSelect({
2273
+ items,
2274
+ onSelect,
2275
+ isMulti = false,
2276
+ initialSelected = [],
2277
+ onSubmit,
2278
+ onCancel,
2279
+ message
2280
+ }) {
2281
+ const [selectedIndex, setSelectedIndex] = useState(0);
2282
+ const [selectedValues, setSelectedValues] = useState(new Set(initialSelected));
2283
+ useInput((input, key) => {
2284
+ if (key.upArrow) {
2285
+ setSelectedIndex((prev) => prev > 0 ? prev - 1 : items.length - 1);
2286
+ }
2287
+ if (key.downArrow) {
2288
+ setSelectedIndex((prev) => prev < items.length - 1 ? prev + 1 : 0);
2289
+ }
2290
+ if (input === " " && isMulti) {
2291
+ const item = items[selectedIndex];
2292
+ if (item) {
2293
+ const newSet = new Set(selectedValues);
2294
+ if (newSet.has(item.value)) {
2295
+ newSet.delete(item.value);
2296
+ } else {
2297
+ newSet.add(item.value);
2298
+ }
2299
+ setSelectedValues(newSet);
2300
+ }
2301
+ }
2302
+ if (key.return) {
2303
+ if (isMulti) {
2304
+ onSubmit?.(Array.from(selectedValues));
2305
+ } else {
2306
+ const item = items[selectedIndex];
2307
+ if (item) onSelect(item);
2308
+ }
2309
+ }
2310
+ if (key.escape) {
2311
+ onCancel?.();
2312
+ }
2313
+ });
2314
+ return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1, children: [
2315
+ message && /* @__PURE__ */ jsx7(Box7, { marginBottom: 1, children: /* @__PURE__ */ jsx7(Text6, { bold: true, children: message }) }),
2316
+ items.map((item, index) => {
2317
+ const isSelected = index === selectedIndex;
2318
+ const isChecked = isMulti && selectedValues.has(item.value);
2319
+ return /* @__PURE__ */ jsxs6(Box7, { children: [
2320
+ /* @__PURE__ */ jsx7(Text6, { color: isSelected ? "cyan" : "white", children: isSelected ? "> " : " " }),
2321
+ isMulti && /* @__PURE__ */ jsx7(Text6, { color: isChecked ? "green" : "gray", children: isChecked ? "[x] " : "[ ] " }),
2322
+ /* @__PURE__ */ jsx7(Text6, { color: isSelected ? "cyan" : "white", children: item.label })
2323
+ ] }, item.key || String(item.value));
2324
+ }),
2325
+ /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: "gray", children: isMulti ? "Space to toggle, Enter to confirm, Esc to cancel" : "Enter to select, Esc to cancel" }) })
2326
+ ] });
2327
+ }
2328
+ var init_SimpleSelect = __esm({
2329
+ "src/mcp/ui/components/SimpleSelect.tsx"() {
2330
+ "use strict";
2331
+ }
2332
+ });
2333
+
2334
+ // src/mcp/ui/ConfigModal.tsx
2335
+ import { useState as useState2 } from "react";
2336
+ import { Box as Box8 } from "ink";
2337
+ import { jsx as jsx8 } from "react/jsx-runtime";
2338
+ var ConfigModal;
2339
+ var init_ConfigModal = __esm({
2340
+ "src/mcp/ui/ConfigModal.tsx"() {
2341
+ "use strict";
2342
+ init_SimpleSelect();
2343
+ init_config();
2344
+ init_detection();
2345
+ init_config();
2346
+ ConfigModal = ({ onBack }) => {
2347
+ const [config, setConfig] = useState2(loadMCPConfig());
2348
+ const allProjects = scanForProjects();
2349
+ const projectItems = allProjects.map((p) => {
2350
+ const projectConfig = config.projects.find(
2351
+ (c) => c.path && c.path === p.dataPath || !c.path && c.name === p.name
2352
+ );
2353
+ const isExposed = projectConfig ? projectConfig.expose : config.defaults.includeNew;
2354
+ return {
2355
+ label: p.name + ` (${p.source})` + (p.path ? ` - ${p.path}` : ""),
2356
+ value: p.dataPath,
2357
+ // Unique ID
2358
+ key: p.dataPath,
2359
+ exposed: isExposed
2360
+ };
2361
+ });
2362
+ const initialSelected = projectItems.filter((p) => p.exposed).map((p) => p.value);
2363
+ const handleSubmit = (selectedIds) => {
2364
+ let newConfig = { ...config };
2365
+ projectItems.forEach((item) => {
2366
+ const isSelected = selectedIds.includes(item.value);
2367
+ const project = allProjects.find((p) => p.dataPath === item.value);
2368
+ if (project) {
2369
+ newConfig = setProjectConfig(
2370
+ newConfig,
2371
+ project.name,
2372
+ isSelected,
2373
+ void 0,
2374
+ // Keep existing permissions or defaults
2375
+ project.path
2376
+ // Ensure path is stored
2377
+ );
2378
+ }
2379
+ });
2380
+ saveMCPConfig(newConfig);
2381
+ onBack();
2382
+ };
2383
+ return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", children: /* @__PURE__ */ jsx8(
2384
+ SimpleSelect,
2385
+ {
2386
+ message: "Select projects to expose via MCP:",
2387
+ items: projectItems,
2388
+ isMulti: true,
2389
+ initialSelected,
2390
+ onSelect: () => {
2391
+ },
2392
+ onSubmit: handleSubmit,
2393
+ onCancel: onBack
2394
+ }
2395
+ ) });
2396
+ };
2397
+ }
2398
+ });
2399
+
2400
+ // src/mcp/ui/InstallModal.tsx
2401
+ import { useState as useState3 } from "react";
2402
+ import { Box as Box9, Text as Text8 } from "ink";
2403
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2404
+ var InstallModal;
2405
+ var init_InstallModal = __esm({
2406
+ "src/mcp/ui/InstallModal.tsx"() {
2407
+ "use strict";
2408
+ init_SimpleSelect();
2409
+ init_install();
2410
+ init_paths();
2411
+ InstallModal = ({ onBack }) => {
2412
+ const [step, setStep] = useState3("select");
2413
+ const [statusMsg, setStatusMsg] = useState3("");
2414
+ const items = [
2415
+ { label: "VSCode (User Settings)", value: "vscode-global" },
2416
+ { label: "VSCode (Workspace)", value: "vscode-workspace" },
2417
+ { label: "Claude Desktop", value: "claude" },
2418
+ { label: "Antigravity", value: "antigravity" }
2419
+ ];
2420
+ const handleInstall = async (targets) => {
2421
+ setStep("installing");
2422
+ setStatusMsg("Installing...");
2423
+ try {
2424
+ const workspacePath = detectWorkspaceRoot();
2425
+ const results = [];
2426
+ for (const target of targets) {
2427
+ const result = await installToConfig(target, workspacePath);
2428
+ results.push(`${target}: ${result ? "Success" : "Failed"}`);
2429
+ }
2430
+ setStatusMsg(results.join("\n"));
2431
+ setStep("done");
2432
+ } catch (e) {
2433
+ setStatusMsg(`Error: ${e}`);
2434
+ setStep("done");
2435
+ }
2436
+ };
2437
+ if (step === "done") {
2438
+ return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "green", padding: 1, children: [
2439
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "green", children: "Installation Complete" }),
2440
+ /* @__PURE__ */ jsx9(Text8, { children: statusMsg }),
2441
+ /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(
2442
+ SimpleSelect,
2443
+ {
2444
+ items: [{ label: "Back to Dashboard", value: "back" }],
2445
+ onSelect: onBack
2446
+ }
2447
+ ) })
2448
+ ] });
2449
+ }
2450
+ return /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", children: /* @__PURE__ */ jsx9(
2451
+ SimpleSelect,
2452
+ {
2453
+ message: "Select IDEs to install/update MCP config:",
2454
+ items,
2455
+ isMulti: true,
2456
+ onSubmit: handleInstall,
2457
+ onSelect: () => {
2458
+ },
2459
+ onCancel: onBack
2460
+ }
2461
+ ) });
2462
+ };
2463
+ }
2464
+ });
2465
+
2268
2466
  // src/mcp/ui/App.tsx
2269
2467
  var App_exports = {};
2270
2468
  __export(App_exports, {
2271
2469
  App: () => App
2272
2470
  });
2273
- import { useState, useEffect as useEffect2 } from "react";
2274
- import { useInput, useApp } from "ink";
2471
+ import { useState as useState4, useEffect as useEffect3 } from "react";
2472
+ import { useInput as useInput2, useApp } from "ink";
2275
2473
  import fs11 from "fs";
2276
- import { jsx as jsx7 } from "react/jsx-runtime";
2474
+ import { jsx as jsx10 } from "react/jsx-runtime";
2277
2475
  var App;
2278
2476
  var init_App = __esm({
2279
2477
  "src/mcp/ui/App.tsx"() {
@@ -2283,15 +2481,18 @@ var init_App = __esm({
2283
2481
  init_detection();
2284
2482
  init_logger();
2285
2483
  init_server();
2286
- App = ({ onExit, onConfigure, onInstall, initialPort }) => {
2484
+ init_ConfigModal();
2485
+ init_InstallModal();
2486
+ App = ({ onExit, initialPort }) => {
2287
2487
  const { exit } = useApp();
2288
- const [logs, setLogs] = useState([]);
2289
- const [serverInfo, setServerInfo] = useState({
2488
+ const [view, setView] = useState4("dashboard");
2489
+ const [logs, setLogs] = useState4([]);
2490
+ const [serverInfo, setServerInfo] = useState4({
2290
2491
  port: initialPort,
2291
2492
  pid: process.pid,
2292
2493
  running: false
2293
2494
  });
2294
- const [showHelp2, setShowHelp] = useState(false);
2495
+ const [showHelp2, setShowHelp] = useState4(false);
2295
2496
  const config = loadMCPConfig();
2296
2497
  const projects = scanForProjects();
2297
2498
  const exposedProjects = projects.filter((p) => {
@@ -2302,7 +2503,7 @@ var init_App = __esm({
2302
2503
  });
2303
2504
  const exposedNames = exposedProjects.map((p) => p.name).slice(0, 5);
2304
2505
  const exposedLabel = exposedNames.length > 0 ? exposedNames.join(", ") + (exposedProjects.length > 5 ? ` (+${exposedProjects.length - 5} more)` : "") : "(none)";
2305
- useEffect2(() => {
2506
+ useEffect3(() => {
2306
2507
  const start = async () => {
2307
2508
  const status = getMCPServerStatus();
2308
2509
  if (!status.running) {
@@ -2320,7 +2521,7 @@ var init_App = __esm({
2320
2521
  return () => {
2321
2522
  };
2322
2523
  }, []);
2323
- useEffect2(() => {
2524
+ useEffect3(() => {
2324
2525
  const logPath = getLogFilePath();
2325
2526
  let lastSize = 0;
2326
2527
  if (fs11.existsSync(logPath)) {
@@ -2347,21 +2548,17 @@ var init_App = __esm({
2347
2548
  }, 500);
2348
2549
  return () => clearInterval(interval);
2349
2550
  }, []);
2350
- useInput((input, key) => {
2551
+ useInput2((input, key) => {
2351
2552
  if (input === "q" || key.ctrl && input === "c") {
2352
2553
  stopMCPServer();
2353
2554
  onExit();
2354
2555
  exit();
2355
2556
  }
2356
2557
  if (input === "p") {
2357
- setLogs((prev) => [...prev, "Switching to configuration wizard..."]);
2358
- onConfigure();
2359
- exit();
2558
+ setView("config");
2360
2559
  }
2361
2560
  if (input === "i") {
2362
- setLogs((prev) => [...prev, "Switching to install wizard..."]);
2363
- onInstall();
2364
- exit();
2561
+ setView("install");
2365
2562
  }
2366
2563
  if (input === "c") {
2367
2564
  setLogs([]);
@@ -2375,7 +2572,13 @@ var init_App = __esm({
2375
2572
  }, { isActive: true });
2376
2573
  const termHeight = process.stdout.rows || 24;
2377
2574
  const logHeight = Math.max(5, termHeight - 12);
2378
- return /* @__PURE__ */ jsx7(
2575
+ if (view === "config") {
2576
+ return /* @__PURE__ */ jsx10(ConfigModal, { onBack: () => setView("dashboard") });
2577
+ }
2578
+ if (view === "install") {
2579
+ return /* @__PURE__ */ jsx10(InstallModal, { onBack: () => setView("dashboard") });
2580
+ }
2581
+ return /* @__PURE__ */ jsx10(
2379
2582
  Dashboard,
2380
2583
  {
2381
2584
  logs,
@@ -2394,7 +2597,7 @@ var init_App = __esm({
2394
2597
  // src/mcp/commands/start.ts
2395
2598
  import { confirm, isCancel as isCancel4, text } from "@clack/prompts";
2396
2599
  async function handleStartServer() {
2397
- const React8 = await import("react");
2600
+ const React11 = await import("react");
2398
2601
  const { render } = await import("ink");
2399
2602
  const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
2400
2603
  const config = loadMCPConfig();
@@ -2434,38 +2637,16 @@ async function handleStartServer() {
2434
2637
  initialPort = newPort;
2435
2638
  }
2436
2639
  }
2437
- console.clear();
2438
- let keepRunning = true;
2439
- while (keepRunning) {
2440
- let nextAction = "exit";
2441
- process.stdin.resume();
2442
- const app = render(React8.createElement(App2, {
2443
- initialPort,
2444
- onExit: () => {
2445
- nextAction = "exit";
2446
- },
2447
- onConfigure: () => {
2448
- nextAction = "configure";
2449
- },
2450
- onInstall: () => {
2451
- nextAction = "install";
2452
- }
2453
- }), {
2454
- exitOnCtrlC: false
2455
- // We handle this in App
2456
- });
2457
- await app.waitUntilExit();
2458
- if (nextAction === "exit") {
2459
- keepRunning = false;
2460
- } else if (nextAction === "configure") {
2461
- console.clear();
2462
- await handleConfigure();
2463
- } else if (nextAction === "install") {
2464
- console.clear();
2465
- const workspacePath = detectWorkspaceRoot();
2466
- await runInstallWizard(workspacePath);
2640
+ process.stdin.resume();
2641
+ const app = render(React11.createElement(App2, {
2642
+ initialPort,
2643
+ onExit: () => {
2467
2644
  }
2468
- }
2645
+ }), {
2646
+ exitOnCtrlC: false
2647
+ });
2648
+ await app.waitUntilExit();
2649
+ console.clear();
2469
2650
  }
2470
2651
  var init_start = __esm({
2471
2652
  "src/mcp/commands/start.ts"() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.38",
3
+ "version": "0.2.39",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",