@steipete/summarize-core 0.11.0 → 0.12.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 (117) hide show
  1. package/LICENSE +21 -0
  2. package/dist/esm/content/bun.js +21 -0
  3. package/dist/esm/content/bun.js.map +1 -0
  4. package/dist/esm/content/index.js +1 -0
  5. package/dist/esm/content/index.js.map +1 -1
  6. package/dist/esm/content/link-preview/client.js +6 -0
  7. package/dist/esm/content/link-preview/client.js.map +1 -1
  8. package/dist/esm/content/link-preview/content/fetcher.js +19 -2
  9. package/dist/esm/content/link-preview/content/fetcher.js.map +1 -1
  10. package/dist/esm/content/link-preview/content/firecrawl.js.map +1 -1
  11. package/dist/esm/content/link-preview/content/html.js.map +1 -1
  12. package/dist/esm/content/link-preview/content/index.js +29 -12
  13. package/dist/esm/content/link-preview/content/index.js.map +1 -1
  14. package/dist/esm/content/link-preview/content/utils.js.map +1 -1
  15. package/dist/esm/content/transcript/index.js +2 -0
  16. package/dist/esm/content/transcript/index.js.map +1 -1
  17. package/dist/esm/content/transcript/providers/generic.js +10 -11
  18. package/dist/esm/content/transcript/providers/generic.js.map +1 -1
  19. package/dist/esm/content/transcript/providers/podcast/apple-flow.js.map +1 -1
  20. package/dist/esm/content/transcript/providers/podcast/media.js +9 -1
  21. package/dist/esm/content/transcript/providers/podcast/media.js.map +1 -1
  22. package/dist/esm/content/transcript/providers/podcast/provider-flow.js +157 -0
  23. package/dist/esm/content/transcript/providers/podcast/provider-flow.js.map +1 -0
  24. package/dist/esm/content/transcript/providers/podcast/rss-feed.js +123 -0
  25. package/dist/esm/content/transcript/providers/podcast/rss-feed.js.map +1 -0
  26. package/dist/esm/content/transcript/providers/podcast/rss-transcript.js +113 -0
  27. package/dist/esm/content/transcript/providers/podcast/rss-transcript.js.map +1 -0
  28. package/dist/esm/content/transcript/providers/podcast/rss.js +2 -226
  29. package/dist/esm/content/transcript/providers/podcast/rss.js.map +1 -1
  30. package/dist/esm/content/transcript/providers/podcast/spotify-flow.js.map +1 -1
  31. package/dist/esm/content/transcript/providers/podcast.js +26 -155
  32. package/dist/esm/content/transcript/providers/podcast.js.map +1 -1
  33. package/dist/esm/content/transcript/providers/transcription-capability.js +22 -0
  34. package/dist/esm/content/transcript/providers/transcription-capability.js.map +1 -0
  35. package/dist/esm/content/transcript/providers/transcription-start.js +40 -30
  36. package/dist/esm/content/transcript/providers/transcription-start.js.map +1 -1
  37. package/dist/esm/content/transcript/providers/youtube/api.js +3 -2
  38. package/dist/esm/content/transcript/providers/youtube/api.js.map +1 -1
  39. package/dist/esm/content/transcript/providers/youtube/captions-player.js +173 -0
  40. package/dist/esm/content/transcript/providers/youtube/captions-player.js.map +1 -0
  41. package/dist/esm/content/transcript/providers/youtube/captions-shared.js +8 -0
  42. package/dist/esm/content/transcript/providers/youtube/captions-shared.js.map +1 -0
  43. package/dist/esm/content/transcript/providers/youtube/captions-transcript.js +361 -0
  44. package/dist/esm/content/transcript/providers/youtube/captions-transcript.js.map +1 -0
  45. package/dist/esm/content/transcript/providers/youtube/captions.js +2 -557
  46. package/dist/esm/content/transcript/providers/youtube/captions.js.map +1 -1
  47. package/dist/esm/content/transcript/providers/youtube/provider-flow.js +189 -0
  48. package/dist/esm/content/transcript/providers/youtube/provider-flow.js.map +1 -0
  49. package/dist/esm/content/transcript/providers/youtube/yt-dlp.js +7 -2
  50. package/dist/esm/content/transcript/providers/youtube/yt-dlp.js.map +1 -1
  51. package/dist/esm/content/transcript/providers/youtube.js +42 -194
  52. package/dist/esm/content/transcript/providers/youtube.js.map +1 -1
  53. package/dist/esm/content/transcript/transcription-config.js +24 -4
  54. package/dist/esm/content/transcript/transcription-config.js.map +1 -1
  55. package/dist/esm/content/url.js +3 -3
  56. package/dist/esm/content/url.js.map +1 -1
  57. package/dist/esm/processes.js.map +1 -1
  58. package/dist/esm/prompts/format.js +6 -0
  59. package/dist/esm/prompts/format.js.map +1 -1
  60. package/dist/esm/prompts/link-summary.js +27 -3
  61. package/dist/esm/prompts/link-summary.js.map +1 -1
  62. package/dist/esm/transcription/onnx-cli.js.map +1 -1
  63. package/dist/esm/transcription/whisper/assemblyai.js +132 -0
  64. package/dist/esm/transcription/whisper/assemblyai.js.map +1 -0
  65. package/dist/esm/transcription/whisper/chunking.js +64 -0
  66. package/dist/esm/transcription/whisper/chunking.js.map +1 -0
  67. package/dist/esm/transcription/whisper/cloud-providers.js +69 -0
  68. package/dist/esm/transcription/whisper/cloud-providers.js.map +1 -0
  69. package/dist/esm/transcription/whisper/core.js +316 -390
  70. package/dist/esm/transcription/whisper/core.js.map +1 -1
  71. package/dist/esm/transcription/whisper/gemini.js +324 -0
  72. package/dist/esm/transcription/whisper/gemini.js.map +1 -0
  73. package/dist/esm/transcription/whisper/preferences.js +16 -0
  74. package/dist/esm/transcription/whisper/preferences.js.map +1 -0
  75. package/dist/esm/transcription/whisper/provider-setup.js +62 -0
  76. package/dist/esm/transcription/whisper/provider-setup.js.map +1 -0
  77. package/dist/esm/transcription/whisper/remote-provider-attempts.js +189 -0
  78. package/dist/esm/transcription/whisper/remote-provider-attempts.js.map +1 -0
  79. package/dist/esm/transcription/whisper/remote.js +220 -0
  80. package/dist/esm/transcription/whisper/remote.js.map +1 -0
  81. package/dist/esm/transcription/whisper/whisper-cpp.js.map +1 -1
  82. package/dist/types/content/bun.d.ts +6 -0
  83. package/dist/types/content/index.d.ts +1 -0
  84. package/dist/types/content/link-preview/client.d.ts +3 -1
  85. package/dist/types/content/link-preview/content/fetcher.d.ts +1 -1
  86. package/dist/types/content/link-preview/content/html.d.ts +1 -1
  87. package/dist/types/content/link-preview/deps.d.ts +8 -2
  88. package/dist/types/content/link-preview/types.d.ts +1 -1
  89. package/dist/types/content/transcript/providers/podcast/flow-context.d.ts +3 -0
  90. package/dist/types/content/transcript/providers/podcast/media.d.ts +4 -2
  91. package/dist/types/content/transcript/providers/podcast/provider-flow.d.ts +7 -0
  92. package/dist/types/content/transcript/providers/podcast/rss-feed.d.ts +15 -0
  93. package/dist/types/content/transcript/providers/podcast/rss-transcript.d.ts +12 -0
  94. package/dist/types/content/transcript/providers/podcast/rss.d.ts +2 -24
  95. package/dist/types/content/transcript/providers/transcription-capability.d.ts +18 -0
  96. package/dist/types/content/transcript/providers/transcription-start.d.ts +10 -3
  97. package/dist/types/content/transcript/providers/youtube/captions-player.d.ts +12 -0
  98. package/dist/types/content/transcript/providers/youtube/captions-shared.d.ts +42 -0
  99. package/dist/types/content/transcript/providers/youtube/captions-transcript.d.ts +4 -0
  100. package/dist/types/content/transcript/providers/youtube/captions.d.ts +2 -19
  101. package/dist/types/content/transcript/providers/youtube/provider-flow.d.ts +34 -0
  102. package/dist/types/content/transcript/providers/youtube/yt-dlp.d.ts +4 -2
  103. package/dist/types/content/transcript/transcription-config.d.ts +6 -0
  104. package/dist/types/content/transcript/types.d.ts +1 -0
  105. package/dist/types/prompts/format.d.ts +1 -0
  106. package/dist/types/prompts/link-summary.d.ts +2 -1
  107. package/dist/types/transcription/whisper/assemblyai.d.ts +17 -0
  108. package/dist/types/transcription/whisper/chunking.d.ts +11 -0
  109. package/dist/types/transcription/whisper/cloud-providers.d.ts +22 -0
  110. package/dist/types/transcription/whisper/core.d.ts +12 -14
  111. package/dist/types/transcription/whisper/gemini.d.ts +14 -0
  112. package/dist/types/transcription/whisper/preferences.d.ts +4 -0
  113. package/dist/types/transcription/whisper/provider-setup.d.ts +30 -0
  114. package/dist/types/transcription/whisper/remote-provider-attempts.d.ts +51 -0
  115. package/dist/types/transcription/whisper/remote.d.ts +51 -0
  116. package/dist/types/transcription/whisper/types.d.ts +1 -1
  117. package/package.json +15 -16
