Skip to main content

gproxy_protocol/transform/openai/stream_generate_content/openai_response/
utils.rs

1use std::collections::BTreeMap;
2
3use crate::openai::count_tokens::types as ot;
4use crate::openai::create_response::response::ResponseBody;
5use crate::openai::create_response::stream::ResponseStreamEvent;
6use crate::openai::create_response::types as rt;
7
8pub fn next_sequence_number(next_sequence_number: &mut u64) -> u64 {
9    let sequence_number = *next_sequence_number;
10    *next_sequence_number = next_sequence_number.saturating_add(1);
11    sequence_number
12}
13
14pub fn push_stream_event(out: &mut Vec<ResponseStreamEvent>, stream_event: ResponseStreamEvent) {
15    out.push(stream_event);
16}
17
18pub fn push_done_event(_out: &mut Vec<ResponseStreamEvent>) {
19    // No-op: the wrapper SSE envelope no longer exists.
20    // Callers that previously appended a Done sentinel can simply stop.
21}
22
23pub fn response_usage_from_counts(
24    input_tokens: u64,
25    cached_tokens: u64,
26    output_tokens: u64,
27    reasoning_tokens: u64,
28) -> rt::ResponseUsage {
29    rt::ResponseUsage {
30        input_tokens,
31        input_tokens_details: rt::ResponseInputTokensDetails { cached_tokens },
32        output_tokens,
33        output_tokens_details: rt::ResponseOutputTokensDetails { reasoning_tokens },
34        total_tokens: input_tokens.saturating_add(output_tokens),
35    }
36}
37
38pub fn response_snapshot(
39    id: &str,
40    model: &str,
41    status: Option<rt::ResponseStatus>,
42    usage: Option<rt::ResponseUsage>,
43    incomplete_reason: Option<rt::ResponseIncompleteReason>,
44    error: Option<rt::ResponseError>,
45    output_text: Option<String>,
46) -> ResponseBody {
47    ResponseBody {
48        id: id.to_string(),
49        created_at: 0,
50        error,
51        incomplete_details: incomplete_reason.map(|reason| rt::ResponseIncompleteDetails {
52            reason: Some(reason),
53        }),
54        instructions: Some(ot::ResponseInput::Text(String::new())),
55        metadata: BTreeMap::new(),
56        model: model.to_string(),
57        object: rt::ResponseObject::Response,
58        output: Vec::new(),
59        parallel_tool_calls: false,
60        temperature: 1.0,
61        tool_choice: ot::ResponseToolChoice::Options(ot::ResponseToolChoiceOptions::Auto),
62        tools: Vec::new(),
63        top_p: 1.0,
64        background: None,
65        completed_at: None,
66        conversation: None,
67        max_output_tokens: None,
68        max_tool_calls: None,
69        output_text: output_text.filter(|text| !text.is_empty()),
70        previous_response_id: None,
71        prompt: None,
72        prompt_cache_key: None,
73        prompt_cache_retention: None,
74        reasoning: None,
75        safety_identifier: None,
76        service_tier: None,
77        status,
78        text: None,
79        top_logprobs: None,
80        truncation: None,
81        usage,
82        user: None,
83    }
84}