rtrt-agent 0.1.7 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +203 -15
- package/README.md +211 -15
- package/THIRD_PARTY_NOTICES/INDEX.md +120 -18
- package/THIRD_PARTY_NOTICES/INVENTORY.json +8151 -0
- package/THIRD_PARTY_NOTICES/SUPPLEMENTS.json +148 -0
- package/THIRD_PARTY_NOTICES/adler2@2.0.1/LICENSE-0BSD +12 -0
- package/THIRD_PARTY_NOTICES/adler2@2.0.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/adler2@2.0.1/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/ahash@0.8.12/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/ahash@0.8.12/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/aho-corasick@1.1.4/COPYING +3 -0
- package/THIRD_PARTY_NOTICES/aho-corasick@1.1.4/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/allocator-api2@0.2.21/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/allocator-api2@0.2.21/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/anstream@1.0.0/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/anstream@1.0.0/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/anstyle-parse@1.0.0/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/anstyle-parse@1.0.0/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/anstyle-query@1.1.5/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/anstyle-query@1.1.5/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/anstyle-wincon@3.0.11/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/anstyle-wincon@3.0.11/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/anstyle@1.0.14/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/anstyle@1.0.14/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/anyhow@1.0.103/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/anyhow@1.0.103/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/async-compression@0.4.42/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/async-compression@0.4.42/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/async-trait@0.1.92/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/async-trait@0.1.92/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/atomic-waker@1.1.2/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/atomic-waker@1.1.2/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/atomic-waker@1.1.2/LICENSE-THIRD-PARTY +45 -0
- package/THIRD_PARTY_NOTICES/autocfg@1.5.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/autocfg@1.5.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/axum-core@0.5.6/LICENSE +27 -0
- package/THIRD_PARTY_NOTICES/axum-macros@0.5.1/LICENSE +7 -0
- package/THIRD_PARTY_NOTICES/axum@0.8.9/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/base64@0.22.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/base64@0.22.1/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/bitflags@2.11.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/bitflags@2.11.1/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/block-buffer@0.10.4/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/block-buffer@0.10.4/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/bytes@1.11.1/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/cc@1.2.62/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/cc@1.2.62/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/cfg-if@1.0.4/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/cfg-if@1.0.4/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/chacha20@0.10.2/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/chacha20@0.10.2/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/chrono@0.4.44/LICENSE.txt +240 -0
- package/THIRD_PARTY_NOTICES/clap@4.6.1/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/clap@4.6.1/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/clap_builder@4.6.0/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/clap_builder@4.6.0/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/clap_derive@4.6.1/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/clap_derive@4.6.1/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/clap_lex@1.1.0/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/clap_lex@1.1.0/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/colorchoice@1.0.5/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/colorchoice@1.0.5/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/compression-codecs@0.4.38/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/compression-codecs@0.4.38/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/compression-core@0.4.32/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/compression-core@0.4.32/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/cpufeatures@0.2.17/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/cpufeatures@0.2.17/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/cpufeatures@0.3.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/cpufeatures@0.3.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/crc32fast@1.5.0/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/crc32fast@1.5.0/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/crossbeam-deque@0.8.6/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/crossbeam-deque@0.8.6/LICENSE-MIT +27 -0
- package/THIRD_PARTY_NOTICES/crossbeam-epoch@0.9.20/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/crossbeam-epoch@0.9.20/LICENSE-MIT +27 -0
- package/THIRD_PARTY_NOTICES/crossbeam-utils@0.8.21/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/crossbeam-utils@0.8.21/LICENSE-MIT +27 -0
- package/THIRD_PARTY_NOTICES/crypto-common@0.1.7/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/crypto-common@0.1.7/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/darling@0.20.11/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/darling@0.23.0/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/darling_core@0.20.11/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/darling_core@0.23.0/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/darling_macro@0.20.11/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/darling_macro@0.23.0/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/derive_builder@0.20.2/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/derive_builder@0.20.2/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/derive_builder_core@0.20.2/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/derive_builder_core@0.20.2/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/derive_builder_macro@0.20.2/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/derive_builder_macro@0.20.2/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/digest@0.10.7/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/digest@0.10.7/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/dirs-sys@0.4.1/LICENSE-APACHE +174 -0
- package/THIRD_PARTY_NOTICES/dirs-sys@0.4.1/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/dirs@5.0.1/LICENSE-APACHE +174 -0
- package/THIRD_PARTY_NOTICES/dirs@5.0.1/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/displaydoc@0.2.5/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/displaydoc@0.2.5/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/dyn-clone@1.0.20/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/dyn-clone@1.0.20/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/either@1.16.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/either@1.16.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/equivalent@1.0.2/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/equivalent@1.0.2/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/errno@0.3.14/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/errno@0.3.14/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/eventsource-stream@0.2.3/Cargo.toml +74 -0
- package/THIRD_PARTY_NOTICES/eventsource-stream@0.2.3/DECLARED-APACHE-2.0.txt +202 -0
- package/THIRD_PARTY_NOTICES/fallible-iterator@0.3.0/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/fallible-iterator@0.3.0/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/fallible-streaming-iterator@0.1.9/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/fallible-streaming-iterator@0.1.9/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/fastrand@2.4.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/fastrand@2.4.1/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/find-msvc-tools@0.1.9/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/find-msvc-tools@0.1.9/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/flate2@1.1.9/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/flate2@1.1.9/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/fnv@1.0.7/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/fnv@1.0.7/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/form_urlencoded@1.2.2/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/form_urlencoded@1.2.2/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/fs2@0.4.3/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/fs2@0.4.3/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/futures-channel@0.3.32/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/futures-channel@0.3.32/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/futures-core@0.3.32/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/futures-core@0.3.32/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/futures-executor@0.3.32/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/futures-executor@0.3.32/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/futures-io@0.3.32/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/futures-io@0.3.32/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/futures-macro@0.3.32/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/futures-macro@0.3.32/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/futures-sink@0.3.32/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/futures-sink@0.3.32/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/futures-task@0.3.32/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/futures-task@0.3.32/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/futures-util@0.3.32/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/futures-util@0.3.32/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/futures@0.3.32/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/futures@0.3.32/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/generic-array@0.14.7/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/getrandom@0.2.17/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/getrandom@0.2.17/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/getrandom@0.3.4/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/getrandom@0.3.4/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/getrandom@0.4.2/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/getrandom@0.4.2/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/handlebars@6.4.1/LICENSE +22 -0
- package/THIRD_PARTY_NOTICES/handlebars@6.4.1/wasm/LICENSE +22 -0
- package/THIRD_PARTY_NOTICES/hashbrown@0.14.5/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/hashbrown@0.14.5/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/hashbrown@0.17.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/hashbrown@0.17.1/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/hashlink@0.9.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/hashlink@0.9.1/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/heck@0.5.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/heck@0.5.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/hmac@0.12.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/hmac@0.12.1/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/http-body-util@0.1.3/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/http-body@1.0.1/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/http-range-header@0.4.2/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/http@1.4.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/http@1.4.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/httparse@1.10.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/httparse@1.10.1/LICENSE-MIT +20 -0
- package/THIRD_PARTY_NOTICES/httpdate@1.0.3/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/httpdate@1.0.3/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/hyper-rustls@0.27.9/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/hyper-rustls@0.27.9/LICENSE-ISC +15 -0
- package/THIRD_PARTY_NOTICES/hyper-rustls@0.27.9/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/hyper-util@0.1.20/LICENSE +19 -0
- package/THIRD_PARTY_NOTICES/hyper@1.9.0/LICENSE +19 -0
- package/THIRD_PARTY_NOTICES/icu_collections@2.1.1/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/icu_locale_core@2.1.1/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/icu_normalizer@2.1.1/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/icu_normalizer_data@2.1.1/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/icu_properties@2.1.2/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/icu_properties_data@2.1.2/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/icu_provider@2.1.1/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/ident_case@1.0.1/LICENSE +19 -0
- package/THIRD_PARTY_NOTICES/idna@1.1.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/idna@1.1.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/idna_adapter@1.2.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/idna_adapter@1.2.1/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/indexmap@2.14.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/indexmap@2.14.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/instant-distance@0.6.1/Cargo.toml +65 -0
- package/THIRD_PARTY_NOTICES/instant-distance@0.6.1/LICENSE +201 -0
- package/THIRD_PARTY_NOTICES/ipnet@2.12.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/ipnet@2.12.0/LICENSE-MIT +7 -0
- package/THIRD_PARTY_NOTICES/is_terminal_polyfill@1.70.2/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/is_terminal_polyfill@1.70.2/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/itoa@1.0.18/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/itoa@1.0.18/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/layout-base@2.0.1/JamaJS-APACHE.txt +210 -0
- package/THIRD_PARTY_NOTICES/lazy_static@1.5.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/lazy_static@1.5.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/libc@0.2.186/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/libc@0.2.186/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/libsqlite3-sys@0.30.1/LICENSE +19 -0
- package/THIRD_PARTY_NOTICES/libsqlite3-sys@0.30.1/sqlcipher/LICENSE +24 -0
- package/THIRD_PARTY_NOTICES/linux-raw-sys@0.12.1/COPYRIGHT +29 -0
- package/THIRD_PARTY_NOTICES/linux-raw-sys@0.12.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/linux-raw-sys@0.12.1/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
- package/THIRD_PARTY_NOTICES/linux-raw-sys@0.12.1/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/litemap@0.8.2/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/lock_api@0.4.14/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/lock_api@0.4.14/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/log@0.4.29/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/log@0.4.29/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/matchers@0.2.0/LICENSE +19 -0
- package/THIRD_PARTY_NOTICES/matchit@0.8.4/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/matchit@0.8.4/LICENSE.httprouter +29 -0
- package/THIRD_PARTY_NOTICES/memchr@2.8.0/COPYING +3 -0
- package/THIRD_PARTY_NOTICES/memchr@2.8.0/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/mime@0.3.17/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/mime@0.3.17/LICENSE-MIT +20 -0
- package/THIRD_PARTY_NOTICES/mime_guess@2.0.5/LICENSE +22 -0
- package/THIRD_PARTY_NOTICES/minimal-lexical@0.2.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/minimal-lexical@0.2.1/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/minimal-lexical@0.2.1/LICENSE.md +37 -0
- package/THIRD_PARTY_NOTICES/miniz_oxide@0.8.9/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/miniz_oxide@0.8.9/LICENSE-APACHE.md +177 -0
- package/THIRD_PARTY_NOTICES/miniz_oxide@0.8.9/LICENSE-MIT.md +24 -0
- package/THIRD_PARTY_NOTICES/miniz_oxide@0.8.9/LICENSE-ZLIB.md +14 -0
- package/THIRD_PARTY_NOTICES/mio@1.2.0/LICENSE +19 -0
- package/THIRD_PARTY_NOTICES/nom@7.1.3/LICENSE +20 -0
- package/THIRD_PARTY_NOTICES/nu-ansi-term@0.50.3/LICENSE +22 -0
- package/THIRD_PARTY_NOTICES/num-modular@0.6.1/LICENSE +201 -0
- package/THIRD_PARTY_NOTICES/num-order@1.2.0/LICENSE +201 -0
- package/THIRD_PARTY_NOTICES/num-traits@0.2.19/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/num-traits@0.2.19/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/num_cpus@1.17.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/num_cpus@1.17.0/LICENSE-MIT +20 -0
- package/THIRD_PARTY_NOTICES/once_cell@1.21.4/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/once_cell@1.21.4/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/once_cell_polyfill@1.70.2/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/once_cell_polyfill@1.70.2/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/option-ext@0.2.0/SOURCE.crate +0 -0
- package/THIRD_PARTY_NOTICES/ordered-float@3.9.2/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/parking_lot@0.12.5/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/parking_lot@0.12.5/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/parking_lot_core@0.9.12/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/parking_lot_core@0.9.12/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/pastey@0.2.3/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/pastey@0.2.3/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/percent-encoding@2.3.2/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/percent-encoding@2.3.2/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/pest@2.8.6/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/pest@2.8.6/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/pest_derive@2.8.6/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/pest_derive@2.8.6/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/pest_generator@2.8.6/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/pest_generator@2.8.6/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/pest_meta@2.8.6/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/pest_meta@2.8.6/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/pin-project-lite@0.2.17/LICENSE-APACHE +177 -0
- package/THIRD_PARTY_NOTICES/pin-project-lite@0.2.17/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/pkg-config@0.3.33/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/pkg-config@0.3.33/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/potential_utf@0.1.5/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/ppv-lite86@0.2.21/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/ppv-lite86@0.2.21/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/proc-macro2@1.0.106/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/proc-macro2@1.0.106/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/quote@1.0.45/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/quote@1.0.45/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/rand@0.10.1/COPYRIGHT +12 -0
- package/THIRD_PARTY_NOTICES/rand@0.10.1/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/rand@0.10.1/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/rand@0.8.6/COPYRIGHT +12 -0
- package/THIRD_PARTY_NOTICES/rand@0.8.6/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/rand@0.8.6/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/rand_chacha@0.3.1/COPYRIGHT +12 -0
- package/THIRD_PARTY_NOTICES/rand_chacha@0.3.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/rand_chacha@0.3.1/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/rand_core@0.10.1/COPYRIGHT +9 -0
- package/THIRD_PARTY_NOTICES/rand_core@0.10.1/LICENSE-APACHE +187 -0
- package/THIRD_PARTY_NOTICES/rand_core@0.10.1/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/rand_core@0.6.4/COPYRIGHT +12 -0
- package/THIRD_PARTY_NOTICES/rand_core@0.6.4/LICENSE-APACHE +187 -0
- package/THIRD_PARTY_NOTICES/rand_core@0.6.4/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/rayon-core@1.13.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/rayon-core@1.13.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/rayon@1.12.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/rayon@1.12.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/ref-cast-impl@1.0.25/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/ref-cast-impl@1.0.25/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/ref-cast@1.0.25/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/ref-cast@1.0.25/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/regex-automata@0.4.14/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/regex-automata@0.4.14/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/regex-syntax@0.8.10/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/regex-syntax@0.8.10/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/regex-syntax@0.8.10/src/unicode_tables/LICENSE-UNICODE +57 -0
- package/THIRD_PARTY_NOTICES/regex@1.12.3/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/regex@1.12.3/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/reqwest@0.12.28/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/reqwest@0.12.28/LICENSE-MIT +20 -0
- package/THIRD_PARTY_NOTICES/rmcp-macros@1.7.0/Cargo.toml +54 -0
- package/THIRD_PARTY_NOTICES/rmcp-macros@1.7.0/LICENSE +216 -0
- package/THIRD_PARTY_NOTICES/rmcp@1.7.0/Cargo.toml +683 -0
- package/THIRD_PARTY_NOTICES/rmcp@1.7.0/LICENSE +216 -0
- package/THIRD_PARTY_NOTICES/rusqlite@0.32.1/LICENSE +19 -0
- package/THIRD_PARTY_NOTICES/rustix@1.1.4/COPYRIGHT +29 -0
- package/THIRD_PARTY_NOTICES/rustix@1.1.4/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/rustix@1.1.4/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
- package/THIRD_PARTY_NOTICES/rustix@1.1.4/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/rustls-pki-types@1.14.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/rustls-pki-types@1.14.1/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/rustls-webpki@0.103.15/LICENSE +19 -0
- package/THIRD_PARTY_NOTICES/rustls@0.23.45/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/rustls@0.23.45/LICENSE-ISC +15 -0
- package/THIRD_PARTY_NOTICES/rustls@0.23.45/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/ryu@1.0.23/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/ryu@1.0.23/LICENSE-BOOST +23 -0
- package/THIRD_PARTY_NOTICES/same-file@1.0.6/COPYING +3 -0
- package/THIRD_PARTY_NOTICES/same-file@1.0.6/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/schemars@0.8.22/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/schemars@1.2.1/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/schemars_derive@0.8.22/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/schemars_derive@1.2.1/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/scopeguard@1.2.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/scopeguard@1.2.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/serde@1.0.228/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/serde@1.0.228/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/serde_core@1.0.228/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/serde_core@1.0.228/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/serde_derive@1.0.228/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/serde_derive@1.0.228/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/serde_derive_internals@0.29.1/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/serde_derive_internals@0.29.1/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/serde_json@1.0.149/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/serde_json@1.0.149/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/serde_path_to_error@0.1.20/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/serde_path_to_error@0.1.20/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/serde_spanned@0.6.9/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/serde_spanned@0.6.9/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/serde_urlencoded@0.7.1/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/serde_urlencoded@0.7.1/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/sha2@0.10.9/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/sha2@0.10.9/LICENSE-MIT +27 -0
- package/THIRD_PARTY_NOTICES/sharded-slab@0.1.7/LICENSE +19 -0
- package/THIRD_PARTY_NOTICES/shlex@1.3.0/LICENSE-APACHE +13 -0
- package/THIRD_PARTY_NOTICES/shlex@1.3.0/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/signal-hook-registry@1.4.8/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/signal-hook-registry@1.4.8/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/simd-adler32@0.3.9/LICENSE.md +21 -0
- package/THIRD_PARTY_NOTICES/slab@0.4.12/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/smallvec@1.15.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/smallvec@1.15.1/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/socket2@0.6.3/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/socket2@0.6.3/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/sse-stream@0.2.3/Cargo.toml +124 -0
- package/THIRD_PARTY_NOTICES/sse-stream@0.2.3/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/sse-stream@0.2.3/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/stable_deref_trait@1.2.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/stable_deref_trait@1.2.1/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/streaming-iterator@0.1.9/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/streaming-iterator@0.1.9/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/strsim@0.11.1/LICENSE +23 -0
- package/THIRD_PARTY_NOTICES/syn@2.0.117/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/syn@2.0.117/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/syn@3.0.6/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/syn@3.0.6/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/sync_wrapper@1.0.2/LICENSE +177 -0
- package/THIRD_PARTY_NOTICES/synstructure@0.13.2/LICENSE +7 -0
- package/THIRD_PARTY_NOTICES/tempfile@3.27.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/tempfile@3.27.0/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/thiserror-impl@2.0.18/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/thiserror-impl@2.0.18/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/thiserror@2.0.18/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/thiserror@2.0.18/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/thread_local@1.1.9/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/thread_local@1.1.9/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/tinystr@0.8.3/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/tokio-macros@2.7.0/LICENSE +22 -0
- package/THIRD_PARTY_NOTICES/tokio-rustls@0.26.4/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/tokio-rustls@0.26.4/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/tokio-stream@0.1.18/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/tokio-util@0.7.18/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/tokio@1.52.3/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/toml@0.8.23/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/toml@0.8.23/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/toml_datetime@0.6.11/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/toml_datetime@0.6.11/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/toml_edit@0.22.27/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/toml_edit@0.22.27/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/toml_write@0.1.2/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/toml_write@0.1.2/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/tower-http@0.6.11/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/tower-layer@0.3.3/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/tower-service@0.3.3/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/tower@0.5.3/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/tracing-attributes@0.1.31/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/tracing-core@0.1.36/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/tracing-core@0.1.36/src/spin/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/tracing-log@0.2.0/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/tracing-subscriber@0.3.23/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/tracing@0.1.44/LICENSE +25 -0
- package/THIRD_PARTY_NOTICES/tree-sitter-language@0.1.7/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/tree-sitter-python@0.23.6/Cargo.toml +60 -0
- package/THIRD_PARTY_NOTICES/tree-sitter-python@0.23.6/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/tree-sitter-rust@0.24.2/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/tree-sitter-typescript@0.23.2/Cargo.toml +62 -0
- package/THIRD_PARTY_NOTICES/tree-sitter-typescript@0.23.2/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/tree-sitter@0.26.9/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/tree-sitter@0.26.9/src/unicode/LICENSE +414 -0
- package/THIRD_PARTY_NOTICES/try-lock@0.2.5/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES/typenum@1.20.0/LICENSE +1 -0
- package/THIRD_PARTY_NOTICES/typenum@1.20.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/typenum@1.20.0/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/ucd-trie@0.1.7/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/ucd-trie@0.1.7/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/unicase@2.9.0/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/unicase@2.9.0/LICENSE-MIT +20 -0
- package/THIRD_PARTY_NOTICES/unicode-ident@1.0.24/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/unicode-ident@1.0.24/LICENSE-MIT +23 -0
- package/THIRD_PARTY_NOTICES/unicode-ident@1.0.24/LICENSE-UNICODE +39 -0
- package/THIRD_PARTY_NOTICES/untrusted@0.9.0/LICENSE.txt +13 -0
- package/THIRD_PARTY_NOTICES/ureq@2.12.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/ureq@2.12.1/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/ureq@2.12.1/src/chunked/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/ureq@2.12.1/src/chunked/LICENSE-MIT +22 -0
- package/THIRD_PARTY_NOTICES/url@2.5.8/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/url@2.5.8/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/utf8_iter@1.0.4/COPYRIGHT +42 -0
- package/THIRD_PARTY_NOTICES/utf8_iter@1.0.4/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/utf8_iter@1.0.4/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/utf8parse@0.2.2/LICENSE-APACHE +176 -0
- package/THIRD_PARTY_NOTICES/utf8parse@0.2.2/LICENSE-MIT +25 -0
- package/THIRD_PARTY_NOTICES/uuid@1.23.1/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/uuid@1.23.1/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/vcpkg@0.2.15/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/vcpkg@0.2.15/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/version_check@0.9.5/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/version_check@0.9.5/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/walkdir@2.5.0/COPYING +3 -0
- package/THIRD_PARTY_NOTICES/walkdir@2.5.0/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/want@0.3.1/LICENSE +20 -0
- package/THIRD_PARTY_NOTICES/whatlang@0.16.4/Cargo.toml +76 -0
- package/THIRD_PARTY_NOTICES/whatlang@0.16.4/LICENSE +26 -0
- package/THIRD_PARTY_NOTICES/winapi-util@0.1.11/COPYING +3 -0
- package/THIRD_PARTY_NOTICES/winapi-util@0.1.11/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/winapi@0.3.9/LICENSE-APACHE +201 -0
- package/THIRD_PARTY_NOTICES/winapi@0.3.9/LICENSE-MIT +19 -0
- package/THIRD_PARTY_NOTICES/windows-link@0.2.1/license-apache-2.0 +201 -0
- package/THIRD_PARTY_NOTICES/windows-link@0.2.1/license-mit +21 -0
- package/THIRD_PARTY_NOTICES/windows-sys@0.48.0/license-apache-2.0 +201 -0
- package/THIRD_PARTY_NOTICES/windows-sys@0.48.0/license-mit +21 -0
- package/THIRD_PARTY_NOTICES/windows-sys@0.61.2/license-apache-2.0 +201 -0
- package/THIRD_PARTY_NOTICES/windows-sys@0.61.2/license-mit +21 -0
- package/THIRD_PARTY_NOTICES/windows-targets@0.48.5/license-apache-2.0 +201 -0
- package/THIRD_PARTY_NOTICES/windows-targets@0.48.5/license-mit +21 -0
- package/THIRD_PARTY_NOTICES/windows_x86_64_msvc@0.48.5/license-apache-2.0 +201 -0
- package/THIRD_PARTY_NOTICES/windows_x86_64_msvc@0.48.5/license-mit +21 -0
- package/THIRD_PARTY_NOTICES/winnow@0.7.15/LICENSE-MIT +18 -0
- package/THIRD_PARTY_NOTICES/writeable@0.6.3/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/yoke-derive@0.8.2/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/yoke@0.8.2/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/zerocopy@0.8.48/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/zerocopy@0.8.48/LICENSE-BSD +24 -0
- package/THIRD_PARTY_NOTICES/zerocopy@0.8.48/LICENSE-MIT +26 -0
- package/THIRD_PARTY_NOTICES/zerofrom-derive@0.1.7/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/zerofrom@0.1.8/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/zeroize@1.8.2/LICENSE-APACHE +202 -0
- package/THIRD_PARTY_NOTICES/zeroize@1.8.2/LICENSE-MIT +21 -0
- package/THIRD_PARTY_NOTICES/zerotrie@0.2.4/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/zerovec-derive@0.11.3/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/zerovec@0.11.6/LICENSE +46 -0
- package/THIRD_PARTY_NOTICES/zmij@1.0.21/LICENSE-MIT +23 -0
- package/package.json +45 -28
- package/runtime/dashboard-acl.js +22 -0
- package/runtime/dashboard-acl.ps1 +103 -0
- package/runtime/dashboard-binary.js +5 -0
- package/runtime/dashboard-bootstrap.js +45 -0
- package/runtime/dashboard-files.js +20 -3
- package/runtime/dashboard-process.js +6 -5
- package/runtime/dashboard-supervisor.js +3 -1
- package/server.js +98 -0
- package/tui/index.js +1 -0
- package/tui/rtrt-statusline-core.d.mts +205 -0
- package/tui/rtrt-statusline-core.mjs +1145 -0
- package/tui/v2/native-runtime.mjs +81 -0
- package/tui/v2/native-state.mjs +66 -0
- package/tui/v2/rtrt-statusline.tsx +116 -0
- package/v2/permissions.js +119 -0
|
@@ -0,0 +1,1145 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from "node:child_process"
|
|
2
|
+
import { performance } from "node:perf_hooks"
|
|
3
|
+
|
|
4
|
+
export const STATUSLINE_VERSION = 1
|
|
5
|
+
export const STATUSLINE_SEPARATOR = " · "
|
|
6
|
+
export const STATUSLINE_FALLBACK = "rtrt · n/a"
|
|
7
|
+
export const STATUSLINE_GROUP_SEPARATOR = " | "
|
|
8
|
+
export const STATUSLINE_WIDE_WIDTH = 100
|
|
9
|
+
export const STATUSLINE_MEDIUM_WIDTH = 70
|
|
10
|
+
export const DEFAULT_DEBOUNCE_MS = 750
|
|
11
|
+
export const DEFAULT_INTERVAL_MS = 15_000
|
|
12
|
+
export const DEFAULT_TIMEOUT_MS = 1_500
|
|
13
|
+
export const STATUSLINE_REFRESH_EVENTS = Object.freeze([
|
|
14
|
+
"server.connected",
|
|
15
|
+
"project.updated",
|
|
16
|
+
"session.created",
|
|
17
|
+
"session.updated",
|
|
18
|
+
"session.compacted",
|
|
19
|
+
"session.deleted",
|
|
20
|
+
"session.diff",
|
|
21
|
+
"session.error",
|
|
22
|
+
"session.idle",
|
|
23
|
+
"session.status",
|
|
24
|
+
])
|
|
25
|
+
|
|
26
|
+
const MAX_OUTPUT_BYTES = 64 * 1024
|
|
27
|
+
const MAX_SEGMENTS = 32
|
|
28
|
+
const MAX_SEGMENT_LENGTH = 256
|
|
29
|
+
const CONTROL_CHAR = /[\u0000-\u001f\u007f-\u009f]/u
|
|
30
|
+
const CLI_TONES = new Set(["accent", "good", "warn", "bad", "muted"])
|
|
31
|
+
const monotonicNow = () => performance.now()
|
|
32
|
+
|
|
33
|
+
const fallbackPayload = Object.freeze({
|
|
34
|
+
version: STATUSLINE_VERSION,
|
|
35
|
+
stale: true,
|
|
36
|
+
degraded: Object.freeze(["statusline"]),
|
|
37
|
+
segments: Object.freeze([
|
|
38
|
+
Object.freeze({
|
|
39
|
+
id: "fallback",
|
|
40
|
+
text: STATUSLINE_FALLBACK,
|
|
41
|
+
compact: STATUSLINE_FALLBACK,
|
|
42
|
+
tone: "muted",
|
|
43
|
+
priority: 0,
|
|
44
|
+
}),
|
|
45
|
+
]),
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const isRecord = (value) => !!value && typeof value === "object" && !Array.isArray(value)
|
|
49
|
+
|
|
50
|
+
const validText = (value, allowEmpty = false) => {
|
|
51
|
+
if (typeof value !== "string" || value.length > MAX_SEGMENT_LENGTH || CONTROL_CHAR.test(value)) return undefined
|
|
52
|
+
const text = value.trim()
|
|
53
|
+
if (!allowEmpty && !text) return undefined
|
|
54
|
+
return text
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const eventSessionID = (event) => {
|
|
58
|
+
if (!isRecord(event) || !isRecord(event.properties)) return undefined
|
|
59
|
+
if (typeof event.properties.sessionID === "string") return event.properties.sessionID
|
|
60
|
+
for (const key of ["part", "message", "info"]) {
|
|
61
|
+
const child = event.properties[key]
|
|
62
|
+
if (!isRecord(child)) continue
|
|
63
|
+
if (typeof child.sessionID === "string") return child.sessionID
|
|
64
|
+
if (key === "info" && typeof event.type === "string" && event.type.startsWith("session.")) {
|
|
65
|
+
if (typeof child.id === "string") return child.id
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return undefined
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function statuslineRefreshTarget(event, activeSessionID = "") {
|
|
72
|
+
const sessionID = eventSessionID(event)
|
|
73
|
+
if (!sessionID) return { app: true }
|
|
74
|
+
return { app: sessionID === activeSessionID, sessionID }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const hasControlChars = (value) => {
|
|
78
|
+
const pending = [value]
|
|
79
|
+
const seen = new Set()
|
|
80
|
+
while (pending.length) {
|
|
81
|
+
const item = pending.pop()
|
|
82
|
+
if (typeof item === "string") {
|
|
83
|
+
if (CONTROL_CHAR.test(item)) return true
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
if (!item || typeof item !== "object" || seen.has(item)) continue
|
|
87
|
+
seen.add(item)
|
|
88
|
+
if (Array.isArray(item)) {
|
|
89
|
+
pending.push(...item)
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
92
|
+
for (const [key, child] of Object.entries(item)) {
|
|
93
|
+
if (CONTROL_CHAR.test(key)) return true
|
|
94
|
+
pending.push(child)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const normalizeSegment = (segment) => {
|
|
101
|
+
if (!isRecord(segment)) return undefined
|
|
102
|
+
|
|
103
|
+
const id = validText(segment.id)
|
|
104
|
+
const text = validText(segment.text)
|
|
105
|
+
const sourceTone = validText(segment.tone)
|
|
106
|
+
const tone = sourceTone && CLI_TONES.has(sourceTone) ? sourceTone : "muted"
|
|
107
|
+
const priority = segment.pri
|
|
108
|
+
if (!id || !text || !sourceTone || !Number.isSafeInteger(priority) || priority < 0 || priority > 255) {
|
|
109
|
+
return undefined
|
|
110
|
+
}
|
|
111
|
+
return { id, text, compact: text, tone, priority }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function parseStatuslineJson(raw) {
|
|
115
|
+
if (typeof raw !== "string" || !raw.trim() || Buffer.byteLength(raw) > MAX_OUTPUT_BYTES) return undefined
|
|
116
|
+
try {
|
|
117
|
+
const value = JSON.parse(raw)
|
|
118
|
+
if (!isRecord(value) || value.v !== STATUSLINE_VERSION || hasControlChars(value)) return undefined
|
|
119
|
+
if (value.stale !== undefined && typeof value.stale !== "boolean") return undefined
|
|
120
|
+
if (
|
|
121
|
+
value.degraded !== undefined &&
|
|
122
|
+
(!Array.isArray(value.degraded) ||
|
|
123
|
+
value.degraded.length > MAX_SEGMENTS ||
|
|
124
|
+
value.degraded.some((item) => !validText(item)))
|
|
125
|
+
) {
|
|
126
|
+
return undefined
|
|
127
|
+
}
|
|
128
|
+
if (!Array.isArray(value.segments) || value.segments.length < 1 || value.segments.length > MAX_SEGMENTS) {
|
|
129
|
+
return undefined
|
|
130
|
+
}
|
|
131
|
+
const segments = value.segments.map(normalizeSegment)
|
|
132
|
+
if (segments.some((segment) => !segment)) return undefined
|
|
133
|
+
return {
|
|
134
|
+
version: STATUSLINE_VERSION,
|
|
135
|
+
stale: value.stale === true,
|
|
136
|
+
degraded: value.degraded?.map((item) => item.trim()) ?? [],
|
|
137
|
+
segments,
|
|
138
|
+
}
|
|
139
|
+
} catch {
|
|
140
|
+
return undefined
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const normalizedWidth = (width) => {
|
|
145
|
+
if (!Number.isFinite(width)) return 80
|
|
146
|
+
return Math.max(1, Math.min(4_096, Math.floor(width)))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function statuslineCommandArgs({ cwd, session, width, model }) {
|
|
150
|
+
const args = [
|
|
151
|
+
"statusline",
|
|
152
|
+
"--opencode",
|
|
153
|
+
"--cwd",
|
|
154
|
+
String(cwd ?? ""),
|
|
155
|
+
"--session",
|
|
156
|
+
String(session ?? ""),
|
|
157
|
+
"--width",
|
|
158
|
+
String(normalizedWidth(width)),
|
|
159
|
+
]
|
|
160
|
+
const selectedModel = validText(model)
|
|
161
|
+
if (selectedModel) args.push("--model", selectedModel)
|
|
162
|
+
return args
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function statuslineBinaryCandidates(bin, env = process.env) {
|
|
166
|
+
const values = [bin, env?.RTRT_BIN, "rtrt"]
|
|
167
|
+
const seen = new Set()
|
|
168
|
+
return values.flatMap((value) => {
|
|
169
|
+
const candidate = validText(value)
|
|
170
|
+
if (!candidate || seen.has(candidate)) return []
|
|
171
|
+
seen.add(candidate)
|
|
172
|
+
return [candidate]
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const runCandidate = ({
|
|
177
|
+
binary,
|
|
178
|
+
args,
|
|
179
|
+
cwd,
|
|
180
|
+
spawnImpl,
|
|
181
|
+
timeoutMs,
|
|
182
|
+
signal,
|
|
183
|
+
setTimeoutFn,
|
|
184
|
+
clearTimeoutFn,
|
|
185
|
+
}) =>
|
|
186
|
+
new Promise((resolve) => {
|
|
187
|
+
let child
|
|
188
|
+
let settled = false
|
|
189
|
+
let bytes = 0
|
|
190
|
+
const chunks = []
|
|
191
|
+
let timeout
|
|
192
|
+
let abort
|
|
193
|
+
|
|
194
|
+
const finish = (payload) => {
|
|
195
|
+
if (settled) return
|
|
196
|
+
settled = true
|
|
197
|
+
clearTimeoutFn(timeout)
|
|
198
|
+
if (abort) signal?.removeEventListener("abort", abort)
|
|
199
|
+
resolve(payload)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (signal?.aborted) {
|
|
203
|
+
finish(undefined)
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
child = spawnImpl(binary, args, {
|
|
209
|
+
cwd: cwd || undefined,
|
|
210
|
+
shell: false,
|
|
211
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
212
|
+
windowsHide: true,
|
|
213
|
+
})
|
|
214
|
+
} catch {
|
|
215
|
+
finish(undefined)
|
|
216
|
+
return
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!child?.stdout || typeof child.once !== "function") {
|
|
220
|
+
try {
|
|
221
|
+
child?.kill?.()
|
|
222
|
+
} catch {}
|
|
223
|
+
finish(undefined)
|
|
224
|
+
return
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
child.stdout.on("data", (chunk) => {
|
|
228
|
+
const data = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
|
|
229
|
+
bytes += data.length
|
|
230
|
+
if (bytes > MAX_OUTPUT_BYTES) {
|
|
231
|
+
try {
|
|
232
|
+
child.kill("SIGKILL")
|
|
233
|
+
} catch {}
|
|
234
|
+
finish(undefined)
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
chunks.push(data)
|
|
238
|
+
})
|
|
239
|
+
child.once("error", () => finish(undefined))
|
|
240
|
+
child.once("close", (code) => {
|
|
241
|
+
if (code !== 0) {
|
|
242
|
+
finish(undefined)
|
|
243
|
+
return
|
|
244
|
+
}
|
|
245
|
+
finish(parseStatuslineJson(Buffer.concat(chunks).toString("utf8")))
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
abort = () => {
|
|
249
|
+
try {
|
|
250
|
+
child.kill("SIGKILL")
|
|
251
|
+
} catch {}
|
|
252
|
+
finish(undefined)
|
|
253
|
+
}
|
|
254
|
+
signal?.addEventListener("abort", abort, { once: true })
|
|
255
|
+
|
|
256
|
+
timeout = setTimeoutFn(() => {
|
|
257
|
+
try {
|
|
258
|
+
child.kill("SIGKILL")
|
|
259
|
+
} catch {}
|
|
260
|
+
finish(undefined)
|
|
261
|
+
}, Math.max(1, timeoutMs))
|
|
262
|
+
timeout.unref?.()
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
export async function runStatusline({
|
|
266
|
+
bin,
|
|
267
|
+
env = process.env,
|
|
268
|
+
cwd,
|
|
269
|
+
session,
|
|
270
|
+
width,
|
|
271
|
+
model,
|
|
272
|
+
spawnImpl = nodeSpawn,
|
|
273
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
274
|
+
signal,
|
|
275
|
+
nowFn = monotonicNow,
|
|
276
|
+
setTimeoutFn = setTimeout,
|
|
277
|
+
clearTimeoutFn = clearTimeout,
|
|
278
|
+
}) {
|
|
279
|
+
const args = statuslineCommandArgs({ cwd, session, width, model })
|
|
280
|
+
const duration = Number.isFinite(timeoutMs) ? Math.max(1, timeoutMs) : DEFAULT_TIMEOUT_MS
|
|
281
|
+
const deadline = nowFn() + duration
|
|
282
|
+
for (const binary of statuslineBinaryCandidates(bin, env)) {
|
|
283
|
+
if (signal?.aborted) return undefined
|
|
284
|
+
const remaining = deadline - nowFn()
|
|
285
|
+
if (remaining <= 0) return undefined
|
|
286
|
+
try {
|
|
287
|
+
const payload = await runCandidate({
|
|
288
|
+
binary,
|
|
289
|
+
args,
|
|
290
|
+
cwd,
|
|
291
|
+
spawnImpl,
|
|
292
|
+
timeoutMs: Math.ceil(remaining),
|
|
293
|
+
signal,
|
|
294
|
+
setTimeoutFn,
|
|
295
|
+
clearTimeoutFn,
|
|
296
|
+
})
|
|
297
|
+
if (payload) return payload
|
|
298
|
+
} catch {}
|
|
299
|
+
}
|
|
300
|
+
return undefined
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function createSpawnLimiter({ concurrency = 2 } = {}) {
|
|
304
|
+
const limit = Number.isSafeInteger(concurrency) ? Math.max(1, Math.min(16, concurrency)) : 2
|
|
305
|
+
const queue = []
|
|
306
|
+
const running = new Set()
|
|
307
|
+
let active = 0
|
|
308
|
+
let disposed = false
|
|
309
|
+
|
|
310
|
+
const cleanup = (entry) => entry.signal?.removeEventListener("abort", entry.abort)
|
|
311
|
+
|
|
312
|
+
const finish = (entry, value) => {
|
|
313
|
+
if (entry.finished) return
|
|
314
|
+
entry.finished = true
|
|
315
|
+
cleanup(entry)
|
|
316
|
+
if (entry.started) {
|
|
317
|
+
active -= 1
|
|
318
|
+
running.delete(entry)
|
|
319
|
+
}
|
|
320
|
+
entry.resolve(value)
|
|
321
|
+
pump()
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const start = (entry) => {
|
|
325
|
+
entry.started = true
|
|
326
|
+
active += 1
|
|
327
|
+
running.add(entry)
|
|
328
|
+
void (async () => {
|
|
329
|
+
let value
|
|
330
|
+
try {
|
|
331
|
+
value = await entry.task(entry.controller.signal)
|
|
332
|
+
} catch {}
|
|
333
|
+
finish(entry, value)
|
|
334
|
+
})()
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const pump = () => {
|
|
338
|
+
while (!disposed && active < limit && queue.length > 0) {
|
|
339
|
+
let selected = 0
|
|
340
|
+
for (let index = 1; index < queue.length; index += 1) {
|
|
341
|
+
if (queue[index].priority > queue[selected].priority) selected = index
|
|
342
|
+
}
|
|
343
|
+
const [entry] = queue.splice(selected, 1)
|
|
344
|
+
if (!entry.finished) start(entry)
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
run(task, { signal, priority = 0 } = {}) {
|
|
350
|
+
if (disposed || signal?.aborted) return Promise.resolve(undefined)
|
|
351
|
+
return new Promise((resolve) => {
|
|
352
|
+
const entry = {
|
|
353
|
+
task,
|
|
354
|
+
signal,
|
|
355
|
+
priority: Number.isFinite(priority) ? priority : 0,
|
|
356
|
+
controller: new AbortController(),
|
|
357
|
+
resolve,
|
|
358
|
+
started: false,
|
|
359
|
+
finished: false,
|
|
360
|
+
abort: undefined,
|
|
361
|
+
}
|
|
362
|
+
entry.abort = () => {
|
|
363
|
+
entry.controller.abort()
|
|
364
|
+
if (entry.started) return
|
|
365
|
+
const index = queue.indexOf(entry)
|
|
366
|
+
if (index >= 0) queue.splice(index, 1)
|
|
367
|
+
finish(entry, undefined)
|
|
368
|
+
}
|
|
369
|
+
signal?.addEventListener("abort", entry.abort, { once: true })
|
|
370
|
+
queue.push(entry)
|
|
371
|
+
pump()
|
|
372
|
+
})
|
|
373
|
+
},
|
|
374
|
+
activeCount: () => active,
|
|
375
|
+
queuedCount: () => queue.length,
|
|
376
|
+
dispose() {
|
|
377
|
+
if (disposed) return
|
|
378
|
+
disposed = true
|
|
379
|
+
for (const entry of queue.splice(0)) {
|
|
380
|
+
entry.controller.abort()
|
|
381
|
+
finish(entry, undefined)
|
|
382
|
+
}
|
|
383
|
+
for (const entry of running) entry.controller.abort()
|
|
384
|
+
},
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const isWideCodePoint = (code) =>
|
|
389
|
+
code >= 0x1100 &&
|
|
390
|
+
(code <= 0x115f ||
|
|
391
|
+
code === 0x2329 ||
|
|
392
|
+
code === 0x232a ||
|
|
393
|
+
(code >= 0x2e80 && code <= 0xa4cf && code !== 0x303f) ||
|
|
394
|
+
(code >= 0xac00 && code <= 0xd7a3) ||
|
|
395
|
+
(code >= 0xf900 && code <= 0xfaff) ||
|
|
396
|
+
(code >= 0xfe10 && code <= 0xfe19) ||
|
|
397
|
+
(code >= 0xfe30 && code <= 0xfe6f) ||
|
|
398
|
+
(code >= 0xff00 && code <= 0xff60) ||
|
|
399
|
+
(code >= 0xffe0 && code <= 0xffe6) ||
|
|
400
|
+
(code >= 0x1f300 && code <= 0x1faff) ||
|
|
401
|
+
(code >= 0x20000 && code <= 0x3fffd))
|
|
402
|
+
|
|
403
|
+
export function cellWidth(text) {
|
|
404
|
+
let width = 0
|
|
405
|
+
for (const character of text) {
|
|
406
|
+
if (/\p{Mark}/u.test(character) || character === "\u200d" || character === "\ufe0f") continue
|
|
407
|
+
width += isWideCodePoint(character.codePointAt(0)) ? 2 : 1
|
|
408
|
+
}
|
|
409
|
+
return width
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const truncateToWidth = (text, width) => {
|
|
413
|
+
if (cellWidth(text) <= width) return text
|
|
414
|
+
if (width <= 1) return "…".slice(0, width)
|
|
415
|
+
let output = ""
|
|
416
|
+
let used = 0
|
|
417
|
+
for (const character of text) {
|
|
418
|
+
const size = cellWidth(character)
|
|
419
|
+
if (used + size > width - 1) break
|
|
420
|
+
output += character
|
|
421
|
+
used += size
|
|
422
|
+
}
|
|
423
|
+
return `${output}…`
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const findCatalogModel = (providers, providerID, modelID) => {
|
|
427
|
+
if (!Array.isArray(providers) || typeof providerID !== "string" || typeof modelID !== "string") {
|
|
428
|
+
return undefined
|
|
429
|
+
}
|
|
430
|
+
const provider = providers.find((item) => item?.id === providerID)
|
|
431
|
+
if (!isRecord(provider?.models)) return undefined
|
|
432
|
+
const direct = provider.models[modelID]
|
|
433
|
+
if (isRecord(direct)) return direct
|
|
434
|
+
return Object.values(provider.models).find(
|
|
435
|
+
(model) => isRecord(model) && model.id === modelID && (!model.providerID || model.providerID === providerID),
|
|
436
|
+
)
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const tokenCount = (value) => (Number.isFinite(value) && value > 0 ? value : 0)
|
|
440
|
+
|
|
441
|
+
const contextTone = (percent) => {
|
|
442
|
+
if (percent > 100) return "warn"
|
|
443
|
+
if (percent >= 90) return "bad"
|
|
444
|
+
if (percent >= 75) return "warn"
|
|
445
|
+
return "good"
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export function deriveSessionEconomics({ session, messages = [], providers = [], status } = {}) {
|
|
449
|
+
let cost = { text: "N/A", tone: "muted" }
|
|
450
|
+
if (session?.cost === 0) {
|
|
451
|
+
cost = { text: "$0?", tone: "muted" }
|
|
452
|
+
} else if (Number.isFinite(session?.cost) && session.cost > 0) {
|
|
453
|
+
cost = { text: `~$${session.cost.toFixed(2)}`, tone: "accent" }
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const selected = session?.model
|
|
457
|
+
const selectedModel = findCatalogModel(providers, selected?.providerID, selected?.id)
|
|
458
|
+
const selectedText = validText(selectedModel?.name) ?? validText(selected?.id)
|
|
459
|
+
const model = selectedText
|
|
460
|
+
? { text: truncateToWidth(selectedText.split("/").at(-1), 22), tone: "accent" }
|
|
461
|
+
: { text: "N/A", tone: "muted" }
|
|
462
|
+
const selectedProviderID = validText(selected?.providerID)
|
|
463
|
+
const selectedModelID = validText(selected?.id)
|
|
464
|
+
const modelRef =
|
|
465
|
+
selectedProviderID && selectedModelID ? validText(`${selectedProviderID}/${selectedModelID}`) : undefined
|
|
466
|
+
|
|
467
|
+
let context = { text: "N/A", tone: "muted" }
|
|
468
|
+
if (Array.isArray(messages)) {
|
|
469
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
470
|
+
const message = messages[index]
|
|
471
|
+
if (message?.role !== "assistant") continue
|
|
472
|
+
const tokens = message.tokens
|
|
473
|
+
if (message.error || !Number.isFinite(message.time?.completed) || tokenCount(tokens?.output) <= 0) {
|
|
474
|
+
continue
|
|
475
|
+
}
|
|
476
|
+
const used =
|
|
477
|
+
tokenCount(tokens?.input) +
|
|
478
|
+
tokenCount(tokens?.output) +
|
|
479
|
+
tokenCount(tokens?.reasoning) +
|
|
480
|
+
tokenCount(tokens?.cache?.read) +
|
|
481
|
+
tokenCount(tokens?.cache?.write)
|
|
482
|
+
if (used <= 0) continue
|
|
483
|
+
const exactModel = findCatalogModel(providers, message.providerID, message.modelID)
|
|
484
|
+
const limit = exactModel?.limit?.context
|
|
485
|
+
if (Number.isFinite(limit) && limit > 0) {
|
|
486
|
+
const percent = Math.max(0, Math.round((used / limit) * 100))
|
|
487
|
+
const headroom = Math.max(0, 100 - percent)
|
|
488
|
+
context = { text: `${percent}%`, tone: contextTone(percent), used, limit, percent, headroom }
|
|
489
|
+
} else {
|
|
490
|
+
context = { text: "N/A", tone: "muted", used }
|
|
491
|
+
}
|
|
492
|
+
break
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// OpenCode omits idle sessions from the status map.
|
|
497
|
+
const sessionStatus = session
|
|
498
|
+
? ({
|
|
499
|
+
busy: { text: "BUSY", tone: "accent" },
|
|
500
|
+
retry: { text: "RETRY", tone: "bad" },
|
|
501
|
+
idle: { text: "IDLE", tone: "muted" },
|
|
502
|
+
}[status?.type] ?? { text: "IDLE", tone: "muted" })
|
|
503
|
+
: { text: "UNKNOWN", tone: "muted" }
|
|
504
|
+
|
|
505
|
+
return {
|
|
506
|
+
cost,
|
|
507
|
+
context,
|
|
508
|
+
model,
|
|
509
|
+
status: sessionStatus,
|
|
510
|
+
week: { text: "N/A/not exposed", tone: "muted" },
|
|
511
|
+
modelRef,
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const renderedWidth = (segments) =>
|
|
516
|
+
segments.reduce((sum, segment) => sum + cellWidth(segment.text), 0) +
|
|
517
|
+
Math.max(0, segments.length - 1) * cellWidth(STATUSLINE_SEPARATOR)
|
|
518
|
+
|
|
519
|
+
export function selectSegments(payload, { width = 80, compact = false } = {}) {
|
|
520
|
+
const limit = normalizedWidth(width)
|
|
521
|
+
let selected = payload.segments.flatMap((segment, index) => {
|
|
522
|
+
const text = compact ? segment.compact : segment.text
|
|
523
|
+
return text ? [{ ...segment, text, index }] : []
|
|
524
|
+
})
|
|
525
|
+
while (selected.length > 1 && renderedWidth(selected) > limit) {
|
|
526
|
+
let remove = 0
|
|
527
|
+
for (let index = 1; index < selected.length; index += 1) {
|
|
528
|
+
if (
|
|
529
|
+
selected[index].priority < selected[remove].priority ||
|
|
530
|
+
(selected[index].priority === selected[remove].priority && selected[index].index > selected[remove].index)
|
|
531
|
+
) {
|
|
532
|
+
remove = index
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
selected.splice(remove, 1)
|
|
536
|
+
}
|
|
537
|
+
if (selected.length === 1) selected[0] = { ...selected[0], text: truncateToWidth(selected[0].text, limit) }
|
|
538
|
+
return selected.map(({ index: _index, ...segment }) => segment)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
export function initialStatuslineState() {
|
|
542
|
+
return { payload: fallbackPayload, lastGood: undefined, stale: true, unavailable: true }
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
export function nextStatuslineState(previous, payload) {
|
|
546
|
+
if (payload) return { payload, lastGood: payload, stale: payload.stale === true, unavailable: false }
|
|
547
|
+
if (previous.lastGood) {
|
|
548
|
+
return { payload: previous.lastGood, lastGood: previous.lastGood, stale: true, unavailable: false }
|
|
549
|
+
}
|
|
550
|
+
return initialStatuslineState()
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
export function renderSegments(state, options = {}) {
|
|
554
|
+
const payload =
|
|
555
|
+
state.stale && !state.unavailable
|
|
556
|
+
? {
|
|
557
|
+
version: STATUSLINE_VERSION,
|
|
558
|
+
stale: true,
|
|
559
|
+
segments: [
|
|
560
|
+
...state.payload.segments,
|
|
561
|
+
{ id: "stale", text: "stale", compact: "stale", tone: "muted", priority: 1_000 },
|
|
562
|
+
],
|
|
563
|
+
}
|
|
564
|
+
: state.payload
|
|
565
|
+
const segments = selectSegments(payload, options)
|
|
566
|
+
return state.stale ? segments.map((segment) => ({ ...segment, tone: "muted" })) : segments
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const viewPart = (text, role, tone, id) => ({ text, role, tone, id })
|
|
570
|
+
|
|
571
|
+
const valueGroup = (id, text, tone = "muted", role = "value") => ({
|
|
572
|
+
id,
|
|
573
|
+
parts: [viewPart(text, role, tone, id)],
|
|
574
|
+
})
|
|
575
|
+
|
|
576
|
+
const metricGroup = (id, label, text, tone) => ({
|
|
577
|
+
id,
|
|
578
|
+
parts: [
|
|
579
|
+
viewPart(`${label} `, "label", "muted", id),
|
|
580
|
+
viewPart(text, "value", tone, id),
|
|
581
|
+
],
|
|
582
|
+
})
|
|
583
|
+
|
|
584
|
+
const groupText = (group) => group.parts.map((part) => part.text).join("")
|
|
585
|
+
const groupsWidth = (groups, separator) =>
|
|
586
|
+
groups.reduce((sum, group) => sum + cellWidth(groupText(group)), 0) +
|
|
587
|
+
Math.max(0, groups.length - 1) * cellWidth(separator)
|
|
588
|
+
|
|
589
|
+
const rowFromGroups = (id, groups, separator) => {
|
|
590
|
+
const parts = []
|
|
591
|
+
for (const [index, group] of groups.entries()) {
|
|
592
|
+
if (index > 0) parts.push(viewPart(separator, "separator", "muted", "separator"))
|
|
593
|
+
parts.push(...group.parts)
|
|
594
|
+
}
|
|
595
|
+
return { id, parts }
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
const sourceTone = (state, segment) => (state.stale ? "muted" : segment?.tone ?? "muted")
|
|
599
|
+
|
|
600
|
+
const segmentValue = (segments, id, prefix = "") => {
|
|
601
|
+
const segment = segments.get(id)
|
|
602
|
+
if (!segment) return undefined
|
|
603
|
+
const text = prefix && segment.text.startsWith(prefix) ? segment.text.slice(prefix.length) : segment.text
|
|
604
|
+
return text ? { text, segment } : undefined
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const savingsValues = (segments) => {
|
|
608
|
+
const savings = segments.get("savings")
|
|
609
|
+
if (savings) {
|
|
610
|
+
const save = /(?:^|\s)save:([^\s]+)/u.exec(savings.text)?.[1]
|
|
611
|
+
const command = /(?:^|\s)cmd:([^\s]+)/u.exec(savings.text)?.[1]
|
|
612
|
+
return {
|
|
613
|
+
save: save ? { text: save, segment: savings } : undefined,
|
|
614
|
+
command: command ? { text: command, segment: savings } : undefined,
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
const sigma = segments.get("sigma")
|
|
618
|
+
if (!sigma) return {}
|
|
619
|
+
const text = sigma.text.replace(/^(?:Σ|sigma):?/iu, "")
|
|
620
|
+
return text ? { save: { text, segment: sigma } } : {}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const headroomValues = (segments) => {
|
|
624
|
+
const value = segmentValue(segments, "headroom", "room:")
|
|
625
|
+
if (!value) return undefined
|
|
626
|
+
const boundary = value.text.lastIndexOf(":")
|
|
627
|
+
if (boundary < 0) return { full: value.text, compact: value.text, segment: value.segment }
|
|
628
|
+
const target = value.text.slice(0, boundary)
|
|
629
|
+
const amount = value.text.slice(boundary + 1)
|
|
630
|
+
return {
|
|
631
|
+
full: target && amount ? `${target} ${amount}` : value.text,
|
|
632
|
+
compact: amount || value.text,
|
|
633
|
+
segment: value.segment,
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
const reportedPercentToken = (text) => {
|
|
638
|
+
const match = /\d+(?:\.\d+)?%/u.exec(text)
|
|
639
|
+
if (!match) return undefined
|
|
640
|
+
const before = match.index > 0 ? text[match.index - 1] : ""
|
|
641
|
+
const after = text[match.index + match[0].length] ?? ""
|
|
642
|
+
if (
|
|
643
|
+
(before && /[\p{Letter}\p{Number}_.+-]/u.test(before)) ||
|
|
644
|
+
(after && /[\p{Letter}\p{Number}_.%]/u.test(after))
|
|
645
|
+
) {
|
|
646
|
+
return undefined
|
|
647
|
+
}
|
|
648
|
+
const value = Number(match[0].slice(0, -1))
|
|
649
|
+
if (!Number.isFinite(value) || value < 0 || value > 100) return undefined
|
|
650
|
+
return { text: match[0], index: match.index }
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
const officialLimitValue = (segments, id) => {
|
|
654
|
+
const segment = segments.get(id)
|
|
655
|
+
if (!segment) return undefined
|
|
656
|
+
const percentToken = reportedPercentToken(segment.text)
|
|
657
|
+
if (!percentToken) return undefined
|
|
658
|
+
const percent = percentToken.text
|
|
659
|
+
let reset = segment.text.slice(percentToken.index + percent.length).trim()
|
|
660
|
+
reset = reset
|
|
661
|
+
.replace(/^[|,;/-]\s*/u, "")
|
|
662
|
+
.replace(/^(?:reset(?:s|_at)?|r)\s*[:=]?\s*/iu, "")
|
|
663
|
+
.replace(/^(?:in\s+|↻\s*|@\s*)/iu, "")
|
|
664
|
+
.replace(/\s+/gu, "")
|
|
665
|
+
return {
|
|
666
|
+
full: reset ? `${percent}/${reset}` : percent,
|
|
667
|
+
percent,
|
|
668
|
+
segment,
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const statusGroups = (state, missing) => {
|
|
673
|
+
const groups = []
|
|
674
|
+
if (state.stale && !state.unavailable) groups.push(valueGroup("stale", "STALE", "warn"))
|
|
675
|
+
if (state.unavailable || missing || (state.payload.degraded?.length ?? 0) > 0) {
|
|
676
|
+
groups.push(valueGroup("degraded", "DEGRADED", "bad"))
|
|
677
|
+
}
|
|
678
|
+
if (groups.length === 0) groups.push(valueGroup("live", "LIVE", "good"))
|
|
679
|
+
return groups
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const replaceGroupText = (groups, id, text) =>
|
|
683
|
+
groups.map((group) => {
|
|
684
|
+
if (group.id !== id) return group
|
|
685
|
+
const last = group.parts.length - 1
|
|
686
|
+
return {
|
|
687
|
+
...group,
|
|
688
|
+
parts: group.parts.map((part, index) => (index === last ? { ...part, text } : part)),
|
|
689
|
+
}
|
|
690
|
+
})
|
|
691
|
+
|
|
692
|
+
const removeGroup = (groups, id) => groups.filter((group) => group.id !== id)
|
|
693
|
+
|
|
694
|
+
const capGroupValues = (source, limits) => {
|
|
695
|
+
let groups = source
|
|
696
|
+
for (const [id, limit] of limits) {
|
|
697
|
+
const group = groups.find((item) => item.id === id)
|
|
698
|
+
if (!group) continue
|
|
699
|
+
const value = group.parts.at(-1)?.text ?? ""
|
|
700
|
+
groups = replaceGroupText(groups, id, truncateToWidth(value, limit))
|
|
701
|
+
}
|
|
702
|
+
return groups
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const fitWideIdentityGroups = (source, width) => {
|
|
706
|
+
let groups = capGroupValues(source, [
|
|
707
|
+
["project", 36],
|
|
708
|
+
["git", 24],
|
|
709
|
+
["model", 22],
|
|
710
|
+
])
|
|
711
|
+
if (groupsWidth(groups, " ") > width) groups = removeGroup(groups, "git")
|
|
712
|
+
const project = groups.find((group) => group.id === "project")
|
|
713
|
+
if (project && groupsWidth(groups, " ") > width) {
|
|
714
|
+
const overflow = groupsWidth(groups, " ") - width
|
|
715
|
+
const current = groupText(project)
|
|
716
|
+
groups = replaceGroupText(groups, "project", truncateToWidth(current, Math.max(4, cellWidth(current) - overflow)))
|
|
717
|
+
}
|
|
718
|
+
if (groupsWidth(groups, " ") > width) groups = removeGroup(groups, "project")
|
|
719
|
+
return groups
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const fitWideMetricGroups = (source, width) => {
|
|
723
|
+
let groups = capGroupValues(source, [
|
|
724
|
+
["style", 12],
|
|
725
|
+
["savings", 8],
|
|
726
|
+
["command", 8],
|
|
727
|
+
["memory", 18],
|
|
728
|
+
["headroom", 18],
|
|
729
|
+
["cost", 12],
|
|
730
|
+
["context", 5],
|
|
731
|
+
["week", 15],
|
|
732
|
+
["limit-5h", 12],
|
|
733
|
+
["limit-week", 12],
|
|
734
|
+
])
|
|
735
|
+
for (const id of ["headroom", "memory", "command", "savings", "style"]) {
|
|
736
|
+
if (groupsWidth(groups, STATUSLINE_GROUP_SEPARATOR) <= width) break
|
|
737
|
+
groups = removeGroup(groups, id)
|
|
738
|
+
}
|
|
739
|
+
return groups
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
const fitMediumGroups = (source, width) => {
|
|
743
|
+
let groups = capGroupValues(source, [
|
|
744
|
+
["project", 18],
|
|
745
|
+
["model", 16],
|
|
746
|
+
["style", 12],
|
|
747
|
+
["savings", 8],
|
|
748
|
+
["command", 8],
|
|
749
|
+
["headroom", 10],
|
|
750
|
+
["cost", 12],
|
|
751
|
+
["context", 5],
|
|
752
|
+
["week", 15],
|
|
753
|
+
["limit-5h", 12],
|
|
754
|
+
["limit-week", 12],
|
|
755
|
+
])
|
|
756
|
+
for (const id of ["week", "headroom", "command"]) {
|
|
757
|
+
if (groupsWidth(groups, STATUSLINE_GROUP_SEPARATOR) <= width) break
|
|
758
|
+
groups = removeGroup(groups, id)
|
|
759
|
+
}
|
|
760
|
+
const project = groups.find((group) => group.id === "project")
|
|
761
|
+
if (project && groupsWidth(groups, STATUSLINE_GROUP_SEPARATOR) > width) {
|
|
762
|
+
const overflow = groupsWidth(groups, STATUSLINE_GROUP_SEPARATOR) - width
|
|
763
|
+
const current = groupText(project)
|
|
764
|
+
groups = replaceGroupText(groups, "project", truncateToWidth(current, Math.max(4, cellWidth(current) - overflow)))
|
|
765
|
+
}
|
|
766
|
+
for (const id of ["model", "project", "style", "savings", "badge"]) {
|
|
767
|
+
if (groupsWidth(groups, STATUSLINE_GROUP_SEPARATOR) <= width) break
|
|
768
|
+
groups = removeGroup(groups, id)
|
|
769
|
+
}
|
|
770
|
+
if (groupsWidth(groups, STATUSLINE_GROUP_SEPARATOR) <= width) {
|
|
771
|
+
return { groups, separator: STATUSLINE_GROUP_SEPARATOR }
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
const fallback = []
|
|
775
|
+
for (const id of ["savings", "cost", "context", "session-status"]) {
|
|
776
|
+
const group = groups.find((item) => item.id === id)
|
|
777
|
+
const value = group?.parts.at(-1)
|
|
778
|
+
if (value) fallback.push(valueGroup(id, truncateToWidth(value.text, id === "cost" ? 12 : 8), value.tone))
|
|
779
|
+
}
|
|
780
|
+
for (const [id, label] of [
|
|
781
|
+
["limit-5h", "5H"],
|
|
782
|
+
["limit-week", "WEEK"],
|
|
783
|
+
]) {
|
|
784
|
+
const group = groups.find((item) => item.id === id)
|
|
785
|
+
const value = group?.parts.at(-1)
|
|
786
|
+
if (!value) continue
|
|
787
|
+
fallback.push(metricGroup(id, label, truncateToWidth(value.text, 12), value.tone))
|
|
788
|
+
}
|
|
789
|
+
fallback.push(...groups.filter((group) => ["stale", "degraded", "live"].includes(group.id)))
|
|
790
|
+
return {
|
|
791
|
+
groups: fitNarrowGroups(fallback, width, ["context", "cost", "savings", "session-status", "limit-5h", "limit-week"]),
|
|
792
|
+
separator: " ",
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
const fitNarrowGroups = (source, width, removalOrder = ["cost", "context", "style", "savings"]) => {
|
|
797
|
+
let groups = source
|
|
798
|
+
for (const id of removalOrder) {
|
|
799
|
+
if (groupsWidth(groups, " ") <= width) break
|
|
800
|
+
groups = removeGroup(groups, id)
|
|
801
|
+
}
|
|
802
|
+
if (groups.length === 0) groups = [valueGroup("missing", "N/A", "bad")]
|
|
803
|
+
if (groupsWidth(groups, " ") <= width) return groups
|
|
804
|
+
const text = groups.map(groupText).join(" ")
|
|
805
|
+
return [valueGroup("status", truncateToWidth(text, width), "bad")]
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
export function createStatuslineViewModel(state, { width = 80, economics, promptRight = false } = {}) {
|
|
809
|
+
const limit = normalizedWidth(width)
|
|
810
|
+
const layout = limit >= STATUSLINE_WIDE_WIDTH ? "wide" : limit >= STATUSLINE_MEDIUM_WIDTH ? "medium" : "narrow"
|
|
811
|
+
const sessionEconomics = economics ?? deriveSessionEconomics()
|
|
812
|
+
const segments = new Map(state.payload.segments.map((segment) => [segment.id, segment]))
|
|
813
|
+
const project = segmentValue(segments, "project")
|
|
814
|
+
const git = segmentValue(segments, "git")
|
|
815
|
+
const style = segmentValue(segments, "style", "opt:")
|
|
816
|
+
const savings = savingsValues(segments)
|
|
817
|
+
const memory = segmentValue(segments, "memory", "mem:")
|
|
818
|
+
const headroom = headroomValues(segments)
|
|
819
|
+
const limitsFresh = !state.stale && !state.unavailable
|
|
820
|
+
const limit5h = limitsFresh ? officialLimitValue(segments, "limit_5h") : undefined
|
|
821
|
+
const limitWeek = limitsFresh ? officialLimitValue(segments, "limit_week") : undefined
|
|
822
|
+
const missing = state.unavailable || (!style && !savings.save)
|
|
823
|
+
const statuses = statusGroups(state, missing)
|
|
824
|
+
|
|
825
|
+
if (layout === "wide") {
|
|
826
|
+
const identity = [valueGroup("badge", "[RTRT]", "accent", "badge")]
|
|
827
|
+
if (state.unavailable) {
|
|
828
|
+
identity.push(valueGroup("missing", "N/A", "bad"))
|
|
829
|
+
} else {
|
|
830
|
+
if (project) identity.push(valueGroup("project", truncateToWidth(project.text, 36), sourceTone(state, project.segment)))
|
|
831
|
+
if (git) identity.push(valueGroup("git", truncateToWidth(git.text, 24), sourceTone(state, git.segment)))
|
|
832
|
+
}
|
|
833
|
+
identity.push(
|
|
834
|
+
metricGroup("model", "MODEL", sessionEconomics.model.text, sessionEconomics.model.tone),
|
|
835
|
+
metricGroup("session-status", "STATE", sessionEconomics.status.text, sessionEconomics.status.tone),
|
|
836
|
+
...statuses,
|
|
837
|
+
)
|
|
838
|
+
|
|
839
|
+
const metrics = []
|
|
840
|
+
if (state.unavailable) {
|
|
841
|
+
for (const label of ["OPT", "SAVE", "CMD", "MEM", "ROOM"]) {
|
|
842
|
+
metrics.push(metricGroup(label.toLowerCase(), label, "N/A", "bad"))
|
|
843
|
+
}
|
|
844
|
+
} else {
|
|
845
|
+
if (style) metrics.push(metricGroup("style", "OPT", style.text, sourceTone(state, style.segment)))
|
|
846
|
+
if (savings.save) metrics.push(metricGroup("savings", "SAVE", savings.save.text, sourceTone(state, savings.save.segment)))
|
|
847
|
+
if (savings.command) metrics.push(metricGroup("command", "CMD", savings.command.text, sourceTone(state, savings.command.segment)))
|
|
848
|
+
if (memory) metrics.push(metricGroup("memory", "MEM", truncateToWidth(memory.text, 18), sourceTone(state, memory.segment)))
|
|
849
|
+
if (headroom) metrics.push(metricGroup("headroom", "ROOM", truncateToWidth(headroom.full, 28), sourceTone(state, headroom.segment)))
|
|
850
|
+
if (metrics.length === 0) metrics.push(metricGroup("metrics", "METRICS", "N/A", "bad"))
|
|
851
|
+
}
|
|
852
|
+
metrics.push(
|
|
853
|
+
metricGroup("cost", "COST", sessionEconomics.cost.text, sessionEconomics.cost.tone),
|
|
854
|
+
metricGroup("context", "CTX", sessionEconomics.context.text, sessionEconomics.context.tone),
|
|
855
|
+
)
|
|
856
|
+
if (limit5h) {
|
|
857
|
+
metrics.push(metricGroup("limit-5h", "5H", limit5h.full, sourceTone(state, limit5h.segment)))
|
|
858
|
+
}
|
|
859
|
+
metrics.push(
|
|
860
|
+
limitWeek
|
|
861
|
+
? metricGroup("limit-week", "WEEK", limitWeek.full, sourceTone(state, limitWeek.segment))
|
|
862
|
+
: metricGroup("week", "WEEK", sessionEconomics.week.text, sessionEconomics.week.tone),
|
|
863
|
+
)
|
|
864
|
+
const fittedIdentity = fitWideIdentityGroups(identity, limit)
|
|
865
|
+
const fittedMetrics = fitWideMetricGroups(metrics, limit)
|
|
866
|
+
return {
|
|
867
|
+
layout,
|
|
868
|
+
width: limit,
|
|
869
|
+
rows: [
|
|
870
|
+
rowFromGroups("identity", fittedIdentity, " "),
|
|
871
|
+
rowFromGroups("metrics", fittedMetrics, STATUSLINE_GROUP_SEPARATOR),
|
|
872
|
+
],
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
if (layout === "medium") {
|
|
877
|
+
let groups = [valueGroup("badge", "[RTRT]", "accent", "badge")]
|
|
878
|
+
if (state.unavailable) {
|
|
879
|
+
groups.push(valueGroup("missing", "N/A", "bad"))
|
|
880
|
+
} else {
|
|
881
|
+
if (project) groups.push(valueGroup("project", truncateToWidth(project.text, 18), sourceTone(state, project.segment)))
|
|
882
|
+
groups.push(metricGroup("model", "MODEL", sessionEconomics.model.text, sessionEconomics.model.tone))
|
|
883
|
+
groups.push(metricGroup("session-status", "STATE", sessionEconomics.status.text, sessionEconomics.status.tone))
|
|
884
|
+
if (style) groups.push(metricGroup("style", "OPT", style.text, sourceTone(state, style.segment)))
|
|
885
|
+
if (savings.save) groups.push(metricGroup("savings", "SAVE", savings.save.text, sourceTone(state, savings.save.segment)))
|
|
886
|
+
groups.push(metricGroup("cost", "COST", sessionEconomics.cost.text, sessionEconomics.cost.tone))
|
|
887
|
+
groups.push(metricGroup("context", "CTX", sessionEconomics.context.text, sessionEconomics.context.tone))
|
|
888
|
+
if (savings.command) groups.push(metricGroup("command", "CMD", savings.command.text, sourceTone(state, savings.command.segment)))
|
|
889
|
+
if (headroom) groups.push(metricGroup("headroom", "ROOM", headroom.compact, sourceTone(state, headroom.segment)))
|
|
890
|
+
}
|
|
891
|
+
if (state.unavailable) {
|
|
892
|
+
groups.push(
|
|
893
|
+
metricGroup("model", "MODEL", sessionEconomics.model.text, sessionEconomics.model.tone),
|
|
894
|
+
metricGroup("session-status", "STATE", sessionEconomics.status.text, sessionEconomics.status.tone),
|
|
895
|
+
metricGroup("cost", "COST", sessionEconomics.cost.text, sessionEconomics.cost.tone),
|
|
896
|
+
metricGroup("context", "CTX", sessionEconomics.context.text, sessionEconomics.context.tone),
|
|
897
|
+
)
|
|
898
|
+
}
|
|
899
|
+
if (limit5h) {
|
|
900
|
+
groups.push(metricGroup("limit-5h", "5H", limit5h.full, sourceTone(state, limit5h.segment)))
|
|
901
|
+
}
|
|
902
|
+
groups.push(
|
|
903
|
+
limitWeek
|
|
904
|
+
? metricGroup("limit-week", "WEEK", limitWeek.full, sourceTone(state, limitWeek.segment))
|
|
905
|
+
: metricGroup("week", "WEEK", sessionEconomics.week.text, sessionEconomics.week.tone),
|
|
906
|
+
...statuses,
|
|
907
|
+
)
|
|
908
|
+
const fitted = fitMediumGroups(groups, limit)
|
|
909
|
+
return { layout, width: limit, rows: [rowFromGroups("summary", fitted.groups, fitted.separator)] }
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
let groups = []
|
|
913
|
+
if (!state.unavailable && savings.save) {
|
|
914
|
+
groups.push(valueGroup("savings", savings.save.text, sourceTone(state, savings.save.segment)))
|
|
915
|
+
}
|
|
916
|
+
if (!promptRight && !state.unavailable && style) {
|
|
917
|
+
groups.unshift(valueGroup("style", style.text, sourceTone(state, style.segment)))
|
|
918
|
+
}
|
|
919
|
+
groups.push(valueGroup("cost", sessionEconomics.cost.text, sessionEconomics.cost.tone))
|
|
920
|
+
if (promptRight) groups.push(valueGroup("context", sessionEconomics.context.text, sessionEconomics.context.tone))
|
|
921
|
+
if (promptRight && limitWeek) {
|
|
922
|
+
groups.push(valueGroup("limit-week", limitWeek.percent, sourceTone(state, limitWeek.segment)))
|
|
923
|
+
}
|
|
924
|
+
if (statuses[0]?.id !== "live") groups.push(...statuses)
|
|
925
|
+
groups = fitNarrowGroups(
|
|
926
|
+
groups,
|
|
927
|
+
limit,
|
|
928
|
+
promptRight ? ["limit-week", "context", "cost", "savings"] : ["cost", "style", "savings"],
|
|
929
|
+
)
|
|
930
|
+
return { layout, width: limit, rows: [rowFromGroups("core", groups, " ")] }
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
export function renderStatuslineViewText(state, options = {}) {
|
|
934
|
+
return createStatuslineViewModel(state, options)
|
|
935
|
+
.rows.map((row) => row.parts.map((part) => part.text).join(""))
|
|
936
|
+
.join("\n")
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
export function renderStatuslineText(state, options = {}) {
|
|
940
|
+
return renderStatuslineViewText(state, options)
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
export function createRefreshScheduler({
|
|
944
|
+
run,
|
|
945
|
+
debounceMs = DEFAULT_DEBOUNCE_MS,
|
|
946
|
+
intervalMs = DEFAULT_INTERVAL_MS,
|
|
947
|
+
setTimeoutFn = setTimeout,
|
|
948
|
+
clearTimeoutFn = clearTimeout,
|
|
949
|
+
setIntervalFn = setInterval,
|
|
950
|
+
clearIntervalFn = clearInterval,
|
|
951
|
+
}) {
|
|
952
|
+
let started = false
|
|
953
|
+
let disposed = false
|
|
954
|
+
let queued = false
|
|
955
|
+
let debounce
|
|
956
|
+
let interval
|
|
957
|
+
let running
|
|
958
|
+
|
|
959
|
+
const execute = () => {
|
|
960
|
+
if (disposed) return Promise.resolve()
|
|
961
|
+
if (running) {
|
|
962
|
+
queued = true
|
|
963
|
+
return running
|
|
964
|
+
}
|
|
965
|
+
running = (async () => {
|
|
966
|
+
do {
|
|
967
|
+
queued = false
|
|
968
|
+
try {
|
|
969
|
+
await run()
|
|
970
|
+
} catch {}
|
|
971
|
+
} while (queued && !disposed)
|
|
972
|
+
})().finally(() => {
|
|
973
|
+
running = undefined
|
|
974
|
+
if (queued && !disposed) void execute()
|
|
975
|
+
})
|
|
976
|
+
return running
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
const clearDebounce = () => {
|
|
980
|
+
if (debounce === undefined) return
|
|
981
|
+
clearTimeoutFn(debounce)
|
|
982
|
+
debounce = undefined
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
const request = (immediate = false) => {
|
|
986
|
+
if (disposed) return
|
|
987
|
+
clearDebounce()
|
|
988
|
+
if (immediate) {
|
|
989
|
+
void execute()
|
|
990
|
+
return
|
|
991
|
+
}
|
|
992
|
+
debounce = setTimeoutFn(() => {
|
|
993
|
+
debounce = undefined
|
|
994
|
+
void execute()
|
|
995
|
+
}, Math.max(0, debounceMs))
|
|
996
|
+
debounce?.unref?.()
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
return {
|
|
1000
|
+
start() {
|
|
1001
|
+
if (started || disposed) return
|
|
1002
|
+
started = true
|
|
1003
|
+
request(true)
|
|
1004
|
+
if (intervalMs > 0) {
|
|
1005
|
+
interval = setIntervalFn(() => request(true), intervalMs)
|
|
1006
|
+
interval?.unref?.()
|
|
1007
|
+
}
|
|
1008
|
+
},
|
|
1009
|
+
request,
|
|
1010
|
+
flush() {
|
|
1011
|
+
clearDebounce()
|
|
1012
|
+
return execute()
|
|
1013
|
+
},
|
|
1014
|
+
dispose() {
|
|
1015
|
+
disposed = true
|
|
1016
|
+
clearDebounce()
|
|
1017
|
+
if (interval !== undefined) clearIntervalFn(interval)
|
|
1018
|
+
},
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
export function createStatuslineController({
|
|
1023
|
+
load,
|
|
1024
|
+
onState = () => {},
|
|
1025
|
+
debounceMs = DEFAULT_DEBOUNCE_MS,
|
|
1026
|
+
intervalMs = DEFAULT_INTERVAL_MS,
|
|
1027
|
+
timers = {},
|
|
1028
|
+
}) {
|
|
1029
|
+
let context = { cwd: "", session: "", width: 80, model: "" }
|
|
1030
|
+
let state = initialStatuslineState()
|
|
1031
|
+
let generation = 0
|
|
1032
|
+
let activeRefresh
|
|
1033
|
+
const lifetime = new AbortController()
|
|
1034
|
+
const scheduler = createRefreshScheduler({
|
|
1035
|
+
run: async () => {
|
|
1036
|
+
const snapshot = { ...context }
|
|
1037
|
+
const startedGeneration = generation
|
|
1038
|
+
const refresh = new AbortController()
|
|
1039
|
+
const abortRefresh = () => refresh.abort()
|
|
1040
|
+
activeRefresh = refresh
|
|
1041
|
+
lifetime.signal.addEventListener("abort", abortRefresh, { once: true })
|
|
1042
|
+
let payload
|
|
1043
|
+
try {
|
|
1044
|
+
payload = await load(snapshot, refresh.signal)
|
|
1045
|
+
} catch {}
|
|
1046
|
+
lifetime.signal.removeEventListener("abort", abortRefresh)
|
|
1047
|
+
if (activeRefresh === refresh) activeRefresh = undefined
|
|
1048
|
+
if (
|
|
1049
|
+
lifetime.signal.aborted ||
|
|
1050
|
+
refresh.signal.aborted ||
|
|
1051
|
+
startedGeneration !== generation ||
|
|
1052
|
+
snapshot.cwd !== context.cwd ||
|
|
1053
|
+
snapshot.session !== context.session ||
|
|
1054
|
+
snapshot.width !== context.width ||
|
|
1055
|
+
snapshot.model !== context.model
|
|
1056
|
+
) {
|
|
1057
|
+
return
|
|
1058
|
+
}
|
|
1059
|
+
state = nextStatuslineState(state, payload)
|
|
1060
|
+
try {
|
|
1061
|
+
onState(state)
|
|
1062
|
+
} catch {}
|
|
1063
|
+
},
|
|
1064
|
+
debounceMs,
|
|
1065
|
+
intervalMs,
|
|
1066
|
+
...timers,
|
|
1067
|
+
})
|
|
1068
|
+
|
|
1069
|
+
return {
|
|
1070
|
+
start: scheduler.start,
|
|
1071
|
+
request: scheduler.request,
|
|
1072
|
+
refreshNow: scheduler.flush,
|
|
1073
|
+
dispose() {
|
|
1074
|
+
activeRefresh?.abort()
|
|
1075
|
+
lifetime.abort()
|
|
1076
|
+
scheduler.dispose()
|
|
1077
|
+
},
|
|
1078
|
+
setContext(next) {
|
|
1079
|
+
const updated = {
|
|
1080
|
+
cwd: typeof next.cwd === "string" ? next.cwd : context.cwd,
|
|
1081
|
+
session: typeof next.session === "string" ? next.session : context.session,
|
|
1082
|
+
width: next.width === undefined ? context.width : normalizedWidth(next.width),
|
|
1083
|
+
model: typeof next.model === "string" ? next.model : context.model,
|
|
1084
|
+
}
|
|
1085
|
+
if (
|
|
1086
|
+
updated.cwd === context.cwd &&
|
|
1087
|
+
updated.session === context.session &&
|
|
1088
|
+
updated.width === context.width &&
|
|
1089
|
+
updated.model === context.model
|
|
1090
|
+
) {
|
|
1091
|
+
return
|
|
1092
|
+
}
|
|
1093
|
+
context = updated
|
|
1094
|
+
generation += 1
|
|
1095
|
+
activeRefresh?.abort()
|
|
1096
|
+
scheduler.request()
|
|
1097
|
+
},
|
|
1098
|
+
getState: () => state,
|
|
1099
|
+
getContext: () => ({ ...context }),
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
export function createKeyedControllerPool({ create }) {
|
|
1104
|
+
const entries = new Map()
|
|
1105
|
+
|
|
1106
|
+
const dispose = (entry) => {
|
|
1107
|
+
try {
|
|
1108
|
+
entry.value.dispose()
|
|
1109
|
+
} catch {}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
return {
|
|
1113
|
+
acquire(key) {
|
|
1114
|
+
let entry = entries.get(key)
|
|
1115
|
+
if (!entry) {
|
|
1116
|
+
entry = { value: create(key), refs: 0 }
|
|
1117
|
+
entries.set(key, entry)
|
|
1118
|
+
}
|
|
1119
|
+
entry.refs += 1
|
|
1120
|
+
let released = false
|
|
1121
|
+
return {
|
|
1122
|
+
value: entry.value,
|
|
1123
|
+
release() {
|
|
1124
|
+
if (released) return
|
|
1125
|
+
released = true
|
|
1126
|
+
entry.refs -= 1
|
|
1127
|
+
if (entry.refs > 0 || entries.get(key) !== entry) return
|
|
1128
|
+
entries.delete(key)
|
|
1129
|
+
dispose(entry)
|
|
1130
|
+
},
|
|
1131
|
+
}
|
|
1132
|
+
},
|
|
1133
|
+
get(key) {
|
|
1134
|
+
return entries.get(key)?.value
|
|
1135
|
+
},
|
|
1136
|
+
forEach(callback) {
|
|
1137
|
+
for (const [key, entry] of entries) callback(entry.value, key)
|
|
1138
|
+
},
|
|
1139
|
+
size: () => entries.size,
|
|
1140
|
+
dispose() {
|
|
1141
|
+
for (const entry of entries.values()) dispose(entry)
|
|
1142
|
+
entries.clear()
|
|
1143
|
+
},
|
|
1144
|
+
}
|
|
1145
|
+
}
|