[windows][ime] TSF 失败后的静默 unicode 兜底按 Enter 发送换行并可能与迟到插入叠加,导致聊天输入框内容重复与拆分

Aperta
#1,318 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
18/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
rust, tauri
Ambito
desktop

Direzione di ricerca

Start in src-tauri/src/core_adapters.rs at the TSF submit failure branch, where the warning is logged and allow_non_tsf_fallback routes to windows_unicode_fallback. Then read insert_via_unicode_keystrokes, which currently logs nothing, and check how newline_mode = enter turns \n into Enter presses. A first step is adding the missing fallback log lines; done means the fallback path is visible in logs and a regression test asserts that a multi-paragraph insert under TSF NotDispatched sends the text once without submitting.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

现象

  • 触发条件:windowsInsertionMode = tsf、allowNonTsfInsertionFallback = true(默认开启)、windowsSendInputNewlineMode = enter(出厂默认);目标为聊天类前台输入框(实测 Codex Desktop 的 Chromium composer,进程 ChatGPT.exe);听写内容经 Structured 润色后包含多个段落/分条。
  • 当前表现:一次听写后,目标输入框出现两份内容、尾部片段劈裂重复;内容逐段被以 Enter 提交为新消息("说完一条分出新的一条,结束后还会出现第三条")。记事本/普通网页不复现(TSF 正常 Committed,不走兜底;Enter 也不提交)。
  • 证据(2026-10-31 本机日志,已脱敏,仅含长度/hash/session id):
    • 正常路径:submit begin op=commit ... payload_bytes=308(= 146 字符 ×2 + 16 头部,commit 只含一份文本)→ status=Committed → Ok(Inserted)。
    • 异常路径:submit complete op=commit status=NotDispatched → [WARN] [core-adapter] TSF submit failed: TSF edit session was rejected before dispatch → 0.4s 后 insert_final result=Ok(Inserted),期间没有任何兜底路径日志。该会话 polish 85 字符,目标输入框实际出现约 2×85 字符(内容两份、尾部片段 ×2)。
    • 近期统计:probe deadline expired 32 次、NotDispatched 6 次,目标均为 Codex Desktop composer;失败后均未观察到第二次 submit 或兜底日志。

影响

  • 聊天类应用中听写结果重复、被拆分成多条消息提交,需手工清理;核心听写链路在此类应用中不可信。
  • 兜底路径零日志:故障时无法从日志定位(本次排查的主要成本),用户侧表现为"随机重复"。
  • 观测:单日兜底路径触发最高 20 次(2026-10-24)。

复现步骤

  1. Windows 11 x64 + OpenLess 2.0.2-Beta.3+build.141-c9f49c60,保持 windowsInsertionMode=tsf、windowsSendInputNewlineMode=enter(出厂默认)。
  2. 前台置为 Codex Desktop 消息输入框(Chromium WebView composer)。
  3. 听写一段会被 Structured 风格润色成多段/分条的内容,松手。
  4. 观察目标输入框:内容两份 / 尾部片段重复 / 被按段提交为新消息;日志特征为 TSF submit failed 后 0.2~2s 内 Ok(Inserted) 且无兜底日志。

根因定位(代码固定到 v2.0.2-Beta.3-tauri)

  1. src-tauri/src/core_adapters.rs TSF 提交失败分支:log::warn!("[core-adapter] TSF submit failed: {error}") 后 break InsertStatus::Failed;allow_non_tsf_fallback 为真时进入 windows_unicode_fallback(&self.context, &text)。
  2. 同文件 windows_unicode_fallback(约 :5240):insert_via_unicode_keystrokes(text, WindowsSendInputOptions { newline_mode: windows_sendinput_newline_mode }),函数内零日志;newline_mode = "enter" 时每个 \n 转成 Enter 键按下——聊天类 composer 中即"提交消息"。
  3. TSF NotDispatched / rejected-before-dispatch 不保证文本未插入:异步 edit 仍可能落进文档(源码注释自证 "a timeout proves nothing: the edit can still commit"),与逐字打字兜底叠加 → 内容 ×2、尾部劈裂。
  4. payload 字节数学(chars×2+16)证明 commit 本身只含一份文本;重复由"迟到但真实落地的 TSF 插入 × 打字兜底"叠加造成,而非 commit 重复。

建议接受标准

  • windows_unicode_fallback 进入/完成写入日志(建议并入 insert-diagnostics:operation=insert_fallback_unicode、chars、result),从日志可直接判定走了兜底。
  • TSF NotDispatched/outcome-unknown 时不再无条件报 Ok(Inserted):至少在日志/用户可见文案中提示"文本可能已插入",并评估兜底前探测目标现有内容。
  • 评估兜底打字换行默认值:enter 在聊天类输入框会提交消息;考虑默认 shiftEnter 或在文档标注 enter 模式风险。
  • 回归用例:TSF NotDispatched + 多段文本 + 聊天类前台,断言目标只收到一份文本、无意外提交。

TODO / 不确定项

  • Codex Desktop composer 对 TSF 异步 apply 的确切时序未做 instrumentation(黑盒);"TSF 失败但实际已插入"由内容 ×2 观测与源码注释佐证,未逐帧取证。
  • 其他 Chromium/Electron 应用的 TSF 拒绝率未统计。

已验证的绕过

  • windowsInsertionMode = paste(剪贴板 + Ctrl+V 单次插入):本机实测不再出现重复/拆分,重启后配置稳定。
  • 或 windowsSendInputNewlineMode = shiftEnter:兜底打字不再提交消息,但 TSF × 兜底双插入风险仍在。

环境:Windows 11 Pro 10.0.26200 x64;OpenLess 2.0.2-Beta.3+build.141-c9f49c60。本 issue 不含转写正文,仅含长度、hash、session id 与日志结构。

Lingua principale
Rust
Stelle
3.7k
Fork
349
Merge medio
2g 14h
PR unite (30g)
97

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Open-Less/openless

Tutte le issue di Open-Less/openless

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.