@@ -0,0 +1,12 @@
1
+ import type { TranscriptSegment } from "../../../link-preview/types.js";
2
+ export declare function tryFetchTranscriptFromFeedXml({ fetchImpl, feedXml, episodeTitle, notes, }: {
3
+ fetchImpl: typeof fetch;
4
+ feedXml: string;
5
+ episodeTitle: string | null;
6
+ notes: string[];
7
+ }): Promise<{
8
+ text: string;
9
+ transcriptUrl: string;
10
+ transcriptType: string | null;
11
+ segments: TranscriptSegment[] | null;
12
+ } | null>;
@@ -1,24 +1,2 @@
1
- import type { TranscriptSegment } from "../../../link-preview/types.js";
2
- export declare function looksLikeRssOrAtomFeed(xml: string): boolean;
3
- export declare function extractEnclosureFromFeed(xml: string): {
4
- enclosureUrl: string;
5
- durationSeconds: number | null;
6
- } | null;
7
- export declare function extractEnclosureForEpisode(feedXml: string, episodeTitle: string): {
8
- enclosureUrl: string;
9
- durationSeconds: number | null;
10
- } | null;
11
- export declare function extractItemDurationSeconds(itemXml: string): number | null;
12
- export declare function decodeXmlEntities(value: string): string;
13
- export declare function normalizeLooseTitle(value: string): string;
14
- export declare function tryFetchTranscriptFromFeedXml({ fetchImpl, feedXml, episodeTitle, notes, }: {
15
- fetchImpl: typeof fetch;
16
- feedXml: string;
17
- episodeTitle: string | null;
18
- notes: string[];
19
- }): Promise<{
20
- text: string;
21
- transcriptUrl: string;
22
- transcriptType: string | null;
23
- segments: TranscriptSegment[] | null;
24
- } | null>;
1
+ export { decodeXmlEntities, extractEnclosureForEpisode, extractEnclosureFromFeed, extractItemDurationSeconds, looksLikeRssOrAtomFeed, normalizeLooseTitle, } from "./rss-feed.js";
2
+ export { tryFetchTranscriptFromFeedXml } from "./rss-transcript.js";
@@ -0,0 +1,18 @@
1
+ import type { TranscriptionConfig } from "../transcription-config.js";
2
+ import type { ProviderResult, TranscriptSource } from "../types.js";
3
+ import { type TranscriptionAvailability } from "./transcription-start.js";
4
+ export type TranscriptProviderCapabilities = {
5
+ availability: TranscriptionAvailability;
6
+ canTranscribe: boolean;
7
+ canRunYtDlp: boolean;
8
+ missingProviderNote: string;
9
+ };
10
+ export declare function resolveTranscriptProviderCapabilities({ transcription, ytDlpPath, }: {
11
+ transcription: TranscriptionConfig;
12
+ ytDlpPath?: string | null;
13
+ }): Promise<TranscriptProviderCapabilities>;
14
+ export declare function buildMissingTranscriptionProviderResult(args: {
15
+ attemptedProviders: TranscriptSource[];
16
+ metadata: NonNullable<ProviderResult["metadata"]>;
17
+ notes?: string[] | null;
18
+ }): ProviderResult;
@@ -1,5 +1,5 @@
1
- import type { TranscriptionProviderHint } from "../../link-preview/deps.js";
2
1
  import { resolvePreferredOnnxModel } from "../../../transcription/onnx-cli.js";
