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
|
//! Per-provider configuration.
//!
//! `Config` is a tagged union keyed by `APIStyle`. Each variant carries the
//! settings specific to one wire dialect. New providers add a new tag and a
//! new payload struct here; nothing else in libpanto needs a central enum
//! refresh.
/// The wire dialect a provider speaks.
pub const APIStyle = enum {
openai_chat,
anthropic_messages,
};
/// Reasoning intensity hint sent to providers that support it.
///
/// `.default` omits the field entirely so the provider's own default applies.
/// `.off` sends `"none"` (supported by OpenRouter/NanoGPT; ignored or rejected
/// elsewhere). The remaining values mirror the `reasoning_effort` parameter
/// accepted by OpenAI reasoning models and OpenAI-compatible proxies.
pub const ReasoningEffort = enum {
default,
off,
minimal,
low,
medium,
high,
};
pub const OpenAIChatConfig = struct {
api_key: []const u8,
base_url: []const u8,
model: []const u8,
reasoning: ReasoningEffort = .default,
};
pub const AnthropicMessagesConfig = struct {
api_key: []const u8,
base_url: []const u8,
model: []const u8,
/// Value sent in the `anthropic-version` header.
api_version: []const u8 = "2023-06-01",
/// Required by Anthropic's Messages API.
max_tokens: u32 = 4096,
};
pub const Config = union(APIStyle) {
openai_chat: OpenAIChatConfig,
anthropic_messages: AnthropicMessagesConfig,
pub fn style(self: Config) APIStyle {
return @as(APIStyle, self);
}
};
const t = @import("std").testing;
test "Config - openai_chat variant" {
const cfg: Config = .{ .openai_chat = .{
.api_key = "sk-test",
.base_url = "https://api.openai.com/v1",
.model = "gpt-4o",
.reasoning = .high,
} };
try t.expectEqual(APIStyle.openai_chat, cfg.style());
try t.expectEqualStrings("sk-test", cfg.openai_chat.api_key);
try t.expectEqual(ReasoningEffort.high, cfg.openai_chat.reasoning);
}
test "Config - anthropic_messages variant" {
const cfg: Config = .{ .anthropic_messages = .{
.api_key = "sk-ant-test",
.base_url = "https://api.anthropic.com",
.model = "claude-sonnet-4-20250514",
} };
try t.expectEqual(APIStyle.anthropic_messages, cfg.style());
try t.expectEqualStrings("2023-06-01", cfg.anthropic_messages.api_version);
try t.expectEqual(@as(u32, 4096), cfg.anthropic_messages.max_tokens);
}
test "Config - openai_chat reasoning defaults to .default" {
const cfg: Config = .{ .openai_chat = .{
.api_key = "k",
.base_url = "u",
.model = "m",
} };
try t.expectEqual(ReasoningEffort.default, cfg.openai_chat.reasoning);
}
|