fix(cli): fix session show/list JSON output to not redact input messages (#6436)
ISSUES CLOSED: #6436
This commit is contained in:
@@ -39,6 +39,11 @@ Feature: Session CLI commands
|
||||
Then the session CLI output should be valid JSON
|
||||
And the session CLI JSON should contain "sessions"
|
||||
|
||||
Scenario: List sessions JSON includes token usage counts
|
||||
Given there are mocked existing sessions
|
||||
When I run session CLI list with --format json
|
||||
Then the session CLI JSON list token usage should include counts
|
||||
|
||||
# Show command tests
|
||||
Scenario: Show session with valid ID
|
||||
Given there is a mocked session with messages
|
||||
@@ -59,6 +64,11 @@ Feature: Session CLI commands
|
||||
When I run session CLI show with --format json
|
||||
Then the session CLI output should be valid JSON
|
||||
|
||||
Scenario: Show session JSON includes token usage counts
|
||||
Given there is a mocked session with messages
|
||||
When I run session CLI show with --format json
|
||||
Then the session CLI JSON token usage should include counts
|
||||
|
||||
Scenario: Show session with invalid ID
|
||||
When I run session CLI show with an invalid session ID
|
||||
Then the session CLI should exit with error
|
||||
|
||||
@@ -514,6 +514,44 @@ 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 token usage should include counts")
|
||||
def step_json_show_token_usage_counts(context: Context) -> None:
|
||||
parsed = json.loads(context.result.output)
|
||||
data = _unwrap_envelope(parsed)
|
||||
token_usage = data.get("token_usage")
|
||||
assert isinstance(token_usage, dict), (
|
||||
f"token_usage missing or not an object: {token_usage}"
|
||||
)
|
||||
_assert_token_usage_counts_are_ints(token_usage)
|
||||
|
||||
|
||||
@then("the session CLI JSON list token usage should include counts")
|
||||
def step_json_list_token_usage_counts(context: Context) -> None:
|
||||
parsed = json.loads(context.result.output)
|
||||
data = _unwrap_envelope(parsed)
|
||||
sessions = data.get("sessions")
|
||||
assert isinstance(sessions, list), f"sessions missing or not a list: {sessions}"
|
||||
for index, session in enumerate(sessions):
|
||||
token_usage = session.get("token_usage")
|
||||
assert isinstance(token_usage, dict), (
|
||||
f"token_usage missing for session {index}: {token_usage}"
|
||||
)
|
||||
_assert_token_usage_counts_are_ints(token_usage)
|
||||
|
||||
|
||||
def _assert_token_usage_counts_are_ints(token_usage: dict[str, Any]) -> None:
|
||||
input_tokens = token_usage.get("input_tokens")
|
||||
output_tokens = token_usage.get("output_tokens")
|
||||
assert isinstance(input_tokens, int), (
|
||||
f"input_tokens should be int, got {input_tokens!r}"
|
||||
)
|
||||
assert isinstance(output_tokens, int), (
|
||||
f"output_tokens should be int, got {output_tokens!r}"
|
||||
)
|
||||
assert input_tokens != "***REDACTED***", "input_tokens should not be redacted"
|
||||
assert output_tokens != "***REDACTED***", "output_tokens should not be redacted"
|
||||
|
||||
|
||||
@then("the session CLI should exit with error")
|
||||
def step_exit_with_error(context: Context) -> None:
|
||||
assert context.result.exit_code != 0, (
|
||||
|
||||
@@ -133,6 +133,11 @@ def _session_list_dict(sessions: list[Session]) -> dict[str, Any]:
|
||||
"actor": s.actor_name or "(none)",
|
||||
"messages": s.message_count,
|
||||
"updated": s.updated_at.isoformat(),
|
||||
"token_usage": {
|
||||
"input_tokens": s.token_usage.input_tokens,
|
||||
"output_tokens": s.token_usage.output_tokens,
|
||||
"estimated_cost": f"${s.token_usage.estimated_cost:.4f}",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ _FALSE_POSITIVE_KEYS: set[str] = {
|
||||
"token_count",
|
||||
"token_limit",
|
||||
"token_usage",
|
||||
"input_tokens",
|
||||
"output_tokens",
|
||||
"max_tokens",
|
||||
"total_tokens",
|
||||
"prompt_tokens",
|
||||
|
||||
Reference in New Issue
Block a user