Help us shape the future of Go! Take the 2026 Go Developer Survey

plugins

package
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package plugins loads Agent Plugins 1.0.0 packages (https://agent-plugins.org).

This file validates a plugin's root plugin.json manifest under the spec's containment rules. It never makes a network request: the $schema value is only compared against the one recognized URL.

Index

Constants

View Source
const DefaultKeep = 5

DefaultKeep is how many versions besides current Prune keeps.

View Source
const (
	HostUserNamespace = "extism:host/user" // tinyagent-provided host functions

)

Namespaces a guest module may import from.

View Source
const MCPFile = "mcp.json"

MCPFile is the MCP configuration's name at the plugin root.

View Source
const MCPSchemaV1 = "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json"

MCPSchemaV1 is the only mcp.json $schema value recognized.

View Source
const ManifestFile = "plugin.json"

ManifestFile is the manifest's name at the plugin root.

View Source
const MaxManifestBytes = 1 << 20

MaxManifestBytes caps how much of plugin.json is read.

View Source
const MaxWasmBytes = 64 << 20

MaxWasmBytes caps a module file's size.

View Source
const SchemaV1 = "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"

SchemaV1 is the only plugin.json $schema value recognized.

View Source
const SkillsDir = "skills"

SkillsDir is the plugin's skills directory, relative to the plugin root.

Variables

View Source
var ErrPermission = errors.New("permission denied")

ErrPermission marks a load or swap refused because the module asks for more than it may have.

View Source
var ErrTainted = errors.New("session is tainted: module loads and swaps are refused")

ErrTainted marks a load or swap refused because the session is locked down after untrusted content entered it.

View Source
var ErrTampered = errors.New("stored module does not match its hash")

ErrTampered is returned when a stored version doesn't match its hash.

View Source
var ErrUnsupported = errors.New("unsupported transport")

ErrUnsupported marks an mcp.json entry whose transport tinyagent can't run (streamable-http and sse: remote MCP is not supported).

Functions

func DataDir

func DataDir(name string) (string, error)

DataDir returns the plugin's persistent PLUGIN_DATA directory, under the user config directory. It is not created here.

func ResolveInside

func ResolveInside(root, path string) (string, error)

ResolveInside resolves path through symlinks and returns it only when the result stays within the already-resolved root.

func Server

func Server(e MCPEntry, auth config.PluginServer, root, data string) (config.MCPServer, error)

Server maps an authorized stdio entry to a tinyagent MCP server definition: placeholders expanded once in args, env values and cwd, the mcp.json env set, and PLUGIN_ROOT and PLUGIN_DATA set last.

func Servers

func Servers(l Loaded, cfg config.Plugin, create bool) ([]config.MCPServer, error)

Servers returns the MCP server definitions the config authorizes for loaded plugin l (cfg is its config entry). A rejected plugin with authorized servers, a listed server that is missing, invalid or unsupported, or a disabled mcp.json is an error naming plugin and server. With create set, the plugin's PLUGIN_DATA directory is created (0700).

func SkillSources

func SkillSources(ls []Loaded) []skills.PluginSource

SkillSources returns the skills/ directory of each loaded plugin, in order.

func StoreName

func StoreName(plugin, module string) string

StoreName is the store's directory name for a plugin's module.

func ValidName

func ValidName(s string) bool

ValidName reports whether s is a valid plugin name: 1-64 characters of [a-z0-9.-], starting and ending with [a-z0-9], with no "--" or "..".

Types

type DataKind

type DataKind string

DataKind is a data module's schema.

const (
	DataPrompt DataKind = "prompt" // markdown, YAML front-matter with name
	DataSkill  DataKind = "skill"  // markdown, YAML front-matter with description
	DataRetry  DataKind = "retry"  // JSON or TOML retry policy
)

type DataModule

type DataModule struct {
	Name  string
	Kind  DataKind
	Taint Tainter // optional; switches are refused once tainted
	// Store, when set, keeps every version under StoreName; Set adds the
	// version and makes it current.
	Store     *ModuleStore
	StoreName string
	// contains filtered or unexported fields
}

DataModule holds the active version of one data module.

func (*DataModule) Current

func (d *DataModule) Current() *DataVersion

Current returns the active version, or nil before the first Set.

func (*DataModule) LoadStored

func (d *DataModule) LoadStored() (*DataVersion, error)

LoadStored makes the store's verified current version active.

func (*DataModule) Rollback

func (d *DataModule) Rollback() error

Rollback switches back to the previous version.

func (*DataModule) RollbackTo

func (d *DataModule) RollbackTo(hash string) (*DataVersion, error)

RollbackTo moves the store's current pointer to an older hash and activates it; refused after taint.

func (*DataModule) Set

func (d *DataModule) Set(content []byte) (*DataVersion, error)

Set validates content against the module's schema and atomically makes it the active version. Invalid content leaves the old version active.

func (*DataModule) SetFile

func (d *DataModule) SetFile(path string) (*DataVersion, error)

SetFile is Set with content read from path.

type DataVersion

type DataVersion struct {
	Hash    string // sha256 of Content, hex
	Content []byte
	Meta    map[string]any // front-matter fields (prompt, skill)
	Retry   *RetryPolicy   // retry only
}

DataVersion is one validated version of a data module.

type HostFunc

type HostFunc = extism.HostFunction

HostFunc is a host function the caller may offer to modules.

type Loaded

type Loaded struct {
	Path     string // the configured path
	Manifest *Manifest
	Err      error
	MCP      *MCPConfig // nil when the plugin was rejected
}

Loaded is one configured plugin after loading. Err is set when the plugin was rejected; Manifest is set otherwise.

func Load

func Load(cfg []config.Plugin) ([]Loaded, error)

Load loads every configured plugin in order. A rejected plugin is reported in its Loaded.Err and doesn't stop the others; two plugins with the same manifest name are an error, since names identify plugins.

func (Loaded) MCPWarnings

func (l Loaded) MCPWarnings(auth []config.PluginServer) []string

MCPWarnings returns the non-fatal mcp.json problems of a loaded plugin: MCP disabled by a bad top-level file, and invalid or unsupported entries that aren't authorized (authorized ones fail in Servers instead).

type MCPConfig

type MCPConfig struct {
	Present bool
	Err     error
	Digest  string // SHA-256 of the file, hex
	Entries []MCPEntry
}

MCPConfig is a plugin's parsed mcp.json. Present is false when the file doesn't exist; Err set means MCP is disabled for the plugin.

func LoadMCP

func LoadMCP(root string) *MCPConfig

LoadMCP reads <root>/mcp.json, where root is the resolved plugin root.

func (*MCPConfig) Entry

func (c *MCPConfig) Entry(name string) (MCPEntry, bool)

Entry returns the named entry.

type MCPEntry

type MCPEntry struct {
	Name    string
	Type    string
	Err     error
	Command string
	Args    []string
	Env     map[string]string
	Cwd     string
}

MCPEntry is one mcp.json server. Err is set when the entry can't be started; the other fields hold the stdio definition before expansion.

type Manifest

type Manifest struct {
	Name        string
	Version     string
	Description string
	Root        string // filesystem-resolved plugin root
	Extensions  map[string]json.RawMessage
	Warnings    []string // non-fatal problems (unknown fields, bad extensions)
}

Manifest is a validated plugin.json.

func LoadManifest

func LoadManifest(dir string) (*Manifest, error)

LoadManifest reads and validates <dir>/plugin.json. An error means the plugin is rejected; non-fatal problems are returned in Manifest.Warnings.

type ModuleStore

type ModuleStore struct {
	Dir string
	Now func() time.Time // for tests; time.Now when nil
}

ModuleStore is rooted at Dir.

func (*ModuleStore) Current

func (s *ModuleStore) Current(module string) (string, error)

Current returns the active hash ("" with no error before any version).

func (*ModuleStore) Meta

func (s *ModuleStore) Meta(module, hash string) (*VersionMeta, error)

Meta reads a version's sidecar.

func (*ModuleStore) Modules

func (s *ModuleStore) Modules() ([]string, error)

Modules lists the stored modules.

func (*ModuleStore) Pinned

func (s *ModuleStore) Pinned(module string) (Permissions, error)

Pinned returns the first load's permissions.

func (*ModuleStore) Prune

func (s *ModuleStore) Prune(module string, keep int) ([]string, error)

Prune removes all but current and the keep newest other versions of a module, returning the removed hashes. Current is never removed.

func (*ModuleStore) Put

func (s *ModuleStore) Put(module, ext string, data []byte, perms Permissions, manifest json.RawMessage) (string, error)

Put adds a version (a no-op when the hash is already stored) and returns its hash. It does not move current. The first Put of a module pins its permissions.

func (*ModuleStore) Read

func (s *ModuleStore) Read(module, hash string) ([]byte, *VersionMeta, error)

Read returns a version's content after verifying its hash.

func (*ModuleStore) ReadCurrent

func (s *ModuleStore) ReadCurrent(module string) ([]byte, *VersionMeta, error)

ReadCurrent reads and verifies the active version.

func (*ModuleStore) Rollback

func (s *ModuleStore) Rollback(module, hash string, taint Tainter) error

Rollback points current at an older stored version. It is refused after taint, when the version's permissions are wider than the first load's, or when the version fails its hash check.

func (*ModuleStore) SetCurrent

func (s *ModuleStore) SetCurrent(module, hash string) error

SetCurrent atomically points current at a stored hash.

func (*ModuleStore) SetSource

func (s *ModuleStore) SetSource(module, hash string) error

SetSource records the hash last ingested from the plugin's own file.

func (*ModuleStore) Source

func (s *ModuleStore) Source(module string) string

Source returns the hash last ingested from the plugin's own file.

func (*ModuleStore) Versions

func (s *ModuleStore) Versions(module string) ([]VersionMeta, error)

Versions lists a module's versions, newest first.

type Permissions

type Permissions struct {
	HostFuncs []string          `json:"host_functions,omitempty"`
	Paths     map[string]string `json:"allowed_paths,omitempty"` // host path -> guest path
	Hosts     []string          `json:"allowed_hosts,omitempty"`
	WASI      bool              `json:"wasi,omitempty"`
}

Permissions is a set of capabilities: what a caller grants, or what a module declares it needs.

type RetryPolicy

type RetryPolicy struct {
	MaxAttempts int `json:"max_attempts" toml:"max_attempts"`
	BackoffMS   int `json:"backoff_ms" toml:"backoff_ms"`
}

RetryPolicy is the retry data module's schema.

type SessionGrant

type SessionGrant struct {
	Root      string
	Hosts     []string
	CheckPath func(abs string, write bool) error // nil allows
	Taint     Tainter
}

SessionGrant derives what the session lets a module have. It is never wider than the session: tinyagent offers no host functions to modules; paths must resolve inside Root and pass CheckPath (the session's file_access rules); hosts must be listed in Hosts (the session's sandbox_allowed_domains, exact entries only); WASI itself grants no filesystem or network.

type Tainter

type Tainter interface{ Tainted() bool }

Tainter reports whether the session is locked down (lockdown.State).

type VersionMeta

type VersionMeta struct {
	Hash        string          `json:"hash"`
	Ext         string          `json:"ext"`
	Manifest    json.RawMessage `json:"manifest,omitempty"`
	Permissions Permissions     `json:"permissions"`
	LoadedAt    time.Time       `json:"loaded_at"`
}

VersionMeta is a version's sidecar.

type WasmDecl

type WasmDecl struct {
	Name     string       `json:"name"`
	File     string       `json:"file"`
	Version  string       `json:"version"`
	Exports  []WasmExport `json:"exports"`
	Requires Permissions  `json:"requires"`
	// Source and Lang declare a module built from Go source by TinyAgent
	// (with TinyGo, an external, separately downloaded tool) instead of a
	// prebuilt file: Source is a directory relative to the plugin root and
	// Lang must be "go".
	Source string `json:"source,omitempty"`
	Lang   string `json:"lang,omitempty"`
}

WasmDecl is one module declared in plugin.json.

func WasmDecls

func WasmDecls(m *Manifest) ([]WasmDecl, error)

WasmDecls returns the modules a plugin declares.

type WasmExport

type WasmExport struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

WasmExport is one exported function offered as a tool.

type WasmHost

type WasmHost struct {
	Grant Permissions
	Funcs []HostFunc // host functions the caller can offer, by name
	Taint Tainter    // optional
	// contains filtered or unexported fields
}

WasmHost loads code modules for one caller.

func (*WasmHost) Load

func (h *WasmHost) Load(ctx context.Context, m WasmManifest, wasm []byte) (*WasmModule, error)

Load loads the first version of a module. The manifest must be a subset of the host's grant; it is then pinned as the module's permission list.

func (*WasmHost) LoadFile

func (h *WasmHost) LoadFile(ctx context.Context, m WasmManifest, path string) (*WasmModule, error)

LoadFile is Load with the module read from path.

type WasmManifest

type WasmManifest struct {
	Name     string      `json:"name"`
	Version  string      `json:"version"`
	Requires Permissions `json:"requires"`
}

WasmManifest describes one code module version.

type WasmModule

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

WasmModule is a swappable code module. Calls go to the current instance; Swap replaces it without blocking calls already running.

func (*WasmModule) Call

func (m *WasmModule) Call(ctx context.Context, fn string, input []byte) (uint32, []byte, error)

Call runs an exported function on the current instance. A swap during the call doesn't affect it: it finishes on the instance it started on.

func (*WasmModule) Close

func (m *WasmModule) Close()

Close tears down the current instance and unregisters the module.

func (*WasmModule) Permissions

func (m *WasmModule) Permissions() Permissions

Permissions returns the permission list pinned at first load.

func (*WasmModule) Swap

func (m *WasmModule) Swap(ctx context.Context, nm WasmManifest, wasm []byte) error

Swap replaces the module with a new version. The new manifest must stay within the permissions pinned at first load (and the host's grant). The new instance is built first; on any error the old one keeps running. The old instance closes once its in-flight calls finish.

func (*WasmModule) SwapFile

func (m *WasmModule) SwapFile(ctx context.Context, nm WasmManifest, path string) error

SwapFile is Swap with the module read from path.

func (*WasmModule) Version

func (m *WasmModule) Version() string

Version is the current version string.

type WasmPool

type WasmPool struct {
	// Store, when set, keeps every version of each module; activation loads
	// the version its current pointer names (verifying its hash), and a
	// changed plugin file is added as a new version and made current.
	Store *ModuleStore
	// Compile builds Go source files into a module (TinyGo under the OS
	// sandbox). Modules declared with source need it and Store.
	Compile func(ctx context.Context, files map[string][]byte) ([]byte, error)
	// contains filtered or unexported fields
}

WasmPool keeps loaded code modules for the process. Activate loads them on first use and, on a later activation (an ACP session, a reload), swaps in a module whose file changed, under the permission list pinned at first load.

func (*WasmPool) Activate

func (p *WasmPool) Activate(ctx context.Context, ls []Loaded, cfg []config.Plugin, g SessionGrant, w io.Writer) *WasmTools

Activate loads or refreshes every authorized module of the loaded plugins. A module that is refused is reported on w and skipped; the others still load.

func (*WasmPool) Close

func (p *WasmPool) Close()

Close tears down every module.

type WasmTools

type WasmTools struct {
	Specs []model.ToolSpec
	// contains filtered or unexported fields
}

WasmTools is the tool catalog of one activation.

func (*WasmTools) Call

func (t *WasmTools) Call(ctx context.Context, name, raw string) (out string, isErr, ok bool)

Call runs a tool. The arguments JSON is the module's input and its output is the result; a non-zero return code marks an error. ok is false for names that aren't WebAssembly tools.

Jump to

Keyboard shortcuts

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