diff options
| author | t <t@tjp.lol> | 2026-07-06 16:39:32 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-07-07 10:44:20 -0600 |
| commit | 0fa6d4209ff9b4a95e7d1955887aa4c73ee3423c (patch) | |
| tree | bb07dc02986bd67f6564f85949ad2cd784363514 /libpanto-c | |
| parent | 715fc34d833e043e9919fcce503ce3ec7cae5aea (diff) | |
expose openai_responses API style to C and Go bindings
Diffstat (limited to 'libpanto-c')
| -rw-r--r-- | libpanto-c/include/panto.h | 5 | ||||
| -rw-r--r-- | libpanto-c/src/lib.zig | 10 |
2 files changed, 8 insertions, 7 deletions
diff --git a/libpanto-c/include/panto.h b/libpanto-c/include/panto.h index 5457715..4302bb8 100644 --- a/libpanto-c/include/panto.h +++ b/libpanto-c/include/panto.h @@ -25,7 +25,7 @@ typedef struct { const uint8_t *ptr; size_t len; } PantoSlice; typedef enum { PANTO_OK = 0, PANTO_ERROR = 1 } PantoStatus; typedef enum { PANTO_NEXT_EVENT = 0, PANTO_NEXT_DONE = 1, PANTO_NEXT_ERROR = 2 } PantoNextStatus; -typedef enum { PANTO_OPENAI_CHAT = 0, PANTO_ANTHROPIC_MESSAGES = 1 } PantoAPIStyle; +typedef enum { PANTO_OPENAI_CHAT = 0, PANTO_ANTHROPIC_MESSAGES = 1, PANTO_OPENAI_RESPONSES = 2, PANTO_OPENAI_CODEX_RESPONSES = 3 } PantoAPIStyle; typedef enum { PANTO_REASONING_DEFAULT = 0, PANTO_REASONING_OFF, PANTO_REASONING_MINIMAL, PANTO_REASONING_LOW, PANTO_REASONING_MEDIUM, PANTO_REASONING_HIGH } PantoReasoningEffort; typedef enum { PANTO_THINKING_DISABLED = 0, PANTO_THINKING_ENABLED, PANTO_THINKING_ADAPTIVE } PantoThinking; typedef enum { PANTO_EFFORT_LOW = 0, PANTO_EFFORT_MEDIUM, PANTO_EFFORT_HIGH, PANTO_EFFORT_XHIGH, PANTO_EFFORT_MAX } PantoEffort; @@ -40,8 +40,9 @@ typedef struct { PantoSlice id, created, modified, last_user_message, base_url, typedef struct { PantoSessionInfo *ptr; size_t len; } PantoSessionInfoList; typedef struct { bool found; PantoSession *session; } PantoSessionResult; typedef struct { const char *api_key, *base_url, *model; PantoReasoningEffort reasoning; uint32_t max_tokens; } PantoOpenAIChatConfig; +typedef struct { const char *api_key, *base_url, *model; PantoReasoningEffort reasoning; uint32_t max_tokens; } PantoOpenAIResponsesConfig; typedef struct { const char *api_key, *base_url, *model, *api_version; uint32_t max_tokens; PantoThinking thinking; PantoEffort effort; bool has_thinking_budget_tokens; uint32_t thinking_budget_tokens; bool thinking_interleaved; } PantoAnthropicMessagesConfig; -typedef struct { PantoAPIStyle tag; union { PantoOpenAIChatConfig openai_chat; PantoAnthropicMessagesConfig anthropic_messages; } data; } PantoProviderConfig; +typedef struct { PantoAPIStyle tag; union { PantoOpenAIChatConfig openai_chat; PantoAnthropicMessagesConfig anthropic_messages; PantoOpenAIResponsesConfig openai_responses; } data; } PantoProviderConfig; typedef struct { uint32_t keep_verbatim; bool has_model; PantoProviderConfig model; bool has_compaction_prompt; const char *compaction_prompt; } PantoCompactionConfig; typedef struct { size_t max_attempts; uint64_t initial_delay_ms, max_delay_ms; double multiplier; bool jitter; } PantoRetryConfig; typedef struct { PantoProviderConfig provider; PantoCompactionConfig compaction; PantoRetryConfig retry; } PantoConfig; diff --git a/libpanto-c/src/lib.zig b/libpanto-c/src/lib.zig index 7f61ae3..4fcf94b 100644 --- a/libpanto-c/src/lib.zig +++ b/libpanto-c/src/lib.zig @@ -26,7 +26,7 @@ const MessageBuilder = struct { role: panto.MessageRole, blocks: std.ArrayList(p pub const PantoSlice = extern struct { ptr: ?[*]const u8, len: usize }; pub const PantoStatus = enum(c_int) { ok = 0, err = 1 }; pub const PantoNextStatus = enum(c_int) { event = 0, done = 1, err = 2 }; -pub const PantoAPIStyle = enum(c_int) { openai_chat = 0, anthropic_messages = 1 }; +pub const PantoAPIStyle = enum(c_int) { openai_chat = 0, anthropic_messages = 1, openai_responses = 2, openai_codex_responses = 3 }; pub const PantoReasoningEffort = enum(c_int) { default = 0, off, minimal, low, medium, high }; pub const PantoThinking = enum(c_int) { disabled = 0, enabled, adaptive }; pub const PantoEffort = enum(c_int) { low = 0, medium, high, xhigh, max }; @@ -40,8 +40,9 @@ pub const PantoSessionInfo = extern struct { id: PantoSlice, created: PantoSlice pub const PantoSessionInfoList = extern struct { ptr: ?[*]PantoSessionInfo, len: usize }; pub const PantoSessionResult = extern struct { found: bool, session: ?*PantoSession }; pub const PantoOpenAIChatConfig = extern struct { api_key: ?[*:0]const u8, base_url: ?[*:0]const u8, model: ?[*:0]const u8, reasoning: PantoReasoningEffort, max_tokens: u32 }; +pub const PantoOpenAIResponsesConfig = extern struct { api_key: ?[*:0]const u8, base_url: ?[*:0]const u8, model: ?[*:0]const u8, reasoning: PantoReasoningEffort, max_tokens: u32 }; pub const PantoAnthropicMessagesConfig = extern struct { api_key: ?[*:0]const u8, base_url: ?[*:0]const u8, model: ?[*:0]const u8, api_version: ?[*:0]const u8, max_tokens: u32, thinking: PantoThinking, effort: PantoEffort, has_thinking_budget_tokens: bool, thinking_budget_tokens: u32, thinking_interleaved: bool }; -pub const PantoProviderConfig = extern struct { tag: PantoAPIStyle, data: extern union { openai_chat: PantoOpenAIChatConfig, anthropic_messages: PantoAnthropicMessagesConfig } }; +pub const PantoProviderConfig = extern struct { tag: PantoAPIStyle, data: extern union { openai_chat: PantoOpenAIChatConfig, anthropic_messages: PantoAnthropicMessagesConfig, openai_responses: PantoOpenAIResponsesConfig } }; pub const PantoCompactionConfig = extern struct { keep_verbatim: u32, has_model: bool, model: PantoProviderConfig, has_compaction_prompt: bool, compaction_prompt: ?[*:0]const u8 }; pub const PantoRetryConfig = extern struct { max_attempts: usize, initial_delay_ms: u64, max_delay_ms: u64, multiplier: f64, jitter: bool }; pub const PantoConfig = extern struct { provider: PantoProviderConfig, compaction: PantoCompactionConfig, retry: PantoRetryConfig }; @@ -485,6 +486,8 @@ fn convertProvider(p: PantoProviderConfig) !panto.ProviderConfig { return switch (p.tag) { .openai_chat => .{ .openai_chat = .{ .api_key = try dupCStr(p.data.openai_chat.api_key), .base_url = try dupCStr(p.data.openai_chat.base_url), .model = try dupCStr(p.data.openai_chat.model), .reasoning = @enumFromInt(@intFromEnum(p.data.openai_chat.reasoning)), .max_tokens = p.data.openai_chat.max_tokens } }, .anthropic_messages => .{ .anthropic_messages = .{ .api_key = try dupCStr(p.data.anthropic_messages.api_key), .base_url = try dupCStr(p.data.anthropic_messages.base_url), .model = try dupCStr(p.data.anthropic_messages.model), .api_version = if (cstr(p.data.anthropic_messages.api_version).len == 0) "2023-06-01" else try dupCStr(p.data.anthropic_messages.api_version), .max_tokens = p.data.anthropic_messages.max_tokens, .thinking = @enumFromInt(@intFromEnum(p.data.anthropic_messages.thinking)), .effort = @enumFromInt(@intFromEnum(p.data.anthropic_messages.effort)), .thinking_budget_tokens = if (p.data.anthropic_messages.has_thinking_budget_tokens) p.data.anthropic_messages.thinking_budget_tokens else null, .thinking_interleaved = p.data.anthropic_messages.thinking_interleaved } }, + .openai_responses => .{ .openai_responses = .{ .api_key = try dupCStr(p.data.openai_responses.api_key), .base_url = try dupCStr(p.data.openai_responses.base_url), .model = try dupCStr(p.data.openai_responses.model), .reasoning = @enumFromInt(@intFromEnum(p.data.openai_responses.reasoning)), .max_tokens = p.data.openai_responses.max_tokens } }, + .openai_codex_responses => return error.UnsupportedProvider, }; } fn freeConfig(c: *panto.Config) void { @@ -506,9 +509,6 @@ fn freeProvider(pv: *panto.ProviderConfig) void { allocator.free(c.model); if (c.api_version.ptr != "2023-06-01".ptr) allocator.free(c.api_version); }, - // The Responses styles are not constructible across the C ABI (no - // PantoAPIStyle variant), so `convertProvider` never builds them; these - // cases exist only to keep the union switch exhaustive. .openai_responses, .openai_codex_responses => |c| { allocator.free(c.api_key); allocator.free(c.base_url); |
