shellsession

package
v0.37.0 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package shellsession manages one persistent PTY-backed shell per chat session, rooted at the session's workspace root and outliving individual commands. Output lives in a bounded scrollback ring with monotonically increasing offsets; the agent never receives it streamed and must read scrollback explicitly. Run submits exactly one line, gated by HITL.

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
	// Workspace is the operator's workspace-root allowlist, enforced against
	// whatever CwdResolver returns; the only source of the default root.
	// Nil means no allowlist, and an absolute cwd is taken as given.
	Workspace *vfs.Factory
	// 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
	// ScrubEnv, when set, maps the parent environment to the one a spawned
	// shell inherits, so serve's own secrets never reach an agent-reachable
	// PTY. Nil inherits the full environment.
	ScrubEnv func([]string) []string
}

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
	// Resize records the terminal geometry for sessionID and applies it to
	// the live shell when there is one. Total: an unknown session, a reaped
	// shell, or a non-positive dimension are no-ops, not errors. The size is
	// remembered even with no live shell, so the next one is born at it.
	Resize(sessionID string, rows, cols int)
	// Subscribe registers fn for live output of sessionID, invoked from a
	// dedicated goroutine so a slow consumer cannot stall the PTY. The
	// current scrollback is delivered immediately as a Reset chunk.
	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