prior-cli 1.3.9 → 1.3.11
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/bin/prior.js +64 -50
- package/package.json +1 -1
package/bin/prior.js
CHANGED
|
@@ -628,27 +628,56 @@ async function startChat(opts = {}) {
|
|
|
628
628
|
{ cmd: '/exit', desc: 'Exit' },
|
|
629
629
|
];
|
|
630
630
|
|
|
631
|
-
|
|
632
|
-
let
|
|
631
|
+
// Unified sub-row tracker — covers image indicator + slash suggestions
|
|
632
|
+
let _subRowCount = 0;
|
|
633
|
+
let _suggTimer = null;
|
|
633
634
|
|
|
634
|
-
|
|
635
|
-
|
|
635
|
+
// Clear all rows rendered below the input line
|
|
636
|
+
function clearAllSubRows() {
|
|
637
|
+
if (!_subRowCount) return;
|
|
636
638
|
process.stdout.write('\x1b[s');
|
|
637
|
-
for (let i = 0; i <
|
|
639
|
+
for (let i = 0; i < _subRowCount; i++) process.stdout.write('\x1b[B\r\x1b[2K');
|
|
638
640
|
process.stdout.write('\x1b[u');
|
|
639
|
-
|
|
640
|
-
}
|
|
641
|
+
_subRowCount = 0;
|
|
642
|
+
}
|
|
641
643
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
644
|
+
// Alias used by the loop's rl.question callback
|
|
645
|
+
clearSuggestions = clearAllSubRows;
|
|
646
|
+
|
|
647
|
+
// Redraw image indicator + slash suggestions — always called together so
|
|
648
|
+
// they share the same row-count and never stomp on each other.
|
|
649
|
+
function renderSubRows(line) {
|
|
650
|
+
clearAllSubRows();
|
|
651
|
+
process.stdout.write('\x1b[s');
|
|
652
|
+
let rows = 0;
|
|
653
|
+
|
|
654
|
+
// Image indicator — always first, persists across backspace/typing
|
|
655
|
+
if (_pendingImageBase64) {
|
|
656
|
+
process.stdout.write(`\x1b[B\r\x1b[2K ${c.brand('◈')} ${c.dim('[Image] attached · alt+v to remove')}`);
|
|
657
|
+
rows++;
|
|
650
658
|
}
|
|
651
|
-
|
|
659
|
+
|
|
660
|
+
// Slash-command suggestions
|
|
661
|
+
if ((line || '').startsWith('/')) {
|
|
662
|
+
const word = line.split(' ')[0];
|
|
663
|
+
const matches = SLASH_CMDS.filter(({ cmd }) => cmd.startsWith(word));
|
|
664
|
+
for (const { cmd, desc } of matches) {
|
|
665
|
+
process.stdout.write(`\x1b[B\r\x1b[2K${c.brand(' ' + cmd.padEnd(14))}${c.dim(desc)}`);
|
|
666
|
+
rows++;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
process.stdout.write('\x1b[u');
|
|
671
|
+
_subRowCount = rows;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Show a one-off message below the input (cleared on next keypress)
|
|
675
|
+
function flashSubRow(msg) {
|
|
676
|
+
clearAllSubRows();
|
|
677
|
+
process.stdout.write('\x1b[s');
|
|
678
|
+
process.stdout.write(`\x1b[B\r\x1b[2K ${msg}`);
|
|
679
|
+
process.stdout.write('\x1b[u');
|
|
680
|
+
_subRowCount = 1;
|
|
652
681
|
}
|
|
653
682
|
|
|
654
683
|
process.stdin.on('keypress', (ch, key) => {
|
|
@@ -661,52 +690,37 @@ async function startChat(opts = {}) {
|
|
|
661
690
|
return;
|
|
662
691
|
}
|
|
663
692
|
|
|
664
|
-
// Alt+V —
|
|
693
|
+
// Alt+V — grab image from clipboard, or remove if already attached
|
|
665
694
|
if (key.meta && key.name === 'v') {
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
695
|
+
if (_pendingImageBase64) {
|
|
696
|
+
_pendingImageBase64 = null;
|
|
697
|
+
renderSubRows(rl.line || '');
|
|
698
|
+
} else {
|
|
699
|
+
try {
|
|
700
|
+
const ps = `Add-Type -AssemblyName System.Windows.Forms; $img = [System.Windows.Forms.Clipboard]::GetImage(); if ($img) { $ms = New-Object System.IO.MemoryStream; $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png); [Convert]::ToBase64String($ms.ToArray()) } else { '' }`;
|
|
701
|
+
const b64 = execSync(`powershell -NoProfile -Command "${ps}"`, { timeout: 5000 }).toString().trim();
|
|
702
|
+
if (b64) {
|
|
703
|
+
_pendingImageBase64 = b64;
|
|
704
|
+
renderSubRows(rl.line || '');
|
|
705
|
+
} else {
|
|
706
|
+
flashSubRow(c.muted('✗ No image found in clipboard'));
|
|
707
|
+
}
|
|
708
|
+
} catch {
|
|
709
|
+
flashSubRow(c.muted('✗ Could not read clipboard'));
|
|
679
710
|
}
|
|
680
|
-
} catch {
|
|
681
|
-
process.stdout.write('\x1b[s');
|
|
682
|
-
process.stdout.write(`\x1b[B\r\x1b[2K ${c.muted('✗ Could not read clipboard')}`);
|
|
683
|
-
process.stdout.write('\x1b[u');
|
|
684
711
|
}
|
|
685
712
|
return;
|
|
686
713
|
}
|
|
687
714
|
|
|
688
715
|
if (key.name === 'return' || key.name === 'enter' || (key.ctrl && key.name === 'c')) {
|
|
689
|
-
|
|
690
|
-
const clearRows = _suggCount + (_pendingImageBase64 ? 1 : 0);
|
|
691
|
-
if (clearRows > 0) {
|
|
692
|
-
process.stdout.write('\x1b[s');
|
|
693
|
-
for (let i = 0; i < clearRows; i++) process.stdout.write('\x1b[B\r\x1b[2K');
|
|
694
|
-
process.stdout.write('\x1b[u');
|
|
695
|
-
_suggCount = 0;
|
|
696
|
-
}
|
|
716
|
+
clearAllSubRows();
|
|
697
717
|
return;
|
|
698
718
|
}
|
|
699
719
|
|
|
720
|
+
// Redraw sub-rows on every keypress so backspace / typing never wipes them
|
|
700
721
|
_suggTimer = setTimeout(() => {
|
|
701
722
|
_suggTimer = null;
|
|
702
|
-
|
|
703
|
-
if (!line.startsWith('/')) {
|
|
704
|
-
clearSuggestions();
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
const word = line.split(' ')[0];
|
|
708
|
-
const matches = SLASH_CMDS.filter(({ cmd }) => cmd.startsWith(word));
|
|
709
|
-
renderSuggestions(matches);
|
|
723
|
+
renderSubRows(rl.line || '');
|
|
710
724
|
}, 50);
|
|
711
725
|
});
|
|
712
726
|
}
|