summaryrefslogtreecommitdiff
path: root/libpanto/src/provider.zig
diff options
context:
space:
mode:
Diffstat (limited to 'libpanto/src/provider.zig')
-rw-r--r--libpanto/src/provider.zig16
1 files changed, 13 insertions, 3 deletions
diff --git a/libpanto/src/provider.zig b/libpanto/src/provider.zig
index bc39026..ab60678 100644
--- a/libpanto/src/provider.zig
+++ b/libpanto/src/provider.zig
@@ -3,7 +3,9 @@ const std = @import("std");
const config_mod = @import("config.zig");
const conversation = @import("conversation.zig");
const tool_registry_mod = @import("tool_registry.zig");
+const session_mod = @import("session.zig");
pub const ToolRegistry = tool_registry_mod.ToolRegistry;
+pub const Usage = session_mod.Usage;
pub const ContentBlockType = enum {
Text,
@@ -35,13 +37,21 @@ pub const ContentBlockType = enum {
/// or in the Provider (HTTP/parse/stream failure). It is the last callback the
/// receiver will see for that turn. `onError` itself cannot fail; receivers
/// must swallow secondary failures during cleanup.
+///
+/// `onMessageComplete`'s `usage` argument carries the wire-reported token
+/// counts for the just-finished assistant turn. Providers fire this exactly
+/// once per successful turn. `usage` is `null` only when the wire genuinely
+/// did not deliver any usage information — chiefly OpenAI-compatible proxies
+/// (OpenRouter, vLLM, some self-hosted backends) that ignore
+/// `stream_options.include_usage`. Receivers that compute cost should record
+/// the null case explicitly ("unknown") rather than treating it as zero.
pub const ReceiverVTable = struct {
onMessageStart: *const fn (*anyopaque, conversation.MessageRole) anyerror!void,
onBlockStart: *const fn (*anyopaque, ContentBlockType, usize) anyerror!void,
onToolDetails: *const fn (*anyopaque, usize, []const u8, []const u8) anyerror!void,
onContentDelta: *const fn (*anyopaque, usize, []const u8) anyerror!void,
onBlockComplete: *const fn (*anyopaque, usize, conversation.ContentBlock) anyerror!void,
- onMessageComplete: *const fn (*anyopaque, conversation.Message) anyerror!void,
+ onMessageComplete: *const fn (*anyopaque, conversation.Message, ?Usage) anyerror!void,
onError: *const fn (*anyopaque, anyerror) void,
};
@@ -69,8 +79,8 @@ pub const Receiver = struct {
try self.vtable.onBlockComplete(self.ptr, block_index, block);
}
- pub fn onMessageComplete(self: Receiver, message: conversation.Message) !void {
- try self.vtable.onMessageComplete(self.ptr, message);
+ pub fn onMessageComplete(self: Receiver, message: conversation.Message, usage: ?Usage) !void {
+ try self.vtable.onMessageComplete(self.ptr, message, usage);
}
pub fn onError(self: Receiver, err: anyerror) void {