pluginrt

package
v0.1.1246 Latest Latest
Warning

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

Go to latest
Published: Oct 15, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package pluginrt runs magpie's built-in plugins: the parts of magpie not everyone needs (Lxxyx on X: "功能太多了"), each one a package under plugins/ that registers a Manifest. The runtime applies the ones the user has on (plugins.yml, see config.go) in the order their Requires and Provides make, and disposes of what each registered, in reverse, when it is turned off. One that fails or panics is FAILED and the rest run on.

The runtime is core: it never imports a plugin, and a plugin never imports another (TestPluginsImportOnlyCore). Plugins reach each other only through the services they Provide.

Index

Constants

View Source
const (
	PresetEssentials = "essentials"
	PresetAll        = "all"
)

Presets a plugins.yml can name.

View Source
const API = "1.0"

API is the host API plugins are written against. A plugin's Manifest.API is a caret range ("^1", "^1.2"): the same major, and a minor no newer than this one's. One that doesn't match isn't applied.

Variables

View Source
var Core = []string{"settings", "providers", "gateway", "window"}

Core are the services magpie itself provides, which a plugin may Require without another plugin providing them.

Functions

func Compatible

func Compatible(want string) bool

Compatible is whether a plugin written for the caret range want runs on this host's API. An empty range is "^1".

func KeepFresh added in v0.1.1243

func KeepFresh(ctx context.Context, every time.Duration, also ...string)

KeepFresh refreshes the process's runtime (Refresh) as it starts and whenever plugins.yml, or one of also (a file an InUse reads), changes, until ctx ends. The process serving the gateway runs it: the window or `magpie plugin builtin` in another process may turn a plugin on or off, and what a plugin registers with the gateway (an observer) follows without a restart.

func Path

func Path() string

Path is plugins.yml, in magpie's folder.

func Register

func Register(m Manifest)

Register adds a built-in plugin; plugins call it from init. Two with one id is a programming error.

func Set

func Set(id string, on bool) error

Set turns plugin id on or off as the user's own choice, keeping the rest of plugins.yml as it was. A plugins.yml that doesn't parse is not written over: the user fixes it, or removes it.

func SetConfig added in v0.1.1228

func SetConfig(id string, config map[string]any) error

SetConfig sets plugin id's settings in config as the user's own, keeping its others and the rest of plugins.yml as they were. Only what its settings' schema allows is taken: a key it doesn't have, or a value of the wrong kind or out of range, is refused and nothing is written.

func SetPreset

func SetPreset(preset string) error

SetPreset changes the preset, keeping the user's own rows.

func Settle

func Settle(newInstall bool) (bool, error)

Settle writes a first plugins.yml when there is none: the Essentials preset on a new install, All on a magpie that ran here before. It says whether it wrote one. A plugins.yml there, or one that can't be looked at, is left as it is.

Types

type Composed

type Composed struct {
	ID      string            `json:"id" yaml:"id"`
	Enabled bool              `json:"enabled" yaml:"enabled"`
	Source  Source            `json:"source" yaml:"source"`
	Chosen  bool              `json:"chosen" yaml:"chosen"` // plugins.yml's say, before what is in use
	InUse   int               `json:"inUse" yaml:"inUse,omitempty"`
	Config  map[string]any    `json:"config,omitempty" yaml:"config,omitempty"`
	Sources map[string]Source `json:"configSources,omitempty" yaml:"configSources,omitempty"`
}

Composed is one plugin as plugins.yml and its use make it.

func Compose

func Compose(ms []Manifest, f File) []Composed

Compose layers f over the defaults for each manifest, in ms' order.

func Refresh

func Refresh() ([]Composed, error)

Refresh composes plugins.yml with the registered plugins and brings the process's runtime to it, made on the first call. A plugins.yml that can't be read leaves the runtime as it was (every plugin on, before the first good read) and is returned.

type Ctx

type Ctx struct {
	ID     string
	Config map[string]any // the composed config, read only
	// contains filtered or unexported fields
}

Ctx is what a plugin's Apply is handed. Everything registered through it is undone when the plugin is turned off, in reverse.

func (*Ctx) Contribute

func (c *Ctx) Contribute(slot, key string)

Contribute puts a part in the window while the plugin is active.

func (*Ctx) OnDispose

func (c *Ctx) OnDispose(f func())

OnDispose runs f when the plugin is turned off or magpie stops.

func (*Ctx) Provide

func (c *Ctx) Provide(name string, v any)

Provide gives a service other plugins may Require. It is withdrawn when the plugin is turned off.

func (*Ctx) Service

func (c *Ctx) Service(name string) any

Service is a service a plugin Provides, or nil.

type File

type File struct {
	Preset  string `yaml:"preset,omitempty"`
	Plugins []Row  `yaml:"plugins,omitempty"`
}

File is plugins.yml as written.

func Load

func Load() (File, bool, error)

Load reads plugins.yml. A file not there is (File{}, false, nil): the default layers alone. One that can't be read or doesn't parse is an error, never an empty file.

type Manifest

