use defect_core::llm::{ProviderChunk, ProviderError, Usage};
use futures::Stream;
use toac::body::codec::sse::SseEventStream;
use tokio_util::sync::CancellationToken;
use super::openai_chat;
use crate::wire::openai::components as wire;
pub fn decode_stream(
sse: SseEventStream,
cancel: CancellationToken,
) -> impl Stream<Item = Result<ProviderChunk, ProviderError>> + Send {
openai_chat::decode_stream_with_usage_parser(sse, cancel, usage_from_deepseek_wire)
}
fn usage_from_deepseek_wire(
raw_usage: Option<&serde_json::Value>,
wire_usage: &wire::CompletionUsage,
) -> Usage {
let raw_cache_hit_tokens = raw_usage
.and_then(|usage| usage.get("prompt_cache_hit_tokens"))
.and_then(serde_json::Value::as_u64);
Usage {
input_tokens: u64::try_from(wire_usage.prompt_tokens).ok(),
output_tokens: u64::try_from(wire_usage.completion_tokens).ok(),
cache_read_input_tokens: raw_cache_hit_tokens.or_else(|| {
wire_usage
.prompt_tokens_details
.as_ref()
.and_then(|details| details.cached_tokens)
.and_then(|value| u64::try_from(value).ok())
}),
cache_creation_input_tokens: None,
}
}