Skip to content

symfonic.core.prompt.blocks.sources.file_revision

file_revision

What a block file read may fail with, and how its revision is derived.

The failure vocabulary and the content digest of :mod:symfonic.core.prompt.blocks.sources.file, kept apart from the adapter that raises them. A caller that only needs to catch a block file failure -- or to compute the revision a given text would carry -- does not have to import the adapter, and the size ceiling that guards the read is declared next to the errors it produces rather than inside the class that enforces it.

MAX_BLOCK_FILE_BYTES module-attribute

MAX_BLOCK_FILE_BYTES = 1048576

The largest file this adapter will read into a prompt -- 1 MiB.

A prompt block is operator-authored text, not a general-purpose file store: an authored block that size is already implausible, and reading past it converts a config mistake (a deploy that swapped a small IDENTITY.md for a generated or log file) into unbounded memory growth on every single resolve, with the failure surfacing downstream as memory pressure or a provider context error rather than through the block's on_source_failure policy. Checked against the file's stat size before any read, so an oversized file never reaches read_text.

REVISION_ALGORITHM module-attribute

REVISION_ALGORITHM = 'sha256'

The digest naming the revision. Recorded in the revision id itself.

BlockFileNotFoundError

Bases: BlockFileUnavailableError, NotFoundError

The backing file does not exist.

Derives from both :class:BlockFileUnavailableError (so a resolver catching the source-failure family catches it) and :class:~symfonic.core.protocols.NotFoundError (so "absent" stays distinguishable from "present but unreadable" -- an operator who mistyped a path and one whose deploy dropped read permissions need different fixes).

BlockFileUnavailableError

Bases: StorageError

The backing file exists but could not be read as block content.

A permission denial, a path that is a directory, or content that is not decodable in the declared encoding. Typed as a :class:~symfonic.core.protocols.StorageError so the resolver routes it through the block's on_source_failure policy instead of letting a raw :class:OSError escape past it.

content_revision

content_revision(content: str) -> str

Return the revision id for content -- sha256:<hex>.

A pure function of the text, with no filesystem access at all, so the same content produces the same revision on every host and at every mtime. Exposed rather than inlined so a cache-invalidation check can compute the expected revision for content it already holds, without a second read.

The text is hashed as UTF-8 regardless of the encoding it was read in: the revision identifies the block's content, so re-saving the same words in a different on-disk encoding must not present itself as an edit.

Source code in src/symfonic/core/prompt/blocks/sources/file_revision.py
def content_revision(content: str) -> str:
    """Return the revision id for ``content`` -- ``sha256:<hex>``.

    A pure function of the text, with no filesystem access at all, so
    the same content produces the same revision on every host and at
    every mtime. Exposed rather than inlined so a cache-invalidation
    check can compute the expected revision for content it already
    holds, without a second read.

    The text is hashed as UTF-8 regardless of the encoding it was read
    in: the revision identifies the block's *content*, so re-saving the
    same words in a different on-disk encoding must not present itself
    as an edit.
    """
    digest = hashlib.sha256(content.encode("utf-8")).hexdigest()
    return f"{REVISION_ALGORITHM}:{digest}"