Split long AI responses into multiple platform messages during streaming
instead of truncating them. The manager counts accumulated delta runes
and opens a new stream when approaching the platform's TextChunkLimit.
Uses a soft/hard limit strategy that prefers splitting at sentence ends
or line breaks over cutting mid-sentence.
- Add pushDelta with soft (75%) / hard (100%) limit and natural break
point detection
- Add splitStream, pushFinalAfterSplit, pushFinalWithChunking helpers
- Fix Discord adapter to use RuneCount Message Length
- Add tests for delta splitting, natural breaks, and final handling
* feat(telegram): use sendMessageDraft for streaming in private chats
Use Telegram Bot API 9.3's sendMessageDraft to stream partial messages
with smooth animation in private chats, replacing the sendMessage +
editMessageText approach. Group/channel chats keep the existing
edit-based streaming.
- Add sendTelegramDraft() for the sendMessageDraft API
- Detect private chats via conversation_type metadata in OpenStream
- Use 300ms throttle for drafts (vs 5s for edits)
- Send permanent messages at tool call boundaries and on final event
- Reset buffer atomically in StreamEventFinal to prevent duplicate
messages when multiple final events fire (one per assistant output)
* test(telegram): improve draft mode test assertions
Add sendTextForTest hook for sendTelegramTextReturnMessage to enable
direct assertion of send calls. Clean up residual unused variables
and replace indirect assertions with explicit mock-based verification.
Allow configuring a custom Telegram Bot API base URL (`apiBaseURL`) per
channel, enabling users behind restricted networks to route requests
through a reverse proxy (e.g. Nginx, Cloudflare Workers).
Both API calls and file downloads respect the configured endpoint.
When omitted, the official https://api.telegram.org is used.
Closes#159
Add ProcessingStatusNotifier implementation: show 👀 reaction while
processing, remove on completion/failure. Fix isReplyToBot to match
only the current bot (bot.Self.ID) instead of any bot, preventing
multiple bots from responding to the same reply. Add rune-safe text
truncation for Telegram message length limit.
Strip invalid UTF-8 byte sequences in sendTelegramTextReturnMessage and
editTelegramMessageText to prevent "text must be encoded in UTF-8" errors
that abort the stream mid-response.
Catch unique constraint violation (SQLSTATE 23505) during route creation
in ResolveConversation and fall back to Find, preventing duplicate key
errors when concurrent inbound messages hit the same chat simultaneously.
Add shared IsUniqueViolation helper to internal/db.
Increase edit throttle from 250ms to 1500ms to respect Telegram per-chat limits,
remove newline bypass that effectively disabled throttling, add dedicated
editStreamMessageFinal with retry for final message delivery, and simplify
editTelegramMessageText by removing blocking sleep in favor of caller-level retry.
- Treat 400 "message is not modified" as success to avoid user-facing error
- On 429: sleep retry_after and retry once in editTelegramMessageText;
stream backs off lastEditedAt and returns nil
- Require error code 400 for message-not-modified check; add production
error string to unit tests
- Lower base throttle to 250ms; add test hooks and tests for 429 retry
and stream backoff
Propagate conversation type (direct/group/thread) from channel adapters
all the way to the agent prompt. Store conversation_type on bot_channel_routes
so the bot knows whether a message originates from a p2p chat, group, or thread.
Schema changes are folded into the 0001 init migration (destructive update).
Merge upstream fx refactor and adapt all services to use go.uber.org/fx
for dependency injection. Resolve conflicts in main.go, server.go,
and service constructors while preserving our domain model changes.
- Fix telegram adapter panic on shutdown (double close channel)
- Fix feishu adapter processing messages after stop
- Increase directory lookup timeout from 2s to 5s
- Rename chat module to conversation with flow-based architecture
- Move channelidentities into channel/identities subpackage
- Add channel/route for routing logic
- Add message service with event hub
- Add MCP providers: container, directory, schedule
- Refactor Feishu/Telegram adapters with directory and stream support
- Add platform management page and channel badges in web UI
- Update database schema for conversations, messages and channel routes
- Add @memoh/shared package for cross-package type definitions
Align channel identity and bind flow across backend and app-facing layers, including generated swagger artifacts and package lock updates while excluding docs content changes.
- Refactor channel manager with support for Sender/Receiver interfaces and hot-swappable adapters.
- Implement identity routing and pre-authentication logic for inbound messages.
- Update database schema to support bot pre-auth keys and extended channel session metadata.
- Add Telegram and Feishu channel configuration and adapter enhancements.
- Update Swagger documentation and internal handlers for channel management.
Co-authored-by: Cursor <cursoragent@cursor.com>
Major changes:
1. Core Architecture: Decoupled Bots from Users. Bots now have independent lifecycles, member management (bot_members), and dedicated configurations.
2. Channel Gateway:
- Implemented a unified Channel Manager supporting Feishu, Telegram, and Local (Web/CLI) adapters.
- Added message processing pipeline to normalize interactions across different platforms.
- Introduced a Contact system for identity binding and guest access policies.
3. Database & Tooling:
- Consolidated all migrations into 0001_init with updated schema for bots, channels, and contacts.
- Optimized sqlc.yaml to automatically track the migrations directory.
4. Agent Enhancements:
- Introduced ToolContext to provide Agents with platform-aware execution capabilities (e.g., messaging, contact lookups).
- Added tool logging and fallback mechanisms for toolChoice execution.
5. UI & Docs: Updated frontend stores, UI components, and Swagger documentation to align with the new Bot-centric model.