audiobookshelf-mcp 0.1.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +255 -0
  3. package/dist/api.d.ts +38 -0
  4. package/dist/api.js +122 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/config.d.ts +24 -0
  7. package/dist/config.js +78 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/confirm.d.ts +36 -0
  10. package/dist/confirm.js +72 -0
  11. package/dist/confirm.js.map +1 -0
  12. package/dist/filters.d.ts +32 -0
  13. package/dist/filters.js +81 -0
  14. package/dist/filters.js.map +1 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +24 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/result.d.ts +18 -0
  19. package/dist/result.js +71 -0
  20. package/dist/result.js.map +1 -0
  21. package/dist/schema.d.ts +12 -0
  22. package/dist/schema.js +36 -0
  23. package/dist/schema.js.map +1 -0
  24. package/dist/server.d.ts +3 -0
  25. package/dist/server.js +43 -0
  26. package/dist/server.js.map +1 -0
  27. package/dist/shape.d.ts +72 -0
  28. package/dist/shape.js +397 -0
  29. package/dist/shape.js.map +1 -0
  30. package/dist/tools/collections.d.ts +5 -0
  31. package/dist/tools/collections.js +183 -0
  32. package/dist/tools/collections.js.map +1 -0
  33. package/dist/tools/items.d.ts +3 -0
  34. package/dist/tools/items.js +117 -0
  35. package/dist/tools/items.js.map +1 -0
  36. package/dist/tools/libraries.d.ts +3 -0
  37. package/dist/tools/libraries.js +337 -0
  38. package/dist/tools/libraries.js.map +1 -0
  39. package/dist/tools/me.d.ts +3 -0
  40. package/dist/tools/me.js +141 -0
  41. package/dist/tools/me.js.map +1 -0
  42. package/dist/tools/playlists.d.ts +5 -0
  43. package/dist/tools/playlists.js +200 -0
  44. package/dist/tools/playlists.js.map +1 -0
  45. package/dist/tools/progress.d.ts +5 -0
  46. package/dist/tools/progress.js +161 -0
  47. package/dist/tools/progress.js.map +1 -0
  48. package/package.json +61 -0
