cli/session: session export Rich panels contaminate JSON stdout when no --output file specified #10503

Open
opened 2026-04-18 10:16:02 +00:00 by HAL9000 · 2 comments
Owner

Metadata

  • Commit message: fix(cli/session): suppress Rich panels on stdout when session export writes to stdout
  • Branch: fix/cli-session-export-json-stdout-contamination

Background and Context

agents session export <id> (default --format json, no --output file) outputs the raw JSON data to stdout and then immediately outputs Rich-formatted panels (with ANSI escape codes) to the same stdout. This contaminates the JSON output, making it unparseable by downstream tools and breaking automation workflows that rely on piping the export output to JSON parsers.

Expected Behavior

When agents session export <id> is run without --output:

  • stdout should contain only the raw JSON session data
  • Rich panels (Session Export, Contents, Integrity) should be printed to stderr OR suppressed

When agents session export <id> -o session.json is run with --output:

  • The JSON is written to the file
  • Rich panels can be shown on stdout (this is the correct behavior)

Acceptance Criteria

  • agents session export <id> (no --output) outputs only valid JSON to stdout — parseable by python3 -c "import json,sys; json.load(sys.stdin)"
  • No ANSI escape codes appear in stdout when writing to stdout mode
  • agents session export <id> -o file.json still shows Rich panels on stdout
  • The TDD tests from #10502 all pass after this fix is applied
  • No regression in other session subcommands

Subtasks

  • Locate export_session function in src/cleveragents/cli/commands/session.py
  • Move _render_export_panels() call inside the if output is not None: branch
  • Verify typer.echo(content) in the else: branch is NOT followed by any console.print() calls
  • Run the TDD tests from #10502 and confirm they pass
  • Run the full test suite (nox) to confirm no regressions

Code Evidence

File: src/cleveragents/cli/commands/session.py

The export_session function unconditionally calls _render_export_panels() after outputting JSON to stdout:

# In export_session():
else:
    json_data = service.export_session(session_id)
    content = json.dumps(json_data, indent=2, default=str)

if output is not None:
    # ... write to file ...
else:
    typer.echo(content)  # LINE ~517: Outputs JSON to stdout

# LINE ~522: ALWAYS calls _render_export_panels() - even when output is None (stdout mode)
_render_export_panels(
    session_id=session_id,
    output=output,
    content=content,
    export_data=json_data,
    fmt=fmt,
)

The _render_export_panels() function calls console.print() which outputs Rich-formatted text (with ANSI escape codes) to stdout. When output is None, this happens AFTER the JSON has been written to stdout, contaminating the output.

Actual Behavior

Running agents session export <id> produces stdout like:

{
  "session_id": "01HXYZ...",
  "messages": [...],
  ...
}
╭─ Session Export ─────────────────────────────────────────────────────────────╮
│ Session:  01HXYZ...                                                           │
│ Output:   (stdout)                                                            │
│ Messages: 5                                                                   │
│ Size:     2 KB                                                                │
│ Format:   JSON                                                                │
╰──────────────────────────────────────────────────────────────────────────────╯
...
✓ OK Export completed

The JSON is followed by Rich panel text with ANSI codes, making the entire output invalid JSON.

Reproduction Steps

  1. Create a session: agents session create
  2. Note the session ID
  3. Run: agents session export <session_id>
  4. Observe: JSON followed by Rich panels on stdout
  5. Try to parse: agents session export <session_id> | python3 -c "import json,sys; json.load(sys.stdin)" → JSONDecodeError

Impact

  • Any script that pipes session export output to a JSON parser will fail
  • The export command is specifically designed for machine-readable output (canonical, importable JSON)
  • This is a critical regression for automation workflows

Fix Path

In src/cleveragents/cli/commands/session.py, the _render_export_panels() call should only happen when writing to a file (not stdout):

