@fgv/ts-extras 5.1.0-5 → 5.1.0-50

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 (488) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +90 -0
  3. package/dist/index.browser.js +6 -2
  4. package/dist/index.browser.js.map +1 -0
  5. package/dist/index.js +2 -1
  6. package/dist/index.js.map +1 -0
  7. package/dist/packlets/ai-assist/chatRequestBuilders.js +282 -0
  8. package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  9. package/dist/packlets/ai-assist/{apiClient.js → completionClient.js} +165 -214
  10. package/dist/packlets/ai-assist/completionClient.js.map +1 -0
  11. package/dist/packlets/ai-assist/converters.js +47 -3
  12. package/dist/packlets/ai-assist/converters.js.map +1 -0
  13. package/dist/packlets/ai-assist/embeddingClient.js +345 -0
  14. package/dist/packlets/ai-assist/embeddingClient.js.map +1 -0
  15. package/dist/packlets/ai-assist/endpoint.js +107 -0
  16. package/dist/packlets/ai-assist/endpoint.js.map +1 -0
  17. package/dist/packlets/ai-assist/http.js +104 -0
  18. package/dist/packlets/ai-assist/http.js.map +1 -0
  19. package/dist/packlets/ai-assist/imageGenerationClient.js +454 -0
  20. package/dist/packlets/ai-assist/imageGenerationClient.js.map +1 -0
  21. package/dist/packlets/ai-assist/imageOptionsResolver.js +193 -0
  22. package/dist/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  23. package/dist/packlets/ai-assist/index.js +12 -4
  24. package/dist/packlets/ai-assist/index.js.map +1 -0
  25. package/dist/packlets/ai-assist/jsonCompletion.js +93 -0
  26. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -0
  27. package/dist/packlets/ai-assist/jsonResponse.js +423 -0
  28. package/dist/packlets/ai-assist/jsonResponse.js.map +1 -0
  29. package/dist/packlets/ai-assist/listModelsClient.js +294 -0
  30. package/dist/packlets/ai-assist/listModelsClient.js.map +1 -0
  31. package/dist/packlets/ai-assist/model.js +301 -9
  32. package/dist/packlets/ai-assist/model.js.map +1 -0
  33. package/dist/packlets/ai-assist/registry.js +376 -12
  34. package/dist/packlets/ai-assist/registry.js.map +1 -0
  35. package/dist/packlets/ai-assist/sseParser.js +123 -0
  36. package/dist/packlets/ai-assist/sseParser.js.map +1 -0
  37. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +376 -0
  38. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  39. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +687 -0
  40. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  41. package/dist/packlets/ai-assist/streamingAdapters/common.js +187 -0
  42. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  43. package/dist/packlets/ai-assist/streamingAdapters/gemini.js +208 -0
  44. package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  45. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +175 -0
  46. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  47. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +390 -0
  48. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  49. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +178 -0
  50. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  51. package/dist/packlets/ai-assist/streamingClient.js +140 -0
  52. package/dist/packlets/ai-assist/streamingClient.js.map +1 -0
  53. package/dist/packlets/ai-assist/thinkingOptionsResolver.js +288 -0
  54. package/dist/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  55. package/dist/packlets/ai-assist/toolFormats.js +106 -10
  56. package/dist/packlets/ai-assist/toolFormats.js.map +1 -0
  57. package/dist/packlets/conversion/converters.js +35 -1
  58. package/dist/packlets/conversion/converters.js.map +1 -0
  59. package/dist/packlets/conversion/index.js.map +1 -0
  60. package/dist/packlets/crypto-utils/constants.js.map +1 -0
  61. package/dist/packlets/crypto-utils/converters.js +42 -4
  62. package/dist/packlets/crypto-utils/converters.js.map +1 -0
  63. package/dist/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  64. package/dist/packlets/crypto-utils/encryptedFile.js +37 -0
  65. package/dist/packlets/crypto-utils/encryptedFile.js.map +1 -0
  66. package/dist/packlets/crypto-utils/hpkeProvider.js +355 -0
  67. package/dist/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  68. package/dist/packlets/crypto-utils/index.browser.js +13 -2
  69. package/dist/packlets/crypto-utils/index.browser.js.map +1 -0
  70. package/dist/packlets/crypto-utils/index.js +9 -1
  71. package/dist/packlets/crypto-utils/index.js.map +1 -0
  72. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js +71 -0
  73. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  74. package/dist/packlets/crypto-utils/keystore/converters.js +111 -16
  75. package/dist/packlets/crypto-utils/keystore/converters.js.map +1 -0
  76. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +287 -0
  77. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  78. package/dist/packlets/crypto-utils/keystore/index.browser.js +36 -0
  79. package/dist/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  80. package/dist/packlets/crypto-utils/keystore/index.js +3 -0
  81. package/dist/packlets/crypto-utils/keystore/index.js.map +1 -0
  82. package/dist/packlets/crypto-utils/keystore/keyStore.js +872 -119
  83. package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  84. package/dist/packlets/crypto-utils/keystore/model.js +35 -4
  85. package/dist/packlets/crypto-utils/keystore/model.js.map +1 -0
  86. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js +21 -0
  87. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  88. package/dist/packlets/crypto-utils/model.js +32 -0
  89. package/dist/packlets/crypto-utils/model.js.map +1 -0
  90. package/dist/packlets/crypto-utils/nodeCryptoProvider.js +347 -1
  91. package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  92. package/dist/packlets/crypto-utils/seedDerivedKeyPair.js +120 -0
  93. package/dist/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -0
  94. package/dist/packlets/crypto-utils/spkiHelpers.js +284 -0
  95. package/dist/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  96. package/dist/packlets/csv/csvFileHelpers.js +0 -14
  97. package/dist/packlets/csv/csvFileHelpers.js.map +1 -0
  98. package/dist/packlets/csv/csvHelpers.js +14 -0
  99. package/dist/packlets/csv/csvHelpers.js.map +1 -0
  100. package/dist/packlets/csv/index.browser.js +1 -3
  101. package/dist/packlets/csv/index.browser.js.map +1 -0
  102. package/dist/packlets/csv/index.js.map +1 -0
  103. package/dist/packlets/experimental/extendedArray.js.map +1 -0
  104. package/dist/packlets/experimental/formatter.js.map +1 -0
  105. package/dist/packlets/experimental/index.js.map +1 -0
  106. package/dist/packlets/experimental/rangeOf.js.map +1 -0
  107. package/dist/packlets/hash/index.browser.js.map +1 -0
  108. package/dist/packlets/hash/index.js.map +1 -0
  109. package/dist/packlets/hash/index.node.js.map +1 -0
  110. package/dist/packlets/hash/md5Normalizer.browser.js.map +1 -0
  111. package/dist/packlets/hash/md5Normalizer.js.map +1 -0
  112. package/dist/packlets/mustache/index.js.map +1 -0
  113. package/dist/packlets/mustache/interfaces.js.map +1 -0
  114. package/dist/packlets/mustache/mustacheTemplate.js +42 -4
  115. package/dist/packlets/mustache/mustacheTemplate.js.map +1 -0
  116. package/dist/packlets/record-jar/index.browser.js +1 -3
  117. package/dist/packlets/record-jar/index.browser.js.map +1 -0
  118. package/dist/packlets/record-jar/index.js.map +1 -0
  119. package/dist/packlets/record-jar/recordJarFileHelpers.js +0 -18
  120. package/dist/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  121. package/dist/packlets/record-jar/recordJarHelpers.js +18 -0
  122. package/dist/packlets/record-jar/recordJarHelpers.js.map +1 -0
  123. package/dist/packlets/safer-fetch/addressClassification.js +438 -0
  124. package/dist/packlets/safer-fetch/addressClassification.js.map +1 -0
  125. package/dist/packlets/safer-fetch/addressPolicy.js +119 -0
  126. package/dist/packlets/safer-fetch/addressPolicy.js.map +1 -0
  127. package/dist/packlets/safer-fetch/contentType.js +120 -0
  128. package/dist/packlets/safer-fetch/contentType.js.map +1 -0
  129. package/dist/packlets/safer-fetch/deadline.js +254 -0
  130. package/dist/packlets/safer-fetch/deadline.js.map +1 -0
  131. package/dist/packlets/safer-fetch/defaults.js +131 -0
  132. package/dist/packlets/safer-fetch/defaults.js.map +1 -0
  133. package/dist/packlets/safer-fetch/failureReason.js +21 -0
  134. package/dist/packlets/safer-fetch/failureReason.js.map +1 -0
  135. package/dist/packlets/safer-fetch/guards.js +148 -0
  136. package/dist/packlets/safer-fetch/guards.js.map +1 -0
  137. package/dist/packlets/safer-fetch/index.browser.js +58 -0
  138. package/dist/packlets/safer-fetch/index.browser.js.map +1 -0
  139. package/dist/packlets/safer-fetch/index.js +52 -0
  140. package/dist/packlets/safer-fetch/index.js.map +1 -0
  141. package/dist/packlets/safer-fetch/model.js +21 -0
  142. package/dist/packlets/safer-fetch/model.js.map +1 -0
  143. package/dist/packlets/safer-fetch/nodeAddressGuard.js +191 -0
  144. package/dist/packlets/safer-fetch/nodeAddressGuard.js.map +1 -0
  145. package/dist/packlets/safer-fetch/redirect.js +93 -0
  146. package/dist/packlets/safer-fetch/redirect.js.map +1 -0
  147. package/dist/packlets/safer-fetch/retry.js +188 -0
  148. package/dist/packlets/safer-fetch/retry.js.map +1 -0
  149. package/dist/packlets/safer-fetch/saferFetch.js +755 -0
  150. package/dist/packlets/safer-fetch/saferFetch.js.map +1 -0
  151. package/dist/packlets/safer-fetch/transport.js +50 -0
  152. package/dist/packlets/safer-fetch/transport.js.map +1 -0
  153. package/dist/packlets/yaml/converters.js.map +1 -0
  154. package/dist/packlets/yaml/index.js +1 -0
  155. package/dist/packlets/yaml/index.js.map +1 -0
  156. package/dist/packlets/yaml/serializers.js +48 -0
  157. package/dist/packlets/yaml/serializers.js.map +1 -0
  158. package/dist/packlets/zip-file-tree/index.js.map +1 -0
  159. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js +99 -9
  160. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  161. package/dist/packlets/zip-file-tree/zipFileTreeWriter.js +16 -1
  162. package/dist/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  163. package/dist/ts-extras.d.ts +6648 -553
  164. package/dist/tsdoc-metadata.json +1 -1
  165. package/lib/index.browser.d.ts +5 -2
  166. package/lib/index.browser.d.ts.map +1 -0
  167. package/lib/index.browser.js +11 -3
  168. package/lib/index.browser.js.map +1 -0
  169. package/lib/index.d.ts +2 -1
  170. package/lib/index.d.ts.map +1 -0
  171. package/lib/index.js +3 -1
  172. package/lib/index.js.map +1 -0
  173. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +149 -0
  174. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -0
  175. package/lib/packlets/ai-assist/chatRequestBuilders.js +293 -0
  176. package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  177. package/lib/packlets/ai-assist/completionClient.d.ts +74 -0
  178. package/lib/packlets/ai-assist/completionClient.d.ts.map +1 -0
  179. package/lib/packlets/ai-assist/{apiClient.js → completionClient.js} +164 -213
  180. package/lib/packlets/ai-assist/completionClient.js.map +1 -0
  181. package/lib/packlets/ai-assist/converters.d.ts +15 -1
  182. package/lib/packlets/ai-assist/converters.d.ts.map +1 -0
  183. package/lib/packlets/ai-assist/converters.js +47 -3
  184. package/lib/packlets/ai-assist/converters.js.map +1 -0
  185. package/lib/packlets/ai-assist/embeddingClient.d.ts +69 -0
  186. package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -0
  187. package/lib/packlets/ai-assist/embeddingClient.js +349 -0
  188. package/lib/packlets/ai-assist/embeddingClient.js.map +1 -0
  189. package/lib/packlets/ai-assist/endpoint.d.ts +49 -0
  190. package/lib/packlets/ai-assist/endpoint.d.ts.map +1 -0
  191. package/lib/packlets/ai-assist/endpoint.js +113 -0
  192. package/lib/packlets/ai-assist/endpoint.js.map +1 -0
  193. package/lib/packlets/ai-assist/http.d.ts +34 -0
  194. package/lib/packlets/ai-assist/http.d.ts.map +1 -0
  195. package/lib/packlets/ai-assist/http.js +109 -0
  196. package/lib/packlets/ai-assist/http.js.map +1 -0
  197. package/lib/packlets/ai-assist/imageGenerationClient.d.ts +46 -0
  198. package/lib/packlets/ai-assist/imageGenerationClient.d.ts.map +1 -0
  199. package/lib/packlets/ai-assist/imageGenerationClient.js +458 -0
  200. package/lib/packlets/ai-assist/imageGenerationClient.js.map +1 -0
  201. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts +66 -0
  202. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts.map +1 -0
  203. package/lib/packlets/ai-assist/imageOptionsResolver.js +197 -0
  204. package/lib/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  205. package/lib/packlets/ai-assist/index.d.ts +12 -4
  206. package/lib/packlets/ai-assist/index.d.ts.map +1 -0
  207. package/lib/packlets/ai-assist/index.js +47 -4
  208. package/lib/packlets/ai-assist/index.js.map +1 -0
  209. package/lib/packlets/ai-assist/jsonCompletion.d.ts +93 -0
  210. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -0
  211. package/lib/packlets/ai-assist/jsonCompletion.js +97 -0
  212. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -0
  213. package/lib/packlets/ai-assist/jsonResponse.d.ts +194 -0
  214. package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -0
  215. package/lib/packlets/ai-assist/jsonResponse.js +429 -0
  216. package/lib/packlets/ai-assist/jsonResponse.js.map +1 -0
  217. package/lib/packlets/ai-assist/listModelsClient.d.ts +46 -0
  218. package/lib/packlets/ai-assist/listModelsClient.d.ts.map +1 -0
  219. package/lib/packlets/ai-assist/listModelsClient.js +298 -0
  220. package/lib/packlets/ai-assist/listModelsClient.js.map +1 -0
  221. package/lib/packlets/ai-assist/model.d.ts +1346 -12
  222. package/lib/packlets/ai-assist/model.d.ts.map +1 -0
  223. package/lib/packlets/ai-assist/model.js +309 -10
  224. package/lib/packlets/ai-assist/model.js.map +1 -0
  225. package/lib/packlets/ai-assist/registry.d.ts +76 -1
  226. package/lib/packlets/ai-assist/registry.d.ts.map +1 -0
  227. package/lib/packlets/ai-assist/registry.js +381 -13
  228. package/lib/packlets/ai-assist/registry.js.map +1 -0
  229. package/lib/packlets/ai-assist/sseParser.d.ts +45 -0
  230. package/lib/packlets/ai-assist/sseParser.d.ts.map +1 -0
  231. package/lib/packlets/ai-assist/sseParser.js +128 -0
  232. package/lib/packlets/ai-assist/sseParser.js.map +1 -0
  233. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +72 -0
  234. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -0
  235. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +379 -0
  236. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  237. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +269 -0
  238. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -0
  239. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +694 -0
  240. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  241. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +163 -0
  242. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -0
  243. package/lib/packlets/ai-assist/streamingAdapters/common.js +193 -0
  244. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  245. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts +43 -0
  246. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -0
  247. package/lib/packlets/ai-assist/streamingAdapters/gemini.js +211 -0
  248. package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  249. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts +19 -0
  250. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts.map +1 -0
  251. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js +178 -0
  252. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  253. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +33 -0
  254. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -0
  255. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +393 -0
  256. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  257. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts +34 -0
  258. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -0
  259. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +181 -0
  260. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  261. package/lib/packlets/ai-assist/streamingClient.d.ts +50 -0
  262. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -0
  263. package/lib/packlets/ai-assist/streamingClient.js +146 -0
  264. package/lib/packlets/ai-assist/streamingClient.js.map +1 -0
  265. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts +87 -0
  266. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts.map +1 -0
  267. package/lib/packlets/ai-assist/thinkingOptionsResolver.js +294 -0
  268. package/lib/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  269. package/lib/packlets/ai-assist/toolFormats.d.ts +40 -9
  270. package/lib/packlets/ai-assist/toolFormats.d.ts.map +1 -0
  271. package/lib/packlets/ai-assist/toolFormats.js +107 -10
  272. package/lib/packlets/ai-assist/toolFormats.js.map +1 -0
  273. package/lib/packlets/conversion/converters.d.ts +8 -1
  274. package/lib/packlets/conversion/converters.d.ts.map +1 -0
  275. package/lib/packlets/conversion/converters.js +36 -2
  276. package/lib/packlets/conversion/converters.js.map +1 -0
  277. package/lib/packlets/conversion/index.d.ts.map +1 -0
  278. package/lib/packlets/conversion/index.js.map +1 -0
  279. package/lib/packlets/crypto-utils/constants.d.ts.map +1 -0
  280. package/lib/packlets/crypto-utils/constants.js.map +1 -0
  281. package/lib/packlets/crypto-utils/converters.d.ts +20 -1
  282. package/lib/packlets/crypto-utils/converters.d.ts.map +1 -0
  283. package/lib/packlets/crypto-utils/converters.js +43 -5
  284. package/lib/packlets/crypto-utils/converters.js.map +1 -0
  285. package/lib/packlets/crypto-utils/directEncryptionProvider.d.ts.map +1 -0
  286. package/lib/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  287. package/lib/packlets/crypto-utils/encryptedFile.d.ts +25 -0
  288. package/lib/packlets/crypto-utils/encryptedFile.d.ts.map +1 -0
  289. package/lib/packlets/crypto-utils/encryptedFile.js +38 -0
  290. package/lib/packlets/crypto-utils/encryptedFile.js.map +1 -0
  291. package/lib/packlets/crypto-utils/hpkeProvider.d.ts +150 -0
  292. package/lib/packlets/crypto-utils/hpkeProvider.d.ts.map +1 -0
  293. package/lib/packlets/crypto-utils/hpkeProvider.js +359 -0
  294. package/lib/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  295. package/lib/packlets/crypto-utils/index.browser.d.ts +5 -1
  296. package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -0
  297. package/lib/packlets/crypto-utils/index.browser.js +28 -3
  298. package/lib/packlets/crypto-utils/index.browser.js.map +1 -0
  299. package/lib/packlets/crypto-utils/index.d.ts +5 -1
  300. package/lib/packlets/crypto-utils/index.d.ts.map +1 -0
  301. package/lib/packlets/crypto-utils/index.js +24 -1
  302. package/lib/packlets/crypto-utils/index.js.map +1 -0
  303. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts +54 -0
  304. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts.map +1 -0
  305. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js +74 -0
  306. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  307. package/lib/packlets/crypto-utils/keystore/converters.d.ts +68 -6
  308. package/lib/packlets/crypto-utils/keystore/converters.d.ts.map +1 -0
  309. package/lib/packlets/crypto-utils/keystore/converters.js +109 -14
  310. package/lib/packlets/crypto-utils/keystore/converters.js.map +1 -0
  311. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts +148 -0
  312. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts.map +1 -0
  313. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +324 -0
  314. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  315. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts +10 -0
  316. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts.map +1 -0
  317. package/lib/packlets/crypto-utils/keystore/index.browser.js +76 -0
  318. package/lib/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  319. package/lib/packlets/crypto-utils/keystore/index.d.ts +2 -0
  320. package/lib/packlets/crypto-utils/keystore/index.d.ts.map +1 -0
  321. package/lib/packlets/crypto-utils/keystore/index.js +5 -1
  322. package/lib/packlets/crypto-utils/keystore/index.js.map +1 -0
  323. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +314 -13
  324. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -0
  325. package/lib/packlets/crypto-utils/keystore/keyStore.js +877 -124
  326. package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  327. package/lib/packlets/crypto-utils/keystore/model.d.ts +404 -21
  328. package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -0
  329. package/lib/packlets/crypto-utils/keystore/model.js +37 -5
  330. package/lib/packlets/crypto-utils/keystore/model.js.map +1 -0
  331. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts +53 -0
  332. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts.map +1 -0
  333. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js +22 -0
  334. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  335. package/lib/packlets/crypto-utils/model.d.ts +518 -10
  336. package/lib/packlets/crypto-utils/model.d.ts.map +1 -0
  337. package/lib/packlets/crypto-utils/model.js +33 -1
  338. package/lib/packlets/crypto-utils/model.js.map +1 -0
  339. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts +142 -2
  340. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -0
  341. package/lib/packlets/crypto-utils/nodeCryptoProvider.js +346 -0
  342. package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  343. package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts +42 -0
  344. package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts.map +1 -0
  345. package/lib/packlets/crypto-utils/seedDerivedKeyPair.js +123 -0
  346. package/lib/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -0
  347. package/lib/packlets/crypto-utils/spkiHelpers.d.ts +151 -0
  348. package/lib/packlets/crypto-utils/spkiHelpers.d.ts.map +1 -0
  349. package/lib/packlets/crypto-utils/spkiHelpers.js +297 -0
  350. package/lib/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  351. package/lib/packlets/csv/csvFileHelpers.d.ts +0 -10
  352. package/lib/packlets/csv/csvFileHelpers.d.ts.map +1 -0
  353. package/lib/packlets/csv/csvFileHelpers.js +0 -15
  354. package/lib/packlets/csv/csvFileHelpers.js.map +1 -0
  355. package/lib/packlets/csv/csvHelpers.d.ts +10 -0
  356. package/lib/packlets/csv/csvHelpers.d.ts.map +1 -0
  357. package/lib/packlets/csv/csvHelpers.js +15 -0
  358. package/lib/packlets/csv/csvHelpers.js.map +1 -0
  359. package/lib/packlets/csv/index.browser.d.ts +0 -1
  360. package/lib/packlets/csv/index.browser.d.ts.map +1 -0
  361. package/lib/packlets/csv/index.browser.js +1 -5
  362. package/lib/packlets/csv/index.browser.js.map +1 -0
  363. package/lib/packlets/csv/index.d.ts.map +1 -0
  364. package/lib/packlets/csv/index.js.map +1 -0
  365. package/lib/packlets/experimental/extendedArray.d.ts.map +1 -0
  366. package/lib/packlets/experimental/extendedArray.js.map +1 -0
  367. package/lib/packlets/experimental/formatter.d.ts.map +1 -0
  368. package/lib/packlets/experimental/formatter.js.map +1 -0
  369. package/lib/packlets/experimental/index.d.ts.map +1 -0
  370. package/lib/packlets/experimental/index.js.map +1 -0
  371. package/lib/packlets/experimental/rangeOf.d.ts.map +1 -0
  372. package/lib/packlets/experimental/rangeOf.js.map +1 -0
  373. package/lib/packlets/hash/index.browser.d.ts.map +1 -0
  374. package/lib/packlets/hash/index.browser.js.map +1 -0
  375. package/lib/packlets/hash/index.d.ts.map +1 -0
  376. package/lib/packlets/hash/index.js.map +1 -0
  377. package/lib/packlets/hash/index.node.d.ts.map +1 -0
  378. package/lib/packlets/hash/index.node.js.map +1 -0
  379. package/lib/packlets/hash/md5Normalizer.browser.d.ts.map +1 -0
  380. package/lib/packlets/hash/md5Normalizer.browser.js.map +1 -0
  381. package/lib/packlets/hash/md5Normalizer.d.ts.map +1 -0
  382. package/lib/packlets/hash/md5Normalizer.js.map +1 -0
  383. package/lib/packlets/mustache/index.d.ts +1 -1
  384. package/lib/packlets/mustache/index.d.ts.map +1 -0
  385. package/lib/packlets/mustache/index.js.map +1 -0
  386. package/lib/packlets/mustache/interfaces.d.ts +34 -0
  387. package/lib/packlets/mustache/interfaces.d.ts.map +1 -0
  388. package/lib/packlets/mustache/interfaces.js.map +1 -0
  389. package/lib/packlets/mustache/mustacheTemplate.d.ts +2 -0
  390. package/lib/packlets/mustache/mustacheTemplate.d.ts.map +1 -0
  391. package/lib/packlets/mustache/mustacheTemplate.js +42 -4
  392. package/lib/packlets/mustache/mustacheTemplate.js.map +1 -0
  393. package/lib/packlets/record-jar/index.browser.d.ts +0 -1
  394. package/lib/packlets/record-jar/index.browser.d.ts.map +1 -0
  395. package/lib/packlets/record-jar/index.browser.js +1 -5
  396. package/lib/packlets/record-jar/index.browser.js.map +1 -0
  397. package/lib/packlets/record-jar/index.d.ts.map +1 -0
  398. package/lib/packlets/record-jar/index.js.map +1 -0
  399. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts +0 -11
  400. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts.map +1 -0
  401. package/lib/packlets/record-jar/recordJarFileHelpers.js +0 -19
  402. package/lib/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  403. package/lib/packlets/record-jar/recordJarHelpers.d.ts +11 -0
  404. package/lib/packlets/record-jar/recordJarHelpers.d.ts.map +1 -0
  405. package/lib/packlets/record-jar/recordJarHelpers.js +19 -0
  406. package/lib/packlets/record-jar/recordJarHelpers.js.map +1 -0
  407. package/lib/packlets/safer-fetch/addressClassification.d.ts +144 -0
  408. package/lib/packlets/safer-fetch/addressClassification.d.ts.map +1 -0
  409. package/lib/packlets/safer-fetch/addressClassification.js +441 -0
  410. package/lib/packlets/safer-fetch/addressClassification.js.map +1 -0
  411. package/lib/packlets/safer-fetch/addressPolicy.d.ts +113 -0
  412. package/lib/packlets/safer-fetch/addressPolicy.d.ts.map +1 -0
  413. package/lib/packlets/safer-fetch/addressPolicy.js +123 -0
  414. package/lib/packlets/safer-fetch/addressPolicy.js.map +1 -0
  415. package/lib/packlets/safer-fetch/contentType.d.ts +51 -0
  416. package/lib/packlets/safer-fetch/contentType.d.ts.map +1 -0
  417. package/lib/packlets/safer-fetch/contentType.js +127 -0
  418. package/lib/packlets/safer-fetch/contentType.js.map +1 -0
  419. package/lib/packlets/safer-fetch/deadline.d.ts +138 -0
  420. package/lib/packlets/safer-fetch/deadline.d.ts.map +1 -0
  421. package/lib/packlets/safer-fetch/deadline.js +258 -0
  422. package/lib/packlets/safer-fetch/deadline.js.map +1 -0
  423. package/lib/packlets/safer-fetch/defaults.d.ts +108 -0
  424. package/lib/packlets/safer-fetch/defaults.d.ts.map +1 -0
  425. package/lib/packlets/safer-fetch/defaults.js +134 -0
  426. package/lib/packlets/safer-fetch/defaults.js.map +1 -0
  427. package/lib/packlets/safer-fetch/failureReason.d.ts +148 -0
  428. package/lib/packlets/safer-fetch/failureReason.d.ts.map +1 -0
  429. package/lib/packlets/safer-fetch/failureReason.js +22 -0
  430. package/lib/packlets/safer-fetch/failureReason.js.map +1 -0
  431. package/lib/packlets/safer-fetch/guards.d.ts +62 -0
  432. package/lib/packlets/safer-fetch/guards.d.ts.map +1 -0
  433. package/lib/packlets/safer-fetch/guards.js +153 -0
  434. package/lib/packlets/safer-fetch/guards.js.map +1 -0
  435. package/lib/packlets/safer-fetch/index.browser.d.ts +33 -0
  436. package/lib/packlets/safer-fetch/index.browser.d.ts.map +1 -0
  437. package/lib/packlets/safer-fetch/index.browser.js +82 -0
  438. package/lib/packlets/safer-fetch/index.browser.js.map +1 -0
  439. package/lib/packlets/safer-fetch/index.d.ts +27 -0
  440. package/lib/packlets/safer-fetch/index.d.ts.map +1 -0
  441. package/lib/packlets/safer-fetch/index.js +78 -0
  442. package/lib/packlets/safer-fetch/index.js.map +1 -0
  443. package/lib/packlets/safer-fetch/model.d.ts +373 -0
  444. package/lib/packlets/safer-fetch/model.d.ts.map +1 -0
  445. package/lib/packlets/safer-fetch/model.js +22 -0
  446. package/lib/packlets/safer-fetch/model.js.map +1 -0
  447. package/lib/packlets/safer-fetch/nodeAddressGuard.d.ts +129 -0
  448. package/lib/packlets/safer-fetch/nodeAddressGuard.d.ts.map +1 -0
  449. package/lib/packlets/safer-fetch/nodeAddressGuard.js +196 -0
  450. package/lib/packlets/safer-fetch/nodeAddressGuard.js.map +1 -0
  451. package/lib/packlets/safer-fetch/redirect.d.ts +62 -0
  452. package/lib/packlets/safer-fetch/redirect.d.ts.map +1 -0
  453. package/lib/packlets/safer-fetch/redirect.js +98 -0
  454. package/lib/packlets/safer-fetch/redirect.js.map +1 -0
  455. package/lib/packlets/safer-fetch/retry.d.ts +162 -0
  456. package/lib/packlets/safer-fetch/retry.d.ts.map +1 -0
  457. package/lib/packlets/safer-fetch/retry.js +197 -0
  458. package/lib/packlets/safer-fetch/retry.js.map +1 -0
  459. package/lib/packlets/safer-fetch/saferFetch.d.ts +108 -0
  460. package/lib/packlets/safer-fetch/saferFetch.d.ts.map +1 -0
  461. package/lib/packlets/safer-fetch/saferFetch.js +760 -0
  462. package/lib/packlets/safer-fetch/saferFetch.js.map +1 -0
  463. package/lib/packlets/safer-fetch/transport.d.ts +18 -0
  464. package/lib/packlets/safer-fetch/transport.d.ts.map +1 -0
  465. package/lib/packlets/safer-fetch/transport.js +53 -0
  466. package/lib/packlets/safer-fetch/transport.js.map +1 -0
  467. package/lib/packlets/yaml/converters.d.ts.map +1 -0
  468. package/lib/packlets/yaml/converters.js.map +1 -0
  469. package/lib/packlets/yaml/index.d.ts +1 -0
  470. package/lib/packlets/yaml/index.d.ts.map +1 -0
  471. package/lib/packlets/yaml/index.js +1 -0
  472. package/lib/packlets/yaml/index.js.map +1 -0
  473. package/lib/packlets/yaml/serializers.d.ts +45 -0
  474. package/lib/packlets/yaml/serializers.d.ts.map +1 -0
  475. package/lib/packlets/yaml/serializers.js +84 -0
  476. package/lib/packlets/yaml/serializers.js.map +1 -0
  477. package/lib/packlets/zip-file-tree/index.d.ts.map +1 -0
  478. package/lib/packlets/zip-file-tree/index.js.map +1 -0
  479. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts +84 -8
  480. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts.map +1 -0
  481. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js +99 -9
  482. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  483. package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts +26 -1
  484. package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts.map +1 -0
  485. package/lib/packlets/zip-file-tree/zipFileTreeWriter.js +17 -1
  486. package/lib/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  487. package/package.json +30 -15
  488. package/lib/packlets/ai-assist/apiClient.d.ts +0 -60
