boxshclient

package
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Apr 21, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package boxshclient provides a JSON-RPC client for the boxsh sandbox process.

Index

Constants

View Source
const (
	NetworkDisabled  = string(sandboxpkg.NetworkDisabled)
	NetworkAllowAll  = string(sandboxpkg.NetworkAllowAll)
	NetworkWhitelist = string(sandboxpkg.NetworkWhitelist)
)

Variables

This section is empty.

Functions

func CleanupLegacySessionDirs added in v0.13.0

func CleanupLegacySessionDirs(dir string)

CleanupLegacySessionDirs removes orphaned session dirs from the old incorrect location caused by the filepath.Dir(UserRoot) bug. Legacy dirs have no metadata so they are removed without syncing.

func CleanupOrphanedSessions added in v0.13.0

func CleanupOrphanedSessions(annaHome string)

CleanupOrphanedSessions syncs and removes any leftover session directories from crashed processes. Sessions with readable metadata are synced back to their source workspace; sessions without metadata are removed silently.

func CleanupSessionDir

func CleanupSessionDir(sessionDir string) error

CleanupSessionDir removes the ephemeral session directory and its metadata sidecar.

func CreateSessionDir

func CreateSessionDir(baseDir string) (string, error)

CreateSessionDir creates an ephemeral session directory for the overlay root. The caller is responsible for cleaning up the directory.

func DefaultAnnaHome

func DefaultAnnaHome() string

func IsSharedBackendError

func IsSharedBackendError(err error) bool

IsSharedBackendError reports whether an error originated from the shared backend.

func PlatformSupportsBoxsh

func PlatformSupportsBoxsh() bool

PlatformSupportsBoxsh reports whether the current platform supports boxsh sandboxing.

func ResolveManagedBoxshPath

func ResolveManagedBoxshPath(annaHome string) (string, error)

ResolveManagedBoxshPath returns the path to the managed boxsh binary in annaHome.

func ResolveSandboxCwd

func ResolveSandboxCwd(userRoot, workDir string) string

ResolveSandboxCwd determines the working directory inside the sandbox. If workDir is empty or not under the user root, it defaults to the user root.

func SyncSessionToSrc added in v0.13.0

func SyncSessionToSrc(dst, src string) error

SyncSessionToSrc copies all files from the session overlay upperdir (dst) back to the source workspace (src) using cp -a. Only files written during the session exist in dst. Deletions are not propagated.

TODO: propagate deletions. Options: (a) pre-populate DST with a full copy of SRC at session start, then use `rsync -a --delete DST/ SRC/` on close; (b) track deletions in boxshHost.Remove and replay them on SRC at close.

func ValidatePathWithinRoot added in v0.10.1

func ValidatePathWithinRoot(userRoot, path string) error

ValidatePathWithinRoot checks that a path stays within the configured root. This is a defensive check used before passing paths to the boxsh client.

func WriteSessionMeta added in v0.13.0

func WriteSessionMeta(sessionDir, src string) error

WriteSessionMeta writes a sidecar metadata file next to sessionDir.

Types

type BackendConfig

type BackendConfig struct {
	// BinaryPath is the path to the boxsh binary. If empty, uses managed binary.
	BinaryPath string

	// AnnaHome is the Anna home directory (used for binary resolution).
	AnnaHome string

	// UserRoot is the writable root mounted into the sandbox.
	UserRoot string

	// Sandbox contains the sandbox network configuration.
	Sandbox NetworkConfig

	// WorkDir is the working directory for tool execution.
	// This is resolved relative to the user root.
	WorkDir string

	// SessionBaseDir is the base directory for ephemeral session directories.
	// Defaults to AnnaHome/cache/sandbox/sessions.
	SessionBaseDir string

	// ReadOnlyDirs are mounted read-only into the sandbox so helper binaries
	// and user PATH directories remain available from shell commands.
	ReadOnlyDirs []string
}

BackendConfig configures the shared backend.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client manages a boxsh --rpc subprocess and provides typed RPC methods.

func New

func New(binaryPath string, cfg SessionConfig) *Client

New creates a boxsh client with the given binary path and session configuration.

func (*Client) Alive

func (c *Client) Alive() bool

Alive reports whether the boxsh process is still running.

func (*Client) Close

func (c *Client) Close() error

Close shuts down the boxsh process and cleans up resources.

func (*Client) Edit

func (c *Client) Edit(ctx context.Context, params EditParams) (*EditResult, error)

Edit applies string replacements to a file in the sandbox.

func (*Client) Exec

func (c *Client) Exec(ctx context.Context, params ExecParams) (*ExecResult, error)

Exec runs a bash command in the sandbox.

func (*Client) List

List is not supported by boxsh 2.0.1.

func (*Client) Read

func (c *Client) Read(ctx context.Context, params ReadParams) (*ReadResult, error)

Read reads a file from the sandbox.

func (*Client) Start

func (c *Client) Start(ctx context.Context) error

Start launches the boxsh --rpc subprocess and initializes the session.

func (*Client) Stat

Stat is not supported by boxsh 2.0.1.

func (*Client) Stderr

