fix: revert CWD tracker from readLoop — corrupts ANSI escape sequences
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 1m4s
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 1m4s
ProcessOutput() in the readLoop was processing every byte of SSH output, looking for OSC 7 sequences. When these sequences split across read boundaries (common with 32KB buffer), partial sequences leaked through and corrupted xterm.js parser state — producing red/green color blocks instead of text, and characters rendering at wrong widths. Reverted readLoop to direct passthrough (v0.7.3 behavior). Also removed shell integration injection (stty -echo + PROMPT_COMMAND) which caused terminal mode disruption on macOS. Also removed 4px xterm padding that could cause fitAddon cell width miscalculation. CWD tracking will be re-implemented via a separate SSH exec channel that polls pwd without touching the terminal data stream. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bce77e0932
commit
c3beb6df6b
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
.terminal-container .xterm {
|
.terminal-container .xterm {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-container .xterm-viewport {
|
.terminal-container .xterm-viewport {
|
||||||
|
|||||||
@ -142,23 +142,10 @@ func (s *SSHService) Connect(hostname string, port int, username string, authMet
|
|||||||
// Launch goroutine to read stdout and forward data via the output handler
|
// Launch goroutine to read stdout and forward data via the output handler
|
||||||
go s.readLoop(sessionID, stdout)
|
go s.readLoop(sessionID, stdout)
|
||||||
|
|
||||||
// Inject shell integration for CWD tracking (OSC 7).
|
// CWD tracking disabled — ProcessOutput() in the readLoop was corrupting
|
||||||
// Uses stty -echo to suppress the command from appearing in the terminal,
|
// ANSI escape sequences when OSC 7 sequences split across read boundaries.
|
||||||
// then restores echo. A leading space keeps it out of shell history.
|
// CWD following will be re-implemented via a separate SSH exec channel
|
||||||
go func() {
|
// that doesn't touch the terminal data stream.
|
||||||
time.Sleep(500 * time.Millisecond)
|
|
||||||
// Suppress echo, set PROMPT_COMMAND for bash (zsh uses precmd),
|
|
||||||
// restore echo, then clear the current line so no visual artifact remains.
|
|
||||||
injection := " stty -echo 2>/dev/null; " +
|
|
||||||
ShellIntegrationCommand("bash") + "; " +
|
|
||||||
"if [ -n \"$ZSH_VERSION\" ]; then " + ShellIntegrationCommand("zsh") + "; fi; " +
|
|
||||||
"stty echo 2>/dev/null\n"
|
|
||||||
sshSession.mu.Lock()
|
|
||||||
if sshSession.Stdin != nil {
|
|
||||||
_, _ = sshSession.Stdin.Write([]byte(injection))
|
|
||||||
}
|
|
||||||
sshSession.mu.Unlock()
|
|
||||||
}()
|
|
||||||
|
|
||||||
return sessionID, nil
|
return sessionID, nil
|
||||||
}
|
}
|
||||||
@ -216,32 +203,13 @@ func (s *SSHService) buildHostKeyCallback(hostname string, port int) ssh.HostKey
|
|||||||
// (stripping OSC 7 sequences), and calls the output handler with cleaned data.
|
// (stripping OSC 7 sequences), and calls the output handler with cleaned data.
|
||||||
// It stops when the reader returns an error (typically EOF when the session closes).
|
// It stops when the reader returns an error (typically EOF when the session closes).
|
||||||
func (s *SSHService) readLoop(sessionID string, reader io.Reader) {
|
func (s *SSHService) readLoop(sessionID string, reader io.Reader) {
|
||||||
// Grab the CWD tracker for this session (if any)
|
|
||||||
s.mu.RLock()
|
|
||||||
sess := s.sessions[sessionID]
|
|
||||||
s.mu.RUnlock()
|
|
||||||
|
|
||||||
buf := make([]byte, 32*1024)
|
buf := make([]byte, 32*1024)
|
||||||
for {
|
for {
|
||||||
n, err := reader.Read(buf)
|
n, err := reader.Read(buf)
|
||||||
if n > 0 {
|
if n > 0 && s.outputHandler != nil {
|
||||||
data := make([]byte, n)
|
data := make([]byte, n)
|
||||||
copy(data, buf[:n])
|
copy(data, buf[:n])
|
||||||
|
s.outputHandler(sessionID, data)
|
||||||
// Process CWD tracking — strips OSC 7 sequences from output
|
|
||||||
if sess != nil && sess.CWDTracker != nil {
|
|
||||||
cleaned, newCWD := sess.CWDTracker.ProcessOutput(data)
|
|
||||||
data = cleaned
|
|
||||||
|
|
||||||
// Emit CWD change event if a new path was detected
|
|
||||||
if newCWD != "" && s.cwdHandler != nil {
|
|
||||||
s.cwdHandler(sessionID, newCWD)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(data) > 0 && s.outputHandler != nil {
|
|
||||||
s.outputHandler(sessionID, data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user