or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

adapters-integration.mdbrain-user-management.mdcli.mdcore-bot-management.mddatastore.mdindex.mdmessage-handling.mdscripts-middleware.md
tile.json

brain-user-management.mddocs/

Brain and User Management

Robot memory system with user management, persistent data storage, and automatic serialization for maintaining state across restarts.

Capabilities

Brain Class

The Brain serves as the robot's memory system, providing data persistence and user management functionality.

/**
 * Robot memory and user management system
 * @param robot - Robot instance that owns this brain
 */
class Brain {
  constructor(robot: Robot);
  
  // Properties
  data: {
    users: Record<string, User>;
    _private: Record<string, any>;
  };
  autoSave: boolean;
  
  // Data storage methods
  set(key: string, value: any): Brain;
  get(key: string): any;
  remove(key: string): Brain;
  
  // Persistence methods
  save(): void;
  close(): void;
  
  // User management methods
  users(): Record<string, User>;
  userForId(id: string, options?: UserOptions): User;
  userForName(name: string): User | null;
  usersForRawFuzzyName(fuzzyName: string): User[];
  usersForFuzzyName(fuzzyName: string): User[];
  
  // Configuration methods
  setAutoSave(enabled: boolean): void;
  resetSaveInterval(seconds: number): void;
  mergeData(data: any): void;
}

Usage Examples:

import { Robot } from "hubot";

const robot = new Robot("Shell");

// Store and retrieve data (chainable)
robot.brain.set('server-stats', { uptime: Date.now(), requests: 0 })
  .set('app-version', '1.0.0');
const stats = robot.brain.get('server-stats');

// Remove data (chainable)
robot.brain.remove('old-data').remove('another-key');

// Configure auto-save (enabled by default)
robot.brain.setAutoSave(true);
robot.brain.resetSaveInterval(30); // Save every 30 seconds

// Access all users
const allUsers = robot.brain.users();
console.log(`Total users: ${Object.keys(allUsers).length}`);

// Get or create user by ID
const user = robot.brain.userForId('user123', { name: 'Alice' });

// Find user by name
const alice = robot.brain.userForName('Alice');

// Fuzzy name search
const matches = robot.brain.usersForFuzzyName('al'); // Finds "Alice", "Albert", etc.

// Manual save trigger
robot.brain.save();

// Cleanup on shutdown
robot.brain.close();

User Class

Represents individual chat users with persistent data storage capabilities.

/**
 * User representation with persistent data storage
 * @param id - Unique user identifier
 * @param options - Hash of user properties
 */
class User {
  constructor(id: string, options?: UserOptions);
  
  // Properties
  id: string;
  name: string; // Defaults to id if not provided
  room?: string;
  
  // Data storage methods
  async set(key: string, value: any): Promise<void>;
  async get(key: string): Promise<any>;
}

interface UserOptions {
  name?: string;
  room?: string;
  [key: string]: any; // Additional user properties
}

Usage Examples:

// Create user with basic info
const user = new User('user123', {
  name: 'Alice Smith',
  room: 'general',
  email: 'alice@example.com'
});

// Store user-specific data (async)
await user.set('preferences', { theme: 'dark', notifications: true });
await user.set('score', 100);
await user.set('last-seen', new Date().toISOString());

// Retrieve user data (async)
const prefs = await user.get('preferences');
const score = await user.get('score');

// Use in listeners (async)
robot.hear(/my score/i, async (res) => {
  const score = await res.message.user.get('score') || 0;
  res.reply(`Your score is ${score} points!`);
});

robot.hear(/set theme (.+)/i, async (res) => {
  const theme = res.match[1];
  await res.message.user.set('theme', theme);
  res.reply(`Theme set to ${theme}`);
});

Data Persistence

Brain automatically handles data persistence with configurable auto-save functionality.

// Brain emits events for persistence
robot.brain.on('save', (data) => {
  // Save data to your preferred storage (file, database, etc.)
  console.log('Saving brain data:', data);
});

robot.brain.on('loaded', (data) => {
  console.log('Brain data loaded');
});

// Manual data merging (for loading from storage)
const savedData = loadFromStorage(); // Your storage implementation
robot.brain.mergeData(savedData);

User Search and Management

Advanced user lookup capabilities with fuzzy matching.

/**
 * Get all users as object with user IDs as keys
 */
users(): Record<string, User>;

/**
 * Get or create user by ID
 * @param id - User ID
 * @param options - User properties if creating new user
 */
userForId(id: string, options?: UserOptions): User;

/**
 * Find user by exact name match
 * @param name - User's display name
 */
userForName(name: string): User | null;

/**
 * Find users by fuzzy name matching (raw search)
 * @param fuzzyName - Partial or fuzzy name to match
 */
usersForRawFuzzyName(fuzzyName: string): User[];

/**
 * Find users by fuzzy name with exact match preference
 * @param fuzzyName - Partial or fuzzy name to match
 */
usersForFuzzyName(fuzzyName: string): User[];

Usage Examples:

// Find users for @mentions
robot.hear(/@(\w+)/i, (res) => {
  const username = res.match[1];
  const users = robot.brain.usersForFuzzyName(username);
  
  if (users.length === 1) {
    res.send(`You mentioned ${users[0].name}`);
  } else if (users.length > 1) {
    const names = users.map(u => u.name).join(', ');
    res.send(`Multiple users found: ${names}`);
  } else {
    res.send(`User '${username}' not found`);
  }
});

// User statistics
robot.respond(/user stats/i, (res) => {
  const users = robot.brain.users();
  const userCount = Object.keys(users).length;
  const activeUsers = Object.values(users).filter(u => 
    u.get('last-seen') && 
    new Date(u.get('last-seen')) > new Date(Date.now() - 24 * 60 * 60 * 1000)
  ).length;
  
  res.send(`Total users: ${userCount}, Active today: ${activeUsers}`);
});

DataStore Integration

Brain can integrate with custom DataStore implementations for different persistence backends.

/**
 * Abstract DataStore interface for persistent storage
 * @param robot - Robot instance
 */
class DataStore {
  constructor(robot: Robot);
  
  robot: Robot;
  
  // Global data methods
  async set(key: string, value: any): Promise<void>;
  async get(key: string): Promise<any>;
  async setObject(key: string, objectKey: string, value: any): Promise<void>;
  async getObject(key: string, objectKey: string): Promise<any>;
  async setArray(key: string, value: any): Promise<void>;
}

/**
 * Error class for DataStore unavailable conditions
 * @param message - Error message
 */
class DataStoreUnavailable extends Error {
  constructor(message: string);
}

Types

interface BrainData {
  users: Record<string, User>;
  _private: Record<string, any>;
}

interface UserData {
  id: string;
  name: string;
  room?: string;
  [key: string]: any;
}

interface BrainEvents {
  'save': (data: BrainData) => void;
  'loaded': () => void;
  'close': () => void;
}