func (c *Client) Stderr() string

Stderr returns buffered stderr output from the boxsh process.

func (*Client) Write

func (c *Client) Write(ctx context.Context, params WriteParams) (*WriteResult, error)

Write writes content to a file in the sandbox.

type DirEntry

type DirEntry struct {
	Name  string `json:"name"`
	IsDir bool   `json:"is_dir"`
	Size  int64  `json:"size"`
}

DirEntry represents a single directory entry.

type EditParams

type EditParams struct {
	FilePath string     `json:"path"`
	Edits    []EditSpec `json:"edits"`
}

EditParams are parameters for the Edit method.

type EditResult

type EditResult struct {
	Path         string `json:"path"`
	Replacements int    `json:"replacements"`
	Diff         string `json:"diff,omitempty"`
}

EditResult is the result from the Edit method.

type EditSpec

type EditSpec struct {
	OldText string `json:"oldText"`
	NewText string `json:"newText"`
}

EditSpec is one edit operation accepted by boxsh.

type ExecParams

type ExecParams struct {
	Command string `json:"command"`
	Timeout int    `json:"timeout,omitempty"`
}

ExecParams are parameters for the Exec method.

type ExecResult

type ExecResult struct {
	Stdout   string `json:"stdout"`
	Stderr   string `json:"stderr"`
	ExitCode int    `json:"exit_code"`
}

ExecResult is the result from the Exec method.

type ListParams

type ListParams struct {
	DirPath string `json:"dir_path,omitempty"`
}

ListParams are parameters for the List method (directory listing).

type ListResult

type ListResult struct {
	Entries []DirEntry `json:"entries"`
}

ListResult is the result from the List method.

type NetworkConfig

type NetworkConfig struct {
	Mode      string
	Allowlist []string
}

func (NetworkConfig) ModeOrDefault

func (c NetworkConfig) ModeOrDefault() string

type NormalizeResult

type NormalizeResult struct {
	// Content is the main text output for the tool.
	Content string

	// IsError indicates if this is an error result.
	IsError bool

	// Metadata contains additional information (exit codes, timing, etc.).
	Metadata map[string]any
}

NormalizeResult contains normalized output for Anna tools.

type Normalizer

type Normalizer struct {
	// MaxOutputLen limits the length of normalized output before truncation.
	// 0 means use default (50KB as per tools.TruncateTail).
	MaxOutputLen int

	// IncludeTimestamps determines whether to include timing info in output.
	IncludeTimestamps bool
}

Normalizer converts boxsh RPC responses into Anna-compatible tool outputs.

func NewNormalizer

func NewNormalizer() *Normalizer

NewNormalizer creates a default normalizer with sensible defaults.

func (*Normalizer) NormalizeEdit

func (n *Normalizer) NormalizeEdit(result *EditResult) *NormalizeResult

NormalizeEdit converts an EditResult to Anna-compatible output.

func (*Normalizer) NormalizeError

func (n *Normalizer) NormalizeError(err error, toolName string) *NormalizeResult

NormalizeError converts an error into Anna-compatible output.

func (*Normalizer) NormalizeExec

func (n *Normalizer) NormalizeExec(result *ExecResult, elapsed time.Duration) *NormalizeResult

NormalizeExec converts an ExecResult to Anna-compatible output.

func (*Normalizer) NormalizeRead

func (n *Normalizer) NormalizeRead(result *ReadResult, filePath string, requestedOffset int) *NormalizeResult

NormalizeRead converts a ReadResult to Anna-compatible output.

func (*Normalizer) NormalizeWrite

func (n *Normalizer) NormalizeWrite(result *WriteResult) *NormalizeResult

NormalizeWrite converts a WriteResult to Anna-compatible output.

type RPCError

type RPCError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data,omitempty"`
}

RPCError represents a JSON-RPC error.

func (*RPCError) Error

func (e *RPCError) Error() string

type ReadParams

type ReadParams struct {
	FilePath string `json:"path"`
	Offset   int    `json:"offset,omitempty"`
	Limit    int    `json:"limit,omitempty"`
}

ReadParams are parameters for the Read method.

type ReadResult

type ReadResult struct {
	Content    string `json:"content"`
	TotalLines int    `json:"total_lines"`
	Truncated  bool   `json:"truncated"`
}

ReadResult is the result from the Read method.

type Request

type Request struct {
	JSONRPC string          `json:"jsonrpc"`
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params,omitempty"`
	ID      uint64          `json:"id,omitempty"`
}

Request is a JSON-RPC request.

type Response

type Response struct {
	JSONRPC string          `json:"jsonrpc"`
	Result  json.RawMessage `json:"result,omitempty"`
	Error   *RPCError       `json:"error,omitempty"`
	ID      uint64          `json:"id"`
}

Response is a JSON-RPC response.

type SessionConfig

