diff --git a/src/index.ts b/src/index.ts index d6c8124..f97d525 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,7 +19,7 @@ async function main(): Promise { console.log('[App] Starting Remote Coding Agent (Telegram + Claude MVP)'); // Validate required environment variables - const required = ['DATABASE_URL', 'TELEGRAM_BOT_TOKEN']; + const required = ['DATABASE_URL']; const missing = required.filter(v => !process.env[v]); if (missing.length > 0) { console.error('[App] Missing required environment variables:', missing.join(', ')); @@ -27,6 +27,14 @@ async function main(): Promise { process.exit(1); } + // Validate at least one platform adapter is configured + const hasTelegram = !!process.env.TELEGRAM_BOT_TOKEN; + const hasGitHub = process.env.GITHUB_TOKEN && process.env.WEBHOOK_SECRET; + if (!hasTelegram && !hasGitHub) { + console.error('[App] No platform adapters configured. Set TELEGRAM_BOT_TOKEN or GITHUB_TOKEN+WEBHOOK_SECRET.'); + process.exit(1); + } + // Validate AI assistant credentials (warn if missing, don't fail) const hasClaudeCredentials = process.env.CLAUDE_API_KEY || process.env.CLAUDE_CODE_OAUTH_TOKEN; const hasCodexCredentials = process.env.CODEX_ID_TOKEN && process.env.CODEX_ACCESS_TOKEN; @@ -169,34 +177,41 @@ async function main(): Promise { console.log(`[Express] Health check server listening on port ${port}`); }); - // Initialize platform adapter (Telegram) - const streamingMode = (process.env.TELEGRAM_STREAMING_MODE || 'stream') as 'stream' | 'batch'; - const telegram = new TelegramAdapter(process.env.TELEGRAM_BOT_TOKEN!, streamingMode); + // Initialize Telegram adapter (conditional) + let telegram: TelegramAdapter | null = null; + if (process.env.TELEGRAM_BOT_TOKEN) { + const streamingMode = (process.env.TELEGRAM_STREAMING_MODE || 'stream') as 'stream' | 'batch'; + telegram = new TelegramAdapter(process.env.TELEGRAM_BOT_TOKEN, streamingMode); - // Handle text messages - telegram.getBot().on('text', async ctx => { - const conversationId = telegram.getConversationId(ctx); - const message = ctx.message.text; + // Handle text messages + telegram.getBot().on('text', async ctx => { + const conversationId = telegram!.getConversationId(ctx); + const message = ctx.message.text; - if (!message) return; + if (!message) return; - // Fire-and-forget: handler returns immediately, processing happens async - lockManager - .acquireLock(conversationId, async () => { - await handleMessage(telegram, conversationId, message); - }) - .catch(error => { - console.error('[Telegram] Failed to process message:', error); - }); - }); + // Fire-and-forget: handler returns immediately, processing happens async + lockManager + .acquireLock(conversationId, async () => { + await handleMessage(telegram!, conversationId, message); + }) + .catch(error => { + console.error('[Telegram] Failed to process message:', error); + }); + }); - // Start bot - await telegram.start(); + // Start bot + await telegram.start(); + } else { + console.log('[Telegram] Adapter not initialized (missing TELEGRAM_BOT_TOKEN)'); + } // Graceful shutdown const shutdown = (): void => { console.log('[App] Shutting down gracefully...'); - telegram.stop(); + if (telegram) { + telegram.stop(); + } pool.end().then(() => { console.log('[Database] Connection pool closed'); process.exit(0); @@ -207,7 +222,12 @@ async function main(): Promise { process.once('SIGTERM', shutdown); console.log('[App] Remote Coding Agent is ready!'); - console.log('[App] Send messages to your Telegram bot to get started'); + if (telegram) { + console.log('[App] Telegram bot is active - send messages to get started'); + } + if (github) { + console.log('[App] GitHub webhook endpoint active at /webhooks/github'); + } console.log('[App] Test endpoint available: POST http://localhost:' + port + '/test/message'); }