mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 07:29:42 +02:00
fix: don't discard codex/gemini/antigravity conversations on Resume; fix DELETE ownership dup + missing broadcast
resumeHistorySession() creates the resumed row in its own mode via a modeConfigKey map (opencode/pi/grok/omp -> continueSession, deepseek -> resumeSession) and retires the old row afterward. codex, gemini and antigravity were missing from that map, so resuming one of their rows started a brand-new session with NO continuation while still deleting the row it came from -- silent data loss dressed as the duplicate-row fix. Gate row retirement on continuesSomething (true only for modes that actually got a continuation config) instead of wiring an unverified sessionId->native-conversation-id assumption for the three affected CLIs. DELETE /api/sessions/:id reimplemented the ownership 404 check inline in two places instead of going through findSessionOrFail, and its persisted-only-session branch never broadcast session:deleted, so other open tabs kept the retired row until their next unrelated fetch. Extract the shared 404 into sessionNotFoundError(), add findPersistedSessionOrFail() alongside findSessionOrFail() in route-helpers.ts (same ownership contract, returns a SessionState instead of a live Session), and use both from the route instead of inline checks. Add the missing broadcast.
This commit is contained in:
@@ -67,6 +67,7 @@ import {
|
||||
autoConfigureRalph,
|
||||
canAccessOwned,
|
||||
CASES_DIR,
|
||||
findPersistedSessionOrFail,
|
||||
findSessionOrFail,
|
||||
getAuthUser,
|
||||
isAdmin,
|
||||
@@ -1191,25 +1192,19 @@ export function registerSessionRoutes(
|
||||
// rather than 404ing: the caller means "make this row go away", and a
|
||||
// stale duplicate row is exactly what's left behind otherwise. Pinned
|
||||
// sessions keep their existing demote-not-delete protection.
|
||||
const session = ctx.sessions.get(id);
|
||||
if (!session) {
|
||||
const persisted = ctx.store.getSession(id);
|
||||
if (!persisted || !canAccessOwned(getAuthUser(req), persisted.owner)) {
|
||||
throw Object.assign(new Error(`Session ${id} not found`), {
|
||||
statusCode: 404,
|
||||
body: createErrorResponse(ApiErrorCode.NOT_FOUND, `Session ${id} not found`),
|
||||
});
|
||||
}
|
||||
if (!ctx.sessions.has(id)) {
|
||||
// Called for its existence/ownership 404 side effect only — demoteOrRemoveSession
|
||||
// below re-looks-up the record by id, so the returned SessionState is unused here.
|
||||
findPersistedSessionOrFail(ctx.store, id, req);
|
||||
ctx.store.demoteOrRemoveSession(id);
|
||||
// Mirrors the broadcast at the tail of the live-session cleanup path
|
||||
// (_doCleanupSession in server.ts) — without it, other open tabs keep
|
||||
// showing the retired row until their next unrelated fetch.
|
||||
ctx.broadcast(SseEvent.SessionDeleted, { id });
|
||||
return {};
|
||||
}
|
||||
if (req && !canAccessOwned(getAuthUser(req), session.owner)) {
|
||||
throw Object.assign(new Error(`Session ${id} not found`), {
|
||||
statusCode: 404,
|
||||
body: createErrorResponse(ApiErrorCode.NOT_FOUND, `Session ${id} not found`),
|
||||
});
|
||||
}
|
||||
|
||||
const session = findSessionOrFail(ctx, id, req);
|
||||
await ctx.cleanupSession(session.id, killMux, 'user_delete');
|
||||
return {};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user