From 5841856288e1e3278b3533ecd34da0c1e38d6472 Mon Sep 17 00:00:00 2001 From: Sathvik Gilakamsetty Date: Sat, 16 May 2026 02:36:19 +0000 Subject: [PATCH] fix(streaming): fix SSE buffer corruption and add CJK sentence splitting (#1794) --- src/openhuman/channels/providers/presentation.rs | 12 ++++++++++++ .../channels/providers/presentation_tests.rs | 9 +++++++++ src/openhuman/providers/compatible_stream.rs | 3 +-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/openhuman/channels/providers/presentation.rs b/src/openhuman/channels/providers/presentation.rs index bd2cd7136..e8c9e7758 100644 --- a/src/openhuman/channels/providers/presentation.rs +++ b/src/openhuman/channels/providers/presentation.rs @@ -311,6 +311,7 @@ fn split_sentences(text: &str) -> Vec { current.push(chars[i]); let ch = chars[i]; + // Latin sentence terminators: split on ". " followed by uppercase. if (ch == '.' || ch == '!' || ch == '?') && i + 2 < chars.len() && chars[i + 1] == ' ' @@ -325,6 +326,17 @@ fn split_sentences(text: &str) -> Vec { continue; } + // CJK sentence terminators: split after fullwidth period/exclamation/question. + if (ch == '\u{3002}' || ch == '\u{FF01}' || ch == '\u{FF1F}') && i + 1 < chars.len() { + let trimmed = current.trim().to_string(); + if !trimmed.is_empty() { + parts.push(trimmed); + } + current.clear(); + i += 1; + continue; + } + i += 1; } diff --git a/src/openhuman/channels/providers/presentation_tests.rs b/src/openhuman/channels/providers/presentation_tests.rs index e3e1dc70b..cb04ff0ac 100644 --- a/src/openhuman/channels/providers/presentation_tests.rs +++ b/src/openhuman/channels/providers/presentation_tests.rs @@ -180,6 +180,15 @@ fn split_sentences_single_sentence_without_terminator() { assert_eq!(out.len(), 1); } +#[test] +fn split_sentences_splits_on_cjk_terminators() { + let out = split_sentences("你好世界。今天天气很好!你觉得呢?"); + assert_eq!(out.len(), 3); + assert_eq!(out[0], "你好世界。"); + assert_eq!(out[1], "今天天气很好!"); + assert_eq!(out[2], "你觉得呢?"); +} + #[test] fn group_sentences_single_entry_roundtrip() { let v: Vec = vec!["Hello world".into()]; diff --git a/src/openhuman/providers/compatible_stream.rs b/src/openhuman/providers/compatible_stream.rs index 172ebe9ce..f19c53a0b 100644 --- a/src/openhuman/providers/compatible_stream.rs +++ b/src/openhuman/providers/compatible_stream.rs @@ -52,8 +52,7 @@ pub(crate) fn sse_bytes_to_chunks( // Process complete lines while let Some(pos) = buffer.find('\n') { - let line = buffer.drain(..=pos).collect::(); - buffer = buffer[pos + 1..].to_string(); + let line: String = buffer.drain(..=pos).collect(); match parse_sse_line(&line) { Ok(Some(content)) => {