studio

package
v0.3.3 Latest Latest
Warning

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

Go to latest
Published: Nov 4, 2026 License: GPL-3.0 Imports: 33 Imported by: 0

Documentation

Overview

Package studio provides the plugin Studio replay runner (WS11c) and the Studio and extensibility MCP and agent tools (WS11h).

Package studio implements Ether's in-console plugin development environment (SPEC §3.1, WS11a, WS11b, WS11d): templates, project file storage, TypeScript compilation via esbuild, conformance and copy checks, sandboxed dev execution with shadow mode and undo journalling, live ViewSpec preview, inspector call history with plain-language validation hints, hot reload over /api/stream, and direct installation through the plugin host's permission sheet.

Index

Constants

View Source
const (
	DefaultReplayTimeout = 15 * time.Second
	MaxReplayTimeout     = 30 * time.Second

	DefaultRankingTraces = 1000
	MaxRankingTraces     = 5000
	MaxChangedPreview    = 200

	DefaultEventDays  = 7
	MaxEventDays      = 7
	DefaultEventLimit = 500
	MaxEventLimit     = 2000

	DefaultListPages = 2
	MaxListPages     = 5
	MaxListPreview   = 25

	DefaultChannelProbes = 5
	MaxChannelProbes     = 5
)

Replay bounds keep every replay background-safe with no request-path impact.

Variables

View Source
var ErrNotEditable = errors.New("studio: this plugin runs on another device; its code is not on this server")

ErrNotEditable reports a plugin whose code does not live on this server (a sidecar on another device).

View Source
var ErrProjectNotFound = errors.New("studio: project not found")

ErrProjectNotFound is returned when a Studio project ID does not exist.

Functions

func ProjectTools

func ProjectTools(s *Studio) []tools.Tool

ProjectTools use the same draft service as human editing. Drafts are sandboxed, so writes apply directly; nothing installs or touches viewers.

func RedactJSON

func RedactJSON(raw json.RawMessage) string

RedactJSON masks values under secret-looking keys before storing in the Studio inspector ring.

func RegisterTools

func RegisterTools(cat *tools.Catalogue, deps ToolDeps) error

RegisterTools registers the Studio and extensibility tools into cat.

func Tools

func Tools(deps ToolDeps) []tools.Tool

Tools returns the 8 Studio and extensibility tools (WS11h): registry_describe, viewspec_validate, viewspec_render, plugin_scaffold, plugin_check, plugin_replay, plugin_shadow_report, and plugin_install.

Types

type ChangedPick

type ChangedPick struct {
	HistoryID         int64  `json:"historyId"`
	TitleKey          string `json:"titleKey"`
	TitleName         string `json:"titleName"`
	Profile           string `json:"profile,omitempty"`
	BeforeReleaseID   string `json:"beforeReleaseId"`
	BeforeReleaseName string `json:"beforeReleaseName"`
	AfterReleaseID    string `json:"afterReleaseId"`
	AfterReleaseName  string `json:"afterReleaseName"`
	BeforePluginKey   int64  `json:"beforePluginKey"`
	AfterPluginKey    int64  `json:"afterPluginKey"`
}

ChangedPick records one title whose winning release changed when the plugin step or condition was active.

type ChannelReplayReport

type ChannelReplayReport struct {
	ChannelCount    int                 `json:"channelCount"`
	WithGuideCount  int                 `json:"withGuideCount"`
	GuideCoverage   float64             `json:"guideCoverage"`
	TotalPrograms   int                 `json:"totalPrograms"`
	ProbesAttempted int                 `json:"probesAttempted"`
	ProbesOK        int                 `json:"probesOk"`
	Probes          []StreamProbeResult `json:"probes"`
	TotalUnits      int64               `json:"totalUnits"`
}

ChannelReplayReport summarizes a Live TV channel source replay: channel count, guide coverage, and a sample probe of up to 5 stream inputs.

type CheckItem

type CheckItem struct {
	ID       string `json:"id"`
	Category string `json:"category"` // "manifest" | "copy" | "schema" | "compile" | "runtime" | "viewspec"
	Label    string `json:"label"`
	Status   string `json:"status"` // "pass" | "fail" | "warn"
	Message  string `json:"message,omitempty"`
	Fix      string `json:"fix,omitempty"`
}

CheckItem is one conformance check outcome from the kit / Studio check runner.

