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.
- package/README.md +175 -0
- package/bin/cli.js +2 -0
- package/dist/claude/ClaudeProcess.d.ts +77 -0
- package/dist/claude/ClaudeProcess.d.ts.map +1 -0
- package/dist/claude/ClaudeProcess.js +270 -0
- package/dist/claude/ClaudeProcess.js.map +1 -0
- package/dist/claude/EventAdapter.d.ts +44 -0
- package/dist/claude/EventAdapter.d.ts.map +1 -0
- package/dist/claude/EventAdapter.js +129 -0
- package/dist/claude/EventAdapter.js.map +1 -0
- package/dist/claude/index.d.ts +10 -0
- package/dist/claude/index.d.ts.map +1 -0
- package/dist/claude/index.js +9 -0
- package/dist/claude/index.js.map +1 -0
- package/dist/claude/types.d.ts +244 -0
- package/dist/claude/types.d.ts.map +1 -0
- package/dist/claude/types.js +8 -0
- package/dist/claude/types.js.map +1 -0
- package/dist/env.d.ts +21 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +49 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +360 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/AnsiStripper.d.ts +54 -0
- package/dist/parser/AnsiStripper.d.ts.map +1 -0
- package/dist/parser/AnsiStripper.js +115 -0
- package/dist/parser/AnsiStripper.js.map +1 -0
- package/dist/parser/OptionExtractor.d.ts +31 -0
- package/dist/parser/OptionExtractor.d.ts.map +1 -0
- package/dist/parser/OptionExtractor.js +91 -0
- package/dist/parser/OptionExtractor.js.map +1 -0
- package/dist/parser/OutputParser.d.ts +121 -0
- package/dist/parser/OutputParser.d.ts.map +1 -0
- package/dist/parser/OutputParser.js +306 -0
- package/dist/parser/OutputParser.js.map +1 -0
- package/dist/parser/PromptDetector.d.ts +20 -0
- package/dist/parser/PromptDetector.d.ts.map +1 -0
- package/dist/parser/PromptDetector.js +68 -0
- package/dist/parser/PromptDetector.js.map +1 -0
- package/dist/parser/index.d.ts +7 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +5 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/types.d.ts +73 -0
- package/dist/parser/types.d.ts.map +1 -0
- package/dist/parser/types.js +2 -0
- package/dist/parser/types.js.map +1 -0
- package/dist/pty/OutputBuffer.d.ts +39 -0
- package/dist/pty/OutputBuffer.d.ts.map +1 -0
- package/dist/pty/OutputBuffer.js +55 -0
- package/dist/pty/OutputBuffer.js.map +1 -0
- package/dist/pty/PtyProcess.d.ts +47 -0
- package/dist/pty/PtyProcess.d.ts.map +1 -0
- package/dist/pty/PtyProcess.js +94 -0
- package/dist/pty/PtyProcess.js.map +1 -0
- package/dist/pty/PtyService.d.ts +55 -0
- package/dist/pty/PtyService.d.ts.map +1 -0
- package/dist/pty/PtyService.js +115 -0
- package/dist/pty/PtyService.js.map +1 -0
- package/dist/pty/index.d.ts +5 -0
- package/dist/pty/index.d.ts.map +1 -0
- package/dist/pty/index.js +4 -0
- package/dist/pty/index.js.map +1 -0
- package/dist/pty/types.d.ts +36 -0
- package/dist/pty/types.d.ts.map +1 -0
- package/dist/pty/types.js +2 -0
- package/dist/pty/types.js.map +1 -0
- package/dist/router/BoundedQueue.d.ts +57 -0
- package/dist/router/BoundedQueue.d.ts.map +1 -0
- package/dist/router/BoundedQueue.js +86 -0
- package/dist/router/BoundedQueue.js.map +1 -0
- package/dist/router/EventRouter.d.ts +103 -0
- package/dist/router/EventRouter.d.ts.map +1 -0
- package/dist/router/EventRouter.js +169 -0
- package/dist/router/EventRouter.js.map +1 -0
- package/dist/router/index.d.ts +13 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +12 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/types.d.ts +104 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +6 -0
- package/dist/router/types.js.map +1 -0
- package/dist/telegram/TelegramBot.d.ts +151 -0
- package/dist/telegram/TelegramBot.d.ts.map +1 -0
- package/dist/telegram/TelegramBot.js +514 -0
- package/dist/telegram/TelegramBot.js.map +1 -0
- package/dist/telegram/index.d.ts +7 -0
- package/dist/telegram/index.d.ts.map +1 -0
- package/dist/telegram/index.js +6 -0
- package/dist/telegram/index.js.map +1 -0
- package/dist/telegram/types.d.ts +30 -0
- package/dist/telegram/types.d.ts.map +1 -0
- package/dist/telegram/types.js +5 -0
- package/dist/telegram/types.js.map +1 -0
- package/dist/terminal/TerminalInterface.d.ts +61 -0
- package/dist/terminal/TerminalInterface.d.ts.map +1 -0
- package/dist/terminal/TerminalInterface.js +218 -0
- package/dist/terminal/TerminalInterface.js.map +1 -0
- package/dist/terminal/index.d.ts +3 -0
- package/dist/terminal/index.d.ts.map +1 -0
- package/dist/terminal/index.js +2 -0
- package/dist/terminal/index.js.map +1 -0
- package/dist/terminal/types.d.ts +17 -0
- package/dist/terminal/types.d.ts.map +1 -0
- package/dist/terminal/types.js +2 -0
- package/dist/terminal/types.js.map +1 -0
- 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,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"}
|