summaryrefslogtreecommitdiff
path: root/libpanto/src/provider.zig
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-06-02 15:00:44 -0600
committert <t@tjp.lol>2026-06-02 16:37:32 -0600
commit8b88b886346460b1ab29edb03ad85bc3bb565a45 (patch)
tree13b9ab56061a722641389b5fc8ac1113d09b66e5 /libpanto/src/provider.zig
parent7268c0b8e8bcf4b325581fabe7476a394f167738 (diff)
compaction
Diffstat (limited to 'libpanto/src/provider.zig')
-rw-r--r--libpanto/src/provider.zig31
1 files changed, 31 insertions, 0 deletions
diff --git a/libpanto/src/provider.zig b/libpanto/src/provider.zig
index 1a8ee4e..6ccbefe 100644
--- a/libpanto/src/provider.zig
+++ b/libpanto/src/provider.zig
@@ -14,6 +14,28 @@ pub const ContentBlockType = enum {
ToolResult,
};
+/// Heuristic detector for provider context-overflow rejections, applied to
+/// an HTTP 400 error response body. Both OpenAI-compatible and Anthropic
+/// APIs reject oversized requests on the input side with HTTP 400 and a
+/// recognizable message; matching it lets the agent compact and retry
+/// instead of surfacing a hard error.
+///
+/// Markers (case-sensitive substrings, as the wire emits them):
+/// - OpenAI: `context_length_exceeded`, `maximum context length`
+/// - Anthropic: `prompt is too long`
+pub fn isContextOverflowBody(body: []const u8) bool {
+ const markers = [_][]const u8{
+ "context_length_exceeded",
+ "maximum context length",
+ "prompt is too long",
+ "context window",
+ };
+ for (markers) |m| {
+ if (std.mem.indexOf(u8, body, m) != null) return true;
+ }
+ return false;
+}
+
/// Vtable for receiving streaming events from a Provider.
///
/// The lifecycle callbacks (`onMessageStart` ... `onMessageComplete`) return
@@ -143,3 +165,12 @@ pub const StreamFn = *const fn (
conv: *conversation.Conversation,
receiver: *Receiver,
) anyerror!void;
+
+test "isContextOverflowBody - matches known markers, rejects others" {
+ const t2 = std.testing;
+ try t2.expect(isContextOverflowBody("{\"error\":{\"code\":\"context_length_exceeded\"}}"));
+ try t2.expect(isContextOverflowBody("This model's maximum context length is 8192 tokens"));
+ try t2.expect(isContextOverflowBody("prompt is too long: 250000 tokens > 200000 maximum"));
+ try t2.expect(!isContextOverflowBody("{\"error\":{\"code\":\"invalid_api_key\"}}"));
+ try t2.expect(!isContextOverflowBody("rate limit exceeded"));
+}