Skip to content

fix(state): delete the session state file when a session is deleted - #637

Open
Mukller wants to merge 1 commit into
Tarquinen:devfrom
Mukller:fix/session-state-cleanup
Open

Mukller wants to merge 1 commit into
Tarquinen:devfrom
Mukller:fix/session-state-cleanup

Conversation

@Mukller

@Mukller Mukller commented Sep 28, 2026

Copy link
Copy Markdown

Closes #557

Problem

DCP persists prune state per session at
$XDG_DATA_HOME/opencode/storage/plugin/dcp/{sessionId}.json, and nothing ever removed those files. Deleting a session left the file on disk forever, and loadAllSessionStats kept counting it — it aggregates every *.json in that directory, so the all-time totals drifted upward permanently.

The host already emits session.deleted carrying the session id, but createEventHandler only ever looked at message.part.updated:

if (input.event.type !== "message.part.updated") {
    return
}

so the delete case was unreachable.

Change

  • deleteSessionState(sessionId, logger) in lib/state/persistence.ts unlinks the file and swallows the error, since the file may never have been written or may already be gone.
  • createEventHandler handles session.deleted before the timestamp extraction, so it cannot perturb the compression-timing branch. If the deleted session is the one the plugin holds state for, state.sessionId is detached so the next request re-initialises instead of writing the file straight back.

Verification

tests/session-cleanup.test.ts, six cases:

  • the state file is gone after session.deleted
  • deleting one session leaves the active session's file and in-memory id alone
  • deleting the active session detaches state.sessionId
  • malformed delete events (properties missing, empty id) are harmless
  • the message.part.updated timing branch still records compression starts
  • unrelated events do not touch the storage directory

Three of the six fail on the current implementation with the orphaned state file survived.

Full suite 125 passing, tsc --noEmit clean, prettier --check clean.

Closes Tarquinen#557

DCP persists prune state per session at
$XDG_DATA_HOME/opencode/storage/plugin/dcp/{sessionId}.json. Nothing ever removed
those files, so deleting a session left an orphan on disk forever - and
loadAllSessionStats kept counting it, because it aggregates every file it finds
in that directory.

The host already emits session.deleted with the session id, and
createEventHandler previously only looked at message.part.updated, so the
delete branch is simply unreachable today.

deleteSessionState unlinks the file and swallows the error, since the file may
never have been written or may already be gone. If the deleted session is the
one the plugin holds state for, the in-memory session id is detached so a later
request re-initialises instead of writing the file back.

The session.deleted check runs before the timestamp extraction so it cannot
change the behaviour of the compression timing branch, which is covered by a
test.

Tests: tests/session-cleanup.test.ts, six cases. Three fail on the current
implementation with `the orphaned state file survived`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant