diff --git a/frontend/src/assets/css/terminal.css b/frontend/src/assets/css/terminal.css index 2e67ee6..c4ff062 100644 --- a/frontend/src/assets/css/terminal.css +++ b/frontend/src/assets/css/terminal.css @@ -10,7 +10,6 @@ .terminal-container .xterm { height: 100%; - padding: 4px; } .terminal-container .xterm-viewport { diff --git a/internal/ssh/service.go b/internal/ssh/service.go index db81178..723530e 100644 --- a/internal/ssh/service.go +++ b/internal/ssh/service.go @@ -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 go s.readLoop(sessionID, stdout) - // Inject shell integration for CWD tracking (OSC 7). - // Uses stty -echo to suppress the command from appearing in the terminal, - // then restores echo. A leading space keeps it out of shell history. - go func() { - 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() - }() + // CWD tracking disabled — ProcessOutput() in the readLoop was corrupting + // ANSI escape sequences when OSC 7 sequences split across read boundaries. + // CWD following will be re-implemented via a separate SSH exec channel + // that doesn't touch the terminal data stream. 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. // It stops when the reader returns an error (typically EOF when the session closes). 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) for { n, err := reader.Read(buf) - if n > 0 { + if n > 0 && s.outputHandler != nil { data := make([]byte, n) copy(data, buf[:n]) - - // 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) - } + s.outputHandler(sessionID, data) } if err != nil { break