# ollama-kit

[![Crates.io](https://img.shields.io/crates/v/ollama-kit.svg)](https://crates.io/crates/ollama-kit)
[![Documentation](https://docs.rs/ollama-kit/badge.svg)](https://docs.rs/ollama-kit)
[![License](https://img.shields.io/crates/l/ollama-kit.svg)](https://github.com/Pulko/ollama-kit/blob/main/LICENSE)
[![Crates.io downloads](https://img.shields.io/crates/d/ollama-kit.svg)](https://crates.io/crates/ollama-kit)
[![CI](https://img.shields.io/github/actions/workflow/status/Pulko/ollama-kit/rust.yml?branch=main)](https://github.com/Pulko/ollama-kit/actions/workflows/rust.yml)

Thin layer on [`ollama-rs`](https://docs.rs/ollama-rs): configured `reqwest`, optional `call` / `call_stream` (timeouts, concurrency, retries), and `ensure` for “is this model local?” (lists; may `pull` only when `auto_pull` + `Development`). Does not start Ollama.

## Cargo.toml

```toml
ollama-kit = "0.2"
ollama-kit = { version = "0.2", features = ["stream"] }
```

## API sketch

| | |
|--|--|
| `OllamaRuntime::new` + `RuntimeConfig` | URL, timeouts, auth; rejects `Production` + `auto_pull`. |
| `ensure` | List local names; pull only if `auto_pull` and `Development`. |
| `auto_pull` / `mode` | Getters mirroring [`RuntimeConfig`]. |
| `call` / `call_stream` | Guarded ollama-rs calls. |
| `client` / `guard` | Unguarded; use `guard().run` for `Fn()` shapes. |

## Example

```rust
use std::time::Duration;

use ollama_kit::{OllamaRuntime, RuntimeConfig, RuntimeMode};

async fn demo() -> ollama_kit::Result<()> {
    let rt = OllamaRuntime::new(RuntimeConfig {
        base_url: "http://127.0.0.1:11434".into(),
        timeout: Duration::from_secs(120),
        connect_timeout: Duration::from_secs(10),
        max_retries: 2,
        max_concurrent: 4,
        auto_pull: false,
        mode: RuntimeMode::Production,
        auth: None,
    })
    .await?;

    rt.ensure("mistral").await?;
    let _ = rt.call(|c| c.list_local_models()).await?;
    Ok(())
}
```

## Docs / license

[cargo doc](https://docs.rs/ollama-kit). MIT — `LICENSE`.
