src — presence

Module: src-presence Cohesion: 0.80 Members: 0

src — presence

The src/presence/typing-indicator.ts module provides a robust mechanism for managing "typing" indicators and overall system presence. It's designed to allow other parts of the application to signal active user input (e.g., a bot typing a response) and to reflect the system's general availability status.

Module Overview

This module centralizes the logic for:

  1. Signaling Typing Activity: Initiating and stopping "typing..." indicators for specific communication channels and chats.
  2. Maintaining System Presence: Tracking the overall status of the application (e.g., online, busy, idle).
  3. Event-Driven Communication: Notifying subscribers about changes in typing status or system presence.

It's a self-contained utility that other modules (e.g., channel-specific integrations like Telegram or Discord bots) can leverage to provide a more responsive and informative user experience.

Key Concepts

ChannelType

A union type defining the supported communication channels.

type ChannelType = 'telegram' | 'discord' | 'slack' | 'terminal';

TypingSession

An interface representing an active typing indicator for a specific chat.

interface TypingSession {
  channel: ChannelType;
  chatId: string;
  interval: ReturnType<typeof setInterval> | null; class="hl-cmt">// The interval for periodic updates
  active: boolean; class="hl-cmt">// Whether the session is currently active
  startedAt: number; class="hl-cmt">// Timestamp when the session began
}

PresenceState

An interface defining the overall presence status of the system.

interface PresenceState {
  status: &#39;online&#39; | &#39;busy&#39; | &#39;idle&#39; | &#39;offline&#39;;
  lastActivity: number; class="hl-cmt">// Timestamp of the last status update
  currentTask?: string; class="hl-cmt">// Optional description of the current task
}

TypingIndicatorManager Class

The TypingIndicatorManager is the core class of this module. It extends Node.js's EventEmitter, allowing it to emit events when typing status or presence changes.

Initialization

class TypingIndicatorManager extends EventEmitter {
  private sessions: Map<string, TypingSession> = new Map();
  private presence: PresenceState = { status: &#39;online&#39;, lastActivity: Date.now() };
  private intervalMs: number;

  constructor(intervalMs: number = 4000) {
    super();
    this.intervalMs = intervalMs; class="hl-cmt">// How often to re-emit &#39;typing&#39; events
  }
  class="hl-cmt">// ...
}

The constructor initializes the manager with an optional intervalMs parameter, which dictates how frequently the 'typing' event should be re-emitted while a session is active. This is crucial for platforms that require periodic "typing" signals to keep the indicator visible.

Core Functionality

startTyping(channel: ChannelType, chatId: string): string

Initiates a typing indicator for a specific channel and chatId.

stopTyping(key: string): void

Stops a specific typing indicator session identified by its key.

stopAll(): void

Stops all currently active typing indicator sessions. This method iterates through all active sessions and calls stopTyping for each.

Presence Management

updatePresence(status: PresenceState['status'], task?: string): void

Manually updates the system's overall presence state.

getPresence(): PresenceState

Returns a copy of the current PresenceState.

getActiveCount(): number

Returns the number of currently active typing sessions.

Lifecycle

dispose(): void

Performs cleanup for the TypingIndicatorManager.

Events Emitted

The TypingIndicatorManager emits two types of events:

  1. 'typing':

  1. 'presence':

Internal Flow

The following diagram illustrates the core interactions within the TypingIndicatorManager when handling typing sessions:

graph TD
    subgraph TypingIndicatorManager
        A[startTyping(channel, chatId)] --> B{Create TypingSession}
        B --> C[Emit 'typing' (true)]
        C --> D[setInterval(emit 'typing' (true))]
        D -- periodically --> C
        D --> E[updatePresence('busy')]

        F[stopTyping(key)] --> G{Clear interval}
        G --> H[Emit 'typing' (false)]
        H --> I{Delete TypingSession}
        I --> J{If no sessions, updatePresence('online')}
    end

Integration with the Codebase

The TypingIndicatorManager is designed to be a central service for managing presence and typing states.

A typical integration pattern would involve:

  1. Instantiating TypingIndicatorManager once in the application's bootstrap phase.
  2. Channel-specific modules (e.g., TelegramAdapter, DiscordAdapter) subscribing to the 'typing' event.
  3. Core application logic or command handlers calling startTyping and stopTyping as needed.
  4. Monitoring or dashboard components subscribing to the 'presence' event.

This module ensures that the application can communicate its activity and availability effectively across various platforms without tightly coupling the presence logic to specific channel implementations.