fix(cli): restore session list json contract
CI / benchmark-publish (pull_request) Has been skipped
CI / helm (pull_request) Successful in 35s
CI / push-validation (pull_request) Successful in 21s
CI / build (pull_request) Successful in 52s
CI / lint (pull_request) Successful in 1m0s
CI / quality (pull_request) Successful in 1m33s
CI / security (pull_request) Successful in 1m45s
CI / typecheck (pull_request) Successful in 1m49s
CI / integration_tests (pull_request) Successful in 3m58s
CI / e2e_tests (pull_request) Successful in 4m32s
CI / unit_tests (pull_request) Successful in 5m55s
CI / docker (pull_request) Successful in 1m31s
CI / coverage (pull_request) Successful in 10m47s
CI / status-check (pull_request) Successful in 3s
CI / build (push) Successful in 47s
CI / lint (push) Successful in 57s
CI / helm (push) Successful in 28s
CI / quality (push) Successful in 1m11s
CI / typecheck (push) Successful in 1m34s
CI / security (push) Successful in 1m36s
CI / push-validation (push) Successful in 21s
CI / benchmark-publish (push) Failing after 40s
CI / integration_tests (push) Successful in 3m47s
CI / e2e_tests (push) Successful in 4m9s
CI / unit_tests (push) Successful in 7m0s
CI / docker (push) Successful in 1m31s
CI / coverage (push) Successful in 10m40s
CI / status-check (push) Successful in 3s
CI / benchmark-publish (pull_request) Has been skipped
CI / helm (pull_request) Successful in 35s
CI / push-validation (pull_request) Successful in 21s
CI / build (pull_request) Successful in 52s
CI / lint (pull_request) Successful in 1m0s
CI / quality (pull_request) Successful in 1m33s
CI / security (pull_request) Successful in 1m45s
CI / typecheck (pull_request) Successful in 1m49s
CI / integration_tests (pull_request) Successful in 3m58s
CI / e2e_tests (pull_request) Successful in 4m32s
CI / unit_tests (pull_request) Successful in 5m55s
CI / docker (pull_request) Successful in 1m31s
CI / coverage (pull_request) Successful in 10m47s
CI / status-check (pull_request) Successful in 3s
CI / build (push) Successful in 47s
CI / lint (push) Successful in 57s
CI / helm (push) Successful in 28s
CI / quality (push) Successful in 1m11s
CI / typecheck (push) Successful in 1m34s
CI / security (push) Successful in 1m36s
CI / push-validation (push) Successful in 21s
CI / benchmark-publish (push) Failing after 40s
CI / integration_tests (push) Successful in 3m47s
CI / e2e_tests (push) Successful in 4m9s
CI / unit_tests (push) Successful in 7m0s
CI / docker (push) Successful in 1m31s
CI / coverage (push) Successful in 10m40s
CI / status-check (push) Successful in 3s
Ensure the session list helper only emits the documented fields so downstream consumers stay compliant, and tighten the Behave coverage to enforce the contract.\n\nISSUES CLOSED: #6436
This commit was merged in pull request #6699.
This commit is contained in:
@@ -39,10 +39,10 @@ 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
|
||||
Scenario: List sessions JSON matches the documented contract
|
||||
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
|
||||
Then the session CLI JSON list entries should match the documented contract
|
||||
|
||||
# Show command tests
|
||||
Scenario: Show session with valid ID
|
||||
|
||||
@@ -525,18 +525,26 @@ def step_json_show_token_usage_counts(context: Context) -> None:
|
||||
_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:
|
||||
@then("the session CLI JSON list entries should match the documented contract")
|
||||
def step_json_list_contract(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 isinstance(session, dict), (
|
||||
f"session entry at index {index} is not an object: {session!r}"
|
||||
)
|
||||
expected_keys = {"id", "name", "actor", "messages", "updated"}
|
||||
actual_keys = set(session.keys())
|
||||
missing = expected_keys - actual_keys
|
||||
extra = actual_keys - expected_keys
|
||||
assert not missing, (
|
||||
f"session entry {index} missing keys {sorted(missing)}: {session!r}"
|
||||
)
|
||||
assert not extra, (
|
||||
f"session entry {index} has undocumented keys {sorted(extra)}: {session!r}"
|
||||
)
|
||||
_assert_token_usage_counts_are_ints(token_usage)
|
||||
|
||||
|
||||
def _assert_token_usage_counts_are_ints(token_usage: dict[str, Any]) -> None:
|
||||
|
||||
@@ -133,11 +133,6 @@ 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}",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user