diff --git a/Cargo.lock b/Cargo.lock index eb14a2f..9b1c826 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "adler2" version = "2.0.1" @@ -17,6 +23,24 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -29,7 +53,7 @@ version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67555e1f1ece39d737e28c8a017721287753af3f93225e4a445b29ccb0f5912c" dependencies = [ - "nom", + "nom 7.1.3", "ratatui", "simdutf8", "smallvec", @@ -42,12 +66,93 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.18", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 8.0.0", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" +dependencies = [ + "arrayvec", +] + [[package]] name = "axum" version = "0.8.9" @@ -115,18 +220,81 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +[[package]] +name = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "built" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" + [[package]] name = "bumpalo" version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.11.1" @@ -155,6 +323,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -164,6 +334,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "cfg_aliases" version = "0.2.1" @@ -177,14 +353,24 @@ dependencies = [ "anyhow", "axum", "futures-util", + "portable-pty", "ratatui", "reqwest", "serde", "serde_json", "tokio", "tui-markdown", + "uuid", + "wezterm-surface", + "wezterm-term", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "compact_str" version = "0.8.2" @@ -199,6 +385,15 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -208,13 +403,38 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crossterm" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags", + "bitflags 2.13.0", "crossterm_winapi", "mio", "parking_lot", @@ -233,6 +453,32 @@ dependencies = [ "winapi", ] +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csscolorparser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" +dependencies = [ + "lab", + "phf", +] + [[package]] name = "darling" version = "0.23.0" @@ -253,7 +499,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.117", ] [[package]] @@ -264,9 +510,15 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.117", ] +[[package]] +name = "deltae" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" + [[package]] name = "deranged" version = "0.5.8" @@ -282,6 +534,16 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "displaydoc" version = "0.2.6" @@ -290,15 +552,41 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "either" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -315,12 +603,94 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide 0.8.9", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fancy-regex" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + [[package]] name = "find-msvc-tools" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "finl_unicode" +version = "1.3.0" +source = "git+https://github.com/wez/finl_unicode.git?branch=no_std#a1892f26245529f2ef3877a9ebd610c96cec07a6" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flate2" version = "1.1.9" @@ -328,7 +698,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.9", ] [[package]] @@ -343,6 +713,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -381,7 +757,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -418,6 +794,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getopts" version = "0.2.24" @@ -449,17 +835,51 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "gif" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "glob" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.15.5" @@ -468,7 +888,18 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", ] [[package]] @@ -483,6 +914,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "http" version = "1.4.2" @@ -528,6 +965,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + [[package]] name = "hyper" version = "1.10.1" @@ -670,6 +1116,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -697,6 +1149,46 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7" + [[package]] name = "indexmap" version = "2.14.0" @@ -705,6 +1197,8 @@ checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown 0.17.1", + "serde", + "serde_core", ] [[package]] @@ -726,7 +1220,18 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn", + "syn 2.0.117", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -759,6 +1264,16 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.100" @@ -770,12 +1285,52 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lab" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + [[package]] name = "libc" version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +[[package]] +name = "libfuzzer-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -809,6 +1364,15 @@ version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + [[package]] name = "lru" version = "0.12.5" @@ -818,6 +1382,15 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "lru" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" +dependencies = [ + "hashbrown 0.16.1", +] + [[package]] name = "lru-slab" version = "0.1.2" @@ -830,12 +1403,28 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + [[package]] name = "memchr" version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +[[package]] +name = "memmem" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" + [[package]] name = "mime" version = "0.3.17" @@ -848,6 +1437,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -870,6 +1468,55 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.13.0", + "cfg-if", + "cfg_aliases 0.1.1", + "libc", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.13.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + +[[package]] +name = "no_std_io2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" +dependencies = [ + "memchr", +] + [[package]] name = "nom" version = "7.1.3" @@ -880,12 +1527,78 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-conv" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -898,7 +1611,7 @@ version = "6.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc3cbf698f9438986c11a880c90a6d04b9de27575afd28bbf45b154b6c709e2" dependencies = [ - "bitflags", + "bitflags 2.13.0", "libc", "once_cell", "onig_sys", @@ -914,6 +1627,15 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -943,12 +1665,113 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + [[package]] name = "percent-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pest_meta" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" +dependencies = [ + "pest", + "sha2", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand 0.8.6", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -974,6 +1797,40 @@ dependencies = [ "time", ] +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "portable-pty" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4a596a2b3d2752d94f51fac2d4a96737b8705dddd311a32b9af47211f08671e" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "downcast-rs", + "filedescriptor 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "libc", + "log", + "nix 0.28.0", + "serial2", + "shared_library", + "shell-words", + "winapi", + "winreg", +] + [[package]] name = "potential_utf" version = "0.1.5" @@ -1008,6 +1865,16 @@ dependencies = [ "yansi", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -1026,13 +1893,32 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" +dependencies = [ + "quote", + "syn 2.0.117", +] + [[package]] name = "pulldown-cmark" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ - "bitflags", + "bitflags 2.13.0", "getopts", "memchr", "pulldown-cmark-escape", @@ -1045,6 +1931,27 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" +[[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.39.4" @@ -1061,7 +1968,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", - "cfg_aliases", + "cfg_aliases 0.2.1", "pin-project-lite", "quinn-proto", "quinn-udp", @@ -1083,7 +1990,7 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand", + "rand 0.9.4", "ring", "rustc-hash", "rustls", @@ -1101,7 +2008,7 @@ version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ - "cfg_aliases", + "cfg_aliases 0.2.1", "libc", "once_cell", "socket2", @@ -1124,6 +2031,21 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.9.4" @@ -1131,7 +2053,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.9.5", ] [[package]] @@ -1141,9 +2063,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.5", ] +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + [[package]] name = "rand_core" version = "0.9.5" @@ -1159,14 +2087,14 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" dependencies = [ - "bitflags", + "bitflags 2.13.0", "cassowary", "compact_str", "crossterm", "indoc", "instability", "itertools 0.13.0", - "lru", + "lru 0.12.5", "paste", "strum", "unicode-segmentation", @@ -1174,13 +2102,83 @@ dependencies = [ "unicode-width 0.2.0", ] +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.14.0", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.4", + "rand_chacha", + "simd_helpers", + "thiserror 2.0.18", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.13.0", ] [[package]] @@ -1259,6 +2257,12 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + [[package]] name = "ring" version = "0.17.14" @@ -1299,7 +2303,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn", + "syn 2.0.117", "unicode-ident", ] @@ -1324,7 +2328,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys", @@ -1426,7 +2430,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1465,6 +2469,44 @@ dependencies = [ "serde", ] +[[package]] +name = "serial2" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eb6ea5562eeaed6936b8b54e086aa0f88b9e5b1bef45beb038e2519fa1185b1" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shared_library" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" +dependencies = [ + "lazy_static", + "libc", +] + +[[package]] +name = "shell-words" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" + [[package]] name = "shlex" version = "2.0.1" @@ -1508,12 +2550,27 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "simdutf8" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + [[package]] name = "slab" version = "0.4.12" @@ -1573,7 +2630,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 2.0.117", ] [[package]] @@ -1582,6 +2639,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.117" @@ -1610,7 +2678,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1634,6 +2702,70 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "terminfo" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" +dependencies = [ + "fnv", + "nom 7.1.3", + "phf", + "phf_codegen", +] + +[[package]] +name = "termios" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" +dependencies = [ + "libc", +] + +[[package]] +name = "termwiz" +version = "0.24.0" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "anyhow", + "bitflags 2.13.0", + "fancy-regex", + "filedescriptor 0.8.3 (git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de)", + "finl_unicode", + "fixedbitset", + "image", + "libc", + "log", + "memmem", + "nix 0.29.0", + "num-derive", + "num-traits", + "ordered-float", + "pest", + "pest_derive", + "phf", + "sha2", + "signal-hook", + "siphasher", + "terminfo", + "termios", + "thiserror 1.0.69", + "ucd-trie", + "unicode-segmentation", + "vtparse", + "wezterm-bidi", + "wezterm-blob-leases", + "wezterm-cell", + "wezterm-char-props", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-escape-parser", + "wezterm-input-types", + "wezterm-surface", + "winapi", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -1660,7 +2792,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1671,7 +2803,21 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", +] + +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", ] [[package]] @@ -1755,7 +2901,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1833,7 +2979,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags", + "bitflags 2.13.0", "bytes", "futures-util", "http", @@ -1877,7 +3023,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1911,6 +3057,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "unicase" version = "2.9.0" @@ -1923,6 +3081,15 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.13.3" @@ -1952,6 +3119,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "untrusted" version = "0.9.0" @@ -1976,6 +3149,48 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7" +dependencies = [ + "getrandom 0.4.2", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vtparse" +version = "0.7.0" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "utf8parse", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -2007,7 +3222,16 @@ version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", ] [[package]] @@ -2052,7 +3276,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -2065,6 +3289,28 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -2078,6 +3324,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.13.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "web-sys" version = "0.3.100" @@ -2107,6 +3365,184 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "wezterm-bidi" +version = "0.2.3" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "log", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-blob-leases" +version = "0.1.1" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "getrandom 0.3.4", + "sha2", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "wezterm-cell" +version = "0.1.0" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "finl_unicode", + "image", + "log", + "ordered-float", + "serde", + "sha2", + "thiserror 1.0.69", + "wezterm-blob-leases", + "wezterm-char-props", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-escape-parser", +] + +[[package]] +name = "wezterm-char-props" +version = "0.1.3" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "phf", + "serde", + "ucd-trie", +] + +[[package]] +name = "wezterm-color-types" +version = "0.3.0" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "csscolorparser", + "deltae", + "num-traits", + "serde", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-dynamic" +version = "0.2.1" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "log", + "ordered-float", + "strsim", + "thiserror 2.0.18", + "wezterm-dynamic-derive", +] + +[[package]] +name = "wezterm-dynamic-derive" +version = "0.1.1" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wezterm-escape-parser" +version = "0.1.0" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "base64", + "bitflags 2.13.0", + "hex", + "image", + "log", + "nix 0.29.0", + "num-derive", + "num-traits", + "ordered-float", + "pest", + "pest_derive", + "sha2", + "thiserror 2.0.18", + "vtparse", + "wezterm-blob-leases", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-input-types", + "winapi", +] + +[[package]] +name = "wezterm-input-types" +version = "0.1.0" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "bitflags 1.3.2", + "euclid", + "serde", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-surface" +version = "0.1.0" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "bitflags 2.13.0", + "fancy-regex", + "finl_unicode", + "fixedbitset", + "ordered-float", + "siphasher", + "unicode-segmentation", + "wezterm-bidi", + "wezterm-cell", + "wezterm-char-props", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-escape-parser", + "wezterm-input-types", +] + +[[package]] +name = "wezterm-term" +version = "0.1.0" +source = "git+https://github.com/wezterm/wezterm?rev=891bed31b75f7a71b78e8f42ad07ae89bf99a7de#891bed31b75f7a71b78e8f42ad07ae89bf99a7de" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "csscolorparser", + "downcast-rs", + "finl_unicode", + "hex", + "humansize", + "image", + "lazy_static", + "log", + "lru 0.16.4", + "miniz_oxide 0.7.4", + "num-traits", + "ordered-float", + "serde", + "terminfo", + "termwiz", + "unicode-normalization", + "url", + "wezterm-bidi", + "wezterm-cell", + "wezterm-dynamic", + "wezterm-escape-parser", + "wezterm-surface", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2309,18 +3745,121 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.13.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "writeable" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + [[package]] name = "yaml-rust" version = "0.4.5" @@ -2355,7 +3894,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] @@ -2376,7 +3915,7 @@ checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2396,7 +3935,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] @@ -2436,7 +3975,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2444,3 +3983,27 @@ name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index 6cc23fb..7110791 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,11 @@ serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.150" tokio = { version = "1.52.3", features = ["full"] } tui-markdown = "=0.3.5" + +# Embedded terminal module (src/term.rs): wezterm's terminal model is not +# published on crates.io, so we pin a rev of the monorepo. portable-pty is +# from the same project. +portable-pty = "0.9" +wezterm-term = { git = "https://github.com/wezterm/wezterm", rev = "891bed31b75f7a71b78e8f42ad07ae89bf99a7de" } +wezterm-surface = { git = "https://github.com/wezterm/wezterm", rev = "891bed31b75f7a71b78e8f42ad07ae89bf99a7de" } +uuid = { version = "1", features = ["v4"] } diff --git a/src/app.rs b/src/app.rs index 7cf3bac..8417ebd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -20,6 +20,18 @@ pub struct App { pub filter_popup: Option, /// Whether the session list panel is expanded. pub show_sessions: bool, + /// Session UUID of the embedded `claude` pane (src/term.rs), so the tap + /// can recognise traffic belonging to it. + pub embed_session: Option, + /// True while the embedded session shows a large interactive prompt + /// (AskUserQuestion/ExitPlanMode seen in the stream, answer not yet + /// echoed back) — the UI gives the pane more rows while set. + pub embed_grow: bool, +} + +/// Client-side tools that render a large interactive UI in Claude Code. +fn is_interactive_tool(name: &str) -> bool { + matches!(name, "AskUserQuestion" | "ExitPlanMode") } impl App { @@ -33,6 +45,8 @@ impl App { filters: [true; FILTER_LABELS.len()], filter_popup: None, show_sessions: true, + embed_session: None, + embed_grow: false, } } } @@ -96,6 +110,10 @@ pub fn attach_tool_results(app: &SharedApp, key: &str, body: &Value) { return; }; let mut a = app.lock().unwrap(); + let is_embed = a.embed_session.as_deref() == Some(key); + // Set when the answer to an interactive prompt comes back: the embedded + // pane's prompt is gone, so the extra rows can be released. + let mut answered = false; let Some(s) = a.sessions.iter_mut().find(|s| s.key == key) else { return; }; @@ -114,6 +132,9 @@ pub fn attach_tool_results(app: &SharedApp, key: &str, body: &Value) { continue; }; if let Some(e) = s.entries.get_mut(idx) { + if let Kind::Tool { name } = &e.kind { + answered |= is_interactive_tool(name); + } e.result = Some(ToolResult { content: flatten_result_content(b.get("content")), is_error: b.get("is_error").and_then(Value::as_bool).unwrap_or(false), @@ -121,6 +142,9 @@ pub fn attach_tool_results(app: &SharedApp, key: &str, body: &Value) { } } } + if is_embed && answered { + a.embed_grow = false; + } } /// tool_result content is either a plain string or an array of content blocks. @@ -180,6 +204,9 @@ impl Tap { pub fn handle(&mut self, ev: &str, d: &Value) { let mut a = self.app.lock().unwrap(); + // Set when a completed block means the embedded pane is about to show + // a big interactive prompt (checked against embed_session below). + let mut interactive = false; let s = &mut a.sessions[self.sidx]; s.last_activity = Instant::now(); match ev { @@ -256,7 +283,8 @@ impl Tap { let e = &mut s.entries[i]; e.done = true; // Tool input arrives as JSON fragments; pretty-print once complete. - if matches!(e.kind, Kind::Tool { .. }) { + if let Kind::Tool { name } = &e.kind { + interactive = is_interactive_tool(name); if let Ok(v) = serde_json::from_str::(&e.content) { if let Ok(p) = serde_json::to_string_pretty(&v) { e.content = p; @@ -291,6 +319,14 @@ impl Tap { } _ => {} } + // The embedded pane is about to render an interactive prompt + // (wire-order guarantees this fires before Claude Code draws it): + // ask the UI for more rows. + if interactive + && a.embed_session.as_deref() == Some(a.sessions[self.sidx].key.as_str()) + { + a.embed_grow = true; + } } } @@ -353,6 +389,44 @@ mod tests { assert!(a.sessions[0].tool_ids.is_empty(), "id consumed"); } + #[test] + fn interactive_tool_toggles_embed_grow() { + let app: SharedApp = Arc::new(Mutex::new(App::new())); + app.lock().unwrap().embed_session = Some("emb".into()); + let mut tap = Tap::new(app.clone(), "emb".into(), "claude-x".into()); + tap.handle( + "content_block_start", + &json!({"content_block": {"type": "tool_use", "id": "toolu_q", "name": "AskUserQuestion"}}), + ); + assert!(!app.lock().unwrap().embed_grow, "not before the block completes"); + tap.handle("content_block_stop", &json!({})); + assert!(app.lock().unwrap().embed_grow, "grow once the prompt is imminent"); + drop(tap); + + // The user's answer comes back in the next request body → shrink. + attach_tool_results( + &app, + "emb", + &json!({"messages": [{"role": "user", "content": [ + {"type": "tool_result", "tool_use_id": "toolu_q", "content": "picked A"} + ]}]}), + ); + assert!(!app.lock().unwrap().embed_grow); + } + + #[test] + fn non_embed_session_never_grows() { + let app: SharedApp = Arc::new(Mutex::new(App::new())); + app.lock().unwrap().embed_session = Some("emb".into()); + let mut tap = Tap::new(app.clone(), "other".into(), "claude-x".into()); + tap.handle( + "content_block_start", + &json!({"content_block": {"type": "tool_use", "id": "toolu_q", "name": "AskUserQuestion"}}), + ); + tap.handle("content_block_stop", &json!({})); + assert!(!app.lock().unwrap().embed_grow); + } + #[test] fn unknown_tool_id_is_ignored() { let app: SharedApp = Arc::new(Mutex::new(App::new())); diff --git a/src/main.rs b/src/main.rs index c3490fa..defb019 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod app; mod proxy; mod sse; +mod term; mod ui; use app::App; @@ -31,7 +32,7 @@ fn main() -> anyhow::Result<()> { rt.block_on(proxy_handle)?; Ok(()) } else { - let r = ui::run(app); + let r = ui::run(app, port); rt.shutdown_background(); r } diff --git a/src/term.rs b/src/term.rs new file mode 100644 index 0000000..0ac483e --- /dev/null +++ b/src/term.rs @@ -0,0 +1,276 @@ +//! Embedded terminal module: runs `claude` inside a PTY and renders it as a +//! pane in our TUI. Self-contained — all portable-pty / wezterm-term usage +//! lives here so the feature can be toggled (or removed) without touching the +//! proxy/tap pipeline. +//! +//! Data flow: a reader thread pumps PTY output into `wezterm_term::Terminal` +//! (a full terminal model that also *answers* terminal queries by writing back +//! through the PTY writer — important for Ink-based Claude Code). The UI +//! thread locks the model each frame to paint cells, and forwards keystrokes +//! via `key_down`, which encodes them respecting whatever modes the child has +//! configured (application cursor keys, kitty keyboard, bracketed paste…). + +use anyhow::Context; +use portable_pty::{native_pty_system, ChildKiller, CommandBuilder, MasterPty, PtySize}; +use ratatui::buffer::Buffer; +use ratatui::layout::Rect; +use ratatui::style::{Color, Modifier}; +use std::io::Read; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, Mutex}; +use wezterm_surface::CursorVisibility; +use wezterm_term::color::{ColorAttribute, ColorPalette}; +use wezterm_term::{ + Intensity, KeyCode, KeyModifiers, Terminal, TerminalConfiguration, TerminalSize, Underline, +}; + +#[derive(Debug)] +struct Config; + +impl TerminalConfiguration for Config { + fn color_palette(&self) -> ColorPalette { + ColorPalette::default() + } + + // Claude Code can use the kitty keyboard protocol (shift+enter etc.); + // wezterm-term implements the encoding, so let the child enable it. + fn enable_kitty_keyboard(&self) -> bool { + true + } +} + +pub struct EmbeddedTerm { + term: Arc>, + master: Box, + killer: Box, + exited: Arc, + /// Session UUID passed to `claude --session-id`; lets the tap recognise + /// which proxied session belongs to this pane. + pub session_id: String, + rows: u16, + cols: u16, +} + +impl EmbeddedTerm { + /// Spawn `claude` in a fresh PTY, routed through our proxy. + pub fn spawn(port: u16, rows: u16, cols: u16) -> anyhow::Result { + let session_id = uuid::Uuid::new_v4().to_string(); + let mut cmd = CommandBuilder::new("claude"); + cmd.args(["--session-id", &session_id]); + cmd.env("ANTHROPIC_BASE_URL", format!("http://127.0.0.1:{port}")); + if let Ok(cwd) = std::env::current_dir() { + cmd.cwd(cwd); + } + Self::spawn_cmd(cmd, session_id, rows, cols) + } + + fn spawn_cmd( + cmd: CommandBuilder, + session_id: String, + rows: u16, + cols: u16, + ) -> anyhow::Result { + let pty = native_pty_system() + .openpty(PtySize { rows, cols, pixel_width: 0, pixel_height: 0 }) + .context("openpty")?; + let child = pty.slave.spawn_command(cmd).context("spawn child")?; + let killer = child.clone_killer(); + drop(pty.slave); + + // The terminal model writes query responses (DSR/DA/XTGETTCAP…) and + // key encodings back to the child through this writer. + let writer = pty.master.take_writer().context("pty writer")?; + let term = Arc::new(Mutex::new(Terminal::new( + TerminalSize { + rows: rows as usize, + cols: cols as usize, + pixel_width: 0, + pixel_height: 0, + dpi: 0, + }, + Arc::new(Config), + "claude-thinking", + env!("CARGO_PKG_VERSION"), + writer, + ))); + + let exited = Arc::new(AtomicBool::new(false)); + let mut reader = pty.master.try_clone_reader().context("pty reader")?; + { + let term = term.clone(); + let exited = exited.clone(); + std::thread::spawn(move || { + let mut child = child; + let mut buf = [0u8; 8192]; + loop { + match reader.read(&mut buf) { + Ok(0) | Err(_) => break, + Ok(n) => term.lock().unwrap().advance_bytes(&buf[..n]), + } + } + let _ = child.wait(); + exited.store(true, Ordering::Relaxed); + }); + } + + Ok(Self { term, master: pty.master, killer, exited, session_id, rows, cols }) + } + + pub fn exited(&self) -> bool { + self.exited.load(Ordering::Relaxed) + } + + /// Resize PTY + terminal model to the pane's inner size (no-op if unchanged). + pub fn resize(&mut self, rows: u16, cols: u16) { + if (rows, cols) == (self.rows, self.cols) || rows == 0 || cols == 0 { + return; + } + self.rows = rows; + self.cols = cols; + let _ = self.master.resize(PtySize { rows, cols, pixel_width: 0, pixel_height: 0 }); + self.term.lock().unwrap().resize(TerminalSize { + rows: rows as usize, + cols: cols as usize, + pixel_width: 0, + pixel_height: 0, + dpi: 0, + }); + } + + /// Forward a key press to the child. Returns false for keys we don't map. + pub fn key(&self, k: ratatui::crossterm::event::KeyEvent) -> bool { + use ratatui::crossterm::event::KeyCode as CK; + use ratatui::crossterm::event::KeyModifiers as CM; + let key = match k.code { + CK::Char(c) => KeyCode::Char(c), + CK::Enter => KeyCode::Enter, + CK::Backspace => KeyCode::Backspace, + CK::Tab => KeyCode::Tab, + CK::BackTab => KeyCode::Tab, // SHIFT carried via modifiers + CK::Esc => KeyCode::Escape, + CK::Left => KeyCode::LeftArrow, + CK::Right => KeyCode::RightArrow, + CK::Up => KeyCode::UpArrow, + CK::Down => KeyCode::DownArrow, + CK::Home => KeyCode::Home, + CK::End => KeyCode::End, + CK::PageUp => KeyCode::PageUp, + CK::PageDown => KeyCode::PageDown, + CK::Delete => KeyCode::Delete, + CK::Insert => KeyCode::Insert, + CK::F(n) => KeyCode::Function(n), + _ => return false, + }; + let mut mods = KeyModifiers::NONE; + if k.modifiers.contains(CM::SHIFT) || k.code == CK::BackTab { + mods |= KeyModifiers::SHIFT; + } + if k.modifiers.contains(CM::CONTROL) { + mods |= KeyModifiers::CTRL; + } + if k.modifiers.contains(CM::ALT) { + mods |= KeyModifiers::ALT; + } + self.term.lock().unwrap().key_down(key, mods).is_ok() + } + + /// Paint the visible screen into `area`. Returns the cursor position + /// (absolute buffer coordinates) when the child wants it shown. + pub fn render(&self, area: Rect, buf: &mut Buffer) -> Option<(u16, u16)> { + let term = self.term.lock().unwrap(); + let screen = term.screen(); + let first = screen.phys_row(0); + let lines = screen.lines_in_phys_range(first..first + screen.physical_rows); + for (y, line) in lines.iter().enumerate() { + if y as u16 >= area.height { + break; + } + for cell in line.visible_cells() { + let x = cell.cell_index() as u16; + if x >= area.width { + break; + } + let attrs = cell.attrs(); + let dst = &mut buf[(area.x + x, area.y + y as u16)]; + dst.set_symbol(cell.str()); + if let Some(c) = conv_color(attrs.foreground()) { + dst.set_fg(c); + } + if let Some(c) = conv_color(attrs.background()) { + dst.set_bg(c); + } + let mut m = Modifier::empty(); + if attrs.intensity() == Intensity::Bold { + m |= Modifier::BOLD; + } + if attrs.intensity() == Intensity::Half { + m |= Modifier::DIM; + } + if attrs.italic() { + m |= Modifier::ITALIC; + } + if attrs.underline() != Underline::None { + m |= Modifier::UNDERLINED; + } + if attrs.reverse() { + m |= Modifier::REVERSED; + } + if attrs.strikethrough() { + m |= Modifier::CROSSED_OUT; + } + dst.set_style(ratatui::style::Style::new().add_modifier(m)); + } + } + let cursor = term.cursor_pos(); + (cursor.visibility == CursorVisibility::Visible + && (cursor.x as u16) < area.width + && (cursor.y as u16) < area.height) + .then(|| (area.x + cursor.x as u16, area.y + cursor.y as u16)) + } +} + +impl Drop for EmbeddedTerm { + fn drop(&mut self) { + let _ = self.killer.kill(); + } +} + +/// termwiz color → ratatui color. `Default` maps to None (keep pane default). +fn conv_color(c: ColorAttribute) -> Option { + match c { + ColorAttribute::Default => None, + ColorAttribute::PaletteIndex(i) => Some(Color::Indexed(i)), + ColorAttribute::TrueColorWithDefaultFallback(c) + | ColorAttribute::TrueColorWithPaletteFallback(c, _) => { + let (r, g, b, _) = c.to_srgb_u8(); + Some(Color::Rgb(r, g, b)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::time::{Duration, Instant}; + + /// Full pipeline: PTY spawn → reader thread → wezterm-term model → + /// ratatui buffer. Headless-safe: the *child* gets the tty, not us. + #[test] + fn pty_output_reaches_rendered_buffer() { + let mut cmd = CommandBuilder::new("sh"); + cmd.args(["-c", "printf 'hello-embed'; sleep 1"]); + let area = Rect::new(0, 0, 40, 5); + let et = EmbeddedTerm::spawn_cmd(cmd, "test-session".into(), 5, 40).unwrap(); + let deadline = Instant::now() + Duration::from_secs(5); + loop { + let mut buf = Buffer::empty(area); + et.render(area, &mut buf); + let row: String = (0..area.width).map(|x| buf[(x, 0)].symbol()).collect(); + if row.contains("hello-embed") { + break; + } + assert!(Instant::now() < deadline, "never rendered output: {row:?}"); + std::thread::sleep(Duration::from_millis(50)); + } + } +} diff --git a/src/ui.rs b/src/ui.rs index a983982..fc3c8b8 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,4 +1,5 @@ use crate::app::{filter_index, fmt_tokens, Kind, SharedApp, ToolResult, FILTER_LABELS}; +use crate::term::EmbeddedTerm; use ratatui::crossterm::event::{self, Event, KeyCode, KeyEventKind, KeyModifiers}; use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::style::{Color, Style, Stylize}; @@ -8,26 +9,104 @@ use ratatui::widgets::{Block, Clear, List, ListItem, ListState, Paragraph, Wrap} use ratatui::Frame; use std::time::Duration; -pub fn run(app: SharedApp) -> anyhow::Result<()> { +/// Embedded `claude` pane state (UI-thread only; the shared App carries just +/// the session id + grow flag so the proxy tap can talk to it). +struct EmbedUi { + term: Option, + visible: bool, + port: u16, +} + +impl EmbedUi { + /// Pane is visible and the child is still running → it owns plain keys. + fn focused(&self) -> bool { + self.visible && self.term.as_ref().is_some_and(|t| !t.exited()) + } +} + +pub fn run(app: SharedApp, port: u16) -> anyhow::Result<()> { let mut terminal = ratatui::init(); - let res = event_loop(&mut terminal, app); + let mut eui = EmbedUi { term: None, visible: false, port }; + let res = event_loop(&mut terminal, app, &mut eui); ratatui::restore(); res } -fn event_loop(terminal: &mut ratatui::DefaultTerminal, app: SharedApp) -> anyhow::Result<()> { +fn toggle_embed(eui: &mut EmbedUi, app: &SharedApp) { + if eui.visible { + eui.visible = false; + // A dead child is dropped on hide so the next toggle respawns. + if eui.term.as_ref().is_some_and(|t| t.exited()) { + eui.term = None; + app.lock().unwrap().embed_session = None; + } + return; + } + if eui.term.as_ref().is_some_and(|t| t.exited()) { + eui.term = None; + } + if eui.term.is_none() { + // Real dimensions are applied on the first draw via resize(). + match EmbeddedTerm::spawn(eui.port, 20, 80) { + Ok(t) => { + let mut a = app.lock().unwrap(); + a.embed_session = Some(t.session_id.clone()); + a.embed_grow = false; + drop(a); + eui.term = Some(t); + } + Err(e) => { + app.lock().unwrap().status = format!("claude spawn failed: {e}"); + return; + } + } + } + eui.visible = true; +} + +fn event_loop( + terminal: &mut ratatui::DefaultTerminal, + app: SharedApp, + eui: &mut EmbedUi, +) -> anyhow::Result<()> { loop { - terminal.draw(|f| draw(f, &app))?; + terminal.draw(|f| draw(f, &app, eui))?; if !event::poll(Duration::from_millis(33))? { continue; } if let Event::Key(k) = event::read()? { + if k.kind == KeyEventKind::Release { + continue; + } + // Alt-c toggles the embedded claude pane in every state. + if k.code == KeyCode::Char('c') && k.modifiers.contains(KeyModifiers::ALT) { + if k.kind == KeyEventKind::Press { + toggle_embed(eui, &app); + } + continue; + } + let embed_focused = eui.focused(); + // Modifier-split routing: while the pane is focused, plain keys + // (incl. ctrl-c!) belong to claude; ALT-keys control the feed. + // The filter popup is modal and keeps its plain keys. + if embed_focused + && !k.modifiers.contains(KeyModifiers::ALT) + && app.lock().unwrap().filter_popup.is_none() + { + if let Some(et) = &eui.term { + et.key(k); + } + continue; + } if k.kind != KeyEventKind::Press { continue; } let mut a = app.lock().unwrap(); let nsess = a.sessions.len(); - if k.code == KeyCode::Char('c') && k.modifiers.contains(KeyModifiers::CONTROL) { + if !embed_focused + && k.code == KeyCode::Char('c') + && k.modifiers.contains(KeyModifiers::CONTROL) + { return Ok(()); } // Filter popup captures input while open. @@ -50,11 +129,13 @@ fn event_loop(terminal: &mut ratatui::DefaultTerminal, app: SharedApp) -> anyhow KeyCode::Char('q') | KeyCode::Esc => return Ok(()), KeyCode::Char('f') => a.filter_popup = Some(0), KeyCode::Char('s') => a.show_sessions = !a.show_sessions, - KeyCode::Tab if nsess > 0 => { + // n/p mirror tab/backtab: alt-tab is usually grabbed by the + // window manager, so the embed-focused state needs them. + KeyCode::Tab | KeyCode::Char('n') if nsess > 0 => { a.selected = (a.selected + 1) % nsess; a.follow = true; } - KeyCode::BackTab if nsess > 0 => { + KeyCode::BackTab | KeyCode::Char('p') if nsess > 0 => { a.selected = (a.selected + nsess - 1) % nsess; a.follow = true; } @@ -85,10 +166,24 @@ fn event_loop(terminal: &mut ratatui::DefaultTerminal, app: SharedApp) -> anyhow } } -fn draw(f: &mut Frame, app: &SharedApp) { +fn draw(f: &mut Frame, app: &SharedApp, eui: &mut EmbedUi) { let mut a = app.lock().unwrap(); - let [main, footer] = Layout::vertical([Constraint::Min(1), Constraint::Length(1)]) - .areas(f.area()); + // Embedded pane height: nothing when hidden; ~35% of the screen normally, + // ~60% while the tap says an interactive prompt is on screen. + let show_embed = eui.visible && eui.term.is_some(); + let embed_h = if show_embed { + let total = f.area().height; + let pct = if a.embed_grow { 60 } else { 35 }; + ((total as u32 * pct / 100) as u16).clamp(10, total.saturating_sub(10)) + } else { + 0 + }; + let [main, embed_area, footer] = Layout::vertical([ + Constraint::Min(1), + Constraint::Length(embed_h), + Constraint::Length(1), + ]) + .areas(f.area()); let left_width = if a.show_sessions { 26 } else { 0 }; let [left, right] = Layout::horizontal([Constraint::Length(left_width), Constraint::Min(10)]) .areas(main); @@ -228,10 +323,40 @@ fn draw(f: &mut Frame, app: &SharedApp) { a.scroll = new_scroll; a.follow = new_follow; + // Embedded claude pane + if show_embed { + let et = eui.term.as_mut().unwrap(); + let exited = et.exited(); + let id: String = et.session_id.chars().take(8).collect(); + let title = if exited { + format!(" claude · {id} · exited ") + } else { + format!(" claude · {id} ") + }; + let block = Block::bordered().title(title); + let inner = block.inner(embed_area); + f.render_widget(block, embed_area); + if exited { + f.render_widget( + Paragraph::new("\n claude exited — alt-c to close this pane") + .dark_gray(), + inner, + ); + } else { + et.resize(inner.height, inner.width); + if let Some(pos) = et.render(inner, f.buffer_mut()) { + f.set_cursor_position(pos); + } + } + } + + let embed_focused = eui.focused(); let keys = if a.filter_popup.is_some() { "space toggle · j/k move · f/esc close" + } else if embed_focused { + "alt-c hide claude · alt-q quit · alt-j/k scroll · alt-f filter · alt-n/p session" } else { - "q quit · tab session · s sessions · j/k scroll · f filter · g top · G bottom" + "q quit · tab session · s sessions · j/k scroll · f filter · g top · G bottom · alt-c claude" }; f.render_widget( Paragraph::new(Line::from(format!(" {} | {keys}", a.status)).dark_gray()),