tg-claude 0.1.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.
Files changed (111) hide show
  1. package/README.md +175 -0
  2. package/bin/cli.js +2 -0
  3. package/dist/claude/ClaudeProcess.d.ts +77 -0
  4. package/dist/claude/ClaudeProcess.d.ts.map +1 -0
  5. package/dist/claude/ClaudeProcess.js +270 -0
  6. package/dist/claude/ClaudeProcess.js.map +1 -0
  7. package/dist/claude/EventAdapter.d.ts +44 -0
  8. package/dist/claude/EventAdapter.d.ts.map +1 -0
  9. package/dist/claude/EventAdapter.js +129 -0
  10. package/dist/claude/EventAdapter.js.map +1 -0
  11. package/dist/claude/index.d.ts +10 -0
  12. package/dist/claude/index.d.ts.map +1 -0
  13. package/dist/claude/index.js +9 -0
  14. package/dist/claude/index.js.map +1 -0
  15. package/dist/claude/types.d.ts +244 -0
  16. package/dist/claude/types.d.ts.map +1 -0
  17. package/dist/claude/types.js +8 -0
  18. package/dist/claude/types.js.map +1 -0
  19. package/dist/env.d.ts +21 -0
  20. package/dist/env.d.ts.map +1 -0
  21. package/dist/env.js +49 -0
  22. package/dist/env.js.map +1 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +360 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/parser/AnsiStripper.d.ts +54 -0
  28. package/dist/parser/AnsiStripper.d.ts.map +1 -0
  29. package/dist/parser/AnsiStripper.js +115 -0
  30. package/dist/parser/AnsiStripper.js.map +1 -0
  31. package/dist/parser/OptionExtractor.d.ts +31 -0
  32. package/dist/parser/OptionExtractor.d.ts.map +1 -0
  33. package/dist/parser/OptionExtractor.js +91 -0
  34. package/dist/parser/OptionExtractor.js.map +1 -0
  35. package/dist/parser/OutputParser.d.ts +121 -0
  36. package/dist/parser/OutputParser.d.ts.map +1 -0
  37. package/dist/parser/OutputParser.js +306 -0
  38. package/dist/parser/OutputParser.js.map +1 -0
  39. package/dist/parser/PromptDetector.d.ts +20 -0
  40. package/dist/parser/PromptDetector.d.ts.map +1 -0
  41. package/dist/parser/PromptDetector.js +68 -0
  42. package/dist/parser/PromptDetector.js.map +1 -0
  43. package/dist/parser/index.d.ts +7 -0
  44. package/dist/parser/index.d.ts.map +1 -0
  45. package/dist/parser/index.js +5 -0
  46. package/dist/parser/index.js.map +1 -0
  47. package/dist/parser/types.d.ts +73 -0
  48. package/dist/parser/types.d.ts.map +1 -0
  49. package/dist/parser/types.js +2 -0
  50. package/dist/parser/types.js.map +1 -0
  51. package/dist/pty/OutputBuffer.d.ts +39 -0
  52. package/dist/pty/OutputBuffer.d.ts.map +1 -0
  53. package/dist/pty/OutputBuffer.js +55 -0
  54. package/dist/pty/OutputBuffer.js.map +1 -0
  55. package/dist/pty/PtyProcess.d.ts +47 -0
  56. package/dist/pty/PtyProcess.d.ts.map +1 -0
  57. package/dist/pty/PtyProcess.js +94 -0
  58. package/dist/pty/PtyProcess.js.map +1 -0
  59. package/dist/pty/PtyService.d.ts +55 -0
  60. package/dist/pty/PtyService.d.ts.map +1 -0
  61. package/dist/pty/PtyService.js +115 -0
  62. package/dist/pty/PtyService.js.map +1 -0
  63. package/dist/pty/index.d.ts +5 -0
  64. package/dist/pty/index.d.ts.map +1 -0
  65. package/dist/pty/index.js +4 -0
  66. package/dist/pty/index.js.map +1 -0
  67. package/dist/pty/types.d.ts +36 -0
  68. package/dist/pty/types.d.ts.map +1 -0
  69. package/dist/pty/types.js +2 -0
  70. package/dist/pty/types.js.map +1 -0
  71. package/dist/router/BoundedQueue.d.ts +57 -0
  72. package/dist/router/BoundedQueue.d.ts.map +1 -0
  73. package/dist/router/BoundedQueue.js +86 -0
  74. package/dist/router/BoundedQueue.js.map +1 -0
  75. package/dist/router/EventRouter.d.ts +103 -0
  76. package/dist/router/EventRouter.d.ts.map +1 -0
  77. package/dist/router/EventRouter.js +169 -0
  78. package/dist/router/EventRouter.js.map +1 -0
  79. package/dist/router/index.d.ts +13 -0
  80. package/dist/router/index.d.ts.map +1 -0
  81. package/dist/router/index.js +12 -0
  82. package/dist/router/index.js.map +1 -0
  83. package/dist/router/types.d.ts +104 -0
  84. package/dist/router/types.d.ts.map +1 -0
  85. package/dist/router/types.js +6 -0
  86. package/dist/router/types.js.map +1 -0
  87. package/dist/telegram/TelegramBot.d.ts +151 -0
  88. package/dist/telegram/TelegramBot.d.ts.map +1 -0
  89. package/dist/telegram/TelegramBot.js +514 -0
  90. package/dist/telegram/TelegramBot.js.map +1 -0
  91. package/dist/telegram/index.d.ts +7 -0
  92. package/dist/telegram/index.d.ts.map +1 -0
  93. package/dist/telegram/index.js +6 -0
  94. package/dist/telegram/index.js.map +1 -0
  95. package/dist/telegram/types.d.ts +30 -0
  96. package/dist/telegram/types.d.ts.map +1 -0
  97. package/dist/telegram/types.js +5 -0
  98. package/dist/telegram/types.js.map +1 -0
  99. package/dist/terminal/TerminalInterface.d.ts +61 -0
  100. package/dist/terminal/TerminalInterface.d.ts.map +1 -0
  101. package/dist/terminal/TerminalInterface.js +218 -0
  102. package/dist/terminal/TerminalInterface.js.map +1 -0
  103. package/dist/terminal/index.d.ts +3 -0
  104. package/dist/terminal/index.d.ts.map +1 -0
  105. package/dist/terminal/index.js +2 -0
  106. package/dist/terminal/index.js.map +1 -0
  107. package/dist/terminal/types.d.ts +17 -0
  108. package/dist/terminal/types.d.ts.map +1 -0
  109. package/dist/terminal/types.js +2 -0
  110. package/dist/terminal/types.js.map +1 -0
  111. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,175 @@