type CheckReport

type CheckReport struct {
	OK          bool              `json:"ok"`
	Checks      []CheckItem       `json:"checks"`
	Diagnostics []wasm.Diagnostic `json:"diagnostics"`
}

CheckReport is the complete result of checking a Studio project.

type CheckRequest

type CheckRequest struct {
	Manifest json.RawMessage   `json:"manifest"`
	Files    map[string]string `json:"files,omitempty"`
}

CheckRequest holds the manifest and files to validate in Studio.

type CompileResult

type CompileResult struct {
	OK            bool              `json:"ok"`
	Diagnostics   []wasm.Diagnostic `json:"diagnostics"`
	JSSize        int               `json:"jsSize,omitempty"`
	SourcemapSize int               `json:"sourcemapSize,omitempty"`
	// contains filtered or unexported fields
}

CompileResult holds the output and diagnostics from compiling a project.

type CreateProjectOptions

type CreateProjectOptions struct {
	Template   string `json:"template"`
	PluginID   string `json:"pluginId,omitempty"`
	Name       string `json:"name,omitempty"`
	Slot       string `json:"slot,omitempty"`
	StremioURL string `json:"stremioUrl,omitempty"`
}

CreateProjectOptions customizes a project scaffolded from a template.

type Deps

type Deps struct {
	Manager *plugins.Manager
	Engine  *wasm.Engine
	// Publish sends a live SSE event (such as "studio.reload") to the console.
	Publish func(ctx context.Context, typ string, data any) error
	Logger  *slog.Logger
	Now     func() time.Time
	// Installed runs after Studio or its agent installs a plugin, so the
	// app can switch on what it adds (a Live TV source for channels).
	Installed func(ctx context.Context, rec plugins.Record)
}

Deps are the explicit dependencies for the Studio service.

type DevInstance

type DevInstance struct {
	Manifest json.RawMessage   `json:"manifest"`
	Entry    string            `json:"entry,omitempty"`
	Files    map[string]string `json:"files,omitempty"`
	Settings map[string]any    `json:"settings,omitempty"`
	Secrets  map[string]string `json:"secrets,omitempty"`
	Grants   plugins.Grants    `json:"grants,omitempty"`
}

DevInstance is an unsaved or in-progress plugin from the Studio editor.

type EventReplayReport

type EventReplayReport struct {
	Days            int                    `json:"days"`
	EventsLoaded    int                    `json:"eventsLoaded"`
	EventsMatched   int                    `json:"eventsMatched"`
	EventsDelivered int                    `json:"eventsDelivered"`
	EventsAcked     int                    `json:"eventsAcked"`
	Batches         int                    `json:"batches"`
	Writes          []RecordedWrite        `json:"writes"`
	Notifications   []RecordedNotification `json:"notifications"`
	OutboundCalls   []RecordedOutbound     `json:"outboundCalls,omitempty"`
	Logs            []RecordedLog          `json:"logs,omitempty"`
	TotalUnits      int64                  `json:"totalUnits"`
}

EventReplayReport summarizes what a plugin would have done when fed recent normalized events from plugins_event_log in a dry-run context.

type ListItem

type ListItem struct {
	ID     string `json:"id"`
	IMDbID string `json:"imdbId,omitempty"`
	TMDBID int    `json:"tmdbId,omitempty"`
	Title  string `json:"title"`
	Type   string `json:"type,omitempty"`
	Year   int    `json:"year,omitempty"`
}

ListItem is one entry returned by a list source plugin's catalog route.

type ListReplayReport

type ListReplayReport struct {
	SourceKey       string         `json:"sourceKey,omitempty"`
	Catalog         string         `json:"catalog"`
	MediaType       string         `json:"mediaType"`
	PagesFetched    int            `json:"pagesFetched"`
	TotalItems      int            `json:"totalItems"`
	MatchedItems    int            `json:"matchedItems"`
	UnmatchedItems  int            `json:"unmatchedItems"`
	MatchRate       float64        `json:"matchRate"`
	Preview         []MatchedTitle `json:"preview"`
	UnmatchedSample []string       `json:"unmatchedSample,omitempty"`
	TotalUnits      int64          `json:"totalUnits"`
}

ListReplayReport summarizes a list source replay: pages fetched, catalogue match rate, and a preview of matched titles.

type MatchedTitle

