RateLimiter.cleanupLoop() runs a background goroutine that never
terminates. When SetRateLimitCfg() is called (e.g. during config
reload), a new RateLimiter is created with a new goroutine, but the
old goroutine keeps running forever — a goroutine leak.
Add a stop channel and Stop() method to RateLimiter. Call Stop() on the
previous limiter in SetRateLimitCfg() and in Engine.Stop() to ensure
clean shutdown.
Streaming Preview:
- Real-time message preview during agent response (like "typing" indicator)
- Supported on Telegram, Discord, and Feishu
- Configurable interval, min delta chars, and max preview length
Rate Limiting:
- Per-session sliding-window rate limiter
- Prevents users from flooding the bot with messages
- Configurable max messages and window size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>