@steipete/summarize 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/CHANGELOG.md +44 -1
  2. package/README.md +63 -17
  3. package/dist/cli.js +1 -1
  4. package/dist/esm/cache-keys.js +75 -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 +14 -91
  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 +50 -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 +438 -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/daemon/agent-model.js +235 -0
  27. package/dist/esm/daemon/agent-model.js.map +1 -0
  28. package/dist/esm/daemon/agent-request.js +87 -0
  29. package/dist/esm/daemon/agent-request.js.map +1 -0
  30. package/dist/esm/daemon/agent.js +42 -243
  31. package/dist/esm/daemon/agent.js.map +1 -1
  32. package/dist/esm/daemon/chat.js +69 -8
  33. package/dist/esm/daemon/chat.js.map +1 -1
  34. package/dist/esm/daemon/cli.js +21 -4
  35. package/dist/esm/daemon/cli.js.map +1 -1
  36. package/dist/esm/daemon/config.js +65 -9
  37. package/dist/esm/daemon/config.js.map +1 -1
  38. package/dist/esm/daemon/env-snapshot.js +4 -0
  39. package/dist/esm/daemon/env-snapshot.js.map +1 -1
  40. package/dist/esm/daemon/flow-context.js +8 -1
  41. package/dist/esm/daemon/flow-context.js.map +1 -1
  42. package/dist/esm/daemon/models.js +16 -0
  43. package/dist/esm/daemon/models.js.map +1 -1
  44. package/dist/esm/daemon/process-registry.js.map +1 -1
  45. package/dist/esm/daemon/server-admin-routes.js +134 -0
  46. package/dist/esm/daemon/server-admin-routes.js.map +1 -0
  47. package/dist/esm/daemon/server-agent-route.js +104 -0
  48. package/dist/esm/daemon/server-agent-route.js.map +1 -0
  49. package/dist/esm/daemon/server-http.js +89 -0
  50. package/dist/esm/daemon/server-http.js.map +1 -0
  51. package/dist/esm/daemon/server-session-routes.js +209 -0
  52. package/dist/esm/daemon/server-session-routes.js.map +1 -0
  53. package/dist/esm/daemon/server-session.js +118 -0
  54. package/dist/esm/daemon/server-session.js.map +1 -0
  55. package/dist/esm/daemon/server-sse.js +28 -0
  56. package/dist/esm/daemon/server-sse.js.map +1 -0
  57. package/dist/esm/daemon/server-summarize-execution.js +357 -0
  58. package/dist/esm/daemon/server-summarize-execution.js.map +1 -0
  59. package/dist/esm/daemon/server-summarize-request.js +119 -0
  60. package/dist/esm/daemon/server-summarize-request.js.map +1 -0
  61. package/dist/esm/daemon/server.js +72 -1121
  62. package/dist/esm/daemon/server.js.map +1 -1
  63. package/dist/esm/daemon/summarize-progress.js +1 -1
  64. package/dist/esm/daemon/summarize-progress.js.map +1 -1
  65. package/dist/esm/daemon/summarize.js.map +1 -1
  66. package/dist/esm/llm/cli-exec.js +75 -0
  67. package/dist/esm/llm/cli-exec.js.map +1 -0
  68. package/dist/esm/llm/cli-provider-output.js +191 -0
  69. package/dist/esm/llm/cli-provider-output.js.map +1 -0
  70. package/dist/esm/llm/cli.js +3 -212
  71. package/dist/esm/llm/cli.js.map +1 -1
  72. package/dist/esm/llm/generate-text-document.js +109 -0
  73. package/dist/esm/llm/generate-text-document.js.map +1 -0
  74. package/dist/esm/llm/generate-text-shared.js +102 -0
  75. package/dist/esm/llm/generate-text-shared.js.map +1 -0
  76. package/dist/esm/llm/generate-text-stream.js +258 -0
  77. package/dist/esm/llm/generate-text-stream.js.map +1 -0
  78. package/dist/esm/llm/generate-text.js +145 -480
  79. package/dist/esm/llm/generate-text.js.map +1 -1
  80. package/dist/esm/llm/model-id.js +21 -20
  81. package/dist/esm/llm/model-id.js.map +1 -1
  82. package/dist/esm/llm/provider-capabilities.js +2 -0
  83. package/dist/esm/llm/provider-capabilities.js.map +1 -0
  84. package/dist/esm/llm/provider-profile.js +142 -0
  85. package/dist/esm/llm/provider-profile.js.map +1 -0
  86. package/dist/esm/llm/providers/google.js +42 -5
  87. package/dist/esm/llm/providers/google.js.map +1 -1
  88. package/dist/esm/llm/providers/models.js +13 -0
  89. package/dist/esm/llm/providers/models.js.map +1 -1
  90. package/dist/esm/llm/providers/openai.js.map +1 -1
  91. package/dist/esm/llm/transcript-to-markdown.js.map +1 -1
  92. package/dist/esm/model-auto-cli.js +89 -0
  93. package/dist/esm/model-auto-cli.js.map +1 -0
  94. package/dist/esm/model-auto-rules.js +86 -0
  95. package/dist/esm/model-auto-rules.js.map +1 -0
  96. package/dist/esm/model-auto.js +10 -245
  97. package/dist/esm/model-auto.js.map +1 -1
  98. package/dist/esm/model-spec.js +23 -17
  99. package/dist/esm/model-spec.js.map +1 -1
  100. package/dist/esm/refresh-free.js +1 -1
  101. package/dist/esm/refresh-free.js.map +1 -1
  102. package/dist/esm/run/attachments.js +1 -1
  103. package/dist/esm/run/attachments.js.map +1 -1
  104. package/dist/esm/run/bird/exec.js +23 -0
  105. package/dist/esm/run/bird/exec.js.map +1 -0
  106. package/dist/esm/run/bird/media.js +171 -0
  107. package/dist/esm/run/bird/media.js.map +1 -0
  108. package/dist/esm/run/bird/parse.js +82 -0
  109. package/dist/esm/run/bird/parse.js.map +1 -0
  110. package/dist/esm/run/bird/types.js +2 -0
  111. package/dist/esm/run/bird/types.js.map +1 -0
  112. package/dist/esm/run/bird.js +86 -144
  113. package/dist/esm/run/bird.js.map +1 -1
  114. package/dist/esm/run/cache-state.js.map +1 -1
  115. package/dist/esm/run/constants.js +2 -1
  116. package/dist/esm/run/constants.js.map +1 -1
  117. package/dist/esm/run/env.js +3 -0
  118. package/dist/esm/run/env.js.map +1 -1
  119. package/dist/esm/run/finish-line-labels.js +76 -0
  120. package/dist/esm/run/finish-line-labels.js.map +1 -0
  121. package/dist/esm/run/finish-line-lengths.js +96 -0
  122. package/dist/esm/run/finish-line-lengths.js.map +1 -0
  123. package/dist/esm/run/finish-line.js +3 -169
  124. package/dist/esm/run/finish-line.js.map +1 -1
  125. package/dist/esm/run/flows/asset/extract.js.map +1 -1
  126. package/dist/esm/run/flows/asset/input.js +1 -1
  127. package/dist/esm/run/flows/asset/input.js.map +1 -1
  128. package/dist/esm/run/flows/asset/media.js +19 -10
  129. package/dist/esm/run/flows/asset/media.js.map +1 -1
  130. package/dist/esm/run/flows/asset/output.js.map +1 -1
  131. package/dist/esm/run/flows/asset/preprocess.js.map +1 -1
  132. package/dist/esm/run/flows/asset/summary-attempts.js +109 -0
  133. package/dist/esm/run/flows/asset/summary-attempts.js.map +1 -0
  134. package/dist/esm/run/flows/asset/summary.js +19 -107
  135. package/dist/esm/run/flows/asset/summary.js.map +1 -1
  136. package/dist/esm/run/flows/url/extract.js +7 -4
  137. package/dist/esm/run/flows/url/extract.js.map +1 -1
  138. package/dist/esm/run/flows/url/flow-progress.js +119 -0
  139. package/dist/esm/run/flows/url/flow-progress.js.map +1 -0
  140. package/dist/esm/run/flows/url/flow.js +22 -93
  141. package/dist/esm/run/flows/url/flow.js.map +1 -1
  142. package/dist/esm/run/flows/url/markdown.js +21 -3
  143. package/dist/esm/run/flows/url/markdown.js.map +1 -1
  144. package/dist/esm/run/flows/url/progress-status.js +56 -0
  145. package/dist/esm/run/flows/url/progress-status.js.map +1 -0
  146. package/dist/esm/run/flows/url/slides-output-render.js +78 -0
  147. package/dist/esm/run/flows/url/slides-output-render.js.map +1 -0
  148. package/dist/esm/run/flows/url/slides-output-state.js +86 -0
  149. package/dist/esm/run/flows/url/slides-output-state.js.map +1 -0
  150. package/dist/esm/run/flows/url/slides-output-stream.js +271 -0
  151. package/dist/esm/run/flows/url/slides-output-stream.js.map +1 -0
  152. package/dist/esm/run/flows/url/slides-output.js +29 -422
  153. package/dist/esm/run/flows/url/slides-output.js.map +1 -1
  154. package/dist/esm/run/flows/url/slides-text-markdown.js +431 -0
  155. package/dist/esm/run/flows/url/slides-text-markdown.js.map +1 -0
  156. package/dist/esm/run/flows/url/slides-text-transcript.js +199 -0
  157. package/dist/esm/run/flows/url/slides-text-transcript.js.map +1 -0
  158. package/dist/esm/run/flows/url/slides-text-types.js +2 -0
  159. package/dist/esm/run/flows/url/slides-text-types.js.map +1 -0
  160. package/dist/esm/run/flows/url/slides-text.js +2 -627
  161. package/dist/esm/run/flows/url/slides-text.js.map +1 -1
  162. package/dist/esm/run/flows/url/summary-finish.js +34 -0
  163. package/dist/esm/run/flows/url/summary-finish.js.map +1 -0
  164. package/dist/esm/run/flows/url/summary-json.js +32 -0
  165. package/dist/esm/run/flows/url/summary-json.js.map +1 -0
  166. package/dist/esm/run/flows/url/summary-prompt.js +147 -0
  167. package/dist/esm/run/flows/url/summary-prompt.js.map +1 -0
  168. package/dist/esm/run/flows/url/summary-resolution.js +320 -0
  169. package/dist/esm/run/flows/url/summary-resolution.js.map +1 -0
  170. package/dist/esm/run/flows/url/summary-timestamps.js +136 -0
  171. package/dist/esm/run/flows/url/summary-timestamps.js.map +1 -0
  172. package/dist/esm/run/flows/url/summary.js +49 -543
  173. package/dist/esm/run/flows/url/summary.js.map +1 -1
  174. package/dist/esm/run/help.js +9 -3
  175. package/dist/esm/run/help.js.map +1 -1
  176. package/dist/esm/run/markdown-transforms.js +89 -0
  177. package/dist/esm/run/markdown-transforms.js.map +1 -0
  178. package/dist/esm/run/markdown.js +1 -96
  179. package/dist/esm/run/markdown.js.map +1 -1
  180. package/dist/esm/run/run-env.js +28 -7
  181. package/dist/esm/run/run-env.js.map +1 -1
  182. package/dist/esm/run/run-settings-parse.js +73 -0
  183. package/dist/esm/run/run-settings-parse.js.map +1 -0
  184. package/dist/esm/run/run-settings.js +1 -72
  185. package/dist/esm/run/run-settings.js.map +1 -1
  186. package/dist/esm/run/runner-contexts.js +116 -0
  187. package/dist/esm/run/runner-contexts.js.map +1 -0
  188. package/dist/esm/run/runner-execution.js +62 -0
  189. package/dist/esm/run/runner-execution.js.map +1 -0
  190. package/dist/esm/run/runner-flags.js +97 -0
  191. package/dist/esm/run/runner-flags.js.map +1 -0
  192. package/dist/esm/run/runner-setup.js +109 -0
  193. package/dist/esm/run/runner-setup.js.map +1 -0
  194. package/dist/esm/run/runner-slides.js +38 -0
  195. package/dist/esm/run/runner-slides.js.map +1 -0
  196. package/dist/esm/run/runner.js +99 -390
  197. package/dist/esm/run/runner.js.map +1 -1
  198. package/dist/esm/run/slides-render.js +5 -2
  199. package/dist/esm/run/slides-render.js.map +1 -1
  200. package/dist/esm/run/stdin-temp-file.js +1 -1
  201. package/dist/esm/run/stdin-temp-file.js.map +1 -1
  202. package/dist/esm/run/streaming.js +1 -0
  203. package/dist/esm/run/streaming.js.map +1 -1
  204. package/dist/esm/run/summary-engine.js +26 -10
  205. package/dist/esm/run/summary-engine.js.map +1 -1
  206. package/dist/esm/run/summary-llm.js +2 -1
  207. package/dist/esm/run/summary-llm.js.map +1 -1
  208. package/dist/esm/run/terminal.js +4 -1
  209. package/dist/esm/run/terminal.js.map +1 -1
  210. package/dist/esm/run/transcriber-cli.js +1 -1
  211. package/dist/esm/run/transcriber-cli.js.map +1 -1
  212. package/dist/esm/slides/download.js +242 -0
  213. package/dist/esm/slides/download.js.map +1 -0
  214. package/dist/esm/slides/extract-finalize.js +98 -0
  215. package/dist/esm/slides/extract-finalize.js.map +1 -0
  216. package/dist/esm/slides/extract.js +64 -1621
  217. package/dist/esm/slides/extract.js.map +1 -1
  218. package/dist/esm/slides/frame-extraction.js +372 -0
  219. package/dist/esm/slides/frame-extraction.js.map +1 -0
  220. package/dist/esm/slides/ingest.js +167 -0
  221. package/dist/esm/slides/ingest.js.map +1 -0
  222. package/dist/esm/slides/ocr.js +91 -0
  223. package/dist/esm/slides/ocr.js.map +1 -0
  224. package/dist/esm/slides/process.js +218 -0
  225. package/dist/esm/slides/process.js.map +1 -0
  226. package/dist/esm/slides/scene-detection.js +387 -0
  227. package/dist/esm/slides/scene-detection.js.map +1 -0
  228. package/dist/esm/slides/source-id.js +42 -0
  229. package/dist/esm/slides/source-id.js.map +1 -0
  230. package/dist/esm/tty/progress/fetch-html.js.map +1 -1
  231. package/dist/esm/tty/progress/transcript.js +21 -8
  232. package/dist/esm/tty/progress/transcript.js.map +1 -1
  233. package/dist/esm/tty/spinner.js +8 -2
  234. package/dist/esm/tty/spinner.js.map +1 -1
  235. package/dist/esm/tty/website-progress.js +5 -3
  236. package/dist/esm/tty/website-progress.js.map +1 -1
  237. package/dist/esm/version.js +1 -1
  238. package/dist/types/cache-keys.d.ts +44 -0
  239. package/dist/types/cache-slides-cleanup.d.ts +1 -0
  240. package/dist/types/cache.d.ts +1 -9
  241. package/dist/types/config/env.d.ts +6 -0
  242. package/dist/types/config/model.d.ts +3 -0
  243. package/dist/types/config/parse-helpers.d.ts +7 -0
  244. package/dist/types/config/read.d.ts +2 -0
  245. package/dist/types/config/sections.d.ts +33 -0
  246. package/dist/types/config/types.d.ts +230 -0
  247. package/dist/types/config.d.ts +3 -209
  248. package/dist/types/costs.d.ts +1 -1
  249. package/dist/types/daemon/agent-model.d.ts +40 -0
  250. package/dist/types/daemon/agent-request.d.ts +14 -0
  251. package/dist/types/daemon/chat.d.ts +3 -1
  252. package/dist/types/daemon/config.d.ts +13 -2
  253. package/dist/types/daemon/env-snapshot.d.ts +1 -1
  254. package/dist/types/daemon/flow-context.d.ts +1 -1
  255. package/dist/types/daemon/models.d.ts +1 -0
  256. package/dist/types/daemon/server-admin-routes.d.ts +22 -0
  257. package/dist/types/daemon/server-agent-route.d.ts +9 -0
  258. package/dist/types/daemon/server-http.d.ts +10 -0
  259. package/dist/types/daemon/server-session-routes.d.ts +11 -0
  260. package/dist/types/daemon/server-session.d.ts +52 -0
  261. package/dist/types/daemon/server-sse.d.ts +12 -0
  262. package/dist/types/daemon/server-summarize-execution.d.ts +70 -0
  263. package/dist/types/daemon/server-summarize-request.d.ts +36 -0
  264. package/dist/types/daemon/server.d.ts +3 -4
  265. package/dist/types/daemon/summarize.d.ts +1 -1
  266. package/dist/types/llm/cli-exec.d.ts +13 -0
  267. package/dist/types/llm/cli-provider-output.d.ts +16 -0
  268. package/dist/types/llm/generate-text-document.d.ts +34 -0
  269. package/dist/types/llm/generate-text-shared.d.ts +25 -0
  270. package/dist/types/llm/generate-text-stream.d.ts +26 -0
  271. package/dist/types/llm/generate-text.d.ts +6 -26
  272. package/dist/types/llm/html-to-markdown.d.ts +1 -1
  273. package/dist/types/llm/model-id.d.ts +1 -1
  274. package/dist/types/llm/provider-capabilities.d.ts +2 -0
  275. package/dist/types/llm/provider-profile.d.ts +31 -0
  276. package/dist/types/llm/providers/google.d.ts +6 -0
  277. package/dist/types/llm/providers/models.d.ts +5 -0
  278. package/dist/types/llm/transcript-to-markdown.d.ts +1 -1
  279. package/dist/types/model-auto-cli.d.ts +15 -0
  280. package/dist/types/model-auto-rules.d.ts +7 -0
  281. package/dist/types/model-auto.d.ts +5 -7
  282. package/dist/types/model-spec.d.ts +2 -2
  283. package/dist/types/run/attachments.d.ts +2 -2
  284. package/dist/types/run/bird/exec.d.ts +1 -0
  285. package/dist/types/run/bird/media.d.ts +3 -0
  286. package/dist/types/run/bird/parse.d.ts +3 -0
  287. package/dist/types/run/bird/types.d.ts +18 -0
  288. package/dist/types/run/bird.d.ts +12 -17
  289. package/dist/types/run/cache-state.d.ts +1 -1
  290. package/dist/types/run/constants.d.ts +2 -1
  291. package/dist/types/run/env.d.ts +1 -0
  292. package/dist/types/run/finish-line-labels.d.ts +29 -0
  293. package/dist/types/run/finish-line-lengths.d.ts +23 -0
  294. package/dist/types/run/finish-line.d.ts +2 -52
  295. package/dist/types/run/flows/asset/extract.d.ts +1 -1
  296. package/dist/types/run/flows/asset/input.d.ts +1 -1
  297. package/dist/types/run/flows/asset/preprocess.d.ts +1 -1
  298. package/dist/types/run/flows/asset/summary-attempts.d.ts +24 -0
  299. package/dist/types/run/flows/asset/summary.d.ts +6 -2
  300. package/dist/types/run/flows/url/flow-progress.d.ts +41 -0
  301. package/dist/types/run/flows/url/markdown.d.ts +2 -2
  302. package/dist/types/run/flows/url/progress-status.d.ts +16 -0
  303. package/dist/types/run/flows/url/slides-output-render.d.ts +43 -0
  304. package/dist/types/run/flows/url/slides-output-state.d.ts +21 -0
  305. package/dist/types/run/flows/url/slides-output-stream.d.ts +18 -0
  306. package/dist/types/run/flows/url/slides-output.d.ts +2 -17
  307. package/dist/types/run/flows/url/slides-text-markdown.d.ts +46 -0
  308. package/dist/types/run/flows/url/slides-text-transcript.d.ts +36 -0
  309. package/dist/types/run/flows/url/slides-text-types.d.ts +8 -0
  310. package/dist/types/run/flows/url/slides-text.d.ts +3 -87
  311. package/dist/types/run/flows/url/summary-finish.d.ts +16 -0
  312. package/dist/types/run/flows/url/summary-json.d.ts +51 -0
  313. package/dist/types/run/flows/url/summary-prompt.d.ts +22 -0
  314. package/dist/types/run/flows/url/summary-resolution.d.ts +31 -0
  315. package/dist/types/run/flows/url/summary-timestamps.d.ts +11 -0
  316. package/dist/types/run/flows/url/types.d.ts +4 -0
  317. package/dist/types/run/markdown-transforms.d.ts +3 -0
  318. package/dist/types/run/run-context.d.ts +4 -0
  319. package/dist/types/run/run-env.d.ts +4 -0
  320. package/dist/types/run/run-settings-parse.d.ts +5 -0
  321. package/dist/types/run/runner-contexts.d.ts +62 -0
  322. package/dist/types/run/runner-execution.d.ts +57 -0
  323. package/dist/types/run/runner-flags.d.ts +41 -0
  324. package/dist/types/run/runner-setup.d.ts +21 -0
  325. package/dist/types/run/runner-slides.d.ts +8 -0
  326. package/dist/types/run/streaming.d.ts +1 -1
  327. package/dist/types/run/summary-engine.d.ts +8 -4
  328. package/dist/types/run/summary-llm.d.ts +4 -3
  329. package/dist/types/run/terminal.d.ts +2 -0
  330. package/dist/types/run/types.d.ts +2 -2
  331. package/dist/types/slides/download.d.ts +29 -0
  332. package/dist/types/slides/extract-finalize.d.ts +57 -0
  333. package/dist/types/slides/extract.d.ts +1 -7
  334. package/dist/types/slides/frame-extraction.d.ts +38 -0
  335. package/dist/types/slides/ingest.d.ts +47 -0
  336. package/dist/types/slides/ocr.d.ts +5 -0
  337. package/dist/types/slides/process.d.ts +22 -0
  338. package/dist/types/slides/scene-detection.d.ts +75 -0
  339. package/dist/types/slides/source-id.d.ts +2 -0
  340. package/dist/types/version.d.ts +1 -1
  341. package/docs/_config.yml +1 -0
  342. package/docs/agent.md +3 -2
  343. package/docs/assets/site.css +134 -2
  344. package/docs/cache.md +2 -1
  345. package/docs/chrome-extension.md +12 -4
  346. package/docs/cli.md +2 -2
  347. package/docs/config.md +11 -4
  348. package/docs/index.html +5 -0
  349. package/docs/llm.md +5 -2
  350. package/docs/manual-tests.md +3 -0
  351. package/docs/media.md +3 -1
  352. package/docs/model-auto.md +2 -2
  353. package/docs/model-provider-resolution.md +57 -0
  354. package/docs/site/index.html +5 -0
  355. package/docs/slides-rendering-flow.md +46 -0
  356. package/docs/slides.md +5 -5
  357. package/docs/smoketest.md +1 -1
  358. package/docs/transcript-provider-flow.md +66 -0
  359. package/docs/website.md +1 -0
  360. package/docs/youtube.md +4 -2
  361. package/package.json +34 -41
