Metadata-Version: 2.4
Name: maximem-vity-sdk
Version: 0.1.0
Summary: Vity by Maximem AI — cross-session semantic memory SDK with profile-based recall and memory graph.
Author-email: Maximem AI <hello@maximem.ai>
License: MIT
Project-URL: Homepage, https://maximem.ai
Project-URL: Documentation, https://docs.maximem.ai/vity
Project-URL: Repository, https://github.com/maximem-ai/vity-sdk-python
Keywords: memory,ai,semantic-memory,hermes,vity,maximem
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.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<1,>=0.24
Provides-Extra: dev
Requires-Dist: pytest<9,>=7; extra == "dev"
Requires-Dist: build<2,>=1; extra == "dev"
Requires-Dist: twine<6,>=4; extra == "dev"
Dynamic: license-file

# maximem-vity-sdk

**Vity by Maximem AI** — a lightweight Python SDK for cross-session semantic
memory. Store facts and preferences, recall relevant context for a prompt, run
semantic search, and capture whole conversation turns — all over the Maximem
REST API.

```python
from maximem_vity import VityClient

client = VityClient(api_key="mx_...")

# Recall context ready to inject into a system prompt
context = client.recall(current_prompt="What color theme does the user like?")

# Store an explicit fact
client.store("User prefers dark mode", memory_type="preference")

# Semantic search
hits = client.search("editor preferences", top_k=5)
```

## Installation

```bash
pip install maximem-vity-sdk
```

Requires Python ≥ 3.9. The only runtime dependency is [`httpx`](https://www.python-httpx.org/).

## Authentication

Every request is authenticated with a Maximem API key (it starts with `mx_`).
**The API key owns the memory space** — `VityClient` takes no channel or user
ID. Use a *separate* API key whenever memories must be isolated between users
or accounts.

Get your key at [maximem.ai/dashboard](https://maximem.ai/dashboard).

```python
import os
from maximem_vity import VityClient

client = VityClient(api_key=os.environ["MAXIMEM_API_KEY"])
```

```bash
export MAXIMEM_API_KEY="mx_..."
```

## API

### `recall(current_prompt, recent_messages=None, max_tokens=1000, strategy="hybrid") -> str`

Returns a plain-text context block for the current prompt, ready to inject into
a system prompt (empty string if nothing relevant). `strategy` is one of
`"semantic"`, `"recency"`, or `"hybrid"`.

```python
context = client.recall(
    current_prompt="Remind me what we decided about the API.",
    recent_messages=[{"role": "user", "content": "Let's revisit the API."}],
    max_tokens=800,
)
```

### `store(content, memory_type="fact", category="", importance="medium") -> dict`

Stores a single explicit memory. `memory_type` accepts the high-level aliases
`fact`, `preference`, `emotion`, `episode`, `knowledge`, `profile` (mapped to
Maximem categories automatically), or pass `category` directly to override.
`importance` is `"low"`, `"medium"`, or `"high"`. Returns `{"id": ..., "stored": True}`.

```python
client.store("User's timezone is IST", memory_type="fact", importance="high")
```

### `search(query, top_k=10, limit=0, category="", min_score=0.0) -> list[dict]`

Semantic search. Returns a list of dicts shaped as
`{"content", "type", "score", "id", "created_at"}`. `top_k` is the convenience
limit (capped at 20 by the API); `limit` overrides it when set.

```python
for hit in client.search("favourite languages", top_k=5, min_score=0.3):
    print(hit["score"], hit["content"])
```

### `capture(messages, agent_id="hermes", session_key="") -> dict`

Captures a full conversation turn into long-term memory. `messages` is a list
of `{"role", "content", "timestamp"}` dicts (timestamps are filled in if
omitted). Returns `{"captured": N, "deduplicated": M}`.

```python
client.capture([
    {"role": "user", "content": "I hate comic sans"},
    {"role": "assistant", "content": "Noted — I'll avoid it."},
])
```

### `forget(query="", dry_run=True) -> dict`

Deletes memories matching a query. **Defaults to a dry run** — pass
`dry_run=False` to actually delete. Returns `{"count": N, "ids": [...]}`.

```python
preview = client.forget(query="old project notes")          # safe preview
client.forget(query="old project notes", dry_run=False)     # actually delete
```

### Convenience shims

- `ingest(messages, session_id="")` — alias for `capture()`.
- `get_profile()` — a broad search returning the user's stored memories.

### Lifecycle

`VityClient` holds a pooled HTTP connection. Close it explicitly or use it as a
context manager:

```python
with VityClient(api_key="mx_...") as client:
    client.store("User prefers tabs over spaces")
# connection closed automatically
```

## Error handling

All errors derive from `VityError`:

| Exception | Raised when |
|---|---|
| `VityAuthError` | API key missing or invalid (HTTP 401) |
| `VityRateLimitError` | Rate limit exceeded (HTTP 429) — back off and retry |
| `VityUnavailableError` | Network error, timeout, or service error (HTTP 5xx) |
| `VityError` | Any other API error |

```python
from maximem_vity import VityClient, VityError

try:
    client.store("...")
except VityError as e:
    logger.warning("Memory write failed: %s", e)
```

## Configuration

| Option | Default | Description |
|---|---|---|
| `api_key` | — | Required. Maximem API key (`mx_...`). |
| `endpoint` | `https://agenticrouter-prod.maximem.ai` | Override for staging. |
| `timeout` | `30.0` | Per-request timeout in seconds. |

## Development

```bash
pip install -e ".[dev]"
pytest                      # run the test suite
python -m build             # build the wheel + sdist into dist/
```

## License

MIT © Maximem AI
