rrce-workflow 0.2.47 → 0.2.48

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 -27
  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);
@@ -3349,6 +3374,22 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
3349
3374
  process.exit(1);
3350
3375
  }
3351
3376
  }
3377
+ if (config.storageMode === "global") {
3378
+ const targetGlobalPath = path14.join(customGlobalPath || getDefaultRRCEHome(), "workspaces", workspaceName);
3379
+ if (fs14.existsSync(targetGlobalPath)) {
3380
+ const overwriteAction = await select2({
3381
+ message: `Project '${workspaceName}' already exists globally.`,
3382
+ options: [
3383
+ { value: "overwrite", label: "Overwrite existing project", hint: "Will replace global config" },
3384
+ { value: "cancel", label: "Cancel setup" }
3385
+ ]
3386
+ });
3387
+ if (isCancel6(overwriteAction) || overwriteAction === "cancel") {
3388
+ cancel2("Setup cancelled.");
3389
+ process.exit(0);
3390
+ }
3391
+ }
3392
+ }
3352
3393
  s.start("Generating configuration");
3353
3394
  try {
3354
3395
  await generateConfiguration({
@@ -3850,26 +3891,103 @@ var init_update_flow = __esm({
3850
3891
  }
3851
3892
  });
3852
3893
 
3894
+ // src/commands/wizard/delete-flow.ts
3895
+ import { multiselect as multiselect5, confirm as confirm8, spinner as spinner7, note as note11, cancel as cancel6, isCancel as isCancel10 } from "@clack/prompts";
3896
+ import pc12 from "picocolors";
3897
+ import * as fs18 from "fs";
3898
+ async function runDeleteGlobalProjectFlow(availableProjects) {
3899
+ const globalProjects = availableProjects.filter((p) => p.source === "global");
3900
+ if (globalProjects.length === 0) {
3901
+ note11("No globally stored projects found to delete.", "Info");
3902
+ return;
3903
+ }
3904
+ const selectedProjects = await multiselect5({
3905
+ message: "Select global projects to DELETE (Irreversible)",
3906
+ options: globalProjects.map((p) => ({
3907
+ value: p.name,
3908
+ label: p.name,
3909
+ hint: p.dataPath
3910
+ })),
3911
+ required: false
3912
+ });
3913
+ if (isCancel10(selectedProjects)) {
3914
+ cancel6("Deletion cancelled.");
3915
+ return;
3916
+ }
3917
+ const projectsToDelete = selectedProjects;
3918
+ if (projectsToDelete.length === 0) {
3919
+ note11("No projects selected.", "Cancelled");
3920
+ return;
3921
+ }
3922
+ const confirmed = await confirm8({
3923
+ message: `${pc12.red("WARNING:")} This will PERMANENTLY DELETE the knowledge/config for ${projectsToDelete.length} detected global projects.
3924
+ Are you sure?`,
3925
+ initialValue: false
3926
+ });
3927
+ if (!confirmed || isCancel10(confirmed)) {
3928
+ cancel6("Deletion cancelled.");
3929
+ return;
3930
+ }
3931
+ const s = spinner7();
3932
+ s.start("Deleting projects...");
3933
+ try {
3934
+ const mcpConfig = loadMCPConfig();
3935
+ let configChanged = false;
3936
+ for (const projectName of projectsToDelete) {
3937
+ const project = globalProjects.find((p) => p.name === projectName);
3938
+ if (!project) continue;
3939
+ if (fs18.existsSync(project.dataPath)) {
3940
+ fs18.rmSync(project.dataPath, { recursive: true, force: true });
3941
+ }
3942
+ const newConfig = removeProjectConfig(mcpConfig, projectName);
3943
+ configChanged = true;
3944
+ }
3945
+ if (configChanged) {
3946
+ saveMCPConfig(mcpConfig);
3947
+ }
3948
+ s.stop(`Successfully deleted ${projectsToDelete.length} projects.`);
3949
+ await new Promise((r) => setTimeout(r, 1e3));
3950
+ } catch (error) {
3951
+ s.stop("Error occurred during deletion");
3952
+ note11(`Failed to delete some projects: ${error}`, "Error");
3953
+ }
3954
+ }
3955
+ var init_delete_flow = __esm({
3956
+ "src/commands/wizard/delete-flow.ts"() {
3957
+ "use strict";
3958
+ init_detection();
3959
+ init_config();
3960
+ }
3961
+ });
3962
+
3853
3963
  // src/commands/wizard/index.ts
3854
3964
  var wizard_exports = {};
3855
3965
  __export(wizard_exports, {
3856
3966
  runWizard: () => runWizard
3857
3967
  });
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";
3968
+ import { intro as intro2, select as select4, spinner as spinner8, note as note12, outro as outro7, isCancel as isCancel11 } from "@clack/prompts";
3969
+ import pc13 from "picocolors";
3970
+ import * as fs19 from "fs";
3861
3971
  async function runWizard() {
3862
- intro2(pc12.cyan(pc12.inverse(" RRCE-Workflow Setup ")));
3863
- const s = spinner7();
3972
+ intro2(pc13.cyan(pc13.inverse(" RRCE-Workflow Setup ")));
3973
+ const s = spinner8();
3864
3974
  s.start("Detecting environment");
3865
3975
  const workspacePath = detectWorkspaceRoot();
3866
3976
  const workspaceName = getWorkspaceName(workspacePath);
3867
3977
  const gitUser = getGitUser();
3978
+ try {
3979
+ const mcpConfig = loadMCPConfig();
3980
+ const { config: cleanConfig, removed } = cleanStaleProjects(mcpConfig);
3981
+ if (removed.length > 0) {
3982
+ saveMCPConfig(cleanConfig);
3983
+ }
3984
+ } catch (e) {
3985
+ }
3868
3986
  await new Promise((r) => setTimeout(r, 800));
3869
3987
  s.stop("Environment detected");
3870
- note11(
3871
- `Git User: ${pc12.bold(gitUser || "(not found)")}
3872
- Workspace: ${pc12.bold(workspaceName)}`,
3988
+ note12(
3989
+ `Git User: ${pc13.bold(gitUser || "(not found)")}
3990
+ Workspace: ${pc13.bold(workspaceName)}`,
3873
3991
  "Context"
3874
3992
  );
3875
3993
  const detectedProjects = scanForProjects({
@@ -3877,18 +3995,18 @@ Workspace: ${pc12.bold(workspaceName)}`,
3877
3995
  workspacePath
3878
3996
  });
3879
3997
  const configFilePath = getConfigPath(workspacePath);
3880
- const isAlreadyConfigured = fs18.existsSync(configFilePath);
3998
+ const isAlreadyConfigured = fs19.existsSync(configFilePath);
3881
3999
  let currentStorageMode = null;
3882
4000
  if (isAlreadyConfigured) {
3883
4001
  try {
3884
- const configContent = fs18.readFileSync(configFilePath, "utf-8");
4002
+ const configContent = fs19.readFileSync(configFilePath, "utf-8");
3885
4003
  const modeMatch = configContent.match(/mode:\s*(global|workspace)/);
3886
4004
  currentStorageMode = modeMatch?.[1] ?? null;
3887
4005
  } catch {
3888
4006
  }
3889
4007
  }
3890
4008
  const localDataPath = getLocalWorkspacePath(workspacePath);
3891
- const hasLocalData = fs18.existsSync(localDataPath);
4009
+ const hasLocalData = fs19.existsSync(localDataPath);
3892
4010
  if (isAlreadyConfigured) {
3893
4011
  const menuOptions = [];
3894
4012
  menuOptions.push({
@@ -3896,6 +4014,13 @@ Workspace: ${pc12.bold(workspaceName)}`,
3896
4014
  label: "\u{1F50C} Configure MCP Server",
3897
4015
  hint: "Expose projects to AI assistants (VSCode, Antigravity, Claude)"
3898
4016
  });
4017
+ if (detectedProjects.some((p) => p.source === "global")) {
4018
+ menuOptions.push({
4019
+ value: "delete-global",
4020
+ label: "\u{1F5D1}\uFE0F Delete global project(s)",
4021
+ hint: "Remove knowledge and configuration"
4022
+ });
4023
+ }
3899
4024
  if (detectedProjects.length > 0) {
3900
4025
  menuOptions.push({
3901
4026
  value: "link",
@@ -3913,18 +4038,22 @@ Workspace: ${pc12.bold(workspaceName)}`,
3913
4038
  menuOptions.push({ value: "update", label: "\u{1F4E6} Update from package", hint: "Get latest prompts & templates" });
3914
4039
  menuOptions.push({ value: "reconfigure", label: "\u{1F527} Reconfigure project", hint: "Change storage mode, tools, etc." });
3915
4040
  menuOptions.push({ value: "exit", label: "\u21A9 Exit" });
3916
- const action = await select3({
4041
+ const action = await select4({
3917
4042
  message: "This workspace is already configured. What would you like to do?",
3918
4043
  options: menuOptions
3919
4044
  });
3920
- if (isCancel10(action) || action === "exit") {
3921
- outro6("Exited.");
4045
+ if (isCancel11(action) || action === "exit") {
4046
+ outro7("Exited.");
3922
4047
  process.exit(0);
3923
4048
  }
3924
4049
  if (action === "mcp") {
3925
4050
  await runMCP();
3926
4051
  return;
3927
4052
  }
4053
+ if (action === "delete-global") {
4054
+ await runDeleteGlobalProjectFlow(detectedProjects);
4055
+ return;
4056
+ }
3928
4057
  if (action === "link") {
3929
4058
  await runLinkProjectsFlow(workspacePath, workspaceName);
3930
4059
  return;
@@ -3952,7 +4081,9 @@ var init_wizard = __esm({
3952
4081
  init_link_flow();
3953
4082
  init_sync_flow();
3954
4083
  init_update_flow();
4084
+ init_delete_flow();
3955
4085
  init_mcp();
4086
+ init_config();
3956
4087
  }
3957
4088
  });
3958
4089
 
@@ -3961,18 +4092,18 @@ init_wizard();
3961
4092
 
3962
4093
  // src/commands/selector.ts
3963
4094
  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";
4095
+ import { intro as intro3, select as select5, note as note13, cancel as cancel8, isCancel as isCancel12, outro as outro8 } from "@clack/prompts";
4096
+ import pc14 from "picocolors";
3966
4097
  import * as path17 from "path";
3967
4098
  async function runSelector() {
3968
4099
  const workspaceName = path17.basename(process.cwd());
3969
- intro3(pc13.cyan(pc13.inverse(` RRCE-Workflow | ${workspaceName} `)));
4100
+ intro3(pc14.cyan(pc14.inverse(` RRCE-Workflow | ${workspaceName} `)));
3970
4101
  const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
3971
4102
  if (prompts.length === 0) {
3972
- cancel7("No agents found. Run `rrce-workflow` to set up.");
4103
+ cancel8("No agents found. Run `rrce-workflow` to set up.");
3973
4104
  process.exit(0);
3974
4105
  }
3975
- const selection = await select4({
4106
+ const selection = await select5({
3976
4107
  message: "Select an agent:",
3977
4108
  options: [
3978
4109
  {
@@ -3992,8 +4123,8 @@ async function runSelector() {
3992
4123
  }))
3993
4124
  ]
3994
4125
  });
3995
- if (isCancel11(selection)) {
3996
- cancel7("Selection cancelled.");
4126
+ if (isCancel12(selection)) {
4127
+ cancel8("Selection cancelled.");
3997
4128
  process.exit(0);
3998
4129
  }
3999
4130
  if (selection === "mcp") {
@@ -4007,12 +4138,12 @@ async function runSelector() {
4007
4138
  return;
4008
4139
  }
4009
4140
  const prompt = selection;
4010
- note12(
4141
+ note13(
4011
4142
  `Use this agent in your IDE by invoking:
4012
- ${pc13.bold(pc13.cyan(`@${prompt.frontmatter.name}`))}`,
4143
+ ${pc14.bold(pc14.cyan(`@${prompt.frontmatter.name}`))}`,
4013
4144
  "Agent Selected"
4014
4145
  );
4015
- outro7("Done");
4146
+ outro8("Done");
4016
4147
  }
4017
4148
 
4018
4149
  // 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.48",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",