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/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
- type: "thinking" | "tool" | "text" | "segment_end" | "done",
11
- content: string,
12
- segmentId?: number
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
- tokens: number;
18
- lastUpdate: number;
17
+ tokens: number;
18
+ lastUpdate: number;
19
19
  }
20
20
 
21
21
  // Session persistence data
22
22
  export interface SessionData {
23
- session_id: string;
24
- saved_at: string;
25
- working_dir: string;
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
- input_tokens: number;
31
- output_tokens: number;
32
- cache_read_input_tokens?: number;
33
- cache_creation_input_tokens?: number;
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
- command: string;
41
- args?: string[];
42
- env?: Record<string, string>;
41
+ command: string;
42
+ args?: string[];
43
+ env?: Record<string, string>;
43
44
  }
44
45
 
45
46
  export interface McpHttpConfig {
46
- type: "http";
47
- url: string;
48
- headers?: Record<string, string>;
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
- | "message"
54
- | "auth"
55
- | "tool_use"
56
- | "error"
57
- | "rate_limit";
54
+ | "message"
55
+ | "auth"
56
+ | "tool_use"
57
+ | "error"
58
+ | "rate_limit";
58
59
 
59
60
  export interface AuditEvent {
60
- timestamp: string;
61
- event: AuditEventType;
62
- user_id: number;
63
- username?: string;
64
- [key: string]: unknown;
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
- items: string[];
70
- ctx: Context;
71
- caption?: string;
72
- statusMsg?: Message;
73
- timeout: Timer;
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 (sessionModule.session.isRunning) {
237
- console.log("! prefix - interrupting current query");
238
- sessionModule.session.markInterrupt();
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;