From a91b93cfe84f927c27890d08aed4daa9a30e63ee Mon Sep 17 00:00:00 2001 From: Fu <1340468261@qq.com> Date: Sun, 31 May 2026 20:20:50 +0800 Subject: [PATCH] fix: remove premature session/end call from stop hook The agentStop hook (src/hooks/stop.ts) was calling /agentmemory/session/end on every assistant turn completion. In Claude Code CLI this fires after every response, causing sessions to be marked completed mid-conversation. Claude Code has a dedicated sessionEnd hook for true session exit; Codex does not. The session/end call was originally added as a Codex workaround (#579) but cannot be safely retained because we lack a reliable Codex identifier in the hook payload, and a blacklist guard would still incorrectly fire for Hermes and other agents without SessionEnd. Remove the call with a TODO comment documenting the Codex regression. Re-add once a reliable agent identifier is available. Fixes #745 Signed-off-by: Fu <1340468261@qq.com> --- plugin/scripts/stop.mjs | 6 ------ src/hooks/stop.ts | 17 +++++++++++------ test/copilot-plugin.test.ts | 12 ++++++++++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/plugin/scripts/stop.mjs b/plugin/scripts/stop.mjs index 03d30c64f..bf5b2e719 100755 --- a/plugin/scripts/stop.mjs +++ b/plugin/scripts/stop.mjs @@ -29,12 +29,6 @@ async function main() { body: JSON.stringify({ sessionId }), signal: AbortSignal.timeout(12e4) }).catch(() => {}); - fetch(`${REST_URL}/agentmemory/session/end`, { - method: "POST", - headers: authHeaders(), - body: JSON.stringify({ sessionId }), - signal: AbortSignal.timeout(5e3) - }).catch(() => {}); setTimeout(() => process.exit(0), 1500).unref(); } main(); diff --git a/src/hooks/stop.ts b/src/hooks/stop.ts index 4103796e0..8f8a9ffcd 100644 --- a/src/hooks/stop.ts +++ b/src/hooks/stop.ts @@ -46,12 +46,17 @@ async function main() { signal: AbortSignal.timeout(120000), }).catch(() => {}); - fetch(`${REST_URL}/agentmemory/session/end`, { - method: "POST", - headers: authHeaders(), - body: JSON.stringify({ sessionId }), - signal: AbortSignal.timeout(5000), - }).catch(() => {}); + // TODO(codex-session-end): Codex does not fire a separate SessionEnd event, + // so its Stop hook was the only signal to close the session lifecycle. + // We removed the /session/end call here because Claude Code (and other agents) + // fire Stop after every assistant turn, causing premature session completion. + // Re-add once a reliable Codex identifier is available in the hook payload. + // fetch(`${REST_URL}/agentmemory/session/end`, { + // method: "POST", + // headers: authHeaders(), + // body: JSON.stringify({ sessionId }), + // signal: AbortSignal.timeout(5000), + // }).catch(() => {}); setTimeout(() => process.exit(0), 1500).unref(); } diff --git a/test/copilot-plugin.test.ts b/test/copilot-plugin.test.ts index cd01b2d87..5fe04f022 100644 --- a/test/copilot-plugin.test.ts +++ b/test/copilot-plugin.test.ts @@ -377,4 +377,16 @@ describe("Copilot hook scripts", () => { }, }); }); + + it("stop calls /summarize but not /session/end", async () => { + const result = await runHook("scripts/stop.mjs", { + sessionId: "copilot-session", + cwd: "C:\\repo", + }); + + expect(result.stdout).toBe(""); + const paths = result.requests.map((r) => r.path); + expect(paths).toContain("/agentmemory/summarize"); + expect(paths).not.toContain("/agentmemory/session/end"); + }); });