@termfleet/terminal 0.1.1 → 0.1.2

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.
@@ -13,6 +13,7 @@ export type TmuxTerminalSocketOptions<TAuthorization = void> = {
13
13
  cwd?: string;
14
14
  errorLabel?: string;
15
15
  onInput?: (data: string, authorization: TAuthorization | undefined) => Promise<void> | void;
16
+ readOnly?: boolean;
16
17
  rows?: number;
17
18
  socket: WebSocket;
18
19
  terminalId: string;
@@ -1,6 +1,6 @@
1
1
  import pty from "@homebridge/node-pty-prebuilt-multiarch";
2
2
  import fs from "node:fs";
3
- import { assertSession, getWindowSize } from "./tmux.js";
3
+ import { assertSession, getStatusLineCount, getWindowSize } from "./tmux.js";
4
4
  export class TmuxTerminalAttachError extends Error {
5
5
  phase;
6
6
  constructor(phase, cause) {
@@ -25,8 +25,13 @@ export function attachTmuxTerminalSocket(options) {
25
25
  catch (error) {
26
26
  throw new TmuxTerminalAttachError("resolve", error);
27
27
  }
28
- const cols = options.cols ?? tmuxSize.width;
29
- const rows = options.rows ?? tmuxSize.height;
28
+ // Observers inherit the durable pane dimensions exactly. Even an ignore-size tmux client can
29
+ // become the size source when it is the only attached client, so accepting the browser viewport
30
+ // here would silently reflow someone else's terminal merely by opening a read-only mirror.
31
+ const cols = options.readOnly ? tmuxSize.width : options.cols ?? tmuxSize.width;
32
+ const rows = options.readOnly
33
+ ? tmuxSize.height + getStatusLineCount(options.terminalId, options.tmuxSocket)
34
+ : options.rows ?? tmuxSize.height;
30
35
  let reconciledPty;
31
36
  try {
32
37
  reconciledPty = spawnReconciledPty("tmux", [
@@ -34,6 +39,7 @@ export function attachTmuxTerminalSocket(options) {
34
39
  "-T",
35
40
  "RGB",
36
41
  "attach-session",
42
+ ...(options.readOnly ? ["-r"] : []),
37
43
  "-t",
38
44
  options.terminalId
39
45
  ], {
package/dist/tmux.d.ts CHANGED
@@ -97,6 +97,7 @@ export declare function getWindowSize({ name, socket, window }: {
97
97
  window?: number;
98
98
  socket?: string;
99
99
  }): TmuxWindowSize;
100
+ export declare function getStatusLineCount(name: string, socket?: string): number;
100
101
  export declare function listWindowSizesAsync(socket?: string): Promise<Map<string, TmuxWindowSize>>;
101
102
  export declare function setPaneStyle(target: string, style: string, socket?: string): Promise<void>;
102
103
  export declare function clearPaneStyle(target: string, socket?: string): Promise<void>;
package/dist/tmux.js CHANGED
@@ -514,6 +514,19 @@ export function getWindowSize({ name, socket, window = 0 }) {
514
514
  }
515
515
  return { height, width };
516
516
  }
517
+ export function getStatusLineCount(name, socket) {
518
+ assertSession(name, socket);
519
+ const value = run("tmux", tmuxArgs(socket, ["show-options", "-Aqv", "-t", name, "status"])).trim();
520
+ if (value === "off")
521
+ return 0;
522
+ if (value === "on")
523
+ return 1;
524
+ const lines = Number(value);
525
+ if (!Number.isInteger(lines) || lines < 0 || lines > 5) {
526
+ throw new Error(`Could not determine tmux status height for ${name}.`);
527
+ }
528
+ return lines;
529
+ }
517
530
  // Every window-0 size in ONE async exec, keyed by session. The observe loop uses
518
531
  // this to size windows off the event loop instead of a synchronous getWindowSize
519
532
  // per window — that per-window fan-out blocked the provider loop under a large fleet
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@termfleet/terminal",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Framework-neutral terminal transport and durable tmux session substrate extracted from Termfleet.",
5
5
  "keywords": [
6
6
  "pty",