Metadata-Version: 2.4
Name: lexicor-client
Version: 0.1.0a1
Summary: Python client SDK for the Lexicor API
Author: Lexicor contributors
License: MIT
Project-URL: Homepage, https://lexicor.io
Project-URL: Documentation, https://lexicor.io/docs/sdks/python
Project-URL: Repository, https://github.com/thebigduck/Lexicor
Project-URL: Bug Tracker, https://github.com/thebigduck/Lexicor/issues
Project-URL: Source, https://github.com/thebigduck/Lexicor/tree/master/sdks/python
Keywords: lexicor,api,sdk,intentgraph,semantic-mediation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: respx>=0.21; extra == "dev"

# Lexicor Python Client

Python SDK for the Lexicor API.

## Installation

Once published to PyPI:

```bash
pip install lexicor-client
```

From this repo (editable):

```bash
pip install -e sdks/python
```

From GitHub without a clone:

```bash
pip install "git+https://github.com/thebigduck/Lexicor.git#subdirectory=sdks/python"
```

Publishing / tag process: [`../PUBLISH.md`](../PUBLISH.md).

## Quick start

```python
from lexicor_client import LexicorClient

client = LexicorClient("https://api.lexicor.io", api_key="lx-your-key")

ing = client.ingest("Schedule a follow-up with the team next Tuesday.", build_packet=False)
assert ing["parsed"]
my_graph = ing["intent_graph"]
normalized = client.normalize(my_graph)
result = client.roundtrip(my_graph)
comparison = client.compare(my_graph, normalized)
```

## Ingress and LM fallback

Template ingress is the default. Enable model-backed parsing when no template matches (server must have `OPENAI_API_KEY`):

```python
client.ingest(
    "Some unusual directive…",
    lm_fallback=True,
    build_packet=True,
    render_strategy="ascii_compact",
)
```

## Negotiation and full packets

Advertise capabilities, confirm the session, then build and decode transport packets (same flow as `POST /v1/negotiate/*` and `/v1/packet/*`):

```python
agent_id = "my-remote-agent"
client.negotiate_advertise(
    agent_id,
    supported_codecs=["lexicor-line-v1"],
    supported_symbol_tables=["core-sym-1"],
    supported_fidelity_tiers=[0, 1, 2, 3],
)
offer = client.negotiate_offer("sess-001", agent_id)
if offer["type"] != "offer":
    raise RuntimeError(offer.get("reason", "negotiation failed"))
contract = offer["contract"]
client.negotiate_confirm("sess-001")
contract["session_id"] = "sess-001"

built = client.packet_build(
    my_graph,
    session=contract,
    render_strategy="ascii_compact",
    payload_mode="semantic_transport",
)
packet = built["packet"]
decoded = client.packet_decode(packet)
graph = decoded["intent_graph"]
```

Optional **`transport=`** (advanced): pass an `httpx.BaseTransport` when constructing `LexicorClient` for custom HTTP behavior.

## Features

- Automatic retry with exponential backoff
- Rate limit handling (429 with Retry-After)
- Context manager support
- Type hints throughout
