WorkspaceFileBackend

org.llm4s.agent.harness.workspace.WorkspaceFileBackend
See theWorkspaceFileBackend companion object
@Experimental
final class WorkspaceFileBackend extends FileBackend

A containerised workspace's files as a FileBackend (design ยง4.33): /src/a.txt is the workspace's src/a.txt, / its root. One workspace is one tenant's: an application serving several builds one backend per tenant and picks it with FileBackend.resolved (rule 8).

  • '''Order.''' A mutation locks the whole workspace, files/workspace/<id> (WorkspaceLocks), as a command there does, so a batch's edits and commands apply in call order, even two paths that name one file through a link. Reads take no lock and see the workspace as it is.
  • '''Replay.''' The target is Verifiable (C4). Each mutation runs ReplayGuard.verifiable under ctx.effectKey("file.write" | "file.edit" | "file.delete", path): the plan reads the file once, makes every refusal, and plans a compare-and-set against the hash it read, which the runner applies atomically under its mutation lock and replaces the file atomically. So a replayed edit that landed returns its first outcome, one that did not runs again, and one whose file another writer changed is refused.
  • '''Bounds.''' Content and an edit's result at most maxFileBytes UTF-8 bytes, checked before they are sent; a read at most the runner's maxFileSize; listings at most the runner's maxDirectoryEntries, then limit. A listing the runner cut is truncated, its entries those the runner returned, sorted.
  • '''Block.''' A workspace effect stays when a Block retracts its turn (rule 5).

Listings show what the runner's default exclusions (.git, node_modules, ...) leave, and skip entries whose names are not valid paths. grep reads each file whole, as text: a file that is not UTF-8 or is over the runner's size limit is skipped and the listing marked truncated.

Attributes

Companion
object
Graph
Supertypes
trait FileBackend
class Object
trait Matchable
class Any

Members list

Value members

Concrete methods

Deletes the file, or the empty directory, path.

Deletes the file, or the empty directory, path.

Attributes

def edit(path: VPath, old: String, replacement: String, replaceAll: Boolean, ctx: FileContext): Result[(FileEdited, StateUpdate)]

Replaces old with replacement in the file path: the one occurrence, or every occurrence when replaceAll. Refused when old is empty or absent, or occurs more than once and not replaceAll.

Replaces old with replacement in the file path: the one occurrence, or every occurrence when replaceAll. Refused when old is empty or absent, or occurs more than once and not replaceAll.

Attributes

def find(under: VPath, accept: VPath => Boolean, limit: Int, ctx: FileContext): Result[Listing[VPath]]

The files within under that accept takes, in path order, at most limit: accept is applied before the limit, so a file it refuses never takes a place (a composite passes a predicate that refuses the paths a mount shadows, and relies on this to fill its limit with visible files). search likewise.

The files within under that accept takes, in path order, at most limit: accept is applied before the limit, so a file it refuses never takes a place (a composite passes a predicate that refuses the paths a mount shadows, and relies on this to fill its limit with visible files). search likewise.

Attributes

def locks(path: VPath): Set[LockKey]

The locks a mutation of path holds.

The locks a mutation of path holds.

Attributes

def ls(path: VPath, limit: Int, ctx: FileContext): Result[Listing[FileInfo]]

The entries directly beneath the directory path, in path order, at most limit.

The entries directly beneath the directory path, in path order, at most limit.

Attributes

def read(path: VPath, offset: Int, limit: Int, ctx: FileContext): Result[FileLines]

At most limit lines of the file path, from the 0-based line offset.

At most limit lines of the file path, from the 0-based line offset.

Attributes

def search(under: VPath, regex: Pattern, accept: VPath => Boolean, limit: Int, ctx: FileContext): Result[Listing[GrepMatch]]

The lines matching regex of the files within under that accept takes, in path then line order. regex is the model's: match it with org.llm4s.security.RegexSafetyManager.safeFind, never a bare matcher, so a catastrophic pattern is bounded and cannot overflow the stack.

The lines matching regex of the files within under that accept takes, in path then line order. regex is the model's: match it with org.llm4s.security.RegexSafetyManager.safeFind, never a bare matcher, so a catastrophic pattern is bounded and cannot overflow the stack.

Attributes

def write(path: VPath, content: String, ctx: FileContext): Result[(FileWritten, StateUpdate)]

Writes the file path, creating it or replacing it.

Writes the file path, creating it or replacing it.

Attributes

Inherited methods

final def glob(pattern: Glob, under: VPath, limit: Int, ctx: FileContext): Result[Listing[VPath]]

The files within under whose path relative to under matches pattern.

The files within under whose path relative to under matches pattern.

Attributes

Inherited from:
FileBackend
final def grep(regex: String, under: VPath, include: Option[Glob], limit: Int, ctx: FileContext): Result[Listing[GrepMatch]]

The lines matching regex in the files within under. include filters the files: a pattern with no / matches a file's name, one with a / its path relative to under (as ripgrep's --glob).

The lines matching regex in the files within under. include filters the files: a pattern with no / matches a file's name, one with a / its path relative to under (as ripgrep's --glob).

Attributes

Inherited from:
FileBackend

Concrete fields

val id: String
val maxFileBytes: Long

C4's class for this target.

C4's class for this target.

Attributes

val writes: Set[StateKey[_, _]]

The state keys the StateUpdates of this backend's mutations touch; a tool declares them in writes.

The state keys the StateUpdates of this backend's mutations touch; a tool declares them in writes.

Attributes