From 02b4c7a35ac0b714bc045d54fb4bb45d1ce4e490 Mon Sep 17 00:00:00 2001 From: t Date: Sat, 13 Jun 2026 23:45:59 -0600 Subject: Add Codex Responses support and session debugging Teach provider config and auth resolution about the Codex Responses dialect, including user-facing `style = "openai_responses"` with `dialect = "codex"`. Serialize and parse Responses traffic with provider-specific reasoning replay, assistant phase metadata, and robust function-call assembly keyed by `output_index` so streamed tool inputs survive proxy quirks and empty terminal payloads. Also persist thinking origins and message metadata across sessions, add the Anthropic interleaved-thinking header switch, write per-session debug logs, and improve the TUI and scripts for inspecting tool output and session costs. --- src/models_toml.zig | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) (limited to 'src/models_toml.zig') diff --git a/src/models_toml.zig b/src/models_toml.zig index 955640d..622bdf6 100644 --- a/src/models_toml.zig +++ b/src/models_toml.zig @@ -21,7 +21,8 @@ //! //! # anthropic_messages-only knobs: //! api_version = # Anthropic-Version header; default "2023-06-01" -//! thinking = # disabled | enabled | adaptive (default: disabled) +//! thinking = # disabled | enabled | adaptive (default: disabled, +//! # or adaptive when `effort` is present) //! effort = # low | medium | high | xhigh | max (default: medium) //! # only used when thinking = "adaptive" //! thinking_budget_tokens = # max reasoning tokens for thinking = "enabled" @@ -268,13 +269,15 @@ fn ingestModel( break :blk null; }; + const has_effort = v.get("effort") != null; + const thinking: Thinking = blk: { if (v.get("thinking")) |t| { if (t.asString()) |s| { break :blk std.meta.stringToEnum(Thinking, s) orelse .disabled; } } - break :blk .disabled; + break :blk if (has_effort) .adaptive else .disabled; }; const effort: Effort = blk: { @@ -527,6 +530,39 @@ test "parseInto: anthropic adaptive thinking with effort" { try testing.expectEqual(false, def.thinking_interleaved); // default } +test "parseInto: anthropic effort implies adaptive thinking" { + var models = emptyModels(testing.allocator); + defer models.deinit(); + + const src = + \\[anthropic.opus] + \\model = "claude-opus-4-8" + \\effort = "high" + ; + try parseInto(&models, src); + + const def = models.defs.get("anthropic", "opus").?; + try testing.expectEqual(Thinking.adaptive, def.thinking); + try testing.expectEqual(Effort.high, def.effort); +} + +test "parseInto: explicit thinking overrides effort-implied adaptive thinking" { + var models = emptyModels(testing.allocator); + defer models.deinit(); + + const src = + \\[anthropic.haiku] + \\model = "claude-haiku-4-5-20251001" + \\thinking = "disabled" + \\effort = "high" + ; + try parseInto(&models, src); + + const def = models.defs.get("anthropic", "haiku").?; + try testing.expectEqual(Thinking.disabled, def.thinking); + try testing.expectEqual(Effort.high, def.effort); +} + test "parseInto: anthropic thinking disabled" { var models = emptyModels(testing.allocator); defer models.deinit(); -- cgit v1.3