aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/dinggerd/assets/pi/pi-agent-state.ts21
-rw-r--r--crates/dinggerd/src/hooks.rs2
-rwxr-xr-xtests/e2e.sh32
3 files changed, 37 insertions, 18 deletions
diff --git a/crates/dinggerd/assets/pi/pi-agent-state.ts b/crates/dinggerd/assets/pi/pi-agent-state.ts
index 49d4b9c..df9e4e2 100644
--- a/crates/dinggerd/assets/pi/pi-agent-state.ts
+++ b/crates/dinggerd/assets/pi/pi-agent-state.ts
@@ -3,29 +3,16 @@
// add custom hooks/plugins beside this file instead of editing it.
import net from "node:net";
-import path from "node:path";
-import { execSync } from "node:child_process";
// The dingger hook receiver listens here; override with DINGGER_AGENT_SOCKET.
const socketPath =
process.env.DINGGER_AGENT_SOCKET ||
`${process.env.HOME}/.local/state/dingger/agent.sock`;
-// The extension runs inside a tmux pane, so it finds its own pane id.
-function discoverPaneId(): string | undefined {
- try {
- const out = execSync('tmux display-message -p "#{pane_id}"', {
- encoding: "utf8",
- stdio: ["ignore", "pipe", "ignore"],
- });
- const paneId = out.trim();
- return paneId.startsWith("%") ? paneId : undefined;
- } catch {
- return undefined;
- }
-}
-
-const paneId = process.env.DINGGER_PANE_ID || discoverPaneId();
+// tmux sets TMUX_PANE in the environment of every process it starts in a
+// pane, so it names exactly the pane this pi runs in. (Asking tmux for "the
+// current pane" is wrong: that is the session's active pane, not ours.)
+const paneId = process.env.DINGGER_PANE_ID || process.env.TMUX_PANE;
const source = "dingger:pi";
function enabled() {
diff --git a/crates/dinggerd/src/hooks.rs b/crates/dinggerd/src/hooks.rs
index 40f0f20..524fb2d 100644
--- a/crates/dinggerd/src/hooks.rs
+++ b/crates/dinggerd/src/hooks.rs
@@ -124,7 +124,7 @@ fn handle_stream(stream: UnixStream) {
continue;
}
};
- debug!(pane = %params.pane_id, ?state, "hook report");
+ info!(pane = %params.pane_id, ?state, "hook report");
{
let mut reports = reports();
let pane = reports.entry(params.pane_id).or_default();
diff --git a/tests/e2e.sh b/tests/e2e.sh
index d74d73b..b63260c 100755
--- a/tests/e2e.sh
+++ b/tests/e2e.sh
@@ -239,6 +239,38 @@ else
fail "menu bar binary not found at $MENUBAR"
fi
+# --- 12. the shipped pi extension reports for its own pane -------------------
+echo "12. pi extension"
+cat >"$DIR/ext-harness.mjs" <<'JS'
+// Loads the shipped extension with a fake pi and fires lifecycle events.
+const ext = await import(process.env.EXTENSION);
+const on = {};
+ext.default({ on: (name, fn) => (on[name] = fn), events: { on: () => {} } });
+const ctx = { mode: "tui", isIdle: () => true };
+for (const event of process.argv.slice(2)) {
+ await on[event]?.({ type: event, reason: "reload" }, ctx);
+ await new Promise((r) => setTimeout(r, 300));
+}
+JS
+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" \
+ node --experimental-strip-types --no-warnings "$DIR/ext-harness.mjs" "$@"
+}
+if command -v node >/dev/null; then
+ # A2 is not the active pane of session a (wa1 is the active window), the
+ # case where asking tmux for "the current pane" picks the wrong pane.
+ [ "$(t display -p -t a: '#{pane_id}')" != "$A2" ] && pass "A2 is not session a's active pane" || fail "test setup: A2 is active"
+ before_a1=$(opt "$A1" @agent_state)
+ ext "$A2" session_start agent_start
+ expect "extension report lands on A2 (working)" "opt $A2 @agent_state" working
+ expect "A1 untouched" "opt $A1 @agent_state" "$before_a1"
+ ext "$A2" agent_settled
+ expect "extension completion away from the window: A2 done" "opt $A2 @agent_state" done
+else
+ fail "node not found; cannot test the pi extension"
+fi
+
echo
echo "$PASSES passed, $FAILS failed"
[ "$FAILS" -eq 0 ] || { echo "--- daemon log tail"; tail -30 "$DIR/daemon.log"; exit 1; }