# reka
Async Rust SDK for [Reka API](https://docs.reka.ai/).
## Installation
```toml
[dependencies]
reka = "0.1.0"
```
By default the crate uses `reqwest` with `rustls-tls`. To use platform-native TLS instead:
```toml
[dependencies]
reka = { version = "0.1.0", default-features = false, features = ["native-tls"] }
```
## Authentication
Set `REKA_API_KEY` in your environment:
```sh
export REKA_API_KEY=...
```
You can then create a client with `Client::from_env()`, or build one explicitly with `Client::new(...)` or `Client::with_config(...)`.
## Quick Start
```rust,no_run
use reka::{ChatMessage, Client, CreateChatCompletionArgs, ModelId};
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), reka::RekaError> {
let client = Client::from_env()?;
let args = CreateChatCompletionArgs::new(
ModelId::flash(),
vec![ChatMessage::user("Reply with the single word OK.")],
)
.with_max_tokens(32);
let response = client.chat().create(&args).await?;
let content = response.choices[0]
.message
.content
.as_deref()
.unwrap_or_default();
println!("{content}");
Ok(())
}
```
## Streaming
Streaming uses the same args type as non-streaming chat requests:
```rust,no_run
use reka::{ChatMessage, Client, CreateChatCompletionArgs, ModelId};
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), reka::RekaError> {
let client = Client::from_env()?;
let args = CreateChatCompletionArgs::new(
ModelId::flash(),
vec![ChatMessage::user("Stream a short greeting.")],
);
let _stream = client.chat().stream(&args).await?;
Ok(())
}
```
## Research
Research requests build on top of chat-style messages with additional research options:
```rust,no_run
use reka::{
ChatMessage, Client, CreateResearchArgs, ModelId, UserLocation, WebSearchOptions,
};
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), reka::RekaError> {
let client = Client::from_env()?;
let args = CreateResearchArgs::new(
ModelId::flash_research(),
vec![ChatMessage::user("Summarize the latest Reka product announcements.")],
)
.with_web_search(
WebSearchOptions::new()
.with_max_uses(3)
.with_user_location(
UserLocation::new()
.with_country("US")
.with_timezone("America/Los_Angeles"),
),
);
let _response = client.research().create(&args).await?;
Ok(())
}
```
## Vision
Vision APIs follow the same pattern with typed `*Args` values:
```rust,no_run
use reka::{Client, DeleteVideoArgs, GetVideoArgs, ListVideosArgs};
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), reka::RekaError> {
let client = Client::from_env()?;
let _health = client.vision().health().await?;
let _videos = client
.vision()
.videos()
.list(&ListVideosArgs::new().with_ids(["video-1", "video-2"]))
.await?;
let _video = client
.vision()
.videos()
.get(&GetVideoArgs::new("video-1"))
.await?;
let _deleted = client
.vision()
.videos()
.delete(&DeleteVideoArgs::new("video-2"))
.await?;
Ok(())
}
```
## Configuration
Use `ClientConfig` when you need custom base URLs, timeouts, headers, or a custom user agent:
```rust
use std::time::Duration;
use reka::{Client, ClientConfig};
let config = ClientConfig::builder("test-api-key")
.timeout(Duration::from_secs(10))
.connect_timeout(Duration::from_secs(3))
.build()?;
let client = Client::with_config(config)?;
assert_eq!(client.config().timeout(), Duration::from_secs(10));
# Ok::<(), reka::RekaError>(())
```
## Notes
- The crate is async and expects a Tokio runtime.
- Use `ModelId::flash()`, `ModelId::core()`, `ModelId::edge()`, and related helpers for common model IDs.
- Unknown API fields are preserved in `extra` maps across most response types.
- Docs for the raw HTTP API are intentionally not exposed; the public surface is the typed client API.
## License
MIT