summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig70
1 files changed, 48 insertions, 22 deletions
diff --git a/src/main.zig b/src/main.zig
index 20686eb..28f1144 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -704,6 +704,13 @@ fn persistTurn(
model: []const u8,
per_message_usage: []const ?panto.session_manager.Usage,
) !void {
+ var batch_messages: std.ArrayList(panto.session_manager.DiskMessage) = .empty;
+ defer batch_messages.deinit(alloc);
+ var batch_providers: std.ArrayList(?[]const u8) = .empty;
+ defer batch_providers.deinit(alloc);
+ var batch_models: std.ArrayList(?[]const u8) = .empty;
+ defer batch_models.deinit(alloc);
+
var i = start_index;
var assistant_seen: usize = 0;
while (i < conv.messages.items.len) : (i += 1) {
@@ -718,22 +725,23 @@ fn persistTurn(
blocks[allocated] = try panto.session.contentBlockToDisk(alloc, block);
allocated += 1;
}
+ if (msg.role == .assistant and hasToolUseWithoutFollowingResults(conv, i)) {
+ for (blocks[0..allocated]) |b| b.deinit(alloc);
+ alloc.free(blocks);
+ continue;
+ }
switch (msg.role) {
.system => {
// Mid-turn system messages aren't a thing in pantograph today.
// Treat as harmless and persist verbatim, sans stamps.
- _ = try mgr.appendMessage(
- .{ .role = .system, .content = blocks },
- null,
- null,
- );
+ try batch_messages.append(alloc, .{ .role = .system, .content = blocks });
+ try batch_providers.append(alloc, null);
+ try batch_models.append(alloc, null);
},
.user => {
- _ = try mgr.appendMessage(
- .{ .role = .user, .content = blocks },
- provider,
- model,
- );
+ try batch_messages.append(alloc, .{ .role = .user, .content = blocks });
+ try batch_providers.append(alloc, provider);
+ try batch_models.append(alloc, model);
},
.assistant => {
// Pair this assistant message with its usage, if the
@@ -745,19 +753,37 @@ fn persistTurn(
else
null;
assistant_seen += 1;
- _ = try mgr.appendMessage(
- .{
- .role = .assistant,
- .content = blocks,
- .provider = try alloc.dupe(u8, provider),
- .model = try alloc.dupe(u8, model),
- .stop_reason = try alloc.dupe(u8, "stop"),
- .usage = usage,
- },
- null,
- null,
- );
+ try batch_messages.append(alloc, .{
+ .role = .assistant,
+ .content = blocks,
+ .provider = try alloc.dupe(u8, provider),
+ .model = try alloc.dupe(u8, model),
+ .stop_reason = try alloc.dupe(u8, "stop"),
+ .usage = usage,
+ });
+ try batch_providers.append(alloc, null);
+ try batch_models.append(alloc, null);
},
}
}
+ try mgr.appendMessagesAtomic(batch_messages.items, batch_providers.items, batch_models.items);
+}
+
+fn hasToolUseWithoutFollowingResults(conv: *const panto.conversation.Conversation, index: usize) bool {
+ const msg = conv.messages.items[index];
+ for (msg.content.items) |block| {
+ if (block != .ToolUse) continue;
+ if (index + 1 >= conv.messages.items.len) return true;
+ const next = conv.messages.items[index + 1];
+ if (next.role != .user) return true;
+ var found = false;
+ for (next.content.items) |next_block| {
+ if (next_block == .ToolResult and std.mem.eql(u8, next_block.ToolResult.tool_use_id, block.ToolUse.id)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) return true;
+ }
+ return false;
}