@deadair/plugin-sdk 0.8.2 → 0.9.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/README.md CHANGED
@@ -20,6 +20,7 @@ A plugin extends deadair by declaring capabilities:
20
20
  | `charts` | say what is popular: a chart id in, ranked names out |
21
21
  | `similarity` | say who else sounds like this: an artist in, artists out |
22
22
  | `news` | say what happened outside the station: a feed in, entries out |
23
+ | `podcast` | carry somebody else's programme: a show in, episodes out |
23
24
  | `search` | ask the open web a question: words in, pages out |
24
25
  | `weather` | say what it is like outside: a place in, measurements out |
25
26
  | `scrobble` | report what the station played to somebody else's service |
@@ -564,6 +565,62 @@ Note what `search` is not. Looking for something to PLAY is `searchTracks` on
564
565
  the catalog capability, which answers with provider ids the station can resolve
565
566
  into audio. Nothing a search plugin returns can be scheduled.
566
567
 
568
+ ## Carrying podcasts
569
+
570
+ A `podcast` plugin says what programmes the station subscribes to and what each
571
+ has published. Two methods are required and one is optional:
572
+
573
+ ```ts
574
+ async listShows(): Promise<PodcastShow[]> {
575
+ return this.subscriptions.map(row => ({ id: row.id, title: row.name, feedUrl: row.url }));
576
+ }
577
+
578
+ async listEpisodes({ showId, limit, since }: PodcastEpisodesQuery): Promise<PodcastEpisode[]> {
579
+ const feed = await fetchFeed(this.host, this.feedFor(showId));
580
+ return feed.items
581
+ .filter(item => item.enclosure !== undefined) // no audio, no episode
582
+ .map(item => ({ id: item.id, showId, showTitle: feed.title ?? '', title: item.title,
583
+ durationMs: item.durationMs, audio: { url: item.enclosure!.url } }))
584
+ .slice(0, limit);
585
+ }
586
+ ```
587
+
588
+ `parseFeed` reads a podcast feed's enclosure and `itunes:duration` for you, so
589
+ most of a feed-reading podcast plugin is the mapping above. Four things about it
590
+ are easy to get wrong.
591
+
592
+ **You never fetch the audio.** `audio.url` is an address the HOST fetches, once,
593
+ hours before the episode is due on air, into the station's own store. An episode
594
+ is far larger than any body a plugin is allowed to read through `host.fetch`,
595
+ and when it is wanted is a station decision you cannot see. So the address has
596
+ to carry whatever it needs, like `resolveStreamUrl`'s: it is fetched with no
597
+ headers from you.
598
+
599
+ **An id is a promise.** The station remembers which episodes it has fetched and
600
+ aired by `PodcastEpisode.id`, so the same episode must have the same id on every
601
+ call, or it is fetched and aired twice. `FeedItem.id` already keeps that promise.
602
+
603
+ **Leave out what cannot be carried.** An entry with no enclosure, or one at an
604
+ address nothing can fetch, is not an episode the station can air; handing it over
605
+ only makes the host drop it. And `durationMs` is the publisher's claim, passed
606
+ on as one. Do not estimate a length from a file size.
607
+
608
+ **An empty array is an answer**, on the terms `search` and `news` set: a show
609
+ whose feed is down, an id you no longer recognise and a show with nothing
610
+ published are one outcome to the host, and one show's bad day must not cost the
611
+ others.
612
+
613
+ `searchShows` is a directory, for an operator looking for something to subscribe
614
+ to, and it answers with `PodcastDirectoryEntry` rather than `PodcastShow`: its
615
+ `id` is the directory's own and its `feedUrl` is what subscribing needs. What a
616
+ subscription IS stays yours, which is why there is no method for it.
617
+
618
+ Note what this capability is not: a `catalog`. An episode is not a record, and
619
+ every rule the station applies to a record, from rotation and artist spacing to
620
+ crossfading and scrobbling, is wrong for an hour of somebody else's programme.
621
+ The station carries an episode the way it carries a programme it made itself:
622
+ one item, aired whole, as speech, when a clock band names the show.
623
+
567
624
  ## Saying what it is like outside
568
625
 
569
626
  A `weather` plugin has one method, and the caller supplies the place:
