Documentation
¶
Index ¶
- Constants
- func AttachRelay(ctx context.Context, listenAddr, sessionID, attachMode string, ...) error
- func AttachWriter(listenAddr, sessionID, attachMode string) (detached bool, err error)
- func DialTerminal(listenAddr, sessionID, attachMode string) (*websocket.Conn, error)
- func InjectInput(listenAddr, sessionID string, input []byte) error
- func IsScreenSnapshotFrame(data []byte) bool
- func IsServeSubcommand(arg string) bool
- func ParseResizeMessage(data []byte) (cols, rows int, ok bool)
- func PrepareSessionInjectMode(listenAddr, sessionID string) error
- func ProcessAlive(pid int) bool
- func ReadSnapshot(listenAddr, sessionID string) (frame string, scrollback string, cols, rows int, err error)
- func RegistryDir(cfg RegistryConfig) string
- func RemoveRegistry(cfg RegistryConfig, sessionID string)
- func RemoveRegistryIfMatch(cfg RegistryConfig, sessionID, listenAddr string, pid int)
- func RenderObserverFrame(data []byte, cols, rows int) []byte
- func RenderSnapshotOutput(frame, scrollback string, cols, rows int) string
- func RenderSnapshotScrollback(raw string, cols, rows int) string
- func RenderVTStateToText(vt vt10x.Terminal, cols, rows int) ([]byte, bool)
- func ReserveCustomSessionID(cfg RegistryConfig, sessionID string) (func(), error)
- func ReserveRegistrySessionID(cfg RegistryConfig) (string, func(), error)
- func SanitizeForPrint(data string) string
- func ScreenSnapshotToText(data []byte, cols, rows int) ([]byte, bool)
- func SendMessage(listenAddr, sessionID, message string, suffixCR bool) error
- func ServeSession(ctx context.Context, opts ServeOptions) error
- func ServeSubcommand(argv []string) string
- func SlugifyCommandLine(argv []string) string
- func SnapshotText(listenAddr, sessionID string) (string, error)
- func StreamObserver(listenAddr, sessionID string, w io.Writer) error
- func TCPReachable(addr string) bool
- func TTYAttachOnConnect(stdout *os.File) func(upstream *wsWriter) error
- func TTYAttachTerminalSize(stdout *os.File) (cols, rows int)
- func TTYWatchHome() (string, error)
- func TerminalWebSocketURL(listenAddr, sessionID, attachMode string) (string, error)
- func WaitHeadless(ctx context.Context, result *HeadlessRunResult, command []string) error
- func WebAttachOnConnect(listenAddr, sessionID string, out io.Writer, cols, rows int) func(upstream *wsWriter) error
- func WriteRegistry(cfg RegistryConfig, entry RegistryEntry) error
- type AttachRelayConfig
- type AttachSink
- type CheckWritableFunc
- type EphemeralSession
- func (s *EphemeralSession) Entry() *RegistryEntry
- func (s *EphemeralSession) Kill() error
- func (s *EphemeralSession) Send(message string) error
- func (s *EphemeralSession) Snapshot() (string, error)
- func (s *EphemeralSession) StartDetached(ctx context.Context, binaryPath string) error
- func (s *EphemeralSession) StartInProcess(ctx context.Context) error
- func (s *EphemeralSession) WaitWritable(check CheckWritableFunc, timeout time.Duration) WritableStatus
- type ExitStatus
- type HeadlessRunOptions
- type HeadlessRunResult
- type RegistryConfig
- type RegistryEntry
- func ListRegistryEntries(cfg RegistryConfig, prune bool) ([]RegistryEntry, error)
- func LookupAcrossSubdirs(home string, subdirs []string, sessionID string) (*RegistryEntry, string, error)
- func ReadRegistry(cfg RegistryConfig, sessionID string) (*RegistryEntry, error)
- func WaitForRegistryEntry(cfg RegistryConfig, sessionID string, timeout time.Duration) (*RegistryEntry, error)
- type ServeOptions
- type TTYAttachSink
- type WSAttachClient
- type WebSocketAttachSink
- type WritableStatus
Constants ¶
const (
// HeadlessWaitingLine is logged to stderr once during the SIGINT grace window.
HeadlessWaitingLine = "waiting for program to exit..."
)
Variables ¶
This section is empty.
Functions ¶
func AttachRelay ¶ added in v0.0.51
func AttachRelay(ctx context.Context, listenAddr, sessionID, attachMode string, cfg AttachRelayConfig, sink AttachSink) error
AttachRelay connects to a live terminal and relays output/input through sink.
func AttachWriter ¶ added in v0.0.48
AttachWriter attaches stdin/stdout to a live terminal session. Returns detached=true when the user pressed Ctrl-].
func DialTerminal ¶ added in v0.0.48
DialTerminal connects to a live terminal session and consumes the handshake.
func InjectInput ¶ added in v0.0.48
InjectInput writes input to a live session via server-side HTTP inject API.
func IsScreenSnapshotFrame ¶
IsScreenSnapshotFrame reports ptywrap screen snapshot binary frames.
func IsServeSubcommand ¶
IsServeSubcommand reports whether arg is a slug-based serve reexec token.
func ParseResizeMessage ¶ added in v0.0.51
ParseResizeMessage extracts cols/rows from a browser resize JSON message.
func PrepareSessionInjectMode ¶
PrepareSessionInjectMode disables canonical mode before injecting input.
func ProcessAlive ¶
ProcessAlive reports whether pid responds to signal 0.
func ReadSnapshot ¶
func ReadSnapshot(listenAddr, sessionID string) (frame string, scrollback string, cols, rows int, err error)
ReadSnapshot fetches the current screen frame for a live session via a single attach_mode=snapshot WebSocket (no resize, does not claim writer). Scrollback is left empty so rendering prefers the server screen frame.
Important: do not use attach_mode=screen here. "screen" claims the writer role; closing that short-lived socket reaps the PTY child (stopChild on writer close), which breaks multi-poll waitForPrompt + inject (CSI Down / Enter / /status).
func RegistryDir ¶ added in v0.0.48
func RegistryDir(cfg RegistryConfig) string
RegistryDir returns {home}/{subdir}/ for the given config.
func RemoveRegistry ¶
func RemoveRegistry(cfg RegistryConfig, sessionID string)
RemoveRegistry deletes the registry file and any claim for a session.
func RemoveRegistryIfMatch ¶
func RemoveRegistryIfMatch(cfg RegistryConfig, sessionID, listenAddr string, pid int)
RemoveRegistryIfMatch deletes the registry file only when the on-disk entry still belongs to the caller (same listen address and pid). Stale __serve__ cleanup can otherwise delete a newer session that reused the same session id.
func RenderObserverFrame ¶
RenderObserverFrame converts observer-mode PTY bytes to visible text without CSI/C0 leaks.
func RenderSnapshotOutput ¶
RenderSnapshotOutput converts a ptywrap screen snapshot frame and/or raw scrollback into printable snapshot text, matching the screen attach pipeline used by run.
func RenderSnapshotScrollback ¶
RenderSnapshotScrollback converts accumulated scrollback to printable snapshot text.
func RenderVTStateToText ¶
RenderVTStateToText extracts printable lines from a vt10x terminal state.
func ReserveCustomSessionID ¶
func ReserveCustomSessionID(cfg RegistryConfig, sessionID string) (func(), error)
ReserveCustomSessionID validates id and ensures it is not held by a live session. Stale registry entries are pruned so the id can be reused. On success a side-car claim file is written so the exclusive flock can be released before __serve__ registers (the claim is not a *.json registry entry, so waiters do not treat it as a ready session).
func ReserveRegistrySessionID ¶
func ReserveRegistrySessionID(cfg RegistryConfig) (string, func(), error)
ReserveRegistrySessionID returns the next session-N id under flock and writes a side-car claim so the lock can be released before WaitForRegistryEntry.
func SanitizeForPrint ¶
SanitizeForPrint strips CSI, OSC, and C0 control sequences except \n \r \t.
func ScreenSnapshotToText ¶
ScreenSnapshotToText renders a screen snapshot frame to plain text.
func SendMessage ¶ added in v0.0.48
SendMessage prepares inject mode and sends verbatim bytes. When suffixCR is true, appends '\r' only if message contains no '\r'.
func ServeSession ¶
func ServeSession(ctx context.Context, opts ServeOptions) error
ServeSession runs the embedded ptywrap HTTP server until the command exits.
func ServeSubcommand ¶
ServeSubcommand wraps SlugifyCommandLine as the internal reexec argv token.
func SlugifyCommandLine ¶
SlugifyCommandLine produces a stable slug from a session command argv.
func SnapshotText ¶
SnapshotText returns rendered printable snapshot text for a live session.
func StreamObserver ¶ added in v0.0.48
StreamObserver streams readonly terminal output to w.
func TCPReachable ¶
TCPReachable reports whether a TCP listen address accepts connections.
func TTYAttachOnConnect ¶ added in v0.0.51
TTYAttachOnConnect sends an initial resize and watches SIGWINCH when stdout is a TTY.
func TTYAttachTerminalSize ¶ added in v0.0.51
TTYAttachTerminalSize returns the current terminal dimensions when stdout is a TTY.
func TTYWatchHome ¶
TTYWatchHome returns the tty-watch data directory.
func TerminalWebSocketURL ¶ added in v0.0.48
TerminalWebSocketURL builds the WebSocket URL for a terminal session.
func WaitHeadless ¶ added in v0.0.48
func WaitHeadless(ctx context.Context, result *HeadlessRunResult, command []string) error
WaitHeadless blocks until the serve child exits, forwarding SIGINT to the PTY session with the same grace window as tty-watch run --headless.
func WebAttachOnConnect ¶ added in v0.0.51
func WebAttachOnConnect(listenAddr, sessionID string, out io.Writer, cols, rows int) func(upstream *wsWriter) error
WebAttachOnConnect primes browser output with snapshot scrollback. Resize is sent by the browser client after the websocket opens so upstream resize acks are not relayed before interactive input during attach setup.
func WriteRegistry ¶
func WriteRegistry(cfg RegistryConfig, entry RegistryEntry) error
WriteRegistry creates the registry file for a live session and drops any provisional claim for the same id.
Types ¶
type AttachRelayConfig ¶ added in v0.0.51
type AttachRelayConfig struct {
ExitOnTerminalExit bool
SkipScreenSnapshotConversion bool
Cols, Rows int
OnConnect func(upstream *wsWriter) error
}
AttachRelayConfig controls relayTerminalOutput behaviour for an attach session.
type AttachSink ¶ added in v0.0.51
type AttachSink interface {
OutputWriter() io.Writer
RunInput(ctx context.Context, upstream *wsWriter) error
// DrainOutputAfterInput reports whether upstream output should be read briefly
// after stdin reaches EOF (piped attach clients).
DrainOutputAfterInput() bool
}
AttachSink receives PTY output and forwards interactive input to the upstream terminal.
type CheckWritableFunc ¶ added in v0.0.48
type CheckWritableFunc func(scrollback []byte) WritableStatus
CheckWritableFunc inspects scrollback bytes for prompt readiness.
type EphemeralSession ¶
type EphemeralSession struct {
Home string
RegistrySubdir string
SessionID string
Command []string
ExtraPaths []string
// contains filtered or unexported fields
}
EphemeralSession manages a short-lived tty-watch session without CLI subprocesses.
func NewEphemeralSession ¶
func NewEphemeralSession(home, sessionID string, command []string) *EphemeralSession
NewEphemeralSession returns a session scoped to home, id, and command argv.
func (*EphemeralSession) Entry ¶
func (s *EphemeralSession) Entry() *RegistryEntry
Entry returns the current registry entry when available.
func (*EphemeralSession) Kill ¶
func (s *EphemeralSession) Kill() error
Kill terminates the session and removes its registry entry.
func (*EphemeralSession) Send ¶
func (s *EphemeralSession) Send(message string) error
Send injects follow-up text into the live session.
func (*EphemeralSession) Snapshot ¶
func (s *EphemeralSession) Snapshot() (string, error)
Snapshot returns rendered printable snapshot text.
func (*EphemeralSession) StartDetached ¶
func (s *EphemeralSession) StartDetached(ctx context.Context, binaryPath string) error
StartDetached re-executes binaryPath with a slug-based serve token.
func (*EphemeralSession) StartInProcess ¶
func (s *EphemeralSession) StartInProcess(ctx context.Context) error
StartInProcess launches ServeSession in the current process.
func (*EphemeralSession) WaitWritable ¶
func (s *EphemeralSession) WaitWritable(check CheckWritableFunc, timeout time.Duration) WritableStatus
WaitWritable polls check readiness against live scrollback.
type ExitStatus ¶ added in v0.0.48
type ExitStatus struct {
Code int
}
ExitStatus reports a non-zero exit code from headless wait handling.
func (*ExitStatus) Error ¶ added in v0.0.48
func (e *ExitStatus) Error() string
type HeadlessRunOptions ¶ added in v0.0.48
type HeadlessRunOptions struct {
Home string
RegistrySubdir string // e.g. "grok-tty-registry"; empty uses tty-watch default
SessionID string // empty → auto-reserve session-N
Command []string
BinaryPath string // re-exec target for __serve__ (os.Args[0])
Cwd string
ExtraPaths []string
// KeepAlive, when true, sets TTY_WATCH_KEEP_ALIVE so __serve__ stays alive
// after the PTY child exits (intentional keep-tty). Default false: serve
// exits shortly after the child so short attached runs leave no orphans.
KeepAlive bool
}
HeadlessRunOptions configures a detached __serve__ child session.
type HeadlessRunResult ¶ added in v0.0.48
type HeadlessRunResult struct {
SessionID string
Entry *RegistryEntry
Cmd *exec.Cmd
Registry RegistryConfig
Wait func() error
}
HeadlessRunResult is returned after the detached serve child registers.
func HeadlessRun ¶ added in v0.0.48
func HeadlessRun(ctx context.Context, opts HeadlessRunOptions) (*HeadlessRunResult, error)
HeadlessRun reserves a session id, spawns a detached __serve__ child, and waits for the registry entry.
type RegistryConfig ¶ added in v0.0.48
type RegistryConfig struct {
Home string // AGENT_RUN_HOME or TTY_WATCH_HOME
Subdir string // "registry" for tty-watch; "grok-tty-registry" for agent-run
}
RegistryConfig selects the registry directory under a home path.
func DefaultRegistryConfig ¶ added in v0.0.48
func DefaultRegistryConfig(home string) RegistryConfig
DefaultRegistryConfig returns the tty-watch default registry layout.
type RegistryEntry ¶
type RegistryEntry struct {
SessionID string `json:"session_id"`
ListenAddr string `json:"listen_addr"`
PID int `json:"pid"`
CreatedAt string `json:"created_at"`
Command []string `json:"command"`
Cwd string `json:"cwd,omitempty"`
}
RegistryEntry maps a tty-watch session id to the embedded ptywrap listen address.
func ListRegistryEntries ¶
func ListRegistryEntries(cfg RegistryConfig, prune bool) ([]RegistryEntry, error)
ListRegistryEntries returns all registry entries, optionally pruning unreachable ones.
func LookupAcrossSubdirs ¶ added in v0.0.48
func LookupAcrossSubdirs(home string, subdirs []string, sessionID string) (*RegistryEntry, string, error)
LookupAcrossSubdirs searches subdirs under home for a session id. Returns the entry, the subdir where it was found, or an error.
func ReadRegistry ¶
func ReadRegistry(cfg RegistryConfig, sessionID string) (*RegistryEntry, error)
ReadRegistry loads a session registry entry.
func WaitForRegistryEntry ¶
func WaitForRegistryEntry(cfg RegistryConfig, sessionID string, timeout time.Duration) (*RegistryEntry, error)
WaitForRegistryEntry polls until a session registry entry is available.
type ServeOptions ¶
type ServeOptions struct {
SessionID string
Command []string
Home string
RegistrySubdir string
Cwd string
ExtraPaths []string
KeepAlive bool
// OnListening is invoked in a goroutine after the PTY session is created and
// the registry entry is written. ctx is cancelled when the serve session ends.
// listenAddr is the bound HTTP listen address; home and registrySubdir are the
// resolved registry location for this serve process.
OnListening func(ctx context.Context, listenAddr, home, registrySubdir string)
}
ServeOptions configures an embedded PTY server session.
type TTYAttachSink ¶ added in v0.0.51
type TTYAttachSink struct {
// contains filtered or unexported fields
}
TTYAttachSink relays attach IO through the process stdin/stdout.
func NewTTYAttachSink ¶ added in v0.0.51
func NewTTYAttachSink() (*TTYAttachSink, func(), error)
NewTTYAttachSink prepares stdin/stdout for interactive attach.
func (*TTYAttachSink) Detached ¶ added in v0.0.51
func (s *TTYAttachSink) Detached() bool
func (*TTYAttachSink) DrainOutputAfterInput ¶ added in v0.0.51
func (s *TTYAttachSink) DrainOutputAfterInput() bool
func (*TTYAttachSink) OutputWriter ¶ added in v0.0.51
func (s *TTYAttachSink) OutputWriter() io.Writer
type WSAttachClient ¶ added in v0.0.48
type WSAttachClient struct {
Conn *websocket.Conn
Role string
// contains filtered or unexported fields
}
WSAttachClient is a lightweight WebSocket attach helper for doctest harnesses.
func DialPTYAttach ¶ added in v0.0.48
func DialPTYAttach(listenAddr, sessionID, attachMode string) (*WSAttachClient, error)
DialPTYAttach connects to a ptywrap session with the given attach mode.
func (*WSAttachClient) Close ¶ added in v0.0.48
func (c *WSAttachClient) Close()
Close closes the WebSocket connection.
func (*WSAttachClient) Output ¶ added in v0.0.48
func (c *WSAttachClient) Output() string
Output returns accumulated PTY output from the attach client.
func (*WSAttachClient) TryResize ¶ added in v0.0.48
func (c *WSAttachClient) TryResize(cols, rows int) error
TryResize sends a resize control message.
func (*WSAttachClient) TryWriteInput ¶ added in v0.0.48
func (c *WSAttachClient) TryWriteInput(data []byte) error
TryWriteInput sends binary input when the attach role allows writing.
type WebSocketAttachSink ¶ added in v0.0.51
type WebSocketAttachSink struct {
// contains filtered or unexported fields
}
WebSocketAttachSink relays attach IO through a browser WebSocket connection.
func NewWebSocketAttachSink ¶ added in v0.0.51
func NewWebSocketAttachSink(conn *websocket.Conn) *WebSocketAttachSink
NewWebSocketAttachSink creates a sink for browser terminal websocket clients.
func (*WebSocketAttachSink) DrainOutputAfterInput ¶ added in v0.0.51
func (s *WebSocketAttachSink) DrainOutputAfterInput() bool
func (*WebSocketAttachSink) OutputWriter ¶ added in v0.0.51
func (s *WebSocketAttachSink) OutputWriter() io.Writer
type WritableStatus ¶ added in v0.0.48
WritableStatus reports whether a TTY session is ready to receive injected input.
func WaitUntilWritable ¶ added in v0.0.48
func WaitUntilWritable(check CheckWritableFunc, listenAddr, sessionID string, timeout time.Duration) WritableStatus
WaitUntilWritable polls check until ready or timeout. A zero or negative timeout waits indefinitely.