feat: unify agent status schema

This commit is contained in:
jackwener
2026-03-10 21:02:08 +08:00
parent 32d074dc9f
commit 642ffe84a8
4 changed files with 71 additions and 8 deletions

View File

@@ -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:

View File

@@ -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)

View File

@@ -5,6 +5,7 @@ from __future__ import annotations
import json
import logging
import math
import os
import random
import re
import time

View File

@@ -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,
}