Metadata-Version: 2.4
Name: aimind
Version: 1.6.1
Summary: Universal AI interface: multi-model chat, real streaming, adaptive image generation and 27 agents in one clean API - no account, no keys, nothing to configure
Author: aimind
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://pypi.org/project/aimind/
Project-URL: Documentation, https://pypi.org/project/aimind/
Project-URL: Changelog, https://pypi.org/project/aimind/
Keywords: ai,llm,chatbot,chat,streaming,image-generation,agents,multi-model,no-api-key,python
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: LEGAL.md
Requires-Dist: requests>=2.28.0
Provides-Extra: async
Requires-Dist: aiohttp>=3.8.0; extra == "async"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Dynamic: license-file

# AIMind

**One API. Many models. Image generation. 27 agents. No account, no keys, no limits you can hit.**

A pip-installable `aimind` package with a clean, quiet front end and a fully
self-contained core: every client prepares its own session, renews it
automatically, routes for the lowest latency, and runs parallel work on worker
threads. Call sites, return values, errors and logs stay clean — nothing about
how it works leaks into your code.

```bash
pip install aimind
```

**[Full user guide with examples → GUIDE.md](GUIDE.md)** — chat, streaming,
memory, attaching images to a chat, image generation, agents, errors,
parallelism, recipes and troubleshooting.

```python
from aimind import AIMind

ai = AIMind()                                  # session prepared automatically
print(ai.chat("Hello!"))

for chunk in ai.chat_stream("Tell me a story"):
    print(chunk, end="", flush=True)           # chunk by chunk, ~3s to first chunk

img = ai.generate_image("A sunset over mountains")
img.save("sunset.png")                         # best model, automatic fallback

print(ai.chat_with_agent("coding-mentor", "Explain decorators"))
print(ai.usage())                              # what has been used so far
```

## Measured latency

From `python tools/benchmark.py --image` (rerun anytime):

| phase | seconds | note |
| --- | --- | --- |
| client setup | 0.00 | session prepared in the background |
| first chat (cold) | 6.8 | includes any pending setup |
| steady chat (median) | 5.3 | 4.2–6.2 s range |
| **streaming: first chunk** | **3.4** | real incremental delivery |
| streaming: complete | 5.8 | |
| 4 parallel chats | 8.1 | vs 21.0 s one at a time (**2.6×**) |
| 3 models in parallel | 7.6 | |
| chat after a connection is replaced | 6.6 | replacement is invisible |
| image render | 9.8 | FLUX.2 Klein, best model available |

## How it stays fast

- **A connection is ready before you ask.** The first one is prepared while
  your code is still starting, so the first request does not pay a setup cost —
  and after every call the next one is prepared in the background.
- **Single-flight creation.** A burst of parallel calls costs *one* setup, not
  one per call — excess creators wait and reuse the result.
- **Two routes, chosen automatically.** The fastest route carries normal
  traffic (and true streaming). If it is blocked or throttled, the request is
  retried on an alternate route; you see nothing but a slightly slower reply.
- **Thread-safe pool, strict lock order.** Verified deadlock-free under
  8 threads × continuous session churn (regression test included).
- **Capped internals.** Health checks and probes never let a reasoning model
  ramble; diagnostics stay fast.
- **Parallel everything.** Image batches, multi-model runs, `ping()` and the
  test suite all use worker threads on separate sessions.

## First token, not just total time

What decides whether a chat feels fast is the time to the **first token**, so
that is what the library is tuned and measured for (medians of repeated live
runs with the session already active — `python tools/memory_probe.py`):

| category | model | first token | with a full 9.5k history |
| --- | --- | --- | --- |
| `fast` **(default)** | ministral-8b / qwen-2.5-7b | **3.6–5.0 s** | 2.7–2.9 s |
| `coder` | qwen3-coder-30b | 4.0 s | 3.6 s |
| `creative` | qwen3-30b-instruct | 4.9 s | 4.2 s |
| `powerful` | deepseek-v4-flash | 7.0 s | 5.5 s |
| `balanced` | gemma-4-26b | 6.6 s | 8.2 s |
| `reasoning` | deepseek-r1 | 12.3 s | 16.0 s |

A full conversation does **not** slow the first token down and does not make a
request heavier: history is sent as context, so a completely full window
behaves exactly like a short one.

## Memory and the context window

Conversations are remembered and windowed automatically. The window is
**10,000 characters** (the same rule the reference client uses): small chats are
sent whole, a long conversation keeps the newest turns and drops the oldest —
and unlike the reference client, it *tells you*:

```python
ai.memory_status()
# {'messages': 34, 'sent': 12, 'dropped': 22, 'chars': 14320,
#  'context_limit': 10000, 'percent': 143.2, 'windowed': True, 'full': True,
#  'advice': 'Context window is full - older messages are no longer sent. '
#            'Start a new chat with ai.new_chat() for the full history.'}

ai.last_notice     # same message, also logged once
ai.new_chat()      # clean, full-history conversation again
```

## Nothing to run out of

There is no counter to watch and no ceiling to plan around. Every call is
served by its own freshly prepared connection, a replacement is lined up in the
background straight after, and if a request is ever declined the library simply
moves that request onto the next connection and finishes it — chat, streaming
and images alike. You cannot hit a wall, and you never handle an error about
one.

```python
ai.usage()
# {'session': '...', 'requests': 3, 'tokens': 418,
#  'sessions_used': 3, 'rotates_automatically': True}

ai.session_status()        # connections used, renewals, active, totals
ai.new_session()           # prepare a new connection now (rarely needed)
```

