treesap 0.1.13 → 0.2.1
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 +31 -192
- package/dist/app.d.ts +28 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +184 -0
- package/dist/app.js.map +1 -0
- package/dist/context.d.ts +36 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +95 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -9
- package/dist/index.js.map +1 -1
- package/dist/middleware/cors.d.ts +11 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/cors.js +34 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/serve-static.d.ts +6 -0
- package/dist/middleware/serve-static.d.ts.map +1 -0
- package/dist/middleware/serve-static.js +68 -0
- package/dist/middleware/serve-static.js.map +1 -0
- package/dist/node.d.ts +8 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +52 -0
- package/dist/node.js.map +1 -0
- package/dist/path.d.ts +10 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +45 -0
- package/dist/path.js.map +1 -0
- package/dist/vite.d.ts +31 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +278 -0
- package/dist/vite.js.map +1 -0
- package/package.json +33 -40
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -137
- package/dist/cli.js.map +0 -1
- package/dist/components/BaseHead.d.ts +0 -5
- package/dist/components/BaseHead.d.ts.map +0 -1
- package/dist/components/BaseHead.js +0 -161
- package/dist/components/BaseHead.js.map +0 -1
- package/dist/components/ChatInput.d.ts +0 -7
- package/dist/components/ChatInput.d.ts.map +0 -1
- package/dist/components/ChatInput.js +0 -11
- package/dist/components/ChatInput.js.map +0 -1
- package/dist/components/Sidebar.d.ts +0 -8
- package/dist/components/Sidebar.d.ts.map +0 -1
- package/dist/components/Sidebar.js +0 -7
- package/dist/components/Sidebar.js.map +0 -1
- package/dist/components/SimpleLivePreview.d.ts +0 -7
- package/dist/components/SimpleLivePreview.d.ts.map +0 -1
- package/dist/components/SimpleLivePreview.js +0 -7
- package/dist/components/SimpleLivePreview.js.map +0 -1
- package/dist/components/Terminal.d.ts +0 -7
- package/dist/components/Terminal.d.ts.map +0 -1
- package/dist/components/Terminal.js +0 -14
- package/dist/components/Terminal.js.map +0 -1
- package/dist/components/VoiceRecorder.d.ts +0 -4
- package/dist/components/VoiceRecorder.d.ts.map +0 -1
- package/dist/components/VoiceRecorder.js +0 -5
- package/dist/components/VoiceRecorder.js.map +0 -1
- package/dist/components/icons/GeminiLogo.d.ts +0 -7
- package/dist/components/icons/GeminiLogo.d.ts.map +0 -1
- package/dist/components/icons/GeminiLogo.js +0 -5
- package/dist/components/icons/GeminiLogo.js.map +0 -1
- package/dist/components/icons/OllamaLogo.d.ts +0 -2
- package/dist/components/icons/OllamaLogo.d.ts.map +0 -1
- package/dist/components/icons/OllamaLogo.js +0 -5
- package/dist/components/icons/OllamaLogo.js.map +0 -1
- package/dist/layouts/Layout.d.ts +0 -9
- package/dist/layouts/Layout.d.ts.map +0 -1
- package/dist/layouts/Layout.js +0 -9
- package/dist/layouts/Layout.js.map +0 -1
- package/dist/layouts/NotFoundLayout.d.ts +0 -2
- package/dist/layouts/NotFoundLayout.d.ts.map +0 -1
- package/dist/layouts/NotFoundLayout.js +0 -6
- package/dist/layouts/NotFoundLayout.js.map +0 -1
- package/dist/pages/Code.d.ts +0 -7
- package/dist/pages/Code.d.ts.map +0 -1
- package/dist/pages/Code.js +0 -8
- package/dist/pages/Code.js.map +0 -1
- package/dist/pages/Home.d.ts +0 -7
- package/dist/pages/Home.d.ts.map +0 -1
- package/dist/pages/Home.js +0 -8
- package/dist/pages/Home.js.map +0 -1
- package/dist/pages/Welcome.d.ts +0 -2
- package/dist/pages/Welcome.d.ts.map +0 -1
- package/dist/pages/Welcome.js +0 -6
- package/dist/pages/Welcome.js.map +0 -1
- package/dist/server.d.ts +0 -11
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -434
- package/dist/server.js.map +0 -1
- package/dist/services/dev-server.d.ts +0 -29
- package/dist/services/dev-server.d.ts.map +0 -1
- package/dist/services/dev-server.js +0 -201
- package/dist/services/dev-server.js.map +0 -1
- package/dist/services/terminal.d.ts +0 -46
- package/dist/services/terminal.d.ts.map +0 -1
- package/dist/services/terminal.js +0 -264
- package/dist/services/terminal.js.map +0 -1
- package/dist/services/websocket.d.ts +0 -48
- package/dist/services/websocket.d.ts.map +0 -1
- package/dist/services/websocket.js +0 -332
- package/dist/services/websocket.js.map +0 -1
- package/dist/static/components/ChatInput.js +0 -237
- package/dist/static/components/Sidebar.js +0 -225
- package/dist/static/components/SimpleLivePreview.js +0 -305
- package/dist/static/components/Terminal.js +0 -461
- package/dist/static/components/TerminalTabs.js +0 -383
- package/dist/static/favicon.svg +0 -14
- package/dist/static/signals/LivePreviewSignal.js +0 -71
- package/dist/static/signals/SidebarSignal.js +0 -123
- package/dist/static/signals/TerminalSignal.js +0 -273
- package/dist/static/styles/main.css +0 -1761
- package/src/cli.ts +0 -155
- package/src/components/BaseHead.ts +0 -164
- package/src/components/ChatInput.tsx +0 -56
- package/src/components/Sidebar.tsx +0 -99
- package/src/components/SimpleLivePreview.tsx +0 -40
- package/src/components/Terminal.tsx +0 -40
- package/src/components/VoiceRecorder.tsx +0 -33
- package/src/components/icons/GeminiLogo.tsx +0 -10
- package/src/components/icons/OllamaLogo.tsx +0 -5
- package/src/index.tsx +0 -12
- package/src/layouts/Layout.tsx +0 -41
- package/src/layouts/NotFoundLayout.tsx +0 -15
- package/src/pages/Code.tsx +0 -34
- package/src/pages/Welcome.tsx +0 -56
- package/src/server.tsx +0 -519
- package/src/services/dev-server.ts +0 -234
- package/src/services/terminal.ts +0 -325
- package/src/services/websocket.ts +0 -405
- package/src/static/components/ChatInput.js +0 -237
- package/src/static/components/Sidebar.js +0 -225
- package/src/static/components/SimpleLivePreview.js +0 -305
- package/src/static/components/Terminal.js +0 -461
- package/src/static/components/TerminalTabs.js +0 -383
- package/src/static/favicon.svg +0 -14
- package/src/static/signals/LivePreviewSignal.js +0 -71
- package/src/static/signals/SidebarSignal.js +0 -123
- package/src/static/signals/TerminalSignal.js +0 -273
- package/src/static/styles/main.css +0 -1761
- package/src/styles/input.css +0 -3
- package/tailwind.config.ts +0 -22
- package/tsconfig.json +0 -37
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/services/websocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,SAAS,EAAE,MAAM,IAAI,CAAC;AAKhD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,SAAS,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,wBAAwB;IACnC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAgC;IAClD,OAAO,CAAC,MAAM,CAAC,OAAO,CAAsC;IAC5D,OAAO,CAAC,MAAM,CAAC,cAAc,CAAkC;IAE/D,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM;IA8ChC,OAAO,CAAC,MAAM,CAAC,aAAa;IAsB5B,OAAO,CAAC,MAAM,CAAC,aAAa;IAqC5B,OAAO,CAAC,MAAM,CAAC,UAAU;IAuCzB,OAAO,CAAC,MAAM,CAAC,WAAW;IAe1B,OAAO,CAAC,MAAM,CAAC,WAAW;IA8B1B,OAAO,CAAC,MAAM,CAAC,YAAY;IA0B3B,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAY/B,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAOjC,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAYtC,OAAO,CAAC,MAAM,CAAC,0BAA0B;IAiBzC,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAQ3C,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAcjC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAenC,OAAO,CAAC,MAAM,CAAC,YAAY;IAe3B,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAKrD,MAAM,CAAC,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAaxE,MAAM,CAAC,iBAAiB,IAAI,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAO7E,MAAM,CAAC,mBAAmB,IAAI,MAAM;IAIpC,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM;IAoBrC,MAAM,CAAC,OAAO;CAUf"}
|
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
import { WebSocketServer, WebSocket } from 'ws';
|
|
2
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
-
import { TerminalService } from './terminal.js';
|
|
4
|
-
export class WebSocketTerminalService {
|
|
5
|
-
static wss = null;
|
|
6
|
-
static clients = new Map();
|
|
7
|
-
static sessionClients = new Map(); // sessionId -> Set<clientId>
|
|
8
|
-
static initialize(server) {
|
|
9
|
-
this.wss = new WebSocketServer({
|
|
10
|
-
server,
|
|
11
|
-
path: '/terminal/ws'
|
|
12
|
-
});
|
|
13
|
-
this.wss.on('connection', (ws, request) => {
|
|
14
|
-
const clientId = uuidv4();
|
|
15
|
-
const client = {
|
|
16
|
-
id: clientId,
|
|
17
|
-
ws,
|
|
18
|
-
lastPing: new Date()
|
|
19
|
-
};
|
|
20
|
-
this.clients.set(clientId, client);
|
|
21
|
-
console.log(`WebSocket client connected: ${clientId}`);
|
|
22
|
-
// Set up message handler
|
|
23
|
-
ws.on('message', (data) => {
|
|
24
|
-
this.handleMessage(clientId, data);
|
|
25
|
-
});
|
|
26
|
-
// Set up disconnect handler
|
|
27
|
-
ws.on('close', () => {
|
|
28
|
-
this.handleDisconnect(clientId);
|
|
29
|
-
});
|
|
30
|
-
// Set up error handler
|
|
31
|
-
ws.on('error', (error) => {
|
|
32
|
-
console.error(`WebSocket error for client ${clientId}:`, error);
|
|
33
|
-
this.handleDisconnect(clientId);
|
|
34
|
-
});
|
|
35
|
-
// Send initial connection success
|
|
36
|
-
this.sendToClient(clientId, {
|
|
37
|
-
type: 'pong',
|
|
38
|
-
timestamp: Date.now()
|
|
39
|
-
});
|
|
40
|
-
// Set up ping/pong for connection health
|
|
41
|
-
this.setupPingPong(clientId);
|
|
42
|
-
});
|
|
43
|
-
console.log('WebSocket server initialized for terminal connections');
|
|
44
|
-
}
|
|
45
|
-
static setupPingPong(clientId) {
|
|
46
|
-
const client = this.clients.get(clientId);
|
|
47
|
-
if (!client)
|
|
48
|
-
return;
|
|
49
|
-
const pingInterval = setInterval(() => {
|
|
50
|
-
if (client.ws.readyState === WebSocket.OPEN) {
|
|
51
|
-
client.ws.ping();
|
|
52
|
-
client.lastPing = new Date();
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
clearInterval(pingInterval);
|
|
56
|
-
}
|
|
57
|
-
}, 30000); // Ping every 30 seconds
|
|
58
|
-
client.ws.on('pong', () => {
|
|
59
|
-
client.lastPing = new Date();
|
|
60
|
-
});
|
|
61
|
-
client.ws.on('close', () => {
|
|
62
|
-
clearInterval(pingInterval);
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
static handleMessage(clientId, data) {
|
|
66
|
-
try {
|
|
67
|
-
const message = JSON.parse(data.toString());
|
|
68
|
-
const client = this.clients.get(clientId);
|
|
69
|
-
if (!client) {
|
|
70
|
-
console.error(`Client ${clientId} not found`);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
switch (message.type) {
|
|
74
|
-
case 'join':
|
|
75
|
-
this.handleJoin(clientId, message);
|
|
76
|
-
break;
|
|
77
|
-
case 'leave':
|
|
78
|
-
this.handleLeave(clientId, message);
|
|
79
|
-
break;
|
|
80
|
-
case 'input':
|
|
81
|
-
this.handleInput(clientId, message);
|
|
82
|
-
break;
|
|
83
|
-
case 'resize':
|
|
84
|
-
this.handleResize(clientId, message);
|
|
85
|
-
break;
|
|
86
|
-
case 'ping':
|
|
87
|
-
this.sendToClient(clientId, {
|
|
88
|
-
type: 'pong',
|
|
89
|
-
timestamp: Date.now()
|
|
90
|
-
});
|
|
91
|
-
break;
|
|
92
|
-
default:
|
|
93
|
-
console.warn(`Unknown message type: ${message.type}`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
console.error(`Error parsing WebSocket message from ${clientId}:`, error);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
static handleJoin(clientId, message) {
|
|
101
|
-
const client = this.clients.get(clientId);
|
|
102
|
-
if (!client || !message.sessionId)
|
|
103
|
-
return;
|
|
104
|
-
console.log(`Client ${clientId} joining session ${message.sessionId}`);
|
|
105
|
-
// Remove client from any existing session
|
|
106
|
-
if (client.sessionId) {
|
|
107
|
-
this.removeClientFromSession(clientId, client.sessionId);
|
|
108
|
-
}
|
|
109
|
-
// Get or create terminal session
|
|
110
|
-
let session = TerminalService.getSession(message.sessionId);
|
|
111
|
-
if (!session) {
|
|
112
|
-
console.log(`Creating new terminal session: ${message.sessionId}`);
|
|
113
|
-
session = TerminalService.createSession(message.sessionId);
|
|
114
|
-
}
|
|
115
|
-
// Update client info
|
|
116
|
-
client.sessionId = message.sessionId;
|
|
117
|
-
client.terminalId = message.terminalId;
|
|
118
|
-
// Add client to session tracking
|
|
119
|
-
this.addClientToSession(clientId, message.sessionId);
|
|
120
|
-
// Set up output listener for this session (if not already set up)
|
|
121
|
-
this.setupSessionOutputListener(message.sessionId);
|
|
122
|
-
// Send connection confirmation
|
|
123
|
-
this.sendToClient(clientId, {
|
|
124
|
-
type: 'connected',
|
|
125
|
-
sessionId: message.sessionId,
|
|
126
|
-
timestamp: Date.now()
|
|
127
|
-
});
|
|
128
|
-
// Notify all clients in this session about client count
|
|
129
|
-
this.broadcastClientCount(message.sessionId);
|
|
130
|
-
}
|
|
131
|
-
static handleLeave(clientId, message) {
|
|
132
|
-
const client = this.clients.get(clientId);
|
|
133
|
-
if (!client)
|
|
134
|
-
return;
|
|
135
|
-
console.log(`Client ${clientId} leaving session ${client.sessionId}`);
|
|
136
|
-
if (client.sessionId) {
|
|
137
|
-
this.removeClientFromSession(clientId, client.sessionId);
|
|
138
|
-
this.broadcastClientCount(client.sessionId);
|
|
139
|
-
}
|
|
140
|
-
client.sessionId = undefined;
|
|
141
|
-
client.terminalId = undefined;
|
|
142
|
-
}
|
|
143
|
-
static handleInput(clientId, message) {
|
|
144
|
-
const client = this.clients.get(clientId);
|
|
145
|
-
if (!client || !message.sessionId || message.data === undefined)
|
|
146
|
-
return;
|
|
147
|
-
;
|
|
148
|
-
// Get the terminal session
|
|
149
|
-
const session = TerminalService.getSession(message.sessionId);
|
|
150
|
-
if (!session) {
|
|
151
|
-
console.error(`Session ${message.sessionId} not found`);
|
|
152
|
-
this.sendToClient(clientId, {
|
|
153
|
-
type: 'error',
|
|
154
|
-
data: 'Terminal session not found',
|
|
155
|
-
timestamp: Date.now()
|
|
156
|
-
});
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
// Send input directly to PTY (raw input like key presses)
|
|
160
|
-
try {
|
|
161
|
-
session.lastActivity = new Date();
|
|
162
|
-
session.process.write(message.data);
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
console.error(`Failed to send input to session ${message.sessionId}:`, error);
|
|
166
|
-
this.sendToClient(clientId, {
|
|
167
|
-
type: 'error',
|
|
168
|
-
data: 'Failed to send input to terminal',
|
|
169
|
-
timestamp: Date.now()
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
static handleResize(clientId, message) {
|
|
174
|
-
const client = this.clients.get(clientId);
|
|
175
|
-
if (!client || !message.sessionId || message.cols === undefined || message.rows === undefined)
|
|
176
|
-
return;
|
|
177
|
-
// Get the terminal session
|
|
178
|
-
const session = TerminalService.getSession(message.sessionId);
|
|
179
|
-
if (!session) {
|
|
180
|
-
console.error(`Session ${message.sessionId} not found for resize`);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
// Resize the PTY
|
|
184
|
-
try {
|
|
185
|
-
console.log(`Resizing terminal session ${message.sessionId} to ${message.cols}x${message.rows}`);
|
|
186
|
-
session.process.resize(message.cols, message.rows);
|
|
187
|
-
session.lastActivity = new Date();
|
|
188
|
-
// Update session dimensions
|
|
189
|
-
session.cols = message.cols;
|
|
190
|
-
session.rows = message.rows;
|
|
191
|
-
}
|
|
192
|
-
catch (error) {
|
|
193
|
-
console.error(`Failed to resize session ${message.sessionId}:`, error);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
static handleDisconnect(clientId) {
|
|
197
|
-
const client = this.clients.get(clientId);
|
|
198
|
-
console.log(`WebSocket client disconnected: ${clientId}`);
|
|
199
|
-
if (client?.sessionId) {
|
|
200
|
-
this.removeClientFromSession(clientId, client.sessionId);
|
|
201
|
-
this.broadcastClientCount(client.sessionId);
|
|
202
|
-
}
|
|
203
|
-
this.clients.delete(clientId);
|
|
204
|
-
}
|
|
205
|
-
static addClientToSession(clientId, sessionId) {
|
|
206
|
-
if (!this.sessionClients.has(sessionId)) {
|
|
207
|
-
this.sessionClients.set(sessionId, new Set());
|
|
208
|
-
}
|
|
209
|
-
this.sessionClients.get(sessionId).add(clientId);
|
|
210
|
-
}
|
|
211
|
-
static removeClientFromSession(clientId, sessionId) {
|
|
212
|
-
const clientSet = this.sessionClients.get(sessionId);
|
|
213
|
-
if (clientSet) {
|
|
214
|
-
clientSet.delete(clientId);
|
|
215
|
-
if (clientSet.size === 0) {
|
|
216
|
-
this.sessionClients.delete(sessionId);
|
|
217
|
-
// Clean up output listener if no clients are connected
|
|
218
|
-
this.cleanupSessionOutputListener(sessionId);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
static setupSessionOutputListener(sessionId) {
|
|
223
|
-
const session = TerminalService.getSession(sessionId);
|
|
224
|
-
if (!session)
|
|
225
|
-
return;
|
|
226
|
-
// Check if listener already exists
|
|
227
|
-
if (session.eventEmitter.listenerCount('output') > 0) {
|
|
228
|
-
return; // Listener already set up
|
|
229
|
-
}
|
|
230
|
-
const handleOutput = (data) => {
|
|
231
|
-
this.broadcastToSession(sessionId, data);
|
|
232
|
-
};
|
|
233
|
-
session.eventEmitter.on('output', handleOutput);
|
|
234
|
-
console.log(`Set up output listener for session ${sessionId}`);
|
|
235
|
-
}
|
|
236
|
-
static cleanupSessionOutputListener(sessionId) {
|
|
237
|
-
const session = TerminalService.getSession(sessionId);
|
|
238
|
-
if (!session)
|
|
239
|
-
return;
|
|
240
|
-
session.eventEmitter.removeAllListeners('output');
|
|
241
|
-
console.log(`Cleaned up output listener for session ${sessionId}`);
|
|
242
|
-
}
|
|
243
|
-
static broadcastToSession(sessionId, data) {
|
|
244
|
-
const clientIds = this.sessionClients.get(sessionId);
|
|
245
|
-
if (!clientIds)
|
|
246
|
-
return;
|
|
247
|
-
const message = {
|
|
248
|
-
...data,
|
|
249
|
-
timestamp: Date.now()
|
|
250
|
-
};
|
|
251
|
-
for (const clientId of clientIds) {
|
|
252
|
-
this.sendToClient(clientId, message);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
static broadcastClientCount(sessionId) {
|
|
256
|
-
const clientIds = this.sessionClients.get(sessionId);
|
|
257
|
-
const count = clientIds ? clientIds.size : 0;
|
|
258
|
-
if (clientIds) {
|
|
259
|
-
for (const clientId of clientIds) {
|
|
260
|
-
this.sendToClient(clientId, {
|
|
261
|
-
type: 'clients_count',
|
|
262
|
-
count,
|
|
263
|
-
timestamp: Date.now()
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
static sendToClient(clientId, message) {
|
|
269
|
-
const client = this.clients.get(clientId);
|
|
270
|
-
if (!client || client.ws.readyState !== WebSocket.OPEN) {
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
try {
|
|
274
|
-
client.ws.send(JSON.stringify(message));
|
|
275
|
-
}
|
|
276
|
-
catch (error) {
|
|
277
|
-
console.error(`Error sending message to client ${clientId}:`, error);
|
|
278
|
-
this.handleDisconnect(clientId);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
// API methods for external control
|
|
282
|
-
static getSessionClients(sessionId) {
|
|
283
|
-
const clientSet = this.sessionClients.get(sessionId);
|
|
284
|
-
return clientSet ? Array.from(clientSet) : [];
|
|
285
|
-
}
|
|
286
|
-
static sendCommandToSession(sessionId, command) {
|
|
287
|
-
// Send command to terminal
|
|
288
|
-
const success = TerminalService.executeCommand(sessionId, command);
|
|
289
|
-
if (success) {
|
|
290
|
-
// The output will be automatically broadcast to all connected clients
|
|
291
|
-
// via the output listener
|
|
292
|
-
console.log(`Command sent to session ${sessionId}: ${command.substring(0, 50)}...`);
|
|
293
|
-
}
|
|
294
|
-
return success;
|
|
295
|
-
}
|
|
296
|
-
static getActiveSessions() {
|
|
297
|
-
return Array.from(this.sessionClients.entries()).map(([sessionId, clients]) => ({
|
|
298
|
-
sessionId,
|
|
299
|
-
clientCount: clients.size
|
|
300
|
-
}));
|
|
301
|
-
}
|
|
302
|
-
static getConnectedClients() {
|
|
303
|
-
return this.clients.size;
|
|
304
|
-
}
|
|
305
|
-
static closeSession(sessionId) {
|
|
306
|
-
const clientIds = this.sessionClients.get(sessionId);
|
|
307
|
-
if (clientIds) {
|
|
308
|
-
// Notify all clients that the session is closing
|
|
309
|
-
for (const clientId of clientIds) {
|
|
310
|
-
this.sendToClient(clientId, {
|
|
311
|
-
type: 'session_closed',
|
|
312
|
-
sessionId,
|
|
313
|
-
timestamp: Date.now()
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
// Clean up client tracking
|
|
317
|
-
this.sessionClients.delete(sessionId);
|
|
318
|
-
}
|
|
319
|
-
// Clean up the terminal session
|
|
320
|
-
TerminalService.destroySession(sessionId);
|
|
321
|
-
}
|
|
322
|
-
static cleanup() {
|
|
323
|
-
if (this.wss) {
|
|
324
|
-
console.log('Closing WebSocket server...');
|
|
325
|
-
this.wss.close();
|
|
326
|
-
this.wss = null;
|
|
327
|
-
}
|
|
328
|
-
this.clients.clear();
|
|
329
|
-
this.sessionClients.clear();
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
//# sourceMappingURL=websocket.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/services/websocket.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
// ChatInput component JavaScript for chat-style terminal input
|
|
2
|
-
class ChatInputManager {
|
|
3
|
-
constructor(chatInputId) {
|
|
4
|
-
this.chatInputId = chatInputId;
|
|
5
|
-
this.container = document.getElementById(chatInputId);
|
|
6
|
-
this.textarea = document.getElementById(`${chatInputId}-textarea`);
|
|
7
|
-
this.sendBtn = document.getElementById(`${chatInputId}-send-btn`);
|
|
8
|
-
this.executeBtn = document.getElementById(`${chatInputId}-execute-btn`);
|
|
9
|
-
|
|
10
|
-
// Get chat input data from window
|
|
11
|
-
const chatInputData = window[`chatInputData_${chatInputId.replace(/-/g, '_')}`];
|
|
12
|
-
if (!chatInputData) {
|
|
13
|
-
console.error(`No chat input data found for ${chatInputId}`);
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
this.terminalId = chatInputData.terminalId;
|
|
18
|
-
|
|
19
|
-
console.log(`ChatInput ${chatInputId} initialized for terminal:`, this.terminalId);
|
|
20
|
-
|
|
21
|
-
this.init();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
init() {
|
|
25
|
-
if (!this.container || !this.textarea || !this.sendBtn || !this.executeBtn) {
|
|
26
|
-
console.error('ChatInput elements not found!', {
|
|
27
|
-
container: !!this.container,
|
|
28
|
-
textarea: !!this.textarea,
|
|
29
|
-
sendBtn: !!this.sendBtn,
|
|
30
|
-
executeBtn: !!this.executeBtn
|
|
31
|
-
});
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
this.setupEventListeners();
|
|
36
|
-
this.setupAutoResize();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
setupEventListeners() {
|
|
40
|
-
// Handle send to input button click
|
|
41
|
-
this.sendBtn.addEventListener('click', () => {
|
|
42
|
-
this.sendToInput();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Handle execute button click
|
|
46
|
-
this.executeBtn.addEventListener('click', () => {
|
|
47
|
-
this.executeCommand();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// Handle textarea key events
|
|
51
|
-
this.textarea.addEventListener('keydown', (e) => {
|
|
52
|
-
// Enter without shift sends to input field
|
|
53
|
-
if (e.key === 'Enter' && !e.shiftKey) {
|
|
54
|
-
e.preventDefault();
|
|
55
|
-
this.sendToInput();
|
|
56
|
-
}
|
|
57
|
-
// Ctrl+Enter or Cmd+Enter executes
|
|
58
|
-
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
|
|
59
|
-
e.preventDefault();
|
|
60
|
-
this.executeCommand();
|
|
61
|
-
}
|
|
62
|
-
// Allow Shift+Enter for new lines (default behavior)
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// Handle input to auto-resize textarea
|
|
66
|
-
this.textarea.addEventListener('input', () => {
|
|
67
|
-
this.adjustTextareaHeight();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Disable buttons when textarea is empty
|
|
71
|
-
this.textarea.addEventListener('input', () => {
|
|
72
|
-
this.updateButtonState();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// Focus textarea when container is clicked
|
|
76
|
-
this.container.addEventListener('click', (e) => {
|
|
77
|
-
if (e.target === this.container) {
|
|
78
|
-
this.textarea.focus();
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
setupAutoResize() {
|
|
84
|
-
// Initial state
|
|
85
|
-
this.adjustTextareaHeight();
|
|
86
|
-
this.updateButtonState();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
adjustTextareaHeight() {
|
|
90
|
-
if (!this.textarea) return;
|
|
91
|
-
|
|
92
|
-
// Reset height to auto to get the correct scrollHeight
|
|
93
|
-
this.textarea.style.height = 'auto';
|
|
94
|
-
|
|
95
|
-
// Calculate the new height based on content
|
|
96
|
-
const scrollHeight = this.textarea.scrollHeight;
|
|
97
|
-
const maxHeight = 120; // Max height from CSS
|
|
98
|
-
const minHeight = 40; // Min height from CSS
|
|
99
|
-
|
|
100
|
-
const newHeight = Math.min(Math.max(scrollHeight, minHeight), maxHeight);
|
|
101
|
-
this.textarea.style.height = `${newHeight}px`;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
updateButtonState() {
|
|
105
|
-
if (!this.textarea || !this.sendBtn || !this.executeBtn) return;
|
|
106
|
-
|
|
107
|
-
const hasContent = this.textarea.value.trim().length > 0;
|
|
108
|
-
this.sendBtn.disabled = !hasContent;
|
|
109
|
-
this.executeBtn.disabled = false; // Execute button is always enabled
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
sendToInput() {
|
|
113
|
-
if (!this.textarea) return;
|
|
114
|
-
|
|
115
|
-
const input = this.textarea.value.trim();
|
|
116
|
-
if (!input) return;
|
|
117
|
-
|
|
118
|
-
// Get the terminal manager for the associated terminal
|
|
119
|
-
const terminalManager = this.getTerminalManager();
|
|
120
|
-
if (!terminalManager) {
|
|
121
|
-
console.error(`No terminal manager found for terminal: ${this.terminalId}`);
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Send the input to the terminal input field (without executing)
|
|
126
|
-
console.log(`Sending text to terminal input field ${this.terminalId}:`, input);
|
|
127
|
-
console.log('ChatInput sending (programmatic):', JSON.stringify(input), 'char codes:', input.split('').map(c => c.charCodeAt(0)));
|
|
128
|
-
|
|
129
|
-
// Simplest approach: just send the text directly
|
|
130
|
-
// This should work for most cases in Claude Code
|
|
131
|
-
terminalManager.sendInput(input);
|
|
132
|
-
|
|
133
|
-
// Clear the textarea
|
|
134
|
-
this.textarea.value = '';
|
|
135
|
-
this.adjustTextareaHeight();
|
|
136
|
-
this.updateButtonState();
|
|
137
|
-
|
|
138
|
-
// Focus back to textarea for next input
|
|
139
|
-
this.textarea.focus();
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
executeCommand() {
|
|
143
|
-
// Get the terminal manager for the associated terminal
|
|
144
|
-
const terminalManager = this.getTerminalManager();
|
|
145
|
-
if (!terminalManager) {
|
|
146
|
-
console.error(`No terminal manager found for terminal: ${this.terminalId}`);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Execute whatever is currently in the terminal input field
|
|
151
|
-
console.log(`Executing command in terminal ${this.terminalId}`);
|
|
152
|
-
console.log('ChatInput executing (programmatic):', JSON.stringify('\r'), 'char code:', '\r'.charCodeAt(0));
|
|
153
|
-
terminalManager.sendInput('\r');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
getTerminalManager() {
|
|
157
|
-
// Access global terminal managers
|
|
158
|
-
if (window.terminalManagers && window.terminalManagers.has(this.terminalId)) {
|
|
159
|
-
return window.terminalManagers.get(this.terminalId);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Fallback: try to find by checking all managers
|
|
163
|
-
if (window.terminalManagers) {
|
|
164
|
-
for (const [terminalId, manager] of window.terminalManagers.entries()) {
|
|
165
|
-
if (terminalId === this.terminalId) {
|
|
166
|
-
return manager;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// If not found, log available terminals for debugging
|
|
172
|
-
if (window.terminalManagers) {
|
|
173
|
-
console.log('Available terminal managers:', Array.from(window.terminalManagers.keys()));
|
|
174
|
-
console.log('Looking for terminal ID:', this.terminalId);
|
|
175
|
-
} else {
|
|
176
|
-
console.log('No terminal managers found in window object');
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
focus() {
|
|
183
|
-
if (this.textarea) {
|
|
184
|
-
this.textarea.focus();
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
destroy() {
|
|
189
|
-
// Clean up event listeners if needed
|
|
190
|
-
// The component will be removed from DOM, so most cleanup is automatic
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Auto-initialize when script loads
|
|
195
|
-
console.log('ChatInput.js loaded, looking for chat input containers...');
|
|
196
|
-
let chatInputManagers = new Map();
|
|
197
|
-
|
|
198
|
-
function initializeChatInputs() {
|
|
199
|
-
// Look for all sapling-islands with chat input content
|
|
200
|
-
const saplingIslands = document.querySelectorAll('sapling-island');
|
|
201
|
-
|
|
202
|
-
for (const island of saplingIslands) {
|
|
203
|
-
// Look for chat input container
|
|
204
|
-
const chatInputDiv = island.querySelector('div[id*="chat-input"]');
|
|
205
|
-
if (chatInputDiv && chatInputDiv.id) {
|
|
206
|
-
const chatInputId = chatInputDiv.id;
|
|
207
|
-
console.log('Found chat input component with ID:', chatInputId);
|
|
208
|
-
|
|
209
|
-
// Check if we already have a manager for this chat input
|
|
210
|
-
if (!chatInputManagers.has(chatInputId)) {
|
|
211
|
-
const manager = new ChatInputManager(chatInputId);
|
|
212
|
-
chatInputManagers.set(chatInputId, manager);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
console.log(`Initialized ${chatInputManagers.size} chat input(s)`);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Try immediate initialization
|
|
221
|
-
if (document.readyState === 'loading') {
|
|
222
|
-
document.addEventListener('DOMContentLoaded', initializeChatInputs);
|
|
223
|
-
} else {
|
|
224
|
-
initializeChatInputs();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Make available globally
|
|
228
|
-
window.chatInputManagers = chatInputManagers;
|
|
229
|
-
window.ChatInputManager = ChatInputManager;
|
|
230
|
-
window.initializeChatInputs = initializeChatInputs;
|
|
231
|
-
|
|
232
|
-
// Cleanup on page unload
|
|
233
|
-
window.addEventListener('beforeunload', () => {
|
|
234
|
-
for (const manager of chatInputManagers.values()) {
|
|
235
|
-
manager.destroy();
|
|
236
|
-
}
|
|
237
|
-
});
|