plugin

package
v0.12.3 Latest Latest
Warning

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

Go to latest
Published: Jun 24, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// ProtocolVersion is the JSON-RPC plugin protocol version supported by this host.
	ProtocolVersion = "1.0"
	// NamespacePrefix is the host-owned namespace for discovered plugin libraries.
	NamespacePrefix = "plugin."
)
View Source
const ControlLibraryName = "scriptling.plugin"
View Source
const DefaultReleaseTimeout = 2 * time.Second

DefaultReleaseTimeout is used by Release and GC finalizers when no caller context is available. Use ReleaseWithContext for request-scoped cleanup.

Variables

This section is empty.

Functions

func Logger added in v0.11.0

func Logger(ctx context.Context) logger.Logger

Logger returns a call-scoped proxy to the manager's host logger. It uses ctx to find the active plugin call runtime, so plugin code should request it from functions, constructors, methods, or property accessors and should not store it globally. If ctx is not attached to an active plugin call, Logger returns a no-op logger.

func NewControlLibrary

func NewControlLibrary(manager *Manager, registrar Registrar, scriptRegistrar ScriptLibraryRegistrar, unregistrar LibraryUnregistrar) *object.Library

func NormalizeLibraryName

func NormalizeLibraryName(name string) string

NormalizeLibraryName returns name in the host-owned plugin namespace.

func RegisterLibraries

func RegisterLibraries(registrar Registrar, manager *Manager)

func Release

func Release(obj object.Object) error

func ReleaseWithContext

func ReleaseWithContext(ctx context.Context, obj object.Object) error

ReleaseWithContext explicitly releases a remote plugin object using ctx.

Types

type Callback

type Callback interface {
	Call(ctx context.Context, args ...any) (Value, error)
}

Callback is a host callback passed into a plugin call. It is valid only until the outer plugin function, constructor, or method returns.

type CallbackRef

type CallbackRef struct {
	ID string `json:"id"`
}

CallbackRef identifies a callback valid during one outer plugin call.

type ClassSchema

type ClassSchema struct {
	Name        string           `json:"name"`
	Description string           `json:"description,omitempty"`
	Constructor FunctionSchema   `json:"constructor,omitempty"`
	Methods     []FunctionSchema `json:"methods,omitempty"`
	Properties  []PropertySchema `json:"properties,omitempty"`
	Source      string           `json:"source,omitempty"`
}

ClassSchema describes a plugin class and its methods.

type Client

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

func LoadClient added in v0.12.1

func LoadClient(ctx context.Context, path string, args []string) (*Client, error)

LoadClient spawns an executable and performs the plugin protocol handshake. The returned client has Metadata populated from the handshake result. args, if non-empty, are passed as command-line arguments to the executable.

func SpawnClient added in v0.12.1

func SpawnClient(ctx context.Context, path string, args []string) (*Client, error)

SpawnClient spawns an executable without performing the plugin handshake. The caller is responsible for any handshake exchange via Call. args, if non-empty, are passed as command-line arguments to the executable.

func (*Client) Batch added in v0.12.1

func (c *Client) Batch(ctx context.Context, requests []batchRequest) ([]json.RawMessage, error)

Batch sends multiple raw JSON-RPC requests in one batch frame and returns results in the same order as requests. Batch does not support host callbacks.

func (*Client) Call added in v0.12.1

func (c *Client) Call(ctx context.Context, method string, params any, out any) error

Call sends a raw JSON-RPC request to the executable and unmarshals the result into out (which may be nil to ignore the result). params may be any JSON-marshalable value (struct, map, slice, scalar). It is the low-level building block for non-plugin JSON-RPC peers; plugin callers should prefer CallFunction / NewObject / CallMethod which use the plugin method names.

func (*Client) CallFunction

func (c *Client) CallFunction(ctx context.Context, name string, args []Value, kwargs map[string]Value) (Value, error)

func (*Client) CallFunctionWithCallbacks

func (c *Client) CallFunctionWithCallbacks(ctx context.Context, name string, args []Value, kwargs map[string]Value, callbacks *callbackSet) (Value, error)

func (*Client) CallMethod

func (c *Client) CallMethod(ctx context.Context, objectID, method string, args []Value, kwargs map[string]Value) (Value, error)

func (*Client) CallMethodWithCallbacks

func (c *Client) CallMethodWithCallbacks(ctx context.Context, objectID, method string, args []Value, kwargs map[string]Value, callbacks *callbackSet) (Value, error)

func (*Client) Close

func (c *Client) Close() error

Close shuts down this plugin process. The plugin.shutdown notification is best-effort: peers that do not implement the plugin protocol (e.g. raw JSON-RPC executables loaded via LoadPath(scriptling=false)) will return a method-not-found error which is intentionally ignored. Handshaken Scriptling plugins still report shutdown RPC errors. Real failures — the process not exiting, or exiting with a non-zero status — are also reported.

func (*Client) DestroyObject

func (c *Client) DestroyObject(ctx context.Context, objectID string) error

func (*Client) HandshakeDone added in v0.12.1

func (c *Client) HandshakeDone() bool

HandshakeDone reports whether the plugin protocol handshake was completed. call_function uses this to route automatically: handshook clients use the typed plugin transport (function.call), non-handshook clients send the method name directly as a raw JSON-RPC request.

func (*Client) Health

func (c *Client) Health() error

Health reports whether this plugin process and stdio transport are healthy.

func (*Client) Metadata

func (c *Client) Metadata() Metadata

func (*Client) NewObject

func (c *Client) NewObject(ctx context.Context, class string, args []Value, kwargs map[string]Value) (*RemoteRef, error)

func (*Client) NewObjectWithCallbacks

func (c *Client) NewObjectWithCallbacks(ctx context.Context, class string, args []Value, kwargs map[string]Value, callbacks *callbackSet) (*RemoteRef, error)

func (*Client) Path added in v0.12.1

func (c *Client) Path() string

Path returns the filesystem path of the executable this client runs.

func (*Client) SetName added in v0.12.1

func (c *Client) SetName(name string)

SetName overrides the library name used to register this client. It is only meaningful before the client is added to a Manager and is intended for raw (non-plugin-handshake) clients whose name would otherwise be empty.

type ConstantSchema

type ConstantSchema struct {
	Name  string `json:"name"`
	Value Value  `json:"value"`
}

ConstantSchema describes a plugin constant.

type FunctionSchema

type FunctionSchema struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Source      string `json:"source,omitempty"`
}

FunctionSchema describes a plugin function or supplied wrapper source.

type LibraryUnregistrar added in v0.12.1

type LibraryUnregistrar interface {
	UnregisterLibrary(name string)
	UnregisterScriptLibrary(name string)
}

type Manager

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

func NewManager

func NewManager(log logger.Logger, crashHandler ...func(name string, err error)) *Manager

NewManager creates an empty plugin manager. If log is not nil, plugin log records emitted through Logger(ctx) are forwarded to it. If crashHandler is provided, it is called when a loaded plugin process exits unexpectedly.

func (*Manager) AddDir

func (m *Manager) AddDir(dir string)

AddDir adds a directory whose executable files should be loaded as plugins.

func (*Manager) Close

func (m *Manager) Close() error

Close shuts down all loaded plugin processes and clears the local client map. For scoped managers this fully releases all locally loaded plugins without touching the parent's plugins. Close is safe to call more than once.

func (*Manager) Get

func (m *Manager) Get(name string) (*Client, bool)

Get returns a loaded plugin client by short or fully-qualified library name. It checks the local map first; if not found and this is a scope with a parent, it falls back to the parent (and so on up the chain). Local always wins.

func (*Manager) Health

func (m *Manager) Health() map[string]error

Health returns loaded plugins whose process or stdio transport is unhealthy.

func (*Manager) List

func (m *Manager) List() []Metadata

List returns metadata for all loaded plugins sorted by library name. If this Manager is a scope, parent plugins are included in the result. A child scope cannot load a name that an ancestor already owns, so name collisions between local and parent are not possible; the seen-map guard is kept as a safety net in case of direct manager manipulation.

func (*Manager) Load

func (m *Manager) Load(ctx context.Context) error

Load eagerly starts all executable plugins in configured plugin directories.

func (*Manager) LoadPath added in v0.12.1

func (m *Manager) LoadPath(ctx context.Context, name, path string, scriptling bool, args []string) (*Client, error)

LoadPath starts a single executable, or connects to an http(s) JSON-RPC endpoint, and registers it under name. Executable identity is by absolute path; HTTP identity is by URL.

If scriptling is true, the plugin protocol handshake is performed and the client can be driven through CallFunction / CallMethod / call_function / call_method. If scriptling is false, the handshake is skipped and call_function sends the function name directly as the JSON-RPC method.

args, if non-empty, are passed as command-line arguments to the executable (e.g. ["--json-rpc", "./setup.py"] when spawning `scriptling` itself).

name is normalised into the plugin.* namespace (e.g. "widgets" becomes "plugin.widgets"); the returned client's Metadata().Name reflects that.

func (*Manager) LoadURL added in v0.12.1

func (m *Manager) LoadURL(ctx context.Context, name, rawURL string, scriptling, insecureSkipTLS bool, headers ...map[string]string) (*Client, error)

LoadURL connects to an HTTP(S) JSON-RPC endpoint and registers it under name. If scriptling is true, the plugin protocol handshake is performed. If insecureSkipTLS is true, HTTPS certificate verification is skipped. Optional headers are sent with every HTTP request.

func (*Manager) NewScope added in v0.12.3

func (m *Manager) NewScope(opts ...ScopeOption) *Manager

NewScope creates a child Manager that inherits the logger and shared HTTP transports from this Manager. Plugins loaded into the scope are invisible to the parent and to other scopes. When the scope is closed, only its locally loaded plugins are unloaded; the parent's plugins are unaffected.

