rrce-workflow 0.3.0 → 0.3.2

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 +1096 -799
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -574,9 +574,97 @@ var init_detection_service = __esm({
574
574
  }
575
575
  });
576
576
 
577
- // src/lib/autocomplete-prompt.ts
577
+ // src/types/prompt.ts
578
+ import { z } from "zod";
579
+ var PromptArgSchema, AutoIdentitySchema, PromptFrontmatterSchema;
580
+ var init_prompt = __esm({
581
+ "src/types/prompt.ts"() {
582
+ "use strict";
583
+ PromptArgSchema = z.object({
584
+ name: z.string(),
585
+ default: z.string().optional(),
586
+ prompt: z.string().optional()
587
+ });
588
+ AutoIdentitySchema = z.object({
589
+ user: z.string(),
590
+ model: z.string()
591
+ });
592
+ PromptFrontmatterSchema = z.object({
593
+ name: z.string(),
594
+ description: z.string(),
595
+ "argument-hint": z.union([z.string(), z.array(z.string())]).optional(),
596
+ tools: z.array(z.string()).optional(),
597
+ mode: z.enum(["primary", "subagent"]).optional(),
598
+ "required-args": z.array(PromptArgSchema).optional(),
599
+ "optional-args": z.array(PromptArgSchema).optional(),
600
+ "auto-identity": AutoIdentitySchema.optional()
601
+ });
602
+ }
603
+ });
604
+
605
+ // src/lib/prompts.ts
578
606
  import * as fs4 from "fs";
579
607
  import * as path4 from "path";
608
+ import { fileURLToPath } from "url";
609
+ import matter from "gray-matter";
610
+ function parsePromptFile(filePath) {
611
+ try {
612
+ const fileContent = fs4.readFileSync(filePath, "utf-8");
613
+ const { data, content } = matter(fileContent);
614
+ const parsed = PromptFrontmatterSchema.safeParse(data);
615
+ if (!parsed.success) {
616
+ console.error(`Failed to parse frontmatter in ${filePath}:`, parsed.error);
617
+ return null;
618
+ }
619
+ return {
620
+ frontmatter: parsed.data,
621
+ content: content.trim(),
622
+ filePath
623
+ };
624
+ } catch (error) {
625
+ console.error(`Error reading prompt file ${filePath}:`, error);
626
+ return null;
627
+ }
628
+ }
629
+ function loadPromptsFromDir(dirPath) {
630
+ if (!fs4.existsSync(dirPath)) {
631
+ return [];
632
+ }
633
+ const files = fs4.readdirSync(dirPath).filter((f) => f.endsWith(".md"));
634
+ const prompts = [];
635
+ for (const file of files) {
636
+ const prompt = parsePromptFile(path4.join(dirPath, file));
637
+ if (prompt) {
638
+ prompts.push(prompt);
639
+ }
640
+ }
641
+ return prompts;
642
+ }
643
+ function getAgentCoreDir() {
644
+ if (__dirname.includes("/src/") || __dirname.includes("\\src\\")) {
645
+ if (fs4.existsSync(path4.join(process.cwd(), "agent-core"))) {
646
+ return path4.join(process.cwd(), "agent-core");
647
+ }
648
+ return path4.resolve(__dirname, "../..", "agent-core");
649
+ }
650
+ return path4.join(__dirname, "..", "agent-core");
651
+ }
652
+ function getAgentCorePromptsDir() {
653
+ return path4.join(getAgentCoreDir(), "prompts");
654
+ }
655
+ var __filename, __dirname;
656
+ var init_prompts = __esm({
657
+ "src/lib/prompts.ts"() {
658
+ "use strict";
659
+ init_prompt();
660
+ __filename = fileURLToPath(import.meta.url);
661
+ __dirname = path4.dirname(__filename);
662
+ }
663
+ });
664
+
665
+ // src/lib/autocomplete-prompt.ts
666
+ import * as fs5 from "fs";
667
+ import * as path5 from "path";
580
668
  import * as readline from "readline";
581
669
  import pc from "picocolors";
