@vestra-player/sdk 1.5.3 → 1.5.6
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 +27 -0
- package/README.md +3 -1
- package/dist/plugin/testing.d.ts +9 -2
- package/dist/plugin/testing.js +9 -2
- package/dist/plugin/types.d.ts +68 -20
- package/dist/plugin/ui.js +22 -7
- package/llms-full.txt +7090 -0
- package/llms.txt +205 -0
- package/package.json +7 -2
- package/slint/vestra/markdown.slint +56 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.6
|
|
4
|
+
|
|
5
|
+
**A reference for AI assistants.** Documentation and packaging only; no API change, `apiVersion` stays `vestra/1`. (1.5.5 was not published to npm; this release includes its changes.)
|
|
6
|
+
|
|
7
|
+
- **`llms.txt` and `llms-full.txt`** ([llmstxt.org](https://llmstxt.org)) in the package, exported as `@vestra-player/sdk/llms.txt` and `@vestra-player/sdk/llms-full.txt` (in `node_modules/@vestra-player/sdk/`), and on the documentation site (`https://vestrasys.github.io/vestra-player-sdk/llms.txt`). For Vestra Player AI and other assistants that write plugins.
|
|
8
|
+
- `llms.txt` (about 10 KB): what a plugin is, the rules, the folder layout, a manifest with every field and the manifest limits, `activate`, every capability, a `TestHost` test, the command line, the common error codes, and the line numbers of each topic in the full file.
|
|
9
|
+
- `llms-full.txt` (about 300 KB): the guides (Getting started, the UI concept page, both how-tos), every public declaration of `@vestra-player/sdk` and `@vestra-player/sdk/testing` with its description and its `@capability`, `@player`, `@param`, `@returns`, `@throws` and `@deprecated` tags, the internal types the API refers to, and each example's README, walkthrough and complete source (TypeScript, Slint, tests).
|
|
10
|
+
- Generated from the sources by `npm run docs:llms` (`scripts/llms.mjs`); CI fails when the committed files are stale.
|
|
11
|
+
- **Getting started**: a "Rules for plugins" section (only the public SDK, `import type`, no other plugins, no system commands, macOS and Windows, your own id) and a manifest with every field.
|
|
12
|
+
- `scripts/check-pack.mjs` allows the two files and checks that they name the package version; the install smoke test resolves both exports.
|
|
13
|
+
|
|
14
|
+
## 1.5.5
|
|
15
|
+
|
|
16
|
+
**Reserved `vestra.` ids** (player 0.4.1). Documentation only; no API change, `apiVersion` stays `vestra/1`.
|
|
17
|
+
|
|
18
|
+
- Only the plugins built into the player are official plugins; the ids `vestra` and `vestra.*` (any case) are reserved for them. Every other plugin is a third-party plugin, including those hosted in the official plugin repository, and uses `<GitHub user or organization>.<plugin name>`.
|
|
19
|
+
- `PluginError` lists the code `reserved`: `packages.validate`, `packages.validateArchive`, `PackageCandidate.trial` and `PackageCandidate.install` refuse a package with a reserved id. Development loads (`vestra-player --plugin DIR`) still accept one, with a warning, so built-in plugins can be developed; they are never installed.
|
|
20
|
+
## 1.5.4
|
|
21
|
+
|
|
22
|
+
**Markdown in list rows** (the player after 0.4.0). Additive; `apiVersion` stays `vestra/1`, and plugins written for 1.5.3 need no change.
|
|
23
|
+
|
|
24
|
+
- **A `MarkdownRef` at any depth.** A document from `plugin.ui.markdown` may now be a field at any depth of a property value, wherever the Slint type is `[MarkdownBlock]`: for example the `body` of each row of a chat's `[Message]` list. Before, it could only be the whole value of a `[MarkdownBlock]` property. `PropValue` is now `PropData | ImageRef`, where the new **`PropData`** is JSON whose values may also be `MarkdownRef`s, at any depth. A released document is refused with `invalid` wherever it is in the value. An `ImageRef` stays a whole value only: nested in an array or object it is `invalid` (a type error in TypeScript, and refused by the SDK and the player). Older players refuse a nested document like any value they cannot convert.
|
|
25
|
+
- **Limits:** a document still holds at most 256 KB of text, 4000 blocks and 64 images; all of a value's text, its documents' text included, counts toward the value's 1 MiB; each document is one of its 4096 values.
|
|
26
|
+
- **`MarkdownBlocks`** (new in `@vestra/markdown.slint`): the blocks of a document without scrolling, as tall as their content, for your own layout or a `ListView` row. `in [MarkdownBlock] blocks`, `in bool code-copy` (default `false`), callbacks `link-clicked(string)` and `copy-code(string)`. `MarkdownView` is now a `ScrollView` around it and gains the same `code-copy` and `copy-code`; it looks as before.
|
|
27
|
+
- **Code copy, opt in.** With `code-copy: true`, code blocks get a 复制 button that reports `copy-code(code)` with the block's text; the plugin copies it (`plugin.clipboard.writeText`). Off by default: views that do not set it look and behave as before.
|
|
28
|
+
- **Cheaper updates** (player): writing a value again with unchanged documents does not parse them again (a new reference for the same text included), and a value with documents is updated in place where its shape allows: changed rows, rows added or removed at the end, and only the changed blocks of a changed document. Streaming a reply into the last row of a 200-message list therefore keeps the list, its scroll position and the other rows. Nothing to change in plugins.
|
|
29
|
+
- `TestHost` keeps nested documents in the view's properties as they were sent; `host.markdown(value)` reads one back from a field (`host.markdown(rows[0].body)`).
|
|
3
30
|
## 1.5.3
|
|
4
31
|
|
|
5
32
|
**File resolvers: local files as generated streams** (player 0.4.1). Additive; `apiVersion` stays `vestra/1`. Plugins that register one set `"minPlayerVersion": "0.4.1"`: an older player refuses the declaration (`invalid`).
|
package/README.md
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
<a href="https://vestrasys.github.io/vestra-player-sdk/">Documentation</a> ·
|
|
13
13
|
<a href="https://vestrasys.github.io/vestra-player-sdk/documents/Getting_started.html">Getting started</a> ·
|
|
14
14
|
<a href="https://github.com/vestrasys/vestra-player-sdk/tree/main/examples">Examples</a> ·
|
|
15
|
-
<a href="https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md">Changelog</a>
|
|
15
|
+
<a href="https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md">Changelog</a> ·
|
|
16
|
+
<a href="https://vestrasys.github.io/vestra-player-sdk/llms.txt">llms.txt</a>
|
|
16
17
|
</p>
|
|
17
18
|
## Features
|
|
18
19
|
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
- **Tests without the player**: `@vestra-player/sdk/testing` runs your plugin against an in-memory host with `node --test`.
|
|
22
23
|
- **One command line tool**, `vestra-plugin`, to check, test, build and pack a `.vxp` package.
|
|
23
24
|
- **The same API on macOS and Windows**; every plugin runs in its own Node.js 26 process that the player ships.
|
|
25
|
+
- **A reference for AI assistants**: [`llms.txt`](https://vestrasys.github.io/vestra-player-sdk/llms.txt) (short index) and [`llms-full.txt`](https://vestrasys.github.io/vestra-player-sdk/llms-full.txt) (every declaration, the guides and the examples), also in the package as `@vestra-player/sdk/llms.txt` and `@vestra-player/sdk/llms-full.txt`.
|
|
24
26
|
|
|
25
27
|
## Install
|
|
26
28
|
|
package/dist/plugin/testing.d.ts
CHANGED
|
@@ -1128,9 +1128,16 @@ export declare class TestHost implements Transport {
|
|
|
1128
1128
|
*/
|
|
1129
1129
|
readonly remoteImages: Map<string, string | null>;
|
|
1130
1130
|
/**
|
|
1131
|
-
* The Markdown document a
|
|
1131
|
+
* The Markdown document a value holds (its wire form read back), or
|
|
1132
1132
|
* `null` when the value is not one. `images` maps each remote address to
|
|
1133
|
-
* the downloaded file.
|
|
1133
|
+
* the downloaded file. Pass a whole property value or a field of one: a
|
|
1134
|
+
* document nested in rows is read the same way.
|
|
1135
|
+
*
|
|
1136
|
+
* @example
|
|
1137
|
+
* ```ts
|
|
1138
|
+
* const rows = host.window("chat").props["messages"] as { body: Json }[];
|
|
1139
|
+
* assert.equal(host.markdown(rows[0]!.body)?.text, "**Hello**");
|
|
1140
|
+
* ```
|
|
1134
1141
|
*/
|
|
1135
1142
|
markdown(value: Json | undefined): MarkdownWire | null;
|
|
1136
1143
|
/**
|
package/dist/plugin/testing.js
CHANGED
|
@@ -1482,9 +1482,16 @@ export class TestHost {
|
|
|
1482
1482
|
*/
|
|
1483
1483
|
remoteImages = new Map();
|
|
1484
1484
|
/**
|
|
1485
|
-
* The Markdown document a
|
|
1485
|
+
* The Markdown document a value holds (its wire form read back), or
|
|
1486
1486
|
* `null` when the value is not one. `images` maps each remote address to
|
|
1487
|
-
* the downloaded file.
|
|
1487
|
+
* the downloaded file. Pass a whole property value or a field of one: a
|
|
1488
|
+
* document nested in rows is read the same way.
|
|
1489
|
+
*
|
|
1490
|
+
* @example
|
|
1491
|
+
* ```ts
|
|
1492
|
+
* const rows = host.window("chat").props["messages"] as { body: Json }[];
|
|
1493
|
+
* assert.equal(host.markdown(rows[0]!.body)?.text, "**Hello**");
|
|
1494
|
+
* ```
|
|
1488
1495
|
*/
|
|
1489
1496
|
markdown(value) {
|
|
1490
1497
|
const doc = value
|
package/dist/plugin/types.d.ts
CHANGED
|
@@ -75,6 +75,7 @@ export interface Disposable {
|
|
|
75
75
|
* | `backend-uncertain` | The player's backend blocked a filter stage; call `retry()`. |
|
|
76
76
|
* | `cleanup` | {@link PackageTrial.stop} could not confirm cleanup; call it again. |
|
|
77
77
|
* | `limit` | A player-wide limit was reached (for example the number of commands). |
|
|
78
|
+
* | `reserved` | {@link Packages.validate}, {@link PackageCandidate.trial}, {@link PackageCandidate.install}: the id is `vestra` or starts with `vestra.` (any case), which only the player's built-in plugins use (player 0.4.1). |
|
|
78
79
|
* | `versionMismatch` | The package needs a newer player (`minPlayerVersion`) or another `apiVersion`. |
|
|
79
80
|
* | `ui-prepare` | The player could not prepare a mounted panel or a settings page (its Slint file does not compile, a bound property is not declared, or another plugin's panel holds the slot); `message` has the diagnostics. |
|
|
80
81
|
* | `ui` | The player could not apply a property to a tool window or a settings page, or could not build the Options window (a property the Slint file does not declare, a value of the wrong type); `message` has Slint's reason. |
|
|
@@ -562,18 +563,31 @@ export interface ImageRef {
|
|
|
562
563
|
readonly __vestraImage: true;
|
|
563
564
|
}
|
|
564
565
|
/**
|
|
565
|
-
* A Markdown document for `MarkdownView`, made by
|
|
566
|
+
* A Markdown document for `MarkdownView` or `MarkdownBlocks`, made by
|
|
567
|
+
* {@link Ui.markdown}.
|
|
566
568
|
*
|
|
567
569
|
* @remarks
|
|
568
|
-
* Opaque, like {@link ImageRef}: pass it
|
|
569
|
-
* `[MarkdownBlock]
|
|
570
|
-
* `@vestra/markdown.slint`)
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
*
|
|
570
|
+
* Opaque, like {@link ImageRef}: pass it where the Slint type is
|
|
571
|
+
* `[MarkdownBlock]`: the whole value of such a property (the `blocks` of
|
|
572
|
+
* `MarkdownView` from `@vestra/markdown.slint`) or, from SDK 1.5.4, a
|
|
573
|
+
* `[MarkdownBlock]` field at any depth of a property value, such as the
|
|
574
|
+
* `body` of each row of a chat's message list. It carries the text, the
|
|
575
|
+
* base address and the local copies of its remote images; the player parses
|
|
576
|
+
* and draws it. Writing a document whose text did not change (a new
|
|
577
|
+
* reference for the same text included) costs the player no parsing, and a
|
|
578
|
+
* changed document updates only the blocks that changed. It belongs to the
|
|
579
|
+
* scope that created it: once that scope is disposed, writing it fails with
|
|
580
|
+
* `invalid`, wherever it is in the value.
|
|
581
|
+
*
|
|
582
|
+
* @example Chat messages, one document per row
|
|
583
|
+
* ```ts
|
|
584
|
+
* const chat = plugin.windows.create("ui/chat.slint");
|
|
585
|
+
* const body = await plugin.ui.markdown("**Hello**", { remoteImages: false });
|
|
586
|
+
* chat.set({ messages: [{ id: "m1", role: "assistant", body }] });
|
|
587
|
+
* ```
|
|
588
|
+
*
|
|
589
|
+
* @player 0.2.0; nested in a value: the player after 0.4.0
|
|
590
|
+
* @see {@link Ui.markdown}, {@link MarkdownOptions}, {@link PropValue}
|
|
577
591
|
* @since 1.1.0
|
|
578
592
|
* @category UI
|
|
579
593
|
*/
|
|
@@ -607,8 +621,9 @@ export interface MarkdownOptions {
|
|
|
607
621
|
remoteImages?: boolean;
|
|
608
622
|
}
|
|
609
623
|
/**
|
|
610
|
-
* The value of one Slint property: JSON
|
|
611
|
-
* as the whole value of
|
|
624
|
+
* The value of one Slint property: JSON with Markdown documents at any
|
|
625
|
+
* depth ({@link PropData}), or an image as the whole value of an `image`
|
|
626
|
+
* property.
|
|
612
627
|
*
|
|
613
628
|
* @remarks
|
|
614
629
|
* JSON becomes Slint values as you would expect: booleans for `bool`,
|
|
@@ -618,14 +633,37 @@ export interface MarkdownOptions {
|
|
|
618
633
|
* is refused (Slint treats `_` and `-` as the same, so use camelCase or
|
|
619
634
|
* kebab-case).
|
|
620
635
|
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
636
|
+
* A {@link MarkdownRef} goes where the Slint type is `[MarkdownBlock]`: the
|
|
637
|
+
* whole value, or a field at any depth (SDK 1.5.4; older players refuse a
|
|
638
|
+
* nested one). An {@link ImageRef} only as the whole value: nested in an
|
|
639
|
+
* array or object it is `invalid`.
|
|
640
|
+
*
|
|
641
|
+
* Limits per value: nesting depth 8, 4096 values in total (a document is
|
|
642
|
+
* one), 1024 rows per array, 64 KiB per string and 1 MiB of text in total,
|
|
643
|
+
* the text of its Markdown documents included (256 KB per document). A
|
|
644
|
+
* value over a limit is a failed write (see {@link View}).
|
|
624
645
|
*
|
|
625
646
|
* @since 1.0.0
|
|
626
647
|
* @category UI
|
|
627
648
|
*/
|
|
628
|
-
export type PropValue =
|
|
649
|
+
export type PropValue = PropData | ImageRef;
|
|
650
|
+
/**
|
|
651
|
+
* JSON whose values may also be Markdown documents, at any depth: the part
|
|
652
|
+
* of {@link PropValue} that nests.
|
|
653
|
+
*
|
|
654
|
+
* @example A message list whose rows carry a document
|
|
655
|
+
* ```ts
|
|
656
|
+
* const messages: PropData = [
|
|
657
|
+
* { id: "m1", role: "user", body: await plugin.ui.markdown("Hi") },
|
|
658
|
+
* ];
|
|
659
|
+
* ```
|
|
660
|
+
*
|
|
661
|
+
* @since 1.5.4
|
|
662
|
+
* @category UI
|
|
663
|
+
*/
|
|
664
|
+
export type PropData = null | boolean | number | string | MarkdownRef | PropData[] | {
|
|
665
|
+
[key: string]: PropData;
|
|
666
|
+
};
|
|
629
667
|
/**
|
|
630
668
|
* Properties to write to a view, by name.
|
|
631
669
|
*
|
|
@@ -4046,13 +4084,18 @@ export interface PackageCandidate {
|
|
|
4046
4084
|
readonly manifest: PackageManifest;
|
|
4047
4085
|
/** The checks the player ran. */
|
|
4048
4086
|
readonly checks: string[];
|
|
4049
|
-
/**
|
|
4087
|
+
/**
|
|
4088
|
+
* Load it temporarily alongside the installed plugins. A reserved id
|
|
4089
|
+
* (`vestra.*`) fails with `reserved`.
|
|
4090
|
+
*/
|
|
4050
4091
|
trial(): Promise<PackageTrial>;
|
|
4051
4092
|
/**
|
|
4052
4093
|
* Install it. The same source upgrades the installed plugin (its data
|
|
4053
4094
|
* stays); another source fails with `conflict` unless `replace` is set;
|
|
4054
4095
|
* a built-in id fails with `unsupported` (built-ins update with the
|
|
4055
|
-
* player).
|
|
4096
|
+
* player). A reserved id (`vestra` or `vestra.*`, which every built-in
|
|
4097
|
+
* uses) fails with `reserved` (player 0.4.1; already when validated), as
|
|
4098
|
+
* only the player installs built-in plugins.
|
|
4056
4099
|
*/
|
|
4057
4100
|
install(options?: InstallOptions): Promise<PackageChange>;
|
|
4058
4101
|
}
|
|
@@ -4160,12 +4203,17 @@ export interface PluginWarning {
|
|
|
4160
4203
|
* ```
|
|
4161
4204
|
*/
|
|
4162
4205
|
export interface Packages {
|
|
4163
|
-
/**
|
|
4206
|
+
/**
|
|
4207
|
+
* Validate a package directory (`plugins.manage`). A package whose id is
|
|
4208
|
+
* reserved for the built-in plugins (`vestra` or `vestra.*`) fails with
|
|
4209
|
+
* `reserved` (player 0.4.1).
|
|
4210
|
+
*/
|
|
4164
4211
|
validate(directory: string): Promise<PackageCandidate>;
|
|
4165
4212
|
/**
|
|
4166
4213
|
* Validate a `.vxp` package file (`plugins.manage`, player 0.2.0): the
|
|
4167
4214
|
* same checks as {@link Packages.validate} after unpacking. Check the
|
|
4168
|
-
* file's sha256 yourself before calling when you know it.
|
|
4215
|
+
* file's sha256 yourself before calling when you know it. A reserved id
|
|
4216
|
+
* fails with `reserved`, as in {@link Packages.validate}.
|
|
4169
4217
|
*/
|
|
4170
4218
|
validateArchive(file: string): Promise<PackageCandidate>;
|
|
4171
4219
|
/** Restore a plugin's previous version (`plugins.manage`). */
|
package/dist/plugin/ui.js
CHANGED
|
@@ -31,18 +31,33 @@ export class ImageHandle {
|
|
|
31
31
|
return { $vestraImage: this.path, ref: this.#ref };
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
/**
|
|
35
|
-
|
|
34
|
+
/**
|
|
35
|
+
* A property value as sent: images and documents in wire form, documents at
|
|
36
|
+
* any depth (released ones refused wherever they are); an image only as the
|
|
37
|
+
* whole value, like the player.
|
|
38
|
+
*/
|
|
39
|
+
function wireValue(value, nested = false) {
|
|
36
40
|
if (value instanceof MarkdownHandle) {
|
|
37
41
|
if (value.released)
|
|
38
42
|
throw failure("invalid", "Markdown document was released with the scope that created it");
|
|
39
43
|
return value.toJSON();
|
|
40
44
|
}
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
if (value instanceof ImageHandle) {
|
|
46
|
+
if (nested)
|
|
47
|
+
throw failure("invalid", `image ${value.path}: an image reference must be the whole value of an image property`);
|
|
48
|
+
if (value.released)
|
|
49
|
+
throw failure("invalid", `image ${value.path} was released with the scope that created it`);
|
|
50
|
+
return value.toJSON();
|
|
51
|
+
}
|
|
52
|
+
if (Array.isArray(value))
|
|
53
|
+
return value.map((item) => wireValue(item, true));
|
|
54
|
+
if (value !== null && typeof value === "object") {
|
|
55
|
+
const out = {};
|
|
56
|
+
for (const [key, item] of Object.entries(value))
|
|
57
|
+
out[key] = wireValue(item, true);
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
46
61
|
}
|
|
47
62
|
export const ui = (scope) => ({
|
|
48
63
|
image(path) {
|