[codex] Clear role-scoped sessions (#139)

* add gated codex goals support

* sync README SDK versions

* bump claude agent sdk

* add codex goals settings toggle

* reuse status dashboard message and simplify settings actions

* refine settings page UX

* fix settings nav hash routing

* add dashboard UX verification

* refine dashboard settings and inbox UX

* remove inbox top-level navigation

* remove dashboard health top-level navigation

* fix: allow runtime image attachment paths

* feat: configure attachment allowlist dirs

* fix: clean duplicate dashboard status messages

* fix: poll dashboard duplicate cleanup between status updates

* fix: delete dashboard duplicates on create

* Refine settings IA with tabbed sections

* Add read-only runtime inventory settings

* Fix runtime inventory MCP JSON parsing

* Add room skill settings inventory

* Add room skill setting mutations

* Apply room skill overrides to runner spawn

* Refine scheduled task dashboard UX

* Remove reviewer final prompt reinjection

* Stabilize pnpm verification fixture

* Remove previous owner final prompt carryover

* Clear role-scoped sessions
This commit is contained in:
Eyejoker
2026-05-17 01:02:40 +08:00
committed by GitHub
parent 59874427aa
commit 86e3fa7521
4 changed files with 78 additions and 3 deletions

28
src/db-sessions.test.ts Normal file
View File

@@ -0,0 +1,28 @@
import { beforeEach, describe, expect, it } from 'vitest';
import {
_initTestDatabase,
deleteAllSessionsForGroup,
getSession,
setSession,
} from './db.js';
describe('session accessors', () => {
beforeEach(() => {
_initTestDatabase();
});
it('deletes owner, reviewer, and arbiter role-scoped sessions for a group', () => {
setSession('group-a', 'owner-session');
setSession('group-a:reviewer', 'reviewer-session');
setSession('group-a:arbiter', 'arbiter-session');
setSession('group-b', 'other-session');
deleteAllSessionsForGroup('group-a');
expect(getSession('group-a')).toBeUndefined();
expect(getSession('group-a:reviewer')).toBeUndefined();
expect(getSession('group-a:arbiter')).toBeUndefined();
expect(getSession('group-b')).toBe('other-session');
});
});

View File

@@ -141,8 +141,11 @@ export function deleteAllSessionsForGroupFromDatabase(
groupFolder: string, groupFolder: string,
): void { ): void {
database database
.prepare('DELETE FROM sessions WHERE group_folder = ?') .prepare(
.run(groupFolder); `DELETE FROM sessions
WHERE group_folder IN (?, ?, ?)`,
)
.run(groupFolder, `${groupFolder}:reviewer`, `${groupFolder}:arbiter`);
} }
export function getAllSessionsForAgentTypeFromDatabase( export function getAllSessionsForAgentTypeFromDatabase(

37
src/runtime-state.test.ts Normal file
View File

@@ -0,0 +1,37 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
const db = vi.hoisted(() => ({
assignRoom: vi.fn(),
deleteAllSessionsForGroup: vi.fn(),
deleteSession: vi.fn(),
getAllRoomBindings: vi.fn(() => ({})),
getAllSessions: vi.fn(() => ({})),
getRouterState: vi.fn(() => ''),
setRouterState: vi.fn(),
setSession: vi.fn(),
}));
vi.mock('./db.js', () => db);
import { createRuntimeState } from './runtime-state.js';
describe('createRuntimeState', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('clears role-scoped sessions from memory when allRoles is requested', () => {
const state = createRuntimeState();
state.persistSession('group-a', 'owner-session');
state.persistSession('group-a:reviewer', 'reviewer-session');
state.persistSession('group-a:arbiter', 'arbiter-session');
state.persistSession('group-b', 'other-session');
state.clearSession('group-a', { allRoles: true });
expect(state.getSessions()).toEqual({ 'group-b': 'other-session' });
expect(db.deleteAllSessionsForGroup).toHaveBeenCalledWith('group-a');
expect(db.deleteSession).not.toHaveBeenCalled();
});
});

View File

@@ -48,10 +48,17 @@ export function createRuntimeState(): RuntimeState {
groupFolder: string, groupFolder: string,
opts?: { allRoles?: boolean }, opts?: { allRoles?: boolean },
): void => { ): void => {
delete sessions[groupFolder];
if (opts?.allRoles) { if (opts?.allRoles) {
for (const key of [
groupFolder,
`${groupFolder}:reviewer`,
`${groupFolder}:arbiter`,
]) {
delete sessions[key];
}
deleteAllSessionsForGroup(groupFolder); deleteAllSessionsForGroup(groupFolder);
} else { } else {
delete sessions[groupFolder];
deleteSession(groupFolder); deleteSession(groupFolder);
} }
}; };