@media-engine/core 0.1.1 → 1.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 (92) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +48 -20
  3. package/README.ru.md +46 -19
  4. package/dist/cache/memory.js +10 -8
  5. package/dist/cache/memory.js.map +1 -1
  6. package/dist/details/types.d.ts +6 -0
  7. package/dist/engine/availability.d.ts +1 -0
  8. package/dist/engine/availability.js +8 -0
  9. package/dist/engine/availability.js.map +1 -1
  10. package/dist/engine/circuit-breaker.d.ts +1 -0
  11. package/dist/engine/circuit-breaker.js +11 -0
  12. package/dist/engine/circuit-breaker.js.map +1 -1
  13. package/dist/engine/concurrency-limiter.js +2 -2
  14. package/dist/engine/concurrency-limiter.js.map +1 -1
  15. package/dist/engine/engine.d.ts +9 -4
  16. package/dist/engine/engine.js +294 -104
  17. package/dist/engine/engine.js.map +1 -1
  18. package/dist/engine/in-flight.d.ts +12 -1
  19. package/dist/engine/in-flight.js +69 -14
  20. package/dist/engine/in-flight.js.map +1 -1
  21. package/dist/engine/operation.d.ts +7 -0
  22. package/dist/engine/operation.js +49 -0
  23. package/dist/engine/operation.js.map +1 -0
  24. package/dist/engine/provider-calls.d.ts +11 -0
  25. package/dist/engine/provider-calls.js +63 -12
  26. package/dist/engine/provider-calls.js.map +1 -1
  27. package/dist/engine/query.d.ts +6 -1
  28. package/dist/engine/query.js +228 -36
  29. package/dist/engine/query.js.map +1 -1
  30. package/dist/engine/response-meta.d.ts +3 -1
  31. package/dist/engine/response-meta.js +8 -1
  32. package/dist/engine/response-meta.js.map +1 -1
  33. package/dist/engine/runtime.d.ts +2 -0
  34. package/dist/engine/runtime.js +19 -0
  35. package/dist/engine/runtime.js.map +1 -1
  36. package/dist/engine/search-discovery.d.ts +3 -0
  37. package/dist/engine/search-discovery.js +35 -0
  38. package/dist/engine/search-discovery.js.map +1 -0
  39. package/dist/engine/search-enrichment-shared.d.ts +23 -0
  40. package/dist/engine/search-enrichment-shared.js +68 -0
  41. package/dist/engine/search-enrichment-shared.js.map +1 -0
  42. package/dist/engine/search-enrichment.d.ts +21 -7
  43. package/dist/engine/search-enrichment.js +135 -75
  44. package/dist/engine/search-enrichment.js.map +1 -1
  45. package/dist/engine/search-identity-snapshot.d.ts +15 -0
  46. package/dist/engine/search-identity-snapshot.js +101 -0
  47. package/dist/engine/search-identity-snapshot.js.map +1 -0
  48. package/dist/engine/search-outcomes.d.ts +32 -0
  49. package/dist/engine/search-outcomes.js +118 -0
  50. package/dist/engine/search-outcomes.js.map +1 -0
  51. package/dist/engine/search-poster-enrichment.d.ts +31 -0
  52. package/dist/engine/search-poster-enrichment.js +93 -0
  53. package/dist/engine/search-poster-enrichment.js.map +1 -0
  54. package/dist/engine/search-result-freeze.d.ts +13 -0
  55. package/dist/engine/search-result-freeze.js +155 -0
  56. package/dist/engine/search-result-freeze.js.map +1 -0
  57. package/dist/engine/torrents.d.ts +22 -0
  58. package/dist/engine/torrents.js +188 -0
  59. package/dist/engine/torrents.js.map +1 -0
  60. package/dist/engine/types.d.ts +7 -1
  61. package/dist/errors/types.d.ts +1 -1
  62. package/dist/errors/types.js.map +1 -1
  63. package/dist/index.d.ts +2 -1
  64. package/dist/index.js +1 -1
  65. package/dist/index.js.map +1 -1
  66. package/dist/media/types.d.ts +1 -1
  67. package/dist/merge/diversity.d.ts +15 -0
  68. package/dist/merge/diversity.js +52 -0
  69. package/dist/merge/diversity.js.map +1 -0
  70. package/dist/merge/priority.js +3 -1
  71. package/dist/merge/priority.js.map +1 -1
  72. package/dist/merge/scoring.d.ts +10 -0
  73. package/dist/merge/scoring.js +132 -28
  74. package/dist/merge/scoring.js.map +1 -1
  75. package/dist/merge/strategy.js +53 -13
  76. package/dist/merge/strategy.js.map +1 -1
  77. package/dist/providers/registry.d.ts +4 -2
  78. package/dist/providers/registry.js +11 -2
  79. package/dist/providers/registry.js.map +1 -1
  80. package/dist/providers/types.d.ts +4 -0
  81. package/dist/response/types.d.ts +20 -0
  82. package/dist/search/types.d.ts +34 -0
  83. package/dist/streaming/types.d.ts +1 -0
  84. package/dist/testing/providers.js +2 -0
  85. package/dist/testing/providers.js.map +1 -1
  86. package/dist/torrent/index.d.ts +1 -0
  87. package/dist/torrent/index.js +2 -0
  88. package/dist/torrent/index.js.map +1 -0
  89. package/dist/torrent/types.d.ts +132 -0
  90. package/dist/torrent/types.js +2 -0
  91. package/dist/torrent/types.js.map +1 -0
  92. package/package.json +8 -3