@@ -1,193 +1,79 @@
1
- import { completeSimple, streamSimple } from "@mariozechner/pi-ai";
2
- import { createUnsupportedFunctionalityError } from "./errors.js";
1
+ import { completeSimple } from "@mariozechner/pi-ai";
2
+ import { maybeGenerateDocumentText } from "./generate-text-document.js";
3
+ import { computeRetryDelayMs, isGoogleEmptySummaryError, isRetryableTimeoutError, promptToContext, resolveEffectiveTemperature, resolveGoogleEmptyResponseFallbackModelId, sleep, } from "./generate-text-shared.js";
4
+ import { streamTextWithContext } from "./generate-text-stream.js";
3
5
  import { parseGatewayStyleModelId } from "./model-id.js";
4
- import { userTextAndImageMessage } from "./prompt.js";
5
- import { completeAnthropicDocument, completeAnthropicText, normalizeAnthropicModelAccessError, } from "./providers/anthropic.js";
6
- import { completeGoogleDocument, completeGoogleText } from "./providers/google.js";
7
- import { resolveAnthropicModel, resolveGoogleModel, resolveOpenAiModel, resolveXaiModel, resolveZaiModel, } from "./providers/models.js";
8
- import { completeOpenAiDocument, completeOpenAiText, resolveOpenAiClientConfig, } from "./providers/openai.js";
6
+ import { resolveOpenAiCompatibleClientConfigForProvider } from "./provider-capabilities.js";
7
+ import { completeAnthropicText, normalizeAnthropicModelAccessError, } from "./providers/anthropic.js";
8
+ import { completeGoogleText } from "./providers/google.js";
9
+ import { resolveNvidiaModel, resolveXaiModel, resolveZaiModel, } from "./providers/models.js";
10
+ import { completeOpenAiText } from "./providers/openai.js";
9
11
  import { extractText } from "./providers/shared.js";
