registry

package
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 29, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultMaxDecompressedSize caps the total extracted archive size.
	DefaultMaxDecompressedSize int64 = 500 * 1024 * 1024
	// DefaultMaxFileCount caps the number of archive entries processed.
	DefaultMaxFileCount = 10000
)
View Source
const (
	// DefaultMaxArchiveSize caps the compressed archive stream before extraction.
	DefaultMaxArchiveSize int64 = 50 * 1024 * 1024
)

Variables

View Source
var (
	// ErrArchiveDestinationRequired reports that ExtractArchive received a blank destination root.
	ErrArchiveDestinationRequired = errors.New("destination root is required")
	// ErrArchiveEntryPathRequired reports that an archive entry did not contain a usable path.
	ErrArchiveEntryPathRequired = errors.New("archive entry path is required")
	// ErrArchiveEntryMustBeRelative reports that an archive entry path was absolute.
	ErrArchiveEntryMustBeRelative = errors.New("archive entry must be relative")
	// ErrArchiveEntryEscapesRoot reports that an archive entry would escape the extraction root.
	ErrArchiveEntryEscapesRoot = errors.New("archive entry escapes the extraction root")
	// ErrUnsupportedArchiveEntryType reports that ExtractArchive encountered an unsupported tar entry type.
	ErrUnsupportedArchiveEntryType = errors.New("unsupported archive entry type")
	// ErrPathRootRequired reports that PathWithinRoot received a blank root path.
	ErrPathRootRequired = errors.New("root path is required")
	// ErrPathOutsideRoot reports that a path resolves outside the provided root.
	ErrPathOutsideRoot = errors.New("path must stay within the root directory")
	// ErrPathTraversesSymlink reports that extraction would traverse a symlink on disk.
	ErrPathTraversesSymlink = errors.New("path traverses symlink")
)
View Source
var (
	// ErrArchiveTooLargeCompressed reports a compressed archive stream above its configured limit.
	ErrArchiveTooLargeCompressed = errors.New("registry: archive exceeds max compressed size")
)
View Source
var ErrNotSupported = errors.New("registry: operation not supported")

ErrNotSupported reports that a registry source does not implement an operation.

View Source
var ErrPackageNotFound = errors.New("registry: package not found")

ErrPackageNotFound reports that no registry source resolved a package slug.

Functions

func CleanArchiveEntryPath

func CleanArchiveEntryPath(entry string) (string, error)

CleanArchiveEntryPath normalizes one archive entry and rejects absolute or escaping paths.

func ExtractArchive

func ExtractArchive(reader io.Reader, destRoot string) error

ExtractArchive extracts a tar.gz archive into destRoot using the default decompressed-size and file-count limits.

func MoveInstalledDir

func MoveInstalledDir(extractedDir string, targetDir string, replaceExisting bool) error

MoveInstalledDir moves an extracted package directory into its final location. If replaceExisting is true, the current target is atomically backed up and restored on failure.

func NewPackageNotFoundError

func NewPackageNotFoundError(slug string) error

NewPackageNotFoundError returns the canonical package-not-found error.

func PathWithinRoot

func PathWithinRoot(root string, child string) (string, error)

PathWithinRoot resolves a child path and guarantees it stays under root.

func VersionIsNewer

func VersionIsNewer(current string, latest string) bool

VersionIsNewer reports whether latest is a valid semantic version newer than current. Invalid version strings never produce an update signal.

Types

type Detail

type Detail struct {
	Listing
	Readme     string   `json:"readme"`
	MCPServers []string `json:"mcp_servers,omitempty"`
	Tags       []string `json:"tags"`
	License    string   `json:"license"`
	Repository string   `json:"repository"`
	Versions   []string `json:"versions"`
}

Detail is the full metadata for one registry package.

type DownloadOpts

type DownloadOpts struct {
	Version        string
	Asset          string
	MaxArchiveSize int64
}

DownloadOpts controls version and asset selection for a download.

type DownloadResult

type DownloadResult struct {
	Reader      io.ReadCloser
	Slug        string
	Version     string
	ContentSize int64
	Checksum    string
	ContentType string
}

DownloadResult is the structured download response returned by a source.

type Downloader

type Downloader interface {
	Download(ctx context.Context, slug string, opts DownloadOpts) (*DownloadResult, error)
}

Downloader is the minimal download contract required by the installer.

type InstallResult

type InstallResult struct {
	Slug        string `json:"slug"`
	Name        string `json:"name"`
	Version     string `json:"version"`
	Source      string `json:"source"`
	InstallPath string `json:"install_path"`
	Checksum    string `json:"checksum"`
}

InstallResult is the outcome of a registry-backed install.

type Installer

type Installer struct {
	// contains filtered or unexported fields
}

Installer handles download, extraction, validation, verification, and the final atomic move into place.

func NewInstaller

func NewInstaller(dl Downloader, opts ...InstallerOption) *Installer

NewInstaller constructs a new domain-agnostic install pipeline.

func (*Installer) Install

