@steipete/summarize 0.9.0 → 0.10.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 (203) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/LICENSE +1 -1
  3. package/README.md +307 -184
  4. package/dist/cli.js +1 -1
  5. package/dist/esm/cache.js +72 -4
  6. package/dist/esm/cache.js.map +1 -1
  7. package/dist/esm/config.js +127 -1
  8. package/dist/esm/config.js.map +1 -1
  9. package/dist/esm/daemon/agent.js +547 -0
  10. package/dist/esm/daemon/agent.js.map +1 -0
  11. package/dist/esm/daemon/chat.js +83 -175
  12. package/dist/esm/daemon/chat.js.map +1 -1
  13. package/dist/esm/daemon/cli.js +35 -3
  14. package/dist/esm/daemon/cli.js.map +1 -1
  15. package/dist/esm/daemon/env-snapshot.js +3 -0
  16. package/dist/esm/daemon/env-snapshot.js.map +1 -1
  17. package/dist/esm/daemon/flow-context.js +31 -8
  18. package/dist/esm/daemon/flow-context.js.map +1 -1
  19. package/dist/esm/daemon/launchd.js +27 -0
  20. package/dist/esm/daemon/launchd.js.map +1 -1
  21. package/dist/esm/daemon/process-registry.js +206 -0
  22. package/dist/esm/daemon/process-registry.js.map +1 -0
  23. package/dist/esm/daemon/schtasks.js +64 -0
  24. package/dist/esm/daemon/schtasks.js.map +1 -1
  25. package/dist/esm/daemon/server.js +712 -42
  26. package/dist/esm/daemon/server.js.map +1 -1
  27. package/dist/esm/daemon/summarize.js +33 -4
  28. package/dist/esm/daemon/summarize.js.map +1 -1
  29. package/dist/esm/daemon/systemd.js +61 -0
  30. package/dist/esm/daemon/systemd.js.map +1 -1
  31. package/dist/esm/flags.js +24 -0
  32. package/dist/esm/flags.js.map +1 -1
  33. package/dist/esm/llm/providers/openai.js +1 -1
  34. package/dist/esm/llm/providers/openai.js.map +1 -1
  35. package/dist/esm/media-cache.js +251 -0
  36. package/dist/esm/media-cache.js.map +1 -0
  37. package/dist/esm/processes.js +2 -0
  38. package/dist/esm/processes.js.map +1 -0
  39. package/dist/esm/run/bird.js +118 -5
  40. package/dist/esm/run/bird.js.map +1 -1
  41. package/dist/esm/run/cli-preflight.js +19 -1
  42. package/dist/esm/run/cli-preflight.js.map +1 -1
  43. package/dist/esm/run/finish-line.js +11 -4
  44. package/dist/esm/run/finish-line.js.map +1 -1
  45. package/dist/esm/run/flows/asset/extract.js +70 -0
  46. package/dist/esm/run/flows/asset/extract.js.map +1 -0
  47. package/dist/esm/run/flows/asset/input.js +208 -24
  48. package/dist/esm/run/flows/asset/input.js.map +1 -1
  49. package/dist/esm/run/flows/asset/media-policy.js +3 -0
  50. package/dist/esm/run/flows/asset/media-policy.js.map +1 -0
  51. package/dist/esm/run/flows/asset/media.js +224 -0
  52. package/dist/esm/run/flows/asset/media.js.map +1 -0
  53. package/dist/esm/run/flows/asset/output.js +98 -0
  54. package/dist/esm/run/flows/asset/output.js.map +1 -0
  55. package/dist/esm/run/flows/asset/summary.js +157 -7
  56. package/dist/esm/run/flows/asset/summary.js.map +1 -1
  57. package/dist/esm/run/flows/url/extract.js +6 -6
  58. package/dist/esm/run/flows/url/extract.js.map +1 -1
  59. package/dist/esm/run/flows/url/flow.js +336 -36
  60. package/dist/esm/run/flows/url/flow.js.map +1 -1
  61. package/dist/esm/run/flows/url/markdown.js +6 -1
  62. package/dist/esm/run/flows/url/markdown.js.map +1 -1
  63. package/dist/esm/run/flows/url/slides-output.js +485 -0
  64. package/dist/esm/run/flows/url/slides-output.js.map +1 -0
  65. package/dist/esm/run/flows/url/slides-text.js +628 -0
  66. package/dist/esm/run/flows/url/slides-text.js.map +1 -0
  67. package/dist/esm/run/flows/url/summary.js +356 -82
  68. package/dist/esm/run/flows/url/summary.js.map +1 -1
  69. package/dist/esm/run/help.js +94 -5
  70. package/dist/esm/run/help.js.map +1 -1
  71. package/dist/esm/run/logging.js +12 -4
  72. package/dist/esm/run/logging.js.map +1 -1
  73. package/dist/esm/run/media-cache-state.js +33 -0
  74. package/dist/esm/run/media-cache-state.js.map +1 -0
  75. package/dist/esm/run/progress.js +19 -1
  76. package/dist/esm/run/progress.js.map +1 -1
  77. package/dist/esm/run/run-settings.js +39 -1
  78. package/dist/esm/run/run-settings.js.map +1 -1
  79. package/dist/esm/run/runner.js +196 -8
  80. package/dist/esm/run/runner.js.map +1 -1
  81. package/dist/esm/run/slides-cli.js +225 -0
  82. package/dist/esm/run/slides-cli.js.map +1 -0
  83. package/dist/esm/run/slides-render.js +163 -0
  84. package/dist/esm/run/slides-render.js.map +1 -0
  85. package/dist/esm/run/stream-output.js +10 -3
  86. package/dist/esm/run/stream-output.js.map +1 -1
  87. package/dist/esm/run/summary-engine.js +33 -7
  88. package/dist/esm/run/summary-engine.js.map +1 -1
  89. package/dist/esm/run/transcriber-cli.js +148 -0
  90. package/dist/esm/run/transcriber-cli.js.map +1 -0
  91. package/dist/esm/shared/sse-events.js +4 -0
  92. package/dist/esm/shared/sse-events.js.map +1 -1
  93. package/dist/esm/slides/extract.js +1942 -0
  94. package/dist/esm/slides/extract.js.map +1 -0
  95. package/dist/esm/slides/index.js +4 -0
  96. package/dist/esm/slides/index.js.map +1 -0
  97. package/dist/esm/slides/settings.js +73 -0
  98. package/dist/esm/slides/settings.js.map +1 -0
  99. package/dist/esm/slides/store.js +111 -0
  100. package/dist/esm/slides/store.js.map +1 -0
  101. package/dist/esm/slides/types.js +2 -0
  102. package/dist/esm/slides/types.js.map +1 -0
  103. package/dist/esm/tty/osc-progress.js +21 -1
  104. package/dist/esm/tty/osc-progress.js.map +1 -1
  105. package/dist/esm/tty/progress/fetch-html.js +8 -4
  106. package/dist/esm/tty/progress/fetch-html.js.map +1 -1
  107. package/dist/esm/tty/progress/transcript.js +82 -31
  108. package/dist/esm/tty/progress/transcript.js.map +1 -1
  109. package/dist/esm/tty/spinner.js +2 -2
  110. package/dist/esm/tty/spinner.js.map +1 -1
  111. package/dist/esm/tty/theme.js +189 -0
  112. package/dist/esm/tty/theme.js.map +1 -0
  113. package/dist/esm/tty/website-progress.js +17 -13
  114. package/dist/esm/tty/website-progress.js.map +1 -1
  115. package/dist/esm/version.js +1 -1
  116. package/dist/esm/version.js.map +1 -1
  117. package/dist/types/cache.d.ts +14 -2
  118. package/dist/types/config.d.ts +23 -0
  119. package/dist/types/daemon/agent.d.ts +25 -0
  120. package/dist/types/daemon/chat.d.ts +10 -18
  121. package/dist/types/daemon/env-snapshot.d.ts +1 -1
  122. package/dist/types/daemon/flow-context.d.ts +21 -1
  123. package/dist/types/daemon/launchd.d.ts +4 -0
  124. package/dist/types/daemon/process-registry.d.ts +73 -0
  125. package/dist/types/daemon/schtasks.d.ts +4 -0
  126. package/dist/types/daemon/summarize.d.ts +36 -5
  127. package/dist/types/daemon/systemd.d.ts +4 -0
  128. package/dist/types/flags.d.ts +1 -0
  129. package/dist/types/media-cache.d.ts +22 -0
  130. package/dist/types/processes.d.ts +1 -0
  131. package/dist/types/run/bird.d.ts +7 -0
  132. package/dist/types/run/finish-line.d.ts +2 -1
  133. package/dist/types/run/flows/asset/extract.d.ts +18 -0
  134. package/dist/types/run/flows/asset/input.d.ts +12 -2
  135. package/dist/types/run/flows/asset/media-policy.d.ts +2 -0
  136. package/dist/types/run/flows/asset/media.d.ts +21 -0
  137. package/dist/types/run/flows/asset/output.d.ts +42 -0
  138. package/dist/types/run/flows/asset/summary.d.ts +6 -0
  139. package/dist/types/run/flows/url/extract.d.ts +2 -1
  140. package/dist/types/run/flows/url/slides-output.d.ts +66 -0
  141. package/dist/types/run/flows/url/slides-text.d.ts +87 -0
  142. package/dist/types/run/flows/url/summary.d.ts +11 -3
  143. package/dist/types/run/flows/url/types.d.ts +29 -2
  144. package/dist/types/run/help.d.ts +3 -0
  145. package/dist/types/run/logging.d.ts +3 -2
  146. package/dist/types/run/media-cache-state.d.ts +7 -0
  147. package/dist/types/run/progress.d.ts +2 -1
  148. package/dist/types/run/run-settings.d.ts +7 -1
  149. package/dist/types/run/slides-cli.d.ts +9 -0
  150. package/dist/types/run/slides-render.d.ts +30 -0
  151. package/dist/types/run/stream-output.d.ts +2 -1
  152. package/dist/types/run/summary-engine.d.ts +11 -1
  153. package/dist/types/run/transcriber-cli.d.ts +8 -0
  154. package/dist/types/shared/sse-events.d.ts +20 -0
  155. package/dist/types/slides/extract.d.ts +42 -0
  156. package/dist/types/slides/index.d.ts +5 -0
  157. package/dist/types/slides/settings.d.ts +20 -0
  158. package/dist/types/slides/store.d.ts +15 -0
  159. package/dist/types/slides/types.d.ts +40 -0
  160. package/dist/types/tty/osc-progress.d.ts +2 -2
  161. package/dist/types/tty/progress/fetch-html.d.ts +3 -1
  162. package/dist/types/tty/progress/transcript.d.ts +3 -1
  163. package/dist/types/tty/spinner.d.ts +3 -1
  164. package/dist/types/tty/theme.d.ts +44 -0
  165. package/dist/types/tty/website-progress.d.ts +3 -1
  166. package/dist/types/version.d.ts +1 -1
  167. package/docs/README.md +1 -1
  168. package/docs/_config.yml +26 -0
  169. package/docs/_layouts/default.html +60 -0
  170. package/docs/agent.md +333 -0
  171. package/docs/assets/site.css +748 -0
  172. package/docs/assets/site.js +72 -0
  173. package/docs/assets/summarize-cli.png +0 -0
  174. package/docs/assets/summarize-extension.png +0 -0
  175. package/docs/assets/youtube-slides.png +0 -0
  176. package/docs/cache.md +29 -3
  177. package/docs/chrome-extension.md +61 -11
  178. package/docs/config.md +50 -2
  179. package/docs/extract-only.md +8 -0
  180. package/docs/index.html +205 -0
  181. package/docs/index.md +25 -0
  182. package/docs/llm.md +11 -1
  183. package/docs/manual-tests.md +2 -0
  184. package/docs/media.md +3 -0
  185. package/docs/nvidia-onnx-transcription.md +55 -0
  186. package/docs/site/assets/site.css +399 -228
  187. package/docs/site/assets/summarize-cli.png +0 -0
  188. package/docs/site/assets/summarize-extension.png +0 -0
  189. package/docs/site/docs/chrome-extension.html +89 -0
  190. package/docs/site/docs/config.html +1 -0
  191. package/docs/site/docs/extract-only.html +1 -0
  192. package/docs/site/docs/firecrawl.html +1 -0
  193. package/docs/site/docs/index.html +5 -0
  194. package/docs/site/docs/llm.html +1 -0
  195. package/docs/site/docs/openai.html +1 -0
  196. package/docs/site/docs/website.html +1 -0
  197. package/docs/site/docs/youtube.html +1 -0
  198. package/docs/site/index.html +148 -84
  199. package/docs/slides.md +74 -0
  200. package/docs/timestamps.md +103 -0
  201. package/docs/website.md +12 -0
  202. package/docs/youtube.md +16 -0
  203. package/package.json +16 -15
