mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-10-05 20:44:07 +08:00
fix: anchor compaction to provider input usage
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use serde::Serialize;
|
||||
|
||||
use super::ProviderType;
|
||||
use super::{ProviderType, Usage};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NewLlmCall {
|
||||
@@ -22,6 +22,14 @@ pub struct NewLlmCall {
|
||||
pub detailed: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct LlmCallUsageAnchor {
|
||||
pub request_type: ProviderType,
|
||||
pub usage: Usage,
|
||||
pub message_count: usize,
|
||||
pub tool_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct LlmCallSummary {
|
||||
pub call_id: String,
|
||||
|
||||
@@ -2,6 +2,8 @@ use std::ops::AddAssign;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::ProviderType;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct Usage {
|
||||
pub input_tokens: Option<u64>,
|
||||
@@ -12,6 +14,19 @@ pub struct Usage {
|
||||
pub reasoning_tokens: Option<u64>,
|
||||
}
|
||||
|
||||
impl Usage {
|
||||
/// Returns the provider-visible input context without counting cached tokens twice.
|
||||
pub(crate) fn context_input_tokens(self, provider: ProviderType) -> Option<u64> {
|
||||
let input = self.input_tokens?;
|
||||
match provider {
|
||||
ProviderType::OpenAiChat | ProviderType::OpenAiResponses => Some(input),
|
||||
ProviderType::Anthropic => input
|
||||
.checked_add(self.cache_read_tokens.unwrap_or_default())?
|
||||
.checked_add(self.cache_write_tokens.unwrap_or_default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Usage {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.input_tokens = sum(self.input_tokens, rhs.input_tokens);
|
||||
@@ -30,6 +45,41 @@ fn sum(left: Option<u64>, right: Option<u64>) -> Option<u64> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Usage;
|
||||
use crate::model::ProviderType;
|
||||
|
||||
#[test]
|
||||
fn openai_context_input_does_not_double_count_cached_tokens() {
|
||||
let usage = Usage {
|
||||
input_tokens: Some(140_649),
|
||||
cache_read_tokens: Some(120_000),
|
||||
cache_write_tokens: Some(10_000),
|
||||
..Usage::default()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
usage.context_input_tokens(ProviderType::OpenAiResponses),
|
||||
Some(140_649)
|
||||
);
|
||||
assert_eq!(
|
||||
usage.context_input_tokens(ProviderType::OpenAiChat),
|
||||
Some(140_649)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anthropic_context_input_includes_disjoint_cache_tokens() {
|
||||
let usage = Usage {
|
||||
input_tokens: Some(10_649),
|
||||
cache_read_tokens: Some(120_000),
|
||||
cache_write_tokens: Some(10_000),
|
||||
..Usage::default()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
usage.context_input_tokens(ProviderType::Anthropic),
|
||||
Some(140_649)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn turn_total_only_reports_fields_known_for_every_cycle() {
|
||||
|
||||
Reference in New Issue
Block a user