ompchamber 0.3.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.
- package/README.md +253 -0
- package/dist/client/apple-touch-icon.png +0 -0
- package/dist/client/icon-192x192.png +0 -0
- package/dist/client/icon-512x512.png +0 -0
- package/dist/client/icon-maskable-512x512.png +0 -0
- package/dist/client/icon.svg +60 -0
- package/dist/client/index.html +41 -0
- package/dist/client/manifest.webmanifest +38 -0
- package/dist/client/static/css/g.f36aa429fa.css +1 -0
- package/dist/client/static/css/index.a0f07455bd.css +2 -0
- package/dist/client/static/css/katex-vendor.ca3a0600e8.css +1 -0
- package/dist/client/static/font/KaTeX_AMS-Regular.1608a09b4a.woff +0 -0
- package/dist/client/static/font/KaTeX_AMS-Regular.4aafdb685c.ttf +0 -0
- package/dist/client/static/font/KaTeX_AMS-Regular.a79f1c3119.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Caligraphic-Bold.b67709187b.woff +0 -0
- package/dist/client/static/font/KaTeX_Caligraphic-Bold.cce5b8ecea.ttf +0 -0
- package/dist/client/static/font/KaTeX_Caligraphic-Bold.ec17d13264.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Caligraphic-Regular.07ef19e7b0.ttf +0 -0
- package/dist/client/static/font/KaTeX_Caligraphic-Regular.55fac25845.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Caligraphic-Regular.dad44a7fc6.woff +0 -0
- package/dist/client/static/font/KaTeX_Fraktur-Bold.9f256b8593.woff +0 -0
- package/dist/client/static/font/KaTeX_Fraktur-Bold.b18f59e1d1.ttf +0 -0
- package/dist/client/static/font/KaTeX_Fraktur-Bold.d42a5579b0.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Fraktur-Regular.7c1871215e.woff +0 -0
- package/dist/client/static/font/KaTeX_Fraktur-Regular.d3c882a649.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Fraktur-Regular.ed38e79f57.ttf +0 -0
- package/dist/client/static/font/KaTeX_Main-Bold.b74a1a8b2c.ttf +0 -0
- package/dist/client/static/font/KaTeX_Main-Bold.c3fb5ac22f.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Main-Bold.d181c4650d.woff +0 -0
- package/dist/client/static/font/KaTeX_Main-BoldItalic.6f2bb1dff2.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Main-BoldItalic.70d8b0a530.ttf +0 -0
- package/dist/client/static/font/KaTeX_Main-BoldItalic.e3f82f9d27.woff +0 -0
- package/dist/client/static/font/KaTeX_Main-Italic.47373d1e51.ttf +0 -0
- package/dist/client/static/font/KaTeX_Main-Italic.8916142bec.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Main-Italic.9024d815ba.woff +0 -0
- package/dist/client/static/font/KaTeX_Main-Regular.0462f03bdf.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Main-Regular.7f51fe0340.woff +0 -0
- package/dist/client/static/font/KaTeX_Main-Regular.b7f8fe9b5f.ttf +0 -0
- package/dist/client/static/font/KaTeX_Math-BoldItalic.572d331f69.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Math-BoldItalic.a879cf8383.ttf +0 -0
- package/dist/client/static/font/KaTeX_Math-BoldItalic.f1035d8d5d.woff +0 -0
- package/dist/client/static/font/KaTeX_Math-Italic.5295ba483a.woff +0 -0
- package/dist/client/static/font/KaTeX_Math-Italic.939bc64440.ttf +0 -0
- package/dist/client/static/font/KaTeX_Math-Italic.f28c23acad.woff2 +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Bold.8c5b5494b6.woff2 +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Bold.94e1e8dc5f.ttf +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Bold.bf59d231c3.woff +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Italic.3b1e59b3ba.woff2 +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Italic.7c9bc82b17.woff +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Italic.b4c20c84d8.ttf +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Regular.740484788f.woff +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Regular.ba21ed5f84.woff2 +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Regular.d4d7ba4804.ttf +0 -0
- package/dist/client/static/font/KaTeX_Script-Regular.03e9641d6f.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Script-Regular.0750571032.woff +0 -0
- package/dist/client/static/font/KaTeX_Script-Regular.fe9cbbe1a0.ttf +0 -0
- package/dist/client/static/font/KaTeX_Size1-Regular.e1e279cbdd.woff +0 -0
- package/dist/client/static/font/KaTeX_Size1-Regular.eae34984b3.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Size1-Regular.fabc004aab.ttf +0 -0
- package/dist/client/static/font/KaTeX_Size2-Regular.577270225e.woff +0 -0
- package/dist/client/static/font/KaTeX_Size2-Regular.5916a24fa3.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Size2-Regular.d6b476ecd3.ttf +0 -0
- package/dist/client/static/font/KaTeX_Size3-Regular.9acaf01c64.woff +0 -0
- package/dist/client/static/font/KaTeX_Size3-Regular.a144ef5840.ttf +0 -0
- package/dist/client/static/font/KaTeX_Size4-Regular.10d95fd3a2.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Size4-Regular.7a996c9da2.woff +0 -0
- package/dist/client/static/font/KaTeX_Size4-Regular.fbccdabe0a.ttf +0 -0
- package/dist/client/static/font/KaTeX_Typewriter-Regular.6258592bdc.woff +0 -0
- package/dist/client/static/font/KaTeX_Typewriter-Regular.a8709e3622.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Typewriter-Regular.d97aaf4a1e.ttf +0 -0
- package/dist/client/static/font/fira-code-cyrillic-400-normal.5971438a4a.woff2 +0 -0
- package/dist/client/static/font/fira-code-cyrillic-400-normal.9bb7bfea9c.woff +0 -0
- package/dist/client/static/font/fira-code-cyrillic-500-normal.5486265b18.woff2 +0 -0
- package/dist/client/static/font/fira-code-cyrillic-500-normal.89f92bfb31.woff +0 -0
- package/dist/client/static/font/fira-code-cyrillic-600-normal.2805b497e5.woff +0 -0
- package/dist/client/static/font/fira-code-cyrillic-600-normal.86e0df22a3.woff2 +0 -0
- package/dist/client/static/font/fira-code-cyrillic-700-normal.505a88f22a.woff +0 -0
- package/dist/client/static/font/fira-code-cyrillic-700-normal.76f5e8d2e2.woff2 +0 -0
- package/dist/client/static/font/fira-code-cyrillic-ext-400-normal.3c4b15e57d.woff2 +0 -0
- package/dist/client/static/font/fira-code-cyrillic-ext-400-normal.61323debaa.woff +0 -0
- package/dist/client/static/font/fira-code-cyrillic-ext-500-normal.0f34210f2a.woff2 +0 -0
- package/dist/client/static/font/fira-code-cyrillic-ext-500-normal.2497cfa1aa.woff +0 -0
- package/dist/client/static/font/fira-code-cyrillic-ext-600-normal.40fce94af9.woff2 +0 -0
- package/dist/client/static/font/fira-code-cyrillic-ext-600-normal.6c8774b829.woff +0 -0
- package/dist/client/static/font/fira-code-cyrillic-ext-700-normal.4b742eb865.woff +0 -0
- package/dist/client/static/font/fira-code-cyrillic-ext-700-normal.e75eb4fccc.woff2 +0 -0
- package/dist/client/static/font/fira-code-greek-400-normal.bb900468b6.woff2 +0 -0
- package/dist/client/static/font/fira-code-greek-400-normal.be76e699ba.woff +0 -0
- package/dist/client/static/font/fira-code-greek-500-normal.176c9fb001.woff2 +0 -0
- package/dist/client/static/font/fira-code-greek-500-normal.d2c596136b.woff +0 -0
- package/dist/client/static/font/fira-code-greek-600-normal.490c3deed7.woff +0 -0
- package/dist/client/static/font/fira-code-greek-600-normal.7df14376d9.woff2 +0 -0
- package/dist/client/static/font/fira-code-greek-700-normal.c82b6072fc.woff2 +0 -0
- package/dist/client/static/font/fira-code-greek-700-normal.d5f2b2917b.woff +0 -0
- package/dist/client/static/font/fira-code-greek-ext-400-normal.4849a79781.woff +0 -0
- package/dist/client/static/font/fira-code-greek-ext-400-normal.7f5bfc4538.woff2 +0 -0
- package/dist/client/static/font/fira-code-greek-ext-500-normal.aaccca4075.woff2 +0 -0
- package/dist/client/static/font/fira-code-greek-ext-500-normal.e383181256.woff +0 -0
- package/dist/client/static/font/fira-code-greek-ext-600-normal.78cb4bff8e.woff +0 -0
- package/dist/client/static/font/fira-code-greek-ext-600-normal.d6c93d54f9.woff2 +0 -0
- package/dist/client/static/font/fira-code-greek-ext-700-normal.57ec7c92d9.woff +0 -0
- package/dist/client/static/font/fira-code-greek-ext-700-normal.8fafdae5e8.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-400-normal.2655b10c55.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-400-normal.973295532b.woff +0 -0
- package/dist/client/static/font/fira-code-latin-500-normal.7ae2be8fb8.woff +0 -0
- package/dist/client/static/font/fira-code-latin-500-normal.92a991f204.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-600-normal.1dbbe5bc27.woff +0 -0
- package/dist/client/static/font/fira-code-latin-600-normal.43788eb7f1.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-700-normal.2667215d33.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-700-normal.497a70148b.woff +0 -0
- package/dist/client/static/font/fira-code-latin-ext-400-normal.9dfae29aaf.woff +0 -0
- package/dist/client/static/font/fira-code-latin-ext-400-normal.e534ae46e2.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-ext-500-normal.24c7b781b0.woff +0 -0
- package/dist/client/static/font/fira-code-latin-ext-500-normal.aad44ab072.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-ext-600-normal.7bed0f2f7e.woff +0 -0
- package/dist/client/static/font/fira-code-latin-ext-600-normal.c509a7c9f1.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-ext-700-normal.6c66c8b0a9.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-ext-700-normal.88f64e2822.woff +0 -0
- package/dist/client/static/font/fira-code-symbols2-400-normal.97d3f4b17c.woff +0 -0
- package/dist/client/static/font/fira-code-symbols2-500-normal.b06f1a06e4.woff +0 -0
- package/dist/client/static/font/fira-code-symbols2-600-normal.304b653b93.woff +0 -0
- package/dist/client/static/font/fira-code-symbols2-700-normal.d8ce0ad586.woff +0 -0
- package/dist/client/static/js/async/0.8e59f2eb5b.js +1 -0
- package/dist/client/static/js/async/0k.5852e6b4fa.js +1 -0
- package/dist/client/static/js/async/0w.9ed36d5860.js +1 -0
- package/dist/client/static/js/async/1.f387c12b63.js +1 -0
- package/dist/client/static/js/async/12.d091f91c99.js +1 -0
- package/dist/client/static/js/async/13.8f810a8a6c.js +1 -0
- package/dist/client/static/js/async/19.6fe909d55a.js +160 -0
- package/dist/client/static/js/async/1b.23f1141a38.js +1 -0
- package/dist/client/static/js/async/1k.544adbf77d.js +2 -0
- package/dist/client/static/js/async/1k.544adbf77d.js.LICENSE.txt +6 -0
- package/dist/client/static/js/async/1p.0d5cddda96.js +1 -0
- package/dist/client/static/js/async/2.b589f1733b.js +1 -0
- package/dist/client/static/js/async/2v.96165101de.js +1 -0
- package/dist/client/static/js/async/3.0cacc08423.js +1 -0
- package/dist/client/static/js/async/37.b28b2f61cd.js +1 -0
- package/dist/client/static/js/async/3d.5085fb913f.js +1 -0
- package/dist/client/static/js/async/3j.a2fcea99be.js +2 -0
- package/dist/client/static/js/async/3j.a2fcea99be.js.LICENSE.txt +11 -0
- package/dist/client/static/js/async/3p.bcf32a0983.js +1 -0
- package/dist/client/static/js/async/3r.3a69e98ee0.js +64 -0
- package/dist/client/static/js/async/3u.1228460e2a.js +1 -0
- package/dist/client/static/js/async/3y.22075aa079.js +198 -0
- package/dist/client/static/js/async/3y.22075aa079.js.LICENSE.txt +5 -0
- package/dist/client/static/js/async/4.9442eeb472.js +1 -0
- package/dist/client/static/js/async/4e.678285ca55.js +1 -0
- package/dist/client/static/js/async/4k.33a0c7eeb4.js +1 -0
- package/dist/client/static/js/async/4q.aad20dab25.js +1 -0
- package/dist/client/static/js/async/5.ebaf8b89cc.js +36 -0
- package/dist/client/static/js/async/51.1938cec320.js +2 -0
- package/dist/client/static/js/async/51.1938cec320.js.LICENSE.txt +6 -0
- package/dist/client/static/js/async/5b.d88304bc13.js +1 -0
- package/dist/client/static/js/async/5j.d6407c4248.js +287 -0
- package/dist/client/static/js/async/5o.88316d4460.js +62 -0
- package/dist/client/static/js/async/6.7929428505.js +1 -0
- package/dist/client/static/js/async/66.5dfa29f957.js +93 -0
- package/dist/client/static/js/async/69.a18a10882f.js +1 -0
- package/dist/client/static/js/async/6o.5b1a06a382.js +1 -0
- package/dist/client/static/js/async/7.e4a9288dd0.js +1 -0
- package/dist/client/static/js/async/73.50280ce58d.js +1 -0
- package/dist/client/static/js/async/7e.a1cc9bfd88.js +1 -0
- package/dist/client/static/js/async/7l.7a6a377ecc.js +1 -0
- package/dist/client/static/js/async/8.5067439d8c.js +1 -0
- package/dist/client/static/js/async/8j.ea110663fb.js +1 -0
- package/dist/client/static/js/async/a.bce4542392.js +1 -0
- package/dist/client/static/js/async/aa.65d3852576.js +1 -0
- package/dist/client/static/js/async/ar.9dc8b1992a.js +2 -0
- package/dist/client/static/js/async/ar.9dc8b1992a.js.LICENSE.txt +6 -0
- package/dist/client/static/js/async/az.d656062b0f.js +1 -0
- package/dist/client/static/js/async/b.b4f6f06515.js +1 -0
- package/dist/client/static/js/async/bi.cbfe8eaa8e.js +1 -0
- package/dist/client/static/js/async/bq.586bc738d1.js +1 -0
- package/dist/client/static/js/async/c.cd45b0ac45.js +1 -0
- package/dist/client/static/js/async/c0.0af1e640d3.js +24 -0
- package/dist/client/static/js/async/ca.8a52cfd447.js +1 -0
- package/dist/client/static/js/async/cf.d34fff5d67.js +1 -0
- package/dist/client/static/js/async/ct.38d9da8a5a.js +1 -0
- package/dist/client/static/js/async/cx.ca5feec570.js +226 -0
- package/dist/client/static/js/async/d.a5fc8fe1b3.js +1 -0
- package/dist/client/static/js/async/da.f62c70f6c8.js +1 -0
- package/dist/client/static/js/async/dp.1725d6432c.js +1 -0
- package/dist/client/static/js/async/e.93214d622b.js +79 -0
- package/dist/client/static/js/async/f.ab50467719.js +19 -0
- package/dist/client/static/js/async/f.ab50467719.js.LICENSE.txt +12 -0
- package/dist/client/static/js/async/f8.bbf0dbae70.js +1 -0
- package/dist/client/static/js/async/fw.fb1a08b92d.js +6 -0
- package/dist/client/static/js/async/fw.fb1a08b92d.js.LICENSE.txt +6 -0
- package/dist/client/static/js/async/h.4e790471e4.js +27 -0
- package/dist/client/static/js/async/h1.e8d5aa8e80.js +1 -0
- package/dist/client/static/js/async/h3.216e9798ab.js +148 -0
- package/dist/client/static/js/async/hd.0da931b622.js +1 -0
- package/dist/client/static/js/async/hk.ba7fb04d41.js +1 -0
- package/dist/client/static/js/async/hn.7568bdb58b.js +1 -0
- package/dist/client/static/js/async/ho.475a5e1ae4.js +1 -0
- package/dist/client/static/js/async/hp.e9fe2e395a.js +2 -0
- package/dist/client/static/js/async/hp.e9fe2e395a.js.LICENSE.txt +17 -0
- package/dist/client/static/js/async/hs.6d480d0ded.js +41 -0
- package/dist/client/static/js/async/i.7c148e8440.js +1 -0
- package/dist/client/static/js/async/id.573df20f29.js +1 -0
- package/dist/client/static/js/async/j.ab925882d8.js +1 -0
- package/dist/client/static/js/async/jd.63886a1f09.js +1 -0
- package/dist/client/static/js/async/jg.69a4beade8.js +86 -0
- package/dist/client/static/js/async/jl.874d352278.js +1 -0
- package/dist/client/static/js/async/jll.11313b455a.js +1 -0
- package/dist/client/static/js/async/js.67182759ef.js +1 -0
- package/dist/client/static/js/async/jsc.23b70d6f40.js +1 -0
- package/dist/client/static/js/async/jse.334588ff5d.js +1 -0
- package/dist/client/static/js/async/jz.72eb929106.js +77 -0
- package/dist/client/static/js/async/k.e878dd350f.js +217 -0
- package/dist/client/static/js/async/ka.c1990ecaa3.js +115 -0
- package/dist/client/static/js/async/ku.29c8a59d0c.js +1 -0
- package/dist/client/static/js/async/ky.8dab1dade0.js +1 -0
- package/dist/client/static/js/async/l.102a97fce6.js +104 -0
- package/dist/client/static/js/async/l6.45f3b62e15.js +1 -0
- package/dist/client/static/js/async/l9.949710adaf.js +83 -0
- package/dist/client/static/js/async/l9.949710adaf.js.LICENSE.txt +13 -0
- package/dist/client/static/js/async/m.3fc017a055.js +28 -0
- package/dist/client/static/js/async/m.3fc017a055.js.LICENSE.txt +6 -0
- package/dist/client/static/js/async/me.8ace414f80.js +23 -0
- package/dist/client/static/js/async/mt.0352e976d8.js +1 -0
- package/dist/client/static/js/async/n.a9f1c51701.js +1 -0
- package/dist/client/static/js/async/na.a36cd532d6.js +1 -0
- package/dist/client/static/js/async/nk.6de011832e.js +1 -0
- package/dist/client/static/js/async/o.36353dfb88.js +1 -0
- package/dist/client/static/js/async/oc.9c060c9779.js +8 -0
- package/dist/client/static/js/async/og.ae7acf03ac.js +193 -0
- package/dist/client/static/js/async/p.48ecfcd14e.js +1 -0
- package/dist/client/static/js/async/px.783b6f91f2.js +1 -0
- package/dist/client/static/js/async/q.0b6fb9bf8d.js +21 -0
- package/dist/client/static/js/async/q.0b6fb9bf8d.js.LICENSE.txt +6 -0
- package/dist/client/static/js/async/q5.e683f7c26e.js +286 -0
- package/dist/client/static/js/async/qs.2a9ddb3c72.js +1 -0
- package/dist/client/static/js/async/r.51010ad87c.js +1 -0
- package/dist/client/static/js/async/rd.b77011ab7f.js +2 -0
- package/dist/client/static/js/async/rd.b77011ab7f.js.LICENSE.txt +4 -0
- package/dist/client/static/js/async/rf.cfbde7f744.js +2 -0
- package/dist/client/static/js/async/rf.cfbde7f744.js.LICENSE.txt +6 -0
- package/dist/client/static/js/async/s.c7d521a8ae.js +2 -0
- package/dist/client/static/js/async/s.c7d521a8ae.js.LICENSE.txt +6 -0
- package/dist/client/static/js/async/sy.7345abcd67.js +94 -0
- package/dist/client/static/js/async/t.0dcb01dfde.js +1 -0
- package/dist/client/static/js/async/t9.d44f57d518.js +1 -0
- package/dist/client/static/js/async/ta.973534bbec.js +1 -0
- package/dist/client/static/js/async/ty.3d93cf5f5f.js +1 -0
- package/dist/client/static/js/async/u.0871ac5b22.js +1 -0
- package/dist/client/static/js/async/up.ea990da0ff.js +32 -0
- package/dist/client/static/js/async/uw.8890abbabc.js +1 -0
- package/dist/client/static/js/async/v.5c7a4b087b.js +1 -0
- package/dist/client/static/js/async/vn.e98e2f3b61.js +309 -0
- package/dist/client/static/js/async/vp.9b13bf8610.js +1 -0
- package/dist/client/static/js/async/vu.311f1d202c.js +34 -0
- package/dist/client/static/js/async/w.08ac210f60.js +1 -0
- package/dist/client/static/js/async/wt.ad92393a90.js +1 -0
- package/dist/client/static/js/async/x.563f72ca6b.js +1 -0
- package/dist/client/static/js/async/x0.475516418f.js +1 -0
- package/dist/client/static/js/async/x1.da8687159b.js +90 -0
- package/dist/client/static/js/async/xl.a3c562a58c.js +1 -0
- package/dist/client/static/js/async/xn.afecebbbd9.js +2 -0
- package/dist/client/static/js/async/xn.afecebbbd9.js.LICENSE.txt +12 -0
- package/dist/client/static/js/async/y.1a9ed7a5d8.js +1 -0
- package/dist/client/static/js/async/y6.43c57defe4.js +1 -0
- package/dist/client/static/js/async/yb.8c1342401d.js +1 -0
- package/dist/client/static/js/async/ybq.4491f2f2dc.js +1 -0
- package/dist/client/static/js/async/yg.9bd4e09ecb.js +149 -0
- package/dist/client/static/js/async/yq.917ddd7ba2.js +1 -0
- package/dist/client/static/js/async/ys.00687cf82d.js +38 -0
- package/dist/client/static/js/async/yv.593a3f7d54.js +1 -0
- package/dist/client/static/js/async/z.56f61a4374.js +1 -0
- package/dist/client/static/js/async/zi.5fdb07b86a.js +24 -0
- package/dist/client/static/js/async/zj.654f37e8ff.js +1 -0
- package/dist/client/static/js/async/zn.966d6f1cc6.js +1 -0
- package/dist/client/static/js/async/zo.26213b40c0.js +1 -0
- package/dist/client/static/js/async/zx.e9f4105e00.js +1 -0
- package/dist/client/static/js/g.124fba0826.js +139 -0
- package/dist/client/static/js/g.124fba0826.js.LICENSE.txt +8 -0
- package/dist/client/static/js/index.907fd4670e.js +68 -0
- package/dist/client/static/js/index.907fd4670e.js.LICENSE.txt +4 -0
- package/dist/client/static/js/katex-vendor.95e48cf65a.js +1 -0
- package/dist/client/static/js/markdown-vendor.9da142c67b.js +144 -0
- package/dist/client/static/js/shiki-vendor.cb8452ddcd.js +1 -0
- package/dist/client/sw.js +15 -0
- package/package.json +75 -0
- package/src/cli/lib/args.js +233 -0
- package/src/cli/lib/commands/logs.js +108 -0
- package/src/cli/lib/commands/restart.js +28 -0
- package/src/cli/lib/commands/serve.js +109 -0
- package/src/cli/lib/commands/status.js +63 -0
- package/src/cli/lib/commands/stop.js +63 -0
- package/src/cli/lib/commands/update.js +120 -0
- package/src/cli/lib/output.js +136 -0
- package/src/cli/lib/path-utils.js +48 -0
- package/src/cli/lib/path-utils.test.js +71 -0
- package/src/cli/lib/paths.js +60 -0
- package/src/cli/lib/process-lifecycle.js +110 -0
- package/src/cli/lib/runtime.js +280 -0
- package/src/cli/ompchamber.js +56 -0
- package/src/client/App.tsx +95 -0
- package/src/client/bootstrap.d.ts +12 -0
- package/src/client/components/common/ComposerPicker.tsx +116 -0
- package/src/client/components/common/ComposerTextarea.tsx +131 -0
- package/src/client/components/common/CopyButton.tsx +73 -0
- package/src/client/components/common/FolderPicker.tsx +270 -0
- package/src/client/components/common/MarkdownRenderer.tsx +107 -0
- package/src/client/components/common/Modal.tsx +75 -0
- package/src/client/components/common/PWAInstallButton.tsx +113 -0
- package/src/client/components/common/StatCard.tsx +52 -0
- package/src/client/components/common/StreamStatusDot.tsx +28 -0
- package/src/client/components/common/SubagentStatusIcon.tsx +27 -0
- package/src/client/components/common/Toast.tsx +79 -0
- package/src/client/components/common/ToastStack.tsx +18 -0
- package/src/client/components/common/ViewportSelector.tsx +206 -0
- package/src/client/components/common/code-editor/index.tsx +343 -0
- package/src/client/components/common/code-surface/index.tsx +75 -0
- package/src/client/components/common/file-icon/brand-paths.ts +62 -0
- package/src/client/components/common/file-icon/index.tsx +127 -0
- package/src/client/components/common/lazy-panels.tsx +80 -0
- package/src/client/components/common/session-state-provider/index.tsx +55 -0
- package/src/client/components/common/sort-menu/index.tsx +63 -0
- package/src/client/components/common/sort-menu/options.ts +24 -0
- package/src/client/components/common/viewport.ts +21 -0
- package/src/client/components/common/workspace-options-menu/index.tsx +84 -0
- package/src/client/components/layout/RightActivityBar.tsx +95 -0
- package/src/client/components/layout/desktop-layout/ResizeHandle.tsx +10 -0
- package/src/client/components/layout/desktop-layout/TopNavbar.tsx +94 -0
- package/src/client/components/layout/desktop-layout/WorkspacePanels.tsx +175 -0
- package/src/client/components/layout/desktop-layout/index.tsx +280 -0
- package/src/client/components/layout/desktop-layout/resizer/index.tsx +344 -0
- package/src/client/components/layout/session-sidebar/CategoryItem.tsx +264 -0
- package/src/client/components/layout/session-sidebar/Footer.tsx +28 -0
- package/src/client/components/layout/session-sidebar/Header.tsx +29 -0
- package/src/client/components/layout/session-sidebar/Modals.tsx +209 -0
- package/src/client/components/layout/session-sidebar/SessionItem.tsx +145 -0
- package/src/client/components/layout/session-sidebar/SessionList.tsx +52 -0
- package/src/client/components/layout/session-sidebar/Skeleton.tsx +36 -0
- package/src/client/components/layout/session-sidebar/SubagentList.tsx +152 -0
- package/src/client/components/layout/session-sidebar/Toolbar.tsx +123 -0
- package/src/client/components/layout/session-sidebar/about-modal/SocialLinks.tsx +43 -0
- package/src/client/components/layout/session-sidebar/about-modal/UpdateSection.tsx +172 -0
- package/src/client/components/layout/session-sidebar/about-modal/index.tsx +63 -0
- package/src/client/components/layout/session-sidebar/index.tsx +174 -0
- package/src/client/components/mobile/LayoutWrapper.tsx +221 -0
- package/src/client/components/mobile/MainView.tsx +68 -0
- package/src/client/components/mobile/RightSidebar.tsx +217 -0
- package/src/client/components/mobile/SessionSidebar.tsx +175 -0
- package/src/client/components/mobile/mobile-main-view/Header.tsx +264 -0
- package/src/client/components/mobile/mobile-right-sidebar/FullDiff.tsx +80 -0
- package/src/client/components/mobile/mobile-right-sidebar/FullEditor.tsx +141 -0
- package/src/client/components/mobile/mobile-right-sidebar/Header.tsx +121 -0
- package/src/client/components/mobile/mobile-session-sidebar/Footer.tsx +69 -0
- package/src/client/components/mobile/mobile-session-sidebar/Header.tsx +34 -0
- package/src/client/components/mobile/mobile-session-sidebar/Item.tsx +168 -0
- package/src/client/components/mobile/mobile-session-sidebar/List.tsx +53 -0
- package/src/client/components/mobile/mobile-session-sidebar/SessionRow.tsx +99 -0
- package/src/client/components/mobile/mobile-session-sidebar/Skeleton.tsx +36 -0
- package/src/client/components/mobile/mobile-session-sidebar/Toolbar.tsx +176 -0
- package/src/client/components/settings/LoadingState.tsx +22 -0
- package/src/client/components/settings/Modal.tsx +277 -0
- package/src/client/components/settings/ProjectSelectorDropdown.tsx +142 -0
- package/src/client/components/settings/SettingsSidebarList.tsx +122 -0
- package/src/client/components/settings/Sidebar.tsx +153 -0
- package/src/client/components/settings/categories/AgentSettings.tsx +84 -0
- package/src/client/components/settings/categories/AppearanceSettings.tsx +50 -0
- package/src/client/components/settings/categories/BehaviorSettings.tsx +73 -0
- package/src/client/components/settings/categories/ChatSettings.tsx +24 -0
- package/src/client/components/settings/categories/CommandSettings.tsx +81 -0
- package/src/client/components/settings/categories/McpSettings.tsx +142 -0
- package/src/client/components/settings/categories/NotificationSettings.tsx +97 -0
- package/src/client/components/settings/categories/OmpSettings.tsx +312 -0
- package/src/client/components/settings/categories/OtherSettings.tsx +16 -0
- package/src/client/components/settings/categories/ProjectSettings.tsx +176 -0
- package/src/client/components/settings/categories/ProviderSettings.tsx +146 -0
- package/src/client/components/settings/categories/SkillCatalogSettings.tsx +309 -0
- package/src/client/components/settings/categories/SkillSettings.tsx +69 -0
- package/src/client/components/settings/categories/TokenUsageSettings.tsx +264 -0
- package/src/client/components/settings/categories/UsageSettings.tsx +77 -0
- package/src/client/components/settings/categories/agent-settings/DetailPane.tsx +333 -0
- package/src/client/components/settings/categories/agent-settings/SidebarList.tsx +42 -0
- package/src/client/components/settings/categories/behavior-settings/Editor.tsx +244 -0
- package/src/client/components/settings/categories/chat-settings/FollowUpSection.tsx +120 -0
- package/src/client/components/settings/categories/chat-settings/KeybindingsSection.tsx +107 -0
- package/src/client/components/settings/categories/chat-settings/TransportSection.tsx +101 -0
- package/src/client/components/settings/categories/command-settings/DetailPane.tsx +292 -0
- package/src/client/components/settings/categories/command-settings/SidebarList.tsx +39 -0
- package/src/client/components/settings/categories/mcp-settings/ConnectionTest.tsx +89 -0
- package/src/client/components/settings/categories/mcp-settings/DetailPane.tsx +311 -0
- package/src/client/components/settings/categories/mcp-settings/ImportModal.tsx +161 -0
- package/src/client/components/settings/categories/mcp-settings/SidebarList.tsx +120 -0
- package/src/client/components/settings/categories/omp-settings/ConfigTabs.tsx +243 -0
- package/src/client/components/settings/categories/omp-settings/ExtensionsPanel.tsx +61 -0
- package/src/client/components/settings/categories/omp-settings/RoleEditor.tsx +66 -0
- package/src/client/components/settings/categories/omp-settings/RowEditor.tsx +337 -0
- package/src/client/components/settings/categories/project-settings/AccentPalette.tsx +76 -0
- package/src/client/components/settings/categories/project-settings/DetailsForm.tsx +71 -0
- package/src/client/components/settings/categories/project-settings/DetailsHeader.tsx +38 -0
- package/src/client/components/settings/categories/project-settings/IconGrid.tsx +152 -0
- package/src/client/components/settings/categories/project-settings/ModelDropdown.tsx +95 -0
- package/src/client/components/settings/categories/project-settings/NameInput.tsx +26 -0
- package/src/client/components/settings/categories/project-settings/SidebarList.tsx +100 -0
- package/src/client/components/settings/categories/provider-settings/AddProviderModal.tsx +201 -0
- package/src/client/components/settings/categories/provider-settings/AuthSection.tsx +121 -0
- package/src/client/components/settings/categories/provider-settings/Header.tsx +22 -0
- package/src/client/components/settings/categories/provider-settings/Icons.tsx +35 -0
- package/src/client/components/settings/categories/provider-settings/LoginModal.tsx +224 -0
- package/src/client/components/settings/categories/provider-settings/ModelCapabilitiesModal.tsx +114 -0
- package/src/client/components/settings/categories/provider-settings/ModelConfigModal.tsx +155 -0
- package/src/client/components/settings/categories/provider-settings/ModelsList.tsx +191 -0
- package/src/client/components/settings/categories/provider-settings/ReconnectModal.tsx +163 -0
- package/src/client/components/settings/categories/provider-settings/SidebarList.tsx +133 -0
- package/src/client/components/settings/categories/skill-catalog/AddSourceModal.tsx +133 -0
- package/src/client/components/settings/categories/skill-settings/DetailPane.tsx +210 -0
- package/src/client/components/settings/categories/skill-settings/SidebarList.tsx +164 -0
- package/src/client/components/settings/categories/token-usage-settings/Breakdown.tsx +127 -0
- package/src/client/components/settings/categories/token-usage-settings/Chart.tsx +74 -0
- package/src/client/components/settings/categories/token-usage-settings/MetricsGrid.tsx +44 -0
- package/src/client/components/settings/categories/usage-settings/DeepSeekCard.tsx +66 -0
- package/src/client/components/settings/categories/usage-settings/KenariCard.tsx +68 -0
- package/src/client/components/settings/categories/usage-settings/ProviderCard.tsx +52 -0
- package/src/client/components/settings/categories/usage-settings/ProviderDetail.tsx +39 -0
- package/src/client/components/settings/categories/usage-settings/QuotaSection.tsx +93 -0
- package/src/client/components/settings/categories/usage-settings/SidebarList.tsx +77 -0
- package/src/client/components/settings/categories/usage-settings/UsageTable.tsx +66 -0
- package/src/client/components/settings/categories/usage-settings/format.ts +63 -0
- package/src/client/components/settings/categories/usage-settings/providers.ts +45 -0
- package/src/client/components/workspace/SearchPanel.tsx +259 -0
- package/src/client/components/workspace/browser-panel/ActivityToasts.tsx +46 -0
- package/src/client/components/workspace/browser-panel/AddressBar.tsx +84 -0
- package/src/client/components/workspace/browser-panel/Screencast.tsx +109 -0
- package/src/client/components/workspace/browser-panel/index.tsx +69 -0
- package/src/client/components/workspace/browser-toolbar/ZoomControls.tsx +48 -0
- package/src/client/components/workspace/browser-toolbar/index.tsx +140 -0
- package/src/client/components/workspace/chat-timeline/AiMessageFooter.tsx +250 -0
- package/src/client/components/workspace/chat-timeline/AttachmentChips.tsx +119 -0
- package/src/client/components/workspace/chat-timeline/ComposerDock.tsx +121 -0
- package/src/client/components/workspace/chat-timeline/EmptyWorkspacePrompt.tsx +220 -0
- package/src/client/components/workspace/chat-timeline/GeneratingIndicator.tsx +94 -0
- package/src/client/components/workspace/chat-timeline/MessageItem.tsx +321 -0
- package/src/client/components/workspace/chat-timeline/MessageList.tsx +122 -0
- package/src/client/components/workspace/chat-timeline/MinimapShortcuts.tsx +47 -0
- package/src/client/components/workspace/chat-timeline/NewChatModal.tsx +69 -0
- package/src/client/components/workspace/chat-timeline/QueueList.tsx +94 -0
- package/src/client/components/workspace/chat-timeline/SessionSkeleton.tsx +89 -0
- package/src/client/components/workspace/chat-timeline/SubagentView.tsx +148 -0
- package/src/client/components/workspace/chat-timeline/SystemNotice.tsx +209 -0
- package/src/client/components/workspace/chat-timeline/TaskResultContent.tsx +175 -0
- package/src/client/components/workspace/chat-timeline/ThinkingSection.tsx +130 -0
- package/src/client/components/workspace/chat-timeline/TimelineBody.tsx +130 -0
- package/src/client/components/workspace/chat-timeline/ToolCallCard.tsx +291 -0
- package/src/client/components/workspace/chat-timeline/ToolCallingSection.tsx +96 -0
- package/src/client/components/workspace/chat-timeline/UndoConfirmModal.tsx +83 -0
- package/src/client/components/workspace/chat-timeline/chat-input/AccessDropdown.tsx +53 -0
- package/src/client/components/workspace/chat-timeline/chat-input/AttachmentToolbar.tsx +63 -0
- package/src/client/components/workspace/chat-timeline/chat-input/ThinkingLevelDropdown.tsx +49 -0
- package/src/client/components/workspace/chat-timeline/chat-input/Toolbar.tsx +108 -0
- package/src/client/components/workspace/chat-timeline/chat-input/access-levels.ts +14 -0
- package/src/client/components/workspace/chat-timeline/chat-input/index.tsx +341 -0
- package/src/client/components/workspace/chat-timeline/index.tsx +290 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/ask-dialog/Footer.tsx +97 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/ask-dialog/Header.tsx +52 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/ask-dialog/Lazy.tsx +24 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/ask-dialog/SelectBody.tsx +110 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/ask-dialog/index.tsx +321 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/hashline-patch/index.tsx +92 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/index.tsx +160 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Ask.tsx +205 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/AstEdit.tsx +202 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Bash.tsx +223 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Checkpoint.tsx +49 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/ContextNotes.tsx +66 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Debug.tsx +91 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Edit.tsx +288 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Eval.tsx +202 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Github.tsx +91 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Goal.tsx +247 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Hub.tsx +273 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Lsp.tsx +276 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/ManageSkill.tsx +93 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Mcp.tsx +143 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Memory.tsx +93 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Read.tsx +246 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Resolve.tsx +96 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/SearchFs.tsx +132 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/SearchTool.tsx +317 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/SecurityScan.tsx +102 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/TaskResult.tsx +240 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Think.tsx +52 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Todo.tsx +141 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/WebSearch.tsx +118 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/shared/DiffView.tsx +150 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/shared/FallbackOutput.tsx +107 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/shared/JsonCodeBlock.tsx +79 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/shared/ToolCardShell.tsx +151 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/shared/read-line-meta.ts +95 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/shared/tool-input.ts +18 -0
- package/src/client/components/workspace/chat-timeline/tool-renderers/shared/truncate.ts +18 -0
- package/src/client/components/workspace/context-panel/CostBreakdownPopover.tsx +74 -0
- package/src/client/components/workspace/context-panel/LastMessageCard.tsx +34 -0
- package/src/client/components/workspace/context-panel/RawJsonViewer.tsx +94 -0
- package/src/client/components/workspace/context-panel/RawMessagesList.tsx +293 -0
- package/src/client/components/workspace/context-panel/StatsGrid.tsx +64 -0
- package/src/client/components/workspace/context-panel/TokenDistributionBar.tsx +62 -0
- package/src/client/components/workspace/context-panel/WindowCard.tsx +35 -0
- package/src/client/components/workspace/context-panel/index.tsx +142 -0
- package/src/client/components/workspace/context-panel/raw-messages.ts +54 -0
- package/src/client/components/workspace/diff-panel/SplitView.tsx +165 -0
- package/src/client/components/workspace/diff-panel/Toolbar.tsx +177 -0
- package/src/client/components/workspace/diff-panel/UnifiedView.tsx +117 -0
- package/src/client/components/workspace/diff-panel/index.tsx +213 -0
- package/src/client/components/workspace/editor/Tabs.tsx +149 -0
- package/src/client/components/workspace/editor/Toolbar.tsx +90 -0
- package/src/client/components/workspace/editor/index.tsx +189 -0
- package/src/client/components/workspace/file-explorer/GitRepoDropdown.tsx +143 -0
- package/src/client/components/workspace/file-explorer/Modals.tsx +236 -0
- package/src/client/components/workspace/file-explorer/TreeItem.tsx +289 -0
- package/src/client/components/workspace/file-explorer/index.tsx +193 -0
- package/src/client/components/workspace/git-panel/BranchToolbar.tsx +188 -0
- package/src/client/components/workspace/git-panel/ChangesList.tsx +168 -0
- package/src/client/components/workspace/git-panel/CommitBox.tsx +48 -0
- package/src/client/components/workspace/git-panel/FileItem.tsx +91 -0
- package/src/client/components/workspace/git-panel/Modals.tsx +97 -0
- package/src/client/components/workspace/git-panel/RepoHeader.tsx +137 -0
- package/src/client/components/workspace/git-panel/TreeItem.tsx +186 -0
- package/src/client/components/workspace/git-panel/TreeView.tsx +36 -0
- package/src/client/components/workspace/git-panel/commit-modal/CommitActions.tsx +97 -0
- package/src/client/components/workspace/git-panel/commit-modal/CommitDiffViewer.tsx +205 -0
- package/src/client/components/workspace/git-panel/commit-modal/CommitRow.tsx +179 -0
- package/src/client/components/workspace/git-panel/commit-modal/GraphCanvas.tsx +164 -0
- package/src/client/components/workspace/git-panel/commit-modal/Header.tsx +127 -0
- package/src/client/components/workspace/git-panel/commit-modal/index.tsx +269 -0
- package/src/client/components/workspace/git-panel/index.tsx +326 -0
- package/src/client/components/workspace/model-dropdown/Footer.tsx +21 -0
- package/src/client/components/workspace/model-dropdown/Header.tsx +50 -0
- package/src/client/components/workspace/model-dropdown/Item.tsx +137 -0
- package/src/client/components/workspace/model-dropdown/Panel.tsx +146 -0
- package/src/client/components/workspace/model-dropdown/Section.tsx +87 -0
- package/src/client/components/workspace/model-dropdown/Skeleton.tsx +39 -0
- package/src/client/components/workspace/model-dropdown/SpecsTooltip.tsx +91 -0
- package/src/client/components/workspace/model-dropdown/groups.ts +62 -0
- package/src/client/components/workspace/model-dropdown/index.tsx +245 -0
- package/src/client/components/workspace/model-dropdown/use-catalog.ts +111 -0
- package/src/client/components/workspace/terminal-panel/Header.tsx +50 -0
- package/src/client/components/workspace/terminal-panel/InputBar.tsx +82 -0
- package/src/client/components/workspace/terminal-panel/LogEntry.tsx +70 -0
- package/src/client/components/workspace/terminal-panel/QuickActions.tsx +39 -0
- package/src/client/components/workspace/terminal-panel/RealtimeXtermView.tsx +340 -0
- package/src/client/components/workspace/terminal-panel/index.tsx +110 -0
- package/src/client/components/workspace/usage-panel/ProviderSelect.tsx +208 -0
- package/src/client/components/workspace/usage-panel/index.tsx +98 -0
- package/src/client/components/workspace/user-browser-panel/AddressBar.tsx +134 -0
- package/src/client/components/workspace/user-browser-panel/Frame.tsx +72 -0
- package/src/client/components/workspace/user-browser-panel/index.tsx +87 -0
- package/src/client/data/agent-data/builtin.ts +31 -0
- package/src/client/data/agent-data/index.ts +10 -0
- package/src/client/data/agent-data/orchestrator.ts +113 -0
- package/src/client/data/agent-data/specialist.ts +245 -0
- package/src/client/data/context-data/index.test.ts +88 -0
- package/src/client/data/context-data/index.ts +310 -0
- package/src/client/data/context-data/presets.ts +128 -0
- package/src/client/data/mock/chat.ts +236 -0
- package/src/client/data/mock/git-commits.ts +304 -0
- package/src/client/data/mock/subagents.ts +212 -0
- package/src/client/data/mock/token-usage.ts +129 -0
- package/src/client/data/models/catalog.ts +293 -0
- package/src/client/data/samples/dialogue-session.ts +285 -0
- package/src/client/data/samples/sample-subagents/scout-raw.ts +341 -0
- package/src/client/data/samples/sample-subagents/sleeper-raw.ts +294 -0
- package/src/client/data/samples/sample-tools/built-in-part1.ts +265 -0
- package/src/client/data/samples/sample-tools/built-in-part2.ts +180 -0
- package/src/client/data/samples/sample-tools/other.ts +162 -0
- package/src/client/data/samples/subagent-session.ts +99 -0
- package/src/client/data/samples/tools-session.ts +85 -0
- package/src/client/data/samples/virtual-devices-session.ts +333 -0
- package/src/client/data/settings/behavior.ts +12 -0
- package/src/client/data/settings/command.ts +188 -0
- package/src/client/data/settings/mcp.ts +28 -0
- package/src/client/data/settings/omp-schema.json +1 -0
- package/src/client/data/settings/project.ts +58 -0
- package/src/client/data/settings/provider.ts +185 -0
- package/src/client/data/settings/skill.ts +340 -0
- package/src/client/data/theme/terminal.ts +150 -0
- package/src/client/hooks/browser/use-screencast.ts +178 -0
- package/src/client/hooks/browser/use-user-browser.ts +105 -0
- package/src/client/hooks/chat/composer/index.ts +181 -0
- package/src/client/hooks/chat/composer/items.ts +47 -0
- package/src/client/hooks/chat/omp/index.ts +348 -0
- package/src/client/hooks/chat/omp/revalidation-throttle.ts +71 -0
- package/src/client/hooks/chat/omp/session-list.tsx +148 -0
- package/src/client/hooks/chat/omp/session-sidebar-controller.ts +249 -0
- package/src/client/hooks/chat/omp/session-statuses.ts +83 -0
- package/src/client/hooks/chat/omp/status.ts +31 -0
- package/src/client/hooks/chat/omp/stream-poll.ts +37 -0
- package/src/client/hooks/chat/omp/stream.ts +108 -0
- package/src/client/hooks/chat/stream.ts +228 -0
- package/src/client/hooks/chat/subagent/index.ts +290 -0
- package/src/client/hooks/chat/timeline/actions.ts +322 -0
- package/src/client/hooks/chat/timeline/auto-scroll.ts +58 -0
- package/src/client/hooks/chat/timeline/browser-context.ts +40 -0
- package/src/client/hooks/chat/timeline/extension-dialog.ts +56 -0
- package/src/client/hooks/chat/timeline/index.ts +333 -0
- package/src/client/hooks/chat/timeline/queue.ts +87 -0
- package/src/client/hooks/chat/timeline/scroll.ts +134 -0
- package/src/client/hooks/chat/timeline/send.ts +348 -0
- package/src/client/hooks/chat/timeline/session-load.ts +334 -0
- package/src/client/hooks/chat/timeline/session-title.ts +40 -0
- package/src/client/hooks/chat/timeline/subagent-view.ts +92 -0
- package/src/client/hooks/chat/timeline/undo-confirmation.ts +29 -0
- package/src/client/hooks/editor/use-file-editor.ts +302 -0
- package/src/client/hooks/models/use-model-names.ts +17 -0
- package/src/client/hooks/models/use-models-catalog.ts +45 -0
- package/src/client/hooks/models/use-provider-names.ts +18 -0
- package/src/client/hooks/settings/crud-list.ts +187 -0
- package/src/client/hooks/settings/instruction-file.ts +91 -0
- package/src/client/hooks/settings/providers.ts +295 -0
- package/src/client/hooks/settings/skill-catalog.ts +37 -0
- package/src/client/hooks/settings/use-chamber-setting.ts +12 -0
- package/src/client/hooks/settings/useUsageReport.ts +41 -0
- package/src/client/hooks/ui/clipboard.ts +33 -0
- package/src/client/hooks/ui/copy-flag.ts +27 -0
- package/src/client/hooks/ui/inline-rename.ts +93 -0
- package/src/client/hooks/ui/notification-sound.ts +108 -0
- package/src/client/hooks/ui/on-click-outside.ts +22 -0
- package/src/client/hooks/ui/open-file.ts +42 -0
- package/src/client/hooks/ui/scrollbar-fade.ts +33 -0
- package/src/client/hooks/ui/show-more.ts +23 -0
- package/src/client/hooks/ui/syntax-ready.ts +17 -0
- package/src/client/hooks/ui/theme.ts +76 -0
- package/src/client/hooks/ui/toasts.ts +22 -0
- package/src/client/hooks/ui/updates.ts +108 -0
- package/src/client/hooks/ui/visibility-refresh.ts +66 -0
- package/src/client/hooks/ui/window-event.ts +52 -0
- package/src/client/hooks/workspace/commit-interactions.ts +111 -0
- package/src/client/hooks/workspace/commit-pagination.ts +106 -0
- package/src/client/hooks/workspace/file-tabs.ts +136 -0
- package/src/client/hooks/workspace/git-status.ts +89 -0
- package/src/client/hooks/workspace/git-tree.ts +146 -0
- package/src/client/hooks/workspace/panel-refresh.ts +72 -0
- package/src/client/hooks/workspace/panel-widths.ts +59 -0
- package/src/client/hooks/workspace/search-stream.ts +76 -0
- package/src/client/hooks/workspace/session-state/context.ts +15 -0
- package/src/client/hooks/workspace/session-state/index.ts +62 -0
- package/src/client/hooks/workspace/terminal-output.ts +66 -0
- package/src/client/hooks/workspace/terminal.ts +283 -0
- package/src/client/hooks/workspace/workspace-folder-actions.ts +110 -0
- package/src/client/lib/router/fetcher.ts +100 -0
- package/src/client/lib/router/search-params.ts +82 -0
- package/src/client/main.tsx +23 -0
- package/src/client/tailwind.css +364 -0
- package/src/server/db.server.ts +338 -0
- package/src/server/index.ts +19 -0
- package/src/server/lib/browser/runtime.test.ts +110 -0
- package/src/server/lib/browser/runtime.ts +160 -0
- package/src/server/lib/chat/session-store.server.ts +61 -0
- package/src/server/lib/db/client.ts +55 -0
- package/src/server/lib/db/settings-store.ts +148 -0
- package/src/server/lib/fs/atomic-write.ts +27 -0
- package/src/server/lib/fs/git-diff.ts +116 -0
- package/src/server/lib/fs/git-log.ts +174 -0
- package/src/server/lib/fs/repo-scope.ts +14 -0
- package/src/server/lib/fs/root.ts +77 -0
- package/src/server/lib/fs/shell.ts +71 -0
- package/src/server/lib/fs/terminal-cwd.ts +49 -0
- package/src/server/lib/models/provider-registry.server.ts +269 -0
- package/src/server/lib/omp/config/agents.ts +162 -0
- package/src/server/lib/omp/config/behavior.ts +113 -0
- package/src/server/lib/omp/config/config-cli.ts +94 -0
- package/src/server/lib/omp/config/disabled-providers.ts +68 -0
- package/src/server/lib/omp/config/extensions.ts +90 -0
- package/src/server/lib/omp/config/instructions.ts +81 -0
- package/src/server/lib/omp/config/mcp-test.ts +346 -0
- package/src/server/lib/omp/config/mcp.ts +258 -0
- package/src/server/lib/omp/config/providers.ts +276 -0
- package/src/server/lib/omp/config/roles.ts +46 -0
- package/src/server/lib/omp/config/skills-catalog.ts +93 -0
- package/src/server/lib/omp/config/skills.ts +118 -0
- package/src/server/lib/omp/config/yaml.ts +48 -0
- package/src/server/lib/omp/core/auth-credentials.ts +87 -0
- package/src/server/lib/omp/core/cli.ts +69 -0
- package/src/server/lib/omp/core/paths.ts +154 -0
- package/src/server/lib/omp/core/registry.ts +140 -0
- package/src/server/lib/omp/core/worktree.ts +106 -0
- package/src/server/lib/omp/rpc/constants.ts +185 -0
- package/src/server/lib/omp/rpc/errors.ts +27 -0
- package/src/server/lib/omp/rpc/kill-tree.ts +49 -0
- package/src/server/lib/omp/rpc/lines.ts +38 -0
- package/src/server/lib/omp/rpc/manager.ts +310 -0
- package/src/server/lib/omp/rpc/pending-ui-dialogs.ts +55 -0
- package/src/server/lib/omp/rpc/process-helpers.ts +82 -0
- package/src/server/lib/omp/rpc/process.ts +319 -0
- package/src/server/lib/omp/rpc/session-commands.ts +218 -0
- package/src/server/lib/omp/rpc/session-registry.ts +300 -0
- package/src/server/lib/omp/rpc/utility.ts +199 -0
- package/src/server/lib/omp/rpc/web-state.ts +94 -0
- package/src/server/lib/omp/session/files.ts +282 -0
- package/src/server/lib/omp/session/locator.ts +60 -0
- package/src/server/lib/omp/session/messages.ts +222 -0
- package/src/server/lib/omp/session/reader.ts +150 -0
- package/src/server/lib/omp/session/sidebar-data.server.ts +195 -0
- package/src/server/lib/omp/session/stats.ts +85 -0
- package/src/server/lib/omp/session/subagent-presence.ts +74 -0
- package/src/server/lib/omp/session/telemetry/compute.ts +188 -0
- package/src/server/lib/omp/session/telemetry/format.ts +110 -0
- package/src/server/lib/omp/session/telemetry/index.ts +4 -0
- package/src/server/lib/omp/session/telemetry/scan.ts +21 -0
- package/src/server/lib/omp/session/telemetry-raw.ts +96 -0
- package/src/server/lib/omp/session/telemetry.test.ts +154 -0
- package/src/server/lib/omp/session/title-slot.ts +203 -0
- package/src/server/lib/omp/session/usage.ts +298 -0
- package/src/server/lib/omp/subagent/history/fold.ts +196 -0
- package/src/server/lib/omp/subagent/history/index.ts +110 -0
- package/src/server/lib/omp/subagent/history/paths.ts +29 -0
- package/src/server/lib/omp/subagent/history/transcript.test.ts +87 -0
- package/src/server/lib/omp/subagent/history/transcript.ts +122 -0
- package/src/server/lib/remix-compat.ts +29 -0
- package/src/server/lib/route-adapter.ts +144 -0
- package/src/server/lib/sse.ts +248 -0
- package/src/server/lib/updates/apply.ts +46 -0
- package/src/server/lib/updates/check.ts +41 -0
- package/src/server/lib/updates/github.ts +71 -0
- package/src/server/lib/updates/install-method.ts +73 -0
- package/src/server/lib/updates/install.test.ts +74 -0
- package/src/server/lib/updates/install.ts +294 -0
- package/src/server/lib/updates/omp.ts +86 -0
- package/src/server/lib/usage/deepseek.ts +59 -0
- package/src/server/lib/usage/kenari.ts +251 -0
- package/src/server/lib/usage/provider-key.ts +83 -0
- package/src/server/mock.server.ts +33 -0
- package/src/server/plugins/compress.ts +51 -0
- package/src/server/plugins/dev-assets.ts +49 -0
- package/src/server/plugins/ssr.ts +100 -0
- package/src/server/plugins/static.ts +81 -0
- package/src/server/routes/agent/command.ts +81 -0
- package/src/server/routes/agent/events.ts +56 -0
- package/src/server/routes/agent/index.ts +12 -0
- package/src/server/routes/agent/new.ts +83 -0
- package/src/server/routes/agent/prewarm.ts +27 -0
- package/src/server/routes/agent/ws.ts +168 -0
- package/src/server/routes/browser/index.ts +6 -0
- package/src/server/routes/browser/stream.ts +217 -0
- package/src/server/routes/chat/index.ts +12 -0
- package/src/server/routes/chat/rewind.ts +162 -0
- package/src/server/routes/chat/root.ts +78 -0
- package/src/server/routes/chat/session.ts +339 -0
- package/src/server/routes/chat/stream.ts +111 -0
- package/src/server/routes/files/index.ts +10 -0
- package/src/server/routes/files/root.ts +29 -0
- package/src/server/routes/files/toggle.ts +20 -0
- package/src/server/routes/folders/create.ts +98 -0
- package/src/server/routes/folders/folder.ts +78 -0
- package/src/server/routes/folders/index.ts +16 -0
- package/src/server/routes/fs/action.ts +84 -0
- package/src/server/routes/fs/git.ts +334 -0
- package/src/server/routes/fs/index.ts +19 -0
- package/src/server/routes/fs/read.ts +258 -0
- package/src/server/routes/fs/replace.ts +69 -0
- package/src/server/routes/fs/search.ts +135 -0
- package/src/server/routes/fs/validate.ts +61 -0
- package/src/server/routes/health/index.ts +6 -0
- package/src/server/routes/health/probe.ts +27 -0
- package/src/server/routes/index.ts +38 -0
- package/src/server/routes/models/index.ts +8 -0
- package/src/server/routes/models/roles.ts +31 -0
- package/src/server/routes/models/root.ts +328 -0
- package/src/server/routes/omp/commands.ts +29 -0
- package/src/server/routes/omp/extensions.ts +34 -0
- package/src/server/routes/omp/index.ts +20 -0
- package/src/server/routes/omp/login.ts +112 -0
- package/src/server/routes/omp/plugins.ts +82 -0
- package/src/server/routes/omp/pricing.ts +65 -0
- package/src/server/routes/omp/session-stats.ts +30 -0
- package/src/server/routes/omp/sidebar.ts +40 -0
- package/src/server/routes/omp/state.ts +22 -0
- package/src/server/routes/sessions/folder.ts +16 -0
- package/src/server/routes/sessions/index.ts +25 -0
- package/src/server/routes/sessions/list.ts +23 -0
- package/src/server/routes/sessions/session.ts +331 -0
- package/src/server/routes/sessions/subagents.ts +82 -0
- package/src/server/routes/settings/agents.ts +128 -0
- package/src/server/routes/settings/behavior.ts +125 -0
- package/src/server/routes/settings/commands.ts +89 -0
- package/src/server/routes/settings/index.ts +28 -0
- package/src/server/routes/settings/mcp-test.ts +71 -0
- package/src/server/routes/settings/mcp.ts +261 -0
- package/src/server/routes/settings/omp-config.ts +47 -0
- package/src/server/routes/settings/projects.ts +84 -0
- package/src/server/routes/settings/provider-models.ts +278 -0
- package/src/server/routes/settings/providers.ts +137 -0
- package/src/server/routes/settings/root.ts +40 -0
- package/src/server/routes/settings/skills.ts +175 -0
- package/src/server/routes/settings/usage.ts +81 -0
- package/src/server/routes/telemetry/context.ts +52 -0
- package/src/server/routes/telemetry/index.ts +10 -0
- package/src/server/routes/telemetry/raw-messages.ts +80 -0
- package/src/server/routes/telemetry/tokens.ts +163 -0
- package/src/server/routes/terminal/index.ts +8 -0
- package/src/server/routes/terminal/run.ts +135 -0
- package/src/server/routes/terminal/stream.ts +100 -0
- package/src/server/routes/updates/apply.ts +25 -0
- package/src/server/routes/updates/check.ts +27 -0
- package/src/server/routes/updates/index.ts +8 -0
- package/src/server/routes/well-known/devtools.ts +9 -0
- package/src/server/routes/well-known/index.ts +6 -0
- package/src/shared/lib/browser/activity.ts +115 -0
- package/src/shared/lib/browser/cdp.ts +201 -0
- package/src/shared/lib/browser/connection.ts +81 -0
- package/src/shared/lib/browser/observer.ts +129 -0
- package/src/shared/lib/browser/page-context.ts +20 -0
- package/src/shared/lib/browser/targets.test.ts +45 -0
- package/src/shared/lib/browser/targets.ts +74 -0
- package/src/shared/lib/browser/url.ts +21 -0
- package/src/shared/lib/browser/util.ts +20 -0
- package/src/shared/lib/browser/viewer.ts +303 -0
- package/src/shared/lib/browser/watcher.ts +75 -0
- package/src/shared/lib/chat/attachments.ts +62 -0
- package/src/shared/lib/chat/capitalize.ts +9 -0
- package/src/shared/lib/chat/composer/client.ts +210 -0
- package/src/shared/lib/chat/composer/filter.ts +62 -0
- package/src/shared/lib/chat/composer/translate.ts +103 -0
- package/src/shared/lib/chat/composer/trigger.ts +53 -0
- package/src/shared/lib/chat/detect-format.ts +38 -0
- package/src/shared/lib/chat/duration.ts +82 -0
- package/src/shared/lib/chat/omp/agent-events.test.ts +152 -0
- package/src/shared/lib/chat/omp/agent-events.ts +347 -0
- package/src/shared/lib/chat/omp/file-mutations.ts +42 -0
- package/src/shared/lib/chat/omp/socket.ts +95 -0
- package/src/shared/lib/chat/omp/sse.ts +53 -0
- package/src/shared/lib/chat/omp/status.ts +45 -0
- package/src/shared/lib/chat/omp/transport.ts +50 -0
- package/src/shared/lib/chat/order.ts +40 -0
- package/src/shared/lib/chat/read-sse.ts +99 -0
- package/src/shared/lib/chat/stream-service.ts +273 -0
- package/src/shared/lib/chat/task-result-parser.ts +166 -0
- package/src/shared/lib/chat/timeline/omp-callbacks.ts +293 -0
- package/src/shared/lib/chat/timeline/stream-callbacks.ts +202 -0
- package/src/shared/lib/chat/timeline/stream-raf.ts +59 -0
- package/src/shared/lib/chat/timeline/tool-phrases.ts +224 -0
- package/src/shared/lib/chat/timeline/tool-verbs.ts +160 -0
- package/src/shared/lib/chat/timeline/turns.ts +30 -0
- package/src/shared/lib/chat/title-case.ts +293 -0
- package/src/shared/lib/chat/todo-parser.ts +257 -0
- package/src/shared/lib/chat/tool-status.ts +20 -0
- package/src/shared/lib/code/ansi.ts +24 -0
- package/src/shared/lib/code/editor-utils.ts +16 -0
- package/src/shared/lib/code/format.ts +17 -0
- package/src/shared/lib/code/highlighter.ts +135 -0
- package/src/shared/lib/code/parser.ts +237 -0
- package/src/shared/lib/code/shiki-langs.ts +93 -0
- package/src/shared/lib/code/shiki-themes.ts +14 -0
- package/src/shared/lib/code/syntax-highlight.test.ts +153 -0
- package/src/shared/lib/code/syntax-highlight.ts +290 -0
- package/src/shared/lib/db/transaction.server.ts +20 -0
- package/src/shared/lib/format/number.ts +69 -0
- package/src/shared/lib/format/time.ts +39 -0
- package/src/shared/lib/fs/diff-parser.ts +135 -0
- package/src/shared/lib/fs/file-tree.ts +26 -0
- package/src/shared/lib/fs/git-graph.ts +184 -0
- package/src/shared/lib/fs/git-status.ts +161 -0
- package/src/shared/lib/markdown/marked.ts +228 -0
- package/src/shared/lib/markdown/mermaid.ts +153 -0
- package/src/shared/lib/markdown/sanitize.ts +138 -0
- package/src/shared/lib/models/catalog.ts +88 -0
- package/src/shared/lib/models/client.ts +51 -0
- package/src/shared/lib/models/identity.ts +21 -0
- package/src/shared/lib/models/provider-cleanup.ts +20 -0
- package/src/shared/lib/models/provider-connection.ts +41 -0
- package/src/shared/lib/models/provider-label.ts +40 -0
- package/src/shared/lib/models/provider-models.ts +97 -0
- package/src/shared/lib/models/provider-presets.ts +29 -0
- package/src/shared/lib/models/remote-list.ts +125 -0
- package/src/shared/lib/models/server-cache.ts +27 -0
- package/src/shared/lib/models/thinking-levels.ts +68 -0
- package/src/shared/lib/omp/config/access-mode.server.ts +27 -0
- package/src/shared/lib/omp/config/access-mode.ts +31 -0
- package/src/shared/lib/omp/config/schema-extras.ts +230 -0
- package/src/shared/lib/omp/config/schema-types.ts +49 -0
- package/src/shared/lib/omp/config/schema.ts +81 -0
- package/src/shared/lib/omp/rpc/frame.ts +134 -0
- package/src/shared/lib/omp/session/default-title.test.ts +50 -0
- package/src/shared/lib/omp/session/default-title.ts +51 -0
- package/src/shared/lib/omp/session/hashline-patch.test.ts +89 -0
- package/src/shared/lib/omp/session/hashline-patch.ts +134 -0
- package/src/shared/lib/omp/session/jsonl.ts +197 -0
- package/src/shared/lib/omp/session/mapper.ts +145 -0
- package/src/shared/lib/omp/session/messages-map.ts +179 -0
- package/src/shared/lib/omp/session/messages-parse.ts +69 -0
- package/src/shared/lib/omp/session/parse-message-blocks.ts +223 -0
- package/src/shared/lib/omp/session/prewarm.ts +41 -0
- package/src/shared/lib/omp/session/sidebar.ts +77 -0
- package/src/shared/lib/omp/session/stream-state.server.ts +106 -0
- package/src/shared/lib/omp/session/telemetry-blocks.ts +60 -0
- package/src/shared/lib/omp/session/timestamps.ts +20 -0
- package/src/shared/lib/omp/session/turn-error.ts +40 -0
- package/src/shared/lib/omp/subagent/history/client.ts +76 -0
- package/src/shared/lib/omp/subagent/history/settlement.ts +113 -0
- package/src/shared/lib/omp/subagent/history/status.ts +40 -0
- package/src/shared/lib/omp/subagent/parse.ts +284 -0
- package/src/shared/lib/omp/subagent/result-details.ts +53 -0
- package/src/shared/lib/omp/subagent/transcript-client.ts +178 -0
- package/src/shared/lib/settings/client.test.ts +62 -0
- package/src/shared/lib/settings/client.ts +96 -0
- package/src/shared/lib/updates/semver.ts +34 -0
- package/src/shared/lib/util/guards.ts +14 -0
- package/src/shared/lib/workspace/active-project.ts +42 -0
- package/src/shared/lib/workspace/panel-widths.test.ts +72 -0
- package/src/shared/lib/workspace/panel-widths.ts +79 -0
- package/src/shared/lib/workspace/project-icon.ts +29 -0
- package/src/shared/lib/workspace/project-settings-migration.ts +62 -0
- package/src/shared/lib/workspace/project-settings.ts +139 -0
- package/src/shared/lib/workspace/refresh-cadence.ts +128 -0
- package/src/shared/lib/workspace/relative-time.ts +25 -0
- package/src/shared/lib/workspace/right-panels.ts +51 -0
- package/src/shared/lib/workspace/schema-migrations.ts +19 -0
- package/src/shared/lib/workspace/session-state/store.ts +267 -0
- package/src/shared/lib/workspace/sidebar-expanded.ts +23 -0
- package/src/shared/lib/workspace/sidebar-sort.test.ts +200 -0
- package/src/shared/lib/workspace/sidebar-sort.ts +131 -0
- package/src/shared/types/browser.ts +58 -0
- package/src/shared/types/chat.ts +289 -0
- package/src/shared/types/context.ts +87 -0
- package/src/shared/types/fs.ts +36 -0
- package/src/shared/types/git.ts +60 -0
- package/src/shared/types/index.ts +22 -0
- package/src/shared/types/omp/agent.ts +109 -0
- package/src/shared/types/omp/instructions.ts +38 -0
- package/src/shared/types/omp/session.ts +153 -0
- package/src/shared/types/omp/subagent.ts +176 -0
- package/src/shared/types/settings/agent.ts +16 -0
- package/src/shared/types/settings/command.ts +12 -0
- package/src/shared/types/settings/mcp.ts +22 -0
- package/src/shared/types/settings/project.ts +18 -0
- package/src/shared/types/settings/provider.ts +42 -0
- package/src/shared/types/settings/skill.ts +35 -0
- package/src/shared/types/settings/state.ts +59 -0
- package/src/shared/types/settings/usage.ts +99 -0
- package/src/shared/types/terminal.ts +19 -0
- package/src/shared/types/tokenUsage.ts +44 -0
- package/src/shared/types/updates.ts +38 -0
- package/src/shared/types/workspace.ts +56 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { createDb, type DbClient } from '@/server/lib/db/client';
|
|
5
|
+
import { isMockMode } from '@/server/mock.server';
|
|
6
|
+
import { SAMPLE_TOOLS_SESSION_ID, getSampleToolsSession } from '@/client/data/samples/tools-session';
|
|
7
|
+
import { SAMPLE_DIALOGUE_SESSION_ID, getSampleDialogueSession } from '@/client/data/samples/dialogue-session';
|
|
8
|
+
import { SAMPLE_DEVICES_SESSION_ID, getSampleDevicesSession } from '@/client/data/samples/virtual-devices-session';
|
|
9
|
+
import { loadOmpSidebarData } from '@/server/lib/omp/session/reader';
|
|
10
|
+
import { pathExists, projectPathKey } from '@/server/lib/omp/core/paths';
|
|
11
|
+
|
|
12
|
+
let dbPromise: Promise<DbClient> | null = null;
|
|
13
|
+
|
|
14
|
+
/** SYNC_WORKSPACE env flag (default true when unset). When enabled in real
|
|
15
|
+
* mode, workspace folders are auto-created from discovered omp projects. */
|
|
16
|
+
export function isWorkspaceSyncEnabled(): boolean {
|
|
17
|
+
const raw = (Bun.env.SYNC_WORKSPACE || '').trim().toLowerCase();
|
|
18
|
+
if (raw === '') return true;
|
|
19
|
+
return raw !== 'false' && raw !== '0' && raw !== 'off' && raw !== 'no';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function getDatabasePath(): Promise<string> {
|
|
23
|
+
if (isMockMode()) {
|
|
24
|
+
return path.join(process.cwd(), 'workspace.db');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const customPath = Bun.env.OMPCHAMBER_DB_PATH || Bun.env.DB_PATH;
|
|
28
|
+
if (customPath) {
|
|
29
|
+
const resolvedPath = customPath.startsWith('~')
|
|
30
|
+
? path.join(os.homedir(), customPath.slice(1))
|
|
31
|
+
: path.resolve(customPath);
|
|
32
|
+
const dir = path.dirname(resolvedPath);
|
|
33
|
+
if (!(await pathExists(dir))) {
|
|
34
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
return resolvedPath;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const defaultDir = path.join(os.homedir(), '.ompchamber');
|
|
40
|
+
if (!(await pathExists(defaultDir))) {
|
|
41
|
+
await fs.promises.mkdir(defaultDir, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
return path.join(defaultDir, 'db.sqlite');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function getDb(): Promise<DbClient> {
|
|
47
|
+
if (dbPromise) return dbPromise;
|
|
48
|
+
|
|
49
|
+
dbPromise = (async () => {
|
|
50
|
+
const dbPath = await getDatabasePath();
|
|
51
|
+
const db = createDb(dbPath);
|
|
52
|
+
|
|
53
|
+
await db.exec(`
|
|
54
|
+
CREATE TABLE IF NOT EXISTS workspace_folders (
|
|
55
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
56
|
+
name TEXT NOT NULL,
|
|
57
|
+
is_expanded BOOLEAN DEFAULT 0,
|
|
58
|
+
project_path TEXT,
|
|
59
|
+
model TEXT DEFAULT 'Not selected',
|
|
60
|
+
accent_color TEXT DEFAULT '',
|
|
61
|
+
icon TEXT DEFAULT 'default',
|
|
62
|
+
custom_icon_url TEXT,
|
|
63
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
67
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
68
|
+
folder_id INTEGER NOT NULL,
|
|
69
|
+
title TEXT NOT NULL,
|
|
70
|
+
is_active BOOLEAN DEFAULT 0,
|
|
71
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
72
|
+
FOREIGN KEY (folder_id) REFERENCES workspace_folders (id)
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
CREATE TABLE IF NOT EXISTS app_settings (
|
|
76
|
+
key TEXT PRIMARY KEY,
|
|
77
|
+
value TEXT NOT NULL
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
CREATE TABLE IF NOT EXISTS chat_sessions (
|
|
81
|
+
session_id TEXT PRIMARY KEY,
|
|
82
|
+
title TEXT,
|
|
83
|
+
messages TEXT NOT NULL,
|
|
84
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
CREATE TABLE IF NOT EXISTS deleted_workspaces (
|
|
88
|
+
project_path TEXT PRIMARY KEY,
|
|
89
|
+
deleted_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
CREATE TABLE IF NOT EXISTS archived_sessions (
|
|
93
|
+
session_id TEXT PRIMARY KEY,
|
|
94
|
+
archived_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
CREATE TABLE IF NOT EXISTS session_ui_state (
|
|
98
|
+
session_id TEXT PRIMARY KEY,
|
|
99
|
+
state TEXT NOT NULL DEFAULT '{}',
|
|
100
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
CREATE TABLE IF NOT EXISTS queued_messages (
|
|
104
|
+
id TEXT PRIMARY KEY,
|
|
105
|
+
session_id TEXT NOT NULL,
|
|
106
|
+
position INTEGER NOT NULL,
|
|
107
|
+
message TEXT NOT NULL DEFAULT '',
|
|
108
|
+
attachments TEXT NOT NULL DEFAULT '[]',
|
|
109
|
+
provider TEXT,
|
|
110
|
+
model_id TEXT,
|
|
111
|
+
thinking_level TEXT,
|
|
112
|
+
access_mode TEXT,
|
|
113
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
114
|
+
);
|
|
115
|
+
CREATE INDEX IF NOT EXISTS idx_queued_messages_session ON queued_messages (session_id, position);
|
|
116
|
+
|
|
117
|
+
CREATE TABLE IF NOT EXISTS session_stream_state (
|
|
118
|
+
session_id TEXT PRIMARY KEY,
|
|
119
|
+
status TEXT NOT NULL,
|
|
120
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
121
|
+
);
|
|
122
|
+
`);
|
|
123
|
+
|
|
124
|
+
const { migrateWorkspaceFolderColumns } = await import('@/shared/lib/workspace/schema-migrations');
|
|
125
|
+
await migrateWorkspaceFolderColumns(db);
|
|
126
|
+
|
|
127
|
+
await db.exec(`
|
|
128
|
+
CREATE TABLE IF NOT EXISTS files (
|
|
129
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
130
|
+
session_id INTEGER NOT NULL,
|
|
131
|
+
parent_id INTEGER,
|
|
132
|
+
name TEXT NOT NULL,
|
|
133
|
+
type TEXT NOT NULL,
|
|
134
|
+
is_expanded BOOLEAN DEFAULT 0,
|
|
135
|
+
FOREIGN KEY (session_id) REFERENCES sessions (id),
|
|
136
|
+
FOREIGN KEY (parent_id) REFERENCES files (id)
|
|
137
|
+
);
|
|
138
|
+
`);
|
|
139
|
+
|
|
140
|
+
// Seed data based on MOCK mode
|
|
141
|
+
const folderCount = await db.get('SELECT COUNT(*) as count FROM workspace_folders');
|
|
142
|
+
|
|
143
|
+
if (isMockMode()) {
|
|
144
|
+
// MOCK=true: Seed demo workspace folders, sample chats, and session files
|
|
145
|
+
if (folderCount.count === 0) {
|
|
146
|
+
await db.exec(`
|
|
147
|
+
INSERT OR IGNORE INTO workspace_folders (id, name, is_expanded) VALUES
|
|
148
|
+
(1, 'Chats', 1),
|
|
149
|
+
(2, 'Workspace', 1),
|
|
150
|
+
(3, 'drrealhandler', 1);
|
|
151
|
+
`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Ensure ompchamber, Workspace, drrealhandler folders exist
|
|
155
|
+
await db.run("INSERT OR IGNORE INTO workspace_folders (id, name, is_expanded) VALUES (1, 'ompchamber', 1)");
|
|
156
|
+
await db.run("INSERT OR IGNORE INTO workspace_folders (id, name, is_expanded) VALUES (2, 'Workspace', 1)");
|
|
157
|
+
await db.run("INSERT OR IGNORE INTO workspace_folders (id, name, is_expanded) VALUES (3, 'drrealhandler', 1)");
|
|
158
|
+
await db.run("UPDATE workspace_folders SET name = 'ompchamber' WHERE id = 1");
|
|
159
|
+
|
|
160
|
+
// Seed specific sessions matching screenshot
|
|
161
|
+
const existingChats = await db.all("SELECT * FROM sessions WHERE folder_id = 1");
|
|
162
|
+
const title1 = 'Cek stream subagent di ompweb';
|
|
163
|
+
const title2 = 'Fitur Diff Panel dan Git Status Files';
|
|
164
|
+
const title3 = 'Implementasi Saved State UI per Session ID';
|
|
165
|
+
const title4 = 'Review loading indicator, model & intent title';
|
|
166
|
+
const title5 = 'Status fitur streer dan queue';
|
|
167
|
+
|
|
168
|
+
if (existingChats.length === 0) {
|
|
169
|
+
await db.run("INSERT INTO sessions (folder_id, title, is_active) VALUES (1, ?, 0)", [title1]);
|
|
170
|
+
await db.run("INSERT INTO sessions (folder_id, title, is_active) VALUES (1, ?, 0)", [title2]);
|
|
171
|
+
await db.run("INSERT INTO sessions (folder_id, title, is_active) VALUES (1, ?, 1)", [title3]);
|
|
172
|
+
await db.run("INSERT INTO sessions (folder_id, title, is_active) VALUES (1, ?, 0)", [title4]);
|
|
173
|
+
await db.run("INSERT INTO sessions (folder_id, title, is_active) VALUES (1, ?, 0)", [title5]);
|
|
174
|
+
} else {
|
|
175
|
+
await db.run("UPDATE sessions SET title = ? WHERE id = 1", [title1]);
|
|
176
|
+
await db.run("UPDATE sessions SET title = ? WHERE id = 2", [title2]);
|
|
177
|
+
await db.run("UPDATE sessions SET title = ? WHERE id = 3", [title3]);
|
|
178
|
+
await db.run("UPDATE sessions SET title = ? WHERE id = 4", [title4]);
|
|
179
|
+
await db.run("UPDATE sessions SET title = ? WHERE id = 5", [title5]);
|
|
180
|
+
await db.run("UPDATE sessions SET is_active = 0 WHERE folder_id = 1");
|
|
181
|
+
await db.run("UPDATE sessions SET is_active = 1 WHERE id = 3");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Pre-seed sample sessions data
|
|
185
|
+
try {
|
|
186
|
+
const s1 = getSampleToolsSession();
|
|
187
|
+
await db.run('INSERT OR REPLACE INTO chat_sessions (session_id, title, messages, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)', ['1', s1.title, JSON.stringify(s1.messages)]);
|
|
188
|
+
await db.run('INSERT OR REPLACE INTO chat_sessions (session_id, title, messages, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)', [SAMPLE_TOOLS_SESSION_ID, s1.title, JSON.stringify(s1.messages)]);
|
|
189
|
+
|
|
190
|
+
const s2 = getSampleDialogueSession();
|
|
191
|
+
await db.run('INSERT OR REPLACE INTO chat_sessions (session_id, title, messages, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)', ['2', s2.title, JSON.stringify(s2.messages)]);
|
|
192
|
+
await db.run('INSERT OR REPLACE INTO chat_sessions (session_id, title, messages, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)', [SAMPLE_DIALOGUE_SESSION_ID, s2.title, JSON.stringify(s2.messages)]);
|
|
193
|
+
|
|
194
|
+
const s3 = getSampleDevicesSession();
|
|
195
|
+
await db.run('INSERT OR REPLACE INTO chat_sessions (session_id, title, messages, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)', ['3', s3.title, JSON.stringify(s3.messages)]);
|
|
196
|
+
await db.run('INSERT OR REPLACE INTO chat_sessions (session_id, title, messages, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)', [SAMPLE_DEVICES_SESSION_ID, s3.title, JSON.stringify(s3.messages)]);
|
|
197
|
+
const s3Row = await db.get("SELECT id FROM sessions WHERE folder_id = 1 AND title = ?", [title3]);
|
|
198
|
+
if (s3Row) {
|
|
199
|
+
await db.run('INSERT OR REPLACE INTO chat_sessions (session_id, title, messages, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)', [String(s3Row.id), s3.title, JSON.stringify(s3.messages)]);
|
|
200
|
+
}
|
|
201
|
+
} catch (e) {
|
|
202
|
+
console.error('Failed to pre-seed sample sessions:', e);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const existingWorkspace = await db.all("SELECT * FROM sessions WHERE folder_id = 2");
|
|
206
|
+
if (existingWorkspace.length === 0) {
|
|
207
|
+
const workspaceTitles = [
|
|
208
|
+
'History Commit 2026-09-05 23:00',
|
|
209
|
+
'History Commit 2026-09-04 23:00',
|
|
210
|
+
'History Commit 2026-09-03 23:00',
|
|
211
|
+
'Error SMSC latency pada jns6.5 smppv2',
|
|
212
|
+
'Penyebab provider_submit_status=-1 di jns6.5 Smartfren SMPP',
|
|
213
|
+
'jns6.5 filevalidator error Mask Code di Release',
|
|
214
|
+
'Union query transaksi 202607 dan 202606'
|
|
215
|
+
];
|
|
216
|
+
for (const t of workspaceTitles) {
|
|
217
|
+
await db.run("INSERT INTO sessions (folder_id, title, is_active) VALUES (2, ?, 0)", [t]);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const existingDrreal = await db.all("SELECT * FROM sessions WHERE folder_id = 3");
|
|
222
|
+
if (existingDrreal.length === 0) {
|
|
223
|
+
const drrealTitles = [
|
|
224
|
+
'Buat branch feat/add-provider-err-telco-to-dr-smpp',
|
|
225
|
+
'Update wiki v1.5.0 & testing dari add-configurabel',
|
|
226
|
+
'Konfigurasi rute DR SMPP via config lookup',
|
|
227
|
+
'drrealhandler update v1.5.0',
|
|
228
|
+
'Gitlab wiki clone isi kosong'
|
|
229
|
+
];
|
|
230
|
+
for (const t of drrealTitles) {
|
|
231
|
+
await db.run("INSERT INTO sessions (folder_id, title, is_active) VALUES (3, ?, 0)", [t]);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Add random sessions if we don't have enough to demonstrate the UI
|
|
236
|
+
const sessionCount = await db.get('SELECT COUNT(*) as count FROM sessions');
|
|
237
|
+
if (sessionCount.count < 15) {
|
|
238
|
+
const titles = [
|
|
239
|
+
'Fix header styling issue', 'Implement authentication flow', 'Setup CI/CD pipeline',
|
|
240
|
+
'Debug database connection', 'Update README.md docs', 'Refactor UI components'
|
|
241
|
+
];
|
|
242
|
+
|
|
243
|
+
for (let i = 1; i <= 3; i++) {
|
|
244
|
+
const numSessions = 3;
|
|
245
|
+
for (let j = 0; j < numSessions; j++) {
|
|
246
|
+
const title = titles[Math.floor(Math.random() * titles.length)] + ' #' + Math.floor(Math.random() * 1000);
|
|
247
|
+
await db.run('INSERT INTO sessions (folder_id, title, is_active) VALUES (?, ?, 0)', [i, title]);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Seed random files for all sessions if files table is empty
|
|
253
|
+
const fileCount = await db.get('SELECT COUNT(*) as count FROM files');
|
|
254
|
+
if (fileCount.count === 0) {
|
|
255
|
+
const allSessions = await db.all('SELECT id FROM sessions');
|
|
256
|
+
for (const session of allSessions) {
|
|
257
|
+
// Create root folders
|
|
258
|
+
const res = await db.run('INSERT INTO files (session_id, parent_id, name, type, is_expanded) VALUES (?, NULL, ?, ?, ?)', [session.id, 'src', 'folder', 1]);
|
|
259
|
+
const srcId = res.lastID;
|
|
260
|
+
|
|
261
|
+
const res2 = await db.run('INSERT INTO files (session_id, parent_id, name, type, is_expanded) VALUES (?, NULL, ?, ?, ?)', [session.id, 'components', 'folder', 0]);
|
|
262
|
+
const componentsId = res2.lastID;
|
|
263
|
+
|
|
264
|
+
// Create files in src
|
|
265
|
+
await db.run('INSERT INTO files (session_id, parent_id, name, type, is_expanded) VALUES (?, ?, ?, ?, ?)', [session.id, srcId, 'index.tsx', 'file', 0]);
|
|
266
|
+
await db.run('INSERT INTO files (session_id, parent_id, name, type, is_expanded) VALUES (?, ?, ?, ?, ?)', [session.id, srcId, 'App.tsx', 'file', 0]);
|
|
267
|
+
await db.run('INSERT INTO files (session_id, parent_id, name, type, is_expanded) VALUES (?, ?, ?, ?, ?)', [session.id, srcId, 'styles.css', 'file', 0]);
|
|
268
|
+
|
|
269
|
+
// Create files in components
|
|
270
|
+
await db.run('INSERT INTO files (session_id, parent_id, name, type, is_expanded) VALUES (?, ?, ?, ?, ?)', [session.id, componentsId, 'Button.tsx', 'file', 0]);
|
|
271
|
+
await db.run('INSERT INTO files (session_id, parent_id, name, type, is_expanded) VALUES (?, ?, ?, ?, ?)', [session.id, componentsId, 'Header.tsx', 'file', 0]);
|
|
272
|
+
|
|
273
|
+
// Some root files
|
|
274
|
+
await db.run('INSERT INTO files (session_id, parent_id, name, type, is_expanded) VALUES (?, NULL, ?, ?, ?)', [session.id, 'package.json', 'file', 0]);
|
|
275
|
+
await db.run('INSERT INTO files (session_id, parent_id, name, type, is_expanded) VALUES (?, NULL, ?, ?, ?)', [session.id, 'README.md', 'file', 0]);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
// MOCK=false (Real Data Mode): when SYNC_WORKSPACE is enabled (default),
|
|
280
|
+
// auto-create workspace folders from discovered omp projects. User-made
|
|
281
|
+
// folders are never deleted; only additive sync.
|
|
282
|
+
if (isWorkspaceSyncEnabled()) {
|
|
283
|
+
try {
|
|
284
|
+
await syncWorkspaceFoldersWithOmp(db);
|
|
285
|
+
} catch (err) {
|
|
286
|
+
// Discovery must never block app startup.
|
|
287
|
+
console.error('OMP workspace sync failed:', err);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const { migrateLegacyProjectSettings } = await import('@/shared/lib/workspace/project-settings-migration');
|
|
293
|
+
await migrateLegacyProjectSettings(db);
|
|
294
|
+
|
|
295
|
+
return db;
|
|
296
|
+
})();
|
|
297
|
+
|
|
298
|
+
return dbPromise;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Additive-only folder ↔ omp project sync: creates a workspace folder for
|
|
303
|
+
* every project discovered from ~/.omp/agent (folder name = lowercase
|
|
304
|
+
* basename, bound via project_path). It never modifies or deletes existing
|
|
305
|
+
* user data — no renames, no re-binding of unbound folders — and it skips
|
|
306
|
+
* projects the user has explicitly deleted (tombstoned in
|
|
307
|
+
* `deleted_workspaces`), so a deleted workspace stays deleted.
|
|
308
|
+
*/
|
|
309
|
+
async function syncWorkspaceFoldersWithOmp(db: DbClient): Promise<void> {
|
|
310
|
+
const { orderedOmpProjects, projectDisplayName } = await import('@/shared/lib/omp/session/sidebar');
|
|
311
|
+
|
|
312
|
+
const data = await loadOmpSidebarData();
|
|
313
|
+
const existing = await db.all('SELECT id, name, project_path FROM workspace_folders');
|
|
314
|
+
const tombstoned = await db.all('SELECT project_path FROM deleted_workspaces');
|
|
315
|
+
|
|
316
|
+
// Compare by canonical key, not raw string: tombstones may predate the
|
|
317
|
+
// directory (unresolved symlink spelling) while project.path is realpath'd.
|
|
318
|
+
const byPath = new Set(existing.map((r) => r.project_path).filter(Boolean).map(projectPathKey));
|
|
319
|
+
const usedNames = new Set(existing.map((r) => (r.name as string).toLowerCase()));
|
|
320
|
+
const deletedPaths = new Set(tombstoned.map((r) => projectPathKey(r.project_path as string)));
|
|
321
|
+
|
|
322
|
+
for (const project of orderedOmpProjects(data)) {
|
|
323
|
+
if (deletedPaths.has(projectPathKey(project.path))) continue;
|
|
324
|
+
if (byPath.has(projectPathKey(project.path))) continue;
|
|
325
|
+
|
|
326
|
+
const name = projectDisplayName(project);
|
|
327
|
+
let candidate = name;
|
|
328
|
+
let suffix = 2;
|
|
329
|
+
while (usedNames.has(candidate)) {
|
|
330
|
+
candidate = `${name}-${suffix++}`;
|
|
331
|
+
}
|
|
332
|
+
usedNames.add(candidate);
|
|
333
|
+
await db.run(
|
|
334
|
+
'INSERT INTO workspace_folders (name, is_expanded, project_path) VALUES (?, 1, ?)',
|
|
335
|
+
[candidate, project.path],
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
2
|
+
import { apiRoutes } from '@/server/routes';
|
|
3
|
+
import { ssrRoutes } from '@/server/plugins/ssr';
|
|
4
|
+
|
|
5
|
+
const port = Number(Bun.env.PORT) || 3000;
|
|
6
|
+
const host = Bun.env.HOST || 'localhost';
|
|
7
|
+
|
|
8
|
+
const app = new Elysia().use(apiRoutes).use(ssrRoutes);
|
|
9
|
+
|
|
10
|
+
await app.listen({ port, hostname: host });
|
|
11
|
+
|
|
12
|
+
console.log(`[ompchamber] listening on http://${host}:${port}`);
|
|
13
|
+
|
|
14
|
+
for (const signal of ['SIGTERM', 'SIGINT'] as const) {
|
|
15
|
+
process.once(signal, () => {
|
|
16
|
+
void app.stop();
|
|
17
|
+
process.exit(0);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { afterAll, afterEach, beforeEach, describe, expect, test } from 'bun:test';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import { homedir } from 'os';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
|
|
11
|
+
import { findProjectRuntimeDir, isTcpPortLive } from '@/server/lib/browser/runtime';
|
|
12
|
+
|
|
13
|
+
const tempRoots: string[] = [];
|
|
14
|
+
const savedEnv: Record<string, string | undefined> = {};
|
|
15
|
+
|
|
16
|
+
async function makeRuntimeDir(name: string): Promise<string> {
|
|
17
|
+
const dir = join(homedir(), Bun.env.PI_CONFIG_DIR!, 'run', 'daemons', name);
|
|
18
|
+
await fs.promises.mkdir(join(dir, 'omp.browser.headless.profile'), { recursive: true });
|
|
19
|
+
await Bun.write(join(dir, 'scope.json'), JSON.stringify({ projectDir: '/tmp/fake-project' }));
|
|
20
|
+
return dir;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function writeDevToolsActivePort(runtimeDir: string, port: number, wsPath: string): Promise<void> {
|
|
24
|
+
await Bun.write(join(runtimeDir, 'omp.browser.headless.profile', 'DevToolsActivePort'), `${port}\n${wsPath}\n`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
beforeEach(async () => {
|
|
28
|
+
// getConfigRoot() = homedir()/getConfigDirName(), and os.homedir() is
|
|
29
|
+
// snapshotted at process start — a runtime HOME change is invisible.
|
|
30
|
+
// PI_CONFIG_DIR is a *relative name* joined onto homedir, so isolate via a
|
|
31
|
+
// uniquely named config dir inside the real home.
|
|
32
|
+
savedEnv.PI_CONFIG_DIR = Bun.env.PI_CONFIG_DIR;
|
|
33
|
+
savedEnv.XDG_STATE_HOME = Bun.env.XDG_STATE_HOME;
|
|
34
|
+
const name = `.omp-browser-test-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
35
|
+
tempRoots.push(join(homedir(), name));
|
|
36
|
+
await fs.promises.mkdir(join(homedir(), name, 'run', 'daemons'), { recursive: true });
|
|
37
|
+
Bun.env.PI_CONFIG_DIR = name;
|
|
38
|
+
Bun.env.XDG_STATE_HOME = '';
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
if (savedEnv.PI_CONFIG_DIR === undefined) delete Bun.env.PI_CONFIG_DIR;
|
|
43
|
+
else Bun.env.PI_CONFIG_DIR = savedEnv.PI_CONFIG_DIR;
|
|
44
|
+
if (savedEnv.XDG_STATE_HOME === undefined) delete Bun.env.XDG_STATE_HOME;
|
|
45
|
+
else Bun.env.XDG_STATE_HOME = savedEnv.XDG_STATE_HOME;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
afterAll(() => {
|
|
49
|
+
for (const root of tempRoots) fs.rmSync(root, { recursive: true, force: true });
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('isTcpPortLive', () => {
|
|
53
|
+
test('true for a listening port', async () => {
|
|
54
|
+
const server = Bun.listen({ hostname: '127.0.0.1', port: 0, socket: { data() {}, close() {}, error() {} } });
|
|
55
|
+
try {
|
|
56
|
+
expect(await isTcpPortLive(server.port)).toBe(true);
|
|
57
|
+
} finally {
|
|
58
|
+
server.stop(true);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('false for a closed port', async () => {
|
|
63
|
+
// Grab a free port, then release it so nothing listens there.
|
|
64
|
+
const server = Bun.listen({ hostname: '127.0.0.1', port: 0, socket: { data() {}, close() {}, error() {} } });
|
|
65
|
+
const port = server.port;
|
|
66
|
+
server.stop(true);
|
|
67
|
+
expect(await isTcpPortLive(port)).toBe(false);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('findProjectRuntimeDir', () => {
|
|
72
|
+
test('returns endpoint for a live daemon', async () => {
|
|
73
|
+
const runtimeDir = await makeRuntimeDir('live');
|
|
74
|
+
const server = Bun.listen({ hostname: '127.0.0.1', port: 0, socket: { data() {}, close() {}, error() {} } });
|
|
75
|
+
try {
|
|
76
|
+
await writeDevToolsActivePort(runtimeDir, server.port, '/devtools/browser/live-id');
|
|
77
|
+
const found = await findProjectRuntimeDir('/tmp/fake-project');
|
|
78
|
+
expect(found).not.toBeNull();
|
|
79
|
+
expect(found?.port).toBe(server.port);
|
|
80
|
+
expect(found?.wsUrl).toBe(`ws://127.0.0.1:${server.port}/devtools/browser/live-id`);
|
|
81
|
+
expect(found?.daemonName).toBe('omp.browser.headless');
|
|
82
|
+
} finally {
|
|
83
|
+
server.stop(true);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('rejects a stale DevToolsActivePort whose port is dead', async () => {
|
|
88
|
+
const runtimeDir = await makeRuntimeDir('stale');
|
|
89
|
+
const server = Bun.listen({ hostname: '127.0.0.1', port: 0, socket: { data() {}, close() {}, error() {} } });
|
|
90
|
+
const port = server.port;
|
|
91
|
+
server.stop(true);
|
|
92
|
+
await writeDevToolsActivePort(runtimeDir, port, '/devtools/browser/dead-id');
|
|
93
|
+
expect(await findProjectRuntimeDir('/tmp/fake-project')).toBeNull();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('returns null for an unknown project', async () => {
|
|
97
|
+
await makeRuntimeDir('other');
|
|
98
|
+
const server = Bun.listen({ hostname: '127.0.0.1', port: 0, socket: { data() {}, close() {}, error() {} } });
|
|
99
|
+
try {
|
|
100
|
+
await writeDevToolsActivePort(
|
|
101
|
+
join(homedir(), Bun.env.PI_CONFIG_DIR!, 'run', 'daemons', 'other'),
|
|
102
|
+
server.port,
|
|
103
|
+
'/devtools/browser/other',
|
|
104
|
+
);
|
|
105
|
+
expect(await findProjectRuntimeDir('/tmp/never-registered')).toBeNull();
|
|
106
|
+
} finally {
|
|
107
|
+
server.stop(true);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Discovery of omp's project-shared Chromium runtime state.
|
|
8
|
+
*
|
|
9
|
+
* For a project directory omp runs one broker-supervised browser daemon under
|
|
10
|
+
* `~/.omp/run/daemons/<hash>/` (or `$XDG_STATE_HOME/omp/run/daemons/<hash>/`).
|
|
11
|
+
* `scope.json` maps the runtime dir back to its project; `<daemon>.profile/
|
|
12
|
+
* DevToolsActivePort` carries the live CDP port and WebSocket path; and
|
|
13
|
+
* `<daemon>.targets/<ompPid>.json` lists the page target ids that the omp
|
|
14
|
+
* process with that pid opened. This module only reads that state — it never
|
|
15
|
+
* starts, mutates, or closes the browser.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { readdir, realpath } from 'fs/promises';
|
|
19
|
+
import * as path from 'path';
|
|
20
|
+
import { getConfigRoot } from '@/server/lib/omp/core/paths';
|
|
21
|
+
|
|
22
|
+
/** Candidate daemon names, in the order the viewer prefers them. */
|
|
23
|
+
const DAEMON_NAMES = ['omp.browser.headless', 'omp.browser.headed'] as const;
|
|
24
|
+
|
|
25
|
+
/** File Chromium writes next to its profile with the live CDP endpoint. */
|
|
26
|
+
const DEVTOOLS_ACTIVE_PORT = 'DevToolsActivePort';
|
|
27
|
+
|
|
28
|
+
interface ProjectRuntime {
|
|
29
|
+
runtimeDir: string;
|
|
30
|
+
daemonName: string;
|
|
31
|
+
/** CDP TCP port (DevToolsActivePort line 1). */
|
|
32
|
+
port: number;
|
|
33
|
+
/** Browser-level CDP WebSocket URL: ws://127.0.0.1:<port><wsPath>. */
|
|
34
|
+
wsUrl: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Resolve symlinks when possible; fall back to a plain absolute path. */
|
|
38
|
+
async function canonicalPath(value: string): Promise<string> {
|
|
39
|
+
try {
|
|
40
|
+
return await realpath(value);
|
|
41
|
+
} catch {
|
|
42
|
+
return path.resolve(value);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Runtime-dir roots to scan: the config root always, XDG state when set. */
|
|
47
|
+
function candidateRoots(): string[] {
|
|
48
|
+
const roots = [path.join(getConfigRoot(), 'run', 'daemons')];
|
|
49
|
+
const stateHome = Bun.env.XDG_STATE_HOME?.trim();
|
|
50
|
+
if (stateHome) roots.push(path.join(stateHome, 'omp', 'run', 'daemons'));
|
|
51
|
+
return roots;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* TCP probe with a short timeout — Chromium writes DevToolsActivePort before
|
|
56
|
+
* it starts listening, and the file survives a crash, so the port must be
|
|
57
|
+
* checked before the endpoint is trusted.
|
|
58
|
+
*/
|
|
59
|
+
export async function isTcpPortLive(port: number, host = '127.0.0.1', timeoutMs = 750): Promise<boolean> {
|
|
60
|
+
const socket = Bun.connect({
|
|
61
|
+
hostname: host,
|
|
62
|
+
port,
|
|
63
|
+
socket: {
|
|
64
|
+
data() {},
|
|
65
|
+
close() {},
|
|
66
|
+
error() {},
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
// Bun.connect resolves to a TCPSocket on success and rejects with
|
|
70
|
+
// "Failed to connect" when nothing listens — no timeout race needed for the
|
|
71
|
+
// loopback case, but guard against a hung connect anyway.
|
|
72
|
+
const opened = await Promise.race([
|
|
73
|
+
socket.then(() => true, () => false),
|
|
74
|
+
new Promise<boolean>((resolve) => setTimeout(() => resolve(false), timeoutMs)),
|
|
75
|
+
]);
|
|
76
|
+
if (opened) await socket.then((s) => s.end());
|
|
77
|
+
return opened;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Read a daemon's live CDP endpoint from its DevToolsActivePort file. */
|
|
81
|
+
async function readDaemonEndpoint(
|
|
82
|
+
runtimeDir: string,
|
|
83
|
+
): Promise<{ daemonName: string; port: number; wsUrl: string } | null> {
|
|
84
|
+
for (const daemonName of DAEMON_NAMES) {
|
|
85
|
+
const file = path.join(runtimeDir, `${daemonName}.profile`, DEVTOOLS_ACTIVE_PORT);
|
|
86
|
+
let raw: string;
|
|
87
|
+
try {
|
|
88
|
+
raw = await Bun.file(file).text();
|
|
89
|
+
} catch {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const [portLine = '', pathLine = ''] = raw.split('\n');
|
|
93
|
+
const port = Number.parseInt(portLine.trim(), 10);
|
|
94
|
+
const wsPath = pathLine.trim();
|
|
95
|
+
if (!Number.isInteger(port) || port <= 0 || !wsPath) continue;
|
|
96
|
+
// Stale file: Chromium crashed or was killed after writing it. Treat the
|
|
97
|
+
// daemon as gone so callers report `browser-offline` instead of hanging.
|
|
98
|
+
if (!(await isTcpPortLive(port))) continue;
|
|
99
|
+
return { daemonName, port, wsUrl: `ws://127.0.0.1:${port}${wsPath}` };
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Find the runtime dir whose `scope.json` points at `cwd` and return its live
|
|
106
|
+
* daemon endpoint, or null when the project has no running shared browser.
|
|
107
|
+
*/
|
|
108
|
+
export async function findProjectRuntimeDir(cwd: string): Promise<ProjectRuntime | null> {
|
|
109
|
+
if (!cwd) return null;
|
|
110
|
+
const target = await canonicalPath(cwd);
|
|
111
|
+
for (const root of candidateRoots()) {
|
|
112
|
+
let entries: string[];
|
|
113
|
+
try {
|
|
114
|
+
entries = await readdir(root);
|
|
115
|
+
} catch {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
for (const entry of entries) {
|
|
119
|
+
const runtimeDir = path.join(root, entry);
|
|
120
|
+
let scopeRaw: string;
|
|
121
|
+
try {
|
|
122
|
+
scopeRaw = await Bun.file(path.join(runtimeDir, 'scope.json')).text();
|
|
123
|
+
} catch {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
let projectDir: unknown;
|
|
127
|
+
try {
|
|
128
|
+
projectDir = (JSON.parse(scopeRaw) as { projectDir?: unknown }).projectDir;
|
|
129
|
+
} catch {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (typeof projectDir !== 'string' || projectDir.length === 0) continue;
|
|
133
|
+
if ((await canonicalPath(projectDir)) !== target) continue;
|
|
134
|
+
const endpoint = await readDaemonEndpoint(runtimeDir);
|
|
135
|
+
if (endpoint) return { runtimeDir, ...endpoint };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Page target ids opened by the omp process with `pid`, in creation order.
|
|
143
|
+
* Missing or malformed registry files degrade to an empty list.
|
|
144
|
+
*/
|
|
145
|
+
export async function readOwnedTargetIds(
|
|
146
|
+
runtimeDir: string,
|
|
147
|
+
daemonName: string,
|
|
148
|
+
pid: number,
|
|
149
|
+
): Promise<string[]> {
|
|
150
|
+
try {
|
|
151
|
+
const raw = await Bun.file(path.join(runtimeDir, `${daemonName}.targets`, `${pid}.json`)).text();
|
|
152
|
+
const parsed = JSON.parse(raw) as { pid?: unknown; targets?: unknown };
|
|
153
|
+
// Guard against a recycled pid inheriting a dead process's registry file.
|
|
154
|
+
if (parsed.pid !== pid) return [];
|
|
155
|
+
if (!Array.isArray(parsed.targets)) return [];
|
|
156
|
+
return parsed.targets.filter((target): target is string => typeof target === 'string');
|
|
157
|
+
} catch {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
}
|