type MatchedTitle struct {
	RatingKey  string `json:"ratingKey,omitempty"`
	ExternalID string `json:"externalId,omitempty"`
	Title      string `json:"title"`
	Type       string `json:"type,omitempty"`
	Year       int    `json:"year,omitempty"`
}

MatchedTitle is one catalogue title matched from a list source item.

type PreviewResponse

type PreviewResponse struct {
	Kind   string           `json:"kind"` // "view" | "route"
	Route  string           `json:"route"`
	Page   string           `json:"page,omitempty"`
	Title  string           `json:"title,omitempty"`
	Spec   json.RawMessage  `json:"spec,omitempty"`
	Data   json.RawMessage  `json:"data,omitempty"`
	Body   json.RawMessage  `json:"body,omitempty"`
	Valid  bool             `json:"valid"`
	Errors []string         `json:"errors,omitempty"`
	Hints  []ValidationHint `json:"hints,omitempty"`
	MS     int64            `json:"ms"`
}

PreviewResponse is the result of previewing a project's UI page/slot or capability route.

type Project

type Project struct {
	ID       string            `json:"id"`
	Template string            `json:"template"`
	Name     string            `json:"name"`
	PluginID string            `json:"pluginId"`
	Slot     string            `json:"slot,omitempty"`
	Files    map[string]string `json:"files"`
	// AddonOf is the installed add-on this draft was opened from; its code
	// reaches that add-on through ether.addon.get. The add-on link itself
	// stays sealed in the plugin record and never enters the draft.
	AddonOf string `json:"addonOf,omitempty"`
	// Installed is set once the draft has been installed, so removing the
	// plugin also clears its draft.
	Installed   bool              `json:"installed,omitempty"`
	Shadow      bool              `json:"shadow"`
	Settings    map[string]any    `json:"settings,omitempty"`
	Diagnostics []wasm.Diagnostic `json:"diagnostics"`
	DefaultPage string            `json:"defaultPage,omitempty"`
	DefaultPath string            `json:"defaultRoute,omitempty"`
	CreatedAt   time.Time         `json:"createdAt"`
	UpdatedAt   time.Time         `json:"updatedAt"`
	// contains filtered or unexported fields
}

Project is one in-progress plugin project in Studio.

type ProjectSummary

type ProjectSummary struct {
	ID        string    `json:"id"`
	Template  string    `json:"template"`
	Name      string    `json:"name"`
	PluginID  string    `json:"pluginId"`
	Slot      string    `json:"slot,omitempty"`
	Shadow    bool      `json:"shadow"`
	Errors    int       `json:"errors"`
	UpdatedAt time.Time `json:"updatedAt"`
	AddonOf   string    `json:"addonOf,omitempty"`
	Installed bool      `json:"installed,omitempty"`
}

ProjectSummary is one item in the Studio project list.

type RankingBudgetStats

type RankingBudgetStats struct {
	TotalUnits          int64   `json:"totalUnits"`
	MaxBatchUnits       int64   `json:"maxBatchUnits"`
	SlowCandidates      int     `json:"slowCandidates"`
	MemoHits            int     `json:"memoHits"`
	Timeouts            int     `json:"timeouts"`
	Traps               int     `json:"traps"`
	PerCandidateLimitMS float64 `json:"perCandidateLimitMs"`
	BatchLimitMS        float64 `json:"batchLimitMs"`
}

RankingBudgetStats reports hot-path governance units, slow candidates, and memo hits across the replay run.

type RankingReplayReport

type RankingReplayReport struct {
	Mode                string             `json:"mode"` // "ranking_step" or "rule_condition"
	StepKey             string             `json:"stepKey,omitempty"`
	ConditionKey        string             `json:"conditionKey,omitempty"`
	Position            int                `json:"position"`
	LadderBefore        []string           `json:"ladderBefore"`
	LadderAfter         []string           `json:"ladderAfter"`
	TracesLoaded        int                `json:"tracesLoaded"`
	TracesEvaluated     int                `json:"tracesEvaluated"`
	CandidatesEvaluated int                `json:"candidatesEvaluated"`
	ChangedCount        int                `json:"changedCount"`
	UnchangedCount      int                `json:"unchangedCount"`
	Changed             []ChangedPick      `json:"changed"`
	Timings             RankingTimings     `json:"timings"`
	Budget              RankingBudgetStats `json:"budget"`
}

