@gonzih/cc-tg 0.9.15 → 0.9.17

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/tokens.js ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * OAuth token pool management.
3
+ *
4
+ * Supports CLAUDE_CODE_OAUTH_TOKENS (comma-separated list of tokens).
5
+ * Falls back to CLAUDE_CODE_OAUTH_TOKEN for single-token / backwards compat.
6
+ */
7
+ let tokens = [];
8
+ let currentIndex = 0;
9
+ let initialized = false;
10
+ /**
11
+ * Load tokens from env vars. Called on startup; also re-callable in tests.
12
+ * Priority: CLAUDE_CODE_OAUTH_TOKENS > CLAUDE_CODE_OAUTH_TOKEN > (empty)
13
+ */
14
+ export function loadTokens() {
15
+ const multi = process.env.CLAUDE_CODE_OAUTH_TOKENS;
16
+ if (multi) {
17
+ tokens = multi.split(",").map((t) => t.trim()).filter(Boolean);
18
+ }
19
+ else {
20
+ const single = process.env.CLAUDE_CODE_OAUTH_TOKEN;
21
+ tokens = single ? [single] : [];
22
+ }
23
+ currentIndex = 0;
24
+ initialized = true;
25
+ return tokens;
26
+ }
27
+ function ensureInitialized() {
28
+ if (!initialized)
29
+ loadTokens();
30
+ }
31
+ /** Returns the current active token, or empty string if none configured. */
32
+ export function getCurrentToken() {
33
+ ensureInitialized();
34
+ return tokens[currentIndex] ?? "";
35
+ }
36
+ /**
37
+ * Advance to the next token (wraps around).
38
+ * Returns the new current token.
39
+ */
40
+ export function rotateToken() {
41
+ ensureInitialized();
42
+ if (tokens.length === 0)
43
+ return "";
44
+ currentIndex = (currentIndex + 1) % tokens.length;
45
+ return tokens[currentIndex];
46
+ }
47
+ /** Zero-based index of the current token. */
48
+ export function getTokenIndex() {
49
+ ensureInitialized();
50
+ return currentIndex;
51
+ }
52
+ /** Total number of tokens in the pool. */
53
+ export function getTokenCount() {
54
+ ensureInitialized();
55
+ return tokens.length;
56
+ }
@@ -3,8 +3,7 @@ export function detectUsageLimit(text) {
3
3
  if (lower.includes('extra usage') ||
4
4
  lower.includes('usage has been disabled') ||
5
5
  lower.includes('billing_error') ||
6
- lower.includes('usage limit reached') ||
7
- lower.includes('your usage limit')) {
6
+ lower.includes('usage limit')) {
8
7
  const wake = nextHourBoundary() + 5 * 60 * 1000;
9
8
  return {
10
9
  detected: true,
@@ -13,7 +12,7 @@ export function detectUsageLimit(text) {
13
12
  humanMessage: `⏸ Claude usage limit reached. Will auto-resume at ${new Date(wake).toUTCString()}. I'll message you when it's back.`,
14
13
  };
15
14
  }
16
- if (lower.includes('currently overloaded') || lower.includes('overloaded with requests')) {
15
+ if (lower.includes('rate limit') || lower.includes('overloaded')) {
17
16
  return {
18
17
  detected: true,
19
18
  reason: 'rate_limit',
package/dist/voice.js CHANGED
@@ -5,7 +5,7 @@
5
5
  import { execFile } from "child_process";
6
6
  import { promisify } from "util";
7
7
  import { existsSync } from "fs";
8
- import { unlink } from "fs/promises";
8
+ import { unlink, readFile } from "fs/promises";
9
9
  import { tmpdir } from "os";
10
10
  import { join } from "path";
11
11
  import https from "https";
@@ -92,32 +92,34 @@ export async function transcribeVoice(fileUrl) {
92
92
  "-c:a", "pcm_s16le",
93
93
  wavPath,
94
94
  ]);
95
- // 3. Run whisper-cpp (with one retry on signal-kill)
96
- const whisperArgs = [
97
- "-m", model,
98
- "-f", wavPath,
99
- "--no-timestamps",
100
- "-l", "auto",
101
- "--output-txt",
102
- ];
103
- let stdout = "";
104
- for (let attempt = 1; attempt <= 2; attempt++) {
105
- try {
106
- const result = await execFileAsync(whisperBin, whisperArgs, { timeout: 60000 });
107
- stdout = result.stdout;
108
- break;
109
- }
110
- catch (e) {
111
- // If killed by signal and we have another attempt, retry
112
- if (attempt < 2 && (e.signal || !e.message)) {
113
- console.warn(`[voice] whisper attempt ${attempt} failed (${e.signal || 'no message'}), retrying...`);
114
- continue;
115
- }
116
- throw e;
117
- }
95
+ // 3. Run whisper-cpp
96
+ // --output-txt writes to ${wavPath}.txt (NOT stdout)
97
+ // -l auto fails with .en models — detect and use -l en instead
98
+ const isEnModel = model.includes(".en.");
99
+ const langArgs = isEnModel ? ["-l", "en"] : ["-l", "auto"];
100
+ try {
101
+ await execFileAsync(whisperBin, [
102
+ "-m", model,
103
+ "-f", wavPath,
104
+ "--no-timestamps",
105
+ ...langArgs,
106
+ "--output-txt", // writes to wavPath + ".txt"
107
+ ]);
108
+ }
109
+ catch (err) {
110
+ const msg = err instanceof Error ? err.message : String(err);
111
+ throw new Error(`whisper-cpp failed: ${msg}`);
112
+ }
113
+ // Read the output file whisper-cpp wrote
114
+ const txtPath = `${wavPath}.txt`;
115
+ let raw = "";
116
+ try {
117
+ raw = await readFile(txtPath, "utf-8");
118
+ }
119
+ catch {
120
+ throw new Error("whisper-cpp ran but produced no output file");
118
121
  }
119
- // whisper outputs to stdout — strip leading/trailing whitespace and [BLANK_AUDIO] artifacts
120
- const text = stdout
122
+ const text = raw
121
123
  .replace(/\[BLANK_AUDIO\]/gi, "")
122
124
  .replace(/\[.*?\]/g, "") // remove timestamp artifacts
123
125
  .trim();
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@gonzih/cc-tg",
3
- "version": "0.9.15",
3
+ "version": "0.9.17",
4
4
  "description": "Claude Code Telegram bot — chat with Claude Code via Telegram",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "cc-tg": "./dist/index.js"
8
8
  },
9
9
  "scripts": {
10
- "build": "tsc",
10
+ "build": "tsc && chmod +x dist/index.js",
11
11
  "start": "node dist/index.js",
12
12
  "dev": "node --loader ts-node/esm src/index.ts",
13
13
  "test": "vitest run",
@@ -18,10 +18,11 @@
18
18
  "dist/"
19
19
  ],
20
20
  "dependencies": {
21
+ "@gonzih/agent-ops": "^0.1.0",
21
22
  "node-telegram-bot-api": "^0.66.0"
22
23
  },
23
24
  "devDependencies": {
24
- "@types/node": "^22.19.15",
25
+ "@types/node": "^22.0.0",
25
26
  "@types/node-telegram-bot-api": "^0.64.0",
26
27
  "@vitest/coverage-v8": "^4.1.0",
27
28
  "typescript": "^5.5.0",