feat: «Здесь» from a machine's terminal opens the file pane in the terminal's folder (asked of the agent); Аккаунт › Вид can turn «Здесь» back to the home folder. Version 0.2.1

This commit is contained in:
redtea committed 2026-10-16 18:28:15 +03:00
1 parent 57c2f1338f
commit 087eabf3b4
12 files changed
+163 -6

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
package agent
import (
"errors"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"sync"
"golang.org/x/sys/unix"
)
// termsBySID are the running terminals by their session, so the panel can
// ask where one of them is.
var termsBySID sync.Map // sid -> *PTY
// Cwd is the folder the terminal is in now: that of the program in front
// (the shell, or what it runs), else of the shell itself.
func (p *PTY) Cwd() (string, error) {
pid := 0
if g, err := unix.IoctlGetInt(int(p.f.Fd()), unix.TIOCGPGRP); err == nil && g > 0 {
pid = g
}
if pid > 0 {
if d, err := procCwd(pid); err == nil {
return d, nil
}
}
return procCwd(p.cmd.Process.Pid)
}
// procCwd is a process's working folder: /proc on Linux, lsof elsewhere.
func procCwd(pid int) (string, error) {
if runtime.GOOS == "linux" {
return os.Readlink("/proc/" + strconv.Itoa(pid) + "/cwd")
}
out, err := exec.Command("lsof", "-a", "-p", strconv.Itoa(pid), "-d", "cwd", "-Fn").Output()
if err != nil {
return "", err
}
for _, l := range strings.Split(string(out), "\n") {
if strings.HasPrefix(l, "n/") {
return l[1:], nil
}
}
return "", errors.New("папка терминала не найдена")
}
// termCwd answers the panel: where the terminal of session sid is now.
func termCwd(sid string) (any, error) {
v, ok := termsBySID.Load(sid)
if !ok {
return nil, errors.New("терминал не найден")
}
d, err := v.(*PTY).Cwd()
if err != nil {
return nil, err
}
return map[string]string{"path": d}, nil
}