RankingReplayReport summarizes the before/after impact of a plugin ranking step or rule condition across recorded resolver_history traces.

type RankingTimings

type RankingTimings struct {
	TotalMS        int64 `json:"totalMs"`
	PluginUS       int64 `json:"pluginUs"`
	AvgBatchUS     int64 `json:"avgBatchUs"`
	MaxBatchUS     int64 `json:"maxBatchUs"`
	AvgCandidateUS int64 `json:"avgCandidateUs"`
}

RankingTimings reports wall-clock and hot-path execution times.

type RecordedLog

type RecordedLog struct {
	Level   string         `json:"level"`
	Message string         `json:"message"`
	Attrs   map[string]any `json:"attrs,omitempty"`
}

RecordedLog is one plugin log line captured during replay.

type RecordedNotification

type RecordedNotification struct {
	Kind    string          `json:"kind"` // "owner_notice", "channel_render", "webhook"
	EventID string          `json:"eventId,omitempty"`
	Title   string          `json:"title,omitempty"`
	Text    string          `json:"text"`
	Format  string          `json:"format,omitempty"`
	Target  string          `json:"target,omitempty"`
	Payload json.RawMessage `json:"payload,omitempty"`
}

RecordedNotification is one notification or notice rendered during a dry-run replay without being sent.

type RecordedOutbound

type RecordedOutbound struct {
	Method string `json:"method"`
	URL    string `json:"url"`
	Body   string `json:"body,omitempty"`
}

RecordedOutbound is one outbound HTTP request intercepted in dry-run mode.

type RecordedWrite

type RecordedWrite struct {
	Op       string          `json:"op"`
	ViewerID int64           `json:"viewerId,omitempty"`
	Target   string          `json:"target,omitempty"`
	Watched  *bool           `json:"watched,omitempty"`
	Value    json.RawMessage `json:"value,omitempty"`
}

RecordedWrite is one host write captured during a dry-run replay without being applied to live storage.

type ReplayDeps

type ReplayDeps struct {
	DB      *sql.DB
	Manager *plugins.Manager
	Engine  *wasm.Engine
	Logger  *slog.Logger
	Now     func() time.Time
	Timeout time.Duration

	// Profiles returns configured quality profiles so ranking replay can
	// look up a trace's profile by name. When nil, a default profile is used.
	Profiles func() []core.QualityProfile

	// CatalogMatch checks whether a list item matches a title in Ether's
	// catalogue. When nil, Runner falls back to searching the database if
	// a catalogue table is present.
	CatalogMatch func(ctx context.Context, item ListItem) (MatchedTitle, bool)

	// ProbeStream probes one Live TV channel stream URL. When nil, Runner
	// uses a bounded HTTP/URL probe.
	ProbeStream func(ctx context.Context, rawURL string, headers map[string]string) StreamProbeResult

	// HTTPClient is used by the default stream prober when ProbeStream is nil.
	HTTPClient *http.Client
}

ReplayDeps configures a Studio replay Runner.

type ReplayKind

type ReplayKind string

ReplayKind names which replay mode to run.

const (
	ReplayRanking  ReplayKind = "ranking"
	ReplayEvents   ReplayKind = "events"
	ReplayList     ReplayKind = "list"
	ReplayChannels ReplayKind = "channels"
)

type ReplayParams

type ReplayParams struct {
	// Ranking and rule-condition parameters.
	StepKey      string               `json:"stepKey,omitempty"`
	ConditionKey string               `json:"conditionKey,omitempty"`
	Operator     string               `json:"operator,omitempty"`
	Value        json.RawMessage      `json:"value,omitempty"`
	Action       string               `json:"action,omitempty"`
	Position     *int                 `json:"position,omitempty"`
	AfterStep    string               `json:"afterStep,omitempty"`
	Config       json.RawMessage      `json:"config,omitempty"`
	Limit        int                  `json:"limit,omitempty"`
	Profile      *core.QualityProfile `json:"profile,omitempty"`

	// Event replay parameters.
	Days   int      `json:"days,omitempty"`
	Events []string `json:"events,omitempty"`

	// List source replay parameters.
	SourceKey string `json:"sourceKey,omitempty"`
	Catalog   string `json:"catalog,omitempty"`
	MediaType string `json:"mediaType,omitempty"`
	Pages     int    `json:"pages,omitempty"`

	// Channel replay parameters.
	ProbeLimit int `json:"probeLimit,omitempty"`
}

