El seam de plugins en TypeScript, su ciclo de vida, la precedencia explícita y el contrato SeekableMediaSource de las fuentes.
Implementado en parte. El seam de plugins en TypeScript (
@styx/plugin-sdk) y los tres módulos propios existen. Lo que no existe todavía es la aplicación de permisos, la negociación de versiones y el aislamiento: están declarados y se aplican entrack/plugins-sdk. El estado de los gates detrack/plugin-seamsestá en su vista del roadmap.
| Nivel | Estado |
|---|---|
TypeScript (plugin-sdk) | Vivo hoy. Los plugins corren dentro del servicio que los registra |
| Nativo (C ABI) | Objetivo. protocols/plugin-abi/ no se implementa hasta definir el modelo de confianza |
Un plugin nunca lee bytes de vídeo: los bytes los lee el daemon (regla r04/r48).
@styx/plugin-sdk define cuatro puntos de extensión (PluginKind), cada uno con su contrato en un
único mapa, de modo que no puede registrarse un tipo de plugin sin interfaz:
| Tipo | Contrato | Consumidor | Qué hace |
|---|---|---|---|
metadata | IMetadataProvider | catalog-svc | Enriquece los metadatos de un asset ya indexado |
search | ISearchProvider | catalog-svc | Busca en fuentes externas |
source | ISourceProvider | sources-svc | Resuelve un URI a un adaptador de fuente |
seed | ISeedProvider | catalog-svc | Siembra un catálogo de demostración al arrancar |
Módulos propios incluidos: @styx/plugin-demo-open-cinema (siembra), @styx/plugin-source-local
(fuente de ficheros locales) y @styx/plugin-metadata-local-nfo (metadatos desde ficheros .nfo).
Cada servicio con plugins instancia su registro estático en src/service/plugins/registry.ts;
añadir un proveedor es añadirlo al registro del servicio, sin tocar el seam. Una decisión posterior
(dec-0114) añade el escaneo e identificación por contenido como un plugin más sobre este seam.
El manifiesto describe qué es el plugin y qué pediría, pero hoy nadie lo aplica. Lo declarado:
builtin, official, trusted-native, sandboxed, remote y
community. dec-0117 ya fija una consecuencia: sólo los tres primeros pueden ejecutar código
dentro del proceso del daemon.local-authoritative o derived. Es entrada de la precedencia: un .nfo
escrito por el usuario gana a un dato derivado.fs:read, fs:write, net:outbound, secrets:own, bus:publish,
bus:subscribe): documentación estructurada; declararlos no concede nada y omitirlos no impide
nada.Entre varios proveedores del mismo tipo, el orden no lo decide el orden de importación. La cadena es: bloqueo manual, después autoridad local, después el orden de proveedores configurado, después el desempate por id. Un bloqueo hacia un plugin inexistente o que no cubre ese tipo es un error de construcción: se falla en el arranque en lugar de elegir en silencio a otro.
Dos máquinas de estados separadas:
registered, initializing, active, stopping, stopped. Un fallo de
initialize() lleva a stopped; el porqué vive en la salud. La inicialización tiene un plazo.healthy, degraded, unavailable, failed, misconfigured y disabled. Los
estados observados los mueve una sonda libremente; los latcheados (failed,
misconfigured) se abandonan siempre pasando por unavailable, nunca saltando a healthy; y
disabled es administrativo. Sirven tráfico healthy y degraded: un proveedor caído no debe
impedir arrancar el catálogo.SeekableMediaSourceToda fuente de medios (local, HTTP con rangos, S3, WebDAV, SFTP, torrent, Jellyfin, Xtream o
compuesta) se normaliza a la interfaz ISeekableMediaSource de @styx/source-sdk (decisión r04):
probe, playback, seek, trick-play, subtitle,
background-cache) que afecta a prioridad, precarga y expulsión;cancel(requestId)), no global;La misma abstracción existe en Zig dentro del daemon (media-core/source), y los códigos de error
de la fuente se generan una vez y se comparten entre ambos lados. Sin FUSE en el camino caliente:
el almacenamiento remoto va por su API nativa.