prior-cli 1.3.9 → 1.3.10
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 +52 -43
- 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 replace · type your prompt and press enter')}`);
|
|
657
|
+
rows++;
|
|
658
|
+
}
|
|
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
|
+
}
|
|
650
668
|
}
|
|
651
|
-
|
|
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,32 @@ async function startChat(opts = {}) {
|
|
|
661
690
|
return;
|
|
662
691
|
}
|
|
663
692
|
|
|
664
|
-
// Alt+V —
|
|
693
|
+
// Alt+V — grab image from Windows clipboard
|
|
665
694
|
if (key.meta && key.name === 'v') {
|
|
666
695
|
try {
|
|
667
696
|
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 { '' }`;
|
|
668
697
|
const b64 = execSync(`powershell -NoProfile -Command "${ps}"`, { timeout: 5000 }).toString().trim();
|
|
669
698
|
if (b64) {
|
|
670
699
|
_pendingImageBase64 = b64;
|
|
671
|
-
|
|
672
|
-
process.stdout.write('\x1b[s');
|
|
673
|
-
process.stdout.write(`\x1b[B\r\x1b[2K ${c.brand('◈')} ${c.dim('image from clipboard attached — type your prompt and press enter')}`);
|
|
674
|
-
process.stdout.write('\x1b[u');
|
|
700
|
+
renderSubRows(rl.line || ''); // immediate redraw with indicator
|
|
675
701
|
} else {
|
|
676
|
-
|
|
677
|
-
process.stdout.write(`\x1b[B\r\x1b[2K ${c.muted('✗ No image found in clipboard')}`);
|
|
678
|
-
process.stdout.write('\x1b[u');
|
|
702
|
+
flashSubRow(c.muted('✗ No image found in clipboard'));
|
|
679
703
|
}
|
|
680
704
|
} catch {
|
|
681
|
-
|
|
682
|
-
process.stdout.write(`\x1b[B\r\x1b[2K ${c.muted('✗ Could not read clipboard')}`);
|
|
683
|
-
process.stdout.write('\x1b[u');
|
|
705
|
+
flashSubRow(c.muted('✗ Could not read clipboard'));
|
|
684
706
|
}
|
|
685
707
|
return;
|
|
686
708
|
}
|
|
687
709
|
|
|
688
710
|
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
|
-
}
|
|
711
|
+
clearAllSubRows();
|
|
697
712
|
return;
|
|
698
713
|
}
|
|
699
714
|
|
|
715
|
+
// Redraw sub-rows on every keypress so backspace / typing never wipes them
|
|
700
716
|
_suggTimer = setTimeout(() => {
|
|
701
717
|
_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);
|
|
718
|
+
renderSubRows(rl.line || '');
|
|
710
719
|
}, 50);
|
|
711
720
|
});
|
|
712
721
|
}
|