Make thread/channel/message deletion complete (hard delete)
Deleting a thread, channel, or message was a no-op/soft-delete: messages were only dropped from the plugin outbox (still in hermes' session store, hence searchable/recoverable) and channels/threads were merely archived. Now deletion is complete and non-recoverable, with no search trace: - purge.py (new): hard-delete from hermes' session store (state.db). delete_lane wipes a channel's/thread's sessions + messages; deleting a messages row also drops it from the FTS5 index via the delete triggers. delete_message removes one message, matched by (session, role, exact content, closest timestamp) since plugin m_<hex> ids aren't persisted. - channels.py: delete() hard-deletes the row (and a channel's child threads) instead of archiving. - outbox.py: add delete_lane() (wipe all frames for a lane) and message_info() (read a message's final role/text/ts for the match). - adapter.py: on_channel_delete wipes outbox + session store; on_message_delete purges the session-store row per message. - App: delete confirmations no longer claim history stays for search; ChannelStore removes a channel's threads on channel delete. - Docs updated to describe hard deletion.
This commit is contained in:
1 parent
9286937e2d
commit
17bf41a0b9
11 files changed
+373
-51
No files matched your search
@@ -293,20 +293,28 @@ class ChannelDirectory:
|
||||
return self.get(chat_id)
|
||||
|
||||
def delete(self, chat_id: str) -> dict[str, Any] | None:
|
||||
"""Soft-delete (archive) a channel. History stays for search.
|
||||
"""Hard-delete a channel or thread (and, for a channel, its threads).
|
||||
|
||||
The default channel cannot be deleted. Returns the (archived) entry,
|
||||
or ``None`` when the id is unknown / is the default.
|
||||
The row is removed from the directory entirely -- not recoverable. The
|
||||
caller (adapter) is responsible for wiping the lane's history from the
|
||||
outbox and the hermes session store so no search trace survives.
|
||||
|
||||
The default channel cannot be deleted. Returns the (deleted) entry, or
|
||||
``None`` when the id is unknown / is the default.
|
||||
"""
|
||||
with self._lock:
|
||||
row = self._conn.execute(
|
||||
"SELECT is_default FROM channels WHERE chat_id = ?", (chat_id,)
|
||||
"SELECT * FROM channels WHERE chat_id = ?", (chat_id,)
|
||||
).fetchone()
|
||||
if row is None or row["is_default"]:
|
||||
return None
|
||||
self._conn.execute("UPDATE channels SET archived = 1 WHERE chat_id = ?", (chat_id,))
|
||||
entry = _row_to_entry(row)
|
||||
self._conn.execute("DELETE FROM channels WHERE chat_id = ?", (chat_id,))
|
||||
# A channel takes its threads with it.
|
||||
if entry["kind"] != KIND_THREAD:
|
||||
self._conn.execute("DELETE FROM channels WHERE parent_chat_id = ?", (chat_id,))
|
||||
self._conn.commit()
|
||||
return self.get(chat_id)
|
||||
return entry
|
||||
|
||||
# ── reads ─────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
Reference in new issue
Block a user