Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ in the same process without one overriding the other.
identical otherwise — only the name and import path changed.
2. **`client.me()` no longer exists on `AgentClient`.** Identity moved
to `UserClient.me()` and the response shape changed too
(`UserPrincipal` with `user_id` / `email` / `name` /
(`UserPrincipal` with `user_id` / `username` / `email` /
`principal_type` / `key_prefix`, replacing `MeResponse` with
`agent_id` / `agent_name`). Listing your agents now goes through
`UserClient.agents.list()` instead.
Expand Down Expand Up @@ -141,7 +141,7 @@ from xagent_sdk import UserClient

with UserClient() as user:
me = user.me()
print(f"user_id={me.user_id} email={me.email} name={me.name}")
print(f"user_id={me.user_id} username={me.username} email={me.email}")
```

Each call hits the backend; cache the value locally if you need it
Expand Down
12 changes: 7 additions & 5 deletions python/src/xagent_sdk/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,17 @@ class UserPrincipal:
is bound to.

``principal_type`` is the stable enum string ``"user"`` for the
surface ``UserClient`` covers. ``key_prefix`` is the public-safe
6-char handle (``xag_personal_<prefix>_...``) and is safe to log;
the secret half of the key is never returned by this endpoint.
surface ``UserClient`` covers. ``username`` is the user's login name.
``email`` is optional and ``None`` when the account has no email set.
``key_prefix`` is the public-safe 6-char handle
(``xag_personal_<prefix>_...``) and is safe to log; the secret half of
the key is never returned by this endpoint.
"""

principal_type: str
user_id: int
email: str
name: str
username: str
email: str | None
key_prefix: str


Expand Down
5 changes: 3 additions & 2 deletions python/tests/e2e/test_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ def test_user_me(user_client: UserClient) -> None:
assert isinstance(me, UserPrincipal)
assert me.principal_type == "user"
assert me.user_id > 0
assert me.email
assert me.name
assert me.username
# email is optional (null for accounts with none set)
assert me.email is None or isinstance(me.email, str)
assert me.key_prefix


Expand Down
26 changes: 25 additions & 1 deletion python/tests/unit/test_user_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,34 @@ def test_returns_user_principal(self) -> None:
assert isinstance(me, UserPrincipal)
assert me.principal_type == "user"
assert me.user_id == 123
assert me.username == "alex"
assert me.email == "user@example.com"
assert me.name == "Alex"
assert me.key_prefix == "abc123"

def test_me_email_may_be_null(self) -> None:
# The backend returns email=null for accounts with no email set;
# UserPrincipal.email is optional, so this must parse cleanly.
def handler(req: httpx.Request) -> httpx.Response:
return httpx.Response(
200,
json={
"principal_type": "user",
"user_id": 1,
"username": "administrator",
"email": None,
"key_prefix": "abc123",
},
)

with UserClient(
personal_key="xag_personal_p_s",
base_url="https://test.example",
transport=httpx.MockTransport(handler),
) as c:
me = c.me()
assert me.username == "administrator"
assert me.email is None

def test_401_raises_invalid_api_key(self) -> None:
with (
UserClient(
Expand Down
2 changes: 1 addition & 1 deletion shared/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ implicit and documented below.

| File | Endpoint | Notes |
|---|---|---|
| `me_user.json` | `GET /v1/me` | User principal: `principal_type / user_id / email / name / key_prefix` |
| `me_user.json` | `GET /v1/me` | User principal: `principal_type / user_id / username / email (nullable) / key_prefix` |
| `templates_list.json` | `GET /v1/templates` | Bare JSON array; each entry keys its id under `id` (SDKs surface it as `template_id`) plus `name`, optional `description` |
| `templates_detail.json` | `GET /v1/templates/{id}` | Single object keyed by `id`; carries the merge-target `agent_config` dict |
| `agents_list.json` | `GET /v1/agents` | Bare JSON array; each entry keys its id under `id` (SDKs surface it as `agent_id`); covers `active`, `draft`, `paused` status values |
Expand Down
2 changes: 1 addition & 1 deletion shared/fixtures/v1/responses/me_user.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"principal_type": "user",
"user_id": 123,
"username": "alex",
"email": "user@example.com",
"name": "Alex",
"key_prefix": "abc123"
}
Loading