watch-tail 0.6.2 → 0.8.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 (275) hide show
  1. package/README.md +37 -15
  2. package/build/client/_app/immutable/assets/0.zDk3x0WE.css +2 -0
  3. package/build/client/_app/immutable/assets/0.zDk3x0WE.css.br +0 -0
  4. package/build/client/_app/immutable/assets/0.zDk3x0WE.css.gz +0 -0
  5. package/build/client/_app/immutable/assets/{EventScatter.DA5sZ1c0.css → EventScatter.CCk6ByS3.css} +1 -1
  6. package/build/client/_app/immutable/assets/EventScatter.CCk6ByS3.css.br +0 -0
  7. package/build/client/_app/immutable/assets/EventScatter.CCk6ByS3.css.gz +0 -0
  8. package/build/client/_app/immutable/chunks/{8x_7TBuS.js → 9z7cmAWt.js} +1 -1
  9. package/build/client/_app/immutable/chunks/9z7cmAWt.js.br +0 -0
  10. package/build/client/_app/immutable/chunks/9z7cmAWt.js.gz +0 -0
  11. package/build/client/_app/immutable/chunks/{D1Hr4tKw.js → B26Z2DQX.js} +1 -1
  12. package/build/client/_app/immutable/chunks/B26Z2DQX.js.br +0 -0
  13. package/build/client/_app/immutable/chunks/B26Z2DQX.js.gz +0 -0
  14. package/build/client/_app/immutable/chunks/{KA1QvXmu.js → B5kJ4QGS.js} +1 -1
  15. package/build/client/_app/immutable/chunks/B5kJ4QGS.js.br +0 -0
  16. package/build/client/_app/immutable/chunks/B5kJ4QGS.js.gz +0 -0
  17. package/build/client/_app/immutable/chunks/{sf5kQ3yV.js → BF1MBUT7.js} +1 -1
  18. package/build/client/_app/immutable/chunks/BF1MBUT7.js.br +0 -0
  19. package/build/client/_app/immutable/chunks/BF1MBUT7.js.gz +0 -0
  20. package/build/client/_app/immutable/chunks/{F4LqKrLs.js → BJEa1AAY.js} +5 -5
  21. package/build/client/_app/immutable/chunks/BJEa1AAY.js.br +0 -0
  22. package/build/client/_app/immutable/chunks/BJEa1AAY.js.gz +0 -0
  23. package/build/client/_app/immutable/chunks/{w7c5E2ms.js → BKpbhYu9.js} +1 -1
  24. package/build/client/_app/immutable/chunks/BKpbhYu9.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/BKpbhYu9.js.gz +0 -0
  26. package/build/client/_app/immutable/chunks/{DtV-MjyX.js → BVlqiKgb.js} +1 -1
  27. package/build/client/_app/immutable/chunks/BVlqiKgb.js.br +0 -0
  28. package/build/client/_app/immutable/chunks/BVlqiKgb.js.gz +0 -0
  29. package/build/client/_app/immutable/chunks/{DWm-CGbg.js → BWGaSL1l.js} +1 -1
  30. package/build/client/_app/immutable/chunks/BWGaSL1l.js.br +0 -0
  31. package/build/client/_app/immutable/chunks/BWGaSL1l.js.gz +0 -0
  32. package/build/client/_app/immutable/chunks/{BNDRPiSt.js → B_Z4tBMl.js} +1 -1
  33. package/build/client/_app/immutable/chunks/B_Z4tBMl.js.br +0 -0
  34. package/build/client/_app/immutable/chunks/B_Z4tBMl.js.gz +0 -0
  35. package/build/client/_app/immutable/chunks/{BWDKMHXq.js → Bo46v6NJ.js} +1 -1
  36. package/build/client/_app/immutable/chunks/Bo46v6NJ.js.br +0 -0
  37. package/build/client/_app/immutable/chunks/Bo46v6NJ.js.gz +0 -0
  38. package/build/client/_app/immutable/chunks/{BKpsnTLG.js → BpDPh_kG.js} +1 -1
  39. package/build/client/_app/immutable/chunks/BpDPh_kG.js.br +0 -0
  40. package/build/client/_app/immutable/chunks/BpDPh_kG.js.gz +0 -0
  41. package/build/client/_app/immutable/chunks/{DQCjzVyz.js → BzFqst10.js} +1 -1
  42. package/build/client/_app/immutable/chunks/BzFqst10.js.br +0 -0
  43. package/build/client/_app/immutable/chunks/BzFqst10.js.gz +0 -0
  44. package/build/client/_app/immutable/chunks/{KsLFdNDs.js → C3JYac4u.js} +1 -1
  45. package/build/client/_app/immutable/chunks/C3JYac4u.js.br +0 -0
  46. package/build/client/_app/immutable/chunks/C3JYac4u.js.gz +0 -0
  47. package/build/client/_app/immutable/chunks/{CG0TPRkn.js → CBzF0p8K.js} +1 -1
  48. package/build/client/_app/immutable/chunks/CBzF0p8K.js.br +0 -0
  49. package/build/client/_app/immutable/chunks/CBzF0p8K.js.gz +0 -0
  50. package/build/client/_app/immutable/chunks/{1cmfrS0o.js → CM9QBz5w.js} +1 -1
  51. package/build/client/_app/immutable/chunks/CM9QBz5w.js.br +0 -0
  52. package/build/client/_app/immutable/chunks/CM9QBz5w.js.gz +0 -0
  53. package/build/client/_app/immutable/chunks/{DznDQzx1.js → CZqQKfBo.js} +1 -1
  54. package/build/client/_app/immutable/chunks/CZqQKfBo.js.br +0 -0
  55. package/build/client/_app/immutable/chunks/CZqQKfBo.js.gz +0 -0
  56. package/build/client/_app/immutable/chunks/Cr-NovV3.js +5 -0
  57. package/build/client/_app/immutable/chunks/Cr-NovV3.js.br +0 -0
  58. package/build/client/_app/immutable/chunks/Cr-NovV3.js.gz +0 -0
  59. package/build/client/_app/immutable/chunks/{DqJI6J5U.js → Cz6pnyFa.js} +1 -1
  60. package/build/client/_app/immutable/chunks/Cz6pnyFa.js.br +0 -0
  61. package/build/client/_app/immutable/chunks/Cz6pnyFa.js.gz +0 -0
  62. package/build/client/_app/immutable/chunks/{CBRk0OGa.js → D2fsDTN5.js} +1 -1
  63. package/build/client/_app/immutable/chunks/D2fsDTN5.js.br +0 -0
  64. package/build/client/_app/immutable/chunks/D2fsDTN5.js.gz +0 -0
  65. package/build/client/_app/immutable/chunks/{CpeJ2iPd.js → DBcd9YbV.js} +1 -1
  66. package/build/client/_app/immutable/chunks/DBcd9YbV.js.br +0 -0
  67. package/build/client/_app/immutable/chunks/DBcd9YbV.js.gz +0 -0
  68. package/build/client/_app/immutable/chunks/{OoMmWNOu.js → DC_milOQ.js} +1 -1
  69. package/build/client/_app/immutable/chunks/DC_milOQ.js.br +0 -0
  70. package/build/client/_app/immutable/chunks/DC_milOQ.js.gz +0 -0
  71. package/build/client/_app/immutable/chunks/{CIDBs8t6.js → DNiEIfDZ.js} +1 -1
  72. package/build/client/_app/immutable/chunks/DNiEIfDZ.js.br +0 -0
  73. package/build/client/_app/immutable/chunks/DNiEIfDZ.js.gz +0 -0
  74. package/build/client/_app/immutable/chunks/{Dc9It0QB.js → DWdskt_Y.js} +1 -1
  75. package/build/client/_app/immutable/chunks/DWdskt_Y.js.br +0 -0
  76. package/build/client/_app/immutable/chunks/DWdskt_Y.js.gz +0 -0
  77. package/build/client/_app/immutable/chunks/{DYDQbI6D.js → DsMQ6HVM.js} +1 -1
  78. package/build/client/_app/immutable/chunks/DsMQ6HVM.js.br +0 -0
  79. package/build/client/_app/immutable/chunks/DsMQ6HVM.js.gz +0 -0
  80. package/build/client/_app/immutable/chunks/Dxeyu30B.js +1 -0
  81. package/build/client/_app/immutable/chunks/Dxeyu30B.js.br +1 -0
  82. package/build/client/_app/immutable/chunks/Dxeyu30B.js.gz +0 -0
  83. package/build/client/_app/immutable/chunks/{CfPyeeq3.js → H4Anb6kP.js} +1 -1
  84. package/build/client/_app/immutable/chunks/H4Anb6kP.js.br +0 -0
  85. package/build/client/_app/immutable/chunks/H4Anb6kP.js.gz +0 -0
  86. package/build/client/_app/immutable/chunks/MDK8mPOo.js +1 -0
  87. package/build/client/_app/immutable/chunks/MDK8mPOo.js.br +0 -0
  88. package/build/client/_app/immutable/chunks/MDK8mPOo.js.gz +0 -0
  89. package/build/client/_app/immutable/chunks/{D0IrjYE5.js → X7CLxGgV.js} +1 -1
  90. package/build/client/_app/immutable/chunks/X7CLxGgV.js.br +0 -0
  91. package/build/client/_app/immutable/chunks/X7CLxGgV.js.gz +0 -0
  92. package/build/client/_app/immutable/chunks/{D6rwn6Ed.js → cK-f5ch_.js} +1 -1
  93. package/build/client/_app/immutable/chunks/cK-f5ch_.js.br +2 -0
  94. package/build/client/_app/immutable/chunks/cK-f5ch_.js.gz +0 -0
  95. package/build/client/_app/immutable/chunks/{UsO0MS14.js → mhYP0ygJ.js} +1 -1
  96. package/build/client/_app/immutable/chunks/mhYP0ygJ.js.br +0 -0
  97. package/build/client/_app/immutable/chunks/mhYP0ygJ.js.gz +0 -0
  98. package/build/client/_app/immutable/chunks/{AAWh0-tL.js → vB0ff9Sn.js} +1 -1
  99. package/build/client/_app/immutable/chunks/vB0ff9Sn.js.br +0 -0
  100. package/build/client/_app/immutable/chunks/vB0ff9Sn.js.gz +0 -0
  101. package/build/client/_app/immutable/entry/{app.FQLd-NC-.js → app.CinEZGkq.js} +2 -2
  102. package/build/client/_app/immutable/entry/app.CinEZGkq.js.br +0 -0
  103. package/build/client/_app/immutable/entry/app.CinEZGkq.js.gz +0 -0
  104. package/build/client/_app/immutable/entry/start.B7e0-3Hk.js +1 -0
  105. package/build/client/_app/immutable/entry/start.B7e0-3Hk.js.br +1 -0
  106. package/build/client/_app/immutable/entry/start.B7e0-3Hk.js.gz +0 -0
  107. package/build/client/_app/immutable/nodes/{0.BN3NguWs.js → 0.CFO0Fthy.js} +1 -1
  108. package/build/client/_app/immutable/nodes/0.CFO0Fthy.js.br +0 -0
  109. package/build/client/_app/immutable/nodes/{0.BN3NguWs.js.gz → 0.CFO0Fthy.js.gz} +0 -0
  110. package/build/client/_app/immutable/nodes/{1.5EZfoLCg.js → 1.kGO9dV9J.js} +1 -1
  111. package/build/client/_app/immutable/nodes/1.kGO9dV9J.js.br +0 -0
  112. package/build/client/_app/immutable/nodes/1.kGO9dV9J.js.gz +0 -0
  113. package/build/client/_app/immutable/nodes/2.eGSziRQX.js +5 -0
  114. package/build/client/_app/immutable/nodes/2.eGSziRQX.js.br +0 -0
  115. package/build/client/_app/immutable/nodes/2.eGSziRQX.js.gz +0 -0
  116. package/build/client/_app/version.json +1 -1
  117. package/build/client/_app/version.json.br +0 -0
  118. package/build/client/_app/version.json.gz +0 -0
  119. package/build/handler.js +4 -4
  120. package/build/index.js +4 -4
  121. package/build/server/chunks/chunks/{EventScatter.js-D3Jaw_Cw.js → EventScatter.js-CG0RcOU6.js} +82 -20
  122. package/build/server/chunks/chunks/{EventScatter.js-D3Jaw_Cw.js.map → EventScatter.js-CG0RcOU6.js.map} +1 -1
  123. package/build/server/chunks/chunks/{archive.js-C2D-5edp.js → archive.js-D2jtMmDo.js} +134 -26
  124. package/build/server/chunks/chunks/archive.js-D2jtMmDo.js.map +1 -0
  125. package/build/server/chunks/chunks/{aws.js-DkPqAybc.js → env2.js-C5BgBJDY.js} +63 -6
  126. package/build/server/chunks/chunks/env2.js-C5BgBJDY.js.map +1 -0
  127. package/build/server/chunks/chunks/identity.js-NmGXxBz3.js +22 -0
  128. package/build/server/chunks/chunks/identity.js-NmGXxBz3.js.map +1 -0
  129. package/build/server/chunks/chunks/{internal2.js-627EG4am.js → internal2.js-BMcEVxqN.js} +2 -2
  130. package/build/server/chunks/chunks/{internal2.js-627EG4am.js.map → internal2.js-BMcEVxqN.js.map} +1 -1
  131. package/build/server/chunks/chunks/{level-filter.js-B3o2hyWD.js → level-filter.js-D9MNrew3.js} +2 -2
  132. package/build/server/chunks/chunks/{level-filter.js-B3o2hyWD.js.map → level-filter.js-D9MNrew3.js.map} +1 -1
  133. package/build/server/chunks/chunks/{log-buffer.js-BI_gQOls.js → log-buffer.js-A9FA-Qv8.js} +18 -3
  134. package/build/server/chunks/chunks/log-buffer.js-A9FA-Qv8.js.map +1 -0
  135. package/build/server/chunks/chunks/{regions.js-IQPMyP5C.js → regions.js-COf7DgnH.js} +3 -3
  136. package/build/server/chunks/chunks/regions.js-COf7DgnH.js.map +1 -0
  137. package/build/server/chunks/chunks/{series-buckets.js-BjigySff.js → series-buckets.js-DFGWkob5.js} +34 -8
  138. package/build/server/chunks/chunks/series-buckets.js-DFGWkob5.js.map +1 -0
  139. package/build/server/chunks/chunks/{state.js-DbqJPX0Y.js → state.js-vZj9lo1I.js} +2 -2
  140. package/build/server/chunks/chunks/{state.js-DbqJPX0Y.js.map → state.js-vZj9lo1I.js.map} +1 -1
  141. package/build/server/chunks/entries/endpoints/api/archive/{_server.ts.js-83Ch7djd.js → _server.ts.js-C4hWyXuu.js} +17 -9
  142. package/build/server/chunks/entries/endpoints/api/archive/_server.ts.js-C4hWyXuu.js.map +1 -0
  143. package/build/server/chunks/entries/endpoints/api/health/{_server.ts.js-VctnBhIJ.js → _server.ts.js-C5tfrpmC.js} +4 -5
  144. package/build/server/chunks/entries/endpoints/api/health/_server.ts.js-C5tfrpmC.js.map +1 -0
  145. package/build/server/chunks/entries/endpoints/api/identity/{_server.ts.js-Dt540Sio.js → _server.ts.js-PWRPScuN.js} +6 -24
  146. package/build/server/chunks/entries/endpoints/api/identity/_server.ts.js-PWRPScuN.js.map +1 -0
  147. package/build/server/chunks/entries/endpoints/api/log-groups/{_server.ts.js-drLgUdvB.js → _server.ts.js-D4y43Vwe.js} +14 -11
  148. package/build/server/chunks/entries/endpoints/api/log-groups/_server.ts.js-D4y43Vwe.js.map +1 -0
  149. package/build/server/chunks/entries/endpoints/api/regions/{_server.ts.js-CBqfN6Pg.js → _server.ts.js-9_g0ojki.js} +8 -9
  150. package/build/server/chunks/entries/endpoints/api/regions/_server.ts.js-9_g0ojki.js.map +1 -0
  151. package/build/server/chunks/entries/endpoints/api/series/{_server.ts.js-DOvBhEDU.js → _server.ts.js-DibT3Hjc.js} +34 -16
  152. package/build/server/chunks/entries/endpoints/api/series/_server.ts.js-DibT3Hjc.js.map +1 -0
  153. package/build/server/chunks/entries/endpoints/api/stream/{_server.ts.js-B9_-4ssJ.js → _server.ts.js-BxXw5K0R.js} +32 -20
  154. package/build/server/chunks/entries/endpoints/api/stream/_server.ts.js-BxXw5K0R.js.map +1 -0
  155. package/build/server/chunks/entries/fallbacks/{error.svelte.js-B8dLO9gT.js → error.svelte.js-bokc4skC.js} +3 -3
  156. package/build/server/chunks/entries/fallbacks/{error.svelte.js-B8dLO9gT.js.map → error.svelte.js-bokc4skC.js.map} +1 -1
  157. package/build/server/chunks/entries/pages/{_layout.svelte.js-CBQpEToy.js → _layout.svelte.js-8U7ZeKYO.js} +3 -3
  158. package/build/server/chunks/entries/pages/_layout.svelte.js-8U7ZeKYO.js.map +1 -0
  159. package/build/server/chunks/entries/pages/{_page.svelte.js-BwuzE25P.js → _page.svelte.js-DRoSEPVH.js} +149 -41
  160. package/build/server/chunks/entries/pages/_page.svelte.js-DRoSEPVH.js.map +1 -0
  161. package/build/server/chunks/{handler-hlKcUyVP.js → handler-BkYErjbr.js} +3 -3
  162. package/build/server/chunks/{handler-hlKcUyVP.js.map → handler-BkYErjbr.js.map} +1 -1
  163. package/build/server/chunks/{index.js-BfPWKsz6.js → index.js-5mkIDcpy.js} +2 -2
  164. package/build/server/chunks/{index.js-BfPWKsz6.js.map → index.js-5mkIDcpy.js.map} +1 -1
  165. package/build/server/chunks/{manifest.js-uuijI5lm.js → manifest.js-BGoS-vRx.js} +12 -12
  166. package/build/server/chunks/{manifest.js-uuijI5lm.js.map → manifest.js-BGoS-vRx.js.map} +1 -1
  167. package/build/server/chunks/nodes/{0.js-CNFDDPj5.js → 0.js-BIj6k30n.js} +4 -4
  168. package/build/server/chunks/nodes/{0.js-CNFDDPj5.js.map → 0.js-BIj6k30n.js.map} +1 -1
  169. package/build/server/chunks/nodes/{1.js-bi9PXX_2.js → 1.js-BQibx33b.js} +3 -3
  170. package/build/server/chunks/nodes/{1.js-bi9PXX_2.js.map → 1.js-BQibx33b.js.map} +1 -1
  171. package/build/server/chunks/nodes/{2.js-3MYCPEqM.js → 2.js-CczDSPv9.js} +4 -4
  172. package/build/server/chunks/nodes/{2.js-3MYCPEqM.js.map → 2.js-CczDSPv9.js.map} +1 -1
  173. package/dist/cli/index.js +13 -6
  174. package/dist/cli/options.js +1 -1
  175. package/dist/cli/server.js +19 -4
  176. package/dist/lib/cli/aws.js +4 -4
  177. package/dist/lib/log-buffer.js +1 -1
  178. package/package.json +6 -6
  179. package/build/client/_app/immutable/assets/0.Dfts6BC4.css +0 -2
  180. package/build/client/_app/immutable/assets/0.Dfts6BC4.css.br +0 -0
  181. package/build/client/_app/immutable/assets/0.Dfts6BC4.css.gz +0 -0
  182. package/build/client/_app/immutable/assets/EventScatter.DA5sZ1c0.css.br +0 -0
  183. package/build/client/_app/immutable/assets/EventScatter.DA5sZ1c0.css.gz +0 -0
  184. package/build/client/_app/immutable/chunks/1cmfrS0o.js.br +0 -0
  185. package/build/client/_app/immutable/chunks/1cmfrS0o.js.gz +0 -0
  186. package/build/client/_app/immutable/chunks/8x_7TBuS.js.br +0 -0
  187. package/build/client/_app/immutable/chunks/8x_7TBuS.js.gz +0 -0
  188. package/build/client/_app/immutable/chunks/AAWh0-tL.js.br +0 -0
  189. package/build/client/_app/immutable/chunks/AAWh0-tL.js.gz +0 -0
  190. package/build/client/_app/immutable/chunks/BKpsnTLG.js.br +0 -0
  191. package/build/client/_app/immutable/chunks/BKpsnTLG.js.gz +0 -0
  192. package/build/client/_app/immutable/chunks/BNDRPiSt.js.br +0 -0
  193. package/build/client/_app/immutable/chunks/BNDRPiSt.js.gz +0 -0
  194. package/build/client/_app/immutable/chunks/BWDKMHXq.js.br +0 -0
  195. package/build/client/_app/immutable/chunks/BWDKMHXq.js.gz +0 -0
  196. package/build/client/_app/immutable/chunks/BjxZ_neZ.js +0 -5
  197. package/build/client/_app/immutable/chunks/BjxZ_neZ.js.br +0 -0
  198. package/build/client/_app/immutable/chunks/BjxZ_neZ.js.gz +0 -0
  199. package/build/client/_app/immutable/chunks/CBRk0OGa.js.br +0 -0
  200. package/build/client/_app/immutable/chunks/CBRk0OGa.js.gz +0 -0
  201. package/build/client/_app/immutable/chunks/CG0TPRkn.js.br +0 -0
  202. package/build/client/_app/immutable/chunks/CG0TPRkn.js.gz +0 -0
  203. package/build/client/_app/immutable/chunks/CGReuhGk.js +0 -1
  204. package/build/client/_app/immutable/chunks/CGReuhGk.js.br +0 -1
  205. package/build/client/_app/immutable/chunks/CGReuhGk.js.gz +0 -0
  206. package/build/client/_app/immutable/chunks/CIDBs8t6.js.br +0 -0
  207. package/build/client/_app/immutable/chunks/CIDBs8t6.js.gz +0 -0
  208. package/build/client/_app/immutable/chunks/CfPyeeq3.js.br +0 -0
  209. package/build/client/_app/immutable/chunks/CfPyeeq3.js.gz +0 -0
  210. package/build/client/_app/immutable/chunks/CpeJ2iPd.js.br +0 -0
  211. package/build/client/_app/immutable/chunks/CpeJ2iPd.js.gz +0 -0
  212. package/build/client/_app/immutable/chunks/D0IrjYE5.js.br +0 -0
  213. package/build/client/_app/immutable/chunks/D0IrjYE5.js.gz +0 -0
  214. package/build/client/_app/immutable/chunks/D1Hr4tKw.js.br +0 -0
  215. package/build/client/_app/immutable/chunks/D1Hr4tKw.js.gz +0 -0
  216. package/build/client/_app/immutable/chunks/D6rwn6Ed.js.br +0 -1
  217. package/build/client/_app/immutable/chunks/D6rwn6Ed.js.gz +0 -0
  218. package/build/client/_app/immutable/chunks/DQCjzVyz.js.br +0 -0
  219. package/build/client/_app/immutable/chunks/DQCjzVyz.js.gz +0 -0
  220. package/build/client/_app/immutable/chunks/DWm-CGbg.js.br +0 -0
  221. package/build/client/_app/immutable/chunks/DWm-CGbg.js.gz +0 -0
  222. package/build/client/_app/immutable/chunks/DYDQbI6D.js.br +0 -0
  223. package/build/client/_app/immutable/chunks/DYDQbI6D.js.gz +0 -0
  224. package/build/client/_app/immutable/chunks/Dc9It0QB.js.br +0 -0
  225. package/build/client/_app/immutable/chunks/Dc9It0QB.js.gz +0 -0
  226. package/build/client/_app/immutable/chunks/DkQY3T0m.js +0 -1
  227. package/build/client/_app/immutable/chunks/DkQY3T0m.js.br +0 -0
  228. package/build/client/_app/immutable/chunks/DkQY3T0m.js.gz +0 -0
  229. package/build/client/_app/immutable/chunks/DqJI6J5U.js.br +0 -0
  230. package/build/client/_app/immutable/chunks/DqJI6J5U.js.gz +0 -0
  231. package/build/client/_app/immutable/chunks/DtV-MjyX.js.br +0 -0
  232. package/build/client/_app/immutable/chunks/DtV-MjyX.js.gz +0 -0
  233. package/build/client/_app/immutable/chunks/DznDQzx1.js.br +0 -0
  234. package/build/client/_app/immutable/chunks/DznDQzx1.js.gz +0 -0
  235. package/build/client/_app/immutable/chunks/F4LqKrLs.js.br +0 -0
  236. package/build/client/_app/immutable/chunks/F4LqKrLs.js.gz +0 -0
  237. package/build/client/_app/immutable/chunks/KA1QvXmu.js.br +0 -0
  238. package/build/client/_app/immutable/chunks/KA1QvXmu.js.gz +0 -0
  239. package/build/client/_app/immutable/chunks/KsLFdNDs.js.br +0 -0
  240. package/build/client/_app/immutable/chunks/KsLFdNDs.js.gz +0 -0
  241. package/build/client/_app/immutable/chunks/OoMmWNOu.js.br +0 -0
  242. package/build/client/_app/immutable/chunks/OoMmWNOu.js.gz +0 -0
  243. package/build/client/_app/immutable/chunks/UsO0MS14.js.br +0 -0
  244. package/build/client/_app/immutable/chunks/UsO0MS14.js.gz +0 -0
  245. package/build/client/_app/immutable/chunks/sf5kQ3yV.js.br +0 -0
  246. package/build/client/_app/immutable/chunks/sf5kQ3yV.js.gz +0 -0
  247. package/build/client/_app/immutable/chunks/w7c5E2ms.js.br +0 -0
  248. package/build/client/_app/immutable/chunks/w7c5E2ms.js.gz +0 -0
  249. package/build/client/_app/immutable/entry/app.FQLd-NC-.js.br +0 -0
  250. package/build/client/_app/immutable/entry/app.FQLd-NC-.js.gz +0 -0
  251. package/build/client/_app/immutable/entry/start.DqW_lChD.js +0 -1
  252. package/build/client/_app/immutable/entry/start.DqW_lChD.js.br +0 -1
  253. package/build/client/_app/immutable/entry/start.DqW_lChD.js.gz +0 -0
  254. package/build/client/_app/immutable/nodes/0.BN3NguWs.js.br +0 -0
  255. package/build/client/_app/immutable/nodes/1.5EZfoLCg.js.br +0 -0
  256. package/build/client/_app/immutable/nodes/1.5EZfoLCg.js.gz +0 -0
  257. package/build/client/_app/immutable/nodes/2.CbcDv2oO.js +0 -4
  258. package/build/client/_app/immutable/nodes/2.CbcDv2oO.js.br +0 -0
  259. package/build/client/_app/immutable/nodes/2.CbcDv2oO.js.gz +0 -0
  260. package/build/server/chunks/chunks/archive.js-C2D-5edp.js.map +0 -1
  261. package/build/server/chunks/chunks/aws.js-DkPqAybc.js.map +0 -1
  262. package/build/server/chunks/chunks/env2.js-CcIskxOZ.js +0 -60
  263. package/build/server/chunks/chunks/env2.js-CcIskxOZ.js.map +0 -1
  264. package/build/server/chunks/chunks/log-buffer.js-BI_gQOls.js.map +0 -1
  265. package/build/server/chunks/chunks/regions.js-IQPMyP5C.js.map +0 -1
  266. package/build/server/chunks/chunks/series-buckets.js-BjigySff.js.map +0 -1
  267. package/build/server/chunks/entries/endpoints/api/archive/_server.ts.js-83Ch7djd.js.map +0 -1
  268. package/build/server/chunks/entries/endpoints/api/health/_server.ts.js-VctnBhIJ.js.map +0 -1
  269. package/build/server/chunks/entries/endpoints/api/identity/_server.ts.js-Dt540Sio.js.map +0 -1
  270. package/build/server/chunks/entries/endpoints/api/log-groups/_server.ts.js-drLgUdvB.js.map +0 -1
  271. package/build/server/chunks/entries/endpoints/api/regions/_server.ts.js-CBqfN6Pg.js.map +0 -1
  272. package/build/server/chunks/entries/endpoints/api/series/_server.ts.js-DOvBhEDU.js.map +0 -1
  273. package/build/server/chunks/entries/endpoints/api/stream/_server.ts.js-B9_-4ssJ.js.map +0 -1
  274. package/build/server/chunks/entries/pages/_layout.svelte.js-CBQpEToy.js.map +0 -1
  275. package/build/server/chunks/entries/pages/_page.svelte.js-BwuzE25P.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { ah as escape_html } from '../../chunks/server.js-CAEBuMIH.js';
