1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! Async Rust SDK for the [TypeSafe AI](https://typesafe.ai) API.
//!
//! The crate is published as `typesafe-sdk-rust` because `typesafe-sdk` is
//! already taken on crates.io; the library it builds is `typesafe_sdk`, so
//! callers write `use typesafe_sdk::...`.
//!
//! # Asking questions
//!
//! A call asks a set of named questions about a state. The set is built once,
//! validated and serialized by [`Questions::prepare`], and the resulting
//! [`PreparedQuestions`] is reused by every call that asks it. A [`Client`]
//! sends it: [`Client::system_one`] makes a request, whose methods set the
//! model, the deadline, extra headers and extra body members, and
//! [`send`](SystemOne::send) sends it and decodes the answers.
//!
//! ```
//! use std::time::Duration;
//!
//! use typesafe_sdk::{Choice, Client, Noul, Questions, Score};
//!
//! let questions = Questions::new()
//! .noul("billing", Noul::new().instructions("Is this about billing?"))
//! .choice("tone", Choice::new(["calm", "angry"]).instructions("What is the tone?"))
//! .score("urgency", Score::new(["can wait", "this week", "today"]))
//! .prepare()?;
//! assert_eq!(questions.names().collect::<Vec<_>>(), ["billing", "tone", "urgency"]);
//!
//! // `Client::from_env()` reads the same settings from TYPESAFE_API_KEY and
//! // friends. Building connects to nothing.
//! let client = Client::builder().api_key("your-api-key").build()?;
//!
//! let state = "I was charged twice for one order.";
//! let request = client
//! .system_one(state, &questions)
//! .model("jev-latest")
//! .timeout(Duration::from_secs(2))
//! .header("x-team", "billing");
//!
//! // Sending needs a Tokio runtime; this example stops before it.
//! async fn ask(request: typesafe_sdk::SystemOne<'_, typesafe_sdk::HyperTransport, str>)
//! -> Result<f64, typesafe_sdk::Error> {
//! let response = request.send().await?;
//! Ok(response.answers().noul("billing").map_or(0.0, |answer| answer.noul()))
//! }
//! drop(ask(request));
//! # Ok::<(), typesafe_sdk::Error>(())
//! ```
//!
//! # Runtime requirements
//!
//! Every network operation is `async` and expects a [Tokio] runtime whose
//! **time driver is enabled** (`#[tokio::main]`, or a `Builder` with
//! `enable_time()` / `enable_all()`). Per-attempt deadlines and HTTP/2
//! keep-alive both arm timers, and Tokio panics when a timer is created on a
//! runtime without that driver.
//!
//! # Safety
//!
//! The crate is `#![forbid(unsafe_code)]`. Dependencies that use `unsafe`
//! internally are confined to single modules so that swapping one out is a
//! local change.
//!
//! [Tokio]: https://docs.rs/tokio
pub use crate::;
pub use crateQuestionSet;
/// Implements [`QuestionSet`](trait@QuestionSet) and [`AnswerSet`] for a struct with one field
/// per question.
///
/// Available with the `macros` feature, which is on by default.
///
/// ```
/// use typesafe_sdk::{ChoiceAnswer, NoulAnswer, QuestionSet, ScoreAnswer};
///
/// #[derive(QuestionSet)]
/// struct Ticket {
/// #[noul(instructions = "Is this about billing?", yes = "payments or invoices")]
/// billing: NoulAnswer,
/// #[choice(instructions = "What is the tone?", options("calm" = "neutral or polite", "angry"))]
/// tone: ChoiceAnswer,
/// #[score(instructions = "How urgent?", levels("can wait", "this week", "today"))]
/// urgency: ScoreAnswer,
/// }
///
/// assert_eq!(Ticket::prepared().names().collect::<Vec<_>>(), ["billing", "tone", "urgency"]);
/// ```
pub use QuestionSet;
/// Compiles every Rust block of `README.md` as a doctest, so the front page
/// cannot drift from the API. The typed-answers block needs the derive, hence
/// the feature.
;