fix(cli): fix JSON/YAML envelope messages[].text to show actual content (#6457)
CI / benchmark-publish (pull_request) Has been skipped
CI / push-validation (pull_request) Successful in 34s
CI / lint (pull_request) Successful in 39s
CI / build (pull_request) Successful in 39s
CI / helm (pull_request) Successful in 40s
CI / quality (pull_request) Successful in 43s
CI / typecheck (pull_request) Successful in 54s
CI / security (pull_request) Successful in 56s
CI / e2e_tests (pull_request) Successful in 3m17s
CI / unit_tests (pull_request) Successful in 4m59s
CI / docker (pull_request) Successful in 1m20s
CI / integration_tests (pull_request) Successful in 8m38s
CI / coverage (pull_request) Successful in 10m17s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Successful in 58m15s

This commit is contained in:
2026-04-10 00:35:22 +00:00
parent 8a87675a58
commit 0ff220b2fd
3 changed files with 93 additions and 4 deletions
+9
View File
@@ -21,6 +21,7 @@ Feature: Session CLI commands
When I run session CLI create with --format json
Then the session CLI create should succeed
And the session CLI output should be valid JSON
And the session CLI JSON envelope message should be "Session created"
# List command tests
Scenario: List sessions when empty
@@ -28,6 +29,12 @@ Feature: Session CLI commands
When I run session CLI list
Then the session CLI output should contain "No sessions found"
Scenario: List sessions with JSON format when empty
Given there are no mocked sessions
When I run session CLI list with --format json
Then the session CLI output should be valid JSON
And the session CLI JSON envelope message should be "0 sessions listed"
Scenario: List sessions with populated data
Given there are mocked existing sessions
When I run session CLI list
@@ -38,6 +45,7 @@ Feature: Session CLI commands
When I run session CLI list with --format json
Then the session CLI output should be valid JSON
And the session CLI JSON should contain "sessions"
And the session CLI JSON envelope message should be "2 sessions listed"
# Show command tests
Scenario: Show session with valid ID
@@ -58,6 +66,7 @@ Feature: Session CLI commands
Given there is a mocked session with messages
When I run session CLI show with --format json
Then the session CLI output should be valid JSON
And the session CLI JSON envelope message should be "Session details loaded"
Scenario: Show session with invalid ID
When I run session CLI show with an invalid session ID
+19
View File
@@ -514,6 +514,25 @@ def step_json_contains_key(context: Context, key: str) -> None:
assert key in data, f"Key '{key}' not found in JSON: {data}"
@then('the session CLI JSON envelope message should be "{expected}"')
def step_json_envelope_message(context: Context, expected: str) -> None:
parsed = json.loads(context.result.output)
assert isinstance(parsed, dict), (
f"Expected envelope dict, got {type(parsed)}: {context.result.output}"
)
messages = parsed.get("messages")
assert isinstance(messages, list), (
f"Expected 'messages' list, got {type(messages)}: {messages}"
)
assert messages, "Envelope messages should not be empty"
first = messages[0]
assert isinstance(first, dict), f"Message entry should be dict, got {type(first)}"
actual = first.get("text")
assert actual == expected, (
f"Expected message text '{expected}', got '{actual}' in {messages}"
)
@then("the session CLI should exit with error")
def step_exit_with_error(context: Context) -> None:
assert context.result.exit_code != 0, (
+65 -4
View File
@@ -48,6 +48,20 @@ _log = logging.getLogger(__name__)
# Reusable --format option description
_FORMAT_HELP = "Output format: json, yaml, plain, table, or rich (default: rich)"
def _command_label(subcommand: str, *tokens: str) -> str:
"""Build a CLI command string for envelope metadata."""
parts: list[str] = ["agents", "session", subcommand]
parts.extend(token for token in tokens if token)
return " ".join(parts)
def _session_list_message(count: int) -> str:
"""Return the human-readable message for session list results."""
suffix = "session" if count == 1 else "sessions"
return f"{count} {suffix} listed"
# ---------------------------------------------------------------------------
# Module-level service accessor (patchable in tests)
# ---------------------------------------------------------------------------
@@ -207,7 +221,18 @@ def create(
data = _session_summary_dict(session)
if fmt not in (OutputFormat.RICH.value, OutputFormat.COLOR.value):
typer.echo(format_output(dict(data), fmt))
extra_tokens: list[str] = []
if actor:
extra_tokens.extend(["--actor", actor])
extra_tokens.extend(["--format", fmt])
typer.echo(
format_output(
dict(data),
fmt,
command=_command_label("create", *extra_tokens),
messages=[{"level": "ok", "text": "Session created"}],
)
)
return
details = (
@@ -292,7 +317,19 @@ def list_sessions(
# For machine-readable formats, always emit a structured empty list
# so that callers parsing JSON/YAML receive valid output.
if fmt not in (OutputFormat.RICH.value, OutputFormat.COLOR.value):
typer.echo(format_output({"sessions": [], "total": 0}, fmt))
typer.echo(
format_output(
{"sessions": [], "total": 0},
fmt,
command=_command_label("list", "--format", fmt),
messages=[
{
"level": "ok",
"text": _session_list_message(0),
}
],
)
)
return
console.print("[yellow]No sessions found.[/yellow]")
console.print("Create one with 'agents session create'")
@@ -301,7 +338,19 @@ def list_sessions(
data = _session_list_dict(sessions)
if fmt not in (OutputFormat.RICH.value, OutputFormat.COLOR.value):
typer.echo(format_output(data, fmt))
typer.echo(
format_output(
data,
fmt,
command=_command_label("list", "--format", fmt),
messages=[
{
"level": "ok",
"text": _session_list_message(len(sessions)),
}
],
)
)
return
# Rich table
@@ -367,7 +416,19 @@ def show(
data = session.as_cli_dict()
if fmt not in (OutputFormat.RICH.value, OutputFormat.COLOR.value):
typer.echo(format_output(dict(data), fmt))
typer.echo(
format_output(
dict(data),
fmt,
command=_command_label(
"show",
session_id,
"--format",
fmt,
),
messages=[{"level": "ok", "text": "Session details loaded"}],
)
)
return
# Session summary panel — field order per spec: ID, Actor, Messages,