type Manifest struct {
	ID  string
	API string // the host API range it is written for, "^1"
	// Requires are services it can't run without; Provides those it gives
	// others ("router.strategy/groups")
	Requires, Provides []string
	// Essential plugins are on in the Essentials preset a new install
	// starts with; every built-in is on for a magpie that ran before
	Essential bool
	// Name and Sub say what it is, in English; the window translates them
	Name, Sub string
	// One and Many say what of it is in use, of 1 or of {n}
	One, Many string
	// InUse counts what the user has made with it (groups, warm-ups, items
	// given to agents). One in use stays on whatever plugins.yml says: off,
	// its things would go on working with nowhere to see or change them.
	// An error counts as in use: unknown is never unused.
	InUse func() (int, error)
	// Apply registers the plugin's parts; nil is a plugin of parts only
	// (Contribute) that does nothing else
	Apply func(*Ctx) error
	// Parts are the window's parts it is, by slot: "nav.page" sessions,
	// "settings.section" otel, "part" groups (whatever the page marks
	// data-feature="<id>"). The runtime contributes them before Apply.
	Parts []Part
	// Defaults is its config before plugins.yml's preset and rows
	Defaults map[string]any
	// Settings is a struct of its settings, their defaults its values
	// (schema.go): the window draws their form, and SetConfig takes only
	// what it allows. Register adds them to Defaults.
	Settings any
	// Client are its files in the window, under assets/plugins/<id>/: its
	// scripts register its parts with the window's kernel (kernel.js), its
	// i18n.js says its words in each language, and a .css is its styles.
	// TestBuiltinClientsLoaded holds the page to loading each.
	Client []string
	// contains filtered or unexported fields
}

Manifest is a built-in plugin: what it is, what it needs and gives, and Apply, which registers its parts through the Ctx.

func Registered

func Registered() []Manifest

Registered are the built-in plugins, by id.

func (Manifest) Schema added in v0.1.1228

func (m Manifest) Schema() *Schema

Schema is the schema of the plugin's Settings, nil for one with none.

type Part

type Part struct{ Slot, Key string }

Part is one thing a plugin puts in the window: a Slot and a Key in it.

type Property added in v0.1.1228

type Property struct {
	Type        string   `json:"type"` // boolean, integer, number, string
	Title       string   `json:"title"`
	Description string   `json:"description,omitempty"`
	Enum        []any    `json:"enum,omitempty"`
	Minimum     *float64 `json:"minimum,omitempty"`
	Maximum     *float64 `json:"maximum,omitempty"`
	Default     any      `json:"default"`
}

Property is one setting.

type Row

type Row struct {
	ID      string         `yaml:"id"`
	Enabled *bool          `yaml:"enabled,omitempty"`
	Config  map[string]any `yaml:"config,omitempty"`
}

Row is the user's own say about one plugin: only what they set.

type Runtime

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

Runtime applies the plugins that are on and keeps what each registered.

func New

func New(ms []Manifest) *Runtime

New is a runtime of the registered plugins, none applied yet.

func Running

func Running() *Runtime

Running is the process's runtime, nil before the first Refresh.

func (*Runtime) Active

func (rt *Runtime) Active(id string) bool

Active is whether the plugin id is applied now.

func (*Runtime) Reconcile

func (rt *Runtime) Reconcile(on map[string]bool, config map[string]map[string]any)

Reconcile brings the runtime to on: each plugin wanted and not active is applied, once what it requires is provided; each active one no longer wanted is disposed, with whatever requires a service it provided. on says, by id, whether a plugin is wanted; config is each one's composed config.

func (*Runtime) Statuses

func (rt *Runtime) Statuses() []Status

Statuses are the plugins as they run now, by id.

func (*Runtime) Stop

func (rt *Runtime) Stop()

Stop disposes of every active plugin, newest first.

type Schema added in v0.1.1228

type Schema struct {
	Type       string               `json:"type"` // "object"
	Properties map[string]*Property `json:"properties"`
	Order      []string             `json:"x-order"`
}

Schema is a plugin's settings as JSON Schema says an object: the window draws a form from it. Order is the fields' order, as JSON keeps no order of an object's keys.

func SchemaOf added in v0.1.1228

func SchemaOf(v any) (*Schema, map[string]any)

SchemaOf is the schema of the settings struct v, and its defaults. A field of a kind a form can't draw, or a tag that doesn't parse, is a programming error.

func (*Schema) Validate added in v0.1.1228

func (s *Schema) Validate(config map[string]any) (map[string]any, error)

Validate gives config as the schema's types, or says the first key or value it doesn't allow.

type Source

type Source string

Source says which layer a composed value came from.

const (
	FromDefault Source = "default"
	FromPreset  Source = "preset"
	FromUser    Source = "user"
	FromInUse   Source = "in use"
)

type State

type State string

State is where a plugin is in its life.

const (
	Off      State = "off"      // turned off in plugins.yml
	Pending  State = "pending"  // on, waiting for a service no active plugin provides
	Active   State = "active"   // applied
	Failed   State = "failed"   // Apply returned an error or panicked
	Disposed State = "disposed" // turned off at run time, its parts gone
)

type Status

type Status struct {
	ID    string `json:"id"`
	State State  `json:"state"`
	// Why says what kept it from Active: the service it waits for, the
	// error it failed with, the API it wants
	Why   string `json:"why,omitempty"`
	Parts []Part `json:"parts,omitempty"`
}

Status is one plugin as it runs now.

Jump to

Keyboard shortcuts

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