oh-skillhub 0.1.12 → 0.1.14
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/package.json +1 -1
- package/src/cli.js +111 -13
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -174,7 +174,7 @@ async function runCleanWithAnswers(options, input, output, scriptedAnswers = nul
|
|
|
174
174
|
let selected;
|
|
175
175
|
let prefilledConfirmation = null;
|
|
176
176
|
if (!cleanOptions.names.length && !cleanOptions.dryRun) {
|
|
177
|
-
if (!hasScriptedAnswers && input.isTTY) {
|
|
177
|
+
if (!hasScriptedAnswers && input.isTTY && output.isTTY) {
|
|
178
178
|
selected = await promptCleanSelection(input, output, discovered);
|
|
179
179
|
} else {
|
|
180
180
|
output.write(renderCleanSelectionMenu(discovered));
|
|
@@ -203,6 +203,10 @@ async function runCleanWithAnswers(options, input, output, scriptedAnswers = nul
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
async function promptCleanSelection(input, output, skills) {
|
|
206
|
+
if (input.isTTY && output.isTTY) {
|
|
207
|
+
const selectedIndexes = await runRawCleanSelection(input, output, skills);
|
|
208
|
+
return selectedIndexes.map((index) => skills[index]);
|
|
209
|
+
}
|
|
206
210
|
output.write(renderCleanSelectionMenu(skills));
|
|
207
211
|
const rl = readlinePromises.createInterface({ input, output });
|
|
208
212
|
try {
|
|
@@ -572,6 +576,7 @@ function runRawTuiSelection(input, output, choices, agent = "codex") {
|
|
|
572
576
|
function runRawAgentSelection(input, output) {
|
|
573
577
|
return new Promise((resolve, reject) => {
|
|
574
578
|
let cursor = 0;
|
|
579
|
+
let selected = 0;
|
|
575
580
|
const wasRaw = input.isRaw;
|
|
576
581
|
|
|
577
582
|
readline.emitKeypressEvents(input);
|
|
@@ -579,7 +584,7 @@ function runRawAgentSelection(input, output) {
|
|
|
579
584
|
|
|
580
585
|
function render() {
|
|
581
586
|
output.write("\x1b[2J\x1b[H");
|
|
582
|
-
output.write(renderRawAgentMenu(cursor));
|
|
587
|
+
output.write(renderRawAgentMenu(cursor, selected));
|
|
583
588
|
}
|
|
584
589
|
|
|
585
590
|
function cleanup() {
|
|
@@ -604,9 +609,14 @@ function runRawAgentSelection(input, output) {
|
|
|
604
609
|
render();
|
|
605
610
|
return;
|
|
606
611
|
}
|
|
607
|
-
if (key &&
|
|
612
|
+
if (key && key.name === "space") {
|
|
613
|
+
selected = cursor;
|
|
614
|
+
render();
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
if (key && key.name === "return") {
|
|
608
618
|
cleanup();
|
|
609
|
-
resolve(AGENT_CHOICES[
|
|
619
|
+
resolve(AGENT_CHOICES[selected].agent);
|
|
610
620
|
}
|
|
611
621
|
}
|
|
612
622
|
|
|
@@ -619,6 +629,7 @@ function runRawAgentSelection(input, output) {
|
|
|
619
629
|
function runRawActionSelection(input, output) {
|
|
620
630
|
return new Promise((resolve, reject) => {
|
|
621
631
|
let cursor = 0;
|
|
632
|
+
let selected = 0;
|
|
622
633
|
const wasRaw = input.isRaw;
|
|
623
634
|
|
|
624
635
|
readline.emitKeypressEvents(input);
|
|
@@ -626,7 +637,7 @@ function runRawActionSelection(input, output) {
|
|
|
626
637
|
|
|
627
638
|
function render() {
|
|
628
639
|
output.write("\x1b[2J\x1b[H");
|
|
629
|
-
output.write(renderRawActionMenu(cursor));
|
|
640
|
+
output.write(renderRawActionMenu(cursor, selected));
|
|
630
641
|
}
|
|
631
642
|
|
|
632
643
|
function cleanup() {
|
|
@@ -651,9 +662,14 @@ function runRawActionSelection(input, output) {
|
|
|
651
662
|
render();
|
|
652
663
|
return;
|
|
653
664
|
}
|
|
654
|
-
if (key &&
|
|
665
|
+
if (key && key.name === "space") {
|
|
666
|
+
selected = cursor;
|
|
667
|
+
render();
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
if (key && key.name === "return") {
|
|
655
671
|
cleanup();
|
|
656
|
-
resolve(ACTION_CHOICES[
|
|
672
|
+
resolve(ACTION_CHOICES[selected].action);
|
|
657
673
|
}
|
|
658
674
|
}
|
|
659
675
|
|
|
@@ -663,7 +679,7 @@ function runRawActionSelection(input, output) {
|
|
|
663
679
|
});
|
|
664
680
|
}
|
|
665
681
|
|
|
666
|
-
function renderRawActionMenu(cursor) {
|
|
682
|
+
function renderRawActionMenu(cursor, selected = cursor) {
|
|
667
683
|
const width = 76;
|
|
668
684
|
const line = `+${"-".repeat(width - 2)}+`;
|
|
669
685
|
const lines = [
|
|
@@ -673,19 +689,20 @@ function renderRawActionMenu(cursor) {
|
|
|
673
689
|
line,
|
|
674
690
|
"",
|
|
675
691
|
colorize("Choose action", ANSI.bold),
|
|
676
|
-
colorize(" Up/Down or j/k: move Space
|
|
692
|
+
colorize(" Up/Down or j/k: move Space: select Enter: confirm Ctrl+C: cancel", ANSI.dim),
|
|
677
693
|
"",
|
|
678
694
|
];
|
|
679
695
|
ACTION_CHOICES.forEach((choice, index) => {
|
|
680
696
|
const pointer = index === cursor ? ">" : " ";
|
|
681
|
-
const
|
|
697
|
+
const highlighted = index === cursor;
|
|
698
|
+
const row = `${pointer} ${rawCheckbox(index === selected, highlighted)} ${choice.label.padEnd(22, " ")} ${choice.hint}`;
|
|
682
699
|
lines.push(index === cursor ? colorize(row, ANSI.reverse, ANSI.bold) : row);
|
|
683
700
|
});
|
|
684
701
|
lines.push("");
|
|
685
702
|
return `${lines.join("\n")}\n`;
|
|
686
703
|
}
|
|
687
704
|
|
|
688
|
-
function renderRawAgentMenu(cursor) {
|
|
705
|
+
function renderRawAgentMenu(cursor, selected = cursor) {
|
|
689
706
|
const width = 76;
|
|
690
707
|
const line = `+${"-".repeat(width - 2)}+`;
|
|
691
708
|
const lines = [
|
|
@@ -695,12 +712,13 @@ function renderRawAgentMenu(cursor) {
|
|
|
695
712
|
line,
|
|
696
713
|
"",
|
|
697
714
|
colorize("Choose install target", ANSI.bold),
|
|
698
|
-
colorize(" Up/Down or j/k: move Space
|
|
715
|
+
colorize(" Up/Down or j/k: move Space: select Enter: confirm Ctrl+C: cancel", ANSI.dim),
|
|
699
716
|
"",
|
|
700
717
|
];
|
|
701
718
|
AGENT_CHOICES.forEach((choice, index) => {
|
|
702
719
|
const pointer = index === cursor ? ">" : " ";
|
|
703
|
-
const
|
|
720
|
+
const highlighted = index === cursor;
|
|
721
|
+
const row = `${pointer} ${rawCheckbox(index === selected, highlighted)} ${choice.label.padEnd(10, " ")} ${choice.hint}`;
|
|
704
722
|
lines.push(index === cursor ? colorize(row, ANSI.reverse, ANSI.bold) : row);
|
|
705
723
|
});
|
|
706
724
|
lines.push("");
|
|
@@ -738,6 +756,85 @@ function renderRawTuiMenu(choices, cursor, selected, agent = "codex") {
|
|
|
738
756
|
return `${lines.join("\n")}\n`;
|
|
739
757
|
}
|
|
740
758
|
|
|
759
|
+
function runRawCleanSelection(input, output, skills) {
|
|
760
|
+
return new Promise((resolve, reject) => {
|
|
761
|
+
let cursor = 0;
|
|
762
|
+
const selected = new Set([cursor]);
|
|
763
|
+
const wasRaw = input.isRaw;
|
|
764
|
+
|
|
765
|
+
readline.emitKeypressEvents(input);
|
|
766
|
+
input.setRawMode(true);
|
|
767
|
+
|
|
768
|
+
function render() {
|
|
769
|
+
output.write("\x1b[2J\x1b[H");
|
|
770
|
+
output.write(renderRawCleanSelectionMenu(skills, cursor, selected));
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
function cleanup() {
|
|
774
|
+
input.removeListener("keypress", onKeypress);
|
|
775
|
+
input.setRawMode(Boolean(wasRaw));
|
|
776
|
+
output.write("\x1b[?25h");
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
function onKeypress(_str, key) {
|
|
780
|
+
if (key && key.ctrl && key.name === "c") {
|
|
781
|
+
cleanup();
|
|
782
|
+
reject(new Error("Cancelled."));
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
if (key && (key.name === "down" || key.name === "j")) {
|
|
786
|
+
cursor = (cursor + 1) % skills.length;
|
|
787
|
+
render();
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
if (key && (key.name === "up" || key.name === "k")) {
|
|
791
|
+
cursor = (cursor - 1 + skills.length) % skills.length;
|
|
792
|
+
render();
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
if (key && key.name === "space") {
|
|
796
|
+
if (selected.has(cursor)) selected.delete(cursor);
|
|
797
|
+
else selected.add(cursor);
|
|
798
|
+
render();
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
if (key && key.name === "return") {
|
|
802
|
+
cleanup();
|
|
803
|
+
resolve(selected.size ? Array.from(selected).sort((a, b) => a - b) : [cursor]);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
output.write("\x1b[?25l");
|
|
808
|
+
render();
|
|
809
|
+
input.on("keypress", onKeypress);
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
function renderRawCleanSelectionMenu(skills, cursor, selected) {
|
|
814
|
+
const width = 92;
|
|
815
|
+
const line = `+${"-".repeat(width - 2)}+`;
|
|
816
|
+
const lines = [
|
|
817
|
+
line,
|
|
818
|
+
rawHeaderLine("OH SkillHub", width, ANSI.cyan, ANSI.bold),
|
|
819
|
+
rawHeaderLine("OpenHarmony Skills Cleaner", width, ANSI.dim),
|
|
820
|
+
line,
|
|
821
|
+
"",
|
|
822
|
+
colorize("Detected skills", ANSI.bold),
|
|
823
|
+
colorize(" Up/Down or j/k: move Space: select Enter: clean Ctrl+C: cancel", ANSI.dim),
|
|
824
|
+
"",
|
|
825
|
+
];
|
|
826
|
+
skills.forEach((skill, index) => {
|
|
827
|
+
const pointer = index === cursor ? ">" : " ";
|
|
828
|
+
const highlighted = index === cursor;
|
|
829
|
+
const checkbox = rawCheckbox(selected.has(index), highlighted);
|
|
830
|
+
const group = `${skill.domain || "unknown"}/${skill.stage || "unknown"}`;
|
|
831
|
+
const row = `${pointer} ${checkbox} ${skill.name.padEnd(36, " ")} ${skill.status.padEnd(9, " ")} ${group}`;
|
|
832
|
+
lines.push(highlighted ? colorize(row, ANSI.reverse, ANSI.bold) : row);
|
|
833
|
+
});
|
|
834
|
+
lines.push("");
|
|
835
|
+
return `${lines.join("\n")}\n`;
|
|
836
|
+
}
|
|
837
|
+
|
|
741
838
|
function colorize(value, ...codes) {
|
|
742
839
|
return `${codes.join("")}${value}${ANSI.reset}`;
|
|
743
840
|
}
|
|
@@ -947,6 +1044,7 @@ module.exports = {
|
|
|
947
1044
|
renderCleanPlan,
|
|
948
1045
|
renderRawActionMenu,
|
|
949
1046
|
renderRawAgentMenu,
|
|
1047
|
+
renderRawCleanSelectionMenu,
|
|
950
1048
|
parseSelection,
|
|
951
1049
|
renderRawTuiMenu,
|
|
952
1050
|
renderTuiMenu,
|