* feat: add group message batching, Telegram group gating, and instantGroups Group Message Batcher: - New GroupBatcher buffers group chat messages and flushes on timer or @mention - Channel-agnostic: works with any ChannelAdapter - Configurable per-channel via groupPollIntervalMin (default: 10min, 0 = immediate) - formatGroupBatchEnvelope formats batched messages as chat logs for the agent - Single-message batches unwrapped to use DM-style formatMessageEnvelope Telegram Group Gating: - my_chat_member handler: bot leaves groups when added by unpaired users - Groups added by paired users are auto-approved via group-store - Group messages bypass DM pairing (middleware skips group/supergroup chats) - Mention detection for @bot in group messages Channel Group Support: - All adapters: getDmPolicy() interface method - Discord: serverId (guildId), wasMentioned, pairing bypass for guilds - Signal: group messages bypass pairing - Slack: wasMentioned field on messages instantGroups Config: - Per-channel instantGroups config to bypass batching for specific groups - For Discord, checked against both serverId and chatId - YAML config → env vars → parsed in main.ts → Set passed to bot Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: preserve large numeric IDs in instantGroups YAML config Discord snowflake IDs exceed Number.MAX_SAFE_INTEGER, so YAML parses unquoted IDs as lossy JavaScript numbers. Use the document AST to extract the original string representation and avoid precision loss. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Slack dmPolicy, Telegram group gating check - Add dmPolicy to SlackConfig and wire through config/env/adapter (was hardcoded to 'open', now reads from config like other adapters) - Check isGroupApproved() in Telegram middleware before processing group messages (approveGroup was called but never checked) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
170 lines
4.9 KiB
TypeScript
170 lines
4.9 KiB
TypeScript
/**
|
|
* LettaBot Configuration Types
|
|
*
|
|
* Two modes:
|
|
* 1. Self-hosted: Uses baseUrl (e.g., http://localhost:8283), no API key
|
|
* 2. Letta Cloud: Uses apiKey, optional BYOK providers
|
|
*/
|
|
|
|
export interface LettaBotConfig {
|
|
// Server connection
|
|
server: {
|
|
// 'cloud' (api.letta.com) or 'selfhosted'
|
|
mode: 'cloud' | 'selfhosted';
|
|
// Only for selfhosted mode
|
|
baseUrl?: string;
|
|
// Only for cloud mode
|
|
apiKey?: string;
|
|
};
|
|
|
|
// Agent configuration
|
|
agent: {
|
|
id?: string;
|
|
name: string;
|
|
model: string;
|
|
};
|
|
|
|
// BYOK providers (cloud mode only)
|
|
providers?: ProviderConfig[];
|
|
|
|
// Channel configurations
|
|
channels: {
|
|
telegram?: TelegramConfig;
|
|
slack?: SlackConfig;
|
|
whatsapp?: WhatsAppConfig;
|
|
signal?: SignalConfig;
|
|
discord?: DiscordConfig;
|
|
};
|
|
|
|
// Features
|
|
features?: {
|
|
cron?: boolean;
|
|
heartbeat?: {
|
|
enabled: boolean;
|
|
intervalMin?: number;
|
|
};
|
|
maxToolCalls?: number; // Abort if agent calls this many tools in one turn (default: 100)
|
|
};
|
|
|
|
// Polling - system-level background checks (Gmail, etc.)
|
|
polling?: PollingYamlConfig;
|
|
|
|
// Integrations (Google Workspace, etc.)
|
|
// NOTE: integrations.google is a legacy path for polling config.
|
|
// Prefer the top-level `polling` section instead.
|
|
integrations?: {
|
|
google?: GoogleConfig;
|
|
};
|
|
|
|
// Transcription (voice messages)
|
|
transcription?: TranscriptionConfig;
|
|
|
|
// Attachment handling
|
|
attachments?: {
|
|
maxMB?: number;
|
|
maxAgeDays?: number;
|
|
};
|
|
|
|
// API server (health checks, CLI messaging)
|
|
api?: {
|
|
port?: number; // Default: 8080 (or PORT env var)
|
|
host?: string; // Default: 127.0.0.1 (secure). Use '0.0.0.0' for Docker/Railway
|
|
corsOrigin?: string; // CORS origin. Default: same-origin only
|
|
};
|
|
}
|
|
|
|
export interface TranscriptionConfig {
|
|
provider: 'openai'; // Only OpenAI supported currently
|
|
apiKey?: string; // Falls back to OPENAI_API_KEY env var
|
|
model?: string; // Defaults to 'whisper-1'
|
|
}
|
|
|
|
export interface PollingYamlConfig {
|
|
enabled?: boolean; // Master switch (default: auto-detected from sub-configs)
|
|
intervalMs?: number; // Polling interval in milliseconds (default: 60000)
|
|
gmail?: {
|
|
enabled?: boolean; // Enable Gmail polling
|
|
account?: string; // Gmail account to poll (e.g., user@example.com)
|
|
};
|
|
}
|
|
|
|
export interface ProviderConfig {
|
|
id: string; // e.g., 'anthropic', 'openai'
|
|
name: string; // e.g., 'lc-anthropic'
|
|
type: string; // e.g., 'anthropic', 'openai'
|
|
apiKey: string;
|
|
}
|
|
|
|
export interface TelegramConfig {
|
|
enabled: boolean;
|
|
token?: string;
|
|
dmPolicy?: 'pairing' | 'allowlist' | 'open';
|
|
allowedUsers?: string[];
|
|
groupPollIntervalMin?: number; // Batch interval in minutes (default: 10, 0 = immediate)
|
|
instantGroups?: string[]; // Group chat IDs that bypass batching
|
|
}
|
|
|
|
export interface SlackConfig {
|
|
enabled: boolean;
|
|
appToken?: string;
|
|
botToken?: string;
|
|
dmPolicy?: 'pairing' | 'allowlist' | 'open';
|
|
allowedUsers?: string[];
|
|
groupPollIntervalMin?: number; // Batch interval in minutes (default: 10, 0 = immediate)
|
|
instantGroups?: string[]; // Channel IDs that bypass batching
|
|
}
|
|
|
|
export interface WhatsAppConfig {
|
|
enabled: boolean;
|
|
selfChat?: boolean;
|
|
dmPolicy?: 'pairing' | 'allowlist' | 'open';
|
|
allowedUsers?: string[];
|
|
groupPolicy?: 'open' | 'disabled' | 'allowlist';
|
|
groupAllowFrom?: string[];
|
|
mentionPatterns?: string[];
|
|
groups?: Record<string, { requireMention?: boolean }>;
|
|
groupPollIntervalMin?: number; // Batch interval in minutes (default: 10, 0 = immediate)
|
|
instantGroups?: string[]; // Group JIDs that bypass batching
|
|
}
|
|
|
|
export interface SignalConfig {
|
|
enabled: boolean;
|
|
phone?: string;
|
|
selfChat?: boolean;
|
|
dmPolicy?: 'pairing' | 'allowlist' | 'open';
|
|
allowedUsers?: string[];
|
|
// Group gating
|
|
mentionPatterns?: string[]; // Regex patterns for mention detection (e.g., ["@bot"])
|
|
groups?: Record<string, { requireMention?: boolean }>; // Per-group settings, "*" for defaults
|
|
groupPollIntervalMin?: number; // Batch interval in minutes (default: 10, 0 = immediate)
|
|
instantGroups?: string[]; // Group IDs that bypass batching
|
|
}
|
|
|
|
export interface DiscordConfig {
|
|
enabled: boolean;
|
|
token?: string;
|
|
dmPolicy?: 'pairing' | 'allowlist' | 'open';
|
|
allowedUsers?: string[];
|
|
groupPollIntervalMin?: number; // Batch interval in minutes (default: 10, 0 = immediate)
|
|
instantGroups?: string[]; // Guild/server IDs or channel IDs that bypass batching
|
|
}
|
|
|
|
export interface GoogleConfig {
|
|
enabled: boolean;
|
|
account?: string;
|
|
services?: string[]; // e.g., ['gmail', 'calendar', 'drive', 'contacts', 'docs', 'sheets']
|
|
pollIntervalSec?: number; // Polling interval in seconds (default: 60)
|
|
}
|
|
|
|
// Default config
|
|
export const DEFAULT_CONFIG: LettaBotConfig = {
|
|
server: {
|
|
mode: 'cloud',
|
|
},
|
|
agent: {
|
|
name: 'LettaBot',
|
|
model: 'zai/glm-4.7', // Free model default
|
|
},
|
|
channels: {},
|
|
};
|