fix: stop draining queue on /clear (remove SessionEnd shim) (#2136)
* fix: stop draining queue on /clear (and on every other SessionEnd) The SessionEnd hook was wired to session-complete on Claude Code, Gemini CLI, the transcripts processor, the OpenCode plugin, and OpenClaw. All of those paths called POST /api/sessions/complete, which marked the session completed and abandoned every still-pending observation in the queue. So typing /clear (or logging out, or quitting) wiped in-flight work that the worker was perfectly happy to keep processing on its own. Removed the entire shim: - Deleted SessionEnd hook block in plugin/hooks/hooks.json - Deleted src/cli/handlers/session-complete.ts and its registry entry - Deleted POST /api/sessions/complete route + Zod schema in SessionRoutes - Removed call from transcripts processor handleSessionEnd - Removed call from opencode-plugin session.deleted handler - Removed Gemini SessionEnd → session-complete mapping - Removed openclaw scheduleSessionComplete + completionDelayMs + timer state - Updated tests + comments accordingly Explicit user-initiated deletion (DELETE /api/sessions/:id and POST /api/sessions/:sessionDbId/complete from the viewer UI) still works via SessionCompletionHandler.completeByDbId — that's the only path that should drain the queue. The worker self-completes via its SDK-agent generator's finally-block, so no external completion call is needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: clarify opencode-plugin session.deleted is in-memory cleanup only Greptile P2: file-level header still implied session.deleted called the worker. Now it only cleans up the local contentSessionIdsByOpenCodeSessionId map; worker self-completes via the SDK-agent generator finally-block. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -266,12 +266,6 @@ describe("Observation I/O event handlers", () => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.url === "/api/sessions/complete") {
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({ status: "completed" }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.url?.startsWith("/api/context/inject")) {
|
||||
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
|
||||
res.end("# Claude-Mem Context\n\n## Timeline\n- Session 1: Did some work");
|
||||
@@ -446,8 +440,7 @@ describe("Observation I/O event handlers", () => {
|
||||
assert.ok(summarizeRequest!.body.contentSessionId.startsWith("openclaw-summarize-test-"));
|
||||
|
||||
const completeRequest = receivedRequests.find((r) => r.url === "/api/sessions/complete");
|
||||
assert.ok(completeRequest, "should send complete to worker");
|
||||
assert.ok(completeRequest!.body.contentSessionId.startsWith("openclaw-summarize-test-"));
|
||||
assert.ok(!completeRequest, "should not send complete (worker self-completes)");
|
||||
});
|
||||
|
||||
it("agent_end extracts text from array content", async () => {
|
||||
|
||||
+3
-28
@@ -644,12 +644,7 @@ export default function claudeMemPlugin(api: OpenClawPluginApi): void {
|
||||
const sessionIds = new Map<string, string>();
|
||||
const canonicalSessionKeys = new Map<string, string>();
|
||||
const sessionAliasesByCanonicalKey = new Map<string, Set<string>>();
|
||||
const pendingCompletionTimers = new Map<string, ReturnType<typeof setTimeout>>();
|
||||
const recentPromptInits = new Map<string, number>();
|
||||
const completionDelayMs = (() => {
|
||||
const val = Number((userConfig as Record<string, unknown>).completionDelayMs);
|
||||
return Number.isFinite(val) ? Math.max(0, val) : 5000;
|
||||
})();
|
||||
const syncMemoryFile = userConfig.syncMemoryFile !== false; // default true
|
||||
const syncMemoryFileExclude = new Set(userConfig.syncMemoryFileExclude || []);
|
||||
|
||||
@@ -733,18 +728,6 @@ export default function claudeMemPlugin(api: OpenClawPluginApi): void {
|
||||
sessionIds.delete(canonicalKey);
|
||||
}
|
||||
|
||||
function scheduleSessionComplete(contentSessionId: string): void {
|
||||
const existingTimer = pendingCompletionTimers.get(contentSessionId);
|
||||
if (existingTimer) clearTimeout(existingTimer);
|
||||
const timer = setTimeout(() => {
|
||||
pendingCompletionTimers.delete(contentSessionId);
|
||||
workerPostFireAndForget(workerPort, "/api/sessions/complete", {
|
||||
contentSessionId,
|
||||
}, api.logger);
|
||||
}, completionDelayMs);
|
||||
pendingCompletionTimers.set(contentSessionId, timer);
|
||||
}
|
||||
|
||||
// TTL cache for context injection to avoid re-fetching on every LLM turn.
|
||||
// before_prompt_build fires on every turn; caching for 60s keeps the worker
|
||||
// load manageable while still picking up new observations reasonably quickly.
|
||||
@@ -898,7 +881,7 @@ export default function claudeMemPlugin(api: OpenClawPluginApi): void {
|
||||
});
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Event: agent_end — summarize and complete session
|
||||
// Event: agent_end — summarize session (worker self-completes)
|
||||
// ------------------------------------------------------------------
|
||||
api.on("agent_end", async (event, ctx) => {
|
||||
const { contentSessionId } = rememberSessionContext(ctx);
|
||||
@@ -922,16 +905,12 @@ export default function claudeMemPlugin(api: OpenClawPluginApi): void {
|
||||
}
|
||||
}
|
||||
|
||||
// Await summarize so the worker receives it before complete.
|
||||
// This also gives in-flight tool_result_persist observations time to arrive
|
||||
// (they use fire-and-forget and may still be in transit).
|
||||
// Send summarize. The worker self-completes the session when its SDK-agent
|
||||
// generator drains; no explicit complete call needed.
|
||||
await workerPost(workerPort, "/api/sessions/summarize", {
|
||||
contentSessionId,
|
||||
last_assistant_message: lastAssistantMessage,
|
||||
}, api.logger);
|
||||
|
||||
api.logger.info(`[claude-mem] Scheduling session complete in ${completionDelayMs}ms: ${contentSessionId}`);
|
||||
scheduleSessionComplete(contentSessionId);
|
||||
});
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@@ -952,10 +931,6 @@ export default function claudeMemPlugin(api: OpenClawPluginApi): void {
|
||||
recentPromptInits.clear();
|
||||
canonicalSessionKeys.clear();
|
||||
sessionAliasesByCanonicalKey.clear();
|
||||
for (const timer of pendingCompletionTimers.values()) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
pendingCompletionTimers.clear();
|
||||
api.logger.info("[claude-mem] Gateway started — session tracking reset");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user