Documentation
¶
Overview ¶
Package session is uam's native session backend. It replaces the private tmux server: every managed agent runs under a small detached "host" process (`uam __host`, see host.go) that owns the agent's PTY, renders its output through an in-process terminal emulator, and serves peek / reply / attach / kill over a per-session Unix socket. Hosts outlive the uam process that started them, so sessions keep running when the TUI exits — the same lifetime contract the tmux server provided — without requiring tmux to be installed.
Index ¶
- Constants
- Variables
- func DefaultDir() string
- func EnsureDir(dir string) error
- func PrimaryScreenProvider(identity string) bool
- func ProcAlive(pid int) bool
- func ProviderIdentityPath(dir, name string) (string, error)
- func ReadProviderIdentity(dir, name string) (string, error)
- func RunAttach(args []string) error
- func RunHost(args []string) error
- func SocketPath(dir, name string) string
- func ValidateName(name string) error
- func VerifyDir(dir string) error
- func WriteProviderIdentity(dir, name, providerSessionID string) error
- type Client
- func (c *Client) AttachArgv(name string) ([]string, error)
- func (c *Client) Capture(ctx context.Context, name string, lines int) (string, error)
- func (c *Client) CreateProviderSession(ctx context.Context, spec CreateSpec) error
- func (c *Client) CreateSession(ctx context.Context, name, cwd string, env map[string]string, command []string) error
- func (c *Client) Doctor(ctx context.Context, name string) (RuntimeDiagnostic, error)
- func (c *Client) HasSession(_ context.Context, name string) bool
- func (c *Client) Kill(ctx context.Context, name string) error
- func (c *Client) KillAll(ctx context.Context) error
- func (c *Client) List(_ context.Context) ([]Info, error)
- func (c *Client) RuntimeCount(_ context.Context) (int, error)
- func (c *Client) SendLine(ctx context.Context, name, text string) error
- func (c *Client) SendPrompt(ctx context.Context, name, text string) error
- func (c *Client) SetSessionLabel(ctx context.Context, name, label string) error
- type CreateSpec
- type Info
- type RuntimeDiagnostic
- type SessionBusyError
- type State
Constants ¶
const ( AttachPrefixEnv = "UAM_ATTACH_PREFIX" AttachBackDetachEnv = "UAM_ATTACH_BACK_DETACH" AttachPolicyMouseEnv = "UAM_ATTACH_POLICY_MOUSE" AttachPolicyPrefixEnv = "UAM_ATTACH_POLICY_PREFIX" AttachPolicyBackDetachEnv = "UAM_ATTACH_POLICY_BACK_DETACH" )
const AttachEffectiveProfileEnv = "UAM_ATTACH_EFFECTIVE_PROFILE"
const AttachMouseEnv = "UAM_ATTACH_MOUSE"
const AttachQuietEnv = "UAM_ATTACH_QUIET"
const AttachSelectedProfileEnv = "UAM_ATTACH_SELECTED_PROFILE"
const ProviderIdentityFileEnv = "UAM_PROVIDER_IDENTITY_FILE"
ProviderIdentityFileEnv names the provider-neutral identity handoff read by the host after the managed process exits.
Variables ¶
var ErrInvalidSessionName = fmt.Errorf("session name failed allow-list")
ErrInvalidSessionName is returned when a session name fails the allow-list.
var ErrSessionBusy = errors.New("session controller is attached")
ErrSessionBusy identifies operations rejected while a controller owns the PTY.
var NameRE = regexp.MustCompile(`^uam-[a-z0-9]+-[0-9a-f]{1,16}$`)
NameRE is the allow-list for session names uam may create. It matches the canonical shape minted by adapter.startSession ("uam-<provider>-<id>"): a lowercase-alphanumeric provider segment and a hex id segment. Names that pass are safe to embed in file paths (no separators, no dots).
Functions ¶
func DefaultDir ¶
func DefaultDir() string
DefaultDir returns the runtime directory holding per-session sockets and state files: $UAM_SESSION_DIR if set, else a per-UID directory under the system temp dir (like tmux's /tmp/tmux-<uid>).
$XDG_RUNTIME_DIR is deliberately NOT used: systemd-logind deletes it when the user's last login session ends, not only on reboot — which would strand still-running detached hosts (they survive logout) with no socket or state file, and a later "resume" would spawn duplicates. The temp dir survives logout and is cleared on reboot, matching the hosts' actual lifetime. Unix socket paths must also stay short (the sockaddr_un limit is ~104 bytes), which rules out deep home paths.
func EnsureDir ¶
EnsureDir creates the runtime directory owner-only. The 0700 mode is the security boundary: sockets and state files inside inherit protection from it, so another local user can neither attach to a session nor inject input. Because the default parent is the sticky shared temp dir, the directory is also verified to be a real directory (not a symlink) owned by the current user — a foreign pre-created /tmp/uam-<uid> is refused, like tmux refuses a foreign /tmp/tmux-<uid>.
func PrimaryScreenProvider ¶
PrimaryScreenProvider reports whether identity names a provider that owns the primary screen. Exported so the adapter-policy parity test can check the runtime decision against each provider's declaration.
func ProcAlive ¶
ProcAlive reports whether pid is a live process (signal-0 probe). It is the native equivalent of the old tmux.PaneAlive.
func ProviderIdentityPath ¶
ProviderIdentityPath returns the canonical provider identity handoff path inside the verified native-session runtime boundary.
func ReadProviderIdentity ¶
ReadProviderIdentity returns the verified provider session identity. A missing handoff is advisory and returns an empty identity without error.
func RunAttach ¶
RunAttach is the entry point of `uam __attach`: it puts the terminal in raw mode and bridges it to a session host — the native replacement for `tmux attach`. It returns when the user detaches (Ctrl+B d, or Ctrl+Left while nothing is typed — see stdinFilter) or the agent exits.
func RunHost ¶
RunHost is the entry point of the detached per-session host process (`uam __host`). It starts the agent command under a PTY, mirrors all output into a terminal emulator (for peek/replay), serves the control socket, and on agent exit marks the persisted record closed before cleaning up its runtime files. It only returns on fatal startup errors or after the agent exits.
func SocketPath ¶
SocketPath returns the control socket path for a session.
func ValidateName ¶
ValidateName rejects session names outside the canonical allow-list.
func VerifyDir ¶
VerifyDir validates an existing runtime directory without changing it. The directory is the local authorization boundary around session sockets and state, so every read/control path must call this before trusting files beneath it.
func WriteProviderIdentity ¶
WriteProviderIdentity atomically publishes a provider session identity in the native-session runtime directory.
Types ¶
type Client ¶
type Client struct {
// Dir is the runtime directory holding sockets and state files.
Dir string
// Exe overrides the binary used to spawn hosts and attach clients
// (normally the running uam binary itself). Tests point it at the test
// binary.
Exe string
}
Client talks to per-session host processes. It is the drop-in replacement for the old tmux.Client: same operations, but against uam's own session hosts instead of a tmux server.
func (*Client) AttachArgv ¶
AttachArgv returns the argv that attaches the current terminal to the session — the uam binary's own attach client instead of `tmux attach`.
func (*Client) Capture ¶
Capture returns the rendered tail of the session's terminal, like `tmux capture-pane -p -J` did.
func (*Client) CreateProviderSession ¶
func (c *Client) CreateProviderSession(ctx context.Context, spec CreateSpec) error
func (*Client) CreateSession ¶
func (c *Client) CreateSession(ctx context.Context, name, cwd string, env map[string]string, command []string) error
CreateSession spawns a detached host running command in cwd. It returns once the host reports the agent started (or with the host's startup error), mirroring the synchronous contract of `tmux new-session -d`.
func (*Client) HasSession ¶
HasSession reports whether a live host exists for name.
func (*Client) Kill ¶
Kill terminates the session's agent and waits for the host to confirm the session is gone. Killing a session that does not exist is an error, like `tmux kill-session` (callers that need idempotence probe HasSession).
func (*Client) KillAll ¶
KillAll terminates every managed session. It replaces `tmux kill-server` and is idempotent: an empty (or missing) runtime directory is success.
func (*Client) List ¶
List enumerates live sessions by scanning the runtime directory's state files — no subprocess, no socket round-trips. Leftovers from a crashed host are swept once both the host and its agent are gone.
func (*Client) SendLine ¶
SendLine types text into the session and submits it with a single Enter (carriage return). Interior newlines are delivered literally so a multi-line prompt lands in the agent's input buffer as one prompt — the same contract the tmux SendLine implemented keystroke-by-keystroke (F13).
func (*Client) SendPrompt ¶
SendPrompt is SendLine for a provider that is still starting: the host types the prompt only once the provider has taken the terminal out of canonical mode. Before that switch the line discipline turns the trailing Enter into a newline, and the composer that later reads it never submits.
type CreateSpec ¶
type Info ¶
type Info struct {
Name string
CreatedUnix int64
ChildPID int
// Cwd is the agent process's current working directory (live from /proc
// when available, else the directory the session started in).
Cwd string
// Alive reports whether the agent process itself is still running. The
// host lingers briefly after the child exits, so this is the liveness
// signal the dashboard's Active/Failed classification keys on.
Alive bool
}
Info is one live session as reported by List.
type RuntimeDiagnostic ¶
type SessionBusyError ¶
type SessionBusyError struct {
Operation string
}
SessionBusyError preserves the rejected operation across the host protocol.
func (*SessionBusyError) Error ¶
func (err *SessionBusyError) Error() string
func (*SessionBusyError) Is ¶
func (err *SessionBusyError) Is(target error) bool
type State ¶
type State struct {
Name string `json:"name"`
HostPID int `json:"host_pid"`
// HostStart / ChildStart are platform-specific stable process identities
// derived from kernel start times (0 where unavailable). They disambiguate
// a recycled PID from the original
// process, so a stale state file can never make uam treat — or worse,
// signal — an unrelated process as a session.
HostStart int64 `json:"host_start,omitempty"`
ChildPID int `json:"child_pid"`
ChildStart int64 `json:"child_start,omitempty"`
CreatedUnix int64 `json:"created_unix"`
Cwd string `json:"cwd"`
Label string `json:"label,omitempty"`
ProviderIdentity string `json:"provider_identity,omitempty"`
Command []string `json:"command"`
}
State is the on-disk record a host writes next to its socket. It is the native replacement for `tmux list-sessions` output: List scans these files to enumerate live sessions without dialing every socket.
Source Files
¶
- attach.go
- attach_cleanup.go
- attach_control.go
- attach_fd.go
- attach_hello.go
- attach_input_flush_linux.go
- attach_policy.go
- client.go
- client_registry.go
- diagnostic.go
- host.go
- host_attach.go
- host_control_frame.go
- host_controller.go
- host_pty.go
- ownership_error.go
- proc_start_linux.go
- proto.go
- provider_identity.go
- provider_terminal_policy.go
- scrollback_policy.go
- session.go
- status_line.go
- termios_linux.go