@@ -39,6 +39,7 @@ import type { AnalysisRef, TrackAnalysis, TrackCuePoints, TrackLoudness, TrackTa
39
39
  import type { AudioJoin, AudioOverlay } from './capabilities/mixer.js';
40
40
  import type { ChartDescriptor, ChartEntry, ChartQuery } from './capabilities/charts.js';
41
41
  import type { NewsFeedDescriptor, NewsItem, NewsQuery } from './capabilities/news.js';
42
+ import type { PodcastAudio, PodcastDirectoryEntry, PodcastDirectoryQuery, PodcastEpisode, PodcastEpisodesQuery, PodcastShow } from './capabilities/podcast.js';
42
43
  import type { ScrobblePlay, ScrobbleRejection, ScrobbleResult } from './capabilities/scrobble.js';
43
44
  import type { SearchQuery, SearchResult } from './capabilities/search.js';
44
45
  import type { ArtistTrack, SimilarArtist } from './capabilities/similarity.js';
@@ -148,6 +149,12 @@ export type AssertAllBoundaryPayloadsAreJsonSafe = AssertAllTrue<{
148
149
  NewsFeedDescriptor: IsJsonSafe<NewsFeedDescriptor>;
149
150
  NewsQuery: IsJsonSafe<NewsQuery>;
150
151
  NewsItem: IsJsonSafe<NewsItem>;
152
+ PodcastShow: IsJsonSafe<PodcastShow>;
153
+ PodcastAudio: IsJsonSafe<PodcastAudio>;
154
+ PodcastEpisode: IsJsonSafe<PodcastEpisode>;
155
+ PodcastEpisodesQuery: IsJsonSafe<PodcastEpisodesQuery>;
156
+ PodcastDirectoryQuery: IsJsonSafe<PodcastDirectoryQuery>;
157
+ PodcastDirectoryEntry: IsJsonSafe<PodcastDirectoryEntry>;
151
158
  SimilarArtist: IsJsonSafe<SimilarArtist>;
152
159
  ArtistTrack: IsJsonSafe<ArtistTrack>;
153
160
  SearchQuery: IsJsonSafe<SearchQuery>;
@@ -165,7 +172,7 @@ export type AssertAllBoundaryPayloadsAreJsonSafe = AssertAllTrue<{
165
172
  * registry-coverage test can compare it against what is actually exported
166
173
  * from the boundary source files.
167
174
  */
168
- export declare const JSON_SAFE_PAYLOAD_TYPES: readonly ["PluginConnectionResult", "PluginPermissions", "NetworkPermissionHost", "NetworkPermissionFromConfig", "PluginGrantRequest", "ConfigField", "ConfigFieldOption", "ConfigFieldColumn", "PluginManifest", "ProviderTrack", "ProviderPlaylist", "ProviderStream", "TrackFetchSession", "TrackFetchRequest", "SearchTracksOptions", "ListPlaylistsOptions", "GetPlaylistTracksOptions", "PlaybackState", "TrackRef", "ArtistRef", "AlbumRef", "ExternalId", "ExternalLink", "SourceDocument", "TrackEnrichment", "ArtistEnrichment", "AlbumEnrichment", "SpeechRequest", "SpeechVoice", "LlmMessage", "LlmToolDeclaration", "LlmToolCall", "LlmUsage", "LlmRequest", "LlmResult", "LlmModelInfo", "AnalysisRef", "AudioJoin", "AudioOverlay", "TrackCuePoints", "TrackLoudness", "TrackTaggedLoudness", "TrackAnalysis", "ChartDescriptor", "ChartQuery", "ChartEntry", "NewsFeedDescriptor", "NewsQuery", "NewsItem", "SimilarArtist", "ArtistTrack", "SearchQuery", "SearchResult", "WeatherQuery", "WeatherConditions", "WeatherDay", "WeatherReading", "ScrobblePlay", "ScrobbleRejection", "ScrobbleResult"];
175
+ export declare const JSON_SAFE_PAYLOAD_TYPES: readonly ["PluginConnectionResult", "PluginPermissions", "NetworkPermissionHost", "NetworkPermissionFromConfig", "PluginGrantRequest", "ConfigField", "ConfigFieldOption", "ConfigFieldColumn", "PluginManifest", "ProviderTrack", "ProviderPlaylist", "ProviderStream", "TrackFetchSession", "TrackFetchRequest", "SearchTracksOptions", "ListPlaylistsOptions", "GetPlaylistTracksOptions", "PlaybackState", "TrackRef", "ArtistRef", "AlbumRef", "ExternalId", "ExternalLink", "SourceDocument", "TrackEnrichment", "ArtistEnrichment", "AlbumEnrichment", "SpeechRequest", "SpeechVoice", "LlmMessage", "LlmToolDeclaration", "LlmToolCall", "LlmUsage", "LlmRequest", "LlmResult", "LlmModelInfo", "AnalysisRef", "AudioJoin", "AudioOverlay", "TrackCuePoints", "TrackLoudness", "TrackTaggedLoudness", "TrackAnalysis", "ChartDescriptor", "ChartQuery", "ChartEntry", "NewsFeedDescriptor", "NewsQuery", "NewsItem", "PodcastShow", "PodcastAudio", "PodcastEpisode", "PodcastEpisodesQuery", "PodcastDirectoryQuery", "PodcastDirectoryEntry", "SimilarArtist", "ArtistTrack", "SearchQuery", "SearchResult", "WeatherQuery", "WeatherConditions", "WeatherDay", "WeatherReading", "ScrobblePlay", "ScrobbleRejection", "ScrobbleResult"];
169
176
  /**
170
177
  * Boundary interfaces that are deliberately NOT payloads: they describe
171
178
  * methods, so they carry functions by definition and can never be JSON-safe.
@@ -175,7 +182,7 @@ export declare const JSON_SAFE_PAYLOAD_TYPES: readonly ["PluginConnectionResult"
175
182
  * interfaces explicitly is what makes "is this a payload or a contract?" a
176
183
  * conscious decision for anyone adding one, rather than a silent omission.
177
184
  */
178
- export declare const BOUNDARY_METHOD_TYPES: readonly ["PluginLogger", "PluginStorage", "PluginSecrets", "PluginConfigAccess", "PluginOAuth", "PluginEvents", "PluginTrackFetcher", "PluginHost", "PluginLifecycle", "MusicProviderCatalog", "MusicProviderStream", "MusicProviderSteer", "MusicProviderOAuth", "MusicProvider", "EnrichmentProvider", "SpeechPluginInstance", "LlmPluginInstance", "AnalysisProvider", "MixerProvider", "ChartsProvider", "NewsProvider", "SimilarityProvider", "SearchProvider", "WeatherProvider", "ScrobbleProvider"];
185
+ export declare const BOUNDARY_METHOD_TYPES: readonly ["PluginLogger", "PluginStorage", "PluginSecrets", "PluginConfigAccess", "PluginOAuth", "PluginEvents", "PluginTrackFetcher", "PluginHost", "PluginLifecycle", "MusicProviderCatalog", "MusicProviderStream", "MusicProviderSteer", "MusicProviderOAuth", "MusicProvider", "EnrichmentProvider", "SpeechPluginInstance", "LlmPluginInstance", "AnalysisProvider", "MixerProvider", "ChartsProvider", "NewsProvider", "PodcastProvider", "SimilarityProvider", "SearchProvider", "WeatherProvider", "ScrobbleProvider"];
179
186
  /**
180
187
  * Boundary interfaces that deliberately carry a LIVE object, and so are neither
181
188
  * payloads nor method contracts.
@@ -1 +1 @@
1
- {"version":3,"file":"boundary.json.safe.d.ts","sourceRoot":"","sources":["../src/boundary.json.safe.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"boundary.json.safe.d.ts","sourceRoot":"","sources":["../src/boundary.json.safe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,248 @@
1
+ /**
2
+ * The `podcast` kind. A podcast plugin answers "what programmes has this
3
+ * station subscribed to, and what has each of them published", as episodes
4
+ * somebody else made.
5
+ *
6
+ * ## It reports, and the host fetches
7
+ *
8
+ * Nothing here plays anything, schedules anything, or fetches the audio. A
9
+ * plugin hands over what its feeds published, with each episode's audio as an
10
+ * ADDRESS, and the station decides whether and when to carry it. The host then
11
+ * fetches that address itself, once, hours ahead of the slot, into the same
12
+ * store the station's own recordings live in. Two reasons it is the host and not
13
+ * the plugin:
14
+ *
15
+ * - **Size.** An episode is tens of megabytes, often more than a hundred. Every
16
+ * body a plugin reads through `host.fetch` is bounded well below that, on
17
+ * purpose, and raising the bound for one capability would raise it for every
18
+ * plugin reading through the same guard.
19
+ * - **Timing.** The audio is wanted when a clock band asks for it, which is a
20
+ * station decision a plugin cannot see. A plugin that fetched on its own
21
+ * schedule would either fetch everything or guess.
22
+ *
23
+ * The same boundary `capabilities/news.ts` keeps, one step further: a news
24
+ * plugin reports and the station decides what to SAY; a podcast plugin reports
25
+ * and the station decides what to AIR. A source able to put itself on air is a
26
+ * source that can talk over an operator's decisions.
27
+ *
28
+ * ## An episode is not a record
29
+ *
30
+ * Deliberately not a `catalog` provider with shows for playlists and episodes
31
+ * for tracks, which is the shape that needs nothing new and is wrong everywhere
32
+ * it touches. The station treats a record as a song: it draws it into rotation,
33
+ * spaces it by artist, asks the enrichment sources about it, measures it,
34
+ * crossfades into it, scrobbles it at half its length, and refuses its file past
35
+ * the size of an album. An hour-long programme survives none of that. What it
36
+ * needs is what the station already does for a programme it made itself — one
37
+ * item that airs whole, as speech, at the time a clock band says — and the
38
+ * shapes below are what that needs and no more.
39
+ *
40
+ * ## `id`s are a de-duplication contract
41
+ *
42
+ * **A {@link PodcastEpisode.id} is stable for the same episode across calls**,
43
+ * on exactly `news.ts`'s terms, because the host remembers which episodes it has
44
+ * fetched and which it has aired by that id. A plugin that renumbered would have
45
+ * the station fetch and air the same episode twice. Building episodes with
46
+ * `parseFeed` gives this for free; it is where the ladder lives. A
47
+ * {@link PodcastShow.id} is stable in the same way, for as long as the operator
48
+ * keeps the subscription.
49
+ *
50
+ * Every shape here is JSON-safe.
51
+ */
52
+ /**
53
+ * One programme this plugin carries: something the operator subscribed to.
54
+ *
55
+ * `id` is scoped to this plugin and needs to be unique only within it. The host
56
+ * qualifies it before anything outside sees it, so a short flat id is right.
57
+ */
58
+ export interface PodcastShow {
59
+ id: string;
60
+ /** What the show calls itself, e.g. `The Long Wave`. What a presenter says out loud. */
61
+ title: string;
62
+ /** Who makes it, as the publisher writes it. */
63
+ author?: string;
64
+ /** What the show says about itself, as PLAIN TEXT. It may reach a model's context. */
65
+ description?: string;
66
+ /** The show's artwork. Always http(s), and stable across calls (README rule 7). */
67
+ artworkUrl?: string;
68
+ /** Where the show lives for a person, as opposed to its feed. */
69
+ homeUrl?: string;
70
+ /**
71
+ * Where the show's feed is, when the plugin reads one.
72
+ *
73
+ * Reported so the console can say which subscription a show came from and
74
+ * tell a directory result apart from a show the station already carries.
75
+ * Nothing fetches it but the plugin.
76
+ */
77
+ feedUrl?: string;
78
+ /** ISO 639-1, or the feed's own tag (`en-gb`), when the plugin knows. */
79
+ language?: string;
80
+ /** The publisher's own labels, unmapped. */
81
+ categories?: string[];
82
+ /**
83
+ * Whether the publisher marked the whole show explicit. Absent means the
84
+ * feed did not say, which is not the same as clean; see
85
+ * {@link PodcastEpisode.explicit}.
86
+ */
87
+ explicit?: boolean;
88
+ }
89
+ /**
90
+ * Where an episode's audio is, and what the publisher says about it.
91
+ *
92
+ * Only `url` is load-bearing. The rest are the publisher's claims, passed on as
93
+ * claims: the host reads the bytes it actually receives and decides from those
94
+ * what it holds. `mimeType` in particular is whatever the publisher's CMS wrote,
95
+ * and `audio/x-m4a`, `audio/mp3` and an empty string are all ordinary.
96
+ */
97
+ export interface PodcastAudio {
98
+ /**
99
+ * An http(s) address the HOST will fetch, with no headers from the plugin.
100
+ *
101
+ * The same rule `ProviderStream.url` is under and for the same reason:
102
+ * whatever authentication it needs has to be in the address, because it is
103
+ * fetched by somebody other than the plugin that found it. A feed that
104
+ * needs a login for its audio is one this capability cannot carry.
105
+ */
106
+ url: string;
107
+ mimeType?: string;
108
+ /** The declared size in bytes. A claim, and a hint about cost rather than a limit. */
109
+ lengthBytes?: number;
110
+ }
111
+ /** One programme a show published. */
112
+ export interface PodcastEpisode {
113
+ /** Stable across calls. See the de-duplication contract in this file's header. */
114
+ id: string;
115
+ /** The {@link PodcastShow.id} this belongs to, as the plugin's own unqualified id. */
116
+ showId: string;
117
+ /** That show's title, so a caller reading one list can say what it is part of. */
118
+ showTitle: string;
119
+ title: string;
120
+ /**
121
+ * What the publisher says the episode is about, as PLAIN TEXT.
122
+ *
123
+ * The line a presenter reaches for when introducing it, which is why it has
124
+ * to be plain: it ends up in a model's context and possibly a voice.
125
+ */
126
+ summary?: string;
127
+ /** The episode's page, for a person. Never the audio; that is {@link audio}. */
128
+ url?: string;
129
+ /** ISO-8601. Never a `Date`, and absent when the feed published no readable one. */
130
+ publishedAt?: string;
131
+ /**
132
+ * How long it runs, in whole milliseconds, as the publisher says.
133
+ *
134
+ * A claim, and the only length the station has before the bytes arrive, so
135
+ * it is what an episode is planned against. Absent when the feed made none:
136
+ * a plugin must not estimate one from a file size.
137
+ */
138
+ durationMs?: number;
139
+ audio: PodcastAudio;
140
+ /** The episode's own artwork where it has some, else the show's. Always http(s). */
141
+ artworkUrl?: string;
142
+ /** The publisher's season number, a positive whole number. */
143
+ season?: number;
144
+ /** The publisher's episode number within its season, a positive whole number. */
145
+ number?: number;
146
+ /**
147
+ * Whether the publisher marked this episode explicit.
148
+ *
149
+ * Absent means the feed did not say, which is not the same as clean. A host
150
+ * enforcing a clean-only policy has to demand a positive `false`, on
151
+ * `ProviderTrack.advisory`'s argument: treating silence as consent is how a
152
+ * station promises something it cannot deliver.
153
+ */
154
+ explicit?: boolean;
155
+ }
156
+ /** What a podcast source is asked for when the host wants a show's episodes. */
157
+ export interface PodcastEpisodesQuery {
158
+ /**
159
+ * A {@link PodcastShow.id} this plugin offered.
160
+ *
161
+ * Required, unlike `NewsQuery.feedId`, because an episode is always of a
162
+ * show and the host keeps them per show. "Everything, merged" is a question
163
+ * nobody here asks.
164
+ */
165
+ showId: string;
166
+ /** How many episodes to return, newest first. A plugin may return fewer; it must not return more. */
167
+ limit: number;
168
+ /**
169
+ * Only episodes published after this instant, as an ISO-8601 string.
170
+ *
171
+ * A plugin that cannot filter upstream filters what it got rather than
172
+ * ignoring this, `NewsQuery.since`'s rule. An undated episode is kept: it is
173
+ * unjudgeable rather than old.
174
+ */
175
+ since?: string;
176
+ }
177
+ /** What a directory is asked when an operator looks for a show to subscribe to. */
178
+ export interface PodcastDirectoryQuery {
179
+ /** Words the operator typed: a show's name, a publisher, a subject. */
180
+ query: string;
181
+ /** How many results to return. A plugin may return fewer; it must not return more. */
182
+ limit: number;
183
+ }
184
+ /**
185
+ * A show a directory knows about, which the station may or may not carry.
186
+ *
187
+ * Its own shape rather than a {@link PodcastShow}, because the two answer
188
+ * different questions: a show is something this plugin will list episodes of,
189
+ * and this is somewhere an operator could point it. `id` is the DIRECTORY'S
190
+ * identifier, meaningful to nothing here but as a key in a list, and `feedUrl`
191
+ * is what subscribing actually needs.
192
+ */
193
+ export interface PodcastDirectoryEntry {
194
+ id: string;
195
+ title: string;
196
+ /** Where the show's feed is. Required: a directory result nobody can subscribe to is no result. */
197
+ feedUrl: string;
198
+ author?: string;
199
+ /** PLAIN TEXT. */
200
+ description?: string;
201
+ /** Always http(s). */
202
+ artworkUrl?: string;
203
+ homeUrl?: string;
204
+ categories?: string[];
205
+ explicit?: boolean;
206
+ }
207
+ /**
208
+ * Implemented by a `podcast` plugin.
209
+ */
210
+ export interface PodcastProvider {
211
+ /**
212
+ * What this plugin carries, right now.
213
+ *
214
+ * Asked per call rather than cached by the host, for the reason
215
+ * `NewsProvider.listFeeds` is: an operator editing a subscription
216
+ * reinitializes the plugin, and a list built from a config field would
217
+ * otherwise be a boot snapshot of a setting that has since changed.
218
+ *
219
+ * An empty array is an ordinary answer. A plugin nobody has subscribed to
220
+ * anything yet has nothing to offer, and that is not a failure.
221
+ */
222
+ listShows(): Promise<PodcastShow[]>;
223
+ /**
224
+ * A show's episodes, newest first, each with an address its audio can be
225
+ * fetched from.
226
+ *
227
+ * Leave out an entry that attaches no audio, or attaches it somewhere
228
+ * nothing can fetch: an episode without {@link PodcastEpisode.audio} is not
229
+ * one the station can carry, and handing it over only makes the host drop
230
+ * it. Return `[]` for a `showId` you do not recognise rather than throwing
231
+ * — the host asks the plugin that named the id, so an unknown one is a
232
+ * stale request — and the same for a show whose feed could not be read:
233
+ * one failing show must not cost the others.
234
+ */
235
+ listEpisodes(query: PodcastEpisodesQuery): Promise<PodcastEpisode[]>;
236
+ /**
237
+ * Shows a directory knows about, for an operator looking for something to
238
+ * subscribe to.
239
+ *
240
+ * Optional: a plugin that reads only the feeds it was given is a complete
241
+ * podcast plugin. Subscribing is not part of this capability, because what
242
+ * a subscription IS (a row in a config field, an account on a service) is
243
+ * each plugin's own business. An empty array is an answer, including for a
244
+ * directory that is down.
245
+ */
246
+ searchShows?(query: PodcastDirectoryQuery): Promise<PodcastDirectoryEntry[]>;
247
+ }
248
+ //# sourceMappingURL=podcast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"podcast.d.ts","sourceRoot":"","sources":["../../src/capabilities/podcast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,wFAAwF;IACxF,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IACzB;;;;;;;OAOG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,sCAAsC;AACtC,MAAM,WAAW,cAAc;IAC3B,kFAAkF;IAClF,EAAE,EAAE,MAAM,CAAC;IACX,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,YAAY,CAAC;IACpB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,gFAAgF;AAChF,MAAM,WAAW,oBAAoB;IACjC;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,qGAAqG;IACrG,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,mFAAmF;AACnF,MAAM,WAAW,qBAAqB;IAClC,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,qBAAqB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B;;;;;;;;;;OAUG;IACH,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEpC;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAErE;;;;;;;;;OASG;IACH,WAAW,CAAC,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;CAChF"}
@@ -2,6 +2,7 @@ import type { ChartsProvider } from './capabilities/charts.js';
2
2
  import type { EnrichmentProvider } from './capabilities/enrichment.js';
3
3
  import type { MusicProviderCatalog, MusicProviderOAuth, MusicProviderSteer, MusicProviderStream } from './capabilities/music.provider.js';
4
4
  import type { NewsProvider } from './capabilities/news.js';
5
+ import type { PodcastProvider } from './capabilities/podcast.js';
5
6
  import type { ScrobbleProvider } from './capabilities/scrobble.js';
6
7
  import type { SearchProvider } from './capabilities/search.js';
7
8
  import type { SimilarityProvider } from './capabilities/similarity.js';
@@ -35,6 +36,8 @@ export type EnrichmentPluginInstance = PluginLifecycle & EnrichmentProvider;
35
36
  export type ChartsPluginInstance = PluginLifecycle & ChartsProvider;
36
37
  /** Instance shape for a `news` plugin. */
37
38
  export type NewsPluginInstance = PluginLifecycle & NewsProvider;
39
+ /** Instance shape for a `podcast` plugin. `searchShows` stays optional, as it is on the capability. */
40
+ export type PodcastPluginInstance = PluginLifecycle & PodcastProvider;
38
41
  /** Instance shape for a `similarity` plugin. */
39
42
  export type SimilarityPluginInstance = PluginLifecycle & SimilarityProvider;
40
43
  /** Instance shape for a `search` plugin. */
@@ -1 +1 @@
1
- {"version":3,"file":"define.plugin.d.ts","sourceRoot":"","sources":["../src/define.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC1I,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC;AAE7C;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,SAAS,SAAS,cAAc,GAAG,cAAc,IAAI,MAAM,SAAS,CAAC;AAE/F,6CAA6C;AAC7C,MAAM,WAAW,aAAa,CAAC,SAAS,SAAS,cAAc,GAAG,cAAc;IAC5E,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG,eAAe,GACrD,OAAO,CAAC,oBAAoB,CAAC,GAC7B,OAAO,CAAC,mBAAmB,CAAC,GAC5B,OAAO,CAAC,kBAAkB,CAAC,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEhC,iDAAiD;AACjD,MAAM,MAAM,wBAAwB,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAE5E,4CAA4C;AAC5C,MAAM,MAAM,oBAAoB,GAAG,eAAe,GAAG,cAAc,CAAC;AAEpE,0CAA0C;AAC1C,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,YAAY,CAAC;AAEhE,gDAAgD;AAChD,MAAM,MAAM,wBAAwB,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAE5E,4CAA4C;AAC5C,MAAM,MAAM,oBAAoB,GAAG,eAAe,GAAG,cAAc,CAAC;AAEpE,6CAA6C;AAC7C,MAAM,MAAM,qBAAqB,GAAG,eAAe,GAAG,eAAe,CAAC;AAEtE,8CAA8C;AAC9C,MAAM,MAAM,sBAAsB,GAAG,eAAe,GAAG,gBAAgB,CAAC;AAExE;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,SAAS,SAAS,cAAc,EACzD,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,GAClC,aAAa,CAAC,SAAS,CAAC,CAE1B"}
1
+ {"version":3,"file":"define.plugin.d.ts","sourceRoot":"","sources":["../src/define.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC1I,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC;AAE7C;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,SAAS,SAAS,cAAc,GAAG,cAAc,IAAI,MAAM,SAAS,CAAC;AAE/F,6CAA6C;AAC7C,MAAM,WAAW,aAAa,CAAC,SAAS,SAAS,cAAc,GAAG,cAAc;IAC5E,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG,eAAe,GACrD,OAAO,CAAC,oBAAoB,CAAC,GAC7B,OAAO,CAAC,mBAAmB,CAAC,GAC5B,OAAO,CAAC,kBAAkB,CAAC,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEhC,iDAAiD;AACjD,MAAM,MAAM,wBAAwB,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAE5E,4CAA4C;AAC5C,MAAM,MAAM,oBAAoB,GAAG,eAAe,GAAG,cAAc,CAAC;AAEpE,0CAA0C;AAC1C,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,YAAY,CAAC;AAEhE,uGAAuG;AACvG,MAAM,MAAM,qBAAqB,GAAG,eAAe,GAAG,eAAe,CAAC;AAEtE,gDAAgD;AAChD,MAAM,MAAM,wBAAwB,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAE5E,4CAA4C;AAC5C,MAAM,MAAM,oBAAoB,GAAG,eAAe,GAAG,cAAc,CAAC;AAEpE,6CAA6C;AAC7C,MAAM,MAAM,qBAAqB,GAAG,eAAe,GAAG,eAAe,CAAC;AAEtE,8CAA8C;AAC9C,MAAM,MAAM,sBAAsB,GAAG,eAAe,GAAG,gBAAgB,CAAC;AAExE;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,SAAS,SAAS,cAAc,EACzD,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,GAClC,aAAa,CAAC,SAAS,CAAC,CAE1B"}
@@ -23,6 +23,23 @@ import type { HostFetchInit, PluginHost } from './plugin.host.js';
23
23
  * worth asking and this file does not — and putting a cache behind a pure
24
24
  * parser would hide it from the one caller that must not be surprised by it.
25
25
  *
26
+ * ## A podcast is a feed with an attachment
27
+ *
28
+ * A podcast feed is RSS 2.0 with the iTunes namespace on top, and the part a
29
+ * station needs from it is exactly the part a news reader throws away: the
30
+ * `enclosure`, which is the audio, and `itunes:duration`, which is how long it
31
+ * runs. Both are read here onto {@link FeedItem.enclosure} and
32
+ * {@link FeedItem.durationMs}, and the channel's own description, artwork and
33
+ * language onto {@link ParsedFeed}, because a second plugin reading a podcast
34
+ * would otherwise write the same namespace handling again. Every one of those
35
+ * fields is optional, so a reader that wants none of them (`plugins/rss`) reads
36
+ * exactly what it read before.
37
+ *
38
+ * What an enclosure is NOT is a link. {@link FeedItem.url} is still only ever
39
+ * the page a person reads, and the audio never arrives there: a news reader
40
+ * that followed an enclosure as though it were the story would fetch a
41
+ * sixty-megabyte file to look for paragraphs in it.
42
+ *
26
43
  * ## Tolerant in one specific direction
27
44
  *
28
45
  * A feed is somebody else's file, served by somebody else's edge, and the ways
@@ -56,12 +73,79 @@ export interface FeedItem {
56
73
  publishedAt?: string;
57
74
  author?: string;
58
75
  categories?: string[];
76
+ /**
77
+ * The file attached to this entry, which for a podcast is the episode
78
+ * itself. See {@link FeedEnclosure}.
79
+ *
80
+ * Absent for an entry that attaches nothing, which is every entry of an
81
+ * ordinary news feed, and for one whose attachment is not at an http(s)
82
+ * address somebody could fetch.
83
+ */
84
+ enclosure?: FeedEnclosure;
85
+ /**
86
+ * How long the attachment runs, in whole milliseconds, as the PUBLISHER
87
+ * says: `itunes:duration`, written as `HH:MM:SS`, `MM:SS` or bare seconds.
88
+ *
89
+ * A claim rather than a measurement, and absent where the feed made none
90
+ * or made one this cannot read. Nothing here guesses one from the
91
+ * enclosure's size, because a byte count divided by a bitrate nobody
92
+ * stated is a number that looks measured and is not.
93
+ */
94
+ durationMs?: number;
95
+ /** This entry's own artwork, where it has some (`itunes:image`). Always http(s). */
96
+ imageUrl?: string;
97
+ /**
98
+ * Whether the publisher marked this entry explicit (`itunes:explicit`).
99
+ *
100
+ * Absent means the feed did not say, which is not the same as clean: a
101
+ * reader enforcing a clean-only policy has to demand a positive `false`,
102
+ * on `ProviderTrack.advisory`'s argument.
103
+ */
104
+ explicit?: boolean;
105
+ /** `itunes:season`, a positive whole number, when the publisher numbers them. */
106
+ season?: number;
107
+ /** `itunes:episode`, a positive whole number, when the publisher numbers them. */
108
+ episode?: number;
109
+ }
110
+ /**
111
+ * A file attached to an entry: RSS 2.0's `<enclosure>` or an Atom
112
+ * `<link rel="enclosure">`.
113
+ *
114
+ * Every part except the address is the publisher's claim and is passed on as
115
+ * one. `type` in particular is whatever the publisher's CMS wrote, and
116
+ * `audio/x-m4a`, `audio/mp3` and an empty string are all ordinary: a reader
117
+ * deciding what it can play reads this and the address's extension together.
118
+ */
119
+ export interface FeedEnclosure {
120
+ /** Always http(s). An enclosure at any other address is not reported at all. */
121
+ url: string;
122
+ /** The declared media type, lower-cased, e.g. `audio/mpeg`. */
123
+ type?: string;
124
+ /**
125
+ * The declared size in bytes. Absent when the feed wrote nothing, zero, or
126
+ * something that is not a whole number, all three of which are common: a
127
+ * great many feeds write `length="0"` because the element requires the
128
+ * attribute and the publisher did not know.
129
+ */
130
+ lengthBytes?: number;
59
131
  }
60
132
  /** A feed, and what it holds. */
61
133
  export interface ParsedFeed {
62
134
  title?: string;
63
135
  /** Where the publication itself lives, as opposed to any one entry. */
64
136
  homeUrl?: string;
137
+ /** What the publication says about itself, as plain text. See {@link FEED_SUMMARY_MAX_CHARS}. */
138
+ description?: string;
139
+ /** Who publishes it: `itunes:author`, or an Atom feed's own `author`. */
140
+ author?: string;
141
+ /** The publication's artwork: `itunes:image`, or RSS 2.0's `<image><url>`. Always http(s). */
142
+ imageUrl?: string;
143
+ /** The language the publication declares, as written (`en`, `en-us`). */
144
+ language?: string;
145
+ /** The publication's own labels, including iTunes categories. Deduplicated, order kept. */
146
+ categories?: string[];
147
+ /** Whether the publisher marked the whole publication explicit. See {@link FeedItem.explicit}. */
148
+ explicit?: boolean;
65
149
  /** Newest first where the feed said, and otherwise in the order it listed them. */
66
150
  items: FeedItem[];
67
151
  }
@@ -1 +1 @@
1
- {"version":3,"file":"feed.parse.d.ts","sourceRoot":"","sources":["../src/feed.parse.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,8CAA8C;AAC9C,MAAM,WAAW,QAAQ;IACrB;;;;;;;;;;;;OAYG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,iCAAiC;AACjC,MAAM,WAAW,UAAU;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,KAAK,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAuB1C;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAgCjD;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAoBxG"}
1
+ {"version":3,"file":"feed.parse.d.ts","sourceRoot":"","sources":["../src/feed.parse.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,8CAA8C;AAC9C,MAAM,WAAW,QAAQ;IACrB;;;;;;;;;;;;OAYG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC1B,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,iCAAiC;AACjC,MAAM,WAAW,UAAU;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iGAAiG;IACjG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mFAAmF;IACnF,KAAK,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAuB1C;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAqDjD;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAoBxG"}
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export * from './capabilities/llm.js';
6
6
  export * from './capabilities/mixer.js';
7
7
  export * from './capabilities/music.provider.js';
8
8
  export * from './capabilities/news.js';
9
+ export * from './capabilities/podcast.js';
9
10
  export * from './capabilities/scrobble.js';
10
11
  export * from './capabilities/search.js';
11
12
  export * from './capabilities/similarity.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}