lewtun HF Staff OpenAI Codex commited on
Commit
fde34dc
Β·
unverified Β·
1 Parent(s): beb0c92

Align CLI help output (#248)

Browse files

* Align CLI help output

Co-authored-by: OpenAI Codex <codex@openai.com>

* Address CLI help review feedback

Co-authored-by: OpenAI Codex <codex@openai.com>

---------

Co-authored-by: OpenAI Codex <codex@openai.com>

agent/utils/terminal_display.py CHANGED
@@ -6,6 +6,7 @@ import asyncio
6
  import re
7
 
8
  from rich.console import Console
 
9
  from rich.markdown import Heading, Markdown
10
  from rich.panel import Panel
11
  from rich.theme import Theme
@@ -446,23 +447,72 @@ def print_yolo_approve(count: int) -> None:
446
 
447
  # ── Help ───────────────────────────────────────────────────────────────
448
 
449
- HELP_TEXT = f"""\
450
- {_I}[bold]Commands[/bold]
451
- {_I} [cyan]/help[/cyan] Show this help
452
- {_I} [cyan]/undo[/cyan] Undo last turn
453
- {_I} [cyan]/compact[/cyan] Compact context window
454
- {_I} [cyan]/resume[/cyan] [index|id|path] Pick up from a log in ./session_logs
455
- {_I} [cyan]/model[/cyan] [id] Show available models or switch
456
- {_I} [cyan]/effort[/cyan] [level] Reasoning effort (minimal|low|medium|high|xhigh|max|off)
457
- {_I} [cyan]/yolo[/cyan] Toggle auto-approve mode
458
- {_I} [cyan]/status[/cyan] Current model & turn count
459
- {_I} [cyan]/share-traces[/cyan] [public|private] Show/flip visibility of your HF trace dataset
460
- {_I} [cyan]/quit[/cyan] Exit"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
 
462
 
463
  def print_help() -> None:
464
  _console.print()
465
- _console.print(HELP_TEXT)
466
  _console.print()
467
 
468
 
 
6
  import re
7
 
8
  from rich.console import Console
9
+ from rich.markup import escape
10
  from rich.markdown import Heading, Markdown
11
  from rich.panel import Panel
12
  from rich.theme import Theme
 
447
 
448
  # ── Help ───────────────────────────────────────────────────────────────
449
 
450
+ HELP_ROWS: tuple[tuple[str, str, str], ...] = (
451
+ ("/help", "", "Show this help"),
452
+ ("/undo", "", "Undo last turn"),
453
+ ("/compact", "", "Compact context window"),
454
+ ("/resume", "[index|id|path]", "Pick up from ./session_logs"),
455
+ ("/model", "[id]", "Show available models or switch"),
456
+ (
457
+ "/effort",
458
+ "[level]",
459
+ "Set reasoning effort preference",
460
+ ),
461
+ ("/yolo", "", "Toggle auto-approve mode"),
462
+ ("/status", "", "Current model & turn count"),
463
+ (
464
+ "/share-traces",
465
+ "[public|private]",
466
+ "Show or change HF trace visibility",
467
+ ),
468
+ ("/quit", "", "Exit"),
469
+ )
470
+
471
+
472
+ def _help_column_widths(
473
+ rows: tuple[tuple[str, str, str], ...],
474
+ ) -> tuple[int, int]:
475
+ return (
476
+ max(len(command) for command, _, _ in rows),
477
+ max(len(args) for _, args, _ in rows),
478
+ )
479
+
480
+
481
+ def _format_help_row(
482
+ command: str,
483
+ args: str,
484
+ description: str,
485
+ command_width: int,
486
+ args_width: int,
487
+ ) -> str:
488
+ command_gap = " " * (command_width - len(command) + 2)
489
+ args_gap = " " * (args_width - len(args) + 2)
490
+ command_markup = f"[cyan]{escape(command)}[/cyan]"
491
+ args_markup = f"[muted]{escape(args)}[/muted]" if args else ""
492
+ return f"{_I} {command_markup}{command_gap}{args_markup}{args_gap}{description}"
493
+
494
+
495
+ def format_help_text(rows: tuple[tuple[str, str, str], ...] | None = None) -> str:
496
+ help_rows = HELP_ROWS if rows is None else rows
497
+ command_width, args_width = _help_column_widths(help_rows)
498
+ return "\n".join(
499
+ [f"{_I}[bold]Commands[/bold]"]
500
+ + [
501
+ _format_help_row(
502
+ command,
503
+ args,
504
+ description,
505
+ command_width,
506
+ args_width,
507
+ )
508
+ for command, args, description in help_rows
509
+ ]
510
+ )
511
 
512
 
513
  def print_help() -> None:
514
  _console.print()
515
+ _console.print(format_help_text())
516
  _console.print()
517
 
518
 
tests/unit/test_cli_rendering.py CHANGED
@@ -5,6 +5,7 @@ from io import StringIO
5
  from types import SimpleNamespace
6
 
7
  import pytest
 
8
 
9
  import agent.main as main_mod
10
  from agent.tools.research_tool import _get_research_model
@@ -29,6 +30,50 @@ def test_non_anthropic_research_model_is_unchanged():
29
  assert _get_research_model("openai/gpt-5.4") == "openai/gpt-5.4"
30
 
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  def test_subagent_display_does_not_spawn_background_redraw(monkeypatch):
33
  calls: list[object] = []
34
 
 
5
  from types import SimpleNamespace
6
 
7
  import pytest
8
+ from rich.console import Console
9
 
10
  import agent.main as main_mod
11
  from agent.tools.research_tool import _get_research_model
 
30
  assert _get_research_model("openai/gpt-5.4") == "openai/gpt-5.4"
31
 
32
 
33
+ def test_help_output_keeps_descriptions_aligned(monkeypatch):
34
+ output = StringIO()
35
+ console = Console(
36
+ file=output,
37
+ color_system=None,
38
+ theme=terminal_display._THEME,
39
+ width=120,
40
+ )
41
+ monkeypatch.setattr(terminal_display, "_console", console)
42
+
43
+ terminal_display.print_help()
44
+
45
+ lines = [line.rstrip() for line in output.getvalue().splitlines() if line.strip()]
46
+ description_columns = []
47
+ for command, args, description in terminal_display.HELP_ROWS:
48
+ line = next(line for line in lines if command in line)
49
+ if args:
50
+ assert args in line
51
+ description_columns.append(line.index(description))
52
+
53
+ assert len(set(description_columns)) == 1
54
+
55
+
56
+ def test_help_output_recomputes_widths_from_rows():
57
+ rows = terminal_display.HELP_ROWS + (
58
+ ("/longer-command", "[longer-args]", "Synthetic help row"),
59
+ )
60
+ output = StringIO()
61
+ Console(
62
+ file=output,
63
+ color_system=None,
64
+ theme=terminal_display._THEME,
65
+ width=140,
66
+ ).print(terminal_display.format_help_text(rows))
67
+
68
+ lines = [line.rstrip() for line in output.getvalue().splitlines() if line.strip()]
69
+ description_columns = [
70
+ next(line for line in lines if command in line).index(description)
71
+ for command, _args, description in rows
72
+ ]
73
+
74
+ assert len(set(description_columns)) == 1
75
+
76
+
77
  def test_subagent_display_does_not_spawn_background_redraw(monkeypatch):
78
  calls: list[object] = []
79