//! 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); }