rrce-workflow 0.2.17 → 0.2.18
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.
- package/dist/index.js +91 -215
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/commands/wizard/index.ts
|
|
2
|
-
import { intro, select as select2, spinner as spinner5, note as note5, outro as outro5, isCancel as
|
|
3
|
-
import
|
|
4
|
-
import * as
|
|
2
|
+
import { intro, select as select2, spinner as spinner5, note as note5, outro as outro5, isCancel as isCancel5 } from "@clack/prompts";
|
|
3
|
+
import pc5 from "picocolors";
|
|
4
|
+
import * as fs10 from "fs";
|
|
5
5
|
|
|
6
6
|
// src/lib/git.ts
|
|
7
7
|
import { execSync } from "child_process";
|
|
@@ -249,10 +249,10 @@ function parseWorkspaceConfig(configPath) {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
// src/commands/wizard/setup-flow.ts
|
|
252
|
-
import { group, select, multiselect, confirm, spinner, note, outro, cancel, isCancel
|
|
253
|
-
import
|
|
254
|
-
import * as
|
|
255
|
-
import * as
|
|
252
|
+
import { group, text, select, multiselect, confirm, spinner, note, outro, cancel, isCancel } from "@clack/prompts";
|
|
253
|
+
import pc from "picocolors";
|
|
254
|
+
import * as fs6 from "fs";
|
|
255
|
+
import * as path6 from "path";
|
|
256
256
|
|
|
257
257
|
// src/lib/prompts.ts
|
|
258
258
|
import * as fs3 from "fs";
|
|
@@ -433,134 +433,6 @@ function generateVSCodeWorkspace(workspacePath, workspaceName, linkedProjects, c
|
|
|
433
433
|
fs5.writeFileSync(workspaceFilePath, JSON.stringify(workspace, null, 2));
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
-
// src/lib/autocomplete-prompt.ts
|
|
437
|
-
import { TextPrompt, isCancel } from "@clack/core";
|
|
438
|
-
import * as fs6 from "fs";
|
|
439
|
-
import * as path6 from "path";
|
|
440
|
-
import pc from "picocolors";
|
|
441
|
-
async function directoryAutocomplete(opts) {
|
|
442
|
-
let completions = [];
|
|
443
|
-
let completionIndex = 0;
|
|
444
|
-
let lastTabValue = "";
|
|
445
|
-
const prompt = new TextPrompt({
|
|
446
|
-
initialValue: opts.initialValue,
|
|
447
|
-
validate: opts.validate,
|
|
448
|
-
render() {
|
|
449
|
-
const title = `${pc.cyan("\u25C6")} ${opts.message}`;
|
|
450
|
-
const hintText = opts.hint ? pc.dim(` (${opts.hint})`) : "";
|
|
451
|
-
let inputLine;
|
|
452
|
-
if (this.state === "error") {
|
|
453
|
-
inputLine = `${pc.yellow("\u25B2")} ${this.valueWithCursor}`;
|
|
454
|
-
} else if (this.state === "submit") {
|
|
455
|
-
inputLine = `${pc.green("\u2713")} ${pc.dim(String(this.value || ""))}`;
|
|
456
|
-
} else {
|
|
457
|
-
inputLine = `${pc.cyan("\u2502")} ${this.valueWithCursor || pc.dim(opts.placeholder || "")}`;
|
|
458
|
-
}
|
|
459
|
-
let result2 = `${title}${hintText}
|
|
460
|
-
${inputLine}`;
|
|
461
|
-
if (this.state === "error" && this.error) {
|
|
462
|
-
result2 += `
|
|
463
|
-
${pc.yellow("\u2502")} ${pc.yellow(this.error)}`;
|
|
464
|
-
}
|
|
465
|
-
if (completions.length > 1 && this.state === "active") {
|
|
466
|
-
const remaining = completions.length - 1;
|
|
467
|
-
result2 += `
|
|
468
|
-
${pc.dim("\u2502")} ${pc.dim(`+${remaining} more, press Tab again to cycle`)}`;
|
|
469
|
-
}
|
|
470
|
-
return result2;
|
|
471
|
-
}
|
|
472
|
-
});
|
|
473
|
-
prompt.on("key", (key) => {
|
|
474
|
-
if (key === " " || key === "tab") {
|
|
475
|
-
handleTabCompletion(prompt);
|
|
476
|
-
} else {
|
|
477
|
-
completions = [];
|
|
478
|
-
completionIndex = 0;
|
|
479
|
-
lastTabValue = "";
|
|
480
|
-
}
|
|
481
|
-
});
|
|
482
|
-
function handleTabCompletion(p) {
|
|
483
|
-
const input = String(p.value || "");
|
|
484
|
-
const expanded = input.startsWith("~") ? input.replace(/^~/, process.env.HOME || "") : input;
|
|
485
|
-
if (lastTabValue === input && completions.length > 1) {
|
|
486
|
-
completionIndex = (completionIndex + 1) % completions.length;
|
|
487
|
-
const completion = completions[completionIndex] || "";
|
|
488
|
-
setPromptValue(p, completion);
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
completions = getDirectoryCompletions(expanded);
|
|
492
|
-
completionIndex = 0;
|
|
493
|
-
lastTabValue = input;
|
|
494
|
-
if (completions.length === 1) {
|
|
495
|
-
const completion = completions[0] || "";
|
|
496
|
-
setPromptValue(p, completion.endsWith("/") ? completion : completion + "/");
|
|
497
|
-
completions = [];
|
|
498
|
-
lastTabValue = "";
|
|
499
|
-
} else if (completions.length > 1) {
|
|
500
|
-
const commonPrefix = getCommonPrefix(completions);
|
|
501
|
-
if (commonPrefix.length > expanded.length) {
|
|
502
|
-
setPromptValue(p, commonPrefix);
|
|
503
|
-
lastTabValue = formatForDisplay(commonPrefix);
|
|
504
|
-
} else {
|
|
505
|
-
setPromptValue(p, completions[0] || "");
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
function setPromptValue(p, value2) {
|
|
510
|
-
const displayValue = formatForDisplay(value2);
|
|
511
|
-
p.value = displayValue;
|
|
512
|
-
}
|
|
513
|
-
function formatForDisplay(value2) {
|
|
514
|
-
const home = process.env.HOME || "";
|
|
515
|
-
return value2.startsWith(home) ? value2.replace(home, "~") : value2;
|
|
516
|
-
}
|
|
517
|
-
function getDirectoryCompletions(inputPath) {
|
|
518
|
-
try {
|
|
519
|
-
let dirToScan;
|
|
520
|
-
let prefix;
|
|
521
|
-
if (inputPath === "" || inputPath === "/") {
|
|
522
|
-
dirToScan = inputPath || "/";
|
|
523
|
-
prefix = "";
|
|
524
|
-
} else if (inputPath.endsWith("/")) {
|
|
525
|
-
dirToScan = inputPath;
|
|
526
|
-
prefix = "";
|
|
527
|
-
} else {
|
|
528
|
-
dirToScan = path6.dirname(inputPath);
|
|
529
|
-
prefix = path6.basename(inputPath).toLowerCase();
|
|
530
|
-
}
|
|
531
|
-
if (!fs6.existsSync(dirToScan)) {
|
|
532
|
-
return [];
|
|
533
|
-
}
|
|
534
|
-
const entries = fs6.readdirSync(dirToScan, { withFileTypes: true }).filter((entry) => {
|
|
535
|
-
if (!entry.isDirectory()) return false;
|
|
536
|
-
if (entry.name.startsWith(".") && !prefix.startsWith(".")) return false;
|
|
537
|
-
return prefix === "" || entry.name.toLowerCase().startsWith(prefix);
|
|
538
|
-
}).map((entry) => path6.join(dirToScan, entry.name)).sort();
|
|
539
|
-
return entries;
|
|
540
|
-
} catch {
|
|
541
|
-
return [];
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
function getCommonPrefix(strings) {
|
|
545
|
-
if (strings.length === 0) return "";
|
|
546
|
-
if (strings.length === 1) return strings[0] || "";
|
|
547
|
-
let prefix = strings[0] || "";
|
|
548
|
-
for (let i = 1; i < strings.length; i++) {
|
|
549
|
-
const str = strings[i] || "";
|
|
550
|
-
while (prefix.length > 0 && !str.startsWith(prefix)) {
|
|
551
|
-
prefix = prefix.slice(0, -1);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
return prefix;
|
|
555
|
-
}
|
|
556
|
-
const result = await prompt.prompt();
|
|
557
|
-
if (isCancel(result)) {
|
|
558
|
-
return result;
|
|
559
|
-
}
|
|
560
|
-
const value = String(result || "");
|
|
561
|
-
return value.startsWith("~") ? value.replace(/^~/, process.env.HOME || "") : value;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
436
|
// src/commands/wizard/setup-flow.ts
|
|
565
437
|
async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
566
438
|
const s = spinner();
|
|
@@ -592,8 +464,8 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
592
464
|
options: existingProjects.map((project) => ({
|
|
593
465
|
value: `${project.name}:${project.source}`,
|
|
594
466
|
// Unique key
|
|
595
|
-
label: `${project.name} ${
|
|
596
|
-
hint:
|
|
467
|
+
label: `${project.name} ${pc.dim(`(${project.source})`)}`,
|
|
468
|
+
hint: pc.dim(
|
|
597
469
|
project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
|
|
598
470
|
)
|
|
599
471
|
})),
|
|
@@ -643,7 +515,7 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
643
515
|
`Storage: ${config.storageMode === "both" ? "global + workspace" : config.storageMode}`
|
|
644
516
|
];
|
|
645
517
|
if (customGlobalPath && customGlobalPath !== getDefaultRRCEHome()) {
|
|
646
|
-
summary.push(`Global path: ${
|
|
518
|
+
summary.push(`Global path: ${pc.cyan(customGlobalPath)}`);
|
|
647
519
|
}
|
|
648
520
|
if (dataPaths.length > 0) {
|
|
649
521
|
summary.push(`Data paths:`);
|
|
@@ -656,13 +528,13 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
656
528
|
const linkedProjects = config.linkedProjects;
|
|
657
529
|
if (linkedProjects.length > 0) {
|
|
658
530
|
summary.push(`Linked projects: ${linkedProjects.join(", ")}`);
|
|
659
|
-
summary.push(`Workspace file: ${
|
|
531
|
+
summary.push(`Workspace file: ${pc.cyan(`${workspaceName}.code-workspace`)}`);
|
|
660
532
|
}
|
|
661
533
|
note(summary.join("\n"), "Setup Summary");
|
|
662
534
|
if (linkedProjects.length > 0) {
|
|
663
|
-
outro(
|
|
535
|
+
outro(pc.green(`\u2713 Setup complete! Open ${pc.bold(`${workspaceName}.code-workspace`)} in VSCode to access linked knowledge.`));
|
|
664
536
|
} else {
|
|
665
|
-
outro(
|
|
537
|
+
outro(pc.green(`\u2713 Setup complete! Your agents are ready to use.`));
|
|
666
538
|
}
|
|
667
539
|
} catch (error) {
|
|
668
540
|
s.stop("Error occurred");
|
|
@@ -677,7 +549,7 @@ async function resolveGlobalPath() {
|
|
|
677
549
|
options.push({
|
|
678
550
|
value: "default",
|
|
679
551
|
label: `Default (${defaultPath})`,
|
|
680
|
-
hint: isDefaultWritable ?
|
|
552
|
+
hint: isDefaultWritable ? pc.green("\u2713 writable") : pc.red("\u2717 not writable")
|
|
681
553
|
});
|
|
682
554
|
options.push({
|
|
683
555
|
value: "custom",
|
|
@@ -689,14 +561,14 @@ async function resolveGlobalPath() {
|
|
|
689
561
|
options,
|
|
690
562
|
initialValue: isDefaultWritable ? "default" : "custom"
|
|
691
563
|
});
|
|
692
|
-
if (
|
|
564
|
+
if (isCancel(choice)) {
|
|
693
565
|
return void 0;
|
|
694
566
|
}
|
|
695
567
|
if (choice === "default") {
|
|
696
568
|
if (!isDefaultWritable) {
|
|
697
569
|
note(
|
|
698
|
-
`${
|
|
699
|
-
${
|
|
570
|
+
`${pc.yellow("\u26A0")} Cannot write to default path:
|
|
571
|
+
${pc.dim(defaultPath)}
|
|
700
572
|
|
|
701
573
|
This can happen when running via npx/bunx in restricted environments.
|
|
702
574
|
Please choose a custom path instead.`,
|
|
@@ -706,18 +578,18 @@ Please choose a custom path instead.`,
|
|
|
706
578
|
}
|
|
707
579
|
return defaultPath;
|
|
708
580
|
}
|
|
709
|
-
const suggestedPath =
|
|
710
|
-
const customPath = await
|
|
581
|
+
const suggestedPath = path6.join(process.env.HOME || "~", ".local", "share", "rrce-workflow");
|
|
582
|
+
const customPath = await text({
|
|
711
583
|
message: "Enter custom global path:",
|
|
712
|
-
|
|
713
|
-
|
|
584
|
+
defaultValue: suggestedPath,
|
|
585
|
+
placeholder: suggestedPath,
|
|
714
586
|
validate: (value) => {
|
|
715
587
|
if (!value.trim()) {
|
|
716
588
|
return "Path cannot be empty";
|
|
717
589
|
}
|
|
718
|
-
const
|
|
719
|
-
if (!checkWriteAccess(
|
|
720
|
-
return `Cannot write to ${
|
|
590
|
+
const expandedPath2 = value.startsWith("~") ? value.replace("~", process.env.HOME || "") : value;
|
|
591
|
+
if (!checkWriteAccess(expandedPath2)) {
|
|
592
|
+
return `Cannot write to ${expandedPath2}. Please choose a writable path.`;
|
|
721
593
|
}
|
|
722
594
|
return void 0;
|
|
723
595
|
}
|
|
@@ -725,20 +597,24 @@ Please choose a custom path instead.`,
|
|
|
725
597
|
if (isCancel(customPath)) {
|
|
726
598
|
return void 0;
|
|
727
599
|
}
|
|
728
|
-
|
|
600
|
+
let expandedPath = customPath.startsWith("~") ? customPath.replace("~", process.env.HOME || "") : customPath;
|
|
601
|
+
if (!expandedPath.endsWith(".rrce-workflow")) {
|
|
602
|
+
expandedPath = path6.join(expandedPath, ".rrce-workflow");
|
|
603
|
+
}
|
|
604
|
+
return expandedPath;
|
|
729
605
|
}
|
|
730
606
|
async function generateConfiguration(config, workspacePath, workspaceName, allProjects = []) {
|
|
731
607
|
const dataPaths = getDataPaths(config.storageMode, workspaceName, workspacePath, config.globalPath);
|
|
732
608
|
for (const dataPath of dataPaths) {
|
|
733
609
|
ensureDir(dataPath);
|
|
734
|
-
ensureDir(
|
|
735
|
-
ensureDir(
|
|
736
|
-
ensureDir(
|
|
737
|
-
ensureDir(
|
|
610
|
+
ensureDir(path6.join(dataPath, "knowledge"));
|
|
611
|
+
ensureDir(path6.join(dataPath, "refs"));
|
|
612
|
+
ensureDir(path6.join(dataPath, "tasks"));
|
|
613
|
+
ensureDir(path6.join(dataPath, "templates"));
|
|
738
614
|
}
|
|
739
615
|
const agentCoreDir = getAgentCoreDir();
|
|
740
616
|
syncMetadataToAll(agentCoreDir, dataPaths);
|
|
741
|
-
copyDirToAllStoragePaths(
|
|
617
|
+
copyDirToAllStoragePaths(path6.join(agentCoreDir, "templates"), "templates", dataPaths);
|
|
742
618
|
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
743
619
|
if (config.tools.includes("copilot")) {
|
|
744
620
|
const copilotPath = getAgentPromptPath(workspacePath, "copilot");
|
|
@@ -750,8 +626,8 @@ async function generateConfiguration(config, workspacePath, workspaceName, allPr
|
|
|
750
626
|
ensureDir(antigravityPath);
|
|
751
627
|
copyPromptsToDir(prompts, antigravityPath, ".md");
|
|
752
628
|
}
|
|
753
|
-
const workspaceConfigPath =
|
|
754
|
-
ensureDir(
|
|
629
|
+
const workspaceConfigPath = path6.join(workspacePath, ".rrce-workflow", "config.yaml");
|
|
630
|
+
ensureDir(path6.dirname(workspaceConfigPath));
|
|
755
631
|
let configContent = `# RRCE-Workflow Configuration
|
|
756
632
|
version: 1
|
|
757
633
|
|
|
@@ -779,7 +655,7 @@ linked_projects:
|
|
|
779
655
|
`;
|
|
780
656
|
});
|
|
781
657
|
}
|
|
782
|
-
|
|
658
|
+
fs6.writeFileSync(workspaceConfigPath, configContent);
|
|
783
659
|
if (config.tools.includes("copilot") || config.linkedProjects.length > 0) {
|
|
784
660
|
const selectedProjects = allProjects.filter(
|
|
785
661
|
(p) => config.linkedProjects.includes(`${p.name}:${p.source}`)
|
|
@@ -788,8 +664,8 @@ linked_projects:
|
|
|
788
664
|
}
|
|
789
665
|
}
|
|
790
666
|
function getDataPaths(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
791
|
-
const globalPath =
|
|
792
|
-
const workspacePath =
|
|
667
|
+
const globalPath = path6.join(customGlobalPath || getDefaultRRCEHome(), "workspaces", workspaceName);
|
|
668
|
+
const workspacePath = path6.join(workspaceRoot, ".rrce-workflow");
|
|
793
669
|
switch (mode) {
|
|
794
670
|
case "global":
|
|
795
671
|
return [globalPath];
|
|
@@ -803,9 +679,9 @@ function getDataPaths(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
|
803
679
|
}
|
|
804
680
|
|
|
805
681
|
// src/commands/wizard/link-flow.ts
|
|
806
|
-
import { multiselect as multiselect2, spinner as spinner2, note as note2, outro as outro2, cancel as cancel2, isCancel as
|
|
807
|
-
import
|
|
808
|
-
import * as
|
|
682
|
+
import { multiselect as multiselect2, spinner as spinner2, note as note2, outro as outro2, cancel as cancel2, isCancel as isCancel2 } from "@clack/prompts";
|
|
683
|
+
import pc2 from "picocolors";
|
|
684
|
+
import * as fs7 from "fs";
|
|
809
685
|
async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
810
686
|
const projects = scanForProjects({
|
|
811
687
|
excludeWorkspace: workspaceName,
|
|
@@ -813,7 +689,7 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
|
813
689
|
scanSiblings: true
|
|
814
690
|
});
|
|
815
691
|
if (projects.length === 0) {
|
|
816
|
-
outro2(
|
|
692
|
+
outro2(pc2.yellow("No other projects found. Try setting up another project first."));
|
|
817
693
|
return;
|
|
818
694
|
}
|
|
819
695
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
@@ -822,14 +698,14 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
|
822
698
|
options: projects.map((project) => ({
|
|
823
699
|
value: `${project.name}:${project.source}`,
|
|
824
700
|
// Unique key
|
|
825
|
-
label: `${project.name} ${
|
|
826
|
-
hint:
|
|
701
|
+
label: `${project.name} ${pc2.dim(`(${project.source})`)}`,
|
|
702
|
+
hint: pc2.dim(
|
|
827
703
|
project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
|
|
828
704
|
)
|
|
829
705
|
})),
|
|
830
706
|
required: true
|
|
831
707
|
});
|
|
832
|
-
if (
|
|
708
|
+
if (isCancel2(linkedProjects)) {
|
|
833
709
|
cancel2("Cancelled.");
|
|
834
710
|
process.exit(0);
|
|
835
711
|
}
|
|
@@ -844,7 +720,7 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
|
844
720
|
const s = spinner2();
|
|
845
721
|
s.start("Linking projects");
|
|
846
722
|
const configFilePath = getConfigPath(workspacePath);
|
|
847
|
-
let configContent =
|
|
723
|
+
let configContent = fs7.readFileSync(configFilePath, "utf-8");
|
|
848
724
|
if (configContent.includes("linked_projects:")) {
|
|
849
725
|
const lines = configContent.split("\n");
|
|
850
726
|
const linkedIndex = lines.findIndex((l) => l.trim() === "linked_projects:");
|
|
@@ -871,49 +747,49 @@ linked_projects:
|
|
|
871
747
|
`;
|
|
872
748
|
});
|
|
873
749
|
}
|
|
874
|
-
|
|
750
|
+
fs7.writeFileSync(configFilePath, configContent);
|
|
875
751
|
generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, customGlobalPath);
|
|
876
752
|
s.stop("Projects linked");
|
|
877
753
|
const workspaceFile = `${workspaceName}.code-workspace`;
|
|
878
754
|
const summary = [
|
|
879
755
|
`Linked projects:`,
|
|
880
|
-
...selectedProjects.map((p) => ` \u2713 ${p.name} ${
|
|
756
|
+
...selectedProjects.map((p) => ` \u2713 ${p.name} ${pc2.dim(`(${p.source})`)}`),
|
|
881
757
|
``,
|
|
882
|
-
`Workspace file: ${
|
|
758
|
+
`Workspace file: ${pc2.cyan(workspaceFile)}`
|
|
883
759
|
];
|
|
884
760
|
note2(summary.join("\n"), "Link Summary");
|
|
885
|
-
outro2(
|
|
761
|
+
outro2(pc2.green(`\u2713 Projects linked! Open ${pc2.bold(workspaceFile)} in VSCode to access linked data.`));
|
|
886
762
|
}
|
|
887
763
|
|
|
888
764
|
// src/commands/wizard/sync-flow.ts
|
|
889
|
-
import { confirm as confirm2, spinner as spinner3, note as note3, outro as outro3, cancel as cancel3, isCancel as
|
|
890
|
-
import
|
|
891
|
-
import * as
|
|
892
|
-
import * as
|
|
765
|
+
import { confirm as confirm2, spinner as spinner3, note as note3, outro as outro3, cancel as cancel3, isCancel as isCancel3 } from "@clack/prompts";
|
|
766
|
+
import pc3 from "picocolors";
|
|
767
|
+
import * as fs8 from "fs";
|
|
768
|
+
import * as path7 from "path";
|
|
893
769
|
async function runSyncToGlobalFlow(workspacePath, workspaceName) {
|
|
894
770
|
const localPath = getLocalWorkspacePath(workspacePath);
|
|
895
771
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
896
|
-
const globalPath =
|
|
772
|
+
const globalPath = path7.join(customGlobalPath, "workspaces", workspaceName);
|
|
897
773
|
const subdirs = ["knowledge", "prompts", "templates", "tasks", "refs"];
|
|
898
774
|
const existingDirs = subdirs.filter(
|
|
899
|
-
(dir) =>
|
|
775
|
+
(dir) => fs8.existsSync(path7.join(localPath, dir))
|
|
900
776
|
);
|
|
901
777
|
if (existingDirs.length === 0) {
|
|
902
|
-
outro3(
|
|
778
|
+
outro3(pc3.yellow("No data found in workspace storage to sync."));
|
|
903
779
|
return;
|
|
904
780
|
}
|
|
905
781
|
note3(
|
|
906
782
|
`The following will be copied to global storage:
|
|
907
783
|
${existingDirs.map((d) => ` \u2022 ${d}/`).join("\n")}
|
|
908
784
|
|
|
909
|
-
Destination: ${
|
|
785
|
+
Destination: ${pc3.cyan(globalPath)}`,
|
|
910
786
|
"Sync Preview"
|
|
911
787
|
);
|
|
912
788
|
const shouldSync = await confirm2({
|
|
913
789
|
message: "Proceed with sync to global storage?",
|
|
914
790
|
initialValue: true
|
|
915
791
|
});
|
|
916
|
-
if (
|
|
792
|
+
if (isCancel3(shouldSync) || !shouldSync) {
|
|
917
793
|
outro3("Sync cancelled.");
|
|
918
794
|
return;
|
|
919
795
|
}
|
|
@@ -922,27 +798,27 @@ Destination: ${pc4.cyan(globalPath)}`,
|
|
|
922
798
|
try {
|
|
923
799
|
ensureDir(globalPath);
|
|
924
800
|
for (const dir of existingDirs) {
|
|
925
|
-
const srcDir =
|
|
926
|
-
const destDir =
|
|
801
|
+
const srcDir = path7.join(localPath, dir);
|
|
802
|
+
const destDir = path7.join(globalPath, dir);
|
|
927
803
|
ensureDir(destDir);
|
|
928
804
|
copyDirRecursive(srcDir, destDir);
|
|
929
805
|
}
|
|
930
806
|
const configFilePath = getConfigPath(workspacePath);
|
|
931
|
-
let configContent =
|
|
807
|
+
let configContent = fs8.readFileSync(configFilePath, "utf-8");
|
|
932
808
|
configContent = configContent.replace(/mode:\s*workspace/, "mode: both");
|
|
933
|
-
|
|
809
|
+
fs8.writeFileSync(configFilePath, configContent);
|
|
934
810
|
s.stop("Sync complete");
|
|
935
811
|
const summary = [
|
|
936
812
|
`Synced directories:`,
|
|
937
813
|
...existingDirs.map((d) => ` \u2713 ${d}/`),
|
|
938
814
|
``,
|
|
939
|
-
`Global path: ${
|
|
940
|
-
`Storage mode updated to: ${
|
|
815
|
+
`Global path: ${pc3.cyan(globalPath)}`,
|
|
816
|
+
`Storage mode updated to: ${pc3.bold("both")}`,
|
|
941
817
|
``,
|
|
942
818
|
`Other projects can now link this knowledge!`
|
|
943
819
|
];
|
|
944
820
|
note3(summary.join("\n"), "Sync Summary");
|
|
945
|
-
outro3(
|
|
821
|
+
outro3(pc3.green("\u2713 Workspace knowledge synced to global storage!"));
|
|
946
822
|
} catch (error) {
|
|
947
823
|
s.stop("Error occurred");
|
|
948
824
|
cancel3(`Failed to sync: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -951,10 +827,10 @@ Destination: ${pc4.cyan(globalPath)}`,
|
|
|
951
827
|
}
|
|
952
828
|
|
|
953
829
|
// src/commands/wizard/update-flow.ts
|
|
954
|
-
import { confirm as confirm3, spinner as spinner4, note as note4, outro as outro4, cancel as cancel4, isCancel as
|
|
955
|
-
import
|
|
956
|
-
import * as
|
|
957
|
-
import * as
|
|
830
|
+
import { confirm as confirm3, spinner as spinner4, note as note4, outro as outro4, cancel as cancel4, isCancel as isCancel4 } from "@clack/prompts";
|
|
831
|
+
import pc4 from "picocolors";
|
|
832
|
+
import * as fs9 from "fs";
|
|
833
|
+
import * as path8 from "path";
|
|
958
834
|
async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
959
835
|
const s = spinner4();
|
|
960
836
|
s.start("Checking for updates");
|
|
@@ -978,16 +854,16 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
978
854
|
message: "Proceed with update?",
|
|
979
855
|
initialValue: true
|
|
980
856
|
});
|
|
981
|
-
if (
|
|
857
|
+
if (isCancel4(shouldUpdate) || !shouldUpdate) {
|
|
982
858
|
outro4("Update cancelled.");
|
|
983
859
|
return;
|
|
984
860
|
}
|
|
985
861
|
s.start("Updating from package");
|
|
986
862
|
for (const dataPath of dataPaths) {
|
|
987
|
-
copyDirToAllStoragePaths(
|
|
863
|
+
copyDirToAllStoragePaths(path8.join(agentCoreDir, "templates"), "templates", [dataPath]);
|
|
988
864
|
}
|
|
989
865
|
const configFilePath = getConfigPath(workspacePath);
|
|
990
|
-
const configContent =
|
|
866
|
+
const configContent = fs9.readFileSync(configFilePath, "utf-8");
|
|
991
867
|
if (configContent.includes("copilot: true")) {
|
|
992
868
|
const copilotPath = getAgentPromptPath(workspacePath, "copilot");
|
|
993
869
|
ensureDir(copilotPath);
|
|
@@ -1007,7 +883,7 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
1007
883
|
`Your configuration and knowledge files were preserved.`
|
|
1008
884
|
];
|
|
1009
885
|
note4(summary.join("\n"), "Update Summary");
|
|
1010
|
-
outro4(
|
|
886
|
+
outro4(pc4.green("\u2713 Successfully updated from package!"));
|
|
1011
887
|
} catch (error) {
|
|
1012
888
|
s.stop("Error occurred");
|
|
1013
889
|
cancel4(`Failed to update: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -1015,8 +891,8 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
1015
891
|
}
|
|
1016
892
|
}
|
|
1017
893
|
function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
1018
|
-
const globalPath =
|
|
1019
|
-
const workspacePath =
|
|
894
|
+
const globalPath = path8.join(customGlobalPath, "workspaces", workspaceName);
|
|
895
|
+
const workspacePath = path8.join(workspaceRoot, ".rrce-workflow");
|
|
1020
896
|
switch (mode) {
|
|
1021
897
|
case "global":
|
|
1022
898
|
return [globalPath];
|
|
@@ -1031,7 +907,7 @@ function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot,
|
|
|
1031
907
|
|
|
1032
908
|
// src/commands/wizard/index.ts
|
|
1033
909
|
async function runWizard() {
|
|
1034
|
-
intro(
|
|
910
|
+
intro(pc5.cyan(pc5.inverse(" RRCE-Workflow Setup ")));
|
|
1035
911
|
const s = spinner5();
|
|
1036
912
|
s.start("Detecting environment");
|
|
1037
913
|
const workspacePath = detectWorkspaceRoot();
|
|
@@ -1040,8 +916,8 @@ async function runWizard() {
|
|
|
1040
916
|
await new Promise((r) => setTimeout(r, 800));
|
|
1041
917
|
s.stop("Environment detected");
|
|
1042
918
|
note5(
|
|
1043
|
-
`Git User: ${
|
|
1044
|
-
Workspace: ${
|
|
919
|
+
`Git User: ${pc5.bold(gitUser || "(not found)")}
|
|
920
|
+
Workspace: ${pc5.bold(workspaceName)}`,
|
|
1045
921
|
"Context"
|
|
1046
922
|
);
|
|
1047
923
|
const detectedProjects = scanForProjects({
|
|
@@ -1050,18 +926,18 @@ Workspace: ${pc6.bold(workspaceName)}`,
|
|
|
1050
926
|
scanSiblings: true
|
|
1051
927
|
});
|
|
1052
928
|
const configFilePath = getConfigPath(workspacePath);
|
|
1053
|
-
const isAlreadyConfigured =
|
|
929
|
+
const isAlreadyConfigured = fs10.existsSync(configFilePath);
|
|
1054
930
|
let currentStorageMode = null;
|
|
1055
931
|
if (isAlreadyConfigured) {
|
|
1056
932
|
try {
|
|
1057
|
-
const configContent =
|
|
933
|
+
const configContent = fs10.readFileSync(configFilePath, "utf-8");
|
|
1058
934
|
const modeMatch = configContent.match(/mode:\s*(global|workspace|both)/);
|
|
1059
935
|
currentStorageMode = modeMatch?.[1] ?? null;
|
|
1060
936
|
} catch {
|
|
1061
937
|
}
|
|
1062
938
|
}
|
|
1063
939
|
const localDataPath = getLocalWorkspacePath(workspacePath);
|
|
1064
|
-
const hasLocalData =
|
|
940
|
+
const hasLocalData = fs10.existsSync(localDataPath);
|
|
1065
941
|
if (isAlreadyConfigured) {
|
|
1066
942
|
const menuOptions = [];
|
|
1067
943
|
if (detectedProjects.length > 0) {
|
|
@@ -1084,7 +960,7 @@ Workspace: ${pc6.bold(workspaceName)}`,
|
|
|
1084
960
|
message: "This workspace is already configured. What would you like to do?",
|
|
1085
961
|
options: menuOptions
|
|
1086
962
|
});
|
|
1087
|
-
if (
|
|
963
|
+
if (isCancel5(action) || action === "exit") {
|
|
1088
964
|
outro5("Exited.");
|
|
1089
965
|
process.exit(0);
|
|
1090
966
|
}
|
|
@@ -1105,12 +981,12 @@ Workspace: ${pc6.bold(workspaceName)}`,
|
|
|
1105
981
|
}
|
|
1106
982
|
|
|
1107
983
|
// src/commands/selector.ts
|
|
1108
|
-
import { intro as intro2, select as select3, note as note6, cancel as cancel6, isCancel as
|
|
1109
|
-
import
|
|
1110
|
-
import * as
|
|
984
|
+
import { intro as intro2, select as select3, note as note6, cancel as cancel6, isCancel as isCancel6, outro as outro6 } from "@clack/prompts";
|
|
985
|
+
import pc6 from "picocolors";
|
|
986
|
+
import * as path9 from "path";
|
|
1111
987
|
async function runSelector() {
|
|
1112
|
-
const workspaceName =
|
|
1113
|
-
intro2(
|
|
988
|
+
const workspaceName = path9.basename(process.cwd());
|
|
989
|
+
intro2(pc6.cyan(pc6.inverse(` RRCE-Workflow | ${workspaceName} `)));
|
|
1114
990
|
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
1115
991
|
if (prompts.length === 0) {
|
|
1116
992
|
cancel6("No agents found. Run `rrce-workflow` to set up.");
|
|
@@ -1124,14 +1000,14 @@ async function runSelector() {
|
|
|
1124
1000
|
hint: p.frontmatter.description
|
|
1125
1001
|
}))
|
|
1126
1002
|
});
|
|
1127
|
-
if (
|
|
1003
|
+
if (isCancel6(selection)) {
|
|
1128
1004
|
cancel6("Selection cancelled.");
|
|
1129
1005
|
process.exit(0);
|
|
1130
1006
|
}
|
|
1131
1007
|
const prompt = selection;
|
|
1132
1008
|
note6(
|
|
1133
1009
|
`Use this agent in your IDE by invoking:
|
|
1134
|
-
${
|
|
1010
|
+
${pc6.bold(pc6.cyan(`@${prompt.frontmatter.name}`))}`,
|
|
1135
1011
|
"Agent Selected"
|
|
1136
1012
|
);
|
|
1137
1013
|
outro6("Done");
|