mattermost-claude-code 0.5.4 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,23 +17,21 @@ Share Claude Code sessions live in a Mattermost channel. Your colleagues can wat
17
17
 
18
18
  ## How it works
19
19
 
20
- ```
21
- ┌─────────────────────────────────────────────────────────────────┐
22
- Your Local Machine
23
- │ ┌─────────────────┐ ┌─────────────────────────────┐ │
24
- │ │ Claude Code CLI │◀───────▶│ mm-claude │ │
25
- │ │ (subprocess) │ stdio (this service) │ │
26
- │ └─────────────────┘ └──────────┬──────────────────┘ │
27
- └─────────────────────────────────────────┼───────────────────────┘
28
- WebSocket + REST API
29
- (outbound only)
30
- ┌─────────────────────────────────────────────────────────────────┐
31
- │ Mattermost Server │
32
- │ ┌─────────────────┐ ┌─────────────────────────────┐ │
33
- │ │ Bot Account │◀───────▶│ Channel │ │
34
- │ │ @claude-code │ │ #claude-sessions │ │
35
- │ └─────────────────┘ └─────────────────────────────┘ │
36
- └─────────────────────────────────────────────────────────────────┘
20
+ ```mermaid
21
+ flowchart TB
22
+ subgraph local["Your Local Machine"]
23
+ cli["Claude Code CLI<br/>(subprocess)"]
24
+ mm["mm-claude<br/>(this service)"]
25
+ cli <-->|"stdio"| mm
26
+ end
27
+
28
+ subgraph server["Mattermost Server"]
29
+ bot["Bot Account<br/>@claude-code"]
30
+ channel["Channel<br/>#claude-sessions"]
31
+ bot <--> channel
32
+ end
33
+
34
+ mm -->|"WebSocket + REST API<br/>(outbound only)"| server
37
35
  ```
38
36
 
39
37
  Runs entirely on your machine - only **outbound** connections to Mattermost. No port forwarding needed!
@@ -51,6 +51,7 @@ interface Session {
51
51
  activeSubagents: Map<string, string>;
52
52
  updateTimer: ReturnType<typeof setTimeout> | null;
53
53
  typingTimer: ReturnType<typeof setInterval> | null;
54
+ timeoutWarningPosted: boolean;
54
55
  }
55
56
  export declare class SessionManager {
56
57
  private mattermost;
@@ -16,6 +16,7 @@ const EMOJI_TO_INDEX = {
16
16
  // =============================================================================
17
17
  const MAX_SESSIONS = parseInt(process.env.MAX_SESSIONS || '5', 10);
18
18
  const SESSION_TIMEOUT_MS = parseInt(process.env.SESSION_TIMEOUT_MS || '1800000', 10); // 30 min
19
+ const SESSION_WARNING_MS = 5 * 60 * 1000; // Warn 5 minutes before timeout
19
20
  // =============================================================================
20
21
  // SessionManager - Manages multiple concurrent Claude Code sessions
21
22
  // =============================================================================
@@ -127,6 +128,7 @@ export class SessionManager {
127
128
  activeSubagents: new Map(),
128
129
  updateTimer: null,
129
130
  typingTimer: null,
131
+ timeoutWarningPosted: false,
130
132
  };
131
133
  // Register session
132
134
  this.sessions.set(actualThreadId, session);
@@ -157,8 +159,9 @@ export class SessionManager {
157
159
  const session = this.sessions.get(threadId);
158
160
  if (!session)
159
161
  return;
160
- // Update last activity
162
+ // Update last activity and reset timeout warning
161
163
  session.lastActivityAt = new Date();
164
+ session.timeoutWarningPosted = false;
162
165
  // Check for special tool uses that need custom handling
163
166
  if (event.type === 'assistant') {
164
167
  const msg = event.message;
@@ -937,8 +940,10 @@ export class SessionManager {
937
940
  /** Cleanup idle sessions that have exceeded timeout */
938
941
  cleanupIdleSessions() {
939
942
  const now = Date.now();
943
+ const warningThreshold = SESSION_TIMEOUT_MS - SESSION_WARNING_MS;
940
944
  for (const [threadId, session] of this.sessions.entries()) {
941
945
  const idleTime = now - session.lastActivityAt.getTime();
946
+ // Check if we should time out
942
947
  if (idleTime > SESSION_TIMEOUT_MS) {
943
948
  const mins = Math.round(idleTime / 60000);
944
949
  const shortId = threadId.substring(0, 8);
@@ -946,6 +951,14 @@ export class SessionManager {
946
951
  this.mattermost.createPost(`⏰ **Session timed out** — no activity for ${mins} minutes`, session.threadId).catch(() => { });
947
952
  this.killSession(threadId);
948
953
  }
954
+ // Check if we should show warning (only once)
955
+ else if (idleTime > warningThreshold && !session.timeoutWarningPosted) {
956
+ const remainingMins = Math.round((SESSION_TIMEOUT_MS - idleTime) / 60000);
957
+ const shortId = threadId.substring(0, 8);
958
+ console.log(` ⚠️ Session (${shortId}…) warning: ${remainingMins}m until timeout`);
959
+ this.mattermost.createPost(`⚠️ **Session idle** — will time out in ~${remainingMins} minutes. Send a message to keep it alive.`, session.threadId).catch(() => { });
960
+ session.timeoutWarningPosted = true;
961
+ }
949
962
  }
950
963
  }
951
964
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mattermost-claude-code",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "Share Claude Code sessions live in a Mattermost channel with interactive features",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",