mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 02:36:01 -10:00
A fourth kind of tab opens a real shell (ConPTY on Windows, a pty elsewhere) in the project folder, outside the model's permissions and sandbox and with the host's provider keys left out of its environment. The kernel keeps each shell's output, so a tab left or a window reloaded comes back as it was; a tab is named for the command submitted while the shell is busy and carries a blue dot, and closing a busy one asks first. Also: the composer's note stack no longer clips to a few pixels when it holds two notes, which left the second one overlapping the input.
73 lines
1.5 KiB
Go
73 lines
1.5 KiB
Go
//go:build !windows
|
|
|
|
package terminal
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"os/exec"
|
|
"sync"
|
|
|
|
cpty "github.com/creack/pty"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
type unixPty struct {
|
|
f *os.File
|
|
cmd *exec.Cmd
|
|
once sync.Once
|
|
}
|
|
|
|
func startPty(o Options) (pty, error) {
|
|
cmd := exec.Command(o.Shell, o.Args...)
|
|
cmd.Dir = o.Dir
|
|
if len(o.Env) > 0 {
|
|
cmd.Env = o.Env
|
|
}
|
|
f, err := cpty.StartWithSize(cmd, &cpty.Winsize{Cols: o.Cols, Rows: o.Rows})
|
|
if err != nil {
|
|
return nil, fail(CodeStartFailed, "%v", err)
|
|
}
|
|
return &unixPty{f: f, cmd: cmd}, nil
|
|
}
|
|
|
|
func (p *unixPty) Read(b []byte) (int, error) { return p.f.Read(b) }
|
|
func (p *unixPty) Write(b []byte) (int, error) { return p.f.Write(b) }
|
|
func (p *unixPty) Close() error {
|
|
var err error
|
|
p.once.Do(func() { err = p.f.Close() })
|
|
return err
|
|
}
|
|
func (p *unixPty) Resize(cols, rows uint16) error {
|
|
return cpty.Setsize(p.f, &cpty.Winsize{Cols: cols, Rows: rows})
|
|
}
|
|
|
|
func (p *unixPty) Wait() (int, error) {
|
|
err := p.cmd.Wait()
|
|
var exit *exec.ExitError
|
|
if errors.As(err, &exit) {
|
|
return exit.ExitCode(), nil
|
|
}
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
return 0, nil
|
|
}
|
|
|
|
func (p *unixPty) Kill() error {
|
|
if p.cmd.Process == nil {
|
|
return nil
|
|
}
|
|
return p.cmd.Process.Kill()
|
|
}
|
|
|
|
// Busy is whether the terminal's foreground process group is not the shell's
|
|
// own: a command it started and is waiting on holds the terminal.
|
|
func (p *unixPty) Busy() bool {
|
|
if p.cmd.Process == nil {
|
|
return false
|
|
}
|
|
group, err := unix.IoctlGetInt(int(p.f.Fd()), unix.TIOCGPGRP)
|
|
return err == nil && group != p.cmd.Process.Pid
|
|
}
|