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
//! Provider-neutral request types for the native runtime.
use serde::Serialize;
use supercode_interchange::ChatMessage;
/// A tool advertised to a model.
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct ToolSchema {
/// Tool name.
pub name: String,
/// Description the model uses to decide when to call it.
pub description: String,
/// JSON Schema for the tool's input object.
pub parameters: serde_json::Value,
}
impl ToolSchema {
/// Construct a tool schema.
pub fn new(
name: impl Into<String>,
description: impl Into<String>,
parameters: serde_json::Value,
) -> Self {
Self {
name: name.into(),
description: description.into(),
parameters,
}
}
}
/// A single model-completion request.
#[derive(Debug, Clone, PartialEq)]
pub struct ChatRequest {
/// Model id.
pub model: String,
/// Full conversation so far.
pub messages: Vec<ChatMessage>,
/// Tools to advertise (may be empty).
pub tools: Vec<ToolSchema>,
/// Optional sampling temperature.
pub temperature: Option<f32>,
/// Optional output token cap.
pub max_tokens: Option<u32>,
/// Reasoning/effort level, such as `"low"` or `"high"`.
pub effort: Option<String>,
/// Structured-output constraint sent as `response_format`.
pub response_format: Option<serde_json::Value>,
/// BP-13 (catalog D9 "Fast mode / service tiers"): the provider service
/// tier this request asks for (`"auto"`, `"priority"`, `"flex"`, …).
/// Sent verbatim as the OpenAI-compatible `service_tier` field; `None`
/// omits it, which is what every pre-BP-13 caller produced.
pub service_tier: Option<String>,
/// BP-13 (catalog D9 "Reasoning effort / thinking budgets"): a cap on
/// reasoning/thinking TOKENS for this request — Claude Code's
/// `MAX_THINKING_TOKENS`, the budget half of `effort`'s level half.
/// Sent as the unified `reasoning.max_tokens` field; `None` omits it.
pub thinking_budget: Option<u32>,
/// Arbitrary provider-native request fields.
pub extra_body: serde_json::Map<String, serde_json::Value>,
}
impl ChatRequest {
/// Construct a minimal request with a model and conversation.
pub fn new(model: impl Into<String>, messages: Vec<ChatMessage>) -> Self {
Self {
model: model.into(),
messages,
tools: Vec::new(),
temperature: None,
max_tokens: None,
effort: None,
response_format: None,
service_tier: None,
thinking_budget: None,
extra_body: serde_json::Map::new(),
}
}
}