Metadata-Version: 2.4
Name: uss-aigent
Version: 0.1.2
Summary: A progressive-disclosure Python library for LLM APIs
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Requires-Python: >=3.10
Requires-Dist: httpx
Provides-Extra: dev
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Description-Content-Type: text/markdown

# Aigent

A progressive-disclosure Python library for LLM APIs. Start with a one-liner, scale to full control — all in idiomatic Python.

```python
from aigent import Aigent

agent = Aigent(api_type="openai")
with agent.session() as s:
    print(s.chat("Hello!"))
```

## Installation

```bash
pip install uss-aigent
```

Requires Python 3.10+. The only external dependency is [httpx](https://www.pypi.org/project/httpx/).

## Quick Start

### Tier 1 — Chat

```python
from aigent import Aigent

# Zero-config: reads OPENAI_API_KEY / ANTHROPIC_API_KEY from env
agent = Aigent(api_type="anthropic")

with agent.session(system="You are a professional translator.") as s:
    result = s.chat("Translate to English: 你好世界")
    print(result)
```

### Tier 2 — Tools

```python
from aigent import Aigent, tool

@tool
def get_weather(city: str, unit: str = "celsius") -> str:
    """Get current weather for a city."""
    # In real code, call a weather API here
    return f"{city}: 22°{unit[0].upper()}"

agent = Aigent(api_type="openai")
with agent.session(tools=[get_weather]) as s:
    reply = s.chat("What's the weather in Beijing?")
    print(reply)
```

The `@tool` decorator auto-generates JSON Schema from your function signature and docstring — no manual schema writing.

### Tier 3 — Full Control

```python
from aigent import Aigent, Message

agent = Aigent(api_type="anthropic")

# Manually orchestrate messages
resp = agent.raw(
    [Message.system("You are helpful."), Message.user("Hi!")],
    max_tokens=200,
    temperature=0.7,
)
print(resp.content)   # str
print(resp.usage)     # Usage(prompt_tokens=..., completion_tokens=...)
```

## Session & Role API

```python
agent = Aigent()

with agent.session() as s:
    # Chat as user (default)
    s.chat("Hello")

    # Chat as assistant
    s.chat("I'm doing great!", role="assistant")

    # Streaming
    for token in s.chat("Write a poem", stream=True):
        print(token, end="")

    # Insert without sending — build context gradually
    s.user.insert("I want to learn Python.")
    s.assistant.insert("Great choice! Where would you like to start?")
    reply = s.chat()  # sends existing history without adding new message

    # Role objects
    s.system.insert("You are a Python expert.")
    s.role("tool").insert('{"result": 42}', tool_call_id="call_abc")

    # History management
    print(s.history)   # read-only list of messages
    s.clear()           # reset the conversation
```

## Supported Backends

| `api_type` | Backend | Default Model |
|------------|---------|---------------|
| `"openai"` | OpenAI Chat Completions | `gpt-4o` |
| `"anthropic"` | Anthropic Messages | `claude-sonnet-4-6` |

OpenAI-compatible services (Azure, local LLMs, etc.) work via `api_type="openai"` with a custom `base_url`.

## Configuration

```python
agent = Aigent(
    api_type="openai",
    api_key="sk-...",                  # or OPENAI_API_KEY env var
    base_url="https://api.openai.com/v1",  # or OPENAI_BASE_URL env var
    model="gpt-4o",                   # or OPENAI_MODEL env var
    system="You are helpful.",         # default system prompt for all sessions
    timeout=30.0,
    max_retries=3,
)
```

Environment variables per backend:

| Env | OpenAI | Anthropic |
|-----|--------|-----------|
| API key | `OPENAI_API_KEY` | `ANTHROPIC_API_KEY` |
| Base URL | `OPENAI_BASE_URL` | `ANTHROPIC_BASE_URL` |
| Model | `OPENAI_MODEL` | `ANTHROPIC_MODEL` |

## Error Handling

```python
from aigent import (
    Aigent,
    AuthenticationError,
    RateLimitError,
    APIError,
    ConnectionError,
    TimeoutError,
)

agent = Aigent()
try:
    with agent.session() as s:
        s.chat("Hello")
except AuthenticationError:
    print("Check your API key.")
except RateLimitError:
    print("Slow down.")
except (ConnectionError, TimeoutError):
    print("Network issue.")
except APIError as e:
    print(f"API returned {e.status_code}")
```

All exceptions inherit from `LLMError`.

## Streaming

```python
with agent.session() as s:
    for token in s.chat("Tell me a story", stream=True):
        print(token, end="", flush=True)
    # Tokens are also accumulated and auto-appended to history
```

## License

Apache 2.0 — see [LICENSE](LICENSE).
