myrlin-workbook 0.9.11 → 0.9.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myrlin-workbook",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
4
4
  "description": "Browser-based project manager for Claude Code sessions - session discovery, multi-terminal, cost tracking, docs, and kanban board",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -257,6 +257,7 @@ class TerminalPane {
257
257
  this._writeBuf = '';
258
258
  this._activitySample = '';
259
259
  this._writeRaf = null;
260
+ this._pasteHandled = false;
260
261
  }
261
262
 
262
263
  _log(msg) {
@@ -400,10 +401,17 @@ class TerminalPane {
400
401
  const xtermTextarea = container.querySelector('.xterm-helper-textarea');
401
402
  if (xtermTextarea) {
402
403
  xtermTextarea.addEventListener('beforeinput', (e) => {
403
- // Block paste events - we handle Ctrl+V/Cmd+V ourselves via
404
- // pasteFromClipboard() to avoid xterm.js onData firing twice
404
+ // Intercept paste-via-beforeinput to prevent xterm.js onData double-send.
405
+ // Extract the pasted text and send it through our WebSocket instead.
406
+ // Set _pasteHandled flag so the paste event handler doesn't double-send.
405
407
  if (e.inputType === 'insertFromPaste') {
406
408
  e.preventDefault();
409
+ this._pasteHandled = true;
410
+ const text = e.data || (e.dataTransfer && e.dataTransfer.getData('text/plain')) || '';
411
+ if (text && this.ws && this.ws.readyState === WebSocket.OPEN) {
412
+ const bracketedText = '\x1b[200~' + text + '\x1b[201~';
413
+ this.ws.send(JSON.stringify({ type: 'input', data: bracketedText }));
414
+ }
407
415
  return;
408
416
  }
409
417
 
@@ -426,10 +434,22 @@ class TerminalPane {
426
434
  }
427
435
  }, { capture: true });
428
436
 
429
- // Also block native paste event as a fallback
437
+ // Intercept native paste events (right-click > Paste, Edit menu, touch-paste)
438
+ // and route them through our WebSocket instead of letting xterm.js double-send.
439
+ // Ctrl+V/Cmd+V is handled by the custom key handler. beforeinput may have
440
+ // already handled this paste (sets _pasteHandled), so check the flag first.
430
441
  xtermTextarea.addEventListener('paste', (e) => {
431
442
  e.preventDefault();
432
443
  e.stopPropagation();
444
+ if (this._pasteHandled) {
445
+ this._pasteHandled = false;
446
+ return;
447
+ }
448
+ const text = (e.clipboardData || window.clipboardData || '').getData('text');
449
+ if (text && this.ws && this.ws.readyState === WebSocket.OPEN) {
450
+ const bracketedText = '\x1b[200~' + text + '\x1b[201~';
451
+ this.ws.send(JSON.stringify({ type: 'input', data: bracketedText }));
452
+ }
433
453
  }, { capture: true });
434
454
  }
435
455