@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
@@ -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,259 @@ 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.
390
+ *
391
+ * @remarks
392
+ * Two axes live here and nothing else: the **quality tier** (`base` / `advanced`
393
+ * / `frontier`) selects the *completion* model, and `image` / `embedding` select
394
+ * the non-completion modalities.
395
+ *
396
+ * There is deliberately **no `tools` or `thinking` key**. Both existed before the
397
+ * quality-tier axis landed and were removed with it: server-side tools and
398
+ * reasoning effort are orthogonal *request* params that ride on top of whatever
399
+ * model the tier already selected — they never select a model. A tool-using or
400
+ * thinking-enabled call passes a tier like any other call (omit → `base`, or
401
+ * `'advanced'` / `'frontier'`) and sets the tools / thinking request params
402
+ * independently. Thinking composes with any tier without a tier-level capability
403
+ * check — but that is a statement about the tier axis, not a claim that every
404
+ * provider supports thinking: several descriptors declare
405
+ * `thinkingMode: 'unsupported'` (e.g. `copy-paste`, `groq`, `mistral`, `ollama`,
406
+ * `openai-compat`).
407
+ *
408
+ * Thinking availability is declared **per provider**, on the descriptor's
409
+ * `thinkingMode`; the descriptor does not encode per-model thinking availability at
410
+ * all, so a provider that declares support may still have individual models its own
411
+ * API rejects thinking on. (`adaptiveThinkingModelPrefixes` is per-model but selects
412
+ * a wire *shape*, not availability.) What the tier axis guarantees is therefore
413
+ * narrow and exact: a tier selects a model within one provider and never changes the
414
+ * provider, so it never changes `thinkingMode`.
415
+ *
416
+ * Do not add a `'tools'` or `'thinking'` key here, and do not hand-roll a
417
+ * `resolveModel` + `resolveModelAlias` walk to emulate one — call
418
+ * `resolveProviderModel` with the tier you want.
74
419
  * @public
75
420
  */
76
- export type ModelSpecKey = 'base' | 'tools' | 'image';
421
+ export type ModelSpecKey = 'base' | 'advanced' | 'frontier' | 'image' | 'embedding';
77
422
  /**
78
423
  * All valid {@link ModelSpecKey} values.
79
424
  * @public
@@ -91,18 +436,18 @@ export declare const MODEL_SPEC_BASE_KEY: ModelSpecKey;
91
436
  * @remarks
92
437
  * A bare string is equivalent to `{ base: string }`. This keeps the simple
93
438
  * case simple while allowing context-aware model selection (e.g. different
94
- * models for tool-augmented vs. base completions).
439
+ * models for different quality tiers).
95
440
  *
96
441
  * @example
97
442
  * ```typescript
98
443
  * // Simple — same model for all contexts:
99
- * const simple: ModelSpec = 'grok-4-1-fast';
444
+ * const simple: ModelSpec = 'grok-4.3';
100
445
  *
101
- * // Context-aware — reasoning model when tools are active:
102
- * const split: ModelSpec = { base: 'grok-4-1-fast', tools: 'grok-4-1-fast-reasoning' };
446
+ * // Context-aware — different model per quality tier:
447
+ * const split: ModelSpec = { base: 'gpt-5.6-luna', advanced: 'gpt-5.6-terra', frontier: 'gpt-5.6-sol' };
103
448
  *
104
- * // Future nested per-tool model selection:
105
- * const nested: ModelSpec = { base: 'grok-fast', tools: { base: 'grok-r', image: 'grok-v' } };
449
+ * // Nesteda tier branch is itself a spec:
450
+ * const nested: ModelSpec = { base: 'grok-fast', advanced: { base: 'grok-r', image: 'grok-v' } };
106
451
  * ```
107
452
  * @public
108
453
  */
@@ -119,26 +464,208 @@ export type ModelSpec = string | IModelSpecMap;
119
464
  * @remarks
120
465
  * Resolution rules:
121
466
  * 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.
467
+ * 2. If the spec is an object, walk the ordered candidate keys for the context:
468
+ * a quality-tier context (`advanced`/`frontier`) cascades through the
469
+ * tier-fallback table (`frontier → advanced → base`, `advanced → base`);
470
+ * every other context resolves flat (`[context]`); `undefined` resolves to
471
+ * the shared `base` fallback. The first present key wins.
123
472
  * 3. Otherwise, fall back to the {@link MODEL_SPEC_BASE_KEY | 'base'} key.
124
473
  * 4. If neither context nor `'base'` exists, use the first available value.
125
474
  *
126
475
  * @param spec - The model specification to resolve
127
- * @param context - Optional context key (e.g. `'tools'`)
476
+ * @param context - Optional context key (e.g. `'advanced'`)
128
477
  * @returns The resolved model string
129
478
  * @public
130
479
  */
131
480
  export declare function resolveModel(spec: ModelSpec, context?: string): string;