@@ -9,27 +9,47 @@ export const EXTERNAL_ID_SHORTCUTS = [
9
9
  "myAnimeList",
10
10
  "aniList",
11
11
  ];
12
+ const EXTERNAL_ID_SOURCES = [...EXTERNAL_ID_SHORTCUTS, "worldArt"];
13
+ const NUMERIC_EXTERNAL_ID_SOURCES = new Set([
14
+ "tmdb",
15
+ "kinopoisk",
16
+ "shikimori",
17
+ "myAnimeList",
18
+ "aniList",
19
+ "worldArt",
20
+ ]);
21
+ const MEDIA_TYPES = new Set(["movie", "series", "anime"]);
22
+ const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f]/u;
23
+ const IMDB_TITLE_ID = /^tt\d{7,12}$/u;
24
+ const NUMERIC_EXTERNAL_ID = /^\d+$/u;
12
25
  const SEARCH_FALLBACK_MIN_TOKENS = 3;
13
26
  const SEARCH_FALLBACK_MIN_LAST_TOKEN_LENGTH = 4;
14
27
  const SEARCH_JOINED_FALLBACK_MIN_LENGTH = 6;
15
28
  const SEARCH_JOINED_FALLBACK_MAX_LENGTH = 8;
16
29
  const SEARCH_JOINED_FALLBACK_MIN_PART_LENGTH = 3;
17
30
  const MAX_SEARCH_LIMIT = 100;
31
+ const MAX_TORRENT_LIMIT = 100;
32
+ const MAX_TORRENT_ALTERNATIVE_TITLES = 20;
18
33
  const MAX_PROVIDER_SEARCH_LIMIT = 100;
34
+ const MAX_TITLE_LENGTH = 300;
35
+ const MAX_LANGUAGE_LENGTH = 35;
36
+ const MAX_EXTERNAL_ID_LENGTH = 128;
37
+ const MAX_DEPRECATED_DETAILS_ID_LENGTH = 128;
38
+ const MAX_PROVIDER_FILTER_LENGTH = 100;
39
+ const MAX_PROVIDER_FILTERS = 100;
19
40
  // Normalizes top-level external ID shortcuts into the ids object.
20
41
  // Нормализует верхнеуровневые сокращения внешних ID в объект ids.
21
42
  export function normalizeSearchQuery(query) {
22
- const ids = { ...(query.ids ?? {}) };
23
- for (const key of EXTERNAL_ID_SHORTCUTS) {
24
- const value = query[key];
25
- if (value) {
26
- ids[key] = value;
27
- }
28
- }
43
+ const title = normalizeOptionalString(query.title);
44
+ const ids = normalizeExternalIds(query.ids, query);
45
+ const language = normalizeLanguage(query.language);
29
46
  return {
30
- ...query,
31
- title: query.title?.trim(),
32
- ids: hasExternalIds(ids) ? ids : undefined,
47
+ ...(title ? { title } : {}),
48
+ ...(query.type !== undefined ? { type: query.type } : {}),
49
+ ...(query.year !== undefined ? { year: query.year } : {}),
50
+ ...(ids ? { ids } : {}),
51
+ ...(query.limit !== undefined ? { limit: query.limit } : {}),
52
+ ...(language ? { language } : {}),
33
53
  };
34
54
  }
35
55
  // Infers a provider lookup language only when the caller did not specify one.
