gent-cli 13.0.0 β 14.0.0
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/commands/login.js +4 -0
- package/src/commands/pet.js +48 -15
- package/src/commands/register.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gent-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.0.0",
|
|
4
4
|
"description": "A modern, Git-like version control CLI with cloud sync, AI-powered superpowers (ask/review/docs/changelog), and zero-friction setup (gent setup/doctor/config).",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/commands/login.js
CHANGED
|
@@ -8,12 +8,14 @@ const inquirer = require('inquirer');
|
|
|
8
8
|
const ora = require('ora');
|
|
9
9
|
const boxen = require('boxen');
|
|
10
10
|
const authService = require('../services/auth-service');
|
|
11
|
+
const pet = require('./pet');
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Login user
|
|
14
15
|
* @param {Object} options - Command options
|
|
15
16
|
*/
|
|
16
17
|
async function login(options) {
|
|
18
|
+
pet.banner('Knock knock β let\'s sign you in.', 'Enter your details below.');
|
|
17
19
|
console.log(chalk.cyan('\nπ Login to your Gent account\n'));
|
|
18
20
|
|
|
19
21
|
try {
|
|
@@ -75,6 +77,8 @@ ${chalk.bold('Commands:')}
|
|
|
75
77
|
borderColor: 'cyan'
|
|
76
78
|
}));
|
|
77
79
|
|
|
80
|
+
await pet.celebrate('auth');
|
|
81
|
+
|
|
78
82
|
} catch (error) {
|
|
79
83
|
console.error(chalk.red('\nβ Login failed'));
|
|
80
84
|
console.error(chalk.red(`Error: ${error.message}\n`));
|
package/src/commands/pet.js
CHANGED
|
@@ -379,25 +379,35 @@ const SCENES = {
|
|
|
379
379
|
const HIDE = '\x1b[?25l';
|
|
380
380
|
const SHOW = '\x1b[?25h';
|
|
381
381
|
const CLEAR_LINE = '\x1b[2K';
|
|
382
|
+
const HOME = '\x1b[H';
|
|
383
|
+
const ENTER_ALT = '\x1b[?1049h'; // switch to the alternate screen buffer
|
|
384
|
+
const LEAVE_ALT = '\x1b[?1049l'; // β¦and restore the user's scrollback on exit
|
|
382
385
|
const up = (n) => `\x1b[${n}A`;
|
|
383
386
|
|
|
384
387
|
/**
|
|
385
|
-
* Play a scene.
|
|
386
|
-
*
|
|
388
|
+
* Play a scene. Resolves when finished.
|
|
389
|
+
*
|
|
390
|
+
* Two redraw strategies:
|
|
391
|
+
* - altScreen:true β take over the whole screen (alternate buffer), redraw
|
|
392
|
+
* from HOME each frame, restore on exit. Zero scrollback drift. Used by the
|
|
393
|
+
* standalone `gent pet` command.
|
|
394
|
+
* - altScreen:false β inline redraw below existing output via cursor-up, so a
|
|
395
|
+
* command's own text stays visible above. Used by post-command celebrations.
|
|
387
396
|
*
|
|
388
397
|
* @param {string} sceneName
|
|
389
398
|
* @param {object} opts
|
|
390
|
-
* @param {boolean} opts.loop
|
|
391
|
-
* @param {boolean} opts.footer
|
|
392
|
-
* @param {boolean} opts.goodbye
|
|
399
|
+
* @param {boolean} opts.loop keep looping until Ctrl+C (default: play once)
|
|
400
|
+
* @param {boolean} opts.footer show the hint line under the stage
|
|
401
|
+
* @param {boolean} opts.goodbye print a farewell line when done
|
|
402
|
+
* @param {boolean} opts.altScreen use the alternate screen buffer
|
|
393
403
|
* @returns {Promise<void>}
|
|
394
404
|
*/
|
|
395
|
-
function play(sceneName, { loop = false, footer = true, goodbye = false } = {}) {
|
|
405
|
+
function play(sceneName, { loop = false, footer = true, goodbye = false, altScreen = false, maxTicks = Infinity } = {}) {
|
|
396
406
|
return new Promise((resolve) => {
|
|
397
407
|
const scene = SCENES[sceneName] || SCENES.idle;
|
|
398
408
|
const cv = new Canvas(CV_W, CV_H);
|
|
399
409
|
const state = { count: 0, tip: TIPS[Math.floor(Math.random() * TIPS.length)] };
|
|
400
|
-
const totalTicks = loop ? Infinity : scene.cycle + 1; // one clean cycle
|
|
410
|
+
const totalTicks = loop ? Infinity : Math.min(scene.cycle + 1, maxTicks); // one clean cycle, capped
|
|
401
411
|
let t = 0;
|
|
402
412
|
let printed = false;
|
|
403
413
|
let done = false;
|
|
@@ -408,7 +418,6 @@ function play(sceneName, { loop = false, footer = true, goodbye = false } = {})
|
|
|
408
418
|
chalk.gray(' Β· more scenes: ') + C.say('gent pet push|pull|merge')
|
|
409
419
|
: '';
|
|
410
420
|
|
|
411
|
-
// Draw one frame, moving the cursor back over the previous frame.
|
|
412
421
|
const paint = () => {
|
|
413
422
|
cv.clear();
|
|
414
423
|
scene.fn(cv, t, state);
|
|
@@ -418,8 +427,12 @@ function play(sceneName, { loop = false, footer = true, goodbye = false } = {})
|
|
|
418
427
|
const lines = cv.render().split('\n');
|
|
419
428
|
lines.push(footerLine());
|
|
420
429
|
const block = lines.map(l => CLEAR_LINE + l).join('\n');
|
|
421
|
-
if (
|
|
422
|
-
|
|
430
|
+
if (altScreen) {
|
|
431
|
+
process.stdout.write(HOME + block);
|
|
432
|
+
} else {
|
|
433
|
+
if (printed) process.stdout.write(up(lines.length));
|
|
434
|
+
process.stdout.write(block + '\n');
|
|
435
|
+
}
|
|
423
436
|
printed = true;
|
|
424
437
|
};
|
|
425
438
|
|
|
@@ -428,7 +441,7 @@ function play(sceneName, { loop = false, footer = true, goodbye = false } = {})
|
|
|
428
441
|
done = true;
|
|
429
442
|
clearInterval(timer);
|
|
430
443
|
process.removeListener('SIGINT', onSig);
|
|
431
|
-
process.stdout.write(SHOW);
|
|
444
|
+
process.stdout.write(SHOW + (altScreen ? LEAVE_ALT : ''));
|
|
432
445
|
if (goodbye) {
|
|
433
446
|
console.log(C.body(' Genti waves.') + chalk.gray(' Come back with ') + C.say('gent pet') + chalk.gray('.'));
|
|
434
447
|
}
|
|
@@ -437,7 +450,7 @@ function play(sceneName, { loop = false, footer = true, goodbye = false } = {})
|
|
|
437
450
|
|
|
438
451
|
const onSig = () => finish();
|
|
439
452
|
|
|
440
|
-
process.stdout.write(HIDE);
|
|
453
|
+
process.stdout.write((altScreen ? ENTER_ALT + HOME : '') + HIDE);
|
|
441
454
|
paint();
|
|
442
455
|
const timer = setInterval(() => {
|
|
443
456
|
t++;
|
|
@@ -448,6 +461,22 @@ function play(sceneName, { loop = false, footer = true, goodbye = false } = {})
|
|
|
448
461
|
});
|
|
449
462
|
}
|
|
450
463
|
|
|
464
|
+
/**
|
|
465
|
+
* A compact STATIC Genti header β safe to print above an interactive prompt
|
|
466
|
+
* (inquirer, etc.) because it never animates or moves the cursor.
|
|
467
|
+
* @param {string} greeting bold line beside the mascot
|
|
468
|
+
* @param {string} [sub] dimmer line under the greeting
|
|
469
|
+
*/
|
|
470
|
+
function banner(greeting, sub) {
|
|
471
|
+
if (process.env.GENT_NO_PET || !process.stdout.isTTY) return;
|
|
472
|
+
const cv = new Canvas(52, 9);
|
|
473
|
+
cv.sprite(mascot({}), 1, 0);
|
|
474
|
+
cv.sprite(legs('stand'), 1, 7);
|
|
475
|
+
cv.text(18, 2, greeting, C.body);
|
|
476
|
+
if (sub) cv.text(18, 4, sub, C.say);
|
|
477
|
+
console.log('\n' + cv.render());
|
|
478
|
+
}
|
|
479
|
+
|
|
451
480
|
// Static single frame for non-TTY (piped) output.
|
|
452
481
|
function still(sceneName) {
|
|
453
482
|
const cv = new Canvas(CV_W, CV_H);
|
|
@@ -476,8 +505,9 @@ async function petCommand(scene, options = {}) {
|
|
|
476
505
|
}
|
|
477
506
|
|
|
478
507
|
if (!process.stdout.isTTY) return still(name);
|
|
479
|
-
// Default: play once
|
|
480
|
-
|
|
508
|
+
// Default: play once, on the alternate screen so nothing pollutes scrollback.
|
|
509
|
+
// `--loop` keeps it running until Ctrl+C.
|
|
510
|
+
await play(name, { loop: !!options.loop, footer: true, goodbye: true, altScreen: true });
|
|
481
511
|
}
|
|
482
512
|
|
|
483
513
|
/**
|
|
@@ -492,9 +522,12 @@ async function celebrate(scene) {
|
|
|
492
522
|
if (process.env.GENT_NO_PET || process.env.CI) return;
|
|
493
523
|
if (!SCENES[scene]) return;
|
|
494
524
|
console.log(); // one blank line between command output and Genti
|
|
495
|
-
|
|
525
|
+
// Auth flows just need a quick friendly wave; action scenes tell a fuller story.
|
|
526
|
+
const maxTicks = (scene === 'auth' || scene === 'login') ? 34 : Infinity;
|
|
527
|
+
await play(scene, { loop: false, footer: false, goodbye: false, maxTicks });
|
|
496
528
|
} catch (_) { /* ignore β decoration only */ }
|
|
497
529
|
}
|
|
498
530
|
|
|
499
531
|
module.exports = petCommand;
|
|
500
532
|
module.exports.celebrate = celebrate;
|
|
533
|
+
module.exports.banner = banner;
|
package/src/commands/register.js
CHANGED
|
@@ -8,12 +8,14 @@ const inquirer = require('inquirer');
|
|
|
8
8
|
const ora = require('ora');
|
|
9
9
|
const boxen = require('boxen');
|
|
10
10
|
const authService = require('../services/auth-service');
|
|
11
|
+
const pet = require('./pet');
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Register a new user
|
|
14
15
|
* @param {Object} options - Command options
|
|
15
16
|
*/
|
|
16
17
|
async function register(options) {
|
|
18
|
+
pet.banner('New here? Let\'s get you set up.', 'Create your account below.');
|
|
17
19
|
console.log(chalk.cyan('\nπ Create your Gent account\n'));
|
|
18
20
|
|
|
19
21
|
try {
|
|
@@ -120,6 +122,8 @@ ${chalk.bold('Next steps:')}
|
|
|
120
122
|
borderColor: 'green'
|
|
121
123
|
}));
|
|
122
124
|
|
|
125
|
+
await pet.celebrate('auth');
|
|
126
|
+
|
|
123
127
|
} catch (error) {
|
|
124
128
|
console.error(chalk.red('\nβ Registration failed'));
|
|
125
129
|
console.error(chalk.red(`Error: ${error.message}\n`));
|