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

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,116 @@
1
+ // Copyright (c) 2026 Erik Fortune
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software, and to permit persons to whom the Software is
8
+ // furnished to do so, subject to the following conditions:
9
+ //
10
+ // The above copyright notice and this permission notice shall be included in all
11
+ // copies or substantial portions of the Software.
12
+ //
13
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ // SOFTWARE.
20
+ /**
21
+ * Streaming chat completion client. Public façade over the per-format
22
+ * adapters under `streamingAdapters/`: provider dispatch and pre-flight
23
+ * validation live here; format-specific request/translation logic and the
24
+ * typed event-payload validators live with each adapter.
25
+ *
26
+ * @packageDocumentation
27
+ */
28
+ import { fail } from '@fgv/ts-utils';
29
+ import { resolveEffectiveBaseUrl } from './endpoint';
30
+ import { resolveModel } from './model';
31
+ import { callAnthropicStream } from './streamingAdapters/anthropic';
32
+ import { callGeminiStream } from './streamingAdapters/gemini';
33
+ import { callOpenAiChatStream } from './streamingAdapters/openaiChat';
34
+ import { callOpenAiResponsesStream } from './streamingAdapters/openaiResponses';
35
+ import { checkTemperatureConflict, mergeThinkingConfig, providerDiscriminatorForId } from './thinkingOptionsResolver';
36
+ export { callProxiedCompletionStream } from './streamingAdapters/proxy';
37
+ /**
38
+ * Calls the appropriate streaming chat completion API for a given provider.
39
+ *
40
+ * @remarks
41
+ * Pre-flight rejection: when `descriptor.streamingCorsRestricted === true`
42
+ * and the call isn't being routed through a proxy, this returns
43
+ * `Result.fail` before fetch is invoked. Callers should route through
44
+ * {@link AiAssist.callProxiedCompletionStream} or surface the failure to the user.
45
+ *
46
+ * Connection-time failures (auth, network, non-2xx) surface as the outer
47
+ * `Result.fail`. Once iteration begins, errors mid-stream surface as a
48
+ * terminal error event ({@link AiAssist.IAiStreamError}) followed by the iterable
49
+ * ending. The final successful event is {@link AiAssist.IAiStreamDone}.
50
+ *
51
+ * @param params - Request parameters including descriptor, API key, prompt, and optional tools
52
+ * @returns A streaming iterable of unified events, or a Result.fail
53
+ * @public
54
+ */
55
+ export async function callProviderCompletionStream(params) {
56
+ var _a;
57
+ const { descriptor, apiKey, prompt, messagesBefore, temperature, modelOverride, logger, tools, signal, endpoint, thinking } = params;
58
+ const baseUrlResult = resolveEffectiveBaseUrl(descriptor, endpoint);
59
+ if (baseUrlResult.isFailure()) {
60
+ return fail(baseUrlResult.message);
61
+ }
62
+ if (descriptor.streamingCorsRestricted) {
63
+ return fail(`provider "${descriptor.id}" requires a proxy for streaming; none is configured`);
64
+ }
65
+ if (prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {
66
+ return fail(`provider "${descriptor.id}" does not accept image input`);
67
+ }
68
+ const hasTools = tools !== undefined && tools.length > 0;
69
+ const discriminator = providerDiscriminatorForId(descriptor.id);
70
+ const hasThinkingConfig = discriminator !== undefined &&
71
+ ((thinking === null || thinking === void 0 ? void 0 : thinking.effort) !== undefined ||
72
+ ((_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);
73
+ const modelContext = hasThinkingConfig ? 'thinking' : hasTools ? 'tools' : undefined;
74
+ const model = resolveModel(modelOverride !== null && modelOverride !== void 0 ? modelOverride : descriptor.defaultModel, modelContext);
75
+ if (model.length === 0) {
76
+ return fail(`provider "${descriptor.id}": no model resolved; pass modelOverride or set descriptor.defaultModel`);
77
+ }
78
+ let resolvedThinking;
79
+ if (thinking !== undefined) {
80
+ if (discriminator !== undefined) {
81
+ const mergeResult = mergeThinkingConfig(thinking, model, discriminator);
82
+ /* c8 ignore next 3 - mergeThinkingConfig always succeeds; defensive guard */
83
+ if (mergeResult.isFailure()) {
84
+ return fail(mergeResult.message);
85
+ }
86
+ resolvedThinking = mergeResult.value;
87
+ const conflictResult = checkTemperatureConflict(resolvedThinking, discriminator, temperature);
88
+ if (conflictResult.isFailure()) {
89
+ return fail(conflictResult.message);
90
+ }
91
+ }
92
+ }
93
+ const effectiveTemperature = temperature !== null && temperature !== void 0 ? temperature : 0.7;
94
+ const config = {
95
+ baseUrl: baseUrlResult.value,
96
+ apiKey,
97
+ model
98
+ };
99
+ switch (descriptor.apiFormat) {
100
+ case 'openai':
101
+ if (hasTools) {
102
+ return callOpenAiResponsesStream(config, prompt, tools, messagesBefore, effectiveTemperature, logger, signal, resolvedThinking);
103
+ }
104
+ return callOpenAiChatStream(config, prompt, messagesBefore, effectiveTemperature, logger, signal, resolvedThinking);
105
+ case 'anthropic':
106
+ return callAnthropicStream(config, prompt, messagesBefore, effectiveTemperature, tools, logger, signal, resolvedThinking);
107
+ case 'gemini':
108
+ return callGeminiStream(config, prompt, messagesBefore, effectiveTemperature, tools, logger, signal, resolvedThinking);
109
+ /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */
110
+ default: {
111
+ const _exhaustive = descriptor.apiFormat;
112
+ return fail(`unsupported API format: ${String(_exhaustive)}`);
113
+ }
114
+ }
115
+ }
116
+ //# sourceMappingURL=streamingClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamingClient.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/streamingClient.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 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"]}
@@ -0,0 +1,265 @@
1
+ // Copyright (c) 2026 Erik Fortune
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software, and to permit persons to whom the Software is
8
+ // furnished to do so, subject to the following conditions:
9
+ //
10
+ // The above copyright notice and this permission notice shall be included in all
11
+ // copies or substantial portions of the Software.
12
+ //
13
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ // SOFTWARE.
20
+ import { fail, succeed } from '@fgv/ts-utils';
21
+ /**
22
+ * Maps an AiProviderId (registry key) to the coarse family discriminator used
23
+ * in IThinkingProviderConfig. Returns undefined for providers without thinking support.
24
+ * @internal
25
+ */
26
+ export function providerDiscriminatorForId(providerId) {
27
+ switch (providerId) {
28
+ case 'anthropic':
29
+ return 'anthropic';
30
+ case 'openai':
31
+ return 'openai';
32
+ case 'google-gemini':
33
+ return 'google';
34
+ case 'xai-grok':
35
+ return 'xai';
36
+ default:
37
+ return undefined;
38
+ }
39
+ }
40
+ // ============================================================================
41
+ // Common-subset mapping
42
+ // ============================================================================
43
+ /**
44
+ * Maps generic effort to Anthropic wire effort. @internal
45
+ */
46
+ function genericEffortToAnthropic(effort) {
47
+ return effort; // 1:1 mapping for the common subset
48
+ }
49
+ /**
50
+ * Maps generic effort to OpenAI wire effort. @internal
51
+ */
52
+ function genericEffortToOpenAi(effort) {
53
+ return effort; // 1:1 mapping for the common subset
54
+ }
55
+ /**
56
+ * Maps generic effort to Gemini thinkingBudget. @internal
57
+ */
58
+ function genericEffortToGemini(effort) {
59
+ switch (effort) {
60
+ case 'low':
61
+ return 1024;
62
+ case 'medium':
63
+ return 4096;
64
+ case 'high':
65
+ return 8192;
66
+ }
67
+ }
68
+ /**
69
+ * Maps generic effort to xAI reasoning_effort. @internal
70
+ */
71
+ function genericEffortToXai(effort) {
72
+ return effort; // 1:1 mapping for the common subset
73
+ }
74
+ // ============================================================================
75
+ // Block applicability
76
+ // ============================================================================
77
+ /**
78
+ * Returns true when a provider config block applies to the given resolved model
79
+ * and provider discriminator.
80
+ *
81
+ * Applicability rules:
82
+ * - provider must match the coarse discriminator
83
+ * - if models array is present, resolved model must match (exact or base-name prefix)
84
+ * - if models array is absent, the block is provider-generic (applies to all)
85
+ *
86
+ * Prefix matching supports versioned IDs: `'claude-sonnet-4-5'` matches resolved
87
+ * `'claude-sonnet-4-5-20250929'`. An entry matches when it equals the resolved model
88
+ * or when the resolved model starts with the entry followed by a `-`.
89
+ *
90
+ * 'other' blocks require models to be present (enforced by the type).
91
+ * @internal
92
+ */
93
+ function modelNameMatches(resolvedModel, name) {
94
+ return resolvedModel === name || resolvedModel.startsWith(`${name}-`);
95
+ }
96
+ function blockApplies(block, resolvedModel, discriminator) {
97
+ if (block.provider !== discriminator && block.provider !== 'other') {
98
+ return false;
99
+ }
100
+ if (block.provider === 'other') {
101
+ return block.models.some((name) => modelNameMatches(resolvedModel, name));
102
+ }
103
+ if (block.models !== undefined) {
104
+ return block.models.some((name) => modelNameMatches(resolvedModel, name));
105
+ }
106
+ return true; // provider-generic block
107
+ }
108
+ /**
109
+ * Returns true when a block is model-specific (has a models array).
110
+ * Used to partition blocks into merge tiers.
111
+ * @internal
112
+ */
113
+ function isModelSpecific(block) {
114
+ if (block.provider === 'other') {
115
+ return true; // other blocks always require models
116
+ }
117
+ return block.models !== undefined;
118
+ }
119
+ // ============================================================================
120
+ // Merge function
121
+ // ============================================================================
122
+ /**
123
+ * Resolves the effective thinking wire parameters for a specific resolved model
124
+ * by merging all applicable config blocks in precedence order.
125
+ *
126
+ * Precedence (later tier wins; within tier, later declaration wins):
127
+ * 1. Generic effort (top-level IThinkingConfig.effort) → common-subset mapping
128
+ * 2. Provider-generic blocks (matching provider, no models filter)
129
+ * 3. Model-specific blocks (matching provider + models array includes resolved model)
130
+ * 4. Other blocks (provider: 'other', models includes resolved model) — same tier as 3
131
+ *
132
+ * Blocks whose provider does not match are silently skipped.
133
+ *
134
+ * Note: when the resolved OpenAI effort is `'none'`, reasoning is disabled and
135
+ * temperature is accepted; see {@link IOpenAiThinkingConfig.effort} for the full
136
+ * hybrid-mode semantics.
137
+ *
138
+ * @param config - The caller's IThinkingConfig
139
+ * @param resolvedModel - The concrete model string after registry resolution
140
+ * @param discriminator - Coarse provider family
141
+ * @returns Merged effective config for wire encoding
142
+ * @internal
143
+ */
144
+ export function mergeThinkingConfig(config, resolvedModel, discriminator) {
145
+ let resolved = {};
146
+ // Tier 1: generic effort → common-subset mapping
147
+ if (config.effort !== undefined) {
148
+ switch (discriminator) {
149
+ case 'anthropic':
150
+ resolved = Object.assign(Object.assign({}, resolved), { anthropicEffort: genericEffortToAnthropic(config.effort) });
151
+ break;
152
+ case 'openai':
153
+ resolved = Object.assign(Object.assign({}, resolved), { openAiEffort: genericEffortToOpenAi(config.effort) });
154
+ break;
155
+ case 'google':
156
+ resolved = Object.assign(Object.assign({}, resolved), { geminiThinkingBudget: genericEffortToGemini(config.effort) });
157
+ break;
158
+ case 'xai':
159
+ resolved = Object.assign(Object.assign({}, resolved), { xaiEffort: genericEffortToXai(config.effort) });
160
+ break;
161
+ }
162
+ }
163
+ if (!config.providers) {
164
+ return succeed(resolved);
165
+ }
166
+ // Partition into tiers 2 and 3+4
167
+ const applicableBlocks = config.providers.filter((b) => blockApplies(b, resolvedModel, discriminator));
168
+ const genericBlocks = applicableBlocks.filter((b) => !isModelSpecific(b));
169
+ const specificBlocks = applicableBlocks.filter((b) => isModelSpecific(b));
170
+ // Tier 2: provider-generic blocks (declaration order; later wins)
171
+ for (const block of genericBlocks) {
172
+ resolved = applyBlock(resolved, block, discriminator);
173
+ }
174
+ // Tier 3+4: model-specific + other blocks (declaration order; later wins)
175
+ for (const block of specificBlocks) {
176
+ resolved = applyBlock(resolved, block, discriminator);
177
+ }
178
+ return succeed(resolved);
179
+ }
180
+ /**
181
+ * Applies a single config block to the accumulated resolved config.
182
+ * @internal
183
+ */
184
+ function applyBlock(current, block, discriminator) {
185
+ if (block.provider === 'other') {
186
+ const merged = current.otherParams !== undefined ? Object.assign(Object.assign({}, current.otherParams), block.config) : block.config;
187
+ return Object.assign(Object.assign({}, current), { otherParams: merged });
188
+ }
189
+ switch (discriminator) {
190
+ case 'anthropic':
191
+ if (block.provider === 'anthropic') {
192
+ if (block.config.effort !== undefined) {
193
+ return Object.assign(Object.assign({}, current), { anthropicEffort: block.config.effort });
194
+ }
195
+ }
196
+ break;
197
+ case 'openai':
198
+ if (block.provider === 'openai') {
199
+ if (block.config.effort !== undefined) {
200
+ return Object.assign(Object.assign({}, current), { openAiEffort: block.config.effort });
201
+ }
202
+ }
203
+ break;
204
+ case 'google':
205
+ if (block.provider === 'google') {
206
+ const updated = Object.assign({}, current);
207
+ if (block.config.thinkingBudget !== undefined) {
208
+ return Object.assign(Object.assign({}, updated), { geminiThinkingBudget: block.config.thinkingBudget });
209
+ }
210
+ return updated;
211
+ }
212
+ /* c8 ignore next - blockApplies guarantees provider match; unreachable for google */
213
+ break;
214
+ case 'xai':
215
+ if (block.provider === 'xai') {
216
+ if (block.config.effort !== undefined) {
217
+ return Object.assign(Object.assign({}, current), { xaiEffort: block.config.effort });
218
+ }
219
+ }
220
+ break;
221
+ }
222
+ return current;
223
+ }
224
+ // ============================================================================
225
+ // Temperature conflict check
226
+ // ============================================================================
227
+ /**
228
+ * Returns a Result.fail if temperature conflicts with thinking mode for the
229
+ * given provider, otherwise succeed(undefined).
230
+ *
231
+ * Per D4: temperature + thinking = Result.fail for Anthropic, OpenAI (when
232
+ * effective effort is non-null and non-'none'), and xAI (conservative default
233
+ * pending live verification). Gemini accepts temperature alongside thinking.
234
+ *
235
+ * @internal
236
+ */
237
+ export function checkTemperatureConflict(resolved, discriminator, temperature) {
238
+ if (temperature === undefined) {
239
+ return succeed(undefined);
240
+ }
241
+ switch (discriminator) {
242
+ case 'anthropic':
243
+ if (resolved.anthropicEffort !== undefined) {
244
+ return fail('thinking mode is not compatible with temperature on provider anthropic: remove temperature or disable thinking');
245
+ }
246
+ break;
247
+ case 'openai':
248
+ // 'none' disables reasoning; temperature is accepted in that case
249
+ if (resolved.openAiEffort !== undefined && resolved.openAiEffort !== 'none') {
250
+ return fail('thinking mode is not compatible with temperature on provider openai: remove temperature or disable thinking');
251
+ }
252
+ break;
253
+ case 'xai':
254
+ // Conservative default: fail if xAI effort is active (per D8 — live verification pending)
255
+ if (resolved.xaiEffort !== undefined && resolved.xaiEffort !== 'none') {
256
+ return fail('thinking mode is not compatible with temperature on provider xai: remove temperature or disable thinking');
257
+ }
258
+ break;
259
+ case 'google':
260
+ // Gemini accepts temperature alongside thinkingConfig — no conflict
261
+ break;
262
+ }
263
+ return succeed(undefined);
264
+ }
265
+ //# sourceMappingURL=thinkingOptionsResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thinkingOptionsResolver.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/thinkingOptionsResolver.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 * Merge logic and runtime validation for thinking/reasoning options.\n * @packageDocumentation\n */\n\nimport { type JsonObject } from '@fgv/ts-json-base';\nimport { fail, Result, succeed } from '@fgv/ts-utils';\n\nimport type {\n IThinkingConfig,\n IThinkingProviderConfig,\n IAnthropicThinkingConfig,\n IOpenAiThinkingConfig,\n IXAiThinkingConfig\n} from './model';\n\n// ============================================================================\n// Provider discriminator\n// ============================================================================\n\n/**\n * Coarse provider family used to discriminate thinking config blocks.\n * Maps from AiProviderId to the IThinkingProviderConfig `provider` discriminator.\n * @internal\n */\nexport type ThinkingProviderDiscriminator = 'anthropic' | 'openai' | 'google' | 'xai';\n\n/**\n * Maps an AiProviderId (registry key) to the coarse family discriminator used\n * in IThinkingProviderConfig. Returns undefined for providers without thinking support.\n * @internal\n */\nexport function providerDiscriminatorForId(providerId: string): ThinkingProviderDiscriminator | undefined {\n switch (providerId) {\n case 'anthropic':\n return 'anthropic';\n case 'openai':\n return 'openai';\n case 'google-gemini':\n return 'google';\n case 'xai-grok':\n return 'xai';\n default:\n return undefined;\n }\n}\n\n// ============================================================================\n// Resolved wire shape\n// ============================================================================\n\n/**\n * Resolved thinking wire parameters for a specific provider, after merging\n * all applicable config blocks. Ready for provider-specific wire encoding.\n * @internal\n */\nexport interface IResolvedThinkingConfig {\n /** Anthropic: output_config.effort value */\n readonly anthropicEffort?: IAnthropicThinkingConfig['effort'];\n /** OpenAI Chat: reasoning_effort value; OpenAI Responses: reasoning.effort */\n readonly openAiEffort?: IOpenAiThinkingConfig['effort'];\n /** Gemini: generationConfig.thinkingConfig.thinkingBudget */\n readonly geminiThinkingBudget?: number;\n /** xAI: reasoning_effort value (omit for grok-4) */\n readonly xaiEffort?: IXAiThinkingConfig['effort'];\n /** Other/passthrough: merged verbatim into wire request */\n readonly otherParams?: JsonObject;\n}\n\n// ============================================================================\n// Common-subset mapping\n// ============================================================================\n\n/**\n * Maps generic effort to Anthropic wire effort. @internal\n */\nfunction genericEffortToAnthropic(effort: 'low' | 'medium' | 'high'): IAnthropicThinkingConfig['effort'] {\n return effort; // 1:1 mapping for the common subset\n}\n\n/**\n * Maps generic effort to OpenAI wire effort. @internal\n */\nfunction genericEffortToOpenAi(effort: 'low' | 'medium' | 'high'): IOpenAiThinkingConfig['effort'] {\n return effort; // 1:1 mapping for the common subset\n}\n\n/**\n * Maps generic effort to Gemini thinkingBudget. @internal\n */\nfunction genericEffortToGemini(effort: 'low' | 'medium' | 'high'): number {\n switch (effort) {\n case 'low':\n return 1024;\n case 'medium':\n return 4096;\n case 'high':\n return 8192;\n }\n}\n\n/**\n * Maps generic effort to xAI reasoning_effort. @internal\n */\nfunction genericEffortToXai(effort: 'low' | 'medium' | 'high'): IXAiThinkingConfig['effort'] {\n return effort; // 1:1 mapping for the common subset\n}\n\n// ============================================================================\n// Block applicability\n// ============================================================================\n\n/**\n * Returns true when a provider config block applies to the given resolved model\n * and provider discriminator.\n *\n * Applicability rules:\n * - provider must match the coarse discriminator\n * - if models array is present, resolved model must match (exact or base-name prefix)\n * - if models array is absent, the block is provider-generic (applies to all)\n *\n * Prefix matching supports versioned IDs: `'claude-sonnet-4-5'` matches resolved\n * `'claude-sonnet-4-5-20250929'`. An entry matches when it equals the resolved model\n * or when the resolved model starts with the entry followed by a `-`.\n *\n * 'other' blocks require models to be present (enforced by the type).\n * @internal\n */\nfunction modelNameMatches(resolvedModel: string, name: string): boolean {\n return resolvedModel === name || resolvedModel.startsWith(`${name}-`);\n}\n\nfunction blockApplies(\n block: IThinkingProviderConfig,\n resolvedModel: string,\n discriminator: ThinkingProviderDiscriminator\n): boolean {\n if (block.provider !== discriminator && block.provider !== 'other') {\n return false;\n }\n if (block.provider === 'other') {\n return block.models.some((name) => modelNameMatches(resolvedModel, name));\n }\n if (block.models !== undefined) {\n return (block.models as ReadonlyArray<string>).some((name) => modelNameMatches(resolvedModel, name));\n }\n return true; // provider-generic block\n}\n\n/**\n * Returns true when a block is model-specific (has a models array).\n * Used to partition blocks into merge tiers.\n * @internal\n */\nfunction isModelSpecific(block: IThinkingProviderConfig): boolean {\n if (block.provider === 'other') {\n return true; // other blocks always require models\n }\n return block.models !== undefined;\n}\n\n// ============================================================================\n// Merge function\n// ============================================================================\n\n/**\n * Resolves the effective thinking wire parameters for a specific resolved model\n * by merging all applicable config blocks in precedence order.\n *\n * Precedence (later tier wins; within tier, later declaration wins):\n * 1. Generic effort (top-level IThinkingConfig.effort) → common-subset mapping\n * 2. Provider-generic blocks (matching provider, no models filter)\n * 3. Model-specific blocks (matching provider + models array includes resolved model)\n * 4. Other blocks (provider: 'other', models includes resolved model) — same tier as 3\n *\n * Blocks whose provider does not match are silently skipped.\n *\n * Note: when the resolved OpenAI effort is `'none'`, reasoning is disabled and\n * temperature is accepted; see {@link IOpenAiThinkingConfig.effort} for the full\n * hybrid-mode semantics.\n *\n * @param config - The caller's IThinkingConfig\n * @param resolvedModel - The concrete model string after registry resolution\n * @param discriminator - Coarse provider family\n * @returns Merged effective config for wire encoding\n * @internal\n */\nexport function mergeThinkingConfig(\n config: IThinkingConfig,\n resolvedModel: string,\n discriminator: ThinkingProviderDiscriminator\n): Result<IResolvedThinkingConfig> {\n let resolved: IResolvedThinkingConfig = {};\n\n // Tier 1: generic effort → common-subset mapping\n if (config.effort !== undefined) {\n switch (discriminator) {\n case 'anthropic':\n resolved = { ...resolved, anthropicEffort: genericEffortToAnthropic(config.effort) };\n break;\n case 'openai':\n resolved = { ...resolved, openAiEffort: genericEffortToOpenAi(config.effort) };\n break;\n case 'google':\n resolved = { ...resolved, geminiThinkingBudget: genericEffortToGemini(config.effort) };\n break;\n case 'xai':\n resolved = { ...resolved, xaiEffort: genericEffortToXai(config.effort) };\n break;\n }\n }\n\n if (!config.providers) {\n return succeed(resolved);\n }\n\n // Partition into tiers 2 and 3+4\n const applicableBlocks = config.providers.filter((b) => blockApplies(b, resolvedModel, discriminator));\n const genericBlocks = applicableBlocks.filter((b) => !isModelSpecific(b));\n const specificBlocks = applicableBlocks.filter((b) => isModelSpecific(b));\n\n // Tier 2: provider-generic blocks (declaration order; later wins)\n for (const block of genericBlocks) {\n resolved = applyBlock(resolved, block, discriminator);\n }\n\n // Tier 3+4: model-specific + other blocks (declaration order; later wins)\n for (const block of specificBlocks) {\n resolved = applyBlock(resolved, block, discriminator);\n }\n\n return succeed(resolved);\n}\n\n/**\n * Applies a single config block to the accumulated resolved config.\n * @internal\n */\nfunction applyBlock(\n current: IResolvedThinkingConfig,\n block: IThinkingProviderConfig,\n discriminator: ThinkingProviderDiscriminator\n): IResolvedThinkingConfig {\n if (block.provider === 'other') {\n const merged =\n current.otherParams !== undefined ? { ...current.otherParams, ...block.config } : block.config;\n return { ...current, otherParams: merged };\n }\n\n switch (discriminator) {\n case 'anthropic':\n if (block.provider === 'anthropic') {\n if (block.config.effort !== undefined) {\n return { ...current, anthropicEffort: block.config.effort };\n }\n }\n break;\n case 'openai':\n if (block.provider === 'openai') {\n if (block.config.effort !== undefined) {\n return { ...current, openAiEffort: block.config.effort };\n }\n }\n break;\n case 'google':\n if (block.provider === 'google') {\n const updated: IResolvedThinkingConfig = { ...current };\n if (block.config.thinkingBudget !== undefined) {\n return { ...updated, geminiThinkingBudget: block.config.thinkingBudget };\n }\n return updated;\n }\n /* c8 ignore next - blockApplies guarantees provider match; unreachable for google */\n break;\n case 'xai':\n if (block.provider === 'xai') {\n if (block.config.effort !== undefined) {\n return { ...current, xaiEffort: block.config.effort };\n }\n }\n break;\n }\n return current;\n}\n\n// ============================================================================\n// Temperature conflict check\n// ============================================================================\n\n/**\n * Returns a Result.fail if temperature conflicts with thinking mode for the\n * given provider, otherwise succeed(undefined).\n *\n * Per D4: temperature + thinking = Result.fail for Anthropic, OpenAI (when\n * effective effort is non-null and non-'none'), and xAI (conservative default\n * pending live verification). Gemini accepts temperature alongside thinking.\n *\n * @internal\n */\nexport function checkTemperatureConflict(\n resolved: IResolvedThinkingConfig,\n discriminator: ThinkingProviderDiscriminator,\n temperature: number | undefined\n): Result<undefined> {\n if (temperature === undefined) {\n return succeed(undefined);\n }\n\n switch (discriminator) {\n case 'anthropic':\n if (resolved.anthropicEffort !== undefined) {\n return fail(\n 'thinking mode is not compatible with temperature on provider anthropic: remove temperature or disable thinking'\n );\n }\n break;\n case 'openai':\n // 'none' disables reasoning; temperature is accepted in that case\n if (resolved.openAiEffort !== undefined && resolved.openAiEffort !== 'none') {\n return fail(\n 'thinking mode is not compatible with temperature on provider openai: remove temperature or disable thinking'\n );\n }\n break;\n case 'xai':\n // Conservative default: fail if xAI effort is active (per D8 — live verification pending)\n if (resolved.xaiEffort !== undefined && resolved.xaiEffort !== 'none') {\n return fail(\n 'thinking mode is not compatible with temperature on provider xai: remove temperature or disable thinking'\n );\n }\n break;\n case 'google':\n // Gemini accepts temperature alongside thinkingConfig — no conflict\n break;\n }\n return succeed(undefined);\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolFormats.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/toolFormats.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 * Provider-specific tool format translation and tool resolution logic.\n * @packageDocumentation\n */\n\nimport { type JsonObject } from '@fgv/ts-json-base';\n\nimport {\n type AiServerToolConfig,\n type IAiProviderDescriptor,\n type IAiToolEnablement,\n type IAiWebSearchToolConfig\n} from './model';\n\n// ============================================================================\n// Tool resolution\n// ============================================================================\n\n/**\n * Resolves the effective tools for a completion call.\n *\n * - If per-call tools are provided, they override settings-level tools entirely.\n * - Otherwise, settings-level enabled tools are used.\n * - Only tools supported by the provider are included.\n * - Returns an empty array if no tools are enabled (= no tools sent).\n *\n * @param descriptor - The provider descriptor (used to filter by supported tools)\n * @param settingsTools - Tool enablement from provider settings (optional)\n * @param perCallTools - Per-call tool override (optional)\n * @returns The resolved list of tool configs to include in the request\n * @public\n */\nexport function resolveEffectiveTools(\n descriptor: IAiProviderDescriptor,\n settingsTools?: ReadonlyArray<IAiToolEnablement>,\n perCallTools?: ReadonlyArray<AiServerToolConfig>\n): ReadonlyArray<AiServerToolConfig> {\n const supported = new Set(descriptor.supportedTools);\n\n if (perCallTools !== undefined) {\n return perCallTools.filter((t) => supported.has(t.type));\n }\n\n if (settingsTools === undefined) {\n return [];\n }\n\n return settingsTools\n .filter((e) => e.enabled && supported.has(e.type))\n .map((e): AiServerToolConfig => e.config ?? { type: e.type });\n}\n\n// ============================================================================\n// OpenAI / xAI Responses API format\n// ============================================================================\n\n/**\n * Formats a web search tool config for the xAI/OpenAI Responses API.\n * @internal\n */\nfunction webSearchToResponsesApi(config: IAiWebSearchToolConfig): JsonObject {\n const tool: Record<string, unknown> = { type: 'web_search' };\n\n if (config.allowedDomains || config.blockedDomains) {\n const filters: Record<string, unknown> = {};\n if (config.allowedDomains) {\n filters.allowed_domains = [...config.allowedDomains];\n }\n if (config.blockedDomains) {\n filters.excluded_domains = [...config.blockedDomains];\n }\n tool.filters = filters;\n }\n\n if (config.enableImageUnderstanding) {\n tool.enable_image_understanding = true;\n }\n\n return tool as JsonObject;\n}\n\n/**\n * Formats tool configs for the xAI/OpenAI Responses API.\n * @param tools - The resolved tool configs\n * @returns Provider-native tool objects for the `tools` request field\n * @public\n */\nexport function toResponsesApiTools(tools: ReadonlyArray<AiServerToolConfig>): ReadonlyArray<JsonObject> {\n return tools.map((t) => {\n switch (t.type) {\n case 'web_search':\n return webSearchToResponsesApi(t);\n /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */\n default: {\n const _exhaustive: never = t.type;\n return { type: String(_exhaustive) } as JsonObject;\n }\n }\n });\n}\n\n// ============================================================================\n// Anthropic Messages API format\n// ============================================================================\n\n/**\n * Formats a web search tool config for the Anthropic Messages API.\n * @internal\n */\nfunction webSearchToAnthropic(config: IAiWebSearchToolConfig): JsonObject {\n const tool: Record<string, unknown> = {\n type: 'web_search_20250305',\n name: 'web_search'\n };\n\n if (config.maxUses !== undefined) {\n tool.max_uses = config.maxUses;\n }\n if (config.allowedDomains) {\n tool.allowed_domains = [...config.allowedDomains];\n }\n if (config.blockedDomains) {\n tool.blocked_domains = [...config.blockedDomains];\n }\n\n return tool as JsonObject;\n}\n\n/**\n * Formats tool configs for the Anthropic Messages API.\n * @param tools - The resolved tool configs\n * @returns Provider-native tool objects for the `tools` request field\n * @public\n */\nexport function toAnthropicTools(tools: ReadonlyArray<AiServerToolConfig>): ReadonlyArray<JsonObject> {\n return tools.map((t) => {\n switch (t.type) {\n case 'web_search':\n return webSearchToAnthropic(t);\n /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */\n default: {\n const _exhaustive: never = t.type;\n return { type: String(_exhaustive) } as JsonObject;\n }\n }\n });\n}\n\n// ============================================================================\n// Gemini generateContent API format\n// ============================================================================\n\n/**\n * Formats tool configs for the Gemini generateContent API.\n * Gemini uses `google_search` for search grounding — no per-tool config options.\n * @param tools - The resolved tool configs\n * @returns Provider-native tool objects for the `tools` request field\n * @public\n */\nexport function toGeminiTools(tools: ReadonlyArray<AiServerToolConfig>): ReadonlyArray<JsonObject> {\n const result: JsonObject[] = [];\n\n for (const t of tools) {\n switch (t.type) {\n case 'web_search':\n result.push({ google_search: {} } as JsonObject);\n break;\n /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */\n default: {\n const _exhaustive: never = t.type;\n result.push({ type: String(_exhaustive) } as JsonObject);\n }\n }\n }\n\n return result;\n}\n"]}
@@ -60,15 +60,49 @@ export const isoDate = new Conversion.BaseConverter((from) => {
60
60
  else if (from instanceof Date) {
61
61
  return succeed(from);
62
62
  }
63
+ else if (from instanceof DateTime) {
64
+ if (from.isValid) {
65
+ return succeed(from.toJSDate());
66
+ }
67
+ return fail(`Invalid date: ${from.invalidExplanation}`);
68
+ }
63
69
  return fail(`Cannot convert ${JSON.stringify(from)} to Date`);
64
70
  });
71
+ /**
72
+ * A `Converter` which converts an iso formatted string, a number or a `Date` object to
73
+ * a `DateTime` object.
74
+ * @public
75
+ */
76
+ export const isoDateTime = new Conversion.BaseConverter((from) => {
77
+ if (typeof from === 'string') {
78
+ const dt = DateTime.fromISO(from);
79
+ if (dt.isValid) {
80
+ return succeed(dt);
81
+ }
82
+ return fail(`Invalid date: ${dt.invalidExplanation}`);
83
+ }
84
+ else if (typeof from === 'number') {
85
+ return succeed(DateTime.fromMillis(from));
86
+ /* c8 ignore next 3 - Date instance path not exercised in current test suite */
87
+ }
88
+ else if (from instanceof Date) {
89
+ return succeed(DateTime.fromJSDate(from));
90
+ }
91
+ else if (from instanceof DateTime) {
92
+ if (from.isValid) {
93
+ return succeed(from);
94
+ }
95
+ return fail(`Invalid date: ${from.invalidExplanation}`);
96
+ }
97
+ return fail(`Cannot convert ${JSON.stringify(from)} to DateTime`);
98
+ });
65
99
  /**
66
100
  * A helper function to create a `Converter` which converts `unknown` to {@link Experimental.ExtendedArray | ExtendedArray<T>}.
67
101
  * @remarks
68
102
  * If `onError` is `'failOnError'` (default), then the entire conversion fails if any element cannot
69
103
  * be converted. If `onError` is `'ignoreErrors'`, then failing elements are silently ignored.
70
104
  * @param converter - `Converter` used to convert each item in the array
71
- * @param ignoreErrors - Specifies treatment of unconvertible elements
105
+ * @param onError - Specifies treatment of unconvertible elements
72
106
  * @beta
73
107
  */
74
108
  export function extendedArrayOf(label, converter, onError = 'failOnError') {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converters.js","sourceRoot":"","sources":["../../../src/packlets/conversion/converters.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2020 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\nimport { Conversion, Converter, Converters, Result, captureResult, fail, succeed } from '@fgv/ts-utils';\nimport { DateTime } from 'luxon';\nimport Mustache from 'mustache';\nimport { ExtendedArray, RangeOf, RangeOfProperties } from '../experimental';\n\n/**\n * Helper function to create a `StringConverter` which converts\n * `unknown` to `string`, applying template conversions supplied at construction time or at\n * runtime as context.\n * @remarks\n * Template conversions are applied using `mustache` syntax.\n * @param defaultContext - Optional default context to use for template values.\n * @returns A new `Converter` returning `string`.\n * @public\n */\nexport function templateString(defaultContext?: unknown): Conversion.StringConverter<string, unknown> {\n return new Conversion.StringConverter<string, unknown>(\n defaultContext,\n undefined,\n (from: unknown, __self: Converter<string, unknown>, context?: unknown) => {\n if (typeof from !== 'string') {\n return fail(`Not a string: ${JSON.stringify(from)}`);\n }\n return captureResult(() => Mustache.render(from, context));\n }\n );\n}\n\n/**\n * A `Converter` which converts an iso formatted string, a number or a `Date` object to\n * a `Date` object.\n * @public\n */\nexport const isoDate: Converter<Date, unknown> = new Conversion.BaseConverter<Date>((from: unknown) => {\n if (typeof from === 'string') {\n const dt = DateTime.fromISO(from);\n if (dt.isValid) {\n return succeed(dt.toJSDate());\n }\n return fail(`Invalid date: ${dt.invalidExplanation}`);\n } else if (typeof from === 'number') {\n return succeed(new Date(from));\n } else if (from instanceof Date) {\n return succeed(from);\n } else if (from instanceof DateTime) {\n if (from.isValid) {\n return succeed(from.toJSDate());\n }\n return fail(`Invalid date: ${from.invalidExplanation}`);\n }\n return fail(`Cannot convert ${JSON.stringify(from)} to Date`);\n});\n\n/**\n * A `Converter` which converts an iso formatted string, a number or a `Date` object to\n * a `DateTime` object.\n * @public\n */\nexport const isoDateTime: Converter<DateTime, unknown> = new Conversion.BaseConverter<DateTime>(\n (from: unknown) => {\n if (typeof from === 'string') {\n const dt = DateTime.fromISO(from);\n if (dt.isValid) {\n return succeed(dt);\n }\n return fail(`Invalid date: ${dt.invalidExplanation}`);\n } else if (typeof from === 'number') {\n return succeed(DateTime.fromMillis(from));\n /* c8 ignore next 3 - Date instance path not exercised in current test suite */\n } else if (from instanceof Date) {\n return succeed(DateTime.fromJSDate(from));\n } else if (from instanceof DateTime) {\n if (from.isValid) {\n return succeed(from);\n }\n return fail(`Invalid date: ${from.invalidExplanation}`);\n }\n return fail(`Cannot convert ${JSON.stringify(from)} to DateTime`);\n }\n);\n\n/**\n * A helper function to create a `Converter` which converts `unknown` to {@link Experimental.ExtendedArray | ExtendedArray<T>}.\n * @remarks\n * If `onError` is `'failOnError'` (default), then the entire conversion fails if any element cannot\n * be converted. If `onError` is `'ignoreErrors'`, then failing elements are silently ignored.\n * @param converter - `Converter` used to convert each item in the array\n * @param onError - Specifies treatment of unconvertible elements\n * @beta\n */\nexport function extendedArrayOf<T, TC = undefined>(\n label: string,\n converter: Converter<T, TC>,\n onError: Conversion.OnError = 'failOnError'\n): Converter<ExtendedArray<T>, TC> {\n return Converters.arrayOf(converter, onError).map((items: T[]) => {\n return captureResult(() => new ExtendedArray(label, ...items));\n });\n}\n\n/**\n * A helper wrapper to construct a `Converter` which converts to an arbitrary strongly-typed\n * range of some comparable type.\n * @param converter - `Converter` used to convert `min` and `max` extent of the range.\n * @param constructor - Static constructor to instantiate the object.\n * @public\n */\nexport function rangeTypeOf<T, RT extends RangeOf<T>, TC = unknown>(\n converter: Converter<T, TC>,\n constructor: (init: RangeOfProperties<T>) => Result<RT>\n): Converter<RT, TC> {\n return new Conversion.BaseConverter((from: unknown, __self, context?: TC) => {\n const result = Converters.object(\n {\n min: converter,\n max: converter\n },\n { optionalFields: ['min', 'max'] }\n ).convert(from, context);\n if (result.isSuccess()) {\n return constructor({ min: result.value.min, max: result.value.max });\n }\n return fail(result.message);\n });\n}\n\n/**\n * A helper wrapper to construct a `Converter` which converts to {@link Experimental.RangeOf | RangeOf<T>}\n * where `<T>` is some comparable type.\n * @param converter - `Converter` used to convert `min` and `max` extent of the range.\n * @public\n */\nexport function rangeOf<T, TC = unknown>(converter: Converter<T, TC>): Converter<RangeOf<T>, TC> {\n return rangeTypeOf<T, RangeOf<T>, TC>(converter, RangeOf.createRange);\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/conversion/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,CAAC","sourcesContent":["/*\n * Copyright (c) 2023 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\nimport * as Converters from './converters';\n\nexport { Converters };\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/constants.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;AAEZ,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,yBAAkC,CAAC;AAExE;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAsB,CAAC;AAExD;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAW,EAAE,CAAC;AAE3C;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAW,EAAE,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAW,EAAE,CAAC","sourcesContent":["// Copyright (c) 2024 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// Constants\n// ============================================================================\n\n/**\n * Current format version for encrypted files.\n * @public\n */\nexport const ENCRYPTED_FILE_FORMAT = 'encrypted-collection-v1' as const;\n\n/**\n * Default encryption algorithm.\n * @public\n */\nexport const DEFAULT_ALGORITHM = 'AES-256-GCM' as const;\n\n/**\n * Key size in bytes for AES-256.\n * @public\n */\nexport const AES_256_KEY_SIZE: number = 32;\n\n/**\n * IV size in bytes for GCM mode.\n * @public\n */\nexport const GCM_IV_SIZE: number = 12;\n\n/**\n * Auth tag size in bytes for GCM mode.\n * @public\n */\nexport const GCM_AUTH_TAG_SIZE: number = 16;\n"]}
@@ -44,16 +44,36 @@ export const encryptedFileErrorMode = Converters.enumeratedValue(['fail', 'skip'
44
44
  * Converter for {@link CryptoUtils.KeyDerivationFunction | key derivation function} type.
45
45
  * @public
46
46
  */
47
- export const keyDerivationFunction = Converters.enumeratedValue(['pbkdf2']);
47
+ export const keyDerivationFunction = Converters.enumeratedValue(['pbkdf2', 'argon2id']);
48
48
  /**
49
- * Converter for {@link CryptoUtils.IKeyDerivationParams | key derivation parameters}.
49
+ * Converter for {@link CryptoUtils.IPbkdf2KeyDerivationParams | PBKDF2 key derivation parameters}.
50
50
  * @public
51
51
  */
52
- export const keyDerivationParams = Converters.object({
53
- kdf: keyDerivationFunction,
52
+ export const pbkdf2KeyDerivationParams = Converters.object({
53
+ kdf: Converters.enumeratedValue(['pbkdf2']),
54
54
  salt: Converters.string,
55
55
  iterations: Converters.number
56
56
  });
57
+ /**
58
+ * Converter for {@link CryptoUtils.IArgon2idKeyDerivationParams | Argon2id key derivation parameters}.
59
+ * @public
60
+ */
61
+ export const argon2idKeyDerivationParams = Converters.object({
62
+ kdf: Converters.enumeratedValue(['argon2id']),
63
+ salt: Converters.string,
64
+ memoryKiB: Converters.number,
65
+ iterations: Converters.number,
66
+ parallelism: Converters.number
67
+ });
68
+ /**
69
+ * Converter for {@link CryptoUtils.IKeyDerivationParams | key derivation parameters}.
70
+ * Handles both PBKDF2 and Argon2id discriminated union arms.
71
+ * @public
72
+ */
73
+ export const keyDerivationParams = Converters.oneOf([
74
+ pbkdf2KeyDerivationParams,
75
+ argon2idKeyDerivationParams
76
+ ]);
57
77
  /**
58
78
  * Converter for base64 strings (validates format).
59
79
  * @public