@keboola/api-client 35.0.0 → 39.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 (268) hide show
  1. package/AGENTS.md +12 -3
  2. package/API-SURFACE.md +14 -1
  3. package/CHANGELOG.md +102 -0
  4. package/README.md +19 -17
  5. package/dist/{ManagementClientAuthError-ey-f03vy.js → ManagementClientAuthError-Cr9IOsnJ.js} +3 -2
  6. package/dist/{ManagementClientAuthError-ey-f03vy.js.map → ManagementClientAuthError-Cr9IOsnJ.js.map} +1 -1
  7. package/dist/{ManagementClientAuthError-DD4u0EU7.cjs → ManagementClientAuthError-FcfMJNhr.cjs} +3 -2
  8. package/dist/{ManagementClientAuthError-DD4u0EU7.cjs.map → ManagementClientAuthError-FcfMJNhr.cjs.map} +1 -1
  9. package/dist/ai/index.cjs +2 -2
  10. package/dist/ai/index.js +2 -2
  11. package/dist/{appLogs-BjfUoWzs.cjs → appLogs-C_zP0lpv.cjs} +2 -2
  12. package/dist/{appLogs-BjfUoWzs.cjs.map → appLogs-C_zP0lpv.cjs.map} +1 -1
  13. package/dist/{appLogs-xsVkTriU.js → appLogs-Cl7Q_MR9.js} +2 -2
  14. package/dist/{appLogs-xsVkTriU.js.map → appLogs-Cl7Q_MR9.js.map} +1 -1
  15. package/dist/apps/index.cjs +29 -22
  16. package/dist/apps/index.cjs.map +1 -1
  17. package/dist/apps/index.d.cts +31 -73
  18. package/dist/apps/index.d.ts +31 -73
  19. package/dist/apps/index.js +29 -22
  20. package/dist/apps/index.js.map +1 -1
  21. package/dist/apps/types.d.cts +2 -2
  22. package/dist/apps/types.d.ts +2 -2
  23. package/dist/assets/index.cjs +1 -1
  24. package/dist/assets/index.js +1 -1
  25. package/dist/auth/index.cjs +1 -1
  26. package/dist/auth/index.js +1 -1
  27. package/dist/{auth-aItmDu45.js → auth-BjmkFOgd.js} +2 -2
  28. package/dist/{auth-aItmDu45.js.map → auth-BjmkFOgd.js.map} +1 -1
  29. package/dist/{auth-JQ33o3nU.cjs → auth-DLWnl18b.cjs} +2 -2
  30. package/dist/{auth-JQ33o3nU.cjs.map → auth-DLWnl18b.cjs.map} +1 -1
  31. package/dist/{authClient-_PpvGgZJ.cjs → authClient-8yU1last.cjs} +5 -5
  32. package/dist/{authClient-_PpvGgZJ.cjs.map → authClient-8yU1last.cjs.map} +1 -1
  33. package/dist/{authClient-D7W9vWPR.js → authClient-BTo4Afm6.js} +5 -5
  34. package/dist/{authClient-D7W9vWPR.js.map → authClient-BTo4Afm6.js.map} +1 -1
  35. package/dist/billing/index.cjs +2 -2
  36. package/dist/billing/index.js +2 -2
  37. package/dist/businessWorkspaceApi/index.cjs +3 -0
  38. package/dist/businessWorkspaceApi/index.d.cts +2 -0
  39. package/dist/businessWorkspaceApi/index.d.ts +2 -0
  40. package/dist/businessWorkspaceApi/index.js +2 -0
  41. package/dist/businessWorkspaceApi/types.cjs +0 -0
  42. package/dist/businessWorkspaceApi/types.d.cts +2 -0
  43. package/dist/businessWorkspaceApi/types.d.ts +2 -0
  44. package/dist/businessWorkspaceApi/types.js +1 -0
  45. package/dist/businessWorkspaceApi-BD-iUj07.js +61 -0
  46. package/dist/businessWorkspaceApi-BD-iUj07.js.map +1 -0
  47. package/dist/businessWorkspaceApi-wyBdbpIJ.cjs +66 -0
  48. package/dist/businessWorkspaceApi-wyBdbpIJ.cjs.map +1 -0
  49. package/dist/businessWorkspaceApiClient-C2WyWN3b.d.ts +529 -0
  50. package/dist/businessWorkspaceApiClient-CRM1U8b-.d.cts +529 -0
  51. package/dist/chat/index.cjs +5 -5
  52. package/dist/chat/index.cjs.map +1 -1
  53. package/dist/chat/index.d.cts +1 -1
  54. package/dist/chat/index.d.ts +1 -1
  55. package/dist/chat/index.js +5 -5
  56. package/dist/chat/index.js.map +1 -1
  57. package/dist/constants/index.cjs +1 -1
  58. package/dist/constants/index.d.cts +2 -2
  59. package/dist/constants/index.d.ts +2 -2
  60. package/dist/constants/index.js +1 -1
  61. package/dist/{constants-wfbFsqqN.js → constants-C2tYAJSj.js} +10 -1
  62. package/dist/constants-C2tYAJSj.js.map +1 -0
  63. package/dist/{constants-C4DlsF_M.cjs → constants-C6xku_Vx.cjs} +10 -1
  64. package/dist/constants-C6xku_Vx.cjs.map +1 -0
  65. package/dist/{createFetchClient-DgMiqTJ8.cjs → createFetchClient-BlgPbjFj.cjs} +14 -2
  66. package/dist/createFetchClient-BlgPbjFj.cjs.map +1 -0
  67. package/dist/{createFetchClient-U-ZrwPl2.js → createFetchClient-C-cadpBx.js} +14 -2
  68. package/dist/createFetchClient-C-cadpBx.js.map +1 -0
  69. package/dist/{createGenericFetchClient-rxvUUbap.js → createGenericFetchClient-Bnf1QK9W.js} +2 -2
  70. package/dist/{createGenericFetchClient-rxvUUbap.js.map → createGenericFetchClient-Bnf1QK9W.js.map} +1 -1
  71. package/dist/{createGenericFetchClient-o3cPJeRn.cjs → createGenericFetchClient-lcozzwk2.cjs} +2 -2
  72. package/dist/{createGenericFetchClient-o3cPJeRn.cjs.map → createGenericFetchClient-lcozzwk2.cjs.map} +1 -1
  73. package/dist/{createOpenapiFetchClient-DhUU3M1W.cjs → createOpenapiFetchClient-C3UmDXpe.cjs} +2 -2
  74. package/dist/{createOpenapiFetchClient-DhUU3M1W.cjs.map → createOpenapiFetchClient-C3UmDXpe.cjs.map} +1 -1
  75. package/dist/{createOpenapiFetchClient-BVSc9ibR.js → createOpenapiFetchClient-COaPeeQ0.js} +2 -2
  76. package/dist/{createOpenapiFetchClient-BVSc9ibR.js.map → createOpenapiFetchClient-COaPeeQ0.js.map} +1 -1
  77. package/dist/{credential-DVWvJFJs.cjs → credential-CAulvfZ-.cjs} +2 -2
  78. package/dist/{credential-DVWvJFJs.cjs.map → credential-CAulvfZ-.cjs.map} +1 -1
  79. package/dist/{credential-CihSf_xs.js → credential-DWXbo4IX.js} +2 -2
  80. package/dist/{credential-CihSf_xs.js.map → credential-DWXbo4IX.js.map} +1 -1
  81. package/dist/dataScience/index.cjs +2 -2
  82. package/dist/dataScience/index.js +2 -2
  83. package/dist/{dataScience-C1gO5zUn.js → dataScience-B_BmnB1m.js} +5 -5
  84. package/dist/{dataScience-C1gO5zUn.js.map → dataScience-B_BmnB1m.js.map} +1 -1
  85. package/dist/{dataScience-0Rl_EuV_.cjs → dataScience-D-hyc4GY.cjs} +5 -5
  86. package/dist/{dataScience-0Rl_EuV_.cjs.map → dataScience-D-hyc4GY.cjs.map} +1 -1
  87. package/dist/developerPortal/index.cjs +1 -1
  88. package/dist/developerPortal/index.js +1 -1
  89. package/dist/{developerPortalClient-ki0XS_OD.cjs → developerPortalClient-CutPqoAa.cjs} +3 -3
  90. package/dist/{developerPortalClient-ki0XS_OD.cjs.map → developerPortalClient-CutPqoAa.cjs.map} +1 -1
  91. package/dist/{developerPortalClient-C_48z8BN.js → developerPortalClient-yHFTkKPb.js} +3 -3
  92. package/dist/{developerPortalClient-C_48z8BN.js.map → developerPortalClient-yHFTkKPb.js.map} +1 -1
  93. package/dist/domain/permissions/index.d.cts +2 -2
  94. package/dist/domain/permissions/index.d.ts +2 -2
  95. package/dist/editor/index.cjs +2 -2
  96. package/dist/editor/index.js +2 -2
  97. package/dist/encryption/index.cjs +1 -1
  98. package/dist/encryption/index.d.cts +1 -1
  99. package/dist/encryption/index.d.ts +1 -1
  100. package/dist/encryption/index.js +1 -1
  101. package/dist/encryption/types.d.cts +1 -1
  102. package/dist/encryption/types.d.ts +1 -1
  103. package/dist/import/index.cjs +1 -1
  104. package/dist/import/index.js +1 -1
  105. package/dist/{import-C83w7BKz.cjs → import-7YyyD_U_.cjs} +3 -3
  106. package/dist/{import-C83w7BKz.cjs.map → import-7YyyD_U_.cjs.map} +1 -1
  107. package/dist/{import-CROEK82b.js → import-xliONVib.js} +3 -3
  108. package/dist/{import-CROEK82b.js.map → import-xliONVib.js.map} +1 -1
  109. package/dist/{index-D8rcUbnk.d.ts → index-1r_CskjU.d.ts} +2 -2
  110. package/dist/{index-P-iT5THa.d.ts → index-BK-qHT39.d.ts} +8 -4
  111. package/dist/{index-BLx14ZI4.d.cts → index-CHXnJQ9s.d.cts} +117 -76
  112. package/dist/{index-Dodwl64k.d.cts → index-CWoEnDJ_.d.cts} +8 -4
  113. package/dist/{index-NaYLwG_h.d.ts → index-DBklbaTp.d.cts} +9 -1
  114. package/dist/{index-NaYLwG_h.d.cts → index-DBklbaTp.d.ts} +9 -1
  115. package/dist/{index-BgLnWTZU.d.cts → index-DVw4Av4b.d.cts} +4 -4
  116. package/dist/{index-DR4QqItd.d.cts → index-DWf6FXOr.d.cts} +2 -2
  117. package/dist/{index-CqgtL2NU.d.ts → index-De5qUWhp.d.ts} +4 -4
  118. package/dist/{index-DFBFa3SS.d.ts → index-GfKzh267.d.ts} +117 -76
  119. package/dist/index.cjs +30 -19
  120. package/dist/index.cjs.map +1 -1
  121. package/dist/index.d.cts +3 -3
  122. package/dist/index.d.ts +3 -3
  123. package/dist/index.js +30 -20
  124. package/dist/index.js.map +1 -1
  125. package/dist/{isLoginPageRedirect-B0EmRsHr.cjs → isLoginPageRedirect-Cm6Pn8Pj.cjs} +2 -2
  126. package/dist/{isLoginPageRedirect-B0EmRsHr.cjs.map → isLoginPageRedirect-Cm6Pn8Pj.cjs.map} +1 -1
  127. package/dist/{isLoginPageRedirect-BTTAedW-.js → isLoginPageRedirect-hyPqyWNX.js} +2 -2
  128. package/dist/{isLoginPageRedirect-BTTAedW-.js.map → isLoginPageRedirect-hyPqyWNX.js.map} +1 -1
  129. package/dist/kaiAgent/index.cjs +1 -1
  130. package/dist/kaiAgent/index.d.cts +1 -1
  131. package/dist/kaiAgent/index.d.ts +1 -1
  132. package/dist/kaiAgent/index.js +1 -1
  133. package/dist/kaiAgent/types.d.cts +2 -2
  134. package/dist/kaiAgent/types.d.ts +2 -2
  135. package/dist/{kaiAgent-8LNzGhZc.js → kaiAgent-CcT2oNip.js} +41 -6
  136. package/dist/kaiAgent-CcT2oNip.js.map +1 -0
  137. package/dist/{kaiAgent-B_TaUPRt.cjs → kaiAgent-DaB6UCsh.cjs} +41 -6
  138. package/dist/kaiAgent-DaB6UCsh.cjs.map +1 -0
  139. package/dist/{kaiAgentClient-BJj_2aqt.d.ts → kaiAgentClient-B5L4gbQ1.d.ts} +8 -3
  140. package/dist/{kaiAgentClient-DhTaM3GC.d.cts → kaiAgentClient-CHpULyeG.d.cts} +8 -3
  141. package/dist/management/index.cjs +1 -1
  142. package/dist/management/index.d.cts +2 -2
  143. package/dist/management/index.d.ts +2 -2
  144. package/dist/management/index.js +1 -1
  145. package/dist/management/types.d.cts +2 -2
  146. package/dist/management/types.d.ts +2 -2
  147. package/dist/{management-BoxlRNg2.cjs → management-DeZiQSlw.cjs} +41 -8
  148. package/dist/management-DeZiQSlw.cjs.map +1 -0
  149. package/dist/{management-Bp440RsV.js → management-ckdnu1dA.js} +41 -8
  150. package/dist/management-ckdnu1dA.js.map +1 -0
  151. package/dist/metastore/index.cjs +1 -1
  152. package/dist/metastore/index.js +1 -1
  153. package/dist/{metastore-BYYWTb3m.cjs → metastore-9AGrwjmN.cjs} +4 -4
  154. package/dist/{metastore-BYYWTb3m.cjs.map → metastore-9AGrwjmN.cjs.map} +1 -1
  155. package/dist/{metastore-VCDRVhUT.js → metastore-B0PolCjQ.js} +4 -4
  156. package/dist/{metastore-VCDRVhUT.js.map → metastore-B0PolCjQ.js.map} +1 -1
  157. package/dist/microsoftGraph/index.cjs +2 -2
  158. package/dist/microsoftGraph/index.js +2 -2
  159. package/dist/notifications/index.cjs +3 -3
  160. package/dist/notifications/index.js +3 -3
  161. package/dist/oauth/index.cjs +1 -1
  162. package/dist/oauth/index.js +1 -1
  163. package/dist/{oauth--asfePw-.js → oauth-BnHVf4cB.js} +5 -5
  164. package/dist/{oauth--asfePw-.js.map → oauth-BnHVf4cB.js.map} +1 -1
  165. package/dist/{oauth-B8yqG6Sy.cjs → oauth-DNtv4Ihb.cjs} +5 -5
  166. package/dist/{oauth-B8yqG6Sy.cjs.map → oauth-DNtv4Ihb.cjs.map} +1 -1
  167. package/dist/omnisearch/index.cjs +2 -2
  168. package/dist/omnisearch/index.js +2 -2
  169. package/dist/{project-hePfzUY0.d.cts → project-BRpzv3yE.d.cts} +2 -2
  170. package/dist/{project-C2wvX0xZ.d.ts → project-DCHOxRWd.d.ts} +2 -2
  171. package/dist/queryService/index.cjs +1 -1
  172. package/dist/queryService/index.d.cts +1 -1
  173. package/dist/queryService/index.d.ts +1 -1
  174. package/dist/queryService/index.js +1 -1
  175. package/dist/{queryService-BVtjkXy1.cjs → queryService-BVwD6Vmc.cjs} +5 -5
  176. package/dist/{queryService-BVtjkXy1.cjs.map → queryService-BVwD6Vmc.cjs.map} +1 -1
  177. package/dist/{queryService-Ca65E5KH.js → queryService-j3XZ2mX6.js} +5 -5
  178. package/dist/{queryService-Ca65E5KH.js.map → queryService-j3XZ2mX6.js.map} +1 -1
  179. package/dist/queue/index.cjs +1 -1
  180. package/dist/queue/index.d.cts +1 -1
  181. package/dist/queue/index.d.ts +1 -1
  182. package/dist/queue/index.js +1 -1
  183. package/dist/{queue-DyotLFJi.js → queue-Dagl0sdP.js} +4 -4
  184. package/dist/{queue-DyotLFJi.js.map → queue-Dagl0sdP.js.map} +1 -1
  185. package/dist/{queue-OJJUUqc2.cjs → queue-e3rMWbmK.cjs} +4 -4
  186. package/dist/{queue-OJJUUqc2.cjs.map → queue-e3rMWbmK.cjs.map} +1 -1
  187. package/dist/scheduler/index.cjs +3 -3
  188. package/dist/scheduler/index.js +3 -3
  189. package/dist/sdk/configurations/index.d.cts +4 -4
  190. package/dist/sdk/configurations/index.d.ts +4 -4
  191. package/dist/sdk/developerPortal/index.cjs +3 -3
  192. package/dist/sdk/developerPortal/index.js +3 -3
  193. package/dist/sdk/queryService/index.d.cts +1 -1
  194. package/dist/sdk/queryService/index.d.ts +1 -1
  195. package/dist/sdk/semanticLayer/index.cjs +1 -1
  196. package/dist/sdk/semanticLayer/index.js +1 -1
  197. package/dist/sdk/storage/index.d.cts +1 -1
  198. package/dist/sdk/storage/index.d.ts +1 -1
  199. package/dist/sdk/vault/index.d.cts +1 -1
  200. package/dist/sdk/vault/index.d.ts +1 -1
  201. package/dist/{semanticLayer-CSqmtHRo.js → semanticLayer-6_gtFxDu.js} +38 -5
  202. package/dist/semanticLayer-6_gtFxDu.js.map +1 -0
  203. package/dist/{semanticLayer-E0Vilu8u.cjs → semanticLayer-9uTaU7UT.cjs} +38 -5
  204. package/dist/semanticLayer-9uTaU7UT.cjs.map +1 -0
  205. package/dist/{serviceIds-DRcoTnSd.d.ts → serviceIds-DC-H6ZD9.d.cts} +2 -1
  206. package/dist/{serviceIds-DRcoTnSd.d.cts → serviceIds-DC-H6ZD9.d.ts} +2 -1
  207. package/dist/status/index.cjs +1 -1
  208. package/dist/status/index.js +1 -1
  209. package/dist/storage/index.cjs +5 -4
  210. package/dist/storage/index.d.cts +2 -2
  211. package/dist/storage/index.d.ts +2 -2
  212. package/dist/storage/index.js +5 -5
  213. package/dist/storage/types.d.cts +3 -3
  214. package/dist/storage/types.d.ts +3 -3
  215. package/dist/{storage-BKm7cztt.cjs → storage-HFUdEy7P.cjs} +43 -6
  216. package/dist/storage-HFUdEy7P.cjs.map +1 -0
  217. package/dist/{storage-LYwFQPNO.js → storage-Ob1LUIDq.js} +38 -7
  218. package/dist/storage-Ob1LUIDq.js.map +1 -0
  219. package/dist/stream/index.cjs +3 -3
  220. package/dist/stream/index.js +3 -3
  221. package/dist/syncActions/index.cjs +1 -1
  222. package/dist/syncActions/index.js +1 -1
  223. package/dist/{syncActions-QeBhIVhG.js → syncActions-B3NS5a0g.js} +5 -5
  224. package/dist/{syncActions-QeBhIVhG.js.map → syncActions-B3NS5a0g.js.map} +1 -1
  225. package/dist/{syncActions-OEZdVffK.cjs → syncActions-D2DhY6pP.cjs} +5 -5
  226. package/dist/{syncActions-OEZdVffK.cjs.map → syncActions-D2DhY6pP.cjs.map} +1 -1
  227. package/dist/telemetry/index.cjs +3 -3
  228. package/dist/telemetry/index.js +3 -3
  229. package/dist/{types-B3GOGUJ7.d.cts → types-B-P4vQe0.d.cts} +47 -2
  230. package/dist/{types-DEc55spK.d.ts → types-B95uNQ9o.d.ts} +3 -3
  231. package/dist/{types-BQsOHNI0.d.ts → types-BrPlv-NS.d.ts} +3 -3
  232. package/dist/{types-DjrRmQUe.d.cts → types-CmF3pR2n.d.cts} +3 -3
  233. package/dist/{types-f8W_j6qD.d.cts → types-Crhy0c9m.d.cts} +657 -199
  234. package/dist/{types-CBgLCkYe.d.ts → types-D6UmMa6E.d.ts} +224 -401
  235. package/dist/{types-DPS8nwkV.d.cts → types-DOyNe7oe.d.cts} +2 -1
  236. package/dist/{types-BMeDOB_D.d.ts → types-DPl8pZsY.d.ts} +47 -2
  237. package/dist/{types-DARv_P6O.d.cts → types-DXskkNp8.d.cts} +224 -401
  238. package/dist/{types-CaYtinmA.d.cts → types-D_j2Uq5X.d.cts} +3 -3
  239. package/dist/{types-BupPADSm.d.ts → types-DrqKICcK.d.ts} +657 -199
  240. package/dist/{types-DBOSvWtD.d.ts → types-gi4Eay19.d.ts} +2 -1
  241. package/dist/{validateConnectionStatus-olE2sQ3U.js → validateConnectionStatus-828HV8WL.js} +4 -3
  242. package/dist/validateConnectionStatus-828HV8WL.js.map +1 -0
  243. package/dist/{validateConnectionStatus-CsvYmCOI.cjs → validateConnectionStatus-CvBKyeDO.cjs} +4 -3
  244. package/dist/validateConnectionStatus-CvBKyeDO.cjs.map +1 -0
  245. package/dist/vault/index.cjs +4 -4
  246. package/dist/vault/index.js +4 -4
  247. package/package.json +34 -8
  248. package/surface/apps.md +11 -11
  249. package/surface/billing.md +2 -2
  250. package/surface/businessWorkspaceApi.md +12 -0
  251. package/surface/chat.md +1 -1
  252. package/surface/editor.md +5 -5
  253. package/surface/kaiAgent.md +5 -2
  254. package/surface/management.md +4 -0
  255. package/dist/constants-C4DlsF_M.cjs.map +0 -1
  256. package/dist/constants-wfbFsqqN.js.map +0 -1
  257. package/dist/createFetchClient-DgMiqTJ8.cjs.map +0 -1
  258. package/dist/createFetchClient-U-ZrwPl2.js.map +0 -1
  259. package/dist/kaiAgent-8LNzGhZc.js.map +0 -1
  260. package/dist/kaiAgent-B_TaUPRt.cjs.map +0 -1
  261. package/dist/management-BoxlRNg2.cjs.map +0 -1
  262. package/dist/management-Bp440RsV.js.map +0 -1
  263. package/dist/semanticLayer-CSqmtHRo.js.map +0 -1
  264. package/dist/semanticLayer-E0Vilu8u.cjs.map +0 -1
  265. package/dist/storage-BKm7cztt.cjs.map +0 -1
  266. package/dist/storage-LYwFQPNO.js.map +0 -1
  267. package/dist/validateConnectionStatus-CsvYmCOI.cjs.map +0 -1
  268. package/dist/validateConnectionStatus-olE2sQ3U.js.map +0 -1