582
670
  function directoryPrompt(opts) {
@@ -635,19 +723,19 @@ function completeDirectory(line) {
635
723
  prefix = "";
636
724
  basePath = expanded;
637
725
  } else {
638
- dirToScan = path4.dirname(expanded);
639
- prefix = path4.basename(expanded).toLowerCase();
726
+ dirToScan = path5.dirname(expanded);
727
+ prefix = path5.basename(expanded).toLowerCase();
640
728
  basePath = dirToScan === "/" ? "/" : dirToScan + "/";
641
729
  }
642
- if (!fs4.existsSync(dirToScan)) {
730
+ if (!fs5.existsSync(dirToScan)) {
643
731
  return [[], line];
644
732
  }
645
- const entries = fs4.readdirSync(dirToScan, { withFileTypes: true }).filter((entry) => {
733
+ const entries = fs5.readdirSync(dirToScan, { withFileTypes: true }).filter((entry) => {
646
734
  if (!entry.isDirectory()) return false;
647
735
  if (entry.name.startsWith(".") && !prefix.startsWith(".")) return false;
648
736
  return prefix === "" || entry.name.toLowerCase().startsWith(prefix);
649
737
  }).map((entry) => {
650
- const fullPath = path4.join(dirToScan, entry.name);
738
+ const fullPath = path5.join(dirToScan, entry.name);
651
739
  const displayPath = fullPath.startsWith(process.env.HOME || "") ? fullPath.replace(process.env.HOME || "", "~") : fullPath;
652
740
  return displayPath + "/";
653
741
  }).sort();
@@ -693,7 +781,7 @@ __export(tui_utils_exports, {
693
781
  });
694
782
  import { select, note, isCancel } from "@clack/prompts";
695
783
  import pc2 from "picocolors";
696
- import * as path5 from "path";
784
+ import * as path6 from "path";
697
785
  async function resolveGlobalPath() {
698
786
  const prefs = loadUserPreferences();
699
787
  const defaultPath = prefs.defaultGlobalPath || getDefaultRRCEHome2();
@@ -732,7 +820,7 @@ Please choose a custom path instead.`,
732
820
  }
733
821
  return defaultPath;
734
822
  }
735
- const suggestedPath = path5.join(process.env.HOME || "~", ".rrce-workflow");
823
+ const suggestedPath = path6.join(process.env.HOME || "~", ".rrce-workflow");
736
824
  const customPath = await directoryPrompt({
737
825
  message: "Enter custom global path (Tab to autocomplete):",
738
826
  defaultValue: suggestedPath,
@@ -751,7 +839,7 @@ Please choose a custom path instead.`,
751
839
  }
752
840
  let expandedPath = customPath;
753
841
  if (!expandedPath.endsWith(".rrce-workflow")) {
754
- expandedPath = path5.join(expandedPath, ".rrce-workflow");
842
+ expandedPath = path6.join(expandedPath, ".rrce-workflow");
755
843
  }
756
844
  saveUserPreferences({ defaultGlobalPath: expandedPath, useCustomGlobalPath: true });
757
845
  return expandedPath;
@@ -766,8 +854,8 @@ var init_tui_utils = __esm({
766
854
  });
767
855
 
768
856
  // src/mcp/install.ts
769
- import * as fs5 from "fs";
770
- import * as path6 from "path";
857
+ import * as fs6 from "fs";
858
+ import * as path7 from "path";
771
859
  import * as os from "os";
772
860
  function checkInstallStatus(workspacePath) {
773
861
  return {
@@ -779,46 +867,46 @@ function checkInstallStatus(workspacePath) {
779
867
  };
780
868
  }
781
869
  function checkAntigravityConfig() {
782
- if (!fs5.existsSync(ANTIGRAVITY_CONFIG)) return false;
870
+ if (!fs6.existsSync(ANTIGRAVITY_CONFIG)) return false;
783
871
  try {
784
- const content = JSON.parse(fs5.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
872
+ const content = JSON.parse(fs6.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
785
873
  return !!content.mcpServers?.["rrce"];
786
874
  } catch {
787
875
  return false;
788
876
  }
789
877
  }
790
878
  function checkClaudeConfig() {
791
- if (!fs5.existsSync(CLAUDE_CONFIG)) return false;
879
+ if (!fs6.existsSync(CLAUDE_CONFIG)) return false;
792
880
  try {
793
- const content = JSON.parse(fs5.readFileSync(CLAUDE_CONFIG, "utf-8"));
881
+ const content = JSON.parse(fs6.readFileSync(CLAUDE_CONFIG, "utf-8"));
794
882
  return !!content.mcpServers?.["rrce"];
795
883
  } catch {
796
884
  return false;
797
885
  }
798
886
  }
799
887
  function checkVSCodeGlobalConfig() {
800
- if (!fs5.existsSync(VSCODE_GLOBAL_CONFIG)) return false;
888
+ if (!fs6.existsSync(VSCODE_GLOBAL_CONFIG)) return false;
801
889
  try {
802
- const content = JSON.parse(fs5.readFileSync(VSCODE_GLOBAL_CONFIG, "utf-8"));
890
+ const content = JSON.parse(fs6.readFileSync(VSCODE_GLOBAL_CONFIG, "utf-8"));
803
891
  return !!content["mcp.servers"]?.["rrce"];
804
892
  } catch {
805
893
  return false;
806
894
  }
807
895
  }
808
896
  function checkVSCodeWorkspaceConfig(workspacePath) {
809
- const configPath = path6.join(workspacePath, ".vscode", "mcp.json");
810
- if (!fs5.existsSync(configPath)) return false;
897
+ const configPath = path7.join(workspacePath, ".vscode", "mcp.json");
898
+ if (!fs6.existsSync(configPath)) return false;
811
899
  try {
812
- const content = JSON.parse(fs5.readFileSync(configPath, "utf-8"));
900
+ const content = JSON.parse(fs6.readFileSync(configPath, "utf-8"));
813
901
  return !!content.servers?.["rrce"];
814
902
  } catch {
815
903
  return false;
816
904
  }
817
905
  }
818
906
  function checkOpenCodeConfig() {
819
- if (!fs5.existsSync(OPENCODE_CONFIG)) return false;
907
+ if (!fs6.existsSync(OPENCODE_CONFIG)) return false;
820
908
  try {
821
- const content = JSON.parse(fs5.readFileSync(OPENCODE_CONFIG, "utf-8"));
909
+ const content = JSON.parse(fs6.readFileSync(OPENCODE_CONFIG, "utf-8"));
822
910
  return !!content.mcp?.["rrce"];
823
911
  } catch {
824
912
  return false;
@@ -845,14 +933,14 @@ function installToConfig(target, workspacePath) {
845
933
  }
846
934
  }
847
935
  function installToAntigravity() {
848
- const dir = path6.dirname(ANTIGRAVITY_CONFIG);
849
- if (!fs5.existsSync(dir)) {
850
- fs5.mkdirSync(dir, { recursive: true });
936
+ const dir = path7.dirname(ANTIGRAVITY_CONFIG);
937
+ if (!fs6.existsSync(dir)) {
938
+ fs6.mkdirSync(dir, { recursive: true });
851
939
  }
852
940
  let config = { mcpServers: {} };
853
- if (fs5.existsSync(ANTIGRAVITY_CONFIG)) {
941
+ if (fs6.existsSync(ANTIGRAVITY_CONFIG)) {
854
942
  try {
855
- config = JSON.parse(fs5.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
943
+ config = JSON.parse(fs6.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
856
944
  } catch {
857
945
  }
858
946
  }
@@ -862,21 +950,21 @@ function installToAntigravity() {
862
950
  args: ["-y", "rrce-workflow", "mcp", "start"]
863
951
  };
864
952
  try {
865
- fs5.writeFileSync(ANTIGRAVITY_CONFIG, JSON.stringify(config, null, 2));
953
+ fs6.writeFileSync(ANTIGRAVITY_CONFIG, JSON.stringify(config, null, 2));
866
954
  return true;
867
955
  } catch {
868
956
  return false;
869
957
  }
870
958
  }
871
959
  function installToClaude() {
872
- const dir = path6.dirname(CLAUDE_CONFIG);
873
- if (!fs5.existsSync(dir)) {
874
- fs5.mkdirSync(dir, { recursive: true });
960
+ const dir = path7.dirname(CLAUDE_CONFIG);
961
+ if (!fs6.existsSync(dir)) {
962
+ fs6.mkdirSync(dir, { recursive: true });
875
963
  }
876
964
  let config = { mcpServers: {} };
877
- if (fs5.existsSync(CLAUDE_CONFIG)) {
965
+ if (fs6.existsSync(CLAUDE_CONFIG)) {
878
966
  try {
879
- config = JSON.parse(fs5.readFileSync(CLAUDE_CONFIG, "utf-8"));
967
+ config = JSON.parse(fs6.readFileSync(CLAUDE_CONFIG, "utf-8"));
880
968
  } catch {
881
969
  }
882
970
  }
@@ -886,21 +974,21 @@ function installToClaude() {
886
974
  args: ["-y", "rrce-workflow", "mcp", "start"]
887
975
  };
888
976
  try {
889
- fs5.writeFileSync(CLAUDE_CONFIG, JSON.stringify(config, null, 2));
977
+ fs6.writeFileSync(CLAUDE_CONFIG, JSON.stringify(config, null, 2));
890
978
  return true;
891
979
  } catch {
892
980
  return false;
893
981
  }
894
982
  }
895
983
  function installToVSCodeGlobal() {
896
- const dir = path6.dirname(VSCODE_GLOBAL_CONFIG);
897
- if (!fs5.existsSync(dir)) {
898
- fs5.mkdirSync(dir, { recursive: true });
984
+ const dir = path7.dirname(VSCODE_GLOBAL_CONFIG);
985
+ if (!fs6.existsSync(dir)) {
986
+ fs6.mkdirSync(dir, { recursive: true });
899
987
  }
900
988
  let settings = {};
901
- if (fs5.existsSync(VSCODE_GLOBAL_CONFIG)) {
989
+ if (fs6.existsSync(VSCODE_GLOBAL_CONFIG)) {
902
990
  try {
903
- settings = JSON.parse(fs5.readFileSync(VSCODE_GLOBAL_CONFIG, "utf-8"));
991
+ settings = JSON.parse(fs6.readFileSync(VSCODE_GLOBAL_CONFIG, "utf-8"));
904
992
  } catch {
905
993
  }
906
994
  }
@@ -910,22 +998,22 @@ function installToVSCodeGlobal() {
910
998
  args: ["-y", "rrce-workflow", "mcp", "start"]
911
999
  };
912
1000
  try {
913
- fs5.writeFileSync(VSCODE_GLOBAL_CONFIG, JSON.stringify(settings, null, 2));
1001
+ fs6.writeFileSync(VSCODE_GLOBAL_CONFIG, JSON.stringify(settings, null, 2));
914
1002
  return true;
915
1003
  } catch {
916
1004
  return false;
917
1005
  }
918
1006
  }
919
1007
  function installToVSCodeWorkspace(workspacePath) {
920
- const vscodeDir = path6.join(workspacePath, ".vscode");
921
- const configPath = path6.join(vscodeDir, "mcp.json");
922
- if (!fs5.existsSync(vscodeDir)) {
923
- fs5.mkdirSync(vscodeDir, { recursive: true });
1008
+ const vscodeDir = path7.join(workspacePath, ".vscode");
1009
+ const configPath = path7.join(vscodeDir, "mcp.json");
1010
+ if (!fs6.existsSync(vscodeDir)) {
1011
+ fs6.mkdirSync(vscodeDir, { recursive: true });
924
1012
  }
925
1013
  let config = { servers: {} };
926
- if (fs5.existsSync(configPath)) {
1014
+ if (fs6.existsSync(configPath)) {
927
1015
  try {
928
- config = JSON.parse(fs5.readFileSync(configPath, "utf-8"));
1016
+ config = JSON.parse(fs6.readFileSync(configPath, "utf-8"));
929
1017
  } catch {
930
1018
  }
931
1019
  }
@@ -935,23 +1023,23 @@ function installToVSCodeWorkspace(workspacePath) {
935
1023
  args: ["-y", "rrce-workflow", "mcp", "start"]
936
1024
  };
937
1025
  try {
938
- fs5.writeFileSync(configPath, JSON.stringify(config, null, 2));
1026
+ fs6.writeFileSync(configPath, JSON.stringify(config, null, 2));
939
1027
  return true;
940
1028
  } catch {
941
1029
  return false;
942
1030
  }
943
1031
  }
944
1032
  function installToOpenCode() {
945
- const dir = path6.dirname(OPENCODE_CONFIG);
946
- if (!fs5.existsSync(dir)) {
947
- fs5.mkdirSync(dir, { recursive: true });
1033
+ const dir = path7.dirname(OPENCODE_CONFIG);
1034
+ if (!fs6.existsSync(dir)) {
1035
+ fs6.mkdirSync(dir, { recursive: true });
948
1036
  }
949
1037
  let config = {
950
1038
  $schema: "https://opencode.ai/config.json"
951
1039
  };
952
- if (fs5.existsSync(OPENCODE_CONFIG)) {
1040
+ if (fs6.existsSync(OPENCODE_CONFIG)) {
953
1041
  try {
954
- config = JSON.parse(fs5.readFileSync(OPENCODE_CONFIG, "utf-8"));
1042
+ config = JSON.parse(fs6.readFileSync(OPENCODE_CONFIG, "utf-8"));
955
1043
  } catch (error) {
956
1044
  console.error("Warning: Could not parse existing OpenCode config, creating fresh config");
957
1045
  }
@@ -963,7 +1051,7 @@ function installToOpenCode() {
963
1051
  enabled: true
964
1052
  };
965
1053
  try {
966
- fs5.writeFileSync(OPENCODE_CONFIG, JSON.stringify(config, null, 2) + "\n");
1054
+ fs6.writeFileSync(OPENCODE_CONFIG, JSON.stringify(config, null, 2) + "\n");
967
1055
  return true;
968
1056
  } catch (error) {
969
1057
  console.error("Failed to write OpenCode config:", error instanceof Error ? error.message : String(error));
@@ -987,115 +1075,170 @@ function getTargetLabel(target) {
987
1075
  }
988
1076
  }
989
1077
  function isOpenCodeInstalled() {
990
- const configDir = path6.join(os.homedir(), ".config/opencode");
991
- const configFile = path6.join(configDir, "opencode.json");
992
- return fs5.existsSync(configDir) || fs5.existsSync(configFile);
1078
+ const configDir = path7.join(os.homedir(), ".config/opencode");
1079
+ const configFile = path7.join(configDir, "opencode.json");
1080
+ return fs6.existsSync(configDir) || fs6.existsSync(configFile);
993
1081
  }
994
1082
  function isAntigravityInstalled() {
995
- const configDir = path6.join(os.homedir(), ".gemini/antigravity");
996
- return fs5.existsSync(configDir);
1083
+ const configDir = path7.join(os.homedir(), ".gemini/antigravity");
1084
+ return fs6.existsSync(configDir);
997
1085
  }
998
1086
  function isVSCodeInstalled() {
999
- const configDir = path6.join(os.homedir(), ".config/Code/User");
1000
- return fs5.existsSync(configDir);
1087
+ const configDir = path7.join(os.homedir(), ".config/Code/User");
1088
+ return fs6.existsSync(configDir);
1001
1089
  }
1002
1090
  var ANTIGRAVITY_CONFIG, CLAUDE_CONFIG, VSCODE_GLOBAL_CONFIG, OPENCODE_CONFIG_DIR, OPENCODE_CONFIG;
1003
1091
  var init_install = __esm({
1004
1092
  "src/mcp/install.ts"() {
1005
1093
  "use strict";
1006
- ANTIGRAVITY_CONFIG = path6.join(os.homedir(), ".gemini/antigravity/mcp_config.json");
1007
- CLAUDE_CONFIG = path6.join(os.homedir(), ".config/claude/claude_desktop_config.json");
1008
- VSCODE_GLOBAL_CONFIG = path6.join(os.homedir(), ".config/Code/User/settings.json");
1009
- OPENCODE_CONFIG_DIR = path6.join(os.homedir(), ".config/opencode");
1010
- OPENCODE_CONFIG = path6.join(OPENCODE_CONFIG_DIR, "opencode.json");
1094
+ ANTIGRAVITY_CONFIG = path7.join(os.homedir(), ".gemini/antigravity/mcp_config.json");
1095
+ CLAUDE_CONFIG = path7.join(os.homedir(), ".config/claude/claude_desktop_config.json");
1096
+ VSCODE_GLOBAL_CONFIG = path7.join(os.homedir(), ".config/Code/User/settings.json");
1097
+ OPENCODE_CONFIG_DIR = path7.join(os.homedir(), ".config/opencode");
1098
+ OPENCODE_CONFIG = path7.join(OPENCODE_CONFIG_DIR, "opencode.json");
1011
1099
  }
1012
1100
  });
1013
1101
 
1014
- // src/types/prompt.ts
1015
- import { z } from "zod";
1016
- var PromptArgSchema, AutoIdentitySchema, PromptFrontmatterSchema;
1017
- var init_prompt = __esm({
1018
- "src/types/prompt.ts"() {
1019
- "use strict";
1020
- PromptArgSchema = z.object({
1021
- name: z.string(),
1022
- default: z.string().optional(),
1023
- prompt: z.string().optional()
1024
- });
1025
- AutoIdentitySchema = z.object({
1026
- user: z.string(),
1027
- model: z.string()
1028
- });
1029
- PromptFrontmatterSchema = z.object({
1030
- name: z.string(),
1031
- description: z.string(),
1032
- "argument-hint": z.union([z.string(), z.array(z.string())]).optional(),
1033
- tools: z.array(z.string()).optional(),
1034
- mode: z.enum(["primary", "subagent"]).optional(),
1035
- "required-args": z.array(PromptArgSchema).optional(),
1036
- "optional-args": z.array(PromptArgSchema).optional(),
1037
- "auto-identity": AutoIdentitySchema.optional()
1038
- });
1102
+ // src/commands/wizard/utils.ts
1103
+ import * as fs7 from "fs";
1104
+ import * as path8 from "path";
1105
+ import * as os2 from "os";
1106
+ import { stringify } from "yaml";
1107
+ function getOpenCodeConfigPath() {
1108
+ return path8.join(os2.homedir(), ".config", "opencode", "opencode.json");
1109
+ }
1110
+ function copyPromptsToDir(prompts, targetDir, extension) {
1111
+ for (const prompt of prompts) {
1112
+ const baseName = path8.basename(prompt.filePath, ".md");
1113
+ const targetName = baseName + extension;
1114
+ const targetPath = path8.join(targetDir, targetName);
1115
+ const content = fs7.readFileSync(prompt.filePath, "utf-8");
1116
+ fs7.writeFileSync(targetPath, content);
1117
+ }
1118
+ }
1119
+ function updateOpenCodeConfig(newAgents) {
1120
+ const opencodePath = path8.join(os2.homedir(), ".config", "opencode", "opencode.json");
1121
+ if (!fs7.existsSync(opencodePath)) {
1122
+ return;
1039
1123
  }
1040
- });
1041
-
1042
- // src/lib/prompts.ts
1043
- import * as fs6 from "fs";
1044
- import * as path7 from "path";
1045
- import { fileURLToPath } from "url";
1046
- import matter from "gray-matter";
1047
- function parsePromptFile(filePath) {
1048
1124
  try {
1049
- const fileContent = fs6.readFileSync(filePath, "utf-8");
1050
- const { data, content } = matter(fileContent);
1051
- const parsed = PromptFrontmatterSchema.safeParse(data);
1052
- if (!parsed.success) {
1053
- console.error(`Failed to parse frontmatter in ${filePath}:`, parsed.error);
1054
- return null;
1125
+ const config = JSON.parse(fs7.readFileSync(opencodePath, "utf8"));
1126
+ if (!config.agents) {
1127
+ config.agents = {};
1055
1128
  }
1056
- return {
1057
- frontmatter: parsed.data,
1058
- content: content.trim(),
1059
- filePath
1060
- };
1061
- } catch (error) {
1062
- console.error(`Error reading prompt file ${filePath}:`, error);
1063
- return null;
1129
+ const existingAgentKeys = Object.keys(config.agents);
1130
+ const rrceKeys = existingAgentKeys.filter((key) => key.startsWith("rrce_"));
1131
+ for (const key of rrceKeys) {
1132
+ if (!newAgents[key]) {
1133
+ delete config.agents[key];
1134
+ }
1135
+ }
1136
+ for (const [key, value] of Object.entries(newAgents)) {
1137
+ if (key.startsWith("rrce_")) {
1138
+ config.agents[key] = value;
1139
+ }
1140
+ }
1141
+ fs7.writeFileSync(opencodePath, JSON.stringify(config, null, 2));
1142
+ } catch (e) {
1143
+ console.error("Failed to update OpenCode config:", e);
1064
1144
  }
1065
1145
  }
1066
- function loadPromptsFromDir(dirPath) {
1067
- if (!fs6.existsSync(dirPath)) {
1068
- return [];
1146
+ function convertToOpenCodeAgent(prompt, useFileReference = false, promptFilePath) {
1147
+ const { frontmatter, content } = prompt;
1148
+ const tools = {};
1149
+ const hostTools = ["read", "write", "edit", "bash", "grep", "glob", "webfetch", "terminalLastCommand", "task"];
1150
+ if (frontmatter.tools) {
1151
+ for (const tool of frontmatter.tools) {
1152
+ if (hostTools.includes(tool)) {
1153
+ tools[tool] = true;
1154
+ } else {
1155
+ tools[`rrce_${tool}`] = true;
1156
+ }
1157
+ }
1069
1158
  }
1070
- const files = fs6.readdirSync(dirPath).filter((f) => f.endsWith(".md"));
1071
- const prompts = [];
1072
- for (const file of files) {
1073
- const prompt = parsePromptFile(path7.join(dirPath, file));
1074
- if (prompt) {
1075
- prompts.push(prompt);
1159
+ tools["webfetch"] = true;
1160
+ const mode = frontmatter.mode || "subagent";
1161
+ const invocationHint = mode === "primary" ? "" : " (Invoke via @rrce_*)";
1162
+ return {
1163
+ description: `${frontmatter.description}${invocationHint}`,
1164
+ mode,
1165
+ prompt: useFileReference && promptFilePath ? `{file:${promptFilePath}}` : content,
1166
+ tools
1167
+ };
1168
+ }
1169
+ function copyDirRecursive(src, dest) {
1170
+ const entries = fs7.readdirSync(src, { withFileTypes: true });
1171
+ for (const entry of entries) {
1172
+ const srcPath = path8.join(src, entry.name);
1173
+ const destPath = path8.join(dest, entry.name);
1174
+ if (entry.isDirectory()) {
1175
+ ensureDir(destPath);
1176
+ copyDirRecursive(srcPath, destPath);
1177
+ } else {
1178
+ fs7.copyFileSync(srcPath, destPath);
1076
1179
  }
1077
1180
  }
1078
- return prompts;
1079
1181
  }
1080
- function getAgentCoreDir() {
1081
- if (__dirname.includes("/src/") || __dirname.includes("\\src\\")) {
1082
- if (fs6.existsSync(path7.join(process.cwd(), "agent-core"))) {
1083
- return path7.join(process.cwd(), "agent-core");
1182
+ function clearDirectory(dirPath) {
1183
+ if (!fs7.existsSync(dirPath)) return;
1184
+ const entries = fs7.readdirSync(dirPath, { withFileTypes: true });
1185
+ for (const entry of entries) {
1186
+ if (entry.isFile()) {
1187
+ fs7.unlinkSync(path8.join(dirPath, entry.name));
1084
1188
  }
1085
- return path7.resolve(__dirname, "../..", "agent-core");
1086
1189
  }
1087
- return path7.join(__dirname, "..", "agent-core");
1088
1190
  }
1089
- function getAgentCorePromptsDir() {
1090
- return path7.join(getAgentCoreDir(), "prompts");
1191
+ function surgicalUpdateOpenCodeAgents(prompts, mode, dataPath) {
1192
+ if (mode === "global") {
1193
+ try {
1194
+ const openCodeConfig = getOpenCodeConfigPath();
1195
+ const promptsDir = path8.join(path8.dirname(openCodeConfig), "prompts");
1196
+ ensureDir(promptsDir);
1197
+ const newAgents = {};
1198
+ for (const prompt of prompts) {
1199
+ const baseName = path8.basename(prompt.filePath, ".md");
1200
+ const agentId = `rrce_${baseName}`;
1201
+ const promptFileName = `rrce-${baseName}.md`;
1202
+ const promptFilePath = path8.join(promptsDir, promptFileName);
1203
+ fs7.writeFileSync(promptFilePath, prompt.content);
1204
+ const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
1205
+ newAgents[agentId] = agentConfig;
1206
+ }
1207
+ updateOpenCodeConfig(newAgents);
1208
+ if (fs7.existsSync(openCodeConfig)) {
1209
+ const config = JSON.parse(fs7.readFileSync(openCodeConfig, "utf8"));
1210
+ if (!config.agents) config.agents = {};
1211
+ if (!config.agents.plan) config.agents.plan = {};
1212
+ config.agents.plan.disable = true;
1213
+ fs7.writeFileSync(openCodeConfig, JSON.stringify(config, null, 2));
1214
+ }
1215
+ } catch (e) {
1216
+ console.error("Failed to update global OpenCode config with agents:", e);
1217
+ throw e;
1218
+ }
1219
+ } else {
1220
+ const opencodeBaseDir = path8.join(dataPath, ".opencode", "agent");
1221
+ ensureDir(opencodeBaseDir);
1222
+ clearDirectory(opencodeBaseDir);
1223
+ for (const prompt of prompts) {
1224
+ const baseName = path8.basename(prompt.filePath, ".md");
1225
+ const agentId = `rrce_${baseName}`;
1226
+ const agentConfig = convertToOpenCodeAgent(prompt);
1227
+ const content = `---
1228
+ ${stringify({
1229
+ description: agentConfig.description,
1230
+ mode: agentConfig.mode,
1231
+ tools: agentConfig.tools
1232
+ })}---
1233
+ ${agentConfig.prompt}`;
1234
+ fs7.writeFileSync(path8.join(opencodeBaseDir, `${agentId}.md`), content);
1235
+ }
1236
+ }
1091
1237
  }
1092
- var __filename, __dirname;
1093
- var init_prompts = __esm({
1094
- "src/lib/prompts.ts"() {
1238
+ var init_utils = __esm({
1239
+ "src/commands/wizard/utils.ts"() {
1095
1240
  "use strict";
1096
- init_prompt();
1097
- __filename = fileURLToPath(import.meta.url);
1098
- __dirname = path7.dirname(__filename);
1241
+ init_paths();
1099
1242
  }
1100
1243
  });
1101
1244
 
@@ -3872,7 +4015,7 @@ Hidden projects: ${projects.length - exposedCount}`,
3872
4015
  async function handleConfigureGlobalPath() {
3873
4016
  const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
3874
4017
  const fs26 = await import("fs");
3875
- const path24 = await import("path");
4018
+ const path25 = await import("path");
3876
4019
  note3(
3877
4020
  `MCP Hub requires a ${pc5.bold("global storage path")} to store its configuration
3878
4021
  and coordinate across projects.
@@ -3895,7 +4038,7 @@ locally in each project. MCP needs a central location.`,
3895
4038
  `${pc5.green("\u2713")} Global path configured: ${pc5.cyan(resolvedPath)}
3896
4039
 
3897
4040
  MCP config will be stored at:
3898
- ${path24.join(resolvedPath, "mcp.yaml")}`,
4041
+ ${path25.join(resolvedPath, "mcp.yaml")}`,
3899
4042
  "Configuration Saved"
3900
4043
  );
3901
4044
  return true;
@@ -5364,12 +5507,359 @@ var init_mcp = __esm({
5364
5507
  }
5365
5508
  });
5366
5509
 
5367
- // src/commands/wizard/index.ts
5368
- import { intro as intro2, select as select5, spinner as spinner7, note as note11, outro as outro7, isCancel as isCancel12 } from "@clack/prompts";
5369
- import pc13 from "picocolors";
5370
- import * as fs25 from "fs";
5371
-
5372
- // src/lib/git.ts
5510
+ // src/commands/wizard/update-flow.ts
5511
+ var update_flow_exports = {};
5512
+ __export(update_flow_exports, {
5513
+ runSilentUpdate: () => runSilentUpdate,
5514
+ runUpdateFlow: () => runUpdateFlow
5515
+ });
5516
+ import { confirm as confirm5, spinner as spinner2, note as note6, outro as outro2, cancel as cancel2, isCancel as isCancel7 } from "@clack/prompts";
5517
+ import pc8 from "picocolors";
5518
+ import * as fs21 from "fs";
5519
+ import * as path22 from "path";
5520
+ import { stringify as stringify2, parse } from "yaml";
5521
+ function backupFile(filePath) {
5522
+ if (!fs21.existsSync(filePath)) return null;
5523
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").split("T")[0] + "-" + Date.now();
5524
+ const backupPath = `${filePath}.${timestamp}.bak`;
5525
+ try {
5526
+ fs21.copyFileSync(filePath, backupPath);
5527
+ return backupPath;
5528
+ } catch (e) {
5529
+ console.error(`Failed to backup ${filePath}:`, e);
5530
+ return null;
5531
+ }
5532
+ }
5533
+ function getPackageVersion2() {
5534
+ try {
5535
+ const agentCoreDir = getAgentCoreDir();
5536
+ const packageJsonPath = path22.join(path22.dirname(agentCoreDir), "package.json");
5537
+ if (fs21.existsSync(packageJsonPath)) {
5538
+ return JSON.parse(fs21.readFileSync(packageJsonPath, "utf8")).version;
5539
+ }
5540
+ } catch (e) {
5541
+ }
5542
+ return "0.0.0";
5543
+ }
5544
+ async function performUpdate(workspacePath, workspaceName, currentStorageMode, options = {}) {
5545
+ const agentCoreDir = getAgentCoreDir();
5546
+ const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
5547
+ const runningVersion = getPackageVersion2();
5548
+ const mode = currentStorageMode || "global";
5549
+ const customGlobalPath = getEffectiveRRCEHome(workspacePath);
5550
+ const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
5551
+ const configFilePath = getConfigPath(workspacePath);
5552
+ let currentSyncedVersion;
5553
+ if (fs21.existsSync(configFilePath)) {
5554
+ try {
5555
+ const content = fs21.readFileSync(configFilePath, "utf-8");
5556
+ const config = parse(content);
5557
+ currentSyncedVersion = config.last_synced_version;
5558
+ } catch (e) {
5559
+ }
5560
+ }
5561
+ const driftReport = DriftService.checkDrift(dataPaths[0], currentSyncedVersion, runningVersion);
5562
+ const ideTargets = [];
5563
+ if (fs21.existsSync(configFilePath)) {
5564
+ const configContent = fs21.readFileSync(configFilePath, "utf-8");
5565
+ if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
5566
+ if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
5567
+ if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
5568
+ }
5569
+ for (const dataPath of dataPaths) {
5570
+ const dirs = ["templates", "prompts", "docs"];
5571
+ const updatedFiles = [];
5572
+ for (const dir of dirs) {
5573
+ const srcDir = path22.join(agentCoreDir, dir);
5574
+ if (!fs21.existsSync(srcDir)) continue;
5575
+ const syncFiles = (src, rel) => {
5576
+ const entries = fs21.readdirSync(src, { withFileTypes: true });
5577
+ for (const entry of entries) {
5578
+ const entrySrc = path22.join(src, entry.name);
5579
+ const entryRel = path22.join(rel, entry.name);
5580
+ const entryDest = path22.join(dataPath, entryRel);
5581
+ if (entry.isDirectory()) {
5582
+ ensureDir(entryDest);
5583
+ syncFiles(entrySrc, entryRel);
5584
+ } else {
5585
+ if (driftReport.modifiedFiles.includes(entryRel)) {
5586
+ backupFile(entryDest);
5587
+ }
5588
+ fs21.copyFileSync(entrySrc, entryDest);
5589
+ updatedFiles.push(entryRel);
5590
+ }
5591
+ }
5592
+ };
5593
+ syncFiles(srcDir, dir);
5594
+ }
5595
+ const manifest = DriftService.generateManifest(dataPath, updatedFiles);
5596
+ DriftService.saveManifest(dataPath, manifest);
5597
+ }
5598
+ const rrceHome = customGlobalPath || getDefaultRRCEHome2();
5599
+ ensureDir(path22.join(rrceHome, "templates"));
5600
+ ensureDir(path22.join(rrceHome, "docs"));
5601
+ copyDirRecursive(path22.join(agentCoreDir, "templates"), path22.join(rrceHome, "templates"));
5602
+ copyDirRecursive(path22.join(agentCoreDir, "docs"), path22.join(rrceHome, "docs"));
5603
+ if (fs21.existsSync(configFilePath)) {
5604
+ const configContent = fs21.readFileSync(configFilePath, "utf-8");
5605
+ if (configContent.includes("copilot: true")) {
5606
+ const copilotPath = getAgentPromptPath(workspacePath, "copilot");
5607
+ ensureDir(copilotPath);
5608
+ clearDirectory(copilotPath);
5609
+ copyPromptsToDir(prompts, copilotPath, ".agent.md");
5610
+ }
5611
+ if (configContent.includes("antigravity: true")) {
5612
+ const antigravityPath = getAgentPromptPath(workspacePath, "antigravity");
5613
+ ensureDir(antigravityPath);
5614
+ clearDirectory(antigravityPath);
5615
+ copyPromptsToDir(prompts, antigravityPath, ".md");
5616
+ }
5617
+ if (configContent.includes("opencode: true")) {
5618
+ const primaryDataPath = dataPaths[0];
5619
+ if (primaryDataPath) {
5620
+ surgicalUpdateOpenCodeAgents(prompts, mode, primaryDataPath);
5621
+ }
5622
+ }
5623
+ try {
5624
+ const yaml = parse(configContent);
5625
+ yaml.last_synced_version = runningVersion;
5626
+ fs21.writeFileSync(configFilePath, stringify2(yaml));
5627
+ } catch (e) {
5628
+ console.error("Failed to update config.yaml version:", e);
5629
+ }
5630
+ }
5631
+ const mcpPath = path22.join(rrceHome, "mcp.yaml");
5632
+ if (fs21.existsSync(mcpPath)) {
5633
+ try {
5634
+ const content = fs21.readFileSync(mcpPath, "utf-8");
5635
+ const yaml = parse(content);
5636
+ if (yaml.projects) {
5637
+ const project = yaml.projects.find((p) => p.name === workspaceName);
5638
+ if (project) {
5639
+ project.last_synced_version = runningVersion;
5640
+ fs21.writeFileSync(mcpPath, stringify2(yaml));
5641
+ }
5642
+ }
5643
+ } catch (e) {
5644
+ console.error("Failed to update mcp.yaml version:", e);
5645
+ }
5646
+ }
5647
+ return {
5648
+ success: true,
5649
+ ideTargets,
5650
+ modifiedFiles: driftReport.modifiedFiles
5651
+ };
5652
+ }
5653
+ async function runSilentUpdate(workspacePath, workspaceName, currentStorageMode) {
5654
+ const s = spinner2();
5655
+ s.start("Applying updates...");
5656
+ try {
5657
+ await performUpdate(workspacePath, workspaceName, currentStorageMode, { silent: true });
5658
+ s.stop("Updates applied");
5659
+ } catch (error) {
5660
+ s.stop("Update failed");
5661
+ throw error;
5662
+ }
5663
+ }
5664
+ async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
5665
+ const s = spinner2();
5666
+ s.start("Checking for updates");
5667
+ try {
5668
+ const agentCoreDir = getAgentCoreDir();
5669
+ const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
5670
+ const runningVersion = getPackageVersion2();
5671
+ const mode = currentStorageMode || "global";
5672
+ const customGlobalPath = getEffectiveRRCEHome(workspacePath);
5673
+ const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
5674
+ const configFilePath = getConfigPath(workspacePath);
5675
+ let currentSyncedVersion;
5676
+ if (fs21.existsSync(configFilePath)) {
5677
+ try {
5678
+ const content = fs21.readFileSync(configFilePath, "utf-8");
5679
+ const config = parse(content);
5680
+ currentSyncedVersion = config.last_synced_version;
5681
+ } catch (e) {
5682
+ }
5683
+ }
5684
+ const driftReport = DriftService.checkDrift(dataPaths[0], currentSyncedVersion, runningVersion);
5685
+ s.stop("Updates found");
5686
+ if (driftReport.type === "version") {
5687
+ note6(`New version available: ${pc8.green(runningVersion)} (Current synced: ${pc8.dim(currentSyncedVersion || "None")})`, "Update Available");
5688
+ }
5689
+ if (driftReport.modifiedFiles.length > 0) {
5690
+ note6(
5691
+ pc8.yellow(`The following files have been modified and will be backed up before updating:
5692
+ `) + driftReport.modifiedFiles.map((f) => ` \u2022 ${f}`).join("\n"),
5693
+ "Modifications Detected"
5694
+ );
5695
+ }
5696
+ const updateTargets = [
5697
+ ` \u2022 prompts/ (${prompts.length} agent prompts)`,
5698
+ ` \u2022 templates/ (output templates)`,
5699
+ ` \u2022 docs/ (documentation)`
5700
+ ];
5701
+ const ideTargets = [];
5702
+ if (fs21.existsSync(configFilePath)) {
5703
+ const configContent = fs21.readFileSync(configFilePath, "utf-8");
5704
+ if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
5705
+ if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
5706
+ if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
5707
+ }
5708
+ if (ideTargets.length > 0) {
5709
+ updateTargets.push(` \u2022 IDE integrations: ${ideTargets.join(", ")}`);
5710
+ }
5711
+ note6(
5712
+ `The following will be updated from the package:
5713
+ ${updateTargets.join("\n")}
5714
+
5715
+ Target locations:
5716
+ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
5717
+ "Update Preview"
5718
+ );
5719
+ const shouldUpdate = await confirm5({
5720
+ message: "Proceed with update?",
5721
+ initialValue: true
5722
+ });
5723
+ if (isCancel7(shouldUpdate) || !shouldUpdate) {
5724
+ outro2("Update cancelled.");
5725
+ return;
5726
+ }
5727
+ s.start("Updating from package");
5728
+ for (const dataPath of dataPaths) {
5729
+ const dirs = ["templates", "prompts", "docs"];
5730
+ const updatedFiles = [];
5731
+ for (const dir of dirs) {
5732
+ const srcDir = path22.join(agentCoreDir, dir);
5733
+ if (!fs21.existsSync(srcDir)) continue;
5734
+ const syncFiles = (src, rel) => {
5735
+ const entries = fs21.readdirSync(src, { withFileTypes: true });
5736
+ for (const entry of entries) {
5737
+ const entrySrc = path22.join(src, entry.name);
5738
+ const entryRel = path22.join(rel, entry.name);
5739
+ const entryDest = path22.join(dataPath, entryRel);
5740
+ if (entry.isDirectory()) {
5741
+ ensureDir(entryDest);
5742
+ syncFiles(entrySrc, entryRel);
5743
+ } else {
5744
+ if (driftReport.modifiedFiles.includes(entryRel)) {
5745
+ backupFile(entryDest);
5746
+ }
5747
+ fs21.copyFileSync(entrySrc, entryDest);
5748
+ updatedFiles.push(entryRel);
5749
+ }
5750
+ }
5751
+ };
5752
+ syncFiles(srcDir, dir);
5753
+ }
5754
+ const manifest = DriftService.generateManifest(dataPath, updatedFiles);
5755
+ DriftService.saveManifest(dataPath, manifest);
5756
+ }
5757
+ const rrceHome = customGlobalPath || getDefaultRRCEHome2();
5758
+ ensureDir(path22.join(rrceHome, "templates"));
5759
+ ensureDir(path22.join(rrceHome, "docs"));
5760
+ copyDirRecursive(path22.join(agentCoreDir, "templates"), path22.join(rrceHome, "templates"));
5761
+ copyDirRecursive(path22.join(agentCoreDir, "docs"), path22.join(rrceHome, "docs"));
5762
+ if (fs21.existsSync(configFilePath)) {
5763
+ const configContent = fs21.readFileSync(configFilePath, "utf-8");
5764
+ if (configContent.includes("copilot: true")) {
5765
+ const copilotPath = getAgentPromptPath(workspacePath, "copilot");
5766
+ ensureDir(copilotPath);
5767
+ clearDirectory(copilotPath);
5768
+ copyPromptsToDir(prompts, copilotPath, ".agent.md");
5769
+ }
5770
+ if (configContent.includes("antigravity: true")) {
5771
+ const antigravityPath = getAgentPromptPath(workspacePath, "antigravity");
5772
+ ensureDir(antigravityPath);
5773
+ clearDirectory(antigravityPath);
5774
+ copyPromptsToDir(prompts, antigravityPath, ".md");
5775
+ }
5776
+ if (configContent.includes("opencode: true")) {
5777
+ const primaryDataPath = dataPaths[0];
5778
+ if (primaryDataPath) {
5779
+ surgicalUpdateOpenCodeAgents(prompts, mode, primaryDataPath);
5780
+ }
5781
+ }
5782
+ try {
5783
+ const yaml = parse(configContent);
5784
+ yaml.last_synced_version = runningVersion;
5785
+ fs21.writeFileSync(configFilePath, stringify2(yaml));
5786
+ } catch (e) {
5787
+ console.error("Failed to update config.yaml version:", e);
5788
+ }
5789
+ }
5790
+ const mcpPath = path22.join(rrceHome, "mcp.yaml");
5791
+ if (fs21.existsSync(mcpPath)) {
5792
+ try {
5793
+ const content = fs21.readFileSync(mcpPath, "utf-8");
5794
+ const yaml = parse(content);
5795
+ if (yaml.projects) {
5796
+ const project = yaml.projects.find((p) => p.name === workspaceName);
5797
+ if (project) {
5798
+ project.last_synced_version = runningVersion;
5799
+ fs21.writeFileSync(mcpPath, stringify2(yaml));
5800
+ }
5801
+ }
5802
+ } catch (e) {
5803
+ console.error("Failed to update mcp.yaml version:", e);
5804
+ }
5805
+ }
5806
+ s.stop("Update complete");
5807
+ const summary = [
5808
+ `Updated:`,
5809
+ ` \u2713 ${prompts.length} agent prompts`,
5810
+ ` \u2713 Output templates`,
5811
+ ` \u2713 Documentation`
5812
+ ];
5813
+ if (ideTargets.length > 0) {
5814
+ summary.push(` \u2713 IDE integrations: ${ideTargets.join(", ")}`);
5815
+ }
5816
+ if (driftReport.modifiedFiles.length > 0) {
5817
+ summary.push(` \u2713 ${driftReport.modifiedFiles.length} modified files backed up`);
5818
+ }
5819
+ summary.push(
5820
+ ``,
5821
+ `Your configuration and knowledge files were preserved.`,
5822
+ ``,
5823
+ pc8.dim(`\u{1F4A1} If using OpenCode, you may need to reload for changes to take effect.`)
5824
+ );
5825
+ note6(summary.join("\n"), "Update Summary");
5826
+ outro2(pc8.green("\u2713 Successfully updated from package!"));
5827
+ } catch (error) {
5828
+ s.stop("Error occurred");
5829
+ cancel2(`Failed to update: ${error instanceof Error ? error.message : String(error)}`);
5830
+ process.exit(1);
5831
+ }
5832
+ }
5833
+ function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
5834
+ const globalPath = path22.join(customGlobalPath, "workspaces", workspaceName);
5835
+ const workspacePath = path22.join(workspaceRoot, ".rrce-workflow");
5836
+ switch (mode) {
5837
+ case "global":
5838
+ return [globalPath];
5839
+ case "workspace":
5840
+ return [workspacePath];
5841
+ default:
5842
+ return [globalPath];
5843
+ }
5844
+ }
5845
+ var init_update_flow = __esm({
5846
+ "src/commands/wizard/update-flow.ts"() {
5847
+ "use strict";
5848
+ init_paths();
5849
+ init_prompts();
5850
+ init_utils();
5851
+ init_drift_service();
5852
+ }
5853
+ });
5854
+
5855
+ // src/commands/wizard/index.ts
5856
+ import { intro as intro2, select as select5, spinner as spinner7, note as note11, outro as outro7, isCancel as isCancel12, confirm as confirm10 } from "@clack/prompts";
5857
+ import pc13 from "picocolors";
5858
+ import * as fs25 from "fs";
5859
+ import * as path24 from "path";
5860
+ import { parse as parse2 } from "yaml";
5861
+
5862
+ // src/lib/git.ts
5373
5863
  import { execSync } from "child_process";
5374
5864
  function getGitUser() {
5375
5865
  try {
@@ -5383,13 +5873,15 @@ function getGitUser() {
5383
5873
  // src/commands/wizard/index.ts
5384
5874
  init_paths();
5385
5875
  init_detection_service();
5876
+ init_prompts();
5386
5877
 
5387
5878
  // src/commands/wizard/setup-flow.ts
5388
- import { spinner as spinner2, note as note6, outro as outro2, cancel as cancel2, isCancel as isCancel7, confirm as confirm5, select as select3 } from "@clack/prompts";
5389
- import pc8 from "picocolors";
5879
+ import { spinner as spinner3, note as note7, outro as outro3, cancel as cancel3, isCancel as isCancel8, confirm as confirm6, select as select3 } from "@clack/prompts";
5880
+ import pc9 from "picocolors";
5390
5881
  init_detection();
5391
5882
  init_tui_utils();
5392
5883
  init_install();
5884
+ init_paths();
5393
5885
 
5394
5886
  // src/commands/wizard/setup-prompts.ts
5395
5887
  init_install();
@@ -5505,108 +5997,29 @@ async function promptConfirmation() {
5505
5997
  // src/commands/wizard/setup-actions.ts
5506
5998
  init_paths();
5507
5999
  init_prompts();
6000
+ init_utils();
5508
6001
  import * as fs10 from "fs";
5509
6002
  import * as path12 from "path";
5510
6003
  import pc4 from "picocolors";
5511
6004
  import { note as note2 } from "@clack/prompts";
5512
- import { stringify as stringify2 } from "yaml";
5513
6005
 
5514
- // src/commands/wizard/utils.ts
6006
+ // src/commands/wizard/vscode.ts
5515
6007
  init_paths();
5516
- import * as fs7 from "fs";
5517
- import * as path8 from "path";
5518
- import * as os2 from "os";
5519
- import "yaml";
5520
- function copyPromptsToDir(prompts, targetDir, extension) {
5521
- for (const prompt of prompts) {
5522
- const baseName = path8.basename(prompt.filePath, ".md");
5523
- const targetName = baseName + extension;
5524
- const targetPath = path8.join(targetDir, targetName);
5525
- const content = fs7.readFileSync(prompt.filePath, "utf-8");
5526
- fs7.writeFileSync(targetPath, content);
5527
- }
5528
- }
5529
- function updateOpenCodeConfig(newAgents) {
5530
- const opencodePath = path8.join(os2.homedir(), ".config", "opencode", "opencode.json");
5531
- if (!fs7.existsSync(opencodePath)) {
5532
- return;
5533
- }
5534
- try {
5535
- const config = JSON.parse(fs7.readFileSync(opencodePath, "utf8"));
5536
- if (!config.agents) {
5537
- config.agents = {};
5538
- }
5539
- const existingAgentKeys = Object.keys(config.agents);
5540
- const rrceKeys = existingAgentKeys.filter((key) => key.startsWith("rrce_"));
5541
- for (const key of rrceKeys) {
5542
- if (!newAgents[key]) {
5543
- delete config.agents[key];
5544
- }
5545
- }
5546
- for (const [key, value] of Object.entries(newAgents)) {
5547
- if (key.startsWith("rrce_")) {
5548
- config.agents[key] = value;
5549
- }
5550
- }
5551
- fs7.writeFileSync(opencodePath, JSON.stringify(config, null, 2));
5552
- } catch (e) {
5553
- console.error("Failed to update OpenCode config:", e);
5554
- }
5555
- }
5556
- function convertToOpenCodeAgent(prompt, useFileReference = false, promptFilePath) {
5557
- const { frontmatter, content } = prompt;
5558
- const tools = {};
5559
- const hostTools = ["read", "write", "edit", "bash", "grep", "glob", "webfetch", "terminalLastCommand", "task"];
5560
- if (frontmatter.tools) {
5561
- for (const tool of frontmatter.tools) {
5562
- if (hostTools.includes(tool)) {
5563
- tools[tool] = true;
5564
- } else {
5565
- tools[`rrce_${tool}`] = true;
5566
- }
5567
- }
5568
- }
5569
- tools["webfetch"] = true;
5570
- const mode = frontmatter.mode || "subagent";
5571
- const invocationHint = mode === "primary" ? "" : " (Invoke via @rrce_*)";
5572
- return {
5573
- description: `${frontmatter.description}${invocationHint}`,
5574
- mode,
5575
- prompt: useFileReference && promptFilePath ? `{file:${promptFilePath}}` : content,
5576
- tools
5577
- };
5578
- }
5579
- function copyDirRecursive(src, dest) {
5580
- const entries = fs7.readdirSync(src, { withFileTypes: true });
5581
- for (const entry of entries) {
5582
- const srcPath = path8.join(src, entry.name);
5583
- const destPath = path8.join(dest, entry.name);
5584
- if (entry.isDirectory()) {
5585
- ensureDir(destPath);
5586
- copyDirRecursive(srcPath, destPath);
5587
- } else {
5588
- fs7.copyFileSync(srcPath, destPath);
5589
- }
5590
- }
5591
- }
5592
-
5593
- // src/commands/wizard/vscode.ts
5594
- init_paths();
5595
- init_detection();
5596
- import * as fs8 from "fs";
5597
- import * as path9 from "path";
5598
- function generateVSCodeWorkspace(workspacePath, workspaceName, linkedProjects, customGlobalPath) {
5599
- const workspaceFilePath = path9.join(workspacePath, `${workspaceName}.code-workspace`);
5600
- let workspace;
5601
- if (fs8.existsSync(workspaceFilePath)) {
5602
- try {
5603
- const content = fs8.readFileSync(workspaceFilePath, "utf-8");
5604
- workspace = JSON.parse(content);
5605
- } catch {
5606
- workspace = { folders: [], settings: {} };
5607
- }
5608
- } else {
5609
- workspace = { folders: [], settings: {} };
6008
+ init_detection();
6009
+ import * as fs8 from "fs";
6010
+ import * as path9 from "path";
6011
+ function generateVSCodeWorkspace(workspacePath, workspaceName, linkedProjects, customGlobalPath) {
6012
+ const workspaceFilePath = path9.join(workspacePath, `${workspaceName}.code-workspace`);
6013
+ let workspace;
6014
+ if (fs8.existsSync(workspaceFilePath)) {
6015
+ try {
6016
+ const content = fs8.readFileSync(workspaceFilePath, "utf-8");
6017
+ workspace = JSON.parse(content);
6018
+ } catch {
6019
+ workspace = { folders: [], settings: {} };
6020
+ }
6021
+ } else {
6022
+ workspace = { folders: [], settings: {} };
5610
6023
  }
5611
6024
  if (!workspace.settings) {
5612
6025
  workspace.settings = {};
@@ -5677,6 +6090,46 @@ function generateVSCodeWorkspace(workspacePath, workspaceName, linkedProjects, c
5677
6090
 
5678
6091
  // src/commands/wizard/setup-actions.ts
5679
6092
  init_install();
6093
+ function detectExistingProject(workspacePath, workspaceName, globalPath) {
6094
+ const rrceHome = globalPath || getDefaultRRCEHome2();
6095
+ const globalConfigPath = path12.join(rrceHome, "workspaces", workspaceName, "config.yaml");
6096
+ const workspaceConfigPath = path12.join(workspacePath, ".rrce-workflow", "config.yaml");
6097
+ const hasOpenCodeAgents = checkForRRCEAgents();
6098
+ if (fs10.existsSync(globalConfigPath)) {
6099
+ return {
6100
+ isExisting: true,
6101
+ currentMode: "global",
6102
+ configPath: globalConfigPath
6103
+ };
6104
+ } else if (fs10.existsSync(workspaceConfigPath)) {
6105
+ return {
6106
+ isExisting: true,
6107
+ currentMode: "workspace",
6108
+ configPath: workspaceConfigPath
6109
+ };
6110
+ } else if (hasOpenCodeAgents) {
6111
+ return {
6112
+ isExisting: true,
6113
+ currentMode: null,
6114
+ configPath: null
6115
+ };
6116
+ }
6117
+ return {
6118
+ isExisting: false,
6119
+ currentMode: null,
6120
+ configPath: null
6121
+ };
6122
+ }
6123
+ function checkForRRCEAgents() {
6124
+ if (!fs10.existsSync(OPENCODE_CONFIG)) return false;
6125
+ try {
6126
+ const config = JSON.parse(fs10.readFileSync(OPENCODE_CONFIG, "utf8"));
6127
+ const agentKeys = Object.keys(config.agent || config.agents || {});
6128
+ return agentKeys.some((key) => key.startsWith("rrce_"));
6129
+ } catch {
6130
+ return false;
6131
+ }
6132
+ }
5680
6133
  function createDirectoryStructure(dataPaths) {
5681
6134
  for (const dataPath of dataPaths) {
5682
6135
  ensureDir(dataPath);
@@ -5715,48 +6168,7 @@ async function installAgentPrompts(config, workspacePath, dataPaths) {
5715
6168
  if (config.tools.includes("opencode")) {
5716
6169
  const primaryDataPath = dataPaths[0];
5717
6170
  if (primaryDataPath) {
5718
- if (config.storageMode === "global") {
5719
- try {
5720
- const promptsDir = path12.join(path12.dirname(OPENCODE_CONFIG), "prompts");
5721
- ensureDir(promptsDir);
5722
- let opencodeConfig = { $schema: "https://opencode.ai/config.json" };
5723
- if (fs10.existsSync(OPENCODE_CONFIG)) {
5724
- opencodeConfig = JSON.parse(fs10.readFileSync(OPENCODE_CONFIG, "utf-8"));
5725
- }
5726
- if (!opencodeConfig.agent) opencodeConfig.agent = {};
5727
- for (const prompt of prompts) {
5728
- const baseName = path12.basename(prompt.filePath, ".md");
5729
- const agentId = `rrce_${baseName}`;
5730
- const promptFileName = `rrce-${baseName}.md`;
5731
- const promptFilePath = path12.join(promptsDir, promptFileName);
5732
- fs10.writeFileSync(promptFilePath, prompt.content);
5733
- const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
5734
- opencodeConfig.agent[agentId] = agentConfig;
5735
- }
5736
- if (!opencodeConfig.agent) opencodeConfig.agent = {};
5737
- if (!opencodeConfig.agent.plan) opencodeConfig.agent.plan = {};
5738
- opencodeConfig.agent.plan.disable = true;
5739
- fs10.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
5740
- } catch (e) {
5741
- console.error("Failed to update global OpenCode config with agents:", e);
5742
- }
5743
- } else {
5744
- const opencodeBaseDir = path12.join(primaryDataPath, ".opencode", "agent");
5745
- ensureDir(opencodeBaseDir);
5746
- for (const prompt of prompts) {
5747
- const baseName = path12.basename(prompt.filePath, ".md");
5748
- const agentId = `rrce_${baseName}`;
5749
- const agentConfig = convertToOpenCodeAgent(prompt);
5750
- const content = `---
5751
- ${stringify2({
5752
- description: agentConfig.description,
5753
- mode: agentConfig.mode,
5754
- tools: agentConfig.tools
5755
- })}---
5756
- ${agentConfig.prompt}`;
5757
- fs10.writeFileSync(path12.join(opencodeBaseDir, `${agentId}.md`), content);
5758
- }
5759
- }
6171
+ surgicalUpdateOpenCodeAgents(prompts, config.storageMode, primaryDataPath);
5760
6172
  }
5761
6173
  }
5762
6174
  }
@@ -5882,8 +6294,8 @@ async function runExpressSetup(workspacePath, workspaceName, existingProjects, s
5882
6294
  ],
5883
6295
  initialValue: "global"
5884
6296
  });
5885
- if (isCancel7(storageModeResult)) {
5886
- cancel2("Setup cancelled.");
6297
+ if (isCancel8(storageModeResult)) {
6298
+ cancel3("Setup cancelled.");
5887
6299
  process.exit(0);
5888
6300
  }
5889
6301
  const storageMode = storageModeResult;
@@ -5891,7 +6303,7 @@ async function runExpressSetup(workspacePath, workspaceName, existingProjects, s
5891
6303
  if (storageMode === "global") {
5892
6304
  customGlobalPath = await resolveGlobalPath();
5893
6305
  if (!customGlobalPath) {
5894
- cancel2("Setup cancelled - no global path selected.");
6306
+ cancel3("Setup cancelled - no global path selected.");
5895
6307
  process.exit(0);
5896
6308
  }
5897
6309
  }
@@ -5900,8 +6312,8 @@ async function runExpressSetup(workspacePath, workspaceName, existingProjects, s
5900
6312
  if (isVSCodeInstalled()) toolsPreview.push("GitHub Copilot");
5901
6313
  if (isAntigravityInstalled()) toolsPreview.push("Antigravity");
5902
6314
  const toolsText = toolsPreview.length > 0 ? toolsPreview.join(", ") : "None detected";
5903
- note6(
5904
- `${pc8.bold("Express Setup will configure:")}
6315
+ note7(
6316
+ `${pc9.bold("Express Setup will configure:")}
5905
6317
  \u2022 Storage: ${storageMode === "global" ? "Global" : "Workspace"}
5906
6318
  \u2022 MCP Server: Enabled
5907
6319
  \u2022 Semantic Search (RAG): Enabled
@@ -5909,12 +6321,12 @@ async function runExpressSetup(workspacePath, workspaceName, existingProjects, s
5909
6321
  ` : "") + `\u2022 AI Tools: ${toolsText}`,
5910
6322
  "Configuration Preview"
5911
6323
  );
5912
- const confirmed = await confirm5({
6324
+ const confirmed = await confirm6({
5913
6325
  message: "Proceed with express setup?",
5914
6326
  initialValue: true
5915
6327
  });
5916
- if (isCancel7(confirmed) || !confirmed) {
5917
- cancel2("Setup cancelled.");
6328
+ if (isCancel8(confirmed) || !confirmed) {
6329
+ cancel3("Setup cancelled.");
5918
6330
  process.exit(0);
5919
6331
  }
5920
6332
  const defaultTools = [];
@@ -5935,19 +6347,63 @@ async function runExpressSetup(workspacePath, workspaceName, existingProjects, s
5935
6347
  const { updateGitignore: updateGitignore2 } = await Promise.resolve().then(() => (init_gitignore(), gitignore_exports));
5936
6348
  updateGitignore2(workspacePath, config.storageMode, config.tools);
5937
6349
  }
5938
- const startMCP = await confirm5({
6350
+ const startMCP = await confirm6({
5939
6351
  message: "Start MCP server now?",
5940
6352
  initialValue: true
5941
6353
  });
5942
- if (startMCP && !isCancel7(startMCP)) {
6354
+ if (startMCP && !isCancel8(startMCP)) {
5943
6355
  const { runMCP: runMCP2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
5944
6356
  await runMCP2();
5945
6357
  } else {
5946
- outro2(pc8.green(`\u2713 Express setup complete! Run ${pc8.cyan("npx rrce-workflow mcp")} to start the server.`));
6358
+ outro3(pc9.green(`\u2713 Express setup complete! Run ${pc9.cyan("npx rrce-workflow mcp")} to start the server.`));
6359
+ }
6360
+ }
6361
+ async function runSetupAsUpdate(workspacePath, workspaceName, currentMode) {
6362
+ let mode = currentMode;
6363
+ if (!mode) {
6364
+ const modeResult = await select3({
6365
+ message: "Storage mode not detected. Please confirm:",
6366
+ options: [
6367
+ { value: "global", label: "Global (~/.rrce-workflow/)" },
6368
+ { value: "workspace", label: "Workspace (.rrce-workflow/)" }
6369
+ ],
6370
+ initialValue: "global"
6371
+ });
6372
+ if (isCancel8(modeResult)) {
6373
+ cancel3("Setup cancelled.");
6374
+ process.exit(0);
6375
+ }
6376
+ mode = modeResult;
6377
+ }
6378
+ const { runUpdateFlow: runUpdateFlow2 } = await Promise.resolve().then(() => (init_update_flow(), update_flow_exports));
6379
+ await runUpdateFlow2(workspacePath, workspaceName, mode);
6380
+ const startMCP = await confirm6({
6381
+ message: "Start MCP server now?",
6382
+ initialValue: true
6383
+ });
6384
+ if (startMCP && !isCancel8(startMCP)) {
6385
+ const { runMCP: runMCP2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6386
+ await runMCP2();
6387
+ } else {
6388
+ outro3(pc9.green(`\u2713 Setup complete! Run ${pc9.cyan("npx rrce-workflow mcp")} to start the server.`));
5947
6389
  }
5948
6390
  }
5949
6391
  async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
5950
- const s = spinner2();
6392
+ const customGlobalPath = getDefaultRRCEHome2();
6393
+ const existingProjectInfo = detectExistingProject(workspacePath, workspaceName, customGlobalPath);
6394
+ if (existingProjectInfo.isExisting) {
6395
+ note7(
6396
+ `${pc9.cyan("\u2139")} Existing RRCE installation detected.
6397
+ Running smart update to sync with latest version.`,
6398
+ "Update Mode"
6399
+ );
6400
+ return runSetupAsUpdate(
6401
+ workspacePath,
6402
+ workspaceName,
6403
+ existingProjectInfo.currentMode
6404
+ );
6405
+ }
6406
+ const s = spinner3();
5951
6407
  const setupModeResult = await select3({
5952
6408
  message: "Setup mode:",
5953
6409
  options: [
@@ -5956,19 +6412,19 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
5956
6412
  ],
5957
6413
  initialValue: "express"
5958
6414
  });
5959
- if (isCancel7(setupModeResult)) {
5960
- cancel2("Setup cancelled.");
6415
+ if (isCancel8(setupModeResult)) {
6416
+ cancel3("Setup cancelled.");
5961
6417
  process.exit(0);
5962
6418
  }
5963
6419
  if (setupModeResult === "express") {
5964
6420
  return runExpressSetup(workspacePath, workspaceName, existingProjects, s);
5965
6421
  }
5966
6422
  const storageMode = await promptStorageMode();
5967
- let customGlobalPath;
6423
+ let resolvedGlobalPath;
5968
6424
  if (storageMode === "global") {
5969
- customGlobalPath = await resolveGlobalPath();
5970
- if (!customGlobalPath) {
5971
- cancel2("Setup cancelled - no global path selected.");
6425
+ resolvedGlobalPath = await resolveGlobalPath();
6426
+ if (!resolvedGlobalPath) {
6427
+ cancel3("Setup cancelled - no global path selected.");
5972
6428
  process.exit(0);
5973
6429
  }
5974
6430
  }
@@ -5982,12 +6438,12 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
5982
6438
  const enableRAG = await promptRAG();
5983
6439
  const confirmed = await promptConfirmation();
5984
6440
  if (!confirmed) {
5985
- outro2("Setup cancelled by user.");
6441
+ outro3("Setup cancelled by user.");
5986
6442
  process.exit(0);
5987
6443
  }
5988
6444
  const config = {
5989
6445
  storageMode,
5990
- globalPath: customGlobalPath,
6446
+ globalPath: resolvedGlobalPath,
5991
6447
  tools,
5992
6448
  linkedProjects,
5993
6449
  addToGitignore,
@@ -6016,493 +6472,228 @@ async function executeSetup(config, workspacePath, workspaceName, allProjects, s
6016
6472
  if (needsVSCodeWorkspace) {
6017
6473
  const selectedProjects = allProjects.filter(
6018
6474
  (p) => config.linkedProjects.includes(`${p.name}:${p.source}`)
6019
- );
6020
- generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, config.globalPath);
6021
- }
6022
- await registerWithMCP(config, workspacePath, workspaceName);
6023
- const ideResults = installToSelectedIDEs(config.tools);
6024
- s.stop("Configuration generated");
6025
- const dataSummary = getDataPaths(config.storageMode, workspaceName, workspacePath, config.globalPath);
6026
- const summary = [
6027
- `${pc8.green("\u2713")} Data stored at: ${pc8.dim(dataSummary[0])}`,
6028
- config.tools.length > 0 ? `${pc8.green("\u2713")} Tools: ${config.tools.join(", ")}` : null,
6029
- config.exposeToMCP ? `${pc8.green("\u2713")} MCP server configured` : null,
6030
- config.enableRAG ? `${pc8.green("\u2713")} Semantic Search enabled` : null,
6031
- config.linkedProjects.length > 0 ? `${pc8.green("\u2713")} Linked ${config.linkedProjects.length} project(s)` : null,
6032
- ideResults.success.length > 0 ? `${pc8.green("\u2713")} RRCE installed to: ${ideResults.success.join(", ")}` : null,
6033
- ideResults.failed.length > 0 ? `${pc8.yellow("\u26A0")} Failed to install to: ${ideResults.failed.join(", ")}` : null
6034
- ].filter(Boolean);
6035
- if (ideResults.success.length > 0) {
6036
- summary.push("");
6037
- summary.push(pc8.dim("\u{1F4A1} You may need to restart your IDE or refresh MCP config for changes to take effect."));
6038
- }
6039
- note6(summary.join("\n"), "Setup Complete");
6040
- } catch (error) {
6041
- s.stop("Error occurred");
6042
- cancel2(
6043
- `Setup failed: ${error instanceof Error ? error.message : String(error)}
6044
-
6045
- ${pc8.dim("Tip: You can re-run the wizard to try again.")}`
6046
- );
6047
- process.exit(1);
6048
- }
6049
- }
6050
- async function handlePostSetup(config, workspacePath, workspaceName, linkedProjects) {
6051
- if (config.exposeToMCP) {
6052
- const shouldConfigureMCP = await confirm5({
6053
- message: "Would you like to start the MCP server now?",
6054
- initialValue: true
6055
- });
6056
- if (shouldConfigureMCP && !isCancel7(shouldConfigureMCP)) {
6057
- const { runMCP: runMCP2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6058
- await runMCP2();
6059
- } else {
6060
- if (linkedProjects.length > 0) {
6061
- outro2(pc8.green(`\u2713 Setup complete! Open ${pc8.bold(`${workspaceName}.code-workspace`)} in VSCode.`));
6062
- } else {
6063
- outro2(pc8.green(`\u2713 Setup complete! Run ${pc8.cyan("npx rrce-workflow mcp")} to start the server.`));
6064
- }
6065
- }
6066
- } else {
6067
- if (linkedProjects.length > 0) {
6068
- outro2(pc8.green(`\u2713 Setup complete! Open ${pc8.bold(`${workspaceName}.code-workspace`)} in VSCode.`));
6069
- } else {
6070
- outro2(pc8.green(`\u2713 Setup complete! Your agents are ready to use.`));
6071
- }
6072
- }
6073
- }
6074
-
6075
- // src/commands/wizard/link-flow.ts
6076
- init_paths();
6077
- import { multiselect as multiselect4, spinner as spinner3, note as note7, outro as outro3, cancel as cancel3, isCancel as isCancel8, confirm as confirm6 } from "@clack/prompts";
6078
- import pc9 from "picocolors";
6079
- import * as fs21 from "fs";
6080
- init_detection();
6081
- async function runLinkProjectsFlow(workspacePath, workspaceName) {
6082
- const projects = scanForProjects({
6083
- excludeWorkspace: workspaceName,
6084
- workspacePath
6085
- });
6086
- if (projects.length === 0) {
6087
- outro3(pc9.yellow("No other projects found. Try setting up another project first."));
6088
- return;
6089
- }
6090
- const customGlobalPath = getEffectiveRRCEHome(workspacePath);
6091
- const linkedProjects = await multiselect4({
6092
- message: "Select projects to link:",
6093
- options: projects.map((project) => ({
6094
- value: `${project.name}:${project.source}`,
6095
- // Unique key
6096
- label: `${project.name} ${pc9.dim(`(${project.source})`)}`,
6097
- hint: pc9.dim(
6098
- project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
6099
- )
6100
- })),
6101
- required: true
6102
- });
6103
- if (isCancel8(linkedProjects)) {
6104
- cancel3("Cancelled.");
6105
- process.exit(0);
6106
- }
6107
- const selectedKeys = linkedProjects;
6108
- if (selectedKeys.length === 0) {
6109
- outro3("No projects selected.");
6110
- return;
6111
- }
6112
- const selectedProjects = projects.filter(
6113
- (p) => selectedKeys.includes(`${p.name}:${p.source}`)
6114
- );
6115
- const s = spinner3();
6116
- s.start("Linking projects");
6117
- const configFilePath = getConfigPath(workspacePath);
6118
- let configContent = fs21.readFileSync(configFilePath, "utf-8");
6119
- if (configContent.includes("linked_projects:")) {
6120
- const lines = configContent.split("\n");
6121
- const linkedIndex = lines.findIndex((l) => l.trim() === "linked_projects:");
6122
- if (linkedIndex !== -1) {
6123
- let insertIndex = linkedIndex + 1;
6124
- while (insertIndex < lines.length && lines[insertIndex]?.startsWith(" - ")) {
6125
- insertIndex++;
6126
- }
6127
- for (const project of selectedProjects) {
6128
- const entry = ` - ${project.name}:${project.source}`;
6129
- if (!configContent.includes(entry)) {
6130
- lines.splice(insertIndex, 0, entry);
6131
- insertIndex++;
6132
- }
6133
- }
6134
- configContent = lines.join("\n");
6135
- }
6136
- } else {
6137
- configContent += `
6138
- linked_projects:
6139
- `;
6140
- selectedProjects.forEach((project) => {
6141
- configContent += ` - ${project.name}:${project.source}
6142
- `;
6143
- });
6144
- }
6145
- fs21.writeFileSync(configFilePath, configContent);
6146
- generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, customGlobalPath);
6147
- s.stop("Projects linked");
6148
- const workspaceFile = `${workspaceName}.code-workspace`;
6149
- const summary = [
6150
- `Linked projects:`,
6151
- ...selectedProjects.map((p) => ` \u2713 ${p.name} ${pc9.dim(`(${p.source})`)}`),
6152
- ``,
6153
- `Workspace file: ${pc9.cyan(workspaceFile)}`
6154
- ];
6155
- note7(summary.join("\n"), "Link Summary");
6156
- outro3(pc9.green(`\u2713 Projects linked! Open ${pc9.bold(workspaceFile)} in VSCode to access linked data.`));
6157
- const shouldExpose = await confirm6({
6158
- message: "Also expose these linked projects to the MCP server (for Agent access)?",
6159
- initialValue: true
6160
- });
6161
- if (shouldExpose && !isCancel8(shouldExpose)) {
6162
- try {
6163
- const { loadMCPConfig: loadMCPConfig3, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6164
- const mcpConfig = loadMCPConfig3();
6165
- for (const project of selectedProjects) {
6166
- setProjectConfig2(mcpConfig, project.name, true, void 0, project.dataPath);
6167
- }
6168
- saveMCPConfig2(mcpConfig);
6169
- note7("Projects have been added to the global MCP configuration.", "MCP Updated");
6170
- } catch (err) {
6171
- note7(`Failed to update MCP config: ${err}`, "MCP Update Failed");
6172
- }
6173
- }
6174
- }
6175
-
6176
- // src/commands/wizard/sync-flow.ts
6177
- init_paths();
6178
- import { confirm as confirm7, spinner as spinner4, note as note8, outro as outro4, cancel as cancel4, isCancel as isCancel9 } from "@clack/prompts";
6179
- import pc10 from "picocolors";
6180
- import * as fs22 from "fs";
6181
- import * as path22 from "path";
6182
- async function runSyncToGlobalFlow(workspacePath, workspaceName) {
6183
- const localPath = getLocalWorkspacePath(workspacePath);
6184
- const customGlobalPath = getEffectiveRRCEHome(workspacePath);
6185
- const globalPath = path22.join(customGlobalPath, "workspaces", workspaceName);
6186
- const subdirs = ["knowledge", "prompts", "templates", "tasks", "refs"];
6187
- const existingDirs = subdirs.filter(
6188
- (dir) => fs22.existsSync(path22.join(localPath, dir))
6189
- );
6190
- if (existingDirs.length === 0) {
6191
- outro4(pc10.yellow("No data found in workspace storage to sync."));
6192
- return;
6193
- }
6194
- note8(
6195
- `The following will be copied to global storage:
6196
- ${existingDirs.map((d) => ` \u2022 ${d}/`).join("\n")}
6197
-
6198
- Destination: ${pc10.cyan(globalPath)}`,
6199
- "Sync Preview"
6200
- );
6201
- const shouldSync = await confirm7({
6202
- message: "Proceed with sync to global storage?",
6203
- initialValue: true
6204
- });
6205
- if (isCancel9(shouldSync) || !shouldSync) {
6206
- outro4("Sync cancelled.");
6207
- return;
6208
- }
6209
- const s = spinner4();
6210
- s.start("Syncing to global storage");
6211
- try {
6212
- ensureDir(globalPath);
6213
- for (const dir of existingDirs) {
6214
- const srcDir = path22.join(localPath, dir);
6215
- const destDir = path22.join(globalPath, dir);
6216
- ensureDir(destDir);
6217
- copyDirRecursive(srcDir, destDir);
6218
- }
6219
- s.stop("Sync complete");
6220
- const summary = [
6221
- `Synced directories:`,
6222
- ...existingDirs.map((d) => ` \u2713 ${d}/`),
6223
- ``,
6224
- `Global path: ${pc10.cyan(globalPath)}`,
6225
- ``,
6226
- `Other projects can now link this knowledge!`
6227
- ];
6228
- note8(summary.join("\n"), "Sync Summary");
6229
- outro4(pc10.green("\u2713 Workspace knowledge synced to global storage!"));
6230
- } catch (error) {
6231
- s.stop("Error occurred");
6232
- cancel4(`Failed to sync: ${error instanceof Error ? error.message : String(error)}`);
6233
- process.exit(1);
6234
- }
6235
- }
6236
-
6237
- // src/commands/wizard/update-flow.ts
6238
- init_paths();
6239
- init_prompts();
6240
- import { confirm as confirm8, spinner as spinner5, note as note9, outro as outro5, cancel as cancel5, isCancel as isCancel10 } from "@clack/prompts";
6241
- import pc11 from "picocolors";
6242
- import * as fs23 from "fs";
6243
- import * as path23 from "path";
6244
- import { stringify as stringify3, parse } from "yaml";
6245
- init_install();
6246
- init_drift_service();
6247
- function backupFile(filePath) {
6248
- if (!fs23.existsSync(filePath)) return null;
6249
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").split("T")[0] + "-" + Date.now();
6250
- const backupPath = `${filePath}.${timestamp}.bak`;
6251
- try {
6252
- fs23.copyFileSync(filePath, backupPath);
6253
- return backupPath;
6254
- } catch (e) {
6255
- console.error(`Failed to backup ${filePath}:`, e);
6256
- return null;
6257
- }
6258
- }
6259
- function getPackageVersion2() {
6260
- try {
6261
- const agentCoreDir = getAgentCoreDir();
6262
- const packageJsonPath = path23.join(path23.dirname(agentCoreDir), "package.json");
6263
- if (fs23.existsSync(packageJsonPath)) {
6264
- return JSON.parse(fs23.readFileSync(packageJsonPath, "utf8")).version;
6265
- }
6266
- } catch (e) {
6267
- }
6268
- return "0.0.0";
6269
- }
6270
- async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
6271
- const s = spinner5();
6272
- s.start("Checking for updates");
6273
- try {
6274
- const agentCoreDir = getAgentCoreDir();
6275
- const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
6276
- const runningVersion = getPackageVersion2();
6277
- const mode = currentStorageMode || "global";
6278
- const customGlobalPath = getEffectiveRRCEHome(workspacePath);
6279
- const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
6280
- const configFilePath = getConfigPath(workspacePath);
6281
- let currentSyncedVersion;
6282
- if (fs23.existsSync(configFilePath)) {
6283
- try {
6284
- const content = fs23.readFileSync(configFilePath, "utf-8");
6285
- const config = parse(content);
6286
- currentSyncedVersion = config.last_synced_version;
6287
- } catch (e) {
6288
- }
6289
- }
6290
- const driftReport = DriftService.checkDrift(dataPaths[0], currentSyncedVersion, runningVersion);
6291
- s.stop("Updates found");
6292
- if (driftReport.type === "version") {
6293
- note9(`New version available: ${pc11.green(runningVersion)} (Current synced: ${pc11.dim(currentSyncedVersion || "None")})`, "Update Available");
6294
- }
6295
- if (driftReport.modifiedFiles.length > 0) {
6296
- note9(
6297
- pc11.yellow(`The following files have been modified and will be backed up before updating:
6298
- `) + driftReport.modifiedFiles.map((f) => ` \u2022 ${f}`).join("\n"),
6299
- "Modifications Detected"
6300
- );
6301
- }
6302
- const updateTargets = [
6303
- ` \u2022 prompts/ (${prompts.length} agent prompts)`,
6304
- ` \u2022 templates/ (output templates)`,
6305
- ` \u2022 docs/ (documentation)`
6306
- ];
6307
- const ideTargets = [];
6308
- if (fs23.existsSync(configFilePath)) {
6309
- const configContent = fs23.readFileSync(configFilePath, "utf-8");
6310
- if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
6311
- if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
6312
- if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
6313
- }
6314
- if (ideTargets.length > 0) {
6315
- updateTargets.push(` \u2022 IDE integrations: ${ideTargets.join(", ")}`);
6316
- }
6317
- note9(
6318
- `The following will be updated from the package:
6319
- ${updateTargets.join("\n")}
6320
-
6321
- Target locations:
6322
- ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
6323
- "Update Preview"
6324
- );
6325
- const shouldUpdate = await confirm8({
6326
- message: "Proceed with update?",
6327
- initialValue: true
6328
- });
6329
- if (isCancel10(shouldUpdate) || !shouldUpdate) {
6330
- outro5("Update cancelled.");
6331
- return;
6332
- }
6333
- s.start("Updating from package");
6334
- for (const dataPath of dataPaths) {
6335
- const dirs = ["templates", "prompts", "docs"];
6336
- const updatedFiles = [];
6337
- for (const dir of dirs) {
6338
- const srcDir = path23.join(agentCoreDir, dir);
6339
- if (!fs23.existsSync(srcDir)) continue;
6340
- const syncFiles = (src, rel) => {
6341
- const entries = fs23.readdirSync(src, { withFileTypes: true });
6342
- for (const entry of entries) {
6343
- const entrySrc = path23.join(src, entry.name);
6344
- const entryRel = path23.join(rel, entry.name);
6345
- const entryDest = path23.join(dataPath, entryRel);
6346
- if (entry.isDirectory()) {
6347
- ensureDir(entryDest);
6348
- syncFiles(entrySrc, entryRel);
6349
- } else {
6350
- if (driftReport.modifiedFiles.includes(entryRel)) {
6351
- backupFile(entryDest);
6352
- }
6353
- fs23.copyFileSync(entrySrc, entryDest);
6354
- updatedFiles.push(entryRel);
6355
- }
6356
- }
6357
- };
6358
- syncFiles(srcDir, dir);
6359
- }
6360
- const manifest = DriftService.generateManifest(dataPath, updatedFiles);
6361
- DriftService.saveManifest(dataPath, manifest);
6362
- }
6363
- const rrceHome = customGlobalPath || getDefaultRRCEHome2();
6364
- ensureDir(path23.join(rrceHome, "templates"));
6365
- ensureDir(path23.join(rrceHome, "docs"));
6366
- copyDirRecursive(path23.join(agentCoreDir, "templates"), path23.join(rrceHome, "templates"));
6367
- copyDirRecursive(path23.join(agentCoreDir, "docs"), path23.join(rrceHome, "docs"));
6368
- if (fs23.existsSync(configFilePath)) {
6369
- const configContent = fs23.readFileSync(configFilePath, "utf-8");
6370
- if (configContent.includes("copilot: true")) {
6371
- const copilotPath = getAgentPromptPath(workspacePath, "copilot");
6372
- ensureDir(copilotPath);
6373
- clearDirectory(copilotPath);
6374
- copyPromptsToDir(prompts, copilotPath, ".agent.md");
6375
- }
6376
- if (configContent.includes("antigravity: true")) {
6377
- const antigravityPath = getAgentPromptPath(workspacePath, "antigravity");
6378
- ensureDir(antigravityPath);
6379
- clearDirectory(antigravityPath);
6380
- copyPromptsToDir(prompts, antigravityPath, ".md");
6381
- }
6382
- if (configContent.includes("opencode: true")) {
6383
- const primaryDataPath = dataPaths[0];
6384
- if (primaryDataPath) {
6385
- updateOpenCodeAgents(prompts, mode, primaryDataPath);
6386
- }
6387
- }
6388
- try {
6389
- const yaml = parse(configContent);
6390
- yaml.last_synced_version = runningVersion;
6391
- fs23.writeFileSync(configFilePath, stringify3(yaml));
6392
- } catch (e) {
6393
- console.error("Failed to update config.yaml version:", e);
6394
- }
6395
- }
6396
- const mcpPath = path23.join(rrceHome, "mcp.yaml");
6397
- if (fs23.existsSync(mcpPath)) {
6398
- try {
6399
- const content = fs23.readFileSync(mcpPath, "utf-8");
6400
- const yaml = parse(content);
6401
- if (yaml.projects) {
6402
- const project = yaml.projects.find((p) => p.name === workspaceName);
6403
- if (project) {
6404
- project.last_synced_version = runningVersion;
6405
- fs23.writeFileSync(mcpPath, stringify3(yaml));
6406
- }
6407
- }
6408
- } catch (e) {
6409
- console.error("Failed to update mcp.yaml version:", e);
6410
- }
6411
- }
6412
- s.stop("Update complete");
6413
- const summary = [
6414
- `Updated:`,
6415
- ` \u2713 ${prompts.length} agent prompts`,
6416
- ` \u2713 Output templates`,
6417
- ` \u2713 Documentation`
6418
- ];
6419
- if (ideTargets.length > 0) {
6420
- summary.push(` \u2713 IDE integrations: ${ideTargets.join(", ")}`);
6475
+ );
6476
+ generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, config.globalPath);
6421
6477
  }
6422
- if (driftReport.modifiedFiles.length > 0) {
6423
- summary.push(` \u2713 ${driftReport.modifiedFiles.length} modified files backed up`);
6478
+ await registerWithMCP(config, workspacePath, workspaceName);
6479
+ const ideResults = installToSelectedIDEs(config.tools);
6480
+ s.stop("Configuration generated");
6481
+ const dataSummary = getDataPaths(config.storageMode, workspaceName, workspacePath, config.globalPath);
6482
+ const summary = [
6483
+ `${pc9.green("\u2713")} Data stored at: ${pc9.dim(dataSummary[0])}`,
6484
+ config.tools.length > 0 ? `${pc9.green("\u2713")} Tools: ${config.tools.join(", ")}` : null,
6485
+ config.exposeToMCP ? `${pc9.green("\u2713")} MCP server configured` : null,
6486
+ config.enableRAG ? `${pc9.green("\u2713")} Semantic Search enabled` : null,
6487
+ config.linkedProjects.length > 0 ? `${pc9.green("\u2713")} Linked ${config.linkedProjects.length} project(s)` : null,
6488
+ ideResults.success.length > 0 ? `${pc9.green("\u2713")} RRCE installed to: ${ideResults.success.join(", ")}` : null,
6489
+ ideResults.failed.length > 0 ? `${pc9.yellow("\u26A0")} Failed to install to: ${ideResults.failed.join(", ")}` : null
6490
+ ].filter(Boolean);
6491
+ if (ideResults.success.length > 0) {
6492
+ summary.push("");
6493
+ summary.push(pc9.dim("\u{1F4A1} You may need to restart your IDE or refresh MCP config for changes to take effect."));
6424
6494
  }
6425
- summary.push(
6426
- ``,
6427
- `Your configuration and knowledge files were preserved.`,
6428
- ``,
6429
- pc11.dim(`\u{1F4A1} If using OpenCode, you may need to reload for changes to take effect.`)
6430
- );
6431
- note9(summary.join("\n"), "Update Summary");
6432
- outro5(pc11.green("\u2713 Successfully updated from package!"));
6495
+ note7(summary.join("\n"), "Setup Complete");
6433
6496
  } catch (error) {
6434
6497
  s.stop("Error occurred");
6435
- cancel5(`Failed to update: ${error instanceof Error ? error.message : String(error)}`);
6498
+ cancel3(
6499
+ `Setup failed: ${error instanceof Error ? error.message : String(error)}
6500
+
6501
+ ${pc9.dim("Tip: You can re-run the wizard to try again.")}`
6502
+ );
6436
6503
  process.exit(1);
6437
6504
  }
6438
6505
  }
6439
- function updateOpenCodeAgents(prompts, mode, primaryDataPath) {
6440
- if (mode === "global") {
6441
- try {
6442
- const promptsDir = path23.join(path23.dirname(OPENCODE_CONFIG), "prompts");
6443
- ensureDir(promptsDir);
6444
- const newAgents = {};
6445
- for (const prompt of prompts) {
6446
- const baseName = path23.basename(prompt.filePath, ".md");
6447
- const agentId = `rrce_${baseName}`;
6448
- const promptFileName = `rrce-${baseName}.md`;
6449
- const promptFilePath = path23.join(promptsDir, promptFileName);
6450
- fs23.writeFileSync(promptFilePath, prompt.content);
6451
- const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
6452
- newAgents[agentId] = agentConfig;
6453
- }
6454
- updateOpenCodeConfig(newAgents);
6455
- if (fs23.existsSync(OPENCODE_CONFIG)) {
6456
- const config = JSON.parse(fs23.readFileSync(OPENCODE_CONFIG, "utf8"));
6457
- if (!config.agents) config.agents = {};
6458
- if (!config.agents.plan) config.agents.plan = {};
6459
- config.agents.plan.disable = true;
6460
- fs23.writeFileSync(OPENCODE_CONFIG, JSON.stringify(config, null, 2));
6506
+ async function handlePostSetup(config, workspacePath, workspaceName, linkedProjects) {
6507
+ if (config.exposeToMCP) {
6508
+ const shouldConfigureMCP = await confirm6({
6509
+ message: "Would you like to start the MCP server now?",
6510
+ initialValue: true
6511
+ });
6512
+ if (shouldConfigureMCP && !isCancel8(shouldConfigureMCP)) {
6513
+ const { runMCP: runMCP2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6514
+ await runMCP2();
6515
+ } else {
6516
+ if (linkedProjects.length > 0) {
6517
+ outro3(pc9.green(`\u2713 Setup complete! Open ${pc9.bold(`${workspaceName}.code-workspace`)} in VSCode.`));
6518
+ } else {
6519
+ outro3(pc9.green(`\u2713 Setup complete! Run ${pc9.cyan("npx rrce-workflow mcp")} to start the server.`));
6461
6520
  }
6462
- } catch (e) {
6463
- console.error("Failed to update global OpenCode config with agents:", e);
6464
6521
  }
6465
6522
  } else {
6466
- const opencodeBaseDir = path23.join(primaryDataPath, ".opencode", "agent");
6467
- ensureDir(opencodeBaseDir);
6468
- clearDirectory(opencodeBaseDir);
6469
- for (const prompt of prompts) {
6470
- const baseName = path23.basename(prompt.filePath, ".md");
6471
- const agentId = `rrce_${baseName}`;
6472
- const agentConfig = convertToOpenCodeAgent(prompt);
6473
- const content = `---
6474
- ${stringify3({
6475
- description: agentConfig.description,
6476
- mode: agentConfig.mode,
6477
- tools: agentConfig.tools
6478
- })}---
6479
- ${agentConfig.prompt}`;
6480
- fs23.writeFileSync(path23.join(opencodeBaseDir, `${agentId}.md`), content);
6523
+ if (linkedProjects.length > 0) {
6524
+ outro3(pc9.green(`\u2713 Setup complete! Open ${pc9.bold(`${workspaceName}.code-workspace`)} in VSCode.`));
6525
+ } else {
6526
+ outro3(pc9.green(`\u2713 Setup complete! Your agents are ready to use.`));
6481
6527
  }
6482
6528
  }
6483
6529
  }
6484
- function clearDirectory(dirPath) {
6485
- if (!fs23.existsSync(dirPath)) return;
6486
- const entries = fs23.readdirSync(dirPath, { withFileTypes: true });
6487
- for (const entry of entries) {
6488
- if (entry.isFile()) {
6489
- fs23.unlinkSync(path23.join(dirPath, entry.name));
6530
+
6531
+ // src/commands/wizard/link-flow.ts
6532
+ init_paths();
6533
+ import { multiselect as multiselect4, spinner as spinner4, note as note8, outro as outro4, cancel as cancel4, isCancel as isCancel9, confirm as confirm7 } from "@clack/prompts";
6534
+ import pc10 from "picocolors";
6535
+ import * as fs22 from "fs";
6536
+ init_detection();
6537
+ async function runLinkProjectsFlow(workspacePath, workspaceName) {
6538
+ const projects = scanForProjects({
6539
+ excludeWorkspace: workspaceName,
6540
+ workspacePath
6541
+ });
6542
+ if (projects.length === 0) {
6543
+ outro4(pc10.yellow("No other projects found. Try setting up another project first."));
6544
+ return;
6545
+ }
6546
+ const customGlobalPath = getEffectiveRRCEHome(workspacePath);
6547
+ const linkedProjects = await multiselect4({
6548
+ message: "Select projects to link:",
6549
+ options: projects.map((project) => ({
6550
+ value: `${project.name}:${project.source}`,
6551
+ // Unique key
6552
+ label: `${project.name} ${pc10.dim(`(${project.source})`)}`,
6553
+ hint: pc10.dim(
6554
+ project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
6555
+ )
6556
+ })),
6557
+ required: true
6558
+ });
6559
+ if (isCancel9(linkedProjects)) {
6560
+ cancel4("Cancelled.");
6561
+ process.exit(0);
6562
+ }
6563
+ const selectedKeys = linkedProjects;
6564
+ if (selectedKeys.length === 0) {
6565
+ outro4("No projects selected.");
6566
+ return;
6567
+ }
6568
+ const selectedProjects = projects.filter(
6569
+ (p) => selectedKeys.includes(`${p.name}:${p.source}`)
6570
+ );
6571
+ const s = spinner4();
6572
+ s.start("Linking projects");
6573
+ const configFilePath = getConfigPath(workspacePath);
6574
+ let configContent = fs22.readFileSync(configFilePath, "utf-8");
6575
+ if (configContent.includes("linked_projects:")) {
6576
+ const lines = configContent.split("\n");
6577
+ const linkedIndex = lines.findIndex((l) => l.trim() === "linked_projects:");
6578
+ if (linkedIndex !== -1) {
6579
+ let insertIndex = linkedIndex + 1;
6580
+ while (insertIndex < lines.length && lines[insertIndex]?.startsWith(" - ")) {
6581
+ insertIndex++;
6582
+ }
6583
+ for (const project of selectedProjects) {
6584
+ const entry = ` - ${project.name}:${project.source}`;
6585
+ if (!configContent.includes(entry)) {
6586
+ lines.splice(insertIndex, 0, entry);
6587
+ insertIndex++;
6588
+ }
6589
+ }
6590
+ configContent = lines.join("\n");
6591
+ }
6592
+ } else {
6593
+ configContent += `
6594
+ linked_projects:
6595
+ `;
6596
+ selectedProjects.forEach((project) => {
6597
+ configContent += ` - ${project.name}:${project.source}
6598
+ `;
6599
+ });
6600
+ }
6601
+ fs22.writeFileSync(configFilePath, configContent);
6602
+ generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, customGlobalPath);
6603
+ s.stop("Projects linked");
6604
+ const workspaceFile = `${workspaceName}.code-workspace`;
6605
+ const summary = [
6606
+ `Linked projects:`,
6607
+ ...selectedProjects.map((p) => ` \u2713 ${p.name} ${pc10.dim(`(${p.source})`)}`),
6608
+ ``,
6609
+ `Workspace file: ${pc10.cyan(workspaceFile)}`
6610
+ ];
6611
+ note8(summary.join("\n"), "Link Summary");
6612
+ outro4(pc10.green(`\u2713 Projects linked! Open ${pc10.bold(workspaceFile)} in VSCode to access linked data.`));
6613
+ const shouldExpose = await confirm7({
6614
+ message: "Also expose these linked projects to the MCP server (for Agent access)?",
6615
+ initialValue: true
6616
+ });
6617
+ if (shouldExpose && !isCancel9(shouldExpose)) {
6618
+ try {
6619
+ const { loadMCPConfig: loadMCPConfig3, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6620
+ const mcpConfig = loadMCPConfig3();
6621
+ for (const project of selectedProjects) {
6622
+ setProjectConfig2(mcpConfig, project.name, true, void 0, project.dataPath);
6623
+ }
6624
+ saveMCPConfig2(mcpConfig);
6625
+ note8("Projects have been added to the global MCP configuration.", "MCP Updated");
6626
+ } catch (err) {
6627
+ note8(`Failed to update MCP config: ${err}`, "MCP Update Failed");
6490
6628
  }
6491
6629
  }
6492
6630
  }
6493
- function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
6631
+
6632
+ // src/commands/wizard/sync-flow.ts
6633
+ init_paths();
6634
+ init_utils();
6635
+ import { confirm as confirm8, spinner as spinner5, note as note9, outro as outro5, cancel as cancel5, isCancel as isCancel10 } from "@clack/prompts";
6636
+ import pc11 from "picocolors";
6637
+ import * as fs23 from "fs";
6638
+ import * as path23 from "path";
6639
+ async function runSyncToGlobalFlow(workspacePath, workspaceName) {
6640
+ const localPath = getLocalWorkspacePath(workspacePath);
6641
+ const customGlobalPath = getEffectiveRRCEHome(workspacePath);
6494
6642
  const globalPath = path23.join(customGlobalPath, "workspaces", workspaceName);
6495
- const workspacePath = path23.join(workspaceRoot, ".rrce-workflow");
6496
- switch (mode) {
6497
- case "global":
6498
- return [globalPath];
6499
- case "workspace":
6500
- return [workspacePath];
6501
- default:
6502
- return [globalPath];
6643
+ const subdirs = ["knowledge", "prompts", "templates", "tasks", "refs"];
6644
+ const existingDirs = subdirs.filter(
6645
+ (dir) => fs23.existsSync(path23.join(localPath, dir))
6646
+ );
6647
+ if (existingDirs.length === 0) {
6648
+ outro5(pc11.yellow("No data found in workspace storage to sync."));
6649
+ return;
6650
+ }
6651
+ note9(
6652
+ `The following will be copied to global storage:
6653
+ ${existingDirs.map((d) => ` \u2022 ${d}/`).join("\n")}
6654
+
6655
+ Destination: ${pc11.cyan(globalPath)}`,
6656
+ "Sync Preview"
6657
+ );
6658
+ const shouldSync = await confirm8({
6659
+ message: "Proceed with sync to global storage?",
6660
+ initialValue: true
6661
+ });
6662
+ if (isCancel10(shouldSync) || !shouldSync) {
6663
+ outro5("Sync cancelled.");
6664
+ return;
6665
+ }
6666
+ const s = spinner5();
6667
+ s.start("Syncing to global storage");
6668
+ try {
6669
+ ensureDir(globalPath);
6670
+ for (const dir of existingDirs) {
6671
+ const srcDir = path23.join(localPath, dir);
6672
+ const destDir = path23.join(globalPath, dir);
6673
+ ensureDir(destDir);
6674
+ copyDirRecursive(srcDir, destDir);
6675
+ }
6676
+ s.stop("Sync complete");
6677
+ const summary = [
6678
+ `Synced directories:`,
6679
+ ...existingDirs.map((d) => ` \u2713 ${d}/`),
6680
+ ``,
6681
+ `Global path: ${pc11.cyan(globalPath)}`,
6682
+ ``,
6683
+ `Other projects can now link this knowledge!`
6684
+ ];
6685
+ note9(summary.join("\n"), "Sync Summary");
6686
+ outro5(pc11.green("\u2713 Workspace knowledge synced to global storage!"));
6687
+ } catch (error) {
6688
+ s.stop("Error occurred");
6689
+ cancel5(`Failed to sync: ${error instanceof Error ? error.message : String(error)}`);
6690
+ process.exit(1);
6503
6691
  }
6504
6692
  }
6505
6693
 
6694
+ // src/commands/wizard/index.ts
6695
+ init_update_flow();
6696
+
6506
6697
  // src/commands/wizard/delete-flow.ts
6507
6698
  import { multiselect as multiselect5, confirm as confirm9, spinner as spinner6, note as note10, cancel as cancel6, isCancel as isCancel11 } from "@clack/prompts";
6508
6699
  import pc12 from "picocolors";
@@ -6570,6 +6761,76 @@ Are you sure?`,
6570
6761
  // src/commands/wizard/index.ts
6571
6762
  init_mcp();
6572
6763
  init_config();
6764
+ function getPackageVersion3() {
6765
+ try {
6766
+ const agentCoreDir = getAgentCoreDir();
6767
+ const packageJsonPath = path24.join(path24.dirname(agentCoreDir), "package.json");
6768
+ if (fs25.existsSync(packageJsonPath)) {
6769
+ return JSON.parse(fs25.readFileSync(packageJsonPath, "utf8")).version;
6770
+ }
6771
+ } catch (e) {
6772
+ }
6773
+ return "0.0.0";
6774
+ }
6775
+ function getLastSyncedVersion(workspacePath, workspaceName) {
6776
+ const configFilePath = getConfigPath(workspacePath);
6777
+ if (fs25.existsSync(configFilePath)) {
6778
+ try {
6779
+ const content = fs25.readFileSync(configFilePath, "utf-8");
6780
+ const config = parse2(content);
6781
+ if (config.last_synced_version) {
6782
+ return config.last_synced_version;
6783
+ }
6784
+ } catch (e) {
6785
+ }
6786
+ }
6787
+ const rrceHome = getEffectiveRRCEHome(workspacePath) || getDefaultRRCEHome2();
6788
+ const mcpPath = path24.join(rrceHome, "mcp.yaml");
6789
+ if (fs25.existsSync(mcpPath)) {
6790
+ try {
6791
+ const content = fs25.readFileSync(mcpPath, "utf-8");
6792
+ const config = parse2(content);
6793
+ const project = config.projects?.find((p) => p.name === workspaceName);
6794
+ if (project?.last_synced_version) {
6795
+ return project.last_synced_version;
6796
+ }
6797
+ } catch (e) {
6798
+ }
6799
+ }
6800
+ return void 0;
6801
+ }
6802
+ async function checkAndPromptUpdate(workspacePath, workspaceName, currentStorageMode) {
6803
+ const runningVersion = getPackageVersion3();
6804
+ const lastSyncedVersion = getLastSyncedVersion(workspacePath, workspaceName);
6805
+ if (lastSyncedVersion === runningVersion) {
6806
+ return true;
6807
+ }
6808
+ const versionInfo = lastSyncedVersion ? `${pc13.dim(lastSyncedVersion)} \u2192 ${pc13.green(runningVersion)}` : `${pc13.dim("unknown")} \u2192 ${pc13.green(runningVersion)}`;
6809
+ note11(
6810
+ `${pc13.bold(pc13.cyan("Update available!"))} ${versionInfo}
6811
+
6812
+ New prompts, templates, and agent improvements are ready to install.
6813
+ Your custom knowledge and configuration will be preserved.`,
6814
+ "\u{1F4E6} Version Update"
6815
+ );
6816
+ const shouldUpdate = await confirm10({
6817
+ message: "Apply update now?",
6818
+ initialValue: true
6819
+ });
6820
+ if (isCancel12(shouldUpdate)) {
6821
+ return false;
6822
+ }
6823
+ if (shouldUpdate) {
6824
+ await runSilentUpdate(workspacePath, workspaceName, currentStorageMode);
6825
+ note11(
6826
+ `${pc13.green("\u2713")} Updated to version ${pc13.bold(runningVersion)}
6827
+
6828
+ All agent prompts, templates, and IDE integrations have been synced.`,
6829
+ "Update Complete"
6830
+ );
6831
+ }
6832
+ return true;
6833
+ }
6573
6834
  async function runWizard() {
6574
6835
  intro2(pc13.cyan(pc13.inverse(" RRCE-Workflow Setup ")));
6575
6836
  const s = spinner7();
@@ -6620,24 +6881,22 @@ Workspace: ${pc13.bold(workspaceName)}`,
6620
6881
  const localDataPath = getLocalWorkspacePath(workspacePath);
6621
6882
  const hasLocalData = fs25.existsSync(localDataPath);
6622
6883
  if (isAlreadyConfigured) {
6884
+ const continueToMenu = await checkAndPromptUpdate(workspacePath, workspaceName, currentStorageMode);
6885
+ if (!continueToMenu) {
6886
+ outro7("Exited.");
6887
+ process.exit(0);
6888
+ }
6623
6889
  const menuOptions = [];
6624
6890
  menuOptions.push({
6625
6891
  value: "mcp",
6626
- label: "\u{1F50C} Configure MCP Server",
6627
- hint: "Expose projects to AI assistants (VSCode, Antigravity, Claude)"
6892
+ label: "\u{1F50C} MCP Dashboard",
6893
+ hint: "Manage projects & AI integrations"
6628
6894
  });
6629
- if (detectedProjects.some((p) => p.source === "global")) {
6630
- menuOptions.push({
6631
- value: "delete-global",
6632
- label: "\u{1F5D1}\uFE0F Delete global project(s)",
6633
- hint: "Remove knowledge and configuration"
6634
- });
6635
- }
6636
- if (detectedProjects.length > 0) {
6895
+ if (detectedProjects.some((p) => p.source === "global") || detectedProjects.length > 0) {
6637
6896
  menuOptions.push({
6638
- value: "link",
6639
- label: "\u{1F517} Link other project knowledge",
6640
- hint: `${detectedProjects.length} projects detected (global + sibling)`
6897
+ value: "manage",
6898
+ label: "\u{1F4C1} Manage Projects",
6899
+ hint: "Link, delete, or sync projects"
6641
6900
  });
6642
6901
  }
6643
6902
  if (currentStorageMode === "workspace" && hasLocalData) {
@@ -6647,11 +6906,10 @@ Workspace: ${pc13.bold(workspaceName)}`,
6647
6906
  hint: "Share knowledge with other projects"
6648
6907
  });
6649
6908
  }
6650
- menuOptions.push({ value: "update", label: "\u{1F4E6} Update from package", hint: "Get latest prompts & templates" });
6651
- menuOptions.push({ value: "reconfigure", label: "\u{1F527} Reconfigure project", hint: "Change storage mode, tools, etc." });
6909
+ menuOptions.push({ value: "advanced", label: "\u2699\uFE0F Advanced", hint: "Update, reconfigure, or troubleshoot" });
6652
6910
  menuOptions.push({ value: "exit", label: "\u21A9 Exit" });
6653
6911
  const action = await select5({
6654
- message: "This workspace is already configured. What would you like to do?",
6912
+ message: "What would you like to do?",
6655
6913
  options: menuOptions
6656
6914
  });
6657
6915
  if (isCancel12(action) || action === "exit") {
@@ -6662,23 +6920,62 @@ Workspace: ${pc13.bold(workspaceName)}`,
6662
6920
  await runMCP();
6663
6921
  return;
6664
6922
  }
6665
- if (action === "delete-global") {
6666
- await runDeleteGlobalProjectFlow(detectedProjects);
6667
- return;
6668
- }
6669
- if (action === "link") {
6670
- await runLinkProjectsFlow(workspacePath, workspaceName);
6671
- return;
6923
+ if (action === "manage") {
6924
+ const manageOptions = [];
6925
+ if (detectedProjects.some((p) => p.source === "global")) {
6926
+ manageOptions.push({
6927
+ value: "delete-global",
6928
+ label: "\u{1F5D1}\uFE0F Delete global project(s)",
6929
+ hint: "Remove knowledge and configuration"
6930
+ });
6931
+ }
6932
+ if (detectedProjects.length > 0) {
6933
+ manageOptions.push({
6934
+ value: "link",
6935
+ label: "\u{1F517} Link other project knowledge",
6936
+ hint: `${detectedProjects.length} projects detected`
6937
+ });
6938
+ }
6939
+ manageOptions.push({ value: "back", label: "\u21A9 Back to main menu" });
6940
+ const manageAction = await select5({
6941
+ message: "Project Management",
6942
+ options: manageOptions
6943
+ });
6944
+ if (isCancel12(manageAction) || manageAction === "back") {
6945
+ return runWizard();
6946
+ }
6947
+ if (manageAction === "delete-global") {
6948
+ await runDeleteGlobalProjectFlow(detectedProjects);
6949
+ return;
6950
+ }
6951
+ if (manageAction === "link") {
6952
+ await runLinkProjectsFlow(workspacePath, workspaceName);
6953
+ return;
6954
+ }
6672
6955
  }
6673
6956
  if (action === "sync-global") {
6674
6957
  await runSyncToGlobalFlow(workspacePath, workspaceName);
6675
6958
  return;
6676
6959
  }
6677
- if (action === "update") {
6678
- await runUpdateFlow(workspacePath, workspaceName, currentStorageMode);
6679
- return;
6680
- }
6681
- if (action === "reconfigure") {
6960
+ if (action === "advanced") {
6961
+ const advancedOptions = [
6962
+ { value: "update", label: "\u{1F4E6} Manual Update", hint: "Force update from package" },
6963
+ { value: "reconfigure", label: "\u{1F527} Reconfigure Project", hint: "Change storage mode, tools, etc." },
6964
+ { value: "back", label: "\u21A9 Back to main menu" }
6965
+ ];
6966
+ const advancedAction = await select5({
6967
+ message: "Advanced Options",
6968
+ options: advancedOptions
6969
+ });
6970
+ if (isCancel12(advancedAction) || advancedAction === "back") {
6971
+ return runWizard();
6972
+ }
6973
+ if (advancedAction === "update") {
6974
+ await runUpdateFlow(workspacePath, workspaceName, currentStorageMode);
6975
+ return;
6976
+ }
6977
+ if (advancedAction === "reconfigure") {
6978
+ }
6682
6979
  }
6683
6980
  }
6684
6981
  await runSetupFlow(workspacePath, workspaceName, detectedProjects);