@steipete/summarize 0.10.0 → 0.11.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 (374) hide show
  1. package/CHANGELOG.md +80 -28
  2. package/README.md +115 -30
  3. package/dist/cli.js +1 -1
  4. package/dist/esm/cache.js +67 -65
  5. package/dist/esm/cache.js.map +1 -1
  6. package/dist/esm/cli-main.js +27 -27
  7. package/dist/esm/cli-main.js.map +1 -1
  8. package/dist/esm/cli.js +2 -2
  9. package/dist/esm/cli.js.map +1 -1
  10. package/dist/esm/config.js +310 -166
  11. package/dist/esm/config.js.map +1 -1
  12. package/dist/esm/content/asset.js +53 -50
  13. package/dist/esm/content/asset.js.map +1 -1
  14. package/dist/esm/content/index.js +1 -1
  15. package/dist/esm/content/index.js.map +1 -1
  16. package/dist/esm/costs.js +1 -1
  17. package/dist/esm/costs.js.map +1 -1
  18. package/dist/esm/daemon/agent.js +165 -164
  19. package/dist/esm/daemon/agent.js.map +1 -1
  20. package/dist/esm/daemon/auto-mode.js +3 -3
  21. package/dist/esm/daemon/auto-mode.js.map +1 -1
  22. package/dist/esm/daemon/chat.js +16 -14
  23. package/dist/esm/daemon/chat.js.map +1 -1
  24. package/dist/esm/daemon/cli-entrypoint.js +72 -0
  25. package/dist/esm/daemon/cli-entrypoint.js.map +1 -0
  26. package/dist/esm/daemon/cli.js +63 -87
  27. package/dist/esm/daemon/cli.js.map +1 -1
  28. package/dist/esm/daemon/config.js +15 -15
  29. package/dist/esm/daemon/config.js.map +1 -1
  30. package/dist/esm/daemon/constants.js +6 -6
  31. package/dist/esm/daemon/constants.js.map +1 -1
  32. package/dist/esm/daemon/env-merge.js.map +1 -1
  33. package/dist/esm/daemon/env-snapshot.js +36 -31
  34. package/dist/esm/daemon/env-snapshot.js.map +1 -1
  35. package/dist/esm/daemon/flow-context.js +59 -28
  36. package/dist/esm/daemon/flow-context.js.map +1 -1
  37. package/dist/esm/daemon/launchd.js +100 -55
  38. package/dist/esm/daemon/launchd.js.map +1 -1
  39. package/dist/esm/daemon/meta.js +5 -5
  40. package/dist/esm/daemon/meta.js.map +1 -1
  41. package/dist/esm/daemon/models.js +54 -31
  42. package/dist/esm/daemon/models.js.map +1 -1
  43. package/dist/esm/daemon/process-registry.js +15 -15
  44. package/dist/esm/daemon/process-registry.js.map +1 -1
  45. package/dist/esm/daemon/schtasks.js +42 -42
  46. package/dist/esm/daemon/schtasks.js.map +1 -1
  47. package/dist/esm/daemon/server.js +248 -244
  48. package/dist/esm/daemon/server.js.map +1 -1
  49. package/dist/esm/daemon/summarize-progress.js +11 -11
  50. package/dist/esm/daemon/summarize-progress.js.map +1 -1
  51. package/dist/esm/daemon/summarize.js +29 -29
  52. package/dist/esm/daemon/summarize.js.map +1 -1
  53. package/dist/esm/daemon/systemd.js +47 -47
  54. package/dist/esm/daemon/systemd.js.map +1 -1
  55. package/dist/esm/firecrawl.js +12 -12
  56. package/dist/esm/firecrawl.js.map +1 -1
  57. package/dist/esm/flags.js +32 -32
  58. package/dist/esm/flags.js.map +1 -1
  59. package/dist/esm/index.js +3 -3
  60. package/dist/esm/index.js.map +1 -1
  61. package/dist/esm/language.js +1 -1
  62. package/dist/esm/language.js.map +1 -1
  63. package/dist/esm/llm/cli.js +128 -64
  64. package/dist/esm/llm/cli.js.map +1 -1
  65. package/dist/esm/llm/errors.js +1 -1
  66. package/dist/esm/llm/errors.js.map +1 -1
  67. package/dist/esm/llm/generate-text.js +107 -98
  68. package/dist/esm/llm/generate-text.js.map +1 -1
  69. package/dist/esm/llm/google-models.js +17 -17
  70. package/dist/esm/llm/google-models.js.map +1 -1
  71. package/dist/esm/llm/html-to-markdown.js +3 -3
  72. package/dist/esm/llm/html-to-markdown.js.map +1 -1
  73. package/dist/esm/llm/model-id.js +38 -16
  74. package/dist/esm/llm/model-id.js.map +1 -1
  75. package/dist/esm/llm/prompt.js +5 -5
  76. package/dist/esm/llm/prompt.js.map +1 -1
  77. package/dist/esm/llm/providers/anthropic.js +33 -33
  78. package/dist/esm/llm/providers/anthropic.js.map +1 -1
  79. package/dist/esm/llm/providers/google.js +19 -19
  80. package/dist/esm/llm/providers/google.js.map +1 -1
  81. package/dist/esm/llm/providers/models.js +30 -30
  82. package/dist/esm/llm/providers/models.js.map +1 -1
  83. package/dist/esm/llm/providers/openai.js +35 -34
  84. package/dist/esm/llm/providers/openai.js.map +1 -1
  85. package/dist/esm/llm/providers/shared.js +8 -8
  86. package/dist/esm/llm/providers/shared.js.map +1 -1
  87. package/dist/esm/llm/transcript-to-markdown.js +9 -5
  88. package/dist/esm/llm/transcript-to-markdown.js.map +1 -1
  89. package/dist/esm/llm/usage.js +18 -18
  90. package/dist/esm/llm/usage.js.map +1 -1
  91. package/dist/esm/logging/daemon.js +21 -21
  92. package/dist/esm/logging/daemon.js.map +1 -1
  93. package/dist/esm/logging/ring-file.js +5 -5
  94. package/dist/esm/logging/ring-file.js.map +1 -1
  95. package/dist/esm/markitdown.js +21 -19
  96. package/dist/esm/markitdown.js.map +1 -1
  97. package/dist/esm/media-cache.js +39 -39
  98. package/dist/esm/media-cache.js.map +1 -1
  99. package/dist/esm/model-auto.js +175 -106
  100. package/dist/esm/model-auto.js.map +1 -1
  101. package/dist/esm/model-spec.js +52 -42
  102. package/dist/esm/model-spec.js.map +1 -1
  103. package/dist/esm/pricing/litellm.js +4 -4
  104. package/dist/esm/pricing/litellm.js.map +1 -1
  105. package/dist/esm/processes.js +1 -1
  106. package/dist/esm/processes.js.map +1 -1
  107. package/dist/esm/prompts/index.js +1 -1
  108. package/dist/esm/prompts/index.js.map +1 -1
  109. package/dist/esm/refresh-free.js +81 -81
  110. package/dist/esm/refresh-free.js.map +1 -1
  111. package/dist/esm/run/attachments.js +47 -44
  112. package/dist/esm/run/attachments.js.map +1 -1
  113. package/dist/esm/run/bird.js +26 -26
  114. package/dist/esm/run/bird.js.map +1 -1
  115. package/dist/esm/run/cache-state.js +7 -7
  116. package/dist/esm/run/cache-state.js.map +1 -1
  117. package/dist/esm/run/cli-fallback-state.js +45 -0
  118. package/dist/esm/run/cli-fallback-state.js.map +1 -0
  119. package/dist/esm/run/cli-preflight.js +24 -24
  120. package/dist/esm/run/cli-preflight.js.map +1 -1
  121. package/dist/esm/run/constants.js +12 -12
  122. package/dist/esm/run/constants.js.map +1 -1
  123. package/dist/esm/run/cookies/twitter.js +47 -47
  124. package/dist/esm/run/cookies/twitter.js.map +1 -1
  125. package/dist/esm/run/env.js +21 -15
  126. package/dist/esm/run/env.js.map +1 -1
  127. package/dist/esm/run/fetch-with-timeout.js +4 -4
  128. package/dist/esm/run/fetch-with-timeout.js.map +1 -1
  129. package/dist/esm/run/finish-line.js +68 -68
  130. package/dist/esm/run/finish-line.js.map +1 -1
  131. package/dist/esm/run/flows/asset/extract.js +15 -15
  132. package/dist/esm/run/flows/asset/extract.js.map +1 -1
  133. package/dist/esm/run/flows/asset/input.js +47 -66
  134. package/dist/esm/run/flows/asset/input.js.map +1 -1
  135. package/dist/esm/run/flows/asset/media-policy.js +1 -1
  136. package/dist/esm/run/flows/asset/media-policy.js.map +1 -1
  137. package/dist/esm/run/flows/asset/media.js +49 -40
  138. package/dist/esm/run/flows/asset/media.js.map +1 -1
  139. package/dist/esm/run/flows/asset/output.js +12 -12
  140. package/dist/esm/run/flows/asset/output.js.map +1 -1
  141. package/dist/esm/run/flows/asset/preprocess.js +79 -44
  142. package/dist/esm/run/flows/asset/preprocess.js.map +1 -1
  143. package/dist/esm/run/flows/asset/summary.js +173 -106
  144. package/dist/esm/run/flows/asset/summary.js.map +1 -1
  145. package/dist/esm/run/flows/url/extract.js +26 -26
  146. package/dist/esm/run/flows/url/extract.js.map +1 -1
  147. package/dist/esm/run/flows/url/flow.js +104 -98
  148. package/dist/esm/run/flows/url/flow.js.map +1 -1
  149. package/dist/esm/run/flows/url/markdown.js +57 -57
  150. package/dist/esm/run/flows/url/markdown.js.map +1 -1
  151. package/dist/esm/run/flows/url/slides-output.js +61 -59
  152. package/dist/esm/run/flows/url/slides-output.js.map +1 -1
  153. package/dist/esm/run/flows/url/slides-text.js +85 -85
  154. package/dist/esm/run/flows/url/slides-text.js.map +1 -1
  155. package/dist/esm/run/flows/url/summary.js +174 -107
  156. package/dist/esm/run/flows/url/summary.js.map +1 -1
  157. package/dist/esm/run/format.js +10 -10
  158. package/dist/esm/run/format.js.map +1 -1
  159. package/dist/esm/run/help.js +141 -135
  160. package/dist/esm/run/help.js.map +1 -1
  161. package/dist/esm/run/logging.js +10 -10
  162. package/dist/esm/run/logging.js.map +1 -1
  163. package/dist/esm/run/markdown.js +12 -12
  164. package/dist/esm/run/markdown.js.map +1 -1
  165. package/dist/esm/run/media-cache-state.js +5 -5
  166. package/dist/esm/run/media-cache-state.js.map +1 -1
  167. package/dist/esm/run/model-attempts.js.map +1 -1
  168. package/dist/esm/run/openrouter.js +11 -11
  169. package/dist/esm/run/openrouter.js.map +1 -1
  170. package/dist/esm/run/progress.js +1 -1
  171. package/dist/esm/run/progress.js.map +1 -1
  172. package/dist/esm/run/run-config.js +16 -16
  173. package/dist/esm/run/run-config.js.map +1 -1
  174. package/dist/esm/run/run-context.js +2 -2
  175. package/dist/esm/run/run-context.js.map +1 -1
  176. package/dist/esm/run/run-env.js +55 -54
  177. package/dist/esm/run/run-env.js.map +1 -1
  178. package/dist/esm/run/run-input.js +3 -3
  179. package/dist/esm/run/run-input.js.map +1 -1
  180. package/dist/esm/run/run-metrics.js +16 -16
  181. package/dist/esm/run/run-metrics.js.map +1 -1
  182. package/dist/esm/run/run-models.js +28 -23
  183. package/dist/esm/run/run-models.js.map +1 -1
  184. package/dist/esm/run/run-output.js +3 -3
  185. package/dist/esm/run/run-output.js.map +1 -1
  186. package/dist/esm/run/run-settings.js +83 -34
  187. package/dist/esm/run/run-settings.js.map +1 -1
  188. package/dist/esm/run/run-stream.js +4 -4
  189. package/dist/esm/run/run-stream.js.map +1 -1
  190. package/dist/esm/run/runner.js +166 -127
  191. package/dist/esm/run/runner.js.map +1 -1
  192. package/dist/esm/run/slides-cli.js +43 -42
  193. package/dist/esm/run/slides-cli.js.map +1 -1
  194. package/dist/esm/run/slides-render.js +36 -36
  195. package/dist/esm/run/slides-render.js.map +1 -1
  196. package/dist/esm/run/stdin-temp-file.js +77 -0
  197. package/dist/esm/run/stdin-temp-file.js.map +1 -0
  198. package/dist/esm/run/stream-output.js +7 -7
  199. package/dist/esm/run/stream-output.js.map +1 -1
  200. package/dist/esm/run/streaming.js +16 -16
  201. package/dist/esm/run/streaming.js.map +1 -1
  202. package/dist/esm/run/summary-engine.js +57 -51
  203. package/dist/esm/run/summary-engine.js.map +1 -1
  204. package/dist/esm/run/summary-llm.js +3 -3
  205. package/dist/esm/run/summary-llm.js.map +1 -1
  206. package/dist/esm/run/terminal.js +4 -4
  207. package/dist/esm/run/terminal.js.map +1 -1
  208. package/dist/esm/run/tips.js +2 -2
  209. package/dist/esm/run/tips.js.map +1 -1
  210. package/dist/esm/run/transcriber-cli.js +49 -49
  211. package/dist/esm/run/transcriber-cli.js.map +1 -1
  212. package/dist/esm/run.js +1 -1
  213. package/dist/esm/run.js.map +1 -1
  214. package/dist/esm/shared/contracts.js +1 -1
  215. package/dist/esm/shared/contracts.js.map +1 -1
  216. package/dist/esm/shared/sse-events.js +16 -16
  217. package/dist/esm/shared/sse-events.js.map +1 -1
  218. package/dist/esm/shared/streaming-merge.js +3 -3
  219. package/dist/esm/shared/streaming-merge.js.map +1 -1
  220. package/dist/esm/slides/extract.js +258 -249
  221. package/dist/esm/slides/extract.js.map +1 -1
  222. package/dist/esm/slides/index.js +3 -3
  223. package/dist/esm/slides/index.js.map +1 -1
  224. package/dist/esm/slides/settings.js +14 -14
  225. package/dist/esm/slides/settings.js.map +1 -1
  226. package/dist/esm/slides/store.js +9 -9
  227. package/dist/esm/slides/store.js.map +1 -1
  228. package/dist/esm/tty/format.js +13 -13
  229. package/dist/esm/tty/format.js.map +1 -1
  230. package/dist/esm/tty/osc-progress.js +1 -1
  231. package/dist/esm/tty/osc-progress.js.map +1 -1
  232. package/dist/esm/tty/progress/fetch-html.js +14 -14
  233. package/dist/esm/tty/progress/fetch-html.js.map +1 -1
  234. package/dist/esm/tty/progress/transcript.js +70 -62
  235. package/dist/esm/tty/progress/transcript.js.map +1 -1
  236. package/dist/esm/tty/spinner.js +20 -9
  237. package/dist/esm/tty/spinner.js.map +1 -1
  238. package/dist/esm/tty/theme.js +92 -92
  239. package/dist/esm/tty/theme.js.map +1 -1
  240. package/dist/esm/tty/website-progress.js +32 -32
  241. package/dist/esm/tty/website-progress.js.map +1 -1
  242. package/dist/esm/version.js +29 -29
  243. package/dist/esm/version.js.map +1 -1
  244. package/dist/types/cache.d.ts +6 -6
  245. package/dist/types/config.d.ts +49 -7
  246. package/dist/types/content/asset.d.ts +8 -6
  247. package/dist/types/content/index.d.ts +1 -1
  248. package/dist/types/costs.d.ts +3 -3
  249. package/dist/types/daemon/agent.d.ts +1 -1
  250. package/dist/types/daemon/auto-mode.d.ts +3 -3
  251. package/dist/types/daemon/chat.d.ts +2 -2
  252. package/dist/types/daemon/cli-entrypoint.d.ts +2 -0
  253. package/dist/types/daemon/config.d.ts +2 -2
  254. package/dist/types/daemon/env-merge.d.ts +1 -1
  255. package/dist/types/daemon/env-snapshot.d.ts +1 -1
  256. package/dist/types/daemon/flow-context.d.ts +7 -7
  257. package/dist/types/daemon/launchd.d.ts +8 -0
  258. package/dist/types/daemon/models.d.ts +6 -2
  259. package/dist/types/daemon/process-registry.d.ts +5 -5
  260. package/dist/types/daemon/server.d.ts +2 -2
  261. package/dist/types/daemon/summarize-progress.d.ts +1 -1
  262. package/dist/types/daemon/summarize.d.ts +7 -7
  263. package/dist/types/firecrawl.d.ts +1 -1
  264. package/dist/types/flags.d.ts +11 -11
  265. package/dist/types/index.d.ts +4 -4
  266. package/dist/types/language.d.ts +1 -1
  267. package/dist/types/llm/attachments.d.ts +1 -1
  268. package/dist/types/llm/cli.d.ts +3 -3
  269. package/dist/types/llm/generate-text.d.ts +7 -7
  270. package/dist/types/llm/html-to-markdown.d.ts +3 -3
  271. package/dist/types/llm/model-id.d.ts +1 -1
  272. package/dist/types/llm/prompt.d.ts +2 -2
  273. package/dist/types/llm/providers/anthropic.d.ts +3 -3
  274. package/dist/types/llm/providers/google.d.ts +3 -3
  275. package/dist/types/llm/providers/models.d.ts +2 -2
  276. package/dist/types/llm/providers/openai.d.ts +4 -4
  277. package/dist/types/llm/providers/shared.d.ts +2 -2
  278. package/dist/types/llm/transcript-to-markdown.d.ts +4 -2
  279. package/dist/types/llm/usage.d.ts +1 -1
  280. package/dist/types/logging/daemon.d.ts +4 -4
  281. package/dist/types/markitdown.d.ts +1 -1
  282. package/dist/types/media-cache.d.ts +2 -2
  283. package/dist/types/model-auto.d.ts +14 -4
  284. package/dist/types/model-spec.d.ts +10 -10
  285. package/dist/types/pricing/litellm.d.ts +1 -1
  286. package/dist/types/processes.d.ts +1 -1
  287. package/dist/types/prompts/index.d.ts +1 -1
  288. package/dist/types/run/attachments.d.ts +7 -7
  289. package/dist/types/run/bird.d.ts +2 -2
  290. package/dist/types/run/cache-state.d.ts +2 -2
  291. package/dist/types/run/cli-fallback-state.d.ts +6 -0
  292. package/dist/types/run/constants.d.ts +1 -1
  293. package/dist/types/run/cookies/twitter.d.ts +1 -1
  294. package/dist/types/run/env.d.ts +1 -1
  295. package/dist/types/run/finish-line.d.ts +5 -5
  296. package/dist/types/run/flows/asset/extract.d.ts +4 -4
  297. package/dist/types/run/flows/asset/input.d.ts +9 -3
  298. package/dist/types/run/flows/asset/media.d.ts +1 -1
  299. package/dist/types/run/flows/asset/output.d.ts +5 -5
  300. package/dist/types/run/flows/asset/preprocess.d.ts +23 -17
  301. package/dist/types/run/flows/asset/summary.d.ts +19 -17
  302. package/dist/types/run/flows/url/extract.d.ts +1 -1
  303. package/dist/types/run/flows/url/flow.d.ts +1 -1
  304. package/dist/types/run/flows/url/markdown.d.ts +6 -6
  305. package/dist/types/run/flows/url/slides-output.d.ts +7 -7
  306. package/dist/types/run/flows/url/slides-text.d.ts +9 -9
  307. package/dist/types/run/flows/url/summary.d.ts +11 -11
  308. package/dist/types/run/flows/url/types.d.ts +26 -22
  309. package/dist/types/run/format.d.ts +3 -3
  310. package/dist/types/run/help.d.ts +1 -1
  311. package/dist/types/run/media-cache-state.d.ts +2 -2
  312. package/dist/types/run/model-attempts.d.ts +1 -1
  313. package/dist/types/run/run-config.d.ts +4 -4
  314. package/dist/types/run/run-context.d.ts +3 -1
  315. package/dist/types/run/run-env.d.ts +3 -1
  316. package/dist/types/run/run-input.d.ts +2 -2
  317. package/dist/types/run/run-metrics.d.ts +3 -3
  318. package/dist/types/run/run-models.d.ts +3 -2
  319. package/dist/types/run/run-output.d.ts +1 -1
  320. package/dist/types/run/run-settings.d.ts +15 -6
  321. package/dist/types/run/run-stream.d.ts +2 -2
  322. package/dist/types/run/runner.d.ts +3 -2
  323. package/dist/types/run/slides-render.d.ts +4 -4
  324. package/dist/types/run/stdin-temp-file.d.ts +9 -0
  325. package/dist/types/run/stream-output.d.ts +1 -1
  326. package/dist/types/run/streaming.d.ts +4 -4
  327. package/dist/types/run/summary-engine.d.ts +11 -11
  328. package/dist/types/run/summary-llm.d.ts +5 -5
  329. package/dist/types/run/types.d.ts +4 -4
  330. package/dist/types/run.d.ts +1 -1
  331. package/dist/types/shared/contracts.d.ts +2 -2
  332. package/dist/types/shared/sse-events.d.ts +9 -9
  333. package/dist/types/slides/extract.d.ts +5 -4
  334. package/dist/types/slides/index.d.ts +5 -5
  335. package/dist/types/slides/store.d.ts +2 -2
  336. package/dist/types/slides/types.d.ts +2 -2
  337. package/dist/types/tty/osc-progress.d.ts +5 -5
  338. package/dist/types/tty/progress/fetch-html.d.ts +3 -3
  339. package/dist/types/tty/progress/transcript.d.ts +3 -3
  340. package/dist/types/tty/spinner.d.ts +2 -2
  341. package/dist/types/tty/theme.d.ts +2 -2
  342. package/dist/types/tty/website-progress.d.ts +3 -3
  343. package/dist/types/version.d.ts +1 -1
  344. package/docs/agent.md +38 -4
  345. package/docs/assets/site.js +46 -46
  346. package/docs/chrome-extension.md +11 -5
  347. package/docs/cli.md +59 -13
  348. package/docs/config.md +59 -10
  349. package/docs/extract-only.md +2 -0
  350. package/docs/index.html +33 -14
  351. package/docs/llm.md +7 -4
  352. package/docs/media.md +5 -4
  353. package/docs/model-auto.md +3 -2
  354. package/docs/nvidia-onnx-transcription.md +3 -3
  355. package/docs/openai.md +1 -1
  356. package/docs/releasing.md +3 -0
  357. package/docs/site/404.html +4 -1
  358. package/docs/site/assets/site.js +46 -46
  359. package/docs/site/docs/chrome-extension.html +18 -6
  360. package/docs/site/docs/config.html +29 -8
  361. package/docs/site/docs/extract-only.html +16 -4
  362. package/docs/site/docs/firecrawl.html +12 -3
  363. package/docs/site/docs/index.html +35 -6
  364. package/docs/site/docs/llm.html +19 -5
  365. package/docs/site/docs/openai.html +18 -5
  366. package/docs/site/docs/website.html +29 -9
  367. package/docs/site/docs/youtube.html +12 -3
  368. package/docs/site/index.html +33 -14
  369. package/docs/slides.md +13 -5
  370. package/docs/smoketest.md +29 -20
  371. package/docs/timestamps.md +21 -0
  372. package/docs/website.md +2 -1
  373. package/docs/youtube.md +4 -0
  374. package/package.json +36 -35