@@ -46,41 +66,65 @@ export function inferTitleLanguage(title) {
46
66
  // Normalizes top-level external ID shortcuts into a details ids object.
47
67
  // Нормализует верхнеуровневые сокращения внешних ID в объект ids для details.
48
68
  export function normalizeDetailsQuery(query) {
49
- const ids = { ...(query.ids ?? {}) };
50
- for (const key of EXTERNAL_ID_SHORTCUTS) {
51
- const value = query[key];
52
- if (value) {
53
- ids[key] = value;
54
- }
55
- }
69
+ const ids = normalizeExternalIds(query.ids, query);
70
+ const id = normalizeOptionalString(query.id);
71
+ const language = normalizeLanguage(query.language);
56
72
  return {
57
- ...query,
58
- ids: hasExternalIds(ids) ? ids : undefined,
73
+ ...(!ids && id ? { id } : {}),
74
+ ...(ids ? { ids } : {}),
75
+ ...(query.type !== undefined ? { type: query.type } : {}),
76
+ ...(language ? { language } : {}),
59
77
  };
60
78
  }
61
79
  // Normalizes top-level external ID shortcuts into a streaming ids object.
62
80
  // Нормализует верхнеуровневые сокращения внешних ID в объект ids для streaming.
63
81
  export function normalizeStreamQuery(query) {
64
- const ids = { ...(query.ids ?? {}) };
65
- const providers = query.providers?.map((provider) => provider.trim()).filter(Boolean);
66
- const language = query.language?.trim();
67
- for (const key of EXTERNAL_ID_SHORTCUTS) {
68
- const value = query[key];
69
- if (value) {
70
- ids[key] = value;
71
- }
72
- }
82
+ const title = normalizeOptionalString(query.title);
83
+ const ids = normalizeExternalIds(query.ids, query);
84
+ const providers = normalizeProviderFilters(query.providers);
85
+ const language = normalizeLanguage(query.language);
73
86
  return {
74
- ...query,
75
- title: query.title?.trim(),
76
- ...(hasExternalIds(ids) ? { ids } : {}),
77
- ...(providers && providers.length > 0 ? { providers } : {}),
87
+ type: query.type,
88
+ ...(ids ? { ids } : {}),
89
+ ...(title ? { title } : {}),
90
+ ...(query.year !== undefined ? { year: query.year } : {}),
91
+ ...(query.seasonNumber !== undefined ? { seasonNumber: query.seasonNumber } : {}),
92
+ ...(query.episodeNumber !== undefined ? { episodeNumber: query.episodeNumber } : {}),
93
+ ...(query.absoluteEpisodeNumber !== undefined
94
+ ? { absoluteEpisodeNumber: query.absoluteEpisodeNumber }
95
+ : {}),
96
+ ...(providers ? { providers } : {}),
78
97
  ...(language ? { language } : {}),
79
98
  };
80
99
  }
100
+ // Normalizes top-level external ID shortcuts into a torrent discovery ids object.
101
+ // Нормализует верхнеуровневые сокращения внешних ID в torrent discovery ids object.
102
+ export function normalizeTorrentQuery(query) {
103
+ const title = normalizeOptionalString(query.title);
104
+ const alternativeTitles = normalizeAlternativeTitles(query.alternativeTitles, title);
105
+ const ids = normalizeExternalIds(query.ids, query);
106
+ const providers = normalizeProviderFilters(query.providers);
107
+ const language = normalizeLanguage(query.language);
108
+ return {
109
+ type: query.type,
110
+ ...(ids ? { ids } : {}),
111
+ ...(title ? { title } : {}),
112
+ ...(alternativeTitles ? { alternativeTitles } : {}),
113
+ ...(query.year !== undefined ? { year: query.year } : {}),
114
+ ...(query.seasonNumber !== undefined ? { seasonNumber: query.seasonNumber } : {}),
115
+ ...(query.episodeNumber !== undefined ? { episodeNumber: query.episodeNumber } : {}),
116
+ ...(query.absoluteEpisodeNumber !== undefined
117
+ ? { absoluteEpisodeNumber: query.absoluteEpisodeNumber }
118
+ : {}),
119
+ ...(providers ? { providers } : {}),
120
+ ...(language ? { language } : {}),
121
+ ...(query.limit !== undefined ? { limit: query.limit } : {}),
122
+ };
123
+ }
81
124
  // Validates that a search query has at least one supported lookup input.
82
125
  // Проверяет, что search query содержит хотя бы один поддерживаемый вход для поиска.
83
126
  export function validateSearchQuery(query) {
127
+ validateCommonQueryFields(query);
84
128
  if (query.limit !== undefined &&
85
129
  (!Number.isInteger(query.limit) || query.limit < 0 || query.limit > MAX_SEARCH_LIMIT)) {
86
130
  throw new MediaEngineError({
@@ -88,6 +132,9 @@ export function validateSearchQuery(query) {
88
132
  message: `Search query limit must be an integer between 0 and ${MAX_SEARCH_LIMIT}.`,
89
133
  });
90
134
  }
135
+ if (query.year !== undefined && (!Number.isInteger(query.year) || query.year < 0)) {
136
+ throwInvalidQuery("Search query year must be a non-negative integer.");
137
+ }
91
138
  if (query.title || hasExternalIds(query.ids)) {
92
139
  return;
93
140
  }
@@ -99,23 +146,40 @@ export function validateSearchQuery(query) {
99
146
  // Validates that a details query has at least one supported lookup input.
100
147
  // Проверяет, что details query содержит хотя бы один поддерживаемый вход для поиска.
101
148
  export function validateDetailsQuery(query) {
102
- if (query.id?.trim() || hasExternalIds(query.ids)) {
149
+ validateCommonQueryFields(query);
150
+ if (query.id) {
151
+ validateBoundedString("Details query id", query.id, MAX_DEPRECATED_DETAILS_ID_LENGTH);
152
+ }
153
+ if (hasExternalIds(query.ids)) {
103
154
  return;
104
155
  }
156
+ if (query.id?.trim()) {
157
+ throw new MediaEngineError({
158
+ code: "INVALID_QUERY",
159
+ message: "Details query id is not a supported global lookup. Use ids or a named external ID shortcut.",
160
+ });
161
+ }
105
162
  throw new MediaEngineError({
106
163
  code: "INVALID_QUERY",
107
- message: "Details query must include id or external ids.",
164
+ message: "Details query must include external ids.",
108
165
  });
109
166
  }
110
167
  // Validates that a streaming query can identify a media item or episode.
111
168
  // Проверяет, что streaming query может определить медиа или эпизод.
112
169
  export function validateStreamQuery(query) {
170
+ validateCommonQueryFields(query);
113
171
  if (!query.type) {
114
172
  throw new MediaEngineError({
115
173
  code: "INVALID_QUERY",
116
174
  message: "Stream query type is required.",
117
175
  });
118
176
  }
177
+ if (query.providers && query.providers.length > MAX_PROVIDER_FILTERS) {
178
+ throwInvalidQuery(`Stream query providers must contain at most ${MAX_PROVIDER_FILTERS} unique names.`);
179
+ }
180
+ for (const provider of query.providers ?? []) {
181
+ validateBoundedString("Stream query provider", provider, MAX_PROVIDER_FILTER_LENGTH);
182
+ }
119
183
  if ([query.year, query.seasonNumber, query.episodeNumber, query.absoluteEpisodeNumber].some((value) => value !== undefined && (!Number.isInteger(value) || value < 0))) {
120
184
  throw new MediaEngineError({
121
185
  code: "INVALID_QUERY",
@@ -130,6 +194,37 @@ export function validateStreamQuery(query) {
130
194
  message: "Stream query must include title or external ids.",
131
195
  });
132
196
  }
197
+ // Validates that a torrent discovery query can identify a media item or episode.
198
+ // Проверяет, что torrent discovery query может определить медиа или эпизод.
199
+ export function validateTorrentQuery(query) {
200
+ validateCommonQueryFields(query);
201
+ if (query.alternativeTitles && query.alternativeTitles.length > MAX_TORRENT_ALTERNATIVE_TITLES) {
202
+ throwInvalidQuery(`Torrent discovery query alternativeTitles must contain at most ${MAX_TORRENT_ALTERNATIVE_TITLES} unique titles.`);
203
+ }
204
+ for (const alternativeTitle of query.alternativeTitles ?? []) {
205
+ validateBoundedString("Torrent discovery query alternative title", alternativeTitle, MAX_TITLE_LENGTH);
206
+ }
207
+ if (!query.type) {
208
+ throwInvalidQuery("Torrent discovery query type is required.");
209
+ }
210
+ if (query.providers && query.providers.length > MAX_PROVIDER_FILTERS) {
211
+ throwInvalidQuery(`Torrent discovery query providers must contain at most ${MAX_PROVIDER_FILTERS} unique names.`);
212
+ }
213
+ for (const provider of query.providers ?? []) {
214
+ validateBoundedString("Torrent discovery query provider", provider, MAX_PROVIDER_FILTER_LENGTH);
215
+ }
216
+ if ([query.year, query.seasonNumber, query.episodeNumber, query.absoluteEpisodeNumber].some((value) => value !== undefined && (!Number.isInteger(value) || value < 0))) {
217
+ throwInvalidQuery("Torrent discovery query numeric fields must be non-negative integers.");
218
+ }
219
+ if (query.limit !== undefined &&
220
+ (!Number.isInteger(query.limit) || query.limit < 0 || query.limit > MAX_TORRENT_LIMIT)) {
221
+ throwInvalidQuery(`Torrent discovery query limit must be an integer between 0 and ${MAX_TORRENT_LIMIT}.`);
222
+ }
223
+ if (query.title || hasExternalIds(query.ids)) {
224
+ return;
225
+ }
226
+ throwInvalidQuery("Torrent discovery query must include title or external ids.");
227
+ }
133
228
  // Gives providers enough candidates so the engine can rank before applying the public limit.
134
229
  // Дает провайдерам достаточно кандидатов, чтобы движок ранжировал до применения публичного limit.
135
230
  export function createProviderSearchQuery(query) {
@@ -192,6 +287,12 @@ export function appendUniqueSearchResults(target, candidates) {
192
287
  export function createSearchCacheKey(query) {
193
288
  return `search:${JSON.stringify(sortObject(query))}`;
194
289
  }
290
+ // Shares confirmed identity ordering across equivalent searches with different public limits.
291
+ // Разделяет подтвержденный порядок identity между эквивалентными поисками с разными limit.
292
+ export function createSearchIdentitySnapshotCacheKey(query) {
293
+ const { limit: _limit, ...identityQuery } = query;
294
+ return `search-identity:${JSON.stringify(sortObject(identityQuery))}`;
295
+ }
195
296
  // Creates a stable cache key for a normalized details query.
196
297
  // Создает стабильный cache key для нормализованного details query.
197
298
  export function createDetailsCacheKey(query) {
@@ -199,14 +300,105 @@ export function createDetailsCacheKey(query) {
199
300
  }
200
301
  // Creates a stable cache key for a normalized streaming query.
201
302
  // Создает стабильный cache key для нормализованного streaming query.
202
- export function createAvailabilityCacheKey(query) {
203
- return `availability:${JSON.stringify(sortObject(query))}`;
303
+ export function createAvailabilityCacheKey(query, playbackUserAgent) {
304
+ const base = `availability:${JSON.stringify(sortObject(query))}`;
305
+ return playbackUserAgent === undefined
306
+ ? base
307
+ : `${base}:playback-user-agent:${JSON.stringify(playbackUserAgent)}`;
308
+ }
309
+ // Creates a stable cache key for a normalized torrent discovery query.
310
+ // Создает стабильный cache key для нормализованного torrent discovery query.
311
+ export function createTorrentDiscoveryCacheKey(query) {
312
+ return `torrents:${JSON.stringify(sortObject(query))}`;
204
313
  }
205
314
  // Checks whether an external ID object contains at least one ID.
206
315
  // Проверяет, содержит ли объект внешних ID хотя бы один ID.
207
316
  export function hasExternalIds(ids) {
208
317
  return Boolean(ids && Object.values(ids).some((value) => Boolean(value)));
209
318
  }
319
+ function normalizeExternalIds(nestedIds, shortcuts) {
320
+ const ids = {};
321
+ for (const source of EXTERNAL_ID_SOURCES) {
322
+ const nestedValue = normalizeOptionalString(nestedIds?.[source]);
323
+ const shortcutValue = EXTERNAL_ID_SHORTCUTS.includes(source)
324
+ ? normalizeOptionalString(shortcuts[source])
325
+ : undefined;
326
+ const value = shortcutValue ?? nestedValue;
327
+ if (value) {
328
+ ids[source] = source === "imdb" ? value.toLowerCase() : value;
329
+ }
330
+ }
331
+ return hasExternalIds(ids) ? ids : undefined;
332
+ }
333
+ function normalizeProviderFilters(providers) {
334
+ if (!providers) {
335
+ return undefined;
336
+ }
337
+ const normalized = [...new Set(providers.map(normalizeOptionalString).filter(isString))].sort();
338
+ return normalized.length > 0 ? normalized : undefined;
339
+ }
340
+ function normalizeAlternativeTitles(values, primaryTitle) {
341
+ if (!values)
342
+ return undefined;
343
+ if (!Array.isArray(values) || values.length > MAX_TORRENT_ALTERNATIVE_TITLES) {
344
+ throwInvalidQuery(`Torrent discovery query alternativeTitles must contain at most ${MAX_TORRENT_ALTERNATIVE_TITLES} titles.`);
345
+ }
346
+ const primaryKey = primaryTitle?.toLocaleLowerCase();
347
+ const titles = new Map();
348
+ for (const value of values) {
349
+ if (typeof value !== "string") {
350
+ throwInvalidQuery("Torrent discovery query alternativeTitles must contain only strings.");
351
+ }
352
+ const normalized = normalizeOptionalString(value);
353
+ const key = normalized?.toLocaleLowerCase();
354
+ if (normalized && key !== primaryKey && !titles.has(key)) {
355
+ titles.set(key, normalized);
356
+ }
357
+ }
358
+ return titles.size > 0 ? [...titles.values()] : undefined;
359
+ }
360
+ function normalizeLanguage(language) {
361
+ return normalizeOptionalString(language)?.toLowerCase();
362
+ }
363
+ function normalizeOptionalString(value) {
364
+ const normalized = value?.trim();
365
+ return normalized ? normalized : undefined;
366
+ }
367
+ function validateCommonQueryFields(query) {
368
+ if (query.type !== undefined && !MEDIA_TYPES.has(query.type)) {
369
+ throwInvalidQuery("Query type must be movie, series, or anime.");
370
+ }
371
+ if (query.title) {
372
+ validateBoundedString("Query title", query.title, MAX_TITLE_LENGTH);
373
+ }
374
+ if (query.language) {
375
+ validateBoundedString("Query language", query.language, MAX_LANGUAGE_LENGTH);
376
+ }
377
+ for (const [source, value] of Object.entries(query.ids ?? {})) {
378
+ validateBoundedString(`External ID ${source}`, value, MAX_EXTERNAL_ID_LENGTH);
379
+ if (source === "imdb" && !IMDB_TITLE_ID.test(value)) {
380
+ throwInvalidQuery("External ID imdb must use the tt prefix followed by 7 to 12 digits.");
381
+ }
382
+ if (NUMERIC_EXTERNAL_ID_SOURCES.has(source) &&
383
+ !NUMERIC_EXTERNAL_ID.test(value)) {
384
+ throwInvalidQuery(`External ID ${source} must contain only digits.`);
385
+ }
386
+ }
387
+ }
388
+ function validateBoundedString(field, value, maxLength) {
389
+ if (value.length > maxLength) {
390
+ throwInvalidQuery(`${field} must be at most ${maxLength} characters.`);
391
+ }
392
+ if (CONTROL_CHARACTERS.test(value)) {
393
+ throwInvalidQuery(`${field} must not contain control characters.`);
394
+ }
395
+ }
396
+ function throwInvalidQuery(message) {
397
+ throw new MediaEngineError({ code: "INVALID_QUERY", message });
398
+ }
399
+ function isString(value) {
400
+ return value !== undefined;
401
+ }
210
402
  // Sorts object keys recursively for deterministic JSON cache keys.
211
403
  // Рекурсивно сортирует ключи объекта для детерминированных JSON cache keys.
212
404
  export function sortObject(value) {
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/engine/query.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/engine/query.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { EngineWarning, ProviderFailure, ProviderTimingMeta, ResponseMeta } from "../response/index.js";
1
+ import type { EngineWarning, ProviderFailure, ProviderTimingMeta, ResponseMeta, SearchEnrichmentDebugMeta, SearchIdentitySnapshotDebugMeta } from "../response/index.js";
2
2
  export interface ResponseMetaInput {
3
3
  requested: string[];
4
4
  successful: string[];
@@ -8,6 +8,8 @@ export interface ResponseMetaInput {
8
8
  tookMs: number;
9
9
  debug: boolean;
10
10
  timings?: ProviderTimingMeta[];
11
+ enrichment?: SearchEnrichmentDebugMeta;
12
+ identitySnapshot?: SearchIdentitySnapshotDebugMeta;
11
13
  }
12
14
  export declare function createResponseMeta(input: ResponseMetaInput): ResponseMeta;
13
15
  export declare function elapsedSince(startedAt: number): number;
@@ -12,8 +12,15 @@ export function createResponseMeta(input) {
12
12
  warnings: input.warnings.length > 0 ? input.warnings : undefined,
13
13
  debug: input.debug
14
14
  ? {
15
- providers: input.requested,
15
+ providers: [
16
+ ...new Set([
17
+ ...input.requested,
18
+ ...(input.timings ?? []).map((timing) => timing.provider),
19
+ ]),
20
+ ],
16
21
  timings: input.timings ?? [],
22
+ enrichment: input.enrichment,
23
+ ...(input.identitySnapshot ? { identitySnapshot: input.identitySnapshot } : {}),
17
24
  }
18
25
  : undefined,
19
26
  };
@@ -1 +1 @@
1
- {"version":3,"file":"response-meta.js","sourceRoot":"","sources":["../../src/engine/response-meta.ts"],"names":[],"mappings":"AAoBA,qDAAqD;AACrD,0DAA0D;AAC1D,MAAM,UAAU,kBAAkB,CAAC,KAAwB;IACzD,OAAO;QACL,SAAS,EAAE;YACT,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB;QACD,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QAChE,KAAK,EAAE,KAAK,CAAC,KAAK;YAChB,CAAC,CAAC;gBACE,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;aAC7B;YACH,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"response-meta.js","sourceRoot":"","sources":["../../src/engine/response-meta.ts"],"names":[],"mappings":"AAwBA,qDAAqD;AACrD,0DAA0D;AAC1D,MAAM,UAAU,kBAAkB,CAAC,KAAwB;IACzD,OAAO;QACL,SAAS,EAAE;YACT,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB;QACD,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QAChE,KAAK,EAAE,KAAK,CAAC,KAAK;YAChB,CAAC,CAAC;gBACE,SAAS,EAAE;oBACT,GAAG,IAAI,GAAG,CAAC;wBACT,GAAG,KAAK,CAAC,SAAS;wBAClB,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;qBAC1D,CAAC;iBACH;gBACD,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;gBAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChF;YACH,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;AAChC,CAAC"}
@@ -1,3 +1,5 @@
1
1
  import type { StreamingProvider } from "../streaming/index.js";
2
+ import type { TorrentProvider } from "../torrent/index.js";
2
3
  export declare function validateStreamingProviders(providers: StreamingProvider[]): StreamingProvider[];
4
+ export declare function validateTorrentProviders(providers: TorrentProvider[]): TorrentProvider[];
3
5
  export declare function resolveProviderTimeoutMs(providerName: string, timeoutMs: number | undefined, providerTimeouts: Readonly<Record<string, number>>): number | undefined;
@@ -17,6 +17,25 @@ export function validateStreamingProviders(providers) {
17
17
  }
18
18
  return [...providers];
19
19
  }
20
+ // Validates torrent providers and rejects duplicate public names.
21
+ // Проверяет torrent-провайдеры и отклоняет дубли публичных имен.
22
+ export function validateTorrentProviders(providers) {
23
+ const names = new Set();
24
+ for (const provider of providers) {
25
+ const name = provider.name.trim();
26
+ if (!name) {
27
+ throw new Error("Torrent provider name is required.");
28
+ }
29
+ if (name !== provider.name) {
30
+ throw new Error(`Torrent provider name "${provider.name}" must not include leading or trailing whitespace.`);
31
+ }
32
+ if (names.has(name)) {
33
+ throw new Error(`Torrent provider "${name}" is already registered.`);
34
+ }
35
+ names.add(name);
36
+ }
37
+ return [...providers];
38
+ }
20
39
  // Resolves a provider override without allowing it to exceed the global boundary.
21
40
  // Выбирает override провайдера, не позволяя ему превысить глобальную границу.
22
41
  export function resolveProviderTimeoutMs(providerName, timeoutMs, providerTimeouts) {
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/engine/runtime.ts"],"names":[],"mappings":"AAEA,oEAAoE;AACpE,mEAAmE;AACnE,MAAM,UAAU,0BAA0B,CAAC,SAA8B;IACvE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAElC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,IAAI,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,4BAA4B,QAAQ,CAAC,IAAI,oDAAoD,CAC9F,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,0BAA0B,CAAC,CAAC;QACzE,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;AACxB,CAAC;AAED,kFAAkF;AAClF,8EAA8E;AAC9E,MAAM,UAAU,wBAAwB,CACtC,YAAoB,EACpB,SAA6B,EAC7B,gBAAkD;IAElD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAEzD,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAC9F,CAAC"}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/engine/runtime.ts"],"names":[],"mappings":"AAGA,oEAAoE;AACpE,mEAAmE;AACnE,MAAM,UAAU,0BAA0B,CAAC,SAA8B;IACvE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAElC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,IAAI,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,4BAA4B,QAAQ,CAAC,IAAI,oDAAoD,CAC9F,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,0BAA0B,CAAC,CAAC;QACzE,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;AACxB,CAAC;AAED,kEAAkE;AAClE,iEAAiE;AACjE,MAAM,UAAU,wBAAwB,CAAC,SAA4B;IACnE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAElC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,IAAI,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,0BAA0B,QAAQ,CAAC,IAAI,oDAAoD,CAC5F,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,0BAA0B,CAAC,CAAC;QACvE,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;AACxB,CAAC;AAED,kFAAkF;AAClF,8EAA8E;AAC9E,MAAM,UAAU,wBAAwB,CACtC,YAAoB,EACpB,SAA6B,EAC7B,gBAAkD;IAElD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAEzD,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAC9F,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { MediaSearchResult, SearchQuery } from "../search/index.js";
2
+ export declare function needsFallbackTitleDiscovery(query: SearchQuery, relevantResults: MediaSearchResult[]): boolean;
3
+ export declare function needsPrimaryTitleBroadening(query: SearchQuery, relevantResults: MediaSearchResult[]): boolean;
@@ -0,0 +1,35 @@
1
+ import { normalizeTitle } from "../merge/title.js";
2
+ // Decides whether slower fallback discovery can still resolve title identity.
3
+ // Решает, может ли более медленный fallback discovery уточнить identity по названию.
4
+ export function needsFallbackTitleDiscovery(query, relevantResults) {
5
+ if (!query.title?.trim() || hasExternalIds(query)) {
6
+ return false;
7
+ }
8
+ if (relevantResults.length === 0) {
9
+ return true;
10
+ }
11
+ const normalizedQuery = normalizeTitle(query.title);
12
+ const isExactPrimaryMatch = (result) => [result.item.title, result.item.originalTitle]
13
+ .filter((title) => Boolean(title))
14
+ .some((title) => normalizeTitle(title) === normalizedQuery);
15
+ const exactMatches = relevantResults.filter((result) => isExactPrimaryMatch(result));
16
+ if (exactMatches.length === 0) {
17
+ return normalizedQuery.split(" ").filter(Boolean).length >= 2;
18
+ }
19
+ return isExactPrimaryMatch(relevantResults[0]) && exactMatches.length > 1;
20
+ }
21
+ // Broadens likely multi-word typos even when weak fuzzy candidates prevented an empty result.
22
+ // Расширяет вероятную multi-word опечатку, даже если weak fuzzy candidates дали непустой ответ.
23
+ export function needsPrimaryTitleBroadening(query, relevantResults) {
24
+ if (!query.title?.trim() || hasExternalIds(query)) {
25
+ return false;
26
+ }
27
+ const normalizedQuery = normalizeTitle(query.title);
28
+ return !relevantResults.some((result) => [result.item.title, result.item.originalTitle]
29
+ .filter((title) => Boolean(title))
30
+ .some((title) => normalizeTitle(title) === normalizedQuery));
31
+ }
32
+ function hasExternalIds(query) {
33
+ return Object.values(query.ids ?? {}).some(Boolean);
34
+ }
35
+ //# sourceMappingURL=search-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-discovery.js","sourceRoot":"","sources":["../../src/engine/search-discovery.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,8EAA8E;AAC9E,qFAAqF;AACrF,MAAM,UAAU,2BAA2B,CACzC,KAAkB,EAClB,eAAoC;IAEpC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,eAAe,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,mBAAmB,GAAG,CAAC,MAAyB,EAAW,EAAE,CACjE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;SAC3C,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SAClD,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,eAAe,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC;IAErF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,mBAAmB,CAAC,eAAe,CAAC,CAAC,CAAE,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;AAC7E,CAAC;AAED,8FAA8F;AAC9F,gGAAgG;AAChG,MAAM,UAAU,2BAA2B,CACzC,KAAkB,EAClB,eAAoC;IAEpC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,eAAe,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEpD,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CACtC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;SAC3C,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SAClD,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,eAAe,CAAC,CAC9D,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAkB;IACxC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { DetailsQuery } from "../details/index.js";
2
+ import type { ExternalIds, MediaDetails, MediaItem } from "../media/index.js";
3
+ import type { MediaProvider } from "../providers/index.js";
4
+ import type { MediaSearchResult } from "../search/index.js";
5
+ import type { ProviderSearchCallOutcome } from "./provider-calls.js";
6
+ export interface PlannedIdEnrichment {
7
+ provider: MediaProvider;
8
+ outcome: Promise<ProviderSearchCallOutcome>;
9
+ }
10
+ export declare function supportsSearchEnrichmentFeature(provider: MediaProvider, feature: "posters" | "ratings"): boolean;
11
+ export declare function supportsSearchEnrichment(provider: MediaProvider): boolean;
12
+ export declare function createSearchDetailsQuery(result: MediaSearchResult, language: string | undefined): DetailsQuery;
13
+ export declare function searchItemAsDetails(item: MediaItem): MediaDetails;
14
+ export declare function hasSharedExternalId(left: ExternalIds | undefined, right: ExternalIds | undefined): boolean;
15
+ export declare class SearchEnrichmentCallBudget {
16
+ private readonly getProviderTimeoutMs;
17
+ private readonly startedAt;
18
+ private readonly providerCalls;
19
+ private calls;
20
+ constructor(getProviderTimeoutMs: (providerName: string) => number | undefined);
21
+ getRemainingWallTimeMs(): number;
22
+ reserve(providerName: string): number | undefined;
23
+ }
@@ -0,0 +1,68 @@
1
+ import { EXTERNAL_ID_SHORTCUTS } from "./query.js";
2
+ const SEARCH_ENRICHMENT_MAX_ADDITIONAL_CALLS = 6;
3
+ const SEARCH_ENRICHMENT_MAX_CALLS_PER_PROVIDER = 2;
4
+ const SEARCH_ENRICHMENT_MAX_WALL_TIME_MS = 1_500;
5
+ export function supportsSearchEnrichmentFeature(provider, feature) {
6
+ return provider.capabilities.features?.includes(feature) ?? true;
7
+ }
8
+ export function supportsSearchEnrichment(provider) {
9
+ return provider.capabilities.searchEnrichment !== false;
10
+ }
11
+ export function createSearchDetailsQuery(result, language) {
12
+ return {
13
+ type: result.item.type,
14
+ ids: result.item.ids,
15
+ language,
16
+ };
17
+ }
18
+ // Reuses only compact fields; every details-only field remains absent by construction.
19
+ // Переиспользует только compact-поля; details-only поля намеренно остаются пустыми.
20
+ export function searchItemAsDetails(item) {
21
+ switch (item.type) {
22
+ case "movie":
23
+ return { ...item, type: "movie" };
24
+ case "series":
25
+ return { ...item, type: "series" };
26
+ case "anime":
27
+ return { ...item, type: "anime" };
28
+ }
29
+ }
30
+ // Checks whether two normalized media identities share at least one exact external ID.
31
+ // Проверяет, совпадает ли у двух нормализованных media identity хотя бы один внешний ID.
32
+ export function hasSharedExternalId(left, right) {
33
+ if (!left || !right) {
34
+ return false;
35
+ }
36
+ return EXTERNAL_ID_SHORTCUTS.some((key) => Boolean(left[key] && left[key] === right[key]));
37
+ }
38
+ export class SearchEnrichmentCallBudget {
39
+ getProviderTimeoutMs;
40
+ startedAt = Date.now();
41
+ providerCalls = new Map();
42
+ calls = 0;
43
+ constructor(getProviderTimeoutMs) {
44
+ this.getProviderTimeoutMs = getProviderTimeoutMs;
45
+ }
46
+ getRemainingWallTimeMs() {
47
+ return Math.max(0, SEARCH_ENRICHMENT_MAX_WALL_TIME_MS - (Date.now() - this.startedAt));
48
+ }
49
+ reserve(providerName) {
50
+ const providerCalls = this.providerCalls.get(providerName) ?? 0;
51
+ if (this.calls >= SEARCH_ENRICHMENT_MAX_ADDITIONAL_CALLS ||
52
+ providerCalls >= SEARCH_ENRICHMENT_MAX_CALLS_PER_PROVIDER) {
53
+ return undefined;
54
+ }
55
+ const remainingWallTimeMs = this.getRemainingWallTimeMs();
56
+ const remainingProviderTimeMs = this.getProviderTimeoutMs(providerName);
57
+ const timeoutMs = remainingProviderTimeMs === undefined
58
+ ? remainingWallTimeMs
59
+ : Math.min(remainingWallTimeMs, remainingProviderTimeMs);
60
+ if (timeoutMs <= 0) {
61
+ return undefined;
62
+ }
63
+ this.calls += 1;
64
+ this.providerCalls.set(providerName, providerCalls + 1);
65
+ return timeoutMs;
66
+ }
67
+ }
68
+ //# sourceMappingURL=search-enrichment-shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-enrichment-shared.js","sourceRoot":"","sources":["../../src/engine/search-enrichment-shared.ts"],"names":[],"mappings":"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"}