@@ -0,0 +1,70 @@
1
+ import { convertToMarkdownWithMarkitdown } from '../../../markitdown.js';
2
+ import { formatBytes } from '../../../tty/format.js';
3
+ import { getFileBytesFromAttachment, getTextContentFromAttachment, shouldMarkitdownConvertMediaType, } from '../../attachments.js';
4
+ import { MAX_TEXT_BYTES_DEFAULT } from '../../constants.js';
5
+ import { hasUvxCli } from '../../env.js';
6
+ import { withUvxTip } from '../../tips.js';
7
+ const baseDiagnostics = {
8
+ strategy: 'html',
9
+ firecrawl: { used: false },
10
+ markdown: { used: false, provider: null },
11
+ transcript: { textProvided: false, provider: null },
12
+ };
13
+ export async function extractAssetContent({ ctx, attachment, }) {
14
+ const textContent = getTextContentFromAttachment(attachment);
15
+ if (textContent) {
16
+ if (textContent.bytes > MAX_TEXT_BYTES_DEFAULT) {
17
+ throw new Error(`Text file too large (${formatBytes(textContent.bytes)}). Limit is ${formatBytes(MAX_TEXT_BYTES_DEFAULT)}.`);
18
+ }
19
+ return {
20
+ content: textContent.content,
21
+ diagnostics: baseDiagnostics,
22
+ };
23
+ }
24
+ if (attachment.kind === 'image') {
25
+ const name = attachment.filename ?? 'image';
26
+ throw new Error(`No extractable text found in ${name} (${attachment.mediaType}).`);
27
+ }
28
+ const fileBytes = getFileBytesFromAttachment(attachment);
29
+ if (!fileBytes) {
30
+ throw new Error('Internal error: missing file bytes for extraction');
31
+ }
32
+ if (ctx.preprocessMode === 'off') {
33
+ throw new Error(`This build does not support extracting binary files (${attachment.mediaType}). Enable preprocessing (e.g. --preprocess auto) and install uvx/markitdown.`);
34
+ }
35
+ if (!shouldMarkitdownConvertMediaType(attachment.mediaType)) {
36
+ const name = attachment.filename ?? 'file';
37
+ throw new Error(`Unsupported file type: ${name} (${attachment.mediaType})\n` +
38
+ `This build can only extract text-like files. Convert this file to text first.`);
39
+ }
40
+ if (!hasUvxCli(ctx.env)) {
41
+ throw withUvxTip(new Error(`Missing uvx/markitdown for preprocessing ${attachment.mediaType}.`), ctx.env);
42
+ }
43
+ let markdown;
44
+ try {
45
+ markdown = await convertToMarkdownWithMarkitdown({
46
+ bytes: fileBytes,
47
+ filenameHint: attachment.filename,
48
+ mediaTypeHint: attachment.mediaType,
49
+ uvxCommand: ctx.envForRun.UVX_PATH,
50
+ timeoutMs: ctx.timeoutMs,
51
+ env: ctx.env,
52
+ execFileImpl: ctx.execFileImpl,
53
+ });
54
+ }
55
+ catch (error) {
56
+ const message = error instanceof Error ? error.message : String(error);
57
+ throw new Error(`Failed to preprocess ${attachment.mediaType} with markitdown: ${message}.`);
58
+ }
59
+ if (Buffer.byteLength(markdown, 'utf8') > MAX_TEXT_BYTES_DEFAULT) {
60
+ throw new Error(`Preprocessed Markdown too large (${formatBytes(Buffer.byteLength(markdown, 'utf8'))}). Limit is ${formatBytes(MAX_TEXT_BYTES_DEFAULT)}.`);
61
+ }
62
+ return {
63
+ content: markdown,
64
+ diagnostics: {
65
+ ...baseDiagnostics,
66
+ markdown: { used: true, provider: null, notes: 'markitdown' },
67
+ },
68
+ };
69
+ }
70
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../../../../../src/run/flows/asset/extract.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,108 @@
1
1
  import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { isDirectMediaUrl } from '@steipete/summarize-core/content/url';
