@corbet-labs/ccht 0.2.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 +194 -212
- package/index.d.ts +6 -1
- 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 -28
- 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 -234
- package/source/THIRD-PARTY.md +0 -45
- package/source/dependencies.tar.gz +0 -0
- package/source/examples/native.rs +0 -45
- package/source/src/configuration.rs +0 -89
- package/source/src/conversation.rs +0 -569
- package/source/src/lib.rs +0 -30
- package/source/src/native/client.rs +0 -395
- package/source/src/native/fixture.py +0 -114
- package/source/src/native/mod.rs +0 -252
- package/source/src/native/session.rs +0 -603
- package/source/src/native/tests.rs +0 -463
- package/source/src/web.rs +0 -35
package/src/auth.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/** Typed mirrors of the Rust auth surface (`ccht::auth`) for web consumers.
|
|
2
|
+
*
|
|
3
|
+
* The conversation model stays in Rust/Wasm; these types only describe *who*
|
|
4
|
+
* may act. Transport, login ceremonies, credential storage, polling and
|
|
5
|
+
* product copy belong to the embedding application. Nothing here touches the
|
|
6
|
+
* DOM, performs network I/O, or spawns processes: effects run in the
|
|
7
|
+
* application backend and reach the browser through app-supplied async
|
|
8
|
+
* callbacks and explicit service keys.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Login state of one provider, mirroring `ccht::auth::AuthState`.
|
|
12
|
+
*
|
|
13
|
+
* The shape round-trips the Rust `snake_case` JSON byte-for-byte, so a state
|
|
14
|
+
* serialized by Rust deserializes here and vice versa:
|
|
15
|
+
* - `Unknown` becomes the string `"unknown"`.
|
|
16
|
+
* - `Unauthenticated` becomes the string `"unauthenticated"`.
|
|
17
|
+
* - `Authenticated { account }` becomes `{"authenticated": {"account": ...}}`,
|
|
18
|
+
* where `account` is a display-only label (string), `null`, or absent.
|
|
19
|
+
* The label is provenance for the UI and never an authentication proof.
|
|
20
|
+
*/
|
|
21
|
+
export type AuthState = 'unknown' | 'unauthenticated' | { authenticated: { account?: string | null } };
|
|
22
|
+
|
|
23
|
+
/** Whether routine work may proceed without prompting for login first. Mirrors `AuthState::authenticated`. */
|
|
24
|
+
export function isAuthenticated(state: AuthState): boolean {
|
|
25
|
+
return typeof state === 'object' && state !== null && 'authenticated' in state;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Display-only account label (username, email, or subscription name), or null when absent. Never a secret. */
|
|
29
|
+
export function authAccount(state: AuthState): string | null {
|
|
30
|
+
if (typeof state === 'object' && state !== null && 'authenticated' in state) {
|
|
31
|
+
return state.authenticated.account ?? null;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Whether a decoded JSON value has the exact Rust `AuthState` shape. Unknown fields inside the inner object are ignored, matching serde's default. */
|
|
37
|
+
export function isAuthState(value: unknown): value is AuthState {
|
|
38
|
+
try {
|
|
39
|
+
parseAuthState(value);
|
|
40
|
+
return true;
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Validate a decoded JSON value as the Rust `AuthState` shape. Throws a `TypeError` when the shape differs. */
|
|
47
|
+
export function parseAuthState(value: unknown): AuthState {
|
|
48
|
+
if (value === 'unknown' || value === 'unauthenticated') {
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
52
|
+
const keys = Object.keys(value);
|
|
53
|
+
if (keys.length === 1 && keys[0] === 'authenticated') {
|
|
54
|
+
const inner = (value as { authenticated: unknown }).authenticated;
|
|
55
|
+
if (typeof inner === 'object' && inner !== null && !Array.isArray(inner)) {
|
|
56
|
+
const account = (inner as { account?: unknown }).account;
|
|
57
|
+
if (account === undefined) {
|
|
58
|
+
return { authenticated: {} };
|
|
59
|
+
}
|
|
60
|
+
if (account === null || typeof account === 'string') {
|
|
61
|
+
return { authenticated: { account } };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw new TypeError('invalid AuthState');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Device-code challenge as exchanged during a provider login ceremony.
|
|
70
|
+
*
|
|
71
|
+
* Field names stay `snake_case` to match the wire format applications pass
|
|
72
|
+
* between their backend and the browser. The backend remains authoritative:
|
|
73
|
+
* it issues the challenge, pins any provider-specific endpoint, and polls
|
|
74
|
+
* for completion. The browser only displays a validated challenge and never
|
|
75
|
+
* invents one.
|
|
76
|
+
*/
|
|
77
|
+
export interface Challenge {
|
|
78
|
+
verification_url: string;
|
|
79
|
+
user_code: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const CHALLENGE_CODE_PATTERN = /^[A-Za-z0-9-]+$/;
|
|
83
|
+
const CHALLENGE_CODE_MAX_LENGTH = 64;
|
|
84
|
+
|
|
85
|
+
/** Whether a value is a renderable device-code challenge.
|
|
86
|
+
*
|
|
87
|
+
* Accepts any `https:` URL with a host (applications may narrow this
|
|
88
|
+
* further, for example by pinning the provider's device endpoint) and a
|
|
89
|
+
* non-empty code of up to 64 ASCII alphanumeric or `-` characters. URLs with
|
|
90
|
+
* embedded credentials are rejected. Never throws; validate before rendering
|
|
91
|
+
* a challenge as a link or code.
|
|
92
|
+
*/
|
|
93
|
+
export function validateChallenge(value: unknown): value is Challenge {
|
|
94
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const { verification_url, user_code } = value as Record<string, unknown>;
|
|
98
|
+
if (typeof verification_url !== 'string' || typeof user_code !== 'string') {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (user_code.length < 1 || user_code.length > CHALLENGE_CODE_MAX_LENGTH) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (!CHALLENGE_CODE_PATTERN.test(user_code)) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
let url: URL;
|
|
108
|
+
try {
|
|
109
|
+
url = new URL(verification_url);
|
|
110
|
+
} catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (url.protocol !== 'https:' || url.hostname === '') {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
if (url.username !== '' || url.password !== '') {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Opaque credential, mirroring `ccht::auth::Credential`.
|
|
123
|
+
*
|
|
124
|
+
* Stores treat both fields as opaque. `account` is display-only; `secret`
|
|
125
|
+
* holds the raw secret bytes. Encode at the application boundary (for
|
|
126
|
+
* example with `TextEncoder` or base64) when the backing store needs text,
|
|
127
|
+
* and never write secrets to logs, errors, or fixtures.
|
|
128
|
+
*/
|
|
129
|
+
export interface Credential {
|
|
130
|
+
account: string;
|
|
131
|
+
secret: Uint8Array;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Application-supplied credential persistence, mirroring `ccht::auth::CredentialsProvider`.
|
|
135
|
+
*
|
|
136
|
+
* One method triple per service key. Service keys are application-defined
|
|
137
|
+
* opaque strings (never ambient authority); native applications back this
|
|
138
|
+
* with the OS keychain and web applications with origin-scoped browser
|
|
139
|
+
* storage. Removing a missing entry succeeds. Implementations reject the
|
|
140
|
+
* promise when the backing store fails.
|
|
141
|
+
*/
|
|
142
|
+
export interface CredentialsProvider {
|
|
143
|
+
/** Read stored credentials, if any, for a service key. */
|
|
144
|
+
readCredentials(service: string): Promise<Credential | null>;
|
|
145
|
+
/** Persist credentials for a service key, replacing any previous entry. */
|
|
146
|
+
writeCredentials(service: string, credential: Credential): Promise<void>;
|
|
147
|
+
/** Remove stored credentials for a service key. Missing entries are not an error. */
|
|
148
|
+
deleteCredentials(service: string): Promise<void>;
|
|
149
|
+
}
|
|
@@ -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>
|