Skip to content

responses

responses #

Response models for the CaptureGraph captured-data file API.

Pydantic models for the CaptureGraph server's captured-data file API, shared between capturegraph-server (produces) and capturegraph-sync (consumes). The full wire spec lives in docs/dsl/captured-data-format.md.

EntriesResponse #

Bases: BaseModel

Response from the directories enumeration endpoint.

exists is the directory's own presence on disk, told apart from an empty listing so a loaded Array/Map keeps a present-but-empty directory (an empty collection) distinct from an absent one (Missing). entries are the distinct child stems (subdirectory names plus file stems without extension), sorted — Map key-encoded names and Array zero-padded indices in the layout.

Source code in capturegraph-lib/capturegraph/api_models/responses.py
class EntriesResponse(BaseModel):
    """Response from the ``directories`` enumeration endpoint.

    ``exists`` is the directory's own presence on disk, told apart from an empty
    listing so a loaded Array/Map keeps a present-but-empty directory (an empty
    collection) distinct from an absent one (Missing). ``entries`` are the
    distinct child stems (subdirectory names plus file stems without extension),
    sorted — Map key-encoded names and Array zero-padded indices in the layout.
    """

    exists: bool
    entries: list[str]

FileSaveResponse #

Bases: BaseModel

Response from the files:save batch endpoint.

results[i] is the present verdict for the request's entries[i], ready for the client to cache each written leaf without a follow-up read.

Source code in capturegraph-lib/capturegraph/api_models/responses.py
class FileSaveResponse(BaseModel):
    """Response from the ``files:save`` batch endpoint.

    ``results[i]`` is the ``present`` verdict for the request's ``entries[i]``,
    ready for the client to cache each written leaf without a follow-up read.
    """

    results: list[LeafState]

LeafResolveResponse #

Bases: BaseModel

Response from files:resolve.

results[i] answers the request's entries[i].

Source code in capturegraph-lib/capturegraph/api_models/responses.py
class LeafResolveResponse(BaseModel):
    """Response from ``files:resolve``.

    ``results[i]`` answers the request's ``entries[i]``.
    """

    results: list[LeafState]

LeafState #

Bases: BaseModel

The server's verdict for one leaf, the unit of the resolve and save APIs.

A leaf has exactly one status:

  • unchanged: the client's known_version is still current. No payload; the client serves its cached copy.
  • present: the leaf exists with content identified by version (an opaque token; equal versions mean identical bytes). extension is the on-disk extension. inline_base64 carries the bytes themselves when they are small enough to ship inline (saving a separate download); it is absent for large files, which the client fetches from load/file. dynamic is True for interceptor-generated leaves, whose value the server recomputes on every request — the client may cache one for offline use but must not enroll it in background revalidation.
  • missing: no such leaf exists. No payload.

version is the single content identity: a static file's is the base64 blake2b of its bytes, an interceptor leaf's is the base64 blake2b of its generated bytes. The client treats it as opaque — it only compares versions and uses one as a cache key, never computing its own.

Source code in capturegraph-lib/capturegraph/api_models/responses.py
class LeafState(BaseModel):
    """The server's verdict for one leaf, the unit of the resolve and save APIs.

    A leaf has exactly one ``status``:

    - ``unchanged``: the client's ``known_version`` is still current. No payload;
      the client serves its cached copy.
    - ``present``: the leaf exists with content identified by ``version`` (an
      opaque token; equal versions mean identical bytes). ``extension`` is the
      on-disk extension. ``inline_base64`` carries the bytes themselves when they
      are small enough to ship inline (saving a separate download); it is absent
      for large files, which the client fetches from ``load/file``. ``dynamic``
      is True for interceptor-generated leaves, whose value the server recomputes
      on every request — the client may cache one for offline use but must not
      enroll it in background revalidation.
    - ``missing``: no such leaf exists. No payload.

    ``version`` is the single content identity: a static file's is the base64
    blake2b of its bytes, an interceptor leaf's is the base64 blake2b of its
    generated bytes. The client treats it as opaque — it only compares versions
    and uses one as a cache key, never computing its own.
    """

    status: Literal["unchanged", "present", "missing"]
    version: str | None = None
    extension: str | None = None
    dynamic: bool = False
    inline_base64: str | None = None

    @model_validator(mode="after")
    def _check_payload(self) -> "LeafState":
        """Validate that a leaf's payload fields match its ``status``.

        A present leaf carries a version and extension; the others carry no
        payload. Pins the single-source-of-truth invariant so a malformed
        verdict fails loud on both producer and consumer.
        """
        if self.status == "present":
            if self.version is None or self.extension is None:
                raise ValueError("a 'present' leaf must carry version and extension")
        else:
            if (
                self.version is not None
                or self.extension is not None
                or self.inline_base64 is not None
                or self.dynamic
            ):
                raise ValueError(f"a '{self.status}' leaf must carry no payload")
        return self

    @staticmethod
    def unchanged() -> "LeafState":
        """The client's cached version is still current."""
        return LeafState(status="unchanged")

    @staticmethod
    def missing() -> "LeafState":
        """No leaf exists at this path."""
        return LeafState(status="missing")

    @staticmethod
    def present(
        version: str,
        extension: str,
        inline_base64: str | None = None,
        dynamic: bool = False,
    ) -> "LeafState":
        """Build a present leaf with the given content version and extension.

        ``inline_base64`` carries the bytes themselves when small enough to
        ship inline; ``dynamic`` marks an interceptor-generated leaf.
        """
        return LeafState(
            status="present",
            version=version,
            extension=extension,
            inline_base64=inline_base64,
            dynamic=dynamic,
        )

missing() staticmethod #

No leaf exists at this path.

Source code in capturegraph-lib/capturegraph/api_models/responses.py
@staticmethod
def missing() -> "LeafState":
    """No leaf exists at this path."""
    return LeafState(status="missing")

present(version, extension, inline_base64=None, dynamic=False) staticmethod #

Build a present leaf with the given content version and extension.

inline_base64 carries the bytes themselves when small enough to ship inline; dynamic marks an interceptor-generated leaf.

Source code in capturegraph-lib/capturegraph/api_models/responses.py
@staticmethod
def present(
    version: str,
    extension: str,
    inline_base64: str | None = None,
    dynamic: bool = False,
) -> "LeafState":
    """Build a present leaf with the given content version and extension.

    ``inline_base64`` carries the bytes themselves when small enough to
    ship inline; ``dynamic`` marks an interceptor-generated leaf.
    """
    return LeafState(
        status="present",
        version=version,
        extension=extension,
        inline_base64=inline_base64,
        dynamic=dynamic,
    )

unchanged() staticmethod #

The client's cached version is still current.

Source code in capturegraph-lib/capturegraph/api_models/responses.py
@staticmethod
def unchanged() -> "LeafState":
    """The client's cached version is still current."""
    return LeafState(status="unchanged")

TargetsResponse #

Bases: BaseModel

Response listing available targets on the server.

Source code in capturegraph-lib/capturegraph/api_models/responses.py
class TargetsResponse(BaseModel):
    """Response listing available targets on the server."""

    targets: list[str]