481
+ /**
482
+ * Canonical fgv alias → concrete provider model map.
483
+ *
484
+ * @remarks
485
+ * Keys are full fgv aliases (`@<providerId>:<role>`, e.g. `@google-gemini:flash`);
486
+ * values are the current concrete provider model id (or a provider-native alias,
487
+ * which is resolved with one further indirection hop). Additive; absence of an
488
+ * `aliases` field on a descriptor means "this provider defines no aliases" and
489
+ * every model string passes through verbatim.
490
+ * @public
491
+ */
492
+ export interface IModelAliasMap {
493
+ readonly [alias: string]: string;
494
+ }
495
+ /**
496
+ * Marker prefix for an fgv model alias.
497
+ *
498
+ * @remarks
499
+ * A model string is an fgv alias **iff** it begins with this sigil. Everything
500
+ * else is a raw provider model id and passes through {@link resolveModelAlias}
501
+ * untouched — this is what keeps the alias layer back-compatible (no current
502
+ * `defaultModel`, `modelOverride`, or self-hosted `model:tag` id starts with `@`).
503
+ * @public
504
+ */
505
+ export declare const MODEL_ALIAS_SIGIL: '@';
506
+ /**
507
+ * Resolves a single (possibly-aliased) model string against a provider descriptor.
508
+ *
509
+ * @remarks
510
+ * Resolution rules:
511
+ * 1. No leading {@link MODEL_ALIAS_SIGIL} → raw provider id, returned verbatim.
512
+ * 2. Leading sigil + registered in `descriptor.aliases` → the registered target,
513
+ * which is itself resolved — so a chain of `@` aliases is followed until a
514
+ * non-`@` (concrete provider) id is reached. The canonical case is a single
515
+ * hop (an fgv alias targeting a provider-native alias), but longer chains
516
+ * resolve too.
517
+ * 3. Leading sigil + unregistered → fails loudly, naming the provider and alias.
518
+ *
519
+ * An `@`→`@` cycle is guarded by a visited-set and fails rather than exhausting
520
+ * the stack.
521
+ *
522
+ * @param descriptor - The provider descriptor whose `aliases` map is consulted.
523
+ * @param model - The (possibly-aliased) model string to resolve.
524
+ * @returns `Result` with the concrete provider model id, or a failure.
525
+ * @public
526
+ */
527
+ export declare function resolveModelAlias(descriptor: IAiProviderDescriptor, model: string): Result<string>;
528
+ /**
529
+ * The full provider model-resolution chokepoint: the {@link ModelSpecKey} walk
530
+ * (via {@link resolveModel}) THEN {@link resolveModelAlias}.
531
+ *
532
+ * @remarks
533
+ * Replaces the bare `resolveModel(modelOverride ?? descriptor.defaultModel, context)`
534
+ * call plus the duplicated empty-result check at each call-time chokepoint. The
535
+ * `ModelSpec` branch is selected first; the resulting string — which may itself
536
+ * be an fgv alias — is then resolved to a concrete id.
537
+ *
538
+ * **This is the whole model-selection surface — do not hand-roll the walk.**
539
+ * Callers should pass the `ModelSpecKey` they want and use the concrete id
540
+ * this returns; a manual `resolveModel` + `resolveModelAlias` sequence is
541
+ * both redundant and easy to get wrong (it is how alias-form ids leak into
542
+ * capability lookups such as `resolveImageCapability`).
543
+ *
544
+ * **`context` carries the quality tier and the modality — never tools or
545
+ * thinking.** `ModelSpecKey` has no `tools` / `thinking` key: server-side
546
+ * tools and reasoning effort are orthogonal request params that ride on top of
547
+ * whatever model the tier selected, and never select a model. A tool-path caller
548
+ * passes a tier like any other caller — omit `context` for `base`, or pass
549
+ * `'advanced'` / `'frontier'` — and sets the tools / thinking request params
550
+ * separately.
551
+ *
552
+ * @param descriptor - The provider descriptor (supplies `defaultModel` and `aliases`).
553
+ * @param modelOverride - An optional caller-supplied `ModelSpec` that takes precedence
554
+ * over `descriptor.defaultModel`. May itself contain or be an alias.
555
+ * @param context - Optional {@link ModelSpecKey} selecting the spec branch.
556
+ * @returns `Result` with the concrete provider model id, or a failure.
557
+ * @public
558
+ */
559
+ export declare function resolveProviderModel(descriptor: IAiProviderDescriptor, modelOverride: ModelSpec | undefined, context?: ModelSpecKey): Result<string>;
560
+ /**
561
+ * Determines whether a concrete (already-resolved) model id must be invoked via
562
+ * the OpenAI Responses API rather than chat completions.
563
+ *
564
+ * @remarks
565
+ * Matches `modelId` against the descriptor's
566
+ * {@link IAiProviderDescriptor.responsesOnlyModelPrefixes} by prefix. A provider
567
+ * that declares no list (the common case) always returns `false`. Consulted by
568
+ * both the completion (`callProviderCompletion`) and streaming
569
+ * (`callProviderCompletionStream`) OpenAI dispatch branches so a Responses-only
570
+ * model (e.g. `gpt-5.5-pro`) routes correctly even with no tools requested.
571
+ *
572
+ * @param descriptor - The provider descriptor supplying the prefix list.
573
+ * @param modelId - The resolved concrete model id to test.
574
+ * @returns `true` when `modelId` starts with any declared Responses-only prefix.
575
+ * @public
576
+ */
577
+ export declare function isResponsesOnlyModel(descriptor: IAiProviderDescriptor, modelId: string): boolean;
578
+ /**
579
+ * Determines whether a concrete (already-resolved) Anthropic model id uses the adaptive
580
+ * thinking wire shape (`thinking: { type: 'adaptive' }` + top-level `output_config.effort`)
581
+ * rather than the legacy manual-budget shape (`thinking: { type: 'enabled', budget_tokens }`).
582
+ *
583
+ * @remarks
584
+ * Matches `modelId` against the descriptor's
585
+ * {@link IAiProviderDescriptor.adaptiveThinkingModelPrefixes} using the same
586
+ * exact-or-dash-bounded matcher semantics as the model-specific blocks in
587
+ * `mergeThinkingConfig` (an entry matches when it equals the resolved model or when the
588
+ * resolved model starts with the entry followed by a `-`) — a plain prefix match would risk a
589
+ * false positive against an unrelated model sharing the same leading characters. A provider
590
+ * that declares no list (the common case — this is Anthropic-specific) always returns `false`.
591
+ * Consulted by the completion (`callProviderCompletion`), streaming
592
+ * (`callProviderCompletionStream`), and client-tool (`executeClientToolTurn`) Anthropic
593
+ * dispatch sites so every Anthropic wire-request path picks the correct thinking shape for the
594
+ * resolved model.
595
+ *
596
+ * @param descriptor - The provider descriptor supplying the prefix list.
597
+ * @param modelId - The resolved concrete model id to test.
598
+ * @returns `true` when `modelId` exactly matches or is dash-bounded-prefixed by any declared
599
+ * adaptive-thinking prefix.
600
+ * @public
601
+ */
602
+ export declare function isAdaptiveThinkingModel(descriptor: IAiProviderDescriptor, modelId: string): boolean;
603
+ /**
604
+ * Determines whether a provider's OpenAI-compatible Chat Completions request
605
+ * should use the modern `max_completion_tokens` field instead of the legacy
606
+ * `max_tokens` field for capping output length.
607
+ *
608
+ * @remarks
609
+ * OpenAI's Chat Completions API deprecated `max_tokens` in favor of
610
+ * `max_completion_tokens`. Every other provider routed through the shared
611
+ * OpenAI-compatible chat-completions adapter (xAI Grok, Groq, Mistral, Ollama,
612
+ * self-hosted `openai-compat` servers) still expects the legacy `max_tokens`
613
+ * field, so this returns `true` only for the `'openai'` provider id. Consulted
614
+ * by both the completion (`callProviderCompletion`) and streaming
615
+ * (`callProviderCompletionStream`) chat-completions dispatch branches. Not
616
+ * consulted on the Responses API path — `max_output_tokens` applies uniformly
617
+ * there for both OpenAI and xAI (see `isResponsesOnlyModel`) —
618
+ * nor by any non-`'openai'`-format provider (Anthropic, Gemini).
619
+ *
620
+ * @param descriptor - The provider descriptor.
621
+ * @returns `true` only for the `'openai'` provider id.
622
+ * @public
623
+ */
624
+ export declare function usesMaxCompletionTokensField(descriptor: IAiProviderDescriptor): boolean;
132
625
  /**
133
626
  * All known AI provider identifiers.
134
627
  * @public
135
628
  */
136
- export type AiProviderId = 'copy-paste' | 'xai-grok' | 'openai' | 'anthropic' | 'google-gemini' | 'groq' | 'mistral';
629
+ export type AiProviderId = 'copy-paste' | 'xai-grok' | 'openai' | 'openai-compat' | 'anthropic' | 'google-gemini' | 'groq' | 'mistral' | 'ollama';
137
630
  /**
138
631
  * API format categories for provider routing.
139
632
  * @public
140
633
  */
141
634
  export type AiApiFormat = 'openai' | 'anthropic' | 'gemini';
635
+ /**
636
+ * API format categories for image-generation provider routing.
637
+ *
638
+ * @remarks
639
+ * - `'openai-images'` — OpenAI Images API. Routes to `/images/generations`
640
+ * (text-only) or `/images/edits` (when reference images are present).
641
+ * - `'xai-images'` — xAI Images API. Text-only JSON generation request.
642
+ * - `'xai-images-edits'` — xAI Images API for Grok Imagine models. Uses JSON
643
+ * body with `{ type: "image_url" }` objects (not multipart).
644
+ * - `'gemini-image-out'` — Google Gemini chat-style `:generateContent`
645
+ * endpoint that returns image parts (Gemini Flash Image / "Nano
646
+ * Banana"). Accepts reference images.
647
+ *
648
+ * @public
649
+ */
650
+ export type AiImageApiFormat = 'openai-images' | 'xai-images' | 'xai-images-edits' | 'gemini-image-out';
651
+ /**
652
+ * API format categories for embedding provider routing.
653
+ *
654
+ * @remarks
655
+ * - `'openai-embeddings'` — OpenAI `/v1/embeddings` shape. Serves OpenAI,
656
+ * Ollama (via `/v1`), openai-compat self-hosted servers (vLLM, LM Studio,
657
+ * llama.cpp's openai-server), and Mistral (`mistral-embed`) — all of which
658
+ * speak the same request/response shape.
659
+ * - `'gemini-embeddings'` — Google Gemini `:batchEmbedContents` endpoint. A
660
+ * genuinely divergent shape (different route, auth header, request body, and
661
+ * the `taskType` retrieval-asymmetry knob that has no OpenAI analog).
662
+ *
663
+ * Named with the `ApiFormat` suffix for symmetry with `AiApiFormat` and
664
+ * `AiImageApiFormat`.
665
+ *
666
+ * @public
667
+ */
668
+ export type AiEmbeddingApiFormat = 'openai-embeddings' | 'gemini-embeddings';
142
669
  /**
143
670
  * Result of an AI provider completion call.
144
671
  * @public
@@ -149,6 +676,108 @@ export interface IAiCompletionResponse {
149
676
  /** Whether the response was truncated due to token limits */
150
677
  readonly truncated: boolean;
151
678
  }
679
+ /**
680
+ * Default `max_tokens` sent to the Anthropic Messages API when the caller does
681
+ * not supply an explicit `maxTokens` override.
682
+ *
683
+ * @remarks
684
+ * Anthropic's Messages API requires `max_tokens` on every request — there is
685
+ * no provider-side default the way there is for OpenAI Chat/Responses,
686
+ * Gemini, or xAI, all of which accept a request with no cap and apply their
687
+ * own default. Anthropic is therefore the only provider that needs — or
688
+ * gets — a library-supplied fallback; every other provider omits the field
689
+ * entirely when the caller doesn't set `maxTokens` (see
690
+ * `IProviderCompletionParams.maxTokens`).
691
+ *
692
+ * Callers whose structured/JSON output scales with input size and hits this
693
+ * ceiling see a silent truncation that often surfaces downstream as a
694
+ * confusing `extractJsonText` parse failure rather than an obvious "too
695
+ * short" error — pass `maxTokens` explicitly to raise the cap for those
696
+ * requests.
697
+ * @public
698
+ */
699
+ export declare const DEFAULT_ANTHROPIC_MAX_TOKENS: number;
700
+ /**
701
+ * A text-content delta arriving during a streaming completion.
702
+ * @public
703
+ */
704
+ export interface IAiStreamTextDelta {
705
+ readonly type: 'text-delta';
706
+ /** The newly arrived text fragment. */
707
+ readonly delta: string;
708
+ }
709
+ /**
710
+ * A server-side tool progress event arriving during a streaming completion.
711
+ * Surfaced for providers that emit explicit tool-progress markers (OpenAI
712
+ * Responses API, Anthropic). Gemini's grounding doesn't emit these.
713
+ * @public
714
+ */
715
+ export interface IAiStreamToolEvent {
716
+ readonly type: 'tool-event';
717
+ /** Which server-side tool this event describes. */
718
+ readonly toolType: AiServerToolType;
719
+ /** Tool lifecycle phase. */
720
+ readonly phase: 'started' | 'completed';
721
+ /**
722
+ * Optional provider-specific detail. For web_search this is typically the
723
+ * search query when available; format varies by provider.
724
+ */
725
+ readonly detail?: string;
726
+ }
727
+ /**
728
+ * Terminal success event for a streaming completion. Carries the aggregated
729
+ * full text and truncation status for callers that want both the progressive
730
+ * UI and the complete result.
731
+ * @public
732
+ */
733
+ export interface IAiStreamDone {
734
+ readonly type: 'done';
735
+ /** Whether the response was truncated due to token limits. */
736
+ readonly truncated: boolean;
737
+ /** The full concatenated text from all `text-delta` events. */
738
+ readonly fullText: string;
739
+ /**
740
+ * Provider-reported reason a truncated response was cut short (e.g.
741
+ * `'max_output_tokens'`, `'content_filter'`), when the provider supplies one.
742
+ * Currently populated only by the OpenAI / xAI Responses adapter, from the
743
+ * completed payload's `incomplete_details.reason`. Meaningful only when
744
+ * `truncated === true`; `undefined` otherwise (and whenever the provider
745
+ * reports truncation without a reason).
746
+ */
747
+ readonly incompleteReason?: string;
748
+ }
749
+ /**
750
+ * Terminal failure event for a streaming completion. After this event no
751
+ * further events are emitted.
752
+ *
753
+ * @remarks
754
+ * Connection-time failures (auth, network, pre-flight CORS rejection) are
755
+ * surfaced via the outer `Result.fail` returned by
756
+ * `callProviderCompletionStream` rather than as an `error` event, so callers
757
+ * can distinguish "didn't start" from "started but errored mid-stream."
758
+ *
759
+ * @public
760
+ */
761
+ export interface IAiStreamError {
762
+ readonly type: 'error';
763
+ readonly message: string;
764
+ }
765
+ /**
766
+ * Discriminated union of events emitted by a streaming completion.
767
+ *
768
+ * @remarks
769
+ * **Exhaustive-switch consumers must handle all variants.** The three
770
+ * `client-tool-*` variants were added when client-tool support shipped;
771
+ * update every exhaustive switch over this union in lockstep.
772
+ *
773
+ * @public
774
+ */
775
+ export type IAiStreamEvent = IAiStreamTextDelta | IAiStreamToolEvent | IAiStreamToolUseStart | IAiStreamToolUseDelta | IAiStreamToolUseComplete | IAiStreamDone | IAiStreamError;
776
+ /**
777
+ * Thinking/reasoning mode support for a provider.
778
+ * @public
779
+ */
780
+ export type AiThinkingMode = 'optional' | 'required' | 'unsupported';
152
781
  /**
153
782
  * Describes a single AI provider — single source of truth for all metadata.
154
783
  * @public
@@ -168,10 +797,696 @@ export interface IAiProviderDescriptor {
168
797
  readonly baseUrl: string;
169
798
  /** Default model specification — string or context-aware map. */
170
799
  readonly defaultModel: ModelSpec;
800
+ /**
801
+ * Canonical fgv alias → concrete model map for this provider. Absent means the
802
+ * provider defines no aliases and every model string passes through verbatim.
803
+ *
804
+ * @remarks
805
+ * Keys are full fgv aliases (`@<providerId>:<role>`); values are the current
806
+ * concrete model id (or a provider-native alias). Consulted by
807
+ * {@link resolveModelAlias} / {@link resolveProviderModel} at each call-time
808
+ * resolution chokepoint, downstream of the {@link ModelSpecKey} walk. Additive
809
+ * and optional — composes with the existing per-descriptor `imageGeneration` /
810
+ * `embedding` capability arrays.
811
+ */
812
+ readonly aliases?: IModelAliasMap;
171
813
  /** Which server-side tools this provider supports (empty = none). */
172
814
  readonly supportedTools: ReadonlyArray<AiServerToolType>;
173
815
  /** Whether this provider's API enforces CORS restrictions that prevent direct browser calls. */
174
816
  readonly corsRestricted: boolean;
817
+ /**
818
+ * Whether this provider's streaming completion endpoint requires a proxy
819
+ * for direct browser calls. Some providers gate streaming separately from
820
+ * non-streaming (rare), so this is tracked independently from
821
+ * {@link IAiProviderDescriptor.corsRestricted}.
822
+ *
823
+ * @remarks
824
+ * When `true`, `callProviderCompletionStream` rejects up front unless the
825
+ * call is being routed through a proxy.
826
+ */
827
+ readonly streamingCorsRestricted: boolean;
828
+ /**
829
+ * Whether this provider's chat completions API accepts image input
830
+ * (i.e. supports vision prompts). When false, calls with
831
+ * `prompt.attachments` are rejected up front.
832
+ */
833
+ readonly acceptsImageInput: boolean;
834
+ /**
835
+ * Whether this provider supports thinking/reasoning mode.
836
+ * - 'optional': thinking can be enabled but is not required
837
+ * - 'required': thinking is always active (e.g. o-series models)
838
+ * - 'unsupported': thinking is not supported
839
+ */
840
+ readonly thinkingMode: AiThinkingMode;
841
+ /**
842
+ * Image-generation capabilities, scoped to model id prefixes. Empty or
843
+ * undefined means the provider does not support image generation.
844
+ *
845
+ * @remarks
846
+ * The dispatcher matches the resolved model id against each rule's
847
+ * `modelPrefix` and selects the longest match (see
848
+ * {@link AiAssist.resolveImageCapability}). An empty `modelPrefix` is the
849
+ * catch-all and matches every model id.
850
+ *
851
+ * Multiple entries support providers that host more than one image-API
852
+ * surface under one baseUrl. The dispatcher selects the longest-matching
853
+ * prefix, so a provider can list a specific-prefix surface alongside an
854
+ * empty-prefix catch-all and the right model routes to the right API.
855
+ *
856
+ * Image-model selection reuses the existing `image` {@link ModelSpecKey}.
857
+ * Providers that declare `imageGeneration` should declare a model in
858
+ * `defaultModel.image`, e.g. `{ base: '@openai:mini', image: '@openai:image' }`.
859
+ */
860
+ readonly imageGeneration?: ReadonlyArray<IAiImageModelCapability>;
861
+ /**
862
+ * Embedding capabilities, scoped to model id prefixes. Empty or undefined
863
+ * means the provider does not support embeddings.
864
+ *
865
+ * @remarks
866
+ * The dispatcher matches the resolved embedding model id against each rule's
867
+ * `modelPrefix` and selects the longest match (see
868
+ * {@link AiAssist.resolveEmbeddingCapability}). An empty `modelPrefix` is the
869
+ * catch-all and matches every model id.
870
+ *
871
+ * Embedding-model selection uses the `embedding` {@link ModelSpecKey}.
872
+ * Providers that declare `embedding` should declare a model in
873
+ * `defaultModel.embedding`, e.g. `{ base: '@openai:mini', embedding: '@openai:embedding' }`.
874
+ * Self-hosted providers (`ollama`, `openai-compat`) leave it unset — the
875
+ * caller supplies the embedding model via `modelOverride`.
876
+ */
877
+ readonly embedding?: ReadonlyArray<IAiEmbeddingModelCapability>;
878
+ /**
879
+ * Concrete model ids (prefix-matched) that must be invoked via the OpenAI
880
+ * Responses API rather than chat completions — e.g. `gpt-5.5-pro`. Non-OpenAI
881
+ * `apiFormat`s ignore this.
882
+ *
883
+ * @remarks
884
+ * Some current-generation OpenAI models (the `-pro` tier) are Responses-API-only
885
+ * and 400 on `/chat/completions`. The completion and streaming dispatch consult
886
+ * this list (via the sibling predicate {@link AiAssist.isResponsesOnlyModel})
887
+ * and route a matching model to the Responses path
888
+ * even when no tools are requested. Mirrors the prefix-matching shape of the
889
+ * `imageGeneration` / `embedding` capability arrays; adding a new Responses-only
890
+ * line is a one-entry descriptor edit. Empty or undefined means no model is
891
+ * Responses-only.
892
+ */
893
+ readonly responsesOnlyModelPrefixes?: ReadonlyArray<string>;
894
+ /**
895
+ * Concrete Anthropic model ids (exact-or-dash-bounded-prefix-matched) that require the
896
+ * adaptive thinking wire shape (`thinking: { type: 'adaptive' }` + top-level
897
+ * `output_config: { effort }`) rather than the legacy manual-budget shape
898
+ * (`thinking: { type: 'enabled', budget_tokens }`). Non-Anthropic `apiFormat`s ignore this.
899
+ *
900
+ * @remarks
901
+ * The Claude 5 family (`claude-sonnet-5`, `claude-opus-5`, `claude-fable-5`, including their
902
+ * dated snapshots) rejects `thinking.type: 'enabled'` with an HTTP 400 and requires the
903
+ * adaptive shape; older models (`claude-sonnet-4-6`, `claude-opus-4-8`, `claude-haiku-4-5`,
904
+ * etc.) keep the legacy shape. The completion (`callProviderCompletion`), streaming
905
+ * (`callProviderCompletionStream`), and client-tool (`executeClientToolTurn`) Anthropic
906
+ * dispatch sites consult this list (via the sibling predicate
907
+ * `isAdaptiveThinkingModel`) to pick the correct wire shape for the resolved
908
+ * model. Mirrors the prefix-matching shape of `responsesOnlyModelPrefixes`, but with
909
+ * exact-or-dash-bounded matching (an entry matches a resolved model that equals it or starts
910
+ * with it followed by `-`) rather than a plain prefix, since Anthropic model families share
911
+ * numeric leading characters (`claude-sonnet-5` vs. a hypothetical `claude-sonnet-50`).
912
+ * Empty or undefined means no model uses the adaptive shape.
913
+ */
914
+ readonly adaptiveThinkingModelPrefixes?: ReadonlyArray<string>;
915
+ }
916
+ /**
917
+ * Image-generation capability for a model family within a provider. Used as
918
+ * an entry in {@link IAiProviderDescriptor.imageGeneration}.
919
+ *
920
+ * @public
921
+ */
922
+ export interface IAiImageModelCapability {
923
+ /**
924
+ * Prefix matched against the resolved image model id. The empty string is
925
+ * the catch-all and matches every model. When multiple rules' prefixes
926
+ * match a model id, the longest prefix wins; ties are broken by
927
+ * first-encountered.
928
+ */
929
+ readonly modelPrefix: string;
930
+ /** API format used to dispatch requests for matching models. */
931
+ readonly format: AiImageApiFormat;
932
+ /**
933
+ * Whether matching models accept reference images via
934
+ * {@link AiAssist.IAiImageGenerationParams.referenceImages}. When false or
935
+ * undefined, calls that include reference images are rejected up front.
936
+ */
937
+ readonly acceptsImageReferenceInput?: boolean;
938
+ /** Accepted size strings. When present, dispatcher pre-validates. */
939
+ readonly acceptedSizes?: ReadonlyArray<string>;
940
+ /** When true, quality param is sent. When false/undefined, don't send quality. */
941
+ readonly supportsQualityParam?: boolean;
942
+ /** Accepted quality values when supportsQualityParam is true. */
943
+ readonly acceptedQualities?: ReadonlyArray<string>;
944
+ /** Maximum count (n). When present, dispatcher pre-validates. */
945
+ readonly maxCount?: number;
946
+ /**
947
+ * How to encode the output format on the wire:
948
+ * - 'response-format': send response_format: 'b64_json' (openai-images catch-all)
949
+ * - 'output-format': send output_format (gpt-image-1)
950
+ * - 'none': send neither (Gemini Flash)
951
+ */
952
+ readonly outputParamStyle?: 'response-format' | 'output-format' | 'none';
953
+ /** Default MIME type for response images. */
954
+ readonly defaultOutputMimeType?: string;
955
+ }
956
+ /**
957
+ * Embedding capability for a model family within a provider. Used as an entry
958
+ * in {@link IAiProviderDescriptor.embedding}.
959
+ *
960
+ * @public
961
+ */
962
+ export interface IAiEmbeddingModelCapability {
963
+ /**
964
+ * Prefix matched against the resolved embedding model id. The empty string is
965
+ * the catch-all and matches every model. When multiple rules' prefixes match
966
+ * a model id, the longest prefix wins; ties are broken by first-encountered.
967
+ */
968
+ readonly modelPrefix: string;
969
+ /** API format used to dispatch requests for matching models. */
970
+ readonly format: AiEmbeddingApiFormat;
971
+ /**
972
+ * Whether matching models honor a requested output `dimensions`
973
+ * (OpenAI `text-embedding-3-*`, Gemini `gemini-embedding-001` via MRL
974
+ * truncation). When false/undefined, a caller-supplied `dimensions` is a
975
+ * no-op (logged, not failed — see {@link AiAssist.IAiEmbeddingParams}).
976
+ */
977
+ readonly supportsDimensions?: boolean;
978
+ /**
979
+ * Whether matching models honor a `taskType` hint (Gemini only today). When
980
+ * false/undefined, a caller-supplied `taskType` is a no-op (logged, not
981
+ * failed).
982
+ */
983
+ readonly supportsTaskType?: boolean;
984
+ /** Native fixed output dimension, when the model has one (metadata only). */
985
+ readonly defaultDimensions?: number;
986
+ /**
987
+ * Maximum number of inputs accepted per request. When present, the dispatcher
988
+ * rejects batches larger than this up front (no auto-chunking in v1).
989
+ */
990
+ readonly maxBatchSize?: number;
991
+ }
992
+ /**
993
+ * A single embedding task-type hint (Gemini-style). Cross-provider; providers
994
+ * that don't support task typing ignore it (logged, not failed). Open string
995
+ * union so new Gemini task types don't force a churn, with the known set
996
+ * enumerated for ergonomics.
997
+ *
998
+ * @remarks
999
+ * Values are the kebab-case cross-provider form; the Gemini adapter maps them to
1000
+ * `SCREAMING_SNAKE_CASE` on the wire (e.g. `'retrieval-document'` →
1001
+ * `RETRIEVAL_DOCUMENT`).
1002
+ *
1003
+ * @public
1004
+ */
1005
+ export type AiEmbeddingTaskType = 'retrieval-query' | 'retrieval-document' | 'semantic-similarity' | 'classification' | 'clustering' | 'code-retrieval-query' | 'question-answering' | 'fact-verification' | (string & {});
1006
+ /**
1007
+ * Parameters for an embedding request. Batch is the norm: `input` accepts a
1008
+ * single string or an array; the result always exposes a vector array aligned
1009
+ * by index to the input.
1010
+ *
1011
+ * @public
1012
+ */
1013
+ export interface IAiEmbeddingParams {
1014
+ /** One or more input strings. A bare string is treated as a single-element batch. */
1015
+ readonly input: string | ReadonlyArray<string>;
1016
+ /**
1017
+ * Requested output dimensionality. Honored only by models whose capability
1018
+ * declares `supportsDimensions` (OpenAI `text-embedding-3-*`, Gemini
1019
+ * `gemini-embedding-001` via MRL truncation). Ignored — with a `logger.info`
1020
+ * note — by models that don't.
1021
+ */
1022
+ readonly dimensions?: number;
1023
+ /**
1024
+ * Task-type hint. Mapped to Gemini `taskType`; a no-op (with a `logger.info`
1025
+ * note) on OpenAI/Ollama/compat/Mistral. Preserves Gemini's
1026
+ * query-vs-document retrieval asymmetry.
1027
+ */
1028
+ readonly taskType?: AiEmbeddingTaskType;
1029
+ }
1030
+ /**
1031
+ * Token-usage accounting for an embedding call, when the provider reports it.
1032
+ * @public
1033
+ */
1034
+ export interface IAiEmbeddingUsage {
1035
+ /** Tokens consumed by the input(s). */
1036
+ readonly promptTokens?: number;
1037
+ /** Total tokens billed. */
1038
+ readonly totalTokens?: number;
1039
+ }
1040
+ /**
1041
+ * Result of an embedding call. `vectors[i]` is the embedding for `input[i]`,
1042
+ * in request order.
1043
+ *
1044
+ * @remarks
1045
+ * Vectors are plain `number[]` (not `Float32Array`) for JSON-wire fidelity and
1046
+ * validator-friendliness — consumers who want a typed array call
1047
+ * `Float32Array.from(vector)` at the vector-store / WebGPU boundary. The
1048
+ * library does not L2-normalize; Gemini's MRL truncation (when
1049
+ * `dimensions < native`) returns un-normalized vectors that the consumer should
1050
+ * normalize if their similarity metric requires it.
1051
+ *
1052
+ * @public
1053
+ */
1054
+ export interface IAiEmbeddingResult {
1055
+ /** One vector per input, aligned by index to the request order. */
1056
+ readonly vectors: ReadonlyArray<ReadonlyArray<number>>;
1057
+ /** The resolved provider-native model id that produced the vectors. */
1058
+ readonly model: string;
1059
+ /** Dimensionality of each returned vector (`vectors[0].length`; `0` for empty input). */
1060
+ readonly dimensions: number;
1061
+ /** Token usage, when the provider reports it (OpenAI-format; absent for Gemini). */
1062
+ readonly usage?: IAiEmbeddingUsage;
1063
+ }
1064
+ /** Pixel dimension sizes accepted by gpt-image-1. @public */
1065
+ export type GptImageSize = '1024x1024' | '1536x1024' | '1024x1536' | 'auto';
1066
+ /** All accepted image size strings across all providers. @public */
1067
+ export type AiImageSize = GptImageSize;
1068
+ /** Quality values for gpt-image-1. @public */
1069
+ export type GptImageQuality = 'low' | 'medium' | 'high' | 'auto';
1070
+ /** All accepted quality strings across all providers. @public */
1071
+ export type AiImageQuality = GptImageQuality;
1072
+ /** Model names in the GPT Image family. @public */
1073
+ export type GptImageModelNames = 'gpt-image-1' | 'gpt-image-1.5' | 'gpt-image-2';
1074
+ /** Model names in the xAI Grok Imagine family. @public */
1075
+ export type GrokImagineModelNames = 'grok-imagine-image' | 'grok-imagine-image-quality';
1076
+ /** Model names in the Gemini Flash Image family. @public */
1077
+ export type GeminiFlashImageModelNames = 'gemini-3.1-flash-image';
1078
+ /**
1079
+ * Provider-specific config for gpt-image-1.
1080
+ * @public
1081
+ */
1082
+ export interface IGptImageGenerationConfig {
1083
+ /** Image dimensions. */
1084
+ readonly size?: GptImageSize;
1085
+ /** Quality tier. */
1086
+ readonly quality?: GptImageQuality;
1087
+ /** Output format (replaces response_format for this model). */
1088
+ readonly outputFormat?: 'png' | 'jpeg' | 'webp';
1089
+ /** JPEG/WebP compression level 0–100. */
1090
+ readonly outputCompression?: number;
1091
+ /** Background transparency control. */
1092
+ readonly background?: 'transparent' | 'opaque' | 'auto';
1093
+ /** Content moderation strictness. */
1094
+ readonly moderation?: 'low' | 'auto';
1095
+ }
1096
+ /**
1097
+ * Provider-specific config for xAI Grok Imagine models.
1098
+ * @public
1099
+ */
1100
+ export interface IGrokImagineImageGenerationConfig {
1101
+ /** Aspect ratio string (xAI uses aspect ratios, not pixel dimensions). */
1102
+ readonly aspectRatio?: string;
1103
+ /** Resolution hint. */
1104
+ readonly resolution?: string;
1105
+ }
1106
+ /**
1107
+ * Provider-specific config for Gemini Flash Image.
1108
+ * @public
1109
+ */
1110
+ export interface IGeminiFlashImageGenerationConfig {
1111
+ /** Aspect ratio string. */
1112
+ readonly aspectRatio?: string;
1113
+ }
1114
+ /**
1115
+ * Base shape shared by all named family option blocks.
1116
+ * Provides a typed `models` field for applicability filtering without unsafe casts.
1117
+ * @internal
1118
+ */
1119
+ export interface INamedModelFamilyConfig {
1120
+ readonly models?: readonly string[];
1121
+ }
1122
+ /**
1123
+ * Options block scoped to GPT Image family models.
1124
+ * @public
1125
+ */
1126
+ export interface IGptImageModelOptions extends INamedModelFamilyConfig {
1127
+ readonly provider: 'openai';
1128
+ readonly family: 'gpt-image';
1129
+ readonly models?: GptImageModelNames[];
1130
+ readonly config: IGptImageGenerationConfig;
1131
+ }
1132
+ /**
1133
+ * Options block scoped to xAI Grok Imagine family models.
1134
+ * @public
1135
+ */
1136
+ export interface IGrokImagineModelOptions extends INamedModelFamilyConfig {
1137
+ readonly provider: 'xai';
1138
+ readonly family: 'grok-imagine';
1139
+ readonly models?: GrokImagineModelNames[];
1140
+ readonly config: IGrokImagineImageGenerationConfig;
1141
+ }
1142
+ /**
1143
+ * Options block scoped to Gemini Flash Image models.
1144
+ * @public
1145
+ */
1146
+ export interface IGeminiFlashImageModelOptions extends INamedModelFamilyConfig {
1147
+ readonly provider: 'google';
1148
+ readonly family: 'gemini-flash-image';
1149
+ readonly models?: GeminiFlashImageModelNames[];
1150
+ readonly config: IGeminiFlashImageGenerationConfig;
1151
+ }
1152
+ /**
1153
+ * Escape-hatch options block for models not covered by a named family.
1154
+ * @remarks
1155
+ * `models` is required — there is no implicit "all" for unknown model families.
1156
+ * `config` is `JsonObject` — passed verbatim to the wire request with no validation.
1157
+ * This is the "trust me, I know what I'm doing" path for callers who need to send
1158
+ * wire params our typed configs don't yet expose.
1159
+ * @public
1160
+ */
1161
+ export interface IOtherModelOptions {
1162
+ readonly provider: 'other';
1163
+ readonly models: string[];
1164
+ readonly config: JsonObject;
1165
+ }
1166
+ /**
1167
+ * Discriminated union of all model-family option blocks.
1168
+ * Discriminated on `provider` + `family` fields.
1169
+ * @public
1170
+ */
1171
+ export type IModelFamilyConfig = IGptImageModelOptions | IGrokImagineModelOptions | IGeminiFlashImageModelOptions | IOtherModelOptions;
1172
+ /**
1173
+ * Options for image generation requests.
1174
+ *
1175
+ * @remarks
1176
+ * Uses a layered architecture:
1177
+ * 1. Generic top-level options (size, count, quality, seed) apply across providers
1178
+ * via the resolved model's registry mapping.
1179
+ * 2. Optional `models` array contains model-family-scoped blocks; the resolver
1180
+ * picks applicable blocks based on the resolved model and applies them in
1181
+ * declaration order.
1182
+ *
1183
+ * **Merge precedence (later wins):**
1184
+ * 1. Generic top-level options (lowest precedence)
1185
+ * 2. Family-generic blocks (matching family, models field omitted)
1186
+ * 3. Model-specific blocks (models array includes resolved model name)
1187
+ * 4. Other blocks (provider: 'other', models array includes resolved model name)
1188
+ *
1189
+ * Provider-mismatch: blocks whose provider doesn't match the dispatcher's
1190
+ * provider lineage are silently skipped.
1191
+ *
1192
+ * @public
1193
+ */
1194
+ export interface IAiImageGenerationOptions {
1195
+ /**
1196
+ * Image dimensions for OpenAI models (mapped to `size` field).
1197
+ * For xAI or Gemini Flash aspect ratio, use the corresponding `models` family block.
1198
+ */
1199
+ readonly size?: AiImageSize;
1200
+ /** Number of images. Default 1. Some models enforce a maximum. */
1201
+ readonly count?: number;
1202
+ /**
1203
+ * Quality tier. Accepted values differ per model:
1204
+ * - gpt-image-1: 'low' | 'medium' | 'high' | 'auto'
1205
+ * Other models ignore this field.
1206
+ */
1207
+ readonly quality?: AiImageQuality;
1208
+ /** Reproducibility seed, where supported. */
1209
+ readonly seed?: number;
1210
+ /**
1211
+ * Optional precision via model-family-scoped blocks. The resolver picks
1212
+ * applicable blocks dynamically based on the resolved model.
1213
+ */
1214
+ readonly models?: ReadonlyArray<IModelFamilyConfig>;
1215
+ }
1216
+ /**
1217
+ * Parameters for an image-generation request.
1218
+ * @public
1219
+ */
1220
+ export interface IAiImageGenerationParams {
1221
+ /** The text prompt describing the desired image. */
1222
+ readonly prompt: string;
1223
+ /** Optional generation options. */
1224
+ readonly options?: IAiImageGenerationOptions;
1225
+ /**
1226
+ * Optional reference images. When present, the provider will use them as
1227
+ * visual context (e.g. to preserve a character's appearance across multiple
1228
+ * generations). The dispatcher resolves the
1229
+ * {@link AiAssist.IAiImageModelCapability} for the requested model and
1230
+ * rejects the call up front if `acceptsImageReferenceInput` is not set on
1231
+ * the matching capability. An empty array is treated identically to
1232
+ * `undefined`.
1233
+ */
1234
+ readonly referenceImages?: ReadonlyArray<IAiImageAttachment>;
1235
+ }
1236
+ /**
1237
+ * A single generated image.
1238
+ * @public
1239
+ */
1240
+ export interface IAiGeneratedImage extends IAiImageData {
1241
+ /**
1242
+ * The prompt as rewritten by the provider, if any. OpenAI's image models
1243
+ * commonly rewrite prompts; other providers do not.
1244
+ */
1245
+ readonly revisedPrompt?: string;
1246
+ }
1247
+ /**
1248
+ * Capability vocabulary used to describe what a model can do. Used as both
1249
+ * a filter and as a tag in {@link AiAssist.IAiModelInfo.capabilities}.
1250
+ *
1251
+ * @remarks
1252
+ * Adding a new capability is cheap; adding the *first* one after consumers
1253
+ * already exist forces churn. The initial vocabulary is intentionally broad
1254
+ * even though only `image-generation` is fully exercised today.
1255
+ *
1256
+ * @public
1257
+ */
1258
+ export type AiModelCapability = 'chat' | 'tools' | 'vision' | 'image-generation' | 'thinking' | 'embedding';
1259
+ /**
1260
+ * All valid `AiModelCapability` values — the single source of truth for
1261
+ * the capability vocabulary (used by validators and capability filters).
1262
+ * @public
1263
+ */
1264
+ export declare const allModelCapabilities: ReadonlyArray<AiModelCapability>;
1265
+ /**
1266
+ * Information about a single model returned by a provider's list endpoint,
1267
+ * with capabilities already resolved (native + config rules).
1268
+ * @public
1269
+ */
1270
+ export interface IAiModelInfo {
1271
+ /** Provider-native model identifier. */
1272
+ readonly id: string;
1273
+ /** Resolved capability set — union of native declarations and config rules. */
1274
+ readonly capabilities: ReadonlySet<AiModelCapability>;
1275
+ /** Friendly name for display, when known. */
1276
+ readonly displayName?: string;
1277
+ }
1278
+ /**
1279
+ * One rule in an {@link IAiModelCapabilityConfig}. Multiple rules can match
1280
+ * a single model — their capability arrays are unioned.
1281
+ * @public
1282
+ */
1283
+ export interface IAiModelCapabilityRule {
1284
+ /** RegExp tested against the model id (using `.test`). */
1285
+ readonly idPattern: RegExp;
1286
+ /** Capabilities this rule attributes to matching models. */
1287
+ readonly capabilities: ReadonlyArray<AiModelCapability>;
1288
+ /**
1289
+ * Friendly display-name override for matching models. The function form
1290
+ * lets one rule format many ids (e.g. `(id) => id.toUpperCase()`).
1291
+ * If multiple matching rules supply `displayName`, the first match wins.
1292
+ */
1293
+ readonly displayName?: string | ((id: string) => string);
1294
+ }
1295
+ /**
1296
+ * Configuration that maps model id patterns to capabilities. Used to
1297
+ * augment (or, where the provider supplies no capability info, fully
1298
+ * derive) the capability set for each listed model.
1299
+ * @public
1300
+ */
1301
+ export interface IAiModelCapabilityConfig {
1302
+ /** Per-provider rules. Tried before {@link AiAssist.IAiModelCapabilityConfig.global}. */
1303
+ readonly perProvider?: {
1304
+ readonly [P in AiProviderId]?: ReadonlyArray<IAiModelCapabilityRule>;
1305
+ };
1306
+ /** Cross-provider fallback rules. */
1307
+ readonly global?: ReadonlyArray<IAiModelCapabilityRule>;
1308
+ }
1309
+ /**
1310
+ * Result of an image-generation call.
1311
+ * @public
1312
+ */
1313
+ export interface IAiImageGenerationResponse {
1314
+ /** The generated images, in provider-returned order. */
1315
+ readonly images: ReadonlyArray<IAiGeneratedImage>;
1316
+ }
1317
+ /**
1318
+ * Model IDs for Anthropic thinking-capable models.
1319
+ *
1320
+ * @remarks
1321
+ * Only thinking-capable lines are listed. The non-tier `@anthropic:haiku` alias (reachable via
1322
+ * `modelOverride` only) is deliberately omitted — it is not documented as thinking-capable, so
1323
+ * naming it in a thinking-model filter would be misleading. `claude-fable-5` (the `@anthropic:fable`
1324
+ * non-tier alias) is thinking-capable and reachable via `modelOverride`, so it is listed.
1325
+ * @public
1326
+ */
1327
+ 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' | 'claude-opus-5' | 'claude-fable-5';
1328
+ /**
1329
+ * Model IDs for OpenAI thinking-capable models.
1330
+ * @public
1331
+ */
1332
+ 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.6-sol' | 'gpt-5.6-terra' | 'gpt-5.6-luna' | 'gpt-5-pro';
1333
+ /**
1334
+ * Model IDs for Google Gemini thinking-capable models.
1335
+ * @public
1336
+ */
1337
+ export type GeminiThinkingModelNames = 'gemini-3.1-pro-preview' | 'gemini-3.5-flash' | 'gemini-3.1-flash-lite';
1338
+ /**
1339
+ * Model IDs for xAI thinking-capable models.
1340
+ * @public
1341
+ */
1342
+ export type XAiThinkingModelNames = 'grok-3-mini' | 'grok-4.3' | 'grok-4' | 'grok-4.5';
1343
+ /**
1344
+ * Anthropic-specific thinking configuration.
1345
+ * @public
1346
+ */
1347
+ export interface IAnthropicThinkingConfig {
1348
+ /**
1349
+ * Anthropic effort level. The emit-site converts to `thinking.budget_tokens`
1350
+ * (the integer budget the Anthropic API requires). Mapping policy: low = 2048,
1351
+ * medium = 8192, high = 24000, max = 32000.
1352
+ * - 'low' | 'medium' | 'high': all thinking-capable models
1353
+ * - 'max': Opus 4.6 only
1354
+ */
1355
+ readonly effort?: 'low' | 'medium' | 'high' | 'max';
1356
+ }
1357
+ /**
1358
+ * OpenAI-specific thinking configuration.
1359
+ * @remarks
1360
+ * Maps to `reasoning_effort` (Chat Completions path) or `reasoning.effort`
1361
+ * (Responses API path) on the wire. The adapter selects the correct field.
1362
+ * @public
1363
+ */
1364
+ export interface IOpenAiThinkingConfig {
1365
+ /**
1366
+ * OpenAI reasoning effort. Maps 1:1 to the wire field.
1367
+ * - 'none': disables reasoning (gpt-5.x only; rejected by o-series)
1368
+ * - 'minimal': fastest (gpt-5.x)
1369
+ * - 'low' | 'medium' | 'high': standard tiers
1370
+ * - 'xhigh': highest (select gpt-5.x models only)
1371
+ *
1372
+ * @remarks
1373
+ * When effective effort is 'none', reasoning is disabled and temperature is
1374
+ * accepted by gpt-5.x models. This is the only case where temperature and
1375
+ * thinking config co-exist without a Result.fail.
1376
+ */
1377
+ readonly effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
1378
+ }
1379
+ /**
1380
+ * Google Gemini-specific thinking configuration.
1381
+ * @public
1382
+ */
1383
+ export interface IGeminiThinkingConfig {
1384
+ /**
1385
+ * Token budget for thinking. Maps 1:1 to `thinkingBudget` on the wire.
1386
+ * - 0: disable thinking (Flash and Flash-Lite only; error on Pro)
1387
+ * - positive integer: soft token cap
1388
+ * - -1: dynamic
1389
+ * - omitted: model default
1390
+ */
1391
+ readonly thinkingBudget?: number;
1392
+ /**
1393
+ * Whether to include thought summaries in the response.
1394
+ * @remarks
1395
+ * INERT in phase B. Adapters never send `includeThoughts: true`.
1396
+ * Wired up by the followup stream `ai-assist-thinking-events`.
1397
+ */
1398
+ readonly includeThoughts?: boolean;
1399
+ }
1400
+ /**
1401
+ * xAI-specific thinking configuration.
1402
+ * @public
1403
+ */
1404
+ export interface IXAiThinkingConfig {
1405
+ /**
1406
+ * xAI reasoning effort. Maps 1:1 to `reasoning_effort` on the wire.
1407
+ * For grok-4, the adapter omits this field (grok-4 always reasons and
1408
+ * rejects the parameter).
1409
+ */
1410
+ readonly effort?: 'none' | 'low' | 'medium' | 'high';
1411
+ }
1412
+ /**
1413
+ * Anthropic-specific thinking options block.
1414
+ * @public
1415
+ */
1416
+ export interface IAnthropicThinkingOptions {
1417
+ readonly provider: 'anthropic';
1418
+ readonly models?: ReadonlyArray<AnthropicThinkingModelNames>;
1419
+ readonly config: IAnthropicThinkingConfig;
1420
+ }
1421
+ /**
1422
+ * OpenAI-specific thinking options block.
1423
+ * @public
1424
+ */
1425
+ export interface IOpenAiThinkingOptions {
1426
+ readonly provider: 'openai';
1427
+ readonly models?: ReadonlyArray<OpenAiThinkingModelNames>;
1428
+ readonly config: IOpenAiThinkingConfig;
1429
+ }
1430
+ /**
1431
+ * Google Gemini-specific thinking options block.
1432
+ * @public
1433
+ */
1434
+ export interface IGeminiThinkingOptions {
1435
+ readonly provider: 'google';
1436
+ readonly models?: ReadonlyArray<GeminiThinkingModelNames>;
1437
+ readonly config: IGeminiThinkingConfig;
1438
+ }
1439
+ /**
1440
+ * xAI-specific thinking options block.
1441
+ * @public
1442
+ */
1443
+ export interface IXAiThinkingOptions {
1444
+ readonly provider: 'xai';
1445
+ readonly models?: ReadonlyArray<XAiThinkingModelNames>;
1446
+ readonly config: IXAiThinkingConfig;
1447
+ }
1448
+ /**
1449
+ * Escape-hatch options block for providers not covered by typed configs.
1450
+ * @remarks
1451
+ * `models` is required — no implicit "all" for unknown providers.
1452
+ * `config` fields are merged verbatim into the wire request.
1453
+ * @public
1454
+ */
1455
+ export interface IOtherThinkingOptions {
1456
+ readonly provider: 'other';
1457
+ readonly models: ReadonlyArray<string>;
1458
+ readonly config: JsonObject;
1459
+ }
1460
+ /**
1461
+ * Discriminated union of per-provider thinking config blocks.
1462
+ * @public
1463
+ */
1464
+ export type IThinkingProviderConfig = IAnthropicThinkingOptions | IOpenAiThinkingOptions | IGeminiThinkingOptions | IXAiThinkingOptions | IOtherThinkingOptions;
1465
+ /**
1466
+ * Thinking/reasoning mode configuration for a completion request.
1467
+ *
1468
+ * @remarks
1469
+ * The generic `effort` field covers the common-subset cross-provider vocabulary.
1470
+ * For provider-specific precision (Anthropic 'max', OpenAI 'xhigh', Gemini token
1471
+ * budgets, xAI effort-level tuning), use the `providers` array.
1472
+ *
1473
+ * Absence (or undefined) means "no thinking mode" — existing callers are unaffected.
1474
+ *
1475
+ * @public
1476
+ */
1477
+ export interface IThinkingConfig {
1478
+ /**
1479
+ * Cross-provider effort level. Common-subset mapping:
1480
+ * - 'low': Anthropic effort:low | OpenAI effort:low | Gemini thinkingBudget:1024 | xAI reasoning_effort:low
1481
+ * - 'medium': effort:medium | effort:medium | thinkingBudget:4096 | reasoning_effort:medium
1482
+ * - 'high': effort:high | effort:high | thinkingBudget:8192 | reasoning_effort:high
1483
+ */
1484
+ readonly effort?: 'low' | 'medium' | 'high';
1485
+ /**
1486
+ * Optional per-provider precision blocks. Blocks for providers that don't
1487
+ * match the resolved model's provider are silently skipped.
1488
+ */
1489
+ readonly providers?: ReadonlyArray<IThinkingProviderConfig>;
175
1490
  }
176
1491
  /**
177
1492
  * Configuration for a single AI assist provider.
@@ -186,6 +1501,14 @@ export interface IAiAssistProviderConfig {
186
1501
  readonly model?: ModelSpec;
187
1502
  /** Tool enablement/configuration. Tools are disabled unless explicitly enabled. */
188
1503
  readonly tools?: ReadonlyArray<IAiToolEnablement>;
1504
+ /**
1505
+ * Optional caller-supplied endpoint URL (http/https). Overrides
1506
+ * `descriptor.baseUrl` for this provider. Used to point a provider at a
1507
+ * self-hosted server (Ollama, LM Studio, llama.cpp's openai-server) or a
1508
+ * local proxy. Validation lives in `@fgv/ts-extras` — query strings,
1509
+ * fragments, and userinfo are rejected.
1510
+ */
1511
+ readonly endpoint?: string;
189
1512
  }
190
1513
  /**
191
1514
  * AI assist settings — which providers are enabled and their configuration.
@@ -219,4 +1542,15 @@ export interface IAiAssistKeyStore {
219
1542
  /** Get an API key by secret name */
220
1543
  getApiKey(name: string): Result<string>;
221
1544
  }
1545
+ /**
1546
+ * Returns the canonical `CryptoUtils.KeyStore.KeyStore` secret name for a provider's API key,
1547
+ * of the form `provider:<providerId>`. Apps that store provider API keys in a `KeyStore`
1548
+ * should use this name (rather than inventing their own) so that a single keystore vault
1549
+ * works consistently across every fgv app.
1550
+ *
1551
+ * @param providerId - The provider whose API key secret name is requested.
1552
+ * @returns The canonical keystore secret name, e.g. `'provider:openai'`.
1553
+ * @public
1554
+ */
1555
+ export declare function providerApiKeySecretName(providerId: AiProviderId): string;
222
1556
  //# sourceMappingURL=model.d.ts.map