Skip to content

Multi-Session Threads For Telegram - #237

Open
tamircher wants to merge 1 commit into
moazbuilds:masterfrom
tamircher:feat/telegram-parallel-topics
Open

Multi-Session Threads For Telegram#237
tamircher wants to merge 1 commit into
moazbuilds:masterfrom
tamircher:feat/telegram-parallel-topics

Conversation

@tamircher

Copy link
Copy Markdown

Each Telegram topic already gets its own session, and the runner keeps independent per-thread serial queues (threadQueues) — but the Telegram handler gates every incoming message on the global isMainBusy(), so any in-flight run anywhere blocks all topics.

This PR adds per-thread busy tracking in the runner (isThreadBusy/isGlobalBusy) and checks only the target topic's queue (or the global session for non-topic chats). Each topic becomes a fully independent session running in parallel; a second message to the same topic still gets the polite busy reply.

Changes

  • src/runner.ts: per-thread busy set + global counter, maintained in execClaude's entry/finally alongside mainRunCount
  • src/commands/telegram.ts: busy check scoped to the message's sessionKey instead of global

🤖 Generated with Claude Code

Each Telegram topic already gets its own session and the runner keeps
independent per-thread serial queues (threadQueues), but the handler
gated every incoming message on the global isMainBusy() — any in-flight
run anywhere blocked all topics.

Add per-thread busy tracking in the runner (isThreadBusy/isGlobalBusy)
and check only the target topic's queue (or the global session for
non-topic chats), so each topic is a fully independent session running
in parallel. A second message to the same topic still gets the polite
busy reply.

@TerrysPOV TerrysPOV left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review

Found 1 issue:

  1. /kill becomes a cross-topic footgun once parallel topics are enabled. killActive() iterates the global mainActiveProcs set and SIGTERMs every entry — before this PR that set could only ever hold one proc, so kill-all was kill-mine. After this PR, a /kill issued from topic A also terminates the in-flight Claude run in topics B, C, etc. Codex flagged this exact concern on PR #184 ("Track active subprocesses per task before exposing /kill") — the Set was added then, but killActive was never made thread-aware.

killActive is global:

claudeclaw/src/runner.ts

Lines 283 to 295 in fc2b9f6

// outside the main queue and must not be killed by /kill.
const mainActiveProcs = new Set<ReturnType<typeof Bun.spawn>>();
/** Kill all running main-queue claude subprocesses. Returns true if anything was killed. */
export function killActive(): boolean {
if (mainActiveProcs.size === 0) return false;
for (const proc of mainActiveProcs) {
try { proc.kill(); } catch {}
}
mainActiveProcs.clear();
return true;
}

Telegram /kill handler invokes it without scoping to the caller's topic:

if (command === "/kill") {
const killed = killActive();
await sendMessage(config.token, chatId, killed ? "Killed active agent." : "No active agent running.", threadId);
return;
}

Quickest fix: track procs per-thread (e.g. Map<string | "__global__", Set<Proc>> keyed on threadId from the execClaude call site) and have killActive(threadId) only iterate its own bucket. Telegram handler passes the message's sessionKey.

Also missing the mandatory plugin + marketplace version bumps (.claude-plugin/plugin.json and .claude-plugin/marketplace.json). I can maintainer-commit those once the killActive fix lands.

tbertran added a commit to tbertran/claudeclaw that referenced this pull request Jul 19, 2026
killActive() terminates every in-flight main run across all channels and
threads. Matches Telegram's existing contract (moazbuilds#184), not a regression;
thread-scoped kill tracked separately (moazbuilds#237).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants