@deadair/plugin-sdk 0.2.0
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/LICENSE +21 -0
- package/README.md +1062 -0
- package/dist/article.parse.d.ts +82 -0
- package/dist/article.parse.d.ts.map +1 -0
- package/dist/boundary.json.safe.d.ts +191 -0
- package/dist/boundary.json.safe.d.ts.map +1 -0
- package/dist/capabilities/analysis.d.ts +330 -0
- package/dist/capabilities/analysis.d.ts.map +1 -0
- package/dist/capabilities/charts.d.ts +134 -0
- package/dist/capabilities/charts.d.ts.map +1 -0
- package/dist/capabilities/enrichment.d.ts +255 -0
- package/dist/capabilities/enrichment.d.ts.map +1 -0
- package/dist/capabilities/llm.d.ts +318 -0
- package/dist/capabilities/llm.d.ts.map +1 -0
- package/dist/capabilities/mixer.d.ts +183 -0
- package/dist/capabilities/mixer.d.ts.map +1 -0
- package/dist/capabilities/music.provider.d.ts +245 -0
- package/dist/capabilities/music.provider.d.ts.map +1 -0
- package/dist/capabilities/news.d.ts +171 -0
- package/dist/capabilities/news.d.ts.map +1 -0
- package/dist/capabilities/scrobble.d.ts +133 -0
- package/dist/capabilities/scrobble.d.ts.map +1 -0
- package/dist/capabilities/search.d.ts +122 -0
- package/dist/capabilities/search.d.ts.map +1 -0
- package/dist/capabilities/similarity.d.ts +101 -0
- package/dist/capabilities/similarity.d.ts.map +1 -0
- package/dist/capabilities/speech.d.ts +211 -0
- package/dist/capabilities/speech.d.ts.map +1 -0
- package/dist/capabilities/weather.d.ts +192 -0
- package/dist/capabilities/weather.d.ts.map +1 -0
- package/dist/chunk-7QVYU63E.js +7 -0
- package/dist/chunk-7QVYU63E.js.map +1 -0
- package/dist/define.plugin.d.ts +56 -0
- package/dist/define.plugin.d.ts.map +1 -0
- package/dist/feed.parse.d.ts +97 -0
- package/dist/feed.parse.d.ts.map +1 -0
- package/dist/html.text.d.ts +71 -0
- package/dist/html.text.d.ts.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1153 -0
- package/dist/index.js.map +1 -0
- package/dist/match.text.d.ts +28 -0
- package/dist/match.text.d.ts.map +1 -0
- package/dist/plugin.api.version.d.ts +9 -0
- package/dist/plugin.api.version.d.ts.map +1 -0
- package/dist/plugin.base.d.ts +80 -0
- package/dist/plugin.base.d.ts.map +1 -0
- package/dist/plugin.config.fields.d.ts +524 -0
- package/dist/plugin.config.fields.d.ts.map +1 -0
- package/dist/plugin.config.read.d.ts +52 -0
- package/dist/plugin.config.read.d.ts.map +1 -0
- package/dist/plugin.error.d.ts +177 -0
- package/dist/plugin.error.d.ts.map +1 -0
- package/dist/plugin.host.d.ts +220 -0
- package/dist/plugin.host.d.ts.map +1 -0
- package/dist/plugin.host.response.d.ts +42 -0
- package/dist/plugin.host.response.d.ts.map +1 -0
- package/dist/plugin.http.d.ts +80 -0
- package/dist/plugin.http.d.ts.map +1 -0
- package/dist/plugin.lifecycle.d.ts +68 -0
- package/dist/plugin.lifecycle.d.ts.map +1 -0
- package/dist/plugin.manifest.d.ts +282 -0
- package/dist/plugin.manifest.d.ts.map +1 -0
- package/dist/plugin.permissions.d.ts +186 -0
- package/dist/plugin.permissions.d.ts.map +1 -0
- package/dist/testing/fake.plugin.host.d.ts +85 -0
- package/dist/testing/fake.plugin.host.d.ts.map +1 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +141 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.api.version.d.ts","sourceRoot":"","sources":["../src/plugin.api.version.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,UAAU,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { PluginHost } from './plugin.host.js';
|
|
2
|
+
import type { PluginLifecycle } from './plugin.lifecycle.js';
|
|
3
|
+
/** Undoes one thing a plugin set up. Run in reverse order of registration when the plugin unloads. */
|
|
4
|
+
export type PluginDisposer = () => void | Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* The base a plugin extends, so unloading is correct by construction.
|
|
7
|
+
*
|
|
8
|
+
* Two jobs, both of them chores every plugin was otherwise doing by hand:
|
|
9
|
+
*
|
|
10
|
+
* 1. **`this.host` is there or it throws with a sentence.** Each plugin used to
|
|
11
|
+
* hold `host?: PluginHost` and write its own `hostOrThrow()`, or forget to
|
|
12
|
+
* and get a `TypeError` about reading a property of undefined instead.
|
|
13
|
+
* 2. **Teardown is registered next to setup.** {@link Plugin.register} takes an
|
|
14
|
+
* undo, and the base runs every one on unload, last registered first,
|
|
15
|
+
* whether or not {@link Plugin.onUnload} throws.
|
|
16
|
+
*
|
|
17
|
+
* The second matters MORE in this host, not less. Plugins run inside the API process
|
|
18
|
+
* (`packages/plugin-sdk/CLAUDE.md` § "Trust and egress"), so a timer or a socket a plugin forgets
|
|
19
|
+
* is not confined to a sandbox that gets torn down: it lives in the server until somebody restarts
|
|
20
|
+
* it. Reloading a plugin on every config change is a normal thing an operator does, so "forgets on
|
|
21
|
+
* unload" compounds.
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* class MyPlugin extends Plugin implements EnrichmentPluginInstance {
|
|
25
|
+
* protected async onLoad(): Promise<void> {
|
|
26
|
+
* const timer = setInterval(() => void this.refresh(), 60_000);
|
|
27
|
+
* this.register(() => clearInterval(timer));
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* Extending this is optional: the host only ever asks for `PluginLifecycle`, so
|
|
33
|
+
* a plugin that implements `init` and `dispose` itself is as valid as it was.
|
|
34
|
+
*/
|
|
35
|
+
export declare abstract class Plugin implements PluginLifecycle {
|
|
36
|
+
private currentHost?;
|
|
37
|
+
private readonly disposers;
|
|
38
|
+
/**
|
|
39
|
+
* The host, once `init` has run.
|
|
40
|
+
*
|
|
41
|
+
* A getter rather than a field so the failure is a sentence naming the
|
|
42
|
+
* plugin instead of a `TypeError` from somewhere three calls deeper.
|
|
43
|
+
*
|
|
44
|
+
* @throws {PluginError} `internal` when read before `init` or after
|
|
45
|
+
* `dispose`. Both are host bugs rather than operator ones, which is what
|
|
46
|
+
* that code means.
|
|
47
|
+
*/
|
|
48
|
+
protected get host(): PluginHost;
|
|
49
|
+
/**
|
|
50
|
+
* Registers something to undo when this plugin unloads.
|
|
51
|
+
*
|
|
52
|
+
* Call it next to the setup it undoes, which is the whole point: a
|
|
53
|
+
* `clearInterval` written beside its `setInterval` is one that cannot drift
|
|
54
|
+
* away from it as the file grows.
|
|
55
|
+
*/
|
|
56
|
+
protected register(disposer: PluginDisposer): void;
|
|
57
|
+
/** {@link Plugin.register} for the common case. Works for `setTimeout` and `setInterval` alike. */
|
|
58
|
+
protected registerTimer(timer: ReturnType<typeof setTimeout>): void;
|
|
59
|
+
/** Your setup. Called once, after `this.host` is available and before any capability method. */
|
|
60
|
+
protected onLoad(): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Anything left to undo that `register` could not express, such as dropping
|
|
63
|
+
* a cache. Runs after every registered disposer.
|
|
64
|
+
*/
|
|
65
|
+
protected onUnload(): Promise<void>;
|
|
66
|
+
init(host: PluginHost): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Undoes everything, in reverse.
|
|
69
|
+
*
|
|
70
|
+
* Every disposer runs even if an earlier one throws, because one broken
|
|
71
|
+
* undo must not strand the rest: the failure is logged and the walk
|
|
72
|
+
* continues. `onUnload` runs afterwards for the same reason it exists, and
|
|
73
|
+
* `this.host` is released last so both still have it.
|
|
74
|
+
*
|
|
75
|
+
* Idempotent. The host calls it on unload, on a config change and at
|
|
76
|
+
* shutdown, and those can overlap.
|
|
77
|
+
*/
|
|
78
|
+
dispose(): Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=plugin.base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.base.d.ts","sourceRoot":"","sources":["../src/plugin.base.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,sGAAsG;AACtG,MAAM,MAAM,cAAc,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,8BAAsB,MAAO,YAAW,eAAe;IACnD,OAAO,CAAC,WAAW,CAAC,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD;;;;;;;;;OASG;IACH,SAAS,KAAK,IAAI,IAAI,UAAU,CAK/B;IAED;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAIlD,mGAAmG;IACnG,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI;IAInE,gGAAgG;IAChG,SAAS,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;;OAGG;IACH,SAAS,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3C;;;;;;;;;;OAUG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAoBjC"}
|
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* The kinds of input a plugin can ask the operator for.
|
|
4
|
+
*
|
|
5
|
+
* - `string` free text, one line
|
|
6
|
+
* - `text` free text over several lines, for anything a person writes
|
|
7
|
+
* rather than pastes: a prompt, a persona, a list of phrasings.
|
|
8
|
+
* Stored exactly like a `string`, so nothing downstream has to
|
|
9
|
+
* know it exists; the difference is the box the operator types
|
|
10
|
+
* into, and a one-line box for a paragraph is the reason a
|
|
11
|
+
* setting like that ends up being edited by hand in psql
|
|
12
|
+
* - `url` free text validated/normalised as a URL
|
|
13
|
+
* - `secret` write-only: the host encrypts it, the settings UI never reads
|
|
14
|
+
* it back, and only `host.secrets.get()` sees the plaintext
|
|
15
|
+
* - `number` numeric input
|
|
16
|
+
* - `boolean` toggle
|
|
17
|
+
* - `select` one of `options`
|
|
18
|
+
* - `multiselect` any number of `options`, stored as a JSON array of the chosen
|
|
19
|
+
* values. Read it back with {@link parseMultiSelect}
|
|
20
|
+
* - `list` any number of ROWS with the same `columns`, stored as a JSON
|
|
21
|
+
* array of objects. Read it back with {@link parseRows}. For a
|
|
22
|
+
* list whose entries have parts — a feed with a name and a
|
|
23
|
+
* category — where the alternative is a `text` field with a
|
|
24
|
+
* separator in it and a line an operator can mistype into
|
|
25
|
+
* silence
|
|
26
|
+
* - `note` not an input at all: static help text rendered in the form
|
|
27
|
+
*/
|
|
28
|
+
export type ConfigFieldType = 'string' | 'text' | 'url' | 'secret' | 'number' | 'boolean' | 'select' | 'multiselect' | 'list' | 'note';
|
|
29
|
+
/**
|
|
30
|
+
* What a `number` field's value is measured in, so the form can offer a control a person can use.
|
|
31
|
+
*
|
|
32
|
+
* The VALUE is always stored in the unit named here — `bytes` means the row holds bytes — and the
|
|
33
|
+
* console converts on the way in and out. That is the whole point: a byte count is the right thing
|
|
34
|
+
* for code to compare against and a terrible thing to type, and the alternative to declaring it is
|
|
35
|
+
* either storing a friendlier unit (and doing the multiplication at every reader) or special-casing
|
|
36
|
+
* a particular setting key inside the form, which is the kind of thing nobody finds later.
|
|
37
|
+
*
|
|
38
|
+
* `fraction` is the second member and the one the first paragraph predicted: the row holds a share
|
|
39
|
+
* between 0 and 1, because that is what the code multiplying by it wants, and the console says
|
|
40
|
+
* `40%`, because that is what a person means. Honoured by a `slider`, which is the control every
|
|
41
|
+
* share in this station asks for; a fraction drawn as an ordinary spinner is still shown as the
|
|
42
|
+
* fraction it stores, since a number typed exactly is unambiguous either way.
|
|
43
|
+
*
|
|
44
|
+
* An enum rather than a boolean because the third member is obvious (a duration in milliseconds has
|
|
45
|
+
* exactly the same problem) and because a closed set is what the contract mirroring this can
|
|
46
|
+
* express.
|
|
47
|
+
*/
|
|
48
|
+
export type ConfigFieldUnit = 'bytes' | 'fraction';
|
|
49
|
+
/**
|
|
50
|
+
* The control a field asks for, where the default one for its type is not the readable one.
|
|
51
|
+
*
|
|
52
|
+
* {@link ConfigFieldUnit}'s sibling, and the same bargain: what is STORED does not change, only the
|
|
53
|
+
* thing the operator touches. A `slider` over a share between 0 and 1 stores a fraction, and every
|
|
54
|
+
* reader still reads a fraction.
|
|
55
|
+
*
|
|
56
|
+
* Opt-in per field rather than inferred from `min` and `max` being present, which is the whole
|
|
57
|
+
* point. A slider is right for a value somebody feels for (a percentage, a trim in decibels, one
|
|
58
|
+
* pad every N breaks) and wrong for one they have to hit exactly: 3500 out of 0 to 600000 is a
|
|
59
|
+
* pixel, and a pause in milliseconds is a number an operator types rather than aims at. Declaring
|
|
60
|
+
* it makes that a judgement per setting instead of a rule that is right eight times and wrong six.
|
|
61
|
+
*
|
|
62
|
+
* A `slider` must declare both `min` and `max`, since a range with no ends is not one a track can
|
|
63
|
+
* be drawn for. A field asking for one without them falls back to the ordinary input rather than
|
|
64
|
+
* failing: this is a hint about drawing, and a form that renders nothing is worse than a form that
|
|
65
|
+
* renders a spinner.
|
|
66
|
+
*
|
|
67
|
+
* `tags` is for a `string` that is really a SET, stored as one comma-separated line because that is
|
|
68
|
+
* what the reader behind it splits. It changes nothing about the value: the form splits on the way
|
|
69
|
+
* in and joins on the way out, so `dialogueKinds()` keeps parsing exactly the string it always did.
|
|
70
|
+
* What it buys is that a set of names is added to and removed from one at a time, rather than by
|
|
71
|
+
* editing punctuation in a sentence — a stray comma in a one-line box is a kind the station simply
|
|
72
|
+
* does not have, and nothing says so. The cost is that a value CONTAINING a comma cannot be one
|
|
73
|
+
* tag, which is why this is asked for per field rather than being what a `string` does.
|
|
74
|
+
*/
|
|
75
|
+
export type ConfigFieldControl = 'slider' | 'tags';
|
|
76
|
+
/** One choice in a `select`, a `multiselect`, or a suggestion list. */
|
|
77
|
+
export interface ConfigFieldOption {
|
|
78
|
+
value: string;
|
|
79
|
+
label: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Where a field's or a column's choices come from when neither the plugin nor the operator's own
|
|
83
|
+
* server is the one that knows them.
|
|
84
|
+
*
|
|
85
|
+
* A closed HOST vocabulary, and the third of three ways a choice can be offered: `options` is what
|
|
86
|
+
* the PLUGIN decided when its manifest was written, `suggestConfigOptions()` is what the operator's
|
|
87
|
+
* own server currently says, and this is what the STATION says. It exists because a plugin cannot
|
|
88
|
+
* ask — a news plugin has no way to learn which categories this station holds, and the alternative
|
|
89
|
+
* is a free-text cell where `sports` and `sport` are a silent miss nobody sees until bulletins start
|
|
90
|
+
* declining.
|
|
91
|
+
*
|
|
92
|
+
* `intl.timeZones` is the second member and stretches the name slightly: it is the PLATFORM's list
|
|
93
|
+
* rather than the station's, out of `Intl.supportedValuesOf('timeZone')`. It belongs here anyway,
|
|
94
|
+
* because the property is about who can answer rather than about where the answer is kept, and the
|
|
95
|
+
* console is again the only side that can — a zone name has to be one the browser and the server
|
|
96
|
+
* both know, and a server that enumerated its own would be answering for a different machine.
|
|
97
|
+
*
|
|
98
|
+
* `station.newsFeeds` answers the feeds the installed plugins currently offer, by their qualified id
|
|
99
|
+
* and the operator's own name for each. It is the one source whose value is minted by a PLUGIN and
|
|
100
|
+
* whose list only the station can assemble, which is why it is here rather than being something a
|
|
101
|
+
* plugin could answer: the ids are qualified with the plugin that offered them, and no plugin knows
|
|
102
|
+
* what the others are called.
|
|
103
|
+
*
|
|
104
|
+
* The four `plugins.*` members answer the enabled plugins that declare a given capability — speech,
|
|
105
|
+
* llm, mixer, analysis — by id and name, for the settings that pick which plugin a capability with
|
|
106
|
+
* several installed candidates uses. Those settings stay free text (`selectPlugin` in
|
|
107
|
+
* `plugin.selection.ts` accepts an id that is not currently a candidate without falling back), so
|
|
108
|
+
* this is a suggestion list rather than a closed `select` — the console resolves it the same way as
|
|
109
|
+
* the other sources here, against the plugin list rather than a static enum.
|
|
110
|
+
*
|
|
111
|
+
* `llm.models` is the odd one and the only member whose answer comes from a PLUGIN rather than from
|
|
112
|
+
* a station table: the models the selected model plugin currently offers, for the settings that say
|
|
113
|
+
* which model a particular writer should use. It resolves through the suggestions route every plugin
|
|
114
|
+
* settings form already uses, against whichever plugin `llm.pluginId` names, so the six writer
|
|
115
|
+
* settings offer the same list the plugin's own form does — including which provider each model
|
|
116
|
+
* lives on, since a model name carries that.
|
|
117
|
+
*
|
|
118
|
+
* An enum rather than a boolean for {@link ConfigFieldUnit}'s reason: the next one (voices,
|
|
119
|
+
* personas) is obvious, and a closed set is what the contract mirroring this can express. Whatever
|
|
120
|
+
* it names is resolved by the CONSOLE; nothing here reaches a plugin.
|
|
121
|
+
*/
|
|
122
|
+
export type ConfigFieldOptionSource = 'station.newsCategories' | 'station.newsFeeds' | 'intl.timeZones' | 'plugins.speech' | 'plugins.llm' | 'plugins.mixer' | 'plugins.analysis' | 'llm.models';
|
|
123
|
+
/**
|
|
124
|
+
* One column of a `list` field.
|
|
125
|
+
*
|
|
126
|
+
* Still a smaller vocabulary than {@link ConfigFieldType} — no nested `list`, because a table inside
|
|
127
|
+
* a table is a form nobody can fill in — but `secret` is now in it, and the reason it was not is
|
|
128
|
+
* worth keeping because it is what had to be built to allow it. A row was stored as plain JSON with
|
|
129
|
+
* nothing to encrypt one cell against: a ciphertext has to belong to a ROW, and a row had no
|
|
130
|
+
* identity beyond its position in an array the console rewrites whole on every save. {@link ROW_ID_KEY}
|
|
131
|
+
* is that identity, and {@link rowSecretKey} is where the cell's ciphertext lives.
|
|
132
|
+
*
|
|
133
|
+
* Every ordinary cell is stored as a STRING in the row, so a column is about the control the
|
|
134
|
+
* operator gets rather than about the shape of what is kept. A `secret` cell is the exception and
|
|
135
|
+
* the exception is the point: it is never in the row at all, and the row an author reads back has
|
|
136
|
+
* no trace of it. See {@link readRowSecret}.
|
|
137
|
+
*/
|
|
138
|
+
export interface ConfigFieldColumn {
|
|
139
|
+
/**
|
|
140
|
+
* Key this cell is stored under inside the row object.
|
|
141
|
+
*
|
|
142
|
+
* Whatever suits the plugin, dots included, exactly like {@link ConfigField.key}. A row editor
|
|
143
|
+
* addresses a cell by a path and a dot in a path means a step into a nested object, but that is
|
|
144
|
+
* the FORM's problem and it solves it the way it already solves the same problem for a
|
|
145
|
+
* dot-keyed station setting: it names its inputs positionally and puts the real keys back on
|
|
146
|
+
* the way out. Nothing a plugin author has to know about.
|
|
147
|
+
*
|
|
148
|
+
* One character is refused, and only because {@link rowSecretKey} joins on it: a `/`. That
|
|
149
|
+
* separator has to be unambiguous or a cell's ciphertext could be addressed by two different
|
|
150
|
+
* keys, so it is refused at the schema rather than escaped.
|
|
151
|
+
*/
|
|
152
|
+
key: string;
|
|
153
|
+
/** Column heading. */
|
|
154
|
+
label: string;
|
|
155
|
+
/**
|
|
156
|
+
* `string` free text, `url` free text meant to be an address, `select` one of `options`, and
|
|
157
|
+
* `secret` a credential this row holds — write-only, encrypted per cell, and never in the row.
|
|
158
|
+
*/
|
|
159
|
+
type: 'string' | 'url' | 'select' | 'secret';
|
|
160
|
+
/** Whether a row is only counted once this cell is filled in. */
|
|
161
|
+
required?: boolean;
|
|
162
|
+
/** Ghost text inside the cell. */
|
|
163
|
+
placeholder?: string;
|
|
164
|
+
/** Choices, fixed when the manifest is written. See {@link ConfigField.options}. */
|
|
165
|
+
options?: ConfigFieldOption[];
|
|
166
|
+
/** Choices only the station can enumerate. See {@link ConfigFieldOptionSource}. */
|
|
167
|
+
optionsFrom?: ConfigFieldOptionSource;
|
|
168
|
+
/**
|
|
169
|
+
* Key of another column in the same list. This cell only applies to a row whose cell there
|
|
170
|
+
* holds one of {@link dependsOnValues}.
|
|
171
|
+
*
|
|
172
|
+
* For the table whose columns are not all about the same row: a provider list where the
|
|
173
|
+
* address belongs to a self-hosted server and the API key to a vendor, a supplier list where
|
|
174
|
+
* one kind is reached by URL and another by account id. Without it every column is drawn on
|
|
175
|
+
* every row, so an operator meets a cell their row has no use for, with no way to tell it from
|
|
176
|
+
* one they have not filled in yet.
|
|
177
|
+
*
|
|
178
|
+
* **This is not the rendering hint {@link ConfigField.dependsOn} is**, and the difference is
|
|
179
|
+
* the whole reason it is here. A field-level `dependsOn` hides a control and the server never
|
|
180
|
+
* reads it. This says the cell DOES NOT APPLY, so the console declines to send it and the host
|
|
181
|
+
* declines to derive anything from it — which for a `url` column means the row contributes no
|
|
182
|
+
* hostname to the plugin's allowlist (`addressCells` in `plugin.host.factory.ts`). An address
|
|
183
|
+
* typed on a row before its kind was changed would otherwise widen the allowlist by a host the
|
|
184
|
+
* plugin can never call, which is exactly the quiet widening that path exists to refuse.
|
|
185
|
+
*
|
|
186
|
+
* Forgiving in three places, all of them the same instinct as `isVisible` in the console's
|
|
187
|
+
* form: a target this list does not declare shows the cell, a target cell that is EMPTY shows
|
|
188
|
+
* the cell, and values without a target are ignored. The empty case is the load-bearing one. A
|
|
189
|
+
* column has no `default`, so a row somebody has just added holds `''` in every cell, and a
|
|
190
|
+
* rule that hid a cell there would hide it on the one row that most needs filling in.
|
|
191
|
+
*
|
|
192
|
+
* A `secret` cell that does not apply keeps whatever is stored rather than being cleared.
|
|
193
|
+
* Absent already means "keep it" in `plugin.config.rows.ts`, and reading a visibility rule as
|
|
194
|
+
* an instruction to destroy a credential would be a surprise nobody asked for.
|
|
195
|
+
*/
|
|
196
|
+
dependsOn?: string;
|
|
197
|
+
/**
|
|
198
|
+
* The values of the {@link dependsOn} cell that this one applies to. Ignored without a target.
|
|
199
|
+
*
|
|
200
|
+
* Omitted means "any value at all", which is what a field-level `dependsOn` already means, so
|
|
201
|
+
* an author who knows that one knows this.
|
|
202
|
+
*/
|
|
203
|
+
dependsOnValues?: string[];
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The chosen values of a `multiselect`, out of the string it is stored as.
|
|
207
|
+
*
|
|
208
|
+
* Stored as a JSON array because plugin config is a string map, and read back
|
|
209
|
+
* through here so every plugin agrees on the encoding. Tolerant on purpose: a
|
|
210
|
+
* value hand-edited into something unreadable answers empty rather than failing
|
|
211
|
+
* a load, which for a field like "which models can use tools" is the difference
|
|
212
|
+
* between a degraded station and one that will not start.
|
|
213
|
+
*/
|
|
214
|
+
export declare function parseMultiSelect(raw: unknown): string[];
|
|
215
|
+
/**
|
|
216
|
+
* The cell key a row's own identity is stored under.
|
|
217
|
+
*
|
|
218
|
+
* A reserved name rather than a column an author declares, because it is not data: nobody types it,
|
|
219
|
+
* nothing renders it, and a plugin that ignores it entirely is a plugin that behaves exactly as it
|
|
220
|
+
* did before this existed. The host mints one when a row is first saved and preserves it forever
|
|
221
|
+
* after.
|
|
222
|
+
*
|
|
223
|
+
* ## Why a row needs a name at all
|
|
224
|
+
*
|
|
225
|
+
* Only so a {@link ConfigFieldColumn} may be a `secret`. A secret is encrypted and kept out of the
|
|
226
|
+
* row, which means something has to say which row a given ciphertext belongs to — and until this
|
|
227
|
+
* existed the only answer was "the third one", from a console that rewrites the whole array on
|
|
228
|
+
* every save and lets the operator reorder it. Position is not identity. A `$` leads it because no
|
|
229
|
+
* sensible column key does, and because a row whose keys are printed somewhere reads as obviously
|
|
230
|
+
* not-a-column.
|
|
231
|
+
*/
|
|
232
|
+
export declare const ROW_ID_KEY = "$id";
|
|
233
|
+
/**
|
|
234
|
+
* Where a `secret` cell's ciphertext lives, in the same flat map a `secret` FIELD's does.
|
|
235
|
+
*
|
|
236
|
+
* `field/row/column`, joined on the one character a field key and a column key may not contain
|
|
237
|
+
* (both schemas refuse it below). That is what keeps this unambiguous against a plain secret
|
|
238
|
+
* field's key, which is a bare field key and can therefore never collide with a three-part one.
|
|
239
|
+
*
|
|
240
|
+
* One map rather than a nested shape because everything already built for secrets — encrypting per
|
|
241
|
+
* entry, reporting configured-ness as a boolean, the rule that no value ever leaves the server —
|
|
242
|
+
* works on a flat `Record<string, string>` and needed no changes to carry these.
|
|
243
|
+
*/
|
|
244
|
+
export declare function rowSecretKey(fieldKey: string, rowId: string, columnKey: string): string;
|
|
245
|
+
/**
|
|
246
|
+
* Whether a stored secret key belongs to a row rather than to a field.
|
|
247
|
+
*
|
|
248
|
+
* For the host, which merges stored secrets back into the form to validate it: a row's cells belong
|
|
249
|
+
* inside their row and putting them at the top level would show a plugin's schema three keys it has
|
|
250
|
+
* never declared.
|
|
251
|
+
*/
|
|
252
|
+
export declare function isRowSecretKey(key: string): boolean;
|
|
253
|
+
/**
|
|
254
|
+
* The rows of a `list` field, out of the string it is stored as.
|
|
255
|
+
*
|
|
256
|
+
* A JSON array of objects in a string, for {@link parseMultiSelect}'s reason and encoded the same
|
|
257
|
+
* way, so a `list` needs nothing of the storage path that a `string` did not already have. Tolerant
|
|
258
|
+
* in the same way and for the same stakes: anything unreadable is no rows rather than a plugin that
|
|
259
|
+
* will not load, and a cell that is not a string is dropped rather than stringified, since a number
|
|
260
|
+
* where a URL was expected is a mistake worth seeing as an empty cell.
|
|
261
|
+
*
|
|
262
|
+
* A row with nothing in it is dropped, because the form leaves one behind whenever an operator adds
|
|
263
|
+
* a row and thinks better of it.
|
|
264
|
+
*/
|
|
265
|
+
export declare function parseRows(raw: unknown): Record<string, string>[];
|
|
266
|
+
/**
|
|
267
|
+
* A declarative description of one row in a plugin's settings form. The host
|
|
268
|
+
* renders these; plugins never ship UI.
|
|
269
|
+
*/
|
|
270
|
+
export interface ConfigField {
|
|
271
|
+
/** Key this value is stored under, and the key `host.config`/`host.secrets` reads it back by. */
|
|
272
|
+
key: string;
|
|
273
|
+
/** Human label shown next to the input. */
|
|
274
|
+
label: string;
|
|
275
|
+
type: ConfigFieldType;
|
|
276
|
+
/** Whether the form refuses to save without a value. Defaults to false. */
|
|
277
|
+
required?: boolean;
|
|
278
|
+
/** Prefilled value. Never provide a default for a `secret`. */
|
|
279
|
+
default?: string | number | boolean;
|
|
280
|
+
/**
|
|
281
|
+
* What a `number`'s value is measured in. Ignored on every other type.
|
|
282
|
+
*
|
|
283
|
+
* See {@link ConfigFieldUnit}: the stored value stays in this unit and only the control the
|
|
284
|
+
* operator touches changes.
|
|
285
|
+
*/
|
|
286
|
+
unit?: ConfigFieldUnit;
|
|
287
|
+
/**
|
|
288
|
+
* The control to draw this field with, where the ordinary one for its type reads badly.
|
|
289
|
+
*
|
|
290
|
+
* `slider` is for a `number` and is ignored without both `min` and `max`; `tags` is for a
|
|
291
|
+
* `string`. See {@link ConfigFieldControl}. Nothing about the stored value changes either way.
|
|
292
|
+
*/
|
|
293
|
+
control?: ConfigFieldControl;
|
|
294
|
+
/**
|
|
295
|
+
* How coarsely a `control` moves. Ignored without one, and defaults to 1.
|
|
296
|
+
*
|
|
297
|
+
* The unit is the field's own, so a share between 0 and 1 wants `0.05` and a word count wants
|
|
298
|
+
* `10`. Worth setting on anything whose range is wider than the pixels it is drawn in, since
|
|
299
|
+
* the alternative is a control that can express values nobody wants and cannot be stopped on
|
|
300
|
+
* the ones they do.
|
|
301
|
+
*/
|
|
302
|
+
step?: number;
|
|
303
|
+
/**
|
|
304
|
+
* The smallest and largest a `number` may be, inclusive. Ignored on every other type.
|
|
305
|
+
*
|
|
306
|
+
* A range the field is DECLARED with rather than one the reader clamps to, which is the whole
|
|
307
|
+
* point: a resolver that clamps answers a legal number for an illegal one, so the station runs
|
|
308
|
+
* on something the console never showed and the operator never chose. Declared here, the console
|
|
309
|
+
* refuses it in front of them and the station's own settings route refuses it again for anything
|
|
310
|
+
* that did not come through a console.
|
|
311
|
+
*
|
|
312
|
+
* A plugin's config is NOT validated against these — the host stores what it is handed and a
|
|
313
|
+
* plugin's own schema is what judges it — so for a plugin these are a hint to the form. For a
|
|
314
|
+
* station setting they are enforced, in `serializeSetting`.
|
|
315
|
+
*/
|
|
316
|
+
min?: number;
|
|
317
|
+
max?: number;
|
|
318
|
+
/** Ghost text inside the input. */
|
|
319
|
+
placeholder?: string;
|
|
320
|
+
/** Longer explanation rendered under the input. */
|
|
321
|
+
help?: string;
|
|
322
|
+
/**
|
|
323
|
+
* Choices, for a `select` or a `multiselect`.
|
|
324
|
+
*
|
|
325
|
+
* Fixed when the manifest is written, so this is for a closed set the plugin
|
|
326
|
+
* decides. For anything the operator's own server decides, implement
|
|
327
|
+
* `suggestConfigOptions()` instead: what it returns for this key replaces
|
|
328
|
+
* these, and it can also turn a `string` into free text with suggestions.
|
|
329
|
+
*/
|
|
330
|
+
options?: ConfigFieldOption[];
|
|
331
|
+
/**
|
|
332
|
+
* Choices only the console can enumerate. See {@link ConfigFieldOptionSource}.
|
|
333
|
+
*
|
|
334
|
+
* The field-level twin of {@link ConfigFieldColumn.optionsFrom}, and it resolves the same way
|
|
335
|
+
* and merges at the same point: whatever `suggestConfigOptions()` says for this key wins, and
|
|
336
|
+
* this is what is offered when it says nothing.
|
|
337
|
+
*/
|
|
338
|
+
optionsFrom?: ConfigFieldOptionSource;
|
|
339
|
+
/**
|
|
340
|
+
* The columns of a `list`, in the order they are drawn. Ignored on every other type.
|
|
341
|
+
*
|
|
342
|
+
* A `list` with none is a field with nothing to fill in, so declare at least one.
|
|
343
|
+
*/
|
|
344
|
+
columns?: ConfigFieldColumn[];
|
|
345
|
+
/**
|
|
346
|
+
* Key of another field in the same form. This field is only shown when
|
|
347
|
+
* that field has a truthy value.
|
|
348
|
+
*/
|
|
349
|
+
dependsOn?: string;
|
|
350
|
+
/**
|
|
351
|
+
* Key of the `number` field that is the UPPER end of the range this one opens. Declared on the
|
|
352
|
+
* lower end only, and ignored on every other type.
|
|
353
|
+
*
|
|
354
|
+
* Two settings, still: each keeps its own key, its own row and its own validation, and
|
|
355
|
+
* `serializeSetting` refuses each one by name exactly as it did before. What this changes is
|
|
356
|
+
* that the console draws them as one control with two handles instead of two boxes that happen
|
|
357
|
+
* to sit next to each other.
|
|
358
|
+
*
|
|
359
|
+
* The reason is legibility. Two boxes cannot say that one is the far end of the other, so a
|
|
360
|
+
* range arrives as two settings whose labels have to carry the relationship ("fewest", "most",
|
|
361
|
+
* "the other end") and an operator reads the pair rather than seeing it. One track with two
|
|
362
|
+
* handles says it in the shape of the control.
|
|
363
|
+
*
|
|
364
|
+
* NOT correctness, which is worth stating because it is the plausible reason and it is wrong
|
|
365
|
+
* here: every reader of a paired setting in this station takes the two ends as an UNORDERED
|
|
366
|
+
* pair and sorts them, so a range stored the wrong way round has always been tolerated rather
|
|
367
|
+
* than obeyed. The handles not crossing is a nicety on top, not the point.
|
|
368
|
+
*
|
|
369
|
+
* Worth declaring only where the declared range is narrow enough that the whole track is
|
|
370
|
+
* usable. A pair bounded by a typo guard rather than by intent — one to a hundred and twenty
|
|
371
|
+
* minutes, for a station that runs eight to twelve — puts both handles in the first tenth and
|
|
372
|
+
* makes the exact figure somebody has in mind a pixel. Those stay two boxes.
|
|
373
|
+
*
|
|
374
|
+
* A rendering hint like {@link ConfigField.dependsOn}, and forgiving in the same way: if the
|
|
375
|
+
* named key is not in this form, both ends fall back to their own controls rather than one of
|
|
376
|
+
* them disappearing. A settings page that draws one group of a larger set is the ordinary case
|
|
377
|
+
* for that.
|
|
378
|
+
*/
|
|
379
|
+
rangeWith?: string;
|
|
380
|
+
}
|
|
381
|
+
export declare const configFieldOptionSchema: z.ZodObject<{
|
|
382
|
+
value: z.ZodString;
|
|
383
|
+
label: z.ZodString;
|
|
384
|
+
}, z.core.$strip>;
|
|
385
|
+
export declare const configFieldTypeSchema: z.ZodEnum<{
|
|
386
|
+
string: "string";
|
|
387
|
+
number: "number";
|
|
388
|
+
boolean: "boolean";
|
|
389
|
+
text: "text";
|
|
390
|
+
url: "url";
|
|
391
|
+
secret: "secret";
|
|
392
|
+
select: "select";
|
|
393
|
+
multiselect: "multiselect";
|
|
394
|
+
list: "list";
|
|
395
|
+
note: "note";
|
|
396
|
+
}>;
|
|
397
|
+
export declare const configFieldUnitSchema: z.ZodEnum<{
|
|
398
|
+
bytes: "bytes";
|
|
399
|
+
fraction: "fraction";
|
|
400
|
+
}>;
|
|
401
|
+
export declare const configFieldControlSchema: z.ZodEnum<{
|
|
402
|
+
slider: "slider";
|
|
403
|
+
tags: "tags";
|
|
404
|
+
}>;
|
|
405
|
+
/**
|
|
406
|
+
* Every member of {@link ConfigFieldOptionSource}, and it has to stay every member: this validates
|
|
407
|
+
* real manifests at load, so a source missing here is a plugin the host refuses to start. Two were
|
|
408
|
+
* missing for exactly that reason and nothing caught it, because no bundled plugin had asked for
|
|
409
|
+
* one yet.
|
|
410
|
+
*/
|
|
411
|
+
export declare const configFieldOptionSourceSchema: z.ZodEnum<{
|
|
412
|
+
"station.newsCategories": "station.newsCategories";
|
|
413
|
+
"station.newsFeeds": "station.newsFeeds";
|
|
414
|
+
"intl.timeZones": "intl.timeZones";
|
|
415
|
+
"plugins.speech": "plugins.speech";
|
|
416
|
+
"plugins.llm": "plugins.llm";
|
|
417
|
+
"plugins.mixer": "plugins.mixer";
|
|
418
|
+
"plugins.analysis": "plugins.analysis";
|
|
419
|
+
"llm.models": "llm.models";
|
|
420
|
+
}>;
|
|
421
|
+
export declare const configFieldColumnSchema: z.ZodObject<{
|
|
422
|
+
key: z.ZodString;
|
|
423
|
+
label: z.ZodString;
|
|
424
|
+
type: z.ZodEnum<{
|
|
425
|
+
string: "string";
|
|
426
|
+
url: "url";
|
|
427
|
+
secret: "secret";
|
|
428
|
+
select: "select";
|
|
429
|
+
}>;
|
|
430
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
431
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
432
|
+
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
433
|
+
value: z.ZodString;
|
|
434
|
+
label: z.ZodString;
|
|
435
|
+
}, z.core.$strip>>>;
|
|
436
|
+
optionsFrom: z.ZodOptional<z.ZodEnum<{
|
|
437
|
+
"station.newsCategories": "station.newsCategories";
|
|
438
|
+
"station.newsFeeds": "station.newsFeeds";
|
|
439
|
+
"intl.timeZones": "intl.timeZones";
|
|
440
|
+
"plugins.speech": "plugins.speech";
|
|
441
|
+
"plugins.llm": "plugins.llm";
|
|
442
|
+
"plugins.mixer": "plugins.mixer";
|
|
443
|
+
"plugins.analysis": "plugins.analysis";
|
|
444
|
+
"llm.models": "llm.models";
|
|
445
|
+
}>>;
|
|
446
|
+
dependsOn: z.ZodOptional<z.ZodString>;
|
|
447
|
+
dependsOnValues: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
448
|
+
}, z.core.$strip>;
|
|
449
|
+
export declare const configFieldSchema: z.ZodObject<{
|
|
450
|
+
key: z.ZodString;
|
|
451
|
+
label: z.ZodString;
|
|
452
|
+
type: z.ZodEnum<{
|
|
453
|
+
string: "string";
|
|
454
|
+
number: "number";
|
|
455
|
+
boolean: "boolean";
|
|
456
|
+
text: "text";
|
|
457
|
+
url: "url";
|
|
458
|
+
secret: "secret";
|
|
459
|
+
select: "select";
|
|
460
|
+
multiselect: "multiselect";
|
|
461
|
+
list: "list";
|
|
462
|
+
note: "note";
|
|
463
|
+
}>;
|
|
464
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
465
|
+
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
466
|
+
unit: z.ZodOptional<z.ZodEnum<{
|
|
467
|
+
bytes: "bytes";
|
|
468
|
+
fraction: "fraction";
|
|
469
|
+
}>>;
|
|
470
|
+
control: z.ZodOptional<z.ZodEnum<{
|
|
471
|
+
slider: "slider";
|
|
472
|
+
tags: "tags";
|
|
473
|
+
}>>;
|
|
474
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
475
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
476
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
477
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
478
|
+
help: z.ZodOptional<z.ZodString>;
|
|
479
|
+
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
480
|
+
value: z.ZodString;
|
|
481
|
+
label: z.ZodString;
|
|
482
|
+
}, z.core.$strip>>>;
|
|
483
|
+
optionsFrom: z.ZodOptional<z.ZodEnum<{
|
|
484
|
+
"station.newsCategories": "station.newsCategories";
|
|
485
|
+
"station.newsFeeds": "station.newsFeeds";
|
|
486
|
+
"intl.timeZones": "intl.timeZones";
|
|
487
|
+
"plugins.speech": "plugins.speech";
|
|
488
|
+
"plugins.llm": "plugins.llm";
|
|
489
|
+
"plugins.mixer": "plugins.mixer";
|
|
490
|
+
"plugins.analysis": "plugins.analysis";
|
|
491
|
+
"llm.models": "llm.models";
|
|
492
|
+
}>>;
|
|
493
|
+
columns: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
494
|
+
key: z.ZodString;
|
|
495
|
+
label: z.ZodString;
|
|
496
|
+
type: z.ZodEnum<{
|
|
497
|
+
string: "string";
|
|
498
|
+
url: "url";
|
|
499
|
+
secret: "secret";
|
|
500
|
+
select: "select";
|
|
501
|
+
}>;
|
|
502
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
503
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
504
|
+
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
505
|
+
value: z.ZodString;
|
|
506
|
+
label: z.ZodString;
|
|
507
|
+
}, z.core.$strip>>>;
|
|
508
|
+
optionsFrom: z.ZodOptional<z.ZodEnum<{
|
|
509
|
+
"station.newsCategories": "station.newsCategories";
|
|
510
|
+
"station.newsFeeds": "station.newsFeeds";
|
|
511
|
+
"intl.timeZones": "intl.timeZones";
|
|
512
|
+
"plugins.speech": "plugins.speech";
|
|
513
|
+
"plugins.llm": "plugins.llm";
|
|
514
|
+
"plugins.mixer": "plugins.mixer";
|
|
515
|
+
"plugins.analysis": "plugins.analysis";
|
|
516
|
+
"llm.models": "llm.models";
|
|
517
|
+
}>>;
|
|
518
|
+
dependsOn: z.ZodOptional<z.ZodString>;
|
|
519
|
+
dependsOnValues: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
520
|
+
}, z.core.$strip>>>;
|
|
521
|
+
dependsOn: z.ZodOptional<z.ZodString>;
|
|
522
|
+
rangeWith: z.ZodOptional<z.ZodString>;
|
|
523
|
+
}, z.core.$strip>;
|
|
524
|
+
//# sourceMappingURL=plugin.config.fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.config.fields.d.ts","sourceRoot":"","sources":["../src/plugin.config.fields.ts"],"names":[],"mappings":"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"}
|