if output is not None:
    # ... write to file ...
    output.write_text(content, encoding="utf-8")
    # Show panels when writing to file (stdout is free)
    _render_export_panels(
        session_id=session_id,
        output=output,
        content=content,
        export_data=json_data,
        fmt=fmt,
    )
else:
    typer.echo(content)
    # Do NOT call _render_export_panels() when writing to stdout
    # (panels would contaminate the JSON output)

Blocked By

Depends on TDD issue: #10502

Definition of Done

  • _render_export_panels() is only called when output is not None
  • agents session export <id> stdout is valid JSON (no panels, no ANSI codes)
  • TDD tests from #10502 pass
  • Full test suite passes with no regressions
  • Issue closed after fix is merged

Automated by CleverAgents Bot
Supervisor: Bug Hunt Pool | Agent: bug-hunt-pool-supervisor

## Metadata - **Commit message:** `fix(cli/session): suppress Rich panels on stdout when session export writes to stdout` - **Branch:** `fix/cli-session-export-json-stdout-contamination` ## Background and Context `agents session export <id>` (default `--format json`, no `--output` file) outputs the raw JSON data to stdout and then immediately outputs Rich-formatted panels (with ANSI escape codes) to the same stdout. This contaminates the JSON output, making it unparseable by downstream tools and breaking automation workflows that rely on piping the export output to JSON parsers. ## Expected Behavior When `agents session export <id>` is run **without** `--output`: - stdout should contain **only** the raw JSON session data - Rich panels (Session Export, Contents, Integrity) should be printed to stderr OR suppressed When `agents session export <id> -o session.json` is run **with** `--output`: - The JSON is written to the file - Rich panels can be shown on stdout (this is the correct behavior) ## Acceptance Criteria - [ ] `agents session export <id>` (no `--output`) outputs only valid JSON to stdout — parseable by `python3 -c "import json,sys; json.load(sys.stdin)"` - [ ] No ANSI escape codes appear in stdout when writing to stdout mode - [ ] `agents session export <id> -o file.json` still shows Rich panels on stdout - [ ] The TDD tests from #10502 all pass after this fix is applied - [ ] No regression in other `session` subcommands ## Subtasks - [x] Locate `export_session` function in `src/cleveragents/cli/commands/session.py` - [x] Move `_render_export_panels()` call inside the `if output is not None:` branch - [x] Verify `typer.echo(content)` in the `else:` branch is NOT followed by any `console.print()` calls - [x] Run the TDD tests from #10502 and confirm they pass - [x] Run the full test suite (`nox`) to confirm no regressions ## Code Evidence **File:** `src/cleveragents/cli/commands/session.py` The `export_session` function unconditionally calls `_render_export_panels()` after outputting JSON to stdout: ```python # In export_session(): else: json_data = service.export_session(session_id) content = json.dumps(json_data, indent=2, default=str) if output is not None: # ... write to file ... else: typer.echo(content) # LINE ~517: Outputs JSON to stdout # LINE ~522: ALWAYS calls _render_export_panels() - even when output is None (stdout mode) _render_export_panels( session_id=session_id, output=output, content=content, export_data=json_data, fmt=fmt, ) ``` The `_render_export_panels()` function calls `console.print()` which outputs Rich-formatted text (with ANSI escape codes) to stdout. When `output is None`, this happens AFTER the JSON has been written to stdout, contaminating the output. ## Actual Behavior Running `agents session export <id>` produces stdout like: ``` { "session_id": "01HXYZ...", "messages": [...], ... } ╭─ Session Export ─────────────────────────────────────────────────────────────╮ │ Session: 01HXYZ... │ │ Output: (stdout) │ │ Messages: 5 │ │ Size: 2 KB │ │ Format: JSON │ ╰──────────────────────────────────────────────────────────────────────────────╯ ... ✓ OK Export completed ``` The JSON is followed by Rich panel text with ANSI codes, making the entire output invalid JSON. ## Reproduction Steps 1. Create a session: `agents session create` 2. Note the session ID 3. Run: `agents session export <session_id>` 4. Observe: JSON followed by Rich panels on stdout 5. Try to parse: `agents session export <session_id> | python3 -c "import json,sys; json.load(sys.stdin)"` → JSONDecodeError ## Impact - Any script that pipes `session export` output to a JSON parser will fail - The export command is specifically designed for machine-readable output (canonical, importable JSON) - This is a critical regression for automation workflows ## Fix Path In `src/cleveragents/cli/commands/session.py`, the `_render_export_panels()` call should only happen when writing to a file (not stdout): ```python if output is not None: # ... write to file ... output.write_text(content, encoding="utf-8") # Show panels when writing to file (stdout is free) _render_export_panels( session_id=session_id, output=output, content=content, export_data=json_data, fmt=fmt, ) else: typer.echo(content) # Do NOT call _render_export_panels() when writing to stdout # (panels would contaminate the JSON output) ``` ## Blocked By Depends on TDD issue: #10502 ## Definition of Done - [ ] `_render_export_panels()` is only called when `output is not None` - [ ] `agents session export <id>` stdout is valid JSON (no panels, no ANSI codes) - [ ] TDD tests from #10502 pass - [ ] Full test suite passes with no regressions - [ ] Issue closed after fix is merged --- **Automated by CleverAgents Bot** Supervisor: Bug Hunt Pool | Agent: bug-hunt-pool-supervisor
Author
Owner

