Skip to main content

typesafe_system_one/
lib.rs

1//! Unofficial async Rust client for the TypeSafe AI System One API (Jev).
2//!
3//! System One answers *noul* (yes/no), *choice* (one-of-many), and *score*
4//! (rubric rating) questions about arbitrary JSON content ("state") in a single
5//! request, with calibrated probabilities and a confidence value you can gate
6//! on. This crate is a thin, well-behaved async client for it.
7//!
8//! # Quick start
9//!
10//! ```no_run
11//! # async fn run() -> Result<(), typesafe_system_one::Error> {
12//! use typesafe_system_one::{Client, Noul, Choice, Score, SystemOneRequest};
13//!
14//! let client = Client::from_env()?;
15//!
16//! let response = client
17//!     .system_one(
18//!         SystemOneRequest::new("I was charged twice.")
19//!             .question("billing", Noul::new("Is this about billing?"))
20//!             .question(
21//!                 "tone",
22//!                 Choice::new("What is the tone?")
23//!                     .option("calm", "A neutral or polite message")
24//!                     .option("angry", "An upset or hostile message"),
25//!             )
26//!             .question(
27//!                 "urgency",
28//!                 Score::new("How urgent is this?", ["Can wait", "Needs attention today"]),
29//!             ),
30//!     )
31//!     .await?;
32//!
33//! println!("model: {}", response.model);
34//! println!("billing noul: {:?}", response.noul("billing").map(|a| a.noul));
35//! if let Some(choice) = response.choice("tone") {
36//!     if choice.confidence >= 0.7 {
37//!         println!("tone: {}", choice.choice);
38//!     }
39//! }
40//! # Ok(())
41//! # }
42//! ```
43//!
44//! The client is async only: every method returns a future, and there is no
45//! blocking variant. Run it from an async runtime such as
46//! [`tokio`](https://crates.io/crates/tokio).
47//!
48//! # Overview
49//!
50//! - [`Client`] — construct with [`Client::builder`] or [`Client::from_env`].
51//! - [`SystemOneRequest`] — build a request with [`Noul`], [`Choice`], and
52//!   [`Score`] questions.
53//! - [`SystemOneResponse`] — typed answers plus usage and request metadata.
54//! - [`RetryPolicy`] — retries, backoff, and retry-after handling.
55//! - [`Error`] — everything that can go wrong.
56//!
57//! See `README.md` for a longer guide, and the repository's `SPEC.md` for the
58//! authoritative behavior contract both clients in this repo implement.
59//!
60//! This crate is unofficial and not affiliated with TypeSafe.
61
62#![deny(missing_docs)]
63#![forbid(unsafe_code)]
64#![doc = include_str!("../README.md")]
65
66mod answers;
67mod call_options;
68mod client;
69mod config;
70mod errors;
71mod logging;
72mod questions;
73mod request;
74mod retry;
75
76pub use answers::{
77    Answer, ChoiceAnswer, ModelMetadata, NoulAnswer, ScoreAnswer, SystemOneResponse, Usage,
78};
79pub use client::{Client, ClientBuilder, RequestOptions};
80pub use config::LogLevel;
81pub use errors::{ApiError, ApiErrorKind, Error};
82pub use questions::{Choice, Noul, NoulCriteria, Question, Score};
83pub use request::SystemOneRequest;
84pub use retry::RetryPolicy;
85
86/// The base URL used when neither the builder nor `TYPESAFE_BASE_URL` set one.
87pub const DEFAULT_BASE_URL: &str = "https://api.typesafe.ai";
88
89/// The model used when neither the builder nor `TYPESAFE_DEFAULT_MODEL` set one.
90pub const DEFAULT_MODEL: &str = "jev-latest";
91
92/// The default per-attempt timeout (covers connect through reading the full body).
93pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
94
95/// The `x-typesafe-request-id` response header, exposed on responses and errors.
96pub const REQUEST_ID_HEADER: &str = "x-typesafe-request-id";
97
98use std::time::Duration;