ctb 1.1.0 → 1.3.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 +50 -11
- package/docs/plans/2026-02-01-performance-reliability-improvements.md +1038 -0
- package/package.json +1 -1
- package/src/__tests__/cli.test.ts +12 -0
- package/src/__tests__/errors.test.ts +60 -0
- package/src/__tests__/events.test.ts +43 -0
- package/src/__tests__/session.test.ts +472 -0
- package/src/__tests__/telegram-api.test.ts +80 -0
- package/src/bot.ts +27 -3
- package/src/cli.ts +94 -0
- package/src/errors.ts +58 -0
- package/src/events.ts +57 -0
- package/src/handlers/commands.ts +383 -50
- package/src/handlers/index.ts +8 -1
- package/src/handlers/streaming.ts +23 -27
- package/src/handlers/text.ts +2 -1
- package/src/index.ts +53 -18
- package/src/session.ts +207 -7
- package/src/telegram-api.ts +195 -0
- package/src/types.ts +34 -33
- package/src/utils.ts +4 -21
package/src/types.ts
CHANGED
|
@@ -7,70 +7,71 @@ import type { Message } from "grammy/types";
|
|
|
7
7
|
|
|
8
8
|
// Status callback for streaming updates
|
|
9
9
|
export type StatusCallback = (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
type: "thinking" | "tool" | "text" | "segment_end" | "done",
|
|
11
|
+
content: string,
|
|
12
|
+
segmentId?: number,
|
|
13
13
|
) => Promise<void>;
|
|
14
14
|
|
|
15
15
|
// Rate limit bucket for token bucket algorithm
|
|
16
16
|
export interface RateLimitBucket {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
tokens: number;
|
|
18
|
+
lastUpdate: number;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// Session persistence data
|
|
22
22
|
export interface SessionData {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
version: number;
|
|
24
|
+
session_id: string;
|
|
25
|
+
saved_at: string;
|
|
26
|
+
working_dir: string;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
// Token usage from Claude
|
|
29
30
|
export interface TokenUsage {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
input_tokens: number;
|
|
32
|
+
output_tokens: number;
|
|
33
|
+
cache_read_input_tokens?: number;
|
|
34
|
+
cache_creation_input_tokens?: number;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
// MCP server configuration types
|
|
37
38
|
export type McpServerConfig = McpStdioConfig | McpHttpConfig;
|
|
38
39
|
|
|
39
40
|
export interface McpStdioConfig {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
command: string;
|
|
42
|
+
args?: string[];
|
|
43
|
+
env?: Record<string, string>;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
export interface McpHttpConfig {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
type: "http";
|
|
48
|
+
url: string;
|
|
49
|
+
headers?: Record<string, string>;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
// Audit log event types
|
|
52
53
|
export type AuditEventType =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
| "message"
|
|
55
|
+
| "auth"
|
|
56
|
+
| "tool_use"
|
|
57
|
+
| "error"
|
|
58
|
+
| "rate_limit";
|
|
58
59
|
|
|
59
60
|
export interface AuditEvent {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
timestamp: string;
|
|
62
|
+
event: AuditEventType;
|
|
63
|
+
user_id: number;
|
|
64
|
+
username?: string;
|
|
65
|
+
[key: string]: unknown;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
// Pending media group for buffering albums
|
|
68
69
|
export interface PendingMediaGroup {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
items: string[];
|
|
71
|
+
ctx: Context;
|
|
72
|
+
caption?: string;
|
|
73
|
+
statusMsg?: Message;
|
|
74
|
+
timeout: Timer;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
// Bot context with optional message
|
package/src/utils.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
TRANSCRIPTION_AVAILABLE,
|
|
15
15
|
TRANSCRIPTION_PROMPT,
|
|
16
16
|
} from "./config";
|
|
17
|
+
import { botEvents } from "./events";
|
|
17
18
|
import type { AuditEvent } from "./types";
|
|
18
19
|
|
|
19
20
|
// ============== OpenAI Client ==============
|
|
@@ -211,35 +212,17 @@ export function startTypingIndicator(ctx: Context): TypingController {
|
|
|
211
212
|
|
|
212
213
|
// ============== Message Interrupt ==============
|
|
213
214
|
|
|
214
|
-
// Import session lazily to avoid circular dependency
|
|
215
|
-
let sessionModule: {
|
|
216
|
-
session: {
|
|
217
|
-
isRunning: boolean;
|
|
218
|
-
stop: () => Promise<"stopped" | "pending" | false>;
|
|
219
|
-
markInterrupt: () => void;
|
|
220
|
-
clearStopRequested: () => void;
|
|
221
|
-
};
|
|
222
|
-
} | null = null;
|
|
223
|
-
|
|
224
215
|
export async function checkInterrupt(text: string): Promise<string> {
|
|
225
216
|
if (!text || !text.startsWith("!")) {
|
|
226
217
|
return text;
|
|
227
218
|
}
|
|
228
219
|
|
|
229
|
-
// Lazy import to avoid circular dependency
|
|
230
|
-
if (!sessionModule) {
|
|
231
|
-
sessionModule = await import("./session");
|
|
232
|
-
}
|
|
233
|
-
|
|
234
220
|
const strippedText = text.slice(1).trimStart();
|
|
235
221
|
|
|
236
|
-
if (
|
|
237
|
-
console.log("! prefix -
|
|
238
|
-
|
|
239
|
-
await sessionModule.session.stop();
|
|
222
|
+
if (botEvents.getSessionState()) {
|
|
223
|
+
console.log("! prefix - requesting interrupt");
|
|
224
|
+
botEvents.emit("interruptRequested", undefined);
|
|
240
225
|
await Bun.sleep(100);
|
|
241
|
-
// Clear stopRequested so the new message can proceed
|
|
242
|
-
sessionModule.session.clearStopRequested();
|
|
243
226
|
}
|
|
244
227
|
|
|
245
228
|
return strippedText;
|