version: 2.1
orbs:
  win: circleci/windows@5.0
  python: circleci/python@1.2
  node: circleci/node@5.1

parameters:
  run-all-workflows:
    type: boolean
    default: false
  run-python-workflow:
    type: boolean
    default: false
  run-chat-workflow:
    type: boolean
    default: false
  run-ts-workflow:
    type: boolean
    default: false

jobs:
  # work around CircleCI-Public/path-filtering-orb#20
  noop:
    docker:
      - image: cimg/base:current
    steps:
      - run: "true"

  build-offline-chat-installer-macos:
    macos:
      xcode: 15.4.0
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-macos-
      - run:
          name: Install Rosetta
          command: softwareupdate --install-rosetta --agree-to-license  # needed for QtIFW
      - run:
          name: Install dependencies
          command: brew install ccache wget
      - run:
          name: Installing Qt
          command: |
            wget "https://gpt4all.io/ci/qt-unified-macOS-x64-4.6.0-online.dmg"
            hdiutil attach qt-unified-macOS-x64-4.6.0-online.dmg
            /Volumes/qt-unified-macOS-x64-4.6.0-online/qt-unified-macOS-x64-4.6.0-online.app/Contents/MacOS/qt-unified-macOS-x64-4.6.0-online --no-force-installations --no-default-installations --no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations --email $QT_EMAIL --password $QT_PASSWORD install qt.tools.cmake qt.tools.ifw.48 qt.tools.ninja qt.qt6.651.clang_64 qt.qt6.651.qt5compat qt.qt6.651.debug_info qt.qt6.651.addons.qtpdf qt.qt6.651.addons.qthttpserver
            hdiutil detach /Volumes/qt-unified-macOS-x64-4.6.0-online
      - run:
          name: Setup Keychain
          command: |
            echo $MAC_SIGNING_CERT | base64 --decode > cert.p12
            security create-keychain -p "$MAC_KEYCHAIN_KEY" sign.keychain
            security default-keychain -s sign.keychain
            security unlock-keychain -p "$MAC_KEYCHAIN_KEY" sign.keychain
            security import cert.p12 -k sign.keychain -P "$MAC_SIGNING_CERT_PWD" -T /usr/bin/codesign
            security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MAC_KEYCHAIN_KEY" sign.keychain
      - run:
          name: Build
          no_output_timeout: 30m
          command: |
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            mkdir build
            cd build
            export PATH=$PATH:$HOME/Qt/Tools/QtInstallerFramework/4.8/bin
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake \
              -S ../gpt4all-chat -B . -G Ninja \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_PREFIX_PATH:PATH=~/Qt/6.5.1/macos/lib/cmake \
              -DCMAKE_MAKE_PROGRAM:FILEPATH=~/Qt/Tools/Ninja/ninja \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DBUILD_UNIVERSAL=ON \
              -DCMAKE_OSX_DEPLOYMENT_TARGET=12.6 \
              -DGGML_METAL_MACOSX_VERSION_MIN=12.6 \
              -DMACDEPLOYQT=~/Qt/6.5.1/macos/bin/macdeployqt \
              -DGPT4ALL_OFFLINE_INSTALLER=ON \
              -DGPT4ALL_SIGN_INSTALL=ON
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake --build . --target all
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake --build . --target install
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake --build . --target package
            ccache -s
            mkdir upload
            cp gpt4all-installer-* upload
      # persist the unsigned installer
      - store_artifacts:
          path: build/upload
      - save_cache:
          key: ccache-gpt4all-macos-{{ epoch }}
          when: always
          paths:
            - ../.ccache
      # add workspace so signing jobs can connect & obtain dmg
      - persist_to_workspace:
          root: build
          # specify path to only include components we want to persist
          # accross builds
          paths:
            - upload

  sign-offline-chat-installer-macos:
    macos:
      xcode: 15.4.0
    steps:
      - checkout
      # attach to a workspace containing unsigned dmg
      - attach_workspace:
          at: build
      - run:
          name: "Setup Keychain"
          command: |
            echo $MAC_SIGNING_CERT | base64 --decode > cert.p12
            security create-keychain -p "$MAC_KEYCHAIN_KEY" sign.keychain
            security default-keychain -s sign.keychain
            security unlock-keychain -p "$MAC_KEYCHAIN_KEY" sign.keychain
            security import cert.p12 -k sign.keychain -P "$MAC_SIGNING_CERT_PWD" -T /usr/bin/codesign
            security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MAC_KEYCHAIN_KEY" sign.keychain
            rm cert.p12
      - run:
          name: "Sign App Bundle"
          command: |
            python3 -m pip install click
            python3 gpt4all-chat/cmake/sign_dmg.py --input-dmg build/upload/gpt4all-installer-darwin.dmg --output-dmg build/upload/gpt4all-installer-darwin-signed.dmg --signing-identity "$MAC_SIGNING_CERT_NAME"
      - run:
          name: "Sign DMG"
          command: |
            codesign --options runtime --timestamp -s "$MAC_SIGNING_CERT_NAME" build/upload/gpt4all-installer-darwin-signed.dmg
      # add workspace so signing jobs can connect & obtain dmg
      - persist_to_workspace:
          root: build
          # specify path to only include components we want to persist
          # accross builds
          paths:
            - upload

  notarize-offline-chat-installer-macos:
    macos:
      xcode: 15.4.0
    steps:
      - checkout
      - attach_workspace:
          at: build
      - run:
          name: "Notarize"
          command: |
            xcrun notarytool submit build/upload/gpt4all-installer-darwin-signed.dmg --apple-id "$MAC_NOTARIZATION_ID" --team-id "$MAC_NOTARIZATION_TID" --password "$MAC_NOTARIZATION_KEY" --wait  | tee notarize_log.txt
      - run:
          name: "Report Notarization Failure"
          command: |
            NID=`python3 .circleci/grab_notary_id.py notarize_log.txt` && export NID
            xcrun notarytool log $NID --keychain-profile "notary-profile"
            exit 1
          when: on_fail
      - run:
          name: "Staple"
          command: |
            xcrun stapler staple build/upload/gpt4all-installer-darwin-signed.dmg
      - store_artifacts:
          path: build/upload

  build-online-chat-installer-macos:
    macos:
      xcode: 15.4.0
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-macos-
      - run:
          name: Install Rosetta
          command: softwareupdate --install-rosetta --agree-to-license  # needed for QtIFW
      - run:
          name: Install dependencies
          command: brew install ccache wget
      - run:
          name: Installing Qt
          command: |
            wget "https://gpt4all.io/ci/qt-unified-macOS-x64-4.6.0-online.dmg"
            hdiutil attach qt-unified-macOS-x64-4.6.0-online.dmg
            /Volumes/qt-unified-macOS-x64-4.6.0-online/qt-unified-macOS-x64-4.6.0-online.app/Contents/MacOS/qt-unified-macOS-x64-4.6.0-online --no-force-installations --no-default-installations --no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations --email $QT_EMAIL --password $QT_PASSWORD install qt.tools.cmake qt.tools.ifw.48 qt.tools.ninja qt.qt6.651.clang_64 qt.qt6.651.qt5compat qt.qt6.651.debug_info qt.qt6.651.addons.qtpdf qt.qt6.651.addons.qthttpserver
            hdiutil detach /Volumes/qt-unified-macOS-x64-4.6.0-online
      - run:
          name: Setup Keychain
          command: |
            echo $MAC_SIGNING_CERT | base64 --decode > cert.p12
            security create-keychain -p "$MAC_KEYCHAIN_KEY" sign.keychain
            security default-keychain -s sign.keychain
            security unlock-keychain -p "$MAC_KEYCHAIN_KEY" sign.keychain
            security import cert.p12 -k sign.keychain -P "$MAC_SIGNING_CERT_PWD" -T /usr/bin/codesign
            security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MAC_KEYCHAIN_KEY" sign.keychain
      - run:
          name: Build
          no_output_timeout: 30m
          command: |
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            mkdir build
            cd build
            export PATH=$PATH:$HOME/Qt/Tools/QtInstallerFramework/4.8/bin
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake \
              -S ../gpt4all-chat -B . -G Ninja \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_PREFIX_PATH:PATH=~/Qt/6.5.1/macos/lib/cmake \
              -DCMAKE_MAKE_PROGRAM:FILEPATH=~/Qt/Tools/Ninja/ninja \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DBUILD_UNIVERSAL=ON \
              -DCMAKE_OSX_DEPLOYMENT_TARGET=12.6 \
              -DGGML_METAL_MACOSX_VERSION_MIN=12.6 \
              -DMACDEPLOYQT=~/Qt/6.5.1/macos/bin/macdeployqt \
              -DGPT4ALL_OFFLINE_INSTALLER=OFF \
              -DGPT4ALL_SIGN_INSTALL=ON
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake --build . --target all
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake --build . --target install
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake --build . --target package
            ccache -s
            mkdir upload
            cp gpt4all-installer-* upload
            tar -cvzf upload/repository.tar.gz -C _CPack_Packages/Darwin/IFW/gpt4all-installer-darwin repository
      # persist the unsigned installer
      - store_artifacts:
          path: build/upload
      - save_cache:
          key: ccache-gpt4all-macos-{{ epoch }}
          when: always
          paths:
            - ../.ccache
      # add workspace so signing jobs can connect & obtain dmg
      - persist_to_workspace:
          root: build
          # specify path to only include components we want to persist
          # accross builds
          paths:
            - upload

  sign-online-chat-installer-macos:
    macos:
      xcode: 15.4.0
    steps:
      - checkout
      # attach to a workspace containing unsigned dmg
      - attach_workspace:
          at: build
      - run:
          name: "Setup Keychain"
          command: |
            echo $MAC_SIGNING_CERT | base64 --decode > cert.p12
            security create-keychain -p "$MAC_KEYCHAIN_KEY" sign.keychain
            security default-keychain -s sign.keychain
            security unlock-keychain -p "$MAC_KEYCHAIN_KEY" sign.keychain
            security import cert.p12 -k sign.keychain -P "$MAC_SIGNING_CERT_PWD" -T /usr/bin/codesign
            security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MAC_KEYCHAIN_KEY" sign.keychain
            rm cert.p12
      - run:
          name: "Sign App Bundle"
          command: |
            python3 -m pip install click
            python3 gpt4all-chat/cmake/sign_dmg.py --input-dmg build/upload/gpt4all-installer-darwin.dmg --output-dmg build/upload/gpt4all-installer-darwin-signed.dmg --signing-identity "$MAC_SIGNING_CERT_NAME"
      - run:
          name: "Sign DMG"
          command: |
            codesign --options runtime --timestamp -s "$MAC_SIGNING_CERT_NAME" build/upload/gpt4all-installer-darwin-signed.dmg
      # add workspace so signing jobs can connect & obtain dmg
      - persist_to_workspace:
          root: build
          # specify path to only include components we want to persist
          # accross builds
          paths:
            - upload

  notarize-online-chat-installer-macos:
    macos:
      xcode: 15.4.0
    steps:
      - checkout
      - attach_workspace:
          at: build
      - run:
          name: "Notarize"
          command: |
            xcrun notarytool submit build/upload/gpt4all-installer-darwin-signed.dmg --apple-id "$MAC_NOTARIZATION_ID" --team-id "$MAC_NOTARIZATION_TID" --password "$MAC_NOTARIZATION_KEY" --wait  | tee notarize_log.txt
      - run:
          name: "Report Notarization Failure"
          command: |
            NID=`python3 .circleci/grab_notary_id.py notarize_log.txt` && export NID
            xcrun notarytool log $NID --keychain-profile "notary-profile"
            exit 1
          when: on_fail
      - run:
          name: "Staple"
          command: |
            xcrun stapler staple build/upload/gpt4all-installer-darwin-signed.dmg
      - store_artifacts:
          path: build/upload

  build-offline-chat-installer-linux:
    machine:
      image: ubuntu-2204:current
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-linux-amd64-
      - run:
          name: Setup Linux and Dependencies
          command: |
            wget -qO- "https://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc
            wget -qO- "https://packages.lunarg.com/vulkan/1.3.290/lunarg-vulkan-1.3.290-jammy.list" | sudo tee /etc/apt/sources.list.d/lunarg-vulkan-1.3.290-jammy.list
            wget "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb"
            sudo dpkg -i cuda-keyring_1.1-1_all.deb
            packages=(
              bison build-essential ccache cuda-compiler-11-8 flex g++-12 gperf libcublas-dev-11-8 libfontconfig1
              libfreetype6 libgl1-mesa-dev libmysqlclient21 libnvidia-compute-550-server libodbc2 libpq5 libwayland-dev
              libx11-6 libx11-xcb1 libxcb-cursor0 libxcb-glx0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0
              libxcb-render-util0 libxcb-shape0 libxcb-shm0 libxcb-sync1 libxcb-util1 libxcb-xfixes0 libxcb-xinerama0
              libxcb-xkb1 libxcb1 libxext6 libxfixes3 libxi6 libxkbcommon-dev libxkbcommon-x11-0 libxrender1 patchelf
              python3 vulkan-sdk
            )
            sudo apt-get update
            sudo apt-get install -y "${packages[@]}"
      - run:
          name: Installing Qt
          command: |
            wget "https://gpt4all.io/ci/qt-unified-linux-x64-4.6.0-online.run"
            chmod +x qt-unified-linux-x64-4.6.0-online.run
            ./qt-unified-linux-x64-4.6.0-online.run --no-force-installations --no-default-installations --no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations --email $QT_EMAIL --password $QT_PASSWORD install qt.tools.cmake qt.tools.ifw.48 qt.tools.ninja qt.qt6.651.gcc_64 qt.qt6.651.qt5compat qt.qt6.651.debug_info qt.qt6.651.addons.qtpdf qt.qt6.651.addons.qthttpserver
      - run:
          name: Build linuxdeployqt
          command: |
            git clone https://github.com/nomic-ai/linuxdeployqt
            cd linuxdeployqt && qmake && sudo make install
      - run:
          name: Build
          no_output_timeout: 30m
          command: |
            set -eo pipefail
            export CMAKE_PREFIX_PATH=~/Qt/6.5.1/gcc_64/lib/cmake
            export PATH=$PATH:$HOME/Qt/Tools/QtInstallerFramework/4.8/bin
            export PATH=$PATH:/usr/local/cuda/bin
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            mkdir build
            cd build
            mkdir upload
            ~/Qt/Tools/CMake/bin/cmake \
              -S ../gpt4all-chat -B . \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_C_COMPILER=gcc-12 \
              -DCMAKE_CXX_COMPILER=g++-12 \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache \
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON \
              -DGPT4ALL_OFFLINE_INSTALLER=ON
            ~/Qt/Tools/CMake/bin/cmake --build . -j$(nproc) --target all
            ~/Qt/Tools/CMake/bin/cmake --build . -j$(nproc) --target install
            ~/Qt/Tools/CMake/bin/cmake --build . -j$(nproc) --target package
            ccache -s
            cp gpt4all-installer-* upload
      - store_artifacts:
          path: build/upload
      - save_cache:
          key: ccache-gpt4all-linux-amd64-{{ epoch }}
          when: always
          paths:
            - ../.ccache

  build-online-chat-installer-linux:
    machine:
      image: ubuntu-2204:current
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-linux-amd64-
      - run:
          name: Setup Linux and Dependencies
          command: |
            wget -qO- "https://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc
            wget -qO- "https://packages.lunarg.com/vulkan/1.3.290/lunarg-vulkan-1.3.290-jammy.list" | sudo tee /etc/apt/sources.list.d/lunarg-vulkan-1.3.290-jammy.list
            wget "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb"
            sudo dpkg -i cuda-keyring_1.1-1_all.deb
            packages=(
              bison build-essential ccache cuda-compiler-11-8 flex g++-12 gperf libcublas-dev-11-8 libfontconfig1
              libfreetype6 libgl1-mesa-dev libmysqlclient21 libnvidia-compute-550-server libodbc2 libpq5 libwayland-dev
              libx11-6 libx11-xcb1 libxcb-cursor0 libxcb-glx0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0
              libxcb-render-util0 libxcb-shape0 libxcb-shm0 libxcb-sync1 libxcb-util1 libxcb-xfixes0 libxcb-xinerama0
              libxcb-xkb1 libxcb1 libxext6 libxfixes3 libxi6 libxkbcommon-dev libxkbcommon-x11-0 libxrender1 patchelf
              python3 vulkan-sdk
            )
            sudo apt-get update
            sudo apt-get install -y "${packages[@]}"
      - run:
          name: Installing Qt
          command: |
            wget "https://gpt4all.io/ci/qt-unified-linux-x64-4.6.0-online.run"
            chmod +x qt-unified-linux-x64-4.6.0-online.run
            ./qt-unified-linux-x64-4.6.0-online.run --no-force-installations --no-default-installations --no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations --email $QT_EMAIL --password $QT_PASSWORD install qt.tools.cmake qt.tools.ifw.48 qt.tools.ninja qt.qt6.651.gcc_64 qt.qt6.651.qt5compat qt.qt6.651.debug_info qt.qt6.651.addons.qtpdf qt.qt6.651.addons.qthttpserver
      - run:
          name: Build linuxdeployqt
          command: |
            git clone https://github.com/nomic-ai/linuxdeployqt
            cd linuxdeployqt && qmake && sudo make install
      - run:
          name: Build
          no_output_timeout: 30m
          command: |
            set -eo pipefail
            export CMAKE_PREFIX_PATH=~/Qt/6.5.1/gcc_64/lib/cmake
            export PATH=$PATH:$HOME/Qt/Tools/QtInstallerFramework/4.8/bin
            export PATH=$PATH:/usr/local/cuda/bin
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            mkdir build
            cd build
            mkdir upload
            ~/Qt/Tools/CMake/bin/cmake \
              -S ../gpt4all-chat -B . \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_C_COMPILER=gcc-12 \
              -DCMAKE_CXX_COMPILER=g++-12 \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache \
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON \
              -DGPT4ALL_OFFLINE_INSTALLER=OFF
            ~/Qt/Tools/CMake/bin/cmake --build . -j$(nproc) --target all
            ~/Qt/Tools/CMake/bin/cmake --build . -j$(nproc) --target install
            ~/Qt/Tools/CMake/bin/cmake --build . -j$(nproc) --target package
            ccache -s
            cp gpt4all-installer-* upload
            tar -cvzf upload/repository.tar.gz -C _CPack_Packages/Linux/IFW/gpt4all-installer-linux repository
      - store_artifacts:
          path: build/upload
      - save_cache:
          key: ccache-gpt4all-linux-amd64-{{ epoch }}
          when: always
          paths:
            - ../.ccache

  build-offline-chat-installer-windows:
    machine:
      image: windows-server-2022-gui:current
      resource_class: windows.large
      shell: powershell.exe -ExecutionPolicy Bypass
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-win-amd64-
      - run:
          name: Install dependencies
          command: choco install -y ccache wget
      - run:
          name: Installing Qt
          command: |
            wget.exe "https://gpt4all.io/ci/qt-unified-windows-x64-4.6.0-online.exe"
            & .\qt-unified-windows-x64-4.6.0-online.exe --no-force-installations --no-default-installations --no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations --email ${Env:QT_EMAIL} --password ${Env:QT_PASSWORD} install qt.tools.cmake qt.tools.ifw.48 qt.tools.ninja qt.qt6.651.win64_msvc2019_64 qt.qt6.651.qt5compat qt.qt6.651.debug_info qt.qt6.651.addons.qtpdf qt.qt6.651.addons.qthttpserver
      - run:
          name: Install VulkanSDK
          command: |
            wget.exe "https://sdk.lunarg.com/sdk/download/1.3.261.1/windows/VulkanSDK-1.3.261.1-Installer.exe"
            .\VulkanSDK-1.3.261.1-Installer.exe --accept-licenses --default-answer --confirm-command install
      - run:
          name: Install CUDA Toolkit
          command: |
            wget.exe "https://developer.download.nvidia.com/compute/cuda/11.8.0/network_installers/cuda_11.8.0_windows_network.exe"
            .\cuda_11.8.0_windows_network.exe -s cudart_11.8 nvcc_11.8 cublas_11.8 cublas_dev_11.8
      - run:
          name: "Install Dotnet 8"
          command: |
            mkdir dotnet
            cd dotnet
            $dotnet_url="https://download.visualstudio.microsoft.com/download/pr/5af098e1-e433-4fda-84af-3f54fd27c108/6bd1c6e48e64e64871957289023ca590/dotnet-sdk-8.0.302-win-x64.zip"
            wget.exe "$dotnet_url"
            Expand-Archive -LiteralPath .\dotnet-sdk-8.0.302-win-x64.zip
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
            $Env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=$true
            dotnet tool install --global AzureSignTool
      - run:
          name: Build
          no_output_timeout: 30m
          command: |
            $vsInstallPath = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -property installationpath
            Import-Module "${vsInstallPath}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
            Enter-VsDevShell -VsInstallPath "$vsInstallPath" -SkipAutomaticLocation -DevCmdArguments '-arch=x64 -no_logo'

            $Env:PATH = "${Env:PATH};C:\VulkanSDK\1.3.261.1\bin"
            $Env:PATH = "${Env:PATH};C:\Qt\Tools\QtInstallerFramework\4.8\bin"
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
            ccache -o "cache_dir=${pwd}\..\.ccache" -o max_size=500M -p -z
            mkdir build
            cd build
            & "C:\Qt\Tools\CMake_64\bin\cmake.exe" `
              -S ..\gpt4all-chat -B . -G Ninja `
              -DCMAKE_BUILD_TYPE=Release `
              "-DCMAKE_PREFIX_PATH:PATH=C:\Qt\6.5.1\msvc2019_64" `
              "-DCMAKE_MAKE_PROGRAM:FILEPATH=C:\Qt\Tools\Ninja\ninja.exe" `
              -DCMAKE_C_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache `
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON `
              -DGPT4ALL_OFFLINE_INSTALLER=ON
            & "C:\Qt\Tools\Ninja\ninja.exe"
            & "C:\Qt\Tools\Ninja\ninja.exe" install
            & "C:\Qt\Tools\Ninja\ninja.exe" package
            ccache -s
            mkdir upload
            copy gpt4all-installer-win64.exe upload
      - store_artifacts:
          path: build/upload
            # add workspace so signing jobs can connect & obtain dmg
      - save_cache:
          key: ccache-gpt4all-win-amd64-{{ epoch }}
          when: always
          paths:
            - ..\.ccache
      - persist_to_workspace:
          root: build
          # specify path to only include components we want to persist
          # accross builds
          paths:
            - upload

  sign-offline-chat-installer-windows:
    machine:
      image: windows-server-2022-gui:current
      resource_class: windows.large
      shell: powershell.exe -ExecutionPolicy Bypass
    steps:
      - checkout
      - attach_workspace:
          at: build
      - run:
          name: Install dependencies
          command: choco install -y wget
      - run:
          name: "Install Dotnet 8 && Azure Sign Tool"
          command: |
            mkdir dotnet
            cd dotnet
            $dotnet_url="https://download.visualstudio.microsoft.com/download/pr/5af098e1-e433-4fda-84af-3f54fd27c108/6bd1c6e48e64e64871957289023ca590/dotnet-sdk-8.0.302-win-x64.zip"
            wget.exe "$dotnet_url"
            Expand-Archive -LiteralPath .\dotnet-sdk-8.0.302-win-x64.zip
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
            $Env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=$true
            dotnet tool install --global AzureSignTool
      - run:
          name: "Sign Windows Installer With AST"
          command: |
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
            AzureSignTool.exe sign -du "https://gpt4all.io/index.html" -kvu https://gpt4all.vault.azure.net -kvi "$Env:AZSignGUID" -kvs "$Env:AZSignPWD" -kvc "$Env:AZSignCertName" -kvt "$Env:AZSignTID" -tr http://timestamp.digicert.com -v "$($(Get-Location).Path)\build\upload\gpt4all-installer-win64.exe"
      - store_artifacts:
          path: build/upload

  build-online-chat-installer-windows:
    machine:
      image: windows-server-2022-gui:current
      resource_class: windows.large
      shell: powershell.exe -ExecutionPolicy Bypass
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-win-amd64-
      - run:
          name: Install dependencies
          command: choco install -y ccache wget
      - run:
          name: Installing Qt
          command: |
            wget.exe "https://gpt4all.io/ci/qt-unified-windows-x64-4.6.0-online.exe"
            & .\qt-unified-windows-x64-4.6.0-online.exe --no-force-installations --no-default-installations --no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations --email ${Env:QT_EMAIL} --password ${Env:QT_PASSWORD} install qt.tools.cmake qt.tools.ifw.48 qt.tools.ninja qt.qt6.651.win64_msvc2019_64 qt.qt6.651.qt5compat qt.qt6.651.debug_info qt.qt6.651.addons.qtpdf qt.qt6.651.addons.qthttpserver
      - run:
          name: Install VulkanSDK
          command: |
            wget.exe "https://sdk.lunarg.com/sdk/download/1.3.261.1/windows/VulkanSDK-1.3.261.1-Installer.exe"
            .\VulkanSDK-1.3.261.1-Installer.exe --accept-licenses --default-answer --confirm-command install
      - run:
          name: Install CUDA Toolkit
          command: |
            wget.exe "https://developer.download.nvidia.com/compute/cuda/11.8.0/network_installers/cuda_11.8.0_windows_network.exe"
            .\cuda_11.8.0_windows_network.exe -s cudart_11.8 nvcc_11.8 cublas_11.8 cublas_dev_11.8
      - run:
          name: "Install Dotnet 8"
          command: |
            mkdir dotnet
            cd dotnet
            $dotnet_url="https://download.visualstudio.microsoft.com/download/pr/5af098e1-e433-4fda-84af-3f54fd27c108/6bd1c6e48e64e64871957289023ca590/dotnet-sdk-8.0.302-win-x64.zip"
            wget.exe "$dotnet_url"
            Expand-Archive -LiteralPath .\dotnet-sdk-8.0.302-win-x64.zip
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
      - run:
          name: "Setup Azure SignTool"
          command: |
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
            $Env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=$true
            dotnet tool install --global AzureSignTool
      - run:
          name: Build
          no_output_timeout: 30m
          command: |
            $vsInstallPath = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -property installationpath
            Import-Module "${vsInstallPath}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
            Enter-VsDevShell -VsInstallPath "$vsInstallPath" -SkipAutomaticLocation -DevCmdArguments '-arch=x64 -no_logo'

            $Env:PATH = "${Env:PATH};C:\VulkanSDK\1.3.261.1\bin"
            $Env:PATH = "${Env:PATH};C:\Qt\Tools\QtInstallerFramework\4.8\bin"
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
            ccache -o "cache_dir=${pwd}\..\.ccache" -o max_size=500M -p -z
            mkdir build
            cd build
            & "C:\Qt\Tools\CMake_64\bin\cmake.exe" `
              -S ..\gpt4all-chat -B . -G Ninja `
              -DCMAKE_BUILD_TYPE=Release `
              "-DCMAKE_PREFIX_PATH:PATH=C:\Qt\6.5.1\msvc2019_64" `
              "-DCMAKE_MAKE_PROGRAM:FILEPATH=C:\Qt\Tools\Ninja\ninja.exe" `
              -DCMAKE_C_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache `
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON `
              -DGPT4ALL_OFFLINE_INSTALLER=OFF
            & "C:\Qt\Tools\Ninja\ninja.exe"
            & "C:\Qt\Tools\Ninja\ninja.exe" install
            & "C:\Qt\Tools\Ninja\ninja.exe" package
            ccache -s
            mkdir upload
            copy gpt4all-installer-win64.exe upload
            Set-Location -Path "_CPack_Packages/win64/IFW/gpt4all-installer-win64"
            Compress-Archive -Path 'repository' -DestinationPath '..\..\..\..\upload\repository.zip'
      - store_artifacts:
          path: build/upload
      - save_cache:
          key: ccache-gpt4all-win-amd64-{{ epoch }}
          when: always
          paths:
            - ..\.ccache
      # add workspace so signing jobs can connect & obtain dmg
      - persist_to_workspace:
          root: build
          # specify path to only include components we want to persist
          # accross builds
          paths:
            - upload

  sign-online-chat-installer-windows:
    machine:
      image: windows-server-2022-gui:current
      resource_class: windows.large
      shell: powershell.exe -ExecutionPolicy Bypass
    steps:
      - checkout
      - attach_workspace:
          at: build
      - run:
          name: Install dependencies
          command: choco install -y wget
      - run:
          name: "Install Dotnet 8"
          command: |
            mkdir dotnet
            cd dotnet
            $dotnet_url="https://download.visualstudio.microsoft.com/download/pr/5af098e1-e433-4fda-84af-3f54fd27c108/6bd1c6e48e64e64871957289023ca590/dotnet-sdk-8.0.302-win-x64.zip"
            wget.exe "$dotnet_url"
            Expand-Archive -LiteralPath .\dotnet-sdk-8.0.302-win-x64.zip
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
      - run:
          name: "Setup Azure SignTool"
          command: |
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
            $Env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=$true
            dotnet tool install --global AzureSignTool
      - run:
          name: "Sign Windows Installer With AST"
          command: |
            $Env:DOTNET_ROOT="$($(Get-Location).Path)\dotnet\dotnet-sdk-8.0.302-win-x64"
            $Env:PATH="$Env:DOTNET_ROOT;$Env:PATH"
            AzureSignTool.exe sign -du "https://gpt4all.io/index.html" -kvu https://gpt4all.vault.azure.net -kvi "$Env:AZSignGUID" -kvs "$Env:AZSignPWD" -kvc "$Env:AZSignCertName" -kvt "$Env:AZSignTID" -tr http://timestamp.digicert.com -v "$($(Get-Location).Path)/build/upload/gpt4all-installer-win64.exe"
      - store_artifacts:
          path: build/upload

  build-gpt4all-chat-linux:
    machine:
      image: ubuntu-2204:current
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-linux-amd64-
      - run:
          name: Setup Linux and Dependencies
          command: |
            wget -qO- "https://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc
            wget -qO- "https://packages.lunarg.com/vulkan/1.3.290/lunarg-vulkan-1.3.290-jammy.list" | sudo tee /etc/apt/sources.list.d/lunarg-vulkan-1.3.290-jammy.list
            wget "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb"
            sudo dpkg -i cuda-keyring_1.1-1_all.deb
            packages=(
              bison build-essential ccache cuda-compiler-11-8 flex g++-12 gperf libcublas-dev-11-8 libfontconfig1
              libfreetype6 libgl1-mesa-dev libmysqlclient21 libnvidia-compute-550-server libodbc2 libpq5 libwayland-dev
              libx11-6 libx11-xcb1 libxcb-cursor0 libxcb-glx0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0
              libxcb-render-util0 libxcb-shape0 libxcb-shm0 libxcb-sync1 libxcb-util1 libxcb-xfixes0 libxcb-xinerama0
              libxcb-xkb1 libxcb1 libxext6 libxfixes3 libxi6 libxkbcommon-dev libxkbcommon-x11-0 libxrender1 python3
              vulkan-sdk
            )
            sudo apt-get update
            sudo apt-get install -y "${packages[@]}"
      - run:
          name: Installing Qt
          command: |
            wget "https://gpt4all.io/ci/qt-unified-linux-x64-4.6.0-online.run"
            chmod +x qt-unified-linux-x64-4.6.0-online.run
            ./qt-unified-linux-x64-4.6.0-online.run --no-force-installations --no-default-installations --no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations --email $QT_EMAIL --password $QT_PASSWORD install qt.tools.cmake qt.tools.ifw.48 qt.tools.ninja qt.qt6.651.gcc_64 qt.qt6.651.qt5compat qt.qt6.651.debug_info qt.qt6.651.addons.qtpdf qt.qt6.651.addons.qthttpserver
      - run:
          name: Build
          no_output_timeout: 30m
          command: |
            export CMAKE_PREFIX_PATH=~/Qt/6.5.1/gcc_64/lib/cmake
            export PATH=$PATH:/usr/local/cuda/bin
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            ~/Qt/Tools/CMake/bin/cmake \
              -S gpt4all-chat -B build \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_C_COMPILER=gcc-12 \
              -DCMAKE_CXX_COMPILER=g++-12 \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache \
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON
            ~/Qt/Tools/CMake/bin/cmake --build build -j$(nproc) --target all
            ccache -s
      - save_cache:
          key: ccache-gpt4all-linux-amd64-{{ epoch }}
          when: always
          paths:
            - ../.ccache

  build-gpt4all-chat-windows:
    machine:
      image: windows-server-2022-gui:current
      resource_class: windows.large
      shell: powershell.exe -ExecutionPolicy Bypass
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-win-amd64-
      - run:
          name: Install dependencies
          command: choco install -y ccache wget
      - run:
          name: Installing Qt
          command: |
            wget.exe "https://gpt4all.io/ci/qt-unified-windows-x64-4.6.0-online.exe"
            & .\qt-unified-windows-x64-4.6.0-online.exe --no-force-installations --no-default-installations --no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations --email ${Env:QT_EMAIL} --password ${Env:QT_PASSWORD} install qt.tools.cmake qt.tools.ifw.48 qt.tools.ninja qt.qt6.651.win64_msvc2019_64 qt.qt6.651.qt5compat qt.qt6.651.debug_info qt.qt6.651.addons.qtpdf qt.qt6.651.addons.qthttpserver
      - run:
          name: Install VulkanSDK
          command: |
            wget.exe "https://sdk.lunarg.com/sdk/download/1.3.261.1/windows/VulkanSDK-1.3.261.1-Installer.exe"
            .\VulkanSDK-1.3.261.1-Installer.exe --accept-licenses --default-answer --confirm-command install
      - run:
          name: Install CUDA Toolkit
          command: |
            wget.exe "https://developer.download.nvidia.com/compute/cuda/11.8.0/network_installers/cuda_11.8.0_windows_network.exe"
            .\cuda_11.8.0_windows_network.exe -s cudart_11.8 nvcc_11.8 cublas_11.8 cublas_dev_11.8
      - run:
          name: Build
          no_output_timeout: 30m
          command: |
            $vsInstallPath = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -property installationpath
            Import-Module "${vsInstallPath}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
            Enter-VsDevShell -VsInstallPath "$vsInstallPath" -SkipAutomaticLocation -DevCmdArguments '-arch=x64 -no_logo'

            $Env:PATH = "${Env:PATH};C:\VulkanSDK\1.3.261.1\bin"
            $Env:VULKAN_SDK = "C:\VulkanSDK\1.3.261.1"
            ccache -o "cache_dir=${pwd}\..\.ccache" -o max_size=500M -p -z
            & "C:\Qt\Tools\CMake_64\bin\cmake.exe" `
              -S gpt4all-chat -B build -G Ninja `
              -DCMAKE_BUILD_TYPE=Release `
              "-DCMAKE_PREFIX_PATH:PATH=C:\Qt\6.5.1\msvc2019_64" `
              "-DCMAKE_MAKE_PROGRAM:FILEPATH=C:\Qt\Tools\Ninja\ninja.exe" `
              -DCMAKE_C_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache `
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON
            & "C:\Qt\Tools\Ninja\ninja.exe" -C build
            ccache -s
      - save_cache:
          key: ccache-gpt4all-win-amd64-{{ epoch }}
          when: always
          paths:
            - ..\.ccache

  build-gpt4all-chat-macos:
    macos:
      xcode: 15.4.0
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-macos-
      - run:
          name: Install Rosetta
          command: softwareupdate --install-rosetta --agree-to-license  # needed for QtIFW
      - run:
          name: Install dependencies
          command: brew install ccache wget
      - run:
          name: Installing Qt
          command: |
            wget "https://gpt4all.io/ci/qt-unified-macOS-x64-4.6.0-online.dmg"
            hdiutil attach qt-unified-macOS-x64-4.6.0-online.dmg
            /Volumes/qt-unified-macOS-x64-4.6.0-online/qt-unified-macOS-x64-4.6.0-online.app/Contents/MacOS/qt-unified-macOS-x64-4.6.0-online --no-force-installations --no-default-installations --no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations --email $QT_EMAIL --password $QT_PASSWORD install qt.tools.cmake qt.tools.ifw.48 qt.tools.ninja qt.qt6.651.clang_64 qt.qt6.651.qt5compat qt.qt6.651.debug_info qt.qt6.651.addons.qtpdf qt.qt6.651.addons.qthttpserver
            hdiutil detach /Volumes/qt-unified-macOS-x64-4.6.0-online
      - run:
          name: Build
          no_output_timeout: 30m
          command: |
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake \
              -S gpt4all-chat -B build -G Ninja \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_PREFIX_PATH:PATH=~/Qt/6.5.1/macos/lib/cmake \
              -DCMAKE_MAKE_PROGRAM:FILEPATH=~/Qt/Tools/Ninja/ninja \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DBUILD_UNIVERSAL=ON \
              -DCMAKE_OSX_DEPLOYMENT_TARGET=12.6 \
              -DGGML_METAL_MACOSX_VERSION_MIN=12.6
            ~/Qt/Tools/CMake/CMake.app/Contents/bin/cmake --build build --target all
            ccache -s
      - save_cache:
          key: ccache-gpt4all-macos-{{ epoch }}
          when: always
          paths:
            - ../.ccache

  build-ts-docs:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - node/install:
          node-version: "18.16"
      - run: node --version
      - run: corepack enable
      - node/install-packages:
          pkg-manager: npm
          app-dir: gpt4all-bindings/typescript
          override-ci-command: npm install --ignore-scripts
      - run:
          name: build docs ts yo
          command: |
            cd gpt4all-bindings/typescript
            npm run docs:build

  build-py-docs:
    docker:
      - image: circleci/python:3.8
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: |
            sudo apt-get update
            sudo apt-get -y install python3 python3-pip
            sudo pip3 install awscli --upgrade
            sudo pip3 install mkdocs mkdocs-material mkautodoc 'mkdocstrings[python]' markdown-captions pillow cairosvg
      - run:
          name: Make Documentation
          command: |
            cd gpt4all-bindings/python
            mkdocs build
      - run:
          name: Deploy Documentation
          command: |
            cd gpt4all-bindings/python
            aws s3 sync --delete site/ s3://docs.gpt4all.io/
      - run:
          name: Invalidate docs.gpt4all.io cloudfront
          command: aws cloudfront create-invalidation --distribution-id E1STQOW63QL2OH --paths "/*"

  build-py-linux:
    machine:
      image: ubuntu-2204:current
    steps:
      - checkout
      - restore_cache:
          keys:
            - ccache-gpt4all-linux-amd64-
      - run:
          name: Set Python Version
          command: pyenv global 3.11.2
      - run:
          name: Install dependencies
          command: |
            wget -qO- "https://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc
            wget -qO- "https://packages.lunarg.com/vulkan/1.3.290/lunarg-vulkan-1.3.290-jammy.list" | sudo tee /etc/apt/sources.list.d/lunarg-vulkan-1.3.290-jammy.list
            wget "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb"
            sudo dpkg -i cuda-keyring_1.1-1_all.deb
            packages=(
              build-essential ccache cmake cuda-compiler-11-8 g++-12 libcublas-dev-11-8 libnvidia-compute-550-server
              vulkan-sdk
            )
            sudo apt-get update
            sudo apt-get install -y "${packages[@]}"
            pip install setuptools wheel cmake
      - run:
          name: Build C library
          no_output_timeout: 30m
          command: |
            export PATH=$PATH:/usr/local/cuda/bin
            git submodule update --init --recursive
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            cd gpt4all-backend
            cmake -B build \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_C_COMPILER=gcc-12 \
              -DCMAKE_CXX_COMPILER=g++-12 \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache \
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON \
              -DCMAKE_CUDA_ARCHITECTURES='52-virtual;61-virtual;70-virtual;75-virtual'
            cmake --build build -j$(nproc)
            ccache -s
      - run:
          name: Build wheel
          command: |
            cd gpt4all-bindings/python/
            python setup.py bdist_wheel --plat-name=manylinux1_x86_64
      - store_artifacts:
          path: gpt4all-bindings/python/dist
      - save_cache:
          key: ccache-gpt4all-linux-amd64-{{ epoch }}
          when: always
          paths:
            - ../.ccache
      - persist_to_workspace:
          root: gpt4all-bindings/python/dist
          paths:
            - "*.whl"

  build-py-macos:
    macos:
      xcode: 15.4.0
    resource_class: macos.m1.large.gen1
    steps:
      - checkout
      - restore_cache:
          keys:
            - ccache-gpt4all-macos-
      - run:
          name: Install dependencies
          command: |
            brew install ccache cmake
            pip install setuptools wheel cmake
      - run:
          name: Build C library
          no_output_timeout: 30m
          command: |
            git submodule update --init  # don't use --recursive because macOS doesn't use Kompute
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            cd gpt4all-backend
            cmake -B build \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DBUILD_UNIVERSAL=ON \
              -DCMAKE_OSX_DEPLOYMENT_TARGET=12.6 \
              -DGGML_METAL_MACOSX_VERSION_MIN=12.6
            cmake --build build --parallel
            ccache -s
      - run:
          name: Build wheel
          command: |
            cd gpt4all-bindings/python
            python setup.py bdist_wheel --plat-name=macosx_10_15_universal2
      - store_artifacts:
          path: gpt4all-bindings/python/dist
      - save_cache:
          key: ccache-gpt4all-macos-{{ epoch }}
          when: always
          paths:
            - ../.ccache
      - persist_to_workspace:
          root: gpt4all-bindings/python/dist
          paths:
            - "*.whl"

  build-py-windows:
    machine:
      image: windows-server-2022-gui:current
      resource_class: windows.large
      shell: powershell.exe -ExecutionPolicy Bypass
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-win-amd64-
      - run:
          name: Install dependencies
          command:
            choco install -y ccache cmake ninja wget --installargs 'ADD_CMAKE_TO_PATH=System'
      - run:
          name: Install VulkanSDK
          command: |
            wget.exe "https://sdk.lunarg.com/sdk/download/1.3.261.1/windows/VulkanSDK-1.3.261.1-Installer.exe"
            .\VulkanSDK-1.3.261.1-Installer.exe --accept-licenses --default-answer --confirm-command install
      - run:
          name: Install CUDA Toolkit
          command: |
            wget.exe "https://developer.download.nvidia.com/compute/cuda/11.8.0/network_installers/cuda_11.8.0_windows_network.exe"
            .\cuda_11.8.0_windows_network.exe -s cudart_11.8 nvcc_11.8 cublas_11.8 cublas_dev_11.8
      - run:
          name: Install Python dependencies
          command: pip install setuptools wheel cmake
      - run:
          name: Build C library
          no_output_timeout: 30m
          command: |
            $vsInstallPath = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -property installationpath
            Import-Module "${vsInstallPath}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
            Enter-VsDevShell -VsInstallPath "$vsInstallPath" -SkipAutomaticLocation -DevCmdArguments '-arch=x64 -no_logo'

            $Env:PATH += ";C:\VulkanSDK\1.3.261.1\bin"
            $Env:VULKAN_SDK = "C:\VulkanSDK\1.3.261.1"
            ccache -o "cache_dir=${pwd}\..\.ccache" -o max_size=500M -p -z
            cd gpt4all-backend
            cmake -B build -G Ninja `
              -DCMAKE_BUILD_TYPE=Release `
              -DCMAKE_C_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache `
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON `
              -DCMAKE_CUDA_ARCHITECTURES='52-virtual;61-virtual;70-virtual;75-virtual'
            cmake --build build --parallel
            ccache -s
      - run:
          name: Build wheel
          command: |
            cd gpt4all-bindings/python
            python setup.py bdist_wheel --plat-name=win_amd64
      - store_artifacts:
          path: gpt4all-bindings/python/dist
      - save_cache:
          key: ccache-gpt4all-win-amd64-{{ epoch }}
          when: always
          paths:
            - ..\.ccache
      - persist_to_workspace:
          root: gpt4all-bindings/python/dist
          paths:
            - "*.whl"

  publish-wheels:
    docker:
      - image: circleci/python:3.8
    steps:
      - setup_remote_docker
      - attach_workspace:
          at: /tmp/workspace
      - run:
          name: Install dependencies
          command: |
            sudo apt-get update
            sudo apt-get install -y build-essential cmake
            pip install setuptools wheel twine
      - run:
          name: Upload Python package
          command: |
            twine upload /tmp/workspace/*.whl --username __token__ --password $PYPI_CRED
      - store_artifacts:
          path: /tmp/workspace

  build-bindings-backend-linux:
    machine:
      image: ubuntu-2204:current
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-linux-amd64-
      - run:
          name: Install dependencies
          command: |
            wget -qO- "https://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc
            wget -qO- "https://packages.lunarg.com/vulkan/1.3.290/lunarg-vulkan-1.3.290-jammy.list" | sudo tee /etc/apt/sources.list.d/lunarg-vulkan-1.3.290-jammy.list
            wget "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb"
            sudo dpkg -i cuda-keyring_1.1-1_all.deb
            packages=(
              build-essential ccache cmake cuda-compiler-11-8 g++-12 libcublas-dev-11-8 libnvidia-compute-550-server
              vulkan-sdk
            )
            sudo apt-get update
            sudo apt-get install -y "${packages[@]}"
      - run:
          name: Build Libraries
          no_output_timeout: 30m
          command: |
            export PATH=$PATH:/usr/local/cuda/bin
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            cd gpt4all-backend
            mkdir -p runtimes/build
            cd runtimes/build
            cmake ../.. \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_C_COMPILER=gcc-12 \
              -DCMAKE_C_COMPILER=g++-12 \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache \
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON
            cmake --build . -j$(nproc)
            ccache -s
            mkdir ../linux-x64
            cp -L *.so ../linux-x64 # otherwise persist_to_workspace seems to mess symlinks
      - save_cache:
          key: ccache-gpt4all-linux-amd64-{{ epoch }}
          when: always
          paths:
            - ../.ccache
      - persist_to_workspace:
          root: gpt4all-backend
          paths:
            - runtimes/linux-x64/*.so

  build-bindings-backend-macos:
    macos:
      xcode: 15.4.0
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-macos-
      - run:
          name: Install dependencies
          command: |
            brew install ccache cmake
      - run:
          name: Build Libraries
          no_output_timeout: 30m
          command: |
            ccache -o "cache_dir=${PWD}/../.ccache" -o max_size=500M -p -z
            cd gpt4all-backend
            mkdir -p runtimes/build
            cd runtimes/build
            cmake ../.. \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_C_COMPILER_LAUNCHER=ccache \
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
              -DBUILD_UNIVERSAL=ON \
              -DCMAKE_OSX_DEPLOYMENT_TARGET=12.6 \
              -DGGML_METAL_MACOSX_VERSION_MIN=12.6
            cmake --build . --parallel
            ccache -s
            mkdir ../osx-x64
            cp -L *.dylib ../osx-x64
            cp ../../llama.cpp-mainline/*.metal ../osx-x64
            ls ../osx-x64
      - save_cache:
          key: ccache-gpt4all-macos-{{ epoch }}
          when: always
          paths:
            - ../.ccache
      - persist_to_workspace:
          root: gpt4all-backend
          paths:
            - runtimes/osx-x64/*.dylib
            - runtimes/osx-x64/*.metal

  build-bindings-backend-windows:
    machine:
      image: windows-server-2022-gui:current
      resource_class: windows.large
      shell: powershell.exe -ExecutionPolicy Bypass
    steps:
      - checkout
      - run:
          name: Update Submodules
          command: |
            git submodule sync
            git submodule update --init --recursive
      - restore_cache:
          keys:
            - ccache-gpt4all-win-amd64-
      - run:
          name: Install dependencies
          command: |
            choco install -y ccache cmake ninja wget --installargs 'ADD_CMAKE_TO_PATH=System'
      - run:
          name: Install VulkanSDK
          command: |
            wget.exe "https://sdk.lunarg.com/sdk/download/1.3.261.1/windows/VulkanSDK-1.3.261.1-Installer.exe"
            .\VulkanSDK-1.3.261.1-Installer.exe --accept-licenses --default-answer --confirm-command install
      - run:
          name: Install CUDA Toolkit
          command: |
            wget.exe "https://developer.download.nvidia.com/compute/cuda/11.8.0/network_installers/cuda_11.8.0_windows_network.exe"
            .\cuda_11.8.0_windows_network.exe -s cudart_11.8 nvcc_11.8 cublas_11.8 cublas_dev_11.8
      - run:
          name: Build Libraries
          no_output_timeout: 30m
          command: |
            $vsInstallPath = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -property installationpath
            Import-Module "${vsInstallPath}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
            Enter-VsDevShell -VsInstallPath "$vsInstallPath" -SkipAutomaticLocation -DevCmdArguments '-arch=x64 -no_logo'

            $Env:Path += ";C:\VulkanSDK\1.3.261.1\bin"
            $Env:VULKAN_SDK = "C:\VulkanSDK\1.3.261.1"
            ccache -o "cache_dir=${pwd}\..\.ccache" -o max_size=500M -p -z
            cd gpt4all-backend
            mkdir runtimes/win-x64_msvc
            cd runtimes/win-x64_msvc
            cmake -S ../.. -B . -G Ninja `
              -DCMAKE_BUILD_TYPE=Release `
              -DCMAKE_C_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CXX_COMPILER_LAUNCHER=ccache `
              -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache `
              -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON
            cmake --build . --parallel
            ccache -s
            cp bin/Release/*.dll .
      - save_cache:
          key: ccache-gpt4all-win-amd64-{{ epoch }}
          when: always
          paths:
            - ..\.ccache
      - persist_to_workspace:
          root: gpt4all-backend
          paths:
            - runtimes/win-x64_msvc/*.dll

  build-nodejs-linux:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - attach_workspace:
          at: /tmp/gpt4all-backend
      - node/install:
          install-yarn: true
          node-version: "18.16"
      - run: node --version
      - run: corepack enable
      - node/install-packages:
          app-dir: gpt4all-bindings/typescript
          pkg-manager: yarn
          override-ci-command: yarn install
      - run:
          command: |
            cd gpt4all-bindings/typescript
            yarn prebuildify -t 18.16.0 --napi
      - run:
          command: |
            mkdir -p gpt4all-backend/prebuilds/linux-x64
            mkdir -p gpt4all-backend/runtimes/linux-x64
            cp /tmp/gpt4all-backend/runtimes/linux-x64/*-*.so gpt4all-backend/runtimes/linux-x64
            cp gpt4all-bindings/typescript/prebuilds/linux-x64/*.node gpt4all-backend/prebuilds/linux-x64
      - persist_to_workspace:
          root: gpt4all-backend
          paths:
            - prebuilds/linux-x64/*.node
            - runtimes/linux-x64/*-*.so

  build-nodejs-macos:
    macos:
      xcode: 15.4.0
    steps:
      - checkout
      - attach_workspace:
          at: /tmp/gpt4all-backend
      - node/install:
          install-yarn: true
          node-version: "18.16"
      - run: node --version
      - run: corepack enable
      - node/install-packages:
          app-dir: gpt4all-bindings/typescript
          pkg-manager: yarn
          override-ci-command: yarn install
      - run:
          command: |
            cd gpt4all-bindings/typescript
            yarn prebuildify -t 18.16.0 --napi
      - run:
          name: "Persisting all necessary things to workspace"
          command: |
            mkdir -p gpt4all-backend/prebuilds/darwin-x64
            mkdir -p gpt4all-backend/runtimes/darwin
            cp /tmp/gpt4all-backend/runtimes/osx-x64/*-*.* gpt4all-backend/runtimes/darwin
            cp gpt4all-bindings/typescript/prebuilds/darwin-x64/*.node gpt4all-backend/prebuilds/darwin-x64
      - persist_to_workspace:
          root: gpt4all-backend
          paths:
            - prebuilds/darwin-x64/*.node
            - runtimes/darwin/*-*.*

  build-nodejs-windows:
    executor:
      name: win/default
      size: large
      shell: powershell.exe -ExecutionPolicy Bypass
    steps:
      - checkout
      - attach_workspace:
          at: /tmp/gpt4all-backend
      - run: choco install wget -y
      - run:
          command: |
            wget.exe "https://nodejs.org/dist/v18.16.0/node-v18.16.0-x86.msi" -P C:\Users\circleci\Downloads\
            MsiExec.exe /i C:\Users\circleci\Downloads\node-v18.16.0-x86.msi /qn
      - run:
          command: |
            Start-Process powershell -verb runAs -Args "-start GeneralProfile"
            nvm install 18.16.0
            nvm use 18.16.0
      - run: node --version
      - run: corepack enable
      - run:
          command: |
            npm install -g yarn
            cd gpt4all-bindings/typescript
            yarn install
      - run:
          command: |
            cd gpt4all-bindings/typescript
            yarn prebuildify -t 18.16.0 --napi
      - run:
          command: |
            mkdir -p gpt4all-backend/prebuilds/win32-x64
            mkdir -p gpt4all-backend/runtimes/win32-x64
            cp /tmp/gpt4all-backend/runtimes/win-x64_msvc/*-*.dll gpt4all-backend/runtimes/win32-x64
            cp gpt4all-bindings/typescript/prebuilds/win32-x64/*.node gpt4all-backend/prebuilds/win32-x64

      - persist_to_workspace:
          root: gpt4all-backend
          paths:
            - prebuilds/win32-x64/*.node
            - runtimes/win32-x64/*-*.dll

  prepare-npm-pkg:
    docker:
      - image: cimg/base:stable
    steps:
      - attach_workspace:
          at: /tmp/gpt4all-backend
      - checkout
      - node/install:
          install-yarn: true
          node-version: "18.16"
      - run: node --version
      - run: corepack enable
      - run:
          command: |
            cd gpt4all-bindings/typescript
            # excluding llmodel. nodejs bindings dont need llmodel.dll
            mkdir -p runtimes/win32-x64/native
            mkdir -p prebuilds/win32-x64/
            cp /tmp/gpt4all-backend/runtimes/win-x64_msvc/*-*.dll runtimes/win32-x64/native/
            cp /tmp/gpt4all-backend/prebuilds/win32-x64/*.node prebuilds/win32-x64/

            mkdir -p runtimes/linux-x64/native
            mkdir -p prebuilds/linux-x64/
            cp /tmp/gpt4all-backend/runtimes/linux-x64/*-*.so runtimes/linux-x64/native/
            cp /tmp/gpt4all-backend/prebuilds/linux-x64/*.node prebuilds/linux-x64/

            # darwin has univeral runtime libraries
            mkdir -p runtimes/darwin/native
            mkdir -p prebuilds/darwin-x64/

            cp /tmp/gpt4all-backend/runtimes/darwin/*-*.* runtimes/darwin/native/

            cp /tmp/gpt4all-backend/prebuilds/darwin-x64/*.node prebuilds/darwin-x64/

            # Fallback build if user is not on above prebuilds
            mv -f binding.ci.gyp binding.gyp

            mkdir gpt4all-backend
            cd ../../gpt4all-backend
            mv llmodel.h llmodel.cpp llmodel_c.cpp llmodel_c.h sysinfo.h dlhandle.h ../gpt4all-bindings/typescript/gpt4all-backend/

      # Test install
      - node/install-packages:
          app-dir: gpt4all-bindings/typescript
          pkg-manager: yarn
          override-ci-command: yarn install
      - run:
          command: |
            cd gpt4all-bindings/typescript
            yarn run test
      - run:
          command: |
            cd gpt4all-bindings/typescript
            npm set //registry.npmjs.org/:_authToken=$NPM_TOKEN
            npm publish

main_only: &main_only
  filters:
    branches:
      only: main

workflows:
  version: 2
  noop:
    when:
      not:
        or:
          - << pipeline.parameters.run-all-workflows >>
          - << pipeline.parameters.run-python-workflow >>
          - << pipeline.parameters.run-ts-workflow >>
          - << pipeline.parameters.run-chat-workflow >>
    jobs:
      - noop
  build-chat-offline-installers:
    when:
      or:
        - << pipeline.parameters.run-all-workflows >>
        - << pipeline.parameters.run-chat-workflow >>
    jobs:
      - hold:
          type: approval
      - build-offline-chat-installer-macos:
          requires:
            - hold
      - sign-offline-chat-installer-macos:
          requires:
            - build-offline-chat-installer-macos
      - notarize-offline-chat-installer-macos:
          requires:
            - sign-offline-chat-installer-macos
      - build-offline-chat-installer-windows:
          requires:
            - hold
      - sign-offline-chat-installer-windows:
          requires:
            - build-offline-chat-installer-windows
      - build-offline-chat-installer-linux:
          requires:
            - hold
  build-chat-online-installers:
    when:
      or:
        - << pipeline.parameters.run-all-workflows >>
        - << pipeline.parameters.run-chat-workflow >>
    jobs:
      - hold:
          <<: *main_only
          type: approval
      - build-online-chat-installer-macos:
          <<: *main_only
          requires:
            - hold
      - sign-online-chat-installer-macos:
          <<: *main_only
          requires:
            - build-online-chat-installer-macos
      - notarize-online-chat-installer-macos:
          <<: *main_only
          requires:
            - sign-online-chat-installer-macos
      - build-online-chat-installer-windows:
          <<: *main_only
          requires:
            - hold
      - sign-online-chat-installer-windows:
          <<: *main_only
          requires:
            - build-online-chat-installer-windows
      - build-online-chat-installer-linux:
          <<: *main_only
          requires:
            - hold
  build-and-test-gpt4all-chat:
    when:
      or:
        - << pipeline.parameters.run-all-workflows >>
        - << pipeline.parameters.run-chat-workflow >>
    jobs:
      - hold:
          type: approval
      - build-gpt4all-chat-linux:
          requires:
            - hold
      - build-gpt4all-chat-windows:
          requires:
            - hold
      - build-gpt4all-chat-macos:
          requires:
            - hold
  deploy-docs:
    when:
      or:
        - << pipeline.parameters.run-all-workflows >>
        - << pipeline.parameters.run-python-workflow >>
    jobs:
      - build-ts-docs:
          <<: *main_only
      - build-py-docs:
          <<: *main_only
  build-python:
    when:
      or:
        - << pipeline.parameters.run-all-workflows >>
        - << pipeline.parameters.run-python-workflow >>
    jobs:
      - pypi-hold:
          <<: *main_only
          type: approval
      - hold:
          type: approval
      - build-py-linux:
          requires:
            - hold
      - build-py-macos:
          requires:
            - hold
      - build-py-windows:
          requires:
            - hold
      - publish-wheels:
          <<: *main_only
          requires:
            - pypi-hold
            - build-py-windows
            - build-py-linux
            - build-py-macos
  build-bindings:
    when:
      or:
       - << pipeline.parameters.run-all-workflows >>
       - << pipeline.parameters.run-python-workflow >>
       - << pipeline.parameters.run-ts-workflow >>
    jobs:
      - hold:
          type: approval
      - nodejs-hold:
          type: approval
      - npm-hold:
          <<: *main_only
          type: approval
      - build-bindings-backend-linux:
          requires:
            - hold
      - build-bindings-backend-macos:
          requires:
            - hold
      - build-bindings-backend-windows:
          requires:
            - hold

      # NodeJs Jobs
      - prepare-npm-pkg:
          <<: *main_only
          requires:
            - npm-hold
            - build-nodejs-linux
            - build-nodejs-windows
            - build-nodejs-macos
      - build-nodejs-linux:
          requires:
            - nodejs-hold
            - build-bindings-backend-linux
      - build-nodejs-windows:
          requires:
            - nodejs-hold
            - build-bindings-backend-windows
      - build-nodejs-macos:
          requires:
            - nodejs-hold
            - build-bindings-backend-macos