func (i *Installer) Install(
	ctx context.Context,
	slug string,
	dlOpts DownloadOpts,
	targetDir string,
) (_ *InstallResult, err error)

Install downloads, extracts, verifies, and atomically moves a package into its final target directory.

type InstallerOption

type InstallerOption func(*Installer)

InstallerOption customizes the installer pipeline.

func WithInstallerMaxArchiveSize

func WithInstallerMaxArchiveSize(size int64) InstallerOption

WithInstallerMaxArchiveSize overrides the compressed archive limit.

func WithInstallerMaxDecompressedSize

func WithInstallerMaxDecompressedSize(size int64) InstallerOption

WithInstallerMaxDecompressedSize overrides the extracted payload limit.

func WithInstallerMaxFileCount

func WithInstallerMaxFileCount(count int) InstallerOption

WithInstallerMaxFileCount overrides the extracted file-count limit.

func WithInstallerNow

func WithInstallerNow(now func() time.Time) InstallerOption

WithInstallerNow overrides the clock used for stale-temp cleanup.

func WithInstallerTempDirMaxAge

func WithInstallerTempDirMaxAge(age time.Duration) InstallerOption

WithInstallerTempDirMaxAge overrides the stale-temp cleanup threshold.

type Listing

type Listing struct {
	Slug        string      `json:"slug"`
	Name        string      `json:"name"`
	Description string      `json:"description"`
	Author      string      `json:"author"`
	Version     string      `json:"version"`
	Downloads   int         `json:"downloads"`
	Source      string      `json:"source"`
	Type        PackageType `json:"type"`
}

Listing is one registry search result.

type MultiRegistry

type MultiRegistry struct {
	// contains filtered or unexported fields
}

MultiRegistry aggregates multiple registry sources.

Sources are ordered from lowest priority to highest priority. Higher-priority sources override lower-priority search results when the same slug appears more than once.

func NewMultiRegistry

func NewMultiRegistry(logger *slog.Logger, sources ...Source) *MultiRegistry

NewMultiRegistry constructs a registry aggregator over one or more sources.

func (*MultiRegistry) CheckUpdate

func (m *MultiRegistry) CheckUpdate(ctx context.Context, slug string, currentVersion string) (*UpdateInfo, error)

CheckUpdate compares the local version against the latest version available from the resolved source.

func (*MultiRegistry) Close

func (m *MultiRegistry) Close() error

Close closes every underlying source and joins any close errors.

func (*MultiRegistry) Download

func (m *MultiRegistry) Download(ctx context.Context, slug string, opts DownloadOpts) (*DownloadResult, error)

Download delegates the archive fetch to the highest-priority source that can resolve the requested slug.

func (*MultiRegistry) Info

func (m *MultiRegistry) Info(ctx context.Context, slug string) (*Detail, error)

Info resolves package detail from the highest-priority source that has the requested slug.

func (*MultiRegistry) Search

func (m *MultiRegistry) Search(ctx context.Context, query string, opts SearchOpts) ([]Listing, error)

Search queries every searchable registry source concurrently and merges the results using source priority.

func (*MultiRegistry) SourceNamed

func (m *MultiRegistry) SourceNamed(name string) Source

SourceNamed returns the highest-priority source with the requested name.

type PackageNotFoundError

type PackageNotFoundError struct {
	Slug string
}

PackageNotFoundError carries the missing package slug.

func (PackageNotFoundError) Error

func (e PackageNotFoundError) Error() string

func (PackageNotFoundError) Is

func (e PackageNotFoundError) Is(target error) bool

type PackageType

type PackageType string

PackageType distinguishes skills from extensions in registry results.

const (
	PackageTypeSkill     PackageType = "skill"
	PackageTypeExtension PackageType = "extension"
	PackageTypeAll       PackageType = ""
)

type SearchOpts

type SearchOpts struct {
	Limit  int         `json:"limit"`
	Offset int         `json:"offset"`
	Type   PackageType `json:"type"`
}

SearchOpts controls search pagination and package filtering.

type Source

type Source interface {
	Name() string
	Capabilities() SourceCaps
	Search(ctx context.Context, query string, opts SearchOpts) ([]Listing, error)
	Info(ctx context.Context, slug string) (*Detail, error)
	Download(ctx context.Context, slug string, opts DownloadOpts) (*DownloadResult, error)
	Close() error
}

Source abstracts one registry backend.

type SourceCaps

type SourceCaps struct {
	Search bool
}

SourceCaps declares which operations one registry source supports.

type UpdateInfo

type UpdateInfo struct {
	Slug           string `json:"slug"`
	CurrentVersion string `json:"current_version"`
	LatestVersion  string `json:"latest_version"`
	HasUpdate      bool   `json:"has_update"`
	Source         string `json:"source"`
}

UpdateInfo is the result of a local-vs-remote update check.

Directories

Path Synopsis
Package clawhub implements the ClawHub registry adapter.
Package clawhub implements the ClawHub registry adapter.
Package github implements the GitHub Releases registry adapter.
Package github implements the GitHub Releases registry adapter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL