Documentation
¶
Index ¶
- Constants
- func Logger(ctx context.Context) logger.Logger
- func NewControlLibrary(manager *Manager, registrar Registrar, scriptRegistrar ScriptLibraryRegistrar, ...) *object.Library
- func NormalizeLibraryName(name string) string
- func RegisterClientLibrary(registrar Registrar, client *Client)
- func RegisterLibraries(registrar Registrar, manager *Manager)
- func Release(obj object.Object) error
- func ReleaseWithContext(ctx context.Context, obj object.Object) error
- type Callback
- type CallbackRef
- type ClassSchema
- type Client
- func (c *Client) Batch(ctx context.Context, requests []batchRequest) ([]json.RawMessage, error)
- func (c *Client) Call(ctx context.Context, method string, params any, out any) error
- func (c *Client) CallFunction(ctx context.Context, name string, args []Value, kwargs map[string]Value) (Value, error)
- func (c *Client) CallFunctionWithCallbacks(ctx context.Context, name string, args []Value, kwargs map[string]Value, ...) (Value, error)
- func (c *Client) CallMethod(ctx context.Context, objectID, method string, args []Value, ...) (Value, error)
- func (c *Client) CallMethodWithCallbacks(ctx context.Context, objectID, method string, args []Value, ...) (Value, error)
- func (c *Client) Close() error
- func (c *Client) DestroyObject(ctx context.Context, objectID string) error
- func (c *Client) HandshakeDone() bool
- func (c *Client) Health() error
- func (c *Client) Metadata() Metadata
- func (c *Client) NewObject(ctx context.Context, class string, args []Value, kwargs map[string]Value) (*RemoteRef, error)
- func (c *Client) NewObjectWithCallbacks(ctx context.Context, class string, args []Value, kwargs map[string]Value, ...) (*RemoteRef, error)
- func (c *Client) Path() string
- func (c *Client) SetName(name string)
- type ConstantSchema
- type FunctionSchema
- type LibraryUnregistrar
- type Manager
- func (m *Manager) AddDir(dir string)
- func (m *Manager) Close() error
- func (m *Manager) Get(name string) (*Client, bool)
- func (m *Manager) Health() map[string]error
- func (m *Manager) List() []Metadata
- func (m *Manager) Load(ctx context.Context) error
- func (m *Manager) LoadPath(ctx context.Context, name, path string, scriptling bool, args []string) (*Client, error)
- func (m *Manager) LoadURL(ctx context.Context, name, rawURL string, scriptling, insecureSkipTLS bool, ...) (*Client, error)
- func (m *Manager) NewScope(opts ...ScopeOption) *Manager
- func (m *Manager) SetCrashHandler(handler func(name string, err error))
- func (m *Manager) SetLogger(log logger.Logger)
- func (m *Manager) Unload(name string) error
- func (m *Manager) Warnings() []string
- type Metadata
- type PropertySchema
- type RPCError
- type Registrar
- type RemoteRef
- type Schema
- type ScopeOption
- type ScriptLibraryRegistrar
- type Server
- func (s *Server) Constant(name string, value any) *Server
- func (s *Server) ObjectCount() int
- func (s *Server) RegisterBuiltin(name string, fn object.BuiltinFunction) *Server
- func (s *Server) RegisterBuiltinClass(name string, class *object.Class) *Server
- func (s *Server) RegisterClass(builder *object.ClassBuilder) *Server
- func (s *Server) RegisterFunc(name string, builder *object.FunctionBuilder) *Server
- func (s *Server) RegisterScriptClass(name string, source string) *Server
- func (s *Server) RegisterScriptFunc(name string, source string) *Server
- func (s *Server) Run() error
- func (s *Server) RunIO(input io.Reader, output io.Writer) error
- func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (s *Server) Wrapper(name string, source string) *Server
- type TransportMode
- type Value
Constants ¶
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." )
const ControlLibraryName = "scriptling.plugin"
const DefaultHandshakeTimeout = 15 * time.Second
DefaultHandshakeTimeout caps how long handshake() will wait for the plugin protocol handshake to complete. It bounds detection of broken or unresponsive plugins while still tolerating slow subprocess startup under load (cold container starts, network filesystems, parallel test execution). The caller's context deadline always takes precedence if it is shorter.
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
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 ¶
NormalizeLibraryName returns name in the host-owned plugin namespace.
func RegisterClientLibrary ¶ added in v0.15.0
RegisterClientLibrary registers the proxy library for a single already-handshaked client. Useful when you have a Client obtained via LoadClientFromIO or similar and want to expose it without a full Manager.
func RegisterLibraries ¶
Types ¶
type Callback ¶
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
}
Client is a connection to a loaded plugin. Over stdio it is a bidirectional JSON-RPC peer (built on jsonrpc.Peer) — outbound calls to the plugin and inbound host callbacks (callback.call, host.log) share one stream. Over HTTP it is a unidirectional JSON-RPC client (built on jsonrpc.HTTPTransport); callbacks are not available over HTTP.
func LoadClient ¶ added in v0.12.1
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 LoadClientFromIO ¶ added in v0.15.0
func LoadClientFromIO(ctx context.Context, in io.ReadCloser, out io.WriteCloser) (*Client, error)
LoadClientFromIO connects to a plugin server over an existing bidirectional stream and performs the plugin protocol handshake. Use this when the server is already running and accessible via in-process pipes (e.g. tests, embedded servers). The caller is responsible for closing in/out when done.
func SpawnClient ¶ added in v0.12.1
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
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
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 (*Client) CallFunctionWithCallbacks ¶
func (*Client) CallMethod ¶
func (*Client) CallMethodWithCallbacks ¶
func (*Client) Close ¶
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 (*Client) HandshakeDone ¶ added in v0.12.1
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) NewObjectWithCallbacks ¶
type ConstantSchema ¶
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 Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
func NewManager ¶
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 ¶
AddDir adds a directory whose executable files should be loaded as plugins.
func (*Manager) Close ¶
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 ¶
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 ¶
Health returns loaded plugins whose process or stdio transport is unhealthy.
func (*Manager) List ¶
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) 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 ¶
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
SetLogger installs the host logger used for log records emitted by plugins.
func (*Manager) Unload ¶ added in v0.12.1
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).
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 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 Server ¶
type Server struct {
// contains filtered or unexported fields
}
func (*Server) ObjectCount ¶ added in v0.15.0
ObjectCount returns the number of live server-side objects. Useful in tests.
func (*Server) RegisterBuiltin ¶ added in v0.15.0
func (s *Server) RegisterBuiltin(name string, fn object.BuiltinFunction) *Server
RegisterBuiltin registers a raw builtin function directly, bypassing the FunctionBuilder reflection layer. Use this when the function is already an object.BuiltinFunction (e.g. a closure that wraps a script handler).
func (*Server) RegisterBuiltinClass ¶ added in v0.15.0
RegisterBuiltinClass registers a scriptling *object.Class directly, bypassing the ClassBuilder. Use this when the class was loaded from a scriptling module (e.g. via Scriptling.Eval) rather than built from Go code.
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 (*Server) RegisterScriptFunc ¶
func (*Server) RunIO ¶
RunIO serves the plugin protocol over a bidirectional stream (stdio). The jsonrpc.Peer handles framing, batch dispatch, notification detection and response correlation in both directions; dispatch runs in the peer's server.
RunIO blocks until the input reaches EOF — normally because the host closed the child's stdin after plugin.shutdown (which destroys objects and returns a response). The server need not force-exit on shutdown: the response is written before the host closes stdin, so there is no flush-before-exit race. Object finalizers run on plugin.shutdown and again on EOF (idempotent).
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. Framing (POST handling, batches, notifications, error responses, 204 on no-response) is provided by jsonrpc.Server.ServeHTTP; this server only supplies the plugin methods.
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.