@corbet-labs/ccht 0.1.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +199 -168
- package/index.d.ts +17 -2
- package/index.js +8 -1
- package/package.json +12 -26
- package/src/auth.ts +149 -0
- package/src/components/AccountConnection.svelte +201 -0
- package/src/components/Dock.svelte +172 -0
- package/src/dock.ts +244 -0
- package/wasm/ccht_bg.wasm +0 -0
- package/LICENSE +0 -307
- package/LICENSE.md +0 -25
- package/LICENSES/GPL-3.0-only.txt +0 -232
- package/LICENSES/LGPL-3.0-only.txt +0 -304
- package/LICENSES/dependencies/agent-client-protocol-2.1.0/LICENSE +0 -191
- package/LICENSES/dependencies/agent-client-protocol-derive-2.1.0/LICENSE +0 -191
- package/LICENSES/dependencies/agent-client-protocol-schema-1.7.0/LICENSE +0 -190
- package/LICENSES/dependencies/android_system_properties-0.1.6/LICENSE-APACHE +0 -13
- package/LICENSES/dependencies/android_system_properties-0.1.6/LICENSE-MIT +0 -20
- package/LICENSES/dependencies/anyhow-1.0.104/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/anyhow-1.0.104/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-channel-2.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-channel-2.5.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-io-2.6.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-io-2.6.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-lock-3.4.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-lock-3.4.2/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-process-2.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-process-2.5.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-signal-0.2.14/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-signal-0.2.14/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-task-4.7.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-task-4.7.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/atomic-waker-1.1.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/atomic-waker-1.1.2/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/atomic-waker-1.1.2/LICENSE-THIRD-PARTY +0 -45
- package/LICENSES/dependencies/autocfg-1.5.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/autocfg-1.5.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/base64-0.22.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/base64-0.22.1/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/base64-0.23.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/base64-0.23.1/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/bitflags-1.3.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/bitflags-1.3.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/bitflags-2.13.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/bitflags-2.13.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/blocking-1.7.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/blocking-1.7.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/bs58-0.5.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/bs58-0.5.1/LICENSE-MIT +0 -20
- package/LICENSES/dependencies/bumpalo-3.20.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/bumpalo-3.20.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/cc-1.4.5/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/cc-1.4.5/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/cfg-if-1.0.4/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/cfg-if-1.0.4/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/chrono-0.4.45/LICENSE.txt +0 -240
- package/LICENSES/dependencies/concurrent-queue-2.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/concurrent-queue-2.5.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/convert_case-0.10.0/LICENSE +0 -21
- package/LICENSES/dependencies/core-foundation-sys-0.8.7/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/core-foundation-sys-0.8.7/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/crossbeam-deque-0.8.8/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/crossbeam-deque-0.8.8/LICENSE-MIT +0 -27
- package/LICENSES/dependencies/crossbeam-epoch-0.9.21/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/crossbeam-epoch-0.9.21/LICENSE-MIT +0 -27
- package/LICENSES/dependencies/crossbeam-utils-0.8.23/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/crossbeam-utils-0.8.23/LICENSE-MIT +0 -27
- package/LICENSES/dependencies/darling-0.24.1/LICENSE +0 -21
- package/LICENSES/dependencies/darling_core-0.24.1/LICENSE +0 -21
- package/LICENSES/dependencies/darling_macro-0.24.1/LICENSE +0 -21
- package/LICENSES/dependencies/defmt-1.1.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/defmt-1.1.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/defmt-macros-1.1.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/defmt-macros-1.1.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/defmt-parser-1.0.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/defmt-parser-1.0.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/deranged-0.5.8/LICENSE-Apache +0 -202
- package/LICENSES/dependencies/deranged-0.5.8/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/derive_more-2.1.1/LICENSE +0 -21
- package/LICENSES/dependencies/derive_more-impl-2.1.1/LICENSE +0 -21
- package/LICENSES/dependencies/dyn-clone-1.0.20/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/dyn-clone-1.0.20/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/either-1.18.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/either-1.18.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/equivalent-1.0.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/equivalent-1.0.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/errno-0.3.14/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/errno-0.3.14/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/event-listener-5.4.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/event-listener-5.4.2/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/event-listener-strategy-0.5.4/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/event-listener-strategy-0.5.4/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/fallible-iterator-0.3.0/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/fallible-iterator-0.3.0/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/fastrand-2.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/fastrand-2.5.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/find-msvc-tools-0.1.12/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/find-msvc-tools-0.1.12/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/fixedbitset-0.5.7/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/fixedbitset-0.5.7/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/foldhash-0.2.0/LICENSE +0 -19
- package/LICENSES/dependencies/futures-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-channel-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-channel-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-concurrency-7.7.1/LICENSE-APACHE +0 -190
- package/LICENSES/dependencies/futures-concurrency-7.7.1/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/futures-core-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-core-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-executor-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-executor-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-io-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-io-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-lite-2.6.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/futures-lite-2.6.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/futures-lite-2.6.1/LICENSE-THIRD-PARTY +0 -45
- package/LICENSES/dependencies/futures-macro-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-macro-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-sink-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-sink-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-task-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-task-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-util-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-util-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/getrandom-0.4.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/getrandom-0.4.3/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/gimli-0.32.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/gimli-0.32.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/hashbrown-0.12.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/hashbrown-0.12.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/hashbrown-0.16.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/hashbrown-0.16.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/hashbrown-0.17.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/hashbrown-0.17.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/heck-0.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/heck-0.5.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/hermit-abi-0.5.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/hermit-abi-0.5.3/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/hex-0.4.3/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/hex-0.4.3/LICENSE-MIT +0 -20
- package/LICENSES/dependencies/iana-time-zone-0.1.65/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/iana-time-zone-0.1.65/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/iana-time-zone-haiku-0.1.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/iana-time-zone-haiku-0.1.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/id-arena-2.3.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/id-arena-2.3.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/ident_case-1.0.1/LICENSE +0 -19
- package/LICENSES/dependencies/indexmap-1.9.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/indexmap-1.9.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/indexmap-2.14.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/indexmap-2.14.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/itoa-1.0.18/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/itoa-1.0.18/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/jiff-0.2.35/COPYING +0 -3
- package/LICENSES/dependencies/jiff-0.2.35/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-0.2.35/UNLICENSE +0 -24
- package/LICENSES/dependencies/jiff-core-0.1.0/COPYING +0 -3
- package/LICENSES/dependencies/jiff-core-0.1.0/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-core-0.1.0/UNLICENSE +0 -24
- package/LICENSES/dependencies/jiff-static-0.2.35/COPYING +0 -3
- package/LICENSES/dependencies/jiff-static-0.2.35/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-static-0.2.35/UNLICENSE +0 -24
- package/LICENSES/dependencies/jiff-tzdb-0.1.8/COPYING +0 -3
- package/LICENSES/dependencies/jiff-tzdb-0.1.8/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-tzdb-0.1.8/UNLICENSE +0 -24
- package/LICENSES/dependencies/jiff-tzdb-platform-0.1.3/COPYING +0 -3
- package/LICENSES/dependencies/jiff-tzdb-platform-0.1.3/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-tzdb-platform-0.1.3/UNLICENSE +0 -24
- package/LICENSES/dependencies/js-sys-0.3.105/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/js-sys-0.3.105/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/leb128-0.2.7/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/leb128-0.2.7/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/leb128fmt-0.1.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/leb128fmt-0.1.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/libc-0.2.189/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/libc-0.2.189/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/COPYRIGHT +0 -29
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/log-0.4.34/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/log-0.4.34/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/memchr-2.8.3/COPYING +0 -3
- package/LICENSES/dependencies/memchr-2.8.3/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/memchr-2.8.3/UNLICENSE +0 -24
- package/LICENSES/dependencies/mio-1.2.3/LICENSE +0 -19
- package/LICENSES/dependencies/num-conv-0.2.2/LICENSE-Apache +0 -177
- package/LICENSES/dependencies/num-conv-0.2.2/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/num-traits-0.2.19/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/num-traits-0.2.19/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/once_cell-1.21.4/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/once_cell-1.21.4/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/parking-2.2.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/parking-2.2.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/parking-2.2.1/LICENSE-THIRD-PARTY +0 -9
- package/LICENSES/dependencies/pin-project-1.1.13/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/pin-project-1.1.13/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/pin-project-internal-1.1.13/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/pin-project-internal-1.1.13/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/pin-project-lite-0.2.17/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/pin-project-lite-0.2.17/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/piper-0.2.5/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/piper-0.2.5/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/polling-3.11.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/polling-3.11.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/portable-atomic-1.15.0/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/portable-atomic-1.15.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/portable-atomic-util-0.2.8/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/portable-atomic-util-0.2.8/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/powerfmt-0.2.0/LICENSE-Apache +0 -202
- package/LICENSES/dependencies/powerfmt-0.2.0/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/proc-macro2-1.0.107/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/proc-macro2-1.0.107/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/quote-1.0.47/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/quote-1.0.47/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/r-efi-6.0.0/AUTHORS +0 -75
- package/LICENSES/dependencies/rayon-1.12.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rayon-1.12.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/rayon-core-1.13.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rayon-core-1.13.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/ref-cast-1.0.27/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/ref-cast-1.0.27/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/ref-cast-impl-1.0.27/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/ref-cast-impl-1.0.27/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/rustc-demangle-0.1.28/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rustc-demangle-0.1.28/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/rustc-hash-2.1.3/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/rustc-hash-2.1.3/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/rustc_version-0.4.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rustc_version-0.4.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/rustix-1.1.4/COPYRIGHT +0 -29
- package/LICENSES/dependencies/rustix-1.1.4/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rustix-1.1.4/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/rustix-1.1.4/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/rustversion-1.0.23/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/rustversion-1.0.23/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/schemars-0.9.0/LICENSE +0 -21
- package/LICENSES/dependencies/schemars-1.2.2/LICENSE +0 -21
- package/LICENSES/dependencies/schemars_derive-1.2.2/LICENSE +0 -21
- package/LICENSES/dependencies/semver-1.0.28/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/semver-1.0.28/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde-1.0.229/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde-1.0.229/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_core-1.0.229/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde_core-1.0.229/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_derive-1.0.229/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde_derive-1.0.229/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_derive_internals-0.30.0/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde_derive_internals-0.30.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_json-1.0.151/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde_json-1.0.151/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_with-3.23.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/serde_with-3.23.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/serde_with_macros-3.23.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/serde_with_macros-3.23.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/shell-words-1.1.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/shell-words-1.1.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/shlex-2.0.1/LICENSE-APACHE +0 -13
- package/LICENSES/dependencies/shlex-2.0.1/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/signal-hook-registry-1.4.8/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/signal-hook-registry-1.4.8/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/slab-0.4.12/LICENSE +0 -25
- package/LICENSES/dependencies/smallvec-1.16.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/smallvec-1.16.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/socket2-0.6.5/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/socket2-0.6.5/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/stable_deref_trait-1.2.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/stable_deref_trait-1.2.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/strsim-0.11.1/LICENSE +0 -23
- package/LICENSES/dependencies/strum-0.28.0/LICENSE +0 -21
- package/LICENSES/dependencies/strum_macros-0.28.0/LICENSE +0 -21
- package/LICENSES/dependencies/syn-2.0.119/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/syn-2.0.119/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/syn-3.0.5/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/syn-3.0.5/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/thiserror-2.0.20/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/thiserror-2.0.20/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/thiserror-impl-2.0.20/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/thiserror-impl-2.0.20/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/time-0.3.55/LICENSE-Apache +0 -177
- package/LICENSES/dependencies/time-0.3.55/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/time-core-0.1.9/LICENSE-Apache +0 -177
- package/LICENSES/dependencies/time-core-0.1.9/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/time-macros-0.2.32/LICENSE-Apache +0 -177
- package/LICENSES/dependencies/time-macros-0.2.32/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/tinyvec-1.13.2/LICENSE-APACHE.md +0 -202
- package/LICENSES/dependencies/tinyvec-1.13.2/LICENSE-MIT.md +0 -5
- package/LICENSES/dependencies/tinyvec-1.13.2/LICENSE-ZLIB.md +0 -11
- package/LICENSES/dependencies/tinyvec_macros-0.1.1/LICENSE-APACHE.md +0 -202
- package/LICENSES/dependencies/tinyvec_macros-0.1.1/LICENSE-MIT.md +0 -21
- package/LICENSES/dependencies/tinyvec_macros-0.1.1/LICENSE-ZLIB.md +0 -20
- package/LICENSES/dependencies/tokio-1.53.1/LICENSE +0 -21
- package/LICENSES/dependencies/tokio-macros-2.7.2/LICENSE +0 -22
- package/LICENSES/dependencies/tracing-0.1.44/LICENSE +0 -25
- package/LICENSES/dependencies/tracing-attributes-0.1.31/LICENSE +0 -25
- package/LICENSES/dependencies/tracing-core-0.1.36/LICENSE +0 -25
- package/LICENSES/dependencies/unicode-ident-1.0.24/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/unicode-ident-1.0.24/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/unicode-ident-1.0.24/LICENSE-UNICODE +0 -39
- package/LICENSES/dependencies/unicode-segmentation-1.13.3/COPYRIGHT +0 -7
- package/LICENSES/dependencies/unicode-segmentation-1.13.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/unicode-segmentation-1.13.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/unicode-xid-0.2.6/COPYRIGHT +0 -7
- package/LICENSES/dependencies/unicode-xid-0.2.6/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/unicode-xid-0.2.6/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/uuid-1.26.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/uuid-1.26.1/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/walrus-0.26.5/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/walrus-0.26.5/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/walrus-macro-0.26.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/walrus-macro-0.26.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/wasm-bindgen-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-bindgen-cli-support-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-cli-support-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-bindgen-macro-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-macro-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-bindgen-macro-support-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-macro-support-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-bindgen-shared-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-shared-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-encoder-0.245.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-encoder-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/wasm-encoder-0.245.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/wasmparser-0.245.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasmparser-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/wasmparser-0.245.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/windows-core-0.62.2/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-core-0.62.2/license-mit +0 -21
- package/LICENSES/dependencies/windows-implement-0.60.2/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-implement-0.60.2/license-mit +0 -21
- package/LICENSES/dependencies/windows-interface-0.59.3/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-interface-0.59.3/license-mit +0 -21
- package/LICENSES/dependencies/windows-link-0.2.1/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-link-0.2.1/license-mit +0 -21
- package/LICENSES/dependencies/windows-result-0.4.1/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-result-0.4.1/license-mit +0 -21
- package/LICENSES/dependencies/windows-strings-0.5.1/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-strings-0.5.1/license-mit +0 -21
- package/LICENSES/dependencies/windows-sys-0.61.2/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-sys-0.61.2/license-mit +0 -21
- package/LICENSES/dependencies/zmij-1.0.23/LICENSE-MIT +0 -23
- package/THIRD-PARTY.md +0 -45
- package/source/.cargo/config.toml +0 -5
- package/source/.ci/upstream-notices/PROVENANCE.json +0 -198
- package/source/.ci/upstream-notices/agent-client-protocol-2.1.0/LICENSE +0 -191
- package/source/.ci/upstream-notices/agent-client-protocol-derive-2.1.0/LICENSE +0 -191
- package/source/.ci/upstream-notices/agent-client-protocol-schema-1.7.0/LICENSE +0 -190
- package/source/.ci/upstream-notices/defmt-parser-1.0.0/LICENSE-APACHE +0 -201
- package/source/.ci/upstream-notices/defmt-parser-1.0.0/LICENSE-MIT +0 -25
- package/source/.ci/upstream-notices/r-efi-6.0.0/AUTHORS +0 -75
- package/source/.ci/upstream-notices/wasm-encoder-0.245.1/LICENSE-APACHE +0 -201
- package/source/.ci/upstream-notices/wasm-encoder-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/source/.ci/upstream-notices/wasm-encoder-0.245.1/LICENSE-MIT +0 -23
- package/source/.ci/upstream-notices/wasmparser-0.245.1/LICENSE-APACHE +0 -201
- package/source/.ci/upstream-notices/wasmparser-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/source/.ci/upstream-notices/wasmparser-0.245.1/LICENSE-MIT +0 -23
- package/source/.ci/wasm-bundle/Cargo.toml +0 -10
- package/source/.ci/wasm-bundle/src/main.rs +0 -17
- package/source/CHANGELOG.md +0 -11
- package/source/Cargo.lock +0 -1622
- package/source/Cargo.toml +0 -48
- package/source/LICENSE +0 -307
- package/source/LICENSE.md +0 -25
- package/source/LICENSES/GPL-3.0-only.txt +0 -232
- package/source/LICENSES/LGPL-3.0-only.txt +0 -304
- package/source/README.md +0 -185
- package/source/THIRD-PARTY.md +0 -45
- package/source/dependencies.tar.gz +0 -0
- package/source/examples/native.rs +0 -45
- package/source/src/conversation.rs +0 -557
- package/source/src/lib.rs +0 -27
- package/source/src/native/client.rs +0 -417
- package/source/src/native/fixture.py +0 -104
- package/source/src/native/mod.rs +0 -249
- package/source/src/native/session.rs +0 -541
- package/source/src/native/tests.rs +0 -427
- package/source/src/web.rs +0 -35
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
<!-- Product-neutral account connector. The application backend owns all effects
|
|
2
|
+
(starting device flows, polling logins, storing keys, signing out); this
|
|
3
|
+
component only renders state and forwards user intent through app-supplied
|
|
4
|
+
async callbacks. It never spawns agents, polls, or touches credentials. -->
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import {
|
|
7
|
+
authAccount,
|
|
8
|
+
isAuthenticated,
|
|
9
|
+
validateChallenge,
|
|
10
|
+
type AuthState,
|
|
11
|
+
type Challenge
|
|
12
|
+
} from '../auth.js';
|
|
13
|
+
|
|
14
|
+
interface AccountRef {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
kind: 'chatgpt' | 'opencode_go' | (string & {});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
account,
|
|
22
|
+
state: authState = 'unknown' as AuthState,
|
|
23
|
+
busy = false,
|
|
24
|
+
challenge = null as Challenge | null,
|
|
25
|
+
onStart,
|
|
26
|
+
onCancel,
|
|
27
|
+
onKeySubmit,
|
|
28
|
+
onDisconnect
|
|
29
|
+
}: {
|
|
30
|
+
account: AccountRef;
|
|
31
|
+
state: AuthState;
|
|
32
|
+
busy: boolean;
|
|
33
|
+
challenge?: Challenge | null;
|
|
34
|
+
onStart: () => void | Promise<void>;
|
|
35
|
+
onCancel: () => void | Promise<void>;
|
|
36
|
+
onKeySubmit: (key: string) => void | Promise<void>;
|
|
37
|
+
onDisconnect?: () => void | Promise<void>;
|
|
38
|
+
} = $props();
|
|
39
|
+
|
|
40
|
+
let key = $state('');
|
|
41
|
+
let copyError = $state('');
|
|
42
|
+
|
|
43
|
+
// Renamed locally: a binding called `state` would shadow the `$state` rune analysis.
|
|
44
|
+
const authenticated: boolean = $derived(isAuthenticated(authState));
|
|
45
|
+
const accountName: string | null = $derived(authAccount(authState));
|
|
46
|
+
const validChallenge: Challenge | null = $derived(
|
|
47
|
+
challenge != null && validateChallenge(challenge) ? challenge : null
|
|
48
|
+
);
|
|
49
|
+
const isDeviceCodeAccount: boolean = $derived(account.kind === 'chatgpt');
|
|
50
|
+
const isKeyAccount: boolean = $derived(account.kind === 'opencode_go');
|
|
51
|
+
const keyInputId: string = $derived(`ccht-key-${account.id.replace(/[^a-zA-Z0-9_-]/g, '-')}`);
|
|
52
|
+
const canSubmitKey: boolean = $derived(key.trim().length >= 8 && !busy);
|
|
53
|
+
|
|
54
|
+
// Callbacks run application effects; the app surfaces their failures
|
|
55
|
+
// through its own operation state, so a rejection here stays silent.
|
|
56
|
+
function invoke(action: () => void | Promise<void>): void {
|
|
57
|
+
try {
|
|
58
|
+
const result = action();
|
|
59
|
+
if (result instanceof Promise) {
|
|
60
|
+
result.catch(() => {});
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
// Handled by the application through its own operation state.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function submitKey(event: SubmitEvent): void {
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
const value = key.trim();
|
|
70
|
+
// Clear immediately so the secret never lingers in component state.
|
|
71
|
+
key = '';
|
|
72
|
+
if (value.length < 8) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
invoke(() => onKeySubmit(value));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function copyAndContinue(): Promise<void> {
|
|
79
|
+
if (!validChallenge) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Open during the click so browsers do not block the sign-in window after copying.
|
|
83
|
+
if (typeof window !== 'undefined') {
|
|
84
|
+
window.open(validChallenge.verification_url, '_blank', 'noopener,noreferrer');
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
await navigator.clipboard.writeText(validChallenge.user_code);
|
|
88
|
+
copyError = '';
|
|
89
|
+
} catch {
|
|
90
|
+
copyError = 'Could not copy automatically. Copy the code above into the sign-in page.';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<section class="ccht-account" aria-label={`${account.label} connection`}>
|
|
96
|
+
{#if authenticated}
|
|
97
|
+
<p class="ccht-status" role="status">Connected{#if accountName} · {accountName}{/if}</p>
|
|
98
|
+
<button
|
|
99
|
+
type="button"
|
|
100
|
+
class="ccht-button ccht-disconnect"
|
|
101
|
+
disabled={busy}
|
|
102
|
+
onclick={() => invoke(onDisconnect ?? onCancel)}
|
|
103
|
+
>
|
|
104
|
+
Disconnect
|
|
105
|
+
</button>
|
|
106
|
+
{:else if authState === 'unknown'}
|
|
107
|
+
<p class="ccht-status" role="status">Checking {account.label} connection status…</p>
|
|
108
|
+
{#if busy}
|
|
109
|
+
<button type="button" class="ccht-button ccht-cancel" onclick={() => invoke(onCancel)}>
|
|
110
|
+
Cancel
|
|
111
|
+
</button>
|
|
112
|
+
{/if}
|
|
113
|
+
{:else if isDeviceCodeAccount}
|
|
114
|
+
{#if validChallenge}
|
|
115
|
+
<div class="ccht-challenge" aria-live="polite">
|
|
116
|
+
<p class="ccht-hint">Enter this code on the {account.label} sign-in page:</p>
|
|
117
|
+
<code class="ccht-code">{validChallenge.user_code}</code>
|
|
118
|
+
<button type="button" class="ccht-button" disabled={busy} onclick={() => void copyAndContinue()}>
|
|
119
|
+
Copy code and continue
|
|
120
|
+
</button>
|
|
121
|
+
<p>
|
|
122
|
+
<a
|
|
123
|
+
class="ccht-link"
|
|
124
|
+
href={validChallenge.verification_url}
|
|
125
|
+
target="_blank"
|
|
126
|
+
rel="noopener noreferrer"
|
|
127
|
+
>
|
|
128
|
+
Continue to {account.label}
|
|
129
|
+
</a>
|
|
130
|
+
</p>
|
|
131
|
+
{#if copyError}<p class="ccht-error" role="alert">{copyError}</p>{/if}
|
|
132
|
+
</div>
|
|
133
|
+
{:else if busy}
|
|
134
|
+
<p class="ccht-status" role="status">Starting account connection…</p>
|
|
135
|
+
{:else}
|
|
136
|
+
<p class="ccht-hint">Sign in with your {account.label} account.</p>
|
|
137
|
+
<button type="button" class="ccht-button" onclick={() => invoke(onStart)}>
|
|
138
|
+
Sign in to {account.label}
|
|
139
|
+
</button>
|
|
140
|
+
{/if}
|
|
141
|
+
{#if busy}
|
|
142
|
+
<button type="button" class="ccht-button ccht-cancel" onclick={() => invoke(onCancel)}>
|
|
143
|
+
Cancel
|
|
144
|
+
</button>
|
|
145
|
+
{/if}
|
|
146
|
+
{:else if isKeyAccount}
|
|
147
|
+
<form class="ccht-keyform" onsubmit={submitKey}>
|
|
148
|
+
<label class="ccht-label" for={keyInputId}>
|
|
149
|
+
{account.label} account key
|
|
150
|
+
<input
|
|
151
|
+
id={keyInputId}
|
|
152
|
+
class="ccht-input"
|
|
153
|
+
type="password"
|
|
154
|
+
autocomplete="off"
|
|
155
|
+
spellcheck="false"
|
|
156
|
+
maxlength="4096"
|
|
157
|
+
bind:value={key}
|
|
158
|
+
disabled={busy}
|
|
159
|
+
/>
|
|
160
|
+
</label>
|
|
161
|
+
<button type="submit" class="ccht-button" disabled={!canSubmitKey}>
|
|
162
|
+
Connect {account.label}
|
|
163
|
+
</button>
|
|
164
|
+
</form>
|
|
165
|
+
{#if busy}
|
|
166
|
+
<button type="button" class="ccht-button ccht-cancel" onclick={() => invoke(onCancel)}>
|
|
167
|
+
Cancel
|
|
168
|
+
</button>
|
|
169
|
+
{/if}
|
|
170
|
+
{:else}
|
|
171
|
+
<p class="ccht-status" role="status">Not connected</p>
|
|
172
|
+
<p class="ccht-hint">Sign in with your {account.label} account.</p>
|
|
173
|
+
<button type="button" class="ccht-button" disabled={busy} onclick={() => invoke(onStart)}>
|
|
174
|
+
Sign in to {account.label}
|
|
175
|
+
</button>
|
|
176
|
+
{#if busy}
|
|
177
|
+
<button type="button" class="ccht-button ccht-cancel" onclick={() => invoke(onCancel)}>
|
|
178
|
+
Cancel
|
|
179
|
+
</button>
|
|
180
|
+
{/if}
|
|
181
|
+
{/if}
|
|
182
|
+
</section>
|
|
183
|
+
|
|
184
|
+
<style>
|
|
185
|
+
.ccht-account {
|
|
186
|
+
color: var(--ccht-fg, inherit);
|
|
187
|
+
}
|
|
188
|
+
.ccht-status,
|
|
189
|
+
.ccht-hint {
|
|
190
|
+
color: var(--ccht-muted, inherit);
|
|
191
|
+
}
|
|
192
|
+
.ccht-error {
|
|
193
|
+
color: var(--ccht-error, #b91c1c);
|
|
194
|
+
}
|
|
195
|
+
.ccht-code {
|
|
196
|
+
background-color: var(--ccht-code-bg, transparent);
|
|
197
|
+
}
|
|
198
|
+
.ccht-link {
|
|
199
|
+
color: var(--ccht-accent, inherit);
|
|
200
|
+
}
|
|
201
|
+
</style>
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
<!-- Product-neutral edge rail. The application owns all effects (dock state,
|
|
2
|
+
persistence, focus targets beyond this panel); this component only renders
|
|
3
|
+
the tab and panel chrome and forwards user intent through app-supplied
|
|
4
|
+
open/close callbacks. It never fetches, spawns, or stores anything. -->
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import type { Snippet } from 'svelte';
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
side = 'left',
|
|
10
|
+
title,
|
|
11
|
+
open,
|
|
12
|
+
onClose,
|
|
13
|
+
onOpen,
|
|
14
|
+
tabLabel,
|
|
15
|
+
tabSummary = '',
|
|
16
|
+
closeLabel,
|
|
17
|
+
panelId,
|
|
18
|
+
children
|
|
19
|
+
}: {
|
|
20
|
+
side: 'left' | 'right';
|
|
21
|
+
title: string;
|
|
22
|
+
open: boolean;
|
|
23
|
+
onClose: () => void;
|
|
24
|
+
onOpen: () => void;
|
|
25
|
+
tabLabel: string;
|
|
26
|
+
tabSummary?: string;
|
|
27
|
+
closeLabel?: string;
|
|
28
|
+
panelId: string;
|
|
29
|
+
children: Snippet;
|
|
30
|
+
} = $props();
|
|
31
|
+
|
|
32
|
+
let panelEl: HTMLElement | undefined = $state(undefined);
|
|
33
|
+
let tabEl: HTMLButtonElement | undefined = $state(undefined);
|
|
34
|
+
let wasOpen = $state(false);
|
|
35
|
+
let prevFocus: HTMLElement | null = $state(null);
|
|
36
|
+
const dismissLabel = $derived(closeLabel ?? `Close ${title}`);
|
|
37
|
+
|
|
38
|
+
function handleTabClick(event: MouseEvent) {
|
|
39
|
+
prevFocus = event.currentTarget as HTMLElement;
|
|
40
|
+
onOpen();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
$effect(() => {
|
|
44
|
+
if (open && !wasOpen) {
|
|
45
|
+
wasOpen = true;
|
|
46
|
+
prevFocus ??= document.activeElement as HTMLElement | null;
|
|
47
|
+
requestAnimationFrame(() => {
|
|
48
|
+
// First visible, enabled control wins; hidden or disabled nodes
|
|
49
|
+
// never take focus. Fixed panels have no offsetParent, so filter
|
|
50
|
+
// on client rects instead.
|
|
51
|
+
const target = [...(panelEl?.querySelectorAll<HTMLElement>(
|
|
52
|
+
'button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], [tabindex]:not([tabindex="-1"])'
|
|
53
|
+
) ?? [])].find((node) => node.getClientRects().length > 0) ?? panelEl;
|
|
54
|
+
target?.focus();
|
|
55
|
+
});
|
|
56
|
+
} else if (!open && wasOpen) {
|
|
57
|
+
wasOpen = false;
|
|
58
|
+
const restore = prevFocus?.isConnected ? prevFocus : null;
|
|
59
|
+
prevFocus = null;
|
|
60
|
+
requestAnimationFrame(() => {
|
|
61
|
+
(restore ?? tabEl)?.focus?.();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
$effect(() => {
|
|
67
|
+
if (panelEl) (panelEl as HTMLElement & { inert: boolean }).inert = !open;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
function onKeydown(event: KeyboardEvent) {
|
|
71
|
+
if (event.key === 'Escape' && open) onClose();
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<svelte:window onkeydown={onKeydown} />
|
|
76
|
+
|
|
77
|
+
{#if !open}
|
|
78
|
+
<button
|
|
79
|
+
bind:this={tabEl}
|
|
80
|
+
type="button"
|
|
81
|
+
class="ccht-dock-tab"
|
|
82
|
+
data-side={side}
|
|
83
|
+
aria-expanded="false"
|
|
84
|
+
aria-controls={panelId}
|
|
85
|
+
aria-label={tabSummary ? `Open ${title}: ${tabSummary}` : `Open ${title}`}
|
|
86
|
+
onclick={handleTabClick}
|
|
87
|
+
><span class="ccht-dock-tab-text">{tabLabel} · {tabSummary || title}</span></button>
|
|
88
|
+
{/if}
|
|
89
|
+
|
|
90
|
+
<div
|
|
91
|
+
bind:this={panelEl}
|
|
92
|
+
id={panelId}
|
|
93
|
+
class="ccht-dock-panel"
|
|
94
|
+
data-side={side}
|
|
95
|
+
data-open={open ? 'true' : 'false'}
|
|
96
|
+
role="dialog"
|
|
97
|
+
aria-label={title}
|
|
98
|
+
aria-hidden={!open}
|
|
99
|
+
tabindex="-1"
|
|
100
|
+
>
|
|
101
|
+
<div class="ccht-dock-head">
|
|
102
|
+
<div class="ccht-dock-title"><h2>{title}</h2>{#if tabSummary}<p>{tabSummary}</p>{/if}</div>
|
|
103
|
+
<button type="button" class="ccht-dock-close" aria-label={dismissLabel} onclick={onClose}>Close</button>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="ccht-dock-body">{@render children()}</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<style>
|
|
109
|
+
.ccht-dock-tab {
|
|
110
|
+
position: fixed; top: 50%; z-index: 80; transform: translateY(-50%);
|
|
111
|
+
max-height: min(60vh, 30rem); max-width: 2.4rem; padding: 0.7rem 0.4rem;
|
|
112
|
+
display: flex; align-items: center; justify-content: center;
|
|
113
|
+
border: 1px solid var(--ccht-border, #30405c);
|
|
114
|
+
color: var(--ccht-fg, #c2cede);
|
|
115
|
+
background: var(--ccht-tab-bg, #111c2df2);
|
|
116
|
+
font: 800 0.68rem ui-monospace, monospace; cursor: pointer;
|
|
117
|
+
writing-mode: vertical-rl; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
118
|
+
}
|
|
119
|
+
.ccht-dock-tab[data-side='left'] { left: 0; border-left: 0; border-radius: 0 0.5rem 0.5rem 0; }
|
|
120
|
+
.ccht-dock-tab[data-side='right'] { right: 0; border-right: 0; border-radius: 0.5rem 0 0 0.5rem; }
|
|
121
|
+
.ccht-dock-tab:hover {
|
|
122
|
+
border-color: var(--ccht-accent, #53708f);
|
|
123
|
+
color: var(--ccht-fg-bright, #e2eaf5);
|
|
124
|
+
background: var(--ccht-tab-bg-hover, #17243af2);
|
|
125
|
+
}
|
|
126
|
+
.ccht-dock-tab-text { overflow: hidden; text-overflow: ellipsis; }
|
|
127
|
+
.ccht-dock-panel {
|
|
128
|
+
position: fixed; top: 0; bottom: 0; z-index: 70;
|
|
129
|
+
width: min(30rem, 100vw); display: flex; flex-direction: column;
|
|
130
|
+
background: var(--ccht-panel-bg, #0d1625);
|
|
131
|
+
color: var(--ccht-fg, #d8e2f0); visibility: hidden;
|
|
132
|
+
transition: transform 0.2s ease, visibility 0s linear 0.2s;
|
|
133
|
+
}
|
|
134
|
+
.ccht-dock-panel[data-side='left'] {
|
|
135
|
+
left: 0; border-right: 1px solid var(--ccht-border, #223049); transform: translateX(-102%);
|
|
136
|
+
}
|
|
137
|
+
.ccht-dock-panel[data-side='right'] {
|
|
138
|
+
right: 0; border-left: 1px solid var(--ccht-border, #223049); transform: translateX(102%);
|
|
139
|
+
}
|
|
140
|
+
.ccht-dock-panel[data-open='true'] { transform: none; visibility: visible; transition: transform 0.2s ease; }
|
|
141
|
+
.ccht-dock-panel[data-open='false'] { visibility: hidden; }
|
|
142
|
+
.ccht-dock-head {
|
|
143
|
+
display: flex; align-items: center; justify-content: space-between; gap: 0.8rem;
|
|
144
|
+
padding: 1rem 1.1rem; border-bottom: 1px solid var(--ccht-border, #223049);
|
|
145
|
+
}
|
|
146
|
+
.ccht-dock-title { min-width: 0; }
|
|
147
|
+
.ccht-dock-title h2 { margin: 0; font-size: 1.02rem; overflow-wrap: anywhere; }
|
|
148
|
+
.ccht-dock-title p {
|
|
149
|
+
margin: 0.3rem 0 0; overflow-wrap: anywhere;
|
|
150
|
+
color: var(--ccht-muted, #8fa0b7); font: 750 0.68rem ui-monospace, monospace;
|
|
151
|
+
}
|
|
152
|
+
.ccht-dock-close {
|
|
153
|
+
flex: 0 0 auto; min-height: 2.5rem; padding: 0.55rem 0.85rem;
|
|
154
|
+
border: 1px solid var(--ccht-border, #30405c); border-radius: 0.5rem;
|
|
155
|
+
color: var(--ccht-fg, #c2cede);
|
|
156
|
+
background: var(--ccht-tab-bg, #111c2d);
|
|
157
|
+
font-size: 0.72rem; font-weight: 850; cursor: pointer;
|
|
158
|
+
}
|
|
159
|
+
.ccht-dock-close:hover {
|
|
160
|
+
border-color: var(--ccht-accent, #53708f);
|
|
161
|
+
background: var(--ccht-tab-bg-hover, #17243a);
|
|
162
|
+
}
|
|
163
|
+
.ccht-dock-body {
|
|
164
|
+
flex: 1; min-height: 0; overflow: auto; padding: 1rem 1.1rem;
|
|
165
|
+
display: grid; gap: 0.85rem; align-content: start;
|
|
166
|
+
}
|
|
167
|
+
@media (max-width: 560px) {
|
|
168
|
+
.ccht-dock-panel { width: 100vw; }
|
|
169
|
+
.ccht-dock-head, .ccht-dock-body { padding-left: 0.85rem; padding-right: 0.85rem; }
|
|
170
|
+
}
|
|
171
|
+
@media (prefers-reduced-motion: reduce) { .ccht-dock-panel { transition: none; } }
|
|
172
|
+
</style>
|
package/src/dock.ts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/** Framework-free dock state for web consumers, mirroring the dock vocabulary.
|
|
2
|
+
*
|
|
3
|
+
* Docks are named regions of application chrome (for example a chat rail or
|
|
4
|
+
* a configuration panel). `DockKind` classifies a dock, `Placement` places
|
|
5
|
+
* it, and the manager tracks which docks exist, which are open, and where
|
|
6
|
+
* each one sits. The conversation model stays in Rust/Wasm; these types only
|
|
7
|
+
* describe *where* a surface lives and whether it is visible.
|
|
8
|
+
*
|
|
9
|
+
* This module is plain TypeScript: no DOM access, no network I/O, no spawned
|
|
10
|
+
* processes, and no storage. Persistence travels through `serialize` /
|
|
11
|
+
* `restore` as explicit JSON handled by the application; focus is handed off
|
|
12
|
+
* through an opaque token the application moves to its own focus target.
|
|
13
|
+
* Product copy belongs to the embedding application.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** What a dock is for. `chat` hosts a conversation surface, `config` hosts
|
|
17
|
+
* settings, and `custom` covers every application-defined use. */
|
|
18
|
+
export type DockKind = 'chat' | 'config' | 'custom';
|
|
19
|
+
|
|
20
|
+
/** Where a dock sits. Edge values pin the dock to a window edge; `inline`
|
|
21
|
+
* renders it in the normal application flow instead. */
|
|
22
|
+
export type Placement = 'left' | 'right' | 'bottom' | 'inline';
|
|
23
|
+
|
|
24
|
+
const DOCK_ID_PATTERN = /^[a-z0-9-_]+$/;
|
|
25
|
+
const DOCK_ID_MAX_LENGTH = 64;
|
|
26
|
+
|
|
27
|
+
/** Validate a dock id. Returns an error message, or null when the id is valid.
|
|
28
|
+
*
|
|
29
|
+
* Rules: a non-empty string of at most 64 ASCII `[a-z0-9-_]` characters.
|
|
30
|
+
* Never throws; validate before registering or restoring a dock.
|
|
31
|
+
*/
|
|
32
|
+
export function validateDockId(id: unknown): string | null {
|
|
33
|
+
if (typeof id !== 'string' || id.length === 0) {
|
|
34
|
+
return 'invalid dock id: must be a non-empty string';
|
|
35
|
+
}
|
|
36
|
+
if (id.length > DOCK_ID_MAX_LENGTH) {
|
|
37
|
+
return 'invalid dock id: must be at most 64 characters';
|
|
38
|
+
}
|
|
39
|
+
if (!DOCK_ID_PATTERN.test(id)) {
|
|
40
|
+
return 'invalid dock id: must match [a-z0-9-_]';
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** One persisted dock entry. `open` is the only mutable runtime state; the
|
|
46
|
+
* focus token is deliberately absent and never survives serialization. */
|
|
47
|
+
export interface DockEntry {
|
|
48
|
+
id: string;
|
|
49
|
+
kind: DockKind;
|
|
50
|
+
placement: Placement;
|
|
51
|
+
open: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Named dock registry with open state, placement, and focus handoff.
|
|
55
|
+
*
|
|
56
|
+
* Methods that name a dock throw `Error('UnknownDock: <id>')` for ids that
|
|
57
|
+
* were never registered. `register` throws `Error('DuplicateDock: <id>')`
|
|
58
|
+
* for an id that already exists, and rethrows the `validateDockId` message
|
|
59
|
+
* for a malformed id. Invalid kinds, placements, focus tokens, and snapshots
|
|
60
|
+
* throw `Error` with a fixed `invalid ...` message.
|
|
61
|
+
*/
|
|
62
|
+
export interface DockManager {
|
|
63
|
+
/** Register a closed dock. Throws on a malformed id, an invalid kind or
|
|
64
|
+
* placement, or a duplicate id. */
|
|
65
|
+
register(id: string, kind: DockKind, placement: Placement): void;
|
|
66
|
+
/** Mark a dock open. Throws `UnknownDock` for an unregistered id. */
|
|
67
|
+
open(id: string): void;
|
|
68
|
+
/** Mark a dock open and stage a focus token for the application to consume
|
|
69
|
+
* with `takeFocusToken`. The token must be a non-empty string. */
|
|
70
|
+
openWithFocus(id: string, token: string): void;
|
|
71
|
+
/** Mark a dock closed. Throws `UnknownDock` for an unregistered id. */
|
|
72
|
+
close(id: string): void;
|
|
73
|
+
/** Flip a dock's open state and return the new state. */
|
|
74
|
+
toggle(id: string): boolean;
|
|
75
|
+
/** Whether a dock is currently open. */
|
|
76
|
+
isOpen(id: string): boolean;
|
|
77
|
+
/** A dock's current placement. */
|
|
78
|
+
placement(id: string): Placement;
|
|
79
|
+
/** Move a dock to another placement. */
|
|
80
|
+
setPlacement(id: string, placement: Placement): void;
|
|
81
|
+
/** Ids of open docks, in registration order. */
|
|
82
|
+
openDocks(): string[];
|
|
83
|
+
/** Take the staged focus token once, clearing it; null when none is staged. */
|
|
84
|
+
takeFocusToken(): string | null;
|
|
85
|
+
/** Mark every dock closed. Staged focus tokens are left untouched. */
|
|
86
|
+
closeAll(): void;
|
|
87
|
+
/** Persist `[{id, kind, placement, open}]` as JSON, in registration order.
|
|
88
|
+
* The focus token is never persisted. */
|
|
89
|
+
serialize(): string;
|
|
90
|
+
/** Replace all state from `serialize` output. Validates every entry first,
|
|
91
|
+
* so a malformed snapshot leaves the current state untouched, and clears
|
|
92
|
+
* any staged focus token. */
|
|
93
|
+
restore(json: string): void;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Create an empty dock manager. Managers are independent; applications that
|
|
97
|
+
* need shared state pass one manager around instead of creating several. */
|
|
98
|
+
export function createDockManager(): DockManager {
|
|
99
|
+
const docks = new Map<string, { kind: DockKind; placement: Placement; open: boolean }>();
|
|
100
|
+
let focusToken: string | null = null;
|
|
101
|
+
|
|
102
|
+
function entry(id: string): { kind: DockKind; placement: Placement; open: boolean } {
|
|
103
|
+
const found = docks.get(id);
|
|
104
|
+
if (found === undefined) {
|
|
105
|
+
throw new Error(`UnknownDock: ${id}`);
|
|
106
|
+
}
|
|
107
|
+
return found;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function checkKind(kind: unknown): asserts kind is DockKind {
|
|
111
|
+
if (kind !== 'chat' && kind !== 'config' && kind !== 'custom') {
|
|
112
|
+
throw new Error('invalid dock kind');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function checkPlacement(value: unknown): asserts value is Placement {
|
|
117
|
+
if (value !== 'left' && value !== 'right' && value !== 'bottom' && value !== 'inline') {
|
|
118
|
+
throw new Error('invalid dock placement');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function checkToken(token: unknown): asserts token is string {
|
|
123
|
+
if (typeof token !== 'string' || token.length === 0) {
|
|
124
|
+
throw new Error('invalid focus token');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
register(id, kind, placement) {
|
|
130
|
+
const invalid = validateDockId(id);
|
|
131
|
+
if (invalid !== null) {
|
|
132
|
+
throw new Error(invalid);
|
|
133
|
+
}
|
|
134
|
+
checkKind(kind);
|
|
135
|
+
checkPlacement(placement);
|
|
136
|
+
if (docks.has(id)) {
|
|
137
|
+
throw new Error(`DuplicateDock: ${id}`);
|
|
138
|
+
}
|
|
139
|
+
docks.set(id, { kind, placement, open: false });
|
|
140
|
+
},
|
|
141
|
+
open(id) {
|
|
142
|
+
entry(id).open = true;
|
|
143
|
+
},
|
|
144
|
+
openWithFocus(id, token) {
|
|
145
|
+
checkToken(token);
|
|
146
|
+
entry(id).open = true;
|
|
147
|
+
focusToken = token;
|
|
148
|
+
},
|
|
149
|
+
close(id) {
|
|
150
|
+
entry(id).open = false;
|
|
151
|
+
},
|
|
152
|
+
toggle(id) {
|
|
153
|
+
const target = entry(id);
|
|
154
|
+
target.open = !target.open;
|
|
155
|
+
return target.open;
|
|
156
|
+
},
|
|
157
|
+
isOpen(id) {
|
|
158
|
+
return entry(id).open;
|
|
159
|
+
},
|
|
160
|
+
placement(id) {
|
|
161
|
+
return entry(id).placement;
|
|
162
|
+
},
|
|
163
|
+
setPlacement(id, placement) {
|
|
164
|
+
checkPlacement(placement);
|
|
165
|
+
entry(id).placement = placement;
|
|
166
|
+
},
|
|
167
|
+
openDocks() {
|
|
168
|
+
const ids: string[] = [];
|
|
169
|
+
for (const [id, state] of docks) {
|
|
170
|
+
if (state.open) {
|
|
171
|
+
ids.push(id);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return ids;
|
|
175
|
+
},
|
|
176
|
+
takeFocusToken() {
|
|
177
|
+
const token = focusToken;
|
|
178
|
+
focusToken = null;
|
|
179
|
+
return token;
|
|
180
|
+
},
|
|
181
|
+
closeAll() {
|
|
182
|
+
for (const state of docks.values()) {
|
|
183
|
+
state.open = false;
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
serialize() {
|
|
187
|
+
const snapshot: DockEntry[] = [];
|
|
188
|
+
for (const [id, state] of docks) {
|
|
189
|
+
snapshot.push({ id, kind: state.kind, placement: state.placement, open: state.open });
|
|
190
|
+
}
|
|
191
|
+
return JSON.stringify(snapshot);
|
|
192
|
+
},
|
|
193
|
+
restore(json) {
|
|
194
|
+
let decoded: unknown;
|
|
195
|
+
try {
|
|
196
|
+
decoded = JSON.parse(json);
|
|
197
|
+
} catch {
|
|
198
|
+
throw new Error('invalid dock snapshot: not JSON');
|
|
199
|
+
}
|
|
200
|
+
if (!Array.isArray(decoded)) {
|
|
201
|
+
throw new Error('invalid dock snapshot: must be an array');
|
|
202
|
+
}
|
|
203
|
+
const next = new Map<string, { kind: DockKind; placement: Placement; open: boolean }>();
|
|
204
|
+
for (const value of decoded) {
|
|
205
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
206
|
+
throw new Error('invalid dock snapshot: entry must be an object');
|
|
207
|
+
}
|
|
208
|
+
const record = value as Record<string, unknown>;
|
|
209
|
+
const invalid = validateDockId(record.id);
|
|
210
|
+
if (invalid !== null) {
|
|
211
|
+
throw new Error(`invalid dock snapshot: ${invalid}`);
|
|
212
|
+
}
|
|
213
|
+
const id = record.id as string;
|
|
214
|
+
if (record.kind !== 'chat' && record.kind !== 'config' && record.kind !== 'custom') {
|
|
215
|
+
throw new Error('invalid dock snapshot: invalid dock kind');
|
|
216
|
+
}
|
|
217
|
+
if (
|
|
218
|
+
record.placement !== 'left' &&
|
|
219
|
+
record.placement !== 'right' &&
|
|
220
|
+
record.placement !== 'bottom' &&
|
|
221
|
+
record.placement !== 'inline'
|
|
222
|
+
) {
|
|
223
|
+
throw new Error('invalid dock snapshot: invalid dock placement');
|
|
224
|
+
}
|
|
225
|
+
if (typeof record.open !== 'boolean') {
|
|
226
|
+
throw new Error('invalid dock snapshot: open must be a boolean');
|
|
227
|
+
}
|
|
228
|
+
if (next.has(id)) {
|
|
229
|
+
throw new Error('invalid dock snapshot: duplicate dock id');
|
|
230
|
+
}
|
|
231
|
+
next.set(id, {
|
|
232
|
+
kind: record.kind,
|
|
233
|
+
placement: record.placement,
|
|
234
|
+
open: record.open,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
docks.clear();
|
|
238
|
+
for (const [id, state] of next) {
|
|
239
|
+
docks.set(id, state);
|
|
240
|
+
}
|
|
241
|
+
focusToken = null;
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
}
|
package/wasm/ccht_bg.wasm
CHANGED
|
Binary file
|