@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 +57 -0
- package/dist/boundary.json.safe.d.ts +9 -2
- package/dist/boundary.json.safe.d.ts.map +1 -1
- package/dist/capabilities/podcast.d.ts +248 -0
- package/dist/capabilities/podcast.d.ts.map +1 -0
- package/dist/define.plugin.d.ts +3 -0
- package/dist/define.plugin.d.ts.map +1 -1
- package/dist/feed.parse.d.ts +84 -0
- package/dist/feed.parse.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -4
- package/dist/index.js.map +1 -1
- package/dist/plugin.config.fields.d.ts +10 -1
- package/dist/plugin.config.fields.d.ts.map +1 -1
- package/dist/plugin.manifest.d.ts +16 -1
- package/dist/plugin.manifest.d.ts.map +1 -1
- package/package.json +1 -1
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":"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"}
|
package/dist/define.plugin.d.ts
CHANGED
|
@@ -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"}
|
package/dist/feed.parse.d.ts
CHANGED
|
@@ -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
|
}
|
package/dist/feed.parse.d.ts.map
CHANGED
|
@@ -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
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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"}
|