@steipete/summarize 0.11.1 → 0.13.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 (427) hide show
  1. package/CHANGELOG.md +73 -1
  2. package/README.md +102 -32
  3. package/dist/cli.js +1 -1
  4. package/dist/esm/cache-keys.js +83 -0
  5. package/dist/esm/cache-keys.js.map +1 -0
  6. package/dist/esm/cache-slides-cleanup.js +47 -0
  7. package/dist/esm/cache-slides-cleanup.js.map +1 -0
  8. package/dist/esm/cache.js +15 -92
  9. package/dist/esm/cache.js.map +1 -1
  10. package/dist/esm/config/env.js +49 -0
  11. package/dist/esm/config/env.js.map +1 -0
  12. package/dist/esm/config/model.js +193 -0
  13. package/dist/esm/config/model.js.map +1 -0
  14. package/dist/esm/config/parse-helpers.js +55 -0
  15. package/dist/esm/config/parse-helpers.js.map +1 -0
  16. package/dist/esm/config/read.js +83 -0
  17. package/dist/esm/config/read.js.map +1 -0
  18. package/dist/esm/config/sections.js +472 -0
  19. package/dist/esm/config/sections.js.map +1 -0
  20. package/dist/esm/config/types.js +2 -0
  21. package/dist/esm/config/types.js.map +1 -0
  22. package/dist/esm/config.js +24 -807
  23. package/dist/esm/config.js.map +1 -1
  24. package/dist/esm/content/asset.js +2 -2
  25. package/dist/esm/content/asset.js.map +1 -1
  26. package/dist/esm/costs.js.map +1 -1
  27. package/dist/esm/daemon/agent-model.js +283 -0
  28. package/dist/esm/daemon/agent-model.js.map +1 -0
  29. package/dist/esm/daemon/agent-request.js +87 -0
  30. package/dist/esm/daemon/agent-request.js.map +1 -0
  31. package/dist/esm/daemon/agent.js +42 -243
  32. package/dist/esm/daemon/agent.js.map +1 -1
  33. package/dist/esm/daemon/chat.js +118 -9
  34. package/dist/esm/daemon/chat.js.map +1 -1
  35. package/dist/esm/daemon/cli.js +121 -9
  36. package/dist/esm/daemon/cli.js.map +1 -1
  37. package/dist/esm/daemon/config.js +65 -9
  38. package/dist/esm/daemon/config.js.map +1 -1
  39. package/dist/esm/daemon/env-snapshot.js +6 -0
  40. package/dist/esm/daemon/env-snapshot.js.map +1 -1
  41. package/dist/esm/daemon/flow-context.js +84 -74
  42. package/dist/esm/daemon/flow-context.js.map +1 -1
  43. package/dist/esm/daemon/models.js +26 -0
  44. package/dist/esm/daemon/models.js.map +1 -1
  45. package/dist/esm/daemon/process-registry.js.map +1 -1
  46. package/dist/esm/daemon/schtasks.js +101 -5
  47. package/dist/esm/daemon/schtasks.js.map +1 -1
  48. package/dist/esm/daemon/server-admin-routes.js +134 -0
  49. package/dist/esm/daemon/server-admin-routes.js.map +1 -0
  50. package/dist/esm/daemon/server-agent-route.js +104 -0
  51. package/dist/esm/daemon/server-agent-route.js.map +1 -0
  52. package/dist/esm/daemon/server-http.js +89 -0
  53. package/dist/esm/daemon/server-http.js.map +1 -0
  54. package/dist/esm/daemon/server-session-routes.js +209 -0
  55. package/dist/esm/daemon/server-session-routes.js.map +1 -0
  56. package/dist/esm/daemon/server-session.js +118 -0
  57. package/dist/esm/daemon/server-session.js.map +1 -0
  58. package/dist/esm/daemon/server-sse.js +28 -0
  59. package/dist/esm/daemon/server-sse.js.map +1 -0
  60. package/dist/esm/daemon/server-summarize-execution.js +357 -0
  61. package/dist/esm/daemon/server-summarize-execution.js.map +1 -0
  62. package/dist/esm/daemon/server-summarize-request.js +119 -0
  63. package/dist/esm/daemon/server-summarize-request.js.map +1 -0
  64. package/dist/esm/daemon/server.js +79 -1121
  65. package/dist/esm/daemon/server.js.map +1 -1
  66. package/dist/esm/daemon/summarize-progress.js +1 -1
  67. package/dist/esm/daemon/summarize-progress.js.map +1 -1
  68. package/dist/esm/daemon/summarize.js.map +1 -1
  69. package/dist/esm/daemon/windows-container.js +21 -0
  70. package/dist/esm/daemon/windows-container.js.map +1 -0
  71. package/dist/esm/llm/cli-exec.js +75 -0
  72. package/dist/esm/llm/cli-exec.js.map +1 -0
  73. package/dist/esm/llm/cli-provider-output.js +415 -0
  74. package/dist/esm/llm/cli-provider-output.js.map +1 -0
  75. package/dist/esm/llm/cli.js +97 -218
  76. package/dist/esm/llm/cli.js.map +1 -1
  77. package/dist/esm/llm/generate-text-document.js +109 -0
  78. package/dist/esm/llm/generate-text-document.js.map +1 -0
  79. package/dist/esm/llm/generate-text-shared.js +121 -0
  80. package/dist/esm/llm/generate-text-shared.js.map +1 -0
  81. package/dist/esm/llm/generate-text-stream.js +291 -0
  82. package/dist/esm/llm/generate-text-stream.js.map +1 -0
  83. package/dist/esm/llm/generate-text.js +172 -480
  84. package/dist/esm/llm/generate-text.js.map +1 -1
  85. package/dist/esm/llm/github-models.js +45 -0
  86. package/dist/esm/llm/github-models.js.map +1 -0
  87. package/dist/esm/llm/html-to-markdown.js.map +1 -1
  88. package/dist/esm/llm/model-id.js +37 -20
  89. package/dist/esm/llm/model-id.js.map +1 -1
  90. package/dist/esm/llm/provider-capabilities.js +2 -0
  91. package/dist/esm/llm/provider-capabilities.js.map +1 -0
  92. package/dist/esm/llm/provider-profile.js +184 -0
  93. package/dist/esm/llm/provider-profile.js.map +1 -0
  94. package/dist/esm/llm/providers/google.js +42 -5
  95. package/dist/esm/llm/providers/google.js.map +1 -1
  96. package/dist/esm/llm/providers/models.js +19 -1
  97. package/dist/esm/llm/providers/models.js.map +1 -1
  98. package/dist/esm/llm/providers/openai.js +243 -5
  99. package/dist/esm/llm/providers/openai.js.map +1 -1
  100. package/dist/esm/llm/transcript-to-markdown.js.map +1 -1
  101. package/dist/esm/media-cache.js +3 -0
  102. package/dist/esm/media-cache.js.map +1 -1
  103. package/dist/esm/model-auto-cli.js +91 -0
  104. package/dist/esm/model-auto-cli.js.map +1 -0
  105. package/dist/esm/model-auto-rules.js +86 -0
  106. package/dist/esm/model-auto-rules.js.map +1 -0
  107. package/dist/esm/model-auto.js +10 -245
  108. package/dist/esm/model-auto.js.map +1 -1
  109. package/dist/esm/model-spec.js +62 -19
  110. package/dist/esm/model-spec.js.map +1 -1
  111. package/dist/esm/refresh-free.js +1 -1
  112. package/dist/esm/refresh-free.js.map +1 -1
  113. package/dist/esm/run/attachments.js +1 -1
  114. package/dist/esm/run/attachments.js.map +1 -1
  115. package/dist/esm/run/bird/exec.js +23 -0
  116. package/dist/esm/run/bird/exec.js.map +1 -0
  117. package/dist/esm/run/bird/media.js +171 -0
  118. package/dist/esm/run/bird/media.js.map +1 -0
  119. package/dist/esm/run/bird/parse.js +82 -0
  120. package/dist/esm/run/bird/parse.js.map +1 -0
  121. package/dist/esm/run/bird/types.js +2 -0
  122. package/dist/esm/run/bird/types.js.map +1 -0
  123. package/dist/esm/run/bird.js +86 -144
  124. package/dist/esm/run/bird.js.map +1 -1
  125. package/dist/esm/run/cache-state.js.map +1 -1
  126. package/dist/esm/run/cli-fallback-state.js +6 -1
  127. package/dist/esm/run/cli-fallback-state.js.map +1 -1
  128. package/dist/esm/run/constants.js +2 -1
  129. package/dist/esm/run/constants.js.map +1 -1
  130. package/dist/esm/run/env.js +24 -3
  131. package/dist/esm/run/env.js.map +1 -1
  132. package/dist/esm/run/finish-line-labels.js +76 -0
  133. package/dist/esm/run/finish-line-labels.js.map +1 -0
  134. package/dist/esm/run/finish-line-lengths.js +96 -0
  135. package/dist/esm/run/finish-line-lengths.js.map +1 -0
  136. package/dist/esm/run/finish-line.js +3 -169
  137. package/dist/esm/run/finish-line.js.map +1 -1
  138. package/dist/esm/run/flows/asset/extract.js.map +1 -1
  139. package/dist/esm/run/flows/asset/input.js +1 -1
  140. package/dist/esm/run/flows/asset/input.js.map +1 -1
  141. package/dist/esm/run/flows/asset/media.js +19 -10
  142. package/dist/esm/run/flows/asset/media.js.map +1 -1
  143. package/dist/esm/run/flows/asset/output.js.map +1 -1
  144. package/dist/esm/run/flows/asset/preprocess.js.map +1 -1
  145. package/dist/esm/run/flows/asset/summary-attempts.js +117 -0
  146. package/dist/esm/run/flows/asset/summary-attempts.js.map +1 -0
  147. package/dist/esm/run/flows/asset/summary.js +30 -107
  148. package/dist/esm/run/flows/asset/summary.js.map +1 -1
  149. package/dist/esm/run/flows/url/extract.js +7 -4
  150. package/dist/esm/run/flows/url/extract.js.map +1 -1
  151. package/dist/esm/run/flows/url/extraction-session.js +174 -0
  152. package/dist/esm/run/flows/url/extraction-session.js.map +1 -0
  153. package/dist/esm/run/flows/url/fetch-options.js +32 -0
  154. package/dist/esm/run/flows/url/fetch-options.js.map +1 -0
  155. package/dist/esm/run/flows/url/flow-progress.js +123 -0
  156. package/dist/esm/run/flows/url/flow-progress.js.map +1 -0
  157. package/dist/esm/run/flows/url/flow.js +70 -462
  158. package/dist/esm/run/flows/url/flow.js.map +1 -1
  159. package/dist/esm/run/flows/url/markdown.js +38 -3
  160. package/dist/esm/run/flows/url/markdown.js.map +1 -1
  161. package/dist/esm/run/flows/url/progress-status-state.js +28 -0
  162. package/dist/esm/run/flows/url/progress-status-state.js.map +1 -0
  163. package/dist/esm/run/flows/url/progress-status.js +51 -0
  164. package/dist/esm/run/flows/url/progress-status.js.map +1 -0
  165. package/dist/esm/run/flows/url/slides-output-render.js +78 -0
  166. package/dist/esm/run/flows/url/slides-output-render.js.map +1 -0
  167. package/dist/esm/run/flows/url/slides-output-state.js +86 -0
  168. package/dist/esm/run/flows/url/slides-output-state.js.map +1 -0
  169. package/dist/esm/run/flows/url/slides-output-stream.js +271 -0
  170. package/dist/esm/run/flows/url/slides-output-stream.js.map +1 -0
  171. package/dist/esm/run/flows/url/slides-output.js +29 -422
  172. package/dist/esm/run/flows/url/slides-output.js.map +1 -1
  173. package/dist/esm/run/flows/url/slides-session.js +159 -0
  174. package/dist/esm/run/flows/url/slides-session.js.map +1 -0
  175. package/dist/esm/run/flows/url/slides-text-markdown.js +431 -0
  176. package/dist/esm/run/flows/url/slides-text-markdown.js.map +1 -0
  177. package/dist/esm/run/flows/url/slides-text-transcript.js +199 -0
  178. package/dist/esm/run/flows/url/slides-text-transcript.js.map +1 -0
  179. package/dist/esm/run/flows/url/slides-text-types.js +2 -0
  180. package/dist/esm/run/flows/url/slides-text-types.js.map +1 -0
  181. package/dist/esm/run/flows/url/slides-text.js +2 -627
  182. package/dist/esm/run/flows/url/slides-text.js.map +1 -1
  183. package/dist/esm/run/flows/url/summary-finish.js +40 -0
  184. package/dist/esm/run/flows/url/summary-finish.js.map +1 -0
  185. package/dist/esm/run/flows/url/summary-json.js +32 -0
  186. package/dist/esm/run/flows/url/summary-json.js.map +1 -0
  187. package/dist/esm/run/flows/url/summary-prompt.js +147 -0
  188. package/dist/esm/run/flows/url/summary-prompt.js.map +1 -0
  189. package/dist/esm/run/flows/url/summary-resolution.js +327 -0
  190. package/dist/esm/run/flows/url/summary-resolution.js.map +1 -0
  191. package/dist/esm/run/flows/url/summary-timestamps.js +136 -0
  192. package/dist/esm/run/flows/url/summary-timestamps.js.map +1 -0
  193. package/dist/esm/run/flows/url/summary.js +139 -667
  194. package/dist/esm/run/flows/url/summary.js.map +1 -1
  195. package/dist/esm/run/flows/url/types.js +31 -1
  196. package/dist/esm/run/flows/url/types.js.map +1 -1
  197. package/dist/esm/run/flows/url/video-only.js +68 -0
  198. package/dist/esm/run/flows/url/video-only.js.map +1 -0
  199. package/dist/esm/run/help.js +15 -5
  200. package/dist/esm/run/help.js.map +1 -1
  201. package/dist/esm/run/markdown-transforms.js +89 -0
  202. package/dist/esm/run/markdown-transforms.js.map +1 -0
  203. package/dist/esm/run/markdown.js +1 -96
  204. package/dist/esm/run/markdown.js.map +1 -1
  205. package/dist/esm/run/run-config.js +1 -1
  206. package/dist/esm/run/run-config.js.map +1 -1
  207. package/dist/esm/run/run-env.js +28 -7
  208. package/dist/esm/run/run-env.js.map +1 -1
  209. package/dist/esm/run/run-models.js +35 -5
  210. package/dist/esm/run/run-models.js.map +1 -1
  211. package/dist/esm/run/run-settings-parse.js +77 -0
  212. package/dist/esm/run/run-settings-parse.js.map +1 -0
  213. package/dist/esm/run/run-settings.js +7 -72
  214. package/dist/esm/run/run-settings.js.map +1 -1
  215. package/dist/esm/run/runner-contexts.js +122 -0
  216. package/dist/esm/run/runner-contexts.js.map +1 -0
  217. package/dist/esm/run/runner-execution.js +82 -0
  218. package/dist/esm/run/runner-execution.js.map +1 -0
  219. package/dist/esm/run/runner-flags.js +97 -0
  220. package/dist/esm/run/runner-flags.js.map +1 -0
  221. package/dist/esm/run/runner-plan.js +369 -0
  222. package/dist/esm/run/runner-plan.js.map +1 -0
  223. package/dist/esm/run/runner-setup.js +109 -0
  224. package/dist/esm/run/runner-setup.js.map +1 -0
  225. package/dist/esm/run/runner-slides.js +49 -0
  226. package/dist/esm/run/runner-slides.js.map +1 -0
  227. package/dist/esm/run/runner.js +53 -692
  228. package/dist/esm/run/runner.js.map +1 -1
  229. package/dist/esm/run/slides-cli.js +3 -2
  230. package/dist/esm/run/slides-cli.js.map +1 -1
  231. package/dist/esm/run/slides-render.js +5 -2
  232. package/dist/esm/run/slides-render.js.map +1 -1
  233. package/dist/esm/run/stdin-temp-file.js +1 -1
  234. package/dist/esm/run/stdin-temp-file.js.map +1 -1
  235. package/dist/esm/run/streaming.js +2 -0
  236. package/dist/esm/run/streaming.js.map +1 -1
  237. package/dist/esm/run/summary-engine.js +50 -10
  238. package/dist/esm/run/summary-engine.js.map +1 -1
  239. package/dist/esm/run/summary-llm.js +2 -1
  240. package/dist/esm/run/summary-llm.js.map +1 -1
  241. package/dist/esm/run/terminal.js +4 -1
  242. package/dist/esm/run/terminal.js.map +1 -1
  243. package/dist/esm/run/transcriber-cli.js +1 -1
  244. package/dist/esm/run/transcriber-cli.js.map +1 -1
  245. package/dist/esm/shared/slides-text.js +2 -0
  246. package/dist/esm/shared/slides-text.js.map +1 -0
  247. package/dist/esm/slides/download.js +242 -0
  248. package/dist/esm/slides/download.js.map +1 -0
  249. package/dist/esm/slides/extract-finalize.js +98 -0
  250. package/dist/esm/slides/extract-finalize.js.map +1 -0
  251. package/dist/esm/slides/extract.js +105 -1685
  252. package/dist/esm/slides/extract.js.map +1 -1
  253. package/dist/esm/slides/frame-extraction.js +372 -0
  254. package/dist/esm/slides/frame-extraction.js.map +1 -0
  255. package/dist/esm/slides/index.js +2 -1
  256. package/dist/esm/slides/index.js.map +1 -1
  257. package/dist/esm/slides/ingest.js +194 -0
  258. package/dist/esm/slides/ingest.js.map +1 -0
  259. package/dist/esm/slides/ocr.js +91 -0
  260. package/dist/esm/slides/ocr.js.map +1 -0
  261. package/dist/esm/slides/process.js +218 -0
  262. package/dist/esm/slides/process.js.map +1 -0
  263. package/dist/esm/slides/scene-detection.js +387 -0
  264. package/dist/esm/slides/scene-detection.js.map +1 -0
  265. package/dist/esm/slides/source-id.js +42 -0
  266. package/dist/esm/slides/source-id.js.map +1 -0
  267. package/dist/esm/slides/source.js +80 -0
  268. package/dist/esm/slides/source.js.map +1 -0
  269. package/dist/esm/tty/progress/fetch-html.js +6 -0
  270. package/dist/esm/tty/progress/fetch-html.js.map +1 -1
  271. package/dist/esm/tty/progress/transcript-state.js +202 -0
  272. package/dist/esm/tty/progress/transcript-state.js.map +1 -0
  273. package/dist/esm/tty/progress/transcript.js +43 -194
  274. package/dist/esm/tty/progress/transcript.js.map +1 -1
  275. package/dist/esm/tty/spinner.js +17 -3
  276. package/dist/esm/tty/spinner.js.map +1 -1
  277. package/dist/esm/tty/website-progress.js +16 -3
  278. package/dist/esm/tty/website-progress.js.map +1 -1
  279. package/dist/esm/version.js +1 -1
  280. package/dist/types/cache-keys.d.ts +44 -0
  281. package/dist/types/cache-slides-cleanup.d.ts +1 -0
  282. package/dist/types/cache.d.ts +2 -10
  283. package/dist/types/config/env.d.ts +6 -0
  284. package/dist/types/config/model.d.ts +3 -0
  285. package/dist/types/config/parse-helpers.d.ts +7 -0
  286. package/dist/types/config/read.d.ts +2 -0
  287. package/dist/types/config/sections.d.ts +34 -0
  288. package/dist/types/config/types.d.ts +238 -0
  289. package/dist/types/config.d.ts +3 -209
  290. package/dist/types/costs.d.ts +1 -1
  291. package/dist/types/daemon/agent-model.d.ts +40 -0
  292. package/dist/types/daemon/agent-request.d.ts +14 -0
  293. package/dist/types/daemon/chat.d.ts +3 -1
  294. package/dist/types/daemon/config.d.ts +13 -2
  295. package/dist/types/daemon/env-snapshot.d.ts +1 -1
  296. package/dist/types/daemon/flow-context.d.ts +2 -2
  297. package/dist/types/daemon/models.d.ts +3 -0
  298. package/dist/types/daemon/schtasks.d.ts +2 -1
  299. package/dist/types/daemon/server-admin-routes.d.ts +22 -0
  300. package/dist/types/daemon/server-agent-route.d.ts +9 -0
  301. package/dist/types/daemon/server-http.d.ts +10 -0
  302. package/dist/types/daemon/server-session-routes.d.ts +11 -0
  303. package/dist/types/daemon/server-session.d.ts +52 -0
  304. package/dist/types/daemon/server-sse.d.ts +12 -0
  305. package/dist/types/daemon/server-summarize-execution.d.ts +70 -0
  306. package/dist/types/daemon/server-summarize-request.d.ts +36 -0
  307. package/dist/types/daemon/server.d.ts +4 -4
  308. package/dist/types/daemon/summarize.d.ts +1 -1
  309. package/dist/types/daemon/windows-container.d.ts +1 -0
  310. package/dist/types/llm/cli-exec.d.ts +13 -0
  311. package/dist/types/llm/cli-provider-output.d.ts +25 -0
  312. package/dist/types/llm/generate-text-document.d.ts +35 -0
  313. package/dist/types/llm/generate-text-shared.d.ts +32 -0
  314. package/dist/types/llm/generate-text-stream.d.ts +27 -0
  315. package/dist/types/llm/generate-text.d.ts +7 -26
  316. package/dist/types/llm/github-models.d.ts +5 -0
  317. package/dist/types/llm/html-to-markdown.d.ts +2 -1
  318. package/dist/types/llm/model-id.d.ts +1 -1
  319. package/dist/types/llm/provider-capabilities.d.ts +2 -0
  320. package/dist/types/llm/provider-profile.d.ts +31 -0
  321. package/dist/types/llm/providers/google.d.ts +6 -0
  322. package/dist/types/llm/providers/models.d.ts +5 -0
  323. package/dist/types/llm/providers/openai.d.ts +9 -5
  324. package/dist/types/llm/providers/types.d.ts +1 -0
  325. package/dist/types/llm/transcript-to-markdown.d.ts +2 -1
  326. package/dist/types/model-auto-cli.d.ts +15 -0
  327. package/dist/types/model-auto-rules.d.ts +7 -0
  328. package/dist/types/model-auto.d.ts +5 -7
  329. package/dist/types/model-spec.d.ts +4 -3
  330. package/dist/types/run/attachments.d.ts +3 -2
  331. package/dist/types/run/bird/exec.d.ts +1 -0
  332. package/dist/types/run/bird/media.d.ts +3 -0
  333. package/dist/types/run/bird/parse.d.ts +3 -0
  334. package/dist/types/run/bird/types.d.ts +18 -0
  335. package/dist/types/run/bird.d.ts +12 -17
  336. package/dist/types/run/cache-state.d.ts +1 -1
  337. package/dist/types/run/constants.d.ts +2 -1
  338. package/dist/types/run/env.d.ts +6 -0
  339. package/dist/types/run/finish-line-labels.d.ts +29 -0
  340. package/dist/types/run/finish-line-lengths.d.ts +23 -0
  341. package/dist/types/run/finish-line.d.ts +2 -52
  342. package/dist/types/run/flows/asset/extract.d.ts +1 -1
  343. package/dist/types/run/flows/asset/input.d.ts +1 -1
  344. package/dist/types/run/flows/asset/preprocess.d.ts +1 -1
  345. package/dist/types/run/flows/asset/summary-attempts.d.ts +24 -0
  346. package/dist/types/run/flows/asset/summary.d.ts +16 -2
  347. package/dist/types/run/flows/url/extraction-session.d.ts +22 -0
  348. package/dist/types/run/flows/url/fetch-options.d.ts +29 -0
  349. package/dist/types/run/flows/url/flow-progress.d.ts +43 -0
  350. package/dist/types/run/flows/url/markdown.d.ts +2 -2
  351. package/dist/types/run/flows/url/progress-status-state.d.ts +17 -0
  352. package/dist/types/run/flows/url/progress-status.d.ts +17 -0
  353. package/dist/types/run/flows/url/slides-output-render.d.ts +43 -0
  354. package/dist/types/run/flows/url/slides-output-state.d.ts +21 -0
  355. package/dist/types/run/flows/url/slides-output-stream.d.ts +18 -0
  356. package/dist/types/run/flows/url/slides-output.d.ts +2 -17
  357. package/dist/types/run/flows/url/slides-session.d.ts +26 -0
  358. package/dist/types/run/flows/url/slides-text-markdown.d.ts +46 -0
  359. package/dist/types/run/flows/url/slides-text-transcript.d.ts +36 -0
  360. package/dist/types/run/flows/url/slides-text-types.d.ts +8 -0
  361. package/dist/types/run/flows/url/slides-text.d.ts +3 -87
  362. package/dist/types/run/flows/url/summary-finish.d.ts +16 -0
  363. package/dist/types/run/flows/url/summary-json.d.ts +51 -0
  364. package/dist/types/run/flows/url/summary-prompt.d.ts +22 -0
  365. package/dist/types/run/flows/url/summary-resolution.d.ts +31 -0
  366. package/dist/types/run/flows/url/summary-timestamps.d.ts +11 -0
  367. package/dist/types/run/flows/url/types.d.ts +20 -0
  368. package/dist/types/run/flows/url/video-only.d.ts +27 -0
  369. package/dist/types/run/markdown-transforms.d.ts +3 -0
  370. package/dist/types/run/run-context.d.ts +4 -0
  371. package/dist/types/run/run-env.d.ts +4 -0
  372. package/dist/types/run/run-settings-parse.d.ts +5 -0
  373. package/dist/types/run/run-settings.d.ts +2 -1
  374. package/dist/types/run/runner-contexts.d.ts +37 -0
  375. package/dist/types/run/runner-execution.d.ts +58 -0
  376. package/dist/types/run/runner-flags.d.ts +41 -0
  377. package/dist/types/run/runner-plan.d.ts +19 -0
  378. package/dist/types/run/runner-setup.d.ts +21 -0
  379. package/dist/types/run/runner-slides.d.ts +9 -0
  380. package/dist/types/run/streaming.d.ts +2 -1
  381. package/dist/types/run/summary-engine.d.ts +8 -4
  382. package/dist/types/run/summary-llm.d.ts +5 -3
  383. package/dist/types/run/terminal.d.ts +2 -0
  384. package/dist/types/run/types.d.ts +3 -2
  385. package/dist/types/shared/slides-text.d.ts +1 -0
  386. package/dist/types/slides/download.d.ts +29 -0
  387. package/dist/types/slides/extract-finalize.d.ts +57 -0
  388. package/dist/types/slides/extract.d.ts +2 -13
  389. package/dist/types/slides/frame-extraction.d.ts +38 -0
  390. package/dist/types/slides/index.d.ts +2 -1
  391. package/dist/types/slides/ingest.d.ts +47 -0
  392. package/dist/types/slides/ocr.d.ts +5 -0
  393. package/dist/types/slides/process.d.ts +22 -0
  394. package/dist/types/slides/scene-detection.d.ts +75 -0
  395. package/dist/types/slides/source-id.d.ts +2 -0
  396. package/dist/types/slides/source.d.ts +8 -0
  397. package/dist/types/tty/progress/fetch-html.d.ts +1 -0
  398. package/dist/types/tty/progress/transcript-state.d.ts +27 -0
  399. package/dist/types/tty/progress/transcript.d.ts +1 -0
  400. package/dist/types/tty/spinner.d.ts +1 -0
  401. package/dist/types/version.d.ts +1 -1
  402. package/docs/README.md +1 -1
  403. package/docs/_config.yml +1 -0
  404. package/docs/agent.md +3 -2
  405. package/docs/assets/site.css +145 -2
  406. package/docs/cache.md +2 -1
  407. package/docs/chrome-extension.md +19 -5
  408. package/docs/cli.md +26 -8
  409. package/docs/config.md +30 -9
  410. package/docs/extract-only.md +2 -2
  411. package/docs/firecrawl.md +2 -1
  412. package/docs/index.html +5 -0
  413. package/docs/llm.md +34 -5
  414. package/docs/manual-tests.md +3 -0
  415. package/docs/media.md +9 -1
  416. package/docs/model-auto.md +2 -2
  417. package/docs/model-provider-resolution.md +57 -0
  418. package/docs/releasing.md +9 -12
  419. package/docs/site/docs/chrome-extension.html +1 -1
  420. package/docs/site/index.html +5 -0
  421. package/docs/slides-rendering-flow.md +46 -0
  422. package/docs/slides.md +5 -5
  423. package/docs/smoketest.md +1 -1
  424. package/docs/transcript-provider-flow.md +73 -0
  425. package/docs/website.md +3 -1
  426. package/docs/youtube.md +4 -2
  427. package/package.json +17 -16
