aboutsummaryrefslogtreecommitdiff
path: root/tests/e2e.sh
diff options
context:
space:
mode:
authorIgor Soarez <igor@soarez.org>2026-10-30 17:27:21 +0200
committerIgor Soarez <igor@soarez.org>2026-10-30 17:27:21 +0200
commitb0cfd10b80443d3f67d263ff4db177bb53cc90ed (patch)
tree957951350434f38da83457f5467b6c000e892867 /tests/e2e.sh
parent91436536b69c10aa333c2b2978284b57cca3ed64 (diff)
reload pi agents on an old extension: versioned extension, control socket, menu item and reload-agents
Diffstat (limited to 'tests/e2e.sh')
-rwxr-xr-xtests/e2e.sh54
1 files changed, 49 insertions, 5 deletions
diff --git a/tests/e2e.sh b/tests/e2e.sh
index 4b60316..7f72e3c 100755
--- a/tests/e2e.sh
+++ b/tests/e2e.sh
@@ -30,6 +30,8 @@ PASSES=0
# Every dingger invocation below (daemon, focus, poke, menu bar) targets the
# isolated server and the test daemon's hook socket.
export DINGGER_TMUX_SOCKET="$SOCK" DINGGER_AGENT_SOCKET="$HOOK" DINGGER_STATE_DIR="$DIR/state"
+# The daemon updates an installed pi extension when it starts: not the user's.
+export PI_CODING_AGENT_DIR="$DIR/pi-agent"
t() { tmux -u -L "$SOCK" "$@"; }
@@ -38,7 +40,7 @@ cleanup() {
[ -n "${DAEMON2_PID:-}" ] && kill "$DAEMON2_PID" 2>/dev/null
t kill-server 2>/dev/null
tmux -L "$SOCK-restore-$$" kill-server 2>/dev/null
- rm -rf "$DIR"
+ if [ -n "${E2E_KEEP:-}" ]; then echo "kept $DIR"; else rm -rf "$DIR"; fi
}
trap cleanup EXIT
@@ -258,14 +260,14 @@ if [ -x "$MENUBAR" ]; then
expect "A1 done" "opt $A1 @agent_state" done
expect "menu title" "mb --print | head -1" "title: ×1 ✓1"
expect "menu rows: herdr priority; idle most recent first (C1 since its jump in step 4, B1 since the start)" \
- "mb --print | tail -n +2 | cut -f1,2 | tr '\t\n' '|;'" "× blocked|pi;✓ done|Deploy the widget;○ idle|pi;○ idle|Review PR 42;"
+ "mb --print | tail -n +2 | grep -v '^⟳' | cut -f1,2 | tr '\t\n' '|;'" "× blocked|pi;✓ done|Deploy the widget;○ idle|pi;○ idle|Review PR 42;"
# Wait for working: B1 was idle before, so idle alone would not show the turn.
hook "$B1" working
expect "B1 working" "opt $B1 @agent_state" working
hook "$B1" idle
expect "B1 finishes a turn while watched: idle" "opt $B1 @agent_state" idle
expect "and is now the most recent idle agent: listed first" \
- "mb --print | tail -n +2 | cut -f1,2 | tr '\t\n' '|;'" "× blocked|pi;✓ done|Deploy the widget;○ idle|Review PR 42;○ idle|pi;"
+ "mb --print | tail -n +2 | grep -v '^⟳' | cut -f1,2 | tr '\t\n' '|;'" "× blocked|pi;✓ done|Deploy the widget;○ idle|Review PR 42;○ idle|pi;"
expect "subtitle: location, harness, waiting time" "mb --print | grep 'Deploy the widget' | cut -f3" "a · wa1 · pi · done now"
expect "idle subtitle has no waiting time" "mb --print | grep 'Review PR 42' | cut -f3" "b · wb1 · pi"
mb --click "$A1"
@@ -319,9 +321,12 @@ for (const arg of process.argv.slice(2)) {
await new Promise((r) => setTimeout(r, 300));
}
JS
+# The extension as installed: stamped with its version.
+mkdir -p "$DIR/pi-harness"
+PI_CODING_AGENT_DIR="$DIR/pi-harness" "$DINGGER" install pi >/dev/null
ext() { # pane events... (run "inside" a pane: tmux sets TMUX_PANE there)
local pane=$1; shift
- TMUX_PANE="$pane" EXTENSION="$ROOT/crates/dinggerd/assets/pi/pi-agent-state.ts" \
+ TMUX_PANE="$pane" EXTENSION="$DIR/pi-harness/extensions/dingger-agent-state.ts" \
node --experimental-strip-types --no-warnings "$DIR/ext-harness.mjs" "$@"
}
if command -v node >/dev/null; then
@@ -981,13 +986,52 @@ if command -v node >/dev/null; then
: >"$EXTLOG"; iext "$U1" session_start "/unread"
expect "/unread marks it" "opt $U1 @agent_state" done
expect "and says so" "grep -c '^notify marked unread: dingger shows it as done until you come back to it$' $EXTLOG" 1
- look "$AWAY"; look "$U1"
+ # A held mark clears only once a tick sees the user away (a tick here
+ # takes ~0.3 s; two looks within one would never be seen apart).
+ look "$AWAY"; sleep 1; look "$U1"
expect "unr: seen again" "opt $U1 @agent_state" idle
: >"$EXTLOG"; iext "$U1" session_start agent_start "/unread"
expect "/unread while working is refused" "grep -c '^notify only an idle agent can be marked unread$' $EXTLOG" 1
expect "and changes nothing" "opt $U1 @agent_state" working
fi
+# --- 23. agents on an old extension ------------------------------------------
+# pi's extension reports its version and control socket; the daemon counts
+# the agents on another version, which the menu offers to reload. (The
+# reload itself, against a real pi: tests/pi-live.sh.)
+echo "23. agents on an old extension"
+ext_report() { # pane version control
+ python3 - "$HOOK" "$1" "$2" "$3" <<'PY'
+import json, socket, sys
+params = {"pane_id": sys.argv[2], "agent": "pi", "state": "idle", "extension": sys.argv[3], "control": sys.argv[4]}
+s = socket.socket(socket.AF_UNIX)
+s.connect(sys.argv[1])
+s.sendall((json.dumps({"method": "pane.report_agent", "params": params}) + "\n").encode())
+s.close()
+PY
+}
+mkdir -p "$DIR/pi-current"
+PI_CODING_AGENT_DIR="$DIR/pi-current" $DINGGER install pi >/dev/null
+CURRENT=$(grep -o 'extensionVersion = "[0-9a-f]*"' "$DIR/pi-current/extensions/dingger-agent-state.ts" | cut -d'"' -f2)
+t new-session -d -s ext -n e1 -c "$DIR" "$DIR/bin/pi"
+E1=$(t display -p -t ext:e1 '#{pane_id}')
+# The agents reported so far sent no version: an extension from before
+# versions, which only a /reload by hand updates.
+expect "ext: the others are by hand" "[ \"\$(gopt @dingger_outdated_by_hand)\" -gt 0 ] && echo yes" yes
+BY_HAND=$(gopt @dingger_outdated_by_hand)
+ext_report "$E1" 0000000000000000 "$DIR/pi-0.sock"
+expect "ext: the version is on the pane" "opt $E1 @dingger_extension" 0000000000000000
+expect "and its control socket" "opt $E1 @dingger_control" "$DIR/pi-0.sock"
+expect "another version: reloadable" "gopt @dingger_outdated" 1
+expect "the menu offers to reload it" "mb --print | grep '^⟳'" \
+ "$(printf '⟳ Reload 1 Agent on an Old Extension\teach when idle and off screen · %s more need /reload' "$BY_HAND")"
+expect "reload-agents refuses without the current extension installed" "$DINGGER reload-agents 2>&1 | grep -c 'run .dingger install pi. first'" 1
+ext_report "$E1" "$CURRENT" "$DIR/pi-1.sock"
+expect "the current version: not counted" "gopt @dingger_outdated" 0
+expect "the menu: only those by hand, not clickable" "mb --print | grep '^⟳'" \
+ "$(printf '⟳ %s Agents Need /reload\ttheir dingger extension is too old to reload them\t(disabled)' "$BY_HAND")"
+t kill-session -t ext
+
# Every daemon this run started must stop with it.
kill "$DAEMON_PID" "$DAEMON2_PID" 2>/dev/null
expect "the test daemons stop" "ps -o pid= -p $DAEMON_PID,$DAEMON2_PID | wc -l | tr -d ' '" 0