shellsession

package
v0.36.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package shellsession manages one persistent PTY-backed shell per chat session.

It is the backend of the "Shell Sessions" surface (see docs/development/blueprints/beam/shell-sessions.md). A shell is created on demand, rooted at the session's workspace root, and outlives individual commands: cwd, environment, history, and long-running processes persist between submitted lines. Output is captured in a bounded scrollback ring with monotonically increasing offsets so both the agent (via the read tool) and the live UI stream (via subscribers) can consume "everything since a marker" cheaply and without races.

Two reference-only ingestion paths exist, matching the files/@-mention principle: the agent NEVER receives terminal output streamed into its context; it must ask for scrollback explicitly through the read tool, and the human watches the live stream through subscribers. Line input is the approval unit: Run submits exactly one line, gated upstream by the same HITL machinery that wraps every tool.

Index

Constants

View Source
const (
	ToolsProviderName = "shell_session"
	ToolRun           = "shell_session_run"
	ToolRead          = "shell_session_read"
)

Tool names. The provider ("shell_session") is one ToolsRepo exposing two function tools. Run is gated by the same HITL machinery that wraps every tool (default policy → approve); Read is ungated by policy (reference-only reads).

Variables

This section is empty.

Functions

func NewTools

func NewTools(mgr Manager) taskengine.ToolsRepo

NewTools returns the shell_session ToolsRepo. Register it in the engine's LocalTools map under ToolsProviderName exactly like local_shell/local_fs, so it is HITL-wrapped and reachable to the agent only when shell tooling is on.

Types

type Chunk

type Chunk struct {
	Offset int64
	Data   string
	Reset  bool
}

Chunk is one batch of terminal output delivered to a subscriber. Offset is the absolute scrollback offset where Data begins. Reset marks the initial snapshot a fresh subscriber receives (or a stream restart after the PTY was recreated), signalling the consumer to replace rather than append.

type Config

type Config struct {
	// CwdResolver returns the workspace root a new shell should be rooted at,
	// given the tool/request context (which carries the session id). Required.
	CwdResolver func(ctx context.Context) string
	// DefaultRoot is used when CwdResolver yields an empty string.
	DefaultRoot string
	// Shell overrides the shell executable; empty picks a platform default.
	Shell string
	// ScrollbackBytes bounds retained output per shell (default 64 KiB).
	ScrollbackBytes int
	// IdleTimeout kills inactive shells (default 15m; <=0 disables reaping).
	IdleTimeout time.Duration
}

Config configures a Manager. Zero values fall back to sane defaults.

type Manager

type Manager interface {
	// Run ensures a shell exists for sessionID (rooted via the cwd resolver
	// against ctx) and submits one line to it. ctx is used only for cwd
	// resolution at creation time.
	Run(ctx context.Context, sessionID, line string) (RunResult, error)
	// Read returns scrollback for sessionID: bytes since `since` when since >= 0,
	// otherwise the last `tailBytes`. Never creates a shell.
	Read(sessionID string, since int64, tailBytes int) ReadResult
	// Subscribe registers fn for live output of sessionID. fn is invoked from a
	// dedicated goroutine (so a slow consumer cannot stall the PTY). The current
	// scrollback is delivered immediately as a Reset chunk. The returned cancel
	// stops delivery.
	Subscribe(sessionID string, fn func(Chunk)) (cancel func())
	// Kill terminates and forgets sessionID's shell (session close/delete).
	Kill(sessionID string)
	// Shutdown kills every shell and stops the reaper.
	Shutdown()
}

Manager owns the process-global set of per-session shells. All methods are safe for concurrent use and key on the internal chat-session id.

func NewManager

func NewManager(cfg Config) Manager

NewManager builds a Manager and starts its idle reaper.

type ReadResult

type ReadResult struct {
	Content    string
	FromOffset int64
	NextOffset int64
	Exists     bool
}

ReadResult is a scrollback slice: the content, the offset it starts at, and the current end marker to hand to the next read.

type ReadResultJSON

type ReadResultJSON struct {
	Content    string `json:"content"`
	FromOffset int64  `json:"from_offset"`
	NextOffset int64  `json:"next_offset"`
	Exists     bool   `json:"exists"`
	Note       string `json:"note,omitempty"`
}

ReadResultJSON is the structured result of a scrollback read.

type RunResult

type RunResult struct {
	Offset   int64
	Snapshot string
	Started  bool // a new shell was created for this run
}

RunResult is what Run returns after submitting a line: the scrollback end marker and a best-effort snapshot of the output captured within the initial window (empty when the command is still running silently).

type RunResultJSON

type RunResultJSON struct {
	Offset  int64  `json:"offset"`
	Output  string `json:"output"`
	Started bool   `json:"started_new_shell,omitempty"`
	Note    string `json:"note,omitempty"`
}

RunResultJSON is the structured result the agent receives from a run: a marker and the initial output snapshot. The agent polls shell_session_read with the returned offset to follow long-running commands.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL