@vestra-player/sdk 1.5.55 → 1.5.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/docs-tree.json.gz +0 -0
- package/dist/plugin/appearance.js +49 -2
- package/dist/plugin/resolvers.js +29 -4
- package/dist/plugin/types.d.ts +79 -36
- package/llms.txt +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.58
|
|
4
|
+
|
|
5
|
+
**Who must change: nobody.** Documentation only: no change to the TypeScript API, the wire or `TestHost`, `apiVersion` stays `vestra/1`, no new capability, no player version needed. Plugin authors should read what the player's new plugin supervisor does with their plugin (player 0.6.6, and the defaults planned for 0.6.7), and check that `activate` never waits for its own commands or views.
|
|
6
|
+
|
|
7
|
+
- **The plugin supervisor, as a plugin sees it** ([How the player runs and talks to plugins](docs/explanation/host-and-node.md), [How a plugin runs](docs/explanation/plugins.md)). Player 0.6.6: a failed start is tried up to three more times; a built-in that crashes starts again by itself after 3 s, 6 s…; the fifth crash within 10 minutes stops a plugin until it is reloaded; an own process's JavaScript heap is capped at 512 MB (V8's heap only, not `Buffer` contents or addons), and passing it ends the process with "<name> ran out of memory"; a process that ended by itself gets no `runtime.stop`; without on-demand start a third-party plugin is listed as failed on its first crash, as before; at quit every plugin is stopped at once with 1 s in all; and two processes of one plugin never use its data directory at the same time. With on-demand start (lazy activation, `VESTRA_LAZY=1` in 0.6.6): a crashed plugin keeps its entries, shown disabled with the reason during a pause of 1 s, 2 s, 4 s…, and starts again on its next use (a resident plugin by itself); third-party plugins start a few at a time, clicks first; every start holds its clicks, resolutions, drops and view callbacks until `runtime.ready` (so an `activate` that awaits its own command or view callback waits until the start timeout); at most 64 are held per plugin, and one that cannot be taken is answered ("<name> is busy", "… could not start", "… is disabled") instead of dropped; busy work (a `busy` command, a dialog, a settings page shown, a resolution) keeps a plugin running with no time limit, and its idle time counts from when the work ends. Planned for player 0.6.7: on-demand start for everyone; a process budget for the machine's memory and the system's memory pressure put idle plugins in standby early, with the stop reason `idle`; idle time 30 s, start timeout 60 s, 5 s grace for a disable, uninstall, reload, upgrade or standby, a 5-minute cap on a player request awaiting the plugin's reply (a resolution; declared busy work stays uncapped), and a resident plugin never goes to standby. The source excerpts of host code that no longer exists (the lazy-activation trigger list, the 15-second activation record, the 250 ms idle poll, the stop's 5 ms poll) are replaced by descriptions of the current behaviour.
|
|
8
|
+
- **[Reference: limits › Plugin processes](docs/reference/limits.md#plugin-processes)**: heap cap, start timeout, retries, start limit, restart pauses, stop graces, quit, idle time, request timeout, start slots (`min(4, max(2, cores / 2))` plus a reserve for clicks), held triggers (64), waiting starts (256), the process budget (`clamp(physical MiB / 2 × 0.30 / 85, 3, 16)`) and the memory pressure thresholds (both planned for 0.6.7), for player 0.6.6 and as planned for 0.6.7.
|
|
9
|
+
- **`StopReason`** lists when each reason comes with the supervisor: `quit` also after a lost GPU device, `disable` clears session storage, `idle` also for the process budget and memory pressure (planned for 0.6.7; never for a busy plugin), `failed` also for a start timeout (possibly while `activate` runs) and, planned for 0.6.7, an unanswered request; a crash or running out of memory is no stop at all. The stop reasons are no longer described as planned: they shipped in player 0.6.4. **`PluginInfo.process`** `"idle"` also covers the pause after a crash before a plugin starts again. `Plugin`, `DisposeInfo` and [Store a plugin's data](docs/how-to/store-data.md) give the new stop graces.
|
|
10
|
+
- **`appearance.changed` says what changed** (player 0.6.6): `"changed": ["theme"]` or `["language"]` beside `theme` and `language`. This SDK does not read it yet; a later release uses it so that a plugin woken by a language change no longer hears its unchanged theme once.
|
|
11
|
+
|
|
12
|
+
## 1.5.57
|
|
13
|
+
|
|
14
|
+
**Who must change: nobody.** The first npm release with 1.5.56's fix: no change to the TypeScript API or the wire, `apiVersion` stays `vestra/1`, no new capability, no player version needed.
|
|
15
|
+
|
|
16
|
+
- **1.5.56 never reached npm.** Its tag was pushed, but the release run (41502365359) skipped `publish` because GitHub never gave its two macOS jobs a hosted runner (capacity) and they were cancelled. 1.5.57 publishes the same code: `appearance.onChange` and `resolvers.onFileTypesChange` hear a change the player woke the plugin for, and the session-storage clearing docs, as described under [1.5.56](#1556). Install 1.5.57; there is no `@vestra-player/sdk@1.5.56` on npm.
|
|
17
|
+
- _Release process_: runner capacity no longer blocks a release (product-owner ruling, 2026-11-02). `release.yml` publishes once `verify`, `static`, `build`, `docs` and the Ubuntu and Windows tests and examples pass; macOS tests and examples still run on every release as `test-macos`, beside `publish` and without gating it. `_test.yml` takes an `os` input (a JSON array of runner labels, all three by default), so pull requests and `main` still test and gate on Ubuntu, Windows and macOS as before. [Maintaining › Releasing](docs/maintaining.md#releasing) says so.
|
|
18
|
+
|
|
19
|
+
## 1.5.56
|
|
20
|
+
|
|
21
|
+
**Who must change: nobody.** A fix: no change to the TypeScript API or the wire, `apiVersion` stays `vestra/1`, no new capability, no player version needed.
|
|
22
|
+
|
|
23
|
+
- **`appearance.onChange` and `resolvers.onFileTypesChange` hear a change the player woke the plugin for.** A plugin the player stopped and starts again to deliver a palette or file-type change ([Idle plugins are stopped](docs/explanation/plugins.md#idle-plugins-are-stopped)) read the new value with `window.state` at start; the held `appearance.changed` or `resolvers.fileTypes` that followed compared equal to it, so the listeners never ran. The SDK now compares an event with what the listeners last heard, not with the value read at start: they hear the change once, and the same value again is still not a change. The player sends `resolvers.fileTypes` only when the list changed. It sends `appearance.changed` when the theme or the language changed, both values each time; an event whose language differs from the last one the SDK saw is a language change, and as before does not call `onChange` unless the theme differs too (also for the echo of the plugin's own `setLanguage`). One case remains: a plugin the player woke for a language change alone cannot tell it from a theme change, since the event does not say what changed, and its `onChange` may hear the unchanged theme once. A field naming the change could be added to the event later without breaking anything. `appearance.theme`, `resolvers.fileTypes` and views read the same values as before. `packages.onChange` and `bindings.onChange` (the other two events that wake a plugin) never compared, and are unchanged.
|
|
24
|
+
- _Docs_: when session storage is cleared, corrected against the player: also when a store or another plugin with `plugins.manage` disables the plugin (`packages.setEnabled(id, false)`, or an update installed with `enabled: false`, player 0.6.4), and when an earlier installation kept for a later reinstall (after a `replace`) is dropped because the player keeps only so many; [How a plugin runs › Stopping](docs/explanation/plugins.md#stopping) names other plugins with `plugins.manage` too. `SessionStorage`, [How a plugin runs › Restarts](docs/explanation/plugins.md#restarts-activate-can-run-more-than-once) and [Store a plugin's data](docs/how-to/store-data.md) say so. `Appearance.onChange` and `Resolvers.onFileTypesChange` describe the wake.
|
|
25
|
+
|
|
3
26
|
## 1.5.55
|
|
4
27
|
|
|
5
28
|
**Who must change: nobody, but check `TestHost` tests that update a disabled plugin.** Additive: `InstallOptions` gains `enabled` and `TestHost` gains `installKeepsDisabled`, `apiVersion` stays `vestra/1`, no new capability, and existing code still compiles. Older players ignore the option, and an install there always enables the plugin. One `TestHost` behaviour change at run time: like player 0.6.4, it now keeps a `disabled` entry disabled when the plugin under test installs an update or reinstall over it without `enabled`, where it used to make it `running`. A test that expects the update to run (the player's Store test did) sets `host.installKeepsDisabled = false` to keep playing players up to 0.6.3, or asserts the new rule; a test that covers both runs once with each.
|
package/dist/docs-tree.json.gz
CHANGED
|
Binary file
|
|
@@ -18,12 +18,34 @@ class AppearanceService {
|
|
|
18
18
|
/** The saved interface language (the next start's). */
|
|
19
19
|
language;
|
|
20
20
|
#listeners = new Set();
|
|
21
|
+
/**
|
|
22
|
+
* The theme listeners last heard (or the last event's), not the one read
|
|
23
|
+
* at start: a plugin woken from standby reads the new theme from
|
|
24
|
+
* `window.state`, then gets the `appearance.changed` the player held for
|
|
25
|
+
* it, and its listeners still hear that change. Left unset until the
|
|
26
|
+
* first event on purpose: set from the start-up read, it would hide that
|
|
27
|
+
* held change again.
|
|
28
|
+
*/
|
|
29
|
+
#notified;
|
|
30
|
+
/**
|
|
31
|
+
* The language as the start-up read and later events carried it (not
|
|
32
|
+
* `language`, which the plugin's own `setLanguage` changes before its
|
|
33
|
+
* echo arrives). The player sends `appearance.changed` once per change
|
|
34
|
+
* of the theme or of the language, each with both values: an event whose
|
|
35
|
+
* language differs from this one is a language change, and its theme is
|
|
36
|
+
* compared with `theme` as before. Only a newest event that repeats the
|
|
37
|
+
* start-up language is taken for a theme change; a plugin woken for a
|
|
38
|
+
* language change gets that too, so its listeners may hear the unchanged
|
|
39
|
+
* theme once (the event does not say what changed).
|
|
40
|
+
*/
|
|
41
|
+
#eventLanguage;
|
|
21
42
|
#started = false;
|
|
22
43
|
constructor(runtime) {
|
|
23
44
|
this.#runtime = runtime;
|
|
24
45
|
this.theme =
|
|
25
46
|
windowOf(runtime).appearance ?? "vestra";
|
|
26
47
|
this.language = preference(windowOf(runtime).language) ?? "system";
|
|
48
|
+
this.#eventLanguage = this.language;
|
|
27
49
|
}
|
|
28
50
|
start() {
|
|
29
51
|
if (this.#started)
|
|
@@ -33,22 +55,47 @@ class AppearanceService {
|
|
|
33
55
|
this.#runtime.on("appearance.changed", (data) => {
|
|
34
56
|
const event = data;
|
|
35
57
|
const language = preference(event?.language);
|
|
58
|
+
// Older players send no language: their events are theme changes.
|
|
59
|
+
const languageChanged = language !== undefined && language !== this.#eventLanguage;
|
|
60
|
+
if (language)
|
|
61
|
+
this.#eventLanguage = language;
|
|
36
62
|
if (language && language !== this.language) {
|
|
37
63
|
this.language = language;
|
|
38
64
|
this.#runtime.invalidate();
|
|
39
65
|
}
|
|
40
66
|
const theme = event?.theme;
|
|
41
|
-
if (theme
|
|
67
|
+
if (!theme || !THEMES.includes(theme))
|
|
68
|
+
return;
|
|
69
|
+
if (languageChanged) {
|
|
70
|
+
// The theme came along unchanged (or this plugin set it already).
|
|
42
71
|
this.accept(theme);
|
|
72
|
+
this.#notified = theme;
|
|
73
|
+
}
|
|
74
|
+
else
|
|
75
|
+
this.changed(theme);
|
|
43
76
|
}, "events", true);
|
|
44
77
|
}
|
|
78
|
+
/** A theme change event: listeners hear it unless they already did. */
|
|
79
|
+
changed(theme) {
|
|
80
|
+
const changed = theme !== this.theme;
|
|
81
|
+
this.theme = theme;
|
|
82
|
+
if (theme !== this.#notified)
|
|
83
|
+
this.#notify(theme);
|
|
84
|
+
if (changed)
|
|
85
|
+
this.#runtime.invalidate();
|
|
86
|
+
}
|
|
87
|
+
/** After this plugin's own `set`: only a change from the current theme. */
|
|
45
88
|
accept(theme) {
|
|
46
89
|
if (theme === this.theme)
|
|
47
90
|
return;
|
|
48
91
|
this.theme = theme;
|
|
92
|
+
this.#notify(theme);
|
|
93
|
+
this.#runtime.invalidate();
|
|
94
|
+
}
|
|
95
|
+
#notify(theme) {
|
|
96
|
+
this.#notified = theme;
|
|
49
97
|
for (const listener of [...this.#listeners])
|
|
50
98
|
listener(theme);
|
|
51
|
-
this.#runtime.invalidate();
|
|
52
99
|
}
|
|
53
100
|
watch(listener) {
|
|
54
101
|
this.#listeners.add(listener);
|
package/dist/plugin/resolvers.js
CHANGED
|
@@ -17,6 +17,14 @@ class FileTypesService {
|
|
|
17
17
|
#runtime;
|
|
18
18
|
types;
|
|
19
19
|
#listeners = new Set();
|
|
20
|
+
/**
|
|
21
|
+
* The list listeners last heard, not the one read at start: a plugin
|
|
22
|
+
* woken from standby reads the new list from `window.state`, then gets
|
|
23
|
+
* the `resolvers.fileTypes` the player held for it, and its listeners
|
|
24
|
+
* still hear that change. The player sends the event only when the list
|
|
25
|
+
* changed, so a first event is always news to the listeners.
|
|
26
|
+
*/
|
|
27
|
+
#notified;
|
|
20
28
|
#started = false;
|
|
21
29
|
constructor(runtime) {
|
|
22
30
|
this.#runtime = runtime;
|
|
@@ -30,7 +38,7 @@ class FileTypesService {
|
|
|
30
38
|
this.#runtime.on("resolvers.fileTypes", (data) => {
|
|
31
39
|
const types = data?.fileTypes;
|
|
32
40
|
if (Array.isArray(types) && types.every((t) => typeof t === "string"))
|
|
33
|
-
this.
|
|
41
|
+
this.changed(types);
|
|
34
42
|
}, "events", true);
|
|
35
43
|
// What changed between the start-up read and the subscription.
|
|
36
44
|
const window = windowOf(this.#runtime);
|
|
@@ -39,16 +47,33 @@ class FileTypesService {
|
|
|
39
47
|
this.accept(window.fileTypes, this.#runtime.can("events"));
|
|
40
48
|
});
|
|
41
49
|
}
|
|
42
|
-
/** `
|
|
50
|
+
/** From `resolvers.fileTypes`: listeners hear it unless they already did. */
|
|
51
|
+
changed(types) {
|
|
52
|
+
const changed = !sameTypes(types, this.types);
|
|
53
|
+
if (changed)
|
|
54
|
+
this.types = Object.freeze([...types]);
|
|
55
|
+
if (!this.#notified || !sameTypes(types, this.#notified))
|
|
56
|
+
this.#notify(types);
|
|
57
|
+
if (changed)
|
|
58
|
+
this.#runtime.invalidate();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* From a `window.state` read: only a change from the current list.
|
|
62
|
+
* `notify`: false without `events`, whose listeners never fire.
|
|
63
|
+
*/
|
|
43
64
|
accept(types, notify = true) {
|
|
44
65
|
if (sameTypes(types, this.types))
|
|
45
66
|
return;
|
|
46
67
|
this.types = Object.freeze([...types]);
|
|
47
68
|
if (notify)
|
|
48
|
-
|
|
49
|
-
listener([...types]);
|
|
69
|
+
this.#notify(types);
|
|
50
70
|
this.#runtime.invalidate();
|
|
51
71
|
}
|
|
72
|
+
#notify(types) {
|
|
73
|
+
this.#notified = Object.freeze([...types]);
|
|
74
|
+
for (const listener of [...this.#listeners])
|
|
75
|
+
listener([...types]);
|
|
76
|
+
}
|
|
52
77
|
watch(listener) {
|
|
53
78
|
this.#listeners.add(listener);
|
|
54
79
|
const held = this.#runtime.hold("resolvers.fileTypes");
|
package/dist/plugin/types.d.ts
CHANGED
|
@@ -524,8 +524,10 @@ export interface Scope extends Disposable {
|
|
|
524
524
|
* (menus, windows, panels, filters, subtitle layers, snapshots, jobs,
|
|
525
525
|
* resolvers, streams); pending requests then fail with `disabled` and the
|
|
526
526
|
* root scope is disposed for local cleanup (timers, signals, sockets). A
|
|
527
|
-
* process that has not exited after
|
|
528
|
-
*
|
|
527
|
+
* process that has not exited after its grace is killed: 300 ms in player
|
|
528
|
+
* 0.6.6 (2 s when it goes to standby), planned to be 5 s from player 0.6.7
|
|
529
|
+
* (300 ms after a fault); at quit all plugins together get 1 s. Media the
|
|
530
|
+
* plugin opened with {@link Player.open} keeps playing.
|
|
529
531
|
*
|
|
530
532
|
* @example Write a minimal plugin with one menu item
|
|
531
533
|
* Tools ▸ Say hello, or Ctrl+H, shows "Hello from" and the plugin's id.
|
|
@@ -575,8 +577,8 @@ export interface Plugin extends Scope {
|
|
|
575
577
|
*/
|
|
576
578
|
readonly dataDirectory: string;
|
|
577
579
|
/**
|
|
578
|
-
* Why the player stops this plugin (SDK 1.5.54
|
|
579
|
-
*
|
|
580
|
+
* Why the player stops this plugin (SDK 1.5.54, player 0.6.4): set when
|
|
581
|
+
* the stop begins, before any
|
|
580
582
|
* {@link Scope.onDispose} cleanup runs. `undefined` while the plugin
|
|
581
583
|
* runs, and for every stop by an older player (one whose own SDK is older
|
|
582
584
|
* than 1.5.54 does not have the property at all). See {@link StopReason}.
|
|
@@ -587,23 +589,40 @@ export interface Plugin extends Scope {
|
|
|
587
589
|
* Why the player stopped the plugin ({@link DisposeInfo.reason},
|
|
588
590
|
* {@link Plugin.stopReason}).
|
|
589
591
|
*
|
|
590
|
-
* - `quit`: the player quits.
|
|
591
|
-
*
|
|
592
|
+
* - `quit`: the player quits (or restarts after a lost GPU device). Every
|
|
593
|
+
* plugin is stopped at the same time, with 1 s in all (300 ms after a
|
|
594
|
+
* lost device; player 0.6.6).
|
|
595
|
+
* - `disable`: the user, or a plugin with `plugins.manage`, switched the
|
|
596
|
+
* plugin off. Its session storage is cleared.
|
|
592
597
|
* - `uninstall`: the user uninstalls it.
|
|
593
598
|
* - `reload`: it is reloaded (from the plugin manager, or a development
|
|
594
599
|
* load with `--plugin`).
|
|
595
600
|
* - `upgrade`: an install or update replaces the running version; also a
|
|
596
601
|
* new version stopped because its install was cancelled (the previous
|
|
597
602
|
* version comes back).
|
|
598
|
-
* - `idle`:
|
|
603
|
+
* - `idle`: the plugin goes to standby and its next use starts it again;
|
|
604
|
+
* its menu items, keys, settings pages, resolvers and drop targets stay,
|
|
605
|
+
* and so does its session storage
|
|
599
606
|
* ([Idle plugins](../../docs/explanation/plugins.md#idle-plugins-are-stopped)).
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
607
|
+
* Only with on-demand start (lazy activation), off by default up to
|
|
608
|
+
* player 0.6.6 (`VESTRA_LAZY=1` turns it on) and planned for everyone in
|
|
609
|
+
* player 0.6.7. It comes after the idle time without use (60 s; 30 s
|
|
610
|
+
* planned for 0.6.7), right after a first run that holds nothing live,
|
|
611
|
+
* and when the player's limit on third-party processes or low system
|
|
612
|
+
* memory puts an idle plugin in standby early (planned for 0.6.7). A busy
|
|
613
|
+
* plugin never gets it; a resident one (it held something live when it
|
|
614
|
+
* became ready) only after the idle time, and from player 0.6.7 (planned)
|
|
615
|
+
* never.
|
|
603
616
|
* - `failed`: the player stops it for a fault it can still tell the plugin
|
|
604
|
-
* about
|
|
605
|
-
*
|
|
606
|
-
*
|
|
617
|
+
* about: a malformed request, an unreadable or oversized line, a start
|
|
618
|
+
* that is not ready within the start timeout (15 s; 60 s planned for
|
|
619
|
+
* player 0.6.7; the stop may come while `activate` still runs), an
|
|
620
|
+
* uncaught exception the shared process attributes to this plugin, and,
|
|
621
|
+
* planned for player 0.6.7, a request from the player (a resolution) it
|
|
622
|
+
* leaves unanswered for 5 minutes. From player 0.6.6 the player may
|
|
623
|
+
* start it again afterwards (a built-in or resident plugin by itself, a
|
|
624
|
+
* plugin with on-demand start on its next use), until the fifth fault
|
|
625
|
+
* within 10 minutes.
|
|
607
626
|
* - `host-lost`: the plugin's runner saw its pipe to the player close
|
|
608
627
|
* without a stop: the player crashed or was killed. Requests are refused
|
|
609
628
|
* with `disabled`; clean up locally only. Player 0.6.4 sends `quit` on a
|
|
@@ -614,20 +633,22 @@ export interface Plugin extends Scope {
|
|
|
614
633
|
* {@link Scope.onDispose} cleanups do not run. That is the case when its
|
|
615
634
|
* own process is killed because its input queue is full or a write to it
|
|
616
635
|
* failed, when its own process fails to activate (the runner exits without
|
|
617
|
-
* cleaning up), when the process
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
*
|
|
625
|
-
*
|
|
626
|
-
*
|
|
627
|
-
*
|
|
628
|
-
*
|
|
629
|
-
*
|
|
630
|
-
*
|
|
636
|
+
* cleaning up), when the process ended by itself (it crashed, or its
|
|
637
|
+
* JavaScript heap passed the 512 MB cap of player 0.6.6 and V8 ended it:
|
|
638
|
+
* "ran out of memory"), and when the shared runner is restarted as a whole
|
|
639
|
+
* (a hang, a fault it cannot attribute, an unreadable line of its own, a
|
|
640
|
+
* member's full input queue, the runner exiting): every member is killed
|
|
641
|
+
* with it. Keep state that must survive such an end in storage as it
|
|
642
|
+
* changes, not only in a cleanup. Timings and restarts are in
|
|
643
|
+
* [How the player runs and talks to plugins](../../docs/explanation/host-and-node.md#crashes-and-restarts).
|
|
644
|
+
*
|
|
645
|
+
* Player 0.6.4 and later send the reason with `runtime.stop`, and their
|
|
646
|
+
* runner reports `host-lost`. Players up to 0.6.3 give no reason for any
|
|
647
|
+
* stop, a lost player included (`undefined`); so does a stop that does not
|
|
648
|
+
* come from the player (a `TestHost` `stop()` without a reason). A value
|
|
649
|
+
* this SDK does not know reads as `undefined`.
|
|
650
|
+
*
|
|
651
|
+
* @player 0.6.4; older players give no reason (`undefined`).
|
|
631
652
|
* @since 1.5.54
|
|
632
653
|
* @category Plugin
|
|
633
654
|
*/
|
|
@@ -647,8 +668,9 @@ export interface DisposeInfo {
|
|
|
647
668
|
*/
|
|
648
669
|
readonly stopping: boolean;
|
|
649
670
|
/**
|
|
650
|
-
* Why the player stops the plugin (
|
|
651
|
-
* `stopping` is false, and for
|
|
671
|
+
* Why the player stops the plugin (player 0.6.4; the causes are listed at
|
|
672
|
+
* {@link StopReason}); `undefined` while `stopping` is false, and for
|
|
673
|
+
* every stop by an older player.
|
|
652
674
|
*/
|
|
653
675
|
readonly reason?: StopReason;
|
|
654
676
|
}
|
|
@@ -3140,7 +3162,13 @@ export interface Appearance {
|
|
|
3140
3162
|
* Needs `events`: without it the listener never runs for other plugins'
|
|
3141
3163
|
* changes. Views need no help to follow the palette; use this for things
|
|
3142
3164
|
* the plugin draws itself (a rendered image, colours it computes). Errors
|
|
3143
|
-
* go to {@link Scope.onError}.
|
|
3165
|
+
* go to {@link Scope.onError}. When the player starts a stopped plugin
|
|
3166
|
+
* for a palette change (player 0.5.21), {@link Appearance.theme} already
|
|
3167
|
+
* has the new palette at start and the listener still hears the change
|
|
3168
|
+
* (SDK 1.5.56; before, it did not run). A language change does not call
|
|
3169
|
+
* it, except in one case: a plugin started for a language change alone
|
|
3170
|
+
* may hear the unchanged palette once, since the player's event does not
|
|
3171
|
+
* say which of the two changed.
|
|
3144
3172
|
*
|
|
3145
3173
|
* @capability events
|
|
3146
3174
|
*
|
|
@@ -8424,6 +8452,10 @@ export interface Resolvers {
|
|
|
8424
8452
|
/**
|
|
8425
8453
|
* {@link Resolvers.fileTypes} changed: a file resolver was added, or its
|
|
8426
8454
|
* plugin stopped. Needs `events`; without it the listener never fires.
|
|
8455
|
+
* When the player starts a stopped plugin for this change (player
|
|
8456
|
+
* 0.5.21), {@link Resolvers.fileTypes} already has the new list at start
|
|
8457
|
+
* and the listener still hears the change (SDK 1.5.56; before, it did not
|
|
8458
|
+
* run).
|
|
8427
8459
|
*
|
|
8428
8460
|
* @param listener - Receives the new list.
|
|
8429
8461
|
* @returns A handle that removes the listener.
|
|
@@ -8803,11 +8835,19 @@ export interface PluginInfo {
|
|
|
8803
8835
|
display?: PluginDisplay;
|
|
8804
8836
|
/**
|
|
8805
8837
|
* For `state: "running"`: `"running"` while its process runs, `"idle"`
|
|
8806
|
-
* while the
|
|
8807
|
-
*
|
|
8808
|
-
*
|
|
8809
|
-
*
|
|
8810
|
-
*
|
|
8838
|
+
* while the plugin is switched on but has no process. That is standby
|
|
8839
|
+
* with on-demand start (lazy activation): nothing used it for the idle
|
|
8840
|
+
* time, or the player's limit on third-party processes or low system
|
|
8841
|
+
* memory stopped it early (planned for player 0.6.7); it starts again on its next
|
|
8842
|
+
* use, and its menu items, keys, settings pages, resolvers and drop
|
|
8843
|
+
* targets stay. From player 0.6.6 it is also the pause after a crash: a
|
|
8844
|
+
* built-in or resident plugin waiting to start again by itself, or a
|
|
8845
|
+
* plugin with on-demand start whose commands are shown disabled with the
|
|
8846
|
+
* reason until the pause ends. Absent in other states and from players
|
|
8847
|
+
* before 0.5.18. A change between the two alone does not fire
|
|
8848
|
+
* {@link Packages.onChange}; a plugin stopped by the start limit (five
|
|
8849
|
+
* crashes within 10 minutes) is `state: "failed"` with that in
|
|
8850
|
+
* {@link PluginInfo.error}.
|
|
8811
8851
|
*
|
|
8812
8852
|
* @since 1.5.38
|
|
8813
8853
|
*/
|
|
@@ -9721,7 +9761,10 @@ export interface Storage {
|
|
|
9721
9761
|
* | --- | --- |
|
|
9722
9762
|
* | The plugin's process restarts: reload, upgrade, crash | kept |
|
|
9723
9763
|
* | The plugin failed to start or failed, and starts again | kept |
|
|
9724
|
-
* | The user
|
|
9764
|
+
* | The user, or a plugin with `plugins.manage` (`packages.setEnabled(id, false)`), disables the plugin | cleared |
|
|
9765
|
+
* | An update or reinstall with `enabled: false` switches an enabled plugin off (player 0.6.4) | cleared |
|
|
9766
|
+
* | The plugin is uninstalled | cleared |
|
|
9767
|
+
* | An earlier installation kept for a later reinstall (after a `replace`) is dropped because the player keeps only so many | cleared |
|
|
9725
9768
|
* | The player quits | cleared |
|
|
9726
9769
|
*
|
|
9727
9770
|
* - **Per plugin.** A plugin sees only its own keys. Like
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Vestra Player SDK
|
|
2
2
|
|
|
3
|
-
> @vestra-player/sdk 1.5.
|
|
3
|
+
> @vestra-player/sdk 1.5.58: write plugins for Vestra Player in TypeScript (plugin API `vestra/1`). A plugin is a folder with `manifest.json` and an entry module whose default export `activate(plugin)` the player calls. The documentation is a tree of short pages read by path, like `go doc`: the same pages and API as https://vestrasys.github.io/vestra-player-sdk/.
|
|
4
4
|
|
|
5
5
|
## Read the documentation
|
|
6
6
|
|