@rudderhq/server 0.3.6-canary.9 → 0.4.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 (325) hide show
  1. package/dist/bootstrap/register-api-routes.d.ts.map +1 -1
  2. package/dist/bootstrap/register-api-routes.js +2 -0
  3. package/dist/bootstrap/register-api-routes.js.map +1 -1
  4. package/dist/bundled-plugins/plugin-linear/dist/worker.js +35 -2
  5. package/dist/bundled-plugins/plugin-linear/dist/worker.js.map +2 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +103 -26
  8. package/dist/index.js.map +1 -1
  9. package/dist/routes/activity.d.ts +1 -1
  10. package/dist/routes/activity.d.ts.map +1 -1
  11. package/dist/routes/activity.js +21 -5
  12. package/dist/routes/activity.js.map +1 -1
  13. package/dist/routes/agents.d.ts.map +1 -1
  14. package/dist/routes/agents.js +254 -4
  15. package/dist/routes/agents.js.map +1 -1
  16. package/dist/routes/agents.management-routes.d.ts.map +1 -1
  17. package/dist/routes/agents.management-routes.js +132 -40
  18. package/dist/routes/agents.management-routes.js.map +1 -1
  19. package/dist/routes/automations.d.ts +8 -0
  20. package/dist/routes/automations.d.ts.map +1 -1
  21. package/dist/routes/automations.js.map +1 -1
  22. package/dist/routes/chats.d.ts.map +1 -1
  23. package/dist/routes/chats.js +228 -115
  24. package/dist/routes/chats.js.map +1 -1
  25. package/dist/routes/chats.stream-routes.d.ts.map +1 -1
  26. package/dist/routes/chats.stream-routes.js +94 -5
  27. package/dist/routes/chats.stream-routes.js.map +1 -1
  28. package/dist/routes/issues.comments-attachments.d.ts.map +1 -1
  29. package/dist/routes/issues.comments-attachments.js +72 -83
  30. package/dist/routes/issues.comments-attachments.js.map +1 -1
  31. package/dist/routes/issues.d.ts +8 -0
  32. package/dist/routes/issues.d.ts.map +1 -1
  33. package/dist/routes/issues.js +0 -4
  34. package/dist/routes/issues.js.map +1 -1
  35. package/dist/routes/issues.mutations.d.ts.map +1 -1
  36. package/dist/routes/issues.mutations.js +2 -26
  37. package/dist/routes/issues.mutations.js.map +1 -1
  38. package/dist/routes/messenger.d.ts.map +1 -1
  39. package/dist/routes/messenger.js +33 -1
  40. package/dist/routes/messenger.js.map +1 -1
  41. package/dist/routes/orgs.d.ts.map +1 -1
  42. package/dist/routes/orgs.js +16 -0
  43. package/dist/routes/orgs.js.map +1 -1
  44. package/dist/routes/plugin-ui-static.d.ts +4 -4
  45. package/dist/routes/plugin-ui-static.js +5 -5
  46. package/dist/routes/plugin-ui-static.js.map +1 -1
  47. package/dist/routes/plugins.d.ts +4 -4
  48. package/dist/routes/plugins.js +10 -10
  49. package/dist/routes/plugins.operations-routes.d.ts +1 -1
  50. package/dist/routes/plugins.operations-routes.js +2 -2
  51. package/dist/routes/plugins.operations-routes.js.map +1 -1
  52. package/dist/routes/run-intelligence.js +5 -5
  53. package/dist/routes/run-intelligence.js.map +1 -1
  54. package/dist/routes/website-metadata.d.ts +8 -0
  55. package/dist/routes/website-metadata.d.ts.map +1 -0
  56. package/dist/routes/website-metadata.js +67 -0
  57. package/dist/routes/website-metadata.js.map +1 -0
  58. package/dist/services/activity.d.ts.map +1 -1
  59. package/dist/services/activity.js +1 -1
  60. package/dist/services/activity.js.map +1 -1
  61. package/dist/services/agent-instructions.d.ts +1 -0
  62. package/dist/services/agent-instructions.d.ts.map +1 -1
  63. package/dist/services/agent-instructions.js +57 -6
  64. package/dist/services/agent-instructions.js.map +1 -1
  65. package/dist/services/agent-run-context.d.ts +3 -1
  66. package/dist/services/agent-run-context.d.ts.map +1 -1
  67. package/dist/services/agent-run-context.js +7 -0
  68. package/dist/services/agent-run-context.js.map +1 -1
  69. package/dist/services/agent-startup-context.d.ts +2 -1
  70. package/dist/services/agent-startup-context.d.ts.map +1 -1
  71. package/dist/services/agent-startup-context.js +6 -26
  72. package/dist/services/agent-startup-context.js.map +1 -1
  73. package/dist/services/agents.d.ts +9 -1
  74. package/dist/services/agents.d.ts.map +1 -1
  75. package/dist/services/agents.js.map +1 -1
  76. package/dist/services/approvals.d.ts +8 -0
  77. package/dist/services/approvals.d.ts.map +1 -1
  78. package/dist/services/approvals.js.map +1 -1
  79. package/dist/services/automation-chat-output.d.ts +1 -1
  80. package/dist/services/automations.d.ts +4 -4
  81. package/dist/services/automations.d.ts.map +1 -1
  82. package/dist/services/automations.js +12 -0
  83. package/dist/services/automations.js.map +1 -1
  84. package/dist/services/budgets.d.ts +8 -0
  85. package/dist/services/budgets.d.ts.map +1 -1
  86. package/dist/services/budgets.js.map +1 -1
  87. package/dist/services/calendar.d.ts +2 -2
  88. package/dist/services/calendar.js +3 -3
  89. package/dist/services/calendar.js.map +1 -1
  90. package/dist/services/chat-agent-runs.d.ts +2 -0
  91. package/dist/services/chat-agent-runs.d.ts.map +1 -1
  92. package/dist/services/chat-agent-runs.js +6 -0
  93. package/dist/services/chat-agent-runs.js.map +1 -1
  94. package/dist/services/chat-assistant.d.ts.map +1 -1
  95. package/dist/services/chat-assistant.helpers.d.ts +1 -0
  96. package/dist/services/chat-assistant.helpers.d.ts.map +1 -1
  97. package/dist/services/chat-assistant.helpers.js +7 -10
  98. package/dist/services/chat-assistant.helpers.js.map +1 -1
  99. package/dist/services/chat-assistant.js +23 -6
  100. package/dist/services/chat-assistant.js.map +1 -1
  101. package/dist/services/chat-generation-locks.d.ts +6 -1
  102. package/dist/services/chat-generation-locks.d.ts.map +1 -1
  103. package/dist/services/chat-generation-locks.js +20 -2
  104. package/dist/services/chat-generation-locks.js.map +1 -1
  105. package/dist/services/chat-title-generation.d.ts +36 -0
  106. package/dist/services/chat-title-generation.d.ts.map +1 -0
  107. package/dist/services/chat-title-generation.js +107 -0
  108. package/dist/services/chat-title-generation.js.map +1 -0
  109. package/dist/services/chats.d.ts +471 -25
  110. package/dist/services/chats.d.ts.map +1 -1
  111. package/dist/services/chats.helpers.d.ts +2 -2
  112. package/dist/services/chats.js +651 -35
  113. package/dist/services/chats.js.map +1 -1
  114. package/dist/services/costs.d.ts +1 -1
  115. package/dist/services/finance.d.ts +2 -2
  116. package/dist/services/finance.js +1 -1
  117. package/dist/services/finance.js.map +1 -1
  118. package/dist/services/goals.d.ts +8 -0
  119. package/dist/services/goals.d.ts.map +1 -1
  120. package/dist/services/goals.js.map +1 -1
  121. package/dist/services/heartbeat-run-reference.d.ts +1 -0
  122. package/dist/services/heartbeat-run-reference.d.ts.map +1 -1
  123. package/dist/services/heartbeat-run-reference.js +3 -2
  124. package/dist/services/heartbeat-run-reference.js.map +1 -1
  125. package/dist/services/integrations/agent-integrations.d.ts +19 -0
  126. package/dist/services/integrations/agent-integrations.d.ts.map +1 -1
  127. package/dist/services/integrations/agent-integrations.js +30 -0
  128. package/dist/services/integrations/agent-integrations.js.map +1 -1
  129. package/dist/services/integrations/feishu/app-registration.d.ts +74 -0
  130. package/dist/services/integrations/feishu/app-registration.d.ts.map +1 -0
  131. package/dist/services/integrations/feishu/app-registration.js +226 -0
  132. package/dist/services/integrations/feishu/app-registration.js.map +1 -0
  133. package/dist/services/integrations/feishu/inbound-dispatcher-db.d.ts +4 -0
  134. package/dist/services/integrations/feishu/inbound-dispatcher-db.d.ts.map +1 -1
  135. package/dist/services/integrations/feishu/inbound-dispatcher-db.js +35 -5
  136. package/dist/services/integrations/feishu/inbound-dispatcher-db.js.map +1 -1
  137. package/dist/services/integrations/feishu/inbound-dispatcher.d.ts +2 -0
  138. package/dist/services/integrations/feishu/inbound-dispatcher.d.ts.map +1 -1
  139. package/dist/services/integrations/feishu/inbound-dispatcher.js.map +1 -1
  140. package/dist/services/integrations/feishu/runtime-registry.d.ts +20 -0
  141. package/dist/services/integrations/feishu/runtime-registry.d.ts.map +1 -0
  142. package/dist/services/integrations/feishu/runtime-registry.js +41 -0
  143. package/dist/services/integrations/feishu/runtime-registry.js.map +1 -0
  144. package/dist/services/integrations/feishu/runtime.d.ts +21 -23
  145. package/dist/services/integrations/feishu/runtime.d.ts.map +1 -1
  146. package/dist/services/integrations/feishu/runtime.js +135 -45
  147. package/dist/services/integrations/feishu/runtime.js.map +1 -1
  148. package/dist/services/integrations/feishu/user-bindings.d.ts +22 -0
  149. package/dist/services/integrations/feishu/user-bindings.d.ts.map +1 -0
  150. package/dist/services/integrations/feishu/user-bindings.js +57 -0
  151. package/dist/services/integrations/feishu/user-bindings.js.map +1 -0
  152. package/dist/services/issue-approvals.d.ts +2 -2
  153. package/dist/services/issue-review-wakeup.js +1 -1
  154. package/dist/services/issue-review-wakeup.js.map +1 -1
  155. package/dist/services/issues.comments-attachments.d.ts +3 -3
  156. package/dist/services/issues.d.ts +14 -6
  157. package/dist/services/issues.d.ts.map +1 -1
  158. package/dist/services/issues.helpers.d.ts +9 -1
  159. package/dist/services/issues.helpers.d.ts.map +1 -1
  160. package/dist/services/issues.helpers.js +8 -0
  161. package/dist/services/issues.helpers.js.map +1 -1
  162. package/dist/services/issues.js +1 -1
  163. package/dist/services/issues.js.map +1 -1
  164. package/dist/services/knowledge-portability/organization-skills.catalog.d.ts +1 -1
  165. package/dist/services/library-entries.d.ts +8 -0
  166. package/dist/services/library-entries.d.ts.map +1 -1
  167. package/dist/services/library-entries.js +8 -0
  168. package/dist/services/library-entries.js.map +1 -1
  169. package/dist/services/messenger.d.ts +19 -4
  170. package/dist/services/messenger.d.ts.map +1 -1
  171. package/dist/services/messenger.js +136 -18
  172. package/dist/services/messenger.js.map +1 -1
  173. package/dist/services/plugin-capability-validator.d.ts +1 -1
  174. package/dist/services/plugin-capability-validator.js +2 -2
  175. package/dist/services/plugin-dev-watcher.js +1 -1
  176. package/dist/services/plugin-event-bus.d.ts +3 -3
  177. package/dist/services/plugin-event-bus.js +3 -3
  178. package/dist/services/plugin-job-coordinator.d.ts +1 -1
  179. package/dist/services/plugin-job-coordinator.js +1 -1
  180. package/dist/services/plugin-job-scheduler.d.ts +1 -1
  181. package/dist/services/plugin-job-scheduler.js +1 -1
  182. package/dist/services/plugin-job-store.d.ts +2 -2
  183. package/dist/services/plugin-job-store.js +2 -2
  184. package/dist/services/plugin-lifecycle.d.ts +4 -4
  185. package/dist/services/plugin-lifecycle.js +3 -3
  186. package/dist/services/plugin-loader.core.d.ts +4 -4
  187. package/dist/services/plugin-loader.core.js +2 -2
  188. package/dist/services/plugin-loader.core.js.map +1 -1
  189. package/dist/services/plugin-loader.d.ts +3 -3
  190. package/dist/services/plugin-loader.helpers.d.ts +26 -25
  191. package/dist/services/plugin-loader.helpers.d.ts.map +1 -1
  192. package/dist/services/plugin-loader.helpers.js +10 -9
  193. package/dist/services/plugin-loader.helpers.js.map +1 -1
  194. package/dist/services/plugin-loader.js +3 -3
  195. package/dist/services/plugin-loader.worker-paths.d.ts +3 -3
  196. package/dist/services/plugin-manifest-validator.d.ts +2 -2
  197. package/dist/services/plugin-registry.d.ts +9 -9
  198. package/dist/services/plugin-registry.js +1 -1
  199. package/dist/services/plugin-secrets-handler.d.ts +2 -2
  200. package/dist/services/plugin-secrets-handler.js +2 -2
  201. package/dist/services/plugin-state-store.d.ts +3 -3
  202. package/dist/services/plugin-state-store.js +3 -3
  203. package/dist/services/plugin-stream-bus.d.ts +1 -1
  204. package/dist/services/plugin-stream-bus.js +1 -1
  205. package/dist/services/plugin-tool-dispatcher.d.ts +2 -2
  206. package/dist/services/plugin-tool-dispatcher.js +2 -2
  207. package/dist/services/plugin-tool-registry.d.ts +2 -2
  208. package/dist/services/plugin-tool-registry.js +2 -2
  209. package/dist/services/plugin-worker-manager.d.ts +4 -4
  210. package/dist/services/plugin-worker-manager.d.ts.map +1 -1
  211. package/dist/services/plugin-worker-manager.js +8 -7
  212. package/dist/services/plugin-worker-manager.js.map +1 -1
  213. package/dist/services/run-intelligence.js +3 -3
  214. package/dist/services/run-intelligence.js.map +1 -1
  215. package/dist/services/runtime-kernel/heartbeat.core.d.ts +9 -1
  216. package/dist/services/runtime-kernel/heartbeat.core.d.ts.map +1 -1
  217. package/dist/services/runtime-kernel/heartbeat.core.js +16 -5
  218. package/dist/services/runtime-kernel/heartbeat.core.js.map +1 -1
  219. package/dist/services/runtime-kernel/heartbeat.d.ts +3 -3
  220. package/dist/services/runtime-kernel/heartbeat.execute.d.ts.map +1 -1
  221. package/dist/services/runtime-kernel/heartbeat.execute.js +17 -3
  222. package/dist/services/runtime-kernel/heartbeat.execute.js.map +1 -1
  223. package/dist/services/runtime-kernel/heartbeat.misc.js +1 -1
  224. package/dist/services/runtime-kernel/heartbeat.recovery.d.ts +1 -1
  225. package/dist/services/runtime-kernel/heartbeat.recovery.js +7 -7
  226. package/dist/services/runtime-kernel/heartbeat.recovery.js.map +1 -1
  227. package/dist/services/runtime-kernel/heartbeat.release.js +4 -4
  228. package/dist/services/runtime-kernel/heartbeat.release.js.map +1 -1
  229. package/dist/services/runtime-kernel/heartbeat.wakeup.js +1 -1
  230. package/dist/services/sidebar-badges.d.ts.map +1 -1
  231. package/dist/services/sidebar-badges.js +13 -1
  232. package/dist/services/sidebar-badges.js.map +1 -1
  233. package/dist/services/title-generation.d.ts +13 -0
  234. package/dist/services/title-generation.d.ts.map +1 -0
  235. package/dist/services/title-generation.js +77 -0
  236. package/dist/services/title-generation.js.map +1 -0
  237. package/dist/services/website-metadata.d.ts +17 -0
  238. package/dist/services/website-metadata.d.ts.map +1 -0
  239. package/dist/services/website-metadata.js +293 -0
  240. package/dist/services/website-metadata.js.map +1 -0
  241. package/dist/services/workspace-backups.d.ts +22 -0
  242. package/dist/services/workspace-backups.d.ts.map +1 -1
  243. package/dist/services/workspace-backups.js +161 -5
  244. package/dist/services/workspace-backups.js.map +1 -1
  245. package/dist/services/workspace-runtime.services.d.ts +1 -1
  246. package/package.json +14 -13
  247. package/resources/bundled-skills/rudder/SKILL.md +7 -6
  248. package/resources/bundled-skills/rudder/references/cli-reference.md +3 -3
  249. package/resources/bundled-skills/rudder-create-plugin/SKILL.md +2 -2
  250. package/skills/rudder/SKILL.md +7 -6
  251. package/skills/rudder/references/cli-reference.md +3 -3
  252. package/skills/rudder-create-plugin/SKILL.md +2 -2
  253. package/ui-dist/assets/{_basePickBy-CM0XatHw.js → _basePickBy-CyhMvFCw.js} +1 -1
  254. package/ui-dist/assets/{_baseUniq-CdBBmdoP.js → _baseUniq-k3x-egdv.js} +1 -1
  255. package/ui-dist/assets/{arc-DSTtxyJ9.js → arc-DVwZMGLR.js} +1 -1
  256. package/ui-dist/assets/{architectureDiagram-2XIMDMQ5-BkHMYb5I.js → architectureDiagram-2XIMDMQ5-BvKp7DHW.js} +1 -1
  257. package/ui-dist/assets/{blockDiagram-WCTKOSBZ-EYczZxwW.js → blockDiagram-WCTKOSBZ-CQ0KLoGd.js} +1 -1
  258. package/ui-dist/assets/{c4Diagram-IC4MRINW-Xo9qijMi.js → c4Diagram-IC4MRINW-BY44eeD7.js} +1 -1
  259. package/ui-dist/assets/channel-Cb8ybYSt.js +1 -0
  260. package/ui-dist/assets/{chunk-4BX2VUAB-CKzta1FF.js → chunk-4BX2VUAB-D7D6PuZU.js} +1 -1
  261. package/ui-dist/assets/{chunk-55IACEB6-BxxUB0ww.js → chunk-55IACEB6-CraDwywJ.js} +1 -1
  262. package/ui-dist/assets/{chunk-FMBD7UC4-0F4oxVtY.js → chunk-FMBD7UC4-BGYh4kbq.js} +1 -1
  263. package/ui-dist/assets/{chunk-JSJVCQXG-CVMPMlVD.js → chunk-JSJVCQXG-DndeOLp_.js} +1 -1
  264. package/ui-dist/assets/{chunk-KX2RTZJC-lPrAWT94.js → chunk-KX2RTZJC-Cx0eOadl.js} +1 -1
  265. package/ui-dist/assets/{chunk-NQ4KR5QH-Bufcm7Iv.js → chunk-NQ4KR5QH-PNVbQ_36.js} +1 -1
  266. package/ui-dist/assets/{chunk-QZHKN3VN-CucmdWnl.js → chunk-QZHKN3VN-DKsTZ1-C.js} +1 -1
  267. package/ui-dist/assets/{chunk-WL4C6EOR-Dz0oYQrJ.js → chunk-WL4C6EOR-B4aSDSws.js} +1 -1
  268. package/ui-dist/assets/classDiagram-VBA2DB6C-US2diuPm.js +1 -0
  269. package/ui-dist/assets/classDiagram-v2-RAHNMMFH-US2diuPm.js +1 -0
  270. package/ui-dist/assets/clone-CbFoFrhF.js +1 -0
  271. package/ui-dist/assets/{cose-bilkent-S5V4N54A-DzyX-Er8.js → cose-bilkent-S5V4N54A-DwgS7_iT.js} +1 -1
  272. package/ui-dist/assets/{dagre-KLK3FWXG-BbZzCKuN.js → dagre-KLK3FWXG-CGMeHr1L.js} +1 -1
  273. package/ui-dist/assets/{diagram-E7M64L7V-B5Rb7Bm4.js → diagram-E7M64L7V-1AVTOsRS.js} +1 -1
  274. package/ui-dist/assets/{diagram-IFDJBPK2-Cpu1Xc8G.js → diagram-IFDJBPK2-hfbRtuHq.js} +1 -1
  275. package/ui-dist/assets/{diagram-P4PSJMXO-kLfHqRlk.js → diagram-P4PSJMXO-BypSVEur.js} +1 -1
  276. package/ui-dist/assets/{erDiagram-INFDFZHY-rCnUyQUb.js → erDiagram-INFDFZHY-DWMZC8pq.js} +1 -1
  277. package/ui-dist/assets/{flowDiagram-PKNHOUZH-BhOz8cvV.js → flowDiagram-PKNHOUZH-C4ODl03j.js} +1 -1
  278. package/ui-dist/assets/{ganttDiagram-A5KZAMGK-Csg9g3hz.js → ganttDiagram-A5KZAMGK-K0UbcKpB.js} +1 -1
  279. package/ui-dist/assets/{gitGraphDiagram-K3NZZRJ6-DLPnSlRs.js → gitGraphDiagram-K3NZZRJ6-CEtw8QBQ.js} +1 -1
  280. package/ui-dist/assets/{graph-BrxYh68N.js → graph-D-YEM3eO.js} +1 -1
  281. package/ui-dist/assets/{index-DMkClCka.js → index--e_5aFtV.js} +1 -1
  282. package/ui-dist/assets/{index-G_y-oBne.js → index--wGHASfH.js} +1 -1
  283. package/ui-dist/assets/index-2sHXDbqQ.css +1 -0
  284. package/ui-dist/assets/{index-BQW242nS.js → index-8D4SrlCZ.js} +1 -1
  285. package/ui-dist/assets/{index-DpdsNIGb.js → index-B9FglFcf.js} +1 -1
  286. package/ui-dist/assets/{index-D4FFno9t.js → index-BOLNi_9C.js} +1 -1
  287. package/ui-dist/assets/{index-COBwmF-C.js → index-BVSwDm4x.js} +1 -1
  288. package/ui-dist/assets/{index-BkzdTp2b.js → index-C4vZZ0jB.js} +1 -1
  289. package/ui-dist/assets/{index-Br07RRw1.js → index-CMZ9kRE0.js} +1 -1
  290. package/ui-dist/assets/{index-mOyLwPeE.js → index-CZb2W71E.js} +1 -1
  291. package/ui-dist/assets/{index-DiMeST8g.js → index-Cfp9ooqM.js} +1 -1
  292. package/ui-dist/assets/{index-BeZv_Z0b.js → index-CyWWtF_x.js} +1 -1
  293. package/ui-dist/assets/{index-CsraICzz.js → index-CzQXnPD8.js} +1 -1
  294. package/ui-dist/assets/{index-Bw8MgLaM.js → index-D2uGk78l.js} +446 -446
  295. package/ui-dist/assets/{index-Cb2qts0o.js → index-DVl9xsgP.js} +1 -1
  296. package/ui-dist/assets/{index-D0rP99dj.js → index-T4jxRzoA.js} +1 -1
  297. package/ui-dist/assets/{index-B6_gFYNj.js → index-V0iKRmt7.js} +1 -1
  298. package/ui-dist/assets/{index-Dj72ldIc.js → index-byosaKUg.js} +1 -1
  299. package/ui-dist/assets/{index-D_06pAuN.js → index-nUtypsmU.js} +1 -1
  300. package/ui-dist/assets/{infoDiagram-LFFYTUFH-CRBKgiEf.js → infoDiagram-LFFYTUFH-C6TFdmXf.js} +1 -1
  301. package/ui-dist/assets/{ishikawaDiagram-PHBUUO56-DI3jquVE.js → ishikawaDiagram-PHBUUO56-DyiJqs9l.js} +1 -1
  302. package/ui-dist/assets/{journeyDiagram-4ABVD52K-DDFZ2Q6D.js → journeyDiagram-4ABVD52K-A-q8eZgk.js} +1 -1
  303. package/ui-dist/assets/{kanban-definition-K7BYSVSG-yL5u3cXV.js → kanban-definition-K7BYSVSG-B_1rE7-5.js} +1 -1
  304. package/ui-dist/assets/{layout-DDZaRkp7.js → layout-kMGiiRYg.js} +1 -1
  305. package/ui-dist/assets/{linear-CWngWuQa.js → linear-PdbwVMlL.js} +1 -1
  306. package/ui-dist/assets/{mermaid.core-CQuYoq9K.js → mermaid.core-Cev3K7jk.js} +4 -4
  307. package/ui-dist/assets/{mindmap-definition-YRQLILUH-BwSsHtTO.js → mindmap-definition-YRQLILUH-C8xkWcsS.js} +1 -1
  308. package/ui-dist/assets/{pieDiagram-SKSYHLDU-BasUkvwH.js → pieDiagram-SKSYHLDU-D2I_J-RQ.js} +1 -1
  309. package/ui-dist/assets/{quadrantDiagram-337W2JSQ-D0D2xp36.js → quadrantDiagram-337W2JSQ-B6BBePuG.js} +1 -1
  310. package/ui-dist/assets/{requirementDiagram-Z7DCOOCP-CztN9kDh.js → requirementDiagram-Z7DCOOCP-BUl7tTbs.js} +1 -1
  311. package/ui-dist/assets/{sankeyDiagram-WA2Y5GQK-2xDqN9ox.js → sankeyDiagram-WA2Y5GQK-Dus4b_vo.js} +1 -1
  312. package/ui-dist/assets/{sequenceDiagram-2WXFIKYE-CO3OUPIJ.js → sequenceDiagram-2WXFIKYE-DnwzyMvt.js} +1 -1
  313. package/ui-dist/assets/{stateDiagram-RAJIS63D-DuQ1QZcT.js → stateDiagram-RAJIS63D-CWYWUh48.js} +1 -1
  314. package/ui-dist/assets/stateDiagram-v2-FVOUBMTO-yRuBqnCA.js +1 -0
  315. package/ui-dist/assets/{timeline-definition-YZTLITO2-CnOxbQeb.js → timeline-definition-YZTLITO2-D7vwtWgR.js} +1 -1
  316. package/ui-dist/assets/{treemap-KZPCXAKY-DD77IFOl.js → treemap-KZPCXAKY-CGCh4N8D.js} +1 -1
  317. package/ui-dist/assets/{vennDiagram-LZ73GAT5-DOXTGJn1.js → vennDiagram-LZ73GAT5-Bq1y4idx.js} +1 -1
  318. package/ui-dist/assets/{xychartDiagram-JWTSCODW-DWkrcdri.js → xychartDiagram-JWTSCODW-CMFdYJaJ.js} +1 -1
  319. package/ui-dist/index.html +2 -2
  320. package/ui-dist/assets/channel-BRnz7pSY.js +0 -1
  321. package/ui-dist/assets/classDiagram-VBA2DB6C-Q3YuI9dv.js +0 -1
  322. package/ui-dist/assets/classDiagram-v2-RAHNMMFH-Q3YuI9dv.js +0 -1
  323. package/ui-dist/assets/clone-C1exIyAN.js +0 -1
  324. package/ui-dist/assets/index-Dz8xxyqB.css +0 -1
  325. package/ui-dist/assets/stateDiagram-v2-FVOUBMTO-DQbZqbl9.js +0 -1