2
4
  import { classifyUrl, loadLocalAsset, loadRemoteAsset, } from '../../../content/asset.js';
3
5
  import { formatBytes } from '../../../tty/format.js';
4
6
  import { startOscProgress } from '../../../tty/osc-progress.js';
5
7
  import { startSpinner } from '../../../tty/spinner.js';
8
+ import { createThemeRenderer, resolveThemeNameFromSources, resolveTrueColor, } from '../../../tty/theme.js';
6
9
  import { assertAssetMediaTypeSupported } from '../../attachments.js';
10
+ /**
11
+ * Check if a media type should route through transcription.
12
+ */
13
+ function isTranscribableMediaType(mediaType) {
14
+ const normalized = mediaType.toLowerCase();
15
+ return normalized.startsWith('audio/') || normalized.startsWith('video/');
16
+ }
17
+ const TRANSCRIBABLE_EXTENSIONS = new Set([
18
+ // Audio
19
+ '.mp3',
20
+ '.wav',
21
+ '.m4a',
22
+ '.aac',
23
+ '.ogg',
24
+ '.flac',
25
+ '.wma',
26
+ '.aiff',
27
+ '.opus',
28
+ // Video
29
+ '.mp4',
30
+ '.mkv',
31
+ '.avi',
32
+ '.mov',
33
+ '.wmv',
34
+ '.flv',
35
+ '.webm',
36
+ '.m4v',
37
+ '.mpeg',
38
+ '.mpg',
39
+ ]);
40
+ const createProgressTheme = (envForRun, enabled) => {
41
+ const env = envForRun ?? {};
42
+ return createThemeRenderer({
43
+ themeName: resolveThemeNameFromSources({ env: env.SUMMARIZE_THEME }),
44
+ enabled,
45
+ trueColor: resolveTrueColor(env),
46
+ });
47
+ };
48
+ const renderStatus = (theme, label, detail = '…') => `${theme.label(label)}${theme.dim(detail)}`;
49
+ const renderStatusWithMeta = (theme, label, meta, suffix = '…') => `${theme.label(label)} ${meta}${theme.dim(suffix)}`;
50
+ const renderModelSuffix = (theme, modelId) => `${theme.dim(' (model: ')}${theme.accent(modelId)}${theme.dim(')')}`;
51
+ function normalizePathForExtension(value) {
52
+ try {
53
+ return new URL(value).pathname;
54
+ }
55
+ catch {
56
+ return value.split(/[?#]/, 1)[0];
57
+ }
58
+ }
59
+ /**
60
+ * Check if a file extension indicates transcribable media.
61
+ * Used to route large audio/video files directly to the media handler
62
+ * which has a higher size limit (2GB vs 50MB).
63
+ */
64
+ function isTranscribableExtension(filePath) {
65
+ if (isDirectMediaUrl(filePath))
66
+ return true;
67
+ const ext = path.extname(normalizePathForExtension(filePath)).toLowerCase();
68
+ return TRANSCRIBABLE_EXTENSIONS.has(ext);
69
+ }
70
+ function formatTranscriptionMeta({ filename, sizeLabel, dim, }) {
71
+ const details = sizeLabel ? `${sizeLabel}` : '';
72
+ return details ? `${filename} ${dim('(')}${details}${dim(')')}` : filename;
73
+ }
74
+ function setTranscribingSpinnerText({ spinner, theme, meta, modelId, }) {
75
+ const modelLabel = modelId ? renderModelSuffix(theme, modelId) : '';
76
+ spinner.setText(renderStatusWithMeta(theme, 'Transcribing', `${meta}${modelLabel}`));
77
+ }
78
+ async function runMediaTranscription({ ctx, sourceKind, sourceLabel, filename, sizeLabel, spinner, }) {
79
+ const theme = createProgressTheme(ctx.envForRun, ctx.progressEnabled);
80
+ const dim = (value) => theme.dim(value);
81
+ const meta = formatTranscriptionMeta({ filename, sizeLabel, dim });
82
+ if (ctx.progressEnabled) {
83
+ setTranscribingSpinnerText({ spinner, theme, meta });
84
+ }
85
+ await ctx.summarizeMediaFile?.({
86
+ sourceKind,
87
+ sourceLabel,
88
+ attachment: {
89
+ kind: 'file',
90
+ filename,
91
+ mediaType: 'audio/mpeg', // Will be detected properly by summarizeMediaFile
92
+ bytes: new Uint8Array(0), // Placeholder - summarizeMediaFile reads from path directly
93
+ },
94
+ onModelChosen: (modelId) => {
95
+ if (!ctx.progressEnabled)
96
+ return;
97
+ setTranscribingSpinnerText({ spinner, theme, meta, modelId });
98
+ },
99
+ });
100
+ }
7
101
  export async function handleFileInput(ctx, inputTarget) {
8
102
  if (inputTarget.kind !== 'file')
9
103
  return false;
10
104
  let sizeLabel = null;
105
+ const theme = createProgressTheme(ctx.envForRun, ctx.progressEnabled);
11
106
  try {
12
107
  const stat = await fs.stat(inputTarget.filePath);
13
108
  if (stat.isFile()) {
@@ -25,9 +120,10 @@ export async function handleFileInput(ctx, inputTarget) {
25
120
  write: (data) => ctx.stderr.write(data),
26
121
  });
27
122
  const spinner = startSpinner({
28
- text: sizeLabel ? `Loading file (${sizeLabel})…` : 'Loading file…',
123
+ text: renderStatus(theme, 'Loading file', sizeLabel ? ` (${sizeLabel})…` : '…'),
29
124
  enabled: ctx.progressEnabled,
30
125
  stream: ctx.stderr,
126
+ color: theme.palette.spinner,
31
127
  });
32
128
  let stopped = false;
33
129
  const stopProgress = () => {
@@ -37,20 +133,41 @@ export async function handleFileInput(ctx, inputTarget) {
37
133
  spinner.stopAndClear();
38
134
  stopOscProgress();
39
135
  };
40
- const clearProgressLine = () => {
41
- stopProgress();
136
+ const pauseProgressLine = () => {
137
+ spinner.pause();
138
+ return () => spinner.resume();
42
139
  };
43
- ctx.setClearProgressBeforeStdout(clearProgressLine);
140
+ ctx.setClearProgressBeforeStdout(pauseProgressLine);
44
141
  try {
142
+ // Check if file looks like transcribable media by extension.
143
+ // If so, route directly to summarizeMediaFile which has a higher size limit (2GB).
144
+ // This avoids the 50MB limit in loadLocalAsset for audio/video files.
145
+ if (isTranscribableExtension(inputTarget.filePath) && ctx.summarizeMediaFile) {
146
+ const filename = path.basename(inputTarget.filePath);
147
+ await runMediaTranscription({
148
+ ctx,
149
+ sourceKind: 'file',
150
+ sourceLabel: inputTarget.filePath,
151
+ filename,
152
+ sizeLabel,
153
+ spinner,
154
+ });
155
+ return true;
156
+ }
45
157
  const loaded = await loadLocalAsset({ filePath: inputTarget.filePath });
46
158
  assertAssetMediaTypeSupported({ attachment: loaded.attachment, sizeLabel });
159
+ const isTranscribable = isTranscribableMediaType(loaded.attachment.mediaType);
160
+ const handler = isTranscribable && ctx.summarizeMediaFile ? ctx.summarizeMediaFile : ctx.summarizeAsset;
161
+ const dim = (value) => theme.dim(value);
47
162
  if (ctx.progressEnabled) {
48
163
  const mt = loaded.attachment.mediaType;
49
164
  const name = loaded.attachment.filename;
50
165
  const details = sizeLabel ? `${mt}, ${sizeLabel}` : mt;
51
- spinner.setText(name ? `Summarizing ${name} (${details})…` : `Summarizing ${details}…`);
166
+ const action = isTranscribable ? 'Transcribing' : 'Summarizing';
167
+ const meta = name ? `${name} ${dim('(')}${details}${dim(')')}` : details;
168
+ spinner.setText(renderStatusWithMeta(theme, action, meta));
52
169
  }
53
- await ctx.summarizeAsset({
170
+ await handler({
54
171
  sourceKind: 'file',
55
172
  sourceLabel: loaded.sourceLabel,
56
173
  attachment: loaded.attachment,
@@ -60,24 +177,79 @@ export async function handleFileInput(ctx, inputTarget) {
60
177
  const mt = loaded.attachment.mediaType;
61
178
  const name = loaded.attachment.filename;
62
179
  const details = sizeLabel ? `${mt}, ${sizeLabel}` : mt;
63
- spinner.setText(name
64
- ? `Summarizing ${name} (${details}, model: ${modelId})…`
65
- : `Summarizing ${details} (model: ${modelId})…`);
180
+ const meta = name ? `${name} ${dim('(')}${details}${dim(')')}` : details;
181
+ const modelLabel = renderModelSuffix(theme, modelId);
182
+ spinner.setText(renderStatusWithMeta(theme, 'Summarizing', `${meta}${modelLabel}`));
66
183
  },
67
184
  });
68
185
  return true;
69
186
  }
70
187
  finally {
71
- ctx.clearProgressIfCurrent(clearProgressLine);
188
+ ctx.clearProgressIfCurrent(pauseProgressLine);
72
189
  stopProgress();
73
190
  }
74
191
  }
75
- export async function handleUrlAsset(ctx, url, isYoutubeUrl) {
192
+ export async function withUrlAsset(ctx, url, isYoutubeUrl, handler) {
76
193
  if (!url || isYoutubeUrl)
77
194
  return false;
195
+ // For remote media URLs (by extension), route directly to summarizeMediaFile.
196
+ // This avoids the 50MB limit in loadRemoteAsset - yt-dlp handles streaming download.
197
+ if (isTranscribableExtension(url) && ctx.summarizeMediaFile) {
198
+ const theme = createProgressTheme(ctx.envForRun, ctx.progressEnabled);
199
+ const filename = (() => {
200
+ try {
201
+ return path.basename(new URL(url).pathname) || 'media';
202
+ }
203
+ catch {
204
+ return 'media';
205
+ }
206
+ })();
207
+ const stopOscProgress = startOscProgress({
208
+ label: 'Transcribing media',
209
+ indeterminate: true,
210
+ env: ctx.env,
211
+ isTty: ctx.progressEnabled,
212
+ write: (data) => ctx.stderr.write(data),
213
+ });
214
+ const spinner = startSpinner({
215
+ text: renderStatusWithMeta(theme, 'Transcribing', filename),
216
+ enabled: ctx.progressEnabled,
217
+ stream: ctx.stderr,
218
+ color: theme.palette.spinner,
219
+ });
220
+ let stopped = false;
221
+ const stopProgress = () => {
222
+ if (stopped)
223
+ return;
224
+ stopped = true;
225
+ spinner.stopAndClear();
226
+ stopOscProgress();
227
+ };
228
+ const pauseProgressLine = () => {
229
+ spinner.pause();
230
+ return () => spinner.resume();
231
+ };
232
+ ctx.setClearProgressBeforeStdout(pauseProgressLine);
233
+ try {
234
+ await runMediaTranscription({
235
+ ctx,
236
+ sourceKind: 'asset-url',
237
+ sourceLabel: url,
238
+ filename,
239
+ sizeLabel: null,
240
+ spinner,
241
+ });
242
+ return true;
243
+ }
244
+ finally {
245
+ ctx.clearProgressIfCurrent(pauseProgressLine);
246
+ stopProgress();
247
+ }
248
+ }
78
249
  const kind = await classifyUrl({ url, fetchImpl: ctx.trackedFetch, timeoutMs: ctx.timeoutMs });
79
250
  if (kind.kind !== 'asset')
80
251
  return false;
252
+ const theme = createProgressTheme(ctx.envForRun, ctx.progressEnabled);
81
253
  const stopOscProgress = startOscProgress({
82
254
  label: 'Downloading file',
83
255
  indeterminate: true,
@@ -86,9 +258,10 @@ export async function handleUrlAsset(ctx, url, isYoutubeUrl) {
86
258
  write: (data) => ctx.stderr.write(data),
87
259
  });
88
260
  const spinner = startSpinner({
89
- text: 'Downloading file',
261
+ text: renderStatus(theme, 'Downloading file'),
90
262
  enabled: ctx.progressEnabled,
91
263
  stream: ctx.stderr,
264
+ color: theme.palette.spinner,
92
265
  });
93
266
  let stopped = false;
94
267
  const stopProgress = () => {
@@ -98,10 +271,11 @@ export async function handleUrlAsset(ctx, url, isYoutubeUrl) {
98
271
  spinner.stopAndClear();
99
272
  stopOscProgress();
100
273
  };
101
- const clearProgressLine = () => {
102
- stopProgress();
274
+ const pauseProgressLine = () => {
275
+ spinner.pause();
276
+ return () => spinner.resume();
103
277
  };
104
- ctx.setClearProgressBeforeStdout(clearProgressLine);
278
+ ctx.setClearProgressBeforeStdout(pauseProgressLine);
105
279
  try {
106
280
  const loaded = await (async () => {
107
281
  try {
@@ -117,8 +291,22 @@ export async function handleUrlAsset(ctx, url, isYoutubeUrl) {
117
291
  if (!loaded)
118
292
  return false;
119
293
  assertAssetMediaTypeSupported({ attachment: loaded.attachment, sizeLabel: null });
120
- if (ctx.progressEnabled)
121
- spinner.setText('Summarizing…');
294
+ await handler({ loaded, spinner, clearProgressLine: pauseProgressLine });
295
+ return true;
296
+ }
297
+ finally {
298
+ ctx.clearProgressIfCurrent(pauseProgressLine);
299
+ stopProgress();
300
+ }
301
+ }
302
+ export async function handleUrlAsset(ctx, url, isYoutubeUrl) {
303
+ // Media URL handling is now in withUrlAsset
304
+ return withUrlAsset(ctx, url, isYoutubeUrl, async ({ loaded, spinner }) => {
305
+ const theme = createProgressTheme(ctx.envForRun, ctx.progressEnabled);
306
+ const dim = (value) => theme.dim(value);
307
+ if (ctx.progressEnabled) {
308
+ spinner.setText(renderStatusWithMeta(theme, 'Summarizing', dim('file')));
309
+ }
122
310
  await ctx.summarizeAsset({
123
311
  sourceKind: 'asset-url',
124
312
  sourceLabel: loaded.sourceLabel,
@@ -126,14 +314,10 @@ export async function handleUrlAsset(ctx, url, isYoutubeUrl) {
126
314
  onModelChosen: (modelId) => {
127
315
  if (!ctx.progressEnabled)
128
316
  return;
129
- spinner.setText(`Summarizing (model: ${modelId})…`);
317
+ const modelLabel = renderModelSuffix(theme, modelId);
318
+ spinner.setText(renderStatusWithMeta(theme, 'Summarizing', `${dim('file')}${modelLabel}`));
130
319
  },
131
320
  });
132
- return true;
133
- }
134
- finally {
135
- ctx.clearProgressIfCurrent(clearProgressLine);
136
- stopProgress();
137
- }
321
+ });
138
322
  }
139
323
  //# sourceMappingURL=input.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../../../src/run/flows/asset/input.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../../../src/run/flows/asset/input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export const MAX_LOCAL_MEDIA_BYTES = 2 * 1024 * 1024 * 1024;
2
+ export const MAX_LOCAL_MEDIA_LABEL = '2 GB';
3
+ //# sourceMappingURL=media-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-policy.js","sourceRoot":"","sources":["../../../../../src/run/flows/asset/media-policy.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAC3D,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAA"}
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Media file transcription handler for local audio/video files.
3
+ * Phase 2: Transcript provider integration
4
+ * Phase 2.2: Local file path handling for transcript caching
5
+ */
6
+ import { statSync } from 'node:fs';
7
+ import { isAbsolute, resolve as resolvePath } from 'node:path';
8
+ import { pathToFileURL } from 'node:url';
9
+ import { createLinkPreviewClient } from '../../../content/index.js';
10
+ import { createFirecrawlScraper } from '../../../firecrawl.js';
11
+ import { readTweetWithBird } from '../../bird.js';
12
+ import { resolveTwitterCookies } from '../../cookies/twitter.js';
13
+ import { hasBirdCli } from '../../env.js';
14
+ import { writeVerbose } from '../../logging.js';
15
+ import { MAX_LOCAL_MEDIA_BYTES, MAX_LOCAL_MEDIA_LABEL } from './media-policy.js';
16
+ /**
17
+ * Get file modification time for cache invalidation support.
18
+ * Returns null if the path is not a local file or file doesn't exist.
19
+ */
20
+ function getFileModificationTime(filePath) {
21
+ // Only support absolute local file paths
22
+ if (!isAbsolute(filePath)) {
23
+ return null;
24
+ }
25
+ try {
26
+ const stats = statSync(filePath);
27
+ return stats.mtimeMs ?? null;
28
+ }
29
+ catch {
30
+ // File doesn't exist or can't be accessed
31
+ return null;
32
+ }
33
+ }
34
+ /**
35
+ * Handler for local audio/video files.
36
+ *
37
+ * Phase 2 Implementation:
38
+ * 1. Validates transcription provider availability
39
+ * 2. Creates LinkPreviewClient with necessary dependencies
40
+ * 3. Calls client.fetchLinkContent to trigger transcription
41
+ * 4. Converts transcript text to AssetAttachment
42
+ * 5. Calls summarizeAsset with the transcript
43
+ *
44
+ * Phase 2.2 Enhancement:
45
+ * - Captures file modification time for cache invalidation
46
+ * - Passes fileMtime to transcript cache for local file support
47
+ */
48
+ export async function summarizeMediaFile(ctx, args) {
49
+ // Check if basic transcription setup is available
50
+ const openaiKey = ctx.env.OPENAI_API_KEY;
51
+ const falKey = ctx.env.FAL_KEY;
52
+ // Helper to check if a binary is available on PATH
53
+ const isBinaryAvailable = async (binary) => {
54
+ const { spawn } = await import('node:child_process');
55
+ return new Promise((resolve) => {
56
+ const proc = spawn(binary, ['--help'], {
57
+ stdio: ['ignore', 'ignore', 'ignore'],
58
+ env: ctx.env,
59
+ });
60
+ proc.on('error', () => resolve(false));
61
+ proc.on('close', (code) => resolve(code === 0));
62
+ });
63
+ };
64
+ // Check for yt-dlp: either via env var or on PATH
65
+ const ytDlpPath = ctx.env.YT_DLP_PATH || ((await isBinaryAvailable('yt-dlp')) ? 'yt-dlp' : null);
66
+ // Check for whisper.cpp: either via env var or by checking if whisper-cli is on PATH
67
+ const hasLocalWhisper = ctx.env.SUMMARIZE_WHISPER_CPP_BINARY
68
+ ? true
69
+ : await isBinaryAvailable('whisper-cli');
70
+ const hasAnyTranscriptionProvider = openaiKey || falKey || hasLocalWhisper;
71
+ if (!hasAnyTranscriptionProvider) {
72
+ throw new Error(`Media file transcription requires one of the following:
73
+
74
+ 1. OpenAI Whisper:
75
+ Set OPENAI_API_KEY=sk-...
76
+
77
+ 2. FAL Whisper:
78
+ Set FAL_KEY=...
79
+
80
+ 3. Local whisper.cpp (recommended, free):
81
+ brew install ggerganov/ggerganov/whisper-cpp
82
+ Ensure whisper-cli is on your PATH (or set SUMMARIZE_WHISPER_CPP_BINARY)
83
+
84
+ See: https://github.com/openai/whisper for setup details`);
85
+ }
86
+ const isHttpUrl = (value) => {
87
+ try {
88
+ const parsed = new URL(value);
89
+ return parsed.protocol === 'http:' || parsed.protocol === 'https:';
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ };
95
+ // For URLs, skip local file validation - yt-dlp will handle the download
96
+ const isUrl = args.sourceKind === 'asset-url' || isHttpUrl(args.sourceLabel);
97
+ let absolutePath;
98
+ let fileMtime = null;
99
+ if (isUrl) {
100
+ // For URLs, use the URL directly - no local path resolution needed
101
+ absolutePath = args.sourceLabel;
102
+ }
103
+ else {
104
+ absolutePath = resolvePath(args.sourceLabel);
105
+ // Get file modification time for cache invalidation (after path resolution)
106
+ fileMtime = getFileModificationTime(absolutePath);
107
+ // Validate file size before attempting transcription
108
+ try {
109
+ const stats = statSync(absolutePath);
110
+ const fileSizeBytes = stats.size;
111
+ const maxSizeBytes = MAX_LOCAL_MEDIA_BYTES;
112
+ if (fileSizeBytes === 0) {
113
+ throw new Error('Media file is empty (0 bytes). Please provide a valid audio/video file.');
114
+ }
115
+ if (fileSizeBytes > maxSizeBytes) {
116
+ const fileSizeMB = Math.round(fileSizeBytes / (1024 * 1024));
117
+ throw new Error(`Media file is too large (${fileSizeMB} MB). Maximum supported size is ${MAX_LOCAL_MEDIA_LABEL}.`);
118
+ }
119
+ }
120
+ catch (error) {
121
+ if (error instanceof Error &&
122
+ (error.message.includes('empty') || error.message.includes('large'))) {
123
+ throw error; // Re-throw our validation errors
124
+ }
125
+ // For other statSync errors (e.g., file not found), let them bubble up
126
+ throw new Error(`Unable to access media file: ${error instanceof Error ? error.message : 'Unknown error'}`);
127
+ }
128
+ }
129
+ const cacheMode = ctx.cache.mode;
130
+ // Create Firecrawl scraper if configured
131
+ const firecrawlScraper = ctx.apiStatus.firecrawlConfigured && ctx.env.FIRECRAWL_API_KEY
132
+ ? createFirecrawlScraper({
133
+ apiKey: ctx.env.FIRECRAWL_API_KEY,
134
+ fetchImpl: ctx.trackedFetch,
135
+ })
136
+ : null;
137
+ // Create reader for bird tweets (for completeness, not used for media)
138
+ const readTweetWithBirdClient = hasBirdCli(ctx.env)
139
+ ? ({ url, timeoutMs }) => readTweetWithBird({ url, timeoutMs, env: ctx.env })
140
+ : null;
141
+ // Create link preview client for transcript resolution
142
+ const transcriptCache = cacheMode === 'default' ? (ctx.cache.store?.transcriptCache ?? null) : null;
143
+ const client = createLinkPreviewClient({
144
+ apifyApiToken: ctx.apiStatus.apifyToken,
145
+ ytDlpPath: ytDlpPath,
146
+ falApiKey: falKey,
147
+ openaiApiKey: openaiKey,
148
+ scrapeWithFirecrawl: firecrawlScraper,
149
+ convertHtmlToMarkdown: null, // Not needed for media
150
+ readTweetWithBird: readTweetWithBirdClient,
151
+ resolveTwitterCookies: async (_args) => {
152
+ const res = await resolveTwitterCookies({ env: ctx.env });
153
+ return {
154
+ cookiesFromBrowser: res.cookies.cookiesFromBrowser,
155
+ source: res.cookies.source,
156
+ warnings: res.warnings,
157
+ };
158
+ },
159
+ fetch: ctx.trackedFetch,
160
+ transcriptCache,
161
+ mediaCache: ctx.mediaCache ?? null,
162
+ onProgress: (_event) => {
163
+ // Could update progress here if needed
164
+ // For now, silent transcription
165
+ },
166
+ });
167
+ try {
168
+ // For URLs, use directly. For local files, convert to file:// URL.
169
+ // yt-dlp can handle both http(s) URLs and file:// URLs.
170
+ const fileUrl = isUrl ? absolutePath : pathToFileURL(absolutePath).href;
171
+ // Fetch the link content (will trigger transcription for media)
172
+ // Using file:// URL ensures the provider chain can handle local files properly
173
+ const extracted = await client.fetchLinkContent(fileUrl, {
174
+ timeoutMs: ctx.timeoutMs,
175
+ cacheMode,
176
+ youtubeTranscript: 'auto', // Not used for local files, but set for completeness
177
+ mediaTranscript: 'prefer', // Prefer transcription for media files
178
+ transcriptTimestamps: false,
179
+ fileMtime, // Include file modification time for cache invalidation
180
+ });
181
+ // Check if we got a transcript
182
+ if (!extracted.content || extracted.content.trim().length === 0) {
183
+ throw new Error(`Failed to transcribe media file. Check that:
184
+ - Audio/video format is supported (MP3, WAV, M4A, OGG, FLAC, MP4, MOV, WEBM)
185
+ - Transcription provider is configured
186
+ - File is readable
187
+ - Media file is not corrupted`);
188
+ }
189
+ // Create a text-based attachment from the transcript
190
+ const filename = args.sourceLabel.split('/').pop() ?? 'media';
191
+ const transcriptAttachment = {
192
+ mediaType: 'text/plain',
193
+ filename: `${filename}.transcript.txt`,
194
+ kind: 'file',
195
+ bytes: new TextEncoder().encode(extracted.content),
196
+ };
197
+ writeVerbose(ctx.stderr, ctx.verbose, `transcription done media file: ${extracted.diagnostics?.transcript?.provider ?? 'unknown'}`, false, ctx.envForRun);
198
+ // If extract mode, output the transcript directly without LLM summarization
199
+ if (ctx.extractMode) {
200
+ ctx.clearProgressForStdout();
201
+ ctx.stdout.write(extracted.content);
202
+ if (!extracted.content.endsWith('\n')) {
203
+ ctx.stdout.write('\n');
204
+ }
205
+ return;
206
+ }
207
+ // Call the standard asset summarization with the transcript
208
+ const { summarizeAsset } = await import('./summary.js');
209
+ await summarizeAsset(ctx, {
210
+ sourceKind: 'file',
211
+ sourceLabel: `${args.sourceLabel} (transcript)`,
212
+ attachment: transcriptAttachment,
213
+ onModelChosen: args.onModelChosen,
214
+ });
215
+ }
216
+ catch (error) {
217
+ // Re-throw with better context for transcription errors
218
+ if (error instanceof Error && error.message.includes('transcribe')) {
219
+ throw error;
220
+ }
221
+ throw new Error(`Transcription failed: ${error instanceof Error ? error.message : String(error)}`);
222
+ }
223
+ }
224
+ //# sourceMappingURL=media.js.map