@fgv/ts-extras 5.1.0-3 → 5.1.0-31

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 (334) hide show
  1. package/dist/index.browser.js +4 -2
  2. package/dist/index.browser.js.map +1 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/packlets/ai-assist/apiClient.js +958 -131
  5. package/dist/packlets/ai-assist/apiClient.js.map +1 -0
  6. package/dist/packlets/ai-assist/chatRequestBuilders.js +186 -0
  7. package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  8. package/dist/packlets/ai-assist/converters.js +2 -1
  9. package/dist/packlets/ai-assist/converters.js.map +1 -0
  10. package/dist/packlets/ai-assist/endpoint.js +78 -0
  11. package/dist/packlets/ai-assist/endpoint.js.map +1 -0
  12. package/dist/packlets/ai-assist/imageOptionsResolver.js +212 -0
  13. package/dist/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  14. package/dist/packlets/ai-assist/index.js +7 -3
  15. package/dist/packlets/ai-assist/index.js.map +1 -0
  16. package/dist/packlets/ai-assist/jsonCompletion.js +95 -0
  17. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -0
  18. package/dist/packlets/ai-assist/jsonResponse.js +149 -0
  19. package/dist/packlets/ai-assist/jsonResponse.js.map +1 -0
  20. package/dist/packlets/ai-assist/model.js +21 -4
  21. package/dist/packlets/ai-assist/model.js.map +1 -0
  22. package/dist/packlets/ai-assist/registry.js +235 -10
  23. package/dist/packlets/ai-assist/registry.js.map +1 -0
  24. package/dist/packlets/ai-assist/sseParser.js +123 -0
  25. package/dist/packlets/ai-assist/sseParser.js.map +1 -0
  26. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +197 -0
  27. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  28. package/dist/packlets/ai-assist/streamingAdapters/common.js +79 -0
  29. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  30. package/dist/packlets/ai-assist/streamingAdapters/gemini.js +172 -0
  31. package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  32. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +165 -0
  33. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  34. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +179 -0
  35. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  36. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +163 -0
  37. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  38. package/dist/packlets/ai-assist/streamingClient.js +116 -0
  39. package/dist/packlets/ai-assist/streamingClient.js.map +1 -0
  40. package/dist/packlets/ai-assist/thinkingOptionsResolver.js +265 -0
  41. package/dist/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  42. package/dist/packlets/ai-assist/toolFormats.js.map +1 -0
  43. package/dist/packlets/conversion/converters.js +35 -1
  44. package/dist/packlets/conversion/converters.js.map +1 -0
  45. package/dist/packlets/conversion/index.js.map +1 -0
  46. package/dist/packlets/crypto-utils/constants.js.map +1 -0
  47. package/dist/packlets/crypto-utils/converters.js +24 -4
  48. package/dist/packlets/crypto-utils/converters.js.map +1 -0
  49. package/dist/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  50. package/dist/packlets/crypto-utils/encryptedFile.js.map +1 -0
  51. package/dist/packlets/crypto-utils/hpkeProvider.js +333 -0
  52. package/dist/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  53. package/dist/packlets/crypto-utils/index.browser.js +7 -0
  54. package/dist/packlets/crypto-utils/index.browser.js.map +1 -0
  55. package/dist/packlets/crypto-utils/index.js +6 -0
  56. package/dist/packlets/crypto-utils/index.js.map +1 -0
  57. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js +71 -0
  58. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  59. package/dist/packlets/crypto-utils/keystore/converters.js +103 -11
  60. package/dist/packlets/crypto-utils/keystore/converters.js.map +1 -0
  61. package/dist/packlets/crypto-utils/keystore/index.js +1 -0
  62. package/dist/packlets/crypto-utils/keystore/index.js.map +1 -0
  63. package/dist/packlets/crypto-utils/keystore/keyStore.js +618 -118
  64. package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  65. package/dist/packlets/crypto-utils/keystore/model.js +22 -1
  66. package/dist/packlets/crypto-utils/keystore/model.js.map +1 -0
  67. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js +21 -0
  68. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  69. package/dist/packlets/crypto-utils/model.js +32 -0
  70. package/dist/packlets/crypto-utils/model.js.map +1 -0
  71. package/dist/packlets/crypto-utils/nodeCryptoProvider.js +270 -1
  72. package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  73. package/dist/packlets/crypto-utils/spkiHelpers.js +130 -0
  74. package/dist/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  75. package/dist/packlets/csv/csvFileHelpers.js +0 -14
  76. package/dist/packlets/csv/csvFileHelpers.js.map +1 -0
  77. package/dist/packlets/csv/csvHelpers.js +14 -0
  78. package/dist/packlets/csv/csvHelpers.js.map +1 -0
  79. package/dist/packlets/csv/index.browser.js +1 -3
  80. package/dist/packlets/csv/index.browser.js.map +1 -0
  81. package/dist/packlets/csv/index.js.map +1 -0
  82. package/dist/packlets/experimental/extendedArray.js.map +1 -0
  83. package/dist/packlets/experimental/formatter.js.map +1 -0
  84. package/dist/packlets/experimental/index.js.map +1 -0
  85. package/dist/packlets/experimental/rangeOf.js.map +1 -0
  86. package/dist/packlets/hash/index.browser.js.map +1 -0
  87. package/dist/packlets/hash/index.js.map +1 -0
  88. package/dist/packlets/hash/index.node.js.map +1 -0
  89. package/dist/packlets/hash/md5Normalizer.browser.js.map +1 -0
  90. package/dist/packlets/hash/md5Normalizer.js.map +1 -0
  91. package/dist/packlets/mustache/index.js.map +1 -0
  92. package/dist/packlets/mustache/interfaces.js.map +1 -0
  93. package/dist/packlets/mustache/mustacheTemplate.js +42 -4
  94. package/dist/packlets/mustache/mustacheTemplate.js.map +1 -0
  95. package/dist/packlets/record-jar/index.browser.js +1 -3
  96. package/dist/packlets/record-jar/index.browser.js.map +1 -0
  97. package/dist/packlets/record-jar/index.js.map +1 -0
  98. package/dist/packlets/record-jar/recordJarFileHelpers.js +0 -18
  99. package/dist/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  100. package/dist/packlets/record-jar/recordJarHelpers.js +18 -0
  101. package/dist/packlets/record-jar/recordJarHelpers.js.map +1 -0
  102. package/dist/packlets/yaml/converters.js.map +1 -0
  103. package/dist/packlets/yaml/index.js +1 -0
  104. package/dist/packlets/yaml/index.js.map +1 -0
  105. package/dist/packlets/yaml/serializers.js +48 -0
  106. package/dist/packlets/yaml/serializers.js.map +1 -0
  107. package/dist/packlets/zip-file-tree/index.js.map +1 -0
  108. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js +2 -2
  109. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  110. package/dist/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  111. package/dist/ts-extras.d.ts +2869 -154
  112. package/dist/tsdoc-metadata.json +1 -1
  113. package/lib/index.browser.d.ts +4 -2
  114. package/lib/index.browser.d.ts.map +1 -0
  115. package/lib/index.browser.js +8 -3
  116. package/lib/index.browser.js.map +1 -0
  117. package/lib/index.d.ts.map +1 -0
  118. package/lib/index.js.map +1 -0
  119. package/lib/packlets/ai-assist/apiClient.d.ts +99 -16
  120. package/lib/packlets/ai-assist/apiClient.d.ts.map +1 -0
  121. package/lib/packlets/ai-assist/apiClient.js +961 -130
  122. package/lib/packlets/ai-assist/apiClient.js.map +1 -0
  123. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +89 -0
  124. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -0
  125. package/lib/packlets/ai-assist/chatRequestBuilders.js +195 -0
  126. package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  127. package/lib/packlets/ai-assist/converters.d.ts.map +1 -0
  128. package/lib/packlets/ai-assist/converters.js +2 -1
  129. package/lib/packlets/ai-assist/converters.js.map +1 -0
  130. package/lib/packlets/ai-assist/endpoint.d.ts +28 -0
  131. package/lib/packlets/ai-assist/endpoint.d.ts.map +1 -0
  132. package/lib/packlets/ai-assist/endpoint.js +82 -0
  133. package/lib/packlets/ai-assist/endpoint.js.map +1 -0
  134. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts +74 -0
  135. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts.map +1 -0
  136. package/lib/packlets/ai-assist/imageOptionsResolver.js +216 -0
  137. package/lib/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  138. package/lib/packlets/ai-assist/index.d.ts +7 -3
  139. package/lib/packlets/ai-assist/index.d.ts.map +1 -0
  140. package/lib/packlets/ai-assist/index.js +21 -1
  141. package/lib/packlets/ai-assist/index.js.map +1 -0
  142. package/lib/packlets/ai-assist/jsonCompletion.d.ts +93 -0
  143. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -0
  144. package/lib/packlets/ai-assist/jsonCompletion.js +99 -0
  145. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -0
  146. package/lib/packlets/ai-assist/jsonResponse.d.ts +91 -0
  147. package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -0
  148. package/lib/packlets/ai-assist/jsonResponse.js +154 -0
  149. package/lib/packlets/ai-assist/jsonResponse.js.map +1 -0
  150. package/lib/packlets/ai-assist/model.d.ts +720 -7
  151. package/lib/packlets/ai-assist/model.d.ts.map +1 -0
  152. package/lib/packlets/ai-assist/model.js +22 -4
  153. package/lib/packlets/ai-assist/model.js.map +1 -0
  154. package/lib/packlets/ai-assist/registry.d.ts +34 -1
  155. package/lib/packlets/ai-assist/registry.d.ts.map +1 -0
  156. package/lib/packlets/ai-assist/registry.js +238 -11
  157. package/lib/packlets/ai-assist/registry.js.map +1 -0
  158. package/lib/packlets/ai-assist/sseParser.d.ts +45 -0
  159. package/lib/packlets/ai-assist/sseParser.d.ts.map +1 -0
  160. package/lib/packlets/ai-assist/sseParser.js +128 -0
  161. package/lib/packlets/ai-assist/sseParser.js.map +1 -0
  162. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +19 -0
  163. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -0
  164. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +200 -0
  165. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  166. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +83 -0
  167. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -0
  168. package/lib/packlets/ai-assist/streamingAdapters/common.js +83 -0
  169. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  170. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts +20 -0
  171. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -0
  172. package/lib/packlets/ai-assist/streamingAdapters/gemini.js +175 -0
  173. package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  174. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts +19 -0
  175. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts.map +1 -0
  176. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js +168 -0
  177. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  178. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +20 -0
  179. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -0
  180. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +182 -0
  181. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  182. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts +34 -0
  183. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -0
  184. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +166 -0
  185. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  186. package/lib/packlets/ai-assist/streamingClient.d.ts +33 -0
  187. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -0
  188. package/lib/packlets/ai-assist/streamingClient.js +121 -0
  189. package/lib/packlets/ai-assist/streamingClient.js.map +1 -0
  190. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts +71 -0
  191. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts.map +1 -0
  192. package/lib/packlets/ai-assist/thinkingOptionsResolver.js +270 -0
  193. package/lib/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  194. package/lib/packlets/ai-assist/toolFormats.d.ts.map +1 -0
  195. package/lib/packlets/ai-assist/toolFormats.js.map +1 -0
  196. package/lib/packlets/conversion/converters.d.ts +8 -1
  197. package/lib/packlets/conversion/converters.d.ts.map +1 -0
  198. package/lib/packlets/conversion/converters.js +36 -2
  199. package/lib/packlets/conversion/converters.js.map +1 -0
  200. package/lib/packlets/conversion/index.d.ts.map +1 -0
  201. package/lib/packlets/conversion/index.js.map +1 -0
  202. package/lib/packlets/crypto-utils/constants.d.ts.map +1 -0
  203. package/lib/packlets/crypto-utils/constants.js.map +1 -0
  204. package/lib/packlets/crypto-utils/converters.d.ts +12 -1
  205. package/lib/packlets/crypto-utils/converters.d.ts.map +1 -0
  206. package/lib/packlets/crypto-utils/converters.js +25 -5
  207. package/lib/packlets/crypto-utils/converters.js.map +1 -0
  208. package/lib/packlets/crypto-utils/directEncryptionProvider.d.ts.map +1 -0
  209. package/lib/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  210. package/lib/packlets/crypto-utils/encryptedFile.d.ts.map +1 -0
  211. package/lib/packlets/crypto-utils/encryptedFile.js.map +1 -0
  212. package/lib/packlets/crypto-utils/hpkeProvider.d.ts +142 -0
  213. package/lib/packlets/crypto-utils/hpkeProvider.d.ts.map +1 -0
  214. package/lib/packlets/crypto-utils/hpkeProvider.js +337 -0
  215. package/lib/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  216. package/lib/packlets/crypto-utils/index.browser.d.ts +3 -0
  217. package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -0
  218. package/lib/packlets/crypto-utils/index.browser.js +14 -1
  219. package/lib/packlets/crypto-utils/index.browser.js.map +1 -0
  220. package/lib/packlets/crypto-utils/index.d.ts +3 -0
  221. package/lib/packlets/crypto-utils/index.d.ts.map +1 -0
  222. package/lib/packlets/crypto-utils/index.js +13 -1
  223. package/lib/packlets/crypto-utils/index.js.map +1 -0
  224. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts +54 -0
  225. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts.map +1 -0
  226. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js +74 -0
  227. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  228. package/lib/packlets/crypto-utils/keystore/converters.d.ts +68 -6
  229. package/lib/packlets/crypto-utils/keystore/converters.d.ts.map +1 -0
  230. package/lib/packlets/crypto-utils/keystore/converters.js +101 -9
  231. package/lib/packlets/crypto-utils/keystore/converters.js.map +1 -0
  232. package/lib/packlets/crypto-utils/keystore/index.d.ts +1 -0
  233. package/lib/packlets/crypto-utils/keystore/index.d.ts.map +1 -0
  234. package/lib/packlets/crypto-utils/keystore/index.js +1 -0
  235. package/lib/packlets/crypto-utils/keystore/index.js.map +1 -0
  236. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +198 -13
  237. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -0
  238. package/lib/packlets/crypto-utils/keystore/keyStore.js +624 -124
  239. package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  240. package/lib/packlets/crypto-utils/keystore/model.d.ts +268 -19
  241. package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -0
  242. package/lib/packlets/crypto-utils/keystore/model.js +24 -2
  243. package/lib/packlets/crypto-utils/keystore/model.js.map +1 -0
  244. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts +50 -0
  245. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts.map +1 -0
  246. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js +22 -0
  247. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  248. package/lib/packlets/crypto-utils/model.d.ts +338 -10
  249. package/lib/packlets/crypto-utils/model.d.ts.map +1 -0
  250. package/lib/packlets/crypto-utils/model.js +33 -1
  251. package/lib/packlets/crypto-utils/model.js.map +1 -0
  252. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts +110 -2
  253. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -0
  254. package/lib/packlets/crypto-utils/nodeCryptoProvider.js +269 -0
  255. package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  256. package/lib/packlets/crypto-utils/spkiHelpers.d.ts +53 -0
  257. package/lib/packlets/crypto-utils/spkiHelpers.d.ts.map +1 -0
  258. package/lib/packlets/crypto-utils/spkiHelpers.js +136 -0
  259. package/lib/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  260. package/lib/packlets/csv/csvFileHelpers.d.ts +0 -10
  261. package/lib/packlets/csv/csvFileHelpers.d.ts.map +1 -0
  262. package/lib/packlets/csv/csvFileHelpers.js +0 -15
  263. package/lib/packlets/csv/csvFileHelpers.js.map +1 -0
  264. package/lib/packlets/csv/csvHelpers.d.ts +10 -0
  265. package/lib/packlets/csv/csvHelpers.d.ts.map +1 -0
  266. package/lib/packlets/csv/csvHelpers.js +15 -0
  267. package/lib/packlets/csv/csvHelpers.js.map +1 -0
  268. package/lib/packlets/csv/index.browser.d.ts +0 -1
  269. package/lib/packlets/csv/index.browser.d.ts.map +1 -0
  270. package/lib/packlets/csv/index.browser.js +1 -5
  271. package/lib/packlets/csv/index.browser.js.map +1 -0
  272. package/lib/packlets/csv/index.d.ts.map +1 -0
  273. package/lib/packlets/csv/index.js.map +1 -0
  274. package/lib/packlets/experimental/extendedArray.d.ts.map +1 -0
  275. package/lib/packlets/experimental/extendedArray.js.map +1 -0
  276. package/lib/packlets/experimental/formatter.d.ts.map +1 -0
  277. package/lib/packlets/experimental/formatter.js.map +1 -0
  278. package/lib/packlets/experimental/index.d.ts.map +1 -0
  279. package/lib/packlets/experimental/index.js.map +1 -0
  280. package/lib/packlets/experimental/rangeOf.d.ts.map +1 -0
  281. package/lib/packlets/experimental/rangeOf.js.map +1 -0
  282. package/lib/packlets/hash/index.browser.d.ts.map +1 -0
  283. package/lib/packlets/hash/index.browser.js.map +1 -0
  284. package/lib/packlets/hash/index.d.ts.map +1 -0
  285. package/lib/packlets/hash/index.js.map +1 -0
  286. package/lib/packlets/hash/index.node.d.ts.map +1 -0
  287. package/lib/packlets/hash/index.node.js.map +1 -0
  288. package/lib/packlets/hash/md5Normalizer.browser.d.ts.map +1 -0
  289. package/lib/packlets/hash/md5Normalizer.browser.js.map +1 -0
  290. package/lib/packlets/hash/md5Normalizer.d.ts.map +1 -0
  291. package/lib/packlets/hash/md5Normalizer.js.map +1 -0
  292. package/lib/packlets/mustache/index.d.ts +1 -1
  293. package/lib/packlets/mustache/index.d.ts.map +1 -0
  294. package/lib/packlets/mustache/index.js.map +1 -0
  295. package/lib/packlets/mustache/interfaces.d.ts +34 -0
  296. package/lib/packlets/mustache/interfaces.d.ts.map +1 -0
  297. package/lib/packlets/mustache/interfaces.js.map +1 -0
  298. package/lib/packlets/mustache/mustacheTemplate.d.ts +2 -0
  299. package/lib/packlets/mustache/mustacheTemplate.d.ts.map +1 -0
  300. package/lib/packlets/mustache/mustacheTemplate.js +42 -4
  301. package/lib/packlets/mustache/mustacheTemplate.js.map +1 -0
  302. package/lib/packlets/record-jar/index.browser.d.ts +0 -1
  303. package/lib/packlets/record-jar/index.browser.d.ts.map +1 -0
  304. package/lib/packlets/record-jar/index.browser.js +1 -5
  305. package/lib/packlets/record-jar/index.browser.js.map +1 -0
  306. package/lib/packlets/record-jar/index.d.ts.map +1 -0
  307. package/lib/packlets/record-jar/index.js.map +1 -0
  308. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts +0 -11
  309. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts.map +1 -0
  310. package/lib/packlets/record-jar/recordJarFileHelpers.js +0 -19
  311. package/lib/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  312. package/lib/packlets/record-jar/recordJarHelpers.d.ts +11 -0
  313. package/lib/packlets/record-jar/recordJarHelpers.d.ts.map +1 -0
  314. package/lib/packlets/record-jar/recordJarHelpers.js +19 -0
  315. package/lib/packlets/record-jar/recordJarHelpers.js.map +1 -0
  316. package/lib/packlets/yaml/converters.d.ts.map +1 -0
  317. package/lib/packlets/yaml/converters.js.map +1 -0
  318. package/lib/packlets/yaml/index.d.ts +1 -0
  319. package/lib/packlets/yaml/index.d.ts.map +1 -0
  320. package/lib/packlets/yaml/index.js +1 -0
  321. package/lib/packlets/yaml/index.js.map +1 -0
  322. package/lib/packlets/yaml/serializers.d.ts +45 -0
  323. package/lib/packlets/yaml/serializers.d.ts.map +1 -0
  324. package/lib/packlets/yaml/serializers.js +84 -0
  325. package/lib/packlets/yaml/serializers.js.map +1 -0
  326. package/lib/packlets/zip-file-tree/index.d.ts.map +1 -0
  327. package/lib/packlets/zip-file-tree/index.js.map +1 -0
  328. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts +2 -2
  329. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts.map +1 -0
  330. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js +2 -2
  331. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  332. package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts.map +1 -0
  333. package/lib/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  334. package/package.json +16 -15
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ // Copyright (c) 2026 Erik Fortune
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
22
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
23
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
24
+ var m = o[Symbol.asyncIterator], i;
25
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
26
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
27
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
28
+ };
29
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
30
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
31
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
32
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
33
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
34
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
35
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
36
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
37
+ function fulfill(value) { resume("next", value); }
38
+ function reject(value) { resume("throw", value); }
39
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.callOpenAiResponsesStream = callOpenAiResponsesStream;
43
+ /**
44
+ * Streaming adapter for the OpenAI / xAI Responses API. This is the format
45
+ * used when server-side tools (e.g. web_search) are requested — Chat
46
+ * Completions doesn't support tool progress events, but the Responses API
47
+ * does.
48
+ *
49
+ * @packageDocumentation
50
+ */
51
+ const ts_utils_1 = require("@fgv/ts-utils");
52
+ const chatRequestBuilders_1 = require("../chatRequestBuilders");
53
+ const endpoint_1 = require("../endpoint");
54
+ const sseParser_1 = require("../sseParser");
55
+ const toolFormats_1 = require("../toolFormats");
56
+ const common_1 = require("./common");
57
+ const responsesDeltaPayload = ts_utils_1.Validators.object({
58
+ delta: ts_utils_1.Validators.string
59
+ });
60
+ const responsesCompletedPayload = ts_utils_1.Validators.object({
61
+ response: ts_utils_1.Validators.object({ status: ts_utils_1.Validators.string.optional() }, { options: { optionalFields: ['status'] } })
62
+ });
63
+ const responsesErrorInner = ts_utils_1.Validators.object({ message: ts_utils_1.Validators.string.optional() }, { options: { optionalFields: ['message'] } });
64
+ const responsesErrorPayload = ts_utils_1.Validators.object({
65
+ error: responsesErrorInner.optional(),
66
+ message: ts_utils_1.Validators.string.optional()
67
+ }, { options: { optionalFields: ['error', 'message'] } });
68
+ // ============================================================================
69
+ // Stream translator
70
+ // ============================================================================
71
+ /**
72
+ * Translates an OpenAI Responses API SSE stream into unified events.
73
+ *
74
+ * @internal
75
+ */
76
+ function translateOpenAiResponsesStream(response) {
77
+ return __asyncGenerator(this, arguments, function* translateOpenAiResponsesStream_1() {
78
+ var _a, e_1, _b, _c;
79
+ var _d, _e, _f;
80
+ let fullText = '';
81
+ let truncated = false;
82
+ let completed = false;
83
+ try {
84
+ /* c8 ignore next - body is non-null at this point per openSseConnection */
85
+ if (!response.body)
86
+ return yield __await(void 0);
87
+ try {
88
+ for (var _g = true, _h = __asyncValues((0, sseParser_1.readSseEvents)(response.body)), _j; _j = yield __await(_h.next()), _a = _j.done, !_a; _g = true) {
89
+ _c = _j.value;
90
+ _g = false;
91
+ const message = _c;
92
+ const eventName = message.event;
93
+ if (eventName === 'response.output_text.delta') {
94
+ const payload = (0, common_1.validateEventPayload)((0, sseParser_1.parseSseEventJson)(message.data), responsesDeltaPayload);
95
+ /* c8 ignore next 1 - defensive: payload?.delta null branch unreachable after validation */
96
+ const delta = payload === null || payload === void 0 ? void 0 : payload.delta;
97
+ if (typeof delta === 'string' && delta.length > 0) {
98
+ fullText += delta;
99
+ yield yield __await({ type: 'text-delta', delta });
100
+ }
101
+ }
102
+ else if (eventName === 'response.web_search_call.in_progress') {
103
+ yield yield __await({ type: 'tool-event', toolType: 'web_search', phase: 'started' });
104
+ }
105
+ else if (eventName === 'response.web_search_call.completed') {
106
+ yield yield __await({ type: 'tool-event', toolType: 'web_search', phase: 'completed' });
107
+ }
108
+ else if (eventName === 'response.completed') {
109
+ const payload = (0, common_1.validateEventPayload)((0, sseParser_1.parseSseEventJson)(message.data), responsesCompletedPayload);
110
+ /* c8 ignore next 1 - defensive: payload?.response null branch unreachable after validation */
111
+ truncated = (payload === null || payload === void 0 ? void 0 : payload.response.status) === 'incomplete';
112
+ completed = true;
113
+ /* c8 ignore next 1 - defensive: eventName === 'error' alternative not exercised in tests */
114
+ }
115
+ else if (eventName === 'response.failed' || eventName === 'error') {
116
+ const payload = (0, common_1.validateEventPayload)((0, sseParser_1.parseSseEventJson)(message.data), responsesErrorPayload);
117
+ /* c8 ignore next 1 - defensive: payload?.error and payload?.message null branches unreachable */
118
+ const errMsg = (_f = (_e = (_d = payload === null || payload === void 0 ? void 0 : payload.error) === null || _d === void 0 ? void 0 : _d.message) !== null && _e !== void 0 ? _e : payload === null || payload === void 0 ? void 0 : payload.message) !== null && _f !== void 0 ? _f : 'Responses API stream failed';
119
+ yield yield __await({ type: 'error', message: errMsg });
120
+ return yield __await(void 0);
121
+ }
122
+ }
123
+ }
124
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
125
+ finally {
126
+ try {
127
+ if (!_g && !_a && (_b = _h.return)) yield __await(_b.call(_h));
128
+ }
129
+ finally { if (e_1) throw e_1.error; }
130
+ }
131
+ }
132
+ catch (err) /* c8 ignore start - defensive: stream errors are always Error instances */ {
133
+ yield yield __await({ type: 'error', message: err instanceof Error ? err.message : String(err) });
134
+ return yield __await(void 0);
135
+ } /* c8 ignore stop */
136
+ if (completed) {
137
+ yield yield __await({ type: 'done', truncated, fullText });
138
+ }
139
+ else {
140
+ yield yield __await({ type: 'error', message: 'Responses API stream ended without a completed event' });
141
+ }
142
+ });
143
+ }
144
+ // ============================================================================
145
+ // Per-format request caller
146
+ // ============================================================================
147
+ /**
148
+ * Issues a streaming Responses API request (with tools) and returns the
149
+ * unified-event iterable on success.
150
+ *
151
+ * @internal
152
+ */
153
+ async function callOpenAiResponsesStream(config, prompt, tools, messagesBefore, temperature, logger, signal, resolvedThinking) {
154
+ var _a;
155
+ const url = `${config.baseUrl}/responses`;
156
+ const input = (0, chatRequestBuilders_1.buildMessages)(prompt.system, (0, chatRequestBuilders_1.buildOpenAiResponsesUserContent)(prompt), {
157
+ head: messagesBefore
158
+ });
159
+ const effort = (_a = resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.openAiEffort) !== null && _a !== void 0 ? _a : resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.xaiEffort;
160
+ const supportsReasoning = config.model !== 'grok-4';
161
+ const body = {
162
+ model: config.model,
163
+ input,
164
+ tools: (0, toolFormats_1.toResponsesApiTools)(tools),
165
+ stream: true
166
+ };
167
+ if (effort !== undefined && supportsReasoning) {
168
+ body.reasoning = { effort };
169
+ }
170
+ if (effort === undefined || effort === 'none') {
171
+ body.temperature = temperature;
172
+ }
173
+ if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
174
+ Object.assign(body, resolvedThinking.otherParams);
175
+ }
176
+ const headers = (0, endpoint_1.bearerAuthHeader)(config.apiKey);
177
+ /* c8 ignore next 3 - optional logger */
178
+ logger === null || logger === void 0 ? void 0 : logger.info(`OpenAI Responses streaming: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);
179
+ const conn = await (0, common_1.openSseConnection)(url, headers, body, logger, signal);
180
+ return conn.onSuccess((response) => (0, ts_utils_1.succeed)(translateOpenAiResponsesStream(response)));
181
+ }
182
+ //# sourceMappingURL=openaiResponses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openaiResponses.js","sourceRoot":"","sources":["../../../../src/packlets/ai-assist/streamingAdapters/openaiResponses.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Streaming adapter for the OpenAI / xAI Responses API. This is the format\n * used when server-side tools (e.g. web_search) are requested — Chat\n * Completions doesn't support tool progress events, but the Responses API\n * does.\n *\n * @packageDocumentation\n */\n\nimport { type Logging, Result, succeed, type Validator, Validators } from '@fgv/ts-utils';\n\nimport { buildMessages, buildOpenAiResponsesUserContent } from '../chatRequestBuilders';\nimport { bearerAuthHeader } from '../endpoint';\nimport { AiPrompt, type AiServerToolConfig, type IAiStreamEvent, type IChatMessage } from '../model';\nimport { parseSseEventJson, readSseEvents } from '../sseParser';\nimport { toResponsesApiTools } from '../toolFormats';\nimport { type IResolvedThinkingConfig } from '../thinkingOptionsResolver';\nimport { IStreamApiConfig, openSseConnection, validateEventPayload } from './common';\n\n// ============================================================================\n// Event payload shapes\n// ============================================================================\n\n/**\n * Payload of a `response.output_text.delta` SSE event.\n *\n * @internal\n */\ninterface IResponsesDeltaPayload {\n readonly delta: string;\n}\n\n/**\n * Payload of a `response.completed` SSE event. `status === 'incomplete'`\n * signals the stream was cut short (max output tokens, etc.).\n *\n * @internal\n */\ninterface IResponsesCompletedPayload {\n readonly response: { readonly status?: string };\n}\n\n/**\n * Payload of a `response.failed` or `error` SSE event. Both shapes appear\n * in the wild — sometimes `error.message`, sometimes a top-level `message`.\n *\n * @internal\n */\ninterface IResponsesErrorPayload {\n readonly error?: { readonly message?: string };\n readonly message?: string;\n}\n\nconst responsesDeltaPayload: Validator<IResponsesDeltaPayload> = Validators.object<IResponsesDeltaPayload>({\n delta: Validators.string\n});\n\nconst responsesCompletedPayload: Validator<IResponsesCompletedPayload> =\n Validators.object<IResponsesCompletedPayload>({\n response: Validators.object<{ status?: string }>(\n { status: Validators.string.optional() },\n { options: { optionalFields: ['status'] } }\n )\n });\n\nconst responsesErrorInner: Validator<{ message?: string }> = Validators.object<{ message?: string }>(\n { message: Validators.string.optional() },\n { options: { optionalFields: ['message'] } }\n);\n\nconst responsesErrorPayload: Validator<IResponsesErrorPayload> = Validators.object<IResponsesErrorPayload>(\n {\n error: responsesErrorInner.optional(),\n message: Validators.string.optional()\n },\n { options: { optionalFields: ['error', 'message'] } }\n);\n\n// ============================================================================\n// Stream translator\n// ============================================================================\n\n/**\n * Translates an OpenAI Responses API SSE stream into unified events.\n *\n * @internal\n */\nasync function* translateOpenAiResponsesStream(response: Response): AsyncGenerator<IAiStreamEvent> {\n let fullText = '';\n let truncated = false;\n let completed = false;\n\n try {\n /* c8 ignore next - body is non-null at this point per openSseConnection */\n if (!response.body) return;\n for await (const message of readSseEvents(response.body)) {\n const eventName = message.event;\n if (eventName === 'response.output_text.delta') {\n const payload = validateEventPayload(parseSseEventJson(message.data), responsesDeltaPayload);\n /* c8 ignore next 1 - defensive: payload?.delta null branch unreachable after validation */\n const delta = payload?.delta;\n if (typeof delta === 'string' && delta.length > 0) {\n fullText += delta;\n yield { type: 'text-delta', delta };\n }\n } else if (eventName === 'response.web_search_call.in_progress') {\n yield { type: 'tool-event', toolType: 'web_search', phase: 'started' };\n } else if (eventName === 'response.web_search_call.completed') {\n yield { type: 'tool-event', toolType: 'web_search', phase: 'completed' };\n } else if (eventName === 'response.completed') {\n const payload = validateEventPayload(parseSseEventJson(message.data), responsesCompletedPayload);\n /* c8 ignore next 1 - defensive: payload?.response null branch unreachable after validation */\n truncated = payload?.response.status === 'incomplete';\n completed = true;\n /* c8 ignore next 1 - defensive: eventName === 'error' alternative not exercised in tests */\n } else if (eventName === 'response.failed' || eventName === 'error') {\n const payload = validateEventPayload(parseSseEventJson(message.data), responsesErrorPayload);\n /* c8 ignore next 1 - defensive: payload?.error and payload?.message null branches unreachable */\n const errMsg = payload?.error?.message ?? payload?.message ?? 'Responses API stream failed';\n yield { type: 'error', message: errMsg };\n return;\n }\n }\n } catch (err: unknown) /* c8 ignore start - defensive: stream errors are always Error instances */ {\n yield { type: 'error', message: err instanceof Error ? err.message : String(err) };\n return;\n } /* c8 ignore stop */\n\n if (completed) {\n yield { type: 'done', truncated, fullText };\n } else {\n yield { type: 'error', message: 'Responses API stream ended without a completed event' };\n }\n}\n\n// ============================================================================\n// Per-format request caller\n// ============================================================================\n\n/**\n * Issues a streaming Responses API request (with tools) and returns the\n * unified-event iterable on success.\n *\n * @internal\n */\nexport async function callOpenAiResponsesStream(\n config: IStreamApiConfig,\n prompt: AiPrompt,\n tools: ReadonlyArray<AiServerToolConfig>,\n messagesBefore: ReadonlyArray<IChatMessage> | undefined,\n temperature: number,\n logger?: Logging.ILogger,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig\n): Promise<Result<AsyncIterable<IAiStreamEvent>>> {\n const url = `${config.baseUrl}/responses`;\n const input = buildMessages(prompt.system, buildOpenAiResponsesUserContent(prompt), {\n head: messagesBefore\n });\n const effort = resolvedThinking?.openAiEffort ?? resolvedThinking?.xaiEffort;\n const supportsReasoning = config.model !== 'grok-4';\n const body: Record<string, unknown> = {\n model: config.model,\n input,\n tools: toResponsesApiTools(tools),\n stream: true\n };\n if (effort !== undefined && supportsReasoning) {\n body.reasoning = { effort };\n }\n if (effort === undefined || effort === 'none') {\n body.temperature = temperature;\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n const headers: Record<string, string> = bearerAuthHeader(config.apiKey);\n /* c8 ignore next 3 - optional logger */\n logger?.info(\n `OpenAI Responses streaming: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`\n );\n const conn = await openSseConnection(url, headers, body, logger, signal);\n return conn.onSuccess((response) => succeed(translateOpenAiResponsesStream(response)));\n}\n"]}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Streaming adapter for a caller-provided proxy server. Unlike the
3
+ * provider-specific adapters, the proxy speaks our own unified vocabulary
4
+ * directly: each `data:` line is a JSON-serialized {@link AiAssist.IAiStreamEvent},
5
+ * so this adapter only validates the event-type discriminator and forwards.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ import { Result } from '@fgv/ts-utils';
10
+ import { type IAiStreamEvent } from '../model';
11
+ import { IProviderCompletionStreamParams } from './common';
12
+ /**
13
+ * Calls the streaming chat endpoint on a proxy server instead of calling
14
+ * the provider directly from the browser.
15
+ *
16
+ * @remarks
17
+ * Proxy contract:
18
+ * - Endpoint: `POST ${proxyUrl}/api/ai/completion-stream`
19
+ * - Request body: same JSON as `/api/ai/completion` plus `"stream": true`
20
+ * - Response: `Content-Type: text/event-stream`; body is the unified
21
+ * {@link AiAssist.IAiStreamEvent} JSON-serialized one event per SSE `data:` line
22
+ * (no `event:` line needed since the type discriminator is in the JSON).
23
+ * - Error response (when the proxy can't even start): JSON `{error: string}`
24
+ * with a non-2xx status, surfaced as `proxy: ${error}`.
25
+ *
26
+ * The proxy server is responsible for opening the upstream SSE connection,
27
+ * translating provider-native events to the unified vocabulary, and
28
+ * forwarding events as they arrive (no buffering). The library does not
29
+ * ship a proxy implementation.
30
+ *
31
+ * @public
32
+ */
33
+ export declare function callProxiedCompletionStream(proxyUrl: string, params: IProviderCompletionStreamParams): Promise<Result<AsyncIterable<IAiStreamEvent>>>;
34
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../../../src/packlets/ai-assist/streamingAdapters/proxy.ts"],"names":[],"mappings":"AAoBA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAuC,MAAM,eAAe,CAAC;AAE5E,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,EAAE,+BAA+B,EAA2C,MAAM,UAAU,CAAC;AAkEpG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CA6ChD"}
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ // Copyright (c) 2026 Erik Fortune
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
22
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
23
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
24
+ var m = o[Symbol.asyncIterator], i;
25
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
26
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
27
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
28
+ };
29
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
30
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
31
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
32
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
33
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
34
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
35
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
36
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
37
+ function fulfill(value) { resume("next", value); }
38
+ function reject(value) { resume("throw", value); }
39
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.callProxiedCompletionStream = callProxiedCompletionStream;
43
+ /**
44
+ * Streaming adapter for a caller-provided proxy server. Unlike the
45
+ * provider-specific adapters, the proxy speaks our own unified vocabulary
46
+ * directly: each `data:` line is a JSON-serialized {@link AiAssist.IAiStreamEvent},
47
+ * so this adapter only validates the event-type discriminator and forwards.
48
+ *
49
+ * @packageDocumentation
50
+ */
51
+ const ts_utils_1 = require("@fgv/ts-utils");
52
+ const sseParser_1 = require("../sseParser");
53
+ const common_1 = require("./common");
54
+ const proxyEventTypes = ['text-delta', 'tool-event', 'done', 'error'];
55
+ const proxyEventEnvelope = ts_utils_1.Validators.object({
56
+ type: ts_utils_1.Validators.enumeratedValue(proxyEventTypes)
57
+ });
58
+ // ============================================================================
59
+ // Stream translator
60
+ // ============================================================================
61
+ /**
62
+ * Translates a proxied SSE stream back into {@link AiAssist.IAiStreamEvent} objects.
63
+ * Validation is limited to the type discriminator; the proxy is contractually
64
+ * required to emit shape-correct unified events.
65
+ *
66
+ * @internal
67
+ */
68
+ function translateProxyStream(response) {
69
+ return __asyncGenerator(this, arguments, function* translateProxyStream_1() {
70
+ var _a, e_1, _b, _c;
71
+ try {
72
+ /* c8 ignore next - body is non-null at this point per openSseConnection */
73
+ if (!response.body)
74
+ return yield __await(void 0);
75
+ try {
76
+ for (var _d = true, _e = __asyncValues((0, sseParser_1.readSseEvents)(response.body)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
77
+ _c = _f.value;
78
+ _d = false;
79
+ const message = _c;
80
+ const json = (0, sseParser_1.parseSseEventJson)(message.data);
81
+ /* c8 ignore next 3 - defensive: malformed SSE events skipped */
82
+ if (json === undefined) {
83
+ continue;
84
+ }
85
+ const envelope = (0, common_1.validateEventPayload)(json, proxyEventEnvelope);
86
+ /* c8 ignore next 3 - defensive: SSE events without valid envelope skipped */
87
+ if (!envelope) {
88
+ continue;
89
+ }
90
+ const event = json;
91
+ yield yield __await(event);
92
+ if (envelope.type === 'done' || envelope.type === 'error') {
93
+ return yield __await(void 0);
94
+ }
95
+ }
96
+ }
97
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
98
+ finally {
99
+ try {
100
+ if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
101
+ }
102
+ finally { if (e_1) throw e_1.error; }
103
+ }
104
+ }
105
+ catch (err) /* c8 ignore start - defensive: stream errors are always Error instances */ {
106
+ yield yield __await({ type: 'error', message: err instanceof Error ? err.message : String(err) });
107
+ } /* c8 ignore stop */
108
+ });
109
+ }
110
+ // ============================================================================
111
+ // Public entry point
112
+ // ============================================================================
113
+ /**
114
+ * Calls the streaming chat endpoint on a proxy server instead of calling
115
+ * the provider directly from the browser.
116
+ *
117
+ * @remarks
118
+ * Proxy contract:
119
+ * - Endpoint: `POST ${proxyUrl}/api/ai/completion-stream`
120
+ * - Request body: same JSON as `/api/ai/completion` plus `"stream": true`
121
+ * - Response: `Content-Type: text/event-stream`; body is the unified
122
+ * {@link AiAssist.IAiStreamEvent} JSON-serialized one event per SSE `data:` line
123
+ * (no `event:` line needed since the type discriminator is in the JSON).
124
+ * - Error response (when the proxy can't even start): JSON `{error: string}`
125
+ * with a non-2xx status, surfaced as `proxy: ${error}`.
126
+ *
127
+ * The proxy server is responsible for opening the upstream SSE connection,
128
+ * translating provider-native events to the unified vocabulary, and
129
+ * forwarding events as they arrive (no buffering). The library does not
130
+ * ship a proxy implementation.
131
+ *
132
+ * @public
133
+ */
134
+ async function callProxiedCompletionStream(proxyUrl, params) {
135
+ const { descriptor, apiKey, prompt, messagesBefore, temperature, modelOverride, logger, tools, signal, thinking } = params;
136
+ const promptBody = { system: prompt.system, user: prompt.user };
137
+ if (prompt.attachments.length > 0) {
138
+ promptBody.attachments = prompt.attachments;
139
+ }
140
+ const body = {
141
+ providerId: descriptor.id,
142
+ apiKey,
143
+ prompt: promptBody,
144
+ /* c8 ignore next 1 - defensive: temperature always uses default 0.7 in proxy streaming tests */
145
+ temperature: temperature !== null && temperature !== void 0 ? temperature : 0.7,
146
+ stream: true
147
+ };
148
+ if (messagesBefore && messagesBefore.length > 0) {
149
+ body.messagesBefore = messagesBefore;
150
+ }
151
+ if (modelOverride !== undefined) {
152
+ body.modelOverride = modelOverride;
153
+ }
154
+ if (tools && tools.length > 0) {
155
+ body.tools = tools;
156
+ }
157
+ if (thinking !== undefined) {
158
+ body.thinking = thinking;
159
+ }
160
+ /* c8 ignore next 1 - optional logger */
161
+ logger === null || logger === void 0 ? void 0 : logger.info(`AI streaming proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);
162
+ const url = `${proxyUrl}/api/ai/completion-stream`;
163
+ const conn = await (0, common_1.openSseConnection)(url, {}, body, logger, signal);
164
+ return conn.onSuccess((response) => (0, ts_utils_1.succeed)(translateProxyStream(response)));
165
+ }
166
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../../../src/packlets/ai-assist/streamingAdapters/proxy.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Streaming adapter for a caller-provided proxy server. Unlike the\n * provider-specific adapters, the proxy speaks our own unified vocabulary\n * directly: each `data:` line is a JSON-serialized {@link AiAssist.IAiStreamEvent},\n * so this adapter only validates the event-type discriminator and forwards.\n *\n * @packageDocumentation\n */\n\nimport { Result, succeed, type Validator, Validators } from '@fgv/ts-utils';\n\nimport { type IAiStreamEvent } from '../model';\nimport { parseSseEventJson, readSseEvents } from '../sseParser';\nimport { IProviderCompletionStreamParams, openSseConnection, validateEventPayload } from './common';\n\n// ============================================================================\n// Event payload shape — a tagged-event envelope\n// ============================================================================\n\ntype ProxyEventType = 'text-delta' | 'tool-event' | 'done' | 'error';\n\n/**\n * Minimal envelope used to identify and discriminate proxy events. Once the\n * `type` is recognized, the event is forwarded as-is — the unified shape is\n * the proxy contract, so there's no further per-type validation here.\n *\n * @internal\n */\ninterface IProxyEventEnvelope {\n readonly type: ProxyEventType;\n}\n\nconst proxyEventTypes: ReadonlyArray<ProxyEventType> = ['text-delta', 'tool-event', 'done', 'error'];\n\nconst proxyEventEnvelope: Validator<IProxyEventEnvelope> = Validators.object<IProxyEventEnvelope>({\n type: Validators.enumeratedValue<ProxyEventType>(proxyEventTypes)\n});\n\n// ============================================================================\n// Stream translator\n// ============================================================================\n\n/**\n * Translates a proxied SSE stream back into {@link AiAssist.IAiStreamEvent} objects.\n * Validation is limited to the type discriminator; the proxy is contractually\n * required to emit shape-correct unified events.\n *\n * @internal\n */\nasync function* translateProxyStream(response: Response): AsyncGenerator<IAiStreamEvent> {\n try {\n /* c8 ignore next - body is non-null at this point per openSseConnection */\n if (!response.body) return;\n for await (const message of readSseEvents(response.body)) {\n const json = parseSseEventJson(message.data);\n /* c8 ignore next 3 - defensive: malformed SSE events skipped */\n if (json === undefined) {\n continue;\n }\n const envelope = validateEventPayload(json, proxyEventEnvelope);\n /* c8 ignore next 3 - defensive: SSE events without valid envelope skipped */\n if (!envelope) {\n continue;\n }\n const event = json as IAiStreamEvent;\n yield event;\n if (envelope.type === 'done' || envelope.type === 'error') {\n return;\n }\n }\n } catch (err: unknown) /* c8 ignore start - defensive: stream errors are always Error instances */ {\n yield { type: 'error', message: err instanceof Error ? err.message : String(err) };\n } /* c8 ignore stop */\n}\n\n// ============================================================================\n// Public entry point\n// ============================================================================\n\n/**\n * Calls the streaming chat endpoint on a proxy server instead of calling\n * the provider directly from the browser.\n *\n * @remarks\n * Proxy contract:\n * - Endpoint: `POST ${proxyUrl}/api/ai/completion-stream`\n * - Request body: same JSON as `/api/ai/completion` plus `\"stream\": true`\n * - Response: `Content-Type: text/event-stream`; body is the unified\n * {@link AiAssist.IAiStreamEvent} JSON-serialized one event per SSE `data:` line\n * (no `event:` line needed since the type discriminator is in the JSON).\n * - Error response (when the proxy can't even start): JSON `{error: string}`\n * with a non-2xx status, surfaced as `proxy: ${error}`.\n *\n * The proxy server is responsible for opening the upstream SSE connection,\n * translating provider-native events to the unified vocabulary, and\n * forwarding events as they arrive (no buffering). The library does not\n * ship a proxy implementation.\n *\n * @public\n */\nexport async function callProxiedCompletionStream(\n proxyUrl: string,\n params: IProviderCompletionStreamParams\n): Promise<Result<AsyncIterable<IAiStreamEvent>>> {\n const {\n descriptor,\n apiKey,\n prompt,\n messagesBefore,\n temperature,\n modelOverride,\n logger,\n tools,\n signal,\n thinking\n } = params;\n\n const promptBody: Record<string, unknown> = { system: prompt.system, user: prompt.user };\n if (prompt.attachments.length > 0) {\n promptBody.attachments = prompt.attachments;\n }\n const body: Record<string, unknown> = {\n providerId: descriptor.id,\n apiKey,\n prompt: promptBody,\n /* c8 ignore next 1 - defensive: temperature always uses default 0.7 in proxy streaming tests */\n temperature: temperature ?? 0.7,\n stream: true\n };\n if (messagesBefore && messagesBefore.length > 0) {\n body.messagesBefore = messagesBefore;\n }\n if (modelOverride !== undefined) {\n body.modelOverride = modelOverride;\n }\n if (tools && tools.length > 0) {\n body.tools = tools;\n }\n if (thinking !== undefined) {\n body.thinking = thinking;\n }\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`AI streaming proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);\n\n const url = `${proxyUrl}/api/ai/completion-stream`;\n const conn = await openSseConnection(url, {}, body, logger, signal);\n return conn.onSuccess((response) => succeed(translateProxyStream(response)));\n}\n"]}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Streaming chat completion client. Public façade over the per-format
3
+ * adapters under `streamingAdapters/`: provider dispatch and pre-flight
4
+ * validation live here; format-specific request/translation logic and the
5
+ * typed event-payload validators live with each adapter.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ import { Result } from '@fgv/ts-utils';
10
+ import { type IAiStreamEvent } from './model';
11
+ import { type IProviderCompletionStreamParams } from './streamingAdapters/common';
12
+ export { callProxiedCompletionStream } from './streamingAdapters/proxy';
13
+ export type { IProviderCompletionStreamParams } from './streamingAdapters/common';
14
+ /**
15
+ * Calls the appropriate streaming chat completion API for a given provider.
16
+ *
17
+ * @remarks
18
+ * Pre-flight rejection: when `descriptor.streamingCorsRestricted === true`
19
+ * and the call isn't being routed through a proxy, this returns
20
+ * `Result.fail` before fetch is invoked. Callers should route through
21
+ * {@link AiAssist.callProxiedCompletionStream} or surface the failure to the user.
22
+ *
23
+ * Connection-time failures (auth, network, non-2xx) surface as the outer
24
+ * `Result.fail`. Once iteration begins, errors mid-stream surface as a
25
+ * terminal error event ({@link AiAssist.IAiStreamError}) followed by the iterable
26
+ * ending. The final successful event is {@link AiAssist.IAiStreamDone}.
27
+ *
28
+ * @param params - Request parameters including descriptor, API key, prompt, and optional tools
29
+ * @returns A streaming iterable of unified events, or a Result.fail
30
+ * @public
31
+ */
32
+ export declare function callProviderCompletionStream(params: IProviderCompletionStreamParams): Promise<Result<AsyncIterable<IAiStreamEvent>>>;
33
+ //# sourceMappingURL=streamingClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamingClient.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/streamingClient.ts"],"names":[],"mappings":"AAoBA;;;;;;;GAOG;AAEH,OAAO,EAAQ,MAAM,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,SAAS,CAAC;AAE5D,OAAO,EAAE,KAAK,+BAA+B,EAAyB,MAAM,4BAA4B,CAAC;AAWzG,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,YAAY,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAElF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CAoHhD"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ // Copyright (c) 2026 Erik Fortune
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.callProxiedCompletionStream = void 0;
23
+ exports.callProviderCompletionStream = callProviderCompletionStream;
24
+ /**
25
+ * Streaming chat completion client. Public façade over the per-format
26
+ * adapters under `streamingAdapters/`: provider dispatch and pre-flight
27
+ * validation live here; format-specific request/translation logic and the
28
+ * typed event-payload validators live with each adapter.
29
+ *
30
+ * @packageDocumentation
31
+ */
32
+ const ts_utils_1 = require("@fgv/ts-utils");
33
+ const endpoint_1 = require("./endpoint");
34
+ const model_1 = require("./model");
35
+ const anthropic_1 = require("./streamingAdapters/anthropic");
36
+ const gemini_1 = require("./streamingAdapters/gemini");
37
+ const openaiChat_1 = require("./streamingAdapters/openaiChat");
38
+ const openaiResponses_1 = require("./streamingAdapters/openaiResponses");
39
+ const thinkingOptionsResolver_1 = require("./thinkingOptionsResolver");
40
+ var proxy_1 = require("./streamingAdapters/proxy");
41
+ Object.defineProperty(exports, "callProxiedCompletionStream", { enumerable: true, get: function () { return proxy_1.callProxiedCompletionStream; } });
42
+ /**
43
+ * Calls the appropriate streaming chat completion API for a given provider.
44
+ *
45
+ * @remarks
46
+ * Pre-flight rejection: when `descriptor.streamingCorsRestricted === true`
47
+ * and the call isn't being routed through a proxy, this returns
48
+ * `Result.fail` before fetch is invoked. Callers should route through
49
+ * {@link AiAssist.callProxiedCompletionStream} or surface the failure to the user.
50
+ *
51
+ * Connection-time failures (auth, network, non-2xx) surface as the outer
52
+ * `Result.fail`. Once iteration begins, errors mid-stream surface as a
53
+ * terminal error event ({@link AiAssist.IAiStreamError}) followed by the iterable
54
+ * ending. The final successful event is {@link AiAssist.IAiStreamDone}.
55
+ *
56
+ * @param params - Request parameters including descriptor, API key, prompt, and optional tools
57
+ * @returns A streaming iterable of unified events, or a Result.fail
58
+ * @public
59
+ */
60
+ async function callProviderCompletionStream(params) {
61
+ var _a;
62
+ const { descriptor, apiKey, prompt, messagesBefore, temperature, modelOverride, logger, tools, signal, endpoint, thinking } = params;
63
+ const baseUrlResult = (0, endpoint_1.resolveEffectiveBaseUrl)(descriptor, endpoint);
64
+ if (baseUrlResult.isFailure()) {
65
+ return (0, ts_utils_1.fail)(baseUrlResult.message);
66
+ }
67
+ if (descriptor.streamingCorsRestricted) {
68
+ return (0, ts_utils_1.fail)(`provider "${descriptor.id}" requires a proxy for streaming; none is configured`);
69
+ }
70
+ if (prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {
71
+ return (0, ts_utils_1.fail)(`provider "${descriptor.id}" does not accept image input`);
72
+ }
73
+ const hasTools = tools !== undefined && tools.length > 0;
74
+ const discriminator = (0, thinkingOptionsResolver_1.providerDiscriminatorForId)(descriptor.id);
75
+ const hasThinkingConfig = discriminator !== undefined &&
76
+ ((thinking === null || thinking === void 0 ? void 0 : thinking.effort) !== undefined ||
77
+ ((_a = thinking === null || thinking === void 0 ? void 0 : thinking.providers) === null || _a === void 0 ? void 0 : _a.some((b) => b.provider === 'other' || b.provider === discriminator)) === true);
78
+ const modelContext = hasThinkingConfig ? 'thinking' : hasTools ? 'tools' : undefined;
79
+ const model = (0, model_1.resolveModel)(modelOverride !== null && modelOverride !== void 0 ? modelOverride : descriptor.defaultModel, modelContext);
80
+ if (model.length === 0) {
81
+ return (0, ts_utils_1.fail)(`provider "${descriptor.id}": no model resolved; pass modelOverride or set descriptor.defaultModel`);
82
+ }
83
+ let resolvedThinking;
84
+ if (thinking !== undefined) {
85
+ if (discriminator !== undefined) {
86
+ const mergeResult = (0, thinkingOptionsResolver_1.mergeThinkingConfig)(thinking, model, discriminator);
87
+ /* c8 ignore next 3 - mergeThinkingConfig always succeeds; defensive guard */
88
+ if (mergeResult.isFailure()) {
89
+ return (0, ts_utils_1.fail)(mergeResult.message);
90
+ }
91
+ resolvedThinking = mergeResult.value;
92
+ const conflictResult = (0, thinkingOptionsResolver_1.checkTemperatureConflict)(resolvedThinking, discriminator, temperature);
93
+ if (conflictResult.isFailure()) {
94
+ return (0, ts_utils_1.fail)(conflictResult.message);
95
+ }
96
+ }
97
+ }
98
+ const effectiveTemperature = temperature !== null && temperature !== void 0 ? temperature : 0.7;
99
+ const config = {
100
+ baseUrl: baseUrlResult.value,
101
+ apiKey,
102
+ model
103
+ };
104
+ switch (descriptor.apiFormat) {
105
+ case 'openai':
106
+ if (hasTools) {
107
+ return (0, openaiResponses_1.callOpenAiResponsesStream)(config, prompt, tools, messagesBefore, effectiveTemperature, logger, signal, resolvedThinking);
108
+ }
109
+ return (0, openaiChat_1.callOpenAiChatStream)(config, prompt, messagesBefore, effectiveTemperature, logger, signal, resolvedThinking);
110
+ case 'anthropic':
111
+ return (0, anthropic_1.callAnthropicStream)(config, prompt, messagesBefore, effectiveTemperature, tools, logger, signal, resolvedThinking);
112
+ case 'gemini':
113
+ return (0, gemini_1.callGeminiStream)(config, prompt, messagesBefore, effectiveTemperature, tools, logger, signal, resolvedThinking);
114
+ /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */
115
+ default: {
116
+ const _exhaustive = descriptor.apiFormat;
117
+ return (0, ts_utils_1.fail)(`unsupported API format: ${String(_exhaustive)}`);
118
+ }
119
+ }
120
+ }
121
+ //# sourceMappingURL=streamingClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamingClient.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/streamingClient.ts"],"names":[],"mappings":";AAAA,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AACxE,2DAA2D;AAC3D,EAAE;AACF,iFAAiF;AACjF,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,gFAAgF;AAChF,YAAY;;;AAgDZ,oEAsHC;AApKD;;;;;;;GAOG;AAEH,4CAA6C;AAE7C,yCAAqD;AACrD,mCAA4D;AAC5D,6DAAoE;AAEpE,uDAA8D;AAC9D,+DAAsE;AACtE,yEAAgF;AAChF,uEAKmC;AAEnC,mDAAwE;AAA/D,oHAAA,2BAA2B,OAAA;AAGpC;;;;;;;;;;;;;;;;;GAiBG;AACI,KAAK,UAAU,4BAA4B,CAChD,MAAuC;;IAEvC,MAAM,EACJ,UAAU,EACV,MAAM,EACN,MAAM,EACN,cAAc,EACd,WAAW,EACX,aAAa,EACb,MAAM,EACN,KAAK,EACL,MAAM,EACN,QAAQ,EACR,QAAQ,EACT,GAAG,MAAM,CAAC;IAEX,MAAM,aAAa,GAAG,IAAA,kCAAuB,EAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACpE,IAAI,aAAa,CAAC,SAAS,EAAE,EAAE,CAAC;QAC9B,OAAO,IAAA,eAAI,EAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,UAAU,CAAC,uBAAuB,EAAE,CAAC;QACvC,OAAO,IAAA,eAAI,EAAC,aAAa,UAAU,CAAC,EAAE,sDAAsD,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC;QACnE,OAAO,IAAA,eAAI,EAAC,aAAa,UAAU,CAAC,EAAE,+BAA+B,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,IAAA,oDAA0B,EAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAChE,MAAM,iBAAiB,GACrB,aAAa,KAAK,SAAS;QAC3B,CAAC,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,MAAM,MAAK,SAAS;YAC7B,CAAA,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,SAAS,0CAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,aAAa,CAAC,MAAK,IAAI,CAAC,CAAC;IACvG,MAAM,YAAY,GAAG,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAErF,MAAM,KAAK,GAAG,IAAA,oBAAY,EAAC,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,UAAU,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IACnF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAA,eAAI,EACT,aAAa,UAAU,CAAC,EAAE,yEAAyE,CACpG,CAAC;IACJ,CAAC;IAED,IAAI,gBAAqD,CAAC;IAC1D,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,WAAW,GAAG,IAAA,6CAAmB,EAAC,QAAQ,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;YACxE,6EAA6E;YAC7E,IAAI,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC;gBAC5B,OAAO,IAAA,eAAI,EAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;YACD,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC;YACrC,MAAM,cAAc,GAAG,IAAA,kDAAwB,EAAC,gBAAgB,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;YAC9F,IAAI,cAAc,CAAC,SAAS,EAAE,EAAE,CAAC;gBAC/B,OAAO,IAAA,eAAI,EAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,oBAAoB,GAAG,WAAW,aAAX,WAAW,cAAX,WAAW,GAAI,GAAG,CAAC;IAEhD,MAAM,MAAM,GAAqB;QAC/B,OAAO,EAAE,aAAa,CAAC,KAAK;QAC5B,MAAM;QACN,KAAK;KACN,CAAC;IAEF,QAAQ,UAAU,CAAC,SAAS,EAAE,CAAC;QAC7B,KAAK,QAAQ;YACX,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,IAAA,2CAAyB,EAC9B,MAAM,EACN,MAAM,EACN,KAAK,EACL,cAAc,EACd,oBAAoB,EACpB,MAAM,EACN,MAAM,EACN,gBAAgB,CACjB,CAAC;YACJ,CAAC;YACD,OAAO,IAAA,iCAAoB,EACzB,MAAM,EACN,MAAM,EACN,cAAc,EACd,oBAAoB,EACpB,MAAM,EACN,MAAM,EACN,gBAAgB,CACjB,CAAC;QACJ,KAAK,WAAW;YACd,OAAO,IAAA,+BAAmB,EACxB,MAAM,EACN,MAAM,EACN,cAAc,EACd,oBAAoB,EACpB,KAAK,EACL,MAAM,EACN,MAAM,EACN,gBAAgB,CACjB,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,IAAA,yBAAgB,EACrB,MAAM,EACN,MAAM,EACN,cAAc,EACd,oBAAoB,EACpB,KAAK,EACL,MAAM,EACN,MAAM,EACN,gBAAgB,CACjB,CAAC;QACJ,qFAAqF;QACrF,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,WAAW,GAAU,UAAU,CAAC,SAAS,CAAC;YAChD,OAAO,IAAA,eAAI,EAAC,2BAA2B,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Streaming chat completion client. Public façade over the per-format\n * adapters under `streamingAdapters/`: provider dispatch and pre-flight\n * validation live here; format-specific request/translation logic and the\n * typed event-payload validators live with each adapter.\n *\n * @packageDocumentation\n */\n\nimport { fail, Result } from '@fgv/ts-utils';\n\nimport { resolveEffectiveBaseUrl } from './endpoint';\nimport { type IAiStreamEvent, resolveModel } from './model';\nimport { callAnthropicStream } from './streamingAdapters/anthropic';\nimport { type IProviderCompletionStreamParams, type IStreamApiConfig } from './streamingAdapters/common';\nimport { callGeminiStream } from './streamingAdapters/gemini';\nimport { callOpenAiChatStream } from './streamingAdapters/openaiChat';\nimport { callOpenAiResponsesStream } from './streamingAdapters/openaiResponses';\nimport {\n checkTemperatureConflict,\n mergeThinkingConfig,\n providerDiscriminatorForId,\n type IResolvedThinkingConfig\n} from './thinkingOptionsResolver';\n\nexport { callProxiedCompletionStream } from './streamingAdapters/proxy';\nexport type { IProviderCompletionStreamParams } from './streamingAdapters/common';\n\n/**\n * Calls the appropriate streaming chat completion API for a given provider.\n *\n * @remarks\n * Pre-flight rejection: when `descriptor.streamingCorsRestricted === true`\n * and the call isn't being routed through a proxy, this returns\n * `Result.fail` before fetch is invoked. Callers should route through\n * {@link AiAssist.callProxiedCompletionStream} or surface the failure to the user.\n *\n * Connection-time failures (auth, network, non-2xx) surface as the outer\n * `Result.fail`. Once iteration begins, errors mid-stream surface as a\n * terminal error event ({@link AiAssist.IAiStreamError}) followed by the iterable\n * ending. The final successful event is {@link AiAssist.IAiStreamDone}.\n *\n * @param params - Request parameters including descriptor, API key, prompt, and optional tools\n * @returns A streaming iterable of unified events, or a Result.fail\n * @public\n */\nexport async function callProviderCompletionStream(\n params: IProviderCompletionStreamParams\n): Promise<Result<AsyncIterable<IAiStreamEvent>>> {\n const {\n descriptor,\n apiKey,\n prompt,\n messagesBefore,\n temperature,\n modelOverride,\n logger,\n tools,\n signal,\n endpoint,\n thinking\n } = params;\n\n const baseUrlResult = resolveEffectiveBaseUrl(descriptor, endpoint);\n if (baseUrlResult.isFailure()) {\n return fail(baseUrlResult.message);\n }\n if (descriptor.streamingCorsRestricted) {\n return fail(`provider \"${descriptor.id}\" requires a proxy for streaming; none is configured`);\n }\n if (prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {\n return fail(`provider \"${descriptor.id}\" does not accept image input`);\n }\n\n const hasTools = tools !== undefined && tools.length > 0;\n const discriminator = providerDiscriminatorForId(descriptor.id);\n const hasThinkingConfig =\n discriminator !== undefined &&\n (thinking?.effort !== undefined ||\n thinking?.providers?.some((b) => b.provider === 'other' || b.provider === discriminator) === true);\n const modelContext = hasThinkingConfig ? 'thinking' : hasTools ? 'tools' : undefined;\n\n const model = resolveModel(modelOverride ?? descriptor.defaultModel, modelContext);\n if (model.length === 0) {\n return fail(\n `provider \"${descriptor.id}\": no model resolved; pass modelOverride or set descriptor.defaultModel`\n );\n }\n\n let resolvedThinking: IResolvedThinkingConfig | undefined;\n if (thinking !== undefined) {\n if (discriminator !== undefined) {\n const mergeResult = mergeThinkingConfig(thinking, model, discriminator);\n /* c8 ignore next 3 - mergeThinkingConfig always succeeds; defensive guard */\n if (mergeResult.isFailure()) {\n return fail(mergeResult.message);\n }\n resolvedThinking = mergeResult.value;\n const conflictResult = checkTemperatureConflict(resolvedThinking, discriminator, temperature);\n if (conflictResult.isFailure()) {\n return fail(conflictResult.message);\n }\n }\n }\n\n const effectiveTemperature = temperature ?? 0.7;\n\n const config: IStreamApiConfig = {\n baseUrl: baseUrlResult.value,\n apiKey,\n model\n };\n\n switch (descriptor.apiFormat) {\n case 'openai':\n if (hasTools) {\n return callOpenAiResponsesStream(\n config,\n prompt,\n tools,\n messagesBefore,\n effectiveTemperature,\n logger,\n signal,\n resolvedThinking\n );\n }\n return callOpenAiChatStream(\n config,\n prompt,\n messagesBefore,\n effectiveTemperature,\n logger,\n signal,\n resolvedThinking\n );\n case 'anthropic':\n return callAnthropicStream(\n config,\n prompt,\n messagesBefore,\n effectiveTemperature,\n tools,\n logger,\n signal,\n resolvedThinking\n );\n case 'gemini':\n return callGeminiStream(\n config,\n prompt,\n messagesBefore,\n effectiveTemperature,\n tools,\n logger,\n signal,\n resolvedThinking\n );\n /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */\n default: {\n const _exhaustive: never = descriptor.apiFormat;\n return fail(`unsupported API format: ${String(_exhaustive)}`);\n }\n }\n}\n"]}