@corbet-labs/ccht 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +307 -0
- package/LICENSE.md +25 -0
- package/LICENSES/GPL-3.0-only.txt +232 -0
- package/LICENSES/LGPL-3.0-only.txt +304 -0
- package/LICENSES/dependencies/agent-client-protocol-2.1.0/LICENSE +191 -0
- package/LICENSES/dependencies/agent-client-protocol-derive-2.1.0/LICENSE +191 -0
- package/LICENSES/dependencies/agent-client-protocol-schema-1.7.0/LICENSE +190 -0
- package/LICENSES/dependencies/android_system_properties-0.1.6/LICENSE-APACHE +13 -0
- package/LICENSES/dependencies/android_system_properties-0.1.6/LICENSE-MIT +20 -0
- package/LICENSES/dependencies/anyhow-1.0.104/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/anyhow-1.0.104/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/async-channel-2.5.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/async-channel-2.5.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/async-io-2.6.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/async-io-2.6.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/async-lock-3.4.2/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/async-lock-3.4.2/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/async-process-2.5.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/async-process-2.5.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/async-signal-0.2.14/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/async-signal-0.2.14/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/async-task-4.7.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/async-task-4.7.1/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/atomic-waker-1.1.2/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/atomic-waker-1.1.2/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/atomic-waker-1.1.2/LICENSE-THIRD-PARTY +45 -0
- package/LICENSES/dependencies/autocfg-1.5.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/autocfg-1.5.1/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/base64-0.22.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/base64-0.22.1/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/base64-0.23.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/base64-0.23.1/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/bitflags-1.3.2/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/bitflags-1.3.2/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/bitflags-2.13.2/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/bitflags-2.13.2/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/blocking-1.7.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/blocking-1.7.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/bs58-0.5.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/bs58-0.5.1/LICENSE-MIT +20 -0
- package/LICENSES/dependencies/bumpalo-3.20.3/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/bumpalo-3.20.3/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/cc-1.4.5/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/cc-1.4.5/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/cfg-if-1.0.4/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/cfg-if-1.0.4/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/chrono-0.4.45/LICENSE.txt +240 -0
- package/LICENSES/dependencies/concurrent-queue-2.5.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/concurrent-queue-2.5.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/convert_case-0.10.0/LICENSE +21 -0
- package/LICENSES/dependencies/core-foundation-sys-0.8.7/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/core-foundation-sys-0.8.7/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/crossbeam-deque-0.8.8/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/crossbeam-deque-0.8.8/LICENSE-MIT +27 -0
- package/LICENSES/dependencies/crossbeam-epoch-0.9.21/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/crossbeam-epoch-0.9.21/LICENSE-MIT +27 -0
- package/LICENSES/dependencies/crossbeam-utils-0.8.23/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/crossbeam-utils-0.8.23/LICENSE-MIT +27 -0
- package/LICENSES/dependencies/darling-0.24.1/LICENSE +21 -0
- package/LICENSES/dependencies/darling_core-0.24.1/LICENSE +21 -0
- package/LICENSES/dependencies/darling_macro-0.24.1/LICENSE +21 -0
- package/LICENSES/dependencies/defmt-1.1.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/defmt-1.1.1/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/defmt-macros-1.1.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/defmt-macros-1.1.1/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/defmt-parser-1.0.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/defmt-parser-1.0.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/deranged-0.5.8/LICENSE-Apache +202 -0
- package/LICENSES/dependencies/deranged-0.5.8/LICENSE-MIT +19 -0
- package/LICENSES/dependencies/derive_more-2.1.1/LICENSE +21 -0
- package/LICENSES/dependencies/derive_more-impl-2.1.1/LICENSE +21 -0
- package/LICENSES/dependencies/dyn-clone-1.0.20/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/dyn-clone-1.0.20/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/either-1.18.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/either-1.18.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/equivalent-1.0.2/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/equivalent-1.0.2/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/errno-0.3.14/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/errno-0.3.14/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/event-listener-5.4.2/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/event-listener-5.4.2/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/event-listener-strategy-0.5.4/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/event-listener-strategy-0.5.4/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/fallible-iterator-0.3.0/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/fallible-iterator-0.3.0/LICENSE-MIT +19 -0
- package/LICENSES/dependencies/fastrand-2.5.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/fastrand-2.5.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/find-msvc-tools-0.1.12/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/find-msvc-tools-0.1.12/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/fixedbitset-0.5.7/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/fixedbitset-0.5.7/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/foldhash-0.2.0/LICENSE +19 -0
- package/LICENSES/dependencies/futures-0.3.34/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/futures-0.3.34/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/futures-channel-0.3.34/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/futures-channel-0.3.34/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/futures-concurrency-7.7.1/LICENSE-APACHE +190 -0
- package/LICENSES/dependencies/futures-concurrency-7.7.1/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/futures-core-0.3.34/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/futures-core-0.3.34/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/futures-executor-0.3.34/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/futures-executor-0.3.34/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/futures-io-0.3.34/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/futures-io-0.3.34/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/futures-lite-2.6.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/futures-lite-2.6.1/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/futures-lite-2.6.1/LICENSE-THIRD-PARTY +45 -0
- package/LICENSES/dependencies/futures-macro-0.3.34/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/futures-macro-0.3.34/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/futures-sink-0.3.34/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/futures-sink-0.3.34/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/futures-task-0.3.34/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/futures-task-0.3.34/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/futures-util-0.3.34/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/futures-util-0.3.34/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/getrandom-0.4.3/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/getrandom-0.4.3/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/gimli-0.32.3/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/gimli-0.32.3/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/hashbrown-0.12.3/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/hashbrown-0.12.3/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/hashbrown-0.16.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/hashbrown-0.16.1/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/hashbrown-0.17.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/hashbrown-0.17.1/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/heck-0.5.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/heck-0.5.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/hermit-abi-0.5.3/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/hermit-abi-0.5.3/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/hex-0.4.3/LICENSE-APACHE +202 -0
- package/LICENSES/dependencies/hex-0.4.3/LICENSE-MIT +20 -0
- package/LICENSES/dependencies/iana-time-zone-0.1.65/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/iana-time-zone-0.1.65/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/iana-time-zone-haiku-0.1.2/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/iana-time-zone-haiku-0.1.2/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/id-arena-2.3.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/id-arena-2.3.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/ident_case-1.0.1/LICENSE +19 -0
- package/LICENSES/dependencies/indexmap-1.9.3/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/indexmap-1.9.3/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/indexmap-2.14.2/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/indexmap-2.14.2/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/itoa-1.0.18/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/itoa-1.0.18/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/jiff-0.2.35/COPYING +3 -0
- package/LICENSES/dependencies/jiff-0.2.35/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/jiff-0.2.35/UNLICENSE +24 -0
- package/LICENSES/dependencies/jiff-core-0.1.0/COPYING +3 -0
- package/LICENSES/dependencies/jiff-core-0.1.0/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/jiff-core-0.1.0/UNLICENSE +24 -0
- package/LICENSES/dependencies/jiff-static-0.2.35/COPYING +3 -0
- package/LICENSES/dependencies/jiff-static-0.2.35/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/jiff-static-0.2.35/UNLICENSE +24 -0
- package/LICENSES/dependencies/jiff-tzdb-0.1.8/COPYING +3 -0
- package/LICENSES/dependencies/jiff-tzdb-0.1.8/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/jiff-tzdb-0.1.8/UNLICENSE +24 -0
- package/LICENSES/dependencies/jiff-tzdb-platform-0.1.3/COPYING +3 -0
- package/LICENSES/dependencies/jiff-tzdb-platform-0.1.3/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/jiff-tzdb-platform-0.1.3/UNLICENSE +24 -0
- package/LICENSES/dependencies/js-sys-0.3.105/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/js-sys-0.3.105/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/leb128-0.2.7/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/leb128-0.2.7/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/leb128fmt-0.1.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/leb128fmt-0.1.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/libc-0.2.189/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/libc-0.2.189/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/COPYRIGHT +29 -0
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/log-0.4.34/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/log-0.4.34/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/memchr-2.8.3/COPYING +3 -0
- package/LICENSES/dependencies/memchr-2.8.3/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/memchr-2.8.3/UNLICENSE +24 -0
- package/LICENSES/dependencies/mio-1.2.3/LICENSE +19 -0
- package/LICENSES/dependencies/num-conv-0.2.2/LICENSE-Apache +177 -0
- package/LICENSES/dependencies/num-conv-0.2.2/LICENSE-MIT +19 -0
- package/LICENSES/dependencies/num-traits-0.2.19/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/num-traits-0.2.19/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/once_cell-1.21.4/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/once_cell-1.21.4/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/parking-2.2.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/parking-2.2.1/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/parking-2.2.1/LICENSE-THIRD-PARTY +9 -0
- package/LICENSES/dependencies/pin-project-1.1.13/LICENSE-APACHE +177 -0
- package/LICENSES/dependencies/pin-project-1.1.13/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/pin-project-internal-1.1.13/LICENSE-APACHE +177 -0
- package/LICENSES/dependencies/pin-project-internal-1.1.13/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/pin-project-lite-0.2.17/LICENSE-APACHE +177 -0
- package/LICENSES/dependencies/pin-project-lite-0.2.17/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/piper-0.2.5/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/piper-0.2.5/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/polling-3.11.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/polling-3.11.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/portable-atomic-1.15.0/LICENSE-APACHE +177 -0
- package/LICENSES/dependencies/portable-atomic-1.15.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/portable-atomic-util-0.2.8/LICENSE-APACHE +177 -0
- package/LICENSES/dependencies/portable-atomic-util-0.2.8/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/powerfmt-0.2.0/LICENSE-Apache +202 -0
- package/LICENSES/dependencies/powerfmt-0.2.0/LICENSE-MIT +19 -0
- package/LICENSES/dependencies/proc-macro2-1.0.107/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/proc-macro2-1.0.107/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/quote-1.0.47/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/quote-1.0.47/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/r-efi-6.0.0/AUTHORS +75 -0
- package/LICENSES/dependencies/rayon-1.12.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/rayon-1.12.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/rayon-core-1.13.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/rayon-core-1.13.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/ref-cast-1.0.27/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/ref-cast-1.0.27/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/ref-cast-impl-1.0.27/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/ref-cast-impl-1.0.27/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/rustc-demangle-0.1.28/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/rustc-demangle-0.1.28/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/rustc-hash-2.1.3/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/rustc-hash-2.1.3/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/rustc_version-0.4.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/rustc_version-0.4.1/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/rustix-1.1.4/COPYRIGHT +29 -0
- package/LICENSES/dependencies/rustix-1.1.4/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/rustix-1.1.4/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
- package/LICENSES/dependencies/rustix-1.1.4/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/rustversion-1.0.23/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/rustversion-1.0.23/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/schemars-0.9.0/LICENSE +21 -0
- package/LICENSES/dependencies/schemars-1.2.2/LICENSE +21 -0
- package/LICENSES/dependencies/schemars_derive-1.2.2/LICENSE +21 -0
- package/LICENSES/dependencies/semver-1.0.28/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/semver-1.0.28/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/serde-1.0.229/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/serde-1.0.229/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/serde_core-1.0.229/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/serde_core-1.0.229/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/serde_derive-1.0.229/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/serde_derive-1.0.229/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/serde_derive_internals-0.30.0/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/serde_derive_internals-0.30.0/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/serde_json-1.0.151/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/serde_json-1.0.151/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/serde_with-3.23.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/serde_with-3.23.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/serde_with_macros-3.23.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/serde_with_macros-3.23.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/shell-words-1.1.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/shell-words-1.1.1/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/shlex-2.0.1/LICENSE-APACHE +13 -0
- package/LICENSES/dependencies/shlex-2.0.1/LICENSE-MIT +21 -0
- package/LICENSES/dependencies/signal-hook-registry-1.4.8/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/signal-hook-registry-1.4.8/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/slab-0.4.12/LICENSE +25 -0
- package/LICENSES/dependencies/smallvec-1.16.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/smallvec-1.16.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/socket2-0.6.5/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/socket2-0.6.5/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/stable_deref_trait-1.2.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/stable_deref_trait-1.2.1/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/strsim-0.11.1/LICENSE +23 -0
- package/LICENSES/dependencies/strum-0.28.0/LICENSE +21 -0
- package/LICENSES/dependencies/strum_macros-0.28.0/LICENSE +21 -0
- package/LICENSES/dependencies/syn-2.0.119/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/syn-2.0.119/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/syn-3.0.5/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/syn-3.0.5/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/thiserror-2.0.20/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/thiserror-2.0.20/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/thiserror-impl-2.0.20/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/thiserror-impl-2.0.20/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/time-0.3.55/LICENSE-Apache +177 -0
- package/LICENSES/dependencies/time-0.3.55/LICENSE-MIT +19 -0
- package/LICENSES/dependencies/time-core-0.1.9/LICENSE-Apache +177 -0
- package/LICENSES/dependencies/time-core-0.1.9/LICENSE-MIT +19 -0
- package/LICENSES/dependencies/time-macros-0.2.32/LICENSE-Apache +177 -0
- package/LICENSES/dependencies/time-macros-0.2.32/LICENSE-MIT +19 -0
- package/LICENSES/dependencies/tinyvec-1.13.2/LICENSE-APACHE.md +202 -0
- package/LICENSES/dependencies/tinyvec-1.13.2/LICENSE-MIT.md +5 -0
- package/LICENSES/dependencies/tinyvec-1.13.2/LICENSE-ZLIB.md +11 -0
- package/LICENSES/dependencies/tinyvec_macros-0.1.1/LICENSE-APACHE.md +202 -0
- package/LICENSES/dependencies/tinyvec_macros-0.1.1/LICENSE-MIT.md +21 -0
- package/LICENSES/dependencies/tinyvec_macros-0.1.1/LICENSE-ZLIB.md +20 -0
- package/LICENSES/dependencies/tokio-1.53.1/LICENSE +21 -0
- package/LICENSES/dependencies/tokio-macros-2.7.2/LICENSE +22 -0
- package/LICENSES/dependencies/tracing-0.1.44/LICENSE +25 -0
- package/LICENSES/dependencies/tracing-attributes-0.1.31/LICENSE +25 -0
- package/LICENSES/dependencies/tracing-core-0.1.36/LICENSE +25 -0
- package/LICENSES/dependencies/unicode-ident-1.0.24/LICENSE-APACHE +176 -0
- package/LICENSES/dependencies/unicode-ident-1.0.24/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/unicode-ident-1.0.24/LICENSE-UNICODE +39 -0
- package/LICENSES/dependencies/unicode-segmentation-1.13.3/COPYRIGHT +7 -0
- package/LICENSES/dependencies/unicode-segmentation-1.13.3/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/unicode-segmentation-1.13.3/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/unicode-xid-0.2.6/COPYRIGHT +7 -0
- package/LICENSES/dependencies/unicode-xid-0.2.6/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/unicode-xid-0.2.6/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/uuid-1.26.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/uuid-1.26.1/LICENSE-MIT +26 -0
- package/LICENSES/dependencies/walrus-0.26.5/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/walrus-0.26.5/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/walrus-macro-0.26.0/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/walrus-macro-0.26.0/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
- package/LICENSES/dependencies/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/wasm-bindgen-0.2.128/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/wasm-bindgen-0.2.128/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/wasm-bindgen-cli-support-0.2.128/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/wasm-bindgen-cli-support-0.2.128/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/wasm-bindgen-macro-0.2.128/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/wasm-bindgen-macro-0.2.128/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/wasm-bindgen-macro-support-0.2.128/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/wasm-bindgen-macro-support-0.2.128/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/wasm-bindgen-shared-0.2.128/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/wasm-bindgen-shared-0.2.128/LICENSE-MIT +25 -0
- package/LICENSES/dependencies/wasm-encoder-0.245.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/wasm-encoder-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
- package/LICENSES/dependencies/wasm-encoder-0.245.1/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/wasmparser-0.245.1/LICENSE-APACHE +201 -0
- package/LICENSES/dependencies/wasmparser-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
- package/LICENSES/dependencies/wasmparser-0.245.1/LICENSE-MIT +23 -0
- package/LICENSES/dependencies/windows-core-0.62.2/license-apache-2.0 +201 -0
- package/LICENSES/dependencies/windows-core-0.62.2/license-mit +21 -0
- package/LICENSES/dependencies/windows-implement-0.60.2/license-apache-2.0 +201 -0
- package/LICENSES/dependencies/windows-implement-0.60.2/license-mit +21 -0
- package/LICENSES/dependencies/windows-interface-0.59.3/license-apache-2.0 +201 -0
- package/LICENSES/dependencies/windows-interface-0.59.3/license-mit +21 -0
- package/LICENSES/dependencies/windows-link-0.2.1/license-apache-2.0 +201 -0
- package/LICENSES/dependencies/windows-link-0.2.1/license-mit +21 -0
- package/LICENSES/dependencies/windows-result-0.4.1/license-apache-2.0 +201 -0
- package/LICENSES/dependencies/windows-result-0.4.1/license-mit +21 -0
- package/LICENSES/dependencies/windows-strings-0.5.1/license-apache-2.0 +201 -0
- package/LICENSES/dependencies/windows-strings-0.5.1/license-mit +21 -0
- package/LICENSES/dependencies/windows-sys-0.61.2/license-apache-2.0 +201 -0
- package/LICENSES/dependencies/windows-sys-0.61.2/license-mit +21 -0
- package/LICENSES/dependencies/zmij-1.0.23/LICENSE-MIT +23 -0
- package/README.md +185 -0
- package/THIRD-PARTY.md +45 -0
- package/index.d.ts +47 -0
- package/index.js +28 -0
- package/package.json +36 -0
- package/source/.cargo/config.toml +5 -0
- package/source/.ci/upstream-notices/PROVENANCE.json +198 -0
- package/source/.ci/upstream-notices/agent-client-protocol-2.1.0/LICENSE +191 -0
- package/source/.ci/upstream-notices/agent-client-protocol-derive-2.1.0/LICENSE +191 -0
- package/source/.ci/upstream-notices/agent-client-protocol-schema-1.7.0/LICENSE +190 -0
- package/source/.ci/upstream-notices/defmt-parser-1.0.0/LICENSE-APACHE +201 -0
- package/source/.ci/upstream-notices/defmt-parser-1.0.0/LICENSE-MIT +25 -0
- package/source/.ci/upstream-notices/r-efi-6.0.0/AUTHORS +75 -0
- package/source/.ci/upstream-notices/wasm-encoder-0.245.1/LICENSE-APACHE +201 -0
- package/source/.ci/upstream-notices/wasm-encoder-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
- package/source/.ci/upstream-notices/wasm-encoder-0.245.1/LICENSE-MIT +23 -0
- package/source/.ci/upstream-notices/wasmparser-0.245.1/LICENSE-APACHE +201 -0
- package/source/.ci/upstream-notices/wasmparser-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
- package/source/.ci/upstream-notices/wasmparser-0.245.1/LICENSE-MIT +23 -0
- package/source/.ci/wasm-bundle/Cargo.toml +10 -0
- package/source/.ci/wasm-bundle/src/main.rs +17 -0
- package/source/CHANGELOG.md +11 -0
- package/source/Cargo.lock +1622 -0
- package/source/Cargo.toml +48 -0
- package/source/LICENSE +307 -0
- package/source/LICENSE.md +25 -0
- package/source/LICENSES/GPL-3.0-only.txt +232 -0
- package/source/LICENSES/LGPL-3.0-only.txt +304 -0
- package/source/README.md +185 -0
- package/source/THIRD-PARTY.md +45 -0
- package/source/dependencies.tar.gz +0 -0
- package/source/examples/native.rs +45 -0
- package/source/src/conversation.rs +557 -0
- package/source/src/lib.rs +27 -0
- package/source/src/native/client.rs +417 -0
- package/source/src/native/fixture.py +104 -0
- package/source/src/native/mod.rs +249 -0
- package/source/src/native/session.rs +541 -0
- package/source/src/native/tests.rs +427 -0
- package/source/src/web.rs +35 -0
- package/wasm/ccht.d.ts +60 -0
- package/wasm/ccht.js +275 -0
- package/wasm/ccht_bg.wasm +0 -0
- package/wasm/ccht_bg.wasm.d.ts +13 -0
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
//! Platform-independent conversation events and rendering state.
|
|
2
|
+
|
|
3
|
+
use std::collections::BTreeMap;
|
|
4
|
+
|
|
5
|
+
use serde::{Deserialize, Serialize};
|
|
6
|
+
use thiserror::Error;
|
|
7
|
+
|
|
8
|
+
use crate::acp;
|
|
9
|
+
|
|
10
|
+
/// Version of the application-facing event envelope.
|
|
11
|
+
pub const WIRE_VERSION: u16 = 1;
|
|
12
|
+
/// Maximum accepted serialized event size.
|
|
13
|
+
pub const MAX_EVENT_BYTES: usize = 1024 * 1024;
|
|
14
|
+
const MAX_TURNS: usize = 256;
|
|
15
|
+
const MAX_TURN_BYTES: usize = 8 * 1024 * 1024;
|
|
16
|
+
|
|
17
|
+
/// A prompt whose correlation identity is assigned by the application.
|
|
18
|
+
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
19
|
+
pub struct Prompt {
|
|
20
|
+
/// Unique identity for this delivery attempt. Never reuse it to retry an uncertain delivery.
|
|
21
|
+
pub request_id: String,
|
|
22
|
+
/// Official ACP content blocks, including any application-owned context.
|
|
23
|
+
pub content: Vec<acp::ContentBlock>,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
impl Prompt {
|
|
27
|
+
/// Construct a plain-text prompt.
|
|
28
|
+
pub fn text(request_id: impl Into<String>, text: impl Into<String>) -> Self {
|
|
29
|
+
Self {
|
|
30
|
+
request_id: request_id.into(),
|
|
31
|
+
content: vec![acp::ContentBlock::from(text.into())],
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// A native session event. Events during history loading have no active request.
|
|
37
|
+
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
38
|
+
pub struct SessionEvent {
|
|
39
|
+
/// Application request identity, when a prompt is active.
|
|
40
|
+
pub request_id: Option<String>,
|
|
41
|
+
/// Structured event payload.
|
|
42
|
+
pub event: Event,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// Shared event payload. Upstream ACP types preserve tool and capability details.
|
|
46
|
+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
47
|
+
#[serde(tag = "kind", rename_all = "snake_case")]
|
|
48
|
+
pub enum Event {
|
|
49
|
+
/// Agent output, tools, plans, usage, or session configuration.
|
|
50
|
+
Update {
|
|
51
|
+
/// Original typed ACP update.
|
|
52
|
+
update: acp::SessionUpdate,
|
|
53
|
+
},
|
|
54
|
+
/// A permission decision is required from the application's authority.
|
|
55
|
+
Permission {
|
|
56
|
+
/// Identity of the pending permission request, not the prompt identity.
|
|
57
|
+
request_id: String,
|
|
58
|
+
/// The options and tool activity reported by the agent.
|
|
59
|
+
request: acp::RequestPermissionRequest,
|
|
60
|
+
},
|
|
61
|
+
/// The prompt finished. Cancellation and refusal remain distinct reasons.
|
|
62
|
+
Completed {
|
|
63
|
+
/// Agent-reported terminal reason.
|
|
64
|
+
stop_reason: acp::StopReason,
|
|
65
|
+
},
|
|
66
|
+
/// A terminal failure with a safe, application-facing description.
|
|
67
|
+
Error {
|
|
68
|
+
/// Stable failure category.
|
|
69
|
+
code: String,
|
|
70
|
+
/// Sanitized description; never raw credentials or process output.
|
|
71
|
+
message: String,
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// An application-authorized event suitable for persistence, SSE or other transports.
|
|
76
|
+
///
|
|
77
|
+
/// Sequence numbers start at one and increase within each request. They are not
|
|
78
|
+
/// a database cursor. Applications authenticate/authorize the conversation before
|
|
79
|
+
/// handing events to a consumer; this envelope is not an authorization mechanism.
|
|
80
|
+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
81
|
+
pub struct WireEvent {
|
|
82
|
+
/// Protocol version, currently one.
|
|
83
|
+
pub version: u16,
|
|
84
|
+
/// Application-owned conversation identity, including role isolation where needed.
|
|
85
|
+
pub conversation_id: String,
|
|
86
|
+
/// Application-owned prompt/delivery identity.
|
|
87
|
+
pub request_id: String,
|
|
88
|
+
/// Contiguous sequence number within the request, starting at one.
|
|
89
|
+
pub sequence: u64,
|
|
90
|
+
/// Shared structured event.
|
|
91
|
+
pub event: Event,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
impl WireEvent {
|
|
95
|
+
/// Wrap an event with its application-owned routing and ordering identity.
|
|
96
|
+
pub fn new(
|
|
97
|
+
conversation_id: impl Into<String>,
|
|
98
|
+
request_id: impl Into<String>,
|
|
99
|
+
sequence: u64,
|
|
100
|
+
event: Event,
|
|
101
|
+
) -> Self {
|
|
102
|
+
Self {
|
|
103
|
+
version: WIRE_VERSION,
|
|
104
|
+
conversation_id: conversation_id.into(),
|
|
105
|
+
request_id: request_id.into(),
|
|
106
|
+
sequence,
|
|
107
|
+
event,
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/// An unresolved permission prompt. Rendering this does not authorize the action.
|
|
113
|
+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
114
|
+
pub struct PendingPermission {
|
|
115
|
+
/// Native permission-request identity.
|
|
116
|
+
pub request_id: String,
|
|
117
|
+
/// Original request and the allowed response options.
|
|
118
|
+
pub request: acp::RequestPermissionRequest,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// Conversation processing failure. Rejected events do not mutate the snapshot.
|
|
122
|
+
#[derive(Clone, Debug, Error, PartialEq, Eq)]
|
|
123
|
+
pub enum ConversationError {
|
|
124
|
+
/// The producer speaks an unsupported envelope version.
|
|
125
|
+
#[error("unsupported ccht event version")]
|
|
126
|
+
Version,
|
|
127
|
+
/// The event belongs to a different conversation.
|
|
128
|
+
#[error("event belongs to another conversation")]
|
|
129
|
+
Scope,
|
|
130
|
+
/// A request identifier or sequence is invalid.
|
|
131
|
+
#[error("request identity and positive sequence are required")]
|
|
132
|
+
Identity,
|
|
133
|
+
/// A cursor skipped an event. The application must replay the missing event.
|
|
134
|
+
#[error("event sequence has a gap; replay the missing events")]
|
|
135
|
+
Gap,
|
|
136
|
+
/// An event arrived after the request was terminal.
|
|
137
|
+
#[error("request is already terminal")]
|
|
138
|
+
Terminal,
|
|
139
|
+
/// A bounded event or conversation exceeded its capacity.
|
|
140
|
+
#[error("conversation capacity exceeded")]
|
|
141
|
+
Capacity,
|
|
142
|
+
/// The event is not valid ccht JSON.
|
|
143
|
+
#[error("invalid ccht event JSON")]
|
|
144
|
+
Json,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/// Renderable state for one prompt, shared between web and native consumers.
|
|
148
|
+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
149
|
+
pub struct TurnState {
|
|
150
|
+
/// Application-owned request identity.
|
|
151
|
+
pub request_id: String,
|
|
152
|
+
/// Last applied event sequence.
|
|
153
|
+
pub last_sequence: u64,
|
|
154
|
+
/// Accumulated assistant text.
|
|
155
|
+
pub text: String,
|
|
156
|
+
/// User text supplied by upstream history replay, if any.
|
|
157
|
+
pub user_text: String,
|
|
158
|
+
/// Non-text user content from history replay, preserved separately by role.
|
|
159
|
+
pub user_content: Vec<acp::ContentBlock>,
|
|
160
|
+
/// Separately reported thought text; applications choose whether to display it.
|
|
161
|
+
pub thought_text: String,
|
|
162
|
+
/// Non-text thought content, preserved separately from visible assistant output.
|
|
163
|
+
pub thought_content: Vec<acp::ContentBlock>,
|
|
164
|
+
/// Non-text assistant content, preserved without flattening.
|
|
165
|
+
pub content: Vec<acp::ContentBlock>,
|
|
166
|
+
/// Current tool calls, including updates to their content and status.
|
|
167
|
+
pub tools: BTreeMap<String, acp::ToolCall>,
|
|
168
|
+
/// Unresolved permission requests.
|
|
169
|
+
pub permissions: Vec<PendingPermission>,
|
|
170
|
+
/// Latest other update of each ACP type, preserving plans/configuration/usage.
|
|
171
|
+
pub updates: BTreeMap<String, serde_json::Value>,
|
|
172
|
+
/// `streaming`, `awaiting_permission`, `completed`, `cancelled`, `refused`, or `failed`.
|
|
173
|
+
pub status: String,
|
|
174
|
+
/// Exact upstream terminal reason.
|
|
175
|
+
pub stop_reason: Option<acp::StopReason>,
|
|
176
|
+
/// Safe terminal error details.
|
|
177
|
+
pub error: Option<serde_json::Value>,
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
impl TurnState {
|
|
181
|
+
fn new(request_id: String) -> Self {
|
|
182
|
+
Self {
|
|
183
|
+
request_id,
|
|
184
|
+
last_sequence: 0,
|
|
185
|
+
text: String::new(),
|
|
186
|
+
user_text: String::new(),
|
|
187
|
+
user_content: Vec::new(),
|
|
188
|
+
thought_text: String::new(),
|
|
189
|
+
thought_content: Vec::new(),
|
|
190
|
+
content: Vec::new(),
|
|
191
|
+
tools: BTreeMap::new(),
|
|
192
|
+
permissions: Vec::new(),
|
|
193
|
+
updates: BTreeMap::new(),
|
|
194
|
+
status: "streaming".into(),
|
|
195
|
+
stop_reason: None,
|
|
196
|
+
error: None,
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
fn update(&mut self, update: acp::SessionUpdate) -> Result<(), ConversationError> {
|
|
201
|
+
match update {
|
|
202
|
+
acp::SessionUpdate::AgentMessageChunk(chunk) => match chunk.content {
|
|
203
|
+
acp::ContentBlock::Text(text) => self.text.push_str(&text.text),
|
|
204
|
+
other => self.content.push(other),
|
|
205
|
+
},
|
|
206
|
+
acp::SessionUpdate::UserMessageChunk(chunk) => match chunk.content {
|
|
207
|
+
acp::ContentBlock::Text(text) => self.user_text.push_str(&text.text),
|
|
208
|
+
other => self.user_content.push(other),
|
|
209
|
+
},
|
|
210
|
+
acp::SessionUpdate::AgentThoughtChunk(chunk) => match chunk.content {
|
|
211
|
+
acp::ContentBlock::Text(text) => self.thought_text.push_str(&text.text),
|
|
212
|
+
other => self.thought_content.push(other),
|
|
213
|
+
},
|
|
214
|
+
acp::SessionUpdate::ToolCall(call) => {
|
|
215
|
+
self.tools.insert(call.tool_call_id.to_string(), call);
|
|
216
|
+
}
|
|
217
|
+
acp::SessionUpdate::ToolCallUpdate(update) => {
|
|
218
|
+
let id = update.tool_call_id.to_string();
|
|
219
|
+
let call = self.tools.entry(id).or_insert_with(|| {
|
|
220
|
+
acp::ToolCall::new(update.tool_call_id.clone(), "Tool activity")
|
|
221
|
+
});
|
|
222
|
+
let fields = update.fields;
|
|
223
|
+
if let Some(v) = fields.title {
|
|
224
|
+
call.title = v;
|
|
225
|
+
}
|
|
226
|
+
if let Some(v) = fields.kind {
|
|
227
|
+
call.kind = v;
|
|
228
|
+
}
|
|
229
|
+
if let Some(v) = fields.status {
|
|
230
|
+
call.status = v;
|
|
231
|
+
}
|
|
232
|
+
if let Some(v) = fields.content {
|
|
233
|
+
call.content = v;
|
|
234
|
+
}
|
|
235
|
+
if let Some(v) = fields.locations {
|
|
236
|
+
call.locations = v;
|
|
237
|
+
}
|
|
238
|
+
if let Some(v) = fields.raw_input {
|
|
239
|
+
call.raw_input = Some(v);
|
|
240
|
+
}
|
|
241
|
+
if let Some(v) = fields.raw_output {
|
|
242
|
+
call.raw_output = Some(v);
|
|
243
|
+
}
|
|
244
|
+
if matches!(
|
|
245
|
+
call.status,
|
|
246
|
+
acp::ToolCallStatus::Completed | acp::ToolCallStatus::Failed
|
|
247
|
+
) {
|
|
248
|
+
self.permissions
|
|
249
|
+
.retain(|p| p.request.tool_call.tool_call_id != call.tool_call_id);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
other => {
|
|
253
|
+
let value = serde_json::to_value(other).map_err(|_| ConversationError::Json)?;
|
|
254
|
+
let key = value
|
|
255
|
+
.get("sessionUpdate")
|
|
256
|
+
.and_then(|v| v.as_str())
|
|
257
|
+
.unwrap_or("unknown")
|
|
258
|
+
.to_owned();
|
|
259
|
+
self.updates.insert(key, value);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
self.status = if self.permissions.is_empty() {
|
|
263
|
+
"streaming"
|
|
264
|
+
} else {
|
|
265
|
+
"awaiting_permission"
|
|
266
|
+
}
|
|
267
|
+
.into();
|
|
268
|
+
Ok(())
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/// Bounded, deterministic conversation state. It owns no network, database or UI.
|
|
273
|
+
#[derive(Clone, Debug, PartialEq, Serialize)]
|
|
274
|
+
pub struct Conversation {
|
|
275
|
+
conversation_id: String,
|
|
276
|
+
turns: Vec<TurnState>,
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
impl Conversation {
|
|
280
|
+
/// Create an empty conversation for one application-owned identity.
|
|
281
|
+
pub fn new(conversation_id: impl Into<String>) -> Self {
|
|
282
|
+
Self {
|
|
283
|
+
conversation_id: conversation_id.into(),
|
|
284
|
+
turns: Vec::new(),
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/// Application-owned identity of this conversation.
|
|
289
|
+
pub fn id(&self) -> &str {
|
|
290
|
+
&self.conversation_id
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/// Ordered render state, independent of any frontend framework.
|
|
294
|
+
pub fn turns(&self) -> &[TurnState] {
|
|
295
|
+
&self.turns
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/// Serialize the render state for a browser or another transport.
|
|
299
|
+
pub fn snapshot_json(&self) -> Result<String, ConversationError> {
|
|
300
|
+
serde_json::to_string(self).map_err(|_| ConversationError::Json)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/// Parse and apply a bounded JSON envelope. Duplicate events return false.
|
|
304
|
+
pub fn apply_json(&mut self, json: &str) -> Result<bool, ConversationError> {
|
|
305
|
+
if json.len() > MAX_EVENT_BYTES {
|
|
306
|
+
return Err(ConversationError::Capacity);
|
|
307
|
+
}
|
|
308
|
+
self.apply(serde_json::from_str(json).map_err(|_| ConversationError::Json)?)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/// Apply exactly one ordered event. Duplicate/replayed events return false.
|
|
312
|
+
///
|
|
313
|
+
/// Gaps, scope mismatches and new events after completion fail explicitly.
|
|
314
|
+
/// Applications retain the source event log and replay it on reconnection.
|
|
315
|
+
pub fn apply(&mut self, wire: WireEvent) -> Result<bool, ConversationError> {
|
|
316
|
+
if wire.version != WIRE_VERSION {
|
|
317
|
+
return Err(ConversationError::Version);
|
|
318
|
+
}
|
|
319
|
+
if self.conversation_id.is_empty() || wire.conversation_id != self.conversation_id {
|
|
320
|
+
return Err(ConversationError::Scope);
|
|
321
|
+
}
|
|
322
|
+
if wire.request_id.is_empty() || wire.sequence == 0 {
|
|
323
|
+
return Err(ConversationError::Identity);
|
|
324
|
+
}
|
|
325
|
+
let index = self
|
|
326
|
+
.turns
|
|
327
|
+
.iter()
|
|
328
|
+
.position(|t| t.request_id == wire.request_id);
|
|
329
|
+
if let Some(i) = index {
|
|
330
|
+
if wire.sequence <= self.turns[i].last_sequence {
|
|
331
|
+
return Ok(false);
|
|
332
|
+
}
|
|
333
|
+
if self.turns[i].stop_reason.is_some() || self.turns[i].error.is_some() {
|
|
334
|
+
return Err(ConversationError::Terminal);
|
|
335
|
+
}
|
|
336
|
+
} else if self.turns.len() >= MAX_TURNS {
|
|
337
|
+
return Err(ConversationError::Capacity);
|
|
338
|
+
}
|
|
339
|
+
let mut turn = index
|
|
340
|
+
.map(|i| self.turns[i].clone())
|
|
341
|
+
.unwrap_or_else(|| TurnState::new(wire.request_id));
|
|
342
|
+
if wire.sequence != turn.last_sequence + 1 {
|
|
343
|
+
return Err(ConversationError::Gap);
|
|
344
|
+
}
|
|
345
|
+
if serde_json::to_vec(&wire.event)
|
|
346
|
+
.map_err(|_| ConversationError::Json)?
|
|
347
|
+
.len()
|
|
348
|
+
> MAX_EVENT_BYTES
|
|
349
|
+
{
|
|
350
|
+
return Err(ConversationError::Capacity);
|
|
351
|
+
}
|
|
352
|
+
match wire.event {
|
|
353
|
+
Event::Update { update } => turn.update(update)?,
|
|
354
|
+
Event::Permission {
|
|
355
|
+
request_id,
|
|
356
|
+
request,
|
|
357
|
+
} => {
|
|
358
|
+
if !turn.permissions.iter().any(|p| p.request_id == request_id) {
|
|
359
|
+
turn.permissions.push(PendingPermission {
|
|
360
|
+
request_id,
|
|
361
|
+
request,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
turn.status = "awaiting_permission".into();
|
|
365
|
+
}
|
|
366
|
+
Event::Completed { stop_reason } => {
|
|
367
|
+
turn.status = match stop_reason {
|
|
368
|
+
acp::StopReason::Cancelled => "cancelled",
|
|
369
|
+
acp::StopReason::Refusal => "refused",
|
|
370
|
+
_ => "completed",
|
|
371
|
+
}
|
|
372
|
+
.into();
|
|
373
|
+
turn.stop_reason = Some(stop_reason);
|
|
374
|
+
turn.permissions.clear();
|
|
375
|
+
}
|
|
376
|
+
Event::Error { code, message } => {
|
|
377
|
+
turn.status = "failed".into();
|
|
378
|
+
turn.error = Some(serde_json::json!({"code":code,"message":message}));
|
|
379
|
+
turn.permissions.clear();
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
turn.last_sequence = wire.sequence;
|
|
383
|
+
if serde_json::to_vec(&turn)
|
|
384
|
+
.map_err(|_| ConversationError::Json)?
|
|
385
|
+
.len()
|
|
386
|
+
> MAX_TURN_BYTES
|
|
387
|
+
{
|
|
388
|
+
return Err(ConversationError::Capacity);
|
|
389
|
+
}
|
|
390
|
+
match index {
|
|
391
|
+
Some(i) => self.turns[i] = turn,
|
|
392
|
+
None => self.turns.push(turn),
|
|
393
|
+
}
|
|
394
|
+
Ok(true)
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
#[cfg(test)]
|
|
399
|
+
mod tests {
|
|
400
|
+
use super::*;
|
|
401
|
+
|
|
402
|
+
fn delta(conversation: &str, request: &str, sequence: u64, text: &str) -> WireEvent {
|
|
403
|
+
WireEvent::new(
|
|
404
|
+
conversation,
|
|
405
|
+
request,
|
|
406
|
+
sequence,
|
|
407
|
+
Event::Update {
|
|
408
|
+
update: acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk::new(text.into())),
|
|
409
|
+
},
|
|
410
|
+
)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
#[test]
|
|
414
|
+
fn isolated_conversations_and_idempotent_replay() {
|
|
415
|
+
let mut creator = Conversation::new("creator");
|
|
416
|
+
let mut critic = Conversation::new("critic");
|
|
417
|
+
let first = delta("creator", "r1", 1, "Hello");
|
|
418
|
+
assert!(creator.apply(first.clone()).unwrap());
|
|
419
|
+
assert!(!creator.apply(first.clone()).unwrap());
|
|
420
|
+
assert_eq!(critic.apply(first), Err(ConversationError::Scope));
|
|
421
|
+
assert!(critic.turns().is_empty());
|
|
422
|
+
creator.apply(delta("creator", "r1", 2, " world")).unwrap();
|
|
423
|
+
assert_eq!(creator.turns()[0].text, "Hello world");
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
#[test]
|
|
427
|
+
fn gaps_and_late_updates_do_not_mutate_state() {
|
|
428
|
+
let mut conversation = Conversation::new("c");
|
|
429
|
+
assert_eq!(
|
|
430
|
+
conversation.apply(delta("c", "r", 2, "lost")),
|
|
431
|
+
Err(ConversationError::Gap)
|
|
432
|
+
);
|
|
433
|
+
assert!(conversation.turns().is_empty());
|
|
434
|
+
conversation.apply(delta("c", "r", 1, "partial")).unwrap();
|
|
435
|
+
conversation
|
|
436
|
+
.apply(WireEvent::new(
|
|
437
|
+
"c",
|
|
438
|
+
"r",
|
|
439
|
+
2,
|
|
440
|
+
Event::Completed {
|
|
441
|
+
stop_reason: acp::StopReason::Cancelled,
|
|
442
|
+
},
|
|
443
|
+
))
|
|
444
|
+
.unwrap();
|
|
445
|
+
let before = conversation.snapshot_json().unwrap();
|
|
446
|
+
assert_eq!(
|
|
447
|
+
conversation.apply(delta("c", "r", 3, "late")),
|
|
448
|
+
Err(ConversationError::Terminal)
|
|
449
|
+
);
|
|
450
|
+
assert_eq!(before, conversation.snapshot_json().unwrap());
|
|
451
|
+
assert_eq!(conversation.turns()[0].status, "cancelled");
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
#[test]
|
|
455
|
+
fn non_text_content_preserves_user_assistant_and_thought_roles() {
|
|
456
|
+
let mut conversation = Conversation::new("c");
|
|
457
|
+
let image: acp::ContentBlock = serde_json::from_value(serde_json::json!({
|
|
458
|
+
"type": "image", "data": "aW1hZ2U=", "mimeType": "image/png"
|
|
459
|
+
}))
|
|
460
|
+
.unwrap();
|
|
461
|
+
for (sequence, update) in [
|
|
462
|
+
(
|
|
463
|
+
1,
|
|
464
|
+
acp::SessionUpdate::UserMessageChunk(acp::ContentChunk::new(image.clone())),
|
|
465
|
+
),
|
|
466
|
+
(
|
|
467
|
+
2,
|
|
468
|
+
acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk::new(image.clone())),
|
|
469
|
+
),
|
|
470
|
+
(
|
|
471
|
+
3,
|
|
472
|
+
acp::SessionUpdate::AgentThoughtChunk(acp::ContentChunk::new(image.clone())),
|
|
473
|
+
),
|
|
474
|
+
] {
|
|
475
|
+
conversation
|
|
476
|
+
.apply(WireEvent::new("c", "r", sequence, Event::Update { update }))
|
|
477
|
+
.unwrap();
|
|
478
|
+
}
|
|
479
|
+
let turn = &conversation.turns()[0];
|
|
480
|
+
assert_eq!(turn.user_content.as_slice(), std::slice::from_ref(&image));
|
|
481
|
+
assert_eq!(turn.content.as_slice(), std::slice::from_ref(&image));
|
|
482
|
+
assert_eq!(turn.thought_content, [image]);
|
|
483
|
+
assert!(turn.text.is_empty());
|
|
484
|
+
assert!(turn.user_text.is_empty());
|
|
485
|
+
assert!(turn.thought_text.is_empty());
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
#[test]
|
|
489
|
+
fn tool_updates_preserve_structure_and_resolve_permissions() {
|
|
490
|
+
let mut conversation = Conversation::new("c");
|
|
491
|
+
let call = acp::ToolCall::new("tool-1", "Edit document");
|
|
492
|
+
conversation
|
|
493
|
+
.apply(WireEvent::new(
|
|
494
|
+
"c",
|
|
495
|
+
"r",
|
|
496
|
+
1,
|
|
497
|
+
Event::Update {
|
|
498
|
+
update: acp::SessionUpdate::ToolCall(call),
|
|
499
|
+
},
|
|
500
|
+
))
|
|
501
|
+
.unwrap();
|
|
502
|
+
let permission = acp::RequestPermissionRequest::new(
|
|
503
|
+
"native",
|
|
504
|
+
acp::ToolCallUpdate::new("tool-1", acp::ToolCallUpdateFields::new()),
|
|
505
|
+
vec![acp::PermissionOption::new(
|
|
506
|
+
"deny",
|
|
507
|
+
"Deny",
|
|
508
|
+
acp::PermissionOptionKind::RejectOnce,
|
|
509
|
+
)],
|
|
510
|
+
);
|
|
511
|
+
conversation
|
|
512
|
+
.apply(WireEvent::new(
|
|
513
|
+
"c",
|
|
514
|
+
"r",
|
|
515
|
+
2,
|
|
516
|
+
Event::Permission {
|
|
517
|
+
request_id: "p1".into(),
|
|
518
|
+
request: permission,
|
|
519
|
+
},
|
|
520
|
+
))
|
|
521
|
+
.unwrap();
|
|
522
|
+
assert_eq!(conversation.turns()[0].status, "awaiting_permission");
|
|
523
|
+
let fields = acp::ToolCallUpdateFields::new().status(acp::ToolCallStatus::Failed);
|
|
524
|
+
conversation
|
|
525
|
+
.apply(WireEvent::new(
|
|
526
|
+
"c",
|
|
527
|
+
"r",
|
|
528
|
+
3,
|
|
529
|
+
Event::Update {
|
|
530
|
+
update: acp::SessionUpdate::ToolCallUpdate(acp::ToolCallUpdate::new(
|
|
531
|
+
"tool-1", fields,
|
|
532
|
+
)),
|
|
533
|
+
},
|
|
534
|
+
))
|
|
535
|
+
.unwrap();
|
|
536
|
+
assert!(conversation.turns()[0].permissions.is_empty());
|
|
537
|
+
assert_eq!(
|
|
538
|
+
conversation.turns()[0].tools["tool-1"].status,
|
|
539
|
+
acp::ToolCallStatus::Failed
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
#[test]
|
|
544
|
+
fn invalid_json_versions_and_capacity_fail_without_mutation() {
|
|
545
|
+
let mut conversation = Conversation::new("c");
|
|
546
|
+
assert_eq!(conversation.apply_json("{"), Err(ConversationError::Json));
|
|
547
|
+
let mut event = delta("c", "r", 1, "text");
|
|
548
|
+
event.version = 2;
|
|
549
|
+
assert_eq!(conversation.apply(event), Err(ConversationError::Version));
|
|
550
|
+
let oversized = "x".repeat(MAX_EVENT_BYTES + 1);
|
|
551
|
+
assert_eq!(
|
|
552
|
+
conversation.apply_json(&oversized),
|
|
553
|
+
Err(ConversationError::Capacity)
|
|
554
|
+
);
|
|
555
|
+
assert!(conversation.turns().is_empty());
|
|
556
|
+
}
|
|
557
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//! Reusable conversations for native applications and the web.
|
|
2
|
+
//!
|
|
3
|
+
//! The conversation model and event contract compile to native Rust and Wasm.
|
|
4
|
+
//! Native connections use the official ACP SDK; applications own their UI,
|
|
5
|
+
//! persistence, prompts and authorization decisions.
|
|
6
|
+
//!
|
|
7
|
+
//! ```
|
|
8
|
+
//! use ccht::{Conversation, Event, WireEvent, acp};
|
|
9
|
+
//! let mut conversation = Conversation::new("creator");
|
|
10
|
+
//! let event = WireEvent::new("creator", "turn-1", 1,
|
|
11
|
+
//! Event::Update { update: acp::SessionUpdate::AgentMessageChunk(
|
|
12
|
+
//! acp::ContentChunk::new("Hello".into())) });
|
|
13
|
+
//! conversation.apply(event).unwrap();
|
|
14
|
+
//! assert_eq!(conversation.turns()[0].text, "Hello");
|
|
15
|
+
//! ```
|
|
16
|
+
|
|
17
|
+
/// The official platform-independent ACP version 1 schema.
|
|
18
|
+
pub use agent_client_protocol_schema::v1 as acp;
|
|
19
|
+
|
|
20
|
+
mod conversation;
|
|
21
|
+
pub use conversation::*;
|
|
22
|
+
|
|
23
|
+
#[cfg(all(feature = "native", not(target_family = "wasm")))]
|
|
24
|
+
pub mod native;
|
|
25
|
+
|
|
26
|
+
#[cfg(feature = "web")]
|
|
27
|
+
mod web;
|