tmux-ide 2.9.7 → 2.9.9

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 (34) hide show
  1. package/bin/cli.js +323 -55
  2. package/package.json +2 -2
  3. package/packages/contracts/src/pane-stream.ts +17 -0
  4. package/packages/contracts/src/terminal-graphics.ts +29 -3
  5. package/packages/core/src/kitty-placeholders.ts +29 -11
  6. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +2 -2
  7. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
  8. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
  9. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +2 -2
  10. package/packages/daemon/dist/native/tmux/darwin-arm64/manifest.json +6 -2
  11. package/packages/daemon/dist/native/tmux/darwin-arm64/tmux +0 -0
  12. package/packages/daemon/dist/native/tmux/linux-arm64/manifest.json +6 -2
  13. package/packages/daemon/dist/native/tmux/linux-arm64/tmux +0 -0
  14. package/packages/daemon/dist/native/tmux/linux-x64/manifest.json +6 -2
  15. package/packages/daemon/dist/native/tmux/linux-x64/tmux +0 -0
  16. package/packages/daemon/dist/terminal/attachments/native-runtime.js +25 -12
  17. package/packages/daemon/dist/terminal/graphics/kitty-graphics.js +146 -25
  18. package/packages/daemon/dist/terminal/mirror/mirror-service.js +6 -0
  19. package/packages/daemon/dist/terminal/mirror/session-channel.js +49 -5
  20. package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +109 -7
  21. package/packages/daemon/dist/terminal/session-runtime/registry.js +9 -1
  22. package/packages/daemon/dist/terminal/session-runtime/terminal-replica-interpreter.js +19 -2
  23. package/packages/daemon/dist/terminal/session-runtime/transport-binding.js +4 -0
  24. package/packages/daemon/src/terminal/attachments/native-runtime.ts +28 -13
  25. package/packages/daemon/src/terminal/graphics/__fixtures__/full-frame-client-recorded.ctl +87 -0
  26. package/packages/daemon/src/terminal/graphics/__fixtures__/full-frame-client.ctl +10 -0
  27. package/packages/daemon/src/terminal/graphics/kitty-graphics.ts +143 -28
  28. package/packages/daemon/src/terminal/mirror/mirror-service.ts +11 -0
  29. package/packages/daemon/src/terminal/mirror/session-channel.ts +65 -4
  30. package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +123 -6
  31. package/packages/daemon/src/terminal/session-runtime/registry.ts +18 -1
  32. package/packages/daemon/src/terminal/session-runtime/terminal-replica-interpreter.ts +18 -2
  33. package/packages/daemon/src/terminal/session-runtime/transport-binding.ts +5 -0
  34. package/packages/daemon-client/src/pane-stream-client.ts +8 -0
@@ -422,8 +422,17 @@ export class TerminalReplicaInterpreter {
422
422
  const previous = this.#backend;
423
423
  this.#backend = replacement;
424
424
  this.#attachKitty(replacement);
425
- // tmux never saw cursor-anchored placements; a capture cannot restore them.
426
- this.#kitty.dropCursorPlacements();
425
+ // A capture replay does not erase graphics already observed by this owner.
426
+ // Keep anchors only when both backends agree on their coordinate basis;
427
+ // reflow, history replacement and authoritative stream resets are ambiguous.
428
+ const sameGraphicsBasis =
429
+ operation.bootstrap === "painted-capture" &&
430
+ previous.cols === replacement.cols &&
431
+ previous.rows === replacement.rows &&
432
+ previous.graphicsViewportTop?.() !== undefined &&
433
+ previous.graphicsViewportTop?.() === replacement.graphicsViewportTop?.() &&
434
+ previous.modes().alternateScreen === replacement.modes().alternateScreen;
435
+ if (!sameGraphicsBasis) this.#kitty.dropCursorPlacements();
427
436
  this.#nativeReseedRequested = false;
428
437
  this.#scrollback = scrollback;
429
438
  this.#bootstrap = {
@@ -459,6 +468,8 @@ export class TerminalReplicaInterpreter {
459
468
  return;
460
469
  }
461
470
  if (operation.type === "resize") {
471
+ if (operation.cols !== this.#backend.cols || operation.rows !== this.#backend.rows)
472
+ this.#kitty.dropCursorPlacements();
462
473
  this.#causalCell?.fail("geometry-drift");
463
474
  if (this.#backend.modes().synchronizedOutput) {
464
475
  // Geometry is part of the admitted FIFO even while publication is
@@ -512,6 +523,11 @@ export class TerminalReplicaInterpreter {
512
523
  // Always forward the scanner's output: tmux splits %output (~2 KiB) inside
513
524
  // kitty APCs (~4 KiB chunks), so a chunk with no completed command can still
514
525
  // be all image payload that must never reach the VT parser as text.
526
+ // A chunk entirely inside image payload changes nothing the parser can
527
+ // see. Skipping it matters: every parser write settles on a later timer
528
+ // turn, so a frame split into dozens of %output chunks would otherwise
529
+ // serialize dozens of turns and fall behind a 30 fps image stream.
530
+ if (scanned.forward.byteLength === 0) return;
515
531
  await this.#writeToBackend(this.#backend, scanned.forward);
516
532
  if (this.#observability.enabled)
517
533
  this.#observability.recordSpan(
@@ -458,6 +458,11 @@ export class SessionRuntimeTransportBinding {
458
458
  }
459
459
  }
460
460
 
461
+ setCellPixels(width: number, height: number, precise?: { width: number; height: number }): void {
462
+ this.#assertOpen();
463
+ this.#shared.consumer.setCellPixels?.(width, height, precise);
464
+ }
465
+
461
466
  fitViewport(
462
467
  expectedLease: SessionRuntimeAuthorityLease,
463
468
  cols: number,
@@ -384,6 +384,12 @@ export interface PaneStreamRuntimeClient {
384
384
  ): Promise<WorkspaceMultiplexerMutationResult | null>;
385
385
  /** Pull image bytes announced in graphics state; the daemon sends each once per request. */
386
386
  requestTerminalGraphics(pane: string, digests: readonly string[]): void;
387
+ /** Renderer cell size in device pixels; only after state carried `cellPixels`. */
388
+ setTerminalCellPixels(
389
+ width: number,
390
+ height: number,
391
+ precise?: { width: number; height: number },
392
+ ): void;
387
393
  close(): void;
388
394
  }
389
395
 
@@ -1605,6 +1611,8 @@ export async function connectIssuedPaneStreamRuntimeClient(
1605
1611
  nack: (nack) => send({ type: "terminal-delivery-nack", nack }),
1606
1612
  setVisibility: (address, visibility) =>
1607
1613
  send({ type: "terminal-delivery-visibility", ...address, visibility }),
1614
+ setTerminalCellPixels: (width, height, precise) =>
1615
+ send({ type: "terminal-cell-pixels", width, height, ...(precise ? { precise } : {}) }),
1608
1616
  requestTerminalGraphics: (pane, digests) => {
1609
1617
  for (let start = 0; start < digests.length; start += TERMINAL_GRAPHICS_MAX_REQUEST_DIGESTS)
1610
1618
  send({