Calling Get or List on the scope chains to the parent for fallback: the scope sees its own plugins first and parent plugins where there is no clash.

The scope does not inherit the parent's dirs or crash handler.

func (*Manager) SetCrashHandler

func (m *Manager) SetCrashHandler(handler func(name string, err error))

SetCrashHandler installs a callback for loaded plugin processes that exit unexpectedly. The handler is not called for normal manager shutdown.

func (*Manager) SetLogger added in v0.11.0

func (m *Manager) SetLogger(log logger.Logger)

SetLogger installs the host logger used for log records emitted by plugins.

func (*Manager) Unload added in v0.12.1

func (m *Manager) Unload(name string) error

Unload closes a client registered via LoadPath and removes it from the manager. It is intended for runtime-loaded executables; calling Unload on a plugin discovered via Load also works but the plugin will not be restarted. Returns an error if no client is registered under name (after normalisation).

func (*Manager) Warnings

func (m *Manager) Warnings() []string

Warnings returns non-fatal plugin load warnings collected by the manager.

type Metadata

type Metadata struct {
	Name         string   `json:"name"`
	Version      string   `json:"version"`
	Description  string   `json:"description"`
	Transport    string   `json:"transport,omitempty"`
	Capabilities []string `json:"capabilities,omitempty"`
	Schema       Schema   `json:"schema"`
}

Metadata describes a loaded plugin library.

type PropertySchema added in v0.11.0

type PropertySchema struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Settable    bool   `json:"settable,omitempty"`
}

PropertySchema describes a plugin class property.

type RPCError

type RPCError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func (*RPCError) Error

func (e *RPCError) Error() string

type Registrar

type Registrar interface {
	RegisterLibrary(*object.Library)
}

type RemoteRef

type RemoteRef struct {
	Library string `json:"library"`
	Class   string `json:"class"`
	ID      string `json:"id"`
}

RemoteRef identifies an object stored in a plugin process.

type Schema

type Schema struct {
	Functions []FunctionSchema `json:"functions"`
	Classes   []ClassSchema    `json:"classes"`
	Constants []ConstantSchema `json:"constants"`
}

Schema describes functions, classes, and constants exposed by a plugin.

type ScopeOption added in v0.12.3

type ScopeOption func(*Manager)

ScopeOption configures a scoped Manager created by NewScope.

func WithTransport added in v0.12.3

func WithTransport(mode TransportMode) ScopeOption

WithTransport sets the transport restriction for a scoped Manager. Use TransportHTTP to permit only HTTP(S) plugins, TransportStdio for only stdio executables, or TransportAll (default) to allow both.

type ScriptLibraryRegistrar

type ScriptLibraryRegistrar interface {
	RegisterScriptLibrary(name string, script string) error
}

type Server

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

func NewServer

func NewServer(name, version, description string) *Server

func (*Server) Constant

func (s *Server) Constant(name string, value any) *Server

func (*Server) RegisterClass

func (s *Server) RegisterClass(builder *object.ClassBuilder) *Server

func (*Server) RegisterFunc

func (s *Server) RegisterFunc(name string, builder *object.FunctionBuilder) *Server

func (*Server) RegisterScriptClass

func (s *Server) RegisterScriptClass(name string, source string) *Server

func (*Server) RegisterScriptFunc

func (s *Server) RegisterScriptFunc(name string, source string) *Server

func (*Server) Run

func (s *Server) Run() error

func (*Server) RunIO

func (s *Server) RunIO(input io.Reader, output io.Writer) error

func (*Server) ServeHTTP added in v0.12.1

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP serves the Scriptling plugin JSON-RPC protocol over HTTP. Mount it at a path such as /json-rpc and load it with plugin.Manager.LoadURL or scriptling.plugin.load(..., scriptling=True).

HTTP plugin transport supports normal plugin calls, object lifecycle, and batches. Host callbacks and plugin.Logger(ctx) require the bidirectional stdio transport and are not available over HTTP.

func (*Server) Wrapper

func (s *Server) Wrapper(name string, source string) *Server

type TransportMode added in v0.12.3

type TransportMode int

TransportMode restricts which plugin transport protocols a Manager or scope will accept when LoadPath or LoadURL is called.

const (
	// TransportAll permits both stdio/executable and HTTP(S) plugins (default).
	TransportAll TransportMode = iota
	// TransportHTTP permits only HTTP(S) endpoints; loading executables fails.
	TransportHTTP
	// TransportStdio permits only stdio executables; loading HTTP URLs fails.
	TransportStdio
)

type Value

type Value struct {
	Type     string           `json:"type"`
	Value    any              `json:"value,omitempty"`
	Items    []Value          `json:"items,omitempty"`
	Entries  map[string]Value `json:"entries,omitempty"`
	Remote   *RemoteRef       `json:"remote,omitempty"`
	Callback *CallbackRef     `json:"callback,omitempty"`
}

Value is the JSON-RPC transport representation of Scriptling values.

Jump to

Keyboard shortcuts

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