agentos-vfs-core 0.2.7

Generic async virtual filesystem primitives
Documentation
# agentOS `.aospkg` package container schema.
#
# Container layout: 16-byte header (magic 0x89 'A' 'O' 'S', u16 LE format
# version, u16 reserved, u32 LE manifest len, u32 LE index len) followed by
# chunk1 PackageManifest, chunk2 MountIndex, and chunk3 — the uncompressed
# mount tar served byte-for-byte by `TarFileSystem`.
#
# Chunk payloads are encoded as [u16 little-endian schema version] ++ BARE(root).
# PACKAGE_MANIFEST_VERSION is currently 1. Never edit a published v1.bare in
# place; copy to vN.bare and add converters. Enum members are append-only
# because their order is the on-wire ordinal.
#
# Tooling: two packers encode this schema and must stay behaviorally identical —
# Rust `crates/vfs/src/package_format/pack.rs` (bench/test fixtures, canonical)
# and TS `packages/agentos-toolchain/src/aospkg.ts` (what `agentos-toolchain
# build`/`pack` emit as `dist/package.aospkg`). The TS codecs are generated from
# this file via `pnpm --dir packages/build-tools build:package-format`; the Rust
# types are generated by `crates/vfs/build.rs` (vbare-compiler). The
# `cross_validates_toolchain_built_aospkg` test in
# `crates/vfs/tests/package_format.rs` catches codec drift.
#
# The chunk1 manifest is the ONLY runtime manifest. `agentos-package.json` is a
# toolchain-input file: packers parse it to build chunk1 and strip it from the
# mount tar, so packed packages never ship it and nothing materializes JSON
# back into the guest.

# File type of a mount tar entry, as served by `TarFileSystem` stat/readdir.
type TarEntryKind enum {
  FILE
  DIRECTORY
  SYMLINK
}

# One entry of the chunk3 mount tar. The index lets the VFS project the tar
# without parsing tar headers at VM startup: file contents are served as
# byte ranges directly out of chunk3.
type TarEntry struct {
  # Absolute path within the package mount root, e.g. `/bin/jq`.
  path: str
  kind: TarEntryKind
  # Byte offset of the file's content within chunk3 (the mount tar). 0 for
  # directories and symlinks, which carry no content.
  offset: u64
  # Content length in bytes. 0 for directories and symlinks.
  size: u64
  # POSIX mode bits (file-type bits + permissions) reported by guest stat.
  mode: u32
  # Ownership reported by guest stat. Deterministic packs emit 0.
  uid: u32
  gid: u32
  # Modification time (Unix seconds) reported by guest stat. Deterministic
  # packs emit 0.
  mtime: i64
  # Symlink target; present only when kind is SYMLINK.
  linkTarget: optional<str>
}

# Agent metadata for packages that ship an ACP agent adapter. Present only on
# agent packages; absence means the package is not launchable as an agent.
type AgentBlock struct {
  # Name of a command in `PackageManifest.commands` that speaks ACP on
  # stdio. The sidecar launches this to run the agent.
  acpEntrypoint: str
  # True when the package ships a prebuilt SDK snapshot bundle for fast agent
  # cold starts; see `PackageManifest.snapshotBundlePath`.
  snapshot: bool
  # Environment variables applied to the agent process at launch.
  env: map<str><str>
  # Extra argv appended when launching the ACP entrypoint.
  launchArgs: list<str>
}

# One command projected into the shared `$PATH` dir. All packages link their
# commands into a single `/opt/agentos/bin`, each as its own virtual symlink
# leaf, so the sidecar can enumerate and remap commands from chunk1 alone —
# no tar scan or JSON parse at VM startup.
type CommandTarget struct {
  # The name the guest types: the link name under `/opt/agentos/bin`.
  command: str
  # Path of the executable it resolves to, relative to the package mount root
  # at `/opt/agentos/pkgs/<name>/<version>/`, e.g. `bin/jq` or
  # `dist/claude-cli.mjs`. Not necessarily under `bin/`: npm-style
  # `package.json` `bin` maps may point anywhere in the package.
  entry: str
}

# One man page shipped by the package, derived at pack time from mount paths
# of the form `/share/man/<section>/<page>`. The projection serves manpage
# aliases from this list without scanning the mount index at startup.
type ManPage struct {
  # Man section directory name, e.g. `man1`.
  section: str
  # Page file name within the section, e.g. `jq.1`.
  page: str
}

# One directory the package projects to a fixed location in the guest
# filesystem, for software that expects its runtime files at a well-known
# absolute path (e.g. vim's `$VIMRUNTIME` tree).
type ProvidesFile struct {
  # Source directory relative to the package mount root, e.g. `share/vim/vim92`.
  # Must be a directory; non-directory sources are skipped with a warning.
  source: str
  # Absolute guest path where the source is mounted read-only, e.g.
  # `/usr/local/share/vim/vim92`.
  target: str
}

# Guest environment and filesystem projections the package provides.
type ProvidesBlock struct {
  # Guest-wide environment defaults applied at VM creation. First package
  # wins: a key already set (by the VM config or an earlier package) is not
  # overridden.
  env: map<str><str>
  # Package directories mounted at fixed guest paths; see `ProvidesFile`.
  files: list<ProvidesFile>
}

# Chunk1: the runtime package manifest. Read alone (without chunk2/chunk3) on
# the VM cold-start path to project `/opt/agentos` — keep it small and free of
# anything that would require reading the mount payload.
type PackageManifest struct {
  # Runtime package name, e.g. `jq` or `claude-code`. Names the projection dir
  # `/opt/agentos/pkgs/<name>/` and, for agent packages, the agent id.
  name: str
  # Package version, e.g. `0.3.0-rc.2`. Names the version dir under the
  # package projection dir.
  version: str
  # Agent metadata; present only for packages launchable as ACP agents.
  agent: optional<AgentBlock>
  # Env/file projections; present only when the package provides them.
  provides: optional<ProvidesBlock>
  # Commands linked under `/opt/agentos/bin`. Derived at pack time from the
  # `package.json` `bin` map when present, else from `/bin/*` in the mount.
  commands: list<CommandTarget>
  # Man pages shipped under `/share/man/` in the mount.
  manPages: list<ManPage>
  # Mount-root-relative path to the prebuilt SDK snapshot bundle
  # (`/dist/sdk-snapshot.js`), set iff `agent.snapshot` is true and the file
  # exists in the mount. Null otherwise.
  snapshotBundlePath: optional<str>
}

# Chunk2: index of the chunk3 mount tar, entries sorted by path.
type MountIndex struct {
  tarEntries: list<TarEntry>
}