1
+ # Claude Telegram Bridge
2
+
3
+ Control Claude Code from your phone via Telegram. Get notifications when Claude needs input, respond with buttons or text, and monitor progress from anywhere.
4
+
5
+ ## Features
6
+
7
+ - **Mobile Notifications**: Get Telegram alerts when Claude needs a decision
8
+ - **Interactive Buttons**: Tap to select options without typing
9
+ - **Multi-Select Support**: Handle questions with multiple choices
10
+ - **Dual Interface**: Use both terminal and Telegram simultaneously
11
+ - **Session Continuity**: Continue conversations across turns
12
+ - **Autonomous Mode**: Runs with `--dangerously-skip-permissions` for unattended operation
13
+
14
+ ## Quick Start
15
+
16
+ ### Prerequisites
17
+
18
+ - Node.js 20 or higher
19
+ - Claude Code CLI installed and authenticated (`npm install -g @anthropic-ai/claude-code`)
20
+ - A Telegram account
21
+
22
+ ### 1. Create a Telegram Bot
23
+
24
+ 1. Open Telegram and message [@BotFather](https://t.me/BotFather)
25
+ 2. Send `/newbot`
26
+ 3. Follow the prompts to name your bot
27
+ 4. Copy the bot token you receive (looks like `123456789:ABCdefGHI...`)
28
+
29
+ ### 2. Get Your Telegram User ID
30
+
31
+ 1. Message [@userinfobot](https://t.me/userinfobot) on Telegram
32
+ 2. Copy your numeric user ID (just a number like `123456789`)
33
+
34
+ ### 3. Install and Configure
35
+
36
+ **Option A: Global Install (recommended)**
37
+
38
+ ```bash
39
+ npm install -g tg-claude
40
+ ```
41
+
42
+ **Option B: npx (no install)**
43
+
44
+ ```bash
45
+ npx tg-claude "Your prompt"
46
+ ```
47
+
48
+ Set your environment variables:
49
+
50
+ ```bash
51
+ export TELEGRAM_BOT_TOKEN="your_bot_token"
52
+ export TELEGRAM_USER_ID="your_user_id"
53
+ ```
54
+
55
+ Or create a `.env` file in your working directory:
56
+
57
+ ```bash
58
+ cp .env.example .env
59
+ # Edit .env with your values
60
+ ```
61
+
62
+ ### 4. Run
63
+
64
+ ```bash
65
+ tg-claude "Fix the bug in app.js"
66
+ ```
67
+
68
+ ## Usage
69
+
70
+ ```bash
71
+ tg-claude [options] "Your prompt"
72
+ ```
73
+
74
+ ### Options
75
+
76
+ | Flag | Description |
77
+ |------|-------------|
78
+ | `--help`, `-h` | Show help message |
79
+ | `--version`, `-v` | Show version number |
80
+ | `--verbose` | Show additional logging |
81
+ | `--debug` | Enable debug output |
82
+ | `--quiet` | Suppress bridge logs, show only Claude output |
83
+
84
+ ### Examples
85
+
86
+ ```bash
87
+ # Basic usage
88
+ tg-claude "Explain this codebase"
89
+
90
+ # Verbose output
91
+ tg-claude --verbose "Refactor the auth module"
92
+
93
+ # Quiet mode (only Claude's output)
94
+ tg-claude --quiet "Write tests for user.ts"
95
+
96
+ # Using npx
97
+ npx tg-claude "Create a README"
98
+ ```
99
+
100
+ ## Environment Variables
101
+
102
+ | Variable | Required | Description |
103
+ |----------|----------|-------------|
104
+ | `TELEGRAM_BOT_TOKEN` | Yes | Bot token from @BotFather |
105
+ | `TELEGRAM_USER_ID` | Yes | Your numeric Telegram user ID |
106
+
107
+ Without Telegram credentials, the bridge runs in terminal-only mode.
108
+
109
+ ## How It Works
110
+
111
+ 1. **Start**: You run `tg-claude "your prompt"`
112
+ 2. **Execute**: Claude Code processes your request autonomously
113
+ 3. **Notify**: When Claude needs input, you get a Telegram notification
114
+ 4. **Respond**: Tap a button or type a response
115
+ 5. **Continue**: Claude resumes with your answer
116
+ 6. **Complete**: Get a completion notification when done
117
+
118
+ The bridge uses Claude's `--output-format stream-json` for structured events and `--resume` for session continuity.
119
+
120
+ ### Dual Interface
121
+
122
+ Both terminal and Telegram can respond to prompts:
123
+
124
+ - **Terminal**: Type option numbers or freeform text
125
+ - **Telegram**: Tap buttons or send messages
126
+ - Responses from either interface are echoed to the other
127
+
128
+ ### Security
129
+
130
+ Only the configured `TELEGRAM_USER_ID` can interact with your bot. All other users are silently ignored.
131
+
132
+ ## Troubleshooting
133
+
134
+ ### "TELEGRAM_USER_ID must be a number"
135
+
136
+ Your user ID should be a numeric value like `123456789`, not a username. Get it from [@userinfobot](https://t.me/userinfobot).
137
+
138
+ ### "Claude CLI not found"
139
+
140
+ Install Claude Code CLI:
141
+
142
+ ```bash
143
+ npm install -g @anthropic-ai/claude-code
144
+ claude auth login
145
+ ```
146
+
147
+ ### "Permission denied" on global install
148
+
149
+ Use sudo or configure npm for global installs without sudo:
150
+
151
+ ```bash
152
+ sudo npm install -g tg-claude
153
+ # or
154
+ npm config set prefix ~/.npm-global
155
+ export PATH=~/.npm-global/bin:$PATH
156
+ ```
157
+
158
+ ### Bot not responding
159
+
160
+ 1. Make sure you messaged your bot at least once to start a conversation
161
+ 2. Verify `TELEGRAM_BOT_TOKEN` and `TELEGRAM_USER_ID` are correct
162
+ 3. Check that Claude Code CLI is authenticated (`claude auth status`)
163
+
164
+ ## Development
165
+
166
+ ```bash
167
+ git clone https://github.com/memehalis/tg-claude
168
+ cd tg-claude
169
+ npm install
170
+ npm run dev "test prompt"
171
+ ```
172
+
173
+ ## License
174
+
175
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
@@ -0,0 +1,77 @@
1
+ import type { ClaudeProcessOptions, ClaudeProcessEvents } from './types.js';
2
+ /**
3
+ * ClaudeProcess spawns the Claude CLI as a subprocess and parses
4
+ * NDJSON stream-json output into typed events.
5
+ *
6
+ * Usage:
7
+ * ```typescript
8
+ * const claude = new ClaudeProcess({
9
+ * cwd: '/path/to/project',
10
+ * prompt: 'Hello, Claude!',
11
+ * });
12
+ *
13
+ * claude.on('init', (e) => console.log('Session:', e.sessionId));
14
+ * claude.on('text', (e) => console.log('Text:', e.text));
15
+ * claude.on('complete', (e) => console.log('Done:', e.result));
16
+ * claude.on('error', (e) => console.error('Error:', e.message));
17
+ *
18
+ * await claude.start();
19
+ * ```
20
+ */
21
+ export declare class ClaudeProcess {
22
+ private readonly options;
23
+ private readonly emitter;
24
+ private proc;
25
+ private readline;
26
+ private sessionId;
27
+ private running;
28
+ private stderrChunks;
29
+ private emittedToolUseIds;
30
+ constructor(options: ClaudeProcessOptions);
31
+ /**
32
+ * Subscribe to process events
33
+ */
34
+ on<K extends keyof ClaudeProcessEvents>(event: K, listener: ClaudeProcessEvents[K]): this;
35
+ /**
36
+ * Subscribe to process events (once)
37
+ */
38
+ once<K extends keyof ClaudeProcessEvents>(event: K, listener: ClaudeProcessEvents[K]): this;
39
+ /**
40
+ * Unsubscribe from process events
41
+ */
42
+ off<K extends keyof ClaudeProcessEvents>(event: K, listener: ClaudeProcessEvents[K]): this;
43
+ /**
44
+ * Remove all listeners for an event
45
+ */
46
+ removeAllListeners<K extends keyof ClaudeProcessEvents>(event?: K): this;
47
+ /**
48
+ * Start the Claude CLI process and begin parsing output
49
+ * Resolves when the process exits (or rejects on spawn error)
50
+ */
51
+ start(): Promise<void>;
52
+ /**
53
+ * Build CLI arguments based on options
54
+ */
55
+ private buildArgs;
56
+ /**
57
+ * Handle a parsed stream-json message
58
+ */
59
+ private handleMessage;
60
+ /**
61
+ * Emit an error event with structured details
62
+ */
63
+ private emitError;
64
+ /**
65
+ * Get the current session ID (available after 'init' event)
66
+ */
67
+ get currentSessionId(): string | null;
68
+ /**
69
+ * Check if the process is currently running
70
+ */
71
+ get isRunning(): boolean;
72
+ /**
73
+ * Kill the Claude CLI process
74
+ */
75
+ kill(): void;
76
+ }
77
+ //# sourceMappingURL=ClaudeProcess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClaudeProcess.d.ts","sourceRoot":"","sources":["../../src/claude/ClaudeProcess.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EAcpB,MAAM,YAAY,CAAC;AAapB;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,aAAa;IASZ,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,iBAAiB,CAAqB;gBAEjB,OAAO,EAAE,oBAAoB;IAI1D;;OAEG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,IAAI;IAKzF;;OAEG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,IAAI;IAK3F;;OAEG;IACH,GAAG,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,IAAI;IAK1F;;OAEG;IACH,kBAAkB,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI;IAKxE;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkF5B;;OAEG;IACH,OAAO,CAAC,SAAS;IAoBjB;;OAEG;IACH,OAAO,CAAC,aAAa;IAoFrB;;OAEG;IACH,OAAO,CAAC,SAAS;IASjB;;OAEG;IACH,IAAI,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEpC;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI;CAKb"}
@@ -0,0 +1,270 @@
1
+ import { spawn } from 'child_process';
2
+ import { createInterface } from 'readline';
3
+ import { EventEmitter } from 'events';
4
+ /**
5
+ * ClaudeProcess spawns the Claude CLI as a subprocess and parses
6
+ * NDJSON stream-json output into typed events.
7
+ *
8
+ * Usage:
9
+ * ```typescript
10
+ * const claude = new ClaudeProcess({
11
+ * cwd: '/path/to/project',
12
+ * prompt: 'Hello, Claude!',
13
+ * });
14
+ *
15
+ * claude.on('init', (e) => console.log('Session:', e.sessionId));
16
+ * claude.on('text', (e) => console.log('Text:', e.text));
17
+ * claude.on('complete', (e) => console.log('Done:', e.result));
18
+ * claude.on('error', (e) => console.error('Error:', e.message));
19
+ *
20
+ * await claude.start();
21
+ * ```
22
+ */
23
+ export class ClaudeProcess {
24
+ options;
25
+ emitter;
26
+ proc = null;
27
+ readline = null;
28
+ sessionId = null;
29
+ running = false;
30
+ stderrChunks = [];
31
+ emittedToolUseIds = new Set(); // Dedupe tool_use events
32
+ constructor(options) {
33
+ this.options = options;
34
+ this.emitter = new EventEmitter();
35
+ }
36
+ /**
37
+ * Subscribe to process events
38
+ */
39
+ on(event, listener) {
40
+ this.emitter.on(event, listener);
41
+ return this;
42
+ }
43
+ /**
44
+ * Subscribe to process events (once)
45
+ */
46
+ once(event, listener) {
47
+ this.emitter.once(event, listener);
48
+ return this;
49
+ }
50
+ /**
51
+ * Unsubscribe from process events
52
+ */
53
+ off(event, listener) {
54
+ this.emitter.off(event, listener);
55
+ return this;
56
+ }
57
+ /**
58
+ * Remove all listeners for an event
59
+ */
60
+ removeAllListeners(event) {
61
+ this.emitter.removeAllListeners(event);
62
+ return this;
63
+ }
64
+ /**
65
+ * Start the Claude CLI process and begin parsing output
66
+ * Resolves when the process exits (or rejects on spawn error)
67
+ */
68
+ async start() {
69
+ if (this.running) {
70
+ throw new Error('ClaudeProcess is already running');
71
+ }
72
+ const args = this.buildArgs();
73
+ this.running = true;
74
+ try {
75
+ this.proc = spawn('claude', args, {
76
+ cwd: this.options.cwd,
77
+ stdio: ['ignore', 'pipe', 'pipe'],
78
+ });
79
+ }
80
+ catch (err) {
81
+ this.running = false;
82
+ const error = err;
83
+ this.emitError('spawn', `Failed to spawn claude CLI: ${error.message}`);
84
+ return;
85
+ }
86
+ // Handle spawn errors (e.g., ENOENT when claude is not found)
87
+ this.proc.on('error', (err) => {
88
+ this.running = false;
89
+ if (err.code === 'ENOENT') {
90
+ this.emitError('spawn', "Claude CLI not found. Ensure 'claude' is installed and in PATH.");
91
+ }
92
+ else {
93
+ this.emitError('spawn', `Failed to spawn claude CLI: ${err.message}`);
94
+ }
95
+ });
96
+ // Collect stderr for error reporting
97
+ if (this.proc.stderr) {
98
+ this.proc.stderr.on('data', (chunk) => {
99
+ this.stderrChunks.push(chunk);
100
+ });
101
+ }
102
+ // Create readline interface on stdout for NDJSON parsing
103
+ if (this.proc.stdout) {
104
+ this.readline = createInterface({ input: this.proc.stdout });
105
+ // Parse each line as JSON
106
+ for await (const line of this.readline) {
107
+ if (!line.trim())
108
+ continue;
109
+ try {
110
+ const msg = JSON.parse(line);
111
+ this.handleMessage(msg);
112
+ }
113
+ catch (err) {
114
+ const error = err;
115
+ this.emitError('parse', `Failed to parse JSON: ${error.message}`, {
116
+ line: line.slice(0, 200),
117
+ });
118
+ }
119
+ }
120
+ }
121
+ // Wait for process to exit
122
+ const exitCode = await new Promise((resolve) => {
123
+ if (!this.proc) {
124
+ resolve(null);
125
+ return;
126
+ }
127
+ this.proc.on('close', (code) => {
128
+ this.running = false;
129
+ resolve(code);
130
+ });
131
+ });
132
+ // Report non-zero exit
133
+ if (exitCode !== null && exitCode !== 0) {
134
+ const stderr = Buffer.concat(this.stderrChunks).toString();
135
+ this.emitError('exit', `Claude CLI exited with code ${exitCode}`, {
136
+ code: exitCode,
137
+ stderr: stderr.slice(0, 1000),
138
+ });
139
+ }
140
+ }
141
+ /**
142
+ * Build CLI arguments based on options
143
+ */
144
+ buildArgs() {
145
+ const args = [
146
+ '-p',
147
+ this.options.prompt,
148
+ '--output-format',
149
+ 'stream-json',
150
+ '--verbose',
151
+ ];
152
+ if (this.options.sessionId) {
153
+ args.push('--resume', this.options.sessionId);
154
+ }
155
+ if (this.options.permissionMode) {
156
+ args.push('--permission-mode', this.options.permissionMode);
157
+ }
158
+ return args;
159
+ }
160
+ /**
161
+ * Handle a parsed stream-json message
162
+ */
163
+ handleMessage(msg) {
164
+ switch (msg.type) {
165
+ case 'system':
166
+ if ('subtype' in msg && msg.subtype === 'init') {
167
+ const initMsg = msg;
168
+ this.sessionId = initMsg.session_id;
169
+ const initEvent = {
170
+ sessionId: initMsg.session_id,
171
+ tools: initMsg.tools,
172
+ model: initMsg.model,
173
+ };
174
+ this.emitter.emit('init', initEvent);
175
+ }
176
+ // Hook messages (hook_started, hook_response) are skipped silently
177
+ break;
178
+ case 'assistant': {
179
+ const assistantMsg = msg;
180
+ for (const block of assistantMsg.message.content) {
181
+ if (block.type === 'text') {
182
+ const textEvent = { text: block.text };
183
+ this.emitter.emit('text', textEvent);
184
+ }
185
+ else if (block.type === 'tool_use') {
186
+ // Deduplicate tool_use events by ID (same message may be streamed multiple times)
187
+ if (this.emittedToolUseIds.has(block.id)) {
188
+ continue;
189
+ }
190
+ this.emittedToolUseIds.add(block.id);
191
+ const toolUseEvent = {
192
+ id: block.id,
193
+ name: block.name,
194
+ input: block.input,
195
+ };
196
+ this.emitter.emit('tool_use', toolUseEvent);
197
+ // Emit special 'question' event for AskUserQuestion tool
198
+ if (block.name === 'AskUserQuestion') {
199
+ const askInput = block.input;
200
+ if (askInput.questions && askInput.questions.length > 0) {
201
+ const q = askInput.questions[0]; // Handle first question
202
+ const questionEvent = {
203
+ question: q.question,
204
+ options: q.options,
205
+ multiSelect: q.multiSelect,
206
+ };
207
+ this.emitter.emit('question', questionEvent);
208
+ }
209
+ }
210
+ }
211
+ }
212
+ break;
213
+ }
214
+ case 'user': {
215
+ const userMsg = msg;
216
+ // Emit tool_result for each tool result in the message
217
+ for (const content of userMsg.message.content) {
218
+ if (content.type === 'tool_result') {
219
+ const toolResultEvent = {
220
+ result: content.content,
221
+ isError: content.is_error,
222
+ };
223
+ this.emitter.emit('tool_result', toolResultEvent);
224
+ }
225
+ }
226
+ break;
227
+ }
228
+ case 'result': {
229
+ const resultMsg = msg;
230
+ const completeEvent = {
231
+ result: resultMsg.result,
232
+ sessionId: resultMsg.session_id,
233
+ cost: resultMsg.total_cost_usd,
234
+ duration: resultMsg.duration_ms,
235
+ isError: resultMsg.is_error,
236
+ };
237
+ this.emitter.emit('complete', completeEvent);
238
+ break;
239
+ }
240
+ }
241
+ }
242
+ /**
243
+ * Emit an error event with structured details
244
+ */
245
+ emitError(type, message, details) {
246
+ const errorEvent = { type, message, details };
247
+ this.emitter.emit('error', errorEvent);
248
+ }
249
+ /**
250
+ * Get the current session ID (available after 'init' event)
251
+ */
252
+ get currentSessionId() {
253
+ return this.sessionId;
254
+ }
255
+ /**
256
+ * Check if the process is currently running
257
+ */
258
+ get isRunning() {
259
+ return this.running;
260
+ }
261
+ /**
262
+ * Kill the Claude CLI process
263
+ */
264
+ kill() {
265
+ if (this.proc && this.running) {
266
+ this.proc.kill('SIGTERM');
267
+ }
268
+ }
269
+ }
270
+ //# sourceMappingURL=ClaudeProcess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClaudeProcess.js","sourceRoot":"","sources":["../../src/claude/ClaudeProcess.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { ClaudeProcess } from './ClaudeProcess.js';
2
+ import type { EventRouter } from '../router/EventRouter.js';
3
+ /**
4
+ * EventAdapter bridges ClaudeProcess events to EventRouter format.
5
+ *
6
+ * Subscribes to ClaudeProcess events and publishes corresponding
7
+ * OutboundEvents to the router for Telegram integration.
8
+ */
9
+ export declare class EventAdapter {
10
+ private readonly claudeProcess;
11
+ private readonly router;
12
+ private readonly sessionId;
13
+ private _lastSessionId;
14
+ private _textBuffer;
15
+ private _hasQuestion;
16
+ constructor(claudeProcess: ClaudeProcess, router: EventRouter, sessionId: string);
17
+ /**
18
+ * Subscribe to ClaudeProcess events and wire to router
19
+ */
20
+ private subscribeToEvents;
21
+ /**
22
+ * Clean result text for Telegram
23
+ * - Strips TUI box drawing characters
24
+ * - Returns "Task completed" if empty after cleaning
25
+ */
26
+ private cleanResult;
27
+ /**
28
+ * Get the session ID from Claude's last run (for --resume)
29
+ */
30
+ get lastSessionId(): string | null;
31
+ /**
32
+ * Get accumulated text output
33
+ */
34
+ get textBuffer(): string;
35
+ /**
36
+ * Check if a question was asked in this turn
37
+ */
38
+ get hasQuestion(): boolean;
39
+ /**
40
+ * Clear text buffer and question state for new conversation turn
41
+ */
42
+ reset(): void;
43
+ }
44
+ //# sourceMappingURL=EventAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventAdapter.d.ts","sourceRoot":"","sources":["../../src/claude/EventAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAS5D;;;;;GAKG;AACH,qBAAa,YAAY;IAMrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAP5B,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,YAAY,CAAS;gBAGV,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM;IAKpC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6EzB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAQnB;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,GAAG,IAAI,CAEjC;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;CAId"}