2
- import { p as page } from '../../chunks/state.js-DbqJPX0Y.js';
2
+ import { p as page } from '../../chunks/state.js-vZj9lo1I.js';
3
3
  import '../../chunks/uneval.js-DaakSYFQ.js';
4
4
  import '../../chunks/index-server.js-DNLOKvM0.js';
5
5
  import '../../chunks/shared.js-CgjUIvRK.js';
6
6
  import '../../chunks/exports.js-ClPPfcHj.js';
7
- import '../../chunks/internal2.js-627EG4am.js';
7
+ import '../../chunks/internal2.js-BMcEVxqN.js';
8
8
  import '../../chunks/legacy-client.js-DJmDw3Zx.js';
9
9
  import '../../chunks/utils.js-BIlHjgGW.js';
10
10
 
@@ -16,4 +16,4 @@ function Error($$renderer, $$props) {
16
16
  }
17
17
 
18
18
  export { Error as default };
19
- //# sourceMappingURL=error.svelte.js-B8dLO9gT.js.map
19
+ //# sourceMappingURL=error.svelte.js-bokc4skC.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.svelte.js-B8dLO9gT.js","sources":["../../../../../.svelte-kit/output/server/entries/fallbacks/error.svelte.js"],"sourcesContent":["import { D as escape_html } from \"../../chunks/server.js\";\nimport { t as page } from \"../../chunks/state.js\";\n//#region node_modules/.pnpm/@sveltejs+kit@2.70.3_@sveltejs+vite-plugin-svelte@7.3.0_svelte@5.57.0_vite@8.2.2_@types_ab6e39593f61aae0ad0b9a1bac6935c7/node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte\nfunction Error($$renderer, $$props) {\n\t$$renderer.component(($$renderer) => {\n\t\t$$renderer.push(`<h1>${escape_html(page.status)}</h1> <p>${escape_html(page.error?.message)}</p>`);\n\t});\n}\n//#endregion\nexport { Error as default };\n"],"names":[],"mappings":";;;;;;;;;;AAEA;AACA,SAAS,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE;AACpC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,UAAU,KAAK;AACtC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;AACpG,CAAC,CAAC,CAAC;AACH;;"}
1
+ {"version":3,"file":"error.svelte.js-bokc4skC.js","sources":["../../../../../.svelte-kit/output/server/entries/fallbacks/error.svelte.js"],"sourcesContent":["import { D as escape_html } from \"../../chunks/server.js\";\nimport { t as page } from \"../../chunks/state.js\";\n//#region node_modules/.pnpm/@sveltejs+kit@2.70.3_@sveltejs+vite-plugin-svelte@7.3.0_svelte@5.57.0_vite@8.2.2_@types_ab6e39593f61aae0ad0b9a1bac6935c7/node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte\nfunction Error($$renderer, $$props) {\n\t$$renderer.component(($$renderer) => {\n\t\t$$renderer.push(`<h1>${escape_html(page.status)}</h1> <p>${escape_html(page.error?.message)}</p>`);\n\t});\n}\n//#endregion\nexport { Error as default };\n"],"names":[],"mappings":";;;;;;;;;;AAEA;AACA,SAAS,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE;AACpC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,UAAU,KAAK;AACtC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;AACpG,CAAC,CAAC,CAAC;AACH;;"}
@@ -9,14 +9,14 @@ function _layout($$renderer, $$props) {
9
9
  let { children } = $$props;
10
10
  head("12qhfyh", $$renderer, ($$renderer) => {
11
11
  $$renderer.title(($$renderer) => {
12
- $$renderer.push(`<title>watch-stream</title>`);
12
+ $$renderer.push(`<title>watch-tail</title>`);
13
13
  });
14
14
  $$renderer.push(`<link rel="icon"${attr("href", favicon_default)}/>`);
15
15
  });
16
- $$renderer.push(`<div class="flex h-dvh min-h-[30rem] flex-col overflow-hidden bg-neutral-950 font-sans text-neutral-100 antialiased selection:bg-sky-900/60"><header class="flex-none border-b border-neutral-900 bg-neutral-950/90"><div class="flex w-full items-baseline gap-3 px-3 py-2 sm:px-4"><span class="text-sm font-semibold tracking-tight">watch<span class="text-sky-400">-stream</span></span> <span class="hidden text-xs text-neutral-500 sm:inline">Tail CloudWatch Logs in the browser</span></div></header> <main class="flex min-h-0 w-full flex-1 flex-col gap-3 px-3 py-3 sm:px-4">`);
16
+ $$renderer.push(`<div class="flex h-dvh min-h-[30rem] flex-col overflow-hidden bg-neutral-950 font-sans text-neutral-100 antialiased selection:bg-sky-900/60"><header class="flex-none border-b border-neutral-900 bg-neutral-950/90"><div class="flex w-full items-baseline gap-3 px-3 py-2 sm:px-4"><span class="text-sm font-semibold tracking-tight">watch<span class="text-sky-400">-tail</span></span> <span class="hidden text-xs text-neutral-500 sm:inline">Tail CloudWatch Logs in the browser</span></div></header> <main class="flex min-h-0 w-full flex-1 flex-col gap-3 px-3 py-3 sm:px-4">`);
17
17
  children($$renderer);
18
18
  $$renderer.push(`<!----></main></div>`);
19
19
  }
