@steipete/summarize 0.7.1 → 0.8.1

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 (151) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +53 -2
  3. package/dist/cli.js +3 -0
  4. package/dist/esm/cache.js +353 -0
  5. package/dist/esm/cache.js.map +1 -0
  6. package/dist/esm/config.js +78 -1
  7. package/dist/esm/config.js.map +1 -1
  8. package/dist/esm/content/asset.js +11 -17
  9. package/dist/esm/content/asset.js.map +1 -1
  10. package/dist/esm/daemon/auto-mode.js +8 -0
  11. package/dist/esm/daemon/auto-mode.js.map +1 -0
  12. package/dist/esm/daemon/cli.js +284 -0
  13. package/dist/esm/daemon/cli.js.map +1 -0
  14. package/dist/esm/daemon/config.js +82 -0
  15. package/dist/esm/daemon/config.js.map +1 -0
  16. package/dist/esm/daemon/constants.js +8 -0
  17. package/dist/esm/daemon/constants.js.map +1 -0
  18. package/dist/esm/daemon/env-merge.js +4 -0
  19. package/dist/esm/daemon/env-merge.js.map +1 -0
  20. package/dist/esm/daemon/env-snapshot.js +43 -0
  21. package/dist/esm/daemon/env-snapshot.js.map +1 -0
  22. package/dist/esm/daemon/flow-context.js +265 -0
  23. package/dist/esm/daemon/flow-context.js.map +1 -0
  24. package/dist/esm/daemon/launchd.js +149 -0
  25. package/dist/esm/daemon/launchd.js.map +1 -0
  26. package/dist/esm/daemon/meta.js +35 -0
  27. package/dist/esm/daemon/meta.js.map +1 -0
  28. package/dist/esm/daemon/models.js +175 -0
  29. package/dist/esm/daemon/models.js.map +1 -0
  30. package/dist/esm/daemon/request-settings.js +91 -0
  31. package/dist/esm/daemon/request-settings.js.map +1 -0
  32. package/dist/esm/daemon/schtasks.js +108 -0
  33. package/dist/esm/daemon/schtasks.js.map +1 -0
  34. package/dist/esm/daemon/server.js +399 -0
  35. package/dist/esm/daemon/server.js.map +1 -0
  36. package/dist/esm/daemon/summarize-progress.js +57 -0
  37. package/dist/esm/daemon/summarize-progress.js.map +1 -0
  38. package/dist/esm/daemon/summarize.js +263 -0
  39. package/dist/esm/daemon/summarize.js.map +1 -0
  40. package/dist/esm/daemon/systemd.js +117 -0
  41. package/dist/esm/daemon/systemd.js.map +1 -0
  42. package/dist/esm/flags.js +3 -1
  43. package/dist/esm/flags.js.map +1 -1
  44. package/dist/esm/llm/generate-text.js +445 -154
  45. package/dist/esm/llm/generate-text.js.map +1 -1
  46. package/dist/esm/llm/html-to-markdown.js +4 -1
  47. package/dist/esm/llm/html-to-markdown.js.map +1 -1
  48. package/dist/esm/llm/prompt.js +14 -0
  49. package/dist/esm/llm/prompt.js.map +1 -0
  50. package/dist/esm/llm/transcript-to-markdown.js +57 -0
  51. package/dist/esm/llm/transcript-to-markdown.js.map +1 -0
  52. package/dist/esm/model-spec.js +2 -2
  53. package/dist/esm/model-spec.js.map +1 -1
  54. package/dist/esm/run/attachments.js +10 -42
  55. package/dist/esm/run/attachments.js.map +1 -1
  56. package/dist/esm/run/cache-state.js +48 -0
  57. package/dist/esm/run/cache-state.js.map +1 -0
  58. package/dist/esm/run/cli-preflight.js +15 -1
  59. package/dist/esm/run/cli-preflight.js.map +1 -1
  60. package/dist/esm/run/cookies/twitter.js +224 -0
  61. package/dist/esm/run/cookies/twitter.js.map +1 -0
  62. package/dist/esm/run/fetch-with-timeout.js +1 -1
  63. package/dist/esm/run/fetch-with-timeout.js.map +1 -1
  64. package/dist/esm/run/finish-line.js +46 -17
  65. package/dist/esm/run/finish-line.js.map +1 -1
  66. package/dist/esm/run/flows/asset/input.js +2 -4
  67. package/dist/esm/run/flows/asset/input.js.map +1 -1
  68. package/dist/esm/run/flows/asset/preprocess.js +52 -72
  69. package/dist/esm/run/flows/asset/preprocess.js.map +1 -1
  70. package/dist/esm/run/flows/asset/summary.js +127 -47
  71. package/dist/esm/run/flows/asset/summary.js.map +1 -1
  72. package/dist/esm/run/flows/url/extract.js +6 -1
  73. package/dist/esm/run/flows/url/extract.js.map +1 -1
  74. package/dist/esm/run/flows/url/flow.js +166 -85
  75. package/dist/esm/run/flows/url/flow.js.map +1 -1
  76. package/dist/esm/run/flows/url/markdown.js +88 -46
  77. package/dist/esm/run/flows/url/markdown.js.map +1 -1
  78. package/dist/esm/run/flows/url/summary.js +263 -185
  79. package/dist/esm/run/flows/url/summary.js.map +1 -1
  80. package/dist/esm/run/help.js +33 -2
  81. package/dist/esm/run/help.js.map +1 -1
  82. package/dist/esm/run/run-env.js +36 -2
  83. package/dist/esm/run/run-env.js.map +1 -1
  84. package/dist/esm/run/runner.js +362 -227
  85. package/dist/esm/run/runner.js.map +1 -1
  86. package/dist/esm/run/summary-engine.js +21 -6
  87. package/dist/esm/run/summary-engine.js.map +1 -1
  88. package/dist/esm/run/summary-llm.js +4 -1
  89. package/dist/esm/run/summary-llm.js.map +1 -1
  90. package/dist/esm/tty/format.js +9 -0
  91. package/dist/esm/tty/format.js.map +1 -1
  92. package/dist/esm/version.js +1 -1
  93. package/dist/types/cache.d.ts +70 -0
  94. package/dist/types/config.d.ts +46 -0
  95. package/dist/types/content/asset.d.ts +4 -3
  96. package/dist/types/daemon/auto-mode.d.ts +8 -0
  97. package/dist/types/daemon/cli.d.ts +9 -0
  98. package/dist/types/daemon/config.d.ts +19 -0
  99. package/dist/types/daemon/constants.d.ts +7 -0
  100. package/dist/types/daemon/env-merge.d.ts +5 -0
  101. package/dist/types/daemon/env-snapshot.d.ts +4 -0
  102. package/dist/types/daemon/flow-context.d.ts +28 -0
  103. package/dist/types/daemon/launchd.d.ts +29 -0
  104. package/dist/types/daemon/meta.d.ts +12 -0
  105. package/dist/types/daemon/models.d.ts +27 -0
  106. package/dist/types/daemon/request-settings.d.ts +27 -0
  107. package/dist/types/daemon/schtasks.d.ts +16 -0
  108. package/dist/types/daemon/server.d.ts +12 -0
  109. package/dist/types/daemon/summarize-progress.d.ts +2 -0
  110. package/dist/types/daemon/summarize.d.ts +59 -0
  111. package/dist/types/daemon/systemd.d.ts +16 -0
  112. package/dist/types/flags.d.ts +1 -1
  113. package/dist/types/llm/generate-text.d.ts +11 -5
  114. package/dist/types/llm/html-to-markdown.d.ts +4 -1
  115. package/dist/types/llm/prompt.d.ts +9 -0
  116. package/dist/types/llm/transcript-to-markdown.d.ts +34 -0
  117. package/dist/types/run/attachments.d.ts +4 -10
  118. package/dist/types/run/cache-state.d.ts +12 -0
  119. package/dist/types/run/cli-preflight.d.ts +1 -0
  120. package/dist/types/run/cookies/twitter.d.ts +17 -0
  121. package/dist/types/run/finish-line.d.ts +31 -1
  122. package/dist/types/run/flows/asset/preprocess.d.ts +5 -2
  123. package/dist/types/run/flows/asset/summary.d.ts +11 -0
  124. package/dist/types/run/flows/url/markdown.d.ts +3 -0
  125. package/dist/types/run/flows/url/summary.d.ts +6 -3
  126. package/dist/types/run/flows/url/types.d.ts +52 -18
  127. package/dist/types/run/help.d.ts +1 -0
  128. package/dist/types/run/run-env.d.ts +6 -0
  129. package/dist/types/run/summary-engine.d.ts +8 -2
  130. package/dist/types/run/summary-llm.d.ts +6 -3
  131. package/dist/types/tty/format.d.ts +1 -0
  132. package/dist/types/version.d.ts +1 -1
  133. package/docs/README.md +5 -0
  134. package/docs/cache.md +72 -0
  135. package/docs/chrome-extension.md +180 -0
  136. package/docs/cli.md +6 -0
  137. package/docs/config.md +65 -1
  138. package/docs/extract-only.md +6 -0
  139. package/docs/firecrawl.md +6 -0
  140. package/docs/language.md +6 -0
  141. package/docs/llm.md +20 -0
  142. package/docs/manual-tests.md +6 -0
  143. package/docs/model-auto.md +6 -0
  144. package/docs/openai.md +6 -0
  145. package/docs/site/index.html +11 -1
  146. package/docs/smoketest.md +6 -0
  147. package/docs/website.md +6 -0
  148. package/docs/youtube.md +9 -2
  149. package/package.json +7 -10
  150. package/dist/cli.cjs +0 -80566
  151. package/dist/cli.cjs.map +0 -7