@@ -1,41 +1,46 @@
1
- import { execFile } from 'node:child_process';
2
- import { readFile } from 'node:fs/promises';
3
- import { CommanderError } from 'commander';
4
- import { clearCacheFiles, DEFAULT_CACHE_MAX_MB, resolveCachePath, } from '../cache.js';
5
- import { loadSummarizeConfig } from '../config.js';
6
- import { parseExtractFormat, parseMaxExtractCharactersArg, parseMetricsMode, parseStreamMode, } from '../flags.js';
7
- import { resolveSlideSettings } from '../slides/index.js';
8
- import { createThemeRenderer, resolveThemeNameFromSources, resolveTrueColor } from '../tty/theme.js';
9
- import { formatVersionLine } from '../version.js';
10
- import { createCacheStateFromConfig } from './cache-state.js';
11
- import { handleDaemonCliRequest, handleHelpRequest, handleRefreshFreeRequest, } from './cli-preflight.js';
12
- import { parseCliProviderArg } from './env.js';
13
- import { extractAssetContent } from './flows/asset/extract.js';
14
- import { handleFileInput, withUrlAsset } from './flows/asset/input.js';
15
- import { summarizeMediaFile as summarizeMediaFileImpl } from './flows/asset/media.js';
16
- import { outputExtractedAsset } from './flows/asset/output.js';
17
- import { summarizeAsset as summarizeAssetFlow } from './flows/asset/summary.js';
18
- import { runUrlFlow } from './flows/url/flow.js';
19
- import { attachRichHelp, buildProgram } from './help.js';
20
- import { createMediaCacheFromConfig } from './media-cache-state.js';
21
- import { createProgressGate } from './progress.js';
22
- import { resolveRunContextState } from './run-context.js';
23
- import { resolveRunInput } from './run-input.js';
24
- import { createRunMetrics } from './run-metrics.js';
25
- import { resolveModelSelection } from './run-models.js';
26
- import { resolveDesiredOutputTokens } from './run-output.js';
27
- import { resolveCliRunSettings } from './run-settings.js';
28
- import { resolveStreamSettings } from './run-stream.js';
29
- import { handleSlidesCliRequest } from './slides-cli.js';
30
- import { createSummaryEngine } from './summary-engine.js';
31
- import { isRichTty, supportsColor } from './terminal.js';
32
- import { handleTranscriberCliRequest } from './transcriber-cli.js';
33
- export async function runCli(argv, { env, fetch, execFile: execFileOverride, stdout, stderr }) {
34
- ;
1
+ import { CommanderError } from "commander";
2
+ import { execFile } from "node:child_process";
3
+ import fs from "node:fs/promises";
4
+ import { clearCacheFiles, DEFAULT_CACHE_MAX_MB, resolveCachePath, } from "../cache.js";
5
+ import { loadSummarizeConfig, mergeConfigEnv } from "../config.js";
6
+ import { parseExtractFormat, parseMaxExtractCharactersArg, parseMetricsMode, parseStreamMode, } from "../flags.js";
7
+ import { resolveSlideSettings } from "../slides/index.js";
8
+ import { createThemeRenderer, resolveThemeNameFromSources, resolveTrueColor, } from "../tty/theme.js";
9
+ import { formatVersionLine } from "../version.js";
10
+ import { createCacheStateFromConfig } from "./cache-state.js";
11
+ import { handleDaemonCliRequest, handleHelpRequest, handleRefreshFreeRequest, } from "./cli-preflight.js";
12
+ import { parseCliProviderArg } from "./env.js";
13
+ import { extractAssetContent } from "./flows/asset/extract.js";
14
+ import { handleFileInput, isTranscribableExtension, withUrlAsset } from "./flows/asset/input.js";
15
+ import { summarizeMediaFile as summarizeMediaFileImpl } from "./flows/asset/media.js";
16
+ import { outputExtractedAsset } from "./flows/asset/output.js";
17
+ import { summarizeAsset as summarizeAssetFlow } from "./flows/asset/summary.js";
18
+ import { runUrlFlow } from "./flows/url/flow.js";
19
+ import { attachRichHelp, buildProgram } from "./help.js";
20
+ import { createMediaCacheFromConfig } from "./media-cache-state.js";
21
+ import { createProgressGate } from "./progress.js";
22
+ import { resolveRunContextState } from "./run-context.js";
23
+ import { resolveRunInput } from "./run-input.js";
24
+ import { createRunMetrics } from "./run-metrics.js";
25
+ import { resolveModelSelection } from "./run-models.js";
26
+ import { resolveDesiredOutputTokens } from "./run-output.js";
27
+ import { resolveCliRunSettings } from "./run-settings.js";
28
+ import { resolveStreamSettings } from "./run-stream.js";
29
+ import { handleSlidesCliRequest } from "./slides-cli.js";
30
+ import { createTempFileFromStdin } from "./stdin-temp-file.js";
31
+ import { createSummaryEngine } from "./summary-engine.js";
32
+ import { isRichTty, supportsColor } from "./terminal.js";
33
+ import { handleTranscriberCliRequest } from "./transcriber-cli.js";
34
+ export async function runCli(argv, { env: inputEnv, fetch, execFile: execFileOverride, stdin, stdout, stderr }) {
35
35
  globalThis.AI_SDK_LOG_WARNINGS = false;
36
- const normalizedArgv = argv.filter((arg) => arg !== '--');
37
- const noColorFlag = normalizedArgv.includes('--no-color');
38
- const envForRun = noColorFlag ? { ...env, NO_COLOR: '1', FORCE_COLOR: '0' } : env;
36
+ const normalizedArgv = argv.filter((arg) => arg !== "--");
37
+ const noColorFlag = normalizedArgv.includes("--no-color");
38
+ let envForRun = noColorFlag
39
+ ? { ...inputEnv, NO_COLOR: "1", FORCE_COLOR: "0" }
40
+ : { ...inputEnv };
41
+ const { config: bootstrapConfig } = loadSummarizeConfig({ env: envForRun });
42
+ envForRun = mergeConfigEnv({ env: envForRun, config: bootstrapConfig });
43
+ const env = envForRun;
39
44
  if (handleHelpRequest({ normalizedArgv, envForRun, stdout, stderr })) {
40
45
  return;
41
46
  }
@@ -87,10 +92,10 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
87
92
  program.exitOverride();
88
93
  attachRichHelp(program, envForRun, stdout);
89
94
  try {
90
- program.parse(normalizedArgv, { from: 'user' });
95
+ program.parse(normalizedArgv, { from: "user" });
91
96
  }
92
97
  catch (error) {
93
- if (error instanceof CommanderError && error.code === 'commander.helpDisplayed') {
98
+ if (error instanceof CommanderError && error.code === "commander.helpDisplayed") {
94
99
  return;
95
100
  }
96
101
  throw error;
@@ -99,16 +104,16 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
99
104
  stdout.write(`${formatVersionLine()}\n`);
100
105
  return;
101
106
  }
102
- const promptArg = typeof program.opts().prompt === 'string' ? program.opts().prompt : null;
103
- const promptFileArg = typeof program.opts().promptFile === 'string' ? program.opts().promptFile : null;
107
+ const promptArg = typeof program.opts().prompt === "string" ? program.opts().prompt : null;
108
+ const promptFileArg = typeof program.opts().promptFile === "string" ? program.opts().promptFile : null;
104
109
  if (promptArg && promptFileArg) {
105
- throw new Error('Use either --prompt or --prompt-file (not both).');
110
+ throw new Error("Use either --prompt or --prompt-file (not both).");
106
111
  }
107
112
  let promptOverride = null;
108
113
  if (promptFileArg) {
109
114
  let text;
110
115
  try {
111
- text = await readFile(promptFileArg, 'utf8');
116
+ text = await fs.readFile(promptFileArg, "utf8");
112
117
  }
113
118
  catch (error) {
114
119
  const message = error instanceof Error ? error.message : String(error);
@@ -123,15 +128,15 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
123
128
  else if (promptArg) {
124
129
  const trimmed = promptArg.trim();
125
130
  if (!trimmed) {
126
- throw new Error('Prompt must not be empty.');
131
+ throw new Error("Prompt must not be empty.");
127
132
  }
128
133
  promptOverride = trimmed;
129
134
  }
130
- const clearCacheFlag = normalizedArgv.includes('--clear-cache');
135
+ const clearCacheFlag = normalizedArgv.includes("--clear-cache");
131
136
  if (clearCacheFlag) {
132
- const extraArgs = normalizedArgv.filter((arg) => arg !== '--clear-cache');
137
+ const extraArgs = normalizedArgv.filter((arg) => arg !== "--clear-cache");
133
138
  if (extraArgs.length > 0) {
134
- throw new Error('--clear-cache must be used alone.');
139
+ throw new Error("--clear-cache must be used alone.");
135
140
  }
136
141
  const { config } = loadSummarizeConfig({ env: envForRun });
137
142
  const cachePath = resolveCachePath({
@@ -139,17 +144,17 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
139
144
  cachePath: config?.cache?.path ?? null,
140
145
  });
141
146
  if (!cachePath) {
142
- throw new Error('Unable to resolve cache path (missing HOME).');
147
+ throw new Error("Unable to resolve cache path (missing HOME).");
143
148
  }
144
149
  clearCacheFiles(cachePath);
145
- stdout.write('Cache cleared.\n');
150
+ stdout.write("Cache cleared.\n");
146
151
  return;
147
152
  }
148
- const cacheStatsFlag = normalizedArgv.includes('--cache-stats');
153
+ const cacheStatsFlag = normalizedArgv.includes("--cache-stats");
149
154
  if (cacheStatsFlag) {
150
- const extraArgs = normalizedArgv.filter((arg) => arg !== '--cache-stats');
155
+ const extraArgs = normalizedArgv.filter((arg) => arg !== "--cache-stats");
151
156
  if (extraArgs.length > 0) {
152
- throw new Error('--cache-stats must be used alone.');
157
+ throw new Error("--cache-stats must be used alone.");
153
158
  }
154
159
  const { config } = loadSummarizeConfig({ env: envForRun });
155
160
  const cachePath = resolveCachePath({
@@ -157,26 +162,26 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
157
162
  cachePath: config?.cache?.path ?? null,
158
163
  });
159
164
  if (!cachePath) {
160
- throw new Error('Unable to resolve cache path (missing HOME).');
165
+ throw new Error("Unable to resolve cache path (missing HOME).");
161
166
  }
162
- const cacheMaxMb = typeof config?.cache?.maxMb === 'number' ? config.cache.maxMb : DEFAULT_CACHE_MAX_MB;
167
+ const cacheMaxMb = typeof config?.cache?.maxMb === "number" ? config.cache.maxMb : DEFAULT_CACHE_MAX_MB;
163
168
  const cacheMaxBytes = Math.max(0, cacheMaxMb) * 1024 * 1024;
164
- const { readCacheStats } = await import('../cache.js');
165
- const { formatBytes } = await import('../tty/format.js');
169
+ const { readCacheStats } = await import("../cache.js");
170
+ const { formatBytes } = await import("../tty/format.js");
166
171
  const stats = await readCacheStats(cachePath);
167
172
  stdout.write(`Cache path: ${cachePath}\n`);
168
173
  if (!stats) {
169
- stdout.write('Cache is empty.\n');
174
+ stdout.write("Cache is empty.\n");
170
175
  return;
171
176
  }
172
177
  const sizeLabel = formatBytes(stats.sizeBytes);
173
- const maxLabel = cacheMaxBytes > 0 ? formatBytes(cacheMaxBytes) : 'disabled';
178
+ const maxLabel = cacheMaxBytes > 0 ? formatBytes(cacheMaxBytes) : "disabled";
174
179
  stdout.write(`Size: ${sizeLabel} (max ${maxLabel})\n`);
175
180
  stdout.write(`Entries: total=${stats.totalEntries} extract=${stats.counts.extract} summary=${stats.counts.summary} transcript=${stats.counts.transcript}\n`);
176
181
  return;
177
182
  }
178
- const cliFlagPresent = normalizedArgv.some((arg) => arg === '--cli' || arg.startsWith('--cli='));
179
- let cliProviderArgRaw = typeof program.opts().cli === 'string' ? program.opts().cli : null;
183
+ const cliFlagPresent = normalizedArgv.some((arg) => arg === "--cli" || arg.startsWith("--cli="));
184
+ let cliProviderArgRaw = typeof program.opts().cli === "string" ? program.opts().cli : null;
180
185
  const inputResolution = resolveRunInput({
181
186
  program,
182
187
  cliFlagPresent,
@@ -187,12 +192,12 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
187
192
  const inputTarget = inputResolution.inputTarget;
188
193
  const url = inputResolution.url;
189
194
  const runStartedAtMs = Date.now();
190
- const videoModeExplicitlySet = normalizedArgv.some((arg) => arg === '--video-mode' || arg.startsWith('--video-mode='));
191
- const lengthExplicitlySet = normalizedArgv.some((arg) => arg === '--length' || arg.startsWith('--length='));
192
- const languageExplicitlySet = normalizedArgv.some((arg) => arg === '--language' ||
193
- arg.startsWith('--language=') ||
194
- arg === '--lang' ||
195
- arg.startsWith('--lang='));
195
+ const videoModeExplicitlySet = normalizedArgv.some((arg) => arg === "--video-mode" || arg.startsWith("--video-mode="));
196
+ const lengthExplicitlySet = normalizedArgv.some((arg) => arg === "--length" || arg.startsWith("--length="));
197
+ const languageExplicitlySet = normalizedArgv.some((arg) => arg === "--language" ||
198
+ arg.startsWith("--language=") ||
199
+ arg === "--lang" ||
200
+ arg.startsWith("--lang="));
196
201
  const noCacheFlag = program.opts().cache === false;
197
202
  const noMediaCacheFlag = program.opts().mediaCache === false;
198
203
  const extractMode = Boolean(program.opts().extract) || Boolean(program.opts().extractOnly);
@@ -204,47 +209,47 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
204
209
  const debug = Boolean(program.opts().debug);
205
210
  const verbose = Boolean(program.opts().verbose) || debug;
206
211
  const normalizeTranscriber = (value) => {
207
- if (typeof value !== 'string')
212
+ if (typeof value !== "string")
208
213
  return null;
209
214
  const normalized = value.trim().toLowerCase();
210
- if (normalized === 'auto' ||
211
- normalized === 'whisper' ||
212
- normalized === 'parakeet' ||
213
- normalized === 'canary')
215
+ if (normalized === "auto" ||
216
+ normalized === "whisper" ||
217
+ normalized === "parakeet" ||
218
+ normalized === "canary")
214
219
  return normalized;
215
220
  return null;
216
221
  };
217
- const transcriberExplicitlySet = normalizedArgv.some((arg) => arg === '--transcriber' || arg.startsWith('--transcriber='));
222
+ const transcriberExplicitlySet = normalizedArgv.some((arg) => arg === "--transcriber" || arg.startsWith("--transcriber="));
218
223
  const envTranscriber = envForRun?.SUMMARIZE_TRANSCRIBER ??
219
224
  process.env.SUMMARIZE_TRANSCRIBER ??
220
225
  null;
221
226
  const transcriber = normalizeTranscriber(transcriberExplicitlySet ? program.opts().transcriber : envTranscriber) ??
222
- 'auto';
227
+ "auto";
223
228
  envForRun.SUMMARIZE_TRANSCRIBER = transcriber;
224
- const maxExtractCharacters = parseMaxExtractCharactersArg(typeof program.opts().maxExtractCharacters === 'string'
229
+ const maxExtractCharacters = parseMaxExtractCharactersArg(typeof program.opts().maxExtractCharacters === "string"
225
230
  ? program.opts().maxExtractCharacters
226
231
  : program.opts().maxExtractCharacters != null
227
232
  ? String(program.opts().maxExtractCharacters)
228
233
  : undefined);
229
- const isYoutubeUrl = typeof url === 'string' ? /youtube\.com|youtu\.be/i.test(url) : false;
230
- const formatExplicitlySet = normalizedArgv.some((arg) => arg === '--format' || arg.startsWith('--format='));
231
- const rawFormatOpt = typeof program.opts().format === 'string' ? program.opts().format : null;
234
+ const isYoutubeUrl = typeof url === "string" ? /youtube\.com|youtu\.be/i.test(url) : false;
235
+ const formatExplicitlySet = normalizedArgv.some((arg) => arg === "--format" || arg.startsWith("--format="));
236
+ const rawFormatOpt = typeof program.opts().format === "string" ? program.opts().format : null;
232
237
  const format = parseExtractFormat(formatExplicitlySet
233
- ? (rawFormatOpt ?? 'text')
234
- : extractMode && inputTarget.kind === 'url' && !isYoutubeUrl
235
- ? 'md'
236
- : 'text');
238
+ ? (rawFormatOpt ?? "text")
239
+ : extractMode && inputTarget.kind === "url" && !isYoutubeUrl
240
+ ? "md"
241
+ : "text");
237
242
  const runSettings = resolveCliRunSettings({
238
243
  length: String(program.opts().length),
239
244
  firecrawl: String(program.opts().firecrawl),
240
- markdownMode: typeof program.opts().markdownMode === 'string' ? program.opts().markdownMode : undefined,
241
- markdown: typeof program.opts().markdown === 'string' ? program.opts().markdown : undefined,
245
+ markdownMode: typeof program.opts().markdownMode === "string" ? program.opts().markdownMode : undefined,
246
+ markdown: typeof program.opts().markdown === "string" ? program.opts().markdown : undefined,
242
247
  format,
243
248
  preprocess: String(program.opts().preprocess),
244
249
  youtube: String(program.opts().youtube),
245
250
  timeout: String(program.opts().timeout),
246
251
  retries: String(program.opts().retries),
247
- maxOutputTokens: typeof program.opts().maxOutputTokens === 'string'
252
+ maxOutputTokens: typeof program.opts().maxOutputTokens === "string"
248
253
  ? program.opts().maxOutputTokens
249
254
  : program.opts().maxOutputTokens != null
250
255
  ? String(program.opts().maxOutputTokens)
@@ -252,31 +257,31 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
252
257
  });
253
258
  const { youtubeMode, lengthArg, maxOutputTokensArg, timeoutMs, retries, preprocessMode, firecrawlMode: requestedFirecrawlMode, markdownMode, } = runSettings;
254
259
  if (extractMode && lengthExplicitlySet && !json && isRichTty(stderr)) {
255
- stderr.write('Warning: --length is ignored with --extract (no summary is generated).\n');
260
+ stderr.write("Warning: --length is ignored with --extract (no summary is generated).\n");
256
261
  }
257
- const metricsExplicitlySet = normalizedArgv.some((arg) => arg === '--metrics' || arg.startsWith('--metrics='));
258
- const metricsMode = parseMetricsMode(debug && !metricsExplicitlySet ? 'detailed' : program.opts().metrics);
259
- const metricsEnabled = metricsMode !== 'off';
260
- const metricsDetailed = metricsMode === 'detailed';
262
+ const metricsExplicitlySet = normalizedArgv.some((arg) => arg === "--metrics" || arg.startsWith("--metrics="));
263
+ const metricsMode = parseMetricsMode(debug && !metricsExplicitlySet ? "detailed" : program.opts().metrics);
264
+ const metricsEnabled = metricsMode !== "off";
265
+ const metricsDetailed = metricsMode === "detailed";
261
266
  const shouldComputeReport = metricsEnabled;
262
- const _firecrawlExplicitlySet = normalizedArgv.some((arg) => arg === '--firecrawl' || arg.startsWith('--firecrawl='));
263
- const markdownModeExplicitlySet = normalizedArgv.some((arg) => arg === '--markdown-mode' ||
264
- arg.startsWith('--markdown-mode=') ||
265
- arg === '--markdown' ||
266
- arg.startsWith('--markdown='));
267
- const modelArg = typeof program.opts().model === 'string' ? program.opts().model : null;
268
- const cliProviderArg = typeof cliProviderArgRaw === 'string' && cliProviderArgRaw.trim().length > 0
267
+ const _firecrawlExplicitlySet = normalizedArgv.some((arg) => arg === "--firecrawl" || arg.startsWith("--firecrawl="));
268
+ const markdownModeExplicitlySet = normalizedArgv.some((arg) => arg === "--markdown-mode" ||
269
+ arg.startsWith("--markdown-mode=") ||
270
+ arg === "--markdown" ||
271
+ arg.startsWith("--markdown="));
272
+ const modelArg = typeof program.opts().model === "string" ? program.opts().model : null;
273
+ const cliProviderArg = typeof cliProviderArgRaw === "string" && cliProviderArgRaw.trim().length > 0
269
274
  ? parseCliProviderArg(cliProviderArgRaw)
270
275
  : null;
271
276
  if (cliFlagPresent && modelArg) {
272
- throw new Error('Use either --model or --cli (not both).');
277
+ throw new Error("Use either --model or --cli (not both).");
273
278
  }
274
279
  const explicitModelArg = cliProviderArg
275
280
  ? `cli/${cliProviderArg}`
276
281
  : cliFlagPresent
277
- ? 'auto'
282
+ ? "auto"
278
283
  : modelArg;
279
- const { config, configPath, outputLanguage, openaiWhisperUsdPerMinute, videoMode, cliConfigForRun, configForCli, openaiUseChatCompletions, configModelLabel, apiKey, openrouterApiKey, openrouterConfigured, openaiTranscriptionKey, xaiApiKey, googleApiKey, anthropicApiKey, zaiApiKey, zaiBaseUrl, providerBaseUrls, firecrawlApiKey, firecrawlConfigured, googleConfigured, anthropicConfigured, apifyToken, ytDlpPath, falApiKey, cliAvailability, envForAuto, } = resolveRunContextState({
284
+ const { config, configPath, outputLanguage, openaiWhisperUsdPerMinute, videoMode, cliConfigForRun, configForCli, openaiUseChatCompletions, configModelLabel, apiKey, openrouterApiKey, openrouterConfigured, groqApiKey, openaiTranscriptionKey, xaiApiKey, googleApiKey, anthropicApiKey, zaiApiKey, zaiBaseUrl, providerBaseUrls, firecrawlApiKey, firecrawlConfigured, googleConfigured, anthropicConfigured, apifyToken, ytDlpPath, ytDlpCookiesFromBrowser, falApiKey, cliAvailability, envForAuto, } = resolveRunContextState({
280
285
  env,
281
286
  envForRun,
282
287
  programOpts: program.opts(),
@@ -291,15 +296,15 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
291
296
  config: config?.ui?.theme,
292
297
  });
293
298
  envForRun.SUMMARIZE_THEME = themeName;
294
- if (!promptOverride && typeof config?.prompt === 'string' && config.prompt.trim().length > 0) {
299
+ if (!promptOverride && typeof config?.prompt === "string" && config.prompt.trim().length > 0) {
295
300
  promptOverride = config.prompt.trim();
296
301
  }
297
- const slidesExplicitlySet = normalizedArgv.some((arg) => arg === '--slides' || arg === '--no-slides' || arg.startsWith('--slides='));
298
- const slidesOcrExplicitlySet = normalizedArgv.some((arg) => arg === '--slides-ocr' || arg === '--no-slides-ocr' || arg.startsWith('--slides-ocr='));
299
- const slidesDirExplicitlySet = normalizedArgv.some((arg) => arg === '--slides-dir' || arg.startsWith('--slides-dir='));
300
- const slidesSceneThresholdExplicitlySet = normalizedArgv.some((arg) => arg === '--slides-scene-threshold' || arg.startsWith('--slides-scene-threshold='));
301
- const slidesMaxExplicitlySet = normalizedArgv.some((arg) => arg === '--slides-max' || arg.startsWith('--slides-max='));
302
- const slidesMinDurationExplicitlySet = normalizedArgv.some((arg) => arg === '--slides-min-duration' || arg.startsWith('--slides-min-duration='));
302
+ const slidesExplicitlySet = normalizedArgv.some((arg) => arg === "--slides" || arg === "--no-slides" || arg.startsWith("--slides="));
303
+ const slidesOcrExplicitlySet = normalizedArgv.some((arg) => arg === "--slides-ocr" || arg === "--no-slides-ocr" || arg.startsWith("--slides-ocr="));
304
+ const slidesDirExplicitlySet = normalizedArgv.some((arg) => arg === "--slides-dir" || arg.startsWith("--slides-dir="));
305
+ const slidesSceneThresholdExplicitlySet = normalizedArgv.some((arg) => arg === "--slides-scene-threshold" || arg.startsWith("--slides-scene-threshold="));
306
+ const slidesMaxExplicitlySet = normalizedArgv.some((arg) => arg === "--slides-max" || arg.startsWith("--slides-max="));
307
+ const slidesMinDurationExplicitlySet = normalizedArgv.some((arg) => arg === "--slides-min-duration" || arg.startsWith("--slides-min-duration="));
303
308
  const slidesConfig = config?.slides;
304
309
  const slidesSettings = resolveSlideSettings({
305
310
  slides: slidesExplicitlySet
@@ -314,7 +319,7 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
314
319
  slidesSceneThreshold: slidesSceneThresholdExplicitlySet
315
320
  ? program.opts().slidesSceneThreshold
316
321
  : (slidesConfig?.sceneThreshold ?? program.opts().slidesSceneThreshold),
317
- slidesSceneThresholdExplicit: slidesSceneThresholdExplicitlySet || typeof slidesConfig?.sceneThreshold === 'number',
322
+ slidesSceneThresholdExplicit: slidesSceneThresholdExplicitlySet || typeof slidesConfig?.sceneThreshold === "number",
318
323
  slidesMax: slidesMaxExplicitlySet
319
324
  ? program.opts().slidesMax
320
325
  : (slidesConfig?.max ?? program.opts().slidesMax),
@@ -323,14 +328,14 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
323
328
  : (slidesConfig?.minDuration ?? program.opts().slidesMinDuration),
324
329
  cwd: process.cwd(),
325
330
  });
326
- if (slidesSettings && inputTarget.kind !== 'url') {
327
- throw new Error('--slides is only supported for URL inputs');
331
+ if (slidesSettings && inputTarget.kind !== "url") {
332
+ throw new Error("--slides is only supported for URL inputs");
328
333
  }
329
334
  const transcriptTimestamps = Boolean(program.opts().timestamps) || Boolean(slidesSettings);
330
- const lengthInstruction = promptOverride && lengthExplicitlySet && lengthArg.kind === 'chars'
335
+ const lengthInstruction = promptOverride && lengthExplicitlySet && lengthArg.kind === "chars"
331
336
  ? `Output is ${lengthArg.maxCharacters.toLocaleString()} characters.`
332
337
  : null;
333
- const languageInstruction = promptOverride && languageExplicitlySet && outputLanguage.kind === 'fixed'
338
+ const languageInstruction = promptOverride && languageExplicitlySet && outputLanguage.kind === "fixed"
334
339
  ? `Output should be ${outputLanguage.label}.`
335
340
  : null;
336
341
  const transcriptNamespace = `yt:${youtubeMode}`;
@@ -346,11 +351,19 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
346
351
  noMediaCacheFlag,
347
352
  });
348
353
  try {
349
- if (markdownModeExplicitlySet && format !== 'markdown') {
350
- throw new Error('--markdown-mode is only supported with --format md');
354
+ if (markdownModeExplicitlySet && format !== "markdown") {
355
+ throw new Error("--markdown-mode is only supported with --format md");
351
356
  }
352
- if (markdownModeExplicitlySet && inputTarget.kind !== 'url') {
353
- throw new Error('--markdown-mode is only supported for URL inputs');
357
+ if (markdownModeExplicitlySet &&
358
+ inputTarget.kind !== "url" &&
359
+ inputTarget.kind !== "file" &&
360
+ inputTarget.kind !== "stdin") {
361
+ throw new Error("--markdown-mode is only supported for URL, file, or stdin inputs");
362
+ }
363
+ if (markdownModeExplicitlySet &&
364
+ (inputTarget.kind === "file" || inputTarget.kind === "stdin") &&
365
+ markdownMode !== "llm") {
366
+ throw new Error("Only --markdown-mode llm is supported for file/stdin inputs; other modes require a URL");
354
367
  }
355
368
  const metrics = createRunMetrics({
356
369
  env,
@@ -358,7 +371,7 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
358
371
  maxOutputTokensArg,
359
372
  });
360
373
  const { llmCalls, trackedFetch, buildReport, estimateCostUsd, getLiteLlmCatalog, resolveMaxOutputTokensForCall, resolveMaxInputTokensForCall, setTranscriptionCost, } = metrics;
361
- const { requestedModel, requestedModelInput, requestedModelLabel, isNamedModelSelection, wantsFreeNamedModel, configForModelSelection, isFallbackModel, } = resolveModelSelection({
374
+ const { requestedModel, requestedModelInput, requestedModelLabel, isNamedModelSelection, isImplicitAutoSelection, wantsFreeNamedModel, configForModelSelection, isFallbackModel, } = resolveModelSelection({
362
375
  config,
363
376
  configForCli,
364
377
  configPath,
@@ -371,23 +384,28 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
371
384
  enabled: verboseColor,
372
385
  trueColor: resolveTrueColor(envForRun),
373
386
  });
374
- const renderSpinnerStatus = (label, detail = '') => `${themeForStderr.label(label)}${themeForStderr.dim(detail)}`;
375
- const renderSpinnerStatusWithModel = (label, modelId) => `${themeForStderr.label(label)}${themeForStderr.dim(' (model: ')}${themeForStderr.accent(modelId)}${themeForStderr.dim(')…')}`;
387
+ const renderSpinnerStatus = (label, detail = "") => `${themeForStderr.label(label)}${themeForStderr.dim(detail)}`;
388
+ const renderSpinnerStatusWithModel = (label, modelId) => `${themeForStderr.label(label)}${themeForStderr.dim(" (model: ")}${themeForStderr.accent(modelId)}${themeForStderr.dim(")…")}`;
376
389
  const { streamingEnabled } = resolveStreamSettings({
377
390
  streamMode,
378
391
  stdout,
379
392
  json,
380
393
  extractMode,
381
394
  });
382
- if (extractMode && inputTarget.kind !== 'url') {
383
- throw new Error('--extract is only supported for website/YouTube URLs');
395
+ if (extractMode &&
396
+ inputTarget.kind === "file" &&
397
+ !isTranscribableExtension(inputTarget.filePath)) {
398
+ throw new Error("--extract for local files is only supported for media files (MP3, MP4, WAV, etc.)");
399
+ }
400
+ if (extractMode && inputTarget.kind === "stdin") {
401
+ throw new Error("--extract is not supported for piped stdin input");
384
402
  }
385
403
  // Progress UI (spinner + OSC progress) is shown on stderr. Before writing to stdout (including
386
404
  // streaming output), we stop + clear progress via the progress gate to keep scrollback clean.
387
405
  const progressEnabled = isRichTty(stderr) && !verbose && !json;
388
406
  const progressGate = createProgressGate();
389
407
  const { clearProgressForStdout, restoreProgressAfterStdout, setClearProgressBeforeStdout, clearProgressIfCurrent, } = progressGate;
390
- const fixedModelSpec = requestedModel.kind === 'fixed' ? requestedModel : null;
408
+ const fixedModelSpec = requestedModel.kind === "fixed" ? requestedModel : null;
391
409
  const desiredOutputTokens = resolveDesiredOutputTokens({ lengthArg, maxOutputTokensArg });
392
410
  const summaryEngine = createSummaryEngine({
393
411
  env,
@@ -437,7 +455,7 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
437
455
  if (filtered.length === 0)
438
456
  return;
439
457
  clearProgressForStdout();
440
- stderr.write(`${themeForStderr.dim(`via ${filtered.join(', ')}`)}\n`);
458
+ stderr.write(`${themeForStderr.dim(`via ${filtered.join(", ")}`)}\n`);
441
459
  restoreProgressAfterStdout?.();
442
460
  };
443
461
  const assetSummaryContext = {
@@ -459,6 +477,8 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
459
477
  lengthInstruction,
460
478
  languageInstruction,
461
479
  isFallbackModel,
480
+ isImplicitAutoSelection,
481
+ allowAutoCliFallback: false,
462
482
  desiredOutputTokens,
463
483
  envForAuto,
464
484
  configForModelSelection,
@@ -517,6 +537,21 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
517
537
  setClearProgressBeforeStdout,
518
538
  clearProgressIfCurrent,
519
539
  };
540
+ if (inputTarget.kind === "stdin") {
541
+ const stdinTempFile = await createTempFileFromStdin({
542
+ stream: stdin ?? process.stdin,
543
+ });
544
+ try {
545
+ const stdinInputTarget = { kind: "file", filePath: stdinTempFile.filePath };
546
+ if (await handleFileInput(assetInputContext, stdinInputTarget)) {
547
+ return;
548
+ }
549
+ throw new Error("Failed to process stdin input");
550
+ }
551
+ finally {
552
+ await stdinTempFile.cleanup();
553
+ }
554
+ }
520
555
  if (await handleFileInput(assetInputContext, inputTarget)) {
521
556
  return;
522
557
  }
@@ -524,7 +559,7 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
524
559
  (await withUrlAsset(assetInputContext, url, isYoutubeUrl, async ({ loaded, spinner }) => {
525
560
  if (extractMode) {
526
561
  if (progressEnabled)
527
- spinner.setText(renderSpinnerStatus('Extracting text'));
562
+ spinner.setText(renderSpinnerStatus("Extracting text"));
528
563
  const extracted = await extractAssetContent({
529
564
  ctx: {
530
565
  env,
@@ -572,22 +607,22 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
572
607
  return;
573
608
  }
574
609
  if (progressEnabled)
575
- spinner.setText(renderSpinnerStatus('Summarizing'));
610
+ spinner.setText(renderSpinnerStatus("Summarizing"));
576
611
  await summarizeAsset({
577
- sourceKind: 'asset-url',
612
+ sourceKind: "asset-url",
578
613
  sourceLabel: loaded.sourceLabel,
579
614
  attachment: loaded.attachment,
580
615
  onModelChosen: (modelId) => {
581
616
  if (!progressEnabled)
582
617
  return;
583
- spinner.setText(renderSpinnerStatusWithModel('Summarizing', modelId));
618
+ spinner.setText(renderSpinnerStatusWithModel("Summarizing", modelId));
584
619
  },
585
620
  });
586
621
  }))) {
587
622
  return;
588
623
  }
589
624
  if (!url) {
590
- throw new Error('Only HTTP and HTTPS URLs can be summarized');
625
+ throw new Error("Only HTTP and HTTPS URLs can be summarized");
591
626
  }
592
627
  const urlFlowContext = {
593
628
  io: {
@@ -641,6 +676,8 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
641
676
  requestedModelLabel,
642
677
  fixedModelSpec,
643
678
  isFallbackModel,
679
+ isImplicitAutoSelection,
680
+ allowAutoCliFallback: false,
644
681
  isNamedModelSelection,
645
682
  wantsFreeNamedModel,
646
683
  desiredOutputTokens,
@@ -665,7 +702,9 @@ export async function runCli(argv, { env, fetch, execFile: execFileOverride, std
665
702
  firecrawlApiKey,
666
703
  apifyToken,
667
704
  ytDlpPath,
705
+ ytDlpCookiesFromBrowser,
668
706
  falApiKey,
707
+ groqApiKey,
669
708
  openaiTranscriptionKey,
670
709
  },
671
710
  summaryEngine,