Package Superwhisper with upstream beta tracking (#854)
* Package Superwhisper with upstream beta tracking * Seed fresh Superwhisper shortcuts before daemon startup * Refresh checksum for Superwhisper user setup * Fix Superwhisper panel setup and packaging review findings * Read shell replies when retrying Superwhisper panel setup * Exclude Superwhisper portable menu integration
This commit is contained in:
1 parent
e285432795
commit
7d2c7c50af
11 files changed
+422
No files matched your search
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"source": "local",
|
||||
"release_ring": "fast",
|
||||
"min_release_age": "24h",
|
||||
"upstream": {
|
||||
"watch": {
|
||||
"github": "superultrainc/superwhisper-linux-releases",
|
||||
"allow_prerelease": true,
|
||||
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)-beta\\.(?P<beta>[0-9]+)",
|
||||
"version": "{version}beta{beta}",
|
||||
"variables": {
|
||||
"_version": "{version}-beta.{beta}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
# Maintainer: Omarchy <https://omarchy.org>
|
||||
|
||||
pkgname=superwhisper-bin
|
||||
pkgver=0.1.0beta15
|
||||
_version=0.1.0-beta.15
|
||||
pkgrel=1
|
||||
pkgdesc='Local and cloud voice dictation with Superwhisper'
|
||||
arch=('x86_64')
|
||||
url='https://superwhisper.com'
|
||||
license=('LicenseRef-proprietary' 'MIT')
|
||||
provides=('superwhisper')
|
||||
conflicts=('superwhisper')
|
||||
depends=('glibc' 'libgcc' 'libstdc++' 'libgomp' 'xdg-utils' 'python' 'python-gobject' 'python-cairo' 'gtk4'
|
||||
'gtk4-layer-shell' 'at-spi2-core' 'pipewire-pulse' 'libnotify'
|
||||
'wl-clipboard' 'ffmpeg' 'vulkan-icd-loader' 'librsvg' 'fontconfig'
|
||||
'hicolor-icon-theme' 'foot')
|
||||
optdepends=('fcitx5: insert dictation directly through the input method'
|
||||
'vulkan-intel: local processing on Intel GPUs'
|
||||
'vulkan-radeon: local processing on AMD GPUs')
|
||||
makedepends=('minisign')
|
||||
options=('!debug' '!strip')
|
||||
_release="https://tux.superwhisper.com/x86_64/v$_version/superwhisper-omarchy-x86_64-$_version.tar.zst"
|
||||
source=("superwhisper-$pkgver.tar.zst::$_release"
|
||||
"superwhisper-$pkgver.tar.zst.minisig::$_release.minisig"
|
||||
'linux-release.pub'
|
||||
'superwhisper'
|
||||
'superwhisper.service'
|
||||
'superwhisper.desktop'
|
||||
'superwhisper-url.desktop'
|
||||
'setup-user')
|
||||
noextract=("superwhisper-$pkgver.tar.zst")
|
||||
sha256sums=('99e44cbeb60c44945d2713144f12d0a356b1dfb98ed5702b5468fb6b47ae49c0'
|
||||
'4d933540a9299f5f7835d1f6494ce3facad866c477cdf0e82bf3e9ae5813325d'
|
||||
'0672b5230ed6390f9168eaea009c6ce1e8838f0961a87888d9073d1e1db5267d'
|
||||
'54a0fd574f2b123af24031e910fe0dc47be1d4c055ee5df775f1c681e6201c93'
|
||||
'8b9a2cb81a6ea015d663c9981ba67edafe934eb0e56904fab5030fbbfdd8506b'
|
||||
'c65169c8432223f26b072c8defe9ff65ef82c26be34cd92a9617ed112cb22570'
|
||||
'e67978d239e12a386ec335346b14e10cc7e3bed8b9b1d4bcbed4377f10d4695a'
|
||||
'ffbf2f42e403fca85eb73810742397884fbf949b715ed33cb98f618f33556c16')
|
||||
|
||||
prepare() {
|
||||
minisign -Vm "superwhisper-$pkgver.tar.zst" -x "superwhisper-$pkgver.tar.zst.minisig" -p linux-release.pub
|
||||
bsdtar -xf "superwhisper-$pkgver.tar.zst"
|
||||
local bundle="superwhisper-omarchy-x86_64-$_version"
|
||||
[[ $(< "$bundle/VERSION") == "$_version" ]] || return 1
|
||||
# Qt 6.12 adds a Color type that shadows Omarchy's palette singleton.
|
||||
python - "superwhisper-omarchy-x86_64-$_version/app/assets/omarchy-plugin/superwhisper-panel" <<'PYTHON'
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
|
||||
for path in Path(sys.argv[1]).glob("*.qml"):
|
||||
original = path.read_text()
|
||||
updated = re.sub(r"(?<![\w.])Color\b", "Commons.Color", original)
|
||||
if updated != original:
|
||||
alias = r"(?m)^import qs\.Commons(?: [0-9.]+)? as Commons[ \t]*$"
|
||||
if not re.search(alias, updated):
|
||||
updated, imports = re.subn(r"(?m)^(import qs\.Commons(?: [0-9.]+)?[ \t]*)$", r"\1\nimport qs.Commons as Commons", updated, count=1)
|
||||
if imports != 1:
|
||||
raise SystemExit(f"Cannot qualify palette import in {path}")
|
||||
if len(re.findall(alias, updated)) != 1 or re.search(r"(?<![\w.])Color\b", updated):
|
||||
raise SystemExit(f"Invalid palette references in {path}")
|
||||
path.write_text(updated)
|
||||
PYTHON
|
||||
}
|
||||
|
||||
package() {
|
||||
local bundle="superwhisper-omarchy-x86_64-$_version"
|
||||
install -dm755 "$pkgdir/opt/superwhisper"
|
||||
cp -a --no-preserve=ownership "$bundle/app/." "$pkgdir/opt/superwhisper/"
|
||||
# Omarchy owns its Dictation menu; omit the portable installer's menu writer.
|
||||
rm -f "$pkgdir/opt/superwhisper/scripts/omarchy-menu-rows.py"
|
||||
install -Dm755 superwhisper "$pkgdir/usr/bin/superwhisper"
|
||||
install -Dm644 superwhisper.service "$pkgdir/usr/lib/systemd/user/superwhisper.service"
|
||||
install -Dm644 superwhisper.desktop "$pkgdir/usr/share/applications/superwhisper.desktop"
|
||||
install -Dm644 superwhisper-url.desktop "$pkgdir/usr/share/applications/superwhisper-url.desktop"
|
||||
install -Dm755 setup-user "$pkgdir/usr/share/superwhisper/setup-user"
|
||||
install -Dm644 -t "$pkgdir/usr/share/licenses/$pkgname/" "$bundle"/licenses/*
|
||||
install -Dm644 "$bundle/README.md" "$pkgdir/usr/share/doc/$pkgname/README.md"
|
||||
install -Dm644 "$bundle/app/assets/linux-status/SuperwhisperTUI.ttf" "$pkgdir/usr/share/fonts/superwhisper/SuperwhisperTUI.ttf"
|
||||
for size in 16 32 64 128 256 512 1024; do
|
||||
install -Dm644 "$bundle/app/assets/app-icon/$size.png" "$pkgdir/usr/share/icons/hicolor/${size}x${size}/apps/superwhisper.png"
|
||||
done
|
||||
install -dm755 "$pkgdir/usr/share/fcitx5/addon"
|
||||
sed 's|@LIBRARY@|/opt/superwhisper/lib/fcitx5/libsuperwhisper-fcitx5|' \
|
||||
"$bundle/app/assets/fcitx5/superwhisper.conf.in" > "$pkgdir/usr/share/fcitx5/addon/superwhisper.conf"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# Superwhisper
|
||||
|
||||
Packages the vendor's signed portable x86_64 Linux archive under `/opt/superwhisper`, with a launcher, desktop entries, user service, fonts, icons and the fcitx5 text-commit addon. Local models are downloaded through Superwhisper's settings; they are not bundled in the package.
|
||||
|
||||
`sync-upstream` follows beta releases from `superultrainc/superwhisper-linux-releases`, normalizing `0.1.0-beta.15` to the Arch version `0.1.0beta15` while retaining the vendor version in `_version`. The stable feed has not been published yet. The recipe verifies the archive's SHA256 and Minisign signature against the checked-in vendor release key. Packaging never runs the downloaded installer.
|
||||
|
||||
Omarchy's Setup → Defaults → Dictation → Superwhisper invokes `/usr/share/superwhisper/setup-user`, then configures its shortcuts and saves Superwhisper as the default backend. The package does not add Omarchy menu extensions and omits the portable installer’s menu-writing helper. User setup enables the packaged service, links the vendor's panel and agent skill, and retires known portable-install wrappers and unit overrides with backups. Preferences, history and downloaded models are retained. Package updates come from OPR; the portable install's private update timer is disabled.
|
||||
|
||||
Omarchy loads the selected backend's generated `~/.config/superwhisper/shortcuts.lua` bridge itself, so no Superwhisper block is required in the user's Hyprland files. The bridge retains cancellation and correction-based vocabulary learning alongside Omarchy's shared dictation commands.
|
||||
|
||||
The launcher redirects the vendor’s generated Hyprland include to a private, unloaded file for both the daemon and CLI. User setup waits for daemon readiness. The portable updater is disabled and refused by the packaged launcher. The archive is verified before extraction, its version is checked, and the bundled panel uses explicit Omarchy palette references for Qt 6.12.
|
||||
|
||||
Fresh profiles start with Alt+Space toggle, no native hold, and Escape cancellation before the daemon starts, avoiding a conflict with Omarchy’s Right Alt binding. Existing preferences remain unchanged.
|
||||
|
||||
Panel discovery is asynchronous: user setup retries placement, leaves a pending marker if the shell is unavailable, and retries on the next setup without moving an already placed panel. Bundled component license notices are installed under `/usr/share/licenses/superwhisper-bin/`.
|
||||
@@ -0,0 +1,2 @@
|
||||
untrusted comment: minisign public key BC524820AE37B966
|
||||
RWRmuTeuIEhSvCYQejUR+zzMNsfxAn7pr9iOZ2ZJ9U1/zJwfsqvhzATB
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
backup_suffix=".before-opr.$(date +%s%N)"
|
||||
|
||||
# Retire the portable install's wrappers and unit overrides. Keep its versioned
|
||||
# binaries, preferences, history and models so the change is reversible.
|
||||
launcher="$HOME/.local/bin/superwhisper"
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
if [[ -f $launcher && ! -L $launcher ]] && grep -Fq 'superwhisper/app/current/run.sh' "$launcher"; then
|
||||
mv "$launcher" "$launcher$backup_suffix"
|
||||
ln -s /usr/bin/superwhisper "$launcher"
|
||||
fi
|
||||
if [[ ! -e $launcher && ! -L $launcher ]]; then
|
||||
ln -s /usr/bin/superwhisper "$launcher"
|
||||
fi
|
||||
current="$data_home/superwhisper/app/current"
|
||||
if [[ -L $current && $(readlink "$current") != "/opt/superwhisper" ]]; then
|
||||
mv "$current" "$current$backup_suffix"
|
||||
ln -s /opt/superwhisper "$current"
|
||||
elif [[ ! -e $current && ! -L $current ]]; then
|
||||
mkdir -p "${current%/*}"
|
||||
ln -s /opt/superwhisper "$current"
|
||||
fi
|
||||
unit="$config_home/systemd/user/superwhisper.service"
|
||||
if [[ -f $unit ]] && grep -Fq 'ExecStart=%h/.local/bin/superwhisper daemon' "$unit"; then
|
||||
mv "$unit" "$unit$backup_suffix"
|
||||
fi
|
||||
systemctl --user disable --now superwhisper-update.timer 2>/dev/null || true
|
||||
# Seed a fresh profile before the daemon starts. Its upstream Right Alt hold
|
||||
# conflicts with Omarchy's own bindings and prevents sequential CLI changes.
|
||||
preferences="$config_home/superwhisper/preferences.json"
|
||||
if [[ ! -e $preferences ]]; then
|
||||
mkdir -p "${preferences%/*}"
|
||||
(
|
||||
umask 077
|
||||
printf '%s\n' '{"toggleRecordingShortcut":"Alt+Space","pushToTalkShortcut":"","cancelRecordingShortcut":"Escape"}' > "$preferences"
|
||||
)
|
||||
fi
|
||||
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now superwhisper.service
|
||||
systemctl --user restart superwhisper.service
|
||||
|
||||
ready=false
|
||||
for (( attempt = 0; attempt < 50; attempt++ )); do
|
||||
if superwhisper status >/dev/null 2>&1; then
|
||||
ready=true
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
if [[ $ready != "true" ]]; then
|
||||
echo "Superwhisper did not become ready. Check systemctl --user status superwhisper.service." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
xdg-mime default superwhisper-url.desktop x-scheme-handler/superwhisper
|
||||
|
||||
# Link the vendor's panel and agent guide to the packaged payload. They update
|
||||
# with pacman; no copy of the application or private updater is installed.
|
||||
plugins="$config_home/omarchy/plugins"
|
||||
panel_pending="$config_home/superwhisper/omarchy-panel.pending"
|
||||
if [[ ! -e $plugins/superwhisper-panel && ! -L $plugins/superwhisper-panel ]]; then
|
||||
touch "$panel_pending"
|
||||
fi
|
||||
mkdir -p "$plugins" "$HOME/.agents/skills"
|
||||
ln -sfn /opt/superwhisper/assets/omarchy-plugin/superwhisper-panel "$plugins/superwhisper-panel"
|
||||
ln -sfn /opt/superwhisper/assets/agent-skill/superwhisper "$HOME/.agents/skills/superwhisper"
|
||||
for agent in .claude .codex .pi/agent; do
|
||||
if [[ -d $HOME/$agent ]]; then
|
||||
mkdir -p "$HOME/$agent/skills"
|
||||
ln -sfn /opt/superwhisper/assets/agent-skill/superwhisper "$HOME/$agent/skills/superwhisper"
|
||||
fi
|
||||
done
|
||||
omarchy-shell -q shell rescanPlugins
|
||||
if [[ -f $panel_pending ]]; then
|
||||
for (( attempt = 0; attempt < 50; attempt++ )); do
|
||||
placement=$(omarchy-shell shell putBarWidget superwhisper.panel '{"section":"right"}' 2>/dev/null) || placement=""
|
||||
if [[ $placement == "ok" ]]; then
|
||||
rm "$panel_pending"
|
||||
break
|
||||
elif [[ -z $placement ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
if [[ -f $panel_pending ]]; then
|
||||
echo "Superwhisper is ready; panel setup will retry next time setup-user runs." >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# A running input method discovers the packaged text-commit addon on restart.
|
||||
if systemctl --user -q is-active omarchy-fcitx5.service; then
|
||||
systemctl --user restart omarchy-fcitx5.service
|
||||
fi
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Omarchy loads shortcuts.lua from its selected backend, so the vendor's
|
||||
# generated Hyprland block must live in a file Hyprland does not load.
|
||||
export SUPERWHISPER_HYPR_BINDINGS="${XDG_CONFIG_HOME:-$HOME/.config}/superwhisper/hypr-block.lua"
|
||||
mkdir -p "${SUPERWHISPER_HYPR_BINDINGS%/*}"
|
||||
if [[ ! -e $SUPERWHISPER_HYPR_BINDINGS ]]; then
|
||||
install -m600 /dev/null "$SUPERWHISPER_HYPR_BINDINGS"
|
||||
fi
|
||||
|
||||
if [[ ${1:-} == "update" ]]; then
|
||||
echo "Superwhisper is updated through Omarchy's package repository." >&2
|
||||
exit 1
|
||||
fi
|
||||
exec /opt/superwhisper/run.sh "$@"
|
||||
@@ -0,0 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Superwhisper License Activation
|
||||
Exec=superwhisper open-url %u
|
||||
Icon=superwhisper
|
||||
Terminal=false
|
||||
NoDisplay=true
|
||||
MimeType=x-scheme-handler/superwhisper;
|
||||
@@ -0,0 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Superwhisper
|
||||
Comment=Local and cloud voice dictation
|
||||
Exec=foot --app-id=com.superwhisper.settings --title=Superwhisper --font="JetBrainsMono Nerd Font,Superwhisper TUI:size=12" env SW_TUI_LOGO=font superwhisper settings
|
||||
Icon=superwhisper
|
||||
Terminal=false
|
||||
Categories=Utility;Accessibility;
|
||||
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Superwhisper dictation
|
||||
After=graphical-session.target pipewire.service
|
||||
PartOf=graphical-session.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/superwhisper daemon
|
||||
ExecStopPost=/usr/bin/superwhisper playback-restore
|
||||
Restart=on-failure
|
||||
RestartSec=2
|
||||
KillMode=control-group
|
||||
TimeoutStopSec=15
|
||||
UMask=0077
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical-session.target
|
||||
Reference in new issue
Block a user