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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. package/dist/index.browser.js +4 -2
  2. package/dist/index.browser.js.map +1 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/packlets/ai-assist/apiClient.js +886 -158
  5. package/dist/packlets/ai-assist/apiClient.js.map +1 -0
  6. package/dist/packlets/ai-assist/chatRequestBuilders.js +282 -0
  7. package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  8. package/dist/packlets/ai-assist/converters.js +47 -3
  9. package/dist/packlets/ai-assist/converters.js.map +1 -0
  10. package/dist/packlets/ai-assist/embeddingClient.js +345 -0
  11. package/dist/packlets/ai-assist/embeddingClient.js.map +1 -0
  12. package/dist/packlets/ai-assist/endpoint.js +78 -0
  13. package/dist/packlets/ai-assist/endpoint.js.map +1 -0
  14. package/dist/packlets/ai-assist/http.js +75 -0
  15. package/dist/packlets/ai-assist/http.js.map +1 -0
  16. package/dist/packlets/ai-assist/imageOptionsResolver.js +193 -0
  17. package/dist/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  18. package/dist/packlets/ai-assist/index.js +10 -4
  19. package/dist/packlets/ai-assist/index.js.map +1 -0
  20. package/dist/packlets/ai-assist/jsonCompletion.js +93 -0
  21. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -0
  22. package/dist/packlets/ai-assist/jsonResponse.js +149 -0
  23. package/dist/packlets/ai-assist/jsonResponse.js.map +1 -0
  24. package/dist/packlets/ai-assist/model.js +193 -9
  25. package/dist/packlets/ai-assist/model.js.map +1 -0
  26. package/dist/packlets/ai-assist/registry.js +314 -12
  27. package/dist/packlets/ai-assist/registry.js.map +1 -0
  28. package/dist/packlets/ai-assist/sseParser.js +123 -0
  29. package/dist/packlets/ai-assist/sseParser.js.map +1 -0
  30. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +368 -0
  31. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  32. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +687 -0
  33. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  34. package/dist/packlets/ai-assist/streamingAdapters/common.js +187 -0
  35. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  36. package/dist/packlets/ai-assist/streamingAdapters/gemini.js +204 -0
  37. package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  38. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +170 -0
  39. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  40. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +386 -0
  41. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  42. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +173 -0
  43. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  44. package/dist/packlets/ai-assist/streamingClient.js +140 -0
  45. package/dist/packlets/ai-assist/streamingClient.js.map +1 -0
  46. package/dist/packlets/ai-assist/thinkingOptionsResolver.js +288 -0
  47. package/dist/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  48. package/dist/packlets/ai-assist/toolFormats.js +106 -10
  49. package/dist/packlets/ai-assist/toolFormats.js.map +1 -0
  50. package/dist/packlets/conversion/converters.js +35 -1
  51. package/dist/packlets/conversion/converters.js.map +1 -0
  52. package/dist/packlets/conversion/index.js.map +1 -0
  53. package/dist/packlets/crypto-utils/constants.js.map +1 -0
  54. package/dist/packlets/crypto-utils/converters.js +42 -4
  55. package/dist/packlets/crypto-utils/converters.js.map +1 -0
  56. package/dist/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  57. package/dist/packlets/crypto-utils/encryptedFile.js.map +1 -0
  58. package/dist/packlets/crypto-utils/hpkeProvider.js +333 -0
  59. package/dist/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  60. package/dist/packlets/crypto-utils/index.browser.js +10 -2
  61. package/dist/packlets/crypto-utils/index.browser.js.map +1 -0
  62. package/dist/packlets/crypto-utils/index.js +6 -0
  63. package/dist/packlets/crypto-utils/index.js.map +1 -0
  64. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js +71 -0
  65. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  66. package/dist/packlets/crypto-utils/keystore/converters.js +103 -11
  67. package/dist/packlets/crypto-utils/keystore/converters.js.map +1 -0
  68. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +287 -0
  69. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  70. package/dist/packlets/crypto-utils/keystore/index.browser.js +36 -0
  71. package/dist/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  72. package/dist/packlets/crypto-utils/keystore/index.js +3 -0
  73. package/dist/packlets/crypto-utils/keystore/index.js.map +1 -0
  74. package/dist/packlets/crypto-utils/keystore/keyStore.js +633 -118
  75. package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  76. package/dist/packlets/crypto-utils/keystore/model.js +22 -1
  77. package/dist/packlets/crypto-utils/keystore/model.js.map +1 -0
  78. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js +21 -0
  79. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  80. package/dist/packlets/crypto-utils/model.js +32 -0
  81. package/dist/packlets/crypto-utils/model.js.map +1 -0
  82. package/dist/packlets/crypto-utils/nodeCryptoProvider.js +270 -1
  83. package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  84. package/dist/packlets/crypto-utils/spkiHelpers.js +209 -0
  85. package/dist/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  86. package/dist/packlets/csv/csvFileHelpers.js +0 -14
  87. package/dist/packlets/csv/csvFileHelpers.js.map +1 -0
  88. package/dist/packlets/csv/csvHelpers.js +14 -0
  89. package/dist/packlets/csv/csvHelpers.js.map +1 -0
  90. package/dist/packlets/csv/index.browser.js +1 -3
  91. package/dist/packlets/csv/index.browser.js.map +1 -0
  92. package/dist/packlets/csv/index.js.map +1 -0
  93. package/dist/packlets/experimental/extendedArray.js.map +1 -0
  94. package/dist/packlets/experimental/formatter.js.map +1 -0
  95. package/dist/packlets/experimental/index.js.map +1 -0
  96. package/dist/packlets/experimental/rangeOf.js.map +1 -0
  97. package/dist/packlets/hash/index.browser.js.map +1 -0
  98. package/dist/packlets/hash/index.js.map +1 -0
  99. package/dist/packlets/hash/index.node.js.map +1 -0
  100. package/dist/packlets/hash/md5Normalizer.browser.js.map +1 -0
  101. package/dist/packlets/hash/md5Normalizer.js.map +1 -0
  102. package/dist/packlets/mustache/index.js.map +1 -0
  103. package/dist/packlets/mustache/interfaces.js.map +1 -0
  104. package/dist/packlets/mustache/mustacheTemplate.js +42 -4
  105. package/dist/packlets/mustache/mustacheTemplate.js.map +1 -0
  106. package/dist/packlets/record-jar/index.browser.js +1 -3
  107. package/dist/packlets/record-jar/index.browser.js.map +1 -0
  108. package/dist/packlets/record-jar/index.js.map +1 -0
  109. package/dist/packlets/record-jar/recordJarFileHelpers.js +0 -18
  110. package/dist/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  111. package/dist/packlets/record-jar/recordJarHelpers.js +18 -0
  112. package/dist/packlets/record-jar/recordJarHelpers.js.map +1 -0
  113. package/dist/packlets/yaml/converters.js.map +1 -0
  114. package/dist/packlets/yaml/index.js +1 -0
  115. package/dist/packlets/yaml/index.js.map +1 -0
  116. package/dist/packlets/yaml/serializers.js +48 -0
  117. package/dist/packlets/yaml/serializers.js.map +1 -0
  118. package/dist/packlets/zip-file-tree/index.js.map +1 -0
  119. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js +2 -2
  120. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  121. package/dist/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  122. package/dist/ts-extras.d.ts +3880 -105
  123. package/dist/tsdoc-metadata.json +1 -1
  124. package/lib/index.browser.d.ts +4 -2
  125. package/lib/index.browser.d.ts.map +1 -0
  126. package/lib/index.browser.js +8 -3
  127. package/lib/index.browser.js.map +1 -0
  128. package/lib/index.d.ts.map +1 -0
  129. package/lib/index.js.map +1 -0
  130. package/lib/packlets/ai-assist/apiClient.d.ts +115 -32
  131. package/lib/packlets/ai-assist/apiClient.d.ts.map +1 -0
  132. package/lib/packlets/ai-assist/apiClient.js +888 -156
  133. package/lib/packlets/ai-assist/apiClient.js.map +1 -0
  134. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +149 -0
  135. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -0
  136. package/lib/packlets/ai-assist/chatRequestBuilders.js +293 -0
  137. package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  138. package/lib/packlets/ai-assist/converters.d.ts +15 -1
  139. package/lib/packlets/ai-assist/converters.d.ts.map +1 -0
  140. package/lib/packlets/ai-assist/converters.js +47 -3
  141. package/lib/packlets/ai-assist/converters.js.map +1 -0
  142. package/lib/packlets/ai-assist/embeddingClient.d.ts +69 -0
  143. package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -0
  144. package/lib/packlets/ai-assist/embeddingClient.js +349 -0
  145. package/lib/packlets/ai-assist/embeddingClient.js.map +1 -0
  146. package/lib/packlets/ai-assist/endpoint.d.ts +28 -0
  147. package/lib/packlets/ai-assist/endpoint.d.ts.map +1 -0
  148. package/lib/packlets/ai-assist/endpoint.js +82 -0
  149. package/lib/packlets/ai-assist/endpoint.js.map +1 -0
  150. package/lib/packlets/ai-assist/http.d.ts +24 -0
  151. package/lib/packlets/ai-assist/http.d.ts.map +1 -0
  152. package/lib/packlets/ai-assist/http.js +78 -0
  153. package/lib/packlets/ai-assist/http.js.map +1 -0
  154. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts +66 -0
  155. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts.map +1 -0
  156. package/lib/packlets/ai-assist/imageOptionsResolver.js +197 -0
  157. package/lib/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  158. package/lib/packlets/ai-assist/index.d.ts +10 -4
  159. package/lib/packlets/ai-assist/index.d.ts.map +1 -0
  160. package/lib/packlets/ai-assist/index.js +36 -1
  161. package/lib/packlets/ai-assist/index.js.map +1 -0
  162. package/lib/packlets/ai-assist/jsonCompletion.d.ts +93 -0
  163. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -0
  164. package/lib/packlets/ai-assist/jsonCompletion.js +97 -0
  165. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -0
  166. package/lib/packlets/ai-assist/jsonResponse.d.ts +91 -0
  167. package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -0
  168. package/lib/packlets/ai-assist/jsonResponse.js +154 -0
  169. package/lib/packlets/ai-assist/jsonResponse.js.map +1 -0
  170. package/lib/packlets/ai-assist/model.d.ts +1202 -12
  171. package/lib/packlets/ai-assist/model.d.ts.map +1 -0
  172. package/lib/packlets/ai-assist/model.js +198 -10
  173. package/lib/packlets/ai-assist/model.js.map +1 -0
  174. package/lib/packlets/ai-assist/registry.d.ts +56 -1
  175. package/lib/packlets/ai-assist/registry.d.ts.map +1 -0
  176. package/lib/packlets/ai-assist/registry.js +319 -13
  177. package/lib/packlets/ai-assist/registry.js.map +1 -0
  178. package/lib/packlets/ai-assist/sseParser.d.ts +45 -0
  179. package/lib/packlets/ai-assist/sseParser.d.ts.map +1 -0
  180. package/lib/packlets/ai-assist/sseParser.js +128 -0
  181. package/lib/packlets/ai-assist/sseParser.js.map +1 -0
  182. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +72 -0
  183. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -0
  184. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +371 -0
  185. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  186. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +260 -0
  187. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -0
  188. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +694 -0
  189. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  190. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +154 -0
  191. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -0
  192. package/lib/packlets/ai-assist/streamingAdapters/common.js +193 -0
  193. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  194. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts +43 -0
  195. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -0
  196. package/lib/packlets/ai-assist/streamingAdapters/gemini.js +207 -0
  197. package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  198. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts +19 -0
  199. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts.map +1 -0
  200. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js +173 -0
  201. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  202. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +33 -0
  203. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -0
  204. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +389 -0
  205. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  206. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts +34 -0
  207. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -0
  208. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +176 -0
  209. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  210. package/lib/packlets/ai-assist/streamingClient.d.ts +50 -0
  211. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -0
  212. package/lib/packlets/ai-assist/streamingClient.js +146 -0
  213. package/lib/packlets/ai-assist/streamingClient.js.map +1 -0
  214. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts +87 -0
  215. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts.map +1 -0
  216. package/lib/packlets/ai-assist/thinkingOptionsResolver.js +294 -0
  217. package/lib/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  218. package/lib/packlets/ai-assist/toolFormats.d.ts +40 -9
  219. package/lib/packlets/ai-assist/toolFormats.d.ts.map +1 -0
  220. package/lib/packlets/ai-assist/toolFormats.js +107 -10
  221. package/lib/packlets/ai-assist/toolFormats.js.map +1 -0
  222. package/lib/packlets/conversion/converters.d.ts +8 -1
  223. package/lib/packlets/conversion/converters.d.ts.map +1 -0
  224. package/lib/packlets/conversion/converters.js +36 -2
  225. package/lib/packlets/conversion/converters.js.map +1 -0
  226. package/lib/packlets/conversion/index.d.ts.map +1 -0
  227. package/lib/packlets/conversion/index.js.map +1 -0
  228. package/lib/packlets/crypto-utils/constants.d.ts.map +1 -0
  229. package/lib/packlets/crypto-utils/constants.js.map +1 -0
  230. package/lib/packlets/crypto-utils/converters.d.ts +20 -1
  231. package/lib/packlets/crypto-utils/converters.d.ts.map +1 -0
  232. package/lib/packlets/crypto-utils/converters.js +43 -5
  233. package/lib/packlets/crypto-utils/converters.js.map +1 -0
  234. package/lib/packlets/crypto-utils/directEncryptionProvider.d.ts.map +1 -0
  235. package/lib/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  236. package/lib/packlets/crypto-utils/encryptedFile.d.ts.map +1 -0
  237. package/lib/packlets/crypto-utils/encryptedFile.js.map +1 -0
  238. package/lib/packlets/crypto-utils/hpkeProvider.d.ts +142 -0
  239. package/lib/packlets/crypto-utils/hpkeProvider.d.ts.map +1 -0
  240. package/lib/packlets/crypto-utils/hpkeProvider.js +337 -0
  241. package/lib/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  242. package/lib/packlets/crypto-utils/index.browser.d.ts +4 -1
  243. package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -0
  244. package/lib/packlets/crypto-utils/index.browser.js +21 -3
  245. package/lib/packlets/crypto-utils/index.browser.js.map +1 -0
  246. package/lib/packlets/crypto-utils/index.d.ts +3 -0
  247. package/lib/packlets/crypto-utils/index.d.ts.map +1 -0
  248. package/lib/packlets/crypto-utils/index.js +17 -1
  249. package/lib/packlets/crypto-utils/index.js.map +1 -0
  250. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts +54 -0
  251. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts.map +1 -0
  252. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js +74 -0
  253. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  254. package/lib/packlets/crypto-utils/keystore/converters.d.ts +68 -6
  255. package/lib/packlets/crypto-utils/keystore/converters.d.ts.map +1 -0
  256. package/lib/packlets/crypto-utils/keystore/converters.js +101 -9
  257. package/lib/packlets/crypto-utils/keystore/converters.js.map +1 -0
  258. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts +148 -0
  259. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts.map +1 -0
  260. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +324 -0
  261. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  262. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts +10 -0
  263. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts.map +1 -0
  264. package/lib/packlets/crypto-utils/keystore/index.browser.js +76 -0
  265. package/lib/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  266. package/lib/packlets/crypto-utils/keystore/index.d.ts +2 -0
  267. package/lib/packlets/crypto-utils/keystore/index.d.ts.map +1 -0
  268. package/lib/packlets/crypto-utils/keystore/index.js +5 -1
  269. package/lib/packlets/crypto-utils/keystore/index.js.map +1 -0
  270. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +205 -13
  271. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -0
  272. package/lib/packlets/crypto-utils/keystore/keyStore.js +639 -124
  273. package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  274. package/lib/packlets/crypto-utils/keystore/model.d.ts +275 -19
  275. package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -0
  276. package/lib/packlets/crypto-utils/keystore/model.js +24 -2
  277. package/lib/packlets/crypto-utils/keystore/model.js.map +1 -0
  278. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts +53 -0
  279. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts.map +1 -0
  280. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js +22 -0
  281. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  282. package/lib/packlets/crypto-utils/model.d.ts +348 -10
  283. package/lib/packlets/crypto-utils/model.d.ts.map +1 -0
  284. package/lib/packlets/crypto-utils/model.js +33 -1
  285. package/lib/packlets/crypto-utils/model.js.map +1 -0
  286. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts +110 -2
  287. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -0
  288. package/lib/packlets/crypto-utils/nodeCryptoProvider.js +269 -0
  289. package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  290. package/lib/packlets/crypto-utils/spkiHelpers.d.ts +110 -0
  291. package/lib/packlets/crypto-utils/spkiHelpers.d.ts.map +1 -0
  292. package/lib/packlets/crypto-utils/spkiHelpers.js +219 -0
  293. package/lib/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  294. package/lib/packlets/csv/csvFileHelpers.d.ts +0 -10
  295. package/lib/packlets/csv/csvFileHelpers.d.ts.map +1 -0
  296. package/lib/packlets/csv/csvFileHelpers.js +0 -15
  297. package/lib/packlets/csv/csvFileHelpers.js.map +1 -0
  298. package/lib/packlets/csv/csvHelpers.d.ts +10 -0
  299. package/lib/packlets/csv/csvHelpers.d.ts.map +1 -0
  300. package/lib/packlets/csv/csvHelpers.js +15 -0
  301. package/lib/packlets/csv/csvHelpers.js.map +1 -0
  302. package/lib/packlets/csv/index.browser.d.ts +0 -1
  303. package/lib/packlets/csv/index.browser.d.ts.map +1 -0
  304. package/lib/packlets/csv/index.browser.js +1 -5
  305. package/lib/packlets/csv/index.browser.js.map +1 -0
  306. package/lib/packlets/csv/index.d.ts.map +1 -0
  307. package/lib/packlets/csv/index.js.map +1 -0
  308. package/lib/packlets/experimental/extendedArray.d.ts.map +1 -0
  309. package/lib/packlets/experimental/extendedArray.js.map +1 -0
  310. package/lib/packlets/experimental/formatter.d.ts.map +1 -0
  311. package/lib/packlets/experimental/formatter.js.map +1 -0
  312. package/lib/packlets/experimental/index.d.ts.map +1 -0
  313. package/lib/packlets/experimental/index.js.map +1 -0
  314. package/lib/packlets/experimental/rangeOf.d.ts.map +1 -0
  315. package/lib/packlets/experimental/rangeOf.js.map +1 -0
  316. package/lib/packlets/hash/index.browser.d.ts.map +1 -0
  317. package/lib/packlets/hash/index.browser.js.map +1 -0
  318. package/lib/packlets/hash/index.d.ts.map +1 -0
  319. package/lib/packlets/hash/index.js.map +1 -0
  320. package/lib/packlets/hash/index.node.d.ts.map +1 -0
  321. package/lib/packlets/hash/index.node.js.map +1 -0
  322. package/lib/packlets/hash/md5Normalizer.browser.d.ts.map +1 -0
  323. package/lib/packlets/hash/md5Normalizer.browser.js.map +1 -0
  324. package/lib/packlets/hash/md5Normalizer.d.ts.map +1 -0
  325. package/lib/packlets/hash/md5Normalizer.js.map +1 -0
  326. package/lib/packlets/mustache/index.d.ts +1 -1
  327. package/lib/packlets/mustache/index.d.ts.map +1 -0
  328. package/lib/packlets/mustache/index.js.map +1 -0
  329. package/lib/packlets/mustache/interfaces.d.ts +34 -0
  330. package/lib/packlets/mustache/interfaces.d.ts.map +1 -0
  331. package/lib/packlets/mustache/interfaces.js.map +1 -0
  332. package/lib/packlets/mustache/mustacheTemplate.d.ts +2 -0
  333. package/lib/packlets/mustache/mustacheTemplate.d.ts.map +1 -0
  334. package/lib/packlets/mustache/mustacheTemplate.js +42 -4
  335. package/lib/packlets/mustache/mustacheTemplate.js.map +1 -0
  336. package/lib/packlets/record-jar/index.browser.d.ts +0 -1
  337. package/lib/packlets/record-jar/index.browser.d.ts.map +1 -0
  338. package/lib/packlets/record-jar/index.browser.js +1 -5
  339. package/lib/packlets/record-jar/index.browser.js.map +1 -0
  340. package/lib/packlets/record-jar/index.d.ts.map +1 -0
  341. package/lib/packlets/record-jar/index.js.map +1 -0
  342. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts +0 -11
  343. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts.map +1 -0
  344. package/lib/packlets/record-jar/recordJarFileHelpers.js +0 -19
  345. package/lib/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  346. package/lib/packlets/record-jar/recordJarHelpers.d.ts +11 -0
  347. package/lib/packlets/record-jar/recordJarHelpers.d.ts.map +1 -0
  348. package/lib/packlets/record-jar/recordJarHelpers.js +19 -0
  349. package/lib/packlets/record-jar/recordJarHelpers.js.map +1 -0
  350. package/lib/packlets/yaml/converters.d.ts.map +1 -0
  351. package/lib/packlets/yaml/converters.js.map +1 -0
  352. package/lib/packlets/yaml/index.d.ts +1 -0
  353. package/lib/packlets/yaml/index.d.ts.map +1 -0
  354. package/lib/packlets/yaml/index.js +1 -0
  355. package/lib/packlets/yaml/index.js.map +1 -0
  356. package/lib/packlets/yaml/serializers.d.ts +45 -0
  357. package/lib/packlets/yaml/serializers.d.ts.map +1 -0
  358. package/lib/packlets/yaml/serializers.js +84 -0
  359. package/lib/packlets/yaml/serializers.js.map +1 -0
  360. package/lib/packlets/zip-file-tree/index.d.ts.map +1 -0
  361. package/lib/packlets/zip-file-tree/index.js.map +1 -0
  362. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts +2 -2
  363. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts.map +1 -0
  364. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js +2 -2
  365. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  366. package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts.map +1 -0
  367. package/lib/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  368. package/package.json +20 -15
@@ -1,10 +1,15 @@
1
+ import { Brand } from '@fgv/ts-utils';
1
2
  import { Conversion } from '@fgv/ts-utils';
2
3
  import { Converter } from '@fgv/ts-utils';
4
+ import { DateTime } from 'luxon';
3
5
  import { FileTree } from '@fgv/ts-json-base';
4
6
  import { Hash as Hash_2 } from '@fgv/ts-utils';
7
+ import { JsonObject } from '@fgv/ts-json-base';
8
+ import { JsonSchema } from '@fgv/ts-json-base';
5
9
  import { JsonValue } from '@fgv/ts-json-base';
6
10
  import { Logging } from '@fgv/ts-utils';
7
11
  import { Result } from '@fgv/ts-utils';
12
+ import { Uuid } from '@fgv/ts-utils';
8
13
  import { Validator } from '@fgv/ts-utils';
9
14
 
10
15
  /**
@@ -22,41 +27,151 @@ declare type AiApiFormat = 'openai' | 'anthropic' | 'gemini';
22
27
  declare namespace AiAssist {
23
28
  export {
24
29
  AiPrompt,
30
+ AiModelCapability,
31
+ allModelCapabilities,
25
32
  AiProviderId,
26
33
  AiServerToolType,
27
34
  AiServerToolConfig,
35
+ AiToolConfig,
28
36
  IAiWebSearchToolConfig,
37
+ IAiClientToolConfig,
38
+ IAiToolAnnotations,
39
+ IAiClientTool,
40
+ IAiClientToolCallSummary,
41
+ IAiClientToolContinuation,
42
+ IAiClientToolTurnResult,
29
43
  IAiToolEnablement,
30
44
  IAiCompletionResponse,
31
45
  IChatMessage,
46
+ IChatRequest,
32
47
  AiApiFormat,
48
+ AiImageApiFormat,
49
+ AiEmbeddingApiFormat,
50
+ AiEmbeddingTaskType,
51
+ IAiEmbeddingModelCapability,
52
+ IAiEmbeddingParams,
53
+ IAiEmbeddingUsage,
54
+ IAiEmbeddingResult,
55
+ IAiImageModelCapability,
33
56
  IAiProviderDescriptor,
34
57
  IAiAssistProviderConfig,
35
58
  IAiAssistSettings,
36
59
  DEFAULT_AI_ASSIST,
37
60
  IAiAssistKeyStore,
61
+ IAiImageAttachment,
62
+ IAiImageData,
63
+ AiImageSize,
64
+ AiImageQuality,
65
+ GptImageSize,
66
+ GptImageQuality,
67
+ GptImageModelNames,
68
+ GrokImagineModelNames,
69
+ GeminiFlashImageModelNames,
70
+ IGptImageGenerationConfig,
71
+ IGrokImagineImageGenerationConfig,
72
+ IGeminiFlashImageGenerationConfig,
73
+ IGptImageModelOptions,
74
+ IGrokImagineModelOptions,
75
+ IGeminiFlashImageModelOptions,
76
+ IOtherModelOptions,
77
+ IModelFamilyConfig,
78
+ IAiImageGenerationOptions,
79
+ IAiImageGenerationParams,
80
+ IAiGeneratedImage,
81
+ IAiImageGenerationResponse,
82
+ IAiModelCapabilityRule,
83
+ IAiModelCapabilityConfig,
84
+ IAiModelInfo,
85
+ IAiStreamEvent,
86
+ IAiStreamTextDelta,
87
+ IAiStreamToolEvent,
88
+ IAiStreamToolUseStart,
89
+ IAiStreamToolUseDelta,
90
+ IAiStreamToolUseComplete,
91
+ IAiStreamDone,
92
+ IAiStreamError,
38
93
  ModelSpec,
39
94
  ModelSpecKey,
40
95
  IModelSpecMap,
41
96
  allModelSpecKeys,
42
97
  MODEL_SPEC_BASE_KEY,
43
98
  resolveModel,
99
+ IModelAliasMap,
100
+ MODEL_ALIAS_SIGIL,
101
+ resolveModelAlias,
102
+ resolveProviderModel,
103
+ isResponsesOnlyModel,
104
+ toDataUrl,
105
+ AiThinkingMode,
106
+ IThinkingConfig,
107
+ IThinkingProviderConfig,
108
+ IAnthropicThinkingOptions,
109
+ IOpenAiThinkingOptions,
110
+ IGeminiThinkingOptions,
111
+ IXAiThinkingOptions,
112
+ IOtherThinkingOptions,
113
+ IAnthropicThinkingConfig,
114
+ IOpenAiThinkingConfig,
115
+ IGeminiThinkingConfig,
116
+ IXAiThinkingConfig,
117
+ AnthropicThinkingModelNames,
118
+ OpenAiThinkingModelNames,
119
+ GeminiThinkingModelNames,
120
+ XAiThinkingModelNames,
121
+ IResolvedImageOptions,
122
+ resolveImageOptions,
123
+ validateResolvedOptions,
44
124
  allProviderIds,
45
125
  getProviderDescriptors,
46
126
  getProviderDescriptor,
127
+ resolveImageCapability,
128
+ supportsImageGeneration,
129
+ resolveEmbeddingCapability,
130
+ supportsEmbedding,
131
+ DEFAULT_MODEL_CAPABILITY_CONFIG,
47
132
  callProviderCompletion,
48
133
  callProxiedCompletion,
134
+ callProviderImageGeneration,
135
+ callProxiedImageGeneration,
136
+ callProviderListModels,
137
+ callProxiedListModels,
49
138
  IProviderCompletionParams,
139
+ IProviderImageGenerationParams,
140
+ IProviderListModelsParams,
141
+ callProviderEmbedding,
142
+ callProxiedEmbedding,
143
+ IProviderEmbeddingParams,
144
+ callProviderCompletionStream,
145
+ callProxiedCompletionStream,
146
+ IProviderCompletionStreamParams,
147
+ executeClientToolTurn,
148
+ IExecuteClientToolTurnParams,
149
+ IExecuteClientToolTurnResult,
150
+ IToolExecutionDecision,
50
151
  aiProviderId,
51
152
  aiServerToolType,
52
153
  aiWebSearchToolConfig,
53
154
  aiServerToolConfig,
155
+ aiToolAnnotations,
156
+ aiClientToolConfig,
54
157
  aiToolEnablement,
55
158
  aiAssistProviderConfig,
56
159
  aiAssistSettings,
57
160
  modelSpecKey,
58
161
  modelSpec,
59
- resolveEffectiveTools
162
+ resolveEffectiveTools,
163
+ extractJsonText,
164
+ fencedStringifiedJson,
165
+ IFencedStringifiedJsonExtractorOptions,
166
+ IFencedStringifiedJsonOptions,
167
+ JsonTextExtractor,
168
+ generateJsonCompletion,
169
+ SMART_JSON_PROMPT_HINT,
170
+ IGenerateJsonCompletionParams,
171
+ IGenerateJsonCompletionResult,
172
+ JsonPromptHint,
173
+ anthropicEffortToBudgetTokens,
174
+ IResolvedThinkingConfig
60
175
  }
61
176
  }
62
177
  export { AiAssist }
@@ -73,6 +188,86 @@ declare const aiAssistProviderConfig: Converter<IAiAssistProviderConfig>;
73
188
  */
74
189
  declare const aiAssistSettings: Converter<IAiAssistSettings>;
75
190
 
191
+ /**
192
+ * Converter for {@link AiAssist.IAiClientToolConfig}. Validates the wrapper shape: `type`,
193
+ * `name`, `description`, the presence of a usable `parametersSchema`, and optional
194
+ * host-advisory `annotations`.
195
+ * Does not inspect the inner JSON Schema structure — `JsonSchema.object(...)` already
196
+ * guarantees the schema is valid.
197
+ * @public
198
+ */
199
+ declare const aiClientToolConfig: Converter<IAiClientToolConfig>;
200
+
201
+ /**
202
+ * API format categories for embedding provider routing.
203
+ *
204
+ * @remarks
205
+ * - `'openai-embeddings'` — OpenAI `/v1/embeddings` shape. Serves OpenAI,
206
+ * Ollama (via `/v1`), openai-compat self-hosted servers (vLLM, LM Studio,
207
+ * llama.cpp's openai-server), and Mistral (`mistral-embed`) — all of which
208
+ * speak the same request/response shape.
209
+ * - `'gemini-embeddings'` — Google Gemini `:batchEmbedContents` endpoint. A
210
+ * genuinely divergent shape (different route, auth header, request body, and
211
+ * the `taskType` retrieval-asymmetry knob that has no OpenAI analog).
212
+ *
213
+ * Named with the `ApiFormat` suffix for symmetry with `AiApiFormat` and
214
+ * `AiImageApiFormat`.
215
+ *
216
+ * @public
217
+ */
218
+ declare type AiEmbeddingApiFormat = 'openai-embeddings' | 'gemini-embeddings';
219
+
220
+ /**
221
+ * A single embedding task-type hint (Gemini-style). Cross-provider; providers
222
+ * that don't support task typing ignore it (logged, not failed). Open string
223
+ * union so new Gemini task types don't force a churn, with the known set
224
+ * enumerated for ergonomics.
225
+ *
226
+ * @remarks
227
+ * Values are the kebab-case cross-provider form; the Gemini adapter maps them to
228
+ * `SCREAMING_SNAKE_CASE` on the wire (e.g. `'retrieval-document'` →
229
+ * `RETRIEVAL_DOCUMENT`).
230
+ *
231
+ * @public
232
+ */
233
+ declare type AiEmbeddingTaskType = 'retrieval-query' | 'retrieval-document' | 'semantic-similarity' | 'classification' | 'clustering' | 'code-retrieval-query' | 'question-answering' | 'fact-verification' | (string & {});
234
+
235
+ /**
236
+ * API format categories for image-generation provider routing.
237
+ *
238
+ * @remarks
239
+ * - `'openai-images'` — OpenAI Images API. Routes to `/images/generations`
240
+ * (text-only) or `/images/edits` (when reference images are present).
241
+ * - `'xai-images'` — xAI Images API. Text-only JSON generation request.
242
+ * - `'xai-images-edits'` — xAI Images API for Grok Imagine models. Uses JSON
243
+ * body with `{ type: "image_url" }` objects (not multipart).
244
+ * - `'gemini-image-out'` — Google Gemini chat-style `:generateContent`
245
+ * endpoint that returns image parts (Gemini Flash Image / "Nano
246
+ * Banana"). Accepts reference images.
247
+ *
248
+ * @public
249
+ */
250
+ declare type AiImageApiFormat = 'openai-images' | 'xai-images' | 'xai-images-edits' | 'gemini-image-out';
251
+
252
+ /** All accepted quality strings across all providers. @public */
253
+ declare type AiImageQuality = GptImageQuality;
254
+
255
+ /** All accepted image size strings across all providers. @public */
256
+ declare type AiImageSize = GptImageSize;
257
+
258
+ /**
259
+ * Capability vocabulary used to describe what a model can do. Used as both
260
+ * a filter and as a tag in {@link AiAssist.IAiModelInfo.capabilities}.
261
+ *
262
+ * @remarks
263
+ * Adding a new capability is cheap; adding the *first* one after consumers
264
+ * already exist forces churn. The initial vocabulary is intentionally broad
265
+ * even though only `image-generation` is fully exercised today.
266
+ *
267
+ * @public
268
+ */
269
+ declare type AiModelCapability = 'chat' | 'tools' | 'vision' | 'image-generation' | 'thinking' | 'embedding';
270
+
76
271
  /**
77
272
  * A structured AI prompt with system/user split for direct API calls,
78
273
  * and a lazily-constructed combined version for copy/paste workflows.
@@ -83,16 +278,35 @@ declare class AiPrompt {
83
278
  readonly system: string;
84
279
  /** User request: the specific entity generation request. */
85
280
  readonly user: string;
86
- constructor(user: string, system: string);
87
- /** Combined single-string version (user + system joined) for copy/paste. */
281
+ /**
282
+ * Optional image attachments. When present, vision-capable providers will
283
+ * include them in the user message; non-vision providers will reject the
284
+ * call up front (see {@link AiAssist.IAiProviderDescriptor.acceptsImageInput}).
285
+ */
286
+ readonly attachments: ReadonlyArray<IAiImageAttachment>;
287
+ constructor(user: string, system: string, attachments?: ReadonlyArray<IAiImageAttachment>);
288
+ /**
289
+ * Combined single-string version (user + system joined) for copy/paste.
290
+ * When attachments are present, includes a sentinel noting they aren't
291
+ * part of the copied text.
292
+ */
88
293
  get combined(): string;
294
+ /**
295
+ * Lowers this prompt to the unified {@link AiAssist.IChatRequest} shape consumed
296
+ * by the turn entry points (`callProviderCompletion`,
297
+ * `callProviderCompletionStream`, `generateJsonCompletion`,
298
+ * `executeClientToolTurn`). The prompt becomes a single current `user` turn
299
+ * (carrying any attachments) with the system instructions in the distinct
300
+ * `system` field.
301
+ */
302
+ toRequest(): IChatRequest;
89
303
  }
90
304
 
91
305
  /**
92
306
  * All known AI provider identifiers.
93
307
  * @public
94
308
  */
95
- declare type AiProviderId = 'copy-paste' | 'xai-grok' | 'openai' | 'anthropic' | 'google-gemini' | 'groq' | 'mistral';
309
+ declare type AiProviderId = 'copy-paste' | 'xai-grok' | 'openai' | 'openai-compat' | 'anthropic' | 'google-gemini' | 'groq' | 'mistral' | 'ollama';
96
310
 
97
311
  /**
98
312
  * Converter for {@link AiProviderId}.
@@ -124,6 +338,25 @@ declare type AiServerToolType = 'web_search';
124
338
  */
125
339
  declare const aiServerToolType: Converter<AiServerToolType>;
126
340
 
341
+ /**
342
+ * Thinking/reasoning mode support for a provider.
343
+ * @public
344
+ */
345
+ declare type AiThinkingMode = 'optional' | 'required' | 'unsupported';
346
+
347
+ /**
348
+ * Converter for {@link AiAssist.IAiToolAnnotations} — the five optional host-advisory hints.
349
+ * @public
350
+ */
351
+ declare const aiToolAnnotations: Converter<IAiToolAnnotations>;
352
+
353
+ /**
354
+ * Union of all tool configurations: server-side or client-defined.
355
+ * Discriminated on `type`.
356
+ * @public
357
+ */
358
+ declare type AiToolConfig = AiServerToolConfig | IAiClientToolConfig;
359
+
127
360
  /**
128
361
  * Converter for {@link IAiToolEnablement}.
129
362
  * @public
@@ -136,12 +369,37 @@ declare const aiToolEnablement: Converter<IAiToolEnablement>;
136
369
  */
137
370
  declare const aiWebSearchToolConfig: Converter<IAiWebSearchToolConfig>;
138
371
 
372
+ /**
373
+ * All valid key pair algorithms.
374
+ * @public
375
+ */
376
+ declare const allKeyPairAlgorithms: ReadonlyArray<KeyPairAlgorithm>;
377
+
378
+ /**
379
+ * All valid asymmetric secret types.
380
+ * @public
381
+ */
382
+ declare const allKeyStoreAsymmetricSecretTypes: ReadonlyArray<KeyStoreAsymmetricSecretType>;
383
+
139
384
  /**
140
385
  * All valid key store secret types.
141
386
  * @public
142
387
  */
143
388
  declare const allKeyStoreSecretTypes: ReadonlyArray<KeyStoreSecretType>;
144
389
 
390
+ /**
391
+ * All valid symmetric secret types.
392
+ * @public
393
+ */
394
+ declare const allKeyStoreSymmetricSecretTypes: ReadonlyArray<KeyStoreSymmetricSecretType>;
395
+
396
+ /**
397
+ * All valid `AiModelCapability` values — the single source of truth for
398
+ * the capability vocabulary (used by validators and capability filters).
399
+ * @public
400
+ */
401
+ declare const allModelCapabilities: ReadonlyArray<AiModelCapability>;
402
+
145
403
  /**
146
404
  * All valid {@link ModelSpecKey} values.
147
405
  * @public
@@ -154,6 +412,49 @@ declare const allModelSpecKeys: ReadonlyArray<ModelSpecKey>;
154
412
  */
155
413
  declare const allProviderIds: ReadonlyArray<AiProviderId>;
156
414
 
415
+ /**
416
+ * Maps Anthropic effort level to the `thinking.budget_tokens` integer that the
417
+ * Anthropic API requires when `thinking.type === 'enabled'`.
418
+ *
419
+ * Policy: low = 2048, medium = 8192, high = 24000, max = 32000. The lower three
420
+ * align with the Anthropic-published minimum-meaningful budget, a mid-range
421
+ * default, and a "deep thinking" allotment respectively. `max` targets Opus 4.6's
422
+ * deepest budget and stays within typical model limits.
423
+ *
424
+ * @public
425
+ */
426
+ declare function anthropicEffortToBudgetTokens(effort: NonNullable<IAnthropicThinkingConfig['effort']>): number;
427
+
428
+ /**
429
+ * Model IDs for Anthropic thinking-capable models.
430
+ *
431
+ * @remarks
432
+ * Only thinking-capable lines are listed. The non-tier `@anthropic:haiku` / `@anthropic:fable`
433
+ * aliases (reachable via `modelOverride` only) are deliberately omitted — they are not
434
+ * documented as thinking-capable, so naming them in a thinking-model filter would be misleading.
435
+ * @public
436
+ */
437
+ declare 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';
438
+
439
+ /**
440
+ * Recommended OWASP 2023 minimum Argon2id parameters.
441
+ * Suitable for recovery-row key derivation (high-entropy inputs).
442
+ * @public
443
+ */
444
+ declare const ARGON2ID_OWASP_MIN: IArgon2idParams;
445
+
446
+ /**
447
+ * Stronger Argon2id parameters suitable for user-typed passphrases.
448
+ * @public
449
+ */
450
+ declare const ARGON2ID_PASSPHRASE: IArgon2idParams;
451
+
452
+ /**
453
+ * Converter for {@link CryptoUtils.IArgon2idKeyDerivationParams | Argon2id key derivation parameters}.
454
+ * @public
455
+ */
456
+ declare const argon2idKeyDerivationParams: Converter<IArgon2idKeyDerivationParams>;
457
+
157
458
  /**
158
459
  * Converter for base64 strings (validates format).
159
460
  * @public
@@ -161,39 +462,169 @@ declare const allProviderIds: ReadonlyArray<AiProviderId>;
161
462
  declare const base64String: Converter<string>;
162
463
 
163
464
  /**
164
- * Calls the appropriate chat completion API for a given provider.
465
+ * Decodes a base64url (no-padding) string (RFC 4648 §5) back to a `Uint8Array`.
466
+ *
467
+ * This is the bare primitive with no multibase prefix; use
468
+ * {@link CryptoUtils.multibaseBase64UrlDecode} to decode a multibase-`'m'`-prefixed value.
469
+ *
470
+ * @param encoded - The base64url-no-pad body to decode.
471
+ * @returns `Success` with the decoded bytes, or `Failure` with error context.
472
+ * @public
473
+ */
474
+ declare function base64UrlNoPadDecode(encoded: string): Result<Uint8Array>;
475
+
476
+ /**
477
+ * Encodes a `Uint8Array` as a base64url (no-padding) string (RFC 4648 §5).
478
+ *
479
+ * The body uses the base64url alphabet (`+` → `-`, `/` → `_`) and trailing `=`
480
+ * padding is stripped. This is the bare primitive with no multibase prefix; use
481
+ * {@link CryptoUtils.multibaseBase64UrlEncode} when a multibase-`'m'`-prefixed value is required.
482
+ *
483
+ * @param data - The binary data to encode.
484
+ * @returns The base64url-no-pad string.
485
+ * @public
486
+ */
487
+ declare function base64UrlNoPadEncode(data: Uint8Array): string;
488
+
489
+ /**
490
+ * Calls the appropriate chat completion API for a given provider. Routes by
491
+ * `apiFormat`: `'openai'` (xAI/OpenAI/Groq/Mistral — switches to Responses API
492
+ * when tools are set), `'anthropic'`, or `'gemini'`.
493
+ * @public
494
+ */
495
+ declare function callProviderCompletion(params: IProviderCompletionParams): Promise<Result<IAiCompletionResponse>>;
496
+
497
+ /**
498
+ * Calls the appropriate streaming chat completion API for a given provider.
165
499
  *
166
- * Routes based on the provider descriptor's `apiFormat` field:
167
- * - `'openai'` for xAI, OpenAI, Groq, Mistral
168
- * - `'anthropic'` for Anthropic Claude
169
- * - `'gemini'` for Google Gemini
500
+ * @remarks
501
+ * Pre-flight rejection: when `descriptor.streamingCorsRestricted === true`
502
+ * and the call isn't being routed through a proxy, this returns
503
+ * `Result.fail` before fetch is invoked. Callers should route through
504
+ * {@link AiAssist.callProxiedCompletionStream} or surface the failure to the user.
170
505
  *
171
- * When tools are provided and the provider supports them:
172
- * - OpenAI-format providers switch to the Responses API
173
- * - Anthropic includes tools in the Messages API request
174
- * - Gemini includes Google Search grounding
506
+ * Connection-time failures (auth, network, non-2xx) surface as the outer
507
+ * `Result.fail`. Once iteration begins, errors mid-stream surface as a
508
+ * terminal error event ({@link AiAssist.IAiStreamError}) followed by the iterable
509
+ * ending. The final successful event is {@link AiAssist.IAiStreamDone}.
175
510
  *
176
511
  * @param params - Request parameters including descriptor, API key, prompt, and optional tools
177
- * @returns The completion response with content and truncation status, or a failure
512
+ * @returns A streaming iterable of unified events, or a Result.fail
178
513
  * @public
179
514
  */
180
- declare function callProviderCompletion(params: IProviderCompletionParams): Promise<Result<IAiCompletionResponse>>;
515
+ declare function callProviderCompletionStream(params: IProviderCompletionStreamParams): Promise<Result<AsyncIterable<IAiStreamEvent>>>;
181
516
 
182
517
  /**
183
- * Calls the AI completion endpoint on a proxy server instead of calling
184
- * the provider API directly from the browser.
518
+ * Calls the appropriate embedding API for a given provider. Routes by the
519
+ * `format` of the resolved {@link AiAssist.IAiEmbeddingModelCapability}:
520
+ * `'openai-embeddings'` or `'gemini-embeddings'`.
185
521
  *
186
- * The proxy server handles provider dispatch, CORS, and API key forwarding.
187
- * The request shape mirrors {@link IProviderCompletionParams} but is serialized
188
- * as JSON for the proxy endpoint.
522
+ * @remarks
523
+ * - Rejects up front when the provider declares no embedding capability, when no
524
+ * embedding model resolves, or when the batch exceeds the capability's
525
+ * `maxBatchSize` (no auto-chunking).
526
+ * - An empty `input` array short-circuits to an empty result with no wire call
527
+ * (most providers HTTP-400 on empty input).
528
+ * - Caller-supplied `dimensions`/`taskType` that the model doesn't support are a
529
+ * no-op (logged), not a failure (design §7).
189
530
  *
190
- * @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`)
531
+ * @param params - Request parameters including descriptor, API key, and input.
532
+ * @returns The embedding vectors aligned to input order, or a failure.
533
+ * @public
534
+ */
535
+ declare function callProviderEmbedding(params: IProviderEmbeddingParams): Promise<Result<IAiEmbeddingResult>>;
536
+
537
+ /**
538
+ * Calls the appropriate image-generation API for a given provider. Routes by the
539
+ * `format` field of the resolved {@link IAiImageModelCapability}:
540
+ * `'openai-images'`, `'xai-images'`, `'xai-images-edits'`, or
541
+ * `'gemini-image-out'`. Rejects up front if `referenceImages` is set but the
542
+ * capability does not declare `acceptsImageReferenceInput`.
543
+ * @param params - Request parameters including descriptor, API key, and prompt
544
+ * @public
545
+ */
546
+ declare function callProviderImageGeneration(params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
547
+
548
+ /**
549
+ * Lists models available from a provider, routing by `descriptor.apiFormat`.
550
+ * Capabilities are resolved from native provider info and a configurable rule set.
551
+ * @param params - Request parameters (descriptor, API key, optional capability filter)
552
+ * @public
553
+ */
554
+ declare function callProviderListModels(params: IProviderListModelsParams): Promise<Result<ReadonlyArray<IAiModelInfo>>>;
555
+
556
+ /**
557
+ * Calls the AI completion endpoint on a proxy server instead of calling the
558
+ * provider API directly from the browser. The proxy handles provider dispatch,
559
+ * CORS, and API key forwarding. The request body serializes the unified
560
+ * {@link AiAssist.IChatRequest} shape (`system?` + `messages`). Enforces the same
561
+ * non-empty / trailing-user-turn and image-input invariants as the direct path.
562
+ * @param proxyUrl - Base URL of the proxy server
191
563
  * @param params - Same parameters as {@link callProviderCompletion}
192
- * @returns The completion response, or a failure
193
564
  * @public
194
565
  */
195
566
  declare function callProxiedCompletion(proxyUrl: string, params: IProviderCompletionParams): Promise<Result<IAiCompletionResponse>>;
196
567
 
568
+ /**
569
+ * Calls the streaming chat endpoint on a proxy server instead of calling
570
+ * the provider directly from the browser.
571
+ *
572
+ * @remarks
573
+ * Proxy contract:
574
+ * - Endpoint: `POST ${proxyUrl}/api/ai/completion-stream`
575
+ * - Request body: same JSON as `/api/ai/completion` plus `"stream": true`
576
+ * - Response: `Content-Type: text/event-stream`; body is the unified
577
+ * {@link AiAssist.IAiStreamEvent} JSON-serialized one event per SSE `data:` line
578
+ * (no `event:` line needed since the type discriminator is in the JSON).
579
+ * - Error response (when the proxy can't even start): JSON `{error: string}`
580
+ * with a non-2xx status, surfaced as `proxy: ${error}`.
581
+ *
582
+ * The proxy server is responsible for opening the upstream SSE connection,
583
+ * translating provider-native events to the unified vocabulary, and
584
+ * forwarding events as they arrive (no buffering). The library does not
585
+ * ship a proxy implementation.
586
+ *
587
+ * @public
588
+ */
589
+ declare function callProxiedCompletionStream(proxyUrl: string, params: IProviderCompletionStreamParams): Promise<Result<AsyncIterable<IAiStreamEvent>>>;
590
+
591
+ /**
592
+ * Calls the embedding endpoint on a proxy server instead of calling the provider
593
+ * API directly from the browser. Endpoint: `POST ${proxyUrl}/api/ai/embedding`.
594
+ * Request body: `{ providerId, apiKey, params, modelOverride? }`. The proxy
595
+ * handles descriptor lookup, model/capability resolution, and provider dispatch.
596
+ * Error body `{ error: string }` is surfaced as `proxy: ${error}`.
597
+ *
598
+ * @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`).
599
+ * @param params - Same parameters as {@link AiAssist.callProviderEmbedding}.
600
+ * @returns The embedding result, or a failure.
601
+ * @public
602
+ */
603
+ declare function callProxiedEmbedding(proxyUrl: string, params: IProviderEmbeddingParams): Promise<Result<IAiEmbeddingResult>>;
604
+
605
+ /**
606
+ * Calls the image-generation endpoint on a proxy server instead of calling
607
+ * the provider API directly from the browser.
608
+ * Endpoint: `POST ${proxyUrl}/api/ai/image-generation`. Request body:
609
+ * `{providerId, apiKey, params, modelOverride?}`. The proxy handles descriptor
610
+ * lookup, model resolution, provider dispatch, and response normalization
611
+ * (including repackaging `referenceImages` for the upstream wire format).
612
+ * Error body `{error: string}` is surfaced as `proxy: ${error}`.
613
+ * @param proxyUrl - Base URL of the proxy server
614
+ * @param params - Same parameters as {@link callProviderImageGeneration}
615
+ * @public
616
+ */
617
+ declare function callProxiedImageGeneration(proxyUrl: string, params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
618
+
619
+ /**
620
+ * Calls the model-listing endpoint on a proxy server. Endpoint:
621
+ * `POST ${proxyUrl}/api/ai/list-models`. Capability config is not forwarded;
622
+ * `capabilities` is serialized as a string array. Error body `{error: string}`
623
+ * is surfaced as `proxy: ${error}`.
624
+ * @public
625
+ */
626
+ declare function callProxiedListModels(proxyUrl: string, params: IProviderListModelsParams): Promise<Result<ReadonlyArray<IAiModelInfo>>>;
627
+
197
628
  declare namespace Constants {
198
629
  export {
199
630
  ENCRYPTED_FILE_FORMAT,
@@ -210,7 +641,8 @@ declare namespace Converters {
210
641
  extendedArrayOf,
211
642
  rangeTypeOf,
212
643
  rangeOf,
213
- isoDate
644
+ isoDate,
645
+ isoDateTime
214
646
  }
215
647
  }
216
648
  export { Converters }
@@ -219,6 +651,12 @@ declare namespace Converters_2 {
219
651
  export {
220
652
  keystoreFormat,
221
653
  keystoreSecretType,
654
+ keystoreSymmetricSecretType,
655
+ keystoreAsymmetricSecretType,
656
+ keyPairAlgorithm,
657
+ jsonWebKeyShape,
658
+ keystoreSymmetricEntryJson,
659
+ keystoreAsymmetricEntryJson,
222
660
  keystoreSecretEntryJson,
223
661
  keystoreVaultContents,
224
662
  keystoreFile
@@ -232,8 +670,11 @@ declare namespace Converters_3 {
232
670
  encryptedFileFormat,
233
671
  encryptedFileErrorMode,
234
672
  keyDerivationFunction,
673
+ pbkdf2KeyDerivationParams,
674
+ argon2idKeyDerivationParams,
235
675
  keyDerivationParams,
236
676
  base64String,
677
+ multibaseSpkiPublicKey,
237
678
  uint8ArrayFromBase64,
238
679
  namedSecret,
239
680
  encryptedFile
@@ -271,6 +712,8 @@ declare namespace CryptoUtils {
271
712
  Converters_3 as Converters,
272
713
  DirectEncryptionProvider,
273
714
  IDirectEncryptionProviderParams,
715
+ IKeyPairAlgorithmParams,
716
+ keyPairAlgorithmParams,
274
717
  NodeCryptoProvider,
275
718
  nodeCryptoProvider,
276
719
  createEncryptedFile,
@@ -279,13 +722,34 @@ declare namespace CryptoUtils {
279
722
  ICreateEncryptedFileParams,
280
723
  toBase64,
281
724
  tryDecryptFile,
725
+ base64UrlNoPadDecode,
726
+ base64UrlNoPadEncode,
727
+ exportPublicKeyAsMultibaseSpki,
728
+ importPublicKeyFromMultibaseSpki,
729
+ isValidMultibaseSpkiPublicKey,
730
+ MultibaseSpkiPublicKeyRegExp,
731
+ multibaseBase64UrlDecode,
732
+ multibaseBase64UrlEncode,
733
+ HpkeProvider,
734
+ IHpkeSealResult,
282
735
  isEncryptedFile,
736
+ MultibaseSpkiPublicKey,
283
737
  EncryptionAlgorithm,
284
738
  EncryptedFileFormat,
285
739
  INamedSecret,
286
740
  IEncryptionResult,
741
+ KeyPairAlgorithm,
742
+ IWrapBytesOptions,
743
+ IWrappedBytes,
744
+ allKeyPairAlgorithms,
287
745
  KeyDerivationFunction,
746
+ IPbkdf2KeyDerivationParams,
747
+ IArgon2idKeyDerivationParams,
288
748
  IKeyDerivationParams,
749
+ IArgon2idParams,
750
+ ARGON2ID_OWASP_MIN,
751
+ ARGON2ID_PASSPHRASE,
752
+ IArgon2idProvider,
289
753
  IEncryptedFile,
290
754
  ICryptoProvider,
291
755
  IEncryptionProvider,
@@ -299,9 +763,9 @@ export { CryptoUtils }
299
763
  declare namespace Csv {
300
764
  export {
301
765
  parseCsvString,
766
+ readCsvFromTree,
302
767
  CsvOptions,
303
- readCsvFileSync,
304
- readCsvFromTree
768
+ readCsvFileSync
305
769
  }
306
770
  }
307
771
  export { Csv }
@@ -345,6 +809,16 @@ declare const DEFAULT_ALGORITHM: "AES-256-GCM";
345
809
  */
346
810
  declare const DEFAULT_KEYSTORE_ITERATIONS: number;
347
811
 
812
+ /**
813
+ * Default capability config used by `callProviderListModels` when callers
814
+ * don't supply their own. Patterns are intentionally narrow — false
815
+ * positives are worse than missing a model. Caller can override per call
816
+ * via {@link IProviderListModelsParams.capabilityConfig}.
817
+ *
818
+ * @public
819
+ */
820
+ declare const DEFAULT_MODEL_CAPABILITY_CONFIG: IAiModelCapabilityConfig;
821
+
348
822
  /**
349
823
  * Default {@link Experimental.RangeOfFormats | formats} to use for both
350
824
  * open-ended and complete {@link Experimental.RangeOf | RangeOf<T>}.
@@ -441,6 +915,115 @@ declare type EncryptedFileFormat = typeof Constants.ENCRYPTED_FILE_FORMAT;
441
915
  */
442
916
  declare const encryptedFileFormat: Converter<EncryptedFileFormat>;
443
917
 
918
+ /**
919
+ * {@link CryptoUtils.KeyStore.IPrivateKeyStorage | IPrivateKeyStorage}
920
+ * implementation that persists each private key as its own AES-256-GCM-encrypted
921
+ * file in a directory. The file content is the key's JWK, encrypted with a
922
+ * consumer-supplied 32-byte key via the supplied
923
+ * {@link CryptoUtils.ICryptoProvider | crypto provider}.
924
+ *
925
+ * `supportsNonExtractable` is `false`: persisting to disk requires exporting the
926
+ * private key to JWK, which only works for `extractable: true` keys. The
927
+ * keystore generates extractable keys when a backend reports `false` here.
928
+ *
929
+ * I/O goes through the {@link FileTree.FileTree | FileTree} abstraction (default
930
+ * `FsTree`), so the same implementation works against an in-memory tree (tests)
931
+ * or any other Node-compatible backend.
932
+ *
933
+ * This backend is **Node-only**: it round-trips private keys through
934
+ * `node:crypto` (`crypto.webcrypto.subtle`), so it is intentionally excluded
935
+ * from the browser entry point. Browser consumers should use
936
+ * `IdbPrivateKeyStorage` from `@fgv/ts-web-extras` instead.
937
+ *
938
+ * Single-process assumption: there is no inter-process locking. Concurrent
939
+ * writers to the same directory may race.
940
+ *
941
+ * @public
942
+ */
943
+ declare class EncryptedFilePrivateKeyStorage implements IPrivateKeyStorage {
944
+ /**
945
+ * `false` — disk persistence round-trips via JWK, which requires extractable
946
+ * keys.
947
+ */
948
+ readonly supportsNonExtractable: false;
949
+ private readonly _directory;
950
+ private readonly _encryptionKey;
951
+ private readonly _cryptoProvider;
952
+ private constructor();
953
+ /**
954
+ * Creates a new {@link CryptoUtils.KeyStore.EncryptedFilePrivateKeyStorage}.
955
+ * @param params - {@link CryptoUtils.KeyStore.IEncryptedFilePrivateKeyStorageCreateParams}.
956
+ * @returns `Success` with the new instance, or `Failure` if the encryption
957
+ * key is the wrong size or the storage directory cannot be opened.
958
+ */
959
+ static create(params: IEncryptedFilePrivateKeyStorageCreateParams): Result<EncryptedFilePrivateKeyStorage>;
960
+ /**
961
+ * Stores `key` under `id` as an encrypted JWK file.
962
+ * @param id - Storage handle. Must be a safe filename token
963
+ * (`[A-Za-z0-9._-]+`, not `.`/`..`).
964
+ * @param key - The extractable private `CryptoKey` to persist.
965
+ */
966
+ store(id: string, key: CryptoKey): Promise<Result<string>>;
967
+ /**
968
+ * Loads the private key stored under `id`, decrypting and re-importing it from
969
+ * JWK.
970
+ * @param id - Storage handle.
971
+ */
972
+ load(id: string): Promise<Result<CryptoKey>>;
973
+ /**
974
+ * Deletes the entry stored under `id`. Missing ids fail (the read path is
975
+ * keystore-driven and never asks to delete an id it did not store).
976
+ * @param id - Storage handle.
977
+ */
978
+ delete(id: string): Promise<Result<string>>;
979
+ /**
980
+ * Lists every stored id.
981
+ */
982
+ list(): Promise<Result<readonly string[]>>;
983
+ private _fileNameFor;
984
+ /**
985
+ * Validates the synchronous preconditions for a store: the id is filename-safe,
986
+ * the key is actually a private key, and its algorithm is one we support.
987
+ * Returns the resolved filename and algorithm so the async pipeline can run
988
+ * without re-deriving them.
989
+ */
990
+ private _validateKeyToStore;
991
+ /**
992
+ * Exports `key` to JWK, wraps it in the stored envelope, encrypts it with
993
+ * AES-256-GCM, and writes the resulting file as serialized JSON to `fileName`.
994
+ * Returns the stored `id` on success.
995
+ */
996
+ private _encryptAndWrite;
997
+ private _algorithmOf;
998
+ private _findFile;
999
+ private _writeFile;
1000
+ /**
1001
+ * Reads `file`, decrypts the AES-256-GCM envelope, and validates it into the
1002
+ * typed `IStoredPrivateKeyEnvelope`. Read, decrypt, and shape failures
1003
+ * all surface as a decrypt failure for `id`.
1004
+ */
1005
+ private _decryptEnvelope;
1006
+ /**
1007
+ * Parses and shape-validates the stored JWK, then re-imports it as a private
1008
+ * `CryptoKey` for the envelope's algorithm. The WebCrypto JWK-import algorithm
1009
+ * descriptor is shared between public and private keys for every supported
1010
+ * algorithm, so `IKeyPairAlgorithmParams.importPublicKey` is reused here;
1011
+ * the public/private distinction is carried by the requested `usages`.
1012
+ */
1013
+ private _importPrivateKey;
1014
+ /**
1015
+ * Computes the key usages to request when re-importing a stored private key.
1016
+ * WebCrypto rejects `importKey` if the requested usages include operations
1017
+ * absent from the JWK's `key_ops`, so a key originally created with a narrower
1018
+ * usage set than the algorithm default (e.g. an ECDH key with only
1019
+ * `deriveBits`) would fail to load against the algorithm-wide defaults.
1020
+ * Intersect the algorithm's private usages with the JWK's recorded `key_ops`
1021
+ * so we request exactly the operations the stored key actually supports;
1022
+ * fall back to the algorithm's private usages when `key_ops` is absent.
1023
+ */
1024
+ private _importUsagesFor;
1025
+ }
1026
+
444
1027
  /**
445
1028
  * Supported encryption algorithms.
446
1029
  * @public
@@ -453,6 +1036,29 @@ declare type EncryptionAlgorithm = typeof Constants.DEFAULT_ALGORITHM;
453
1036
  */
454
1037
  declare const encryptionAlgorithm: Converter<EncryptionAlgorithm>;
455
1038
 
1039
+ /**
1040
+ * Orchestrates a single client-tool streaming turn for any supported provider.
1041
+ *
1042
+ * Starts a streaming request, iterates the underlying provider stream, and:
1043
+ * - Forwards `text-delta`, `tool-event`, `client-tool-call-start`, and
1044
+ * `client-tool-call-done` events through to the consumer.
1045
+ * - For each `client-tool-call-done` event: validates the raw args against the
1046
+ * tool's `parametersSchema`, invokes `execute(typedArgs)`, and emits a
1047
+ * `client-tool-result` event.
1048
+ * - After stream completion: builds the per-provider continuation (or
1049
+ * `{ continuation: undefined }` when no tool calls occurred) and resolves
1050
+ * `nextTurn`.
1051
+ *
1052
+ * **Anthropic constraint (E3):** The continuation for Anthropic does not set
1053
+ * a forced `tool_choice`. Only `tool_choice: 'auto'` (the default, i.e.
1054
+ * omitted) is compatible with extended thinking.
1055
+ *
1056
+ * @param params - Turn parameters
1057
+ * @returns `{ events, nextTurn }` — stream iterable + completion promise
1058
+ * @public
1059
+ */
1060
+ declare function executeClientToolTurn(params: IExecuteClientToolTurnParams): Result<IExecuteClientToolTurnResult>;
1061
+
456
1062
  declare namespace Experimental {
457
1063
  export {
458
1064
  ExtendedArray,
@@ -471,6 +1077,20 @@ declare namespace Experimental {
471
1077
  }
472
1078
  export { Experimental }
473
1079
 
1080
+ /**
1081
+ * Exports a public `CryptoKey` as a multibase base64url-encoded SPKI blob.
1082
+ *
1083
+ * The SPKI (SubjectPublicKeyInfo) format is the standard DER-encoded structure
1084
+ * for public keys defined in RFC 5280, RFC 5480, and RFC 8410. It is
1085
+ * algorithm-agnostic and suitable for storage and transmission.
1086
+ *
1087
+ * @param key - The `CryptoKey` to export. Must have `key.type === 'public'`.
1088
+ * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the export operation.
1089
+ * @returns `Success` with the multibase SPKI string, or `Failure` with error context.
1090
+ * @public
1091
+ */
1092
+ declare function exportPublicKeyAsMultibaseSpki(key: CryptoKey, provider: ICryptoProvider): Promise<Result<MultibaseSpkiPublicKey>>;
1093
+
474
1094
  /**
475
1095
  * An experimental array template which extend built-in `Array` to include a handful
476
1096
  * of predicates which return `Result<T>`.
@@ -532,11 +1152,59 @@ declare class ExtendedArray<T> extends Array<T> {
532
1152
  * If `onError` is `'failOnError'` (default), then the entire conversion fails if any element cannot
533
1153
  * be converted. If `onError` is `'ignoreErrors'`, then failing elements are silently ignored.
534
1154
  * @param converter - `Converter` used to convert each item in the array
535
- * @param ignoreErrors - Specifies treatment of unconvertible elements
1155
+ * @param onError - Specifies treatment of unconvertible elements
536
1156
  * @beta
537
1157
  */
538
1158
  declare function extendedArrayOf<T, TC = undefined>(label: string, converter: Converter<T, TC>, onError?: Conversion.OnError): Converter<ExtendedArray<T>, TC>;
539
1159
 
1160
+ /**
1161
+ * Default {@link AiAssist.JsonTextExtractor | extractor} for LLM responses. Tolerates:
1162
+ *
1163
+ * - Leading/trailing whitespace and a leading byte-order mark.
1164
+ * - Markdown code fences (with or without a language tag).
1165
+ * - Conversational preamble before the first `{` or `[`.
1166
+ * - Trailing prose after the matched closing `}` or `]`.
1167
+ *
1168
+ * Out of scope: repairing malformed JSON, handling smart quotes, etc.
1169
+ *
1170
+ * @param text - Raw model output.
1171
+ * @returns A `Result<string>` containing the JSON-shaped substring, or a
1172
+ * `Failure` if no JSON-shaped substring was found.
1173
+ * @public
1174
+ */
1175
+ declare const extractJsonText: JsonTextExtractor;
1176
+
1177
+ /**
1178
+ * Creates a `Converter` that accepts raw LLM response text, runs it through a
1179
+ * tolerant extractor (default: {@link AiAssist.extractJsonText}), parses the
1180
+ * extracted substring as JSON, and applies an optional inner converter or
1181
+ * validator.
1182
+ *
1183
+ * @example
1184
+ * ```ts
1185
+ * const converter = fencedStringifiedJson({ inner: myShapeConverter });
1186
+ * const result = converter.convert(llmText); // Result<MyShape>
1187
+ * ```
1188
+ *
1189
+ * @param options - Optional extractor; omit to keep the default. Without an
1190
+ * `inner` step, the converter resolves to the parsed `JsonValue`.
1191
+ * @returns A `Converter<JsonValue>`.
1192
+ * @public
1193
+ */
1194
+ declare function fencedStringifiedJson(options?: IFencedStringifiedJsonExtractorOptions): Converter<JsonValue>;
1195
+
1196
+ /**
1197
+ * Creates a `Converter` that accepts raw LLM response text, runs it through a
1198
+ * tolerant extractor (default: {@link AiAssist.extractJsonText}), parses the
1199
+ * extracted substring as JSON, and applies the supplied inner converter or
1200
+ * validator.
1201
+ *
1202
+ * @param options - Required `inner` converter/validator and optional extractor.
1203
+ * @returns A `Converter<T>`.
1204
+ * @public
1205
+ */
1206
+ declare function fencedStringifiedJson<T>(options: IFencedStringifiedJsonOptions<T>): Converter<T>;
1207
+
540
1208
  /**
541
1209
  * Formats a list of items using the supplied template and formatter, one result
542
1210
  * per output line.
@@ -628,6 +1296,36 @@ declare const GCM_AUTH_TAG_SIZE: number;
628
1296
  */
629
1297
  declare const GCM_IV_SIZE: number;
630
1298
 
1299
+ /** Model names in the Gemini Flash Image family. @public */
1300
+ declare type GeminiFlashImageModelNames = 'gemini-3.1-flash-image-preview';
1301
+
1302
+ /**
1303
+ * Model IDs for Google Gemini thinking-capable models.
1304
+ * @public
1305
+ */
1306
+ declare type GeminiThinkingModelNames = 'gemini-3.1-pro-preview' | 'gemini-3.5-flash' | 'gemini-3.1-flash-lite';
1307
+
1308
+ /**
1309
+ * Calls {@link AiAssist.callProviderCompletion}, then runs the response text
1310
+ * through a tolerant JSON converter (default:
1311
+ * {@link AiAssist.fencedStringifiedJson}) and the caller's
1312
+ * `converter`/`validator`. Returns the validated value plus the raw text and
1313
+ * underlying completion response for diagnostics.
1314
+ *
1315
+ * @remarks
1316
+ * The default smart prompt hint asks the model to emit raw JSON. The read-side
1317
+ * extractor still tolerates fences and prose, so models that ignore the hint
1318
+ * are still handled.
1319
+ *
1320
+ * Either `converter` or `jsonConverter` must be provided; passing both lets
1321
+ * `jsonConverter` win.
1322
+ *
1323
+ * @param params - Provider parameters plus JSON validation options.
1324
+ * @returns The validated value, the raw text, and the underlying response.
1325
+ * @public
1326
+ */
1327
+ declare function generateJsonCompletion<T>(params: IGenerateJsonCompletionParams<T>): Promise<Result<IGenerateJsonCompletionResult<T>>>;
1328
+
631
1329
  /**
632
1330
  * Get a provider descriptor by id.
633
1331
  * @param id - The provider identifier
@@ -643,6 +1341,18 @@ declare function getProviderDescriptor(id: string): Result<IAiProviderDescriptor
643
1341
  */
644
1342
  declare function getProviderDescriptors(): ReadonlyArray<IAiProviderDescriptor>;
645
1343
 
1344
+ /** Model names in the GPT Image family. @public */
1345
+ declare type GptImageModelNames = 'gpt-image-1' | 'gpt-image-1.5';
1346
+
1347
+ /** Quality values for gpt-image-1. @public */
1348
+ declare type GptImageQuality = 'low' | 'medium' | 'high' | 'auto';
1349
+
1350
+ /** Pixel dimension sizes accepted by gpt-image-1. @public */
1351
+ declare type GptImageSize = '1024x1024' | '1536x1024' | '1024x1536' | 'auto';
1352
+
1353
+ /** Model names in the xAI Grok Imagine family. @public */
1354
+ declare type GrokImagineModelNames = 'grok-imagine-image' | 'grok-imagine-image-quality';
1355
+
646
1356
  declare namespace Hash {
647
1357
  export {
648
1358
  Md5Normalizer
@@ -651,20 +1361,212 @@ declare namespace Hash {
651
1361
  export { Hash }
652
1362
 
653
1363
  /**
654
- * Options for adding a secret derived from a password.
1364
+ * HPKE base mode (RFC 9180) `DHKEM(X25519, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM`.
1365
+ *
1366
+ * Class-based provider that captures a `SubtleCrypto` instance at construction,
1367
+ * matching the existing `NodeCryptoProvider` / `BrowserCryptoProvider` / `KeyStore`
1368
+ * factory pattern used throughout `@fgv/ts-extras/crypto-utils`.
1369
+ *
1370
+ * **Node.js usage:**
1371
+ * ```typescript
1372
+ * import * as crypto from 'crypto';
1373
+ * const hpke = HpkeProvider.create(crypto.webcrypto.subtle).orThrow();
1374
+ * ```
1375
+ *
1376
+ * **Browser usage:**
1377
+ * ```typescript
1378
+ * const hpke = HpkeProvider.create(globalThis.crypto.subtle).orThrow();
1379
+ * ```
1380
+ *
1381
+ * **Runtime requirements:** Node.js 20+ (X25519 in `crypto.webcrypto`);
1382
+ * Chrome 113+, Safari 16.4+, Firefox 118+ (X25519 added to Web Crypto in 2023).
655
1383
  * @public
656
1384
  */
657
- declare interface IAddSecretFromPasswordOptions extends IAddSecretOptions {
1385
+ declare class HpkeProvider {
1386
+ private readonly _subtle;
1387
+ private constructor();
658
1388
  /**
659
- * Whether to replace an existing secret with the same name.
1389
+ * Creates an `HpkeProvider` bound to the given `SubtleCrypto` instance.
1390
+ *
1391
+ * @param subtle - Web Crypto SubtleCrypto instance.
1392
+ * Node.js: `(await import('crypto')).webcrypto.subtle`.
1393
+ * Browser: `globalThis.crypto.subtle`.
1394
+ * @returns `Success` with the provider, or `Failure` if construction fails.
660
1395
  */
661
- readonly replace?: boolean;
1396
+ static create(subtle: SubtleCrypto): Result<HpkeProvider>;
662
1397
  /**
663
- * PBKDF2 iterations for key derivation.
664
- * @defaultValue DEFAULT_SECRET_ITERATIONS (350000)
665
- */
666
- readonly iterations?: number;
667
- }
1398
+ * HPKE base-mode seal (sender side). RFC 9180 §6.1.
1399
+ *
1400
+ * Generates a fresh ephemeral X25519 keypair, runs DHKEM Encap to produce a
1401
+ * shared secret and `enc` (32-byte raw ephemeral public key), derives the AEAD
1402
+ * key and nonce deterministically via the RFC 9180 key schedule, then encrypts
1403
+ * `plaintext` with AES-256-GCM.
1404
+ *
1405
+ * @param recipientPublicKey - Recipient's X25519 public `CryptoKey`
1406
+ * (`algorithm.name === 'X25519'`, `type === 'public'`, **`extractable: true`**).
1407
+ * Must be extractable — DHKEM Encap calls `exportKey('raw', ...)` on this key to
1408
+ * build the KEM shared-secret context. Keys imported with `extractable: false` will
1409
+ * cause this method to return a `Failure`.
1410
+ * @param info - Context-binding bytes. **Load-bearing — no default.**
1411
+ * Binds this ciphertext to a specific application context, preventing replay
1412
+ * across different contexts sharing the same recipient keypair.
1413
+ * Use `new TextEncoder().encode('myapp/v1/use-case\x00' + contextId)` pattern.
1414
+ * Never pass an empty array in production: empty `info` provides no context binding.
1415
+ * @param aad - Additional authenticated data. Integrity-protected but not encrypted.
1416
+ * `new Uint8Array(0)` is valid when no AAD is needed.
1417
+ * @param plaintext - Bytes to encrypt. `new Uint8Array(0)` is valid.
1418
+ * @returns `Success` with `{ enc, ciphertext }`, or `Failure` with error context.
1419
+ */
1420
+ sealBase(recipientPublicKey: CryptoKey, info: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): Promise<Result<IHpkeSealResult>>;
1421
+ /**
1422
+ * HPKE base-mode open (recipient side). RFC 9180 §6.1.
1423
+ *
1424
+ * Decapsulates `enc` using the recipient's X25519 private key, derives the same
1425
+ * AEAD key and nonce from the shared secret and `info`, then authenticates and
1426
+ * decrypts `ciphertext` with AES-256-GCM.
1427
+ *
1428
+ * Returns `Failure` on any of:
1429
+ * - Wrong private key (different DH output → different key derivation)
1430
+ * - Wrong `info` (different key schedule context → different AEAD key)
1431
+ * - Wrong `aad` (AES-GCM authentication fails)
1432
+ * - Tampered `ciphertext` or `enc` (authentication fails or DH fails)
1433
+ * - `enc` not exactly 32 bytes
1434
+ * - `ciphertext` shorter than 16 bytes (no room for authentication tag)
1435
+ *
1436
+ * @param recipientPrivateKey - Recipient's X25519 private `CryptoKey`
1437
+ * (`algorithm.name === 'X25519'`, `type === 'private'`, `usages` includes `'deriveBits'`).
1438
+ * **Must be extractable** (`extractable: true`) — the recipient's public key bytes
1439
+ * are recovered from the JWK `x` field during Decap.
1440
+ * @param info - Context-binding bytes. Must exactly match `info` from `sealBase`.
1441
+ * @param aad - Must exactly match `aad` from `sealBase`.
1442
+ * @param enc - The encapsulated key from `sealBase` — exactly 32 bytes.
1443
+ * @param ciphertext - The ciphertext from `sealBase` — `plaintext.length + 16` bytes.
1444
+ * @returns `Success` with decrypted plaintext bytes, or `Failure` with error context.
1445
+ */
1446
+ openBase(recipientPrivateKey: CryptoKey, info: Uint8Array, aad: Uint8Array, enc: Uint8Array, ciphertext: Uint8Array): Promise<Result<Uint8Array>>;
1447
+ /**
1448
+ * HKDF-SHA256 key derivation (RFC 5869). Extract-then-Expand using SHA-256.
1449
+ *
1450
+ * This is raw RFC 5869 HKDF — it does **not** use RFC 9180's labeled variants.
1451
+ * The HPKE key schedule internally uses labeled HKDF; this method is the unlabeled
1452
+ * version for callers that need standalone key derivation.
1453
+ *
1454
+ * @param secret - Input keying material (IKM). Any length.
1455
+ * @param salt - Optional salt. Use `new Uint8Array(0)` if no salt is available
1456
+ * (RFC 5869: 32 zero bytes are used internally when salt is empty).
1457
+ * @param info - Context / application-binding bytes. Any length.
1458
+ * @param length - Number of output bytes to derive. Maximum 8160 bytes (255 × 32).
1459
+ * @returns `Success` with derived bytes, or `Failure` with error context.
1460
+ */
1461
+ hkdf(secret: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Promise<Result<Uint8Array>>;
1462
+ /**
1463
+ * Encodes an {@link IHpkeSealResult} as a single contiguous byte array for wire transport.
1464
+ *
1465
+ * Format: `enc` (32 bytes, fixed) || `ciphertext` (variable length).
1466
+ * The 32-byte `enc` length is fixed for X25519; the split point is unambiguous.
1467
+ *
1468
+ * @param result - The output of {@link HpkeProvider.sealBase}.
1469
+ * @returns Concatenated bytes: `enc || ciphertext`.
1470
+ */
1471
+ static encodeEnvelope(result: IHpkeSealResult): Uint8Array;
1472
+ /**
1473
+ * Decodes an envelope produced by {@link HpkeProvider.encodeEnvelope}.
1474
+ *
1475
+ * Validates that the buffer is at least 48 bytes (32-byte enc + 16-byte minimum
1476
+ * ciphertext containing the AES-GCM auth tag; zero-length plaintext is the minimum
1477
+ * meaningful case).
1478
+ *
1479
+ * @param envelope - Envelope bytes from `encodeEnvelope`.
1480
+ * @returns `Success` with `{ enc, ciphertext }`, or `Failure` if malformed.
1481
+ */
1482
+ static decodeEnvelope(envelope: Uint8Array): Result<IHpkeSealResult>;
1483
+ }
1484
+
1485
+ /**
1486
+ * Options for adding an asymmetric keypair to the key store.
1487
+ * @public
1488
+ */
1489
+ declare interface IAddKeyPairOptions {
1490
+ /**
1491
+ * Algorithm to use for the new keypair.
1492
+ */
1493
+ readonly algorithm: KeyPairAlgorithm;
1494
+ /**
1495
+ * Optional description for the entry.
1496
+ */
1497
+ readonly description?: string;
1498
+ /**
1499
+ * Whether to replace an existing entry with the same name.
1500
+ * Replacement mints a fresh storage `id` and best-effort deletes the
1501
+ * displaced storage blob; see the keystore design doc for details.
1502
+ */
1503
+ readonly replace?: boolean;
1504
+ /**
1505
+ * Overrides the storage-backend-derived extractability for this key only.
1506
+ * Omit to keep the default (`!privateKeyStorage.supportsNonExtractable`).
1507
+ * A value the backend cannot honor fails loudly rather than silently
1508
+ * downgrading.
1509
+ */
1510
+ readonly extractable?: boolean;
1511
+ }
1512
+
1513
+ /**
1514
+ * Result of adding an asymmetric keypair to the key store.
1515
+ * @public
1516
+ */
1517
+ declare interface IAddKeyPairResult {
1518
+ /**
1519
+ * The asymmetric entry that was added.
1520
+ */
1521
+ readonly entry: IKeyStoreAsymmetricEntry;
1522
+ /**
1523
+ * Whether this replaced an existing entry.
1524
+ */
1525
+ readonly replaced: boolean;
1526
+ /**
1527
+ * Best-effort warning from displaced-resource cleanup. Set when this call
1528
+ * replaced a prior entry but the corresponding
1529
+ * {@link CryptoUtils.KeyStore.IPrivateKeyStorage}.delete failed; the new
1530
+ * keypair is still committed and the orphaned blob is left for consumer-side
1531
+ * GC to reconcile.
1532
+ */
1533
+ readonly warning?: string;
1534
+ }
1535
+
1536
+ /**
1537
+ * Options for adding an Argon2id password-derived secret.
1538
+ * @public
1539
+ */
1540
+ declare interface IAddSecretFromPasswordArgon2idOptions {
1541
+ /**
1542
+ * Argon2id parameters. Defaults to {@link CryptoUtils.ARGON2ID_OWASP_MIN}.
1543
+ */
1544
+ readonly params?: IArgon2idParams;
1545
+ /**
1546
+ * Optional description for the secret.
1547
+ */
1548
+ readonly description?: string;
1549
+ /**
1550
+ * Whether to replace an existing secret with the same name.
1551
+ */
1552
+ readonly replace?: boolean;
1553
+ }
1554
+
1555
+ /**
1556
+ * Options for adding a secret derived from a password.
1557
+ * @public
1558
+ */
1559
+ declare interface IAddSecretFromPasswordOptions extends IAddSecretOptions {
1560
+ /**
1561
+ * Whether to replace an existing secret with the same name.
1562
+ */
1563
+ readonly replace?: boolean;
1564
+ /**
1565
+ * PBKDF2 iterations for key derivation.
1566
+ * @defaultValue DEFAULT_SECRET_ITERATIONS (350000)
1567
+ */
1568
+ readonly iterations?: number;
1569
+ }
668
1570
 
669
1571
  /**
670
1572
  * Result of adding a password-derived secret.
@@ -700,11 +1602,19 @@ declare interface IAddSecretResult {
700
1602
  /**
701
1603
  * The secret entry that was added.
702
1604
  */
703
- readonly entry: IKeyStoreSecretEntry;
1605
+ readonly entry: IKeyStoreSymmetricEntry;
704
1606
  /**
705
1607
  * Whether this replaced an existing secret.
706
1608
  */
707
1609
  readonly replaced: boolean;
1610
+ /**
1611
+ * Best-effort warning from displaced-resource cleanup. Set when this call
1612
+ * replaced an asymmetric-keypair entry but the corresponding
1613
+ * {@link CryptoUtils.KeyStore.IPrivateKeyStorage}.delete failed; the new
1614
+ * entry is still committed and the orphaned blob is left for consumer-side
1615
+ * GC to reconcile.
1616
+ */
1617
+ readonly warning?: string;
708
1618
  }
709
1619
 
710
1620
  /**
@@ -734,6 +1644,14 @@ declare interface IAiAssistProviderConfig {
734
1644
  readonly model?: ModelSpec;
735
1645
  /** Tool enablement/configuration. Tools are disabled unless explicitly enabled. */
736
1646
  readonly tools?: ReadonlyArray<IAiToolEnablement>;
1647
+ /**
1648
+ * Optional caller-supplied endpoint URL (http/https). Overrides
1649
+ * `descriptor.baseUrl` for this provider. Used to point a provider at a
1650
+ * self-hosted server (Ollama, LM Studio, llama.cpp's openai-server) or a
1651
+ * local proxy. Validation lives in `@fgv/ts-extras` — query strings,
1652
+ * fragments, and userinfo are rejected.
1653
+ */
1654
+ readonly endpoint?: string;
737
1655
  }
738
1656
 
739
1657
  /**
@@ -751,6 +1669,145 @@ declare interface IAiAssistSettings {
751
1669
  readonly proxyAllProviders?: boolean;
752
1670
  }
753
1671
 
1672
+ /**
1673
+ * A client-defined tool: configuration + execution callback pair.
1674
+ *
1675
+ * @remarks
1676
+ * The `execute` callback receives typed `TParams` (already validated by
1677
+ * `config.parametersSchema.validate()`) and returns a `Promise<Result<unknown>>`.
1678
+ * Thrown errors are caught via `captureAsyncResult` in the round-trip helper.
1679
+ *
1680
+ * @public
1681
+ */
1682
+ declare interface IAiClientTool<TParams = unknown> {
1683
+ /** The tool's configuration (name, description, parameters schema). */
1684
+ readonly config: IAiClientToolConfig<TParams>;
1685
+ /**
1686
+ * Execute the tool with validated parameters.
1687
+ * @param args - Typed arguments, already validated against `config.parametersSchema`.
1688
+ * @returns A `Promise<Result<unknown>>` — the result is stringified and sent back to the model.
1689
+ */
1690
+ readonly execute: (args: TParams) => Promise<Result<unknown>>;
1691
+ }
1692
+
1693
+ /**
1694
+ * Summary of a single client tool call within a turn: the tool name, call ID,
1695
+ * raw arguments, execution result, and whether the execution was an error.
1696
+ * @public
1697
+ */
1698
+ declare interface IAiClientToolCallSummary {
1699
+ /** The name of the tool that was called. */
1700
+ readonly toolName: string;
1701
+ /** Provider-assigned call identifier (absent for Gemini). */
1702
+ readonly callId?: string;
1703
+ /** The fully accumulated raw arguments object as parsed JSON. */
1704
+ readonly args: JsonObject;
1705
+ /** The stringified result (success value or error message). */
1706
+ readonly result: string;
1707
+ /** Whether execution failed (schema validation failure, execute error, or unknown tool). */
1708
+ readonly isError: boolean;
1709
+ }
1710
+
1711
+ /**
1712
+ * Configuration for a client-defined (harness-supplied) tool.
1713
+ *
1714
+ * @remarks
1715
+ * The `parametersSchema` is the single source of truth for both the wire-format
1716
+ * JSON Schema sent to the provider (via `.toJson()`) and the runtime argument
1717
+ * validation (via `.validate(rawArgs)`). Use `JsonSchema.object(...)` from
1718
+ * `@fgv/ts-json-base` to author the schema as a const (e.g. `const mySchema = JsonSchema.object({...})`);
1719
+ * the static type `TParams` is then derived via `JsonSchema.Static<typeof mySchema>` —
1720
+ * no drift between wire schema and runtime validation.
1721
+ *
1722
+ * @public
1723
+ */
1724
+ declare interface IAiClientToolConfig<TParams = unknown> {
1725
+ /** Discriminator — always `'client_tool'`. */
1726
+ readonly type: 'client_tool';
1727
+ /** Tool name sent to the model (must be unique within a call). */
1728
+ readonly name: string;
1729
+ /** Human-readable description of what the tool does, shown to the model. */
1730
+ readonly description: string;
1731
+ /**
1732
+ * JSON Schema validator for the tool's parameters. Emits wire format via
1733
+ * `.toJson()` and validates model-returned args via `.validate(rawArgs)`.
1734
+ */
1735
+ readonly parametersSchema: JsonSchema.ISchemaValidator<TParams>;
1736
+ /**
1737
+ * Optional host-advisory behavior annotations (read-only / destructive /
1738
+ * idempotent / open-world hints + display title). Consumed by the host's
1739
+ * tool loop; never serialized to the model. See {@link IAiToolAnnotations}.
1740
+ */
1741
+ readonly annotations?: IAiToolAnnotations;
1742
+ }
1743
+
1744
+ /**
1745
+ * The provider-specific continuation data needed to build the follow-up request
1746
+ * for the next round of the conversation.
1747
+ *
1748
+ * @remarks
1749
+ * `messages` are provider-native request objects (Anthropic: content-block arrays,
1750
+ * OpenAI Responses API: input items, Gemini: content parts). The continuation
1751
+ * builder in `clientToolContinuationBuilder.ts` populates this.
1752
+ *
1753
+ * @public
1754
+ */
1755
+ declare interface IAiClientToolContinuation {
1756
+ /**
1757
+ * **Cumulative** provider-native wire-format message objects covering all
1758
+ * tool rounds so far. On each turn, `executeClientToolTurn` prepends the
1759
+ * inbound `continuationMessages` so that this array always contains the
1760
+ * complete wire tail from round 1 through the current round.
1761
+ *
1762
+ * To drive a multi-round loop, simply **replace** `continuationMessages`
1763
+ * with this value — do not manually concatenate:
1764
+ *
1765
+ * ```ts
1766
+ * let tail: JsonObject[] | undefined;
1767
+ * while (true) {
1768
+ * const { events, nextTurn } = executeClientToolTurn({
1769
+ * ..., continuationMessages: tail
1770
+ * }).orThrow();
1771
+ * for await (const e of events) { /* observe *\/ }
1772
+ * const outcome = (await nextTurn).orThrow();
1773
+ * if (!outcome.continuation) break;
1774
+ * tail = [...outcome.continuation.messages]; // replace — already cumulative
1775
+ * }
1776
+ * ```
1777
+ *
1778
+ * The exact shape is provider-native and may include provider-specific
1779
+ * blocks (e.g. Anthropic thinking/redacted_thinking/tool_use, OpenAI
1780
+ * function_call/function_call_output items, Gemini functionCall/functionResponse
1781
+ * parts). These are NOT `IChatMessage[]` and must NOT be placed in the
1782
+ * `messages` parameter — the normalized-message path strips provider-native
1783
+ * fields (thinking signatures, redacted_thinking data) that the server
1784
+ * requires for continuation validation.
1785
+ *
1786
+ * `toolCallsSummary` is per-round only (the calls executed in the current
1787
+ * turn). Only `messages` is cumulative.
1788
+ */
1789
+ readonly messages: ReadonlyArray<JsonObject>;
1790
+ /** Summary of each tool call executed in this turn (per-round, not cumulative). */
1791
+ readonly toolCallsSummary: ReadonlyArray<IAiClientToolCallSummary>;
1792
+ }
1793
+
1794
+ /**
1795
+ * The result of a single client-tool turn: the optional continuation for the next
1796
+ * call (absent when no tool calls occurred) and whether the stream was truncated.
1797
+ * @public
1798
+ */
1799
+ declare interface IAiClientToolTurnResult {
1800
+ /**
1801
+ * The continuation data for the next round-trip. `undefined` when the model
1802
+ * completed without invoking any client tools.
1803
+ */
1804
+ readonly continuation: IAiClientToolContinuation | undefined;
1805
+ /** Whether the stream was truncated (token limit or stop reason). */
1806
+ readonly truncated: boolean;
1807
+ /** The full concatenated text from all `text-delta` events in this turn. */
1808
+ readonly fullText: string;
1809
+ }
1810
+
754
1811
  /**
755
1812
  * Result of an AI provider completion call.
756
1813
  * @public
@@ -762,6 +1819,317 @@ declare interface IAiCompletionResponse {
762
1819
  readonly truncated: boolean;
763
1820
  }
764
1821
 
1822
+ /**
1823
+ * Embedding capability for a model family within a provider. Used as an entry
1824
+ * in {@link IAiProviderDescriptor.embedding}.
1825
+ *
1826
+ * @public
1827
+ */
1828
+ declare interface IAiEmbeddingModelCapability {
1829
+ /**
1830
+ * Prefix matched against the resolved embedding model id. The empty string is
1831
+ * the catch-all and matches every model. When multiple rules' prefixes match
1832
+ * a model id, the longest prefix wins; ties are broken by first-encountered.
1833
+ */
1834
+ readonly modelPrefix: string;
1835
+ /** API format used to dispatch requests for matching models. */
1836
+ readonly format: AiEmbeddingApiFormat;
1837
+ /**
1838
+ * Whether matching models honor a requested output `dimensions`
1839
+ * (OpenAI `text-embedding-3-*`, Gemini `gemini-embedding-001` via MRL
1840
+ * truncation). When false/undefined, a caller-supplied `dimensions` is a
1841
+ * no-op (logged, not failed — see {@link AiAssist.IAiEmbeddingParams}).
1842
+ */
1843
+ readonly supportsDimensions?: boolean;
1844
+ /**
1845
+ * Whether matching models honor a `taskType` hint (Gemini only today). When
1846
+ * false/undefined, a caller-supplied `taskType` is a no-op (logged, not
1847
+ * failed).
1848
+ */
1849
+ readonly supportsTaskType?: boolean;
1850
+ /** Native fixed output dimension, when the model has one (metadata only). */
1851
+ readonly defaultDimensions?: number;
1852
+ /**
1853
+ * Maximum number of inputs accepted per request. When present, the dispatcher
1854
+ * rejects batches larger than this up front (no auto-chunking in v1).
1855
+ */
1856
+ readonly maxBatchSize?: number;
1857
+ }
1858
+
1859
+ /**
1860
+ * Parameters for an embedding request. Batch is the norm: `input` accepts a
1861
+ * single string or an array; the result always exposes a vector array aligned
1862
+ * by index to the input.
1863
+ *
1864
+ * @public
1865
+ */
1866
+ declare interface IAiEmbeddingParams {
1867
+ /** One or more input strings. A bare string is treated as a single-element batch. */
1868
+ readonly input: string | ReadonlyArray<string>;
1869
+ /**
1870
+ * Requested output dimensionality. Honored only by models whose capability
1871
+ * declares `supportsDimensions` (OpenAI `text-embedding-3-*`, Gemini
1872
+ * `gemini-embedding-001` via MRL truncation). Ignored — with a `logger.info`
1873
+ * note — by models that don't.
1874
+ */
1875
+ readonly dimensions?: number;
1876
+ /**
1877
+ * Task-type hint. Mapped to Gemini `taskType`; a no-op (with a `logger.info`
1878
+ * note) on OpenAI/Ollama/compat/Mistral. Preserves Gemini's
1879
+ * query-vs-document retrieval asymmetry.
1880
+ */
1881
+ readonly taskType?: AiEmbeddingTaskType;
1882
+ }
1883
+
1884
+ /**
1885
+ * Result of an embedding call. `vectors[i]` is the embedding for `input[i]`,
1886
+ * in request order.
1887
+ *
1888
+ * @remarks
1889
+ * Vectors are plain `number[]` (not `Float32Array`) for JSON-wire fidelity and
1890
+ * validator-friendliness — consumers who want a typed array call
1891
+ * `Float32Array.from(vector)` at the vector-store / WebGPU boundary. The
1892
+ * library does not L2-normalize; Gemini's MRL truncation (when
1893
+ * `dimensions < native`) returns un-normalized vectors that the consumer should
1894
+ * normalize if their similarity metric requires it.
1895
+ *
1896
+ * @public
1897
+ */
1898
+ declare interface IAiEmbeddingResult {
1899
+ /** One vector per input, aligned by index to the request order. */
1900
+ readonly vectors: ReadonlyArray<ReadonlyArray<number>>;
1901
+ /** The resolved provider-native model id that produced the vectors. */
1902
+ readonly model: string;
1903
+ /** Dimensionality of each returned vector (`vectors[0].length`; `0` for empty input). */
1904
+ readonly dimensions: number;
1905
+ /** Token usage, when the provider reports it (OpenAI-format; absent for Gemini). */
1906
+ readonly usage?: IAiEmbeddingUsage;
1907
+ }
1908
+
1909
+ /**
1910
+ * Token-usage accounting for an embedding call, when the provider reports it.
1911
+ * @public
1912
+ */
1913
+ declare interface IAiEmbeddingUsage {
1914
+ /** Tokens consumed by the input(s). */
1915
+ readonly promptTokens?: number;
1916
+ /** Total tokens billed. */
1917
+ readonly totalTokens?: number;
1918
+ }
1919
+
1920
+ /**
1921
+ * A single generated image.
1922
+ * @public
1923
+ */
1924
+ declare interface IAiGeneratedImage extends IAiImageData {
1925
+ /**
1926
+ * The prompt as rewritten by the provider, if any. OpenAI's image models
1927
+ * commonly rewrite prompts; other providers do not.
1928
+ */
1929
+ readonly revisedPrompt?: string;
1930
+ }
1931
+
1932
+ /**
1933
+ * Image attachment for a vision (image-input) prompt.
1934
+ *
1935
+ * @remarks
1936
+ * Extends {@link IAiImageData} with an OpenAI-specific `detail` hint that is
1937
+ * silently ignored by Anthropic, Gemini, and other providers.
1938
+ *
1939
+ * @public
1940
+ */
1941
+ declare interface IAiImageAttachment extends IAiImageData {
1942
+ /**
1943
+ * OpenAI vision detail hint:
1944
+ * - `'low'`: faster, cheaper, lower fidelity
1945
+ * - `'high'`: slower, more expensive, higher fidelity
1946
+ * - `'auto'` (default): provider chooses
1947
+ *
1948
+ * Ignored by providers other than OpenAI.
1949
+ */
1950
+ readonly detail?: 'low' | 'high' | 'auto';
1951
+ }
1952
+
1953
+ /**
1954
+ * Universal image representation used for both image input (vision prompts)
1955
+ * and image output (generation responses).
1956
+ *
1957
+ * @remarks
1958
+ * The base64 string is raw — no `data:` URL prefix. Use {@link AiAssist.toDataUrl} to
1959
+ * format it for browser-display contexts.
1960
+ *
1961
+ * @public
1962
+ */
1963
+ declare interface IAiImageData {
1964
+ /** MIME type, e.g. `'image/png'`, `'image/jpeg'`, `'image/webp'`. */
1965
+ readonly mimeType: string;
1966
+ /** Base64-encoded image bytes (no `data:` prefix). */
1967
+ readonly base64: string;
1968
+ }
1969
+
1970
+ /**
1971
+ * Options for image generation requests.
1972
+ *
1973
+ * @remarks
1974
+ * Uses a layered architecture:
1975
+ * 1. Generic top-level options (size, count, quality, seed) apply across providers
1976
+ * via the resolved model's registry mapping.
1977
+ * 2. Optional `models` array contains model-family-scoped blocks; the resolver
1978
+ * picks applicable blocks based on the resolved model and applies them in
1979
+ * declaration order.
1980
+ *
1981
+ * **Merge precedence (later wins):**
1982
+ * 1. Generic top-level options (lowest precedence)
1983
+ * 2. Family-generic blocks (matching family, models field omitted)
1984
+ * 3. Model-specific blocks (models array includes resolved model name)
1985
+ * 4. Other blocks (provider: 'other', models array includes resolved model name)
1986
+ *
1987
+ * Provider-mismatch: blocks whose provider doesn't match the dispatcher's
1988
+ * provider lineage are silently skipped.
1989
+ *
1990
+ * @public
1991
+ */
1992
+ declare interface IAiImageGenerationOptions {
1993
+ /**
1994
+ * Image dimensions for OpenAI models (mapped to `size` field).
1995
+ * For xAI or Gemini Flash aspect ratio, use the corresponding `models` family block.
1996
+ */
1997
+ readonly size?: AiImageSize;
1998
+ /** Number of images. Default 1. Some models enforce a maximum. */
1999
+ readonly count?: number;
2000
+ /**
2001
+ * Quality tier. Accepted values differ per model:
2002
+ * - gpt-image-1: 'low' | 'medium' | 'high' | 'auto'
2003
+ * Other models ignore this field.
2004
+ */
2005
+ readonly quality?: AiImageQuality;
2006
+ /** Reproducibility seed, where supported. */
2007
+ readonly seed?: number;
2008
+ /**
2009
+ * Optional precision via model-family-scoped blocks. The resolver picks
2010
+ * applicable blocks dynamically based on the resolved model.
2011
+ */
2012
+ readonly models?: ReadonlyArray<IModelFamilyConfig>;
2013
+ }
2014
+
2015
+ /**
2016
+ * Parameters for an image-generation request.
2017
+ * @public
2018
+ */
2019
+ declare interface IAiImageGenerationParams {
2020
+ /** The text prompt describing the desired image. */
2021
+ readonly prompt: string;
2022
+ /** Optional generation options. */
2023
+ readonly options?: IAiImageGenerationOptions;
2024
+ /**
2025
+ * Optional reference images. When present, the provider will use them as
2026
+ * visual context (e.g. to preserve a character's appearance across multiple
2027
+ * generations). The dispatcher resolves the
2028
+ * {@link AiAssist.IAiImageModelCapability} for the requested model and
2029
+ * rejects the call up front if `acceptsImageReferenceInput` is not set on
2030
+ * the matching capability. An empty array is treated identically to
2031
+ * `undefined`.
2032
+ */
2033
+ readonly referenceImages?: ReadonlyArray<IAiImageAttachment>;
2034
+ }
2035
+
2036
+ /**
2037
+ * Result of an image-generation call.
2038
+ * @public
2039
+ */
2040
+ declare interface IAiImageGenerationResponse {
2041
+ /** The generated images, in provider-returned order. */
2042
+ readonly images: ReadonlyArray<IAiGeneratedImage>;
2043
+ }
2044
+
2045
+ /**
2046
+ * Image-generation capability for a model family within a provider. Used as
2047
+ * an entry in {@link IAiProviderDescriptor.imageGeneration}.
2048
+ *
2049
+ * @public
2050
+ */
2051
+ declare interface IAiImageModelCapability {
2052
+ /**
2053
+ * Prefix matched against the resolved image model id. The empty string is
2054
+ * the catch-all and matches every model. When multiple rules' prefixes
2055
+ * match a model id, the longest prefix wins; ties are broken by
2056
+ * first-encountered.
2057
+ */
2058
+ readonly modelPrefix: string;
2059
+ /** API format used to dispatch requests for matching models. */
2060
+ readonly format: AiImageApiFormat;
2061
+ /**
2062
+ * Whether matching models accept reference images via
2063
+ * {@link AiAssist.IAiImageGenerationParams.referenceImages}. When false or
2064
+ * undefined, calls that include reference images are rejected up front.
2065
+ */
2066
+ readonly acceptsImageReferenceInput?: boolean;
2067
+ /** Accepted size strings. When present, dispatcher pre-validates. */
2068
+ readonly acceptedSizes?: ReadonlyArray<string>;
2069
+ /** When true, quality param is sent. When false/undefined, don't send quality. */
2070
+ readonly supportsQualityParam?: boolean;
2071
+ /** Accepted quality values when supportsQualityParam is true. */
2072
+ readonly acceptedQualities?: ReadonlyArray<string>;
2073
+ /** Maximum count (n). When present, dispatcher pre-validates. */
2074
+ readonly maxCount?: number;
2075
+ /**
2076
+ * How to encode the output format on the wire:
2077
+ * - 'response-format': send response_format: 'b64_json' (openai-images catch-all)
2078
+ * - 'output-format': send output_format (gpt-image-1)
2079
+ * - 'none': send neither (Gemini Flash)
2080
+ */
2081
+ readonly outputParamStyle?: 'response-format' | 'output-format' | 'none';
2082
+ /** Default MIME type for response images. */
2083
+ readonly defaultOutputMimeType?: string;
2084
+ }
2085
+
2086
+ /**
2087
+ * Configuration that maps model id patterns to capabilities. Used to
2088
+ * augment (or, where the provider supplies no capability info, fully
2089
+ * derive) the capability set for each listed model.
2090
+ * @public
2091
+ */
2092
+ declare interface IAiModelCapabilityConfig {
2093
+ /** Per-provider rules. Tried before {@link AiAssist.IAiModelCapabilityConfig.global}. */
2094
+ readonly perProvider?: {
2095
+ readonly [P in AiProviderId]?: ReadonlyArray<IAiModelCapabilityRule>;
2096
+ };
2097
+ /** Cross-provider fallback rules. */
2098
+ readonly global?: ReadonlyArray<IAiModelCapabilityRule>;
2099
+ }
2100
+
2101
+ /**
2102
+ * One rule in an {@link IAiModelCapabilityConfig}. Multiple rules can match
2103
+ * a single model — their capability arrays are unioned.
2104
+ * @public
2105
+ */
2106
+ declare interface IAiModelCapabilityRule {
2107
+ /** RegExp tested against the model id (using `.test`). */
2108
+ readonly idPattern: RegExp;
2109
+ /** Capabilities this rule attributes to matching models. */
2110
+ readonly capabilities: ReadonlyArray<AiModelCapability>;
2111
+ /**
2112
+ * Friendly display-name override for matching models. The function form
2113
+ * lets one rule format many ids (e.g. `(id) => id.toUpperCase()`).
2114
+ * If multiple matching rules supply `displayName`, the first match wins.
2115
+ */
2116
+ readonly displayName?: string | ((id: string) => string);
2117
+ }
2118
+
2119
+ /**
2120
+ * Information about a single model returned by a provider's list endpoint,
2121
+ * with capabilities already resolved (native + config rules).
2122
+ * @public
2123
+ */
2124
+ declare interface IAiModelInfo {
2125
+ /** Provider-native model identifier. */
2126
+ readonly id: string;
2127
+ /** Resolved capability set — union of native declarations and config rules. */
2128
+ readonly capabilities: ReadonlySet<AiModelCapability>;
2129
+ /** Friendly name for display, when known. */
2130
+ readonly displayName?: string;
2131
+ }
2132
+
765
2133
  /**
766
2134
  * Describes a single AI provider — single source of truth for all metadata.
767
2135
  * @public
@@ -781,10 +2149,264 @@ declare interface IAiProviderDescriptor {
781
2149
  readonly baseUrl: string;
782
2150
  /** Default model specification — string or context-aware map. */
783
2151
  readonly defaultModel: ModelSpec;
2152
+ /**
2153
+ * Canonical fgv alias → concrete model map for this provider. Absent means the
2154
+ * provider defines no aliases and every model string passes through verbatim.
2155
+ *
2156
+ * @remarks
2157
+ * Keys are full fgv aliases (`@<providerId>:<role>`); values are the current
2158
+ * concrete model id (or a provider-native alias). Consulted by
2159
+ * {@link resolveModelAlias} / {@link resolveProviderModel} at each call-time
2160
+ * resolution chokepoint, downstream of the {@link ModelSpecKey} walk. Additive
2161
+ * and optional — composes with the existing per-descriptor `imageGeneration` /
2162
+ * `embedding` capability arrays.
2163
+ */
2164
+ readonly aliases?: IModelAliasMap;
784
2165
  /** Which server-side tools this provider supports (empty = none). */
785
2166
  readonly supportedTools: ReadonlyArray<AiServerToolType>;
786
2167
  /** Whether this provider's API enforces CORS restrictions that prevent direct browser calls. */
787
2168
  readonly corsRestricted: boolean;
2169
+ /**
2170
+ * Whether this provider's streaming completion endpoint requires a proxy
2171
+ * for direct browser calls. Some providers gate streaming separately from
2172
+ * non-streaming (rare), so this is tracked independently from
2173
+ * {@link IAiProviderDescriptor.corsRestricted}.
2174
+ *
2175
+ * @remarks
2176
+ * When `true`, `callProviderCompletionStream` rejects up front unless the
2177
+ * call is being routed through a proxy.
2178
+ */
2179
+ readonly streamingCorsRestricted: boolean;
2180
+ /**
2181
+ * Whether this provider's chat completions API accepts image input
2182
+ * (i.e. supports vision prompts). When false, calls with
2183
+ * `prompt.attachments` are rejected up front.
2184
+ */
2185
+ readonly acceptsImageInput: boolean;
2186
+ /**
2187
+ * Whether this provider supports thinking/reasoning mode.
2188
+ * - 'optional': thinking can be enabled but is not required
2189
+ * - 'required': thinking is always active (e.g. o-series models)
2190
+ * - 'unsupported': thinking is not supported
2191
+ */
2192
+ readonly thinkingMode: AiThinkingMode;
2193
+ /**
2194
+ * Image-generation capabilities, scoped to model id prefixes. Empty or
2195
+ * undefined means the provider does not support image generation.
2196
+ *
2197
+ * @remarks
2198
+ * The dispatcher matches the resolved model id against each rule's
2199
+ * `modelPrefix` and selects the longest match (see
2200
+ * {@link AiAssist.resolveImageCapability}). An empty `modelPrefix` is the
2201
+ * catch-all and matches every model id.
2202
+ *
2203
+ * Multiple entries support providers that host more than one image-API
2204
+ * surface under one baseUrl. The dispatcher selects the longest-matching
2205
+ * prefix, so a provider can list a specific-prefix surface alongside an
2206
+ * empty-prefix catch-all and the right model routes to the right API.
2207
+ *
2208
+ * Image-model selection reuses the existing `image` {@link ModelSpecKey}.
2209
+ * Providers that declare `imageGeneration` should declare a model in
2210
+ * `defaultModel.image`, e.g. `{ base: '@openai:mini', image: '@openai:image' }`.
2211
+ */
2212
+ readonly imageGeneration?: ReadonlyArray<IAiImageModelCapability>;
2213
+ /**
2214
+ * Embedding capabilities, scoped to model id prefixes. Empty or undefined
2215
+ * means the provider does not support embeddings.
2216
+ *
2217
+ * @remarks
2218
+ * The dispatcher matches the resolved embedding model id against each rule's
2219
+ * `modelPrefix` and selects the longest match (see
2220
+ * {@link AiAssist.resolveEmbeddingCapability}). An empty `modelPrefix` is the
2221
+ * catch-all and matches every model id.
2222
+ *
2223
+ * Embedding-model selection uses the `embedding` {@link ModelSpecKey}.
2224
+ * Providers that declare `embedding` should declare a model in
2225
+ * `defaultModel.embedding`, e.g. `{ base: '@openai:mini', embedding: '@openai:embedding' }`.
2226
+ * Self-hosted providers (`ollama`, `openai-compat`) leave it unset — the
2227
+ * caller supplies the embedding model via `modelOverride`.
2228
+ */
2229
+ readonly embedding?: ReadonlyArray<IAiEmbeddingModelCapability>;
2230
+ /**
2231
+ * Concrete model ids (prefix-matched) that must be invoked via the OpenAI
2232
+ * Responses API rather than chat completions — e.g. `gpt-5.5-pro`. Non-OpenAI
2233
+ * `apiFormat`s ignore this.
2234
+ *
2235
+ * @remarks
2236
+ * Some current-generation OpenAI models (the `-pro` tier) are Responses-API-only
2237
+ * and 400 on `/chat/completions`. The completion and streaming dispatch consult
2238
+ * this list (via the sibling predicate {@link AiAssist.isResponsesOnlyModel})
2239
+ * and route a matching model to the Responses path
2240
+ * even when no tools are requested. Mirrors the prefix-matching shape of the
2241
+ * `imageGeneration` / `embedding` capability arrays; adding a new Responses-only
2242
+ * line is a one-entry descriptor edit. Empty or undefined means no model is
2243
+ * Responses-only.
2244
+ */
2245
+ readonly responsesOnlyModelPrefixes?: ReadonlyArray<string>;
2246
+ }
2247
+
2248
+ /**
2249
+ * Terminal success event for a streaming completion. Carries the aggregated
2250
+ * full text and truncation status for callers that want both the progressive
2251
+ * UI and the complete result.
2252
+ * @public
2253
+ */
2254
+ declare interface IAiStreamDone {
2255
+ readonly type: 'done';
2256
+ /** Whether the response was truncated due to token limits. */
2257
+ readonly truncated: boolean;
2258
+ /** The full concatenated text from all `text-delta` events. */
2259
+ readonly fullText: string;
2260
+ /**
2261
+ * Provider-reported reason a truncated response was cut short (e.g.
2262
+ * `'max_output_tokens'`, `'content_filter'`), when the provider supplies one.
2263
+ * Currently populated only by the OpenAI / xAI Responses adapter, from the
2264
+ * completed payload's `incomplete_details.reason`. Meaningful only when
2265
+ * `truncated === true`; `undefined` otherwise (and whenever the provider
2266
+ * reports truncation without a reason).
2267
+ */
2268
+ readonly incompleteReason?: string;
2269
+ }
2270
+
2271
+ /**
2272
+ * Terminal failure event for a streaming completion. After this event no
2273
+ * further events are emitted.
2274
+ *
2275
+ * @remarks
2276
+ * Connection-time failures (auth, network, pre-flight CORS rejection) are
2277
+ * surfaced via the outer `Result.fail` returned by
2278
+ * `callProviderCompletionStream` rather than as an `error` event, so callers
2279
+ * can distinguish "didn't start" from "started but errored mid-stream."
2280
+ *
2281
+ * @public
2282
+ */
2283
+ declare interface IAiStreamError {
2284
+ readonly type: 'error';
2285
+ readonly message: string;
2286
+ }
2287
+
2288
+ /**
2289
+ * Discriminated union of events emitted by a streaming completion.
2290
+ *
2291
+ * @remarks
2292
+ * **Exhaustive-switch consumers must handle all variants.** The three
2293
+ * `client-tool-*` variants were added when client-tool support shipped;
2294
+ * update every exhaustive switch over this union in lockstep.
2295
+ *
2296
+ * @public
2297
+ */
2298
+ declare type IAiStreamEvent = IAiStreamTextDelta | IAiStreamToolEvent | IAiStreamToolUseStart | IAiStreamToolUseDelta | IAiStreamToolUseComplete | IAiStreamDone | IAiStreamError;
2299
+
2300
+ /**
2301
+ * A text-content delta arriving during a streaming completion.
2302
+ * @public
2303
+ */
2304
+ declare interface IAiStreamTextDelta {
2305
+ readonly type: 'text-delta';
2306
+ /** The newly arrived text fragment. */
2307
+ readonly delta: string;
2308
+ }
2309
+
2310
+ /**
2311
+ * A server-side tool progress event arriving during a streaming completion.
2312
+ * Surfaced for providers that emit explicit tool-progress markers (OpenAI
2313
+ * Responses API, Anthropic). Gemini's grounding doesn't emit these.
2314
+ * @public
2315
+ */
2316
+ declare interface IAiStreamToolEvent {
2317
+ readonly type: 'tool-event';
2318
+ /** Which server-side tool this event describes. */
2319
+ readonly toolType: AiServerToolType;
2320
+ /** Tool lifecycle phase. */
2321
+ readonly phase: 'started' | 'completed';
2322
+ /**
2323
+ * Optional provider-specific detail. For web_search this is typically the
2324
+ * search query when available; format varies by provider.
2325
+ */
2326
+ readonly detail?: string;
2327
+ }
2328
+
2329
+ /**
2330
+ * Emitted after a client-defined tool has been executed and the result is ready
2331
+ * to be fed back to the model in the round-trip continuation.
2332
+ * @public
2333
+ */
2334
+ declare interface IAiStreamToolUseComplete {
2335
+ readonly type: 'client-tool-result';
2336
+ /** The name of the client tool that was executed. */
2337
+ readonly toolName: string;
2338
+ /**
2339
+ * Provider-assigned call identifier. Absent for Gemini.
2340
+ */
2341
+ readonly callId?: string;
2342
+ /** The stringified result returned by the tool's execute callback. */
2343
+ readonly result: string;
2344
+ /** Whether the tool execution failed (schema validation failure, execute error, or unknown tool). */
2345
+ readonly isError: boolean;
2346
+ }
2347
+
2348
+ /**
2349
+ * Emitted when a client-defined tool call is complete and its arguments are fully
2350
+ * accumulated. The `args` object is the fully parsed JSON object — no further
2351
+ * streaming deltas follow for this call.
2352
+ * @public
2353
+ */
2354
+ declare interface IAiStreamToolUseDelta {
2355
+ readonly type: 'client-tool-call-done';
2356
+ /** The name of the client tool being called. */
2357
+ readonly toolName: string;
2358
+ /**
2359
+ * Provider-assigned call identifier. Absent for Gemini.
2360
+ */
2361
+ readonly callId?: string;
2362
+ /** The fully accumulated and parsed tool arguments. */
2363
+ readonly args: JsonObject;
2364
+ }
2365
+
2366
+ /**
2367
+ * Emitted when a client-defined tool call begins streaming. Carries the tool name
2368
+ * and optional provider-assigned call ID (Anthropic / OpenAI Responses API; absent
2369
+ * for Gemini which does not assign call IDs).
2370
+ * @public
2371
+ */
2372
+ declare interface IAiStreamToolUseStart {
2373
+ readonly type: 'client-tool-call-start';
2374
+ /** The name of the client tool being called. */
2375
+ readonly toolName: string;
2376
+ /**
2377
+ * Provider-assigned call identifier (Anthropic: `toolu_*`; OpenAI: `call_*`).
2378
+ * Absent for Gemini (correlation by name).
2379
+ */
2380
+ readonly callId?: string;
2381
+ }
2382
+
2383
+ /**
2384
+ * Behavior annotations for a client-defined tool.
2385
+ *
2386
+ * @remarks
2387
+ * These are **host-advisory-only hints** describing a tool's side-effect profile.
2388
+ * They are consumed by the host's tool loop (e.g. a before-execute gate) and are
2389
+ * **never serialized to the model** — the provider wire tool-schemas whitelist
2390
+ * `{name, description, parameters}` and ignore this field.
2391
+ *
2392
+ * Field names mirror MCP's `ToolAnnotations` (`@modelcontextprotocol/sdk`) 1:1 so
2393
+ * an MCP tool's annotations pass through unchanged. Per the MCP spec, all fields
2394
+ * are hints — a host should never make tool-use decisions based on annotations
2395
+ * received from an untrusted server without its own validation.
2396
+ *
2397
+ * @public
2398
+ */
2399
+ declare interface IAiToolAnnotations {
2400
+ /** Optional human-readable display title for the tool. */
2401
+ readonly title?: string;
2402
+ /** Hint: the tool does not modify its environment (read-only). */
2403
+ readonly readOnlyHint?: boolean;
2404
+ /** Hint: the tool may perform destructive updates (only meaningful when not read-only). */
2405
+ readonly destructiveHint?: boolean;
2406
+ /** Hint: repeated calls with the same arguments have no additional effect. */
2407
+ readonly idempotentHint?: boolean;
2408
+ /** Hint: the tool interacts with an open world of external entities. */
2409
+ readonly openWorldHint?: boolean;
788
2410
  }
789
2411
 
790
2412
  /**
@@ -814,11 +2436,111 @@ declare interface IAiWebSearchToolConfig {
814
2436
  /** Optional: max number of searches per request. */
815
2437
  readonly maxUses?: number;
816
2438
  /**
817
- * Optional: enable image understanding during web search.
818
- * When true, the model can view and analyze images found during search.
819
- * Currently supported by xAI only; ignored by other providers.
2439
+ * Optional: enable image understanding during web search.
2440
+ * When true, the model can view and analyze images found during search.
2441
+ * Currently supported by xAI only; ignored by other providers.
2442
+ */
2443
+ readonly enableImageUnderstanding?: boolean;
2444
+ }
2445
+
2446
+ /**
2447
+ * Anthropic-specific thinking configuration.
2448
+ * @public
2449
+ */
2450
+ declare interface IAnthropicThinkingConfig {
2451
+ /**
2452
+ * Anthropic effort level. The emit-site converts to `thinking.budget_tokens`
2453
+ * (the integer budget the Anthropic API requires). Mapping policy: low = 2048,
2454
+ * medium = 8192, high = 24000, max = 32000.
2455
+ * - 'low' | 'medium' | 'high': all thinking-capable models
2456
+ * - 'max': Opus 4.6 only
2457
+ */
2458
+ readonly effort?: 'low' | 'medium' | 'high' | 'max';
2459
+ }
2460
+
2461
+ /**
2462
+ * Anthropic-specific thinking options block.
2463
+ * @public
2464
+ */
2465
+ declare interface IAnthropicThinkingOptions {
2466
+ readonly provider: 'anthropic';
2467
+ readonly models?: ReadonlyArray<AnthropicThinkingModelNames>;
2468
+ readonly config: IAnthropicThinkingConfig;
2469
+ }
2470
+
2471
+ /**
2472
+ * Argon2id key derivation parameters (RFC 9106).
2473
+ * @public
2474
+ */
2475
+ declare interface IArgon2idKeyDerivationParams {
2476
+ /** Key derivation function discriminator. */
2477
+ readonly kdf: 'argon2id';
2478
+ /** Base64-encoded salt used for key derivation. */
2479
+ readonly salt: string;
2480
+ /** Memory cost in kibibytes. */
2481
+ readonly memoryKiB: number;
2482
+ /** Number of passes (time cost). */
2483
+ readonly iterations: number;
2484
+ /** Degree of parallelism. */
2485
+ readonly parallelism: number;
2486
+ }
2487
+
2488
+ /**
2489
+ * Parameters for Argon2id key derivation (RFC 9106).
2490
+ * All fields are required; fgv does not pick defaults silently.
2491
+ * @public
2492
+ */
2493
+ declare interface IArgon2idParams {
2494
+ /**
2495
+ * Memory cost in kibibytes (KiB).
2496
+ * OWASP 2023 minimum: 19456 (19 MiB). Stronger: 65536 (64 MiB).
2497
+ * Constraint: \>= 8.
2498
+ */
2499
+ readonly memoryKiB: number;
2500
+ /**
2501
+ * Number of passes (iterations / time cost).
2502
+ * OWASP 2023 minimum: 2. Range: \>= 1.
2503
+ */
2504
+ readonly iterations: number;
2505
+ /**
2506
+ * Degree of parallelism (threads).
2507
+ * Note: WASM-based implementations compute sequentially regardless of this value,
2508
+ * but the value is wired into the algorithm and AFFECTS the output hash bytes.
2509
+ * Callers must use the same parallelism value consistently for a given secret.
2510
+ * Range: 1–255.
2511
+ */
2512
+ readonly parallelism: number;
2513
+ /**
2514
+ * Number of output bytes (hash length).
2515
+ * Typical values: 16 (128-bit), 32 (256-bit, AES-256 key), 64 (512-bit).
2516
+ * Constraint: \>= 4.
2517
+ */
2518
+ readonly outputBytes: number;
2519
+ }
2520
+
2521
+ /**
2522
+ * Argon2id key derivation provider (RFC 9106).
2523
+ *
2524
+ * Implementations are in separate packages to avoid WASM bundle costs for
2525
+ * consumers who don't need Argon2id:
2526
+ * - Node: `@fgv/ts-extras-argon2` (`NodeArgon2Provider`)
2527
+ * - Browser: `@fgv/ts-web-extras-argon2` (`BrowserArgon2Provider`)
2528
+ *
2529
+ * @public
2530
+ */
2531
+ declare interface IArgon2idProvider {
2532
+ /**
2533
+ * Derives key material from a password using Argon2id (RFC 9106 §3.1).
2534
+ *
2535
+ * Returns the raw derived bytes as a `Uint8Array`. Both Node and browser
2536
+ * implementations produce bit-identical output for identical inputs.
2537
+ *
2538
+ * @param password - Password or passphrase. Accepts string (UTF-8) or raw bytes.
2539
+ * @param salt - Salt bytes. Must be random and unique per credential (\>= 16 bytes recommended).
2540
+ * @param params - Argon2id parameters. Use `ARGON2ID_OWASP_MIN` as a starting point.
2541
+ * @returns Success with derived bytes, Failure with error context.
820
2542
  */
821
- readonly enableImageUnderstanding?: boolean;
2543
+ argon2id(password: Uint8Array | string, salt: Uint8Array, params: IArgon2idParams): Promise<Result<Uint8Array>>;
822
2544
  }
823
2545
 
824
2546
  /**
@@ -830,6 +2552,41 @@ declare interface IChatMessage {
830
2552
  readonly role: 'system' | 'user' | 'assistant';
831
2553
  /** Message content */
832
2554
  readonly content: string;
2555
+ /**
2556
+ * Optional image attachments. Only honoured on the **current turn** (the last
2557
+ * message of an {@link AiAssist.IChatRequest}); vision-capable providers include
2558
+ * them in that user message, non-vision providers reject the call up front (see
2559
+ * {@link AiAssist.IAiProviderDescriptor.acceptsImageInput}). Attachments on
2560
+ * history (non-final) messages are ignored.
2561
+ */
2562
+ readonly attachments?: ReadonlyArray<IAiImageAttachment>;
2563
+ }
2564
+
2565
+ /**
2566
+ * An ordered chat request: optional system instructions plus the conversation
2567
+ * turns. The **last** entry in `messages` is the current turn (always a `user`
2568
+ * turn); everything before it is prior conversation history.
2569
+ *
2570
+ * @remarks
2571
+ * This is the unified shape accepted by every turn entry point. Both the
2572
+ * completion path and the client-tool turn path linearize it identically:
2573
+ * `[system, ...history, current user turn, ...continuation]`. Keeping `system`
2574
+ * as a distinct field (rather than a `system`-role message) matches how the
2575
+ * per-provider request builders already separate system from the turn list
2576
+ * (Anthropic top-level `system`, Gemini `systemInstruction`, OpenAI a leading
2577
+ * `system`-role message). `messages` should therefore carry only `user` /
2578
+ * `assistant` turns.
2579
+ *
2580
+ * @public
2581
+ */
2582
+ declare interface IChatRequest {
2583
+ /** System instructions (schema docs, format rules, general guidance). */
2584
+ readonly system?: string;
2585
+ /**
2586
+ * The ordered conversation turns. Must be non-empty; the last entry is the
2587
+ * current `user` turn and the preceding entries are history.
2588
+ */
2589
+ readonly messages: ReadonlyArray<IChatMessage>;
833
2590
  }
834
2591
 
835
2592
  /**
@@ -937,12 +2694,27 @@ declare interface ICryptoProvider {
937
2694
  * @returns Success with derived 32-byte key, or Failure with error
938
2695
  */
939
2696
  deriveKey(password: string, salt: Uint8Array, iterations: number): Promise<Result<Uint8Array>>;
2697
+ /**
2698
+ * Computes a SHA-256 hash of the given data.
2699
+ * @param data - UTF-8 string to hash
2700
+ * @returns Success with hex-encoded hash string, or Failure with error
2701
+ */
2702
+ sha256(data: string): Promise<Result<string>>;
940
2703
  /**
941
2704
  * Generates cryptographically secure random bytes.
942
2705
  * @param length - Number of bytes to generate
943
2706
  * @returns Success with random bytes, or Failure with error
944
2707
  */
945
2708
  generateRandomBytes(length: number): Result<Uint8Array>;
2709
+ /**
2710
+ * Generates a cryptographically random UUIDv4 using the provider's
2711
+ * underlying source of randomness. The default Node and browser
2712
+ * implementations delegate to `globalThis.crypto.randomUUID`;
2713
+ * deterministic providers (e.g. test stubs) may override to produce
2714
+ * reproducible values.
2715
+ * @returns Success with a canonical UUID, or Failure with error.
2716
+ */
2717
+ generateUuid(): Result<Uuid>;
946
2718
  /**
947
2719
  * Encodes binary data to base64 string.
948
2720
  * @param data - Binary data to encode
@@ -955,6 +2727,161 @@ declare interface ICryptoProvider {
955
2727
  * @returns Success with decoded bytes, or Failure if invalid base64
956
2728
  */
957
2729
  fromBase64(base64: string): Result<Uint8Array>;
2730
+ /**
2731
+ * Generates a new asymmetric keypair for the requested algorithm.
2732
+ * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm | algorithm} to use.
2733
+ * @param extractable - Whether the resulting `CryptoKey` objects may be exported.
2734
+ * Set `false` on backends that store `CryptoKey` references directly (e.g.
2735
+ * IndexedDB). Set `true` when the private key must round-trip through JWK or
2736
+ * PKCS#8 (e.g. encrypted-file backends).
2737
+ * @returns Success with the generated `CryptoKeyPair`, or Failure with error context.
2738
+ */
2739
+ generateKeyPair(algorithm: KeyPairAlgorithm, extractable: boolean): Promise<Result<CryptoKeyPair>>;
2740
+ /**
2741
+ * Exports the public half of a keypair as a JSON Web Key.
2742
+ * @param publicKey - The public `CryptoKey` to export. Must be an `extractable`
2743
+ * key generated for an asymmetric algorithm.
2744
+ * @returns Success with the JWK, or Failure with error context.
2745
+ */
2746
+ exportPublicKeyJwk(publicKey: CryptoKey): Promise<Result<JsonWebKey>>;
2747
+ /**
2748
+ * Re-imports a public-key JWK as a `CryptoKey` usable for verification or
2749
+ * encryption (depending on algorithm).
2750
+ * @param jwk - The JSON Web Key produced by {@link CryptoUtils.ICryptoProvider.exportPublicKeyJwk | exportPublicKeyJwk}.
2751
+ * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm | algorithm} the
2752
+ * key was generated for. Determines the import parameters and key usages.
2753
+ * @returns Success with the imported public `CryptoKey`, or Failure with error context.
2754
+ */
2755
+ importPublicKeyJwk(jwk: JsonWebKey, algorithm: KeyPairAlgorithm): Promise<Result<CryptoKey>>;
2756
+ /**
2757
+ * Exports a public `CryptoKey` as a DER-encoded SPKI (SubjectPublicKeyInfo) blob.
2758
+ * SPKI is the standard algorithm-agnostic format for public key storage and transport.
2759
+ * @param publicKey - The `CryptoKey` to export. Must have `key.type === 'public'`.
2760
+ * @returns `Success` with the raw SPKI bytes, or `Failure` with error context.
2761
+ */
2762
+ exportPublicKeySpki(publicKey: CryptoKey): Promise<Result<Uint8Array>>;
2763
+ /**
2764
+ * Imports a public key from a DER-encoded SPKI blob.
2765
+ * @param spkiBytes - The raw SPKI bytes produced by {@link CryptoUtils.ICryptoProvider.exportPublicKeySpki | exportPublicKeySpki}.
2766
+ * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm | algorithm} the key was generated for.
2767
+ * @returns `Success` with the imported public `CryptoKey`, or `Failure` with error context.
2768
+ */
2769
+ importPublicKeySpki(spkiBytes: Uint8Array, algorithm: KeyPairAlgorithm): Promise<Result<CryptoKey>>;
2770
+ /**
2771
+ * Wraps `plaintext` for delivery to the holder of the private key paired
2772
+ * with `recipientPublicKey`. Uses ECIES with ECDH P-256, HKDF-SHA256, and
2773
+ * AES-GCM-256.
2774
+ *
2775
+ * Generates a fresh ephemeral keypair per call; the ephemeral private key
2776
+ * is discarded after the shared-secret derive. Only the recipient (with the
2777
+ * matching private key) and the same HKDF parameters can recover
2778
+ * `plaintext`.
2779
+ *
2780
+ * Empty `plaintext` is permitted; the resulting wrap contains only the
2781
+ * 16-byte GCM authentication tag and round-trips back to an empty
2782
+ * `Uint8Array`.
2783
+ * @param plaintext - The bytes to wrap. Any length supported by AES-GCM
2784
+ * (in practice, well below 2^39 - 256 bits).
2785
+ * @param recipientPublicKey - The recipient's ECDH P-256 public `CryptoKey`.
2786
+ * Must have algorithm name `'ECDH'` and named curve `'P-256'`; mismatched
2787
+ * algorithm or curve yields a `Failure` with error context.
2788
+ * @param options - HKDF parameters; see {@link CryptoUtils.IWrapBytesOptions | IWrapBytesOptions}.
2789
+ * @returns `Success` with the wrapped payload, or `Failure` with error context.
2790
+ */
2791
+ wrapBytes(plaintext: Uint8Array, recipientPublicKey: CryptoKey, options: IWrapBytesOptions): Promise<Result<IWrappedBytes>>;
2792
+ /**
2793
+ * Inverse of {@link CryptoUtils.ICryptoProvider.wrapBytes | wrapBytes}.
2794
+ * Recovers the original `plaintext` from a wrapped payload using the
2795
+ * recipient's private key.
2796
+ *
2797
+ * Returns a `Failure` (never throws) on any of:
2798
+ * - Tampered nonce or ciphertext (AES-GCM authentication fails)
2799
+ * - Wrong private key (different shared secret derives a different wrap key)
2800
+ * - Wrong HKDF parameters (different wrap key)
2801
+ * - Malformed `ephemeralPublicKey` JWK
2802
+ * - Malformed base64 in `nonce` or `ciphertext`
2803
+ * @param wrapped - The wrapped payload produced by `wrapBytes`.
2804
+ * @param recipientPrivateKey - The recipient's ECDH P-256 private
2805
+ * `CryptoKey`. Must have algorithm name `'ECDH'` and named curve `'P-256'`,
2806
+ * and key usages including `'deriveKey'` or `'deriveBits'`.
2807
+ * @param options - The same HKDF parameters used at wrap time.
2808
+ * @returns `Success` with the original `plaintext`, or `Failure` with error context.
2809
+ */
2810
+ unwrapBytes(wrapped: IWrappedBytes, recipientPrivateKey: CryptoKey, options: IWrapBytesOptions): Promise<Result<Uint8Array>>;
2811
+ /**
2812
+ * Signs `data` with `privateKey` using the algorithm inferred from the key.
2813
+ * Delegates to `crypto.subtle.sign`; the algorithm is derived from
2814
+ * `privateKey.algorithm.name` — ECDSA keys are augmented with
2815
+ * `hash: 'SHA-256'` at sign time (the hash is not stored in the key);
2816
+ * all other algorithm names are passed through as-is.
2817
+ * Intended for Ed25519 and ECDSA-P256 asymmetric private keys; for
2818
+ * HMAC-SHA256 authentication codes use {@link ICryptoProvider.hmacSha256} instead.
2819
+ * @param privateKey - A `CryptoKey` with `'sign'` usage (e.g. generated by
2820
+ * {@link CryptoUtils.ICryptoProvider.generateKeyPair | generateKeyPair} with
2821
+ * `'ecdsa-p256'` or `'ed25519'`).
2822
+ * @param data - The bytes to sign.
2823
+ * @returns `Success` with the raw signature bytes, or `Failure` with error context.
2824
+ */
2825
+ sign(privateKey: CryptoKey, data: Uint8Array): Promise<Result<Uint8Array>>;
2826
+ /**
2827
+ * Verifies a signature produced by {@link ICryptoProvider.sign}.
2828
+ * Delegates to `crypto.subtle.verify`; the algorithm is derived from
2829
+ * `publicKey.algorithm.name` — ECDSA keys are augmented with
2830
+ * `hash: 'SHA-256'`; all other algorithm names are passed through as-is.
2831
+ * Intended for Ed25519 and ECDSA-P256 asymmetric public keys; for
2832
+ * HMAC-SHA256 verification use {@link ICryptoProvider.verifyHmacSha256} instead.
2833
+ * @param publicKey - A `CryptoKey` with `'verify'` usage (e.g. the public
2834
+ * half of a keypair generated by
2835
+ * {@link CryptoUtils.ICryptoProvider.generateKeyPair | generateKeyPair} with
2836
+ * `'ecdsa-p256'` or `'ed25519'`).
2837
+ * @param signature - The raw signature bytes produced by `sign`.
2838
+ * @param data - The original data that was signed.
2839
+ * @returns `Success` with `true` if the signature is valid, `false` if it is
2840
+ * not, or `Failure` with error context if the operation itself failed.
2841
+ */
2842
+ verify(publicKey: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<Result<boolean>>;
2843
+ /**
2844
+ * Compares two byte arrays in constant time.
2845
+ *
2846
+ * The comparison visits all bytes of `a` and `b` regardless of where they
2847
+ * diverge, accumulating XOR differences with bitwise-OR. No early-return is
2848
+ * possible once the length check passes, making timing independent of the
2849
+ * byte values. This prevents timing side-channels when comparing MAC outputs,
2850
+ * signed-token bytes, or any secret-derived byte sequences.
2851
+ *
2852
+ * Returns `false` immediately (before the loop) when `a.length !== b.length`;
2853
+ * the length mismatch itself is not secret in normal use.
2854
+ * @param a - First byte array.
2855
+ * @param b - Second byte array.
2856
+ * @returns `true` if the arrays have the same length and identical contents,
2857
+ * `false` otherwise.
2858
+ */
2859
+ timingSafeEqual(a: Uint8Array, b: Uint8Array): boolean;
2860
+ /**
2861
+ * Computes an HMAC-SHA256 authentication code for `data` using `key`.
2862
+ *
2863
+ * The key must be a `CryptoKey` with `'sign'` usage and algorithm name
2864
+ * `'HMAC'` (e.g. derived via PBKDF2 or imported with
2865
+ * `crypto.subtle.importKey`). Use {@link ICryptoProvider.verifyHmacSha256}
2866
+ * for constant-time verification of the output.
2867
+ * @param key - An HMAC `CryptoKey` with `'sign'` usage.
2868
+ * @param data - The bytes to authenticate.
2869
+ * @returns `Success` with the 32-byte MAC, or `Failure` with error context.
2870
+ */
2871
+ hmacSha256(key: CryptoKey, data: Uint8Array): Promise<Result<Uint8Array>>;
2872
+ /**
2873
+ * Verifies an HMAC-SHA256 authentication code in constant time.
2874
+ *
2875
+ * Computes the expected MAC over `data` with `key`, then compares it to
2876
+ * `signature` using {@link ICryptoProvider.timingSafeEqual} so that
2877
+ * mismatches do not leak information through timing.
2878
+ * @param key - An HMAC `CryptoKey` with `'sign'` usage.
2879
+ * @param signature - The MAC bytes to verify (typically 32 bytes).
2880
+ * @param data - The original data that was authenticated.
2881
+ * @returns `Success` with `true` if the MAC is valid, `false` if it is not,
2882
+ * or `Failure` with error context if the MAC computation itself failed.
2883
+ */
2884
+ verifyHmacSha256(key: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<Result<boolean>>;
958
2885
  }
959
2886
 
960
2887
  /**
@@ -1021,6 +2948,42 @@ declare interface IEncryptedFile<TMetadata = JsonValue> {
1021
2948
  readonly keyDerivation?: IKeyDerivationParams;
1022
2949
  }
1023
2950
 
2951
+ /**
2952
+ * Parameters for {@link CryptoUtils.KeyStore.EncryptedFilePrivateKeyStorage.create}.
2953
+ * @public
2954
+ */
2955
+ declare interface IEncryptedFilePrivateKeyStorageCreateParams {
2956
+ /**
2957
+ * Filesystem path to the directory that holds the encrypted private-key
2958
+ * files. Used only when {@link CryptoUtils.KeyStore.IEncryptedFilePrivateKeyStorageCreateParams.tree}
2959
+ * is omitted (the default `FsTree` backing). The directory must already
2960
+ * exist.
2961
+ */
2962
+ readonly directory: string;
2963
+ /**
2964
+ * Raw AES-256-GCM key (32 bytes) used to encrypt each file's JWK content.
2965
+ * Consumer-supplied and decoupled from the keystore's password lifecycle —
2966
+ * derive it however the application sees fit (typically the same
2967
+ * password-derived key material the keystore vault uses).
2968
+ */
2969
+ readonly encryptionKey: Uint8Array;
2970
+ /**
2971
+ * {@link CryptoUtils.ICryptoProvider | Crypto provider} used for the
2972
+ * AES-256-GCM encrypt/decrypt of each file's contents.
2973
+ */
2974
+ readonly cryptoProvider: ICryptoProvider;
2975
+ /**
2976
+ * Optional {@link FileTree.IFileTreeDirectoryItem | FileTree directory}
2977
+ * override. When supplied it is used as the storage directory directly and
2978
+ * {@link CryptoUtils.KeyStore.IEncryptedFilePrivateKeyStorageCreateParams.directory} is ignored —
2979
+ * pass an in-memory tree for tests, or another Node-compatible backend. When
2980
+ * omitted, a mutable `FsTree` rooted at `directory` is used. (This backend is
2981
+ * Node-only — it round-trips keys through `node:crypto` — so a browser file
2982
+ * tree is not a supported target.)
2983
+ */
2984
+ readonly tree?: FileTree.IFileTreeDirectoryItem;
2985
+ }
2986
+
1024
2987
  /**
1025
2988
  * Configuration for encrypted file handling during loading.
1026
2989
  * @public
@@ -1093,6 +3056,313 @@ declare interface IEncryptionResult {
1093
3056
  readonly encryptedData: Uint8Array;
1094
3057
  }
1095
3058
 
3059
+ /**
3060
+ * Parameters for {@link AiAssist.executeClientToolTurn}.
3061
+ *
3062
+ * @remarks
3063
+ * Carries the unified {@link AiAssist.IChatRequest} shape (`system?` + ordered
3064
+ * `messages`): the last message is the current user turn and the preceding
3065
+ * messages are history, linearized before the current turn — identically to the
3066
+ * completion and streaming paths. {@link IExecuteClientToolTurnParams.continuationMessages}
3067
+ * remains a distinct post-current-turn axis (see below).
3068
+ *
3069
+ * @public
3070
+ */
3071
+ declare interface IExecuteClientToolTurnParams extends IChatRequest {
3072
+ /** The provider descriptor for routing (Anthropic / OpenAI / Gemini). */
3073
+ readonly descriptor: IAiProviderDescriptor;
3074
+ /** API key for authentication. */
3075
+ readonly apiKey: string;
3076
+ /**
3077
+ * The cumulative provider-native wire tail from the previous turn's
3078
+ * {@link AiAssist.IAiClientToolContinuation.messages}. Supply this as-is
3079
+ * each round — `messages` is already cumulative, so **replace** rather
3080
+ * than manually concatenate:
3081
+ *
3082
+ * ```ts
3083
+ * tail = outcome.continuation.messages; // replace — already cumulative
3084
+ * ```
3085
+ *
3086
+ * On the first turn this should be `undefined` (or omitted).
3087
+ *
3088
+ * Each provider applies its own shape guard to the supplied wire objects:
3089
+ * - Anthropic: projects each entry to `{ role, content }` (sufficient for
3090
+ * thinking blocks and `tool_result` arrays).
3091
+ * - OpenAI / xAI Responses: passes each item verbatim (`function_call` /
3092
+ * `function_call_output` items carry distinct fields per `type`); only
3093
+ * guards that each entry is a JSON object.
3094
+ * - Gemini: projects each entry to `{ role, parts }`.
3095
+ *
3096
+ * Entries that fail their provider's shape check are silently skipped.
3097
+ * Do NOT place these objects in the `messages` parameter — the
3098
+ * normalized-message path strips provider-native fields.
3099
+ */
3100
+ readonly continuationMessages?: ReadonlyArray<JsonObject>;
3101
+ /**
3102
+ * Sampling temperature. Sent to the provider only when explicitly provided; omitted otherwise
3103
+ * so the provider's own default applies (current-gen models reject a caller-supplied default).
3104
+ */
3105
+ readonly temperature?: number;
3106
+ /** Server-side tools to include. */
3107
+ readonly tools?: ReadonlyArray<AiServerToolConfig>;
3108
+ /** Client-defined tools available for the model to call. */
3109
+ readonly clientTools: ReadonlyArray<IAiClientTool>;
3110
+ /** Optional abort signal. */
3111
+ readonly signal?: AbortSignal;
3112
+ /**
3113
+ * Optional override of the descriptor's default base URL. Same semantics as
3114
+ * the non-streaming completion path and `callProviderCompletionStream`: a
3115
+ * well-formed `http`/`https` URL is substituted for `descriptor.baseUrl`
3116
+ * when composing the per-format request, with the per-format suffix appended
3117
+ * unchanged. Validated at the dispatcher; auth shape is unaffected. Use this
3118
+ * to point a client-tool turn at a local / LAN OpenAI-compatible server
3119
+ * (Ollama, LM Studio, llama.cpp).
3120
+ */
3121
+ readonly endpoint?: string;
3122
+ /** Optional logger for diagnostics. */
3123
+ readonly logger?: Logging.ILogger;
3124
+ /** Optional resolved thinking config (pre-resolved by the caller). */
3125
+ readonly resolvedThinking?: IResolvedThinkingConfig;
3126
+ /** Resolved model string (pre-resolved by the caller). When omitted, uses the descriptor's default model. */
3127
+ readonly model?: string;
3128
+ /**
3129
+ * Optional host gate invoked for each client-tool call **after** the model's raw
3130
+ * args have been validated against the tool's `parametersSchema` and **before**
3131
+ * `tool.execute(...)` runs. The full `tool` (including `tool.config.annotations`)
3132
+ * and the validated `args` are passed so gate logic can key off a tool's behavior
3133
+ * annotations (e.g. deny a `destructiveHint` call pending confirmation).
3134
+ *
3135
+ * Returning `{ action: 'proceed' }` (or omitting the callback) runs `execute`
3136
+ * normally. Returning `{ action: 'deny', reason }` skips `execute` and synthesizes
3137
+ * a denial tool-result carrying `reason` into the continuation (the model sees the
3138
+ * denial and can react); **the turn continues**. A callback that returns `Result.fail`
3139
+ * or rejects is a hard error that **terminates the turn** (fails `nextTurn` + emits an
3140
+ * inline `error` event) — distinct from a `tool.execute` failure, which continues the
3141
+ * turn with an `isError` result. A deny must therefore be explicit.
3142
+ */
3143
+ readonly onBeforeToolExecute?: (tool: IAiClientTool, args: unknown) => Promise<Result<IToolExecutionDecision>>;
3144
+ }
3145
+
3146
+ /**
3147
+ * Return value of {@link AiAssist.executeClientToolTurn}.
3148
+ * @public
3149
+ */
3150
+ declare interface IExecuteClientToolTurnResult {
3151
+ /**
3152
+ * The unified-event iterable. Callers iterate this to drive the streaming UI.
3153
+ * The iterable forwards `text-delta`, `tool-event`, `client-tool-call-start`,
3154
+ * `client-tool-call-done`, and `client-tool-result` events through.
3155
+ */
3156
+ readonly events: AsyncIterable<IAiStreamEvent>;
3157
+ /**
3158
+ * Resolves when the stream terminates. On success, carries the
3159
+ * {@link AiAssist.IAiClientToolTurnResult} with the optional continuation for the
3160
+ * next round. On failure, carries the error message.
3161
+ */
3162
+ readonly nextTurn: Promise<Result<IAiClientToolTurnResult>>;
3163
+ }
3164
+
3165
+ /**
3166
+ * Options shared by every {@link AiAssist.fencedStringifiedJson} call.
3167
+ * @public
3168
+ */
3169
+ declare interface IFencedStringifiedJsonExtractorOptions {
3170
+ /**
3171
+ * Optional pre-parse extractor. Defaults to {@link AiAssist.extractJsonText}.
3172
+ * Provide a custom extractor to handle response shapes the default does not
3173
+ * understand.
3174
+ */
3175
+ readonly extractor?: JsonTextExtractor;
3176
+ }
3177
+
3178
+ /**
3179
+ * Options for the validating overload of {@link AiAssist.fencedStringifiedJson}.
3180
+ * `inner` is required so the typed `Converter<T>` return value can never lie
3181
+ * about the runtime shape.
3182
+ * @public
3183
+ */
3184
+ declare interface IFencedStringifiedJsonOptions<T> extends IFencedStringifiedJsonExtractorOptions {
3185
+ /** Inner converter or validator applied to the parsed JSON value. */
3186
+ readonly inner: Converter<T> | Validator<T>;
3187
+ }
3188
+
3189
+ /**
3190
+ * Provider-specific config for Gemini Flash Image.
3191
+ * @public
3192
+ */
3193
+ declare interface IGeminiFlashImageGenerationConfig {
3194
+ /** Aspect ratio string. */
3195
+ readonly aspectRatio?: string;
3196
+ }
3197
+
3198
+ /**
3199
+ * Options block scoped to Gemini Flash Image models.
3200
+ * @public
3201
+ */
3202
+ declare interface IGeminiFlashImageModelOptions extends INamedModelFamilyConfig {
3203
+ readonly provider: 'google';
3204
+ readonly family: 'gemini-flash-image';
3205
+ readonly models?: GeminiFlashImageModelNames[];
3206
+ readonly config: IGeminiFlashImageGenerationConfig;
3207
+ }
3208
+
3209
+ /**
3210
+ * Google Gemini-specific thinking configuration.
3211
+ * @public
3212
+ */
3213
+ declare interface IGeminiThinkingConfig {
3214
+ /**
3215
+ * Token budget for thinking. Maps 1:1 to `thinkingBudget` on the wire.
3216
+ * - 0: disable thinking (Flash and Flash-Lite only; error on Pro)
3217
+ * - positive integer: soft token cap
3218
+ * - -1: dynamic
3219
+ * - omitted: model default
3220
+ */
3221
+ readonly thinkingBudget?: number;
3222
+ /**
3223
+ * Whether to include thought summaries in the response.
3224
+ * @remarks
3225
+ * INERT in phase B. Adapters never send `includeThoughts: true`.
3226
+ * Wired up by the followup stream `ai-assist-thinking-events`.
3227
+ */
3228
+ readonly includeThoughts?: boolean;
3229
+ }
3230
+
3231
+ /**
3232
+ * Google Gemini-specific thinking options block.
3233
+ * @public
3234
+ */
3235
+ declare interface IGeminiThinkingOptions {
3236
+ readonly provider: 'google';
3237
+ readonly models?: ReadonlyArray<GeminiThinkingModelNames>;
3238
+ readonly config: IGeminiThinkingConfig;
3239
+ }
3240
+
3241
+ /**
3242
+ * Parameters for {@link AiAssist.generateJsonCompletion}. Extends
3243
+ * {@link AiAssist.IProviderCompletionParams} with JSON-validation knobs.
3244
+ * @public
3245
+ */
3246
+ declare interface IGenerateJsonCompletionParams<T> extends IProviderCompletionParams {
3247
+ /**
3248
+ * Caller-supplied `Converter<T>` or `Validator<T>` applied to the parsed
3249
+ * JSON value. Wrapped internally in {@link AiAssist.fencedStringifiedJson}
3250
+ * unless {@link AiAssist.IGenerateJsonCompletionParams.jsonConverter} is
3251
+ * provided.
3252
+ */
3253
+ readonly converter?: Converter<T> | Validator<T>;
3254
+ /**
3255
+ * Full string-to-`T` pipeline override. When supplied, takes precedence over
3256
+ * {@link AiAssist.IGenerateJsonCompletionParams.converter} and lets the
3257
+ * caller plug in a custom extractor or skip the default fence tolerance
3258
+ * entirely.
3259
+ */
3260
+ readonly jsonConverter?: Converter<T>;
3261
+ /**
3262
+ * Controls the optional system-prompt augmentation. Defaults to `'smart'`.
3263
+ * Pass `'none'` to disable, or a string to append custom guidance.
3264
+ */
3265
+ readonly promptHint?: JsonPromptHint;
3266
+ }
3267
+
3268
+ /**
3269
+ * Successful result of {@link AiAssist.generateJsonCompletion}.
3270
+ * @public
3271
+ */
3272
+ declare interface IGenerateJsonCompletionResult<T> {
3273
+ /** The validated JSON value. */
3274
+ readonly value: T;
3275
+ /** The raw response text returned by the provider. */
3276
+ readonly raw: string;
3277
+ /** The full underlying completion response. */
3278
+ readonly response: IAiCompletionResponse;
3279
+ }
3280
+
3281
+ /**
3282
+ * Provider-specific config for gpt-image-1.
3283
+ * @public
3284
+ */
3285
+ declare interface IGptImageGenerationConfig {
3286
+ /** Image dimensions. */
3287
+ readonly size?: GptImageSize;
3288
+ /** Quality tier. */
3289
+ readonly quality?: GptImageQuality;
3290
+ /** Output format (replaces response_format for this model). */
3291
+ readonly outputFormat?: 'png' | 'jpeg' | 'webp';
3292
+ /** JPEG/WebP compression level 0–100. */
3293
+ readonly outputCompression?: number;
3294
+ /** Background transparency control. */
3295
+ readonly background?: 'transparent' | 'opaque' | 'auto';
3296
+ /** Content moderation strictness. */
3297
+ readonly moderation?: 'low' | 'auto';
3298
+ }
3299
+
3300
+ /**
3301
+ * Options block scoped to GPT Image family models.
3302
+ * @public
3303
+ */
3304
+ declare interface IGptImageModelOptions extends INamedModelFamilyConfig {
3305
+ readonly provider: 'openai';
3306
+ readonly family: 'gpt-image';
3307
+ readonly models?: GptImageModelNames[];
3308
+ readonly config: IGptImageGenerationConfig;
3309
+ }
3310
+
3311
+ /**
3312
+ * Provider-specific config for xAI Grok Imagine models.
3313
+ * @public
3314
+ */
3315
+ declare interface IGrokImagineImageGenerationConfig {
3316
+ /** Aspect ratio string (xAI uses aspect ratios, not pixel dimensions). */
3317
+ readonly aspectRatio?: string;
3318
+ /** Resolution hint. */
3319
+ readonly resolution?: string;
3320
+ }
3321
+
3322
+ /**
3323
+ * Options block scoped to xAI Grok Imagine family models.
3324
+ * @public
3325
+ */
3326
+ declare interface IGrokImagineModelOptions extends INamedModelFamilyConfig {
3327
+ readonly provider: 'xai';
3328
+ readonly family: 'grok-imagine';
3329
+ readonly models?: GrokImagineModelNames[];
3330
+ readonly config: IGrokImagineImageGenerationConfig;
3331
+ }
3332
+
3333
+ /**
3334
+ * Output of {@link HpkeProvider.sealBase}.
3335
+ *
3336
+ * The `ciphertext` field includes the 16-byte AES-256-GCM authentication tag
3337
+ * appended by Web Crypto's `encrypt()` operation: `length = plaintext.length + 16`.
3338
+ * @public
3339
+ */
3340
+ declare interface IHpkeSealResult {
3341
+ /**
3342
+ * Encapsulated key — 32-byte raw X25519 ephemeral public key (`enc` in RFC 9180).
3343
+ * Must be transmitted to the recipient alongside `ciphertext`.
3344
+ */
3345
+ readonly enc: Uint8Array;
3346
+ /**
3347
+ * AES-256-GCM ciphertext with the 16-byte authentication tag appended.
3348
+ * Length = `plaintext.length + 16`.
3349
+ */
3350
+ readonly ciphertext: Uint8Array;
3351
+ }
3352
+
3353
+ /**
3354
+ * Options for importing raw key material via {@link KeyStore.importSecret}.
3355
+ * Extends {@link IImportSecretOptions} with a type classification.
3356
+ * @public
3357
+ */
3358
+ declare interface IImportKeyOptions extends IImportSecretOptions {
3359
+ /**
3360
+ * Symmetric secret type classification for the imported key material.
3361
+ * @defaultValue 'encryption-key'
3362
+ */
3363
+ readonly type?: KeyStoreSymmetricSecretType;
3364
+ }
3365
+
1096
3366
  /**
1097
3367
  * Options for importing a secret.
1098
3368
  * @public
@@ -1106,22 +3376,129 @@ declare interface IImportSecretOptions extends IAddSecretOptions {
1106
3376
 
1107
3377
  /**
1108
3378
  * Key derivation parameters stored in encrypted files.
1109
- * Allows decryption with password without needing to know the original salt/iterations.
3379
+ * Discriminated union on `kdf` field: `'pbkdf2'` or `'argon2id'`.
3380
+ * @public
3381
+ */
3382
+ declare type IKeyDerivationParams = IPbkdf2KeyDerivationParams | IArgon2idKeyDerivationParams;
3383
+
3384
+ /**
3385
+ * WebCrypto parameters for a single {@link CryptoUtils.KeyPairAlgorithm}.
3386
+ * Implementations of {@link CryptoUtils.ICryptoProvider} use this table to
3387
+ * translate the small public algorithm enum into the WebCrypto algorithm
3388
+ * objects and key-usage arrays expected by `crypto.subtle`.
1110
3389
  * @public
1111
3390
  */
1112
- declare interface IKeyDerivationParams {
3391
+ declare interface IKeyPairAlgorithmParams {
1113
3392
  /**
1114
- * Key derivation function used.
3393
+ * Algorithm parameters for `crypto.subtle.generateKey`. Always an asymmetric
3394
+ * variant — these algorithms produce a `CryptoKeyPair`, not a single key.
3395
+ * The literal `{ name: 'Ed25519' }` member covers WebCrypto's Secure-Curves
3396
+ * Ed25519 algorithm; `{ name: 'X25519' }` covers the X25519 key-agreement
3397
+ * algorithm. Both take only a `name`; using literals rather than the base
3398
+ * `Algorithm` keeps the union closed to the algorithms this table supports.
1115
3399
  */
1116
- readonly kdf: KeyDerivationFunction;
3400
+ readonly generateKey: RsaHashedKeyGenParams | EcKeyGenParams | {
3401
+ readonly name: 'Ed25519';
3402
+ } | {
3403
+ readonly name: 'X25519';
3404
+ };
1117
3405
  /**
1118
- * Base64-encoded salt used for key derivation.
3406
+ * Algorithm parameters for `crypto.subtle.importKey('jwk', ...)` when
3407
+ * importing the public half of a keypair. The literal `{ name: 'Ed25519' }`
3408
+ * member covers Ed25519 imports; `{ name: 'X25519' }` covers X25519 imports.
3409
+ * Both take only a `name`; using literals rather than the base `Algorithm`
3410
+ * keeps the union closed to the algorithms this table supports.
1119
3411
  */
1120
- readonly salt: string;
3412
+ readonly importPublicKey: RsaHashedImportParams | EcKeyImportParams | {
3413
+ readonly name: 'Ed25519';
3414
+ } | {
3415
+ readonly name: 'X25519';
3416
+ };
1121
3417
  /**
1122
- * Number of iterations used for key derivation.
3418
+ * Default key usages for the generated `CryptoKeyPair`. Both halves receive
3419
+ * the usages WebCrypto considers valid for their role; the platform filters.
1123
3420
  */
1124
- readonly iterations: number;
3421
+ readonly keyPairUsages: ReadonlyArray<KeyUsage>;
3422
+ /**
3423
+ * Key usages applied when re-importing only the public key.
3424
+ */
3425
+ readonly publicKeyUsages: ReadonlyArray<KeyUsage>;
3426
+ }
3427
+
3428
+ /**
3429
+ * An asymmetric keypair entry stored in the vault (in-memory representation).
3430
+ * Holds only the public key (as a JWK) and a stable handle (`id`) the
3431
+ * {@link CryptoUtils.KeyStore.IPrivateKeyStorage} provider uses to fetch the private key.
3432
+ * @public
3433
+ */
3434
+ declare interface IKeyStoreAsymmetricEntry {
3435
+ /**
3436
+ * Unique name for this entry (used as vault lookup key, renameable).
3437
+ */
3438
+ readonly name: string;
3439
+ /**
3440
+ * Asymmetric secret type discriminator.
3441
+ */
3442
+ readonly type: KeyStoreAsymmetricSecretType;
3443
+ /**
3444
+ * Immutable handle used by {@link CryptoUtils.KeyStore.IPrivateKeyStorage} to address the
3445
+ * private key. Independent of `name`; survives renames.
3446
+ */
3447
+ readonly id: string;
3448
+ /**
3449
+ * Algorithm used to generate this keypair.
3450
+ */
3451
+ readonly algorithm: KeyPairAlgorithm;
3452
+ /**
3453
+ * The public key as a JSON Web Key.
3454
+ */
3455
+ readonly publicKeyJwk: JsonWebKey;
3456
+ /**
3457
+ * Optional description for this entry.
3458
+ */
3459
+ readonly description?: string;
3460
+ /**
3461
+ * When this entry was added (ISO 8601).
3462
+ */
3463
+ readonly createdAt: string;
3464
+ }
3465
+
3466
+ /**
3467
+ * JSON-serializable representation of an asymmetric keypair entry.
3468
+ * The private key is not present here — it lives in the
3469
+ * {@link CryptoUtils.KeyStore.IPrivateKeyStorage} provider, addressed by `id`.
3470
+ * @public
3471
+ */
3472
+ declare interface IKeyStoreAsymmetricEntryJson {
3473
+ /**
3474
+ * Unique name for this entry.
3475
+ */
3476
+ readonly name: string;
3477
+ /**
3478
+ * Asymmetric secret type discriminator.
3479
+ */
3480
+ readonly type: KeyStoreAsymmetricSecretType;
3481
+ /**
3482
+ * Immutable handle used by {@link CryptoUtils.KeyStore.IPrivateKeyStorage} to address the
3483
+ * private key.
3484
+ */
3485
+ readonly id: string;
3486
+ /**
3487
+ * Algorithm used to generate this keypair.
3488
+ */
3489
+ readonly algorithm: KeyPairAlgorithm;
3490
+ /**
3491
+ * The public key as a JSON Web Key.
3492
+ */
3493
+ readonly publicKeyJwk: JsonWebKey;
3494
+ /**
3495
+ * Optional description.
3496
+ */
3497
+ readonly description?: string;
3498
+ /**
3499
+ * When this entry was added (ISO 8601).
3500
+ */
3501
+ readonly createdAt: string;
1125
3502
  }
1126
3503
 
1127
3504
  /**
@@ -1137,8 +3514,26 @@ declare interface IKeyStoreCreateParams {
1137
3514
  * PBKDF2 iterations (defaults to DEFAULT_KEYSTORE_ITERATIONS).
1138
3515
  */
1139
3516
  readonly iterations?: number;
3517
+ /**
3518
+ * Optional private-key storage backend. Required to use `addKeyPair` /
3519
+ * `getKeyPair`; absent backends still permit opening, listing, and reading
3520
+ * public-key metadata for asymmetric entries.
3521
+ */
3522
+ readonly privateKeyStorage?: IPrivateKeyStorage;
1140
3523
  }
1141
3524
 
3525
+ /**
3526
+ * Any vault entry, discriminated by `type`.
3527
+ * @public
3528
+ */
3529
+ declare type IKeyStoreEntry = IKeyStoreSymmetricEntry | IKeyStoreAsymmetricEntry;
3530
+
3531
+ /**
3532
+ * Any JSON vault entry, discriminated by `type`.
3533
+ * @public
3534
+ */
3535
+ declare type IKeyStoreEntryJson = IKeyStoreSymmetricEntryJson | IKeyStoreAsymmetricEntryJson;
3536
+
1142
3537
  /**
1143
3538
  * The encrypted key store file format.
1144
3539
  * @public
@@ -1165,9 +3560,9 @@ declare interface IKeyStoreFile {
1165
3560
  */
1166
3561
  readonly encryptedData: string;
1167
3562
  /**
1168
- * Key derivation parameters (required for key store - always password-derived).
3563
+ * Key derivation parameters for the vault master key (always PBKDF2).
1169
3564
  */
1170
- readonly keyDerivation: IKeyDerivationParams;
3565
+ readonly keyDerivation: IPbkdf2KeyDerivationParams;
1171
3566
  }
1172
3567
 
1173
3568
  /**
@@ -1183,22 +3578,46 @@ declare interface IKeyStoreOpenParams {
1183
3578
  * The encrypted key store file content.
1184
3579
  */
1185
3580
  readonly keystoreFile: IKeyStoreFile;
3581
+ /**
3582
+ * Optional private-key storage backend. Required to use `addKeyPair` /
3583
+ * `getKeyPair`; absent backends still permit opening, listing, and reading
3584
+ * public-key metadata for asymmetric entries.
3585
+ */
3586
+ readonly privateKeyStorage?: IPrivateKeyStorage;
1186
3587
  }
1187
3588
 
1188
3589
  /**
1189
- * A secret entry stored in the vault (in-memory representation).
3590
+ * Backwards-compatible alias for {@link CryptoUtils.KeyStore.IKeyStoreSymmetricEntry}.
3591
+ * @deprecated Use {@link CryptoUtils.KeyStore.IKeyStoreSymmetricEntry} for symmetric
3592
+ * entries or {@link CryptoUtils.KeyStore.IKeyStoreEntry} for the discriminated union.
3593
+ * @public
3594
+ */
3595
+ declare type IKeyStoreSecretEntry = IKeyStoreSymmetricEntry;
3596
+
3597
+ /**
3598
+ * Backwards-compatible alias for {@link CryptoUtils.KeyStore.IKeyStoreSymmetricEntryJson}.
3599
+ * @deprecated Use {@link CryptoUtils.KeyStore.IKeyStoreSymmetricEntryJson} for
3600
+ * symmetric entries or {@link CryptoUtils.KeyStore.IKeyStoreEntryJson} for the
3601
+ * discriminated union.
3602
+ * @public
3603
+ */
3604
+ declare type IKeyStoreSecretEntryJson = IKeyStoreSymmetricEntryJson;
3605
+
3606
+ /**
3607
+ * A symmetric secret entry stored in the vault (in-memory representation).
3608
+ * Holds the raw key material directly — for `'encryption-key'` it is a 32-byte
3609
+ * AES-256 key; for `'api-key'` it is the UTF-8 encoded API key string.
1190
3610
  * @public
1191
3611
  */
1192
- declare interface IKeyStoreSecretEntry {
3612
+ declare interface IKeyStoreSymmetricEntry {
1193
3613
  /**
1194
3614
  * Unique name for this secret (used as lookup key).
1195
3615
  */
1196
3616
  readonly name: string;
1197
3617
  /**
1198
- * Secret type discriminator.
1199
- * Defaults to `'encryption-key'` for backwards compatibility.
3618
+ * Symmetric secret type discriminator.
1200
3619
  */
1201
- readonly type: KeyStoreSecretType;
3620
+ readonly type: KeyStoreSymmetricSecretType;
1202
3621
  /**
1203
3622
  * The secret data.
1204
3623
  * - For `'encryption-key'`: 32-byte AES-256 key.
@@ -1216,19 +3635,34 @@ declare interface IKeyStoreSecretEntry {
1216
3635
  }
1217
3636
 
1218
3637
  /**
1219
- * JSON-serializable version of secret entry (for storage).
3638
+ * JSON-serializable representation of a symmetric secret entry.
3639
+ *
3640
+ * @remarks
3641
+ * Describes the *normalized* shape after parsing. `type` is required here
3642
+ * because the converter (see
3643
+ * {@link CryptoUtils.KeyStore.Converters.keystoreSymmetricEntryJson | keystoreSymmetricEntryJson})
3644
+ * injects the default `'encryption-key'` when reading vaults written before
3645
+ * asymmetric-keypair support added the discriminator. Raw on-wire bytes from
3646
+ * a legacy vault may therefore omit `type`; downstream code only ever sees
3647
+ * the post-conversion shape declared here.
3648
+ *
1220
3649
  * @public
1221
3650
  */
1222
- declare interface IKeyStoreSecretEntryJson {
3651
+ declare interface IKeyStoreSymmetricEntryJson {
1223
3652
  /**
1224
3653
  * Unique name for this secret.
1225
3654
  */
1226
3655
  readonly name: string;
1227
3656
  /**
1228
- * Secret type discriminator.
1229
- * Optional for backwards compatibility — missing means `'encryption-key'`.
3657
+ * Symmetric secret type discriminator.
3658
+ *
3659
+ * Required on this normalized model type. Vaults written prior to the
3660
+ * asymmetric-keypair support may omit this field on the wire; the
3661
+ * converter injects `'encryption-key'` when missing for backwards
3662
+ * compatibility, so by the time a value of this type is observed the
3663
+ * discriminator is always present.
1230
3664
  */
1231
- readonly type?: KeyStoreSecretType;
3665
+ readonly type: KeyStoreSymmetricSecretType;
1232
3666
  /**
1233
3667
  * Base64-encoded secret data.
1234
3668
  */
@@ -1244,7 +3678,7 @@ declare interface IKeyStoreSecretEntryJson {
1244
3678
  }
1245
3679
 
1246
3680
  /**
1247
- * The decrypted vault contents - a versioned map of secrets.
3681
+ * The decrypted vault contents - a versioned map of entries.
1248
3682
  * @public
1249
3683
  */
1250
3684
  declare interface IKeyStoreVaultContents {
@@ -1253,9 +3687,9 @@ declare interface IKeyStoreVaultContents {
1253
3687
  */
1254
3688
  readonly version: KeyStoreFormat;
1255
3689
  /**
1256
- * Map of secret name to secret entry.
3690
+ * Map of entry name to entry (symmetric or asymmetric).
1257
3691
  */
1258
- readonly secrets: Record<string, IKeyStoreSecretEntryJson>;
3692
+ readonly secrets: Record<string, IKeyStoreEntryJson>;
1259
3693
  }
1260
3694
 
1261
3695
  /**
@@ -1278,6 +3712,28 @@ declare interface IMissingVariableDetail {
1278
3712
  readonly existingPath: readonly string[];
1279
3713
  }
1280
3714
 
3715
+ /**
3716
+ * Canonical fgv alias → concrete provider model map.
3717
+ *
3718
+ * @remarks
3719
+ * Keys are full fgv aliases (`@<providerId>:<role>`, e.g. `@google-gemini:flash`);
3720
+ * values are the current concrete provider model id (or a provider-native alias,
3721
+ * which is resolved with one further indirection hop). Additive; absence of an
3722
+ * `aliases` field on a descriptor means "this provider defines no aliases" and
3723
+ * every model string passes through verbatim.
3724
+ * @public
3725
+ */
3726
+ declare interface IModelAliasMap {
3727
+ readonly [alias: string]: string;
3728
+ }
3729
+
3730
+ /**
3731
+ * Discriminated union of all model-family option blocks.
3732
+ * Discriminated on `provider` + `family` fields.
3733
+ * @public
3734
+ */
3735
+ declare type IModelFamilyConfig = IGptImageModelOptions | IGrokImagineModelOptions | IGeminiFlashImageModelOptions | IOtherModelOptions;
3736
+
1281
3737
  /**
1282
3738
  * A model specification: either a simple model string or a record mapping
1283
3739
  * context keys to nested model specs.
@@ -1285,18 +3741,18 @@ declare interface IMissingVariableDetail {
1285
3741
  * @remarks
1286
3742
  * A bare string is equivalent to `{ base: string }`. This keeps the simple
1287
3743
  * case simple while allowing context-aware model selection (e.g. different
1288
- * models for tool-augmented vs. base completions).
3744
+ * models for different quality tiers).
1289
3745
  *
1290
3746
  * @example
1291
3747
  * ```typescript
1292
3748
  * // Simple — same model for all contexts:
1293
- * const simple: ModelSpec = 'grok-4-1-fast';
3749
+ * const simple: ModelSpec = 'grok-4.3';
1294
3750
  *
1295
- * // Context-aware — reasoning model when tools are active:
1296
- * const split: ModelSpec = { base: 'grok-4-1-fast', tools: 'grok-4-1-fast-reasoning' };
3751
+ * // Context-aware — different model per quality tier:
3752
+ * const split: ModelSpec = { base: 'gpt-5.4-mini', advanced: 'gpt-5.5', frontier: 'gpt-5.5-pro' };
1297
3753
  *
1298
- * // Future nested per-tool model selection:
1299
- * const nested: ModelSpec = { base: 'grok-fast', tools: { base: 'grok-r', image: 'grok-v' } };
3754
+ * // Nesteda tier branch is itself a spec:
3755
+ * const nested: ModelSpec = { base: 'grok-fast', advanced: { base: 'grok-r', image: 'grok-v' } };
1300
3756
  * ```
1301
3757
  * @public
1302
3758
  */
@@ -1304,6 +3760,25 @@ declare interface IModelSpecMap {
1304
3760
  readonly [key: string]: ModelSpec;
1305
3761
  }
1306
3762
 
3763
+ /**
3764
+ * Imports a public key from a multibase base64url-encoded SPKI blob.
3765
+ *
3766
+ * Decodes the multibase prefix, decodes the base64url body, then uses
3767
+ * the provider to import the key with the algorithm parameters from
3768
+ * {@link CryptoUtils.keyPairAlgorithmParams}.
3769
+ *
3770
+ * Accepts a plain `string` (not only a branded {@link CryptoUtils.MultibaseSpkiPublicKey}),
3771
+ * so callers holding an unbranded value read from storage or the wire can import
3772
+ * it directly; a malformed value fails with error context rather than throwing.
3773
+ *
3774
+ * @param encoded - A multibase SPKI string produced by {@link CryptoUtils.exportPublicKeyAsMultibaseSpki}.
3775
+ * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm} the key was generated for.
3776
+ * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the import operation.
3777
+ * @returns `Success` with the imported public `CryptoKey`, or `Failure` with error context.
3778
+ * @public
3779
+ */
3780
+ declare function importPublicKeyFromMultibaseSpki(encoded: string, algorithm: KeyPairAlgorithm, provider: ICryptoProvider): Promise<Result<CryptoKey>>;
3781
+
1307
3782
  /**
1308
3783
  * Options for template parsing and validation.
1309
3784
  * @public
@@ -1321,6 +3796,32 @@ declare interface IMustacheTemplateOptions {
1321
3796
  * Whether to include partial references in variable extraction (default: false)
1322
3797
  */
1323
3798
  readonly includePartials?: boolean;
3799
+ /**
3800
+ * Escape strategy applied to double-brace `{{name}}` tokens at render
3801
+ * time. Default `'html'` preserves the existing mustache.js behavior
3802
+ * (back-compat).
3803
+ *
3804
+ * Pass `'none'` for LLM-prompt or other non-HTML targets where the
3805
+ * default `& → &amp;` escape would corrupt the output. Pass a custom
3806
+ * function for any other escape policy.
3807
+ *
3808
+ * The strategy is applied per-template via a private `Mustache.Writer`
3809
+ * instance; no global state on the `mustache` module is mutated, so
3810
+ * concurrent templates with different strategies are safe.
3811
+ *
3812
+ * Note: triple-brace `{{{name}}}` tokens are always rendered unescaped
3813
+ * regardless of strategy (standard mustache.js semantics).
3814
+ */
3815
+ readonly escape?: MustacheEscapeStrategy;
3816
+ }
3817
+
3818
+ /**
3819
+ * Base shape shared by all named family option blocks.
3820
+ * Provides a typed `models` field for applicability filtering without unsafe casts.
3821
+ * @internal
3822
+ */
3823
+ declare interface INamedModelFamilyConfig {
3824
+ readonly models?: readonly string[];
1324
3825
  }
1325
3826
 
1326
3827
  /**
@@ -1339,29 +3840,312 @@ declare interface INamedSecret {
1339
3840
  }
1340
3841
 
1341
3842
  /**
1342
- * Parameters for a provider completion request.
3843
+ * OpenAI-specific thinking configuration.
3844
+ * @remarks
3845
+ * Maps to `reasoning_effort` (Chat Completions path) or `reasoning.effort`
3846
+ * (Responses API path) on the wire. The adapter selects the correct field.
3847
+ * @public
3848
+ */
3849
+ declare interface IOpenAiThinkingConfig {
3850
+ /**
3851
+ * OpenAI reasoning effort. Maps 1:1 to the wire field.
3852
+ * - 'none': disables reasoning (gpt-5.x only; rejected by o-series)
3853
+ * - 'minimal': fastest (gpt-5.x)
3854
+ * - 'low' | 'medium' | 'high': standard tiers
3855
+ * - 'xhigh': highest (select gpt-5.x models only)
3856
+ *
3857
+ * @remarks
3858
+ * When effective effort is 'none', reasoning is disabled and temperature is
3859
+ * accepted by gpt-5.x models. This is the only case where temperature and
3860
+ * thinking config co-exist without a Result.fail.
3861
+ */
3862
+ readonly effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
3863
+ }
3864
+
3865
+ /**
3866
+ * OpenAI-specific thinking options block.
3867
+ * @public
3868
+ */
3869
+ declare interface IOpenAiThinkingOptions {
3870
+ readonly provider: 'openai';
3871
+ readonly models?: ReadonlyArray<OpenAiThinkingModelNames>;
3872
+ readonly config: IOpenAiThinkingConfig;
3873
+ }
3874
+
3875
+ /**
3876
+ * Escape-hatch options block for models not covered by a named family.
3877
+ * @remarks
3878
+ * `models` is required — there is no implicit "all" for unknown model families.
3879
+ * `config` is `JsonObject` — passed verbatim to the wire request with no validation.
3880
+ * This is the "trust me, I know what I'm doing" path for callers who need to send
3881
+ * wire params our typed configs don't yet expose.
3882
+ * @public
3883
+ */
3884
+ declare interface IOtherModelOptions {
3885
+ readonly provider: 'other';
3886
+ readonly models: string[];
3887
+ readonly config: JsonObject;
3888
+ }
3889
+
3890
+ /**
3891
+ * Escape-hatch options block for providers not covered by typed configs.
3892
+ * @remarks
3893
+ * `models` is required — no implicit "all" for unknown providers.
3894
+ * `config` fields are merged verbatim into the wire request.
3895
+ * @public
3896
+ */
3897
+ declare interface IOtherThinkingOptions {
3898
+ readonly provider: 'other';
3899
+ readonly models: ReadonlyArray<string>;
3900
+ readonly config: JsonObject;
3901
+ }
3902
+
3903
+ /**
3904
+ * PBKDF2 key derivation parameters.
3905
+ * @public
3906
+ */
3907
+ declare interface IPbkdf2KeyDerivationParams {
3908
+ /** Key derivation function discriminator. */
3909
+ readonly kdf: 'pbkdf2';
3910
+ /** Base64-encoded salt used for key derivation. */
3911
+ readonly salt: string;
3912
+ /** Number of iterations used for key derivation. */
3913
+ readonly iterations: number;
3914
+ }
3915
+
3916
+ /**
3917
+ * Pluggable backend that persists raw asymmetric private keys outside of the
3918
+ * encrypted keystore vault. Concrete implementations:
3919
+ * - {@link CryptoUtils.KeyStore.EncryptedFilePrivateKeyStorage} in
3920
+ * `@fgv/ts-extras` — directory-on-disk, AES-256-GCM-encrypted JWK per key
3921
+ * (Node; `supportsNonExtractable: false`).
3922
+ * - `IdbPrivateKeyStorage` in `@fgv/ts-web-extras` — IndexedDB-backed, stores
3923
+ * `CryptoKey` objects directly (browser; `supportsNonExtractable: true`).
3924
+ *
3925
+ * The keystore writes storage-first: a private key is always stored here
3926
+ * before the corresponding public-key vault entry is committed. Conversely,
3927
+ * deletes hit the vault first and then this storage best-effort. As a result,
3928
+ * crashes or skipped saves can leave orphaned blobs here; callers are expected
3929
+ * to reconcile via {@link CryptoUtils.KeyStore.IPrivateKeyStorage.list} cross-referenced
3930
+ * against the keystore's asymmetric entries.
3931
+ *
3932
+ * @public
3933
+ */
3934
+ declare interface IPrivateKeyStorage {
3935
+ /**
3936
+ * Whether keys generated for this backend may be marked
3937
+ * `extractable: false`. `true` on backends that store `CryptoKey`
3938
+ * objects directly (e.g. IndexedDB). `false` on backends that must
3939
+ * round-trip via JWK (e.g. encrypted-file backends).
3940
+ */
3941
+ readonly supportsNonExtractable: boolean;
3942
+ /**
3943
+ * Stores `key` under `id`. Returns the stored `id` on success so the
3944
+ * call can compose into a Result chain.
3945
+ * @param id - Storage handle to write under.
3946
+ * @param key - The private `CryptoKey` to persist.
3947
+ */
3948
+ store(id: string, key: CryptoKey): Promise<Result<string>>;
3949
+ /**
3950
+ * Loads the private key previously stored under `id`.
3951
+ * @param id - Storage handle to look up.
3952
+ */
3953
+ load(id: string): Promise<Result<CryptoKey>>;
3954
+ /**
3955
+ * Deletes the entry stored under `id`. Returns the deleted `id` on
3956
+ * success so the call can compose into a Result chain.
3957
+ * @param id - Storage handle to remove.
3958
+ */
3959
+ delete(id: string): Promise<Result<string>>;
3960
+ /**
3961
+ * Lists every `id` currently held by the backend. Used by consumers to
3962
+ * garbage-collect orphans left by crashes or aborted sessions; the
3963
+ * keystore itself does not invoke this automatically.
3964
+ */
3965
+ list(): Promise<Result<readonly string[]>>;
3966
+ }
3967
+
3968
+ /**
3969
+ * Parameters for a provider completion request. Carries the unified
3970
+ * {@link AiAssist.IChatRequest} shape (`system?` + ordered `messages`, last =
3971
+ * current user turn); history is linearized before the current turn.
1343
3972
  * @public
1344
3973
  */
1345
- declare interface IProviderCompletionParams {
3974
+ declare interface IProviderCompletionParams extends IChatRequest {
1346
3975
  /** The provider descriptor */
1347
3976
  readonly descriptor: IAiProviderDescriptor;
1348
3977
  /** API key for authentication */
1349
3978
  readonly apiKey: string;
1350
- /** The structured prompt to send */
1351
- readonly prompt: AiPrompt;
1352
3979
  /**
1353
- * Additional messages to append after system+user (e.g. for correction retries).
1354
- * These are appended in order after the initial system and user messages.
3980
+ * Sampling temperature. Sent to the provider only when explicitly provided; omitted otherwise
3981
+ * so the provider's own default applies (current-gen models reject a caller-supplied default).
1355
3982
  */
1356
- readonly additionalMessages?: ReadonlyArray<IChatMessage>;
1357
- /** Sampling temperature (default: 0.7) */
1358
3983
  readonly temperature?: number;
1359
3984
  /** Optional model override — string or context-aware map (uses descriptor.defaultModel otherwise) */
1360
3985
  readonly modelOverride?: ModelSpec;
3986
+ /**
3987
+ * Optional quality tier selecting which completion model to use. `undefined`
3988
+ * selects the `base` tier; `'frontier'` cascades to `advanced` then `base`
3989
+ * when a tier is unset for a provider. Orthogonal to `thinking` and `tools`,
3990
+ * which never select a model.
3991
+ */
3992
+ readonly tier?: 'advanced' | 'frontier';
1361
3993
  /** Optional logger for request/response observability. */
1362
3994
  readonly logger?: Logging.ILogger;
1363
3995
  /** Server-side tools to include in the request. Overrides settings-level tool config when provided. */
1364
3996
  readonly tools?: ReadonlyArray<AiServerToolConfig>;
3997
+ /** Optional abort signal for cancelling the in-flight request. */
3998
+ readonly signal?: AbortSignal;
3999
+ /**
4000
+ * Optional override of the descriptor's default base URL (scheme + host +
4001
+ * optional port + path prefix). The per-route suffix (e.g. `/chat/completions`)
4002
+ * is appended unchanged. Must be a well-formed `http`/`https` URL. Auth shape
4003
+ * is unchanged: `needsSecret` providers still require an API key.
4004
+ */
4005
+ readonly endpoint?: string;
4006
+ /**
4007
+ * Optional thinking/reasoning config. Anthropic, OpenAI, and xAI reject `temperature` when
4008
+ * the effective merged effort is non-`'none'`; Gemini always accepts both.
4009
+ */
4010
+ readonly thinking?: IThinkingConfig;
4011
+ }
4012
+
4013
+ /**
4014
+ * Parameters for a streaming completion request. Structurally identical to
4015
+ * the non-streaming `IProviderCompletionParams`; kept as its own interface
4016
+ * so callers can be explicit about which path they're invoking.
4017
+ *
4018
+ * @remarks
4019
+ * Carries the unified {@link AiAssist.IChatRequest} shape (`system?` + ordered
4020
+ * `messages`): the last message is the current user turn and the preceding
4021
+ * messages are history, linearized before the current turn (identical to the
4022
+ * completion and client-tool turn paths).
4023
+ *
4024
+ * @public
4025
+ */
4026
+ declare interface IProviderCompletionStreamParams extends IChatRequest {
4027
+ /** The provider descriptor */
4028
+ readonly descriptor: IAiProviderDescriptor;
4029
+ /** API key for authentication */
4030
+ readonly apiKey: string;
4031
+ /**
4032
+ * Sampling temperature. Sent to the provider only when explicitly provided; omitted otherwise
4033
+ * so the provider's own default applies (current-gen models reject a caller-supplied default).
4034
+ */
4035
+ readonly temperature?: number;
4036
+ /** Optional model override — string or context-aware map. */
4037
+ readonly modelOverride?: ModelSpec;
4038
+ /**
4039
+ * Optional quality tier selecting which completion model to use. `undefined`
4040
+ * selects the `base` tier; `'frontier'` cascades to `advanced` then `base`
4041
+ * when a tier is unset for a provider. Orthogonal to `thinking` and `tools`,
4042
+ * which never select a model.
4043
+ */
4044
+ readonly tier?: 'advanced' | 'frontier';
4045
+ /** Optional logger for request/response observability. */
4046
+ readonly logger?: Logging.ILogger;
4047
+ /** Server-side tools to include in the request. */
4048
+ readonly tools?: ReadonlyArray<AiServerToolConfig>;
4049
+ /** Optional abort signal for cancelling the in-flight stream. */
4050
+ readonly signal?: AbortSignal;
4051
+ /**
4052
+ * Optional override of the descriptor's default base URL. Same semantics as
4053
+ * the non-streaming completion path: a well-formed `http`/`https` URL is
4054
+ * substituted for `descriptor.baseUrl` when composing the streaming
4055
+ * request, with the per-format suffix appended unchanged. Validated at the
4056
+ * dispatcher; auth shape is unaffected.
4057
+ */
4058
+ readonly endpoint?: string;
4059
+ /**
4060
+ * Optional thinking/reasoning mode configuration.
4061
+ */
4062
+ readonly thinking?: IThinkingConfig;
4063
+ }
4064
+
4065
+ /**
4066
+ * Parameters for a provider embedding request. Mirrors
4067
+ * {@link AiAssist.IProviderImageGenerationParams}.
4068
+ * @public
4069
+ */
4070
+ declare interface IProviderEmbeddingParams {
4071
+ /** The provider descriptor. */
4072
+ readonly descriptor: IAiProviderDescriptor;
4073
+ /** API key for authentication (empty string for keyless self-hosted providers). */
4074
+ readonly apiKey: string;
4075
+ /** The embedding request (input + optional knobs). */
4076
+ readonly params: IAiEmbeddingParams;
4077
+ /**
4078
+ * Optional model override — string or context-aware map. Uses
4079
+ * `descriptor.defaultModel.embedding` otherwise. Self-hosted providers
4080
+ * (`ollama`, `openai-compat`) have no default and require this.
4081
+ */
4082
+ readonly modelOverride?: ModelSpec;
4083
+ /** Optional logger for request/response observability. */
4084
+ readonly logger?: Logging.ILogger;
4085
+ /** Optional abort signal for cancelling the in-flight request. */
4086
+ readonly signal?: AbortSignal;
4087
+ /** Optional override of the descriptor's base URL; the `/embeddings` suffix is appended unchanged. */
4088
+ readonly endpoint?: string;
4089
+ }
4090
+
4091
+ /**
4092
+ * Parameters for an image-generation request.
4093
+ * @public
4094
+ */
4095
+ declare interface IProviderImageGenerationParams {
4096
+ /** The provider descriptor */
4097
+ readonly descriptor: IAiProviderDescriptor;
4098
+ /** API key for authentication */
4099
+ readonly apiKey: string;
4100
+ /** The image-generation request */
4101
+ readonly params: IAiImageGenerationParams;
4102
+ /** Optional model override — string or context-aware map (uses descriptor.defaultModel.image otherwise) */
4103
+ readonly modelOverride?: ModelSpec;
4104
+ /** Optional logger for request/response observability. */
4105
+ readonly logger?: Logging.ILogger;
4106
+ /** Optional abort signal for cancelling the in-flight request. */
4107
+ readonly signal?: AbortSignal;
4108
+ /** Optional override of the descriptor's base URL; per-route suffix is appended unchanged. */
4109
+ readonly endpoint?: string;
4110
+ }
4111
+
4112
+ /**
4113
+ * Parameters for a list-models request.
4114
+ * @public
4115
+ */
4116
+ declare interface IProviderListModelsParams {
4117
+ /** The provider descriptor */
4118
+ readonly descriptor: IAiProviderDescriptor;
4119
+ /** API key for authentication */
4120
+ readonly apiKey: string;
4121
+ /** Optional capability filter; when set, only models declaring this capability are returned. */
4122
+ readonly capability?: AiModelCapability;
4123
+ /** Optional capability config override (defaults to {@link DEFAULT_MODEL_CAPABILITY_CONFIG}). */
4124
+ readonly capabilityConfig?: IAiModelCapabilityConfig;
4125
+ /** Optional logger for request/response observability. */
4126
+ readonly logger?: Logging.ILogger;
4127
+ /** Optional abort signal for cancelling the in-flight request. */
4128
+ readonly signal?: AbortSignal;
4129
+ /** Optional override of the descriptor's base URL; per-format `/models` route is appended unchanged. */
4130
+ readonly endpoint?: string;
4131
+ }
4132
+
4133
+ /**
4134
+ * Result of removing a secret from the key store.
4135
+ * @public
4136
+ */
4137
+ declare interface IRemoveSecretResult {
4138
+ /**
4139
+ * The secret entry that was removed from the vault.
4140
+ */
4141
+ readonly entry: IKeyStoreEntry;
4142
+ /**
4143
+ * Best-effort warning from {@link CryptoUtils.KeyStore.IPrivateKeyStorage}.delete
4144
+ * for asymmetric entries when the storage call failed. The vault entry is
4145
+ * still considered removed and the orphaned blob is left for consumer-side
4146
+ * GC to reconcile.
4147
+ */
4148
+ readonly warning?: string;
1365
4149
  }
1366
4150
 
1367
4151
  /**
@@ -1372,6 +4156,53 @@ declare interface IRequiredMustacheTemplateOptions {
1372
4156
  readonly tags: [string, string];
1373
4157
  readonly includeComments: boolean;
1374
4158
  readonly includePartials: boolean;
4159
+ readonly escape: MustacheEscapeStrategy;
4160
+ }
4161
+
4162
+ /**
4163
+ * The resolved, merged wire parameters for an image generation request.
4164
+ * Built from the layered options and ready for provider-specific encoding.
4165
+ * @public
4166
+ */
4167
+ declare interface IResolvedImageOptions {
4168
+ /** Number of images to generate. */
4169
+ readonly n: number;
4170
+ /** Image size (OpenAI-style pixel strings). */
4171
+ readonly size?: string;
4172
+ /** Quality tier. */
4173
+ readonly quality?: string;
4174
+ /** Seed for reproducibility. */
4175
+ readonly seed?: number;
4176
+ readonly outputFormat?: string;
4177
+ readonly outputCompression?: number;
4178
+ readonly background?: string;
4179
+ readonly moderation?: string;
4180
+ readonly aspectRatio?: string;
4181
+ readonly resolution?: string;
4182
+ readonly geminiAspectRatio?: string;
4183
+ readonly otherParams?: JsonObject;
4184
+ }
4185
+
4186
+ /**
4187
+ * Resolved thinking wire parameters for a specific provider, after merging
4188
+ * all applicable config blocks. Ready for provider-specific wire encoding.
4189
+ *
4190
+ * Callers that pre-resolve thinking config outside of the standard streaming
4191
+ * helpers (e.g. `executeClientToolTurn`) accept this type via the
4192
+ * `resolvedThinking` parameter and pass it directly to the adapter layer.
4193
+ * @public
4194
+ */
4195
+ declare interface IResolvedThinkingConfig {
4196
+ /** Anthropic: effort level; emit-site converts to `thinking.budget_tokens` via `anthropicEffortToBudgetTokens`. */
4197
+ readonly anthropicEffort?: IAnthropicThinkingConfig['effort'];
4198
+ /** OpenAI Chat: reasoning_effort value; OpenAI Responses: reasoning.effort */
4199
+ readonly openAiEffort?: IOpenAiThinkingConfig['effort'];
4200
+ /** Gemini: generationConfig.thinkingConfig.thinkingBudget */
4201
+ readonly geminiThinkingBudget?: number;
4202
+ /** xAI: reasoning_effort value (omit for grok-4) */
4203
+ readonly xaiEffort?: IXAiThinkingConfig['effort'];
4204
+ /** Other/passthrough: merged verbatim into wire request */
4205
+ readonly otherParams?: JsonObject;
1375
4206
  }
1376
4207
 
1377
4208
  /**
@@ -1399,6 +4230,106 @@ declare function isKeyStoreFile(json: unknown): boolean;
1399
4230
  */
1400
4231
  declare const isoDate: Converter<Date, unknown>;
1401
4232
 
4233
+ /**
4234
+ * A `Converter` which converts an iso formatted string, a number or a `Date` object to
4235
+ * a `DateTime` object.
4236
+ * @public
4237
+ */
4238
+ declare const isoDateTime: Converter<DateTime, unknown>;
4239
+
4240
+ /**
4241
+ * Determines whether a concrete (already-resolved) model id must be invoked via
4242
+ * the OpenAI Responses API rather than chat completions.
4243
+ *
4244
+ * @remarks
4245
+ * Matches `modelId` against the descriptor's
4246
+ * {@link IAiProviderDescriptor.responsesOnlyModelPrefixes} by prefix. A provider
4247
+ * that declares no list (the common case) always returns `false`. Consulted by
4248
+ * both the completion (`callProviderCompletion`) and streaming
4249
+ * (`callProviderCompletionStream`) OpenAI dispatch branches so a Responses-only
4250
+ * model (e.g. `gpt-5.5-pro`) routes correctly even with no tools requested.
4251
+ *
4252
+ * @param descriptor - The provider descriptor supplying the prefix list.
4253
+ * @param modelId - The resolved concrete model id to test.
4254
+ * @returns `true` when `modelId` starts with any declared Responses-only prefix.
4255
+ * @public
4256
+ */
4257
+ declare function isResponsesOnlyModel(descriptor: IAiProviderDescriptor, modelId: string): boolean;
4258
+
4259
+ /**
4260
+ * Type guard for {@link CryptoUtils.MultibaseSpkiPublicKey}: a string matching
4261
+ * {@link CryptoUtils.MultibaseSpkiPublicKeyRegExp} (multibase `'m'` prefix + a
4262
+ * non-empty base64url-no-pad body) whose body also satisfies the base64url-no-pad
4263
+ * length rule shared with {@link CryptoUtils.base64UrlNoPadDecode}. This is a
4264
+ * structural *shape* check, not full validation — it does not decode the DER SPKI
4265
+ * or verify the key material/algorithm (a malformed-but-well-shaped string fails
4266
+ * later, with clear context, in {@link CryptoUtils.importPublicKeyFromMultibaseSpki}).
4267
+ *
4268
+ * @param value - The value to test.
4269
+ * @returns `true` if `value` is a well-formed multibase SPKI public key string.
4270
+ * @public
4271
+ */
4272
+ declare function isValidMultibaseSpkiPublicKey(value: unknown): value is MultibaseSpkiPublicKey;
4273
+
4274
+ /**
4275
+ * Thinking/reasoning mode configuration for a completion request.
4276
+ *
4277
+ * @remarks
4278
+ * The generic `effort` field covers the common-subset cross-provider vocabulary.
4279
+ * For provider-specific precision (Anthropic 'max', OpenAI 'xhigh', Gemini token
4280
+ * budgets, xAI effort-level tuning), use the `providers` array.
4281
+ *
4282
+ * Absence (or undefined) means "no thinking mode" — existing callers are unaffected.
4283
+ *
4284
+ * @public
4285
+ */
4286
+ declare interface IThinkingConfig {
4287
+ /**
4288
+ * Cross-provider effort level. Common-subset mapping:
4289
+ * - 'low': Anthropic effort:low | OpenAI effort:low | Gemini thinkingBudget:1024 | xAI reasoning_effort:low
4290
+ * - 'medium': effort:medium | effort:medium | thinkingBudget:4096 | reasoning_effort:medium
4291
+ * - 'high': effort:high | effort:high | thinkingBudget:8192 | reasoning_effort:high
4292
+ */
4293
+ readonly effort?: 'low' | 'medium' | 'high';
4294
+ /**
4295
+ * Optional per-provider precision blocks. Blocks for providers that don't
4296
+ * match the resolved model's provider are silently skipped.
4297
+ */
4298
+ readonly providers?: ReadonlyArray<IThinkingProviderConfig>;
4299
+ }
4300
+
4301
+ /**
4302
+ * Discriminated union of per-provider thinking config blocks.
4303
+ * @public
4304
+ */
4305
+ declare type IThinkingProviderConfig = IAnthropicThinkingOptions | IOpenAiThinkingOptions | IGeminiThinkingOptions | IXAiThinkingOptions | IOtherThinkingOptions;
4306
+
4307
+ /**
4308
+ * Decision returned by an {@link IExecuteClientToolTurnParams.onBeforeToolExecute}
4309
+ * gate for a single client-tool call.
4310
+ *
4311
+ * @remarks
4312
+ * - `{ action: 'proceed' }` — run the tool's `execute` normally.
4313
+ * - `{ action: 'deny', reason }` — do NOT run `execute`; a synthesized tool-result
4314
+ * carrying `reason` is fed into the continuation exactly like a normal result so
4315
+ * the model can react, and a `client-tool-result` event is emitted for the call.
4316
+ * The turn continues.
4317
+ *
4318
+ * A gate that wants to signal a hard error (as opposed to a deliberate deny) should
4319
+ * return `Result.fail` (or reject) from the callback. Note this is NOT the same as a
4320
+ * `tool.execute` failure: an `execute` failure yields an `isError` tool-result and the
4321
+ * **turn continues**, whereas a gate `fail`/reject **terminates the turn** — it fails
4322
+ * `nextTurn` (and emits an inline `error` event) rather than synthesizing a deny.
4323
+ *
4324
+ * @public
4325
+ */
4326
+ declare type IToolExecutionDecision = {
4327
+ readonly action: 'proceed';
4328
+ } | {
4329
+ readonly action: 'deny';
4330
+ readonly reason: string;
4331
+ };
4332
+
1402
4333
  /**
1403
4334
  * Represents a variable reference extracted from a Mustache template.
1404
4335
  * @public
@@ -1423,6 +4354,118 @@ declare interface IVariableRef {
1423
4354
  readonly isSection: boolean;
1424
4355
  }
1425
4356
 
4357
+ /**
4358
+ * Caller-supplied HKDF parameters that domain-separate one
4359
+ * {@link CryptoUtils.ICryptoProvider.wrapBytes | wrapBytes} call from another.
4360
+ * Two wraps that share recipient but differ on `salt` or `info` derive distinct
4361
+ * wrap keys, so callers should pick values that bind the wrap to its
4362
+ * application context (e.g. a content hash for `salt` and a secret name for
4363
+ * `info`).
4364
+ *
4365
+ * Both fields are required; pass an empty `Uint8Array` if the caller has no
4366
+ * value to bind on a given axis. Silent defaulting would hide protocol
4367
+ * mistakes, so the API does not pick defaults.
4368
+ * @public
4369
+ */
4370
+ declare interface IWrapBytesOptions {
4371
+ /**
4372
+ * HKDF salt. Domain-separates this wrap from others in different contexts.
4373
+ * Caller picks; common choices include a content hash, document id, channel
4374
+ * id, etc.
4375
+ */
4376
+ readonly salt: Uint8Array;
4377
+ /**
4378
+ * HKDF info. Further binds the derived key to a specific use within the
4379
+ * calling application. Caller picks; common choices include a secret name,
4380
+ * message type, or version tag.
4381
+ */
4382
+ readonly info: Uint8Array;
4383
+ }
4384
+
4385
+ /**
4386
+ * Output of {@link CryptoUtils.ICryptoProvider.wrapBytes | wrapBytes}. The
4387
+ * shape is JSON-serializable so it can travel directly over the wire or be
4388
+ * persisted as-is.
4389
+ * @public
4390
+ */
4391
+ declare interface IWrappedBytes {
4392
+ /**
4393
+ * Sender's ephemeral ECDH P-256 public key as a JSON Web Key. The matching
4394
+ * ephemeral private key is dropped after the shared-secret derive.
4395
+ */
4396
+ readonly ephemeralPublicKey: JsonWebKey;
4397
+ /**
4398
+ * AES-GCM nonce, base64-encoded. 12 bytes (96 bits) — the standard AES-GCM
4399
+ * nonce length.
4400
+ */
4401
+ readonly nonce: string;
4402
+ /**
4403
+ * AES-GCM ciphertext concatenated with the 16-byte authentication tag,
4404
+ * base64-encoded. Tampering with either the nonce or the ciphertext causes
4405
+ * unwrap to fail GCM authentication.
4406
+ */
4407
+ readonly ciphertext: string;
4408
+ }
4409
+
4410
+ /**
4411
+ * xAI-specific thinking configuration.
4412
+ * @public
4413
+ */
4414
+ declare interface IXAiThinkingConfig {
4415
+ /**
4416
+ * xAI reasoning effort. Maps 1:1 to `reasoning_effort` on the wire.
4417
+ * For grok-4, the adapter omits this field (grok-4 always reasons and
4418
+ * rejects the parameter).
4419
+ */
4420
+ readonly effort?: 'none' | 'low' | 'medium' | 'high';
4421
+ }
4422
+
4423
+ /**
4424
+ * xAI-specific thinking options block.
4425
+ * @public
4426
+ */
4427
+ declare interface IXAiThinkingOptions {
4428
+ readonly provider: 'xai';
4429
+ readonly models?: ReadonlyArray<XAiThinkingModelNames>;
4430
+ readonly config: IXAiThinkingConfig;
4431
+ }
4432
+
4433
+ /**
4434
+ * Options for YAML serialization, mirroring commonly-used `js-yaml` `DumpOptions`.
4435
+ * @public
4436
+ */
4437
+ declare interface IYamlSerializeOptions {
4438
+ /**
4439
+ * Indentation width in spaces (default: 2).
4440
+ */
4441
+ readonly indent?: number;
4442
+ /**
4443
+ * Nesting level at which to switch from block to flow style.
4444
+ * -1 means block style everywhere (default: -1).
4445
+ */
4446
+ readonly flowLevel?: number;
4447
+ /**
4448
+ * If true, sort keys when dumping (default: false).
4449
+ */
4450
+ readonly sortKeys?: boolean;
4451
+ /**
4452
+ * Maximum line width (default: 80).
4453
+ */
4454
+ readonly lineWidth?: number;
4455
+ /**
4456
+ * If true, don't convert duplicate objects into references (default: false).
4457
+ */
4458
+ readonly noRefs?: boolean;
4459
+ /**
4460
+ * If true, don't add an indentation level to array elements (default: false).
4461
+ */
4462
+ readonly noArrayIndent?: boolean;
4463
+ /**
4464
+ * If true, all non-key strings will be quoted (default: false).
4465
+ */
4466
+ readonly forceQuotes?: boolean;
4467
+ }
4468
+
1426
4469
  /**
1427
4470
  * Simple interface for a file to be added to a zip file.
1428
4471
  * @public
@@ -1452,11 +4495,54 @@ declare interface JarRecordParserOptions {
1452
4495
  readonly fixedContinuationSize?: number;
1453
4496
  }
1454
4497
 
4498
+ /**
4499
+ * Controls the optional system-prompt augmentation applied by
4500
+ * {@link AiAssist.generateJsonCompletion}.
4501
+ *
4502
+ * - `'smart'` (default): append {@link AiAssist.SMART_JSON_PROMPT_HINT}.
4503
+ * - `'none'`: do not modify the prompt.
4504
+ * - A string: append the supplied text verbatim.
4505
+ *
4506
+ * @remarks
4507
+ * The `string & {}` branch is the standard TypeScript trick that prevents
4508
+ * the literal members from being widened away — callers still get
4509
+ * autocomplete for `'smart'` and `'none'` while accepting any string.
4510
+ *
4511
+ * @public
4512
+ */
4513
+ declare type JsonPromptHint = 'smart' | 'none' | (string & {});
4514
+
4515
+ /**
4516
+ * A function that pulls a JSON-shaped substring out of arbitrary model text.
4517
+ * Implementations strip whatever wrappers the model added (fences, preamble,
4518
+ * trailing prose) and return the JSON-shaped substring ready for `JSON.parse`.
4519
+ * @public
4520
+ */
4521
+ declare type JsonTextExtractor = (text: string) => Result<string>;
4522
+
4523
+ /**
4524
+ * In-place shape check for a JSON Web Key. Asserts only that the input is a
4525
+ * non-array object whose `kty` discriminator is a string; every other JWK
4526
+ * field passes through untouched. This is intentionally **not** a true JWK
4527
+ * validator — per-algorithm correctness (RSA `n`/`e`, EC `crv`/`x`/`y`,
4528
+ * key-size constraints, etc.) is delegated to `crypto.subtle.importKey` at
4529
+ * first use, which is the authoritative checker. The "shape" suffix in the
4530
+ * name is the warning sign for readers expecting full validation.
4531
+ * @remarks
4532
+ * Built with `Validators.object` (in-place, non-strict) so unknown JWK fields
4533
+ * survive the round-trip; the cast to `FieldValidators<JsonWebKey>` is required
4534
+ * only because TypeScript's mapped type demands an entry for every key in
4535
+ * `JsonWebKey`. At runtime the `ObjectValidator` only inspects keys present in
4536
+ * the field-validators map.
4537
+ * @public
4538
+ */
4539
+ declare const jsonWebKeyShape: Validator<JsonWebKey>;
4540
+
1455
4541
  /**
1456
4542
  * Supported key derivation functions.
1457
4543
  * @public
1458
4544
  */
1459
- declare type KeyDerivationFunction = 'pbkdf2';
4545
+ declare type KeyDerivationFunction = 'pbkdf2' | 'argon2id';
1460
4546
 
1461
4547
  /**
1462
4548
  * Converter for {@link CryptoUtils.KeyDerivationFunction | key derivation function} type.
@@ -1466,22 +4552,74 @@ declare const keyDerivationFunction: Converter<KeyDerivationFunction>;
1466
4552
 
1467
4553
  /**
1468
4554
  * Converter for {@link CryptoUtils.IKeyDerivationParams | key derivation parameters}.
4555
+ * Handles both PBKDF2 and Argon2id discriminated union arms.
1469
4556
  * @public
1470
4557
  */
1471
4558
  declare const keyDerivationParams: Converter<IKeyDerivationParams>;
1472
4559
 
4560
+ /**
4561
+ * Asymmetric keypair algorithms supported by the crypto provider.
4562
+ * - `'ecdsa-p256'`: ECDSA over the P-256 curve, for signing.
4563
+ * - `'rsa-oaep-2048'`: RSA-OAEP, 2048-bit modulus with SHA-256, for encryption.
4564
+ * - `'ecdh-p256'`: ECDH over the P-256 curve, for key agreement
4565
+ * (e.g. as the recipient keypair in
4566
+ * {@link CryptoUtils.ICryptoProvider.wrapBytes | wrapBytes} /
4567
+ * {@link CryptoUtils.ICryptoProvider.unwrapBytes | unwrapBytes}).
4568
+ * - `'ed25519'`: EdDSA over the Edwards25519 curve, for signing.
4569
+ * Deterministic — the per-signature nonce is derived from the private key
4570
+ * and message rather than sampled randomly, eliminating the random-nonce
4571
+ * reuse risk that ECDSA carries. Distinct from X25519 (key agreement over
4572
+ * the Montgomery form, Curve25519).
4573
+ * - `'x25519'`: Diffie-Hellman key agreement over the Montgomery form of
4574
+ * Curve25519. Key-agreement only — use `deriveBits`/`deriveKey` to produce
4575
+ * a shared secret from one party's private key and the peer's public key.
4576
+ * Distinct from Ed25519 (which uses the twisted-Edwards form for signing).
4577
+ * @public
4578
+ */
4579
+ declare type KeyPairAlgorithm = 'ecdsa-p256' | 'rsa-oaep-2048' | 'ecdh-p256' | 'ed25519' | 'x25519';
4580
+
4581
+ /**
4582
+ * Converter for {@link CryptoUtils.KeyStore.KeyPairAlgorithm | key pair algorithm}.
4583
+ * @public
4584
+ */
4585
+ declare const keyPairAlgorithm: Converter<KeyPairAlgorithm>;
4586
+
4587
+ /**
4588
+ * Lookup table from {@link CryptoUtils.KeyPairAlgorithm} to the WebCrypto
4589
+ * parameters needed to drive `crypto.subtle`. Shared between every
4590
+ * {@link CryptoUtils.ICryptoProvider} implementation since both Node and
4591
+ * browser providers speak the same WebCrypto API. Exposed for downstream
4592
+ * provider implementations (e.g. browser-side providers in `@fgv/ts-web-extras`).
4593
+ * @public
4594
+ */
4595
+ declare const keyPairAlgorithmParams: Readonly<Record<KeyPairAlgorithm, IKeyPairAlgorithmParams>>;
4596
+
1473
4597
  declare namespace KeyStore {
1474
4598
  export {
1475
4599
  Converters_2 as Converters,
1476
4600
  KeyStore_2 as KeyStore,
4601
+ EncryptedFilePrivateKeyStorage,
4602
+ IEncryptedFilePrivateKeyStorageCreateParams,
1477
4603
  isKeyStoreFile,
4604
+ allKeyPairAlgorithms,
4605
+ KeyPairAlgorithm,
1478
4606
  KeyStoreFormat,
1479
4607
  KEYSTORE_FORMAT,
1480
4608
  DEFAULT_KEYSTORE_ITERATIONS,
1481
4609
  MIN_SALT_LENGTH,
4610
+ KeyStoreSymmetricSecretType,
4611
+ allKeyStoreSymmetricSecretTypes,
4612
+ KeyStoreAsymmetricSecretType,
4613
+ allKeyStoreAsymmetricSecretTypes,
1482
4614
  KeyStoreSecretType,
1483
4615
  allKeyStoreSecretTypes,
4616
+ IKeyStoreSymmetricEntry,
4617
+ IKeyStoreAsymmetricEntry,
4618
+ IKeyStoreEntry,
1484
4619
  IKeyStoreSecretEntry,
4620
+ IKeyStoreSymmetricEntryJson,
4621
+ IKeyStoreAsymmetricEntryJson,
4622
+ IKeyStoreEntryJson,
1485
4623
  IKeyStoreSecretEntryJson,
1486
4624
  IKeyStoreVaultContents,
1487
4625
  IKeyStoreFile,
@@ -1491,9 +4629,15 @@ declare namespace KeyStore {
1491
4629
  IAddSecretResult,
1492
4630
  IAddSecretOptions,
1493
4631
  IImportSecretOptions,
4632
+ IImportKeyOptions,
1494
4633
  IAddSecretFromPasswordOptions,
1495
4634
  DEFAULT_SECRET_ITERATIONS,
1496
- IAddSecretFromPasswordResult
4635
+ IAddSecretFromPasswordResult,
4636
+ IAddSecretFromPasswordArgon2idOptions,
4637
+ IAddKeyPairOptions,
4638
+ IAddKeyPairResult,
4639
+ IRemoveSecretResult,
4640
+ IPrivateKeyStorage
1497
4641
  }
1498
4642
  }
1499
4643
 
@@ -1530,6 +4674,7 @@ declare namespace KeyStore {
1530
4674
  */
1531
4675
  declare class KeyStore_2 implements IEncryptionProvider {
1532
4676
  private readonly _cryptoProvider;
4677
+ private readonly _privateKeyStorage;
1533
4678
  private readonly _iterations;
1534
4679
  private _keystoreFile;
1535
4680
  private _salt;
@@ -1571,6 +4716,21 @@ declare class KeyStore_2 implements IEncryptionProvider {
1571
4716
  * @public
1572
4717
  */
1573
4718
  unlock(password: string): Promise<Result<KeyStore_2>>;
4719
+ /**
4720
+ * Unlocks an existing key store with a pre-derived key, bypassing
4721
+ * PBKDF2 key derivation. Use this when the derived key has been
4722
+ * stored externally (e.g., in another key store) and the original
4723
+ * password is no longer available.
4724
+ *
4725
+ * The supplied key must have been derived from the correct password
4726
+ * using the key store file's own PBKDF2 parameters (salt and
4727
+ * iteration count).
4728
+ *
4729
+ * @param derivedKey - The pre-derived master key (32 bytes for AES-256)
4730
+ * @returns Success with this instance when unlocked, Failure if key is incorrect
4731
+ * @public
4732
+ */
4733
+ unlockWithKey(derivedKey: Uint8Array): Promise<Result<KeyStore_2>>;
1574
4734
  /**
1575
4735
  * Locks the key store, clearing all secrets from memory.
1576
4736
  * @param force - If true, discards unsaved changes
@@ -1613,12 +4773,23 @@ declare class KeyStore_2 implements IEncryptionProvider {
1613
4773
  */
1614
4774
  listSecrets(): Result<readonly string[]>;
1615
4775
  /**
1616
- * Gets a secret by name.
4776
+ * Gets a secret by name. Returns the {@link CryptoUtils.KeyStore.IKeyStoreEntry | discriminated union}
4777
+ * — callers must check `entry.type` before accessing `key`/`id` since asymmetric
4778
+ * entries carry no raw key material.
1617
4779
  * @param name - Name of the secret
1618
4780
  * @returns Success with secret entry, Failure if not found or locked
1619
4781
  * @public
1620
4782
  */
1621
- getSecret(name: string): Result<IKeyStoreSecretEntry>;
4783
+ getSecret(name: string): Result<IKeyStoreEntry>;
4784
+ /**
4785
+ * Returns the public-key JWK for an asymmetric-keypair entry.
4786
+ * Available without {@link CryptoUtils.KeyStore.IPrivateKeyStorage} since the
4787
+ * public key lives in the vault metadata directly.
4788
+ * @param name - Name of the entry
4789
+ * @returns Success with the JWK, Failure if not found, locked, or wrong type
4790
+ * @public
4791
+ */
4792
+ getPublicKeyJwk(name: string): Result<JsonWebKey>;
1622
4793
  /**
1623
4794
  * Checks if a secret exists.
1624
4795
  * @param name - Name of the secret
@@ -1635,14 +4806,20 @@ declare class KeyStore_2 implements IEncryptionProvider {
1635
4806
  */
1636
4807
  addSecret(name: string, options?: IAddSecretOptions): Promise<Result<IAddSecretResult>>;
1637
4808
  /**
1638
- * Imports an existing secret key.
4809
+ * Imports raw 32-byte key material into the vault.
4810
+ *
4811
+ * Always validates that the key is exactly 32 bytes (AES-256). The optional
4812
+ * `type` field is a classification label stored with the entry; it does not
4813
+ * change the validation rules. For importing UTF-8 API key strings (variable
4814
+ * length), use {@link KeyStore.importApiKey} instead.
4815
+ *
1639
4816
  * @param name - Unique name for the secret
1640
- * @param key - The 32-byte AES-256 key
1641
- * @param options - Optional description, whether to replace existing
4817
+ * @param key - The 32-byte AES-256 key material
4818
+ * @param options - Optional type classification, description, whether to replace existing
1642
4819
  * @returns Success with entry, Failure if locked, key invalid, or exists and !replace
1643
4820
  * @public
1644
4821
  */
1645
- importSecret(name: string, key: Uint8Array, options?: IImportSecretOptions): Result<IAddSecretResult>;
4822
+ importSecret(name: string, key: Uint8Array, options?: IImportKeyOptions): Promise<Result<IAddSecretResult>>;
1646
4823
  /**
1647
4824
  * Adds a secret derived from a password using PBKDF2.
1648
4825
  *
@@ -1659,12 +4836,81 @@ declare class KeyStore_2 implements IEncryptionProvider {
1659
4836
  */
1660
4837
  addSecretFromPassword(name: string, password: string, options?: IAddSecretFromPasswordOptions): Promise<Result<IAddSecretFromPasswordResult>>;
1661
4838
  /**
1662
- * Removes a secret by name.
4839
+ * Verifies that a candidate password derives the same key material currently
4840
+ * stored under `name`, using the supplied
4841
+ * {@link CryptoUtils.IKeyDerivationParams | key derivation parameters}.
4842
+ *
4843
+ * The keystore does not persist per-slot key derivation parameters with the
4844
+ * entry — callers receive them from `addSecretFromPassword` and store them
4845
+ * alongside the encrypted artifact (or wherever else makes sense). Pass
4846
+ * those same parameters here for verification.
4847
+ *
4848
+ * Re-derives a key from `password` + `keyDerivation`, then compares it to
4849
+ * the stored key material in constant time. Restricted to entries of type
4850
+ * `'encryption-key'` — the type produced by `addSecretFromPassword`. Other
4851
+ * symmetric types (`'api-key'`) and asymmetric entries are rejected so
4852
+ * the boolean result reflects "this slot accepts this password" rather
4853
+ * than an incidental byte-equality match against unrelated material.
4854
+ *
4855
+ * Note: the keystore does not currently flag whether an `'encryption-key'`
4856
+ * entry was actually password-derived (vs. random via `addSecret` or raw
4857
+ * via `importSecret`). A `true` result therefore means "the candidate
4858
+ * password produces the same 32 bytes currently stored", which is what
4859
+ * the equivalent consumer-side helper (`verifyGatePassword`) already
4860
+ * implies for entries it manages.
4861
+ *
4862
+ * @param name - Name of the secret to verify against
4863
+ * @param password - Candidate password to test
4864
+ * @param keyDerivation - The key derivation parameters returned by
4865
+ * `addSecretFromPassword` when the secret was created. Only
4866
+ * `kdf: 'pbkdf2'` is supported.
4867
+ * @returns Success(true) when the candidate matches the stored key,
4868
+ * Success(false) when it does not, Failure if locked, secret missing,
4869
+ * wrong type, unsupported `kdf`, or key derivation fails
4870
+ * @public
4871
+ */
4872
+ verifySecretFromPassword(name: string, password: string, keyDerivation: IKeyDerivationParams): Promise<Result<boolean>>;
4873
+ /**
4874
+ * Adds a secret derived from a password using Argon2id (RFC 9106).
4875
+ *
4876
+ * The Argon2id provider must be supplied explicitly; the KeyStore does not
4877
+ * hold one by default (consumers opt in by depending on the argon2 package).
4878
+ *
4879
+ * Returns the key derivation parameters so callers can store them alongside
4880
+ * encrypted artifacts, enabling future re-derivation and verification.
4881
+ *
4882
+ * @param name - Unique name for the secret
4883
+ * @param password - Password or passphrase
4884
+ * @param argon2idProvider - Argon2id provider (Node or Browser implementation)
4885
+ * @param options - Optional: Argon2id params (defaults to ARGON2ID_OWASP_MIN), description, replace flag
4886
+ * @returns Success with entry and keyDerivation params, Failure if locked or invalid
4887
+ * @public
4888
+ */
4889
+ addSecretFromPasswordArgon2id(name: string, password: string, argon2idProvider: IArgon2idProvider, options?: IAddSecretFromPasswordArgon2idOptions): Promise<Result<IAddSecretFromPasswordResult>>;
4890
+ /**
4891
+ * Verifies a candidate password against an Argon2id-derived entry using the
4892
+ * supplied key derivation parameters. Constant-time comparison.
4893
+ *
4894
+ * @param name - Name of the secret to verify against
4895
+ * @param password - Candidate password to test
4896
+ * @param argon2idProvider - Argon2id provider (must produce bit-identical output for identical inputs)
4897
+ * @param keyDerivation - The Argon2id key derivation parameters returned by `addSecretFromPasswordArgon2id`
4898
+ * @returns Success(true) if candidate matches stored key, Success(false) if not,
4899
+ * Failure if locked, secret missing, wrong type, or derivation fails
4900
+ * @public
4901
+ */
4902
+ verifySecretFromPasswordArgon2id(name: string, password: string, argon2idProvider: IArgon2idProvider, keyDerivation: IArgon2idKeyDerivationParams): Promise<Result<boolean>>;
4903
+ /**
4904
+ * Removes a secret by name. Vault-first: the in-memory vault entry is dropped
4905
+ * before any storage cleanup runs. For asymmetric-keypair entries, best-effort
4906
+ * calls {@link CryptoUtils.KeyStore.IPrivateKeyStorage}.delete on the entry's
4907
+ * `id`; a failure is reported via `warning` on the result but does not roll
4908
+ * back the vault removal.
1663
4909
  * @param name - Name of the secret to remove
1664
- * @returns Success with removed entry, Failure if not found or locked
4910
+ * @returns Success with removed entry (and optional warning), Failure if not found or locked
1665
4911
  * @public
1666
4912
  */
1667
- removeSecret(name: string): Result<IKeyStoreSecretEntry>;
4913
+ removeSecret(name: string): Promise<Result<IRemoveSecretResult>>;
1668
4914
  /**
1669
4915
  * Imports an API key string into the vault.
1670
4916
  * The string is UTF-8 encoded and stored with type `'api-key'`.
@@ -1674,7 +4920,7 @@ declare class KeyStore_2 implements IEncryptionProvider {
1674
4920
  * @returns Success with entry, Failure if locked, empty, or exists and !replace
1675
4921
  * @public
1676
4922
  */
1677
- importApiKey(name: string, apiKey: string, options?: IImportSecretOptions): Result<IAddSecretResult>;
4923
+ importApiKey(name: string, apiKey: string, options?: IImportSecretOptions): Promise<Result<IAddSecretResult>>;
1678
4924
  /**
1679
4925
  * Retrieves an API key string by name.
1680
4926
  * Only works for secrets with type `'api-key'`.
@@ -1683,6 +4929,48 @@ declare class KeyStore_2 implements IEncryptionProvider {
1683
4929
  * @public
1684
4930
  */
1685
4931
  getApiKey(name: string): Result<string>;
4932
+ /**
4933
+ * Adds a new asymmetric keypair to the vault. Storage-first: the private key
4934
+ * is stored under a freshly-minted `id` before the public-key vault entry is
4935
+ * committed. If the storage call fails, no vault entry is written and the
4936
+ * operation returns Failure.
4937
+ *
4938
+ * When `replace: true` displaces an existing entry (asymmetric or symmetric),
4939
+ * a fresh `id` is minted; the displaced entry's resources are released
4940
+ * best-effort. Failure of the storage delete is reported via `warning` on the
4941
+ * result but does not roll back the replacement.
4942
+ *
4943
+ * Requires a {@link CryptoUtils.KeyStore.IPrivateKeyStorage} backend
4944
+ * supplied at construction.
4945
+ *
4946
+ * Extractability of the generated private key defaults to the storage
4947
+ * backend's {@link CryptoUtils.KeyStore.IPrivateKeyStorage.supportsNonExtractable}.
4948
+ * `options.extractable` overrides that default for this key only; requesting
4949
+ * `extractable: false` against a backend that cannot store non-extractable
4950
+ * keys fails loudly rather than silently generating an extractable key.
4951
+ *
4952
+ * @param name - Unique name for the entry
4953
+ * @param options - Algorithm, optional description, replace flag, extractable override
4954
+ * @returns Success with the new entry, Failure if locked, no provider, storage write failed,
4955
+ * or the requested extractability cannot be honored by the backend
4956
+ * @public
4957
+ */
4958
+ addKeyPair(name: string, options: IAddKeyPairOptions): Promise<Result<IAddKeyPairResult>>;
4959
+ /**
4960
+ * Retrieves the keypair for an asymmetric-keypair entry. The private key is
4961
+ * loaded from {@link CryptoUtils.KeyStore.IPrivateKeyStorage} on every call —
4962
+ * the keystore never caches private `CryptoKey` references between calls.
4963
+ * The public key is re-imported from the vault's JWK so callers always
4964
+ * receive a `CryptoKey` rather than the JWK form.
4965
+ * @param name - Name of the entry
4966
+ * @returns Success with `{ publicKey, privateKey }`, Failure if not found,
4967
+ * locked, wrong type, no provider, or storage load failed.
4968
+ * @public
4969
+ */
4970
+ getKeyPair(name: string): Promise<Result<{
4971
+ publicKey: CryptoKey;
4972
+ privateKey: CryptoKey;
4973
+ }>>;
1686
4974
  /**
1687
4975
  * Lists secret names filtered by type.
1688
4976
  * @param type - The secret type to filter by
@@ -1697,7 +4985,7 @@ declare class KeyStore_2 implements IEncryptionProvider {
1697
4985
  * @returns Success with updated entry, Failure if source not found, target exists, or locked
1698
4986
  * @public
1699
4987
  */
1700
- renameSecret(oldName: string, newName: string): Result<IKeyStoreSecretEntry>;
4988
+ renameSecret(oldName: string, newName: string): Result<IKeyStoreEntry>;
1701
4989
  /**
1702
4990
  * Saves the key store, returning the encrypted file content.
1703
4991
  * Requires the master password to encrypt.
@@ -1706,6 +4994,20 @@ declare class KeyStore_2 implements IEncryptionProvider {
1706
4994
  * @public
1707
4995
  */
1708
4996
  save(password: string): Promise<Result<IKeyStoreFile>>;
4997
+ /**
4998
+ * Saves the key store using a pre-derived key, bypassing PBKDF2 key
4999
+ * derivation. Use this when the derived key has been stored externally
5000
+ * (e.g., in another key store) and the original password is no longer
5001
+ * available.
5002
+ *
5003
+ * The supplied key must be the same key that was (or would be) derived
5004
+ * from the master password using the key store's PBKDF2 parameters.
5005
+ *
5006
+ * @param derivedKey - The pre-derived master key (32 bytes for AES-256)
5007
+ * @returns Success with IKeyStoreFile, Failure if locked or key invalid
5008
+ * @public
5009
+ */
5010
+ saveWithKey(derivedKey: Uint8Array): Promise<Result<IKeyStoreFile>>;
1709
5011
  /**
1710
5012
  * Changes the master password.
1711
5013
  * Re-encrypts the vault with the new password-derived key.
@@ -1730,6 +5032,40 @@ declare class KeyStore_2 implements IEncryptionProvider {
1730
5032
  * @public
1731
5033
  */
1732
5034
  getEncryptionConfig(): Result<Pick<IEncryptionConfig, 'secretProvider' | 'cryptoProvider'>>;
5035
+ /**
5036
+ * Encrypts the vault with a derived key and returns the key store file.
5037
+ * Shared by `save()` and `saveWithKey()`.
5038
+ */
5039
+ private _encryptVault;
5040
+ /**
5041
+ * Decrypts the vault with a derived key and loads secrets into memory.
5042
+ * Shared by `unlock()` and `unlockWithKey()`.
5043
+ */
5044
+ private _decryptVault;
5045
+ /**
5046
+ * Releases the resources held by an entry being displaced from the vault.
5047
+ * Symmetric entries get their key buffer zeroed in place. Asymmetric entries
5048
+ * have their private-key blob best-effort deleted from
5049
+ * {@link CryptoUtils.KeyStore.IPrivateKeyStorage}; if the storage call fails,
5050
+ * a warning string is returned but the displacement still proceeds — the
5051
+ * orphaned blob is left for consumer-side GC. Without a configured provider,
5052
+ * asymmetric cleanup is silently skipped.
5053
+ * @returns A warning string if storage cleanup failed, otherwise undefined.
5054
+ */
5055
+ private _releaseEntryResources;
5056
+ /**
5057
+ * Constant-time byte comparison. Returns false immediately for length
5058
+ * mismatch (length is not secret); for equal-length inputs, walks the full
5059
+ * buffer accumulating differences via XOR so the running time does not leak
5060
+ * the position of the first differing byte.
5061
+ */
5062
+ private static _timingSafeEqual;
5063
+ /**
5064
+ * Mints a fresh UUID v4 storage handle using the crypto provider's
5065
+ * {@link CryptoUtils.ICryptoProvider.generateRandomBytes | generateRandomBytes}.
5066
+ * Random-bytes failures propagate as Failure.
5067
+ */
5068
+ private _generateId;
1733
5069
  }
1734
5070
 
1735
5071
  /**
@@ -1738,6 +5074,31 @@ declare class KeyStore_2 implements IEncryptionProvider {
1738
5074
  */
1739
5075
  declare const KEYSTORE_FORMAT: KeyStoreFormat;
1740
5076
 
5077
+ /**
5078
+ * Converter for {@link CryptoUtils.KeyStore.IKeyStoreAsymmetricEntryJson | asymmetric keypair entry} in JSON form.
5079
+ * The `publicKeyJwk` field passes through {@link CryptoUtils.KeyStore.Converters.jsonWebKeyShape | jsonWebKeyShape}
5080
+ * (shape check only — see its docs); cryptographic correctness is enforced by
5081
+ * `crypto.subtle.importKey` at use.
5082
+ * @public
5083
+ */
5084
+ declare const keystoreAsymmetricEntryJson: Converter<IKeyStoreAsymmetricEntryJson>;
5085
+
5086
+ /**
5087
+ * Discriminator for asymmetric secret types stored in the vault.
5088
+ * - `'asymmetric-keypair'`: A public/private key pair. The public key is held in
5089
+ * the vault as a JWK; the private key lives in the supplied
5090
+ * {@link CryptoUtils.KeyStore.IPrivateKeyStorage} provider.
5091
+ * @public
5092
+ */
5093
+ declare type KeyStoreAsymmetricSecretType = 'asymmetric-keypair';
5094
+
5095
+ /**
5096
+ * Converter for {@link CryptoUtils.KeyStore.KeyStoreAsymmetricSecretType | asymmetric secret type} discriminator.
5097
+ * Accepts only `'asymmetric-keypair'`.
5098
+ * @public
5099
+ */
5100
+ declare const keystoreAsymmetricSecretType: Converter<KeyStoreAsymmetricSecretType>;
5101
+
1741
5102
  /**
1742
5103
  * Converter for {@link CryptoUtils.KeyStore.IKeyStoreFile | encrypted key store file}.
1743
5104
  * @public
@@ -1763,25 +5124,59 @@ declare const keystoreFormat: Converter<KeyStoreFormat>;
1763
5124
  declare type KeyStoreLockState = 'locked' | 'unlocked';
1764
5125
 
1765
5126
  /**
1766
- * Converter for {@link CryptoUtils.KeyStore.IKeyStoreSecretEntryJson | key store secret entry} in JSON format.
1767
- * The `type` field is optional for backwards compatibility — missing means `'encryption-key'`.
5127
+ * Discriminated-union converter for any {@link CryptoUtils.KeyStore.IKeyStoreEntryJson | key store entry} in JSON form.
5128
+ * Routes by the `type` field: `'asymmetric-keypair'` is parsed by
5129
+ * {@link CryptoUtils.KeyStore.Converters.keystoreAsymmetricEntryJson | keystoreAsymmetricEntryJson},
5130
+ * anything else (including a missing `type` field for backwards compatibility) by
5131
+ * {@link CryptoUtils.KeyStore.Converters.keystoreSymmetricEntryJson | keystoreSymmetricEntryJson}.
1768
5132
  * @public
1769
5133
  */
1770
- declare const keystoreSecretEntryJson: Converter<IKeyStoreSecretEntryJson>;
5134
+ declare const keystoreSecretEntryJson: Converter<IKeyStoreEntryJson>;
1771
5135
 
1772
5136
  /**
1773
- * Discriminator for secret types stored in the vault.
5137
+ * Discriminator for any secret type stored in the vault.
5138
+ * @public
5139
+ */
5140
+ declare type KeyStoreSecretType = KeyStoreSymmetricSecretType | KeyStoreAsymmetricSecretType;
5141
+
5142
+ /**
5143
+ * Converter for {@link CryptoUtils.KeyStore.KeyStoreSecretType | any key store secret type} discriminator.
5144
+ * Accepts both symmetric and asymmetric type values.
5145
+ * @public
5146
+ */
5147
+ declare const keystoreSecretType: Converter<KeyStoreSecretType>;
5148
+
5149
+ /**
5150
+ * Converter for {@link CryptoUtils.KeyStore.IKeyStoreSymmetricEntryJson | symmetric secret entry} in JSON form.
5151
+ *
5152
+ * @remarks
5153
+ * Backwards compatibility with vaults written before asymmetric-keypair
5154
+ * support: those entries may lack the `type` discriminator on the wire. To
5155
+ * keep the model type honest (`type` is required on
5156
+ * {@link CryptoUtils.KeyStore.IKeyStoreSymmetricEntryJson}, see its docs),
5157
+ * we declare `type` in `optionalFields` so the inner `Converters.object` will
5158
+ * accept input without it, then `.map()` injects the default
5159
+ * `'encryption-key'` when missing. The output therefore always carries the
5160
+ * discriminator and downstream code never sees the legacy missing-type form.
5161
+ *
5162
+ * @public
5163
+ */
5164
+ declare const keystoreSymmetricEntryJson: Converter<IKeyStoreSymmetricEntryJson>;
5165
+
5166
+ /**
5167
+ * Discriminator for symmetric secret types stored in the vault.
1774
5168
  * - `'encryption-key'`: A 32-byte AES-256 encryption key.
1775
5169
  * - `'api-key'`: An arbitrary-length API key string (UTF-8 encoded).
1776
5170
  * @public
1777
5171
  */
1778
- declare type KeyStoreSecretType = 'encryption-key' | 'api-key';
5172
+ declare type KeyStoreSymmetricSecretType = 'encryption-key' | 'api-key';
1779
5173
 
1780
5174
  /**
1781
- * Converter for {@link CryptoUtils.KeyStore.KeyStoreSecretType | key store secret type} discriminator.
5175
+ * Converter for {@link CryptoUtils.KeyStore.KeyStoreSymmetricSecretType | symmetric secret type} discriminator.
5176
+ * Accepts only `'encryption-key'` and `'api-key'`.
1782
5177
  * @public
1783
5178
  */
1784
- declare const keystoreSecretType: Converter<KeyStoreSecretType>;
5179
+ declare const keystoreSymmetricSecretType: Converter<KeyStoreSymmetricSecretType>;
1785
5180
 
1786
5181
  /**
1787
5182
  * Converter for {@link CryptoUtils.KeyStore.IKeyStoreVaultContents | key store vault contents} (decrypted state).
@@ -1805,6 +5200,18 @@ declare class Md5Normalizer extends Hash_2.HashingNormalizer {
1805
5200
  */
1806
5201
  declare const MIN_SALT_LENGTH: number;
1807
5202
 
5203
+ /**
5204
+ * Marker prefix for an fgv model alias.
5205
+ *
5206
+ * @remarks
5207
+ * A model string is an fgv alias **iff** it begins with this sigil. Everything
5208
+ * else is a raw provider model id and passes through {@link resolveModelAlias}
5209
+ * untouched — this is what keeps the alias layer back-compatible (no current
5210
+ * `defaultModel`, `modelOverride`, or self-hosted `model:tag` id starts with `@`).
5211
+ * @public
5212
+ */
5213
+ declare const MODEL_ALIAS_SIGIL: '@';
5214
+
1808
5215
  /**
1809
5216
  * Default context key used as fallback when resolving a {@link ModelSpec}.
1810
5217
  * @public
@@ -1829,7 +5236,7 @@ declare const modelSpec: Converter<ModelSpec>;
1829
5236
  * Known context keys for model specification maps.
1830
5237
  * @public
1831
5238
  */
1832
- declare type ModelSpecKey = 'base' | 'tools' | 'image';
5239
+ declare type ModelSpecKey = 'base' | 'advanced' | 'frontier' | 'image' | 'embedding';
1833
5240
 
1834
5241
  /**
1835
5242
  * Converter for {@link ModelSpecKey}.
@@ -1837,18 +5244,98 @@ declare type ModelSpecKey = 'base' | 'tools' | 'image';
1837
5244
  */
1838
5245
  declare const modelSpecKey: Converter<ModelSpecKey>;
1839
5246
 
5247
+ /**
5248
+ * Decodes a multibase base64url (no-padding) string back to a `Uint8Array`.
5249
+ *
5250
+ * Validates that the first character is `'m'` (the multibase prefix for
5251
+ * RFC 4648 base64url without padding), then decodes the remaining body.
5252
+ *
5253
+ * @param encoded - A multibase-prefixed base64url string.
5254
+ * @returns `Success` with the decoded bytes, or `Failure` with error context.
5255
+ * @public
5256
+ */
5257
+ declare function multibaseBase64UrlDecode(encoded: string): Result<Uint8Array>;
5258
+
5259
+ /**
5260
+ * Encodes a `Uint8Array` as a multibase base64url (no-padding) string.
5261
+ *
5262
+ * The multibase prefix `'m'` identifies the encoding as RFC 4648 base64url
5263
+ * without padding. The body uses base64url alphabet: `+` → `-`, `/` → `_`,
5264
+ * and trailing `=` padding is stripped.
5265
+ *
5266
+ * @param data - The binary data to encode.
5267
+ * @returns A multibase-prefixed base64url string (`'m' + base64url-no-pad`).
5268
+ * @public
5269
+ */
5270
+ declare function multibaseBase64UrlEncode(data: Uint8Array): string;
5271
+
5272
+ /**
5273
+ * A multibase base64url-encoded SPKI (SubjectPublicKeyInfo) public key string —
5274
+ * a `'m'` multibase prefix followed by a base64url-no-pad body. Produced by
5275
+ * {@link CryptoUtils.exportPublicKeyAsMultibaseSpki} and consumed by
5276
+ * {@link CryptoUtils.importPublicKeyFromMultibaseSpki}. Obtain the brand at a
5277
+ * boundary via {@link CryptoUtils.isValidMultibaseSpkiPublicKey} or the
5278
+ * {@link CryptoUtils.Converters.multibaseSpkiPublicKey} converter.
5279
+ * @public
5280
+ */
5281
+ declare type MultibaseSpkiPublicKey = Brand<string, 'MultibaseSpkiPublicKey'>;
5282
+
5283
+ /**
5284
+ * Converter for {@link CryptoUtils.MultibaseSpkiPublicKey | multibase SPKI public key} strings.
5285
+ * Validates that the value is a string with the `'m'` multibase prefix and a well-formed
5286
+ * base64url-no-pad body, and yields the branded value. Fails with context on a non-string,
5287
+ * bad-prefix, or malformed-body input.
5288
+ * @public
5289
+ */
5290
+ declare const multibaseSpkiPublicKey: Converter<MultibaseSpkiPublicKey>;
5291
+
5292
+ /**
5293
+ * The structural *shape* of a {@link CryptoUtils.MultibaseSpkiPublicKey}: the
5294
+ * multibase `'m'` prefix followed by a non-empty base64url-no-pad body
5295
+ * (`A-Z`, `a-z`, `0-9`, `-`, `_`).
5296
+ *
5297
+ * This is a shape prefilter, not full validation: it does not decode the DER
5298
+ * SPKI or verify the key material or algorithm (that happens in
5299
+ * {@link CryptoUtils.importPublicKeyFromMultibaseSpki}). The authoritative guard
5300
+ * is {@link CryptoUtils.isValidMultibaseSpkiPublicKey}, which enforces this
5301
+ * pattern **and** additionally rejects a body whose length is an impossible
5302
+ * base64 remainder. Exposed for callers that need the pattern directly (e.g. a
5303
+ * JSON-schema `pattern` field); prefer the guard/converter for validation.
5304
+ *
5305
+ * @public
5306
+ */
5307
+ declare const MultibaseSpkiPublicKeyRegExp: RegExp;
5308
+
1840
5309
  declare namespace Mustache {
1841
5310
  export {
1842
5311
  IContextValidationResult,
1843
5312
  IMissingVariableDetail,
1844
5313
  IMustacheTemplateOptions,
1845
5314
  IVariableRef,
5315
+ MustacheEscapeStrategy,
1846
5316
  MustacheTokenType,
1847
5317
  MustacheTemplate
1848
5318
  }
1849
5319
  }
1850
5320
  export { Mustache }
1851
5321
 
5322
+ /**
5323
+ * Strategy applied to double-brace `{{name}}` tokens at render time.
5324
+ *
5325
+ * - `'html'`: the standard mustache.js HTML escape (back-compat default).
5326
+ * - `'none'`: verbatim passthrough — values are interpolated as-is
5327
+ * (coerced to `String`). Suitable for LLM-prompt rendering and other
5328
+ * non-HTML targets where `& → &amp;` corrupts the output.
5329
+ * - `(value) => string`: caller-supplied escape function.
5330
+ *
5331
+ * Note: triple-brace `{{{name}}}` (and `{{&name}}`) tokens are always
5332
+ * rendered unescaped regardless of this strategy — that is the standard
5333
+ * mustache.js semantics and is not affected by this option.
5334
+ *
5335
+ * @public
5336
+ */
5337
+ declare type MustacheEscapeStrategy = 'html' | 'none' | ((value: string) => string);
5338
+
1852
5339
  /**
1853
5340
  * A helper class for working with Mustache templates that provides
1854
5341
  * validation, variable extraction, and context validation utilities.
@@ -1864,6 +5351,8 @@ declare class MustacheTemplate {
1864
5351
  */
1865
5352
  readonly options: Readonly<IRequiredMustacheTemplateOptions>;
1866
5353
  private readonly _tokens;
5354
+ private readonly _writer;
5355
+ private readonly _escapeFn;
1867
5356
  private _variables?;
1868
5357
  private constructor();
1869
5358
  /**
@@ -1971,12 +5460,24 @@ declare class NodeCryptoProvider implements ICryptoProvider {
1971
5460
  * @returns `Success` with derived 32-byte key, or `Failure` with an error.
1972
5461
  */
1973
5462
  deriveKey(password: string, salt: Uint8Array, iterations: number): Promise<Result<Uint8Array>>;
5463
+ /**
5464
+ * Computes a SHA-256 hash of the given data.
5465
+ * @param data - UTF-8 string to hash
5466
+ * @returns `Success` with hex-encoded hash string, or `Failure` with an error.
5467
+ */
5468
+ sha256(data: string): Promise<Result<string>>;
1974
5469
  /**
1975
5470
  * Generates cryptographically secure random bytes.
1976
5471
  * @param length - Number of bytes to generate
1977
5472
  * @returns Success with random bytes, or Failure with error
1978
5473
  */
1979
5474
  generateRandomBytes(length: number): Result<Uint8Array>;
5475
+ /**
5476
+ * Generates a cryptographically random UUIDv4 via the platform Web Crypto API.
5477
+ * @returns `Success` with the generated UUID, or `Failure` if the runtime
5478
+ * does not expose `globalThis.crypto.randomUUID`.
5479
+ */
5480
+ generateUuid(): Result<Uuid>;
1980
5481
  /**
1981
5482
  * Encodes binary data to base64 string.
1982
5483
  * @param data - Binary data to encode
@@ -1989,6 +5490,102 @@ declare class NodeCryptoProvider implements ICryptoProvider {
1989
5490
  * @returns Success with decoded bytes, or Failure if invalid base64
1990
5491
  */
1991
5492
  fromBase64(base64: string): Result<Uint8Array>;
5493
+ /**
5494
+ * Generates a new asymmetric keypair using Node's WebCrypto.
5495
+ * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm | algorithm} to use.
5496
+ * @param extractable - Whether the resulting keys may be exported.
5497
+ * @returns `Success` with the generated `CryptoKeyPair`, or `Failure` with an error.
5498
+ */
5499
+ generateKeyPair(algorithm: KeyPairAlgorithm, extractable: boolean): Promise<Result<CryptoKeyPair>>;
5500
+ /**
5501
+ * Exports a public `CryptoKey` as a JSON Web Key.
5502
+ * @remarks
5503
+ * Rejects non-public keys at runtime. WebCrypto's `exportKey('jwk', ...)`
5504
+ * does not enforce public-vs-private; without this guard a caller that
5505
+ * passed an extractable private key would receive its private fields
5506
+ * (`d`, `p`, `q`, ...) as JWK, defeating the method's name.
5507
+ * @param publicKey - Extractable public key to export.
5508
+ * @returns `Success` with the JWK, or `Failure` if not a public key or if export fails.
5509
+ */
5510
+ exportPublicKeyJwk(publicKey: CryptoKey): Promise<Result<JsonWebKey>>;
5511
+ /**
5512
+ * Imports a public-key JWK as a `CryptoKey` for the requested algorithm.
5513
+ * @param jwk - The JSON Web Key produced by a prior export.
5514
+ * @param algorithm - The algorithm the key was generated for.
5515
+ * @returns `Success` with the imported public `CryptoKey`, or `Failure` with an error.
5516
+ */
5517
+ importPublicKeyJwk(jwk: JsonWebKey, algorithm: KeyPairAlgorithm): Promise<Result<CryptoKey>>;
5518
+ /**
5519
+ * Exports a public `CryptoKey` as a DER-encoded SPKI blob.
5520
+ * @param publicKey - The public `CryptoKey` to export.
5521
+ * @returns `Success` with the raw SPKI bytes, or `Failure` with error context.
5522
+ */
5523
+ exportPublicKeySpki(publicKey: CryptoKey): Promise<Result<Uint8Array>>;
5524
+ /**
5525
+ * Imports a public key from a DER-encoded SPKI blob.
5526
+ * @param spkiBytes - The raw SPKI bytes.
5527
+ * @param algorithm - The algorithm the key was generated for.
5528
+ * @returns `Success` with the imported public `CryptoKey`, or `Failure` with error context.
5529
+ */
5530
+ importPublicKeySpki(spkiBytes: Uint8Array, algorithm: KeyPairAlgorithm): Promise<Result<CryptoKey>>;
5531
+ /**
5532
+ * Signs `data` with `privateKey` using the algorithm inferred from the key.
5533
+ * @param privateKey - A signing `CryptoKey` (`'ecdsa-p256'` or `'ed25519'`).
5534
+ * @param data - The bytes to sign.
5535
+ * @returns `Success` with the raw signature bytes, or `Failure` with error context.
5536
+ */
5537
+ sign(privateKey: CryptoKey, data: Uint8Array): Promise<Result<Uint8Array>>;
5538
+ /**
5539
+ * Verifies a signature produced by {@link NodeCryptoProvider.sign}.
5540
+ * @param publicKey - A verify `CryptoKey` (`'ecdsa-p256'` or `'ed25519'`).
5541
+ * @param signature - The raw signature bytes.
5542
+ * @param data - The original data that was signed.
5543
+ * @returns `Success` with `true` if valid, `false` if not, or `Failure` with error context.
5544
+ */
5545
+ verify(publicKey: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<Result<boolean>>;
5546
+ /**
5547
+ * Compares two byte arrays in constant time using Node's native
5548
+ * `crypto.timingSafeEqual`. Returns `false` for mismatched lengths
5549
+ * rather than throwing (Node's native throws on length mismatch).
5550
+ * @param a - First byte array.
5551
+ * @param b - Second byte array.
5552
+ * @returns `true` if lengths match and all bytes are equal, `false` otherwise.
5553
+ */
5554
+ timingSafeEqual(a: Uint8Array, b: Uint8Array): boolean;
5555
+ /**
5556
+ * Computes an HMAC-SHA256 MAC for `data` using `key`.
5557
+ * @param key - An HMAC `CryptoKey` with `'sign'` usage.
5558
+ * @param data - The bytes to authenticate.
5559
+ * @returns `Success` with the 32-byte MAC, or `Failure` with error context.
5560
+ */
5561
+ hmacSha256(key: CryptoKey, data: Uint8Array): Promise<Result<Uint8Array>>;
5562
+ /**
5563
+ * Verifies an HMAC-SHA256 MAC in constant time.
5564
+ * @param key - An HMAC `CryptoKey` with `'sign'` usage.
5565
+ * @param signature - The MAC bytes to verify.
5566
+ * @param data - The original data that was authenticated.
5567
+ * @returns `Success` with `true` if valid, `false` if not, or `Failure` with error context.
5568
+ */
5569
+ verifyHmacSha256(key: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<Result<boolean>>;
5570
+ /**
5571
+ * Wraps `plaintext` for the holder of `recipientPublicKey` using
5572
+ * ECIES (ECDH P-256 + HKDF-SHA256 + AES-GCM-256). See
5573
+ * {@link CryptoUtils.ICryptoProvider.wrapBytes | ICryptoProvider.wrapBytes}.
5574
+ * @param plaintext - The bytes to wrap.
5575
+ * @param recipientPublicKey - The recipient's ECDH P-256 public `CryptoKey`.
5576
+ * @param options - HKDF salt and info; see {@link CryptoUtils.IWrapBytesOptions | IWrapBytesOptions}.
5577
+ * @returns `Success` with the wrapped payload, or `Failure` with an error.
5578
+ */
5579
+ wrapBytes(plaintext: Uint8Array, recipientPublicKey: CryptoKey, options: IWrapBytesOptions): Promise<Result<IWrappedBytes>>;
5580
+ /**
5581
+ * Unwraps a payload produced by `wrapBytes` using the recipient's private
5582
+ * key. See {@link CryptoUtils.ICryptoProvider.unwrapBytes | ICryptoProvider.unwrapBytes}.
5583
+ * @param wrapped - The wrapped payload.
5584
+ * @param recipientPrivateKey - The recipient's ECDH P-256 private `CryptoKey`.
5585
+ * @param options - HKDF salt and info matching the wrap call.
5586
+ * @returns `Success` with the original `plaintext`, or `Failure` with an error.
5587
+ */
5588
+ unwrapBytes(wrapped: IWrappedBytes, recipientPrivateKey: CryptoKey, options: IWrapBytesOptions): Promise<Result<Uint8Array>>;
1992
5589
  }
1993
5590
 
1994
5591
  /**
@@ -1997,6 +5594,12 @@ declare class NodeCryptoProvider implements ICryptoProvider {
1997
5594
  */
1998
5595
  declare const nodeCryptoProvider: NodeCryptoProvider;
1999
5596
 
5597
+ /**
5598
+ * Model IDs for OpenAI thinking-capable models.
5599
+ * @public
5600
+ */
5601
+ declare type OpenAiThinkingModelNames = 'o3' | 'o4-mini' | 'o3-deep-research' | 'o4-mini-deep-research' | 'gpt-5' | 'gpt-5.1' | 'gpt-5.2' | 'gpt-5.4-mini' | 'gpt-5.5' | 'gpt-5.5-pro' | 'gpt-5-pro';
5602
+
2000
5603
  /**
2001
5604
  * Parses CSV data from a string.
2002
5605
  * @param body - The CSV string to parse.
@@ -2016,6 +5619,12 @@ declare function parseCsvString(body: string, options?: CsvOptions): Result<unkn
2016
5619
  */
2017
5620
  declare function parseRecordJarLines(lines: string[], options?: JarRecordParserOptions): Result<JarRecord[]>;
2018
5621
 
5622
+ /**
5623
+ * Converter for {@link CryptoUtils.IPbkdf2KeyDerivationParams | PBKDF2 key derivation parameters}.
5624
+ * @public
5625
+ */
5626
+ declare const pbkdf2KeyDerivationParams: Converter<IPbkdf2KeyDerivationParams>;
5627
+
2019
5628
  /**
2020
5629
  * Simple implementation of a possibly open-ended range of some comparable
2021
5630
  * type `<T>` with test and formatting.
@@ -2193,11 +5802,11 @@ declare function readRecordJarFromTree(fileTree: FileTree.FileTree, filePath: st
2193
5802
  declare namespace RecordJar {
2194
5803
  export {
2195
5804
  parseRecordJarLines,
5805
+ readRecordJarFromTree,
2196
5806
  JarRecord,
2197
5807
  JarFieldPicker,
2198
5808
  JarRecordParserOptions,
2199
- readRecordJarFileSync,
2200
- readRecordJarFromTree
5809
+ readRecordJarFileSync
2201
5810
  }
2202
5811
  }
2203
5812
  export { RecordJar }
@@ -2218,29 +5827,155 @@ export { RecordJar }
2218
5827
  */
2219
5828
  declare function resolveEffectiveTools(descriptor: IAiProviderDescriptor, settingsTools?: ReadonlyArray<IAiToolEnablement>, perCallTools?: ReadonlyArray<AiServerToolConfig>): ReadonlyArray<AiServerToolConfig>;
2220
5829
 
5830
+ /**
5831
+ * Resolve the embedding capability that applies to a given model id for a
5832
+ * provider. Returns the entry from {@link IAiProviderDescriptor.embedding} whose
5833
+ * `modelPrefix` is the longest prefix of `modelId`. Ties are broken by
5834
+ * first-encountered.
5835
+ *
5836
+ * @param descriptor - The provider descriptor
5837
+ * @param modelId - The resolved embedding model id
5838
+ * @returns The matching capability, or `undefined` when no rule matches or the
5839
+ * provider declares no embedding capabilities.
5840
+ * @public
5841
+ */
5842
+ declare function resolveEmbeddingCapability(descriptor: IAiProviderDescriptor, modelId: string): IAiEmbeddingModelCapability | undefined;
5843
+
5844
+ /**
5845
+ * Resolve the image-generation capability that applies to a given model id
5846
+ * for a provider. Returns the entry from
5847
+ * {@link IAiProviderDescriptor.imageGeneration} whose `modelPrefix` is the
5848
+ * longest prefix of `modelId`. Ties are broken by first-encountered, so rule
5849
+ * order does not matter for correctness — only for tie-breaking among rules
5850
+ * with identical-length prefixes (an unusual case).
5851
+ *
5852
+ * @param descriptor - The provider descriptor
5853
+ * @param modelId - The resolved image model id
5854
+ * @returns The matching capability, or `undefined` when no rule matches or
5855
+ * the provider declares no image-generation capabilities.
5856
+ * @public
5857
+ */
5858
+ declare function resolveImageCapability(descriptor: IAiProviderDescriptor, modelId: string): IAiImageModelCapability | undefined;
5859
+
5860
+ /**
5861
+ * Resolves the merged image options for a given model and capability.
5862
+ *
5863
+ * @remarks
5864
+ * **Merge precedence (later wins):**
5865
+ * 1. Generic top-level options (size, count, quality, seed)
5866
+ * 2. Family-generic blocks (models field omitted, provider matches)
5867
+ * 3. Model-specific blocks (models array includes the resolved model name)
5868
+ * 4. Other blocks (provider: 'other', models array includes model name)
5869
+ *
5870
+ * Provider-mismatch blocks are silently skipped.
5871
+ *
5872
+ * Within each tier, declaration order — later declaration wins.
5873
+ *
5874
+ * @param modelId - The resolved model string
5875
+ * @param capability - The resolved IAiImageModelCapability for this model
5876
+ * @param options - Caller-supplied options
5877
+ * @returns The merged wire parameters
5878
+ * @public
5879
+ */
5880
+ declare function resolveImageOptions(modelId: string, capability: IAiImageModelCapability, options: IAiImageGenerationOptions | undefined): IResolvedImageOptions;
5881
+
2221
5882
  /**
2222
5883
  * Resolves a {@link ModelSpec} to a concrete model string given an optional context key.
2223
5884
  *
2224
5885
  * @remarks
2225
5886
  * Resolution rules:
2226
5887
  * 1. If the spec is a string, return it directly (context is irrelevant).
2227
- * 2. If the spec is an object and the context key exists, recurse into that branch.
5888
+ * 2. If the spec is an object, walk the ordered candidate keys for the context:
5889
+ * a quality-tier context (`advanced`/`frontier`) cascades through the
5890
+ * tier-fallback table (`frontier → advanced → base`, `advanced → base`);
5891
+ * every other context resolves flat (`[context]`); `undefined` resolves to
5892
+ * the shared `base` fallback. The first present key wins.
2228
5893
  * 3. Otherwise, fall back to the {@link MODEL_SPEC_BASE_KEY | 'base'} key.
2229
5894
  * 4. If neither context nor `'base'` exists, use the first available value.
2230
5895
  *
2231
5896
  * @param spec - The model specification to resolve
2232
- * @param context - Optional context key (e.g. `'tools'`)
5897
+ * @param context - Optional context key (e.g. `'advanced'`)
2233
5898
  * @returns The resolved model string
2234
5899
  * @public
2235
5900
  */
2236
5901
  declare function resolveModel(spec: ModelSpec, context?: string): string;
2237
5902
 
5903
+ /**
5904
+ * Resolves a single (possibly-aliased) model string against a provider descriptor.
5905
+ *
5906
+ * @remarks
5907
+ * Resolution rules:
5908
+ * 1. No leading {@link MODEL_ALIAS_SIGIL} → raw provider id, returned verbatim.
5909
+ * 2. Leading sigil + registered in `descriptor.aliases` → the registered target,
5910
+ * which is itself resolved — so a chain of `@` aliases is followed until a
5911
+ * non-`@` (concrete provider) id is reached. The canonical case is a single
5912
+ * hop (an fgv alias targeting a provider-native alias), but longer chains
5913
+ * resolve too.
5914
+ * 3. Leading sigil + unregistered → fails loudly, naming the provider and alias.
5915
+ *
5916
+ * An `@`→`@` cycle is guarded by a visited-set and fails rather than exhausting
5917
+ * the stack.
5918
+ *
5919
+ * @param descriptor - The provider descriptor whose `aliases` map is consulted.
5920
+ * @param model - The (possibly-aliased) model string to resolve.
5921
+ * @returns `Result` with the concrete provider model id, or a failure.
5922
+ * @public
5923
+ */
5924
+ declare function resolveModelAlias(descriptor: IAiProviderDescriptor, model: string): Result<string>;
5925
+
5926
+ /**
5927
+ * The full provider model-resolution chokepoint: the {@link ModelSpecKey} walk
5928
+ * (via {@link resolveModel}) THEN {@link resolveModelAlias}.
5929
+ *
5930
+ * @remarks
5931
+ * Replaces the bare `resolveModel(modelOverride ?? descriptor.defaultModel, context)`
5932
+ * call plus the duplicated empty-result check at each call-time chokepoint. The
5933
+ * `ModelSpec` branch is selected first; the resulting string — which may itself
5934
+ * be an fgv alias — is then resolved to a concrete id.
5935
+ *
5936
+ * @param descriptor - The provider descriptor (supplies `defaultModel` and `aliases`).
5937
+ * @param modelOverride - An optional caller-supplied `ModelSpec` that takes precedence
5938
+ * over `descriptor.defaultModel`. May itself contain or be an alias.
5939
+ * @param context - Optional {@link ModelSpecKey} selecting the spec branch.
5940
+ * @returns `Result` with the concrete provider model id, or a failure.
5941
+ * @public
5942
+ */
5943
+ declare function resolveProviderModel(descriptor: IAiProviderDescriptor, modelOverride: ModelSpec | undefined, context?: ModelSpecKey): Result<string>;
5944
+
2238
5945
  /**
2239
5946
  * Function type for dynamic secret retrieval.
2240
5947
  * @public
2241
5948
  */
2242
5949
  declare type SecretProvider = (secretName: string) => Promise<Result<Uint8Array>>;
2243
5950
 
5951
+ /**
5952
+ * Default system-prompt suffix appended when {@link AiAssist.IGenerateJsonCompletionParams.promptHint}
5953
+ * is `'smart'` (the default). Designed to discourage code fences and prose in
5954
+ * the model's response while still tolerating them via the read-side extractor.
5955
+ * @public
5956
+ */
5957
+ declare const SMART_JSON_PROMPT_HINT: string;
5958
+
5959
+ /**
5960
+ * Whether a provider declares any embedding capability at all.
5961
+ *
5962
+ * @param descriptor - The provider descriptor
5963
+ * @returns `true` when {@link IAiProviderDescriptor.embedding} has at least one
5964
+ * entry; `false` otherwise.
5965
+ * @public
5966
+ */
5967
+ declare function supportsEmbedding(descriptor: IAiProviderDescriptor): boolean;
5968
+
5969
+ /**
5970
+ * Whether a provider declares any image-generation capability at all.
5971
+ *
5972
+ * @param descriptor - The provider descriptor
5973
+ * @returns `true` when {@link IAiProviderDescriptor.imageGeneration} has at
5974
+ * least one entry; `false` otherwise.
5975
+ * @public
5976
+ */
5977
+ declare function supportsImageGeneration(descriptor: IAiProviderDescriptor): boolean;
5978
+
2244
5979
  /**
2245
5980
  * Helper function to create a `StringConverter` which converts
2246
5981
  * `unknown` to `string`, applying template conversions supplied at construction time or at
@@ -2261,6 +5996,14 @@ declare function templateString(defaultContext?: unknown): Conversion.StringConv
2261
5996
  */
2262
5997
  declare function toBase64(bytes: Uint8Array): string;
2263
5998
 
5999
+ /**
6000
+ * Formats an {@link IAiImageData} as a `data:` URL suitable for browser display.
6001
+ * @param image - The image to format
6002
+ * @returns A `data:<mime>;base64,<data>` URL string
6003
+ * @public
6004
+ */
6005
+ declare function toDataUrl(image: IAiImageData): string;
6006
+
2264
6007
  /**
2265
6008
  * Attempts to parse and decrypt a JSON object as an {@link CryptoUtils.IEncryptedFile | encrypted file}.
2266
6009
  * @typeParam TPayload - Expected type of decrypted content
@@ -2281,9 +6024,32 @@ declare function tryDecryptFile<TPayload extends JsonValue = JsonValue, TMetadat
2281
6024
  */
2282
6025
  declare const uint8ArrayFromBase64: Converter<Uint8Array>;
2283
6026
 
6027
+ /**
6028
+ * Validates the resolved options against per-model registry constraints.
6029
+ *
6030
+ * @remarks
6031
+ * Fails fast on the first violation. Error format:
6032
+ * `model "${model}": ${field} "${value}" is not accepted; accepted values: ${JSON.stringify(accepted)}`
6033
+ *
6034
+ * @param modelId - The resolved model string
6035
+ * @param capability - The resolved capability entry from the registry
6036
+ * @param resolved - The merged options from resolveImageOptions
6037
+ * @returns The same resolved options on success, or a failure with a contextual message
6038
+ * @public
6039
+ */
6040
+ declare function validateResolvedOptions(modelId: string, capability: IAiImageModelCapability, resolved: IResolvedImageOptions): Result<IResolvedImageOptions>;
6041
+
6042
+ /**
6043
+ * Model IDs for xAI thinking-capable models.
6044
+ * @public
6045
+ */
6046
+ declare type XAiThinkingModelNames = 'grok-3-mini' | 'grok-4.3' | 'grok-4';
6047
+
2284
6048
  declare namespace Yaml {
2285
6049
  export {
2286
- yamlConverter
6050
+ yamlConverter,
6051
+ yamlStringify,
6052
+ IYamlSerializeOptions
2287
6053
  }
2288
6054
  }
2289
6055
  export { Yaml }
@@ -2296,6 +6062,15 @@ export { Yaml }
2296
6062
  */
2297
6063
  declare function yamlConverter<T>(converter: Converter<T>): Converter<T>;
2298
6064
 
6065
+ /**
6066
+ * Serializes a value to a YAML string.
6067
+ * @param value - The value to serialize (must be an object or array)
6068
+ * @param options - Optional serialization options
6069
+ * @returns `Success` with YAML string, or `Failure` with error
6070
+ * @public
6071
+ */
6072
+ declare function yamlStringify(value: unknown, options?: IYamlSerializeOptions): Result<string>;
6073
+
2299
6074
  /**
2300
6075
  * Supported compression levels for zip files.
2301
6076
  * @public
@@ -2449,8 +6224,8 @@ declare class ZipFileTreeAccessors<TCT extends string = string> implements FileT
2449
6224
  private constructor();
2450
6225
  /**
2451
6226
  * Default function to infer the content type of a file.
2452
- * @param filePath - The path of the file.
2453
- * @param provided - Optional supplied content type.
6227
+ * @param __filePath - The path of the file.
6228
+ * @param __provided - Optional supplied content type.
2454
6229
  * @returns `Success` with the content type of the file if successful, or
2455
6230
  * `Failure` with an error message otherwise.
2456
6231
  * @remarks This default implementation always returns `Success` with `undefined`.