aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/integration/assets/herdr-agent-state.test.ts39
-rw-r--r--src/integration/assets/omp/herdr-agent-state.ts7
-rw-r--r--src/integration/mod.rs2
3 files changed, 46 insertions, 2 deletions
diff --git a/src/integration/assets/herdr-agent-state.test.ts b/src/integration/assets/herdr-agent-state.test.ts
index 94081e6d..2a86f0ca 100644
--- a/src/integration/assets/herdr-agent-state.test.ts
+++ b/src/integration/assets/herdr-agent-state.test.ts
@@ -498,6 +498,45 @@ test("Oh My Pi retries working before a queued idle state", async () => {
expect(requestState(attemptedRequests[2])).toBe("idle");
});
+test("Oh My Pi keeps working when a turn ends with a scheduled continuation", async () => {
+ const requests = await startRecordingServer("omp-will-continue");
+ process.env.HERDR_OMP_IDLE_DEBOUNCE_MS = "0";
+ const { handlers, pi } = createExtensionHarness();
+
+ const { default: install } = await importFresh("./omp/herdr-agent-state.ts");
+ install(pi);
+
+ let idle = true;
+ const context = {
+ hasUI: true,
+ isIdle: () => idle,
+ sessionManager: {
+ getSessionFile: () => undefined,
+ getSessionId: () => undefined,
+ },
+ };
+
+ handlers.get("session_start")?.({ reason: "startup" }, context);
+ await waitFor(() => requestStates(requests).length === 1);
+
+ idle = false;
+ handlers.get("agent_start")?.({}, context);
+ await waitFor(() => requestStates(requests).length === 2);
+ expect(requestStates(requests)).toEqual(["idle", "working"]);
+
+ // OMP already scheduled an automatic continuation, so this loop end is not a
+ // user-visible settle and must not publish idle. See issue #2851.
+ handlers.get("agent_end")?.({ messages: [], willContinue: true }, context);
+ await Bun.sleep(50);
+ expect(requestStates(requests)).toEqual(["idle", "working"]);
+
+ // The real terminal end still settles the pane.
+ idle = true;
+ handlers.get("agent_end")?.({ messages: [] }, context);
+ await waitFor(() => requestStates(requests).length === 3);
+ expect(requestStates(requests)).toEqual(["idle", "working", "idle"]);
+});
+
test("Pi retries working state after an unanswered socket attempt", async () => {
const { attemptedRequests, deliveredRequests, connectionCount } =
await startDroppedFirstResponseServer("pi-retry");
diff --git a/src/integration/assets/omp/herdr-agent-state.ts b/src/integration/assets/omp/herdr-agent-state.ts
index 88f804aa..0e493787 100644
--- a/src/integration/assets/omp/herdr-agent-state.ts
+++ b/src/integration/assets/omp/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=omp
-// HERDR_INTEGRATION_VERSION=8
+// HERDR_INTEGRATION_VERSION=9
// @ts-nocheck
import net from "node:net";
@@ -442,6 +442,11 @@ export default function (pi) {
// cancel the retry hold and publish a false Idle.
return;
}
+ if (event?.willContinue === true) {
+ // A continuation is already scheduled, so this end is not a settle.
+ // Older builds omit the field and fall through as before.
+ return;
+ }
agentActive = false;
diff --git a/src/integration/mod.rs b/src/integration/mod.rs
index c87ccac6..33bb163d 100644
--- a/src/integration/mod.rs
+++ b/src/integration/mod.rs
@@ -27,7 +27,7 @@ const PI_EXTENSION_ASSET: &str = include_str!("assets/pi/herdr-agent-state.ts");
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;
+const OMP_INTEGRATION_VERSION: u32 = 9;
const CLAUDE_HOOK_INSTALL_NAME: &str = if cfg!(windows) {
"herdr-agent-state.ps1"
} else {