summaryrefslogtreecommitdiff
path: root/libpanto/src/conversation.zig
diff options
context:
space:
mode:
Diffstat (limited to 'libpanto/src/conversation.zig')
-rw-r--r--libpanto/src/conversation.zig27
1 files changed, 23 insertions, 4 deletions
diff --git a/libpanto/src/conversation.zig b/libpanto/src/conversation.zig
index 0e9a4e9..6776412 100644
--- a/libpanto/src/conversation.zig
+++ b/libpanto/src/conversation.zig
@@ -13,6 +13,22 @@ pub fn textualBlockFromSlice(alloc: Allocator, slice: []const u8) !TextualBlock
return buf;
}
+/// A reasoning/thinking block from the assistant.
+///
+/// `text` is the streamed reasoning content. `signature` is the opaque
+/// integrity token Anthropic emits with extended-thinking responses and
+/// requires echoed back verbatim on follow-up turns. It is optional because
+/// other providers (OpenAI-compatible APIs) do not produce it.
+pub const ThinkingBlock = struct {
+ text: TextualBlock = .empty,
+ signature: ?[]const u8 = null,
+
+ pub fn deinit(self: *ThinkingBlock, alloc: Allocator) void {
+ self.text.deinit(alloc);
+ if (self.signature) |sig| alloc.free(sig);
+ }
+};
+
pub const ToolUseBlock = struct {
id: []const u8,
name: []const u8,
@@ -37,13 +53,16 @@ pub const ToolResultBlock = struct {
pub const ContentBlock = union(enum) {
Text: TextualBlock,
- Thinking: TextualBlock,
+ Thinking: ThinkingBlock,
ToolUse: ToolUseBlock,
ToolResult: ToolResultBlock,
pub fn deinit(self: *ContentBlock, alloc: Allocator) void {
switch (self.*) {
- inline else => |*b| b.deinit(alloc),
+ .Text => |*b| b.deinit(alloc),
+ .Thinking => |*b| b.deinit(alloc),
+ .ToolUse => |*b| b.deinit(alloc),
+ .ToolResult => |*b| b.deinit(alloc),
}
}
};
@@ -175,11 +194,11 @@ test "ContentBlock - Thinking variant" {
defer conv.deinit();
try conv.addAssistantMessage(&.{
- .{ .Thinking = try textualBlockFromSlice(allocator, "hmm...") },
+ .{ .Thinking = .{ .text = try textualBlockFromSlice(allocator, "hmm...") } },
.{ .Text = try textualBlockFromSlice(allocator, "answer") },
});
try std.testing.expectEqual(@as(usize, 2), conv.messages.items[0].content.items.len);
- try std.testing.expectEqualStrings("hmm...", conv.messages.items[0].content.items[0].Thinking.items);
+ try std.testing.expectEqualStrings("hmm...", conv.messages.items[0].content.items[0].Thinking.text.items);
try std.testing.expectEqualStrings("answer", conv.messages.items[0].content.items[1].Text.items);
}