@gonzih/cc-tg 0.2.19 → 0.2.21

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/dist/bot.d.ts CHANGED
@@ -38,6 +38,7 @@ export declare class CcTgBot {
38
38
  /** Kill cc-agent PIDs with SIGTERM. Returns the list of killed PIDs. */
39
39
  private killCcAgent;
40
40
  private handleReloadMcp;
41
+ private handleMcpStatus;
41
42
  private handleMcpVersion;
42
43
  private handleClearNpxCache;
43
44
  private handleRestart;
package/dist/bot.js CHANGED
@@ -20,6 +20,7 @@ const BOT_COMMANDS = [
20
20
  { command: "help", description: "Show all available commands" },
21
21
  { command: "cron", description: "Manage cron jobs — add/list/edit/remove/clear" },
22
22
  { command: "reload_mcp", description: "Restart the cc-agent MCP server process" },
23
+ { command: "mcp_status", description: "Check MCP server connection status" },
23
24
  { command: "mcp_version", description: "Show cc-agent npm version and npx cache info" },
24
25
  { command: "clear_npx_cache", description: "Clear npx cache and restart MCP to pick up latest version" },
25
26
  { command: "restart", description: "Restart the bot process in-place" },
@@ -236,6 +237,11 @@ export class CcTgBot {
236
237
  await this.handleReloadMcp(chatId);
237
238
  return;
238
239
  }
240
+ // /mcp_status — run `claude mcp list` and show connection status
241
+ if (text === "/mcp_status") {
242
+ await this.handleMcpStatus(chatId);
243
+ return;
244
+ }
239
245
  // /mcp_version — show published npm version and cached npx entries
240
246
  if (text === "/mcp_version") {
241
247
  await this.handleMcpVersion(chatId);
@@ -454,7 +460,12 @@ export class CcTgBot {
454
460
  });
455
461
  }
456
462
  // Hybrid file upload: find files mentioned in result text that Claude actually wrote
457
- this.uploadMentionedFiles(chatId, text, session);
463
+ try {
464
+ this.uploadMentionedFiles(chatId, text, session);
465
+ }
466
+ catch (err) {
467
+ console.error(`[tg:${chatId}] uploadMentionedFiles error:`, err.message);
468
+ }
458
469
  }
