fix(codex): defer session persistence until user activity

This commit is contained in:
weishu
2026-07-12 11:00:08 +08:00
parent 65e1708c78
commit 5a377e38b9
35 changed files with 2118 additions and 131 deletions
+22 -4
View File
@@ -1,5 +1,7 @@
import { request } from 'node:http';
export const SESSION_HOOK_FORWARD_TIMEOUT_MS = 1_000;
function logError(message: string, error?: unknown): void {
const detail = error instanceof Error ? error.message : (error ? String(error) : '');
const suffix = detail ? `: ${detail}` : '';
@@ -93,6 +95,13 @@ export async function runSessionHookForwarder(args: string[]): Promise<void> {
let hadError = false;
await new Promise<void>((resolve) => {
let settled = false;
let timedOut = false;
const finish = () => {
if (settled) return;
settled = true;
resolve();
};
const req = request({
host: '127.0.0.1',
port,
@@ -111,16 +120,25 @@ export async function runSessionHookForwarder(args: string[]): Promise<void> {
res.on('error', (error) => {
hadError = true;
logError('Error reading hook server response', error);
resolve();
finish();
});
res.on('end', () => resolve());
res.on('end', finish);
res.resume();
});
req.on('error', (error) => {
hadError = true;
logError('Failed to send hook request', error);
resolve();
if (!timedOut) {
logError('Failed to send hook request', error);
}
finish();
});
req.setTimeout(SESSION_HOOK_FORWARD_TIMEOUT_MS, () => {
timedOut = true;
hadError = true;
logError(`Hook request timed out after ${SESSION_HOOK_FORWARD_TIMEOUT_MS}ms`);
req.destroy();
finish();
});
req.end(body);
});
+7 -1
View File
@@ -107,7 +107,6 @@ export async function startHookServer(options: HookServerOptions): Promise<HookS
const sessionId = data.session_id || data.sessionId;
if (sessionId) {
logger.debug(`[hookServer] Session hook received session ID: ${sessionId}`);
onSessionHook(sessionId, data);
} else {
logger.debug('[hookServer] Session hook received but no session_id found in data');
res.writeHead(422, { 'Content-Type': 'text/plain' }).end('missing session_id');
@@ -117,6 +116,13 @@ export async function startHookServer(options: HookServerOptions): Promise<HookS
if (!res.headersSent && !res.writableEnded) {
res.writeHead(200, { 'Content-Type': 'text/plain' }).end('ok');
}
setImmediate(() => {
try {
onSessionHook(sessionId, data);
} catch (error) {
logger.debug('[hookServer] Error dispatching session hook:', error);
}
});
} catch (error) {
clearTimeout(timeout);
if (timedOut) {