workspace

package
v0.3.13 Latest Latest
Warning

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

Go to latest
Published: May 14, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package workspace provides a persistent filesystem abstraction for agent state. Knowledge, Skills, and Memory subsystems share a single Workspace. Execution-boundary concerns (command runners, network policy, resource limits) live in sibling package sdk/sandbox.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrPathTraversal = errdefs.Forbidden(errors.New("workspace: path traversal denied"))
	ErrAccessDenied  = errdefs.Forbidden(errors.New("workspace: access denied"))
	ErrNotFound      = errdefs.NotFound(errors.New("workspace: not found"))
)

Common errors.

Functions

func AtomicWrite added in v0.1.13

func AtomicWrite(ctx context.Context, ws Workspace, path string, data []byte) error

AtomicWrite writes data to path via a tmp file + Rename, so concurrent readers never observe a half-written payload. The tmp file is placed in the same directory as path so Rename stays atomic on POSIX filesystems (cross-directory renames are not guaranteed atomic).

On workspaces whose Rename is non-atomic (e.g. object stores) AtomicWrite still runs cleanly; durability/atomicity is then bounded by the underlying store's guarantees, but never weaker than a plain Write.

func Copy

func Copy(ctx context.Context, ws Workspace, src, dst string) error

Copy copies a file from src to dst within the same workspace.

func Glob

func Glob(ctx context.Context, ws Workspace, pattern string) ([]string, error)

Glob returns paths matching a simple pattern relative to the workspace root. It supports patterns like "*.json", "dir/*.yaml", or "**/*.go". The "**" component matches zero or more directory levels.

func Walk

func Walk(ctx context.Context, ws Workspace, dir string, fn WalkFunc) error

Walk recursively traverses the workspace tree rooted at dir, calling fn for each file and directory. Directories are visited before their contents.

func WithWorkspace

func WithWorkspace(ctx context.Context, ws Workspace) context.Context

Types

type Capabilities added in v0.2.11

type Capabilities struct {
	// AtomicRename is true when [Workspace.Rename] succeeds or
	// fails as a single observable operation; readers never see a
	// half-renamed state. POSIX rename(2) on the same filesystem
	// satisfies this. Object stores that emulate Rename as
	// copy+delete do not.
	AtomicRename bool

	// ReadAfterWrite is true when a successful [Workspace.Write]
	// or [Workspace.Append] is immediately observable to a
	// subsequent [Workspace.Read] / [Workspace.List] /
	// [Workspace.Exists] / [Workspace.Stat] from the same client.
	// Strongly-consistent stores (local filesystem, sufficiently
	// recent S3) are true; eventually-consistent stores are false.
	ReadAfterWrite bool

	// DurableOnWrite is true when a successful Write hits stable
	// storage before returning. Implementations that only buffer
	// in user-space (in-memory mocks, write-back caches) report
	// false. Adapters that own crash-recovery logic (WAL replay,
	// manifest swap) read this to decide whether to perform extra
	// flush operations themselves.
	DurableOnWrite bool

	// Distributed is true when more than one process or host can
	// be opened against the same workspace concurrently. Single-
	// process backends (in-memory map, exclusive local directory)
	// report false; cluster file systems and object stores report
	// true. Coordinators use this to choose between a process-
	// local mutex and a distributed lock primitive.
	Distributed bool
}

Capabilities describes the storage characteristics of a Workspace implementation. Higher-layer adapters that need accurate semantics (e.g. an LSM-style retrieval index that relies on atomic Rename, or a multi-process coordinator that needs to know whether the workspace is shareable) read these via CapabilityReporter instead of hard-coding per-implementation assumptions.

All fields default to false, which is the conservative interpretation: adapters that do not bother to type-assert CapabilityReporter — or that handle a workspace whose author has not yet implemented the interface — see "no guarantees" and pick the safe path. Adding a new field is therefore additive.

func CapabilitiesOf added in v0.2.11

func CapabilitiesOf(ws Workspace) Capabilities

CapabilitiesOf returns ws.Capabilities() when ws implements CapabilityReporter, or a zero-value Capabilities otherwise. nil ws also returns the zero value.

type CapabilityReporter added in v0.2.11

type CapabilityReporter interface {
	Capabilities() Capabilities
}

CapabilityReporter is an optional interface that Workspace implementations may satisfy to publish their Capabilities. Adapters that need the information should type-assert; an implementation that does not satisfy the interface should be treated as a conservative all-false Capabilities.

Convenience: see CapabilitiesOf which performs the type-assert + zero-value fallback in one call.

type CommandOption deprecated

type CommandOption = sandbox.Option

CommandOption is an alias for sandbox.Option.

Deprecated: moved to sdk/sandbox.Option. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

func WithMaxOutput deprecated

func WithMaxOutput(n int64) CommandOption

WithMaxOutput is a thin wrapper around sandbox.WithMaxOutputBytes.

Deprecated: moved to sdk/sandbox.WithMaxOutputBytes. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

type CommandRunner deprecated

type CommandRunner = sandbox.Runner

CommandRunner is an alias for sandbox.Runner.

Deprecated: moved to sdk/sandbox.Runner. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

type ExecOptions deprecated

type ExecOptions = sandbox.ExecOptions

ExecOptions is an alias for sandbox.ExecOptions. The new type adds Env / Net / Resources policy fields; callers that used the legacy Env map[string]string knob should move to ExecOptions.Env.Inject.

Deprecated: moved to sdk/sandbox.ExecOptions. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

type ExecResult deprecated

type ExecResult = sandbox.ExecResult

ExecResult is an alias for sandbox.ExecResult.

Deprecated: moved to sdk/sandbox.ExecResult. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

type GitWorkspace

type GitWorkspace interface {
	Workspace
	GitClone(ctx context.Context, url, dest string) error
	GitPull(ctx context.Context, dir string) error
	GitHead(ctx context.Context, dir string) (string, error)
}

GitWorkspace extends Workspace with Git operations.

type LocalCommandRunner deprecated

type LocalCommandRunner = sandbox.LocalRunner

LocalCommandRunner is an alias for sandbox.LocalRunner.

Deprecated: moved to sdk/sandbox.LocalRunner. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

func NewLocalCommandRunner deprecated

func NewLocalCommandRunner(rootDir string, opts ...CommandOption) *LocalCommandRunner

NewLocalCommandRunner is a thin wrapper around sandbox.NewLocalRunner.

Deprecated: moved to sdk/sandbox.NewLocalRunner. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

type LocalWorkspace

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

LocalWorkspace implements Workspace backed by a local directory.

func NewLocalWorkspace

func NewLocalWorkspace(root string) (*LocalWorkspace, error)

NewLocalWorkspace creates a workspace rooted at the given directory. The root path is resolved through EvalSymlinks to prevent the root itself from being a symlink that could be swapped later.

func (*LocalWorkspace) Append

func (w *LocalWorkspace) Append(_ context.Context, path string, data []byte) error

func (*LocalWorkspace) Capabilities added in v0.2.11

func (w *LocalWorkspace) Capabilities() Capabilities

Capabilities reports LocalWorkspace's storage characteristics: backed by the host filesystem, so Rename is atomic on the same device, writes are read-after-write consistent, and durability matches the underlying filesystem's default flush behaviour. Distributed is false because LocalWorkspace assumes exclusive access to its directory tree.

func (*LocalWorkspace) Delete

func (w *LocalWorkspace) Delete(_ context.Context, path string) error

func (*LocalWorkspace) Exists

func (w *LocalWorkspace) Exists(_ context.Context, path string) (bool, error)

func (*LocalWorkspace) GitClone

func (w *LocalWorkspace) GitClone(ctx context.Context, url, dest string) error

func (*LocalWorkspace) GitHead

func (w *LocalWorkspace) GitHead(ctx context.Context, dir string) (string, error)

func (*LocalWorkspace) GitPull

func (w *LocalWorkspace) GitPull(ctx context.Context, dir string) error

func (*LocalWorkspace) List

func (w *LocalWorkspace) List(_ context.Context, dir string) ([]fs.DirEntry, error)

func (*LocalWorkspace) Read

func (w *LocalWorkspace) Read(_ context.Context, path string) ([]byte, error)

func (*LocalWorkspace) RemoveAll

func (w *LocalWorkspace) RemoveAll(_ context.Context, path string) error

func (*LocalWorkspace) Rename added in v0.1.13

func (w *LocalWorkspace) Rename(_ context.Context, src, dst string) error

func (*LocalWorkspace) Root

func (w *LocalWorkspace) Root() string

Root returns the absolute path of the workspace root.

func (*LocalWorkspace) Stat

func (w *LocalWorkspace) Stat(_ context.Context, path string) (fs.FileInfo, error)

func (*LocalWorkspace) Write

