| 885 | } |
| 886 | |
| 887 | async fn chat_stream_legacy( |
| 888 | &self, |
| 889 | mut request: ChatRequest, |
| 890 | ) -> Result<StreamResult, ProviderError> { |
| 891 | let url = Self::chat_completions_url(self.config.base_url.as_deref()); |
| 892 | request.stream = Some(true); |
| 893 | let mut request_body = Self::build_request_body(&request)?; |
| 894 | |
| 895 | // Match TS SDK: include stream_options for usage tracking |
| 896 | if let Value::Object(obj) = &mut request_body { |
| 897 | obj.insert( |
| 898 | "stream_options".to_string(), |
| 899 | serde_json::json!({"include_usage": true}), |
| 900 | ); |
| 901 | } |
| 902 | |
| 903 | let mut req_builder = self |
| 904 | .client |
| 905 | .post(&url) |
| 906 | .header("Authorization", format!("Bearer {}", self.config.api_key)) |
| 907 | .header("Content-Type", "application/json") |
| 908 | .header("Accept", "text/event-stream"); |
| 909 | |
| 910 | if let Some(org) = &self.config.organization { |
| 911 | req_builder = req_builder.header("OpenAI-Organization", org); |
| 912 | } |
| 913 | |
| 914 | let response = req_builder |
| 915 | .json(&request_body) |
| 916 | .send() |
| 917 | .await |
| 918 | .map_err(|e| ProviderError::NetworkError(e.to_string()))?; |
| 919 | |
| 920 | if !response.status().is_success() { |
| 921 | let status = response.status(); |
| 922 | let body = response.text().await.unwrap_or_default(); |
| 923 | return Err(ProviderError::ApiError(format!("{}: {}", status, body))); |
| 924 | } |
| 925 | |
| 926 | let stream = stream::try_unfold( |
| 927 | ( |
| 928 | response.bytes_stream(), |
| 929 | String::new(), |
| 930 | LegacySseParserState::default(), |
| 931 | VecDeque::<StreamEvent>::new(), |
| 932 | false, |
| 933 | ), |
| 934 | |(mut chunks, mut buffer, mut parser_state, mut pending, mut exhausted)| async move { |
| 935 | loop { |
| 936 | if let Some(event) = pending.pop_front() { |
| 937 | return Ok(Some(( |
| 938 | event, |
| 939 | (chunks, buffer, parser_state, pending, exhausted), |
| 940 | ))); |
| 941 | } |
| 942 | |
| 943 | if exhausted { |
| 944 | return Ok(None); |