@@ -1,8 +1,12 @@
1
1
  import { execFile } from 'node:child_process';
2
+ import { readFile } from 'node:fs/promises';
2
3
  import { CommanderError } from 'commander';
4
+ import { clearCacheFiles, DEFAULT_CACHE_MAX_MB, resolveCachePath, } from '../cache.js';
5
+ import { loadSummarizeConfig } from '../config.js';
3
6
  import { parseDurationMs, parseExtractFormat, parseFirecrawlMode, parseLengthArg, parseMarkdownMode, parseMaxOutputTokensArg, parseMetricsMode, parsePreprocessMode, parseRetriesArg, parseStreamMode, parseYoutubeMode, } from '../flags.js';
4
7
  import { formatVersionLine } from '../version.js';
5
- import { handleHelpRequest, handleRefreshFreeRequest } from './cli-preflight.js';
8
+ import { createCacheStateFromConfig } from './cache-state.js';
9
+ import { handleDaemonCliRequest, handleHelpRequest, handleRefreshFreeRequest, } from './cli-preflight.js';
6
10
  import { parseCliProviderArg } from './env.js';
7
11
  import { handleFileInput, handleUrlAsset } from './flows/asset/input.js';
8
12
  import { summarizeAsset as summarizeAssetFlow } from './flows/asset/summary.js';
