forkoff 1.0.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/LICENSE +17 -0
- package/README.md +173 -0
- package/dist/api.d.ts +44 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +76 -0
- package/dist/api.js.map +1 -0
- package/dist/approval.d.ts +46 -0
- package/dist/approval.d.ts.map +1 -0
- package/dist/approval.js +119 -0
- package/dist/approval.js.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +209 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +868 -0
- package/dist/index.js.map +1 -0
- package/dist/integration.d.ts +30 -0
- package/dist/integration.d.ts.map +1 -0
- package/dist/integration.js +84 -0
- package/dist/integration.js.map +1 -0
- package/dist/terminal.d.ts +25 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +171 -0
- package/dist/terminal.js.map +1 -0
- package/dist/tools/claude-hooks.d.ts +97 -0
- package/dist/tools/claude-hooks.d.ts.map +1 -0
- package/dist/tools/claude-hooks.js +348 -0
- package/dist/tools/claude-hooks.js.map +1 -0
- package/dist/tools/claude-process.d.ts +271 -0
- package/dist/tools/claude-process.d.ts.map +1 -0
- package/dist/tools/claude-process.js +931 -0
- package/dist/tools/claude-process.js.map +1 -0
- package/dist/tools/claude-sessions.d.ts +60 -0
- package/dist/tools/claude-sessions.d.ts.map +1 -0
- package/dist/tools/claude-sessions.js +285 -0
- package/dist/tools/claude-sessions.js.map +1 -0
- package/dist/tools/detector.d.ts +64 -0
- package/dist/tools/detector.d.ts.map +1 -0
- package/dist/tools/detector.js +383 -0
- package/dist/tools/detector.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +15 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/transcript-streamer.d.ts +68 -0
- package/dist/transcript-streamer.d.ts.map +1 -0
- package/dist/transcript-streamer.js +459 -0
- package/dist/transcript-streamer.js.map +1 -0
- package/dist/websocket.d.ts +133 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +247 -0
- package/dist/websocket.js.map +1 -0
- package/nul +0 -0
- package/package.json +54 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code Hooks Integration
|
|
4
|
+
*
|
|
5
|
+
* Integrates with Claude Code's hook system to:
|
|
6
|
+
* - Intercept tool usage (PreToolUse, PostToolUse)
|
|
7
|
+
* - Receive notifications
|
|
8
|
+
* - Request approvals before executing dangerous operations
|
|
9
|
+
*
|
|
10
|
+
* Claude Code hooks are configured in ~/.claude/settings.json
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.claudeHooksManager = void 0;
|
|
47
|
+
const fs = __importStar(require("fs"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const os = __importStar(require("os"));
|
|
50
|
+
const events_1 = require("events");
|
|
51
|
+
class ClaudeHooksManager extends events_1.EventEmitter {
|
|
52
|
+
constructor() {
|
|
53
|
+
super();
|
|
54
|
+
this.isConfigured = false;
|
|
55
|
+
this.claudeDir = path.join(os.homedir(), '.claude');
|
|
56
|
+
this.settingsPath = path.join(this.claudeDir, 'settings.json');
|
|
57
|
+
this.hookScriptPath = this.getHookScriptPath();
|
|
58
|
+
}
|
|
59
|
+
getHookScriptPath() {
|
|
60
|
+
const platform = os.platform();
|
|
61
|
+
if (platform === 'win32') {
|
|
62
|
+
return path.join(os.homedir(), '.forkoff', 'forkoff-hook.cmd');
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
return path.join(os.homedir(), '.forkoff', 'forkoff-hook');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if Claude Code is installed and hooks can be configured
|
|
70
|
+
*/
|
|
71
|
+
canConfigure() {
|
|
72
|
+
return fs.existsSync(this.claudeDir);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if ForkOff hooks are already configured
|
|
76
|
+
*/
|
|
77
|
+
isHookConfigured() {
|
|
78
|
+
if (!fs.existsSync(this.settingsPath)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const settings = this.readSettings();
|
|
83
|
+
const hookName = 'forkoff-hook';
|
|
84
|
+
// Check if any hook configuration references forkoff-hook
|
|
85
|
+
const hookTypes = ['PreToolUse', 'PostToolUse', 'Notification', 'Stop'];
|
|
86
|
+
for (const hookType of hookTypes) {
|
|
87
|
+
const hooks = settings.hooks?.[hookType];
|
|
88
|
+
if (hooks && hooks.some(h => h.hooks.includes(hookName))) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Read Claude settings
|
|
100
|
+
*/
|
|
101
|
+
readSettings() {
|
|
102
|
+
if (!fs.existsSync(this.settingsPath)) {
|
|
103
|
+
return {};
|
|
104
|
+
}
|
|
105
|
+
const content = fs.readFileSync(this.settingsPath, 'utf8');
|
|
106
|
+
return JSON.parse(content);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Write Claude settings
|
|
110
|
+
*/
|
|
111
|
+
writeSettings(settings) {
|
|
112
|
+
fs.writeFileSync(this.settingsPath, JSON.stringify(settings, null, 2));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Install ForkOff hooks into Claude Code
|
|
116
|
+
*/
|
|
117
|
+
async installHooks() {
|
|
118
|
+
if (!this.canConfigure()) {
|
|
119
|
+
throw new Error('Claude Code not found. Please install Claude Code first.');
|
|
120
|
+
}
|
|
121
|
+
// Create hook script directory
|
|
122
|
+
const hookDir = path.dirname(this.hookScriptPath);
|
|
123
|
+
if (!fs.existsSync(hookDir)) {
|
|
124
|
+
fs.mkdirSync(hookDir, { recursive: true });
|
|
125
|
+
}
|
|
126
|
+
// Create the hook script
|
|
127
|
+
await this.createHookScript();
|
|
128
|
+
// Update Claude settings
|
|
129
|
+
const settings = this.readSettings();
|
|
130
|
+
settings.hooks = settings.hooks || {};
|
|
131
|
+
const hookConfig = { matcher: '.*', hooks: ['forkoff-hook'] };
|
|
132
|
+
// Add hooks for all event types
|
|
133
|
+
settings.hooks.PreToolUse = settings.hooks.PreToolUse || [];
|
|
134
|
+
if (!settings.hooks.PreToolUse.some(h => h.hooks.includes('forkoff-hook'))) {
|
|
135
|
+
settings.hooks.PreToolUse.push(hookConfig);
|
|
136
|
+
}
|
|
137
|
+
settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
|
|
138
|
+
if (!settings.hooks.PostToolUse.some(h => h.hooks.includes('forkoff-hook'))) {
|
|
139
|
+
settings.hooks.PostToolUse.push(hookConfig);
|
|
140
|
+
}
|
|
141
|
+
settings.hooks.Notification = settings.hooks.Notification || [];
|
|
142
|
+
if (!settings.hooks.Notification.some(h => h.hooks.includes('forkoff-hook'))) {
|
|
143
|
+
settings.hooks.Notification.push(hookConfig);
|
|
144
|
+
}
|
|
145
|
+
this.writeSettings(settings);
|
|
146
|
+
this.isConfigured = true;
|
|
147
|
+
this.emit('hooks_installed');
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Create the hook script that Claude Code will execute
|
|
151
|
+
*/
|
|
152
|
+
async createHookScript() {
|
|
153
|
+
const platform = os.platform();
|
|
154
|
+
if (platform === 'win32') {
|
|
155
|
+
// Windows batch script
|
|
156
|
+
const script = `@echo off
|
|
157
|
+
node "%~dp0forkoff-hook.js" %*
|
|
158
|
+
`;
|
|
159
|
+
fs.writeFileSync(this.hookScriptPath, script);
|
|
160
|
+
// Create the Node.js script
|
|
161
|
+
const jsScript = this.getHookJsScript();
|
|
162
|
+
fs.writeFileSync(path.join(path.dirname(this.hookScriptPath), 'forkoff-hook.js'), jsScript);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// Unix shell script
|
|
166
|
+
const script = `#!/bin/bash
|
|
167
|
+
node "$(dirname "$0")/forkoff-hook.js" "$@"
|
|
168
|
+
`;
|
|
169
|
+
fs.writeFileSync(this.hookScriptPath, script, { mode: 0o755 });
|
|
170
|
+
// Create the Node.js script
|
|
171
|
+
const jsScript = this.getHookJsScript();
|
|
172
|
+
fs.writeFileSync(path.join(path.dirname(this.hookScriptPath), 'forkoff-hook.js'), jsScript);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get the JavaScript hook script content
|
|
177
|
+
*/
|
|
178
|
+
getHookJsScript() {
|
|
179
|
+
return `#!/usr/bin/env node
|
|
180
|
+
/**
|
|
181
|
+
* ForkOff Hook Script for Claude Code
|
|
182
|
+
* This script is called by Claude Code for hook events
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
const http = require('http');
|
|
186
|
+
const fs = require('fs');
|
|
187
|
+
const path = require('path');
|
|
188
|
+
|
|
189
|
+
// Read input from stdin
|
|
190
|
+
let input = '';
|
|
191
|
+
process.stdin.setEncoding('utf8');
|
|
192
|
+
process.stdin.on('data', (chunk) => {
|
|
193
|
+
input += chunk;
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
process.stdin.on('end', async () => {
|
|
197
|
+
try {
|
|
198
|
+
const hookData = JSON.parse(input);
|
|
199
|
+
|
|
200
|
+
// Try to send to ForkOff daemon
|
|
201
|
+
await sendToForkOff(hookData);
|
|
202
|
+
|
|
203
|
+
// By default, allow the operation to continue
|
|
204
|
+
const output = { continue: true };
|
|
205
|
+
console.log(JSON.stringify(output));
|
|
206
|
+
process.exit(0);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
// On error, still allow the operation
|
|
209
|
+
console.log(JSON.stringify({ continue: true }));
|
|
210
|
+
process.exit(0);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
async function sendToForkOff(hookData) {
|
|
215
|
+
return new Promise((resolve, reject) => {
|
|
216
|
+
// Read config to find daemon port
|
|
217
|
+
const configPath = path.join(require('os').homedir(), '.forkoff', 'config.json');
|
|
218
|
+
|
|
219
|
+
let port = 47471; // Default daemon port
|
|
220
|
+
try {
|
|
221
|
+
if (fs.existsSync(configPath)) {
|
|
222
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
223
|
+
port = config.daemonPort || port;
|
|
224
|
+
}
|
|
225
|
+
} catch {}
|
|
226
|
+
|
|
227
|
+
const data = JSON.stringify(hookData);
|
|
228
|
+
|
|
229
|
+
const options = {
|
|
230
|
+
hostname: '127.0.0.1',
|
|
231
|
+
port: port,
|
|
232
|
+
path: '/hook',
|
|
233
|
+
method: 'POST',
|
|
234
|
+
headers: {
|
|
235
|
+
'Content-Type': 'application/json',
|
|
236
|
+
'Content-Length': Buffer.byteLength(data)
|
|
237
|
+
},
|
|
238
|
+
timeout: 1000
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const req = http.request(options, (res) => {
|
|
242
|
+
let response = '';
|
|
243
|
+
res.on('data', (chunk) => response += chunk);
|
|
244
|
+
res.on('end', () => resolve(response));
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
req.on('error', () => resolve(null)); // Daemon not running, that's ok
|
|
248
|
+
req.on('timeout', () => {
|
|
249
|
+
req.destroy();
|
|
250
|
+
resolve(null);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
req.write(data);
|
|
254
|
+
req.end();
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
`;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Remove ForkOff hooks from Claude Code
|
|
261
|
+
*/
|
|
262
|
+
async uninstallHooks() {
|
|
263
|
+
if (!fs.existsSync(this.settingsPath)) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const settings = this.readSettings();
|
|
267
|
+
if (settings.hooks) {
|
|
268
|
+
// Remove forkoff-hook from all hook types
|
|
269
|
+
for (const hookType of ['PreToolUse', 'PostToolUse', 'Notification', 'Stop']) {
|
|
270
|
+
if (settings.hooks[hookType]) {
|
|
271
|
+
settings.hooks[hookType] = settings.hooks[hookType].filter(h => !h.hooks.includes('forkoff-hook'));
|
|
272
|
+
if (settings.hooks[hookType].length === 0) {
|
|
273
|
+
delete settings.hooks[hookType];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (Object.keys(settings.hooks).length === 0) {
|
|
278
|
+
delete settings.hooks;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
this.writeSettings(settings);
|
|
282
|
+
// Remove hook scripts
|
|
283
|
+
const hookDir = path.dirname(this.hookScriptPath);
|
|
284
|
+
if (fs.existsSync(hookDir)) {
|
|
285
|
+
try {
|
|
286
|
+
fs.rmSync(hookDir, { recursive: true });
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
// Ignore errors
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
this.isConfigured = false;
|
|
293
|
+
this.emit('hooks_uninstalled');
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Process a hook event (called by the hook script via local HTTP)
|
|
297
|
+
*/
|
|
298
|
+
processHookEvent(hookData) {
|
|
299
|
+
this.emit('hook_event', hookData);
|
|
300
|
+
switch (hookData.hook_type) {
|
|
301
|
+
case 'PreToolUse':
|
|
302
|
+
return this.handlePreToolUse(hookData);
|
|
303
|
+
case 'PostToolUse':
|
|
304
|
+
return this.handlePostToolUse(hookData);
|
|
305
|
+
case 'Notification':
|
|
306
|
+
return this.handleNotification(hookData);
|
|
307
|
+
case 'Stop':
|
|
308
|
+
return this.handleStop(hookData);
|
|
309
|
+
default:
|
|
310
|
+
return { continue: true };
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
handlePreToolUse(hookData) {
|
|
314
|
+
this.emit('pre_tool_use', {
|
|
315
|
+
toolName: hookData.tool_name,
|
|
316
|
+
toolInput: hookData.tool_input,
|
|
317
|
+
sessionId: hookData.session_id,
|
|
318
|
+
});
|
|
319
|
+
// For now, always allow - approval logic can be added later
|
|
320
|
+
return { continue: true };
|
|
321
|
+
}
|
|
322
|
+
handlePostToolUse(hookData) {
|
|
323
|
+
this.emit('post_tool_use', {
|
|
324
|
+
toolName: hookData.tool_name,
|
|
325
|
+
toolInput: hookData.tool_input,
|
|
326
|
+
toolOutput: hookData.tool_output,
|
|
327
|
+
sessionId: hookData.session_id,
|
|
328
|
+
});
|
|
329
|
+
return { continue: true };
|
|
330
|
+
}
|
|
331
|
+
handleNotification(hookData) {
|
|
332
|
+
this.emit('notification', {
|
|
333
|
+
message: hookData.message,
|
|
334
|
+
sessionId: hookData.session_id,
|
|
335
|
+
});
|
|
336
|
+
return { continue: true };
|
|
337
|
+
}
|
|
338
|
+
handleStop(hookData) {
|
|
339
|
+
this.emit('stop', {
|
|
340
|
+
sessionId: hookData.session_id,
|
|
341
|
+
transcriptPath: hookData.transcript_path,
|
|
342
|
+
});
|
|
343
|
+
return { continue: true };
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
exports.claudeHooksManager = new ClaudeHooksManager();
|
|
347
|
+
exports.default = exports.claudeHooksManager;
|
|
348
|
+
//# sourceMappingURL=claude-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-hooks.js","sourceRoot":"","sources":["../../src/tools/claude-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Process Manager
|
|
3
|
+
* Spawns and manages Claude CLI processes for terminal sessions
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
/**
|
|
7
|
+
* Represents a pending approval request that is waiting for user response.
|
|
8
|
+
* Used internally to track active approval requests and manage their timeouts.
|
|
9
|
+
*
|
|
10
|
+
* @interface PendingApproval
|
|
11
|
+
* @property {string} approvalId - Unique identifier for this approval request
|
|
12
|
+
* @property {string} terminalSessionId - The terminal session that triggered this approval
|
|
13
|
+
* @property {number} createdAt - Unix timestamp (ms) when the approval was created
|
|
14
|
+
* @property {NodeJS.Timeout} timeoutId - Reference to the timeout that will auto-deny if no response
|
|
15
|
+
*/
|
|
16
|
+
interface PendingApproval {
|
|
17
|
+
approvalId: string;
|
|
18
|
+
terminalSessionId: string;
|
|
19
|
+
createdAt: number;
|
|
20
|
+
timeoutId: NodeJS.Timeout;
|
|
21
|
+
}
|
|
22
|
+
interface ProcessOutputEvent {
|
|
23
|
+
terminalSessionId: string;
|
|
24
|
+
output: string;
|
|
25
|
+
type: 'stdout' | 'stderr' | 'exit';
|
|
26
|
+
exitCode?: number;
|
|
27
|
+
}
|
|
28
|
+
interface SessionEndedEvent {
|
|
29
|
+
terminalSessionId: string;
|
|
30
|
+
directory: string;
|
|
31
|
+
sessionKey?: string;
|
|
32
|
+
exitCode: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Event payload emitted when Claude CLI requests user approval.
|
|
36
|
+
* This is sent to the mobile app to display an approval dialog to the user.
|
|
37
|
+
*
|
|
38
|
+
* @interface ClaudeApprovalRequest
|
|
39
|
+
* @property {string} approvalId - Unique identifier for this approval request
|
|
40
|
+
* @property {string} terminalSessionId - The terminal session that triggered this approval
|
|
41
|
+
* @property {string} [sessionKey] - Optional Claude session key for session resumption
|
|
42
|
+
* @property {string[]} context - Recent output lines providing context for the approval
|
|
43
|
+
* @property {string[]} options - Available response options in "key:label" format
|
|
44
|
+
* (e.g., ['y:yes', 'n:no', 'p:plan'])
|
|
45
|
+
* @property {string} promptText - The actual approval prompt text from Claude CLI
|
|
46
|
+
*/
|
|
47
|
+
interface ClaudeApprovalRequest {
|
|
48
|
+
approvalId: string;
|
|
49
|
+
terminalSessionId: string;
|
|
50
|
+
sessionKey?: string;
|
|
51
|
+
context: string[];
|
|
52
|
+
options: string[];
|
|
53
|
+
promptText: string;
|
|
54
|
+
}
|
|
55
|
+
/** SDK message structure received from Claude CLI JSONL output */
|
|
56
|
+
interface SdkMessage {
|
|
57
|
+
type: string;
|
|
58
|
+
subtype?: string;
|
|
59
|
+
[key: string]: unknown;
|
|
60
|
+
}
|
|
61
|
+
/** Thinking content event payload */
|
|
62
|
+
interface ThinkingContentEvent {
|
|
63
|
+
terminalSessionId: string;
|
|
64
|
+
sessionKey?: string;
|
|
65
|
+
thinkingId: string;
|
|
66
|
+
content: string;
|
|
67
|
+
partial: boolean;
|
|
68
|
+
}
|
|
69
|
+
/** Token usage event payload */
|
|
70
|
+
interface TokenUsageEvent {
|
|
71
|
+
terminalSessionId: string;
|
|
72
|
+
sessionKey?: string;
|
|
73
|
+
usage: {
|
|
74
|
+
inputTokens: number;
|
|
75
|
+
outputTokens: number;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Task structure for task progress tracking */
|
|
79
|
+
interface TaskInfo {
|
|
80
|
+
id: string;
|
|
81
|
+
subject: string;
|
|
82
|
+
status: 'pending' | 'in_progress' | 'completed';
|
|
83
|
+
activeForm?: string;
|
|
84
|
+
}
|
|
85
|
+
/** Task progress event payload */
|
|
86
|
+
interface TaskProgressEvent {
|
|
87
|
+
terminalSessionId: string;
|
|
88
|
+
sessionKey?: string;
|
|
89
|
+
type: 'created' | 'updated' | 'completed' | 'list';
|
|
90
|
+
task?: TaskInfo;
|
|
91
|
+
tasks?: TaskInfo[];
|
|
92
|
+
}
|
|
93
|
+
/** Event payload for SDK messages */
|
|
94
|
+
interface SdkMessageEvent {
|
|
95
|
+
terminalSessionId: string;
|
|
96
|
+
message: SdkMessage;
|
|
97
|
+
}
|
|
98
|
+
/** Type-safe event signatures for ClaudeProcessManager */
|
|
99
|
+
interface ClaudeProcessManagerEvents {
|
|
100
|
+
output: [event: ProcessOutputEvent];
|
|
101
|
+
session_ended: [event: SessionEndedEvent];
|
|
102
|
+
sdk_message: [event: SdkMessageEvent];
|
|
103
|
+
claude_approval_request: [request: ClaudeApprovalRequest];
|
|
104
|
+
thinking_content: [event: ThinkingContentEvent];
|
|
105
|
+
token_usage: [event: TokenUsageEvent];
|
|
106
|
+
task_progress: [event: TaskProgressEvent];
|
|
107
|
+
}
|
|
108
|
+
declare class ClaudeProcessManager extends EventEmitter {
|
|
109
|
+
private processes;
|
|
110
|
+
private pendingApprovals;
|
|
111
|
+
private readonly APPROVAL_TIMEOUT_MS;
|
|
112
|
+
private readonly MAX_OUTPUT_BUFFER_LINES;
|
|
113
|
+
/** Track closed sessions for auto-restart */
|
|
114
|
+
private closedSessions;
|
|
115
|
+
/** Maximum number of auto-restarts per session to prevent chaos */
|
|
116
|
+
private readonly MAX_AUTO_RESTARTS;
|
|
117
|
+
/** Type-safe emit for known events */
|
|
118
|
+
emit<K extends keyof ClaudeProcessManagerEvents>(event: K, ...args: ClaudeProcessManagerEvents[K]): boolean;
|
|
119
|
+
/** Type-safe on for known events */
|
|
120
|
+
on<K extends keyof ClaudeProcessManagerEvents>(event: K, listener: (...args: ClaudeProcessManagerEvents[K]) => void): this;
|
|
121
|
+
/**
|
|
122
|
+
* Start a new Claude session in the specified directory
|
|
123
|
+
*/
|
|
124
|
+
startSession(directory: string, terminalSessionId: string): Promise<{
|
|
125
|
+
cwd: string;
|
|
126
|
+
}>;
|
|
127
|
+
/**
|
|
128
|
+
* Resume an existing Claude session
|
|
129
|
+
*/
|
|
130
|
+
resumeSession(sessionKey: string, directory: string, terminalSessionId: string): Promise<{
|
|
131
|
+
cwd: string;
|
|
132
|
+
}>;
|
|
133
|
+
/**
|
|
134
|
+
* Send input to a Claude process in JSONL format
|
|
135
|
+
* Format: {"type":"user","message":{"role":"user","content":"..."}}
|
|
136
|
+
*
|
|
137
|
+
* IMPORTANT: Claude SDK with --resume and streaming JSON only supports ONE turn per process.
|
|
138
|
+
* So we kill any existing process and spawn a fresh one for each message.
|
|
139
|
+
* Since we use --resume, the conversation history is preserved.
|
|
140
|
+
*/
|
|
141
|
+
sendInput(terminalSessionId: string, input: string): Promise<boolean>;
|
|
142
|
+
/**
|
|
143
|
+
* Check if a session is a Claude session (active or restartable)
|
|
144
|
+
*/
|
|
145
|
+
isClaudeSession(terminalSessionId: string): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Register session info without spawning a process.
|
|
148
|
+
* Used when mobile opens a session view - we store the info so we can spawn later on first message.
|
|
149
|
+
*/
|
|
150
|
+
registerSession(sessionKey: string, directory: string, terminalSessionId: string): void;
|
|
151
|
+
/**
|
|
152
|
+
* Set up event handlers for the spawned process
|
|
153
|
+
*/
|
|
154
|
+
private setupProcessHandlers;
|
|
155
|
+
/**
|
|
156
|
+
* Resolve path (handle ~ for home directory)
|
|
157
|
+
* SECURITY: Validates path doesn't contain dangerous characters
|
|
158
|
+
*/
|
|
159
|
+
private resolvePath;
|
|
160
|
+
/**
|
|
161
|
+
* Kill a Claude process
|
|
162
|
+
*/
|
|
163
|
+
killProcess(terminalSessionId: string): void;
|
|
164
|
+
/**
|
|
165
|
+
* Get all active process IDs
|
|
166
|
+
*/
|
|
167
|
+
getActiveProcessIds(): string[];
|
|
168
|
+
/**
|
|
169
|
+
* Get all active sessions with their details
|
|
170
|
+
*/
|
|
171
|
+
getActiveSessions(): Array<{
|
|
172
|
+
terminalSessionId: string;
|
|
173
|
+
sessionKey?: string;
|
|
174
|
+
directory: string;
|
|
175
|
+
}>;
|
|
176
|
+
/**
|
|
177
|
+
* Clean up old closed session entries to prevent memory leaks.
|
|
178
|
+
* Sessions older than 1 hour are removed.
|
|
179
|
+
*/
|
|
180
|
+
cleanupOldClosedSessions(): void;
|
|
181
|
+
/**
|
|
182
|
+
* Clear restart counter for a session, allowing fresh restarts.
|
|
183
|
+
* Useful when user explicitly wants to reset.
|
|
184
|
+
*/
|
|
185
|
+
clearRestartCounter(terminalSessionId: string): void;
|
|
186
|
+
/**
|
|
187
|
+
* Checks Claude CLI output for approval patterns and emits approval request events.
|
|
188
|
+
*
|
|
189
|
+
* Scans the output against all patterns in APPROVAL_PATTERNS. When a match is found,
|
|
190
|
+
* creates a unique approval ID, sets up a timeout for auto-denial, and emits a
|
|
191
|
+
* 'claude_approval_request' event with the approval details.
|
|
192
|
+
*
|
|
193
|
+
* Prevents duplicate approvals for the same terminal session.
|
|
194
|
+
*
|
|
195
|
+
* @param {string} terminalSessionId - The terminal session ID producing the output
|
|
196
|
+
* @param {string} output - Raw output text from the Claude CLI process
|
|
197
|
+
* @param {ClaudeProcessInfo} processInfo - Process information including output buffer
|
|
198
|
+
* @fires ClaudeProcessManager#claude_approval_request
|
|
199
|
+
* @private
|
|
200
|
+
*/
|
|
201
|
+
private checkForApprovalPattern;
|
|
202
|
+
/**
|
|
203
|
+
* Checks SDK messages for tool_use content and emits approval notifications.
|
|
204
|
+
*
|
|
205
|
+
* In SDK mode, Claude doesn't emit text approval prompts. Instead, we detect
|
|
206
|
+
* tool_use in the SDK messages and emit approval notifications so the mobile
|
|
207
|
+
* app can display what Claude is doing. Note: This is a notification, not
|
|
208
|
+
* a blocking approval - the tool may already be executed by the time the
|
|
209
|
+
* user sees this.
|
|
210
|
+
*
|
|
211
|
+
* @param {string} terminalSessionId - The terminal session ID
|
|
212
|
+
* @param {any} message - The parsed SDK JSON message
|
|
213
|
+
* @param {ClaudeProcessInfo} processInfo - Process info for context
|
|
214
|
+
* @private
|
|
215
|
+
*/
|
|
216
|
+
private checkForToolUseInSdkMessage;
|
|
217
|
+
/**
|
|
218
|
+
* Handles approval request timeout by automatically denying the request.
|
|
219
|
+
*
|
|
220
|
+
* Called when the approval timeout (APPROVAL_TIMEOUT_MS) expires without
|
|
221
|
+
* receiving a user response. Automatically sends 'n' (no/deny) to the
|
|
222
|
+
* Claude CLI process to prevent indefinite blocking.
|
|
223
|
+
*
|
|
224
|
+
* @param {string} approvalId - The unique identifier of the timed-out approval
|
|
225
|
+
* @private
|
|
226
|
+
*/
|
|
227
|
+
private handleApprovalTimeout;
|
|
228
|
+
/**
|
|
229
|
+
* Handles an approval response received from the mobile app.
|
|
230
|
+
*
|
|
231
|
+
* Processes the user's response to an approval request by:
|
|
232
|
+
* 1. Looking up the pending approval by ID
|
|
233
|
+
* 2. Clearing the auto-deny timeout
|
|
234
|
+
* 3. Writing the response character (e.g., 'y', 'n', 'p') to the Claude CLI stdin
|
|
235
|
+
*
|
|
236
|
+
* @param {string} approvalId - The unique identifier of the approval being responded to
|
|
237
|
+
* @param {string} response - The user's response (first character will be sent to stdin)
|
|
238
|
+
* @public
|
|
239
|
+
*/
|
|
240
|
+
handleApprovalResponse(approvalId: string, response: string): void;
|
|
241
|
+
/**
|
|
242
|
+
* Retrieves a pending approval request for a specific terminal session.
|
|
243
|
+
*
|
|
244
|
+
* Searches through all pending approvals to find one matching the given
|
|
245
|
+
* terminal session ID. Useful for checking if there's an active approval
|
|
246
|
+
* request for a session before creating a new one.
|
|
247
|
+
*
|
|
248
|
+
* @param {string} terminalSessionId - The terminal session ID to search for
|
|
249
|
+
* @returns {PendingApproval | undefined} The pending approval if found, undefined otherwise
|
|
250
|
+
* @public
|
|
251
|
+
*/
|
|
252
|
+
getPendingApproval(terminalSessionId: string): PendingApproval | undefined;
|
|
253
|
+
/**
|
|
254
|
+
* Parse thinking content from SDK messages.
|
|
255
|
+
* Claude SDK emits content_block_delta with type 'thinking' for extended thinking.
|
|
256
|
+
*/
|
|
257
|
+
private parseThinkingContent;
|
|
258
|
+
/**
|
|
259
|
+
* Parse token usage from SDK messages.
|
|
260
|
+
* Claude SDK emits message_delta with usage field containing token counts.
|
|
261
|
+
*/
|
|
262
|
+
private parseTokenUsage;
|
|
263
|
+
/**
|
|
264
|
+
* Parse task progress from SDK messages.
|
|
265
|
+
* Detects TaskCreate, TaskUpdate, TaskList tool uses and extracts task data.
|
|
266
|
+
*/
|
|
267
|
+
private parseTaskProgress;
|
|
268
|
+
}
|
|
269
|
+
export declare const claudeProcessManager: ClaudeProcessManager;
|
|
270
|
+
export default claudeProcessManager;
|
|
271
|
+
//# sourceMappingURL=claude-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-process.d.ts","sourceRoot":"","sources":["../../src/tools/claude-process.ts"],"names":[],"mappings":"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"}
|