From aa6bf9d29318bcb46998c5f972f2e587ab72b48d Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sat, 25 Nov 2023 21:29:37 +0100
Subject: [PATCH 01/25] Added build configurations for Intel and AMD hardware
---
Dockerfile | 5 ++-
crates/llama-cpp-bindings/Cargo.toml | 2 +
crates/llama-cpp-bindings/build.rs | 18 ++++++++
crates/tabby/Cargo.toml | 2 +
oneapi.Dockerfile | 61 ++++++++++++++++++++++++++++
rocm.Dockerfile | 61 ++++++++++++++++++++++++++++
6 files changed, 147 insertions(+), 2 deletions(-)
create mode 100644 oneapi.Dockerfile
create mode 100644 rocm.Dockerfile
diff --git a/Dockerfile b/Dockerfile
index 69ac755a59f..170fa641420 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,7 +9,7 @@ ARG BASE_CUDA_RUN_CONTAINER=nvidia/cuda:${CUDA_VERSION}-runtime-ubuntu${UBUNTU_V
FROM ${BASE_CUDA_DEV_CONTAINER} as build
# Rust toolchain version
-ARG RUST_TOOLCHAIN stable
+ARG RUST_TOOLCHAIN=stable
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
@@ -29,12 +29,13 @@ RUN curl https://sh.rustup.rs -sSf | bash -s -- --default-toolchain ${RUST_TOOLC
ENV PATH="/root/.cargo/bin:${PATH}"
WORKDIR /root/workspace
-COPY . .
RUN mkdir -p /opt/tabby/bin
RUN mkdir -p /opt/tabby/lib
RUN mkdir -p target
+COPY . .
+
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/root/workspace/target \
cargo build --features cuda --release --package tabby && \
diff --git a/crates/llama-cpp-bindings/Cargo.toml b/crates/llama-cpp-bindings/Cargo.toml
index 5dbf46f3019..5cccfe8ff3e 100644
--- a/crates/llama-cpp-bindings/Cargo.toml
+++ b/crates/llama-cpp-bindings/Cargo.toml
@@ -5,6 +5,8 @@ edition = "2021"
[features]
cuda = []
+rocm = []
+oneapi = []
[build-dependencies]
cxx-build = "1.0"
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index 488df009664..59266f632b8 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -31,6 +31,24 @@ fn main() {
println!("cargo:rustc-link-lib=cublas");
println!("cargo:rustc-link-lib=cublasLt");
}
+ if cfg!(feature = "rocm") {
+ config.define("LLAMA_HIPBLAS", "ON");
+ config.define("CMAKE_C_COMPILER", "/opt/rocm/llvm/bin/clang");
+ config.define("CMAKE_CXX_COMPILER", "/opt/rocm/llvm/bin/clang++");
+ println!("cargo:rustc-link-search=native=/opt/rocm/hipblas/lib");
+ println!("cargo:rustc-link-search=native=/opt/rocm/hipblaslt/lib");
+ println!("cargo:rustc-link-lib=hipblas");
+ println!("cargo:rustc-link-lib=hipblaslt");
+ }
+ if cfg!(feature = "oneapi") {
+ config.define("LLAMA_BLAS", "ON");
+ config.define("LLAMA_BLAS_VENDOR", "Intel10_64lp");
+ println!("cargo:rustc-link-search=native=/opt/intel/oneapi/mkl/latest/lib");
+ println!("cargo:rustc-link-lib=mkl_rt");
+ println!("cargo:rustc-link-lib=pthread");
+ println!("cargo:rustc-link-lib=m");
+ println!("cargo:rustc-link-lib=dl");
+ }
let dst = config.build();
println!("cargo:rustc-link-search=native={}/build", dst.display());
diff --git a/crates/tabby/Cargo.toml b/crates/tabby/Cargo.toml
index 2c804e36f48..ce9835523e8 100644
--- a/crates/tabby/Cargo.toml
+++ b/crates/tabby/Cargo.toml
@@ -7,6 +7,8 @@ edition = "2021"
default = ["ee"]
ee = ["dep:tabby-webserver"]
cuda = ["llama-cpp-bindings/cuda"]
+rocm = ["llama-cpp-bindings/rocm"]
+oneapi = ["llama-cpp-bindings/oneapi"]
experimental-http = ["dep:http-api-bindings"]
[dependencies]
diff --git a/oneapi.Dockerfile b/oneapi.Dockerfile
new file mode 100644
index 00000000000..0ded05d3822
--- /dev/null
+++ b/oneapi.Dockerfile
@@ -0,0 +1,61 @@
+ARG UBUNTU_VERSION=22.04
+# This needs to generally match the container host's environment.
+ARG ONEAPI_VERSION=2024.0.0
+# Target the CUDA build image
+ARG BASE_ONEAPI_DEV_CONTAINER="intel/oneapi-basekit:${ONEAPI_VERSION}-devel-ubuntu${UBUNTU_VERSION}"
+# Target the CUDA runtime image
+ARG BASE_ONEAPI_RUN_CONTAINER="intel/oneapi-runtime:${ONEAPI_VERSION}-devel-ubuntu${UBUNTU_VERSION}"
+
+FROM ${BASE_ONEAPI_DEV_CONTAINER} as build
+
+# Rust toolchain version
+ARG RUST_TOOLCHAIN=stable
+
+ENV DEBIAN_FRONTEND=noninteractive
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ curl \
+ pkg-config \
+ libssl-dev \
+ protobuf-compiler \
+ git \
+ cmake \
+ && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# setup rust.
+RUN curl https://sh.rustup.rs -sSf | bash -s -- --default-toolchain ${RUST_TOOLCHAIN} -y
+ENV PATH="/root/.cargo/bin:${PATH}"
+
+WORKDIR /root/workspace
+
+RUN mkdir -p /opt/tabby/bin
+RUN mkdir -p /opt/tabby/lib
+RUN mkdir -p target
+
+COPY . .
+
+RUN --mount=type=cache,target=/usr/local/cargo/registry \
+ --mount=type=cache,target=/root/workspace/target \
+ cargo build --features oneapi --release --package tabby && \
+ cp target/release/tabby /opt/tabby/bin/
+
+FROM ${BASE_ONEAPI_RUN_CONTAINER} as runtime
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ git \
+ && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# Disable safe directory in docker
+# Context: https://github.com/git/git/commit/8959555cee7ec045958f9b6dd62e541affb7e7d9
+RUN git config --system --add safe.directory "*"
+
+COPY --from=build /opt/tabby /opt/tabby
+
+ENV TABBY_ROOT=/data
+
+ENTRYPOINT ["/opt/tabby/bin/tabby"]
diff --git a/rocm.Dockerfile b/rocm.Dockerfile
new file mode 100644
index 00000000000..f5314376958
--- /dev/null
+++ b/rocm.Dockerfile
@@ -0,0 +1,61 @@
+ARG UBUNTU_VERSION=22.04
+# This needs to generally match the container host's environment.
+ARG ROCM_VERSION=5.7
+# Target the CUDA build image
+ARG BASE_ROCM_DEV_CONTAINER="rocm/dev-ubuntu-${UBUNTU_VERSION}:${ROCM_VERSION}"
+# Target the CUDA runtime image
+ARG BASE_ROCM_RUN_CONTAINER="rocm/dev-ubuntu-${UBUNTU_VERSION}:${ROCM_VERSION}"
+
+FROM ${BASE_ROCM_DEV_CONTAINER} as build
+
+# Rust toolchain version
+ARG RUST_TOOLCHAIN=stable
+
+ENV DEBIAN_FRONTEND=noninteractive
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ curl \
+ pkg-config \
+ libssl-dev \
+ protobuf-compiler \
+ git \
+ cmake \
+ && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# setup rust.
+RUN curl https://sh.rustup.rs -sSf | bash -s -- --default-toolchain ${RUST_TOOLCHAIN} -y
+ENV PATH="/root/.cargo/bin:${PATH}"
+
+WORKDIR /root/workspace
+
+RUN mkdir -p /opt/tabby/bin
+RUN mkdir -p /opt/tabby/lib
+RUN mkdir -p target
+
+COPY . .
+
+RUN --mount=type=cache,target=/usr/local/cargo/registry \
+ --mount=type=cache,target=/root/workspace/target \
+ cargo build --features rocm --release --package tabby && \
+ cp target/release/tabby /opt/tabby/bin/
+
+FROM ${BASE_ROCM_RUN_CONTAINER} as runtime
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ git \
+ && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# Disable safe directory in docker
+# Context: https://github.com/git/git/commit/8959555cee7ec045958f9b6dd62e541affb7e7d9
+RUN git config --system --add safe.directory "*"
+
+COPY --from=build /opt/tabby /opt/tabby
+
+ENV TABBY_ROOT=/data
+
+ENTRYPOINT ["/opt/tabby/bin/tabby"]
From 5732d7ddf0916c6bc15f59cbfe59d8b1f9cb9731 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sat, 25 Nov 2023 21:55:33 +0100
Subject: [PATCH 02/25] Improved rocm build
---
.dockerignore | 4 ++++
crates/llama-cpp-bindings/build.rs | 3 +--
rocm.Dockerfile | 4 ++--
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/.dockerignore b/.dockerignore
index de70e0d1677..dc662c389cf 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,2 +1,6 @@
+ci
+clients
+.github
+python
**/target
**/node_modules
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index 59266f632b8..431e388615b 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -35,10 +35,9 @@ fn main() {
config.define("LLAMA_HIPBLAS", "ON");
config.define("CMAKE_C_COMPILER", "/opt/rocm/llvm/bin/clang");
config.define("CMAKE_CXX_COMPILER", "/opt/rocm/llvm/bin/clang++");
+ println!("cargo:rustc-link-arg=-Wl,--copy-dt-needed-entries");
println!("cargo:rustc-link-search=native=/opt/rocm/hipblas/lib");
- println!("cargo:rustc-link-search=native=/opt/rocm/hipblaslt/lib");
println!("cargo:rustc-link-lib=hipblas");
- println!("cargo:rustc-link-lib=hipblaslt");
}
if cfg!(feature = "oneapi") {
config.define("LLAMA_BLAS", "ON");
diff --git a/rocm.Dockerfile b/rocm.Dockerfile
index f5314376958..87ccd51acf1 100644
--- a/rocm.Dockerfile
+++ b/rocm.Dockerfile
@@ -2,9 +2,9 @@ ARG UBUNTU_VERSION=22.04
# This needs to generally match the container host's environment.
ARG ROCM_VERSION=5.7
# Target the CUDA build image
-ARG BASE_ROCM_DEV_CONTAINER="rocm/dev-ubuntu-${UBUNTU_VERSION}:${ROCM_VERSION}"
+ARG BASE_ROCM_DEV_CONTAINER="rocm/dev-ubuntu-${UBUNTU_VERSION}:${ROCM_VERSION}-complete"
# Target the CUDA runtime image
-ARG BASE_ROCM_RUN_CONTAINER="rocm/dev-ubuntu-${UBUNTU_VERSION}:${ROCM_VERSION}"
+ARG BASE_ROCM_RUN_CONTAINER="rocm/dev-ubuntu-${UBUNTU_VERSION}:${ROCM_VERSION}-complete"
FROM ${BASE_ROCM_DEV_CONTAINER} as build
From 1e05350d71868c911c34fa5d1d4eebd790405f81 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sat, 25 Nov 2023 22:48:26 +0100
Subject: [PATCH 03/25] Added options for OneAPI and ROCm
---
crates/tabby/src/main.rs | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/crates/tabby/src/main.rs b/crates/tabby/src/main.rs
index fe7c4a4ad7b..a4d6fc1c6a8 100644
--- a/crates/tabby/src/main.rs
+++ b/crates/tabby/src/main.rs
@@ -69,6 +69,14 @@ pub enum Device {
#[strum(serialize = "cuda")]
Cuda,
+ #[cfg(feature = "rocm")]
+ #[strum(serialize = "rocm")]
+ Rocm,
+
+ #[cfg(feature = "oneapi")]
+ #[strum(serialize = "oneapi")]
+ OneApi,
+
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
#[strum(serialize = "metal")]
Metal,
@@ -89,7 +97,17 @@ impl Device {
*self == Device::Cuda
}
- #[cfg(not(any(all(target_os = "macos", target_arch = "aarch64"), feature = "cuda")))]
+ #[cfg(feature = "rocm")]
+ pub fn ggml_use_gpu(&self) -> bool {
+ *self == Device::Rocm
+ }
+
+ #[cfg(feature = "oneapi")]
+ pub fn ggml_use_gpu(&self) -> bool {
+ *self == Device::OneApi
+ }
+
+ #[cfg(not(any(all(target_os = "macos", target_arch = "aarch64"), feature = "cuda", feature = "rocm", feature = "oneapi")))]
pub fn ggml_use_gpu(&self) -> bool {
false
}
From 3496bb9b863758ee1eb2d32a7ce56fef3a1c5fe1 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 26 Nov 2023 01:47:01 +0100
Subject: [PATCH 04/25] Build llama using icx
---
crates/llama-cpp-bindings/build.rs | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index 431e388615b..e79b1875e7a 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -1,3 +1,4 @@
+use std::env::var;
use std::path::Path;
use cmake::Config;
@@ -40,10 +41,29 @@ fn main() {
println!("cargo:rustc-link-lib=hipblas");
}
if cfg!(feature = "oneapi") {
+ let mkl_root = var("MKLROOT").expect("MKLROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
+ let compiler_root = var("CMPLR_ROOT").expect("CMPLR_ROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
config.define("LLAMA_BLAS", "ON");
config.define("LLAMA_BLAS_VENDOR", "Intel10_64lp");
- println!("cargo:rustc-link-search=native=/opt/intel/oneapi/mkl/latest/lib");
- println!("cargo:rustc-link-lib=mkl_rt");
+ config.define("C_FLAGS", "-fiopenmp -fopenmp-targets=spir64 -m64 -DMKL_ILP64");
+ config.define("CXX_FLAGS", "-fiopenmp -fopenmp-targets=spir64 -m64 -DMKL_ILP64");
+ config.define("CMAKE_C_COMPILER", format!("{}/bin/icx", compiler_root));
+ config.define("CMAKE_CXX_COMPILER", format!("{}/bin/icpx", compiler_root));
+ println!("cargo:rustc-link-arg=-fiopenmp");
+ println!("cargo:rustc-link-arg=-fopenmp-targets=spir64");
+ println!("cargo:rustc-link-arg=-fsycl");
+ println!("cargo:rustc-link-arg=-Wl,--no-as-needed");
+ println!("cargo:rustc-link-search=native={}/lib", compiler_root);
+ println!("cargo:rustc-link-search=native={}/lib", mkl_root);
+ println!("cargo:rustc-link-lib=intlc");
+ println!("cargo:rustc-link-lib=svml");
+ println!("cargo:rustc-link-lib=mkl_sycl_blas");
+ println!("cargo:rustc-link-lib=mkl_intel_ilp64");
+ println!("cargo:rustc-link-lib=mkl_intel_thread");
+ println!("cargo:rustc-link-lib=mkl_core");
+ println!("cargo:rustc-link-lib=iomp5");
+ println!("cargo:rustc-link-lib=sycl");
+ println!("cargo:rustc-link-lib=stdc++");
println!("cargo:rustc-link-lib=pthread");
println!("cargo:rustc-link-lib=m");
println!("cargo:rustc-link-lib=dl");
From 609847512c147e2591cb492cac1f2c6947cc4168 Mon Sep 17 00:00:00 2001
From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com>
Date: Sun, 26 Nov 2023 02:49:49 +0000
Subject: [PATCH 05/25] [autofix.ci] apply automated fixes
---
crates/llama-cpp-bindings/build.rs | 19 +++++++++++++------
crates/tabby/src/main.rs | 7 ++++++-
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index e79b1875e7a..78b8a8c6bcf 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -1,5 +1,4 @@
-use std::env::var;
-use std::path::Path;
+use std::{env::var, path::Path};
use cmake::Config;
@@ -41,12 +40,20 @@ fn main() {
println!("cargo:rustc-link-lib=hipblas");
}
if cfg!(feature = "oneapi") {
- let mkl_root = var("MKLROOT").expect("MKLROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
- let compiler_root = var("CMPLR_ROOT").expect("CMPLR_ROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
+ let mkl_root = var("MKLROOT")
+ .expect("MKLROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
+ let compiler_root = var("CMPLR_ROOT")
+ .expect("CMPLR_ROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
config.define("LLAMA_BLAS", "ON");
config.define("LLAMA_BLAS_VENDOR", "Intel10_64lp");
- config.define("C_FLAGS", "-fiopenmp -fopenmp-targets=spir64 -m64 -DMKL_ILP64");
- config.define("CXX_FLAGS", "-fiopenmp -fopenmp-targets=spir64 -m64 -DMKL_ILP64");
+ config.define(
+ "C_FLAGS",
+ "-fiopenmp -fopenmp-targets=spir64 -m64 -DMKL_ILP64",
+ );
+ config.define(
+ "CXX_FLAGS",
+ "-fiopenmp -fopenmp-targets=spir64 -m64 -DMKL_ILP64",
+ );
config.define("CMAKE_C_COMPILER", format!("{}/bin/icx", compiler_root));
config.define("CMAKE_CXX_COMPILER", format!("{}/bin/icpx", compiler_root));
println!("cargo:rustc-link-arg=-fiopenmp");
diff --git a/crates/tabby/src/main.rs b/crates/tabby/src/main.rs
index a4d6fc1c6a8..b626abed97a 100644
--- a/crates/tabby/src/main.rs
+++ b/crates/tabby/src/main.rs
@@ -107,7 +107,12 @@ impl Device {
*self == Device::OneApi
}
- #[cfg(not(any(all(target_os = "macos", target_arch = "aarch64"), feature = "cuda", feature = "rocm", feature = "oneapi")))]
+ #[cfg(not(any(
+ all(target_os = "macos", target_arch = "aarch64"),
+ feature = "cuda",
+ feature = "rocm",
+ feature = "oneapi"
+ )))]
pub fn ggml_use_gpu(&self) -> bool {
false
}
From 7d38fc49f3a5bc538319ad91f6f9b65268b8a52c Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 26 Nov 2023 03:59:59 +0100
Subject: [PATCH 06/25] Fixed rocm image
---
.dockerignore | 1 +
crates/llama-cpp-bindings/build.rs | 14 ++++++++++----
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/.dockerignore b/.dockerignore
index dc662c389cf..ca65e5c7b99 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,3 +1,4 @@
+.idea
ci
clients
.github
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index 78b8a8c6bcf..4bdb5bea399 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -32,11 +32,18 @@ fn main() {
println!("cargo:rustc-link-lib=cublasLt");
}
if cfg!(feature = "rocm") {
+ let rocm_root = "/opt/rocm";
+ //config.generator("Ninja");
config.define("LLAMA_HIPBLAS", "ON");
- config.define("CMAKE_C_COMPILER", "/opt/rocm/llvm/bin/clang");
- config.define("CMAKE_CXX_COMPILER", "/opt/rocm/llvm/bin/clang++");
+ config.define("CMAKE_C_COMPILER", format!("{}/llvm/bin/clang", rocm_root));
+ config.define("CMAKE_CXX_COMPILER", format!("{}/llvm/bin/clang++", rocm_root));
+ config.define("AMDGPU_TARGETS", "gfx803;gfx900;gfx906:xnack-;gfx908:xnack-;gfx90a:xnack+;gfx90a:xnack-;gfx940;gfx941;gfx942;gfx1010;gfx1012;gfx1030;gfx1100;gfx1101;gfx1102");
println!("cargo:rustc-link-arg=-Wl,--copy-dt-needed-entries");
- println!("cargo:rustc-link-search=native=/opt/rocm/hipblas/lib");
+ println!("cargo:rustc-link-search=native={}/hip/lib", rocm_root);
+ println!("cargo:rustc-link-search=native={}/rocblas/lib", rocm_root);
+ println!("cargo:rustc-link-search=native={}/hipblas/lib", rocm_root);
+ println!("cargo:rustc-link-lib=amdhip64");
+ println!("cargo:rustc-link-lib=rocblas");
println!("cargo:rustc-link-lib=hipblas");
}
if cfg!(feature = "oneapi") {
@@ -70,7 +77,6 @@ fn main() {
println!("cargo:rustc-link-lib=mkl_core");
println!("cargo:rustc-link-lib=iomp5");
println!("cargo:rustc-link-lib=sycl");
- println!("cargo:rustc-link-lib=stdc++");
println!("cargo:rustc-link-lib=pthread");
println!("cargo:rustc-link-lib=m");
println!("cargo:rustc-link-lib=dl");
From 4f90c98e6ab3fe3ab4d921ba610b42bc168f850a Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 26 Nov 2023 04:45:19 +0100
Subject: [PATCH 07/25] Build ROCm
---
.github/workflows/docker.yml | 45 +++++++++++++++++++++++++++++++----
Dockerfile => cuda.Dockerfile | 0
2 files changed, 40 insertions(+), 5 deletions(-)
rename Dockerfile => cuda.Dockerfile (100%)
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 1e7482119d1..58ee2b6b4a3 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -50,7 +50,10 @@ jobs:
# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
- uses: docker/setup-buildx-action@v2.0.0
+ uses: docker/setup-buildx-action@v3.0.0
+ with:
+ # Needed to support OCI annotations
+ version: v0.12.0
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
@@ -78,7 +81,7 @@ jobs:
- name: Docker meta
id: meta
- uses: docker/metadata-action@v4
+ uses: docker/metadata-action@v5.0.0
with:
# list of Docker images to use as base name for tags
images: |
@@ -91,17 +94,50 @@ jobs:
type=schedule,pattern={{date 'YYYYMMDD'}}
type=semver,pattern={{version}}
+ - name: Docker meta for ROCm
+ id: meta-rocm
+ uses: docker/metadata-action@v5.0.0
+ with:
+ # list of Docker images to use as base name for tags
+ images: |
+ ghcr.io/${{ env.IMAGE_NAME }}/rocm
+ ${{ env.IMAGE_NAME }}-rocm
+ # generate Docker tags based on the following events/attributes
+ variant: rocm
+ tags: |
+ type=raw,value={{branch}}-{{sha}},enable=${{ startsWith(github.ref, 'refs/heads') }}
+ type=schedule,pattern=nightly
+ type=schedule,pattern={{date 'YYYYMMDD'}}
+ type=semver,pattern={{version}}
+
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
- uses: docker/build-push-action@v3.1.1
+ uses: docker/build-push-action@v5.1.0
with:
- file: Dockerfile
+ file: cuda.Dockerfile
push: true
context: .
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+ annotations: ${{ steps.meta.outputs.labels }}
+ cache-from: ${{ steps.cache.outputs.cache-from }}
+ cache-to: ${{ steps.cache.outputs.cache-to }}
+ build-args: RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+
+ # Build and push Docker image with Buildx (don't push on PR)
+ # https://github.com/docker/build-push-action
+ - name: Build and push Docker image for ROCm
+ id: build-and-push-rocm
+ uses: docker/build-push-action@v5.1.0
+ with:
+ file: rocm.Dockerfile
+ push: true
+ context: .
+ tags: ${{ steps.meta-rocm.outputs.tags }}
+ labels: ${{ steps.meta-rocm.outputs.labels }}
+ annotations: ${{ steps.meta-rocm.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
build-args: RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
@@ -112,4 +148,3 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
repository: tabbyml/tabby
-
diff --git a/Dockerfile b/cuda.Dockerfile
similarity index 100%
rename from Dockerfile
rename to cuda.Dockerfile
From c0804cb96c9c05e742b23c2e115e0ed18a4441e4 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 26 Nov 2023 19:46:10 +0100
Subject: [PATCH 08/25] Tried to adjust compile flags for SYCL
---
crates/llama-cpp-bindings/build.rs | 62 +++++++++++++++++++++---------
crates/tabby/build.rs | 30 +++++++++++++++
oneapi.Dockerfile | 15 ++++++--
3 files changed, 86 insertions(+), 21 deletions(-)
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index 4bdb5bea399..66183d453e2 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -4,6 +4,20 @@ use cmake::Config;
fn main() {
const LLAMA_CMAKE_PATH: &str = "llama.cpp/CMakeLists.txt";
+ let intel_compile_flags: Vec<&str> = vec![
+ "-fsycl",
+ "-fsycl-targets=spir64_gen",
+ "-fiopenmp",
+ "-fopenmp-targets=spir64_gen",
+ "-m64",
+ "-DMKL_ILP64",
+ "-qopt-report=3",
+ "-O3",
+ "-Xs",
+ "-device skl",
+ //"-device *",
+ ];
+ const AMDGPU_TARGETS: &str = "gfx803;gfx900;gfx906:xnack-;gfx908:xnack-;gfx90a:xnack+;gfx90a:xnack-;gfx940;gfx941;gfx942;gfx1010;gfx1012;gfx1030;gfx1100;gfx1101;gfx1102";
assert!(
Path::new(LLAMA_CMAKE_PATH).exists(),
@@ -33,11 +47,13 @@ fn main() {
}
if cfg!(feature = "rocm") {
let rocm_root = "/opt/rocm";
- //config.generator("Ninja");
config.define("LLAMA_HIPBLAS", "ON");
config.define("CMAKE_C_COMPILER", format!("{}/llvm/bin/clang", rocm_root));
- config.define("CMAKE_CXX_COMPILER", format!("{}/llvm/bin/clang++", rocm_root));
- config.define("AMDGPU_TARGETS", "gfx803;gfx900;gfx906:xnack-;gfx908:xnack-;gfx90a:xnack+;gfx90a:xnack-;gfx940;gfx941;gfx942;gfx1010;gfx1012;gfx1030;gfx1100;gfx1101;gfx1102");
+ config.define(
+ "CMAKE_CXX_COMPILER",
+ format!("{}/llvm/bin/clang++", rocm_root),
+ );
+ config.define("AMDGPU_TARGETS", AMDGPU_TARGETS);
println!("cargo:rustc-link-arg=-Wl,--copy-dt-needed-entries");
println!("cargo:rustc-link-search=native={}/hip/lib", rocm_root);
println!("cargo:rustc-link-search=native={}/rocblas/lib", rocm_root);
@@ -53,25 +69,25 @@ fn main() {
.expect("CMPLR_ROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
config.define("LLAMA_BLAS", "ON");
config.define("LLAMA_BLAS_VENDOR", "Intel10_64lp");
- config.define(
- "C_FLAGS",
- "-fiopenmp -fopenmp-targets=spir64 -m64 -DMKL_ILP64",
- );
- config.define(
- "CXX_FLAGS",
- "-fiopenmp -fopenmp-targets=spir64 -m64 -DMKL_ILP64",
- );
+ config.define("C_FLAGS", intel_compile_flags.join(" "));
+ config.define("CXX_FLAGS", intel_compile_flags.join(" "));
config.define("CMAKE_C_COMPILER", format!("{}/bin/icx", compiler_root));
config.define("CMAKE_CXX_COMPILER", format!("{}/bin/icpx", compiler_root));
println!("cargo:rustc-link-arg=-fiopenmp");
- println!("cargo:rustc-link-arg=-fopenmp-targets=spir64");
+ println!("cargo:rustc-link-arg=-fopenmp-targets=spir64_gen");
println!("cargo:rustc-link-arg=-fsycl");
println!("cargo:rustc-link-arg=-Wl,--no-as-needed");
println!("cargo:rustc-link-search=native={}/lib", compiler_root);
println!("cargo:rustc-link-search=native={}/lib", mkl_root);
- println!("cargo:rustc-link-lib=intlc");
println!("cargo:rustc-link-lib=svml");
println!("cargo:rustc-link-lib=mkl_sycl_blas");
+ println!("cargo:rustc-link-lib=mkl_sycl_lapack");
+ println!("cargo:rustc-link-lib=mkl_sycl_dft");
+ println!("cargo:rustc-link-lib=mkl_sycl_sparse");
+ println!("cargo:rustc-link-lib=mkl_sycl_vm");
+ println!("cargo:rustc-link-lib=mkl_sycl_rng");
+ println!("cargo:rustc-link-lib=mkl_sycl_stats");
+ println!("cargo:rustc-link-lib=mkl_sycl_data_fitting");
println!("cargo:rustc-link-lib=mkl_intel_ilp64");
println!("cargo:rustc-link-lib=mkl_intel_thread");
println!("cargo:rustc-link-lib=mkl_core");
@@ -85,10 +101,20 @@ fn main() {
let dst = config.build();
println!("cargo:rustc-link-search=native={}/build", dst.display());
- cxx_build::bridge("src/lib.rs")
+ let crate_dir = var("CARGO_MANIFEST_DIR").unwrap();
+
+ let mut build = cxx_build::bridge("src/lib.rs");
+ if cfg!(feature = "oneapi") {
+ let compiler_root = var("CMPLR_ROOT").unwrap();
+ build.compiler(format!("{}/bin/icpx", compiler_root));
+ for flag in intel_compile_flags {
+ build.flag(flag);
+ }
+ }
+ build
.file("src/engine.cc")
- .flag_if_supported("-Iinclude")
- .flag_if_supported("-Illama.cpp")
- .flag_if_supported("-std=c++14")
- .compile("cxxbridge");
+ .include(format!("{}/include", crate_dir))
+ .include("llama.cpp")
+ .flag_if_supported("-std=c++14");
+ build.compile("cxxbridge");
}
diff --git a/crates/tabby/build.rs b/crates/tabby/build.rs
index dc138d23067..4c876d1429f 100644
--- a/crates/tabby/build.rs
+++ b/crates/tabby/build.rs
@@ -1,8 +1,38 @@
+use std::env;
use std::error::Error;
use vergen::EmitBuilder;
fn main() -> Result<(), Box> {
+ if cfg!(feature = "oneapi") {
+ let mkl_root = env::var("MKLROOT")
+ .expect("MKLROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
+ let compiler_root = env::var("CMPLR_ROOT")
+ .expect("CMPLR_ROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
+ println!("cargo:rustc-link-arg=-fiopenmp");
+ println!("cargo:rustc-link-arg=-fopenmp-targets=spir64_gen");
+ println!("cargo:rustc-link-arg=-fsycl");
+ println!("cargo:rustc-link-arg=-Wl,--no-as-needed");
+ println!("cargo:rustc-link-search=native={}/lib", compiler_root);
+ println!("cargo:rustc-link-search=native={}/lib", mkl_root);
+ println!("cargo:rustc-link-lib=svml");
+ println!("cargo:rustc-link-lib=mkl_sycl_blas");
+ println!("cargo:rustc-link-lib=mkl_sycl_lapack");
+ println!("cargo:rustc-link-lib=mkl_sycl_dft");
+ println!("cargo:rustc-link-lib=mkl_sycl_sparse");
+ println!("cargo:rustc-link-lib=mkl_sycl_vm");
+ println!("cargo:rustc-link-lib=mkl_sycl_rng");
+ println!("cargo:rustc-link-lib=mkl_sycl_stats");
+ println!("cargo:rustc-link-lib=mkl_sycl_data_fitting");
+ println!("cargo:rustc-link-lib=mkl_intel_ilp64");
+ println!("cargo:rustc-link-lib=mkl_intel_thread");
+ println!("cargo:rustc-link-lib=mkl_core");
+ println!("cargo:rustc-link-lib=iomp5");
+ println!("cargo:rustc-link-lib=sycl");
+ println!("cargo:rustc-link-lib=pthread");
+ println!("cargo:rustc-link-lib=m");
+ println!("cargo:rustc-link-lib=dl");
+ }
// touch
EmitBuilder::builder()
.all_build()
diff --git a/oneapi.Dockerfile b/oneapi.Dockerfile
index 0ded05d3822..263be55489d 100644
--- a/oneapi.Dockerfile
+++ b/oneapi.Dockerfile
@@ -20,6 +20,7 @@ RUN apt-get update && \
protobuf-compiler \
git \
cmake \
+ intel-opencl-icd \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
@@ -28,6 +29,12 @@ RUN apt-get update && \
RUN curl https://sh.rustup.rs -sSf | bash -s -- --default-toolchain ${RUST_TOOLCHAIN} -y
ENV PATH="/root/.cargo/bin:${PATH}"
+RUN update-alternatives --install "/usr/bin/cc" "cc" "${CMPLR_ROOT}/bin/icx" 100
+RUN update-alternatives --install "/usr/bin/c++" "c++" "${CMPLR_ROOT}/bin/icpx" 100
+RUN update-alternatives --install "/usr/bin/ld" "ld" "${CMPLR_ROOT}/bin/compiler/ld.lld" 100
+ENV RUSTFLAGS="-C link-args=-fPIC -C link-args=-fsycl -C link-args=-L${CMPLR_ROOT}/lib -C link-args=-lsycl -C link-args=-lintlc"
+ENV OPENSSL_NO_VENDOR=1
+
WORKDIR /root/workspace
RUN mkdir -p /opt/tabby/bin
@@ -36,9 +43,11 @@ RUN mkdir -p target
COPY . .
-RUN --mount=type=cache,target=/usr/local/cargo/registry \
- --mount=type=cache,target=/root/workspace/target \
- cargo build --features oneapi --release --package tabby && \
+#RUN --mount=type=cache,target=/usr/local/cargo/registry \
+# --mount=type=cache,target=/root/workspace/target \
+# cargo build --features oneapi --release --package tabby && \
+# cp target/release/tabby /opt/tabby/bin/
+RUN cargo build --features oneapi --release --package tabby && \
cp target/release/tabby /opt/tabby/bin/
FROM ${BASE_ONEAPI_RUN_CONTAINER} as runtime
From 8d56d37789bdb04f705c31a93ceb139532aabecd Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 26 Nov 2023 19:56:19 +0100
Subject: [PATCH 09/25] Removed references to oneAPI
---
crates/llama-cpp-bindings/Cargo.toml | 1 -
crates/llama-cpp-bindings/build.rs | 68 ++-------------------------
crates/tabby/Cargo.toml | 1 -
crates/tabby/build.rs | 30 ------------
crates/tabby/src/main.rs | 31 +++++-------
oneapi.Dockerfile | 70 ----------------------------
6 files changed, 16 insertions(+), 185 deletions(-)
delete mode 100644 oneapi.Dockerfile
diff --git a/crates/llama-cpp-bindings/Cargo.toml b/crates/llama-cpp-bindings/Cargo.toml
index 5cccfe8ff3e..eb64ea3c9b3 100644
--- a/crates/llama-cpp-bindings/Cargo.toml
+++ b/crates/llama-cpp-bindings/Cargo.toml
@@ -6,7 +6,6 @@ edition = "2021"
[features]
cuda = []
rocm = []
-oneapi = []
[build-dependencies]
cxx-build = "1.0"
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index 66183d453e2..ccca52341c8 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -1,22 +1,9 @@
-use std::{env::var, path::Path};
+use std::path::Path;
use cmake::Config;
fn main() {
const LLAMA_CMAKE_PATH: &str = "llama.cpp/CMakeLists.txt";
- let intel_compile_flags: Vec<&str> = vec![
- "-fsycl",
- "-fsycl-targets=spir64_gen",
- "-fiopenmp",
- "-fopenmp-targets=spir64_gen",
- "-m64",
- "-DMKL_ILP64",
- "-qopt-report=3",
- "-O3",
- "-Xs",
- "-device skl",
- //"-device *",
- ];
const AMDGPU_TARGETS: &str = "gfx803;gfx900;gfx906:xnack-;gfx908:xnack-;gfx90a:xnack+;gfx90a:xnack-;gfx940;gfx941;gfx942;gfx1010;gfx1012;gfx1030;gfx1100;gfx1101;gfx1102";
assert!(
@@ -62,59 +49,14 @@ fn main() {
println!("cargo:rustc-link-lib=rocblas");
println!("cargo:rustc-link-lib=hipblas");
}
- if cfg!(feature = "oneapi") {
- let mkl_root = var("MKLROOT")
- .expect("MKLROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
- let compiler_root = var("CMPLR_ROOT")
- .expect("CMPLR_ROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
- config.define("LLAMA_BLAS", "ON");
- config.define("LLAMA_BLAS_VENDOR", "Intel10_64lp");
- config.define("C_FLAGS", intel_compile_flags.join(" "));
- config.define("CXX_FLAGS", intel_compile_flags.join(" "));
- config.define("CMAKE_C_COMPILER", format!("{}/bin/icx", compiler_root));
- config.define("CMAKE_CXX_COMPILER", format!("{}/bin/icpx", compiler_root));
- println!("cargo:rustc-link-arg=-fiopenmp");
- println!("cargo:rustc-link-arg=-fopenmp-targets=spir64_gen");
- println!("cargo:rustc-link-arg=-fsycl");
- println!("cargo:rustc-link-arg=-Wl,--no-as-needed");
- println!("cargo:rustc-link-search=native={}/lib", compiler_root);
- println!("cargo:rustc-link-search=native={}/lib", mkl_root);
- println!("cargo:rustc-link-lib=svml");
- println!("cargo:rustc-link-lib=mkl_sycl_blas");
- println!("cargo:rustc-link-lib=mkl_sycl_lapack");
- println!("cargo:rustc-link-lib=mkl_sycl_dft");
- println!("cargo:rustc-link-lib=mkl_sycl_sparse");
- println!("cargo:rustc-link-lib=mkl_sycl_vm");
- println!("cargo:rustc-link-lib=mkl_sycl_rng");
- println!("cargo:rustc-link-lib=mkl_sycl_stats");
- println!("cargo:rustc-link-lib=mkl_sycl_data_fitting");
- println!("cargo:rustc-link-lib=mkl_intel_ilp64");
- println!("cargo:rustc-link-lib=mkl_intel_thread");
- println!("cargo:rustc-link-lib=mkl_core");
- println!("cargo:rustc-link-lib=iomp5");
- println!("cargo:rustc-link-lib=sycl");
- println!("cargo:rustc-link-lib=pthread");
- println!("cargo:rustc-link-lib=m");
- println!("cargo:rustc-link-lib=dl");
- }
let dst = config.build();
println!("cargo:rustc-link-search=native={}/build", dst.display());
- let crate_dir = var("CARGO_MANIFEST_DIR").unwrap();
-
- let mut build = cxx_build::bridge("src/lib.rs");
- if cfg!(feature = "oneapi") {
- let compiler_root = var("CMPLR_ROOT").unwrap();
- build.compiler(format!("{}/bin/icpx", compiler_root));
- for flag in intel_compile_flags {
- build.flag(flag);
- }
- }
- build
+ cxx_build::bridge("src/lib.rs")
.file("src/engine.cc")
- .include(format!("{}/include", crate_dir))
+ .include("include")
.include("llama.cpp")
- .flag_if_supported("-std=c++14");
- build.compile("cxxbridge");
+ .flag_if_supported("-std=c++14")
+ .compile("cxxbridge");
}
diff --git a/crates/tabby/Cargo.toml b/crates/tabby/Cargo.toml
index ce9835523e8..904c0ccdb74 100644
--- a/crates/tabby/Cargo.toml
+++ b/crates/tabby/Cargo.toml
@@ -8,7 +8,6 @@ default = ["ee"]
ee = ["dep:tabby-webserver"]
cuda = ["llama-cpp-bindings/cuda"]
rocm = ["llama-cpp-bindings/rocm"]
-oneapi = ["llama-cpp-bindings/oneapi"]
experimental-http = ["dep:http-api-bindings"]
[dependencies]
diff --git a/crates/tabby/build.rs b/crates/tabby/build.rs
index 4c876d1429f..dc138d23067 100644
--- a/crates/tabby/build.rs
+++ b/crates/tabby/build.rs
@@ -1,38 +1,8 @@
-use std::env;
use std::error::Error;
use vergen::EmitBuilder;
fn main() -> Result<(), Box> {
- if cfg!(feature = "oneapi") {
- let mkl_root = env::var("MKLROOT")
- .expect("MKLROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
- let compiler_root = env::var("CMPLR_ROOT")
- .expect("CMPLR_ROOT needs to be defined to compile for oneAPI (use setvars.sh to set)");
- println!("cargo:rustc-link-arg=-fiopenmp");
- println!("cargo:rustc-link-arg=-fopenmp-targets=spir64_gen");
- println!("cargo:rustc-link-arg=-fsycl");
- println!("cargo:rustc-link-arg=-Wl,--no-as-needed");
- println!("cargo:rustc-link-search=native={}/lib", compiler_root);
- println!("cargo:rustc-link-search=native={}/lib", mkl_root);
- println!("cargo:rustc-link-lib=svml");
- println!("cargo:rustc-link-lib=mkl_sycl_blas");
- println!("cargo:rustc-link-lib=mkl_sycl_lapack");
- println!("cargo:rustc-link-lib=mkl_sycl_dft");
- println!("cargo:rustc-link-lib=mkl_sycl_sparse");
- println!("cargo:rustc-link-lib=mkl_sycl_vm");
- println!("cargo:rustc-link-lib=mkl_sycl_rng");
- println!("cargo:rustc-link-lib=mkl_sycl_stats");
- println!("cargo:rustc-link-lib=mkl_sycl_data_fitting");
- println!("cargo:rustc-link-lib=mkl_intel_ilp64");
- println!("cargo:rustc-link-lib=mkl_intel_thread");
- println!("cargo:rustc-link-lib=mkl_core");
- println!("cargo:rustc-link-lib=iomp5");
- println!("cargo:rustc-link-lib=sycl");
- println!("cargo:rustc-link-lib=pthread");
- println!("cargo:rustc-link-lib=m");
- println!("cargo:rustc-link-lib=dl");
- }
// touch
EmitBuilder::builder()
.all_build()
diff --git a/crates/tabby/src/main.rs b/crates/tabby/src/main.rs
index b626abed97a..652ba4b823f 100644
--- a/crates/tabby/src/main.rs
+++ b/crates/tabby/src/main.rs
@@ -1,12 +1,3 @@
-mod routes;
-mod services;
-
-mod download;
-mod serve;
-
-#[cfg(feature = "ee")]
-mod worker;
-
use clap::{Parser, Subcommand};
use opentelemetry::{
global,
@@ -14,9 +5,19 @@ use opentelemetry::{
KeyValue,
};
use opentelemetry_otlp::WithExportConfig;
-use tabby_common::config::Config;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};
+use tabby_common::config::Config;
+
+mod routes;
+mod services;
+
+mod download;
+mod serve;
+
+#[cfg(feature = "ee")]
+mod worker;
+
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
@@ -73,10 +74,6 @@ pub enum Device {
#[strum(serialize = "rocm")]
Rocm,
- #[cfg(feature = "oneapi")]
- #[strum(serialize = "oneapi")]
- OneApi,
-
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
#[strum(serialize = "metal")]
Metal,
@@ -102,16 +99,10 @@ impl Device {
*self == Device::Rocm
}
- #[cfg(feature = "oneapi")]
- pub fn ggml_use_gpu(&self) -> bool {
- *self == Device::OneApi
- }
-
#[cfg(not(any(
all(target_os = "macos", target_arch = "aarch64"),
feature = "cuda",
feature = "rocm",
- feature = "oneapi"
)))]
pub fn ggml_use_gpu(&self) -> bool {
false
diff --git a/oneapi.Dockerfile b/oneapi.Dockerfile
deleted file mode 100644
index 263be55489d..00000000000
--- a/oneapi.Dockerfile
+++ /dev/null
@@ -1,70 +0,0 @@
-ARG UBUNTU_VERSION=22.04
-# This needs to generally match the container host's environment.
-ARG ONEAPI_VERSION=2024.0.0
-# Target the CUDA build image
-ARG BASE_ONEAPI_DEV_CONTAINER="intel/oneapi-basekit:${ONEAPI_VERSION}-devel-ubuntu${UBUNTU_VERSION}"
-# Target the CUDA runtime image
-ARG BASE_ONEAPI_RUN_CONTAINER="intel/oneapi-runtime:${ONEAPI_VERSION}-devel-ubuntu${UBUNTU_VERSION}"
-
-FROM ${BASE_ONEAPI_DEV_CONTAINER} as build
-
-# Rust toolchain version
-ARG RUST_TOOLCHAIN=stable
-
-ENV DEBIAN_FRONTEND=noninteractive
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- curl \
- pkg-config \
- libssl-dev \
- protobuf-compiler \
- git \
- cmake \
- intel-opencl-icd \
- && \
- apt-get clean && \
- rm -rf /var/lib/apt/lists/*
-
-# setup rust.
-RUN curl https://sh.rustup.rs -sSf | bash -s -- --default-toolchain ${RUST_TOOLCHAIN} -y
-ENV PATH="/root/.cargo/bin:${PATH}"
-
-RUN update-alternatives --install "/usr/bin/cc" "cc" "${CMPLR_ROOT}/bin/icx" 100
-RUN update-alternatives --install "/usr/bin/c++" "c++" "${CMPLR_ROOT}/bin/icpx" 100
-RUN update-alternatives --install "/usr/bin/ld" "ld" "${CMPLR_ROOT}/bin/compiler/ld.lld" 100
-ENV RUSTFLAGS="-C link-args=-fPIC -C link-args=-fsycl -C link-args=-L${CMPLR_ROOT}/lib -C link-args=-lsycl -C link-args=-lintlc"
-ENV OPENSSL_NO_VENDOR=1
-
-WORKDIR /root/workspace
-
-RUN mkdir -p /opt/tabby/bin
-RUN mkdir -p /opt/tabby/lib
-RUN mkdir -p target
-
-COPY . .
-
-#RUN --mount=type=cache,target=/usr/local/cargo/registry \
-# --mount=type=cache,target=/root/workspace/target \
-# cargo build --features oneapi --release --package tabby && \
-# cp target/release/tabby /opt/tabby/bin/
-RUN cargo build --features oneapi --release --package tabby && \
- cp target/release/tabby /opt/tabby/bin/
-
-FROM ${BASE_ONEAPI_RUN_CONTAINER} as runtime
-
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- git \
- && \
- apt-get clean && \
- rm -rf /var/lib/apt/lists/*
-
-# Disable safe directory in docker
-# Context: https://github.com/git/git/commit/8959555cee7ec045958f9b6dd62e541affb7e7d9
-RUN git config --system --add safe.directory "*"
-
-COPY --from=build /opt/tabby /opt/tabby
-
-ENV TABBY_ROOT=/data
-
-ENTRYPOINT ["/opt/tabby/bin/tabby"]
From dd72b82c1ef8d812c639a3c19b7f73f27aa7226e Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 26 Nov 2023 20:53:26 +0100
Subject: [PATCH 10/25] Provide info about the used device for ROCm
---
Cargo.lock | 21 +++++++++
crates/tabby/Cargo.toml | 7 +--
crates/tabby/build.rs | 4 ++
crates/tabby/src/services/health.rs | 31 +++++++++++--
crates/tabby/src/worker.rs | 9 ++--
.../(dashboard)/components/worker-card.tsx | 41 ++++++++++++++---
ee/tabby-ui/app/(dashboard)/page.tsx | 31 +++++--------
ee/tabby-ui/lib/gql/generates/gql.ts | 8 ++--
ee/tabby-ui/lib/gql/generates/graphql.ts | 9 ++--
ee/tabby-ui/lib/gql/request-documents.tsx | 4 +-
ee/tabby-ui/lib/hooks/use-health.tsx | 6 +--
ee/tabby-ui/lib/hooks/use-workers.ts | 12 ++---
ee/tabby-webserver/graphql/schema.graphql | 2 +-
ee/tabby-webserver/src/api.rs | 9 ++--
ee/tabby-webserver/src/lib.rs | 44 +++++++++----------
ee/tabby-webserver/src/server/worker.rs | 4 +-
ee/tabby-webserver/ui/404.html | 2 +-
.../_buildManifest.js | 0
.../_ssgManifest.js | 0
...00ef6e5d.js => layout-9112e2f61825d91a.js} | 2 +-
.../app/(dashboard)/page-223f244bef7bc3fe.js | 1 +
.../app/(dashboard)/page-2dac77bf7366362b.js | 1 -
.../chunks/app/layout-a709b0b21d295a91.js | 1 +
.../chunks/app/layout-ca2c7a9f923b6e61.js | 1 -
...1e9c77580f.js => page-0e44acab13f2ae38.js} | 2 +-
...1a6b57.js => main-app-564c82becf4880fe.js} | 2 +-
ee/tabby-webserver/ui/index.html | 2 +-
ee/tabby-webserver/ui/index.txt | 12 ++---
ee/tabby-webserver/ui/playground.html | 2 +-
ee/tabby-webserver/ui/playground.txt | 10 ++---
ee/tabby-webserver/ui/swagger.html | 2 +-
ee/tabby-webserver/ui/swagger.txt | 10 ++---
32 files changed, 183 insertions(+), 109 deletions(-)
rename ee/tabby-webserver/ui/_next/static/{KwTUFhDElVXkDE3jiCtD0 => -IQIiI3YS2Md2tsCaIleK}/_buildManifest.js (100%)
rename ee/tabby-webserver/ui/_next/static/{KwTUFhDElVXkDE3jiCtD0 => -IQIiI3YS2Md2tsCaIleK}/_ssgManifest.js (100%)
rename ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/{layout-3f83ef2900ef6e5d.js => layout-9112e2f61825d91a.js} (95%)
create mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js
delete mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-2dac77bf7366362b.js
create mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/layout-a709b0b21d295a91.js
delete mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/layout-ca2c7a9f923b6e61.js
rename ee/tabby-webserver/ui/_next/static/chunks/app/playground/{page-8ff3131e9c77580f.js => page-0e44acab13f2ae38.js} (99%)
rename ee/tabby-webserver/ui/_next/static/chunks/{main-app-65c258ee101a6b57.js => main-app-564c82becf4880fe.js} (67%)
diff --git a/Cargo.lock b/Cargo.lock
index 8e4dc9bf8ea..ed7c0a5b3b4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3743,6 +3743,26 @@ dependencies = [
"serde",
]
+[[package]]
+name = "rocm_smi_lib"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aab3a8127b4332d79efce5c924c79f04eb35ab4f1e540947320f86de1c9465bb"
+dependencies = [
+ "libc",
+ "rocm_smi_lib_sys",
+]
+
+[[package]]
+name = "rocm_smi_lib_sys"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc32313f54e56d303342caae5cde35e5605ba7f946735985a11c00b2b5d6479"
+dependencies = [
+ "cmake",
+ "libc",
+]
+
[[package]]
name = "rusqlite"
version = "0.29.0"
@@ -4577,6 +4597,7 @@ dependencies = [
"opentelemetry-otlp",
"regex",
"reqwest",
+ "rocm_smi_lib",
"serde",
"serde_json",
"serdeconv",
diff --git a/crates/tabby/Cargo.toml b/crates/tabby/Cargo.toml
index 904c0ccdb74..02ab17efe7e 100644
--- a/crates/tabby/Cargo.toml
+++ b/crates/tabby/Cargo.toml
@@ -6,8 +6,8 @@ edition = "2021"
[features]
default = ["ee"]
ee = ["dep:tabby-webserver"]
-cuda = ["llama-cpp-bindings/cuda"]
-rocm = ["llama-cpp-bindings/rocm"]
+cuda = ["llama-cpp-bindings/cuda", "dep:nvml-wrapper"]
+rocm = ["llama-cpp-bindings/rocm", "dep:rocm_smi_lib"]
experimental-http = ["dep:http-api-bindings"]
[dependencies]
@@ -37,7 +37,8 @@ tracing-opentelemetry = "0.18.0"
tantivy = { workspace = true }
anyhow = { workspace = true }
sysinfo = "0.29.8"
-nvml-wrapper = "0.9.0"
+nvml-wrapper = { version = "0.9.0", optional = true }
+rocm_smi_lib = { version = "0.1.14", optional = true }
http-api-bindings = { path = "../http-api-bindings", optional = true } # included when build with `experimental-http` feature
async-stream = { workspace = true }
axum-streams = { version = "0.9.1", features = ["json"] }
diff --git a/crates/tabby/build.rs b/crates/tabby/build.rs
index dc138d23067..7f827159cc8 100644
--- a/crates/tabby/build.rs
+++ b/crates/tabby/build.rs
@@ -3,6 +3,10 @@ use std::error::Error;
use vergen::EmitBuilder;
fn main() -> Result<(), Box> {
+ if cfg!(feature = "rocm") {
+ let rocm_root = "/opt/rocm";
+ println!("cargo:rustc-link-search=native={}/lib", rocm_root);
+ }
// touch
EmitBuilder::builder()
.all_build()
diff --git a/crates/tabby/src/services/health.rs b/crates/tabby/src/services/health.rs
index 5e48efe34b9..71558979f47 100644
--- a/crates/tabby/src/services/health.rs
+++ b/crates/tabby/src/services/health.rs
@@ -1,7 +1,12 @@
use std::env::consts::ARCH;
use anyhow::Result;
+#[cfg(feature = "cuda")]
use nvml_wrapper::Nvml;
+#[cfg(feature = "rocm")]
+use rocm_smi_lib::error::RocmErr;
+#[cfg(feature = "rocm")]
+use rocm_smi_lib::RocmSmi;
use serde::{Deserialize, Serialize};
use sysinfo::{CpuExt, System, SystemExt};
use utoipa::ToSchema;
@@ -18,7 +23,7 @@ pub struct HealthState {
arch: String,
cpu_info: String,
cpu_count: usize,
- cuda_devices: Vec,
+ gpu_devices: Vec,
version: Version,
}
@@ -26,7 +31,7 @@ impl HealthState {
pub fn new(model: Option<&str>, chat_model: Option<&str>, device: &Device) -> Self {
let (cpu_info, cpu_count) = read_cpu_info();
- let cuda_devices = match read_cuda_devices() {
+ let cuda_devices = match read_gpu_devices() {
Ok(s) => s,
Err(_) => vec![],
};
@@ -38,7 +43,7 @@ impl HealthState {
arch: ARCH.to_string(),
cpu_info,
cpu_count,
- cuda_devices,
+ gpu_devices: cuda_devices,
version: Version::new(),
}
}
@@ -59,7 +64,8 @@ pub fn read_cpu_info() -> (String, usize) {
(info, count)
}
-pub fn read_cuda_devices() -> Result> {
+#[cfg(feature = "cuda")]
+pub fn read_gpu_devices() -> Result> {
// In cases of MacOS or docker containers where --gpus are not specified,
// the Nvml::init() would return an error. In these scenarios, we
// assign cuda_devices to be empty, indicating that the current runtime
@@ -74,6 +80,23 @@ pub fn read_cuda_devices() -> Result> {
Ok(cuda_devices)
}
+#[cfg(feature = "rocm")]
+pub fn read_gpu_devices() -> Result, RocmErr> {
+ let rocm = RocmSmi::init()?;
+ let mut rocm_devices = vec![];
+ let device_count = rocm.get_device_count();
+ for i in 0..device_count {
+ let name = rocm.get_device_identifiers(i)?.name;
+ rocm_devices.push(name);
+ }
+ Ok(rocm_devices)
+}
+
+#[cfg(not(any(feature = "cuda", feature = "rocm",)))]
+pub fn read_gpu_devices() -> Result> {
+ Ok(vec![])
+}
+
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)]
pub struct Version {
build_date: String,
diff --git a/crates/tabby/src/worker.rs b/crates/tabby/src/worker.rs
index eedfafe7a29..69bdaacbe7f 100644
--- a/crates/tabby/src/worker.rs
+++ b/crates/tabby/src/worker.rs
@@ -3,15 +3,16 @@ use std::{env::consts::ARCH, sync::Arc};
use anyhow::Result;
use axum::{routing, Router};
use clap::Args;
-use tabby_webserver::api::{tracing_context, HubClient, WorkerKind};
use tracing::{info, warn};
+use tabby_webserver::api::{tracing_context, HubClient, WorkerKind};
+
use crate::{
routes::{self, run_app},
services::{
chat::create_chat_service,
completion::create_completion_service,
- health::{read_cpu_info, read_cuda_devices},
+ health::{read_cpu_info, read_gpu_devices},
model::download_model_if_needed,
},
Device,
@@ -105,7 +106,7 @@ impl WorkerContext {
async fn register_impl(&self, kind: WorkerKind, args: &WorkerArgs) -> Result<()> {
let (cpu_info, cpu_count) = read_cpu_info();
- let cuda_devices = read_cuda_devices().unwrap_or_default();
+ let gpu_devices = read_gpu_devices().unwrap_or_default();
let worker = self
.client
.register_worker(
@@ -117,7 +118,7 @@ impl WorkerContext {
ARCH.to_string(),
cpu_info,
cpu_count as i32,
- cuda_devices,
+ gpu_devices,
args.token.clone(),
)
.await??;
diff --git a/ee/tabby-ui/app/(dashboard)/components/worker-card.tsx b/ee/tabby-ui/app/(dashboard)/components/worker-card.tsx
index 3d38525b7eb..0b0878acb3f 100644
--- a/ee/tabby-ui/app/(dashboard)/components/worker-card.tsx
+++ b/ee/tabby-ui/app/(dashboard)/components/worker-card.tsx
@@ -1,6 +1,6 @@
-import { CardTitle, CardHeader, CardContent, Card } from '@/components/ui/card'
-import { Worker, WorkerKind } from '@/lib/gql/generates/graphql'
-import { cn } from '@/lib/utils'
+import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card'
+import {Worker, WorkerKind} from '@/lib/gql/generates/graphql'
+import {cn} from '@/lib/utils'
type RunnerType = WorkerKind | 'INDEX'
@@ -13,7 +13,7 @@ export default function RunnerCard({
name,
kind,
device,
- cudaDevices,
+ gpuDevices,
cpuCount,
cpuInfo
}: RunnerCardProps) {
@@ -78,8 +78,37 @@ export default function RunnerCard({
{device == 'cuda' &&
- cudaDevices?.length &&
- cudaDevices.map((x, i) => (
+ gpuDevices?.length &&
+ gpuDevices.map((x, i) => (
+
+
+
+
+
+
+
+
+
+
+
+
+ {x}
+
+ ))}
+ {device == 'rocm' &&
+ gpuDevices?.length &&
+ gpuDevices.map((x, i) => (
diff --git a/ee/tabby-ui/lib/gql/generates/gql.ts b/ee/tabby-ui/lib/gql/generates/gql.ts
index 0af4c32fd6f..ecfcb68fcc0 100644
--- a/ee/tabby-ui/lib/gql/generates/gql.ts
+++ b/ee/tabby-ui/lib/gql/generates/gql.ts
@@ -1,6 +1,6 @@
/* eslint-disable */
import * as types from './graphql'
-import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'
+import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'
/**
* Map of all GraphQL operations in the project.
@@ -13,7 +13,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/
* Therefore it is highly recommended to use the babel or swc plugin for production.
*/
const documents = {
- '\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n cudaDevices\n }\n }\n':
+ '\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n':
types.GetWorkersDocument,
'\n query GetRegistrationToken {\n registrationToken\n }\n':
types.GetRegistrationTokenDocument
@@ -37,8 +37,8 @@ export function graphql(source: string): unknown
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(
- source: '\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n cudaDevices\n }\n }\n'
-): (typeof documents)['\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n cudaDevices\n }\n }\n']
+ source: '\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n'
+): (typeof documents)['\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n']
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
diff --git a/ee/tabby-ui/lib/gql/generates/graphql.ts b/ee/tabby-ui/lib/gql/generates/graphql.ts
index adadd03d711..555cc81ac4d 100644
--- a/ee/tabby-ui/lib/gql/generates/graphql.ts
+++ b/ee/tabby-ui/lib/gql/generates/graphql.ts
@@ -1,5 +1,6 @@
/* eslint-disable */
-import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'
+import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'
+
export type Maybe = T | null
export type InputMaybe = Maybe
export type Exact = {
@@ -46,8 +47,8 @@ export type Worker = {
arch: Scalars['String']['output']
cpuCount: Scalars['Int']['output']
cpuInfo: Scalars['String']['output']
- cudaDevices: Array
device: Scalars['String']['output']
+ gpuDevices: Array
kind: WorkerKind
name: Scalars['String']['output']
}
@@ -70,7 +71,7 @@ export type GetWorkersQuery = {
arch: string
cpuInfo: string
cpuCount: number
- cudaDevices: Array
+ gpuDevices: Array
}>
}
@@ -104,7 +105,7 @@ export const GetWorkersDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'arch' } },
{ kind: 'Field', name: { kind: 'Name', value: 'cpuInfo' } },
{ kind: 'Field', name: { kind: 'Name', value: 'cpuCount' } },
- { kind: 'Field', name: { kind: 'Name', value: 'cudaDevices' } }
+ { kind: 'Field', name: { kind: 'Name', value: 'gpuDevices' } }
]
}
}
diff --git a/ee/tabby-ui/lib/gql/request-documents.tsx b/ee/tabby-ui/lib/gql/request-documents.tsx
index 3c3df64fbed..01310aad6d8 100644
--- a/ee/tabby-ui/lib/gql/request-documents.tsx
+++ b/ee/tabby-ui/lib/gql/request-documents.tsx
@@ -1,4 +1,4 @@
-import { graphql } from './generates'
+import {graphql} from './generates'
export const getAllWorkersDocument = graphql(/* GraphQL */ `
query GetWorkers {
@@ -10,7 +10,7 @@ export const getAllWorkersDocument = graphql(/* GraphQL */ `
arch
cpuInfo
cpuCount
- cudaDevices
+ gpuDevices
}
}
`)
diff --git a/ee/tabby-ui/lib/hooks/use-health.tsx b/ee/tabby-ui/lib/hooks/use-health.tsx
index 5108e867fc8..2d6bed2a4c1 100644
--- a/ee/tabby-ui/lib/hooks/use-health.tsx
+++ b/ee/tabby-ui/lib/hooks/use-health.tsx
@@ -1,16 +1,16 @@
'use client'
import useSWRImmutable from 'swr/immutable'
-import { SWRResponse } from 'swr'
+import {SWRResponse} from 'swr'
import fetcher from '@/lib/tabby-fetcher'
export interface HealthInfo {
- device: 'metal' | 'cpu' | 'cuda'
+ device: 'metal' | 'cpu' | 'cuda' | 'rocm'
model?: string
chat_model?: string
cpu_info: string
cpu_count: number
- cuda_devices: string[]
+ gpu_devices: string[]
version: {
build_date: string
git_describe: string
diff --git a/ee/tabby-ui/lib/hooks/use-workers.ts b/ee/tabby-ui/lib/hooks/use-workers.ts
index af1ffdd2a01..94bdc52b3e6 100644
--- a/ee/tabby-ui/lib/hooks/use-workers.ts
+++ b/ee/tabby-ui/lib/hooks/use-workers.ts
@@ -1,9 +1,9 @@
import React from 'react'
-import { groupBy, findIndex, slice } from 'lodash-es'
-import { Worker, WorkerKind } from '@/lib/gql/generates/graphql'
-import { getAllWorkersDocument } from '@/lib/gql/request-documents'
-import { useGraphQL } from './use-graphql'
-import type { HealthInfo } from './use-health'
+import {findIndex, groupBy, slice} from 'lodash-es'
+import {Worker, WorkerKind} from '@/lib/gql/generates/graphql'
+import {getAllWorkersDocument} from '@/lib/gql/request-documents'
+import {useGraphQL} from './use-graphql'
+import type {HealthInfo} from './use-health'
const modelNameMap: Record = {
[WorkerKind.Chat]: 'chat_model',
@@ -22,7 +22,7 @@ function transformHealthInfoToWorker(
cpuInfo: healthInfo.cpu_info,
name: healthInfo?.[modelNameMap[kind]] ?? '',
cpuCount: healthInfo.cpu_count,
- cudaDevices: healthInfo.cuda_devices
+ gpuDevices: healthInfo.gpu_devices
}
}
diff --git a/ee/tabby-webserver/graphql/schema.graphql b/ee/tabby-webserver/graphql/schema.graphql
index 6b67428f4cc..364c0145f0b 100644
--- a/ee/tabby-webserver/graphql/schema.graphql
+++ b/ee/tabby-webserver/graphql/schema.graphql
@@ -20,7 +20,7 @@ type Worker {
arch: String!
cpuInfo: String!
cpuCount: Int!
- cudaDevices: [String!]!
+ gpuDevices: [String!]!
}
schema {
diff --git a/ee/tabby-webserver/src/api.rs b/ee/tabby-webserver/src/api.rs
index fa5998ff205..d3b0268a04b 100644
--- a/ee/tabby-webserver/src/api.rs
+++ b/ee/tabby-webserver/src/api.rs
@@ -1,12 +1,13 @@
use async_trait::async_trait;
use juniper::{GraphQLEnum, GraphQLObject};
use serde::{Deserialize, Serialize};
+use thiserror::Error;
+use tokio_tungstenite::connect_async;
+
use tabby_common::api::{
code::{CodeSearch, CodeSearchError, SearchResponse},
event::RawEventLogger,
};
-use thiserror::Error;
-use tokio_tungstenite::connect_async;
use crate::websocket::WebSocketTransport;
@@ -25,7 +26,7 @@ pub struct Worker {
pub arch: String,
pub cpu_info: String,
pub cpu_count: i32,
- pub cuda_devices: Vec,
+ pub gpu_devices: Vec,
}
#[derive(Serialize, Deserialize, Error, Debug)]
@@ -50,7 +51,7 @@ pub trait Hub {
arch: String,
cpu_info: String,
cpu_count: i32,
- cuda_devices: Vec,
+ gpu_devices: Vec,
token: String,
) -> Result;
diff --git a/ee/tabby-webserver/src/lib.rs b/ee/tabby-webserver/src/lib.rs
index 8a5ad9e6c8b..856eb364362 100644
--- a/ee/tabby-webserver/src/lib.rs
+++ b/ee/tabby-webserver/src/lib.rs
@@ -1,24 +1,5 @@
-pub mod api;
-
-mod schema;
-pub use schema::create_schema;
-use tabby_common::api::{
- code::{CodeSearch, SearchResponse},
- event::RawEventLogger,
-};
-use tokio::sync::Mutex;
-use tracing::{error, warn};
-use websocket::WebSocketTransport;
-
-mod db;
-mod repositories;
-mod server;
-mod ui;
-mod websocket;
-
use std::{net::SocketAddr, sync::Arc};
-use api::{Hub, RegisterWorkerError, Worker, WorkerKind};
use axum::{
extract::{ws::WebSocket, ConnectInfo, State, WebSocketUpgrade},
http::Request,
@@ -27,10 +8,29 @@ use axum::{
routing, Extension, Router,
};
use hyper::Body;
+use tarpc::server::{BaseChannel, Channel};
+use tokio::sync::Mutex;
+use tracing::{error, warn};
+
+use api::{Hub, RegisterWorkerError, Worker, WorkerKind};
use juniper_axum::{graphiql, graphql, playground};
+pub use schema::create_schema;
use schema::Schema;
use server::ServerContext;
-use tarpc::server::{BaseChannel, Channel};
+use tabby_common::api::{
+ code::{CodeSearch, SearchResponse},
+ event::RawEventLogger,
+};
+use websocket::WebSocketTransport;
+
+pub mod api;
+
+mod db;
+mod repositories;
+mod schema;
+mod server;
+mod ui;
+mod websocket;
pub async fn attach_webserver(
api: Router,
@@ -126,7 +126,7 @@ impl Hub for Arc {
arch: String,
cpu_info: String,
cpu_count: i32,
- cuda_devices: Vec,
+ gpu_devices: Vec,
token: String,
) -> Result {
if token.is_empty() {
@@ -165,7 +165,7 @@ impl Hub for Arc {
arch,
cpu_info,
cpu_count,
- cuda_devices,
+ gpu_devices,
};
self.ctx.register_worker(worker).await
}
diff --git a/ee/tabby-webserver/src/server/worker.rs b/ee/tabby-webserver/src/server/worker.rs
index 128da9cbe84..f8084da13c4 100644
--- a/ee/tabby-webserver/src/server/worker.rs
+++ b/ee/tabby-webserver/src/server/worker.rs
@@ -59,9 +59,9 @@ fn random_index(size: usize) -> usize {
#[cfg(test)]
mod tests {
+ use crate::api::WorkerKind;
use super::*;
- use crate::api::WorkerKind;
#[tokio::test]
async fn test_worker_group() {
@@ -90,7 +90,7 @@ mod tests {
arch: "x86_64".to_owned(),
cpu_info: "Fake CPU".to_owned(),
cpu_count: 32,
- cuda_devices: vec![],
+ gpu_devices: vec![],
}
}
}
diff --git a/ee/tabby-webserver/ui/404.html b/ee/tabby-webserver/ui/404.html
index abd1b2caefe..a6b8a79e13a 100644
--- a/ee/tabby-webserver/ui/404.html
+++ b/ee/tabby-webserver/ui/404.html
@@ -1 +1 @@
-404: This page could not be found. Tabby
404
This page could not be found.
\ No newline at end of file
+404: This page could not be found. Tabby
404
This page could not be found.
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/KwTUFhDElVXkDE3jiCtD0/_buildManifest.js b/ee/tabby-webserver/ui/_next/static/-IQIiI3YS2Md2tsCaIleK/_buildManifest.js
similarity index 100%
rename from ee/tabby-webserver/ui/_next/static/KwTUFhDElVXkDE3jiCtD0/_buildManifest.js
rename to ee/tabby-webserver/ui/_next/static/-IQIiI3YS2Md2tsCaIleK/_buildManifest.js
diff --git a/ee/tabby-webserver/ui/_next/static/KwTUFhDElVXkDE3jiCtD0/_ssgManifest.js b/ee/tabby-webserver/ui/_next/static/-IQIiI3YS2Md2tsCaIleK/_ssgManifest.js
similarity index 100%
rename from ee/tabby-webserver/ui/_next/static/KwTUFhDElVXkDE3jiCtD0/_ssgManifest.js
rename to ee/tabby-webserver/ui/_next/static/-IQIiI3YS2Md2tsCaIleK/_ssgManifest.js
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-3f83ef2900ef6e5d.js b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js
similarity index 95%
rename from ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-3f83ef2900ef6e5d.js
rename to ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js
index fd8ca3b5453..b4ab5d2d122 100644
--- a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-3f83ef2900ef6e5d.js
+++ b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js
@@ -1 +1 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[642],{95420:function(e,t,n){Promise.resolve().then(n.bind(n,30831))},30831:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return c}});var r=n(57437),s=n(39311),i=n(7404),l=n(61396),o=n.n(l),a=n(24033);function c(e){let{children:t,className:n}=e;return(0,r.jsxs)("div",{className:(0,s.cn)("grid overflow-hidden lg:grid-cols-[280px_1fr]",n),children:[(0,r.jsx)("div",{className:"hidden border-r bg-zinc-100/40 dark:bg-zinc-800/40 lg:block",children:(0,r.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,r.jsx)("div",{className:"h-[12px]"}),(0,r.jsx)("div",{className:"flex-1",children:(0,r.jsxs)("nav",{className:"grid items-start gap-4 px-4 text-sm font-medium",children:[(0,r.jsxs)(h,{href:"/",children:[(0,r.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-4 w-4",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("path",{d:"m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}),(0,r.jsx)("polyline",{points:"9 22 9 12 15 12 15 22"})]}),"Home"]}),(0,r.jsxs)(h,{href:"/swagger",children:[(0,r.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-4 w-4",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("path",{d:"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"}),(0,r.jsx)("path",{d:"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"}),(0,r.jsx)("path",{d:"M6 8h2"}),(0,r.jsx)("path",{d:"M6 12h2"}),(0,r.jsx)("path",{d:"M16 8h2"}),(0,r.jsx)("path",{d:"M16 12h2"})]}),"Swagger"]})]})})]})}),(0,r.jsx)("div",{className:"flex flex-1 flex-col overflow-auto",children:t})]})}let d=(0,i.j)("flex items-center gap-3 rounded-lg px-3 py-2 text-zinc-900 transition-all hover:text-zinc-900 dark:text-zinc-50 dark:hover:text-zinc-50",{variants:{state:{selected:"bg-zinc-200 dark:bg-zinc-800","not-selected":""}},defaultVariants:{state:"not-selected"}});function h(e){let{href:t,children:n}=e,s=(0,a.usePathname)();return(0,r.jsx)(o(),{className:d({state:s==t?"selected":"not-selected"}),href:t,children:n})}},39311:function(e,t,n){"use strict";n.d(t,{aF:function(){return a},cn:function(){return l},x0:function(){return o}});var r=n(50348),s=n(28481),i=n(23986);function l(){for(var e=arguments.length,t=Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:50,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/[ ,.:;\n,。:;]/;if(!e)return"";if(e.length<=t)return e;let r=e.slice(0,t),s=-1;for(let e=t-1;e>=0;e--)if(n.test(r[e])){s=e;break}return -1!==s&&(r=r.slice(0,s)),r+"..."}},67650:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"RouterContext",{enumerable:!0,get:function(){return i}});let r=n(21024),s=r._(n(2265)),i=s.default.createContext(null)},24033:function(e,t,n){e.exports=n(20290)}},function(e){e.O(0,[882,396,971,864,744],function(){return e(e.s=95420)}),_N_E=e.O()}]);
\ No newline at end of file
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[642],{95926:function(e,t,n){Promise.resolve().then(n.bind(n,30831))},30831:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return c}});var r=n(57437),s=n(39311),i=n(7404),l=n(61396),o=n.n(l),a=n(24033);function c(e){let{children:t,className:n}=e;return(0,r.jsxs)("div",{className:(0,s.cn)("grid overflow-hidden lg:grid-cols-[280px_1fr]",n),children:[(0,r.jsx)("div",{className:"hidden border-r bg-zinc-100/40 dark:bg-zinc-800/40 lg:block",children:(0,r.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,r.jsx)("div",{className:"h-[12px]"}),(0,r.jsx)("div",{className:"flex-1",children:(0,r.jsxs)("nav",{className:"grid items-start gap-4 px-4 text-sm font-medium",children:[(0,r.jsxs)(h,{href:"/",children:[(0,r.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-4 w-4",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("path",{d:"m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}),(0,r.jsx)("polyline",{points:"9 22 9 12 15 12 15 22"})]}),"Home"]}),(0,r.jsxs)(h,{href:"/swagger",children:[(0,r.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-4 w-4",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("path",{d:"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"}),(0,r.jsx)("path",{d:"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"}),(0,r.jsx)("path",{d:"M6 8h2"}),(0,r.jsx)("path",{d:"M6 12h2"}),(0,r.jsx)("path",{d:"M16 8h2"}),(0,r.jsx)("path",{d:"M16 12h2"})]}),"Swagger"]})]})})]})}),(0,r.jsx)("div",{className:"flex flex-1 flex-col overflow-auto",children:t})]})}let d=(0,i.j)("flex items-center gap-3 rounded-lg px-3 py-2 text-zinc-900 transition-all hover:text-zinc-900 dark:text-zinc-50 dark:hover:text-zinc-50",{variants:{state:{selected:"bg-zinc-200 dark:bg-zinc-800","not-selected":""}},defaultVariants:{state:"not-selected"}});function h(e){let{href:t,children:n}=e,s=(0,a.usePathname)();return(0,r.jsx)(o(),{className:d({state:s==t?"selected":"not-selected"}),href:t,children:n})}},39311:function(e,t,n){"use strict";n.d(t,{aF:function(){return a},cn:function(){return l},x0:function(){return o}});var r=n(50348),s=n(28481),i=n(23986);function l(){for(var e=arguments.length,t=Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:50,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/[ ,.:;\n,。:;]/;if(!e)return"";if(e.length<=t)return e;let r=e.slice(0,t),s=-1;for(let e=t-1;e>=0;e--)if(n.test(r[e])){s=e;break}return -1!==s&&(r=r.slice(0,s)),r+"..."}},67650:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"RouterContext",{enumerable:!0,get:function(){return i}});let r=n(21024),s=r._(n(2265)),i=s.default.createContext(null)},24033:function(e,t,n){e.exports=n(20290)}},function(e){e.O(0,[882,396,971,864,744],function(){return e(e.s=95926)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js
new file mode 100644
index 00000000000..52f2b1cf4db
--- /dev/null
+++ b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js
@@ -0,0 +1 @@
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[130],{89853:function(e,t,n){Promise.resolve().then(n.bind(n,60901))},60901:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return M}});var s=n(57437),a=n(93023),r=n(12609),i=n(84168),o=n(16775),l=n(13287),d=n(2265),c=n(39311);let u=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("rounded-lg border bg-card text-card-foreground shadow-sm",n),...a})});u.displayName="Card";let h=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("flex flex-col space-y-1.5 p-6",n),...a})});h.displayName="CardHeader";let x=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("h3",{ref:t,className:(0,c.cn)("text-2xl font-semibold leading-none tracking-tight",n),...a})});x.displayName="CardTitle";let m=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("p",{ref:t,className:(0,c.cn)("text-sm text-muted-foreground",n),...a})});m.displayName="CardDescription";let p=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("p-6 pt-0",n),...a})});p.displayName="CardContent";let f=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("flex items-center p-6 pt-0",n),...a})});f.displayName="CardFooter";var j=n(70349);function g(e){let{addr:t,name:n,kind:a,device:r,gpuDevices:i,cpuCount:o,cpuInfo:l}=e,d=(0,c.cn)("ml-2","whitespace-nowrap","overflow-hidden","overflow-ellipsis"),m="".concat(l," (").concat(o," cores)");return(0,s.jsxs)(u,{className:"rounded-xl p-2 shadow-md lg:w-[260px]",children:[(0,s.jsx)(h,{className:"p-0 px-4 pb-2 pt-4",children:(0,s.jsxs)(x,{className:"text-md flex items-center font-normal",children:[(0,s.jsx)(k,{type:a}),(0,s.jsx)("p",{title:n,className:d,children:n})]})}),(0,s.jsxs)(p,{className:"flex flex-col gap-2 p-0 px-4 pb-4 pt-2",children:[(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-5 w-5 text-gray-400",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("rect",{x:"16",y:"16",width:"6",height:"6",rx:"1"}),(0,s.jsx)("rect",{x:"2",y:"16",width:"6",height:"6",rx:"1"}),(0,s.jsx)("rect",{x:"9",y:"2",width:"6",height:"6",rx:"1"}),(0,s.jsx)("path",{d:"M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"}),(0,s.jsx)("path",{d:"M12 12V8"})]}),(0,s.jsx)("p",{title:t,className:d,children:t})]}),(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("rect",{height:"16",rx:"2",width:"16",x:"4",y:"4"}),(0,s.jsx)("rect",{height:"6",width:"6",x:"9",y:"9"}),(0,s.jsx)("path",{d:"M15 2v2"}),(0,s.jsx)("path",{d:"M15 20v2"}),(0,s.jsx)("path",{d:"M2 15h2"}),(0,s.jsx)("path",{d:"M2 9h2"}),(0,s.jsx)("path",{d:"M20 15h2"}),(0,s.jsx)("path",{d:"M20 9h2"}),(0,s.jsx)("path",{d:"M9 2v2"}),(0,s.jsx)("path",{d:"M9 20v2"})]}),(0,s.jsx)("p",{title:m,className:d,children:m})]}),"cuda"==r&&(null==i?void 0:i.length)&&i.map((e,t)=>(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("path",{d:"M6 19v-3"}),(0,s.jsx)("path",{d:"M10 19v-3"}),(0,s.jsx)("path",{d:"M14 19v-3"}),(0,s.jsx)("path",{d:"M18 19v-3"}),(0,s.jsx)("path",{d:"M8 11V9"}),(0,s.jsx)("path",{d:"M16 11V9"}),(0,s.jsx)("path",{d:"M12 11V9"}),(0,s.jsx)("path",{d:"M2 15h20"}),(0,s.jsx)("path",{d:"M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1.1a2 2 0 0 0 0 3.837V17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5.1a2 2 0 0 0 0-3.837Z"})]}),(0,s.jsx)("p",{title:e,className:d,children:e})]},t)),"rocm"==r&&(null==i?void 0:i.length)&&i.map((e,t)=>(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("path",{d:"M6 19v-3"}),(0,s.jsx)("path",{d:"M10 19v-3"}),(0,s.jsx)("path",{d:"M14 19v-3"}),(0,s.jsx)("path",{d:"M18 19v-3"}),(0,s.jsx)("path",{d:"M8 11V9"}),(0,s.jsx)("path",{d:"M16 11V9"}),(0,s.jsx)("path",{d:"M12 11V9"}),(0,s.jsx)("path",{d:"M2 15h20"}),(0,s.jsx)("path",{d:"M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1.1a2 2 0 0 0 0 3.837V17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5.1a2 2 0 0 0 0-3.837Z"})]}),(0,s.jsx)("p",{title:e,className:d,children:e})]},t))]})]})}function v(e){let{children:t}=e;return(0,s.jsx)("div",{className:"mt-2 flex items-center text-sm text-gray-500",children:t})}function k(e){let{type:t}=e,n="h-5 w-5";return t==j.xj.Completion?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"}),(0,s.jsx)("polyline",{points:"14 2 14 8 20 8"}),(0,s.jsx)("path",{d:"m10 13-2 2 2 2"}),(0,s.jsx)("path",{d:"m14 17 2-2-2-2"})]}):t==j.xj.Chat?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"M14 9a2 2 0 0 1-2 2H6l-4 4V4c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v5Z"}),(0,s.jsx)("path",{d:"M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1"})]}):"INDEX"==t?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"m9 9-2 2 2 2"}),(0,s.jsx)("path",{d:"m13 13 2-2-2-2"}),(0,s.jsx)("circle",{cx:"11",cy:"11",r:"8"}),(0,s.jsx)("path",{d:"m21 21-4.3-4.3"})]}):void 0}var w=n(8724),N=n(71427),y=n(10144),b=n(33555);let C="community-dialog-shown";function M(){let[e,t]=(0,d.useState)(!1);return(0,d.useEffect)(()=>{localStorage.getItem(C)||(t(!0),localStorage.setItem(C,"true"))},[]),(0,s.jsxs)("div",{className:"p-4 lg:p-16",children:[(0,s.jsx)(_,{}),(0,s.jsx)(r.Vq,{open:e,onOpenChange:t,children:(0,s.jsxs)(r.cZ,{children:[(0,s.jsxs)(r.fK,{className:"gap-3",children:[(0,s.jsx)(r.$N,{children:"Join the Tabby community"}),(0,s.jsx)(r.Be,{children:"Connect with other contributors building Tabby. Share knowledge, get help, and contribute to the open-source project."})]}),(0,s.jsx)(r.cN,{className:"sm:justify-start",children:(0,s.jsxs)("a",{target:"_blank",href:"https://join.slack.com/t/tabbycommunity/shared_invite/zt-1xeiddizp-bciR2RtFTaJ37RBxr8VxpA",className:(0,a.d)(),children:[(0,s.jsx)(i.gx,{className:"-ml-2 h-8 w-8"}),"Join us on Slack"]})})]})})]})}function _(){let{data:e}=(0,l.Q)(),t=(0,w.s)(e),{data:n}=(0,N.a)(y.$);if(e)return(0,s.jsxs)("div",{className:"flex w-full flex-col gap-3",children:[(0,s.jsxs)("h1",{children:[(0,s.jsx)("span",{className:"font-bold",children:"Congratulations"}),", your tabby instance is up!"]}),(0,s.jsx)("span",{className:"flex flex-wrap gap-1",children:(0,s.jsx)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby/releases/tag/".concat(e.version.git_describe),children:(0,s.jsx)("img",{src:"https://img.shields.io/badge/version-".concat(encodeURIComponent(e.version.git_describe.replaceAll("-","--")),"-green")})})}),(0,s.jsx)(o.Z,{}),(0,s.jsxs)("div",{className:"mt-4 rounded-lg bg-zinc-100 p-4 dark:bg-zinc-800",children:[(0,s.jsx)("span",{className:"font-bold",children:"Workers"}),!!(null==n?void 0:n.registrationToken)&&(0,s.jsxs)("div",{className:"flex items-center gap-1",children:["Registeration token: ",(0,s.jsx)("span",{className:"text-sm rounded-lg text-red-600",children:n.registrationToken}),(0,s.jsx)(b.q,{value:n.registrationToken})]}),(0,s.jsxs)("div",{className:"mt-4 flex flex-col gap-4 lg:flex-row lg:flex-wrap",children:[!!(null==t?void 0:t[j.xj.Completion])&&(0,s.jsx)(s.Fragment,{children:t[j.xj.Completion].map((e,t)=>(0,s.jsx)(g,{...e},t))}),!!(null==t?void 0:t[j.xj.Chat])&&(0,s.jsx)(s.Fragment,{children:t[j.xj.Chat].map((e,t)=>(0,s.jsx)(g,{...e},t))}),(0,s.jsx)(g,{addr:"localhost",name:"Code Search Index",kind:"INDEX",arch:"",device:e.device,gpuDevices:e.gpu_devices,cpuCount:e.cpu_count,cpuInfo:e.cpu_info})]})]})]})}},33555:function(e,t,n){"use strict";n.d(t,{q:function(){return o}});var s=n(57437);n(2265);var a=n(93023),r=n(84168),i=n(77723);function o(e){let{className:t,value:n,...o}=e,{isCopied:l,copyToClipboard:d}=(0,i.m)({timeout:2e3});return n?(0,s.jsxs)(a.z,{variant:"ghost",size:"icon",className:t,onClick:()=>{l||d(n)},...o,children:[l?(0,s.jsx)(r.NO,{}):(0,s.jsx)(r.vU,{}),(0,s.jsx)("span",{className:"sr-only",children:"Copy"})]}):null}},12609:function(e,t,n){"use strict";n.d(t,{$N:function(){return m},Be:function(){return p},Vq:function(){return l},cN:function(){return x},cZ:function(){return u},fK:function(){return h}});var s=n(57437),a=n(2265),r=n(25555),i=n(39311),o=n(84168);let l=r.fC;r.xz;let d=e=>{let{className:t,children:n,...a}=e;return(0,s.jsx)(r.h_,{className:(0,i.cn)(t),...a,children:(0,s.jsx)("div",{className:"fixed inset-0 z-50 flex items-start justify-center sm:items-center",children:n})})};d.displayName=r.h_.displayName;let c=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.aV,{ref:t,className:(0,i.cn)("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",n),...a})});c.displayName=r.aV.displayName;let u=a.forwardRef((e,t)=>{let{className:n,children:a,...l}=e;return(0,s.jsxs)(d,{children:[(0,s.jsx)(c,{}),(0,s.jsxs)(r.VY,{ref:t,className:(0,i.cn)("fixed z-50 grid w-full gap-4 rounded-b-lg border bg-background p-6 shadow-sm animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",n),...l,children:[a,(0,s.jsxs)(r.x8,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[(0,s.jsx)(o.bM,{}),(0,s.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})});u.displayName=r.VY.displayName;let h=e=>{let{className:t,...n}=e;return(0,s.jsx)("div",{className:(0,i.cn)("flex flex-col space-y-1.5 text-center sm:text-left",t),...n})};h.displayName="DialogHeader";let x=e=>{let{className:t,...n}=e;return(0,s.jsx)("div",{className:(0,i.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...n})};x.displayName="DialogFooter";let m=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.Dx,{ref:t,className:(0,i.cn)("text-lg font-semibold leading-none tracking-tight",n),...a})});m.displayName=r.Dx.displayName;let p=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.dk,{ref:t,className:(0,i.cn)("text-sm text-muted-foreground",n),...a})});p.displayName=r.dk.displayName},16775:function(e,t,n){"use strict";n.d(t,{Z:function(){return o}});var s=n(57437),a=n(2265),r=n(26823),i=n(39311);let o=a.forwardRef((e,t)=>{let{className:n,orientation:a="horizontal",decorative:o=!0,...l}=e;return(0,s.jsx)(r.f,{ref:t,decorative:o,orientation:a,className:(0,i.cn)("shrink-0 bg-border","horizontal"===a?"h-[1px] w-full":"h-full w-[1px]",n),...l})});o.displayName=r.f.displayName},70349:function(e,t,n){"use strict";var s,a;n.d(t,{bh:function(){return i},d3:function(){return r},xj:function(){return s}}),(a=s||(s={})).Chat="CHAT",a.Completion="COMPLETION";let r={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetWorkers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"workers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"kind"}},{kind:"Field",name:{kind:"Name",value:"name"}},{kind:"Field",name:{kind:"Name",value:"addr"}},{kind:"Field",name:{kind:"Name",value:"device"}},{kind:"Field",name:{kind:"Name",value:"arch"}},{kind:"Field",name:{kind:"Name",value:"cpuInfo"}},{kind:"Field",name:{kind:"Name",value:"cpuCount"}},{kind:"Field",name:{kind:"Name",value:"gpuDevices"}}]}}]}}]},i={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetRegistrationToken"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"registrationToken"}}]}}]}},10144:function(e,t,n){"use strict";n.d(t,{G:function(){return i},$:function(){return o}});var s=n(70349);let a={"\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n":s.d3,"\n query GetRegistrationToken {\n registrationToken\n }\n":s.bh};function r(e){var t;return null!==(t=a[e])&&void 0!==t?t:{}}let i=r("\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n"),o=r("\n query GetRegistrationToken {\n registrationToken\n }\n")},77723:function(e,t,n){"use strict";n.d(t,{m:function(){return a}});var s=n(2265);function a(e){let{timeout:t=2e3}=e,[n,a]=s.useState(!1);return{isCopied:n,copyToClipboard:e=>{var n;(null===(n=navigator.clipboard)||void 0===n?void 0:n.writeText)&&e&&navigator.clipboard.writeText(e).then(()=>{a(!0),setTimeout(()=>{a(!1)},t)})}}}},71427:function(e,t,n){"use strict";n.d(t,{a:function(){return l}});var s,a=n(30713),r=n(95054),i=n(62601);let o=new r.g6("".concat(null!==(s=i.env.NEXT_PUBLIC_TABBY_SERVER_URL)&&void 0!==s?s:"","/graphql"));function l(e,t,n){return(0,a.ZP)([e,t],e=>{let[t,n]=e;return o.request(t,n)},n)}},13287:function(e,t,n){"use strict";n.d(t,{Q:function(){return r}});var s=n(1589),a=n(97605);function r(){return(0,s.Z)("/v1/health",a.Z)}},8724:function(e,t,n){"use strict";n.d(t,{s:function(){return h}});var s=n(2265),a=n(91317),r=n(16630),i=n(35512),o=n(70349),l=n(10144),d=n(71427);let c={[o.xj.Chat]:"chat_model",[o.xj.Completion]:"model"};function u(e,t){var n;return{kind:t,device:e.device,addr:"localhost",arch:"",cpuInfo:e.cpu_info,name:null!==(n=null==e?void 0:e[c[t]])&&void 0!==n?n:"",cpuCount:e.cpu_count,gpuDevices:e.gpu_devices}}function h(e){let{data:t}=(0,d.a)(l.G),n=null==t?void 0:t.workers,c=s.useMemo(()=>{let t=(0,i.Z)(n),s=(0,r.Z)(t,{kind:o.xj.Completion})>-1,l=(0,r.Z)(t,{kind:o.xj.Chat})>-1;return!s&&(null==e?void 0:e.model)&&t.push(u(e,o.xj.Completion)),!l&&(null==e?void 0:e.chat_model)&&t.push(u(e,o.xj.Chat)),(0,a.Z)(t,"kind")},[e,n]);return c}}},function(e){e.O(0,[882,845,431,286,967,971,864,744],function(){return e(e.s=89853)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-2dac77bf7366362b.js b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-2dac77bf7366362b.js
deleted file mode 100644
index 9352d633f28..00000000000
--- a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-2dac77bf7366362b.js
+++ /dev/null
@@ -1 +0,0 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[130],{75045:function(e,t,n){Promise.resolve().then(n.bind(n,60901))},60901:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return M}});var s=n(57437),a=n(93023),r=n(12609),i=n(84168),o=n(16775),l=n(13287),d=n(2265),c=n(39311);let u=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("rounded-lg border bg-card text-card-foreground shadow-sm",n),...a})});u.displayName="Card";let x=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("flex flex-col space-y-1.5 p-6",n),...a})});x.displayName="CardHeader";let h=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("h3",{ref:t,className:(0,c.cn)("text-2xl font-semibold leading-none tracking-tight",n),...a})});h.displayName="CardTitle";let m=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("p",{ref:t,className:(0,c.cn)("text-sm text-muted-foreground",n),...a})});m.displayName="CardDescription";let p=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("p-6 pt-0",n),...a})});p.displayName="CardContent";let f=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("flex items-center p-6 pt-0",n),...a})});f.displayName="CardFooter";var j=n(70349);function v(e){let{addr:t,name:n,kind:a,device:r,cudaDevices:i,cpuCount:o,cpuInfo:l}=e,d=(0,c.cn)("ml-2","whitespace-nowrap","overflow-hidden","overflow-ellipsis"),m="".concat(l," (").concat(o," cores)");return(0,s.jsxs)(u,{className:"rounded-xl p-2 shadow-md lg:w-[260px]",children:[(0,s.jsx)(x,{className:"p-0 px-4 pb-2 pt-4",children:(0,s.jsxs)(h,{className:"text-md flex items-center font-normal",children:[(0,s.jsx)(k,{type:a}),(0,s.jsx)("p",{title:n,className:d,children:n})]})}),(0,s.jsxs)(p,{className:"flex flex-col gap-2 p-0 px-4 pb-4 pt-2",children:[(0,s.jsxs)(g,{children:[(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-5 w-5 text-gray-400",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("rect",{x:"16",y:"16",width:"6",height:"6",rx:"1"}),(0,s.jsx)("rect",{x:"2",y:"16",width:"6",height:"6",rx:"1"}),(0,s.jsx)("rect",{x:"9",y:"2",width:"6",height:"6",rx:"1"}),(0,s.jsx)("path",{d:"M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"}),(0,s.jsx)("path",{d:"M12 12V8"})]}),(0,s.jsx)("p",{title:t,className:d,children:t})]}),(0,s.jsxs)(g,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("rect",{height:"16",rx:"2",width:"16",x:"4",y:"4"}),(0,s.jsx)("rect",{height:"6",width:"6",x:"9",y:"9"}),(0,s.jsx)("path",{d:"M15 2v2"}),(0,s.jsx)("path",{d:"M15 20v2"}),(0,s.jsx)("path",{d:"M2 15h2"}),(0,s.jsx)("path",{d:"M2 9h2"}),(0,s.jsx)("path",{d:"M20 15h2"}),(0,s.jsx)("path",{d:"M20 9h2"}),(0,s.jsx)("path",{d:"M9 2v2"}),(0,s.jsx)("path",{d:"M9 20v2"})]}),(0,s.jsx)("p",{title:m,className:d,children:m})]}),"cuda"==r&&(null==i?void 0:i.length)&&i.map((e,t)=>(0,s.jsxs)(g,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("path",{d:"M6 19v-3"}),(0,s.jsx)("path",{d:"M10 19v-3"}),(0,s.jsx)("path",{d:"M14 19v-3"}),(0,s.jsx)("path",{d:"M18 19v-3"}),(0,s.jsx)("path",{d:"M8 11V9"}),(0,s.jsx)("path",{d:"M16 11V9"}),(0,s.jsx)("path",{d:"M12 11V9"}),(0,s.jsx)("path",{d:"M2 15h20"}),(0,s.jsx)("path",{d:"M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1.1a2 2 0 0 0 0 3.837V17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5.1a2 2 0 0 0 0-3.837Z"})]}),(0,s.jsx)("p",{title:e,className:d,children:e})]},t))]})]})}function g(e){let{children:t}=e;return(0,s.jsx)("div",{className:"mt-2 flex items-center text-sm text-gray-500",children:t})}function k(e){let{type:t}=e,n="h-5 w-5";return t==j.xj.Completion?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"}),(0,s.jsx)("polyline",{points:"14 2 14 8 20 8"}),(0,s.jsx)("path",{d:"m10 13-2 2 2 2"}),(0,s.jsx)("path",{d:"m14 17 2-2-2-2"})]}):t==j.xj.Chat?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"M14 9a2 2 0 0 1-2 2H6l-4 4V4c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v5Z"}),(0,s.jsx)("path",{d:"M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1"})]}):"INDEX"==t?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"m9 9-2 2 2 2"}),(0,s.jsx)("path",{d:"m13 13 2-2-2-2"}),(0,s.jsx)("circle",{cx:"11",cy:"11",r:"8"}),(0,s.jsx)("path",{d:"m21 21-4.3-4.3"})]}):void 0}var N=n(8724),w=n(71427),y=n(10144),b=n(33555);let C="community-dialog-shown";function M(){let[e,t]=(0,d.useState)(!1);return(0,d.useEffect)(()=>{localStorage.getItem(C)||(t(!0),localStorage.setItem(C,"true"))},[]),(0,s.jsxs)("div",{className:"p-4 lg:p-16",children:[(0,s.jsx)(_,{}),(0,s.jsx)(r.Vq,{open:e,onOpenChange:t,children:(0,s.jsxs)(r.cZ,{children:[(0,s.jsxs)(r.fK,{className:"gap-3",children:[(0,s.jsx)(r.$N,{children:"Join the Tabby community"}),(0,s.jsx)(r.Be,{children:"Connect with other contributors building Tabby. Share knowledge, get help, and contribute to the open-source project."})]}),(0,s.jsx)(r.cN,{className:"sm:justify-start",children:(0,s.jsxs)("a",{target:"_blank",href:"https://join.slack.com/t/tabbycommunity/shared_invite/zt-1xeiddizp-bciR2RtFTaJ37RBxr8VxpA",className:(0,a.d)(),children:[(0,s.jsx)(i.gx,{className:"-ml-2 h-8 w-8"}),"Join us on Slack"]})})]})})]})}function _(){let{data:e}=(0,l.Q)(),t=(0,N.s)(e),{data:n}=(0,w.a)(y.$);if(e)return(0,s.jsxs)("div",{className:"flex w-full flex-col gap-3",children:[(0,s.jsxs)("h1",{children:[(0,s.jsx)("span",{className:"font-bold",children:"Congratulations"}),", your tabby instance is up!"]}),(0,s.jsx)("span",{className:"flex flex-wrap gap-1",children:(0,s.jsx)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby/releases/tag/".concat(e.version.git_describe),children:(0,s.jsx)("img",{src:"https://img.shields.io/badge/version-".concat(encodeURIComponent(e.version.git_describe.replaceAll("-","--")),"-green")})})}),(0,s.jsx)(o.Z,{}),(0,s.jsxs)("div",{className:"mt-4 rounded-lg bg-zinc-100 p-4 dark:bg-zinc-800",children:[(0,s.jsx)("span",{className:"font-bold",children:"Workers"}),!!(null==n?void 0:n.registrationToken)&&(0,s.jsxs)("div",{className:"flex items-center gap-1",children:["Registeration token: ",(0,s.jsx)("span",{className:"text-sm rounded-lg text-red-600",children:n.registrationToken}),(0,s.jsx)(b.q,{value:n.registrationToken})]}),(0,s.jsxs)("div",{className:"mt-4 flex flex-col gap-4 lg:flex-row lg:flex-wrap",children:[!!(null==t?void 0:t[j.xj.Completion])&&(0,s.jsx)(s.Fragment,{children:t[j.xj.Completion].map((e,t)=>(0,s.jsx)(v,{...e},t))}),!!(null==t?void 0:t[j.xj.Chat])&&(0,s.jsx)(s.Fragment,{children:t[j.xj.Chat].map((e,t)=>(0,s.jsx)(v,{...e},t))}),(0,s.jsx)(v,{addr:"localhost",name:"Code Search Index",kind:"INDEX",arch:"",device:e.device,cudaDevices:e.cuda_devices,cpuCount:e.cpu_count,cpuInfo:e.cpu_info})]})]})]})}},33555:function(e,t,n){"use strict";n.d(t,{q:function(){return o}});var s=n(57437);n(2265);var a=n(93023),r=n(84168),i=n(77723);function o(e){let{className:t,value:n,...o}=e,{isCopied:l,copyToClipboard:d}=(0,i.m)({timeout:2e3});return n?(0,s.jsxs)(a.z,{variant:"ghost",size:"icon",className:t,onClick:()=>{l||d(n)},...o,children:[l?(0,s.jsx)(r.NO,{}):(0,s.jsx)(r.vU,{}),(0,s.jsx)("span",{className:"sr-only",children:"Copy"})]}):null}},12609:function(e,t,n){"use strict";n.d(t,{$N:function(){return m},Be:function(){return p},Vq:function(){return l},cN:function(){return h},cZ:function(){return u},fK:function(){return x}});var s=n(57437),a=n(2265),r=n(25555),i=n(39311),o=n(84168);let l=r.fC;r.xz;let d=e=>{let{className:t,children:n,...a}=e;return(0,s.jsx)(r.h_,{className:(0,i.cn)(t),...a,children:(0,s.jsx)("div",{className:"fixed inset-0 z-50 flex items-start justify-center sm:items-center",children:n})})};d.displayName=r.h_.displayName;let c=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.aV,{ref:t,className:(0,i.cn)("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",n),...a})});c.displayName=r.aV.displayName;let u=a.forwardRef((e,t)=>{let{className:n,children:a,...l}=e;return(0,s.jsxs)(d,{children:[(0,s.jsx)(c,{}),(0,s.jsxs)(r.VY,{ref:t,className:(0,i.cn)("fixed z-50 grid w-full gap-4 rounded-b-lg border bg-background p-6 shadow-sm animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",n),...l,children:[a,(0,s.jsxs)(r.x8,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[(0,s.jsx)(o.bM,{}),(0,s.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})});u.displayName=r.VY.displayName;let x=e=>{let{className:t,...n}=e;return(0,s.jsx)("div",{className:(0,i.cn)("flex flex-col space-y-1.5 text-center sm:text-left",t),...n})};x.displayName="DialogHeader";let h=e=>{let{className:t,...n}=e;return(0,s.jsx)("div",{className:(0,i.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...n})};h.displayName="DialogFooter";let m=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.Dx,{ref:t,className:(0,i.cn)("text-lg font-semibold leading-none tracking-tight",n),...a})});m.displayName=r.Dx.displayName;let p=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.dk,{ref:t,className:(0,i.cn)("text-sm text-muted-foreground",n),...a})});p.displayName=r.dk.displayName},16775:function(e,t,n){"use strict";n.d(t,{Z:function(){return o}});var s=n(57437),a=n(2265),r=n(26823),i=n(39311);let o=a.forwardRef((e,t)=>{let{className:n,orientation:a="horizontal",decorative:o=!0,...l}=e;return(0,s.jsx)(r.f,{ref:t,decorative:o,orientation:a,className:(0,i.cn)("shrink-0 bg-border","horizontal"===a?"h-[1px] w-full":"h-full w-[1px]",n),...l})});o.displayName=r.f.displayName},70349:function(e,t,n){"use strict";var s,a;n.d(t,{bh:function(){return i},d3:function(){return r},xj:function(){return s}}),(a=s||(s={})).Chat="CHAT",a.Completion="COMPLETION";let r={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetWorkers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"workers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"kind"}},{kind:"Field",name:{kind:"Name",value:"name"}},{kind:"Field",name:{kind:"Name",value:"addr"}},{kind:"Field",name:{kind:"Name",value:"device"}},{kind:"Field",name:{kind:"Name",value:"arch"}},{kind:"Field",name:{kind:"Name",value:"cpuInfo"}},{kind:"Field",name:{kind:"Name",value:"cpuCount"}},{kind:"Field",name:{kind:"Name",value:"cudaDevices"}}]}}]}}]},i={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetRegistrationToken"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"registrationToken"}}]}}]}},10144:function(e,t,n){"use strict";n.d(t,{G:function(){return i},$:function(){return o}});var s=n(70349);let a={"\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n cudaDevices\n }\n }\n":s.d3,"\n query GetRegistrationToken {\n registrationToken\n }\n":s.bh};function r(e){var t;return null!==(t=a[e])&&void 0!==t?t:{}}let i=r("\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n cudaDevices\n }\n }\n"),o=r("\n query GetRegistrationToken {\n registrationToken\n }\n")},77723:function(e,t,n){"use strict";n.d(t,{m:function(){return a}});var s=n(2265);function a(e){let{timeout:t=2e3}=e,[n,a]=s.useState(!1);return{isCopied:n,copyToClipboard:e=>{var n;(null===(n=navigator.clipboard)||void 0===n?void 0:n.writeText)&&e&&navigator.clipboard.writeText(e).then(()=>{a(!0),setTimeout(()=>{a(!1)},t)})}}}},71427:function(e,t,n){"use strict";n.d(t,{a:function(){return l}});var s,a=n(30713),r=n(95054),i=n(62601);let o=new r.g6("".concat(null!==(s=i.env.NEXT_PUBLIC_TABBY_SERVER_URL)&&void 0!==s?s:"","/graphql"));function l(e,t,n){return(0,a.ZP)([e,t],e=>{let[t,n]=e;return o.request(t,n)},n)}},13287:function(e,t,n){"use strict";n.d(t,{Q:function(){return r}});var s=n(1589),a=n(97605);function r(){return(0,s.Z)("/v1/health",a.Z)}},8724:function(e,t,n){"use strict";n.d(t,{s:function(){return x}});var s=n(2265),a=n(91317),r=n(16630),i=n(35512),o=n(70349),l=n(10144),d=n(71427);let c={[o.xj.Chat]:"chat_model",[o.xj.Completion]:"model"};function u(e,t){var n;return{kind:t,device:e.device,addr:"localhost",arch:"",cpuInfo:e.cpu_info,name:null!==(n=null==e?void 0:e[c[t]])&&void 0!==n?n:"",cpuCount:e.cpu_count,cudaDevices:e.cuda_devices}}function x(e){let{data:t}=(0,d.a)(l.G),n=null==t?void 0:t.workers,c=s.useMemo(()=>{let t=(0,i.Z)(n),s=(0,r.Z)(t,{kind:o.xj.Completion})>-1,l=(0,r.Z)(t,{kind:o.xj.Chat})>-1;return!s&&(null==e?void 0:e.model)&&t.push(u(e,o.xj.Completion)),!l&&(null==e?void 0:e.chat_model)&&t.push(u(e,o.xj.Chat)),(0,a.Z)(t,"kind")},[e,n]);return c}}},function(e){e.O(0,[882,845,431,286,967,971,864,744],function(){return e(e.s=75045)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/layout-a709b0b21d295a91.js b/ee/tabby-webserver/ui/_next/static/chunks/app/layout-a709b0b21d295a91.js
new file mode 100644
index 00000000000..87dd44dde05
--- /dev/null
+++ b/ee/tabby-webserver/ui/_next/static/chunks/app/layout-a709b0b21d295a91.js
@@ -0,0 +1 @@
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{6435:function(e,t,n){"use strict";n.d(t,{F:function(){return d},f:function(){return u}});var r=n(2265);let i=["light","dark"],a="(prefers-color-scheme: dark)",l="undefined"==typeof window,o=(0,r.createContext)(void 0),s={setTheme:e=>{},themes:[]},d=()=>{var e;return null!==(e=(0,r.useContext)(o))&&void 0!==e?e:s},u=e=>(0,r.useContext)(o)?r.createElement(r.Fragment,null,e.children):r.createElement(m,e),c=["light","dark"],m=({forcedTheme:e,disableTransitionOnChange:t=!1,enableSystem:n=!0,enableColorScheme:l=!0,storageKey:s="theme",themes:d=c,defaultTheme:u=n?"system":"light",attribute:m="data-theme",value:b,children:y,nonce:g})=>{let[k,_]=(0,r.useState)(()=>h(s,u)),[x,N]=(0,r.useState)(()=>h(s)),S=b?Object.values(b):d,j=(0,r.useCallback)(e=>{let r=e;if(!r)return;"system"===e&&n&&(r=p());let a=b?b[r]:r,o=t?v():null,s=document.documentElement;if("class"===m?(s.classList.remove(...S),a&&s.classList.add(a)):a?s.setAttribute(m,a):s.removeAttribute(m),l){let e=i.includes(u)?u:null,t=i.includes(r)?r:e;s.style.colorScheme=t}null==o||o()},[]),C=(0,r.useCallback)(e=>{_(e);try{localStorage.setItem(s,e)}catch(e){}},[e]),w=(0,r.useCallback)(t=>{let r=p(t);N(r),"system"===k&&n&&!e&&j("system")},[k,e]);(0,r.useEffect)(()=>{let e=window.matchMedia(a);return e.addListener(w),w(e),()=>e.removeListener(w)},[w]),(0,r.useEffect)(()=>{let e=e=>{e.key===s&&C(e.newValue||u)};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[C]),(0,r.useEffect)(()=>{j(null!=e?e:k)},[e,k]);let T=(0,r.useMemo)(()=>({theme:k,setTheme:C,forcedTheme:e,resolvedTheme:"system"===k?x:k,themes:n?[...d,"system"]:d,systemTheme:n?x:void 0}),[k,C,e,x,n,d]);return r.createElement(o.Provider,{value:T},r.createElement(f,{forcedTheme:e,disableTransitionOnChange:t,enableSystem:n,enableColorScheme:l,storageKey:s,themes:d,defaultTheme:u,attribute:m,value:b,children:y,attrs:S,nonce:g}),y)},f=(0,r.memo)(({forcedTheme:e,storageKey:t,attribute:n,enableSystem:l,enableColorScheme:o,defaultTheme:s,value:d,attrs:u,nonce:c})=>{let m="system"===s,f="class"===n?`var d=document.documentElement,c=d.classList;c.remove(${u.map(e=>`'${e}'`).join(",")});`:`var d=document.documentElement,n='${n}',s='setAttribute';`,h=o?i.includes(s)&&s?`if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${s}'`:"if(e==='light'||e==='dark')d.style.colorScheme=e":"",v=(e,t=!1,r=!0)=>{let a=d?d[e]:e,l=t?e+"|| ''":`'${a}'`,s="";return o&&r&&!t&&i.includes(e)&&(s+=`d.style.colorScheme = '${e}';`),"class"===n?s+=t||a?`c.add(${l})`:"null":a&&(s+=`d[s](n,${l})`),s},p=e?`!function(){${f}${v(e)}}()`:l?`!function(){try{${f}var e=localStorage.getItem('${t}');if('system'===e||(!e&&${m})){var t='${a}',m=window.matchMedia(t);if(m.media!==t||m.matches){${v("dark")}}else{${v("light")}}}else if(e){${d?`var x=${JSON.stringify(d)};`:""}${v(d?"x[e]":"e",!0)}}${m?"":"else{"+v(s,!1,!1)+"}"}${h}}catch(e){}}()`:`!function(){try{${f}var e=localStorage.getItem('${t}');if(e){${d?`var x=${JSON.stringify(d)};`:""}${v(d?"x[e]":"e",!0)}}else{${v(s,!1,!1)};}${h}}catch(t){}}();`;return r.createElement("script",{nonce:c,dangerouslySetInnerHTML:{__html:p}})},()=>!0),h=(e,t)=>{let n;if(!l){try{n=localStorage.getItem(e)||void 0}catch(e){}return n||t}},v=()=>{let e=document.createElement("style");return e.appendChild(document.createTextNode("*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),document.head.appendChild(e),()=>{window.getComputedStyle(document.body),setTimeout(()=>{document.head.removeChild(e)},1)}},p=e=>(e||(e=window.matchMedia(a)),e.matches?"dark":"light")},66958:function(e,t,n){Promise.resolve().then(n.t.bind(n,58877,23)),Promise.resolve().then(n.bind(n,11486)),Promise.resolve().then(n.bind(n,78495)),Promise.resolve().then(n.t.bind(n,6928,23)),Promise.resolve().then(n.t.bind(n,33195,23)),Promise.resolve().then(n.bind(n,5925))},11486:function(e,t,n){"use strict";n.r(t),n.d(t,{Header:function(){return E}});var r=n(57437);n(2265);var i=n(39311),a=n(93023),l=n(84168),o=n(30415),s=n.n(o),d=n(61396),u=n.n(d),c=n(13287),m=n(1589);let f=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,h=e=>{if("string"!=typeof e)throw TypeError("Invalid argument expected string");let t=e.match(f);if(!t)throw Error(`Invalid argument not valid semver ('${e}' received)`);return t.shift(),t},v=e=>"*"===e||"x"===e||"X"===e,p=e=>{let t=parseInt(e,10);return isNaN(t)?e:t},b=(e,t)=>typeof e!=typeof t?[String(e),String(t)]:[e,t],y=(e,t)=>{if(v(e)||v(t))return 0;let[n,r]=b(p(e),p(t));return n>r?1:n{for(let n=0;n{let n=h(e),r=h(t),i=n.pop(),a=r.pop(),l=g(n,r);return 0!==l?l:i&&a?g(i.split("."),a.split(".")):i||a?i?-1:1:0},_=(e,t,n)=>{S(n);let r=k(e,t);return x[n].includes(r)},x={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1],"!=":[-1,1]},N=Object.keys(x),S=e=>{if("string"!=typeof e)throw TypeError(`Invalid operator type, expected string but got ${typeof e}`);if(-1===N.indexOf(e))throw Error(`Invalid operator, expected one of ${N.join("|")}`)};var j=n(8724),C=n(70349),w=n(91067);let T=s()(()=>n.e(376).then(n.bind(n,15376)).then(e=>e.ThemeToggle),{loadableGenerated:{webpack:()=>[15376]},ssr:!1});function E(){var e;let{data:t}=(0,c.Q)(),n=(0,j.s)(t),o=(0,w.Z)(n,C.xj.Chat),s=null==t?void 0:null===(e=t.version)||void 0===e?void 0:e.git_describe,{data:d}=(0,m.Z)("https://api.github.com/repos/TabbyML/tabby/releases/latest",e=>fetch(e).then(e=>e.json())),f=function(e,t){try{return e&&t&&_(t.name,e,">")}catch(e){return console.warn(e),!0}}(s,d);return(0,r.jsxs)("header",{className:"from-background/10 via-background/50 to-background/80 sticky top-0 z-50 flex h-16 w-full shrink-0 items-center justify-between border-b bg-gradient-to-b px-4 backdrop-blur-xl",children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(T,{}),(0,r.jsx)(u(),{href:"/",className:(0,i.cn)((0,a.d)({variant:"link"})),children:"Dashboard"}),o&&(0,r.jsx)(u(),{href:"/playground",className:(0,i.cn)((0,a.d)({variant:"link"})),children:"Playground"})]}),(0,r.jsxs)("div",{className:"flex items-center justify-end space-x-2",children:[f&&(0,r.jsxs)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby/releases/latest",rel:"noopener noreferrer",className:(0,a.d)({variant:"ghost"}),children:[(0,r.jsx)(l.Qs,{className:"text-yellow-600 dark:text-yellow-400"}),(0,r.jsxs)("span",{className:"ml-2 hidden md:flex",children:["New version (",null==d?void 0:d.name,") available"]})]}),(0,r.jsxs)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby",rel:"noopener noreferrer",className:(0,i.cn)((0,a.d)({variant:"outline"})),children:[(0,r.jsx)(l.Mr,{}),(0,r.jsx)("span",{className:"ml-2 hidden md:flex",children:"GitHub"})]})]})]})}},78495:function(e,t,n){"use strict";n.r(t),n.d(t,{Providers:function(){return l}});var r=n(57437);n(2265);var i=n(6435),a=n(95482);function l(e){let{children:t,...n}=e;return(0,r.jsx)(i.f,{...n,children:(0,r.jsx)(a.pn,{children:t})})}},95482:function(e,t,n){"use strict";n.d(t,{_v:function(){return u},aJ:function(){return d},pn:function(){return o},u:function(){return s}});var r=n(57437),i=n(2265),a=n(75224),l=n(39311);let o=a.zt,s=a.fC,d=a.xz,u=i.forwardRef((e,t)=>{let{className:n,sideOffset:i=4,...o}=e;return(0,r.jsx)(a.VY,{ref:t,sideOffset:i,className:(0,l.cn)("z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-xs font-medium text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",n),...o})});u.displayName=a.VY.displayName},70349:function(e,t,n){"use strict";var r,i;n.d(t,{bh:function(){return l},d3:function(){return a},xj:function(){return r}}),(i=r||(r={})).Chat="CHAT",i.Completion="COMPLETION";let a={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetWorkers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"workers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"kind"}},{kind:"Field",name:{kind:"Name",value:"name"}},{kind:"Field",name:{kind:"Name",value:"addr"}},{kind:"Field",name:{kind:"Name",value:"device"}},{kind:"Field",name:{kind:"Name",value:"arch"}},{kind:"Field",name:{kind:"Name",value:"cpuInfo"}},{kind:"Field",name:{kind:"Name",value:"cpuCount"}},{kind:"Field",name:{kind:"Name",value:"gpuDevices"}}]}}]}}]},l={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetRegistrationToken"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"registrationToken"}}]}}]}},10144:function(e,t,n){"use strict";n.d(t,{G:function(){return l},$:function(){return o}});var r=n(70349);let i={"\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n":r.d3,"\n query GetRegistrationToken {\n registrationToken\n }\n":r.bh};function a(e){var t;return null!==(t=i[e])&&void 0!==t?t:{}}let l=a("\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n"),o=a("\n query GetRegistrationToken {\n registrationToken\n }\n")},71427:function(e,t,n){"use strict";n.d(t,{a:function(){return s}});var r,i=n(30713),a=n(95054),l=n(62601);let o=new a.g6("".concat(null!==(r=l.env.NEXT_PUBLIC_TABBY_SERVER_URL)&&void 0!==r?r:"","/graphql"));function s(e,t,n){return(0,i.ZP)([e,t],e=>{let[t,n]=e;return o.request(t,n)},n)}},13287:function(e,t,n){"use strict";n.d(t,{Q:function(){return a}});var r=n(1589),i=n(97605);function a(){return(0,r.Z)("/v1/health",i.Z)}},8724:function(e,t,n){"use strict";n.d(t,{s:function(){return m}});var r=n(2265),i=n(91317),a=n(16630),l=n(35512),o=n(70349),s=n(10144),d=n(71427);let u={[o.xj.Chat]:"chat_model",[o.xj.Completion]:"model"};function c(e,t){var n;return{kind:t,device:e.device,addr:"localhost",arch:"",cpuInfo:e.cpu_info,name:null!==(n=null==e?void 0:e[u[t]])&&void 0!==n?n:"",cpuCount:e.cpu_count,gpuDevices:e.gpu_devices}}function m(e){let{data:t}=(0,d.a)(s.G),n=null==t?void 0:t.workers,u=r.useMemo(()=>{let t=(0,l.Z)(n),r=(0,a.Z)(t,{kind:o.xj.Completion})>-1,s=(0,a.Z)(t,{kind:o.xj.Chat})>-1;return!r&&(null==e?void 0:e.model)&&t.push(c(e,o.xj.Completion)),!s&&(null==e?void 0:e.chat_model)&&t.push(c(e,o.xj.Chat)),(0,i.Z)(t,"kind")},[e,n]);return u}},30415:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return l}});let r=n(21024);n(2265);let i=r._(n(54));function a(e){return{default:(null==e?void 0:e.default)||e}}function l(e,t){let n=i.default,r={loading:e=>{let{error:t,isLoading:n,pastDelay:r}=e;return null}};"function"==typeof e&&(r.loader=e),Object.assign(r,t);let l=r.loader;return n({...r,loader:()=>null!=l?l().then(a):Promise.resolve(a(()=>null))})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},63388:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e,t){for(var n in t)Object.defineProperty(e,n,{enumerable:!0,get:t[n]})}(t,{suspense:function(){return i},NoSSR:function(){return a}}),n(21024),n(2265);let r=n(54922);function i(){let e=Error(r.NEXT_DYNAMIC_NO_SSR_CODE);throw e.digest=r.NEXT_DYNAMIC_NO_SSR_CODE,e}function a(e){let{children:t}=e;return t}},54:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return l}});let r=n(21024),i=r._(n(2265)),a=n(63388),l=function(e){let t=Object.assign({loader:null,loading:null,ssr:!0},e);function n(e){let n=t.loading,r=i.default.createElement(n,{isLoading:!0,pastDelay:!0,error:null}),l=t.ssr?i.default.Fragment:a.NoSSR,o=t.lazy;return i.default.createElement(i.default.Suspense,{fallback:r},i.default.createElement(l,null,i.default.createElement(o,e)))}return t.lazy=i.default.lazy(t.loader),n.displayName="LoadableComponent",n}},58877:function(){},6928:function(e){e.exports={style:{fontFamily:"'__Inter_e66fe9', '__Inter_Fallback_e66fe9'",fontStyle:"normal"},className:"__className_e66fe9",variable:"__variable_e66fe9"}},33195:function(e){e.exports={style:{fontFamily:"'__JetBrains_Mono_bd9c35', '__JetBrains_Mono_Fallback_bd9c35'",fontStyle:"normal"},className:"__className_bd9c35",variable:"__variable_bd9c35"}}},function(e){e.O(0,[882,845,431,892,396,967,971,864,744],function(){return e(e.s=66958)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/layout-ca2c7a9f923b6e61.js b/ee/tabby-webserver/ui/_next/static/chunks/app/layout-ca2c7a9f923b6e61.js
deleted file mode 100644
index 74fd9aaeec2..00000000000
--- a/ee/tabby-webserver/ui/_next/static/chunks/app/layout-ca2c7a9f923b6e61.js
+++ /dev/null
@@ -1 +0,0 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{6435:function(e,t,n){"use strict";n.d(t,{F:function(){return d},f:function(){return u}});var r=n(2265);let a=["light","dark"],i="(prefers-color-scheme: dark)",l="undefined"==typeof window,o=(0,r.createContext)(void 0),s={setTheme:e=>{},themes:[]},d=()=>{var e;return null!==(e=(0,r.useContext)(o))&&void 0!==e?e:s},u=e=>(0,r.useContext)(o)?r.createElement(r.Fragment,null,e.children):r.createElement(m,e),c=["light","dark"],m=({forcedTheme:e,disableTransitionOnChange:t=!1,enableSystem:n=!0,enableColorScheme:l=!0,storageKey:s="theme",themes:d=c,defaultTheme:u=n?"system":"light",attribute:m="data-theme",value:b,children:y,nonce:k})=>{let[g,_]=(0,r.useState)(()=>h(s,u)),[x,N]=(0,r.useState)(()=>h(s)),S=b?Object.values(b):d,j=(0,r.useCallback)(e=>{let r=e;if(!r)return;"system"===e&&n&&(r=p());let i=b?b[r]:r,o=t?v():null,s=document.documentElement;if("class"===m?(s.classList.remove(...S),i&&s.classList.add(i)):i?s.setAttribute(m,i):s.removeAttribute(m),l){let e=a.includes(u)?u:null,t=a.includes(r)?r:e;s.style.colorScheme=t}null==o||o()},[]),C=(0,r.useCallback)(e=>{_(e);try{localStorage.setItem(s,e)}catch(e){}},[e]),w=(0,r.useCallback)(t=>{let r=p(t);N(r),"system"===g&&n&&!e&&j("system")},[g,e]);(0,r.useEffect)(()=>{let e=window.matchMedia(i);return e.addListener(w),w(e),()=>e.removeListener(w)},[w]),(0,r.useEffect)(()=>{let e=e=>{e.key===s&&C(e.newValue||u)};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[C]),(0,r.useEffect)(()=>{j(null!=e?e:g)},[e,g]);let T=(0,r.useMemo)(()=>({theme:g,setTheme:C,forcedTheme:e,resolvedTheme:"system"===g?x:g,themes:n?[...d,"system"]:d,systemTheme:n?x:void 0}),[g,C,e,x,n,d]);return r.createElement(o.Provider,{value:T},r.createElement(f,{forcedTheme:e,disableTransitionOnChange:t,enableSystem:n,enableColorScheme:l,storageKey:s,themes:d,defaultTheme:u,attribute:m,value:b,children:y,attrs:S,nonce:k}),y)},f=(0,r.memo)(({forcedTheme:e,storageKey:t,attribute:n,enableSystem:l,enableColorScheme:o,defaultTheme:s,value:d,attrs:u,nonce:c})=>{let m="system"===s,f="class"===n?`var d=document.documentElement,c=d.classList;c.remove(${u.map(e=>`'${e}'`).join(",")});`:`var d=document.documentElement,n='${n}',s='setAttribute';`,h=o?a.includes(s)&&s?`if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${s}'`:"if(e==='light'||e==='dark')d.style.colorScheme=e":"",v=(e,t=!1,r=!0)=>{let i=d?d[e]:e,l=t?e+"|| ''":`'${i}'`,s="";return o&&r&&!t&&a.includes(e)&&(s+=`d.style.colorScheme = '${e}';`),"class"===n?s+=t||i?`c.add(${l})`:"null":i&&(s+=`d[s](n,${l})`),s},p=e?`!function(){${f}${v(e)}}()`:l?`!function(){try{${f}var e=localStorage.getItem('${t}');if('system'===e||(!e&&${m})){var t='${i}',m=window.matchMedia(t);if(m.media!==t||m.matches){${v("dark")}}else{${v("light")}}}else if(e){${d?`var x=${JSON.stringify(d)};`:""}${v(d?"x[e]":"e",!0)}}${m?"":"else{"+v(s,!1,!1)+"}"}${h}}catch(e){}}()`:`!function(){try{${f}var e=localStorage.getItem('${t}');if(e){${d?`var x=${JSON.stringify(d)};`:""}${v(d?"x[e]":"e",!0)}}else{${v(s,!1,!1)};}${h}}catch(t){}}();`;return r.createElement("script",{nonce:c,dangerouslySetInnerHTML:{__html:p}})},()=>!0),h=(e,t)=>{let n;if(!l){try{n=localStorage.getItem(e)||void 0}catch(e){}return n||t}},v=()=>{let e=document.createElement("style");return e.appendChild(document.createTextNode("*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),document.head.appendChild(e),()=>{window.getComputedStyle(document.body),setTimeout(()=>{document.head.removeChild(e)},1)}},p=e=>(e||(e=window.matchMedia(i)),e.matches?"dark":"light")},25330:function(e,t,n){Promise.resolve().then(n.t.bind(n,58877,23)),Promise.resolve().then(n.bind(n,11486)),Promise.resolve().then(n.bind(n,78495)),Promise.resolve().then(n.t.bind(n,6928,23)),Promise.resolve().then(n.t.bind(n,33195,23)),Promise.resolve().then(n.bind(n,5925))},11486:function(e,t,n){"use strict";n.r(t),n.d(t,{Header:function(){return E}});var r=n(57437);n(2265);var a=n(39311),i=n(93023),l=n(84168),o=n(30415),s=n.n(o),d=n(61396),u=n.n(d),c=n(13287),m=n(1589);let f=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,h=e=>{if("string"!=typeof e)throw TypeError("Invalid argument expected string");let t=e.match(f);if(!t)throw Error(`Invalid argument not valid semver ('${e}' received)`);return t.shift(),t},v=e=>"*"===e||"x"===e||"X"===e,p=e=>{let t=parseInt(e,10);return isNaN(t)?e:t},b=(e,t)=>typeof e!=typeof t?[String(e),String(t)]:[e,t],y=(e,t)=>{if(v(e)||v(t))return 0;let[n,r]=b(p(e),p(t));return n>r?1:n{for(let n=0;n{let n=h(e),r=h(t),a=n.pop(),i=r.pop(),l=k(n,r);return 0!==l?l:a&&i?k(a.split("."),i.split(".")):a||i?a?-1:1:0},_=(e,t,n)=>{S(n);let r=g(e,t);return x[n].includes(r)},x={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1],"!=":[-1,1]},N=Object.keys(x),S=e=>{if("string"!=typeof e)throw TypeError(`Invalid operator type, expected string but got ${typeof e}`);if(-1===N.indexOf(e))throw Error(`Invalid operator, expected one of ${N.join("|")}`)};var j=n(8724),C=n(70349),w=n(91067);let T=s()(()=>n.e(376).then(n.bind(n,15376)).then(e=>e.ThemeToggle),{loadableGenerated:{webpack:()=>[15376]},ssr:!1});function E(){var e;let{data:t}=(0,c.Q)(),n=(0,j.s)(t),o=(0,w.Z)(n,C.xj.Chat),s=null==t?void 0:null===(e=t.version)||void 0===e?void 0:e.git_describe,{data:d}=(0,m.Z)("https://api.github.com/repos/TabbyML/tabby/releases/latest",e=>fetch(e).then(e=>e.json())),f=function(e,t){try{return e&&t&&_(t.name,e,">")}catch(e){return console.warn(e),!0}}(s,d);return(0,r.jsxs)("header",{className:"from-background/10 via-background/50 to-background/80 sticky top-0 z-50 flex h-16 w-full shrink-0 items-center justify-between border-b bg-gradient-to-b px-4 backdrop-blur-xl",children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(T,{}),(0,r.jsx)(u(),{href:"/",className:(0,a.cn)((0,i.d)({variant:"link"})),children:"Dashboard"}),o&&(0,r.jsx)(u(),{href:"/playground",className:(0,a.cn)((0,i.d)({variant:"link"})),children:"Playground"})]}),(0,r.jsxs)("div",{className:"flex items-center justify-end space-x-2",children:[f&&(0,r.jsxs)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby/releases/latest",rel:"noopener noreferrer",className:(0,i.d)({variant:"ghost"}),children:[(0,r.jsx)(l.Qs,{className:"text-yellow-600 dark:text-yellow-400"}),(0,r.jsxs)("span",{className:"ml-2 hidden md:flex",children:["New version (",null==d?void 0:d.name,") available"]})]}),(0,r.jsxs)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby",rel:"noopener noreferrer",className:(0,a.cn)((0,i.d)({variant:"outline"})),children:[(0,r.jsx)(l.Mr,{}),(0,r.jsx)("span",{className:"ml-2 hidden md:flex",children:"GitHub"})]})]})]})}},78495:function(e,t,n){"use strict";n.r(t),n.d(t,{Providers:function(){return l}});var r=n(57437);n(2265);var a=n(6435),i=n(95482);function l(e){let{children:t,...n}=e;return(0,r.jsx)(a.f,{...n,children:(0,r.jsx)(i.pn,{children:t})})}},95482:function(e,t,n){"use strict";n.d(t,{_v:function(){return u},aJ:function(){return d},pn:function(){return o},u:function(){return s}});var r=n(57437),a=n(2265),i=n(75224),l=n(39311);let o=i.zt,s=i.fC,d=i.xz,u=a.forwardRef((e,t)=>{let{className:n,sideOffset:a=4,...o}=e;return(0,r.jsx)(i.VY,{ref:t,sideOffset:a,className:(0,l.cn)("z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-xs font-medium text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",n),...o})});u.displayName=i.VY.displayName},70349:function(e,t,n){"use strict";var r,a;n.d(t,{bh:function(){return l},d3:function(){return i},xj:function(){return r}}),(a=r||(r={})).Chat="CHAT",a.Completion="COMPLETION";let i={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetWorkers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"workers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"kind"}},{kind:"Field",name:{kind:"Name",value:"name"}},{kind:"Field",name:{kind:"Name",value:"addr"}},{kind:"Field",name:{kind:"Name",value:"device"}},{kind:"Field",name:{kind:"Name",value:"arch"}},{kind:"Field",name:{kind:"Name",value:"cpuInfo"}},{kind:"Field",name:{kind:"Name",value:"cpuCount"}},{kind:"Field",name:{kind:"Name",value:"cudaDevices"}}]}}]}}]},l={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetRegistrationToken"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"registrationToken"}}]}}]}},10144:function(e,t,n){"use strict";n.d(t,{G:function(){return l},$:function(){return o}});var r=n(70349);let a={"\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n cudaDevices\n }\n }\n":r.d3,"\n query GetRegistrationToken {\n registrationToken\n }\n":r.bh};function i(e){var t;return null!==(t=a[e])&&void 0!==t?t:{}}let l=i("\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n cudaDevices\n }\n }\n"),o=i("\n query GetRegistrationToken {\n registrationToken\n }\n")},71427:function(e,t,n){"use strict";n.d(t,{a:function(){return s}});var r,a=n(30713),i=n(95054),l=n(62601);let o=new i.g6("".concat(null!==(r=l.env.NEXT_PUBLIC_TABBY_SERVER_URL)&&void 0!==r?r:"","/graphql"));function s(e,t,n){return(0,a.ZP)([e,t],e=>{let[t,n]=e;return o.request(t,n)},n)}},13287:function(e,t,n){"use strict";n.d(t,{Q:function(){return i}});var r=n(1589),a=n(97605);function i(){return(0,r.Z)("/v1/health",a.Z)}},8724:function(e,t,n){"use strict";n.d(t,{s:function(){return m}});var r=n(2265),a=n(91317),i=n(16630),l=n(35512),o=n(70349),s=n(10144),d=n(71427);let u={[o.xj.Chat]:"chat_model",[o.xj.Completion]:"model"};function c(e,t){var n;return{kind:t,device:e.device,addr:"localhost",arch:"",cpuInfo:e.cpu_info,name:null!==(n=null==e?void 0:e[u[t]])&&void 0!==n?n:"",cpuCount:e.cpu_count,cudaDevices:e.cuda_devices}}function m(e){let{data:t}=(0,d.a)(s.G),n=null==t?void 0:t.workers,u=r.useMemo(()=>{let t=(0,l.Z)(n),r=(0,i.Z)(t,{kind:o.xj.Completion})>-1,s=(0,i.Z)(t,{kind:o.xj.Chat})>-1;return!r&&(null==e?void 0:e.model)&&t.push(c(e,o.xj.Completion)),!s&&(null==e?void 0:e.chat_model)&&t.push(c(e,o.xj.Chat)),(0,a.Z)(t,"kind")},[e,n]);return u}},30415:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return l}});let r=n(21024);n(2265);let a=r._(n(54));function i(e){return{default:(null==e?void 0:e.default)||e}}function l(e,t){let n=a.default,r={loading:e=>{let{error:t,isLoading:n,pastDelay:r}=e;return null}};"function"==typeof e&&(r.loader=e),Object.assign(r,t);let l=r.loader;return n({...r,loader:()=>null!=l?l().then(i):Promise.resolve(i(()=>null))})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},63388:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e,t){for(var n in t)Object.defineProperty(e,n,{enumerable:!0,get:t[n]})}(t,{suspense:function(){return a},NoSSR:function(){return i}}),n(21024),n(2265);let r=n(54922);function a(){let e=Error(r.NEXT_DYNAMIC_NO_SSR_CODE);throw e.digest=r.NEXT_DYNAMIC_NO_SSR_CODE,e}function i(e){let{children:t}=e;return t}},54:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return l}});let r=n(21024),a=r._(n(2265)),i=n(63388),l=function(e){let t=Object.assign({loader:null,loading:null,ssr:!0},e);function n(e){let n=t.loading,r=a.default.createElement(n,{isLoading:!0,pastDelay:!0,error:null}),l=t.ssr?a.default.Fragment:i.NoSSR,o=t.lazy;return a.default.createElement(a.default.Suspense,{fallback:r},a.default.createElement(l,null,a.default.createElement(o,e)))}return t.lazy=a.default.lazy(t.loader),n.displayName="LoadableComponent",n}},58877:function(){},6928:function(e){e.exports={style:{fontFamily:"'__Inter_e66fe9', '__Inter_Fallback_e66fe9'",fontStyle:"normal"},className:"__className_e66fe9",variable:"__variable_e66fe9"}},33195:function(e){e.exports={style:{fontFamily:"'__JetBrains_Mono_bd9c35', '__JetBrains_Mono_Fallback_bd9c35'",fontStyle:"normal"},className:"__className_bd9c35",variable:"__variable_bd9c35"}}},function(e){e.O(0,[882,845,431,892,396,967,971,864,744],function(){return e(e.s=25330)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-8ff3131e9c77580f.js b/ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-0e44acab13f2ae38.js
similarity index 99%
rename from ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-8ff3131e9c77580f.js
rename to ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-0e44acab13f2ae38.js
index eaf17c9895e..546726321fd 100644
--- a/ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-8ff3131e9c77580f.js
+++ b/ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-0e44acab13f2ae38.js
@@ -1 +1 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[383],{24283:function(e,t,s){Promise.resolve().then(s.bind(s,34926))},34926:function(e,t,s){"use strict";s.r(t),s.d(t,{default:function(){return eA}});var n=s(57437),l=s(2265),a=s(82504),r=s(39311),i=s(16775),o=s(48975),d=s(82180),c=s(30513),u=s(4523),m=s(77723),f=s(84168),x=s(93023);let h={javascript:".js",python:".py",java:".java",c:".c",cpp:".cpp","c++":".cpp","c#":".cs",ruby:".rb",php:".php",swift:".swift","objective-c":".m",kotlin:".kt",typescript:".ts",go:".go",perl:".pl",rust:".rs",scala:".scala",haskell:".hs",lua:".lua",shell:".sh",sql:".sql",html:".html",css:".css"},p=function(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],s="ABCDEFGHJKLMNPQRSTUVWXY3456789",n="";for(let t=0;t{let{language:t,value:s}=e,{isCopied:l,copyToClipboard:a}=(0,m.m)({timeout:2e3});return(0,n.jsxs)("div",{className:"codeblock relative w-full bg-zinc-950 font-sans",children:[(0,n.jsxs)("div",{className:"flex w-full items-center justify-between bg-zinc-800 px-6 py-2 pr-4 text-zinc-100",children:[(0,n.jsx)("span",{className:"text-xs lowercase",children:t}),(0,n.jsxs)("div",{className:"flex items-center space-x-1",children:[(0,n.jsxs)(x.z,{variant:"ghost",className:"hover:bg-zinc-800 focus-visible:ring-1 focus-visible:ring-slate-700 focus-visible:ring-offset-0",onClick:()=>{let e=h[t]||".file",n="file-".concat(p(3,!0)).concat(e),l=window.prompt("Enter file name",n);if(!l)return;let a=new Blob([s],{type:"text/plain"}),r=URL.createObjectURL(a),i=document.createElement("a");i.download=l,i.href=r,i.style.display="none",document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r)},size:"icon",children:[(0,n.jsx)(f.Dj,{}),(0,n.jsx)("span",{className:"sr-only",children:"Download"})]}),(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",className:"text-xs hover:bg-zinc-800 focus-visible:ring-1 focus-visible:ring-slate-700 focus-visible:ring-offset-0",onClick:()=>{l||a(s)},children:[l?(0,n.jsx)(f.NO,{}):(0,n.jsx)(f.vU,{}),(0,n.jsx)("span",{className:"sr-only",children:"Copy code"})]})]})]}),(0,n.jsx)(c.Z,{language:t,style:u.RY,PreTag:"div",showLineNumbers:!0,customStyle:{margin:0,width:"100%",background:"transparent",padding:"1.5rem 1rem"},codeTagProps:{style:{fontSize:"0.9rem",fontFamily:"var(--font-mono)"}},children:s})]})});v.displayName="CodeBlock";var g=s(19349);let j=(0,l.memo)(g.D,(e,t)=>e.children===t.children&&e.className===t.className);var b=s(16691),y=s.n(b),N=s(33555);function w(e){let{message:t,className:s,handleMessageAction:l,...a}=e;return(0,n.jsxs)("div",{className:(0,r.cn)("flex items-center justify-end transition-opacity group-hover:opacity-100 md:absolute md:-right-[5rem] md:-top-2 md:opacity-0",s),...a,children:["user"===t.role?(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:e=>l(t.id,"edit"),children:[(0,n.jsx)(f.yl,{}),(0,n.jsx)("span",{className:"sr-only",children:"Edit message"})]}):(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:e=>l(t.id,"regenerate"),children:[(0,n.jsx)(f.tr,{}),(0,n.jsx)("span",{className:"sr-only",children:"Regenerate message"})]}),(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:e=>l(t.id,"delete"),children:[(0,n.jsx)(f.IT,{}),(0,n.jsx)("span",{className:"sr-only",children:"Delete message"})]}),(0,n.jsx)(N.q,{value:t.content})]})}function k(e){let{message:t,handleMessageAction:s,...l}=e;return(0,n.jsxs)("div",{className:(0,r.cn)("group relative mb-4 flex items-start md:-ml-12"),...l,children:[(0,n.jsx)("div",{className:(0,r.cn)("flex h-8 w-8 shrink-0 select-none items-center justify-center rounded-md border shadow","user"===t.role?"bg-background":"bg-primary text-primary-foreground"),children:"user"===t.role?(0,n.jsx)(f.f7,{}):(0,n.jsx)(C,{})}),(0,n.jsxs)("div",{className:"ml-4 flex-1 space-y-2 overflow-hidden px-1",children:[(0,n.jsx)(j,{className:"prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0",remarkPlugins:[o.Z,d.Z],components:{p(e){let{children:t}=e;return(0,n.jsx)("p",{className:"mb-2 last:mb-0",children:t})},code(e){let{node:t,inline:s,className:l,children:a,...r}=e;if(a.length){if("▍"==a[0])return(0,n.jsx)("span",{className:"mt-1 animate-pulse cursor-default",children:"▍"});a[0]=a[0].replace("`▍`","▍")}let i=/language-(\w+)/.exec(l||"");return s?(0,n.jsx)("code",{className:l,...r,children:a}):(0,n.jsx)(v,{language:i&&i[1]||"",value:String(a).replace(/\n$/,""),...r},Math.random())}},children:t.content}),(0,n.jsx)(w,{message:t,handleMessageAction:s})]})]})}function C(){return(0,n.jsx)(y(),{style:{borderRadius:4},src:"https://avatars.githubusercontent.com/u/125617854?s=128&v=4",alt:"tabby",width:"128",height:"128"})}function z(e){let{messages:t,handleMessageAction:s}=e;return t.length?(0,n.jsx)("div",{className:"relative mx-auto max-w-2xl px-4",children:t.map((e,l)=>(0,n.jsxs)("div",{children:[(0,n.jsx)(k,{message:e,handleMessageAction:s}),l{let{className:s,sideOffset:l=4,...a}=e;return(0,n.jsx)(S.VY,{ref:t,sideOffset:l,className:(0,r.cn)("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",s),...a})});T.displayName=S.VY.displayName;var O=s(92402),L=s(45470),Z=s(24144),A=s(62700);let M=l.createContext({}),V=l.forwardRef((e,t)=>(0,n.jsx)(H,{...e,ref:t}));V.displayName="ComboboxAnchor";let F=l.forwardRef((e,t)=>{let{getInputProps:s,open:a}=l.useContext(M),{onKeyDown:r,onChange:i,onInput:o,onBlur:d,onClick:c,...u}=e;return(0,n.jsx)(L.Z,{...s((0,A.Z)({onKeyDown:e=>{"Enter"===e.key&&a?e.preventDefault():null==r||r(e)},onChange:i,onInput:o,onBlur:d,onClick:c,ref:t},Z.Z)),...u})});F.displayName="ComboboxTextarea";let q=l.forwardRef((e,t)=>{let{children:s,style:a,popupMatchAnchorWidth:r,...i}=e,{getMenuProps:o,anchorRef:d}=l.useContext(M),c=l.useRef(void 0);return l.useLayoutEffect(()=>{if(r){let e=d.current;if(e){let t=e.getBoundingClientRect();c.current=t.width}}},[]),(0,n.jsx)(I,{children:(0,n.jsx)(T,{align:"start",onOpenAutoFocus:e=>e.preventDefault(),style:{width:c.current,...a},...o({ref:t},{suppressRefError:!0}),...i,children:s})})});q.displayName="ComboboxContent";let B=l.forwardRef((e,t)=>{let{item:s,index:a,className:i,children:o,disabled:d,...c}=e,{highlightedIndex:u,selectedItem:m,getItemProps:f}=l.useContext(M),x=u===a,h=m===s;return(0,n.jsx)(_,{asChild:!0,children:(0,n.jsx)("div",{className:(0,r.cn)("relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",x&&"text-accent-foreground bg-accent",h&&"font-bold",d&&"pointer-events-none opacity-50",i),...f({item:s,index:a,onMouseLeave:e=>e.preventDefault(),onMouseOut:e=>e.preventDefault()}),...c,children:"function"==typeof o?o({highlighted:x,selected:h}):o})},s.id)});function P(e){let{options:t,onSelect:s,inputRef:a,children:r}=e,[i,o]=l.useState(!1),d=l.useRef(null),c=null!=a?a:d,u=l.useRef(null),m=l.useCallback((e,t)=>{let{type:s,changes:n}=t;return s===O.Kb.stateChangeTypes.MenuMouseLeave?{...n,highlightedIndex:e.highlightedIndex}:n},[]),f=(0,O.Kb)({items:null!=t?t:[],isOpen:i,onSelectedItemChange(e){let{selectedItem:t}=e;t&&(null==s||s(t),o(!1))},onIsOpenChange:e=>{let{isOpen:t}=e;t||o(!1)},stateReducer:m}),{setHighlightedIndex:x,highlightedIndex:h}=f,p=i&&!!(null==t?void 0:t.length);l.useEffect(()=>{p&&t.length&&-1===h&&x(0),p&&!t.length&&o(!1)},[p,t]),l.useEffect(()=>{(null==t?void 0:t.length)?o(!0):o(!1)},[t]);let v=l.useMemo(()=>({...f,open:p,inputRef:c,anchorRef:u}),[f,p,c,u]);return(0,n.jsx)(M.Provider,{value:v,children:(0,n.jsx)(D,{open:p,children:"function"==typeof r?r(v):r})})}B.displayName="ComboboxOption";var U=s(97605),Y=s(50976),K=s(91067);let J=l.forwardRef(function(e,t){let{onSubmit:s,input:a,setInput:i,isLoading:o}=e,{formRef:d,onKeyDown:c}=function(){let e=(0,l.useRef)(null);return{formRef:e,onKeyDown:t=>{if("Enter"===t.key&&!t.shiftKey&&!t.nativeEvent.isComposing){var s;null===(s=e.current)||void 0===s||s.requestSubmit(),t.preventDefault()}}}}(),[u,m]=l.useState(null),h=l.useRef(""),p=l.useRef(null),v=l.useRef(),g=l.useRef(),[j,b]=l.useState([]),[y,N]=l.useState({});(0,R.ZP)(u,U.Z,{revalidateOnFocus:!1,dedupingInterval:0,onSuccess:(e,t)=>{var s;t===h.current&&b(null!==(s=null==e?void 0:e.hits)&&void 0!==s?s:[])}}),l.useImperativeHandle(t,()=>({focus:()=>{var e;null===(e=p.current)||void 0===e||e.focus()}})),l.useEffect(()=>{a&&p.current&&p.current!==document.activeElement&&p.current.focus()},[a]),l.useLayoutEffect(()=>{var e,t,s;(null===(e=g.current)||void 0===e?void 0:e.length)&&(null===(s=p.current)||void 0===s||null===(t=s.setSelectionRange)||void 0===t||t.call(s,g.current[0],g.current[1]),g.current=void 0)});let w=l.useMemo(()=>(0,Y.Z)(e=>{var t,s,n,l;let a=null!==(n=null===(t=e.target)||void 0===t?void 0:t.value)&&void 0!==n?n:"",r=null!==(l=null===(s=e.target)||void 0===s?void 0:s.selectionEnd)&&void 0!==l?l:0,i=$(a,r),o=null==i?void 0:i[1];if(o){let e=encodeURIComponent("name:".concat(o," kind:function")),t="/v1beta/search?q=".concat(e);h.current=t,m(t)}else b([])},200),[]),k=async e=>{if(e.preventDefault(),!(null==a?void 0:a.trim()))return;let t=a;Object.keys(y).forEach(e=>{var s,n,l;let a=y[e];(null==a?void 0:a.doc)&&(t=t.replaceAll(e,"\n```".concat(null!==(n=null===(s=a.doc)||void 0===s?void 0:s.language)&&void 0!==n?n:"","\n").concat(null!==(l=a.doc.body)&&void 0!==l?l:"","\n","```","\n")))}),i(""),await s(t)},C=(e,t)=>{t&&["ArrowRight","ArrowLeft","Home","End"].includes(e.key)?b([]):c(e)};return(0,n.jsx)("form",{onSubmit:k,ref:d,children:(0,n.jsx)(P,{inputRef:p,options:j,onSelect:e=>{var t,s,n;let l=null!==(t=v.current)&&void 0!==t?t:0,r=$(a,l);if(r){N({...y,["@".concat(null===(s=e.doc)||void 0===s?void 0:s.name)]:e});let t="@".concat(null==e?void 0:null===(n=e.doc)||void 0===n?void 0:n.name," "),o=a.substring(0,l).replace(new RegExp(r[0]),""),d=o.length+t.length;g.current=[d,d],i(o+t+a.slice(l))}b([])},children:e=>{var t,s,l,d;let{open:c,highlightedIndex:u}=e,m=null==j?void 0:j[u];return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(V,{children:(0,n.jsxs)("div",{className:"bg-background relative flex max-h-60 w-full grow flex-col overflow-hidden px-8 sm:rounded-md sm:border sm:px-12",children:[(0,n.jsx)("span",{className:(0,r.cn)((0,x.d)({size:"sm",variant:"ghost"}),"bg-background hover:bg-background absolute left-0 top-4 h-8 w-8 rounded-full p-0 sm:left-4"),children:(0,n.jsx)(f.yl,{})}),(0,n.jsx)(F,{tabIndex:0,rows:1,placeholder:"Ask a question.",spellCheck:!1,className:"min-h-[60px] w-full resize-none bg-transparent px-4 py-[1.3rem] focus-within:outline-none sm:text-sm",value:a,ref:p,onChange:e=>{(0,K.Z)(e,"target.value")?(v.current=e.target.selectionEnd,i(e.target.value),w(e)):v.current=void 0},onKeyDown:e=>C(e,c)}),(0,n.jsx)("div",{className:"absolute right-0 top-4 sm:right-4",children:(0,n.jsxs)(E.u,{children:[(0,n.jsx)(E.aJ,{asChild:!0,children:(0,n.jsxs)(x.z,{type:"submit",size:"icon",disabled:o||""===a,children:[(0,n.jsx)(f.vq,{}),(0,n.jsx)("span",{className:"sr-only",children:"Send message"})]})}),(0,n.jsx)(E._v,{children:"Send message"})]})})]})}),(0,n.jsx)(q,{align:"start",side:"top",onOpenAutoFocus:e=>e.preventDefault(),className:"w-[60vw] md:w-[430px]",children:(0,n.jsxs)(D,{open:c&&!!m,children:[(0,n.jsx)(H,{asChild:!0,children:(0,n.jsx)("div",{className:"max-h-[300px] overflow-y-scroll",children:c&&!!(null==j?void 0:j.length)&&j.map((e,t)=>{var s,l,a;return(0,n.jsx)(B,{item:e,index:t,children:(0,n.jsxs)("div",{className:"flex w-full items-center justify-between gap-8 overflow-x-hidden",children:[(0,n.jsxs)("div",{className:"flex items-center gap-1",children:[(0,n.jsx)(W,{kind:null==e?void 0:null===(s=e.doc)||void 0===s?void 0:s.kind}),(0,n.jsxs)("div",{className:"max-w-[200px] truncate",children:[null==e?void 0:null===(l=e.doc)||void 0===l?void 0:l.name,"(...)"]})]}),(0,n.jsx)("div",{className:"text-muted-foreground flex-1 truncate text-right text-sm",children:null==e?void 0:null===(a=e.doc)||void 0===a?void 0:a.body})]})},null==e?void 0:e.id)})})}),(0,n.jsx)(T,{asChild:!0,align:"start",side:"right",alignOffset:-4,onOpenAutoFocus:e=>e.preventDefault(),onKeyDownCapture:e=>e.preventDefault(),className:"rounded-none",collisionPadding:{bottom:120},children:(0,n.jsxs)("div",{className:"flex max-h-[70vh] w-[20vw] flex-col overflow-y-auto px-2 md:w-[240px] lg:w-[340px]",children:[(0,n.jsxs)("div",{className:"mb-2",children:[(null==m?void 0:null===(t=m.doc)||void 0===t?void 0:t.kind)?"(".concat(null==m?void 0:null===(s=m.doc)||void 0===s?void 0:s.kind,") "):"",null==m?void 0:null===(l=m.doc)||void 0===l?void 0:l.name]}),(0,n.jsx)("div",{className:"text-muted-foreground flex-1 whitespace-pre-wrap break-all",children:null==m?void 0:null===(d=m.doc)||void 0===d?void 0:d.body})]})})]})})]})}})})});function $(e,t){let s=e.substring(0,t),n=/@(\w+)$/.exec(s);return n}function W(e){let{kind:t,...s}=e;return(0,n.jsx)(f.sW,{...s})}function X(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,[t,s]=l.useState(!1);return l.useEffect(()=>{let t=()=>{s(window.innerHeight+window.scrollY>=document.body.offsetHeight-e)};return window.addEventListener("scroll",t,{passive:!0}),t(),()=>{window.removeEventListener("scroll",t)}},[e]),t}function G(e){let{className:t,...s}=e,l=X();return(0,n.jsxs)(x.z,{variant:"outline",size:"icon",className:(0,r.cn)("absolute right-4 top-1 z-10 bg-background transition-opacity duration-300 sm:right-8 md:top-2",l?"opacity-0":"opacity-100",t),onClick:()=>window.scrollTo({top:document.body.offsetHeight,behavior:"smooth"}),...s,children:[(0,n.jsx)(f.BD,{}),(0,n.jsx)("span",{className:"sr-only",children:"Scroll to bottom"})]})}function Q(e){let{href:t,children:s}=e;return(0,n.jsxs)("a",{href:t,target:"_blank",className:"inline-flex flex-1 justify-center gap-1 leading-4 hover:underline",children:[(0,n.jsx)("span",{children:s}),(0,n.jsx)("svg",{"aria-hidden":"true",height:"7",viewBox:"0 0 6 6",width:"7",className:"opacity-70",children:(0,n.jsx)("path",{d:"M1.25215 5.54731L0.622742 4.9179L3.78169 1.75597H1.3834L1.38936 0.890915H5.27615V4.78069H4.40513L4.41109 2.38538L1.25215 5.54731Z",fill:"currentColor"})})]})}function ee(e){let{className:t,...s}=e;return(0,n.jsxs)("p",{className:(0,r.cn)("px-2 text-center text-xs leading-normal text-muted-foreground",t),...s,children:[(0,n.jsx)(Q,{href:"https://tabby.tabbyml.com",children:"Tabby"}),", an opensource, self-hosted AI coding assistant ."]})}function et(e){let{id:t,isLoading:s,stop:a,append:i,reload:o,input:d,setInput:c,messages:u,className:m,onSubmit:h}=e,p=l.useRef(null);return l.useEffect(()=>{var e;null==p||null===(e=p.current)||void 0===e||e.focus()},[t]),(0,n.jsxs)("div",{className:(0,r.cn)("from-muted/10 to-muted/30 bg-gradient-to-b from-10% to-50%",m),children:[(0,n.jsx)(G,{}),(0,n.jsxs)("div",{className:"mx-auto sm:max-w-2xl sm:px-4",children:[(0,n.jsx)("div",{className:"flex h-10 items-center justify-center",children:s?(0,n.jsxs)(x.z,{variant:"outline",onClick:()=>a(),className:"bg-background",children:[(0,n.jsx)(f.zu,{className:"mr-2"}),"Stop generating"]}):(null==u?void 0:u.length)>0&&(0,n.jsxs)(x.z,{variant:"outline",onClick:()=>o(),className:"bg-background",children:[(0,n.jsx)(f.tr,{className:"mr-2"}),"Regenerate response"]})}),(0,n.jsxs)("div",{className:"bg-background space-y-4 border-t px-4 py-2 shadow-lg sm:rounded-t-xl sm:border md:py-4",children:[(0,n.jsx)(J,{ref:p,onSubmit:h,input:d,setInput:c,isLoading:s}),(0,n.jsx)(ee,{className:"hidden sm:block"})]})]})]})}let es=[{heading:"Convert list of string to numbers",message:"How to convert a list of string to numbers in python"},{heading:"How to parse email address",message:"How to parse email address with regex"}];function en(e){let{setInput:t}=e;return(0,n.jsx)("div",{className:"mx-auto max-w-2xl px-4",children:(0,n.jsxs)("div",{className:"rounded-lg border bg-background p-8",children:[(0,n.jsx)("h1",{className:"mb-2 text-lg font-semibold",children:"Welcome to Playground!"}),(0,n.jsx)("p",{className:"leading-normal text-muted-foreground",children:"You can start a conversation here or try the following examples:"}),(0,n.jsx)("div",{className:"mt-4 flex flex-col items-start space-y-2",children:es.map((e,s)=>(0,n.jsxs)(x.z,{variant:"link",className:"h-auto p-0 text-base",onClick:()=>t(e.message),children:[(0,n.jsx)(f.Ec,{className:"mr-2 text-muted-foreground"}),e.heading]},s))})]})})}var el=s(4327);function ea(e){let{trackVisibility:t}=e,s=X(),{ref:a,entry:r,inView:i}=(0,el.YD)({trackVisibility:t,delay:100,rootMargin:"0px 0px -150px 0px"});return l.useEffect(()=>{s&&t&&!i&&(null==r||r.target.scrollIntoView({block:"start"}))},[i,r,s,t]),(0,n.jsx)("div",{ref:a,className:"h-px w-full"})}var er=s(5925),ei=s(4913);let eo=new TextDecoder("utf-8");async function ed(e,t){for(let s of e){let{content:e}=JSON.parse(s);t.enqueue(e)}}async function ec(e,t){let s="";for(;;){let{value:n,done:l}=await e.read();if(l)break;s+=eo.decode(n,{stream:!0});let a=s.split(/\r\n|\n|\r/g);s=a.pop()||"",await ed(a,t)}if(s){let e=[s];await ed(e,t)}t.close()}var eu=s(62601);let em=eu.env.NEXT_PUBLIC_TABBY_SERVER_URL||"";var ef=s(94660),ex=s(74810);let eh=["_hasHydrated","setHasHydrated"],ep={_hasHydrated:!1,chats:void 0,activeChatId:(0,r.x0)()},ev=(0,ef.Ue)()((0,ex.tJ)(e=>({...ep,setHasHydrated:t=>{e({_hasHydrated:t})}}),{name:"tabby-chat-storage",partialize:e=>Object.fromEntries(Object.entries(e).filter(e=>{let[t]=e;return!eh.includes(t)})),onRehydrateStorage:()=>e=>{e&&e.setHasHydrated(!0)}}));ev.getState;let eg=ev.setState,ej=e=>{eg(()=>({activeChatId:e}))},eb=(e,t)=>{let s=null!=e?e:(0,r.x0)();eg(e=>({activeChatId:s,chats:[{id:s,title:null!=t?t:"",messages:[],createdAt:new Date,userId:"",path:""},...e.chats||[]]}))},ey=e=>{eg(t=>{var s;return{activeChatId:(0,r.x0)(),chats:null===(s=t.chats)||void 0===s?void 0:s.filter(t=>t.id!==e)}})},eN=()=>{eg(()=>({activeChatId:(0,r.x0)(),chats:[]}))},ew=(e,t)=>{eg(s=>{var n;return{chats:null===(n=s.chats)||void 0===n?void 0:n.map(s=>s.id===e?{...s,messages:t}:s)}})},ek=(e,t)=>{eg(s=>{var n;return{chats:null===(n=s.chats)||void 0===n?void 0:n.map(s=>s.id===e?{...s,...t}:s)}})};var eC=s(83390),ez=s(16630);let eR=!0,eE=(e,t)=>{let s=function(){let[e,t]=l.useState(()=>!eR);return l.useEffect(function(){eR=!1,t(!0)},[]),e}(),n=e(e=>null==e?void 0:e._hasHydrated),a=e(t),[r,i]=l.useState(s&&n?a:void 0);return l.useEffect(()=>{i(a)},[a]),r},eS=()=>(0,n.jsxs)("ul",{className:"space-y-3",children:[(0,n.jsx)("li",{className:"h-4 w-full rounded-full bg-gray-200 dark:bg-gray-700"}),(0,n.jsx)("li",{className:"h-4 w-full rounded-full bg-gray-200 dark:bg-gray-700"}),(0,n.jsx)("li",{className:"h-4 w-full rounded-full bg-gray-200 dark:bg-gray-700"}),(0,n.jsx)("li",{className:"h-4 w-full rounded-full bg-gray-200 dark:bg-gray-700"})]});function eD(e){let{id:t,initialMessages:s,loading:i,className:o}=e;(0,l.useEffect)(()=>{let e=window.fetch;window.fetch=async function(t,s){var n;if("/api/chat"!==t)return e(t,s);let{messages:l}=JSON.parse(s.body),a=await e("".concat(em,"/v1beta/chat/completions"),{...s,method:"POST",headers:{"Content-Type":"application/json"}}),r=(n=void 0,(function(e){var t;let s=null===(t=e.body)||void 0===t?void 0:t.getReader();return new ReadableStream({async start(e){if(!s){e.close();return}await ec(s,e)}})})(a).pipeThrough((0,ei.T_)(n)).pipeThrough((0,ei.h6)(null==n?void 0:n.experimental_streamData)));return new ei.wn(r)}},[]);let d=eE(ev,e=>e.chats),{messages:c,append:u,reload:m,stop:f,isLoading:x,input:h,setInput:p,setMessages:v}=(0,a.R)({initialMessages:s,id:t,body:{id:t},onResponse(e){401===e.status&&er.toast.error(e.statusText)}}),[g,j]=l.useState(),b=e=>{let t=(0,ez.Z)(c,{id:e}),s=null==c?void 0:c[t-1];(null==s?void 0:s.role)==="user"&&(v(c.slice(0,t-1)),u(s))},y=e=>{let t=(0,eC.Z)(c,{id:e});t&&v(c.filter(t=>t.id!==e))},N=e=>{let t=(0,eC.Z)(c,{id:e});t&&(p(t.content),j(e))},w=async e=>{if(-1===(0,ez.Z)(d,{id:t}))eb(t,(0,r.aF)(e));else if(g){let e=(0,ez.Z)(c,{id:g});v(c.slice(0,e)),j(void 0)}await u({id:(0,r.x0)(),content:e,role:"user"})};return l.useEffect(()=>{t&&ew(t,c)},[c]),l.useEffect(()=>{let e=document.documentElement.scrollHeight;return window.scrollTo(0,e),()=>f()},[]),(0,n.jsx)("div",{className:"flex justify-center overflow-x-hidden",children:(0,n.jsxs)("div",{className:"w-full max-w-2xl px-4",children:[(0,n.jsx)("div",{className:(0,r.cn)("pb-[200px] pt-4 md:pt-10",o),children:i?(0,n.jsxs)("div",{className:"group relative mb-4 flex animate-pulse items-start md:-ml-12",children:[(0,n.jsx)("div",{className:"shrink-0",children:(0,n.jsx)("span",{className:"block h-8 w-8 rounded-md bg-gray-200 dark:bg-gray-700"})}),(0,n.jsx)("div",{className:"ml-4 flex-1 space-y-2 overflow-hidden px-1",children:(0,n.jsx)(eS,{})})]}):c.length?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(z,{messages:c,handleMessageAction:(e,t)=>{switch(t){case"edit":N(e);break;case"delete":y(e);break;case"regenerate":b(e)}}}),(0,n.jsx)(ea,{trackVisibility:x})]}):(0,n.jsx)(en,{setInput:p})}),(0,n.jsx)(et,{onSubmit:w,className:"fixed inset-x-0 bottom-0 lg:ml-[280px]",id:t,isLoading:x,stop:f,append:u,reload:m,messages:c,input:h,setInput:p})]})})}let e_=(e,t)=>{if(Array.isArray(e)&&t)return e.find(e=>e.id===t)};var eI=s(12609);let eH=l.forwardRef((e,t)=>{let{className:s,type:l,...a}=e;return(0,n.jsx)("input",{type:l,className:(0,r.cn)("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",s),ref:t,...a})});eH.displayName="Input";let eT=e=>{let{children:t,initialValue:s,chatId:a}=e,[r,i]=l.useState(!1),o=l.useRef(null),[d,c]=l.useState(s),u=async e=>{e.preventDefault(),(null==d?void 0:d.trim())&&(ek(a,{title:d}),i(!1))};return(0,n.jsxs)(eI.Vq,{open:r,onOpenChange:i,children:[(0,n.jsxs)(E.u,{children:[(0,n.jsx)(E.aJ,{asChild:!0,children:(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:()=>i(!0),children:[(0,n.jsx)(f.yl,{}),(0,n.jsx)("span",{className:"sr-only",children:"Edit"})]})}),(0,n.jsx)(E._v,{side:"bottom",children:"Edit"})]}),(0,n.jsx)(eI.cZ,{className:"bg-background",children:(0,n.jsxs)(eI.fK,{className:"gap-3",children:[(0,n.jsx)(eI.$N,{children:"Set Chat Title"}),(0,n.jsx)(eI.Be,{asChild:!0,children:(0,n.jsxs)("form",{className:"relative",onSubmit:u,ref:o,children:[(0,n.jsx)(eH,{className:"h-10 pr-12",value:d,onChange:e=>c(e.target.value),onKeyDown:e=>{if("Enter"===e.key){var t;null===(t=o.current)||void 0===t||t.requestSubmit(),e.preventDefault()}}}),(0,n.jsx)("div",{className:"absolute right-2 top-1",children:(0,n.jsxs)(E.u,{children:[(0,n.jsx)(E.aJ,{asChild:!0,children:(0,n.jsxs)(x.z,{type:"submit",size:"icon",disabled:""===d,children:[(0,n.jsx)(f.vq,{}),(0,n.jsx)("span",{className:"sr-only",children:"Send message"})]})}),(0,n.jsx)(E._v,{children:"Edit Title"})]})})]})})]})})]})},eO=e=>{let{onClear:t,onClick:s,onBlur:a,...r}=e,[i,o]=l.useState(!1),d=()=>{o(!1)};return(0,n.jsx)(x.z,{className:"h-12 w-full justify-start",variant:"ghost",...r,onClick:e=>{i?(t(),o(!1)):o(!0),null==s||s(e)},onBlur:e=>{i&&d(),null==a||a(e)},children:i?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(f.NO,{}),(0,n.jsx)("span",{className:"ml-2",children:"Confirm Clear Chats"})]}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(f.IT,{}),(0,n.jsx)("span",{className:"ml-2",children:"Clear Chats"})]})})},eL=e=>{let{className:t}=e,s=eE(ev,e=>e._hasHydrated),l=eE(ev,e=>e.chats),a=eE(ev,e=>e.activeChatId),o=(e,t)=>{ey(t)};return(0,n.jsx)(n.Fragment,{children:(0,n.jsx)("div",{className:(0,r.cn)(t),children:(0,n.jsxs)("div",{className:"fixed inset-y-0 left-0 flex w-[279px] flex-col gap-2 overflow-hidden px-3 pt-16",children:[(0,n.jsx)("div",{className:"shrink-0 pb-0 pt-2",children:(0,n.jsxs)(x.z,{className:"h-12 w-full justify-start",variant:"ghost",onClick:e=>{ej((0,r.x0)())},children:[(0,n.jsx)(f.SC,{}),(0,n.jsx)("span",{className:"ml-2",children:"New Chat"})]})}),(0,n.jsx)(i.Z,{}),(0,n.jsx)("div",{className:"flex flex-1 flex-col gap-2 overflow-y-auto",children:s?(0,n.jsx)(n.Fragment,{children:null==l?void 0:l.map(e=>{let t=a===e.id;return(0,n.jsxs)("div",{onClick:t=>ej(e.id),className:(0,r.cn)("hover:bg-accent flex cursor-pointer items-center justify-between gap-3 rounded-lg px-3 py-2 text-zinc-900 transition-all hover:text-zinc-900 dark:text-zinc-50 hover:dark:bg-zinc-900 dark:hover:text-zinc-50",t&&"!bg-zinc-200 dark:!bg-zinc-800"),children:[(0,n.jsx)("span",{className:"truncate leading-8",children:e.title||"(Untitled)"}),t&&(0,n.jsxs)("div",{className:"flex items-center",onClick:e=>e.stopPropagation(),children:[(0,n.jsx)(eT,{initialValue:e.title,chatId:e.id}),(0,n.jsxs)(E.u,{children:[(0,n.jsx)(E.aJ,{asChild:!0,children:(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:t=>o(t,e.id),children:[(0,n.jsx)(f.IT,{}),(0,n.jsx)("span",{className:"sr-only",children:"Delete"})]})}),(0,n.jsx)(E._v,{side:"bottom",children:"Delete"})]})]})]},e.id)})}):(0,n.jsx)(eS,{})}),(0,n.jsx)(i.Z,{}),(0,n.jsx)("div",{className:"shrink-0 pb-2",children:(0,n.jsx)(eO,{disabled:(null==l?void 0:l.length)===0,onClear:()=>{eN()}})})]})})})},eZ=[];function eA(){var e;let t=eE(ev,e=>e._hasHydrated),s=eE(ev,e=>e.chats),l=eE(ev,e=>e.activeChatId),a=e_(s,l);return(0,n.jsxs)("div",{className:"grid flex-1 overflow-hidden lg:grid-cols-[280px_1fr]",children:[(0,n.jsx)(eL,{className:"hidden w-[280px] border-r bg-zinc-100/40 dark:bg-zinc-800/40 lg:block"}),(0,n.jsx)(eD,{loading:!t,id:l,initialMessages:null!==(e=null==a?void 0:a.messages)&&void 0!==e?e:eZ},l)]})}},33555:function(e,t,s){"use strict";s.d(t,{q:function(){return i}});var n=s(57437);s(2265);var l=s(93023),a=s(84168),r=s(77723);function i(e){let{className:t,value:s,...i}=e,{isCopied:o,copyToClipboard:d}=(0,r.m)({timeout:2e3});return s?(0,n.jsxs)(l.z,{variant:"ghost",size:"icon",className:t,onClick:()=>{o||d(s)},...i,children:[o?(0,n.jsx)(a.NO,{}):(0,n.jsx)(a.vU,{}),(0,n.jsx)("span",{className:"sr-only",children:"Copy"})]}):null}},12609:function(e,t,s){"use strict";s.d(t,{$N:function(){return x},Be:function(){return h},Vq:function(){return o},cN:function(){return f},cZ:function(){return u},fK:function(){return m}});var n=s(57437),l=s(2265),a=s(25555),r=s(39311),i=s(84168);let o=a.fC;a.xz;let d=e=>{let{className:t,children:s,...l}=e;return(0,n.jsx)(a.h_,{className:(0,r.cn)(t),...l,children:(0,n.jsx)("div",{className:"fixed inset-0 z-50 flex items-start justify-center sm:items-center",children:s})})};d.displayName=a.h_.displayName;let c=l.forwardRef((e,t)=>{let{className:s,...l}=e;return(0,n.jsx)(a.aV,{ref:t,className:(0,r.cn)("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",s),...l})});c.displayName=a.aV.displayName;let u=l.forwardRef((e,t)=>{let{className:s,children:l,...o}=e;return(0,n.jsxs)(d,{children:[(0,n.jsx)(c,{}),(0,n.jsxs)(a.VY,{ref:t,className:(0,r.cn)("fixed z-50 grid w-full gap-4 rounded-b-lg border bg-background p-6 shadow-sm animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",s),...o,children:[l,(0,n.jsxs)(a.x8,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[(0,n.jsx)(i.bM,{}),(0,n.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})});u.displayName=a.VY.displayName;let m=e=>{let{className:t,...s}=e;return(0,n.jsx)("div",{className:(0,r.cn)("flex flex-col space-y-1.5 text-center sm:text-left",t),...s})};m.displayName="DialogHeader";let f=e=>{let{className:t,...s}=e;return(0,n.jsx)("div",{className:(0,r.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...s})};f.displayName="DialogFooter";let x=l.forwardRef((e,t)=>{let{className:s,...l}=e;return(0,n.jsx)(a.Dx,{ref:t,className:(0,r.cn)("text-lg font-semibold leading-none tracking-tight",s),...l})});x.displayName=a.Dx.displayName;let h=l.forwardRef((e,t)=>{let{className:s,...l}=e;return(0,n.jsx)(a.dk,{ref:t,className:(0,r.cn)("text-sm text-muted-foreground",s),...l})});h.displayName=a.dk.displayName},16775:function(e,t,s){"use strict";s.d(t,{Z:function(){return i}});var n=s(57437),l=s(2265),a=s(26823),r=s(39311);let i=l.forwardRef((e,t)=>{let{className:s,orientation:l="horizontal",decorative:i=!0,...o}=e;return(0,n.jsx)(a.f,{ref:t,decorative:i,orientation:l,className:(0,r.cn)("shrink-0 bg-border","horizontal"===l?"h-[1px] w-full":"h-full w-[1px]",s),...o})});i.displayName=a.f.displayName},95482:function(e,t,s){"use strict";s.d(t,{_v:function(){return c},aJ:function(){return d},pn:function(){return i},u:function(){return o}});var n=s(57437),l=s(2265),a=s(75224),r=s(39311);let i=a.zt,o=a.fC,d=a.xz,c=l.forwardRef((e,t)=>{let{className:s,sideOffset:l=4,...i}=e;return(0,n.jsx)(a.VY,{ref:t,sideOffset:l,className:(0,r.cn)("z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-xs font-medium text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",s),...i})});c.displayName=a.VY.displayName},77723:function(e,t,s){"use strict";s.d(t,{m:function(){return l}});var n=s(2265);function l(e){let{timeout:t=2e3}=e,[s,l]=n.useState(!1);return{isCopied:s,copyToClipboard:e=>{var s;(null===(s=navigator.clipboard)||void 0===s?void 0:s.writeText)&&e&&navigator.clipboard.writeText(e).then(()=>{l(!0),setTimeout(()=>{l(!1)},t)})}}}}},function(e){e.O(0,[882,845,892,286,899,967,971,864,744],function(){return e(e.s=24283)}),_N_E=e.O()}]);
\ No newline at end of file
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[383],{40009:function(e,t,s){Promise.resolve().then(s.bind(s,34926))},34926:function(e,t,s){"use strict";s.r(t),s.d(t,{default:function(){return eA}});var n=s(57437),l=s(2265),a=s(82504),r=s(39311),i=s(16775),o=s(48975),d=s(82180),c=s(30513),u=s(4523),m=s(77723),f=s(84168),x=s(93023);let h={javascript:".js",python:".py",java:".java",c:".c",cpp:".cpp","c++":".cpp","c#":".cs",ruby:".rb",php:".php",swift:".swift","objective-c":".m",kotlin:".kt",typescript:".ts",go:".go",perl:".pl",rust:".rs",scala:".scala",haskell:".hs",lua:".lua",shell:".sh",sql:".sql",html:".html",css:".css"},p=function(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],s="ABCDEFGHJKLMNPQRSTUVWXY3456789",n="";for(let t=0;t{let{language:t,value:s}=e,{isCopied:l,copyToClipboard:a}=(0,m.m)({timeout:2e3});return(0,n.jsxs)("div",{className:"codeblock relative w-full bg-zinc-950 font-sans",children:[(0,n.jsxs)("div",{className:"flex w-full items-center justify-between bg-zinc-800 px-6 py-2 pr-4 text-zinc-100",children:[(0,n.jsx)("span",{className:"text-xs lowercase",children:t}),(0,n.jsxs)("div",{className:"flex items-center space-x-1",children:[(0,n.jsxs)(x.z,{variant:"ghost",className:"hover:bg-zinc-800 focus-visible:ring-1 focus-visible:ring-slate-700 focus-visible:ring-offset-0",onClick:()=>{let e=h[t]||".file",n="file-".concat(p(3,!0)).concat(e),l=window.prompt("Enter file name",n);if(!l)return;let a=new Blob([s],{type:"text/plain"}),r=URL.createObjectURL(a),i=document.createElement("a");i.download=l,i.href=r,i.style.display="none",document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r)},size:"icon",children:[(0,n.jsx)(f.Dj,{}),(0,n.jsx)("span",{className:"sr-only",children:"Download"})]}),(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",className:"text-xs hover:bg-zinc-800 focus-visible:ring-1 focus-visible:ring-slate-700 focus-visible:ring-offset-0",onClick:()=>{l||a(s)},children:[l?(0,n.jsx)(f.NO,{}):(0,n.jsx)(f.vU,{}),(0,n.jsx)("span",{className:"sr-only",children:"Copy code"})]})]})]}),(0,n.jsx)(c.Z,{language:t,style:u.RY,PreTag:"div",showLineNumbers:!0,customStyle:{margin:0,width:"100%",background:"transparent",padding:"1.5rem 1rem"},codeTagProps:{style:{fontSize:"0.9rem",fontFamily:"var(--font-mono)"}},children:s})]})});v.displayName="CodeBlock";var g=s(19349);let j=(0,l.memo)(g.D,(e,t)=>e.children===t.children&&e.className===t.className);var b=s(16691),y=s.n(b),N=s(33555);function w(e){let{message:t,className:s,handleMessageAction:l,...a}=e;return(0,n.jsxs)("div",{className:(0,r.cn)("flex items-center justify-end transition-opacity group-hover:opacity-100 md:absolute md:-right-[5rem] md:-top-2 md:opacity-0",s),...a,children:["user"===t.role?(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:e=>l(t.id,"edit"),children:[(0,n.jsx)(f.yl,{}),(0,n.jsx)("span",{className:"sr-only",children:"Edit message"})]}):(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:e=>l(t.id,"regenerate"),children:[(0,n.jsx)(f.tr,{}),(0,n.jsx)("span",{className:"sr-only",children:"Regenerate message"})]}),(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:e=>l(t.id,"delete"),children:[(0,n.jsx)(f.IT,{}),(0,n.jsx)("span",{className:"sr-only",children:"Delete message"})]}),(0,n.jsx)(N.q,{value:t.content})]})}function k(e){let{message:t,handleMessageAction:s,...l}=e;return(0,n.jsxs)("div",{className:(0,r.cn)("group relative mb-4 flex items-start md:-ml-12"),...l,children:[(0,n.jsx)("div",{className:(0,r.cn)("flex h-8 w-8 shrink-0 select-none items-center justify-center rounded-md border shadow","user"===t.role?"bg-background":"bg-primary text-primary-foreground"),children:"user"===t.role?(0,n.jsx)(f.f7,{}):(0,n.jsx)(C,{})}),(0,n.jsxs)("div",{className:"ml-4 flex-1 space-y-2 overflow-hidden px-1",children:[(0,n.jsx)(j,{className:"prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0",remarkPlugins:[o.Z,d.Z],components:{p(e){let{children:t}=e;return(0,n.jsx)("p",{className:"mb-2 last:mb-0",children:t})},code(e){let{node:t,inline:s,className:l,children:a,...r}=e;if(a.length){if("▍"==a[0])return(0,n.jsx)("span",{className:"mt-1 animate-pulse cursor-default",children:"▍"});a[0]=a[0].replace("`▍`","▍")}let i=/language-(\w+)/.exec(l||"");return s?(0,n.jsx)("code",{className:l,...r,children:a}):(0,n.jsx)(v,{language:i&&i[1]||"",value:String(a).replace(/\n$/,""),...r},Math.random())}},children:t.content}),(0,n.jsx)(w,{message:t,handleMessageAction:s})]})]})}function C(){return(0,n.jsx)(y(),{style:{borderRadius:4},src:"https://avatars.githubusercontent.com/u/125617854?s=128&v=4",alt:"tabby",width:"128",height:"128"})}function z(e){let{messages:t,handleMessageAction:s}=e;return t.length?(0,n.jsx)("div",{className:"relative mx-auto max-w-2xl px-4",children:t.map((e,l)=>(0,n.jsxs)("div",{children:[(0,n.jsx)(k,{message:e,handleMessageAction:s}),l{let{className:s,sideOffset:l=4,...a}=e;return(0,n.jsx)(S.VY,{ref:t,sideOffset:l,className:(0,r.cn)("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",s),...a})});T.displayName=S.VY.displayName;var O=s(92402),L=s(45470),Z=s(24144),A=s(62700);let M=l.createContext({}),V=l.forwardRef((e,t)=>(0,n.jsx)(H,{...e,ref:t}));V.displayName="ComboboxAnchor";let F=l.forwardRef((e,t)=>{let{getInputProps:s,open:a}=l.useContext(M),{onKeyDown:r,onChange:i,onInput:o,onBlur:d,onClick:c,...u}=e;return(0,n.jsx)(L.Z,{...s((0,A.Z)({onKeyDown:e=>{"Enter"===e.key&&a?e.preventDefault():null==r||r(e)},onChange:i,onInput:o,onBlur:d,onClick:c,ref:t},Z.Z)),...u})});F.displayName="ComboboxTextarea";let q=l.forwardRef((e,t)=>{let{children:s,style:a,popupMatchAnchorWidth:r,...i}=e,{getMenuProps:o,anchorRef:d}=l.useContext(M),c=l.useRef(void 0);return l.useLayoutEffect(()=>{if(r){let e=d.current;if(e){let t=e.getBoundingClientRect();c.current=t.width}}},[]),(0,n.jsx)(I,{children:(0,n.jsx)(T,{align:"start",onOpenAutoFocus:e=>e.preventDefault(),style:{width:c.current,...a},...o({ref:t},{suppressRefError:!0}),...i,children:s})})});q.displayName="ComboboxContent";let B=l.forwardRef((e,t)=>{let{item:s,index:a,className:i,children:o,disabled:d,...c}=e,{highlightedIndex:u,selectedItem:m,getItemProps:f}=l.useContext(M),x=u===a,h=m===s;return(0,n.jsx)(_,{asChild:!0,children:(0,n.jsx)("div",{className:(0,r.cn)("relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",x&&"text-accent-foreground bg-accent",h&&"font-bold",d&&"pointer-events-none opacity-50",i),...f({item:s,index:a,onMouseLeave:e=>e.preventDefault(),onMouseOut:e=>e.preventDefault()}),...c,children:"function"==typeof o?o({highlighted:x,selected:h}):o})},s.id)});function P(e){let{options:t,onSelect:s,inputRef:a,children:r}=e,[i,o]=l.useState(!1),d=l.useRef(null),c=null!=a?a:d,u=l.useRef(null),m=l.useCallback((e,t)=>{let{type:s,changes:n}=t;return s===O.Kb.stateChangeTypes.MenuMouseLeave?{...n,highlightedIndex:e.highlightedIndex}:n},[]),f=(0,O.Kb)({items:null!=t?t:[],isOpen:i,onSelectedItemChange(e){let{selectedItem:t}=e;t&&(null==s||s(t),o(!1))},onIsOpenChange:e=>{let{isOpen:t}=e;t||o(!1)},stateReducer:m}),{setHighlightedIndex:x,highlightedIndex:h}=f,p=i&&!!(null==t?void 0:t.length);l.useEffect(()=>{p&&t.length&&-1===h&&x(0),p&&!t.length&&o(!1)},[p,t]),l.useEffect(()=>{(null==t?void 0:t.length)?o(!0):o(!1)},[t]);let v=l.useMemo(()=>({...f,open:p,inputRef:c,anchorRef:u}),[f,p,c,u]);return(0,n.jsx)(M.Provider,{value:v,children:(0,n.jsx)(D,{open:p,children:"function"==typeof r?r(v):r})})}B.displayName="ComboboxOption";var U=s(97605),Y=s(50976),K=s(91067);let J=l.forwardRef(function(e,t){let{onSubmit:s,input:a,setInput:i,isLoading:o}=e,{formRef:d,onKeyDown:c}=function(){let e=(0,l.useRef)(null);return{formRef:e,onKeyDown:t=>{if("Enter"===t.key&&!t.shiftKey&&!t.nativeEvent.isComposing){var s;null===(s=e.current)||void 0===s||s.requestSubmit(),t.preventDefault()}}}}(),[u,m]=l.useState(null),h=l.useRef(""),p=l.useRef(null),v=l.useRef(),g=l.useRef(),[j,b]=l.useState([]),[y,N]=l.useState({});(0,R.ZP)(u,U.Z,{revalidateOnFocus:!1,dedupingInterval:0,onSuccess:(e,t)=>{var s;t===h.current&&b(null!==(s=null==e?void 0:e.hits)&&void 0!==s?s:[])}}),l.useImperativeHandle(t,()=>({focus:()=>{var e;null===(e=p.current)||void 0===e||e.focus()}})),l.useEffect(()=>{a&&p.current&&p.current!==document.activeElement&&p.current.focus()},[a]),l.useLayoutEffect(()=>{var e,t,s;(null===(e=g.current)||void 0===e?void 0:e.length)&&(null===(s=p.current)||void 0===s||null===(t=s.setSelectionRange)||void 0===t||t.call(s,g.current[0],g.current[1]),g.current=void 0)});let w=l.useMemo(()=>(0,Y.Z)(e=>{var t,s,n,l;let a=null!==(n=null===(t=e.target)||void 0===t?void 0:t.value)&&void 0!==n?n:"",r=null!==(l=null===(s=e.target)||void 0===s?void 0:s.selectionEnd)&&void 0!==l?l:0,i=$(a,r),o=null==i?void 0:i[1];if(o){let e=encodeURIComponent("name:".concat(o," kind:function")),t="/v1beta/search?q=".concat(e);h.current=t,m(t)}else b([])},200),[]),k=async e=>{if(e.preventDefault(),!(null==a?void 0:a.trim()))return;let t=a;Object.keys(y).forEach(e=>{var s,n,l;let a=y[e];(null==a?void 0:a.doc)&&(t=t.replaceAll(e,"\n```".concat(null!==(n=null===(s=a.doc)||void 0===s?void 0:s.language)&&void 0!==n?n:"","\n").concat(null!==(l=a.doc.body)&&void 0!==l?l:"","\n","```","\n")))}),i(""),await s(t)},C=(e,t)=>{t&&["ArrowRight","ArrowLeft","Home","End"].includes(e.key)?b([]):c(e)};return(0,n.jsx)("form",{onSubmit:k,ref:d,children:(0,n.jsx)(P,{inputRef:p,options:j,onSelect:e=>{var t,s,n;let l=null!==(t=v.current)&&void 0!==t?t:0,r=$(a,l);if(r){N({...y,["@".concat(null===(s=e.doc)||void 0===s?void 0:s.name)]:e});let t="@".concat(null==e?void 0:null===(n=e.doc)||void 0===n?void 0:n.name," "),o=a.substring(0,l).replace(new RegExp(r[0]),""),d=o.length+t.length;g.current=[d,d],i(o+t+a.slice(l))}b([])},children:e=>{var t,s,l,d;let{open:c,highlightedIndex:u}=e,m=null==j?void 0:j[u];return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(V,{children:(0,n.jsxs)("div",{className:"bg-background relative flex max-h-60 w-full grow flex-col overflow-hidden px-8 sm:rounded-md sm:border sm:px-12",children:[(0,n.jsx)("span",{className:(0,r.cn)((0,x.d)({size:"sm",variant:"ghost"}),"bg-background hover:bg-background absolute left-0 top-4 h-8 w-8 rounded-full p-0 sm:left-4"),children:(0,n.jsx)(f.yl,{})}),(0,n.jsx)(F,{tabIndex:0,rows:1,placeholder:"Ask a question.",spellCheck:!1,className:"min-h-[60px] w-full resize-none bg-transparent px-4 py-[1.3rem] focus-within:outline-none sm:text-sm",value:a,ref:p,onChange:e=>{(0,K.Z)(e,"target.value")?(v.current=e.target.selectionEnd,i(e.target.value),w(e)):v.current=void 0},onKeyDown:e=>C(e,c)}),(0,n.jsx)("div",{className:"absolute right-0 top-4 sm:right-4",children:(0,n.jsxs)(E.u,{children:[(0,n.jsx)(E.aJ,{asChild:!0,children:(0,n.jsxs)(x.z,{type:"submit",size:"icon",disabled:o||""===a,children:[(0,n.jsx)(f.vq,{}),(0,n.jsx)("span",{className:"sr-only",children:"Send message"})]})}),(0,n.jsx)(E._v,{children:"Send message"})]})})]})}),(0,n.jsx)(q,{align:"start",side:"top",onOpenAutoFocus:e=>e.preventDefault(),className:"w-[60vw] md:w-[430px]",children:(0,n.jsxs)(D,{open:c&&!!m,children:[(0,n.jsx)(H,{asChild:!0,children:(0,n.jsx)("div",{className:"max-h-[300px] overflow-y-scroll",children:c&&!!(null==j?void 0:j.length)&&j.map((e,t)=>{var s,l,a;return(0,n.jsx)(B,{item:e,index:t,children:(0,n.jsxs)("div",{className:"flex w-full items-center justify-between gap-8 overflow-x-hidden",children:[(0,n.jsxs)("div",{className:"flex items-center gap-1",children:[(0,n.jsx)(W,{kind:null==e?void 0:null===(s=e.doc)||void 0===s?void 0:s.kind}),(0,n.jsxs)("div",{className:"max-w-[200px] truncate",children:[null==e?void 0:null===(l=e.doc)||void 0===l?void 0:l.name,"(...)"]})]}),(0,n.jsx)("div",{className:"text-muted-foreground flex-1 truncate text-right text-sm",children:null==e?void 0:null===(a=e.doc)||void 0===a?void 0:a.body})]})},null==e?void 0:e.id)})})}),(0,n.jsx)(T,{asChild:!0,align:"start",side:"right",alignOffset:-4,onOpenAutoFocus:e=>e.preventDefault(),onKeyDownCapture:e=>e.preventDefault(),className:"rounded-none",collisionPadding:{bottom:120},children:(0,n.jsxs)("div",{className:"flex max-h-[70vh] w-[20vw] flex-col overflow-y-auto px-2 md:w-[240px] lg:w-[340px]",children:[(0,n.jsxs)("div",{className:"mb-2",children:[(null==m?void 0:null===(t=m.doc)||void 0===t?void 0:t.kind)?"(".concat(null==m?void 0:null===(s=m.doc)||void 0===s?void 0:s.kind,") "):"",null==m?void 0:null===(l=m.doc)||void 0===l?void 0:l.name]}),(0,n.jsx)("div",{className:"text-muted-foreground flex-1 whitespace-pre-wrap break-all",children:null==m?void 0:null===(d=m.doc)||void 0===d?void 0:d.body})]})})]})})]})}})})});function $(e,t){let s=e.substring(0,t),n=/@(\w+)$/.exec(s);return n}function W(e){let{kind:t,...s}=e;return(0,n.jsx)(f.sW,{...s})}function X(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,[t,s]=l.useState(!1);return l.useEffect(()=>{let t=()=>{s(window.innerHeight+window.scrollY>=document.body.offsetHeight-e)};return window.addEventListener("scroll",t,{passive:!0}),t(),()=>{window.removeEventListener("scroll",t)}},[e]),t}function G(e){let{className:t,...s}=e,l=X();return(0,n.jsxs)(x.z,{variant:"outline",size:"icon",className:(0,r.cn)("absolute right-4 top-1 z-10 bg-background transition-opacity duration-300 sm:right-8 md:top-2",l?"opacity-0":"opacity-100",t),onClick:()=>window.scrollTo({top:document.body.offsetHeight,behavior:"smooth"}),...s,children:[(0,n.jsx)(f.BD,{}),(0,n.jsx)("span",{className:"sr-only",children:"Scroll to bottom"})]})}function Q(e){let{href:t,children:s}=e;return(0,n.jsxs)("a",{href:t,target:"_blank",className:"inline-flex flex-1 justify-center gap-1 leading-4 hover:underline",children:[(0,n.jsx)("span",{children:s}),(0,n.jsx)("svg",{"aria-hidden":"true",height:"7",viewBox:"0 0 6 6",width:"7",className:"opacity-70",children:(0,n.jsx)("path",{d:"M1.25215 5.54731L0.622742 4.9179L3.78169 1.75597H1.3834L1.38936 0.890915H5.27615V4.78069H4.40513L4.41109 2.38538L1.25215 5.54731Z",fill:"currentColor"})})]})}function ee(e){let{className:t,...s}=e;return(0,n.jsxs)("p",{className:(0,r.cn)("px-2 text-center text-xs leading-normal text-muted-foreground",t),...s,children:[(0,n.jsx)(Q,{href:"https://tabby.tabbyml.com",children:"Tabby"}),", an opensource, self-hosted AI coding assistant ."]})}function et(e){let{id:t,isLoading:s,stop:a,append:i,reload:o,input:d,setInput:c,messages:u,className:m,onSubmit:h}=e,p=l.useRef(null);return l.useEffect(()=>{var e;null==p||null===(e=p.current)||void 0===e||e.focus()},[t]),(0,n.jsxs)("div",{className:(0,r.cn)("from-muted/10 to-muted/30 bg-gradient-to-b from-10% to-50%",m),children:[(0,n.jsx)(G,{}),(0,n.jsxs)("div",{className:"mx-auto sm:max-w-2xl sm:px-4",children:[(0,n.jsx)("div",{className:"flex h-10 items-center justify-center",children:s?(0,n.jsxs)(x.z,{variant:"outline",onClick:()=>a(),className:"bg-background",children:[(0,n.jsx)(f.zu,{className:"mr-2"}),"Stop generating"]}):(null==u?void 0:u.length)>0&&(0,n.jsxs)(x.z,{variant:"outline",onClick:()=>o(),className:"bg-background",children:[(0,n.jsx)(f.tr,{className:"mr-2"}),"Regenerate response"]})}),(0,n.jsxs)("div",{className:"bg-background space-y-4 border-t px-4 py-2 shadow-lg sm:rounded-t-xl sm:border md:py-4",children:[(0,n.jsx)(J,{ref:p,onSubmit:h,input:d,setInput:c,isLoading:s}),(0,n.jsx)(ee,{className:"hidden sm:block"})]})]})]})}let es=[{heading:"Convert list of string to numbers",message:"How to convert a list of string to numbers in python"},{heading:"How to parse email address",message:"How to parse email address with regex"}];function en(e){let{setInput:t}=e;return(0,n.jsx)("div",{className:"mx-auto max-w-2xl px-4",children:(0,n.jsxs)("div",{className:"rounded-lg border bg-background p-8",children:[(0,n.jsx)("h1",{className:"mb-2 text-lg font-semibold",children:"Welcome to Playground!"}),(0,n.jsx)("p",{className:"leading-normal text-muted-foreground",children:"You can start a conversation here or try the following examples:"}),(0,n.jsx)("div",{className:"mt-4 flex flex-col items-start space-y-2",children:es.map((e,s)=>(0,n.jsxs)(x.z,{variant:"link",className:"h-auto p-0 text-base",onClick:()=>t(e.message),children:[(0,n.jsx)(f.Ec,{className:"mr-2 text-muted-foreground"}),e.heading]},s))})]})})}var el=s(4327);function ea(e){let{trackVisibility:t}=e,s=X(),{ref:a,entry:r,inView:i}=(0,el.YD)({trackVisibility:t,delay:100,rootMargin:"0px 0px -150px 0px"});return l.useEffect(()=>{s&&t&&!i&&(null==r||r.target.scrollIntoView({block:"start"}))},[i,r,s,t]),(0,n.jsx)("div",{ref:a,className:"h-px w-full"})}var er=s(5925),ei=s(4913);let eo=new TextDecoder("utf-8");async function ed(e,t){for(let s of e){let{content:e}=JSON.parse(s);t.enqueue(e)}}async function ec(e,t){let s="";for(;;){let{value:n,done:l}=await e.read();if(l)break;s+=eo.decode(n,{stream:!0});let a=s.split(/\r\n|\n|\r/g);s=a.pop()||"",await ed(a,t)}if(s){let e=[s];await ed(e,t)}t.close()}var eu=s(62601);let em=eu.env.NEXT_PUBLIC_TABBY_SERVER_URL||"";var ef=s(94660),ex=s(74810);let eh=["_hasHydrated","setHasHydrated"],ep={_hasHydrated:!1,chats:void 0,activeChatId:(0,r.x0)()},ev=(0,ef.Ue)()((0,ex.tJ)(e=>({...ep,setHasHydrated:t=>{e({_hasHydrated:t})}}),{name:"tabby-chat-storage",partialize:e=>Object.fromEntries(Object.entries(e).filter(e=>{let[t]=e;return!eh.includes(t)})),onRehydrateStorage:()=>e=>{e&&e.setHasHydrated(!0)}}));ev.getState;let eg=ev.setState,ej=e=>{eg(()=>({activeChatId:e}))},eb=(e,t)=>{let s=null!=e?e:(0,r.x0)();eg(e=>({activeChatId:s,chats:[{id:s,title:null!=t?t:"",messages:[],createdAt:new Date,userId:"",path:""},...e.chats||[]]}))},ey=e=>{eg(t=>{var s;return{activeChatId:(0,r.x0)(),chats:null===(s=t.chats)||void 0===s?void 0:s.filter(t=>t.id!==e)}})},eN=()=>{eg(()=>({activeChatId:(0,r.x0)(),chats:[]}))},ew=(e,t)=>{eg(s=>{var n;return{chats:null===(n=s.chats)||void 0===n?void 0:n.map(s=>s.id===e?{...s,messages:t}:s)}})},ek=(e,t)=>{eg(s=>{var n;return{chats:null===(n=s.chats)||void 0===n?void 0:n.map(s=>s.id===e?{...s,...t}:s)}})};var eC=s(83390),ez=s(16630);let eR=!0,eE=(e,t)=>{let s=function(){let[e,t]=l.useState(()=>!eR);return l.useEffect(function(){eR=!1,t(!0)},[]),e}(),n=e(e=>null==e?void 0:e._hasHydrated),a=e(t),[r,i]=l.useState(s&&n?a:void 0);return l.useEffect(()=>{i(a)},[a]),r},eS=()=>(0,n.jsxs)("ul",{className:"space-y-3",children:[(0,n.jsx)("li",{className:"h-4 w-full rounded-full bg-gray-200 dark:bg-gray-700"}),(0,n.jsx)("li",{className:"h-4 w-full rounded-full bg-gray-200 dark:bg-gray-700"}),(0,n.jsx)("li",{className:"h-4 w-full rounded-full bg-gray-200 dark:bg-gray-700"}),(0,n.jsx)("li",{className:"h-4 w-full rounded-full bg-gray-200 dark:bg-gray-700"})]});function eD(e){let{id:t,initialMessages:s,loading:i,className:o}=e;(0,l.useEffect)(()=>{let e=window.fetch;window.fetch=async function(t,s){var n;if("/api/chat"!==t)return e(t,s);let{messages:l}=JSON.parse(s.body),a=await e("".concat(em,"/v1beta/chat/completions"),{...s,method:"POST",headers:{"Content-Type":"application/json"}}),r=(n=void 0,(function(e){var t;let s=null===(t=e.body)||void 0===t?void 0:t.getReader();return new ReadableStream({async start(e){if(!s){e.close();return}await ec(s,e)}})})(a).pipeThrough((0,ei.T_)(n)).pipeThrough((0,ei.h6)(null==n?void 0:n.experimental_streamData)));return new ei.wn(r)}},[]);let d=eE(ev,e=>e.chats),{messages:c,append:u,reload:m,stop:f,isLoading:x,input:h,setInput:p,setMessages:v}=(0,a.R)({initialMessages:s,id:t,body:{id:t},onResponse(e){401===e.status&&er.toast.error(e.statusText)}}),[g,j]=l.useState(),b=e=>{let t=(0,ez.Z)(c,{id:e}),s=null==c?void 0:c[t-1];(null==s?void 0:s.role)==="user"&&(v(c.slice(0,t-1)),u(s))},y=e=>{let t=(0,eC.Z)(c,{id:e});t&&v(c.filter(t=>t.id!==e))},N=e=>{let t=(0,eC.Z)(c,{id:e});t&&(p(t.content),j(e))},w=async e=>{if(-1===(0,ez.Z)(d,{id:t}))eb(t,(0,r.aF)(e));else if(g){let e=(0,ez.Z)(c,{id:g});v(c.slice(0,e)),j(void 0)}await u({id:(0,r.x0)(),content:e,role:"user"})};return l.useEffect(()=>{t&&ew(t,c)},[c]),l.useEffect(()=>{let e=document.documentElement.scrollHeight;return window.scrollTo(0,e),()=>f()},[]),(0,n.jsx)("div",{className:"flex justify-center overflow-x-hidden",children:(0,n.jsxs)("div",{className:"w-full max-w-2xl px-4",children:[(0,n.jsx)("div",{className:(0,r.cn)("pb-[200px] pt-4 md:pt-10",o),children:i?(0,n.jsxs)("div",{className:"group relative mb-4 flex animate-pulse items-start md:-ml-12",children:[(0,n.jsx)("div",{className:"shrink-0",children:(0,n.jsx)("span",{className:"block h-8 w-8 rounded-md bg-gray-200 dark:bg-gray-700"})}),(0,n.jsx)("div",{className:"ml-4 flex-1 space-y-2 overflow-hidden px-1",children:(0,n.jsx)(eS,{})})]}):c.length?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(z,{messages:c,handleMessageAction:(e,t)=>{switch(t){case"edit":N(e);break;case"delete":y(e);break;case"regenerate":b(e)}}}),(0,n.jsx)(ea,{trackVisibility:x})]}):(0,n.jsx)(en,{setInput:p})}),(0,n.jsx)(et,{onSubmit:w,className:"fixed inset-x-0 bottom-0 lg:ml-[280px]",id:t,isLoading:x,stop:f,append:u,reload:m,messages:c,input:h,setInput:p})]})})}let e_=(e,t)=>{if(Array.isArray(e)&&t)return e.find(e=>e.id===t)};var eI=s(12609);let eH=l.forwardRef((e,t)=>{let{className:s,type:l,...a}=e;return(0,n.jsx)("input",{type:l,className:(0,r.cn)("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",s),ref:t,...a})});eH.displayName="Input";let eT=e=>{let{children:t,initialValue:s,chatId:a}=e,[r,i]=l.useState(!1),o=l.useRef(null),[d,c]=l.useState(s),u=async e=>{e.preventDefault(),(null==d?void 0:d.trim())&&(ek(a,{title:d}),i(!1))};return(0,n.jsxs)(eI.Vq,{open:r,onOpenChange:i,children:[(0,n.jsxs)(E.u,{children:[(0,n.jsx)(E.aJ,{asChild:!0,children:(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:()=>i(!0),children:[(0,n.jsx)(f.yl,{}),(0,n.jsx)("span",{className:"sr-only",children:"Edit"})]})}),(0,n.jsx)(E._v,{side:"bottom",children:"Edit"})]}),(0,n.jsx)(eI.cZ,{className:"bg-background",children:(0,n.jsxs)(eI.fK,{className:"gap-3",children:[(0,n.jsx)(eI.$N,{children:"Set Chat Title"}),(0,n.jsx)(eI.Be,{asChild:!0,children:(0,n.jsxs)("form",{className:"relative",onSubmit:u,ref:o,children:[(0,n.jsx)(eH,{className:"h-10 pr-12",value:d,onChange:e=>c(e.target.value),onKeyDown:e=>{if("Enter"===e.key){var t;null===(t=o.current)||void 0===t||t.requestSubmit(),e.preventDefault()}}}),(0,n.jsx)("div",{className:"absolute right-2 top-1",children:(0,n.jsxs)(E.u,{children:[(0,n.jsx)(E.aJ,{asChild:!0,children:(0,n.jsxs)(x.z,{type:"submit",size:"icon",disabled:""===d,children:[(0,n.jsx)(f.vq,{}),(0,n.jsx)("span",{className:"sr-only",children:"Send message"})]})}),(0,n.jsx)(E._v,{children:"Edit Title"})]})})]})})]})})]})},eO=e=>{let{onClear:t,onClick:s,onBlur:a,...r}=e,[i,o]=l.useState(!1),d=()=>{o(!1)};return(0,n.jsx)(x.z,{className:"h-12 w-full justify-start",variant:"ghost",...r,onClick:e=>{i?(t(),o(!1)):o(!0),null==s||s(e)},onBlur:e=>{i&&d(),null==a||a(e)},children:i?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(f.NO,{}),(0,n.jsx)("span",{className:"ml-2",children:"Confirm Clear Chats"})]}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(f.IT,{}),(0,n.jsx)("span",{className:"ml-2",children:"Clear Chats"})]})})},eL=e=>{let{className:t}=e,s=eE(ev,e=>e._hasHydrated),l=eE(ev,e=>e.chats),a=eE(ev,e=>e.activeChatId),o=(e,t)=>{ey(t)};return(0,n.jsx)(n.Fragment,{children:(0,n.jsx)("div",{className:(0,r.cn)(t),children:(0,n.jsxs)("div",{className:"fixed inset-y-0 left-0 flex w-[279px] flex-col gap-2 overflow-hidden px-3 pt-16",children:[(0,n.jsx)("div",{className:"shrink-0 pb-0 pt-2",children:(0,n.jsxs)(x.z,{className:"h-12 w-full justify-start",variant:"ghost",onClick:e=>{ej((0,r.x0)())},children:[(0,n.jsx)(f.SC,{}),(0,n.jsx)("span",{className:"ml-2",children:"New Chat"})]})}),(0,n.jsx)(i.Z,{}),(0,n.jsx)("div",{className:"flex flex-1 flex-col gap-2 overflow-y-auto",children:s?(0,n.jsx)(n.Fragment,{children:null==l?void 0:l.map(e=>{let t=a===e.id;return(0,n.jsxs)("div",{onClick:t=>ej(e.id),className:(0,r.cn)("hover:bg-accent flex cursor-pointer items-center justify-between gap-3 rounded-lg px-3 py-2 text-zinc-900 transition-all hover:text-zinc-900 dark:text-zinc-50 hover:dark:bg-zinc-900 dark:hover:text-zinc-50",t&&"!bg-zinc-200 dark:!bg-zinc-800"),children:[(0,n.jsx)("span",{className:"truncate leading-8",children:e.title||"(Untitled)"}),t&&(0,n.jsxs)("div",{className:"flex items-center",onClick:e=>e.stopPropagation(),children:[(0,n.jsx)(eT,{initialValue:e.title,chatId:e.id}),(0,n.jsxs)(E.u,{children:[(0,n.jsx)(E.aJ,{asChild:!0,children:(0,n.jsxs)(x.z,{variant:"ghost",size:"icon",onClick:t=>o(t,e.id),children:[(0,n.jsx)(f.IT,{}),(0,n.jsx)("span",{className:"sr-only",children:"Delete"})]})}),(0,n.jsx)(E._v,{side:"bottom",children:"Delete"})]})]})]},e.id)})}):(0,n.jsx)(eS,{})}),(0,n.jsx)(i.Z,{}),(0,n.jsx)("div",{className:"shrink-0 pb-2",children:(0,n.jsx)(eO,{disabled:(null==l?void 0:l.length)===0,onClear:()=>{eN()}})})]})})})},eZ=[];function eA(){var e;let t=eE(ev,e=>e._hasHydrated),s=eE(ev,e=>e.chats),l=eE(ev,e=>e.activeChatId),a=e_(s,l);return(0,n.jsxs)("div",{className:"grid flex-1 overflow-hidden lg:grid-cols-[280px_1fr]",children:[(0,n.jsx)(eL,{className:"hidden w-[280px] border-r bg-zinc-100/40 dark:bg-zinc-800/40 lg:block"}),(0,n.jsx)(eD,{loading:!t,id:l,initialMessages:null!==(e=null==a?void 0:a.messages)&&void 0!==e?e:eZ},l)]})}},33555:function(e,t,s){"use strict";s.d(t,{q:function(){return i}});var n=s(57437);s(2265);var l=s(93023),a=s(84168),r=s(77723);function i(e){let{className:t,value:s,...i}=e,{isCopied:o,copyToClipboard:d}=(0,r.m)({timeout:2e3});return s?(0,n.jsxs)(l.z,{variant:"ghost",size:"icon",className:t,onClick:()=>{o||d(s)},...i,children:[o?(0,n.jsx)(a.NO,{}):(0,n.jsx)(a.vU,{}),(0,n.jsx)("span",{className:"sr-only",children:"Copy"})]}):null}},12609:function(e,t,s){"use strict";s.d(t,{$N:function(){return x},Be:function(){return h},Vq:function(){return o},cN:function(){return f},cZ:function(){return u},fK:function(){return m}});var n=s(57437),l=s(2265),a=s(25555),r=s(39311),i=s(84168);let o=a.fC;a.xz;let d=e=>{let{className:t,children:s,...l}=e;return(0,n.jsx)(a.h_,{className:(0,r.cn)(t),...l,children:(0,n.jsx)("div",{className:"fixed inset-0 z-50 flex items-start justify-center sm:items-center",children:s})})};d.displayName=a.h_.displayName;let c=l.forwardRef((e,t)=>{let{className:s,...l}=e;return(0,n.jsx)(a.aV,{ref:t,className:(0,r.cn)("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",s),...l})});c.displayName=a.aV.displayName;let u=l.forwardRef((e,t)=>{let{className:s,children:l,...o}=e;return(0,n.jsxs)(d,{children:[(0,n.jsx)(c,{}),(0,n.jsxs)(a.VY,{ref:t,className:(0,r.cn)("fixed z-50 grid w-full gap-4 rounded-b-lg border bg-background p-6 shadow-sm animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",s),...o,children:[l,(0,n.jsxs)(a.x8,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[(0,n.jsx)(i.bM,{}),(0,n.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})});u.displayName=a.VY.displayName;let m=e=>{let{className:t,...s}=e;return(0,n.jsx)("div",{className:(0,r.cn)("flex flex-col space-y-1.5 text-center sm:text-left",t),...s})};m.displayName="DialogHeader";let f=e=>{let{className:t,...s}=e;return(0,n.jsx)("div",{className:(0,r.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...s})};f.displayName="DialogFooter";let x=l.forwardRef((e,t)=>{let{className:s,...l}=e;return(0,n.jsx)(a.Dx,{ref:t,className:(0,r.cn)("text-lg font-semibold leading-none tracking-tight",s),...l})});x.displayName=a.Dx.displayName;let h=l.forwardRef((e,t)=>{let{className:s,...l}=e;return(0,n.jsx)(a.dk,{ref:t,className:(0,r.cn)("text-sm text-muted-foreground",s),...l})});h.displayName=a.dk.displayName},16775:function(e,t,s){"use strict";s.d(t,{Z:function(){return i}});var n=s(57437),l=s(2265),a=s(26823),r=s(39311);let i=l.forwardRef((e,t)=>{let{className:s,orientation:l="horizontal",decorative:i=!0,...o}=e;return(0,n.jsx)(a.f,{ref:t,decorative:i,orientation:l,className:(0,r.cn)("shrink-0 bg-border","horizontal"===l?"h-[1px] w-full":"h-full w-[1px]",s),...o})});i.displayName=a.f.displayName},95482:function(e,t,s){"use strict";s.d(t,{_v:function(){return c},aJ:function(){return d},pn:function(){return i},u:function(){return o}});var n=s(57437),l=s(2265),a=s(75224),r=s(39311);let i=a.zt,o=a.fC,d=a.xz,c=l.forwardRef((e,t)=>{let{className:s,sideOffset:l=4,...i}=e;return(0,n.jsx)(a.VY,{ref:t,sideOffset:l,className:(0,r.cn)("z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-xs font-medium text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",s),...i})});c.displayName=a.VY.displayName},77723:function(e,t,s){"use strict";s.d(t,{m:function(){return l}});var n=s(2265);function l(e){let{timeout:t=2e3}=e,[s,l]=n.useState(!1);return{isCopied:s,copyToClipboard:e=>{var s;(null===(s=navigator.clipboard)||void 0===s?void 0:s.writeText)&&e&&navigator.clipboard.writeText(e).then(()=>{l(!0),setTimeout(()=>{l(!1)},t)})}}}}},function(e){e.O(0,[882,845,892,286,899,967,971,864,744],function(){return e(e.s=40009)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/main-app-65c258ee101a6b57.js b/ee/tabby-webserver/ui/_next/static/chunks/main-app-564c82becf4880fe.js
similarity index 67%
rename from ee/tabby-webserver/ui/_next/static/chunks/main-app-65c258ee101a6b57.js
rename to ee/tabby-webserver/ui/_next/static/chunks/main-app-564c82becf4880fe.js
index 4c4ab468d9f..31607d0f44e 100644
--- a/ee/tabby-webserver/ui/_next/static/chunks/main-app-65c258ee101a6b57.js
+++ b/ee/tabby-webserver/ui/_next/static/chunks/main-app-564c82becf4880fe.js
@@ -1 +1 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{49989:function(e,n,t){Promise.resolve().then(t.t.bind(t,76054,23)),Promise.resolve().then(t.t.bind(t,41729,23)),Promise.resolve().then(t.t.bind(t,81443,23)),Promise.resolve().then(t.t.bind(t,36384,23)),Promise.resolve().then(t.t.bind(t,18639,23)),Promise.resolve().then(t.t.bind(t,65146,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[971,864],function(){return n(23123),n(49989)}),_N_E=e.O()}]);
\ No newline at end of file
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{11787:function(e,n,t){Promise.resolve().then(t.t.bind(t,76054,23)),Promise.resolve().then(t.t.bind(t,41729,23)),Promise.resolve().then(t.t.bind(t,81443,23)),Promise.resolve().then(t.t.bind(t,36384,23)),Promise.resolve().then(t.t.bind(t,18639,23)),Promise.resolve().then(t.t.bind(t,65146,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[971,864],function(){return n(23123),n(11787)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/index.html b/ee/tabby-webserver/ui/index.html
index 2482906dde3..fc0900acd76 100644
--- a/ee/tabby-webserver/ui/index.html
+++ b/ee/tabby-webserver/ui/index.html
@@ -1 +1 @@
-Tabby - Dashboard
\ No newline at end of file
+Tabby - Dashboard
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/index.txt b/ee/tabby-webserver/ui/index.txt
index d68940dd0b9..acbd8bdbdcd 100644
--- a/ee/tabby-webserver/ui/index.txt
+++ b/ee/tabby-webserver/ui/index.txt
@@ -1,15 +1,15 @@
1:HL["/_next/static/media/86fdec36ddd9097e-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
2:HL["/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
3:HL["/_next/static/css/6473d52ca6f0f35c.css","style"]
-0:["KwTUFhDElVXkDE3jiCtD0",[[["",{"children":["(dashboard)",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
-6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-ca2c7a9f923b6e61.js"],"name":"Toaster","async":false}
-7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-ca2c7a9f923b6e61.js"],"name":"Providers","async":false}
-8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-ca2c7a9f923b6e61.js"],"name":"Header","async":false}
+0:["-IQIiI3YS2Md2tsCaIleK",[[["",{"children":["(dashboard)",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
+6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Toaster","async":false}
+7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Providers","async":false}
+8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Header","async":false}
9:I{"id":81443,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
a:I{"id":18639,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
-b:I{"id":30831,"chunks":["882:static/chunks/882-5574357230a12cf9.js","396:static/chunks/396-89319c375c83667c.js","642:static/chunks/app/(dashboard)/layout-3f83ef2900ef6e5d.js"],"name":"","async":false}
+b:I{"id":30831,"chunks":["882:static/chunks/882-5574357230a12cf9.js","396:static/chunks/396-89319c375c83667c.js","642:static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js"],"name":"","async":false}
d:I{"id":65146,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
-e:I{"id":60901,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","286:static/chunks/286-453e01dda7220f79.js","967:static/chunks/967-f02728ac0b1b01a8.js","130:static/chunks/app/(dashboard)/page-2dac77bf7366362b.js"],"name":"","async":false}
+e:I{"id":60901,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","286:static/chunks/286-453e01dda7220f79.js","967:static/chunks/967-f02728ac0b1b01a8.js","130:static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js"],"name":"","async":false}
5:[["$","meta","0",{"charSet":"utf-8"}],["$","title","1",{"children":"Tabby - Dashboard"}],["$","meta","2",{"name":"description","content":"Tabby, an opensource, self-hosted AI coding assistant."}],["$","meta","3",{"name":"theme-color","media":"(prefers-color-scheme: light)","content":"white"}],["$","meta","4",{"name":"theme-color","media":"(prefers-color-scheme: dark)","content":"black"}],["$","meta","5",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","6",{"name":"next-size-adjust"}]]
4:[null,["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":[["$","head",null,{}],["$","body",null,{"className":"font-sans antialiased __variable_e66fe9 __variable_bd9c35","children":[["$","$L6",null,{}],["$","$L7",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"children":[["$","div",null,{"className":"flex min-h-screen flex-col","children":[["$","$L8",null,{}],["$","main",null,{"className":"bg-muted/50 flex flex-1 flex-col","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":[null,["$","$Lb",null,{"className":"flex-1","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children","(dashboard)","children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":["$Lc",["$","$Ld",null,{"propsForComponent":{"params":{}},"Component":"$e"}],null],"segment":"__PAGE__"},"styles":[]}]}],null],"segment":"(dashboard)"},"styles":[]}]}]]}],null]}]]}]]}],null]
c:null
diff --git a/ee/tabby-webserver/ui/playground.html b/ee/tabby-webserver/ui/playground.html
index dce7e19446b..5b1bda429b7 100644
--- a/ee/tabby-webserver/ui/playground.html
+++ b/ee/tabby-webserver/ui/playground.html
@@ -1 +1 @@
-Tabby - Playground
Scroll to bottom
Tabby , an opensource, self-hosted AI coding assistant .
\ No newline at end of file
+Tabby - Playground
Scroll to bottom
Tabby , an opensource, self-hosted AI coding assistant .
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/playground.txt b/ee/tabby-webserver/ui/playground.txt
index 86931927330..ec44a686c22 100644
--- a/ee/tabby-webserver/ui/playground.txt
+++ b/ee/tabby-webserver/ui/playground.txt
@@ -1,13 +1,13 @@
1:HL["/_next/static/media/86fdec36ddd9097e-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
2:HL["/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
3:HL["/_next/static/css/6473d52ca6f0f35c.css","style"]
-0:["KwTUFhDElVXkDE3jiCtD0",[[["",{"children":["playground",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
-6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-ca2c7a9f923b6e61.js"],"name":"Toaster","async":false}
-7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-ca2c7a9f923b6e61.js"],"name":"Providers","async":false}
-8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-ca2c7a9f923b6e61.js"],"name":"Header","async":false}
+0:["-IQIiI3YS2Md2tsCaIleK",[[["",{"children":["playground",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
+6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Toaster","async":false}
+7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Providers","async":false}
+8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Header","async":false}
9:I{"id":81443,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
a:I{"id":18639,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
-c:I{"id":34926,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","892:static/chunks/892-eb176514ab2c02ba.js","286:static/chunks/286-453e01dda7220f79.js","899:static/chunks/899-0d9fbfefc7a97fe2.js","967:static/chunks/967-f02728ac0b1b01a8.js","383:static/chunks/app/playground/page-8ff3131e9c77580f.js"],"name":"","async":false}
+c:I{"id":34926,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","892:static/chunks/892-eb176514ab2c02ba.js","286:static/chunks/286-453e01dda7220f79.js","899:static/chunks/899-0d9fbfefc7a97fe2.js","967:static/chunks/967-f02728ac0b1b01a8.js","383:static/chunks/app/playground/page-0e44acab13f2ae38.js"],"name":"","async":false}
5:[["$","meta","0",{"charSet":"utf-8"}],["$","title","1",{"children":"Tabby - Playground"}],["$","meta","2",{"name":"description","content":"Tabby, an opensource, self-hosted AI coding assistant."}],["$","meta","3",{"name":"theme-color","media":"(prefers-color-scheme: light)","content":"white"}],["$","meta","4",{"name":"theme-color","media":"(prefers-color-scheme: dark)","content":"black"}],["$","meta","5",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","6",{"name":"next-size-adjust"}]]
4:[null,["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":[["$","head",null,{}],["$","body",null,{"className":"font-sans antialiased __variable_e66fe9 __variable_bd9c35","children":[["$","$L6",null,{}],["$","$L7",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"children":[["$","div",null,{"className":"flex min-h-screen flex-col","children":[["$","$L8",null,{}],["$","main",null,{"className":"bg-muted/50 flex flex-1 flex-col","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children","playground","children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined","childProp":{"current":["$Lb",["$","$Lc",null,{}],null],"segment":"__PAGE__"},"styles":[]}],"segment":"playground"},"styles":[]}]}]]}],null]}]]}]]}],null]
b:null
diff --git a/ee/tabby-webserver/ui/swagger.html b/ee/tabby-webserver/ui/swagger.html
index fa4b7906217..bcb33d21dc8 100644
--- a/ee/tabby-webserver/ui/swagger.html
+++ b/ee/tabby-webserver/ui/swagger.html
@@ -1 +1 @@
-API
\ No newline at end of file
+API
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/swagger.txt b/ee/tabby-webserver/ui/swagger.txt
index 1e8a2e285c6..ad16b9bd13e 100644
--- a/ee/tabby-webserver/ui/swagger.txt
+++ b/ee/tabby-webserver/ui/swagger.txt
@@ -1,13 +1,13 @@
1:HL["/_next/static/media/86fdec36ddd9097e-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
2:HL["/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
3:HL["/_next/static/css/6473d52ca6f0f35c.css","style"]
-0:["KwTUFhDElVXkDE3jiCtD0",[[["",{"children":["(dashboard)",{"children":["swagger",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
-6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-ca2c7a9f923b6e61.js"],"name":"Toaster","async":false}
-7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-ca2c7a9f923b6e61.js"],"name":"Providers","async":false}
-8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-ca2c7a9f923b6e61.js"],"name":"Header","async":false}
+0:["-IQIiI3YS2Md2tsCaIleK",[[["",{"children":["(dashboard)",{"children":["swagger",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
+6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Toaster","async":false}
+7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Providers","async":false}
+8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Header","async":false}
9:I{"id":81443,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
a:I{"id":18639,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
-b:I{"id":30831,"chunks":["882:static/chunks/882-5574357230a12cf9.js","396:static/chunks/396-89319c375c83667c.js","642:static/chunks/app/(dashboard)/layout-3f83ef2900ef6e5d.js"],"name":"","async":false}
+b:I{"id":30831,"chunks":["882:static/chunks/882-5574357230a12cf9.js","396:static/chunks/396-89319c375c83667c.js","642:static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js"],"name":"","async":false}
5:[["$","meta","0",{"charSet":"utf-8"}],["$","title","1",{"children":"API"}],["$","meta","2",{"name":"description","content":"Tabby, an opensource, self-hosted AI coding assistant."}],["$","meta","3",{"name":"theme-color","media":"(prefers-color-scheme: light)","content":"white"}],["$","meta","4",{"name":"theme-color","media":"(prefers-color-scheme: dark)","content":"black"}],["$","meta","5",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","6",{"name":"next-size-adjust"}]]
4:[null,["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":[["$","head",null,{}],["$","body",null,{"className":"font-sans antialiased __variable_e66fe9 __variable_bd9c35","children":[["$","$L6",null,{}],["$","$L7",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"children":[["$","div",null,{"className":"flex min-h-screen flex-col","children":[["$","$L8",null,{}],["$","main",null,{"className":"bg-muted/50 flex flex-1 flex-col","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":[null,["$","$Lb",null,{"className":"flex-1","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children","(dashboard)","children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children","(dashboard)","children","swagger","children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined","childProp":{"current":["$Lc",["$","iframe",null,{"className":"grow","src":"/swagger-ui"}],null],"segment":"__PAGE__"},"styles":[]}],"segment":"swagger"},"styles":[]}]}],null],"segment":"(dashboard)"},"styles":[]}]}]]}],null]}]]}]]}],null]
c:null
From b4a02d1369acb265774554ef81b98c9024ce0a23 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 26 Nov 2023 21:41:21 +0100
Subject: [PATCH 11/25] Added ROCm documentation
---
.dockerignore | 1 +
README.md | 13 +++++++++-
website/docs/configuration.md | 2 +-
website/docs/extensions/troubleshooting.md | 6 ++---
website/docs/faq.mdx | 22 +++++++++++++----
website/docs/installation/apple.md | 2 +-
website/docs/installation/docker-compose.mdx | 25 ++++++++++++++++++--
website/docs/installation/docker.mdx | 9 +++++++
website/docs/installation/modal/index.md | 10 ++++----
9 files changed, 73 insertions(+), 17 deletions(-)
diff --git a/.dockerignore b/.dockerignore
index ca65e5c7b99..bfbb41f4fe5 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -5,3 +5,4 @@ clients
python
**/target
**/node_modules
+website
diff --git a/README.md b/README.md
index 062609161c7..9ab0dfe6a3d 100644
--- a/README.md
+++ b/README.md
@@ -49,14 +49,25 @@ You can find our documentation [here](https://tabby.tabbyml.com/docs/getting-sta
- ⚙️ [Configuration](https://tabby.tabbyml.com/docs/configuration)
### Run Tabby in 1 Minute
-The easiest way to start a Tabby server is by using the following Docker command:
+The easiest way to start a Tabby server is by using the following Docker command...
+...with cuda:
```bash
docker run -it \
--gpus all -p 8080:8080 -v $HOME/.tabby:/data \
tabbyml/tabby \
serve --model TabbyML/StarCoder-1B --device cuda
```
+
+...with ROCm (Linux only):
+```bash
+docker run -it \
+ --device /dev/dri --device /dev/kfd \
+ -p 8080:8080 -v $HOME/.tabby:/data \
+ tabbyml/tabby-rocm \
+ serve --model TabbyML/StarCoder-1B --device rocm
+```
+
For additional options (e.g inference type, parallelism), please refer to the [documentation page](https://tabbyml.github.io/tabby).
## 🤝 Contributing
diff --git a/website/docs/configuration.md b/website/docs/configuration.md
index 2e0b21084c9..bdec2748106 100644
--- a/website/docs/configuration.md
+++ b/website/docs/configuration.md
@@ -95,7 +95,7 @@ struct HealthState {
arch: String,
cpu_info: String,
cpu_count: usize,
- cuda_devices: Vec,
+ gpu_devices: Vec,
version: Version,
}
```
diff --git a/website/docs/extensions/troubleshooting.md b/website/docs/extensions/troubleshooting.md
index d687ffe13ef..84acf9885c8 100644
--- a/website/docs/extensions/troubleshooting.md
+++ b/website/docs/extensions/troubleshooting.md
@@ -110,9 +110,9 @@ Keep in mind that Tabby may not provide any suggestions based on the current cod
If your completion requests are timing out, Tabby may display a warning message.
This could be due to network issues or poor server performance, especially when
running a large model on a CPU. To improve performance, consider running the model
-on a GPU with CUDA support or on Apple M1/M2 with Metal support. When running
-the server, make sure to specify the device in the arguments using `--device cuda`
-or `--device metal`. You can also try using a smaller model from the available [models](../models/).
+on a GPU with CUDA or ROCm support or on Apple M1/M2 with Metal support. When running
+the server, make sure to specify the device in the arguments using `--device cuda`, `--device rocm` or
+`--device metal`. You can also try using a smaller model from the available [models](../models/).
By default, the timeout for automatically triggered completion requests is set to 5 seconds.
You can adjust this timeout value in the `~/.tabby-client/agent/config.toml` configuration file.
diff --git a/website/docs/faq.mdx b/website/docs/faq.mdx
index 3dc6ecb632f..f50093f9c30 100644
--- a/website/docs/faq.mdx
+++ b/website/docs/faq.mdx
@@ -1,10 +1,11 @@
-import CodeBlock from '@theme/CodeBlock';
-
# ⁉️ Frequently Asked Questions
How much VRAM a LLM model consumes?
- By default, Tabby operates in int8 mode with CUDA, requiring approximately 8GB of VRAM for CodeLlama-7B.
+
+
By default, Tabby operates in int8 mode with CUDA, requiring approximately 8GB of VRAM for CodeLlama-7B.
+
For ROCm the actual limits are currently largely untested, but the same CodeLlama-7B seems to use 8GB of VRAM as well on a AMD Radeon™ RX 7900 XTX according to the ROCm monitoring tools.
+
@@ -18,13 +19,26 @@ import CodeBlock from '@theme/CodeBlock';
To determine the mapping between the GPU card type and its compute capability, please visit this page
+
+ This also seems to be available on AMD Radeon™ GPUs, but it's unclear which cards besides RDNA3 support this.
+
How to utilize multiple NVIDIA GPUs?
-
Tabby only supports the use of a single GPU. To utilize multiple GPUs, you can initiate multiple Tabby instances and set CUDA_VISIBLE_DEVICES accordingly.
+
Tabby only supports the use of a single GPU. To utilize multiple GPUs, you can initiate multiple Tabby instances and set CUDA_VISIBLE_DEVICES or HIP_VISIBLE_DEVICES accordingly.
+
+
+
+
+ My AMD ROCm device isn't supported by ROCm
+
+
+ You can use the HSA_OVERRIDE_GFX_VERSION variable if there is a similar GPU that is supported by ROCm you can set it to that.
+ For example for RDNA2 you can set it to 10.3.0 and to 11.0.0 for RDNA3.
+
diff --git a/website/docs/installation/apple.md b/website/docs/installation/apple.md
index 90bd2f6de1b..8fed35ce4ed 100644
--- a/website/docs/installation/apple.md
+++ b/website/docs/installation/apple.md
@@ -14,4 +14,4 @@ brew install tabbyml/tabby/tabby
tabby serve --device metal --model TabbyML/StarCoder-1B
```
-The compute power of M1/M2 is limited and is likely to be sufficient only for individual usage. If you require a shared instance for a team, we recommend considering Docker hosting with CUDA. You can find more information about Docker [here](./docker).
+The compute power of M1/M2 is limited and is likely to be sufficient only for individual usage. If you require a shared instance for a team, we recommend considering Docker hosting with CUDA or ROCm. You can find more information about Docker [here](./docker).
diff --git a/website/docs/installation/docker-compose.mdx b/website/docs/installation/docker-compose.mdx
index 9f79d67ab91..b2f6f83a602 100644
--- a/website/docs/installation/docker-compose.mdx
+++ b/website/docs/installation/docker-compose.mdx
@@ -5,6 +5,8 @@ sidebar_position: 1
# Docker Compose
This guide explains how to launch Tabby using docker-compose.
+
+
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
@@ -16,7 +18,7 @@ version: '3.5'
services:
tabby:
- restart: always
+ restart: unless-stopped
image: tabbyml/tabby
command: serve --model TabbyML/StarCoder-1B
volumes:
@@ -32,7 +34,7 @@ services:
version: '3.5'
services:
tabby:
- restart: always
+ restart: unless-stopped
image: tabbyml/tabby
command: serve --model TabbyML/StarCoder-1B --device cuda
volumes:
@@ -48,6 +50,25 @@ services:
capabilities: [gpu]
```
+
+
+
+```yaml title="docker-compose.yml"
+version: '3.5'
+services:
+ tabby:
+ restart: unless-stopped
+ image: tabbyml/tabby-rocm
+ command: serve --model TabbyML/StarCoder-1B --device rocm
+ volumes:
+ - "$HOME/.tabby:/data"
+ ports:
+ - 8080:8080
+ devices:
+ - /dev/dri
+ - /dev/kfd
+```
+
diff --git a/website/docs/installation/docker.mdx b/website/docs/installation/docker.mdx
index 31c78b034b9..f3602f77c09 100644
--- a/website/docs/installation/docker.mdx
+++ b/website/docs/installation/docker.mdx
@@ -6,6 +6,8 @@ sidebar_position: 0
This guide explains how to launch Tabby using docker.
+
+
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
@@ -23,5 +25,12 @@ import TabItem from '@theme/TabItem';
docker run -it --gpus all -p 8080:8080 -v $HOME/.tabby:/data tabbyml/tabby serve --model TabbyML/StarCoder-1B --device cuda
```
+
+
+
+ ```bash title="run.sh"
+ docker run -it --device /dev/dri --device /dev/kfd -p 8080:8080 -v $HOME/.tabby:/data tabbyml/tabby serve --model TabbyML/StarCoder-1B --device cuda
+ ```
+
diff --git a/website/docs/installation/modal/index.md b/website/docs/installation/modal/index.md
index 78f6f3bb43e..e10e22b2e60 100644
--- a/website/docs/installation/modal/index.md
+++ b/website/docs/installation/modal/index.md
@@ -20,11 +20,11 @@ GPU_CONFIG = gpu.T4()
Currently supported GPUs in Modal:
-- `T4`: Low-cost GPU option, providing 16GiB of GPU memory.
-- `L4`: Mid-tier GPU option, providing 24GiB of GPU memory.
-- `A100`: The most powerful GPU available in the cloud. Available in 40GiB and 80GiB GPU memory configurations.
-- `A10G`: A10G GPUs deliver up to 3.3x better ML training performance, 3x better ML inference performance, and 3x better graphics performance, in comparison to NVIDIA T4 GPUs.
-- `Any`: Selects any one of the GPU classes available within Modal, according to availability.
+- `NVIDIA T4`: Low-cost GPU option, providing 16GiB of GPU memory.
+- `NVIDIA L4`: Mid-tier GPU option, providing 24GiB of GPU memory.
+- `NVIDIA A100`: The most powerful GPU available in the cloud. Available in 40GiB and 80GiB GPU memory configurations.
+- `NVIDIA A10G`: A10G GPUs deliver up to 3.3x better ML training performance, 3x better ML inference performance, and 3x better graphics performance, in comparison to NVIDIA T4 GPUs.
+- `NVIDIA Any`: Selects any one of the GPU classes available within Modal, according to availability.
For detailed usage, please check official [Modal GPU reference](https://modal.com/docs/reference/modal.gpu).
From 7b40db6c080a96c8cafec70684a2e7e0064a6b0b Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Mon, 27 Nov 2023 19:19:31 +0100
Subject: [PATCH 12/25] Addressed review comments
---
.github/workflows/docker-cuda.yml | 118 ++++++++++++++++++
.../workflows/{docker.yml => docker-rocm.yml} | 35 +-----
crates/llama-cpp-bindings/build.rs | 3 +-
crates/tabby/src/services/health.rs | 8 +-
4 files changed, 128 insertions(+), 36 deletions(-)
create mode 100644 .github/workflows/docker-cuda.yml
rename .github/workflows/{docker.yml => docker-rocm.yml} (73%)
diff --git a/.github/workflows/docker-cuda.yml b/.github/workflows/docker-cuda.yml
new file mode 100644
index 00000000000..4aaa2c856ec
--- /dev/null
+++ b/.github/workflows/docker-cuda.yml
@@ -0,0 +1,118 @@
+name: Create and publish CUDA docker image
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '0 20 */1 * *'
+ push:
+ tags:
+ - 'v*'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }}
+
+ # If this is enabled it will cancel current running and start latest
+ cancel-in-progress: true
+
+env:
+ RUST_TOOLCHAIN: 1.73.0
+
+jobs:
+ release-docker:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ # This is used to complete the identity challenge
+ # with sigstore/fulcio when running outside of PRs.
+ id-token: write
+
+ steps:
+ - name: Free Disk Space (Ubuntu)
+ uses: jlumbroso/free-disk-space@main
+ with:
+ # this might remove tools that are actually needed,
+ # if set to "true" but frees about 6 GB
+ tool-cache: true
+
+ # all of these default to true, but feel free to set to
+ # "false" if necessary for your workflow
+ android: true
+ dotnet: true
+ haskell: true
+ large-packages: false
+ swap-storage: true
+
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+
+ # Workaround: https://github.com/docker/build-push-action/issues/461
+ - name: Setup Docker buildx
+ uses: docker/setup-buildx-action@v3.0.0
+ with:
+ # Needed to support OCI annotations
+ version: v0.12.0
+
+ # Login against a Docker registry except on PR
+ # https://github.com/docker/login-action
+ - name: Log into GitHub Container registry
+ uses: docker/login-action@v2.0.0
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Log into Docker Hub
+ uses: docker/login-action@v2.0.0
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+ - name: Generate image name
+ run: |
+ echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
+
+ - uses: int128/docker-build-cache-config-action@v1
+ id: cache
+ with:
+ image: ghcr.io/${{ env.IMAGE_NAME }}/cache
+
+ - name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5.0.0
+ with:
+ # list of Docker images to use as base name for tags
+ images: |
+ ghcr.io/${{ env.IMAGE_NAME }}
+ ${{ env.IMAGE_NAME }}
+ # generate Docker tags based on the following events/attributes
+ tags: |
+ type=raw,value={{branch}}-{{sha}},enable=${{ startsWith(github.ref, 'refs/heads') }}
+ type=schedule,pattern=nightly
+ type=schedule,pattern={{date 'YYYYMMDD'}}
+ type=semver,pattern={{version}}
+
+ # Build and push Docker image with Buildx (don't push on PR)
+ # https://github.com/docker/build-push-action
+ - name: Build and push Docker image
+ id: build-and-push
+ uses: docker/build-push-action@v5.1.0
+ with:
+ file: cuda.Dockerfile
+ push: true
+ context: .
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ annotations: ${{ steps.meta.outputs.labels }}
+ cache-from: ${{ steps.cache.outputs.cache-from }}
+ cache-to: ${{ steps.cache.outputs.cache-to }}
+ build-args: RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+
+ - name: Docker Hub Description
+ uses: peter-evans/dockerhub-description@v3
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+ repository: tabbyml/tabby
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker-rocm.yml
similarity index 73%
rename from .github/workflows/docker.yml
rename to .github/workflows/docker-rocm.yml
index 58ee2b6b4a3..ca4963777f1 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker-rocm.yml
@@ -1,4 +1,4 @@
-name: Create and publish docker image
+name: Create and publish ROCm docker image
on:
workflow_dispatch:
@@ -82,21 +82,6 @@ jobs:
- name: Docker meta
id: meta
uses: docker/metadata-action@v5.0.0
- with:
- # list of Docker images to use as base name for tags
- images: |
- ghcr.io/${{ env.IMAGE_NAME }}
- ${{ env.IMAGE_NAME }}
- # generate Docker tags based on the following events/attributes
- tags: |
- type=raw,value={{branch}}-{{sha}},enable=${{ startsWith(github.ref, 'refs/heads') }}
- type=schedule,pattern=nightly
- type=schedule,pattern={{date 'YYYYMMDD'}}
- type=semver,pattern={{version}}
-
- - name: Docker meta for ROCm
- id: meta-rocm
- uses: docker/metadata-action@v5.0.0
with:
# list of Docker images to use as base name for tags
images: |
@@ -116,7 +101,7 @@ jobs:
id: build-and-push
uses: docker/build-push-action@v5.1.0
with:
- file: cuda.Dockerfile
+ file: rocm.Dockerfile
push: true
context: .
tags: ${{ steps.meta.outputs.tags }}
@@ -126,22 +111,6 @@ jobs:
cache-to: ${{ steps.cache.outputs.cache-to }}
build-args: RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
- # Build and push Docker image with Buildx (don't push on PR)
- # https://github.com/docker/build-push-action
- - name: Build and push Docker image for ROCm
- id: build-and-push-rocm
- uses: docker/build-push-action@v5.1.0
- with:
- file: rocm.Dockerfile
- push: true
- context: .
- tags: ${{ steps.meta-rocm.outputs.tags }}
- labels: ${{ steps.meta-rocm.outputs.labels }}
- annotations: ${{ steps.meta-rocm.outputs.labels }}
- cache-from: ${{ steps.cache.outputs.cache-from }}
- cache-to: ${{ steps.cache.outputs.cache-to }}
- build-args: RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
-
- name: Docker Hub Description
uses: peter-evans/dockerhub-description@v3
with:
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index ccca52341c8..e38506d9c63 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -4,7 +4,6 @@ use cmake::Config;
fn main() {
const LLAMA_CMAKE_PATH: &str = "llama.cpp/CMakeLists.txt";
- const AMDGPU_TARGETS: &str = "gfx803;gfx900;gfx906:xnack-;gfx908:xnack-;gfx90a:xnack+;gfx90a:xnack-;gfx940;gfx941;gfx942;gfx1010;gfx1012;gfx1030;gfx1100;gfx1101;gfx1102";
assert!(
Path::new(LLAMA_CMAKE_PATH).exists(),
@@ -33,6 +32,8 @@ fn main() {
println!("cargo:rustc-link-lib=cublasLt");
}
if cfg!(feature = "rocm") {
+ const AMDGPU_TARGETS: &str = "gfx803;gfx900;gfx906:xnack-;gfx908:xnack-;gfx90a:xnack+;gfx90a:xnack-;gfx940;gfx941;gfx942;gfx1010;gfx1012;gfx1030;gfx1100;gfx1101;gfx1102";
+
let rocm_root = "/opt/rocm";
config.define("LLAMA_HIPBLAS", "ON");
config.define("CMAKE_C_COMPILER", format!("{}/llvm/bin/clang", rocm_root));
diff --git a/crates/tabby/src/services/health.rs b/crates/tabby/src/services/health.rs
index 71558979f47..b69eb222e78 100644
--- a/crates/tabby/src/services/health.rs
+++ b/crates/tabby/src/services/health.rs
@@ -24,6 +24,8 @@ pub struct HealthState {
cpu_info: String,
cpu_count: usize,
gpu_devices: Vec,
+ #[deprecated(note = "Use the more generic gpu_devices instead")]
+ cuda_devices: Vec,
version: Version,
}
@@ -31,11 +33,12 @@ impl HealthState {
pub fn new(model: Option<&str>, chat_model: Option<&str>, device: &Device) -> Self {
let (cpu_info, cpu_count) = read_cpu_info();
- let cuda_devices = match read_gpu_devices() {
+ let gpu_devices = match read_gpu_devices() {
Ok(s) => s,
Err(_) => vec![],
};
+ #[allow(deprecated)]
Self {
model: model.map(|x| x.to_owned()),
chat_model: chat_model.map(|x| x.to_owned()),
@@ -43,7 +46,8 @@ impl HealthState {
arch: ARCH.to_string(),
cpu_info,
cpu_count,
- gpu_devices: cuda_devices,
+ gpu_devices: gpu_devices.clone(),
+ cuda_devices: gpu_devices,
version: Version::new(),
}
}
From 55c78847245d3925745d6a54909e0252dc2b75d7 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Tue, 28 Nov 2023 23:44:44 +0100
Subject: [PATCH 13/25] Refactored to expose generic accelerator information
---
Cargo.lock | 22 +---
crates/llama-cpp-bindings/build.rs | 4 +-
crates/tabby-common/Cargo.toml | 1 +
crates/tabby-common/src/api/accelerator.rs | 21 ++++
crates/tabby-common/src/api/mod.rs | 1 +
crates/tabby-inference/src/decoding.rs | 5 +-
crates/tabby/Cargo.toml | 7 +-
crates/tabby/src/main.rs | 3 +-
crates/tabby/src/serve.rs | 4 +-
crates/tabby/src/services/health.rs | 112 +++++++++++++-----
crates/tabby/src/worker.rs | 7 +-
.../(dashboard)/components/worker-card.tsx | 46 ++-----
ee/tabby-ui/app/(dashboard)/page.tsx | 37 ++++--
ee/tabby-ui/lib/gql/generates/gql.ts | 8 +-
ee/tabby-ui/lib/gql/generates/graphql.ts | 52 +++++++-
ee/tabby-ui/lib/gql/request-documents.tsx | 9 +-
ee/tabby-ui/lib/hooks/use-health.tsx | 11 +-
ee/tabby-ui/lib/hooks/use-workers.ts | 18 ++-
ee/tabby-ui/lib/utils.ts | 8 +-
ee/tabby-webserver/graphql/schema.graphql | 18 ++-
ee/tabby-webserver/src/api.rs | 10 +-
ee/tabby-webserver/src/lib.rs | 14 +--
ee/tabby-webserver/ui/404.html | 2 +-
.../static/chunks/967-77bee9da62f91e7a.js | 1 +
.../static/chunks/967-f02728ac0b1b01a8.js | 1 -
.../(dashboard)/layout-9112e2f61825d91a.js | 1 -
.../(dashboard)/layout-d5a067a319c8b1d7.js | 1 +
.../app/(dashboard)/page-223f244bef7bc3fe.js | 1 -
.../app/(dashboard)/page-799bd801adc161c7.js | 1 +
.../chunks/app/layout-01cdb629b9621465.js | 1 +
.../chunks/app/layout-a709b0b21d295a91.js | 1 -
...ab13f2ae38.js => page-178c9cbcb60d3ef7.js} | 0
.../_buildManifest.js | 0
.../_ssgManifest.js | 0
ee/tabby-webserver/ui/index.html | 2 +-
ee/tabby-webserver/ui/index.txt | 12 +-
ee/tabby-webserver/ui/playground.html | 2 +-
ee/tabby-webserver/ui/playground.txt | 10 +-
ee/tabby-webserver/ui/swagger.html | 2 +-
ee/tabby-webserver/ui/swagger.txt | 10 +-
40 files changed, 298 insertions(+), 168 deletions(-)
create mode 100644 crates/tabby-common/src/api/accelerator.rs
create mode 100644 ee/tabby-webserver/ui/_next/static/chunks/967-77bee9da62f91e7a.js
delete mode 100644 ee/tabby-webserver/ui/_next/static/chunks/967-f02728ac0b1b01a8.js
delete mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js
create mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-d5a067a319c8b1d7.js
delete mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js
create mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-799bd801adc161c7.js
create mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/layout-01cdb629b9621465.js
delete mode 100644 ee/tabby-webserver/ui/_next/static/chunks/app/layout-a709b0b21d295a91.js
rename ee/tabby-webserver/ui/_next/static/chunks/app/playground/{page-0e44acab13f2ae38.js => page-178c9cbcb60d3ef7.js} (100%)
rename ee/tabby-webserver/ui/_next/static/{-IQIiI3YS2Md2tsCaIleK => yoSiYgCA8KR8UtHATY8_5}/_buildManifest.js (100%)
rename ee/tabby-webserver/ui/_next/static/{-IQIiI3YS2Md2tsCaIleK => yoSiYgCA8KR8UtHATY8_5}/_ssgManifest.js (100%)
diff --git a/Cargo.lock b/Cargo.lock
index ed7c0a5b3b4..5ca449496f3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3743,26 +3743,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "rocm_smi_lib"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aab3a8127b4332d79efce5c924c79f04eb35ab4f1e540947320f86de1c9465bb"
-dependencies = [
- "libc",
- "rocm_smi_lib_sys",
-]
-
-[[package]]
-name = "rocm_smi_lib_sys"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc32313f54e56d303342caae5cde35e5605ba7f946735985a11c00b2b5d6479"
-dependencies = [
- "cmake",
- "libc",
-]
-
[[package]]
name = "rusqlite"
version = "0.29.0"
@@ -4597,7 +4577,6 @@ dependencies = [
"opentelemetry-otlp",
"regex",
"reqwest",
- "rocm_smi_lib",
"serde",
"serde_json",
"serdeconv",
@@ -4631,6 +4610,7 @@ dependencies = [
"async-trait",
"filenamify",
"glob",
+ "juniper",
"lazy_static",
"reqwest",
"serde",
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index e38506d9c63..338db3b3eae 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -1,4 +1,4 @@
-use std::path::Path;
+use std::{env, path::Path};
use cmake::Config;
@@ -34,7 +34,7 @@ fn main() {
if cfg!(feature = "rocm") {
const AMDGPU_TARGETS: &str = "gfx803;gfx900;gfx906:xnack-;gfx908:xnack-;gfx90a:xnack+;gfx90a:xnack-;gfx940;gfx941;gfx942;gfx1010;gfx1012;gfx1030;gfx1100;gfx1101;gfx1102";
- let rocm_root = "/opt/rocm";
+ let rocm_root = env::var("ROCM_ROOT").unwrap_or("/opt/rocm".to_string());
config.define("LLAMA_HIPBLAS", "ON");
config.define("CMAKE_C_COMPILER", format!("{}/llvm/bin/clang", rocm_root));
config.define(
diff --git a/crates/tabby-common/Cargo.toml b/crates/tabby-common/Cargo.toml
index 755559d251f..2b10aed783c 100644
--- a/crates/tabby-common/Cargo.toml
+++ b/crates/tabby-common/Cargo.toml
@@ -14,6 +14,7 @@ uuid = { version = "1.4.1", features = ["v4"] }
tantivy.workspace = true
anyhow.workspace = true
glob = "0.3.1"
+juniper.workspace = true
utoipa.workspace = true
serde_json.workspace = true
async-trait.workspace = true
diff --git a/crates/tabby-common/src/api/accelerator.rs b/crates/tabby-common/src/api/accelerator.rs
new file mode 100644
index 00000000000..59e7fdadda2
--- /dev/null
+++ b/crates/tabby-common/src/api/accelerator.rs
@@ -0,0 +1,21 @@
+use juniper::{GraphQLEnum, GraphQLObject};
+use serde::{Deserialize, Serialize};
+use utoipa::ToSchema;
+
+#[derive(Serialize, Deserialize, GraphQLEnum, ToSchema, PartialEq, Clone, Debug)]
+pub enum DeviceType {
+ Cuda,
+ Rocm,
+}
+
+#[derive(Serialize, Deserialize, GraphQLObject, ToSchema, Clone, Debug)]
+pub struct Accelerator {
+ /// Universally unique ID of the accelerator, if available
+ pub uuid: Option,
+ /// Technical name of the underlying hardware chip, if available
+ pub chip_name: Option,
+ /// User readable name for the accelerator
+ pub display_name: String,
+ /// Type of the accelerator device
+ pub device_type: DeviceType,
+}
diff --git a/crates/tabby-common/src/api/mod.rs b/crates/tabby-common/src/api/mod.rs
index cebf170a1e9..465540a84fa 100644
--- a/crates/tabby-common/src/api/mod.rs
+++ b/crates/tabby-common/src/api/mod.rs
@@ -1,2 +1,3 @@
+pub mod accelerator;
pub mod code;
pub mod event;
diff --git a/crates/tabby-inference/src/decoding.rs b/crates/tabby-inference/src/decoding.rs
index 5bf202ae8d4..3584ef99a00 100644
--- a/crates/tabby-inference/src/decoding.rs
+++ b/crates/tabby-inference/src/decoding.rs
@@ -50,7 +50,8 @@ fn create_stop_regex(stop_words: Vec) -> Regex {
.iter()
.map(|x| regex::escape(&reverse(x)))
.collect();
- let regex_string = r"(?m)\A".to_owned() + "((" + &reversed_stop_words.join(")|(") + "))";
+ let regex_string =
+ r"(?m)\A".to_owned() + "((" + reversed_stop_words.join(")|(").as_str() + "))";
Regex::new(®ex_string).expect("Failed to create regex")
}
@@ -69,7 +70,7 @@ impl StopCondition {
pub fn should_stop(&mut self, new_text: &str) -> bool {
if !new_text.is_empty() {
- self.reversed_text = reverse(new_text) + &self.reversed_text;
+ self.reversed_text = reverse(new_text) + self.reversed_text.as_str();
if let Some(re) = &self.stop_re {
if re.is_match(&self.reversed_text) {
diff --git a/crates/tabby/Cargo.toml b/crates/tabby/Cargo.toml
index 02ab17efe7e..f5495381c83 100644
--- a/crates/tabby/Cargo.toml
+++ b/crates/tabby/Cargo.toml
@@ -6,8 +6,8 @@ edition = "2021"
[features]
default = ["ee"]
ee = ["dep:tabby-webserver"]
-cuda = ["llama-cpp-bindings/cuda", "dep:nvml-wrapper"]
-rocm = ["llama-cpp-bindings/rocm", "dep:rocm_smi_lib"]
+cuda = ["llama-cpp-bindings/cuda"]
+rocm = ["llama-cpp-bindings/rocm"]
experimental-http = ["dep:http-api-bindings"]
[dependencies]
@@ -37,8 +37,7 @@ tracing-opentelemetry = "0.18.0"
tantivy = { workspace = true }
anyhow = { workspace = true }
sysinfo = "0.29.8"
-nvml-wrapper = { version = "0.9.0", optional = true }
-rocm_smi_lib = { version = "0.1.14", optional = true }
+nvml-wrapper = { version = "0.9.0" }
http-api-bindings = { path = "../http-api-bindings", optional = true } # included when build with `experimental-http` feature
async-stream = { workspace = true }
axum-streams = { version = "0.9.1", features = ["json"] }
diff --git a/crates/tabby/src/main.rs b/crates/tabby/src/main.rs
index 652ba4b823f..ae56c2403e7 100644
--- a/crates/tabby/src/main.rs
+++ b/crates/tabby/src/main.rs
@@ -5,9 +5,8 @@ use opentelemetry::{
KeyValue,
};
use opentelemetry_otlp::WithExportConfig;
-use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};
-
use tabby_common::config::Config;
+use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};
mod routes;
mod services;
diff --git a/crates/tabby/src/serve.rs b/crates/tabby/src/serve.rs
index 6cea454ba9b..74327443ee5 100644
--- a/crates/tabby/src/serve.rs
+++ b/crates/tabby/src/serve.rs
@@ -5,7 +5,7 @@ use clap::Args;
use hyper::StatusCode;
use tabby_common::{
api,
- api::{code::CodeSearch, event::EventLogger},
+ api::{accelerator, code::CodeSearch, event::EventLogger},
config::Config,
usage,
};
@@ -58,6 +58,8 @@ Install following IDE / Editor extensions to get started with [Tabby](https://gi
chat::ChatCompletionRequest,
chat::Message,
chat::ChatCompletionChunk,
+ accelerator::DeviceType,
+ accelerator::Accelerator,
health::HealthState,
health::Version,
api::code::SearchResponse,
diff --git a/crates/tabby/src/services/health.rs b/crates/tabby/src/services/health.rs
index b69eb222e78..81e676b3bcf 100644
--- a/crates/tabby/src/services/health.rs
+++ b/crates/tabby/src/services/health.rs
@@ -1,14 +1,12 @@
-use std::env::consts::ARCH;
+use std::{env, env::consts::ARCH, process::Command, str::from_utf8};
use anyhow::Result;
-#[cfg(feature = "cuda")]
+use lazy_static::lazy_static;
use nvml_wrapper::Nvml;
-#[cfg(feature = "rocm")]
-use rocm_smi_lib::error::RocmErr;
-#[cfg(feature = "rocm")]
-use rocm_smi_lib::RocmSmi;
+use regex::Regex;
use serde::{Deserialize, Serialize};
use sysinfo::{CpuExt, System, SystemExt};
+use tabby_common::api::accelerator::{Accelerator, DeviceType};
use utoipa::ToSchema;
use crate::Device;
@@ -23,7 +21,7 @@ pub struct HealthState {
arch: String,
cpu_info: String,
cpu_count: usize,
- gpu_devices: Vec,
+ accelerators: Vec,
#[deprecated(note = "Use the more generic gpu_devices instead")]
cuda_devices: Vec,
version: Version,
@@ -33,10 +31,15 @@ impl HealthState {
pub fn new(model: Option<&str>, chat_model: Option<&str>, device: &Device) -> Self {
let (cpu_info, cpu_count) = read_cpu_info();
- let gpu_devices = match read_gpu_devices() {
- Ok(s) => s,
- Err(_) => vec![],
- };
+ let accelerators = read_accelerators();
+
+ let mut cuda_devices = vec![];
+
+ for accelerator in &accelerators {
+ if accelerator.device_type == DeviceType::Cuda {
+ cuda_devices.push(accelerator.display_name.clone());
+ }
+ }
#[allow(deprecated)]
Self {
@@ -46,8 +49,8 @@ impl HealthState {
arch: ARCH.to_string(),
cpu_info,
cpu_count,
- gpu_devices: gpu_devices.clone(),
- cuda_devices: gpu_devices,
+ accelerators,
+ cuda_devices,
version: Version::new(),
}
}
@@ -68,8 +71,7 @@ pub fn read_cpu_info() -> (String, usize) {
(info, count)
}
-#[cfg(feature = "cuda")]
-pub fn read_gpu_devices() -> Result> {
+pub fn read_cuda_devices() -> Result> {
// In cases of MacOS or docker containers where --gpus are not specified,
// the Nvml::init() would return an error. In these scenarios, we
// assign cuda_devices to be empty, indicating that the current runtime
@@ -78,27 +80,83 @@ pub fn read_gpu_devices() -> Result> {
let mut cuda_devices = vec![];
let device_count = nvml.device_count()?;
for i in 0..device_count {
- let name = nvml.device_by_index(i)?.name()?;
- cuda_devices.push(name);
+ let dev = nvml.device_by_index(i)?;
+ let resource = Accelerator {
+ uuid: Some(dev.uuid()?),
+ chip_name: None,
+ display_name: dev.name()?,
+ device_type: DeviceType::Cuda,
+ };
+ cuda_devices.push(resource);
}
Ok(cuda_devices)
}
-#[cfg(feature = "rocm")]
-pub fn read_gpu_devices() -> Result, RocmErr> {
- let rocm = RocmSmi::init()?;
+pub fn read_rocm_devices() -> Result> {
+ lazy_static! {
+ static ref NAME_REGEX: Regex = Regex::new(r"(?m)^ Name: +([a-zA-Z0-9]+) *$",).unwrap();
+ static ref MARKETING_NAME_REGEX: Regex =
+ Regex::new(r"(?m)^ Marketing Name: +(\S.*\S) *$").unwrap();
+ static ref UUID_REGEX: Regex =
+ Regex::new(r"(?m)^ Uuid: +GPU-([a-zA-Z0-9\-]+) *$").unwrap();
+ static ref DEVICE_TYPE_REGEX: Regex =
+ Regex::new(r"(?m)^ Device Type: +([a-zA-Z0-9-]+) *$").unwrap();
+ }
+
+ let cmd_res = Command::new("rocminfon").output()?;
+ let output = from_utf8(cmd_res.stdout.as_slice())?;
+ let agent_outputs = output.split("Agent ").skip(1);
let mut rocm_devices = vec![];
- let device_count = rocm.get_device_count();
- for i in 0..device_count {
- let name = rocm.get_device_identifiers(i)?.name;
- rocm_devices.push(name);
+ for agent_output in agent_outputs {
+ let device_type = DEVICE_TYPE_REGEX
+ .captures(agent_output)
+ .unwrap()
+ .get(1)
+ .unwrap()
+ .as_str();
+ if device_type != "GPU" {
+ continue;
+ }
+
+ let name = NAME_REGEX
+ .captures(agent_output)
+ .unwrap()
+ .get(1)
+ .unwrap()
+ .as_str();
+ let marketing_name = MARKETING_NAME_REGEX
+ .captures(agent_output)
+ .unwrap()
+ .get(1)
+ .unwrap()
+ .as_str();
+ let uuid = UUID_REGEX
+ .captures(agent_output)
+ .map(|c| c.get(1).unwrap().as_str());
+ let accelerator = Accelerator {
+ uuid: uuid.map(|s| s.to_string()),
+ chip_name: Some(name.to_string()),
+ display_name: marketing_name.to_string(),
+ device_type: DeviceType::Rocm,
+ };
+ rocm_devices.push(accelerator);
}
Ok(rocm_devices)
}
-#[cfg(not(any(feature = "cuda", feature = "rocm",)))]
-pub fn read_gpu_devices() -> Result> {
- Ok(vec![])
+pub fn read_accelerators() -> Vec {
+ let mut devices = vec![];
+ if let Ok(cuda_devices) = read_cuda_devices() {
+ for dev in cuda_devices {
+ devices.push(dev);
+ }
+ }
+ if let Ok(rocm_devices) = read_rocm_devices() {
+ for dev in rocm_devices {
+ devices.push(dev);
+ }
+ }
+ devices
}
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)]
diff --git a/crates/tabby/src/worker.rs b/crates/tabby/src/worker.rs
index 69bdaacbe7f..2bc5c5e4fde 100644
--- a/crates/tabby/src/worker.rs
+++ b/crates/tabby/src/worker.rs
@@ -3,16 +3,15 @@ use std::{env::consts::ARCH, sync::Arc};
use anyhow::Result;
use axum::{routing, Router};
use clap::Args;
-use tracing::{info, warn};
-
use tabby_webserver::api::{tracing_context, HubClient, WorkerKind};
+use tracing::{info, warn};
use crate::{
routes::{self, run_app},
services::{
chat::create_chat_service,
completion::create_completion_service,
- health::{read_cpu_info, read_gpu_devices},
+ health::{read_accelerators, read_cpu_info},
model::download_model_if_needed,
},
Device,
@@ -106,7 +105,7 @@ impl WorkerContext {
async fn register_impl(&self, kind: WorkerKind, args: &WorkerArgs) -> Result<()> {
let (cpu_info, cpu_count) = read_cpu_info();
- let gpu_devices = read_gpu_devices().unwrap_or_default();
+ let gpu_devices = read_accelerators();
let worker = self
.client
.register_worker(
diff --git a/ee/tabby-ui/app/(dashboard)/components/worker-card.tsx b/ee/tabby-ui/app/(dashboard)/components/worker-card.tsx
index 0b0878acb3f..79145c4163d 100644
--- a/ee/tabby-ui/app/(dashboard)/components/worker-card.tsx
+++ b/ee/tabby-ui/app/(dashboard)/components/worker-card.tsx
@@ -1,6 +1,6 @@
-import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card'
-import {Worker, WorkerKind} from '@/lib/gql/generates/graphql'
-import {cn} from '@/lib/utils'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+import { Worker, WorkerKind } from '@/lib/gql/generates/graphql'
+import { cn } from '@/lib/utils'
type RunnerType = WorkerKind | 'INDEX'
@@ -13,7 +13,7 @@ export default function RunnerCard({
name,
kind,
device,
- gpuDevices,
+ accelerators,
cpuCount,
cpuInfo
}: RunnerCardProps) {
@@ -77,9 +77,8 @@ export default function RunnerCard({
{cpuMessage}
- {device == 'cuda' &&
- gpuDevices?.length &&
- gpuDevices.map((x, i) => (
+ {accelerators?.length &&
+ accelerators.map((x, i) => (
- {x}
-
- ))}
- {device == 'rocm' &&
- gpuDevices?.length &&
- gpuDevices.map((x, i) => (
-
-
-
-
-
-
-
-
-
-
-
-
- {x}
+
+ {x.displayName}
+
))}
diff --git a/ee/tabby-ui/app/(dashboard)/page.tsx b/ee/tabby-ui/app/(dashboard)/page.tsx
index 93e3166c9f8..7dad12eca93 100644
--- a/ee/tabby-ui/app/(dashboard)/page.tsx
+++ b/ee/tabby-ui/app/(dashboard)/page.tsx
@@ -1,17 +1,25 @@
'use client'
-import {buttonVariants} from '@/components/ui/button'
-import {Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle} from '@/components/ui/dialog'
-import {IconSlack} from '@/components/ui/icons'
-import {Separator} from '@/components/ui/separator'
-import {useHealth} from '@/lib/hooks/use-health'
-import {PropsWithChildren, useEffect, useState} from 'react'
+import { buttonVariants } from '@/components/ui/button'
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle
+} from '@/components/ui/dialog'
+import { IconSlack } from '@/components/ui/icons'
+import { Separator } from '@/components/ui/separator'
+import { useHealth } from '@/lib/hooks/use-health'
+import { PropsWithChildren, useEffect, useState } from 'react'
import WorkerCard from './components/worker-card'
-import {useWorkers} from '@/lib/hooks/use-workers'
-import {WorkerKind} from '@/lib/gql/generates/graphql'
-import {useGraphQL} from '@/lib/hooks/use-graphql'
-import {getRegistrationTokenDocument} from '@/lib/gql/request-documents'
-import {CopyButton} from '@/components/copy-button'
+import { useWorkers } from '@/lib/hooks/use-workers'
+import { WorkerKind } from '@/lib/gql/generates/graphql'
+import { useGraphQL } from '@/lib/hooks/use-graphql'
+import { getRegistrationTokenDocument } from '@/lib/gql/request-documents'
+import { CopyButton } from '@/components/copy-button'
+import { deviceTypeMap } from "@/lib/utils";
const COMMUNITY_DIALOG_SHOWN_KEY = 'community-dialog-shown'
@@ -130,7 +138,12 @@ function MainPanel() {
kind="INDEX"
arch=""
device={healthInfo.device}
- gpuDevices={healthInfo.gpu_devices}
+ accelerators={healthInfo.accelerators.map(x => ({
+ uuid: x.uuid,
+ chipName: x.chip_name,
+ displayName: x.display_name,
+ deviceType: deviceTypeMap[x.device_type],
+ }))}
cpuCount={healthInfo.cpu_count}
cpuInfo={healthInfo.cpu_info}
/>
diff --git a/ee/tabby-ui/lib/gql/generates/gql.ts b/ee/tabby-ui/lib/gql/generates/gql.ts
index ecfcb68fcc0..1e821426474 100644
--- a/ee/tabby-ui/lib/gql/generates/gql.ts
+++ b/ee/tabby-ui/lib/gql/generates/gql.ts
@@ -1,6 +1,6 @@
/* eslint-disable */
import * as types from './graphql'
-import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'
+import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'
/**
* Map of all GraphQL operations in the project.
@@ -13,7 +13,7 @@ import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/co
* Therefore it is highly recommended to use the babel or swc plugin for production.
*/
const documents = {
- '\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n':
+ '\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n accelerators {\n uuid\n chipName\n displayName\n deviceType\n }\n }\n }\n':
types.GetWorkersDocument,
'\n query GetRegistrationToken {\n registrationToken\n }\n':
types.GetRegistrationTokenDocument
@@ -37,8 +37,8 @@ export function graphql(source: string): unknown
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(
- source: '\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n'
-): (typeof documents)['\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n']
+ source: '\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n accelerators {\n uuid\n chipName\n displayName\n deviceType\n }\n }\n }\n'
+): (typeof documents)['\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n accelerators {\n uuid\n chipName\n displayName\n deviceType\n }\n }\n }\n']
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
diff --git a/ee/tabby-ui/lib/gql/generates/graphql.ts b/ee/tabby-ui/lib/gql/generates/graphql.ts
index 555cc81ac4d..4d979f4f79e 100644
--- a/ee/tabby-ui/lib/gql/generates/graphql.ts
+++ b/ee/tabby-ui/lib/gql/generates/graphql.ts
@@ -1,5 +1,5 @@
/* eslint-disable */
-import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'
+import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'
export type Maybe = T | null
export type InputMaybe = Maybe
@@ -30,6 +30,23 @@ export type Scalars = {
Float: { input: number; output: number }
}
+export type Accelerator = {
+ __typename?: 'Accelerator'
+ /** Technical name of the underlying hardware chip, if available */
+ chipName?: Maybe
+ /** Type of the accelerator device */
+ deviceType: DeviceType
+ /** User readable name for the accelerator */
+ displayName: Scalars['String']['output']
+ /** Universally unique ID of the accelerator, if available */
+ uuid?: Maybe
+}
+
+export enum DeviceType {
+ Cuda = 'CUDA',
+ Rocm = 'ROCM'
+}
+
export type Mutation = {
__typename?: 'Mutation'
resetRegistrationToken: Scalars['String']['output']
@@ -43,12 +60,12 @@ export type Query = {
export type Worker = {
__typename?: 'Worker'
+ accelerators: Array
addr: Scalars['String']['output']
arch: Scalars['String']['output']
cpuCount: Scalars['Int']['output']
cpuInfo: Scalars['String']['output']
device: Scalars['String']['output']
- gpuDevices: Array
kind: WorkerKind
name: Scalars['String']['output']
}
@@ -71,7 +88,13 @@ export type GetWorkersQuery = {
arch: string
cpuInfo: string
cpuCount: number
- gpuDevices: Array
+ accelerators: Array<{
+ __typename?: 'Accelerator'
+ uuid?: string | null
+ chipName?: string | null
+ displayName: string
+ deviceType: DeviceType
+ }>
}>
}
@@ -105,7 +128,28 @@ export const GetWorkersDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'arch' } },
{ kind: 'Field', name: { kind: 'Name', value: 'cpuInfo' } },
{ kind: 'Field', name: { kind: 'Name', value: 'cpuCount' } },
- { kind: 'Field', name: { kind: 'Name', value: 'gpuDevices' } }
+ {
+ kind: 'Field',
+ name: { kind: 'Name', value: 'accelerators' },
+ selectionSet: {
+ kind: 'SelectionSet',
+ selections: [
+ { kind: 'Field', name: { kind: 'Name', value: 'uuid' } },
+ {
+ kind: 'Field',
+ name: { kind: 'Name', value: 'chipName' }
+ },
+ {
+ kind: 'Field',
+ name: { kind: 'Name', value: 'displayName' }
+ },
+ {
+ kind: 'Field',
+ name: { kind: 'Name', value: 'deviceType' }
+ }
+ ]
+ }
+ }
]
}
}
diff --git a/ee/tabby-ui/lib/gql/request-documents.tsx b/ee/tabby-ui/lib/gql/request-documents.tsx
index 01310aad6d8..7caade040b2 100644
--- a/ee/tabby-ui/lib/gql/request-documents.tsx
+++ b/ee/tabby-ui/lib/gql/request-documents.tsx
@@ -1,4 +1,4 @@
-import {graphql} from './generates'
+import { graphql } from './generates'
export const getAllWorkersDocument = graphql(/* GraphQL */ `
query GetWorkers {
@@ -10,7 +10,12 @@ export const getAllWorkersDocument = graphql(/* GraphQL */ `
arch
cpuInfo
cpuCount
- gpuDevices
+ accelerators {
+ uuid
+ chipName
+ displayName
+ deviceType
+ }
}
}
`)
diff --git a/ee/tabby-ui/lib/hooks/use-health.tsx b/ee/tabby-ui/lib/hooks/use-health.tsx
index 2d6bed2a4c1..33633794063 100644
--- a/ee/tabby-ui/lib/hooks/use-health.tsx
+++ b/ee/tabby-ui/lib/hooks/use-health.tsx
@@ -1,16 +1,23 @@
'use client'
import useSWRImmutable from 'swr/immutable'
-import {SWRResponse} from 'swr'
+import { SWRResponse } from 'swr'
import fetcher from '@/lib/tabby-fetcher'
+export interface Accelerator {
+ uuid?: string;
+ chip_name?: string;
+ display_name: string;
+ device_type: 'Cuda' | 'Rocm';
+}
+
export interface HealthInfo {
device: 'metal' | 'cpu' | 'cuda' | 'rocm'
model?: string
chat_model?: string
cpu_info: string
cpu_count: number
- gpu_devices: string[]
+ accelerators: Accelerator[]
version: {
build_date: string
git_describe: string
diff --git a/ee/tabby-ui/lib/hooks/use-workers.ts b/ee/tabby-ui/lib/hooks/use-workers.ts
index 94bdc52b3e6..d59875566f7 100644
--- a/ee/tabby-ui/lib/hooks/use-workers.ts
+++ b/ee/tabby-ui/lib/hooks/use-workers.ts
@@ -1,9 +1,10 @@
import React from 'react'
-import {findIndex, groupBy, slice} from 'lodash-es'
-import {Worker, WorkerKind} from '@/lib/gql/generates/graphql'
-import {getAllWorkersDocument} from '@/lib/gql/request-documents'
-import {useGraphQL} from './use-graphql'
-import type {HealthInfo} from './use-health'
+import { findIndex, groupBy, slice } from 'lodash-es'
+import { Worker, WorkerKind } from '@/lib/gql/generates/graphql'
+import { getAllWorkersDocument } from '@/lib/gql/request-documents'
+import { useGraphQL } from './use-graphql'
+import type { HealthInfo } from './use-health'
+import { deviceTypeMap } from "@/lib/utils";
const modelNameMap: Record = {
[WorkerKind.Chat]: 'chat_model',
@@ -22,7 +23,12 @@ function transformHealthInfoToWorker(
cpuInfo: healthInfo.cpu_info,
name: healthInfo?.[modelNameMap[kind]] ?? '',
cpuCount: healthInfo.cpu_count,
- gpuDevices: healthInfo.gpu_devices
+ accelerators: healthInfo.accelerators.map(x => ({
+ uuid: x.uuid,
+ chipName: x.chip_name,
+ displayName: x.display_name,
+ deviceType: deviceTypeMap[x.device_type],
+ }))
}
}
diff --git a/ee/tabby-ui/lib/utils.ts b/ee/tabby-ui/lib/utils.ts
index bfe780c22ea..d9b14736d19 100644
--- a/ee/tabby-ui/lib/utils.ts
+++ b/ee/tabby-ui/lib/utils.ts
@@ -1,6 +1,12 @@
-import { clsx, type ClassValue } from 'clsx'
+import { type ClassValue, clsx } from 'clsx'
import { customAlphabet } from 'nanoid'
import { twMerge } from 'tailwind-merge'
+import { DeviceType } from "@/lib/gql/generates/graphql";
+
+export const deviceTypeMap: Record<'Cuda' | 'Rocm', DeviceType> = {
+ Cuda: DeviceType.Cuda,
+ Rocm: DeviceType.Rocm,
+}
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
diff --git a/ee/tabby-webserver/graphql/schema.graphql b/ee/tabby-webserver/graphql/schema.graphql
index 364c0145f0b..0829bbd6346 100644
--- a/ee/tabby-webserver/graphql/schema.graphql
+++ b/ee/tabby-webserver/graphql/schema.graphql
@@ -7,6 +7,17 @@ type Mutation {
resetRegistrationToken: String!
}
+type Accelerator {
+ "Universally unique ID of the accelerator, if available"
+ uuid: String
+ "Technical name of the underlying hardware chip, if available"
+ chipName: String
+ "User readable name for the accelerator"
+ displayName: String!
+ "Type of the accelerator device"
+ deviceType: DeviceType!
+}
+
type Query {
workers: [Worker!]!
registrationToken: String!
@@ -20,7 +31,12 @@ type Worker {
arch: String!
cpuInfo: String!
cpuCount: Int!
- gpuDevices: [String!]!
+ accelerators: [Accelerator!]!
+}
+
+enum DeviceType {
+ CUDA
+ ROCM
}
schema {
diff --git a/ee/tabby-webserver/src/api.rs b/ee/tabby-webserver/src/api.rs
index d3b0268a04b..ff49d6d1868 100644
--- a/ee/tabby-webserver/src/api.rs
+++ b/ee/tabby-webserver/src/api.rs
@@ -1,13 +1,13 @@
use async_trait::async_trait;
use juniper::{GraphQLEnum, GraphQLObject};
use serde::{Deserialize, Serialize};
-use thiserror::Error;
-use tokio_tungstenite::connect_async;
-
use tabby_common::api::{
+ accelerator::Accelerator,
code::{CodeSearch, CodeSearchError, SearchResponse},
event::RawEventLogger,
};
+use thiserror::Error;
+use tokio_tungstenite::connect_async;
use crate::websocket::WebSocketTransport;
@@ -26,7 +26,7 @@ pub struct Worker {
pub arch: String,
pub cpu_info: String,
pub cpu_count: i32,
- pub gpu_devices: Vec,
+ pub accelerators: Vec,
}
#[derive(Serialize, Deserialize, Error, Debug)]
@@ -51,7 +51,7 @@ pub trait Hub {
arch: String,
cpu_info: String,
cpu_count: i32,
- gpu_devices: Vec,
+ accelerators: Vec,
token: String,
) -> Result;
diff --git a/ee/tabby-webserver/src/lib.rs b/ee/tabby-webserver/src/lib.rs
index 856eb364362..c993349ed60 100644
--- a/ee/tabby-webserver/src/lib.rs
+++ b/ee/tabby-webserver/src/lib.rs
@@ -1,5 +1,6 @@
use std::{net::SocketAddr, sync::Arc};
+use api::{Hub, RegisterWorkerError, Worker, WorkerKind};
use axum::{
extract::{ws::WebSocket, ConnectInfo, State, WebSocketUpgrade},
http::Request,
@@ -8,19 +9,18 @@ use axum::{
routing, Extension, Router,
};
use hyper::Body;
-use tarpc::server::{BaseChannel, Channel};
-use tokio::sync::Mutex;
-use tracing::{error, warn};
-
-use api::{Hub, RegisterWorkerError, Worker, WorkerKind};
use juniper_axum::{graphiql, graphql, playground};
pub use schema::create_schema;
use schema::Schema;
use server::ServerContext;
use tabby_common::api::{
+ accelerator::Accelerator,
code::{CodeSearch, SearchResponse},
event::RawEventLogger,
};
+use tarpc::server::{BaseChannel, Channel};
+use tokio::sync::Mutex;
+use tracing::{error, warn};
use websocket::WebSocketTransport;
pub mod api;
@@ -126,7 +126,7 @@ impl Hub for Arc {
arch: String,
cpu_info: String,
cpu_count: i32,
- gpu_devices: Vec,
+ accelerators: Vec,
token: String,
) -> Result {
if token.is_empty() {
@@ -165,7 +165,7 @@ impl Hub for Arc {
arch,
cpu_info,
cpu_count,
- gpu_devices,
+ accelerators,
};
self.ctx.register_worker(worker).await
}
diff --git a/ee/tabby-webserver/ui/404.html b/ee/tabby-webserver/ui/404.html
index a6b8a79e13a..8782c42959a 100644
--- a/ee/tabby-webserver/ui/404.html
+++ b/ee/tabby-webserver/ui/404.html
@@ -1 +1 @@
-404: This page could not be found. Tabby
404
This page could not be found.
\ No newline at end of file
+404: This page could not be found. Tabby
404
This page could not be found.
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/967-77bee9da62f91e7a.js b/ee/tabby-webserver/ui/_next/static/chunks/967-77bee9da62f91e7a.js
new file mode 100644
index 00000000000..3b142ce9c28
--- /dev/null
+++ b/ee/tabby-webserver/ui/_next/static/chunks/967-77bee9da62f91e7a.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[967],{93023:function(n,e,t){t.d(e,{d:function(){return s},z:function(){return c}});var r=t(57437),i=t(2265),a=t(67256),l=t(7404),o=t(39311);let s=(0,l.j)("inline-flex items-center justify-center rounded-md text-sm font-medium shadow ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",{variants:{variant:{default:"bg-primary text-primary-foreground shadow-md hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground hover:bg-destructive/90",outline:"border border-input hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"shadow-none hover:bg-accent hover:text-accent-foreground",link:"text-primary underline-offset-4 shadow-none hover:underline"},size:{default:"h-8 px-4 py-2",sm:"h-8 rounded-md px-3",lg:"h-11 rounded-md px-8",icon:"h-8 w-8 p-0"}},defaultVariants:{variant:"default",size:"default"}}),c=i.forwardRef((n,e)=>{let{className:t,variant:i,size:l,asChild:c=!1,...u}=n,d=c?a.g7:"button";return(0,r.jsx)(d,{className:(0,o.cn)(s({variant:i,size:l,className:t})),ref:e,...u})});c.displayName="Button"},84168:function(n,e,t){t.d(e,{BD:function(){return l},C9:function(){return f},Dj:function(){return g},Ec:function(){return o},IT:function(){return d},Mr:function(){return a},NO:function(){return x},O3:function(){return w},Qs:function(){return C},SC:function(){return c},bM:function(){return p},f7:function(){return s},gx:function(){return k},sW:function(){return N},tr:function(){return h},vU:function(){return m},vq:function(){return u},yl:function(){return j},zu:function(){return v}});var r=t(57437);t(2265);var i=t(39311);function a(n){let{className:e,...t}=n;return(0,r.jsxs)("svg",{role:"img",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:[(0,r.jsx)("title",{children:"GitHub"}),(0,r.jsx)("path",{d:"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"})]})}function l(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"m205.66 149.66-72 72a8 8 0 0 1-11.32 0l-72-72a8 8 0 0 1 11.32-11.32L120 196.69V40a8 8 0 0 1 16 0v156.69l58.34-58.35a8 8 0 0 1 11.32 11.32Z"})})}function o(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"m221.66 133.66-72 72a8 8 0 0 1-11.32-11.32L196.69 136H40a8 8 0 0 1 0-16h156.69l-58.35-58.34a8 8 0 0 1 11.32-11.32l72 72a8 8 0 0 1 0 11.32Z"})})}function s(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M230.92 212c-15.23-26.33-38.7-45.21-66.09-54.16a72 72 0 1 0-73.66 0c-27.39 8.94-50.86 27.82-66.09 54.16a8 8 0 1 0 13.85 8c18.84-32.56 52.14-52 89.07-52s70.23 19.44 89.07 52a8 8 0 1 0 13.85-8ZM72 96a56 56 0 1 1 56 56 56.06 56.06 0 0 1-56-56Z"})})}function c(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M224 128a8 8 0 0 1-8 8h-80v80a8 8 0 0 1-16 0v-80H40a8 8 0 0 1 0-16h80V40a8 8 0 0 1 16 0v80h80a8 8 0 0 1 8 8Z"})})}function u(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M200 32v144a8 8 0 0 1-8 8H67.31l34.35 34.34a8 8 0 0 1-11.32 11.32l-48-48a8 8 0 0 1 0-11.32l48-48a8 8 0 0 1 11.32 11.32L67.31 168H184V32a8 8 0 0 1 16 0Z"})})}function d(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M216 48h-40v-8a24 24 0 0 0-24-24h-48a24 24 0 0 0-24 24v8H40a8 8 0 0 0 0 16h8v144a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16V64h8a8 8 0 0 0 0-16ZM96 40a8 8 0 0 1 8-8h48a8 8 0 0 1 8 8v8H96Zm96 168H64V64h128Zm-80-104v64a8 8 0 0 1-16 0v-64a8 8 0 0 1 16 0Zm48 0v64a8 8 0 0 1-16 0v-64a8 8 0 0 1 16 0Z"})})}function h(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M197.67 186.37a8 8 0 0 1 0 11.29C196.58 198.73 170.82 224 128 224c-37.39 0-64.53-22.4-80-39.85V208a8 8 0 0 1-16 0v-48a8 8 0 0 1 8-8h48a8 8 0 0 1 0 16H55.44C67.76 183.35 93 208 128 208c36 0 58.14-21.46 58.36-21.68a8 8 0 0 1 11.31.05ZM216 40a8 8 0 0 0-8 8v23.85C192.53 54.4 165.39 32 128 32c-42.82 0-68.58 25.27-69.66 26.34a8 8 0 0 0 11.3 11.34C69.86 69.46 92 48 128 48c35 0 60.24 24.65 72.56 40H168a8 8 0 0 0 0 16h48a8 8 0 0 0 8-8V48a8 8 0 0 0-8-8Z"})})}function v(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24Zm0 192a88 88 0 1 1 88-88 88.1 88.1 0 0 1-88 88Zm24-120h-48a8 8 0 0 0-8 8v48a8 8 0 0 0 8 8h48a8 8 0 0 0 8-8v-48a8 8 0 0 0-8-8Zm-8 48h-32v-32h32Z"})})}function f(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M233.54 142.23a8 8 0 0 0-8-2 88.08 88.08 0 0 1-109.8-109.8 8 8 0 0 0-10-10 104.84 104.84 0 0 0-52.91 37A104 104 0 0 0 136 224a103.09 103.09 0 0 0 62.52-20.88 104.84 104.84 0 0 0 37-52.91 8 8 0 0 0-1.98-7.98Zm-44.64 48.11A88 88 0 0 1 65.66 67.11a89 89 0 0 1 31.4-26A106 106 0 0 0 96 56a104.11 104.11 0 0 0 104 104 106 106 0 0 0 14.92-1.06 89 89 0 0 1-26.02 31.4Z"})})}function w(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M120 40V16a8 8 0 0 1 16 0v24a8 8 0 0 1-16 0Zm72 88a64 64 0 1 1-64-64 64.07 64.07 0 0 1 64 64Zm-16 0a48 48 0 1 0-48 48 48.05 48.05 0 0 0 48-48ZM58.34 69.66a8 8 0 0 0 11.32-11.32l-16-16a8 8 0 0 0-11.32 11.32Zm0 116.68-16 16a8 8 0 0 0 11.32 11.32l16-16a8 8 0 0 0-11.32-11.32ZM192 72a8 8 0 0 0 5.66-2.34l16-16a8 8 0 0 0-11.32-11.32l-16 16A8 8 0 0 0 192 72Zm5.66 114.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32-11.32ZM48 128a8 8 0 0 0-8-8H16a8 8 0 0 0 0 16h24a8 8 0 0 0 8-8Zm80 80a8 8 0 0 0-8 8v24a8 8 0 0 0 16 0v-24a8 8 0 0 0-8-8Zm112-88h-24a8 8 0 0 0 0 16h24a8 8 0 0 0 0-16Z"})})}function m(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M216 32H88a8 8 0 0 0-8 8v40H40a8 8 0 0 0-8 8v128a8 8 0 0 0 8 8h128a8 8 0 0 0 8-8v-40h40a8 8 0 0 0 8-8V40a8 8 0 0 0-8-8Zm-56 176H48V96h112Zm48-48h-32V88a8 8 0 0 0-8-8H96V48h112Z"})})}function x(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"m229.66 77.66-128 128a8 8 0 0 1-11.32 0l-56-56a8 8 0 0 1 11.32-11.32L96 188.69 218.34 66.34a8 8 0 0 1 11.32 11.32Z"})})}function g(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M224 152v56a16 16 0 0 1-16 16H48a16 16 0 0 1-16-16v-56a8 8 0 0 1 16 0v56h160v-56a8 8 0 0 1 16 0Zm-101.66 5.66a8 8 0 0 0 11.32 0l40-40a8 8 0 0 0-11.32-11.32L136 132.69V40a8 8 0 0 0-16 0v92.69l-26.34-26.35a8 8 0 0 0-11.32 11.32Z"})})}function p(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{d:"M205.66 194.34a8 8 0 0 1-11.32 11.32L128 139.31l-66.34 66.35a8 8 0 0 1-11.32-11.32L116.69 128 50.34 61.66a8 8 0 0 1 11.32-11.32L128 116.69l66.34-66.35a8 8 0 0 1 11.32 11.32L139.31 128Z"})})}function j(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:(0,i.cn)("h-4 w-4",e),...t,children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"})})}function k(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",className:(0,i.cn)("h-4 w-4",e),viewBox:"0 0 270 270",...t,children:(0,r.jsxs)("g",{children:[(0,r.jsxs)("g",{children:[(0,r.jsx)("path",{style:{fill:"#E01E5A"},d:"M99.4,151.2c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9h12.9V151.2z"}),(0,r.jsx)("path",{style:{fill:"#E01E5A"},d:"M105.9,151.2c0-7.1,5.8-12.9,12.9-12.9s12.9,5.8,12.9,12.9v32.3c0,7.1-5.8,12.9-12.9,12.9 s-12.9-5.8-12.9-12.9V151.2z"})]}),(0,r.jsxs)("g",{children:[(0,r.jsx)("path",{style:{fill:"#36C5F0"},d:"M118.8,99.4c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9s12.9,5.8,12.9,12.9v12.9H118.8z"}),(0,r.jsx)("path",{style:{fill:"#36C5F0"},d:"M118.8,105.9c7.1,0,12.9,5.8,12.9,12.9s-5.8,12.9-12.9,12.9H86.5c-7.1,0-12.9-5.8-12.9-12.9 s5.8-12.9,12.9-12.9H118.8z"})]}),(0,r.jsxs)("g",{children:[(0,r.jsx)("path",{style:{fill:"#2EB67D"},d:"M170.6,118.8c0-7.1,5.8-12.9,12.9-12.9c7.1,0,12.9,5.8,12.9,12.9s-5.8,12.9-12.9,12.9h-12.9V118.8z"}),(0,r.jsx)("path",{style:{fill:"#2EB67D"},d:"M164.1,118.8c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9V86.5c0-7.1,5.8-12.9,12.9-12.9 c7.1,0,12.9,5.8,12.9,12.9V118.8z"})]}),(0,r.jsxs)("g",{children:[(0,r.jsx)("path",{style:{fill:"#ECB22E"},d:"M151.2,170.6c7.1,0,12.9,5.8,12.9,12.9c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9v-12.9H151.2z"}),(0,r.jsx)("path",{style:{fill:"#ECB22E"},d:"M151.2,164.1c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9h32.3c7.1,0,12.9,5.8,12.9,12.9 c0,7.1-5.8,12.9-12.9,12.9H151.2z"})]})]})})}function C(n){let{className:e,...t}=n;return(0,r.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:(0,i.cn)("h-4 w-4",e),viewBox:"0 0 24 24",...t,children:[(0,r.jsx)("path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"}),(0,r.jsx)("path",{d:"M12 9v4"}),(0,r.jsx)("path",{d:"M12 17h.01"})]})}function N(n){let{className:e,...t}=n;return(0,r.jsx)("svg",{width:"16",height:"16",viewBox:"0 0 16 16",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",...t,children:(0,r.jsx)("path",{d:"M13.51 4l-5-3h-1l-5 3-.49.86v6l.49.85 5 3h1l5-3 .49-.85v-6L13.51 4zm-6 9.56l-4.5-2.7V5.7l4.5 2.45v5.41zM3.27 4.7l4.74-2.84 4.74 2.84-4.74 2.59L3.27 4.7zm9.74 6.16l-4.5 2.7V8.15l4.5-2.45v5.16z"})})}},70349:function(n,e,t){var r,i,a,l;t.d(e,{Yi:function(){return r},bh:function(){return s},d3:function(){return o},xj:function(){return i}}),(a=r||(r={})).Cuda="CUDA",a.Rocm="ROCM",(l=i||(i={})).Chat="CHAT",l.Completion="COMPLETION";let o={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetWorkers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"workers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"kind"}},{kind:"Field",name:{kind:"Name",value:"name"}},{kind:"Field",name:{kind:"Name",value:"addr"}},{kind:"Field",name:{kind:"Name",value:"device"}},{kind:"Field",name:{kind:"Name",value:"arch"}},{kind:"Field",name:{kind:"Name",value:"cpuInfo"}},{kind:"Field",name:{kind:"Name",value:"cpuCount"}},{kind:"Field",name:{kind:"Name",value:"accelerators"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"uuid"}},{kind:"Field",name:{kind:"Name",value:"chipName"}},{kind:"Field",name:{kind:"Name",value:"displayName"}},{kind:"Field",name:{kind:"Name",value:"deviceType"}}]}}]}}]}}]},s={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetRegistrationToken"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"registrationToken"}}]}}]}},97605:function(n,e,t){t.d(e,{Z:function(){return r}});function r(n){return fetch(n).then(n=>n.json())}},39311:function(n,e,t){t.d(e,{aF:function(){return u},cn:function(){return s},uY:function(){return o},x0:function(){return c}});var r=t(50348),i=t(28481),a=t(23986),l=t(70349);let o={Cuda:l.Yi.Cuda,Rocm:l.Yi.Rocm};function s(){for(var n=arguments.length,e=Array(n),t=0;t1&&void 0!==arguments[1]?arguments[1]:50,t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/[ ,.:;\n,。:;]/;if(!n)return"";if(n.length<=e)return n;let r=n.slice(0,e),i=-1;for(let n=e-1;n>=0;n--)if(t.test(r[n])){i=n;break}return -1!==i&&(r=r.slice(0,i)),r+"..."}}}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/967-f02728ac0b1b01a8.js b/ee/tabby-webserver/ui/_next/static/chunks/967-f02728ac0b1b01a8.js
deleted file mode 100644
index 1feffdee79c..00000000000
--- a/ee/tabby-webserver/ui/_next/static/chunks/967-f02728ac0b1b01a8.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[967],{93023:function(n,t,r){r.d(t,{d:function(){return c},z:function(){return i}});var e=r(57437),l=r(2265),s=r(67256),a=r(7404),o=r(39311);let c=(0,a.j)("inline-flex items-center justify-center rounded-md text-sm font-medium shadow ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",{variants:{variant:{default:"bg-primary text-primary-foreground shadow-md hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground hover:bg-destructive/90",outline:"border border-input hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"shadow-none hover:bg-accent hover:text-accent-foreground",link:"text-primary underline-offset-4 shadow-none hover:underline"},size:{default:"h-8 px-4 py-2",sm:"h-8 rounded-md px-3",lg:"h-11 rounded-md px-8",icon:"h-8 w-8 p-0"}},defaultVariants:{variant:"default",size:"default"}}),i=l.forwardRef((n,t)=>{let{className:r,variant:l,size:a,asChild:i=!1,...u}=n,h=i?s.g7:"button";return(0,e.jsx)(h,{className:(0,o.cn)(c({variant:l,size:a,className:r})),ref:t,...u})});i.displayName="Button"},84168:function(n,t,r){r.d(t,{BD:function(){return a},C9:function(){return f},Dj:function(){return m},Ec:function(){return o},IT:function(){return h},Mr:function(){return s},NO:function(){return g},O3:function(){return d},Qs:function(){return M},SC:function(){return i},bM:function(){return p},f7:function(){return c},gx:function(){return Z},sW:function(){return C},tr:function(){return v},vU:function(){return x},vq:function(){return u},yl:function(){return j},zu:function(){return w}});var e=r(57437);r(2265);var l=r(39311);function s(n){let{className:t,...r}=n;return(0,e.jsxs)("svg",{role:"img",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:[(0,e.jsx)("title",{children:"GitHub"}),(0,e.jsx)("path",{d:"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"})]})}function a(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"m205.66 149.66-72 72a8 8 0 0 1-11.32 0l-72-72a8 8 0 0 1 11.32-11.32L120 196.69V40a8 8 0 0 1 16 0v156.69l58.34-58.35a8 8 0 0 1 11.32 11.32Z"})})}function o(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"m221.66 133.66-72 72a8 8 0 0 1-11.32-11.32L196.69 136H40a8 8 0 0 1 0-16h156.69l-58.35-58.34a8 8 0 0 1 11.32-11.32l72 72a8 8 0 0 1 0 11.32Z"})})}function c(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M230.92 212c-15.23-26.33-38.7-45.21-66.09-54.16a72 72 0 1 0-73.66 0c-27.39 8.94-50.86 27.82-66.09 54.16a8 8 0 1 0 13.85 8c18.84-32.56 52.14-52 89.07-52s70.23 19.44 89.07 52a8 8 0 1 0 13.85-8ZM72 96a56 56 0 1 1 56 56 56.06 56.06 0 0 1-56-56Z"})})}function i(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M224 128a8 8 0 0 1-8 8h-80v80a8 8 0 0 1-16 0v-80H40a8 8 0 0 1 0-16h80V40a8 8 0 0 1 16 0v80h80a8 8 0 0 1 8 8Z"})})}function u(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M200 32v144a8 8 0 0 1-8 8H67.31l34.35 34.34a8 8 0 0 1-11.32 11.32l-48-48a8 8 0 0 1 0-11.32l48-48a8 8 0 0 1 11.32 11.32L67.31 168H184V32a8 8 0 0 1 16 0Z"})})}function h(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M216 48h-40v-8a24 24 0 0 0-24-24h-48a24 24 0 0 0-24 24v8H40a8 8 0 0 0 0 16h8v144a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16V64h8a8 8 0 0 0 0-16ZM96 40a8 8 0 0 1 8-8h48a8 8 0 0 1 8 8v8H96Zm96 168H64V64h128Zm-80-104v64a8 8 0 0 1-16 0v-64a8 8 0 0 1 16 0Zm48 0v64a8 8 0 0 1-16 0v-64a8 8 0 0 1 16 0Z"})})}function v(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M197.67 186.37a8 8 0 0 1 0 11.29C196.58 198.73 170.82 224 128 224c-37.39 0-64.53-22.4-80-39.85V208a8 8 0 0 1-16 0v-48a8 8 0 0 1 8-8h48a8 8 0 0 1 0 16H55.44C67.76 183.35 93 208 128 208c36 0 58.14-21.46 58.36-21.68a8 8 0 0 1 11.31.05ZM216 40a8 8 0 0 0-8 8v23.85C192.53 54.4 165.39 32 128 32c-42.82 0-68.58 25.27-69.66 26.34a8 8 0 0 0 11.3 11.34C69.86 69.46 92 48 128 48c35 0 60.24 24.65 72.56 40H168a8 8 0 0 0 0 16h48a8 8 0 0 0 8-8V48a8 8 0 0 0-8-8Z"})})}function w(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24Zm0 192a88 88 0 1 1 88-88 88.1 88.1 0 0 1-88 88Zm24-120h-48a8 8 0 0 0-8 8v48a8 8 0 0 0 8 8h48a8 8 0 0 0 8-8v-48a8 8 0 0 0-8-8Zm-8 48h-32v-32h32Z"})})}function f(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M233.54 142.23a8 8 0 0 0-8-2 88.08 88.08 0 0 1-109.8-109.8 8 8 0 0 0-10-10 104.84 104.84 0 0 0-52.91 37A104 104 0 0 0 136 224a103.09 103.09 0 0 0 62.52-20.88 104.84 104.84 0 0 0 37-52.91 8 8 0 0 0-1.98-7.98Zm-44.64 48.11A88 88 0 0 1 65.66 67.11a89 89 0 0 1 31.4-26A106 106 0 0 0 96 56a104.11 104.11 0 0 0 104 104 106 106 0 0 0 14.92-1.06 89 89 0 0 1-26.02 31.4Z"})})}function d(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M120 40V16a8 8 0 0 1 16 0v24a8 8 0 0 1-16 0Zm72 88a64 64 0 1 1-64-64 64.07 64.07 0 0 1 64 64Zm-16 0a48 48 0 1 0-48 48 48.05 48.05 0 0 0 48-48ZM58.34 69.66a8 8 0 0 0 11.32-11.32l-16-16a8 8 0 0 0-11.32 11.32Zm0 116.68-16 16a8 8 0 0 0 11.32 11.32l16-16a8 8 0 0 0-11.32-11.32ZM192 72a8 8 0 0 0 5.66-2.34l16-16a8 8 0 0 0-11.32-11.32l-16 16A8 8 0 0 0 192 72Zm5.66 114.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32-11.32ZM48 128a8 8 0 0 0-8-8H16a8 8 0 0 0 0 16h24a8 8 0 0 0 8-8Zm80 80a8 8 0 0 0-8 8v24a8 8 0 0 0 16 0v-24a8 8 0 0 0-8-8Zm112-88h-24a8 8 0 0 0 0 16h24a8 8 0 0 0 0-16Z"})})}function x(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M216 32H88a8 8 0 0 0-8 8v40H40a8 8 0 0 0-8 8v128a8 8 0 0 0 8 8h128a8 8 0 0 0 8-8v-40h40a8 8 0 0 0 8-8V40a8 8 0 0 0-8-8Zm-56 176H48V96h112Zm48-48h-32V88a8 8 0 0 0-8-8H96V48h112Z"})})}function g(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"m229.66 77.66-128 128a8 8 0 0 1-11.32 0l-56-56a8 8 0 0 1 11.32-11.32L96 188.69 218.34 66.34a8 8 0 0 1 11.32 11.32Z"})})}function m(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M224 152v56a16 16 0 0 1-16 16H48a16 16 0 0 1-16-16v-56a8 8 0 0 1 16 0v56h160v-56a8 8 0 0 1 16 0Zm-101.66 5.66a8 8 0 0 0 11.32 0l40-40a8 8 0 0 0-11.32-11.32L136 132.69V40a8 8 0 0 0-16 0v92.69l-26.34-26.35a8 8 0 0 0-11.32 11.32Z"})})}function p(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 256 256",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{d:"M205.66 194.34a8 8 0 0 1-11.32 11.32L128 139.31l-66.34 66.35a8 8 0 0 1-11.32-11.32L116.69 128 50.34 61.66a8 8 0 0 1 11.32-11.32L128 116.69l66.34-66.35a8 8 0 0 1 11.32 11.32L139.31 128Z"})})}function j(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:(0,l.cn)("h-4 w-4",t),...r,children:(0,e.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"})})}function Z(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",className:(0,l.cn)("h-4 w-4",t),viewBox:"0 0 270 270",...r,children:(0,e.jsxs)("g",{children:[(0,e.jsxs)("g",{children:[(0,e.jsx)("path",{style:{fill:"#E01E5A"},d:"M99.4,151.2c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9h12.9V151.2z"}),(0,e.jsx)("path",{style:{fill:"#E01E5A"},d:"M105.9,151.2c0-7.1,5.8-12.9,12.9-12.9s12.9,5.8,12.9,12.9v32.3c0,7.1-5.8,12.9-12.9,12.9 s-12.9-5.8-12.9-12.9V151.2z"})]}),(0,e.jsxs)("g",{children:[(0,e.jsx)("path",{style:{fill:"#36C5F0"},d:"M118.8,99.4c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9s12.9,5.8,12.9,12.9v12.9H118.8z"}),(0,e.jsx)("path",{style:{fill:"#36C5F0"},d:"M118.8,105.9c7.1,0,12.9,5.8,12.9,12.9s-5.8,12.9-12.9,12.9H86.5c-7.1,0-12.9-5.8-12.9-12.9 s5.8-12.9,12.9-12.9H118.8z"})]}),(0,e.jsxs)("g",{children:[(0,e.jsx)("path",{style:{fill:"#2EB67D"},d:"M170.6,118.8c0-7.1,5.8-12.9,12.9-12.9c7.1,0,12.9,5.8,12.9,12.9s-5.8,12.9-12.9,12.9h-12.9V118.8z"}),(0,e.jsx)("path",{style:{fill:"#2EB67D"},d:"M164.1,118.8c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9V86.5c0-7.1,5.8-12.9,12.9-12.9 c7.1,0,12.9,5.8,12.9,12.9V118.8z"})]}),(0,e.jsxs)("g",{children:[(0,e.jsx)("path",{style:{fill:"#ECB22E"},d:"M151.2,170.6c7.1,0,12.9,5.8,12.9,12.9c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9v-12.9H151.2z"}),(0,e.jsx)("path",{style:{fill:"#ECB22E"},d:"M151.2,164.1c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9h32.3c7.1,0,12.9,5.8,12.9,12.9 c0,7.1-5.8,12.9-12.9,12.9H151.2z"})]})]})})}function M(n){let{className:t,...r}=n;return(0,e.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:(0,l.cn)("h-4 w-4",t),viewBox:"0 0 24 24",...r,children:[(0,e.jsx)("path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"}),(0,e.jsx)("path",{d:"M12 9v4"}),(0,e.jsx)("path",{d:"M12 17h.01"})]})}function C(n){let{className:t,...r}=n;return(0,e.jsx)("svg",{width:"16",height:"16",viewBox:"0 0 16 16",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",...r,children:(0,e.jsx)("path",{d:"M13.51 4l-5-3h-1l-5 3-.49.86v6l.49.85 5 3h1l5-3 .49-.85v-6L13.51 4zm-6 9.56l-4.5-2.7V5.7l4.5 2.45v5.41zM3.27 4.7l4.74-2.84 4.74 2.84-4.74 2.59L3.27 4.7zm9.74 6.16l-4.5 2.7V8.15l4.5-2.45v5.16z"})})}},97605:function(n,t,r){r.d(t,{Z:function(){return e}});function e(n){return fetch(n).then(n=>n.json())}},39311:function(n,t,r){r.d(t,{aF:function(){return c},cn:function(){return a},x0:function(){return o}});var e=r(50348),l=r(28481),s=r(23986);function a(){for(var n=arguments.length,t=Array(n),r=0;r1&&void 0!==arguments[1]?arguments[1]:50,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/[ ,.:;\n,。:;]/;if(!n)return"";if(n.length<=t)return n;let e=n.slice(0,t),l=-1;for(let n=t-1;n>=0;n--)if(r.test(e[n])){l=n;break}return -1!==l&&(e=e.slice(0,l)),e+"..."}}}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js
deleted file mode 100644
index b4ab5d2d122..00000000000
--- a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js
+++ /dev/null
@@ -1 +0,0 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[642],{95926:function(e,t,n){Promise.resolve().then(n.bind(n,30831))},30831:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return c}});var r=n(57437),s=n(39311),i=n(7404),l=n(61396),o=n.n(l),a=n(24033);function c(e){let{children:t,className:n}=e;return(0,r.jsxs)("div",{className:(0,s.cn)("grid overflow-hidden lg:grid-cols-[280px_1fr]",n),children:[(0,r.jsx)("div",{className:"hidden border-r bg-zinc-100/40 dark:bg-zinc-800/40 lg:block",children:(0,r.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,r.jsx)("div",{className:"h-[12px]"}),(0,r.jsx)("div",{className:"flex-1",children:(0,r.jsxs)("nav",{className:"grid items-start gap-4 px-4 text-sm font-medium",children:[(0,r.jsxs)(h,{href:"/",children:[(0,r.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-4 w-4",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("path",{d:"m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}),(0,r.jsx)("polyline",{points:"9 22 9 12 15 12 15 22"})]}),"Home"]}),(0,r.jsxs)(h,{href:"/swagger",children:[(0,r.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-4 w-4",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,r.jsx)("path",{d:"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"}),(0,r.jsx)("path",{d:"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"}),(0,r.jsx)("path",{d:"M6 8h2"}),(0,r.jsx)("path",{d:"M6 12h2"}),(0,r.jsx)("path",{d:"M16 8h2"}),(0,r.jsx)("path",{d:"M16 12h2"})]}),"Swagger"]})]})})]})}),(0,r.jsx)("div",{className:"flex flex-1 flex-col overflow-auto",children:t})]})}let d=(0,i.j)("flex items-center gap-3 rounded-lg px-3 py-2 text-zinc-900 transition-all hover:text-zinc-900 dark:text-zinc-50 dark:hover:text-zinc-50",{variants:{state:{selected:"bg-zinc-200 dark:bg-zinc-800","not-selected":""}},defaultVariants:{state:"not-selected"}});function h(e){let{href:t,children:n}=e,s=(0,a.usePathname)();return(0,r.jsx)(o(),{className:d({state:s==t?"selected":"not-selected"}),href:t,children:n})}},39311:function(e,t,n){"use strict";n.d(t,{aF:function(){return a},cn:function(){return l},x0:function(){return o}});var r=n(50348),s=n(28481),i=n(23986);function l(){for(var e=arguments.length,t=Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:50,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/[ ,.:;\n,。:;]/;if(!e)return"";if(e.length<=t)return e;let r=e.slice(0,t),s=-1;for(let e=t-1;e>=0;e--)if(n.test(r[e])){s=e;break}return -1!==s&&(r=r.slice(0,s)),r+"..."}},67650:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"RouterContext",{enumerable:!0,get:function(){return i}});let r=n(21024),s=r._(n(2265)),i=s.default.createContext(null)},24033:function(e,t,n){e.exports=n(20290)}},function(e){e.O(0,[882,396,971,864,744],function(){return e(e.s=95926)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-d5a067a319c8b1d7.js b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-d5a067a319c8b1d7.js
new file mode 100644
index 00000000000..4840828f70a
--- /dev/null
+++ b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/layout-d5a067a319c8b1d7.js
@@ -0,0 +1 @@
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[642],{95926:function(e,n,i){Promise.resolve().then(i.bind(i,30831))},30831:function(e,n,i){"use strict";i.r(n),i.d(n,{default:function(){return o}});var t=i(57437),a=i(39311),r=i(7404),d=i(61396),l=i.n(d),s=i(24033);function o(e){let{children:n,className:i}=e;return(0,t.jsxs)("div",{className:(0,a.cn)("grid overflow-hidden lg:grid-cols-[280px_1fr]",i),children:[(0,t.jsx)("div",{className:"hidden border-r bg-zinc-100/40 dark:bg-zinc-800/40 lg:block",children:(0,t.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,t.jsx)("div",{className:"h-[12px]"}),(0,t.jsx)("div",{className:"flex-1",children:(0,t.jsxs)("nav",{className:"grid items-start gap-4 px-4 text-sm font-medium",children:[(0,t.jsxs)(u,{href:"/",children:[(0,t.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-4 w-4",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("path",{d:"m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}),(0,t.jsx)("polyline",{points:"9 22 9 12 15 12 15 22"})]}),"Home"]}),(0,t.jsxs)(u,{href:"/swagger",children:[(0,t.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-4 w-4",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("path",{d:"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"}),(0,t.jsx)("path",{d:"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"}),(0,t.jsx)("path",{d:"M6 8h2"}),(0,t.jsx)("path",{d:"M6 12h2"}),(0,t.jsx)("path",{d:"M16 8h2"}),(0,t.jsx)("path",{d:"M16 12h2"})]}),"Swagger"]})]})})]})}),(0,t.jsx)("div",{className:"flex flex-1 flex-col overflow-auto",children:n})]})}let c=(0,r.j)("flex items-center gap-3 rounded-lg px-3 py-2 text-zinc-900 transition-all hover:text-zinc-900 dark:text-zinc-50 dark:hover:text-zinc-50",{variants:{state:{selected:"bg-zinc-200 dark:bg-zinc-800","not-selected":""}},defaultVariants:{state:"not-selected"}});function u(e){let{href:n,children:i}=e,a=(0,s.usePathname)();return(0,t.jsx)(l(),{className:c({state:a==n?"selected":"not-selected"}),href:n,children:i})}},70349:function(e,n,i){"use strict";var t,a,r,d;i.d(n,{Yi:function(){return t},bh:function(){return s},d3:function(){return l},xj:function(){return a}}),(r=t||(t={})).Cuda="CUDA",r.Rocm="ROCM",(d=a||(a={})).Chat="CHAT",d.Completion="COMPLETION";let l={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetWorkers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"workers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"kind"}},{kind:"Field",name:{kind:"Name",value:"name"}},{kind:"Field",name:{kind:"Name",value:"addr"}},{kind:"Field",name:{kind:"Name",value:"device"}},{kind:"Field",name:{kind:"Name",value:"arch"}},{kind:"Field",name:{kind:"Name",value:"cpuInfo"}},{kind:"Field",name:{kind:"Name",value:"cpuCount"}},{kind:"Field",name:{kind:"Name",value:"accelerators"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"uuid"}},{kind:"Field",name:{kind:"Name",value:"chipName"}},{kind:"Field",name:{kind:"Name",value:"displayName"}},{kind:"Field",name:{kind:"Name",value:"deviceType"}}]}}]}}]}}]},s={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetRegistrationToken"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"registrationToken"}}]}}]}},39311:function(e,n,i){"use strict";i.d(n,{aF:function(){return c},cn:function(){return s},uY:function(){return l},x0:function(){return o}});var t=i(50348),a=i(28481),r=i(23986),d=i(70349);let l={Cuda:d.Yi.Cuda,Rocm:d.Yi.Rocm};function s(){for(var e=arguments.length,n=Array(e),i=0;i1&&void 0!==arguments[1]?arguments[1]:50,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/[ ,.:;\n,。:;]/;if(!e)return"";if(e.length<=n)return e;let t=e.slice(0,n),a=-1;for(let e=n-1;e>=0;e--)if(i.test(t[e])){a=e;break}return -1!==a&&(t=t.slice(0,a)),t+"..."}},67650:function(e,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"RouterContext",{enumerable:!0,get:function(){return r}});let t=i(21024),a=t._(i(2265)),r=a.default.createContext(null)},24033:function(e,n,i){e.exports=i(20290)}},function(e){e.O(0,[882,396,971,864,744],function(){return e(e.s=95926)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js
deleted file mode 100644
index 52f2b1cf4db..00000000000
--- a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js
+++ /dev/null
@@ -1 +0,0 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[130],{89853:function(e,t,n){Promise.resolve().then(n.bind(n,60901))},60901:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return M}});var s=n(57437),a=n(93023),r=n(12609),i=n(84168),o=n(16775),l=n(13287),d=n(2265),c=n(39311);let u=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("rounded-lg border bg-card text-card-foreground shadow-sm",n),...a})});u.displayName="Card";let h=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("flex flex-col space-y-1.5 p-6",n),...a})});h.displayName="CardHeader";let x=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("h3",{ref:t,className:(0,c.cn)("text-2xl font-semibold leading-none tracking-tight",n),...a})});x.displayName="CardTitle";let m=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("p",{ref:t,className:(0,c.cn)("text-sm text-muted-foreground",n),...a})});m.displayName="CardDescription";let p=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("p-6 pt-0",n),...a})});p.displayName="CardContent";let f=d.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,c.cn)("flex items-center p-6 pt-0",n),...a})});f.displayName="CardFooter";var j=n(70349);function g(e){let{addr:t,name:n,kind:a,device:r,gpuDevices:i,cpuCount:o,cpuInfo:l}=e,d=(0,c.cn)("ml-2","whitespace-nowrap","overflow-hidden","overflow-ellipsis"),m="".concat(l," (").concat(o," cores)");return(0,s.jsxs)(u,{className:"rounded-xl p-2 shadow-md lg:w-[260px]",children:[(0,s.jsx)(h,{className:"p-0 px-4 pb-2 pt-4",children:(0,s.jsxs)(x,{className:"text-md flex items-center font-normal",children:[(0,s.jsx)(k,{type:a}),(0,s.jsx)("p",{title:n,className:d,children:n})]})}),(0,s.jsxs)(p,{className:"flex flex-col gap-2 p-0 px-4 pb-4 pt-2",children:[(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-5 w-5 text-gray-400",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("rect",{x:"16",y:"16",width:"6",height:"6",rx:"1"}),(0,s.jsx)("rect",{x:"2",y:"16",width:"6",height:"6",rx:"1"}),(0,s.jsx)("rect",{x:"9",y:"2",width:"6",height:"6",rx:"1"}),(0,s.jsx)("path",{d:"M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"}),(0,s.jsx)("path",{d:"M12 12V8"})]}),(0,s.jsx)("p",{title:t,className:d,children:t})]}),(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("rect",{height:"16",rx:"2",width:"16",x:"4",y:"4"}),(0,s.jsx)("rect",{height:"6",width:"6",x:"9",y:"9"}),(0,s.jsx)("path",{d:"M15 2v2"}),(0,s.jsx)("path",{d:"M15 20v2"}),(0,s.jsx)("path",{d:"M2 15h2"}),(0,s.jsx)("path",{d:"M2 9h2"}),(0,s.jsx)("path",{d:"M20 15h2"}),(0,s.jsx)("path",{d:"M20 9h2"}),(0,s.jsx)("path",{d:"M9 2v2"}),(0,s.jsx)("path",{d:"M9 20v2"})]}),(0,s.jsx)("p",{title:m,className:d,children:m})]}),"cuda"==r&&(null==i?void 0:i.length)&&i.map((e,t)=>(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("path",{d:"M6 19v-3"}),(0,s.jsx)("path",{d:"M10 19v-3"}),(0,s.jsx)("path",{d:"M14 19v-3"}),(0,s.jsx)("path",{d:"M18 19v-3"}),(0,s.jsx)("path",{d:"M8 11V9"}),(0,s.jsx)("path",{d:"M16 11V9"}),(0,s.jsx)("path",{d:"M12 11V9"}),(0,s.jsx)("path",{d:"M2 15h20"}),(0,s.jsx)("path",{d:"M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1.1a2 2 0 0 0 0 3.837V17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5.1a2 2 0 0 0 0-3.837Z"})]}),(0,s.jsx)("p",{title:e,className:d,children:e})]},t)),"rocm"==r&&(null==i?void 0:i.length)&&i.map((e,t)=>(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("path",{d:"M6 19v-3"}),(0,s.jsx)("path",{d:"M10 19v-3"}),(0,s.jsx)("path",{d:"M14 19v-3"}),(0,s.jsx)("path",{d:"M18 19v-3"}),(0,s.jsx)("path",{d:"M8 11V9"}),(0,s.jsx)("path",{d:"M16 11V9"}),(0,s.jsx)("path",{d:"M12 11V9"}),(0,s.jsx)("path",{d:"M2 15h20"}),(0,s.jsx)("path",{d:"M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1.1a2 2 0 0 0 0 3.837V17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5.1a2 2 0 0 0 0-3.837Z"})]}),(0,s.jsx)("p",{title:e,className:d,children:e})]},t))]})]})}function v(e){let{children:t}=e;return(0,s.jsx)("div",{className:"mt-2 flex items-center text-sm text-gray-500",children:t})}function k(e){let{type:t}=e,n="h-5 w-5";return t==j.xj.Completion?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"}),(0,s.jsx)("polyline",{points:"14 2 14 8 20 8"}),(0,s.jsx)("path",{d:"m10 13-2 2 2 2"}),(0,s.jsx)("path",{d:"m14 17 2-2-2-2"})]}):t==j.xj.Chat?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"M14 9a2 2 0 0 1-2 2H6l-4 4V4c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v5Z"}),(0,s.jsx)("path",{d:"M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1"})]}):"INDEX"==t?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"m9 9-2 2 2 2"}),(0,s.jsx)("path",{d:"m13 13 2-2-2-2"}),(0,s.jsx)("circle",{cx:"11",cy:"11",r:"8"}),(0,s.jsx)("path",{d:"m21 21-4.3-4.3"})]}):void 0}var w=n(8724),N=n(71427),y=n(10144),b=n(33555);let C="community-dialog-shown";function M(){let[e,t]=(0,d.useState)(!1);return(0,d.useEffect)(()=>{localStorage.getItem(C)||(t(!0),localStorage.setItem(C,"true"))},[]),(0,s.jsxs)("div",{className:"p-4 lg:p-16",children:[(0,s.jsx)(_,{}),(0,s.jsx)(r.Vq,{open:e,onOpenChange:t,children:(0,s.jsxs)(r.cZ,{children:[(0,s.jsxs)(r.fK,{className:"gap-3",children:[(0,s.jsx)(r.$N,{children:"Join the Tabby community"}),(0,s.jsx)(r.Be,{children:"Connect with other contributors building Tabby. Share knowledge, get help, and contribute to the open-source project."})]}),(0,s.jsx)(r.cN,{className:"sm:justify-start",children:(0,s.jsxs)("a",{target:"_blank",href:"https://join.slack.com/t/tabbycommunity/shared_invite/zt-1xeiddizp-bciR2RtFTaJ37RBxr8VxpA",className:(0,a.d)(),children:[(0,s.jsx)(i.gx,{className:"-ml-2 h-8 w-8"}),"Join us on Slack"]})})]})})]})}function _(){let{data:e}=(0,l.Q)(),t=(0,w.s)(e),{data:n}=(0,N.a)(y.$);if(e)return(0,s.jsxs)("div",{className:"flex w-full flex-col gap-3",children:[(0,s.jsxs)("h1",{children:[(0,s.jsx)("span",{className:"font-bold",children:"Congratulations"}),", your tabby instance is up!"]}),(0,s.jsx)("span",{className:"flex flex-wrap gap-1",children:(0,s.jsx)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby/releases/tag/".concat(e.version.git_describe),children:(0,s.jsx)("img",{src:"https://img.shields.io/badge/version-".concat(encodeURIComponent(e.version.git_describe.replaceAll("-","--")),"-green")})})}),(0,s.jsx)(o.Z,{}),(0,s.jsxs)("div",{className:"mt-4 rounded-lg bg-zinc-100 p-4 dark:bg-zinc-800",children:[(0,s.jsx)("span",{className:"font-bold",children:"Workers"}),!!(null==n?void 0:n.registrationToken)&&(0,s.jsxs)("div",{className:"flex items-center gap-1",children:["Registeration token: ",(0,s.jsx)("span",{className:"text-sm rounded-lg text-red-600",children:n.registrationToken}),(0,s.jsx)(b.q,{value:n.registrationToken})]}),(0,s.jsxs)("div",{className:"mt-4 flex flex-col gap-4 lg:flex-row lg:flex-wrap",children:[!!(null==t?void 0:t[j.xj.Completion])&&(0,s.jsx)(s.Fragment,{children:t[j.xj.Completion].map((e,t)=>(0,s.jsx)(g,{...e},t))}),!!(null==t?void 0:t[j.xj.Chat])&&(0,s.jsx)(s.Fragment,{children:t[j.xj.Chat].map((e,t)=>(0,s.jsx)(g,{...e},t))}),(0,s.jsx)(g,{addr:"localhost",name:"Code Search Index",kind:"INDEX",arch:"",device:e.device,gpuDevices:e.gpu_devices,cpuCount:e.cpu_count,cpuInfo:e.cpu_info})]})]})]})}},33555:function(e,t,n){"use strict";n.d(t,{q:function(){return o}});var s=n(57437);n(2265);var a=n(93023),r=n(84168),i=n(77723);function o(e){let{className:t,value:n,...o}=e,{isCopied:l,copyToClipboard:d}=(0,i.m)({timeout:2e3});return n?(0,s.jsxs)(a.z,{variant:"ghost",size:"icon",className:t,onClick:()=>{l||d(n)},...o,children:[l?(0,s.jsx)(r.NO,{}):(0,s.jsx)(r.vU,{}),(0,s.jsx)("span",{className:"sr-only",children:"Copy"})]}):null}},12609:function(e,t,n){"use strict";n.d(t,{$N:function(){return m},Be:function(){return p},Vq:function(){return l},cN:function(){return x},cZ:function(){return u},fK:function(){return h}});var s=n(57437),a=n(2265),r=n(25555),i=n(39311),o=n(84168);let l=r.fC;r.xz;let d=e=>{let{className:t,children:n,...a}=e;return(0,s.jsx)(r.h_,{className:(0,i.cn)(t),...a,children:(0,s.jsx)("div",{className:"fixed inset-0 z-50 flex items-start justify-center sm:items-center",children:n})})};d.displayName=r.h_.displayName;let c=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.aV,{ref:t,className:(0,i.cn)("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",n),...a})});c.displayName=r.aV.displayName;let u=a.forwardRef((e,t)=>{let{className:n,children:a,...l}=e;return(0,s.jsxs)(d,{children:[(0,s.jsx)(c,{}),(0,s.jsxs)(r.VY,{ref:t,className:(0,i.cn)("fixed z-50 grid w-full gap-4 rounded-b-lg border bg-background p-6 shadow-sm animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",n),...l,children:[a,(0,s.jsxs)(r.x8,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[(0,s.jsx)(o.bM,{}),(0,s.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})});u.displayName=r.VY.displayName;let h=e=>{let{className:t,...n}=e;return(0,s.jsx)("div",{className:(0,i.cn)("flex flex-col space-y-1.5 text-center sm:text-left",t),...n})};h.displayName="DialogHeader";let x=e=>{let{className:t,...n}=e;return(0,s.jsx)("div",{className:(0,i.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...n})};x.displayName="DialogFooter";let m=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.Dx,{ref:t,className:(0,i.cn)("text-lg font-semibold leading-none tracking-tight",n),...a})});m.displayName=r.Dx.displayName;let p=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.dk,{ref:t,className:(0,i.cn)("text-sm text-muted-foreground",n),...a})});p.displayName=r.dk.displayName},16775:function(e,t,n){"use strict";n.d(t,{Z:function(){return o}});var s=n(57437),a=n(2265),r=n(26823),i=n(39311);let o=a.forwardRef((e,t)=>{let{className:n,orientation:a="horizontal",decorative:o=!0,...l}=e;return(0,s.jsx)(r.f,{ref:t,decorative:o,orientation:a,className:(0,i.cn)("shrink-0 bg-border","horizontal"===a?"h-[1px] w-full":"h-full w-[1px]",n),...l})});o.displayName=r.f.displayName},70349:function(e,t,n){"use strict";var s,a;n.d(t,{bh:function(){return i},d3:function(){return r},xj:function(){return s}}),(a=s||(s={})).Chat="CHAT",a.Completion="COMPLETION";let r={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetWorkers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"workers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"kind"}},{kind:"Field",name:{kind:"Name",value:"name"}},{kind:"Field",name:{kind:"Name",value:"addr"}},{kind:"Field",name:{kind:"Name",value:"device"}},{kind:"Field",name:{kind:"Name",value:"arch"}},{kind:"Field",name:{kind:"Name",value:"cpuInfo"}},{kind:"Field",name:{kind:"Name",value:"cpuCount"}},{kind:"Field",name:{kind:"Name",value:"gpuDevices"}}]}}]}}]},i={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetRegistrationToken"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"registrationToken"}}]}}]}},10144:function(e,t,n){"use strict";n.d(t,{G:function(){return i},$:function(){return o}});var s=n(70349);let a={"\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n":s.d3,"\n query GetRegistrationToken {\n registrationToken\n }\n":s.bh};function r(e){var t;return null!==(t=a[e])&&void 0!==t?t:{}}let i=r("\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n"),o=r("\n query GetRegistrationToken {\n registrationToken\n }\n")},77723:function(e,t,n){"use strict";n.d(t,{m:function(){return a}});var s=n(2265);function a(e){let{timeout:t=2e3}=e,[n,a]=s.useState(!1);return{isCopied:n,copyToClipboard:e=>{var n;(null===(n=navigator.clipboard)||void 0===n?void 0:n.writeText)&&e&&navigator.clipboard.writeText(e).then(()=>{a(!0),setTimeout(()=>{a(!1)},t)})}}}},71427:function(e,t,n){"use strict";n.d(t,{a:function(){return l}});var s,a=n(30713),r=n(95054),i=n(62601);let o=new r.g6("".concat(null!==(s=i.env.NEXT_PUBLIC_TABBY_SERVER_URL)&&void 0!==s?s:"","/graphql"));function l(e,t,n){return(0,a.ZP)([e,t],e=>{let[t,n]=e;return o.request(t,n)},n)}},13287:function(e,t,n){"use strict";n.d(t,{Q:function(){return r}});var s=n(1589),a=n(97605);function r(){return(0,s.Z)("/v1/health",a.Z)}},8724:function(e,t,n){"use strict";n.d(t,{s:function(){return h}});var s=n(2265),a=n(91317),r=n(16630),i=n(35512),o=n(70349),l=n(10144),d=n(71427);let c={[o.xj.Chat]:"chat_model",[o.xj.Completion]:"model"};function u(e,t){var n;return{kind:t,device:e.device,addr:"localhost",arch:"",cpuInfo:e.cpu_info,name:null!==(n=null==e?void 0:e[c[t]])&&void 0!==n?n:"",cpuCount:e.cpu_count,gpuDevices:e.gpu_devices}}function h(e){let{data:t}=(0,d.a)(l.G),n=null==t?void 0:t.workers,c=s.useMemo(()=>{let t=(0,i.Z)(n),s=(0,r.Z)(t,{kind:o.xj.Completion})>-1,l=(0,r.Z)(t,{kind:o.xj.Chat})>-1;return!s&&(null==e?void 0:e.model)&&t.push(u(e,o.xj.Completion)),!l&&(null==e?void 0:e.chat_model)&&t.push(u(e,o.xj.Chat)),(0,a.Z)(t,"kind")},[e,n]);return c}}},function(e){e.O(0,[882,845,431,286,967,971,864,744],function(){return e(e.s=89853)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-799bd801adc161c7.js b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-799bd801adc161c7.js
new file mode 100644
index 00000000000..5c2d0233bd1
--- /dev/null
+++ b/ee/tabby-webserver/ui/_next/static/chunks/app/(dashboard)/page-799bd801adc161c7.js
@@ -0,0 +1 @@
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[130],{89853:function(e,t,n){Promise.resolve().then(n.bind(n,60901))},60901:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return _}});var s=n(57437),a=n(93023),r=n(12609),i=n(84168),o=n(16775),l=n(13287),c=n(2265),d=n(39311);let u=c.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,d.cn)("rounded-lg border bg-card text-card-foreground shadow-sm",n),...a})});u.displayName="Card";let h=c.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,d.cn)("flex flex-col space-y-1.5 p-6",n),...a})});h.displayName="CardHeader";let x=c.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("h3",{ref:t,className:(0,d.cn)("text-2xl font-semibold leading-none tracking-tight",n),...a})});x.displayName="CardTitle";let p=c.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("p",{ref:t,className:(0,d.cn)("text-sm text-muted-foreground",n),...a})});p.displayName="CardDescription";let m=c.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,d.cn)("p-6 pt-0",n),...a})});m.displayName="CardContent";let f=c.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)("div",{ref:t,className:(0,d.cn)("flex items-center p-6 pt-0",n),...a})});f.displayName="CardFooter";var j=n(70349);function g(e){let{addr:t,name:n,kind:a,device:r,accelerators:i,cpuCount:o,cpuInfo:l}=e,c=(0,d.cn)("ml-2","whitespace-nowrap","overflow-hidden","overflow-ellipsis"),p="".concat(l," (").concat(o," cores)");return(0,s.jsxs)(u,{className:"rounded-xl p-2 shadow-md lg:w-[260px]",children:[(0,s.jsx)(h,{className:"p-0 px-4 pb-2 pt-4",children:(0,s.jsxs)(x,{className:"text-md flex items-center font-normal",children:[(0,s.jsx)(N,{type:a}),(0,s.jsx)("p",{title:n,className:c,children:n})]})}),(0,s.jsxs)(m,{className:"flex flex-col gap-2 p-0 px-4 pb-4 pt-2",children:[(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:" h-5 w-5 text-gray-400",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("rect",{x:"16",y:"16",width:"6",height:"6",rx:"1"}),(0,s.jsx)("rect",{x:"2",y:"16",width:"6",height:"6",rx:"1"}),(0,s.jsx)("rect",{x:"9",y:"2",width:"6",height:"6",rx:"1"}),(0,s.jsx)("path",{d:"M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"}),(0,s.jsx)("path",{d:"M12 12V8"})]}),(0,s.jsx)("p",{title:t,className:c,children:t})]}),(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("rect",{height:"16",rx:"2",width:"16",x:"4",y:"4"}),(0,s.jsx)("rect",{height:"6",width:"6",x:"9",y:"9"}),(0,s.jsx)("path",{d:"M15 2v2"}),(0,s.jsx)("path",{d:"M15 20v2"}),(0,s.jsx)("path",{d:"M2 15h2"}),(0,s.jsx)("path",{d:"M2 9h2"}),(0,s.jsx)("path",{d:"M20 15h2"}),(0,s.jsx)("path",{d:"M20 9h2"}),(0,s.jsx)("path",{d:"M9 2v2"}),(0,s.jsx)("path",{d:"M9 20v2"})]}),(0,s.jsx)("p",{title:p,className:c,children:p})]}),(null==i?void 0:i.length)&&i.map((e,t)=>(0,s.jsxs)(v,{children:[(0,s.jsxs)("svg",{className:" h-5 w-5 text-gray-400",fill:"none",height:"24",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg",children:[(0,s.jsx)("path",{d:"M6 19v-3"}),(0,s.jsx)("path",{d:"M10 19v-3"}),(0,s.jsx)("path",{d:"M14 19v-3"}),(0,s.jsx)("path",{d:"M18 19v-3"}),(0,s.jsx)("path",{d:"M8 11V9"}),(0,s.jsx)("path",{d:"M16 11V9"}),(0,s.jsx)("path",{d:"M12 11V9"}),(0,s.jsx)("path",{d:"M2 15h20"}),(0,s.jsx)("path",{d:"M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1.1a2 2 0 0 0 0 3.837V17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5.1a2 2 0 0 0 0-3.837Z"})]}),(0,s.jsx)("p",{title:e.chipName?"".concat(e.displayName," (").concat(e.chipName,")"):e.displayName,className:c,children:e.displayName})]},t))]})]})}function v(e){let{children:t}=e;return(0,s.jsx)("div",{className:"mt-2 flex items-center text-sm text-gray-500",children:t})}function N(e){let{type:t}=e,n="h-5 w-5";return t==j.xj.Completion?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"}),(0,s.jsx)("polyline",{points:"14 2 14 8 20 8"}),(0,s.jsx)("path",{d:"m10 13-2 2 2 2"}),(0,s.jsx)("path",{d:"m14 17 2-2-2-2"})]}):t==j.xj.Chat?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"M14 9a2 2 0 0 1-2 2H6l-4 4V4c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v5Z"}),(0,s.jsx)("path",{d:"M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1"})]}):"INDEX"==t?(0,s.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:n,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("path",{d:"m9 9-2 2 2 2"}),(0,s.jsx)("path",{d:"m13 13 2-2-2-2"}),(0,s.jsx)("circle",{cx:"11",cy:"11",r:"8"}),(0,s.jsx)("path",{d:"m21 21-4.3-4.3"})]}):void 0}var w=n(8724),y=n(71427),k=n(10144),b=n(33555);let C="community-dialog-shown";function _(){let[e,t]=(0,c.useState)(!1);return(0,c.useEffect)(()=>{localStorage.getItem(C)||(t(!0),localStorage.setItem(C,"true"))},[]),(0,s.jsxs)("div",{className:"p-4 lg:p-16",children:[(0,s.jsx)(M,{}),(0,s.jsx)(r.Vq,{open:e,onOpenChange:t,children:(0,s.jsxs)(r.cZ,{children:[(0,s.jsxs)(r.fK,{className:"gap-3",children:[(0,s.jsx)(r.$N,{children:"Join the Tabby community"}),(0,s.jsx)(r.Be,{children:"Connect with other contributors building Tabby. Share knowledge, get help, and contribute to the open-source project."})]}),(0,s.jsx)(r.cN,{className:"sm:justify-start",children:(0,s.jsxs)("a",{target:"_blank",href:"https://join.slack.com/t/tabbycommunity/shared_invite/zt-1xeiddizp-bciR2RtFTaJ37RBxr8VxpA",className:(0,a.d)(),children:[(0,s.jsx)(i.gx,{className:"-ml-2 h-8 w-8"}),"Join us on Slack"]})})]})})]})}function M(){let{data:e}=(0,l.Q)(),t=(0,w.s)(e),{data:n}=(0,y.a)(k.$);if(e)return(0,s.jsxs)("div",{className:"flex w-full flex-col gap-3",children:[(0,s.jsxs)("h1",{children:[(0,s.jsx)("span",{className:"font-bold",children:"Congratulations"}),", your tabby instance is up!"]}),(0,s.jsx)("span",{className:"flex flex-wrap gap-1",children:(0,s.jsx)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby/releases/tag/".concat(e.version.git_describe),children:(0,s.jsx)("img",{src:"https://img.shields.io/badge/version-".concat(encodeURIComponent(e.version.git_describe.replaceAll("-","--")),"-green")})})}),(0,s.jsx)(o.Z,{}),(0,s.jsxs)("div",{className:"mt-4 rounded-lg bg-zinc-100 p-4 dark:bg-zinc-800",children:[(0,s.jsx)("span",{className:"font-bold",children:"Workers"}),!!(null==n?void 0:n.registrationToken)&&(0,s.jsxs)("div",{className:"flex items-center gap-1",children:["Registeration token: ",(0,s.jsx)("span",{className:"text-sm rounded-lg text-red-600",children:n.registrationToken}),(0,s.jsx)(b.q,{value:n.registrationToken})]}),(0,s.jsxs)("div",{className:"mt-4 flex flex-col gap-4 lg:flex-row lg:flex-wrap",children:[!!(null==t?void 0:t[j.xj.Completion])&&(0,s.jsx)(s.Fragment,{children:t[j.xj.Completion].map((e,t)=>(0,s.jsx)(g,{...e},t))}),!!(null==t?void 0:t[j.xj.Chat])&&(0,s.jsx)(s.Fragment,{children:t[j.xj.Chat].map((e,t)=>(0,s.jsx)(g,{...e},t))}),(0,s.jsx)(g,{addr:"localhost",name:"Code Search Index",kind:"INDEX",arch:"",device:e.device,accelerators:e.accelerators.map(e=>({uuid:e.uuid,chipName:e.chip_name,displayName:e.display_name,deviceType:d.uY[e.device_type]})),cpuCount:e.cpu_count,cpuInfo:e.cpu_info})]})]})]})}},33555:function(e,t,n){"use strict";n.d(t,{q:function(){return o}});var s=n(57437);n(2265);var a=n(93023),r=n(84168),i=n(77723);function o(e){let{className:t,value:n,...o}=e,{isCopied:l,copyToClipboard:c}=(0,i.m)({timeout:2e3});return n?(0,s.jsxs)(a.z,{variant:"ghost",size:"icon",className:t,onClick:()=>{l||c(n)},...o,children:[l?(0,s.jsx)(r.NO,{}):(0,s.jsx)(r.vU,{}),(0,s.jsx)("span",{className:"sr-only",children:"Copy"})]}):null}},12609:function(e,t,n){"use strict";n.d(t,{$N:function(){return p},Be:function(){return m},Vq:function(){return l},cN:function(){return x},cZ:function(){return u},fK:function(){return h}});var s=n(57437),a=n(2265),r=n(25555),i=n(39311),o=n(84168);let l=r.fC;r.xz;let c=e=>{let{className:t,children:n,...a}=e;return(0,s.jsx)(r.h_,{className:(0,i.cn)(t),...a,children:(0,s.jsx)("div",{className:"fixed inset-0 z-50 flex items-start justify-center sm:items-center",children:n})})};c.displayName=r.h_.displayName;let d=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.aV,{ref:t,className:(0,i.cn)("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",n),...a})});d.displayName=r.aV.displayName;let u=a.forwardRef((e,t)=>{let{className:n,children:a,...l}=e;return(0,s.jsxs)(c,{children:[(0,s.jsx)(d,{}),(0,s.jsxs)(r.VY,{ref:t,className:(0,i.cn)("fixed z-50 grid w-full gap-4 rounded-b-lg border bg-background p-6 shadow-sm animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",n),...l,children:[a,(0,s.jsxs)(r.x8,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[(0,s.jsx)(o.bM,{}),(0,s.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})});u.displayName=r.VY.displayName;let h=e=>{let{className:t,...n}=e;return(0,s.jsx)("div",{className:(0,i.cn)("flex flex-col space-y-1.5 text-center sm:text-left",t),...n})};h.displayName="DialogHeader";let x=e=>{let{className:t,...n}=e;return(0,s.jsx)("div",{className:(0,i.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...n})};x.displayName="DialogFooter";let p=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.Dx,{ref:t,className:(0,i.cn)("text-lg font-semibold leading-none tracking-tight",n),...a})});p.displayName=r.Dx.displayName;let m=a.forwardRef((e,t)=>{let{className:n,...a}=e;return(0,s.jsx)(r.dk,{ref:t,className:(0,i.cn)("text-sm text-muted-foreground",n),...a})});m.displayName=r.dk.displayName},16775:function(e,t,n){"use strict";n.d(t,{Z:function(){return o}});var s=n(57437),a=n(2265),r=n(26823),i=n(39311);let o=a.forwardRef((e,t)=>{let{className:n,orientation:a="horizontal",decorative:o=!0,...l}=e;return(0,s.jsx)(r.f,{ref:t,decorative:o,orientation:a,className:(0,i.cn)("shrink-0 bg-border","horizontal"===a?"h-[1px] w-full":"h-full w-[1px]",n),...l})});o.displayName=r.f.displayName},10144:function(e,t,n){"use strict";n.d(t,{G:function(){return i},$:function(){return o}});var s=n(70349);let a={"\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n accelerators {\n uuid\n chipName\n displayName\n deviceType\n }\n }\n }\n":s.d3,"\n query GetRegistrationToken {\n registrationToken\n }\n":s.bh};function r(e){var t;return null!==(t=a[e])&&void 0!==t?t:{}}let i=r("\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n accelerators {\n uuid\n chipName\n displayName\n deviceType\n }\n }\n }\n"),o=r("\n query GetRegistrationToken {\n registrationToken\n }\n")},77723:function(e,t,n){"use strict";n.d(t,{m:function(){return a}});var s=n(2265);function a(e){let{timeout:t=2e3}=e,[n,a]=s.useState(!1);return{isCopied:n,copyToClipboard:e=>{var n;(null===(n=navigator.clipboard)||void 0===n?void 0:n.writeText)&&e&&navigator.clipboard.writeText(e).then(()=>{a(!0),setTimeout(()=>{a(!1)},t)})}}}},71427:function(e,t,n){"use strict";n.d(t,{a:function(){return l}});var s,a=n(30713),r=n(95054),i=n(62601);let o=new r.g6("".concat(null!==(s=i.env.NEXT_PUBLIC_TABBY_SERVER_URL)&&void 0!==s?s:"","/graphql"));function l(e,t,n){return(0,a.ZP)([e,t],e=>{let[t,n]=e;return o.request(t,n)},n)}},13287:function(e,t,n){"use strict";n.d(t,{Q:function(){return r}});var s=n(1589),a=n(97605);function r(){return(0,s.Z)("/v1/health",a.Z)}},8724:function(e,t,n){"use strict";n.d(t,{s:function(){return x}});var s=n(2265),a=n(16630),r=n(91317),i=n(35512),o=n(70349),l=n(10144),c=n(71427),d=n(39311);let u={[o.xj.Chat]:"chat_model",[o.xj.Completion]:"model"};function h(e,t){var n;return{kind:t,device:e.device,addr:"localhost",arch:"",cpuInfo:e.cpu_info,name:null!==(n=null==e?void 0:e[u[t]])&&void 0!==n?n:"",cpuCount:e.cpu_count,accelerators:e.accelerators.map(e=>({uuid:e.uuid,chipName:e.chip_name,displayName:e.display_name,deviceType:d.uY[e.device_type]}))}}function x(e){let{data:t}=(0,c.a)(l.G),n=null==t?void 0:t.workers,d=s.useMemo(()=>{let t=(0,i.Z)(n),s=(0,a.Z)(t,{kind:o.xj.Completion})>-1,l=(0,a.Z)(t,{kind:o.xj.Chat})>-1;return!s&&(null==e?void 0:e.model)&&t.push(h(e,o.xj.Completion)),!l&&(null==e?void 0:e.chat_model)&&t.push(h(e,o.xj.Chat)),(0,r.Z)(t,"kind")},[e,n]);return d}}},function(e){e.O(0,[882,845,431,286,967,971,864,744],function(){return e(e.s=89853)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/layout-01cdb629b9621465.js b/ee/tabby-webserver/ui/_next/static/chunks/app/layout-01cdb629b9621465.js
new file mode 100644
index 00000000000..85e65dcd810
--- /dev/null
+++ b/ee/tabby-webserver/ui/_next/static/chunks/app/layout-01cdb629b9621465.js
@@ -0,0 +1 @@
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{6435:function(e,t,n){"use strict";n.d(t,{F:function(){return u},f:function(){return d}});var r=n(2265);let a=["light","dark"],l="(prefers-color-scheme: dark)",o="undefined"==typeof window,i=(0,r.createContext)(void 0),s={setTheme:e=>{},themes:[]},u=()=>{var e;return null!==(e=(0,r.useContext)(i))&&void 0!==e?e:s},d=e=>(0,r.useContext)(i)?r.createElement(r.Fragment,null,e.children):r.createElement(m,e),c=["light","dark"],m=({forcedTheme:e,disableTransitionOnChange:t=!1,enableSystem:n=!0,enableColorScheme:o=!0,storageKey:s="theme",themes:u=c,defaultTheme:d=n?"system":"light",attribute:m="data-theme",value:b,children:y,nonce:g})=>{let[_,x]=(0,r.useState)(()=>h(s,d)),[k,N]=(0,r.useState)(()=>h(s)),j=b?Object.values(b):u,w=(0,r.useCallback)(e=>{let r=e;if(!r)return;"system"===e&&n&&(r=v());let l=b?b[r]:r,i=t?p():null,s=document.documentElement;if("class"===m?(s.classList.remove(...j),l&&s.classList.add(l)):l?s.setAttribute(m,l):s.removeAttribute(m),o){let e=a.includes(d)?d:null,t=a.includes(r)?r:e;s.style.colorScheme=t}null==i||i()},[]),C=(0,r.useCallback)(e=>{x(e);try{localStorage.setItem(s,e)}catch(e){}},[e]),S=(0,r.useCallback)(t=>{let r=v(t);N(r),"system"===_&&n&&!e&&w("system")},[_,e]);(0,r.useEffect)(()=>{let e=window.matchMedia(l);return e.addListener(S),S(e),()=>e.removeListener(S)},[S]),(0,r.useEffect)(()=>{let e=e=>{e.key===s&&C(e.newValue||d)};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[C]),(0,r.useEffect)(()=>{w(null!=e?e:_)},[e,_]);let T=(0,r.useMemo)(()=>({theme:_,setTheme:C,forcedTheme:e,resolvedTheme:"system"===_?k:_,themes:n?[...u,"system"]:u,systemTheme:n?k:void 0}),[_,C,e,k,n,u]);return r.createElement(i.Provider,{value:T},r.createElement(f,{forcedTheme:e,disableTransitionOnChange:t,enableSystem:n,enableColorScheme:o,storageKey:s,themes:u,defaultTheme:d,attribute:m,value:b,children:y,attrs:j,nonce:g}),y)},f=(0,r.memo)(({forcedTheme:e,storageKey:t,attribute:n,enableSystem:o,enableColorScheme:i,defaultTheme:s,value:u,attrs:d,nonce:c})=>{let m="system"===s,f="class"===n?`var d=document.documentElement,c=d.classList;c.remove(${d.map(e=>`'${e}'`).join(",")});`:`var d=document.documentElement,n='${n}',s='setAttribute';`,h=i?a.includes(s)&&s?`if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${s}'`:"if(e==='light'||e==='dark')d.style.colorScheme=e":"",p=(e,t=!1,r=!0)=>{let l=u?u[e]:e,o=t?e+"|| ''":`'${l}'`,s="";return i&&r&&!t&&a.includes(e)&&(s+=`d.style.colorScheme = '${e}';`),"class"===n?s+=t||l?`c.add(${o})`:"null":l&&(s+=`d[s](n,${o})`),s},v=e?`!function(){${f}${p(e)}}()`:o?`!function(){try{${f}var e=localStorage.getItem('${t}');if('system'===e||(!e&&${m})){var t='${l}',m=window.matchMedia(t);if(m.media!==t||m.matches){${p("dark")}}else{${p("light")}}}else if(e){${u?`var x=${JSON.stringify(u)};`:""}${p(u?"x[e]":"e",!0)}}${m?"":"else{"+p(s,!1,!1)+"}"}${h}}catch(e){}}()`:`!function(){try{${f}var e=localStorage.getItem('${t}');if(e){${u?`var x=${JSON.stringify(u)};`:""}${p(u?"x[e]":"e",!0)}}else{${p(s,!1,!1)};}${h}}catch(t){}}();`;return r.createElement("script",{nonce:c,dangerouslySetInnerHTML:{__html:v}})},()=>!0),h=(e,t)=>{let n;if(!o){try{n=localStorage.getItem(e)||void 0}catch(e){}return n||t}},p=()=>{let e=document.createElement("style");return e.appendChild(document.createTextNode("*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),document.head.appendChild(e),()=>{window.getComputedStyle(document.body),setTimeout(()=>{document.head.removeChild(e)},1)}},v=e=>(e||(e=window.matchMedia(l)),e.matches?"dark":"light")},66958:function(e,t,n){Promise.resolve().then(n.t.bind(n,58877,23)),Promise.resolve().then(n.bind(n,11486)),Promise.resolve().then(n.bind(n,78495)),Promise.resolve().then(n.t.bind(n,6928,23)),Promise.resolve().then(n.t.bind(n,33195,23)),Promise.resolve().then(n.bind(n,5925))},11486:function(e,t,n){"use strict";n.r(t),n.d(t,{Header:function(){return E}});var r=n(57437);n(2265);var a=n(39311),l=n(93023),o=n(84168),i=n(30415),s=n.n(i),u=n(61396),d=n.n(u),c=n(13287),m=n(1589);let f=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,h=e=>{if("string"!=typeof e)throw TypeError("Invalid argument expected string");let t=e.match(f);if(!t)throw Error(`Invalid argument not valid semver ('${e}' received)`);return t.shift(),t},p=e=>"*"===e||"x"===e||"X"===e,v=e=>{let t=parseInt(e,10);return isNaN(t)?e:t},b=(e,t)=>typeof e!=typeof t?[String(e),String(t)]:[e,t],y=(e,t)=>{if(p(e)||p(t))return 0;let[n,r]=b(v(e),v(t));return n>r?1:n{for(let n=0;n{let n=h(e),r=h(t),a=n.pop(),l=r.pop(),o=g(n,r);return 0!==o?o:a&&l?g(a.split("."),l.split(".")):a||l?a?-1:1:0},x=(e,t,n)=>{j(n);let r=_(e,t);return k[n].includes(r)},k={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1],"!=":[-1,1]},N=Object.keys(k),j=e=>{if("string"!=typeof e)throw TypeError(`Invalid operator type, expected string but got ${typeof e}`);if(-1===N.indexOf(e))throw Error(`Invalid operator, expected one of ${N.join("|")}`)};var w=n(8724),C=n(70349),S=n(91067);let T=s()(()=>n.e(376).then(n.bind(n,15376)).then(e=>e.ThemeToggle),{loadableGenerated:{webpack:()=>[15376]},ssr:!1});function E(){var e;let{data:t}=(0,c.Q)(),n=(0,w.s)(t),i=(0,S.Z)(n,C.xj.Chat),s=null==t?void 0:null===(e=t.version)||void 0===e?void 0:e.git_describe,{data:u}=(0,m.Z)("https://api.github.com/repos/TabbyML/tabby/releases/latest",e=>fetch(e).then(e=>e.json())),f=function(e,t){try{return e&&t&&x(t.name,e,">")}catch(e){return console.warn(e),!0}}(s,u);return(0,r.jsxs)("header",{className:"from-background/10 via-background/50 to-background/80 sticky top-0 z-50 flex h-16 w-full shrink-0 items-center justify-between border-b bg-gradient-to-b px-4 backdrop-blur-xl",children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(T,{}),(0,r.jsx)(d(),{href:"/",className:(0,a.cn)((0,l.d)({variant:"link"})),children:"Dashboard"}),i&&(0,r.jsx)(d(),{href:"/playground",className:(0,a.cn)((0,l.d)({variant:"link"})),children:"Playground"})]}),(0,r.jsxs)("div",{className:"flex items-center justify-end space-x-2",children:[f&&(0,r.jsxs)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby/releases/latest",rel:"noopener noreferrer",className:(0,l.d)({variant:"ghost"}),children:[(0,r.jsx)(o.Qs,{className:"text-yellow-600 dark:text-yellow-400"}),(0,r.jsxs)("span",{className:"ml-2 hidden md:flex",children:["New version (",null==u?void 0:u.name,") available"]})]}),(0,r.jsxs)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby",rel:"noopener noreferrer",className:(0,a.cn)((0,l.d)({variant:"outline"})),children:[(0,r.jsx)(o.Mr,{}),(0,r.jsx)("span",{className:"ml-2 hidden md:flex",children:"GitHub"})]})]})]})}},78495:function(e,t,n){"use strict";n.r(t),n.d(t,{Providers:function(){return o}});var r=n(57437);n(2265);var a=n(6435),l=n(95482);function o(e){let{children:t,...n}=e;return(0,r.jsx)(a.f,{...n,children:(0,r.jsx)(l.pn,{children:t})})}},95482:function(e,t,n){"use strict";n.d(t,{_v:function(){return d},aJ:function(){return u},pn:function(){return i},u:function(){return s}});var r=n(57437),a=n(2265),l=n(75224),o=n(39311);let i=l.zt,s=l.fC,u=l.xz,d=a.forwardRef((e,t)=>{let{className:n,sideOffset:a=4,...i}=e;return(0,r.jsx)(l.VY,{ref:t,sideOffset:a,className:(0,o.cn)("z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-xs font-medium text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",n),...i})});d.displayName=l.VY.displayName},10144:function(e,t,n){"use strict";n.d(t,{G:function(){return o},$:function(){return i}});var r=n(70349);let a={"\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n accelerators {\n uuid\n chipName\n displayName\n deviceType\n }\n }\n }\n":r.d3,"\n query GetRegistrationToken {\n registrationToken\n }\n":r.bh};function l(e){var t;return null!==(t=a[e])&&void 0!==t?t:{}}let o=l("\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n accelerators {\n uuid\n chipName\n displayName\n deviceType\n }\n }\n }\n"),i=l("\n query GetRegistrationToken {\n registrationToken\n }\n")},71427:function(e,t,n){"use strict";n.d(t,{a:function(){return s}});var r,a=n(30713),l=n(95054),o=n(62601);let i=new l.g6("".concat(null!==(r=o.env.NEXT_PUBLIC_TABBY_SERVER_URL)&&void 0!==r?r:"","/graphql"));function s(e,t,n){return(0,a.ZP)([e,t],e=>{let[t,n]=e;return i.request(t,n)},n)}},13287:function(e,t,n){"use strict";n.d(t,{Q:function(){return l}});var r=n(1589),a=n(97605);function l(){return(0,r.Z)("/v1/health",a.Z)}},8724:function(e,t,n){"use strict";n.d(t,{s:function(){return f}});var r=n(2265),a=n(16630),l=n(91317),o=n(35512),i=n(70349),s=n(10144),u=n(71427),d=n(39311);let c={[i.xj.Chat]:"chat_model",[i.xj.Completion]:"model"};function m(e,t){var n;return{kind:t,device:e.device,addr:"localhost",arch:"",cpuInfo:e.cpu_info,name:null!==(n=null==e?void 0:e[c[t]])&&void 0!==n?n:"",cpuCount:e.cpu_count,accelerators:e.accelerators.map(e=>({uuid:e.uuid,chipName:e.chip_name,displayName:e.display_name,deviceType:d.uY[e.device_type]}))}}function f(e){let{data:t}=(0,u.a)(s.G),n=null==t?void 0:t.workers,d=r.useMemo(()=>{let t=(0,o.Z)(n),r=(0,a.Z)(t,{kind:i.xj.Completion})>-1,s=(0,a.Z)(t,{kind:i.xj.Chat})>-1;return!r&&(null==e?void 0:e.model)&&t.push(m(e,i.xj.Completion)),!s&&(null==e?void 0:e.chat_model)&&t.push(m(e,i.xj.Chat)),(0,l.Z)(t,"kind")},[e,n]);return d}},30415:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return o}});let r=n(21024);n(2265);let a=r._(n(54));function l(e){return{default:(null==e?void 0:e.default)||e}}function o(e,t){let n=a.default,r={loading:e=>{let{error:t,isLoading:n,pastDelay:r}=e;return null}};"function"==typeof e&&(r.loader=e),Object.assign(r,t);let o=r.loader;return n({...r,loader:()=>null!=o?o().then(l):Promise.resolve(l(()=>null))})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},63388:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e,t){for(var n in t)Object.defineProperty(e,n,{enumerable:!0,get:t[n]})}(t,{suspense:function(){return a},NoSSR:function(){return l}}),n(21024),n(2265);let r=n(54922);function a(){let e=Error(r.NEXT_DYNAMIC_NO_SSR_CODE);throw e.digest=r.NEXT_DYNAMIC_NO_SSR_CODE,e}function l(e){let{children:t}=e;return t}},54:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return o}});let r=n(21024),a=r._(n(2265)),l=n(63388),o=function(e){let t=Object.assign({loader:null,loading:null,ssr:!0},e);function n(e){let n=t.loading,r=a.default.createElement(n,{isLoading:!0,pastDelay:!0,error:null}),o=t.ssr?a.default.Fragment:l.NoSSR,i=t.lazy;return a.default.createElement(a.default.Suspense,{fallback:r},a.default.createElement(o,null,a.default.createElement(i,e)))}return t.lazy=a.default.lazy(t.loader),n.displayName="LoadableComponent",n}},58877:function(){},6928:function(e){e.exports={style:{fontFamily:"'__Inter_e66fe9', '__Inter_Fallback_e66fe9'",fontStyle:"normal"},className:"__className_e66fe9",variable:"__variable_e66fe9"}},33195:function(e){e.exports={style:{fontFamily:"'__JetBrains_Mono_bd9c35', '__JetBrains_Mono_Fallback_bd9c35'",fontStyle:"normal"},className:"__className_bd9c35",variable:"__variable_bd9c35"}}},function(e){e.O(0,[882,845,431,892,396,967,971,864,744],function(){return e(e.s=66958)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/layout-a709b0b21d295a91.js b/ee/tabby-webserver/ui/_next/static/chunks/app/layout-a709b0b21d295a91.js
deleted file mode 100644
index 87dd44dde05..00000000000
--- a/ee/tabby-webserver/ui/_next/static/chunks/app/layout-a709b0b21d295a91.js
+++ /dev/null
@@ -1 +0,0 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{6435:function(e,t,n){"use strict";n.d(t,{F:function(){return d},f:function(){return u}});var r=n(2265);let i=["light","dark"],a="(prefers-color-scheme: dark)",l="undefined"==typeof window,o=(0,r.createContext)(void 0),s={setTheme:e=>{},themes:[]},d=()=>{var e;return null!==(e=(0,r.useContext)(o))&&void 0!==e?e:s},u=e=>(0,r.useContext)(o)?r.createElement(r.Fragment,null,e.children):r.createElement(m,e),c=["light","dark"],m=({forcedTheme:e,disableTransitionOnChange:t=!1,enableSystem:n=!0,enableColorScheme:l=!0,storageKey:s="theme",themes:d=c,defaultTheme:u=n?"system":"light",attribute:m="data-theme",value:b,children:y,nonce:g})=>{let[k,_]=(0,r.useState)(()=>h(s,u)),[x,N]=(0,r.useState)(()=>h(s)),S=b?Object.values(b):d,j=(0,r.useCallback)(e=>{let r=e;if(!r)return;"system"===e&&n&&(r=p());let a=b?b[r]:r,o=t?v():null,s=document.documentElement;if("class"===m?(s.classList.remove(...S),a&&s.classList.add(a)):a?s.setAttribute(m,a):s.removeAttribute(m),l){let e=i.includes(u)?u:null,t=i.includes(r)?r:e;s.style.colorScheme=t}null==o||o()},[]),C=(0,r.useCallback)(e=>{_(e);try{localStorage.setItem(s,e)}catch(e){}},[e]),w=(0,r.useCallback)(t=>{let r=p(t);N(r),"system"===k&&n&&!e&&j("system")},[k,e]);(0,r.useEffect)(()=>{let e=window.matchMedia(a);return e.addListener(w),w(e),()=>e.removeListener(w)},[w]),(0,r.useEffect)(()=>{let e=e=>{e.key===s&&C(e.newValue||u)};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[C]),(0,r.useEffect)(()=>{j(null!=e?e:k)},[e,k]);let T=(0,r.useMemo)(()=>({theme:k,setTheme:C,forcedTheme:e,resolvedTheme:"system"===k?x:k,themes:n?[...d,"system"]:d,systemTheme:n?x:void 0}),[k,C,e,x,n,d]);return r.createElement(o.Provider,{value:T},r.createElement(f,{forcedTheme:e,disableTransitionOnChange:t,enableSystem:n,enableColorScheme:l,storageKey:s,themes:d,defaultTheme:u,attribute:m,value:b,children:y,attrs:S,nonce:g}),y)},f=(0,r.memo)(({forcedTheme:e,storageKey:t,attribute:n,enableSystem:l,enableColorScheme:o,defaultTheme:s,value:d,attrs:u,nonce:c})=>{let m="system"===s,f="class"===n?`var d=document.documentElement,c=d.classList;c.remove(${u.map(e=>`'${e}'`).join(",")});`:`var d=document.documentElement,n='${n}',s='setAttribute';`,h=o?i.includes(s)&&s?`if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${s}'`:"if(e==='light'||e==='dark')d.style.colorScheme=e":"",v=(e,t=!1,r=!0)=>{let a=d?d[e]:e,l=t?e+"|| ''":`'${a}'`,s="";return o&&r&&!t&&i.includes(e)&&(s+=`d.style.colorScheme = '${e}';`),"class"===n?s+=t||a?`c.add(${l})`:"null":a&&(s+=`d[s](n,${l})`),s},p=e?`!function(){${f}${v(e)}}()`:l?`!function(){try{${f}var e=localStorage.getItem('${t}');if('system'===e||(!e&&${m})){var t='${a}',m=window.matchMedia(t);if(m.media!==t||m.matches){${v("dark")}}else{${v("light")}}}else if(e){${d?`var x=${JSON.stringify(d)};`:""}${v(d?"x[e]":"e",!0)}}${m?"":"else{"+v(s,!1,!1)+"}"}${h}}catch(e){}}()`:`!function(){try{${f}var e=localStorage.getItem('${t}');if(e){${d?`var x=${JSON.stringify(d)};`:""}${v(d?"x[e]":"e",!0)}}else{${v(s,!1,!1)};}${h}}catch(t){}}();`;return r.createElement("script",{nonce:c,dangerouslySetInnerHTML:{__html:p}})},()=>!0),h=(e,t)=>{let n;if(!l){try{n=localStorage.getItem(e)||void 0}catch(e){}return n||t}},v=()=>{let e=document.createElement("style");return e.appendChild(document.createTextNode("*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),document.head.appendChild(e),()=>{window.getComputedStyle(document.body),setTimeout(()=>{document.head.removeChild(e)},1)}},p=e=>(e||(e=window.matchMedia(a)),e.matches?"dark":"light")},66958:function(e,t,n){Promise.resolve().then(n.t.bind(n,58877,23)),Promise.resolve().then(n.bind(n,11486)),Promise.resolve().then(n.bind(n,78495)),Promise.resolve().then(n.t.bind(n,6928,23)),Promise.resolve().then(n.t.bind(n,33195,23)),Promise.resolve().then(n.bind(n,5925))},11486:function(e,t,n){"use strict";n.r(t),n.d(t,{Header:function(){return E}});var r=n(57437);n(2265);var i=n(39311),a=n(93023),l=n(84168),o=n(30415),s=n.n(o),d=n(61396),u=n.n(d),c=n(13287),m=n(1589);let f=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,h=e=>{if("string"!=typeof e)throw TypeError("Invalid argument expected string");let t=e.match(f);if(!t)throw Error(`Invalid argument not valid semver ('${e}' received)`);return t.shift(),t},v=e=>"*"===e||"x"===e||"X"===e,p=e=>{let t=parseInt(e,10);return isNaN(t)?e:t},b=(e,t)=>typeof e!=typeof t?[String(e),String(t)]:[e,t],y=(e,t)=>{if(v(e)||v(t))return 0;let[n,r]=b(p(e),p(t));return n>r?1:n{for(let n=0;n{let n=h(e),r=h(t),i=n.pop(),a=r.pop(),l=g(n,r);return 0!==l?l:i&&a?g(i.split("."),a.split(".")):i||a?i?-1:1:0},_=(e,t,n)=>{S(n);let r=k(e,t);return x[n].includes(r)},x={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1],"!=":[-1,1]},N=Object.keys(x),S=e=>{if("string"!=typeof e)throw TypeError(`Invalid operator type, expected string but got ${typeof e}`);if(-1===N.indexOf(e))throw Error(`Invalid operator, expected one of ${N.join("|")}`)};var j=n(8724),C=n(70349),w=n(91067);let T=s()(()=>n.e(376).then(n.bind(n,15376)).then(e=>e.ThemeToggle),{loadableGenerated:{webpack:()=>[15376]},ssr:!1});function E(){var e;let{data:t}=(0,c.Q)(),n=(0,j.s)(t),o=(0,w.Z)(n,C.xj.Chat),s=null==t?void 0:null===(e=t.version)||void 0===e?void 0:e.git_describe,{data:d}=(0,m.Z)("https://api.github.com/repos/TabbyML/tabby/releases/latest",e=>fetch(e).then(e=>e.json())),f=function(e,t){try{return e&&t&&_(t.name,e,">")}catch(e){return console.warn(e),!0}}(s,d);return(0,r.jsxs)("header",{className:"from-background/10 via-background/50 to-background/80 sticky top-0 z-50 flex h-16 w-full shrink-0 items-center justify-between border-b bg-gradient-to-b px-4 backdrop-blur-xl",children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(T,{}),(0,r.jsx)(u(),{href:"/",className:(0,i.cn)((0,a.d)({variant:"link"})),children:"Dashboard"}),o&&(0,r.jsx)(u(),{href:"/playground",className:(0,i.cn)((0,a.d)({variant:"link"})),children:"Playground"})]}),(0,r.jsxs)("div",{className:"flex items-center justify-end space-x-2",children:[f&&(0,r.jsxs)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby/releases/latest",rel:"noopener noreferrer",className:(0,a.d)({variant:"ghost"}),children:[(0,r.jsx)(l.Qs,{className:"text-yellow-600 dark:text-yellow-400"}),(0,r.jsxs)("span",{className:"ml-2 hidden md:flex",children:["New version (",null==d?void 0:d.name,") available"]})]}),(0,r.jsxs)("a",{target:"_blank",href:"https://github.com/TabbyML/tabby",rel:"noopener noreferrer",className:(0,i.cn)((0,a.d)({variant:"outline"})),children:[(0,r.jsx)(l.Mr,{}),(0,r.jsx)("span",{className:"ml-2 hidden md:flex",children:"GitHub"})]})]})]})}},78495:function(e,t,n){"use strict";n.r(t),n.d(t,{Providers:function(){return l}});var r=n(57437);n(2265);var i=n(6435),a=n(95482);function l(e){let{children:t,...n}=e;return(0,r.jsx)(i.f,{...n,children:(0,r.jsx)(a.pn,{children:t})})}},95482:function(e,t,n){"use strict";n.d(t,{_v:function(){return u},aJ:function(){return d},pn:function(){return o},u:function(){return s}});var r=n(57437),i=n(2265),a=n(75224),l=n(39311);let o=a.zt,s=a.fC,d=a.xz,u=i.forwardRef((e,t)=>{let{className:n,sideOffset:i=4,...o}=e;return(0,r.jsx)(a.VY,{ref:t,sideOffset:i,className:(0,l.cn)("z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-xs font-medium text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",n),...o})});u.displayName=a.VY.displayName},70349:function(e,t,n){"use strict";var r,i;n.d(t,{bh:function(){return l},d3:function(){return a},xj:function(){return r}}),(i=r||(r={})).Chat="CHAT",i.Completion="COMPLETION";let a={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetWorkers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"workers"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"kind"}},{kind:"Field",name:{kind:"Name",value:"name"}},{kind:"Field",name:{kind:"Name",value:"addr"}},{kind:"Field",name:{kind:"Name",value:"device"}},{kind:"Field",name:{kind:"Name",value:"arch"}},{kind:"Field",name:{kind:"Name",value:"cpuInfo"}},{kind:"Field",name:{kind:"Name",value:"cpuCount"}},{kind:"Field",name:{kind:"Name",value:"gpuDevices"}}]}}]}}]},l={kind:"Document",definitions:[{kind:"OperationDefinition",operation:"query",name:{kind:"Name",value:"GetRegistrationToken"},selectionSet:{kind:"SelectionSet",selections:[{kind:"Field",name:{kind:"Name",value:"registrationToken"}}]}}]}},10144:function(e,t,n){"use strict";n.d(t,{G:function(){return l},$:function(){return o}});var r=n(70349);let i={"\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n":r.d3,"\n query GetRegistrationToken {\n registrationToken\n }\n":r.bh};function a(e){var t;return null!==(t=i[e])&&void 0!==t?t:{}}let l=a("\n query GetWorkers {\n workers {\n kind\n name\n addr\n device\n arch\n cpuInfo\n cpuCount\n gpuDevices\n }\n }\n"),o=a("\n query GetRegistrationToken {\n registrationToken\n }\n")},71427:function(e,t,n){"use strict";n.d(t,{a:function(){return s}});var r,i=n(30713),a=n(95054),l=n(62601);let o=new a.g6("".concat(null!==(r=l.env.NEXT_PUBLIC_TABBY_SERVER_URL)&&void 0!==r?r:"","/graphql"));function s(e,t,n){return(0,i.ZP)([e,t],e=>{let[t,n]=e;return o.request(t,n)},n)}},13287:function(e,t,n){"use strict";n.d(t,{Q:function(){return a}});var r=n(1589),i=n(97605);function a(){return(0,r.Z)("/v1/health",i.Z)}},8724:function(e,t,n){"use strict";n.d(t,{s:function(){return m}});var r=n(2265),i=n(91317),a=n(16630),l=n(35512),o=n(70349),s=n(10144),d=n(71427);let u={[o.xj.Chat]:"chat_model",[o.xj.Completion]:"model"};function c(e,t){var n;return{kind:t,device:e.device,addr:"localhost",arch:"",cpuInfo:e.cpu_info,name:null!==(n=null==e?void 0:e[u[t]])&&void 0!==n?n:"",cpuCount:e.cpu_count,gpuDevices:e.gpu_devices}}function m(e){let{data:t}=(0,d.a)(s.G),n=null==t?void 0:t.workers,u=r.useMemo(()=>{let t=(0,l.Z)(n),r=(0,a.Z)(t,{kind:o.xj.Completion})>-1,s=(0,a.Z)(t,{kind:o.xj.Chat})>-1;return!r&&(null==e?void 0:e.model)&&t.push(c(e,o.xj.Completion)),!s&&(null==e?void 0:e.chat_model)&&t.push(c(e,o.xj.Chat)),(0,i.Z)(t,"kind")},[e,n]);return u}},30415:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return l}});let r=n(21024);n(2265);let i=r._(n(54));function a(e){return{default:(null==e?void 0:e.default)||e}}function l(e,t){let n=i.default,r={loading:e=>{let{error:t,isLoading:n,pastDelay:r}=e;return null}};"function"==typeof e&&(r.loader=e),Object.assign(r,t);let l=r.loader;return n({...r,loader:()=>null!=l?l().then(a):Promise.resolve(a(()=>null))})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},63388:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e,t){for(var n in t)Object.defineProperty(e,n,{enumerable:!0,get:t[n]})}(t,{suspense:function(){return i},NoSSR:function(){return a}}),n(21024),n(2265);let r=n(54922);function i(){let e=Error(r.NEXT_DYNAMIC_NO_SSR_CODE);throw e.digest=r.NEXT_DYNAMIC_NO_SSR_CODE,e}function a(e){let{children:t}=e;return t}},54:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return l}});let r=n(21024),i=r._(n(2265)),a=n(63388),l=function(e){let t=Object.assign({loader:null,loading:null,ssr:!0},e);function n(e){let n=t.loading,r=i.default.createElement(n,{isLoading:!0,pastDelay:!0,error:null}),l=t.ssr?i.default.Fragment:a.NoSSR,o=t.lazy;return i.default.createElement(i.default.Suspense,{fallback:r},i.default.createElement(l,null,i.default.createElement(o,e)))}return t.lazy=i.default.lazy(t.loader),n.displayName="LoadableComponent",n}},58877:function(){},6928:function(e){e.exports={style:{fontFamily:"'__Inter_e66fe9', '__Inter_Fallback_e66fe9'",fontStyle:"normal"},className:"__className_e66fe9",variable:"__variable_e66fe9"}},33195:function(e){e.exports={style:{fontFamily:"'__JetBrains_Mono_bd9c35', '__JetBrains_Mono_Fallback_bd9c35'",fontStyle:"normal"},className:"__className_bd9c35",variable:"__variable_bd9c35"}}},function(e){e.O(0,[882,845,431,892,396,967,971,864,744],function(){return e(e.s=66958)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-0e44acab13f2ae38.js b/ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-178c9cbcb60d3ef7.js
similarity index 100%
rename from ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-0e44acab13f2ae38.js
rename to ee/tabby-webserver/ui/_next/static/chunks/app/playground/page-178c9cbcb60d3ef7.js
diff --git a/ee/tabby-webserver/ui/_next/static/-IQIiI3YS2Md2tsCaIleK/_buildManifest.js b/ee/tabby-webserver/ui/_next/static/yoSiYgCA8KR8UtHATY8_5/_buildManifest.js
similarity index 100%
rename from ee/tabby-webserver/ui/_next/static/-IQIiI3YS2Md2tsCaIleK/_buildManifest.js
rename to ee/tabby-webserver/ui/_next/static/yoSiYgCA8KR8UtHATY8_5/_buildManifest.js
diff --git a/ee/tabby-webserver/ui/_next/static/-IQIiI3YS2Md2tsCaIleK/_ssgManifest.js b/ee/tabby-webserver/ui/_next/static/yoSiYgCA8KR8UtHATY8_5/_ssgManifest.js
similarity index 100%
rename from ee/tabby-webserver/ui/_next/static/-IQIiI3YS2Md2tsCaIleK/_ssgManifest.js
rename to ee/tabby-webserver/ui/_next/static/yoSiYgCA8KR8UtHATY8_5/_ssgManifest.js
diff --git a/ee/tabby-webserver/ui/index.html b/ee/tabby-webserver/ui/index.html
index fc0900acd76..9c734963356 100644
--- a/ee/tabby-webserver/ui/index.html
+++ b/ee/tabby-webserver/ui/index.html
@@ -1 +1 @@
-Tabby - Dashboard
\ No newline at end of file
+Tabby - Dashboard
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/index.txt b/ee/tabby-webserver/ui/index.txt
index acbd8bdbdcd..5fc956f38da 100644
--- a/ee/tabby-webserver/ui/index.txt
+++ b/ee/tabby-webserver/ui/index.txt
@@ -1,15 +1,15 @@
1:HL["/_next/static/media/86fdec36ddd9097e-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
2:HL["/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
3:HL["/_next/static/css/6473d52ca6f0f35c.css","style"]
-0:["-IQIiI3YS2Md2tsCaIleK",[[["",{"children":["(dashboard)",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
-6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Toaster","async":false}
-7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Providers","async":false}
-8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Header","async":false}
+0:["yoSiYgCA8KR8UtHATY8_5",[[["",{"children":["(dashboard)",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
+6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-77bee9da62f91e7a.js","185:static/chunks/app/layout-01cdb629b9621465.js"],"name":"Toaster","async":false}
+7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-77bee9da62f91e7a.js","185:static/chunks/app/layout-01cdb629b9621465.js"],"name":"Providers","async":false}
+8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-77bee9da62f91e7a.js","185:static/chunks/app/layout-01cdb629b9621465.js"],"name":"Header","async":false}
9:I{"id":81443,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
a:I{"id":18639,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
-b:I{"id":30831,"chunks":["882:static/chunks/882-5574357230a12cf9.js","396:static/chunks/396-89319c375c83667c.js","642:static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js"],"name":"","async":false}
+b:I{"id":30831,"chunks":["882:static/chunks/882-5574357230a12cf9.js","396:static/chunks/396-89319c375c83667c.js","642:static/chunks/app/(dashboard)/layout-d5a067a319c8b1d7.js"],"name":"","async":false}
d:I{"id":65146,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
-e:I{"id":60901,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","286:static/chunks/286-453e01dda7220f79.js","967:static/chunks/967-f02728ac0b1b01a8.js","130:static/chunks/app/(dashboard)/page-223f244bef7bc3fe.js"],"name":"","async":false}
+e:I{"id":60901,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","286:static/chunks/286-453e01dda7220f79.js","967:static/chunks/967-77bee9da62f91e7a.js","130:static/chunks/app/(dashboard)/page-799bd801adc161c7.js"],"name":"","async":false}
5:[["$","meta","0",{"charSet":"utf-8"}],["$","title","1",{"children":"Tabby - Dashboard"}],["$","meta","2",{"name":"description","content":"Tabby, an opensource, self-hosted AI coding assistant."}],["$","meta","3",{"name":"theme-color","media":"(prefers-color-scheme: light)","content":"white"}],["$","meta","4",{"name":"theme-color","media":"(prefers-color-scheme: dark)","content":"black"}],["$","meta","5",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","6",{"name":"next-size-adjust"}]]
4:[null,["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":[["$","head",null,{}],["$","body",null,{"className":"font-sans antialiased __variable_e66fe9 __variable_bd9c35","children":[["$","$L6",null,{}],["$","$L7",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"children":[["$","div",null,{"className":"flex min-h-screen flex-col","children":[["$","$L8",null,{}],["$","main",null,{"className":"bg-muted/50 flex flex-1 flex-col","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":[null,["$","$Lb",null,{"className":"flex-1","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children","(dashboard)","children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":["$Lc",["$","$Ld",null,{"propsForComponent":{"params":{}},"Component":"$e"}],null],"segment":"__PAGE__"},"styles":[]}]}],null],"segment":"(dashboard)"},"styles":[]}]}]]}],null]}]]}]]}],null]
c:null
diff --git a/ee/tabby-webserver/ui/playground.html b/ee/tabby-webserver/ui/playground.html
index 5b1bda429b7..f5455c04a7a 100644
--- a/ee/tabby-webserver/ui/playground.html
+++ b/ee/tabby-webserver/ui/playground.html
@@ -1 +1 @@
-Tabby - Playground
Scroll to bottom
Tabby , an opensource, self-hosted AI coding assistant .
\ No newline at end of file
+Tabby - Playground
Scroll to bottom
Tabby , an opensource, self-hosted AI coding assistant .
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/playground.txt b/ee/tabby-webserver/ui/playground.txt
index ec44a686c22..919a75c9e22 100644
--- a/ee/tabby-webserver/ui/playground.txt
+++ b/ee/tabby-webserver/ui/playground.txt
@@ -1,13 +1,13 @@
1:HL["/_next/static/media/86fdec36ddd9097e-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
2:HL["/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
3:HL["/_next/static/css/6473d52ca6f0f35c.css","style"]
-0:["-IQIiI3YS2Md2tsCaIleK",[[["",{"children":["playground",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
-6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Toaster","async":false}
-7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Providers","async":false}
-8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Header","async":false}
+0:["yoSiYgCA8KR8UtHATY8_5",[[["",{"children":["playground",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
+6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-77bee9da62f91e7a.js","185:static/chunks/app/layout-01cdb629b9621465.js"],"name":"Toaster","async":false}
+7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-77bee9da62f91e7a.js","185:static/chunks/app/layout-01cdb629b9621465.js"],"name":"Providers","async":false}
+8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-77bee9da62f91e7a.js","185:static/chunks/app/layout-01cdb629b9621465.js"],"name":"Header","async":false}
9:I{"id":81443,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
a:I{"id":18639,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
-c:I{"id":34926,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","892:static/chunks/892-eb176514ab2c02ba.js","286:static/chunks/286-453e01dda7220f79.js","899:static/chunks/899-0d9fbfefc7a97fe2.js","967:static/chunks/967-f02728ac0b1b01a8.js","383:static/chunks/app/playground/page-0e44acab13f2ae38.js"],"name":"","async":false}
+c:I{"id":34926,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","892:static/chunks/892-eb176514ab2c02ba.js","286:static/chunks/286-453e01dda7220f79.js","899:static/chunks/899-0d9fbfefc7a97fe2.js","967:static/chunks/967-77bee9da62f91e7a.js","383:static/chunks/app/playground/page-178c9cbcb60d3ef7.js"],"name":"","async":false}
5:[["$","meta","0",{"charSet":"utf-8"}],["$","title","1",{"children":"Tabby - Playground"}],["$","meta","2",{"name":"description","content":"Tabby, an opensource, self-hosted AI coding assistant."}],["$","meta","3",{"name":"theme-color","media":"(prefers-color-scheme: light)","content":"white"}],["$","meta","4",{"name":"theme-color","media":"(prefers-color-scheme: dark)","content":"black"}],["$","meta","5",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","6",{"name":"next-size-adjust"}]]
4:[null,["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":[["$","head",null,{}],["$","body",null,{"className":"font-sans antialiased __variable_e66fe9 __variable_bd9c35","children":[["$","$L6",null,{}],["$","$L7",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"children":[["$","div",null,{"className":"flex min-h-screen flex-col","children":[["$","$L8",null,{}],["$","main",null,{"className":"bg-muted/50 flex flex-1 flex-col","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children","playground","children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined","childProp":{"current":["$Lb",["$","$Lc",null,{}],null],"segment":"__PAGE__"},"styles":[]}],"segment":"playground"},"styles":[]}]}]]}],null]}]]}]]}],null]
b:null
diff --git a/ee/tabby-webserver/ui/swagger.html b/ee/tabby-webserver/ui/swagger.html
index bcb33d21dc8..fe79e55e0af 100644
--- a/ee/tabby-webserver/ui/swagger.html
+++ b/ee/tabby-webserver/ui/swagger.html
@@ -1 +1 @@
-API
\ No newline at end of file
+API
\ No newline at end of file
diff --git a/ee/tabby-webserver/ui/swagger.txt b/ee/tabby-webserver/ui/swagger.txt
index ad16b9bd13e..e324281ca67 100644
--- a/ee/tabby-webserver/ui/swagger.txt
+++ b/ee/tabby-webserver/ui/swagger.txt
@@ -1,13 +1,13 @@
1:HL["/_next/static/media/86fdec36ddd9097e-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
2:HL["/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
3:HL["/_next/static/css/6473d52ca6f0f35c.css","style"]
-0:["-IQIiI3YS2Md2tsCaIleK",[[["",{"children":["(dashboard)",{"children":["swagger",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
-6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Toaster","async":false}
-7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Providers","async":false}
-8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-f02728ac0b1b01a8.js","185:static/chunks/app/layout-a709b0b21d295a91.js"],"name":"Header","async":false}
+0:["yoSiYgCA8KR8UtHATY8_5",[[["",{"children":["(dashboard)",{"children":["swagger",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],"$L4",[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/6473d52ca6f0f35c.css","precedence":"next"}]],"$L5"]]]]
+6:I{"id":5925,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-77bee9da62f91e7a.js","185:static/chunks/app/layout-01cdb629b9621465.js"],"name":"Toaster","async":false}
+7:I{"id":78495,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-77bee9da62f91e7a.js","185:static/chunks/app/layout-01cdb629b9621465.js"],"name":"Providers","async":false}
+8:I{"id":11486,"chunks":["882:static/chunks/882-5574357230a12cf9.js","845:static/chunks/845-c760f8c52c4fcf50.js","431:static/chunks/431-7ea9c8ff0df11123.js","892:static/chunks/892-eb176514ab2c02ba.js","396:static/chunks/396-89319c375c83667c.js","967:static/chunks/967-77bee9da62f91e7a.js","185:static/chunks/app/layout-01cdb629b9621465.js"],"name":"Header","async":false}
9:I{"id":81443,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
a:I{"id":18639,"chunks":["272:static/chunks/webpack-27adc8d5d81c534f.js","971:static/chunks/fd9d1056-6779f76bb208370f.js","864:static/chunks/864-39b4a82d88034324.js"],"name":"","async":false}
-b:I{"id":30831,"chunks":["882:static/chunks/882-5574357230a12cf9.js","396:static/chunks/396-89319c375c83667c.js","642:static/chunks/app/(dashboard)/layout-9112e2f61825d91a.js"],"name":"","async":false}
+b:I{"id":30831,"chunks":["882:static/chunks/882-5574357230a12cf9.js","396:static/chunks/396-89319c375c83667c.js","642:static/chunks/app/(dashboard)/layout-d5a067a319c8b1d7.js"],"name":"","async":false}
5:[["$","meta","0",{"charSet":"utf-8"}],["$","title","1",{"children":"API"}],["$","meta","2",{"name":"description","content":"Tabby, an opensource, self-hosted AI coding assistant."}],["$","meta","3",{"name":"theme-color","media":"(prefers-color-scheme: light)","content":"white"}],["$","meta","4",{"name":"theme-color","media":"(prefers-color-scheme: dark)","content":"black"}],["$","meta","5",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","6",{"name":"next-size-adjust"}]]
4:[null,["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":[["$","head",null,{}],["$","body",null,{"className":"font-sans antialiased __variable_e66fe9 __variable_bd9c35","children":[["$","$L6",null,{}],["$","$L7",null,{"attribute":"class","defaultTheme":"system","enableSystem":true,"children":[["$","div",null,{"className":"flex min-h-screen flex-col","children":[["$","$L8",null,{}],["$","main",null,{"className":"bg-muted/50 flex flex-1 flex-col","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":[null,["$","$Lb",null,{"className":"flex-1","children":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children","(dashboard)","children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"childProp":{"current":["$","$L9",null,{"parallelRouterKey":"children","segmentPath":["children","(dashboard)","children","swagger","children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$La",null,{}],"templateStyles":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined","childProp":{"current":["$Lc",["$","iframe",null,{"className":"grow","src":"/swagger-ui"}],null],"segment":"__PAGE__"},"styles":[]}],"segment":"swagger"},"styles":[]}]}],null],"segment":"(dashboard)"},"styles":[]}]}]]}],null]}]]}]]}],null]
c:null
From cbbdf22846c1f9b496c737aef6cf0d7387510aef Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Tue, 28 Nov 2023 23:55:42 +0100
Subject: [PATCH 14/25] Pull request cleanup
---
crates/tabby/Cargo.toml | 2 +-
crates/tabby/src/services/health.rs | 2 +-
crates/tabby/src/worker.rs | 4 ++--
ee/tabby-ui/app/(dashboard)/page.tsx | 12 ++++++------
website/docs/configuration.md | 15 +++++++++++++--
website/docs/installation/docker.mdx | 3 ++-
6 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/crates/tabby/Cargo.toml b/crates/tabby/Cargo.toml
index f5495381c83..904c0ccdb74 100644
--- a/crates/tabby/Cargo.toml
+++ b/crates/tabby/Cargo.toml
@@ -37,7 +37,7 @@ tracing-opentelemetry = "0.18.0"
tantivy = { workspace = true }
anyhow = { workspace = true }
sysinfo = "0.29.8"
-nvml-wrapper = { version = "0.9.0" }
+nvml-wrapper = "0.9.0"
http-api-bindings = { path = "../http-api-bindings", optional = true } # included when build with `experimental-http` feature
async-stream = { workspace = true }
axum-streams = { version = "0.9.1", features = ["json"] }
diff --git a/crates/tabby/src/services/health.rs b/crates/tabby/src/services/health.rs
index 81e676b3bcf..386747da632 100644
--- a/crates/tabby/src/services/health.rs
+++ b/crates/tabby/src/services/health.rs
@@ -83,7 +83,7 @@ pub fn read_cuda_devices() -> Result> {
let dev = nvml.device_by_index(i)?;
let resource = Accelerator {
uuid: Some(dev.uuid()?),
- chip_name: None,
+ chip_name: None, // NVML doesn't provide us with chip info, like "AD102" or so
display_name: dev.name()?,
device_type: DeviceType::Cuda,
};
diff --git a/crates/tabby/src/worker.rs b/crates/tabby/src/worker.rs
index 2bc5c5e4fde..de083b68f5b 100644
--- a/crates/tabby/src/worker.rs
+++ b/crates/tabby/src/worker.rs
@@ -105,7 +105,7 @@ impl WorkerContext {
async fn register_impl(&self, kind: WorkerKind, args: &WorkerArgs) -> Result<()> {
let (cpu_info, cpu_count) = read_cpu_info();
- let gpu_devices = read_accelerators();
+ let accelerators = read_accelerators();
let worker = self
.client
.register_worker(
@@ -117,7 +117,7 @@ impl WorkerContext {
ARCH.to_string(),
cpu_info,
cpu_count as i32,
- gpu_devices,
+ accelerators,
args.token.clone(),
)
.await??;
diff --git a/ee/tabby-ui/app/(dashboard)/page.tsx b/ee/tabby-ui/app/(dashboard)/page.tsx
index 7dad12eca93..f64b032c967 100644
--- a/ee/tabby-ui/app/(dashboard)/page.tsx
+++ b/ee/tabby-ui/app/(dashboard)/page.tsx
@@ -2,12 +2,12 @@
import { buttonVariants } from '@/components/ui/button'
import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogTitle
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle
} from '@/components/ui/dialog'
import { IconSlack } from '@/components/ui/icons'
import { Separator } from '@/components/ui/separator'
diff --git a/website/docs/configuration.md b/website/docs/configuration.md
index bdec2748106..e338617fcbd 100644
--- a/website/docs/configuration.md
+++ b/website/docs/configuration.md
@@ -88,6 +88,17 @@ We collect non-sensitive data that helps us understand how Tabby is used. For no
As of the date 10/07/2023, the following information has been collected:
```rust
+pub struct Accelerator {
+ /// Universally unique ID of the accelerator, if available
+ pub uuid: Option,
+ /// Technical name of the underlying hardware chip, if available
+ pub chip_name: Option,
+ /// User readable name for the accelerator
+ pub display_name: String,
+ /// Type of the accelerator device
+ pub device_type: DeviceType,
+}
+
struct HealthState {
model: String,
chat_model: Option,
@@ -95,12 +106,12 @@ struct HealthState {
arch: String,
cpu_info: String,
cpu_count: usize,
- gpu_devices: Vec,
+ accelerators: Vec,
version: Version,
}
```
-For an up-to-date list of the fields we have collected, please refer to [health.rs](https://github.com/TabbyML/tabby/blob/main/crates/tabby/src/serve/health.rs#L11).
+For an up-to-date list of the fields we have collected, please refer to [health.rs](https://github.com/TabbyML/tabby/blob/main/crates/tabby/src/services/health.rs#L11).
### How to disable it
To disable usage collection, set the `TABBY_DISABLE_USAGE_COLLECTION` environment variable by `export TABBY_DISABLE_USAGE_COLLECTION=1`.
diff --git a/website/docs/installation/docker.mdx b/website/docs/installation/docker.mdx
index f3602f77c09..330f77d312c 100644
--- a/website/docs/installation/docker.mdx
+++ b/website/docs/installation/docker.mdx
@@ -8,6 +8,7 @@ This guide explains how to launch Tabby using docker.
+
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
@@ -29,7 +30,7 @@ import TabItem from '@theme/TabItem';
```bash title="run.sh"
- docker run -it --device /dev/dri --device /dev/kfd -p 8080:8080 -v $HOME/.tabby:/data tabbyml/tabby serve --model TabbyML/StarCoder-1B --device cuda
+ docker run -it --device /dev/dri --device /dev/kfd -p 8080:8080 -v $HOME/.tabby:/data tabbyml/tabby serve --model TabbyML/StarCoder-1B --device rocm
```
From f80007c57ef323598da5947b26a8d787f4d674ed Mon Sep 17 00:00:00 2001
From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com>
Date: Sun, 10 Dec 2023 12:43:48 +0000
Subject: [PATCH 15/25] [autofix.ci] apply automated fixes
---
.../(dashboard)/cluster/components/cluster.tsx | 16 ++++++++--------
.../cluster/components/worker-card.tsx | 11 +++++++++--
ee/tabby-ui/lib/hooks/use-health.tsx | 8 ++++----
ee/tabby-ui/lib/hooks/use-workers.ts | 12 ++++++------
ee/tabby-ui/lib/utils.ts | 7 ++++---
5 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/ee/tabby-ui/app/(dashboard)/cluster/components/cluster.tsx b/ee/tabby-ui/app/(dashboard)/cluster/components/cluster.tsx
index dd2d1543d8e..a8f2fd78389 100644
--- a/ee/tabby-ui/app/(dashboard)/cluster/components/cluster.tsx
+++ b/ee/tabby-ui/app/(dashboard)/cluster/components/cluster.tsx
@@ -5,6 +5,7 @@ import { WorkerKind } from '@/lib/gql/generates/graphql'
import { useHealth } from '@/lib/hooks/use-health'
import { useWorkers } from '@/lib/hooks/use-workers'
import { useAuthenticatedGraphQLQuery, useGraphQLForm } from '@/lib/tabby/gql'
+import { deviceTypeMap } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import { IconRotate } from '@/components/ui/icons'
import { Input } from '@/components/ui/input'
@@ -12,7 +13,6 @@ import { Separator } from '@/components/ui/separator'
import { CopyButton } from '@/components/copy-button'
import WorkerCard from './worker-card'
-import { deviceTypeMap } from "@/lib/utils";
const getRegistrationTokenDocument = graphql(/* GraphQL */ `
query GetRegistrationToken {
@@ -31,13 +31,13 @@ function toBadgeString(str: string) {
}
export default function Workers() {
- const {data: healthInfo} = useHealth()
+ const { data: healthInfo } = useHealth()
const workers = useWorkers()
- const {data: registrationTokenRes, mutate} = useAuthenticatedGraphQLQuery(
+ const { data: registrationTokenRes, mutate } = useAuthenticatedGraphQLQuery(
getRegistrationTokenDocument
)
- const {onSubmit: resetRegistrationToken} = useGraphQLForm(
+ const { onSubmit: resetRegistrationToken } = useGraphQLForm(
resetRegistrationTokenDocument,
{
onSuccess: () => mutate()
@@ -64,7 +64,7 @@ export default function Workers() {
/>
-
+
{!!registrationTokenRes?.registrationToken && (
Registration token:
@@ -78,9 +78,9 @@ export default function Workers() {
variant="hover-destructive"
onClick={() => resetRegistrationToken()}
>
-
+
-
+
)}
@@ -109,7 +109,7 @@ export default function Workers() {
uuid: a.uuid,
chipName: a.chip_name,
deviceType: deviceTypeMap[a.device_type],
- displayName: a.display_name,
+ displayName: a.display_name
}))}
cpuCount={healthInfo.cpu_count}
cpuInfo={healthInfo.cpu_info}
diff --git a/ee/tabby-ui/app/(dashboard)/cluster/components/worker-card.tsx b/ee/tabby-ui/app/(dashboard)/cluster/components/worker-card.tsx
index b87cbc8624d..2596c4c4c4d 100644
--- a/ee/tabby-ui/app/(dashboard)/cluster/components/worker-card.tsx
+++ b/ee/tabby-ui/app/(dashboard)/cluster/components/worker-card.tsx
@@ -1,6 +1,6 @@
-import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Worker, WorkerKind } from '@/lib/gql/generates/graphql'
import { cn } from '@/lib/utils'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
type RunnerType = WorkerKind | 'INDEX'
@@ -111,7 +111,14 @@ export default function RunnerCard({
-
+
{x.displayName}
diff --git a/ee/tabby-ui/lib/hooks/use-health.tsx b/ee/tabby-ui/lib/hooks/use-health.tsx
index dc15443b72f..477b459bbcd 100644
--- a/ee/tabby-ui/lib/hooks/use-health.tsx
+++ b/ee/tabby-ui/lib/hooks/use-health.tsx
@@ -7,10 +7,10 @@ import fetcher from '@/lib/tabby/fetcher'
import { useAuthenticatedApi } from '../tabby/auth'
export interface Accelerator {
- uuid?: string;
- chip_name?: string;
- display_name: string;
- device_type: 'Cuda' | 'Rocm';
+ uuid?: string
+ chip_name?: string
+ display_name: string
+ device_type: 'Cuda' | 'Rocm'
}
export interface HealthInfo {
diff --git a/ee/tabby-ui/lib/hooks/use-workers.ts b/ee/tabby-ui/lib/hooks/use-workers.ts
index 75075d7d4f4..a30e341f005 100644
--- a/ee/tabby-ui/lib/hooks/use-workers.ts
+++ b/ee/tabby-ui/lib/hooks/use-workers.ts
@@ -4,9 +4,9 @@ import { findIndex, groupBy, slice } from 'lodash-es'
import { graphql } from '@/lib/gql/generates'
import { Worker, WorkerKind } from '@/lib/gql/generates/graphql'
import { useAuthenticatedGraphQLQuery } from '@/lib/tabby/gql'
+import { deviceTypeMap } from '@/lib/utils'
import { useHealth, type HealthInfo } from './use-health'
-import { deviceTypeMap } from "@/lib/utils";
const modelNameMap: Record = {
[WorkerKind.Chat]: 'chat_model',
@@ -29,7 +29,7 @@ function transformHealthInfoToWorker(
uuid: x.uuid,
chipName: x.chip_name,
displayName: x.display_name,
- deviceType: deviceTypeMap[x.device_type],
+ deviceType: deviceTypeMap[x.device_type]
}))
}
}
@@ -45,10 +45,10 @@ export const getAllWorkersDocument = graphql(/* GraphQL */ `
cpuInfo
cpuCount
accelerators {
- uuid
- chipName
- displayName
- deviceType
+ uuid
+ chipName
+ displayName
+ deviceType
}
}
}
diff --git a/ee/tabby-ui/lib/utils.ts b/ee/tabby-ui/lib/utils.ts
index d9b14736d19..9fd87da6fa0 100644
--- a/ee/tabby-ui/lib/utils.ts
+++ b/ee/tabby-ui/lib/utils.ts
@@ -1,11 +1,12 @@
-import { type ClassValue, clsx } from 'clsx'
+import { clsx, type ClassValue } from 'clsx'
import { customAlphabet } from 'nanoid'
import { twMerge } from 'tailwind-merge'
-import { DeviceType } from "@/lib/gql/generates/graphql";
+
+import { DeviceType } from '@/lib/gql/generates/graphql'
export const deviceTypeMap: Record<'Cuda' | 'Rocm', DeviceType> = {
Cuda: DeviceType.Cuda,
- Rocm: DeviceType.Rocm,
+ Rocm: DeviceType.Rocm
}
export function cn(...inputs: ClassValue[]) {
From b993d5d3a7167b0baf4e0b9d2119000f22b87cd3 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 10 Dec 2023 14:06:51 +0100
Subject: [PATCH 16/25] Tried to fix most build issues
---
ee/tabby-webserver/src/api.rs | 36 +++----------------------
ee/tabby-webserver/src/lib.rs | 20 +-------------
ee/tabby-webserver/src/schema/worker.rs | 3 ++-
website/docs/configuration.md | 2 +-
4 files changed, 8 insertions(+), 53 deletions(-)
diff --git a/ee/tabby-webserver/src/api.rs b/ee/tabby-webserver/src/api.rs
index 1605fd5d655..aa182c590d9 100644
--- a/ee/tabby-webserver/src/api.rs
+++ b/ee/tabby-webserver/src/api.rs
@@ -6,38 +6,10 @@ use tabby_common::api::{
};
use tokio_tungstenite::connect_async;
-pub use crate::schema::worker::{RegisterWorkerError, Worker, WorkerKind};
-use crate::websocket::WebSocketTransport;
-
-#[derive(GraphQLEnum, Serialize, Deserialize, Clone, Debug)]
-pub enum WorkerKind {
- Completion,
- Chat,
-}
-
-#[derive(GraphQLObject, Serialize, Deserialize, Clone, Debug)]
-pub struct Worker {
- pub kind: WorkerKind,
- pub name: String,
- pub addr: String,
- pub device: String,
- pub arch: String,
- pub cpu_info: String,
- pub cpu_count: i32,
- pub accelerators: Vec,
-}
-
-#[derive(Serialize, Deserialize, Error, Debug)]
-pub enum RegisterWorkerError {
- #[error("Invalid token")]
- InvalidToken(String),
-
- #[error("Feature requires enterprise license")]
- RequiresEnterpriseLicense,
-
- #[error("Each hub client should only calls register_worker once")]
- RegisterWorkerOnce,
-}
+use crate::{
+ schema::worker::{RegisterWorkerError, Worker, WorkerKind},
+ websocket::WebSocketTransport,
+};
#[tarpc::service]
pub trait Hub {
diff --git a/ee/tabby-webserver/src/lib.rs b/ee/tabby-webserver/src/lib.rs
index f0d5675afef..1cc902b38ac 100644
--- a/ee/tabby-webserver/src/lib.rs
+++ b/ee/tabby-webserver/src/lib.rs
@@ -1,15 +1,6 @@
pub mod api;
mod schema;
-use api::Hub;
-pub use schema::create_schema;
-use tabby_common::api::{
- code::{CodeSearch, SearchResponse},
- event::RawEventLogger,
-};
-use tokio::sync::Mutex;
-use tracing::{error, warn};
-use websocket::WebSocketTransport;
mod repositories;
mod service;
@@ -18,6 +9,7 @@ mod websocket;
use std::{net::SocketAddr, sync::Arc};
+use api::Hub;
use axum::{
extract::{ws::WebSocket, ConnectInfo, State, WebSocketUpgrade},
http::Request,
@@ -32,7 +24,6 @@ use schema::{
worker::{RegisterWorkerError, Worker, WorkerKind},
Schema, ServiceLocator,
};
-use server::ServerContext;
use service::create_service_locator;
use tabby_common::api::{
accelerator::Accelerator,
@@ -44,15 +35,6 @@ use tokio::sync::Mutex;
use tracing::{error, warn};
use websocket::WebSocketTransport;
-pub mod api;
-
-mod db;
-mod repositories;
-mod schema;
-mod server;
-mod ui;
-mod websocket;
-
pub async fn attach_webserver(
api: Router,
ui: Router,
diff --git a/ee/tabby-webserver/src/schema/worker.rs b/ee/tabby-webserver/src/schema/worker.rs
index 78223ee8e33..64f6b1a4ef5 100644
--- a/ee/tabby-webserver/src/schema/worker.rs
+++ b/ee/tabby-webserver/src/schema/worker.rs
@@ -4,6 +4,7 @@ use axum::middleware::Next;
use hyper::{Body, Request};
use juniper::{GraphQLEnum, GraphQLObject};
use serde::{Deserialize, Serialize};
+use tabby_common::api::accelerator::Accelerator;
use thiserror::Error;
#[derive(GraphQLEnum, Serialize, Deserialize, Clone, Debug)]
@@ -21,7 +22,7 @@ pub struct Worker {
pub arch: String,
pub cpu_info: String,
pub cpu_count: i32,
- pub cuda_devices: Vec,
+ pub accelerators: Vec,
}
#[derive(Serialize, Deserialize, Error, Debug)]
diff --git a/website/docs/configuration.md b/website/docs/configuration.md
index e1a6caf3b88..449b9b01c8d 100644
--- a/website/docs/configuration.md
+++ b/website/docs/configuration.md
@@ -116,7 +116,7 @@ struct HealthState {
}
```
-For an up-to-date list of the fields we have collected, please refer to [health.rs](https://github.com/TabbyML/tabby/blob/main/crates/tabby/src/services/health.rs#L11).
+For an up-to-date list of the fields we have collected, please refer to [health.rs](https://github.com/TabbyML/tabby/blob/main/crates/tabby/src/serve/health.rs#L11).
### How to disable it
To disable usage collection, set the `TABBY_DISABLE_USAGE_COLLECTION` environment variable by `export TABBY_DISABLE_USAGE_COLLECTION=1`.
From 1bc6f4801e2583c13ba81e69b2cffa7702fa8a89 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 10 Dec 2023 14:37:52 +0100
Subject: [PATCH 17/25] Fixed the rest of the build issues
---
crates/llama-cpp-bindings/build.rs | 6 ++++--
crates/llama-cpp-bindings/src/llama.rs | 2 +-
crates/tabby/src/services/health.rs | 4 ++--
ee/tabby-webserver/src/api.rs | 2 +-
ee/tabby-webserver/src/lib.rs | 12 +++++++++++-
ee/tabby-webserver/src/schema/worker.rs | 2 ++
ee/tabby-webserver/src/service/worker.rs | 2 ++
7 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index bddf030a706..48520af374e 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -33,7 +33,7 @@ fn main() {
println!("cargo:rustc-link-lib=cublasLt");
}
if cfg!(feature = "rocm") {
- let amd_gpu_targets: Vec<&str> = vec![
+ let amd_gpu_default_targets: Vec<&str> = vec![
"gfx803",
"gfx900",
"gfx906:xnack-",
@@ -51,6 +51,8 @@ fn main() {
"gfx1102",
"gfx1103",
];
+ let amd_gpu_targets =
+ env::var("AMDGPU_TARGETS").unwrap_or(amd_gpu_default_targets.join(";"));
let rocm_root = env::var("ROCM_ROOT").unwrap_or("/opt/rocm".to_string());
config.define("LLAMA_HIPBLAS", "ON");
@@ -59,7 +61,7 @@ fn main() {
"CMAKE_CXX_COMPILER",
format!("{}/llvm/bin/clang++", rocm_root),
);
- config.define("AMDGPU_TARGETS", amd_gpu_targets.join(";"));
+ config.define("AMDGPU_TARGETS", amd_gpu_targets);
println!("cargo:rustc-link-arg=-Wl,--copy-dt-needed-entries");
println!("cargo:rustc-link-search=native={}/hip/lib", rocm_root);
println!("cargo:rustc-link-search=native={}/rocblas/lib", rocm_root);
diff --git a/crates/llama-cpp-bindings/src/llama.rs b/crates/llama-cpp-bindings/src/llama.rs
index 15db1358dc5..b288a3adc26 100644
--- a/crates/llama-cpp-bindings/src/llama.rs
+++ b/crates/llama-cpp-bindings/src/llama.rs
@@ -83,7 +83,7 @@ impl LlamaServiceImpl {
};
for ffi::StepOutput { request_id, text } in result {
- let mut stopped = false;
+ let mut stopped;
let LlamaRunningRequest { tx, stop_condition } =
self.requests.get_mut(&request_id).unwrap();
diff --git a/crates/tabby/src/services/health.rs b/crates/tabby/src/services/health.rs
index 386747da632..7ad42f95089 100644
--- a/crates/tabby/src/services/health.rs
+++ b/crates/tabby/src/services/health.rs
@@ -22,7 +22,7 @@ pub struct HealthState {
cpu_info: String,
cpu_count: usize,
accelerators: Vec,
- #[deprecated(note = "Use the more generic gpu_devices instead")]
+ #[deprecated(note = "Please use the more generic accelerators instead")]
cuda_devices: Vec,
version: Version,
}
@@ -103,7 +103,7 @@ pub fn read_rocm_devices() -> Result> {
Regex::new(r"(?m)^ Device Type: +([a-zA-Z0-9-]+) *$").unwrap();
}
- let cmd_res = Command::new("rocminfon").output()?;
+ let cmd_res = Command::new("rocminfo").output()?;
let output = from_utf8(cmd_res.stdout.as_slice())?;
let agent_outputs = output.split("Agent ").skip(1);
let mut rocm_devices = vec![];
diff --git a/ee/tabby-webserver/src/api.rs b/ee/tabby-webserver/src/api.rs
index aa182c590d9..36031fe3f1a 100644
--- a/ee/tabby-webserver/src/api.rs
+++ b/ee/tabby-webserver/src/api.rs
@@ -6,7 +6,7 @@ use tabby_common::api::{
};
use tokio_tungstenite::connect_async;
-use crate::{
+pub use crate::{
schema::worker::{RegisterWorkerError, Worker, WorkerKind},
websocket::WebSocketTransport,
};
diff --git a/ee/tabby-webserver/src/lib.rs b/ee/tabby-webserver/src/lib.rs
index 1cc902b38ac..484165246a8 100644
--- a/ee/tabby-webserver/src/lib.rs
+++ b/ee/tabby-webserver/src/lib.rs
@@ -26,7 +26,7 @@ use schema::{
};
use service::create_service_locator;
use tabby_common::api::{
- accelerator::Accelerator,
+ accelerator::{Accelerator, DeviceType},
code::{CodeSearch, SearchResponse},
event::RawEventLogger,
};
@@ -159,6 +159,15 @@ impl Hub for Arc {
let addr = format!("http://{}:{}", self.conn.ip(), port);
*worker_addr = addr.clone();
+ let mut cuda_devices = vec![];
+
+ for accelerator in &accelerators {
+ if accelerator.device_type == DeviceType::Cuda {
+ cuda_devices.push(accelerator.display_name.clone())
+ }
+ }
+
+ #[allow(deprecated)]
let worker = Worker {
name,
kind,
@@ -168,6 +177,7 @@ impl Hub for Arc {
cpu_info,
cpu_count,
accelerators,
+ cuda_devices,
};
self.ctx.worker().register_worker(worker).await
}
diff --git a/ee/tabby-webserver/src/schema/worker.rs b/ee/tabby-webserver/src/schema/worker.rs
index 64f6b1a4ef5..20af4af380f 100644
--- a/ee/tabby-webserver/src/schema/worker.rs
+++ b/ee/tabby-webserver/src/schema/worker.rs
@@ -23,6 +23,8 @@ pub struct Worker {
pub cpu_info: String,
pub cpu_count: i32,
pub accelerators: Vec,
+ #[deprecated(note = "Please use the more generic accelerators instead")]
+ pub cuda_devices: Vec,
}
#[derive(Serialize, Deserialize, Error, Debug)]
diff --git a/ee/tabby-webserver/src/service/worker.rs b/ee/tabby-webserver/src/service/worker.rs
index 195a6a1e870..1292049cd4d 100644
--- a/ee/tabby-webserver/src/service/worker.rs
+++ b/ee/tabby-webserver/src/service/worker.rs
@@ -82,6 +82,7 @@ mod tests {
}
fn make_worker(addr: &str) -> Worker {
+ #[allow(deprecated)]
Worker {
name: "Fake worker".to_owned(),
kind: WorkerKind::Chat,
@@ -91,6 +92,7 @@ mod tests {
cpu_info: "Fake CPU".to_owned(),
cpu_count: 32,
accelerators: vec![],
+ cuda_devices: vec![],
}
}
}
From 94d22c42f4c27683ec45b136d642452a87ad8027 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 10 Dec 2023 15:15:31 +0100
Subject: [PATCH 18/25] Added rocm binary build
---
.github/workflows/release.yml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b22676562ba..8f0ba9bc75a 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -26,7 +26,7 @@ jobs:
container: ${{ matrix.container }}
strategy:
matrix:
- binary: [aarch64-apple-darwin, x86_64-manylinux2014, x86_64-manylinux2014-cuda117]
+ binary: [aarch64-apple-darwin, x86_64-manylinux2014, x86_64-manylinux2014-cuda117, x86_64-manylinux2014-rocm5.7]
include:
- os: macos-latest
target: aarch64-apple-darwin
@@ -40,6 +40,11 @@ jobs:
binary: x86_64-manylinux2014-cuda117
container: sameli/manylinux2014_x86_64_cuda_11.7
build_args: --features cuda
+ - os: ubuntu-latest
+ target: x86_64-unknown-linux-gnu
+ binary: x86_64-manylinux2014-rocm5.7
+ container: rocm/dev-ubuntu-22.04:rocm5.7
+ build_args: --features rocm
env:
SCCACHE_GHA_ENABLED: true
From b3ef2e26ba9056ebf137ea85b59da1a665f9f0ac Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Fri, 22 Dec 2023 13:01:31 +0100
Subject: [PATCH 19/25] Added ROCm 6.0 build
---
.github/workflows/release.yml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4b39430aec9..720a966d4be 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -66,6 +66,11 @@ jobs:
binary: x86_64-manylinux2014-rocm57
container: ghcr.io/cromefire/hipblas-manylinux/2014/5.7:latest
build_args: --features rocm
+ - os: ubuntu-latest
+ target: x86_64-unknown-linux-gnu
+ binary: x86_64-manylinux2014-rocm60
+ container: ghcr.io/cromefire/hipblas-manylinux/2014/6.0:latest
+ build_args: --features rocm
env:
SCCACHE_GHA_ENABLED: true
From df62a7d8e9c2b5cfecbb6a312eda46020f57b478 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Fri, 22 Dec 2023 14:15:20 +0100
Subject: [PATCH 20/25] Fixed build and slimmed down container
---
Cargo.lock | 1 +
crates/tabby/src/worker.rs | 9 +++++++-
ee/tabby-webserver/src/hub/api.rs | 2 ++
ee/tabby-webserver/src/hub/mod.rs | 2 ++
ee/tabby-webserver/src/lib.rs | 10 +-------
rocm.Dockerfile | 38 ++++++++++++++++++++++---------
6 files changed, 41 insertions(+), 21 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index ac879cdf0ec..4a2dc9600cc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3712,6 +3712,7 @@ dependencies = [
"filenamify",
"glob",
"home",
+ "juniper",
"lazy_static",
"reqwest",
"serde",
diff --git a/crates/tabby/src/worker.rs b/crates/tabby/src/worker.rs
index f859550026d..3e88b444ad3 100644
--- a/crates/tabby/src/worker.rs
+++ b/crates/tabby/src/worker.rs
@@ -91,7 +91,13 @@ struct WorkerContext {
impl WorkerContext {
async fn new(kind: WorkerKind, args: &WorkerArgs) -> Self {
let (cpu_info, cpu_count) = read_cpu_info();
- let cuda_devices = read_cuda_devices().unwrap_or_default();
+ let accelerators = read_accelerators();
+
+ // For compatibility
+ let mut cuda_devices = vec![];
+ for accelerator in &accelerators {
+ cuda_devices.push(accelerator.display_name.clone());
+ }
Self {
client: tabby_webserver::public::create_client(
@@ -105,6 +111,7 @@ impl WorkerContext {
arch: ARCH.to_string(),
cpu_info,
cpu_count: cpu_count as i32,
+ cuda_devices,
accelerators,
},
)
diff --git a/ee/tabby-webserver/src/hub/api.rs b/ee/tabby-webserver/src/hub/api.rs
index 61de89b2eec..62ce8dc4663 100644
--- a/ee/tabby-webserver/src/hub/api.rs
+++ b/ee/tabby-webserver/src/hub/api.rs
@@ -3,6 +3,7 @@ use axum::{headers::Header, http::HeaderName};
use hyper::Request;
use serde::{Deserialize, Serialize};
use tabby_common::api::{
+ accelerator::Accelerator,
code::{CodeSearch, CodeSearchError, SearchResponse},
event::RawEventLogger,
};
@@ -109,6 +110,7 @@ pub struct RegisterWorkerRequest {
pub cpu_info: String,
pub cpu_count: i32,
pub cuda_devices: Vec,
+ pub accelerators: Vec,
}
pub static REGISTER_WORKER_HEADER: HeaderName = HeaderName::from_static("x-tabby-register-worker");
diff --git a/ee/tabby-webserver/src/hub/mod.rs b/ee/tabby-webserver/src/hub/mod.rs
index de459527c85..8dcc3b55bc3 100644
--- a/ee/tabby-webserver/src/hub/mod.rs
+++ b/ee/tabby-webserver/src/hub/mod.rs
@@ -45,6 +45,7 @@ pub(crate) async fn ws_handler(
let addr = format!("http://{}:{}", addr.ip(), request.port);
+ #[allow(deprecated)]
let worker = Worker {
name: request.name,
kind: request.kind,
@@ -54,6 +55,7 @@ pub(crate) async fn ws_handler(
cpu_info: request.cpu_info,
cpu_count: request.cpu_count,
cuda_devices: request.cuda_devices,
+ accelerators: request.accelerators,
};
ws.on_upgrade(move |socket| handle_socket(state, socket, worker))
diff --git a/ee/tabby-webserver/src/lib.rs b/ee/tabby-webserver/src/lib.rs
index af79bbf1238..6c38e121775 100644
--- a/ee/tabby-webserver/src/lib.rs
+++ b/ee/tabby-webserver/src/lib.rs
@@ -17,7 +17,6 @@ pub mod public {
use std::sync::Arc;
-use api::Hub;
use axum::{
extract::State,
http::Request,
@@ -29,14 +28,7 @@ use juniper_axum::{graphiql, graphql, playground};
pub use schema::create_schema;
use schema::{Schema, ServiceLocator};
use service::create_service_locator;
-use tabby_common::api::{
- accelerator::{Accelerator, DeviceType},
- code::{CodeSearch, SearchResponse},
- event::RawEventLogger,
-};
-use tokio::sync::Mutex;
-use tracing::{error, warn};
-use websocket::WebSocketTransport;
+use tabby_common::api::{code::CodeSearch, event::RawEventLogger};
pub async fn attach_webserver(
api: Router,
diff --git a/rocm.Dockerfile b/rocm.Dockerfile
index 87ccd51acf1..dddbd373417 100644
--- a/rocm.Dockerfile
+++ b/rocm.Dockerfile
@@ -1,12 +1,26 @@
-ARG UBUNTU_VERSION=22.04
-# This needs to generally match the container host's environment.
-ARG ROCM_VERSION=5.7
-# Target the CUDA build image
-ARG BASE_ROCM_DEV_CONTAINER="rocm/dev-ubuntu-${UBUNTU_VERSION}:${ROCM_VERSION}-complete"
-# Target the CUDA runtime image
-ARG BASE_ROCM_RUN_CONTAINER="rocm/dev-ubuntu-${UBUNTU_VERSION}:${ROCM_VERSION}-complete"
+# Ubuntu version to be used as base
+ARG UBUNTU_VERSION=jammy
+# URL to the amdgpu-install debian package
+ARG AMDGPU_INSTALL_URL=https://repo.radeon.com/amdgpu-install/6.0/ubuntu/${UBUNTU_VERSION}/amdgpu-install_6.0.60000-1_all.deb
-FROM ${BASE_ROCM_DEV_CONTAINER} as build
+FROM ubuntu:${UBUNTU_VERSION} as hipblas_base
+
+ARG AMDGPU_INSTALL_URL
+
+# Install ROCm
+RUN apt-get update && \
+ apt-get install -y curl ca-certificates && \
+ curl -Lo /tmp/amdgpu-install.deb "${AMDGPU_INSTALL_URL}" && \
+ apt-get install -y /tmp/amdgpu-install.deb && \
+ rm /tmp/amdgpu-install.deb && \
+ apt-get update && \
+ apt-get install -y "hipblas" && \
+ apt-get purge -y curl ca-certificates && \
+ apt-get autoremove -y && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+FROM hipblas_base as build
# Rust toolchain version
ARG RUST_TOOLCHAIN=stable
@@ -15,23 +29,25 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
+ ca-certificates \
pkg-config \
libssl-dev \
protobuf-compiler \
git \
cmake \
+ hipblas-dev \
+ build-essential \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# setup rust.
-RUN curl https://sh.rustup.rs -sSf | bash -s -- --default-toolchain ${RUST_TOOLCHAIN} -y
+RUN curl https://sh.rustup.rs -sSf | sh -s -- --profile minimal --no-modify-path --default-toolchain ${RUST_TOOLCHAIN} -y
ENV PATH="/root/.cargo/bin:${PATH}"
WORKDIR /root/workspace
RUN mkdir -p /opt/tabby/bin
-RUN mkdir -p /opt/tabby/lib
RUN mkdir -p target
COPY . .
@@ -41,7 +57,7 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \
cargo build --features rocm --release --package tabby && \
cp target/release/tabby /opt/tabby/bin/
-FROM ${BASE_ROCM_RUN_CONTAINER} as runtime
+FROM hipblas_base as runtime
RUN apt-get update && \
apt-get install -y --no-install-recommends \
From 234f58a8ae810e759601261fdae291927cb7be21 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Tue, 2 Jan 2024 18:49:24 +0100
Subject: [PATCH 21/25] Fixed certificates in docker file
---
rocm.Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rocm.Dockerfile b/rocm.Dockerfile
index dddbd373417..e1d5807cdd5 100644
--- a/rocm.Dockerfile
+++ b/rocm.Dockerfile
@@ -15,7 +15,7 @@ RUN apt-get update && \
rm /tmp/amdgpu-install.deb && \
apt-get update && \
apt-get install -y "hipblas" && \
- apt-get purge -y curl ca-certificates && \
+ apt-get purge -y curl && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
From 28ce9f1653f2c479f61d2cb9f4afd331b36b7e4f Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Tue, 2 Jan 2024 18:57:35 +0100
Subject: [PATCH 22/25] Fixed merge issue
---
crates/juniper-axum/src/lib.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/crates/juniper-axum/src/lib.rs b/crates/juniper-axum/src/lib.rs
index 092f46f873d..15ae6380f78 100644
--- a/crates/juniper-axum/src/lib.rs
+++ b/crates/juniper-axum/src/lib.rs
@@ -1,4 +1,5 @@
pub mod extract;
+pub mod relay;
pub mod response;
use std::future;
From fd0891bd6571e74495c85657b584d7e236d59bd3 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Tue, 2 Jan 2024 18:59:58 +0100
Subject: [PATCH 23/25] Fixed merge issue in workflow
---
.github/workflows/release.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d3c910b3455..d0e97be204b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -12,7 +12,7 @@ on:
- '.github/workflows/release.yml'
concurrency:
- group: ${{ github.workflow_ref }}-${{ github.head_ref || github.ref_name }}
+ group: ${{ github.workflow_ref }}-${{ github.head_ref || github.ref_name }}
# If this is enabled it will cancel current running and start latest
cancel-in-progress: true
@@ -26,7 +26,7 @@ jobs:
container: ${{ matrix.container }}
strategy:
matrix:
- binary: [aarch64-apple-darwin, x86_64-manylinux2014, x86_64-windows-msvc, x86_64-manylinux2014-cuda117, x86_64-manylinux2014-cuda122, x86_64-windows-msvc-cuda117, x86_64-windows-msvc-cuda122, x86_64-manylinux2014-rocm57]
+ binary: [ aarch64-apple-darwin, x86_64-manylinux2014, x86_64-windows-msvc, x86_64-manylinux2014-cuda117, x86_64-manylinux2014-cuda122, x86_64-windows-msvc-cuda117, x86_64-windows-msvc-cuda122, x86_64-manylinux2014-rocm57, x86_64-manylinux2014-rocm60 ]
include:
- os: macos-latest
target: aarch64-apple-darwin
@@ -151,7 +151,7 @@ jobs:
- uses: ncipollo/release-action@v1
with:
- allowUpdates: true
+ allowUpdates: true
prerelease: true
artifacts: "tabby_*/tabby_*"
tag: ${{ github.ref_name }}
From b13bbec224aa1f9818f83cd3b4f9494d80b7302e Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Sun, 14 Jan 2024 23:53:08 +0100
Subject: [PATCH 24/25] Added support for specifying targets for docker build
---
rocm.Dockerfile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/rocm.Dockerfile b/rocm.Dockerfile
index e1d5807cdd5..655a1e7ab08 100644
--- a/rocm.Dockerfile
+++ b/rocm.Dockerfile
@@ -6,6 +6,8 @@ ARG AMDGPU_INSTALL_URL=https://repo.radeon.com/amdgpu-install/6.0/ubuntu/${UBUNT
FROM ubuntu:${UBUNTU_VERSION} as hipblas_base
ARG AMDGPU_INSTALL_URL
+ARG AMDGPU_TARGETS
+ENV PATH="/opt/rocm/bin:${PATH}"
# Install ROCm
RUN apt-get update && \
From 99f63f36a91dcbaf760e0d17aa08851ba36985b6 Mon Sep 17 00:00:00 2001
From: Cromefire_
Date: Mon, 15 Jan 2024 02:57:25 +0100
Subject: [PATCH 25/25] Fixed docker build
---
.dockerignore | 2 ++
.gitignore | 1 +
crates/llama-cpp-bindings/build.rs | 3 +++
rocm.Dockerfile | 16 +++++++++++-----
4 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/.dockerignore b/.dockerignore
index bfbb41f4fe5..aee7e976293 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -6,3 +6,5 @@ python
**/target
**/node_modules
website
+*.log
+*.Dockerfile
diff --git a/.gitignore b/.gitignore
index dcdc169416a..5e61104ff3d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ node_modules
.DS_Store
.vscode/
__pycache__
+*.log
diff --git a/crates/llama-cpp-bindings/build.rs b/crates/llama-cpp-bindings/build.rs
index 78076eb4268..d0363840a5c 100644
--- a/crates/llama-cpp-bindings/build.rs
+++ b/crates/llama-cpp-bindings/build.rs
@@ -21,6 +21,9 @@ fn main() {
fn build_llama_cpp() {
let mut config = Config::new("llama.cpp");
+ config.define("LLAMA_BUILD_TESTS", "OFF");
+ config.define("LLAMA_BUILD_EXAMPLES", "OFF");
+ config.define("LLAMA_BUILD_SERVER", "OFF");
if cfg!(target_os = "macos") {
config.define("LLAMA_METAL", "ON");
println!("cargo:rustc-link-lib=framework=Foundation");
diff --git a/rocm.Dockerfile b/rocm.Dockerfile
index 655a1e7ab08..e65b64e567b 100644
--- a/rocm.Dockerfile
+++ b/rocm.Dockerfile
@@ -6,8 +6,8 @@ ARG AMDGPU_INSTALL_URL=https://repo.radeon.com/amdgpu-install/6.0/ubuntu/${UBUNT
FROM ubuntu:${UBUNTU_VERSION} as hipblas_base
ARG AMDGPU_INSTALL_URL
-ARG AMDGPU_TARGETS
ENV PATH="/opt/rocm/bin:${PATH}"
+ENV LD_LIBRARY_PATH="/opt/rocm/lib:${LD_LIBRARY_PATH}"
# Install ROCm
RUN apt-get update && \
@@ -16,7 +16,7 @@ RUN apt-get update && \
apt-get install -y /tmp/amdgpu-install.deb && \
rm /tmp/amdgpu-install.deb && \
apt-get update && \
- apt-get install -y "hipblas" && \
+ apt-get install -y --no-install-recommends hipblas rocblas comgr && \
apt-get purge -y curl && \
apt-get autoremove -y && \
apt-get clean && \
@@ -38,13 +38,16 @@ RUN apt-get update && \
git \
cmake \
hipblas-dev \
+ rocblas-dev \
+ rocm-device-libs \
build-essential \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# setup rust.
-RUN curl https://sh.rustup.rs -sSf | sh -s -- --profile minimal --no-modify-path --default-toolchain ${RUST_TOOLCHAIN} -y
+RUN curl https://sh.rustup.rs -sSf | sh -s -- --profile minimal --no-modify-path --default-toolchain ${RUST_TOOLCHAIN} -y && \
+ /root/.cargo/bin/cargo --version
ENV PATH="/root/.cargo/bin:${PATH}"
WORKDIR /root/workspace
@@ -54,11 +57,14 @@ RUN mkdir -p target
COPY . .
+ARG AMDGPU_TARGETS
+
RUN --mount=type=cache,target=/usr/local/cargo/registry \
- --mount=type=cache,target=/root/workspace/target \
- cargo build --features rocm --release --package tabby && \
+ cargo build -vv --features rocm --release --package tabby && \
cp target/release/tabby /opt/tabby/bin/
+RUN ldd /opt/tabby/bin/tabby 2>&1 | grep rocm > /dev/null
+
FROM hipblas_base as runtime
RUN apt-get update && \