@gonzih/cc-tg 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,6 +29,7 @@ Open your bot in Telegram and start chatting.
29
29
  | `ANTHROPIC_API_KEY` | yes* | Alternative — API key from console.anthropic.com |
30
30
  | `ALLOWED_USER_IDS` | no | Comma-separated Telegram user IDs. Leave empty to allow anyone |
31
31
  | `CWD` | no | Working directory for Claude Code. Defaults to current directory |
32
+ | `THREAD_CWD_MAP` | no | JSON mapping of forum topic names or IDs to CWD paths (see [Multi-topic sessions](#multi-topic-sessions)) |
32
33
 
33
34
  *One of `CLAUDE_CODE_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN`, or `ANTHROPIC_API_KEY` required.
34
35
 
@@ -118,6 +119,37 @@ Manage the cc-agent MCP server from Telegram without SSH:
118
119
  ### Self-restart
119
120
  `/restart` — spawns a detached child process with the same Node binary and args, sends you a confirmation message, then exits. The new process inherits all environment variables. No SSH required to restart the bot after updates.
120
121
 
122
+ ### Multi-topic sessions
123
+
124
+ When you use cc-tg in a **Telegram group with Topics enabled** (a "Forum" group), each topic gets its own **isolated Claude Code session**. One bot token, one daemon, unlimited isolated project contexts.
125
+
126
+ **How it works:**
127
+ - Session key = `chatId:threadId` for forum topics
128
+ - Session key = `chatId:main` for direct messages and non-topic groups (backward compatible)
129
+ - Commands like `/reset`, `/stop`, `/status` are scoped to the current topic
130
+
131
+ **Setup:**
132
+ 1. Create a Telegram group → Settings → Topics → Enable
133
+ 2. Create topics for each project (e.g. "Simorgh", "LeWM", "EcoClaw")
134
+ 3. Each topic now has its own isolated Claude context
135
+
136
+ **Optional: route topics to different working directories**
137
+
138
+ Set `THREAD_CWD_MAP` to a JSON string mapping topic names (or thread IDs) to absolute paths:
139
+
140
+ ```bash
141
+ THREAD_CWD_MAP='{"Simorgh":"/Users/you/simorgh-app","LeWM":"/Users/you/le-wm","EcoClaw":"/Users/you/ecoclaw"}'
142
+ ```
143
+
144
+ When cc-tg creates a new session for a topic, it looks up the topic name in this map and starts Claude in the corresponding directory. If no match is found, falls back to `CWD`.
145
+
146
+ You can also map by numeric thread ID:
147
+ ```bash
148
+ THREAD_CWD_MAP='{"12345":"/Users/you/project-a","67890":"/Users/you/project-b"}'
149
+ ```
150
+
151
+ If `THREAD_CWD_MAP` is not set, all topics share the same CWD — context isolation still works, just without directory routing.
152
+
121
153
  ### Typing indicator
122
154
  While Claude is working, the bot sends a continuous typing indicator. Works for both regular messages and cron job execution.
123
155
 
package/dist/bot.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Telegram bot that routes messages to/from a Claude Code subprocess.
3
+ * One ClaudeProcess per chat_id — sessions are isolated per user.
4
+ */
5
+ import TelegramBot from "node-telegram-bot-api";
6
+ export interface BotOptions {
7
+ telegramToken: string;
8
+ claudeToken?: string;
9
+ cwd?: string;
10
+ allowedUserIds?: number[];
11
+ groupChatIds?: number[];
12
+ }
13
+ export declare class CcTgBot {
14
+ private bot;
15
+ private sessions;
16
+ private pendingRetries;
17
+ private opts;
18
+ private cron;
19
+ private costStore;
20
+ private botUsername;
21
+ private botId;
22
+ constructor(opts: BotOptions);
23
+ private registerBotCommands;
24
+ /** Session key: "chatId:threadId" for topics, "chatId:main" for DMs/non-topic groups */
25
+ private sessionKey;
26
+ /**
27
+ * Send a message back to the correct thread (or plain chat if no thread).
28
+ * When threadId is undefined, calls sendMessage with exactly 2 args to preserve
29
+ * backward-compatible call signatures (no extra options object).
30
+ */
31
+ private replyToChat;
32
+ /** Parse THREAD_CWD_MAP env var — maps thread name or thread_id to a CWD path */
33
+ private getThreadCwdMap;
34
+ private isAllowed;
35
+ private handleTelegram;
36
+ private handleVoice;
37
+ private handlePhoto;
38
+ private handleDocument;
39
+ private getOrCreateSession;
40
+ private handleClaudeMessage;
41
+ private startTyping;
42
+ private stopTyping;
43
+ private flushPending;
44
+ private trackWrittenFiles;
45
+ private isSensitiveFile;
46
+ private uploadMentionedFiles;
47
+ private extractToolName;
48
+ private runCronTask;
49
+ private handleCron;
50
+ private handleCronEdit;
51
+ /** Find cc-agent PIDs via pgrep. Returns array of numeric PIDs. */
52
+ private findCcAgentPids;
53
+ /** Kill cc-agent PIDs with SIGTERM. Returns the list of killed PIDs. */
54
+ private killCcAgent;
55
+ private handleReloadMcp;
56
+ private handleMcpStatus;
57
+ private handleMcpVersion;
58
+ private handleClearNpxCache;
59
+ private handleRestart;
60
+ private handleGetFile;
61
+ private callCcAgentTool;
62
+ private killSession;
63
+ getMe(): Promise<TelegramBot.User>;
64
+ stop(): void;
65
+ }
66
+ export declare function splitMessage(text: string, maxLen?: number): string[];