@@ -36,6 +40,15 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
36
40
  })) {
37
41
  return;
38
42
  }
43
+ if (await handleDaemonCliRequest({
44
+ normalizedArgv,
45
+ envForRun,
46
+ fetchImpl: fetch,
47
+ stdout,
48
+ stderr,
49
+ })) {
50
+ return;
51
+ }
39
52
  const execFileImpl = execFileOverride ?? execFile;
40
53
  const program = buildProgram();
41
54
  program.configureOutput({
@@ -61,6 +74,82 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
61
74
  stdout.write(`${formatVersionLine()}\n`);
62
75
  return;
63
76
  }
77
+ const promptArg = typeof program.opts().prompt === 'string' ? program.opts().prompt : null;
78
+ const promptFileArg = typeof program.opts().promptFile === 'string' ? program.opts().promptFile : null;
79
+ if (promptArg && promptFileArg) {
80
+ throw new Error('Use either --prompt or --prompt-file (not both).');
81
+ }
82
+ let promptOverride = null;
83
+ if (promptFileArg) {
84
+ let text;
85
+ try {
86
+ text = await readFile(promptFileArg, 'utf8');
87
+ }
88
+ catch (error) {
89
+ const message = error instanceof Error ? error.message : String(error);
90
+ throw new Error(`Failed to read --prompt-file ${promptFileArg}: ${message}`);
91
+ }
92
+ const trimmed = text.trim();
93
+ if (!trimmed) {
94
+ throw new Error(`Prompt file ${promptFileArg} is empty.`);
95
+ }
96
+ promptOverride = trimmed;
97
+ }
98
+ else if (promptArg) {
99
+ const trimmed = promptArg.trim();
100
+ if (!trimmed) {
101
+ throw new Error('Prompt must not be empty.');
102
+ }
103
+ promptOverride = trimmed;
104
+ }
105
+ const clearCacheFlag = normalizedArgv.includes('--clear-cache');
106
+ if (clearCacheFlag) {
107
+ const extraArgs = normalizedArgv.filter((arg) => arg !== '--clear-cache');
108
+ if (extraArgs.length > 0) {
109
+ throw new Error('--clear-cache must be used alone.');
110
+ }
111
+ const { config } = loadSummarizeConfig({ env: envForRun });
112
+ const cachePath = resolveCachePath({
113
+ env: envForRun,
114
+ cachePath: config?.cache?.path ?? null,
115
+ });
116
+ if (!cachePath) {
117
+ throw new Error('Unable to resolve cache path (missing HOME).');
118
+ }
119
+ clearCacheFiles(cachePath);
120
+ stdout.write('Cache cleared.\n');
121
+ return;
122
+ }
123
+ const cacheStatsFlag = normalizedArgv.includes('--cache-stats');
124
+ if (cacheStatsFlag) {
125
+ const extraArgs = normalizedArgv.filter((arg) => arg !== '--cache-stats');
126
+ if (extraArgs.length > 0) {
127
+ throw new Error('--cache-stats must be used alone.');
128
+ }
129
+ const { config } = loadSummarizeConfig({ env: envForRun });
130
+ const cachePath = resolveCachePath({
131
+ env: envForRun,
132
+ cachePath: config?.cache?.path ?? null,
133
+ });
134
+ if (!cachePath) {
135
+ throw new Error('Unable to resolve cache path (missing HOME).');
136
+ }
137
+ const cacheMaxMb = typeof config?.cache?.maxMb === 'number' ? config.cache.maxMb : DEFAULT_CACHE_MAX_MB;
138
+ const cacheMaxBytes = Math.max(0, cacheMaxMb) * 1024 * 1024;
139
+ const { readCacheStats } = await import('../cache.js');
140
+ const { formatBytes } = await import('../tty/format.js');
141
+ const stats = await readCacheStats(cachePath);
142
+ stdout.write(`Cache path: ${cachePath}\n`);
143
+ if (!stats) {
144
+ stdout.write('Cache is empty.\n');
145
+ return;
146
+ }
147
+ const sizeLabel = formatBytes(stats.sizeBytes);
148
+ const maxLabel = cacheMaxBytes > 0 ? formatBytes(cacheMaxBytes) : 'disabled';
149
+ stdout.write(`Size: ${sizeLabel} (max ${maxLabel})\n`);
150
+ stdout.write(`Entries: total=${stats.totalEntries} extract=${stats.counts.extract} summary=${stats.counts.summary} transcript=${stats.counts.transcript}\n`);
151
+ return;
152
+ }
64
153
  const cliFlagPresent = normalizedArgv.some((arg) => arg === '--cli' || arg.startsWith('--cli='));
65
154
  let cliProviderArgRaw = typeof program.opts().cli === 'string' ? program.opts().cli : null;
66
155
  const inputResolution = resolveRunInput({
@@ -84,6 +173,7 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
84
173
  arg === '--lang' ||
85
174
  arg.startsWith('--lang='));
86
175
  const retries = parseRetriesArg(program.opts().retries);
176
+ const noCacheFlag = program.opts().cache === false;
87
177
  const extractMode = Boolean(program.opts().extract) || Boolean(program.opts().extractOnly);
88
178
  const json = Boolean(program.opts().json);
89
179
  const streamMode = parseStreamMode(program.opts().stream);
@@ -138,238 +228,283 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
138
228
  cliFlagPresent,
139
229
  cliProviderArg,
140
230
  });
141
- const { apiKey, openrouterApiKey, openrouterConfigured, openaiTranscriptionKey, xaiApiKey, googleApiKey, anthropicApiKey, zaiApiKey, zaiBaseUrl, firecrawlApiKey, firecrawlConfigured, googleConfigured, anthropicConfigured, apifyToken, ytDlpPath, falApiKey, cliAvailability, envForAuto, } = resolveEnvState({ env, envForRun, configForCli });
142
- if (markdownModeExplicitlySet && format !== 'markdown') {
143
- throw new Error('--markdown-mode is only supported with --format md');
144
- }
145
- if (markdownModeExplicitlySet && inputTarget.kind !== 'url') {
146
- throw new Error('--markdown-mode is only supported for website URLs');
147
- }
148
- const metrics = createRunMetrics({
149
- env,
150
- fetchImpl: fetch,
151
- maxOutputTokensArg,
152
- });
153
- const { llmCalls, trackedFetch, buildReport, estimateCostUsd, getLiteLlmCatalog, resolveMaxOutputTokensForCall, resolveMaxInputTokensForCall, setTranscriptionCost, } = metrics;
154
- const { requestedModel, requestedModelInput, requestedModelLabel, isNamedModelSelection, wantsFreeNamedModel, configForModelSelection, isFallbackModel, } = resolveModelSelection({
155
- config,
156
- configForCli,
157
- configPath,
158
- envForRun,
159
- explicitModelArg,
160
- });
161
- const verboseColor = supportsColor(stderr, envForRun);
162
- const { streamingEnabled } = resolveStreamSettings({
163
- streamMode,
164
- stdout,
165
- json,
166
- extractMode,
167
- });
168
- if (extractMode && inputTarget.kind !== 'url') {
169
- throw new Error('--extract is only supported for website/YouTube URLs');
231
+ if (!promptOverride && typeof config?.prompt === 'string' && config.prompt.trim().length > 0) {
232
+ promptOverride = config.prompt.trim();
170
233
  }
171
- // Progress UI (spinner + OSC progress) is shown on stderr. Before writing to stdout (including
172
- // streaming output), we stop + clear progress via the progress gate to keep scrollback clean.
173
- const progressEnabled = isRichTty(stderr) && !verbose && !json;
174
- const progressGate = createProgressGate();
175
- const { clearProgressForStdout, setClearProgressBeforeStdout, clearProgressIfCurrent } = progressGate;
176
- const fixedModelSpec = requestedModel.kind === 'fixed' ? requestedModel : null;
177
- const desiredOutputTokens = resolveDesiredOutputTokens({ lengthArg, maxOutputTokensArg });
178
- const summaryEngine = createSummaryEngine({
179
- env,
234
+ const lengthInstruction = promptOverride && lengthExplicitlySet && lengthArg.kind === 'chars'
235
+ ? `Output is ${lengthArg.maxCharacters.toLocaleString()} characters.`
236
+ : null;
237
+ const languageInstruction = promptOverride && languageExplicitlySet && outputLanguage.kind === 'fixed'
238
+ ? `Output should be ${outputLanguage.label}.`
239
+ : null;
240
+ const transcriptNamespace = `yt:${youtubeMode}`;
241
+ const cacheState = await createCacheStateFromConfig({
180
242
  envForRun,
181
- stdout,
182
- stderr,
183
- execFileImpl,
184
- timeoutMs,
185
- retries,
186
- streamingEnabled,
187
- plain,
188
- verbose,
189
- verboseColor,
190
- openaiUseChatCompletions,
191
- cliConfigForRun: cliConfigForRun ?? null,
192
- cliAvailability,
193
- trackedFetch,
194
- resolveMaxOutputTokensForCall,
195
- resolveMaxInputTokensForCall,
196
- llmCalls,
197
- clearProgressForStdout,
198
- apiKeys: {
199
- xaiApiKey,
200
- openaiApiKey: apiKey,
201
- googleApiKey,
202
- anthropicApiKey,
203
- openrouterApiKey,
204
- },
205
- keyFlags: {
206
- googleConfigured,
207
- anthropicConfigured,
208
- openrouterConfigured,
209
- },
210
- zai: {
211
- apiKey: zaiApiKey,
212
- baseUrl: zaiBaseUrl,
213
- },
243
+ config,
244
+ noCacheFlag,
245
+ transcriptNamespace,
214
246
  });
215
- const writeViaFooter = (parts) => {
216
- if (json)
217
- return;
218
- if (extractMode)
247
+ try {
248
+ const { apiKey, openrouterApiKey, openrouterConfigured, openaiTranscriptionKey, xaiApiKey, googleApiKey, anthropicApiKey, zaiApiKey, zaiBaseUrl, providerBaseUrls, firecrawlApiKey, firecrawlConfigured, googleConfigured, anthropicConfigured, apifyToken, ytDlpPath, falApiKey, cliAvailability, envForAuto, } = resolveEnvState({ env, envForRun, configForCli });
249
+ if (markdownModeExplicitlySet && format !== 'markdown') {
250
+ throw new Error('--markdown-mode is only supported with --format md');
251
+ }
252
+ if (markdownModeExplicitlySet && inputTarget.kind !== 'url') {
253
+ throw new Error('--markdown-mode is only supported for URL inputs');
254
+ }
255
+ const metrics = createRunMetrics({
256
+ env,
257
+ fetchImpl: fetch,
258
+ maxOutputTokensArg,
259
+ });
260
+ const { llmCalls, trackedFetch, buildReport, estimateCostUsd, getLiteLlmCatalog, resolveMaxOutputTokensForCall, resolveMaxInputTokensForCall, setTranscriptionCost, } = metrics;
261
+ const { requestedModel, requestedModelInput, requestedModelLabel, isNamedModelSelection, wantsFreeNamedModel, configForModelSelection, isFallbackModel, } = resolveModelSelection({
262
+ config,
263
+ configForCli,
264
+ configPath,
265
+ envForRun,
266
+ explicitModelArg,
267
+ });
268
+ const verboseColor = supportsColor(stderr, envForRun);
269
+ const { streamingEnabled } = resolveStreamSettings({
270
+ streamMode,
271
+ stdout,
272
+ json,
273
+ extractMode,
274
+ });
275
+ if (extractMode && inputTarget.kind !== 'url') {
276
+ throw new Error('--extract is only supported for website/YouTube URLs');
277
+ }
278
+ // Progress UI (spinner + OSC progress) is shown on stderr. Before writing to stdout (including
279
+ // streaming output), we stop + clear progress via the progress gate to keep scrollback clean.
280
+ const progressEnabled = isRichTty(stderr) && !verbose && !json;
281
+ const progressGate = createProgressGate();
282
+ const { clearProgressForStdout, setClearProgressBeforeStdout, clearProgressIfCurrent } = progressGate;
283
+ const fixedModelSpec = requestedModel.kind === 'fixed' ? requestedModel : null;
284
+ const desiredOutputTokens = resolveDesiredOutputTokens({ lengthArg, maxOutputTokensArg });
285
+ const summaryEngine = createSummaryEngine({
286
+ env,
287
+ envForRun,
288
+ stdout,
289
+ stderr,
290
+ execFileImpl,
291
+ timeoutMs,
292
+ retries,
293
+ streamingEnabled,
294
+ plain,
295
+ verbose,
296
+ verboseColor,
297
+ openaiUseChatCompletions,
298
+ cliConfigForRun: cliConfigForRun ?? null,
299
+ cliAvailability,
300
+ trackedFetch,
301
+ resolveMaxOutputTokensForCall,
302
+ resolveMaxInputTokensForCall,
303
+ llmCalls,
304
+ clearProgressForStdout,
305
+ apiKeys: {
306
+ xaiApiKey,
307
+ openaiApiKey: apiKey,
308
+ googleApiKey,
309
+ anthropicApiKey,
310
+ openrouterApiKey,
311
+ },
312
+ keyFlags: {
313
+ googleConfigured,
314
+ anthropicConfigured,
315
+ openrouterConfigured,
316
+ },
317
+ zai: {
318
+ apiKey: zaiApiKey,
319
+ baseUrl: zaiBaseUrl,
320
+ },
321
+ providerBaseUrls,
322
+ });
323
+ const writeViaFooter = (parts) => {
324
+ if (json)
325
+ return;
326
+ if (extractMode)
327
+ return;
328
+ const filtered = parts.map((p) => p.trim()).filter(Boolean);
329
+ if (filtered.length === 0)
330
+ return;
331
+ clearProgressForStdout();
332
+ stderr.write(`${ansi('2', `via ${filtered.join(', ')}`, verboseColor)}\n`);
333
+ };
334
+ const assetSummaryContext = {
335
+ env,
336
+ envForRun,
337
+ stdout,
338
+ stderr,
339
+ execFileImpl,
340
+ timeoutMs,
341
+ preprocessMode,
342
+ format,
343
+ lengthArg,
344
+ outputLanguage,
345
+ videoMode,
346
+ fixedModelSpec,
347
+ promptOverride,
348
+ lengthInstruction,
349
+ languageInstruction,
350
+ isFallbackModel,
351
+ desiredOutputTokens,
352
+ envForAuto,
353
+ configForModelSelection,
354
+ cliAvailability,
355
+ requestedModel,
356
+ requestedModelInput,
357
+ requestedModelLabel,
358
+ wantsFreeNamedModel,
359
+ isNamedModelSelection,
360
+ maxOutputTokensArg,
361
+ json,
362
+ metricsEnabled,
363
+ metricsDetailed,
364
+ shouldComputeReport,
365
+ runStartedAtMs,
366
+ verbose,
367
+ verboseColor,
368
+ streamingEnabled,
369
+ plain,
370
+ summaryEngine,
371
+ trackedFetch,
372
+ writeViaFooter,
373
+ clearProgressForStdout,
374
+ getLiteLlmCatalog,
375
+ buildReport,
376
+ estimateCostUsd,
377
+ llmCalls,
378
+ cache: cacheState,
379
+ apiStatus: {
380
+ xaiApiKey,
381
+ apiKey,
382
+ openrouterApiKey,
383
+ apifyToken,
384
+ firecrawlConfigured,
385
+ googleConfigured,
386
+ anthropicConfigured,
387
+ providerBaseUrls,
388
+ zaiApiKey,
389
+ zaiBaseUrl,
390
+ },
391
+ };
392
+ const summarizeAsset = (args) => summarizeAssetFlow(assetSummaryContext, args);
393
+ const assetInputContext = {
394
+ env,
395
+ stderr,
396
+ progressEnabled,
397
+ timeoutMs,
398
+ trackedFetch,
399
+ summarizeAsset,
400
+ setClearProgressBeforeStdout,
401
+ clearProgressIfCurrent,
402
+ };
403
+ if (await handleFileInput(assetInputContext, inputTarget)) {
219
404
  return;
220
- const filtered = parts.map((p) => p.trim()).filter(Boolean);
221
- if (filtered.length === 0)
405
+ }
406
+ if (url && (await handleUrlAsset(assetInputContext, url, isYoutubeUrl))) {
222
407
  return;
223
- clearProgressForStdout();
224
- stderr.write(`${ansi('2', `via ${filtered.join(', ')}`, verboseColor)}\n`);
225
- };
226
- const assetSummaryContext = {
227
- env,
228
- envForRun,
229
- stdout,
230
- stderr,
231
- execFileImpl,
232
- timeoutMs,
233
- preprocessMode,
234
- format,
235
- lengthArg,
236
- outputLanguage,
237
- videoMode,
238
- fixedModelSpec,
239
- isFallbackModel,
240
- desiredOutputTokens,
241
- envForAuto,
242
- configForModelSelection,
243
- cliAvailability,
244
- requestedModel,
245
- requestedModelInput,
246
- requestedModelLabel,
247
- wantsFreeNamedModel,
248
- isNamedModelSelection,
249
- maxOutputTokensArg,
250
- json,
251
- metricsEnabled,
252
- metricsDetailed,
253
- shouldComputeReport,
254
- runStartedAtMs,
255
- verbose,
256
- verboseColor,
257
- streamingEnabled,
258
- plain,
259
- summaryEngine,
260
- trackedFetch,
261
- writeViaFooter,
262
- clearProgressForStdout,
263
- getLiteLlmCatalog,
264
- buildReport,
265
- estimateCostUsd,
266
- llmCalls,
267
- apiStatus: {
268
- xaiApiKey,
269
- apiKey,
270
- openrouterApiKey,
271
- apifyToken,
272
- firecrawlConfigured,
273
- googleConfigured,
274
- anthropicConfigured,
275
- zaiApiKey,
276
- zaiBaseUrl,
277
- },
278
- };
279
- const summarizeAsset = (args) => summarizeAssetFlow(assetSummaryContext, args);
280
- const assetInputContext = {
281
- env,
282
- stderr,
283
- progressEnabled,
284
- timeoutMs,
285
- trackedFetch,
286
- summarizeAsset,
287
- setClearProgressBeforeStdout,
288
- clearProgressIfCurrent,
289
- };
290
- if (await handleFileInput(assetInputContext, inputTarget)) {
291
- return;
292
- }
293
- if (url && (await handleUrlAsset(assetInputContext, url, isYoutubeUrl))) {
294
- return;
408
+ }
409
+ if (!url) {
410
+ throw new Error('Only HTTP and HTTPS URLs can be summarized');
411
+ }
412
+ const urlFlowContext = {
413
+ io: {
414
+ env,
415
+ envForRun,
416
+ stdout,
417
+ stderr,
418
+ execFileImpl,
419
+ fetch: trackedFetch,
420
+ },
421
+ flags: {
422
+ timeoutMs,
423
+ maxExtractCharacters: null,
424
+ retries,
425
+ format,
426
+ markdownMode,
427
+ preprocessMode,
428
+ youtubeMode,
429
+ firecrawlMode: requestedFirecrawlMode,
430
+ videoMode,
431
+ outputLanguage,
432
+ lengthArg,
433
+ promptOverride,
434
+ lengthInstruction,
435
+ languageInstruction,
436
+ maxOutputTokensArg,
437
+ json,
438
+ extractMode,
439
+ metricsEnabled,
440
+ metricsDetailed,
441
+ shouldComputeReport,
442
+ runStartedAtMs,
443
+ verbose,
444
+ verboseColor,
445
+ progressEnabled,
446
+ streamingEnabled,
447
+ plain,
448
+ configPath,
449
+ configModelLabel,
450
+ },
451
+ model: {
452
+ requestedModel,
453
+ requestedModelInput,
454
+ requestedModelLabel,
455
+ fixedModelSpec,
456
+ isFallbackModel,
457
+ isNamedModelSelection,
458
+ wantsFreeNamedModel,
459
+ desiredOutputTokens,
460
+ configForModelSelection,
461
+ envForAuto,
462
+ cliAvailability,
463
+ openaiUseChatCompletions,
464
+ openaiWhisperUsdPerMinute,
465
+ apiStatus: {
466
+ xaiApiKey,
467
+ apiKey,
468
+ openrouterApiKey,
469
+ openrouterConfigured,
470
+ googleApiKey,
471
+ googleConfigured,
472
+ anthropicApiKey,
473
+ anthropicConfigured,
474
+ providerBaseUrls,
475
+ zaiApiKey,
476
+ zaiBaseUrl,
477
+ firecrawlConfigured,
478
+ firecrawlApiKey,
479
+ apifyToken,
480
+ ytDlpPath,
481
+ falApiKey,
482
+ openaiTranscriptionKey,
483
+ },
484
+ summaryEngine,
485
+ getLiteLlmCatalog,
486
+ llmCalls,
487
+ },
488
+ cache: cacheState,
489
+ hooks: {
490
+ onModelChosen: null,
491
+ onExtracted: null,
492
+ onLinkPreviewProgress: null,
493
+ onSummaryCached: null,
494
+ setTranscriptionCost,
495
+ summarizeAsset,
496
+ writeViaFooter,
497
+ clearProgressForStdout,
498
+ setClearProgressBeforeStdout,
499
+ clearProgressIfCurrent,
500
+ buildReport,
501
+ estimateCostUsd,
502
+ },
503
+ };
504
+ await runUrlFlow({ ctx: urlFlowContext, url, isYoutubeUrl });
295
505
  }
296
- if (!url) {
297
- throw new Error('Only HTTP and HTTPS URLs can be summarized');
506
+ finally {
507
+ cacheState.store?.close();
298
508
  }
299
- const urlFlowContext = {
300
- env,
301
- envForRun,
302
- stdout,
303
- stderr,
304
- execFileImpl,
305
- timeoutMs,
306
- retries,
307
- format,
308
- markdownMode,
309
- preprocessMode,
310
- youtubeMode,
311
- firecrawlMode: requestedFirecrawlMode,
312
- videoMode,
313
- outputLanguage,
314
- lengthArg,
315
- maxOutputTokensArg,
316
- requestedModel,
317
- requestedModelInput,
318
- requestedModelLabel,
319
- fixedModelSpec,
320
- isFallbackModel,
321
- isNamedModelSelection,
322
- wantsFreeNamedModel,
323
- desiredOutputTokens,
324
- configForModelSelection,
325
- envForAuto,
326
- cliAvailability,
327
- json,
328
- extractMode,
329
- metricsEnabled,
330
- metricsDetailed,
331
- shouldComputeReport,
332
- runStartedAtMs,
333
- verbose,
334
- verboseColor,
335
- progressEnabled,
336
- streamingEnabled,
337
- plain,
338
- openaiUseChatCompletions,
339
- configPath,
340
- configModelLabel,
341
- openaiWhisperUsdPerMinute,
342
- setTranscriptionCost,
343
- apiStatus: {
344
- xaiApiKey,
345
- apiKey,
346
- openrouterApiKey,
347
- openrouterConfigured,
348
- googleApiKey,
349
- googleConfigured,
350
- anthropicApiKey,
351
- anthropicConfigured,
352
- zaiApiKey,
353
- zaiBaseUrl,
354
- firecrawlConfigured,
355
- firecrawlApiKey,
356
- apifyToken,
357
- ytDlpPath,
358
- falApiKey,
359
- openaiTranscriptionKey,
360
- },
361
- trackedFetch,
362
- summaryEngine,
363
- summarizeAsset,
364
- writeViaFooter,
365
- clearProgressForStdout,
366
- setClearProgressBeforeStdout,
367
- clearProgressIfCurrent,
368
- getLiteLlmCatalog,
369
- buildReport,
370
- estimateCostUsd,
371
- llmCalls,
372
- };
373
- await runUrlFlow({ ctx: urlFlowContext, url, isYoutubeUrl });
374
509
  }
375
510
  //# sourceMappingURL=runner.js.map