From 192c3edbff4ac0d95d4616b51e9fc0357cb71923 Mon Sep 17 00:00:00 2001 From: Aakash Kattelu Date: Mon, 10 Aug 2026 14:07:52 -0400 Subject: [PATCH] docs(cli): regenerate command reference for `session view` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the generated `session view` accordion to the docs snippet and points the session-debugging workflows at it. Trims the docstring to plain prose — the RST double-backticks were rendering literally in `--help`, where every other command uses unmarked flag names — and stops the generator emitting a trailing blank line that tripped end-of-file-fixer on every regeneration. Co-Authored-By: Claude Opus 5 --- docs/snippets/cli-commands.mdx | 44 ++++++++++++++++++- docs/v3/documentation/reference/cli.mdx | 6 +-- honcho-cli/scripts/generate_cli_docs.py | 2 +- honcho-cli/src/honcho_cli/commands/message.py | 5 +-- honcho-cli/src/honcho_cli/commands/session.py | 32 ++++++-------- honcho-cli/src/honcho_cli/output.py | 19 +++----- honcho-cli/tests/test_commands.py | 2 +- 7 files changed, 69 insertions(+), 41 deletions(-) diff --git a/docs/snippets/cli-commands.mdx b/docs/snippets/cli-commands.mdx index 4eb9d2d3..800d45a7 100644 --- a/docs/snippets/cli-commands.mdx +++ b/docs/snippets/cli-commands.mdx @@ -305,7 +305,7 @@ honcho peer set-metadata ## honcho session -List, inspect, create, delete, and manage conversation sessions and their peers. +List, inspect, view, create, delete, and manage conversation sessions and their peers. @@ -461,6 +461,48 @@ honcho session summaries [] + +View a session transcript as a chat log. + +Modes (pick one): + +- default / --last N: tail of the conversation (most recent N) +- --page N [--size M]: page through the full transcript +- --all: every message + +Paging follows the requested order: --page 1 starts at the oldest message, +or the newest with --reverse. + +Human mode prints a row-delimited table. JSON mode emits the message list +(same shape as message list). + +```bash +honcho session view [] +``` + + + + Show only the N most recent messages (default when no --page/--all: 50). + + + 1-indexed page of the full transcript. Use for page 2+. + + + Messages per page; requires --page (1-100, default: 50). + + + Show the full transcript (every page). + + + Newest first (default is chronological: oldest at top). + + + Include message IDs in the transcript. + + + Filter by peer ID. Short alias: `-p`. + + ## honcho workspace diff --git a/docs/v3/documentation/reference/cli.mdx b/docs/v3/documentation/reference/cli.mdx index 7b89bfeb..2b460d48 100644 --- a/docs/v3/documentation/reference/cli.mdx +++ b/docs/v3/documentation/reference/cli.mdx @@ -142,7 +142,7 @@ When you pick up a workspace and need to orient — start broad, narrow to the p ```bash honcho session inspect --json - honcho message list --last 20 --json + honcho session view --last 20 honcho session context --json honcho session summaries --json ``` @@ -150,7 +150,7 @@ When you pick up a workspace and need to orient — start broad, narrow to the p - `honcho session context` shows exactly what an agent would receive at inference time — check it before `honcho peer chat` if a response surprises you. + `honcho session context` shows exactly what an agent would receive at inference time — check it before `honcho peer chat` if a response surprises you. `honcho session view` shows the raw transcript that context was built from; it prints content verbatim, so tag-delimited and multi-line messages appear exactly as stored. ### A peer isn't learning @@ -176,7 +176,7 @@ When an agent's responses don't reflect what you expect it to know. ```bash honcho session context --json honcho session summaries --json -honcho message list --last 50 --json +honcho session view --last 50 ``` ### Dialectic returns bad answers diff --git a/honcho-cli/scripts/generate_cli_docs.py b/honcho-cli/scripts/generate_cli_docs.py index 8fa4e223..a632b069 100644 --- a/honcho-cli/scripts/generate_cli_docs.py +++ b/honcho-cli/scripts/generate_cli_docs.py @@ -230,7 +230,7 @@ def build() -> str: body: list[str] = [] for name in sorted(root.commands): body.extend(_render_top(root.commands[name], ["honcho", name])) - return HEADER + "\n".join(body) + "\n" + return HEADER + "\n".join(body).rstrip("\n") + "\n" def main() -> int: diff --git a/honcho-cli/src/honcho_cli/commands/message.py b/honcho-cli/src/honcho_cli/commands/message.py index 2742556c..40aa83af 100644 --- a/honcho-cli/src/honcho_cli/commands/message.py +++ b/honcho-cli/src/honcho_cli/commands/message.py @@ -42,9 +42,8 @@ def list_messages( try: filters = {"peer_id": config.peer_id} if config.peer_id else None - # Fetch newest-first so we always get the most recent N messages — the - # shared helper walks pages, so --last above one page isn't truncated — - # then flip to oldest-at-top / newest-at-bottom for readable display. + # Fetch newest-first so we always get the most recent N messages, then + # flip to oldest-at-top / newest-at-bottom for readable display. # --reverse keeps the raw server order (oldest first, descending in table). msgs, _ = _fetch_recent_messages(sess, filters, last) if not reverse: diff --git a/honcho-cli/src/honcho_cli/commands/session.py b/honcho-cli/src/honcho_cli/commands/session.py index 861d4bb8..5f63f87c 100644 --- a/honcho-cli/src/honcho_cli/commands/session.py +++ b/honcho-cli/src/honcho_cli/commands/session.py @@ -136,8 +136,7 @@ def inspect( # Server-side ceiling on page size (fastapi-pagination's default ``Params`` -# declares ``size`` as ``Query(50, ge=1, le=100)``), enforced locally so an -# out-of-range --size is a CLI error rather than an opaque 422. +# declares ``size`` as ``Query(50, ge=1, le=100)``). MAX_PAGE_SIZE = 100 DEFAULT_PAGE_SIZE = 50 @@ -145,8 +144,7 @@ DEFAULT_PAGE_SIZE = 50 def _fetch_recent_messages(sess, filters: dict | None, last: int) -> tuple[list, int | None]: """Fetch the ``last`` most recent messages, newest first. - Walks as many newest-first server pages as it takes to fill the window, so - ``last`` above the page cap is honored instead of silently truncated. + Walks as many newest-first server pages as it takes to fill the window. Returns the messages plus the session's total message count (if reported). """ page = sess.messages( @@ -211,21 +209,20 @@ def view( Modes (pick one): - - default / ``--last N`` — tail of the conversation (most recent N) - - ``--page N [--size M]`` — page through the full transcript - - ``--all`` — every message + - default / --last N: tail of the conversation (most recent N) + - --page N [--size M]: page through the full transcript + - --all: every message - Paging follows the requested order: ``--page 1`` starts at the oldest - message, or the newest with ``--reverse``. + Paging follows the requested order: --page 1 starts at the oldest message, + or the newest with --reverse. Human mode prints a row-delimited table. JSON mode emits the message list - (same shape as ``message list``). + (same shape as message list). """ handle_cmd_flags(json_output=json_output, workspace=workspace, peer=peer, session=session) sid = _get_session_id(session_id) - # Validate every flag before touching the network, so a bad invocation never - # reaches the API. + # Validate every flag before touching the network. modes = sum([ last is not None, page_number is not None, @@ -256,14 +253,13 @@ def view( print_error("INVALID_FLAGS", "--last must be >= 1", {"last": last}) raise typer.Exit(1) - # Default: tail of conversation (most recent 50), matching prior behavior. + # Default: tail of conversation (most recent 50). mode = "page" if page_number is not None else ("all" if all_messages else "last") tail = last if last is not None else DEFAULT_PAGE_SIZE page_size = size if size is not None else DEFAULT_PAGE_SIZE client, config = get_client() - # Read-only: build the Session directly rather than via client.session(), - # which is a get-or-create POST and would create a session on a typo. + # Read-only: client.session() is a get-or-create POST, so build the Session directly. sess = Session(sid, client) try: @@ -272,8 +268,7 @@ def view( pages_meta: int | None = None if mode == "page": - # Page in the order the caller asked for, so --reverse --page 1 is - # the newest page rather than the oldest one displayed backwards. + # Page in the order the caller asked for. result_page = sess.messages( filters=filters, page=page_number, @@ -309,8 +304,7 @@ def view( _handle_error(e, "session", sid) raise # unreachable: _handle_error always exits - # Rendered outside the try so an output-side failure (e.g. a broken pipe - # from `| head`) isn't reported as a session API error. + # Rendered outside the try: output failures aren't session API errors. print_transcript( items, session_id=sid, diff --git a/honcho-cli/src/honcho_cli/output.py b/honcho-cli/src/honcho_cli/output.py index 5c141e28..39f9a2aa 100644 --- a/honcho-cli/src/honcho_cli/output.py +++ b/honcho-cli/src/honcho_cli/output.py @@ -126,11 +126,8 @@ TIMESTAMP_WIDTH = len("2026-01-01T00:00:00.000Z") def _format_timestamp(value: Any) -> str: """Compact UTC timestamp: ``YYYY-MM-DDTHH:MM:SS.mmmZ``. - Offsets are *converted* to UTC rather than dropped, so a non-UTC - ``created_at`` isn't relabelled as UTC. Naive values are assumed UTC, which - is what the API returns. Millisecond precision is kept so messages within - the same second stay distinguishable. Unparseable values pass through - verbatim. + Offsets are converted to UTC; naive values are assumed UTC. Unparseable + values pass through verbatim. """ if value is None: return "" @@ -161,8 +158,7 @@ def print_transcript( Each message dict must have ``peer_id``, ``content``, ``created_at``; ``id`` is optional and only shown when ``show_ids`` is set. ``size`` and - ``reverse`` are echoed back in the next-page hint so following it lands on - the adjacent window rather than a differently-sized one. + ``reverse`` are echoed back in the next-page hint. """ if use_json(): print_json(messages) @@ -193,8 +189,8 @@ def print_transcript( expand=True, pad_edge=False, ) - # time is fixed-width ISO-UTC; ids and peers wrap rather than truncate so a - # displayed ID is always a usable one; content takes the rest. + # time is fixed-width ISO-UTC; ids and peers wrap rather than truncate; + # content takes the rest. table.add_column("time", style="dim", no_wrap=True, width=TIMESTAMP_WIDTH) if show_ids: table.add_column("id", style="dim", no_wrap=True) @@ -207,10 +203,7 @@ def print_transcript( if peer not in peer_color: peer_color[peer] = _PEER_COLORS[len(peer_color) % len(_PEER_COLORS)] - # Content and IDs go through Text, not Markdown or console markup: this is - # a debugging view, so it must show exactly what was stored — Markdown - # would reflow newlines and swallow the ``-style tags that fill - # agent transcripts, and markup would eat bracketed text. + # Text, not Markdown or console markup: content renders verbatim. row: list[Any] = [_format_timestamp(msg.get("created_at"))] if show_ids: row.append(Text(str(msg.get("id") or ""))) diff --git a/honcho-cli/tests/test_commands.py b/honcho-cli/tests/test_commands.py index 64fbe2da..79b387b9 100644 --- a/honcho-cli/tests/test_commands.py +++ b/honcho-cli/tests/test_commands.py @@ -320,7 +320,7 @@ class TestJsonContract: @pytest.mark.parametrize( "args", [ - ["--size", "10"], # --size without --page would be silently ignored + ["--size", "10"], # --size requires --page ["--page", "1", "--size", "500"], # over the server's 100 ceiling ["--page", "0"], ["--last", "0"],