package/AGENTS.md CHANGED
@@ -334,11 +334,19 @@ Three type guards live in `createFetchClient.ts`, re-exported from `@keboola/api
334
334
  | Guard | Catches | UX outcome |
335
335
  | -------------------- | --------------------------------------------------------------- | ------------------------------------------------- |
336
336
  | `isAbortError` | `DOMException { name: 'AbortError' }` | Silently ignore — user/unmount cancelled |
337
- | `isApiError` | HTTP error responses parsed by the SDK | Surface `err.message` (HTTP `statusText`) |
337
+ | `isApiError` | HTTP error responses parsed by the SDK | Surface `readableReason(err)`; see below |
338
338
  | `isFetchClientError` | `TypeError` (DNS/CORS), `SyntaxError` (bad JSON), or `ApiError` | Show a "Network problem" message; do not re-throw |
339
339
 
340
340
  > `DOMException` is in the `FetchClientError` _type_ but **not** matched by the `isFetchClientError` _guard_ — abort `DOMException`s are reachable only through `isAbortError`, so always check `isAbortError` first.
341
341
 
342
+ **Never render `err.message` to a user.** An `ApiError`'s message is a status line — `"404 Not Found"`, or just `"404"` over HTTP/2, which is every production response. It exists so an error reporter has the status; it names neither the action that failed nor anything the reader can do. `readableReason(err)` returns the service's own sentence from the parsed body, and `undefined` when there is none — which is the cue to render your own wording:
343
+
344
+ ```ts
345
+ toast.error(readableReason(err) ?? 'The semantic model could not be deleted.');
346
+ ```
347
+
348
+ Don't reach for `err.message || 'fallback'` or test `err.message === ''` instead. A status line is never empty, so those guards silently stop firing and the reader gets a number where a sentence was written for them.
349
+
342
350
  Error classes the SDK can throw — branch on these instead of a catch-all `unknown`:
343
351
 
344
352
  | Class | Exported from | Branch specifically when… |
@@ -359,6 +367,7 @@ import {
359
367
  isApiError,
360
368
  isFetchClientError,
361
369
  isManagementClientAuthError,
370
+ readableReason,
362
371
  } from '@keboola/api-client';
363
372
 
364
373
  try {
@@ -366,7 +375,7 @@ try {
366
375
  } catch (err) {
367
376
  if (isAbortError(err)) return; // cancelled — no UI
368
377
  if (isManagementClientAuthError(err)) return redirectToLogin();
369
- if (isApiError(err)) return toast.error(err.message); // HTTP error from server
378
+ if (isApiError(err)) return toast.error(readableReason(err) ?? 'Saving failed.'); // see below
370
379
  if (isFetchClientError(err)) return toast.error('Network problem');
371
380
  throw err; // unexpected — propagate
372
381
  }
@@ -377,7 +386,7 @@ TanStack Query's `onError` / `throwOnError` handles most cases; the explicit try
377
386
  - **Transport (`TypeError`)** → transient; retry up to 3× with backoff (`retryDelay: (a) => Math.min(1000 * 2 ** a, 30_000)`). Skip `SyntaxError` (server contract bug, not transient).
378
387
  - **401 / 403** → never retry. Session expiry surfaces as `ManagementClientAuthError` (check `isManagementClientAuthError`) — branch to a global re-login.
379
388
  - **404 on a `GET`** → normal product state; render an empty state, not "Something went wrong". A 404 on a _mutation_ (deleting an already-gone resource) can be treated as success.
380
- - **5xx** → server-side, often transient. The default client wires **no** transport-level retry (the keboola client sets only the storage-token middleware). Add `createRetryMiddleware` to the client's `middlewares` for automatic 5xx retry, and then keep `retry: false` at the query level so attempts don't multiply (query `retry: 2` × the middleware's 6 transport attempts = 18 requests). Surface `err.message` (`statusText`); richer detail may be on `err.data` (typed `unknown` — narrow before reading).
389
+ - **5xx** → server-side, often transient. The default client wires **no** transport-level retry (the keboola client sets only the storage-token middleware). Add `createRetryMiddleware` to the client's `middlewares` for automatic 5xx retry, and then keep `retry: false` at the query level so attempts don't multiply (query `retry: 2` × the middleware's 6 transport attempts = 18 requests). Surface `readableReason(err)` with your own wording as the fallback; richer detail may be on `err.data` (typed `unknown` — narrow before reading).
381
390
 
382
391
  ```ts
383
392
  useQuery({
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
- 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.
7
+ 26 top-level namespaces, 645 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
 
@@ -91,6 +91,15 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
91
91
  - `getCreditsAndTopUp`
92
92
  - `healthCheck`
93
93
 
94
+ ## [`api.businessWorkspaceApi`](./surface/businessWorkspaceApi.md)
95
+
96
+ - `createDashboard`
97
+ - `deleteDashboard`
98
+ - `getDashboard`
99
+ - `getDashboards`
100
+ - `healthCheck`
101
+ - `updateDashboard`
102
+
94
103
  ## [`api.chat`](./surface/chat.md)
95
104
 
96
105
  - `createChat`
@@ -186,6 +195,8 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
186
195
  - `deleteChat`
187
196
  - `downloadSandboxFile`
188
197
  - `getAgentSettings`
198
+ - `getArtifact`
199
+ - `getArtifacts`
189
200
  - `getChat`
190
201
  - `getHistory`
191
202
  - `getSandboxGitBranch`
@@ -198,6 +209,7 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
198
209
  - `getVotes`
199
210
  - `healthCheck`
200
211
  - `listSandboxFiles`
212
+ - `prepareChat`
201
213
  - `readSandboxFile`
202
214
  - `setUserSpendLimit`
203
215
  - `stopChat`
@@ -295,6 +307,7 @@ Every namespace and method reachable from a ready `KeboolaApi` — the `api` hal
295
307
  - `payAsYouGo.getTopUpSetting`
296
308
  - `payAsYouGo.updateStripeCustomer`
297
309
  - `payAsYouGo.updateTopUpSetting`
310
+ - `programmaticProjects.confirm`
298
311
  - `projects.addProjectFeature`
299
312
  - `projects.addProjectTemplateFeature`
300
313
  - `projects.addProjectUser`
package/CHANGELOG.md CHANGED
@@ -1,5 +1,107 @@
1
1
  # @keboola/api-client
2
2
 
3
+ ## 39.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add `management.programmaticProjects` namespace with `confirm({ claimToken? }, signal?)` — redeems an agent project's claim token, making the bearer's account its owner. `claimToken` is optional: Connection also accepts the claim from the `HttpOnly` cookie its confirmation page sets, which is the only copy left after a sign-up or SSO round trip.
8
+
9
+ - Add `businessWorkspaceApi` service client (`@keboola/api-client/businessWorkspaceApi`) for the Business Workspace dashboards backend.
10
+
11
+ - `api.kaiAgent.getArtifacts(chatId)` and `api.kaiAgent.getArtifact(id)`: the two read routes kai-agent now serves for the artifacts it derives at the end of a turn. Both are typed off the regenerated kai-agent schema, and the chat is the authorization — a chat the caller cannot read has no artifacts. There is no write pair, because nothing but the agent creates an artifact.
12
+
13
+ `spec` and `recipe` come back as open maps. The routes document them as passthrough objects, so the generated types carry no shape for either; `ArtifactSpec` / `ArtifactRecipe` in `@keboola/kai-chat/artifacts` are the shapes behind them, and the narrowing belongs in that package — it already depends on this one, and the reverse edge would close a workspace cycle.
14
+
15
+ ### Patch Changes
16
+
17
+ - `readableReason` keeps the message an `ApiError` subclass authored for a reader.
18
+
19
+ It discarded the message of every error matching `isApiError`, but `HtmlResponseError` and `ManagementClientAuthError` overwrite theirs with wording written for exactly this spot — so an expired session surfaced as "Unknown error" rather than saying the session had expired. Only the base class builds its message from the response status, so only the base class is read as carrying a status line.
20
+
21
+ ## 38.0.0
22
+
23
+ ### Minor Changes
24
+
25
+ - Expose the optional organization creation timestamp in Storage token verification responses.
26
+ The ISO-8601 `organization.created` field is nullable when the creation time is unavailable.
27
+
28
+ ## 37.0.0
29
+
30
+ ### Major Changes
31
+
32
+ - **Breaking:** `ApiError.message` is a status line rather than the HTTP reason phrase, and every error class now reports its own `name`.
33
+
34
+ `message` was `response.statusText`, which HTTP/2 leaves empty — so over every production response an error reached a reporter as `Error:` with no message and no status. It is now `"404 Not Found"`, or `"404"` where no reason phrase was sent.
35
+
36
+ **What breaks.** A status line is never empty, so the two ways consumers detected "no reason was reported" both stop working:
37
+
38
+ ```ts
39
+ // Before: `message` was '' over HTTP/2, so the written wording always won.
40
+ // After: `message` is '502', so the written wording never wins.
41
+ toast.error(err.message || "Saving the token failed.");
42
+ if (err.message === "") return "No reason was reported.";
43
+ ```
44
+
45
+ Use `readableReason(err)`, new in this release. It returns the service's own sentence from the parsed response body, and `undefined` when the failure carries none — the cue to render your own wording. It never returns the status line:
46
+
47
+ ```ts
48
+ toast.error(readableReason(err) ?? "Saving the token failed.");
49
+ ```
50
+
51
+ `HtmlResponseError` and `ManagementClientAuthError` previously inherited `ApiError`'s constructor without setting `name`, so they reported as plain `Error`; each now names itself. Anything grouping errors by `name` — Sentry's exception type included — will see the new values.
52
+
53
+ `deleteModel` counts a child object a concurrent cascade already deleted (`404`) as deleted rather than as a failure that keeps the model alive. The model's own delete is tolerant of a `404` only once a child has actually been deleted, so deleting a model that never existed still rejects.
54
+
55
+ ### Minor Changes
56
+
57
+ - `kaiAgentClient` gains `prepareChat(chatId, signal?)`, for the engine's new `POST /api/chat/{id}/prepare`.
58
+
59
+ It asks the engine to build a chat's sandbox — container, workspace, agent process and its MCP connects — before a turn needs one, on a signal from the host's UI that a message is coming. The work continues after the response resolves, and a deployment whose host does not implement the pre-warm port answers `404`, which callers should read as "not supported here" rather than as an error.
60
+
61
+ ### Patch Changes
62
+
63
+ - Refresh an expired management session token when token verification responds with HTTP 401.
64
+
65
+ - `kaiAgentClient.prepareChat` folds a `404` into `{ started: false }` rather than throwing.
66
+
67
+ 404 is the documented "this deployment does not pre-warm", so every caller had to remember to catch it to tell that apart from a real failure.
68
+
69
+ ## 36.0.1
70
+
71
+ ### Patch Changes
72
+
73
+ - `approveToolCall` accepts an optional `dismissed` flag on the approval body. The Kai plan card sends
74
+ it when the user dismisses a plan, so the backend can tell that apart from Request Changes without
75
+ inspecting the user's own text. Additive and optional — existing callers are unaffected.
76
+
77
+ ## 36.0.0
78
+
79
+ ### Major Changes
80
+
81
+ - **Breaking:** the `apps` (`/v2` App Deployments) types are regenerated from the current canary spec, which renamed and dropped fields across `App` and `Deployment`.
82
+
83
+ `App`:
84
+ - `production.desiredId` / `actualId` → `production.desiredDeploymentId` / `actualDeploymentId`; the `desiredNumber` / `actualNumber` twins are gone.
85
+ - `state` values are camelCase and the set changed: `notDeployed | starting | running | suspended | disabled`. `SLEEPING` and `SUSPENDED` collapse into `suspended` (stopped, wakes on the next request); the new `disabled` is stopped by a failure and will not auto-wake.
86
+ - `configVersion`, `mode` and `undeployedChanges` are gone — an app no longer reports whether its config has moved past what is deployed.
87
+
88
+ `Deployment`:
89
+ - `number` and `configId` are gone; `size` → `runtimeSize`. Ids are UUIDv7, not the Kubernetes CR name.
90
+ - `buildState` is `pending | building | ready | failed` (`PREBUILT` → `ready`) and `runState` is camelCase.
91
+
92
+ Client surface:
93
+ - `unpublishApp`, `suspendApp`, `resumeApp` and `promoteDeployment` resolve with the `App` instead of `App | null` — the service answers a no-op with the app unchanged rather than `204`.
94
+ - `resetAppPassword` resolves with `{ password }` rather than the app.
95
+ - `getDeployments` takes a query (`archived`, `offset`, `limit`) between the app id and the signal.
96
+ - `createDeployment` takes `configVersion` to pin an older config version, and `createApp` requires `branchId` and `useManagedGitRepo`.
97
+ - `PATCH /apps/{appId}` is gone from the spec; it was never exposed.
98
+
99
+ `appFixtures` loses `undeployedChanges` and `sleeping`, and gains `disabled`.
100
+
101
+ ### Minor Changes
102
+
103
+ - `createProjectInvitation` accepts an optional `landingApp`, naming the ui-app the invitation leads into instead of the Keboola project. Absent means the ordinary invitation email.
104
+
3
105
  ## 35.0.0
4
106
 
5
107
  ### Major Changes
package/README.md CHANGED
@@ -176,6 +176,7 @@ src/
176
176
  oauth/ # OAuth credentials
177
177
  chat/ # Kai Assistant chat
178
178
  kaiAgent/ # Kai Agent (agentic assistant)
179
+ businessWorkspaceApi/ # Business Workspace dashboards
179
180
  ai/ # AI describe/explain/suggest
180
181
  queue/ # Job Queue
181
182
  queryService/ # SQL query service
@@ -211,23 +212,24 @@ src/
211
212
  On the `api` object returned by `createKeboola()` / `createLegacyKeboola()` — once the session reaches `ready` — the following clients are available.
212
213
  Clients backed by OpenAPI specs are marked with (OpenAPI); the rest use the generic fetch client.
213
214
 
214
- | Accessor | Service | Key methods |
215
- | ------------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
216
- | `api.storage` | Storage API | `buckets.*`, `tables.*`, `files.*`, `branches.*`, `workspaces.*`, `mergeRequests.*`, `jobs.*`, `components.*`, `configurations.*`, `configurationRows.*`, `configurationWorkspaces.*`, `tokens.*`, `getStackInfo()` |
217
- | `api.management` | Management API | `projects.*`, `features.*`, `users.*` |
218
- | `api.vault` | Vault (OpenAPI) | `getVariables()`, `createVariable()`, `deleteVariable()`, `getVariablesByBranchId()`, `getProjectWideVariables()` |
219
- | `api.oauth` | OAuth | `getCredentials()`, `getCredential()`, `createCredential()`, `deleteCredential()` |
220
- | `api.dataScience` | Data Science (OpenAPI) | `getApps()`, `getApp()`, `createApp()`, `patchApp()`, `deleteApp()`, `getAppRuns()`, `getAppRun()`, `getAppLogsTail()`, `getAppLogsDownload()`, `getRuntimes()`, `getSandbox()` |
221
- | `api.editor` | SQL Editor (OpenAPI) | `createSession()`, `getSession()`, `getSessions()`, `getSessionSchema()`, `createQueryJob()`, `tablePreview()`, `tableDefinition()`, `load()`, `unload()` |
222
- | `api.encryption` | Encryption | `encrypt()`, `encryptSecrets()` |
223
- | `api.chat` | Kai Assistant (OpenAPI) | `getHistory()`, `getChat()`, `createChat()`, `deleteChat()`, `getVotes()`, `submitVote()`, `getUsage()`, `getSuggestions()`, `getAgentSettings()`, `getToolsList()` |
224
- | `api.kaiAgent` | Kai Agent (OpenAPI) | `getHistory()`, `getChat()`, `createChat()`, `deleteChat()`, `approveToolCall()`, `submitToolOutput()`, `getSuggestions()`, `getAgentSettings()` |
225
- | `api.ai` | AI Service (OpenAPI) | `describeConfiguration()`, `describeConfigurationVersion()`, `describeConfigurationMerge()`, `explainError()`, `suggestComponent()`, `feedback()` |
226
- | `api.queue` | Job Queue (OpenAPI) | `getJob()`, `searchJobs()` |
227
- | `api.queryService` | Query Service (OpenAPI) | `createQueryJob()`, `cancelQueryJob()`, `getQueryJob()`, `getQueryResults()`, `getQueryHistory()`, `exportResults()` |
228
- | `api.syncActions` | Sync Actions (OpenAPI) | `enrollMFA()`, `gitRepository.*` |
229
- | `api.telemetry` | Telemetry | `provisioning.*` |
230
- | `api.import` | Import (OpenAPI) | `uploadFile()`, `writeTable()` |
215
+ | Accessor | Service | Key methods |
216
+ | -------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
217
+ | `api.storage` | Storage API | `buckets.*`, `tables.*`, `files.*`, `branches.*`, `workspaces.*`, `mergeRequests.*`, `jobs.*`, `components.*`, `configurations.*`, `configurationRows.*`, `configurationWorkspaces.*`, `tokens.*`, `getStackInfo()` |
218
+ | `api.management` | Management API | `projects.*`, `features.*`, `users.*` |
219
+ | `api.vault` | Vault (OpenAPI) | `getVariables()`, `createVariable()`, `deleteVariable()`, `getVariablesByBranchId()`, `getProjectWideVariables()` |
220
+ | `api.oauth` | OAuth | `getCredentials()`, `getCredential()`, `createCredential()`, `deleteCredential()` |
221
+ | `api.dataScience` | Data Science (OpenAPI) | `getApps()`, `getApp()`, `createApp()`, `patchApp()`, `deleteApp()`, `getAppRuns()`, `getAppRun()`, `getAppLogsTail()`, `getAppLogsDownload()`, `getRuntimes()`, `getSandbox()` |
222
+ | `api.editor` | SQL Editor (OpenAPI) | `createSession()`, `getSession()`, `getSessions()`, `getSessionSchema()`, `createQueryJob()`, `tablePreview()`, `tableDefinition()`, `load()`, `unload()` |
223
+ | `api.encryption` | Encryption | `encrypt()`, `encryptSecrets()` |
224
+ | `api.chat` | Kai Assistant (OpenAPI) | `getHistory()`, `getChat()`, `createChat()`, `deleteChat()`, `getVotes()`, `submitVote()`, `getUsage()`, `getSuggestions()`, `getAgentSettings()`, `getToolsList()` |
225
+ | `api.kaiAgent` | Kai Agent (OpenAPI) | `getHistory()`, `getChat()`, `createChat()`, `deleteChat()`, `approveToolCall()`, `submitToolOutput()`, `getSuggestions()`, `getAgentSettings()` |
226
+ | `api.businessWorkspaceApi` | Business Workspace (OpenAPI) | `healthCheck()`, `getDashboards()`, `getDashboard()`, `createDashboard()`, `updateDashboard()`, `deleteDashboard()` |
227
+ | `api.ai` | AI Service (OpenAPI) | `describeConfiguration()`, `describeConfigurationVersion()`, `describeConfigurationMerge()`, `explainError()`, `suggestComponent()`, `feedback()` |
228
+ | `api.queue` | Job Queue (OpenAPI) | `getJob()`, `searchJobs()` |
229
+ | `api.queryService` | Query Service (OpenAPI) | `createQueryJob()`, `cancelQueryJob()`, `getQueryJob()`, `getQueryResults()`, `getQueryHistory()`, `exportResults()` |
230
+ | `api.syncActions` | Sync Actions (OpenAPI) | `enrollMFA()`, `gitRepository.*` |
231
+ | `api.telemetry` | Telemetry | `provisioning.*` |
232
+ | `api.import` | Import (OpenAPI) | `uploadFile()`, `writeTable()` |
231
233
 
232
234
  Additional accessors on the ready client:
233
235
 
@@ -1,10 +1,11 @@
1
- import { g as ApiError } from "./createFetchClient-U-ZrwPl2.js";
1
+ import { g as ApiError } from "./createFetchClient-C-cadpBx.js";
2
2
  //#region src/errors/ManagementClientAuthError.ts
3
3
  var ManagementClientAuthError = class extends ApiError {
4
4
  title;
5
5
  message;
6
6
  constructor(title, message, res) {
7
7
  super(res);
8
+ this.name = "ManagementClientAuthError";
8
9
  this.title = title;
9
10
  this.message = message;
10
11
  }
@@ -12,4 +13,4 @@ var ManagementClientAuthError = class extends ApiError {
12
13
  //#endregion
13
14
  export { ManagementClientAuthError as t };
14
15
 
15
- //# sourceMappingURL=ManagementClientAuthError-ey-f03vy.js.map
16
+ //# sourceMappingURL=ManagementClientAuthError-Cr9IOsnJ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ManagementClientAuthError-ey-f03vy.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-Cr9IOsnJ.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.name = 'ManagementClientAuthError';\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,OAAO;EACZ,KAAK,QAAQ;EACb,KAAK,UAAU;CACjB;AACF"}
@@ -1,10 +1,11 @@
1
- const require_createFetchClient = require("./createFetchClient-DgMiqTJ8.cjs");
1
+ const require_createFetchClient = require("./createFetchClient-BlgPbjFj.cjs");
2
2
  //#region src/errors/ManagementClientAuthError.ts
3
3
  var ManagementClientAuthError = class extends require_createFetchClient.ApiError {
4
4
  title;
5
5
  message;
6
6
  constructor(title, message, res) {
7
7
  super(res);
8
+ this.name = "ManagementClientAuthError";
8
9
  this.title = title;
9
10
  this.message = message;
10
11
  }
@@ -17,4 +18,4 @@ Object.defineProperty(exports, "ManagementClientAuthError", {
17
18
  }
18
19
  });
19
20
 
20
- //# sourceMappingURL=ManagementClientAuthError-DD4u0EU7.cjs.map
21
+ //# sourceMappingURL=ManagementClientAuthError-FcfMJNhr.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ManagementClientAuthError-DD4u0EU7.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-FcfMJNhr.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.name = 'ManagementClientAuthError';\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,OAAO;EACZ,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-DhUU3M1W.cjs");
3
- const require_auth = require("../auth-JQ33o3nU.cjs");
2
+ const require_createOpenapiFetchClient = require("../createOpenapiFetchClient-C3UmDXpe.cjs");
3
+ const require_auth = require("../auth-DLWnl18b.cjs");
4
4
  //#region src/clients/ai/aiClient.ts
5
5
  const createAiClient = ({ baseUrl, middlewares, auth }) => {
6
6
  const client = require_createOpenapiFetchClient.createOpenapiFetchClient({
package/dist/ai/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { t as createOpenapiFetchClient } from "../createOpenapiFetchClient-BVSc9ibR.js";
2
- import { t as createAuthHeaders } from "../auth-aItmDu45.js";
1
+ import { t as createOpenapiFetchClient } from "../createOpenapiFetchClient-COaPeeQ0.js";
2
+ import { t as createAuthHeaders } from "../auth-BjmkFOgd.js";
3
3
  //#region src/clients/ai/aiClient.ts
4
4
  const createAiClient = ({ baseUrl, middlewares, auth }) => {
5
5
  const client = createOpenapiFetchClient({
@@ -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-DgMiqTJ8.cjs");
3
+ const require_createFetchClient = require("./createFetchClient-BlgPbjFj.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-BjfUoWzs.cjs.map
153
+ //# sourceMappingURL=appLogs-C_zP0lpv.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"appLogs-BjfUoWzs.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-C_zP0lpv.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,5 +1,5 @@
1
1
  import { t as isPlainObject } from "./isPlainObject-LYW-03uB.js";
2
- import { f as parseContentDispositionHeader, m as HttpStatus, r as isApiError, s as HttpHeader } from "./createFetchClient-U-ZrwPl2.js";
2
+ import { f as parseContentDispositionHeader, m as HttpStatus, r as isApiError, s as HttpHeader } from "./createFetchClient-C-cadpBx.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-xsVkTriU.js.map
132
+ //# sourceMappingURL=appLogs-Cl7Q_MR9.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"appLogs-xsVkTriU.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-Cl7Q_MR9.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,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_createOpenapiFetchClient = require("../createOpenapiFetchClient-DhUU3M1W.cjs");
3
- const require_auth = require("../auth-JQ33o3nU.cjs");
4
- const require_appLogs = require("../appLogs-BjfUoWzs.cjs");
2
+ const require_createOpenapiFetchClient = require("../createOpenapiFetchClient-C3UmDXpe.cjs");
3
+ const require_auth = require("../auth-DLWnl18b.cjs");
4
+ const require_appLogs = require("../appLogs-C_zP0lpv.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
@@ -10,10 +10,9 @@ const require_appLogs = require("../appLogs-BjfUoWzs.cjs");
10
10
  * `baseUrl` must already point past the `/v2` prefix (`https://<data-science-host>/v2`); the
11
11
  * registry composes it — see `createServiceClients`.
12
12
  *
13
- * Two documented endpoints are deliberately absent: `PATCH /apps/{appId}` has no patchable field
14
- * yet (`name`/`description` are create-only, so `{}` is the only accepted body), and
15
- * `POST /apps/{appId}/activity` is apps-proxy's heartbeat, authenticated by a Manage API token with
16
- * the `apps:proxy` scope that this storage-token client cannot supply.
13
+ * One documented endpoint is deliberately absent: `POST /apps/{appId}/activity` is apps-proxy's
14
+ * heartbeat, authenticated by a Manage API token with the `apps:proxy` scope that this
15
+ * storage-token client cannot supply.
17
16
  */
18
17
  const createAppsClient = ({ baseUrl, middlewares, auth }) => {
19
18
  const client = require_createOpenapiFetchClient.createOpenapiFetchClient({
@@ -48,8 +47,8 @@ const createAppsClient = ({ baseUrl, middlewares, auth }) => {
48
47
  await client.delete("/apps/{appId}", { path: { appId } }, { signal });
49
48
  };
50
49
  /**
51
- * Drops production routing — the app's URL 404s afterwards. `null` when there was nothing to
52
- * unpublish (already unpublished, or never deployed via `/v2`): the service answers `204`.
50
+ * Drops production routing — the app's URL 404s afterwards. A no-op (already unpublished, or
51
+ * never deployed) returns the app unchanged rather than failing.
53
52
  */
54
53
  const unpublishApp = async (appId, signal) => {
55
54
  const { data } = await client.post("/apps/{appId}/unpublish", { path: { appId } }, { signal });
@@ -57,15 +56,15 @@ const createAppsClient = ({ baseUrl, middlewares, auth }) => {
57
56
  };
58
57
  /**
59
58
  * Sleeps the app now instead of waiting for the idle timer, and disarms wake-on-request: a
60
- * visitor gets a `503` until an explicit {@link resumeApp}. `null` when already suspended (`204`).
59
+ * visitor gets a `503` until an explicit {@link resumeApp}. A no-op on an already suspended app.
61
60
  */
62
61
  const suspendApp = async (appId, signal) => {
63
62
  const { data } = await client.post("/apps/{appId}/suspend", { path: { appId } }, { signal });
64
63
  return data;
65
64
  };
66
65
  /**
67
- * Wakes the app now and re-arms wake-on-request. `null` when it was already running (`204`).
68
- * The returned app reports `STARTING` — the operator has not confirmed it serving yet.
66
+ * Wakes the app now and re-arms wake-on-request. A no-op on an already running app.
67
+ * The returned app reports `starting` — the operator has not confirmed it serving yet.
69
68
  */
70
69
  const resumeApp = async (appId, signal) => {
71
70
  const { data } = await client.post("/apps/{appId}/resume", { path: { appId } }, { signal });
@@ -78,7 +77,7 @@ const createAppsClient = ({ baseUrl, middlewares, auth }) => {
78
77
  };
79
78
  /** Mints a fresh password, replacing any existing one. Read it back with {@link getAppPassword}. */
80
79
  const resetAppPassword = async (appId, signal) => {
81
- const { data } = await client.post("/apps/{appId}/reset-password", { path: { appId } }, { signal });
80
+ const { data } = await client.post("/apps/{appId}/password/reset", { path: { appId } }, { signal });
82
81
  return data;
83
82
  };
84
83
  /**
@@ -101,8 +100,8 @@ const createAppsClient = ({ baseUrl, middlewares, auth }) => {
101
100
  };
102
101
  /**
103
102
  * Deploys the app's current config version as a new immutable deployment, promoting it unless
104
- * `body.promote` is `false` (a staged release never runs until promoted). The id and `number` come
105
- * back synchronously; readiness does not.
103
+ * `body.promote` is `false` (a staged release never runs until promoted). Pin an older config
104
+ * version with `body.configVersion`. The deployment comes back synchronously; readiness does not.
106
105
  */
107
106
  const createDeployment = async (appId, body, options = {}) => {
108
107
  const { data } = await client.post("/apps/{appId}/deployments", {
@@ -111,9 +110,17 @@ const createAppsClient = ({ baseUrl, middlewares, auth }) => {
111
110
  }, writeOptions(options));
112
111
  return data;
113
112
  };
114
- /** Full history, retired (`archived: true`) deployments included — rows outlive their workloads. */
115
- const getDeployments = async (appId, signal) => {
116
- const { data } = await client.get("/apps/{appId}/deployments", { path: { appId } }, { signal });
113
+ /**
114
+ * Deployment history, newest page first.
115
+ *
116
+ * - `query.archived` filters on whether the deployment was deleted; omitting it returns both.
117
+ * - A deleted deployment keeps its row — history outlives the workload.
118
+ */
119
+ const getDeployments = async (appId, query = {}, signal) => {
120
+ const { data } = await client.get("/apps/{appId}/deployments", {
121
+ path: { appId },
122
+ query
123
+ }, { signal });
117
124
  return data;
118
125
  };
119
126
  const getDeployment = async (appId, deploymentId, signal) => {
@@ -124,8 +131,8 @@ const createAppsClient = ({ baseUrl, middlewares, auth }) => {
124
131
  return data;
125
132
  };
126
133
  /**
127
- * Retires the deployment: the workload and its rendered-config secret go, the row stays in
128
- * history as `archived`. Rejected with a `409` while the app's `production` still names it.
134
+ * Deletes the deployment: its running resources and credentials go, the row stays in history as
135
+ * `archived`. Rejected with a `409` while the app's `production` still names it.
129
136
  */
130
137
  const deleteDeployment = async (appId, deploymentId, signal) => {
131
138
  await client.delete("/apps/{appId}/deployments/{deploymentId}", { path: {
@@ -135,8 +142,8 @@ const createAppsClient = ({ baseUrl, middlewares, auth }) => {
135
142
  };
136
143
  /**
137
144
  * Makes this deployment production — the same call rolls back, applied to an older one. The route
138
- * switches only once the target serves, so the returned app's `production.desiredId` and
139
- * `.actualId` differ until it converges. `null` when it was already production (`204`).
145
+ * switches only once the target serves, so the returned app's `production.desiredDeploymentId`
146
+ * and `.actualDeploymentId` differ until it converges.
140
147
  */
141
148
  const promoteDeployment = async (appId, deploymentId, signal) => {
142
149
  const { data } = await client.post("/apps/{appId}/deployments/{deploymentId}/promote", { path: {