@@ -0,0 +1,293 @@
1
+ import { JSDOM } from "jsdom";
2
+ import { lookup } from "node:dns/promises";
3
+ import { isIP } from "node:net";
4
+ const MAX_HTML_BYTES = 256 * 1024;
5
+ const MAX_ICON_BYTES = 512 * 1024;
6
+ const FETCH_TIMEOUT_MS = 5_000;
7
+ const MAX_REDIRECTS = 5;
8
+ const SUCCESS_CACHE_TTL_MS = 30 * 60_000;
9
+ const FAILURE_CACHE_TTL_MS = 5 * 60_000;
10
+ const IMAGE_CONTENT_TYPES = new Set([
11
+ "image/gif",
12
+ "image/jpeg",
13
+ "image/jpg",
14
+ "image/png",
15
+ "image/svg+xml",
16
+ "image/vnd.microsoft.icon",
17
+ "image/webp",
18
+ "image/x-icon",
19
+ ]);
20
+ function isPrivateIpAddress(value) {
21
+ const normalized = value.replace(/^\[|\]$/gu, "").toLowerCase();
22
+ const ipv4Mapped = normalized.match(/^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/u);
23
+ if (ipv4Mapped)
24
+ return isPrivateIpAddress(ipv4Mapped[1]);
25
+ if (normalized === "::1" || normalized.startsWith("fe80:") || normalized.startsWith("fc") || normalized.startsWith("fd"))
26
+ return true;
27
+ const parts = normalized.split(".");
28
+ if (parts.length !== 4)
29
+ return false;
30
+ const octets = parts.map((part) => Number(part));
31
+ if (octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255))
32
+ return false;
33
+ const [a, b] = octets;
34
+ if (a === 10 || a === 127 || a === 0)
35
+ return true;
36
+ if (a === 100 && b >= 64 && b <= 127)
37
+ return true;
38
+ if (a === 169 && b === 254)
39
+ return true;
40
+ if (a === 172 && b >= 16 && b <= 31)
41
+ return true;
42
+ if (a === 192 && b === 0)
43
+ return true;
44
+ if (a === 192 && b === 168)
45
+ return true;
46
+ if (a === 198 && (b === 18 || b === 19))
47
+ return true;
48
+ return false;
49
+ }
50
+ function isPrivateHostname(hostname) {
51
+ const normalized = hostname.replace(/^\[|\]$/gu, "").toLowerCase();
52
+ if (normalized === "localhost" || normalized.endsWith(".localhost"))
53
+ return true;
54
+ if (isIP(normalized))
55
+ return isPrivateIpAddress(normalized);
56
+ return false;
57
+ }
58
+ export function parsePublicHttpUrl(value, options = {}) {
59
+ const parsed = new URL(value);
60
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
61
+ throw new Error("Only http and https URLs can be inspected");
62
+ }
63
+ if (!options.allowPrivateHosts && isPrivateHostname(parsed.hostname)) {
64
+ throw new Error("Private network URLs cannot be inspected");
65
+ }
66
+ parsed.hash = "";
67
+ return parsed;
68
+ }
69
+ async function assertPublicResolvedHost(url, options) {
70
+ if (options.allowPrivateHosts || options.fetchImpl || isIP(url.hostname.replace(/^\[|\]$/gu, "")))
71
+ return;
72
+ const addresses = await lookup(url.hostname, { all: true, verbatim: true });
73
+ if (addresses.some((address) => isPrivateIpAddress(address.address))) {
74
+ throw new Error("Private network URLs cannot be inspected");
75
+ }
76
+ }
77
+ async function fetchWithTimeout(url, options, init) {
78
+ let currentUrl = parsePublicHttpUrl(url.href, options);
79
+ const fetchImpl = options.fetchImpl ?? fetch;
80
+ for (let redirectCount = 0; redirectCount <= MAX_REDIRECTS; redirectCount += 1) {
81
+ await assertPublicResolvedHost(currentUrl, options);
82
+ const controller = new AbortController();
83
+ const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
84
+ try {
85
+ const response = await fetchImpl(currentUrl.href, {
86
+ redirect: "manual",
87
+ ...init,
88
+ signal: controller.signal,
89
+ headers: {
90
+ accept: "text/html,application/xhtml+xml,image/avif,image/webp,image/png,image/svg+xml,image/*,*/*;q=0.8",
91
+ "user-agent": "RudderWebsiteMetadata/1.0",
92
+ ...(init?.headers ?? {}),
93
+ },
94
+ });
95
+ if (response.status < 300 || response.status >= 400)
96
+ return { response, url: currentUrl };
97
+ const location = response.headers.get("location");
98
+ if (!location)
99
+ return { response, url: currentUrl };
100
+ currentUrl = parsePublicHttpUrl(new URL(location, currentUrl).href, options);
101
+ }
102
+ finally {
103
+ clearTimeout(timeout);
104
+ }
105
+ }
106
+ throw new Error("Website metadata redirect limit exceeded");
107
+ }
108
+ function metadataCacheKey(url) {
109
+ return url.href;
110
+ }
111
+ const metadataCache = new Map();
112
+ const metadataInflight = new Map();
113
+ async function readLimitedBuffer(response, maxBytes) {
114
+ const body = response.body;
115
+ if (!body)
116
+ return Buffer.alloc(0);
117
+ const reader = body.getReader();
118
+ const chunks = [];
119
+ let total = 0;
120
+ try {
121
+ while (true) {
122
+ const { value, done } = await reader.read();
123
+ if (done)
124
+ break;
125
+ if (!value)
126
+ continue;
127
+ total += value.byteLength;
128
+ if (total > maxBytes) {
129
+ throw new Error("Response exceeds metadata size limit");
130
+ }
131
+ chunks.push(Buffer.from(value));
132
+ }
133
+ }
134
+ finally {
135
+ reader.releaseLock();
136
+ }
137
+ return Buffer.concat(chunks);
138
+ }
139
+ function contentTypeBase(value) {
140
+ return value?.split(";")[0]?.trim().toLowerCase() ?? "";
141
+ }
142
+ function absolutizeHref(href, baseUrl, options) {
143
+ const trimmed = href?.trim();
144
+ if (!trimmed)
145
+ return null;
146
+ try {
147
+ const parsed = parsePublicHttpUrl(new URL(trimmed, baseUrl).href, options);
148
+ parsed.hash = "";
149
+ return parsed.href;
150
+ }
151
+ catch {
152
+ return null;
153
+ }
154
+ }
155
+ function linkRelTokens(element) {
156
+ return (element.getAttribute("rel") ?? "")
157
+ .split(/\s+/u)
158
+ .map((token) => token.trim().toLowerCase())
159
+ .filter(Boolean);
160
+ }
161
+ function readSiteName(document) {
162
+ const selectors = [
163
+ 'meta[property="og:site_name"]',
164
+ 'meta[name="application-name"]',
165
+ 'meta[name="apple-mobile-web-app-title"]',
166
+ ];
167
+ for (const selector of selectors) {
168
+ const value = document.querySelector(selector)?.getAttribute("content")?.trim();
169
+ if (value)
170
+ return value;
171
+ }
172
+ const title = document.querySelector("title")?.textContent?.trim();
173
+ return title || null;
174
+ }
175
+ function iconPriority(element) {
176
+ const rel = new Set(linkRelTokens(element));
177
+ if (rel.has("icon") && rel.has("shortcut"))
178
+ return 0;
179
+ if (rel.has("icon"))
180
+ return 1;
181
+ if (rel.has("apple-touch-icon"))
182
+ return 2;
183
+ if (rel.has("apple-touch-icon-precomposed"))
184
+ return 3;
185
+ if (rel.has("mask-icon"))
186
+ return 4;
187
+ return 10;
188
+ }
189
+ function findDeclaredIcon(document, baseUrl, options) {
190
+ const candidates = Array.from(document.querySelectorAll("link[rel][href]"))
191
+ .filter((element) => {
192
+ const rel = new Set(linkRelTokens(element));
193
+ return rel.has("icon")
194
+ || rel.has("apple-touch-icon")
195
+ || rel.has("apple-touch-icon-precomposed")
196
+ || rel.has("mask-icon");
197
+ })
198
+ .sort((left, right) => iconPriority(left) - iconPriority(right));
199
+ for (const candidate of candidates) {
200
+ const href = absolutizeHref(candidate.getAttribute("href"), baseUrl, options);
201
+ if (href)
202
+ return href;
203
+ }
204
+ return null;
205
+ }
206
+ async function validateIconUrl(iconHref, options) {
207
+ try {
208
+ const { response, url } = await fetchWithTimeout(parsePublicHttpUrl(iconHref, options), options, { method: "GET" });
209
+ if (!response.ok)
210
+ return null;
211
+ const contentType = contentTypeBase(response.headers.get("content-type"));
212
+ if (!IMAGE_CONTENT_TYPES.has(contentType))
213
+ return null;
214
+ await readLimitedBuffer(response, MAX_ICON_BYTES);
215
+ return url.href;
216
+ }
217
+ catch {
218
+ return null;
219
+ }
220
+ }
221
+ async function findImplicitFavicon(baseUrl, options) {
222
+ const faviconUrl = new URL("/favicon.ico", baseUrl);
223
+ return validateIconUrl(faviconUrl.href, options);
224
+ }
225
+ async function resolveWebsiteMetadataUncached(value, options) {
226
+ const pageUrl = parsePublicHttpUrl(value, options);
227
+ const { response, url: finalPageUrl } = await fetchWithTimeout(pageUrl, options);
228
+ if (!response.ok) {
229
+ return { url: finalPageUrl.href, siteName: null, iconUrl: null };
230
+ }
231
+ const contentType = contentTypeBase(response.headers.get("content-type"));
232
+ if (contentType && contentType !== "text/html" && contentType !== "application/xhtml+xml") {
233
+ return { url: finalPageUrl.href, siteName: null, iconUrl: null };
234
+ }
235
+ const html = (await readLimitedBuffer(response, MAX_HTML_BYTES)).toString("utf8");
236
+ const dom = new JSDOM(html, { url: finalPageUrl.href });
237
+ try {
238
+ const document = dom.window.document;
239
+ const declaredIcon = findDeclaredIcon(document, finalPageUrl, options);
240
+ return {
241
+ url: finalPageUrl.href,
242
+ siteName: readSiteName(document),
243
+ iconUrl: (declaredIcon ? await validateIconUrl(declaredIcon, options) : null) ?? await findImplicitFavicon(finalPageUrl, options),
244
+ };
245
+ }
246
+ finally {
247
+ dom.window.close();
248
+ }
249
+ }
250
+ export async function resolveWebsiteMetadata(value, options = {}) {
251
+ const pageUrl = parsePublicHttpUrl(value, options);
252
+ const key = metadataCacheKey(pageUrl);
253
+ if (!options.allowPrivateHosts && !options.fetchImpl) {
254
+ const cached = metadataCache.get(key);
255
+ if (cached && cached.expiresAt > Date.now())
256
+ return cached.value;
257
+ const inflight = metadataInflight.get(key);
258
+ if (inflight)
259
+ return inflight;
260
+ const request = resolveWebsiteMetadataUncached(pageUrl.href, options)
261
+ .then((metadata) => {
262
+ metadataCache.set(key, {
263
+ expiresAt: Date.now() + (metadata.iconUrl ? SUCCESS_CACHE_TTL_MS : FAILURE_CACHE_TTL_MS),
264
+ value: metadata,
265
+ });
266
+ return metadata;
267
+ })
268
+ .finally(() => {
269
+ metadataInflight.delete(key);
270
+ });
271
+ metadataInflight.set(key, request);
272
+ return request;
273
+ }
274
+ return resolveWebsiteMetadataUncached(pageUrl.href, options);
275
+ }
276
+ export async function fetchWebsiteIcon(value, options = {}) {
277
+ const iconUrl = parsePublicHttpUrl(value, options);
278
+ const { response } = await fetchWithTimeout(iconUrl, options);
279
+ if (!response.ok)
280
+ return null;
281
+ const contentType = contentTypeBase(response.headers.get("content-type"));
282
+ if (!IMAGE_CONTENT_TYPES.has(contentType))
283
+ return null;
284
+ const body = await readLimitedBuffer(response, MAX_ICON_BYTES);
285
+ if (body.length <= 0)
286
+ return null;
287
+ return { contentType, body };
288
+ }
289
+ export function __clearWebsiteMetadataCacheForTests() {
290
+ metadataCache.clear();
291
+ metadataInflight.clear();
292
+ }
293
+ //# sourceMappingURL=website-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website-metadata.js","sourceRoot":"","sources":["../../src/services/website-metadata.ts"],"names":[],"mappings":"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"}
@@ -15,11 +15,31 @@ type WorkspaceBackupArtifactMigrationSkip = {
15
15
  to: string;
16
16
  reason: string;
17
17
  };
18
+ export type WorkspaceBackupDownload = {
19
+ artifactRef: string;
20
+ filename: string;
21
+ contentType: "application/json";
22
+ byteSize: number;
23
+ archiveSha256: string | null;
24
+ content: Buffer;
25
+ };
26
+ export type SparseWorkspaceRecoveryResult = {
27
+ orgId: string;
28
+ recovered: boolean;
29
+ backupId: string | null;
30
+ currentFileCount: number;
31
+ backupFileCount: number;
32
+ restoredFileCount: number;
33
+ skippedConflictingFiles: string[];
34
+ reason: string | null;
35
+ error: string | null;
36
+ };
18
37
  export declare function reconcileWorkspaceBackupArtifactStorage(db: Db, liveOrgIds: readonly string[]): Promise<{
19
38
  migrated: WorkspaceBackupArtifactMigration[];
20
39
  skipped: WorkspaceBackupArtifactMigrationSkip[];
21
40
  }>;
22
41
  export declare function workspaceBackupService(db: Db): {
42
+ recoverSparseWorkspaceFromLatestBackup: (orgId: string) => Promise<SparseWorkspaceRecoveryResult>;
23
43
  list(orgId: string): Promise<WorkspaceBackupSummary[]>;
24
44
  create(input: {
25
45
  orgId: string;
@@ -30,6 +50,7 @@ export declare function workspaceBackupService(db: Db): {
30
50
  }): Promise<WorkspaceBackupSummary>;
31
51
  listFiles(orgId: string, backupId: string, directoryPath?: string): Promise<OrganizationWorkspaceFileList>;
32
52
  readFile(orgId: string, backupId: string, filePath: string): Promise<OrganizationWorkspaceFileDetail>;
53
+ getDownload(orgId: string, backupId: string): Promise<WorkspaceBackupDownload>;
33
54
  remove(orgId: string, backupId: string): Promise<WorkspaceBackupSummary>;
34
55
  pruneExpired(now?: Date): Promise<WorkspaceBackupSummary[]>;
35
56
  runScheduledBackups(input?: {
@@ -40,6 +61,7 @@ export declare function workspaceBackupService(db: Db): {
40
61
  created: WorkspaceBackupSummary[];
41
62
  failed: WorkspaceBackupSummary[];
42
63
  deleted: WorkspaceBackupSummary[];
64
+ sparseRecoveries: SparseWorkspaceRecoveryResult[];
43
65
  skipped: number;
44
66
  errors: Array<{
45
67
  orgId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-backups.d.ts","sourceRoot":"","sources":["../../src/services/workspace-backups.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,EAAE,EACR,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,KAAK,+BAA+B,EAEpC,KAAK,6BAA6B,EAClC,KAAK,4BAA4B,EACjC,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EAClC,MAAM,kBAAkB,CAAC;AAmE1B,KAAK,gCAAgC,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,KAAK,oCAAoC,GAAG;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAwKF,wBAAsB,uCAAuC,CAC3D,EAAE,EAAE,EAAE,EACN,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,OAAO,CAAC;IACT,QAAQ,EAAE,gCAAgC,EAAE,CAAC;IAC7C,OAAO,EAAE,oCAAoC,EAAE,CAAC;CACjD,CAAC,CAmFD;AA+ID,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,EAAE;gBAuEvB,MAAM,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC;kBAWxC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,4BAA4B,CAAC;QAC7C,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrC,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,sBAAsB,CAAC;qBA0FZ,MAAM,YAAY,MAAM,2BAAuB,OAAO,CAAC,6BAA6B,CAAC;oBAgBtF,MAAM,YAAY,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,+BAA+B,CAAC;kBA4CvF,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;8BAaxC,OAAO,CAAC,sBAAsB,EAAE,CAAC;gCAqBrC;QAChC,GAAG,CAAC,EAAE,IAAI,CAAC;QACX,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC;QACV,OAAO,EAAE,sBAAsB,EAAE,CAAC;QAClC,MAAM,EAAE,sBAAsB,EAAE,CAAC;QACjC,OAAO,EAAE,sBAAsB,EAAE,CAAC;QAClC,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACnD,CAAC;mBA4CmB,MAAM,YAAY,MAAM,UAAU;QAAE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC;EAmErI"}
1
+ {"version":3,"file":"workspace-backups.d.ts","sourceRoot":"","sources":["../../src/services/workspace-backups.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,9 @@ const WORKSPACE_BACKUP_RUNNING_TIMEOUT_MS = 2 * 60 * 60 * 1000;
34
34
  const MAX_BACKUP_FILE_BYTES = 5 * 1024 * 1024;
35
35
  const MAX_BACKUP_TOTAL_BYTES = 100 * 1024 * 1024;
36
36
  const MAX_WARNING_COUNT = 200;
37
+ const SPARSE_WORKSPACE_RECOVERY_MAX_CURRENT_FILES = 25;
38
+ const SPARSE_WORKSPACE_RECOVERY_MAX_RATIO = 0.25;
39
+ const SPARSE_WORKSPACE_RECOVERY_MIN_BACKUP_FILES = 10;
37
40
  function timestamp(date = new Date()) {
38
41
  const pad = (value) => String(value).padStart(2, "0");
39
42
  return `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`;
@@ -306,6 +309,17 @@ async function fileExists(filePath) {
306
309
  throw error;
307
310
  }
308
311
  }
312
+ async function pathExists(targetPath) {
313
+ try {
314
+ return await fs.lstat(targetPath);
315
+ }
316
+ catch (error) {
317
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
318
+ return null;
319
+ }
320
+ throw error;
321
+ }
322
+ }
309
323
  async function walkWorkspace(rootPath, currentPath, warnings, entries = [], state = { byteSize: 0 }) {
310
324
  const dirents = await fs.readdir(currentPath, { withFileTypes: true });
311
325
  for (const dirent of dirents) {
@@ -374,6 +388,48 @@ function buildManifest(input) {
374
388
  warnings: input.artifact.warnings,
375
389
  };
376
390
  }
391
+ async function restoreMissingArtifactFiles(input) {
392
+ let restoredFileCount = 0;
393
+ const skippedConflictingFiles = [];
394
+ const blockedDirectoryPrefixes = [];
395
+ const directories = input.artifact.entries.filter((entry) => entry.kind === "directory");
396
+ const files = input.artifact.entries.filter((entry) => entry.kind === "file");
397
+ for (const entry of directories) {
398
+ const { resolvedTarget } = resolveWithinRoot(input.workspaceRoot, entry.path);
399
+ const existing = await pathExists(resolvedTarget);
400
+ if (existing && !existing.isDirectory()) {
401
+ skippedConflictingFiles.push(entry.path);
402
+ blockedDirectoryPrefixes.push(`${entry.path}/`);
403
+ continue;
404
+ }
405
+ await fs.mkdir(resolvedTarget, { recursive: true });
406
+ }
407
+ for (const entry of files) {
408
+ if (blockedDirectoryPrefixes.some((prefix) => entry.path.startsWith(prefix))) {
409
+ skippedConflictingFiles.push(entry.path);
410
+ continue;
411
+ }
412
+ const { resolvedTarget } = resolveWithinRoot(input.workspaceRoot, entry.path);
413
+ const existing = await pathExists(resolvedTarget);
414
+ if (existing) {
415
+ if (!existing.isFile()) {
416
+ skippedConflictingFiles.push(entry.path);
417
+ continue;
418
+ }
419
+ if (entry.sha256) {
420
+ const current = await fs.readFile(resolvedTarget);
421
+ if (sha256Buffer(current) !== entry.sha256) {
422
+ skippedConflictingFiles.push(entry.path);
423
+ }
424
+ }
425
+ continue;
426
+ }
427
+ await fs.mkdir(path.dirname(resolvedTarget), { recursive: true });
428
+ await fs.writeFile(resolvedTarget, Buffer.from(entry.dataBase64 ?? "", "base64"), { mode: entry.mode ?? 0o600 });
429
+ restoredFileCount += 1;
430
+ }
431
+ return { restoredFileCount, skippedConflictingFiles };
432
+ }
377
433
  export function workspaceBackupService(db) {
378
434
  const orgs = organizationService(db);
379
435
  async function getBackupRow(orgId, backupId) {
@@ -393,23 +449,27 @@ export function workspaceBackupService(db) {
393
449
  throw unprocessable(row.error ? `Workspace backup failed: ${row.error}` : "Workspace backup failed");
394
450
  }
395
451
  }
396
- async function readArtifact(row) {
452
+ async function readArtifactPayload(row) {
397
453
  assertReadableBackup(row);
398
454
  if (!(await fileExists(row.artifactRef))) {
399
455
  throw notFound("Workspace backup artifact not found");
400
456
  }
401
- const raw = await fs.readFile(row.artifactRef, "utf8");
457
+ const raw = await fs.readFile(row.artifactRef);
402
458
  if (row.archiveSha256 && sha256Buffer(raw) !== row.archiveSha256) {
403
459
  throw unprocessable("Workspace backup artifact checksum does not match the recorded backup metadata");
404
460
  }
405
- const parsed = JSON.parse(raw);
461
+ const parsed = JSON.parse(raw.toString("utf8"));
406
462
  if (parsed.version !== ARTIFACT_VERSION || parsed.orgId !== row.orgId || !Array.isArray(parsed.entries)) {
407
463
  throw unprocessable("Workspace backup artifact is invalid");
408
464
  }
409
465
  for (const entry of parsed.entries) {
410
466
  assertSafeRelativePath(entry.path);
411
467
  }
412
- return parsed;
468
+ return { raw, artifact: parsed };
469
+ }
470
+ async function readArtifact(row) {
471
+ const payload = await readArtifactPayload(row);
472
+ return payload.artifact;
413
473
  }
414
474
  async function countActiveRuns(orgId) {
415
475
  const [row] = await db
@@ -433,7 +493,79 @@ export function workspaceBackupService(db) {
433
493
  .returning();
434
494
  return rows.map(mapBackupRow);
435
495
  }
496
+ async function recoverSparseWorkspaceFromLatestBackup(orgId) {
497
+ const layout = await ensureOrganizationWorkspaceLayout(orgId);
498
+ const warnings = [];
499
+ const currentEntries = await walkWorkspace(layout.root, layout.root, warnings);
500
+ const currentFileCount = currentEntries.filter((entry) => entry.kind === "file").length;
501
+ if (currentFileCount > SPARSE_WORKSPACE_RECOVERY_MAX_CURRENT_FILES) {
502
+ return {
503
+ orgId,
504
+ recovered: false,
505
+ backupId: null,
506
+ currentFileCount,
507
+ backupFileCount: 0,
508
+ restoredFileCount: 0,
509
+ skippedConflictingFiles: [],
510
+ reason: "workspace is not sparse",
511
+ error: null,
512
+ };
513
+ }
514
+ const rows = await db
515
+ .select()
516
+ .from(workspaceBackups)
517
+ .where(and(eq(workspaceBackups.orgId, orgId), or(eq(workspaceBackups.status, "succeeded"), eq(workspaceBackups.status, "restored"))))
518
+ .orderBy(desc(workspaceBackups.fileCount), desc(workspaceBackups.createdAt));
519
+ const candidates = rows.filter((backup) => backup.fileCount >= SPARSE_WORKSPACE_RECOVERY_MIN_BACKUP_FILES
520
+ && currentFileCount <= Math.floor(backup.fileCount * SPARSE_WORKSPACE_RECOVERY_MAX_RATIO));
521
+ if (candidates.length === 0) {
522
+ return {
523
+ orgId,
524
+ recovered: false,
525
+ backupId: null,
526
+ currentFileCount,
527
+ backupFileCount: 0,
528
+ restoredFileCount: 0,
529
+ skippedConflictingFiles: [],
530
+ reason: "no richer backup candidate",
531
+ error: null,
532
+ };
533
+ }
534
+ let lastError = null;
535
+ for (const candidate of candidates) {
536
+ try {
537
+ const artifact = await readArtifact(candidate);
538
+ const restored = await restoreMissingArtifactFiles({ artifact, workspaceRoot: layout.root });
539
+ return {
540
+ orgId,
541
+ recovered: restored.restoredFileCount > 0,
542
+ backupId: candidate.id,
543
+ currentFileCount,
544
+ backupFileCount: candidate.fileCount,
545
+ restoredFileCount: restored.restoredFileCount,
546
+ skippedConflictingFiles: restored.skippedConflictingFiles,
547
+ reason: restored.restoredFileCount > 0 ? null : "no missing files restored",
548
+ error: null,
549
+ };
550
+ }
551
+ catch (error) {
552
+ lastError = error instanceof Error ? error.message : String(error);
553
+ }
554
+ }
555
+ return {
556
+ orgId,
557
+ recovered: false,
558
+ backupId: candidates[0]?.id ?? null,
559
+ currentFileCount,
560
+ backupFileCount: candidates[0]?.fileCount ?? 0,
561
+ restoredFileCount: 0,
562
+ skippedConflictingFiles: [],
563
+ reason: "richer backup recovery failed",
564
+ error: lastError,
565
+ };
566
+ }
436
567
  const service = {
568
+ recoverSparseWorkspaceFromLatestBackup,
437
569
  async list(orgId) {
438
570
  const organization = await orgs.getById(orgId);
439
571
  if (!organization)
@@ -595,6 +727,18 @@ export function workspaceBackupService(db) {
595
727
  truncated,
596
728
  };
597
729
  },
730
+ async getDownload(orgId, backupId) {
731
+ const row = await getBackupRow(orgId, backupId);
732
+ const payload = await readArtifactPayload(row);
733
+ return {
734
+ artifactRef: row.artifactRef,
735
+ filename: path.basename(row.artifactRef),
736
+ contentType: "application/json",
737
+ byteSize: payload.raw.byteLength,
738
+ archiveSha256: row.archiveSha256,
739
+ content: payload.raw,
740
+ };
741
+ },
598
742
  async remove(orgId, backupId) {
599
743
  const row = await getBackupRow(orgId, backupId);
600
744
  await fs.rm(row.artifactRef, { force: true });
@@ -630,6 +774,7 @@ export function workspaceBackupService(db) {
630
774
  const created = [];
631
775
  const failed = [...staleFailed];
632
776
  const errors = [];
777
+ const sparseRecoveries = [];
633
778
  let skipped = 0;
634
779
  for (const organization of organizations) {
635
780
  try {
@@ -643,6 +788,17 @@ export function workspaceBackupService(db) {
643
788
  skipped += 1;
644
789
  continue;
645
790
  }
791
+ const sparseRecovery = await recoverSparseWorkspaceFromLatestBackup(organization.id);
792
+ if (sparseRecovery.recovered || sparseRecovery.error) {
793
+ sparseRecoveries.push(sparseRecovery);
794
+ }
795
+ if (sparseRecovery.error) {
796
+ errors.push({
797
+ orgId: organization.id,
798
+ message: `Sparse workspace recovery failed before scheduled backup: ${sparseRecovery.error}`,
799
+ });
800
+ continue;
801
+ }
646
802
  const backup = await service.create({
647
803
  orgId: organization.id,
648
804
  triggerSource: "scheduled",
@@ -660,7 +816,7 @@ export function workspaceBackupService(db) {
660
816
  });
661
817
  }
662
818
  }
663
- return { created, failed, deleted, skipped, errors };
819
+ return { created, failed, deleted, sparseRecoveries, skipped, errors };
664
820
  },
665
821
  async restore(orgId, backupId, input) {
666
822
  const row = await getBackupRow(orgId, backupId);