extensions

package
v0.11.0-beta.1 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: Apache-2.0, MIT Imports: 13 Imported by: 0

Documentation

Overview

Package extensions is a thin, read-mostly unification layer over the four existing extension surfaces in Overkill: skills, plugins, hooks, and MCP servers (Phase 1.5 #5).

Goals (kept deliberately small):

  • One inventory view: List() returns everything the user can toggle, regardless of which backend owns it.
  • One Enable/Disable verb: callers don't need to know which Registry to talk to.
  • One status check: Get(id) returns Enabled/Source/Description.

Non-goals:

  • Hot-reload coordination (each backend owns that — skills already has fsnotify, plugins doesn't, MCP relies on server lifecycle).
  • Cross-backend dependencies / capability negotiation.
  • Replacing the four backends — we ADAPT them, not rewrite them.

New backends register themselves with the Manager. The Manager has no knowledge of skill/plugin/hook semantics — it just delegates.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = fmt.Errorf("extensions: not found")

ErrNotFound is returned by Manager.Get / Enable / Disable when no backend recognises the requested ID.

View Source
var ErrUnsupported = fmt.Errorf("extensions: operation unsupported by this backend")

ErrUnsupported is returned by Backend.Enable/Disable when the operation isn't supported for that backend (e.g. a directory-based extension that can't be toggled at runtime).

Functions

This section is empty.

Types

type Backend

type Backend interface {
	// Kind reports which extension family this backend serves.
	Kind() Kind
	// List returns the full inventory the backend knows about. Order
	// is unimportant — Manager sorts the merged view.
	List() ([]Extension, error)
	// Get returns a single extension by ID, or ErrNotFound. Added
	// in B138 to let Manager.Get do O(1) lookups instead of O(n)
	// scanning List() results.
	Get(id string) (*Extension, error)
	// Enable / Disable toggle an extension by its (Kind, ID). When the
	// backend doesn't support runtime toggling (e.g. hooks are
	// directory-based), it returns ErrUnsupported. Callers surface
	// that to the user instead of pretending the operation succeeded.
	Enable(id string) error
	Disable(id string) error
}

Backend is implemented by each of the four extension systems. Empty results mean no entries were discovered; inactive and unsupported entries are explicit.

type Extension

type Extension struct {
	Kind              Kind   `json:"kind"`
	ID                string `json:"id"`          // unique within Kind
	Name              string `json:"name"`        // display name
	Description       string `json:"description"` // one-liner
	Source            string `json:"source"`      // bundled | user | remote | mcp-server-name
	Enabled           bool   `json:"enabled"`
	CanToggle         bool   `json:"can_toggle"`
	ToggleScope       string `json:"toggle_scope,omitempty"`
	UnsupportedReason string `json:"unsupported_reason,omitempty"`
	// Metadata is free-form per-backend payload (version, tags, etc.).
	// Consumers (UI) shouldn't depend on specific keys — backend-specific
	// detail belongs in dedicated dialogs.
	Metadata map[string]string `json:"metadata,omitempty"`
}

Extension is the unified record returned by Manager.List/Get. Backends translate their native representations into this struct.

type HookFilesBackend

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

HookFilesBackend lists scripts accepted by the production trusted-file loader. These files apply to newly constructed sessions, not a hidden dummy runtime.

func (*HookFilesBackend) Disable

func (b *HookFilesBackend) Disable(id string) error

func (*HookFilesBackend) Enable

func (b *HookFilesBackend) Enable(id string) error

func (*HookFilesBackend) Get

func (b *HookFilesBackend) Get(id string) (*Extension, error)

func (*HookFilesBackend) Kind

func (*HookFilesBackend) Kind() Kind

func (*HookFilesBackend) List

func (b *HookFilesBackend) List() ([]Extension, error)

type HooksBackend

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

HooksBackend retains disabled file-hook closures so enable restores the same trusted loader's execution checks. Built-in policy hooks remain owner-managed.

func NewHooksBackend

func NewHooksBackend(reg *hooks.Registry) *HooksBackend

func (*HooksBackend) Disable

func (b *HooksBackend) Disable(id string) error

func (*HooksBackend) Enable

func (b *HooksBackend) Enable(id string) error

func (*HooksBackend) Get

func (b *HooksBackend) Get(id string) (*Extension, error)

func (*HooksBackend) Kind

func (*HooksBackend) Kind() Kind

func (*HooksBackend) List

func (b *HooksBackend) List() ([]Extension, error)

type Kind

type Kind string

Kind identifies which underlying system owns an extension.

const (
	KindSkill  Kind = "skill"
	KindPlugin Kind = "plugin"
	KindHook   Kind = "hook"
	KindMCP    Kind = "mcp"
)

type MCPBackend

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

MCPBackend exposes configured servers plus supervised connection state, never command arguments or environment secrets. Per-server runtime toggles do not exist in mcp.Manager and are explicitly unsupported here.

func NewMCPBackend

func NewMCPBackend(cfg config.MCPConfig, manager *mcp.Manager) *MCPBackend

func (*MCPBackend) Disable

func (b *MCPBackend) Disable(id string) error

func (*MCPBackend) Enable

func (b *MCPBackend) Enable(id string) error

func (*MCPBackend) Get

func (b *MCPBackend) Get(id string) (*Extension, error)

func (*MCPBackend) Kind

func (*MCPBackend) Kind() Kind

func (*MCPBackend) List

func (b *MCPBackend) List() ([]Extension, error)

type Manager

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

Manager fans out to the registered backends. Safe for concurrent use.

func NewConfiguredManager

func NewConfiguredManager(reg *skills.Registry, cfg *config.Config, home string) *Manager

NewConfiguredManager inventories configuration without starting executables. A session replaces the hook adapter with its actual executing registry; an API server replaces MCP with its supervised live manager.

func NewManager

func NewManager() *Manager

NewManager returns an empty manager. Register backends with AddBackend before use.

func (*Manager) AddBackend

func (m *Manager) AddBackend(b Backend)

AddBackend installs a backend. Calling twice with the same Kind REPLACES the prior backend (last-wins) so the wire-up can be reordered without panic. Nil backend is a no-op.

func (*Manager) Clone

func (m *Manager) Clone() *Manager

Clone shares backend owners while allowing a session to replace its hooks inventory without changing another session's executing registry.

func (*Manager) Disable

func (m *Manager) Disable(kind Kind, id string) error

Disable mirrors Enable.

func (*Manager) Enable

func (m *Manager) Enable(kind Kind, id string) error

Enable delegates to the backend for the given kind. ErrUnsupported bubbles up so the UI can surface "this kind of extension can't be toggled at runtime" instead of silently no-op'ing.

func (*Manager) Get

func (m *Manager) Get(kind Kind, id string) (*Extension, error)

Get returns the matching extension by (Kind, ID). When the backend implements Backend.Get, we use the O(1) lookup. Otherwise we fall back to scanning List() results (B138).

func (*Manager) List

func (m *Manager) List() ([]Extension, error)

List returns every extension across every registered backend, sorted by (Kind, ID) for stable output. Backend errors surface as a single joined error — partial results are still returned so the UI can show what we DID find.

type PluginsBackend

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

PluginsBackend uses real discovery. The application has not connected a plugin process manager, so discovery is never presented as active execution.

func (*PluginsBackend) Disable

func (b *PluginsBackend) Disable(id string) error

func (*PluginsBackend) Enable

func (b *PluginsBackend) Enable(id string) error

func (*PluginsBackend) Get

func (b *PluginsBackend) Get(id string) (*Extension, error)

func (*PluginsBackend) Kind

func (*PluginsBackend) Kind() Kind

func (*PluginsBackend) List

func (b *PluginsBackend) List() ([]Extension, error)

type SkillsBackend

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

SkillsBackend adapts the existing skills.Registry to the Backend interface. The registry already supports Enable/Disable/List so this is a thin translation layer.

func NewSkillsBackend

func NewSkillsBackend(r *skills.Registry) *SkillsBackend

NewSkillsBackend wires a registry. Nil registry returns nil — the caller is expected to skip AddBackend when skills aren't configured.

func (*SkillsBackend) Disable

func (b *SkillsBackend) Disable(id string) error

func (*SkillsBackend) Enable

func (b *SkillsBackend) Enable(id string) error

func (*SkillsBackend) Get

func (b *SkillsBackend) Get(id string) (*Extension, error)

func (*SkillsBackend) Kind

func (b *SkillsBackend) Kind() Kind

func (*SkillsBackend) List

func (b *SkillsBackend) List() ([]Extension, error)

Jump to

Keyboard shortcuts

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