Skip to main content

jev_sdk/
lib.rs

1//! # jev-sdk
2//!
3//! A Rust client for the [TypeSafe AI](https://typesafe.ai) System One API.
4//!
5//! [Jev](https://typesafe.ai/blog/introducing-system-one-models-and-jev) is a
6//! System One model: instead of generating text, it evaluates typed
7//! *questions* against a *state* and returns structured decisions with
8//! calibrated probabilities and confidence — fast enough to sit inside
9//! ordinary code paths.
10//!
11//! ## Quick start
12//!
13//! ```no_run
14//! use jev_sdk::{Choice, Noul, Question, Score, TypeSafeClient};
15//!
16//! # async fn example() -> Result<(), jev_sdk::Error> {
17//! // Reads TYPESAFE_API_KEY from the environment.
18//! let client = TypeSafeClient::from_env()?;
19//!
20//! let ticket = "Hi, I've been trying to connect my Stripe account for 3 days \
21//!               and it keeps failing. I'm losing sales. Please help ASAP.";
22//!
23//! let response = client
24//!     .system_one(
25//!         ticket,
26//!         [
27//!             (
28//!                 "department",
29//!                 Question::from(Choice::new(
30//!                     "Which team should handle this",
31//!                     [
32//!                         ("billing", Some("Payment or subscription issues")),
33//!                         ("technical", Some("Bugs or integration problems")),
34//!                         ("sales", Some("Pricing or account questions")),
35//!                     ],
36//!                 )),
37//!             ),
38//!             (
39//!                 "frustration",
40//!                 Question::from(Score::new(
41//!                     "How frustrated the customer appears",
42//!                     ["Calm, just stating facts", "Frustrated but civil", "Very angry"],
43//!                 )),
44//!             ),
45//!             (
46//!                 "is_urgent",
47//!                 Question::from(Noul::new("The message conveys urgency or time-sensitivity")),
48//!             ),
49//!         ],
50//!     )
51//!     .await?;
52//!
53//! let department = response.choice("department").unwrap();
54//! println!("route to {} (confidence {:.2})", department.choice, department.confidence);
55//! println!("frustration: {:.2}", response.score("frustration").unwrap().score);
56//! println!("urgent: {:.3}", response.noul("is_urgent").unwrap().noul);
57//! # Ok(())
58//! # }
59//! ```
60//!
61//! ## Configuration
62//!
63//! | Setting | Environment variable | Default |
64//! |---------|----------------------|---------|
65//! | API key | `TYPESAFE_API_KEY` | — (required) |
66//! | Model | `TYPESAFE_DEFAULT_MODEL` | `jev-latest` |
67//! | Base URL | `TYPESAFE_BASE_URL` | `https://api.typesafe.ai` |
68//!
69//! Use [`TypeSafeClient::builder`] for timeouts, retry policy, extra headers,
70//! or a custom `reqwest` client. See [`RetryPolicy`] for retry behavior
71//! (transient `429`/`529` responses are retried with exponential backoff by
72//! default).
73
74mod client;
75mod error;
76mod models;
77mod question;
78mod response;
79mod retry;
80
81pub use client::{
82    ClientBuilder, TypeSafeClient, DEFAULT_BASE_URL, DEFAULT_MODEL, DEFAULT_TIMEOUT, ENV_API_KEY,
83    ENV_BASE_URL, ENV_DEFAULT_MODEL,
84};
85pub use error::{ApiError, Error};
86pub use models::{ListModelsResponse, ModelCard};
87pub use question::{Choice, IntoContent, IntoDescription, Noul, NoulCriteria, Question, Score};
88pub use response::{Answer, ChoiceAnswer, NoulAnswer, ScoreAnswer, SystemOneResponse, Usage};
89pub use retry::RetryPolicy;