From 2fe5ebe06d6e19ac7d8d04e7c74190d77b8bdd1a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 7 Feb 2026 13:09:05 -0800 Subject: [PATCH] feat: expose polling configuration in lettabot.yaml (#202) Add a top-level `polling` section to lettabot.yaml for configuring background polling (Gmail, etc.) instead of relying solely on env vars. - Add `PollingYamlConfig` type with `enabled`, `intervalMs`, and `gmail` subsection - Update `configToEnv()` to map new polling config to env vars - Update `main.ts` to read from YAML config with env var fallback - Maintain backward compat with `integrations.google` legacy path - Document polling config in docs/configuration.md Fixes #201 Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com> Co-authored-by: Cameron --- docs/configuration.md | 51 +++++++++++++++++++++++++++++++++++++++++++ src/config/io.ts | 14 +++++++++--- src/config/types.ts | 14 ++++++++++++ src/main.ts | 25 ++++++++++++++------- 4 files changed, 93 insertions(+), 11 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index b9ff769..ef20829 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -66,6 +66,14 @@ features: enabled: true intervalMin: 60 +# Polling (background checks for Gmail, etc.) +polling: + enabled: true + intervalMs: 60000 # Check every 60 seconds + gmail: + enabled: true + account: user@example.com + # Voice transcription transcription: provider: openai @@ -181,6 +189,47 @@ features: Enable scheduled tasks. See [Cron Setup](./cron-setup.md). +## Polling Configuration + +Background polling for integrations like Gmail. Runs independently of agent cron jobs. + +```yaml +polling: + enabled: true # Master switch (default: auto-detected from sub-configs) + intervalMs: 60000 # Check every 60 seconds (default: 60000) + gmail: + enabled: true + account: user@example.com # Gmail account to poll +``` + +| Option | Type | Default | Description | +|--------|------|---------|-------------| +| `polling.enabled` | boolean | auto | Master switch. Defaults to `true` if any sub-config is enabled | +| `polling.intervalMs` | number | `60000` | Polling interval in milliseconds | +| `polling.gmail.enabled` | boolean | auto | Enable Gmail polling. Auto-detected from `account` | +| `polling.gmail.account` | string | - | Gmail account to poll for unread messages | + +### Legacy config path + +For backward compatibility, Gmail polling can also be configured under `integrations.google`: + +```yaml +integrations: + google: + enabled: true + account: user@example.com + pollIntervalSec: 60 +``` + +The top-level `polling` section takes priority if both are present. + +### Environment variable fallback + +| Env Variable | Polling Config Equivalent | +|--------------|--------------------------| +| `GMAIL_ACCOUNT` | `polling.gmail.account` | +| `POLLING_INTERVAL_MS` | `polling.intervalMs` | + ## Transcription Configuration Voice message transcription via OpenAI Whisper: @@ -223,5 +272,7 @@ Environment variables override config file values: | `WHATSAPP_SELF_CHAT_MODE` | `channels.whatsapp.selfChat` | | `SIGNAL_PHONE_NUMBER` | `channels.signal.phone` | | `OPENAI_API_KEY` | `transcription.apiKey` | +| `GMAIL_ACCOUNT` | `polling.gmail.account` | +| `POLLING_INTERVAL_MS` | `polling.intervalMs` | See [SKILL.md](../SKILL.md) for complete environment variable reference. diff --git a/src/config/io.ts b/src/config/io.ts index 9b7d506..f030b4f 100644 --- a/src/config/io.ts +++ b/src/config/io.ts @@ -169,11 +169,19 @@ export function configToEnv(config: LettaBotConfig): Record { env.MAX_TOOL_CALLS = String(config.features.maxToolCalls); } - // Integrations - Google (Gmail polling) - if (config.integrations?.google?.enabled && config.integrations.google.account) { + // Polling - top-level polling config (preferred) + if (config.polling?.gmail?.enabled && config.polling.gmail.account) { + env.GMAIL_ACCOUNT = config.polling.gmail.account; + } + if (config.polling?.intervalMs) { + env.POLLING_INTERVAL_MS = String(config.polling.intervalMs); + } + + // Integrations - Google (legacy path for Gmail polling, lower priority) + if (!env.GMAIL_ACCOUNT && config.integrations?.google?.enabled && config.integrations.google.account) { env.GMAIL_ACCOUNT = config.integrations.google.account; } - if (config.integrations?.google?.pollIntervalSec) { + if (!env.POLLING_INTERVAL_MS && config.integrations?.google?.pollIntervalSec) { env.POLLING_INTERVAL_MS = String(config.integrations.google.pollIntervalSec * 1000); } diff --git a/src/config/types.ts b/src/config/types.ts index f4c1498..a5a2176 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -46,7 +46,12 @@ export interface LettaBotConfig { 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; }; @@ -74,6 +79,15 @@ export interface TranscriptionConfig { 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' diff --git a/src/main.ts b/src/main.ts index d34f9cf..33d2075 100644 --- a/src/main.ts +++ b/src/main.ts @@ -287,14 +287,23 @@ const config = { }, // Polling - system-level background checks - polling: { - enabled: !!process.env.GMAIL_ACCOUNT, // Enable if any poller is configured - intervalMs: parseInt(process.env.POLLING_INTERVAL_MS || '60000', 10), // Default 1 minute - gmail: { - enabled: !!process.env.GMAIL_ACCOUNT, - account: process.env.GMAIL_ACCOUNT || '', - }, - }, + // Priority: YAML polling section > YAML integrations.google (legacy) > env vars + polling: (() => { + const gmailAccount = yamlConfig.polling?.gmail?.account + || process.env.GMAIL_ACCOUNT || ''; + const gmailEnabled = yamlConfig.polling?.gmail?.enabled ?? !!gmailAccount; + const intervalMs = yamlConfig.polling?.intervalMs + ?? parseInt(process.env.POLLING_INTERVAL_MS || '60000', 10); + const enabled = yamlConfig.polling?.enabled ?? gmailEnabled; + return { + enabled, + intervalMs, + gmail: { + enabled: gmailEnabled, + account: gmailAccount, + }, + }; + })(), }; // Validate at least one channel is configured