groundcrew-cli 0.15.16 → 0.15.17

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/dist/index.js CHANGED
@@ -443,8 +443,12 @@ function readMultilineInput(sessionId) {
443
443
  const buf = [];
444
444
  if (lastTermRow > 0) buf.push(`\x1B[${lastTermRow}A`);
445
445
  buf.push("\r\x1B[J");
446
+ const termW = process.stdout.columns || 80;
447
+ const info = ` ${sessionId} `;
448
+ const dashRight = "\u2500".repeat(Math.max(0, termW - 4 - info.length));
449
+ buf.push(dim("\u2500\u2500\u2500" + info + dashRight));
446
450
  for (let i = 0; i < lines.length; i++) {
447
- if (i > 0) buf.push("\n");
451
+ buf.push("\n");
448
452
  if (i === 0) {
449
453
  buf.push(dim(`[${sessionId}]`) + " " + bold(">") + " " + lines[i]);
450
454
  } else {
@@ -457,7 +461,7 @@ function readMultilineInput(sessionId) {
457
461
  buf.push("\r");
458
462
  const col = padWidth + ccol;
459
463
  if (col > 0) buf.push(`\x1B[${col}C`);
460
- lastTermRow = crow;
464
+ lastTermRow = 1 + crow;
461
465
  process.stdout.write(buf.join(""));
462
466
  };
463
467
  const finish = (result) => {
@@ -606,11 +610,12 @@ function readMultilineInput(sessionId) {
606
610
  continue;
607
611
  }
608
612
  if (str[i] === "") {
609
- if (fullText()) {
613
+ const hasText = fullText();
614
+ if (hasText || lines.length > 1 || lines[0].length > 0) {
610
615
  const lastRow = lines.length - 1;
611
616
  const rowsDown = lastRow - crow;
612
617
  if (rowsDown > 0) process.stdout.write(`\x1B[${rowsDown}B`);
613
- process.stdout.write("\n");
618
+ process.stdout.write("\r\n");
614
619
  lines.length = 0;
615
620
  lines.push("");
616
621
  crow = 0;
@@ -618,7 +623,7 @@ function readMultilineInput(sessionId) {
618
623
  lastTermRow = 0;
619
624
  render();
620
625
  } else {
621
- process.stdout.write("\n");
626
+ process.stdout.write("\r\n");
622
627
  finish(null);
623
628
  return;
624
629
  }
@@ -687,8 +692,10 @@ function readMultilineInput(sessionId) {
687
692
  continue;
688
693
  }
689
694
  if (str[i] === " ") {
690
- if (lines.length === 1 && lines[0].startsWith("/")) {
691
- const matches = CHAT_COMMANDS.filter((c) => c.cmd.startsWith(lines[0]));
695
+ const currentLine = lines[crow];
696
+ if (lines.length === 1 && currentLine.startsWith("/")) {
697
+ const partial = currentLine.split(" ")[0];
698
+ const matches = CHAT_COMMANDS.filter((c) => c.cmd.startsWith(partial));
692
699
  if (matches.length === 1) {
693
700
  lines[0] = matches[0].cmd + " ";
694
701
  ccol = lines[0].length;
@@ -697,7 +704,7 @@ function readMultilineInput(sessionId) {
697
704
  const lastRow = lines.length - 1;
698
705
  const rowsDown = lastRow - crow;
699
706
  if (rowsDown > 0) process.stdout.write(`\x1B[${rowsDown}B`);
700
- process.stdout.write("\n");
707
+ process.stdout.write("\r\n");
701
708
  for (const m of matches) {
702
709
  process.stdout.write(` ${cyan(m.cmd.padEnd(14))} ${dim(m.desc)}
703
710
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groundcrew-cli",
3
- "version": "0.15.16",
3
+ "version": "0.15.17",
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
@@ -587,7 +587,7 @@ function readMultilineInput(sessionId: string): Promise<string | null> {
587
587
  // Visible width of prompt: "[sessionId] > "
588
588
  const padWidth = sessionId.length + 5; // [ + id + ] + space + > + space = len+5
589
589
 
590
- // Track which terminal row the cursor was on after last render
590
+ // Track how many rows up from cursor to top of rendered area (including separator)
591
591
  let lastTermRow = 0;
592
592
  let pasteBuffer = "";
593
593
  let isPasting = false;
@@ -597,13 +597,19 @@ function readMultilineInput(sessionId: string): Promise<string | null> {
597
597
  const render = () => {
598
598
  const buf: string[] = [];
599
599
 
600
- // Move to start of input area
600
+ // Move to start of input area (includes separator line)
601
601
  if (lastTermRow > 0) buf.push(`\x1b[${lastTermRow}A`);
602
602
  buf.push("\r\x1b[J"); // col 0 + clear to end of screen
603
603
 
604
- // Draw each line
604
+ // Separator line: ─── sessionId ─────────
605
+ const termW = process.stdout.columns || 80;
606
+ const info = ` ${sessionId} `;
607
+ const dashRight = "─".repeat(Math.max(0, termW - 4 - info.length));
608
+ buf.push(dim("───" + info + dashRight));
609
+
610
+ // Draw each input line (below separator)
605
611
  for (let i = 0; i < lines.length; i++) {
606
- if (i > 0) buf.push("\n");
612
+ buf.push("\n");
607
613
  if (i === 0) {
608
614
  buf.push(dim(`[${sessionId}]`) + " " + bold(">") + " " + lines[i]);
609
615
  } else {
@@ -620,7 +626,9 @@ function readMultilineInput(sessionId: string): Promise<string | null> {
620
626
  const col = padWidth + ccol;
621
627
  if (col > 0) buf.push(`\x1b[${col}C`);
622
628
 
623
- lastTermRow = crow;
629
+ // lastTermRow = rows from cursor back to top of separator
630
+ // separator is 1 row, then crow rows of input below it
631
+ lastTermRow = 1 + crow;
624
632
  process.stdout.write(buf.join(""));
625
633
  };
626
634
 
@@ -752,17 +760,18 @@ function readMultilineInput(sessionId: string): Promise<string | null> {
752
760
 
753
761
  // Ctrl+C — clear input or exit
754
762
  if (str[i] === "\x03") {
755
- if (fullText()) {
756
- // Move past current rendering, start fresh below
763
+ const hasText = fullText();
764
+ if (hasText || lines.length > 1 || lines[0].length > 0) {
765
+ // Move past current rendering to below last line, start fresh
757
766
  const lastRow = lines.length - 1;
758
767
  const rowsDown = lastRow - crow;
759
768
  if (rowsDown > 0) process.stdout.write(`\x1b[${rowsDown}B`);
760
- process.stdout.write("\n");
769
+ process.stdout.write("\r\n");
761
770
  lines.length = 0; lines.push("");
762
771
  crow = 0; ccol = 0; lastTermRow = 0;
763
772
  render();
764
773
  } else {
765
- process.stdout.write("\n");
774
+ process.stdout.write("\r\n");
766
775
  finish(null); return;
767
776
  }
768
777
  i++; continue;
@@ -807,8 +816,10 @@ function readMultilineInput(sessionId: string): Promise<string | null> {
807
816
 
808
817
  // Tab — slash command completion
809
818
  if (str[i] === "\t") {
810
- if (lines.length === 1 && lines[0].startsWith("/")) {
811
- const matches = CHAT_COMMANDS.filter(c => c.cmd.startsWith(lines[0]));
819
+ const currentLine = lines[crow];
820
+ if (lines.length === 1 && currentLine.startsWith("/")) {
821
+ const partial = currentLine.split(" ")[0]; // only match command part
822
+ const matches = CHAT_COMMANDS.filter(c => c.cmd.startsWith(partial));
812
823
  if (matches.length === 1) {
813
824
  lines[0] = matches[0].cmd + " ";
814
825
  ccol = lines[0].length; render();
@@ -817,7 +828,7 @@ function readMultilineInput(sessionId: string): Promise<string | null> {
817
828
  const lastRow = lines.length - 1;
818
829
  const rowsDown = lastRow - crow;
819
830
  if (rowsDown > 0) process.stdout.write(`\x1b[${rowsDown}B`);
820
- process.stdout.write("\n");
831
+ process.stdout.write("\r\n");
821
832
  for (const m of matches) {
822
833
  process.stdout.write(` ${cyan(m.cmd.padEnd(14))} ${dim(m.desc)}\n`);
823
834
  }