etherplugin

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: 21 Imported by: 0

README

etherplugin (Go SDK)

Go authoring package (github.com/braedonsaunders/ether/sdk/go) for Ether Plugin Protocol v1 (EPP/1).

Execution modes

  1. Native HTTP or WebSocket tunnel sidecar (ether.runtime.kind: "remote"): Compile a standard Go binary and call p.Serve(ctx, etherplugin.ServeOptions{}) (or mount p as an http.Handler). Host calls go over HTTP to /ether/plugin-host/* authenticated with X-Ether-Plugin-Credential.
  2. Hosted WebAssembly guest: not yet supported. Go 1.27.3 GOOS=wasip1 GOARCH=wasm emits wasi_snapshot_preview1 imports (including proc_exit, clock_time_get, and fd_write), which the runtime forbids. TinyGo is not installed here, so a compatible TinyGo build has not been verified. Use a sidecar until a guest is built and tested against Ether's raw WASM ABI.

Usage

package main

import (
	"context"
	"os/signal"
	"syscall"

	etherplugin "github.com/braedonsaunders/ether/sdk/go"
)

func main() {
	p := etherplugin.New(etherplugin.Definition{
		Manifest: etherplugin.Manifest{
			ID:      "org.ether.examples.hello",
			Name:    "Hello plugin",
			Version: "0.1.0",
			Ether: &etherplugin.EtherManifestBlock{
				Protocol:     1,
				Kind:         etherplugin.KindExtension,
				Capabilities: []etherplugin.Capability{etherplugin.CapListSource, etherplugin.CapUI},
				Summary:      "Minimal greeting plugin for Ether.",
				Runtime:      etherplugin.RuntimeDecl{Kind: "remote"},
			},
		},
		Routes: etherplugin.Routes{
			Catalog: func(ctx *etherplugin.Context, req etherplugin.CatalogRequest) (etherplugin.CatalogResponse, error) {
				return etherplugin.CatalogResponse{
					Metas: []etherplugin.CatalogItem{{
						ID:          "tt0133093",
						Type:        req.Type,
						Name:        "Hello from " + req.ID,
						ReleaseInfo: "1999",
					}},
				}, nil
			},
		},
	})

	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()
	_ = p.Serve(ctx, etherplugin.ServeOptions{})
}

WS8b interoperability test

Once internal/plugins/remote is present, run go test -tags ws8b ./sdk/examples/hello/go -run TestWS8bSDKInterop. It starts Ether's tunnel server and exercises the Go, Python, and TypeScript hello sidecars. It requires Python 3 and a Node version with TypeScript support and WebSocket. The SDK sidecars currently make one tunnel connection; if it drops, a process supervisor must restart the sidecar.

Documentation

Overview

Package etherplugin is the Go authoring SDK for Ether Plugin Protocol v1 (EPP/1).

It provides the same declarative router shape, settings decoder, localization helper, host service client, test harness, and capability templates as `@ether/plugin-sdk` (TypeScript) and `ether_plugin` (Python).

Execution modes

Go plugins run as native HTTP or WebSocket tunnel sidecars. Hosted Go is not supported: the standard Go wasip1 toolchain emits WASI imports, which Ether's sandbox rejects. See README.md for details.

Server packages under `internal/` and `cmd/` must not import this package.

Index

Constants

View Source
const (
	// TunnelProtocol is the WebSocket subprotocol for Ether remote plugin tunnels.
	TunnelProtocol = "ether-tunnel-v1"
	// DefaultMaxChunkBytes is the default chunk size for streamed file responses.
	DefaultMaxChunkBytes = 64 * 1024
)

Variables

View Source
var Fixtures = struct {
	PickToken     func(itemID string) string
	Movie         func() MetaItem
	CatalogItem   func() CatalogItem
	PlaybackEvent func(name string) EtherEvent
	Candidate     func() CandidateFacts
}{
	PickToken: func(itemID string) string {
		if itemID == "" {
			itemID = "ether:movie:1"
		}
		return "pick-v1:" + itemID + ":sig-test"
	},
	Movie: func() MetaItem {
		return MetaItem{
			CatalogItem: CatalogItem{
				ID:          "tt0133093",
				Type:        "movie",
				Name:        "The Matrix",
				ReleaseInfo: "1999",
				Description: "A computer hacker learns about the true nature of reality.",
				Genres:      []string{"Action", "Sci-Fi"},
				IMDBRating:  "8.7",
			},
		}
	},
	CatalogItem: func() CatalogItem {
		return CatalogItem{
			ID:          "tt0133093",
			Type:        "movie",
			Name:        "The Matrix",
			ReleaseInfo: "1999",
		}
	},
	PlaybackEvent: func(name string) EtherEvent {
		if name == "" {
			name = "playback.completed"
		}
		return EtherEvent{
			ID:       "evt_01",
			Name:     name,
			At:       "2026-11-02T12:00:00Z",
			ViewerID: 1,
			Payload: map[string]any{
				"titleId":  "tt0133093",
				"title":    "The Matrix",
				"progress": 0.95,
			},
		}
	},
	Candidate: func() CandidateFacts {
		return CandidateFacts{
			ReleaseID:  "rel_01",
			Name:       "The.Matrix.1999.2160p.UHD.BluRay.x265",
			Resolution: 2160,
			HDR:        []string{"DV", "HDR10"},
			VideoCodec: "hevc",
			Cached:     true,
			Verified:   true,
		}
	},
}

Fixtures provides sample EPP/1 records for plugin unit tests.

Functions

func AssertValidViewSpec

func AssertValidViewSpec(doc ViewSpecDocument) error

AssertValidViewSpec validates a ViewSpecDocument for structural rules and rejects any `*ClassName` fields.

func DecodeSettings

func DecodeSettings(
	schema *SettingsSchema,
	incoming map[string]any,
	defaults map[string]any,
) (map[string]any, map[string]string)

DecodeSettings applies schema defaults and validates incoming settings, returning the decoded settings map and any JSON-pointer keyed errors.

func LintCopy

func LintCopy(raw string, maxRunes int) string

LintCopy validates a user-visible string against Ether's copy rules. It returns an empty string when valid, or the plain reason when invalid.

func TRef

func TRef(key string) string

TRef formats a "$t:<key>" localization reference for manifests and ViewSpecs.

Types

type ActionProposal

type ActionProposal struct {
	Category    string         `json:"category"`
	Description string         `json:"description"`
	Input       map[string]any `json:"input,omitempty"`
}

ActionProposal describes a confirmation proposal returned by an Action handler.

type ActionRequest

type ActionRequest struct {
	Action string         `json:"action"`
	Input  map[string]any `json:"input"`
}

ActionRequest is passed to an Action route handler.

type ActionResponse

type ActionResponse struct {
	Toast    string          `json:"toast,omitempty"`
	Refresh  bool            `json:"refresh,omitempty"`
	Open     string          `json:"open,omitempty"`
	Proposal *ActionProposal `json:"proposal,omitempty"`
}

ActionResponse is returned by an Action route handler.

type BehaviorHints

type BehaviorHints struct {
	Adult                 bool `json:"adult,omitempty"`
	P2P                   bool `json:"p2p,omitempty"`
	Configurable          bool `json:"configurable,omitempty"`
	ConfigurationRequired bool `json:"configurationRequired,omitempty"`
}

BehaviorHints carries Stremio-compatible behavior hints.

type CandidateFacts

type CandidateFacts struct {
	ReleaseID     string      `json:"releaseId"`
	Name          string      `json:"name"`
	Size          int64       `json:"size,omitempty"`
	Protocol      string      `json:"protocol,omitempty"`
	SourceClass   string      `json:"sourceClass,omitempty"`
	Indexer       string      `json:"indexer,omitempty"`
	Resolution    any         `json:"resolution,omitempty"`
	HDR           []string    `json:"hdr,omitempty"`
	VideoCodec    string      `json:"videoCodec,omitempty"`
	AudioCodecs   []string    `json:"audioCodecs,omitempty"`
	AudioChannels string      `json:"audioChannels,omitempty"`
	Languages     []string    `json:"languages,omitempty"`
	Subtitles     []string    `json:"subtitles,omitempty"`
	ReleaseType   string      `json:"releaseType,omitempty"`
	Group         string      `json:"group,omitempty"`
	Cached        bool        `json:"cached,omitempty"`
	Verified      bool        `json:"verified,omitempty"`
	ClientCaps    *ClientCaps `json:"clientCaps,omitempty"`
}

CandidateFacts is the release candidate structure passed to RankKey and CondMatch.

type Capability

type Capability string

Capability names a capability declared in manifest.ether.capabilities.

const (
	CapStreamSource   Capability = "stream_source"
	CapDebridProvider Capability = "debrid_provider"
	CapListSource     Capability = "list_source"
	CapLiveTV         Capability = "livetv_channels"
	CapSubtitles      Capability = "subtitles"
	CapMarkers        Capability = "markers"
	CapNotify         Capability = "notify"
	CapEvents         Capability = "events"
	CapRankingStep    Capability = "ranking_step"
	CapRuleCondition  Capability = "rule_condition"
	CapTools          Capability = "tools"
	CapUI             Capability = "ui"
)

type CatalogItem

type CatalogItem struct {
	ID          string   `json:"id"`
	Type        string   `json:"type"`
	Name        string   `json:"name"`
	Poster      string   `json:"poster,omitempty"`
	PosterShape string   `json:"posterShape,omitempty"`
	Background  string   `json:"background,omitempty"`
	Description string   `json:"description,omitempty"`
	ReleaseInfo string   `json:"releaseInfo,omitempty"`
	IMDBRating  string   `json:"imdbRating,omitempty"`
	Genres      []string `json:"genres,omitempty"`
}

CatalogItem is one item in a catalog response.

type CatalogRequest

type CatalogRequest struct {
	Type   string            `json:"type"`
	ID     string            `json:"id"`
	Extra  map[string]string `json:"extra"`
	Skip   int               `json:"skip"`
	Search string            `json:"search,omitempty"`
	Genre  string            `json:"genre,omitempty"`
}

CatalogRequest is passed to a Catalog route handler.

type CatalogResponse

type CatalogResponse struct {
	Metas []CatalogItem `json:"metas"`
}

CatalogResponse is returned by a Catalog route handler.

type CatalogTitleSummary

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

CatalogTitleSummary is a catalog record returned by Host.CatalogSearch or Host.CatalogGet.

type ChannelInput

type ChannelInput struct {
	URL      string            `json:"url"`
	Name     string            `json:"name,omitempty"`
	Headers  map[string]string `json:"headers,omitempty"`
	Priority int               `json:"priority,omitempty"`
}

ChannelInput is one stream input for a Live TV channel.

type ChannelItem

type ChannelItem struct {
	ID      string         `json:"id"`
	Name    string         `json:"name"`
	Number  int            `json:"number,omitempty"`
	Group   string         `json:"group,omitempty"`
	GuideID string         `json:"guideId,omitempty"`
	Inputs  []ChannelInput `json:"inputs"`
}

ChannelItem is one Live TV channel.

type ChannelsMeta

type ChannelsMeta struct {
	Refresh string `json:"refresh,omitempty"`
	Test    bool   `json:"test"`
}

ChannelsMeta describes a Live TV channel contribution.

type ChannelsResponse

type ChannelsResponse struct {
	Channels []ChannelItem `json:"channels"`
}

ChannelsResponse is returned by a Channels route handler.

type ClientCaps

type ClientCaps struct {
	MaxHeight int      `json:"maxHeight,omitempty"`
	HDR       []string `json:"hdr,omitempty"`
	Codecs    []string `json:"codecs,omitempty"`
}

ClientCaps describes playback client capabilities passed to hot-path functions.

type CommandMeta

type CommandMeta struct {
	Key    string `json:"key"`
	Label  string `json:"label"`
	Action string `json:"action"`
}

CommandMeta describes a command contributed by a plugin.

type ConfigureResponse

type ConfigureResponse struct {
	Errors map[string]string `json:"errors"`
}

ConfigureResponse is returned by a Configure route handler.

type Context

type Context struct {
	context.Context
	Manifest  Manifest
	Settings  map[string]any
	Locale    string
	PickToken string
	RequestID string
	Headers   map[string]string
	Query     map[string]string
	Ether     Host
	I18n      *I18n
}

Context is passed to every plugin route handler.

func (*Context) T

func (c *Context) T(key string, params map[string]any) string

T resolves a localized string key with optional parameter interpolation.

type Contributes

type Contributes struct {
	Source         *SourceMeta         `json:"source,omitempty"`
	Channels       *ChannelsMeta       `json:"channels,omitempty"`
	Subtitles      *SubtitlesMeta      `json:"subtitles,omitempty"`
	Markers        *MarkersMeta        `json:"markers,omitempty"`
	Notification   *NotificationMeta   `json:"notification,omitempty"`
	Events         *EventsMeta         `json:"events,omitempty"`
	Integration    *IntegrationMeta    `json:"integration,omitempty"`
	ListSources    []ListSourceMeta    `json:"listSources,omitempty"`
	RankingSteps   []RankingStepMeta   `json:"rankingSteps,omitempty"`
	RuleConditions []RuleConditionMeta `json:"ruleConditions,omitempty"`
	Tools          []ToolMeta          `json:"tools,omitempty"`
	Pages          []PageMeta          `json:"pages,omitempty"`
	Slots          []SlotMeta          `json:"slots,omitempty"`
	Commands       []CommandMeta       `json:"commands,omitempty"`
}

Contributes declares the descriptors a plugin contributes to Ether.

type Definition

type Definition struct {
	Manifest          Manifest
	Routes            Routes
	DefaultSettings   map[string]any
	Strings           StringsCatalog
	DefaultLocale     string
	Host              Host
	RemoteHostOptions RemoteHostOptions
}

Definition configures a new Plugin instance.

type EtherEvent

type EtherEvent struct {
	ID       string         `json:"id"`
	Name     string         `json:"name"`
	At       string         `json:"at"`
	ViewerID int64          `json:"viewerId,omitempty"`
	Payload  map[string]any `json:"payload,omitempty"`
}

EtherEvent is one event delivered in a batch to POST /ether/event.

type EtherManifestBlock

type EtherManifestBlock struct {
	Protocol     int             `json:"protocol"`
	Kind         PluginKind      `json:"kind"`
	Capabilities []Capability    `json:"capabilities,omitempty"`
	Summary      string          `json:"summary"`
	Author       *PluginAuthor   `json:"author,omitempty"`
	License      string          `json:"license,omitempty"`
	Repo         string          `json:"repo,omitempty"`
	Icon         string          `json:"icon,omitempty"`
	Runtime      RuntimeDecl     `json:"runtime"`
	Cluster      string          `json:"cluster,omitempty"`
	Health       *HealthDecl     `json:"health,omitempty"`
	Permissions  *Permissions    `json:"permissions,omitempty"`
	Settings     *SettingsSchema `json:"settings,omitempty"`
	Strings      map[string]any  `json:"strings,omitempty"`
	Schedule     []ScheduleEntry `json:"schedule,omitempty"`
	Contributes  *Contributes    `json:"contributes,omitempty"`
}

EtherManifestBlock holds the EPP/1 `ether` manifest block.

type EventResponse

type EventResponse struct {
	Ack []string `json:"ack"`
}

EventResponse is returned by an Event route handler.

type EventsMeta

type EventsMeta struct {
	Subscribe []string `json:"subscribe"`
}

EventsMeta lists subscribed event names.

type FieldOption

type FieldOption struct {
	Value string `json:"value"`
	Label string `json:"label"`
	Hint  string `json:"hint,omitempty"`
}

FieldOption is one selectable option for a select or multiSelect field.

type FieldProblem

type FieldProblem struct {
	Field   string `json:"field"`
	Message string `json:"message"`
}

FieldProblem describes one schema validation or copy-rule problem.

func LintSettingsSchema

func LintSettingsSchema(schema *SettingsSchema) []FieldProblem

LintSettingsSchema checks a SettingsSchema for forbidden kinds and copy-rule violations.

type FileRangeResponse

type FileRangeResponse struct {
	Status       int               `json:"status,omitempty"`
	ContentType  string            `json:"contentType,omitempty"`
	ContentRange string            `json:"contentRange,omitempty"`
	TotalSize    *int64            `json:"totalSize,omitempty"`
	Headers      map[string]string `json:"headers,omitempty"`
	Body         []byte            `json:"-"`
}

FileRangeResponse is returned by a File route handler.

type FileRequest

type FileRequest struct {
	Path     string `json:"path"`
	Range    string `json:"range,omitempty"`
	HeadOnly bool   `json:"headOnly,omitempty"`
}

FileRequest is passed to a File route handler.

type FolderEntry

type FolderEntry struct {
	Name  string `json:"name"`
	Path  string `json:"path"`
	Dir   bool   `json:"dir"`
	Size  int64  `json:"size,omitempty"`
	Mtime int64  `json:"mtime,omitempty"`
}

FolderEntry describes one entry returned by Host.FoldersList or Host.FoldersStat.

type GuideRequest

type GuideRequest struct {
	ChannelID string `json:"channelId"`
	From      string `json:"from,omitempty"`
	To        string `json:"to,omitempty"`
}

GuideRequest is passed to a Guide route handler.

type GuideResponse

type GuideResponse struct {
	Programmes []ProgrammeItem `json:"programmes"`
}

GuideResponse is returned by a Guide route handler.

type HealthDecl

type HealthDecl struct {
	Interval string `json:"interval,omitempty"`
}

HealthDecl configures periodic health checks.

type HealthResponse

type HealthResponse struct {
	Status string `json:"status"`
	Reason string `json:"reason,omitempty"`
}

HealthResponse is returned by a Health route handler.

type Host

type Host interface {
	KVGet(ctx context.Context, key string) (string, bool, error)
	KVPut(ctx context.Context, key, value string) error
	KVDelete(ctx context.Context, key string) error
	KVList(ctx context.Context, prefix string) ([]string, error)
	SecretGet(ctx context.Context, name string) (string, error)
	Fetch(ctx context.Context, req HostFetchRequest) (HostFetchResponse, error)
	CatalogSearch(ctx context.Context, query string, limit, offset int) ([]CatalogTitleSummary, error)
	CatalogGet(ctx context.Context, id string) (*CatalogTitleSummary, error)
	ViewerHistory(ctx context.Context, viewerID int64, limit, offset int) ([]ViewerWatchEntry, error)
	SetWatchState(ctx context.Context, viewerID int64, titleID string, watched bool) error
	UpsertCollection(ctx context.Context, collection map[string]any) error
	FoldersList(ctx context.Context, root, path string) ([]FolderEntry, error)
	FoldersStat(ctx context.Context, root, path string) (FolderEntry, error)
	NotifyOwner(ctx context.Context, text string) error
	Log(ctx context.Context, level, message string, attrs map[string]any) error
}

Host provides access to Ether host services (KV, secrets, HTTP, catalog, viewers, collections, folders, owner notifications, and logging).

type HostFetchRequest

type HostFetchRequest struct {
	Method  string            `json:"method,omitempty"`
	URL     string            `json:"url"`
	Headers map[string]string `json:"headers,omitempty"`
	Body    string            `json:"body,omitempty"`
}

HostFetchRequest describes an outbound HTTP call via the host service.

type HostFetchResponse

type HostFetchResponse struct {
	Status  int               `json:"status"`
	Headers map[string]string `json:"headers"`
	Body    string            `json:"body"`
}

HostFetchResponse is returned by Host.Fetch.

type I18n

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

I18n resolves localized strings with fallback to base language and "en".

func NewI18n

func NewI18n(catalog StringsCatalog, defaultLocale string) *I18n

NewI18n creates a localization helper backed by a StringsCatalog.

func (*I18n) Catalog

func (i *I18n) Catalog() StringsCatalog

Catalog returns the underlying locale catalog.

func (*I18n) T

func (i *I18n) T(rawKey string, params map[string]any, locale string) string

T resolves a key for the given locale and interpolates {param} placeholders.

type IntegrationMeta

type IntegrationMeta struct {
	Category string   `json:"category"`
	Adds     []string `json:"adds"`
	Connect  string   `json:"connect"`
	Test     bool     `json:"test,omitempty"`
}

IntegrationMeta describes an external service integration.

type JobRequest

type JobRequest struct {
	Name string `json:"name"`
}

JobRequest is passed to a Job route handler.

type JobResponse

type JobResponse map[string]any

JobResponse is returned by a Job route handler.

type ListSourceMeta

type ListSourceMeta struct {
	Key      string `json:"key"`
	Label    string `json:"label"`
	Hint     string `json:"hint,omitempty"`
	Catalog  string `json:"catalog"`
	Params   any    `json:"params,omitempty"`
	MaxItems int    `json:"maxItems,omitempty"`
	Refresh  string `json:"refresh,omitempty"`
}

ListSourceMeta describes a catalog list source.

type Manifest

type Manifest struct {
	ID            string               `json:"id"`
	Version       string               `json:"version"`
	Name          string               `json:"name"`
	Description   string               `json:"description,omitempty"`
	Background    string               `json:"background,omitempty"`
	Types         []string             `json:"types,omitempty"`
	Catalogs      []StremioCatalogDecl `json:"catalogs,omitempty"`
	Resources     []any                `json:"resources,omitempty"`
	IDPrefixes    []string             `json:"idPrefixes,omitempty"`
	BehaviorHints *BehaviorHints       `json:"behaviorHints,omitempty"`
	Ether         *EtherManifestBlock  `json:"ether,omitempty"`
}

Manifest is the EPP/1 manifest document served at GET /manifest.json.

type MarkerItem

type MarkerItem struct {
	Kind  string  `json:"kind"`
	Start float64 `json:"start"`
	End   float64 `json:"end"`
	Label string  `json:"label,omitempty"`
}

MarkerItem is one intro/credits/recap/preview marker.

type MarkersMeta

type MarkersMeta struct {
	Kinds []string `json:"kinds"`
}

MarkersMeta describes a playback markers contribution.

type MarkersRequest

type MarkersRequest struct {
	Type string `json:"type"`
	ID   string `json:"id"`
}

MarkersRequest is passed to a Markers route handler.

type MarkersResponse

type MarkersResponse struct {
	Markers []MarkerItem `json:"markers"`
}

MarkersResponse is returned by a Markers route handler.

type MetaItem

type MetaItem struct {
	CatalogItem
	Runtime  string      `json:"runtime,omitempty"`
	Cast     []string    `json:"cast,omitempty"`
	Director []string    `json:"director,omitempty"`
	Videos   []MetaVideo `json:"videos,omitempty"`
}

MetaItem is a full metadata record returned by a Meta route handler.

type MetaRequest

type MetaRequest struct {
	Type string `json:"type"`
	ID   string `json:"id"`
}

MetaRequest is passed to a Meta route handler.

type MetaResponse

type MetaResponse struct {
	Meta MetaItem `json:"meta"`
}

MetaResponse is returned by a Meta route handler.

type MetaVideo

type MetaVideo struct {
	ID        string `json:"id"`
	Title     string `json:"title"`
	Released  string `json:"released,omitempty"`
	Season    int    `json:"season,omitempty"`
	Episode   int    `json:"episode,omitempty"`
	Overview  string `json:"overview,omitempty"`
	Thumbnail string `json:"thumbnail,omitempty"`
}

MetaVideo describes one episode/video inside a MetaItem.

type MockHost

type MockHost struct {
	KV            map[string]string
	Secrets       map[string]string
	Catalog       map[string]CatalogTitleSummary
	History       map[int64][]ViewerWatchEntry
	WatchState    map[string]bool
	Collections   []map[string]any
	Folders       map[string][]FolderEntry
	Notifications []string
	Logs          []RecordedLog
	FetchHandler  func(ctx context.Context, req HostFetchRequest) (HostFetchResponse, error)
	// contains filtered or unexported fields
}

MockHost is an in-memory Host implementation for unit tests.

func NewMockHost

func NewMockHost() *MockHost

NewMockHost creates an initialized MockHost.

func (*MockHost) CatalogGet

func (m *MockHost) CatalogGet(_ context.Context, id string) (*CatalogTitleSummary, error)

CatalogGet returns a title by ID from the in-memory catalog.

func (*MockHost) CatalogSearch

func (m *MockHost) CatalogSearch(_ context.Context, query string, limit, offset int) ([]CatalogTitleSummary, error)

CatalogSearch searches the in-memory catalog by case-insensitive substring.

func (*MockHost) Fetch

Fetch invokes FetchHandler if set, or returns a 200 "{}" response.

func (*MockHost) FoldersList

func (m *MockHost) FoldersList(_ context.Context, root, path string) ([]FolderEntry, error)

FoldersList returns folder entries for root/path.

func (*MockHost) FoldersStat

func (m *MockHost) FoldersStat(_ context.Context, root, path string) (FolderEntry, error)

FoldersStat returns a FolderEntry for root and path.

func (*MockHost) KVDelete

func (m *MockHost) KVDelete(_ context.Context, key string) error

KVDelete deletes a key from the in-memory KV store.

func (*MockHost) KVGet

func (m *MockHost) KVGet(_ context.Context, key string) (string, bool, error)

KVGet reads a key from the in-memory KV store.

func (*MockHost) KVList

func (m *MockHost) KVList(_ context.Context, prefix string) ([]string, error)

KVList lists keys matching prefix in sorted order.

func (*MockHost) KVPut

func (m *MockHost) KVPut(_ context.Context, key, value string) error

KVPut writes a key-value pair to the in-memory KV store.

func (*MockHost) Log

func (m *MockHost) Log(_ context.Context, level, message string, attrs map[string]any) error

Log appends a RecordedLog entry to Logs.

func (*MockHost) NotifyOwner

func (m *MockHost) NotifyOwner(_ context.Context, text string) error

NotifyOwner appends text to Notifications.

func (*MockHost) SecretGet

func (m *MockHost) SecretGet(_ context.Context, name string) (string, error)

SecretGet reads a secret from the in-memory secrets map.

func (*MockHost) SetWatchState

func (m *MockHost) SetWatchState(_ context.Context, viewerID int64, titleID string, watched bool) error

SetWatchState records watch state for viewerID:titleID.

func (*MockHost) UpsertCollection

func (m *MockHost) UpsertCollection(_ context.Context, collection map[string]any) error

UpsertCollection appends the collection to Collections.

func (*MockHost) ViewerHistory

func (m *MockHost) ViewerHistory(_ context.Context, viewerID int64, limit, offset int) ([]ViewerWatchEntry, error)

ViewerHistory returns watch history for viewerID.

type NotificationMeta

type NotificationMeta struct {
	Fields    any      `json:"fields,omitempty"`
	SendTest  bool     `json:"sendTest"`
	Formats   []string `json:"formats,omitempty"`
	MaxLength int      `json:"maxLength,omitempty"`
}

NotificationMeta describes a notification channel contribution.

type NotifyRequest

type NotifyRequest struct {
	Title    string         `json:"title,omitempty"`
	Message  string         `json:"message"`
	Event    string         `json:"event,omitempty"`
	Settings map[string]any `json:"settings,omitempty"`
}

NotifyRequest is passed to a Notify route handler.

type NotifyResponse

type NotifyResponse struct {
	OK      bool   `json:"ok"`
	Message string `json:"message,omitempty"`
}

NotifyResponse is returned by a Notify route handler.

type OpenStreamRequest

type OpenStreamRequest struct {
	StreamID string `json:"streamId"`
}

OpenStreamRequest is passed to an OpenStream route handler.

type OpenStreamResponse

type OpenStreamResponse struct {
	URL       string            `json:"url,omitempty"`
	Headers   map[string]string `json:"headers,omitempty"`
	ExpiresAt string            `json:"expiresAt,omitempty"`
	File      string            `json:"file,omitempty"`
}

OpenStreamResponse is returned by an OpenStream route handler.

type PageMeta

type PageMeta struct {
	Key   string `json:"key"`
	Label string `json:"label"`
	Route string `json:"route"`
	Group string `json:"group,omitempty"`
	Icon  string `json:"icon,omitempty"`
}

PageMeta describes a ViewSpec page contributed by a plugin.

type Permissions

type Permissions struct {
	Network     []string           `json:"network,omitempty"`
	Catalog     string             `json:"catalog,omitempty"`
	Viewers     *ViewerPermissions `json:"viewers,omitempty"`
	Collections string             `json:"collections,omitempty"`
	Folders     string             `json:"folders,omitempty"`
	Secrets     []string           `json:"secrets,omitempty"`
}

Permissions declares the host access a plugin requests.

type Plugin

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

Plugin is a runnable Ether plugin instance.

func New

func New(def Definition) *Plugin

New constructs a Plugin from a Definition.

func NewCatalogTemplate

func NewCatalogTemplate(opts TemplateOptions) *Plugin

NewCatalogTemplate builds a starter catalog and metadata plugin.

func NewConditionTemplate

func NewConditionTemplate(opts TemplateOptions) *Plugin

NewConditionTemplate builds a starter rule-condition plugin.

func NewRankerTemplate

func NewRankerTemplate(opts TemplateOptions) *Plugin

NewRankerTemplate builds a starter release-ranking step plugin.

func NewScrobblerTemplate

func NewScrobblerTemplate(opts TemplateOptions) *Plugin

NewScrobblerTemplate builds a starter playback event subscriber plugin.

func NewSubtitlesTemplate

func NewSubtitlesTemplate(opts TemplateOptions) *Plugin

NewSubtitlesTemplate builds a starter subtitles provider plugin.

func NewViewTemplate

func NewViewTemplate(opts TemplateOptions) *Plugin

NewViewTemplate builds a starter ViewSpec UI and action plugin.

func (*Plugin) CondMatch

func (p *Plugin) CondMatch(candidate CandidateFacts, operator string, value any) bool

CondMatch invokes the plugin's CondMatch hot-path function.

func (*Plugin) Dispatch

func (p *Plugin) Dispatch(ctx context.Context, req RawRequest) RawResponse

Dispatch routes a RawRequest through the plugin and returns a RawResponse.

func (*Plugin) DispatchTunnelFrame

func (p *Plugin) DispatchTunnelFrame(ctx context.Context, frame TunnelFrame, maxChunkBytes int) []TunnelFrame

DispatchTunnelFrame executes a `"request"` TunnelFrame against a Plugin and returns the outgoing response frames (either a single `"response"` frame or a `"response_start"` / `"response_chunk"` / `"response_end"` sequence for `/ether/file/*` binary responses).

func (*Plugin) GetSettings

func (p *Plugin) GetSettings() map[string]any

GetSettings returns a copy of the plugin's active settings.

func (*Plugin) Manifest

func (p *Plugin) Manifest() Manifest

Manifest returns the plugin's Manifest.

func (*Plugin) RankKey

func (p *Plugin) RankKey(candidate CandidateFacts, config map[string]any) int64

RankKey invokes the plugin's RankKey hot-path function.

func (*Plugin) Serve

func (p *Plugin) Serve(ctx context.Context, opts ServeOptions) error

Serve runs the plugin sidecar until ctx is cancelled.

func (*Plugin) ServeHTTP

func (p *Plugin) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements net/http.Handler for running a Plugin as an HTTP sidecar.

func (*Plugin) SetSettings

func (p *Plugin) SetSettings(incoming map[string]any) (map[string]any, map[string]string)

SetSettings validates and updates the plugin's settings.

func (*Plugin) Start

func (p *Plugin) Start(ctx context.Context, opts ServeOptions) (*ServeHandle, error)

Start launches the plugin sidecar in the background (either HTTP or WebSocket tunnel) and returns a ServeHandle that stops it when Close is called or ctx is cancelled.

type PluginAuthor

type PluginAuthor struct {
	Name string `json:"name,omitempty"`
	URL  string `json:"url,omitempty"`
}

PluginAuthor identifies the plugin author.

type PluginKind

type PluginKind string

PluginKind identifies the top-level plugin classification in manifest.ether.kind.

const (
	KindSource              PluginKind = "source"
	KindIntegration         PluginKind = "integration"
	KindNotificationChannel PluginKind = "notification_channel"
	KindLiveTVSource        PluginKind = "livetv_source"
	KindExtension           PluginKind = "extension"
)

type ProgrammeItem

type ProgrammeItem struct {
	ID          string   `json:"id,omitempty"`
	ChannelID   string   `json:"channelId,omitempty"`
	Title       string   `json:"title"`
	Subtitle    string   `json:"subtitle,omitempty"`
	Description string   `json:"description,omitempty"`
	Start       string   `json:"start"`
	Stop        string   `json:"stop"`
	Icon        string   `json:"icon,omitempty"`
	Categories  []string `json:"categories,omitempty"`
}

ProgrammeItem is one EPG programme entry.

type RankingStepMeta

type RankingStepMeta struct {
	Key             string `json:"key"`
	Label           string `json:"label"`
	Hint            string `json:"hint,omitempty"`
	Editor          any    `json:"editor,omitempty"`
	DefaultPosition int    `json:"defaultPosition,omitempty"`
	Budget          any    `json:"budget,omitempty"`
}

RankingStepMeta describes a custom ranking step.

type RawRequest

type RawRequest struct {
	PluginID string            `json:"pluginId,omitempty"`
	Method   string            `json:"method,omitempty"`
	Path     string            `json:"path"`
	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"`
}

RawRequest is the low-level transport-agnostic request passed to Plugin.Dispatch.

type RawResponse

type RawResponse struct {
	Status     int               `json:"status"`
	Headers    map[string]string `json:"headers,omitempty"`
	Body       json.RawMessage   `json:"body,omitempty"`
	BinaryBody []byte            `json:"-"`
}

RawResponse is the low-level transport-agnostic response returned by Plugin.Dispatch.

type RecordedLog

type RecordedLog struct {
	Level   string
	Message string
	Attrs   map[string]any
}

RecordedLog is one log message recorded by MockHost.

type RemoteHostClient

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

RemoteHostClient implements Host by calling `/ether/plugin-host/*` on the Ether server authenticated with `X-Ether-Plugin-Credential`.

func NewRemoteHostClient

func NewRemoteHostClient(opts RemoteHostOptions) *RemoteHostClient

NewRemoteHostClient creates a RemoteHostClient.

func (*RemoteHostClient) CatalogGet

func (c *RemoteHostClient) CatalogGet(ctx context.Context, id string) (*CatalogTitleSummary, error)

CatalogGet fetches one title summary from the Ether catalog.

func (*RemoteHostClient) CatalogSearch

func (c *RemoteHostClient) CatalogSearch(
	ctx context.Context,
	query string,
	limit, offset int,
) ([]CatalogTitleSummary, error)

CatalogSearch searches the Ether catalog.

func (*RemoteHostClient) Fetch

Fetch performs an outbound HTTP request.

func (*RemoteHostClient) FoldersList

func (c *RemoteHostClient) FoldersList(_ context.Context, _, _ string) ([]FolderEntry, error)

FoldersList is only supported in hosted mode; sidecars access local folders directly.

func (*RemoteHostClient) FoldersStat

func (c *RemoteHostClient) FoldersStat(_ context.Context, _, _ string) (FolderEntry, error)

FoldersStat is only supported in hosted mode; sidecars access local folders directly.

func (*RemoteHostClient) KVDelete

func (c *RemoteHostClient) KVDelete(ctx context.Context, key string) error

KVDelete deletes a key from the plugin's KV namespace.

func (*RemoteHostClient) KVGet

func (c *RemoteHostClient) KVGet(ctx context.Context, key string) (string, bool, error)

KVGet reads a key from the plugin's KV namespace.

func (*RemoteHostClient) KVList

func (c *RemoteHostClient) KVList(ctx context.Context, prefix string) ([]string, error)

KVList lists keys matching the given prefix in the plugin's KV namespace.

func (*RemoteHostClient) KVPut

func (c *RemoteHostClient) KVPut(ctx context.Context, key, value string) error

KVPut writes a key-value pair to the plugin's KV namespace.

func (*RemoteHostClient) Log

func (c *RemoteHostClient) Log(ctx context.Context, level, message string, attrs map[string]any) error

Log sends a structured log entry to Ether.

func (*RemoteHostClient) NotifyOwner

func (c *RemoteHostClient) NotifyOwner(ctx context.Context, text string) error

NotifyOwner sends an owner notification through Ether.

func (*RemoteHostClient) SecretGet

func (c *RemoteHostClient) SecretGet(_ context.Context, _ string) (string, error)

SecretGet is only available in hosted mode; remote plugins receive secrets via /ether/configure.

func (*RemoteHostClient) SetWatchState

func (c *RemoteHostClient) SetWatchState(
	ctx context.Context,
	viewerID int64,
	titleID string,
	watched bool,
) error

SetWatchState updates the watch state for a granted viewer.

func (*RemoteHostClient) SettingsGet

func (c *RemoteHostClient) SettingsGet(ctx context.Context) (map[string]any, error)

SettingsGet reads the current non-secret settings from Ether.

func (*RemoteHostClient) UpsertCollection

func (c *RemoteHostClient) UpsertCollection(ctx context.Context, collection map[string]any) error

UpsertCollection creates or updates a plugin-managed collection.

func (*RemoteHostClient) ViewerHistory

func (c *RemoteHostClient) ViewerHistory(
	ctx context.Context,
	viewerID int64,
	limit, offset int,
) ([]ViewerWatchEntry, error)

ViewerHistory reads watch history for a granted viewer.

type RemoteHostOptions

type RemoteHostOptions struct {
	BaseURL    string
	Credential string
	HTTPClient *http.Client
}

RemoteHostOptions configures a RemoteHostClient for sidecar plugins.

type RouteError

type RouteError struct {
	Status  int
	Code    string
	Message string
}

RouteError represents a structured HTTP error returned by a plugin handler.

func NewRouteError

func NewRouteError(status int, code, message string) *RouteError

NewRouteError constructs a structured RouteError.

func (*RouteError) Error

func (e *RouteError) Error() string

type Routes

type Routes struct {
	Catalog          func(ctx *Context, req CatalogRequest) (CatalogResponse, error)
	Meta             func(ctx *Context, req MetaRequest) (MetaResponse, error)
	Stream           func(ctx *Context, req StreamRequest) (StreamResponse, error)
	OpenStream       func(ctx *Context, req OpenStreamRequest) (OpenStreamResponse, error)
	Subtitles        func(ctx *Context, req SubtitlesRequest) (SubtitlesResponse, error)
	SubtitleDownload func(ctx *Context, req SubtitleDownloadRequest) (SubtitleDownloadResponse, error)
	Markers          func(ctx *Context, req MarkersRequest) (MarkersResponse, error)
	Channels         func(ctx *Context) (ChannelsResponse, error)
	Guide            func(ctx *Context, req GuideRequest) (GuideResponse, error)
	Configure        func(ctx *Context, settings map[string]any) (ConfigureResponse, error)
	Test             func(ctx *Context) (TestResponse, error)
	Options          func(ctx *Context, field string) ([]FieldOption, error)
	Health           func(ctx *Context) (HealthResponse, error)
	Notify           func(ctx *Context, req NotifyRequest) (NotifyResponse, error)
	Event            func(ctx *Context, events []EtherEvent) (EventResponse, error)
	View             func(ctx *Context, req ViewRequest) (ViewResponse, error)
	Action           func(ctx *Context, req ActionRequest) (ActionResponse, error)
	Tool             func(ctx *Context, req ToolRequest) (ToolResponse, error)
	Job              func(ctx *Context, req JobRequest) (JobResponse, error)
	File             func(ctx *Context, req FileRequest) (FileRangeResponse, error)
	RankKey          func(candidate CandidateFacts, config map[string]any) int64
	CondMatch        func(candidate CandidateFacts, operator string, value any) bool
}

Routes holds the capability handlers for a Plugin.

type RuleConditionMeta

type RuleConditionMeta struct {
	Key       string   `json:"key"`
	Label     string   `json:"label"`
	Operators []string `json:"operators,omitempty"`
	Editor    any      `json:"editor,omitempty"`
}

RuleConditionMeta describes a custom rule condition.

type RuntimeDecl

type RuntimeDecl struct {
	Kind   string `json:"kind"`
	Entry  string `json:"entry,omitempty"`
	Module string `json:"module,omitempty"`
}

RuntimeDecl declares how the plugin is executed.

type ScheduleEntry

type ScheduleEntry struct {
	Every string `json:"every"`
	Call  string `json:"call"`
}

ScheduleEntry declares a scheduled background job.

type ServeHandle

type ServeHandle struct {
	// Done closes when the tunnel disconnects. It is nil for HTTP servers.
	Done  <-chan struct{}
	Mode  string
	URL   string
	Port  int
	Close func() error
}

ServeHandle represents a running HTTP or tunnel sidecar session.

type ServeOptions

type ServeOptions struct {
	Mode       string
	Host       string
	Port       int
	TunnelURL  string
	Credential string
}

ServeOptions configures how Plugin.Serve runs in sidecar mode.

type SettingField

type SettingField struct {
	Key         string         `json:"key"`
	Kind        string         `json:"kind"`
	Label       string         `json:"label,omitempty"`
	Hint        string         `json:"hint,omitempty"`
	Required    bool           `json:"required,omitempty"`
	Default     any            `json:"default,omitempty"`
	Options     []FieldOption  `json:"options,omitempty"`
	Fields      []SettingField `json:"fields,omitempty"`
	Min         *float64       `json:"min,omitempty"`
	Max         *float64       `json:"max,omitempty"`
	Placeholder string         `json:"placeholder,omitempty"`
}

SettingField describes one leaf or group setting field.

func CollectSettingFields

func CollectSettingFields(schema *SettingsSchema) []SettingField

CollectSettingFields returns all leaf SettingFields from a SettingsSchema.

type SettingsGroup

type SettingsGroup struct {
	Key      string         `json:"key,omitempty"`
	Label    string         `json:"label,omitempty"`
	Hint     string         `json:"hint,omitempty"`
	Advanced bool           `json:"advanced,omitempty"`
	Fields   []SettingField `json:"fields"`
}

SettingsGroup groups related settings fields.

type SettingsSchema

type SettingsSchema struct {
	Ref    string          `json:"$ref,omitempty"`
	Fields []SettingField  `json:"fields,omitempty"`
	Groups []SettingsGroup `json:"groups,omitempty"`
}

SettingsSchema describes a plugin's configuration fields.

type SlotMeta

type SlotMeta struct {
	Slot  string `json:"slot"`
	Key   string `json:"key"`
	Label string `json:"label"`
	Route string `json:"route"`
}

SlotMeta describes a UI slot contributed by a plugin.

type SourceMeta

type SourceMeta struct {
	Class     string         `json:"class"`
	Abilities []string       `json:"abilities,omitempty"`
	Limits    map[string]any `json:"limits,omitempty"`
}

SourceMeta describes a stream source contribution.

type StreamEtherExt

type StreamEtherExt struct {
	ID          string   `json:"id,omitempty"`
	ReleaseName string   `json:"releaseName,omitempty"`
	Size        int64    `json:"size,omitempty"`
	Languages   []string `json:"languages,omitempty"`
	Lazy        bool     `json:"lazy,omitempty"`
	File        string   `json:"file,omitempty"`
}

StreamEtherExt holds Ether-specific extensions on a StreamItem.

type StreamItem

type StreamItem struct {
	Name        string          `json:"name,omitempty"`
	Title       string          `json:"title,omitempty"`
	Description string          `json:"description,omitempty"`
	URL         string          `json:"url,omitempty"`
	InfoHash    string          `json:"infoHash,omitempty"`
	FileIdx     *int            `json:"fileIdx,omitempty"`
	YtID        string          `json:"ytId,omitempty"`
	ExternalURL string          `json:"externalUrl,omitempty"`
	Ether       *StreamEtherExt `json:"ether,omitempty"`
}

StreamItem is one playable candidate returned by a Stream route handler.

type StreamRequest

type StreamRequest struct {
	Type  string            `json:"type"`
	ID    string            `json:"id"`
	Extra map[string]string `json:"extra"`
}

StreamRequest is passed to a Stream route handler.

type StreamResponse

type StreamResponse struct {
	Streams []StreamItem `json:"streams"`
}

StreamResponse is returned by a Stream route handler.

type StremioCatalogDecl

type StremioCatalogDecl struct {
	Type  string              `json:"type"`
	ID    string              `json:"id"`
	Name  string              `json:"name,omitempty"`
	Extra []StremioExtraField `json:"extra,omitempty"`
}

StremioCatalogDecl declares a Stremio catalog in the manifest.

type StremioExtraField

type StremioExtraField struct {
	Name         string   `json:"name"`
	IsRequired   bool     `json:"isRequired,omitempty"`
	Options      []string `json:"options,omitempty"`
	OptionsLimit int      `json:"optionsLimit,omitempty"`
}

StremioExtraField declares a supported extra parameter on a catalog.

type StringsCatalog

type StringsCatalog map[string]map[string]string

StringsCatalog maps locale codes (e.g. "en", "fr-CA") to key-value tables.

type SubtitleDownloadRequest

type SubtitleDownloadRequest struct {
	ID     string `json:"id"`
	Lang   string `json:"lang"`
	Format string `json:"format"`
}

SubtitleDownloadRequest identifies a viewer-picked subtitle.

type SubtitleDownloadResponse

type SubtitleDownloadResponse struct {
	Format   string `json:"format"`
	Encoding string `json:"encoding"`
	Data     string `json:"data"`
}

SubtitleDownloadResponse carries subtitle text or base64-encoded bytes.

type SubtitleItem

type SubtitleItem struct {
	ID              string `json:"id"`
	URL             string `json:"url,omitempty"`
	Name            string `json:"name,omitempty"`
	Lang            string `json:"lang"`
	Label           string `json:"label,omitempty"`
	Format          string `json:"format,omitempty"`
	HearingImpaired bool   `json:"hearingImpaired,omitempty"`
}

SubtitleItem is one subtitle track returned by a Subtitles route handler.

type SubtitlesMeta

type SubtitlesMeta struct {
	Languages any      `json:"languages,omitempty"`
	Formats   []string `json:"formats,omitempty"`
}

SubtitlesMeta describes a subtitle provider contribution.

type SubtitlesRequest

type SubtitlesRequest struct {
	Type      string            `json:"type"`
	ID        string            `json:"id"`
	Extra     map[string]string `json:"extra"`
	PickToken string            `json:"pickToken"`
	VideoHash string            `json:"videoHash,omitempty"`
	VideoSize int64             `json:"videoSize,omitempty"`
	Filename  string            `json:"filename,omitempty"`
}

SubtitlesRequest is passed to a Subtitles route handler.

type SubtitlesResponse

type SubtitlesResponse struct {
	Subtitles []SubtitleItem `json:"subtitles"`
}

SubtitlesResponse is returned by a Subtitles route handler.

type TemplateOptions

type TemplateOptions struct {
	ID          string
	Name        string
	Version     string
	Summary     string
	Description string
}

TemplateOptions configures a capability starter template.

type TestHarness

type TestHarness struct {
	Plugin *Plugin
	Host   *MockHost
}

TestHarness wraps a Plugin and MockHost for ergonomic unit tests.

func NewTestHarness

func NewTestHarness(p *Plugin, host *MockHost) *TestHarness

NewTestHarness constructs a TestHarness for p.

func (*TestHarness) Action

func (h *TestHarness) Action(action string, input map[string]any) (int, ActionResponse, error)

Action calls POST /ether/action/{action}.

func (*TestHarness) Catalog

func (h *TestHarness) Catalog(typ, id string, extra map[string]string) (int, CatalogResponse, error)

Catalog calls GET /catalog/{type}/{id}[/{extra}].json.

func (*TestHarness) Configure

func (h *TestHarness) Configure(settings map[string]any) (int, ConfigureResponse, error)

Configure calls POST /ether/configure.

func (*TestHarness) Event

func (h *TestHarness) Event(events []EtherEvent) (int, EventResponse, error)

Event calls POST /ether/event.

func (*TestHarness) File

func (h *TestHarness) File(path, rangeHeader string) RawResponse

File calls GET /ether/file/{path}.

func (*TestHarness) Health

func (h *TestHarness) Health() (int, HealthResponse, error)

Health calls GET /ether/health.

func (*TestHarness) Manifest

func (h *TestHarness) Manifest() (Manifest, error)

Manifest fetches and decodes GET /manifest.json.

func (*TestHarness) Markers

func (h *TestHarness) Markers(typ, id string) (int, MarkersResponse, error)

Markers calls GET /ether/markers/{type}/{id}.json.

func (*TestHarness) Meta

func (h *TestHarness) Meta(typ, id string) (int, MetaResponse, error)

Meta calls GET /meta/{type}/{id}.json.

func (*TestHarness) Options

func (h *TestHarness) Options(field string) (int, []FieldOption, error)

Options calls GET /ether/options/{field}.

func (*TestHarness) Request

func (h *TestHarness) Request(req RawRequest) RawResponse

Request dispatches a RawRequest against the plugin.

func (*TestHarness) Stream

func (h *TestHarness) Stream(typ, id string, extra map[string]string) (int, StreamResponse, error)

Stream calls GET /stream/{type}/{id}[/{extra}].json.

func (*TestHarness) Subtitles

func (h *TestHarness) Subtitles(typ, id, pickToken string, extra map[string]string) (int, SubtitlesResponse, RawResponse)

Subtitles calls GET /subtitles/{type}/{id}[/{extra}].json with optional pickToken.

func (*TestHarness) Test

func (h *TestHarness) Test() (int, TestResponse, error)

Test calls POST /ether/test.

func (*TestHarness) Tool

func (h *TestHarness) Tool(name string, input map[string]any) (int, ToolResponse, error)

Tool calls POST /ether/tool/{name}.

func (*TestHarness) View

func (h *TestHarness) View(page string, query map[string]string) (int, ViewResponse, error)

View calls GET /ether/view/{page} and validates the returned ViewSpecDocument.

type TestResponse

type TestResponse struct {
	OK      bool     `json:"ok"`
	Message string   `json:"message,omitempty"`
	Details []string `json:"details,omitempty"`
}

TestResponse is returned by a Test route handler.

type ToolMeta

type ToolMeta struct {
	Name        string         `json:"name"`
	Title       string         `json:"title"`
	Description string         `json:"description"`
	InputSchema map[string]any `json:"inputSchema"`
	ReadOnly    bool           `json:"readOnly,omitempty"`
	Destructive bool           `json:"destructive,omitempty"`
	OpenWorld   bool           `json:"openWorld,omitempty"`
}

ToolMeta describes an agent tool contributed by a plugin.

type ToolRequest

type ToolRequest struct {
	Name  string         `json:"name"`
	Input map[string]any `json:"input"`
}

ToolRequest is passed to a Tool route handler.

type ToolResponse

type ToolResponse map[string]any

ToolResponse is returned by a Tool route handler.

type TunnelError

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

TunnelError carries an error payload inside a TunnelFrame.

type TunnelFrame

type TunnelFrame struct {
	Type          string              `json:"type"`
	ID            string              `json:"id,omitempty"`
	RequestID     string              `json:"requestId,omitempty"`
	Protocol      string              `json:"protocol,omitempty"`
	Plugin        string              `json:"plugin,omitempty"`
	PluginID      string              `json:"pluginId,omitempty"`
	ConnectionID  string              `json:"connectionId,omitempty"`
	Features      []string            `json:"features,omitempty"`
	MaxChunkBytes int                 `json:"maxChunkBytes,omitempty"`
	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          string              `json:"body,omitempty"`
	Data          string              `json:"data,omitempty"`
	Status        int                 `json:"status,omitempty"`
	Deadline      string              `json:"deadline,omitempty"`
	Error         *TunnelError        `json:"error,omitempty"`
}

TunnelFrame is one JSON message sent or received over the `ether-tunnel-v1` WebSocket.

type ViewRequest

type ViewRequest struct {
	Page  string            `json:"page"`
	Query map[string]string `json:"query"`
}

ViewRequest is passed to a View route handler.

type ViewResponse

type ViewResponse struct {
	Spec ViewSpecDocument `json:"spec"`
	Data map[string]any   `json:"data"`
}

ViewResponse is returned by a View route handler.

type ViewSpecDocument

type ViewSpecDocument struct {
	SpecVersion int              `json:"specVersion"`
	Layout      string           `json:"layout"`
	Route       string           `json:"route,omitempty"`
	Header      []map[string]any `json:"header"`
	Body        []map[string]any `json:"body"`
}

ViewSpecDocument is a declarative ViewSpec v1 page specification.

type ViewerPermissions

type ViewerPermissions struct {
	Identity        string `json:"identity,omitempty"`
	WatchHistory    string `json:"watch_history,omitempty"`
	WriteWatchState string `json:"write_watch_state,omitempty"`
}

ViewerPermissions scopes viewer identity and watch-history access.

type ViewerWatchEntry

type ViewerWatchEntry struct {
	TitleID   string `json:"titleId"`
	Title     string `json:"title,omitempty"`
	WatchedAt string `json:"watchedAt,omitempty"`
	Completed bool   `json:"completed,omitempty"`
}

ViewerWatchEntry is one watch-history entry returned by Host.ViewerHistory.

Jump to

Keyboard shortcuts

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