feat: RHS panel — persistent Agent Status sidebar
Added a Right-Hand Sidebar (RHS) panel to the Mattermost plugin that shows live agent activity in a dedicated, always-visible panel. - New RHSPanel component with SessionCard views per active session - registerAppBarComponent adds 'Agent Status' icon to toolbar - Subscribes to WebSocket updates via global listener - Shows active sessions with live elapsed time, tool calls, token count - Shows recent completed sessions below active ones - Responsive CSS matching Mattermost design system The RHS panel solves the scroll-out-of-view problem: the status dashboard stays visible regardless of chat scroll position.
This commit is contained in:
@@ -96,6 +96,21 @@ class StatusBox extends EventEmitter {
|
||||
return post.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Mattermost post.
|
||||
* @param {string} postId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async deletePost(postId) {
|
||||
try {
|
||||
await this._apiCall('DELETE', `/api/v4/posts/${postId}`);
|
||||
if (this.logger) this.logger.debug({ postId }, 'Deleted status post');
|
||||
} catch (err) {
|
||||
if (this.logger) this.logger.warn({ postId, err: err.message }, 'Failed to delete status post');
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a Mattermost post (throttled).
|
||||
* Leading edge fires immediately; subsequent calls within throttleMs are batched.
|
||||
|
||||
@@ -274,9 +274,17 @@ async function startDaemon() {
|
||||
// Check if this session was previously completed (reactivation after idle)
|
||||
const completed = completedBoxes.get(sessionKey);
|
||||
if (completed) {
|
||||
postId = completed.postId;
|
||||
// Delete the old buried post and create a fresh one at the current thread position
|
||||
// so users can see it without scrolling up
|
||||
try {
|
||||
await sharedStatusBox.deletePost(completed.postId);
|
||||
logger.info({ sessionKey, oldPostId: completed.postId }, 'Deleted old buried status box on reactivation');
|
||||
} catch (err) {
|
||||
logger.warn({ sessionKey, oldPostId: completed.postId, err: err.message }, 'Failed to delete old status box (may already be deleted)');
|
||||
}
|
||||
completedBoxes.delete(sessionKey);
|
||||
logger.info({ sessionKey, postId }, 'Reactivating completed session — reusing existing post');
|
||||
// postId stays null — will create a fresh one below
|
||||
logger.info({ sessionKey }, 'Reactivating session — creating fresh status box');
|
||||
}
|
||||
|
||||
// Check for existing post (restart recovery)
|
||||
|
||||
Reference in New Issue
Block a user