package/CHANGELOG.md CHANGED
@@ -1,10 +1,82 @@
1
1
  # Changelog
2
2
 
3
- ## 0.11.1 - 2026-02-14
3
+ ## 0.13.0 - UNRELEASED
4
+
5
+ ### Features
6
+
7
+ - Slides: support `--slides` for local video files in the main CLI and `summarize slides`, route local videos through the shared slide-aware flow, and document the local-file workflow (#149, thanks @steipete).
8
+ - Models: add explicit `github-copilot/...` model support backed by GitHub Models, including shorthand ids like `github-copilot/gpt-5.4` and `GITHUB_TOKEN` / `GH_TOKEN` auth.
9
+ - Models: add OpenCode as a first-class CLI provider across CLI flags, config, auto fallback, daemon picker/chat flows, and Chrome extension settings, while preserving existing OpenClaw behavior (#169, thanks @maciej).
10
+ - CLI providers: add OpenClaw as a configurable CLI backend (`--cli openclaw`, `cli/openclaw/...`, `openclaw/...`) across config, daemon discovery, and docs (#165, thanks @yqf-ai).
11
+ - Config: allow setting a default summary length via `output.length`, and keep prompt-override runs aligned with the configured length/language defaults in both CLI and daemon flows (#178, thanks @maciej).
12
+ - Media detection/cache: recognize `.m3u8` HLS playlists as direct media inputs and preserve the playlist extension in the media cache (#159, thanks @mdsakalu).
13
+
14
+ ### Fixes
15
+
16
+ - OpenAI models: route GPT-5.4 / GPT-5.4 mini / GPT-5.4 nano / GPT-5 mini / GPT-5 nano text requests through direct provider APIs instead of the stale generic parser, preserve the real `gpt-5.4-mini` / `gpt-5.4-nano` ids end-to-end, and fall GitHub Models OpenAI GPT-5-family requests back to `gpt-5-chat` when GitHub rejects the raw id.
17
+ - GitHub Models: make `github-copilot/...` shorthand inference family-based instead of pinning old exact prefixes, so newer ids like `gpt-5.4`, `o5`, and `claude-opus-4.6` normalize correctly when the backend exposes them.
18
+ - Slides/local video: transcribe direct videos for slide summaries, avoid fake local-file “Downloading audio” phases, and keep progress text visible while slide extraction runs.
19
+ - Chrome extension slides: restore slide text/session state more reliably so reruns and reloads do not leave stale or blank slide summaries.
20
+ - Transcription: retry Groq Whisper uploads via `curl` when Node multipart uploads get a 403, fixing local `.ogg` regressions on some environments.
21
+ - YouTube: detect obviously truncated caption-track transcripts on long videos and fall through to yt-dlp transcription instead of caching a broken partial result (#184, thanks @sportiz91).
22
+ - YouTube: treat yt-dlp “no audio stream” videos as a non-fatal unavailable transcript case so summarize can continue cleanly with an explanatory note (#161, thanks @mdsakalu).
23
+ - Cache: include the prompt `<context>` block in summary cache hashing and bump the cache format version so stale cross-page summary collisions cannot be reused (#171, thanks @mvance).
24
+ - CLI providers: stream OpenClaw prompts over stdin instead of `--message`, make daemon side-panel chat honor `openai.useChatCompletions`/custom OpenAI-compatible base URLs, and stop leaking raw Codex JSONL events like `thread.started` when no assistant text was produced.
25
+ - Chrome extension: add a copy button for rendered summaries so results can be copied without manual selection.
26
+ - Chrome extension chat: handle plain-string assistant replies in the side-panel agent loop instead of crashing on `.filter()` tool-call extraction (#186, thanks @Youpen-y).
27
+ - Windows containers: let `summarize daemon install` start the daemon for the current container session without Scheduled Task registration, keep `0.0.0.0` binding Windows-only, and probe slide tools by spawning commands when PATH lookup is unreliable (#152, thanks @mathicg).
28
+ - Windows daemon: keep Scheduled Task startup hidden without breaking `summarize daemon restart` or uninstall by tracking the hidden daemon PID and killing that process tree before reruns/removal (#146, thanks @mathicg).
29
+ - Whisper.cpp: honor config-resolved transcription env overrides for readiness checks, model display, and local transcription so custom binary/model paths work outside `process.env` (#160, thanks @mdsakalu).
30
+ - Daemon models: gracefully fall back for unrecognized custom models when using proxy base URLs instead of crashing on undefined API metadata (#175, thanks @douo).
31
+ - Docs/setup: switch Homebrew instructions from the old tap to the official `brew install summarize` formula, including the side-panel setup UI and release checklist (#172, thanks @zeldrisho).
32
+ - Chrome extension: detect blank `userAgentData.platform` browsers like Vivaldi by falling back to `navigator.platform` before choosing OS-specific setup instructions (#158, thanks @bytrangle).
33
+ - Firecrawl: reject `--firecrawl always` for YouTube URLs with an explicit guidance error instead of silently skipping Firecrawl on the transcript-first path (#145, thanks @steipete).
34
+ - YouTube: keep Gemini-only no-caption runs on the transcription path by forwarding the Google API key from the top-level URL flow into link-preview transcription config (#148, thanks @bytrangle).
35
+ - Homebrew: make the tap formula fail clearly on Linux instead of installing a macOS binary, and add generator/test coverage for the macOS-only guard (#147, thanks @steipete).
36
+ - Maintenance: update the GitHub Pages workflow to `actions/configure-pages@v6` and `actions/deploy-pages@v5` (#182, thanks @dependabot).
37
+
38
+ ## 0.12.0 - 2026-03-11
39
+
40
+ ### Features
41
+
42
+ - Models: add `nvidia/...` provider alias (uses `NVIDIA_API_KEY` + optional `NVIDIA_BASE_URL`) for NVIDIA OpenAI-compatible endpoints.
4
43
 
5
44
  ### Fixes
6
45
 
46
+ - Transcription: add AssemblyAI as a first-class remote provider across direct media, podcast/RSS, and yt-dlp YouTube fallback; refactor remote fallback ordering, expand config/env support (`ASSEMBLYAI_API_KEY`, legacy `apiKeys.assemblyai`), and add AssemblyAI unit + live coverage (#126).
47
+ - X/Twitter: prefer `xurl` for tweet extraction when installed, fall back to `bird`, preserve long-form/article text plus media URLs, add live `xurl` extraction/media coverage, and replace the stale dead-`bird` install tip with a current X CLI recommendation (#70).
48
+ - Models: make daemon agent `artifacts` schemas Gemini-safe, improve Google empty-response handling with preview-to-stable fallback, and switch CLI/auto Gemini defaults away from brittle preview behavior (#82, #96).
49
+ - Agents: expand model auto-resolution errors with checked models, missing env/CLI setup, and daemon restart guidance (#107).
50
+ - Daemon: support multiple saved extension tokens, migrate legacy single-token configs, and accept any configured token for auth (#116).
51
+ - Chrome extension: harden side-panel slides so SSE keepalives no longer false-time out, seeded placeholders no longer block pending/cached slide runs, retries can start a fresh summarize+slides run, and reruns replace stale slide state.
52
+ - Chrome extension: refactor side-panel navigation/run attachment policy so late summary/slide runs no longer attach to the wrong page after tab or URL switches, and expand headless regression coverage for pending-run resume and slide-mode transitions.
53
+ - Chrome extension: default fresh installs to slide mode, keep passive tab navigation out of chat, and align slide cards with CLI `--slides` by preferring per-slide summary text over raw transcript/OCR fallback.
54
+ - Chrome extension tests: add stronger YouTube slide E2E coverage for loaded images, summary-backed slide text, and switching between videos mid-analysis without stale slide-summary bleed.
55
+ - Chrome extension: isolate slide-summary stream callbacks per run and harden Playwright settings hydration so late events no longer blank slide text when switching videos mid-analysis.
56
+ - Transcription: add Gemini audio/video transcription support across direct media, podcast/RSS, and yt-dlp YouTube fallback, including Files API uploads for larger media plus new Gemini live coverage (#89).
7
57
  - npm packaging: publish CLI with `pnpm publish` so `@steipete/summarize-core` is version-pinned in published metadata (no `workspace:*` in registry package).
58
+ - Slides: detect WezTerm as an iTerm-compatible terminal for inline slide images in `--slides` mode. (#133) — thanks @doodaaatimmy-creator.
59
+ - CLI help: surface `summarize refresh-free` in `summarize help` output.
60
+ - CLI: report CLI provider timeouts explicitly, including the duration, command, and a `--timeout` hint instead of collapsing them into generic exec failures (#100, thanks @christophsturm).
61
+ - Daemon: restrict CORS responses to trusted extension and localhost origins, with regression coverage for allowed and denied `Origin` headers (#108, thanks @sebastiondev).
62
+ - Transcription: chunk oversized Groq Whisper uploads with ffmpeg in file mode instead of failing out on files above the 30MB limit (#134, thanks @WinnCook).
63
+ - Docs: tighten landing-page mobile layout so hero, cards, code blocks, and nav stay readable on narrow screens (#118, thanks @Acidias).
64
+ - Release: build macOS x64 Bun artifacts and add regression coverage for Homebrew formula rewrites during dual-arch releases (#122, thanks @androidshu).
65
+ - YouTube: tighten hostname validation across core, slides, and extension helpers so attacker-controlled lookalike hosts are no longer treated as YouTube URLs (#91, thanks @RinZ27).
66
+ - Config: honor `zai.baseUrl` config fallback for blank env values and keep Z.AI base URL overrides working outside the summary flow (#102, thanks @liuy).
67
+ - Chrome extension: tighten options and sidepanel UI spacing, copy actions, and advanced-controls layout for a cleaner panel experience (#86, thanks @morozRed).
68
+ - Slides: warn in summary mode when `--slides` dependencies are missing, and document required local installs for `ffmpeg`, `yt-dlp`, and optional `tesseract`.
69
+ - Docs: fix broken docs index links by setting an empty Jekyll `baseurl` (#113, thanks @Youpen-y).
70
+ - Models: preserve model id casing after the provider prefix so OpenAI-compatible proxies can route exact names correctly (#128, thanks @WinnCook).
71
+ - Cache: give extract entries with unavailable transcripts the same short retry TTL as negative transcript cache entries, so transient Apify failures can recover (#115, thanks @gluneau).
72
+ - Daemon: apply the saved env snapshot to `process.env` before `daemon run` starts so child tools inherit the right PATH and API/tool config under launchd/systemd (#99, thanks @heyalchang).
73
+ - Chrome automation: require sidepanel arming before debugger-backed native input can run in a tab, and auto-disarm after browser JS execution ends (#129, thanks @omnicoder9).
74
+ - Media setup: fix the local whisper.cpp install hint to use the current Homebrew formula name `whisper-cpp` (#92, thanks @zerone0x).
75
+ - CLI output: cap markdown render width on very wide terminals by default, with a `--width` override for manual control (#119, thanks @howardpen9).
76
+ - Slides: size inline slide images from terminal width instead of keeping them pinned to 32 columns, capped at 2x the previous width while preserving `COLUMNS` fallback behavior (#125, #135, thanks @WinnCook).
77
+ - Shell completions: add Fish shell completions for the current CLI flags and option values (#95, thanks @fbehrens).
78
+ - Bun fetch: only opt into compressed HTML/YouTube responses when running under Bun, and retry link-preview fetches with `Accept-Encoding: identity` after Bun decompression failures (#105, thanks @maciej).
79
+ - Daemon: support `cli/...` models in chat and agent endpoints, including CLI auto-fallback when no API-key transport is available (#109, thanks @jetm).
8
80
 
9
81
  ## 0.11.0 - 2026-02-14
10
82
 
package/README.md CHANGED
@@ -1,26 +1,22 @@
1
1
  # Summarize 📝 — Chrome Side Panel + CLI
2
2
 
3
- ![GitHub Repo Banner](https://ghrb.waren.build/banner?header=Summarize%F0%9F%93%9D&subheader=Chrome+Side+Panel+%2B+CLI&bg=f3f4f6&color=1f2937&support=true)
4
-
5
- <!-- Created with GitHub Repo Banner by Waren Gonzaga: https://ghrb.waren.build -->
6
-
7
3
  Fast summaries from URLs, files, and media. Works in the terminal, a Chrome Side Panel and Firefox Sidebar.
8
4
 
9
- **0.11.0 preview (unreleased):** this README reflects the upcoming release.
10
-
11
- ## 0.11.0 preview highlights (most interesting first)
5
+ ## Highlights
12
6
 
13
7
  - Chrome Side Panel **chat** (streaming agent + history) inside the sidebar.
14
- - **YouTube slides**: screenshots + OCR + transcript cards, timestamped seek, OCR/Transcript toggle.
8
+ - **Video slides**: screenshots + OCR + transcript cards for YouTube, direct video URLs, and local video files.
15
9
  - Media-aware summaries: auto‑detect video/audio vs page content.
10
+ - Coding CLI backends: Codex, Claude, Gemini, Cursor Agent, OpenClaw, OpenCode.
16
11
  - Streaming Markdown + metrics + cache‑aware status.
17
12
  - CLI supports URLs, files, podcasts, YouTube, audio/video, PDFs.
18
13
 
19
14
  ## Feature overview
20
15
 
21
16
  - URLs, files, and media: web pages, PDFs, images, audio/video, YouTube, podcasts, RSS.
22
- - Slide extraction for video sources (YouTube/direct media) with OCR + timestamped cards.
23
- - Transcript-first media flow: published transcripts when available, Whisper fallback when not.
17
+ - Slide extraction for video sources (YouTube, direct video URLs, local video files) with OCR + timestamped cards.
18
+ - Transcript-first media flow: published transcripts when available, then Groq/ONNX/whisper.cpp/AssemblyAI/Gemini/OpenAI/FAL transcription fallback when not.
19
+ - Coding CLI providers: Claude, Codex, Gemini, Cursor Agent, OpenClaw, OpenCode.
24
20
  - Streaming output with Markdown rendering, metrics, and cache-aware status.
25
21
  - Local, paid, and free models: OpenAI‑compatible local endpoints, paid providers, plus an OpenRouter free preset.
26
22
  - Output modes: Markdown/text, JSON diagnostics, extract-only, metrics, timing, and cost estimates.
@@ -42,7 +38,7 @@ YouTube slide screenshots (from the browser):
42
38
 
43
39
  1. Install the CLI (choose one):
44
40
  - **npm** (cross‑platform): `npm i -g @steipete/summarize`
45
- - **Homebrew** (macOS arm64): `brew install steipete/tap/summarize`
41
+ - **Homebrew** (Homebrew/core): `brew install summarize`
46
42
  2. Install the extension (Chrome Web Store link above) and open the Side Panel.
47
43
  3. The panel shows a token + install command. Run it in Terminal:
48
44
  - `summarize daemon install --token <TOKEN>`
@@ -58,8 +54,9 @@ Notes:
58
54
 
59
55
  - Summarization only runs when the Side Panel is open.
60
56
  - Auto mode summarizes on navigation (incl. SPAs); otherwise use the button.
61
- - Daemon is localhost-only and requires a shared token.
57
+ - Daemon is localhost-only and requires a shared token; rerunning `summarize daemon install --token <TOKEN>` adds another paired browser token instead of invalidating the old one.
62
58
  - Autostart: macOS (launchd), Linux (systemd user), Windows (Scheduled Task).
59
+ - Windows containers: `summarize daemon install` starts the daemon for the current container session but does not register a Scheduled Task. Run it each time the container starts or add that command to your container startup, and publish port `8787` so the host browser can reach the daemon.
63
60
  - Tip: configure `free` via `summarize refresh-free` (needs `OPENROUTER_API_KEY`). Add `--set-default` to set model=`free`.
64
61
 
65
62
  More:
@@ -118,13 +115,37 @@ npm i @steipete/summarize-core
118
115
  import { createLinkPreviewClient } from "@steipete/summarize-core/content";
119
116
  ```
120
117
 
121
- - Homebrew (custom tap):
118
+ - Homebrew:
119
+
120
+ ```bash
121
+ brew install summarize
122
+ ```
123
+
124
+ Homebrew ships from `homebrew/core` via `brew install summarize`.
125
+ If Homebrew is unavailable in your environment, use the npm global install above.
126
+
127
+ ### Optional local dependencies
128
+
129
+ Install these if you want media-heavy features:
130
+
131
+ - `ffmpeg`: required for `--slides` and many local media/transcription flows
132
+ - `yt-dlp`: required for YouTube slide extraction and some remote media flows
133
+ - `tesseract`: optional OCR for `--slides-ocr`
134
+ - Optional cloud transcription providers:
135
+ - `GROQ_API_KEY`
136
+ - `ASSEMBLYAI_API_KEY`
137
+ - `GEMINI_API_KEY` / `GOOGLE_GENERATIVE_AI_API_KEY` / `GOOGLE_API_KEY`
138
+ - `OPENAI_API_KEY`
139
+ - `FAL_KEY`
140
+
141
+ macOS (Homebrew):
122
142
 
123
143
  ```bash
124
- brew install steipete/tap/summarize
144
+ brew install ffmpeg yt-dlp
145
+ brew install tesseract # optional, for --slides-ocr
125
146
  ```
126
147
 
127
- Apple Silicon only (arm64).
148
+ If `--slides` is enabled and these tools are missing, Summarize warns and continues without slides.
128
149
 
129
150
  ### CLI vs extension
130
151
 
@@ -142,8 +163,8 @@ summarize "https://example.com"
142
163
  URLs or local paths:
143
164
 
144
165
  ```bash
145
- summarize "/path/to/file.pdf" --model google/gemini-3-flash-preview
146
- summarize "https://example.com/report.pdf" --model google/gemini-3-flash-preview
166
+ summarize "/path/to/file.pdf" --model google/gemini-3-flash
167
+ summarize "https://example.com/report.pdf" --model google/gemini-3-flash
147
168
  summarize "/path/to/audio.mp3"
148
169
  summarize "/path/to/video.mp4"
149
170
  ```
@@ -189,10 +210,18 @@ Spotify episode page (best-effort; may fail for exclusives):
189
210
  summarize "https://open.spotify.com/episode/5auotqWAXhhKyb9ymCuBJY"
190
211
  ```
191
212
 
213
+ HLS playlist:
214
+
215
+ ```bash
216
+ summarize "https://example.com/master.m3u8"
217
+ ```
218
+
192
219
  ### Output length
193
220
 
194
221
  `--length` controls how much output we ask for (guideline), not a hard cap.
195
222
 
223
+ Set a default in `~/.summarize/config.json` with `output.length`.
224
+
196
225
  ```bash
197
226
  summarize "https://example.com" --length long
198
227
  summarize "https://example.com" --length 20k
@@ -235,14 +264,20 @@ Use gateway-style ids: `<provider>/<model>`.
235
264
 
236
265
  Examples:
237
266
 
267
+ - `openai/gpt-5.4`
268
+ - `openai/gpt-5.4-mini`
269
+ - `openai/gpt-5.4-nano`
238
270
  - `openai/gpt-5-mini`
271
+ - `openai/gpt-5-nano`
272
+ - `github-copilot/gpt-5.4`
239
273
  - `anthropic/claude-sonnet-4-5`
240
274
  - `xai/grok-4-fast-non-reasoning`
241
- - `google/gemini-3-flash-preview`
275
+ - `google/gemini-3-flash`
242
276
  - `zai/glm-4.7`
243
277
  - `openrouter/openai/gpt-5-mini` (force OpenRouter)
244
278
 
245
279
  Note: some models/providers do not support streaming or certain file media types. When that happens, the CLI prints a friendly error (or auto-disables streaming for that model when supported by the provider).
280
+ `gpt-5.4-mini` and `gpt-5.4-nano` are treated as real model ids; the same shorthand also works under `github-copilot/...`.
246
281
 
247
282
  ### Limits
248
283
 
@@ -265,7 +300,7 @@ Use `summarize --help` or `summarize help` for the full help text.
265
300
  - `--length short|medium|long|xl|xxl|s|m|l|<chars>`
266
301
  - `--language, --lang <language>`: output language (`auto` = match source)
267
302
  - `--max-output-tokens <count>`: hard cap for LLM output tokens
268
- - `--cli [provider]`: use a CLI provider (`--model cli/<provider>`). Supports `claude`, `gemini`, `codex`, `agent`. If omitted, uses auto selection with CLI enabled.
303
+ - `--cli [provider]`: use a CLI provider (`--model cli/<provider>`). Supports `claude`, `gemini`, `codex`, `agent`, `openclaw`, `opencode`. If omitted, uses auto selection with CLI enabled.
269
304
  - `--stream auto|on|off`: stream LLM output (`auto` = TTY only; disabled in `--json` mode)
270
305
  - `--plain`: keep raw output (no ANSI/OSC Markdown rendering)
271
306
  - `--no-color`: disable ANSI colors
@@ -276,7 +311,7 @@ Use `summarize --help` or `summarize help` for the full help text.
276
311
  - Install `uvx`: `brew install uv` (or https://astral.sh/uv/)
277
312
  - `--extract`: print extracted content and exit (URLs only; stdin `-` is not supported)
278
313
  - Deprecated alias: `--extract-only`
279
- - `--slides`: extract slides for YouTube/direct video URLs and render them inline in the summary narrative (auto-renders inline in supported terminals)
314
+ - `--slides`: extract slides for YouTube, direct video URLs, or local video files and render them inline in the summary narrative (auto-renders inline in supported terminals)
280
315
  - `--slides-ocr`: run OCR on extracted slides (requires `tesseract`)
281
316
  - `--slides-dir <dir>`: base output dir for slide images (default `./slides`)
282
317
  - `--slides-scene-threshold <value>`: scene detection threshold (0.1-1.0)
@@ -286,7 +321,7 @@ Use `summarize --help` or `summarize help` for the full help text.
286
321
  - `--verbose`: debug/diagnostics on stderr
287
322
  - `--metrics off|on|detailed`: metrics output (default `on`)
288
323
 
289
- ### Coding CLIs (Codex, Claude, Gemini, Agent)
324
+ ### Coding CLIs (Codex, Claude, Gemini, Agent, OpenClaw, OpenCode)
290
325
 
291
326
  Summarize can use common coding CLIs as local model backends:
292
327
 
@@ -294,11 +329,13 @@ Summarize can use common coding CLIs as local model backends:
294
329
  - `claude` -> `--cli claude` / `--model cli/claude/<model>`
295
330
  - `gemini` -> `--cli gemini` / `--model cli/gemini/<model>`
296
331
  - `agent` (Cursor Agent CLI) -> `--cli agent` / `--model cli/agent/<model>`
332
+ - `openclaw` -> `--cli openclaw` / `--model cli/openclaw/<model>` or `--model openclaw/<model>`
333
+ - `opencode` -> `--cli opencode` / `--model cli/opencode/<model>` (`--model cli/opencode` uses the OpenCode runtime default)
297
334
 
298
335
  Requirements:
299
336
 
300
- - Binary installed and on `PATH` (or set `CODEX_PATH`, `CLAUDE_PATH`, `GEMINI_PATH`, `AGENT_PATH`)
301
- - Provider authenticated (`codex login`, `claude auth`, `gemini` login flow, `agent login` or `CURSOR_API_KEY`)
337
+ - Binary installed and on `PATH` (or set `CODEX_PATH`, `CLAUDE_PATH`, `GEMINI_PATH`, `AGENT_PATH`, `OPENCLAW_PATH`, `OPENCODE_PATH`)
338
+ - Provider authenticated (`codex login`, `claude auth`, `gemini` login flow, `agent login` or `CURSOR_API_KEY`, `opencode auth login`)
302
339
 
303
340
  Quick smoke test:
304
341
 
@@ -309,13 +346,15 @@ summarize --cli codex --plain --timeout 2m /tmp/summarize-cli-smoke.txt
309
346
  summarize --cli claude --plain --timeout 2m /tmp/summarize-cli-smoke.txt
310
347
  summarize --cli gemini --plain --timeout 2m /tmp/summarize-cli-smoke.txt
311
348
  summarize --cli agent --plain --timeout 2m /tmp/summarize-cli-smoke.txt
349
+ summarize --cli openclaw --plain --timeout 2m /tmp/summarize-cli-smoke.txt
350
+ summarize --cli opencode --plain --timeout 2m /tmp/summarize-cli-smoke.txt
312
351
  ```
313
352
 
314
353
  Set explicit CLI allowlist/order:
315
354
 
316
355
  ```json
317
356
  {
318
- "cli": { "enabled": ["codex", "claude", "gemini", "agent"] }
357
+ "cli": { "enabled": ["codex", "claude", "gemini", "agent", "openclaw", "opencode"] }
319
358
  }
320
359
  ```
321
360
 
@@ -327,7 +366,7 @@ Configure implicit auto CLI fallback:
327
366
  "autoFallback": {
328
367
  "enabled": true,
329
368
  "onlyWhenNoApiKeys": true,
330
- "order": ["claude", "gemini", "codex", "agent"]
369
+ "order": ["claude", "gemini", "codex", "agent", "openclaw", "opencode"]
331
370
  }
332
371
  }
333
372
  }
@@ -343,7 +382,7 @@ CLI attempts are prepended when:
343
382
  - `cli.enabled` is set (explicit allowlist/order), or
344
383
  - implicit auto selection is active and `cli.autoFallback` is enabled.
345
384
 
346
- Default fallback behavior: only when no API keys are configured, order `claude, gemini, codex, agent`, and remember/prioritize last successful provider (`~/.summarize/cli-state.json`).
385
+ Default fallback behavior: only when no API keys are configured, order `claude, gemini, codex, agent, openclaw, opencode`, and remember/prioritize last successful provider (`~/.summarize/cli-state.json`).
347
386
 
348
387
  Set explicit CLI attempts:
349
388
 
@@ -382,7 +421,8 @@ Non-YouTube URLs go through a fetch -> extract pipeline. When direct fetch/extra
382
421
 
383
422
  1. Apify (if `APIFY_API_TOKEN` is set): uses a scraping actor (`faVsWy9VTSNVIhWpR`)
384
423
  2. yt-dlp + Whisper (if `yt-dlp` is available): downloads audio, then transcribes with local `whisper.cpp` when installed
385
- (preferred), otherwise falls back to OpenAI (`OPENAI_API_KEY`) or FAL (`FAL_KEY`)
424
+ (preferred), otherwise falls back to Groq (`GROQ_API_KEY`), AssemblyAI (`ASSEMBLYAI_API_KEY`), Gemini
425
+ (`GEMINI_API_KEY` / Google aliases), OpenAI (`OPENAI_API_KEY`), then FAL (`FAL_KEY`)
386
426
 
387
427
  Environment variables for yt-dlp mode:
388
428
 
@@ -390,19 +430,29 @@ Environment variables for yt-dlp mode:
390
430
  - `SUMMARIZE_WHISPER_CPP_MODEL_PATH` - optional override for the local `whisper.cpp` model file
391
431
  - `SUMMARIZE_WHISPER_CPP_BINARY` - optional override for the local binary (default: `whisper-cli`)
392
432
  - `SUMMARIZE_DISABLE_LOCAL_WHISPER_CPP=1` - disable local whisper.cpp (force remote)
433
+ - `GROQ_API_KEY` - Groq Whisper transcription
434
+ - `ASSEMBLYAI_API_KEY` - AssemblyAI transcription
435
+ - `GEMINI_API_KEY` - Gemini transcription (`GOOGLE_GENERATIVE_AI_API_KEY` / `GOOGLE_API_KEY` also work)
393
436
  - `OPENAI_API_KEY` - OpenAI Whisper transcription
394
437
  - `OPENAI_WHISPER_BASE_URL` - optional OpenAI-compatible Whisper endpoint override
395
438
  - `FAL_KEY` - FAL AI Whisper fallback
396
439
 
397
440
  Apify costs money but tends to be more reliable when captions exist.
398
441
 
399
- ### Slide extraction (YouTube + direct video URLs)
442
+ ### Slide extraction (YouTube + direct video URLs + local video files)
400
443
 
401
444
  Extract slide screenshots (scene detection via `ffmpeg`) and optional OCR:
402
445
 
446
+ Requirements:
447
+
448
+ - `ffmpeg` for scene detection and frame extraction
449
+ - `yt-dlp` for YouTube video download/stream resolution
450
+ - `tesseract` only when using `--slides-ocr`
451
+
403
452
  ```bash
404
453
  summarize "https://www.youtube.com/watch?v=..." --slides
405
454
  summarize "https://www.youtube.com/watch?v=..." --slides --slides-ocr
455
+ summarize "/path/to/video.webm" --slides
406
456
  ```
407
457
 
408
458
  Outputs are written under `./slides/<sourceId>/` (or `--slides-dir`). OCR results are included in JSON output
@@ -411,7 +461,7 @@ extractor also samples at a fixed interval to improve coverage.
411
461
  When using `--slides`, supported terminals (kitty/iTerm/Konsole) render inline thumbnails automatically inside the
412
462
  summary narrative (the model inserts `[slide:N]` markers). Timestamp links are clickable when the terminal supports
413
463
  OSC-8 (YouTube/Vimeo/Loom/Dropbox). If inline images are unsupported, Summarize prints a note with the on-disk
414
- slide directory.
464
+ slide directory. Local video files stay on the slide-aware path, transcribe in place, and avoid fake download labels.
415
465
 
416
466
  Use `--slides --extract` to print the full timed transcript and insert slide images inline at matching timestamps.
417
467
 
@@ -425,7 +475,7 @@ summarize "https://www.youtube.com/watch?v=..." --extract --format md --markdown
425
475
 
426
476
  Local audio/video files are transcribed first, then summarized. `--video-mode transcript` forces
427
477
  direct media URLs (and embedded media) through Whisper first. Prefers local `whisper.cpp` when available; otherwise requires
428
- `OPENAI_API_KEY` or `FAL_KEY`.
478
+ one of `GROQ_API_KEY`, `ASSEMBLYAI_API_KEY`, `GEMINI_API_KEY` (or Google aliases), `OPENAI_API_KEY`, or `FAL_KEY`.
429
479
 
430
480
  ### Local ONNX transcription (Parakeet/Canary)
431
481
 
@@ -449,7 +499,7 @@ Run: `summarize <url>`
449
499
  - RSS feeds (Podcasting 2.0 transcripts when available)
450
500
  - Embedded YouTube podcast pages (e.g. JREPodcast)
451
501
 
452
- Transcription: prefers local `whisper.cpp` when installed; otherwise uses OpenAI Whisper or FAL when keys are set.
502
+ Transcription: prefers local `whisper.cpp` when installed; otherwise uses Groq, AssemblyAI, Gemini, OpenAI, or FAL when keys are set.
453
503
 
454
504
  ### Translation paths
455
505
 
@@ -463,7 +513,7 @@ When the input is audio/video, the CLI needs a transcript first. The transcript
463
513
  2. Whisper transcription (fallback)
464
514
  - YouTube: falls back to yt-dlp (audio download) + Whisper transcription when configured; Apify is a last resort.
465
515
  - Prefers local `whisper.cpp` when installed + model available.
466
- - Otherwise uses cloud Whisper (OpenAI `OPENAI_API_KEY`) or FAL (`FAL_KEY`).
516
+ - Otherwise uses cloud transcription in this order: Groq (`GROQ_API_KEY`) → AssemblyAI (`ASSEMBLYAI_API_KEY`) → Gemini (`GEMINI_API_KEY` / Google aliases) → OpenAI (`OPENAI_API_KEY`) FAL (`FAL_KEY`).
467
517
 
468
518
  For direct media URLs, use `--video-mode transcript` to force transcribe -> summarize:
469
519
 
@@ -483,6 +533,7 @@ Supported keys today:
483
533
  {
484
534
  "model": { "id": "openai/gpt-5-mini" },
485
535
  "env": { "OPENAI_API_KEY": "sk-..." },
536
+ "output": { "length": "long" },
486
537
  "ui": { "theme": "ember" }
487
538
  }
488
539
  ```
@@ -502,6 +553,7 @@ Also supported:
502
553
  - `models` (define presets selectable via `--model <preset>`)
503
554
  - `env` (generic env var defaults; process env still wins)
504
555
  - `apiKeys` (legacy shortcut, mapped to env names; prefer `env` for new configs)
556
+ - `output.length` (default `--length`: `short|medium|long|xl|xxl|20k`)
505
557
  - `cache.media` (media download cache: TTL 7 days, 2048 MB cap by default; `--no-media-cache` disables)
506
558
  - `media.videoMode: "auto"|"transcript"|"understand"`
507
559
  - `slides.enabled` / `slides.max` / `slides.ocr` / `slides.dir` (defaults for `--slides`)
@@ -552,6 +604,7 @@ Set the key matching your chosen `--model`:
552
604
  - legacy `"apiKeys"` still works (mapped to env names)
553
605
 
554
606
  - `OPENAI_API_KEY` (for `openai/...`)
607
+ - `NVIDIA_API_KEY` (for `nvidia/...`)
555
608
  - `ANTHROPIC_API_KEY` (for `anthropic/...`)
556
609
  - `XAI_API_KEY` (for `xai/...`)
557
610
  - `Z_AI_API_KEY` (for `zai/...`; supports `ZAI_API_KEY` alias)
@@ -610,6 +663,7 @@ Example:
610
663
 
611
664
  ```bash
612
665
  OPENROUTER_API_KEY=sk-or-... summarize "https://example.com" --model openrouter/meta-llama/llama-3.1-8b-instruct:free
666
+ OPENROUTER_API_KEY=sk-or-... summarize "https://example.com" --model openrouter/minimax/minimax-m2.5
613
667
  ```
614
668
 
615
669
  If your OpenRouter account enforces an allowed-provider list, make sure at least one provider
@@ -617,6 +671,18 @@ is allowed for the selected model. When routing fails, `summarize` prints the ex
617
671
 
618
672
  Legacy: `OPENAI_BASE_URL=https://openrouter.ai/api/v1` (and either `OPENAI_API_KEY` or `OPENROUTER_API_KEY`) also works.
619
673
 
674
+ NVIDIA API Catalog (OpenAI-compatible; free credits):
675
+
676
+ - Set `NVIDIA_API_KEY=...`
677
+ - Optional: `NVIDIA_BASE_URL=https://integrate.api.nvidia.com/v1`
678
+ - Credits: API Catalog trial starts with 1000 free API credits on signup (up to 5000 total via “Request More” in the API Catalog profile)
679
+ - Pick a model id from `/v1/models` (examples: fast `stepfun-ai/step-3.5-flash`, strong but slower `z-ai/glm5`)
680
+
681
+ ```bash
682
+ export NVIDIA_API_KEY="nvapi-..."
683
+ summarize "https://example.com" --model nvidia/stepfun-ai/step-3.5-flash
684
+ ```
685
+
620
686
  Z.AI (OpenAI-compatible):
621
687
 
622
688
  - `Z_AI_API_KEY=...` (or `ZAI_API_KEY=...`)
@@ -626,6 +692,10 @@ Optional services:
626
692
 
627
693
  - `FIRECRAWL_API_KEY` (website extraction fallback)
628
694
  - `YT_DLP_PATH` (path to yt-dlp binary for audio extraction)
695
+ - `GROQ_API_KEY` (Groq Whisper transcription)
696
+ - `ASSEMBLYAI_API_KEY` (AssemblyAI transcription)
697
+ - `GEMINI_API_KEY` / `GOOGLE_GENERATIVE_AI_API_KEY` / `GOOGLE_API_KEY` (Gemini transcription)
698
+ - `OPENAI_API_KEY` / `OPENAI_WHISPER_BASE_URL` (OpenAI Whisper transcription)
629
699
  - `FAL_KEY` (FAL AI API key for audio transcription via Whisper)
630
700
  - `APIFY_API_TOKEN` (YouTube transcript fallback)
631
701
 
package/dist/cli.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- if (!process.env.SUMMARIZE_GIT_SHA) process.env.SUMMARIZE_GIT_SHA = "ae52818b"
2
+ if (!process.env.SUMMARIZE_GIT_SHA) process.env.SUMMARIZE_GIT_SHA = "70006c3e"
3
3
  await import('./esm/cli.js')
@@ -0,0 +1,83 @@
1
+ import { createHash } from "node:crypto";
2
+ export function hashString(value) {
3
+ return createHash("sha256").update(value).digest("hex");
4
+ }
5
+ export function hashJson(value) {
6
+ return hashString(JSON.stringify(value));
7
+ }
8
+ export function normalizeContentForHash(content) {
9
+ return content.replaceAll("\r\n", "\n").trim();
10
+ }
11
+ export function extractTaggedBlock(prompt, tag) {
12
+ const open = `<${tag}>`;
13
+ const close = `</${tag}>`;
14
+ const start = prompt.indexOf(open);
15
+ if (start === -1)
16
+ return null;
17
+ const end = prompt.indexOf(close, start + open.length);
18
+ if (end === -1)
19
+ return null;
20
+ return prompt.slice(start + open.length, end).trim();
21
+ }
22
+ export function buildPromptHash(prompt) {
23
+ const instructionsContent = extractTaggedBlock(prompt, "instructions");
24
+ const contextContent = extractTaggedBlock(prompt, "context");
25
+ // If at least one of the tags is present (even if empty), hash their contents.
26
+ if (instructionsContent !== null || contextContent !== null) {
27
+ const instructions = instructionsContent ?? "";
28
+ const context = contextContent ?? "";
29
+ return hashString(`${instructions}\n${context}`.trim());
30
+ }
31
+ // Fallback for prompts without any tags.
32
+ return hashString(prompt.trim());
33
+ }
34
+ export function buildPromptContentHash({ prompt, fallbackContent, }) {
35
+ const content = extractTaggedBlock(prompt, "content") ?? fallbackContent ?? null;
36
+ if (!content || content.trim().length === 0)
37
+ return null;
38
+ return hashString(normalizeContentForHash(content));
39
+ }
40
+ export function buildLengthKey(lengthArg) {
41
+ return lengthArg.kind === "preset"
42
+ ? `preset:${lengthArg.preset}`
43
+ : `chars:${lengthArg.maxCharacters}`;
44
+ }
45
+ export function buildLanguageKey(outputLanguage) {
46
+ return outputLanguage.kind === "auto" ? "auto" : outputLanguage.tag;
47
+ }
48
+ export function buildExtractCacheKeyValue({ url, options, formatVersion, }) {
49
+ return hashJson({ url, options, formatVersion });
50
+ }
51
+ export function buildSummaryCacheKeyValue({ contentHash, promptHash, model, lengthKey, languageKey, formatVersion, }) {
52
+ return hashJson({
53
+ contentHash,
54
+ promptHash,
55
+ model,
56
+ lengthKey,
57
+ languageKey,
58
+ formatVersion,
59
+ });
60
+ }
61
+ export function buildSlidesCacheKeyValue({ url, settings, formatVersion, }) {
62
+ return hashJson({
63
+ url,
64
+ settings: {
65
+ ocr: settings.ocr,
66
+ outputDir: settings.outputDir,
67
+ sceneThreshold: settings.sceneThreshold,
68
+ autoTuneThreshold: settings.autoTuneThreshold,
69
+ maxSlides: settings.maxSlides,
70
+ minDurationSeconds: settings.minDurationSeconds,
71
+ },
72
+ formatVersion,
73
+ });
74
+ }
75
+ export function buildTranscriptCacheKeyValue({ url, namespace, formatVersion, fileMtime, }) {
76
+ return hashJson({
77
+ url,
78
+ namespace,
79
+ fileMtime: fileMtime ?? null,
80
+ formatVersion,
81
+ });
82
+ }
83
+ //# sourceMappingURL=cache-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-keys.js","sourceRoot":"","sources":["../../src/cache-keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { rmSync } from "node:fs";
2
+ import { isAbsolute, join, resolve as resolvePath, sep as pathSep } from "node:path";
3
+ function normalizeAbsolutePath(value) {
4
+ if (typeof value !== "string")
5
+ return null;
6
+ const trimmed = value.trim();
7
+ if (!trimmed)
8
+ return null;
9
+ const resolved = resolvePath(trimmed);
10
+ return isAbsolute(resolved) ? resolved : null;
11
+ }
12
+ export function cleanupSlidesPayload(raw) {
13
+ let payload;
14
+ try {
15
+ payload = JSON.parse(raw);
16
+ }
17
+ catch {
18
+ return;
19
+ }
20
+ if (!payload || typeof payload !== "object")
21
+ return;
22
+ const slidesDir = normalizeAbsolutePath(payload.slidesDir);
23
+ const slides = Array.isArray(payload.slides)
24
+ ? payload.slides
25
+ : [];
26
+ if (!slidesDir)
27
+ return;
28
+ const dirPrefix = slidesDir.endsWith(pathSep) ? slidesDir : `${slidesDir}${pathSep}`;
29
+ const safeRemove = (target) => {
30
+ try {
31
+ rmSync(target, { force: true });
32
+ }
33
+ catch {
34
+ // ignore
35
+ }
36
+ };
37
+ for (const slide of slides) {
38
+ const imagePath = normalizeAbsolutePath(slide?.imagePath);
39
+ if (!imagePath)
40
+ continue;
41
+ if (!imagePath.startsWith(dirPrefix))
42
+ continue;
43
+ safeRemove(imagePath);
44
+ }
45
+ safeRemove(join(slidesDir, "slides.json"));
46
+ }
47
+ //# sourceMappingURL=cache-slides-cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-slides-cleanup.js","sourceRoot":"","sources":["../../src/cache-slides-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,IAAI,WAAW,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAErF,SAAS,qBAAqB,CAAC,KAAc;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO;IACpD,MAAM,SAAS,GAAG,qBAAqB,CAAE,OAAmC,CAAC,SAAS,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAE,OAAgC,CAAC,MAAM,CAAC;QACpE,CAAC,CAAG,OAAgC,CAAC,MAAyC;QAC9E,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,OAAO,EAAE,CAAC;IACrF,MAAM,UAAU,GAAG,CAAC,MAAc,EAAE,EAAE;QACpC,IAAI,CAAC;YACH,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC,SAAS;YAAE,SAAS;QACzB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,SAAS;QAC/C,UAAU,CAAC,SAAS,CAAC,CAAC;IACxB,CAAC;IACD,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;AAC7C,CAAC"}