func (w *LocalWorkspace) Write(_ context.Context, path string, data []byte) error

type MemWorkspace

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

MemWorkspace implements Workspace entirely in memory.

func NewMemWorkspace

func NewMemWorkspace() *MemWorkspace

func (*MemWorkspace) Append

func (m *MemWorkspace) Append(_ context.Context, path string, data []byte) error

func (*MemWorkspace) Capabilities added in v0.2.11

func (m *MemWorkspace) Capabilities() Capabilities

Capabilities reports MemWorkspace's storage characteristics: in-memory map under a single mutex, so writes are immediately observable, Rename is atomic, but nothing reaches stable storage and the workspace is single-process by construction.

func (*MemWorkspace) Contains

func (m *MemWorkspace) Contains(path, substr string) bool

Contains checks if a path contains a substring — intended for tests.

func (*MemWorkspace) Delete

func (m *MemWorkspace) Delete(_ context.Context, path string) error

func (*MemWorkspace) Exists

func (m *MemWorkspace) Exists(_ context.Context, path string) (bool, error)

func (*MemWorkspace) List

func (m *MemWorkspace) List(_ context.Context, dir string) ([]fs.DirEntry, error)

func (*MemWorkspace) MustWrite

func (m *MemWorkspace) MustWrite(path string, data []byte)

MustWrite panics on error — intended for tests.

func (*MemWorkspace) Read

func (m *MemWorkspace) Read(_ context.Context, path string) ([]byte, error)

func (*MemWorkspace) RemoveAll

func (m *MemWorkspace) RemoveAll(_ context.Context, path string) error

func (*MemWorkspace) Rename added in v0.1.13

func (m *MemWorkspace) Rename(_ context.Context, src, dst string) error

func (*MemWorkspace) Stat

func (m *MemWorkspace) Stat(_ context.Context, path string) (fs.FileInfo, error)

func (*MemWorkspace) Write

func (m *MemWorkspace) Write(_ context.Context, path string, data []byte) error

type NoopCommandRunner deprecated

type NoopCommandRunner = sandbox.NoopRunner

NoopCommandRunner is an alias for sandbox.NoopRunner.

Deprecated: moved to sdk/sandbox.NoopRunner. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

type ScopedCommandRunner deprecated

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

ScopedCommandRunner is the legacy struct-shaped whitelist runner. It is kept as a thin wrapper around sandbox.AllowCommands so existing callers continue to compile.

Deprecated: replaced by the functional sandbox.AllowCommands(inner, allowed) decorator. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

func NewScopedCommandRunner deprecated

func NewScopedCommandRunner(inner CommandRunner, allowed []string) *ScopedCommandRunner

NewScopedCommandRunner wraps inner with the given whitelist. Builds a sandbox.AllowCommands decorator under the hood.

Deprecated: use sandbox.AllowCommands directly. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

func (*ScopedCommandRunner) Exec deprecated

func (r *ScopedCommandRunner) Exec(ctx context.Context, cmd string, args []string, opts ExecOptions) (*ExecResult, error)

Exec implements sandbox.Runner via the underlying AllowCommands decorator built in NewScopedCommandRunner.

Deprecated: see ScopedCommandRunner. Will be removed in v0.5.0 (same window as catalog.Deps.AgentTools and runner.WithActorKey).

type ScopedGitWorkspace

type ScopedGitWorkspace struct {
	*ScopedWorkspace
	// contains filtered or unexported fields
}

func NewScopedGitWorkspace

func NewScopedGitWorkspace(inner GitWorkspace, opts ...ScopedOption) *ScopedGitWorkspace

func (*ScopedGitWorkspace) GitClone

func (s *ScopedGitWorkspace) GitClone(ctx context.Context, url, dest string) error

func (*ScopedGitWorkspace) GitHead

func (s *ScopedGitWorkspace) GitHead(ctx context.Context, dir string) (string, error)

func (*ScopedGitWorkspace) GitPull

func (s *ScopedGitWorkspace) GitPull(ctx context.Context, dir string) error

type ScopedOption

type ScopedOption func(*ScopedWorkspace)

func WithAllowWrite

func WithAllowWrite(patterns ...string) ScopedOption

func WithDenyRead

func WithDenyRead(patterns ...string) ScopedOption

func WithMandatoryDeny

func WithMandatoryDeny(patterns ...string) ScopedOption

func WithViolationLogger

func WithViolationLogger(l ViolationLogger) ScopedOption

type ScopedWorkspace

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

