fix: keep omp panes working through scheduled continuations (#3122)

refs #2851
This commit is contained in:
caner-akca
2026-08-23 02:19:22 +03:00
committed by GitHub
parent 20a500a7f3
commit 2bbb7c9172
4 changed files with 47 additions and 2 deletions
+1
View File
@@ -8,6 +8,7 @@
### Fixed
- New lifecycle event subscriptions now stream only events emitted after subscription begins instead of replaying retained history. (#1270)
- Windows users whose endpoint security blocks the fileless PowerShell install command can now use a local `install.cmd` bootstrap; installer downloads use `curl.exe` while preserving package checksum verification. (#2751)
- Oh My Pi panes now stay working when a turn ends with an automatic continuation already scheduled, instead of briefly reporting idle and completing `agent wait` early. (#2851, thanks @taoeffect)
- Retained mouse selections now copy when Ctrl+C or Cmd+C arrives before a delayed mouse release instead of forwarding the copy shortcut to the pane. (#3100, thanks @moret)
- Removing a background worktree workspace no longer changes focus to its parent workspace. (#3098)
- Prefix bindings such as `prefix+|` now recognize characters produced by macOS Option and custom keyboard layouts, while exact chords such as `prefix+alt+w` keep priority. (#3079, thanks @vlcinsky)
@@ -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");
@@ -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;
+1 -1
View File
@@ -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 {