feat(plugins): add JavaScript plugin system with overlay panel

- Load plugins from <config dir>/plugins/<id>/ when enabled under `plugins` in config
- Expose ctx with mpv events/commands, timers, subtitle context, actions, notify, exec, and panel
- Bind plugin actions via `__plugin-action:<id>/<action>` keybindings (runPluginAction session action)
- Add plugin-panel modal with markdown rendering; closing aborts the panel signal
- Add ai-explain example plugin that queries `codex exec` for the current line
- Add e2e harness `files` option and plugin e2e scenario; document plugins in docs-site and internal docs
This commit is contained in:
sudacode committed 2026-10-26 21:38:51 -07:00
1 parent d3a94536a8
commit ca534cd232
65 files changed
+2555 -39

No files matched your search

+14 -2
View File
@@ -386,6 +386,13 @@ export interface ConfigHotReloadPayload {
secondarySubMode: SecondarySubMode;
}
/** Content of the shared plugin panel. `panelId` changes each time a plugin opens a new panel. */
export interface PluginPanelSnapshot {
panelId: number;
title: string;
markdown: string;
}
export interface SessionActionDispatchRequest {
actionId: SessionActionId;
payload?: SessionActionPayload;
@@ -536,6 +543,9 @@ export interface ElectronAPI {
onOpenSessionHelp: (callback: (payload: SessionHelpOpenPayload) => void) => void;
onOpenChangelog: (callback: () => void) => void;
getChangelogSnapshot: (options?: { refresh?: boolean }) => Promise<ChangelogSnapshot>;
onOpenPluginPanel: (callback: (snapshot: PluginPanelSnapshot) => void) => void;
onPluginPanelUpdate: (callback: (snapshot: PluginPanelSnapshot) => void) => void;
onPluginPanelClose: (callback: (panelId: number) => void) => void;
onOpenControllerSelect: (callback: () => void) => void;
onOpenControllerDebug: (callback: () => void) => void;
onOpenJimaku: (callback: () => void) => void;
@@ -613,7 +623,8 @@ export interface ElectronAPI {
| 'subtitle-sidebar'
| 'session-help'
| 'character-dictionary'
| 'changelog',
| 'changelog'
| 'plugin-panel',
) => void;
notifyOverlayModalOpened: (
modal:
@@ -632,7 +643,8 @@ export interface ElectronAPI {
| 'subtitle-sidebar'
| 'session-help'
| 'character-dictionary'
| 'changelog',
| 'changelog'
| 'plugin-panel',
) => void;
reportOverlayContentBounds: (measurement: OverlayContentMeasurement) => void;
onSessionBindingsChanged: (callback: (bindings: CompiledSessionBinding[]) => void) => void;