feat: unify agent status schema
This commit is contained in:
@@ -106,7 +106,9 @@ def test_cli_whoami_command(monkeypatch) -> None:
|
||||
|
||||
result_json = runner.invoke(cli, ["whoami", "--json"])
|
||||
assert result_json.exit_code == 0
|
||||
assert '"screenName": "testuser"' in result_json.output
|
||||
payload = yaml.safe_load(runner.invoke(cli, ["whoami", "--yaml"]).output)
|
||||
assert payload["ok"] is True
|
||||
assert payload["data"]["user"]["username"] == "testuser"
|
||||
|
||||
|
||||
def test_cli_whoami_auto_yaml(monkeypatch) -> None:
|
||||
@@ -122,7 +124,9 @@ def test_cli_whoami_auto_yaml(monkeypatch) -> None:
|
||||
|
||||
assert result.exit_code == 0
|
||||
payload = yaml.safe_load(result.output)
|
||||
assert payload["screenName"] == "testuser"
|
||||
assert payload["ok"] is True
|
||||
assert payload["schema_version"] == "1"
|
||||
assert payload["data"]["user"]["username"] == "testuser"
|
||||
|
||||
|
||||
def test_cli_status_auto_yaml(monkeypatch) -> None:
|
||||
@@ -138,8 +142,10 @@ def test_cli_status_auto_yaml(monkeypatch) -> None:
|
||||
|
||||
assert result.exit_code == 0
|
||||
payload = yaml.safe_load(result.output)
|
||||
assert payload["authenticated"] is True
|
||||
assert payload["user"]["screenName"] == "testuser"
|
||||
assert payload["ok"] is True
|
||||
assert payload["schema_version"] == "1"
|
||||
assert payload["data"]["authenticated"] is True
|
||||
assert payload["data"]["user"]["username"] == "testuser"
|
||||
|
||||
|
||||
def test_cli_reply_command(monkeypatch) -> None:
|
||||
|
||||
@@ -49,7 +49,15 @@ from .formatter import (
|
||||
print_user_profile,
|
||||
print_user_table,
|
||||
)
|
||||
from .output import default_structured_format, emit_structured, structured_output_options, use_rich_output
|
||||
from .models import UserProfile
|
||||
from .output import (
|
||||
default_structured_format,
|
||||
emit_structured,
|
||||
error_payload,
|
||||
structured_output_options,
|
||||
success_payload,
|
||||
use_rich_output,
|
||||
)
|
||||
from .serialization import (
|
||||
tweets_from_json,
|
||||
tweets_to_data,
|
||||
@@ -65,6 +73,27 @@ FEED_TYPES = ["for-you", "following"]
|
||||
SEARCH_PRODUCTS = ["Top", "Latest", "Photos", "Videos"]
|
||||
|
||||
|
||||
def _agent_user_profile(profile: UserProfile) -> dict:
|
||||
"""Normalize a Twitter/X profile for structured agent output."""
|
||||
data = user_profile_to_dict(profile)
|
||||
return {
|
||||
"id": data["id"],
|
||||
"name": data["name"],
|
||||
"username": data["screenName"],
|
||||
"screenName": data["screenName"],
|
||||
"bio": data["bio"],
|
||||
"location": data["location"],
|
||||
"url": data["url"],
|
||||
"followers": data["followers"],
|
||||
"following": data["following"],
|
||||
"tweets": data["tweets"],
|
||||
"likes": data["likes"],
|
||||
"verified": data["verified"],
|
||||
"profileImageUrl": data["profileImageUrl"],
|
||||
"createdAt": data["createdAt"],
|
||||
}
|
||||
|
||||
|
||||
def _setup_logging(verbose):
|
||||
# type: (bool) -> None
|
||||
level = logging.DEBUG if verbose else logging.WARNING
|
||||
@@ -684,13 +713,13 @@ def status(as_json, as_yaml):
|
||||
client = _get_client_for_output(config, quiet=not rich_output)
|
||||
profile = client.fetch_me()
|
||||
except RuntimeError as exc:
|
||||
payload = {"authenticated": False, "error": str(exc)}
|
||||
payload = error_payload("not_authenticated", str(exc))
|
||||
if emit_structured(payload, as_json=as_json, as_yaml=as_yaml):
|
||||
sys.exit(1)
|
||||
_exit_with_error(exc)
|
||||
return
|
||||
|
||||
payload = {"authenticated": True, "user": user_profile_to_dict(profile)}
|
||||
payload = success_payload({"authenticated": True, "user": _agent_user_profile(profile)})
|
||||
if emit_structured(payload, as_json=as_json, as_yaml=as_yaml):
|
||||
return
|
||||
|
||||
@@ -711,9 +740,11 @@ def whoami(as_json, as_yaml):
|
||||
console.print("👤 Fetching current user...")
|
||||
profile = client.fetch_me()
|
||||
except RuntimeError as exc:
|
||||
if emit_structured(error_payload("not_authenticated", str(exc)), as_json=as_json, as_yaml=as_yaml):
|
||||
raise SystemExit(1) from None
|
||||
_exit_with_error(exc)
|
||||
|
||||
if not emit_structured(user_profile_to_dict(profile), as_json=as_json, as_yaml=as_yaml):
|
||||
if not emit_structured(success_payload({"user": _agent_user_profile(profile)}), as_json=as_json, as_yaml=as_yaml):
|
||||
console.print()
|
||||
print_user_profile(profile, console)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ from __future__ import annotations
|
||||
import json
|
||||
import logging
|
||||
import math
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import time
|
||||
|
||||
@@ -11,6 +11,7 @@ import click
|
||||
import yaml
|
||||
|
||||
_OUTPUT_ENV = "OUTPUT"
|
||||
_SCHEMA_VERSION = "1"
|
||||
|
||||
|
||||
def default_structured_format(*, as_json: bool, as_yaml: bool) -> str | None:
|
||||
@@ -66,3 +67,27 @@ def emit_structured(data: Any, *, as_json: bool, as_yaml: bool) -> bool:
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def success_payload(data: Any) -> dict[str, Any]:
|
||||
"""Wrap structured success data in the shared agent schema."""
|
||||
return {
|
||||
"ok": True,
|
||||
"schema_version": _SCHEMA_VERSION,
|
||||
"data": data,
|
||||
}
|
||||
|
||||
|
||||
def error_payload(code: str, message: str, *, details: Any | None = None) -> dict[str, Any]:
|
||||
"""Wrap structured error data in the shared agent schema."""
|
||||
error = {
|
||||
"code": code,
|
||||
"message": message,
|
||||
}
|
||||
if details is not None:
|
||||
error["details"] = details
|
||||
return {
|
||||
"ok": False,
|
||||
"schema_version": _SCHEMA_VERSION,
|
||||
"error": error,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user