diff options
| author | Rhys <105699450+rhjoh@users.noreply.github.com> | 2026-08-03 10:44:44 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-03 03:44:44 +0300 |
| commit | 5eab32da81b403c2a277222ab97417a8bf90c35f (patch) | |
| tree | 73cfbad865e949e48ea93b4bd58d482b2806e447 /src | |
| parent | 10eb0bc744165ae91dfce9fd731fe170410b34ec (diff) | |
fix(pi): restrict state reporting to tui sessions (#2159)
Co-authored-by: Can Celik <ogulcancelik@gmail.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/integration/assets/herdr-agent-state.test.ts | 25 | ||||
| -rw-r--r-- | src/integration/assets/pi/herdr-agent-state.ts | 6 | ||||
| -rw-r--r-- | src/integration/mod.rs | 2 | ||||
| -rw-r--r-- | src/integration/tests.rs | 2 |
4 files changed, 31 insertions, 4 deletions
diff --git a/src/integration/assets/herdr-agent-state.test.ts b/src/integration/assets/herdr-agent-state.test.ts index f54332ce..94081e6d 100644 --- a/src/integration/assets/herdr-agent-state.test.ts +++ b/src/integration/assets/herdr-agent-state.test.ts @@ -171,6 +171,7 @@ for (const integration of integrations) { { reason: "startup" }, { hasUI: true, + mode: "tui", isIdle: () => true, sessionManager: { getSessionFile: () => undefined, @@ -197,6 +198,7 @@ for (const integration of integrations) { { reason: "reload" }, { hasUI: true, + mode: "tui", isIdle: () => false, sessionManager: { getSessionFile: () => undefined, @@ -268,6 +270,25 @@ test("Pi reports idle only after the agent settles", async () => { expect(requestStates(requests)).toEqual(["idle", "working", "idle"]); }); +test("Pi ignores RPC sessions even when UI APIs are available", async () => { + const requests = await startRecordingServer("pi-rpc"); + const { handlers, pi } = createExtensionHarness(); + const { default: install } = await importFresh("./pi/herdr-agent-state.ts"); + install(pi); + + const context = { + ...piContext(() => true), + hasUI: true, + mode: "rpc", + }; + await handlers.get("session_start")?.({ reason: "startup" }, context); + handlers.get("agent_start")?.({}, context); + handlers.get("agent_settled")?.({}, context); + await Bun.sleep(25); + + expect(requests).toEqual([]); +}); + test("Pi settlement preserves explicit blocked-state precedence", async () => { const requests = await startRecordingServer("pi-settled-blocked"); const { eventHandlers, handlers, pi } = createExtensionHarness(); @@ -307,6 +328,7 @@ test("Pi reports the session replacement source", async () => { { reason: "new" }, { hasUI: true, + mode: "tui", isIdle: () => true, sessionManager: { getSessionFile: () => "/tmp/pi-new.jsonl", @@ -370,6 +392,7 @@ test("Pi waits for a replacement session report before publishing state", async { reason: "new" }, { hasUI: true, + mode: "tui", isIdle: () => false, sessionManager: { getSessionFile: () => "/tmp/pi-new.jsonl", @@ -489,6 +512,7 @@ test("Pi retries working state after an unanswered socket attempt", async () => { reason: "startup" }, { hasUI: true, + mode: "tui", isIdle: () => false, sessionManager: { getSessionFile: () => undefined, @@ -524,6 +548,7 @@ function completionHandlers(handlers: Map<string, Handler>): string[] { function piContext(isIdle: () => boolean) { return { hasUI: true, + mode: "tui", isIdle, sessionManager: { getSessionFile: () => undefined, diff --git a/src/integration/assets/pi/herdr-agent-state.ts b/src/integration/assets/pi/herdr-agent-state.ts index 2e79c7c6..67bc4188 100644 --- a/src/integration/assets/pi/herdr-agent-state.ts +++ b/src/integration/assets/pi/herdr-agent-state.ts @@ -2,7 +2,7 @@ // managed by herdr; reinstalling or updating the integration overwrites this file. // add custom hooks/plugins beside this file instead of editing it. // HERDR_INTEGRATION_ID=pi -// HERDR_INTEGRATION_VERSION=7 +// HERDR_INTEGRATION_VERSION=8 // @ts-nocheck import net from "node:net"; @@ -223,7 +223,9 @@ export default function (pi) { }); pi.on("session_start", async (event, ctx) => { - if (ctx?.hasUI !== true) { + // TUI only: RPC/JSON/print modes are headless (no PTY herdr can display), + // and RPC still reports hasUI=true, so mode is the reliable gate. + if (ctx?.mode !== "tui") { return; } rootSession = true; diff --git a/src/integration/mod.rs b/src/integration/mod.rs index 9fc1886e..8be54c84 100644 --- a/src/integration/mod.rs +++ b/src/integration/mod.rs @@ -23,7 +23,7 @@ pub(crate) use types::{IntegrationRecommendation, IntegrationStatus, Integration const PI_EXTENSION_INSTALL_NAME: &str = "herdr-agent-state.ts"; const PI_EXTENSION_ASSET: &str = include_str!("assets/pi/herdr-agent-state.ts"); -const PI_INTEGRATION_VERSION: u32 = 7; +const PI_INTEGRATION_VERSION: u32 = 8; const OMP_EXTENSION_INSTALL_NAME: &str = "herdr-omp-agent-state.ts"; const OMP_EXTENSION_ASSET: &str = include_str!("assets/omp/herdr-agent-state.ts"); const OMP_INTEGRATION_VERSION: u32 = 8; diff --git a/src/integration/tests.rs b/src/integration/tests.rs index 7abf7be2..6827dae7 100644 --- a/src/integration/tests.rs +++ b/src/integration/tests.rs @@ -2665,7 +2665,7 @@ fn bundled_integration_asset_versions_match_expected_versions() { fn bundled_integration_assets_report_session_refs() { assert!(PI_EXTENSION_ASSET.contains("agent_session_path")); assert!(PI_EXTENSION_ASSET.contains("agent_session_id")); - assert!(PI_EXTENSION_ASSET.contains("ctx?.hasUI !== true")); + assert!(PI_EXTENSION_ASSET.contains("ctx?.mode !== \"tui\"")); assert!(PI_EXTENSION_ASSET.contains("pane.report_agent_session")); assert!(PI_EXTENSION_ASSET.contains("pane.report_agent\"")); assert!(PI_EXTENSION_ASSET.contains("pi.on(\"agent_start\"")); |
