feat: Telegram adapter — session lifecycle, memory compaction & crash recovery#86
Open
henrieopenclaw wants to merge 41 commits intoopenabdev:mainfrom
Open
feat: Telegram adapter — session lifecycle, memory compaction & crash recovery#86henrieopenclaw wants to merge 41 commits intoopenabdev:mainfrom
henrieopenclaw wants to merge 41 commits intoopenabdev:mainfrom
Conversation
- Forum supergroups: create a new topic per conversation (session key = chat_id:thread_id) - Messages already in a topic: reuse the existing topic/session - Plain DMs/groups: fall back to reply chains (reply_parameters) - Session isolation: each topic gets its own ACP session
…tion - Fix compaction drain to use classify_notification() instead of msg.result.content[0].text (wrong path; ACP text is in params.update.content.text) - Fix deadlock in cleanup_idle: release connections write lock before awaiting compaction response - Fix deadlock in get_or_create: replace inline summary injection round-trip with pending_context field on AcpConnection; session_prompt prepends it to the first real user prompt — no extra kiro-cli call, no lock contention Alice test passed: kiro correctly recalls user identity and preferences after session eviction and cold resume.
…from tracking - README fully rewritten for Telegram (replaces Discord content) - Added forum supergroup setup guide and Topics enable instructions - TTL constants documented with src/telegram.rs reference - Memory compaction design documented with ASCII flow - PR description updated with compaction design and correct status - handoff.md added to .gitignore (private dev notes) - docs/session-management.md and docs/pr-telegram-topics-idle-cleanup.md included
… not being supported
…ntion replies - Add ChatMode enum (personal/team) to config, default personal - personal: original behavior — any message creates topic, always reply - team: !kiro creates topic (topic_creator_id gated), Kiro listens silently in topics (👀 reaction), replies only on @mention - Add topic_creator_id config field to restrict !kiro to one user - Fetch bot username on startup for @mention detection - Prefix shared-topic messages with [Name]: for Kiro context - Error feedback on topic creation failure and pool exhaustion - Document both modes in config.toml.example
…ck fix - silent_prompt and rename_topic no longer hold the connection write lock while draining the stream (fixes deadlock when @mention arrives during a silent prompt) - plain messages in #general now buffer silently (👀) instead of being dropped - @mention in #general replies in-place without creating a topic - get_or_create_thread returns a per-user general session key for non-!kiro messages instead of bailing, enabling silent + mention flows - update config.toml.example and README with full team/personal mode docs
…ion restart with --model flag
…keyboard, tap sends slash cmd as silent prompt
…timeout - 200ms drain window after end_turn to capture late-arriving text chunks - tokio::select! with 30s alive check — breaks if agent process dies mid-prompt - 30min hard timeout safety net for hung tool calls - fallback message shows tool summary if text response is empty (fixes the morning hang where kiro got stuck and froze all sessions)
chaodu-agent
added a commit
to chaodu-agent/openab
that referenced
this pull request
Apr 7, 2026
Defines ChatAdapter trait, AdapterRouter, and platform-specific implementations for Discord, Telegram, and Slack. Covers: trait design, config format, message size handling, reaction mapping, security, 5 implementation phases. Relates to openabdev#86 openabdev#93
… and resume - stream_prompt now returns timed_out/agent_died flags after releasing the lock - on abnormal exit: partial summary (text_buf + tool_lines) stored in pool.summaries - session evicted via remove_session so next message spawns fresh with context injected - pool.store_partial_summary() added for external callers - works for both personal and team mode (session-key based, mode-agnostic)
- Add crash_history_size config (default 20) to [pool] - SessionPool records last N user messages per session key - cleanup_idle falls back to raw history when compaction fails (crashed session) - History injected as [Recent messages before crash] context on next resume - remove_session/shutdown clean up history
dogzzdogzz
pushed a commit
to dogzzdogzz/openab
that referenced
this pull request
Apr 10, 2026
Introduces a platform-agnostic adapter layer (ChatAdapter trait + AdapterRouter) that decouples session management, streaming, and reactions from any specific chat platform. Refactors Discord support to implement this trait and adds a new Slack adapter using Socket Mode (WebSocket) with auto-reconnect. - Extract ChatAdapter trait with send/edit/thread/react methods + message_limit() - Extract AdapterRouter with shared session routing, edit-streaming, and reactions - Decouple StatusReactionController from serenity types (uses Arc<dyn ChatAdapter>) - Implement DiscordAdapter (ChatAdapter for Discord via serenity) - Implement SlackAdapter (ChatAdapter for Slack via reqwest + tokio-tungstenite) - Add [slack] config section (bot_token, app_token, allowed_channels, allowed_users) - Support running Discord + Slack simultaneously in one process - Session keys namespaced by platform (discord:xxx, slack:xxx) - Unicode emoji → Slack short name mapping for reactions Relates to openabdev#93, openabdev#94, openabdev#86 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… passthrough - Add ContentBlock enum (Text/Image) matching upstream openabdev/openab openabdev#158 interface — compatible with ACP wire format, re-exported from crate::acp - Fix session/new and session/load passing mcpServers: [] (empty) — now reads from [agent.mcp_servers] config, enabling markitdown and other MCP tools to be available in kiro sessions - Add McpServerConfig to config.rs with name/command/args/env fields - Add mcp_servers_json() helper on SessionPool - Update config.toml.example with MCP server documentation
…image path - Add src/media.rs with MediaInput enum and resolve() transform layer - Image: resize to max 1200px (Lanczos3), re-encode JPEG, vision model gate - GIF passes through unchanged; resize failure falls back to original bytes - session_prompt() now takes Vec<ContentBlock> instead of Option<(Vec<u8>, String)> - Model gate (claude/auto only) applied inside stream_prompt via conn.current_model_id - Add current_model_id field to AcpConnection, populated from session/new response - Add image crate dependency (jpeg/png/gif/webp, no default features) - 22/22 tests passing
…sion model warning - Fix: image-only messages (no caption) were dropped by empty prompt guard - Add [image] placeholder prompt when caption is empty so kiro knows media arrived - Warn user with model name when image dropped due to non-vision model - Image in #General (team mode) now creates topic + replies (not silent)
…ll-out - Add MediaInput::Document variant to media.rs - resolve() is now async — markitdown runs as subprocess via tokio::process::Command - Writes to tempfile (original filename preserved for format detection) - 60s timeout, 20MB size limit, fallback ContentBlock::Text on any error - Documents in #General create a topic (same as images) - [file] placeholder prompt when document sent with no caption - Add tempfile dependency - 23/23 tests passing
- rename_topic now receives effective_prompt ([file]/[image] fallback) instead of empty prompt string when no caption provided - New topics from documents get 📄 placeholder, images keep 📷
markitdown CLI required for document pipeline (MediaInput::Document). Runs as on-demand subprocess — no persistent service, no idle cost.
dogzzdogzz
pushed a commit
to dogzzdogzz/openab
that referenced
this pull request
Apr 12, 2026
Introduces a platform-agnostic adapter layer (ChatAdapter trait + AdapterRouter) that decouples session management, streaming, and reactions from any specific chat platform. Refactors Discord support to implement this trait and adds a new Slack adapter using Socket Mode (WebSocket) with auto-reconnect. - Extract ChatAdapter trait with send/edit/thread/react methods + message_limit() - Extract AdapterRouter with shared session routing, edit-streaming, and reactions - Decouple StatusReactionController from serenity types (uses Arc<dyn ChatAdapter>) - Implement DiscordAdapter (ChatAdapter for Discord via serenity) - Implement SlackAdapter (ChatAdapter for Slack via reqwest + tokio-tungstenite) - Add [slack] config section (bot_token, app_token, allowed_channels, allowed_users) - Support running Discord + Slack simultaneously in one process - Session keys namespaced by platform (discord:xxx, slack:xxx) - Unicode emoji → Slack short name mapping for reactions Relates to openabdev#93, openabdev#94, openabdev#86 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
dogzzdogzz
pushed a commit
to dogzzdogzz/openab
that referenced
this pull request
Apr 12, 2026
Introduces a platform-agnostic adapter layer (ChatAdapter trait + AdapterRouter) that decouples session management, streaming, and reactions from any specific chat platform. Refactors Discord support to implement this trait and adds a new Slack adapter using Socket Mode (WebSocket) with auto-reconnect. - Extract ChatAdapter trait with send/edit/thread/react methods + message_limit() - Extract AdapterRouter with shared session routing, edit-streaming, and reactions - Decouple StatusReactionController from serenity types (uses Arc<dyn ChatAdapter>) - Implement DiscordAdapter (ChatAdapter for Discord via serenity) - Implement SlackAdapter (ChatAdapter for Slack via reqwest + tokio-tungstenite) - Add [slack] config section (bot_token, app_token, allowed_channels, allowed_users) - Support running Discord + Slack simultaneously in one process - Session keys namespaced by platform (discord:xxx, slack:xxx) - Unicode emoji → Slack short name mapping for reactions Relates to openabdev#93, openabdev#94, openabdev#86 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #60. Full Telegram adapter replacing Discord, plus team/personal chat modes.
Architecture
graph LR U(["👤 Telegram User"]) <-->|Bot API| AB["agent-broker (Rust)"] AB <-->|"ACP stdio JSON-RPC"| CLI["kiro-cli / claude / codex / gemini"]Chat Modes
#general@mentionin#general!kiroin#generaltopic_creator_id)@mentionin topicSession Lifecycle
flowchart TD M([User message]) --> GC[get_or_create] GC -->|alive| USE[use existing session] GC -->|dead/new| SP[spawn CLI] SP --> SN[session/new or session/load] SN --> PC{pending_context?} PC -->|yes| PP[prepend summary] PC -->|no| ST PP --> ST[stream_prompt] ST --> PD[prompt_done] PD --> CI[cleanup_idle every 15min] CI --> IT{idle > TTL?} IT -->|yes| CO[compact → evict → notify] CO --> SS[summary stored, injected on resume]Memory Management
Idle Eviction
flowchart TD A([User idle for 2 hours]) --> B[cleanup_idle detects idle > TTL] B --> C[Send compaction prompt to live kiro process] C --> D[Receive summary → store in summaries] D --> E[Kill kiro process, notify user ⏱] E --> F([User sends next message]) F --> G[Spawn new kiro → inject summary] G --> H[Kiro remembers previous conversation ✅]Crash Recovery
flowchart TD A([User sends message]) --> B[record_user_message → VecDeque max 20] B --> C{... kiro crashes ...} C --> D[cleanup_idle detects !alive] D --> E[Attempt compaction → fails] E --> F[Fallback: VecDeque → Recent messages before crash] F --> G[Store in summaries] G --> H([User sends next message]) H --> I[Spawn new kiro → inject crash context] I --> J[Kiro recalls recent context ✅ partial memory]Key changes
teloxide)personalvsteammode viaconfig.tomlsilent_prompt/rename_topicno longer hold write lock during streamallowed_usersis emptyKnown limitations (marked as WORKAROUND in code)
stream_promptstill holds the write lock for its duration — a hung task blocks other messages until timeout fires. Proper fix requires lock-free streaming (same pattern assilent_prompt).