@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,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `search` kind. A search plugin answers an OPEN question by asking a search
|
|
3
|
+
* engine, and hands back what the engine said.
|
|
4
|
+
*
|
|
5
|
+
* ## This is the open web, not the library
|
|
6
|
+
*
|
|
7
|
+
* Nothing here is about records. Looking for something to play is
|
|
8
|
+
* `music.provider.searchTracks`, which answers with tracks that carry provider
|
|
9
|
+
* ids the pick path can resolve; every result here is a page, and a page cannot
|
|
10
|
+
* be scheduled. The two are different questions with different answers, and the
|
|
11
|
+
* host keeps them apart so a model steered by one is never handed the other.
|
|
12
|
+
*
|
|
13
|
+
* ## Why this is not `news`
|
|
14
|
+
*
|
|
15
|
+
* A news plugin serves a MENU an operator assembled: feeds somebody chose, with
|
|
16
|
+
* ids, categories and a de-duplication contract, answering "what happened". This
|
|
17
|
+
* answers "what does the web say about X" — the caller supplies the subject, the
|
|
18
|
+
* plugin has no idea what will come back, and there is nothing stable to
|
|
19
|
+
* de-duplicate against because no two calls ask the same question.
|
|
20
|
+
*
|
|
21
|
+
* ## It reports what the engine said, and it does not summarise
|
|
22
|
+
*
|
|
23
|
+
* A {@link SearchResult.snippet} is the engine's own text, trimmed of markup and
|
|
24
|
+
* otherwise untouched. Several engines will also sell a synthesized ANSWER —
|
|
25
|
+
* Tavily's `answer`, SearXNG's infobox — and this capability deliberately has
|
|
26
|
+
* nowhere to put one. That paragraph is somebody else's model paraphrasing pages
|
|
27
|
+
* this station never sees, so nothing can check it against a source, and a claim
|
|
28
|
+
* that cannot be checked is one the station must not broadcast. The same
|
|
29
|
+
* boundary `capabilities/enrichment.ts` keeps with `SourceDocument`: a plugin
|
|
30
|
+
* fetches and the host thinks.
|
|
31
|
+
*
|
|
32
|
+
* A plugin that wants to contribute PROSE the host can extract claims from
|
|
33
|
+
* declares `enrichment` as well and returns documents there, where the fact
|
|
34
|
+
* store's provenance and quote checking already live.
|
|
35
|
+
*
|
|
36
|
+
* ## Nothing here airs
|
|
37
|
+
*
|
|
38
|
+
* A result is words on a page. Whether any of it is spoken is settled by a break
|
|
39
|
+
* writer on a station that is on air, and this capability has no way to reach one.
|
|
40
|
+
*
|
|
41
|
+
* Every shape here is JSON-safe.
|
|
42
|
+
*/
|
|
43
|
+
/**
|
|
44
|
+
* How fresh a result has to be.
|
|
45
|
+
*
|
|
46
|
+
* Coarse on purpose, because that is how every engine models it: Brave takes
|
|
47
|
+
* `pd|pw|pm|py`, SearXNG takes `day|week|month|year`, and an exact window is not
|
|
48
|
+
* on offer anywhere. A plugin whose engine cannot filter by age ignores it
|
|
49
|
+
* rather than filtering the page itself, since a result's date is frequently the
|
|
50
|
+
* one field an engine gets wrong.
|
|
51
|
+
*/
|
|
52
|
+
export type SearchRecency = 'day' | 'week' | 'month' | 'year';
|
|
53
|
+
/** What a search source is asked. */
|
|
54
|
+
export interface SearchQuery {
|
|
55
|
+
/** The words to search for, as somebody would type them. */
|
|
56
|
+
query: string;
|
|
57
|
+
/** How many results to return. A plugin may return fewer; it must not return more. */
|
|
58
|
+
limit: number;
|
|
59
|
+
/** Only results this recent, when the engine can say. Absent for anything, whatever its age. */
|
|
60
|
+
recency?: SearchRecency;
|
|
61
|
+
/** ISO 639-1, when the caller has an opinion about what language the answer should be in. */
|
|
62
|
+
language?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Only pages on these hostnames, when the caller is asking a narrow question.
|
|
65
|
+
*
|
|
66
|
+
* Every engine expresses this and none of them agree on how: `site:` in the
|
|
67
|
+
* query for the ones that take operators, a list parameter for the ones that
|
|
68
|
+
* do not. A plugin that cannot ask its engine at all filters what came back
|
|
69
|
+
* rather than ignoring this, because a caller that named its sites is
|
|
70
|
+
* usually about to do something with the pages that only holds for those
|
|
71
|
+
* sites — which is what the enrichment half of `plugins/websearch` does with
|
|
72
|
+
* the operator's own allowlist.
|
|
73
|
+
*
|
|
74
|
+
* Bare hostnames, no scheme and no path. Best-effort in the sense that an
|
|
75
|
+
* engine may still find nothing on them; never in the sense that something
|
|
76
|
+
* else may come back.
|
|
77
|
+
*/
|
|
78
|
+
sites?: string[];
|
|
79
|
+
}
|
|
80
|
+
/** One hit. */
|
|
81
|
+
export interface SearchResult {
|
|
82
|
+
/** The page's title, as the engine gave it. */
|
|
83
|
+
title: string;
|
|
84
|
+
/**
|
|
85
|
+
* The engine's own extract, as PLAIN TEXT.
|
|
86
|
+
*
|
|
87
|
+
* Never markup. Search APIs are the worst offenders here: Brave highlights
|
|
88
|
+
* query terms with `<strong>` unless told not to, and descriptions carry
|
|
89
|
+
* HTML entities either way. Both end up in a model's context and possibly in
|
|
90
|
+
* a speaking voice, so `html.text.ts` is what a plugin runs them through.
|
|
91
|
+
*/
|
|
92
|
+
snippet: string;
|
|
93
|
+
/** Where the page is. Kept so a caller can cite it, read it, or check it against an allowlist. */
|
|
94
|
+
url: string;
|
|
95
|
+
/**
|
|
96
|
+
* Who published it, in the fewest words a presenter could say out loud.
|
|
97
|
+
*
|
|
98
|
+
* The engine's own profile name where it has one, and the hostname
|
|
99
|
+
* otherwise. It exists because attribution is the only part of a result a
|
|
100
|
+
* station can broadcast: a URL read aloud is the least useful sentence radio
|
|
101
|
+
* has ever carried, and "according to the Guardian" is a real one.
|
|
102
|
+
*/
|
|
103
|
+
site?: string;
|
|
104
|
+
/** ISO-8601. Never a `Date`, and absent whenever the engine did not say — which is most results. */
|
|
105
|
+
publishedAt?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Implemented by a `search` plugin.
|
|
109
|
+
*/
|
|
110
|
+
export interface SearchProvider {
|
|
111
|
+
/**
|
|
112
|
+
* Run the query, best first.
|
|
113
|
+
*
|
|
114
|
+
* An empty array is an ordinary answer and not a failure: an unconfigured
|
|
115
|
+
* plugin, an engine that is down, a rate limit and a query nothing matches
|
|
116
|
+
* are one outcome to every caller, and the difference belongs in the
|
|
117
|
+
* plugin's own log. Throw only for something the operator has to fix, since
|
|
118
|
+
* the host turns a throw into a line an operator reads.
|
|
119
|
+
*/
|
|
120
|
+
search(query: SearchQuery): Promise<SearchResult[]>;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/capabilities/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAE9D,qCAAqC;AACrC,MAAM,WAAW,WAAW;IACxB,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,eAAe;AACf,MAAM,WAAW,YAAY;IACzB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oGAAoG;IACpG,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACvD"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { ArtistRef } from './enrichment.js';
|
|
2
|
+
/**
|
|
3
|
+
* The `similarity` kind. A similarity plugin answers "who else sounds like this",
|
|
4
|
+
* and optionally "what should I play by them".
|
|
5
|
+
*
|
|
6
|
+
* ## Why this is not part of `enrichment`
|
|
7
|
+
*
|
|
8
|
+
* Enrichment describes something the catalog HOLDS: the host walks its own rows,
|
|
9
|
+
* stores an answer per provider against the row, and trusts it for ninety days.
|
|
10
|
+
* Every part of that machinery is keyed to a catalog row.
|
|
11
|
+
*
|
|
12
|
+
* The artists worth asking about here are precisely the ones the catalog does not
|
|
13
|
+
* hold. A station that only ever hears about acts already in its library is
|
|
14
|
+
* exactly the bubble this exists to break — so the question cannot be keyed to a
|
|
15
|
+
* row, and the answer is not a fact to store against one. It is a list of NAMES
|
|
16
|
+
* that feeds the same pick path a chart does, where the rules already decide what
|
|
17
|
+
* may actually air.
|
|
18
|
+
*
|
|
19
|
+
* ## Names in, names out
|
|
20
|
+
*
|
|
21
|
+
* Nothing here carries a track id, a provider id or a URL, and that is what keeps
|
|
22
|
+
* a similarity plugin from being able to put a record on air. It suggests; the
|
|
23
|
+
* host looks the suggestion up, ingests it if a provider has it, and then judges
|
|
24
|
+
* it like anything else.
|
|
25
|
+
*
|
|
26
|
+
* Every shape here is JSON-safe.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* An artist a source says resembles the one that was asked about.
|
|
30
|
+
*
|
|
31
|
+
* `mbid` and `providerRef` mirror {@link ArtistRef}'s: the first crosses
|
|
32
|
+
* providers, the second is this plugin's own id handed back so a follow-up is a
|
|
33
|
+
* lookup rather than another search. Neither is promised — the name is the only
|
|
34
|
+
* field anything downstream requires, because the name is what the pick path
|
|
35
|
+
* matches on.
|
|
36
|
+
*/
|
|
37
|
+
export interface SimilarArtist {
|
|
38
|
+
name: string;
|
|
39
|
+
/** MusicBrainz artist id, when the source knows one. */
|
|
40
|
+
mbid?: string;
|
|
41
|
+
/** This plugin's own id for the artist, for a later {@link SimilarityProvider.artistTopTracks}. */
|
|
42
|
+
providerRef?: string;
|
|
43
|
+
/**
|
|
44
|
+
* How alike, from 0 to 1, where the source scores it.
|
|
45
|
+
*
|
|
46
|
+
* A HINT for ordering and nothing else. Sources score on wildly different
|
|
47
|
+
* bases — co-listening, tags, editorial — so the host orders within one
|
|
48
|
+
* source's answer and never compares two sources' numbers as if they meant
|
|
49
|
+
* the same thing.
|
|
50
|
+
*/
|
|
51
|
+
match?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A record by an artist, offered as something to play.
|
|
55
|
+
*
|
|
56
|
+
* The same shape a chart entry reduces to, and for the same reason: it is a
|
|
57
|
+
* title and a lead artist, which is what a pick is.
|
|
58
|
+
*/
|
|
59
|
+
export interface ArtistTrack {
|
|
60
|
+
title: string;
|
|
61
|
+
/**
|
|
62
|
+
* The LEAD artist, never a credit line.
|
|
63
|
+
*
|
|
64
|
+
* The same correctness rule the chart capability carries: everything
|
|
65
|
+
* downstream matches a pick on the lead artist alone, so a joined credit is
|
|
66
|
+
* a record that is named correctly and then dropped as one nothing can find.
|
|
67
|
+
*/
|
|
68
|
+
artist: string;
|
|
69
|
+
album?: string;
|
|
70
|
+
year?: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Implemented by a `similarity` plugin.
|
|
74
|
+
*/
|
|
75
|
+
export interface SimilarityProvider {
|
|
76
|
+
/**
|
|
77
|
+
* Artists that resemble this one, best first.
|
|
78
|
+
*
|
|
79
|
+
* An empty array is an ordinary answer and not a failure: an unconfigured
|
|
80
|
+
* plugin, an artist the source has never heard of, and one nothing resembles
|
|
81
|
+
* are all "nothing to add".
|
|
82
|
+
*
|
|
83
|
+
* `limit` is a ceiling on what to return. Returning fewer is fine; returning
|
|
84
|
+
* more wastes an upstream call, since the host trims.
|
|
85
|
+
*/
|
|
86
|
+
similarArtists(ref: ArtistRef, limit: number): Promise<SimilarArtist[]>;
|
|
87
|
+
/**
|
|
88
|
+
* What to play by an artist, best first.
|
|
89
|
+
*
|
|
90
|
+
* Optional, the way `enrichArtist` is on the enrichment capability. A source
|
|
91
|
+
* that can only say who sounds alike is a legitimate plugin — but note what
|
|
92
|
+
* absent costs: the host has a name and no way to turn it into a record, so
|
|
93
|
+
* a plugin without this can inform a DJ and cannot programme an hour.
|
|
94
|
+
*
|
|
95
|
+
* The artist here is one the caller chose, which is usually one this plugin
|
|
96
|
+
* itself named. When it carries a `providerRef` this plugin put there, that
|
|
97
|
+
* is its own id coming back.
|
|
98
|
+
*/
|
|
99
|
+
artistTopTracks?(ref: ArtistRef, limit: number): Promise<ArtistTrack[]>;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=similarity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../../src/capabilities/similarity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B;;;;;;;;;OASG;IACH,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAExE;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;CAC3E"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `speech` capability. A speech plugin takes a line of text and answers
|
|
3
|
+
* with audio: the station saying its own name, reading a back-announce, or
|
|
4
|
+
* delivering a whole talk break.
|
|
5
|
+
*
|
|
6
|
+
* ## The audio comes back as a stream, not as a value
|
|
7
|
+
*
|
|
8
|
+
* {@link SpeechPluginInstance.speak} returns a stream rather than bytes, and
|
|
9
|
+
* the usual implementation is to hand back the `host.fetch` body of the engine
|
|
10
|
+
* call unchanged. So the audio is never held whole anywhere, and a long script
|
|
11
|
+
* costs a chunk of memory rather than a file of it.
|
|
12
|
+
*
|
|
13
|
+
* Cancellation is the host's `cancel()` on that stream, and forwarding a
|
|
14
|
+
* `host.fetch` body propagates it to the socket for you. There is nothing to
|
|
15
|
+
* implement.
|
|
16
|
+
*
|
|
17
|
+
* ## A voice is a name the station chose, not one your engine knows
|
|
18
|
+
*
|
|
19
|
+
* {@link SpeechRequest.voice} is an opaque id from the station's side of the
|
|
20
|
+
* fence — `host`, `newsreader` — and mapping it to whatever your engine actually
|
|
21
|
+
* takes is your job, out of your own config. The host never reads it, never
|
|
22
|
+
* validates it, and never stores anything engine-specific.
|
|
23
|
+
*
|
|
24
|
+
* The indirection is the point, and it was paid for once already: it is what
|
|
25
|
+
* lets the same station voice be a named preset on one engine and a cloned
|
|
26
|
+
* reference clip on another, so changing engine does not rewrite every persona.
|
|
27
|
+
* Keep engine-specific tuning (an expressiveness dial, a similarity weight)
|
|
28
|
+
* inside your own config where it belongs, rather than asking the host to carry
|
|
29
|
+
* knobs only you understand.
|
|
30
|
+
*
|
|
31
|
+
* Every shape here is JSON-safe.
|
|
32
|
+
*/
|
|
33
|
+
import type { PluginLifecycle } from '../plugin.lifecycle.js';
|
|
34
|
+
/**
|
|
35
|
+
* The things a presenter DOES that are not words, as the station names them.
|
|
36
|
+
*
|
|
37
|
+
* A cue rides inside {@link SpeechRequest.text} rather than beside it, written
|
|
38
|
+
* `[laugh]`, which is why nothing in this interface carries one. That is not a
|
|
39
|
+
* shortcut: a laugh happens at a place in a sentence, and a field would have to
|
|
40
|
+
* invent a way to say where.
|
|
41
|
+
*
|
|
42
|
+
* The vocabulary is the STATION's and mapping it is yours, exactly as for
|
|
43
|
+
* {@link SpeechVoice}. A laugh is something a presenter does; whether your engine
|
|
44
|
+
* spells it `[laugh]`, `<laugh>` or not at all is engine business, and the host
|
|
45
|
+
* never learns which.
|
|
46
|
+
*
|
|
47
|
+
* ## Eight, and the second four are not for the presenter
|
|
48
|
+
*
|
|
49
|
+
* This was four, and its stated reason for stopping there was that "a cough or a
|
|
50
|
+
* sniff reads as illness rather than as delivery". That is right about somebody
|
|
51
|
+
* being paid to talk and exactly wrong about somebody on the end of a telephone,
|
|
52
|
+
* where the throat-clear IS the realism — so the vocabulary is wider now and WHO
|
|
53
|
+
* may use which is the host's business rather than this list's.
|
|
54
|
+
*
|
|
55
|
+
* The host keeps the first four. A caller in a production may use all eight. Both
|
|
56
|
+
* sets live app-side, because they are permissions rather than capabilities, and
|
|
57
|
+
* a plugin has no way to know which of its speakers is which.
|
|
58
|
+
*
|
|
59
|
+
* **Widening this list without narrowing the offer is how the presenter starts
|
|
60
|
+
* coughing.** Whatever reads a script back has to be told which of these were
|
|
61
|
+
* actually on offer to the person who wrote it, rather than reaching for the whole
|
|
62
|
+
* vocabulary.
|
|
63
|
+
*
|
|
64
|
+
* Still chosen rather than copied from an engine: `shush` is one this list does
|
|
65
|
+
* not take, because shushing is aimed AT somebody in the room. That is a piece of
|
|
66
|
+
* business rather than a way of delivering a line.
|
|
67
|
+
*
|
|
68
|
+
* **Answer {@link SpeechPluginInstance.listCues} honestly and the rest is free.**
|
|
69
|
+
* The host strips every cue you do not claim before it calls {@link
|
|
70
|
+
* SpeechPluginInstance.speak}, so a plugin that implements nothing here never sees
|
|
71
|
+
* one, and the failure where an engine READS the word "laugh" out loud cannot
|
|
72
|
+
* happen. Claiming one you cannot perform is the only way to break that.
|
|
73
|
+
*/
|
|
74
|
+
export declare const SPEECH_CUES: readonly ["laugh", "chuckle", "sigh", "gasp", "cough", "clear throat", "sniff", "groan"];
|
|
75
|
+
/** One of {@link SPEECH_CUES}. */
|
|
76
|
+
export type SpeechCue = (typeof SPEECH_CUES)[number];
|
|
77
|
+
/** Every cue written into a script, in the order they appear, with repeats. */
|
|
78
|
+
export declare function cuesIn(text: string): SpeechCue[];
|
|
79
|
+
/**
|
|
80
|
+
* The same text with cues removed, or with only some of them kept.
|
|
81
|
+
*
|
|
82
|
+
* `keep` is the set to LEAVE, so the default of none is "take them all out" — the
|
|
83
|
+
* safe direction, and the one an engine that has never heard of a cue wants. A
|
|
84
|
+
* removal closes the space it leaves behind, because `word [laugh] word` would
|
|
85
|
+
* otherwise render with a double space that {@link SPEECH_CUES}' own consumers
|
|
86
|
+
* would have to know to tidy.
|
|
87
|
+
*
|
|
88
|
+
* Only the four are touched. Anything else in brackets is somebody else's problem
|
|
89
|
+
* and stays exactly as it arrived: this is not a bracket stripper.
|
|
90
|
+
*/
|
|
91
|
+
export declare function withoutCues(text: string, keep?: Iterable<SpeechCue>): string;
|
|
92
|
+
/** One thing to say. */
|
|
93
|
+
export interface SpeechRequest {
|
|
94
|
+
/**
|
|
95
|
+
* The words, already final. Nothing downstream rewrites them, so any
|
|
96
|
+
* pronunciation fixing your engine needs is yours to apply.
|
|
97
|
+
*/
|
|
98
|
+
text: string;
|
|
99
|
+
/**
|
|
100
|
+
* Which station voice to use, or absent for this plugin's default.
|
|
101
|
+
*
|
|
102
|
+
* Opaque, and a name the operator chose. An id you have no mapping for
|
|
103
|
+
* should fall back to your default rather than fail: a missing voice is
|
|
104
|
+
* worth a `logger.warn` and a rendered line, not a silent station.
|
|
105
|
+
*/
|
|
106
|
+
voice?: string;
|
|
107
|
+
/**
|
|
108
|
+
* The audio format the caller would prefer, as a bare extension (`mp3`).
|
|
109
|
+
*
|
|
110
|
+
* A hint, and the weakest thing in this interface: answer with whatever you
|
|
111
|
+
* actually produced in {@link SpeechHandle.mime} and the host will believe
|
|
112
|
+
* that instead. Ignore it entirely if your engine emits one format.
|
|
113
|
+
*/
|
|
114
|
+
format?: string;
|
|
115
|
+
}
|
|
116
|
+
/** The audio for one {@link SpeechPluginInstance.speak}, and what it is. */
|
|
117
|
+
export interface SpeechHandle {
|
|
118
|
+
/**
|
|
119
|
+
* What the bytes ARE, as a media type (`audio/mpeg`).
|
|
120
|
+
*
|
|
121
|
+
* Load-bearing rather than decoration: it is what the host stores the audio
|
|
122
|
+
* under and what it later serves, and both consumers of station audio (a
|
|
123
|
+
* browser's `<audio>`, which does not sniff, and the playout engine, which
|
|
124
|
+
* picks its decoder from the content type) go by that header rather than by
|
|
125
|
+
* the bytes. A wav announced as `audio/mpeg` fails as silence rather than
|
|
126
|
+
* as an error anybody sees.
|
|
127
|
+
*/
|
|
128
|
+
mime: string;
|
|
129
|
+
/**
|
|
130
|
+
* The audio.
|
|
131
|
+
*
|
|
132
|
+
* The host reads it to the end or cancels it, and either one releases
|
|
133
|
+
* whatever is underneath. Usually a `host.fetch` body forwarded unchanged,
|
|
134
|
+
* which is what makes that true for free.
|
|
135
|
+
*/
|
|
136
|
+
audio: ReadableStream<Uint8Array>;
|
|
137
|
+
}
|
|
138
|
+
/** One voice this plugin can be asked for. */
|
|
139
|
+
export interface SpeechVoice {
|
|
140
|
+
/** The id to pass back as {@link SpeechRequest.voice}. */
|
|
141
|
+
id: string;
|
|
142
|
+
/** What the console calls it. */
|
|
143
|
+
label: string;
|
|
144
|
+
/** Anything worth knowing when choosing between them: an accent, a register. */
|
|
145
|
+
description?: string;
|
|
146
|
+
/**
|
|
147
|
+
* An opaque token that changes when what this voice SOUNDS LIKE changes.
|
|
148
|
+
*
|
|
149
|
+
* The host does not interpret it, parse it, store it or show it. It uses it
|
|
150
|
+
* for one thing: keying the cached preview at `GET /voices/{id}/sample`, so
|
|
151
|
+
* that remapping `host` from one engine voice to another — or nudging its
|
|
152
|
+
* speed, or swapping its reference clip — mints a new key and the next
|
|
153
|
+
* preview renders instead of playing the old voice back.
|
|
154
|
+
*
|
|
155
|
+
* That was already the claim `VoiceSampleStore` made in its own doc comment
|
|
156
|
+
* and it was not true: the key held the STATION voice id, which is exactly
|
|
157
|
+
* the part that does not change when an operator edits the mapping under it.
|
|
158
|
+
* The fence is intact because this stays opaque — whatever string identifies
|
|
159
|
+
* a rendering to you is the right value, and `engineVoice@speed` is a fine
|
|
160
|
+
* one.
|
|
161
|
+
*
|
|
162
|
+
* Absent is normal. A plugin that omits it keys previews as it always did,
|
|
163
|
+
* which is correct for one whose voices cannot be reconfigured.
|
|
164
|
+
*/
|
|
165
|
+
spec?: string;
|
|
166
|
+
}
|
|
167
|
+
/** A plugin that can speak. */
|
|
168
|
+
export interface SpeechPluginInstance extends PluginLifecycle {
|
|
169
|
+
/**
|
|
170
|
+
* Start turning `request.text` into audio.
|
|
171
|
+
*
|
|
172
|
+
* May return before any audio exists, because the handle carries a stream
|
|
173
|
+
* and not the bytes, so a slow engine shows up as a slow first chunk rather
|
|
174
|
+
* than as a slow `speak`.
|
|
175
|
+
*
|
|
176
|
+
* @throws {PluginError} `config` when the plugin is not set up enough to try
|
|
177
|
+
* (no server address), `upstream` when the engine refused or answered with
|
|
178
|
+
* something that is not audio, `timeout` when it did not answer at all.
|
|
179
|
+
*/
|
|
180
|
+
speak(request: SpeechRequest): Promise<SpeechHandle>;
|
|
181
|
+
/**
|
|
182
|
+
* The voices this plugin can be asked for, for a console that has to draw a
|
|
183
|
+
* list.
|
|
184
|
+
*
|
|
185
|
+
* Optional, because a plugin with exactly one voice is a legitimate thing to
|
|
186
|
+
* be and should not have to describe it. Absent is normal, not broken.
|
|
187
|
+
*/
|
|
188
|
+
listVoices?(): Promise<SpeechVoice[]>;
|
|
189
|
+
/**
|
|
190
|
+
* Which of {@link SPEECH_CUES} this plugin can perform RIGHT NOW.
|
|
191
|
+
*
|
|
192
|
+
* Optional, and absent means none: an engine that only reads words is the
|
|
193
|
+
* ordinary case and should not have to say so. That default is what makes this
|
|
194
|
+
* safe to add — the host strips what you do not claim, so silence costs a
|
|
195
|
+
* plugin nothing and risks nothing.
|
|
196
|
+
*
|
|
197
|
+
* **Answer from what the engine currently IS, not from what this plugin was
|
|
198
|
+
* built against.** On the engine this was written for, cues belong to the
|
|
199
|
+
* loaded MODEL rather than to the server, so swapping the model takes them away
|
|
200
|
+
* with no plugin change involved — which is exactly the case a manifest flag
|
|
201
|
+
* would get wrong, and it would get it wrong by having the station perform to
|
|
202
|
+
* an engine that reads the word out.
|
|
203
|
+
*
|
|
204
|
+
* Called on the path that writes a break as well as the one that speaks it, so
|
|
205
|
+
* keep it cheap and answer empty rather than throwing when the engine cannot be
|
|
206
|
+
* reached: a station that cannot ask should write a script with no cues in it,
|
|
207
|
+
* not fail to write one.
|
|
208
|
+
*/
|
|
209
|
+
listCues?(): Promise<readonly SpeechCue[]>;
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=speech.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speech.d.ts","sourceRoot":"","sources":["../../src/capabilities/speech.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,WAAW,0FAA2F,CAAC;AAEpH,kCAAkC;AAClC,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,+EAA+E;AAC/E,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAEhD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,QAAQ,CAAC,SAAS,CAAM,GAAG,MAAM,CAQhF;AAYD,wBAAwB;AACxB,MAAM,WAAW,aAAa;IAC1B;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IACzB;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;OAMG;IACH,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;CACrC;AAED,8CAA8C;AAC9C,MAAM,WAAW,WAAW;IACxB,0DAA0D;IAC1D,EAAE,EAAE,MAAM,CAAC;IAEX,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IAEd,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,+BAA+B;AAC/B,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IACzD;;;;;;;;;;OAUG;IACH,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAErD;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEtC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,IAAI,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC,CAAC;CAC9C"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `weather` kind. A weather plugin answers "what is it like outside", for
|
|
3
|
+
* one place, as numbers.
|
|
4
|
+
*
|
|
5
|
+
* ## Why this is not `news`, and not `search`
|
|
6
|
+
*
|
|
7
|
+
* All three answer about the world rather than about records, and they are asked
|
|
8
|
+
* different questions. News serves a MENU an operator assembled and answers
|
|
9
|
+
* "what happened", with a de-duplication contract because the same entry comes
|
|
10
|
+
* back on every poll. Search takes words the caller made up and answers "what
|
|
11
|
+
* does the web say about that", with nothing stable to de-duplicate against.
|
|
12
|
+
* This is asked about one PLACE and answers with measurements — a temperature is
|
|
13
|
+
* not a headline, and the station wants to do arithmetic on it rather than read
|
|
14
|
+
* it out verbatim.
|
|
15
|
+
*
|
|
16
|
+
* ## The plugin resolves the place, and the host never geocodes
|
|
17
|
+
*
|
|
18
|
+
* {@link WeatherQuery.place} is a name somebody typed, and turning it into
|
|
19
|
+
* coordinates is exactly the per-service quirk this boundary exists to absorb:
|
|
20
|
+
* one service ships a geocoder, one takes coordinates only, one wants its own
|
|
21
|
+
* city ids. A host that geocoded would have to pick one of those services to
|
|
22
|
+
* geocode WITH, which is the shape of dependency a capability is supposed to
|
|
23
|
+
* remove.
|
|
24
|
+
*
|
|
25
|
+
* {@link WeatherReading.place} comes back as the SERVICE resolved it, because a
|
|
26
|
+
* DJ has to be able to say a real place name rather than whatever was typed into
|
|
27
|
+
* a settings box.
|
|
28
|
+
*
|
|
29
|
+
* ## Everything is metric
|
|
30
|
+
*
|
|
31
|
+
* Temperatures in Celsius, wind in km/h, and no unit field anywhere. What a
|
|
32
|
+
* station SAYS is a station's own decision — a British station says Celsius
|
|
33
|
+
* whichever service it reads — and it is settled where the words are made,
|
|
34
|
+
* beside every other decision about how this station talks. A plugin converting
|
|
35
|
+
* would mean the units on the wire depended on which plugin was installed, which
|
|
36
|
+
* is the one thing a capability must not let happen.
|
|
37
|
+
*
|
|
38
|
+
* This is `ConfigField.unit`'s rule one layer down: the value on the wire is
|
|
39
|
+
* always the declared unit, and nothing downstream learns that the presentation
|
|
40
|
+
* converts.
|
|
41
|
+
*
|
|
42
|
+
* ## A condition is a closed vocabulary
|
|
43
|
+
*
|
|
44
|
+
* {@link WeatherCondition} is short and fixed. WMO code 73, an icon string of
|
|
45
|
+
* `snow`, and a numeric condition id are three spellings of the same weather,
|
|
46
|
+
* and mapping them is the plugin's job for {@link WeatherQuery.place}'s reason.
|
|
47
|
+
* The service's own word survives beside it as
|
|
48
|
+
* {@link WeatherConditions.description}, unread by anything that speaks
|
|
49
|
+
* deterministically and available to a model that wants a phrase somebody wrote.
|
|
50
|
+
*
|
|
51
|
+
* ## Nothing here airs
|
|
52
|
+
*
|
|
53
|
+
* A reading is a number. Whether any of it is spoken is settled by a break
|
|
54
|
+
* writer on a station that is on air, and this capability has no way to reach
|
|
55
|
+
* one.
|
|
56
|
+
*
|
|
57
|
+
* Every shape here is JSON-safe.
|
|
58
|
+
*/
|
|
59
|
+
/**
|
|
60
|
+
* What the sky is doing, in the fewest words that are still distinguishable.
|
|
61
|
+
*
|
|
62
|
+
* Ten arms, chosen so a station can say something true about each one without a
|
|
63
|
+
* caveat, and deliberately not a scale: an intensity ("heavy rain") belongs on
|
|
64
|
+
* the numbers, where a caller can decide for itself what counts as heavy. Every
|
|
65
|
+
* service's own scheme collapses onto this and the plugin is what does the
|
|
66
|
+
* collapsing.
|
|
67
|
+
*/
|
|
68
|
+
export type WeatherCondition = 'clear' | 'cloudy' | 'overcast' | 'fog' | 'drizzle' | 'rain' | 'snow' | 'sleet' | 'thunderstorm' | 'hail';
|
|
69
|
+
/** What a weather source is asked. */
|
|
70
|
+
export interface WeatherQuery {
|
|
71
|
+
/**
|
|
72
|
+
* The place, as somebody wrote it: `Atlanta`, `Chipping Norton, Oxfordshire`.
|
|
73
|
+
*
|
|
74
|
+
* Resolved by the plugin. See the note on this file about why the host does
|
|
75
|
+
* not do it, and {@link WeatherReading.place} for what comes back.
|
|
76
|
+
*/
|
|
77
|
+
place: string;
|
|
78
|
+
/**
|
|
79
|
+
* How many days of forecast to include beyond the current conditions.
|
|
80
|
+
*
|
|
81
|
+
* `0` or absent asks for now alone, which is the common call. A count rather
|
|
82
|
+
* than named horizons (`today`, `tomorrow`, `week`) because those are words
|
|
83
|
+
* for a person and this is a number for a service — and because the words
|
|
84
|
+
* differ per caller: a break writer's "the weekend" and a model's "this week"
|
|
85
|
+
* are the same request with different arithmetic in front of it.
|
|
86
|
+
*
|
|
87
|
+
* A plugin CAPS this at whatever its service will give and answers with what
|
|
88
|
+
* it got, rather than refusing. Asking for more days than exist is a caller
|
|
89
|
+
* being optimistic, not a caller being wrong.
|
|
90
|
+
*/
|
|
91
|
+
days?: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* What it is like, at one moment or across one day.
|
|
95
|
+
*
|
|
96
|
+
* Every measurement is optional, and that is a fact about the services rather
|
|
97
|
+
* than caution: they report different subsets, a forecast day carries figures an
|
|
98
|
+
* observation does not, and a station that must ask whether it HAS the humidity
|
|
99
|
+
* before mentioning it is a station that never says something it does not know.
|
|
100
|
+
* A zero would be a lie in exactly the cases that matter.
|
|
101
|
+
*/
|
|
102
|
+
export interface WeatherConditions {
|
|
103
|
+
condition: WeatherCondition;
|
|
104
|
+
/**
|
|
105
|
+
* The service's own words for it: `light drizzle`, `partly cloudy`.
|
|
106
|
+
*
|
|
107
|
+
* Raw material for a model, never read verbatim by anything deterministic —
|
|
108
|
+
* the same standing `NewsItem.summary` has. Plain text, and absent whenever
|
|
109
|
+
* the service offers nothing better than the code that became
|
|
110
|
+
* {@link condition}.
|
|
111
|
+
*/
|
|
112
|
+
description?: string;
|
|
113
|
+
/** Degrees Celsius. See the note on this file: everything here is metric. */
|
|
114
|
+
temperatureC?: number;
|
|
115
|
+
/** Degrees Celsius, as it feels with the wind and the humidity, when the service computes one. */
|
|
116
|
+
feelsLikeC?: number;
|
|
117
|
+
/** Kilometres per hour. */
|
|
118
|
+
windKph?: number;
|
|
119
|
+
/** Relative humidity, as a percentage between 0 and 100. */
|
|
120
|
+
humidity?: number;
|
|
121
|
+
/** The chance of precipitation, as a percentage between 0 and 100. Rare on an observation. */
|
|
122
|
+
precipitationChance?: number;
|
|
123
|
+
}
|
|
124
|
+
/** One day of the forecast. */
|
|
125
|
+
export interface WeatherDay extends WeatherConditions {
|
|
126
|
+
/**
|
|
127
|
+
* The calendar day AT THE PLACE, as `YYYY-MM-DD`. Never a `Date`.
|
|
128
|
+
*
|
|
129
|
+
* At the place rather than at the server, because that is the only reading of
|
|
130
|
+
* it that makes "tomorrow" mean what a listener thinks it means. A station in
|
|
131
|
+
* one timezone reporting a town in another is an ordinary thing to ask for.
|
|
132
|
+
*/
|
|
133
|
+
date: string;
|
|
134
|
+
highC?: number;
|
|
135
|
+
lowC?: number;
|
|
136
|
+
/** ISO-8601. Never a `Date`. */
|
|
137
|
+
sunrise?: string;
|
|
138
|
+
/** ISO-8601. Never a `Date`. */
|
|
139
|
+
sunset?: string;
|
|
140
|
+
}
|
|
141
|
+
/** What one place is like. */
|
|
142
|
+
export interface WeatherReading {
|
|
143
|
+
/**
|
|
144
|
+
* The place as the SERVICE resolved it, which is not what was asked for.
|
|
145
|
+
*
|
|
146
|
+
* Kept because it is the part a presenter says out loud, and because it is
|
|
147
|
+
* the only evidence anybody has that the right town was found: a station
|
|
148
|
+
* announcing the weather in Birmingham, Alabama to an audience in Birmingham
|
|
149
|
+
* is a failure nothing else here can detect.
|
|
150
|
+
*/
|
|
151
|
+
place: string;
|
|
152
|
+
/**
|
|
153
|
+
* When the observation was made, as an ISO-8601 string. Never a `Date`.
|
|
154
|
+
*
|
|
155
|
+
* Not when it was fetched. A plugin serving a cached reading reports the age
|
|
156
|
+
* of the READING, which is what lets a caller decide a forecast is too old to
|
|
157
|
+
* broadcast — a decision no plugin is in a position to make, since only the
|
|
158
|
+
* caller knows whether anybody is listening.
|
|
159
|
+
*/
|
|
160
|
+
observedAt: string;
|
|
161
|
+
/** What it is like right now. */
|
|
162
|
+
current: WeatherConditions;
|
|
163
|
+
/**
|
|
164
|
+
* Today first, then forward.
|
|
165
|
+
*
|
|
166
|
+
* Absent or empty when {@link WeatherQuery.days} asked for none, and when the
|
|
167
|
+
* service has no forecast to give. Those are the same answer to a caller, and
|
|
168
|
+
* the difference belongs in the plugin's own log.
|
|
169
|
+
*/
|
|
170
|
+
days?: WeatherDay[];
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Implemented by a `weather` plugin.
|
|
174
|
+
*/
|
|
175
|
+
export interface WeatherProvider {
|
|
176
|
+
/**
|
|
177
|
+
* What it is like there.
|
|
178
|
+
*
|
|
179
|
+
* `undefined` is an ordinary answer and not a failure: an unconfigured
|
|
180
|
+
* plugin, a place the service could not resolve, and a service that is down
|
|
181
|
+
* are one outcome to every caller, which is {@link SearchProvider.search}'s
|
|
182
|
+
* empty array wearing the shape this capability has. Throw only for something
|
|
183
|
+
* the operator has to go and fix, since the host turns a throw into a line an
|
|
184
|
+
* operator reads.
|
|
185
|
+
*
|
|
186
|
+
* A place that resolved to somewhere unexpected is NOT one of those cases and
|
|
187
|
+
* must be answered rather than swallowed — {@link WeatherReading.place} is
|
|
188
|
+
* how that becomes visible.
|
|
189
|
+
*/
|
|
190
|
+
getWeather(query: WeatherQuery): Promise<WeatherReading | undefined>;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=weather.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weather.d.ts","sourceRoot":"","sources":["../../src/capabilities/weather.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,cAAc,GAAG,MAAM,CAAC;AAEzI,sCAAsC;AACtC,MAAM,WAAW,YAAY;IACzB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,gBAAgB,CAAC;IAC5B;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kGAAkG;IAClG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8FAA8F;IAC9F,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,+BAA+B;AAC/B,MAAM,WAAW,UAAW,SAAQ,iBAAiB;IACjD;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,8BAA8B;AAC9B,MAAM,WAAW,cAAc;IAC3B;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,OAAO,EAAE,iBAAiB,CAAC;IAC3B;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;CACxE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|