2
+ import type { TranscriptionProviderHint } from "../../link-preview/deps.js";
3
3
  import { type TranscriptionConfig } from "../transcription-config.js";
4
4
  type Env = Record<string, string | undefined>;
5
5
  export type TranscriptionAvailability = {
@@ -7,21 +7,28 @@ export type TranscriptionAvailability = {
7
7
  onnxReady: boolean;
8
8
  hasLocalWhisper: boolean;
9
9
  hasGroq: boolean;
10
+ hasAssemblyAi: boolean;
11
+ hasGemini: boolean;
10
12
  hasOpenai: boolean;
11
13
  hasFal: boolean;
12
14
  hasAnyProvider: boolean;
15
+ geminiModelId: string;
13
16
  };
14
- export declare function resolveTranscriptionAvailability({ env, transcription, groqApiKey, openaiApiKey, falApiKey, }: {
17
+ export declare function resolveTranscriptionAvailability({ env, transcription, groqApiKey, assemblyaiApiKey, geminiApiKey, openaiApiKey, falApiKey, }: {
15
18
  env?: Env;
16
19
  transcription?: Partial<TranscriptionConfig> | null;
17
20
  groqApiKey?: string | null;
21
+ assemblyaiApiKey?: string | null;
22
+ geminiApiKey?: string | null;
18
23
  openaiApiKey?: string | null;
19
24
  falApiKey?: string | null;
20
25
  }): Promise<TranscriptionAvailability>;
21
- export declare function resolveTranscriptionStartInfo({ env, transcription, groqApiKey, openaiApiKey, falApiKey, }: {
26
+ export declare function resolveTranscriptionStartInfo({ env, transcription, groqApiKey, assemblyaiApiKey, geminiApiKey, openaiApiKey, falApiKey, }: {
22
27
  env?: Env;
23
28
  transcription?: Partial<TranscriptionConfig> | null;
24
29
  groqApiKey?: string | null;
30
+ assemblyaiApiKey?: string | null;
31
+ geminiApiKey?: string | null;
25
32
  openaiApiKey?: string | null;
26
33
  falApiKey?: string | null;
27
34
  }): Promise<{
@@ -0,0 +1,12 @@
1
+ export declare function extractInitialPlayerResponse(html: string): Record<string, unknown> | null;
2
+ export declare function extractDurationSecondsFromPlayerPayload(payload: Record<string, unknown>): number | null;
3
+ export declare function extractYoutubeDurationSeconds(html: string): number | null;
4
+ export declare function extractInnertubeApiKey(html: string): string | null;
5
+ export declare function fetchYoutubePlayerPayload(fetchImpl: typeof fetch, { html, videoId }: {
6
+ html: string;
7
+ videoId: string;
8
+ }): Promise<Record<string, unknown> | null>;
9
+ export declare function fetchYoutubeDurationSecondsViaPlayer(fetchImpl: typeof fetch, { html, videoId }: {
10
+ html: string;
11
+ videoId: string;
12
+ }): Promise<number | null>;
@@ -0,0 +1,42 @@
1
+ import type { TranscriptSegment } from "../../../link-preview/types.js";
2
+ export interface YoutubeTranscriptContext {
3
+ html: string;
4
+ originalUrl: string;
5
+ videoId: string;
6
+ }
7
+ export type TranscriptPayload = {
8
+ text: string;
9
+ segments: TranscriptSegment[] | null;
10
+ };
11
+ export declare const REQUEST_HEADERS: Record<string, string>;
12
+ export declare const YT_INITIAL_PLAYER_RESPONSE_TOKEN = "ytInitialPlayerResponse";
13
+ export declare const INNERTUBE_API_KEY_REGEX: RegExp;
14
+ export declare const isObjectLike: (value: unknown) => value is Record<string, unknown>;
15
+ export type YoutubePlayerContext = Record<string, unknown> & {
16
+ client?: unknown;
17
+ };
18
+ export type CaptionsPayload = Record<string, unknown> & {
19
+ captions?: unknown;
20
+ playerCaptionsTracklistRenderer?: unknown;
21
+ };
22
+ export type CaptionListRenderer = Record<string, unknown> & {
23
+ captionTracks?: unknown;
24
+ automaticCaptions?: unknown;
25
+ };
26
+ export type CaptionTrackRecord = Record<string, unknown> & {
27
+ languageCode?: unknown;
28
+ kind?: unknown;
29
+ baseUrl?: unknown;
30
+ url?: unknown;
31
+ };
32
+ export type CaptionEventRecord = Record<string, unknown> & {
33
+ segs?: unknown;
34
+ tStartMs?: unknown;
35
+ dDurationMs?: unknown;
36
+ };
37
+ export type CaptionSegmentRecord = Record<string, unknown> & {
38
+ utf8?: unknown;
39
+ };
40
+ export type CaptionPayload = {
41
+ events?: unknown;
42
+ };
@@ -0,0 +1,4 @@
1
+ import { TranscriptPayload, YoutubeTranscriptContext } from "./captions-shared.js";
2
+ export declare const fetchTranscriptFromCaptionTracks: (fetchImpl: typeof fetch, { html, originalUrl, videoId, skipAutoGenerated, }: YoutubeTranscriptContext & {
3
+ skipAutoGenerated?: boolean;
4
+ }) => Promise<TranscriptPayload | null>;
@@ -1,19 +1,2 @@
1
- import type { TranscriptSegment } from "../../../link-preview/types.js";
2
- interface YoutubeTranscriptContext {
3
- html: string;
4
- originalUrl: string;
5
- videoId: string;
6
- }
7
- type TranscriptPayload = {
8
- text: string;
9
- segments: TranscriptSegment[] | null;
10
- };
11
- export declare function extractYoutubeDurationSeconds(html: string): number | null;
12
- export declare function fetchYoutubeDurationSecondsViaPlayer(fetchImpl: typeof fetch, { html, videoId }: {
13
- html: string;
14
- videoId: string;
15
- }): Promise<number | null>;
16
- export declare const fetchTranscriptFromCaptionTracks: (fetchImpl: typeof fetch, { html, originalUrl, videoId, skipAutoGenerated, }: YoutubeTranscriptContext & {
17
- skipAutoGenerated?: boolean;
18
- }) => Promise<TranscriptPayload | null>;
19
- export {};
1
+ export { extractYoutubeDurationSeconds, fetchYoutubeDurationSecondsViaPlayer, } from "./captions-player.js";
2
+ export { fetchTranscriptFromCaptionTracks } from "./captions-transcript.js";
@@ -0,0 +1,34 @@
1
+ import type { TranscriptionConfig } from "../../transcription-config.js";
2
+ import type { ProviderContext, ProviderFetchOptions, ProviderResult, TranscriptSource } from "../../types.js";
3
+ type DurationMetadata = {
4
+ durationSeconds: number;
5
+ } | null;
6
+ export type YouTubeProviderFlow = {
7
+ context: ProviderContext;
8
+ options: ProviderFetchOptions;
9
+ transcription: TranscriptionConfig;
10
+ htmlText: string;
11
+ attemptedProviders: TranscriptSource[];
12
+ notes: string[];
13
+ effectiveVideoId: string | null;
14
+ durationMetadata: DurationMetadata;
15
+ canRunYtDlp: boolean;
16
+ pushHint: (hint: string) => void;
17
+ };
18
+ export declare function loadYoutubeHtml(context: ProviderContext, options: ProviderFetchOptions): Promise<string | null>;
19
+ export declare function resolveEffectiveVideoId(context: ProviderContext): string | null;
20
+ export declare function resolveDurationMetadata(args: {
21
+ htmlText: string;
22
+ effectiveVideoId: string | null;
23
+ url: string;
24
+ options: ProviderFetchOptions;
25
+ }): Promise<DurationMetadata>;
26
+ export declare function tryApifyTranscript(flow: YouTubeProviderFlow, hint: string): Promise<ProviderResult | null>;
27
+ export declare function tryManualCaptionTranscript(flow: YouTubeProviderFlow): Promise<ProviderResult | null>;
28
+ export declare function tryWebTranscript(flow: YouTubeProviderFlow): Promise<ProviderResult | null>;
29
+ export declare function tryYtDlpTranscript(args: {
30
+ flow: YouTubeProviderFlow;
31
+ mode: ProviderFetchOptions["youtubeTranscriptMode"];
32
+ }): Promise<ProviderResult | null>;
33
+ export declare function buildUnavailableResult(flow: YouTubeProviderFlow): ProviderResult;
34
+ export {};
@@ -1,6 +1,6 @@
1
+ import { type TranscriptionProvider } from "../../../../transcription/whisper.js";
1
2
  import type { MediaCache } from "../../../cache/types.js";
2
3
  import type { LinkPreviewProgressEvent } from "../../../link-preview/deps.js";
3
- import { type TranscriptionProvider } from "../../../../transcription/whisper.js";
4
4
  import { type TranscriptionConfig } from "../../transcription-config.js";
5
5
  type YtDlpTranscriptResult = {
6
6
  text: string | null;
@@ -13,6 +13,8 @@ type YtDlpRequest = {
13
13
  transcription?: Partial<TranscriptionConfig> | null;
14
14
  env?: Record<string, string | undefined>;
15
15
  groqApiKey?: string | null;
16
+ assemblyaiApiKey?: string | null;
17
+ geminiApiKey?: string | null;
16
18
  openaiApiKey?: string | null;
17
19
  falApiKey?: string | null;
18
20
  url: string;
@@ -26,6 +28,6 @@ type YtDlpDurationRequest = {
26
28
  ytDlpPath: string | null;
27
29
  url: string;
28
30
  };
29
- export declare const fetchTranscriptWithYtDlp: ({ ytDlpPath, transcription, env, groqApiKey, openaiApiKey, falApiKey, url, onProgress, service, mediaKind, mediaCache, extraArgs, }: YtDlpRequest) => Promise<YtDlpTranscriptResult>;
31
+ export declare const fetchTranscriptWithYtDlp: ({ ytDlpPath, transcription, env, groqApiKey, assemblyaiApiKey, geminiApiKey, openaiApiKey, falApiKey, url, onProgress, service, mediaKind, mediaCache, extraArgs, }: YtDlpRequest) => Promise<YtDlpTranscriptResult>;
30
32
  export declare const fetchDurationSecondsWithYtDlp: ({ ytDlpPath, url, }: YtDlpDurationRequest) => Promise<number | null>;
31
33
  export {};
@@ -1,15 +1,21 @@
1
1
  export type TranscriptionConfig = {
2
2
  env?: Record<string, string | undefined>;
3
3
  groqApiKey: string | null;
4
+ assemblyaiApiKey: string | null;
5
+ geminiApiKey: string | null;
4
6
  openaiApiKey: string | null;
5
7
  falApiKey: string | null;
8
+ geminiModel: string | null;
6
9
  };
7
10
  type TranscriptionConfigInput = {
8
11
  env?: Record<string, string | undefined>;
9
12
  transcription?: Partial<TranscriptionConfig> | null;
10
13
  groqApiKey?: string | null;
14
+ assemblyaiApiKey?: string | null;
15
+ geminiApiKey?: string | null;
11
16
  openaiApiKey?: string | null;
12
17
  falApiKey?: string | null;
18
+ geminiModel?: string | null;
13
19
  };
14
20
  export declare function resolveTranscriptionConfig(input: TranscriptionConfigInput): TranscriptionConfig;
15
21
  export {};
@@ -22,6 +22,7 @@ export interface ProviderFetchOptions {
22
22
  transcription?: TranscriptionConfig;
23
23
  falApiKey?: string | null;
24
24
  groqApiKey?: string | null;
25
+ geminiApiKey?: string | null;
25
26
  openaiApiKey?: string | null;
26
27
  mediaCache?: MediaCache | null;
27
28
  resolveTwitterCookies?: ResolveTwitterCookies | null;
@@ -1,5 +1,6 @@
1
1
  export type PromptOverrides = {
2
2
  promptOverride?: string | null;
3
+ requiredInstructions?: string[] | null;
3
4
  lengthInstruction?: string | null;
4
5
  languageInstruction?: string | null;
5
6
  };
@@ -16,7 +16,7 @@ export type ShareContextEntry = {
16
16
  replyCount?: number | null;
17
17
  timestamp?: string | null;
18
18
  };
19
- export declare function buildLinkSummaryPrompt({ url, title, siteName, description, content, truncated, hasTranscript, hasTranscriptTimestamps, slides, outputLanguage, summaryLength, shares, promptOverride, lengthInstruction, languageInstruction, }: {
19
+ export declare function buildLinkSummaryPrompt({ url, title, siteName, description, content, truncated, hasTranscript, hasTranscriptTimestamps, timestampLimitInstruction, slides, outputLanguage, summaryLength, shares, promptOverride, lengthInstruction, languageInstruction, }: {
20
20
  url: string;
21
21
  title: string | null;
22
22
  siteName: string | null;
@@ -25,6 +25,7 @@ export declare function buildLinkSummaryPrompt({ url, title, siteName, descripti
25
25
  truncated: boolean;
26
26
  hasTranscript: boolean;
27
27
  hasTranscriptTimestamps?: boolean;
28
+ timestampLimitInstruction?: string | null;
28
29
  slides?: {
29
30
  count: number;
30
31
  text: string;
@@ -0,0 +1,17 @@
1
+ export declare const ASSEMBLYAI_DEFAULT_SPEECH_MODEL = "universal-2";
2
+ export declare const ASSEMBLYAI_DEFAULT_MODELS: readonly ["universal-2"];
3
+ export declare const ASSEMBLYAI_TRANSCRIPTION_MODEL_ID: "assemblyai/universal-2";
4
+ type AssemblyAiOptions = {
5
+ fetchImpl?: typeof fetch;
6
+ baseUrl?: string;
7
+ pollIntervalMs?: number;
8
+ timeoutMs?: number;
9
+ mediaType?: string | null;
10
+ };
11
+ export declare function transcribeWithAssemblyAi(bytes: Uint8Array, mediaType: string, apiKey: string, options?: AssemblyAiOptions): Promise<string | null>;
12
+ export declare function transcribeFileWithAssemblyAi({ filePath, mediaType, apiKey, fetchImpl, baseUrl, pollIntervalMs, timeoutMs, }: {
13
+ filePath: string;
14
+ mediaType: string;
15
+ apiKey: string;
16
+ } & Pick<AssemblyAiOptions, "fetchImpl" | "baseUrl" | "pollIntervalMs" | "timeoutMs">): Promise<string | null>;
17
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { WhisperProgressEvent, WhisperTranscriptionResult } from "./types.js";
2
+ export declare function transcribeChunkedFile({ filePath, segmentSeconds, totalDurationSeconds, onProgress, transcribeSegment, }: {
3
+ filePath: string;
4
+ segmentSeconds: number;
5
+ totalDurationSeconds: number | null;
6
+ onProgress?: ((event: WhisperProgressEvent) => void) | null;
7
+ transcribeSegment: (args: {
8
+ bytes: Uint8Array;
9
+ filename: string;
10
+ }) => Promise<WhisperTranscriptionResult>;
11
+ }): Promise<WhisperTranscriptionResult>;
@@ -0,0 +1,22 @@
1
+ export type CloudProvider = "assemblyai" | "gemini" | "openai" | "fal";
2
+ type CloudProviderKeyState = {
3
+ assemblyaiApiKey: string | null;
4
+ geminiApiKey: string | null;
5
+ openaiApiKey: string | null;
6
+ falApiKey: string | null;
7
+ };
8
+ type CloudProviderAvailability = {
9
+ hasAssemblyAi: boolean;
10
+ hasGemini: boolean;
11
+ hasOpenai: boolean;
12
+ hasFal: boolean;
13
+ };
14
+ export declare function resolveCloudProviderOrder(state: CloudProviderKeyState): CloudProvider[];
15
+ export declare function cloudProviderLabel(provider: CloudProvider, chained: boolean): string;
16
+ export declare function formatCloudFallbackTargets(providers: CloudProvider[]): string;
17
+ export declare function buildCloudProviderHint(availability: CloudProviderAvailability): string | null;
18
+ export declare function buildCloudModelIdChain({ availability, geminiModelId, }: {
19
+ availability: CloudProviderAvailability;
20
+ geminiModelId: string;
21
+ }): string | null;
22
+ export {};
@@ -1,27 +1,25 @@
1
1
  import type { WhisperProgressEvent, WhisperTranscriptionResult } from "./types.js";
2
2
  type Env = Record<string, string | undefined>;
3
- export declare function transcribeMediaWithWhisper({ bytes, mediaType, filename, groqApiKey, skipGroq, openaiApiKey, falApiKey, totalDurationSeconds, onProgress, env, }: {
4
- bytes: Uint8Array;
5
- mediaType: string;
6
- filename: string | null;
3
+ type MediaRequest = {
7
4
  groqApiKey: string | null;
8
- skipGroq?: boolean;
5
+ assemblyaiApiKey?: string | null;
6
+ geminiApiKey?: string | null;
9
7
  openaiApiKey: string | null;
10
8
  falApiKey: string | null;
11
9
  totalDurationSeconds?: number | null;
12
10
  onProgress?: ((event: WhisperProgressEvent) => void) | null;
13
11
  env?: Env;
14
- }): Promise<WhisperTranscriptionResult>;
15
- export declare function transcribeMediaFileWithWhisper({ filePath, mediaType, filename, groqApiKey, openaiApiKey, falApiKey, segmentSeconds, totalDurationSeconds, onProgress, env, }: {
12
+ };
13
+ export declare function transcribeMediaWithWhisper({ bytes, mediaType, filename, groqApiKey, skipGroq, assemblyaiApiKey, geminiApiKey, openaiApiKey, falApiKey, totalDurationSeconds, onProgress, env, }: {
14
+ bytes: Uint8Array;
15
+ mediaType: string;
16
+ filename: string | null;
17
+ skipGroq?: boolean;
18
+ } & MediaRequest): Promise<WhisperTranscriptionResult>;
19
+ export declare function transcribeMediaFileWithWhisper({ filePath, mediaType, filename, groqApiKey, assemblyaiApiKey, geminiApiKey, openaiApiKey, falApiKey, segmentSeconds, totalDurationSeconds, onProgress, env, }: {
16
20
  filePath: string;
17
21
  mediaType: string;
18
22
  filename: string | null;
19
- groqApiKey: string | null;
20
- openaiApiKey: string | null;
21
- falApiKey: string | null;
22
23
  segmentSeconds?: number;
23
- totalDurationSeconds?: number | null;
24
- onProgress?: ((event: WhisperProgressEvent) => void) | null;
25
- env?: Env;
26
- }): Promise<WhisperTranscriptionResult>;
24
+ } & MediaRequest): Promise<WhisperTranscriptionResult>;
27
25
  export {};
@@ -0,0 +1,14 @@
1
+ type Env = Record<string, string | undefined>;
2
+ export declare function transcribeWithGemini(bytes: Uint8Array, mediaType: string, filename: string | null, apiKey: string, options?: {
3
+ env?: Env;
4
+ model?: string | null;
5
+ }): Promise<string | null>;
6
+ export declare function transcribeFileWithGemini({ filePath, mediaType, filename, apiKey, env, model, }: {
7
+ filePath: string;
8
+ mediaType: string;
9
+ filename: string | null;
10
+ apiKey: string;
11
+ env?: Env;
12
+ model?: string | null;
13
+ }): Promise<string | null>;
14
+ export {};
@@ -0,0 +1,4 @@
1
+ type Env = Record<string, string | undefined>;
2
+ export declare function resolveTranscriberPreference(env: Env): "auto" | "whisper" | "parakeet" | "canary";
3
+ export declare function resolveOnnxModelPreference(env: Env): "parakeet" | "canary" | null;
4
+ export {};
@@ -0,0 +1,30 @@
1
+ type Env = Record<string, string | undefined>;
2
+ export declare const DEFAULT_GEMINI_TRANSCRIPTION_MODEL = "gemini-2.5-flash";
3
+ export declare const GEMINI_TRANSCRIPTION_MODEL_ENV = "SUMMARIZE_GEMINI_TRANSCRIPTION_MODEL";
4
+ export declare const TRANSCRIPTION_PROVIDER_ENV_LIST: readonly ["GROQ_API_KEY", "ASSEMBLYAI_API_KEY", "GEMINI_API_KEY", "OPENAI_API_KEY", "FAL_KEY"];
5
+ export declare const TRANSCRIPTION_PROVIDER_ENV_LABEL = "GROQ_API_KEY, ASSEMBLYAI_API_KEY, GEMINI_API_KEY, OPENAI_API_KEY, or FAL_KEY";
6
+ export declare function normalizeApiKey(raw: string | null | undefined): string | null;
7
+ export declare function resolveGeminiApiKey({ env, geminiApiKey, }: {
8
+ env?: Env;
9
+ geminiApiKey?: string | null;
10
+ }): string | null;
11
+ export declare function resolveGroqApiKey({ env, groqApiKey, }: {
12
+ env?: Env;
13
+ groqApiKey?: string | null;
14
+ }): string | null;
15
+ export declare function resolveAssemblyAiApiKey({ env, assemblyaiApiKey, }: {
16
+ env?: Env;
17
+ assemblyaiApiKey?: string | null;
18
+ }): string | null;
19
+ export declare function resolveOpenAiTranscriptionApiKey({ env, openaiApiKey, }: {
20
+ env?: Env;
21
+ openaiApiKey?: string | null;
22
+ }): string | null;
23
+ export declare function resolveFalApiKey({ env, falApiKey, }: {
24
+ env?: Env;
25
+ falApiKey?: string | null;
26
+ }): string | null;
27
+ export declare function resolveGeminiTranscriptionModel(env?: Env): string;
28
+ export declare function buildMissingTranscriptionProviderMessage(): string;
29
+ export declare function buildMissingTranscriptionProviderNote(): string;
30
+ export {};
@@ -0,0 +1,51 @@
1
+ import type { CloudProvider } from "./cloud-providers.js";
2
+ import type { WhisperProgressEvent, WhisperTranscriptionResult } from "./types.js";
3
+ type Env = Record<string, string | undefined>;
4
+ export type RemoteByteState = {
5
+ bytes: Uint8Array;
6
+ mediaType: string;
7
+ filename: string | null;
8
+ };
9
+ type RemoteByteAttemptResult = {
10
+ state: RemoteByteState;
11
+ result: WhisperTranscriptionResult | null;
12
+ error: Error | null;
13
+ skipped?: boolean;
14
+ };
15
+ type RemoteFileAttemptResult = {
16
+ kind: "result";
17
+ result: WhisperTranscriptionResult;
18
+ } | {
19
+ kind: "error";
20
+ error: Error;
21
+ } | {
22
+ kind: "delegate-to-bytes";
23
+ };
24
+ type TranscribeOversizedBytesWithChunking = (args: {
25
+ bytes: Uint8Array;
26
+ mediaType: string;
27
+ filename: string | null;
28
+ onProgress?: ((event: WhisperProgressEvent) => void) | null;
29
+ }) => Promise<WhisperTranscriptionResult>;
30
+ export declare function attemptRemoteBytesProvider(args: {
31
+ provider: CloudProvider;
32
+ state: RemoteByteState;
33
+ assemblyaiApiKey: string | null;
34
+ geminiApiKey: string | null;
35
+ openaiApiKey: string | null;
36
+ falApiKey: string | null;
37
+ env: Env;
38
+ notes: string[];
39
+ onProgress?: ((event: WhisperProgressEvent) => void) | null;
40
+ transcribeOversizedBytesWithChunking?: TranscribeOversizedBytesWithChunking;
41
+ }): Promise<RemoteByteAttemptResult>;
42
+ export declare function attemptRemoteFileProvider(args: {
43
+ provider: CloudProvider;
44
+ filePath: string;
45
+ mediaType: string;
46
+ filename: string | null;
47
+ assemblyaiApiKey: string | null;
48
+ geminiApiKey: string | null;
49
+ env: Env;
50
+ }): Promise<RemoteFileAttemptResult>;
51
+ export {};
@@ -0,0 +1,51 @@
1
+ import type { WhisperProgressEvent, WhisperTranscriptionResult } from "./types.js";
2
+ type Env = Record<string, string | undefined>;
3
+ type CloudArgs = {
4
+ groqApiKey: string | null;
5
+ groqError?: Error | null;
6
+ assemblyaiApiKey: string | null;
7
+ geminiApiKey: string | null;
8
+ openaiApiKey: string | null;
9
+ falApiKey: string | null;
10
+ env: Env;
11
+ };
12
+ export declare function transcribeBytesWithRemoteFallbacks({ bytes, mediaType, filename, notes, groqApiKey, groqError, assemblyaiApiKey, geminiApiKey, openaiApiKey, falApiKey, env, onProgress, transcribeOversizedBytesWithChunking, }: {
13
+ bytes: Uint8Array;
14
+ mediaType: string;
15
+ filename: string | null;
16
+ notes: string[];
17
+ onProgress?: ((event: WhisperProgressEvent) => void) | null;
18
+ transcribeOversizedBytesWithChunking: (args: {
19
+ bytes: Uint8Array;
20
+ mediaType: string;
21
+ filename: string | null;
22
+ onProgress?: ((event: WhisperProgressEvent) => void) | null;
23
+ }) => Promise<WhisperTranscriptionResult>;
24
+ } & CloudArgs): Promise<WhisperTranscriptionResult>;
25
+ export declare function transcribeFileWithRemoteFallbacks({ filePath, mediaType, filename, notes, groqApiKey, groqError, assemblyaiApiKey, geminiApiKey, openaiApiKey, falApiKey, env, totalDurationSeconds, onProgress, transcribeChunkedFile, }: {
26
+ filePath: string;
27
+ mediaType: string;
28
+ filename: string | null;
29
+ notes: string[];
30
+ totalDurationSeconds: number | null;
31
+ onProgress?: ((event: WhisperProgressEvent) => void) | null;
32
+ transcribeChunkedFile: (args: {
33
+ filePath: string;
34
+ segmentSeconds: number;
35
+ totalDurationSeconds: number | null;
36
+ onProgress?: ((event: WhisperProgressEvent) => void) | null;
37
+ }) => Promise<WhisperTranscriptionResult>;
38
+ } & CloudArgs): Promise<WhisperTranscriptionResult>;
39
+ export declare function transcribeOversizedBytesViaTempFile({ bytes, mediaType, filename, onProgress, transcribeFile, }: {
40
+ bytes: Uint8Array;
41
+ mediaType: string;
42
+ filename: string | null;
43
+ onProgress?: ((event: WhisperProgressEvent) => void) | null;
44
+ transcribeFile: (args: {
45
+ filePath: string;
46
+ mediaType: string;
47
+ filename: string | null;
48
+ onProgress?: ((event: WhisperProgressEvent) => void) | null;
49
+ }) => Promise<WhisperTranscriptionResult>;
50
+ }): Promise<WhisperTranscriptionResult>;
51
+ export {};
@@ -1,4 +1,4 @@
1
- export type TranscriptionProvider = "groq" | "openai" | "fal" | "whisper.cpp" | "onnx-parakeet" | "onnx-canary";
1
+ export type TranscriptionProvider = "groq" | "assemblyai" | "gemini" | "openai" | "fal" | "whisper.cpp" | "onnx-parakeet" | "onnx-canary";
2
2
  export type WhisperTranscriptionResult = {
3
3
  text: string | null;
4
4
  provider: TranscriptionProvider | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steipete/summarize-core",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Summarize core library (content extraction + prompts).",
5
5
  "files": [
6
6
  "dist",
@@ -36,28 +36,27 @@
36
36
  "import": "./dist/esm/language.js"
37
37
  }
38
38
  },
39
- "scripts": {
40
- "build": "pnpm clean && tsc -p tsconfig.build.json",
41
- "clean": "rimraf dist",
42
- "typecheck": "tsc -p tsconfig.build.json --noEmit"
43
- },
44
39
  "dependencies": {
45
- "@fal-ai/client": "^1.9.1",
40
+ "@fal-ai/client": "^1.9.4",
46
41
  "@mozilla/readability": "0.6.0",
47
42
  "cheerio": "^1.2.0",
48
- "es-toolkit": "^1.44.0",
49
- "jsdom": "28.0.0",
50
- "sanitize-html": "^2.17.0"
43
+ "es-toolkit": "^1.45.1",
44
+ "jsdom": "28.1.0",
45
+ "sanitize-html": "^2.17.1"
51
46
  },
52
47
  "devDependencies": {
53
- "@types/jsdom": "^27.0.0",
54
- "@types/node": "^25.2.3",
55
- "@types/sanitize-html": "^2.16.0",
56
- "rimraf": "^6.1.2",
48
+ "@types/jsdom": "^28.0.0",
49
+ "@types/node": "^25.3.5",
50
+ "@types/sanitize-html": "^2.16.1",
51
+ "rimraf": "^6.1.3",
57
52
  "typescript": "^5.9.3"
58
53
  },
59
54
  "engines": {
60
55
  "node": ">=22"
61
56
  },
62
- "packageManager": "pnpm@10.25.0+sha512.5e82639027af37cf832061bcc6d639c219634488e0f2baebe785028a793de7b525ffcd3f7ff574f5e9860654e098fe852ba8ac5dd5cefe1767d23a020a92f501"
63
- }
57
+ "scripts": {
58
+ "build": "pnpm clean && tsc -p tsconfig.build.json",
59
+ "clean": "rimraf dist",
60
+ "typecheck": "tsc -p tsconfig.build.json --noEmit"
61
+ }
62
+ }