fix(event): respect tmux integration disabled state in event forwarding

🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2026-04-05 13:27:50 +09:00
parent c9c7b75269
commit 07ccbd2047
2 changed files with 133 additions and 15 deletions
+114 -2
View File
@@ -452,7 +452,16 @@ describe("createEventHandler - event forwarding", () => {
const forwardedEvents: EventInput[] = [] const forwardedEvents: EventInput[] = []
const eventHandler = createEventHandler({ const eventHandler = createEventHandler({
ctx: asEventHandlerContext({}), ctx: asEventHandlerContext({}),
pluginConfig: asPluginConfig({}), pluginConfig: asPluginConfig({
tmux: {
enabled: true,
layout: "main-vertical",
main_pane_size: 60,
main_pane_min_width: 120,
agent_pane_min_width: 40,
isolation: "inline",
},
}),
firstMessageVariantGate: { firstMessageVariantGate: {
markSessionCreated: () => {}, markSessionCreated: () => {},
clear: () => {}, clear: () => {},
@@ -485,6 +494,100 @@ describe("createEventHandler - event forwarding", () => {
expect(forwardedEvents[0]?.event.type).toBe("message.part.delta") expect(forwardedEvents[0]?.event.type).toBe("message.part.delta")
}) })
it("does not forward tmux activity events when tmux integration is disabled", async () => {
//#given
const forwardedEvents: EventInput[] = []
const eventHandler = createEventHandler({
ctx: asEventHandlerContext({}),
pluginConfig: asPluginConfig({
tmux: {
enabled: false,
layout: "main-vertical",
main_pane_size: 60,
main_pane_min_width: 120,
agent_pane_min_width: 40,
isolation: "inline",
},
}),
firstMessageVariantGate: {
markSessionCreated: () => {},
clear: () => {},
},
managers: createEventHandlerManagers({
skillMcpManager: {
disconnectSession: async () => {},
},
tmuxSessionManager: {
onEvent: (event: EventInput["event"]) => {
forwardedEvents.push({ event })
},
onSessionCreated: async () => {},
onSessionDeleted: async () => {},
},
}),
hooks: createEventHandlerHooks({}),
})
//#when
await eventHandler(asEventHandlerInput({
event: {
type: "message.part.delta",
properties: { sessionID: "ses_tmux_disabled", field: "text", delta: "x" },
},
}))
//#then
expect(forwardedEvents).toHaveLength(0)
})
it("does not forward session.created to tmux session manager when tmux integration is disabled", async () => {
//#given
const createdSessions: string[] = []
const eventHandler = createEventHandler({
ctx: asEventHandlerContext({}),
pluginConfig: asPluginConfig({
tmux: {
enabled: false,
layout: "main-vertical",
main_pane_size: 60,
main_pane_min_width: 120,
agent_pane_min_width: 40,
isolation: "inline",
},
}),
firstMessageVariantGate: {
markSessionCreated: () => {},
clear: () => {},
},
managers: createEventHandlerManagers({
skillMcpManager: {
disconnectSession: async () => {},
},
tmuxSessionManager: {
onSessionCreated: async (event: { properties?: { info?: { id?: string } } }) => {
const sessionId = event.properties?.info?.id
if (sessionId) {
createdSessions.push(sessionId)
}
},
onSessionDeleted: async () => {},
},
}),
hooks: createEventHandlerHooks({}),
})
//#when
await eventHandler(asEventHandlerInput({
event: {
type: "session.created",
properties: { info: { id: "ses_tmux_disabled", parentID: "ses_parent" } },
},
}))
//#then
expect(createdSessions).toHaveLength(0)
})
it("forwards session.deleted to write-existing-file-guard hook", async () => { it("forwards session.deleted to write-existing-file-guard hook", async () => {
//#given //#given
const forwardedEvents: EventInput[] = [] const forwardedEvents: EventInput[] = []
@@ -492,7 +595,16 @@ describe("createEventHandler - event forwarding", () => {
const deletedSessions: string[] = [] const deletedSessions: string[] = []
const eventHandler = createEventHandler({ const eventHandler = createEventHandler({
ctx: {} as never, ctx: {} as never,
pluginConfig: {} as never, pluginConfig: asPluginConfig({
tmux: {
enabled: true,
layout: "main-vertical",
main_pane_size: 60,
main_pane_min_width: 120,
agent_pane_min_width: 40,
isolation: "inline",
},
}),
firstMessageVariantGate: { firstMessageVariantGate: {
markSessionCreated: () => {}, markSessionCreated: () => {},
clear: () => {}, clear: () => {},
+19 -13
View File
@@ -36,6 +36,7 @@ import { lspManager } from "../tools";
import type { CreatedHooks } from "../create-hooks"; import type { CreatedHooks } from "../create-hooks";
import type { Managers } from "../create-managers"; import type { Managers } from "../create-managers";
import { isTmuxIntegrationEnabled } from "../create-runtime-tmux-config";
import { pruneRecentSyntheticIdles } from "./recent-synthetic-idles"; import { pruneRecentSyntheticIdles } from "./recent-synthetic-idles";
import { normalizeSessionStatusToIdle } from "./session-status-normalizer"; import { normalizeSessionStatusToIdle } from "./session-status-normalizer";
@@ -138,7 +139,8 @@ export function createEventHandler(args: {
managers: Managers; managers: Managers;
hooks: CreatedHooks; hooks: CreatedHooks;
}): (input: EventInput) => Promise<void> { }): (input: EventInput) => Promise<void> {
const { ctx, firstMessageVariantGate, managers, hooks } = args; const { ctx, pluginConfig, firstMessageVariantGate, managers, hooks } = args;
const tmuxIntegrationEnabled = isTmuxIntegrationEnabled(pluginConfig)
const pluginContext = ctx as { const pluginContext = ctx as {
directory: string; directory: string;
client: { client: {
@@ -344,7 +346,7 @@ export function createEventHandler(args: {
const { event } = input; const { event } = input;
const props = event.properties as Record<string, unknown> | undefined; const props = event.properties as Record<string, unknown> | undefined;
if (TMUX_ACTIVITY_EVENT_TYPES.has(event.type)) { if (tmuxIntegrationEnabled && TMUX_ACTIVITY_EVENT_TYPES.has(event.type)) {
managers.tmuxSessionManager.onEvent?.(event as { type: string; properties?: Record<string, unknown> }); managers.tmuxSessionManager.onEvent?.(event as { type: string; properties?: Record<string, unknown> });
} }
@@ -357,14 +359,16 @@ export function createEventHandler(args: {
firstMessageVariantGate.markSessionCreated(sessionInfo); firstMessageVariantGate.markSessionCreated(sessionInfo);
await managers.tmuxSessionManager.onSessionCreated( if (tmuxIntegrationEnabled) {
event as { await managers.tmuxSessionManager.onSessionCreated(
type: string; event as {
properties?: { type: string;
info?: { id?: string; parentID?: string; title?: string }; properties?: {
}; info?: { id?: string; parentID?: string; title?: string };
}, };
); },
);
}
} }
if (event.type === "session.deleted") { if (event.type === "session.deleted") {
@@ -394,9 +398,11 @@ export function createEventHandler(args: {
deleteSessionTools(sessionInfo.id); deleteSessionTools(sessionInfo.id);
await managers.skillMcpManager.disconnectSession(sessionInfo.id); await managers.skillMcpManager.disconnectSession(sessionInfo.id);
await lspManager.cleanupTempDirectoryClients(); await lspManager.cleanupTempDirectoryClients();
await managers.tmuxSessionManager.onSessionDeleted({ if (tmuxIntegrationEnabled) {
sessionID: sessionInfo.id, await managers.tmuxSessionManager.onSessionDeleted({
}); sessionID: sessionInfo.id,
});
}
} }
} }