fix: clearCompleted must also delete from _knownSessions

Without this, _onSessionAdded never fires on reactivation because
isKnown=true short-circuits the new-session detection branch.

clearCompleted is called on lock file creation / ghost watch fire.
It clears _completedSessions cooldown but the session key stayed in
_knownSessions (isKnown=true), so poll() treated it as already tracked
and silently updated the entry instead of firing _onSessionAdded.

Fix: also delete from _knownSessions in clearCompleted() so next poll
sees the session as unknown and fires _onSessionAdded -> creates new
plugin status box.

Also: findExistingPost skipped in plugin mode on session-added to
prevent stale post reuse from REST search results.
This commit is contained in:
sol
2026-03-09 18:57:54 +00:00
parent cdef7a1903
commit cc65f9b5ce
2 changed files with 12 additions and 3 deletions

View File

@@ -106,6 +106,10 @@ class SessionMonitor extends EventEmitter {
*/
clearCompleted(sessionKey) {
this._completedSessions.delete(sessionKey);
// Also remove from _knownSessions so the next poll sees it as a new session
// and fires _onSessionAdded (which creates the new status box).
// Without this, isKnown=true suppresses _onSessionAdded even after clearCompleted.
this._knownSessions.delete(sessionKey);
}
/**

View File

@@ -287,8 +287,11 @@ async function startDaemon() {
logger.info({ sessionKey }, 'Reactivating session — creating fresh status box');
}
// Check for existing post (restart recovery)
if (!postId) {
// Check for existing post (restart recovery — REST mode only).
// In plugin mode we always create a fresh post: the plugin manages its own
// KV store and the old post is already marked done. Reusing it would make
// the status box appear stuck at the old position in the thread.
if (!postId && !(usePlugin && pluginClient)) {
const saved = savedOffsets[sessionKey]; // eslint-disable-line security/detect-object-injection
if (saved) {
// Try to find existing post in channel history
@@ -300,7 +303,9 @@ async function startDaemon() {
if (!postId) {
try {
if (usePlugin && pluginClient) {
// Plugin mode: create custom_livestatus post via plugin
// Plugin mode: always create a fresh custom_livestatus post.
// The plugin replaces any existing KV entry for this sessionKey so there
// is no risk of duplicate boxes.
postId = await pluginClient.createSession(sessionKey, channelId, rootPostId, agentId);
logger.info({ sessionKey, postId, channelId, mode: 'plugin' }, 'Created status box via plugin');
} else {