Rotating every call also means parallel work never queues: a simultaneous
burst shares one live connection, and sequential calls each get a fresh one for
the lowest possible first token.

## Adaptive images

Every render starts on its own freshly prepared connection and the best
available model is chosen automatically, with instant fallbacks if it is not
offered at that moment:

```python
ai.list_image_models()     # catalogue: metadata + availability
```

| model | status |
| --- | --- |
| `black-forest-labs/flux.2-klein-4b` | default, best quality |
| `flux2-klein-4b-fp8` | automatic fallback |
| `sdxl` | automatic fallback |
| `black-forest-labs/flux.2-flex` | offered when the service provides it |
| `bytedance-seed/seedream-4.5` | offered when the service provides it |
| `recraft/recraft-v4-pro` | offered when the service provides it |

Asking for a model the service is not offering at that moment raises a clear
`ImageGenerationError` naming the alternatives, and nothing else happens.

## Everything else

- **Chat:** 12+ models (fast, balanced, powerful, creative, coder, reasoning),
  system prompts, temperature, memory, streaming with word buffering and
  callbacks.
- **Agents:** 27 built-ins (`coding-mentor`, `fitness-coach`, …) plus custom
  agents stored locally in `~/.aimind/`.
- **Errors:** `AIMindError`, `AuthenticationError`, `RateLimitError`,
  `ModelNotAvailableError`, `InvalidRequestError`, `ImageGenerationError`,
  `NetworkError`, `InvalidResponseError`, `ConfigurationError`.
- **Docs:** `aimind.help()` / `aimind.help("chat")` are built in.

## Tools

```bash
python tools/smoke.py --models      # 11 parallel checks with timings (~25 s)
python tools/benchmark.py --image   # the latency table above
python tools/memory_probe.py        # first-token table + prompt behaviour (live)
python tools/parity_check.py        # public surface vs. the reference package
```

```bash
python -m pytest tests -q                         # 58 offline tests, ~5 s, no network
RUN_LIVE=1 python -m pytest tests/test_live.py -q # 17 live tests, ~60 s
RUN_LIVE=1 python -m pytest tests/test_live.py -q -n 4        # parallel (pytest-xdist)
RUN_LIVE=1 AIMIND_TEST_IMAGE=1 python -m pytest tests/test_live.py -q -k image
```

The offline suite includes a **noise-free guard** that fails the build if any
internal name, provider, gateway or mechanism ever appears in `repr()`,
`usage()`, `session_status()`, `ping()`, `help()`, the bundled docs or the
error messages — and a **no-limits guard** that fails if a usage cap is ever
mentioned in the README, the guide, the bundled docs or any runtime output.

## Repository layout

```
aimind/            the library
  client.py        public surface: chat, streaming, images, agents, diagnostics
  identities.py    session pool: creation, renewal, single-flight, thread safety
  transport.py     routing: primary route (streaming) + alternate route
  fingerprints.py  per-session client identity
  models.py        model catalogue, category aliases, measured latencies
  agents.py        27 built-in agents
  docs.md          built-in documentation used by help()
examples/          6 runnable examples
tests/             offline (fast, deterministic) + live (parallel)
tools/             smoke, benchmark, parity checker
docs/PLAN.md       objective, architecture, parity matrix, task board
docs/INTERNALS.md  internal implementation reference (maintainers only)
docs/VERIFICATION.md  what was verified live, and every defect found on the way
CHANGELOG.md       what changed in each release
```

The public surface is exactly the reference API plus four error classes: no
engine classes, no transport classes, no internals. Everything else lives behind
its own module path and is free to change.

## Configuration

```python
ai = AIMind(
    model="balanced",        # category or concrete id; "reasoning" for deep thinking
    memory=True, max_history=50,
    auto_retry=True, max_retries=3, timeout=120, stream=False, temperature=0.7,
    api_key=None,            # optional, when you have your own key
    request_mode="auto",     # "auto" | "direct" | "alternate"
    fresh_session=True,      # start this client on a brand-new session
)
```

Environment: `AIMIND_HOME` (state directory), `AIMIND_LOG_LEVEL`.

## Releasing

```bash
python tools/publish.py --check                    # build + verify, upload nothing
python tools/publish.py --check --native           # also build a compiled tree
```

The release pipeline runs the offline suite, a live smoke test, the hardening
pass, `twine check --strict`, then installs the built wheel in a throwaway
environment and repeats the suite **and a real chat** from the installed
package, and finally scans every artifact for readable internals. See
[PUBLISHING.md](PUBLISHING.md).

## Licence and terms

**Free to use, not free to copy.** Call the API from your own software,
including commercial software, at no charge; read, quote and cite the
documentation. What is **not** permitted: decoding, decrypting, de-obfuscating,
decompiling or otherwise reverse engineering the distributed module code;
extracting or reconstructing its internals, keys or endpoints; circumventing or
removing any protection or notice; scraping, mirroring, bulk-copying or
mass-republishing the package or its documentation; and selling, reselling,
sublicensing or redistributing those internals or anything derived from them.
Those acts breach the licence and, in many countries, are unlawful in
themselves (anti-circumvention and copyright law).

* Full terms: [LEGAL.md](LEGAL.md) — also shipped with every install and
  readable from code with `aimind.terms()`.
* `LICENSE` is the short form; releases up to 1.5.1 were MIT and remain MIT for
  those who obtained them (`LICENSE-MIT`).

```python
import aimind
print(aimind.terms())          # the notice that covers this install
```

The module code in this distribution is intentionally shipped **encrypted** and
is not provided as readable source. The documentation and the guide are
readable on purpose — that is the part you are meant to learn from.
