Group management functions for registering groups, retrieving group lists, and managing group state.
Core functions
registerGroup
Registers a new group with NanoClaw.
function registerGroup(jid: string, group: RegisteredGroup): void
Chat JID (e.g., "123456789@g.us" for WhatsApp groups)
Group configuration object
Behavior:
- Validates the group folder path
- Creates the group directory structure (
groups/{folder}/logs/)
- Stores group configuration in database
- Rejects registration if folder is invalid
Example:
registerGroup('123@g.us', {
name: 'Team Chat',
folder: 'team',
trigger: '^@Andy\\b',
added_at: new Date().toISOString(),
requiresTrigger: true,
});
getAvailableGroups
Returns list of all available groups ordered by most recent activity.
function getAvailableGroups(): AvailableGroup[]
Array of available groups with metadata
Returns:
interface AvailableGroup {
jid: string; // Chat JID
name: string; // Chat display name
lastActivity: string; // ISO timestamp of last message
isRegistered: boolean; // Whether group is registered
}
Example:
import { getAvailableGroups } from './index.js';
const groups = getAvailableGroups();
console.log(`Found ${groups.length} groups`);
for (const group of groups) {
console.log(`${group.name} (${group.isRegistered ? 'registered' : 'not registered'})`);
}
State management
loadState
Loads router state from database.
function loadState(): void
Loads:
- Last timestamp cursor (
last_timestamp)
- Last agent timestamp per group (
last_agent_timestamp)
- Session IDs by group folder
- Registered groups configuration
saveState
Saves router state to database.
function saveState(): void
Saves:
- Last timestamp cursor
- Last agent timestamp per group
recoverPendingMessages
Recovery function that checks for unprocessed messages on startup.
function recoverPendingMessages(): void
Purpose:
Handles crash recovery by detecting messages that were stored in the database but not yet processed by the agent (e.g., if the process crashed between advancing lastTimestamp and processing messages).
Types
RegisteredGroup
interface RegisteredGroup {
name: string; // Display name
folder: string; // Folder name (alphanumeric + hyphens/underscores)
trigger: string; // Trigger pattern regex
added_at: string; // ISO timestamp of registration
containerConfig?: ContainerConfig; // Optional container configuration
requiresTrigger?: boolean; // Whether trigger is required (default: true)
isMain?: boolean; // True for the main control group (elevated privileges)
}
ContainerConfig
interface ContainerConfig {
additionalMounts?: AdditionalMount[]; // Extra filesystem mounts
timeout?: number; // Container timeout in ms
}
AdditionalMount
interface AdditionalMount {
hostPath: string; // Absolute path on host (supports ~)
containerPath?: string; // Optional container path (defaults to basename)
readonly?: boolean; // Default: true for safety
}
Database operations
Group data is persisted in the SQLite database:
setRegisteredGroup
function setRegisteredGroup(jid: string, group: RegisteredGroup): void
Stores or updates a registered group in the database.
getRegisteredGroup
function getRegisteredGroup(jid: string): (RegisteredGroup & { jid: string }) | undefined
Retrieves a registered group by JID.
getAllRegisteredGroups
function getAllRegisteredGroups(): Record<string, RegisteredGroup>
Returns all registered groups as a map from JID to group configuration.
Folder validation
Group folders must:
- Contain only alphanumeric characters, hyphens, and underscores
- Not be empty
- Not contain path traversal characters (
.., /)
Invalid folders are rejected during registration and skipped when loading from database.
Main group
The “main” group (folder name "main") has special privileges:
- Can see all available groups
- Does not require trigger by default
- Has access to group management functions via IPC