package/dist/shape.js ADDED
@@ -0,0 +1,397 @@
1
+ /**
2
+ * Compact projections of Audiobookshelf objects.
3
+ *
4
+ * An expanded library item carries every audio file, track and chapter with full
5
+ * ffprobe metadata — a single book easily exceeds 40 kB of JSON, a page of 25 of
6
+ * them exceeds the useful context of any model. Every tool that returns media
7
+ * therefore defaults to a projection and offers `detail: "full"` for the raw
8
+ * object.
9
+ *
10
+ * The projections mirror Audiobookshelf's own field names (camelCase) so ids and
11
+ * values can be matched against the API docs; only derived fields
12
+ * (`durationSeconds`, `progressPercent`) are new.
13
+ */
14
+ export const DETAIL_LEVELS = ['compact', 'full'];
15
+ export const DETAIL_DESCRIPTION = '"compact" (default) returns a projection with the fields that matter for ' +
16
+ 'browsing; "full" returns the raw Audiobookshelf object including audio files, ' +
17
+ 'tracks and chapters, which is very large.';
18
+ /** Descriptions from metadata providers and podcast feeds can be many kB. */
19
+ const DESCRIPTION_MAX_LENGTH = 800;
20
+ function rec(value) {
21
+ return value !== null && typeof value === 'object'
22
+ ? value
23
+ : {};
24
+ }
25
+ function str(value) {
26
+ return typeof value === 'string' && value !== '' ? value : undefined;
27
+ }
28
+ function num(value) {
29
+ return typeof value === 'number' && Number.isFinite(value)
30
+ ? value
31
+ : undefined;
32
+ }
33
+ function bool(value) {
34
+ return typeof value === 'boolean' ? value : undefined;
35
+ }
36
+ function arr(value) {
37
+ return Array.isArray(value) ? value : [];
38
+ }
39
+ /**
40
+ * Pulls the list out of an Audiobookshelf response.
41
+ *
42
+ * Several endpoints return a bare array, an envelope (`{ libraries: [...] }`) or
43
+ * a paginated envelope (`{ results: [...] }`) depending on the parameters — the
44
+ * authors endpoint switches shape based on whether `limit` and `page` were both
45
+ * given. Accepting all three keeps the tools from returning an empty list when
46
+ * the server picks the other form.
47
+ */
48
+ export function listFrom(value, ...keys) {
49
+ if (Array.isArray(value))
50
+ return value;
51
+ const object = rec(value);
52
+ for (const key of [...keys, 'results']) {
53
+ if (Array.isArray(object[key]))
54
+ return object[key];
55
+ }
56
+ return [];
57
+ }
58
+ /** Drops undefined values so the projection stays free of empty keys. */
59
+ function defined(object) {
60
+ return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== undefined));
61
+ }
62
+ export function truncateText(value, max = DESCRIPTION_MAX_LENGTH) {
63
+ const text = str(value);
64
+ if (text === undefined)
65
+ return undefined;
66
+ const collapsed = text.replace(/\s+/g, ' ').trim();
67
+ if (collapsed.length <= max)
68
+ return collapsed;
69
+ return `${collapsed.slice(0, max)}… (truncated, ${collapsed.length} characters total)`;
70
+ }
71
+ /** `[{ name, sequence }]` or the minified `seriesName` string → `["Name #2"]`. */
72
+ function seriesLabels(metadata) {
73
+ const series = arr(metadata.series);
74
+ if (series.length > 0) {
75
+ return series.map((entry) => {
76
+ const item = rec(entry);
77
+ const name = str(item.name) ?? '(unnamed series)';
78
+ const sequence = str(item.sequence);
79
+ return sequence ? `${name} #${sequence}` : name;
80
+ });
81
+ }
82
+ const name = str(metadata.seriesName);
83
+ return name ? [name] : undefined;
84
+ }
85
+ /** `[{ id, name }]` or the minified `authorName` string → `["Name"]`. */
86
+ function nameList(entries, minifiedFallback) {
87
+ const list = arr(entries);
88
+ if (list.length > 0) {
89
+ return list.map((entry) => typeof entry === 'string' ? entry : (str(rec(entry).name) ?? '(unnamed)'));
90
+ }
91
+ const joined = str(minifiedFallback);
92
+ return joined ? joined.split(', ').filter(Boolean) : undefined;
93
+ }
94
+ export function compactMediaProgress(value) {
95
+ const progress = rec(value);
96
+ const fraction = num(progress.progress);
97
+ return defined({
98
+ id: str(progress.id),
99
+ libraryItemId: str(progress.libraryItemId),
100
+ episodeId: str(progress.episodeId),
101
+ isFinished: bool(progress.isFinished),
102
+ progressPercent: fraction === undefined ? undefined : Math.round(fraction * 1000) / 10,
103
+ currentTimeSeconds: num(progress.currentTime),
104
+ durationSeconds: num(progress.duration),
105
+ hideFromContinueListening: bool(progress.hideFromContinueListening),
106
+ startedAt: num(progress.startedAt),
107
+ finishedAt: num(progress.finishedAt),
108
+ lastUpdate: num(progress.lastUpdate),
109
+ });
110
+ }
111
+ /**
112
+ * The `/api/me` user object embeds every media progress and every bookmark the
113
+ * account has ever created — for a long-running instance that is by far the
114
+ * largest response of the whole API. The projection keeps identity and
115
+ * permissions and reports the collections as counts.
116
+ */
117
+ export function compactUser(value) {
118
+ const user = rec(value);
119
+ return defined({
120
+ id: str(user.id),
121
+ username: str(user.username),
122
+ type: str(user.type),
123
+ isActive: bool(user.isActive),
124
+ isLocked: bool(user.isLocked),
125
+ createdAt: num(user.createdAt),
126
+ lastSeen: num(user.lastSeen),
127
+ permissions: user.permissions,
128
+ librariesAccessible: user.librariesAccessible,
129
+ itemTagsSelected: user.itemTagsSelected,
130
+ numMediaProgresses: arr(user.mediaProgress).length,
131
+ numBookmarks: arr(user.bookmarks).length,
132
+ numSeriesHiddenFromContinueListening: arr(user.seriesHideFromContinueListening).length,
133
+ });
134
+ }
135
+ export function compactListeningSession(value) {
136
+ const session = rec(value);
137
+ const device = rec(session.deviceInfo);
138
+ return defined({
139
+ id: str(session.id),
140
+ displayTitle: str(session.displayTitle),
141
+ displayAuthor: str(session.displayAuthor),
142
+ mediaType: str(session.mediaType),
143
+ libraryItemId: str(session.libraryItemId),
144
+ episodeId: str(session.episodeId),
145
+ timeListeningSeconds: num(session.timeListening),
146
+ currentTimeSeconds: num(session.currentTime),
147
+ durationSeconds: num(session.duration),
148
+ playMethod: num(session.playMethod),
149
+ mediaPlayer: str(session.mediaPlayer),
150
+ device: str(device.deviceType) ?? str(device.clientName),
151
+ date: str(session.date),
152
+ startedAt: num(session.startedAt),
153
+ updatedAt: num(session.updatedAt),
154
+ });
155
+ }
156
+ export function compactBookmark(value) {
157
+ const bookmark = rec(value);
158
+ return defined({
159
+ libraryItemId: str(bookmark.libraryItemId),
160
+ title: str(bookmark.title),
161
+ timeSeconds: num(bookmark.time),
162
+ createdAt: num(bookmark.createdAt),
163
+ });
164
+ }
165
+ export function compactLibrary(value) {
166
+ const library = rec(value);
167
+ return defined({
168
+ id: str(library.id),
169
+ name: str(library.name),
170
+ mediaType: str(library.mediaType),
171
+ provider: str(library.provider),
172
+ displayOrder: num(library.displayOrder),
173
+ folders: arr(library.folders).map((folder) => defined({
174
+ id: str(rec(folder).id),
175
+ fullPath: str(rec(folder).fullPath),
176
+ })),
177
+ });
178
+ }
179
+ export function compactLibraryItem(value, options = {}) {
180
+ const item = rec(value);
181
+ const media = rec(item.media);
182
+ const metadata = rec(media.metadata);
183
+ const isPodcast = str(item.mediaType) === 'podcast';
184
+ const chapters = arr(media.chapters);
185
+ const episodes = arr(media.episodes);
186
+ const progress = item.userMediaProgress;
187
+ return defined({
188
+ id: str(item.id),
189
+ libraryId: str(item.libraryId),
190
+ mediaType: str(item.mediaType),
191
+ title: str(metadata.title),
192
+ subtitle: str(metadata.subtitle),
193
+ authors: isPodcast
194
+ ? nameList(undefined, metadata.author)
195
+ : nameList(metadata.authors, metadata.authorName),
196
+ narrators: isPodcast
197
+ ? undefined
198
+ : nameList(metadata.narrators, metadata.narratorName),
199
+ series: isPodcast ? undefined : seriesLabels(metadata),
200
+ genres: nameList(metadata.genres, undefined),
201
+ tags: nameList(media.tags, undefined),
202
+ publishedYear: str(metadata.publishedYear),
203
+ publisher: str(metadata.publisher),
204
+ language: str(metadata.language),
205
+ explicit: bool(metadata.explicit),
206
+ abridged: isPodcast ? undefined : bool(metadata.abridged),
207
+ isbn: str(metadata.isbn),
208
+ asin: str(metadata.asin),
209
+ feedUrl: isPodcast ? str(metadata.feedUrl) : undefined,
210
+ durationSeconds: num(media.duration),
211
+ numChapters: chapters.length > 0 ? chapters.length : num(media.numChapters),
212
+ numEpisodes: episodes.length > 0 ? episodes.length : num(media.numEpisodes),
213
+ numTracks: num(media.numTracks),
214
+ sizeBytes: num(item.size),
215
+ addedAt: num(item.addedAt),
216
+ updatedAt: num(item.updatedAt),
217
+ isMissing: bool(item.isMissing) === true ? true : undefined,
218
+ isInvalid: bool(item.isInvalid) === true ? true : undefined,
219
+ progress: progress === undefined || progress === null
220
+ ? undefined
221
+ : compactMediaProgress(progress),
222
+ // `/api/me/items-in-progress` carries no progress object, only the timestamp
223
+ // of the last update — and for podcasts the episode that was in progress.
224
+ progressLastUpdate: num(item.progressLastUpdate),
225
+ recentEpisode: item.recentEpisode === undefined || item.recentEpisode === null
226
+ ? undefined
227
+ : compactPodcastEpisode(item.recentEpisode),
228
+ description: options.includeDescription
229
+ ? truncateText(metadata.description)
230
+ : undefined,
231
+ });
232
+ }
233
+ export function compactPodcastEpisode(value, options = {}) {
234
+ const episode = rec(value);
235
+ const progress = episode.userMediaProgress ?? episode.progress;
236
+ return defined({
237
+ id: str(episode.id),
238
+ libraryItemId: str(episode.libraryItemId),
239
+ podcastId: str(episode.podcastId),
240
+ title: str(episode.title),
241
+ subtitle: str(episode.subtitle),
242
+ season: str(episode.season),
243
+ episode: str(episode.episode),
244
+ episodeType: str(episode.episodeType),
245
+ publishedAt: num(episode.publishedAt),
246
+ pubDate: str(episode.pubDate),
247
+ durationSeconds: num(episode.duration),
248
+ sizeBytes: num(episode.size),
249
+ progress: progress === undefined || progress === null
250
+ ? undefined
251
+ : compactMediaProgress(progress),
252
+ description: options.includeDescription
253
+ ? truncateText(episode.description)
254
+ : undefined,
255
+ });
256
+ }
257
+ /**
258
+ * `includeBooks` is off for lists on purpose: the series endpoint embeds the full
259
+ * book of every entry even when minified, which makes a page of ten series an
260
+ * order of magnitude larger than the series data itself.
261
+ */
262
+ export function compactSeries(value, options = {}) {
263
+ const series = rec(value);
264
+ const books = arr(series.books);
265
+ return defined({
266
+ id: str(series.id),
267
+ name: str(series.name),
268
+ numBooks: books.length > 0 ? books.length : arr(series.libraryItemIds).length,
269
+ totalDurationSeconds: num(series.totalDuration),
270
+ addedAt: num(series.addedAt),
271
+ books: options.includeBooks === true && books.length > 0
272
+ ? books.map((b) => compactLibraryItem(b))
273
+ : undefined,
274
+ });
275
+ }
276
+ /** Days of listening history kept in the projection of the stats endpoint. */
277
+ const RECENT_DAYS = 30;
278
+ /** Items reported in the projection of the stats endpoint. */
279
+ const TOP_ITEMS = 10;
280
+ /**
281
+ * `/api/me/listening-stats` is the largest response of the whole API: it embeds
282
+ * the complete media metadata of every item ever listened to, the totals of every
283
+ * calendar day since the account exists, and ten full session objects. On a
284
+ * three-year-old instance that is ~95 kB. The projection keeps the totals, the
285
+ * last 30 days and the top items.
286
+ */
287
+ export function compactListeningStats(value) {
288
+ const stats = rec(value);
289
+ const days = rec(stats.days);
290
+ const items = rec(stats.items);
291
+ const dayEntries = Object.entries(days)
292
+ .filter((entry) => typeof entry[1] === 'number')
293
+ .sort(([a], [b]) => b.localeCompare(a));
294
+ const topItems = Object.values(items)
295
+ .map((entry) => {
296
+ const item = rec(entry);
297
+ return {
298
+ id: str(item.id),
299
+ title: str(rec(item.mediaMetadata).title),
300
+ timeListeningSeconds: num(item.timeListening) ?? 0,
301
+ };
302
+ })
303
+ .sort((a, b) => b.timeListeningSeconds - a.timeListeningSeconds)
304
+ .slice(0, TOP_ITEMS);
305
+ return defined({
306
+ totalTimeSeconds: num(stats.totalTime),
307
+ todaySeconds: num(stats.today),
308
+ dayOfWeekSeconds: stats.dayOfWeek,
309
+ numDaysWithListening: dayEntries.length,
310
+ numItemsListened: Object.keys(items).length,
311
+ recentDaysSeconds: Object.fromEntries(dayEntries.slice(0, RECENT_DAYS)),
312
+ topItems,
313
+ // The endpoint also embeds ten full session objects. They are left out here:
314
+ // list_listening_sessions returns the same data, paginated and shaped.
315
+ numRecentSessions: arr(stats.recentSessions).length,
316
+ note: dayEntries.length > RECENT_DAYS
317
+ ? `Only the last ${RECENT_DAYS} of ${dayEntries.length} days with listening are shown — call with detail="full" for the complete history. Recent sessions are available from list_listening_sessions.`
318
+ : undefined,
319
+ });
320
+ }
321
+ /**
322
+ * `includeDescription` is off for lists: an author biography runs to hundreds of
323
+ * words, and a library with 25 authors would spend most of the response on them.
324
+ */
325
+ export function compactAuthor(value, options = {}) {
326
+ const author = rec(value);
327
+ const items = arr(author.libraryItems);
328
+ return defined({
329
+ id: str(author.id),
330
+ name: str(author.name),
331
+ asin: str(author.asin),
332
+ numBooks: num(author.numBooks) ?? (items.length || undefined),
333
+ addedAt: num(author.addedAt),
334
+ description: options.includeDescription
335
+ ? truncateText(author.description)
336
+ : undefined,
337
+ libraryItems: items.length > 0 ? items.map((i) => compactLibraryItem(i)) : undefined,
338
+ });
339
+ }
340
+ export function compactCollection(value) {
341
+ const collection = rec(value);
342
+ const books = arr(collection.books);
343
+ return defined({
344
+ id: str(collection.id),
345
+ libraryId: str(collection.libraryId),
346
+ name: str(collection.name),
347
+ description: truncateText(collection.description),
348
+ numBooks: books.length,
349
+ books: books.map((b) => compactLibraryItem(b)),
350
+ createdAt: num(collection.createdAt),
351
+ lastUpdate: num(collection.lastUpdate),
352
+ });
353
+ }
354
+ export function compactPlaylist(value) {
355
+ const playlist = rec(value);
356
+ const items = arr(playlist.items);
357
+ return defined({
358
+ id: str(playlist.id),
359
+ libraryId: str(playlist.libraryId),
360
+ name: str(playlist.name),
361
+ description: truncateText(playlist.description),
362
+ numItems: items.length,
363
+ items: items.map((entry) => {
364
+ const item = rec(entry);
365
+ return defined({
366
+ libraryItemId: str(item.libraryItemId),
367
+ episodeId: str(item.episodeId),
368
+ libraryItem: item.libraryItem === undefined
369
+ ? undefined
370
+ : compactLibraryItem(item.libraryItem),
371
+ episode: item.episode === undefined
372
+ ? undefined
373
+ : compactPodcastEpisode(item.episode),
374
+ });
375
+ }),
376
+ createdAt: num(playlist.createdAt),
377
+ lastUpdate: num(playlist.lastUpdate),
378
+ });
379
+ }
380
+ /**
381
+ * Shapes the paginated envelope of `GET /api/libraries/:id/items` and keeps the
382
+ * paging fields, so a truncated answer can say what to call next.
383
+ */
384
+ export function compactItemPage(value, detail) {
385
+ const page = rec(value);
386
+ const results = arr(page.results);
387
+ return defined({
388
+ total: num(page.total),
389
+ page: num(page.page),
390
+ limit: num(page.limit),
391
+ sortBy: str(page.sortBy),
392
+ filterBy: str(page.filterBy),
393
+ numReturned: results.length,
394
+ results: detail === 'full' ? results : results.map((i) => compactLibraryItem(i)),
395
+ });
396
+ }
397
+ //# sourceMappingURL=shape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape.js","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,MAAM,CAAU,CAAC;AAG1D,MAAM,CAAC,MAAM,kBAAkB,GAC7B,2EAA2E;IAC3E,gFAAgF;IAChF,2CAA2C,CAAC;AAE9C,6EAA6E;AAC7E,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAEnC,SAAS,GAAG,CAAC,KAAc;IACzB,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAChD,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,EAAE,CAAC;AACT,CAAC;AAED,SAAS,GAAG,CAAC,KAAc;IACzB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvE,CAAC;AAED,SAAS,GAAG,CAAC,KAAc;IACzB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACxD,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,SAAS,IAAI,CAAC,KAAc;IAC1B,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC;AAED,SAAS,GAAG,CAAC,KAAc;IACzB,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc,EAAE,GAAG,IAAc;IACxD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAAE,OAAO,MAAM,CAAC,GAAG,CAAc,CAAC;IAClE,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,yEAAyE;AACzE,SAAS,OAAO,CAAoC,MAAS;IAC3D,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CACpD,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,KAAc,EACd,GAAG,GAAG,sBAAsB;IAE5B,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,IAAI,SAAS,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,SAAS,CAAC;IAC9C,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,iBAAiB,SAAS,CAAC,MAAM,oBAAoB,CAAC;AACzF,CAAC;AAED,kFAAkF;AAClF,SAAS,YAAY,CAAC,QAAiC;IACrD,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;YACxB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC;YAClD,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpC,OAAO,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACnC,CAAC;AAED,yEAAyE;AACzE,SAAS,QAAQ,CACf,OAAgB,EAChB,gBAAyB;IAEzB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IAC1B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACxB,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,CAC1E,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpB,aAAa,EAAE,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC1C,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;QAClC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QACrC,eAAe,EACb,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE;QACvE,kBAAkB,EAAE,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC7C,eAAe,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACvC,yBAAyB,EAAE,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QACnE,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;QAClC,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;QACpC,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;KACrC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAChB,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QACpB,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC7B,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC7B,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QAC9B,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC5B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,kBAAkB,EAAE,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM;QAClD,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM;QACxC,oCAAoC,EAAE,GAAG,CACvC,IAAI,CAAC,+BAA+B,CACrC,CAAC,MAAM;KACT,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,KAAc;IAEd,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvC,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACnB,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC;QACvC,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QACzC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;QACjC,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QACzC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;QACjC,oBAAoB,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QAChD,kBAAkB,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;QAC5C,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;QACtC,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC;QACnC,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;QACrC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC;QACxD,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QACvB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;QACjC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;KAClC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC5B,OAAO,OAAO,CAAC;QACb,aAAa,EAAE,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC1C,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC1B,WAAW,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC/B,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;KACnC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACnB,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QACvB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;QACjC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC/B,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC;QACvC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAC3C,OAAO,CAAC;YACN,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACvB,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC;SACpC,CAAC,CACH;KACF,CAAC,CAAC;AACL,CAAC;AAOD,MAAM,UAAU,kBAAkB,CAChC,KAAc,EACd,UAA8B,EAAE;IAEhC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC;IACpD,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC;IAExC,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAChB,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QAC9B,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QAC9B,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAChC,OAAO,EAAE,SAAS;YAChB,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC;YACtC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC;QACnD,SAAS,EAAE,SAAS;YAClB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,YAAY,CAAC;QACvD,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC;QACtD,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;QAC5C,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;QACrC,aAAa,EAAE,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC1C,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;QAClC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACjC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACzD,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QACxB,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QACxB,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;QACtD,eAAe,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;QACpC,WAAW,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC;QAC3E,WAAW,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC;QAC3E,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC;QAC/B,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QACzB,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;QAC1B,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QAC9B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC3D,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC3D,QAAQ,EACN,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI;YACzC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,oBAAoB,CAAC,QAAQ,CAAC;QACpC,6EAA6E;QAC7E,0EAA0E;QAC1E,kBAAkB,EAAE,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC;QAChD,aAAa,EACX,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI;YAC7D,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,aAAa,CAAC;QAC/C,WAAW,EAAE,OAAO,CAAC,kBAAkB;YACrC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC;YACpC,CAAC,CAAC,SAAS;KACd,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAAc,EACd,UAA8B,EAAE;IAEhC,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,iBAAiB,IAAI,OAAO,CAAC,QAAQ,CAAC;IAC/D,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACnB,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QACzC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;QACjC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;QACzB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC/B,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;QAC3B,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;QAC7B,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;QACrC,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;QACrC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;QAC7B,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;QACtC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QAC5B,QAAQ,EACN,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI;YACzC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,oBAAoB,CAAC,QAAQ,CAAC;QACpC,WAAW,EAAE,OAAO,CAAC,kBAAkB;YACrC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC;YACnC,CAAC,CAAC,SAAS;KACd,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAc,EACd,UAAsC,EAAE;IAExC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChC,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAClB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QACtB,QAAQ,EACN,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM;QACrE,oBAAoB,EAAE,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC;QAC/C,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;QAC5B,KAAK,EACH,OAAO,CAAC,YAAY,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAC/C,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;YACzC,CAAC,CAAC,SAAS;KAChB,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,8DAA8D;AAC9D,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IACzB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE/B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;SACpC,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;SAC1E,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAE1C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;SAClC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAChB,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC;YACzC,oBAAoB,EAAE,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;SACnD,CAAC;IACJ,CAAC,CAAC;SACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,oBAAoB,GAAG,CAAC,CAAC,oBAAoB,CAAC;SAC/D,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAEvB,OAAO,OAAO,CAAC;QACb,gBAAgB,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC;QACtC,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;QAC9B,gBAAgB,EAAE,KAAK,CAAC,SAAS;QACjC,oBAAoB,EAAE,UAAU,CAAC,MAAM;QACvC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM;QAC3C,iBAAiB,EAAE,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QACvE,QAAQ;QACR,6EAA6E;QAC7E,uEAAuE;QACvE,iBAAiB,EAAE,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,MAAM;QACnD,IAAI,EACF,UAAU,CAAC,MAAM,GAAG,WAAW;YAC7B,CAAC,CAAC,iBAAiB,WAAW,OAAO,UAAU,CAAC,MAAM,gJAAgJ;YACtM,CAAC,CAAC,SAAS;KAChB,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAc,EACd,UAA8B,EAAE;IAEhC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACvC,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAClB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QACtB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC;QAC7D,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;QAC5B,WAAW,EAAE,OAAO,CAAC,kBAAkB;YACrC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC;YAClC,CAAC,CAAC,SAAS;QACb,YAAY,EACV,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;KACzE,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACtB,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;QACpC,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;QAC1B,WAAW,EAAE,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC;QACjD,QAAQ,EAAE,KAAK,CAAC,MAAM;QACtB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;QAC9C,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;QACpC,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;KACvC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpB,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;QAClC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QACxB,WAAW,EAAE,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC/C,QAAQ,EAAE,KAAK,CAAC,MAAM;QACtB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACzB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;YACxB,OAAO,OAAO,CAAC;gBACb,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC;gBACtC,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC9B,WAAW,EACT,IAAI,CAAC,WAAW,KAAK,SAAS;oBAC5B,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC;gBAC1C,OAAO,EACL,IAAI,CAAC,OAAO,KAAK,SAAS;oBACxB,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAC;QACL,CAAC,CAAC;QACF,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;QAClC,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;KACrC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAc,EACd,MAAmB;IAEnB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClC,OAAO,OAAO,CAAC;QACb,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;QACtB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QACpB,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;QACxB,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC5B,WAAW,EAAE,OAAO,CAAC,MAAM;QAC3B,OAAO,EACL,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;KAC1E,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type AudiobookshelfApi } from '../api.js';
3
+ import { type ConfirmationStore } from '../confirm.js';
4
+ export declare function registerCollectionReadTools(server: McpServer, api: AudiobookshelfApi): void;
5
+ export declare function registerCollectionWriteTools(server: McpServer, api: AudiobookshelfApi, confirmations: ConfirmationStore): void;
@@ -0,0 +1,183 @@
1
+ import { z } from 'zod';
2
+ import { assertPathSegment } from '../api.js';
3
+ import { confirmationPrompt, setResourceKey, } from '../confirm.js';
4
+ import { errorResult, run, textResult, untrustedJsonResult, } from '../result.js';
5
+ import { confirmTokenParam, detailParam } from '../schema.js';
6
+ import { compactCollection, listFrom } from '../shape.js';
7
+ const collectionIdParam = z
8
+ .string()
9
+ .min(1)
10
+ .describe('Collection id, as returned by list_collections');
11
+ const libraryItemIdsParam = z
12
+ .array(z.string().min(1))
13
+ .min(1)
14
+ .max(200)
15
+ .describe('Library item ids of books');
16
+ export function registerCollectionReadTools(server, api) {
17
+ server.registerTool('list_collections', {
18
+ title: 'List collections',
19
+ description: 'Lists collections — the curated, ordered groups of books. Without ' +
20
+ 'library_id it returns the collections of every accessible library. ' +
21
+ 'Collections are shared server-wide; playlists are private per user.',
22
+ inputSchema: {
23
+ library_id: z
24
+ .string()
25
+ .min(1)
26
+ .optional()
27
+ .describe('Restrict the result to this library'),
28
+ detail: detailParam,
29
+ },
30
+ annotations: { readOnlyHint: true },
31
+ }, async ({ library_id, detail }) => run(async () => {
32
+ const path = library_id === undefined
33
+ ? '/api/collections'
34
+ : `/api/libraries/${assertPathSegment(library_id, 'library_id')}/collections`;
35
+ const collections = listFrom(await api.get(path), 'collections');
36
+ return untrustedJsonResult({
37
+ numCollections: collections.length,
38
+ collections: detail === 'full'
39
+ ? collections
40
+ : collections.map(compactCollection),
41
+ });
42
+ }));
43
+ server.registerTool('get_collection', {
44
+ title: 'Get collection',
45
+ description: 'Fetches one collection with the books it contains, in order.',
46
+ inputSchema: {
47
+ collection_id: collectionIdParam,
48
+ detail: detailParam,
49
+ },
50
+ annotations: { readOnlyHint: true },
51
+ }, async ({ collection_id, detail }) => run(async () => {
52
+ const data = await api.get(`/api/collections/${assertPathSegment(collection_id, 'collection_id')}`);
53
+ return untrustedJsonResult(detail === 'full' ? data : compactCollection(data));
54
+ }));
55
+ }
56
+ export function registerCollectionWriteTools(server, api, confirmations) {
57
+ server.registerTool('create_collection', {
58
+ title: 'Create collection',
59
+ description: 'Creates a collection of books. Audiobookshelf rejects empty ' +
60
+ 'collections, so at least one library item id is required, and every ' +
61
+ 'item must be a book from the given library.',
62
+ inputSchema: {
63
+ library_id: z
64
+ .string()
65
+ .min(1)
66
+ .describe('Library the collection belongs to'),
67
+ name: z.string().min(1).max(255).describe('Collection name'),
68
+ description: z
69
+ .string()
70
+ .max(4000)
71
+ .optional()
72
+ .describe('Optional description'),
73
+ library_item_ids: libraryItemIdsParam,
74
+ },
75
+ }, async ({ library_id, name, description, library_item_ids }) => run(async () => {
76
+ const books = library_item_ids.map((id) => assertPathSegment(id, 'library_item_id'));
77
+ const created = await api.post('/api/collections', {
78
+ libraryId: assertPathSegment(library_id, 'library_id'),
79
+ name,
80
+ ...(description !== undefined ? { description } : {}),
81
+ books,
82
+ });
83
+ return untrustedJsonResult(compactCollection(created));
84
+ }));
85
+ server.registerTool('update_collection', {
86
+ title: 'Update collection',
87
+ description: 'Renames a collection, changes its description or reorders its books. ' +
88
+ 'library_item_ids replaces the order completely, so it has to contain ' +
89
+ 'every item that should stay in the collection — use ' +
90
+ 'add_books_to_collection and remove_books_from_collection to change ' +
91
+ 'membership.',
92
+ inputSchema: {
93
+ collection_id: collectionIdParam,
94
+ name: z.string().min(1).max(255).optional().describe('New name'),
95
+ description: z
96
+ .string()
97
+ .max(4000)
98
+ .optional()
99
+ .describe('New description'),
100
+ library_item_ids: z
101
+ .array(z.string().min(1))
102
+ .min(1)
103
+ .max(200)
104
+ .optional()
105
+ .describe('Complete, newly ordered list of the books in the collection'),
106
+ },
107
+ }, async ({ collection_id, name, description, library_item_ids }) => run(async () => {
108
+ if (name === undefined &&
109
+ description === undefined &&
110
+ library_item_ids === undefined) {
111
+ return errorResult('Nothing to update: pass name, description or library_item_ids.');
112
+ }
113
+ const updated = await api.patch(`/api/collections/${assertPathSegment(collection_id, 'collection_id')}`, {
114
+ ...(name !== undefined ? { name } : {}),
115
+ ...(description !== undefined ? { description } : {}),
116
+ ...(library_item_ids !== undefined
117
+ ? {
118
+ books: library_item_ids.map((id) => assertPathSegment(id, 'library_item_id')),
119
+ }
120
+ : {}),
121
+ });
122
+ return untrustedJsonResult(compactCollection(updated));
123
+ }));
124
+ server.registerTool('add_books_to_collection', {
125
+ title: 'Add books to collection',
126
+ description: 'Adds one or more books to an existing collection. Books already in the ' +
127
+ 'collection are ignored; books from a different library are rejected.',
128
+ inputSchema: {
129
+ collection_id: collectionIdParam,
130
+ library_item_ids: libraryItemIdsParam,
131
+ },
132
+ }, async ({ collection_id, library_item_ids }) => run(async () => {
133
+ const updated = await api.post(`/api/collections/${assertPathSegment(collection_id, 'collection_id')}/batch/add`, {
134
+ books: library_item_ids.map((id) => assertPathSegment(id, 'library_item_id')),
135
+ });
136
+ return untrustedJsonResult(compactCollection(updated));
137
+ }));
138
+ server.registerTool('remove_books_from_collection', {
139
+ title: 'Remove books from collection',
140
+ description: 'Removes books from a collection. The books themselves are untouched — ' +
141
+ 'only their membership in the collection ends, and it can be restored ' +
142
+ 'with add_books_to_collection.',
143
+ inputSchema: {
144
+ collection_id: collectionIdParam,
145
+ library_item_ids: libraryItemIdsParam,
146
+ },
147
+ annotations: { destructiveHint: true },
148
+ }, async ({ collection_id, library_item_ids }) => run(async () => {
149
+ const updated = await api.post(`/api/collections/${assertPathSegment(collection_id, 'collection_id')}/batch/remove`, {
150
+ books: library_item_ids.map((id) => assertPathSegment(id, 'library_item_id')),
151
+ });
152
+ return untrustedJsonResult(compactCollection(updated));
153
+ }));
154
+ server.registerTool('delete_collection', {
155
+ title: 'Delete collection',
156
+ description: 'Deletes a collection. The books stay in the library, but the curated ' +
157
+ 'list and its order are gone. Two-step: the first call returns a ' +
158
+ 'confirmation token, the second call with that token performs the ' +
159
+ 'deletion. Requires an Audiobookshelf account with delete permission.',
160
+ inputSchema: {
161
+ collection_id: collectionIdParam,
162
+ confirm_token: confirmTokenParam,
163
+ },
164
+ annotations: { destructiveHint: true },
165
+ }, async ({ collection_id, confirm_token }) => run(async () => {
166
+ const safeId = assertPathSegment(collection_id, 'collection_id');
167
+ const resource = setResourceKey('delete_collection', [safeId]);
168
+ if (!confirmations.consume(resource, confirm_token)) {
169
+ if (confirm_token !== undefined) {
170
+ return errorResult('The confirmation token is invalid, expired or was issued for a ' +
171
+ 'different collection. Call delete_collection without a token to ' +
172
+ 'get a new one.');
173
+ }
174
+ const token = confirmations.issue(resource);
175
+ // Deliberately only the id in this text — a collection name is
176
+ // user-controlled content and this string is read by a model.
177
+ return textResult(confirmationPrompt(`delete collection ${safeId}`, token, confirmations.ttlMinutes));
178
+ }
179
+ await api.delete(`/api/collections/${safeId}`);
180
+ return textResult(`Collection ${safeId} deleted.`);
181
+ }));
182
+ }
183
+ //# sourceMappingURL=collections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/tools/collections.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type AudiobookshelfApi } from '../api.js';
3
+ export declare function registerItemReadTools(server: McpServer, api: AudiobookshelfApi): void;