@keboola/api-client 32.0.0 → 33.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 (377) hide show
  1. package/AGENTS.md +80 -2
  2. package/API-SURFACE.md +4 -1
  3. package/CHANGELOG.md +222 -0
  4. package/dist/{ManagementClientAuthError-B-tyPlyG.cjs → ManagementClientAuthError-DqeXL8nv.cjs} +2 -2
  5. package/dist/{ManagementClientAuthError-B-tyPlyG.cjs.map → ManagementClientAuthError-DqeXL8nv.cjs.map} +1 -1
  6. package/dist/{ManagementClientAuthError-BAFNvOdf.js → ManagementClientAuthError-iKbBugKC.js} +2 -2
  7. package/dist/{ManagementClientAuthError-BAFNvOdf.js.map → ManagementClientAuthError-iKbBugKC.js.map} +1 -1
  8. package/dist/ai/index.cjs +2 -2
  9. package/dist/ai/index.d.cts +2 -2
  10. package/dist/ai/index.d.ts +2 -2
  11. package/dist/ai/index.js +2 -2
  12. package/dist/ai/types.d.cts +1 -1
  13. package/dist/ai/types.d.ts +1 -1
  14. package/dist/{appLogs-DTLE6HTy.js → appLogs-D72eD8vP.js} +2 -2
  15. package/dist/{appLogs-DTLE6HTy.js.map → appLogs-D72eD8vP.js.map} +1 -1
  16. package/dist/{appLogs-NIEDTDHf.cjs → appLogs-D8K0VeNM.cjs} +2 -2
  17. package/dist/{appLogs-NIEDTDHf.cjs.map → appLogs-D8K0VeNM.cjs.map} +1 -1
  18. package/dist/{appLogs-BAaaGYKg.d.cts → appLogs-Q4A7A_Fc.d.cts} +2 -2
  19. package/dist/{appLogs-DX_WTBCa.d.ts → appLogs-u0XMZLjS.d.ts} +2 -2
  20. package/dist/apps/index.cjs +3 -3
  21. package/dist/apps/index.d.cts +3 -3
  22. package/dist/apps/index.d.ts +3 -3
  23. package/dist/apps/index.js +3 -3
  24. package/dist/apps/types.d.cts +2 -2
  25. package/dist/apps/types.d.ts +2 -2
  26. package/dist/assets/index.cjs +1 -1
  27. package/dist/assets/index.d.cts +1 -1
  28. package/dist/assets/index.d.ts +1 -1
  29. package/dist/assets/index.js +1 -1
  30. package/dist/auth/index.cjs +1 -1
  31. package/dist/auth/index.d.cts +1 -1
  32. package/dist/auth/index.d.ts +1 -1
  33. package/dist/auth/index.js +1 -1
  34. package/dist/auth/types.d.cts +2 -2
  35. package/dist/auth/types.d.ts +2 -2
  36. package/dist/{auth-DP-6TFiM.cjs → auth-C2_JLisH.cjs} +2 -2
  37. package/dist/{auth-DP-6TFiM.cjs.map → auth-C2_JLisH.cjs.map} +1 -1
  38. package/dist/{auth-DtbQaeDj.js → auth-CE9rQV3-.js} +2 -2
  39. package/dist/{auth-DtbQaeDj.js.map → auth-CE9rQV3-.js.map} +1 -1
  40. package/dist/{authClient--BtZgjIc.js → authClient-DEyqR7GW.js} +43 -9
  41. package/dist/authClient-DEyqR7GW.js.map +1 -0
  42. package/dist/{authClient-DhfzOUaa.d.cts → authClient-DZ_8lvdJ.d.cts} +6 -6
  43. package/dist/{authClient-CtfyVHRD.d.ts → authClient-DwT6xdg5.d.ts} +6 -6
  44. package/dist/{authClient-b7uec7sw.cjs → authClient-IwQ9Ti0J.cjs} +43 -9
  45. package/dist/authClient-IwQ9Ti0J.cjs.map +1 -0
  46. package/dist/chat/index.cjs +3 -3
  47. package/dist/chat/index.d.cts +2 -2
  48. package/dist/chat/index.d.ts +2 -2
  49. package/dist/chat/index.js +3 -3
  50. package/dist/chat/types.d.cts +1 -1
  51. package/dist/chat/types.d.ts +1 -1
  52. package/dist/{createFetchClient-BbG46bL0.js → createFetchClient-DdyZMhxO.js} +3 -2
  53. package/dist/{createFetchClient-BbG46bL0.js.map → createFetchClient-DdyZMhxO.js.map} +1 -1
  54. package/dist/{createFetchClient-BRfTjBLV.cjs → createFetchClient-DvZvD31l.cjs} +8 -1
  55. package/dist/{createFetchClient-BRfTjBLV.cjs.map → createFetchClient-DvZvD31l.cjs.map} +1 -1
  56. package/dist/{createGenericFetchClient-BHYQLZhe.js → createGenericFetchClient-MQeLRiNW.js} +2 -2
  57. package/dist/{createGenericFetchClient-BHYQLZhe.js.map → createGenericFetchClient-MQeLRiNW.js.map} +1 -1
  58. package/dist/{createGenericFetchClient-DHs-i7_O.cjs → createGenericFetchClient-qfCZlCTv.cjs} +2 -2
  59. package/dist/{createGenericFetchClient-DHs-i7_O.cjs.map → createGenericFetchClient-qfCZlCTv.cjs.map} +1 -1
  60. package/dist/{createOpenapiFetchClient-CyDUFxHB.cjs → createOpenapiFetchClient-C57Ljzi6.cjs} +2 -2
  61. package/dist/{createOpenapiFetchClient-CyDUFxHB.cjs.map → createOpenapiFetchClient-C57Ljzi6.cjs.map} +1 -1
  62. package/dist/{createOpenapiFetchClient-Bn6_Pn0H.js → createOpenapiFetchClient-E7OIVkYv.js} +2 -2
  63. package/dist/{createOpenapiFetchClient-Bn6_Pn0H.js.map → createOpenapiFetchClient-E7OIVkYv.js.map} +1 -1
  64. package/dist/{credential-d2RDcXRB.js → credential-Bxv7yxOZ.js} +7 -4
  65. package/dist/credential-Bxv7yxOZ.js.map +1 -0
  66. package/dist/{credential-DOXH7XRS.cjs → credential-D-X5QQrM.cjs} +7 -4
  67. package/dist/credential-D-X5QQrM.cjs.map +1 -0
  68. package/dist/dataScience/index.cjs +2 -2
  69. package/dist/dataScience/index.d.cts +2 -2
  70. package/dist/dataScience/index.d.ts +2 -2
  71. package/dist/dataScience/index.js +2 -2
  72. package/dist/dataScience/types.d.cts +2 -2
  73. package/dist/dataScience/types.d.ts +2 -2
  74. package/dist/{dataScience-wexHEIue.cjs → dataScience-BPW993AG.cjs} +5 -5
  75. package/dist/{dataScience-wexHEIue.cjs.map → dataScience-BPW993AG.cjs.map} +1 -1
  76. package/dist/{dataScience-Sm8iONhP.js → dataScience-B_TA7wCB.js} +5 -5
  77. package/dist/{dataScience-Sm8iONhP.js.map → dataScience-B_TA7wCB.js.map} +1 -1
  78. package/dist/developerPortal/index.cjs +1 -1
  79. package/dist/developerPortal/index.d.cts +2 -2
  80. package/dist/developerPortal/index.d.ts +2 -2
  81. package/dist/developerPortal/index.js +1 -1
  82. package/dist/developerPortal/types.d.cts +1 -1
  83. package/dist/developerPortal/types.d.ts +1 -1
  84. package/dist/{developerPortalClient-CgTSzLoG.cjs → developerPortalClient-Db2XVB_o.cjs} +3 -3
  85. package/dist/{developerPortalClient-CgTSzLoG.cjs.map → developerPortalClient-Db2XVB_o.cjs.map} +1 -1
  86. package/dist/{developerPortalClient-DywKpDlW.js → developerPortalClient-jk46sjwP.js} +3 -3
  87. package/dist/{developerPortalClient-DywKpDlW.js.map → developerPortalClient-jk46sjwP.js.map} +1 -1
  88. package/dist/domain/permissions/index.d.cts +2 -2
  89. package/dist/domain/permissions/index.d.ts +2 -2
  90. package/dist/editor/index.cjs +2 -2
  91. package/dist/editor/index.d.cts +2 -2
  92. package/dist/editor/index.d.ts +2 -2
  93. package/dist/editor/index.js +2 -2
  94. package/dist/editor/types.d.cts +1 -1
  95. package/dist/editor/types.d.ts +1 -1
  96. package/dist/emitter-dLF1Fyfg.d.cts +11 -0
  97. package/dist/emitter-dLF1Fyfg.d.ts +11 -0
  98. package/dist/encryption/index.cjs +1 -1
  99. package/dist/encryption/index.d.cts +1 -1
  100. package/dist/encryption/index.d.ts +1 -1
  101. package/dist/encryption/index.js +1 -1
  102. package/dist/encryption/types.d.cts +1 -1
  103. package/dist/encryption/types.d.ts +1 -1
  104. package/dist/import/index.cjs +1 -1
  105. package/dist/import/index.d.cts +3 -3
  106. package/dist/import/index.d.ts +3 -3
  107. package/dist/import/index.js +1 -1
  108. package/dist/{import-SQuurg1G.js → import-2nqxQ9Rt.js} +3 -3
  109. package/dist/{import-SQuurg1G.js.map → import-2nqxQ9Rt.js.map} +1 -1
  110. package/dist/{import-C0-y1GQK.cjs → import-DJilJ6tq.cjs} +3 -3
  111. package/dist/{import-C0-y1GQK.cjs.map → import-DJilJ6tq.cjs.map} +1 -1
  112. package/dist/{index-FhKX7Cv1.d.ts → index-B0V1pJAa.d.ts} +241 -200
  113. package/dist/{index-Bg1P6Bb2.d.ts → index-B2OGaUap.d.ts} +6 -6
  114. package/dist/{index-Dbzjvy5h.d.ts → index-BjKjp3Rf.d.ts} +5 -5
  115. package/dist/{index-DeKPpYQy.d.ts → index-C7gxKoDF.d.cts} +3 -3
  116. package/dist/{index-D_7yCRKy.d.cts → index-CTd4YY8e.d.cts} +4 -4
  117. package/dist/{index-DiHHyMEo.d.cts → index-CUXEFQ7i.d.cts} +6 -6
  118. package/dist/{index-eAlN694c.d.cts → index-CVqk63at.d.ts} +3 -3
  119. package/dist/{index-Bc_hXWae.d.ts → index-C_cxKL1V.d.ts} +3 -3
  120. package/dist/{index-tKsiUarj.d.ts → index-ChMtULt4.d.ts} +4 -4
  121. package/dist/{index-Gn1H63Hk.d.cts → index-DCN2lH0v.d.cts} +4 -4
  122. package/dist/{index-Bjk-tCpG.d.cts → index-DIVvL54G.d.cts} +241 -200
  123. package/dist/{index-C7e3wBt9.d.cts → index-DLYAvSWZ.d.cts} +3 -3
  124. package/dist/{index-fHfc_VqS.d.ts → index-DQef014j.d.ts} +4 -4
  125. package/dist/{index-CeJOmN-P.d.ts → index-DVhTNwvu.d.ts} +3 -2
  126. package/dist/{index-CQrKS7PV.d.cts → index-DhVFuQDv.d.cts} +3 -2
  127. package/dist/{index-Ctqkm3Fx.d.ts → index-GNKwr7EQ.d.ts} +4 -4
  128. package/dist/{index-GDdFZCXp.d.ts → index-bB6wvw1f.d.ts} +4 -4
  129. package/dist/{index-BKh0prif.d.cts → index-exNi3I2Q.d.cts} +4 -4
  130. package/dist/{index-CXtdQ7be.d.cts → index-qOK5FtAH.d.cts} +4 -4
  131. package/dist/{index-DqOAjqxN.d.cts → index-t-a7kYnx.d.cts} +5 -5
  132. package/dist/index.cjs +303 -47
  133. package/dist/index.cjs.map +1 -1
  134. package/dist/index.d.cts +7 -6
  135. package/dist/index.d.ts +7 -6
  136. package/dist/index.js +285 -30
  137. package/dist/index.js.map +1 -1
  138. package/dist/{jobStatus-kQ9JqF8t.cjs → jobStatus-0_Y3Sr4i.cjs} +37 -20
  139. package/dist/jobStatus-0_Y3Sr4i.cjs.map +1 -0
  140. package/dist/{jobStatus-DbMupQEK.js → jobStatus-PSZJMTiA.js} +35 -18
  141. package/dist/jobStatus-PSZJMTiA.js.map +1 -0
  142. package/dist/kaiAgent/index.cjs +1 -1
  143. package/dist/kaiAgent/index.d.cts +2 -210
  144. package/dist/kaiAgent/index.d.ts +2 -210
  145. package/dist/kaiAgent/index.js +1 -1
  146. package/dist/kaiAgent/types.d.cts +1 -1
  147. package/dist/kaiAgent/types.d.ts +1 -1
  148. package/dist/{kaiAgent-4OiIK1C2.cjs → kaiAgent-CMVub6Sc.cjs} +48 -4
  149. package/dist/kaiAgent-CMVub6Sc.cjs.map +1 -0
  150. package/dist/{kaiAgent-HDaFS9BR.js → kaiAgent-CYYn0QJW.js} +48 -4
  151. package/dist/kaiAgent-CYYn0QJW.js.map +1 -0
  152. package/dist/kaiAgentClient-B2O0DF4d.d.ts +249 -0
  153. package/dist/kaiAgentClient-iCFR2tRU.d.cts +249 -0
  154. package/dist/management/index.cjs +1 -1
  155. package/dist/management/index.d.cts +1 -1
  156. package/dist/management/index.d.ts +1 -1
  157. package/dist/management/index.js +1 -1
  158. package/dist/management/types.d.cts +1 -1
  159. package/dist/management/types.d.ts +1 -1
  160. package/dist/{management-DfjwQo7z.cjs → management-DGfgKsaA.cjs} +5 -5
  161. package/dist/{management-DfjwQo7z.cjs.map → management-DGfgKsaA.cjs.map} +1 -1
  162. package/dist/{management-CIFhu1Nm.js → management-DNEKhR6a.js} +5 -5
  163. package/dist/{management-CIFhu1Nm.js.map → management-DNEKhR6a.js.map} +1 -1
  164. package/dist/metastore/index.cjs +1 -1
  165. package/dist/metastore/index.d.cts +1 -1
  166. package/dist/metastore/index.d.ts +1 -1
  167. package/dist/metastore/index.js +1 -1
  168. package/dist/metastore/types.d.cts +1 -1
  169. package/dist/metastore/types.d.ts +1 -1
  170. package/dist/{metastore-CrXkKufo.js → metastore-CjwktHvw.js} +4 -4
  171. package/dist/{metastore-CrXkKufo.js.map → metastore-CjwktHvw.js.map} +1 -1
  172. package/dist/{metastore-Dq2NS6jb.cjs → metastore-DksEte8P.cjs} +4 -4
  173. package/dist/{metastore-Dq2NS6jb.cjs.map → metastore-DksEte8P.cjs.map} +1 -1
  174. package/dist/microsoftGraph/index.cjs +2 -2
  175. package/dist/microsoftGraph/index.d.cts +2 -2
  176. package/dist/microsoftGraph/index.d.ts +2 -2
  177. package/dist/microsoftGraph/index.js +2 -2
  178. package/dist/microsoftGraph/types.d.cts +1 -1
  179. package/dist/microsoftGraph/types.d.ts +1 -1
  180. package/dist/notifications/index.cjs +3 -3
  181. package/dist/notifications/index.d.cts +2 -2
  182. package/dist/notifications/index.d.ts +2 -2
  183. package/dist/notifications/index.js +3 -3
  184. package/dist/notifications/types.d.cts +1 -1
  185. package/dist/notifications/types.d.ts +1 -1
  186. package/dist/oauth/index.cjs +1 -1
  187. package/dist/oauth/index.d.cts +2 -2
  188. package/dist/oauth/index.d.ts +2 -2
  189. package/dist/oauth/index.js +1 -1
  190. package/dist/oauth/types.d.cts +1 -1
  191. package/dist/oauth/types.d.ts +1 -1
  192. package/dist/{oauth-CFwSNz37.js → oauth-Bg5zro5S.js} +5 -5
  193. package/dist/{oauth-CFwSNz37.js.map → oauth-Bg5zro5S.js.map} +1 -1
  194. package/dist/{oauth-CkW5gln-.cjs → oauth-DFsI1TE5.cjs} +5 -5
  195. package/dist/{oauth-CkW5gln-.cjs.map → oauth-DFsI1TE5.cjs.map} +1 -1
  196. package/dist/omnisearch/index.cjs +2 -2
  197. package/dist/omnisearch/index.d.cts +2 -2
  198. package/dist/omnisearch/index.d.ts +2 -2
  199. package/dist/omnisearch/index.js +2 -2
  200. package/dist/omnisearch/types.d.cts +1 -1
  201. package/dist/omnisearch/types.d.ts +1 -1
  202. package/dist/{project-BOGaVs-q.d.ts → project-Bh954iOA.d.ts} +2 -2
  203. package/dist/{project-BnQkL8cb.d.cts → project-D25GH8zK.d.cts} +2 -2
  204. package/dist/queryService/index.cjs +1 -1
  205. package/dist/queryService/index.d.cts +1 -1
  206. package/dist/queryService/index.d.ts +1 -1
  207. package/dist/queryService/index.js +1 -1
  208. package/dist/queryService/types.d.cts +1 -1
  209. package/dist/queryService/types.d.ts +1 -1
  210. package/dist/{queryService-BLaGbpm-.cjs → queryService--t_W9PSJ.cjs} +6 -6
  211. package/dist/{queryService-BLaGbpm-.cjs.map → queryService--t_W9PSJ.cjs.map} +1 -1
  212. package/dist/{queryService-DK-jUnET.js → queryService-DX6zeAs_.js} +6 -6
  213. package/dist/{queryService-DK-jUnET.js.map → queryService-DX6zeAs_.js.map} +1 -1
  214. package/dist/queue/index.cjs +1 -1
  215. package/dist/queue/index.d.cts +3 -3
  216. package/dist/queue/index.d.ts +3 -3
  217. package/dist/queue/index.js +1 -1
  218. package/dist/queue/types.d.cts +1 -1
  219. package/dist/queue/types.d.ts +1 -1
  220. package/dist/{queue-B7TY4JLf.cjs → queue-D1_TCe0z.cjs} +5 -5
  221. package/dist/{queue-B7TY4JLf.cjs.map → queue-D1_TCe0z.cjs.map} +1 -1
  222. package/dist/{queue-DViSQ-eq.js → queue-DrLUbk98.js} +5 -5
  223. package/dist/{queue-DViSQ-eq.js.map → queue-DrLUbk98.js.map} +1 -1
  224. package/dist/scheduler/index.cjs +3 -3
  225. package/dist/scheduler/index.d.cts +2 -2
  226. package/dist/scheduler/index.d.ts +2 -2
  227. package/dist/scheduler/index.js +3 -3
  228. package/dist/scheduler/types.d.cts +1 -1
  229. package/dist/scheduler/types.d.ts +1 -1
  230. package/dist/sdk/configurations/index.d.cts +4 -4
  231. package/dist/sdk/configurations/index.d.ts +4 -4
  232. package/dist/sdk/developerPortal/index.cjs +5 -5
  233. package/dist/sdk/developerPortal/index.cjs.map +1 -1
  234. package/dist/sdk/developerPortal/index.d.cts +5 -4
  235. package/dist/sdk/developerPortal/index.d.ts +5 -4
  236. package/dist/sdk/developerPortal/index.js +4 -4
  237. package/dist/sdk/queryService/index.cjs +1 -1
  238. package/dist/sdk/queryService/index.d.cts +1 -1
  239. package/dist/sdk/queryService/index.d.ts +1 -1
  240. package/dist/sdk/queryService/index.js +1 -1
  241. package/dist/sdk/semanticLayer/index.cjs +163 -74
  242. package/dist/sdk/semanticLayer/index.cjs.map +1 -1
  243. package/dist/sdk/semanticLayer/index.d.cts +16 -13
  244. package/dist/sdk/semanticLayer/index.d.ts +16 -13
  245. package/dist/sdk/semanticLayer/index.js +158 -75
  246. package/dist/sdk/semanticLayer/index.js.map +1 -1
  247. package/dist/sdk/semanticLayer/types.d.cts +2 -2
  248. package/dist/sdk/semanticLayer/types.d.ts +2 -2
  249. package/dist/sdk/storage/index.d.cts +1 -1
  250. package/dist/sdk/storage/index.d.ts +1 -1
  251. package/dist/sdk/tag/index.d.cts +2 -2
  252. package/dist/sdk/tag/index.d.ts +2 -2
  253. package/dist/sdk/tag/types.d.cts +1 -1
  254. package/dist/sdk/tag/types.d.ts +1 -1
  255. package/dist/sdk/vault/index.d.cts +1 -1
  256. package/dist/sdk/vault/index.d.ts +1 -1
  257. package/dist/status/index.cjs +1 -1
  258. package/dist/status/index.d.cts +1 -1
  259. package/dist/status/index.d.ts +1 -1
  260. package/dist/status/index.js +1 -1
  261. package/dist/storage/index.cjs +4 -4
  262. package/dist/storage/index.d.cts +2 -2
  263. package/dist/storage/index.d.ts +2 -2
  264. package/dist/storage/index.js +4 -4
  265. package/dist/storage/types.d.cts +2 -2
  266. package/dist/storage/types.d.ts +2 -2
  267. package/dist/{storage-kgxscFEg.js → storage--cVaecFq.js} +7 -7
  268. package/dist/{storage-kgxscFEg.js.map → storage--cVaecFq.js.map} +1 -1
  269. package/dist/{storage-CihHwZ7z.cjs → storage-DexWot8H.cjs} +7 -7
  270. package/dist/{storage-CihHwZ7z.cjs.map → storage-DexWot8H.cjs.map} +1 -1
  271. package/dist/store-C9FQCHGe.js +74 -0
  272. package/dist/store-C9FQCHGe.js.map +1 -0
  273. package/dist/store-xS-Cu_VS.cjs +85 -0
  274. package/dist/store-xS-Cu_VS.cjs.map +1 -0
  275. package/dist/stream/index.cjs +3 -3
  276. package/dist/stream/index.d.cts +2 -2
  277. package/dist/stream/index.d.ts +2 -2
  278. package/dist/stream/index.js +3 -3
  279. package/dist/stream/types.d.cts +1 -1
  280. package/dist/stream/types.d.ts +1 -1
  281. package/dist/syncActions/index.cjs +1 -1
  282. package/dist/syncActions/index.d.cts +1 -1
  283. package/dist/syncActions/index.d.ts +1 -1
  284. package/dist/syncActions/index.js +1 -1
  285. package/dist/syncActions/types.d.cts +1 -1
  286. package/dist/syncActions/types.d.ts +1 -1
  287. package/dist/{syncActions-B75t0NwP.js → syncActions-CkMHM-jB.js} +5 -5
  288. package/dist/{syncActions-B75t0NwP.js.map → syncActions-CkMHM-jB.js.map} +1 -1
  289. package/dist/{syncActions-CevF_TEb.cjs → syncActions-DQq_A9v6.cjs} +5 -5
  290. package/dist/{syncActions-CevF_TEb.cjs.map → syncActions-DQq_A9v6.cjs.map} +1 -1
  291. package/dist/telemetry/index.cjs +1 -1
  292. package/dist/telemetry/index.d.cts +2 -2
  293. package/dist/telemetry/index.d.ts +2 -2
  294. package/dist/telemetry/index.js +1 -1
  295. package/dist/{telemetry-DwlSLVAU.cjs → telemetry-CAu1Qt7B.cjs} +3 -3
  296. package/dist/{telemetry-DwlSLVAU.cjs.map → telemetry-CAu1Qt7B.cjs.map} +1 -1
  297. package/dist/{telemetry-FXpodtJN.js → telemetry-Ca6j0i9w.js} +3 -3
  298. package/dist/{telemetry-FXpodtJN.js.map → telemetry-Ca6j0i9w.js.map} +1 -1
  299. package/dist/{types-CGH_lfxS.d.cts → types-0xa_7cgo.d.cts} +2 -2
  300. package/dist/{types-CyiRYRVq.d.cts → types-3p0adMdd.d.cts} +3 -3
  301. package/dist/{types-BlCoTm7n.d.ts → types-6ThDkaJw.d.ts} +2 -2
  302. package/dist/{types-CkcMoXRk.d.ts → types-6hh_3SZs.d.ts} +3 -3
  303. package/dist/{types-dybUhlU2.d.ts → types-6ku2LeX6.d.ts} +2 -2
  304. package/dist/{types-BH9ljNmj.d.cts → types-B42HhyB0.d.cts} +2 -2
  305. package/dist/{types-C1vhYcic.d.cts → types-B4_MM5Wf.d.cts} +2 -2
  306. package/dist/{types-DlbiVsVo.d.cts → types-B6JJCta-.d.cts} +2 -2
  307. package/dist/{types-sVYo0o9_.d.ts → types-B6lOyHY_.d.ts} +3 -3
  308. package/dist/{types-BZBdLUpH.d.ts → types-B7O5koJb.d.cts} +2 -2
  309. package/dist/{types-De_DA2ga.d.ts → types-BHI8Lin9.d.ts} +2 -2
  310. package/dist/{types-Cj4bLPp5.d.cts → types-BO3sCD0a.d.cts} +37 -6
  311. package/dist/{types-zA3H84SM.d.cts → types-BOnf68s5.d.cts} +2 -2
  312. package/dist/{types-CPanB0p7.d.cts → types-BS5M67xm.d.cts} +3 -3
  313. package/dist/{types-COIsNoTQ.d.cts → types-BT46XIgn.d.cts} +2 -2
  314. package/dist/types-BUYqdN7B.d.ts +205 -0
  315. package/dist/{types-D-qI9ne4.d.ts → types-BYKHr5bR.d.ts} +2 -2
  316. package/dist/{types-D1uloiuY.d.cts → types-Be3Wgn1U.d.cts} +2 -2
  317. package/dist/{types-BTbczawY.d.ts → types-BgVKG4vg.d.ts} +2 -2
  318. package/dist/{types-CyHZ1ZQe.d.ts → types-C2gzqtjf.d.ts} +2 -2
  319. package/dist/{types-Av2egS_l.d.ts → types-C35GWNmq.d.ts} +2 -2
  320. package/dist/{types-D6jKxUv_.d.ts → types-C4mr0lop.d.ts} +35 -3
  321. package/dist/{types-BI2jI-3-.d.cts → types-CCr1-9Q6.d.cts} +3 -3
  322. package/dist/{types-DeSd3gqW.d.ts → types-CHCM9oNk.d.ts} +3 -3
  323. package/dist/{types-BMQW-2Yw.d.ts → types-CNQdtffE.d.ts} +729 -79
  324. package/dist/{types-MbcIiKDI.d.cts → types-CPaluTW7.d.cts} +3 -3
  325. package/dist/{types-CXTqFYah.d.ts → types-CSc8NQCY.d.ts} +37 -6
  326. package/dist/{types-Cz1dj_TM.d.ts → types-C_ilZZkQ.d.ts} +2 -2
  327. package/dist/{types-EJEoI3ZK.d.ts → types-CaMfshWX.d.ts} +2 -2
  328. package/dist/{types-BoV9M5Xg.d.cts → types-Ccgbipp4.d.cts} +2 -2
  329. package/dist/{types-DuiUN0h8.d.ts → types-Cpjk0-ta.d.ts} +2 -2
  330. package/dist/{types-GuWtMCMn.d.cts → types-CrH4H8M4.d.cts} +2 -2
  331. package/dist/{types-DNXC_-fA.d.cts → types-Cu-0LT4f.d.cts} +2 -2
  332. package/dist/{types-BptQ7jpP.d.cts → types-CxmV36rp.d.cts} +2 -2
  333. package/dist/{types-DwpRt3e9.d.ts → types-D-98DirB.d.ts} +2 -2
  334. package/dist/{types-BV2BDccJ.d.cts → types-D6ocCyGh.d.cts} +35 -3
  335. package/dist/{types-COc-nind.d.cts → types-D7Wgcp0u.d.ts} +2 -2
  336. package/dist/{types-ByWD2oeV.d.ts → types-DAzmGzlb.d.ts} +2 -2
  337. package/dist/{types-BREGN3qo.d.cts → types-DHI0g51U.d.cts} +2 -2
  338. package/dist/{types-Dfc58bPE.d.ts → types-DHqIJKwx.d.ts} +2 -2
  339. package/dist/types-DONxb2-c.d.cts +205 -0
  340. package/dist/{types-Di8VIZwQ.d.ts → types-DTTC70Ac.d.ts} +2 -2
  341. package/dist/{types-C2CLlR4i.d.ts → types-DlvZeert.d.ts} +2 -2
  342. package/dist/{types-cDU_J45_.d.cts → types-DqniGeDJ.d.cts} +2 -2
  343. package/dist/{types-iNlsdRkx.d.cts → types-E3VT-zYz.d.cts} +729 -79
  344. package/dist/{types-B4jdPHoL.d.cts → types-Jt0ipbSm.d.cts} +2 -2
  345. package/dist/{types-Bpnpa2Wt.d.ts → types-Ur37iOqb.d.ts} +3 -3
  346. package/dist/{types-BnaAo7xn.d.ts → types-ZGAWRIBW.d.ts} +2 -2
  347. package/dist/{types-CvkqEvhv.d.cts → types-bY6K3y0O.d.cts} +2 -2
  348. package/dist/{types-CpALS017.d.ts → types-k4R8gQ4U.d.ts} +2 -2
  349. package/dist/{types-CcuG9cid.d.cts → types-sO52qIAA.d.cts} +2 -2
  350. package/dist/{types-CJHi0zdD.d.cts → types-sp1rJY9E.d.cts} +2 -2
  351. package/dist/{validateConnectionStatus-V9q6Nl6u.cjs → validateConnectionStatus-24zqIQ0p.cjs} +2 -2
  352. package/dist/{validateConnectionStatus-V9q6Nl6u.cjs.map → validateConnectionStatus-24zqIQ0p.cjs.map} +1 -1
  353. package/dist/{validateConnectionStatus-BrLXkoSI.js → validateConnectionStatus-DhkWg6Eq.js} +2 -2
  354. package/dist/{validateConnectionStatus-BrLXkoSI.js.map → validateConnectionStatus-DhkWg6Eq.js.map} +1 -1
  355. package/dist/vault/index.cjs +4 -4
  356. package/dist/vault/index.d.cts +1 -1
  357. package/dist/vault/index.d.ts +1 -1
  358. package/dist/vault/index.js +4 -4
  359. package/dist/vault/types.d.cts +1 -1
  360. package/dist/vault/types.d.ts +1 -1
  361. package/package.json +2 -2
  362. package/surface/auth.md +2 -2
  363. package/surface/kaiAgent.md +5 -2
  364. package/dist/authClient--BtZgjIc.js.map +0 -1
  365. package/dist/authClient-b7uec7sw.cjs.map +0 -1
  366. package/dist/createStore-BNiCRQXa.js +0 -148
  367. package/dist/createStore-BNiCRQXa.js.map +0 -1
  368. package/dist/createStore-MQbboXcB.cjs +0 -177
  369. package/dist/createStore-MQbboXcB.cjs.map +0 -1
  370. package/dist/credential-DOXH7XRS.cjs.map +0 -1
  371. package/dist/credential-d2RDcXRB.js.map +0 -1
  372. package/dist/jobStatus-DbMupQEK.js.map +0 -1
  373. package/dist/jobStatus-kQ9JqF8t.cjs.map +0 -1
  374. package/dist/kaiAgent-4OiIK1C2.cjs.map +0 -1
  375. package/dist/kaiAgent-HDaFS9BR.js.map +0 -1
  376. package/dist/types-B2vmg_UF.d.cts +0 -148
  377. package/dist/types-RfaldD4P.d.ts +0 -148
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
 
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
+ 24 top-level namespaces, 624 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
 
@@ -184,6 +184,7 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
184
184
  - `getHistory`
185
185
  - `getSandboxGitBranch`
186
186
  - `getSkillsList`
187
+ - `getSpendCaps`
187
188
  - `getSuggestions`
188
189
  - `getToolsList`
189
190
  - `getUsage`
@@ -192,10 +193,12 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
192
193
  - `healthCheck`
193
194
  - `listSandboxFiles`
194
195
  - `readSandboxFile`
196
+ - `setUserSpendLimit`
195
197
  - `stopChat`
196
198
  - `submitToolOutput`
197
199
  - `submitVote`
198
200
  - `updateAgentSettings`
201
+ - `updateSpendCaps`
199
202
  - `updateUserAgentSettings`
200
203
 
201
204
  ## [`api.management`](./surface/management.md)
package/CHANGELOG.md CHANGED
@@ -1,5 +1,227 @@
1
1
  # @keboola/api-client
2
2
 
3
+ ## 33.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - `createEmitter` delivers events in emission order, never nested, and `Store` gains `asReadable()`.
8
+ - An `emit` from inside a listener is queued until the current pass has reached every listener, so
9
+ no listener hears event N+1 before event N. For a store this means a subscriber that writes back
10
+ can no longer leave a later subscriber on stale state — the last notification is always the
11
+ latest value.
12
+ - A listener's own emit is handled after it returns; a throwing listener is logged and does not
13
+ stall the queue behind it. Nothing is coalesced: every event is delivered.
14
+ - A pass reaches the listeners present when it began. Subscribing from inside a listener no longer
15
+ delivers the event in flight to the new listener — it hears the next one, as it would have had it
16
+ subscribed a moment earlier. Unsubscribing (or `clear()`) from inside a listener still takes
17
+ effect immediately for the rest of that pass.
18
+ - `store.asReadable()` returns the same store without `set` — the read-only view consumers were
19
+ building by hand from `get` / `subscribe` / `dispose`.
20
+
21
+ - `auth.pat.create` / `auth.pat.exchange` take a `CreatePatInput` / `ExchangePatInput` whose optional
22
+ fields may be left out, and drop the keys a caller passes as `null` instead of putting them on the
23
+ wire. The spec documents every optional PAT field as "omit, do not send `null`", but the generated
24
+ bodies demand each of them, so a caller holding a nullable — an empty expiry picker, an untouched
25
+ read-only switch — had no way to express the default. `scope` gains the same treatment: a
26
+ `{ projects, readOnly }` that narrows nothing is sent as no `scope` at all.
27
+
28
+ Existing calls keep compiling and keep their behaviour, since the previously required
29
+ `expiresIn: null` / `scope: null` is what the normaliser now drops.
30
+
31
+ - The semantic layer's closed value sets ship as runtime lists, so an authoring surface no longer
32
+ writes them out by hand. `FIELD_ROLES`, `CONSTRAINT_SEVERITIES`, `CONSTRAINT_SCOPES`,
33
+ `RULE_OPERATORS` and `RELATIONSHIP_JOIN_TYPES` join `SQL_DIALECTS` and `CONSTRAINT_TYPES`, which
34
+ move to the same module and keep their existing import paths.
35
+
36
+ ```ts
37
+ import {
38
+ CONSTRAINT_SCOPES,
39
+ metastoreErrorMessage,
40
+ } from "@keboola/api-client/sdk/semanticLayer";
41
+ import type { SemanticConstraintScope } from "@keboola/api-client/sdk/semanticLayer/types";
42
+
43
+ // a total label map, so a scope the metastore adds is a compile error rather than a missing option
44
+ const SCOPE_LABELS: Record<SemanticConstraintScope, string> = {
45
+ global: "Global" /* … */,
46
+ };
47
+ const options = CONSTRAINT_SCOPES.map((value) => ({
48
+ value,
49
+ label: SCOPE_LABELS[value],
50
+ }));
51
+ ```
52
+
53
+ - Each union in `./types` is now derived from its list rather than spelled out again, so the type
54
+ and the list a validator or a dropdown is built from cannot disagree. `SemanticConstraintSeverity`
55
+ and `SemanticRelationshipJoinType` are named for the first time; they were inline unions on
56
+ `SemanticConstraintData.severity` and `SemanticRelationshipData.type`.
57
+ - The `./sdk/semanticLayer/types` entry point stays free of runtime code — the derivation reads the
58
+ lists through an `import type`.
59
+ - `metastoreErrorMessage(body)` reads the one field that says what is actually wrong with a
60
+ rejected write (`errors[0].message`, e.g. `missing property 'fqn'`). The status and the
61
+ response's own message say no more than "Validation failed". Any other shape returns `undefined`,
62
+ so a caller keeps its own fallback.
63
+
64
+ - Reach several projects from one bearer session with `session.forProject(projectId)`
65
+
66
+ A bearer access token is a user token — project scope is a single `X-KBC-ProjectId` header — so one
67
+ session can legitimately address many projects. Until now only the scoped project had clients, and
68
+ the obvious workaround was a second `createKeboola()`, which signs both instances out: they hold the
69
+ same single-use refresh token, and the first to rotate invalidates the other's.
70
+
71
+ `session.forProject(projectId)` returns that project's `ProjectClients` off the session in hand,
72
+ reusing its credential and auth middleware, so a token rotation happens once for every project rather
73
+ than once each. `setProjectAsync` moves the session (and `api`); `forProject` adds a project alongside
74
+ it. A project is bootstrapped once and concurrent callers share that build; a failed build is
75
+ retryable.
76
+
77
+ Every client set is pinned to the sign-in that built it, so `reset()` is a teardown rather than a
78
+ cache eviction — a set held across a sign-out throws `NotAuthenticated` on its next request, the 401
79
+ replay included, instead of quietly acting as whoever signed in after. `clearProject()` drops the
80
+ scope, not the credential, and leaves the extra projects alone. Nothing extra is persisted.
81
+
82
+ The same pin covers every other surface that emits this session's credential.
83
+ `api.storage`/`api.context` and `api.management` rebuild on sign-out, but that could not stop a
84
+ request already in flight from completing as the next user, with the previous project's
85
+ `X-KBC-ProjectId` still on it. `session.getAuthHeaders()` resolved to the dead session's token and
86
+ project, because the proactive rotation swallows its own refusal. A token rotation is pinned to the
87
+ sign-in that spent the refresh token, so one resolving after its own session ended is dropped rather
88
+ than written over the credential of whoever signed in since, and a sign-out abandons the in-flight
89
+ rotation so the next session starts its own. `api.auth` is built once per stack and serves every
90
+ session, so it pins each _request_ to the sign-in that started it: a 401 recovery no longer replays
91
+ as the next user, while `login` still goes out unstamped. `session.restore()` is pinned too — a
92
+ sign-out landing while the stored token is being exchanged resolves `empty` instead of signing the
93
+ user back in.
94
+
95
+ The guard wraps the **credential**, not only the outgoing request, because the 401 path rotates the
96
+ token by calling the credential directly: a straggler from a dead session would otherwise spend the
97
+ live session's single-use refresh token, and sign that session out if the rotation itself came back 401.
98
+
99
+ The pin covers the failure branches too, which is where it was missed. A retry re-invokes `next`,
100
+ so `retryContention` is composed _inside_ the pin rather than beside it in the auth client's
101
+ middleware array — outside it, an `api.auth` request that hit a 503 re-pinned per attempt and the
102
+ retry went out as whoever signed in during the backoff. And a rotation or a restore that _fails_
103
+ after its session ended is re-labelled `NotAuthenticated` before the error travels on: a raw 401
104
+ reads as "this credential is dead" to the credential and as "the stored token is dead" to
105
+ `restore()`, so a straggler used to sign out the session that replaced it, and a losing concurrent
106
+ restore used to clear the winner's stored session — leaving it alive in memory and gone on the next
107
+ reload.
108
+
109
+ A project the session cannot reach now fails its own build and nothing else. Connection answers a
110
+ denied or nonexistent project with the same `invalid_token` 401 as a revoked token, so `forProject`
111
+ reads a 401 that survives a token rotation as being about the project rather than the credential —
112
+ a mistyped project id used to sign the whole session out.
113
+
114
+ `ProjectClients` is now exported as a type.
115
+
116
+ ### Patch Changes
117
+
118
+ - `kaiAgent`'s spend-caps response gains `defaultProjectCapPpu` — the bare platform default project
119
+ cap, independent of what's persisted. Previously only `effectiveProjectCapPpu` (the server's
120
+ resolution of the _persisted_ cap) was exposed, which a consumer could not use to validate a
121
+ cleared-but-unsaved project-cap field against the true default.
122
+
123
+ - `kaiAgent`'s generated schema is regenerated against the deployed spec, so `getUsage` reports the
124
+ spend-cap scope and the one project-level figure a plain member is shown.
125
+ - `getUsage` gains `ppuLimitScope: 'user' | 'project' | null` — which ceiling stops the caller next.
126
+ A label, never a figure: the project's absolute budget stays admin-only.
127
+ - `getUsage` gains `projectPpuPercentage: number | null` — how much of the project's cap is spent.
128
+ It is the fallback a caller with no personal `ppuLimit` is measured against, and `null` only
129
+ where no project cap applies at all.
130
+ - `getChat` gains `ppuPercentage: number | null`, the same figure alongside a conversation.
131
+ - The `rate_limit` error `subtype` splits `monthly_credits` into `monthly_credits_user` and
132
+ `monthly_credits_project`.
133
+ - Additive drift the same regeneration picked up: the `/api/settings/spend-caps` pair, the
134
+ `/api/chat/{id}/sandbox/file/download` path, and a `payload_too_large` error type with its 413.
135
+
136
+ - `Result` gains constructors, guards and combinators, so code that returns a `Result` of its own no
137
+ longer writes the object literal, and code that consumes one no longer branches on `success` by
138
+ hand.
139
+
140
+ ```ts
141
+ import { Result } from "@keboola/api-client";
142
+
143
+ const getStack = (id: string): Result<Stack> =>
144
+ stacks.has(id)
145
+ ? Result.success(stacks.get(id))
146
+ : Result.failure(new Error(`No stack "${id}"`));
147
+
148
+ // handle both branches in one expression, Rust-match style
149
+ const label = Result.match(
150
+ getStack(id),
151
+ (stack) => stack.name,
152
+ (error) => error.message,
153
+ );
154
+
155
+ // at a layer boundary, relabel the failure as the error this layer speaks, then throw it
156
+ const stack = Result.unwrap(
157
+ Result.mapError(
158
+ getStack(id),
159
+ () => new KeboolaError(KeboolaErrorType.Unconfigured),
160
+ ),
161
+ );
162
+ ```
163
+
164
+ - `success` is `Result<T, never>` and `failure` is `Result<never, E>`, so either widens into any
165
+ `Result<T, E>` without an annotation. `Success<T>` and `Failure<E>` name the two branches.
166
+ - `isSuccess` / `isFailure` are type guards; `map`, `mapError` and `andThen` rewrite one branch
167
+ and pass the other through untouched.
168
+ - `match(result, onSuccess, onFailure)` returns whichever callback ran, so the two must agree on a
169
+ type; `void` works. `unwrap` throws the error as-is; `unwrapOr` returns a fallback instead.
170
+ - `tryCatch` and `fromThrowable` reject a task that returns a promise at the type level, since they
171
+ would report success before it settles. Use `tryCatchAsync` / `fromThrowableAsync` for those.
172
+
173
+ - `TableDetail` declares the three freshness fields the detail response carries: `lastImportDate`,
174
+ `lastChangeDate` and `rowsCount`.
175
+
176
+ ```ts
177
+ const table = await api.storage.tables.getTable({ branchId, id });
178
+ // `null` is the table's own answer — nothing has ever been written into it.
179
+ if (table.lastImportDate === null) return "Nothing loaded yet";
180
+ ```
181
+
182
+ - Declared required, where `TableDetailResponse` in the generated schema marks them optional. That
183
+ node marks `?` on every nullable field it has, so the marker conflates "nullable" with
184
+ "optional"; `TableCreateResponse` — which the table list reuses — and `AliasFilterSetResponse`
185
+ declare the same fields required-and-nullable. `Table` and `TableDetail` now agree on all three.
186
+ - `null` means different things per field, and each one says so: never written into
187
+ (`lastImportDate`), and Storage declining to count rather than a count of zero (`rowsCount`).
188
+
189
+ - `isTimeoutError` joins `isAbortError` in the fetch-client error taxonomy, exported from both
190
+ `@keboola/api-client` and `@keboola/api-client/fetchClient`.
191
+
192
+ ```ts
193
+ import { isTimeoutError } from "@keboola/api-client";
194
+
195
+ // `DOMException('signal timed out', 'TimeoutError')` — what an `AbortSignal.timeout` rejects with.
196
+ if (isTimeoutError(error)) return null;
197
+ ```
198
+
199
+ - Matches on `DOMException.name`, since the message is a browser string rather than a contract.
200
+ - Distinct from `isAbortError`: a timeout is the deadline expiring, an abort is someone cancelling.
201
+ - `xhrFetch` is not covered — its `handleAbort` builds an `AbortError` without reading
202
+ `signal.reason`, so a timeout on that transport reports as a cancel.
203
+
204
+ `@keboola/sentry`'s shared `beforeSend` is the first caller: a request that never got a response
205
+ measures the network, not the code, and reports with no stacktrace.
206
+
207
+ - Security patches for transitive dependencies: qs 6.16.0 in api-client, mermaid 11.17.2 and dompurify
208
+ 3.4.14 in design.
209
+
210
+ No API or behaviour change in either package.
211
+
212
+ - Interpret the org-admin `kai-assistant.monthlyCreditsLimitPerUser` Storage key as PPU (the same
213
+ unit an admin sees and sets everywhere else, per AI-3628), converting it to the internal
214
+ Kai-credits ceiling at the read boundary. `@keboola/api-client`'s kai-agent schema regenerated to
215
+ pick up `ppuUsed`/`ppuLimit` on `GET /api/usage`; `@keboola/kai-fake-agent`'s stub updated to match.
216
+ `@keboola/kai-agent` and `@keboola/kbc-ui` are private, nothing to release for them — acknowledged
217
+ so `changeset status` doesn't choke on them alongside the real `@keboola/api-client` release.
218
+
219
+ - Show Kai spend caps in project settings and scope-aware chat copy (AI-3738).
220
+
221
+ `@keboola/api-client`'s kai-agent client/surface-docs regenerated for the spend-caps endpoints;
222
+ `@keboola/constants`, `@keboola/kai-fake-agent`, `@keboola/kai-agent` and `@keboola/kbc-ui` are
223
+ private, nothing to release for them — acknowledged so `changeset status` doesn't choke on them.
224
+
3
225
  ## 32.0.0
4
226
 
5
227
  ### Major Changes
@@ -1,4 +1,4 @@
1
- const require_createFetchClient = require("./createFetchClient-BRfTjBLV.cjs");
1
+ const require_createFetchClient = require("./createFetchClient-DvZvD31l.cjs");
2
2
  //#region src/errors/ManagementClientAuthError.ts
3
3
  var ManagementClientAuthError = class extends require_createFetchClient.ApiError {
4
4
  title;
@@ -17,4 +17,4 @@ Object.defineProperty(exports, "ManagementClientAuthError", {
17
17
  }
18
18
  });
19
19
 
20
- //# sourceMappingURL=ManagementClientAuthError-B-tyPlyG.cjs.map
20
+ //# sourceMappingURL=ManagementClientAuthError-DqeXL8nv.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ManagementClientAuthError-B-tyPlyG.cjs","names":["ApiError"],"sources":["../src/errors/ManagementClientAuthError.ts"],"sourcesContent":["import type { ApiResponse } from '../fetchClient/createFetchClient/types';\n\nimport { ApiError } from './ApiError';\n\nexport class ManagementClientAuthError extends ApiError {\n title: string;\n message: string;\n constructor(title: string, message: string, res: ApiResponse) {\n super(res);\n this.title = title;\n this.message = message;\n }\n}\n"],"mappings":";;AAIA,IAAa,4BAAb,cAA+CA,0BAAAA,SAAS;CACtD;CACA;CACA,YAAY,OAAe,SAAiB,KAAkB;EAC5D,MAAM,GAAG;EACT,KAAK,QAAQ;EACb,KAAK,UAAU;CACjB;AACF"}
1
+ {"version":3,"file":"ManagementClientAuthError-DqeXL8nv.cjs","names":["ApiError"],"sources":["../src/errors/ManagementClientAuthError.ts"],"sourcesContent":["import type { ApiResponse } from '../fetchClient/createFetchClient/types';\n\nimport { ApiError } from './ApiError';\n\nexport class ManagementClientAuthError extends ApiError {\n title: string;\n message: string;\n constructor(title: string, message: string, res: ApiResponse) {\n super(res);\n this.title = title;\n this.message = message;\n }\n}\n"],"mappings":";;AAIA,IAAa,4BAAb,cAA+CA,0BAAAA,SAAS;CACtD;CACA;CACA,YAAY,OAAe,SAAiB,KAAkB;EAC5D,MAAM,GAAG;EACT,KAAK,QAAQ;EACb,KAAK,UAAU;CACjB;AACF"}
@@ -1,4 +1,4 @@
1
- import { m as ApiError } from "./createFetchClient-BbG46bL0.js";
1
+ import { h as ApiError } from "./createFetchClient-DdyZMhxO.js";
2
2
  //#region src/errors/ManagementClientAuthError.ts
3
3
  var ManagementClientAuthError = class extends ApiError {
4
4
  title;
@@ -12,4 +12,4 @@ var ManagementClientAuthError = class extends ApiError {
12
12
  //#endregion
13
13
  export { ManagementClientAuthError as t };
14
14
 
15
- //# sourceMappingURL=ManagementClientAuthError-BAFNvOdf.js.map
15
+ //# sourceMappingURL=ManagementClientAuthError-iKbBugKC.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ManagementClientAuthError-BAFNvOdf.js","names":[],"sources":["../src/errors/ManagementClientAuthError.ts"],"sourcesContent":["import type { ApiResponse } from '../fetchClient/createFetchClient/types';\n\nimport { ApiError } from './ApiError';\n\nexport class ManagementClientAuthError extends ApiError {\n title: string;\n message: string;\n constructor(title: string, message: string, res: ApiResponse) {\n super(res);\n this.title = title;\n this.message = message;\n }\n}\n"],"mappings":";;AAIA,IAAa,4BAAb,cAA+C,SAAS;CACtD;CACA;CACA,YAAY,OAAe,SAAiB,KAAkB;EAC5D,MAAM,GAAG;EACT,KAAK,QAAQ;EACb,KAAK,UAAU;CACjB;AACF"}
1
+ {"version":3,"file":"ManagementClientAuthError-iKbBugKC.js","names":[],"sources":["../src/errors/ManagementClientAuthError.ts"],"sourcesContent":["import type { ApiResponse } from '../fetchClient/createFetchClient/types';\n\nimport { ApiError } from './ApiError';\n\nexport class ManagementClientAuthError extends ApiError {\n title: string;\n message: string;\n constructor(title: string, message: string, res: ApiResponse) {\n super(res);\n this.title = title;\n this.message = message;\n }\n}\n"],"mappings":";;AAIA,IAAa,4BAAb,cAA+C,SAAS;CACtD;CACA;CACA,YAAY,OAAe,SAAiB,KAAkB;EAC5D,MAAM,GAAG;EACT,KAAK,QAAQ;EACb,KAAK,UAAU;CACjB;AACF"}
package/dist/ai/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_createOpenapiFetchClient = require("../createOpenapiFetchClient-CyDUFxHB.cjs");
3
- const require_auth = require("../auth-DP-6TFiM.cjs");
2
+ const require_createOpenapiFetchClient = require("../createOpenapiFetchClient-C57Ljzi6.cjs");
3
+ const require_auth = require("../auth-C2_JLisH.cjs");
4
4
  //#region src/clients/ai/aiClient.ts
5
5
  const createAiClient = ({ baseUrl, middlewares, auth }) => {
6
6
  const client = require_createOpenapiFetchClient.createOpenapiFetchClient({
@@ -1,5 +1,5 @@
1
- import { a as DescribeConfigurationVersionBody, f as SuggestComponentBody, i as DescribeConfigurationMergeBody, l as ExplainErrorBody, p as components, r as DescribeConfigurationBody, s as DocsQuestionBody, u as FeedbackBody } from "../types-CvkqEvhv.cjs";
2
- import { n as ClientInitOptions } from "../types-BREGN3qo.cjs";
1
+ import { a as DescribeConfigurationVersionBody, f as SuggestComponentBody, i as DescribeConfigurationMergeBody, l as ExplainErrorBody, p as components, r as DescribeConfigurationBody, s as DocsQuestionBody, u as FeedbackBody } from "../types-bY6K3y0O.cjs";
2
+ import { n as ClientInitOptions } from "../types-DHI0g51U.cjs";
3
3
  //#region src/clients/ai/aiClient.d.ts
4
4
  declare const createAiClient: ({ baseUrl, middlewares, auth }: ClientInitOptions) => {
5
5
  healthCheck: (signal?: AbortSignal) => Promise<{
@@ -1,5 +1,5 @@
1
- import { a as DescribeConfigurationVersionBody, f as SuggestComponentBody, i as DescribeConfigurationMergeBody, l as ExplainErrorBody, p as components, r as DescribeConfigurationBody, s as DocsQuestionBody, u as FeedbackBody } from "../types-BnaAo7xn.js";
2
- import { n as ClientInitOptions } from "../types-DwpRt3e9.js";
1
+ import { a as DescribeConfigurationVersionBody, f as SuggestComponentBody, i as DescribeConfigurationMergeBody, l as ExplainErrorBody, p as components, r as DescribeConfigurationBody, s as DocsQuestionBody, u as FeedbackBody } from "../types-ZGAWRIBW.js";
2
+ import { n as ClientInitOptions } from "../types-D-98DirB.js";
3
3
  //#region src/clients/ai/aiClient.d.ts
4
4
  declare const createAiClient: ({ baseUrl, middlewares, auth }: ClientInitOptions) => {
5
5
  healthCheck: (signal?: AbortSignal) => Promise<{
package/dist/ai/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { t as createOpenapiFetchClient } from "../createOpenapiFetchClient-Bn6_Pn0H.js";
2
- import { t as createAuthHeaders } from "../auth-DtbQaeDj.js";
1
+ import { t as createOpenapiFetchClient } from "../createOpenapiFetchClient-E7OIVkYv.js";
2
+ import { t as createAuthHeaders } from "../auth-CE9rQV3-.js";
3
3
  //#region src/clients/ai/aiClient.ts
4
4
  const createAiClient = ({ baseUrl, middlewares, auth }) => {
5
5
  const client = createOpenapiFetchClient({
@@ -1,2 +1,2 @@
1
- import { a as DescribeConfigurationVersionBody, c as ErrorExplanation, d as ObjectDescription, f as SuggestComponentBody, i as DescribeConfigurationMergeBody, l as ExplainErrorBody, n as ComponentSuggestion, o as DocsAnswer, r as DescribeConfigurationBody, s as DocsQuestionBody, t as ComponentDocsDetail, u as FeedbackBody } from "../types-CvkqEvhv.cjs";
1
+ import { a as DescribeConfigurationVersionBody, c as ErrorExplanation, d as ObjectDescription, f as SuggestComponentBody, i as DescribeConfigurationMergeBody, l as ExplainErrorBody, n as ComponentSuggestion, o as DocsAnswer, r as DescribeConfigurationBody, s as DocsQuestionBody, t as ComponentDocsDetail, u as FeedbackBody } from "../types-bY6K3y0O.cjs";
2
2
  export { ComponentDocsDetail, ComponentSuggestion, DescribeConfigurationBody, DescribeConfigurationMergeBody, DescribeConfigurationVersionBody, DocsAnswer, DocsQuestionBody, ErrorExplanation, ExplainErrorBody, FeedbackBody, ObjectDescription, SuggestComponentBody };
@@ -1,2 +1,2 @@
1
- import { a as DescribeConfigurationVersionBody, c as ErrorExplanation, d as ObjectDescription, f as SuggestComponentBody, i as DescribeConfigurationMergeBody, l as ExplainErrorBody, n as ComponentSuggestion, o as DocsAnswer, r as DescribeConfigurationBody, s as DocsQuestionBody, t as ComponentDocsDetail, u as FeedbackBody } from "../types-BnaAo7xn.js";
1
+ import { a as DescribeConfigurationVersionBody, c as ErrorExplanation, d as ObjectDescription, f as SuggestComponentBody, i as DescribeConfigurationMergeBody, l as ExplainErrorBody, n as ComponentSuggestion, o as DocsAnswer, r as DescribeConfigurationBody, s as DocsQuestionBody, t as ComponentDocsDetail, u as FeedbackBody } from "../types-ZGAWRIBW.js";
2
2
  export { ComponentDocsDetail, ComponentSuggestion, DescribeConfigurationBody, DescribeConfigurationMergeBody, DescribeConfigurationVersionBody, DocsAnswer, DocsQuestionBody, ErrorExplanation, ExplainErrorBody, FeedbackBody, ObjectDescription, SuggestComponentBody };
@@ -1,5 +1,5 @@
1
1
  import { t as isPlainObject } from "./isPlainObject-LYW-03uB.js";
2
- import { f as HttpStatus, o as HttpHeader, r as isApiError, u as parseContentDispositionHeader } from "./createFetchClient-BbG46bL0.js";
2
+ import { d as parseContentDispositionHeader, p as HttpStatus, r as isApiError, s as HttpHeader } from "./createFetchClient-DdyZMhxO.js";
3
3
  import * as z$1 from "zod";
4
4
  import dayjs from "dayjs";
5
5
  import utc from "dayjs/plugin/utc.js";
@@ -129,4 +129,4 @@ const readAppLogsDownload = async (fetchLogs) => {
129
129
  //#endregion
130
130
  export { readAppLogsDownload as n, readAppLogsTail as r, parseLogLines as t };
131
131
 
132
- //# sourceMappingURL=appLogs-DTLE6HTy.js.map
132
+ //# sourceMappingURL=appLogs-D72eD8vP.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"appLogs-DTLE6HTy.js","names":["z","record"],"sources":["../src/domain/appLogs.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc.js';\nimport * as z from 'zod';\n\nimport {\n type ApiResponse,\n HttpHeader,\n isApiError,\n parseContentDispositionHeader,\n} from '../fetchClient';\nimport { HttpStatus } from '../internal';\nimport { isPlainObject } from '../utils/isPlainObject';\n\n/**\n * Reading a data app's container output. Shared by the two clients wrapping sandboxes-service —\n * `dataScience` (`/v1`) and `apps` (`/v2`) — which serve the same logs under different paths, so the\n * tail contract (how a line is parsed, where the next poll resumes, and that an idle app is not an\n * error) is defined once here rather than per surface.\n */\n\ndayjs.extend(utc);\n\nexport type LogEntry = {\n timestamp: string | null;\n message: string;\n};\n\nconst DEFAULT_LOGS_FILE_NAME = 'logs.txt';\n\nconst ISO_TIMESTAMP_REGEX = /\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z/;\nconst LEADING_ISO_TIMESTAMP_REGEX = /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z)\\s?/;\n\n/** The error envelope sandboxes-service returns; the tail branches on its `code`. */\nconst TailError = z.object({\n context: z.object({\n code: z.string(),\n }),\n});\n\n/**\n * There is nothing to read right now, reported per scope: an app whose serving member is asleep\n * answers `apps.appNotRunning`, a deployment that isn't running answers `apps.deploymentNotRunning` —\n * the normal state of a staged or retired one, since a deployment only runs while it is production.\n */\nconst NOTHING_RUNNING_CODES = new Set(['apps.appNotRunning', 'apps.deploymentNotRunning']);\n\nconst tryParseJsonl = (line: string): LogEntry | null => {\n if (!line.startsWith('{')) return null;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return null;\n }\n\n if (typeof parsed !== 'object' || parsed === null) return null;\n\n const record = parsed as Record<string, unknown>;\n const { timestamp, message } = record;\n\n if (typeof timestamp !== 'string' || typeof message !== 'string') return null;\n\n return {\n timestamp,\n message,\n };\n};\n\nconst parsePlainTextLine = (line: string): LogEntry => {\n const match = line.match(LEADING_ISO_TIMESTAMP_REGEX);\n if (match) {\n return { timestamp: match[1]!, message: line.slice(match[0].length) };\n }\n return { timestamp: null, message: line };\n};\n\nexport const parseLogLine = (line: string): LogEntry =>\n tryParseJsonl(line) ?? parsePlainTextLine(line);\n\nconst toLogEntryFromObject = (raw: Record<string, unknown>): LogEntry | null => {\n if (typeof raw.message !== 'string') return null;\n return {\n timestamp: typeof raw.timestamp === 'string' ? raw.timestamp : null,\n message: raw.message,\n };\n};\n\nexport const parseLogLines = (raw: unknown): LogEntry[] => {\n if (raw === null || raw === undefined || raw === '') return [];\n\n if (Array.isArray(raw)) {\n return raw.flatMap((item) => {\n if (typeof item === 'string') return item === '' ? [] : [parseLogLine(item)];\n if (isPlainObject(item)) {\n const entry = toLogEntryFromObject(item);\n return entry ? [entry] : [];\n }\n return [];\n });\n }\n\n if (isPlainObject(raw)) {\n const entry = toLogEntryFromObject(raw);\n return entry ? [entry] : [];\n }\n\n if (typeof raw !== 'string') return [];\n\n const lines = raw.split('\\n');\n const entries: LogEntry[] = [];\n for (const line of lines) {\n if (line === '') continue;\n entries.push(parseLogLine(line));\n }\n return entries;\n};\n\nexport const lastLogTimestamp = (entries: LogEntry[]) => {\n for (let i = entries.length - 1; i >= 0; i--) {\n const entry = entries[i];\n if (!entry) continue;\n if (entry.timestamp) return entry.timestamp;\n\n // A plain-text line may carry a timestamp embedded mid-line (legacy format).\n const match = entry.message.match(ISO_TIMESTAMP_REGEX);\n if (match) return match[0];\n }\n return null;\n};\n\nconst calculateNextLogTimestamp = (timestamp: string | null) => {\n if (timestamp === null) return null;\n return dayjs(timestamp).utc().add(1, 'second').utc().format();\n};\n\n/**\n * The tail plus the timestamp a follow-up poll resumes from. A {@link NOTHING_RUNNING_CODES} `400`\n * reads as an empty tail rather than an error — an idle app between visits, or a deployment that is\n * not the one currently serving, has no logs to stream and that is its normal condition.\n */\nexport const readAppLogsTail = async (fetchTail: () => Promise<ApiResponse<string>>) => {\n try {\n const { data } = await fetchTail();\n const entries = parseLogLines(data);\n\n return {\n entries,\n nextLogTimestamp: calculateNextLogTimestamp(lastLogTimestamp(entries)),\n };\n } catch (error) {\n if (isApiError(error) && error.response.status === HttpStatus.BAD_REQUEST) {\n const code = TailError.safeParse(error.data).data?.context?.code;\n if (code !== undefined && NOTHING_RUNNING_CODES.has(code)) {\n return { entries: [], nextLogTimestamp: null };\n }\n }\n throw error;\n }\n};\n\n/** The whole log as a file download, named by the service's `Content-Disposition` where it sets one. */\nexport const readAppLogsDownload = async (fetchLogs: () => Promise<ApiResponse<string>>) => {\n const { data, response } = await fetchLogs();\n const contentDisposition = parseContentDispositionHeader(\n response.headers.get(HttpHeader.CONTENT_DISPOSITION),\n );\n\n return {\n logs: data,\n fileName: contentDisposition.filename ?? DEFAULT_LOGS_FILE_NAME,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"appLogs-D72eD8vP.js","names":["z","record"],"sources":["../src/domain/appLogs.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc.js';\nimport * as z from 'zod';\n\nimport {\n type ApiResponse,\n HttpHeader,\n isApiError,\n parseContentDispositionHeader,\n} from '../fetchClient';\nimport { HttpStatus } from '../internal';\nimport { isPlainObject } from '../utils/isPlainObject';\n\n/**\n * Reading a data app's container output. Shared by the two clients wrapping sandboxes-service —\n * `dataScience` (`/v1`) and `apps` (`/v2`) — which serve the same logs under different paths, so the\n * tail contract (how a line is parsed, where the next poll resumes, and that an idle app is not an\n * error) is defined once here rather than per surface.\n */\n\ndayjs.extend(utc);\n\nexport type LogEntry = {\n timestamp: string | null;\n message: string;\n};\n\nconst DEFAULT_LOGS_FILE_NAME = 'logs.txt';\n\nconst ISO_TIMESTAMP_REGEX = /\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z/;\nconst LEADING_ISO_TIMESTAMP_REGEX = /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z)\\s?/;\n\n/** The error envelope sandboxes-service returns; the tail branches on its `code`. */\nconst TailError = z.object({\n context: z.object({\n code: z.string(),\n }),\n});\n\n/**\n * There is nothing to read right now, reported per scope: an app whose serving member is asleep\n * answers `apps.appNotRunning`, a deployment that isn't running answers `apps.deploymentNotRunning` —\n * the normal state of a staged or retired one, since a deployment only runs while it is production.\n */\nconst NOTHING_RUNNING_CODES = new Set(['apps.appNotRunning', 'apps.deploymentNotRunning']);\n\nconst tryParseJsonl = (line: string): LogEntry | null => {\n if (!line.startsWith('{')) return null;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return null;\n }\n\n if (typeof parsed !== 'object' || parsed === null) return null;\n\n const record = parsed as Record<string, unknown>;\n const { timestamp, message } = record;\n\n if (typeof timestamp !== 'string' || typeof message !== 'string') return null;\n\n return {\n timestamp,\n message,\n };\n};\n\nconst parsePlainTextLine = (line: string): LogEntry => {\n const match = line.match(LEADING_ISO_TIMESTAMP_REGEX);\n if (match) {\n return { timestamp: match[1]!, message: line.slice(match[0].length) };\n }\n return { timestamp: null, message: line };\n};\n\nexport const parseLogLine = (line: string): LogEntry =>\n tryParseJsonl(line) ?? parsePlainTextLine(line);\n\nconst toLogEntryFromObject = (raw: Record<string, unknown>): LogEntry | null => {\n if (typeof raw.message !== 'string') return null;\n return {\n timestamp: typeof raw.timestamp === 'string' ? raw.timestamp : null,\n message: raw.message,\n };\n};\n\nexport const parseLogLines = (raw: unknown): LogEntry[] => {\n if (raw === null || raw === undefined || raw === '') return [];\n\n if (Array.isArray(raw)) {\n return raw.flatMap((item) => {\n if (typeof item === 'string') return item === '' ? [] : [parseLogLine(item)];\n if (isPlainObject(item)) {\n const entry = toLogEntryFromObject(item);\n return entry ? [entry] : [];\n }\n return [];\n });\n }\n\n if (isPlainObject(raw)) {\n const entry = toLogEntryFromObject(raw);\n return entry ? [entry] : [];\n }\n\n if (typeof raw !== 'string') return [];\n\n const lines = raw.split('\\n');\n const entries: LogEntry[] = [];\n for (const line of lines) {\n if (line === '') continue;\n entries.push(parseLogLine(line));\n }\n return entries;\n};\n\nexport const lastLogTimestamp = (entries: LogEntry[]) => {\n for (let i = entries.length - 1; i >= 0; i--) {\n const entry = entries[i];\n if (!entry) continue;\n if (entry.timestamp) return entry.timestamp;\n\n // A plain-text line may carry a timestamp embedded mid-line (legacy format).\n const match = entry.message.match(ISO_TIMESTAMP_REGEX);\n if (match) return match[0];\n }\n return null;\n};\n\nconst calculateNextLogTimestamp = (timestamp: string | null) => {\n if (timestamp === null) return null;\n return dayjs(timestamp).utc().add(1, 'second').utc().format();\n};\n\n/**\n * The tail plus the timestamp a follow-up poll resumes from. A {@link NOTHING_RUNNING_CODES} `400`\n * reads as an empty tail rather than an error — an idle app between visits, or a deployment that is\n * not the one currently serving, has no logs to stream and that is its normal condition.\n */\nexport const readAppLogsTail = async (fetchTail: () => Promise<ApiResponse<string>>) => {\n try {\n const { data } = await fetchTail();\n const entries = parseLogLines(data);\n\n return {\n entries,\n nextLogTimestamp: calculateNextLogTimestamp(lastLogTimestamp(entries)),\n };\n } catch (error) {\n if (isApiError(error) && error.response.status === HttpStatus.BAD_REQUEST) {\n const code = TailError.safeParse(error.data).data?.context?.code;\n if (code !== undefined && NOTHING_RUNNING_CODES.has(code)) {\n return { entries: [], nextLogTimestamp: null };\n }\n }\n throw error;\n }\n};\n\n/** The whole log as a file download, named by the service's `Content-Disposition` where it sets one. */\nexport const readAppLogsDownload = async (fetchLogs: () => Promise<ApiResponse<string>>) => {\n const { data, response } = await fetchLogs();\n const contentDisposition = parseContentDispositionHeader(\n response.headers.get(HttpHeader.CONTENT_DISPOSITION),\n );\n\n return {\n logs: data,\n fileName: contentDisposition.filename ?? DEFAULT_LOGS_FILE_NAME,\n };\n};\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
2
2
  const require_isPlainObject = require("./isPlainObject-BB3iy87C.cjs");
3
- const require_createFetchClient = require("./createFetchClient-BRfTjBLV.cjs");
3
+ const require_createFetchClient = require("./createFetchClient-DvZvD31l.cjs");
4
4
  let zod = require("zod");
5
5
  zod = require_rolldown_runtime.__toESM(zod, 1);
6
6
  let dayjs = require("dayjs");
@@ -150,4 +150,4 @@ Object.defineProperty(exports, "readAppLogsTail", {
150
150
  }
151
151
  });
152
152
 
153
- //# sourceMappingURL=appLogs-NIEDTDHf.cjs.map
153
+ //# sourceMappingURL=appLogs-D8K0VeNM.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"appLogs-NIEDTDHf.cjs","names":["utc","z","record","isPlainObject","isApiError","HttpStatus","parseContentDispositionHeader","HttpHeader"],"sources":["../src/domain/appLogs.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc.js';\nimport * as z from 'zod';\n\nimport {\n type ApiResponse,\n HttpHeader,\n isApiError,\n parseContentDispositionHeader,\n} from '../fetchClient';\nimport { HttpStatus } from '../internal';\nimport { isPlainObject } from '../utils/isPlainObject';\n\n/**\n * Reading a data app's container output. Shared by the two clients wrapping sandboxes-service —\n * `dataScience` (`/v1`) and `apps` (`/v2`) — which serve the same logs under different paths, so the\n * tail contract (how a line is parsed, where the next poll resumes, and that an idle app is not an\n * error) is defined once here rather than per surface.\n */\n\ndayjs.extend(utc);\n\nexport type LogEntry = {\n timestamp: string | null;\n message: string;\n};\n\nconst DEFAULT_LOGS_FILE_NAME = 'logs.txt';\n\nconst ISO_TIMESTAMP_REGEX = /\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z/;\nconst LEADING_ISO_TIMESTAMP_REGEX = /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z)\\s?/;\n\n/** The error envelope sandboxes-service returns; the tail branches on its `code`. */\nconst TailError = z.object({\n context: z.object({\n code: z.string(),\n }),\n});\n\n/**\n * There is nothing to read right now, reported per scope: an app whose serving member is asleep\n * answers `apps.appNotRunning`, a deployment that isn't running answers `apps.deploymentNotRunning` —\n * the normal state of a staged or retired one, since a deployment only runs while it is production.\n */\nconst NOTHING_RUNNING_CODES = new Set(['apps.appNotRunning', 'apps.deploymentNotRunning']);\n\nconst tryParseJsonl = (line: string): LogEntry | null => {\n if (!line.startsWith('{')) return null;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return null;\n }\n\n if (typeof parsed !== 'object' || parsed === null) return null;\n\n const record = parsed as Record<string, unknown>;\n const { timestamp, message } = record;\n\n if (typeof timestamp !== 'string' || typeof message !== 'string') return null;\n\n return {\n timestamp,\n message,\n };\n};\n\nconst parsePlainTextLine = (line: string): LogEntry => {\n const match = line.match(LEADING_ISO_TIMESTAMP_REGEX);\n if (match) {\n return { timestamp: match[1]!, message: line.slice(match[0].length) };\n }\n return { timestamp: null, message: line };\n};\n\nexport const parseLogLine = (line: string): LogEntry =>\n tryParseJsonl(line) ?? parsePlainTextLine(line);\n\nconst toLogEntryFromObject = (raw: Record<string, unknown>): LogEntry | null => {\n if (typeof raw.message !== 'string') return null;\n return {\n timestamp: typeof raw.timestamp === 'string' ? raw.timestamp : null,\n message: raw.message,\n };\n};\n\nexport const parseLogLines = (raw: unknown): LogEntry[] => {\n if (raw === null || raw === undefined || raw === '') return [];\n\n if (Array.isArray(raw)) {\n return raw.flatMap((item) => {\n if (typeof item === 'string') return item === '' ? [] : [parseLogLine(item)];\n if (isPlainObject(item)) {\n const entry = toLogEntryFromObject(item);\n return entry ? [entry] : [];\n }\n return [];\n });\n }\n\n if (isPlainObject(raw)) {\n const entry = toLogEntryFromObject(raw);\n return entry ? [entry] : [];\n }\n\n if (typeof raw !== 'string') return [];\n\n const lines = raw.split('\\n');\n const entries: LogEntry[] = [];\n for (const line of lines) {\n if (line === '') continue;\n entries.push(parseLogLine(line));\n }\n return entries;\n};\n\nexport const lastLogTimestamp = (entries: LogEntry[]) => {\n for (let i = entries.length - 1; i >= 0; i--) {\n const entry = entries[i];\n if (!entry) continue;\n if (entry.timestamp) return entry.timestamp;\n\n // A plain-text line may carry a timestamp embedded mid-line (legacy format).\n const match = entry.message.match(ISO_TIMESTAMP_REGEX);\n if (match) return match[0];\n }\n return null;\n};\n\nconst calculateNextLogTimestamp = (timestamp: string | null) => {\n if (timestamp === null) return null;\n return dayjs(timestamp).utc().add(1, 'second').utc().format();\n};\n\n/**\n * The tail plus the timestamp a follow-up poll resumes from. A {@link NOTHING_RUNNING_CODES} `400`\n * reads as an empty tail rather than an error — an idle app between visits, or a deployment that is\n * not the one currently serving, has no logs to stream and that is its normal condition.\n */\nexport const readAppLogsTail = async (fetchTail: () => Promise<ApiResponse<string>>) => {\n try {\n const { data } = await fetchTail();\n const entries = parseLogLines(data);\n\n return {\n entries,\n nextLogTimestamp: calculateNextLogTimestamp(lastLogTimestamp(entries)),\n };\n } catch (error) {\n if (isApiError(error) && error.response.status === HttpStatus.BAD_REQUEST) {\n const code = TailError.safeParse(error.data).data?.context?.code;\n if (code !== undefined && NOTHING_RUNNING_CODES.has(code)) {\n return { entries: [], nextLogTimestamp: null };\n }\n }\n throw error;\n }\n};\n\n/** The whole log as a file download, named by the service's `Content-Disposition` where it sets one. */\nexport const readAppLogsDownload = async (fetchLogs: () => Promise<ApiResponse<string>>) => {\n const { data, response } = await fetchLogs();\n const contentDisposition = parseContentDispositionHeader(\n response.headers.get(HttpHeader.CONTENT_DISPOSITION),\n );\n\n return {\n logs: data,\n fileName: contentDisposition.filename ?? DEFAULT_LOGS_FILE_NAME,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"appLogs-D8K0VeNM.cjs","names":["utc","z","record","isPlainObject","isApiError","HttpStatus","parseContentDispositionHeader","HttpHeader"],"sources":["../src/domain/appLogs.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc.js';\nimport * as z from 'zod';\n\nimport {\n type ApiResponse,\n HttpHeader,\n isApiError,\n parseContentDispositionHeader,\n} from '../fetchClient';\nimport { HttpStatus } from '../internal';\nimport { isPlainObject } from '../utils/isPlainObject';\n\n/**\n * Reading a data app's container output. Shared by the two clients wrapping sandboxes-service —\n * `dataScience` (`/v1`) and `apps` (`/v2`) — which serve the same logs under different paths, so the\n * tail contract (how a line is parsed, where the next poll resumes, and that an idle app is not an\n * error) is defined once here rather than per surface.\n */\n\ndayjs.extend(utc);\n\nexport type LogEntry = {\n timestamp: string | null;\n message: string;\n};\n\nconst DEFAULT_LOGS_FILE_NAME = 'logs.txt';\n\nconst ISO_TIMESTAMP_REGEX = /\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z/;\nconst LEADING_ISO_TIMESTAMP_REGEX = /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z)\\s?/;\n\n/** The error envelope sandboxes-service returns; the tail branches on its `code`. */\nconst TailError = z.object({\n context: z.object({\n code: z.string(),\n }),\n});\n\n/**\n * There is nothing to read right now, reported per scope: an app whose serving member is asleep\n * answers `apps.appNotRunning`, a deployment that isn't running answers `apps.deploymentNotRunning` —\n * the normal state of a staged or retired one, since a deployment only runs while it is production.\n */\nconst NOTHING_RUNNING_CODES = new Set(['apps.appNotRunning', 'apps.deploymentNotRunning']);\n\nconst tryParseJsonl = (line: string): LogEntry | null => {\n if (!line.startsWith('{')) return null;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return null;\n }\n\n if (typeof parsed !== 'object' || parsed === null) return null;\n\n const record = parsed as Record<string, unknown>;\n const { timestamp, message } = record;\n\n if (typeof timestamp !== 'string' || typeof message !== 'string') return null;\n\n return {\n timestamp,\n message,\n };\n};\n\nconst parsePlainTextLine = (line: string): LogEntry => {\n const match = line.match(LEADING_ISO_TIMESTAMP_REGEX);\n if (match) {\n return { timestamp: match[1]!, message: line.slice(match[0].length) };\n }\n return { timestamp: null, message: line };\n};\n\nexport const parseLogLine = (line: string): LogEntry =>\n tryParseJsonl(line) ?? parsePlainTextLine(line);\n\nconst toLogEntryFromObject = (raw: Record<string, unknown>): LogEntry | null => {\n if (typeof raw.message !== 'string') return null;\n return {\n timestamp: typeof raw.timestamp === 'string' ? raw.timestamp : null,\n message: raw.message,\n };\n};\n\nexport const parseLogLines = (raw: unknown): LogEntry[] => {\n if (raw === null || raw === undefined || raw === '') return [];\n\n if (Array.isArray(raw)) {\n return raw.flatMap((item) => {\n if (typeof item === 'string') return item === '' ? [] : [parseLogLine(item)];\n if (isPlainObject(item)) {\n const entry = toLogEntryFromObject(item);\n return entry ? [entry] : [];\n }\n return [];\n });\n }\n\n if (isPlainObject(raw)) {\n const entry = toLogEntryFromObject(raw);\n return entry ? [entry] : [];\n }\n\n if (typeof raw !== 'string') return [];\n\n const lines = raw.split('\\n');\n const entries: LogEntry[] = [];\n for (const line of lines) {\n if (line === '') continue;\n entries.push(parseLogLine(line));\n }\n return entries;\n};\n\nexport const lastLogTimestamp = (entries: LogEntry[]) => {\n for (let i = entries.length - 1; i >= 0; i--) {\n const entry = entries[i];\n if (!entry) continue;\n if (entry.timestamp) return entry.timestamp;\n\n // A plain-text line may carry a timestamp embedded mid-line (legacy format).\n const match = entry.message.match(ISO_TIMESTAMP_REGEX);\n if (match) return match[0];\n }\n return null;\n};\n\nconst calculateNextLogTimestamp = (timestamp: string | null) => {\n if (timestamp === null) return null;\n return dayjs(timestamp).utc().add(1, 'second').utc().format();\n};\n\n/**\n * The tail plus the timestamp a follow-up poll resumes from. A {@link NOTHING_RUNNING_CODES} `400`\n * reads as an empty tail rather than an error — an idle app between visits, or a deployment that is\n * not the one currently serving, has no logs to stream and that is its normal condition.\n */\nexport const readAppLogsTail = async (fetchTail: () => Promise<ApiResponse<string>>) => {\n try {\n const { data } = await fetchTail();\n const entries = parseLogLines(data);\n\n return {\n entries,\n nextLogTimestamp: calculateNextLogTimestamp(lastLogTimestamp(entries)),\n };\n } catch (error) {\n if (isApiError(error) && error.response.status === HttpStatus.BAD_REQUEST) {\n const code = TailError.safeParse(error.data).data?.context?.code;\n if (code !== undefined && NOTHING_RUNNING_CODES.has(code)) {\n return { entries: [], nextLogTimestamp: null };\n }\n }\n throw error;\n }\n};\n\n/** The whole log as a file download, named by the service's `Content-Disposition` where it sets one. */\nexport const readAppLogsDownload = async (fetchLogs: () => Promise<ApiResponse<string>>) => {\n const { data, response } = await fetchLogs();\n const contentDisposition = parseContentDispositionHeader(\n response.headers.get(HttpHeader.CONTENT_DISPOSITION),\n );\n\n return {\n logs: data,\n fileName: contentDisposition.filename ?? DEFAULT_LOGS_FILE_NAME,\n };\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import "./index-CQrKS7PV.cjs";
1
+ import "./index-DhVFuQDv.cjs";
2
2
  //#region src/domain/appLogs.d.ts
3
3
  type LogEntry = {
4
4
  timestamp: string | null;
@@ -7,4 +7,4 @@ type LogEntry = {
7
7
  declare const parseLogLines: (raw: unknown) => LogEntry[];
8
8
  //#endregion
9
9
  export { parseLogLines as n, LogEntry as t };
10
- //# sourceMappingURL=appLogs-BAaaGYKg.d.cts.map
10
+ //# sourceMappingURL=appLogs-Q4A7A_Fc.d.cts.map
@@ -1,4 +1,4 @@
1
- import "./index-CeJOmN-P.js";
1
+ import "./index-DVhTNwvu.js";
2
2
  //#region src/domain/appLogs.d.ts
3
3
  type LogEntry = {
4
4
  timestamp: string | null;
@@ -7,4 +7,4 @@ type LogEntry = {
7
7
  declare const parseLogLines: (raw: unknown) => LogEntry[];
8
8
  //#endregion
9
9
  export { parseLogLines as n, LogEntry as t };
10
- //# sourceMappingURL=appLogs-DX_WTBCa.d.ts.map
10
+ //# sourceMappingURL=appLogs-u0XMZLjS.d.ts.map
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_createOpenapiFetchClient = require("../createOpenapiFetchClient-CyDUFxHB.cjs");
3
- const require_auth = require("../auth-DP-6TFiM.cjs");
4
- const require_appLogs = require("../appLogs-NIEDTDHf.cjs");
2
+ const require_createOpenapiFetchClient = require("../createOpenapiFetchClient-C57Ljzi6.cjs");
3
+ const require_auth = require("../auth-C2_JLisH.cjs");
4
+ const require_appLogs = require("../appLogs-D8K0VeNM.cjs");
5
5
  //#region src/clients/apps/appsClient.ts
6
6
  /**
7
7
  * `/v2` App Deployments — data apps plus the immutable deployment history behind them. Sibling of
@@ -1,6 +1,6 @@
1
- import { n as ClientInitOptions } from "../types-BREGN3qo.cjs";
2
- import { S as components, b as GetLogsTailQuery, c as CreateCredentialBody, f as CredentialId, g as DeploymentId, l as CreateDeploymentBody, r as AppId, s as CreateAppBody, t as App, v as GetAppRunsQuery, x as RunId, y as GetAppsQuery } from "../types-CyiRYRVq.cjs";
3
- import { t as LogEntry } from "../appLogs-BAaaGYKg.cjs";
1
+ import { n as ClientInitOptions } from "../types-DHI0g51U.cjs";
2
+ import { S as components, b as GetLogsTailQuery, c as CreateCredentialBody, f as CredentialId, g as DeploymentId, l as CreateDeploymentBody, r as AppId, s as CreateAppBody, t as App, v as GetAppRunsQuery, x as RunId, y as GetAppsQuery } from "../types-3p0adMdd.cjs";
3
+ import { t as LogEntry } from "../appLogs-Q4A7A_Fc.cjs";
4
4
  //#region src/clients/apps/appsClient.d.ts
5
5
  /**
6
6
  * No `idempotencyKey`. The service accepted an `Idempotency-Key` that turned a replayed create