20
20
 
21
21
  export { _layout as default };
22
- //# sourceMappingURL=_layout.svelte.js-CBQpEToy.js.map
22
+ //# sourceMappingURL=_layout.svelte.js-8U7ZeKYO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_layout.svelte.js-8U7ZeKYO.js","sources":["../../../../../.svelte-kit/output/server/entries/pages/_layout.svelte.js"],"sourcesContent":["import { c as head, w as attr } from \"../../chunks/server.js\";\n//#region src/lib/assets/favicon.svg\nvar favicon_default = \"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2032%2032'%20role='img'%20aria-label='watch-tail'%3e%3ctitle%3ewatch-tail%3c/title%3e%3c!--%20A%20log%20window:%20three%20lines,%20the%20newest%20highlighted,%20with%20the%20tail%20still%20running.%20--%3e%3crect%20width='32'%20height='32'%20rx='7'%20fill='%230a0a0a'%20/%3e%3crect%20x='5'%20y='6.6'%20width='14'%20height='4'%20rx='2'%20fill='%2338bdf8'%20/%3e%3crect%20x='5'%20y='14'%20width='22'%20height='4'%20rx='2'%20fill='%23525252'%20/%3e%3crect%20x='5'%20y='21.4'%20width='17'%20height='4'%20rx='2'%20fill='%23404040'%20/%3e%3ccircle%20cx='25.6'%20cy='8.6'%20r='2.8'%20fill='%2338bdf8'%20/%3e%3c/svg%3e\";\n//#endregion\n//#region src/routes/+layout.svelte\nfunction _layout($$renderer, $$props) {\n\tlet { children } = $$props;\n\thead(\"12qhfyh\", $$renderer, ($$renderer) => {\n\t\t$$renderer.title(($$renderer) => {\n\t\t\t$$renderer.push(`<title>watch-tail</title>`);\n\t\t});\n\t\t$$renderer.push(`<link rel=\"icon\"${attr(\"href\", favicon_default)}/>`);\n\t});\n\t$$renderer.push(`<div class=\"flex h-dvh min-h-[30rem] flex-col overflow-hidden bg-neutral-950 font-sans text-neutral-100 antialiased selection:bg-sky-900/60\"><header class=\"flex-none border-b border-neutral-900 bg-neutral-950/90\"><div class=\"flex w-full items-baseline gap-3 px-3 py-2 sm:px-4\"><span class=\"text-sm font-semibold tracking-tight\">watch<span class=\"text-sky-400\">-tail</span></span> <span class=\"hidden text-xs text-neutral-500 sm:inline\">Tail CloudWatch Logs in the browser</span></div></header> <main class=\"flex min-h-0 w-full flex-1 flex-col gap-3 px-3 py-3 sm:px-4\">`);\n\tchildren($$renderer);\n\t$$renderer.push(`<!----></main></div>`);\n}\n//#endregion\nexport { _layout as default };\n"],"names":[],"mappings":";;;AACA;AACA,IAAI,eAAe,GAAG,orBAAorB;AAC1sB;AACA;AACA,SAAS,OAAO,CAAC,UAAU,EAAE,OAAO,EAAE;AACtC,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO;AAC3B,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,UAAU,KAAK;AAC7C,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,UAAU,KAAK;AACnC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,yBAAyB,CAAC,CAAC;AAC/C,EAAE,CAAC,CAAC;AACJ,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AACH,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,wjBAAwjB,CAAC,CAAC;AAC5kB,CAAC,QAAQ,CAAC,UAAU,CAAC;AACrB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,oBAAoB,CAAC,CAAC;AACxC;;"}
@@ -1,20 +1,20 @@
1
1
  import { ah as escape_html, ag as attr, ai as attr_style, ac as derived, aj as attr_class, ak as ensure_array_like, al as stringify, am as bind_props, an as clsx } from '../../chunks/server.js-CAEBuMIH.js';
2
- import { c as LogStore, f as filterByLevel, g as filterEvents, e as effectiveLevel, t as tokenizeJson, b as detectLevel, h as formatLogMessage, j as eventKey, l as levelColorClass } from '../../chunks/log-buffer.js-BI_gQOls.js';
3
- import { R as REGION_CODES } from '../../chunks/regions.js-IQPMyP5C.js';
2
+ import { f as LogStore, g as filterByLevel, h as filterEvents, c as effectiveLevel, t as tokenizeJson, b as detectLevel, j as formatLogMessage, k as eventKey, l as levelColorClass } from '../../chunks/log-buffer.js-A9FA-Qv8.js';
3
+ import { R as REGION_CODES } from '../../chunks/regions.js-COf7DgnH.js';
4
4
  import { P as PRESET_LABELS, a as presetLabel, H as HISTORIC_PRESETS, t as toDateTimeLocal, d as describeWindow } from '../../chunks/time-range.js-BLMT8aU3.js';
5
- import { p as page, r as replaceState } from '../../chunks/state.js-DbqJPX0Y.js';
6
- import { S as SERIES_LEVEL_COLOR, g as groupByLevel, r as requestRows, L as LEVEL_LABELS, i as isMeaningfulBrush, b as bucketEvents } from '../../chunks/series-buckets.js-BjigySff.js';
5
+ import { p as page, r as replaceState } from '../../chunks/state.js-vZj9lo1I.js';
6
+ import { S as SERIES_LEVEL_COLOR, g as groupByLevel, r as requestRows, a as requestIdOf, c as collectRequests, L as LEVEL_LABELS, i as isMeaningfulBrush, b as requestDurations, d as bucketEvents } from '../../chunks/series-buckets.js-DFGWkob5.js';
7
7
  import '../../chunks/uneval.js-DaakSYFQ.js';
8
8
  import '../../chunks/index-server.js-DNLOKvM0.js';
9
9
  import '../../chunks/shared.js-CgjUIvRK.js';
10
10
  import '../../chunks/exports.js-ClPPfcHj.js';
11
- import '../../chunks/internal2.js-627EG4am.js';
11
+ import '../../chunks/internal2.js-BMcEVxqN.js';
12
12
  import '../../chunks/legacy-client.js-DJmDw3Zx.js';
13
13
  import '../../chunks/utils.js-BIlHjgGW.js';
14
14
 
15
15
  //#region src/lib/format.ts
16
16
  /**
17
- * Formatting helpers for the watch-stream UI. Every function here is pure so it can be unit
17
+ * Formatting helpers for the watch-tail UI. Every function here is pure so it can be unit
18
18
  * tested without a DOM.
19
19
  */
20
20
  /** Placeholder shown when a timestamp is missing or not a number. */
@@ -158,12 +158,12 @@ function EndpointBadge($$renderer, $$props) {
158
158
  */
159
159
  /** `localStorage` keys, prefixed so they are easy to spot in a browser. */
160
160
  var STORAGE_KEYS = {
161
- sidebarWidth: "watch-stream:sidebar-width",
162
- prefixWidth: "watch-stream:prefix-width",
163
- wrap: "watch-stream:wrap",
164
- jsonView: "watch-stream:json-view",
165
- chartOpen: "watch-stream:chart-open",
166
- groupRequests: "watch-stream:group-requests"
161
+ sidebarWidth: "watch-tail:sidebar-width",
162
+ prefixWidth: "watch-tail:prefix-width",
163
+ wrap: "watch-tail:wrap",
164
+ jsonView: "watch-tail:json-view",
165
+ chartOpen: "watch-tail:chart-open",
166
+ groupRequests: "watch-tail:group-requests"
167
167
  };
168
168
  /** Default width of the group-list pane, in rem (matches the original layout). */
169
169
  var SIDEBAR_WIDTH = {
@@ -207,7 +207,7 @@ function EventScatterPanel($$renderer, $$props) {
207
207
  * The real loader: a dynamic import, which is what keeps layerchart out of the
208
208
  * initial bundle. It only runs in the browser, and only once the panel is open.
209
209
  */
210
- const loadChartModule = () => import('../../chunks/EventScatter.js-D3Jaw_Cw.js');
210
+ const loadChartModule = () => import('../../chunks/EventScatter.js-CG0RcOU6.js');
211
211
  /** Bucketed counts for the window. */
212
212
  /** Inclusive start of the window, epoch ms. */
213
213
  /** Inclusive end of the window, epoch ms. */
@@ -219,7 +219,7 @@ function EventScatterPanel($$renderer, $$props) {
219
219
  /** Chart height in px. */
220
220
  /** Start open, which is also what the first visit uses. */
221
221
  /** Chart module loader; defaults to the dynamic import. */
222
- let { points = [], from = 0, to = 0, bucketMs = 0, groups = [], loading = false, byRequest = true, onBrush, height = 200, open = true, loadChart = loadChartModule } = $$props;
222
+ let { metric = "count", onMetricChange, onSelect, points = [], from = 0, to = 0, bucketMs = 0, groups = [], loading = false, byRequest = true, onBrush, height = 200, open = true, loadChart = loadChartModule } = $$props;
223
223
  let expanded = derived(() => open);
224
224
  /** Totals and labels per level, in severity order. */
225
225
  let levelGroups = derived(() => groupByLevel(points));
@@ -230,38 +230,51 @@ function EventScatterPanel($$renderer, $$props) {
230
230
  /** True when there is something to draw. */
231
231
  let hasPoints = derived(() => points.length > 0);
232
232
  /** What one mark stands for, which is what the totals count. */
233
- let unit = derived(() => byRequest ? "requests" : "events");
233
+ let unit = derived(() => metric === "duration" || byRequest ? "requests" : "events");
234
234
  /** Clears the brush, for the host's Reset zoom control. */
235
235
  function reset() {
236
236
  onBrush?.(null);
237
237
  }
238
- $$renderer.push(`<section class="flex min-w-0 flex-col gap-1 rounded-lg border border-neutral-800 bg-neutral-950/60 p-2" data-testid="event-scatter" aria-label="Events over time"><div class="flex flex-wrap items-center gap-x-3 gap-y-1 px-1 text-[0.6875rem]"><button type="button"${attr("aria-expanded", expanded())}${attr("title", expanded() ? "Hide the chart" : "Show the chart")} data-testid="scatter-toggle" class="flex items-center gap-1 rounded-md border border-neutral-800 bg-neutral-900 px-2 py-0.5 font-semibold uppercase tracking-wider text-neutral-400 transition-colors hover:border-neutral-700 hover:text-neutral-200"><span aria-hidden="true">${escape_html(expanded() ? "▾" : "▸")}</span> Events over time</button> <span class="text-neutral-400" data-testid="scatter-summary">${escape_html(formatCount(totalEvents()))}
239
- ${escape_html(unit())} in ${escape_html(formatCount(bucketCount()))} buckets</span> `);
238
+ $$renderer.push(`<section class="flex min-w-0 flex-col gap-1 rounded-lg border border-neutral-800 bg-neutral-950/60 p-2" data-testid="event-scatter"${attr("aria-label", metric === "duration" ? "Request duration over time" : "Events over time")}><div class="flex flex-wrap items-center gap-x-3 gap-y-1 px-1 text-[0.6875rem]"><button type="button"${attr("aria-expanded", expanded())}${attr("title", expanded() ? "Hide the chart" : "Show the chart")} data-testid="scatter-toggle" class="flex items-center gap-1 rounded-md border border-neutral-800 bg-neutral-900 px-2 py-0.5 font-semibold uppercase tracking-wider text-neutral-400 transition-colors hover:border-neutral-700 hover:text-neutral-200"><span aria-hidden="true">${escape_html(expanded() ? "▾" : "▸")}</span> ${escape_html(metric === "duration" ? "Request duration" : "Events over time")}</button> <div role="group" aria-label="Chart metric" class="flex rounded-md border border-neutral-800 p-0.5"><!--[-->`);
239
+ const each_array = ensure_array_like(["count", "duration"]);
240
+ for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
241
+ let choice = each_array[$$index];
242
+ $$renderer.push(`<button type="button"${attr("data-testid", `chart-metric-${choice}`)}${attr("aria-pressed", metric === choice)}${attr_class(`rounded px-2 py-0.5 transition-colors ${metric === choice ? "bg-sky-950 text-sky-300" : "text-neutral-400 hover:text-neutral-200"}`)}>${escape_html(choice === "count" ? "Count" : "Duration (ms)")}</button>`);
243
+ }
244
+ $$renderer.push(`<!--]--></div> <span class="text-neutral-400" data-testid="scatter-summary">${escape_html(formatCount(totalEvents()))}
245
+ ${escape_html(unit())}`);
246
+ if (metric === "count") $$renderer.push(`<!--[0--> in ${escape_html(formatCount(bucketCount()))} buckets`);
247
+ else $$renderer.push("<!--[-1-->");
248
+ $$renderer.push(`<!--]--></span> `);
240
249
  if (groups.length > 1) $$renderer.push(`<!--[0--><span class="text-neutral-500" data-testid="scatter-groups">across ${escape_html(groups.length)} groups</span>`);
241
250
  else $$renderer.push("<!--[-1-->");
242
251
  $$renderer.push(`<!--]--> <!--[-->`);
243
- const each_array = ensure_array_like(levelGroups());
244
- for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
245
- let entry = each_array[$$index];
252
+ const each_array_1 = ensure_array_like(levelGroups());
253
+ for (let $$index_1 = 0, $$length = each_array_1.length; $$index_1 < $$length; $$index_1++) {
254
+ let entry = each_array_1[$$index_1];
246
255
  $$renderer.push(`<span class="flex items-center gap-1 text-neutral-400"${attr("data-testid", `scatter-legend-${stringify(entry.level)}`)}><span class="inline-block h-2 w-2 rounded-full"${attr_style(`background-color: ${stringify(SERIES_LEVEL_COLOR[entry.level])}`)}></span> ${escape_html(entry.label)} <span class="text-neutral-500">${escape_html(formatCount(entry.events))}</span></span>`);
247
256
  }
248
257
  $$renderer.push(`<!--]--> `);
249
- if (loading && expanded()) $$renderer.push(`<!--[0--><span class="text-amber-300" data-testid="scatter-loading">counting…</span>`);
258
+ if (loading && expanded()) $$renderer.push(`<!--[0--><span class="text-amber-300" data-testid="scatter-loading">loading…</span>`);
250
259
  else $$renderer.push("<!--[-1-->");
251
260
  $$renderer.push(`<!--]--> `);
252
261
  if (expanded()) {
253
262
  $$renderer.push("<!--[0-->");
254
- $$renderer.push(`<!--[-1--><span class="ml-auto text-neutral-500" data-testid="scatter-hint">drag to zoom · click to clear</span>`);
263
+ $$renderer.push(`<!--[-1--><span class="ml-auto text-neutral-500" data-testid="scatter-hint">select a point to show logs · drag to zoom · click background to clear</span>`);
255
264
  $$renderer.push(`<!--]-->`);
256
265
  } else $$renderer.push("<!--[-1-->");
257
266
  $$renderer.push(`<!--]--></div> `);
258
267
  if (expanded()) {
259
268
  $$renderer.push("<!--[0-->");
269
+ if (metric === "duration") $$renderer.push(`<!--[0--><p class="px-1 text-[0.6875rem] text-neutral-500" data-testid="duration-note">Observed duration (ms) · last event + its duration − first event · partial requests may
270
+ appear shorter</p>`);
271
+ else $$renderer.push("<!--[-1-->");
272
+ $$renderer.push(`<!--]--> `);
260
273
  if (hasPoints()) {
261
274
  $$renderer.push("<!--[1-->");
262
275
  $$renderer.push(`<!--[-1--><div class="w-full animate-pulse rounded bg-neutral-900/60"${attr_style(`height: ${stringify(height)}px`)}></div>`);
263
276
  $$renderer.push(`<!--]-->`);
264
- } else if (!loading) $$renderer.push(`<!--[2--><p class="px-1 py-6 text-xs text-neutral-500" data-testid="scatter-empty">No events in this window yet.</p>`);
277
+ } else if (!loading) $$renderer.push(`<!--[2--><p class="px-1 py-6 text-xs text-neutral-500" data-testid="scatter-empty">${escape_html(metric === "duration" ? "No requests with a request ID in this window yet." : "No events in this window yet.")}</p>`);
265
278
  else $$renderer.push("<!--[-1-->");
266
279
  $$renderer.push(`<!--]-->`);
267
280
  } else $$renderer.push("<!--[-1-->");
@@ -324,7 +337,7 @@ function RangeControls($$renderer, $$props) {
324
337
  //#endregion
325
338
  //#region src/lib/groups-client.ts
326
339
  /**
327
- * Browser-side fetch helpers for the watch-stream JSON API (`/api/health`, `/api/regions`,
340
+ * Browser-side fetch helpers for the watch-tail JSON API (`/api/health`, `/api/regions`,
328
341
  * `/api/log-groups`, `/api/archive`). Every helper throws {@link ApiError} on a non-2xx response so
329
342
  * the UI can show the API `error` message instead of an opaque failure.
330
343
  */
@@ -377,6 +390,7 @@ function buildSeriesUrl(query) {
377
390
  if (typeof query.to === "number" && Number.isFinite(query.to)) search.set("to", String(Math.round(query.to)));
378
391
  const levels = (query.levels ?? []).filter((level) => level.length > 0);
379
392
  if (levels.length > 0) search.set("level", levels.join(","));
393
+ if (query.metric) search.set("metric", query.metric);
380
394
  if (query.by === "request" || query.by === "event") search.set("by", query.by);
381
395
  if (typeof query.bucketMs === "number" && Number.isFinite(query.bucketMs) && query.bucketMs > 0) search.set("bucket", String(Math.round(query.bucketMs)));
382
396
  return `/api/series?${search.toString()}`;
@@ -424,6 +438,16 @@ async function getJson(url, options) {
424
438
  function fetchLogGroups(query) {
425
439
  return getJson(buildLogGroupsUrl(query), query);
426
440
  }
441
+ /**
442
+ * `GET /api/archive` - what the local DuckDB archive holds.
443
+ *
444
+ * The route answers 200 even when the archive is off or unreadable, so a failed
445
+ * request means the API itself is unreachable and the caller should just hide
446
+ * the archive view.
447
+ */
448
+ function fetchArchiveStatus(options = {}) {
449
+ return getJson(`/api/archive${options.region ? `?${new URLSearchParams({ region: options.region })}` : ""}`, options);
450
+ }
427
451
  /** Message shown when a region has no log groups at all. */
428
452
  function noGroupsMessage(region) {
429
453
  return `No log groups found in ${region}. Start floci and run \`pnpm seed\` to create sample groups.`;
@@ -450,7 +474,7 @@ function describeGroupsError(region, error) {
450
474
  const details = error.details ? ` ${error.details}` : "";
451
475
  return `Could not list log groups in ${region}: ${trimSentence(error.message)}.${details}`;
452
476
  }
453
- return `Could not reach the watch-stream API for ${region}. ${error instanceof Error && error.message !== "" ? error.message : String(error)}`;
477
+ return `Could not reach the watch-tail API for ${region}. ${error instanceof Error && error.message !== "" ? error.message : String(error)}`;
454
478
  }
455
479
  /** Adds group and region context to a stream error payload. */
456
480
  function describeStreamError(region, group, message) {
@@ -550,6 +574,25 @@ function LogGroupList($$renderer, $$props) {
550
574
  });
551
575
  }
552
576
  //#endregion
577
+ //#region src/lib/chart-selection.ts
578
+ /** Resolve a plotted mark against the loaded events, before display filters. */
579
+ function selectedChartEvents(lines, selection) {
580
+ if (selection === null) return /* @__PURE__ */ new Set();
581
+ const { point, bucketMs, byRequest, fallbackGroup } = selection;
582
+ const events = lines.filter((event) => (event.group ?? fallbackGroup) === point.group);
583
+ if (point.requestId !== void 0) return new Set(events.filter((event) => requestIdOf(event) === point.requestId));
584
+ const inBucket = (timestamp) => Math.floor(timestamp / bucketMs) * bucketMs === point.t;
585
+ const matches = /* @__PURE__ */ new Set();
586
+ if (byRequest) {
587
+ for (const request of collectRequests(events)) if (inBucket(request.first) && request.level === point.level) for (const { event } of request.events) matches.add(event);
588
+ }
589
+ for (const event of events) {
590
+ if (byRequest && requestIdOf(event) !== null) continue;
591
+ if (inBucket(event.timestamp) && (effectiveLevel(event) ?? "unknown") === point.level) matches.add(event);
592
+ }
593
+ return matches;
594
+ }
595
+ //#endregion
553
596
  //#region src/lib/components/StatusBadge.svelte
554
597
  function StatusBadge($$renderer, $$props) {
555
598
  /** Connection status reported by the log stream. */
@@ -617,7 +660,7 @@ function LogViewer($$renderer, $$props) {
617
660
  * default, and owned by the page so the chart counts the same requests.
618
661
  */
619
662
  /** Called when the grouping toggle is pressed. */
620
- let { lines = [], status = "idle", error = null, region = "", group = null, filter = "", paused = false, autoScroll = true, pendingCount = 0, droppedCount = 0, receivedCount = 0, mode = "live", ready = null, endReason = null, archivePath = null, groups = [], level = void 0, onLevelChange, groupRequests = true, onGroupToggle, onFilterChange, onPauseToggle, onClear, onAutoScrollToggle } = $$props;
663
+ let { selection = null, onSelectionClear, lines = [], status = "idle", error = null, region = "", group = null, filter = "", paused = false, autoScroll = true, pendingCount = 0, droppedCount = 0, receivedCount = 0, mode = "live", ready = null, endReason = null, archivePath = null, groups = [], level = void 0, onLevelChange, groupRequests = true, onGroupToggle, onFilterChange, onPauseToggle, onClear, onAutoScrollToggle } = $$props;
621
664
  const TIMESTAMP_COLUMN_PX = remToPx(7.5);
622
665
  const ROW_PADDING_PX = remToPx(.75);
623
666
  const ROW_GAP_PX = remToPx(.5);
@@ -669,8 +712,10 @@ function LogViewer($$renderer, $$props) {
669
712
  activeClass: "border-neutral-700 bg-neutral-800 text-neutral-400"
670
713
  }
671
714
  ];
715
+ let selectedEvents = derived(() => selectedChartEvents(lines, selection));
672
716
  /** Lines matching the text filter and the level filter. */
673
717
  let visible = derived(() => filterByLevel(filterEvents(lines, filter), levelFilter()));
718
+ let visibleSelectedCount = derived(() => visible().filter((event) => selectedEvents().has(event)).length);
674
719
  /** How many lines of each level are loaded, including `unknown`. */
675
720
  let levelCounts = derived(() => {
676
721
  const counts = {
@@ -692,6 +737,7 @@ function LogViewer($$renderer, $$props) {
692
737
  const formatted = formatLogMessage(event.message, { prettyJson: jsonView });
693
738
  const levelClass = levelColorClass(rowLevel);
694
739
  return {
740
+ selected: selectedEvents().has(event),
695
741
  key: eventKey(event, index),
696
742
  time: formatTime(event.timestamp),
697
743
  timestamp: formatTimestamp(event.timestamp),
@@ -785,7 +831,6 @@ function LogViewer($$renderer, $$props) {
785
831
  let grouped = derived(() => displayRows().some((row) => row.kind === "request"));
786
832
  /** Requests in view, shown next to the line count while grouping. */
787
833
  let requestCount = derived(() => displayRows().filter((row) => row.kind === "request").length);
788
- /** Keeps the newest line in view while auto-scroll is on (vertical only). */
789
834
  /** Error text with the group and region context. */
790
835
  let errorText = derived(() => error === null ? null : describeStreamError(region, group, error.message));
791
836
  /** True when the ready frame says the events come from the local archive. */
@@ -873,6 +918,13 @@ function LogViewer($$renderer, $$props) {
873
918
  $$renderer.push(`<!--]--></div> <input type="search" aria-label="Filter log lines" placeholder="Filter lines"${attr("value", filter)} class="w-40 rounded-md border border-neutral-800 bg-neutral-900 px-2 py-1 text-xs text-neutral-100 outline-none transition-colors placeholder:text-neutral-600 hover:border-neutral-700 focus:border-sky-600"/> <button type="button"${attr("aria-pressed", wrapLines)} title="Wrap long lines instead of scrolling sideways" data-testid="wrap-toggle"${attr_class(`rounded-md border border-neutral-800 bg-neutral-900 px-2 py-1 text-xs font-medium transition-colors hover:border-neutral-700 ${wrapTone()}`)}>Wrap</button> <button type="button"${attr("aria-pressed", jsonView)} title="Pretty-print JSON log entries (off: click a line to open its JSON)" data-testid="json-toggle"${attr_class(`rounded-md border border-neutral-800 bg-neutral-900 px-2 py-1 text-xs font-medium transition-colors hover:border-neutral-700 ${jsonTone()}`)}>JSON</button> <button type="button"${attr("aria-pressed", groupRequests)} title="Group the lines of one request into a single row, coloured by its most critical line (off: one row per line)" data-testid="group-toggle"${attr_class(`rounded-md border border-neutral-800 bg-neutral-900 px-2 py-1 text-xs font-medium transition-colors hover:border-neutral-700 ${groupTone()}`)}>By request</button> <button type="button"${attr("aria-pressed", paused)} class="rounded-md border border-neutral-800 bg-neutral-900 px-2 py-1 text-xs font-medium text-neutral-300 transition-colors hover:border-neutral-700 hover:text-neutral-100">${escape_html(paused ? "Resume" : "Pause")}</button> <button type="button" class="rounded-md border border-neutral-800 bg-neutral-900 px-2 py-1 text-xs font-medium text-neutral-300 transition-colors hover:border-neutral-700 hover:text-neutral-100">Clear</button> <button type="button"${attr("aria-pressed", autoScroll)}${attr_class(`rounded-md border border-neutral-800 bg-neutral-900 px-2 py-1 text-xs font-medium transition-colors hover:border-neutral-700 ${autoScrollTone()}`)}>Auto-scroll</button></div></div> `);
874
919
  if (errorText() !== null) $$renderer.push(`<!--[0--><p role="alert" data-testid="stream-error" class="border-b border-red-900 bg-red-950/50 px-3 py-2 text-xs leading-5 text-red-300">${escape_html(errorText())}</p>`);
875
920
  else $$renderer.push("<!--[-1-->");
921
+ $$renderer.push(`<!--]--> `);
922
+ if (selection !== null) {
923
+ $$renderer.push(`<!--[0--><div class="flex items-center gap-2 px-3 py-1 text-xs text-sky-300" role="status" data-testid="chart-selection-status">`);
924
+ if (selectedEvents().size === 0) $$renderer.push(`<!--[0-->Selected logs are not in the loaded buffer. Zoom into this time range to load them.`);
925
+ else $$renderer.push(`<!--[-1-->${escape_html(visibleSelectedCount())} of ${escape_html(selectedEvents().size)} selected log lines visible${escape_html(visibleSelectedCount() < selectedEvents().size ? " — clear the text or level filter to see all" : "")}.`);
926
+ $$renderer.push(`<!--]--> <button type="button" class="ml-auto underline">Clear selection</button></div>`);
927
+ } else $$renderer.push("<!--[-1-->");
876
928
  $$renderer.push(`<!--]--> <div class="min-h-0 min-w-0 flex-1 overflow-auto bg-neutral-950" data-testid="log-scroller">`);
877
929
  if (group === null || group === "") $$renderer.push(`<!--[0--><p class="px-3 py-6 text-sm text-neutral-500" data-testid="viewer-idle">Select a log group to start tailing.</p>`);
878
930
  else if (displayRows().length === 0) $$renderer.push(`<!--[1--><p class="px-3 py-6 text-sm text-neutral-500" data-testid="viewer-empty">${escape_html(emptyText())}</p>`);
@@ -881,7 +933,12 @@ function LogViewer($$renderer, $$props) {
881
933
  function logLine($$renderer, row, child) {
882
934
  const expandable = row.expandable !== null;
883
935
  const open = expandable && isExpanded(row.key);
884
- $$renderer.push(`<li${attr_class(`flex flex-wrap items-baseline gap-2 ${child ? "pl-8" : "px-3"} py-0.5 hover:bg-neutral-900/60 ${listClass()} ${expandable ? "cursor-pointer" : ""}`)} data-testid="log-line"${attr("data-request-child", child ? "true" : void 0)}${attr("data-level", row.level ?? "unknown")}${attr("data-expandable", expandable ? "true" : void 0)}${attr("data-expanded", open ? "true" : void 0)}${attr("role", expandable ? "button" : void 0)}${attr("tabindex", expandable ? 0 : void 0)}${attr("aria-expanded", expandable ? open : void 0)}${attr("title", expandable ? open ? "Hide the JSON in this line" : "Show this line as JSON" : void 0)}><span class="w-[7.5rem] shrink-0 text-neutral-500"${attr("title", row.timestamp)}>${escape_html(row.time)}</span> `);
936
+ $$renderer.push(`<li${attr_class(`flex flex-wrap items-baseline gap-2 ${child ? "pl-8" : "px-3"} py-0.5 hover:bg-neutral-900/60 ${listClass()} ${expandable ? "cursor-pointer" : ""}`, void 0, {
937
+ "bg-sky-950": row.selected,
938
+ "ring-1": row.selected,
939
+ "ring-inset": row.selected,
940
+ "ring-sky-700": row.selected
941
+ })} data-testid="log-line"${attr("data-chart-selected", row.selected ? "true" : void 0)}${attr("data-request-child", child ? "true" : void 0)}${attr("data-level", row.level ?? "unknown")}${attr("data-expandable", expandable ? "true" : void 0)}${attr("data-expanded", open ? "true" : void 0)}${attr("role", expandable ? "button" : void 0)}${attr("tabindex", expandable ? 0 : void 0)}${attr("aria-expanded", expandable ? open : void 0)}${attr("title", expandable ? open ? "Hide the JSON in this line" : "Show this line as JSON" : void 0)}><span class="w-[7.5rem] shrink-0 text-neutral-500"${attr("title", row.timestamp)}>${escape_html(row.time)}</span> `);
885
942
  if (groups.length > 1) $$renderer.push(`<!--[0--><span class="w-[9rem] shrink-0 truncate text-teal-400/80"${attr("title", row.group ?? "")} data-testid="log-group">${escape_html(row.group ?? "")}</span>`);
886
943
  else $$renderer.push("<!--[-1-->");
887
944
  $$renderer.push(`<!--]--> <span class="shrink-0 truncate text-sky-400/80"${attr_style(prefixStyle())}${attr("title", row.streamName ?? "")} data-testid="log-stream">${escape_html(row.streamName ?? "")}</span> `);
@@ -916,7 +973,7 @@ function LogViewer($$renderer, $$props) {
916
973
  if (row.kind === "request") {
917
974
  $$renderer.push("<!--[0-->");
918
975
  const open = isExpanded(row.key);
919
- $$renderer.push(`<li${attr_class(clsx(listClass()))} data-testid="log-request-group"${attr("data-request-id", row.id)}${attr("data-level", row.level)}${attr("data-expanded", open ? "true" : void 0)}${attr("data-lines", row.count)}><button type="button" class="flex w-full flex-wrap items-baseline gap-2 px-3 py-0.5 text-left hover:bg-neutral-900/60"${attr("aria-expanded", open)}${attr("title", open ? "Hide the lines of this request" : "Show every line of this request")} data-testid="request-group-summary"><span class="w-[7.5rem] shrink-0 text-neutral-500"${attr("title", row.timestamp)}>${escape_html(row.time)}</span> `);
976
+ $$renderer.push(`<li${attr_class(clsx(listClass()), void 0, { "bg-sky-950": row.children.some((child) => child.selected) })} data-testid="log-request-group"${attr("data-chart-selected", row.children.some((child) => child.selected) ? "true" : void 0)}${attr("data-request-id", row.id)}${attr("data-level", row.level)}${attr("data-expanded", open ? "true" : void 0)}${attr("data-lines", row.count)}><button type="button" class="flex w-full flex-wrap items-baseline gap-2 px-3 py-0.5 text-left hover:bg-neutral-900/60"${attr("aria-expanded", open)}${attr("title", open ? "Hide the lines of this request" : "Show every line of this request")} data-testid="request-group-summary"><span class="w-[7.5rem] shrink-0 text-neutral-500"${attr("title", row.timestamp)}>${escape_html(row.time)}</span> `);
920
977
  if (groups.length > 1) $$renderer.push(`<!--[0--><span class="w-[9rem] shrink-0 truncate text-teal-400/80"${attr("title", row.group ?? "")} data-testid="log-group">${escape_html(row.group ?? "")}</span>`);
921
978
  else $$renderer.push("<!--[-1-->");
922
979
  $$renderer.push(`<!--]--> <span class="shrink-0 truncate text-sky-400/80"${attr_style(prefixStyle())}${attr("title", row.streamName ?? "")} data-testid="log-stream">${escape_html(row.streamName ?? "")}</span> <span class="shrink-0 text-neutral-600" aria-hidden="true">${escape_html(open ? "▾" : "▸")}</span> <span class="shrink-0 rounded border border-neutral-700 bg-neutral-900 px-1.5 font-mono text-[0.6875rem] text-sky-200" data-testid="request-group-id" title="Request id shared by these lines">${escape_html(row.id)}</span> <span class="shrink-0 text-neutral-400" data-testid="request-group-count">${escape_html(formatCount(row.count))} lines</span> <span class="shrink-0 text-neutral-500" data-testid="request-group-span">${escape_html(row.span)}</span> <span${attr_class(`shrink-0 font-medium ${stringify(row.levelClass)}`)} data-testid="request-group-level">${escape_html(row.levelLabel)}</span> `);
@@ -1275,6 +1332,8 @@ function _page($$renderer, $$props) {
1275
1332
  let groupsLoading = false;
1276
1333
  let groupsError = null;
1277
1334
  let endpoint = null;
1335
+ /** Last `/api/archive` answer, or `null` when it could not be read. */
1336
+ let archiveStatus = null;
1278
1337
  let filter = "";
1279
1338
  let autoScroll = true;
1280
1339
  /**
@@ -1294,13 +1353,17 @@ function _page($$renderer, $$props) {
1294
1353
  */
1295
1354
  let groupRequests = true;
1296
1355
  /** Bucketed counts behind the chart. */
1356
+ let chartSelection = null;
1357
+ let seriesBucketMs = 6e4;
1297
1358
  let seriesPoints = [];
1298
1359
  /** True while the archive counts are being fetched. */
1299
1360
  let seriesLoading = false;
1361
+ let chartMetric = "count";
1362
+ let seriesRequest = 0;
1300
1363
  /** True only when the local archive reports that it can be read. */
1301
- let archiveAvailable = derived(() => false);
1364
+ let archiveAvailable = derived(() => archiveStatus?.available === true);
1302
1365
  /** Database file behind the archive, or `null` when it is unknown. */
1303
- let archivePath = derived(() => null);
1366
+ let archivePath = derived(() => archiveStatus?.path ?? null);
1304
1367
  /** Tooltip of the archive badge in the header. */
1305
1368
  let archiveTitle = derived(() => describeArchive(archivePath()));
1306
1369
  /** Sidebar width in pixels; the layout default is 22rem. */
@@ -1317,6 +1380,19 @@ function _page($$renderer, $$props) {
1317
1380
  } catch {}
1318
1381
  }
1319
1382
  /**
1383
+ * Reads `GET /api/archive`. The route answers 200 even for an unusable archive, so a failure
1384
+ * here only means the API is unreachable; the archive view stays hidden in that case.
1385
+ */
1386
+ async function loadArchiveStatus() {
1387
+ const target = region;
1388
+ try {
1389
+ const status = await fetchArchiveStatus({ region: target });
1390
+ if (region === target) archiveStatus = status;
1391
+ } catch {
1392
+ if (region === target) archiveStatus = null;
1393
+ }
1394
+ }
1395
+ /**
1320
1396
  * Loads the log groups of a region from the active source; a newer region or source change wins
1321
1397
  * the race. The CloudWatch URL is left exactly as it was, so only the archive names its source.
1322
1398
  */
@@ -1417,6 +1493,7 @@ function _page($$renderer, $$props) {
1417
1493
  selectedGroups = [];
1418
1494
  seriesPoints = [];
1419
1495
  syncUrl(next, []);
1496
+ loadArchiveStatus();
1420
1497
  loadGroups(next);
1421
1498
  }
1422
1499
  /** Replaces the view parameters in the address bar. */
@@ -1502,13 +1579,16 @@ function _page($$renderer, $$props) {
1502
1579
  * streamed are bucketed here. Both end up as the same points.
1503
1580
  */
1504
1581
  async function loadSeries() {
1582
+ const request = ++seriesRequest;
1583
+ seriesLoading = false;
1505
1584
  if (selectedGroups.length === 0 || region === "") {
1506
1585
  seriesPoints = [];
1507
1586
  return;
1508
1587
  }
1509
1588
  const { from, to } = chartWindow();
1589
+ seriesBucketMs = chartBucketMs(from, to);
1510
1590
  if (source !== "archive") {
1511
- seriesPoints = bucketEvents(stream.lines, {
1591
+ seriesPoints = (chartMetric === "duration" ? requestDurations : bucketEvents)(stream.lines, {
1512
1592
  from,
1513
1593
  to,
1514
1594
  bucketMs: chartBucketMs(from, to),
@@ -1519,19 +1599,25 @@ function _page($$renderer, $$props) {
1519
1599
  return;
1520
1600
  }
1521
1601
  seriesLoading = true;
1602
+ seriesPoints = [];
1522
1603
  try {
1523
- seriesPoints = (await fetchSeries({
1604
+ const series = await fetchSeries({
1524
1605
  region,
1525
1606
  groups: selectedGroups,
1526
1607
  from,
1527
1608
  to,
1528
1609
  levels: levelFilter === null ? [] : [levelFilter],
1529
- by: groupRequests ? "request" : "event"
1530
- })).points;
1610
+ by: groupRequests ? "request" : "event",
1611
+ metric: chartMetric
1612
+ });
1613
+ if (request === seriesRequest) {
1614
+ seriesPoints = series.points;
1615
+ seriesBucketMs = series.bucketMs;
1616
+ }
1531
1617
  } catch {
1532
- seriesPoints = [];
1618
+ if (request === seriesRequest) seriesPoints = [];
1533
1619
  } finally {
1534
- seriesLoading = false;
1620
+ if (request === seriesRequest) seriesLoading = false;
1535
1621
  }
1536
1622
  }
1537
1623
  $$renderer.push(`<div class="flex flex-wrap items-center gap-x-3 gap-y-2"><span class="text-[0.6875rem] font-semibold uppercase tracking-wider text-neutral-500">Watching</span> <span class="max-w-[22rem] truncate rounded-md border border-neutral-800 bg-neutral-900 px-2 py-1 font-mono text-xs text-neutral-200">${escape_html(selectedGroup() ?? "no group selected")}</span> <span class="text-xs text-neutral-500">in</span> <span class="font-mono text-xs text-neutral-300">${escape_html(region === "" ? "resolving region…" : region)}</span> `);
@@ -1597,9 +1683,23 @@ function _page($$renderer, $$props) {
1597
1683
  points: seriesPoints,
1598
1684
  from: chartWindow().from,
1599
1685
  to: chartWindow().to,
1600
- bucketMs: chartBucketMs(chartWindow().from, chartWindow().to),
1686
+ bucketMs: seriesBucketMs,
1601
1687
  groups: selectedGroups,
1602
1688
  byRequest: groupRequests,
1689
+ metric: chartMetric,
1690
+ onMetricChange: (metric) => {
1691
+ chartSelection = null;
1692
+ chartMetric = metric;
1693
+ },
1694
+ onSelect: (point) => {
1695
+ autoScroll = false;
1696
+ chartSelection = {
1697
+ point,
1698
+ bucketMs: seriesBucketMs,
1699
+ byRequest: groupRequests,
1700
+ fallbackGroup: selectedGroup() ?? ""
1701
+ };
1702
+ },
1603
1703
  loading: seriesLoading,
1604
1704
  onBrush: applyBrush
1605
1705
  });
@@ -1608,6 +1708,8 @@ function _page($$renderer, $$props) {
1608
1708
  else $$renderer.push("<!--[-1-->");
1609
1709
  $$renderer.push(`<!--]--> `);
1610
1710
  LogViewer($$renderer, {
1711
+ selection: chartSelection,
1712
+ onSelectionClear: () => chartSelection = null,
1611
1713
  lines: stream.lines,
1612
1714
  status: stream.status,
1613
1715
  error: stream.lastError,
@@ -1630,12 +1732,18 @@ function _page($$renderer, $$props) {
1630
1732
  receivedCount: stream.receivedCount,
1631
1733
  onFilterChange: (value) => filter = value,
1632
1734
  onPauseToggle: () => stream.togglePause(),
1633
- onClear: () => stream.clear(),
1634
- onAutoScrollToggle: () => autoScroll = !autoScroll
1735
+ onClear: () => {
1736
+ chartSelection = null;
1737
+ stream.clear();
1738
+ },
1739
+ onAutoScrollToggle: () => {
1740
+ chartSelection = null;
1741
+ autoScroll = !autoScroll;
1742
+ }
1635
1743
  });
1636
1744
  $$renderer.push(`<!----></div></div>`);
1637
1745
  });
1638
1746
  }
1639
1747
 
1640
1748
  export { _page as default };
1641
- //# sourceMappingURL=_page.svelte.js-BwuzE25P.js.map
1749
+ //# sourceMappingURL=_page.svelte.js-DRoSEPVH.js.map