prior-cli 1.6.0 → 1.6.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.
- package/bin/prior.js +65 -10
- package/package.json +1 -1
package/bin/prior.js
CHANGED
|
@@ -80,18 +80,15 @@ function spinStart(label = '') {
|
|
|
80
80
|
if (!process.stdout.isTTY) return;
|
|
81
81
|
_spinLabel = label;
|
|
82
82
|
_spinStart = Date.now();
|
|
83
|
-
|
|
83
|
+
const startTime = Date.now(); // captured in closure — never reset by label cycling
|
|
84
84
|
_spinTimer = setInterval(() => {
|
|
85
85
|
process.stdout.clearLine(0);
|
|
86
86
|
process.stdout.cursorTo(0);
|
|
87
|
-
const ms = Date.now() -
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
const displayLabel = _spinLabel === 'thinking…' ? THINK_LABELS[labelIdx] : _spinLabel;
|
|
93
|
-
const elapsedStr = ` ${c.dim('(' + fmtElapsed(ms) + ')')}`;
|
|
94
|
-
process.stdout.write(` ${c.brand(SPIN_FRAMES[_spinIdx++ % 4])} ${c.dim(displayLabel)}${elapsedStr}`);
|
|
87
|
+
const ms = Date.now() - startTime;
|
|
88
|
+
const displayLabel = _spinLabel === 'thinking…'
|
|
89
|
+
? THINK_LABELS[Math.floor(ms / 4000) % THINK_LABELS.length]
|
|
90
|
+
: _spinLabel;
|
|
91
|
+
process.stdout.write(` ${c.brand(SPIN_FRAMES[_spinIdx++ % 4])} ${c.dim(displayLabel)} ${c.dim('(' + fmtElapsed(ms) + ')')}`);
|
|
95
92
|
}, 100);
|
|
96
93
|
}
|
|
97
94
|
|
|
@@ -712,7 +709,7 @@ async function startChat(opts = {}) {
|
|
|
712
709
|
console.log(c.ok(' ◉') + c.muted(' Agent mode ') + c.dim('· file web shell image prior-network'));
|
|
713
710
|
|
|
714
711
|
console.log(DIVIDER);
|
|
715
|
-
console.log(c.muted(' /help /clear /compact /censored /uncensored /exit'));
|
|
712
|
+
console.log(c.muted(' /help /clear /compact /timer /censored /uncensored /exit'));
|
|
716
713
|
console.log(DIVIDER);
|
|
717
714
|
console.log('');
|
|
718
715
|
|
|
@@ -730,6 +727,7 @@ async function startChat(opts = {}) {
|
|
|
730
727
|
|
|
731
728
|
const SLASH_CMDS = [
|
|
732
729
|
{ cmd: '/compact', desc: 'Compact conversation to save context' },
|
|
730
|
+
{ cmd: '/timer', desc: 'Set a countdown timer e.g. /timer 30s' },
|
|
733
731
|
{ cmd: '/help', desc: 'Show help' },
|
|
734
732
|
{ cmd: '/clear', desc: 'Clear screen' },
|
|
735
733
|
{ cmd: '/censored', desc: 'Load standard model (qwen)' },
|
|
@@ -1167,10 +1165,67 @@ Be concise but thorough — this summary replaces the full history to save conte
|
|
|
1167
1165
|
return loop();
|
|
1168
1166
|
}
|
|
1169
1167
|
|
|
1168
|
+
case '/timer': {
|
|
1169
|
+
const timerArg = args.join(' ').trim();
|
|
1170
|
+
// Parse duration: e.g. 30, 30s, 5m, 1m30s, 1h
|
|
1171
|
+
const parseDuration = (str) => {
|
|
1172
|
+
if (!str) return null;
|
|
1173
|
+
let total = 0;
|
|
1174
|
+
const re = /(\d+(?:\.\d+)?)\s*([hms]?)/gi;
|
|
1175
|
+
let m, matched = false;
|
|
1176
|
+
while ((m = re.exec(str)) !== null) {
|
|
1177
|
+
const val = parseFloat(m[1]);
|
|
1178
|
+
const unit = (m[2] || 's').toLowerCase();
|
|
1179
|
+
if (unit === 'h') total += val * 3600;
|
|
1180
|
+
else if (unit === 'm') total += val * 60;
|
|
1181
|
+
else total += val;
|
|
1182
|
+
matched = true;
|
|
1183
|
+
}
|
|
1184
|
+
return matched ? Math.round(total) : null;
|
|
1185
|
+
};
|
|
1186
|
+
const fmtCountdown = (sec) => {
|
|
1187
|
+
const h = Math.floor(sec / 3600);
|
|
1188
|
+
const m = Math.floor((sec % 3600) / 60);
|
|
1189
|
+
const s = sec % 60;
|
|
1190
|
+
if (h > 0) return `${h}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`;
|
|
1191
|
+
return `${m > 0 ? m + ':' : ''}${m > 0 ? String(s).padStart(2,'0') : s + 's'}`;
|
|
1192
|
+
};
|
|
1193
|
+
const totalSec = parseDuration(timerArg);
|
|
1194
|
+
if (!totalSec || totalSec <= 0) {
|
|
1195
|
+
console.log(c.err(' Usage: /timer 30s or /timer 5m or /timer 1m30s\n'));
|
|
1196
|
+
return loop();
|
|
1197
|
+
}
|
|
1198
|
+
console.log(c.brand(` Timer set for ${timerArg} — starting now.\n`));
|
|
1199
|
+
let remaining = totalSec;
|
|
1200
|
+
const timerInterval = setInterval(() => {
|
|
1201
|
+
if (process.stdout.isTTY) {
|
|
1202
|
+
process.stdout.clearLine(0);
|
|
1203
|
+
process.stdout.cursorTo(0);
|
|
1204
|
+
}
|
|
1205
|
+
if (remaining <= 0) {
|
|
1206
|
+
clearInterval(timerInterval);
|
|
1207
|
+
if (process.stdout.isTTY) {
|
|
1208
|
+
process.stdout.clearLine(0);
|
|
1209
|
+
process.stdout.cursorTo(0);
|
|
1210
|
+
}
|
|
1211
|
+
// Bell + done message
|
|
1212
|
+
process.stdout.write('\x07');
|
|
1213
|
+
console.log(c.bold(` ⏰ Time's up! (${timerArg})\n`));
|
|
1214
|
+
rl.prompt(true);
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
const bar = '█'.repeat(Math.ceil((remaining / totalSec) * 20)).padEnd(20, '░');
|
|
1218
|
+
process.stdout.write(` ${c.brand('⏱')} ${c.brand(fmtCountdown(remaining).padStart(6))} ${c.dim(bar)}`);
|
|
1219
|
+
remaining--;
|
|
1220
|
+
}, 1000);
|
|
1221
|
+
return loop();
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1170
1224
|
case '/help':
|
|
1171
1225
|
console.log('');
|
|
1172
1226
|
console.log(c.bold(' Commands'));
|
|
1173
1227
|
console.log(c.muted(' /compact ') + 'Compact conversation to save context');
|
|
1228
|
+
console.log(c.muted(' /timer <duration> ') + 'Countdown timer e.g. /timer 30s, /timer 5m');
|
|
1174
1229
|
console.log(c.muted(' /clear ') + 'Clear screen');
|
|
1175
1230
|
console.log(c.muted(' /censored ') + 'Load standard model (qwen)');
|
|
1176
1231
|
console.log(c.muted(' /uncensored ') + 'Load uncensored model (dolphin)');
|