459
470
  trackWrittenFiles(msg, session, cwd) {
460
471
  // Only look at assistant messages with tool_use blocks
@@ -608,7 +619,13 @@ export class CcTgBot {
608
619
  console.log(`[claude:files] skipping sensitive file: ${filePath}`);
609
620
  continue;
610
621
  }
611
- const fileSize = statSync(filePath).size;
622
+ let fileSize;
623
+ try {
624
+ fileSize = statSync(filePath).size;
625
+ }
626
+ catch {
627
+ continue; // file disappeared between existsSync and statSync
628
+ }
612
629
  const MAX_TG_FILE_BYTES = 50 * 1024 * 1024;
613
630
  if (fileSize > MAX_TG_FILE_BYTES) {
614
631
  const mb = (fileSize / (1024 * 1024)).toFixed(1);
@@ -660,7 +677,13 @@ export class CcTgBot {
660
677
  output += text;
661
678
  const result = output.trim();
662
679
  if (result) {
663
- const footer = formatCronCostFooter(cronUsage);
680
+ let footer = "";
681
+ try {
682
+ footer = formatCronCostFooter(cronUsage);
683
+ }
684
+ catch (err) {
685
+ console.error(`[cron] cost footer error:`, err.message);
686
+ }
664
687
  const chunks = splitMessage(`🕐 ${result}${footer}`);
665
688
  (async () => {
666
689
  for (const chunk of chunks) {
@@ -841,12 +864,30 @@ export class CcTgBot {
841
864
  return pids;
842
865
  }
843
866
  async handleReloadMcp(chatId) {
867
+ await this.bot.sendMessage(chatId, "Clearing npx cache and reloading MCP...");
868
+ try {
869
+ const home = process.env.HOME ?? "~";
870
+ execSync(`rm -rf "${home}/.npm/_npx/"`, { encoding: "utf8", shell: "/bin/sh" });
871
+ console.log("[mcp] cleared ~/.npm/_npx/");
872
+ }
873
+ catch (err) {
874
+ await this.bot.sendMessage(chatId, `Warning: failed to clear npx cache: ${err.message}`);
875
+ }
844
876
  const pids = this.killCcAgent();
845
877
  if (pids.length === 0) {
846
- await this.bot.sendMessage(chatId, "No cc-agent process found. MCP will start fresh on the next agent call.");
878
+ await this.bot.sendMessage(chatId, "NPX cache cleared. No cc-agent process found MCP will start fresh on the next agent call.");
847
879
  return;
848
880
  }
849
- await this.bot.sendMessage(chatId, `Sent SIGTERM to cc-agent (pid${pids.length > 1 ? "s" : ""}: ${pids.join(", ")}).\nMCP restarted. New process will load on next agent call.`);
881
+ await this.bot.sendMessage(chatId, `NPX cache cleared. Sent SIGTERM to cc-agent (pid${pids.length > 1 ? "s" : ""}: ${pids.join(", ")}).\nMCP restarted. New process will load on next agent call.`);
882
+ }
883
+ async handleMcpStatus(chatId) {
884
+ try {
885
+ const output = execSync("claude mcp list", { encoding: "utf8", shell: "/bin/sh" }).trim();
886
+ await this.bot.sendMessage(chatId, `MCP server status:\n\n${output || "(no output)"}`);
887
+ }
888
+ catch (err) {
889
+ await this.bot.sendMessage(chatId, `Failed to run claude mcp list: ${err.message}`);
890
+ }
850
891
  }
851
892
  async handleMcpVersion(chatId) {
852
893
  let npmVersion = "unknown";
package/dist/claude.js CHANGED
@@ -107,38 +107,40 @@ export class ClaudeProcess extends EventEmitter {
107
107
  for (const line of lines) {
108
108
  if (!line.trim())
109
109
  continue;
110
+ let raw;
110
111
  try {
111
- const raw = JSON.parse(line);
112
- // Emit usage events from Anthropic API stream events passed through by Claude CLI
113
- if (raw.type === "message_start") {
114
- const usage = (raw.message?.usage);
115
- if (usage) {
116
- this.emit("usage", {
117
- inputTokens: usage.input_tokens ?? 0,
118
- outputTokens: 0, // output_tokens at message_start is always 0
119
- cacheReadTokens: usage.cache_read_input_tokens ?? 0,
120
- cacheWriteTokens: usage.cache_creation_input_tokens ?? 0,
121
- });
122
- }
123
- }
124
- else if (raw.type === "message_delta") {
125
- const usage = raw.usage;
126
- if (usage?.output_tokens) {
127
- this.emit("usage", {
128
- inputTokens: 0,
129
- outputTokens: usage.output_tokens,
130
- cacheReadTokens: 0,
131
- cacheWriteTokens: 0,
132
- });
133
- }
134
- }
135
- const msg = this.parseMessage(raw);
136
- if (msg)
137
- this.emit("message", msg);
112
+ raw = JSON.parse(line);
138
113
  }
139
114
  catch {
140
115
  // Non-JSON line (startup noise etc.) — ignore
116
+ continue;
117
+ }
118
+ // Emit usage events from Anthropic API stream events passed through by Claude CLI
119
+ if (raw.type === "message_start") {
120
+ const usage = (raw.message?.usage);
121
+ if (usage) {
122
+ this.emit("usage", {
123
+ inputTokens: usage.input_tokens ?? 0,
124
+ outputTokens: 0, // output_tokens at message_start is always 0
125
+ cacheReadTokens: usage.cache_read_input_tokens ?? 0,
126
+ cacheWriteTokens: usage.cache_creation_input_tokens ?? 0,
127
+ });
128
+ }
129
+ }
130
+ else if (raw.type === "message_delta") {
131
+ const usage = raw.usage;
132
+ if (usage?.output_tokens) {
133
+ this.emit("usage", {
134
+ inputTokens: 0,
135
+ outputTokens: usage.output_tokens,
136
+ cacheReadTokens: 0,
137
+ cacheWriteTokens: 0,
138
+ });
139
+ }
141
140
  }
141
+ const msg = this.parseMessage(raw);
142
+ if (msg)
143
+ this.emit("message", msg);
142
144
  }
143
145
  }
144
146
  parseMessage(raw) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gonzih/cc-tg",
3
- "version": "0.2.19",
3
+ "version": "0.2.21",
4
4
  "description": "Claude Code Telegram bot — chat with Claude Code via Telegram",
5
5
  "type": "module",
6
6
  "bin": {