feat: implement /kill and auto-clean dead topic state#81
Open
DefaultPerson wants to merge 1 commit into
Open
Conversation
/kill was registered only as a BotCommand menu hint with no handler, so it fell through to forward_command_handler and was sent into Claude Code as a slash command. Wire up an actual kill_command that kills the tmux window, drops the binding, purges window state, removes the session_map entry, and deletes the Telegram topic. Also fix accumulating orphan state when topics die outside /kill: - session.purge_window / remove_session_map_entry / cleanup_dead_topic - topic_closed_handler now invokes the same purge path - status_polling probe accepts both Topic_id_invalid and Message thread not found (interval lowered 60s -> 5s) - send_with_fallback / safe_send react to those markers immediately — needed because unpinAllForumTopicMessages returns ok=true for private chats with arbitrary thread_ids, so the probe alone cannot detect a deleted topic in DM mode restart.sh now sweeps any \$VENV/bin/ccbot processes outside the target pane to prevent multiple instances racing the same bot token.
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.
Summary
/killwas advertised as aBotCommandmenu entry but had no handler — thecatch-all
MessageHandler(filters.COMMAND, ...)forwarded the literal text/killinto the Claude Code TUI. This PR adds the handler and, along the way,fixes the orphan-state buildup that affects every path where a topic dies
(close, delete,
/kill, dead window).Background
When a window goes away, three state files can retain stale entries:
state.json—window_states,window_display_names,user_window_offsetssession_map.json— Claude Code'sSessionStarthook writes it but emits no"session ended" event
monitor_state.jsonThe 60s probe in
status_pollingonly matchedTopic_id_invalid. In privatechats Telegram returns
ok=truefromunpinAllForumTopicMessagesregardless ofmessage_thread_id, so DM-mode topic deletions are never detected via the probeand the worker logs
Failed to send message: Message thread not foundonce persecond indefinitely.
Changes
bot.kill_command— kills the tmux window, drops the binding, purgeswindow state, removes the
session_map.jsonentry, and callsdelete_forum_topic. Registered before the catch-allMessageHandler.session.SessionManager— addspurge_window,remove_session_map_entry, andcleanup_dead_topic. Reused bykill_command,topic_closed_handler, and thestatus_pollingcleanuppaths.
status_polling— probe matches bothTopic_id_invalidandMessage thread not found; interval lowered from 60s to 5s.message_sender.send_with_fallback/safe_send— on a finalBadRequestcontaining either marker, callsession_manager.cleanup_dead_topic(chat_id, thread_id). This is the onlypath that detects DM-mode topic deletion.
scripts/restart.sh— sweeps any.venv/bin/ccbotprocesses outside thetarget tmux pane. Multiple instances polling the same bot token produce
Conflict: terminated by other getUpdates requestand silently break commandrouting.
ruff formatfix inbot.pyfor a pre-existingviolation that broke
ruff format --checkonmain.Test plan
uv run ruff check src/ tests/andruff format --check src/ tests/uv run pyright src/ccbot/— no new errors (two pre-existingresolved_chatF821errors at lines 1144/1522 are untouched)uv run pytest -q— 240 passed (test_kill_command.pyadds 5 cases);one pre-existing unrelated failure on
test_format_tool_result_text[Write]/killin a bound topic kills the window, deletes the topic,purges all three state files
via the send-error path
restart.shkills a stray ccbot instance running in anothertmux server