seahorse-bash-client 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/DESIGN.md ADDED
@@ -0,0 +1,463 @@
1
+ # Seahorse Bash Client - MCP Tool Design
2
+
3
+ ## 개요
4
+
5
+ Stateful bash 머신에서 Seahorse Agent에 역방향 연결하여 PTY 기반 bash 도구를 제공하는 MCP 클라이언트.
6
+
7
+ ## 아키텍처
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────┐
11
+ │ Seahorse Agent Server │
12
+ │ ┌─────────────────┐ ┌─────────────────────────────────┐ │
13
+ │ │ RemoteMCPProvider│◄───│ RemoteMCPConnectionManager │ │
14
+ │ │ (call_tool) │ │ (WebSocket, tool registry) │ │
15
+ │ └─────────────────┘ └───────────────▲─────────────────┘ │
16
+ └──────────────────────────────────────────│──────────────────┘
17
+ │ WebSocket (wss://)
18
+ │ Reverse Connection
19
+ ┌──────────────────────────────────────────│──────────────────┐
20
+ │ Seahorse Bash Client │ │
21
+ │ ┌─────────────────────────────────────────────────────────┐ │
22
+ │ │ WebSocket Client │ │
23
+ │ │ - 서버에 연결 및 tool 등록 │ │
24
+ │ │ - tool_call 수신 → PTY Manager 호출 → 응답 전송 │ │
25
+ │ └─────────────────────────────────────────────────────────┘ │
26
+ │ ┌─────────────────────────────────────────────────────────┐ │
27
+ │ │ PTY Manager (node-pty) │ │
28
+ │ │ - 다중 PTY 세션 관리 │ │
29
+ │ │ - Rolling output buffer (50,000줄) │ │
30
+ │ │ - Exit notification │ │
31
+ │ └─────────────────────────────────────────────────────────┘ │
32
+ └─────────────────────────────────────────────────────────────┘
33
+ ```
34
+
35
+ ## MCP Tools 정의
36
+
37
+ ### 1. `bash_spawn` - PTY 세션 생성 및 명령 실행
38
+
39
+ **용도**: 새로운 PTY 세션을 생성하고 백그라운드에서 명령 실행
40
+
41
+ **Input Schema**:
42
+ ```json
43
+ {
44
+ "type": "object",
45
+ "properties": {
46
+ "command": {
47
+ "type": "string",
48
+ "description": "실행할 명령어 (예: 'npm run dev', 'python server.py')"
49
+ },
50
+ "args": {
51
+ "type": "array",
52
+ "items": { "type": "string" },
53
+ "description": "명령어 인자 (선택)"
54
+ },
55
+ "cwd": {
56
+ "type": "string",
57
+ "description": "작업 디렉토리 (기본: 현재 디렉토리)"
58
+ },
59
+ "env": {
60
+ "type": "object",
61
+ "additionalProperties": { "type": "string" },
62
+ "description": "환경 변수 (기존 환경에 추가)"
63
+ },
64
+ "name": {
65
+ "type": "string",
66
+ "description": "세션 이름/식별자 (선택, 자동 생성)"
67
+ },
68
+ "shell": {
69
+ "type": "string",
70
+ "enum": ["bash", "sh", "zsh"],
71
+ "default": "bash",
72
+ "description": "사용할 쉘"
73
+ },
74
+ "cols": {
75
+ "type": "integer",
76
+ "default": 120,
77
+ "description": "터미널 컬럼 수"
78
+ },
79
+ "rows": {
80
+ "type": "integer",
81
+ "default": 30,
82
+ "description": "터미널 행 수"
83
+ },
84
+ "notifyOnExit": {
85
+ "type": "boolean",
86
+ "default": true,
87
+ "description": "프로세스 종료 시 알림 여부"
88
+ }
89
+ },
90
+ "required": ["command"]
91
+ }
92
+ ```
93
+
94
+ **Response**:
95
+ ```json
96
+ {
97
+ "sessionId": "pty_a1b2c3d4",
98
+ "pid": 12345,
99
+ "command": "npm run dev",
100
+ "status": "running",
101
+ "message": "Session created and command started"
102
+ }
103
+ ```
104
+
105
+ ---
106
+
107
+ ### 2. `bash_exec` - 동기 명령 실행 (단일 명령)
108
+
109
+ **용도**: 단일 명령을 실행하고 완료될 때까지 대기 (기존 bash 세션 재사용)
110
+
111
+ **Input Schema**:
112
+ ```json
113
+ {
114
+ "type": "object",
115
+ "properties": {
116
+ "command": {
117
+ "type": "string",
118
+ "description": "실행할 bash 명령어"
119
+ },
120
+ "cwd": {
121
+ "type": "string",
122
+ "description": "작업 디렉토리 (선택)"
123
+ },
124
+ "timeout": {
125
+ "type": "integer",
126
+ "default": 30000,
127
+ "description": "타임아웃 (밀리초, 기본 30초, 최대 600초)"
128
+ },
129
+ "env": {
130
+ "type": "object",
131
+ "additionalProperties": { "type": "string" },
132
+ "description": "추가 환경 변수"
133
+ }
134
+ },
135
+ "required": ["command"]
136
+ }
137
+ ```
138
+
139
+ **Response**:
140
+ ```json
141
+ {
142
+ "exitCode": 0,
143
+ "stdout": "명령 출력...",
144
+ "stderr": "",
145
+ "duration": 1234,
146
+ "timedOut": false
147
+ }
148
+ ```
149
+
150
+ ---
151
+
152
+ ### 3. `bash_write` - PTY 세션에 입력 전송
153
+
154
+ **용도**: 실행 중인 PTY 세션에 키 입력 전송 (Ctrl+C, 텍스트 입력 등)
155
+
156
+ **Input Schema**:
157
+ ```json
158
+ {
159
+ "type": "object",
160
+ "properties": {
161
+ "sessionId": {
162
+ "type": "string",
163
+ "description": "대상 세션 ID"
164
+ },
165
+ "data": {
166
+ "type": "string",
167
+ "description": "전송할 데이터 (텍스트 또는 이스케이프 시퀀스)"
168
+ },
169
+ "specialKey": {
170
+ "type": "string",
171
+ "enum": ["ctrl+c", "ctrl+d", "ctrl+z", "enter", "tab", "up", "down", "left", "right"],
172
+ "description": "특수 키 (data 대신 사용 가능)"
173
+ }
174
+ },
175
+ "required": ["sessionId"],
176
+ "oneOf": [
177
+ { "required": ["data"] },
178
+ { "required": ["specialKey"] }
179
+ ]
180
+ }
181
+ ```
182
+
183
+ **Special Key Mappings**:
184
+ - `ctrl+c` → `\x03` (SIGINT)
185
+ - `ctrl+d` → `\x04` (EOF)
186
+ - `ctrl+z` → `\x1a` (SIGTSTP - 백그라운드 전환)
187
+ - `enter` → `\r`
188
+ - `tab` → `\t`
189
+ - `up` → `\x1b[A`
190
+ - `down` → `\x1b[B`
191
+
192
+ **Response**:
193
+ ```json
194
+ {
195
+ "success": true,
196
+ "bytesWritten": 1,
197
+ "sessionStatus": "running"
198
+ }
199
+ ```
200
+
201
+ ---
202
+
203
+ ### 4. `bash_read` - PTY 세션 출력 읽기
204
+
205
+ **용도**: PTY 세션의 버퍼된 출력을 페이지네이션과 필터링으로 조회
206
+
207
+ **Input Schema**:
208
+ ```json
209
+ {
210
+ "type": "object",
211
+ "properties": {
212
+ "sessionId": {
213
+ "type": "string",
214
+ "description": "대상 세션 ID"
215
+ },
216
+ "offset": {
217
+ "type": "integer",
218
+ "default": 0,
219
+ "description": "시작 줄 번호 (0부터)"
220
+ },
221
+ "limit": {
222
+ "type": "integer",
223
+ "default": 100,
224
+ "maximum": 1000,
225
+ "description": "반환할 최대 줄 수"
226
+ },
227
+ "pattern": {
228
+ "type": "string",
229
+ "description": "필터링 정규식 (선택)"
230
+ },
231
+ "ignoreCase": {
232
+ "type": "boolean",
233
+ "default": false,
234
+ "description": "대소문자 무시"
235
+ },
236
+ "since": {
237
+ "type": "string",
238
+ "format": "date-time",
239
+ "description": "특정 시간 이후의 출력만 (선택)"
240
+ },
241
+ "tail": {
242
+ "type": "boolean",
243
+ "default": false,
244
+ "description": "true면 마지막 N줄 반환"
245
+ }
246
+ },
247
+ "required": ["sessionId"]
248
+ }
249
+ ```
250
+
251
+ **Response**:
252
+ ```json
253
+ {
254
+ "sessionId": "pty_a1b2c3d4",
255
+ "lines": [
256
+ {"line": 1, "text": "Server starting...", "timestamp": "2024-01-01T00:00:00Z"},
257
+ {"line": 2, "text": "Listening on port 3000", "timestamp": "2024-01-01T00:00:01Z"}
258
+ ],
259
+ "totalLines": 150,
260
+ "hasMore": true,
261
+ "sessionStatus": "running"
262
+ }
263
+ ```
264
+
265
+ ---
266
+
267
+ ### 5. `bash_list` - 모든 PTY 세션 목록
268
+
269
+ **용도**: 현재 활성화된 모든 PTY 세션 정보 조회
270
+
271
+ **Input Schema**:
272
+ ```json
273
+ {
274
+ "type": "object",
275
+ "properties": {
276
+ "status": {
277
+ "type": "string",
278
+ "enum": ["all", "running", "exited", "killed"],
279
+ "default": "all",
280
+ "description": "필터링할 상태"
281
+ },
282
+ "includeOutput": {
283
+ "type": "boolean",
284
+ "default": false,
285
+ "description": "각 세션의 최근 출력 포함 여부"
286
+ },
287
+ "outputLines": {
288
+ "type": "integer",
289
+ "default": 5,
290
+ "description": "includeOutput=true일 때 포함할 줄 수"
291
+ }
292
+ }
293
+ }
294
+ ```
295
+
296
+ **Response**:
297
+ ```json
298
+ {
299
+ "sessions": [
300
+ {
301
+ "sessionId": "pty_a1b2c3d4",
302
+ "name": "dev-server",
303
+ "pid": 12345,
304
+ "command": "npm run dev",
305
+ "status": "running",
306
+ "createdAt": "2024-01-01T00:00:00Z",
307
+ "lineCount": 150,
308
+ "cwd": "/home/user/project",
309
+ "recentOutput": ["Server running on port 3000"]
310
+ }
311
+ ],
312
+ "summary": {
313
+ "total": 3,
314
+ "running": 2,
315
+ "exited": 1,
316
+ "killed": 0
317
+ }
318
+ }
319
+ ```
320
+
321
+ ---
322
+
323
+ ### 6. `bash_kill` - PTY 세션 종료
324
+
325
+ **용도**: 실행 중인 PTY 세션 종료 및 정리
326
+
327
+ **Input Schema**:
328
+ ```json
329
+ {
330
+ "type": "object",
331
+ "properties": {
332
+ "sessionId": {
333
+ "type": "string",
334
+ "description": "종료할 세션 ID"
335
+ },
336
+ "signal": {
337
+ "type": "string",
338
+ "enum": ["SIGTERM", "SIGKILL", "SIGINT"],
339
+ "default": "SIGTERM",
340
+ "description": "전송할 시그널"
341
+ },
342
+ "cleanup": {
343
+ "type": "boolean",
344
+ "default": false,
345
+ "description": "true면 세션 목록에서도 제거 (출력 버퍼 삭제)"
346
+ },
347
+ "gracePeriod": {
348
+ "type": "integer",
349
+ "default": 5000,
350
+ "description": "SIGTERM 후 SIGKILL까지 대기 시간 (ms)"
351
+ }
352
+ },
353
+ "required": ["sessionId"]
354
+ }
355
+ ```
356
+
357
+ **Response**:
358
+ ```json
359
+ {
360
+ "sessionId": "pty_a1b2c3d4",
361
+ "exitCode": 143,
362
+ "signal": "SIGTERM",
363
+ "cleaned": false,
364
+ "finalLineCount": 200,
365
+ "message": "Session terminated successfully"
366
+ }
367
+ ```
368
+
369
+ ---
370
+
371
+ ## WebSocket 프로토콜
372
+
373
+ ### 연결 시 등록 메시지
374
+
375
+ ```json
376
+ {
377
+ "type": "register",
378
+ "server_name": "bash-client-hostname",
379
+ "tools": [
380
+ {
381
+ "name": "bash_spawn",
382
+ "description": "Create a new PTY session and run a command in background",
383
+ "inputSchema": { /* 위의 스키마 */ }
384
+ },
385
+ // ... 나머지 tools
386
+ ],
387
+ "metadata": {
388
+ "version": "1.0.0",
389
+ "hostname": "my-dev-machine",
390
+ "platform": "darwin",
391
+ "shell": "/bin/bash"
392
+ }
393
+ }
394
+ ```
395
+
396
+ ### Tool Call 요청 (Agent → Client)
397
+
398
+ ```json
399
+ {
400
+ "type": "tool_call",
401
+ "request_id": "server_name:uuid",
402
+ "method": "tools/call",
403
+ "params": {
404
+ "name": "bash_spawn",
405
+ "arguments": {
406
+ "command": "npm run dev",
407
+ "cwd": "/home/user/project",
408
+ "notifyOnExit": true
409
+ }
410
+ }
411
+ }
412
+ ```
413
+
414
+ ### Tool Call 응답 (Client → Agent)
415
+
416
+ ```json
417
+ {
418
+ "type": "tool_response",
419
+ "request_id": "server_name:uuid",
420
+ "content": [
421
+ {
422
+ "type": "text",
423
+ "text": "{\"sessionId\": \"pty_a1b2c3d4\", \"pid\": 12345, ...}"
424
+ }
425
+ ],
426
+ "isError": false
427
+ }
428
+ ```
429
+
430
+ ### Exit Notification (Client → Agent)
431
+
432
+ ```json
433
+ {
434
+ "type": "notification",
435
+ "method": "session/exited",
436
+ "params": {
437
+ "sessionId": "pty_a1b2c3d4",
438
+ "exitCode": 0,
439
+ "signal": null,
440
+ "duration": 12345,
441
+ "finalLineCount": 500
442
+ }
443
+ }
444
+ ```
445
+
446
+ ---
447
+
448
+ ## 보안 고려사항
449
+
450
+ 1. **명령 필터링**: 위험한 명령 (`rm -rf /`, `:(){ :|:& };:` 등) 차단 옵션
451
+ 2. **작업 디렉토리 제한**: 특정 디렉토리 하위로만 cwd 제한 가능
452
+ 3. **리소스 제한**: ulimit을 통한 메모리/CPU 제한
453
+ 4. **감사 로깅**: 모든 명령 실행 기록
454
+
455
+ ## 구현 우선순위
456
+
457
+ 1. ✅ WebSocket 역방향 연결
458
+ 2. ✅ `bash_exec` (동기 명령 - 가장 기본)
459
+ 3. ✅ `bash_spawn` (백그라운드 실행)
460
+ 4. ✅ `bash_read` (출력 읽기)
461
+ 5. ✅ `bash_write` (입력 전송)
462
+ 6. ✅ `bash_list` (세션 목록)
463
+ 7. ✅ `bash_kill` (세션 종료)
package/bin/cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/cli.js');
package/dist/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Seahorse Bash Client CLI
4
+ *
5
+ * Connects to Seahorse Agent and provides PTY-based bash tools.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;GAIG"}
package/dist/cli.js ADDED
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Seahorse Bash Client CLI
5
+ *
6
+ * Connects to Seahorse Agent and provides PTY-based bash tools.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const commander_1 = require("commander");
46
+ const chalk_1 = __importDefault(require("chalk"));
47
+ const ora_1 = __importDefault(require("ora"));
48
+ const os_1 = __importDefault(require("os"));
49
+ const websocket_client_1 = require("./websocket-client");
50
+ const VERSION = '1.0.0';
51
+ const program = new commander_1.Command();
52
+ program
53
+ .name('seahorse-bash')
54
+ .description('Seahorse Bash Client - PTY-based bash tools for Seahorse Agent')
55
+ .version(VERSION);
56
+ program
57
+ .command('connect')
58
+ .description('Connect to Seahorse Agent and provide bash tools')
59
+ .requiredOption('-u, --url <url>', 'Seahorse Agent WebSocket URL (e.g., wss://agent.example.com/ws/remote-mcp)')
60
+ .option('-n, --name <name>', 'Server name for identification', `bash-${os_1.default.hostname()}`)
61
+ .option('-s, --shell <shell>', 'Default shell to use', process.env.SHELL || '/bin/bash')
62
+ .option('--reconnect-interval <ms>', 'Reconnect interval in milliseconds', '5000')
63
+ .option('--heartbeat-interval <ms>', 'Heartbeat interval in milliseconds', '30000')
64
+ .option('--max-output-lines <lines>', 'Maximum output lines to buffer per session', '50000')
65
+ .option('--allowed-commands <cmds>', 'Comma-separated list of allowed command prefixes')
66
+ .option('--blocked-commands <cmds>', 'Comma-separated list of blocked command patterns')
67
+ .option('--allowed-cwd <paths>', 'Comma-separated list of allowed working directory paths')
68
+ .option('-k, --insecure', 'Skip SSL certificate verification (for self-signed certs)')
69
+ .action(async (options) => {
70
+ const spinner = (0, ora_1.default)('Connecting to Seahorse Agent...').start();
71
+ const config = {
72
+ serverUrl: options.url,
73
+ serverName: options.name,
74
+ defaultShell: options.shell,
75
+ reconnectInterval: parseInt(options.reconnectInterval, 10),
76
+ heartbeatInterval: parseInt(options.heartbeatInterval, 10),
77
+ maxOutputLines: parseInt(options.maxOutputLines, 10),
78
+ allowedCommands: options.allowedCommands?.split(',').map((s) => s.trim()),
79
+ blockedCommands: options.blockedCommands?.split(',').map((s) => s.trim()),
80
+ allowedCwdPaths: options.allowedCwd?.split(',').map((s) => s.trim()),
81
+ insecure: options.insecure || false,
82
+ };
83
+ const client = new websocket_client_1.WebSocketClient(config);
84
+ // Event handlers
85
+ client.on('connected', () => {
86
+ spinner.succeed(chalk_1.default.green('Connected to Seahorse Agent'));
87
+ console.log(chalk_1.default.gray(` Server name: ${config.serverName}`));
88
+ console.log(chalk_1.default.gray(` Shell: ${config.defaultShell}`));
89
+ console.log(chalk_1.default.gray(` Platform: ${process.platform}`));
90
+ console.log();
91
+ console.log(chalk_1.default.cyan('Listening for tool calls...'));
92
+ console.log(chalk_1.default.gray('Press Ctrl+C to disconnect'));
93
+ console.log();
94
+ });
95
+ client.on('registered', ({ tools }) => {
96
+ console.log(chalk_1.default.green(`Registered ${tools.length} tools:`));
97
+ tools.forEach((tool) => {
98
+ console.log(chalk_1.default.gray(` - ${tool.name}`));
99
+ });
100
+ console.log();
101
+ });
102
+ client.on('disconnected', ({ code, reason }) => {
103
+ console.log(chalk_1.default.yellow(`Disconnected (code: ${code}, reason: ${reason})`));
104
+ });
105
+ client.on('reconnecting', ({ interval }) => {
106
+ console.log(chalk_1.default.yellow(`Reconnecting in ${interval}ms...`));
107
+ });
108
+ client.on('error', (error) => {
109
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
110
+ });
111
+ client.on('tool:call', ({ name, requestId }) => {
112
+ console.log(chalk_1.default.blue(`[${new Date().toISOString()}] Tool call: ${name} (${requestId})`));
113
+ });
114
+ client.on('tool:success', ({ name, requestId }) => {
115
+ console.log(chalk_1.default.green(`[${new Date().toISOString()}] Tool success: ${name} (${requestId})`));
116
+ });
117
+ client.on('tool:error', ({ name, requestId, error }) => {
118
+ console.log(chalk_1.default.red(`[${new Date().toISOString()}] Tool error: ${name} (${requestId}): ${error}`));
119
+ });
120
+ client.on('notification:sent', ({ method }) => {
121
+ console.log(chalk_1.default.magenta(`[${new Date().toISOString()}] Notification: ${method}`));
122
+ });
123
+ // Graceful shutdown
124
+ const shutdown = async () => {
125
+ console.log();
126
+ console.log(chalk_1.default.yellow('Shutting down...'));
127
+ await client.disconnect();
128
+ console.log(chalk_1.default.green('Disconnected. Goodbye!'));
129
+ process.exit(0);
130
+ };
131
+ process.on('SIGINT', shutdown);
132
+ process.on('SIGTERM', shutdown);
133
+ // Connect
134
+ try {
135
+ await client.connect();
136
+ }
137
+ catch (error) {
138
+ spinner.fail(chalk_1.default.red(`Failed to connect: ${error instanceof Error ? error.message : error}`));
139
+ process.exit(1);
140
+ }
141
+ });
142
+ program
143
+ .command('test')
144
+ .description('Test PTY functionality locally (without connecting to agent)')
145
+ .option('-c, --command <cmd>', 'Command to execute', 'echo "Hello from PTY!"')
146
+ .option('-s, --shell <shell>', 'Shell to use', process.env.SHELL || '/bin/bash')
147
+ .action(async (options) => {
148
+ const { PTYManager } = await Promise.resolve().then(() => __importStar(require('./pty-manager')));
149
+ const ptyManager = new PTYManager({ defaultShell: options.shell });
150
+ console.log(chalk_1.default.cyan('Testing PTY Manager...'));
151
+ console.log();
152
+ // Test bash_exec
153
+ console.log(chalk_1.default.yellow('1. Testing bash_exec:'));
154
+ const execResult = await ptyManager.exec({ command: options.command });
155
+ console.log(chalk_1.default.gray(` Exit code: ${execResult.exitCode}`));
156
+ console.log(chalk_1.default.gray(` Duration: ${execResult.duration}ms`));
157
+ console.log(chalk_1.default.gray(` Output: ${execResult.stdout}`));
158
+ console.log();
159
+ // Test bash_spawn
160
+ console.log(chalk_1.default.yellow('2. Testing bash_spawn:'));
161
+ const spawnResult = await ptyManager.spawn({
162
+ command: 'for i in 1 2 3; do echo "Count: $i"; sleep 0.5; done',
163
+ name: 'test-session',
164
+ });
165
+ console.log(chalk_1.default.gray(` Session ID: ${spawnResult.sessionId}`));
166
+ console.log(chalk_1.default.gray(` PID: ${spawnResult.pid}`));
167
+ // Wait for output
168
+ await new Promise((resolve) => setTimeout(resolve, 2000));
169
+ // Test bash_read
170
+ console.log();
171
+ console.log(chalk_1.default.yellow('3. Testing bash_read:'));
172
+ const readResult = ptyManager.read({ sessionId: spawnResult.sessionId, tail: true, limit: 10 });
173
+ console.log(chalk_1.default.gray(` Total lines: ${readResult.totalLines}`));
174
+ readResult.lines.forEach((line) => {
175
+ console.log(chalk_1.default.gray(` [${line.line}] ${line.text}`));
176
+ });
177
+ // Test bash_list
178
+ console.log();
179
+ console.log(chalk_1.default.yellow('4. Testing bash_list:'));
180
+ const listResult = ptyManager.list({});
181
+ console.log(chalk_1.default.gray(` Total sessions: ${listResult.summary.total}`));
182
+ console.log(chalk_1.default.gray(` Running: ${listResult.summary.running}`));
183
+ console.log(chalk_1.default.gray(` Exited: ${listResult.summary.exited}`));
184
+ // Cleanup
185
+ await ptyManager.shutdown();
186
+ console.log();
187
+ console.log(chalk_1.default.green('All tests passed!'));
188
+ });
189
+ program.parse();
190
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}