Keep streaming history aligned with partial typing
Constraint: type_unicode_chunk returns the actual count of inserted characters, including partial failures Rejected: appending the full delta after every successful call | hides short writes and makes typed_text diverge from the screen Confidence: high Scope-risk: narrow Directive: preserve typed_text as the source of truth for what actually reached the focused field during streaming insertion Tested: cargo fmt --manifest-path src-tauri/Cargo.toml; git diff --check; cargo check --manifest-path src-tauri/Cargo.toml; cargo test --manifest-path src-tauri/Cargo.toml --lib Not-tested: desktop runtime smoke on macOS/Windows
This commit is contained in:
1 parent
3563c8eb16
commit
97e91ecdb6
2 files changed
+56
-4
No files matched your search
@@ -122,11 +122,24 @@ async fn run_streaming_polish(
|
||||
// 把 mpsc drain 完,避免发送端阻塞。
|
||||
continue;
|
||||
}
|
||||
let delta_chars = delta.chars().count();
|
||||
match crate::unicode_keystroke::type_unicode_chunk(&delta) {
|
||||
Ok(_) => {
|
||||
typed_text.push_str(&delta);
|
||||
Ok(typed_chars) => {
|
||||
let appended = append_typed_prefix(&mut typed_text, &delta, typed_chars);
|
||||
if appended < delta_chars {
|
||||
let reason = format!(
|
||||
"type_unicode_chunk typed only {appended}/{delta_chars} chars without error"
|
||||
);
|
||||
log::error!(
|
||||
"[coord] streaming_insert: {reason} at typed={} chars; \
|
||||
dropping remaining deltas",
|
||||
typed_text.chars().count()
|
||||
);
|
||||
first_failure = Some(reason);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
append_typed_prefix(&mut typed_text, &delta, e.typed_chars());
|
||||
log::error!(
|
||||
"[coord] streaming_insert: type_unicode_chunk failed at typed={} chars: {e}; \
|
||||
dropping remaining deltas",
|
||||
@@ -1593,9 +1606,20 @@ pub(super) fn cancel_session(inner: &Arc<Inner>) {
|
||||
schedule_capsule_idle(inner, CAPSULE_AUTO_HIDE_DELAY_MS);
|
||||
}
|
||||
|
||||
fn append_typed_prefix(target: &mut String, delta: &str, typed_chars: usize) -> usize {
|
||||
let mut end = 0;
|
||||
let mut appended = 0;
|
||||
for (idx, ch) in delta.char_indices().take(typed_chars) {
|
||||
end = idx + ch.len_utf8();
|
||||
appended += 1;
|
||||
}
|
||||
target.push_str(&delta[..end]);
|
||||
appended
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::finalize_polished_text;
|
||||
use super::{append_typed_prefix, finalize_polished_text};
|
||||
use crate::types::{ChineseScriptPreference, CorrectionRule, PolishMode};
|
||||
|
||||
fn correction_rule(pattern: &str, replacement: &str) -> CorrectionRule {
|
||||
@@ -1643,4 +1667,24 @@ mod tests {
|
||||
|
||||
assert_eq!(result, "OpenAI");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn append_typed_prefix_keeps_unicode_char_boundaries() {
|
||||
let mut typed = String::from("前");
|
||||
|
||||
let appended = append_typed_prefix(&mut typed, "a你🙂b", 3);
|
||||
|
||||
assert_eq!(appended, 3);
|
||||
assert_eq!(typed, "前a你🙂");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn append_typed_prefix_caps_at_delta_length() {
|
||||
let mut typed = String::new();
|
||||
|
||||
let appended = append_typed_prefix(&mut typed, "好", 10);
|
||||
|
||||
assert_eq!(appended, 1);
|
||||
assert_eq!(typed, "好");
|
||||
}
|
||||
}
|
||||
@@ -1771,7 +1771,7 @@ fn compose_hotword_block_preview(hotwords: &[String]) -> String {
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
format!(
|
||||
"热词(用户希望以下写法在输出中保持准确;当转写中出现这些词的同音 / 近形词识别时,优先按上述写法输出,不做无关词的机械替换):\n{}",
|
||||
"热词(用户希望以下写法在输出中保持准确;当转写中出现这些词的同音 / 近形误识别时,优先按上述写法输出,不做无关词的机械替换):\n{}",
|
||||
bullets
|
||||
)
|
||||
}
|
||||
@@ -2720,6 +2720,14 @@ mod tests {
|
||||
assert!(prompt.contains("- OpenLess"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hotword_preview_uses_correct_misrecognition_wording() {
|
||||
let preview = compose_hotword_block_preview(&["OpenLess".into()]);
|
||||
|
||||
assert!(preview.contains("同音 / 近形误识别时,优先按上述写法输出"));
|
||||
assert!(!preview.contains("近形词识别"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compose_system_prompt_uses_user_style_system_prompt_as_base() {
|
||||
let prompt = compose_system_prompt("像正式邮件,但结尾不要客套话", &[]);
|
||||
|
||||
Reference in new issue
Block a user