Preserve CLI session metadata in JSON output

This commit is contained in:
bearsyankees 2026-08-28 15:32:09 -04:00
parent 192e041a35
commit 33c1a5b603
4 changed files with 44 additions and 3 deletions

View file

@ -147,7 +147,13 @@ def _string_list(value: Any) -> list[str]:
def _error(console: Console, error: http.CloudError, *, as_json: bool) -> int:
if as_json:
emit(console, {"error": str(error)}, as_json=True)
raw_payload: Any = error.payload
error_payload = cast("dict[str, Any]", raw_payload)
payload = dict(error_payload) if isinstance(raw_payload, dict) else {}
payload["error"] = str(error)
if payload.get("detail") == payload.get("error"):
payload.pop("detail", None)
emit(console, payload, as_json=True)
else:
console.print(f"[red]Error:[/] {escape(sanitize_terminal_text(error))}")
return error.exit_code

View file

@ -169,6 +169,14 @@ def _use( # noqa: PLR0912, PLR0915
"workspace_id": record["organization_id"],
"workspace_name": record["organization_name"],
"scopes": record["scopes"],
"requested_scopes": record.get("requested_scopes", record["scopes"]),
"scope_ceiling": record.get("scope_ceiling", []),
"scope_profile": record.get("scope_profile", "custom"),
"expires_at": record.get("expires_at"),
"token_id": record.get("token_id"),
"credential_source": record.get("credential_source", "api"),
"device_name": record.get("device_name"),
"stored": not external_token,
}
if as_json:
emit(console, result, as_json=True)

View file

@ -1685,11 +1685,14 @@ def test_workspaces_use_switches_stored_token(
assert record["api_token"] == "old"
assert record["organization_name"] == "Team One"
assert record["email"] == "a@b.test"
assert "org_1" in capsys.readouterr().out
output = json.loads(capsys.readouterr().out)
assert output["workspace_id"] == "org_1"
assert output["scope_profile"] == "custom"
assert output["stored"] is True
def test_workspace_use_explicit_token_starts_with_fresh_account_state(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
monkeypatch: pytest.MonkeyPatch, tmp_path: Path, capsys: Any
) -> None:
auth_path = tmp_path / "platform-auth.json"
monkeypatch.setattr(platform_cli, "AUTH_PATH", auth_path)
@ -1733,6 +1736,9 @@ def test_workspace_use_explicit_token_starts_with_fresh_account_state(
assert record["api_token"] == "account-a-token"
assert record["organization_id"] == "org_a"
assert record["email"] == "account-a@example.test"
output = json.loads(capsys.readouterr().out)
assert output["workspace_id"] == "org_b"
assert output["stored"] is False
def test_workspace_use_environment_token_starts_with_fresh_account_state(

View file

@ -6,9 +6,11 @@ import json
from typing import TYPE_CHECKING, Any
import pytest
from rich.console import Console
from strix.interface import cloud, platform_cli, platform_identity
from strix.interface.cloud import http
from strix.interface.cloud import session as cloud_session
if TYPE_CHECKING:
@ -159,6 +161,25 @@ def test_local_only_logout_is_explicit_and_recoverable(auth_path: Path, capsys:
assert not auth_path.exists()
def test_session_json_errors_preserve_machine_readable_server_details(capsys: Any) -> None:
error = http.CloudError(
"workspace changed",
payload={
"detail": "workspace changed",
"code": "workspace_session_changed",
"current_organization_id": "org_current",
},
)
assert cloud_session._error(Console(), error, as_json=True) == http.EXIT_ERROR
payload = json.loads(capsys.readouterr().out)
assert payload == {
"code": "workspace_session_changed",
"current_organization_id": "org_current",
"error": "workspace changed",
}
def test_cli_device_identity_is_stable_and_privacy_safe(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None: