@keboola/api-client 32.0.0 → 34.0.0

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 (447) hide show
  1. package/AGENTS.md +82 -4
  2. package/API-SURFACE.md +19 -2
  3. package/CHANGELOG.md +465 -0
  4. package/dist/{ManagementClientAuthError-B-tyPlyG.cjs → ManagementClientAuthError-DD4u0EU7.cjs} +2 -2
  5. package/dist/{ManagementClientAuthError-B-tyPlyG.cjs.map → ManagementClientAuthError-DD4u0EU7.cjs.map} +1 -1
  6. package/dist/{ManagementClientAuthError-BAFNvOdf.js → ManagementClientAuthError-ey-f03vy.js} +2 -2
  7. package/dist/{ManagementClientAuthError-BAFNvOdf.js.map → ManagementClientAuthError-ey-f03vy.js.map} +1 -1
  8. package/dist/{ValidationError-CzPWydEb.js → ValidationError-BekhphAq.js} +11 -7
  9. package/dist/ValidationError-BekhphAq.js.map +1 -0
  10. package/dist/{ValidationError-h5qvwahi.cjs → ValidationError-CLVJCCwH.cjs} +16 -6
  11. package/dist/ValidationError-CLVJCCwH.cjs.map +1 -0
  12. package/dist/ai/index.cjs +2 -2
  13. package/dist/ai/index.d.cts +2 -2
  14. package/dist/ai/index.d.ts +2 -2
  15. package/dist/ai/index.js +2 -2
  16. package/dist/ai/types.d.cts +1 -1
  17. package/dist/ai/types.d.ts +1 -1
  18. package/dist/{appLogs-NIEDTDHf.cjs → appLogs-BjfUoWzs.cjs} +2 -2
  19. package/dist/{appLogs-NIEDTDHf.cjs.map → appLogs-BjfUoWzs.cjs.map} +1 -1
  20. package/dist/{appLogs-DX_WTBCa.d.ts → appLogs-Ch7DYpzx.d.ts} +2 -2
  21. package/dist/{appLogs-BAaaGYKg.d.cts → appLogs-D5A13Y0y.d.cts} +2 -2
  22. package/dist/{appLogs-DTLE6HTy.js → appLogs-xsVkTriU.js} +2 -2
  23. package/dist/{appLogs-DTLE6HTy.js.map → appLogs-xsVkTriU.js.map} +1 -1
  24. package/dist/apps/index.cjs +3 -3
  25. package/dist/apps/index.d.cts +3 -3
  26. package/dist/apps/index.d.ts +3 -3
  27. package/dist/apps/index.js +3 -3
  28. package/dist/apps/types.d.cts +2 -2
  29. package/dist/apps/types.d.ts +2 -2
  30. package/dist/assets/index.cjs +1 -1
  31. package/dist/assets/index.d.cts +1 -1
  32. package/dist/assets/index.d.ts +1 -1
  33. package/dist/assets/index.js +1 -1
  34. package/dist/auth/index.cjs +1 -1
  35. package/dist/auth/index.d.cts +1 -1
  36. package/dist/auth/index.d.ts +1 -1
  37. package/dist/auth/index.js +1 -1
  38. package/dist/auth/types.d.cts +2 -2
  39. package/dist/auth/types.d.ts +2 -2
  40. package/dist/{auth-DP-6TFiM.cjs → auth-JQ33o3nU.cjs} +2 -2
  41. package/dist/{auth-DP-6TFiM.cjs.map → auth-JQ33o3nU.cjs.map} +1 -1
  42. package/dist/{auth-DtbQaeDj.js → auth-aItmDu45.js} +2 -2
  43. package/dist/{auth-DtbQaeDj.js.map → auth-aItmDu45.js.map} +1 -1
  44. package/dist/{authClient-DhfzOUaa.d.cts → authClient-CTHNs6Tq.d.cts} +6 -6
  45. package/dist/{authClient--BtZgjIc.js → authClient-D7W9vWPR.js} +43 -9
  46. package/dist/authClient-D7W9vWPR.js.map +1 -0
  47. package/dist/{authClient-CtfyVHRD.d.ts → authClient-D8i3JTM-.d.ts} +6 -6
  48. package/dist/{authClient-b7uec7sw.cjs → authClient-_PpvGgZJ.cjs} +43 -9
  49. package/dist/authClient-_PpvGgZJ.cjs.map +1 -0
  50. package/dist/billing/index.cjs +46 -0
  51. package/dist/billing/index.cjs.map +1 -0
  52. package/dist/billing/index.d.cts +48 -0
  53. package/dist/billing/index.d.ts +48 -0
  54. package/dist/billing/index.js +45 -0
  55. package/dist/billing/index.js.map +1 -0
  56. package/dist/billing/types.cjs +0 -0
  57. package/dist/billing/types.d.cts +635 -0
  58. package/dist/billing/types.d.ts +635 -0
  59. package/dist/billing/types.js +1 -0
  60. package/dist/chat/index.cjs +3 -3
  61. package/dist/chat/index.d.cts +2 -2
  62. package/dist/chat/index.d.ts +2 -2
  63. package/dist/chat/index.js +3 -3
  64. package/dist/chat/types.cjs +18 -0
  65. package/dist/chat/types.cjs.map +1 -1
  66. package/dist/chat/types.d.cts +2 -2
  67. package/dist/chat/types.d.ts +2 -2
  68. package/dist/chat/types.js +18 -1
  69. package/dist/chat/types.js.map +1 -1
  70. package/dist/{configurations-d7SZmw69.js → configurations-BVvcimzo.js} +17 -2
  71. package/dist/configurations-BVvcimzo.js.map +1 -0
  72. package/dist/{configurations-CqwAxiQL.cjs → configurations-CyFF9Dtu.cjs} +22 -1
  73. package/dist/configurations-CyFF9Dtu.cjs.map +1 -0
  74. package/dist/{configurations-ZwBXilW-.js → configurations-VtNE0nrT.js} +2 -2
  75. package/dist/{configurations-ZwBXilW-.js.map → configurations-VtNE0nrT.js.map} +1 -1
  76. package/dist/{configurations-Ck-mNB_E.cjs → configurations-zkNjr73Q.cjs} +2 -2
  77. package/dist/{configurations-Ck-mNB_E.cjs.map → configurations-zkNjr73Q.cjs.map} +1 -1
  78. package/dist/constants/index.cjs +1 -1
  79. package/dist/constants/index.d.cts +1 -1
  80. package/dist/constants/index.d.ts +1 -1
  81. package/dist/constants/index.js +1 -1
  82. package/dist/{constants-lIfSdTzS.cjs → constants-C4DlsF_M.cjs} +3 -2
  83. package/dist/constants-C4DlsF_M.cjs.map +1 -0
  84. package/dist/{constants-ByEwVtGf.js → constants-wfbFsqqN.js} +3 -2
  85. package/dist/constants-wfbFsqqN.js.map +1 -0
  86. package/dist/{createFetchClient-BRfTjBLV.cjs → createFetchClient-DgMiqTJ8.cjs} +26 -4
  87. package/dist/createFetchClient-DgMiqTJ8.cjs.map +1 -0
  88. package/dist/{createFetchClient-BbG46bL0.js → createFetchClient-U-ZrwPl2.js} +15 -5
  89. package/dist/createFetchClient-U-ZrwPl2.js.map +1 -0
  90. package/dist/{createGenericFetchClient-DHs-i7_O.cjs → createGenericFetchClient-o3cPJeRn.cjs} +2 -2
  91. package/dist/{createGenericFetchClient-DHs-i7_O.cjs.map → createGenericFetchClient-o3cPJeRn.cjs.map} +1 -1
  92. package/dist/{createGenericFetchClient-BHYQLZhe.js → createGenericFetchClient-rxvUUbap.js} +2 -2
  93. package/dist/{createGenericFetchClient-BHYQLZhe.js.map → createGenericFetchClient-rxvUUbap.js.map} +1 -1
  94. package/dist/{createOpenapiFetchClient-Bn6_Pn0H.js → createOpenapiFetchClient-BVSc9ibR.js} +2 -2
  95. package/dist/{createOpenapiFetchClient-Bn6_Pn0H.js.map → createOpenapiFetchClient-BVSc9ibR.js.map} +1 -1
  96. package/dist/{createOpenapiFetchClient-CyDUFxHB.cjs → createOpenapiFetchClient-DhUU3M1W.cjs} +2 -2
  97. package/dist/{createOpenapiFetchClient-CyDUFxHB.cjs.map → createOpenapiFetchClient-DhUU3M1W.cjs.map} +1 -1
  98. package/dist/{credential-d2RDcXRB.js → credential-CihSf_xs.js} +7 -4
  99. package/dist/credential-CihSf_xs.js.map +1 -0
  100. package/dist/{credential-DOXH7XRS.cjs → credential-DVWvJFJs.cjs} +7 -4
  101. package/dist/credential-DVWvJFJs.cjs.map +1 -0
  102. package/dist/dataScience/index.cjs +2 -2
  103. package/dist/dataScience/index.d.cts +2 -2
  104. package/dist/dataScience/index.d.ts +2 -2
  105. package/dist/dataScience/index.js +2 -2
  106. package/dist/dataScience/types.d.cts +2 -2
  107. package/dist/dataScience/types.d.ts +2 -2
  108. package/dist/{dataScience-wexHEIue.cjs → dataScience-0Rl_EuV_.cjs} +5 -5
  109. package/dist/{dataScience-wexHEIue.cjs.map → dataScience-0Rl_EuV_.cjs.map} +1 -1
  110. package/dist/{dataScience-Sm8iONhP.js → dataScience-C1gO5zUn.js} +5 -5
  111. package/dist/{dataScience-Sm8iONhP.js.map → dataScience-C1gO5zUn.js.map} +1 -1
  112. package/dist/developerPortal/index.cjs +1 -1
  113. package/dist/developerPortal/index.d.cts +2 -2
  114. package/dist/developerPortal/index.d.ts +2 -2
  115. package/dist/developerPortal/index.js +1 -1
  116. package/dist/developerPortal/types.d.cts +1 -1
  117. package/dist/developerPortal/types.d.ts +1 -1
  118. package/dist/{developerPortalClient-DywKpDlW.js → developerPortalClient-C_48z8BN.js} +3 -3
  119. package/dist/{developerPortalClient-DywKpDlW.js.map → developerPortalClient-C_48z8BN.js.map} +1 -1
  120. package/dist/{developerPortalClient-CgTSzLoG.cjs → developerPortalClient-ki0XS_OD.cjs} +3 -3
  121. package/dist/{developerPortalClient-CgTSzLoG.cjs.map → developerPortalClient-ki0XS_OD.cjs.map} +1 -1
  122. package/dist/domain/permissions/index.cjs +2 -1
  123. package/dist/domain/permissions/index.d.cts +18 -3
  124. package/dist/domain/permissions/index.d.ts +18 -3
  125. package/dist/domain/permissions/index.js +2 -2
  126. package/dist/editor/index.cjs +2 -2
  127. package/dist/editor/index.d.cts +2 -2
  128. package/dist/editor/index.d.ts +2 -2
  129. package/dist/editor/index.js +2 -2
  130. package/dist/editor/types.d.cts +1 -1
  131. package/dist/editor/types.d.ts +1 -1
  132. package/dist/emitter-dLF1Fyfg.d.cts +11 -0
  133. package/dist/emitter-dLF1Fyfg.d.ts +11 -0
  134. package/dist/encryption/index.cjs +1 -1
  135. package/dist/encryption/index.d.cts +1 -1
  136. package/dist/encryption/index.d.ts +1 -1
  137. package/dist/encryption/index.js +1 -1
  138. package/dist/encryption/types.d.cts +1 -1
  139. package/dist/encryption/types.d.ts +1 -1
  140. package/dist/import/index.cjs +1 -1
  141. package/dist/import/index.d.cts +3 -3
  142. package/dist/import/index.d.ts +3 -3
  143. package/dist/import/index.js +1 -1
  144. package/dist/{import-C0-y1GQK.cjs → import-C83w7BKz.cjs} +3 -3
  145. package/dist/{import-C0-y1GQK.cjs.map → import-C83w7BKz.cjs.map} +1 -1
  146. package/dist/{import-SQuurg1G.js → import-CROEK82b.js} +3 -3
  147. package/dist/{import-SQuurg1G.js.map → import-CROEK82b.js.map} +1 -1
  148. package/dist/{index-fHfc_VqS.d.ts → index-3LUk2rpD.d.ts} +4 -4
  149. package/dist/{index-Dbzjvy5h.d.ts → index-6Xe81qN3.d.ts} +5 -5
  150. package/dist/{index-Bjk-tCpG.d.cts → index-BLx14ZI4.d.cts} +306 -205
  151. package/dist/{index-DiHHyMEo.d.cts → index-BgLnWTZU.d.cts} +6 -6
  152. package/dist/{index-Bc_hXWae.d.ts → index-BuegqrS1.d.ts} +3 -3
  153. package/dist/{index-GDdFZCXp.d.ts → index-C77vTm2K.d.ts} +4 -4
  154. package/dist/{index-CXtdQ7be.d.cts → index-CW3Pj7DY.d.cts} +4 -4
  155. package/dist/{index-Bg1P6Bb2.d.ts → index-CqgtL2NU.d.ts} +6 -6
  156. package/dist/{index-DeKPpYQy.d.ts → index-D8rcUbnk.d.ts} +3 -3
  157. package/dist/{index-FhKX7Cv1.d.ts → index-DFBFa3SS.d.ts} +306 -205
  158. package/dist/{index-eAlN694c.d.cts → index-DR4QqItd.d.cts} +3 -3
  159. package/dist/{index-Gn1H63Hk.d.cts → index-DXSmFkol.d.cts} +4 -4
  160. package/dist/{index-D_7yCRKy.d.cts → index-Dodwl64k.d.cts} +69 -36
  161. package/dist/{index-DqOAjqxN.d.cts → index-DppA4k3b.d.cts} +5 -5
  162. package/dist/{index-C7e3wBt9.d.cts → index-Dx52hNLP.d.cts} +3 -3
  163. package/dist/{index-BKh0prif.d.cts → index-GjcJTCbz.d.cts} +4 -4
  164. package/dist/{index-CQrKS7PV.d.cts → index-KuQ79Mnz.d.ts} +14 -3
  165. package/dist/{index-Ctqkm3Fx.d.ts → index-P-iT5THa.d.ts} +69 -36
  166. package/dist/{index-CeJOmN-P.d.ts → index-V7XKUQm9.d.cts} +14 -3
  167. package/dist/{index-tKsiUarj.d.ts → index-pXN4LWUX.d.ts} +4 -4
  168. package/dist/index.cjs +353 -57
  169. package/dist/index.cjs.map +1 -1
  170. package/dist/index.d.cts +7 -6
  171. package/dist/index.d.ts +7 -6
  172. package/dist/index.js +331 -37
  173. package/dist/index.js.map +1 -1
  174. package/dist/isLoginPageRedirect-B0EmRsHr.cjs +25 -0
  175. package/dist/isLoginPageRedirect-B0EmRsHr.cjs.map +1 -0
  176. package/dist/isLoginPageRedirect-BTTAedW-.js +20 -0
  177. package/dist/isLoginPageRedirect-BTTAedW-.js.map +1 -0
  178. package/dist/{jobStatus-kQ9JqF8t.cjs → jobStatus-0_Y3Sr4i.cjs} +37 -20
  179. package/dist/jobStatus-0_Y3Sr4i.cjs.map +1 -0
  180. package/dist/{jobStatus-DbMupQEK.js → jobStatus-PSZJMTiA.js} +35 -18
  181. package/dist/jobStatus-PSZJMTiA.js.map +1 -0
  182. package/dist/kaiAgent/index.cjs +1 -1
  183. package/dist/kaiAgent/index.d.cts +2 -210
  184. package/dist/kaiAgent/index.d.ts +2 -210
  185. package/dist/kaiAgent/index.js +1 -1
  186. package/dist/kaiAgent/types.d.cts +1 -1
  187. package/dist/kaiAgent/types.d.ts +1 -1
  188. package/dist/{kaiAgent-HDaFS9BR.js → kaiAgent-8LNzGhZc.js} +48 -4
  189. package/dist/kaiAgent-8LNzGhZc.js.map +1 -0
  190. package/dist/{kaiAgent-4OiIK1C2.cjs → kaiAgent-B_TaUPRt.cjs} +48 -4
  191. package/dist/kaiAgent-B_TaUPRt.cjs.map +1 -0
  192. package/dist/kaiAgentClient-BJj_2aqt.d.ts +250 -0
  193. package/dist/kaiAgentClient-DhTaM3GC.d.cts +250 -0
  194. package/dist/management/index.cjs +1 -1
  195. package/dist/management/index.d.cts +1 -1
  196. package/dist/management/index.d.ts +1 -1
  197. package/dist/management/index.js +1 -1
  198. package/dist/management/types.d.cts +2 -2
  199. package/dist/management/types.d.ts +2 -2
  200. package/dist/{management-DfjwQo7z.cjs → management-BoxlRNg2.cjs} +53 -10
  201. package/dist/management-BoxlRNg2.cjs.map +1 -0
  202. package/dist/{management-CIFhu1Nm.js → management-Bp440RsV.js} +53 -10
  203. package/dist/management-Bp440RsV.js.map +1 -0
  204. package/dist/metastore/index.cjs +1 -1
  205. package/dist/metastore/index.d.cts +1 -1
  206. package/dist/metastore/index.d.ts +1 -1
  207. package/dist/metastore/index.js +1 -1
  208. package/dist/metastore/types.d.cts +1 -1
  209. package/dist/metastore/types.d.ts +1 -1
  210. package/dist/{metastore-Dq2NS6jb.cjs → metastore-BYYWTb3m.cjs} +4 -4
  211. package/dist/{metastore-Dq2NS6jb.cjs.map → metastore-BYYWTb3m.cjs.map} +1 -1
  212. package/dist/{metastore-CrXkKufo.js → metastore-VCDRVhUT.js} +4 -4
  213. package/dist/{metastore-CrXkKufo.js.map → metastore-VCDRVhUT.js.map} +1 -1
  214. package/dist/microsoftGraph/index.cjs +2 -2
  215. package/dist/microsoftGraph/index.d.cts +2 -2
  216. package/dist/microsoftGraph/index.d.ts +2 -2
  217. package/dist/microsoftGraph/index.js +2 -2
  218. package/dist/microsoftGraph/types.d.cts +1 -1
  219. package/dist/microsoftGraph/types.d.ts +1 -1
  220. package/dist/notifications/index.cjs +3 -3
  221. package/dist/notifications/index.d.cts +2 -2
  222. package/dist/notifications/index.d.ts +2 -2
  223. package/dist/notifications/index.js +3 -3
  224. package/dist/notifications/types.d.cts +1 -1
  225. package/dist/notifications/types.d.ts +1 -1
  226. package/dist/oauth/index.cjs +1 -1
  227. package/dist/oauth/index.d.cts +2 -2
  228. package/dist/oauth/index.d.ts +2 -2
  229. package/dist/oauth/index.js +1 -1
  230. package/dist/oauth/types.d.cts +1 -1
  231. package/dist/oauth/types.d.ts +1 -1
  232. package/dist/{oauth-CFwSNz37.js → oauth--asfePw-.js} +5 -5
  233. package/dist/{oauth-CFwSNz37.js.map → oauth--asfePw-.js.map} +1 -1
  234. package/dist/{oauth-CkW5gln-.cjs → oauth-B8yqG6Sy.cjs} +5 -5
  235. package/dist/{oauth-CkW5gln-.cjs.map → oauth-B8yqG6Sy.cjs.map} +1 -1
  236. package/dist/omnisearch/index.cjs +2 -2
  237. package/dist/omnisearch/index.d.cts +2 -2
  238. package/dist/omnisearch/index.d.ts +2 -2
  239. package/dist/omnisearch/index.js +2 -2
  240. package/dist/omnisearch/types.d.cts +1 -1
  241. package/dist/omnisearch/types.d.ts +1 -1
  242. package/dist/{project-BOGaVs-q.d.ts → project-C2wvX0xZ.d.ts} +2 -2
  243. package/dist/{project-BnQkL8cb.d.cts → project-hePfzUY0.d.cts} +2 -2
  244. package/dist/queryService/index.cjs +1 -1
  245. package/dist/queryService/index.d.cts +1 -1
  246. package/dist/queryService/index.d.ts +1 -1
  247. package/dist/queryService/index.js +1 -1
  248. package/dist/queryService/types.d.cts +1 -1
  249. package/dist/queryService/types.d.ts +1 -1
  250. package/dist/{queryService-BLaGbpm-.cjs → queryService-BVtjkXy1.cjs} +6 -6
  251. package/dist/{queryService-BLaGbpm-.cjs.map → queryService-BVtjkXy1.cjs.map} +1 -1
  252. package/dist/{queryService-DK-jUnET.js → queryService-Ca65E5KH.js} +6 -6
  253. package/dist/{queryService-DK-jUnET.js.map → queryService-Ca65E5KH.js.map} +1 -1
  254. package/dist/queue/index.cjs +1 -1
  255. package/dist/queue/index.d.cts +3 -3
  256. package/dist/queue/index.d.ts +3 -3
  257. package/dist/queue/index.js +1 -1
  258. package/dist/queue/types.d.cts +1 -1
  259. package/dist/queue/types.d.ts +1 -1
  260. package/dist/{queue-DViSQ-eq.js → queue-DyotLFJi.js} +5 -5
  261. package/dist/{queue-DViSQ-eq.js.map → queue-DyotLFJi.js.map} +1 -1
  262. package/dist/{queue-B7TY4JLf.cjs → queue-OJJUUqc2.cjs} +5 -5
  263. package/dist/{queue-B7TY4JLf.cjs.map → queue-OJJUUqc2.cjs.map} +1 -1
  264. package/dist/scheduler/index.cjs +3 -3
  265. package/dist/scheduler/index.d.cts +2 -2
  266. package/dist/scheduler/index.d.ts +2 -2
  267. package/dist/scheduler/index.js +3 -3
  268. package/dist/scheduler/types.d.cts +1 -1
  269. package/dist/scheduler/types.d.ts +1 -1
  270. package/dist/sdk/configurations/index.cjs +1 -1
  271. package/dist/sdk/configurations/index.d.cts +4 -4
  272. package/dist/sdk/configurations/index.d.ts +4 -4
  273. package/dist/sdk/configurations/index.js +1 -1
  274. package/dist/sdk/developerPortal/index.cjs +5 -5
  275. package/dist/sdk/developerPortal/index.cjs.map +1 -1
  276. package/dist/sdk/developerPortal/index.d.cts +5 -4
  277. package/dist/sdk/developerPortal/index.d.ts +5 -4
  278. package/dist/sdk/developerPortal/index.js +4 -4
  279. package/dist/sdk/queryService/index.cjs +2 -2
  280. package/dist/sdk/queryService/index.d.cts +1 -1
  281. package/dist/sdk/queryService/index.d.ts +1 -1
  282. package/dist/sdk/queryService/index.js +2 -2
  283. package/dist/sdk/semanticLayer/index.cjs +21 -359
  284. package/dist/sdk/semanticLayer/index.d.cts +35 -13
  285. package/dist/sdk/semanticLayer/index.d.ts +35 -13
  286. package/dist/sdk/semanticLayer/index.js +2 -347
  287. package/dist/sdk/semanticLayer/types.d.cts +2 -2
  288. package/dist/sdk/semanticLayer/types.d.ts +2 -2
  289. package/dist/sdk/storage/index.d.cts +1 -1
  290. package/dist/sdk/storage/index.d.ts +1 -1
  291. package/dist/sdk/tag/index.d.cts +2 -2
  292. package/dist/sdk/tag/index.d.ts +2 -2
  293. package/dist/sdk/tag/types.d.cts +1 -1
  294. package/dist/sdk/tag/types.d.ts +1 -1
  295. package/dist/sdk/vault/index.d.cts +1 -1
  296. package/dist/sdk/vault/index.d.ts +1 -1
  297. package/dist/semanticLayer-CSqmtHRo.js +692 -0
  298. package/dist/semanticLayer-CSqmtHRo.js.map +1 -0
  299. package/dist/semanticLayer-E0Vilu8u.cjs +811 -0
  300. package/dist/semanticLayer-E0Vilu8u.cjs.map +1 -0
  301. package/dist/{serviceIds-fHLDwOg9.d.ts → serviceIds-DRcoTnSd.d.cts} +2 -1
  302. package/dist/{serviceIds-fHLDwOg9.d.cts → serviceIds-DRcoTnSd.d.ts} +2 -1
  303. package/dist/status/index.cjs +1 -1
  304. package/dist/status/index.d.cts +1 -1
  305. package/dist/status/index.d.ts +1 -1
  306. package/dist/status/index.js +1 -1
  307. package/dist/storage/index.cjs +6 -5
  308. package/dist/storage/index.d.cts +3 -3
  309. package/dist/storage/index.d.ts +3 -3
  310. package/dist/storage/index.js +6 -6
  311. package/dist/storage/types.d.cts +3 -3
  312. package/dist/storage/types.d.ts +3 -3
  313. package/dist/{storage-CihHwZ7z.cjs → storage-BKm7cztt.cjs} +7 -7
  314. package/dist/{storage-CihHwZ7z.cjs.map → storage-BKm7cztt.cjs.map} +1 -1
  315. package/dist/{storage-kgxscFEg.js → storage-LYwFQPNO.js} +7 -7
  316. package/dist/{storage-kgxscFEg.js.map → storage-LYwFQPNO.js.map} +1 -1
  317. package/dist/store-C9FQCHGe.js +74 -0
  318. package/dist/store-C9FQCHGe.js.map +1 -0
  319. package/dist/store-xS-Cu_VS.cjs +85 -0
  320. package/dist/store-xS-Cu_VS.cjs.map +1 -0
  321. package/dist/stream/index.cjs +3 -3
  322. package/dist/stream/index.d.cts +2 -2
  323. package/dist/stream/index.d.ts +2 -2
  324. package/dist/stream/index.js +3 -3
  325. package/dist/stream/types.d.cts +1 -1
  326. package/dist/stream/types.d.ts +1 -1
  327. package/dist/syncActions/index.cjs +1 -1
  328. package/dist/syncActions/index.d.cts +1 -1
  329. package/dist/syncActions/index.d.ts +1 -1
  330. package/dist/syncActions/index.js +1 -1
  331. package/dist/syncActions/types.d.cts +1 -1
  332. package/dist/syncActions/types.d.ts +1 -1
  333. package/dist/{syncActions-CevF_TEb.cjs → syncActions-OEZdVffK.cjs} +6 -6
  334. package/dist/{syncActions-CevF_TEb.cjs.map → syncActions-OEZdVffK.cjs.map} +1 -1
  335. package/dist/{syncActions-B75t0NwP.js → syncActions-QeBhIVhG.js} +6 -6
  336. package/dist/{syncActions-B75t0NwP.js.map → syncActions-QeBhIVhG.js.map} +1 -1
  337. package/dist/telemetry/index.cjs +38 -2
  338. package/dist/telemetry/index.cjs.map +1 -0
  339. package/dist/telemetry/index.d.cts +15 -8
  340. package/dist/telemetry/index.d.ts +15 -8
  341. package/dist/telemetry/index.js +37 -1
  342. package/dist/telemetry/index.js.map +1 -0
  343. package/dist/telemetry/types.d.cts +2 -2
  344. package/dist/telemetry/types.d.ts +2 -2
  345. package/dist/{types-D1uloiuY.d.cts → types-3eUgOA7I.d.cts} +2 -2
  346. package/dist/{types-CvkqEvhv.d.cts → types-52irAt99.d.cts} +2 -2
  347. package/dist/{types-CyHZ1ZQe.d.ts → types-B2U9cFcx.d.ts} +2 -2
  348. package/dist/{types-Av2egS_l.d.ts → types-B3GOGUJ7.d.cts} +753 -45
  349. package/dist/{types-BH9ljNmj.d.cts → types-BEe50G2r.d.cts} +2 -2
  350. package/dist/{types-BlCoTm7n.d.ts → types-BH5LLeJy.d.ts} +2 -2
  351. package/dist/{types-BptQ7jpP.d.cts → types-BMeDOB_D.d.ts} +753 -45
  352. package/dist/{types-MbcIiKDI.d.cts → types-BOqD3Hqy.d.cts} +3 -3
  353. package/dist/{types-DeSd3gqW.d.ts → types-BQsOHNI0.d.ts} +3 -3
  354. package/dist/{types-DNXC_-fA.d.cts → types-BQvv4RaI.d.cts} +2 -2
  355. package/dist/{types-BnaAo7xn.d.ts → types-BTWIPEiU.d.ts} +2 -2
  356. package/dist/{types-C1vhYcic.d.cts → types-BW2BXUB4.d.cts} +2 -2
  357. package/dist/{types-CXTqFYah.d.ts → types-BrYkBQo4.d.ts} +37 -6
  358. package/dist/{types-BZBdLUpH.d.ts → types-BsxLGDoC.d.cts} +2 -2
  359. package/dist/{types-BMQW-2Yw.d.ts → types-BupPADSm.d.ts} +737 -80
  360. package/dist/{types-COc-nind.d.cts → types-Bxhh2SJr.d.ts} +2 -2
  361. package/dist/{types-ByWD2oeV.d.ts → types-BztF4HeB.d.ts} +2 -2
  362. package/dist/{types-dybUhlU2.d.ts → types-C0_2KZ-A.d.ts} +2 -2
  363. package/dist/types-C2vefB4D.d.ts +218 -0
  364. package/dist/{types-CkcMoXRk.d.ts → types-CBgLCkYe.d.ts} +3 -3
  365. package/dist/{types-Cz1dj_TM.d.ts → types-CKiW3n6v.d.ts} +2 -2
  366. package/dist/{types-CcuG9cid.d.cts → types-COL1kVEB.d.cts} +2 -2
  367. package/dist/types-CPB-eF82.d.ts +289 -0
  368. package/dist/{types-BoV9M5Xg.d.cts → types-CW6lCqrC.d.cts} +2 -2
  369. package/dist/{types-CPanB0p7.d.cts → types-CaYtinmA.d.cts} +3 -3
  370. package/dist/{types-De_DA2ga.d.ts → types-CcrvrAJX.d.ts} +2 -2
  371. package/dist/{types-DwpRt3e9.d.ts → types-Ct0YPy2w.d.ts} +2 -2
  372. package/dist/{types-B4jdPHoL.d.cts → types-Cz83RiVu.d.cts} +2 -2
  373. package/dist/{types-DlbiVsVo.d.cts → types-D8Rrz51O.d.cts} +2 -2
  374. package/dist/{types-CyiRYRVq.d.cts → types-DARv_P6O.d.cts} +3 -3
  375. package/dist/{types-DuiUN0h8.d.ts → types-DBOSvWtD.d.ts} +2 -2
  376. package/dist/{types-D6jKxUv_.d.ts → types-DEc55spK.d.ts} +45 -4
  377. package/dist/{types-cDU_J45_.d.cts → types-DNxOHnZI.d.cts} +2 -2
  378. package/dist/{types-GuWtMCMn.d.cts → types-DPS8nwkV.d.cts} +2 -2
  379. package/dist/{types-Di8VIZwQ.d.ts → types-DYzJ6K2e.d.ts} +2 -2
  380. package/dist/{types-BI2jI-3-.d.cts → types-DZk3XHiN.d.cts} +3 -3
  381. package/dist/{types-Dfc58bPE.d.ts → types-DajzGOKB.d.ts} +2 -2
  382. package/dist/{types-C2CLlR4i.d.ts → types-DfvdbRPL.d.ts} +2 -2
  383. package/dist/{types-CpALS017.d.ts → types-DhDNS-5B.d.ts} +21 -3
  384. package/dist/{types-BV2BDccJ.d.cts → types-DjrRmQUe.d.cts} +45 -4
  385. package/dist/{types-sVYo0o9_.d.ts → types-Dmu-8g4O.d.ts} +3 -3
  386. package/dist/{types-COIsNoTQ.d.cts → types-DqxIx9Pi.d.cts} +2 -2
  387. package/dist/{types-Cj4bLPp5.d.cts → types-Jw10xuOW.d.cts} +37 -6
  388. package/dist/{types-CJHi0zdD.d.cts → types-M46WuBSm.d.cts} +2 -2
  389. package/dist/{types-zA3H84SM.d.cts → types-N3EChotg.d.cts} +2 -2
  390. package/dist/{types-Bpnpa2Wt.d.ts → types-OaD-cbbl.d.ts} +3 -3
  391. package/dist/{types-BREGN3qo.d.cts → types-_RhBCj4_.d.cts} +2 -2
  392. package/dist/{types-CGH_lfxS.d.cts → types-bGQb4Jtl.d.cts} +21 -3
  393. package/dist/{types-iNlsdRkx.d.cts → types-f8W_j6qD.d.cts} +737 -80
  394. package/dist/types-fX4gbxfV.d.cts +218 -0
  395. package/dist/types-g3vU7hcg.d.cts +289 -0
  396. package/dist/{types-D-qI9ne4.d.ts → types-l9o4gFsI.d.ts} +2 -2
  397. package/dist/{types-EJEoI3ZK.d.ts → types-nrviNdzZ.d.ts} +2 -2
  398. package/dist/{types-BTbczawY.d.ts → types-zZBxJ0P-.d.ts} +2 -2
  399. package/dist/{validateConnectionStatus-V9q6Nl6u.cjs → validateConnectionStatus-CsvYmCOI.cjs} +5 -4
  400. package/dist/validateConnectionStatus-CsvYmCOI.cjs.map +1 -0
  401. package/dist/{validateConnectionStatus-BrLXkoSI.js → validateConnectionStatus-olE2sQ3U.js} +5 -4
  402. package/dist/{validateConnectionStatus-BrLXkoSI.js.map → validateConnectionStatus-olE2sQ3U.js.map} +1 -1
  403. package/dist/vault/index.cjs +4 -4
  404. package/dist/vault/index.d.cts +1 -1
  405. package/dist/vault/index.d.ts +1 -1
  406. package/dist/vault/index.js +4 -4
  407. package/dist/vault/types.d.cts +1 -1
  408. package/dist/vault/types.d.ts +1 -1
  409. package/package.json +30 -4
  410. package/surface/auth.md +2 -2
  411. package/surface/billing.md +9 -0
  412. package/surface/kaiAgent.md +7 -4
  413. package/surface/management.md +13 -3
  414. package/surface/telemetry.md +2 -4
  415. package/dist/ValidationError-CzPWydEb.js.map +0 -1
  416. package/dist/ValidationError-h5qvwahi.cjs.map +0 -1
  417. package/dist/authClient--BtZgjIc.js.map +0 -1
  418. package/dist/authClient-b7uec7sw.cjs.map +0 -1
  419. package/dist/configurations-CqwAxiQL.cjs.map +0 -1
  420. package/dist/configurations-d7SZmw69.js.map +0 -1
  421. package/dist/constants-ByEwVtGf.js.map +0 -1
  422. package/dist/constants-lIfSdTzS.cjs.map +0 -1
  423. package/dist/createFetchClient-BRfTjBLV.cjs.map +0 -1
  424. package/dist/createFetchClient-BbG46bL0.js.map +0 -1
  425. package/dist/createStore-BNiCRQXa.js +0 -148
  426. package/dist/createStore-BNiCRQXa.js.map +0 -1
  427. package/dist/createStore-MQbboXcB.cjs +0 -177
  428. package/dist/createStore-MQbboXcB.cjs.map +0 -1
  429. package/dist/credential-DOXH7XRS.cjs.map +0 -1
  430. package/dist/credential-d2RDcXRB.js.map +0 -1
  431. package/dist/jobStatus-DbMupQEK.js.map +0 -1
  432. package/dist/jobStatus-kQ9JqF8t.cjs.map +0 -1
  433. package/dist/kaiAgent-4OiIK1C2.cjs.map +0 -1
  434. package/dist/kaiAgent-HDaFS9BR.js.map +0 -1
  435. package/dist/management-CIFhu1Nm.js.map +0 -1
  436. package/dist/management-DfjwQo7z.cjs.map +0 -1
  437. package/dist/sdk/semanticLayer/index.cjs.map +0 -1
  438. package/dist/sdk/semanticLayer/index.js.map +0 -1
  439. package/dist/telemetry-DwlSLVAU.cjs +0 -29
  440. package/dist/telemetry-DwlSLVAU.cjs.map +0 -1
  441. package/dist/telemetry-FXpodtJN.js +0 -24
  442. package/dist/telemetry-FXpodtJN.js.map +0 -1
  443. package/dist/types-B2vmg_UF.d.cts +0 -148
  444. package/dist/types-RfaldD4P.d.ts +0 -148
  445. package/dist/types-lFsTSkhe.d.cts +0 -14
  446. package/dist/types-lFsTSkhe.d.ts +0 -14
  447. package/dist/validateConnectionStatus-V9q6Nl6u.cjs.map +0 -1
package/AGENTS.md CHANGED
@@ -77,7 +77,7 @@ Two flow-specific factories back the SDK, and **both return `{ api, session }`**
77
77
  `subscribe(cb)` (fires on config **and** storage-build transitions), and `debug()`. Then:
78
78
 
79
79
  - bearer: `authenticate(token)` → `setProject(projectId)` / `setProjectAsync(projectId)` (awaits the
80
- build) / `reset()`.
80
+ build) / `forProject(projectId)` (a second project alongside the first) / `reset()`.
81
81
  - legacy: `authenticateStorage(sapiToken)` / `authenticateStorageAsync(sapiToken)` (awaits the build),
82
82
  `authenticateManagement(manageToken)`.
83
83
 
@@ -98,6 +98,83 @@ session.setProject(otherId); // runtime re-scope (rebuilds against the new proje
98
98
  session.debug(); // { baseUrl, authReady, managementReady, storage, config }
99
99
  ```
100
100
 
101
+ ### Several projects at once (bearer)
102
+
103
+ One session can address any number of projects. The credential is a **user** token — project scope is
104
+ one header, `X-KBC-ProjectId` — so `session.forProject(projectId)` builds a `ProjectClients` set for
105
+ any project the user can reach, off the session already in hand:
106
+
107
+ ```ts
108
+ const { api, session } = createKeboola({ baseUrl });
109
+ const result = await api.auth.login.withPassword({ email, password });
110
+ if (!result.mfaRequired) session.authenticate(result); // a TokenSet, not a token string
111
+ await session.setProjectAsync(42); // the session's scope — this is what `api.*` addresses
112
+
113
+ const other = await session.forProject(7); // a second project, alongside the first
114
+ const [mine, theirs] = await Promise.all([
115
+ api.storage.buckets.getBuckets({ branchId: 'default' }), // project 42
116
+ other.storage.buckets.getBuckets({ branchId: 'default' }), // project 7
117
+ ]);
118
+ ```
119
+
120
+ `setProjectAsync` **moves** the session (and `api`) to another project; `forProject` **adds** one. Use
121
+ `setProjectAsync` for the project the app is centred on, and `forProject` for every other project it
122
+ reads alongside — the returned clients are yours to hold and never appear on `api`.
123
+
124
+ - **One credential, one refresh loop.** Every set shares the session's auth middleware, so a token
125
+ rotation happens once and serves all of them.
126
+ - **Repeat calls are cheap** — a project is bootstrapped once and concurrent callers share that one
127
+ build. A failed build is retryable.
128
+ - **A project you cannot reach fails the build, not the session.** Connection answers a denied or
129
+ nonexistent project with the same `invalid_token` 401 as a revoked token — bearer failures are
130
+ collapsed deliberately, so scope cannot be probed. `forProject` is the only surface taking a
131
+ caller-supplied id, so it reads a 401 that survives a token rotation as being about the project:
132
+ the build rejects with the underlying `ApiError` and the session stays signed in. A credential that
133
+ really is dead still signs you out — the refresh itself 401s, which is unambiguous.
134
+ - **Independent of the scope**, in both directions: re-scoping the session never redirects a set
135
+ someone holds, and `forProject(scopedProject)` builds a _second_ set rather than reusing `api`'s.
136
+ For the project the app is centred on, use `api.*`.
137
+ - **Nothing extra is persisted.** Storage still holds one entry, `{ baseUrl, projectId, refreshToken }`
138
+ — and that `projectId` is the _scope_. The extra projects are runtime state; re-add them on startup.
139
+ - **`reset()` really is a teardown.** Every set is pinned to the sign-in that built it, so one held
140
+ across a sign-out throws `KeboolaError` (`NotAuthenticated`) on its next request instead of quietly
141
+ acting as whoever signed in after. Ask again for a fresh one. `clearProject()` drops the scope, not
142
+ the credential, so it leaves the extra projects alone.
143
+
144
+ The pin is not specific to `forProject`: **anything that emits this session's credential is bound to
145
+ the sign-in it was built on** — `api.storage`, `api.context`, `api.management`,
146
+ `session.getAuthHeaders()` and `session.restore()` included. The auth middleware holds no token, it
147
+ reads the credential live, so rebuilding a store on sign-out only stops new reads; a request already
148
+ in flight would otherwise complete as the next user, still stamped with the previous project.
149
+ `api.auth` is built once per stack and serves every session, so it pins each _request_ to the sign-in
150
+ that started it rather than to its build — enough to stop a 401 recovery from replaying as the next
151
+ user, and the next session's `login` runs unstamped either way. The guard wraps the **credential**,
152
+ not just the outgoing request: the 401 path rotates the token by calling the credential directly, and
153
+ a straggler from a dead session would otherwise spend the live session's single-use refresh token —
154
+ and sign that session out if the rotation itself came back 401. Anything new that takes the auth
155
+ middleware, or hands the credential to a transport we don't own, needs the same pin — see
156
+ `createPinnedAuthMiddleware` / `pinToSession` in `bearer/keboola.ts`.
157
+
158
+ **The pin has to cover the failure branches, not only the happy path** — that is where it keeps being
159
+ missed. Two shapes:
160
+
161
+ - **Anything that re-invokes `next` goes _inside_ the pin**, via `createPinnedAuthMiddleware`'s
162
+ `inner`, never beside it in the middleware array. The array's first element is the outermost one,
163
+ so a retry placed there re-enters the pin per attempt — and where the epoch is read per request
164
+ (`api.auth`) every attempt re-pins to whoever is signed in by then. A 503 backoff is long enough
165
+ for a sign-out to land in.
166
+ - **A rotation or a restore that _fails_ after its session ended must be re-labelled before the
167
+ error travels on.** A raw 401 is read as "this credential is dead" by `credential.ts` and as "the
168
+ stored token is dead" by `restore()`, and both then act on the session that replaced it — signing
169
+ it out, or clearing the storage entry it just wrote. Compare the epoch in the `catch` as well as
170
+ after the `await`.
171
+
172
+ ⚠️ **A second `createKeboola()` is not the way to reach a second project — it signs you out of both.**
173
+ Both instances hold the same single-use refresh token, and refresh _rotates_ it, with two-phase
174
+ rotation and replay detection on the server. Whichever instance rotates first invalidates the other's
175
+ token, whose next refresh 401s and signs it out. This is a functional break, not a style preference,
176
+ and it does not depend on a `storage` adapter being configured.
177
+
101
178
  In React, `useApiClient()` returns `api`; `AuthProvider` (bearer) / `LegacyAuthProvider` (legacy) own
102
179
  driving the `session` to ready and gate on a `fallback`. See
103
180
  [`@keboola/api-client-react`](../api-client-react/AGENTS.md).
@@ -112,7 +189,8 @@ const { api, session } = createKeboola({ baseUrl, storage: createLocalStorage()
112
189
  // On startup, call `session.restore()` to rehydrate: it exchanges the persisted refresh token for a
113
190
  // fresh credential eagerly (before any request), then re-scopes to the stored project. It resolves
114
191
  // `{ status: 'restored' | 'empty' | 'expired' }` — `expired` means the refresh token was dead and the
115
- // stored session was cleared; route to login. `session.reset()` clears the stored session.
192
+ // stored session was cleared; route to login. `session.reset()` clears the stored session — and one
193
+ // landing mid-restore wins: the restore resolves `empty` rather than signing the user back in.
116
194
  const result = await session.restore();
117
195
  ```
118
196
 
@@ -383,9 +461,9 @@ api.sdk.tag.* api.sdk.storage.*
383
461
 
384
462
  Clients backing optional stack services (vault, queue, …) throw `ServiceUnavailableError` if absent from the current stack — check `api.context.stack.hasService(...)` before assuming a namespace exists.
385
463
 
386
- **Liveness: every service client exposes a root-level `healthCheck()`** (all but `telemetry`, which has no such endpoint). It resolves with the service's payload when up and throws like any other call when not, and it needs no session — every one of these endpoints answers unauthenticated, so a probe works before login and is indifferent to whether a token rides along. Probe a service that way rather than by calling a real endpoint and interpreting the failure. **A 200 means up and a throw means down — that is the whole contract.** The payload is incidental, so **never hand-roll a response type** to make it look useful. Adding a client means adding its `healthCheck` too, and which client you probe through follows from the spec:
464
+ **Liveness: every service client exposes a root-level `healthCheck()`.** It resolves with the service's payload when up and throws like any other call when not, and it needs no session — every one of these endpoints answers unauthenticated, so a probe works before login and is indifferent to whether a token rides along. Probe a service that way rather than by calling a real endpoint and interpreting the failure. **A 200 means up and a throw means down — that is the whole contract.** The payload is incidental, so **never hand-roll a response type** to make it look useful. Adding a client means adding its `healthCheck` too, and which client you probe through follows from the spec:
387
465
 
388
- - the service's spec declares the probe path → **probe through the client's own OpenAPI client** (`client.get('/health-check', {}, { signal })`). The return type comes from the spec for free — no type argument, no alias in `types.ts`, and no generic client to construct. Five do today: `ai`, `editor`, `import`, `chat` (which probes `/ping`) and `apps` (which probes `/`, the only unauthenticated root the `/v2` surface declares).
466
+ - the service's spec declares the probe path → **probe through the client's own OpenAPI client** (`client.get('/health-check', {}, { signal })`). The return type comes from the spec for free — no type argument, no alias in `types.ts`, and no generic client to construct. Six do today: `ai`, `editor`, `import`, `telemetry`, `chat` (which probes `/ping`) and `apps` (which probes `/`, the only unauthenticated root the `/v2` surface declares).
389
467
  - it doesn't → fall back to a generic fetch client over the service `baseUrl` and **pass no type argument.** The payload resolves as `unknown`, which is honest: callers only need the 200.
390
468
 
391
469
  Both clients run the same middleware chain; the OpenAPI one additionally sends auth headers, which is fine — these endpoints answer the same with a valid token, a bogus one, or none.
package/API-SURFACE.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Every namespace and method reachable from a ready `KeboolaApi` — the `api` half of a keboola client (`createKeboola(...).api` / `createLegacyKeboola(...).api`, or `useApiClient()`). Generated from the TypeScript type checker — see `scripts/gen-surface.mjs`.
6
6
 
7
- 24 top-level namespaces, 621 methods. This index lists method **names** only — full signatures live per namespace under [`surface/`](./surface). Open `surface/<namespace>.md` for the one you need.
7
+ 25 top-level namespaces, 635 methods. This index lists method **names** only — full signatures live per namespace under [`surface/`](./surface). Open `surface/<namespace>.md` for the one you need.
8
8
 
9
9
  ## [`api.ai`](./surface/ai.md)
10
10
 
@@ -85,6 +85,12 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
85
85
  - `webauthn.registerOptions`
86
86
  - `webauthn.remove`
87
87
 
88
+ ## [`api.billing`](./surface/billing.md)
89
+
90
+ - `getCredits`
91
+ - `getCreditsAndTopUp`
92
+ - `healthCheck`
93
+
88
94
  ## [`api.chat`](./surface/chat.md)
89
95
 
90
96
  - `createChat`
@@ -184,6 +190,7 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
184
190
  - `getHistory`
185
191
  - `getSandboxGitBranch`
186
192
  - `getSkillsList`
193
+ - `getSpendCaps`
187
194
  - `getSuggestions`
188
195
  - `getToolsList`
189
196
  - `getUsage`
@@ -192,10 +199,12 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
192
199
  - `healthCheck`
193
200
  - `listSandboxFiles`
194
201
  - `readSandboxFile`
202
+ - `setUserSpendLimit`
195
203
  - `stopChat`
196
204
  - `submitToolOutput`
197
205
  - `submitVote`
198
206
  - `updateAgentSettings`
207
+ - `updateSpendCaps`
199
208
  - `updateUserAgentSettings`
200
209
 
201
210
  ## [`api.management`](./surface/management.md)
@@ -279,6 +288,13 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
279
288
  - `organizations.removeOrganizationUser`
280
289
  - `organizations.setOrganizationMetadata`
281
290
  - `organizations.updateOrganization`
291
+ - `payAsYouGo.createPaymentRequest`
292
+ - `payAsYouGo.getBillingConfiguration`
293
+ - `payAsYouGo.getCreditPurchases`
294
+ - `payAsYouGo.getStripeCustomer`
295
+ - `payAsYouGo.getTopUpSetting`
296
+ - `payAsYouGo.updateStripeCustomer`
297
+ - `payAsYouGo.updateTopUpSetting`
282
298
  - `projects.addProjectFeature`
283
299
  - `projects.addProjectTemplateFeature`
284
300
  - `projects.addProjectUser`
@@ -688,7 +704,8 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
688
704
 
689
705
  ## [`api.telemetry`](./surface/telemetry.md)
690
706
 
691
- - `provisioning.createCredentials`
707
+ - `getProvisioningToken`
708
+ - `healthCheck`
692
709
 
693
710
  ## [`api.vault`](./surface/vault.md)
694
711
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,470 @@
1
1
  # @keboola/api-client
2
2
 
3
+ ## 34.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - New `approvalGoneReasonSchema` / `ApprovalGoneReason` in `chat/types` — the shared wire contract for why a Kai approval slot is gone.
8
+
9
+ kai-agent now tombstones every removed approval slot and answers a POST to a gone slot with 409 carrying the reason as the error envelope's `subtype`, so the client can tell "already processed" and "the chat was stopped" apart from a genuine expiry instead of reading every 404 as one.
10
+
11
+ - `session.getAuthHeaders()` takes an optional project, so a host holding several projects can
12
+ authorize an off-client request against one the session is not scoped to. Until now this surface
13
+ read `X-KBC-ProjectId` off the session's own scope and nothing else, which left the chat SSE stream
14
+ — its only caller, and the one transport with no service client behind it — able to _read_ another
15
+ project through `session.forProject(id)` but never to send to it.
16
+
17
+ ```ts
18
+ // The session's own scope, exactly as before.
19
+ await session.getAuthHeaders();
20
+
21
+ // The project the caller names, whatever the session is scoped to.
22
+ await session.getAuthHeaders(projectId);
23
+ ```
24
+
25
+ - Omitting it is unchanged, including the rule that the scope is re-read _after_ the token
26
+ rotation: a `setProject` mid-flight lands, and a `clearProject` refuses the call.
27
+ - Naming one requires the session to be authenticated, not scoped. The credential is user-level and
28
+ the project is a header on top of it, so a caller that names a project has said everything the
29
+ request needs.
30
+ - A named project survives the rotation as given — it is the caller's, not the session's to move —
31
+ and the session pin is unchanged: a call whose rotation outlived its sign-in is still refused.
32
+ - The project is **not** checked against an access set, because the session cannot acquire one:
33
+ connection collapses every bearer failure into a single `invalid_token` response, so "no access to
34
+ this project" and "revoked token" are indistinguishable. That is the same reason
35
+ `session.forProject` does not probe scope either. Whether a project is reachable is the caller's
36
+ knowledge, from `token.introspect`; what this guarantees is that the header names what was asked
37
+ for and never something else.
38
+
39
+ - New `api.billing` namespace over the Billing API — the pay-as-you-go credit balance of the project
40
+ the token identifies.
41
+
42
+ ```ts
43
+ if (api.context.stack.hasService("billing")) {
44
+ const { remaining, stats } = await api.billing.getCredits();
45
+ }
46
+ ```
47
+
48
+ The service is a separate stack deployment (service id `billing`), not part of the Manage API that
49
+ `api.management.payAsYouGo` covers, and `/credits` authenticates with a Storage API token rather
50
+ than a Manage token — so it gets its own client rather than another method there. Types generate
51
+ from the service's published spec, newly registered in `redocly.yaml`.
52
+ - `getCredits` answers only for a project carrying the `pay-as-you-go` feature.
53
+ - `getCreditsAndTopUp` is the same read with an automatic top-up attempted first, which the service
54
+ runs only when the balance is at or below zero and the project has a top-up configuration
55
+ (`management.payAsYouGo.getTopUpSetting`). A charge that fails does not fail the call.
56
+ - `stats` is absent unless the project has consumption to report.
57
+
58
+ Three groups of endpoints stay unwrapped: `/duration/*` and `/marketplaces/{resolve-token,
59
+ confirm-subscription}` are service-to-service calls needing a Manage _application_ token with a
60
+ `billing:manage` or `marketplace-subscriptions:manage` scope, `/marketplaces/azure-webhook` is
61
+ called by Azure Marketplace against an Azure-issued JWT, and `/` only restates what `healthCheck`
62
+ already reports.
63
+
64
+ The spec's `servers` block names the queue host rather than the billing one; it is ignored, since
65
+ every stack client resolves its base URL from the stack's service index.
66
+
67
+ - `kaiAgent.getHistory` can ask for the conversations one app opened, and every history row says which
68
+ app opened it.
69
+
70
+ ```ts
71
+ // Only what this app started — a business user never sees the data team's Kai threads.
72
+ const { chats } = await api.kaiAgent.getHistory({ client: "business-chat" });
73
+ ```
74
+
75
+ kai-agent lists a project's conversations without regard to which host started them, so a second
76
+ host on the same agent shows its readers somebody else's chats. The service now records the host on
77
+ the chat and filters on it; this is the SDK half.
78
+ - `client` is `'kbc-ui' | 'business-chat'`, and omitting it keeps the current behaviour — every
79
+ conversation, whatever opened it.
80
+ - The row's own `client` is nullable: a chat opened before the service recorded it is unattributable,
81
+ and the service gives those to `kbc-ui`. So a filtered list starts from the deploy, not from the
82
+ project's first conversation.
83
+ - `POST /api/chat` accepts the same `client` on its body, which is what a host sets so its
84
+ conversations are attributed at all.
85
+
86
+ Regenerated from the deployed spec, so `getSpendCaps` / `updateSpendCaps` now carry
87
+ `defaultProjectCapPpu` in the generated schema too. Nothing changes for a caller — the method
88
+ already returned that field through a hand-written zod schema while the service rolled out, and the
89
+ fallback stays until every stack has the deploy.
90
+
91
+ - Type the maintainer SAML SSO read responses (ST-4306).
92
+
93
+ `management/maintainers/types` exports `SamlConfigSummary` and `SamlConfigDetail`, derived from the
94
+ regenerated management schema. The two `GET /manage/maintainers/{maintainerId}/saml*` responses were
95
+ previously typed with every field optional and without `membershipRestriction`; the schema now marks
96
+ all of them required and the detail response also carries `permittedEmailDomains`, so callers no
97
+ longer have to guard fields the backend always sends. The list endpoint documents its 403.
98
+
99
+ The six client methods are unchanged — the two getters pick up the tightened return types on their
100
+ own.
101
+
102
+ - `api.management.payAsYouGo` covers the pay-as-you-go billing endpoints — the credit price and tax
103
+ rates the checkout quotes, a project's credit purchases, its Stripe customer and saved cards, and
104
+ its automatic top-up configuration.
105
+
106
+ ```ts
107
+ const { "credit-price": creditPrice } =
108
+ await api.management.payAsYouGo.getBillingConfiguration();
109
+ const purchases =
110
+ await api.management.payAsYouGo.getCreditPurchases(idProject);
111
+ const { clientSecret } = await api.management.payAsYouGo.createPaymentRequest(
112
+ {
113
+ idProject,
114
+ amount: 100,
115
+ saveCard: true,
116
+ },
117
+ );
118
+ ```
119
+
120
+ Connection serves these off the same host as the Manage API but outside its `/manage` prefix, and
121
+ they accept a Manage token of type `admin` or `session`, so they run through the management client's
122
+ auth middleware like every other management method.
123
+ - Parameters carry the endpoint's own names: the project is `idProject` everywhere except
124
+ `getTopUpSetting`, whose path names it `projectId`.
125
+ - `getStripeCustomer` resolves `null` when the project has no Stripe customer yet — the endpoint
126
+ answers 204.
127
+ - `updateTopUpSetting` resolves `void`; the endpoint answers 202 with no body, so read the stored
128
+ configuration back with `getTopUpSetting`.
129
+ - `getTopUpSetting` throws a 404 `ApiError` when top-up was never configured for the project, which
130
+ is a product state rather than a failure.
131
+
132
+ Four response types are tightened past the manage OpenAPI document, which is looser than the
133
+ endpoints: `credit-price` and the three top-up fields and `clientSecret` are required rather than
134
+ optional, `stripeInvoiceStatus` and `invoiceTopUpType` are unions rather than bare strings, and
135
+ `moneyAmount` is nullable. They revert to plain generated types once connection's spec is corrected.
136
+
137
+ The maintainer SAML responses gained `membershipRestriction`, `getMaintainerSamlConfig` gained
138
+ `permittedEmailDomains`, and both configs' fields are no longer optional — the manage OpenAPI
139
+ document now marks them required.
140
+
141
+ - New `canWriteSemanticLayer(token)` permission predicate — whether a project role may create, update
142
+ or delete semantic-layer objects in the metastore.
143
+
144
+ ```ts
145
+ if (canWriteSemanticLayer(api.context.project.sapiToken)) {
146
+ // offer the add / edit / delete affordances
147
+ }
148
+ ```
149
+
150
+ A denylist, unlike `canWriteKaiSettings`: the metastore's project-level ACL admits ordinary project
151
+ work, so only `readOnly` is refused. Organization-scope promotion stays a separate, narrower right
152
+ the metastore answers with a 403.
153
+
154
+ - `api.telemetry` moves onto its own OpenAPI document, loses its one-method sub-namespace, and gains
155
+ the endpoint the embed dashboards need.
156
+
157
+ ```ts
158
+ const { token } = await api.telemetry.getProvisioningToken({
159
+ project_type: projectType,
160
+ });
161
+ ```
162
+
163
+ - **`getProvisioningToken`** returns the short-lived ES256 JWT a telemetry embed authenticates with.
164
+ Both response fields are optional in the spec, so check `token` before use.
165
+ - **`healthCheck`** joins the other service clients. The endpoint was only ever thought missing
166
+ because its path sits behind the ingress prefix described below.
167
+ - **`provisioning.createCredentials` is gone**, and with it the `provisioning` namespace, so the two
168
+ remaining methods sit directly on `api.telemetry`. It posted to an endpoint the service does not
169
+ route, document, or implement — the word `workspace` appears nowhere in
170
+ `keboola/gooddata-cn-provisioning`, and one ingress rule sends all of `/provisioning/*` to that
171
+ one backend, so there was nowhere else it could have landed. It answered 404 on every stack
172
+ probed and had no caller. `CreateCredentialsBody` and `WorkspaceData` go with it.
173
+
174
+ Types generate from the service's own `swagger.yaml`, newly registered in `redocly.yaml`. Its repo
175
+ is private and it does not serve the document over HTTP, so the spec is vendored beside the
176
+ generated schema — the same local-root arrangement `microsoftGraph` uses.
177
+
178
+ The client owns the `/provisioning` prefix rather than its callers: the service listens on its root,
179
+ and one ingress rule on the telemetry host routes that prefix to it. `baseUrl` stays the plain
180
+ telemetry service URL, and request paths stay the spec's own (`/token`, `/health`).
181
+
182
+ `project_type` is a free-form string passed straight into the JWT claim, not an enum — the service
183
+ validates it nowhere.
184
+
185
+ - Expose organization membership on project users. The shared User type keeps the field optional for older stacks and endpoints that do not return project membership.
186
+
187
+ ### Patch Changes
188
+
189
+ - A successful `text/html` response is only read as Connection's login screen when it actually carries
190
+ a body. Symfony's `Response::prepare()` stamps `Content-Type: text/html` on every bodyless response
191
+ but `204`/`304`, so a framework default was being reported to the user as an expired session.
192
+
193
+ `PUT /pay-as-you-go/billing/top-up` answers `202` with an empty body, and it is the middle call of
194
+ the kbc-ui Pay flow — so buying pay-as-you-go credits failed with "You will be logged out
195
+ automatically." for every user, on every auth strategy, and never reached Stripe. The same trap was
196
+ live on the invitation, join-request, password-reset and token-revoke endpoints.
197
+
198
+ Both validators are fixed, `validateManagementStatus` (`ManagementClientAuthError`) and
199
+ `validateConnectionStatus` (`HtmlResponseError`, used by the storage and auth clients), through a
200
+ new shared `isLoginPageRedirect` — `isHtmlResponse && !isContentEmpty`. `isHtmlResponse` keeps its
201
+ header-only meaning and `isContentEmpty` is new; calling the header check on its own is what read an
202
+ empty `202` as a login page. All three are workspace-internal, not part of the package's public
203
+ export surface.
204
+
205
+ Connection declares JSON on those responses in connection#8414; this is the client-side half
206
+ and holds regardless of what a service labels an empty body.
207
+
208
+ - The semantic-layer SDK parses what it reads instead of asserting it, so an object that does not
209
+ match its declared shape is dropped rather than handed to a caller half-formed.
210
+
211
+ `listModels` and `listObjects` cast the metastore's response to the types in
212
+ `sdk/semanticLayer/types`. Those types declare `SemanticMetricData.name`, `.sql` and
213
+ `SemanticGlossaryData.term`, `.definition` as required strings, and every consumer is entitled to
214
+ call a method on them — the first one to do so (`.trim()`, in business-chat's openers) turns a
215
+ missing field into a `TypeError` thrown inside a render.
216
+ - Each element is validated against its object type's shape. One that fails is left out and the
217
+ reason logged — object type, UUID, and which field is wrong, never the payload, because a model's
218
+ vocabulary and its SQL are the customer's.
219
+ - A drop never takes its container with it, at either level: a model holding one malformed metric
220
+ still lists the other nine, and a dataset carrying one nameless field still lists its other
221
+ columns rather than disappearing from the model.
222
+ - A response that is not a collection still throws a `ValidationError` — reading it as an empty
223
+ list would say "this project has no metrics".
224
+ - Undeclared fields still reach callers untouched, exactly as they did under the cast.
225
+ - `SemanticObject.meta` stops lying: an envelope that omits it — or sends it as `null` — now
226
+ normalizes to `{}` rather than being typed as present and arriving `undefined`.
227
+ - An **optional** enum carrying a value outside the list (`role`, `severity`, `scope`, a
228
+ relationship's `type`) reads as absent instead of dropping its object — a new value the metastore
229
+ starts issuing must not delete the dataset carrying it. A required one (`constraintType`) has no
230
+ such reading.
231
+
232
+ **`listModelChildren` now throws `SemanticLayerUnreadableChildrenError` instead of degrading**, and
233
+ `deleteModel` inherits it. A list read degrades because a shorter list is still useful; this one
234
+ cannot, because it answers what a delete would destroy. A dropped child would otherwise be missing
235
+ from the cascade, leave `failedChildren` empty, and let the model be deleted — orphaning an object
236
+ whose `modelUUID` points at a model that no longer exists and that no list returns, so it can never
237
+ be found, fixed or deleted again. The throw happens before the first child delete, so a refusal
238
+ destroys nothing. An unreadable object is counted against the model its raw envelope names, and
239
+ against every model when the envelope cannot name one.
240
+
241
+ Writes are untouched: the metastore echoes back the object it has just validated and stored.
242
+
243
+ `formatValidationIssues` is now exported alongside `ValidationError`, for boundaries that degrade
244
+ instead of throwing and still owe a one-line reason.
245
+
246
+ ## 33.0.0
247
+
248
+ ### Minor Changes
249
+
250
+ - `createEmitter` delivers events in emission order, never nested, and `Store` gains `asReadable()`.
251
+ - An `emit` from inside a listener is queued until the current pass has reached every listener, so
252
+ no listener hears event N+1 before event N. For a store this means a subscriber that writes back
253
+ can no longer leave a later subscriber on stale state — the last notification is always the
254
+ latest value.
255
+ - A listener's own emit is handled after it returns; a throwing listener is logged and does not
256
+ stall the queue behind it. Nothing is coalesced: every event is delivered.
257
+ - A pass reaches the listeners present when it began. Subscribing from inside a listener no longer
258
+ delivers the event in flight to the new listener — it hears the next one, as it would have had it
259
+ subscribed a moment earlier. Unsubscribing (or `clear()`) from inside a listener still takes
260
+ effect immediately for the rest of that pass.
261
+ - `store.asReadable()` returns the same store without `set` — the read-only view consumers were
262
+ building by hand from `get` / `subscribe` / `dispose`.
263
+
264
+ - `auth.pat.create` / `auth.pat.exchange` take a `CreatePatInput` / `ExchangePatInput` whose optional
265
+ fields may be left out, and drop the keys a caller passes as `null` instead of putting them on the
266
+ wire. The spec documents every optional PAT field as "omit, do not send `null`", but the generated
267
+ bodies demand each of them, so a caller holding a nullable — an empty expiry picker, an untouched
268
+ read-only switch — had no way to express the default. `scope` gains the same treatment: a
269
+ `{ projects, readOnly }` that narrows nothing is sent as no `scope` at all.
270
+
271
+ Existing calls keep compiling and keep their behaviour, since the previously required
272
+ `expiresIn: null` / `scope: null` is what the normaliser now drops.
273
+
274
+ - The semantic layer's closed value sets ship as runtime lists, so an authoring surface no longer
275
+ writes them out by hand. `FIELD_ROLES`, `CONSTRAINT_SEVERITIES`, `CONSTRAINT_SCOPES`,
276
+ `RULE_OPERATORS` and `RELATIONSHIP_JOIN_TYPES` join `SQL_DIALECTS` and `CONSTRAINT_TYPES`, which
277
+ move to the same module and keep their existing import paths.
278
+
279
+ ```ts
280
+ import {
281
+ CONSTRAINT_SCOPES,
282
+ metastoreErrorMessage,
283
+ } from "@keboola/api-client/sdk/semanticLayer";
284
+ import type { SemanticConstraintScope } from "@keboola/api-client/sdk/semanticLayer/types";
285
+
286
+ // a total label map, so a scope the metastore adds is a compile error rather than a missing option
287
+ const SCOPE_LABELS: Record<SemanticConstraintScope, string> = {
288
+ global: "Global" /* … */,
289
+ };
290
+ const options = CONSTRAINT_SCOPES.map((value) => ({
291
+ value,
292
+ label: SCOPE_LABELS[value],
293
+ }));
294
+ ```
295
+
296
+ - Each union in `./types` is now derived from its list rather than spelled out again, so the type
297
+ and the list a validator or a dropdown is built from cannot disagree. `SemanticConstraintSeverity`
298
+ and `SemanticRelationshipJoinType` are named for the first time; they were inline unions on
299
+ `SemanticConstraintData.severity` and `SemanticRelationshipData.type`.
300
+ - The `./sdk/semanticLayer/types` entry point stays free of runtime code — the derivation reads the
301
+ lists through an `import type`.
302
+ - `metastoreErrorMessage(body)` reads the one field that says what is actually wrong with a
303
+ rejected write (`errors[0].message`, e.g. `missing property 'fqn'`). The status and the
304
+ response's own message say no more than "Validation failed". Any other shape returns `undefined`,
305
+ so a caller keeps its own fallback.
306
+
307
+ - Reach several projects from one bearer session with `session.forProject(projectId)`
308
+
309
+ A bearer access token is a user token — project scope is a single `X-KBC-ProjectId` header — so one
310
+ session can legitimately address many projects. Until now only the scoped project had clients, and
311
+ the obvious workaround was a second `createKeboola()`, which signs both instances out: they hold the
312
+ same single-use refresh token, and the first to rotate invalidates the other's.
313
+
314
+ `session.forProject(projectId)` returns that project's `ProjectClients` off the session in hand,
315
+ reusing its credential and auth middleware, so a token rotation happens once for every project rather
316
+ than once each. `setProjectAsync` moves the session (and `api`); `forProject` adds a project alongside
317
+ it. A project is bootstrapped once and concurrent callers share that build; a failed build is
318
+ retryable.
319
+
320
+ Every client set is pinned to the sign-in that built it, so `reset()` is a teardown rather than a
321
+ cache eviction — a set held across a sign-out throws `NotAuthenticated` on its next request, the 401
322
+ replay included, instead of quietly acting as whoever signed in after. `clearProject()` drops the
323
+ scope, not the credential, and leaves the extra projects alone. Nothing extra is persisted.
324
+
325
+ The same pin covers every other surface that emits this session's credential.
326
+ `api.storage`/`api.context` and `api.management` rebuild on sign-out, but that could not stop a
327
+ request already in flight from completing as the next user, with the previous project's
328
+ `X-KBC-ProjectId` still on it. `session.getAuthHeaders()` resolved to the dead session's token and
329
+ project, because the proactive rotation swallows its own refusal. A token rotation is pinned to the
330
+ sign-in that spent the refresh token, so one resolving after its own session ended is dropped rather
331
+ than written over the credential of whoever signed in since, and a sign-out abandons the in-flight
332
+ rotation so the next session starts its own. `api.auth` is built once per stack and serves every
333
+ session, so it pins each _request_ to the sign-in that started it: a 401 recovery no longer replays
334
+ as the next user, while `login` still goes out unstamped. `session.restore()` is pinned too — a
335
+ sign-out landing while the stored token is being exchanged resolves `empty` instead of signing the
336
+ user back in.
337
+
338
+ The guard wraps the **credential**, not only the outgoing request, because the 401 path rotates the
339
+ token by calling the credential directly: a straggler from a dead session would otherwise spend the
340
+ live session's single-use refresh token, and sign that session out if the rotation itself came back 401.
341
+
342
+ The pin covers the failure branches too, which is where it was missed. A retry re-invokes `next`,
343
+ so `retryContention` is composed _inside_ the pin rather than beside it in the auth client's
344
+ middleware array — outside it, an `api.auth` request that hit a 503 re-pinned per attempt and the
345
+ retry went out as whoever signed in during the backoff. And a rotation or a restore that _fails_
346
+ after its session ended is re-labelled `NotAuthenticated` before the error travels on: a raw 401
347
+ reads as "this credential is dead" to the credential and as "the stored token is dead" to
348
+ `restore()`, so a straggler used to sign out the session that replaced it, and a losing concurrent
349
+ restore used to clear the winner's stored session — leaving it alive in memory and gone on the next
350
+ reload.
351
+
352
+ A project the session cannot reach now fails its own build and nothing else. Connection answers a
353
+ denied or nonexistent project with the same `invalid_token` 401 as a revoked token, so `forProject`
354
+ reads a 401 that survives a token rotation as being about the project rather than the credential —
355
+ a mistyped project id used to sign the whole session out.
356
+
357
+ `ProjectClients` is now exported as a type.
358
+
359
+ ### Patch Changes
360
+
361
+ - `kaiAgent`'s spend-caps response gains `defaultProjectCapPpu` — the bare platform default project
362
+ cap, independent of what's persisted. Previously only `effectiveProjectCapPpu` (the server's
363
+ resolution of the _persisted_ cap) was exposed, which a consumer could not use to validate a
364
+ cleared-but-unsaved project-cap field against the true default.
365
+
366
+ - `kaiAgent`'s generated schema is regenerated against the deployed spec, so `getUsage` reports the
367
+ spend-cap scope and the one project-level figure a plain member is shown.
368
+ - `getUsage` gains `ppuLimitScope: 'user' | 'project' | null` — which ceiling stops the caller next.
369
+ A label, never a figure: the project's absolute budget stays admin-only.
370
+ - `getUsage` gains `projectPpuPercentage: number | null` — how much of the project's cap is spent.
371
+ It is the fallback a caller with no personal `ppuLimit` is measured against, and `null` only
372
+ where no project cap applies at all.
373
+ - `getChat` gains `ppuPercentage: number | null`, the same figure alongside a conversation.
374
+ - The `rate_limit` error `subtype` splits `monthly_credits` into `monthly_credits_user` and
375
+ `monthly_credits_project`.
376
+ - Additive drift the same regeneration picked up: the `/api/settings/spend-caps` pair, the
377
+ `/api/chat/{id}/sandbox/file/download` path, and a `payload_too_large` error type with its 413.
378
+
379
+ - `Result` gains constructors, guards and combinators, so code that returns a `Result` of its own no
380
+ longer writes the object literal, and code that consumes one no longer branches on `success` by
381
+ hand.
382
+
383
+ ```ts
384
+ import { Result } from "@keboola/api-client";
385
+
386
+ const getStack = (id: string): Result<Stack> =>
387
+ stacks.has(id)
388
+ ? Result.success(stacks.get(id))
389
+ : Result.failure(new Error(`No stack "${id}"`));
390
+
391
+ // handle both branches in one expression, Rust-match style
392
+ const label = Result.match(
393
+ getStack(id),
394
+ (stack) => stack.name,
395
+ (error) => error.message,
396
+ );
397
+
398
+ // at a layer boundary, relabel the failure as the error this layer speaks, then throw it
399
+ const stack = Result.unwrap(
400
+ Result.mapError(
401
+ getStack(id),
402
+ () => new KeboolaError(KeboolaErrorType.Unconfigured),
403
+ ),
404
+ );
405
+ ```
406
+
407
+ - `success` is `Result<T, never>` and `failure` is `Result<never, E>`, so either widens into any
408
+ `Result<T, E>` without an annotation. `Success<T>` and `Failure<E>` name the two branches.
409
+ - `isSuccess` / `isFailure` are type guards; `map`, `mapError` and `andThen` rewrite one branch
410
+ and pass the other through untouched.
411
+ - `match(result, onSuccess, onFailure)` returns whichever callback ran, so the two must agree on a
412
+ type; `void` works. `unwrap` throws the error as-is; `unwrapOr` returns a fallback instead.
413
+ - `tryCatch` and `fromThrowable` reject a task that returns a promise at the type level, since they
414
+ would report success before it settles. Use `tryCatchAsync` / `fromThrowableAsync` for those.
415
+
416
+ - `TableDetail` declares the three freshness fields the detail response carries: `lastImportDate`,
417
+ `lastChangeDate` and `rowsCount`.
418
+
419
+ ```ts
420
+ const table = await api.storage.tables.getTable({ branchId, id });
421
+ // `null` is the table's own answer — nothing has ever been written into it.
422
+ if (table.lastImportDate === null) return "Nothing loaded yet";
423
+ ```
424
+
425
+ - Declared required, where `TableDetailResponse` in the generated schema marks them optional. That
426
+ node marks `?` on every nullable field it has, so the marker conflates "nullable" with
427
+ "optional"; `TableCreateResponse` — which the table list reuses — and `AliasFilterSetResponse`
428
+ declare the same fields required-and-nullable. `Table` and `TableDetail` now agree on all three.
429
+ - `null` means different things per field, and each one says so: never written into
430
+ (`lastImportDate`), and Storage declining to count rather than a count of zero (`rowsCount`).
431
+
432
+ - `isTimeoutError` joins `isAbortError` in the fetch-client error taxonomy, exported from both
433
+ `@keboola/api-client` and `@keboola/api-client/fetchClient`.
434
+
435
+ ```ts
436
+ import { isTimeoutError } from "@keboola/api-client";
437
+
438
+ // `DOMException('signal timed out', 'TimeoutError')` — what an `AbortSignal.timeout` rejects with.
439
+ if (isTimeoutError(error)) return null;
440
+ ```
441
+
442
+ - Matches on `DOMException.name`, since the message is a browser string rather than a contract.
443
+ - Distinct from `isAbortError`: a timeout is the deadline expiring, an abort is someone cancelling.
444
+ - `xhrFetch` is not covered — its `handleAbort` builds an `AbortError` without reading
445
+ `signal.reason`, so a timeout on that transport reports as a cancel.
446
+
447
+ `@keboola/sentry`'s shared `beforeSend` is the first caller: a request that never got a response
448
+ measures the network, not the code, and reports with no stacktrace.
449
+
450
+ - Security patches for transitive dependencies: qs 6.16.0 in api-client, mermaid 11.17.2 and dompurify
451
+ 3.4.14 in design.
452
+
453
+ No API or behaviour change in either package.
454
+
455
+ - Interpret the org-admin `kai-assistant.monthlyCreditsLimitPerUser` Storage key as PPU (the same
456
+ unit an admin sees and sets everywhere else, per AI-3628), converting it to the internal
457
+ Kai-credits ceiling at the read boundary. `@keboola/api-client`'s kai-agent schema regenerated to
458
+ pick up `ppuUsed`/`ppuLimit` on `GET /api/usage`; `@keboola/kai-fake-agent`'s stub updated to match.
459
+ `@keboola/kai-agent` and `@keboola/kbc-ui` are private, nothing to release for them — acknowledged
460
+ so `changeset status` doesn't choke on them alongside the real `@keboola/api-client` release.
461
+
462
+ - Show Kai spend caps in project settings and scope-aware chat copy (AI-3738).
463
+
464
+ `@keboola/api-client`'s kai-agent client/surface-docs regenerated for the spend-caps endpoints;
465
+ `@keboola/constants`, `@keboola/kai-fake-agent`, `@keboola/kai-agent` and `@keboola/kbc-ui` are
466
+ private, nothing to release for them — acknowledged so `changeset status` doesn't choke on them.
467
+
3
468
  ## 32.0.0
4
469
 
5
470
  ### Major Changes