bundle

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: May 11, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package bundle implements the canonical nSelf paid plugin bundle catalog plus install/remove orchestration with license validation, version pinning, and atomic rollback on failure (S2.T03/T04/T22).

Bundle membership is authoritative here — the source of truth that mirrors .claude/docs/sport/F06-BUNDLE-INVENTORY.md. The cmd layer must consume this package; do NOT duplicate the bundle map elsewhere.

installer.go — S2.T03: `nself bundle install <bundle>` orchestrator.

Atomicity: pre-flight ALL licenses, then install each constituent plugin sequentially via plugin.Install. On any per-plugin failure we roll back by removing every plugin we successfully installed in THIS invocation. Plugins that were already on disk before the call are left untouched.

--dry-run prints the planned actions and exits without filesystem changes. --force bypasses the license pre-flight (logged as "license-bypass"). --strict fails if any plugin in the bundle is missing from the registry

(default: skip missing with a warning).

--channel selects stable/beta/canary for version resolution (T22).

remover.go — S2.T04: `nself bundle remove <bundle>` orchestrator.

Walks the bundle's plugin list and removes each one via plugin.Remove. By default plugin data volumes are dropped; --keep-data preserves them. --dry-run prints the planned actions without touching the filesystem.

Removal proceeds in REVERSE plugin order so that a plugin earlier in the list (often a dependency of later plugins, e.g. ai before claw) is removed last. plugin.Remove's reverse-dependency check is bypassed via force=true because the operator has explicitly asked to tear down the whole bundle.

version_resolver.go — S2.T22: resolve bundle slugs + release channels into concrete plugin version pins. Reads plugins-pro/registry.json via the existing internal/plugin registry fetcher so the same fallback + cache chain (primary URL → GitHub raw → stale cache) applies.

Index

Constants

This section is empty.

Variables

View Source
var DisplayOrder = []string{
	"nclaw", "nchat", "nfamily", "ntv", "clawde", "nsentry", "ntask", "nself-plus",
}

DisplayOrder is the canonical print order for bundle listings.

Functions

func Names

func Names() []string

Names returns every known bundle slug sorted alphabetically. Useful for error messages and shell completion.

func ResolveVersion

func ResolveVersion(ctx context.Context, pluginName string, channel Channel) (string, error)

ResolveVersion returns the version pin for a single plugin under the given channel. Exposed for callers that need to pin one plugin (e.g. compat-check, install --version<latest-channel>).

func UnknownBundleError

func UnknownBundleError(slug string) error

UnknownBundleError formats a friendly error when a slug does not match a known bundle. Includes the sorted list of valid names as a hint.

Types

type Bundle

type Bundle struct {
	Name        string   // Display name (with ɳ glyph)
	Slug        string   // CLI-arg lowercase identifier
	Price       string   // Human-readable price string
	Description string   // Optional one-line description
	Plugins     []string // Plugin slugs in the bundle (nil for meta-bundle)
}

Bundle describes a canonical nSelf plugin bundle.

func All

func All() []Bundle

All returns every Bundle in canonical display order.

func Get

func Get(slug string) (Bundle, bool)

Get returns the Bundle for the given slug. The slug is case-insensitive and trimmed. Returns ok=false when the slug is unknown; callers can call Names() to render a useful error hint.

func (Bundle) IsInstallable

func (b Bundle) IsInstallable() bool

IsInstallable reports whether the bundle can be installed via `nself bundle install`. Meta-bundles (nself-plus) and free bundles (ntask) are not installable as a unit — operators install their constituent plugins directly via `nself plugin install`.

type Channel

type Channel string

Channel is a release-channel identifier (stable/beta/canary). Channels filter candidate registry entries by their PublishStatus before version selection:

stable → status in {"", "stable"}
beta   → status in {"", "stable", "beta"}
canary → all installable statuses (adds "experimental")

"deprecated" and "eol" entries are never resolved by this function regardless of channel — those install paths require explicit --allow-eol acknowledgment through plugin.CheckEOLBlock, not silent bundle install.

const (
	ChannelStable Channel = "stable"
	ChannelBeta   Channel = "beta"
	ChannelCanary Channel = "canary"
)

type InstallOpts

type InstallOpts struct {
	DryRun  bool
	Force   bool
	Strict  bool
	Channel Channel

	// Out is the stream to print human-facing progress messages.
	// nil → os.Stderr.
	Out io.Writer

	// PluginDir overrides the default plugin install location. Empty → use
	// the same resolution as cmd/commands/plugin.resolvePluginDir.
	PluginDir string

	// Config overrides the loaded project config. Optional — when nil the
	// caller-loaded cfg is used by Install via cfg arg.
	Config *config.Config
	// contains filtered or unexported fields
}

InstallOpts captures the user-controllable knobs for bundle install.

type InstallResult

type InstallResult struct {
	Bundle        string
	Channel       Channel
	Planned       []string // plugins planned for install (post channel + strict filter)
	Skipped       []string // plugins skipped because missing from registry (non-strict)
	Installed     []string // plugins successfully installed in this call
	RolledBack    []string // plugins removed during rollback after a failure
	LicenseBypass bool     // true when --force was used
	DryRun        bool
}

InstallResult captures the outcome of a bundle install for callers that need to surface details (e.g. CR/QA harness, audit logger).

func Install

func Install(ctx context.Context, bundleSlug string, opts InstallOpts) (*InstallResult, error)

Install runs the bundle install flow. The returned InstallResult is populated even on error so callers (and tests) can inspect partial state.

type RemoveOpts

type RemoveOpts struct {
	DryRun   bool
	KeepData bool

	// Out is the stream for human-facing progress; nil → os.Stderr.
	Out io.Writer

	// PluginDir overrides the default plugin location.
	PluginDir string

	// Config overrides the loaded project config.
	Config *config.Config
	// contains filtered or unexported fields
}

RemoveOpts captures the user-controllable knobs for bundle remove.

type RemoveResult

type RemoveResult struct {
	Bundle       string
	Planned      []string // plugins planned for removal (post not-installed filter)
	NotInstalled []string
	Removed      []string
	Failed       []string
	DryRun       bool
	KeepData     bool
}

RemoveResult captures the outcome of a bundle remove call.

func Remove

func Remove(ctx context.Context, bundleSlug string, opts RemoveOpts) (*RemoveResult, error)

Remove tears down every plugin in the bundle. Plugins not currently installed are reported under NotInstalled and skipped. Per-plugin removal failures are collected in Failed and surfaced as the returned error, but removal continues for the remaining plugins rather than aborting on first failure — partial cleanup is more useful than a hung-bundle state.

type VersionPins

type VersionPins map[string]string

VersionPins maps plugin slug → concrete semver version string for every installable plugin in a bundle, after channel filtering.

func ResolveBundleVersions

func ResolveBundleVersions(ctx context.Context, bundleSlug string, channel Channel) (VersionPins, error)

ResolveBundleVersions returns the resolved version pins for every plugin in the given bundle, using the highest registry version that satisfies the channel filter. Returns an error for unknown bundle slugs or non-installable bundles (nself-plus, ntask).

Network behavior: delegates to plugin.FetchRegistry which respects the registry cache + fallback chain. A registry fetch failure with no stale cache returns an error; callers should respect that.

Jump to

Keyboard shortcuts

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