ScopedWorkspace wraps a Workspace with dual-mode permission enforcement:

  • Read: deny-only mode — everything readable unless path matches denyRead
  • Write: allow-only mode — nothing writable unless path matches allowWrite
  • Mandatory deny paths are always blocked for both read and write

func NewScopedWorkspace

func NewScopedWorkspace(inner Workspace, opts ...ScopedOption) *ScopedWorkspace

func (*ScopedWorkspace) Append

func (s *ScopedWorkspace) Append(ctx context.Context, path string, data []byte) error

func (*ScopedWorkspace) Capabilities added in v0.2.11

func (s *ScopedWorkspace) Capabilities() Capabilities

Capabilities forwards to the wrapped Workspace, since scoping is a security boundary that does not change durability / atomicity / consistency / distribution semantics. A wrapped Workspace that does not implement CapabilityReporter yields a zero-value (all-false) Capabilities via CapabilitiesOf.

ScopedGitWorkspace embeds ScopedWorkspace and therefore inherits this method.

func (*ScopedWorkspace) Delete

func (s *ScopedWorkspace) Delete(ctx context.Context, path string) error

func (*ScopedWorkspace) Exists

func (s *ScopedWorkspace) Exists(ctx context.Context, path string) (bool, error)

func (*ScopedWorkspace) List

func (s *ScopedWorkspace) List(ctx context.Context, dir string) ([]fs.DirEntry, error)

func (*ScopedWorkspace) Read

func (s *ScopedWorkspace) Read(ctx context.Context, path string) ([]byte, error)

func (*ScopedWorkspace) RemoveAll

func (s *ScopedWorkspace) RemoveAll(ctx context.Context, path string) error

func (*ScopedWorkspace) Rename added in v0.1.13

func (s *ScopedWorkspace) Rename(ctx context.Context, src, dst string) error

func (*ScopedWorkspace) Stat

func (s *ScopedWorkspace) Stat(ctx context.Context, path string) (fs.FileInfo, error)

func (*ScopedWorkspace) Write

func (s *ScopedWorkspace) Write(ctx context.Context, path string, data []byte) error

type ViolationLogger

type ViolationLogger interface {
	LogViolation(ctx context.Context, record ViolationRecord)
}

ViolationLogger receives violation records from ScopedWorkspace.

type ViolationRecord

type ViolationRecord struct {
	Time      time.Time `json:"time"`
	Operation string    `json:"operation"`
	Path      string    `json:"path"`
	Reason    string    `json:"reason"`
}

ViolationRecord captures a rejected operation for audit logging.

type WalkFunc

type WalkFunc func(path string, entry fs.DirEntry) error

WalkFunc is the callback for Walk. Return filepath.SkipDir to skip a directory subtree, or any other non-nil error to abort the walk.

type Workspace

type Workspace interface {
	Read(ctx context.Context, path string) ([]byte, error)
	Write(ctx context.Context, path string, data []byte) error
	Append(ctx context.Context, path string, data []byte) error
	// Rename moves src to dst within the same workspace. Implementations
	// MUST be atomic when the underlying medium supports it (e.g. POSIX
	// rename(2) on a local filesystem). When the medium cannot rename
	// atomically (e.g. object stores) the implementation MAY fall back
	// to copy + delete, but callers should treat Rename as the canonical
	// "publish a finalized payload" operation: write to a tmp path then
	// Rename to the live path so readers never observe a half-written file.
	//
	// Returns ErrNotFound if src does not exist. Overwriting an existing
	// dst is allowed; on local filesystems this is atomic.
	Rename(ctx context.Context, src, dst string) error
	Delete(ctx context.Context, path string) error
	RemoveAll(ctx context.Context, path string) error
	List(ctx context.Context, dir string) ([]fs.DirEntry, error)
	Exists(ctx context.Context, path string) (bool, error)
	Stat(ctx context.Context, path string) (fs.FileInfo, error)
}

Workspace abstracts file operations over a sandboxed directory tree. All paths are relative to the workspace root; absolute paths and path traversals ("..") are rejected.

func MustWorkspaceFrom

func MustWorkspaceFrom(ctx context.Context) Workspace

MustWorkspaceFrom extracts the Workspace from ctx or panics. Intended for use in code paths where a Workspace is guaranteed to be present (e.g. after middleware injection).

func WorkspaceFrom

func WorkspaceFrom(ctx context.Context) (Workspace, bool)

Jump to

Keyboard shortcuts

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