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,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Message-send core for the chamber chat: reads text/image attachments, builds
|
|
8
|
+
* the optimistic user + AI placeholder bubbles, then routes the send through
|
|
9
|
+
* the live omp agent bridge (existing/new session) or the mock SSE stream.
|
|
10
|
+
* Extracted from useChatTimeline so that hook stays under the size ceiling.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { useCallback } from 'preact/hooks';
|
|
14
|
+
import type { Dispatch, SetStateAction } from 'preact/compat';
|
|
15
|
+
import type { Attachment, ChatMessageData, OmpAgentHandle, QueuedMessageModel } from '@/shared/types';
|
|
16
|
+
import type { ApprovalMode } from '@/shared/lib/omp/config/access-mode';
|
|
17
|
+
import { streamChatResponse } from '@/client/hooks/chat/stream';
|
|
18
|
+
import { composeMessageWithTextAttachments, isTextAttachmentFile } from '@/shared/lib/chat/attachments';
|
|
19
|
+
import { loadAgentNames } from '@/shared/lib/chat/composer/client';
|
|
20
|
+
import { translateAgentMentions, translateFileMentions } from '@/shared/lib/chat/composer/translate';
|
|
21
|
+
import { normalizeNoticePositions } from '@/shared/lib/chat/order';
|
|
22
|
+
import { createMockStreamCallbacks } from '@/shared/lib/chat/timeline/stream-callbacks';
|
|
23
|
+
import { PHASE_VERBS } from '@/shared/lib/chat/timeline/tool-phrases';
|
|
24
|
+
import { formatClock } from '@/shared/lib/format/time';
|
|
25
|
+
|
|
26
|
+
type TextFileAttachment = Parameters<typeof composeMessageWithTextAttachments>[1][number];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Build the outgoing prompt. `@agent` mentions are rewritten into an explicit
|
|
30
|
+
* task-tool delegation directive at send time (oh-my-pi has no `@agent`
|
|
31
|
+
* syntax); translation failures fall back to the raw prompt.
|
|
32
|
+
*/
|
|
33
|
+
async function buildPromptText(text: string, textFiles: TextFileAttachment[]): Promise<string> {
|
|
34
|
+
let translated = text;
|
|
35
|
+
try {
|
|
36
|
+
const names = await loadAgentNames();
|
|
37
|
+
if (names.length > 0) translated = translateAgentMentions(text, names).text;
|
|
38
|
+
} catch {
|
|
39
|
+
// keep the raw prompt
|
|
40
|
+
}
|
|
41
|
+
// File mentions are namespaced (`@file:`) by the picker; strip the namespace
|
|
42
|
+
// only after the agent pass so `@file:<name>` is never mistaken for `@agent`.
|
|
43
|
+
return composeMessageWithTextAttachments(translateFileMentions(translated), textFiles);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ChatTimelineSendDeps {
|
|
47
|
+
folders: any[];
|
|
48
|
+
selectedFolderId: number | null;
|
|
49
|
+
sessionId: string | null;
|
|
50
|
+
isOmpSession: boolean;
|
|
51
|
+
appSettings: Record<string, any>;
|
|
52
|
+
ompAgent: OmpAgentHandle;
|
|
53
|
+
setLocalMessages: Dispatch<SetStateAction<ChatMessageData[]>>;
|
|
54
|
+
persistMessages: (messages: any[]) => void;
|
|
55
|
+
setGenerating: (v: boolean) => void;
|
|
56
|
+
setGeneratingVerb: (v: string) => void;
|
|
57
|
+
/** Follow-gated scroll for stream chunks. */
|
|
58
|
+
scrollToBottom: (behavior?: ScrollBehavior) => void;
|
|
59
|
+
/** Explicit user-action scroll: re-engages follow mode (send/steer). */
|
|
60
|
+
jumpToBottom: (behavior?: ScrollBehavior) => void;
|
|
61
|
+
aiPlaceholderIdRef: { current: string | null };
|
|
62
|
+
adoptedSessionIdRef: { current: string | null };
|
|
63
|
+
optimisticUserIdRef: { current: string | null };
|
|
64
|
+
pendingUserDisplaysRef: { current: { sent: string; display: string }[] };
|
|
65
|
+
setSessionModel: (model: { provider: string; modelId: string } | null) => void;
|
|
66
|
+
/** Model/thinking picked in the composer before the session existed —
|
|
67
|
+
* applied to the spawn command so the first prompt runs with them. */
|
|
68
|
+
pendingComposerModelRef: { current: { provider: string; modelId: string } | null };
|
|
69
|
+
pendingThinkingLevelRef: { current: string | null };
|
|
70
|
+
/** Global access-control mode (persisted user preference), read at send time
|
|
71
|
+
* so the spawn-capable requests carry the latest value. */
|
|
72
|
+
accessModeRef: { current: ApprovalMode };
|
|
73
|
+
/** Live composer model/thinking mirror (written by ChatInput) so enqueue can
|
|
74
|
+
* snapshot the selection onto queued items. */
|
|
75
|
+
composerModelRef: { current: { provider: string; modelId: string; thinkingLevel: string } | null };
|
|
76
|
+
abortControllerRef: { current: AbortController | null };
|
|
77
|
+
setInputValue: (v: string) => void;
|
|
78
|
+
setSearchParams: (fn: (prev: URLSearchParams) => URLSearchParams, opts?: { replace?: boolean }) => void;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface ChatTimelineSendResult {
|
|
82
|
+
steerOmpAgent: (text: string, attachments: Attachment[]) => Promise<void>;
|
|
83
|
+
/** `model` re-applies a queued item's snapshot before the prompt runs
|
|
84
|
+
* (set_model / set_thinking_level RPC + prompt access mode). */
|
|
85
|
+
executeSend: (
|
|
86
|
+
text: string,
|
|
87
|
+
attachments: Attachment[],
|
|
88
|
+
options?: { model?: QueuedMessageModel | null },
|
|
89
|
+
) => Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function useChatTimelineSend(deps: ChatTimelineSendDeps): ChatTimelineSendResult {
|
|
93
|
+
const {
|
|
94
|
+
folders,
|
|
95
|
+
selectedFolderId,
|
|
96
|
+
sessionId,
|
|
97
|
+
isOmpSession,
|
|
98
|
+
appSettings,
|
|
99
|
+
ompAgent,
|
|
100
|
+
setLocalMessages,
|
|
101
|
+
persistMessages,
|
|
102
|
+
setGenerating,
|
|
103
|
+
setGeneratingVerb,
|
|
104
|
+
scrollToBottom,
|
|
105
|
+
jumpToBottom,
|
|
106
|
+
aiPlaceholderIdRef,
|
|
107
|
+
adoptedSessionIdRef,
|
|
108
|
+
optimisticUserIdRef,
|
|
109
|
+
pendingUserDisplaysRef,
|
|
110
|
+
setSessionModel,
|
|
111
|
+
pendingComposerModelRef,
|
|
112
|
+
pendingThinkingLevelRef,
|
|
113
|
+
accessModeRef,
|
|
114
|
+
abortControllerRef,
|
|
115
|
+
setInputValue,
|
|
116
|
+
setSearchParams,
|
|
117
|
+
} = deps;
|
|
118
|
+
|
|
119
|
+
// Reads text-file attachments and builds the prompt + image payload for an
|
|
120
|
+
// omp delivery (mirror of executeSend's assembly block).
|
|
121
|
+
const prepareDeliverable = useCallback(async (
|
|
122
|
+
text: string,
|
|
123
|
+
attachments: Attachment[],
|
|
124
|
+
): Promise<{ promptText: string; images?: { data: string; mimeType: string }[] }> => {
|
|
125
|
+
const textFileContents = new Map<string, string>();
|
|
126
|
+
try {
|
|
127
|
+
await Promise.all(
|
|
128
|
+
attachments
|
|
129
|
+
.filter(a => isTextAttachmentFile(a.file))
|
|
130
|
+
.map(async a => {
|
|
131
|
+
textFileContents.set(a.id, await a.file.text());
|
|
132
|
+
})
|
|
133
|
+
);
|
|
134
|
+
} catch {
|
|
135
|
+
// Fall back to prompt without inlined contents if a file cannot be read.
|
|
136
|
+
}
|
|
137
|
+
const textFiles = attachments
|
|
138
|
+
.filter(a => textFileContents.has(a.id))
|
|
139
|
+
.map(a => ({
|
|
140
|
+
name: a.file.name,
|
|
141
|
+
mimeType: a.file.type,
|
|
142
|
+
content: textFileContents.get(a.id) as string,
|
|
143
|
+
size: a.file.size,
|
|
144
|
+
}));
|
|
145
|
+
const promptText = await buildPromptText(text, textFiles);
|
|
146
|
+
pendingUserDisplaysRef.current = [...pendingUserDisplaysRef.current.slice(-7), { sent: promptText, display: text }];
|
|
147
|
+
const images = attachments
|
|
148
|
+
.filter(a => a.file.type.startsWith('image/') && a.dataBase64)
|
|
149
|
+
.map(a => ({ data: a.dataBase64 as string, mimeType: a.file.type }));
|
|
150
|
+
return { promptText, images: images.length ? images : undefined };
|
|
151
|
+
}, []);
|
|
152
|
+
|
|
153
|
+
// Steer the running omp agent with a fresh prompt (interrupt-and-reply).
|
|
154
|
+
const steerOmpAgent = useCallback(async (text: string, attachments: Attachment[]) => {
|
|
155
|
+
const { promptText, images } = await prepareDeliverable(text, attachments);
|
|
156
|
+
const ok = await ompAgent.sendInterruptAndReply(promptText, images);
|
|
157
|
+
if (!ok) setInputValue(text);
|
|
158
|
+
}, [ompAgent, prepareDeliverable, setInputValue]);
|
|
159
|
+
|
|
160
|
+
const executeSend = useCallback(async (
|
|
161
|
+
text: string,
|
|
162
|
+
attachments: Attachment[],
|
|
163
|
+
options?: { model?: QueuedMessageModel | null },
|
|
164
|
+
) => {
|
|
165
|
+
// A queued delivery replays the snapshot the item was queued with; a plain
|
|
166
|
+
// send keeps the session's live picks. 'auto' thinking leaves omp alone.
|
|
167
|
+
const modelOverride = options?.model ?? null;
|
|
168
|
+
const effectiveAccessMode = modelOverride?.accessMode ?? accessModeRef.current;
|
|
169
|
+
const time = formatClock();
|
|
170
|
+
const userMsgId = `msg-${Date.now()}-user`;
|
|
171
|
+
const aiPlaceholderId = `msg-${Date.now() + 1}-ai`;
|
|
172
|
+
|
|
173
|
+
// Read text-file contents once: used for the editor (attachment.content)
|
|
174
|
+
// and for inlining into the prompt (mirror omp-web).
|
|
175
|
+
const textFileContents = new Map<string, string>();
|
|
176
|
+
try {
|
|
177
|
+
await Promise.all(
|
|
178
|
+
attachments
|
|
179
|
+
.filter(a => isTextAttachmentFile(a.file))
|
|
180
|
+
.map(async a => {
|
|
181
|
+
textFileContents.set(a.id, await a.file.text());
|
|
182
|
+
})
|
|
183
|
+
);
|
|
184
|
+
} catch {
|
|
185
|
+
// Fall back to prompt without inlined contents if a file cannot be read.
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const now = Date.now();
|
|
189
|
+
const newUserMsg: ChatMessageData = {
|
|
190
|
+
id: userMsgId,
|
|
191
|
+
role: 'user',
|
|
192
|
+
date: `Today, ${time}`,
|
|
193
|
+
// Precise epoch anchor: the footer run-duration measures from here until
|
|
194
|
+
// the last AI message. The display `date` label is minute-granular, so a
|
|
195
|
+
// string fallback would inflate the measured span by up to 59s.
|
|
196
|
+
startedAt: now,
|
|
197
|
+
content: text,
|
|
198
|
+
attachments: attachments.map(a => ({
|
|
199
|
+
name: a.file.name,
|
|
200
|
+
preview: a.dataBase64 ? `data:${a.file.type};base64,${a.dataBase64}` : a.preview,
|
|
201
|
+
type: a.file.type,
|
|
202
|
+
size: a.file.size,
|
|
203
|
+
content: textFileContents.get(a.id),
|
|
204
|
+
}))
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const initialAiMsg: ChatMessageData = {
|
|
208
|
+
id: aiPlaceholderId,
|
|
209
|
+
role: 'ai',
|
|
210
|
+
date: `Today, ${time}`,
|
|
211
|
+
startedAt: now,
|
|
212
|
+
content: '',
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
setLocalMessages(prev => {
|
|
216
|
+
const next = normalizeNoticePositions([...prev, newUserMsg, initialAiMsg]);
|
|
217
|
+
persistMessages(next.filter(m => m.id !== aiPlaceholderId));
|
|
218
|
+
return next;
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
setGenerating(true);
|
|
222
|
+
setGeneratingVerb(PHASE_VERBS.thinking);
|
|
223
|
+
// An explicit send is user intent to watch the answer: re-engage follow
|
|
224
|
+
// mode even if the user had scrolled away, then scroll to the tail.
|
|
225
|
+
setTimeout(() => jumpToBottom('smooth'), 50);
|
|
226
|
+
|
|
227
|
+
// Real mode: route through the omp agent RPC bridge + event stream.
|
|
228
|
+
if (isOmpSession) {
|
|
229
|
+
aiPlaceholderIdRef.current = aiPlaceholderId;
|
|
230
|
+
optimisticUserIdRef.current = userMsgId;
|
|
231
|
+
// Replay the queued snapshot first so the prompt runs on the exact
|
|
232
|
+
// model/thinking the item was queued with.
|
|
233
|
+
if (modelOverride) {
|
|
234
|
+
await ompAgent.setModel(modelOverride.provider, modelOverride.modelId);
|
|
235
|
+
if (modelOverride.thinkingLevel !== 'auto') {
|
|
236
|
+
await ompAgent.setThinkingLevel(modelOverride.thinkingLevel);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const images = attachments
|
|
240
|
+
.filter(a => a.file.type.startsWith('image/') && a.dataBase64)
|
|
241
|
+
.map(a => ({ data: a.dataBase64 as string, mimeType: a.file.type }));
|
|
242
|
+
// Inline text-file contents into the prompt (mirror omp-web): the model
|
|
243
|
+
// sees the full file content as fenced blocks, not just the filename.
|
|
244
|
+
const textFiles = attachments
|
|
245
|
+
.filter(a => textFileContents.has(a.id))
|
|
246
|
+
.map(a => ({
|
|
247
|
+
name: a.file.name,
|
|
248
|
+
mimeType: a.file.type,
|
|
249
|
+
content: textFileContents.get(a.id) as string,
|
|
250
|
+
size: a.file.size,
|
|
251
|
+
}));
|
|
252
|
+
const promptText = await buildPromptText(text, textFiles);
|
|
253
|
+
const ok = await ompAgent.sendPrompt(promptText, images.length ? images : undefined, { accessMode: effectiveAccessMode });
|
|
254
|
+
if (!ok) {
|
|
255
|
+
// Roll back the optimistic bubbles on a failed send.
|
|
256
|
+
setLocalMessages(prev => prev.filter(m => m.id !== userMsgId && m.id !== aiPlaceholderId));
|
|
257
|
+
aiPlaceholderIdRef.current = null;
|
|
258
|
+
optimisticUserIdRef.current = null;
|
|
259
|
+
setGenerating(false);
|
|
260
|
+
}
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// No active session (fresh "New Session"): in real mode spawn a brand-new
|
|
265
|
+
// omp session and adopt its id; fall back to the mock/simulated path only
|
|
266
|
+
// when the spawn fails (e.g. MOCK=true or no workspace context).
|
|
267
|
+
if (!isOmpSession) {
|
|
268
|
+
const currentFolder = folders.find(f => String(f.id) === String(selectedFolderId));
|
|
269
|
+
const cwd = currentFolder?.project_path || currentFolder?.name;
|
|
270
|
+
if (cwd) {
|
|
271
|
+
const images = attachments
|
|
272
|
+
.filter(a => a.file.type.startsWith('image/') && a.dataBase64)
|
|
273
|
+
.map(a => ({ data: a.dataBase64 as string, mimeType: a.file.type }));
|
|
274
|
+
const textFiles = attachments
|
|
275
|
+
.filter(a => textFileContents.has(a.id))
|
|
276
|
+
.map(a => ({
|
|
277
|
+
name: a.file.name,
|
|
278
|
+
mimeType: a.file.type,
|
|
279
|
+
content: textFileContents.get(a.id) as string,
|
|
280
|
+
size: a.file.size,
|
|
281
|
+
}));
|
|
282
|
+
const promptText = await buildPromptText(text, textFiles);
|
|
283
|
+
optimisticUserIdRef.current = userMsgId;
|
|
284
|
+
const composerModel = pendingComposerModelRef.current;
|
|
285
|
+
const composerThinking = pendingThinkingLevelRef.current;
|
|
286
|
+
const spawned = await ompAgent.sendNewPrompt(
|
|
287
|
+
promptText,
|
|
288
|
+
cwd,
|
|
289
|
+
images.length ? images : undefined,
|
|
290
|
+
{ model: composerModel, thinkingLevel: composerThinking, accessMode: accessModeRef.current },
|
|
291
|
+
);
|
|
292
|
+
if (spawned) {
|
|
293
|
+
adoptedSessionIdRef.current = spawned.sessionId;
|
|
294
|
+
aiPlaceholderIdRef.current = aiPlaceholderId;
|
|
295
|
+
if (spawned.model) setSessionModel(spawned.model);
|
|
296
|
+
pendingComposerModelRef.current = null;
|
|
297
|
+
pendingThinkingLevelRef.current = null;
|
|
298
|
+
fetch(`/api/chat/${encodeURIComponent(spawned.sessionId)}`, {
|
|
299
|
+
method: 'POST',
|
|
300
|
+
headers: { 'Content-Type': 'application/json' },
|
|
301
|
+
body: JSON.stringify({ messages: [newUserMsg] }),
|
|
302
|
+
}).catch(err => console.error('Error persisting spawned user turn:', err));
|
|
303
|
+
setSearchParams(prev => {
|
|
304
|
+
const next = new URLSearchParams(prev);
|
|
305
|
+
next.set('sessionId', spawned.sessionId);
|
|
306
|
+
return next;
|
|
307
|
+
}, { replace: true });
|
|
308
|
+
// The agent_start event refreshes the session metadata/sidebar once
|
|
309
|
+
// the JSONL has the user turn; no immediate refresh is needed here.
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Mock / chamber-created session: existing Gemini/simulated SSE path.
|
|
316
|
+
// Cancel any previous stream
|
|
317
|
+
optimisticUserIdRef.current = null;
|
|
318
|
+
if (abortControllerRef.current) {
|
|
319
|
+
abortControllerRef.current.abort();
|
|
320
|
+
}
|
|
321
|
+
const abortController = new AbortController();
|
|
322
|
+
abortControllerRef.current = abortController;
|
|
323
|
+
|
|
324
|
+
const currentFolder = folders.find(f => String(f.id) === String(selectedFolderId));
|
|
325
|
+
const workspaceName = currentFolder?.name || 'Workspace';
|
|
326
|
+
|
|
327
|
+
await streamChatResponse(
|
|
328
|
+
{
|
|
329
|
+
sessionId: sessionId || `session-${Date.now()}`,
|
|
330
|
+
prompt: text,
|
|
331
|
+
workspaceName,
|
|
332
|
+
attachments,
|
|
333
|
+
signal: abortController.signal,
|
|
334
|
+
},
|
|
335
|
+
createMockStreamCallbacks({
|
|
336
|
+
aiPlaceholderId,
|
|
337
|
+
setLocalMessages,
|
|
338
|
+
persistMessages,
|
|
339
|
+
setGenerating,
|
|
340
|
+
setGeneratingVerb,
|
|
341
|
+
abortControllerRef,
|
|
342
|
+
appSettings,
|
|
343
|
+
scrollToBottom,
|
|
344
|
+
})
|
|
345
|
+
);
|
|
346
|
+
}, [appSettings, folders, isOmpSession, ompAgent, selectedFolderId, sessionId, scrollToBottom, jumpToBottom, persistMessages, setSessionModel, pendingComposerModelRef, pendingThinkingLevelRef, accessModeRef]);
|
|
347
|
+
return { steerOmpAgent, executeSend };
|
|
348
|
+
}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Session loading core for the chamber chat: fetches /api/chat/:sessionId,
|
|
8
|
+
* applies session metadata (model / thinking level / title) and replaces the
|
|
9
|
+
* timeline with the committed messages. Extracted from useChatTimeline so that
|
|
10
|
+
* hook stays under the size ceiling.
|
|
11
|
+
*
|
|
12
|
+
* Reload-mid-stream contract: the timeline fetch must NOT depend on the
|
|
13
|
+
* generating flag alone. On a page reload during a run there is no optimistic
|
|
14
|
+
* bubble yet (fresh mount, refs are null), so the committed JSONL history —
|
|
15
|
+
* including the already-finalized turns of the in-flight run — must load
|
|
16
|
+
* normally; the stream resume continues from there. Clobbering is only possible
|
|
17
|
+
* while an optimistic AI placeholder actually owns the tail of the timeline.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { Dispatch, RefObject, SetStateAction } from 'preact/compat';
|
|
21
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks';
|
|
22
|
+
|
|
23
|
+
import type { ChatMessageData } from '@/shared/types';
|
|
24
|
+
import { normalizeNoticePositions } from '@/shared/lib/chat/order';
|
|
25
|
+
import { SESSION_META_RETRY_SCHEDULE_MS } from '@/shared/lib/workspace/refresh-cadence';
|
|
26
|
+
|
|
27
|
+
export interface SessionDataShape {
|
|
28
|
+
id?: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
model?: string | { provider: string; modelId: string };
|
|
31
|
+
thinkingLevel?: string;
|
|
32
|
+
messages?: any[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface UseSessionLoadDeps {
|
|
36
|
+
sessionId: string | null;
|
|
37
|
+
setLocalMessages: Dispatch<SetStateAction<ChatMessageData[]>>;
|
|
38
|
+
setGenerating: (v: boolean) => void;
|
|
39
|
+
/** Live generating flag written by the caller's `setGenerating` throat. Gates
|
|
40
|
+
* the committed-fetch clobber guard and the seeded-model fallback. */
|
|
41
|
+
isGeneratingRef: { current: boolean };
|
|
42
|
+
/** Live AI placeholder ref: when non-null it owns the timeline tail and the
|
|
43
|
+
* committed fetch must not replace it mid-stream. */
|
|
44
|
+
aiPlaceholderIdRef: { current: string | null };
|
|
45
|
+
/** Caller-owned timeline state mirror: lets the committed fetch merge the
|
|
46
|
+
* live stream tail (rows the JSONL does not carry yet) into history. */
|
|
47
|
+
localMessagesRef: { current: ChatMessageData[] };
|
|
48
|
+
/** Live optimistic user bubble ref: cleared together with the placeholder on
|
|
49
|
+
* a session switch so stale ids cannot survive into the next session. */
|
|
50
|
+
optimisticUserIdRef: { current: string | null };
|
|
51
|
+
/** Drop queued stream updates belonging to the previous session (coalescer). */
|
|
52
|
+
cancelStreamingCoalescer: () => void;
|
|
53
|
+
metaRefreshedRef: { current: string | null };
|
|
54
|
+
/** Scroll container of the timeline: lets loadOlder preserve the viewport
|
|
55
|
+
* position when older rows are prepended above it. */
|
|
56
|
+
scrollRef?: RefObject<HTMLDivElement>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function useSessionLoad(deps: UseSessionLoadDeps) {
|
|
60
|
+
const { sessionId, setLocalMessages, setGenerating, isGeneratingRef, aiPlaceholderIdRef, localMessagesRef, optimisticUserIdRef, cancelStreamingCoalescer, metaRefreshedRef, scrollRef } = deps;
|
|
61
|
+
|
|
62
|
+
const [sessionData, setSessionData] = useState<SessionDataShape | null>(null);
|
|
63
|
+
// History pagination state: the first fetch receives the newest window only;
|
|
64
|
+
// scrolling to the top pages further back via ?before=oldestIndex.
|
|
65
|
+
const [hasMore, setHasMore] = useState(false);
|
|
66
|
+
const [oldestIndex, setOldestIndex] = useState(0);
|
|
67
|
+
const [loadingOlder, setLoadingOlder] = useState(false);
|
|
68
|
+
// Sticky failure flag for the "Load earlier messages" affordance: a failed
|
|
69
|
+
// page fetch must keep the button visible (retryable) instead of silently
|
|
70
|
+
// dropping hasMore, which made the button vanish with no feedback.
|
|
71
|
+
const [loadOlderError, setLoadOlderError] = useState(false);
|
|
72
|
+
// Bumped on every successful older-window prepend; the scroll-anchor layout
|
|
73
|
+
// effect keys on it (its other deps have stable identities, so it needs an
|
|
74
|
+
// explicit change signal per commit).
|
|
75
|
+
const [prependTick, setPrependTick] = useState(0);
|
|
76
|
+
const loadingOlderRef = useRef(false);
|
|
77
|
+
const [sessionLoading, setSessionLoading] = useState(false);
|
|
78
|
+
// Set while prepending older rows; the layout effect below re-anchors the
|
|
79
|
+
// viewport to the content the user was reading instead of jumping.
|
|
80
|
+
const pendingScrollAnchorRef = useRef<{ prevHeight: number; prevTop: number } | null>(null);
|
|
81
|
+
const prevSessionIdRef = useRef<string | null>(null);
|
|
82
|
+
// Real session id adopted by a fresh spawn ("new-…" → UUID). onAgentStart
|
|
83
|
+
// may fire before React re-renders with the new URL, so it reads the id
|
|
84
|
+
// from here instead of the (still-stale) sessionId prop.
|
|
85
|
+
const adoptedSessionIdRef = useRef<string | null>(null);
|
|
86
|
+
// Model seeded from the spawn response; kept until the JSONL writes model_change.
|
|
87
|
+
const seededModelRef = useRef<{ provider: string; modelId: string } | null>(null);
|
|
88
|
+
|
|
89
|
+
const applySessionData = useCallback((incoming: SessionDataShape) => {
|
|
90
|
+
if (incoming.model && typeof incoming.model === 'object') seededModelRef.current = incoming.model;
|
|
91
|
+
const model = incoming.model ?? (isGeneratingRef.current ? seededModelRef.current ?? undefined : undefined);
|
|
92
|
+
setSessionData({ ...incoming, model });
|
|
93
|
+
}, []);
|
|
94
|
+
|
|
95
|
+
const sessionIdRef = useRef(sessionId);
|
|
96
|
+
sessionIdRef.current = sessionId;
|
|
97
|
+
|
|
98
|
+
/** Re-fetch the session's title/metadata after the omp JSONL has been
|
|
99
|
+
* written (spawn or agent end) so the navbar and context panel show the
|
|
100
|
+
* real session title instead of the default. Retries on a front-loaded
|
|
101
|
+
* backoff until the JSONL actually carries messages (omp writes the user
|
|
102
|
+
* turn on agent start). */
|
|
103
|
+
const refreshSessionMeta = useCallback((sid: string) => {
|
|
104
|
+
// The URL lags the adopted id right after a fresh spawn, so accept either.
|
|
105
|
+
const isActive = () => sessionIdRef.current === sid || adoptedSessionIdRef.current === sid;
|
|
106
|
+
if (!isActive()) return;
|
|
107
|
+
let attempt = 0;
|
|
108
|
+
const tryFetch = () => {
|
|
109
|
+
if (!isActive()) return;
|
|
110
|
+
fetch(`/api/chat/${encodeURIComponent(sid)}`)
|
|
111
|
+
.then(res => res.json())
|
|
112
|
+
.then(data => {
|
|
113
|
+
if (!data?.session || !isActive()) return;
|
|
114
|
+
applySessionData(data.session);
|
|
115
|
+
// Signal the sidebar only on a settled read: the early attempts of a
|
|
116
|
+
// fresh spawn see zero messages, and dispatching on those would reset
|
|
117
|
+
// the sidebar's throttle window for the whole spawn.
|
|
118
|
+
if ((data.session.messages?.length ?? 0) > 0) {
|
|
119
|
+
window.dispatchEvent(new CustomEvent('omp:session-updated', { detail: { sessionId: sid } }));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const delay = SESSION_META_RETRY_SCHEDULE_MS[attempt];
|
|
123
|
+
attempt += 1;
|
|
124
|
+
if (delay !== undefined) setTimeout(tryFetch, delay);
|
|
125
|
+
})
|
|
126
|
+
.catch(() => {});
|
|
127
|
+
};
|
|
128
|
+
tryFetch();
|
|
129
|
+
}, [applySessionData]);
|
|
130
|
+
|
|
131
|
+
const setSessionModelWithSeed = useCallback((model: { provider: string; modelId: string } | null) => {
|
|
132
|
+
seededModelRef.current = model;
|
|
133
|
+
setSessionData(prev => ({ ...(prev ?? {}), model: model ?? undefined }));
|
|
134
|
+
}, []);
|
|
135
|
+
|
|
136
|
+
/** Whether the optimistic bubble set currently owns the timeline tail (a
|
|
137
|
+
* local send is in flight). Only then must a committed fetch be skipped —
|
|
138
|
+
* a bare mount (reload mid-run) has isGenerating false AND no placeholder,
|
|
139
|
+
* so committed history still loads. */
|
|
140
|
+
const timelineOwnedByOptimistic = useCallback(
|
|
141
|
+
() => isGeneratingRef.current && Boolean(aiPlaceholderIdRef.current),
|
|
142
|
+
[aiPlaceholderIdRef],
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// Fetch session messages and details from API
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
let active = true;
|
|
148
|
+
setSessionLoading(true);
|
|
149
|
+
// Track the previous session id so a session switch (including "New
|
|
150
|
+
// Session" → new-…) clears the timeline, while the optimistic spawn
|
|
151
|
+
// transition (new-… → real UUID) keeps its bubbles.
|
|
152
|
+
if (sessionId !== prevSessionIdRef.current) {
|
|
153
|
+
const isSpawnAdopt = sessionId && !sessionId.startsWith('new-') && prevSessionIdRef.current?.startsWith('new-');
|
|
154
|
+
// Keep the optimistic bubbles while a local send is in flight and this
|
|
155
|
+
// session is the one it spawned (a fresh spawn may not have passed
|
|
156
|
+
// through "new-…"). A reload mid-run has no adopted id, so history loads.
|
|
157
|
+
const isAdoptingInFlight = isGeneratingRef.current && adoptedSessionIdRef.current === sessionId;
|
|
158
|
+
if (!isSpawnAdopt && !isAdoptingInFlight) {
|
|
159
|
+
setLocalMessages([]);
|
|
160
|
+
setGenerating(false);
|
|
161
|
+
adoptedSessionIdRef.current = null;
|
|
162
|
+
seededModelRef.current = null;
|
|
163
|
+
// The placeholder/optimistic ids belong to the PREVIOUS session's
|
|
164
|
+
// in-flight send; message_end never arrives after a switch away (the
|
|
165
|
+
// stream is disconnected), so they must be dropped here. A stale
|
|
166
|
+
// placeholder made timelineOwnedByOptimistic() report true on return,
|
|
167
|
+
// which silently DISCARDED the committed history fetch of the
|
|
168
|
+
// mid-run session — only newly streamed frames ever appeared.
|
|
169
|
+
aiPlaceholderIdRef.current = null;
|
|
170
|
+
optimisticUserIdRef.current = null;
|
|
171
|
+
// Drop coalesced message_update frames queued by the previous
|
|
172
|
+
// session's stream: otherwise they apply to this (cleared) timeline
|
|
173
|
+
// as phantom bubbles.
|
|
174
|
+
cancelStreamingCoalescer();
|
|
175
|
+
}
|
|
176
|
+
// Reset pagination cursor on every session switch — the window belongs
|
|
177
|
+
// to the previous session otherwise.
|
|
178
|
+
setHasMore(false);
|
|
179
|
+
setOldestIndex(0);
|
|
180
|
+
loadingOlderRef.current = false;
|
|
181
|
+
setLoadingOlder(false);
|
|
182
|
+
setLoadOlderError(false);
|
|
183
|
+
// metaRefreshedRef must NOT survive a session switch — including a
|
|
184
|
+
// spawn adoption. It is the once-per-session guard in onAgentStart
|
|
185
|
+
// (omp-callbacks.ts); keeping the stale value here ate the retrigger,
|
|
186
|
+
// so a title refresh that landed before the omp JSONL had messages
|
|
187
|
+
// (default timestamped title) never ran again and the sidebar stayed
|
|
188
|
+
// on the placeholder until some later event refreshed it.
|
|
189
|
+
metaRefreshedRef.current = null;
|
|
190
|
+
prevSessionIdRef.current = sessionId;
|
|
191
|
+
}
|
|
192
|
+
if (sessionId) {
|
|
193
|
+
fetch(`/api/chat/${sessionId}`)
|
|
194
|
+
.then(res => res.json())
|
|
195
|
+
.then(data => {
|
|
196
|
+
if (!active) return;
|
|
197
|
+
setSessionLoading(false);
|
|
198
|
+
if (data?.session) {
|
|
199
|
+
applySessionData(data.session);
|
|
200
|
+
// Only replace the timeline when the fetch actually has messages.
|
|
201
|
+
// A pending "new-…" session or a just-spawned omp session whose
|
|
202
|
+
// JSONL is not written yet must not wipe the optimistic bubbles.
|
|
203
|
+
const fetched = data.session.messages || [];
|
|
204
|
+
const optimisticOwnsTail = timelineOwnedByOptimistic();
|
|
205
|
+
if (fetched.length > 0 && !optimisticOwnsTail) {
|
|
206
|
+
// Reattach race: a resumed stream may have appended the
|
|
207
|
+
// in-flight segment before this committed fetch resolved (the
|
|
208
|
+
// JSONL does not carry it yet). Keep those live rows instead of
|
|
209
|
+
// dropping them until the next message_update re-renders them.
|
|
210
|
+
if (isGeneratingRef.current) {
|
|
211
|
+
const fetchedIds = fetched.map((m: ChatMessageData) => m.id);
|
|
212
|
+
const liveTail = localMessagesRef.current.filter(m => !fetchedIds.includes(m.id));
|
|
213
|
+
setLocalMessages(normalizeNoticePositions([...fetched, ...liveTail]));
|
|
214
|
+
} else {
|
|
215
|
+
setLocalMessages(normalizeNoticePositions(fetched));
|
|
216
|
+
}
|
|
217
|
+
} else if (!sessionId.startsWith('new-') && !optimisticOwnsTail) {
|
|
218
|
+
setLocalMessages([]);
|
|
219
|
+
}
|
|
220
|
+
if (typeof data.hasMore === 'boolean') setHasMore(data.hasMore);
|
|
221
|
+
if (typeof data.oldestIndex === 'number') setOldestIndex(data.oldestIndex);
|
|
222
|
+
} else {
|
|
223
|
+
setSessionData(null);
|
|
224
|
+
if (!timelineOwnedByOptimistic()) setLocalMessages([]);
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
.catch(err => {
|
|
228
|
+
console.error('Error loading session from API:', err);
|
|
229
|
+
if (active) setSessionLoading(false);
|
|
230
|
+
if (active && !timelineOwnedByOptimistic()) {
|
|
231
|
+
setSessionData(null);
|
|
232
|
+
setLocalMessages([]);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
} else {
|
|
236
|
+
setSessionData(null);
|
|
237
|
+
setLocalMessages([]);
|
|
238
|
+
}
|
|
239
|
+
return () => {
|
|
240
|
+
active = false;
|
|
241
|
+
};
|
|
242
|
+
// sessionModel identity flows through applySessionData; the effect only
|
|
243
|
+
// re-runs on session switches by design.
|
|
244
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
245
|
+
}, [sessionId, applySessionData, timelineOwnedByOptimistic, setLocalMessages, setGenerating]);
|
|
246
|
+
|
|
247
|
+
/** Page the next older window into the timeline. Called from the click
|
|
248
|
+
* handler and the scroll handler when the viewport reaches the top; a no-op
|
|
249
|
+
* while a page is in flight, when the session has no more history, or while
|
|
250
|
+
* the session is a pending optimistic spawn. Prepending older rows only
|
|
251
|
+
* grows the list ABOVE the tail, so it is safe while the agent is
|
|
252
|
+
* generating — unlike a committed refetch, it never clobbers the AI
|
|
253
|
+
* placeholder, and blocking it made the button feel dead mid-run. */
|
|
254
|
+
const loadOlder = useCallback(() => {
|
|
255
|
+
if (!sessionId || sessionId.startsWith('new-')) return;
|
|
256
|
+
if (!hasMore || loadingOlderRef.current) return;
|
|
257
|
+
loadingOlderRef.current = true;
|
|
258
|
+
setLoadingOlder(true);
|
|
259
|
+
setLoadOlderError(false);
|
|
260
|
+
const el = scrollRef?.current;
|
|
261
|
+
if (el) pendingScrollAnchorRef.current = { prevHeight: el.scrollHeight, prevTop: el.scrollTop };
|
|
262
|
+
// Session id snapshot: prepending a window fetched for the PREVIOUS
|
|
263
|
+
// session into the freshly-switched timeline is worse than dropping the
|
|
264
|
+
// page, so the response is discarded if the user switched mid-flight.
|
|
265
|
+
const requestedSessionId = sessionId;
|
|
266
|
+
fetch(`/api/chat/${sessionId}?before=${oldestIndex}`)
|
|
267
|
+
.then(res => {
|
|
268
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
269
|
+
return res.json();
|
|
270
|
+
})
|
|
271
|
+
.then((data: { session?: { messages?: ChatMessageData[] }; hasMore?: boolean; oldestIndex?: number }) => {
|
|
272
|
+
// The main load effect may have cleared/repurposed localMessages for a
|
|
273
|
+
// new session while this fetch was in flight.
|
|
274
|
+
if (sessionIdRef.current !== requestedSessionId) return;
|
|
275
|
+
const older = data.session?.messages ?? [];
|
|
276
|
+
setHasMore(Boolean(data.hasMore));
|
|
277
|
+
if (typeof data.oldestIndex === 'number') setOldestIndex(data.oldestIndex);
|
|
278
|
+
if (older.length === 0) {
|
|
279
|
+
// No rows prepended: the recorded anchor is stale — drop it so a
|
|
280
|
+
// later tick cannot apply it against the wrong geometry.
|
|
281
|
+
pendingScrollAnchorRef.current = null;
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
setLocalMessages(prev => {
|
|
285
|
+
// Drop overlap guard: the server window is index-based, so the
|
|
286
|
+
// fetched slice is strictly older than everything already mounted.
|
|
287
|
+
return [...normalizeNoticePositions(older), ...prev];
|
|
288
|
+
});
|
|
289
|
+
// Bump the prepend tick so the layout effect below re-runs for THIS
|
|
290
|
+
// commit — it previously depended only on stable identities and ran
|
|
291
|
+
// exactly once at mount, so the viewport anchor never fired and every
|
|
292
|
+
// pagination jump snapped the user to the (shifted) top.
|
|
293
|
+
setPrependTick(t => t + 1);
|
|
294
|
+
})
|
|
295
|
+
.catch(() => {
|
|
296
|
+
// Keep the button mounted and marked for retry; a swallowed failure
|
|
297
|
+
// previously also cleared hasMore on the next full reload path.
|
|
298
|
+
if (sessionIdRef.current === requestedSessionId) setLoadOlderError(true);
|
|
299
|
+
})
|
|
300
|
+
.finally(() => {
|
|
301
|
+
loadingOlderRef.current = false;
|
|
302
|
+
setLoadingOlder(false);
|
|
303
|
+
});
|
|
304
|
+
}, [sessionId, hasMore, oldestIndex, scrollRef, setLocalMessages]);
|
|
305
|
+
|
|
306
|
+
// Position preservation: after older rows commit above the viewport, shift
|
|
307
|
+
// scrollTop by the height delta so the rows the user was reading stay put.
|
|
308
|
+
// prependTick changes on every prepend — without it the effect ran only at
|
|
309
|
+
// mount (its other deps are stable) and never re-anchored.
|
|
310
|
+
useLayoutEffect(() => {
|
|
311
|
+
const anchor = pendingScrollAnchorRef.current;
|
|
312
|
+
if (!anchor) return;
|
|
313
|
+
const el = scrollRef?.current;
|
|
314
|
+
if (!el) return;
|
|
315
|
+
pendingScrollAnchorRef.current = null;
|
|
316
|
+
const delta = el.scrollHeight - anchor.prevHeight;
|
|
317
|
+
if (delta > 0) el.scrollTop = anchor.prevTop + delta;
|
|
318
|
+
}, [prependTick, scrollRef]);
|
|
319
|
+
|
|
320
|
+
return {
|
|
321
|
+
sessionData,
|
|
322
|
+
hasMore,
|
|
323
|
+
loadingOlder,
|
|
324
|
+
loadOlderError,
|
|
325
|
+
sessionLoading,
|
|
326
|
+
loadOlder,
|
|
327
|
+
adoptedSessionIdRef,
|
|
328
|
+
seededModelRef,
|
|
329
|
+
applySessionData,
|
|
330
|
+
refreshSessionMeta,
|
|
331
|
+
setSessionModel: setSessionModelWithSeed,
|
|
332
|
+
timelineOwnedByOptimistic,
|
|
333
|
+
};
|
|
334
|
+
}
|