watch-tail 0.9.0 → 0.10.1
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.
- package/README.md +111 -10
- package/build/client/_app/immutable/assets/0.B5hI3s8c.css +2 -0
- package/build/client/_app/immutable/assets/2.Cn4w1JYv.css +1 -0
- package/build/client/_app/immutable/chunks/0bp2Fczu.js +1 -0
- package/build/client/_app/immutable/chunks/B2En4t_E.js +3 -0
- package/build/client/_app/immutable/chunks/{DS3cLPAu.js → B7X5bVGV.js} +1 -1
- package/build/client/_app/immutable/chunks/BDcWO4cr.js +1 -0
- package/build/client/_app/immutable/chunks/{Dkh4Dwm8.js → BDdUgtQ9.js} +1 -1
- package/build/client/_app/immutable/chunks/{0b2v80OK.js → BP77Fyht.js} +1 -1
- package/build/client/_app/immutable/chunks/{dqF8mxBW.js → B_Mg_9D4.js} +1 -1
- package/build/client/_app/immutable/chunks/BvE-N_5_.js +1 -0
- package/build/client/_app/immutable/chunks/C0Fq51PS.js +1 -0
- package/build/client/_app/immutable/chunks/CBu7zaX6.js +15 -0
- package/build/client/_app/immutable/chunks/CDs2jokv.js +1 -0
- package/build/client/_app/immutable/chunks/{B5RiPG8Z.js → CL6wPCzw.js} +1 -1
- package/build/client/_app/immutable/chunks/CMPe3AwH.js +1 -0
- package/build/client/_app/immutable/chunks/{b77-bq1n.js → CRxuTO84.js} +1 -1
- package/build/client/_app/immutable/chunks/CXlCR4o6.js +10 -0
- package/build/client/_app/immutable/chunks/{DQqLOGLe.js → CZZUqHxO.js} +1 -1
- package/build/client/_app/immutable/chunks/{aI_O2VuQ.js → CaFHnwyo.js} +1 -1
- package/build/client/_app/immutable/chunks/CbtqT1c8.js +1 -0
- package/build/client/_app/immutable/chunks/{DGYKsRyW.js → CfRqDrzx.js} +1 -1
- package/build/client/_app/immutable/chunks/CwzJ9AB4.js +1 -0
- package/build/client/_app/immutable/chunks/{DwOZdLDj.js → Cy2yzzl5.js} +1 -1
- package/build/client/_app/immutable/chunks/D067lFSc.js +2 -0
- package/build/client/_app/immutable/chunks/{C_U_Jvk5.js → D27MZEE2.js} +1 -1
- package/build/client/_app/immutable/chunks/{IlwbfbOu.js → D9KJP6hv.js} +1 -1
- package/build/client/_app/immutable/chunks/DO938hpm.js +1 -0
- package/build/client/_app/immutable/chunks/DrLgrJ3k.js +1 -0
- package/build/client/_app/immutable/chunks/DrupwIIS.js +1 -0
- package/build/client/_app/immutable/chunks/LGzrUxfF.js +1 -0
- package/build/client/_app/immutable/chunks/{D7vimbmk.js → PUpq0Ki5.js} +1 -1
- package/build/client/_app/immutable/chunks/{DvxMaQv_.js → kSuEE8Bt.js} +1 -1
- package/build/client/_app/immutable/chunks/y79YFfGW.js +1 -0
- package/build/client/_app/immutable/chunks/zP_HZRCk.js +1 -0
- package/build/client/_app/immutable/entry/app.BEq8gOel.js +2 -0
- package/build/client/_app/immutable/entry/start.DmBlaUbV.js +1 -0
- package/build/client/_app/immutable/nodes/0.D63E8Q6i.js +1 -0
- package/build/client/_app/immutable/nodes/1.DXfG5P6X.js +1 -0
- package/build/client/_app/immutable/nodes/2.45XrHxUU.js +5 -0
- package/build/client/_app/version.json +1 -1
- package/build/env.js +0 -1
- package/build/handler.js +6 -9
- package/build/index.js +6 -9
- package/build/server/chunks/chunks/{archive.js-D2jtMmDo.js → archive.js-D7cGVWaq.js} +331 -31
- package/build/server/chunks/chunks/env.js-l0sNRNKZ.js +0 -1
- package/build/server/chunks/chunks/env2.js-C5BgBJDY.js +0 -1
- package/build/server/chunks/chunks/{exports.js-ClPPfcHj.js → exports.js-CvFPPbaH.js} +0 -6
- package/build/server/chunks/chunks/identity.js-NmGXxBz3.js +0 -1
- package/build/server/chunks/chunks/{index-server.js-CtH9Hqwf.js → index-server.js-DOq0LmqS.js} +87 -112
- package/build/server/chunks/chunks/internal.js-DZ8ZzzjN.js +0 -1
- package/build/server/chunks/chunks/{legacy-client.js-DAqKExQD.js → internal2.js-B2FekELn.js} +279 -7
- package/build/server/chunks/chunks/{level-filter.js-D9MNrew3.js → level-filter.js-kKdNjmbR.js} +2 -3
- package/build/server/chunks/chunks/{log-buffer.js-A9FA-Qv8.js → log-buffer.js-BjT3sJlh.js} +1 -2
- package/build/server/chunks/chunks/regions.js-COf7DgnH.js +0 -1
- package/build/server/chunks/chunks/shared-server.js-Dn5XheXH.js +0 -1
- package/build/server/chunks/chunks/shared.js-CgjUIvRK.js +0 -1
- package/build/server/chunks/chunks/source.js-DZEVvuho.js +0 -1
- package/build/server/chunks/chunks/{state.js-i-NVNGIq.js → state.js-CdO6iuBd.js} +3 -4
- package/build/server/chunks/chunks/text-size.svelte.js-D09gVgvI.js +309 -0
- package/build/server/chunks/chunks/{time-range.js-BLMT8aU3.js → time-range.js-__87ZPq6.js} +9 -5
- package/build/server/chunks/chunks/uneval.js-DaakSYFQ.js +0 -1
- package/build/server/chunks/chunks/utils.js-BIlHjgGW.js +0 -1
- package/build/server/chunks/entries/endpoints/api/archive/{_server.ts.js-C4hWyXuu.js → _server.ts.js-D-97I3hr.js} +2 -3
- package/build/server/chunks/entries/endpoints/api/health/_server.ts.js-C5tfrpmC.js +0 -1
- package/build/server/chunks/entries/endpoints/api/identity/_server.ts.js-PWRPScuN.js +0 -1
- package/build/server/chunks/entries/endpoints/api/log-groups/{_server.ts.js-D4y43Vwe.js → _server.ts.js-BBBsBX5h.js} +2 -3
- package/build/server/chunks/entries/endpoints/api/regions/_server.ts.js-9_g0ojki.js +0 -1
- package/build/server/chunks/entries/endpoints/api/series/{_server.ts.js-DibT3Hjc.js → _server.ts.js-bsGqvQ1O.js} +4 -5
- package/build/server/chunks/entries/endpoints/api/stream/{_server.ts.js-BxXw5K0R.js → _server.ts.js-B6obpUbh.js} +211 -49
- package/build/server/chunks/entries/fallbacks/{error.svelte.js-ylsqA41Y.js → error.svelte.js-BupH3lxJ.js} +4 -7
- package/build/server/chunks/entries/pages/_layout.svelte.js-C3CVxu2T.js +621 -0
- package/build/server/chunks/entries/pages/{_page.svelte.js-C9-7d7mD.js → _page.svelte.js-DS9p1LVo.js} +643 -191
- package/build/server/chunks/{handler-Bqo8aDgP.js → handler-DrjCpeeA.js} +4 -5
- package/build/server/chunks/{index.js-fPvMujCL.js → index.js-BLTOesya.js} +3 -4
- package/build/server/chunks/{manifest.js-Bkj-8GaD.js → manifest.js-C1_IS4sj.js} +8 -9
- package/build/server/chunks/nodes/0.js-BHXaR9OX.js +8 -0
- package/build/server/chunks/nodes/1.js-C-coUSdu.js +8 -0
- package/build/server/chunks/nodes/2.js-Dor6Xgc7.js +8 -0
- package/build/shims.js +0 -1
- package/dist/cli/completions.js +24 -0
- package/dist/cli/index.js +144 -3
- package/dist/cli/mcp/agents.js +344 -0
- package/dist/cli/mcp/backend.js +235 -0
- package/dist/cli/mcp/run.js +245 -0
- package/dist/cli/mcp/stdio.js +103 -0
- package/dist/cli/mcp/tools.js +245 -0
- package/dist/cli/options.js +138 -25
- package/dist/cli/server.js +28 -0
- package/dist/cli/ui.js +20 -1
- package/dist/lib/time-range.js +14 -3
- package/package.json +21 -6
- package/build/client/_app/immutable/assets/0.ChTKqSf6.css +0 -2
- package/build/client/_app/immutable/assets/0.ChTKqSf6.css.br +0 -0
- package/build/client/_app/immutable/assets/0.ChTKqSf6.css.gz +0 -0
- package/build/client/_app/immutable/assets/BrushContext.2tkUc39H.css.br +0 -0
- package/build/client/_app/immutable/assets/BrushContext.2tkUc39H.css.gz +0 -0
- package/build/client/_app/immutable/assets/ChartAnnotations.Bw8CGteN.css.br +0 -0
- package/build/client/_app/immutable/assets/ChartAnnotations.Bw8CGteN.css.gz +0 -0
- package/build/client/_app/immutable/assets/Circle.C5MKzgk2.css.br +0 -1
- package/build/client/_app/immutable/assets/Circle.C5MKzgk2.css.gz +0 -0
- package/build/client/_app/immutable/assets/DefaultTooltip.CGOVIm3D.css.br +0 -0
- package/build/client/_app/immutable/assets/DefaultTooltip.CGOVIm3D.css.gz +0 -0
- package/build/client/_app/immutable/assets/EventScatter.0BkgJO-l.css.br +0 -0
- package/build/client/_app/immutable/assets/EventScatter.0BkgJO-l.css.gz +0 -0
- package/build/client/_app/immutable/assets/Labels.sEaJtb97.css.br +0 -0
- package/build/client/_app/immutable/assets/Labels.sEaJtb97.css.gz +0 -0
- package/build/client/_app/immutable/assets/Legend.DnhxhJ2I.css.br +0 -0
- package/build/client/_app/immutable/assets/Legend.DnhxhJ2I.css.gz +0 -0
- package/build/client/_app/immutable/assets/Path.B0wDzTrn.css.br +0 -0
- package/build/client/_app/immutable/assets/Path.B0wDzTrn.css.gz +0 -0
- package/build/client/_app/immutable/assets/TransformContext.1cjyViIk.css.br +0 -0
- package/build/client/_app/immutable/assets/TransformContext.1cjyViIk.css.gz +0 -0
- package/build/client/_app/immutable/assets/Voronoi.ce7atosu.css.br +0 -0
- package/build/client/_app/immutable/assets/Voronoi.ce7atosu.css.gz +0 -0
- package/build/client/_app/immutable/chunks/0b2v80OK.js.br +0 -0
- package/build/client/_app/immutable/chunks/0b2v80OK.js.gz +0 -0
- package/build/client/_app/immutable/chunks/5EFAIHuJ.js +0 -1
- package/build/client/_app/immutable/chunks/5EFAIHuJ.js.br +0 -0
- package/build/client/_app/immutable/chunks/5EFAIHuJ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B15XBe8D.js +0 -1
- package/build/client/_app/immutable/chunks/B15XBe8D.js.br +0 -0
- package/build/client/_app/immutable/chunks/B15XBe8D.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B5RiPG8Z.js.br +0 -2
- package/build/client/_app/immutable/chunks/B5RiPG8Z.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BR2LaRms.js.br +0 -1
- package/build/client/_app/immutable/chunks/BR2LaRms.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B_KVdCQT.js +0 -10
- package/build/client/_app/immutable/chunks/B_KVdCQT.js.br +0 -0
- package/build/client/_app/immutable/chunks/B_KVdCQT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bjy-W4x2.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bjy-W4x2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bl052uUt.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bl052uUt.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BuCpRsEL.js +0 -1
- package/build/client/_app/immutable/chunks/BuCpRsEL.js.br +0 -0
- package/build/client/_app/immutable/chunks/BuCpRsEL.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BvZtsVvW.js +0 -1
- package/build/client/_app/immutable/chunks/BvZtsVvW.js.br +0 -0
- package/build/client/_app/immutable/chunks/BvZtsVvW.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C3Y15ONf.js +0 -2
- package/build/client/_app/immutable/chunks/C3Y15ONf.js.br +0 -0
- package/build/client/_app/immutable/chunks/C3Y15ONf.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C58PZtCD.js.br +0 -0
- package/build/client/_app/immutable/chunks/C58PZtCD.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C9GPQYs7.js +0 -1
- package/build/client/_app/immutable/chunks/C9GPQYs7.js.br +0 -0
- package/build/client/_app/immutable/chunks/C9GPQYs7.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CBZpkDc1.js.br +0 -0
- package/build/client/_app/immutable/chunks/CBZpkDc1.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CCch3uox.js.br +0 -0
- package/build/client/_app/immutable/chunks/CCch3uox.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C_U_Jvk5.js.br +0 -0
- package/build/client/_app/immutable/chunks/C_U_Jvk5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Cd7JqZj9.js +0 -1
- package/build/client/_app/immutable/chunks/Cd7JqZj9.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cd7JqZj9.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D2PbcyDU.js +0 -1
- package/build/client/_app/immutable/chunks/D2PbcyDU.js.br +0 -0
- package/build/client/_app/immutable/chunks/D2PbcyDU.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D7vimbmk.js.br +0 -0
- package/build/client/_app/immutable/chunks/D7vimbmk.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DAqXSYzi.js +0 -1
- package/build/client/_app/immutable/chunks/DAqXSYzi.js.br +0 -0
- package/build/client/_app/immutable/chunks/DAqXSYzi.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DGYKsRyW.js.br +0 -0
- package/build/client/_app/immutable/chunks/DGYKsRyW.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DPaulGql.js +0 -1
- package/build/client/_app/immutable/chunks/DPaulGql.js.br +0 -1
- package/build/client/_app/immutable/chunks/DPaulGql.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DQqLOGLe.js.br +0 -0
- package/build/client/_app/immutable/chunks/DQqLOGLe.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DS3cLPAu.js.br +0 -0
- package/build/client/_app/immutable/chunks/DS3cLPAu.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Db0q5_zr.js.br +0 -0
- package/build/client/_app/immutable/chunks/Db0q5_zr.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dfvzj6n2.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dfvzj6n2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dkh4Dwm8.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dkh4Dwm8.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DnqfXHAL.js +0 -15
- package/build/client/_app/immutable/chunks/DnqfXHAL.js.br +0 -0
- package/build/client/_app/immutable/chunks/DnqfXHAL.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DsYron7_.js +0 -1
- package/build/client/_app/immutable/chunks/DsYron7_.js.br +0 -0
- package/build/client/_app/immutable/chunks/DsYron7_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DuM1cPdZ.js +0 -1
- package/build/client/_app/immutable/chunks/DuM1cPdZ.js.br +0 -0
- package/build/client/_app/immutable/chunks/DuM1cPdZ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DvxMaQv_.js.br +0 -0
- package/build/client/_app/immutable/chunks/DvxMaQv_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DwOZdLDj.js.br +0 -0
- package/build/client/_app/immutable/chunks/DwOZdLDj.js.gz +0 -0
- package/build/client/_app/immutable/chunks/HclGiUj8.js.br +0 -0
- package/build/client/_app/immutable/chunks/HclGiUj8.js.gz +0 -0
- package/build/client/_app/immutable/chunks/IlwbfbOu.js.br +0 -0
- package/build/client/_app/immutable/chunks/IlwbfbOu.js.gz +0 -0
- package/build/client/_app/immutable/chunks/RobXhXPM.js.br +0 -1
- package/build/client/_app/immutable/chunks/RobXhXPM.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Y5urAfNy.js.br +0 -0
- package/build/client/_app/immutable/chunks/Y5urAfNy.js.gz +0 -0
- package/build/client/_app/immutable/chunks/aI_O2VuQ.js.br +0 -0
- package/build/client/_app/immutable/chunks/aI_O2VuQ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/b77-bq1n.js.br +0 -0
- package/build/client/_app/immutable/chunks/b77-bq1n.js.gz +0 -0
- package/build/client/_app/immutable/chunks/dqF8mxBW.js.br +0 -0
- package/build/client/_app/immutable/chunks/dqF8mxBW.js.gz +0 -0
- package/build/client/_app/immutable/chunks/gkAHSOnS.js +0 -1
- package/build/client/_app/immutable/chunks/gkAHSOnS.js.br +0 -0
- package/build/client/_app/immutable/chunks/gkAHSOnS.js.gz +0 -0
- package/build/client/_app/immutable/chunks/pqiPC7Y8.js +0 -3
- package/build/client/_app/immutable/chunks/pqiPC7Y8.js.br +0 -0
- package/build/client/_app/immutable/chunks/pqiPC7Y8.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ti8ecMFX.js +0 -1
- package/build/client/_app/immutable/chunks/ti8ecMFX.js.br +0 -0
- package/build/client/_app/immutable/chunks/ti8ecMFX.js.gz +0 -0
- package/build/client/_app/immutable/chunks/xihTtKlq.js.br +0 -1
- package/build/client/_app/immutable/chunks/xihTtKlq.js.gz +0 -0
- package/build/client/_app/immutable/chunks/yCfI4PCa.js.br +0 -0
- package/build/client/_app/immutable/chunks/yCfI4PCa.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.CTR4aUFT.js +0 -2
- package/build/client/_app/immutable/entry/app.CTR4aUFT.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CTR4aUFT.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.CC6Ln8E2.js +0 -1
- package/build/client/_app/immutable/entry/start.CC6Ln8E2.js.br +0 -0
- package/build/client/_app/immutable/entry/start.CC6Ln8E2.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.CvUxmLsM.js +0 -1
- package/build/client/_app/immutable/nodes/0.CvUxmLsM.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.CvUxmLsM.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.CbSHqfEx.js +0 -1
- package/build/client/_app/immutable/nodes/1.CbSHqfEx.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.CbSHqfEx.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.DcD5v8dU.js +0 -5
- package/build/client/_app/immutable/nodes/2.DcD5v8dU.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.DcD5v8dU.js.gz +0 -0
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/client/robots.txt.br +0 -0
- package/build/client/robots.txt.gz +0 -0
- package/build/env.js.map +0 -1
- package/build/handler.js.map +0 -1
- package/build/index.js.map +0 -1
- package/build/server/chunks/chunks/Arc.canvas.js-CN0KDoHG.js +0 -701
- package/build/server/chunks/chunks/Arc.canvas.js-CN0KDoHG.js.map +0 -1
- package/build/server/chunks/chunks/Arc.js-C8EC9NoE.js +0 -31
- package/build/server/chunks/chunks/Arc.js-C8EC9NoE.js.map +0 -1
- package/build/server/chunks/chunks/Bar.js-DtAb3LZZ.js +0 -448
- package/build/server/chunks/chunks/Bar.js-DtAb3LZZ.js.map +0 -1
- package/build/server/chunks/chunks/ChartAnnotations.js-twzDSVzY.js +0 -983
- package/build/server/chunks/chunks/ChartAnnotations.js-twzDSVzY.js.map +0 -1
- package/build/server/chunks/chunks/Circle.html.js-BJywADGK.js +0 -355
- package/build/server/chunks/chunks/Circle.html.js-BJywADGK.js.map +0 -1
- package/build/server/chunks/chunks/ClipPath.canvas.js-9Fc0bTEM.js +0 -170
- package/build/server/chunks/chunks/ClipPath.canvas.js-9Fc0bTEM.js.map +0 -1
- package/build/server/chunks/chunks/DefaultTooltip.js-C2NWK2AD.js +0 -352
- package/build/server/chunks/chunks/DefaultTooltip.js-C2NWK2AD.js.map +0 -1
- package/build/server/chunks/chunks/EventScatter.js-CO2GonW-.js +0 -7370
- package/build/server/chunks/chunks/EventScatter.js-CO2GonW-.js.map +0 -1
- package/build/server/chunks/chunks/Labels.js-DB9qoyZ3.js +0 -497
- package/build/server/chunks/chunks/Labels.js-DB9qoyZ3.js.map +0 -1
- package/build/server/chunks/chunks/Legend.js-B_ArjxQ7.js +0 -343
- package/build/server/chunks/chunks/Legend.js-B_ArjxQ7.js.map +0 -1
- package/build/server/chunks/chunks/Line.html.js-B1REcOFe.js +0 -423
- package/build/server/chunks/chunks/Line.html.js-B1REcOFe.js.map +0 -1
- package/build/server/chunks/chunks/Link.canvas.js-nWimAHfH.js +0 -756
- package/build/server/chunks/chunks/Link.canvas.js-nWimAHfH.js.map +0 -1
- package/build/server/chunks/chunks/Path.canvas.js-5A9wB8zQ.js +0 -1259
- package/build/server/chunks/chunks/Path.canvas.js-5A9wB8zQ.js.map +0 -1
- package/build/server/chunks/chunks/Points.html.js-B2o3k-ZZ.js +0 -228
- package/build/server/chunks/chunks/Points.html.js-B2o3k-ZZ.js.map +0 -1
- package/build/server/chunks/chunks/Points.js-D7ozN9W5.js +0 -14
- package/build/server/chunks/chunks/Points.js-D7ozN9W5.js.map +0 -1
- package/build/server/chunks/chunks/Points2.js-BVbWugLT.js +0 -25
- package/build/server/chunks/chunks/Points2.js-BVbWugLT.js.map +0 -1
- package/build/server/chunks/chunks/Rect.html.js-DnQ6ObhQ.js +0 -547
- package/build/server/chunks/chunks/Rect.html.js-DnQ6ObhQ.js.map +0 -1
- package/build/server/chunks/chunks/Spline.js-YnAxvrKY.js +0 -516
- package/build/server/chunks/chunks/Spline.js-YnAxvrKY.js.map +0 -1
- package/build/server/chunks/chunks/Text.html.js-LbmYJb11.js +0 -847
- package/build/server/chunks/chunks/Text.html.js-LbmYJb11.js.map +0 -1
- package/build/server/chunks/chunks/TooltipItem.js-Ce-blieA.js +0 -314
- package/build/server/chunks/chunks/TooltipItem.js-Ce-blieA.js.map +0 -1
- package/build/server/chunks/chunks/Voronoi.js-CalFJAXH.js +0 -2052
- package/build/server/chunks/chunks/Voronoi.js-CalFJAXH.js.map +0 -1
- package/build/server/chunks/chunks/archive.js-D2jtMmDo.js.map +0 -1
- package/build/server/chunks/chunks/array.js-CBp0H4t3.js +0 -8
- package/build/server/chunks/chunks/array.js-CBp0H4t3.js.map +0 -1
- package/build/server/chunks/chunks/attributes.js-CbKEpZKa.js +0 -25
- package/build/server/chunks/chunks/attributes.js-CbKEpZKa.js.map +0 -1
- package/build/server/chunks/chunks/band.js-CjzHWr4k.js +0 -155
- package/build/server/chunks/chunks/band.js-CjzHWr4k.js.map +0 -1
- package/build/server/chunks/chunks/centroid.js-BnGN3LH0.js +0 -1356
- package/build/server/chunks/chunks/centroid.js-BnGN3LH0.js.map +0 -1
- package/build/server/chunks/chunks/common.js-BvQnfkFo.js +0 -5760
- package/build/server/chunks/chunks/common.js-BvQnfkFo.js.map +0 -1
- package/build/server/chunks/chunks/env.js-l0sNRNKZ.js.map +0 -1
- package/build/server/chunks/chunks/env2.js-C5BgBJDY.js.map +0 -1
- package/build/server/chunks/chunks/events.js-zIVaXIP1.js +0 -95
- package/build/server/chunks/chunks/events.js-zIVaXIP1.js.map +0 -1
- package/build/server/chunks/chunks/exports.js-ClPPfcHj.js.map +0 -1
- package/build/server/chunks/chunks/group.js-D0SfevId.js +0 -30
- package/build/server/chunks/chunks/group.js-D0SfevId.js.map +0 -1
- package/build/server/chunks/chunks/identity.js-NmGXxBz3.js.map +0 -1
- package/build/server/chunks/chunks/index-server.js-CtH9Hqwf.js.map +0 -1
- package/build/server/chunks/chunks/index-server2.js-l0sNRNKZ.js +0 -2
- package/build/server/chunks/chunks/index-server2.js-l0sNRNKZ.js.map +0 -1
- package/build/server/chunks/chunks/internal.js-DZ8ZzzjN.js.map +0 -1
- package/build/server/chunks/chunks/internal2.js-CfVVfAb5.js +0 -188
- package/build/server/chunks/chunks/internal2.js-CfVVfAb5.js.map +0 -1
- package/build/server/chunks/chunks/key.svelte.js-Cq0L6YlN.js +0 -695
- package/build/server/chunks/chunks/key.svelte.js-Cq0L6YlN.js.map +0 -1
- package/build/server/chunks/chunks/legacy-client.js-DAqKExQD.js.map +0 -1
- package/build/server/chunks/chunks/level-filter.js-D9MNrew3.js.map +0 -1
- package/build/server/chunks/chunks/lineRadial.js-B7ZNP_Jp.js +0 -126
- package/build/server/chunks/chunks/lineRadial.js-B7ZNP_Jp.js.map +0 -1
- package/build/server/chunks/chunks/linear.js-CHlwr1I4.js +0 -1046
- package/build/server/chunks/chunks/linear.js-CHlwr1I4.js.map +0 -1
- package/build/server/chunks/chunks/log-buffer.js-A9FA-Qv8.js.map +0 -1
- package/build/server/chunks/chunks/math.js-BqujbaBs.js +0 -50
- package/build/server/chunks/chunks/math.js-BqujbaBs.js.map +0 -1
- package/build/server/chunks/chunks/max.js-CuS0BpRI.js +0 -11
- package/build/server/chunks/chunks/max.js-CuS0BpRI.js.map +0 -1
- package/build/server/chunks/chunks/min.js-DZWt5tPl.js +0 -11
- package/build/server/chunks/chunks/min.js-DZWt5tPl.js.map +0 -1
- package/build/server/chunks/chunks/motion.svelte.js-Crk8ri1u.js +0 -677
- package/build/server/chunks/chunks/motion.svelte.js-Crk8ri1u.js.map +0 -1
- package/build/server/chunks/chunks/occlusion.js-ot9_OqWn.js +0 -33
- package/build/server/chunks/chunks/occlusion.js-ot9_OqWn.js.map +0 -1
- package/build/server/chunks/chunks/path.js-BizMrlzb.js +0 -488
- package/build/server/chunks/chunks/path.js-BizMrlzb.js.map +0 -1
- package/build/server/chunks/chunks/path2.js-DLVU8nc9.js +0 -27
- package/build/server/chunks/chunks/path2.js-DLVU8nc9.js.map +0 -1
- package/build/server/chunks/chunks/pointRadial.js-Deeu1LXx.js +0 -7
- package/build/server/chunks/chunks/pointRadial.js-Deeu1LXx.js.map +0 -1
- package/build/server/chunks/chunks/rect.svelte.js-_0PgI5fe.js +0 -187
- package/build/server/chunks/chunks/rect.svelte.js-_0PgI5fe.js.map +0 -1
- package/build/server/chunks/chunks/regions.js-COf7DgnH.js.map +0 -1
- package/build/server/chunks/chunks/scales.svelte.js-DeNkKcI-.js +0 -276
- package/build/server/chunks/chunks/scales.svelte.js-DeNkKcI-.js.map +0 -1
- package/build/server/chunks/chunks/series-buckets.js-C-vMEJT2.js +0 -316
- package/build/server/chunks/chunks/series-buckets.js-C-vMEJT2.js.map +0 -1
- package/build/server/chunks/chunks/shared-server.js-Dn5XheXH.js.map +0 -1
- package/build/server/chunks/chunks/shared.js-CgjUIvRK.js.map +0 -1
- package/build/server/chunks/chunks/source.js-DZEVvuho.js.map +0 -1
- package/build/server/chunks/chunks/state.js-i-NVNGIq.js.map +0 -1
- package/build/server/chunks/chunks/time-range.js-BLMT8aU3.js.map +0 -1
- package/build/server/chunks/chunks/types.js-x3GyGPOz.js +0 -11
- package/build/server/chunks/chunks/types.js-x3GyGPOz.js.map +0 -1
- package/build/server/chunks/chunks/uneval.js-DaakSYFQ.js.map +0 -1
- package/build/server/chunks/chunks/utils.js-BIlHjgGW.js.map +0 -1
- package/build/server/chunks/entries/endpoints/api/archive/_server.ts.js-C4hWyXuu.js.map +0 -1
- package/build/server/chunks/entries/endpoints/api/health/_server.ts.js-C5tfrpmC.js.map +0 -1
- package/build/server/chunks/entries/endpoints/api/identity/_server.ts.js-PWRPScuN.js.map +0 -1
- package/build/server/chunks/entries/endpoints/api/log-groups/_server.ts.js-D4y43Vwe.js.map +0 -1
- package/build/server/chunks/entries/endpoints/api/regions/_server.ts.js-9_g0ojki.js.map +0 -1
- package/build/server/chunks/entries/endpoints/api/series/_server.ts.js-DibT3Hjc.js.map +0 -1
- package/build/server/chunks/entries/endpoints/api/stream/_server.ts.js-BxXw5K0R.js.map +0 -1
- package/build/server/chunks/entries/fallbacks/error.svelte.js-ylsqA41Y.js.map +0 -1
- package/build/server/chunks/entries/pages/_layout.svelte.js-D7sAdBVX.js +0 -113
- package/build/server/chunks/entries/pages/_layout.svelte.js-D7sAdBVX.js.map +0 -1
- package/build/server/chunks/entries/pages/_page.svelte.js-C9-7d7mD.js.map +0 -1
- package/build/server/chunks/handler-Bqo8aDgP.js.map +0 -1
- package/build/server/chunks/index.js-fPvMujCL.js.map +0 -1
- package/build/server/chunks/manifest.js-Bkj-8GaD.js.map +0 -1
- package/build/server/chunks/nodes/0.js-7J6kXnEo.js +0 -9
- package/build/server/chunks/nodes/0.js-7J6kXnEo.js.map +0 -1
- package/build/server/chunks/nodes/1.js-DZXnUx67.js +0 -9
- package/build/server/chunks/nodes/1.js-DZXnUx67.js.map +0 -1
- package/build/server/chunks/nodes/2.js-85y9-1SS.js +0 -9
- package/build/server/chunks/nodes/2.js-85y9-1SS.js.map +0 -1
- package/build/shims.js.map +0 -1
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The agents watch-tail knows how to configure, how to tell whether they are
|
|
3
|
+
* installed, and how to merge a `watch-tail` server entry into their files.
|
|
4
|
+
*
|
|
5
|
+
* Everything is a pure function of the paths and text it is handed: detection
|
|
6
|
+
* takes an `exists`, planning takes the current file contents, so the whole
|
|
7
|
+
* module can be tested against fabricated home directories. Writing files is the
|
|
8
|
+
* caller's job, which keeps this module free of side effects.
|
|
9
|
+
*
|
|
10
|
+
* The registry only lists agents whose configuration format is stable and
|
|
11
|
+
* documented. An agent that is not listed can still be wired up by hand; run
|
|
12
|
+
* `watch-tail mcp init --print` to see the exact entry.
|
|
13
|
+
*/
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
/** Name the server is registered under in every agent. */
|
|
16
|
+
const MCP_SERVER_NAME = 'watch-tail';
|
|
17
|
+
/** `$XDG_CONFIG_HOME`, or the platform default. */
|
|
18
|
+
function xdgConfig(ctx) {
|
|
19
|
+
return ctx.env.XDG_CONFIG_HOME?.trim() || join(ctx.home, '.config');
|
|
20
|
+
}
|
|
21
|
+
/** `%APPDATA%` on Windows. */
|
|
22
|
+
function appData(ctx) {
|
|
23
|
+
return ctx.env.APPDATA?.trim() || join(ctx.home, 'AppData', 'Roaming');
|
|
24
|
+
}
|
|
25
|
+
/** macOS application support directory. */
|
|
26
|
+
function macSupport(ctx) {
|
|
27
|
+
return join(ctx.home, 'Library', 'Application Support');
|
|
28
|
+
}
|
|
29
|
+
/** VS Code's per-user data directory. */
|
|
30
|
+
function vscodeData(ctx) {
|
|
31
|
+
if (ctx.platform === 'darwin')
|
|
32
|
+
return join(macSupport(ctx), 'Code');
|
|
33
|
+
if (ctx.platform === 'win32')
|
|
34
|
+
return join(appData(ctx), 'Code');
|
|
35
|
+
return join(xdgConfig(ctx), 'Code');
|
|
36
|
+
}
|
|
37
|
+
/** Claude Desktop's data directory. */
|
|
38
|
+
function claudeDesktopData(ctx) {
|
|
39
|
+
if (ctx.platform === 'darwin')
|
|
40
|
+
return join(macSupport(ctx), 'Claude');
|
|
41
|
+
if (ctx.platform === 'win32')
|
|
42
|
+
return join(appData(ctx), 'Claude');
|
|
43
|
+
return join(xdgConfig(ctx), 'Claude');
|
|
44
|
+
}
|
|
45
|
+
/** Every agent this build configures, in the order they are offered. */
|
|
46
|
+
export const AGENTS = [
|
|
47
|
+
{
|
|
48
|
+
id: 'claude-desktop',
|
|
49
|
+
name: 'Claude Desktop',
|
|
50
|
+
format: 'json',
|
|
51
|
+
serverKey: 'mcpServers',
|
|
52
|
+
userPath: (ctx) => join(claudeDesktopData(ctx), 'claude_desktop_config.json'),
|
|
53
|
+
detect: (ctx) => [claudeDesktopData(ctx)],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'claude-code',
|
|
57
|
+
name: 'Claude Code',
|
|
58
|
+
format: 'json',
|
|
59
|
+
serverKey: 'mcpServers',
|
|
60
|
+
userPath: (ctx) => join(ctx.home, '.claude.json'),
|
|
61
|
+
projectPath: (ctx) => join(ctx.cwd, '.mcp.json'),
|
|
62
|
+
detect: (ctx) => [join(ctx.home, '.claude'), join(ctx.home, '.claude.json')],
|
|
63
|
+
binary: 'claude',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: 'cursor',
|
|
67
|
+
name: 'Cursor',
|
|
68
|
+
format: 'json',
|
|
69
|
+
serverKey: 'mcpServers',
|
|
70
|
+
userPath: (ctx) => join(ctx.home, '.cursor', 'mcp.json'),
|
|
71
|
+
projectPath: (ctx) => join(ctx.cwd, '.cursor', 'mcp.json'),
|
|
72
|
+
detect: (ctx) => [join(ctx.home, '.cursor')],
|
|
73
|
+
binary: 'cursor',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 'windsurf',
|
|
77
|
+
name: 'Windsurf',
|
|
78
|
+
format: 'json',
|
|
79
|
+
serverKey: 'mcpServers',
|
|
80
|
+
userPath: (ctx) => join(ctx.home, '.codeium', 'windsurf', 'mcp_config.json'),
|
|
81
|
+
detect: (ctx) => [join(ctx.home, '.codeium', 'windsurf')],
|
|
82
|
+
binary: 'windsurf',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: 'vscode',
|
|
86
|
+
name: 'VS Code',
|
|
87
|
+
format: 'json',
|
|
88
|
+
serverKey: 'servers',
|
|
89
|
+
userPath: (ctx) => join(vscodeData(ctx), 'User', 'mcp.json'),
|
|
90
|
+
projectPath: (ctx) => join(ctx.cwd, '.vscode', 'mcp.json'),
|
|
91
|
+
detect: (ctx) => [vscodeData(ctx)],
|
|
92
|
+
binary: 'code',
|
|
93
|
+
entryExtras: { type: 'stdio' },
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'gemini',
|
|
97
|
+
name: 'Gemini CLI',
|
|
98
|
+
format: 'json',
|
|
99
|
+
serverKey: 'mcpServers',
|
|
100
|
+
userPath: (ctx) => join(ctx.home, '.gemini', 'settings.json'),
|
|
101
|
+
detect: (ctx) => [join(ctx.home, '.gemini')],
|
|
102
|
+
binary: 'gemini',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: 'codex',
|
|
106
|
+
name: 'Codex CLI',
|
|
107
|
+
format: 'toml',
|
|
108
|
+
serverKey: 'mcp_servers',
|
|
109
|
+
userPath: (ctx) => join(ctx.home, '.codex', 'config.toml'),
|
|
110
|
+
detect: (ctx) => [join(ctx.home, '.codex')],
|
|
111
|
+
binary: 'codex',
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
/** Looks up an agent by id. */
|
|
115
|
+
export function findAgent(id) {
|
|
116
|
+
return AGENTS.find((agent) => agent.id === id) ?? null;
|
|
117
|
+
}
|
|
118
|
+
/** Checks every known agent against the filesystem and the PATH. */
|
|
119
|
+
export function detectAgents(ctx, io) {
|
|
120
|
+
return AGENTS.map((agent) => {
|
|
121
|
+
const paths = agent.detect(ctx);
|
|
122
|
+
const installed = paths.some((path) => io.exists(path)) ||
|
|
123
|
+
(agent.binary !== undefined && io.commandExists?.(agent.binary) === true);
|
|
124
|
+
return { agent, paths, installed };
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Builds the launch command written into every agent config.
|
|
129
|
+
*
|
|
130
|
+
* The default goes through `npx`, so the agent keeps working after watch-tail is
|
|
131
|
+
* upgraded; the version is pinned so the config is reproducible. `--command`
|
|
132
|
+
* and `--args` replace either half for a local build.
|
|
133
|
+
*/
|
|
134
|
+
export function mcpServerCommand(input) {
|
|
135
|
+
const command = input.command?.trim() ?? '';
|
|
136
|
+
return {
|
|
137
|
+
command: command.length > 0 ? command : 'npx',
|
|
138
|
+
args: [
|
|
139
|
+
...(input.args && input.args.length > 0 ? input.args : ['-y', `watch-tail@${input.version}`]),
|
|
140
|
+
'mcp',
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/** A config file that could not be merged safely. */
|
|
145
|
+
export class AgentConfigError extends Error {
|
|
146
|
+
constructor(message) {
|
|
147
|
+
super(message);
|
|
148
|
+
this.name = 'AgentConfigError';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/** Canonical JSON with object keys sorted, for order-independent comparison. */
|
|
152
|
+
function canonical(value) {
|
|
153
|
+
if (Array.isArray(value))
|
|
154
|
+
return `[${value.map(canonical).join(',')}]`;
|
|
155
|
+
if (typeof value === 'object' && value !== null) {
|
|
156
|
+
const entries = Object.entries(value).toSorted(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
157
|
+
return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(',')}}`;
|
|
158
|
+
}
|
|
159
|
+
return JSON.stringify(value) ?? 'null';
|
|
160
|
+
}
|
|
161
|
+
/** The entry stored for watch-tail, including any agent-specific extras. */
|
|
162
|
+
function serverEntry(agent, command) {
|
|
163
|
+
return { ...agent.entryExtras, command: command.command, args: command.args };
|
|
164
|
+
}
|
|
165
|
+
/** True for a JSON object (not an array or null). */
|
|
166
|
+
function isRecord(value) {
|
|
167
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
168
|
+
}
|
|
169
|
+
/** Merges the entry into a JSON config file. */
|
|
170
|
+
function planJsonConfig(agent, existing, command) {
|
|
171
|
+
const trimmed = existing.trim();
|
|
172
|
+
let root;
|
|
173
|
+
if (trimmed.length === 0) {
|
|
174
|
+
root = {};
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
try {
|
|
178
|
+
const decoded = JSON.parse(trimmed);
|
|
179
|
+
if (typeof decoded !== 'object' || decoded === null || Array.isArray(decoded)) {
|
|
180
|
+
throw new AgentConfigError('the config file does not hold a JSON object');
|
|
181
|
+
}
|
|
182
|
+
root = decoded;
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (error instanceof AgentConfigError)
|
|
186
|
+
throw error;
|
|
187
|
+
throw new AgentConfigError(`the existing config is not valid JSON (${error instanceof Error ? error.message : String(error)})`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const mapValue = root[agent.serverKey];
|
|
191
|
+
const map = isRecord(mapValue) ? mapValue : {};
|
|
192
|
+
// Only the launch fields are ours: anything the user added to the entry (an
|
|
193
|
+
// `env` with AWS_PROFILE, a timeout) survives a re-run.
|
|
194
|
+
const current = map[MCP_SERVER_NAME];
|
|
195
|
+
const entry = { ...(isRecord(current) ? current : {}), ...serverEntry(agent, command) };
|
|
196
|
+
const changed = canonical(current) !== canonical(entry);
|
|
197
|
+
root[agent.serverKey] = { ...map, [MCP_SERVER_NAME]: entry };
|
|
198
|
+
return { contents: `${JSON.stringify(root, null, 2)}\n`, changed };
|
|
199
|
+
}
|
|
200
|
+
/** Renders a TOML basic string using JSON's own escaping, which TOML shares. */
|
|
201
|
+
function quoteToml(value) {
|
|
202
|
+
return JSON.stringify(value);
|
|
203
|
+
}
|
|
204
|
+
/** The TOML keys watch-tail owns in the Codex `[mcp_servers.watch-tail]` section. */
|
|
205
|
+
function tomlEntries(command) {
|
|
206
|
+
return [
|
|
207
|
+
['command', quoteToml(command.command)],
|
|
208
|
+
['args', `[${command.args.map(quoteToml).join(', ')}]`],
|
|
209
|
+
];
|
|
210
|
+
}
|
|
211
|
+
/** Renders the Codex `[mcp_servers.watch-tail]` section. */
|
|
212
|
+
function tomlSection(agent, command) {
|
|
213
|
+
return [
|
|
214
|
+
`[${agent.serverKey}.${MCP_SERVER_NAME}]`,
|
|
215
|
+
...tomlEntries(command).map(([key, value]) => `${key} = ${value}`),
|
|
216
|
+
];
|
|
217
|
+
}
|
|
218
|
+
/** A table header's dotted name with quotes and spaces removed, or `null`. */
|
|
219
|
+
function tomlHeaderName(line) {
|
|
220
|
+
const match = /^\s*\[([^[\]]+)\]\s*(?:#.*)?$/.exec(line);
|
|
221
|
+
if (match === null)
|
|
222
|
+
return null;
|
|
223
|
+
return match[1]
|
|
224
|
+
.split('.')
|
|
225
|
+
.map((part) => part
|
|
226
|
+
.trim()
|
|
227
|
+
.replace(/^"(.*)"$/, '$1')
|
|
228
|
+
.replace(/^'(.*)'$/, '$1'))
|
|
229
|
+
.join('.');
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* How far a line moves the depth of open `[` arrays, ignoring brackets inside
|
|
233
|
+
* strings and comments, so a multi-line `args = [` is read as one value.
|
|
234
|
+
*/
|
|
235
|
+
function bracketDelta(line) {
|
|
236
|
+
let delta = 0;
|
|
237
|
+
let quote = null;
|
|
238
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
239
|
+
const char = line[index];
|
|
240
|
+
if (quote !== null) {
|
|
241
|
+
if (char === '\\' && quote === '"')
|
|
242
|
+
index += 1;
|
|
243
|
+
else if (char === quote)
|
|
244
|
+
quote = null;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (char === '#')
|
|
248
|
+
break;
|
|
249
|
+
if (char === '"' || char === "'")
|
|
250
|
+
quote = char;
|
|
251
|
+
else if (char === '[')
|
|
252
|
+
delta += 1;
|
|
253
|
+
else if (char === ']')
|
|
254
|
+
delta -= 1;
|
|
255
|
+
}
|
|
256
|
+
return delta;
|
|
257
|
+
}
|
|
258
|
+
/** The key a `key = value` line assigns, or `null`. */
|
|
259
|
+
function tomlKey(line) {
|
|
260
|
+
const match = /^\s*("[^"]*"|'[^']*'|[A-Za-z0-9_-]+)\s*=/.exec(line);
|
|
261
|
+
return match === null ? null : match[1].replace(/^["'](.*)["']$/, '$1');
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Sets `entries` in the `[section]` table, or appends the table when the file
|
|
265
|
+
* does not have one.
|
|
266
|
+
*
|
|
267
|
+
* Only the named keys are rewritten (a multi-line value is replaced whole);
|
|
268
|
+
* every other key the user put in the table, such as an `env`, is kept.
|
|
269
|
+
*/
|
|
270
|
+
export function upsertTomlSection(text, section, entries) {
|
|
271
|
+
const lines = text.length === 0 ? [] : text.replace(/\n$/, '').split('\n');
|
|
272
|
+
const start = lines.findIndex((line) => tomlHeaderName(line) === section);
|
|
273
|
+
if (start < 0) {
|
|
274
|
+
const block = [`[${section}]`, ...entries.map(([key, value]) => `${key} = ${value}`)];
|
|
275
|
+
const body = lines.length > 0 ? [...lines, '', ...block] : block;
|
|
276
|
+
return body.join('\n') + '\n';
|
|
277
|
+
}
|
|
278
|
+
// The table runs to the next header (`[t]` or `[[t]]`). Values are read whole,
|
|
279
|
+
// so a line of a multi-line array is never mistaken for one.
|
|
280
|
+
const body = [];
|
|
281
|
+
let end = start + 1;
|
|
282
|
+
while (end < lines.length) {
|
|
283
|
+
if (lines[end].trimStart().startsWith('['))
|
|
284
|
+
break;
|
|
285
|
+
const value = [lines[end]];
|
|
286
|
+
let depth = bracketDelta(lines[end]);
|
|
287
|
+
end += 1;
|
|
288
|
+
while (depth > 0 && end < lines.length) {
|
|
289
|
+
value.push(lines[end]);
|
|
290
|
+
depth += bracketDelta(lines[end]);
|
|
291
|
+
end += 1;
|
|
292
|
+
}
|
|
293
|
+
body.push({ lines: value, key: tomlKey(value[0]) });
|
|
294
|
+
}
|
|
295
|
+
const pending = new Map(entries);
|
|
296
|
+
const rewritten = [];
|
|
297
|
+
for (const item of body) {
|
|
298
|
+
const replacement = item.key === null ? undefined : pending.get(item.key);
|
|
299
|
+
if (replacement === undefined || item.key === null) {
|
|
300
|
+
rewritten.push(...item.lines);
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
rewritten.push(`${item.key} = ${replacement}`);
|
|
304
|
+
pending.delete(item.key);
|
|
305
|
+
}
|
|
306
|
+
// Keys the table did not have go after its last non-blank line.
|
|
307
|
+
let insertAt = rewritten.length;
|
|
308
|
+
while (insertAt > 0 && rewritten[insertAt - 1].trim().length === 0)
|
|
309
|
+
insertAt -= 1;
|
|
310
|
+
rewritten.splice(insertAt, 0, ...[...pending].map(([key, value]) => `${key} = ${value}`));
|
|
311
|
+
return [...lines.slice(0, start + 1), ...rewritten, ...lines.slice(end)].join('\n') + '\n';
|
|
312
|
+
}
|
|
313
|
+
/** Merges the entry into a TOML config file (Codex CLI). */
|
|
314
|
+
function planTomlConfig(agent, existing, command) {
|
|
315
|
+
const section = `${agent.serverKey}.${MCP_SERVER_NAME}`;
|
|
316
|
+
const contents = upsertTomlSection(existing, section, tomlEntries(command));
|
|
317
|
+
const normalized = existing.length === 0 || existing.endsWith('\n') ? existing : `${existing}\n`;
|
|
318
|
+
return { contents, changed: contents !== normalized };
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Plans one file write without touching the filesystem.
|
|
322
|
+
*
|
|
323
|
+
* Throws {@link AgentConfigError} when an existing file cannot be merged safely,
|
|
324
|
+
* so a hand-written config is never clobbered.
|
|
325
|
+
*/
|
|
326
|
+
export function planAgentConfig(input) {
|
|
327
|
+
const { agent, existing, command } = input;
|
|
328
|
+
return agent.format === 'toml'
|
|
329
|
+
? planTomlConfig(agent, existing, command)
|
|
330
|
+
: planJsonConfig(agent, existing, command);
|
|
331
|
+
}
|
|
332
|
+
/** The config file to write for a scope, or `null` when the scope is unsupported. */
|
|
333
|
+
export function agentConfigPath(agent, ctx, scope) {
|
|
334
|
+
if (scope === 'project')
|
|
335
|
+
return agent.projectPath?.(ctx) ?? null;
|
|
336
|
+
return agent.userPath(ctx);
|
|
337
|
+
}
|
|
338
|
+
/** A copy-pasteable snippet for an agent that is configured by hand. */
|
|
339
|
+
export function agentConfigSnippet(agent, command) {
|
|
340
|
+
const entry = serverEntry(agent, command);
|
|
341
|
+
if (agent.format === 'toml')
|
|
342
|
+
return `${tomlSection(agent, command).join('\n')}\n`;
|
|
343
|
+
return JSON.stringify({ [agent.serverKey]: { [MCP_SERVER_NAME]: entry } }, null, 2) + '\n';
|
|
344
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/** A failed request, carrying the API's own error code when there is one. */
|
|
2
|
+
export class ApiRequestError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
status;
|
|
5
|
+
constructor(message, status, code) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'ApiRequestError';
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Parses one SSE frame (the text between blank lines) into an event and payload. */
|
|
13
|
+
export function parseSseFrame(raw) {
|
|
14
|
+
let event = 'message';
|
|
15
|
+
const dataLines = [];
|
|
16
|
+
for (const line of raw.split('\n')) {
|
|
17
|
+
if (line.length === 0 || line.startsWith(':'))
|
|
18
|
+
continue;
|
|
19
|
+
if (line.startsWith('event:')) {
|
|
20
|
+
event = line.slice('event:'.length).trim();
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (line.startsWith('data:')) {
|
|
24
|
+
const value = line.slice('data:'.length);
|
|
25
|
+
dataLines.push(value.startsWith(' ') ? value.slice(1) : value);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (dataLines.length === 0)
|
|
29
|
+
return null;
|
|
30
|
+
const text = dataLines.join('\n');
|
|
31
|
+
let data = text;
|
|
32
|
+
try {
|
|
33
|
+
data = JSON.parse(text);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// A non-JSON payload is passed through as its raw text.
|
|
37
|
+
}
|
|
38
|
+
return { event, data };
|
|
39
|
+
}
|
|
40
|
+
/** Parses every complete frame in `text`. */
|
|
41
|
+
export function parseSseFrames(text) {
|
|
42
|
+
const frames = [];
|
|
43
|
+
for (const block of text.replaceAll('\r\n', '\n').split('\n\n')) {
|
|
44
|
+
const frame = parseSseFrame(block);
|
|
45
|
+
if (frame !== null)
|
|
46
|
+
frames.push(frame);
|
|
47
|
+
}
|
|
48
|
+
return frames;
|
|
49
|
+
}
|
|
50
|
+
/** Folds one parsed frame into the outcome being collected. */
|
|
51
|
+
function applyFrame(outcome, frame) {
|
|
52
|
+
const data = frame.data;
|
|
53
|
+
if (frame.event === 'ready' && data !== null) {
|
|
54
|
+
if (typeof data.region === 'string')
|
|
55
|
+
outcome.region = data.region;
|
|
56
|
+
if (typeof data.source === 'string')
|
|
57
|
+
outcome.source = data.source;
|
|
58
|
+
if (Array.isArray(data.groups))
|
|
59
|
+
outcome.groups = data.groups.filter((group) => typeof group === 'string');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (frame.event === 'log' && data !== null && Array.isArray(data.events)) {
|
|
63
|
+
for (const event of data.events)
|
|
64
|
+
outcome.events.push(event);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (frame.event === 'error' && data !== null) {
|
|
68
|
+
const message = typeof data.message === 'string' ? data.message : 'unknown stream error';
|
|
69
|
+
outcome.error = message;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (frame.event === 'end' && data !== null && typeof data.reason === 'string') {
|
|
73
|
+
outcome.reason = data.reason;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Reads a `/api/stream` response to completion.
|
|
78
|
+
*
|
|
79
|
+
* The route always ends an archive or historic window on its own, and its `end`
|
|
80
|
+
* frame says why, so the reader never has to guess when to stop.
|
|
81
|
+
*/
|
|
82
|
+
export async function collectStream(response) {
|
|
83
|
+
const outcome = {
|
|
84
|
+
region: null,
|
|
85
|
+
source: 'cloudwatch',
|
|
86
|
+
groups: [],
|
|
87
|
+
events: [],
|
|
88
|
+
reason: null,
|
|
89
|
+
error: null,
|
|
90
|
+
};
|
|
91
|
+
const body = response.body;
|
|
92
|
+
if (body === null) {
|
|
93
|
+
for (const frame of parseSseFrames(await response.text()))
|
|
94
|
+
applyFrame(outcome, frame);
|
|
95
|
+
return outcome;
|
|
96
|
+
}
|
|
97
|
+
const reader = body.getReader();
|
|
98
|
+
const decoder = new TextDecoder();
|
|
99
|
+
let buffer = '';
|
|
100
|
+
try {
|
|
101
|
+
for (;;) {
|
|
102
|
+
const { done, value } = await reader.read();
|
|
103
|
+
if (done)
|
|
104
|
+
break;
|
|
105
|
+
buffer += decoder.decode(value, { stream: true });
|
|
106
|
+
let boundary = buffer.indexOf('\n\n');
|
|
107
|
+
while (boundary >= 0) {
|
|
108
|
+
const block = buffer.slice(0, boundary);
|
|
109
|
+
buffer = buffer.slice(boundary + 2);
|
|
110
|
+
const frame = parseSseFrame(block.replaceAll('\r\n', '\n'));
|
|
111
|
+
if (frame !== null)
|
|
112
|
+
applyFrame(outcome, frame);
|
|
113
|
+
boundary = buffer.indexOf('\n\n');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
reader.releaseLock();
|
|
119
|
+
}
|
|
120
|
+
buffer += decoder.decode();
|
|
121
|
+
const rest = parseSseFrame(buffer.replaceAll('\r\n', '\n'));
|
|
122
|
+
if (rest !== null)
|
|
123
|
+
applyFrame(outcome, rest);
|
|
124
|
+
return outcome;
|
|
125
|
+
}
|
|
126
|
+
/** Reads the API error envelope from a failed response, if it holds one. */
|
|
127
|
+
async function readApiError(response) {
|
|
128
|
+
let body = null;
|
|
129
|
+
try {
|
|
130
|
+
body = (await response.json());
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
body = null;
|
|
134
|
+
}
|
|
135
|
+
const message = body?.error ?? `watch-tail answered HTTP ${response.status}`;
|
|
136
|
+
return new ApiRequestError(message, response.status, body?.code);
|
|
137
|
+
}
|
|
138
|
+
/** Builds a URL with only the parameters that have a value. */
|
|
139
|
+
function buildUrl(baseUrl, path, params) {
|
|
140
|
+
const url = new URL(path, baseUrl);
|
|
141
|
+
for (const [key, value] of Object.entries(params)) {
|
|
142
|
+
if (value !== null && value !== '')
|
|
143
|
+
url.searchParams.set(key, value);
|
|
144
|
+
}
|
|
145
|
+
return url;
|
|
146
|
+
}
|
|
147
|
+
/** True when a window bound was actually supplied. */
|
|
148
|
+
function isSet(value) {
|
|
149
|
+
return value !== null && value !== undefined && value.trim().length > 0;
|
|
150
|
+
}
|
|
151
|
+
/** An HTTP implementation of {@link McpBackend}. */
|
|
152
|
+
export function createHttpBackend(input) {
|
|
153
|
+
const { baseUrl, fetchImpl = fetch } = input;
|
|
154
|
+
async function getJson(url, signal) {
|
|
155
|
+
const response = await fetchImpl(url, { signal });
|
|
156
|
+
if (!response.ok)
|
|
157
|
+
throw await readApiError(response);
|
|
158
|
+
return (await response.json());
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
async archiveStatus({ region, signal }) {
|
|
162
|
+
return getJson(buildUrl(baseUrl, '/api/archive', { region }), signal);
|
|
163
|
+
},
|
|
164
|
+
async listLogGroups({ region, prefix, limit, source, signal }) {
|
|
165
|
+
return getJson(buildUrl(baseUrl, '/api/log-groups', {
|
|
166
|
+
region,
|
|
167
|
+
prefix: prefix ?? null,
|
|
168
|
+
limit: limit === null || limit === undefined ? null : String(limit),
|
|
169
|
+
source,
|
|
170
|
+
}), signal);
|
|
171
|
+
},
|
|
172
|
+
async identity({ region, signal }) {
|
|
173
|
+
return getJson(buildUrl(baseUrl, '/api/identity', { region }), signal);
|
|
174
|
+
},
|
|
175
|
+
async search(request) {
|
|
176
|
+
const groups = request.groups;
|
|
177
|
+
// A tool search is always a bounded window. Saying so explicitly matters
|
|
178
|
+
// for `source=cloudwatch`: without `mode=historic` the route would tail
|
|
179
|
+
// live, which never ends (the call would hang) and skips the archive.
|
|
180
|
+
const customWindow = isSet(request.from) && isSet(request.to);
|
|
181
|
+
const url = buildUrl(baseUrl, '/api/stream', {
|
|
182
|
+
region: request.region,
|
|
183
|
+
source: request.source,
|
|
184
|
+
mode: 'historic',
|
|
185
|
+
...(groups.length === 1 ? { group: groups[0] } : { groups: groups.join(',') }),
|
|
186
|
+
...(request.source === 'archive'
|
|
187
|
+
? {
|
|
188
|
+
search: request.search ?? null,
|
|
189
|
+
level: request.levels && request.levels.length > 0 ? request.levels.join(',') : null,
|
|
190
|
+
pageSize: request.pageSize === null || request.pageSize === undefined
|
|
191
|
+
? null
|
|
192
|
+
: String(request.pageSize),
|
|
193
|
+
}
|
|
194
|
+
: { filterPattern: request.filterPattern ?? null }),
|
|
195
|
+
from: request.from ?? null,
|
|
196
|
+
to: request.to ?? null,
|
|
197
|
+
range: customWindow ? null : (request.range ?? null),
|
|
198
|
+
max: request.max === null || request.max === undefined ? null : String(request.max),
|
|
199
|
+
});
|
|
200
|
+
const response = await fetchImpl(url, { signal: request.signal });
|
|
201
|
+
if (!response.ok)
|
|
202
|
+
throw await readApiError(response);
|
|
203
|
+
const outcome = await collectStream(response);
|
|
204
|
+
return {
|
|
205
|
+
region: outcome.region,
|
|
206
|
+
source: outcome.source,
|
|
207
|
+
groups: outcome.groups.length > 0 ? outcome.groups : groups,
|
|
208
|
+
// Several groups, and the archived and CloudWatch parts of one window,
|
|
209
|
+
// stream side by side, so batches arrive interleaved. The sort is
|
|
210
|
+
// stable: events with one timestamp keep the order they arrived in.
|
|
211
|
+
events: outcome.events.toSorted((a, b) => a.timestamp - b.timestamp),
|
|
212
|
+
truncated: outcome.reason === 'event-limit',
|
|
213
|
+
reason: outcome.reason,
|
|
214
|
+
error: outcome.error,
|
|
215
|
+
};
|
|
216
|
+
},
|
|
217
|
+
async count(request) {
|
|
218
|
+
const groups = request.groups;
|
|
219
|
+
const customWindow = isSet(request.from) && isSet(request.to);
|
|
220
|
+
const url = buildUrl(baseUrl, '/api/series', {
|
|
221
|
+
region: request.region,
|
|
222
|
+
source: 'archive',
|
|
223
|
+
...(groups.length === 1 ? { group: groups[0] } : { groups: groups.join(',') }),
|
|
224
|
+
from: request.from ?? null,
|
|
225
|
+
to: request.to ?? null,
|
|
226
|
+
range: customWindow ? null : (request.range ?? null),
|
|
227
|
+
level: request.levels && request.levels.length > 0 ? request.levels.join(',') : null,
|
|
228
|
+
bucket: request.bucket ?? null,
|
|
229
|
+
by: request.by ?? null,
|
|
230
|
+
metric: request.metric ?? null,
|
|
231
|
+
});
|
|
232
|
+
return getJson(url, request.signal);
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|