ReplayParams carries mode-specific parameters for a replay run.

type ReplayReport

type ReplayReport struct {
	PluginID   string               `json:"pluginId"`
	Kind       ReplayKind           `json:"kind"`
	DurationMS int64                `json:"durationMs"`
	TimedOut   bool                 `json:"timedOut,omitempty"`
	Ranking    *RankingReplayReport `json:"ranking,omitempty"`
	Events     *EventReplayReport   `json:"events,omitempty"`
	List       *ListReplayReport    `json:"list,omitempty"`
	Channels   *ChannelReplayReport `json:"channels,omitempty"`
}

ReplayReport is the structured output of one Studio replay run.

type ReplayRequest

type ReplayRequest struct {
	Plugin      string       `json:"plugin,omitempty"`
	DevInstance *DevInstance `json:"devInstance,omitempty"`
	Kind        ReplayKind   `json:"kind"`
	Params      ReplayParams `json:"params,omitempty"`
}

ReplayRequest is the input to POST /api/plugins/studio/replay and Runner.Replay.

type RunRequest

type RunRequest struct {
	Method    string                  `json:"method,omitempty"`
	Path      string                  `json:"path,omitempty"`
	Query     map[string]string       `json:"query,omitempty"`
	Headers   map[string]string       `json:"headers,omitempty"`
	Body      json.RawMessage         `json:"body,omitempty"`
	Locale    string                  `json:"locale,omitempty"`
	HotPath   string                  `json:"hotPath,omitempty"` // "" | "rank" | "cond"
	Candidate *plugins.CandidateFacts `json:"candidate,omitempty"`
	Config    json.RawMessage         `json:"config,omitempty"`
	Operator  string                  `json:"operator,omitempty"`
	Value     json.RawMessage         `json:"value,omitempty"`
}

RunRequest asks Studio to invoke a route or hot-path function on a project's sandboxed dev instance.

type RunResponse

type RunResponse struct {
	Status  int                    `json:"status"`
	Headers map[string]string      `json:"headers,omitempty"`
	Body    json.RawMessage        `json:"body,omitempty"`
	MS      int64                  `json:"ms"`
	Units   int64                  `json:"units"`
	Logs    []string               `json:"logs"`
	Call    plugins.CallRecord     `json:"call"`
	Hints   []ValidationHint       `json:"hints"`
	Journal []plugins.JournalEntry `json:"journal"`
}

RunResponse is the result of invoking a project's sandboxed dev instance.

type Runner

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

Runner executes bounded dry-run replays for installed plugins and Studio dev instances. It is safe for concurrent use; replays are serialized by a small semaphore so background runs cannot starve request paths.

func NewRunner

func NewRunner(deps ReplayDeps) *Runner

NewRunner builds a Studio replay runner.

func (*Runner) Close

func (r *Runner) Close() error

Close releases any engine the Runner created internally.

func (*Runner) HandleReplay

func (r *Runner) HandleReplay(w http.ResponseWriter, req *http.Request)

HandleReplay is the HTTP handler for POST /api/plugins/studio/replay.

func (*Runner) Handler

func (r *Runner) Handler() http.Handler

Handler returns an http.Handler serving POST /api/plugins/studio/replay (and POST /replay when mounted under /api/plugins/studio).

func (*Runner) Replay

func (r *Runner) Replay(ctx context.Context, req ReplayRequest) (ReplayReport, error)

Replay runs a bounded replay and returns its structured report.

type ScaffoldRequest

type ScaffoldRequest struct {
	ID           string   `json:"id"`
	Name         string   `json:"name"`
	Kind         string   `json:"kind,omitempty"`
	Capabilities []string `json:"capabilities,omitempty"`
	Summary      string   `json:"summary,omitempty"`
}

ScaffoldRequest describes a new plugin to generate.

type ScaffoldResult

type ScaffoldResult struct {
	Manifest plugins.Manifest  `json:"manifest"`
	Files    map[string]string `json:"files"`
}

ScaffoldResult holds the generated manifest and source files.

func Scaffold

func Scaffold(req ScaffoldRequest) (ScaffoldResult, error)

Scaffold builds a valid manifest and TypeScript entry file for the requested plugin kind and capabilities.

