feat: streaming command UI improvements#48
Open
chinkan wants to merge 53 commits into
Open
Conversation
…ting - Show command text in verbose tool notification (remove 'command' from sensitive keys, add to SAFE_KEYS) - Add truncate_tail utility for command output display - Add RunningCommand registry and interactive command execution with cancel button via inline keyboard callback - Wire cancel_cmd:* callback handler in Telegram - Retroactively format split streaming messages with entities - Convert all command responses to entity-based send_markdown_message - Add blockquote and table support to markdown_to_entities
…command output The select! loop in execute_command_interactive races child.wait() against the spawned pipe reader tasks. When the child exits quickly, child.wait() resolves before the readers have flushed pipe data through the mpsc channel, producing a result of just "Exit code: 0" with no output. Fix: capture JoinHandle from each spawned reader, then after the select loop exits, await both handles and drain remaining channel data with try_recv() before building the result. This guarantees the output buffer is complete, with no borrow conflicts or cancel-safety issues. Also: fix pre-existing clippy issue in markdown_entities.rs where in_table_cell flag had identical handling to the else branch.
…cate body formatting Changes per code-quality-reviewer PASS_WITH_CONCERNS: - Remove 250ms timeout around post-loop tokio::join!(handles) — any timeout reintroduces a race window where try_recv could miss late chunks. Readers finish within microseconds after pipe EOF, so no timeout is needed. - Remove pre-drain edit_message_text calls in select branches — only update display once after drain with complete output (avoids flicker and duplicate API calls). - Extract format_body() helper to deduplicate the output-formatting pattern that appeared 4 times. - Replace unreachable else with unreachable!().
…ation Root causes: - Double answer_callback_query: first answer (no text, unconditional) swallowed the '⛔ Command cancelled' toast. Telegram only honors the first answer per callback_id. If the first answer failed (used ?), the cancel handler never ran. - child.kill() only killed sh, not descendants of sh -c. - edit_message_text failures were silently swallowed by .ok(). Fixes: 1. telegram.rs: Remove unconditional answer at fn entry. Each branch answers exactly once with appropriate text. Cancel branch now shows the toast. Non-cancel branches use silent answers. 2. agent.rs: Add .process_group(0) to spawn so sh -c gets its own process group. On cancel, call nix::sys::signal::killpg() to send SIGKILL to the entire process group, killing both sh and all descendant processes. 3. agent.rs: Replace .ok() with if-let Err + warn! on all three edit_message_text calls so API failures are logged. 4. tests/command_cancel.rs: Add integration tests for process-group killpg and oneshot-cancel-in-select-loop patterns.
…o subagent loops, ask_parallel
…t, add design docs
Three independent features:
(A) Markdown entities upgrade (src/utils/markdown_entities.rs)
- Blockquote entity via Bot API 7.0+ MessageEntityKind::Blockquote
- Spoiler (||text||) and Underline (<u>text</u>) via PUA sentinel pre-processing
- List formatting: unordered gets \u{2022} bullet, ordered gets 1./2. numbering
(B) Lightweight /btw (src/agent.rs, src/platform/telegram.rs)
- Replaces heavy ask_parallel with ask_parallel_lightweight
- Single LLM call, no tools, no agentic loop, zero lock contention
(C) Steer messages (src/agent.rs, src/platform/telegram.rs)
- MidRunMode enum (Steer/Queue) with memory persistence
- /mode command to toggle between modes
- Injection point moved to pre-LLM-call with mode-aware formatting
- Steer: ephemeral injection; Queue: persisted injection
- /clear also resets mid-run mode
…ions, fallback clarity
…helper, continue save, test
…::new enabled param, _iteration naming
…un_at timing, friendly_tool_name
…background runner
Three fixes for the /btw command:
1. **Model ID bug**: Switched from (which passed the provider
name 'openrouter' as the model string) to
with the agent's
(e.g. 'openrouter/qwen/qwen3-235b-a22b').
2. **True parallelism**: Added to teloxide's
Dispatcher that returns for commands (bypass per-chat
serialization) and for regular messages (preserve
ordering). This fixes the root cause — teloxide's default groups
ALL updates by chat, processing them sequentially.
3. **DB ops in spawned task**: Moved and
into the block so the
handler returns immediately after sending the acknowledgment.
…ionManager, AgenticLoop from Agent god module
M1: CancelRegistry, PlatformSender trait, ToolHandler+T哪怕是ToolRegistry, TelegramAdapter,
BuiltinTools, MemoryTools, SchedulingTools, SkillTools, CommandTool handlers
M2: ConversationManager with compaction, RAG injection, steer application
M3: AgenticLoop loop runner with MessageContainer for dual main/subagent paths
M4: Supervisor ADR, seed::write_lock helper
Bug fixes:
- conversation.rs: use get_or_create_conversation instead of fake ID format
- llm.rs: use default_qualified_model instead of default_provider_name
Critical fixes from code review:
- AgenticLoop::run now receives real user_id/chat_id (not empty strings)
- process_message passes MessageContainer::Conversation to keep compaction live
- Compaction, loop detection, interactive callback re-enabled in main loop
- RAG context injected via inject_rag_context
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.
This PR adds extensive improvements to the streaming command UI:
Key Features:
Technical Improvements: