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:
@@ -39,10 +39,10 @@ describe('GeminiCliHooksInstaller - event mapping', () => {
|
||||
expect(src).toContain("'SessionStart': 'context'");
|
||||
});
|
||||
|
||||
it('should map SessionEnd to session-complete (unchanged)', async () => {
|
||||
it('should not map SessionEnd (worker self-completes; /clear must not drain queue)', async () => {
|
||||
const { readFileSync } = await import('fs');
|
||||
const src = readFileSync('src/services/integrations/GeminiCliHooksInstaller.ts', 'utf-8');
|
||||
expect(src).toContain("'SessionEnd': 'session-complete'");
|
||||
expect(src).not.toContain("'SessionEnd':");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ describe('Hook Lifecycle - Event Handlers', () => {
|
||||
const { getEventHandler } = await import('../src/cli/handlers/index.js');
|
||||
const recognizedTypes = [
|
||||
'context', 'session-init', 'observation',
|
||||
'summarize', 'session-complete', 'user-message', 'file-edit'
|
||||
'summarize', 'user-message', 'file-edit'
|
||||
];
|
||||
for (const type of recognizedTypes) {
|
||||
const handler = getEventHandler(type);
|
||||
@@ -42,15 +42,6 @@ describe('Hook Lifecycle - Event Handlers', () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
it('should include session-complete as a recognized event type (#984)', async () => {
|
||||
const { getEventHandler } = await import('../src/cli/handlers/index.js');
|
||||
const handler = getEventHandler('session-complete');
|
||||
// session-complete should NOT be the no-op handler
|
||||
// We can verify this by checking it's not the same as an unknown type handler
|
||||
expect(handler).toBeDefined();
|
||||
// The real handler has different behavior than the no-op
|
||||
// (it tries to call the worker, while no-op just returns immediately)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user