type StreamProbeResult

type StreamProbeResult struct {
	ChannelID   string `json:"channelId"`
	ChannelName string `json:"channelName"`
	URL         string `json:"url"`
	OK          bool   `json:"ok"`
	Status      int    `json:"status,omitempty"`
	ContentType string `json:"contentType,omitempty"`
	Kind        string `json:"kind,omitempty"` // "hls", "mpegts", "http"
	LatencyMS   int64  `json:"latencyMs"`
	Error       string `json:"error,omitempty"`
}

StreamProbeResult is the outcome of probing one channel input stream.

type Studio

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

Studio manages in-console plugin development projects and dev instances.

func New

func New(deps Deps) *Studio

New creates a new Studio service.

func (*Studio) Calls

Calls returns the dev instance's recorded calls and plain-language validation hints.

func (*Studio) CheckFiles

func (s *Studio) CheckFiles(ctx context.Context, projectID string, files map[string]string) CheckReport

CheckFiles runs the conformance and copy checks on a file set.

func (*Studio) CheckProject

func (s *Studio) CheckProject(ctx context.Context, id string) (CheckReport, error)

CheckProject runs the conformance and copy kit against the Studio project.

func (*Studio) Close

func (s *Studio) Close() error

Close releases the WASM engine if Studio created its own.

func (*Studio) CompileFiles

func (s *Studio) CompileFiles(files map[string]string, entryOverride string) CompileResult

CompileFiles validates JSON files (manifest, settings schema, i18n strings) and compiles the TypeScript/JavaScript entry with wasm.Compile.

func (*Studio) CreateProject

func (s *Studio) CreateProject(ctx context.Context, opts CreateProjectOptions) (*Project, error)

CreateProject scaffolds a new Studio project from one of the 8 templates.

func (*Studio) DeleteProject

func (s *Studio) DeleteProject(ctx context.Context, id string) error

DeleteProject removes a project from Studio.

func (*Studio) ForgetPlugin

func (s *Studio) ForgetPlugin(ctx context.Context, pluginID string)

ForgetPlugin drops the drafts of a plugin that was removed, so stale drafts never linger in Studio's list.

func (*Studio) GetProject

func (s *Studio) GetProject(_ context.Context, id string) (*Project, error)

GetProject returns a copy of a Studio project by project ID or plugin ID.

func (*Studio) Handler

func (s *Studio) Handler() http.Handler

