rrce-workflow 0.2.47 → 0.2.49

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 +191 -48
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -847,6 +847,7 @@ var init_types = __esm({
847
847
  // src/mcp/config.ts
848
848
  var config_exports = {};
849
849
  __export(config_exports, {
850
+ cleanStaleProjects: () => cleanStaleProjects,
850
851
  ensureMCPGlobalPath: () => ensureMCPGlobalPath,
851
852
  getMCPConfigPath: () => getMCPConfigPath,
852
853
  getProjectPermissions: () => getProjectPermissions,
@@ -1123,6 +1124,30 @@ function getProjectPermissions(config, name, projectPath) {
1123
1124
  });
1124
1125
  return project?.permissions ?? config.defaults.permissions;
1125
1126
  }
1127
+ function cleanStaleProjects(config) {
1128
+ const rrceHome = getEffectiveRRCEHome();
1129
+ const globalWorkspacesDir = path9.join(rrceHome, "workspaces");
1130
+ const validProjects = [];
1131
+ const removed = [];
1132
+ for (const project of config.projects) {
1133
+ let exists = false;
1134
+ if (project.path) {
1135
+ exists = fs8.existsSync(project.path);
1136
+ } else {
1137
+ const globalPath = path9.join(globalWorkspacesDir, project.name);
1138
+ exists = fs8.existsSync(globalPath);
1139
+ }
1140
+ if (exists) {
1141
+ validProjects.push(project);
1142
+ } else {
1143
+ removed.push(project.name);
1144
+ }
1145
+ }
1146
+ if (removed.length > 0) {
1147
+ config.projects = validProjects;
1148
+ }
1149
+ return { config, removed };
1150
+ }
1126
1151
  var init_config = __esm({
1127
1152
  "src/mcp/config.ts"() {
1128
1153
  "use strict";
@@ -2349,7 +2374,7 @@ Hidden projects: ${projects.length - exposedCount}`,
2349
2374
  }
2350
2375
  async function handleConfigureGlobalPath() {
2351
2376
  const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
2352
- const fs19 = await import("fs");
2377
+ const fs20 = await import("fs");
2353
2378
  const path18 = await import("path");
2354
2379
  note2(
2355
2380
  `MCP Hub requires a ${pc3.bold("global storage path")} to store its configuration
@@ -2364,8 +2389,8 @@ locally in each project. MCP needs a central location.`,
2364
2389
  return false;
2365
2390
  }
2366
2391
  try {
2367
- if (!fs19.existsSync(resolvedPath)) {
2368
- fs19.mkdirSync(resolvedPath, { recursive: true });
2392
+ if (!fs20.existsSync(resolvedPath)) {
2393
+ fs20.mkdirSync(resolvedPath, { recursive: true });
2369
2394
  }
2370
2395
  const config = loadMCPConfig();
2371
2396
  saveMCPConfig(config);
@@ -3286,6 +3311,10 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
3286
3311
  ],
3287
3312
  required: false
3288
3313
  }),
3314
+ exposeToMCP: () => confirm4({
3315
+ message: "Expose this project to MCP (AI Agent) server?",
3316
+ initialValue: true
3317
+ }),
3289
3318
  linkedProjects: () => {
3290
3319
  if (existingProjects.length === 0) {
3291
3320
  return Promise.resolve([]);
@@ -3311,14 +3340,9 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
3311
3340
  message: "Create configuration?",
3312
3341
  initialValue: true
3313
3342
  }),
3314
- exposeToMCP: () => confirm4({
3315
- message: "Expose this project to MCP (AI Agent) server?",
3316
- initialValue: true
3317
- }),
3318
3343
  enableRAG: () => confirm4({
3319
3344
  message: "Enable Semantic Search (Local Mini RAG)?",
3320
- initialValue: false
3321
- // Default false because it's heavy
3345
+ initialValue: true
3322
3346
  }),
3323
3347
  enableRAGConfirm: ({ results }) => {
3324
3348
  if (results.enableRAG) {
@@ -3349,6 +3373,22 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
3349
3373
  process.exit(1);
3350
3374
  }
3351
3375
  }
3376
+ if (config.storageMode === "global") {
3377
+ const targetGlobalPath = path14.join(customGlobalPath || getDefaultRRCEHome(), "workspaces", workspaceName);
3378
+ if (fs14.existsSync(targetGlobalPath)) {
3379
+ const overwriteAction = await select2({
3380
+ message: `Project '${workspaceName}' already exists globally.`,
3381
+ options: [
3382
+ { value: "overwrite", label: "Overwrite existing project", hint: "Will replace global config" },
3383
+ { value: "cancel", label: "Cancel setup" }
3384
+ ]
3385
+ });
3386
+ if (isCancel6(overwriteAction) || overwriteAction === "cancel") {
3387
+ cancel2("Setup cancelled.");
3388
+ process.exit(0);
3389
+ }
3390
+ }
3391
+ }
3352
3392
  s.start("Generating configuration");
3353
3393
  try {
3354
3394
  await generateConfiguration({
@@ -3441,18 +3481,19 @@ async function generateConfiguration(config, workspacePath, workspaceName, allPr
3441
3481
  copyPromptsToDir(prompts, antigravityPath, ".md");
3442
3482
  }
3443
3483
  }
3444
- const workspaceConfigPath = path14.join(workspacePath, ".rrce-workflow", "config.yaml");
3445
- ensureDir(path14.dirname(workspaceConfigPath));
3446
- let configContent = `# RRCE-Workflow Configuration
3484
+ if (config.storageMode === "workspace") {
3485
+ const workspaceConfigPath = path14.join(workspacePath, ".rrce-workflow", "config.yaml");
3486
+ ensureDir(path14.dirname(workspaceConfigPath));
3487
+ let configContent = `# RRCE-Workflow Configuration
3447
3488
  version: 1
3448
3489
 
3449
3490
  storage:
3450
3491
  mode: ${config.storageMode}`;
3451
- if (config.globalPath && config.globalPath !== getDefaultRRCEHome()) {
3452
- configContent += `
3492
+ if (config.globalPath && config.globalPath !== getDefaultRRCEHome()) {
3493
+ configContent += `
3453
3494
  globalPath: "${config.globalPath}"`;
3454
- }
3455
- configContent += `
3495
+ }
3496
+ configContent += `
3456
3497
 
3457
3498
  project:
3458
3499
  name: "${workspaceName}"
@@ -3461,16 +3502,17 @@ tools:
3461
3502
  copilot: ${config.tools.includes("copilot")}
3462
3503
  antigravity: ${config.tools.includes("antigravity")}
3463
3504
  `;
3464
- if (config.linkedProjects.length > 0) {
3465
- configContent += `
3505
+ if (config.linkedProjects.length > 0) {
3506
+ configContent += `
3466
3507
  linked_projects:
3467
3508
  `;
3468
- config.linkedProjects.forEach((name) => {
3469
- configContent += ` - ${name}
3509
+ config.linkedProjects.forEach((name) => {
3510
+ configContent += ` - ${name}
3470
3511
  `;
3471
- });
3512
+ });
3513
+ }
3514
+ fs14.writeFileSync(workspaceConfigPath, configContent);
3472
3515
  }
3473
- fs14.writeFileSync(workspaceConfigPath, configContent);
3474
3516
  if (config.addToGitignore) {
3475
3517
  updateGitignore(workspacePath, config.storageMode, config.tools);
3476
3518
  }
@@ -3499,6 +3541,7 @@ linked_projects:
3499
3541
  // semanticSearch
3500
3542
  );
3501
3543
  saveMCPConfig2(mcpConfig);
3544
+ saveMCPConfig2(mcpConfig);
3502
3545
  } else {
3503
3546
  setProjectConfig2(
3504
3547
  mcpConfig,
@@ -3506,8 +3549,8 @@ linked_projects:
3506
3549
  true,
3507
3550
  void 0,
3508
3551
  // permissions
3509
- void 0,
3510
- // path
3552
+ workspacePath,
3553
+ // <--- IMPORTANT: Register absolute path so config scanner finds it
3511
3554
  config.enableRAG ? { enabled: true } : void 0
3512
3555
  // semanticSearch
3513
3556
  );
@@ -3850,26 +3893,103 @@ var init_update_flow = __esm({
3850
3893
  }
3851
3894
  });
3852
3895
 
3896
+ // src/commands/wizard/delete-flow.ts
3897
+ import { multiselect as multiselect5, confirm as confirm8, spinner as spinner7, note as note11, cancel as cancel6, isCancel as isCancel10 } from "@clack/prompts";
3898
+ import pc12 from "picocolors";
3899
+ import * as fs18 from "fs";
3900
+ async function runDeleteGlobalProjectFlow(availableProjects) {
3901
+ const globalProjects = availableProjects.filter((p) => p.source === "global");
3902
+ if (globalProjects.length === 0) {
3903
+ note11("No globally stored projects found to delete.", "Info");
3904
+ return;
3905
+ }
3906
+ const selectedProjects = await multiselect5({
3907
+ message: "Select global projects to DELETE (Irreversible)",
3908
+ options: globalProjects.map((p) => ({
3909
+ value: p.name,
3910
+ label: p.name,
3911
+ hint: p.dataPath
3912
+ })),
3913
+ required: false
3914
+ });
3915
+ if (isCancel10(selectedProjects)) {
3916
+ cancel6("Deletion cancelled.");
3917
+ return;
3918
+ }
3919
+ const projectsToDelete = selectedProjects;
3920
+ if (projectsToDelete.length === 0) {
3921
+ note11("No projects selected.", "Cancelled");
3922
+ return;
3923
+ }
3924
+ const confirmed = await confirm8({
3925
+ message: `${pc12.red("WARNING:")} This will PERMANENTLY DELETE the knowledge/config for ${projectsToDelete.length} detected global projects.
3926
+ Are you sure?`,
3927
+ initialValue: false
3928
+ });
3929
+ if (!confirmed || isCancel10(confirmed)) {
3930
+ cancel6("Deletion cancelled.");
3931
+ return;
3932
+ }
3933
+ const s = spinner7();
3934
+ s.start("Deleting projects...");
3935
+ try {
3936
+ const mcpConfig = loadMCPConfig();
3937
+ let configChanged = false;
3938
+ for (const projectName of projectsToDelete) {
3939
+ const project = globalProjects.find((p) => p.name === projectName);
3940
+ if (!project) continue;
3941
+ if (fs18.existsSync(project.dataPath)) {
3942
+ fs18.rmSync(project.dataPath, { recursive: true, force: true });
3943
+ }
3944
+ const newConfig = removeProjectConfig(mcpConfig, projectName);
3945
+ configChanged = true;
3946
+ }
3947
+ if (configChanged) {
3948
+ saveMCPConfig(mcpConfig);
3949
+ }
3950
+ s.stop(`Successfully deleted ${projectsToDelete.length} projects.`);
3951
+ await new Promise((r) => setTimeout(r, 1e3));
3952
+ } catch (error) {
3953
+ s.stop("Error occurred during deletion");
3954
+ note11(`Failed to delete some projects: ${error}`, "Error");
3955
+ }
3956
+ }
3957
+ var init_delete_flow = __esm({
3958
+ "src/commands/wizard/delete-flow.ts"() {
3959
+ "use strict";
3960
+ init_detection();
3961
+ init_config();
3962
+ }
3963
+ });
3964
+
3853
3965
  // src/commands/wizard/index.ts
3854
3966
  var wizard_exports = {};
3855
3967
  __export(wizard_exports, {
3856
3968
  runWizard: () => runWizard
3857
3969
  });
3858
- import { intro as intro2, select as select3, spinner as spinner7, note as note11, outro as outro6, isCancel as isCancel10 } from "@clack/prompts";
3859
- import pc12 from "picocolors";
3860
- import * as fs18 from "fs";
3970
+ import { intro as intro2, select as select4, spinner as spinner8, note as note12, outro as outro7, isCancel as isCancel11 } from "@clack/prompts";
3971
+ import pc13 from "picocolors";
3972
+ import * as fs19 from "fs";
3861
3973
  async function runWizard() {
3862
- intro2(pc12.cyan(pc12.inverse(" RRCE-Workflow Setup ")));
3863
- const s = spinner7();
3974
+ intro2(pc13.cyan(pc13.inverse(" RRCE-Workflow Setup ")));
3975
+ const s = spinner8();
3864
3976
  s.start("Detecting environment");
3865
3977
  const workspacePath = detectWorkspaceRoot();
3866
3978
  const workspaceName = getWorkspaceName(workspacePath);
3867
3979
  const gitUser = getGitUser();
3980
+ try {
3981
+ const mcpConfig = loadMCPConfig();
3982
+ const { config: cleanConfig, removed } = cleanStaleProjects(mcpConfig);
3983
+ if (removed.length > 0) {
3984
+ saveMCPConfig(cleanConfig);
3985
+ }
3986
+ } catch (e) {
3987
+ }
3868
3988
  await new Promise((r) => setTimeout(r, 800));
3869
3989
  s.stop("Environment detected");
3870
- note11(
3871
- `Git User: ${pc12.bold(gitUser || "(not found)")}
3872
- Workspace: ${pc12.bold(workspaceName)}`,
3990
+ note12(
3991
+ `Git User: ${pc13.bold(gitUser || "(not found)")}
3992
+ Workspace: ${pc13.bold(workspaceName)}`,
3873
3993
  "Context"
3874
3994
  );
3875
3995
  const detectedProjects = scanForProjects({
@@ -3877,18 +3997,28 @@ Workspace: ${pc12.bold(workspaceName)}`,
3877
3997
  workspacePath
3878
3998
  });
3879
3999
  const configFilePath = getConfigPath(workspacePath);
3880
- const isAlreadyConfigured = fs18.existsSync(configFilePath);
4000
+ let isAlreadyConfigured = fs19.existsSync(configFilePath);
3881
4001
  let currentStorageMode = null;
3882
4002
  if (isAlreadyConfigured) {
3883
4003
  try {
3884
- const configContent = fs18.readFileSync(configFilePath, "utf-8");
4004
+ const configContent = fs19.readFileSync(configFilePath, "utf-8");
3885
4005
  const modeMatch = configContent.match(/mode:\s*(global|workspace)/);
3886
4006
  currentStorageMode = modeMatch?.[1] ?? null;
3887
4007
  } catch {
3888
4008
  }
4009
+ } else {
4010
+ try {
4011
+ const mcpConfig = loadMCPConfig();
4012
+ const mcpProject = mcpConfig.projects.find((p) => p.path === workspacePath);
4013
+ if (mcpProject) {
4014
+ isAlreadyConfigured = true;
4015
+ currentStorageMode = "global";
4016
+ }
4017
+ } catch (e) {
4018
+ }
3889
4019
  }
3890
4020
  const localDataPath = getLocalWorkspacePath(workspacePath);
3891
- const hasLocalData = fs18.existsSync(localDataPath);
4021
+ const hasLocalData = fs19.existsSync(localDataPath);
3892
4022
  if (isAlreadyConfigured) {
3893
4023
  const menuOptions = [];
3894
4024
  menuOptions.push({
@@ -3896,6 +4026,13 @@ Workspace: ${pc12.bold(workspaceName)}`,
3896
4026
  label: "\u{1F50C} Configure MCP Server",
3897
4027
  hint: "Expose projects to AI assistants (VSCode, Antigravity, Claude)"
3898
4028
  });
4029
+ if (detectedProjects.some((p) => p.source === "global")) {
4030
+ menuOptions.push({
4031
+ value: "delete-global",
4032
+ label: "\u{1F5D1}\uFE0F Delete global project(s)",
4033
+ hint: "Remove knowledge and configuration"
4034
+ });
4035
+ }
3899
4036
  if (detectedProjects.length > 0) {
3900
4037
  menuOptions.push({
3901
4038
  value: "link",
@@ -3913,18 +4050,22 @@ Workspace: ${pc12.bold(workspaceName)}`,
3913
4050
  menuOptions.push({ value: "update", label: "\u{1F4E6} Update from package", hint: "Get latest prompts & templates" });
3914
4051
  menuOptions.push({ value: "reconfigure", label: "\u{1F527} Reconfigure project", hint: "Change storage mode, tools, etc." });
3915
4052
  menuOptions.push({ value: "exit", label: "\u21A9 Exit" });
3916
- const action = await select3({
4053
+ const action = await select4({
3917
4054
  message: "This workspace is already configured. What would you like to do?",
3918
4055
  options: menuOptions
3919
4056
  });
3920
- if (isCancel10(action) || action === "exit") {
3921
- outro6("Exited.");
4057
+ if (isCancel11(action) || action === "exit") {
4058
+ outro7("Exited.");
3922
4059
  process.exit(0);
3923
4060
  }
3924
4061
  if (action === "mcp") {
3925
4062
  await runMCP();
3926
4063
  return;
3927
4064
  }
4065
+ if (action === "delete-global") {
4066
+ await runDeleteGlobalProjectFlow(detectedProjects);
4067
+ return;
4068
+ }
3928
4069
  if (action === "link") {
3929
4070
  await runLinkProjectsFlow(workspacePath, workspaceName);
3930
4071
  return;
@@ -3952,7 +4093,9 @@ var init_wizard = __esm({
3952
4093
  init_link_flow();
3953
4094
  init_sync_flow();
3954
4095
  init_update_flow();
4096
+ init_delete_flow();
3955
4097
  init_mcp();
4098
+ init_config();
3956
4099
  }
3957
4100
  });
3958
4101
 
@@ -3961,18 +4104,18 @@ init_wizard();
3961
4104
 
3962
4105
  // src/commands/selector.ts
3963
4106
  init_prompts();
3964
- import { intro as intro3, select as select4, note as note12, cancel as cancel7, isCancel as isCancel11, outro as outro7 } from "@clack/prompts";
3965
- import pc13 from "picocolors";
4107
+ import { intro as intro3, select as select5, note as note13, cancel as cancel8, isCancel as isCancel12, outro as outro8 } from "@clack/prompts";
4108
+ import pc14 from "picocolors";
3966
4109
  import * as path17 from "path";
3967
4110
  async function runSelector() {
3968
4111
  const workspaceName = path17.basename(process.cwd());
3969
- intro3(pc13.cyan(pc13.inverse(` RRCE-Workflow | ${workspaceName} `)));
4112
+ intro3(pc14.cyan(pc14.inverse(` RRCE-Workflow | ${workspaceName} `)));
3970
4113
  const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
3971
4114
  if (prompts.length === 0) {
3972
- cancel7("No agents found. Run `rrce-workflow` to set up.");
4115
+ cancel8("No agents found. Run `rrce-workflow` to set up.");
3973
4116
  process.exit(0);
3974
4117
  }
3975
- const selection = await select4({
4118
+ const selection = await select5({
3976
4119
  message: "Select an agent:",
3977
4120
  options: [
3978
4121
  {
@@ -3992,8 +4135,8 @@ async function runSelector() {
3992
4135
  }))
3993
4136
  ]
3994
4137
  });
3995
- if (isCancel11(selection)) {
3996
- cancel7("Selection cancelled.");
4138
+ if (isCancel12(selection)) {
4139
+ cancel8("Selection cancelled.");
3997
4140
  process.exit(0);
3998
4141
  }
3999
4142
  if (selection === "mcp") {
@@ -4007,12 +4150,12 @@ async function runSelector() {
4007
4150
  return;
4008
4151
  }
4009
4152
  const prompt = selection;
4010
- note12(
4153
+ note13(
4011
4154
  `Use this agent in your IDE by invoking:
4012
- ${pc13.bold(pc13.cyan(`@${prompt.frontmatter.name}`))}`,
4155
+ ${pc14.bold(pc14.cyan(`@${prompt.frontmatter.name}`))}`,
4013
4156
  "Agent Selected"
4014
4157
  );
4015
- outro7("Done");
4158
+ outro8("Done");
4016
4159
  }
4017
4160
 
4018
4161
  // src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.47",
3
+ "version": "0.2.49",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",