plum-e2e 2.8.5 → 2.9.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 (235) hide show
  1. package/backend/_scaffold/utils/browser.ts +184 -30
  2. package/backend/_scaffold/utils/hooks.ts +37 -8
  3. package/backend/app.js +0 -5
  4. package/backend/config/scripts/generate-report.js +2 -2
  5. package/backend/constants/socketEvents.js +7 -4
  6. package/backend/lib/reportFilename.js +1 -2
  7. package/backend/lib/{screenshotPoller.js → rrwebPoller.js} +7 -4
  8. package/backend/lib/serverBootstrap.js +14 -0
  9. package/backend/logs/runner-cmtbz5b1l0000mr0110b27w5k.log +8 -0
  10. package/backend/mcp/server.js +3 -47
  11. package/backend/package-lock.json +199 -1
  12. package/backend/package.json +3 -1
  13. package/backend/prisma/migrations/20260828120000_add_recording_and_split_runner_worker_count/migration.sql +39 -0
  14. package/backend/prisma/migrations/20260828140000_add_recording_started_ended_at/migration.sql +5 -0
  15. package/backend/prisma/migrations/20260828150000_strip_screenshot_refs_from_reports/migration.sql +34 -0
  16. package/backend/prisma/migrations/20260828160000_add_backup_include_reports/migration.sql +4 -0
  17. package/backend/prisma/schema.prisma +97 -70
  18. package/backend/routes/backup.routes.js +47 -1
  19. package/backend/routes/reports.routes.js +23 -0
  20. package/backend/routes/test-cases.routes.js +7 -2
  21. package/backend/server.js +1 -1
  22. package/backend/services/backupCronService.js +1 -1
  23. package/backend/services/backupService.js +134 -44
  24. package/backend/services/cronService.js +23 -15
  25. package/backend/services/nodeExecutionService.js +41 -15
  26. package/backend/services/nodeStreamRegistry.js +24 -0
  27. package/backend/services/reportService.js +174 -84
  28. package/backend/services/runnerService.js +19 -7
  29. package/backend/services/settingsService.js +6 -3
  30. package/backend/services/testCaseService.js +3 -2
  31. package/backend/services/triggerService.js +20 -13
  32. package/backend/services/userService.js +1 -3
  33. package/backend/websockets/nodeSocketHandler.js +40 -0
  34. package/backend/websockets/socketHandler.js +9 -7
  35. package/frontend/.svelte-kit/adapter-node/.vite/manifest.json +1 -1
  36. package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.C1TbMUws.css +6 -0
  37. package/frontend/.svelte-kit/adapter-node/chunks/internal.js +1 -1
  38. package/frontend/.svelte-kit/adapter-node/entries/pages/_page.svelte.js +22 -22
  39. package/frontend/.svelte-kit/adapter-node/entries/pages/settings/_page.svelte.js +3 -3
  40. package/frontend/.svelte-kit/adapter-node/manifest-full.js +1 -1
  41. package/frontend/.svelte-kit/adapter-node/manifest.js +1 -1
  42. package/frontend/.svelte-kit/adapter-node/nodes/0.js +1 -1
  43. package/frontend/.svelte-kit/adapter-node/nodes/1.js +1 -1
  44. package/frontend/.svelte-kit/adapter-node/nodes/11.js +1 -1
  45. package/frontend/.svelte-kit/adapter-node/nodes/12.js +1 -1
  46. package/frontend/.svelte-kit/adapter-node/nodes/2.js +2 -2
  47. package/frontend/.svelte-kit/adapter-node/nodes/3.js +1 -1
  48. package/frontend/.svelte-kit/adapter-node/nodes/5.js +1 -1
  49. package/frontend/.svelte-kit/adapter-node/nodes/6.js +1 -1
  50. package/frontend/.svelte-kit/adapter-node/nodes/8.js +1 -1
  51. package/frontend/.svelte-kit/adapter-node/nodes/9.js +1 -1
  52. package/frontend/.svelte-kit/ambient.d.ts +4 -0
  53. package/frontend/.svelte-kit/generated/server/internal.js +1 -1
  54. package/frontend/.svelte-kit/output/client/.vite/manifest.json +35 -35
  55. package/frontend/.svelte-kit/output/client/_app/immutable/assets/2.C1TbMUws.css +6 -0
  56. package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.C1TbMUws.css +6 -0
  57. package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{DEKAA-Fm.js → DDZw0L0T.js} +1 -1
  58. package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{Dhf4xQKo.js → kkA1mrsH.js} +2 -2
  59. package/frontend/.svelte-kit/output/client/_app/immutable/entry/{app.B0GH5ONo.js → app.KrtMZ3my.js} +2 -2
  60. package/frontend/.svelte-kit/output/client/_app/immutable/entry/{start.Bn25CW9X.js → start.4qxHHAcl.js} +1 -1
  61. package/frontend/.svelte-kit/output/client/_app/immutable/nodes/{0.-imXt0f5.js → 0.C8DodwXs.js} +1 -1
  62. package/frontend/{build/client/_app/immutable/nodes/1.Dom3CKWF.js → .svelte-kit/output/client/_app/immutable/nodes/1.Df9sLw8b.js} +1 -1
  63. package/frontend/{build/client/_app/immutable/nodes/11.DMlayLCK.js → .svelte-kit/output/client/_app/immutable/nodes/11.BViaDK2m.js} +1 -1
  64. package/frontend/{build/client/_app/immutable/nodes/12.Bu89A1eX.js → .svelte-kit/output/client/_app/immutable/nodes/12.BMSCSd88.js} +1 -1
  65. package/frontend/.svelte-kit/output/client/_app/immutable/nodes/2.BCPSg7H4.js +6 -0
  66. package/frontend/.svelte-kit/output/client/_app/immutable/nodes/{3.B86rlHXU.js → 3.8BFAJoHT.js} +1 -1
  67. package/frontend/{build/client/_app/immutable/nodes/5.CqTXvadV.js → .svelte-kit/output/client/_app/immutable/nodes/5.DVeH2eQP.js} +1 -1
  68. package/frontend/.svelte-kit/output/client/_app/immutable/nodes/{6.BJZ62MCd.js → 6.DI7-IJhN.js} +1 -1
  69. package/frontend/{build/client/_app/immutable/nodes/8.B4fj2Xyu.js → .svelte-kit/output/client/_app/immutable/nodes/8.93Mb3ofT.js} +4 -4
  70. package/frontend/{build/client/_app/immutable/nodes/9.C57_2xq6.js → .svelte-kit/output/client/_app/immutable/nodes/9.CvfGx3Hu.js} +1 -1
  71. package/frontend/.svelte-kit/output/client/_app/version.json +1 -1
  72. package/frontend/.svelte-kit/output/server/.vite/manifest.json +1 -1
  73. package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.C1TbMUws.css +6 -0
  74. package/frontend/.svelte-kit/output/server/chunks/internal.js +1 -1
  75. package/frontend/.svelte-kit/output/server/entries/pages/_page.svelte.js +22 -22
  76. package/frontend/.svelte-kit/output/server/entries/pages/settings/_page.svelte.js +3 -3
  77. package/frontend/.svelte-kit/output/server/manifest-full.js +1 -1
  78. package/frontend/.svelte-kit/output/server/manifest.js +1 -1
  79. package/frontend/.svelte-kit/output/server/nodes/0.js +1 -1
  80. package/frontend/.svelte-kit/output/server/nodes/1.js +1 -1
  81. package/frontend/.svelte-kit/output/server/nodes/11.js +1 -1
  82. package/frontend/.svelte-kit/output/server/nodes/12.js +1 -1
  83. package/frontend/.svelte-kit/output/server/nodes/2.js +2 -2
  84. package/frontend/.svelte-kit/output/server/nodes/3.js +1 -1
  85. package/frontend/.svelte-kit/output/server/nodes/5.js +1 -1
  86. package/frontend/.svelte-kit/output/server/nodes/6.js +1 -1
  87. package/frontend/.svelte-kit/output/server/nodes/8.js +1 -1
  88. package/frontend/.svelte-kit/output/server/nodes/9.js +1 -1
  89. package/frontend/build/client/_app/immutable/assets/2.C1TbMUws.css +6 -0
  90. package/frontend/build/client/_app/immutable/assets/2.C1TbMUws.css.br +0 -0
  91. package/frontend/build/client/_app/immutable/assets/2.C1TbMUws.css.gz +0 -0
  92. package/frontend/build/client/_app/immutable/assets/_page.C1TbMUws.css +6 -0
  93. package/frontend/build/client/_app/immutable/assets/_page.C1TbMUws.css.br +0 -0
  94. package/frontend/build/client/_app/immutable/assets/_page.C1TbMUws.css.gz +0 -0
  95. package/frontend/build/client/_app/immutable/chunks/{DEKAA-Fm.js → DDZw0L0T.js} +1 -1
  96. package/frontend/build/client/_app/immutable/chunks/DDZw0L0T.js.br +0 -0
  97. package/frontend/build/client/_app/immutable/chunks/DDZw0L0T.js.gz +0 -0
  98. package/frontend/build/client/_app/immutable/chunks/{Dhf4xQKo.js → kkA1mrsH.js} +2 -2
  99. package/frontend/build/client/_app/immutable/chunks/kkA1mrsH.js.br +0 -0
  100. package/frontend/build/client/_app/immutable/chunks/kkA1mrsH.js.gz +0 -0
  101. package/frontend/build/client/_app/immutable/entry/{app.B0GH5ONo.js → app.KrtMZ3my.js} +2 -2
  102. package/frontend/build/client/_app/immutable/entry/app.KrtMZ3my.js.br +0 -0
  103. package/frontend/build/client/_app/immutable/entry/app.KrtMZ3my.js.gz +0 -0
  104. package/frontend/build/client/_app/immutable/entry/{start.Bn25CW9X.js → start.4qxHHAcl.js} +1 -1
  105. package/frontend/build/client/_app/immutable/entry/{start.Bn25CW9X.js.br → start.4qxHHAcl.js.br} +0 -0
  106. package/frontend/build/client/_app/immutable/entry/{start.Bn25CW9X.js.gz → start.4qxHHAcl.js.gz} +0 -0
  107. package/frontend/build/client/_app/immutable/nodes/{0.-imXt0f5.js → 0.C8DodwXs.js} +1 -1
  108. package/frontend/build/client/_app/immutable/nodes/0.C8DodwXs.js.br +0 -0
  109. package/frontend/build/client/_app/immutable/nodes/0.C8DodwXs.js.gz +0 -0
  110. package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/1.Dom3CKWF.js → build/client/_app/immutable/nodes/1.Df9sLw8b.js} +1 -1
  111. package/frontend/build/client/_app/immutable/nodes/1.Df9sLw8b.js.br +0 -0
  112. package/frontend/build/client/_app/immutable/nodes/1.Df9sLw8b.js.gz +0 -0
  113. package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/11.DMlayLCK.js → build/client/_app/immutable/nodes/11.BViaDK2m.js} +1 -1
  114. package/frontend/build/client/_app/immutable/nodes/11.BViaDK2m.js.br +0 -0
  115. package/frontend/build/client/_app/immutable/nodes/11.BViaDK2m.js.gz +0 -0
  116. package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/12.Bu89A1eX.js → build/client/_app/immutable/nodes/12.BMSCSd88.js} +1 -1
  117. package/frontend/build/client/_app/immutable/nodes/12.BMSCSd88.js.br +0 -0
  118. package/frontend/build/client/_app/immutable/nodes/{12.Bu89A1eX.js.gz → 12.BMSCSd88.js.gz} +0 -0
  119. package/frontend/build/client/_app/immutable/nodes/2.BCPSg7H4.js +6 -0
  120. package/frontend/build/client/_app/immutable/nodes/2.BCPSg7H4.js.br +0 -0
  121. package/frontend/build/client/_app/immutable/nodes/2.BCPSg7H4.js.gz +0 -0
  122. package/frontend/build/client/_app/immutable/nodes/{3.B86rlHXU.js → 3.8BFAJoHT.js} +1 -1
  123. package/frontend/build/client/_app/immutable/nodes/3.8BFAJoHT.js.br +0 -0
  124. package/frontend/build/client/_app/immutable/nodes/3.8BFAJoHT.js.gz +0 -0
  125. package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/5.CqTXvadV.js → build/client/_app/immutable/nodes/5.DVeH2eQP.js} +1 -1
  126. package/frontend/build/client/_app/immutable/nodes/5.DVeH2eQP.js.br +0 -0
  127. package/frontend/build/client/_app/immutable/nodes/5.DVeH2eQP.js.gz +0 -0
  128. package/frontend/build/client/_app/immutable/nodes/{6.BJZ62MCd.js → 6.DI7-IJhN.js} +1 -1
  129. package/frontend/build/client/_app/immutable/nodes/6.DI7-IJhN.js.br +0 -0
  130. package/frontend/build/client/_app/immutable/nodes/6.DI7-IJhN.js.gz +0 -0
  131. package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/8.B4fj2Xyu.js → build/client/_app/immutable/nodes/8.93Mb3ofT.js} +4 -4
  132. package/frontend/build/client/_app/immutable/nodes/8.93Mb3ofT.js.br +0 -0
  133. package/frontend/build/client/_app/immutable/nodes/8.93Mb3ofT.js.gz +0 -0
  134. package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/9.C57_2xq6.js → build/client/_app/immutable/nodes/9.CvfGx3Hu.js} +1 -1
  135. package/frontend/build/client/_app/immutable/nodes/9.CvfGx3Hu.js.br +0 -0
  136. package/frontend/build/client/_app/immutable/nodes/9.CvfGx3Hu.js.gz +0 -0
  137. package/frontend/build/client/_app/version.json +1 -1
  138. package/frontend/build/client/_app/version.json.br +0 -0
  139. package/frontend/build/client/_app/version.json.gz +0 -0
  140. package/frontend/build/server/chunks/{0-DG1Uv07a.js → 0-D5YWFygh.js} +2 -2
  141. package/frontend/build/server/chunks/{0-DG1Uv07a.js.map → 0-D5YWFygh.js.map} +1 -1
  142. package/frontend/build/server/chunks/{1-iB0ogJU_.js → 1-Kxn9d30Z.js} +2 -2
  143. package/frontend/build/server/chunks/{1-iB0ogJU_.js.map → 1-Kxn9d30Z.js.map} +1 -1
  144. package/frontend/build/server/chunks/{11-Df9vGZ_v.js → 11-CNLerze_.js} +2 -2
  145. package/frontend/build/server/chunks/{11-Df9vGZ_v.js.map → 11-CNLerze_.js.map} +1 -1
  146. package/frontend/build/server/chunks/{12-DqvjCln4.js → 12-De6Ol6pu.js} +2 -2
  147. package/frontend/build/server/chunks/{12-DqvjCln4.js.map → 12-De6Ol6pu.js.map} +1 -1
  148. package/frontend/build/server/chunks/{2-Cte30Dgy.js → 2-Dc_rKWoK.js} +4 -4
  149. package/frontend/build/server/chunks/{2-Cte30Dgy.js.map → 2-Dc_rKWoK.js.map} +1 -1
  150. package/frontend/build/server/chunks/{3-BYKCZi4U.js → 3-DrRqVrcX.js} +2 -2
  151. package/frontend/build/server/chunks/{3-BYKCZi4U.js.map → 3-DrRqVrcX.js.map} +1 -1
  152. package/frontend/build/server/chunks/{5-B6Jc1foX.js → 5-CFeE5dPZ.js} +2 -2
  153. package/frontend/build/server/chunks/{5-B6Jc1foX.js.map → 5-CFeE5dPZ.js.map} +1 -1
  154. package/frontend/build/server/chunks/{6-dXZKtN86.js → 6-DZk37MZH.js} +2 -2
  155. package/frontend/build/server/chunks/{6-dXZKtN86.js.map → 6-DZk37MZH.js.map} +1 -1
  156. package/frontend/build/server/chunks/{8-D-Bp7HzS.js → 8-CKPVFOqJ.js} +3 -3
  157. package/frontend/build/server/chunks/{8-D-Bp7HzS.js.map → 8-CKPVFOqJ.js.map} +1 -1
  158. package/frontend/build/server/chunks/{9-BynjuGUO.js → 9-DirZG_Lu.js} +2 -2
  159. package/frontend/build/server/chunks/{9-BynjuGUO.js.map → 9-DirZG_Lu.js.map} +1 -1
  160. package/frontend/build/server/chunks/{_page.svelte-CpB-fgJl.js → _page.svelte-04WxjOuH.js} +23 -23
  161. package/frontend/build/server/chunks/_page.svelte-04WxjOuH.js.map +5 -0
  162. package/frontend/build/server/chunks/{_page.svelte-wKyUmA2e.js → _page.svelte-8gELc_B1.js} +4 -4
  163. package/frontend/build/server/chunks/_page.svelte-8gELc_B1.js.map +5 -0
  164. package/frontend/build/server/index.js +1 -1
  165. package/frontend/build/server/index.js.map +1 -1
  166. package/frontend/build/server/manifest.js +11 -11
  167. package/frontend/build/server/manifest.js.map +1 -1
  168. package/frontend/package-lock.json +121 -32
  169. package/frontend/package.json +1 -0
  170. package/frontend/src/lib/api/reports.js +13 -4
  171. package/frontend/src/lib/api/repository.js +2 -2
  172. package/frontend/src/lib/api/settings.js +16 -1
  173. package/frontend/src/lib/components/layout/RunnerPanel.svelte +9 -24
  174. package/frontend/src/lib/components/reports/ElementInspector.svelte +141 -0
  175. package/frontend/src/lib/components/reports/LiveReplayer.svelte +110 -0
  176. package/frontend/src/lib/components/reports/MultiTabTimeline.svelte +115 -0
  177. package/frontend/src/lib/components/reports/RecordingPlayer.svelte +786 -0
  178. package/frontend/src/lib/components/reports/StepsRail.svelte +109 -0
  179. package/frontend/src/lib/components/ui/CodeViewer.svelte +61 -0
  180. package/frontend/src/lib/constants.js +0 -1
  181. package/frontend/src/lib/copy/reports.js +18 -8
  182. package/frontend/src/lib/copy/repository.js +6 -0
  183. package/frontend/src/lib/copy/settings.js +25 -4
  184. package/frontend/src/lib/socketEvents.js +7 -4
  185. package/frontend/src/lib/stores/runner.js +26 -3
  186. package/frontend/src/lib/styles/tokens.css +7 -0
  187. package/frontend/src/lib/utils/format.js +108 -2
  188. package/frontend/src/lib/utils/inspectElement.js +34 -0
  189. package/frontend/src/routes/+page.svelte +6 -1
  190. package/frontend/src/routes/reports/+page.svelte +79 -1
  191. package/frontend/src/routes/reports/[id]/+page.svelte +304 -495
  192. package/frontend/src/routes/reports/live/+page.svelte +236 -260
  193. package/frontend/src/routes/settings/+page.svelte +246 -8
  194. package/frontend/src/routes/test-repository/suites/[id]/+page.svelte +116 -0
  195. package/package.json +1 -1
  196. package/backend/playwright.config.js +0 -85
  197. package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.DvMkmYA-.css +0 -6
  198. package/frontend/.svelte-kit/output/client/_app/immutable/assets/2.DvMkmYA-.css +0 -6
  199. package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.DvMkmYA-.css +0 -6
  200. package/frontend/.svelte-kit/output/client/_app/immutable/nodes/2.BnHalSCi.js +0 -6
  201. package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DvMkmYA-.css +0 -6
  202. package/frontend/build/client/_app/immutable/assets/2.DvMkmYA-.css +0 -6
  203. package/frontend/build/client/_app/immutable/assets/2.DvMkmYA-.css.br +0 -0
  204. package/frontend/build/client/_app/immutable/assets/2.DvMkmYA-.css.gz +0 -0
  205. package/frontend/build/client/_app/immutable/assets/_page.DvMkmYA-.css +0 -6
  206. package/frontend/build/client/_app/immutable/assets/_page.DvMkmYA-.css.br +0 -0
  207. package/frontend/build/client/_app/immutable/assets/_page.DvMkmYA-.css.gz +0 -0
  208. package/frontend/build/client/_app/immutable/chunks/DEKAA-Fm.js.br +0 -0
  209. package/frontend/build/client/_app/immutable/chunks/DEKAA-Fm.js.gz +0 -0
  210. package/frontend/build/client/_app/immutable/chunks/Dhf4xQKo.js.br +0 -0
  211. package/frontend/build/client/_app/immutable/chunks/Dhf4xQKo.js.gz +0 -0
  212. package/frontend/build/client/_app/immutable/entry/app.B0GH5ONo.js.br +0 -0
  213. package/frontend/build/client/_app/immutable/entry/app.B0GH5ONo.js.gz +0 -0
  214. package/frontend/build/client/_app/immutable/nodes/0.-imXt0f5.js.br +0 -0
  215. package/frontend/build/client/_app/immutable/nodes/0.-imXt0f5.js.gz +0 -0
  216. package/frontend/build/client/_app/immutable/nodes/1.Dom3CKWF.js.br +0 -0
  217. package/frontend/build/client/_app/immutable/nodes/1.Dom3CKWF.js.gz +0 -0
  218. package/frontend/build/client/_app/immutable/nodes/11.DMlayLCK.js.br +0 -0
  219. package/frontend/build/client/_app/immutable/nodes/11.DMlayLCK.js.gz +0 -0
  220. package/frontend/build/client/_app/immutable/nodes/12.Bu89A1eX.js.br +0 -0
  221. package/frontend/build/client/_app/immutable/nodes/2.BnHalSCi.js +0 -6
  222. package/frontend/build/client/_app/immutable/nodes/2.BnHalSCi.js.br +0 -0
  223. package/frontend/build/client/_app/immutable/nodes/2.BnHalSCi.js.gz +0 -0
  224. package/frontend/build/client/_app/immutable/nodes/3.B86rlHXU.js.br +0 -0
  225. package/frontend/build/client/_app/immutable/nodes/3.B86rlHXU.js.gz +0 -0
  226. package/frontend/build/client/_app/immutable/nodes/5.CqTXvadV.js.br +0 -0
  227. package/frontend/build/client/_app/immutable/nodes/5.CqTXvadV.js.gz +0 -0
  228. package/frontend/build/client/_app/immutable/nodes/6.BJZ62MCd.js.br +0 -0
  229. package/frontend/build/client/_app/immutable/nodes/6.BJZ62MCd.js.gz +0 -0
  230. package/frontend/build/client/_app/immutable/nodes/8.B4fj2Xyu.js.br +0 -0
  231. package/frontend/build/client/_app/immutable/nodes/8.B4fj2Xyu.js.gz +0 -0
  232. package/frontend/build/client/_app/immutable/nodes/9.C57_2xq6.js.br +0 -0
  233. package/frontend/build/client/_app/immutable/nodes/9.C57_2xq6.js.gz +0 -0
  234. package/frontend/build/server/chunks/_page.svelte-CpB-fgJl.js.map +0 -5
  235. package/frontend/build/server/chunks/_page.svelte-wKyUmA2e.js.map +0 -5
