@fgv/ts-extras 5.1.0-4 → 5.1.0-40

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 (368) 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 +886 -158
  5. package/dist/packlets/ai-assist/apiClient.js.map +1 -0
  6. package/dist/packlets/ai-assist/chatRequestBuilders.js +282 -0
  7. package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  8. package/dist/packlets/ai-assist/converters.js +47 -3
  9. package/dist/packlets/ai-assist/converters.js.map +1 -0
  10. package/dist/packlets/ai-assist/embeddingClient.js +345 -0
  11. package/dist/packlets/ai-assist/embeddingClient.js.map +1 -0
  12. package/dist/packlets/ai-assist/endpoint.js +78 -0
  13. package/dist/packlets/ai-assist/endpoint.js.map +1 -0
  14. package/dist/packlets/ai-assist/http.js +75 -0
  15. package/dist/packlets/ai-assist/http.js.map +1 -0
  16. package/dist/packlets/ai-assist/imageOptionsResolver.js +193 -0
  17. package/dist/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  18. package/dist/packlets/ai-assist/index.js +10 -4
  19. package/dist/packlets/ai-assist/index.js.map +1 -0
  20. package/dist/packlets/ai-assist/jsonCompletion.js +93 -0
  21. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -0
  22. package/dist/packlets/ai-assist/jsonResponse.js +149 -0
  23. package/dist/packlets/ai-assist/jsonResponse.js.map +1 -0
  24. package/dist/packlets/ai-assist/model.js +193 -9
  25. package/dist/packlets/ai-assist/model.js.map +1 -0
  26. package/dist/packlets/ai-assist/registry.js +314 -12
  27. package/dist/packlets/ai-assist/registry.js.map +1 -0
  28. package/dist/packlets/ai-assist/sseParser.js +123 -0
  29. package/dist/packlets/ai-assist/sseParser.js.map +1 -0
  30. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +368 -0
  31. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  32. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +687 -0
  33. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  34. package/dist/packlets/ai-assist/streamingAdapters/common.js +187 -0
  35. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  36. package/dist/packlets/ai-assist/streamingAdapters/gemini.js +204 -0
  37. package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  38. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +170 -0
  39. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  40. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +386 -0
  41. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  42. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +173 -0
  43. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  44. package/dist/packlets/ai-assist/streamingClient.js +140 -0
  45. package/dist/packlets/ai-assist/streamingClient.js.map +1 -0
  46. package/dist/packlets/ai-assist/thinkingOptionsResolver.js +288 -0
  47. package/dist/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  48. package/dist/packlets/ai-assist/toolFormats.js +106 -10
  49. package/dist/packlets/ai-assist/toolFormats.js.map +1 -0
  50. package/dist/packlets/conversion/converters.js +35 -1
  51. package/dist/packlets/conversion/converters.js.map +1 -0
  52. package/dist/packlets/conversion/index.js.map +1 -0
  53. package/dist/packlets/crypto-utils/constants.js.map +1 -0
  54. package/dist/packlets/crypto-utils/converters.js +42 -4
  55. package/dist/packlets/crypto-utils/converters.js.map +1 -0
  56. package/dist/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  57. package/dist/packlets/crypto-utils/encryptedFile.js.map +1 -0
  58. package/dist/packlets/crypto-utils/hpkeProvider.js +333 -0
  59. package/dist/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  60. package/dist/packlets/crypto-utils/index.browser.js +10 -2
  61. package/dist/packlets/crypto-utils/index.browser.js.map +1 -0
  62. package/dist/packlets/crypto-utils/index.js +6 -0
  63. package/dist/packlets/crypto-utils/index.js.map +1 -0
  64. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js +71 -0
  65. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  66. package/dist/packlets/crypto-utils/keystore/converters.js +103 -11
  67. package/dist/packlets/crypto-utils/keystore/converters.js.map +1 -0
  68. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +287 -0
  69. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  70. package/dist/packlets/crypto-utils/keystore/index.browser.js +36 -0
  71. package/dist/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  72. package/dist/packlets/crypto-utils/keystore/index.js +3 -0
  73. package/dist/packlets/crypto-utils/keystore/index.js.map +1 -0
  74. package/dist/packlets/crypto-utils/keystore/keyStore.js +633 -118
  75. package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  76. package/dist/packlets/crypto-utils/keystore/model.js +22 -1
  77. package/dist/packlets/crypto-utils/keystore/model.js.map +1 -0
  78. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js +21 -0
  79. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  80. package/dist/packlets/crypto-utils/model.js +32 -0
  81. package/dist/packlets/crypto-utils/model.js.map +1 -0
  82. package/dist/packlets/crypto-utils/nodeCryptoProvider.js +270 -1
  83. package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  84. package/dist/packlets/crypto-utils/spkiHelpers.js +209 -0
  85. package/dist/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  86. package/dist/packlets/csv/csvFileHelpers.js +0 -14
  87. package/dist/packlets/csv/csvFileHelpers.js.map +1 -0
  88. package/dist/packlets/csv/csvHelpers.js +14 -0
  89. package/dist/packlets/csv/csvHelpers.js.map +1 -0
  90. package/dist/packlets/csv/index.browser.js +1 -3
  91. package/dist/packlets/csv/index.browser.js.map +1 -0
  92. package/dist/packlets/csv/index.js.map +1 -0
  93. package/dist/packlets/experimental/extendedArray.js.map +1 -0
  94. package/dist/packlets/experimental/formatter.js.map +1 -0
  95. package/dist/packlets/experimental/index.js.map +1 -0
  96. package/dist/packlets/experimental/rangeOf.js.map +1 -0
  97. package/dist/packlets/hash/index.browser.js.map +1 -0
  98. package/dist/packlets/hash/index.js.map +1 -0
  99. package/dist/packlets/hash/index.node.js.map +1 -0
  100. package/dist/packlets/hash/md5Normalizer.browser.js.map +1 -0
  101. package/dist/packlets/hash/md5Normalizer.js.map +1 -0
  102. package/dist/packlets/mustache/index.js.map +1 -0
  103. package/dist/packlets/mustache/interfaces.js.map +1 -0
  104. package/dist/packlets/mustache/mustacheTemplate.js +42 -4
  105. package/dist/packlets/mustache/mustacheTemplate.js.map +1 -0
  106. package/dist/packlets/record-jar/index.browser.js +1 -3
  107. package/dist/packlets/record-jar/index.browser.js.map +1 -0
  108. package/dist/packlets/record-jar/index.js.map +1 -0
  109. package/dist/packlets/record-jar/recordJarFileHelpers.js +0 -18
  110. package/dist/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  111. package/dist/packlets/record-jar/recordJarHelpers.js +18 -0
  112. package/dist/packlets/record-jar/recordJarHelpers.js.map +1 -0
  113. package/dist/packlets/yaml/converters.js.map +1 -0
  114. package/dist/packlets/yaml/index.js +1 -0
  115. package/dist/packlets/yaml/index.js.map +1 -0
  116. package/dist/packlets/yaml/serializers.js +48 -0
  117. package/dist/packlets/yaml/serializers.js.map +1 -0
  118. package/dist/packlets/zip-file-tree/index.js.map +1 -0
  119. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js +2 -2
  120. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  121. package/dist/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  122. package/dist/ts-extras.d.ts +3880 -105
  123. package/dist/tsdoc-metadata.json +1 -1
  124. package/lib/index.browser.d.ts +4 -2
  125. package/lib/index.browser.d.ts.map +1 -0
  126. package/lib/index.browser.js +8 -3
  127. package/lib/index.browser.js.map +1 -0
  128. package/lib/index.d.ts.map +1 -0
  129. package/lib/index.js.map +1 -0
  130. package/lib/packlets/ai-assist/apiClient.d.ts +115 -32
  131. package/lib/packlets/ai-assist/apiClient.d.ts.map +1 -0
  132. package/lib/packlets/ai-assist/apiClient.js +888 -156
  133. package/lib/packlets/ai-assist/apiClient.js.map +1 -0
  134. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +149 -0
  135. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -0
  136. package/lib/packlets/ai-assist/chatRequestBuilders.js +293 -0
  137. package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  138. package/lib/packlets/ai-assist/converters.d.ts +15 -1
  139. package/lib/packlets/ai-assist/converters.d.ts.map +1 -0
  140. package/lib/packlets/ai-assist/converters.js +47 -3
  141. package/lib/packlets/ai-assist/converters.js.map +1 -0
  142. package/lib/packlets/ai-assist/embeddingClient.d.ts +69 -0
  143. package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -0
  144. package/lib/packlets/ai-assist/embeddingClient.js +349 -0
  145. package/lib/packlets/ai-assist/embeddingClient.js.map +1 -0
  146. package/lib/packlets/ai-assist/endpoint.d.ts +28 -0
  147. package/lib/packlets/ai-assist/endpoint.d.ts.map +1 -0
  148. package/lib/packlets/ai-assist/endpoint.js +82 -0
  149. package/lib/packlets/ai-assist/endpoint.js.map +1 -0
  150. package/lib/packlets/ai-assist/http.d.ts +24 -0
  151. package/lib/packlets/ai-assist/http.d.ts.map +1 -0
  152. package/lib/packlets/ai-assist/http.js +78 -0
  153. package/lib/packlets/ai-assist/http.js.map +1 -0
  154. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts +66 -0
  155. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts.map +1 -0
  156. package/lib/packlets/ai-assist/imageOptionsResolver.js +197 -0
  157. package/lib/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  158. package/lib/packlets/ai-assist/index.d.ts +10 -4
  159. package/lib/packlets/ai-assist/index.d.ts.map +1 -0
  160. package/lib/packlets/ai-assist/index.js +36 -1
  161. package/lib/packlets/ai-assist/index.js.map +1 -0
  162. package/lib/packlets/ai-assist/jsonCompletion.d.ts +93 -0
  163. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -0
  164. package/lib/packlets/ai-assist/jsonCompletion.js +97 -0
  165. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -0
  166. package/lib/packlets/ai-assist/jsonResponse.d.ts +91 -0
  167. package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -0
  168. package/lib/packlets/ai-assist/jsonResponse.js +154 -0
  169. package/lib/packlets/ai-assist/jsonResponse.js.map +1 -0
  170. package/lib/packlets/ai-assist/model.d.ts +1202 -12
  171. package/lib/packlets/ai-assist/model.d.ts.map +1 -0
  172. package/lib/packlets/ai-assist/model.js +198 -10
  173. package/lib/packlets/ai-assist/model.js.map +1 -0
  174. package/lib/packlets/ai-assist/registry.d.ts +56 -1
  175. package/lib/packlets/ai-assist/registry.d.ts.map +1 -0
  176. package/lib/packlets/ai-assist/registry.js +319 -13
  177. package/lib/packlets/ai-assist/registry.js.map +1 -0
  178. package/lib/packlets/ai-assist/sseParser.d.ts +45 -0
  179. package/lib/packlets/ai-assist/sseParser.d.ts.map +1 -0
  180. package/lib/packlets/ai-assist/sseParser.js +128 -0
  181. package/lib/packlets/ai-assist/sseParser.js.map +1 -0
  182. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +72 -0
  183. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -0
  184. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +371 -0
  185. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  186. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +260 -0
  187. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -0
  188. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +694 -0
  189. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  190. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +154 -0
  191. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -0
  192. package/lib/packlets/ai-assist/streamingAdapters/common.js +193 -0
  193. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  194. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts +43 -0
  195. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -0
  196. package/lib/packlets/ai-assist/streamingAdapters/gemini.js +207 -0
  197. package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  198. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts +19 -0
  199. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts.map +1 -0
  200. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js +173 -0
  201. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  202. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +33 -0
  203. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -0
  204. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +389 -0
  205. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  206. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts +34 -0
  207. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -0
  208. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +176 -0
  209. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  210. package/lib/packlets/ai-assist/streamingClient.d.ts +50 -0
  211. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -0
  212. package/lib/packlets/ai-assist/streamingClient.js +146 -0
  213. package/lib/packlets/ai-assist/streamingClient.js.map +1 -0
  214. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts +87 -0
  215. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts.map +1 -0
  216. package/lib/packlets/ai-assist/thinkingOptionsResolver.js +294 -0
  217. package/lib/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  218. package/lib/packlets/ai-assist/toolFormats.d.ts +40 -9
  219. package/lib/packlets/ai-assist/toolFormats.d.ts.map +1 -0
  220. package/lib/packlets/ai-assist/toolFormats.js +107 -10
  221. package/lib/packlets/ai-assist/toolFormats.js.map +1 -0
  222. package/lib/packlets/conversion/converters.d.ts +8 -1
  223. package/lib/packlets/conversion/converters.d.ts.map +1 -0
  224. package/lib/packlets/conversion/converters.js +36 -2
  225. package/lib/packlets/conversion/converters.js.map +1 -0
  226. package/lib/packlets/conversion/index.d.ts.map +1 -0
  227. package/lib/packlets/conversion/index.js.map +1 -0
  228. package/lib/packlets/crypto-utils/constants.d.ts.map +1 -0
  229. package/lib/packlets/crypto-utils/constants.js.map +1 -0
  230. package/lib/packlets/crypto-utils/converters.d.ts +20 -1
  231. package/lib/packlets/crypto-utils/converters.d.ts.map +1 -0
  232. package/lib/packlets/crypto-utils/converters.js +43 -5
  233. package/lib/packlets/crypto-utils/converters.js.map +1 -0
  234. package/lib/packlets/crypto-utils/directEncryptionProvider.d.ts.map +1 -0
  235. package/lib/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  236. package/lib/packlets/crypto-utils/encryptedFile.d.ts.map +1 -0
  237. package/lib/packlets/crypto-utils/encryptedFile.js.map +1 -0
  238. package/lib/packlets/crypto-utils/hpkeProvider.d.ts +142 -0
  239. package/lib/packlets/crypto-utils/hpkeProvider.d.ts.map +1 -0
  240. package/lib/packlets/crypto-utils/hpkeProvider.js +337 -0
  241. package/lib/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  242. package/lib/packlets/crypto-utils/index.browser.d.ts +4 -1
  243. package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -0
  244. package/lib/packlets/crypto-utils/index.browser.js +21 -3
  245. package/lib/packlets/crypto-utils/index.browser.js.map +1 -0
  246. package/lib/packlets/crypto-utils/index.d.ts +3 -0
  247. package/lib/packlets/crypto-utils/index.d.ts.map +1 -0
  248. package/lib/packlets/crypto-utils/index.js +17 -1
  249. package/lib/packlets/crypto-utils/index.js.map +1 -0
  250. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts +54 -0
  251. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts.map +1 -0
  252. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js +74 -0
  253. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  254. package/lib/packlets/crypto-utils/keystore/converters.d.ts +68 -6
  255. package/lib/packlets/crypto-utils/keystore/converters.d.ts.map +1 -0
  256. package/lib/packlets/crypto-utils/keystore/converters.js +101 -9
  257. package/lib/packlets/crypto-utils/keystore/converters.js.map +1 -0
  258. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts +148 -0
  259. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts.map +1 -0
  260. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +324 -0
  261. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  262. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts +10 -0
  263. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts.map +1 -0
  264. package/lib/packlets/crypto-utils/keystore/index.browser.js +76 -0
  265. package/lib/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  266. package/lib/packlets/crypto-utils/keystore/index.d.ts +2 -0
  267. package/lib/packlets/crypto-utils/keystore/index.d.ts.map +1 -0
  268. package/lib/packlets/crypto-utils/keystore/index.js +5 -1
  269. package/lib/packlets/crypto-utils/keystore/index.js.map +1 -0
  270. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +205 -13
  271. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -0
  272. package/lib/packlets/crypto-utils/keystore/keyStore.js +639 -124
  273. package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  274. package/lib/packlets/crypto-utils/keystore/model.d.ts +275 -19
  275. package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -0
  276. package/lib/packlets/crypto-utils/keystore/model.js +24 -2
  277. package/lib/packlets/crypto-utils/keystore/model.js.map +1 -0
  278. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts +53 -0
  279. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts.map +1 -0
  280. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js +22 -0
  281. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  282. package/lib/packlets/crypto-utils/model.d.ts +348 -10
  283. package/lib/packlets/crypto-utils/model.d.ts.map +1 -0
  284. package/lib/packlets/crypto-utils/model.js +33 -1
  285. package/lib/packlets/crypto-utils/model.js.map +1 -0
  286. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts +110 -2
  287. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -0
  288. package/lib/packlets/crypto-utils/nodeCryptoProvider.js +269 -0
  289. package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  290. package/lib/packlets/crypto-utils/spkiHelpers.d.ts +110 -0
  291. package/lib/packlets/crypto-utils/spkiHelpers.d.ts.map +1 -0
  292. package/lib/packlets/crypto-utils/spkiHelpers.js +219 -0
  293. package/lib/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  294. package/lib/packlets/csv/csvFileHelpers.d.ts +0 -10
  295. package/lib/packlets/csv/csvFileHelpers.d.ts.map +1 -0
  296. package/lib/packlets/csv/csvFileHelpers.js +0 -15
  297. package/lib/packlets/csv/csvFileHelpers.js.map +1 -0
  298. package/lib/packlets/csv/csvHelpers.d.ts +10 -0
  299. package/lib/packlets/csv/csvHelpers.d.ts.map +1 -0
  300. package/lib/packlets/csv/csvHelpers.js +15 -0
  301. package/lib/packlets/csv/csvHelpers.js.map +1 -0
  302. package/lib/packlets/csv/index.browser.d.ts +0 -1
  303. package/lib/packlets/csv/index.browser.d.ts.map +1 -0
  304. package/lib/packlets/csv/index.browser.js +1 -5
  305. package/lib/packlets/csv/index.browser.js.map +1 -0
  306. package/lib/packlets/csv/index.d.ts.map +1 -0
  307. package/lib/packlets/csv/index.js.map +1 -0
  308. package/lib/packlets/experimental/extendedArray.d.ts.map +1 -0
  309. package/lib/packlets/experimental/extendedArray.js.map +1 -0
  310. package/lib/packlets/experimental/formatter.d.ts.map +1 -0
  311. package/lib/packlets/experimental/formatter.js.map +1 -0
  312. package/lib/packlets/experimental/index.d.ts.map +1 -0
  313. package/lib/packlets/experimental/index.js.map +1 -0
  314. package/lib/packlets/experimental/rangeOf.d.ts.map +1 -0
  315. package/lib/packlets/experimental/rangeOf.js.map +1 -0
  316. package/lib/packlets/hash/index.browser.d.ts.map +1 -0
  317. package/lib/packlets/hash/index.browser.js.map +1 -0
  318. package/lib/packlets/hash/index.d.ts.map +1 -0
  319. package/lib/packlets/hash/index.js.map +1 -0
  320. package/lib/packlets/hash/index.node.d.ts.map +1 -0
  321. package/lib/packlets/hash/index.node.js.map +1 -0
  322. package/lib/packlets/hash/md5Normalizer.browser.d.ts.map +1 -0
  323. package/lib/packlets/hash/md5Normalizer.browser.js.map +1 -0
  324. package/lib/packlets/hash/md5Normalizer.d.ts.map +1 -0
  325. package/lib/packlets/hash/md5Normalizer.js.map +1 -0
  326. package/lib/packlets/mustache/index.d.ts +1 -1
  327. package/lib/packlets/mustache/index.d.ts.map +1 -0
  328. package/lib/packlets/mustache/index.js.map +1 -0
  329. package/lib/packlets/mustache/interfaces.d.ts +34 -0
  330. package/lib/packlets/mustache/interfaces.d.ts.map +1 -0
  331. package/lib/packlets/mustache/interfaces.js.map +1 -0
  332. package/lib/packlets/mustache/mustacheTemplate.d.ts +2 -0
  333. package/lib/packlets/mustache/mustacheTemplate.d.ts.map +1 -0
  334. package/lib/packlets/mustache/mustacheTemplate.js +42 -4
  335. package/lib/packlets/mustache/mustacheTemplate.js.map +1 -0
  336. package/lib/packlets/record-jar/index.browser.d.ts +0 -1
  337. package/lib/packlets/record-jar/index.browser.d.ts.map +1 -0
  338. package/lib/packlets/record-jar/index.browser.js +1 -5
  339. package/lib/packlets/record-jar/index.browser.js.map +1 -0
  340. package/lib/packlets/record-jar/index.d.ts.map +1 -0
  341. package/lib/packlets/record-jar/index.js.map +1 -0
  342. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts +0 -11
  343. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts.map +1 -0
  344. package/lib/packlets/record-jar/recordJarFileHelpers.js +0 -19
  345. package/lib/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  346. package/lib/packlets/record-jar/recordJarHelpers.d.ts +11 -0
  347. package/lib/packlets/record-jar/recordJarHelpers.d.ts.map +1 -0
  348. package/lib/packlets/record-jar/recordJarHelpers.js +19 -0
  349. package/lib/packlets/record-jar/recordJarHelpers.js.map +1 -0
  350. package/lib/packlets/yaml/converters.d.ts.map +1 -0
  351. package/lib/packlets/yaml/converters.js.map +1 -0
  352. package/lib/packlets/yaml/index.d.ts +1 -0
  353. package/lib/packlets/yaml/index.d.ts.map +1 -0
  354. package/lib/packlets/yaml/index.js +1 -0
  355. package/lib/packlets/yaml/index.js.map +1 -0
  356. package/lib/packlets/yaml/serializers.d.ts +45 -0
  357. package/lib/packlets/yaml/serializers.d.ts.map +1 -0
  358. package/lib/packlets/yaml/serializers.js +84 -0
  359. package/lib/packlets/yaml/serializers.js.map +1 -0
  360. package/lib/packlets/zip-file-tree/index.d.ts.map +1 -0
  361. package/lib/packlets/zip-file-tree/index.js.map +1 -0
  362. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts +2 -2
  363. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts.map +1 -0
  364. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js +2 -2
  365. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  366. package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts.map +1 -0
  367. package/lib/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  368. package/package.json +20 -15
@@ -3,6 +3,50 @@
3
3
  * @packageDocumentation
4
4
  */
5
5
  import { type Result } from '@fgv/ts-utils';
6
+ import { type JsonObject, type JsonSchema } from '@fgv/ts-json-base';
7
+ /**
8
+ * Universal image representation used for both image input (vision prompts)
9
+ * and image output (generation responses).
10
+ *
11
+ * @remarks
12
+ * The base64 string is raw — no `data:` URL prefix. Use {@link AiAssist.toDataUrl} to
13
+ * format it for browser-display contexts.
14
+ *
15
+ * @public
16
+ */
17
+ export interface IAiImageData {
18
+ /** MIME type, e.g. `'image/png'`, `'image/jpeg'`, `'image/webp'`. */
19
+ readonly mimeType: string;
20
+ /** Base64-encoded image bytes (no `data:` prefix). */
21
+ readonly base64: string;
22
+ }
23
+ /**
24
+ * Formats an {@link IAiImageData} as a `data:` URL suitable for browser display.
25
+ * @param image - The image to format
26
+ * @returns A `data:<mime>;base64,<data>` URL string
27
+ * @public
28
+ */
29
+ export declare function toDataUrl(image: IAiImageData): string;
30
+ /**
31
+ * Image attachment for a vision (image-input) prompt.
32
+ *
33
+ * @remarks
34
+ * Extends {@link IAiImageData} with an OpenAI-specific `detail` hint that is
35
+ * silently ignored by Anthropic, Gemini, and other providers.
36
+ *
37
+ * @public
38
+ */
39
+ export interface IAiImageAttachment extends IAiImageData {
40
+ /**
41
+ * OpenAI vision detail hint:
42
+ * - `'low'`: faster, cheaper, lower fidelity
43
+ * - `'high'`: slower, more expensive, higher fidelity
44
+ * - `'auto'` (default): provider chooses
45
+ *
46
+ * Ignored by providers other than OpenAI.
47
+ */
48
+ readonly detail?: 'low' | 'high' | 'auto';
49
+ }
6
50
  /**
7
51
  * A structured AI prompt with system/user split for direct API calls,
8
52
  * and a lazily-constructed combined version for copy/paste workflows.
@@ -13,9 +57,28 @@ export declare class AiPrompt {
13
57
  readonly system: string;
14
58
  /** User request: the specific entity generation request. */
15
59
  readonly user: string;
16
- constructor(user: string, system: string);
17
- /** Combined single-string version (user + system joined) for copy/paste. */
60
+ /**
61
+ * Optional image attachments. When present, vision-capable providers will
62
+ * include them in the user message; non-vision providers will reject the
63
+ * call up front (see {@link AiAssist.IAiProviderDescriptor.acceptsImageInput}).
64
+ */
65
+ readonly attachments: ReadonlyArray<IAiImageAttachment>;
66
+ constructor(user: string, system: string, attachments?: ReadonlyArray<IAiImageAttachment>);
67
+ /**
68
+ * Combined single-string version (user + system joined) for copy/paste.
69
+ * When attachments are present, includes a sentinel noting they aren't
70
+ * part of the copied text.
71
+ */
18
72
  get combined(): string;
73
+ /**
74
+ * Lowers this prompt to the unified {@link AiAssist.IChatRequest} shape consumed
75
+ * by the turn entry points (`callProviderCompletion`,
76
+ * `callProviderCompletionStream`, `generateJsonCompletion`,
77
+ * `executeClientToolTurn`). The prompt becomes a single current `user` turn
78
+ * (carrying any attachments) with the system instructions in the distinct
79
+ * `system` field.
80
+ */
81
+ toRequest(): IChatRequest;
19
82
  }
20
83
  /**
21
84
  * A single chat message in OpenAI format.
@@ -26,6 +89,40 @@ export interface IChatMessage {
26
89
  readonly role: 'system' | 'user' | 'assistant';
27
90
  /** Message content */
28
91
  readonly content: string;
92
+ /**
93
+ * Optional image attachments. Only honoured on the **current turn** (the last
94
+ * message of an {@link AiAssist.IChatRequest}); vision-capable providers include
95
+ * them in that user message, non-vision providers reject the call up front (see
96
+ * {@link AiAssist.IAiProviderDescriptor.acceptsImageInput}). Attachments on
97
+ * history (non-final) messages are ignored.
98
+ */
99
+ readonly attachments?: ReadonlyArray<IAiImageAttachment>;
100
+ }
101
+ /**
102
+ * An ordered chat request: optional system instructions plus the conversation
103
+ * turns. The **last** entry in `messages` is the current turn (always a `user`
104
+ * turn); everything before it is prior conversation history.
105
+ *
106
+ * @remarks
107
+ * This is the unified shape accepted by every turn entry point. Both the
108
+ * completion path and the client-tool turn path linearize it identically:
109
+ * `[system, ...history, current user turn, ...continuation]`. Keeping `system`
110
+ * as a distinct field (rather than a `system`-role message) matches how the
111
+ * per-provider request builders already separate system from the turn list
112
+ * (Anthropic top-level `system`, Gemini `systemInstruction`, OpenAI a leading
113
+ * `system`-role message). `messages` should therefore carry only `user` /
114
+ * `assistant` turns.
115
+ *
116
+ * @public
117
+ */
118
+ export interface IChatRequest {
119
+ /** System instructions (schema docs, format rules, general guidance). */
120
+ readonly system?: string;
121
+ /**
122
+ * The ordered conversation turns. Must be non-empty; the last entry is the
123
+ * current `user` turn and the preceding entries are history.
124
+ */
125
+ readonly messages: ReadonlyArray<IChatMessage>;
29
126
  }
30
127
  /**
31
128
  * Built-in server-side tool types supported across providers.
@@ -69,11 +166,230 @@ export interface IAiToolEnablement {
69
166
  /** Optional tool-specific configuration. */
70
167
  readonly config?: AiServerToolConfig;
71
168
  }
169
+ /**
170
+ * Behavior annotations for a client-defined tool.
171
+ *
172
+ * @remarks
173
+ * These are **host-advisory-only hints** describing a tool's side-effect profile.
174
+ * They are consumed by the host's tool loop (e.g. a before-execute gate) and are
175
+ * **never serialized to the model** — the provider wire tool-schemas whitelist
176
+ * `{name, description, parameters}` and ignore this field.
177
+ *
178
+ * Field names mirror MCP's `ToolAnnotations` (`@modelcontextprotocol/sdk`) 1:1 so
179
+ * an MCP tool's annotations pass through unchanged. Per the MCP spec, all fields
180
+ * are hints — a host should never make tool-use decisions based on annotations
181
+ * received from an untrusted server without its own validation.
182
+ *
183
+ * @public
184
+ */
185
+ export interface IAiToolAnnotations {
186
+ /** Optional human-readable display title for the tool. */
187
+ readonly title?: string;
188
+ /** Hint: the tool does not modify its environment (read-only). */
189
+ readonly readOnlyHint?: boolean;
190
+ /** Hint: the tool may perform destructive updates (only meaningful when not read-only). */
191
+ readonly destructiveHint?: boolean;
192
+ /** Hint: repeated calls with the same arguments have no additional effect. */
193
+ readonly idempotentHint?: boolean;
194
+ /** Hint: the tool interacts with an open world of external entities. */
195
+ readonly openWorldHint?: boolean;
196
+ }
197
+ /**
198
+ * Configuration for a client-defined (harness-supplied) tool.
199
+ *
200
+ * @remarks
201
+ * The `parametersSchema` is the single source of truth for both the wire-format
202
+ * JSON Schema sent to the provider (via `.toJson()`) and the runtime argument
203
+ * validation (via `.validate(rawArgs)`). Use `JsonSchema.object(...)` from
204
+ * `@fgv/ts-json-base` to author the schema as a const (e.g. `const mySchema = JsonSchema.object({...})`);
205
+ * the static type `TParams` is then derived via `JsonSchema.Static<typeof mySchema>` —
206
+ * no drift between wire schema and runtime validation.
207
+ *
208
+ * @public
209
+ */
210
+ export interface IAiClientToolConfig<TParams = unknown> {
211
+ /** Discriminator — always `'client_tool'`. */
212
+ readonly type: 'client_tool';
213
+ /** Tool name sent to the model (must be unique within a call). */
214
+ readonly name: string;
215
+ /** Human-readable description of what the tool does, shown to the model. */
216
+ readonly description: string;
217
+ /**
218
+ * JSON Schema validator for the tool's parameters. Emits wire format via
219
+ * `.toJson()` and validates model-returned args via `.validate(rawArgs)`.
220
+ */
221
+ readonly parametersSchema: JsonSchema.ISchemaValidator<TParams>;
222
+ /**
223
+ * Optional host-advisory behavior annotations (read-only / destructive /
224
+ * idempotent / open-world hints + display title). Consumed by the host's
225
+ * tool loop; never serialized to the model. See {@link IAiToolAnnotations}.
226
+ */
227
+ readonly annotations?: IAiToolAnnotations;
228
+ }
229
+ /**
230
+ * A client-defined tool: configuration + execution callback pair.
231
+ *
232
+ * @remarks
233
+ * The `execute` callback receives typed `TParams` (already validated by
234
+ * `config.parametersSchema.validate()`) and returns a `Promise<Result<unknown>>`.
235
+ * Thrown errors are caught via `captureAsyncResult` in the round-trip helper.
236
+ *
237
+ * @public
238
+ */
239
+ export interface IAiClientTool<TParams = unknown> {
240
+ /** The tool's configuration (name, description, parameters schema). */
241
+ readonly config: IAiClientToolConfig<TParams>;
242
+ /**
243
+ * Execute the tool with validated parameters.
244
+ * @param args - Typed arguments, already validated against `config.parametersSchema`.
245
+ * @returns A `Promise<Result<unknown>>` — the result is stringified and sent back to the model.
246
+ */
247
+ readonly execute: (args: TParams) => Promise<Result<unknown>>;
248
+ }
249
+ /**
250
+ * Union of all tool configurations: server-side or client-defined.
251
+ * Discriminated on `type`.
252
+ * @public
253
+ */
254
+ export type AiToolConfig = AiServerToolConfig | IAiClientToolConfig;
255
+ /**
256
+ * Emitted when a client-defined tool call begins streaming. Carries the tool name
257
+ * and optional provider-assigned call ID (Anthropic / OpenAI Responses API; absent
258
+ * for Gemini which does not assign call IDs).
259
+ * @public
260
+ */
261
+ export interface IAiStreamToolUseStart {
262
+ readonly type: 'client-tool-call-start';
263
+ /** The name of the client tool being called. */
264
+ readonly toolName: string;
265
+ /**
266
+ * Provider-assigned call identifier (Anthropic: `toolu_*`; OpenAI: `call_*`).
267
+ * Absent for Gemini (correlation by name).
268
+ */
269
+ readonly callId?: string;
270
+ }
271
+ /**
272
+ * Emitted when a client-defined tool call is complete and its arguments are fully
273
+ * accumulated. The `args` object is the fully parsed JSON object — no further
274
+ * streaming deltas follow for this call.
275
+ * @public
276
+ */
277
+ export interface IAiStreamToolUseDelta {
278
+ readonly type: 'client-tool-call-done';
279
+ /** The name of the client tool being called. */
280
+ readonly toolName: string;
281
+ /**
282
+ * Provider-assigned call identifier. Absent for Gemini.
283
+ */
284
+ readonly callId?: string;
285
+ /** The fully accumulated and parsed tool arguments. */
286
+ readonly args: JsonObject;
287
+ }
288
+ /**
289
+ * Emitted after a client-defined tool has been executed and the result is ready
290
+ * to be fed back to the model in the round-trip continuation.
291
+ * @public
292
+ */
293
+ export interface IAiStreamToolUseComplete {
294
+ readonly type: 'client-tool-result';
295
+ /** The name of the client tool that was executed. */
296
+ readonly toolName: string;
297
+ /**
298
+ * Provider-assigned call identifier. Absent for Gemini.
299
+ */
300
+ readonly callId?: string;
301
+ /** The stringified result returned by the tool's execute callback. */
302
+ readonly result: string;
303
+ /** Whether the tool execution failed (schema validation failure, execute error, or unknown tool). */
304
+ readonly isError: boolean;
305
+ }
306
+ /**
307
+ * Summary of a single client tool call within a turn: the tool name, call ID,
308
+ * raw arguments, execution result, and whether the execution was an error.
309
+ * @public
310
+ */
311
+ export interface IAiClientToolCallSummary {
312
+ /** The name of the tool that was called. */
313
+ readonly toolName: string;
314
+ /** Provider-assigned call identifier (absent for Gemini). */
315
+ readonly callId?: string;
316
+ /** The fully accumulated raw arguments object as parsed JSON. */
317
+ readonly args: JsonObject;
318
+ /** The stringified result (success value or error message). */
319
+ readonly result: string;
320
+ /** Whether execution failed (schema validation failure, execute error, or unknown tool). */
321
+ readonly isError: boolean;
322
+ }
323
+ /**
324
+ * The provider-specific continuation data needed to build the follow-up request
325
+ * for the next round of the conversation.
326
+ *
327
+ * @remarks
328
+ * `messages` are provider-native request objects (Anthropic: content-block arrays,
329
+ * OpenAI Responses API: input items, Gemini: content parts). The continuation
330
+ * builder in `clientToolContinuationBuilder.ts` populates this.
331
+ *
332
+ * @public
333
+ */
334
+ export interface IAiClientToolContinuation {
335
+ /**
336
+ * **Cumulative** provider-native wire-format message objects covering all
337
+ * tool rounds so far. On each turn, `executeClientToolTurn` prepends the
338
+ * inbound `continuationMessages` so that this array always contains the
339
+ * complete wire tail from round 1 through the current round.
340
+ *
341
+ * To drive a multi-round loop, simply **replace** `continuationMessages`
342
+ * with this value — do not manually concatenate:
343
+ *
344
+ * ```ts
345
+ * let tail: JsonObject[] | undefined;
346
+ * while (true) {
347
+ * const { events, nextTurn } = executeClientToolTurn({
348
+ * ..., continuationMessages: tail
349
+ * }).orThrow();
350
+ * for await (const e of events) { /* observe *\/ }
351
+ * const outcome = (await nextTurn).orThrow();
352
+ * if (!outcome.continuation) break;
353
+ * tail = [...outcome.continuation.messages]; // replace — already cumulative
354
+ * }
355
+ * ```
356
+ *
357
+ * The exact shape is provider-native and may include provider-specific
358
+ * blocks (e.g. Anthropic thinking/redacted_thinking/tool_use, OpenAI
359
+ * function_call/function_call_output items, Gemini functionCall/functionResponse
360
+ * parts). These are NOT `IChatMessage[]` and must NOT be placed in the
361
+ * `messages` parameter — the normalized-message path strips provider-native
362
+ * fields (thinking signatures, redacted_thinking data) that the server
363
+ * requires for continuation validation.
364
+ *
365
+ * `toolCallsSummary` is per-round only (the calls executed in the current
366
+ * turn). Only `messages` is cumulative.
367
+ */
368
+ readonly messages: ReadonlyArray<JsonObject>;
369
+ /** Summary of each tool call executed in this turn (per-round, not cumulative). */
370
+ readonly toolCallsSummary: ReadonlyArray<IAiClientToolCallSummary>;
371
+ }
372
+ /**
373
+ * The result of a single client-tool turn: the optional continuation for the next
374
+ * call (absent when no tool calls occurred) and whether the stream was truncated.
375
+ * @public
376
+ */
377
+ export interface IAiClientToolTurnResult {
378
+ /**
379
+ * The continuation data for the next round-trip. `undefined` when the model
380
+ * completed without invoking any client tools.
381
+ */
382
+ readonly continuation: IAiClientToolContinuation | undefined;
383
+ /** Whether the stream was truncated (token limit or stop reason). */
384
+ readonly truncated: boolean;
385
+ /** The full concatenated text from all `text-delta` events in this turn. */
386
+ readonly fullText: string;
387
+ }
72
388
  /**
73
389
  * Known context keys for model specification maps.
74
390
  * @public
75
391
  */
76
- export type ModelSpecKey = 'base' | 'tools' | 'image';
392
+ export type ModelSpecKey = 'base' | 'advanced' | 'frontier' | 'image' | 'embedding';
77
393
  /**
78
394
  * All valid {@link ModelSpecKey} values.
79
395
  * @public
@@ -91,18 +407,18 @@ export declare const MODEL_SPEC_BASE_KEY: ModelSpecKey;
91
407
  * @remarks
92
408
  * A bare string is equivalent to `{ base: string }`. This keeps the simple
93
409
  * case simple while allowing context-aware model selection (e.g. different
94
- * models for tool-augmented vs. base completions).
410
+ * models for different quality tiers).
95
411
  *
96
412
  * @example
97
413
  * ```typescript
98
414
  * // Simple — same model for all contexts:
99
- * const simple: ModelSpec = 'grok-4-1-fast';
415
+ * const simple: ModelSpec = 'grok-4.3';
100
416
  *
101
- * // Context-aware — reasoning model when tools are active:
102
- * const split: ModelSpec = { base: 'grok-4-1-fast', tools: 'grok-4-1-fast-reasoning' };
417
+ * // Context-aware — different model per quality tier:
418
+ * const split: ModelSpec = { base: 'gpt-5.4-mini', advanced: 'gpt-5.5', frontier: 'gpt-5.5-pro' };
103
419
  *
104
- * // Future nested per-tool model selection:
105
- * const nested: ModelSpec = { base: 'grok-fast', tools: { base: 'grok-r', image: 'grok-v' } };
420
+ * // Nesteda tier branch is itself a spec:
421
+ * const nested: ModelSpec = { base: 'grok-fast', advanced: { base: 'grok-r', image: 'grok-v' } };
106
422
  * ```
107
423
  * @public
108
424
  */
@@ -119,26 +435,147 @@ export type ModelSpec = string | IModelSpecMap;
119
435
  * @remarks
120
436
  * Resolution rules:
121
437
  * 1. If the spec is a string, return it directly (context is irrelevant).
122
- * 2. If the spec is an object and the context key exists, recurse into that branch.
438
+ * 2. If the spec is an object, walk the ordered candidate keys for the context:
439
+ * a quality-tier context (`advanced`/`frontier`) cascades through the
440
+ * tier-fallback table (`frontier → advanced → base`, `advanced → base`);
441
+ * every other context resolves flat (`[context]`); `undefined` resolves to
442
+ * the shared `base` fallback. The first present key wins.
123
443
  * 3. Otherwise, fall back to the {@link MODEL_SPEC_BASE_KEY | 'base'} key.
124
444
  * 4. If neither context nor `'base'` exists, use the first available value.
125
445
  *
126
446
  * @param spec - The model specification to resolve
127
- * @param context - Optional context key (e.g. `'tools'`)
447
+ * @param context - Optional context key (e.g. `'advanced'`)
128
448
  * @returns The resolved model string
129
449
  * @public
130
450
  */
131
451
  export declare function resolveModel(spec: ModelSpec, context?: string): string;
452
+ /**
453
+ * Canonical fgv alias → concrete provider model map.
454
+ *
455
+ * @remarks
456
+ * Keys are full fgv aliases (`@<providerId>:<role>`, e.g. `@google-gemini:flash`);
457
+ * values are the current concrete provider model id (or a provider-native alias,
458
+ * which is resolved with one further indirection hop). Additive; absence of an
459
+ * `aliases` field on a descriptor means "this provider defines no aliases" and
460
+ * every model string passes through verbatim.
461
+ * @public
462
+ */
463
+ export interface IModelAliasMap {
464
+ readonly [alias: string]: string;
465
+ }
466
+ /**
467
+ * Marker prefix for an fgv model alias.
468
+ *
469
+ * @remarks
470
+ * A model string is an fgv alias **iff** it begins with this sigil. Everything
471
+ * else is a raw provider model id and passes through {@link resolveModelAlias}
472
+ * untouched — this is what keeps the alias layer back-compatible (no current
473
+ * `defaultModel`, `modelOverride`, or self-hosted `model:tag` id starts with `@`).
474
+ * @public
475
+ */
476
+ export declare const MODEL_ALIAS_SIGIL: '@';
477
+ /**
478
+ * Resolves a single (possibly-aliased) model string against a provider descriptor.
479
+ *
480
+ * @remarks
481
+ * Resolution rules:
482
+ * 1. No leading {@link MODEL_ALIAS_SIGIL} → raw provider id, returned verbatim.
483
+ * 2. Leading sigil + registered in `descriptor.aliases` → the registered target,
484
+ * which is itself resolved — so a chain of `@` aliases is followed until a
485
+ * non-`@` (concrete provider) id is reached. The canonical case is a single
486
+ * hop (an fgv alias targeting a provider-native alias), but longer chains
487
+ * resolve too.
488
+ * 3. Leading sigil + unregistered → fails loudly, naming the provider and alias.
489
+ *
490
+ * An `@`→`@` cycle is guarded by a visited-set and fails rather than exhausting
491
+ * the stack.
492
+ *
493
+ * @param descriptor - The provider descriptor whose `aliases` map is consulted.
494
+ * @param model - The (possibly-aliased) model string to resolve.
495
+ * @returns `Result` with the concrete provider model id, or a failure.
496
+ * @public
497
+ */
498
+ export declare function resolveModelAlias(descriptor: IAiProviderDescriptor, model: string): Result<string>;
499
+ /**
500
+ * The full provider model-resolution chokepoint: the {@link ModelSpecKey} walk
501
+ * (via {@link resolveModel}) THEN {@link resolveModelAlias}.
502
+ *
503
+ * @remarks
504
+ * Replaces the bare `resolveModel(modelOverride ?? descriptor.defaultModel, context)`
505
+ * call plus the duplicated empty-result check at each call-time chokepoint. The
506
+ * `ModelSpec` branch is selected first; the resulting string — which may itself
507
+ * be an fgv alias — is then resolved to a concrete id.
508
+ *
509
+ * @param descriptor - The provider descriptor (supplies `defaultModel` and `aliases`).
510
+ * @param modelOverride - An optional caller-supplied `ModelSpec` that takes precedence
511
+ * over `descriptor.defaultModel`. May itself contain or be an alias.
512
+ * @param context - Optional {@link ModelSpecKey} selecting the spec branch.
513
+ * @returns `Result` with the concrete provider model id, or a failure.
514
+ * @public
515
+ */
516
+ export declare function resolveProviderModel(descriptor: IAiProviderDescriptor, modelOverride: ModelSpec | undefined, context?: ModelSpecKey): Result<string>;
517
+ /**
518
+ * Determines whether a concrete (already-resolved) model id must be invoked via
519
+ * the OpenAI Responses API rather than chat completions.
520
+ *
521
+ * @remarks
522
+ * Matches `modelId` against the descriptor's
523
+ * {@link IAiProviderDescriptor.responsesOnlyModelPrefixes} by prefix. A provider
524
+ * that declares no list (the common case) always returns `false`. Consulted by
525
+ * both the completion (`callProviderCompletion`) and streaming
526
+ * (`callProviderCompletionStream`) OpenAI dispatch branches so a Responses-only
527
+ * model (e.g. `gpt-5.5-pro`) routes correctly even with no tools requested.
528
+ *
529
+ * @param descriptor - The provider descriptor supplying the prefix list.
530
+ * @param modelId - The resolved concrete model id to test.
531
+ * @returns `true` when `modelId` starts with any declared Responses-only prefix.
532
+ * @public
533
+ */
534
+ export declare function isResponsesOnlyModel(descriptor: IAiProviderDescriptor, modelId: string): boolean;
132
535
  /**
133
536
  * All known AI provider identifiers.
134
537
  * @public
135
538
  */
136
- export type AiProviderId = 'copy-paste' | 'xai-grok' | 'openai' | 'anthropic' | 'google-gemini' | 'groq' | 'mistral';
539
+ export type AiProviderId = 'copy-paste' | 'xai-grok' | 'openai' | 'openai-compat' | 'anthropic' | 'google-gemini' | 'groq' | 'mistral' | 'ollama';
137
540
  /**
138
541
  * API format categories for provider routing.
139
542
  * @public
140
543
  */
141
544
  export type AiApiFormat = 'openai' | 'anthropic' | 'gemini';
545
+ /**
546
+ * API format categories for image-generation provider routing.
547
+ *
548
+ * @remarks
549
+ * - `'openai-images'` — OpenAI Images API. Routes to `/images/generations`
550
+ * (text-only) or `/images/edits` (when reference images are present).
551
+ * - `'xai-images'` — xAI Images API. Text-only JSON generation request.
552
+ * - `'xai-images-edits'` — xAI Images API for Grok Imagine models. Uses JSON
553
+ * body with `{ type: "image_url" }` objects (not multipart).
554
+ * - `'gemini-image-out'` — Google Gemini chat-style `:generateContent`
555
+ * endpoint that returns image parts (Gemini Flash Image / "Nano
556
+ * Banana"). Accepts reference images.
557
+ *
558
+ * @public
559
+ */
560
+ export type AiImageApiFormat = 'openai-images' | 'xai-images' | 'xai-images-edits' | 'gemini-image-out';
561
+ /**
562
+ * API format categories for embedding provider routing.
563
+ *
564
+ * @remarks
565
+ * - `'openai-embeddings'` — OpenAI `/v1/embeddings` shape. Serves OpenAI,
566
+ * Ollama (via `/v1`), openai-compat self-hosted servers (vLLM, LM Studio,
567
+ * llama.cpp's openai-server), and Mistral (`mistral-embed`) — all of which
568
+ * speak the same request/response shape.
569
+ * - `'gemini-embeddings'` — Google Gemini `:batchEmbedContents` endpoint. A
570
+ * genuinely divergent shape (different route, auth header, request body, and
571
+ * the `taskType` retrieval-asymmetry knob that has no OpenAI analog).
572
+ *
573
+ * Named with the `ApiFormat` suffix for symmetry with `AiApiFormat` and
574
+ * `AiImageApiFormat`.
575
+ *
576
+ * @public
577
+ */
578
+ export type AiEmbeddingApiFormat = 'openai-embeddings' | 'gemini-embeddings';
142
579
  /**
143
580
  * Result of an AI provider completion call.
144
581
  * @public
@@ -149,6 +586,87 @@ export interface IAiCompletionResponse {
149
586
  /** Whether the response was truncated due to token limits */
150
587
  readonly truncated: boolean;
151
588
  }
589
+ /**
590
+ * A text-content delta arriving during a streaming completion.
591
+ * @public
592
+ */
593
+ export interface IAiStreamTextDelta {
594
+ readonly type: 'text-delta';
595
+ /** The newly arrived text fragment. */
596
+ readonly delta: string;
597
+ }
598
+ /**
599
+ * A server-side tool progress event arriving during a streaming completion.
600
+ * Surfaced for providers that emit explicit tool-progress markers (OpenAI
601
+ * Responses API, Anthropic). Gemini's grounding doesn't emit these.
602
+ * @public
603
+ */
604
+ export interface IAiStreamToolEvent {
605
+ readonly type: 'tool-event';
606
+ /** Which server-side tool this event describes. */
607
+ readonly toolType: AiServerToolType;
608
+ /** Tool lifecycle phase. */
609
+ readonly phase: 'started' | 'completed';
610
+ /**
611
+ * Optional provider-specific detail. For web_search this is typically the
612
+ * search query when available; format varies by provider.
613
+ */
614
+ readonly detail?: string;
615
+ }
616
+ /**
617
+ * Terminal success event for a streaming completion. Carries the aggregated
618
+ * full text and truncation status for callers that want both the progressive
619
+ * UI and the complete result.
620
+ * @public
621
+ */
622
+ export interface IAiStreamDone {
623
+ readonly type: 'done';
624
+ /** Whether the response was truncated due to token limits. */
625
+ readonly truncated: boolean;
626
+ /** The full concatenated text from all `text-delta` events. */
627
+ readonly fullText: string;
628
+ /**
629
+ * Provider-reported reason a truncated response was cut short (e.g.
630
+ * `'max_output_tokens'`, `'content_filter'`), when the provider supplies one.
631
+ * Currently populated only by the OpenAI / xAI Responses adapter, from the
632
+ * completed payload's `incomplete_details.reason`. Meaningful only when
633
+ * `truncated === true`; `undefined` otherwise (and whenever the provider
634
+ * reports truncation without a reason).
635
+ */
636
+ readonly incompleteReason?: string;
637
+ }
638
+ /**
639
+ * Terminal failure event for a streaming completion. After this event no
640
+ * further events are emitted.
641
+ *
642
+ * @remarks
643
+ * Connection-time failures (auth, network, pre-flight CORS rejection) are
644
+ * surfaced via the outer `Result.fail` returned by
645
+ * `callProviderCompletionStream` rather than as an `error` event, so callers
646
+ * can distinguish "didn't start" from "started but errored mid-stream."
647
+ *
648
+ * @public
649
+ */
650
+ export interface IAiStreamError {
651
+ readonly type: 'error';
652
+ readonly message: string;
653
+ }
654
+ /**
655
+ * Discriminated union of events emitted by a streaming completion.
656
+ *
657
+ * @remarks
658
+ * **Exhaustive-switch consumers must handle all variants.** The three
659
+ * `client-tool-*` variants were added when client-tool support shipped;
660
+ * update every exhaustive switch over this union in lockstep.
661
+ *
662
+ * @public
663
+ */
664
+ export type IAiStreamEvent = IAiStreamTextDelta | IAiStreamToolEvent | IAiStreamToolUseStart | IAiStreamToolUseDelta | IAiStreamToolUseComplete | IAiStreamDone | IAiStreamError;
665
+ /**
666
+ * Thinking/reasoning mode support for a provider.
667
+ * @public
668
+ */
669
+ export type AiThinkingMode = 'optional' | 'required' | 'unsupported';
152
670
  /**
153
671
  * Describes a single AI provider — single source of truth for all metadata.
154
672
  * @public
@@ -168,10 +686,674 @@ export interface IAiProviderDescriptor {
168
686
  readonly baseUrl: string;
169
687
  /** Default model specification — string or context-aware map. */
170
688
  readonly defaultModel: ModelSpec;
689
+ /**
690
+ * Canonical fgv alias → concrete model map for this provider. Absent means the
691
+ * provider defines no aliases and every model string passes through verbatim.
692
+ *
693
+ * @remarks
694
+ * Keys are full fgv aliases (`@<providerId>:<role>`); values are the current
695
+ * concrete model id (or a provider-native alias). Consulted by
696
+ * {@link resolveModelAlias} / {@link resolveProviderModel} at each call-time
697
+ * resolution chokepoint, downstream of the {@link ModelSpecKey} walk. Additive
698
+ * and optional — composes with the existing per-descriptor `imageGeneration` /
699
+ * `embedding` capability arrays.
700
+ */
701
+ readonly aliases?: IModelAliasMap;
171
702
  /** Which server-side tools this provider supports (empty = none). */
172
703
  readonly supportedTools: ReadonlyArray<AiServerToolType>;
173
704
  /** Whether this provider's API enforces CORS restrictions that prevent direct browser calls. */
174
705
  readonly corsRestricted: boolean;
706
+ /**
707
+ * Whether this provider's streaming completion endpoint requires a proxy
708
+ * for direct browser calls. Some providers gate streaming separately from
709
+ * non-streaming (rare), so this is tracked independently from
710
+ * {@link IAiProviderDescriptor.corsRestricted}.
711
+ *
712
+ * @remarks
713
+ * When `true`, `callProviderCompletionStream` rejects up front unless the
714
+ * call is being routed through a proxy.
715
+ */
716
+ readonly streamingCorsRestricted: boolean;
717
+ /**
718
+ * Whether this provider's chat completions API accepts image input
719
+ * (i.e. supports vision prompts). When false, calls with
720
+ * `prompt.attachments` are rejected up front.
721
+ */
722
+ readonly acceptsImageInput: boolean;
723
+ /**
724
+ * Whether this provider supports thinking/reasoning mode.
725
+ * - 'optional': thinking can be enabled but is not required
726
+ * - 'required': thinking is always active (e.g. o-series models)
727
+ * - 'unsupported': thinking is not supported
728
+ */
729
+ readonly thinkingMode: AiThinkingMode;
730
+ /**
731
+ * Image-generation capabilities, scoped to model id prefixes. Empty or
732
+ * undefined means the provider does not support image generation.
733
+ *
734
+ * @remarks
735
+ * The dispatcher matches the resolved model id against each rule's
736
+ * `modelPrefix` and selects the longest match (see
737
+ * {@link AiAssist.resolveImageCapability}). An empty `modelPrefix` is the
738
+ * catch-all and matches every model id.
739
+ *
740
+ * Multiple entries support providers that host more than one image-API
741
+ * surface under one baseUrl. The dispatcher selects the longest-matching
742
+ * prefix, so a provider can list a specific-prefix surface alongside an
743
+ * empty-prefix catch-all and the right model routes to the right API.
744
+ *
745
+ * Image-model selection reuses the existing `image` {@link ModelSpecKey}.
746
+ * Providers that declare `imageGeneration` should declare a model in
747
+ * `defaultModel.image`, e.g. `{ base: '@openai:mini', image: '@openai:image' }`.
748
+ */
749
+ readonly imageGeneration?: ReadonlyArray<IAiImageModelCapability>;
750
+ /**
751
+ * Embedding capabilities, scoped to model id prefixes. Empty or undefined
752
+ * means the provider does not support embeddings.
753
+ *
754
+ * @remarks
755
+ * The dispatcher matches the resolved embedding model id against each rule's
756
+ * `modelPrefix` and selects the longest match (see
757
+ * {@link AiAssist.resolveEmbeddingCapability}). An empty `modelPrefix` is the
758
+ * catch-all and matches every model id.
759
+ *
760
+ * Embedding-model selection uses the `embedding` {@link ModelSpecKey}.
761
+ * Providers that declare `embedding` should declare a model in
762
+ * `defaultModel.embedding`, e.g. `{ base: '@openai:mini', embedding: '@openai:embedding' }`.
763
+ * Self-hosted providers (`ollama`, `openai-compat`) leave it unset — the
764
+ * caller supplies the embedding model via `modelOverride`.
765
+ */
766
+ readonly embedding?: ReadonlyArray<IAiEmbeddingModelCapability>;
767
+ /**
768
+ * Concrete model ids (prefix-matched) that must be invoked via the OpenAI
769
+ * Responses API rather than chat completions — e.g. `gpt-5.5-pro`. Non-OpenAI
770
+ * `apiFormat`s ignore this.
771
+ *
772
+ * @remarks
773
+ * Some current-generation OpenAI models (the `-pro` tier) are Responses-API-only
774
+ * and 400 on `/chat/completions`. The completion and streaming dispatch consult
775
+ * this list (via the sibling predicate {@link AiAssist.isResponsesOnlyModel})
776
+ * and route a matching model to the Responses path
777
+ * even when no tools are requested. Mirrors the prefix-matching shape of the
778
+ * `imageGeneration` / `embedding` capability arrays; adding a new Responses-only
779
+ * line is a one-entry descriptor edit. Empty or undefined means no model is
780
+ * Responses-only.
781
+ */
782
+ readonly responsesOnlyModelPrefixes?: ReadonlyArray<string>;
783
+ }
784
+ /**
785
+ * Image-generation capability for a model family within a provider. Used as
786
+ * an entry in {@link IAiProviderDescriptor.imageGeneration}.
787
+ *
788
+ * @public
789
+ */
790
+ export interface IAiImageModelCapability {
791
+ /**
792
+ * Prefix matched against the resolved image model id. The empty string is
793
+ * the catch-all and matches every model. When multiple rules' prefixes
794
+ * match a model id, the longest prefix wins; ties are broken by
795
+ * first-encountered.
796
+ */
797
+ readonly modelPrefix: string;
798
+ /** API format used to dispatch requests for matching models. */
799
+ readonly format: AiImageApiFormat;
800
+ /**
801
+ * Whether matching models accept reference images via
802
+ * {@link AiAssist.IAiImageGenerationParams.referenceImages}. When false or
803
+ * undefined, calls that include reference images are rejected up front.
804
+ */
805
+ readonly acceptsImageReferenceInput?: boolean;
806
+ /** Accepted size strings. When present, dispatcher pre-validates. */
807
+ readonly acceptedSizes?: ReadonlyArray<string>;
808
+ /** When true, quality param is sent. When false/undefined, don't send quality. */
809
+ readonly supportsQualityParam?: boolean;
810
+ /** Accepted quality values when supportsQualityParam is true. */
811
+ readonly acceptedQualities?: ReadonlyArray<string>;
812
+ /** Maximum count (n). When present, dispatcher pre-validates. */
813
+ readonly maxCount?: number;
814
+ /**
815
+ * How to encode the output format on the wire:
816
+ * - 'response-format': send response_format: 'b64_json' (openai-images catch-all)
817
+ * - 'output-format': send output_format (gpt-image-1)
818
+ * - 'none': send neither (Gemini Flash)
819
+ */
820
+ readonly outputParamStyle?: 'response-format' | 'output-format' | 'none';
821
+ /** Default MIME type for response images. */
822
+ readonly defaultOutputMimeType?: string;
823
+ }
824
+ /**
825
+ * Embedding capability for a model family within a provider. Used as an entry
826
+ * in {@link IAiProviderDescriptor.embedding}.
827
+ *
828
+ * @public
829
+ */
830
+ export interface IAiEmbeddingModelCapability {
831
+ /**
832
+ * Prefix matched against the resolved embedding model id. The empty string is
833
+ * the catch-all and matches every model. When multiple rules' prefixes match
834
+ * a model id, the longest prefix wins; ties are broken by first-encountered.
835
+ */
836
+ readonly modelPrefix: string;
837
+ /** API format used to dispatch requests for matching models. */
838
+ readonly format: AiEmbeddingApiFormat;
839
+ /**
840
+ * Whether matching models honor a requested output `dimensions`
841
+ * (OpenAI `text-embedding-3-*`, Gemini `gemini-embedding-001` via MRL
842
+ * truncation). When false/undefined, a caller-supplied `dimensions` is a
843
+ * no-op (logged, not failed — see {@link AiAssist.IAiEmbeddingParams}).
844
+ */
845
+ readonly supportsDimensions?: boolean;
846
+ /**
847
+ * Whether matching models honor a `taskType` hint (Gemini only today). When
848
+ * false/undefined, a caller-supplied `taskType` is a no-op (logged, not
849
+ * failed).
850
+ */
851
+ readonly supportsTaskType?: boolean;
852
+ /** Native fixed output dimension, when the model has one (metadata only). */
853
+ readonly defaultDimensions?: number;
854
+ /**
855
+ * Maximum number of inputs accepted per request. When present, the dispatcher
856
+ * rejects batches larger than this up front (no auto-chunking in v1).
857
+ */
858
+ readonly maxBatchSize?: number;
859
+ }
860
+ /**
861
+ * A single embedding task-type hint (Gemini-style). Cross-provider; providers
862
+ * that don't support task typing ignore it (logged, not failed). Open string
863
+ * union so new Gemini task types don't force a churn, with the known set
864
+ * enumerated for ergonomics.
865
+ *
866
+ * @remarks
867
+ * Values are the kebab-case cross-provider form; the Gemini adapter maps them to
868
+ * `SCREAMING_SNAKE_CASE` on the wire (e.g. `'retrieval-document'` →
869
+ * `RETRIEVAL_DOCUMENT`).
870
+ *
871
+ * @public
872
+ */
873
+ export type AiEmbeddingTaskType = 'retrieval-query' | 'retrieval-document' | 'semantic-similarity' | 'classification' | 'clustering' | 'code-retrieval-query' | 'question-answering' | 'fact-verification' | (string & {});
874
+ /**
875
+ * Parameters for an embedding request. Batch is the norm: `input` accepts a
876
+ * single string or an array; the result always exposes a vector array aligned
877
+ * by index to the input.
878
+ *
879
+ * @public
880
+ */
881
+ export interface IAiEmbeddingParams {
882
+ /** One or more input strings. A bare string is treated as a single-element batch. */
883
+ readonly input: string | ReadonlyArray<string>;
884
+ /**
885
+ * Requested output dimensionality. Honored only by models whose capability
886
+ * declares `supportsDimensions` (OpenAI `text-embedding-3-*`, Gemini
887
+ * `gemini-embedding-001` via MRL truncation). Ignored — with a `logger.info`
888
+ * note — by models that don't.
889
+ */
890
+ readonly dimensions?: number;
891
+ /**
892
+ * Task-type hint. Mapped to Gemini `taskType`; a no-op (with a `logger.info`
893
+ * note) on OpenAI/Ollama/compat/Mistral. Preserves Gemini's
894
+ * query-vs-document retrieval asymmetry.
895
+ */
896
+ readonly taskType?: AiEmbeddingTaskType;
897
+ }
898
+ /**
899
+ * Token-usage accounting for an embedding call, when the provider reports it.
900
+ * @public
901
+ */
902
+ export interface IAiEmbeddingUsage {
903
+ /** Tokens consumed by the input(s). */
904
+ readonly promptTokens?: number;
905
+ /** Total tokens billed. */
906
+ readonly totalTokens?: number;
907
+ }
908
+ /**
909
+ * Result of an embedding call. `vectors[i]` is the embedding for `input[i]`,
910
+ * in request order.
911
+ *
912
+ * @remarks
913
+ * Vectors are plain `number[]` (not `Float32Array`) for JSON-wire fidelity and
914
+ * validator-friendliness — consumers who want a typed array call
915
+ * `Float32Array.from(vector)` at the vector-store / WebGPU boundary. The
916
+ * library does not L2-normalize; Gemini's MRL truncation (when
917
+ * `dimensions < native`) returns un-normalized vectors that the consumer should
918
+ * normalize if their similarity metric requires it.
919
+ *
920
+ * @public
921
+ */
922
+ export interface IAiEmbeddingResult {
923
+ /** One vector per input, aligned by index to the request order. */
924
+ readonly vectors: ReadonlyArray<ReadonlyArray<number>>;
925
+ /** The resolved provider-native model id that produced the vectors. */
926
+ readonly model: string;
927
+ /** Dimensionality of each returned vector (`vectors[0].length`; `0` for empty input). */
928
+ readonly dimensions: number;
929
+ /** Token usage, when the provider reports it (OpenAI-format; absent for Gemini). */
930
+ readonly usage?: IAiEmbeddingUsage;
931
+ }
932
+ /** Pixel dimension sizes accepted by gpt-image-1. @public */
933
+ export type GptImageSize = '1024x1024' | '1536x1024' | '1024x1536' | 'auto';
934
+ /** All accepted image size strings across all providers. @public */
935
+ export type AiImageSize = GptImageSize;
936
+ /** Quality values for gpt-image-1. @public */
937
+ export type GptImageQuality = 'low' | 'medium' | 'high' | 'auto';
938
+ /** All accepted quality strings across all providers. @public */
939
+ export type AiImageQuality = GptImageQuality;
940
+ /** Model names in the GPT Image family. @public */
941
+ export type GptImageModelNames = 'gpt-image-1' | 'gpt-image-1.5';
942
+ /** Model names in the xAI Grok Imagine family. @public */
943
+ export type GrokImagineModelNames = 'grok-imagine-image' | 'grok-imagine-image-quality';
944
+ /** Model names in the Gemini Flash Image family. @public */
945
+ export type GeminiFlashImageModelNames = 'gemini-3.1-flash-image-preview';
946
+ /**
947
+ * Provider-specific config for gpt-image-1.
948
+ * @public
949
+ */
950
+ export interface IGptImageGenerationConfig {
951
+ /** Image dimensions. */
952
+ readonly size?: GptImageSize;
953
+ /** Quality tier. */
954
+ readonly quality?: GptImageQuality;
955
+ /** Output format (replaces response_format for this model). */
956
+ readonly outputFormat?: 'png' | 'jpeg' | 'webp';
957
+ /** JPEG/WebP compression level 0–100. */
958
+ readonly outputCompression?: number;
959
+ /** Background transparency control. */
960
+ readonly background?: 'transparent' | 'opaque' | 'auto';
961
+ /** Content moderation strictness. */
962
+ readonly moderation?: 'low' | 'auto';
963
+ }
964
+ /**
965
+ * Provider-specific config for xAI Grok Imagine models.
966
+ * @public
967
+ */
968
+ export interface IGrokImagineImageGenerationConfig {
969
+ /** Aspect ratio string (xAI uses aspect ratios, not pixel dimensions). */
970
+ readonly aspectRatio?: string;
971
+ /** Resolution hint. */
972
+ readonly resolution?: string;
973
+ }
974
+ /**
975
+ * Provider-specific config for Gemini Flash Image.
976
+ * @public
977
+ */
978
+ export interface IGeminiFlashImageGenerationConfig {
979
+ /** Aspect ratio string. */
980
+ readonly aspectRatio?: string;
981
+ }
982
+ /**
983
+ * Base shape shared by all named family option blocks.
984
+ * Provides a typed `models` field for applicability filtering without unsafe casts.
985
+ * @internal
986
+ */
987
+ export interface INamedModelFamilyConfig {
988
+ readonly models?: readonly string[];
989
+ }
990
+ /**
991
+ * Options block scoped to GPT Image family models.
992
+ * @public
993
+ */
994
+ export interface IGptImageModelOptions extends INamedModelFamilyConfig {
995
+ readonly provider: 'openai';
996
+ readonly family: 'gpt-image';
997
+ readonly models?: GptImageModelNames[];
998
+ readonly config: IGptImageGenerationConfig;
999
+ }
1000
+ /**
1001
+ * Options block scoped to xAI Grok Imagine family models.
1002
+ * @public
1003
+ */
1004
+ export interface IGrokImagineModelOptions extends INamedModelFamilyConfig {
1005
+ readonly provider: 'xai';
1006
+ readonly family: 'grok-imagine';
1007
+ readonly models?: GrokImagineModelNames[];
1008
+ readonly config: IGrokImagineImageGenerationConfig;
1009
+ }
1010
+ /**
1011
+ * Options block scoped to Gemini Flash Image models.
1012
+ * @public
1013
+ */
1014
+ export interface IGeminiFlashImageModelOptions extends INamedModelFamilyConfig {
1015
+ readonly provider: 'google';
1016
+ readonly family: 'gemini-flash-image';
1017
+ readonly models?: GeminiFlashImageModelNames[];
1018
+ readonly config: IGeminiFlashImageGenerationConfig;
1019
+ }
1020
+ /**
1021
+ * Escape-hatch options block for models not covered by a named family.
1022
+ * @remarks
1023
+ * `models` is required — there is no implicit "all" for unknown model families.
1024
+ * `config` is `JsonObject` — passed verbatim to the wire request with no validation.
1025
+ * This is the "trust me, I know what I'm doing" path for callers who need to send
1026
+ * wire params our typed configs don't yet expose.
1027
+ * @public
1028
+ */
1029
+ export interface IOtherModelOptions {
1030
+ readonly provider: 'other';
1031
+ readonly models: string[];
1032
+ readonly config: JsonObject;
1033
+ }
1034
+ /**
1035
+ * Discriminated union of all model-family option blocks.
1036
+ * Discriminated on `provider` + `family` fields.
1037
+ * @public
1038
+ */
1039
+ export type IModelFamilyConfig = IGptImageModelOptions | IGrokImagineModelOptions | IGeminiFlashImageModelOptions | IOtherModelOptions;
1040
+ /**
1041
+ * Options for image generation requests.
1042
+ *
1043
+ * @remarks
1044
+ * Uses a layered architecture:
1045
+ * 1. Generic top-level options (size, count, quality, seed) apply across providers
1046
+ * via the resolved model's registry mapping.
1047
+ * 2. Optional `models` array contains model-family-scoped blocks; the resolver
1048
+ * picks applicable blocks based on the resolved model and applies them in
1049
+ * declaration order.
1050
+ *
1051
+ * **Merge precedence (later wins):**
1052
+ * 1. Generic top-level options (lowest precedence)
1053
+ * 2. Family-generic blocks (matching family, models field omitted)
1054
+ * 3. Model-specific blocks (models array includes resolved model name)
1055
+ * 4. Other blocks (provider: 'other', models array includes resolved model name)
1056
+ *
1057
+ * Provider-mismatch: blocks whose provider doesn't match the dispatcher's
1058
+ * provider lineage are silently skipped.
1059
+ *
1060
+ * @public
1061
+ */
1062
+ export interface IAiImageGenerationOptions {
1063
+ /**
1064
+ * Image dimensions for OpenAI models (mapped to `size` field).
1065
+ * For xAI or Gemini Flash aspect ratio, use the corresponding `models` family block.
1066
+ */
1067
+ readonly size?: AiImageSize;
1068
+ /** Number of images. Default 1. Some models enforce a maximum. */
1069
+ readonly count?: number;
1070
+ /**
1071
+ * Quality tier. Accepted values differ per model:
1072
+ * - gpt-image-1: 'low' | 'medium' | 'high' | 'auto'
1073
+ * Other models ignore this field.
1074
+ */
1075
+ readonly quality?: AiImageQuality;
1076
+ /** Reproducibility seed, where supported. */
1077
+ readonly seed?: number;
1078
+ /**
1079
+ * Optional precision via model-family-scoped blocks. The resolver picks
1080
+ * applicable blocks dynamically based on the resolved model.
1081
+ */
1082
+ readonly models?: ReadonlyArray<IModelFamilyConfig>;
1083
+ }
1084
+ /**
1085
+ * Parameters for an image-generation request.
1086
+ * @public
1087
+ */
1088
+ export interface IAiImageGenerationParams {
1089
+ /** The text prompt describing the desired image. */
1090
+ readonly prompt: string;
1091
+ /** Optional generation options. */
1092
+ readonly options?: IAiImageGenerationOptions;
1093
+ /**
1094
+ * Optional reference images. When present, the provider will use them as
1095
+ * visual context (e.g. to preserve a character's appearance across multiple
1096
+ * generations). The dispatcher resolves the
1097
+ * {@link AiAssist.IAiImageModelCapability} for the requested model and
1098
+ * rejects the call up front if `acceptsImageReferenceInput` is not set on
1099
+ * the matching capability. An empty array is treated identically to
1100
+ * `undefined`.
1101
+ */
1102
+ readonly referenceImages?: ReadonlyArray<IAiImageAttachment>;
1103
+ }
1104
+ /**
1105
+ * A single generated image.
1106
+ * @public
1107
+ */
1108
+ export interface IAiGeneratedImage extends IAiImageData {
1109
+ /**
1110
+ * The prompt as rewritten by the provider, if any. OpenAI's image models
1111
+ * commonly rewrite prompts; other providers do not.
1112
+ */
1113
+ readonly revisedPrompt?: string;
1114
+ }
1115
+ /**
1116
+ * Capability vocabulary used to describe what a model can do. Used as both
1117
+ * a filter and as a tag in {@link AiAssist.IAiModelInfo.capabilities}.
1118
+ *
1119
+ * @remarks
1120
+ * Adding a new capability is cheap; adding the *first* one after consumers
1121
+ * already exist forces churn. The initial vocabulary is intentionally broad
1122
+ * even though only `image-generation` is fully exercised today.
1123
+ *
1124
+ * @public
1125
+ */
1126
+ export type AiModelCapability = 'chat' | 'tools' | 'vision' | 'image-generation' | 'thinking' | 'embedding';
1127
+ /**
1128
+ * All valid `AiModelCapability` values — the single source of truth for
1129
+ * the capability vocabulary (used by validators and capability filters).
1130
+ * @public
1131
+ */
1132
+ export declare const allModelCapabilities: ReadonlyArray<AiModelCapability>;
1133
+ /**
1134
+ * Information about a single model returned by a provider's list endpoint,
1135
+ * with capabilities already resolved (native + config rules).
1136
+ * @public
1137
+ */
1138
+ export interface IAiModelInfo {
1139
+ /** Provider-native model identifier. */
1140
+ readonly id: string;
1141
+ /** Resolved capability set — union of native declarations and config rules. */
1142
+ readonly capabilities: ReadonlySet<AiModelCapability>;
1143
+ /** Friendly name for display, when known. */
1144
+ readonly displayName?: string;
1145
+ }
1146
+ /**
1147
+ * One rule in an {@link IAiModelCapabilityConfig}. Multiple rules can match
1148
+ * a single model — their capability arrays are unioned.
1149
+ * @public
1150
+ */
1151
+ export interface IAiModelCapabilityRule {
1152
+ /** RegExp tested against the model id (using `.test`). */
1153
+ readonly idPattern: RegExp;
1154
+ /** Capabilities this rule attributes to matching models. */
1155
+ readonly capabilities: ReadonlyArray<AiModelCapability>;
1156
+ /**
1157
+ * Friendly display-name override for matching models. The function form
1158
+ * lets one rule format many ids (e.g. `(id) => id.toUpperCase()`).
1159
+ * If multiple matching rules supply `displayName`, the first match wins.
1160
+ */
1161
+ readonly displayName?: string | ((id: string) => string);
1162
+ }
1163
+ /**
1164
+ * Configuration that maps model id patterns to capabilities. Used to
1165
+ * augment (or, where the provider supplies no capability info, fully
1166
+ * derive) the capability set for each listed model.
1167
+ * @public
1168
+ */
1169
+ export interface IAiModelCapabilityConfig {
1170
+ /** Per-provider rules. Tried before {@link AiAssist.IAiModelCapabilityConfig.global}. */
1171
+ readonly perProvider?: {
1172
+ readonly [P in AiProviderId]?: ReadonlyArray<IAiModelCapabilityRule>;
1173
+ };
1174
+ /** Cross-provider fallback rules. */
1175
+ readonly global?: ReadonlyArray<IAiModelCapabilityRule>;
1176
+ }
1177
+ /**
1178
+ * Result of an image-generation call.
1179
+ * @public
1180
+ */
1181
+ export interface IAiImageGenerationResponse {
1182
+ /** The generated images, in provider-returned order. */
1183
+ readonly images: ReadonlyArray<IAiGeneratedImage>;
1184
+ }
1185
+ /**
1186
+ * Model IDs for Anthropic thinking-capable models.
1187
+ *
1188
+ * @remarks
1189
+ * Only thinking-capable lines are listed. The non-tier `@anthropic:haiku` / `@anthropic:fable`
1190
+ * aliases (reachable via `modelOverride` only) are deliberately omitted — they are not
1191
+ * documented as thinking-capable, so naming them in a thinking-model filter would be misleading.
1192
+ * @public
1193
+ */
1194
+ export type AnthropicThinkingModelNames = 'claude-sonnet-4-5' | 'claude-sonnet-4-6' | 'claude-sonnet-5' | 'claude-opus-4-6' | 'claude-opus-4-7' | 'claude-opus-4-8';
1195
+ /**
1196
+ * Model IDs for OpenAI thinking-capable models.
1197
+ * @public
1198
+ */
1199
+ export type OpenAiThinkingModelNames = 'o3' | 'o4-mini' | 'o3-deep-research' | 'o4-mini-deep-research' | 'gpt-5' | 'gpt-5.1' | 'gpt-5.2' | 'gpt-5.4-mini' | 'gpt-5.5' | 'gpt-5.5-pro' | 'gpt-5-pro';
1200
+ /**
1201
+ * Model IDs for Google Gemini thinking-capable models.
1202
+ * @public
1203
+ */
1204
+ export type GeminiThinkingModelNames = 'gemini-3.1-pro-preview' | 'gemini-3.5-flash' | 'gemini-3.1-flash-lite';
1205
+ /**
1206
+ * Model IDs for xAI thinking-capable models.
1207
+ * @public
1208
+ */
1209
+ export type XAiThinkingModelNames = 'grok-3-mini' | 'grok-4.3' | 'grok-4';
1210
+ /**
1211
+ * Anthropic-specific thinking configuration.
1212
+ * @public
1213
+ */
1214
+ export interface IAnthropicThinkingConfig {
1215
+ /**
1216
+ * Anthropic effort level. The emit-site converts to `thinking.budget_tokens`
1217
+ * (the integer budget the Anthropic API requires). Mapping policy: low = 2048,
1218
+ * medium = 8192, high = 24000, max = 32000.
1219
+ * - 'low' | 'medium' | 'high': all thinking-capable models
1220
+ * - 'max': Opus 4.6 only
1221
+ */
1222
+ readonly effort?: 'low' | 'medium' | 'high' | 'max';
1223
+ }
1224
+ /**
1225
+ * OpenAI-specific thinking configuration.
1226
+ * @remarks
1227
+ * Maps to `reasoning_effort` (Chat Completions path) or `reasoning.effort`
1228
+ * (Responses API path) on the wire. The adapter selects the correct field.
1229
+ * @public
1230
+ */
1231
+ export interface IOpenAiThinkingConfig {
1232
+ /**
1233
+ * OpenAI reasoning effort. Maps 1:1 to the wire field.
1234
+ * - 'none': disables reasoning (gpt-5.x only; rejected by o-series)
1235
+ * - 'minimal': fastest (gpt-5.x)
1236
+ * - 'low' | 'medium' | 'high': standard tiers
1237
+ * - 'xhigh': highest (select gpt-5.x models only)
1238
+ *
1239
+ * @remarks
1240
+ * When effective effort is 'none', reasoning is disabled and temperature is
1241
+ * accepted by gpt-5.x models. This is the only case where temperature and
1242
+ * thinking config co-exist without a Result.fail.
1243
+ */
1244
+ readonly effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
1245
+ }
1246
+ /**
1247
+ * Google Gemini-specific thinking configuration.
1248
+ * @public
1249
+ */
1250
+ export interface IGeminiThinkingConfig {
1251
+ /**
1252
+ * Token budget for thinking. Maps 1:1 to `thinkingBudget` on the wire.
1253
+ * - 0: disable thinking (Flash and Flash-Lite only; error on Pro)
1254
+ * - positive integer: soft token cap
1255
+ * - -1: dynamic
1256
+ * - omitted: model default
1257
+ */
1258
+ readonly thinkingBudget?: number;
1259
+ /**
1260
+ * Whether to include thought summaries in the response.
1261
+ * @remarks
1262
+ * INERT in phase B. Adapters never send `includeThoughts: true`.
1263
+ * Wired up by the followup stream `ai-assist-thinking-events`.
1264
+ */
1265
+ readonly includeThoughts?: boolean;
1266
+ }
1267
+ /**
1268
+ * xAI-specific thinking configuration.
1269
+ * @public
1270
+ */
1271
+ export interface IXAiThinkingConfig {
1272
+ /**
1273
+ * xAI reasoning effort. Maps 1:1 to `reasoning_effort` on the wire.
1274
+ * For grok-4, the adapter omits this field (grok-4 always reasons and
1275
+ * rejects the parameter).
1276
+ */
1277
+ readonly effort?: 'none' | 'low' | 'medium' | 'high';
1278
+ }
1279
+ /**
1280
+ * Anthropic-specific thinking options block.
1281
+ * @public
1282
+ */
1283
+ export interface IAnthropicThinkingOptions {
1284
+ readonly provider: 'anthropic';
1285
+ readonly models?: ReadonlyArray<AnthropicThinkingModelNames>;
1286
+ readonly config: IAnthropicThinkingConfig;
1287
+ }
1288
+ /**
1289
+ * OpenAI-specific thinking options block.
1290
+ * @public
1291
+ */
1292
+ export interface IOpenAiThinkingOptions {
1293
+ readonly provider: 'openai';
1294
+ readonly models?: ReadonlyArray<OpenAiThinkingModelNames>;
1295
+ readonly config: IOpenAiThinkingConfig;
1296
+ }
1297
+ /**
1298
+ * Google Gemini-specific thinking options block.
1299
+ * @public
1300
+ */
1301
+ export interface IGeminiThinkingOptions {
1302
+ readonly provider: 'google';
1303
+ readonly models?: ReadonlyArray<GeminiThinkingModelNames>;
1304
+ readonly config: IGeminiThinkingConfig;
1305
+ }
1306
+ /**
1307
+ * xAI-specific thinking options block.
1308
+ * @public
1309
+ */
1310
+ export interface IXAiThinkingOptions {
1311
+ readonly provider: 'xai';
1312
+ readonly models?: ReadonlyArray<XAiThinkingModelNames>;
1313
+ readonly config: IXAiThinkingConfig;
1314
+ }
1315
+ /**
1316
+ * Escape-hatch options block for providers not covered by typed configs.
1317
+ * @remarks
1318
+ * `models` is required — no implicit "all" for unknown providers.
1319
+ * `config` fields are merged verbatim into the wire request.
1320
+ * @public
1321
+ */
1322
+ export interface IOtherThinkingOptions {
1323
+ readonly provider: 'other';
1324
+ readonly models: ReadonlyArray<string>;
1325
+ readonly config: JsonObject;
1326
+ }
1327
+ /**
1328
+ * Discriminated union of per-provider thinking config blocks.
1329
+ * @public
1330
+ */
1331
+ export type IThinkingProviderConfig = IAnthropicThinkingOptions | IOpenAiThinkingOptions | IGeminiThinkingOptions | IXAiThinkingOptions | IOtherThinkingOptions;
1332
+ /**
1333
+ * Thinking/reasoning mode configuration for a completion request.
1334
+ *
1335
+ * @remarks
1336
+ * The generic `effort` field covers the common-subset cross-provider vocabulary.
1337
+ * For provider-specific precision (Anthropic 'max', OpenAI 'xhigh', Gemini token
1338
+ * budgets, xAI effort-level tuning), use the `providers` array.
1339
+ *
1340
+ * Absence (or undefined) means "no thinking mode" — existing callers are unaffected.
1341
+ *
1342
+ * @public
1343
+ */
1344
+ export interface IThinkingConfig {
1345
+ /**
1346
+ * Cross-provider effort level. Common-subset mapping:
1347
+ * - 'low': Anthropic effort:low | OpenAI effort:low | Gemini thinkingBudget:1024 | xAI reasoning_effort:low
1348
+ * - 'medium': effort:medium | effort:medium | thinkingBudget:4096 | reasoning_effort:medium
1349
+ * - 'high': effort:high | effort:high | thinkingBudget:8192 | reasoning_effort:high
1350
+ */
1351
+ readonly effort?: 'low' | 'medium' | 'high';
1352
+ /**
1353
+ * Optional per-provider precision blocks. Blocks for providers that don't
1354
+ * match the resolved model's provider are silently skipped.
1355
+ */
1356
+ readonly providers?: ReadonlyArray<IThinkingProviderConfig>;
175
1357
  }
176
1358
  /**
177
1359
  * Configuration for a single AI assist provider.
@@ -186,6 +1368,14 @@ export interface IAiAssistProviderConfig {
186
1368
  readonly model?: ModelSpec;
187
1369
  /** Tool enablement/configuration. Tools are disabled unless explicitly enabled. */
188
1370
  readonly tools?: ReadonlyArray<IAiToolEnablement>;
1371
+ /**
1372
+ * Optional caller-supplied endpoint URL (http/https). Overrides
1373
+ * `descriptor.baseUrl` for this provider. Used to point a provider at a
1374
+ * self-hosted server (Ollama, LM Studio, llama.cpp's openai-server) or a
1375
+ * local proxy. Validation lives in `@fgv/ts-extras` — query strings,
1376
+ * fragments, and userinfo are rejected.
1377
+ */
1378
+ readonly endpoint?: string;
189
1379
  }
190
1380
  /**
191
1381
  * AI assist settings — which providers are enabled and their configuration.