38 lines
1.3 KiB
Go
38 lines
1.3 KiB
Go
package xai
|
|
|
|
import (
|
|
"github.com/QuantumNous/new-api/relaykit/dto"
|
|
|
|
"github.com/tidwall/gjson"
|
|
)
|
|
|
|
// xaiResponsesToolUsage reads xAI's billed server-side tool counts from
|
|
// usage.server_side_tool_usage_details (terminal stream frames carry the
|
|
// cumulative usage under response.usage; num_sources_used is not a billed
|
|
// count). web_search_calls replaces the web_search_call items and is priced by
|
|
// the web_search:grok* override; x_search is billed per fetched post and per
|
|
// fetched profile. gjson truncates fractional values and reads non-numbers as
|
|
// zero; SetBillableToolCount ignores negatives and settlement applies
|
|
// MaxBillableToolCallCount.
|
|
func xaiResponsesToolUsage(raw []byte) map[string]int {
|
|
details := gjson.GetBytes(raw, "usage.server_side_tool_usage_details")
|
|
if !details.Exists() {
|
|
details = gjson.GetBytes(raw, "response.usage.server_side_tool_usage_details")
|
|
}
|
|
if !details.IsObject() {
|
|
return nil
|
|
}
|
|
counts := make(map[string]int, 4)
|
|
if calls := details.Get("web_search_calls"); calls.Exists() {
|
|
counts[dto.BuildInToolWebSearch] = int(calls.Int())
|
|
counts[dto.BuildInToolWebSearchPreview] = 0
|
|
}
|
|
if posts := details.Get("x_posts_fetched"); posts.Exists() {
|
|
counts["x_search_posts"] = int(posts.Int())
|
|
}
|
|
if users := details.Get("x_users_fetched"); users.Exists() {
|
|
counts["x_search_profiles"] = int(users.Int())
|
|
}
|
|
return counts
|
|
}
|