Download sidecar on first launch instead of bundling
Major refactor: sidecar is no longer bundled in the installer. Instead,
it's downloaded on first launch with a setup screen offering CPU vs CUDA
choice. This solves the 2GB+ installer size limit and decouples app/sidecar.
Backend:
- New commands: check_sidecar, download_sidecar, check_sidecar_update
- Streaming download with progress events via reqwest
- Added reqwest + futures-util dependencies
- Removed sidecar.zip from bundle resources
- Restored NSIS target (no longer size-constrained)
CI:
- Each platform builds both CPU and CUDA sidecar variants (except macOS: CPU only)
- Sidecar zips uploaded as separate release assets
- Asset naming: sidecar-{os}-{arch}-{variant}.zip
Frontend:
- SidecarSetup.svelte: first-launch setup with CPU/CUDA radio choice,
progress bar, error/retry handling
- Update banner on launch if newer sidecar version available
- Conditional rendering: setup screen → main app flow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -112,13 +112,23 @@ jobs:
|
||||
- name: Set up Python
|
||||
run: uv python install ${{ env.PYTHON_VERSION }}
|
||||
|
||||
- name: Build sidecar
|
||||
- name: Build sidecar (CUDA)
|
||||
working-directory: python
|
||||
run: uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --with-cuda
|
||||
|
||||
- name: Package sidecar for Tauri
|
||||
- name: Package sidecar (CUDA)
|
||||
run: |
|
||||
cd python/dist/voice-to-notes-sidecar && zip -r ../../../src-tauri/sidecar.zip .
|
||||
cd python/dist/voice-to-notes-sidecar && zip -r ../../../sidecar-linux-x86_64-cuda.zip .
|
||||
|
||||
- name: Build sidecar (CPU)
|
||||
working-directory: python
|
||||
run: |
|
||||
rm -rf dist/voice-to-notes-sidecar
|
||||
uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --cpu-only
|
||||
|
||||
- name: Package sidecar (CPU)
|
||||
run: |
|
||||
cd python/dist/voice-to-notes-sidecar && zip -r ../../../sidecar-linux-x86_64-cpu.zip .
|
||||
|
||||
# ── Tauri app ──
|
||||
- name: Set up Node.js
|
||||
@@ -183,6 +193,26 @@ jobs:
|
||||
echo "Upload response: HTTP ${HTTP_CODE}"
|
||||
done
|
||||
|
||||
for file in sidecar-*.zip; do
|
||||
filename=$(basename "$file")
|
||||
encoded_name=$(echo "$filename" | sed 's/ /%20/g')
|
||||
echo "Uploading ${filename} ($(du -h "$file" | cut -f1))..."
|
||||
|
||||
ASSET_ID=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \
|
||||
"${REPO_API}/releases/${RELEASE_ID}/assets" | jq -r ".[] | select(.name == \"${filename}\") | .id // empty")
|
||||
if [ -n "${ASSET_ID}" ]; then
|
||||
curl -s -X DELETE -H "Authorization: token ${BUILD_TOKEN}" \
|
||||
"${REPO_API}/releases/${RELEASE_ID}/assets/${ASSET_ID}"
|
||||
fi
|
||||
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
|
||||
-H "Authorization: token ${BUILD_TOKEN}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
-T "$file" \
|
||||
"${REPO_API}/releases/${RELEASE_ID}/assets?name=${encoded_name}")
|
||||
echo "Upload response: HTTP ${HTTP_CODE}"
|
||||
done
|
||||
|
||||
build-windows:
|
||||
name: Build (Windows)
|
||||
needs: bump-version
|
||||
@@ -214,19 +244,34 @@ jobs:
|
||||
shell: powershell
|
||||
run: uv python install ${{ env.PYTHON_VERSION }}
|
||||
|
||||
- name: Build sidecar
|
||||
- name: Install 7-Zip
|
||||
shell: powershell
|
||||
run: |
|
||||
if (-not (Get-Command 7z -ErrorAction SilentlyContinue)) {
|
||||
choco install 7zip -y
|
||||
}
|
||||
|
||||
- name: Build sidecar (CUDA)
|
||||
shell: powershell
|
||||
working-directory: python
|
||||
run: uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --with-cuda
|
||||
|
||||
- name: Package sidecar for Tauri
|
||||
- name: Package sidecar (CUDA)
|
||||
shell: powershell
|
||||
run: |
|
||||
# Compress-Archive has a 2GB limit; use 7z for CUDA builds
|
||||
if (-not (Get-Command 7z -ErrorAction SilentlyContinue)) {
|
||||
choco install 7zip -y
|
||||
}
|
||||
7z a -tzip -mx=5 src-tauri\sidecar.zip .\python\dist\voice-to-notes-sidecar\*
|
||||
7z a -tzip -mx=5 sidecar-windows-x86_64-cuda.zip .\python\dist\voice-to-notes-sidecar\*
|
||||
|
||||
- name: Build sidecar (CPU)
|
||||
shell: powershell
|
||||
working-directory: python
|
||||
run: |
|
||||
Remove-Item -Recurse -Force dist\voice-to-notes-sidecar
|
||||
uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --cpu-only
|
||||
|
||||
- name: Package sidecar (CPU)
|
||||
shell: powershell
|
||||
run: |
|
||||
7z a -tzip -mx=5 sidecar-windows-x86_64-cpu.zip .\python\dist\voice-to-notes-sidecar\*
|
||||
|
||||
# ── Tauri app ──
|
||||
- name: Set up Node.js
|
||||
@@ -299,6 +344,34 @@ jobs:
|
||||
}
|
||||
}
|
||||
|
||||
Get-ChildItem -Path . -Filter "sidecar-*.zip" | ForEach-Object {
|
||||
$filename = $_.Name
|
||||
$encodedName = [System.Uri]::EscapeDataString($filename)
|
||||
$size = [math]::Round($_.Length / 1MB, 1)
|
||||
Write-Host "Uploading ${filename} (${size} MB)..."
|
||||
|
||||
try {
|
||||
$assets = Invoke-RestMethod -Uri "${REPO_API}/releases/${RELEASE_ID}/assets" -Headers $Headers
|
||||
$existing = $assets | Where-Object { $_.name -eq $filename }
|
||||
if ($existing) {
|
||||
Invoke-RestMethod -Uri "${REPO_API}/releases/${RELEASE_ID}/assets/$($existing.id)" -Method Delete -Headers $Headers
|
||||
}
|
||||
} catch {}
|
||||
|
||||
$uploadUrl = "${REPO_API}/releases/${RELEASE_ID}/assets?name=${encodedName}"
|
||||
$result = curl.exe --fail --silent --show-error `
|
||||
-X POST `
|
||||
-H "Authorization: token $env:BUILD_TOKEN" `
|
||||
-H "Content-Type: application/octet-stream" `
|
||||
-T "$($_.FullName)" `
|
||||
"$uploadUrl" 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "Upload successful: ${filename}"
|
||||
} else {
|
||||
Write-Host "WARNING: Upload failed for ${filename}: ${result}"
|
||||
}
|
||||
}
|
||||
|
||||
build-macos:
|
||||
name: Build (macOS)
|
||||
needs: bump-version
|
||||
@@ -327,13 +400,13 @@ jobs:
|
||||
- name: Set up Python
|
||||
run: uv python install ${{ env.PYTHON_VERSION }}
|
||||
|
||||
- name: Build sidecar
|
||||
- name: Build sidecar (CPU)
|
||||
working-directory: python
|
||||
run: uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --cpu-only
|
||||
|
||||
- name: Package sidecar for Tauri
|
||||
- name: Package sidecar (CPU)
|
||||
run: |
|
||||
cd python/dist/voice-to-notes-sidecar && zip -r ../../../src-tauri/sidecar.zip .
|
||||
cd python/dist/voice-to-notes-sidecar && zip -r ../../../sidecar-macos-aarch64-cpu.zip .
|
||||
|
||||
# ── Tauri app ──
|
||||
- name: Set up Node.js
|
||||
@@ -397,3 +470,23 @@ jobs:
|
||||
"${REPO_API}/releases/${RELEASE_ID}/assets?name=${encoded_name}")
|
||||
echo "Upload response: HTTP ${HTTP_CODE}"
|
||||
done
|
||||
|
||||
for file in sidecar-*.zip; do
|
||||
filename=$(basename "$file")
|
||||
encoded_name=$(echo "$filename" | sed 's/ /%20/g')
|
||||
echo "Uploading ${filename} ($(du -h "$file" | cut -f1))..."
|
||||
|
||||
ASSET_ID=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \
|
||||
"${REPO_API}/releases/${RELEASE_ID}/assets" | jq -r ".[] | select(.name == \"${filename}\") | .id // empty")
|
||||
if [ -n "${ASSET_ID}" ]; then
|
||||
curl -s -X DELETE -H "Authorization: token ${BUILD_TOKEN}" \
|
||||
"${REPO_API}/releases/${RELEASE_ID}/assets/${ASSET_ID}"
|
||||
fi
|
||||
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
|
||||
-H "Authorization: token ${BUILD_TOKEN}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
-T "$file" \
|
||||
"${REPO_API}/releases/${RELEASE_ID}/assets?name=${encoded_name}")
|
||||
echo "Upload response: HTTP ${HTTP_CODE}"
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user