@@ -1025,21 +1025,24 @@ func (m model) Init() tea.Cmd {
10251025 }
10261026 // 视觉能力探测:每次启动对各模型重探一次(见 vision.go),结果经 visionCapMsg 回灌。
10271027 cmds = append (cmds , visionProbeCmds (m .models )... )
1028- if cmd := ForceGraphemeCmd (); cmd != nil {
1029- cmds = append (cmds , cmd )
1030- }
1028+ // 不再强制注入伪 ModeReportMsg 切 grapheme —— bubbletea 启动会自己向终端查询 mode 2027,
1029+ // 终端真实应答经 applyUnicodeCoreReport 校正显示宽度口径,让 deepx 与终端一致(issue #113)。
10311030 // 启动即把控制态与已恢复的历史推进 hub 快照,晚连接的浏览器据此与 TUI 对齐。
10321031 m .broadcastControlState ()
10331032 m .broadcastSessionLoaded ()
10341033 return tea .Batch (cmds ... )
10351034}
10361035
1037- func ForceGraphemeCmd () tea.Cmd {
1038- if ! graphemeWidthMode {
1039- return nil
1040- }
1041- return func () tea.Msg {
1042- return tea.ModeReportMsg {Mode : ansi .ModeUnicodeCore , Value : ansi .ModeSet }
1036+ // applyUnicodeCoreReport 据终端对 mode 2027(Unicode-core)的真实应答校正显示宽度口径。
1037+ // 与 bubbletea cellbuf 的判定保持同口径(其 tea.go 内部:Set/Reset/PermanentlySet 才启用 grapheme),
1038+ // 否则 deepx 自有排版与 textarea 渲染口径不一致,在不支持 2027 的终端会让输入框插入宽字符后
1039+ // 光标后内容重复(issue #113)。NotRecognized / PermanentlyReset 视为不支持,退回 wcwidth。
1040+ func applyUnicodeCoreReport (value ansi.ModeSetting ) {
1041+ switch value {
1042+ case ansi .ModeSet , ansi .ModeReset , ansi .ModePermanentlySet :
1043+ graphemeWidthMode = true
1044+ default :
1045+ graphemeWidthMode = false
10431046 }
10441047}
10451048
@@ -1054,6 +1057,15 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
10541057
10551058 switch msg := msg .(type ) {
10561059
1060+ case tea.ModeReportMsg :
1061+ // 终端对 mode 2027(Unicode-core)的真实应答。据此把显示宽度口径校正到与终端一致,
1062+ // 修输入框插入宽字符后光标后内容重复的问题(issue #113)。其它 mode(如 2026 同步输出)
1063+ // 由 bubbletea 内部处理,这里只关心 Unicode-core。
1064+ if msg .Mode == ansi .ModeUnicodeCore {
1065+ applyUnicodeCoreReport (msg .Value )
1066+ }
1067+ return m , nil
1068+
10571069 case webInputMsg :
10581070 // 浏览器提交的输入,走和终端 Enter 完全相同的提交逻辑。
10591071 var cmd tea.Cmd
0 commit comments