@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
@@ -17,86 +17,13 @@
17
17
  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
18
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  // SOFTWARE.
20
- /**
21
- * Chat completion client for AI assist with support for multiple provider APIs.
22
- *
23
- * Supports OpenAI-compatible providers (xAI, OpenAI, Groq, Mistral) directly,
24
- * plus adapters for Anthropic and Google Gemini.
25
- *
26
- * When server-side tools (e.g. web_search) are configured, providers that support
27
- * them will include tool configuration in the request and handle tool-augmented
28
- * responses.
29
- *
30
- * @packageDocumentation
31
- */
32
- import { isJsonObject } from '@fgv/ts-json-base';
33
20
  import { fail, succeed, Validators } from '@fgv/ts-utils';
34
- import { resolveModel } from './model';
21
+ import { DEFAULT_ANTHROPIC_MAX_TOKENS, isAdaptiveThinkingModel, isResponsesOnlyModel, resolveProviderModel, usesMaxCompletionTokensField } from './model';
22
+ import { anthropicEffortToBudgetTokens, checkTemperatureConflict, mergeThinkingConfig, providerDiscriminatorForId } from './thinkingOptionsResolver';
23
+ import { buildAnthropicMessages, buildGeminiContents, buildMessages, buildOpenAiChatUserContent, buildOpenAiResponsesUserContent, normalizeOutboundMessages, splitChatRequest } from './chatRequestBuilders';
24
+ import { anthropicAuthHeaders, bearerAuthHeader, geminiAuthHeader, resolveEffectiveBaseUrl } from './endpoint';
25
+ import { fetchJson } from './http';
35
26
  import { toAnthropicTools, toGeminiTools, toResponsesApiTools } from './toolFormats';
36
- // ============================================================================
37
- // Shared helpers
38
- // ============================================================================
39
- /**
40
- * Builds the messages array from prompt + optional correction messages.
41
- * @internal
42
- */
43
- function buildMessages(prompt, additionalMessages) {
44
- const messages = [
45
- { role: 'system', content: prompt.system },
46
- { role: 'user', content: prompt.user }
47
- ];
48
- if (additionalMessages) {
49
- for (const msg of additionalMessages) {
50
- messages.push({ role: msg.role, content: msg.content });
51
- }
52
- }
53
- return messages;
54
- }
55
- /**
56
- * Makes an HTTP request and returns the parsed JSON, or a failure.
57
- * @internal
58
- */
59
- async function fetchJson(url, headers, body, logger) {
60
- /* c8 ignore next 1 - optional logger */
61
- logger === null || logger === void 0 ? void 0 : logger.detail(`AI API request: POST ${url}`);
62
- let response;
63
- try {
64
- response = await fetch(url, {
65
- method: 'POST',
66
- headers: Object.assign({ 'Content-Type': 'application/json' }, headers),
67
- body: JSON.stringify(body)
68
- });
69
- }
70
- catch (err) {
71
- const detail = err instanceof Error ? err.message : String(err);
72
- /* c8 ignore next 1 - optional logger */
73
- logger === null || logger === void 0 ? void 0 : logger.error(`AI API request failed: ${detail}`);
74
- return fail(`AI API request failed: ${detail}`);
75
- }
76
- if (!response.ok) {
77
- const errorText = await response.text().catch(() => 'unknown error');
78
- /* c8 ignore next 1 - optional logger */
79
- logger === null || logger === void 0 ? void 0 : logger.error(`AI API returned ${response.status}: ${errorText}`);
80
- return fail(`AI API returned ${response.status}: ${errorText}`);
81
- }
82
- /* c8 ignore next 1 - optional logger */
83
- logger === null || logger === void 0 ? void 0 : logger.detail(`AI API response: ${response.status}`);
84
- let json;
85
- try {
86
- json = await response.json();
87
- }
88
- catch (_a) {
89
- /* c8 ignore next 1 - optional logger */
90
- logger === null || logger === void 0 ? void 0 : logger.error('AI API returned invalid JSON response');
91
- return fail('AI API returned invalid JSON response');
92
- }
93
- if (!isJsonObject(json)) {
94
- /* c8 ignore next 1 - optional logger */
95
- logger === null || logger === void 0 ? void 0 : logger.error('AI API returned non-object JSON response');
96
- return fail('AI API returned non-object JSON response');
97
- }
98
- return succeed(json);
99
- }
100
27
  const openAiMessage = Validators.object({
101
28
  content: Validators.string
102
29
  });
@@ -121,13 +48,6 @@ const responsesApiResponse = Validators.object({
121
48
  output: Validators.arrayOf(responsesApiOutputItem).withConstraint((arr) => arr.length > 0),
122
49
  status: Validators.string
123
50
  });
124
- const anthropicContentBlock = Validators.object({
125
- text: Validators.string
126
- });
127
- const anthropicResponse = Validators.object({
128
- content: Validators.arrayOf(anthropicContentBlock).withConstraint((arr) => arr.length > 0),
129
- stop_reason: Validators.string
130
- });
131
51
  const geminiPart = Validators.object({
132
52
  text: Validators.string
133
53
  });
@@ -149,16 +69,22 @@ const geminiResponse = Validators.object({
149
69
  * Works for xAI Grok, OpenAI, Groq, and Mistral.
150
70
  * @internal
151
71
  */
152
- async function callOpenAiCompletion(config, prompt, additionalMessages, temperature = 0.7, logger) {
72
+ async function callOpenAiCompletion(config, prompt, head, temperature, logger, signal, resolvedThinking, maxTokens, useMaxCompletionTokensField = false) {
73
+ var _a;
153
74
  const url = `${config.baseUrl}/chat/completions`;
154
- const messages = buildMessages(prompt, additionalMessages);
155
- const body = { model: config.model, messages, temperature };
156
- const headers = {
157
- Authorization: `Bearer ${config.apiKey}`
158
- };
75
+ const messages = buildMessages(prompt.system, buildOpenAiChatUserContent(prompt), {
76
+ head
77
+ });
78
+ const effort = (_a = resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.openAiEffort) !== null && _a !== void 0 ? _a : resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.xaiEffort;
79
+ const maxTokensField = useMaxCompletionTokensField ? 'max_completion_tokens' : 'max_tokens';
80
+ const body = Object.assign(Object.assign(Object.assign({ model: config.model, messages }, (temperature !== undefined ? { temperature } : {})), (effort !== undefined && config.model !== 'grok-4' ? { reasoning_effort: effort } : {})), (maxTokens !== undefined ? { [maxTokensField]: maxTokens } : {}));
81
+ if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
82
+ Object.assign(body, resolvedThinking.otherParams);
83
+ }
84
+ const headers = bearerAuthHeader(config.apiKey);
159
85
  /* c8 ignore next 1 - optional logger */
160
86
  logger === null || logger === void 0 ? void 0 : logger.info(`OpenAI completion: model=${config.model}`);
161
- const jsonResult = await fetchJson(url, headers, body, logger);
87
+ const jsonResult = await fetchJson(url, headers, body, logger, signal);
162
88
  if (jsonResult.isFailure()) {
163
89
  return fail(jsonResult.message);
164
90
  }
@@ -197,21 +123,25 @@ function extractResponsesApiText(output) {
197
123
  * Used when tools are configured for an openai-format provider.
198
124
  * @internal
199
125
  */
200
- async function callOpenAiResponsesCompletion(config, prompt, tools, additionalMessages, temperature = 0.7, logger) {
126
+ async function callOpenAiResponsesCompletion(config, prompt, tools = [], head, temperature, logger, signal, resolvedThinking, maxTokens) {
127
+ var _a;
201
128
  const url = `${config.baseUrl}/responses`;
202
- const input = buildMessages(prompt, additionalMessages);
203
- const body = {
204
- model: config.model,
205
- input,
206
- tools: toResponsesApiTools(tools),
207
- temperature
208
- };
209
- const headers = {
210
- Authorization: `Bearer ${config.apiKey}`
211
- };
129
+ const input = buildMessages(prompt.system, buildOpenAiResponsesUserContent(prompt), {
130
+ head
131
+ });
132
+ const effort = (_a = resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.openAiEffort) !== null && _a !== void 0 ? _a : resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.xaiEffort;
133
+ const body = Object.assign(Object.assign(Object.assign({ model: config.model, input }, (tools.length > 0 ? { tools: toResponsesApiTools(tools) } : {})), (temperature !== undefined ? { temperature } : {})), (effort !== undefined && config.model !== 'grok-4' ? { reasoning: { effort } } : {}));
134
+ // Shared by OpenAI and xAI — both route through the Responses API with the same field name.
135
+ if (maxTokens !== undefined) {
136
+ body.max_output_tokens = maxTokens;
137
+ }
138
+ if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
139
+ Object.assign(body, resolvedThinking.otherParams);
140
+ }
141
+ const headers = bearerAuthHeader(config.apiKey);
212
142
  /* c8 ignore next 1 - optional logger */
213
143
  logger === null || logger === void 0 ? void 0 : logger.info(`OpenAI Responses API: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);
214
- const jsonResult = await fetchJson(url, headers, body, logger);
144
+ const jsonResult = await fetchJson(url, headers, body, logger, signal);
215
145
  if (jsonResult.isFailure()) {
216
146
  return fail(jsonResult.message);
217
147
  }
@@ -250,31 +180,29 @@ function extractAnthropicText(content) {
250
180
  }
251
181
  return succeed(textParts.join(''));
252
182
  }
253
- /**
254
- * Calls the Anthropic Messages API.
255
- * When tools are configured, includes them in the request and handles
256
- * mixed content block responses.
257
- * @internal
258
- */
259
- async function callAnthropicCompletion(config, prompt, additionalMessages, temperature = 0.7, logger, tools) {
183
+ /** Calls the Anthropic Messages API with optional tool support. @internal */
184
+ async function callAnthropicCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking, useAdaptiveThinking = false, maxTokens) {
260
185
  const url = `${config.baseUrl}/messages`;
261
- // Anthropic uses system as a top-level field, not in messages
262
- const messages = [{ role: 'user', content: prompt.user }];
263
- if (additionalMessages) {
264
- for (const msg of additionalMessages) {
265
- // Anthropic doesn't have a system role in messages
266
- if (msg.role !== 'system') {
267
- messages.push({ role: msg.role, content: msg.content });
268
- }
186
+ const messages = buildAnthropicMessages(prompt, { head });
187
+ const body = Object.assign({ model: config.model, system: prompt.system, messages,
188
+ // Anthropic's Messages API requires max_tokens on every request — see
189
+ // AiAssist.DEFAULT_ANTHROPIC_MAX_TOKENS for why only this provider defaults it.
190
+ max_tokens: maxTokens !== null && maxTokens !== void 0 ? maxTokens : DEFAULT_ANTHROPIC_MAX_TOKENS }, (temperature !== undefined ? { temperature } : {}));
191
+ const effort = resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.anthropicEffort;
192
+ if (effort !== undefined) {
193
+ if (useAdaptiveThinking) {
194
+ // Claude 5 family: adaptive thinking — no budget_tokens; effort moves to the
195
+ // top-level output_config block. See AiAssist.isAdaptiveThinkingModel.
196
+ body.thinking = { type: 'adaptive' };
197
+ body.output_config = { effort };
198
+ }
199
+ else {
200
+ body.thinking = { type: 'enabled', budget_tokens: anthropicEffortToBudgetTokens(effort) };
269
201
  }
270
202
  }
271
- const body = {
272
- model: config.model,
273
- system: prompt.system,
274
- messages,
275
- max_tokens: 4096,
276
- temperature
277
- };
203
+ if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
204
+ Object.assign(body, resolvedThinking.otherParams);
205
+ }
278
206
  if (tools && tools.length > 0) {
279
207
  body.tools = toAnthropicTools(tools);
280
208
  /* c8 ignore next 3 - optional logger diagnostic output */
@@ -284,37 +212,23 @@ async function callAnthropicCompletion(config, prompt, additionalMessages, tempe
284
212
  /* c8 ignore next 1 - optional logger */
285
213
  logger === null || logger === void 0 ? void 0 : logger.info(`Anthropic completion: model=${config.model}`);
286
214
  }
287
- const headers = {
288
- 'x-api-key': config.apiKey,
289
- 'anthropic-version': '2023-06-01',
290
- 'anthropic-dangerous-direct-browser-access': 'true'
291
- };
292
- const jsonResult = await fetchJson(url, headers, body, logger);
215
+ const headers = anthropicAuthHeaders(config.apiKey);
216
+ const jsonResult = await fetchJson(url, headers, body, logger, signal);
293
217
  if (jsonResult.isFailure()) {
294
218
  return fail(jsonResult.message);
295
219
  }
296
- // When tools are used, the response content is a mixed array of block types.
297
- // We need to extract text from all text blocks.
298
- if (tools && tools.length > 0) {
299
- const rawContent = jsonResult.value.content;
300
- const stopReason = jsonResult.value.stop_reason;
301
- if (!Array.isArray(rawContent)) {
302
- return fail('Anthropic API response: content is not an array');
303
- }
304
- return extractAnthropicText(rawContent).onSuccess((text) => succeed({
305
- content: text,
306
- truncated: stopReason === 'max_tokens'
307
- }));
220
+ const rawContent = jsonResult.value.content;
221
+ const stopReason = jsonResult.value.stop_reason;
222
+ if (!Array.isArray(rawContent)) {
223
+ return fail('Anthropic API response: content is not an array');
308
224
  }
309
- return anthropicResponse
310
- .validate(jsonResult.value)
311
- .withErrorFormat((msg) => `Anthropic API response: ${msg}`)
312
- .onSuccess((response) => {
313
- return succeed({
314
- content: response.content[0].text,
315
- truncated: response.stop_reason === 'max_tokens'
316
- });
317
- });
225
+ if (typeof stopReason !== 'string') {
226
+ return fail('Anthropic API response: stop_reason is missing or not a string');
227
+ }
228
+ return extractAnthropicText(rawContent).onSuccess((text) => succeed({
229
+ content: text,
230
+ truncated: stopReason === 'max_tokens'
231
+ }));
318
232
  }
319
233
  // ============================================================================
320
234
  // Google Gemini adapter
@@ -324,26 +238,27 @@ async function callAnthropicCompletion(config, prompt, additionalMessages, tempe
324
238
  * When tools are configured, includes Google Search grounding.
325
239
  * @internal
326
240
  */
327
- async function callGeminiCompletion(config, prompt, additionalMessages, temperature = 0.7, logger, tools) {
241
+ async function callGeminiCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking, maxTokens) {
328
242
  const url = `${config.baseUrl}/models/${config.model}:generateContent`;
329
- // Gemini uses 'contents' with 'parts', and 'model' role instead of 'assistant'
330
- const contents = [
331
- { role: 'user', parts: [{ text: prompt.user }] }
332
- ];
333
- if (additionalMessages) {
334
- for (const msg of additionalMessages) {
335
- if (msg.role !== 'system') {
336
- contents.push({
337
- role: msg.role === 'assistant' ? 'model' : msg.role,
338
- parts: [{ text: msg.content }]
339
- });
340
- }
341
- }
243
+ const contents = buildGeminiContents(prompt, { head });
244
+ // Temperature is sent only when explicitly provided; otherwise Gemini's default applies.
245
+ const generationConfig = {};
246
+ if (temperature !== undefined) {
247
+ generationConfig.temperature = temperature;
248
+ }
249
+ if (maxTokens !== undefined) {
250
+ generationConfig.maxOutputTokens = maxTokens;
251
+ }
252
+ if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.geminiThinkingBudget) !== undefined) {
253
+ generationConfig.thinkingConfig = { thinkingBudget: resolvedThinking.geminiThinkingBudget };
254
+ }
255
+ if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
256
+ Object.assign(generationConfig, resolvedThinking.otherParams);
342
257
  }
343
258
  const body = {
344
259
  systemInstruction: { parts: [{ text: prompt.system }] },
345
260
  contents,
346
- generationConfig: { temperature }
261
+ generationConfig
347
262
  };
348
263
  if (tools && tools.length > 0) {
349
264
  body.tools = toGeminiTools(tools);
@@ -354,10 +269,8 @@ async function callGeminiCompletion(config, prompt, additionalMessages, temperat
354
269
  /* c8 ignore next 1 - optional logger */
355
270
  logger === null || logger === void 0 ? void 0 : logger.info(`Gemini completion: model=${config.model}`);
356
271
  }
357
- const headers = {
358
- 'x-goog-api-key': config.apiKey
359
- };
360
- const jsonResult = await fetchJson(url, headers, body, logger);
272
+ const headers = geminiAuthHeader(config.apiKey);
273
+ const jsonResult = await fetchJson(url, headers, body, logger, signal);
361
274
  if (jsonResult.isFailure()) {
362
275
  return fail(jsonResult.message);
363
276
  }
@@ -376,33 +289,54 @@ async function callGeminiCompletion(config, prompt, additionalMessages, temperat
376
289
  // Provider dispatcher
377
290
  // ============================================================================
378
291
  /**
379
- * Calls the appropriate chat completion API for a given provider.
380
- *
381
- * Routes based on the provider descriptor's `apiFormat` field:
382
- * - `'openai'` for xAI, OpenAI, Groq, Mistral
383
- * - `'anthropic'` for Anthropic Claude
384
- * - `'gemini'` for Google Gemini
385
- *
386
- * When tools are provided and the provider supports them:
387
- * - OpenAI-format providers switch to the Responses API
388
- * - Anthropic includes tools in the Messages API request
389
- * - Gemini includes Google Search grounding
390
- *
391
- * @param params - Request parameters including descriptor, API key, prompt, and optional tools
392
- * @returns The completion response with content and truncation status, or a failure
292
+ * Calls the appropriate chat completion API for a given provider. Routes by
293
+ * `apiFormat`: `'openai'` (xAI/OpenAI/Groq/Mistral — switches to Responses API
294
+ * when tools are set), `'anthropic'`, or `'gemini'`.
393
295
  * @public
394
296
  */
395
297
  export async function callProviderCompletion(params) {
396
- const { descriptor, apiKey, prompt, additionalMessages, temperature = 0.7, modelOverride, logger, tools } = params;
397
- if (!descriptor.baseUrl) {
398
- return fail(`provider "${descriptor.id}" has no API endpoint configured`);
298
+ const { descriptor, apiKey, system, messages, temperature, modelOverride, tier, logger, tools, signal, endpoint, thinking, maxTokens } = params;
299
+ const splitResult = splitChatRequest(system, messages);
300
+ if (splitResult.isFailure()) {
301
+ return fail(splitResult.message);
302
+ }
303
+ const { prompt, head } = splitResult.value;
304
+ const baseUrlResult = resolveEffectiveBaseUrl(descriptor, endpoint);
305
+ if (baseUrlResult.isFailure()) {
306
+ return fail(baseUrlResult.message);
307
+ }
308
+ if (prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {
309
+ return fail(`provider "${descriptor.id}" does not accept image input`);
399
310
  }
400
311
  const hasTools = tools !== undefined && tools.length > 0;
401
- const modelContext = hasTools ? 'tools' : undefined;
312
+ const discriminator = providerDiscriminatorForId(descriptor.id);
313
+ // The quality tier is the only completion-model selector; thinking and tools
314
+ // are orthogonal request params/capabilities and never pick a model.
315
+ const modelContext = tier;
316
+ const modelResult = resolveProviderModel(descriptor, modelOverride, modelContext);
317
+ if (modelResult.isFailure()) {
318
+ return fail(modelResult.message);
319
+ }
320
+ const model = modelResult.value;
321
+ let resolvedThinking;
322
+ if (thinking !== undefined) {
323
+ if (discriminator !== undefined) {
324
+ const mergeResult = mergeThinkingConfig(thinking, model, discriminator);
325
+ /* c8 ignore next 3 - mergeThinkingConfig always succeeds; defensive guard */
326
+ if (mergeResult.isFailure()) {
327
+ return fail(mergeResult.message);
328
+ }
329
+ resolvedThinking = mergeResult.value;
330
+ const conflictResult = checkTemperatureConflict(resolvedThinking, discriminator, temperature);
331
+ if (conflictResult.isFailure()) {
332
+ return fail(conflictResult.message);
333
+ }
334
+ }
335
+ }
402
336
  const config = {
403
- baseUrl: descriptor.baseUrl,
337
+ baseUrl: baseUrlResult.value,
404
338
  apiKey,
405
- model: resolveModel(modelOverride !== null && modelOverride !== void 0 ? modelOverride : descriptor.defaultModel, modelContext)
339
+ model
406
340
  };
407
341
  /* c8 ignore next 8 - optional logger diagnostic output */
408
342
  if (logger) {
@@ -413,14 +347,16 @@ export async function callProviderCompletion(params) {
413
347
  }
414
348
  switch (descriptor.apiFormat) {
415
349
  case 'openai':
416
- if (hasTools) {
417
- return callOpenAiResponsesCompletion(config, prompt, tools, additionalMessages, temperature, logger);
350
+ // Responses-API-only models (e.g. gpt-5.5-pro) 400 on /chat/completions, so they route
351
+ // to the Responses path even with no tools requested same path the tools case uses.
352
+ if (hasTools || isResponsesOnlyModel(descriptor, config.model)) {
353
+ return callOpenAiResponsesCompletion(config, prompt, tools, head, temperature, logger, signal, resolvedThinking, maxTokens);
418
354
  }
419
- return callOpenAiCompletion(config, prompt, additionalMessages, temperature, logger);
355
+ return callOpenAiCompletion(config, prompt, head, temperature, logger, signal, resolvedThinking, maxTokens, usesMaxCompletionTokensField(descriptor));
420
356
  case 'anthropic':
421
- return callAnthropicCompletion(config, prompt, additionalMessages, temperature, logger, tools);
357
+ return callAnthropicCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking, isAdaptiveThinkingModel(descriptor, config.model), maxTokens);
422
358
  case 'gemini':
423
- return callGeminiCompletion(config, prompt, additionalMessages, temperature, logger, tools);
359
+ return callGeminiCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking, maxTokens);
424
360
  /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */
425
361
  default: {
426
362
  const _exhaustive = descriptor.apiFormat;
@@ -432,28 +368,36 @@ export async function callProviderCompletion(params) {
432
368
  // Proxied completion (routes through a backend server)
433
369
  // ============================================================================
434
370
  /**
435
- * Calls the AI completion endpoint on a proxy server instead of calling
436
- * the provider API directly from the browser.
437
- *
438
- * The proxy server handles provider dispatch, CORS, and API key forwarding.
439
- * The request shape mirrors {@link IProviderCompletionParams} but is serialized
440
- * as JSON for the proxy endpoint.
441
- *
442
- * @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`)
371
+ * Calls the AI completion endpoint on a proxy server instead of calling the
372
+ * provider API directly from the browser. The proxy handles provider dispatch,
373
+ * CORS, and API key forwarding. The request body serializes the unified
374
+ * {@link AiAssist.IChatRequest} shape (`system?` + `messages`). Enforces the same
375
+ * non-empty / trailing-user-turn and image-input invariants as the direct path.
376
+ * @param proxyUrl - Base URL of the proxy server
443
377
  * @param params - Same parameters as {@link callProviderCompletion}
444
- * @returns The completion response, or a failure
445
378
  * @public
446
379
  */
447
380
  export async function callProxiedCompletion(proxyUrl, params) {
448
- const { descriptor, apiKey, prompt, additionalMessages, temperature, modelOverride, logger, tools } = params;
381
+ const { descriptor, apiKey, system, messages, temperature, modelOverride, logger, tools, signal, thinking, maxTokens } = params;
382
+ const splitResult = splitChatRequest(system, messages);
383
+ if (splitResult.isFailure()) {
384
+ return fail(splitResult.message);
385
+ }
386
+ if (splitResult.value.prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {
387
+ return fail(`provider "${descriptor.id}" does not accept image input`);
388
+ }
449
389
  const body = {
450
390
  providerId: descriptor.id,
451
391
  apiKey,
452
- prompt: { system: prompt.system, user: prompt.user },
453
- temperature: temperature !== null && temperature !== void 0 ? temperature : 0.7
392
+ messages: normalizeOutboundMessages(splitResult.value)
454
393
  };
455
- if (additionalMessages && additionalMessages.length > 0) {
456
- body.additionalMessages = additionalMessages;
394
+ // Temperature is forwarded only when explicitly provided, matching the direct path — the proxy
395
+ // omits it from the upstream request so the provider default applies.
396
+ if (temperature !== undefined) {
397
+ body.temperature = temperature;
398
+ }
399
+ if (system !== undefined) {
400
+ body.system = system;
457
401
  }
458
402
  if (modelOverride !== undefined) {
459
403
  body.modelOverride = modelOverride;
@@ -461,14 +405,21 @@ export async function callProxiedCompletion(proxyUrl, params) {
461
405
  if (tools && tools.length > 0) {
462
406
  body.tools = tools;
463
407
  }
408
+ if (thinking !== undefined) {
409
+ body.thinking = thinking;
410
+ }
411
+ // Forwarded only when explicitly provided; the proxy is responsible for mapping it to the
412
+ // correct upstream provider field (see AiAssist.usesMaxCompletionTokensField).
413
+ if (maxTokens !== undefined) {
414
+ body.maxTokens = maxTokens;
415
+ }
464
416
  /* c8 ignore next 1 - optional logger */
465
417
  logger === null || logger === void 0 ? void 0 : logger.info(`AI proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);
466
418
  const url = `${proxyUrl}/api/ai/completion`;
467
- const jsonResult = await fetchJson(url, {}, body, logger);
419
+ const jsonResult = await fetchJson(url, {}, body, logger, signal);
468
420
  if (jsonResult.isFailure()) {
469
421
  return fail(jsonResult.message);
470
422
  }
471
- // Check for error response from proxy
472
423
  const response = jsonResult.value;
473
424
  if (typeof response.error === 'string') {
474
425
  return fail(`proxy: ${response.error}`);
@@ -481,4 +432,4 @@ export async function callProxiedCompletion(proxyUrl, params) {
481
432
  truncated: response.truncated === true
482
433
  });
483
434
  }
484
- //# sourceMappingURL=apiClient.js.map
435
+ //# sourceMappingURL=completionClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completionClient.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/completionClient.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 * Chat completion clients for AI assist. One provider dispatcher over\n * `IAiProviderDescriptor.apiFormat`, the four adapters it routes to (OpenAI Chat\n * Completions, OpenAI/xAI Responses, Anthropic, Google Gemini), the response\n * validators those adapters use, and the proxied variant of the same modality.\n *\n * @packageDocumentation\n */\n\nimport { type JsonObject } from '@fgv/ts-json-base';\nimport { fail, type Logging, Result, succeed, type Validator, Validators } from '@fgv/ts-utils';\n\nimport {\n AiPrompt,\n type AiServerToolConfig,\n DEFAULT_ANTHROPIC_MAX_TOKENS,\n type IAiCompletionResponse,\n type IAiProviderDescriptor,\n type IChatMessage,\n type IChatRequest,\n type IThinkingConfig,\n type ModelSpec,\n type ModelSpecKey,\n isAdaptiveThinkingModel,\n isResponsesOnlyModel,\n resolveProviderModel,\n usesMaxCompletionTokensField\n} from './model';\nimport {\n anthropicEffortToBudgetTokens,\n checkTemperatureConflict,\n mergeThinkingConfig,\n providerDiscriminatorForId,\n type IResolvedThinkingConfig\n} from './thinkingOptionsResolver';\nimport {\n buildAnthropicMessages,\n buildGeminiContents,\n buildMessages,\n buildOpenAiChatUserContent,\n buildOpenAiResponsesUserContent,\n normalizeOutboundMessages,\n splitChatRequest\n} from './chatRequestBuilders';\nimport {\n anthropicAuthHeaders,\n bearerAuthHeader,\n geminiAuthHeader,\n resolveEffectiveBaseUrl\n} from './endpoint';\nimport { type IAiApiConfig, fetchJson } from './http';\nimport { toAnthropicTools, toGeminiTools, toResponsesApiTools } from './toolFormats';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Parameters for a provider completion request. Carries the unified\n * {@link AiAssist.IChatRequest} shape (`system?` + ordered `messages`, last =\n * current user turn); history is linearized before the current turn.\n * @public\n */\nexport interface IProviderCompletionParams extends IChatRequest {\n /** The provider descriptor */\n readonly descriptor: IAiProviderDescriptor;\n /** API key for authentication */\n readonly apiKey: string;\n /**\n * Sampling temperature. Sent to the provider only when explicitly provided; omitted otherwise\n * so the provider's own default applies (current-gen models reject a caller-supplied default).\n */\n readonly temperature?: number;\n /** Optional model override — string or context-aware map (uses descriptor.defaultModel otherwise) */\n readonly modelOverride?: ModelSpec;\n /**\n * Optional quality tier selecting which completion model to use. `undefined`\n * selects the `base` tier; `'frontier'` cascades to `advanced` then `base`\n * when a tier is unset for a provider. Orthogonal to `thinking` and `tools`,\n * which never select a model.\n */\n readonly tier?: 'advanced' | 'frontier';\n /** Optional logger for request/response observability. */\n readonly logger?: Logging.ILogger;\n /** Server-side tools to include in the request. Overrides settings-level tool config when provided. */\n readonly tools?: ReadonlyArray<AiServerToolConfig>;\n /** Optional abort signal for cancelling the in-flight request. */\n readonly signal?: AbortSignal;\n /**\n * Optional override of the descriptor's default base URL (scheme + host +\n * optional port + path prefix). The per-route suffix (e.g. `/chat/completions`)\n * is appended unchanged. Must be a well-formed `http`/`https` URL. Auth shape\n * is unchanged: `needsSecret` providers still require an API key.\n */\n readonly endpoint?: string;\n /**\n * Optional thinking/reasoning config. Anthropic, OpenAI, and xAI reject `temperature` when\n * the effective merged effort is non-`'none'`; Gemini always accepts both.\n */\n readonly thinking?: IThinkingConfig;\n /**\n * Optional cap on generated output tokens, mapped to each provider's native field:\n * Anthropic `max_tokens`, OpenAI Chat Completions `max_completion_tokens`, OpenAI/xAI\n * Responses `max_output_tokens`, Gemini `generationConfig.maxOutputTokens`, and the\n * xAI/Groq/Mistral/Ollama/`openai-compat` chat-completions path `max_tokens`. When unset,\n * every provider except Anthropic omits the field and applies its own default; Anthropic's\n * Messages API requires the field, so it falls back to `DEFAULT_ANTHROPIC_MAX_TOKENS`.\n */\n readonly maxTokens?: number;\n}\n\n// ============================================================================\n// Response validators (non-strict — extra API fields preserved for debugging)\n// ============================================================================\n\n// ---- OpenAI Chat Completions format ----\n\n/** @internal */\ninterface IOpenAiMessage {\n content: string;\n}\n/** @internal */\ninterface IOpenAiChoice {\n message: IOpenAiMessage;\n finish_reason: string;\n}\n/** @internal */\ninterface IOpenAiResponse {\n choices: IOpenAiChoice[];\n}\n\nconst openAiMessage: Validator<IOpenAiMessage> = Validators.object<IOpenAiMessage>({\n content: Validators.string\n});\nconst openAiChoice: Validator<IOpenAiChoice> = Validators.object<IOpenAiChoice>({\n message: openAiMessage,\n finish_reason: Validators.string\n});\nconst openAiResponse: Validator<IOpenAiResponse> = Validators.object<IOpenAiResponse>({\n choices: Validators.arrayOf(openAiChoice).withConstraint((arr) => arr.length > 0)\n});\n\n// ---- OpenAI/xAI Responses API format ----\n\n/** @internal */\ninterface IResponsesApiOutputText {\n type: 'output_text';\n text: string;\n}\n/** @internal */\ninterface IResponsesApiMessage {\n type: 'message';\n role: string;\n content: IResponsesApiOutputText[];\n}\n/** @internal */\ninterface IResponsesApiResponse {\n output: Array<Record<string, unknown>>;\n status: string;\n}\n\nconst responsesApiOutputText: Validator<IResponsesApiOutputText> = Validators.object<IResponsesApiOutputText>(\n {\n type: Validators.literal('output_text'),\n text: Validators.string\n }\n);\nconst responsesApiMessage: Validator<IResponsesApiMessage> = Validators.object<IResponsesApiMessage>({\n type: Validators.literal('message'),\n role: Validators.string,\n content: Validators.arrayOf(responsesApiOutputText).withConstraint((arr) => arr.length > 0)\n});\nconst responsesApiOutputItem: Validator<Record<string, unknown>> = Validators.isA(\n 'object',\n (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null\n);\nconst responsesApiResponse: Validator<IResponsesApiResponse> = Validators.object<IResponsesApiResponse>({\n output: Validators.arrayOf(responsesApiOutputItem).withConstraint((arr) => arr.length > 0),\n status: Validators.string\n});\n\n// ---- Gemini format ----\n\n/** @internal */\ninterface IGeminiPart {\n text: string;\n}\n/** @internal */\ninterface IGeminiContent {\n parts: IGeminiPart[];\n}\n/** @internal */\ninterface IGeminiCandidate {\n content: IGeminiContent;\n finishReason: string;\n}\n/** @internal */\ninterface IGeminiResponse {\n candidates: IGeminiCandidate[];\n}\n\nconst geminiPart: Validator<IGeminiPart> = Validators.object<IGeminiPart>({\n text: Validators.string\n});\nconst geminiContent: Validator<IGeminiContent> = Validators.object<IGeminiContent>({\n parts: Validators.arrayOf(geminiPart).withConstraint((arr) => arr.length > 0)\n});\nconst geminiCandidate: Validator<IGeminiCandidate> = Validators.object<IGeminiCandidate>({\n content: geminiContent,\n finishReason: Validators.string\n});\nconst geminiResponse: Validator<IGeminiResponse> = Validators.object<IGeminiResponse>({\n candidates: Validators.arrayOf(geminiCandidate).withConstraint((arr) => arr.length > 0)\n});\n\n// ============================================================================\n// OpenAI-compatible client (Chat Completions — no tools)\n// ============================================================================\n\n/**\n * Calls an OpenAI-compatible chat completion endpoint.\n * Works for xAI Grok, OpenAI, Groq, and Mistral.\n * @internal\n */\nasync function callOpenAiCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n maxTokens?: number,\n useMaxCompletionTokensField: boolean = false\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/chat/completions`;\n const messages = buildMessages(prompt.system, buildOpenAiChatUserContent(prompt), {\n head\n });\n const effort = resolvedThinking?.openAiEffort ?? resolvedThinking?.xaiEffort;\n const maxTokensField = useMaxCompletionTokensField ? 'max_completion_tokens' : 'max_tokens';\n const body: Record<string, unknown> = {\n model: config.model,\n messages,\n // Temperature is sent only when the caller explicitly provided one — omitting it lets each\n // provider apply its own default (current-gen models reject a non-default temperature). The\n // completion path already rejects temperature + non-'none' thinking upstream\n // (checkTemperatureConflict), so no effort gate is needed here.\n ...(temperature !== undefined ? { temperature } : {}),\n ...(effort !== undefined && config.model !== 'grok-4' ? { reasoning_effort: effort } : {}),\n // Omitted when the caller doesn't set maxTokens — every non-Anthropic provider applies its\n // own default. See AiAssist.usesMaxCompletionTokensField for the field-name split.\n ...(maxTokens !== undefined ? { [maxTokensField]: maxTokens } : {})\n };\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n\n const headers: Record<string, string> = bearerAuthHeader(config.apiKey);\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`OpenAI completion: model=${config.model}`);\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return openAiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `OpenAI API response: ${msg}`)\n .onSuccess((response) => {\n const choice = response.choices[0];\n return succeed({\n content: choice.message.content,\n truncated: choice.finish_reason === 'length'\n });\n });\n}\n\n// ============================================================================\n// OpenAI/xAI Responses API (with tools)\n// ============================================================================\n\n/**\n * Extracts text content from a Responses API output array.\n * Finds the first message-type output item and concatenates its text content blocks.\n * @internal\n */\nfunction extractResponsesApiText(output: Array<Record<string, unknown>>): Result<string> {\n for (const item of output) {\n if (item.type === 'message') {\n const messageResult = responsesApiMessage.validate(item as JsonObject);\n if (messageResult.isSuccess()) {\n return succeed(messageResult.value.content.map((c) => c.text).join(''));\n }\n }\n }\n return fail('Responses API output contained no message with text content');\n}\n\n/**\n * Calls the xAI/OpenAI Responses API with server-side tools.\n * Used when tools are configured for an openai-format provider.\n * @internal\n */\nasync function callOpenAiResponsesCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n tools: ReadonlyArray<AiServerToolConfig> = [],\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n maxTokens?: number\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/responses`;\n const input = buildMessages(prompt.system, buildOpenAiResponsesUserContent(prompt), {\n head\n });\n const effort = resolvedThinking?.openAiEffort ?? resolvedThinking?.xaiEffort;\n const body: Record<string, unknown> = {\n model: config.model,\n input,\n // `tools` is omitted entirely when none are requested — a Responses-only model routed\n // here for tier/model reasons (not tools) must not send an empty tools array.\n ...(tools.length > 0 ? { tools: toResponsesApiTools(tools) } : {}),\n // Temperature is sent only when the caller explicitly provided one (see callOpenAiCompletion).\n ...(temperature !== undefined ? { temperature } : {}),\n ...(effort !== undefined && config.model !== 'grok-4' ? { reasoning: { effort } } : {})\n };\n // Shared by OpenAI and xAI — both route through the Responses API with the same field name.\n if (maxTokens !== undefined) {\n body.max_output_tokens = maxTokens;\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n\n const headers: Record<string, string> = bearerAuthHeader(config.apiKey);\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`OpenAI Responses API: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return responsesApiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `Responses API response: ${msg}`)\n .onSuccess((response) => {\n return extractResponsesApiText(response.output).onSuccess((text) =>\n succeed({\n content: text,\n truncated: response.status === 'incomplete'\n })\n );\n });\n}\n\n// ============================================================================\n// Anthropic adapter\n// ============================================================================\n\n/**\n * Extracts text content from Anthropic response content blocks.\n * When tools are used, the content array contains mixed block types\n * (text, server_tool_use, web_search_tool_result). We extract and\n * concatenate only the text blocks.\n * @internal\n */\nfunction extractAnthropicText(content: unknown[]): Result<string> {\n const textParts: string[] = [];\n for (const block of content) {\n if (typeof block === 'object' && block !== null && 'type' in block) {\n const typed = block as Record<string, unknown>;\n if (typed.type === 'text' && typeof typed.text === 'string') {\n textParts.push(typed.text);\n }\n }\n }\n if (textParts.length === 0) {\n return fail('Anthropic response contained no text content blocks');\n }\n return succeed(textParts.join(''));\n}\n\n/** Calls the Anthropic Messages API with optional tool support. @internal */\nasync function callAnthropicCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n tools?: ReadonlyArray<AiServerToolConfig>,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n useAdaptiveThinking: boolean = false,\n maxTokens?: number\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/messages`;\n const messages = buildAnthropicMessages(prompt, { head });\n const body: Record<string, unknown> = {\n model: config.model,\n system: prompt.system,\n messages,\n // Anthropic's Messages API requires max_tokens on every request — see\n // AiAssist.DEFAULT_ANTHROPIC_MAX_TOKENS for why only this provider defaults it.\n max_tokens: maxTokens ?? DEFAULT_ANTHROPIC_MAX_TOKENS,\n // Temperature is sent only when explicitly provided (Claude-5 rejects any temperature). The\n // completion path rejects temperature + thinking upstream (checkTemperatureConflict), so no\n // effort gate is needed here.\n ...(temperature !== undefined ? { temperature } : {})\n };\n\n const effort = resolvedThinking?.anthropicEffort;\n if (effort !== undefined) {\n if (useAdaptiveThinking) {\n // Claude 5 family: adaptive thinking — no budget_tokens; effort moves to the\n // top-level output_config block. See AiAssist.isAdaptiveThinkingModel.\n body.thinking = { type: 'adaptive' };\n body.output_config = { effort };\n } else {\n body.thinking = { type: 'enabled', budget_tokens: anthropicEffortToBudgetTokens(effort) };\n }\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n\n if (tools && tools.length > 0) {\n body.tools = toAnthropicTools(tools);\n /* c8 ignore next 3 - optional logger diagnostic output */\n logger?.info(`Anthropic completion: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);\n } else {\n /* c8 ignore next 1 - optional logger */\n logger?.info(`Anthropic completion: model=${config.model}`);\n }\n\n const headers: Record<string, string> = anthropicAuthHeaders(config.apiKey);\n\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n\n const rawContent = (jsonResult.value as Record<string, unknown>).content;\n const stopReason = (jsonResult.value as Record<string, unknown>).stop_reason;\n if (!Array.isArray(rawContent)) {\n return fail('Anthropic API response: content is not an array');\n }\n if (typeof stopReason !== 'string') {\n return fail('Anthropic API response: stop_reason is missing or not a string');\n }\n return extractAnthropicText(rawContent).onSuccess((text) =>\n succeed({\n content: text,\n truncated: stopReason === 'max_tokens'\n })\n );\n}\n\n// ============================================================================\n// Google Gemini adapter\n// ============================================================================\n\n/**\n * Calls the Google Gemini generateContent API.\n * When tools are configured, includes Google Search grounding.\n * @internal\n */\nasync function callGeminiCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n tools?: ReadonlyArray<AiServerToolConfig>,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n maxTokens?: number\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/models/${config.model}:generateContent`;\n const contents = buildGeminiContents(prompt, { head });\n\n // Temperature is sent only when explicitly provided; otherwise Gemini's default applies.\n const generationConfig: Record<string, unknown> = {};\n if (temperature !== undefined) {\n generationConfig.temperature = temperature;\n }\n if (maxTokens !== undefined) {\n generationConfig.maxOutputTokens = maxTokens;\n }\n if (resolvedThinking?.geminiThinkingBudget !== undefined) {\n generationConfig.thinkingConfig = { thinkingBudget: resolvedThinking.geminiThinkingBudget };\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(generationConfig, resolvedThinking.otherParams);\n }\n const body: Record<string, unknown> = {\n systemInstruction: { parts: [{ text: prompt.system }] },\n contents,\n generationConfig\n };\n\n if (tools && tools.length > 0) {\n body.tools = toGeminiTools(tools);\n /* c8 ignore next 1 - optional logger */\n logger?.info(`Gemini completion: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);\n } else {\n /* c8 ignore next 1 - optional logger */\n logger?.info(`Gemini completion: model=${config.model}`);\n }\n\n const headers: Record<string, string> = geminiAuthHeader(config.apiKey);\n\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return geminiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `Gemini API response: ${msg}`)\n .onSuccess((response) => {\n const candidate = response.candidates[0];\n return succeed({\n content: candidate.content.parts[0].text,\n truncated: candidate.finishReason === 'MAX_TOKENS'\n });\n });\n}\n\n// ============================================================================\n// Provider dispatcher\n// ============================================================================\n\n/**\n * Calls the appropriate chat completion API for a given provider. Routes by\n * `apiFormat`: `'openai'` (xAI/OpenAI/Groq/Mistral — switches to Responses API\n * when tools are set), `'anthropic'`, or `'gemini'`.\n * @public\n */\nexport async function callProviderCompletion(\n params: IProviderCompletionParams\n): Promise<Result<IAiCompletionResponse>> {\n const {\n descriptor,\n apiKey,\n system,\n messages,\n temperature,\n modelOverride,\n tier,\n logger,\n tools,\n signal,\n endpoint,\n thinking,\n maxTokens\n } = params;\n\n const splitResult = splitChatRequest(system, messages);\n if (splitResult.isFailure()) {\n return fail(splitResult.message);\n }\n const { prompt, head } = splitResult.value;\n\n const baseUrlResult = resolveEffectiveBaseUrl(descriptor, endpoint);\n if (baseUrlResult.isFailure()) {\n return fail(baseUrlResult.message);\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 // The quality tier is the only completion-model selector; thinking and tools\n // are orthogonal request params/capabilities and never pick a model.\n const modelContext: ModelSpecKey | undefined = tier;\n\n const modelResult = resolveProviderModel(descriptor, modelOverride, modelContext);\n if (modelResult.isFailure()) {\n return fail(modelResult.message);\n }\n const model = modelResult.value;\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 config: IAiApiConfig = {\n baseUrl: baseUrlResult.value,\n apiKey,\n model\n };\n /* c8 ignore next 8 - optional logger diagnostic output */\n if (logger) {\n const toolTypes = hasTools ? tools.map((t) => t.type).join(',') : 'none';\n const supported = descriptor.supportedTools.length > 0 ? descriptor.supportedTools.join(',') : 'none';\n logger.info(\n `AI completion: provider=${descriptor.id}, format=${descriptor.apiFormat}, model=${config.model}, ` +\n `tools=${toolTypes}, supported=${supported}`\n );\n }\n\n switch (descriptor.apiFormat) {\n case 'openai':\n // Responses-API-only models (e.g. gpt-5.5-pro) 400 on /chat/completions, so they route\n // to the Responses path even with no tools requested — same path the tools case uses.\n if (hasTools || isResponsesOnlyModel(descriptor, config.model)) {\n return callOpenAiResponsesCompletion(\n config,\n prompt,\n tools,\n head,\n temperature,\n logger,\n signal,\n resolvedThinking,\n maxTokens\n );\n }\n return callOpenAiCompletion(\n config,\n prompt,\n head,\n temperature,\n logger,\n signal,\n resolvedThinking,\n maxTokens,\n usesMaxCompletionTokensField(descriptor)\n );\n case 'anthropic':\n return callAnthropicCompletion(\n config,\n prompt,\n head,\n temperature,\n logger,\n tools,\n signal,\n resolvedThinking,\n isAdaptiveThinkingModel(descriptor, config.model),\n maxTokens\n );\n case 'gemini':\n return callGeminiCompletion(\n config,\n prompt,\n head,\n temperature,\n logger,\n tools,\n signal,\n resolvedThinking,\n maxTokens\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\n// ============================================================================\n// Proxied completion (routes through a backend server)\n// ============================================================================\n\n/**\n * Calls the AI completion endpoint on a proxy server instead of calling the\n * provider API directly from the browser. The proxy handles provider dispatch,\n * CORS, and API key forwarding. The request body serializes the unified\n * {@link AiAssist.IChatRequest} shape (`system?` + `messages`). Enforces the same\n * non-empty / trailing-user-turn and image-input invariants as the direct path.\n * @param proxyUrl - Base URL of the proxy server\n * @param params - Same parameters as {@link callProviderCompletion}\n * @public\n */\nexport async function callProxiedCompletion(\n proxyUrl: string,\n params: IProviderCompletionParams\n): Promise<Result<IAiCompletionResponse>> {\n const {\n descriptor,\n apiKey,\n system,\n messages,\n temperature,\n modelOverride,\n logger,\n tools,\n signal,\n thinking,\n maxTokens\n } = params;\n\n const splitResult = splitChatRequest(system, messages);\n if (splitResult.isFailure()) {\n return fail(splitResult.message);\n }\n if (splitResult.value.prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {\n return fail(`provider \"${descriptor.id}\" does not accept image input`);\n }\n\n const body: Record<string, unknown> = {\n providerId: descriptor.id,\n apiKey,\n messages: normalizeOutboundMessages(splitResult.value)\n };\n // Temperature is forwarded only when explicitly provided, matching the direct path — the proxy\n // omits it from the upstream request so the provider default applies.\n if (temperature !== undefined) {\n body.temperature = temperature;\n }\n if (system !== undefined) {\n body.system = system;\n }\n if (modelOverride !== undefined) {\n body.modelOverride = modelOverride;\n }\n if (tools && tools.length > 0) {\n body.tools = tools;\n }\n if (thinking !== undefined) {\n body.thinking = thinking;\n }\n // Forwarded only when explicitly provided; the proxy is responsible for mapping it to the\n // correct upstream provider field (see AiAssist.usesMaxCompletionTokensField).\n if (maxTokens !== undefined) {\n body.maxTokens = maxTokens;\n }\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`AI proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);\n const url = `${proxyUrl}/api/ai/completion`;\n const jsonResult = await fetchJson(url, {}, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n\n const response = jsonResult.value as Record<string, unknown>;\n if (typeof response.error === 'string') {\n return fail(`proxy: ${response.error}`);\n }\n\n if (typeof response.content !== 'string') {\n return fail('proxy returned invalid response: missing content');\n }\n\n return succeed({\n content: response.content,\n truncated: response.truncated === true\n });\n}\n"]}