10
12
  import { normalizeTokenUsage } from "./usage.js";
11
- function promptToContext(prompt) {
12
- const attachments = prompt.attachments ?? [];
13
- if (attachments.some((attachment) => attachment.kind === "document")) {
14
- throw new Error("Internal error: document prompt cannot be converted to context.");
15
- }
16
- if (attachments.length === 0) {
17
- return {
18
- systemPrompt: prompt.system,
19
- messages: [{ role: "user", content: prompt.userText, timestamp: Date.now() }],
20
- };
21
- }
22
- if (attachments.length !== 1 || attachments[0]?.kind !== "image") {
23
- throw new Error("Internal error: only single image attachments are supported for prompts.");
24
- }
25
- const attachment = attachments[0];
26
- const messages = [
27
- userTextAndImageMessage({
28
- text: prompt.userText,
29
- imageBytes: attachment.bytes,
30
- mimeType: attachment.mediaType,
31
- }),
32
- ];
33
- return { systemPrompt: prompt.system, messages };
34
- }
35
- function isRetryableTimeoutError(error) {
36
- if (!error)
37
- return false;
38
- const message = typeof error === "string"
39
- ? error
40
- : error instanceof Error
41
- ? error.message
42
- : typeof error.message === "string"
43
- ? String(error.message)
44
- : "";
45
- return /timed out/i.test(message) || /empty summary/i.test(message);
46
- }
47
- function computeRetryDelayMs(attempt) {
48
- const base = 500;
49
- const jitter = Math.floor(Math.random() * 200);
50
- return Math.min(2000, base * (attempt + 1) + jitter);
51
- }
52
- function sleep(ms) {
53
- return new Promise((resolve) => setTimeout(resolve, ms));
54
- }
55
- async function withTimeoutFallback({ promise, timeoutMs, fallback, }) {
56
- const effectiveTimeoutMs = Number.isFinite(timeoutMs) && timeoutMs > 0 ? Math.floor(timeoutMs) : 30_000;
57
- let timer = null;
58
- try {
59
- return await Promise.race([
60
- promise,
61
- new Promise((resolve) => {
62
- timer = setTimeout(() => resolve(fallback), effectiveTimeoutMs);
63
- }),
64
- ]);
65
- }
66
- finally {
67
- if (timer)
68
- clearTimeout(timer);
69
- }
70
- }
71
- function streamUsageWithTimeout({ result, timeoutMs, }) {
72
- const normalized = result.then((msg) => normalizeTokenUsage(msg.usage)).catch(() => null);
73
- return withTimeoutFallback({
74
- promise: normalized,
75
- timeoutMs,
76
- fallback: null,
77
- });
78
- }
79
- function isOpenaiGpt5Model(parsed) {
80
- return parsed.provider === "openai" && /^gpt-5([-.].+)?$/i.test(parsed.model);
81
- }
82
- function resolveEffectiveTemperature({ parsed, temperature, }) {
83
- if (typeof temperature !== "number")
84
- return undefined;
85
- if (isOpenaiGpt5Model(parsed))
86
- return undefined;
87
- return temperature;
88
- }
89
- export async function generateTextWithModelId({ modelId, apiKeys, prompt, temperature, maxOutputTokens, timeoutMs, fetchImpl, forceOpenRouter, openaiBaseUrlOverride, anthropicBaseUrlOverride, googleBaseUrlOverride, xaiBaseUrlOverride, forceChatCompletions, retries = 0, onRetry, }) {
13
+ export { streamTextWithContext } from "./generate-text-stream.js";
14
+ export async function generateTextWithModelId({ modelId, apiKeys, prompt, temperature, maxOutputTokens, timeoutMs, fetchImpl, forceOpenRouter, openaiBaseUrlOverride, anthropicBaseUrlOverride, googleBaseUrlOverride, xaiBaseUrlOverride, zaiBaseUrlOverride, forceChatCompletions, retries = 0, onRetry, }) {
90
15
  const parsed = parseGatewayStyleModelId(modelId);
91
- const effectiveTemperature = resolveEffectiveTemperature({ parsed, temperature });
92
- const attachments = prompt.attachments ?? [];
93
- const documentAttachment = attachments.find((attachment) => attachment.kind === "document") ?? null;
94
- if (documentAttachment) {
95
- if (attachments.length !== 1) {
96
- throw new Error("Internal error: document attachments cannot be combined with other inputs.");
97
- }
98
- if (parsed.provider === "anthropic") {
99
- const apiKey = apiKeys.anthropicApiKey;
100
- if (!apiKey)
101
- throw new Error("Missing ANTHROPIC_API_KEY for anthropic/... model");
102
- try {
103
- const result = await completeAnthropicDocument({
104
- modelId: parsed.model,
105
- apiKey,
106
- promptText: prompt.userText,
107
- document: documentAttachment,
108
- system: prompt.system,
109
- maxOutputTokens,
110
- timeoutMs,
111
- fetchImpl,
112
- anthropicBaseUrlOverride,
113
- });
114
- return {
115
- text: result.text,
116
- canonicalModelId: parsed.canonical,
117
- provider: parsed.provider,
118
- usage: result.usage,
119
- };
120
- }
121
- catch (error) {
122
- const normalized = normalizeAnthropicModelAccessError(error, parsed.model);
123
- if (normalized)
124
- throw normalized;
125
- throw error;
126
- }
127
- }
128
- if (parsed.provider === "openai") {
129
- const openaiConfig = resolveOpenAiClientConfig({
130
- apiKeys: {
131
- openaiApiKey: apiKeys.openaiApiKey,
132
- openrouterApiKey: apiKeys.openrouterApiKey,
133
- },
134
- forceOpenRouter,
135
- openaiBaseUrlOverride,
136
- forceChatCompletions,
137
- });
138
- const result = await completeOpenAiDocument({
139
- modelId: parsed.model,
140
- openaiConfig,
141
- promptText: prompt.userText,
142
- document: documentAttachment,
143
- maxOutputTokens,
144
- temperature: effectiveTemperature,
145
- timeoutMs,
146
- fetchImpl,
147
- });
148
- return {
149
- text: result.text,
150
- canonicalModelId: parsed.canonical,
151
- provider: parsed.provider,
152
- usage: result.usage,
153
- };
154
- }
155
- if (parsed.provider === "google") {
156
- const apiKey = apiKeys.googleApiKey;
157
- if (!apiKey)
158
- throw new Error("Missing GEMINI_API_KEY (or GOOGLE_GENERATIVE_AI_API_KEY / GOOGLE_API_KEY) for google/... model");
159
- const result = await completeGoogleDocument({
160
- modelId: parsed.model,
161
- apiKey,
162
- promptText: prompt.userText,
163
- document: documentAttachment,
164
- maxOutputTokens,
165
- temperature: effectiveTemperature,
166
- timeoutMs,
167
- fetchImpl,
168
- googleBaseUrlOverride,
169
- });
170
- return {
171
- text: result.text,
172
- canonicalModelId: parsed.canonical,
173
- provider: parsed.provider,
174
- usage: result.usage,
175
- };
176
- }
177
- throw createUnsupportedFunctionalityError(`document attachments are not supported for ${parsed.provider}/... models`);
178
- }
179
- const context = promptToContext(prompt);
180
- const openaiConfig = parsed.provider === "openai"
181
- ? resolveOpenAiClientConfig({
182
- apiKeys: {
183
- openaiApiKey: apiKeys.openaiApiKey,
184
- openrouterApiKey: apiKeys.openrouterApiKey,
185
- },
16
+ const effectiveTemperature = resolveEffectiveTemperature({
17
+ provider: parsed.provider,
18
+ model: parsed.model,
19
+ temperature,
20
+ });
21
+ const documentResult = await maybeGenerateDocumentText({
22
+ parsed,
23
+ apiKeys,
24
+ prompt,
25
+ maxOutputTokens,
26
+ temperature: effectiveTemperature,
27
+ timeoutMs,
28
+ fetchImpl,
29
+ forceOpenRouter,
30
+ openaiBaseUrlOverride,
31
+ anthropicBaseUrlOverride,
32
+ googleBaseUrlOverride,
33
+ forceChatCompletions,
34
+ retryWithModelId: (fallbackModelId) => generateTextWithModelId({
35
+ modelId: fallbackModelId,
36
+ apiKeys,
37
+ prompt,
38
+ temperature,
39
+ maxOutputTokens,
40
+ timeoutMs,
41
+ fetchImpl,
186
42
  forceOpenRouter,
187
43
  openaiBaseUrlOverride,
44
+ anthropicBaseUrlOverride,
45
+ googleBaseUrlOverride,
46
+ xaiBaseUrlOverride,
47
+ zaiBaseUrlOverride,
188
48
  forceChatCompletions,
189
- })
190
- : null;
49
+ retries,
50
+ onRetry,
51
+ }),
52
+ });
53
+ if (documentResult) {
54
+ return documentResult;
55
+ }
56
+ const context = promptToContext(prompt);
57
+ const resolveOpenAiConfig = () => resolveOpenAiCompatibleClientConfigForProvider({
58
+ provider: "openai",
59
+ openaiApiKey: apiKeys.openaiApiKey,
60
+ openrouterApiKey: apiKeys.openrouterApiKey,
61
+ forceOpenRouter,
62
+ openaiBaseUrlOverride,
63
+ forceChatCompletions,
64
+ });
65
+ const completeSimpleText = async ({ model, apiKey, signal, }) => {
66
+ const result = await completeSimple(model, context, {
67
+ ...(typeof effectiveTemperature === "number" ? { temperature: effectiveTemperature } : {}),
68
+ ...(typeof maxOutputTokens === "number" ? { maxTokens: maxOutputTokens } : {}),
69
+ apiKey,
70
+ signal,
71
+ });
72
+ const text = extractText(result);
73
+ if (!text)
74
+ throw new Error(`LLM returned an empty summary (model ${parsed.canonical}).`);
75
+ return { text, usage: normalizeTokenUsage(result.usage) };
76
+ };
191
77
  const maxRetries = Math.max(0, retries);
192
78
  let attempt = 0;
193
79
  while (attempt <= maxRetries) {
@@ -262,54 +148,100 @@ export async function generateTextWithModelId({ modelId, apiKeys, prompt, temper
262
148
  };
263
149
  }
264
150
  if (parsed.provider === "zai") {
265
- const apiKey = apiKeys.openaiApiKey;
266
- if (!apiKey)
267
- throw new Error("Missing Z_AI_API_KEY for zai/... model");
151
+ const openaiConfig = resolveOpenAiCompatibleClientConfigForProvider({
152
+ provider: "zai",
153
+ openaiApiKey: apiKeys.openaiApiKey,
154
+ openrouterApiKey: apiKeys.openrouterApiKey,
155
+ openaiBaseUrlOverride: zaiBaseUrlOverride ?? openaiBaseUrlOverride,
156
+ });
268
157
  const model = resolveZaiModel({
269
158
  modelId: parsed.model,
270
159
  context,
160
+ openaiBaseUrlOverride: openaiConfig.baseURL,
161
+ });
162
+ const result = await completeSimpleText({
163
+ model,
164
+ apiKey: openaiConfig.apiKey,
165
+ signal: controller.signal,
166
+ });
167
+ return {
168
+ text: result.text,
169
+ canonicalModelId: parsed.canonical,
170
+ provider: parsed.provider,
171
+ usage: result.usage,
172
+ };
173
+ }
174
+ if (parsed.provider === "nvidia") {
175
+ const openaiConfig = resolveOpenAiCompatibleClientConfigForProvider({
176
+ provider: "nvidia",
177
+ openaiApiKey: apiKeys.openaiApiKey,
178
+ openrouterApiKey: apiKeys.openrouterApiKey,
271
179
  openaiBaseUrlOverride,
272
180
  });
273
- const result = await completeSimple(model, context, {
274
- ...(typeof effectiveTemperature === "number"
275
- ? { temperature: effectiveTemperature }
276
- : {}),
277
- ...(typeof maxOutputTokens === "number" ? { maxTokens: maxOutputTokens } : {}),
278
- apiKey,
181
+ const model = resolveNvidiaModel({
182
+ modelId: parsed.model,
183
+ context,
184
+ openaiBaseUrlOverride: openaiConfig.baseURL,
185
+ });
186
+ const result = await completeSimpleText({
187
+ model,
188
+ apiKey: openaiConfig.apiKey,
279
189
  signal: controller.signal,
280
190
  });
281
- const text = extractText(result);
282
- if (!text)
283
- throw new Error(`LLM returned an empty summary (model ${parsed.canonical}).`);
284
191
  return {
285
- text,
192
+ text: result.text,
286
193
  canonicalModelId: parsed.canonical,
287
194
  provider: parsed.provider,
288
- usage: normalizeTokenUsage(result.usage),
195
+ usage: result.usage,
289
196
  };
290
197
  }
291
- if (!openaiConfig) {
292
- throw new Error("Missing OPENAI_API_KEY for openai/... model");
198
+ if (parsed.provider === "openai") {
199
+ const openaiConfig = resolveOpenAiConfig();
200
+ const result = await completeOpenAiText({
201
+ modelId: parsed.model,
202
+ openaiConfig,
203
+ context,
204
+ temperature: effectiveTemperature,
205
+ maxOutputTokens,
206
+ signal: controller.signal,
207
+ });
208
+ return {
209
+ text: result.text,
210
+ canonicalModelId: parsed.canonical,
211
+ provider: parsed.provider,
212
+ usage: result.usage,
213
+ };
293
214
  }
294
- const result = await completeOpenAiText({
295
- modelId: parsed.model,
296
- openaiConfig,
297
- context,
298
- temperature: effectiveTemperature,
299
- maxOutputTokens,
300
- signal: controller.signal,
301
- });
302
- return {
303
- text: result.text,
304
- canonicalModelId: parsed.canonical,
305
- provider: parsed.provider,
306
- usage: result.usage,
307
- };
215
+ /* v8 ignore next */
216
+ throw new Error(`Unknown provider ${parsed.provider}`);
308
217
  }
309
218
  catch (error) {
310
219
  const normalizedError = error instanceof DOMException && error.name === "AbortError"
311
220
  ? new Error(`LLM request timed out after ${timeoutMs}ms (model ${parsed.canonical}).`)
312
221
  : error;
222
+ const googleFallbackModelId = parsed.provider === "google" &&
223
+ isGoogleEmptySummaryError(normalizedError) &&
224
+ resolveGoogleEmptyResponseFallbackModelId(parsed.canonical);
225
+ if (googleFallbackModelId) {
226
+ return generateTextWithModelId({
227
+ modelId: googleFallbackModelId,
228
+ apiKeys,
229
+ prompt,
230
+ temperature,
231
+ maxOutputTokens,
232
+ timeoutMs,
233
+ fetchImpl,
234
+ forceOpenRouter,
235
+ openaiBaseUrlOverride,
236
+ anthropicBaseUrlOverride,
237
+ googleBaseUrlOverride,
238
+ xaiBaseUrlOverride,
239
+ zaiBaseUrlOverride,
240
+ forceChatCompletions,
241
+ retries: Math.max(0, maxRetries - attempt),
242
+ onRetry,
243
+ });
244
+ }
313
245
  if (parsed.provider === "anthropic") {
314
246
  const normalized = normalizeAnthropicModelAccessError(normalizedError, parsed.model);
315
247
  if (normalized)
@@ -348,271 +280,4 @@ export async function streamTextWithModelId({ modelId, apiKeys, prompt, temperat
348
280
  forceChatCompletions,
349
281
  });
350
282
  }
351
- export async function streamTextWithContext({ modelId, apiKeys, context, temperature, maxOutputTokens, timeoutMs, fetchImpl, forceOpenRouter, openaiBaseUrlOverride, anthropicBaseUrlOverride, googleBaseUrlOverride, xaiBaseUrlOverride, forceChatCompletions, }) {
352
- const parsed = parseGatewayStyleModelId(modelId);
353
- const effectiveTemperature = resolveEffectiveTemperature({ parsed, temperature });
354
- void fetchImpl;
355
- const controller = new AbortController();
356
- let timeoutId = null;
357
- const startedAtMs = Date.now();
358
- let lastError = null;
359
- const timeoutError = new Error("LLM request timed out");
360
- const markTimedOut = () => {
361
- if (lastError === timeoutError)
362
- return;
363
- lastError = timeoutError;
364
- controller.abort();
365
- };
366
- const startTimeout = () => {
367
- if (timeoutId)
368
- return;
369
- timeoutId = setTimeout(markTimedOut, timeoutMs);
370
- };
371
- const stopTimeout = () => {
372
- if (!timeoutId)
373
- return;
374
- clearTimeout(timeoutId);
375
- timeoutId = null;
376
- };
377
- const nextWithDeadline = async (promise) => {
378
- const elapsed = Date.now() - startedAtMs;
379
- const remaining = timeoutMs - elapsed;
380
- if (remaining <= 0) {
381
- markTimedOut();
382
- throw timeoutError;
383
- }
384
- let timer = null;
385
- try {
386
- return await Promise.race([
387
- promise,
388
- new Promise((_, reject) => {
389
- timer = setTimeout(() => {
390
- markTimedOut();
391
- reject(timeoutError);
392
- }, remaining);
393
- }),
394
- ]);
395
- }
396
- finally {
397
- if (timer)
398
- clearTimeout(timer);
399
- }
400
- };
401
- const wrapTextStream = (textStream) => ({
402
- async *[Symbol.asyncIterator]() {
403
- startTimeout();
404
- const iterator = textStream[Symbol.asyncIterator]();
405
- try {
406
- while (true) {
407
- const result = await nextWithDeadline(iterator.next());
408
- if (result.done)
409
- break;
410
- yield result.value;
411
- }
412
- }
413
- finally {
414
- stopTimeout();
415
- if (typeof iterator.return === "function") {
416
- const cleanup = iterator.return();
417
- const cleanupPromise = typeof cleanup === "undefined" ? undefined : cleanup;
418
- if (typeof cleanupPromise?.catch === "function") {
419
- void cleanupPromise.catch(() => { });
420
- }
421
- }
422
- }
423
- },
424
- });
425
- try {
426
- if (parsed.provider === "xai") {
427
- const apiKey = apiKeys.xaiApiKey;
428
- if (!apiKey)
429
- throw new Error("Missing XAI_API_KEY for xai/... model");
430
- const model = resolveXaiModel({
431
- modelId: parsed.model,
432
- context,
433
- xaiBaseUrlOverride,
434
- });
435
- const stream = streamSimple(model, context, {
436
- ...(typeof effectiveTemperature === "number" ? { temperature: effectiveTemperature } : {}),
437
- ...(typeof maxOutputTokens === "number" ? { maxTokens: maxOutputTokens } : {}),
438
- apiKey,
439
- signal: controller.signal,
440
- });
441
- const textStream = {
442
- async *[Symbol.asyncIterator]() {
443
- for await (const event of stream) {
444
- if (event.type === "text_delta")
445
- yield event.delta;
446
- if (event.type === "error") {
447
- lastError = event.error;
448
- break;
449
- }
450
- }
451
- },
452
- };
453
- return {
454
- textStream: wrapTextStream(textStream),
455
- canonicalModelId: parsed.canonical,
456
- provider: parsed.provider,
457
- usage: streamUsageWithTimeout({ result: stream.result(), timeoutMs }),
458
- lastError: () => lastError,
459
- };
460
- }
461
- if (parsed.provider === "google") {
462
- const apiKey = apiKeys.googleApiKey;
463
- if (!apiKey)
464
- throw new Error("Missing GEMINI_API_KEY (or GOOGLE_GENERATIVE_AI_API_KEY / GOOGLE_API_KEY) for google/... model");
465
- const model = resolveGoogleModel({
466
- modelId: parsed.model,
467
- context,
468
- googleBaseUrlOverride,
469
- });
470
- const stream = streamSimple(model, context, {
471
- ...(typeof effectiveTemperature === "number" ? { temperature: effectiveTemperature } : {}),
472
- ...(typeof maxOutputTokens === "number" ? { maxTokens: maxOutputTokens } : {}),
473
- apiKey,
474
- signal: controller.signal,
475
- });
476
- const textStream = {
477
- async *[Symbol.asyncIterator]() {
478
- for await (const event of stream) {
479
- if (event.type === "text_delta")
480
- yield event.delta;
481
- if (event.type === "error") {
482
- lastError = event.error;
483
- break;
484
- }
485
- }
486
- },
487
- };
488
- return {
489
- textStream: wrapTextStream(textStream),
490
- canonicalModelId: parsed.canonical,
491
- provider: parsed.provider,
492
- usage: streamUsageWithTimeout({ result: stream.result(), timeoutMs }),
493
- lastError: () => lastError,
494
- };
495
- }
496
- if (parsed.provider === "anthropic") {
497
- const apiKey = apiKeys.anthropicApiKey;
498
- if (!apiKey)
499
- throw new Error("Missing ANTHROPIC_API_KEY for anthropic/... model");
500
- const model = resolveAnthropicModel({
501
- modelId: parsed.model,
502
- context,
503
- anthropicBaseUrlOverride,
504
- });
505
- const stream = streamSimple(model, context, {
506
- ...(typeof effectiveTemperature === "number" ? { temperature: effectiveTemperature } : {}),
507
- ...(typeof maxOutputTokens === "number" ? { maxTokens: maxOutputTokens } : {}),
508
- apiKey,
509
- signal: controller.signal,
510
- });
511
- const textStream = {
512
- async *[Symbol.asyncIterator]() {
513
- for await (const event of stream) {
514
- if (event.type === "text_delta")
515
- yield event.delta;
516
- if (event.type === "error") {
517
- lastError =
518
- normalizeAnthropicModelAccessError(event.error, parsed.model) ?? event.error;
519
- break;
520
- }
521
- }
522
- },
523
- };
524
- return {
525
- textStream: wrapTextStream(textStream),
526
- canonicalModelId: parsed.canonical,
527
- provider: parsed.provider,
528
- usage: streamUsageWithTimeout({ result: stream.result(), timeoutMs }),
529
- lastError: () => lastError,
530
- };
531
- }
532
- if (parsed.provider === "zai") {
533
- const apiKey = apiKeys.openaiApiKey;
534
- if (!apiKey)
535
- throw new Error("Missing Z_AI_API_KEY for zai/... model");
536
- const model = resolveZaiModel({
537
- modelId: parsed.model,
538
- context,
539
- openaiBaseUrlOverride,
540
- });
541
- const stream = streamSimple(model, context, {
542
- ...(typeof effectiveTemperature === "number" ? { temperature: effectiveTemperature } : {}),
543
- ...(typeof maxOutputTokens === "number" ? { maxTokens: maxOutputTokens } : {}),
544
- apiKey,
545
- signal: controller.signal,
546
- });
547
- const textStream = {
548
- async *[Symbol.asyncIterator]() {
549
- for await (const event of stream) {
550
- if (event.type === "text_delta")
551
- yield event.delta;
552
- if (event.type === "error") {
553
- lastError = event.error;
554
- break;
555
- }
556
- }
557
- },
558
- };
559
- return {
560
- textStream: wrapTextStream(textStream),
561
- canonicalModelId: parsed.canonical,
562
- provider: parsed.provider,
563
- usage: streamUsageWithTimeout({ result: stream.result(), timeoutMs }),
564
- lastError: () => lastError,
565
- };
566
- }
567
- const openaiConfig = resolveOpenAiClientConfig({
568
- apiKeys: {
569
- openaiApiKey: apiKeys.openaiApiKey,
570
- openrouterApiKey: apiKeys.openrouterApiKey,
571
- },
572
- forceOpenRouter,
573
- openaiBaseUrlOverride,
574
- forceChatCompletions,
575
- });
576
- const model = resolveOpenAiModel({ modelId: parsed.model, context, openaiConfig });
577
- const stream = streamSimple(model, context, {
578
- ...(typeof effectiveTemperature === "number" ? { temperature: effectiveTemperature } : {}),
579
- ...(typeof maxOutputTokens === "number" ? { maxTokens: maxOutputTokens } : {}),
580
- apiKey: openaiConfig.apiKey,
581
- signal: controller.signal,
582
- });
583
- const textStream = {
584
- async *[Symbol.asyncIterator]() {
585
- for await (const event of stream) {
586
- if (event.type === "text_delta")
587
- yield event.delta;
588
- if (event.type === "error") {
589
- lastError = event.error;
590
- break;
591
- }
592
- }
593
- },
594
- };
595
- return {
596
- textStream: wrapTextStream(textStream),
597
- canonicalModelId: parsed.canonical,
598
- provider: parsed.provider,
599
- usage: streamUsageWithTimeout({ result: stream.result(), timeoutMs }),
600
- lastError: () => lastError,
601
- };
602
- }
603
- catch (error) {
604
- if (parsed.provider === "anthropic") {
605
- const normalized = normalizeAnthropicModelAccessError(error, parsed.model);
606
- if (normalized)
607
- throw normalized;
608
- }
609
- if (error instanceof DOMException && error.name === "AbortError") {
610
- throw new Error("LLM request timed out");
611
- }
612
- throw error;
613
- }
614
- finally {
615
- stopTimeout();
616
- }
617
- }
618
283
  //# sourceMappingURL=generate-text.js.map