Metadata-Version: 2.4
Name: agentfit-py
Version: 0.1.0
Summary: Fit your messages into the LLM context window. Token-aware truncation with multiple strategies, pluggable tokenizers. Python port of @mukundakatta/agentfit.
Project-URL: Homepage, https://github.com/MukundaKatta/agentfit-py
Project-URL: Issues, https://github.com/MukundaKatta/agentfit-py/issues
Project-URL: Source, https://github.com/MukundaKatta/agentfit-py
Project-URL: JS sibling, https://github.com/MukundaKatta/agentfit
Author-email: Mukunda Katta <mukunda.vjcs6@gmail.com>
License: MIT
License-File: LICENSE
Keywords: agents,ai,claude,context-window,gemini,llm,openai,tokens,truncation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
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: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# agentfit-py

[![PyPI](https://img.shields.io/pypi/v/agentfit-py.svg)](https://pypi.org/project/agentfit-py/)
[![Python](https://img.shields.io/pypi/pyversions/agentfit-py.svg)](https://pypi.org/project/agentfit-py/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

**Fit your messages into the LLM context window.** Token-aware truncation with multiple strategies, pluggable tokenizers. Zero runtime dependencies.

Python port of [@mukundakatta/agentfit](https://github.com/MukundaKatta/agentfit). The JS sibling has the full design notes; this README sticks to the Python API.

## Install

```bash
pip install agentfit-py
```

## Usage

```python
from agentfit import count, fit, OverBudgetError

messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user",   "content": "Hello there!"},
    {"role": "assistant", "content": "Hi! How can I help?"},
    {"role": "user",   "content": "Tell me a long story..."},
]

# Estimate tokens (heuristic; pass `tokenizer=...` to plug in tiktoken etc.)
count(messages, model="claude-sonnet-4-6")   # -> int

# Drop messages until under budget. System message + recent N are preserved.
result = fit(
    messages,
    max_tokens=8000,
    model="claude-sonnet-4-6",
    strategy="drop-oldest",      # or "drop-middle" / "priority"
    preserve_system=True,
    preserve_last_n=2,
)

result.messages   # list[dict]  -- survived
result.dropped    # list[dict]  -- removed
result.tokens     # {"before": int, "after": int, "budget": int}
result.fit        # True iff under budget
```

If the budget can't be reached even after dropping all non-protected messages, `fit()` raises `OverBudgetError` (carries the partial result). Use `on_over_budget="return-partial"` to return the over-budget result instead with `fit=False`.

## Strategies

| Strategy | Behavior |
|---|---|
| `drop-oldest` (default) | Drop earliest non-protected message first. |
| `drop-middle` | Drop messages closest to the center; preserves start + recent tail. |
| `priority` | Drop messages with the lowest `priority` field first (default `0`). |

## Custom tokenizer

Pass any `Callable[[str], int]`. Example with `tiktoken`:

```python
import tiktoken
enc = tiktoken.get_encoding("cl100k_base")
fit(messages, max_tokens=8000, tokenizer=lambda s: len(enc.encode(s)))
```

## API differences from the JS sibling

* `count()` and `fit()` use Python keyword args (`max_tokens=`, `preserve_system=`, etc.) instead of the JS options object.
* `fit()` returns a `FitResult` dataclass instead of a plain object.
* No `wrapFetch` / monkey-patching equivalents -- not needed in Python.

See the JS sibling's [README](https://github.com/MukundaKatta/agentfit) for the full design notes and broader algorithmic reasoning.
