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
- Variables
- func ProjectTools(s *Studio) []tools.Tool
- func RedactJSON(raw json.RawMessage) string
- func RegisterTools(cat *tools.Catalogue, deps ToolDeps) error
- func Tools(deps ToolDeps) []tools.Tool
- type ChangedPick
- type ChannelReplayReport
- type CheckItem
- type CheckReport
- type CheckRequest
- type CompileResult
- type CreateProjectOptions
- type Deps
- type DevInstance
- type EventReplayReport
- type ListItem
- type ListReplayReport
- type MatchedTitle
- type PreviewResponse
- type Project
- type ProjectSummary
- type RankingBudgetStats
- type RankingReplayReport
- type RankingTimings
- type RecordedLog
- type RecordedNotification
- type RecordedOutbound
- type RecordedWrite
- type ReplayDeps
- type ReplayKind
- type ReplayParams
- type ReplayReport
- type ReplayRequest
- type RunRequest
- type RunResponse
- type Runner
- type ScaffoldRequest
- type ScaffoldResult
- type StreamProbeResult
- type Studio
- func (s *Studio) Calls(_ context.Context, id string) ([]plugins.CallRecord, []ValidationHint, error)
- func (s *Studio) CheckFiles(ctx context.Context, projectID string, files map[string]string) CheckReport
- func (s *Studio) CheckProject(ctx context.Context, id string) (CheckReport, error)
- func (s *Studio) Close() error
- func (s *Studio) CompileFiles(files map[string]string, entryOverride string) CompileResult
- func (s *Studio) CreateProject(ctx context.Context, opts CreateProjectOptions) (*Project, error)
- func (s *Studio) DeleteProject(ctx context.Context, id string) error
- func (s *Studio) ForgetPlugin(ctx context.Context, pluginID string)
- func (s *Studio) GetProject(_ context.Context, id string) (*Project, error)
- func (s *Studio) Handler() http.Handler
- func (s *Studio) ImportPlugin(ctx context.Context, pluginID string) (*Project, error)
- func (s *Studio) InstallProject(ctx context.Context, id string, opts plugins.InstallOptions) (plugins.Record, error)
- func (s *Studio) InstallProjectCopy(ctx context.Context, id string, opts plugins.InstallOptions) (plugins.Record, error)
- func (s *Studio) Journal(_ context.Context, id string, shadowOnly bool) ([]plugins.JournalEntry, error)
- func (s *Studio) ListProjects(_ context.Context) []ProjectSummary
- func (s *Studio) NotifyInstalled(ctx context.Context, rec plugins.Record)
- func (s *Studio) OpenStorage(ctx context.Context, db *sql.DB) error
- func (s *Studio) PreviewInstallProject(ctx context.Context, id string) (*plugins.Preview, error)
- func (s *Studio) PreviewProject(ctx context.Context, id, pageKey, routeOverride string, ...) (PreviewResponse, error)
- func (s *Studio) RunProject(ctx context.Context, id string, req RunRequest) (RunResponse, error)
- func (s *Studio) SaveFiles(ctx context.Context, id string, files map[string]string, shadow *bool, ...) (*Project, CompileResult, error)
- func (s *Studio) SetShadow(_ context.Context, id string, shadow bool) (*Project, error)
- func (s *Studio) Undo(_ context.Context, id string) (int, error)
- func (s *Studio) WrapPluginHandler(next http.Handler) http.Handler
- type Template
- type ToolCheckReport
- type ToolDeps
- type ValidationHint
Constants ¶
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 ¶
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).
var ErrProjectNotFound = errors.New("studio: project not found")
ErrProjectNotFound is returned when a Studio project ID does not exist.
Functions ¶
func ProjectTools ¶
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 ¶
RegisterTools registers the Studio and extensibility tools into cat.
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 (*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 ¶
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 (*Studio) Calls ¶
func (s *Studio) Calls(_ context.Context, id string) ([]plugins.CallRecord, []ValidationHint, error)
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 ¶
CheckProject runs the conformance and copy kit against the Studio project.
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 ¶
CreateProject scaffolds a new Studio project from one of the 8 templates.
func (*Studio) DeleteProject ¶
DeleteProject removes a project from Studio.
func (*Studio) ForgetPlugin ¶
ForgetPlugin drops the drafts of a plugin that was removed, so stale drafts never linger in Studio's list.
func (*Studio) GetProject ¶
GetProject returns a copy of a Studio project by project ID or plugin ID.
func (*Studio) ImportPlugin ¶
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 ¶
NotifyInstalled tells the app a plugin was installed from Studio.
func (*Studio) OpenStorage ¶
OpenStorage restores authoring drafts only. It never installs a plugin or runs restored code. Compile diagnostics are recomputed by normal previews.
func (*Studio) PreviewInstallProject ¶
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) Undo ¶
Undo reverts all non-undone entries in the dev instance's journal, newest first.
func (*Studio) WrapPluginHandler ¶
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 ¶
LookupTemplate finds a template by ID.
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 ¶
func Check(ctx context.Context, _ *wasm.Engine, req CheckRequest) (ToolCheckReport, error)
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.