Skip to content

Commit 1938fe5

Browse files
feat: aeo-sdk-python v0.1.0 - Python SDK for AEO Protocol v0.1
Parse, build, validate, and fetch AEO declaration documents. Pydantic v2 models for all spec types (Entity, Authority, Claim, Verification, CitationPreferences, AnswerConstraints, Audit). Sync and async fetch helpers via httpx. Pytest suite (8 tests) loads the canonical Person example from the AEO spec and exercises parse, query, round-trip serialization, and constructor build paths. Supports conformance Level 1 (Declare). Signature verification (L2) and audit-endpoint posting (L3) deferred to v0.2.
0 parents  commit 1938fe5

14 files changed

Lines changed: 1215 additions & 0 deletions

‎.github/workflows/ci.yml‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
python-version: ["3.10", "3.11", "3.12"]
15+
steps:
16+
- uses: actions/checkout@v4
17+
- uses: actions/setup-python@v5
18+
with:
19+
python-version: ${{ matrix.python-version }}
20+
- run: pip install -e .[dev]
21+
- run: pytest -v

‎.gitignore‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.DS_Store
2+
Thumbs.db
3+
*.swp
4+
*.swo
5+
.idea/
6+
.vscode/
7+
node_modules/

‎LICENSE‎

Lines changed: 661 additions & 0 deletions
Large diffs are not rendered by default.

‎README.md‎

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# aeo-sdk-python
2+
3+
Python SDK for the [AEO Protocol v0.1](https://github.com/mizcausevic-dev/aeo-protocol-spec) — parse, build, validate, and fetch AEO declaration documents.
4+
5+
## Install
6+
7+
```bash
8+
pip install aeo-protocol
9+
```
10+
11+
## Quickstart
12+
13+
```python
14+
from aeo import Document, fetch_well_known
15+
16+
# Fetch and parse from a live well-known URL
17+
doc = fetch_well_known("https://mizcausevic-dev.github.io")
18+
print(doc.entity.name) # "Miz Causevic"
19+
print(doc.claim_ids()) # ['current-role', 'location', ...]
20+
print(doc.find_claim("years-experience").value) # 30
21+
22+
# Parse from disk
23+
doc = Document.from_file("aeo.json")
24+
25+
# Build programmatically
26+
from aeo import Entity, Authority, Claim, Document
27+
doc = Document(
28+
entity=Entity(
29+
id="https://example.com/#org",
30+
type="Organization",
31+
name="Example Org",
32+
canonical_url="https://example.com/",
33+
),
34+
authority=Authority(primary_sources=["https://example.com/"]),
35+
claims=[Claim(id="tagline", predicate="description", value="A reference example.")],
36+
)
37+
print(doc.to_json())
38+
```
39+
40+
Async variant:
41+
42+
```python
43+
import asyncio
44+
from aeo.client import fetch_well_known_async
45+
46+
doc = asyncio.run(fetch_well_known_async("https://mizcausevic-dev.github.io"))
47+
```
48+
49+
## What it does
50+
51+
- **Parse** — `Document.from_json` / `from_file` / `from_dict`
52+
- **Build** — pydantic v2 model classes for every type in the spec (`Entity`, `Authority`, `Claim`, `Verification`, `CitationPreferences`, `AnswerConstraints`, `Audit`)
53+
- **Serialize** — `Document.to_json()` returns canonical JSON
54+
- **Fetch** — `fetch_well_known(origin)` performs HTTP discovery against `/.well-known/aeo.json` with `Accept: application/aeo+json, application/json`
55+
- **Query** — `doc.claim_ids()` and `doc.find_claim(id)` for convenience
56+
57+
## Conformance
58+
59+
This SDK supports the AEO Protocol at **conformance Level 1 (Declare)**. Signature verification (Level 2) and audit-endpoint posting (Level 3) are not yet implemented; signed documents parse fine but the signature is not verified.
60+
61+
## Dependencies
62+
63+
- [pydantic](https://github.com/pydantic/pydantic) >= 2.0 — model validation and serialization
64+
- [httpx](https://github.com/encode/httpx) >= 0.27 — sync and async HTTP
65+
66+
## Development
67+
68+
```bash
69+
pip install -e .[dev]
70+
pytest -v
71+
```
72+
73+
## Specification
74+
75+
Full spec at [github.com/mizcausevic-dev/aeo-protocol-spec](https://github.com/mizcausevic-dev/aeo-protocol-spec).
76+
77+
## License
78+
79+
AGPL-3.0.
80+
81+
## Kinetic Gain Protocol Suite
82+
83+
| Spec | Implementation |
84+
|---|---|
85+
| [AEO Protocol](https://github.com/mizcausevic-dev/aeo-protocol-spec) | **aeo-sdk-python** (this) · [aeo-sdk-typescript](https://github.com/mizcausevic-dev/aeo-sdk-typescript) · [aeo-sdk-rust](https://github.com/mizcausevic-dev/aeo-sdk-rust) · [aeo-sdk-go](https://github.com/mizcausevic-dev/aeo-sdk-go) · [aeo-cli](https://github.com/mizcausevic-dev/aeo-cli) · [aeo-crawler](https://github.com/mizcausevic-dev/aeo-crawler) |
86+
| [Prompt Provenance](https://github.com/mizcausevic-dev/prompt-provenance-spec) | — |
87+
| [Agent Cards](https://github.com/mizcausevic-dev/agent-cards-spec) | — |
88+
| [AI Evidence Format](https://github.com/mizcausevic-dev/ai-evidence-format-spec) | — |
89+
| [MCP Tool Cards](https://github.com/mizcausevic-dev/mcp-tool-card-spec) | — |
90+
91+
---
92+
93+
**Connect:** [LinkedIn](https://www.linkedin.com/in/mirzacausevic/) · [Kinetic Gain](https://kineticgain.com) · [Medium](https://medium.com/@mizcausevic/) · [Skills](https://mizcausevic.com/skills/)

‎pyproject.toml‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "aeo-protocol"
7+
version = "0.1.0"
8+
description = "Python SDK for the AEO Protocol v0.1 — parse, build, validate, and fetch AEO declaration documents."
9+
readme = "README.md"
10+
license = { text = "AGPL-3.0" }
11+
authors = [{ name = "Miz Causevic" }]
12+
requires-python = ">=3.10"
13+
dependencies = [
14+
"pydantic>=2.0",
15+
"httpx>=0.27",
16+
]
17+
keywords = ["aeo", "answer-engine-optimization", "well-known", "llm", "json-ld"]
18+
classifiers = [
19+
"Development Status :: 3 - Alpha",
20+
"Intended Audience :: Developers",
21+
"License :: OSI Approved :: GNU Affero General Public License v3",
22+
"Programming Language :: Python :: 3",
23+
"Programming Language :: Python :: 3.10",
24+
"Programming Language :: Python :: 3.11",
25+
"Programming Language :: Python :: 3.12",
26+
"Topic :: Software Development :: Libraries",
27+
]
28+
29+
[project.urls]
30+
Homepage = "https://github.com/mizcausevic-dev/aeo-sdk-python"
31+
Specification = "https://github.com/mizcausevic-dev/aeo-protocol-spec"
32+
"Bug Tracker" = "https://github.com/mizcausevic-dev/aeo-sdk-python/issues"
33+
34+
[project.optional-dependencies]
35+
dev = ["pytest>=7", "pytest-asyncio>=0.21"]
36+
37+
[tool.hatch.build.targets.wheel]
38+
packages = ["src/aeo"]
39+
40+
[tool.pytest.ini_options]
41+
testpaths = ["tests"]
42+
asyncio_mode = "auto"

‎src/aeo/__init__.py‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""Python SDK for the AEO Protocol v0.1.
2+
3+
Parse, build, validate, and fetch AEO declaration documents.
4+
5+
Specification: https://github.com/mizcausevic-dev/aeo-protocol-spec
6+
"""
7+
from aeo.document import (
8+
AnswerConstraints,
9+
Audit,
10+
Authority,
11+
CitationPreferences,
12+
Claim,
13+
Document,
14+
Entity,
15+
Verification,
16+
)
17+
from aeo.client import fetch_well_known, well_known_url
18+
19+
__all__ = [
20+
"AnswerConstraints",
21+
"Audit",
22+
"Authority",
23+
"CitationPreferences",
24+
"Claim",
25+
"Document",
26+
"Entity",
27+
"Verification",
28+
"fetch_well_known",
29+
"well_known_url",
30+
]
31+
32+
__version__ = "0.1.0"
33+
PROTOCOL_VERSION = "0.1"
771 Bytes
Binary file not shown.
3.08 KB
Binary file not shown.
7.09 KB
Binary file not shown.

‎src/aeo/client.py‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""HTTP client helpers for the AEO Protocol discovery convention."""
2+
from __future__ import annotations
3+
4+
import httpx
5+
6+
from aeo.document import Document
7+
8+
_WELL_KNOWN_PATH = "/.well-known/aeo.json"
9+
_ACCEPTED_MEDIA_TYPES = "application/aeo+json, application/json"
10+
11+
12+
def well_known_url(origin: str) -> str:
13+
"""Return the canonical well-known URL for an origin.
14+
15+
Strips trailing slashes from the origin and appends the
16+
AEO Protocol well-known path.
17+
"""
18+
return origin.rstrip("/") + _WELL_KNOWN_PATH
19+
20+
21+
def fetch_well_known(
22+
origin: str,
23+
*,
24+
timeout: float = 10.0,
25+
follow_redirects: bool = True,
26+
) -> Document:
27+
"""Fetch and parse the AEO declaration at ``origin``'s well-known URL.
28+
29+
Raises ``httpx.HTTPStatusError`` for non-2xx responses and
30+
``pydantic.ValidationError`` for malformed documents.
31+
"""
32+
url = well_known_url(origin)
33+
with httpx.Client(
34+
timeout=timeout,
35+
follow_redirects=follow_redirects,
36+
headers={"Accept": _ACCEPTED_MEDIA_TYPES},
37+
) as client:
38+
response = client.get(url)
39+
response.raise_for_status()
40+
return Document.from_json(response.text)
41+
42+
43+
async def fetch_well_known_async(
44+
origin: str,
45+
*,
46+
timeout: float = 10.0,
47+
follow_redirects: bool = True,
48+
) -> Document:
49+
"""Async variant of ``fetch_well_known``."""
50+
url = well_known_url(origin)
51+
async with httpx.AsyncClient(
52+
timeout=timeout,
53+
follow_redirects=follow_redirects,
54+
headers={"Accept": _ACCEPTED_MEDIA_TYPES},
55+
) as client:
56+
response = await client.get(url)
57+
response.raise_for_status()
58+
return Document.from_json(response.text)

0 commit comments

Comments
 (0)