@@ -8,7 +8,6 @@ const jwt = require('jsonwebtoken');
8
8
  const prisma = require('./prisma');
9
9
 
10
10
  const JWT_SECRET = process.env.JWT_SECRET || 'plum-dev-secret-change-in-production';
11
- const JWT_EXPIRY = '7d';
12
11
  const SALT_ROUNDS = 10;
13
12
 
14
13
  const userSelect = { id: true, name: true, email: true, role: true, createdAt: true };
@@ -33,8 +32,7 @@ async function login({ email, password }) {
33
32
  if (!match) return null;
34
33
  const token = jwt.sign(
35
34
  { userId: user.id, email: user.email, name: user.name, role: user.role },
36
- JWT_SECRET,
37
- { expiresIn: JWT_EXPIRY }
35
+ JWT_SECRET
38
36
  );
39
37
  return { token, user: { id: user.id, name: user.name, email: user.email, role: user.role } };
40
38
  }
@@ -0,0 +1,40 @@
1
+ /*
2
+ * This file is part of Plum.
3
+ * Licensed under the MIT License. See LICENSE file in the project root for details.
4
+ */
5
+
6
+ const runnerService = require('../services/runnerService');
7
+ const nodeStreamRegistry = require('../services/nodeStreamRegistry');
8
+
9
+ // A separate namespace from the browser-facing default one — a node connects
10
+ // with its own runner token (the same credential it already uses to call back
11
+ // into the primary's HTTP control routes, see runnerService.isValidToken) and
12
+ // announces the jobId it's streaming for, which nodeStreamRegistry maps back
13
+ // to whichever dispatch call is waiting on it.
14
+ function nodeSocketHandler(io) {
15
+ const nodeIo = io.of('/node-stream');
16
+
17
+ nodeIo.use(async (socket, next) => {
18
+ const token = socket.handshake.auth?.token;
19
+ if (await runnerService.isValidToken(token)) return next();
20
+ next(new Error('unauthorized'));
21
+ });
22
+
23
+ nodeIo.on('connection', (socket) => {
24
+ let jobId = null;
25
+
26
+ socket.on('join', (id) => {
27
+ jobId = id;
28
+ });
29
+
30
+ socket.on('rrweb-batch', (batch) => {
31
+ if (jobId) nodeStreamRegistry.getRelay(jobId)?.onRRwebBatch?.(batch);
32
+ });
33
+
34
+ socket.on('log', (text) => {
35
+ if (jobId) nodeStreamRegistry.getRelay(jobId)?.onLog?.(text);
36
+ });
37
+ });
38
+ }
39
+
40
+ module.exports = nodeSocketHandler;
@@ -13,7 +13,7 @@ const reportService = require('../services/reportService');
13
13
  const settingsService = require('../services/settingsService');
14
14
  const notificationService = require('../services/notificationService');
15
15
  const activeRunsService = require('../services/activeRunsService');
16
- const { startSsPoller } = require('../lib/screenshotPoller');
16
+ const { startRRwebPoller } = require('../lib/rrwebPoller');
17
17
  const { runWithRetries } = require('../lib/retryRunner');
18
18
  const { TRIGGER_TYPE, BUILT_IN_RUNNER_ID, TRIGGER_REMOTE } = require('../constants/triggers');
19
19
  const { DEFAULT_BROWSER } = require('../constants/defaults');
@@ -243,8 +243,8 @@ function runBuiltInAttempt({
243
243
  const proc = spawn('npm', ['run', 'test'], { env, shell: true });
244
244
  activeProcs.add(proc);
245
245
 
246
- const ssPoller = startSsPoller(ssDir, ({ stepName, data }) => {
247
- socket.emit(SOCKET_EVENTS.STEP_SCREENSHOT, { stepName, data });
246
+ const ssPoller = startRRwebPoller(ssDir, (batch) => {
247
+ socket.emit(SOCKET_EVENTS.RUNNER_LANE_RRWEB_BATCH, { id: BUILT_IN_RUNNER_ID, ...batch });
248
248
  });
249
249
 
250
250
  proc.stdout.on('data', (d) => onLog(d.toString()));
@@ -362,6 +362,7 @@ async function runBuiltIn(
362
362
  rawCucumberJson: rawJson,
363
363
  tags: tag,
364
364
  triggerType: TRIGGER_TYPE.MANUAL,
365
+ workerCount: workers,
365
366
  browser,
366
367
  testRunId: testRunId ?? null,
367
368
  logs: logBuffer || null,
@@ -468,6 +469,7 @@ async function runDistributed(
468
469
  .saveCombinedReport({
469
470
  reports: collectedReports,
470
471
  runners: laneInfos,
472
+ workers,
471
473
  overallCode,
472
474
  tag,
473
475
  triggerType: TRIGGER_TYPE.MANUAL,
@@ -543,8 +545,8 @@ async function runDistributed(
543
545
  const proc = spawn('npm', ['run', 'test'], { env, shell: true });
544
546
  activeProcs.add(proc);
545
547
 
546
- const ssPoller = startSsPoller(ssDir, ({ stepName, data }) => {
547
- socket.emit(SOCKET_EVENTS.RUNNER_LANE_SCREENSHOT, { id: laneId, stepName, data });
548
+ const ssPoller = startRRwebPoller(ssDir, (batch) => {
549
+ socket.emit(SOCKET_EVENTS.RUNNER_LANE_RRWEB_BATCH, { id: laneId, ...batch });
548
550
  });
549
551
 
550
552
  proc.stdout.on('data', (d) => onLog(d.toString()));
@@ -588,8 +590,8 @@ async function runDistributed(
588
590
  makeSyntheticFailReport(lane.name, chunkIds, 'could not fetch report from runner');
589
591
  resolve({ code, rawJson: JSON.parse(raw) });
590
592
  },
591
- ({ stepName, data }) => {
592
- socket.emit(SOCKET_EVENTS.RUNNER_LANE_SCREENSHOT, { id: laneId, stepName, data });
593
+ (batch) => {
594
+ socket.emit(SOCKET_EVENTS.RUNNER_LANE_RRWEB_BATCH, { id: laneId, ...batch });
593
595
  }
594
596
  );
595
597
  });
@@ -294,7 +294,7 @@
294
294
  "_attributes.js"
295
295
  ],
296
296
  "css": [
297
- "_app/immutable/assets/_page.DvMkmYA-.css"
297
+ "_app/immutable/assets/_page.C1TbMUws.css"
298
298
  ]
299
299
  },
300
300
  "src/routes/login/+page.svelte": {
@@ -0,0 +1,6 @@
1
+ /*
2
+ * This file is part of Plum.
3
+ * Licensed under the MIT License. See LICENSE file in the project root for details.
4
+ */
5
+
6
+ .page-header.svelte-b4oiqy{margin-bottom:1.75rem;padding-bottom:1.5rem;border-bottom:1px solid var(--border)}.header-top.svelte-b4oiqy{display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;margin-bottom:1.25rem}h1.svelte-b4oiqy{font-size:2.5rem;margin-bottom:.25rem}.subtitle.svelte-b4oiqy{color:var(--text-muted);font-size:.875rem}.search-row.svelte-b4oiqy{display:flex;gap:.75rem}.search-wrap.svelte-b4oiqy{position:relative;flex:1;max-width:480px}.search-icon.svelte-b4oiqy{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);color:var(--text-muted);pointer-events:none}.search-input.svelte-b4oiqy{width:100%;padding:.55rem .875rem .55rem 2.25rem;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-subtle);color:var(--text);font-family:var(--font-body);font-size:.875rem;font-weight:300;outline:none;transition:border-color var(--duration-fast),box-shadow var(--duration-fast)}.search-input.svelte-b4oiqy:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);background:var(--bg-elevated)}.sort-bar.svelte-b4oiqy{display:flex;align-items:center;gap:.375rem;margin:1.25rem 0;flex-wrap:wrap}.sort-label.svelte-b4oiqy{font-size:.75rem;color:var(--text-muted);margin-right:.25rem}.sort-chip.svelte-b4oiqy{display:flex;align-items:center;gap:.25rem;height:28px;padding:0 .625rem;font-family:var(--font-body);font-size:.8125rem;color:var(--text-muted);background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--radius-pill);cursor:pointer;transition:color var(--duration-fast),border-color var(--duration-fast),background var(--duration-fast)}.sort-chip.svelte-b4oiqy:hover{color:var(--text);border-color:var(--accent)}.sort-chip.active.svelte-b4oiqy{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}.sort-dir.svelte-b4oiqy{font-size:.7rem;opacity:.8}.search-input.svelte-b4oiqy::placeholder{color:var(--text-muted)}.search-clear.svelte-b4oiqy{position:absolute;right:.625rem;top:50%;transform:translateY(-50%);display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;border:none;background:var(--border);color:var(--text-muted);cursor:pointer;transition:background var(--duration-fast),color var(--duration-fast)}.search-clear.svelte-b4oiqy:hover{background:var(--text-muted);color:var(--bg)}.suites.svelte-b4oiqy{display:flex;flex-direction:column;gap:1rem}.suite.svelte-b4oiqy{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:visible;background:var(--bg-elevated);animation:fadeUp .35s var(--ease-out) both}.suite-header.svelte-b4oiqy{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.875rem 1.25rem;background:var(--bg-subtle);border-bottom:1px solid var(--border);border-radius:var(--radius-lg) var(--radius-lg) 0 0}.suite-header.collapsed.svelte-b4oiqy{border-bottom:none;border-radius:var(--radius-lg)}.suite-toggle.svelte-b4oiqy{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:transparent;color:var(--text-muted);cursor:pointer;flex-shrink:0;border-radius:var(--radius-sm);transition:background var(--duration-fast),color var(--duration-fast)}.suite-toggle.svelte-b4oiqy:hover{background:var(--bg-elevated);color:var(--text)}.suite-toggle.svelte-b4oiqy svg:where(.svelte-b4oiqy){transition:transform var(--duration-fast) var(--ease-out)}.suite-toggle.svelte-b4oiqy svg.rotated:where(.svelte-b4oiqy){transform:rotate(90deg)}.suite-meta.svelte-b4oiqy{display:flex;align-items:center;gap:.625rem;flex:1;min-width:0}.suite-badges.svelte-b4oiqy{display:flex;gap:.25rem;flex-shrink:0}.suite-name.svelte-b4oiqy{font-size:.9rem;font-weight:400;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.suite-count.svelte-b4oiqy{font-size:.75rem;color:var(--text-muted);flex-shrink:0}.run-btn.svelte-b4oiqy{display:inline-flex;align-items:center;gap:.35rem;font-family:var(--font-body);font-size:.75rem;font-weight:400;padding:.3rem .75rem;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg-elevated);color:var(--text-muted);cursor:pointer;white-space:nowrap;flex-shrink:0;transition:background var(--duration-fast),color var(--duration-fast),border-color var(--duration-fast)}.run-btn.svelte-b4oiqy:hover{background:var(--accent-soft);color:var(--accent);border-color:var(--accent)}.tests.svelte-b4oiqy{display:flex;flex-direction:column}.test-row.svelte-b4oiqy{border-bottom:1px solid var(--border);animation:fadeUp .3s var(--ease-out) both}.test-row.svelte-b4oiqy:last-child{border-bottom:none}.test-main.svelte-b4oiqy{display:flex;align-items:center;gap:.625rem;padding:.75rem 1.25rem}.run-icon-btn.svelte-b4oiqy{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;border:1px solid var(--border);background:transparent;color:var(--text-muted);cursor:pointer;flex-shrink:0;transition:background var(--duration-fast),color var(--duration-fast),border-color var(--duration-fast)}.run-icon-btn.svelte-b4oiqy:hover{background:var(--accent);color:var(--white);border-color:var(--accent)}.test-ids.svelte-b4oiqy{display:flex;gap:.25rem;flex-shrink:0}.id-pill.svelte-b4oiqy{position:relative;font-size:.68rem;font-weight:500;letter-spacing:.04em;color:var(--accent);background:var(--accent-soft);border:none;border-radius:var(--radius-pill);padding:.15rem .55rem;cursor:pointer;font-family:JetBrains Mono,monospace;transition:background var(--duration-fast),color var(--duration-fast),filter var(--duration-fast)}.id-pill.svelte-b4oiqy:hover{filter:brightness(.92)}.id-pill.copied.svelte-b4oiqy{color:var(--pass);background:var(--pass-soft)}.id-pill.copied.svelte-b4oiqy:after{content:"Copied";position:absolute;left:50%;bottom:calc(100% + 6px);z-index:50;transform:translate(-50%);padding:.16rem .42rem;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg-elevated);color:var(--pass);box-shadow:0 4px 14px #00000014;font-family:var(--font-body);font-size:.65rem;font-weight:500;letter-spacing:0;pointer-events:none;animation:svelte-b4oiqy-copiedPop 1.4s var(--ease-out) both}.test-name.svelte-b4oiqy{flex:1;font-size:.875rem;color:var(--text);min-width:0}.outline-badge.svelte-b4oiqy{display:inline-block;font-size:.62rem;font-weight:500;letter-spacing:.06em;text-transform:uppercase;background:var(--warn-soft);color:var(--warn);padding:.1rem .4rem;border-radius:var(--radius-pill);margin-left:.4rem;vertical-align:middle}.steps-toggle.svelte-b4oiqy{display:inline-flex;align-items:center;gap:.2rem;font-family:var(--font-body);font-size:.72rem;font-weight:400;color:var(--text-muted);background:transparent;border:1px solid var(--border);border-radius:var(--radius-sm);padding:.2rem .5rem;cursor:pointer;flex-shrink:0;transition:background var(--duration-fast),color var(--duration-fast)}.steps-toggle.svelte-b4oiqy:hover{background:var(--bg-subtle);color:var(--text)}.steps-toggle.svelte-b4oiqy svg:where(.svelte-b4oiqy){transition:transform var(--duration-fast) var(--ease-out)}.steps-toggle.svelte-b4oiqy svg.rotated:where(.svelte-b4oiqy){transform:rotate(90deg)}.steps.svelte-b4oiqy{padding:.75rem 1.25rem .875rem 3.75rem;background:var(--bg-subtle);border-top:1px solid var(--border)}.step-list.svelte-b4oiqy{list-style:none;display:flex;flex-direction:column;gap:.3rem}.step.svelte-b4oiqy{font-size:.8125rem;color:var(--text-muted);font-family:JetBrains Mono,monospace;line-height:1.5;padding-left:1rem;position:relative}.step.svelte-b4oiqy:before{content:"›";position:absolute;left:0;color:var(--accent);font-family:var(--font-body)}.examples.svelte-b4oiqy{margin-top:.75rem;padding-top:.75rem;border-top:1px dashed var(--border)}.examples-label.svelte-b4oiqy{display:block;font-size:.68rem;font-weight:500;letter-spacing:.07em;text-transform:uppercase;color:var(--text-muted);margin-bottom:.5rem}.examples-table-wrap.svelte-b4oiqy{overflow-x:auto}.examples-table.svelte-b4oiqy{border-collapse:collapse;font-size:.78rem;font-family:JetBrains Mono,monospace;width:auto}.examples-table.svelte-b4oiqy th:where(.svelte-b4oiqy){text-align:left;padding:.3rem .75rem;font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);border-bottom:1px solid var(--border);font-family:var(--font-body);font-weight:500}.examples-table.svelte-b4oiqy td:where(.svelte-b4oiqy){padding:.3rem .75rem;color:var(--text-muted);border-bottom:1px solid var(--border)}.examples-table.svelte-b4oiqy tbody:where(.svelte-b4oiqy) tr:where(.svelte-b4oiqy):last-child td:where(.svelte-b4oiqy){border-bottom:none}@keyframes svelte-b4oiqy-copiedPop{0%{opacity:0;transform:translate(-50%,4px) scale(.96)}12%,78%{opacity:1;transform:translate(-50%) scale(1)}to{opacity:0;transform:translate(-50%,-2px) scale(.98)}}
@@ -641,7 +641,7 @@ const options = {
641
641
  <div class="error">
642
642
  <span class="status">` + status + '</span>\n <div class="message">\n <h1>' + message + "</h1>\n </div>\n </div>\n </body>\n</html>\n"
643
643
  },
644
- version_hash: "1m6qzpt"
644
+ version_hash: "1cz1h1z"
645
645
  };
646
646
  async function get_hooks() {
647
647
  let handle;
@@ -84,7 +84,7 @@ function _page($$payload, $$props) {
84
84
  head($$payload, ($$payload2) => {
85
85
  $$payload2.title = `<title>${escape_html(PAGE_TITLE)}</title>`;
86
86
  });
87
- $$payload.out += `<div class="page-header svelte-ll28r2"><div class="header-top svelte-ll28r2"><div class="svelte-ll28r2"><h1 class="svelte-ll28r2">${escape_html(HEADING)}</h1> <p class="subtitle svelte-ll28r2">`;
87
+ $$payload.out += `<div class="page-header svelte-b4oiqy"><div class="header-top svelte-b4oiqy"><div class="svelte-b4oiqy"><h1 class="svelte-b4oiqy">${escape_html(HEADING)}</h1> <p class="subtitle svelte-b4oiqy">`;
88
88
  if (q) {
89
89
  $$payload.out += "<!--[-->";
90
90
  $$payload.out += `${escape_html(visibleOfTotal(visibleTests, totalTests))}`;
@@ -92,7 +92,7 @@ function _page($$payload, $$props) {
92
92
  $$payload.out += "<!--[!-->";
93
93
  $$payload.out += `${escape_html(suiteSummary(suites.length, totalTests))}`;
94
94
  }
95
- $$payload.out += `<!--]--></p></div></div> <div class="search-row svelte-ll28r2"><div class="search-wrap svelte-ll28r2"><svg class="search-icon svelte-ll28r2" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8" class="svelte-ll28r2"></circle><line x1="21" y1="21" x2="16.65" y2="16.65" class="svelte-ll28r2"></line></svg> <input type="text" class="search-input svelte-ll28r2"${attr("value", search)}${attr("placeholder", SEARCH_PLACEHOLDER)}> `;
95
+ $$payload.out += `<!--]--></p></div></div> <div class="search-row svelte-b4oiqy"><div class="search-wrap svelte-b4oiqy"><svg class="search-icon svelte-b4oiqy" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8" class="svelte-b4oiqy"></circle><line x1="21" y1="21" x2="16.65" y2="16.65" class="svelte-b4oiqy"></line></svg> <input type="text" class="search-input svelte-b4oiqy"${attr("value", search)}${attr("placeholder", SEARCH_PLACEHOLDER)}> `;
96
96
  {
97
97
  $$payload.out += "<!--[!-->";
98
98
  }
@@ -100,13 +100,13 @@ function _page($$payload, $$props) {
100
100
  if (!q) {
101
101
  $$payload.out += "<!--[-->";
102
102
  const each_array = ensure_array_like([["id", "ID"], ["name", "Name"]]);
103
- $$payload.out += `<div class="sort-bar svelte-ll28r2"><span class="sort-label svelte-ll28r2">${escape_html(SORT_BY_LABEL)}</span> <!--[-->`;
103
+ $$payload.out += `<div class="sort-bar svelte-b4oiqy"><span class="sort-label svelte-b4oiqy">${escape_html(SORT_BY_LABEL)}</span> <!--[-->`;
104
104
  for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
105
105
  let [val, label] = each_array[$$index];
106
- $$payload.out += `<button${attr("class", `sort-chip svelte-ll28r2 ${stringify([sort.by === val ? "active" : ""].filter(Boolean).join(" "))}`)}>${escape_html(label)} `;
106
+ $$payload.out += `<button${attr("class", `sort-chip svelte-b4oiqy ${stringify([sort.by === val ? "active" : ""].filter(Boolean).join(" "))}`)}>${escape_html(label)} `;
107
107
  if (sort.by === val) {
108
108
  $$payload.out += "<!--[-->";
109
- $$payload.out += `<span class="sort-dir svelte-ll28r2">${escape_html(sort.order === "asc" ? "↑" : "↓")}</span>`;
109
+ $$payload.out += `<span class="sort-dir svelte-b4oiqy">${escape_html(sort.order === "asc" ? "↑" : "↓")}</span>`;
110
110
  } else {
111
111
  $$payload.out += "<!--[!-->";
112
112
  }
@@ -125,43 +125,43 @@ function _page($$payload, $$props) {
125
125
  } else {
126
126
  $$payload.out += "<!--[!-->";
127
127
  const each_array_1 = ensure_array_like(filtered);
128
- $$payload.out += `<div class="suites svelte-ll28r2"><!--[-->`;
128
+ $$payload.out += `<div class="suites svelte-b4oiqy"><!--[-->`;
129
129
  for (let si = 0, $$length = each_array_1.length; si < $$length; si++) {
130
130
  let suite = each_array_1[si];
131
131
  const suiteKey = suiteIds(suite)[0] ?? suite.suiteName;
132
132
  const suiteOpen = !collapsedSuites.has(suiteKey);
133
133
  const each_array_2 = ensure_array_like(suiteIds(suite));
134
- $$payload.out += `<div class="suite svelte-ll28r2"${attr("style", stagger(si, 55))}><div class="suite-header svelte-ll28r2"><button class="suite-toggle svelte-ll28r2"${attr("aria-expanded", suiteOpen)}${attr("aria-label", collapseOrExpandSuiteLabel(suiteOpen))}><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"${attr("class", `svelte-ll28r2 ${stringify([suiteOpen ? "rotated" : ""].filter(Boolean).join(" "))}`)}><polyline points="9 18 15 12 9 6" class="svelte-ll28r2"></polyline></svg></button> <div class="suite-meta svelte-ll28r2"><div class="suite-badges svelte-ll28r2"><!--[-->`;
134
+ $$payload.out += `<div class="suite svelte-b4oiqy"${attr("style", stagger(si, 55))}><div${attr("class", `suite-header svelte-b4oiqy ${stringify([!suiteOpen ? "collapsed" : ""].filter(Boolean).join(" "))}`)}><button class="suite-toggle svelte-b4oiqy"${attr("aria-expanded", suiteOpen)}${attr("aria-label", collapseOrExpandSuiteLabel(suiteOpen))}><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"${attr("class", `svelte-b4oiqy ${stringify([suiteOpen ? "rotated" : ""].filter(Boolean).join(" "))}`)}><polyline points="9 18 15 12 9 6" class="svelte-b4oiqy"></polyline></svg></button> <div class="suite-meta svelte-b4oiqy"><div class="suite-badges svelte-b4oiqy"><!--[-->`;
135
135
  for (let $$index_1 = 0, $$length2 = each_array_2.length; $$index_1 < $$length2; $$index_1++) {
136
136
  let id = each_array_2[$$index_1];
137
- $$payload.out += `<button${attr("class", `id-pill svelte-ll28r2 ${stringify([copiedIds.has(id) ? "copied" : ""].filter(Boolean).join(" "))}`)}${attr("title", copiedIds.has(id) ? copiedTitle(id) : copyTitle(id))}${attr("aria-label", copiedIds.has(id) ? copiedTitle(id) : copyTitle(id))}>${escape_html(id)}</button>`;
137
+ $$payload.out += `<button${attr("class", `id-pill svelte-b4oiqy ${stringify([copiedIds.has(id) ? "copied" : ""].filter(Boolean).join(" "))}`)}${attr("title", copiedIds.has(id) ? copiedTitle(id) : copyTitle(id))}${attr("aria-label", copiedIds.has(id) ? copiedTitle(id) : copyTitle(id))}>${escape_html(id)}</button>`;
138
138
  }
139
- $$payload.out += `<!--]--></div> <span class="suite-name svelte-ll28r2">${escape_html(suite.suiteName)}</span> <span class="suite-count svelte-ll28r2">${escape_html(testCountLabel(suite.tests.length))}</span></div> <button class="run-btn suite-run svelte-ll28r2"${attr("title", RUN_SUITE_LABEL)}><svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" stroke="none" class="svelte-ll28r2"><polygon points="5,3 19,12 5,21" class="svelte-ll28r2"></polygon></svg> ${escape_html(RUN_SUITE_LABEL)}</button></div> `;
139
+ $$payload.out += `<!--]--></div> <span class="suite-name svelte-b4oiqy">${escape_html(suite.suiteName)}</span> <span class="suite-count svelte-b4oiqy">${escape_html(testCountLabel(suite.tests.length))}</span></div> <button class="run-btn suite-run svelte-b4oiqy"${attr("title", RUN_SUITE_LABEL)}><svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" stroke="none" class="svelte-b4oiqy"><polygon points="5,3 19,12 5,21" class="svelte-b4oiqy"></polygon></svg> ${escape_html(RUN_SUITE_LABEL)}</button></div> `;
140
140
  if (suiteOpen) {
141
141
  $$payload.out += "<!--[-->";
142
142
  const each_array_3 = ensure_array_like(suite.tests);
143
- $$payload.out += `<div class="tests svelte-ll28r2"><!--[-->`;
143
+ $$payload.out += `<div class="tests svelte-b4oiqy"><!--[-->`;
144
144
  for (let ti = 0, $$length2 = each_array_3.length; ti < $$length2; ti++) {
145
145
  let test = each_array_3[ti];
146
146
  const pid = primaryId(test);
147
147
  const stepsOpen = expandedSteps.has(pid);
148
148
  const each_array_4 = ensure_array_like(testIds(test));
149
- $$payload.out += `<div class="test-row svelte-ll28r2"${attr("style", stagger(si * 4 + ti, 30))}><div class="test-main svelte-ll28r2"><button class="run-icon-btn svelte-ll28r2"${attr("title", runIdTitle(pid))}${attr("aria-label", runTestLabel(test.testCase))}><svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor" stroke="none" class="svelte-ll28r2"><polygon points="5,3 19,12 5,21" class="svelte-ll28r2"></polygon></svg></button> <div class="test-ids svelte-ll28r2"><!--[-->`;
149
+ $$payload.out += `<div class="test-row svelte-b4oiqy"${attr("style", stagger(si * 4 + ti, 30))}><div class="test-main svelte-b4oiqy"><button class="run-icon-btn svelte-b4oiqy"${attr("title", runIdTitle(pid))}${attr("aria-label", runTestLabel(test.testCase))}><svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor" stroke="none" class="svelte-b4oiqy"><polygon points="5,3 19,12 5,21" class="svelte-b4oiqy"></polygon></svg></button> <div class="test-ids svelte-b4oiqy"><!--[-->`;
150
150
  for (let $$index_2 = 0, $$length3 = each_array_4.length; $$index_2 < $$length3; $$index_2++) {
151
151
  let id = each_array_4[$$index_2];
152
- $$payload.out += `<button${attr("class", `id-pill svelte-ll28r2 ${stringify([copiedIds.has(id) ? "copied" : ""].filter(Boolean).join(" "))}`)}${attr("title", copiedIds.has(id) ? `Copied ${id}` : `Copy ${id}`)}${attr("aria-label", copiedIds.has(id) ? `Copied ${id}` : `Copy ${id}`)}>${escape_html(id)}</button>`;
152
+ $$payload.out += `<button${attr("class", `id-pill svelte-b4oiqy ${stringify([copiedIds.has(id) ? "copied" : ""].filter(Boolean).join(" "))}`)}${attr("title", copiedIds.has(id) ? `Copied ${id}` : `Copy ${id}`)}${attr("aria-label", copiedIds.has(id) ? `Copied ${id}` : `Copy ${id}`)}>${escape_html(id)}</button>`;
153
153
  }
154
- $$payload.out += `<!--]--></div> <span class="test-name svelte-ll28r2">${escape_html(test.testCase)} `;
154
+ $$payload.out += `<!--]--></div> <span class="test-name svelte-b4oiqy">${escape_html(test.testCase)} `;
155
155
  if (test.type === "outline") {
156
156
  $$payload.out += "<!--[-->";
157
- $$payload.out += `<span class="outline-badge svelte-ll28r2">${escape_html(OUTLINE_BADGE)}</span>`;
157
+ $$payload.out += `<span class="outline-badge svelte-b4oiqy">${escape_html(OUTLINE_BADGE)}</span>`;
158
158
  } else {
159
159
  $$payload.out += "<!--[!-->";
160
160
  }
161
161
  $$payload.out += `<!--]--></span> `;
162
162
  if (test.steps?.length > 0) {
163
163
  $$payload.out += "<!--[-->";
164
- $$payload.out += `<button class="steps-toggle svelte-ll28r2"${attr("aria-expanded", stepsOpen)}><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"${attr("class", `svelte-ll28r2 ${stringify([stepsOpen ? "rotated" : ""].filter(Boolean).join(" "))}`)}><polyline points="9 18 15 12 9 6" class="svelte-ll28r2"></polyline></svg> ${escape_html(stepsOpen ? HIDE_LABEL : STEPS_LABEL)}</button>`;
164
+ $$payload.out += `<button class="steps-toggle svelte-b4oiqy"${attr("aria-expanded", stepsOpen)}><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"${attr("class", `svelte-b4oiqy ${stringify([stepsOpen ? "rotated" : ""].filter(Boolean).join(" "))}`)}><polyline points="9 18 15 12 9 6" class="svelte-b4oiqy"></polyline></svg> ${escape_html(stepsOpen ? HIDE_LABEL : STEPS_LABEL)}</button>`;
165
165
  } else {
166
166
  $$payload.out += "<!--[!-->";
167
167
  }
@@ -169,29 +169,29 @@ function _page($$payload, $$props) {
169
169
  if (stepsOpen && test.steps?.length > 0) {
170
170
  $$payload.out += "<!--[-->";
171
171
  const each_array_5 = ensure_array_like(test.steps);
172
- $$payload.out += `<div class="steps svelte-ll28r2"><ol class="step-list svelte-ll28r2"><!--[-->`;
172
+ $$payload.out += `<div class="steps svelte-b4oiqy"><ol class="step-list svelte-b4oiqy"><!--[-->`;
173
173
  for (let $$index_3 = 0, $$length3 = each_array_5.length; $$index_3 < $$length3; $$index_3++) {
174
174
  let step = each_array_5[$$index_3];
175
- $$payload.out += `<li class="step svelte-ll28r2">${escape_html(step)}</li>`;
175
+ $$payload.out += `<li class="step svelte-b4oiqy">${escape_html(step)}</li>`;
176
176
  }
177
177
  $$payload.out += `<!--]--></ol> `;
178
178
  if (test.examples) {
179
179
  $$payload.out += "<!--[-->";
180
180
  const each_array_6 = ensure_array_like(test.examples.headers);
181
181
  const each_array_7 = ensure_array_like(test.examples.rows);
182
- $$payload.out += `<div class="examples svelte-ll28r2"><span class="examples-label svelte-ll28r2">${escape_html(EXAMPLES_LABEL)}</span> <div class="examples-table-wrap svelte-ll28r2"><table class="examples-table svelte-ll28r2"><thead class="svelte-ll28r2"><tr class="svelte-ll28r2"><!--[-->`;
182
+ $$payload.out += `<div class="examples svelte-b4oiqy"><span class="examples-label svelte-b4oiqy">${escape_html(EXAMPLES_LABEL)}</span> <div class="examples-table-wrap svelte-b4oiqy"><table class="examples-table svelte-b4oiqy"><thead class="svelte-b4oiqy"><tr class="svelte-b4oiqy"><!--[-->`;
183
183
  for (let $$index_4 = 0, $$length3 = each_array_6.length; $$index_4 < $$length3; $$index_4++) {
184
184
  let h = each_array_6[$$index_4];
185
- $$payload.out += `<th class="svelte-ll28r2">${escape_html(h)}</th>`;
185
+ $$payload.out += `<th class="svelte-b4oiqy">${escape_html(h)}</th>`;
186
186
  }
187
- $$payload.out += `<!--]--></tr></thead><tbody class="svelte-ll28r2"><!--[-->`;
187
+ $$payload.out += `<!--]--></tr></thead><tbody class="svelte-b4oiqy"><!--[-->`;
188
188
  for (let $$index_6 = 0, $$length3 = each_array_7.length; $$index_6 < $$length3; $$index_6++) {
189
189
  let row = each_array_7[$$index_6];
190
190
  const each_array_8 = ensure_array_like(row);
191
- $$payload.out += `<tr class="svelte-ll28r2"><!--[-->`;
191
+ $$payload.out += `<tr class="svelte-b4oiqy"><!--[-->`;
192
192
  for (let $$index_5 = 0, $$length4 = each_array_8.length; $$index_5 < $$length4; $$index_5++) {
193
193
  let cell = each_array_8[$$index_5];
194
- $$payload.out += `<td class="svelte-ll28r2">${escape_html(cell)}</td>`;
194
+ $$payload.out += `<td class="svelte-b4oiqy">${escape_html(cell)}</td>`;
195
195
  }
196
196
  $$payload.out += `<!--]--></tr>`;
197
197
  }
@@ -263,9 +263,9 @@ function _page($$payload, $$props) {
263
263
  {
264
264
  mcpServers: {
265
265
  plum: {
266
- command: "plum",
267
- args: ["mcp"],
268
- env: { PLUM_API_URL: API_BASE, PLUM_API_KEY: mcpKey }
266
+ type: "http",
267
+ url: `${API_BASE}/mcp`,
268
+ headers: { Authorization: `ApiKey ${mcpKey}` }
269
269
  }
270
270
  }
271
271
  },
@@ -15,7 +15,7 @@ return {
15
15
  assets: new Set(["favicon-32x32.png","favicon.ico"]),
16
16
  mimeTypes: {".png":"image/png"},
17
17
  _: {
18
- client: {start:"_app/immutable/entry/start.Bn25CW9X.js",app:"_app/immutable/entry/app.B0GH5ONo.js",imports:["_app/immutable/entry/start.Bn25CW9X.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/entry/app.B0GH5ONo.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/2zMvi6fR.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
18
+ client: {start:"_app/immutable/entry/start.4qxHHAcl.js",app:"_app/immutable/entry/app.KrtMZ3my.js",imports:["_app/immutable/entry/start.4qxHHAcl.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/entry/app.KrtMZ3my.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/2zMvi6fR.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
19
19
  nodes: [
20
20
  __memo(() => import('./nodes/0.js')),
21
21
  __memo(() => import('./nodes/1.js')),
@@ -15,7 +15,7 @@ return {
15
15
  assets: new Set(["favicon-32x32.png","favicon.ico"]),
16
16
  mimeTypes: {".png":"image/png"},
17
17
  _: {
18
- client: {start:"_app/immutable/entry/start.Bn25CW9X.js",app:"_app/immutable/entry/app.B0GH5ONo.js",imports:["_app/immutable/entry/start.Bn25CW9X.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/entry/app.B0GH5ONo.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/2zMvi6fR.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
18
+ client: {start:"_app/immutable/entry/start.4qxHHAcl.js",app:"_app/immutable/entry/app.KrtMZ3my.js",imports:["_app/immutable/entry/start.4qxHHAcl.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/entry/app.KrtMZ3my.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/2zMvi6fR.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
19
19
  nodes: [
20
20
  __memo(() => import('./nodes/0.js')),
21
21
  __memo(() => import('./nodes/1.js')),
@@ -10,6 +10,6 @@ let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/pages/_layout.svelte.js')).default;
11
11
  export { universal };
12
12
  export const universal_id = "src/routes/+layout.js";
13
- export const imports = ["_app/immutable/nodes/0.-imXt0f5.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/DEKAA-Fm.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/3InFPLvE.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/DbgD7JLa.js","_app/immutable/chunks/BUwxRmHf.js","_app/immutable/chunks/DSLBMEpr.js","_app/immutable/chunks/DMZwI8Cj.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CMEtqUfQ.js","_app/immutable/chunks/CuqnZUex.js","_app/immutable/chunks/BmZ9upwL.js"];
13
+ export const imports = ["_app/immutable/nodes/0.C8DodwXs.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/DDZw0L0T.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/3InFPLvE.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/DbgD7JLa.js","_app/immutable/chunks/BUwxRmHf.js","_app/immutable/chunks/DSLBMEpr.js","_app/immutable/chunks/DMZwI8Cj.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CMEtqUfQ.js","_app/immutable/chunks/CuqnZUex.js","_app/immutable/chunks/BmZ9upwL.js"];
14
14
  export const stylesheets = ["_app/immutable/assets/0.BhSG-jZH.css","_app/immutable/assets/ConfirmModal.Dd3uP-Sk.css","_app/immutable/assets/Modal.BZpm0HP8.css","_app/immutable/assets/Badge.D1SV0Gv7.css"];
15
15
  export const fonts = [];
@@ -8,6 +8,6 @@
8
8
  export const index = 1;
9
9
  let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/fallbacks/error.svelte.js')).default;
11
- export const imports = ["_app/immutable/nodes/1.Dom3CKWF.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/Dhf4xQKo.js"];
11
+ export const imports = ["_app/immutable/nodes/1.Df9sLw8b.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/kkA1mrsH.js"];
12
12
  export const stylesheets = [];
13
13
  export const fonts = [];
@@ -8,6 +8,6 @@
8
8
  export const index = 11;
9
9
  let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/pages/test-repository/runs/_id_/_page.svelte.js')).default;
11
- export const imports = ["_app/immutable/nodes/11.DMlayLCK.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/CzlPaHY9.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CNdcuGR0.js","_app/immutable/chunks/DEKAA-Fm.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/BUwxRmHf.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/CMEtqUfQ.js","_app/immutable/chunks/BKuh57WU.js","_app/immutable/chunks/BAMUGSh7.js"];
11
+ export const imports = ["_app/immutable/nodes/11.BViaDK2m.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/CzlPaHY9.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CNdcuGR0.js","_app/immutable/chunks/DDZw0L0T.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/BUwxRmHf.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/CMEtqUfQ.js","_app/immutable/chunks/BKuh57WU.js","_app/immutable/chunks/BAMUGSh7.js"];
12
12
  export const stylesheets = ["_app/immutable/assets/11.BWAH0Beh.css","_app/immutable/assets/Button.FOWXxvc7.css","_app/immutable/assets/Modal.BZpm0HP8.css","_app/immutable/assets/EmptyState.DUDM4P19.css"];
13
13
  export const fonts = [];
@@ -8,6 +8,6 @@
8
8
  export const index = 12;
9
9
  let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/pages/test-repository/suites/_id_/_page.svelte.js')).default;
11
- export const imports = ["_app/immutable/nodes/12.Bu89A1eX.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/CzlPaHY9.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CNdcuGR0.js","_app/immutable/chunks/Bfc47y5P.js","_app/immutable/chunks/DEKAA-Fm.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/BUwxRmHf.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/BKuh57WU.js","_app/immutable/chunks/DMZwI8Cj.js","_app/immutable/chunks/CMEtqUfQ.js","_app/immutable/chunks/w0D4Uzlq.js","_app/immutable/chunks/BAMUGSh7.js"];
11
+ export const imports = ["_app/immutable/nodes/12.BMSCSd88.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/CzlPaHY9.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CNdcuGR0.js","_app/immutable/chunks/Bfc47y5P.js","_app/immutable/chunks/DDZw0L0T.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/BUwxRmHf.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/BKuh57WU.js","_app/immutable/chunks/DMZwI8Cj.js","_app/immutable/chunks/CMEtqUfQ.js","_app/immutable/chunks/w0D4Uzlq.js","_app/immutable/chunks/BAMUGSh7.js"];
12
12
  export const stylesheets = ["_app/immutable/assets/12.Bj_a_5lv.css","_app/immutable/assets/Button.FOWXxvc7.css","_app/immutable/assets/EmptyState.DUDM4P19.css","_app/immutable/assets/ConfirmModal.Dd3uP-Sk.css","_app/immutable/assets/Modal.BZpm0HP8.css","_app/immutable/assets/Pagination.DZmi2Po-.css"];
13
13
  export const fonts = [];
@@ -8,6 +8,6 @@
8
8
  export const index = 2;
9
9
  let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/pages/_page.svelte.js')).default;
11
- export const imports = ["_app/immutable/nodes/2.BnHalSCi.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/DSLBMEpr.js","_app/immutable/chunks/BKuh57WU.js","_app/immutable/chunks/C8OURRSs.js"];
12
- export const stylesheets = ["_app/immutable/assets/2.DvMkmYA-.css","_app/immutable/assets/EmptyState.DUDM4P19.css"];
11
+ export const imports = ["_app/immutable/nodes/2.BCPSg7H4.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/DSLBMEpr.js","_app/immutable/chunks/BKuh57WU.js","_app/immutable/chunks/C8OURRSs.js"];
12
+ export const stylesheets = ["_app/immutable/assets/2.C1TbMUws.css","_app/immutable/assets/EmptyState.DUDM4P19.css"];
13
13
  export const fonts = [];
@@ -8,6 +8,6 @@
8
8
  export const index = 3;
9
9
  let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/pages/login/_page.svelte.js')).default;
11
- export const imports = ["_app/immutable/nodes/3.B86rlHXU.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/BmZ9upwL.js","_app/immutable/chunks/DCgHuuvs.js","_app/immutable/chunks/Dlnxgs49.js"];
11
+ export const imports = ["_app/immutable/nodes/3.8BFAJoHT.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/BmZ9upwL.js","_app/immutable/chunks/DCgHuuvs.js","_app/immutable/chunks/Dlnxgs49.js"];
12
12
  export const stylesheets = ["_app/immutable/assets/3.BR3wgXcZ.css"];
13
13
  export const fonts = [];
@@ -8,6 +8,6 @@
8
8
  export const index = 5;
9
9
  let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/pages/reports/_id_/_page.svelte.js')).default;
11
- export const imports = ["_app/immutable/nodes/5.CqTXvadV.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/Bfc47y5P.js","_app/immutable/chunks/CNdcuGR0.js","_app/immutable/chunks/DEKAA-Fm.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/DbgD7JLa.js","_app/immutable/chunks/DSLBMEpr.js","_app/immutable/chunks/Co3xKhEp.js","_app/immutable/chunks/CuqnZUex.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CGeZlCaI.js"];
11
+ export const imports = ["_app/immutable/nodes/5.DVeH2eQP.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/Bfc47y5P.js","_app/immutable/chunks/CNdcuGR0.js","_app/immutable/chunks/DDZw0L0T.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/DbgD7JLa.js","_app/immutable/chunks/DSLBMEpr.js","_app/immutable/chunks/Co3xKhEp.js","_app/immutable/chunks/CuqnZUex.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CGeZlCaI.js"];
12
12
  export const stylesheets = ["_app/immutable/assets/5.DFV9OgAu.css","_app/immutable/assets/Badge.D1SV0Gv7.css","_app/immutable/assets/BackLink.CvWWuO3h.css"];
13
13
  export const fonts = [];
@@ -8,6 +8,6 @@
8
8
  export const index = 6;
9
9
  let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/pages/reports/live/_page.svelte.js')).default;
11
- export const imports = ["_app/immutable/nodes/6.BJZ62MCd.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/2zMvi6fR.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/DEKAA-Fm.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/DbgD7JLa.js","_app/immutable/chunks/Co3xKhEp.js","_app/immutable/chunks/DSLBMEpr.js","_app/immutable/chunks/CGeZlCaI.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CuqnZUex.js"];
11
+ export const imports = ["_app/immutable/nodes/6.DI7-IJhN.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/2zMvi6fR.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/DDZw0L0T.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/DbgD7JLa.js","_app/immutable/chunks/Co3xKhEp.js","_app/immutable/chunks/DSLBMEpr.js","_app/immutable/chunks/CGeZlCaI.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CuqnZUex.js"];
12
12
  export const stylesheets = ["_app/immutable/assets/6.CFnbmY-D.css","_app/immutable/assets/BackLink.CvWWuO3h.css","_app/immutable/assets/Badge.D1SV0Gv7.css"];
13
13
  export const fonts = [];
@@ -8,6 +8,6 @@
8
8
  export const index = 8;
9
9
  let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/pages/settings/_page.svelte.js')).default;
11
- export const imports = ["_app/immutable/nodes/8.B4fj2Xyu.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/CzlPaHY9.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CNdcuGR0.js","_app/immutable/chunks/2zMvi6fR.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/3InFPLvE.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/BUwxRmHf.js","_app/immutable/chunks/BmZ9upwL.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/DCgHuuvs.js","_app/immutable/chunks/DMZwI8Cj.js","_app/immutable/chunks/CMEtqUfQ.js","_app/immutable/chunks/CuqnZUex.js"];
11
+ export const imports = ["_app/immutable/nodes/8.93Mb3ofT.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/TOCyHP97.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/CzlPaHY9.js","_app/immutable/chunks/C8OURRSs.js","_app/immutable/chunks/CNdcuGR0.js","_app/immutable/chunks/2zMvi6fR.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/3InFPLvE.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/BUwxRmHf.js","_app/immutable/chunks/BmZ9upwL.js","_app/immutable/chunks/DHM6H-es.js","_app/immutable/chunks/DCgHuuvs.js","_app/immutable/chunks/DMZwI8Cj.js","_app/immutable/chunks/CMEtqUfQ.js","_app/immutable/chunks/CuqnZUex.js"];
12
12
  export const stylesheets = ["_app/immutable/assets/8.BwgOqeMo.css","_app/immutable/assets/Button.FOWXxvc7.css","_app/immutable/assets/ConfirmModal.Dd3uP-Sk.css","_app/immutable/assets/Modal.BZpm0HP8.css","_app/immutable/assets/Badge.D1SV0Gv7.css"];
13
13
  export const fonts = [];
@@ -8,6 +8,6 @@
8
8
  export const index = 9;
9
9
  let component_cache;
10
10
  export const component = async () => component_cache ??= (await import('../entries/pages/setup/_page.svelte.js')).default;
11
- export const imports = ["_app/immutable/nodes/9.C57_2xq6.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/Dhf4xQKo.js","_app/immutable/chunks/BmZ9upwL.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/DCgHuuvs.js","_app/immutable/chunks/Dlnxgs49.js"];
11
+ export const imports = ["_app/immutable/nodes/9.CvfGx3Hu.js","_app/immutable/chunks/CMBQQ9RZ.js","_app/immutable/chunks/BAACMRH5.js","_app/immutable/chunks/CKDtmZUQ.js","_app/immutable/chunks/CgnwuKKO.js","_app/immutable/chunks/CUC98kMZ.js","_app/immutable/chunks/t-La0hgu.js","_app/immutable/chunks/kkA1mrsH.js","_app/immutable/chunks/BmZ9upwL.js","_app/immutable/chunks/C1Vid6wz.js","_app/immutable/chunks/DCgHuuvs.js","_app/immutable/chunks/Dlnxgs49.js"];
12
12
  export const stylesheets = ["_app/immutable/assets/9._h2o67kg.css"];
13
13
  export const fonts = [];
@@ -31,6 +31,7 @@
31
31
  * ```
32
32
  */
33
33
  declare module '$env/static/private' {
34
+ export const CLAUDE_CODE_MESSAGING_TOKEN: string;
34
35
  export const NoDefaultCurrentDirectoryInExePath: string;
35
36
  export const CLAUDE_EFFORT: string;
36
37
  export const CLAUDE_CODE_ENTRYPOINT: string;
@@ -101,6 +102,7 @@ declare module '$env/static/private' {
101
102
  export const GIT_ASKPASS: string;
102
103
  export const OSLogRateLimit: string;
103
104
  export const CLAUDECODE: string;
105
+ export const CLAUDE_CODE_MESSAGING_SOCKET: string;
104
106
  export const npm_node_execpath: string;
105
107
  export const npm_config_prefix: string;
106
108
  export const COLORTERM: string;
@@ -136,6 +138,7 @@ declare module '$env/static/public' {
136
138
  */
137
139
  declare module '$env/dynamic/private' {
138
140
  export const env: {
141
+ CLAUDE_CODE_MESSAGING_TOKEN: string;
139
142
  NoDefaultCurrentDirectoryInExePath: string;
140
143
  CLAUDE_EFFORT: string;
141
144
  CLAUDE_CODE_ENTRYPOINT: string;
@@ -206,6 +209,7 @@ declare module '$env/dynamic/private' {
206
209
  GIT_ASKPASS: string;
207
210
  OSLogRateLimit: string;
208
211
  CLAUDECODE: string;
212
+ CLAUDE_CODE_MESSAGING_SOCKET: string;
209
213
  npm_node_execpath: string;
210
214
  npm_config_prefix: string;
211
215
  COLORTERM: string;
@@ -26,7 +26,7 @@ export const options = {
26
26
  app: ({ head, body, assets, nonce, env }) => "<!--\nThis file is part of Plum.\nLicensed under the MIT License. See LICENSE file in the project root for details.\n-->\n<!doctype html>\n<html lang=\"en\" data-theme=\"light\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<link rel=\"icon\" href=\"" + assets + "/favicon.ico\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t\t<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n\t\t<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n\t\t<link\n\t\t\thref=\"https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500&family=DM+Sans:wght@300;400;500&display=swap\"\n\t\t\trel=\"stylesheet\"\n\t\t/>\n\t\t<!-- Prevent theme flash before Svelte hydrates -->\n\t\t<script>\n\t\t\ttry {\n\t\t\t\tconst t = localStorage.getItem('plum-theme');\n\t\t\t\tif (t) document.documentElement.setAttribute('data-theme', t);\n\t\t\t} catch (e) {}\n\t\t</script>\n\t\t" + head + "\n\t</head>\n\t<body data-sveltekit-preload-data=\"hover\">\n\t\t<div style=\"display: contents\">" + body + "</div>\n\t</body>\n</html>\n",
27
27
  error: ({ status, message }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>" + message + "</title>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\t--bg: white;\n\t\t\t\t--fg: #222;\n\t\t\t\t--divider: #ccc;\n\t\t\t\tbackground: var(--bg);\n\t\t\t\tcolor: var(--fg);\n\t\t\t\tfont-family:\n\t\t\t\t\tsystem-ui,\n\t\t\t\t\t-apple-system,\n\t\t\t\t\tBlinkMacSystemFont,\n\t\t\t\t\t'Segoe UI',\n\t\t\t\t\tRoboto,\n\t\t\t\t\tOxygen,\n\t\t\t\t\tUbuntu,\n\t\t\t\t\tCantarell,\n\t\t\t\t\t'Open Sans',\n\t\t\t\t\t'Helvetica Neue',\n\t\t\t\t\tsans-serif;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.error {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tmax-width: 32rem;\n\t\t\t\tmargin: 0 1rem;\n\t\t\t}\n\n\t\t\t.status {\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-size: 3rem;\n\t\t\t\tline-height: 1;\n\t\t\t\tposition: relative;\n\t\t\t\ttop: -0.05rem;\n\t\t\t}\n\n\t\t\t.message {\n\t\t\t\tborder-left: 1px solid var(--divider);\n\t\t\t\tpadding: 0 0 0 1rem;\n\t\t\t\tmargin: 0 0 0 1rem;\n\t\t\t\tmin-height: 2.5rem;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t}\n\n\t\t\t.message h1 {\n\t\t\t\tfont-weight: 400;\n\t\t\t\tfont-size: 1em;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbody {\n\t\t\t\t\t--bg: #222;\n\t\t\t\t\t--fg: #ddd;\n\t\t\t\t\t--divider: #666;\n\t\t\t\t}\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div class=\"error\">\n\t\t\t<span class=\"status\">" + status + "</span>\n\t\t\t<div class=\"message\">\n\t\t\t\t<h1>" + message + "</h1>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
28
28
  },
29
- version_hash: "1m6qzpt"
29
+ version_hash: "19o4i41"
30
30
  };
31
31
 
32
32
  export async function get_hooks() {