diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-28 12:58:42 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-28 12:58:42 +0200 |
| commit | 183dfe3ae34418653aca3d20628b3938c8348c2a (patch) | |
| tree | c40b09c65d0ee0aa390cbb34a634f0b98c07febc | |
| parent | c873e3ca7b51ce159cbfac5f9635d67e542c4c0a (diff) | |
| download | desktop-assistant-183dfe3ae34418653aca3d20628b3938c8348c2a.tar.gz desktop-assistant-183dfe3ae34418653aca3d20628b3938c8348c2a.zip | |
Replace restart.sh with assistant.sh start|stop|restart|status
start leaves a running assistant or overlay alone and starts only what
is missing; restart is the old restart.sh. status lists each process
with its uptime, memory and children, a stray arecord left by a dead
assistant, the socket, the presentation/gaming pause flags and the
log's last lines, and exits 1 if either process is down.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | AGENTS.md | 6 | ||||
| -rw-r--r-- | README.md | 5 | ||||
| -rwxr-xr-x | assistant.sh | 94 | ||||
| -rwxr-xr-x | restart.sh | 50 |
4 files changed, 101 insertions, 54 deletions
@@ -16,7 +16,7 @@ built-in settings. Examples in `examples/`. STT, LLM and TTS stay local; only the weather and search tools reach the network, and only when a question needs them. Spec: `docs/superpowers/specs/2026-09-26-tools-and-config-design.md`. -Run: `python3 assistant.py` (`--test` for the self-check), or `./restart.sh` +Run: `python3 assistant.py` (`--test` for the self-check), or `./assistant.sh restart` to replace a running one (and its overlay) detached from the terminal. --- @@ -542,8 +542,8 @@ pending. Parses the 2.1 MB ChangeLog in ~95 ms, so no announcement. in `MD_EDITOR` (typora in the user's config), detached. - Live: counts, security fixes and "kernel 7.2.7" spoken, then it offered the recap on its own; "si" opened it (2.2 s). -- The overlay did not show after `restart.sh` started it together with the - assistant: quickshell's `Socket` never retries a failed connect. Fixed in +- The overlay did not show after `restart.sh` (now `assistant.sh`) + started it together with the assistant: quickshell's `Socket` never retries a failed connect. Fixed in the quickshell repo (fresh `Socket` per retry), which also covers login, where the overlay starts first. @@ -44,7 +44,10 @@ Paths, the card name, ports and voices can be changed in `config.toml`, see ```sh python3 assistant.py # run python3 assistant.py --test # self-check -./restart.sh # stop a running one, start detached +./assistant.sh start # detached, with the overlay +./assistant.sh stop +./assistant.sh restart # stop a running one, start again +./assistant.sh status ``` ## Configuration and tools diff --git a/assistant.sh b/assistant.sh new file mode 100755 index 0000000..e288afd --- /dev/null +++ b/assistant.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# desktop-assistant: start, stop, restart or check the voice loop. +# Copyright (C) 2026 Danilo M. <danix@danix.xyz> +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# assistant.sh start|stop|restart|status +# +# stop: SIGTERM any running assistant.py (whisper-server and amixer die +# with it through PDEATHSIG), SIGKILL after 10 s; same for the quickshell +# overlay (OVERLAY, default the quickshell repo next to this one). +# start: run both in their own session, detached from the terminal, +# logging where the Hyprland autostart does; does nothing for one already +# running. restart: stop, then start. status: processes, children, stray +# recorders, socket, pause flags and the log's tail; exit 1 if either is +# down. Run it from the login session: it needs its +# audio, bus, Wayland display and XDG_RUNTIME_DIR. + +set -eu + +dir=$(cd "$(dirname "$0")" && pwd) +log="${XDG_RUNTIME_DIR:?not in a login session}/desktop-assistant.log" +overlay=$(realpath -m "${OVERLAY:-$dir/../quickshell/assistant}") +pat='^\S*python3 (-u )?\S*assistant\.py' +qpat="^qs -p $overlay\$" + +kill_wait() { + pkill -u "$USER" -f "$1" || return 0 + for _ in $(seq 50); do + pgrep -u "$USER" -f "$1" >/dev/null || return 0 + sleep 0.2 + done + pkill -KILL -u "$USER" -f "$1" && sleep 0.5 || true +} + +running() { pgrep -u "$USER" -f "$1" >/dev/null; } + +stop() { + kill_wait "$pat" + kill_wait "$qpat" +} + +start() { + cd "$dir" + running "$pat" || setsid -f python3 -u "$dir/assistant.py" >>"$log" 2>&1 </dev/null + running "$qpat" || setsid -f qs -p "$overlay" >/dev/null 2>&1 </dev/null + sleep 0.5 + status +} + +show() { + local pid + pid=$(pgrep -u "$USER" -of "$2") || { echo "$1: not running"; return 1; } + echo "$1: running" + ps -o pid=,etime=,rss=,args= -p "$pid" | + awk '{ printf " pid %s, up %s, %d MB\n %s", $1, $2, $3 / 1024, $4 + for (i = 5; i <= NF; i++) printf " %s", $i; print "" }' + [ "$1" = assistant ] || return 0 + pgrep -a -P "$pid" | sed 's/^/ child /' +} + +status() { + local rc=0 f + show assistant "$pat" || rc=1 + show overlay "$qpat" || rc=1 + # Children get PDEATHSIG; one left over means the assistant died under it. + pgrep -u "$USER" -af "^arecord .*desktop-assistant\.raw" | sed 's/^/stray: /' || true + [ -S "$XDG_RUNTIME_DIR/desktop-assistant.sock" ] && echo "socket: present" || echo "socket: missing" + for f in presentation gaming; do + [ "$(cat "$XDG_RUNTIME_DIR/status.$f" 2>/dev/null)" = 1 ] && echo "paused: $f mode on" + done + echo "log: $log" + tail -n 5 "$log" 2>/dev/null | sed 's/^/ /' + return $rc +} + +case "${1:-}" in + start) start ;; + stop) stop ;; + restart) stop; start ;; + status) status ;; + *) echo "usage: $0 start|stop|restart|status" >&2; exit 2 ;; +esac diff --git a/restart.sh b/restart.sh deleted file mode 100755 index 24dd5ea..0000000 --- a/restart.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# desktop-assistant: restart the voice loop, detached from the terminal. -# Copyright (C) 2026 Danilo M. <danix@danix.xyz> -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# restart.sh: SIGTERM any running assistant.py (whisper-server and amixer -# die with it through PDEATHSIG), SIGKILL after 10 s, then start a new one -# in its own session, logging where the Hyprland autostart does. The -# quickshell overlay (OVERLAY, default the quickshell repo next to this one) -# is restarted the same way. Run it from the login session: it needs its -# audio, bus, Wayland display and XDG_RUNTIME_DIR. - -set -eu - -dir=$(cd "$(dirname "$0")" && pwd) -log="${XDG_RUNTIME_DIR:?not in a login session}/desktop-assistant.log" -overlay=$(realpath -m "${OVERLAY:-$dir/../quickshell/assistant}") -pat='^\S*python3 (-u )?\S*assistant\.py' -qpat="^qs -p $overlay\$" - -stop() { - pkill -u "$USER" -f "$1" || return 0 - for _ in $(seq 50); do - pgrep -u "$USER" -f "$1" >/dev/null || return 0 - sleep 0.2 - done - pkill -KILL -u "$USER" -f "$1" && sleep 0.5 || true -} - -stop "$pat" -stop "$qpat" - -cd "$dir" -setsid -f python3 -u "$dir/assistant.py" >>"$log" 2>&1 </dev/null -setsid -f qs -p "$overlay" >/dev/null 2>&1 </dev/null -sleep 0.5 -pgrep -u "$USER" -af "$pat" || { echo "assistant not running, see $log" >&2; exit 1; } -pgrep -u "$USER" -af "$qpat" || { echo "overlay not running: qs -p $overlay" >&2; exit 1; } |
