groundcrew-cli 0.14.1 → 0.15.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.
Files changed (3) hide show
  1. package/dist/index.js +13 -19
  2. package/package.json +1 -1
  3. package/src/index.ts +16 -23
package/dist/index.js CHANGED
@@ -415,35 +415,29 @@ function chatCompleter(line) {
415
415
  return [[], line];
416
416
  }
417
417
  function setupInlineSuggestions(rl) {
418
- let lastGhostLen = 0;
418
+ let hasGhost = false;
419
419
  const clearGhost = () => {
420
- if (lastGhostLen > 0) {
421
- process.stdout.write("\x1B[" + lastGhostLen + "D");
422
- process.stdout.write("\x1B[0K");
423
- lastGhostLen = 0;
420
+ if (hasGhost) {
421
+ process.stdout.write("\x1B[u\x1B[K");
422
+ hasGhost = false;
424
423
  }
425
424
  };
426
425
  const showGhost = () => {
427
426
  const line = rl.line;
428
427
  if (!line || !line.startsWith("/") || line.includes(" ")) {
429
- clearGhost();
430
428
  return;
431
429
  }
432
430
  const matches = CHAT_COMMANDS.filter((c) => c.cmd.startsWith(line));
433
- if (matches.length === 0) {
434
- clearGhost();
435
- return;
436
- }
431
+ if (matches.length === 0) return;
437
432
  const best = matches[0];
438
- const ghost = best.cmd.slice(line.length);
439
- const hint = ghost + dim(` \u2014 ${best.desc}`);
440
- const rawLen = ghost.length + ` \u2014 ${best.desc}`.length;
441
- clearGhost();
442
- if (ghost || matches.length > 0) {
443
- process.stdout.write(`\x1B[2m${ghost} \u2014 ${best.desc}\x1B[0m`);
444
- lastGhostLen = rawLen;
445
- process.stdout.write("\x1B[" + rawLen + "D");
446
- }
433
+ const remainder = best.cmd.slice(line.length);
434
+ if (!remainder && matches.length === 1) return;
435
+ const ghost = `${remainder} \u2014 ${best.desc}`;
436
+ process.stdout.write("\x1B[s");
437
+ process.stdout.write("\x1B[K");
438
+ process.stdout.write(`\x1B[2m${ghost}\x1B[0m`);
439
+ process.stdout.write("\x1B[u");
440
+ hasGhost = true;
447
441
  };
448
442
  process.stdin.on("keypress", (_ch, key) => {
449
443
  if (!key) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groundcrew-cli",
3
- "version": "0.14.1",
3
+ "version": "0.15.0",
4
4
  "description": "CLI companion for Groundcrew — queue tasks, send feedback, monitor your Copilot agent from another terminal.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -544,44 +544,37 @@ function chatCompleter(line: string): [string[], string] {
544
544
  * Renders dimmed text after cursor, erased on next keystroke.
545
545
  */
546
546
  function setupInlineSuggestions(rl: readline.Interface): void {
547
- let lastGhostLen = 0;
547
+ let hasGhost = false;
548
548
 
549
549
  const clearGhost = () => {
550
- if (lastGhostLen > 0) {
551
- // Move cursor back to end of typed text, clear ghost
552
- process.stdout.write("\x1b[" + lastGhostLen + "D");
553
- process.stdout.write("\x1b[0K");
554
- lastGhostLen = 0;
550
+ if (hasGhost) {
551
+ // Restore cursor to where user was typing, clear everything after
552
+ process.stdout.write("\x1b[u\x1b[K");
553
+ hasGhost = false;
555
554
  }
556
555
  };
557
556
 
558
557
  const showGhost = () => {
559
558
  const line = (rl as any).line as string;
560
559
  if (!line || !line.startsWith("/") || line.includes(" ")) {
561
- clearGhost();
562
560
  return;
563
561
  }
564
562
 
565
563
  const matches = CHAT_COMMANDS.filter((c) => c.cmd.startsWith(line));
566
- if (matches.length === 0) {
567
- clearGhost();
568
- return;
569
- }
564
+ if (matches.length === 0) return;
570
565
 
571
- // Show best match as ghost
572
566
  const best = matches[0];
573
- const ghost = best.cmd.slice(line.length);
574
- const hint = ghost + dim(` — ${best.desc}`);
575
- const rawLen = ghost.length + ` — ${best.desc}`.length;
567
+ const remainder = best.cmd.slice(line.length);
568
+ if (!remainder && matches.length === 1) return;
576
569
 
577
- clearGhost();
578
- if (ghost || matches.length > 0) {
579
- // Write dimmed ghost text
580
- process.stdout.write(`\x1b[2m${ghost} — ${best.desc}\x1b[0m`);
581
- // Move cursor back to where user is typing
582
- lastGhostLen = rawLen;
583
- process.stdout.write("\x1b[" + rawLen + "D");
584
- }
570
+ const ghost = `${remainder} \u2014 ${best.desc}`;
571
+
572
+ // Save cursor, write dimmed ghost, restore cursor
573
+ process.stdout.write("\x1b[s"); // save cursor position
574
+ process.stdout.write("\x1b[K"); // clear to end of line (remove old ghost)
575
+ process.stdout.write(`\x1b[2m${ghost}\x1b[0m`); // write dimmed ghost
576
+ process.stdout.write("\x1b[u"); // restore cursor to typing position
577
+ hasGhost = true;
585
578
  };
586
579
 
587
580
  // Listen to keypresses