aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/e2e.sh29
-rwxr-xr-xtests/pi-live.sh31
2 files changed, 56 insertions, 4 deletions
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