type SessionConfig struct {
	// Src is the source workspace (read-only lower layer).
	Src string
	// Dst is the destination overlay root exposed inside the sandbox.
	Dst string
	// Cwd is the working directory inside the sandbox.
	Cwd string
	// ReadOnlyDirs are additional host directories bound read-only into the
	// sandbox so executables from PATH remain usable.
	ReadOnlyDirs []string
	// Network mode: disabled, allow_all, or whitelist.
	NetworkMode string
	// NetworkAllowlist is kept for config compatibility. Current boxsh only
	// supports allow-all or fully disabled networking.
	NetworkAllowlist []string
}

SessionConfig configures a boxsh sandbox session.

func BuildSessionConfig

func BuildSessionConfig(info *SessionInfo) SessionConfig

BuildSessionConfig builds a boxsh SessionConfig from SessionInfo.

type SessionInfo

type SessionInfo struct {
	// Src is the source workspace (read-only lower layer).
	Src string

	// Dst is the ephemeral destination upperdir (read-write layer).
	Dst string

	// Cwd is the working directory inside the sandbox.
	Cwd string

	// NetworkMode is the effective network mode.
	NetworkMode string

	// NetworkAllowlist contains allowed hosts/CIDRs for whitelist mode.
	NetworkAllowlist []string
}

SessionInfo holds the resolved session configuration.

type SessionManager

type SessionManager struct {
	// contains filtered or unexported fields
}

SessionManager handles the lifecycle of sandbox sessions including sandbox root selection, ephemeral directory creation, and cleanup.

func NewSessionManager

func NewSessionManager(baseDir string) (*SessionManager, error)

NewSessionManager creates a new session manager with the given base directory. If baseDir is empty, uses AnnaHome/cache/sandbox/sessions.

func (*SessionManager) CleanupSession

func (m *SessionManager) CleanupSession(session *SessionInfo) error

CleanupSession removes the ephemeral session directory.

func (*SessionManager) CreateSession

func (m *SessionManager) CreateSession(opts SessionOptions) (*SessionInfo, error)

CreateSession creates a new sandbox session with an ephemeral upperdir. The caller is responsible for calling CleanupSession to remove the ephemeral directory.

type SessionMeta added in v0.13.0

type SessionMeta struct {
	Src       string    `json:"src"`
	CreatedAt time.Time `json:"created_at"`
}

SessionMeta records the source workspace path for a sandbox session so orphaned sessions can be synced back after a crash.

func ReadSessionMeta added in v0.13.0

func ReadSessionMeta(sessionDir string) (*SessionMeta, error)

ReadSessionMeta reads the sidecar metadata file next to sessionDir.

type SessionOptions

type SessionOptions struct {
	// UserRoot is the writable root mounted into the sandbox.
	UserRoot string

	// WorkDir is the working directory for tool execution.
	WorkDir string

	// Sandbox contains the network policy configuration.
	Sandbox NetworkConfig
}

SessionOptions configures a sandbox session.

type SharedBackend

type SharedBackend struct {
	// contains filtered or unexported fields
}

SharedBackend provides a shared boxsh session for all core tools. It manages the lifecycle of a single boxsh --rpc process that is reused by bash, read, write, and edit operations.

func NewSharedBackend

func NewSharedBackend(cfg BackendConfig) (*SharedBackend, error)

NewSharedBackend creates a new shared backend without starting it. Use Start() to initialize the boxsh process.

func (*SharedBackend) Alive

func (b *SharedBackend) Alive() bool

Alive reports whether the shared backend is healthy and the boxsh process is running.

func (*SharedBackend) Client

func (b *SharedBackend) Client() *Client

Client returns the underlying boxsh client for direct RPC calls. Returns nil if the backend is not started or already closed.

func (*SharedBackend) Close

func (b *SharedBackend) Close() error

Close shuts down the shared backend, terminating the boxsh process and cleaning up the ephemeral session directory.

func (*SharedBackend) SessionDir

func (b *SharedBackend) SessionDir() string

SessionDir returns the ephemeral session directory path (DST). This is primarily for testing and debugging.

func (*SharedBackend) Start

func (b *SharedBackend) Start(ctx context.Context, cfg BackendConfig) error

Start initializes the shared backend by creating the session directory and starting the boxsh RPC process.

func (*SharedBackend) Sync added in v0.13.0

func (b *SharedBackend) Sync() error

Sync copies changed files from the session overlay back to the source workspace without closing the session.

func (*SharedBackend) UserRoot added in v0.10.1

func (b *SharedBackend) UserRoot(ctx context.Context) (string, error)

UserRoot returns the sandbox-visible user root for path resolution.

type StatParams

type StatParams struct {
	Path string `json:"path"`
}

StatParams are parameters for the Stat method.

type StatResult

type StatResult struct {
	Exists  bool   `json:"exists"`
	IsDir   bool   `json:"is_dir"`
	Size    int64  `json:"size"`
	ModTime string `json:"mod_time"`
}

StatResult is the result from the Stat method.

type WriteParams

type WriteParams struct {
	FilePath string `json:"path"`
	Content  string `json:"content"`
}

WriteParams are parameters for the Write method.

type WriteResult

type WriteResult struct {
	BytesWritten int    `json:"bytes_written"`
	Path         string `json:"path"`
}

WriteResult is the result from the Write method.

Jump to

Keyboard shortcuts

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