@@ -0,0 +1,109 @@
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.fetchJson = fetchJson;
23
+ exports.fetchGetJson = fetchGetJson;
24
+ exports.fetchMultipart = fetchMultipart;
25
+ /**
26
+ * Shared low-level HTTP helpers for the AI-assist provider clients (completion,
27
+ * image generation, embedding). Internal to the packlet.
28
+ * @packageDocumentation
29
+ */
30
+ const ts_json_base_1 = require("@fgv/ts-json-base");
31
+ const ts_utils_1 = require("@fgv/ts-utils");
32
+ /**
33
+ * Issue one request and parse a JSON object body, or fail.
34
+ *
35
+ * @remarks
36
+ * The single implementation behind {@link fetchJson}, {@link fetchGetJson} and
37
+ * {@link fetchMultipart} — the three differed *only* in how they built their
38
+ * `RequestInit` and what they logged, and carried byte-identical copies of
39
+ * everything after the `fetch` call. Non-2xx responses, network errors, invalid
40
+ * JSON and non-object JSON bodies are all surfaced as `Result.fail`.
41
+ * @internal
42
+ */
43
+ async function _fetchAndParseJson(url, init, requestLabel, logger) {
44
+ /* c8 ignore next 1 - optional logger */
45
+ logger === null || logger === void 0 ? void 0 : logger.detail(`AI API request: ${requestLabel}`);
46
+ // `captureAsyncResult` normalizes both a synchronous throw and a rejected
47
+ // promise, and its `_errorMessage` is the same `instanceof Error` shaping this
48
+ // used to spell out by hand — so the failure text is unchanged and the
49
+ // defensive `c8 ignore` on the non-Error branch is no longer needed here.
50
+ const fetched = await (0, ts_utils_1.captureAsyncResult)(() => fetch(url, init)).withErrorFormat((msg) => `AI API request failed: ${msg}`);
51
+ if (fetched.isFailure()) {
52
+ /* c8 ignore next 1 - optional logger */
53
+ logger === null || logger === void 0 ? void 0 : logger.error(fetched.message);
54
+ return (0, ts_utils_1.fail)(fetched.message);
55
+ }
56
+ const response = fetched.value;
57
+ if (!response.ok) {
58
+ const errorText = await response.text().catch(() => 'unknown error');
59
+ /* c8 ignore next 1 - optional logger */
60
+ logger === null || logger === void 0 ? void 0 : logger.error(`AI API returned ${response.status}: ${errorText}`);
61
+ return (0, ts_utils_1.fail)(`AI API returned ${response.status}: ${errorText}`);
62
+ }
63
+ /* c8 ignore next 1 - optional logger */
64
+ logger === null || logger === void 0 ? void 0 : logger.detail(`AI API response: ${response.status}`);
65
+ let json;
66
+ try {
67
+ json = await response.json();
68
+ }
69
+ catch (_a) {
70
+ /* c8 ignore next 1 - optional logger */
71
+ logger === null || logger === void 0 ? void 0 : logger.error('AI API returned invalid JSON response');
72
+ return (0, ts_utils_1.fail)('AI API returned invalid JSON response');
73
+ }
74
+ if (!(0, ts_json_base_1.isJsonObject)(json)) {
75
+ /* c8 ignore next 1 - optional logger */
76
+ logger === null || logger === void 0 ? void 0 : logger.error('AI API returned non-object JSON response');
77
+ return (0, ts_utils_1.fail)('AI API returned non-object JSON response');
78
+ }
79
+ return (0, ts_utils_1.succeed)(json);
80
+ }
81
+ /**
82
+ * Makes a JSON POST request and returns the parsed object body, or a failure.
83
+ * @internal
84
+ */
85
+ async function fetchJson(url, headers, body, logger, signal) {
86
+ return _fetchAndParseJson(url, {
87
+ method: 'POST',
88
+ headers: Object.assign({ 'Content-Type': 'application/json' }, headers),
89
+ body: JSON.stringify(body),
90
+ signal
91
+ }, `POST ${url}`, logger);
92
+ }
93
+ /**
94
+ * Makes an HTTP GET request and returns the parsed JSON, or a failure.
95
+ * @internal
96
+ */
97
+ async function fetchGetJson(url, headers, logger, signal) {
98
+ return _fetchAndParseJson(url, { method: 'GET', headers, signal }, `GET ${url}`, logger);
99
+ }
100
+ /**
101
+ * Makes a multipart/form-data POST request and returns the parsed JSON, or a
102
+ * failure. The Content-Type header (with boundary) is set automatically by
103
+ * `fetch` from the `FormData` body — callers must NOT pass it explicitly.
104
+ * @internal
105
+ */
106
+ async function fetchMultipart(url, headers, body, logger, signal) {
107
+ return _fetchAndParseJson(url, { method: 'POST', headers, body, signal }, `POST ${url} (multipart)`, logger);
108
+ }
109
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/http.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;;AAsFZ,8BAkBC;AAMD,oCAOC;AAQD,wCAaC;AAxID;;;;GAIG;AAEH,oDAAkE;AAClE,4CAAwF;AAYxF;;;;;;;;;;GAUG;AACH,KAAK,UAAU,kBAAkB,CAC/B,GAAW,EACX,IAAiB,EACjB,YAAoB,EACpB,MAAwB;IAExB,wCAAwC;IACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,mBAAmB,YAAY,EAAE,CAAC,CAAC;IAElD,0EAA0E;IAC1E,+EAA+E;IAC/E,uEAAuE;IACvE,0EAA0E;IAC1E,MAAM,OAAO,GAAqB,MAAM,IAAA,6BAAkB,EAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,eAAe,CAChG,CAAC,GAAG,EAAE,EAAE,CAAC,0BAA0B,GAAG,EAAE,CACzC,CAAC;IACF,IAAI,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;QACxB,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/B,OAAO,IAAA,eAAI,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,QAAQ,GAAa,OAAO,CAAC,KAAK,CAAC;IAEzC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;QACrE,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;QAClE,OAAO,IAAA,eAAI,EAAC,mBAAmB,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,wCAAwC;IACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,oBAAoB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtD,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,WAAM,CAAC;QACP,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACvD,OAAO,IAAA,eAAI,EAAC,uCAAuC,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,IAAA,2BAAY,EAAC,IAAI,CAAC,EAAE,CAAC;QACxB,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,IAAA,eAAI,EAAC,0CAA0C,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,IAAA,kBAAO,EAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,OAA+B,EAC/B,IAAa,EACb,MAAwB,EACxB,MAAoB;IAEpB,OAAO,kBAAkB,CACvB,GAAG,EACH;QACE,MAAM,EAAE,MAAM;QACd,OAAO,kBAAI,cAAc,EAAE,kBAAkB,IAAK,OAAO,CAAE;QAC3D,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC1B,MAAM;KACP,EACD,QAAQ,GAAG,EAAE,EACb,MAAM,CACP,CAAC;AACJ,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,OAA+B,EAC/B,MAAwB,EACxB,MAAoB;IAEpB,OAAO,kBAAkB,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;AAC3F,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,OAA+B,EAC/B,IAAc,EACd,MAAwB,EACxB,MAAoB;IAEpB,OAAO,kBAAkB,CACvB,GAAG,EACH,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EACzC,QAAQ,GAAG,cAAc,EACzB,MAAM,CACP,CAAC;AACJ,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 * Shared low-level HTTP helpers for the AI-assist provider clients (completion,\n * image generation, embedding). Internal to the packlet.\n * @packageDocumentation\n */\n\nimport { isJsonObject, type JsonObject } from '@fgv/ts-json-base';\nimport { captureAsyncResult, fail, type Logging, Result, succeed } from '@fgv/ts-utils';\n\n/**\n * Internal API configuration built from a provider descriptor.\n * @internal\n */\nexport interface IAiApiConfig {\n readonly baseUrl: string;\n readonly apiKey: string;\n readonly model: string;\n}\n\n/**\n * Issue one request and parse a JSON object body, or fail.\n *\n * @remarks\n * The single implementation behind {@link fetchJson}, {@link fetchGetJson} and\n * {@link fetchMultipart} — the three differed *only* in how they built their\n * `RequestInit` and what they logged, and carried byte-identical copies of\n * everything after the `fetch` call. Non-2xx responses, network errors, invalid\n * JSON and non-object JSON bodies are all surfaced as `Result.fail`.\n * @internal\n */\nasync function _fetchAndParseJson(\n url: string,\n init: RequestInit,\n requestLabel: string,\n logger?: Logging.ILogger\n): Promise<Result<JsonObject>> {\n /* c8 ignore next 1 - optional logger */\n logger?.detail(`AI API request: ${requestLabel}`);\n\n // `captureAsyncResult` normalizes both a synchronous throw and a rejected\n // promise, and its `_errorMessage` is the same `instanceof Error` shaping this\n // used to spell out by hand — so the failure text is unchanged and the\n // defensive `c8 ignore` on the non-Error branch is no longer needed here.\n const fetched: Result<Response> = await captureAsyncResult(() => fetch(url, init)).withErrorFormat(\n (msg) => `AI API request failed: ${msg}`\n );\n if (fetched.isFailure()) {\n /* c8 ignore next 1 - optional logger */\n logger?.error(fetched.message);\n return fail(fetched.message);\n }\n const response: Response = fetched.value;\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'unknown error');\n /* c8 ignore next 1 - optional logger */\n logger?.error(`AI API returned ${response.status}: ${errorText}`);\n return fail(`AI API returned ${response.status}: ${errorText}`);\n }\n\n /* c8 ignore next 1 - optional logger */\n logger?.detail(`AI API response: ${response.status}`);\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n /* c8 ignore next 1 - optional logger */\n logger?.error('AI API returned invalid JSON response');\n return fail('AI API returned invalid JSON response');\n }\n\n if (!isJsonObject(json)) {\n /* c8 ignore next 1 - optional logger */\n logger?.error('AI API returned non-object JSON response');\n return fail('AI API returned non-object JSON response');\n }\n return succeed(json);\n}\n\n/**\n * Makes a JSON POST request and returns the parsed object body, or a failure.\n * @internal\n */\nexport async function fetchJson(\n url: string,\n headers: Record<string, string>,\n body: unknown,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<JsonObject>> {\n return _fetchAndParseJson(\n url,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify(body),\n signal\n },\n `POST ${url}`,\n logger\n );\n}\n\n/**\n * Makes an HTTP GET request and returns the parsed JSON, or a failure.\n * @internal\n */\nexport async function fetchGetJson(\n url: string,\n headers: Record<string, string>,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<JsonObject>> {\n return _fetchAndParseJson(url, { method: 'GET', headers, signal }, `GET ${url}`, logger);\n}\n\n/**\n * Makes a multipart/form-data POST request and returns the parsed JSON, or a\n * failure. The Content-Type header (with boundary) is set automatically by\n * `fetch` from the `FormData` body — callers must NOT pass it explicitly.\n * @internal\n */\nexport async function fetchMultipart(\n url: string,\n headers: Record<string, string>,\n body: FormData,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<JsonObject>> {\n return _fetchAndParseJson(\n url,\n { method: 'POST', headers, body, signal },\n `POST ${url} (multipart)`,\n logger\n );\n}\n"]}
@@ -0,0 +1,46 @@
1
+ import { type Logging, Result } from '@fgv/ts-utils';
2
+ import { type IAiImageGenerationParams, type IAiImageGenerationResponse, type IAiProviderDescriptor, type ModelSpec } from './model';
3
+ /**
4
+ * Parameters for an image-generation request.
5
+ * @public
6
+ */
7
+ export interface IProviderImageGenerationParams {
8
+ /** The provider descriptor */
9
+ readonly descriptor: IAiProviderDescriptor;
10
+ /** API key for authentication */
11
+ readonly apiKey: string;
12
+ /** The image-generation request */
13
+ readonly params: IAiImageGenerationParams;
14
+ /** Optional model override — string or context-aware map (uses descriptor.defaultModel.image otherwise) */
15
+ readonly modelOverride?: ModelSpec;
16
+ /** Optional logger for request/response observability. */
17
+ readonly logger?: Logging.ILogger;
18
+ /** Optional abort signal for cancelling the in-flight request. */
19
+ readonly signal?: AbortSignal;
20
+ /** Optional override of the descriptor's base URL; per-route suffix is appended unchanged. */
21
+ readonly endpoint?: string;
22
+ }
23
+ /**
24
+ * Calls the appropriate image-generation API for a given provider. Routes by the
25
+ * `format` field of the resolved {@link IAiImageModelCapability}:
26
+ * `'openai-images'`, `'xai-images'`, `'xai-images-edits'`, or
27
+ * `'gemini-image-out'`. Rejects up front if `referenceImages` is set but the
28
+ * capability does not declare `acceptsImageReferenceInput`.
29
+ * @param params - Request parameters including descriptor, API key, and prompt
30
+ * @public
31
+ */
32
+ export declare function callProviderImageGeneration(params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
33
+ /**
34
+ * Calls the image-generation endpoint on a proxy server instead of calling
35
+ * the provider API directly from the browser.
36
+ * Endpoint: `POST ${proxyUrl}/api/ai/image-generation`. Request body:
37
+ * `{providerId, apiKey, params, modelOverride?}`. The proxy handles descriptor
38
+ * lookup, model resolution, provider dispatch, and response normalization
39
+ * (including repackaging `referenceImages` for the upstream wire format).
40
+ * Error body `{error: string}` is surfaced as `proxy: ${error}`.
41
+ * @param proxyUrl - Base URL of the proxy server
42
+ * @param params - Same parameters as {@link callProviderImageGeneration}
43
+ * @public
44
+ */
45
+ export declare function callProxiedImageGeneration(proxyUrl: string, params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
46
+ //# sourceMappingURL=imageGenerationClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageGenerationClient.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/imageGenerationClient.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAQ,KAAK,OAAO,EAAc,MAAM,EAAuC,MAAM,eAAe,CAAC;AAE5G,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAE/B,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EAEf,MAAM,SAAS,CAAC;AAmEjB;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,8BAA8B;IAC9B,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAC3C,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAC1C,2GAA2G;IAC3G,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AA6YD;;;;;;;;GAQG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,8BAA8B,GACrC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CA+D7C;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,8BAA8B,GACrC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CA6B7C"}
@@ -0,0 +1,458 @@
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.callProviderImageGeneration = callProviderImageGeneration;
23
+ exports.callProxiedImageGeneration = callProxiedImageGeneration;
24
+ const ts_utils_1 = require("@fgv/ts-utils");
25
+ const model_1 = require("./model");
26
+ const endpoint_1 = require("./endpoint");
27
+ const http_1 = require("./http");
28
+ const registry_1 = require("./registry");
29
+ const imageOptionsResolver_1 = require("./imageOptionsResolver");
30
+ // ============================================================================
31
+ // Image attachment helpers
32
+ // ============================================================================
33
+ /**
34
+ * Decodes a base64-encoded image attachment into a `Blob` suitable for use as
35
+ * a multipart file field. On Node hands the `Buffer` straight to `Blob`
36
+ * (Buffer extends Uint8Array) to skip an intermediate copy; falls back to
37
+ * `atob` in browsers. Inputs come from `FileReader` or prior provider
38
+ * responses, which are trusted to be valid. Note that Node's
39
+ * `Buffer.from(..., 'base64')` silently strips invalid characters rather
40
+ * than throwing, so failures are only observable in the browser path.
41
+ * @internal
42
+ */
43
+ function attachmentToBlob(attachment) {
44
+ if (typeof Buffer !== 'undefined') {
45
+ return (0, ts_utils_1.succeed)(new Blob([Buffer.from(attachment.base64, 'base64')], { type: attachment.mimeType }));
46
+ }
47
+ /* c8 ignore start - Browser-only fallback cannot be tested in Node.js environment */
48
+ try {
49
+ const binary = atob(attachment.base64);
50
+ const bytes = new Uint8Array(binary.length);
51
+ for (let i = 0; i < binary.length; i++) {
52
+ bytes[i] = binary.charCodeAt(i);
53
+ }
54
+ return (0, ts_utils_1.succeed)(new Blob([bytes], { type: attachment.mimeType }));
55
+ }
56
+ catch (e) {
57
+ const message = e instanceof Error ? e.message : String(e);
58
+ return (0, ts_utils_1.fail)(`Invalid base64: ${message}`);
59
+ }
60
+ /* c8 ignore stop */
61
+ }
62
+ /**
63
+ * Maps a MIME type to a sensible file extension for multipart filenames.
64
+ * @internal
65
+ */
66
+ function extensionForMimeType(mimeType) {
67
+ switch (mimeType) {
68
+ case 'image/png':
69
+ return 'png';
70
+ case 'image/jpeg':
71
+ case 'image/jpg':
72
+ return 'jpg';
73
+ case 'image/webp':
74
+ return 'webp';
75
+ case 'image/gif':
76
+ return 'gif';
77
+ default:
78
+ return 'bin';
79
+ }
80
+ }
81
+ const openAiImageItem = ts_utils_1.Validators.object({
82
+ b64_json: ts_utils_1.Validators.string,
83
+ revised_prompt: ts_utils_1.Validators.string.optional()
84
+ });
85
+ const openAiImageResponse = ts_utils_1.Validators.object({
86
+ data: ts_utils_1.Validators.arrayOf(openAiImageItem).withConstraint((arr) => arr.length > 0)
87
+ });
88
+ const geminiImageInlineData = ts_utils_1.Validators.object({
89
+ mimeType: ts_utils_1.Validators.string,
90
+ data: ts_utils_1.Validators.string
91
+ });
92
+ const geminiImageOutPart = ts_utils_1.Validators.object({
93
+ text: ts_utils_1.Validators.string.optional(),
94
+ inlineData: geminiImageInlineData.optional()
95
+ });
96
+ const geminiImageOutContent = ts_utils_1.Validators.object({
97
+ parts: ts_utils_1.Validators.arrayOf(geminiImageOutPart)
98
+ });
99
+ const geminiImageOutCandidate = ts_utils_1.Validators.object({
100
+ content: geminiImageOutContent.optional(),
101
+ finishReason: ts_utils_1.Validators.string.optional(),
102
+ finishMessage: ts_utils_1.Validators.string.optional()
103
+ });
104
+ const geminiImageOutResponse = ts_utils_1.Validators.object({
105
+ candidates: ts_utils_1.Validators.arrayOf(geminiImageOutCandidate).withConstraint((arr) => arr.length > 0)
106
+ });
107
+ // ---- Proxied image generation response ----
108
+ const proxiedGeneratedImage = ts_utils_1.Validators.object({
109
+ mimeType: ts_utils_1.Validators.string,
110
+ base64: ts_utils_1.Validators.string,
111
+ revisedPrompt: ts_utils_1.Validators.string.optional()
112
+ });
113
+ const proxiedImageGenerationResponse = ts_utils_1.Validators.object({
114
+ images: ts_utils_1.Validators.arrayOf(proxiedGeneratedImage).withConstraint((arr) => arr.length > 0)
115
+ });
116
+ // ============================================================================
117
+ // Image generation — adapters
118
+ // ============================================================================
119
+ /** Routes to /images/generations or /images/edits; handles outputParamStyle. @internal */
120
+ async function callOpenAiImageGeneration(config, request, capability, resolved, logger, signal) {
121
+ var _a, _b;
122
+ const refs = (_a = request.referenceImages) !== null && _a !== void 0 ? _a : [];
123
+ const headers = (0, endpoint_1.bearerAuthHeader)(config.apiKey);
124
+ const effectiveMimeType = resolved.outputFormat !== undefined
125
+ ? `image/${resolved.outputFormat}`
126
+ : (_b = capability.defaultOutputMimeType) !== null && _b !== void 0 ? _b : 'image/png';
127
+ const fetched = refs.length > 0
128
+ ? await callOpenAiImagesEdits(config, capability, request, headers, resolved, logger, signal)
129
+ : await callOpenAiImagesGenerations(config, request, headers, resolved, capability, logger, signal);
130
+ return fetched.onSuccess((json) => openAiImageResponse
131
+ .validate(json)
132
+ .withErrorFormat((msg) => `OpenAI images API response: ${msg}`)
133
+ .onSuccess((response) => (0, ts_utils_1.succeed)({
134
+ images: response.data.map((item) => (Object.assign({ mimeType: effectiveMimeType, base64: item.b64_json }, (item.revised_prompt !== undefined ? { revisedPrompt: item.revised_prompt } : {}))))
135
+ })));
136
+ }
137
+ /** Builds the JSON /images/generations request; handles outputParamStyle. @internal */
138
+ function callOpenAiImagesGenerations(config, request, headers, resolved, capability, logger, signal) {
139
+ var _a;
140
+ const body = {
141
+ model: config.model,
142
+ prompt: request.prompt,
143
+ n: resolved.n
144
+ };
145
+ // Output format param — conditional on model capability
146
+ if (capability.outputParamStyle === 'response-format') {
147
+ body.response_format = 'b64_json';
148
+ }
149
+ else if (capability.outputParamStyle === 'output-format') {
150
+ body.output_format = (_a = resolved.outputFormat) !== null && _a !== void 0 ? _a : 'png';
151
+ }
152
+ if (resolved.size !== undefined) {
153
+ body.size = resolved.size;
154
+ }
155
+ if (capability.supportsQualityParam && resolved.quality !== undefined) {
156
+ body.quality = resolved.quality;
157
+ }
158
+ if (resolved.seed !== undefined) {
159
+ body.seed = resolved.seed;
160
+ }
161
+ if (resolved.background !== undefined) {
162
+ body.background = resolved.background;
163
+ }
164
+ if (resolved.moderation !== undefined) {
165
+ body.moderation = resolved.moderation;
166
+ }
167
+ if (resolved.outputCompression !== undefined) {
168
+ body.output_compression = resolved.outputCompression;
169
+ }
170
+ if (resolved.otherParams !== undefined) {
171
+ Object.assign(body, resolved.otherParams);
172
+ }
173
+ /* c8 ignore next 1 - optional logger */
174
+ logger === null || logger === void 0 ? void 0 : logger.info(`Image generation: model=${config.model}, n=${resolved.n}`);
175
+ return (0, http_1.fetchJson)(`${config.baseUrl}/images/generations`, headers, body, logger, signal);
176
+ }
177
+ /** Builds the multipart /images/edits request with ref images. @internal */
178
+ async function callOpenAiImagesEdits(config, capability, request, headers, resolved, logger, signal) {
179
+ const refs = request.referenceImages; // callers verify refs.length > 0 before calling this function
180
+ const blobsResult = (0, ts_utils_1.mapResults)(refs.map((ref, i) => attachmentToBlob(ref).withErrorFormat((msg) => `reference image ${i}: ${msg}`)));
181
+ /* c8 ignore next 3 - decode failure unreachable via Node's Buffer.from (silently strips invalid input) */
182
+ if (blobsResult.isFailure()) {
183
+ return (0, ts_utils_1.fail)(blobsResult.message);
184
+ }
185
+ const form = new FormData();
186
+ form.append('model', config.model);
187
+ form.append('prompt', request.prompt);
188
+ form.append('n', String(resolved.n));
189
+ if (capability.outputParamStyle !== 'output-format') {
190
+ form.append('response_format', 'b64_json');
191
+ }
192
+ if (resolved.size !== undefined) {
193
+ form.append('size', resolved.size);
194
+ }
195
+ blobsResult.value.forEach((blob, i) => {
196
+ form.append('image[]', blob, `ref-${i}.${extensionForMimeType(refs[i].mimeType)}`);
197
+ });
198
+ /* c8 ignore next 1 - optional logger */
199
+ logger === null || logger === void 0 ? void 0 : logger.info(`Image edit: model=${config.model}, n=${resolved.n}, refs=${refs.length}`);
200
+ return (0, http_1.fetchMultipart)(`${config.baseUrl}/images/edits`, headers, form, logger, signal);
201
+ }
202
+ /** Calls xAI /images/edits with JSON body (not multipart); up to 3 source images. @internal */
203
+ async function callXaiImagesEdits(config, request, resolved, logger, signal) {
204
+ var _a;
205
+ /* c8 ignore next 1 - defensive: referenceImages always defined when this function is called */
206
+ const refs = (_a = request.referenceImages) !== null && _a !== void 0 ? _a : [];
207
+ if (refs.length > 3) {
208
+ return (0, ts_utils_1.fail)(`xAI image edits supports at most 3 reference images; got ${refs.length}`);
209
+ }
210
+ const images = refs.map((ref) => ({
211
+ type: 'image_url',
212
+ url: `data:${ref.mimeType};base64,${ref.base64}`
213
+ }));
214
+ const body = {
215
+ model: config.model,
216
+ prompt: request.prompt,
217
+ n: resolved.n,
218
+ response_format: 'b64_json',
219
+ image: images
220
+ };
221
+ if (resolved.aspectRatio !== undefined) {
222
+ body.aspect_ratio = resolved.aspectRatio;
223
+ }
224
+ if (resolved.resolution !== undefined) {
225
+ body.resolution = resolved.resolution;
226
+ }
227
+ if (resolved.otherParams !== undefined) {
228
+ Object.assign(body, resolved.otherParams);
229
+ }
230
+ /* c8 ignore next 1 - optional logger */
231
+ logger === null || logger === void 0 ? void 0 : logger.info(`xAI image edit: model=${config.model}, n=${resolved.n}, refs=${refs.length}`);
232
+ return (0, http_1.fetchJson)(`${config.baseUrl}/images/edits`, (0, endpoint_1.bearerAuthHeader)(config.apiKey), body, logger, signal);
233
+ }
234
+ /**
235
+ * Normalizes an xAI images API response (OpenAI-shaped) into the provider-neutral
236
+ * generated-image result.
237
+ *
238
+ * @remarks
239
+ * Shared by the generations path and the edits path. These were two independent
240
+ * copies 160 lines apart — identical but for the receiver name — so the
241
+ * `defaultOutputMimeType` fallback and the error prefix each existed twice, and a
242
+ * fix to one would silently have missed the other.
243
+ * @internal
244
+ */
245
+ function normalizeXaiImageResponse(json, capability) {
246
+ return openAiImageResponse
247
+ .validate(json)
248
+ .withErrorFormat((msg) => `xAI images API response: ${msg}`)
249
+ .onSuccess((response) => (0, ts_utils_1.succeed)({
250
+ images: response.data.map((item) => {
251
+ var _a;
252
+ return ({
253
+ mimeType: (_a = capability.defaultOutputMimeType) !== null && _a !== void 0 ? _a : 'image/jpeg',
254
+ base64: item.b64_json
255
+ });
256
+ })
257
+ }));
258
+ }
259
+ /** Calls xAI /images/generations; uses aspect_ratio instead of size. @internal */
260
+ async function callXaiImageGeneration(config, request, capability, resolved, logger, signal) {
261
+ const headers = (0, endpoint_1.bearerAuthHeader)(config.apiKey);
262
+ const body = {
263
+ model: config.model,
264
+ prompt: request.prompt,
265
+ n: resolved.n,
266
+ response_format: 'b64_json'
267
+ };
268
+ if (resolved.aspectRatio !== undefined) {
269
+ body.aspect_ratio = resolved.aspectRatio;
270
+ }
271
+ if (resolved.resolution !== undefined) {
272
+ body.resolution = resolved.resolution;
273
+ }
274
+ if (resolved.otherParams !== undefined) {
275
+ Object.assign(body, resolved.otherParams);
276
+ }
277
+ /* c8 ignore next 1 - optional logger */
278
+ logger === null || logger === void 0 ? void 0 : logger.info(`xAI image generation: model=${config.model}, n=${resolved.n}`);
279
+ const fetched = await (0, http_1.fetchJson)(`${config.baseUrl}/images/generations`, headers, body, logger, signal);
280
+ return fetched.onSuccess((json) => normalizeXaiImageResponse(json, capability));
281
+ }
282
+ /**
283
+ * Gemini `finishReason` values that indicate a normal terminal completion rather
284
+ * than a refusal. `STOP` is set on every successful generation (and on completions
285
+ * that return a text part instead of an image); `MAX_TOKENS` is a benign truncation.
286
+ * A candidate carrying only one of these is NOT a decline — treating it as one would
287
+ * mislabel an ordinary no-image outcome as a policy refusal. @internal
288
+ */
289
+ const benignGeminiImageFinishReasons = new Set(['STOP', 'MAX_TOKENS']);
290
+ /** Calls Gemini :generateContent for image output; accepts ref images as inlineData. @internal */
291
+ async function callGeminiImageOutGeneration(config, request, resolved, logger, signal) {
292
+ var _a;
293
+ const url = `${config.baseUrl}/models/${config.model}:generateContent`;
294
+ const refs = (_a = request.referenceImages) !== null && _a !== void 0 ? _a : [];
295
+ const parts = [{ text: request.prompt }];
296
+ for (const ref of refs) {
297
+ parts.push({ inlineData: { mimeType: ref.mimeType, data: ref.base64 } });
298
+ }
299
+ const generationConfig = {};
300
+ if (resolved.geminiAspectRatio !== undefined) {
301
+ generationConfig.imageConfig = { aspectRatio: resolved.geminiAspectRatio };
302
+ }
303
+ if (resolved.otherParams !== undefined) {
304
+ Object.assign(generationConfig, resolved.otherParams);
305
+ }
306
+ const body = { contents: [{ role: 'user', parts }] };
307
+ if (Object.keys(generationConfig).length > 0) {
308
+ body.generationConfig = generationConfig;
309
+ }
310
+ const headers = (0, endpoint_1.geminiAuthHeader)(config.apiKey);
311
+ /* c8 ignore next 1 - optional logger */
312
+ logger === null || logger === void 0 ? void 0 : logger.info(`Gemini image-out: model=${config.model}, refs=${refs.length}`);
313
+ return (await (0, http_1.fetchJson)(url, headers, body, logger, signal)).onSuccess((json) => geminiImageOutResponse
314
+ .validate(json)
315
+ .withErrorFormat((msg) => `Gemini image API response: ${msg}`)
316
+ .onSuccess((response) => {
317
+ var _a, _b;
318
+ const images = [];
319
+ for (const candidate of response.candidates) {
320
+ for (const part of (_b = (_a = candidate.content) === null || _a === void 0 ? void 0 : _a.parts) !== null && _b !== void 0 ? _b : []) {
321
+ if (part.inlineData) {
322
+ images.push({
323
+ mimeType: part.inlineData.mimeType,
324
+ base64: part.inlineData.data
325
+ });
326
+ }
327
+ }
328
+ }
329
+ if (images.length === 0) {
330
+ // A candidate with no image parts is a *decline* only when it carries a
331
+ // refusal-shaped finishReason — i.e. present and not a benign terminal reason
332
+ // (`STOP`/`MAX_TOKENS`). A normal completion that emitted text-instead-of-image
333
+ // carries `finishReason: 'STOP'` and must fall through to the no-image message.
334
+ const declined = response.candidates.find((candidate) => candidate.finishReason !== undefined &&
335
+ !benignGeminiImageFinishReasons.has(candidate.finishReason));
336
+ if ((declined === null || declined === void 0 ? void 0 : declined.finishReason) !== undefined) {
337
+ // Truthiness (not `!== undefined`) so an empty-string finishMessage is treated
338
+ // as "no message" and produces no dangling ` — ` separator.
339
+ const suffix = declined.finishMessage ? ` — ${declined.finishMessage}` : '';
340
+ return (0, ts_utils_1.fail)(`Gemini image generation declined: ${declined.finishReason}${suffix}`);
341
+ }
342
+ return (0, ts_utils_1.fail)('Gemini image API response: no image parts in response');
343
+ }
344
+ return (0, ts_utils_1.succeed)({ images });
345
+ }));
346
+ }
347
+ // ============================================================================
348
+ // Image generation — dispatcher
349
+ // ============================================================================
350
+ /**
351
+ * Calls the appropriate image-generation API for a given provider. Routes by the
352
+ * `format` field of the resolved {@link IAiImageModelCapability}:
353
+ * `'openai-images'`, `'xai-images'`, `'xai-images-edits'`, or
354
+ * `'gemini-image-out'`. Rejects up front if `referenceImages` is set but the
355
+ * capability does not declare `acceptsImageReferenceInput`.
356
+ * @param params - Request parameters including descriptor, API key, and prompt
357
+ * @public
358
+ */
359
+ async function callProviderImageGeneration(params) {
360
+ var _a, _b, _c;
361
+ const { descriptor, apiKey, params: request, modelOverride, logger, signal, endpoint } = params;
362
+ if (!(0, registry_1.supportsImageGeneration)(descriptor)) {
363
+ return (0, ts_utils_1.fail)(`provider "${descriptor.id}" does not support image generation`);
364
+ }
365
+ const baseUrlResult = (0, endpoint_1.resolveEffectiveBaseUrl)(descriptor, endpoint);
366
+ if (baseUrlResult.isFailure()) {
367
+ return (0, ts_utils_1.fail)(baseUrlResult.message);
368
+ }
369
+ const modelResult = (0, model_1.resolveProviderModel)(descriptor, modelOverride, 'image');
370
+ if (modelResult.isFailure()) {
371
+ return (0, ts_utils_1.fail)(modelResult.message);
372
+ }
373
+ const model = modelResult.value;
374
+ const capability = (0, registry_1.resolveImageCapability)(descriptor, model);
375
+ if (capability === undefined) {
376
+ return (0, ts_utils_1.fail)(`provider "${descriptor.id}" does not support image generation for model "${model}"`);
377
+ }
378
+ if (((_b = (_a = request.referenceImages) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 && !capability.acceptsImageReferenceInput) {
379
+ return (0, ts_utils_1.fail)(`model "${model}" does not support reference images`);
380
+ }
381
+ const resolved = (0, imageOptionsResolver_1.resolveImageOptions)(model, capability, request.options);
382
+ const validationResult = (0, imageOptionsResolver_1.validateResolvedOptions)(model, capability, resolved);
383
+ if (validationResult.isFailure()) {
384
+ return (0, ts_utils_1.fail)(validationResult.message);
385
+ }
386
+ const config = {
387
+ baseUrl: baseUrlResult.value,
388
+ apiKey,
389
+ model
390
+ };
391
+ /* c8 ignore next 6 - optional logger diagnostic output */
392
+ if (logger) {
393
+ logger.info(`AI image generation: provider=${descriptor.id}, format=${capability.format}, ` +
394
+ `model=${config.model}`);
395
+ }
396
+ switch (capability.format) {
397
+ case 'openai-images':
398
+ return callOpenAiImageGeneration(config, request, capability, resolved, logger, signal);
399
+ case 'xai-images':
400
+ return callXaiImageGeneration(config, request, capability, resolved, logger, signal);
401
+ case 'xai-images-edits': {
402
+ const refs = (_c = request.referenceImages) !== null && _c !== void 0 ? _c : [];
403
+ if (refs.length > 0) {
404
+ const editsResult = await callXaiImagesEdits(config, request, resolved, logger, signal);
405
+ return editsResult.onSuccess((json) => normalizeXaiImageResponse(json, capability));
406
+ }
407
+ return callXaiImageGeneration(config, request, capability, resolved, logger, signal);
408
+ }
409
+ case 'gemini-image-out':
410
+ return callGeminiImageOutGeneration(config, request, resolved, logger, signal);
411
+ /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */
412
+ default: {
413
+ const _exhaustive = capability.format;
414
+ return (0, ts_utils_1.fail)(`unsupported image API format: ${String(_exhaustive)}`);
415
+ }
416
+ }
417
+ }
418
+ // ============================================================================
419
+ // Proxied image generation
420
+ // ============================================================================
421
+ /**
422
+ * Calls the image-generation endpoint on a proxy server instead of calling
423
+ * the provider API directly from the browser.
424
+ * Endpoint: `POST ${proxyUrl}/api/ai/image-generation`. Request body:
425
+ * `{providerId, apiKey, params, modelOverride?}`. The proxy handles descriptor
426
+ * lookup, model resolution, provider dispatch, and response normalization
427
+ * (including repackaging `referenceImages` for the upstream wire format).
428
+ * Error body `{error: string}` is surfaced as `proxy: ${error}`.
429
+ * @param proxyUrl - Base URL of the proxy server
430
+ * @param params - Same parameters as {@link callProviderImageGeneration}
431
+ * @public
432
+ */
433
+ async function callProxiedImageGeneration(proxyUrl, params) {
434
+ const { descriptor, apiKey, params: request, modelOverride, logger, signal } = params;
435
+ const body = {
436
+ providerId: descriptor.id,
437
+ apiKey,
438
+ params: request
439
+ };
440
+ if (modelOverride !== undefined) {
441
+ body.modelOverride = modelOverride;
442
+ }
443
+ /* c8 ignore next 1 - optional logger */
444
+ logger === null || logger === void 0 ? void 0 : logger.info(`AI image proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);
445
+ const url = `${proxyUrl}/api/ai/image-generation`;
446
+ const jsonResult = await (0, http_1.fetchJson)(url, {}, body, logger, signal);
447
+ if (jsonResult.isFailure()) {
448
+ return (0, ts_utils_1.fail)(jsonResult.message);
449
+ }
450
+ const response = jsonResult.value;
451
+ if (typeof response.error === 'string') {
452
+ return (0, ts_utils_1.fail)(`proxy: ${response.error}`);
453
+ }
454
+ return proxiedImageGenerationResponse
455
+ .validate(response)
456
+ .withErrorFormat((msg) => `proxy returned invalid response: ${msg}`);
457
+ }
458
+ //# sourceMappingURL=imageGenerationClient.js.map