# anura-graph (Python)

Python client for the [AnuraMemory](https://anuramemory.com) knowledge graph API.

## Installation

```bash
pip install anura-graph
```

## Quick Start

```python
from graphmem import GraphMem

mem = GraphMem(api_key="gm_your_key_here")

# Store knowledge
result = mem.remember("Alice works at Acme Corp as a software engineer")
print(f"Extracted {result.extracted_count} facts")

# Retrieve context
ctx = mem.get_context("What does Alice do?")
print(ctx)

# Search for an entity
result = mem.search("Alice")
print(result.edges)
```

## All Methods

### Core

| Method | Description |
|--------|-------------|
| `remember(text)` | Extract knowledge from text and store in the graph |
| `get_context(query, options?)` | Retrieve graph context for a query |
| `search(entity)` | Search for an entity and its 1-hop neighbors |

### Graph Management

| Method | Description |
|--------|-------------|
| `get_graph()` | Get the full graph (nodes, edges, communities) |
| `ingest_triples(triples)` | Ingest triples directly into the graph |
| `delete_edge(id, blacklist?)` | Delete an edge, optionally blacklisting it |
| `update_edge_weight(id, weight?, increment?)` | Update an edge's weight |
| `delete_node(id)` | Delete a node and all its connected edges |
| `export_graph()` | Export the entire graph as portable JSON |
| `import_graph(data)` | Import a graph export into the current project |

### Traces

| Method | Description |
|--------|-------------|
| `list_traces(limit?, cursor?)` | List query traces with pagination |
| `get_trace(id)` | Get details for a specific trace |

### Blacklist

| Method | Description |
|--------|-------------|
| `list_blacklist(limit?, cursor?)` | List blacklisted triples |
| `add_to_blacklist(subject, predicate, object)` | Add a triple to the blacklist |
| `remove_from_blacklist(id)` | Remove a triple from the blacklist |

### Pending Facts

| Method | Description |
|--------|-------------|
| `list_pending(limit?, cursor?)` | List pending facts |
| `approve_fact(id)` | Approve a pending fact |
| `reject_fact(id, blacklist?)` | Reject a pending fact |
| `approve_all()` | Approve all pending facts |
| `reject_all()` | Reject all pending facts |

### Projects

| Method | Description |
|--------|-------------|
| `list_projects()` | List all projects |
| `create_project(name)` | Create a new project |
| `delete_project(id)` | Delete a project |
| `select_project(id)` | Switch active project |

### Communities

| Method | Description |
|--------|-------------|
| `list_communities()` | List all detected communities |
| `detect_communities()` | Run community detection |

### Other

| Method | Description |
|--------|-------------|
| `health()` | Check server health |
| `get_usage()` | Get usage and tier info |

## Configuration

```python
from graphmem import GraphMem, RetryConfig

mem = GraphMem(
    api_key="gm_your_key_here",
    base_url="https://anuramemory.com",  # default
    retry=RetryConfig(
        max_retries=3,       # default
        base_delay=0.5,      # seconds, default
        max_delay=10.0,      # seconds, default
        retry_on=[429, 500, 502, 503, 504],  # default
    ),
    timeout=30.0,  # seconds, default
)
```

## Rate Limit Info

After each request, rate limit info is available:

```python
mem.remember("some fact")
print(mem.rate_limit.remaining)  # requests remaining
print(mem.rate_limit.limit)      # total allowed per window
print(mem.rate_limit.reset)      # unix timestamp when window resets
```

## Error Handling

```python
from graphmem import GraphMem, GraphMemError

mem = GraphMem(api_key="gm_your_key_here")

try:
    mem.remember("some text")
except GraphMemError as e:
    print(f"API error {e.status}: {e}")
    print(e.body)  # raw response body
```

## Context Manager

The client can be used as a context manager to ensure the HTTP connection is properly closed:

```python
with GraphMem(api_key="gm_your_key_here") as mem:
    mem.remember("Alice works at Acme")
    ctx = mem.get_context("Alice")
```

## License

MIT
