Documentation
¶
Index ¶
- Constants
- Variables
- func CleanArchiveEntryPath(entry string) (string, error)
- func ExtractArchive(reader io.Reader, destRoot string) error
- func MoveInstalledDir(extractedDir string, targetDir string, replaceExisting bool) error
- func NewPackageNotFoundError(slug string) error
- func PathWithinRoot(root string, child string) (string, error)
- func VersionIsNewer(current string, latest string) bool
- type Detail
- type DownloadOpts
- type DownloadResult
- type Downloader
- type InstallResult
- type Installer
- type InstallerOption
- func WithInstallerMaxArchiveSize(size int64) InstallerOption
- func WithInstallerMaxDecompressedSize(size int64) InstallerOption
- func WithInstallerMaxFileCount(count int) InstallerOption
- func WithInstallerNow(now func() time.Time) InstallerOption
- func WithInstallerTempDirMaxAge(age time.Duration) InstallerOption
- type Listing
- type MultiRegistry
- func (m *MultiRegistry) CheckUpdate(ctx context.Context, slug string, currentVersion string) (*UpdateInfo, error)
- func (m *MultiRegistry) Close() error
- func (m *MultiRegistry) Download(ctx context.Context, slug string, opts DownloadOpts) (*DownloadResult, error)
- func (m *MultiRegistry) Info(ctx context.Context, slug string) (*Detail, error)
- func (m *MultiRegistry) Search(ctx context.Context, query string, opts SearchOpts) ([]Listing, error)
- func (m *MultiRegistry) SourceNamed(name string) Source
- type PackageNotFoundError
- type PackageType
- type SearchOpts
- type Source
- type SourceCaps
- type UpdateInfo
Constants ¶
const ( // DefaultMaxDecompressedSize caps the total extracted archive size. DefaultMaxDecompressedSize int64 = 500 * 1024 * 1024 // DefaultMaxFileCount caps the number of archive entries processed. DefaultMaxFileCount = 10000 )
const ( // DefaultMaxArchiveSize caps the compressed archive stream before extraction. DefaultMaxArchiveSize int64 = 50 * 1024 * 1024 )
Variables ¶
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") )
var ( // ErrArchiveTooLargeCompressed reports a compressed archive stream above its configured limit. ErrArchiveTooLargeCompressed = errors.New("registry: archive exceeds max compressed size") )
var ErrNotSupported = errors.New("registry: operation not supported")
ErrNotSupported reports that a registry source does not implement an operation.
var ErrPackageNotFound = errors.New("registry: package not found")
ErrPackageNotFound reports that no registry source resolved a package slug.
Functions ¶
func CleanArchiveEntryPath ¶
CleanArchiveEntryPath normalizes one archive entry and rejects absolute or escaping paths.
func ExtractArchive ¶
ExtractArchive extracts a tar.gz archive into destRoot using the default decompressed-size and file-count limits.
func MoveInstalledDir ¶
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 ¶
NewPackageNotFoundError returns the canonical package-not-found error.
func PathWithinRoot ¶
PathWithinRoot resolves a child path and guarantees it stays under root.
func VersionIsNewer ¶
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 ¶
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 ¶
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.