From 130d17f45e5166b66951d8edab5cd68cde564b64 Mon Sep 17 00:00:00 2001 From: vansangpfiev Date: Mon, 28 Apr 2025 10:21:59 +0700 Subject: [PATCH] chore: CI/CD for Windows, Linux commit 4897b2bcf7f044080fce81bd725515e62fc4eb29 Author: vansangpfiev Date: Fri Apr 25 15:32:37 2025 +0700 chore: cleanup tauri config commit 66c5676ec146b25c89cccb570ede7c070dbc5853 Author: vansangpfiev Date: Fri Apr 25 14:37:04 2025 +0700 fix: store path commit bc6560c576873e55f84c4b21764bedbdd9dbd5a8 Author: vansangpfiev Date: Thu Apr 24 09:39:50 2025 +0700 chore: Linux CI commit b036275dc9f1df7614aaca3b358b9c6493082512 Author: vansangpfiev Date: Wed Apr 23 16:41:22 2025 +0700 chore: updater windows commit e91b543dbdd82bd4a44db7550ffb993897b56081 Merge: dea80a83 4a54a378 Author: vansangpfiev Date: Wed Apr 23 16:39:24 2025 +0700 Merge branch 'chore/tauri-cicd' of https://github.com/menloresearch/jan into chore/tauri-cicd-windows commit dea80a83966113b108137c385a3c28920d2adda4 Author: Minh141120 Date: Wed Apr 23 11:47:04 2025 +0700 chore: update azuresigntool install method commit 2ec2234082be57e53887192153fa982a134ea535 Author: Minh141120 Date: Wed Apr 23 11:01:31 2025 +0700 chore: add verbose option build tauri and targets app and dmg for macos build commit 42c7592cc89641130545551d4d864268cde3d5b0 Author: Minh141120 Date: Wed Apr 23 10:35:27 2025 +0700 chore: update targets build commit 4c8ba44ff60cdef8b639fa189f5729dc69c5aff6 Author: Minh141120 Date: Wed Apr 23 09:53:21 2025 +0700 refactor: remove debug step and upload electron build artifact commit 158c08b465e18823e0f2b9a30fd5ecd589d08934 Author: Minh141120 Date: Wed Apr 23 09:21:08 2025 +0700 chore: add script codesign on windows commit 4545b2bcd852029472298e530176494992dd0950 Author: vansangpfiev Date: Tue Apr 22 13:39:49 2025 +0700 chore: update csp setting commit f64a1e1ca958e3c1c685485a06d45956ddcf14a0 Author: Minh141120 Date: Tue Apr 22 10:15:14 2025 +0700 chore: update azuresigntool installation commit 1f4b9d18b332d5205685a6fe68f5dfaf973d273c Author: Minh141120 Date: Tue Apr 22 09:49:42 2025 +0700 chore: update signcommand commit 911a3ab3540f872f6fe906c8e2135440d39f108c Author: Minh141120 Date: Mon Apr 21 19:19:23 2025 +0700 chore: update codesign tauri windows commit fba15c4c2de43b4cb87308ef998cdd8dc88b1ce6 Author: Minh141120 Date: Mon Apr 21 19:04:29 2025 +0700 chore: update path azuresigntool commit 8b8c950b56f5aa42baf76aba064fc99b50758150 Author: Minh141120 Date: Mon Apr 21 18:38:56 2025 +0700 chore: update azuresigntool path commit bd67a2b7908b5f3a126c634a840e0b941373a3c6 Author: Minh141120 Date: Mon Apr 21 17:47:33 2025 +0700 chore: update azuresigntool url commit f70effca7c09cd2fe9b5866b4f194b64a13294b9 Author: Minh141120 Date: Mon Apr 21 17:33:32 2025 +0700 chore: update azuretoolsign download commit 667910772f30369b9afa554ad06e4378f93d0b1a Author: Minh141120 Date: Mon Apr 21 16:56:25 2025 +0700 chore: update path azuresigntool commit f1610bfd80dfa996db4a777bb58475f2e6d02cc6 Author: Minh141120 Date: Mon Apr 21 16:52:36 2025 +0700 chore: update azuresigntool path commit 0873d56fb88fb66c884eff31d3f63aa99858f038 Author: Minh141120 Date: Mon Apr 21 16:19:46 2025 +0700 chore: add debug step commit 88e0b1a697ed478375429686eb1c03ae71a3b447 Author: Minh141120 Date: Mon Apr 21 15:58:39 2025 +0700 ci(windows): download AzureSignTool to src-tauri for Tauri code signing commit 47f94e86589826c3941a3d602298f188d6480980 Author: Minh141120 Date: Mon Apr 21 15:21:20 2025 +0700 fix: AzureSignTool signcommand Path commit dc014a7905fd0b49b5972e24b4d5773c5dc29ea5 Author: Minh141120 Date: Mon Apr 21 15:00:02 2025 +0700 chore: add debug step azuresigntool tauri windows commit ee7b6163a8419604dfba7dc2f967026be4884da4 Author: Minh141120 Date: Mon Apr 21 14:33:33 2025 +0700 chore: tauri windows codesign commit 6607090857120531d8a096f45ff556c3f2553e53 Author: vansangpfiev Date: Thu Apr 17 10:29:50 2025 +0700 chore: add windows download script commit 4b1a5cc29c77eecca75978a1ab3126d2c710e738 Author: Nguyen Ngoc Minh Date: Mon Apr 21 13:44:34 2025 +0700 chore: tauri codesign windows --- .github/scripts/rename-tauri-app.sh | 48 + .../workflows/template-build-linux-x64.yml | 101 +- .github/workflows/template-build-macos.yml | 47 +- .../workflows/template-build-windows-x64.yml | 157 ++- package.json | 3 +- src-tauri/.gitignore | 3 +- src-tauri/Cargo.toml | 2 +- src-tauri/binaries/download.bat | 43 + src-tauri/binaries/download.sh | 15 +- src-tauri/sign.ps1 | 12 + src-tauri/src/core/cmd.rs | 14 +- src-tauri/src/core/setup.rs | 25 +- src-tauri/tauri.bundle.windows.nsis.template | 1020 +++++++++++++++++ src-tauri/tauri.conf.json | 22 +- 14 files changed, 1410 insertions(+), 102 deletions(-) create mode 100644 .github/scripts/rename-tauri-app.sh create mode 100644 src-tauri/binaries/download.bat create mode 100644 src-tauri/sign.ps1 create mode 100644 src-tauri/tauri.bundle.windows.nsis.template diff --git a/.github/scripts/rename-tauri-app.sh b/.github/scripts/rename-tauri-app.sh new file mode 100644 index 000000000..12a1fadb7 --- /dev/null +++ b/.github/scripts/rename-tauri-app.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +INPUT_JSON_FILE="$1" + +CHANNEL="$2" + +if [ "$CHANNEL" == "nightly" ]; then + UPDATER="latest" +else + UPDATER="beta" +fi + +# Check if the input file exists +if [ ! -f "$INPUT_JSON_FILE" ]; then + echo "Input file not found: $INPUT_JSON_FILE" + exit 1 +fi + +# Use jq to transform the content +jq --arg channel "$CHANNEL" --arg updater "$UPDATER" ' + .productName = "Jan-\($channel)" | + .identifier = "jan-\($channel).ai.app" +' "$INPUT_JSON_FILE" > ./tauri.conf.json.tmp + +cat ./tauri.conf.json.tmp + +rm $INPUT_JSON_FILE +mv ./tauri.conf.json.tmp $INPUT_JSON_FILE + +# Update the layout file +# LAYOUT_FILE_PATH="web/app/layout.tsx" + +# if [ ! -f "$LAYOUT_FILE_PATH" ]; then +# echo "File does not exist: $LAYOUT_FILE_PATH" +# exit 1 +# fi + +# Perform the replacements +# sed -i -e "s#Jan#Jan-$CHANNEL#g" "$LAYOUT_FILE_PATH" + +# Notify completion +# echo "File has been updated: $LAYOUT_FILE_PATH" diff --git a/.github/workflows/template-build-linux-x64.yml b/.github/workflows/template-build-linux-x64.yml index 58b566931..0afb47e69 100644 --- a/.github/workflows/template-build-linux-x64.yml +++ b/.github/workflows/template-build-linux-x64.yml @@ -38,10 +38,16 @@ on: required: false DELTA_AWS_SECRET_ACCESS_KEY: required: false + TAURI_SIGNING_PRIVATE_KEY: + required: false + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: + required: false + TAURI_SIGNING_PUBLIC_KEY: + required: false jobs: build-linux-x64: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 environment: production permissions: contents: write @@ -51,6 +57,20 @@ jobs: with: ref: ${{ inputs.ref }} + - name: Free Disk Space Before Build + run: | + echo "Disk space before cleanup:" + df -h + sudo rm -rf /usr/local/.ghcup + sudo rm -rf /opt/hostedtoolcache/CodeQL + sudo rm -rf /usr/local/lib/android/sdk/ndk + sudo rm -rf /usr/share/dotnet + sudo rm -rf /opt/ghc + sudo rm -rf /usr/local/share/boost + sudo apt-get clean + echo "Disk space after cleanup:" + df -h + - name: Replace Icons for Beta Build if: inputs.beta == true && inputs.nightly != true shell: bash @@ -84,25 +104,49 @@ jobs: - name: Install jq uses: dcarbone/install-jq-action@v2.0.1 + - name: Install ctoml + run: | + cargo install ctoml + + - name: Install Tauri dependecies + run: | + sudo apt update + sudo apt install -y libglib2.0-dev libatk1.0-dev libpango1.0-dev libgtk-3-dev libsoup-3.0-dev libwebkit2gtk-4.1-dev librsvg2-dev + - name: Update app version base public_provider if: inputs.public_provider != 'github' run: | echo "Version: ${{ inputs.new_version }}" - # Update the version in electron/package.json - jq --arg version "${{ inputs.new_version }}" '.version = $version' electron/package.json > /tmp/package.json - mv /tmp/package.json electron/package.json + # Update tauri.conf.json + jq --arg version "${{ inputs.new_version }}" '.version = $version | .bundle.createUpdaterArtifacts = true' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json + mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json + + chmod +x .github/scripts/rename-tauri-app.sh + .github/scripts/rename-tauri-app.sh ./src-tauri/tauri.conf.json nightly + + echo ./src-tauri/tauri.conf.json + + # Update Cargo.toml + ctoml ./src-tauri/Cargo.toml package.name "Jan-nightly" + ctoml ./src-tauri/Cargo.toml package.version "${{ inputs.new_version }}" + echo "------------------" + cat ./src-tauri/Cargo.toml + + # # Update the version in electron/package.json + # jq --arg version "${{ inputs.new_version }}" '.version = $version' electron/package.json > /tmp/package.json + # mv /tmp/package.json electron/package.json jq --arg version "${{ inputs.new_version }}" '.version = $version' web/package.json > /tmp/package.json mv /tmp/package.json web/package.json - jq '.build.publish = [{"provider": "generic", "url": "https://delta.jan.ai/nightly", "channel": "latest"}, {"provider": "s3", "acl": null, "bucket": "${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}", "region": "${{ secrets.DELTA_AWS_REGION}}", "path": "temp-nightly", "channel": "latest"}]' electron/package.json > /tmp/package.json - mv /tmp/package.json electron/package.json - cat electron/package.json - chmod +x .github/scripts/rename-app.sh - .github/scripts/rename-app.sh ./electron/package.json nightly - chmod +x .github/scripts/rename-workspace.sh - .github/scripts/rename-workspace.sh ./package.json nightly - echo "------------------------" - cat ./electron/package.json - echo "------------------------" + # jq '.build.publish = [{"provider": "generic", "url": "https://delta.jan.ai/nightly", "channel": "latest"}, {"provider": "s3", "acl": null, "bucket": "${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}", "region": "${{ secrets.DELTA_AWS_REGION}}", "path": "temp-nightly", "channel": "latest"}]' electron/package.json > /tmp/package.json + # mv /tmp/package.json electron/package.json + # cat electron/package.json + # chmod +x .github/scripts/rename-app.sh + # .github/scripts/rename-app.sh ./electron/package.json nightly + # chmod +x .github/scripts/rename-workspace.sh + # .github/scripts/rename-workspace.sh ./package.json nightly + # echo "------------------------" + # cat ./electron/package.json + # echo "------------------------" - name: Change App Name for beta version if: inputs.beta == true @@ -130,6 +174,20 @@ jobs: env: VERSION_TAG: ${{ inputs.new_version }} + - name: Inject Tauri Signing Public Key + run: | + if [ -f "src-tauri/tauri.conf.json" ]; then + echo "Injecting Tauri public key into configuration..." + # Use jq to update the pubkey field in the tauri.conf.json file + jq --arg pubkey "$TAURI_SIGNING_PUBLIC_KEY" '.plugins.updater.pubkey = $pubkey' src-tauri/tauri.conf.json > /tmp/tauri.conf.json + mv /tmp/tauri.conf.json src-tauri/tauri.conf.json + echo "Tauri configuration updated successfully" + else + echo "tauri.conf.json not found" + fi + env: + TAURI_SIGNING_PUBLIC_KEY: ${{ secrets.TAURI_SIGNING_PUBLIC_KEY }} + - name: Build and publish app to aws s3 r2 or github artifactory if: inputs.public_provider != 'github' run: | @@ -148,7 +206,10 @@ jobs: AWS_MAX_ATTEMPTS: '5' POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }} - CORTEX_API_PORT: ${{ inputs.cortex_api_port }} + # CORTEX_API_PORT: ${{ inputs.cortex_api_port }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + TAURI_SIGNING_PUBLIC_KEY: ${{ secrets.TAURI_SIGNING_PUBLIC_KEY }} - name: Build and publish app to github if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && inputs.public_provider == 'github' && inputs.beta == false @@ -158,6 +219,9 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + TAURI_SIGNING_PUBLIC_KEY: ${{ secrets.TAURI_SIGNING_PUBLIC_KEY }} - name: Build and publish app to github if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && inputs.public_provider == 'github' && inputs.beta == true @@ -171,17 +235,20 @@ jobs: AWS_MAX_ATTEMPTS: '5' POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + TAURI_SIGNING_PUBLIC_KEY: ${{ secrets.TAURI_SIGNING_PUBLIC_KEY }} - name: Upload Artifact .deb file if: inputs.public_provider != 'github' uses: actions/upload-artifact@v4 with: name: jan-linux-amd64-${{ inputs.new_version }}-deb - path: ./electron/dist/*.deb + path: ./src-tauri/target/release/bundle/deb/*.deb - name: Upload Artifact .AppImage file if: inputs.public_provider != 'github' uses: actions/upload-artifact@v4 with: name: jan-linux-amd64-${{ inputs.new_version }}-AppImage - path: ./electron/dist/*.AppImage \ No newline at end of file + path: ./src-tauri/target/release/bundle/appimage/*.AppImage \ No newline at end of file diff --git a/.github/workflows/template-build-macos.yml b/.github/workflows/template-build-macos.yml index d2c8f69bf..9c2d0b19b 100644 --- a/.github/workflows/template-build-macos.yml +++ b/.github/workflows/template-build-macos.yml @@ -99,31 +99,50 @@ jobs: - name: Install jq uses: dcarbone/install-jq-action@v2.0.1 + - name: Install ctoml + run: | + cargo install ctoml + - name: Update app version based on latest release tag with build number if: inputs.public_provider != 'github' run: | echo "Version: ${{ inputs.new_version }}" + # Update tauri.conf.json + jq --arg version "${{ inputs.new_version }}" '.version = $version | .bundle.createUpdaterArtifacts = true' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json + mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json + + chmod +x .github/scripts/rename-tauri-app.sh + .github/scripts/rename-tauri-app.sh ./src-tauri/tauri.conf.json nightly + + echo ./src-tauri/tauri.conf.json + + # Update Cargo.toml + ctoml ./src-tauri/Cargo.toml package.name "Jan-nightly" + ctoml ./src-tauri/Cargo.toml package.version "${{ inputs.new_version }}" + echo "------------------" + cat ./src-tauri/Cargo.toml + # Update the version in electron/package.json - jq --arg version "${{ inputs.new_version }}" '.version = $version' electron/package.json > /tmp/package.json - mv /tmp/package.json electron/package.json + # jq --arg version "${{ inputs.new_version }}" '.version = $version' electron/package.json > /tmp/package.json + # mv /tmp/package.json electron/package.json jq --arg version "${{ inputs.new_version }}" '.version = $version' web/package.json > /tmp/package.json mv /tmp/package.json web/package.json - jq '.build.publish = [{"provider": "generic", "url": "https://delta.jan.ai/nightly", "channel": "latest"}, {"provider": "s3", "acl": null, "bucket": "${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}", "region": "${{ secrets.DELTA_AWS_REGION}}", "path": "temp-nightly", "channel": "latest"}]' electron/package.json > /tmp/package.json - mv /tmp/package.json electron/package.json + # jq '.build.publish = [{"provider": "generic", "url": "https://delta.jan.ai/nightly", "channel": "latest"}, {"provider": "s3", "acl": null, "bucket": "${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}", "region": "${{ secrets.DELTA_AWS_REGION}}", "path": "temp-nightly", "channel": "latest"}]' electron/package.json > /tmp/package.json + # mv /tmp/package.json electron/package.json - jq --arg teamid "${{ secrets.APPLE_TEAM_ID }}" '.build.mac.notarize.teamId = $teamid' electron/package.json > /tmp/package.json - mv /tmp/package.json electron/package.json + # jq --arg teamid "${{ secrets.APPLE_TEAM_ID }}" '.build.mac.notarize.teamId = $teamid' electron/package.json > /tmp/package.json + # mv /tmp/package.json electron/package.json # cat electron/package.json - chmod +x .github/scripts/rename-app.sh - .github/scripts/rename-app.sh ./electron/package.json nightly - chmod +x .github/scripts/rename-workspace.sh - .github/scripts/rename-workspace.sh ./package.json nightly - echo "------------------------" - cat ./electron/package.json - echo "------------------------" + # chmod +x .github/scripts/rename-app.sh + # .github/scripts/rename-app.sh ./electron/package.json nightly + # chmod +x .github/scripts/rename-workspace.sh + # .github/scripts/rename-workspace.sh ./package.json nightly + # echo "------------------------" + # cat ./electron/package.json + # echo "------------------------" - name: Change App Name for beta version if: inputs.beta == true @@ -213,7 +232,7 @@ jobs: # AWS_MAX_ATTEMPTS: '5' POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }} - CORTEX_API_PORT: ${{ inputs.cortex_api_port }} + # CORTEX_API_PORT: ${{ inputs.cortex_api_port }} APPLE_CERTIFICATE: ${{ secrets.CODE_SIGN_P12_BASE64 }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.CODE_SIGN_P12_PASSWORD }} APPLE_API_ISSUER: ${{ secrets.NOTARY_ISSUER }} diff --git a/.github/workflows/template-build-windows-x64.yml b/.github/workflows/template-build-windows-x64.yml index 9be028e15..392b6d0db 100644 --- a/.github/workflows/template-build-windows-x64.yml +++ b/.github/workflows/template-build-windows-x64.yml @@ -5,20 +5,20 @@ on: ref: required: true type: string - default: 'refs/heads/main' + default: "refs/heads/main" public_provider: required: true type: string default: none - description: 'none: build only, github: build and publish to github, aws s3: build and publish to aws s3' + description: "none: build only, github: build and publish to github, aws s3: build and publish to aws s3" new_version: required: true type: string - default: '' + default: "" aws_s3_prefix: required: false type: string - default: '/latest/' + default: "/latest/" beta: required: false type: boolean @@ -48,6 +48,12 @@ on: required: false AZURE_CERT_NAME: required: false + TAURI_SIGNING_PRIVATE_KEY: + required: false + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: + required: false + TAURI_SIGNING_PUBLIC_KEY: + required: false jobs: build-windows-x64: @@ -92,37 +98,86 @@ jobs: - name: Install jq uses: dcarbone/install-jq-action@v2.0.1 + - name: Install ctoml + run: | + cargo install ctoml + - name: Update app version base on tag if: inputs.public_provider != 'github' id: version_update shell: bash run: | echo "Version: ${{ inputs.new_version }}" + # Update tauri.conf.json + jq --arg version "${{ inputs.new_version }}" --arg template tauri.bundle.windows.nsis.template '.version = $version | .bundle.createUpdaterArtifacts = true | .bundle.windows.nsis.template = $template' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json + mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json + + chmod +x .github/scripts/rename-tauri-app.sh + .github/scripts/rename-tauri-app.sh ./src-tauri/tauri.conf.json nightly + + echo ./src-tauri/tauri.conf.json + + # Update Cargo.toml + ctoml ./src-tauri/Cargo.toml package.name "Jan-nightly" + ctoml ./src-tauri/Cargo.toml package.version "${{ inputs.new_version }}" + echo "------------------" + cat ./src-tauri/Cargo.toml + + # Update template + get_latest_tag() { + local retries=0 + local max_retries=3 + local tag + while [ $retries -lt $max_retries ]; do + tag=$(curl -s https://api.github.com/repos/menloresearch/jan/releases/latest | jq -r .tag_name) + if [ -n "$tag" ] && [ "$tag" != "null" ]; then + echo $tag + return + else + let retries++ + echo "Retrying... ($retries/$max_retries)" + sleep 2 + fi + done + echo "Failed to fetch latest tag after $max_retries attempts." + exit 1 + } + + LATEST_TAG=$(get_latest_tag) + jan_tag="${LATEST_TAG#v}.0" + echo $jan_tag + sed -i "s/jan_productname/Jan-nightly/g" ./src-tauri/tauri.bundle.windows.nsis.template + sed -i "s/jan_version/${{ inputs.new_version }}/g" ./src-tauri/tauri.bundle.windows.nsis.template + sed -i "s/jan_build/$jan_tag/g" ./src-tauri/tauri.bundle.windows.nsis.template + sed -i "s/jan_mainbinaryname/jan-nightly/g" ./src-tauri/tauri.bundle.windows.nsis.template + echo "------------------" + cat ./src-tauri/tauri.bundle.windows.nsis.template + # Update the version in electron/package.json - jq --arg version "${{ inputs.new_version }}" '.version = $version' electron/package.json > /tmp/package.json - mv /tmp/package.json electron/package.json + # jq --arg version "${{ inputs.new_version }}" '.version = $version' electron/package.json > /tmp/package.json + # mv /tmp/package.json electron/package.json jq --arg version "${{ inputs.new_version }}" '.version = $version' web/package.json > /tmp/package.json mv /tmp/package.json web/package.json - jq '.build.publish = [{"provider": "generic", "url": "https://delta.jan.ai/nightly", "channel": "latest"}, {"provider": "s3", "acl": null, "bucket": "${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}", "region": "${{ secrets.DELTA_AWS_REGION}}", "path": "temp-nightly", "channel": "latest"}]' electron/package.json > /tmp/package.json - mv /tmp/package.json electron/package.json + # jq '.build.publish = [{"provider": "generic", "url": "https://delta.jan.ai/nightly", "channel": "latest"}, {"provider": "s3", "acl": null, "bucket": "${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}", "region": "${{ secrets.DELTA_AWS_REGION}}", "path": "temp-nightly", "channel": "latest"}]' electron/package.json > /tmp/package.json + # mv /tmp/package.json electron/package.json - jq '.build.win.sign = "./sign.js"' electron/package.json > /tmp/package.json - mv /tmp/package.json electron/package.json - cat electron/package.json + # jq '.build.win.sign = "./sign.js"' electron/package.json > /tmp/package.json + # mv /tmp/package.json electron/package.json + # cat electron/package.json - chmod +x .github/scripts/rename-app.sh - .github/scripts/rename-app.sh ./electron/package.json nightly - chmod +x .github/scripts/rename-workspace.sh - .github/scripts/rename-workspace.sh ./package.json nightly - chmod +x .github/scripts/rename-uninstaller.sh - .github/scripts/rename-uninstaller.sh nightly - echo "------------------------" - cat ./electron/package.json - echo "------------------------" - cat ./package.json - echo "------------------------" + # chmod +x .github/scripts/rename-app.sh + # .github/scripts/rename-app.sh ./electron/package.json nightly + # chmod +x .github/scripts/rename-workspace.sh + # .github/scripts/rename-workspace.sh ./package.json nightly + # chmod +x .github/scripts/rename-uninstaller.sh + # .github/scripts/rename-uninstaller.sh nightly + # echo "------------------------" + # cat ./electron/package.json + # echo "------------------------" + # cat ./package.json + # echo "------------------------" - name: Change App Name for beta version if: inputs.beta == true @@ -148,6 +203,13 @@ jobs: if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && inputs.public_provider == 'github' shell: bash run: | + echo "Version: ${{ inputs.new_version }}" + # Update version in tauri.conf.json + jq --arg version "${{ inputs.new_version }}" '.version = $version' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json + mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json + jq --arg template tauri.bundle.windows.nsis '.bundle.windows.nsis.template = $template' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json + mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json + jq --arg version "${VERSION_TAG#v}" '.version = $version' electron/package.json > /tmp/package.json mv /tmp/package.json electron/package.json jq --arg version "${VERSION_TAG#v}" '.version = $version' web/package.json > /tmp/package.json @@ -159,7 +221,22 @@ jobs: - name: Install AzureSignTool run: | - dotnet tool install --global AzureSignTool + dotnet tool install --global --version 6.0.0 AzureSignTool + + - name: Inject Tauri Signing Public Key + shell: bash + run: | + if [ -f "src-tauri/tauri.conf.json" ]; then + echo "Injecting Tauri public key into configuration..." + # Use jq to update the pubkey field in the tauri.conf.json file + jq --arg pubkey "$TAURI_SIGNING_PUBLIC_KEY" '.plugins.updater.pubkey = $pubkey' src-tauri/tauri.conf.json > /tmp/tauri.conf.json + mv /tmp/tauri.conf.json src-tauri/tauri.conf.json + echo "Tauri configuration updated successfully" + else + echo "tauri.conf.json not found" + fi + env: + TAURI_SIGNING_PUBLIC_KEY: ${{ secrets.TAURI_SIGNING_PUBLIC_KEY }} - name: Build and publish app to aws s3 r2 or github artifactory shell: bash @@ -177,15 +254,18 @@ jobs: AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} - AZURE_CERT_NAME: homebrewltd + AZURE_CERT_NAME: ${{ secrets.AZURE_CERT_NAME }} AWS_ACCESS_KEY_ID: ${{ secrets.DELTA_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.DELTA_AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: auto - AWS_EC2_METADATA_DISABLED: 'true' - AWS_MAX_ATTEMPTS: '5' + AWS_EC2_METADATA_DISABLED: "true" + AWS_MAX_ATTEMPTS: "5" POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }} - CORTEX_API_PORT: ${{ inputs.cortex_api_port }} + # CORTEX_API_PORT: ${{ inputs.cortex_api_port }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + TAURI_SIGNING_PUBLIC_KEY: ${{ secrets.TAURI_SIGNING_PUBLIC_KEY }} - name: Build app and publish app to github if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && inputs.public_provider == 'github' && inputs.beta == false @@ -197,9 +277,12 @@ jobs: AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} - AZURE_CERT_NAME: homebrewltd + AZURE_CERT_NAME: ${{ secrets.AZURE_CERT_NAME }} POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + TAURI_SIGNING_PUBLIC_KEY: ${{ secrets.TAURI_SIGNING_PUBLIC_KEY }} - name: Build app and publish app to github if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && inputs.public_provider == 'github' && inputs.beta == true @@ -210,20 +293,22 @@ jobs: AWS_ACCESS_KEY_ID: ${{ secrets.DELTA_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.DELTA_AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: auto - AWS_EC2_METADATA_DISABLED: 'true' - AWS_MAX_ATTEMPTS: '5' + AWS_EC2_METADATA_DISABLED: "true" + AWS_MAX_ATTEMPTS: "5" AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} - # AZURE_CERT_NAME: ${{ secrets.AZURE_CERT_NAME }} - AZURE_CERT_NAME: homebrewltd + AZURE_CERT_NAME: ${{ secrets.AZURE_CERT_NAME }} POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + TAURI_SIGNING_PUBLIC_KEY: ${{ secrets.TAURI_SIGNING_PUBLIC_KEY }} - - name: Upload Artifact - if: inputs.public_provider != 'github' + - name: Upload Signed Artifact uses: actions/upload-artifact@v4 with: - name: jan-win-x64-${{ inputs.new_version }} - path: ./electron/dist/*.exe \ No newline at end of file + name: jan-tauri-windows-${{ inputs.new_version }} + path: | + ./src-tauri/target/release/bundle/nsis/*.exe diff --git a/package.json b/package.json index 2ecf86a79..c443bf4b0 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "install:cortex:win32": "cd src-tauri/binaries && download.bat", "install:cortex": "run-script-os", "dev:tauri": "yarn build:icon && yarn copy:assets:tauri && tauri dev", - "build:tauri": "yarn install:cortex && yarn build:icon && yarn copy:assets:tauri && yarn tauri build", + "build:tauri": "yarn install:cortex && yarn build:icon && yarn copy:assets:tauri && yarn tauri build --verbose", "build:icon": "tauri icon ./src-tauri/icons/icon.png", "build:server": "cd server && yarn build", "build:core": "cd core && yarn build && yarn pack", @@ -46,6 +46,7 @@ "@tauri-apps/cli": "^2.2.5", "concurrently": "^9.1.0", "cpx": "^1.5.0", + "cross-env": "^7.0.3", "husky": "^9.1.5", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", diff --git a/src-tauri/.gitignore b/src-tauri/.gitignore index 043572272..40726cbe0 100644 --- a/src-tauri/.gitignore +++ b/src-tauri/.gitignore @@ -3,4 +3,5 @@ /target/ /gen/schemas binaries -!binaries/download.sh \ No newline at end of file +!binaries/download.sh +!binaries/download.bat \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index dd2b9bd88..9ae8b0a63 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "jan-nightly" +name = "Jan-nightly" version = "0.5.16-1320" description = "Use offline LLMs with your own data. Run open source models like Llama2 or Falcon on your internal computers/servers." authors = ["Jan "] diff --git a/src-tauri/binaries/download.bat b/src-tauri/binaries/download.bat new file mode 100644 index 000000000..2fe11bbbd --- /dev/null +++ b/src-tauri/binaries/download.bat @@ -0,0 +1,43 @@ +@echo off + +set CORTEX_VERSION=1.0.13-rc1 +set ENGINE_VERSION=0.1.55 +set ENGINE_DOWNLOAD_URL=https://github.com/menloresearch/cortex.llamacpp/releases/download/v%ENGINE_VERSION%/cortex.llamacpp-%ENGINE_VERSION%-windows-amd64 +set CUDA_DOWNLOAD_URL=https://github.com/menloresearch/cortex.llamacpp/releases/download/v%ENGINE_VERSION% +@REM set SUBFOLDERS=windows-amd64-noavx-cuda-12-0 windows-amd64-noavx-cuda-11-7 windows-amd64-avx2-cuda-12-0 windows-amd64-avx2-cuda-11-7 windows-amd64-noavx windows-amd64-avx windows-amd64-avx2 windows-amd64-avx512 windows-amd64-vulkan +set BIN_PATH="./" +set DOWNLOAD_TOOL=..\..\extensions\inference-cortex-extension\node_modules\.bin\download + +@REM Download cortex.llamacpp binaries + +call %DOWNLOAD_TOOL% -e --strip 1 -o %BIN_PATH% https://github.com/menloresearch/cortex.cpp/releases/download/v%CORTEX_VERSION%/cortex-%CORTEX_VERSION%-windows-amd64.tar.gz +@REM call %DOWNLOAD_TOOL% %ENGINE_DOWNLOAD_URL%-avx2-cuda-12-0.tar.gz -e --strip 1 -o ./engines/cortex.llamacpp/windows-amd64-avx2-cuda-12-0/v%ENGINE_VERSION% +@REM call %DOWNLOAD_TOOL% %ENGINE_DOWNLOAD_URL%-avx2-cuda-11-7.tar.gz -e --strip 1 -o ./engines/cortex.llamacpp/windows-amd64-avx2-cuda-11-7/v%ENGINE_VERSION% +@REM call %DOWNLOAD_TOOL% %ENGINE_DOWNLOAD_URL%-noavx-cuda-12-0.tar.gz -e --strip 1 -o ./engines/cortex.llamacpp/windows-amd64-noavx-cuda-12-0/v%ENGINE_VERSION% +@REM call %DOWNLOAD_TOOL% %ENGINE_DOWNLOAD_URL%-noavx-cuda-11-7.tar.gz -e --strip 1 -o ./engines/cortex.llamacpp/windows-amd64-noavx-cuda-11-7/v%ENGINE_VERSION% +call %DOWNLOAD_TOOL% %ENGINE_DOWNLOAD_URL%-noavx.tar.gz -e --strip 1 -o ./engines/cortex.llamacpp/windows-amd64-noavx/v%ENGINE_VERSION% +call %DOWNLOAD_TOOL% %ENGINE_DOWNLOAD_URL%-avx.tar.gz -e --strip 1 -o ./engines/cortex.llamacpp/windows-amd64-avx/v%ENGINE_VERSION% +call %DOWNLOAD_TOOL% %ENGINE_DOWNLOAD_URL%-avx2.tar.gz -e --strip 1 -o ./engines/cortex.llamacpp/windows-amd64-avx2/v%ENGINE_VERSION% +call %DOWNLOAD_TOOL% %ENGINE_DOWNLOAD_URL%-avx512.tar.gz -e --strip 1 -o ./engines/cortex.llamacpp/windows-amd64-avx512/v%ENGINE_VERSION% +call %DOWNLOAD_TOOL% %ENGINE_DOWNLOAD_URL%-vulkan.tar.gz -e --strip 1 -o ./engines/cortex.llamacpp/windows-amd64-vulkan/v%ENGINE_VERSION% +@REM call %DOWNLOAD_TOOL% %CUDA_DOWNLOAD_URL%/cuda-12-0-windows-amd64.tar.gz -e --strip 1 -o %BIN_PATH% +@REM call %DOWNLOAD_TOOL% %CUDA_DOWNLOAD_URL%/cuda-11-7-windows-amd64.tar.gz -e --strip 1 -o %BIN_PATH% + +move %BIN_PATH%cortex-server-beta.exe %BIN_PATH%cortex-server.exe +copy %BIN_PATH%cortex-server.exe %BIN_PATH%cortex-server-x86_64-pc-windows-msvc.exe +del %BIN_PATH%cortex-beta.exe +del %BIN_PATH%cortex.exe + +@REM Loop through each folder and move DLLs (excluding engine.dll) +for %%F in (%SUBFOLDERS%) do ( + echo Processing folder: .\engines\cortex.llamacpp\%%F\v%ENGINE_VERSION% + + @REM Move all .dll files except engine.dll + for %%D in (.\engines\cortex.llamacpp\%%F\v%ENGINE_VERSION%\*.dll) do ( + if /I not "%%~nxD"=="engine.dll" ( + move "%%D" "%BIN_PATH%" + ) + ) +) + +echo DLL files moved successfully. diff --git a/src-tauri/binaries/download.sh b/src-tauri/binaries/download.sh index 6073639e9..f9dbed958 100755 --- a/src-tauri/binaries/download.sh +++ b/src-tauri/binaries/download.sh @@ -32,23 +32,24 @@ fi if [ "$OS_TYPE" == "Linux" ]; then # Linux downloads download "${CORTEX_RELEASE_URL}/v${CORTEX_VERSION}/cortex-${CORTEX_VERSION}-linux-amd64.tar.gz" "${BIN_PATH}" - mv .cortex-server-beta ./cortex-server + mv ./cortex-server-beta ./cortex-server rm -rf ./cortex rm -rf ./cortex-beta chmod +x "./cortex-server" + cp ./cortex-server ./cortex-server-x86_64-unknown-linux-gnu # Download engines for Linux download "${ENGINE_DOWNLOAD_URL}-linux-amd64-noavx.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-noavx/v${ENGINE_VERSION}" download "${ENGINE_DOWNLOAD_URL}-linux-amd64-avx.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-avx/v${ENGINE_VERSION}" download "${ENGINE_DOWNLOAD_URL}-linux-amd64-avx2.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-avx2/v${ENGINE_VERSION}" download "${ENGINE_DOWNLOAD_URL}-linux-amd64-avx512.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-avx512/v${ENGINE_VERSION}" - download "${ENGINE_DOWNLOAD_URL}-linux-amd64-avx2-cuda-12-0.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-avx2-cuda-12-0/v${ENGINE_VERSION}" - download "${ENGINE_DOWNLOAD_URL}-linux-amd64-avx2-cuda-11-7.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-avx2-cuda-11-7/v${ENGINE_VERSION}" - download "${ENGINE_DOWNLOAD_URL}-linux-amd64-noavx-cuda-12-0.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-noavx-cuda-12-0/v${ENGINE_VERSION}" - download "${ENGINE_DOWNLOAD_URL}-linux-amd64-noavx-cuda-11-7.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-noavx-cuda-11-7/v${ENGINE_VERSION}" + # download "${ENGINE_DOWNLOAD_URL}-linux-amd64-avx2-cuda-12-0.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-avx2-cuda-12-0/v${ENGINE_VERSION}" + # download "${ENGINE_DOWNLOAD_URL}-linux-amd64-avx2-cuda-11-7.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-avx2-cuda-11-7/v${ENGINE_VERSION}" + # download "${ENGINE_DOWNLOAD_URL}-linux-amd64-noavx-cuda-12-0.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-noavx-cuda-12-0/v${ENGINE_VERSION}" + # download "${ENGINE_DOWNLOAD_URL}-linux-amd64-noavx-cuda-11-7.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-noavx-cuda-11-7/v${ENGINE_VERSION}" download "${ENGINE_DOWNLOAD_URL}-linux-amd64-vulkan.tar.gz" "${SHARED_PATH}/engines/cortex.llamacpp/linux-amd64-vulkan/v${ENGINE_VERSION}" - download "${CUDA_DOWNLOAD_URL}/cuda-12-0-linux-amd64.tar.gz" "${BIN_PATH}" - download "${CUDA_DOWNLOAD_URL}/cuda-11-7-linux-amd64.tar.gz" "${BIN_PATH}" + # download "${CUDA_DOWNLOAD_URL}/cuda-12-0-linux-amd64.tar.gz" "${BIN_PATH}" + # download "${CUDA_DOWNLOAD_URL}/cuda-11-7-linux-amd64.tar.gz" "${BIN_PATH}" elif [ "$OS_TYPE" == "Darwin" ]; then # macOS downloads diff --git a/src-tauri/sign.ps1 b/src-tauri/sign.ps1 new file mode 100644 index 000000000..a54d525fe --- /dev/null +++ b/src-tauri/sign.ps1 @@ -0,0 +1,12 @@ +param ( + [string]$Target +) + +AzureSignTool.exe sign ` + -tr http://timestamp.digicert.com ` + -kvu $env:AZURE_KEY_VAULT_URI ` + -kvi $env:AZURE_CLIENT_ID ` + -kvt $env:AZURE_TENANT_ID ` + -kvs $env:AZURE_CLIENT_SECRET ` + -kvc $env:AZURE_CERT_NAME ` + -v $Target \ No newline at end of file diff --git a/src-tauri/src/core/cmd.rs b/src-tauri/src/core/cmd.rs index 3d7d921ee..a9f90ca80 100644 --- a/src-tauri/src/core/cmd.rs +++ b/src-tauri/src/core/cmd.rs @@ -101,6 +101,7 @@ pub fn get_jan_data_folder_path(app_handle: tauri::AppHandle) -> } let app_configurations = get_app_configurations(app_handle); + log::info!("data_folder: {}", app_configurations.data_folder); PathBuf::from(app_configurations.data_folder) } @@ -158,7 +159,18 @@ pub fn get_configuration_file_path(app_handle: tauri::AppHandle) PathBuf::from(home_dir) }); - app_path.join(CONFIGURATION_FILE_NAME) + let package_name = env!("CARGO_PKG_NAME"); + log::info!("Package name: {}", package_name); + let old_data_dir = app_path + .clone() + .parent() + .unwrap_or(&app_path.join("../")) + .join(package_name); + if old_data_dir.exists() { + return old_data_dir.join(CONFIGURATION_FILE_NAME); + } else { + return app_path.join(CONFIGURATION_FILE_NAME); + } } #[tauri::command] diff --git a/src-tauri/src/core/setup.rs b/src-tauri/src/core/setup.rs index 1b6e0e7f1..eb049a443 100644 --- a/src-tauri/src/core/setup.rs +++ b/src-tauri/src/core/setup.rs @@ -19,7 +19,9 @@ use super::{ }; pub fn install_extensions(app: tauri::AppHandle, force: bool) -> Result<(), String> { - let store = app.store("store.json").expect("Store not initialized"); + let mut store_path = get_jan_data_folder_path(app.clone()); + store_path.push("store.json"); + let store = app.store(store_path).expect("Store not initialized"); let stored_version = store .get("version") .and_then(|v| v.as_str().map(String::from)) @@ -201,29 +203,20 @@ pub fn setup_sidecar(app: &App) -> Result<(), String> { // Setup sidecar let app_state = app.state::(); + let app_data_dir = get_jan_data_folder_path(app.handle().clone()); let mut sidecar_command = app.shell().sidecar("cortex-server").unwrap().args([ "--start-server", "--port", "39291", "--config_file_path", - app.app_handle() - .path() - .app_data_dir() - .unwrap() - .join(".janrc") - .to_str() - .unwrap(), + app_data_dir.join(".janrc").to_str().unwrap(), "--data_folder_path", - app.app_handle() - .path() - .app_data_dir() - .unwrap() - .to_str() - .unwrap(), + app_data_dir.to_str().unwrap(), "--cors", "ON", "--allowed_origins", - "http://localhost:3000,tauri://localhost", + // TODO(sang) '*' is only for testing purpose, will remove it later + "http://localhost:3000,tauri://localhost,*", "config", "--api_keys", app_state.inner().app_token.as_deref().unwrap_or(""), @@ -289,7 +282,7 @@ fn copy_dir_all(src: PathBuf, dst: PathBuf) -> Result<(), String> { pub fn setup_engine_binaries(app: &App) -> Result<(), String> { // Copy engine binaries to app_data - let app_data_dir = app.handle().path().app_data_dir().unwrap(); + let app_data_dir = get_jan_data_folder_path(app.handle().clone()); let binaries_dir = app.handle().path().resource_dir().unwrap().join("binaries"); let themes_dir = app .handle() diff --git a/src-tauri/tauri.bundle.windows.nsis.template b/src-tauri/tauri.bundle.windows.nsis.template new file mode 100644 index 000000000..472f1f5bd --- /dev/null +++ b/src-tauri/tauri.bundle.windows.nsis.template @@ -0,0 +1,1020 @@ +Unicode true +ManifestDPIAware true +; Add in `dpiAwareness` `PerMonitorV2` to manifest for Windows 10 1607+ (note this should not affect lower versions since they should be able to ignore this and pick up `dpiAware` `true` set by `ManifestDPIAware true`) +; Currently undocumented on NSIS's website but is in the Docs folder of source tree, see +; https://github.com/kichik/nsis/blob/5fc0b87b819a9eec006df4967d08e522ddd651c9/Docs/src/attributes.but#L286-L300 +; https://github.com/tauri-apps/tauri/pull/10106 +ManifestDPIAwareness PerMonitorV2 + +!if "lzma" == "none" + SetCompress off +!else + ; Set the compression algorithm. We default to LZMA. + SetCompressor /SOLID "lzma" +!endif + +!include MUI2.nsh +!include FileFunc.nsh +!include x64.nsh +!include WordFunc.nsh +!include "utils.nsh" +!include "FileAssociation.nsh" +!include "Win\COM.nsh" +!include "Win\Propkey.nsh" +!include "StrFunc.nsh" +${StrCase} +${StrLoc} + + +!define WEBVIEW2APPGUID "{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" + +!define MANUFACTURER "ai" +!define PRODUCTNAME "jan_productname" +!define VERSION "jan_version" +!define VERSIONWITHBUILD "jan_build" +!define HOMEPAGE "" +!define INSTALLMODE "currentUser" +!define LICENSE "" +!define INSTALLERICON "" +!define SIDEBARIMAGE "" +!define HEADERIMAGE "" +!define MAINBINARYNAME "jan_mainbinaryname" +!define MAINBINARYSRCPATH "D:\a\jan\jan\src-tauri\target\release\jan_mainbinaryname.exe" +!define BUNDLEID "jan_mainbinaryname.ai.app" +!define COPYRIGHT "" +!define OUTFILE "nsis-output.exe" +!define ARCH "x64" +!define ADDITIONALPLUGINSPATH "D:\a\jan\jan\src-tauri\target\release\nsis\x64\Plugins\x86-unicode\additional" +!define ALLOWDOWNGRADES "true" +!define DISPLAYLANGUAGESELECTOR "false" +!define INSTALLWEBVIEW2MODE "downloadBootstrapper" +!define WEBVIEW2INSTALLERARGS "/silent" +!define WEBVIEW2BOOTSTRAPPERPATH "" +!define WEBVIEW2INSTALLERPATH "" +!define MINIMUMWEBVIEW2VERSION "" +!define UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}" +!define MANUKEY "Software\${MANUFACTURER}" +!define MANUPRODUCTKEY "${MANUKEY}\${PRODUCTNAME}" +!define UNINSTALLERSIGNCOMMAND "$\"powershell$\" $\"-ExecutionPolicy$\" $\"Bypass$\" $\"-File$\" $\"./sign.ps1$\" $\"%1$\"" +!define ESTIMATEDSIZE "793795" +!define STARTMENUFOLDER "" + +Var PassiveMode +Var UpdateMode +Var NoShortcutMode +Var WixMode +Var OldMainBinaryName + +Name "${PRODUCTNAME}" +BrandingText "${COPYRIGHT}" +OutFile "${OUTFILE}" + +; We don't actually use this value as default install path, +; it's just for nsis to append the product name folder in the directory selector +; https://nsis.sourceforge.io/Reference/InstallDir +!define PLACEHOLDER_INSTALL_DIR "placeholder\${PRODUCTNAME}" +InstallDir "${PLACEHOLDER_INSTALL_DIR}" + +VIProductVersion "${VERSIONWITHBUILD}" +VIAddVersionKey "ProductName" "${PRODUCTNAME}" +VIAddVersionKey "FileDescription" "${PRODUCTNAME}" +VIAddVersionKey "LegalCopyright" "${COPYRIGHT}" +VIAddVersionKey "FileVersion" "${VERSION}" +VIAddVersionKey "ProductVersion" "${VERSION}" + +# additional plugins +!addplugindir "${ADDITIONALPLUGINSPATH}" + +; Uninstaller signing command +!if "${UNINSTALLERSIGNCOMMAND}" != "" + !uninstfinalize '${UNINSTALLERSIGNCOMMAND}' +!endif + +; Handle install mode, `perUser`, `perMachine` or `both` +!if "${INSTALLMODE}" == "perMachine" + RequestExecutionLevel highest +!endif + +!if "${INSTALLMODE}" == "currentUser" + RequestExecutionLevel user +!endif + +!if "${INSTALLMODE}" == "both" + !define MULTIUSER_MUI + !define MULTIUSER_INSTALLMODE_INSTDIR "${PRODUCTNAME}" + !define MULTIUSER_INSTALLMODE_COMMANDLINE + !if "${ARCH}" == "x64" + !define MULTIUSER_USE_PROGRAMFILES64 + !else if "${ARCH}" == "arm64" + !define MULTIUSER_USE_PROGRAMFILES64 + !endif + !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "${UNINSTKEY}" + !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "CurrentUser" + !define MULTIUSER_INSTALLMODEPAGE_SHOWUSERNAME + !define MULTIUSER_INSTALLMODE_FUNCTION RestorePreviousInstallLocation + !define MULTIUSER_EXECUTIONLEVEL Highest + !include MultiUser.nsh +!endif + +; Installer icon +!if "${INSTALLERICON}" != "" + !define MUI_ICON "${INSTALLERICON}" +!endif + +; Installer sidebar image +!if "${SIDEBARIMAGE}" != "" + !define MUI_WELCOMEFINISHPAGE_BITMAP "${SIDEBARIMAGE}" +!endif + +; Installer header image +!if "${HEADERIMAGE}" != "" + !define MUI_HEADERIMAGE + !define MUI_HEADERIMAGE_BITMAP "${HEADERIMAGE}" +!endif + +; Define registry key to store installer language +!define MUI_LANGDLL_REGISTRY_ROOT "HKCU" +!define MUI_LANGDLL_REGISTRY_KEY "${MANUPRODUCTKEY}" +!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language" + +; Installer pages, must be ordered as they appear +; 1. Welcome Page +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive +!insertmacro MUI_PAGE_WELCOME + +; 2. License Page (if defined) +!if "${LICENSE}" != "" + !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive + !insertmacro MUI_PAGE_LICENSE "${LICENSE}" +!endif + +; 3. Install mode (if it is set to `both`) +!if "${INSTALLMODE}" == "both" + !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive + !insertmacro MULTIUSER_PAGE_INSTALLMODE +!endif + +; 4. Custom page to ask user if he wants to reinstall/uninstall +; only if a previous installation was detected +Var ReinstallPageCheck +Page custom PageReinstall PageLeaveReinstall +Function PageReinstall + ; Uninstall previous WiX installation if exists. + ; + ; A WiX installer stores the installation info in registry + ; using a UUID and so we have to loop through all keys under + ; `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + ; and check if `DisplayName` and `Publisher` keys match ${PRODUCTNAME} and ${MANUFACTURER} + ; + ; This has a potential issue that there maybe another installation that matches + ; our ${PRODUCTNAME} and ${MANUFACTURER} but wasn't installed by our WiX installer, + ; however, this should be fine since the user will have to confirm the uninstallation + ; and they can chose to abort it if doesn't make sense. + StrCpy $0 0 + wix_loop: + EnumRegKey $1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" $0 + StrCmp $1 "" wix_loop_done ; Exit loop if there is no more keys to loop on + IntOp $0 $0 + 1 + ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "DisplayName" + ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "Publisher" + StrCmp "$R0$R1" "${PRODUCTNAME}${MANUFACTURER}" 0 wix_loop + ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "UninstallString" + ${StrCase} $R1 $R0 "L" + ${StrLoc} $R0 $R1 "msiexec" ">" + StrCmp $R0 0 0 wix_loop_done + StrCpy $WixMode 1 + StrCpy $R6 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" + Goto compare_version + wix_loop_done: + + ; Check if there is an existing installation, if not, abort the reinstall page + ReadRegStr $R0 SHCTX "${UNINSTKEY}" "" + ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString" + ${IfThen} "$R0$R1" == "" ${|} Abort ${|} + + ; Compare this installar version with the existing installation + ; and modify the messages presented to the user accordingly + compare_version: + StrCpy $R4 "$(older)" + ${If} $WixMode = 1 + ReadRegStr $R0 HKLM "$R6" "DisplayVersion" + ${Else} + ReadRegStr $R0 SHCTX "${UNINSTKEY}" "DisplayVersion" + ${EndIf} + ${IfThen} $R0 == "" ${|} StrCpy $R4 "$(unknown)" ${|} + + nsis_tauri_utils::SemverCompare "${VERSION}" $R0 + Pop $R0 + ; Reinstalling the same version + ${If} $R0 = 0 + StrCpy $R1 "$(alreadyInstalledLong)" + StrCpy $R2 "$(addOrReinstall)" + StrCpy $R3 "$(uninstallApp)" + !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(chooseMaintenanceOption)" + ; Upgrading + ${ElseIf} $R0 = 1 + StrCpy $R1 "$(olderOrUnknownVersionInstalled)" + StrCpy $R2 "$(uninstallBeforeInstalling)" + StrCpy $R3 "$(dontUninstall)" + !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)" + ; Downgrading + ${ElseIf} $R0 = -1 + StrCpy $R1 "$(newerVersionInstalled)" + StrCpy $R2 "$(uninstallBeforeInstalling)" + !if "${ALLOWDOWNGRADES}" == "true" + StrCpy $R3 "$(dontUninstall)" + !else + StrCpy $R3 "$(dontUninstallDowngrade)" + !endif + !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)" + ${Else} + Abort + ${EndIf} + + ; Skip showing the page if passive + ; + ; Note that we don't call this earlier at the begining + ; of this function because we need to populate some variables + ; related to current installed version if detected and whether + ; we are downgrading or not. + ${If} $PassiveMode = 1 + Call PageLeaveReinstall + ${Else} + nsDialogs::Create 1018 + Pop $R4 + ${IfThen} $(^RTL) = 1 ${|} nsDialogs::SetRTL $(^RTL) ${|} + + ${NSD_CreateLabel} 0 0 100% 24u $R1 + Pop $R1 + + ${NSD_CreateRadioButton} 30u 50u -30u 8u $R2 + Pop $R2 + ${NSD_OnClick} $R2 PageReinstallUpdateSelection + + ${NSD_CreateRadioButton} 30u 70u -30u 8u $R3 + Pop $R3 + ; Disable this radio button if downgrading and downgrades are disabled + !if "${ALLOWDOWNGRADES}" == "false" + ${IfThen} $R0 = -1 ${|} EnableWindow $R3 0 ${|} + !endif + ${NSD_OnClick} $R3 PageReinstallUpdateSelection + + ; Check the first radio button if this the first time + ; we enter this page or if the second button wasn't + ; selected the last time we were on this page + ${If} $ReinstallPageCheck <> 2 + SendMessage $R2 ${BM_SETCHECK} ${BST_CHECKED} 0 + ${Else} + SendMessage $R3 ${BM_SETCHECK} ${BST_CHECKED} 0 + ${EndIf} + + ${NSD_SetFocus} $R2 + nsDialogs::Show + ${EndIf} +FunctionEnd +Function PageReinstallUpdateSelection + ${NSD_GetState} $R2 $R1 + ${If} $R1 == ${BST_CHECKED} + StrCpy $ReinstallPageCheck 1 + ${Else} + StrCpy $ReinstallPageCheck 2 + ${EndIf} +FunctionEnd +Function PageLeaveReinstall + ${NSD_GetState} $R2 $R1 + + ; If migrating from Wix, always uninstall + ${If} $WixMode = 1 + Goto reinst_uninstall + ${EndIf} + + ; In update mode, always proceeds without uninstalling + ${If} $UpdateMode = 1 + Goto reinst_done + ${EndIf} + + ; $R0 holds whether same(0)/upgrading(1)/downgrading(-1) version + ; $R1 holds the radio buttons state: + ; 1 => first choice was selected + ; 0 => second choice was selected + ${If} $R0 = 0 ; Same version, proceed + ${If} $R1 = 1 ; User chose to add/reinstall + Goto reinst_done + ${Else} ; User chose to uninstall + Goto reinst_uninstall + ${EndIf} + ${ElseIf} $R0 = 1 ; Upgrading + ${If} $R1 = 1 ; User chose to uninstall + Goto reinst_uninstall + ${Else} + Goto reinst_done ; User chose NOT to uninstall + ${EndIf} + ${ElseIf} $R0 = -1 ; Downgrading + ${If} $R1 = 1 ; User chose to uninstall + Goto reinst_uninstall + ${Else} + Goto reinst_done ; User chose NOT to uninstall + ${EndIf} + ${EndIf} + + reinst_uninstall: + HideWindow + ClearErrors + + ${If} $WixMode = 1 + ReadRegStr $R1 HKLM "$R6" "UninstallString" + ExecWait '$R1' $0 + ${Else} + ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" "" + ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString" + ${IfThen} $UpdateMode = 1 ${|} StrCpy $R1 "$R1 /UPDATE" ${|} ; append /UPDATE + ${IfThen} $PassiveMode = 1 ${|} StrCpy $R1 "$R1 /P" ${|} ; append /P + StrCpy $R1 "$R1 _?=$4" ; append uninstall directory + ExecWait '$R1' $0 + ${EndIf} + + BringToFront + + ${IfThen} ${Errors} ${|} StrCpy $0 2 ${|} ; ExecWait failed, set fake exit code + + ${If} $0 <> 0 + ${OrIf} ${FileExists} "$INSTDIR\${MAINBINARYNAME}.exe" + ; User cancelled wix uninstaller? return to select un/reinstall page + ${If} $WixMode = 1 + ${AndIf} $0 = 1602 + Abort + ${EndIf} + + ; User cancelled NSIS uninstaller? return to select un/reinstall page + ${If} $0 = 1 + Abort + ${EndIf} + + ; Other erros? show generic error message and return to select un/reinstall page + MessageBox MB_ICONEXCLAMATION "$(unableToUninstall)" + Abort + ${EndIf} + reinst_done: +FunctionEnd + +; 5. Choose install directory page +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive +!insertmacro MUI_PAGE_DIRECTORY + +; 6. Start menu shortcut page +Var AppStartMenuFolder +!if "${STARTMENUFOLDER}" != "" + !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive + !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${STARTMENUFOLDER}" +!else + !define MUI_PAGE_CUSTOMFUNCTION_PRE Skip +!endif +!insertmacro MUI_PAGE_STARTMENU Application $AppStartMenuFolder + +; 7. Installation page +!insertmacro MUI_PAGE_INSTFILES + +; 8. Finish page +; +; Don't auto jump to finish page after installation page, +; because the installation page has useful info that can be used debug any issues with the installer. +!define MUI_FINISHPAGE_NOAUTOCLOSE +; Use show readme button in the finish page as a button create a desktop shortcut +!define MUI_FINISHPAGE_SHOWREADME +!define MUI_FINISHPAGE_SHOWREADME_TEXT "$(createDesktop)" +!define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateOrUpdateDesktopShortcut +; Show run app after installation. +!define MUI_FINISHPAGE_RUN +!define MUI_FINISHPAGE_RUN_FUNCTION RunMainBinary +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive +!insertmacro MUI_PAGE_FINISH + +Function RunMainBinary + nsis_tauri_utils::RunAsUser "$INSTDIR\${MAINBINARYNAME}.exe" "" +FunctionEnd + +; Uninstaller Pages +; 1. Confirm uninstall page +Var DeleteAppDataCheckbox +Var DeleteAppDataCheckboxState +!define /ifndef WS_EX_LAYOUTRTL 0x00400000 +!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.ConfirmShow +Function un.ConfirmShow ; Add add a `Delete app data` check box + ; $1 inner dialog HWND + ; $2 window DPI + ; $3 style + ; $4 x + ; $5 y + ; $6 width + ; $7 height + FindWindow $1 "#32770" "" $HWNDPARENT ; Find inner dialog + System::Call "user32::GetDpiForWindow(p r1) i .r2" + ${If} $(^RTL) = 1 + StrCpy $3 "${__NSD_CheckBox_EXSTYLE} | ${WS_EX_LAYOUTRTL}" + IntOp $4 50 * $2 + ${Else} + StrCpy $3 "${__NSD_CheckBox_EXSTYLE}" + IntOp $4 0 * $2 + ${EndIf} + IntOp $5 100 * $2 + IntOp $6 400 * $2 + IntOp $7 25 * $2 + IntOp $4 $4 / 96 + IntOp $5 $5 / 96 + IntOp $6 $6 / 96 + IntOp $7 $7 / 96 + System::Call 'user32::CreateWindowEx(i r3, w "${__NSD_CheckBox_CLASS}", w "$(deleteAppData)", i ${__NSD_CheckBox_STYLE}, i r4, i r5, i r6, i r7, p r1, i0, i0, i0) i .s' + Pop $DeleteAppDataCheckbox + SendMessage $HWNDPARENT ${WM_GETFONT} 0 0 $1 + SendMessage $DeleteAppDataCheckbox ${WM_SETFONT} $1 1 +FunctionEnd +!define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.ConfirmLeave +Function un.ConfirmLeave + SendMessage $DeleteAppDataCheckbox ${BM_GETCHECK} 0 0 $DeleteAppDataCheckboxState +FunctionEnd +!define MUI_PAGE_CUSTOMFUNCTION_PRE un.SkipIfPassive +!insertmacro MUI_UNPAGE_CONFIRM + +; 2. Uninstalling Page +!insertmacro MUI_UNPAGE_INSTFILES + +;Languages +!insertmacro MUI_LANGUAGE "English" +!insertmacro MUI_RESERVEFILE_LANGDLL + !include "D:\a\jan\jan\src-tauri\target\release\nsis\x64\English.nsh" + +Function .onInit + ${GetOptions} $CMDLINE "/P" $PassiveMode + ${IfNot} ${Errors} + StrCpy $PassiveMode 1 + ${EndIf} + ; always run in passive mode + StrCpy $PassiveMode 1 + + ${GetOptions} $CMDLINE "/NS" $NoShortcutMode + ${IfNot} ${Errors} + StrCpy $NoShortcutMode 1 + ${EndIf} + + ${GetOptions} $CMDLINE "/UPDATE" $UpdateMode + ${IfNot} ${Errors} + StrCpy $UpdateMode 1 + ${EndIf} + + !if "${DISPLAYLANGUAGESELECTOR}" == "true" + !insertmacro MUI_LANGDLL_DISPLAY + !endif + + !insertmacro SetContext + + ${If} $INSTDIR == "${PLACEHOLDER_INSTALL_DIR}" + ; Set default install location + !if "${INSTALLMODE}" == "perMachine" + ${If} ${RunningX64} + !if "${ARCH}" == "x64" + StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCTNAME}" + !else if "${ARCH}" == "arm64" + StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCTNAME}" + !else + StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCTNAME}" + !endif + ${Else} + StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCTNAME}" + ${EndIf} + !else if "${INSTALLMODE}" == "currentUser" + StrCpy $INSTDIR "$LOCALAPPDATA\Programs\${PRODUCTNAME}" + !endif + + Call RestorePreviousInstallLocation + ${EndIf} + + + !if "${INSTALLMODE}" == "both" + !insertmacro MULTIUSER_INIT + !endif +FunctionEnd + + +Section EarlyChecks + ; Abort silent installer if downgrades is disabled + !if "${ALLOWDOWNGRADES}" == "false" + ${If} ${Silent} + ; If downgrading + ${If} $R0 = -1 + System::Call 'kernel32::AttachConsole(i -1)i.r0' + ${If} $0 <> 0 + System::Call 'kernel32::GetStdHandle(i -11)i.r0' + System::call 'kernel32::SetConsoleTextAttribute(i r0, i 0x0004)' ; set red color + FileWrite $0 "$(silentDowngrades)" + ${EndIf} + Abort + ${EndIf} + ${EndIf} + !endif + +SectionEnd + +Section WebView2 + ; Check if Webview2 is already installed and skip this section + ${If} ${RunningX64} + ReadRegStr $4 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\${WEBVIEW2APPGUID}" "pv" + ${Else} + ReadRegStr $4 HKLM "SOFTWARE\Microsoft\EdgeUpdate\Clients\${WEBVIEW2APPGUID}" "pv" + ${EndIf} + ${If} $4 == "" + ReadRegStr $4 HKCU "SOFTWARE\Microsoft\EdgeUpdate\Clients\${WEBVIEW2APPGUID}" "pv" + ${EndIf} + + ${If} $4 == "" + ; Webview2 installation + ; + ; Skip if updating + ${If} $UpdateMode <> 1 + !if "${INSTALLWEBVIEW2MODE}" == "downloadBootstrapper" + Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe" + DetailPrint "$(webview2Downloading)" + NSISdl::download "https://go.microsoft.com/fwlink/p/?LinkId=2124703" "$TEMP\MicrosoftEdgeWebview2Setup.exe" + Pop $0 + ${If} $0 == "success" + DetailPrint "$(webview2DownloadSuccess)" + ${Else} + DetailPrint "$(webview2DownloadError)" + Abort "$(webview2AbortError)" + ${EndIf} + StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe" + Goto install_webview2 + !endif + + !if "${INSTALLWEBVIEW2MODE}" == "embedBootstrapper" + Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe" + File "/oname=$TEMP\MicrosoftEdgeWebview2Setup.exe" "${WEBVIEW2BOOTSTRAPPERPATH}" + DetailPrint "$(installingWebview2)" + StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe" + Goto install_webview2 + !endif + + !if "${INSTALLWEBVIEW2MODE}" == "offlineInstaller" + Delete "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe" + File "/oname=$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe" "${WEBVIEW2INSTALLERPATH}" + DetailPrint "$(installingWebview2)" + StrCpy $6 "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe" + Goto install_webview2 + !endif + + Goto webview2_done + + install_webview2: + DetailPrint "$(installingWebview2)" + ; $6 holds the path to the webview2 installer + ExecWait "$6 ${WEBVIEW2INSTALLERARGS} /install" $1 + ${If} $1 = 0 + DetailPrint "$(webview2InstallSuccess)" + ${Else} + DetailPrint "$(webview2InstallError)" + Abort "$(webview2AbortError)" + ${EndIf} + webview2_done: + ${EndIf} + ${Else} + !if "${MINIMUMWEBVIEW2VERSION}" != "" + ${VersionCompare} "${MINIMUMWEBVIEW2VERSION}" "$4" $R0 + ${If} $R0 = 1 + update_webview: + DetailPrint "$(installingWebview2)" + ${If} ${RunningX64} + ReadRegStr $R1 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate" "path" + ${Else} + ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\EdgeUpdate" "path" + ${EndIf} + ${If} $R1 == "" + ReadRegStr $R1 HKCU "SOFTWARE\Microsoft\EdgeUpdate" "path" + ${EndIf} + ${If} $R1 != "" + ; Chromium updater docs: https://source.chromium.org/chromium/chromium/src/+/main:docs/updater/user_manual.md + ; Modified from "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft EdgeWebView\ModifyPath" + ExecWait `"$R1" /install appguid=${WEBVIEW2APPGUID}&needsadmin=true` $1 + ${If} $1 = 0 + DetailPrint "$(webview2InstallSuccess)" + ${Else} + MessageBox MB_ICONEXCLAMATION|MB_ABORTRETRYIGNORE "$(webview2InstallError)" IDIGNORE ignore IDRETRY update_webview + Quit + ignore: + ${EndIf} + ${EndIf} + ${EndIf} + !endif + ${EndIf} +SectionEnd + +Section Install + SetOutPath $INSTDIR + + !ifmacrodef NSIS_HOOK_PREINSTALL + !insertmacro NSIS_HOOK_PREINSTALL + !endif + + !insertmacro CheckIfAppIsRunning + + ; Copy main executable + File "${MAINBINARYSRCPATH}" + + ; Copy resources + CreateDirectory "$INSTDIR\resources\themes\joi-light" + CreateDirectory "$INSTDIR\resources\pre-install" + CreateDirectory "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55" + CreateDirectory "$INSTDIR\resources\themes\night-blue" + CreateDirectory "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55" + CreateDirectory "$INSTDIR\resources\themes\joi-dark" + CreateDirectory "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55" + CreateDirectory "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55" + CreateDirectory "$INSTDIR\resources\themes\dark-dimmed" + CreateDirectory "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\engine.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\engine.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\msvcp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\msvcp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\vcomp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\vcomp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\vcruntime140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\vcruntime140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\vcruntime140_1.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\vcruntime140_1.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\version.txt" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\version.txt" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\engine.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\engine.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\msvcp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\msvcp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\vcomp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\vcomp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\vcruntime140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\vcruntime140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\vcruntime140_1.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\vcruntime140_1.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\version.txt" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\version.txt" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\engine.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\engine.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\msvcp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\msvcp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\vcomp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\vcomp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\vcruntime140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\vcruntime140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\vcruntime140_1.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\vcruntime140_1.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\version.txt" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\version.txt" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\engine.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\engine.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\msvcp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\msvcp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\vcomp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\vcomp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\vcruntime140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\vcruntime140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\vcruntime140_1.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\vcruntime140_1.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\version.txt" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\version.txt" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\engine.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\engine.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\msvcp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\msvcp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\vcomp140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\vcomp140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\vcruntime140.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\vcruntime140.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\vcruntime140_1.dll" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\vcruntime140_1.dll" + File /a "/oname=binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\version.txt" "D:\a\jan\jan\src-tauri\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\version.txt" + File /a "/oname=resources\pre-install\janhq-assistant-extension-1.0.2.tgz" "D:\a\jan\jan\src-tauri\resources\pre-install\janhq-assistant-extension-1.0.2.tgz" + File /a "/oname=resources\pre-install\janhq-conversational-extension-1.0.0.tgz" "D:\a\jan\jan\src-tauri\resources\pre-install\janhq-conversational-extension-1.0.0.tgz" + File /a "/oname=resources\pre-install\janhq-engine-management-extension-1.0.3.tgz" "D:\a\jan\jan\src-tauri\resources\pre-install\janhq-engine-management-extension-1.0.3.tgz" + File /a "/oname=resources\pre-install\janhq-hardware-management-extension-1.0.0.tgz" "D:\a\jan\jan\src-tauri\resources\pre-install\janhq-hardware-management-extension-1.0.0.tgz" + File /a "/oname=resources\pre-install\janhq-inference-cortex-extension-1.0.25.tgz" "D:\a\jan\jan\src-tauri\resources\pre-install\janhq-inference-cortex-extension-1.0.25.tgz" + File /a "/oname=resources\pre-install\janhq-model-extension-1.0.36.tgz" "D:\a\jan\jan\src-tauri\resources\pre-install\janhq-model-extension-1.0.36.tgz" + File /a "/oname=resources\themes\dark-dimmed\theme.json" "D:\a\jan\jan\src-tauri\resources\themes\dark-dimmed\theme.json" + File /a "/oname=resources\themes\joi-dark\theme.json" "D:\a\jan\jan\src-tauri\resources\themes\joi-dark\theme.json" + File /a "/oname=resources\themes\joi-light\theme.json" "D:\a\jan\jan\src-tauri\resources\themes\joi-light\theme.json" + File /a "/oname=resources\themes\night-blue\theme.json" "D:\a\jan\jan\src-tauri\resources\themes\night-blue\theme.json" + + ; Copy external binaries + File /a "/oname=cortex-server.exe" "D:\a\jan\jan\src-tauri\binaries\cortex-server-x86_64-pc-windows-msvc.exe" + + ; Create file associations + + ; Register deep links + + ; Create uninstaller + WriteUninstaller "$INSTDIR\uninstall.exe" + + ; Save $INSTDIR in registry for future installations + WriteRegStr SHCTX "${MANUPRODUCTKEY}" "" $INSTDIR + + !if "${INSTALLMODE}" == "both" + ; Save install mode to be selected by default for the next installation such as updating + ; or when uninstalling + WriteRegStr SHCTX "${UNINSTKEY}" $MultiUser.InstallMode 1 + !endif + + ; Remove old main binary if it doesn't match new main binary name + ReadRegStr $OldMainBinaryName SHCTX "${UNINSTKEY}" "MainBinaryName" + ${If} $OldMainBinaryName != "" + ${AndIf} $OldMainBinaryName != "${MAINBINARYNAME}.exe" + Delete "$INSTDIR\$OldMainBinaryName" + ${EndIf} + + ; Save current MAINBINARYNAME for future updates + WriteRegStr SHCTX "${UNINSTKEY}" "MainBinaryName" "${MAINBINARYNAME}.exe" + + ; Registry information for add/remove programs + WriteRegStr SHCTX "${UNINSTKEY}" "DisplayName" "${PRODUCTNAME}" + WriteRegStr SHCTX "${UNINSTKEY}" "DisplayIcon" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\"" + WriteRegStr SHCTX "${UNINSTKEY}" "DisplayVersion" "${VERSION}" + WriteRegStr SHCTX "${UNINSTKEY}" "Publisher" "${MANUFACTURER}" + WriteRegStr SHCTX "${UNINSTKEY}" "InstallLocation" "$\"$INSTDIR$\"" + WriteRegStr SHCTX "${UNINSTKEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1" + WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1" + + ${GetSize} "$INSTDIR" "/M=uninstall.exe /S=0K /G=0" $0 $1 $2 + IntOp $0 $0 + ${ESTIMATEDSIZE} + IntFmt $0 "0x%08X" $0 + WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "$0" + + !if "${HOMEPAGE}" != "" + WriteRegStr SHCTX "${UNINSTKEY}" "URLInfoAbout" "${HOMEPAGE}" + WriteRegStr SHCTX "${UNINSTKEY}" "URLUpdateInfo" "${HOMEPAGE}" + WriteRegStr SHCTX "${UNINSTKEY}" "HelpLink" "${HOMEPAGE}" + !endif + + ; Create start menu shortcut + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + Call CreateOrUpdateStartMenuShortcut + !insertmacro MUI_STARTMENU_WRITE_END + + ; Create desktop shortcut for silent and passive installers + ; because finish page will be skipped + ${If} $PassiveMode = 1 + ${OrIf} ${Silent} + Call CreateOrUpdateDesktopShortcut + ${EndIf} + + !ifmacrodef NSIS_HOOK_POSTINSTALL + !insertmacro NSIS_HOOK_POSTINSTALL + !endif + + ; Auto close this page for passive mode + ${If} $PassiveMode = 1 + SetAutoClose true + ${EndIf} +SectionEnd + +Function .onInstSuccess + ; Check for `/R` flag only in silent and passive installers because + ; GUI installer has a toggle for the user to (re)start the app + ${If} $PassiveMode = 1 + ${OrIf} ${Silent} + ; ${GetOptions} $CMDLINE "/R" $R0 + ; ${IfNot} ${Errors} + ${GetOptions} $CMDLINE "/ARGS" $R0 + nsis_tauri_utils::RunAsUser "$INSTDIR\${MAINBINARYNAME}.exe" "$R0" + ; ${EndIf} + ${EndIf} +FunctionEnd + +Function un.onInit + !insertmacro SetContext + + !if "${INSTALLMODE}" == "both" + !insertmacro MULTIUSER_UNINIT + !endif + + !insertmacro MUI_UNGETLANGUAGE + + ${GetOptions} $CMDLINE "/P" $PassiveMode + ${IfNot} ${Errors} + StrCpy $PassiveMode 1 + ${EndIf} + + ${GetOptions} $CMDLINE "/UPDATE" $UpdateMode + ${IfNot} ${Errors} + StrCpy $UpdateMode 1 + ${EndIf} +FunctionEnd + +Section Uninstall + + !ifmacrodef NSIS_HOOK_PREUNINSTALL + !insertmacro NSIS_HOOK_PREUNINSTALL + !endif + + !insertmacro CheckIfAppIsRunning + + ; Delete the app directory and its content from disk + ; Copy main executable + Delete "$INSTDIR\${MAINBINARYNAME}.exe" + + ; Delete resources + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\engine.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\msvcp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\vcomp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\vcruntime140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\vcruntime140_1.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55\version.txt" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\engine.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\msvcp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\vcomp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\vcruntime140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\vcruntime140_1.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55\version.txt" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\engine.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\msvcp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\vcomp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\vcruntime140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\vcruntime140_1.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55\version.txt" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\engine.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\msvcp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\vcomp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\vcruntime140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\vcruntime140_1.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55\version.txt" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\engine.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\msvcp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\vcomp140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\vcruntime140.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\vcruntime140_1.dll" + Delete "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55\version.txt" + Delete "$INSTDIR\resources\pre-install\janhq-assistant-extension-1.0.2.tgz" + Delete "$INSTDIR\resources\pre-install\janhq-conversational-extension-1.0.0.tgz" + Delete "$INSTDIR\resources\pre-install\janhq-engine-management-extension-1.0.3.tgz" + Delete "$INSTDIR\resources\pre-install\janhq-hardware-management-extension-1.0.0.tgz" + Delete "$INSTDIR\resources\pre-install\janhq-inference-cortex-extension-1.0.25.tgz" + Delete "$INSTDIR\resources\pre-install\janhq-model-extension-1.0.36.tgz" + Delete "$INSTDIR\resources\themes\dark-dimmed\theme.json" + Delete "$INSTDIR\resources\themes\joi-dark\theme.json" + Delete "$INSTDIR\resources\themes\joi-light\theme.json" + Delete "$INSTDIR\resources\themes\night-blue\theme.json" + + ; Delete external binaries + Delete "$INSTDIR\cortex-server.exe" + + ; Delete app associations + + ; Delete deep links + + + ; Delete uninstaller + Delete "$INSTDIR\uninstall.exe" + + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx\v0.1.55" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx2\v0.1.55" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx512\v0.1.55" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-noavx\v0.1.55" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-vulkan\v0.1.55" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx2" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-avx512" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-noavx" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp\windows-amd64-vulkan" + RMDir /REBOOTOK "$INSTDIR\binaries\engines\cortex.llamacpp" + RMDir /REBOOTOK "$INSTDIR\resources\themes\dark-dimmed" + RMDir /REBOOTOK "$INSTDIR\resources\themes\joi-dark" + RMDir /REBOOTOK "$INSTDIR\resources\themes\joi-light" + RMDir /REBOOTOK "$INSTDIR\resources\themes\night-blue" + RMDir /REBOOTOK "$INSTDIR\binaries\engines" + RMDir /REBOOTOK "$INSTDIR\resources\pre-install" + RMDir /REBOOTOK "$INSTDIR\resources\themes" + RMDir /REBOOTOK "$INSTDIR\binaries" + RMDir /REBOOTOK "$INSTDIR\resources" + RMDir "$INSTDIR" + + ; Remove shortcuts if not updating + ${If} $UpdateMode <> 1 + !insertmacro DeleteAppUserModelId + + ; Remove start menu shortcut + !insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder + !insertmacro IsShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + Pop $0 + ${If} $0 = 1 + !insertmacro UnpinShortcut "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" + Delete "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" + RMDir "$SMPROGRAMS\$AppStartMenuFolder" + ${EndIf} + !insertmacro IsShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + Pop $0 + ${If} $0 = 1 + !insertmacro UnpinShortcut "$SMPROGRAMS\${PRODUCTNAME}.lnk" + Delete "$SMPROGRAMS\${PRODUCTNAME}.lnk" + ${EndIf} + + ; Remove desktop shortcuts + !insertmacro IsShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + Pop $0 + ${If} $0 = 1 + !insertmacro UnpinShortcut "$DESKTOP\${PRODUCTNAME}.lnk" + Delete "$DESKTOP\${PRODUCTNAME}.lnk" + ${EndIf} + ${EndIf} + + ; Remove registry information for add/remove programs + !if "${INSTALLMODE}" == "both" + DeleteRegKey SHCTX "${UNINSTKEY}" + !else if "${INSTALLMODE}" == "perMachine" + DeleteRegKey HKLM "${UNINSTKEY}" + !else + DeleteRegKey HKCU "${UNINSTKEY}" + !endif + + ; Removes the Autostart entry for ${PRODUCTNAME} from the HKCU Run key if it exists. + ; This ensures the program does not launch automatically after uninstallation if it exists. + ; If it doesn't exist, it does nothing. + ; We do this when not updating (to preserve the registry value on updates) + ${If} $UpdateMode <> 1 + DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "${PRODUCTNAME}" + ${EndIf} + + ; Delete app data if the checkbox is selected + ; and if not updating + ${If} $DeleteAppDataCheckboxState = 1 + ${AndIf} $UpdateMode <> 1 + ; Clear the install location $INSTDIR from registry + DeleteRegKey SHCTX "${MANUPRODUCTKEY}" + DeleteRegKey /ifempty SHCTX "${MANUKEY}" + + ; Clear the install language from registry + DeleteRegValue HKCU "${MANUPRODUCTKEY}" "Installer Language" + DeleteRegKey /ifempty HKCU "${MANUPRODUCTKEY}" + DeleteRegKey /ifempty HKCU "${MANUKEY}" + + SetShellVarContext current + RmDir /r "$APPDATA\${BUNDLEID}" + RmDir /r "$LOCALAPPDATA\${BUNDLEID}" + ${EndIf} + + !ifmacrodef NSIS_HOOK_POSTUNINSTALL + !insertmacro NSIS_HOOK_POSTUNINSTALL + !endif + + ; Auto close if passive mode or updating + ${If} $PassiveMode = 1 + ${OrIf} $UpdateMode = 1 + SetAutoClose true + ${EndIf} +SectionEnd + +Function RestorePreviousInstallLocation + ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" "" + StrCmp $4 "" +2 0 + StrCpy $INSTDIR $4 +FunctionEnd + +Function Skip + Abort +FunctionEnd + +Function SkipIfPassive + ${IfThen} $PassiveMode = 1 ${|} Abort ${|} +FunctionEnd +Function un.SkipIfPassive + ${IfThen} $PassiveMode = 1 ${|} Abort ${|} +FunctionEnd + +Function CreateOrUpdateStartMenuShortcut + ; We used to use product name as MAINBINARYNAME + ; migrate old shortcuts to target the new MAINBINARYNAME + StrCpy $R0 0 + + !insertmacro IsShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\$OldMainBinaryName" + Pop $0 + ${If} $0 = 1 + !insertmacro SetShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + StrCpy $R0 1 + ${EndIf} + + !insertmacro IsShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\$OldMainBinaryName" + Pop $0 + ${If} $0 = 1 + !insertmacro SetShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + StrCpy $R0 1 + ${EndIf} + + ${If} $R0 = 1 + Return + ${EndIf} + + ; Skip creating shortcut if in update mode or no shortcut mode + ; but always create if migrating from wix + ${If} $WixMode = 0 + ${If} $UpdateMode = 1 + ${OrIf} $NoShortcutMode = 1 + Return + ${EndIf} + ${EndIf} + + !if "${STARTMENUFOLDER}" != "" + CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder" + CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + !insertmacro SetLnkAppUserModelId "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" + !else + CreateShortcut "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + !insertmacro SetLnkAppUserModelId "$SMPROGRAMS\${PRODUCTNAME}.lnk" + !endif +FunctionEnd + +Function CreateOrUpdateDesktopShortcut + ; We used to use product name as MAINBINARYNAME + ; migrate old shortcuts to target the new MAINBINARYNAME + !insertmacro IsShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\$OldMainBinaryName" + Pop $0 + ${If} $0 = 1 + !insertmacro SetShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + Return + ${EndIf} + + ; Skip creating shortcut if in update mode or no shortcut mode + ; but always create if migrating from wix + ${If} $WixMode = 0 + ${If} $UpdateMode = 1 + ${OrIf} $NoShortcutMode = 1 + Return + ${EndIf} + ${EndIf} + + CreateShortcut "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + !insertmacro SetLnkAppUserModelId "$DESKTOP\${PRODUCTNAME}.lnk" +FunctionEnd diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6b8a604b6..efbc154f0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -6,8 +6,8 @@ "build": { "frontendDist": "../web/out", "devUrl": "http://localhost:3000", - "beforeDevCommand": "IS_TAURI=true yarn dev:web", - "beforeBuildCommand": "IS_TAURI=true yarn build:web" + "beforeDevCommand": "cross-env IS_TAURI=true yarn dev:web", + "beforeBuildCommand": "cross-env IS_TAURI=true yarn build:web" }, "app": { "macOSPrivateApi": true, @@ -30,11 +30,11 @@ "security": { "csp": { "default-src": "'self' customprotocol: asset: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*", - "connect-src": "ipc: http://ipc.localhost http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*", + "connect-src": "ipc: http://ipc.localhost http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:* https://registry.npmjs.org", "font-src": ["https://fonts.gstatic.com blob: data:"], "img-src": "'self' asset: http://asset.localhost blob: data:", "style-src": "'unsafe-inline' 'self' https://fonts.googleapis.com", - "script-src": "'self' asset: $APPDATA/**.*" + "script-src": "'self' asset: $APPDATA/**.* http://asset.localhost" }, "assetProtocol": { "enable": true, @@ -50,13 +50,16 @@ "pubkey": "", "endpoints": [ "https://github.com/menloresearch/jan/releases/latest/download/latest.json" - ] + ], + "windows": { + "installMode": "passive" + } } }, "bundle": { "active": true, - "targets": "all", - "createUpdaterArtifacts": true, + "targets": ["nsis", "app", "dmg", "deb", "appimage"], + "createUpdaterArtifacts": false, "icon": [ "icons/32x32.png", "icons/128x128.png", @@ -69,6 +72,9 @@ "resources/themes/**/*", "resources/pre-install/**/*" ], - "externalBin": ["binaries/cortex-server"] + "externalBin": ["binaries/cortex-server"], + "windows": { + "signCommand": "powershell -ExecutionPolicy Bypass -File ./sign.ps1 %1" + } } }