aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJJ Liebig <jonathan.liebig@gmail.com>2026-09-12 15:52:18 +0400
committerGitHub <noreply@github.com>2026-09-12 13:52:18 +0200
commita5d5f6f654a32b27b2bd4dd8edd82f6795359269 (patch)
tree0b54a0fb4c1a136dff8224de617c8403756df19a /src
parentcc36a2943e85134768631d6d289e331c0edb940d (diff)
fix: ignore nested OMP session reports (#3994)
refs #2593
Diffstat (limited to 'src')
-rw-r--r--src/integration/assets/herdr-agent-state.test.ts28
-rw-r--r--src/integration/assets/omp/herdr-agent-state.ts8
-rw-r--r--src/integration/mod.rs2
-rw-r--r--src/pane.rs13
4 files changed, 48 insertions, 3 deletions
diff --git a/src/integration/assets/herdr-agent-state.test.ts b/src/integration/assets/herdr-agent-state.test.ts
index 48cc8708..19b36d94 100644
--- a/src/integration/assets/herdr-agent-state.test.ts
+++ b/src/integration/assets/herdr-agent-state.test.ts
@@ -11,6 +11,7 @@ const originalEnvironment = {
HERDR_OMP_IDLE_DEBOUNCE_MS: process.env.HERDR_OMP_IDLE_DEBOUNCE_MS,
HERDR_PANE_ID: process.env.HERDR_PANE_ID,
HERDR_SOCKET_PATH: process.env.HERDR_SOCKET_PATH,
+ OMPCODE: process.env.OMPCODE,
};
let server: Server | undefined;
@@ -229,6 +230,33 @@ for (const integration of integrations) {
});
}
+test("OMP ignores nested sessions launched inside another OMP shell", async () => {
+ const requests = await startRecordingServer("omp-nested");
+ process.env.OMPCODE = "1";
+ const { handlers, pi } = createExtensionHarness();
+
+ const { default: install } = await importFresh("./omp/herdr-agent-state.ts");
+ install(pi);
+
+ // OMP sets OMPCODE on every shell it spawns. A nested `omp` inherits it and
+ // must not claim the pane's session for its short-lived conversation.
+ expect(handlers.size).toBe(0);
+ await handlers.get("session_start")?.(
+ { reason: "startup" },
+ {
+ hasUI: true,
+ isIdle: () => true,
+ sessionManager: {
+ getSessionFile: () => "/tmp/omp-nested.jsonl",
+ getSessionId: () => "omp-nested",
+ },
+ },
+ );
+ await Bun.sleep(25);
+
+ expect(requests).toEqual([]);
+});
+
test("OMP accepts POSIX and Windows session paths", async () => {
const { isAbsoluteSessionPath } = await importFresh("./omp/herdr-agent-state.ts");
diff --git a/src/integration/assets/omp/herdr-agent-state.ts b/src/integration/assets/omp/herdr-agent-state.ts
index 0e493787..fce62106 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=9
+// HERDR_INTEGRATION_VERSION=10
// @ts-nocheck
import net from "node:net";
@@ -14,9 +14,13 @@ const socketEndpoint =
process.platform === "win32" && socketPath ? `\\\\.\\pipe\\${socketPath}` : socketPath;
const paneId = process.env.HERDR_PANE_ID;
const source = "herdr:omp";
+// OMP marks every shell it spawns with OMPCODE=1. A nested `omp` launched from
+// a parent session's shell inherits it, so that process is not the pane's root
+// agent and must not report its short-lived session over the parent's.
+const nestedOmpSession = process.env.OMPCODE === "1";
function enabled() {
- return HERDR_ENV === "1" && !!socketPath && !!paneId;
+ return HERDR_ENV === "1" && !!socketPath && !!paneId && !nestedOmpSession;
}
let requestQueue = Promise.resolve();
diff --git a/src/integration/mod.rs b/src/integration/mod.rs
index d956c7bc..49808ca2 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 = 9;
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 = 9;
+const OMP_INTEGRATION_VERSION: u32 = 10;
const CLAUDE_HOOK_INSTALL_NAME: &str = if cfg!(windows) {
"herdr-agent-state.ps1"
} else {
diff --git a/src/pane.rs b/src/pane.rs
index 0ba411d0..c56cfbb3 100644
--- a/src/pane.rs
+++ b/src/pane.rs
@@ -147,6 +147,9 @@ impl PaneLaunchEnv {
fn apply_pane_launch_env(cmd: &mut CommandBuilder, launch_env: &PaneLaunchEnv) {
cmd.env_remove("CODEX_THREAD_ID");
+ // OMP sets OMPCODE for shells it spawns. A pane launched from inside OMP
+ // must not inherit it or its root agent would look like a nested session.
+ cmd.env_remove("OMPCODE");
for (key, value) in &launch_env.extra {
cmd.env(key, value);
}
@@ -3558,6 +3561,16 @@ mod tests {
}
#[test]
+ fn pane_launch_env_removes_outer_ompcode_marker() {
+ let mut cmd = CommandBuilder::new("shell");
+ cmd.env("OMPCODE", "1");
+
+ apply_pane_launch_env(&mut cmd, &PaneLaunchEnv::default());
+
+ assert!(cmd.get_env("OMPCODE").is_none());
+ }
+
+ #[test]
fn pane_terminal_identity_removes_outer_windows_terminal_session() {
let mut cmd = CommandBuilder::new("shell");
cmd.env("WT_SESSION", "outer-session");