Handler returns the HTTP handler for /api/plugins/studio/*.

func (*Studio) ImportPlugin

func (s *Studio) ImportPlugin(ctx context.Context, pluginID string) (*Project, error)

ImportPlugin opens an installed plugin in Studio: its newest draft when it has one, otherwise a new draft built from what is installed. A Stremio add-on becomes a native plugin that answers the same routes through the add-on, so editing it has no limits a native plugin lacks.

func (*Studio) InstallProject

func (s *Studio) InstallProject(ctx context.Context, id string, opts plugins.InstallOptions) (plugins.Record, error)

InstallProject installs a Studio project into the live plugin host after the owner confirms the permission sheet.

func (*Studio) InstallProjectCopy

func (s *Studio) InstallProjectCopy(ctx context.Context, id string, opts plugins.InstallOptions) (plugins.Record, error)

InstallProjectCopy installs the draft as a new plugin beside the one it came from ("Save as copy"): a fresh id, the same code and add-on link.

func (*Studio) Journal

func (s *Studio) Journal(_ context.Context, id string, shadowOnly bool) ([]plugins.JournalEntry, error)

Journal returns the dev instance's recorded writes (shadow and live).

func (*Studio) ListProjects

func (s *Studio) ListProjects(_ context.Context) []ProjectSummary

ListProjects returns summaries of all Studio projects, newest first.

func (*Studio) NotifyInstalled

func (s *Studio) NotifyInstalled(ctx context.Context, rec plugins.Record)

NotifyInstalled tells the app a plugin was installed from Studio.

func (*Studio) OpenStorage

func (s *Studio) OpenStorage(ctx context.Context, db *sql.DB) error

OpenStorage restores authoring drafts only. It never installs a plugin or runs restored code. Compile diagnostics are recomputed by normal previews.

func (*Studio) PreviewInstallProject

func (s *Studio) PreviewInstallProject(ctx context.Context, id string) (*plugins.Preview, error)

PreviewInstallProject prepares a Studio project for installation through the plugin host's permission sheet.

func (*Studio) PreviewProject

func (s *Studio) PreviewProject(
	ctx context.Context,
	id, pageKey, routeOverride string,
	params map[string]string,
) (PreviewResponse, error)

PreviewProject fetches and validates a page/slot ViewSpec document or capability route output from the project's sandboxed dev instance.

func (*Studio) RunProject

func (s *Studio) RunProject(ctx context.Context, id string, req RunRequest) (RunResponse, error)

RunProject executes a request or hot-path call against a project's sandboxed dev instance.

func (*Studio) SaveFiles

func (s *Studio) SaveFiles(
	ctx context.Context,
	id string,
	files map[string]string,
	shadow *bool,
	settings map[string]any,
) (*Project, CompileResult, error)

SaveFiles updates a project's files, recompiles it, and broadcasts a studio.reload event over the console stream (SPEC WS11a).

func (*Studio) SetShadow

func (s *Studio) SetShadow(_ context.Context, id string, shadow bool) (*Project, error)

SetShadow toggles shadow mode on a Studio project's dev instance.

func (*Studio) Undo

func (s *Studio) Undo(_ context.Context, id string) (int, error)

Undo reverts all non-undone entries in the dev instance's journal, newest first.

func (*Studio) WrapPluginHandler

func (s *Studio) WrapPluginHandler(next http.Handler) http.Handler

WrapPluginHandler wraps the plugin manager's /api/plugins/* handler so /api/plugins/studio/* routes to Studio and dev-instance view/action/call requests (e.g. /api/plugins/studio:{id}/views/{page}) are served directly by the Studio sandboxed dev instance.

type Template

type Template struct {
	ID              string               `json:"id"`
	Label           string               `json:"label"`
	Summary         string               `json:"summary"`
	Kind            plugins.Kind         `json:"kind"`
	Capabilities    []plugins.Capability `json:"capabilities"`
	DefaultPluginID string               `json:"defaultPluginId"`
	DefaultName     string               `json:"defaultName"`
	DefaultRoute    string               `json:"defaultRoute"`
	DefaultPage     string               `json:"defaultPage,omitempty"`
	SupportsStremio bool                 `json:"supportsStremio,omitempty"`
	SupportsSlot    bool                 `json:"supportsSlot,omitempty"`
	Files           map[string]string    `json:"files"`
}

Template describes a starter plugin template in the Develop tab (WS11a).

func LookupTemplate

func LookupTemplate(id string) (Template, bool)

LookupTemplate finds a template by ID.

func Templates

func Templates() []Template

Templates returns Studio's starter templates in display order, native surfaces first.

type ToolCheckReport

type ToolCheckReport struct {
	OK      bool                 `json:"ok"`
	Issues  []plugins.FieldError `json:"issues"`
	Exports map[string]bool      `json:"exports,omitempty"`
}

ToolCheckReport is the output of Check.

func Check

Check validates a plugin's manifest, copy rules, settings schema, ViewSpec files, and hosted TypeScript or JavaScript entry code.

type ToolDeps

type ToolDeps struct {
	Studio       *Studio
	Registry     *extend.Registry
	TextResolver extend.TextResolver
	Manager      *plugins.Manager
	Runner       *Runner
	Engine       *wasm.Engine
}

ToolDeps holds dependencies for the Studio and extensibility agent and MCP tools.

type ValidationHint

type ValidationHint struct {
	CallID       int64  `json:"callId,omitempty"`
	Route        string `json:"route"`
	Severity     string `json:"severity"` // "warning" | "error" | "info"
	Message      string `json:"message"`
	SuggestedFix string `json:"suggestedFix"`
	Field        string `json:"field,omitempty"`
}

ValidationHint is a plain-language inspector diagnostic on a plugin call, paired with a concrete suggested fix (SPEC WS11b).

func InspectCall

func InspectCall(call plugins.CallRecord) []ValidationHint

InspectCall analyzes one recorded plugin call and returns plain-language validation hints with suggested fixes (SPEC WS11b).

func InspectCalls

func InspectCalls(calls []plugins.CallRecord) []ValidationHint

InspectCalls aggregates plain-language hints across a list of plugin calls.

Jump to

Keyboard shortcuts

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