dmux 2.2.1 → 3.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.
Files changed (197) hide show
  1. package/dist/DmuxApp.d.ts.map +1 -1
  2. package/dist/DmuxApp.js +412 -179
  3. package/dist/DmuxApp.js.map +1 -1
  4. package/dist/MergePane.d.ts.map +1 -1
  5. package/dist/MergePane.js +4 -6
  6. package/dist/MergePane.js.map +1 -1
  7. package/dist/PaneAnalyzer.d.ts +45 -0
  8. package/dist/PaneAnalyzer.d.ts.map +1 -0
  9. package/dist/PaneAnalyzer.js +278 -0
  10. package/dist/PaneAnalyzer.js.map +1 -0
  11. package/dist/_plugin-vue_export-helper.css +1 -0
  12. package/dist/actions/index.d.ts +19 -0
  13. package/dist/actions/index.d.ts.map +1 -0
  14. package/dist/actions/index.js +54 -0
  15. package/dist/actions/index.js.map +1 -0
  16. package/dist/actions/paneActions.d.ts +45 -0
  17. package/dist/actions/paneActions.d.ts.map +1 -0
  18. package/dist/actions/paneActions.js +932 -0
  19. package/dist/actions/paneActions.js.map +1 -0
  20. package/dist/actions/types.d.ts +101 -0
  21. package/dist/actions/types.d.ts.map +1 -0
  22. package/dist/actions/types.js +129 -0
  23. package/dist/actions/types.js.map +1 -0
  24. package/dist/adapters/apiActionHandler.d.ts +64 -0
  25. package/dist/adapters/apiActionHandler.d.ts.map +1 -0
  26. package/dist/adapters/apiActionHandler.js +170 -0
  27. package/dist/adapters/apiActionHandler.js.map +1 -0
  28. package/dist/adapters/tuiActionHandler.d.ts +57 -0
  29. package/dist/adapters/tuiActionHandler.d.ts.map +1 -0
  30. package/dist/adapters/tuiActionHandler.js +152 -0
  31. package/dist/adapters/tuiActionHandler.js.map +1 -0
  32. package/dist/chunks/_plugin-vue_export-helper-Cvoq67hi.js +28 -0
  33. package/dist/components/ActionChoiceDialog.d.ts +16 -0
  34. package/dist/components/ActionChoiceDialog.d.ts.map +1 -0
  35. package/dist/components/ActionChoiceDialog.js +29 -0
  36. package/dist/components/ActionChoiceDialog.js.map +1 -0
  37. package/dist/components/ActionConfirmDialog.d.ts +16 -0
  38. package/dist/components/ActionConfirmDialog.d.ts.map +1 -0
  39. package/dist/components/ActionConfirmDialog.js +31 -0
  40. package/dist/components/ActionConfirmDialog.js.map +1 -0
  41. package/dist/components/ActionInputDialog.d.ts +16 -0
  42. package/dist/components/ActionInputDialog.d.ts.map +1 -0
  43. package/dist/components/ActionInputDialog.js +49 -0
  44. package/dist/components/ActionInputDialog.js.map +1 -0
  45. package/dist/components/ActionProgressDialog.d.ts +13 -0
  46. package/dist/components/ActionProgressDialog.d.ts.map +1 -0
  47. package/dist/components/ActionProgressDialog.js +20 -0
  48. package/dist/components/ActionProgressDialog.js.map +1 -0
  49. package/dist/components/FooterHelp.d.ts +2 -0
  50. package/dist/components/FooterHelp.d.ts.map +1 -1
  51. package/dist/components/FooterHelp.js +9 -2
  52. package/dist/components/FooterHelp.js.map +1 -1
  53. package/dist/components/KebabMenu.d.ts +10 -0
  54. package/dist/components/KebabMenu.d.ts.map +1 -0
  55. package/dist/components/KebabMenu.js +18 -0
  56. package/dist/components/KebabMenu.js.map +1 -0
  57. package/dist/components/LoadingIndicator.d.ts.map +1 -1
  58. package/dist/components/LoadingIndicator.js +5 -5
  59. package/dist/components/LoadingIndicator.js.map +1 -1
  60. package/dist/components/PaneCard.d.ts +1 -0
  61. package/dist/components/PaneCard.d.ts.map +1 -1
  62. package/dist/components/PaneCard.js +21 -20
  63. package/dist/components/PaneCard.js.map +1 -1
  64. package/dist/components/PanesGrid.d.ts +1 -0
  65. package/dist/components/PanesGrid.d.ts.map +1 -1
  66. package/dist/components/PanesGrid.js +5 -4
  67. package/dist/components/PanesGrid.js.map +1 -1
  68. package/dist/components/QRCode.d.ts +7 -0
  69. package/dist/components/QRCode.d.ts.map +1 -0
  70. package/dist/components/QRCode.js +19 -0
  71. package/dist/components/QRCode.js.map +1 -0
  72. package/dist/components/Spinner.d.ts +10 -0
  73. package/dist/components/Spinner.d.ts.map +1 -0
  74. package/dist/components/Spinner.js +15 -0
  75. package/dist/components/Spinner.js.map +1 -0
  76. package/dist/dashboard.html +14 -0
  77. package/dist/dashboard.js +2 -0
  78. package/dist/hooks/useActionSystem.d.ts +31 -0
  79. package/dist/hooks/useActionSystem.d.ts.map +1 -0
  80. package/dist/hooks/useActionSystem.js +95 -0
  81. package/dist/hooks/useActionSystem.js.map +1 -0
  82. package/dist/hooks/useAgentStatus.d.ts +4 -3
  83. package/dist/hooks/useAgentStatus.d.ts.map +1 -1
  84. package/dist/hooks/useAgentStatus.js +45 -194
  85. package/dist/hooks/useAgentStatus.js.map +1 -1
  86. package/dist/hooks/usePaneCreation.d.ts +2 -1
  87. package/dist/hooks/usePaneCreation.d.ts.map +1 -1
  88. package/dist/hooks/usePaneCreation.js +46 -100
  89. package/dist/hooks/usePaneCreation.js.map +1 -1
  90. package/dist/hooks/usePanes.d.ts.map +1 -1
  91. package/dist/hooks/usePanes.js +5 -3
  92. package/dist/hooks/usePanes.js.map +1 -1
  93. package/dist/hooks/useTerminalWidth.d.ts.map +1 -1
  94. package/dist/hooks/useTerminalWidth.js +18 -1
  95. package/dist/hooks/useTerminalWidth.js.map +1 -1
  96. package/dist/hooks/useWorktreeActions.d.ts.map +1 -1
  97. package/dist/hooks/useWorktreeActions.js +4 -0
  98. package/dist/hooks/useWorktreeActions.js.map +1 -1
  99. package/dist/index.js +43 -3
  100. package/dist/index.js.map +1 -1
  101. package/dist/server/actionsApi.d.ts +37 -0
  102. package/dist/server/actionsApi.d.ts.map +1 -0
  103. package/dist/server/actionsApi.js +256 -0
  104. package/dist/server/actionsApi.js.map +1 -0
  105. package/dist/server/embedded-assets.d.ts +13 -0
  106. package/dist/server/embedded-assets.d.ts.map +1 -0
  107. package/dist/server/embedded-assets.js +5012 -0
  108. package/dist/server/embedded-assets.js.map +1 -0
  109. package/dist/server/index.d.ts +21 -0
  110. package/dist/server/index.d.ts.map +1 -0
  111. package/dist/server/index.js +99 -0
  112. package/dist/server/index.js.map +1 -0
  113. package/dist/server/routes.d.ts +3 -0
  114. package/dist/server/routes.d.ts.map +1 -0
  115. package/dist/server/routes.js +672 -0
  116. package/dist/server/routes.js.map +1 -0
  117. package/dist/server/static.d.ts +6 -0
  118. package/dist/server/static.d.ts.map +1 -0
  119. package/dist/server/static.js +3040 -0
  120. package/dist/server/static.js.map +1 -0
  121. package/dist/services/ConfigWatcher.d.ts +20 -0
  122. package/dist/services/ConfigWatcher.d.ts.map +1 -0
  123. package/dist/services/ConfigWatcher.js +75 -0
  124. package/dist/services/ConfigWatcher.js.map +1 -0
  125. package/dist/services/PaneWorkerManager.d.ts +69 -0
  126. package/dist/services/PaneWorkerManager.d.ts.map +1 -0
  127. package/dist/services/PaneWorkerManager.js +272 -0
  128. package/dist/services/PaneWorkerManager.js.map +1 -0
  129. package/dist/services/StatusDetector.d.ts +87 -0
  130. package/dist/services/StatusDetector.d.ts.map +1 -0
  131. package/dist/services/StatusDetector.js +387 -0
  132. package/dist/services/StatusDetector.js.map +1 -0
  133. package/dist/services/TerminalDiffer.d.ts +85 -0
  134. package/dist/services/TerminalDiffer.d.ts.map +1 -0
  135. package/dist/services/TerminalDiffer.js +499 -0
  136. package/dist/services/TerminalDiffer.js.map +1 -0
  137. package/dist/services/TerminalStreamer.d.ts +80 -0
  138. package/dist/services/TerminalStreamer.d.ts.map +1 -0
  139. package/dist/services/TerminalStreamer.js +490 -0
  140. package/dist/services/TerminalStreamer.js.map +1 -0
  141. package/dist/services/TunnelService.d.ts +9 -0
  142. package/dist/services/TunnelService.d.ts.map +1 -0
  143. package/dist/services/TunnelService.js +34 -0
  144. package/dist/services/TunnelService.js.map +1 -0
  145. package/dist/services/WorkerMessageBus.d.ts +48 -0
  146. package/dist/services/WorkerMessageBus.d.ts.map +1 -0
  147. package/dist/services/WorkerMessageBus.js +120 -0
  148. package/dist/services/WorkerMessageBus.js.map +1 -0
  149. package/dist/shared/StateManager.d.ts +34 -0
  150. package/dist/shared/StateManager.d.ts.map +1 -0
  151. package/dist/shared/StateManager.js +108 -0
  152. package/dist/shared/StateManager.js.map +1 -0
  153. package/dist/shared/StreamProtocol.d.ts +75 -0
  154. package/dist/shared/StreamProtocol.d.ts.map +1 -0
  155. package/dist/shared/StreamProtocol.js +37 -0
  156. package/dist/shared/StreamProtocol.js.map +1 -0
  157. package/dist/terminal.html +17 -0
  158. package/dist/terminal.js +3 -0
  159. package/dist/types.d.ts +21 -1
  160. package/dist/types.d.ts.map +1 -1
  161. package/dist/utils/agentDetection.d.ts +18 -0
  162. package/dist/utils/agentDetection.d.ts.map +1 -0
  163. package/dist/utils/agentDetection.js +73 -0
  164. package/dist/utils/agentDetection.js.map +1 -0
  165. package/dist/utils/aiMerge.d.ts +35 -0
  166. package/dist/utils/aiMerge.d.ts.map +1 -0
  167. package/dist/utils/aiMerge.js +298 -0
  168. package/dist/utils/aiMerge.js.map +1 -0
  169. package/dist/utils/conflictResolutionPane.d.ts +19 -0
  170. package/dist/utils/conflictResolutionPane.d.ts.map +1 -0
  171. package/dist/utils/conflictResolutionPane.js +214 -0
  172. package/dist/utils/conflictResolutionPane.js.map +1 -0
  173. package/dist/utils/mergeExecution.d.ts +52 -0
  174. package/dist/utils/mergeExecution.d.ts.map +1 -0
  175. package/dist/utils/mergeExecution.js +192 -0
  176. package/dist/utils/mergeExecution.js.map +1 -0
  177. package/dist/utils/mergeValidation.d.ts +67 -0
  178. package/dist/utils/mergeValidation.d.ts.map +1 -0
  179. package/dist/utils/mergeValidation.js +213 -0
  180. package/dist/utils/mergeValidation.js.map +1 -0
  181. package/dist/utils/paneCreation.d.ts +17 -0
  182. package/dist/utils/paneCreation.d.ts.map +1 -0
  183. package/dist/utils/paneCreation.js +274 -0
  184. package/dist/utils/paneCreation.js.map +1 -0
  185. package/dist/utils/port.d.ts +5 -0
  186. package/dist/utils/port.d.ts.map +1 -0
  187. package/dist/utils/port.js +54 -0
  188. package/dist/utils/port.js.map +1 -0
  189. package/dist/workers/PaneWorker.d.ts +2 -0
  190. package/dist/workers/PaneWorker.d.ts.map +1 -0
  191. package/dist/workers/PaneWorker.js +362 -0
  192. package/dist/workers/PaneWorker.js.map +1 -0
  193. package/dist/workers/WorkerMessages.d.ts +36 -0
  194. package/dist/workers/WorkerMessages.d.ts.map +1 -0
  195. package/dist/workers/WorkerMessages.js +9 -0
  196. package/dist/workers/WorkerMessages.js.map +1 -0
  197. package/package.json +19 -5
@@ -0,0 +1,490 @@
1
+ import { EventEmitter } from 'events';
2
+ import { execSync, spawn } from 'child_process';
3
+ import { existsSync, unlinkSync } from 'fs';
4
+ import { StringDecoder } from 'string_decoder';
5
+ import { formatStreamMessage } from '../shared/StreamProtocol.js';
6
+ /**
7
+ * Manages real-time streaming of tmux panes to browser clients
8
+ * Uses Server-Sent Events for efficient one-way data flow
9
+ */
10
+ export class TerminalStreamer extends EventEmitter {
11
+ streams = new Map();
12
+ isShuttingDown = false;
13
+ /**
14
+ * Start streaming a pane to a client
15
+ */
16
+ async startStream(paneId, tmuxPaneId, client) {
17
+ if (this.isShuttingDown)
18
+ return;
19
+ // Get or create stream info for this pane
20
+ let stream = this.streams.get(paneId);
21
+ if (!stream) {
22
+ stream = await this.initializeStream(paneId, tmuxPaneId);
23
+ this.streams.set(paneId, stream);
24
+ }
25
+ // Add client to stream
26
+ stream.clients.add(client);
27
+ // Send initial state to new client
28
+ await this.sendInitialState(stream, client);
29
+ // If first client, start the streaming
30
+ if (stream.clients.size === 1 && !stream.isActive) {
31
+ await this.activateStream(stream);
32
+ }
33
+ }
34
+ /**
35
+ * Stop streaming to a specific client
36
+ */
37
+ stopStream(paneId, client) {
38
+ const stream = this.streams.get(paneId);
39
+ if (!stream)
40
+ return;
41
+ // Remove client
42
+ stream.clients.delete(client);
43
+ // If no more clients, deactivate stream
44
+ if (stream.clients.size === 0) {
45
+ this.deactivateStream(stream);
46
+ this.streams.delete(paneId);
47
+ }
48
+ }
49
+ /**
50
+ * Initialize stream info for a pane
51
+ */
52
+ async initializeStream(paneId, tmuxPaneId) {
53
+ // Get pane dimensions
54
+ const dimensions = this.getPaneDimensions(tmuxPaneId);
55
+ // Capture current state
56
+ const content = this.capturePaneContent(tmuxPaneId);
57
+ // Create pipe path
58
+ const pipePath = `/tmp/dmux-pipe-${paneId}-${Date.now()}`;
59
+ return {
60
+ paneId,
61
+ tmuxPaneId,
62
+ pipePath,
63
+ clients: new Set(),
64
+ width: dimensions.width,
65
+ height: dimensions.height,
66
+ lastContent: content,
67
+ isActive: false
68
+ };
69
+ }
70
+ /**
71
+ * Send initial state to a new client
72
+ */
73
+ async sendInitialState(stream, client) {
74
+ // Get cursor position from tmux
75
+ const cursorPos = this.getCursorPosition(stream.tmuxPaneId);
76
+ // Send raw content with ANSI codes - frontend will parse
77
+ const initMessage = {
78
+ type: 'init',
79
+ width: stream.width,
80
+ height: stream.height,
81
+ content: stream.lastContent,
82
+ cursorRow: cursorPos.row,
83
+ cursorCol: cursorPos.col,
84
+ timestamp: Date.now()
85
+ };
86
+ try {
87
+ // Send as delimited message using protocol formatter
88
+ client.push(formatStreamMessage(initMessage));
89
+ }
90
+ catch (error) {
91
+ // Client disconnected during init
92
+ }
93
+ }
94
+ /**
95
+ * Get cursor position from tmux
96
+ */
97
+ getCursorPosition(tmuxPaneId) {
98
+ try {
99
+ const output = execSync(`tmux display-message -p -t ${tmuxPaneId} -F "#{cursor_y},#{cursor_x}"`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
100
+ const [row, col] = output.split(',').map(Number);
101
+ return { row: row || 0, col: col || 0 };
102
+ }
103
+ catch (error) {
104
+ return { row: 0, col: 0 };
105
+ }
106
+ }
107
+ /**
108
+ * Activate streaming for a pane (start piping and monitoring)
109
+ */
110
+ async activateStream(stream) {
111
+ if (stream.isActive)
112
+ return;
113
+ try {
114
+ // Stop any existing pipe-pane first
115
+ try {
116
+ execSync(`tmux pipe-pane -t ${stream.tmuxPaneId}`, { stdio: 'pipe' });
117
+ }
118
+ catch {
119
+ // No existing pipe, which is fine
120
+ }
121
+ // Create empty pipe file (using touch to avoid any output)
122
+ execSync(`> ${stream.pipePath}`, { stdio: 'pipe' });
123
+ // Start tmux pipe-pane
124
+ const pipeCmd = `tmux pipe-pane -t ${stream.tmuxPaneId} -o 'cat >> ${stream.pipePath}'`;
125
+ execSync(pipeCmd, { stdio: 'pipe' });
126
+ // Small delay to ensure pipe-pane is ready
127
+ await new Promise(resolve => setTimeout(resolve, 50));
128
+ // Start tailing the pipe file
129
+ stream.tailProcess = spawn('tail', ['-f', stream.pipePath]);
130
+ // Buffer for accumulating output
131
+ let outputBuffer = '';
132
+ let bufferTimeout = null;
133
+ // String decoder to handle multi-byte UTF-8 sequences across chunks
134
+ const decoder = new StringDecoder('utf8');
135
+ /**
136
+ * Check if string ends with incomplete ANSI escape sequence
137
+ * Returns the index where the incomplete sequence starts, or -1 if complete
138
+ */
139
+ const findIncompleteEscape = (str) => {
140
+ // Check last few characters for start of escape sequences
141
+ for (let i = Math.max(0, str.length - 10); i < str.length; i++) {
142
+ if (str.charCodeAt(i) === 27) { // ESC
143
+ const remaining = str.substring(i);
144
+ // ESC without following character
145
+ if (remaining.length === 1)
146
+ return i;
147
+ // ESC[ (CSI) without terminator
148
+ if (remaining[1] === '[') {
149
+ let hasTerminator = false;
150
+ let j = 2;
151
+ for (; j < remaining.length; j++) {
152
+ const c = remaining.charCodeAt(j);
153
+ // Valid CSI parameter/intermediate bytes: 0-9, ;, space through /
154
+ if ((c >= 48 && c <= 57) || c === 59 || (c >= 32 && c <= 47)) {
155
+ continue; // Valid parameter character, keep looking
156
+ }
157
+ // Final byte (terminator): @ through ~
158
+ if (c >= 64 && c <= 126) {
159
+ hasTerminator = true;
160
+ break;
161
+ }
162
+ // Invalid character, sequence is broken - don't buffer it
163
+ break;
164
+ }
165
+ if (!hasTerminator && j === remaining.length) {
166
+ // Reached end without finding terminator, and all chars were valid
167
+ return i;
168
+ }
169
+ }
170
+ // ESC] (OSC) without terminator (BEL or ESC\)
171
+ if (remaining[1] === ']') {
172
+ let hasTerminator = false;
173
+ for (let j = 2; j < remaining.length; j++) {
174
+ if (remaining.charCodeAt(j) === 7) { // BEL
175
+ hasTerminator = true;
176
+ break;
177
+ }
178
+ if (remaining.charCodeAt(j) === 27 && remaining[j + 1] === '\\') { // ESC\
179
+ hasTerminator = true;
180
+ break;
181
+ }
182
+ }
183
+ if (!hasTerminator)
184
+ return i;
185
+ }
186
+ }
187
+ }
188
+ return -1;
189
+ };
190
+ // Handle tail output
191
+ stream.tailProcess.stdout?.on('data', (data) => {
192
+ if (this.isShuttingDown)
193
+ return;
194
+ // Use StringDecoder to properly handle multi-byte UTF-8 sequences
195
+ const chunk = decoder.write(data);
196
+ outputBuffer += chunk;
197
+ // Clear existing timeout
198
+ if (bufferTimeout) {
199
+ clearTimeout(bufferTimeout);
200
+ }
201
+ // Buffer for 16ms (60fps)
202
+ bufferTimeout = setTimeout(() => {
203
+ if (outputBuffer) {
204
+ // Check for incomplete escape sequences
205
+ const incompleteIndex = findIncompleteEscape(outputBuffer);
206
+ if (incompleteIndex >= 0) {
207
+ // Send complete portion, keep incomplete sequence in buffer
208
+ const completeOutput = outputBuffer.substring(0, incompleteIndex);
209
+ outputBuffer = outputBuffer.substring(incompleteIndex);
210
+ if (completeOutput) {
211
+ this.processAndSendUpdates(stream, completeOutput);
212
+ }
213
+ }
214
+ else {
215
+ // Everything is complete, send it all
216
+ this.processAndSendUpdates(stream, outputBuffer);
217
+ outputBuffer = '';
218
+ }
219
+ }
220
+ }, 16);
221
+ });
222
+ // Handle tail process end - flush any remaining bytes
223
+ stream.tailProcess.stdout?.on('end', () => {
224
+ const remaining = decoder.end();
225
+ if (remaining) {
226
+ outputBuffer += remaining;
227
+ if (outputBuffer) {
228
+ this.processAndSendUpdates(stream, outputBuffer);
229
+ outputBuffer = '';
230
+ }
231
+ }
232
+ });
233
+ // Handle tail process errors
234
+ stream.tailProcess.on('error', (error) => {
235
+ // Silently handle tail errors - they're usually benign
236
+ });
237
+ // Start resize monitoring
238
+ stream.resizeCheckInterval = setInterval(() => {
239
+ this.checkForResize(stream);
240
+ }, 500);
241
+ // Periodic full refresh to fix drift from patch-based streaming
242
+ // Patches work well for simple terminal output, but complex TUI apps (Ink, etc.)
243
+ // use cursor positioning that doesn't replay correctly. Full refresh keeps in sync.
244
+ stream.refreshInterval = setInterval(() => {
245
+ const content = this.capturePaneContent(stream.tmuxPaneId);
246
+ // Skip refresh if content is empty (pane might be closed or capture failed)
247
+ if (!content || content.trim().length === 0) {
248
+ return;
249
+ }
250
+ const cursorPos = this.getCursorPosition(stream.tmuxPaneId);
251
+ // Send full refresh as INIT message to reset buffer
252
+ const refreshMessage = {
253
+ type: 'init',
254
+ width: stream.width,
255
+ height: stream.height,
256
+ content: content,
257
+ cursorRow: cursorPos.row,
258
+ cursorCol: cursorPos.col,
259
+ timestamp: Date.now()
260
+ };
261
+ stream.clients.forEach(client => {
262
+ try {
263
+ client.push(formatStreamMessage(refreshMessage));
264
+ }
265
+ catch (error) {
266
+ stream.clients.delete(client);
267
+ }
268
+ });
269
+ stream.lastContent = content;
270
+ }, 2000); // Full refresh every 2 seconds to fix patch drift
271
+ stream.isActive = true;
272
+ }
273
+ catch (error) {
274
+ // Stream activation failed silently
275
+ }
276
+ }
277
+ /**
278
+ * Deactivate streaming for a pane
279
+ */
280
+ deactivateStream(stream) {
281
+ // Stop resize monitoring
282
+ if (stream.resizeCheckInterval) {
283
+ clearInterval(stream.resizeCheckInterval);
284
+ stream.resizeCheckInterval = undefined;
285
+ }
286
+ // Stop refresh interval
287
+ if (stream.refreshInterval) {
288
+ clearInterval(stream.refreshInterval);
289
+ stream.refreshInterval = undefined;
290
+ }
291
+ // Stop tail process
292
+ if (stream.tailProcess) {
293
+ stream.tailProcess.kill();
294
+ stream.tailProcess = undefined;
295
+ }
296
+ // Stop tmux pipe
297
+ try {
298
+ execSync(`tmux pipe-pane -t ${stream.tmuxPaneId}`, { stdio: 'pipe' });
299
+ }
300
+ catch (error) {
301
+ // Ignore pipe-pane stop errors
302
+ }
303
+ // Clean up pipe file
304
+ if (existsSync(stream.pipePath)) {
305
+ try {
306
+ unlinkSync(stream.pipePath);
307
+ }
308
+ catch (error) {
309
+ // Ignore cleanup errors
310
+ }
311
+ }
312
+ stream.isActive = false;
313
+ }
314
+ /**
315
+ * Process output and send updates to clients
316
+ */
317
+ processAndSendUpdates(stream, output) {
318
+ // Get current cursor position for accurate rendering
319
+ const cursorPos = this.getCursorPosition(stream.tmuxPaneId);
320
+ // DEBUG: Log patch details (disabled)
321
+ // const first100 = output.substring(0, 100).replace(/\x1b/g, '\\x1b').replace(/\r/g, '\\r').replace(/\n/g, '\\n');
322
+ // const last100 = output.substring(Math.max(0, output.length - 100)).replace(/\x1b/g, '\\x1b').replace(/\r/g, '\\r').replace(/\n/g, '\\n');
323
+ // console.error(`[PATCH OUT] pane=${stream.paneId} cursor=(${cursorPos.row},${cursorPos.col}) len=${output.length}`);
324
+ // console.error(`[PATCH OUT] first100: ${first100}`);
325
+ // console.error(`[PATCH OUT] last100: ${last100}`);
326
+ // Send raw output with ANSI codes - frontend will parse
327
+ // Keep \r\n sequences - frontend handles them properly
328
+ const patchMessage = {
329
+ type: 'patch',
330
+ changes: [{
331
+ row: 0,
332
+ col: 0,
333
+ text: output
334
+ }],
335
+ cursorRow: cursorPos.row,
336
+ cursorCol: cursorPos.col,
337
+ timestamp: Date.now()
338
+ };
339
+ // Send to all connected clients
340
+ stream.clients.forEach(client => {
341
+ try {
342
+ // Send as delimited message using protocol formatter
343
+ client.push(formatStreamMessage(patchMessage));
344
+ }
345
+ catch (error) {
346
+ // Client disconnected, remove from list
347
+ stream.clients.delete(client);
348
+ }
349
+ });
350
+ // Keep raw content for new clients
351
+ stream.lastContent += output;
352
+ }
353
+ /**
354
+ * Check if pane has been resized
355
+ */
356
+ checkForResize(stream) {
357
+ const dimensions = this.getPaneDimensions(stream.tmuxPaneId);
358
+ if (dimensions.width !== stream.width || dimensions.height !== stream.height) {
359
+ // Pane was resized
360
+ stream.width = dimensions.width;
361
+ stream.height = dimensions.height;
362
+ // Capture new full state
363
+ const content = this.capturePaneContent(stream.tmuxPaneId);
364
+ stream.lastContent = content;
365
+ // Send resize message with raw content - frontend will parse
366
+ const resizeMessage = {
367
+ type: 'resize',
368
+ width: dimensions.width,
369
+ height: dimensions.height,
370
+ content: content,
371
+ timestamp: Date.now()
372
+ };
373
+ stream.clients.forEach(client => {
374
+ try {
375
+ // Send as delimited message using protocol formatter
376
+ client.push(formatStreamMessage(resizeMessage));
377
+ }
378
+ catch (error) {
379
+ // Client disconnected, remove from list
380
+ stream.clients.delete(client);
381
+ }
382
+ });
383
+ // Restart piping after resize
384
+ this.restartPiping(stream);
385
+ }
386
+ }
387
+ /**
388
+ * Restart piping after a resize
389
+ */
390
+ restartPiping(stream) {
391
+ // Stop current pipe
392
+ try {
393
+ execSync(`tmux pipe-pane -t ${stream.tmuxPaneId}`, { stdio: 'pipe' });
394
+ }
395
+ catch { }
396
+ // Kill tail process
397
+ if (stream.tailProcess) {
398
+ stream.tailProcess.kill();
399
+ }
400
+ // Clean up old pipe file
401
+ if (existsSync(stream.pipePath)) {
402
+ try {
403
+ unlinkSync(stream.pipePath);
404
+ }
405
+ catch { }
406
+ }
407
+ // Create new pipe path
408
+ stream.pipePath = `/tmp/dmux-pipe-${stream.paneId}-${Date.now()}`;
409
+ // Restart piping
410
+ setTimeout(() => {
411
+ if (stream.isActive && !this.isShuttingDown) {
412
+ this.activateStream(stream);
413
+ }
414
+ }, 100);
415
+ }
416
+ /**
417
+ * Get pane dimensions from tmux
418
+ */
419
+ getPaneDimensions(tmuxPaneId) {
420
+ try {
421
+ const output = execSync(`tmux display-message -p -t ${tmuxPaneId} -F "#{pane_width}x#{pane_height}"`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
422
+ const [width, height] = output.split('x').map(Number);
423
+ return { width: width || 80, height: height || 24 };
424
+ }
425
+ catch (error) {
426
+ // Return defaults on error
427
+ return { width: 80, height: 24 }; // Default dimensions
428
+ }
429
+ }
430
+ /**
431
+ * Capture current pane content with ANSI codes
432
+ * Only captures the visible area (no scrollback) so cursor position matches
433
+ */
434
+ capturePaneContent(tmuxPaneId) {
435
+ try {
436
+ // -p: print to stdout
437
+ // -e: include escape sequences
438
+ // -J: join wrapped lines
439
+ // Captures only visible pane (no -S means current screen)
440
+ return execSync(`tmux capture-pane -epJ -t ${tmuxPaneId}`, { encoding: 'utf-8', stdio: 'pipe' });
441
+ }
442
+ catch (error) {
443
+ // Return empty on error
444
+ return '';
445
+ }
446
+ }
447
+ /**
448
+ * Get statistics about active streams
449
+ */
450
+ getStats() {
451
+ const streams = Array.from(this.streams.entries()).map(([paneId, stream]) => ({
452
+ paneId,
453
+ clients: stream.clients.size,
454
+ dimensions: `${stream.width}x${stream.height}`
455
+ }));
456
+ const totalClients = streams.reduce((sum, s) => sum + s.clients, 0);
457
+ return {
458
+ activeStreams: this.streams.size,
459
+ totalClients,
460
+ streams
461
+ };
462
+ }
463
+ /**
464
+ * Shutdown all streams
465
+ */
466
+ async shutdown() {
467
+ this.isShuttingDown = true;
468
+ // Deactivate all streams
469
+ for (const stream of this.streams.values()) {
470
+ this.deactivateStream(stream);
471
+ }
472
+ this.streams.clear();
473
+ this.removeAllListeners();
474
+ }
475
+ }
476
+ // Export singleton instance
477
+ let instance = null;
478
+ export function getTerminalStreamer() {
479
+ if (!instance) {
480
+ instance = new TerminalStreamer();
481
+ }
482
+ return instance;
483
+ }
484
+ export function resetTerminalStreamer() {
485
+ if (instance) {
486
+ instance.shutdown();
487
+ instance = null;
488
+ }
489
+ }
490
+ //# sourceMappingURL=TerminalStreamer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TerminalStreamer.js","sourceRoot":"","sources":["../../src/services/TerminalStreamer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare class TunnelService {
2
+ private tunnel;
3
+ private tunnelUrl;
4
+ start(port: number): Promise<string>;
5
+ stop(): Promise<void>;
6
+ getUrl(): string | null;
7
+ }
8
+ export declare const tunnelService: TunnelService;
9
+ //# sourceMappingURL=TunnelService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TunnelService.d.ts","sourceRoot":"","sources":["../../src/services/TunnelService.ts"],"names":[],"mappings":"AAEA,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAAuB;IAElC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiBpC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,MAAM,IAAI,MAAM,GAAG,IAAI;CAGxB;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { startTunnel } from 'untun';
2
+ export class TunnelService {
3
+ tunnel = null;
4
+ tunnelUrl = null;
5
+ async start(port) {
6
+ try {
7
+ this.tunnel = await startTunnel({
8
+ port,
9
+ acceptCloudflareNotice: true
10
+ });
11
+ this.tunnelUrl = await this.tunnel.getURL();
12
+ if (!this.tunnelUrl) {
13
+ throw new Error('Tunnel URL is null');
14
+ }
15
+ return this.tunnelUrl;
16
+ }
17
+ catch (error) {
18
+ console.error('Failed to start tunnel:', error);
19
+ throw error;
20
+ }
21
+ }
22
+ async stop() {
23
+ if (this.tunnel) {
24
+ await this.tunnel.close();
25
+ this.tunnel = null;
26
+ this.tunnelUrl = null;
27
+ }
28
+ }
29
+ getUrl() {
30
+ return this.tunnelUrl;
31
+ }
32
+ }
33
+ export const tunnelService = new TunnelService();
34
+ //# sourceMappingURL=TunnelService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TunnelService.js","sourceRoot":"","sources":["../../src/services/TunnelService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,MAAM,OAAO,aAAa;IAChB,MAAM,GAAQ,IAAI,CAAC;IACnB,SAAS,GAAkB,IAAI,CAAC;IAExC,KAAK,CAAC,KAAK,CAAC,IAAY;QACtB,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,MAAM,WAAW,CAAC;gBAC9B,IAAI;gBACJ,sBAAsB,EAAE,IAAI;aAC7B,CAAC,CAAC;YACH,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,IAAI,CAAC,SAAS,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAChD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { EventEmitter } from 'events';
2
+ import type { OutboundMessage } from '../workers/WorkerMessages.js';
3
+ export type MessageHandler = (paneId: string, message: OutboundMessage) => void | Promise<void>;
4
+ export interface MessageSubscription {
5
+ unsubscribe: () => void;
6
+ }
7
+ /**
8
+ * Central message router for worker communication
9
+ * Handles message distribution and subscription management
10
+ */
11
+ export declare class WorkerMessageBus extends EventEmitter {
12
+ private subscribers;
13
+ private responseHandlers;
14
+ private requestTimeouts;
15
+ /**
16
+ * Handle incoming message from a worker
17
+ */
18
+ handleWorkerMessage(paneId: string, message: OutboundMessage): void;
19
+ /**
20
+ * Subscribe to specific message types
21
+ */
22
+ subscribe(messageType: string, handler: MessageHandler): MessageSubscription;
23
+ /**
24
+ * Subscribe to multiple message types at once
25
+ */
26
+ subscribeMultiple(messageTypes: string[], handler: MessageHandler): MessageSubscription;
27
+ /**
28
+ * Wait for a response to a specific request
29
+ */
30
+ waitForResponse(requestId: string, timeoutMs?: number): Promise<OutboundMessage>;
31
+ /**
32
+ * Clear all subscriptions for a specific message type
33
+ */
34
+ clearSubscriptions(messageType?: string): void;
35
+ /**
36
+ * Get statistics about message bus activity
37
+ */
38
+ getStats(): {
39
+ subscriptionCount: number;
40
+ pendingResponses: number;
41
+ messageTypes: string[];
42
+ };
43
+ /**
44
+ * Cleanup resources
45
+ */
46
+ destroy(): void;
47
+ }
48
+ //# sourceMappingURL=WorkerMessageBus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkerMessageBus.d.ts","sourceRoot":"","sources":["../../src/services/WorkerMessageBus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,8BAA8B,CAAC;AAEpF,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhG,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,WAAW,CAA0C;IAC7D,OAAO,CAAC,gBAAgB,CAA0D;IAClF,OAAO,CAAC,eAAe,CAAqC;IAE5D;;OAEG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAiCnE;;OAEG;IACH,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,mBAAmB;IAe5E;;OAEG;IACH,iBAAiB,CACf,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,EAAE,cAAc,GACtB,mBAAmB;IAUtB;;OAEG;IACH,eAAe,CACb,SAAS,EAAE,MAAM,EACjB,SAAS,GAAE,MAAa,GACvB,OAAO,CAAC,eAAe,CAAC;IAkB3B;;OAEG;IACH,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ9C;;OAEG;IACH,QAAQ,IAAI;QACV,iBAAiB,EAAE,MAAM,CAAC;QAC1B,gBAAgB,EAAE,MAAM,CAAC;QACzB,YAAY,EAAE,MAAM,EAAE,CAAC;KACxB;IAWD;;OAEG;IACH,OAAO,IAAI,IAAI;CAYhB"}