From 3b7b7ed091bae3b0609c38b2d445201cc4b7a026 Mon Sep 17 00:00:00 2001 From: Igor Soarez Date: Thu, 5 Nov 2026 13:12:08 +0200 Subject: pi: a dialog during a run is blocked, and a cancelled run is idle, not done --- tests/e2e.sh | 29 +++++++++++++++++++++++++++++ tests/pi-live.sh | 31 +++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/e2e.sh b/tests/e2e.sh index b1709bc..52367d2 100755 --- a/tests/e2e.sh +++ b/tests/e2e.sh @@ -1178,6 +1178,35 @@ expect "the agent exits" "$DINGGER poke; opt $X1 @agent" "" 80 expect "its context goes with it" "opt $X1 @dingger_context" "" 50 t kill-session -t ctx +# --- 27. a cancelled run is not done ------------------------------------------ +echo "27. cancelled runs" +abort_report() { # pane + python3 - "$HOOK" "$1" <<'PY' +import json, socket, sys +params = {"pane_id": sys.argv[2], "agent": "pi", "state": "idle", "aborted": True} +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 +} +t new-session -d -s can -n c1 -c "$DIR" "$DIR/bin/pi" +t new-window -d -t can: -n c2 -c "$DIR" "$DIR/bin/pi" +K1=$(t display -p -t can:c1 '#{pane_id}'); K2=$(t display -p -t can:c2 '#{pane_id}') +report "$K1" working ""; report "$K2" working "" +expect "both working" "opt $K1 @agent_state; opt $K2 @agent_state" "working +working" 50 +sleep 3.5; : >"$SOUNDS"; : >"$NOTES" +# Nobody watches either: one finishes, the other is cancelled. +report "$K1" idle ""; abort_report "$K2" +expect "finished: done" "opt $K1 @agent_state" done 50 +expect "cancelled: idle" "opt $K2 @agent_state" idle 50 +expect "the finished one notifies" "grep -c 'pi finished|can:c1 (pi)' $NOTES" 1 60 +expect "the cancelled one does not" "grep -c 'can:c2' $NOTES" 0 +expect "one sound, the finished one's" "cat $SOUNDS" done +expect "the menu lists it idle" "mb --print | grep -F 'can · c2' | cut -f1" "○ idle" +t kill-session -t can + # 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 diff --git a/tests/pi-live.sh b/tests/pi-live.sh index 8e01e74..53115ec 100755 --- a/tests/pi-live.sh +++ b/tests/pi-live.sh @@ -63,6 +63,10 @@ export default function (pi) { pi.registerCommand("block", { description: "test: emit blocked", handler: async () => { pi.events.emit("blocked", { active: true, label: "test block" }); } }); pi.registerCommand("unblock", { description: "test: clear blocked", handler: async () => { pi.events.emit("blocked", { active: false }); } }); pi.registerCommand("ask", { description: "test: a confirm dialog", handler: async (_args, ctx) => { await ctx.ui.confirm("Test dialog", "Proceed?"); } }); + // A dialog during a run, the way an extension asks before it goes on. + let askDuring = false; + pi.on("input", (event) => { askDuring = /ask during the run/.test(event.text); }); + pi.on("turn_start", async (_event, ctx) => { if (askDuring) { askDuring = false; await ctx.ui.confirm("Go on?", "A question during the run"); } }); } EOF mkdir -p "$D/bin" "$D/work" "$D/work2" @@ -121,11 +125,28 @@ type_line agent "/block" expect "an extension's blocked event: blocked" "st agent" blocked 50 type_line agent "/unblock" expect "cleared: back to done" "st agent" done 50 +# A dialog opened while idle comes from what you just did: nothing changes. +BEFORE=$(st agent) type_line agent "/ask" -sleep 1.5 -note "during a pi confirm dialog dingger shows: $(st agent) (pi gives extensions no dialog event)" +expect "a dialog opened while idle: on screen" "t capture-pane -p -t main:agent | grep -c 'Test dialog'" 1 30 +sleep 1 +expect "changes nothing" "st agent" "$BEFORE" t send-keys -t main:agent Escape sleep 0.5 +# A dialog during a run: the agent waits on you. +type_line agent "slow 3 ask during the run" +expect "a dialog during a run: blocked" "st agent" blocked 50 +expect "on screen" "t capture-pane -p -t main:agent | grep -c 'Go on?'" 1 30 +t send-keys -t main:agent Enter +expect "answered: working again" "st agent" working 30 +expect "then done" "st agent" done 80 +# A run cancelled (Escape) while nobody watches: idle, not done. +type_line agent "slow 8 cancel me" +expect "a run to cancel: working" "st agent" working 50 +t send-keys -t main:agent Escape +expect "cancelled: idle, not done" "st agent" idle 50 +sleep 1.5 +expect "and stays idle" "st agent" idle type_line agent "/importance high" expect "/importance high: the pane option" "t show -pv -t main:agent @dingger_importance 2>/dev/null" high 50 expect "pi says so" "t capture-pane -p -t main:agent | grep -c 'importance: high'" 1 30 @@ -204,7 +225,8 @@ expect "and done" "st agent" done 60 expect "a message sent is no draft" "draft" "" 30 expect "nor kept" "[ -e \"\$(draft_file)\" ] && echo left || echo gone" gone 30 # What it cost: pi prices each reply; dingger counts them. -replies() { grep -c '"role":"assistant"' "$1"; } +# Priced replies: a cancelled run's reply is not. +replies() { grep '"role":"assistant"' "$1" | grep -vc '"stopReason":"aborted"'; } SESSION_FILE=$(t show -pv -t main:agent @agent_session) N=$(replies "$SESSION_FILE") [ "$N" -ge 3 ] && pass "$N replies so far" || fail "only $N replies" @@ -278,7 +300,8 @@ expect "the layout becomes the restore candidate" "python3 -c 'import json,sys; expect "restore resumes it by its session file" "grep -c -- \"resume .*pi --session\" $D/restore.out" 1 expect "resumed 1 of 1 agents" "grep -c '^resumed 1 of 1 agents' $D/restore.out" 1 expect "it runs again, reporting the same session" "t show -pv -t main:agent @agent_session 2>/dev/null" "$SESSION" 150 -expect "with its conversation" "t capture-pane -p -t main:agent -S - | grep -c 'slow 3 hello'" 1 50 +# Its last message: the first may have scrolled off a long conversation. +expect "with its conversation" "t capture-pane -p -t main:agent -S - | grep -c 'slow 1 after\$'" 1 50 expect "and its importance" "t show -pv -t main:agent @dingger_importance 2>/dev/null" high 50 expect "and its draft, back in the input box" "t capture-pane -p -t main:agent | grep -c '^an unsent idea;'" 1 50 expect "reported again" "t show -pv -t main:agent @dingger_draft 2>/dev/null" "an unsent idea;" 30 -- cgit v1.2.3