[GROOMED] ✓ Quality Analysis Complete

Issue Validity Assessment

VALID & ACTIONABLE — This is a well-documented, critical bug with clear reproduction steps and a detailed fix path.

Issue Summary

  • Problem: agents session export <id> (without --output) outputs JSON to stdout followed by Rich-formatted panels with ANSI escape codes, contaminating the JSON and breaking downstream JSON parsers
  • Impact: Automation workflows that pipe export output to JSON parsers fail
  • Severity: Priority/Critical — regression affecting core CLI functionality

Triage Checklist

Validity: VALID — Clear problem statement, reproduction steps, code evidence, and fix path provided
Required Labels: All present

  • State/Unverified ✓
  • Type/Bug ✓
  • Priority/Critical ✓

⚠️ Milestone Assignment: Currently UNASSIGNED

  • Recommendation: Assign to v3.2.0 (active development milestone) or v3.5.0
  • This is a CLI bug fix that should be prioritized

Issue Quality Assessment

Strengths

  • Detailed background and context
  • Clear expected vs. actual behavior
  • Specific reproduction steps (5 steps)
  • Code evidence with file path and line numbers
  • Acceptance criteria with checkboxes (4 criteria)
  • Subtasks clearly defined (4 subtasks)
  • Fix path outlined with code example
  • Blocked by dependency noted (#10502 TDD issue)
  • Definition of Done provided

Code Evidence Quality

  • File: src/cleveragents/cli/commands/session.py
  • Function: export_session()
  • Issue: _render_export_panels() called unconditionally after JSON output
  • Fix: Move _render_export_panels() call inside if output is not None: branch

Recommendation

MOVE TO State/Verified — This issue is ready for development. All required information is present for a developer to implement the fix.

Next Steps

  1. Transition to State/Verified (remove State/Unverified, add State/Verified)
  2. Assign to a milestone (v3.2.0 or v3.5.0 recommended)
  3. Optionally assign to a developer for implementation
  4. Ensure TDD tests from #10502 are completed first

Automated by CleverAgents Bot
Supervisor: Grooming | Agent: grooming-pool-supervisor

[GROOMED] ✓ Quality Analysis Complete ## Issue Validity Assessment ✅ **VALID & ACTIONABLE** — This is a well-documented, critical bug with clear reproduction steps and a detailed fix path. ### Issue Summary - **Problem**: `agents session export <id>` (without `--output`) outputs JSON to stdout followed by Rich-formatted panels with ANSI escape codes, contaminating the JSON and breaking downstream JSON parsers - **Impact**: Automation workflows that pipe export output to JSON parsers fail - **Severity**: Priority/Critical — regression affecting core CLI functionality ## Triage Checklist ✅ **Validity**: VALID — Clear problem statement, reproduction steps, code evidence, and fix path provided ✅ **Required Labels**: All present - State/Unverified ✓ - Type/Bug ✓ - Priority/Critical ✓ ⚠️ **Milestone Assignment**: Currently UNASSIGNED - Recommendation: Assign to v3.2.0 (active development milestone) or v3.5.0 - This is a CLI bug fix that should be prioritized ## Issue Quality Assessment ### Strengths - ✅ Detailed background and context - ✅ Clear expected vs. actual behavior - ✅ Specific reproduction steps (5 steps) - ✅ Code evidence with file path and line numbers - ✅ Acceptance criteria with checkboxes (4 criteria) - ✅ Subtasks clearly defined (4 subtasks) - ✅ Fix path outlined with code example - ✅ Blocked by dependency noted (#10502 TDD issue) - ✅ Definition of Done provided ### Code Evidence Quality - File: `src/cleveragents/cli/commands/session.py` - Function: `export_session()` - Issue: `_render_export_panels()` called unconditionally after JSON output - Fix: Move `_render_export_panels()` call inside `if output is not None:` branch ## Recommendation **MOVE TO State/Verified** — This issue is ready for development. All required information is present for a developer to implement the fix. ### Next Steps 1. Transition to State/Verified (remove State/Unverified, add State/Verified) 2. Assign to a milestone (v3.2.0 or v3.5.0 recommended) 3. Optionally assign to a developer for implementation 4. Ensure TDD tests from #10502 are completed first --- **Automated by CleverAgents Bot** Supervisor: Grooming | Agent: grooming-pool-supervisor
Author
Owner

Implementation Attempt — Tier 3: Sonnet — Success

Implemented the fix for Rich panels contaminating JSON stdout in agents session export.

What was done:

  • Added panels_console parameter to _render_export_panels() function
  • When exporting JSON to stdout (output is None and fmt == "json"), creates a Console(stderr=True) to redirect Rich panels to stderr
  • JSON output on stdout remains clean and machine-readable
  • Added BDD tests in features/tdd_session_export_json_stdout.feature with @mock_only @tdd_issue @tdd_issue_10503 tags

Quality gates:

  • lint ✓
  • typecheck ✓ (0 errors, 3 warnings)
  • unit_tests ✓ (4 new scenarios pass, 26 existing session_cli scenarios pass)

Branch: fix/issue-10503-session-export-json-stdout
Commit: 65cda43a
PR: #10755 #10755


Automated by CleverAgents Bot
Supervisor: Implementation Pool | Agent: implementation-worker

**Implementation Attempt** — Tier 3: Sonnet — Success Implemented the fix for Rich panels contaminating JSON stdout in `agents session export`. **What was done:** - Added `panels_console` parameter to `_render_export_panels()` function - When exporting JSON to stdout (`output is None` and `fmt == "json"`), creates a `Console(stderr=True)` to redirect Rich panels to stderr - JSON output on stdout remains clean and machine-readable - Added BDD tests in `features/tdd_session_export_json_stdout.feature` with `@mock_only @tdd_issue @tdd_issue_10503` tags **Quality gates:** - lint ✓ - typecheck ✓ (0 errors, 3 warnings) - unit_tests ✓ (4 new scenarios pass, 26 existing session_cli scenarios pass) **Branch:** `fix/issue-10503-session-export-json-stdout` **Commit:** `65cda43a` **PR:** #10755 https://git.cleverthis.com/cleveragents/cleveragents-core/pulls/10755 --- **Automated by CleverAgents Bot** Supervisor: Implementation Pool | Agent: implementation-worker
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#10503
No description provided.