Sagents.FileSystem.FileEntry (Sagents v0.4.2)

Copy Markdown

Represents a file or directory in the virtual filesystem.

Field Semantics

  • :entry_type - Whether this is a file or directory

    • :file - A regular file with content
    • :directory - A directory entry (no content, never dirty)
  • :title - Human-readable display name (e.g. "Hero Character Sheet") Promoted to a first-class field so both application code and LLM tools can reference entries by their user-visible name.

  • :persistence - Storage strategy

    • :memory - Ephemeral, exists only in ETS (e.g., /scratch files)
    • :persisted - Durable, backed by storage (e.g., /Memories files)
  • :loaded - Content availability

    • true - Content is in ETS, ready to use
    • false - Content exists in storage but not loaded (lazy load on read)
  • :dirty_content - Content sync status (only meaningful when persistence: :persisted)

    • false - In-memory content matches storage
    • true - In-memory content differs from storage (needs persist)
  • :dirty_non_content - Non-content change tracking

    • false - Entry-level fields and metadata match storage
    • true - Only non-content fields changed (enables metadata-only persist optimization)

State Examples

Memory file (always loaded, never dirty): %FileEntry{entry_type: :file, persistence: :memory, loaded: true, dirty_content: false, content: "data"}

Persisted file, clean, loaded: %FileEntry{entry_type: :file, persistence: :persisted, loaded: true, dirty_content: false, content: "data"}

Persisted file, not yet loaded (lazy): %FileEntry{entry_type: :file, persistence: :persisted, loaded: false, dirty_content: false, content: nil}

Persisted file, modified since last save: %FileEntry{entry_type: :file, persistence: :persisted, loaded: true, dirty_content: true, content: "new data"}

Directory entry: %FileEntry{entry_type: :directory, persistence: :persisted, loaded: true, dirty_content: false, content: nil}

Summary

Functions

Creates a changeset for a file entry.

Returns true if the entry is a directory.

Marks a persisted file as clean (synced with storage).

Marks a file as loaded with the given content.

Creates a new directory entry.

Creates a file entry for an indexed persisted file (not yet loaded).

Creates a new file entry for memory storage.

Creates a new file entry for persisted storage. Intended for situations when the LLM instructs a new file to be created that will need to be persisted to storage.

Updates file content and marks as dirty if persisted.

Changeset for updating entry-level fields (not content or internal state).

Validates that a name (title or path segment) is safe for use in paths.

Types

t()

@type t() :: %Sagents.FileSystem.FileEntry{
  content: String.t() | nil,
  dirty_content: boolean(),
  dirty_non_content: boolean(),
  entry_type: :file | :directory,
  file_type: String.t() | nil,
  id: String.t() | nil,
  loaded: boolean(),
  metadata: Sagents.FileSystem.FileMetadata.t() | nil,
  path: String.t(),
  persistence: :memory | :persisted,
  title: String.t() | nil
}

Functions

changeset(entry \\ %FileEntry{}, attrs)

Creates a changeset for a file entry.

directory?(arg1)

@spec directory?(t()) :: boolean()

Returns true if the entry is a directory.

mark_clean(entry)

Marks a persisted file as clean (synced with storage).

mark_loaded(entry, content)

Marks a file as loaded with the given content.

Preserves existing metadata if present, updating only content-related fields.

new_directory(path, opts \\ [])

Creates a new directory entry.

Directories have no content, are always "loaded", and are never dirty on creation.

Options

  • :title - Human-readable name for the directory
  • :custom - Custom metadata map
  • :persistence - :memory or :persisted (default: :persisted)

new_indexed_file(path, opts \\ [])

Creates a file entry for an indexed persisted file (not yet loaded).

Accepts optional keyword opts to set :title, :entry_type, and :metadata.

new_memory_file(path, content, opts \\ [])

Creates a new file entry for memory storage.

new_persisted_file(path, content, opts \\ [])

Creates a new file entry for persisted storage. Intended for situations when the LLM instructs a new file to be created that will need to be persisted to storage.

update_content(entry, new_content, opts \\ [])

Updates file content and marks as dirty if persisted.

Preserves existing metadata (custom, created_at, mime_type, etc.) and only updates content-related fields (size, modified_at, checksum).

Returns {:error, :directory_has_no_content} if called on a directory entry.

update_entry_changeset(entry, attrs)

Changeset for updating entry-level fields (not content or internal state).

Only allows :title, :id, and :file_type to be changed.

valid_name?(name)

@spec valid_name?(String.t()) :: boolean()

Validates that a name (title or path segment) is safe for use in paths.

The library enforces minimal restrictions — only characters that would break path resolution are disallowed:

  • / (path separator)
  • null bytes
  • leading/trailing whitespace
  • empty strings