tmex-cli 0.15.2 → 0.16.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.
Files changed (79) hide show
  1. package/CHANGELOG.md +64 -8
  2. package/dist/runtime/server.js +891 -165
  3. package/package.json +1 -1
  4. package/resources/fe-dist/assets/DevicePage-Ccz8gNji.js +24 -0
  5. package/resources/fe-dist/assets/{DevicesPage-DVAiqqAb.js → DevicesPage-sJHXbS_f.js} +1 -1
  6. package/resources/fe-dist/assets/{FilePage-DzKIB_pN.js → FilePage-7FFd1YcW.js} +1 -1
  7. package/resources/fe-dist/assets/{SettingsPage-BTLab-Z3.js → SettingsPage-FrEtqZyI.js} +1 -1
  8. package/resources/fe-dist/assets/{agent-tab-DRxXq67W.js → agent-tab-9THUj7Cf.js} +4 -4
  9. package/resources/fe-dist/assets/{api-B_pG5Lrn.js → api-DV7-9Pvt.js} +1 -1
  10. package/resources/fe-dist/assets/{arc-Bct5uFHQ.js → arc-PDHKfnGP.js} +1 -1
  11. package/resources/fe-dist/assets/{architectureDiagram-3BPJPVTR-BRDZ_iL7.js → architectureDiagram-3BPJPVTR-BiPHTh1e.js} +1 -1
  12. package/resources/fe-dist/assets/{blockDiagram-GPEHLZMM-COe9KyYv.js → blockDiagram-GPEHLZMM-DP_BRHKg.js} +1 -1
  13. package/resources/fe-dist/assets/{c4Diagram-AAUBKEIU-DtQTgbwo.js → c4Diagram-AAUBKEIU-D16QYgyT.js} +1 -1
  14. package/resources/fe-dist/assets/{card-DAJtOO99.js → card-DmfNw0hd.js} +1 -1
  15. package/resources/fe-dist/assets/channel-Dzz9b4fW.js +1 -0
  16. package/resources/fe-dist/assets/{chunk-2J33WTMH-D4_zLlF4.js → chunk-2J33WTMH-DOjtL7ww.js} +1 -1
  17. package/resources/fe-dist/assets/{chunk-4BX2VUAB-C3M9MnUk.js → chunk-4BX2VUAB-BbT67ZXa.js} +1 -1
  18. package/resources/fe-dist/assets/{chunk-55IACEB6-D5BgUYDW.js → chunk-55IACEB6-CnnXwmY_.js} +1 -1
  19. package/resources/fe-dist/assets/{chunk-727SXJPM-C03K3kUu.js → chunk-727SXJPM-TyUdLEW5.js} +1 -1
  20. package/resources/fe-dist/assets/{chunk-AQP2D5EJ-DLv4_X-p.js → chunk-AQP2D5EJ-BMpK4dqa.js} +1 -1
  21. package/resources/fe-dist/assets/{chunk-FMBD7UC4-CXm-3D35.js → chunk-FMBD7UC4-Dx0HVCZZ.js} +1 -1
  22. package/resources/fe-dist/assets/{chunk-ND2GUHAM-DH_J0yjP.js → chunk-ND2GUHAM-BQCoMEti.js} +1 -1
  23. package/resources/fe-dist/assets/{chunk-QZHKN3VN-D5HtoYCj.js → chunk-QZHKN3VN-ilmf5OgK.js} +1 -1
  24. package/resources/fe-dist/assets/classDiagram-4FO5ZUOK-BB9_4XLL.js +1 -0
  25. package/resources/fe-dist/assets/classDiagram-v2-Q7XG4LA2-BB9_4XLL.js +1 -0
  26. package/resources/fe-dist/assets/{copy-BfLwocwm.js → copy-Ct5TNzGp.js} +1 -1
  27. package/resources/fe-dist/assets/{cose-bilkent-S5V4N54A-be9ShD_r.js → cose-bilkent-S5V4N54A-CpWhM7Za.js} +1 -1
  28. package/resources/fe-dist/assets/{dagre-BM42HDAG-CC-KfeHH.js → dagre-BM42HDAG-CWJttTzC.js} +1 -1
  29. package/resources/fe-dist/assets/{diagram-2AECGRRQ-BwKHXV4n.js → diagram-2AECGRRQ-BD8ny_Yg.js} +1 -1
  30. package/resources/fe-dist/assets/{diagram-5GNKFQAL-Bqwpz1fr.js → diagram-5GNKFQAL-CeHcPWRz.js} +1 -1
  31. package/resources/fe-dist/assets/{diagram-KO2AKTUF-CeMGb0yy.js → diagram-KO2AKTUF-tVlrBE8C.js} +1 -1
  32. package/resources/fe-dist/assets/{diagram-LMA3HP47-Bsi1wTvw.js → diagram-LMA3HP47-DGUn-oQn.js} +1 -1
  33. package/resources/fe-dist/assets/{diagram-OG6HWLK6-B4t3XGFO.js → diagram-OG6HWLK6-xKCd1kwA.js} +1 -1
  34. package/resources/fe-dist/assets/{en_US-Cf2EOKiI.js → en_US-CjVU4anP.js} +1 -1
  35. package/resources/fe-dist/assets/{erDiagram-TEJ5UH35-3Mvka2ky.js → erDiagram-TEJ5UH35-C6M5qkGl.js} +1 -1
  36. package/resources/fe-dist/assets/{files-tab-CozXv_f8.js → files-tab-BWkYfaye.js} +5 -5
  37. package/resources/fe-dist/assets/{flowDiagram-I6XJVG4X-DkGA4Ke1.js → flowDiagram-I6XJVG4X-D0MZDHnB.js} +1 -1
  38. package/resources/fe-dist/assets/{ganttDiagram-6RSMTGT7-3vhFpRP7.js → ganttDiagram-6RSMTGT7-YeduSSa_.js} +1 -1
  39. package/resources/fe-dist/assets/{gitGraphDiagram-PVQCEYII-CQV7XGpo.js → gitGraphDiagram-PVQCEYII-Nem1Mvvg.js} +1 -1
  40. package/resources/fe-dist/assets/index-B3ddLSja.js +314 -0
  41. package/resources/fe-dist/assets/index-CuFTSN9i.css +1 -0
  42. package/resources/fe-dist/assets/{index-CxrkvaQh.js → index-iee3U_rD.js} +1 -1
  43. package/resources/fe-dist/assets/{infoDiagram-5YYISTIA-Do4YMzZB.js → infoDiagram-5YYISTIA-Bh6bbh_V.js} +1 -1
  44. package/resources/fe-dist/assets/{ishikawaDiagram-YF4QCWOH-D0s__l6a.js → ishikawaDiagram-YF4QCWOH-CsZHu48j.js} +1 -1
  45. package/resources/fe-dist/assets/{ja_JP-s3e_OwvM.js → ja_JP-Bq-BwOH_.js} +1 -1
  46. package/resources/fe-dist/assets/{journeyDiagram-JHISSGLW-DZWnugOc.js → journeyDiagram-JHISSGLW-CPgnovXt.js} +1 -1
  47. package/resources/fe-dist/assets/{kanban-definition-UN3LZRKU-BgRtdsFS.js → kanban-definition-UN3LZRKU-D4OAuDsS.js} +1 -1
  48. package/resources/fe-dist/assets/{linear-yx1vNDZX.js → linear-CcA4wV7f.js} +1 -1
  49. package/resources/fe-dist/assets/{markdown-preview-BE4zuZfN.js → markdown-preview-CBGlxpTs.js} +3 -3
  50. package/resources/fe-dist/assets/{mermaid.core-DE3GlZm2.js → mermaid.core-D-CshtYr.js} +5 -5
  51. package/resources/fe-dist/assets/{mindmap-definition-RKZ34NQL-25O7ch2Y.js → mindmap-definition-RKZ34NQL-DBpI1nMC.js} +1 -1
  52. package/resources/fe-dist/assets/{pieDiagram-4H26LBE5-Nsg0nJjf.js → pieDiagram-4H26LBE5-D4kh0_Y0.js} +1 -1
  53. package/resources/fe-dist/assets/{quadrantDiagram-W4KKPZXB-vf_qGk-r.js → quadrantDiagram-W4KKPZXB-DNw3oGHQ.js} +1 -1
  54. package/resources/fe-dist/assets/{requirementDiagram-4Y6WPE33-BFfrHVO7.js → requirementDiagram-4Y6WPE33-DqtMaND0.js} +1 -1
  55. package/resources/fe-dist/assets/{sankeyDiagram-5OEKKPKP-Ce_HayCK.js → sankeyDiagram-5OEKKPKP-D-m9Pyie.js} +1 -1
  56. package/resources/fe-dist/assets/{selection-clipboard-Dq6Zemfd.js → selection-clipboard-D3gUQQ7L.js} +1 -1
  57. package/resources/fe-dist/assets/{send-CKtMOmLP.js → send-DaOB9hLq.js} +1 -1
  58. package/resources/fe-dist/assets/{sequenceDiagram-3UESZ5HK-C2vovJ8X.js → sequenceDiagram-3UESZ5HK-CjrimNJf.js} +1 -1
  59. package/resources/fe-dist/assets/{stateDiagram-AJRCARHV-CLu4laAA.js → stateDiagram-AJRCARHV-BT5d8Z8W.js} +1 -1
  60. package/resources/fe-dist/assets/stateDiagram-v2-BHNVJYJU-kSh9IuUW.js +1 -0
  61. package/resources/fe-dist/assets/terminal-settings-panel-DDhlnbRH.js +25 -0
  62. package/resources/fe-dist/assets/{timeline-definition-PNZ67QCA-DkWMKmAT.js → timeline-definition-PNZ67QCA-BeocAFDX.js} +1 -1
  63. package/resources/fe-dist/assets/{transfer-toast-CHZr1a7O.js → transfer-toast-DXl4RHsV.js} +1 -1
  64. package/resources/fe-dist/assets/{triangle-alert-03d4TB5d.js → triangle-alert-FQRTtbTP.js} +1 -1
  65. package/resources/fe-dist/assets/{vennDiagram-CIIHVFJN-BBlcBoH2.js → vennDiagram-CIIHVFJN-CYlmUB5_.js} +1 -1
  66. package/resources/fe-dist/assets/{wardley-L42UT6IY-BnzmzjjA.js → wardley-L42UT6IY-CTyaodt9.js} +1 -1
  67. package/resources/fe-dist/assets/{wardleyDiagram-YWT4CUSO-B3u1V3qc.js → wardleyDiagram-YWT4CUSO-DNlEcEwQ.js} +1 -1
  68. package/resources/fe-dist/assets/{xychartDiagram-2RQKCTM6-BTm5HZXX.js → xychartDiagram-2RQKCTM6-7Zi-6P-I.js} +1 -1
  69. package/resources/fe-dist/assets/{zap-CBeeCQFr.js → zap-BFIAXPXd.js} +1 -1
  70. package/resources/fe-dist/assets/{zh_CN-6UyMkvZM.js → zh_CN-BuxyXhCT.js} +1 -1
  71. package/resources/fe-dist/index.html +2 -2
  72. package/resources/fe-dist/assets/DevicePage-BvwXdfhK.js +0 -19
  73. package/resources/fe-dist/assets/channel-CIG-CxyN.js +0 -1
  74. package/resources/fe-dist/assets/classDiagram-4FO5ZUOK-CNRZMNkk.js +0 -1
  75. package/resources/fe-dist/assets/classDiagram-v2-Q7XG4LA2-CNRZMNkk.js +0 -1
  76. package/resources/fe-dist/assets/index-CEPc0i5O.js +0 -304
  77. package/resources/fe-dist/assets/index-CHeveVji.css +0 -1
  78. package/resources/fe-dist/assets/stateDiagram-v2-BHNVJYJU-CIfUS4rj.js +0 -1
  79. package/resources/fe-dist/assets/terminal-settings-panel-DAWL48fe.js +0 -25
@@ -23375,7 +23375,14 @@ Time: {{time}}`,
23375
23375
  rename: "Rename window",
23376
23376
  renamePlaceholder: "Enter a name",
23377
23377
  renameDesc: "The custom name overrides the title set by the terminal and is kept until the gateway restarts.",
23378
- renameReset: "Use automatic name"
23378
+ renameReset: "Use automatic name",
23379
+ switchPane: "Switch pane",
23380
+ splitRight: "Split right",
23381
+ splitDown: "Split down",
23382
+ paneCount: "{{count}} panes",
23383
+ pane: "Pane",
23384
+ moveToWindow: "Move into this window",
23385
+ breakToWindow: "Break into new window"
23379
23386
  },
23380
23387
  watch: {
23381
23388
  title: "Watch rules",
@@ -24374,7 +24381,14 @@ Bot\uFF1A{{botName}}
24374
24381
  rename: "\u91CD\u547D\u540D\u7A97\u53E3",
24375
24382
  renamePlaceholder: "\u8F93\u5165\u540D\u79F0",
24376
24383
  renameDesc: "\u81EA\u5B9A\u4E49\u540D\u79F0\u4F1A\u8986\u76D6\u7EC8\u7AEF\u8BBE\u7F6E\u7684\u6807\u9898\uFF0C\u5E76\u4FDD\u7559\u81F3 gateway \u91CD\u542F\u3002",
24377
- renameReset: "\u6062\u590D\u81EA\u52A8\u540D\u79F0"
24384
+ renameReset: "\u6062\u590D\u81EA\u52A8\u540D\u79F0",
24385
+ switchPane: "\u5207\u6362 Pane",
24386
+ splitRight: "\u5411\u53F3\u5206\u5C4F",
24387
+ splitDown: "\u5411\u4E0B\u5206\u5C4F",
24388
+ paneCount: "{{count}} \u4E2A pane",
24389
+ pane: "Pane",
24390
+ moveToWindow: "\u79FB\u5165\u6B64\u7A97\u53E3",
24391
+ breakToWindow: "\u62C6\u4E3A\u72EC\u7ACB\u7A97\u53E3"
24378
24392
  },
24379
24393
  watch: {
24380
24394
  title: "\u76D1\u63A7\u89C4\u5219",
@@ -25373,7 +25387,14 @@ Bot\uFF1A{{botName}}
25373
25387
  rename: "\u30A6\u30A3\u30F3\u30C9\u30A6\u540D\u3092\u5909\u66F4",
25374
25388
  renamePlaceholder: "\u540D\u524D\u3092\u5165\u529B",
25375
25389
  renameDesc: "\u30AB\u30B9\u30BF\u30E0\u540D\u306F\u30BF\u30FC\u30DF\u30CA\u30EB\u304C\u8A2D\u5B9A\u3057\u305F\u30BF\u30A4\u30C8\u30EB\u3092\u4E0A\u66F8\u304D\u3057\u3001\u30B2\u30FC\u30C8\u30A6\u30A7\u30A4\u304C\u518D\u8D77\u52D5\u3059\u308B\u307E\u3067\u4FDD\u6301\u3055\u308C\u307E\u3059\u3002",
25376
- renameReset: "\u81EA\u52D5\u540D\u306B\u623B\u3059"
25390
+ renameReset: "\u81EA\u52D5\u540D\u306B\u623B\u3059",
25391
+ switchPane: "\u30DA\u30A4\u30F3\u5207\u66FF",
25392
+ splitRight: "\u53F3\u306B\u5206\u5272",
25393
+ splitDown: "\u4E0B\u306B\u5206\u5272",
25394
+ paneCount: "{{count}} \u30DA\u30A4\u30F3",
25395
+ pane: "\u30DA\u30A4\u30F3",
25396
+ moveToWindow: "\u3053\u306E\u30A6\u30A3\u30F3\u30C9\u30A6\u3078\u79FB\u52D5",
25397
+ breakToWindow: "\u65B0\u3057\u3044\u30A6\u30A3\u30F3\u30C9\u30A6\u306B\u5206\u96E2"
25377
25398
  },
25378
25399
  watch: {
25379
25400
  title: "\u76E3\u8996\u30EB\u30FC\u30EB",
@@ -25621,16 +25642,25 @@ __export(exports_ws_borsh, {
25621
25642
  MAX_CHUNKS_PER_MESSAGE: () => MAX_CHUNKS_PER_MESSAGE,
25622
25643
  MAGIC: () => MAGIC,
25623
25644
  KIND_WATCH_EVENT: () => KIND_WATCH_EVENT,
25645
+ KIND_TMUX_SUBSCRIBE_PANES: () => KIND_TMUX_SUBSCRIBE_PANES,
25646
+ KIND_TMUX_SPLIT_PANE: () => KIND_TMUX_SPLIT_PANE,
25624
25647
  KIND_TMUX_SET_WINDOW_STYLE: () => KIND_TMUX_SET_WINDOW_STYLE,
25625
25648
  KIND_TMUX_SELECT_WINDOW: () => KIND_TMUX_SELECT_WINDOW,
25626
25649
  KIND_TMUX_SELECT: () => KIND_TMUX_SELECT,
25650
+ KIND_TMUX_RESIZE_PANE: () => KIND_TMUX_RESIZE_PANE,
25627
25651
  KIND_TMUX_REORDER_WINDOWS: () => KIND_TMUX_REORDER_WINDOWS,
25628
25652
  KIND_TMUX_REORDER_PANES: () => KIND_TMUX_REORDER_PANES,
25629
25653
  KIND_TMUX_RENAME_WINDOW: () => KIND_TMUX_RENAME_WINDOW,
25654
+ KIND_TMUX_RENAME_PANE: () => KIND_TMUX_RENAME_PANE,
25655
+ KIND_TMUX_MOVE_PANE: () => KIND_TMUX_MOVE_PANE,
25656
+ KIND_TMUX_FOCUS_PANE: () => KIND_TMUX_FOCUS_PANE,
25657
+ KIND_TMUX_FETCH_PANE_HISTORY: () => KIND_TMUX_FETCH_PANE_HISTORY,
25630
25658
  KIND_TMUX_EVENT: () => KIND_TMUX_EVENT,
25631
25659
  KIND_TMUX_CREATE_WINDOW: () => KIND_TMUX_CREATE_WINDOW,
25632
25660
  KIND_TMUX_CLOSE_WINDOW: () => KIND_TMUX_CLOSE_WINDOW,
25633
25661
  KIND_TMUX_CLOSE_PANE: () => KIND_TMUX_CLOSE_PANE,
25662
+ KIND_TMUX_BREAK_PANE: () => KIND_TMUX_BREAK_PANE,
25663
+ KIND_TMUX_APPLY_STACKED_LAYOUT: () => KIND_TMUX_APPLY_STACKED_LAYOUT,
25634
25664
  KIND_TERM_SYNC_SIZE: () => KIND_TERM_SYNC_SIZE,
25635
25665
  KIND_TERM_RESIZE: () => KIND_TERM_RESIZE,
25636
25666
  KIND_TERM_PASTE: () => KIND_TERM_PASTE,
@@ -25717,6 +25747,15 @@ var KIND_STATE_SNAPSHOT_DIFF = 521;
25717
25747
  var KIND_TMUX_SET_WINDOW_STYLE = 522;
25718
25748
  var KIND_TMUX_REORDER_WINDOWS = 523;
25719
25749
  var KIND_TMUX_REORDER_PANES = 524;
25750
+ var KIND_TMUX_SUBSCRIBE_PANES = 525;
25751
+ var KIND_TMUX_FETCH_PANE_HISTORY = 526;
25752
+ var KIND_TMUX_RESIZE_PANE = 527;
25753
+ var KIND_TMUX_APPLY_STACKED_LAYOUT = 528;
25754
+ var KIND_TMUX_SPLIT_PANE = 529;
25755
+ var KIND_TMUX_FOCUS_PANE = 530;
25756
+ var KIND_TMUX_RENAME_PANE = 531;
25757
+ var KIND_TMUX_MOVE_PANE = 532;
25758
+ var KIND_TMUX_BREAK_PANE = 533;
25720
25759
  var KIND_TERM_INPUT = 769;
25721
25760
  var KIND_TERM_PASTE = 770;
25722
25761
  var KIND_TERM_RESIZE = 771;
@@ -25754,6 +25793,15 @@ var VALID_KINDS = new Set([
25754
25793
  KIND_TMUX_SET_WINDOW_STYLE,
25755
25794
  KIND_TMUX_REORDER_WINDOWS,
25756
25795
  KIND_TMUX_REORDER_PANES,
25796
+ KIND_TMUX_SUBSCRIBE_PANES,
25797
+ KIND_TMUX_FETCH_PANE_HISTORY,
25798
+ KIND_TMUX_RESIZE_PANE,
25799
+ KIND_TMUX_APPLY_STACKED_LAYOUT,
25800
+ KIND_TMUX_SPLIT_PANE,
25801
+ KIND_TMUX_FOCUS_PANE,
25802
+ KIND_TMUX_RENAME_PANE,
25803
+ KIND_TMUX_MOVE_PANE,
25804
+ KIND_TMUX_BREAK_PANE,
25757
25805
  KIND_TERM_INPUT,
25758
25806
  KIND_TERM_PASTE,
25759
25807
  KIND_TERM_RESIZE,
@@ -25796,6 +25844,15 @@ function kindToString(kind) {
25796
25844
  [KIND_TMUX_SET_WINDOW_STYLE]: "TMUX_SET_WINDOW_STYLE",
25797
25845
  [KIND_TMUX_REORDER_WINDOWS]: "TMUX_REORDER_WINDOWS",
25798
25846
  [KIND_TMUX_REORDER_PANES]: "TMUX_REORDER_PANES",
25847
+ [KIND_TMUX_SUBSCRIBE_PANES]: "TMUX_SUBSCRIBE_PANES",
25848
+ [KIND_TMUX_FETCH_PANE_HISTORY]: "TMUX_FETCH_PANE_HISTORY",
25849
+ [KIND_TMUX_RESIZE_PANE]: "TMUX_RESIZE_PANE",
25850
+ [KIND_TMUX_APPLY_STACKED_LAYOUT]: "TMUX_APPLY_STACKED_LAYOUT",
25851
+ [KIND_TMUX_SPLIT_PANE]: "TMUX_SPLIT_PANE",
25852
+ [KIND_TMUX_FOCUS_PANE]: "TMUX_FOCUS_PANE",
25853
+ [KIND_TMUX_RENAME_PANE]: "TMUX_RENAME_PANE",
25854
+ [KIND_TMUX_MOVE_PANE]: "TMUX_MOVE_PANE",
25855
+ [KIND_TMUX_BREAK_PANE]: "TMUX_BREAK_PANE",
25799
25856
  [KIND_TERM_INPUT]: "TERM_INPUT",
25800
25857
  [KIND_TERM_PASTE]: "TERM_PASTE",
25801
25858
  [KIND_TERM_RESIZE]: "TERM_RESIZE",
@@ -25880,16 +25937,25 @@ __export(exports_schema, {
25880
25937
  WindowAddEventSchema: () => WindowAddEventSchema,
25881
25938
  WindowActiveEventSchema: () => WindowActiveEventSchema,
25882
25939
  WatchEventSchema: () => WatchEventSchema,
25940
+ TmuxSubscribePanesSchema: () => TmuxSubscribePanesSchema,
25941
+ TmuxSplitPaneSchema: () => TmuxSplitPaneSchema,
25883
25942
  TmuxSetWindowStyleSchema: () => TmuxSetWindowStyleSchema,
25884
25943
  TmuxSelectWindowSchema: () => TmuxSelectWindowSchema,
25885
25944
  TmuxSelectSchema: () => TmuxSelectSchema,
25945
+ TmuxResizePaneSchema: () => TmuxResizePaneSchema,
25886
25946
  TmuxReorderWindowsSchema: () => TmuxReorderWindowsSchema,
25887
25947
  TmuxReorderPanesSchema: () => TmuxReorderPanesSchema,
25888
25948
  TmuxRenameWindowSchema: () => TmuxRenameWindowSchema,
25949
+ TmuxRenamePaneSchema: () => TmuxRenamePaneSchema,
25950
+ TmuxMovePaneSchema: () => TmuxMovePaneSchema,
25951
+ TmuxFocusPaneSchema: () => TmuxFocusPaneSchema,
25952
+ TmuxFetchPaneHistorySchema: () => TmuxFetchPaneHistorySchema,
25889
25953
  TmuxEventSchema: () => TmuxEventSchema,
25890
25954
  TmuxCreateWindowSchema: () => TmuxCreateWindowSchema,
25891
25955
  TmuxCloseWindowSchema: () => TmuxCloseWindowSchema,
25892
25956
  TmuxClosePaneSchema: () => TmuxClosePaneSchema,
25957
+ TmuxBreakPaneSchema: () => TmuxBreakPaneSchema,
25958
+ TmuxApplyStackedLayoutSchema: () => TmuxApplyStackedLayoutSchema,
25893
25959
  TermSyncSizeSchema: () => TermSyncSizeSchema,
25894
25960
  TermResizeSchema: () => TermResizeSchema,
25895
25961
  TermPasteSchema: () => TermPasteSchema,
@@ -26032,6 +26098,53 @@ var TmuxEventSchema = import_zorsh.b.struct({
26032
26098
  eventType: import_zorsh.b.u8(),
26033
26099
  eventData: import_zorsh.b.bytes()
26034
26100
  });
26101
+ var TmuxSubscribePanesSchema = import_zorsh.b.struct({
26102
+ deviceId: import_zorsh.b.string(),
26103
+ paneIds: import_zorsh.b.vec(import_zorsh.b.string())
26104
+ });
26105
+ var TmuxFetchPaneHistorySchema = import_zorsh.b.struct({
26106
+ deviceId: import_zorsh.b.string(),
26107
+ paneId: import_zorsh.b.string(),
26108
+ requestToken: import_zorsh.b.bytes(16)
26109
+ });
26110
+ var TmuxResizePaneSchema = import_zorsh.b.struct({
26111
+ deviceId: import_zorsh.b.string(),
26112
+ paneId: import_zorsh.b.string(),
26113
+ cols: OptionU16Schema,
26114
+ rows: OptionU16Schema
26115
+ });
26116
+ var TmuxApplyStackedLayoutSchema = import_zorsh.b.struct({
26117
+ deviceId: import_zorsh.b.string(),
26118
+ windowId: import_zorsh.b.string(),
26119
+ cols: import_zorsh.b.u16(),
26120
+ rows: import_zorsh.b.u16()
26121
+ });
26122
+ var TmuxSplitPaneSchema = import_zorsh.b.struct({
26123
+ deviceId: import_zorsh.b.string(),
26124
+ paneId: import_zorsh.b.string(),
26125
+ direction: import_zorsh.b.u8(),
26126
+ cwd: OptionStringSchema
26127
+ });
26128
+ var TmuxFocusPaneSchema = import_zorsh.b.struct({
26129
+ deviceId: import_zorsh.b.string(),
26130
+ windowId: import_zorsh.b.string(),
26131
+ paneId: import_zorsh.b.string()
26132
+ });
26133
+ var TmuxRenamePaneSchema = import_zorsh.b.struct({
26134
+ deviceId: import_zorsh.b.string(),
26135
+ paneId: import_zorsh.b.string(),
26136
+ name: import_zorsh.b.string()
26137
+ });
26138
+ var TmuxMovePaneSchema = import_zorsh.b.struct({
26139
+ deviceId: import_zorsh.b.string(),
26140
+ srcPaneId: import_zorsh.b.string(),
26141
+ dstPaneId: import_zorsh.b.string(),
26142
+ position: import_zorsh.b.u8()
26143
+ });
26144
+ var TmuxBreakPaneSchema = import_zorsh.b.struct({
26145
+ deviceId: import_zorsh.b.string(),
26146
+ paneId: import_zorsh.b.string()
26147
+ });
26035
26148
  var TermInputSchema = import_zorsh.b.struct({
26036
26149
  deviceId: import_zorsh.b.string(),
26037
26150
  paneId: import_zorsh.b.string(),
@@ -26096,10 +26209,14 @@ var PaneWireSchema = import_zorsh.b.struct({
26096
26209
  windowId: import_zorsh.b.string(),
26097
26210
  index: import_zorsh.b.u16(),
26098
26211
  title: OptionStringSchema,
26212
+ customName: OptionStringSchema,
26099
26213
  active: import_zorsh.b.bool(),
26100
26214
  width: import_zorsh.b.u16(),
26101
26215
  height: import_zorsh.b.u16(),
26102
- currentPath: OptionStringSchema
26216
+ currentPath: OptionStringSchema,
26217
+ currentCommand: OptionStringSchema,
26218
+ left: OptionU16Schema,
26219
+ top: OptionU16Schema
26103
26220
  });
26104
26221
  var WindowWireSchema = import_zorsh.b.struct({
26105
26222
  id: import_zorsh.b.string(),
@@ -26107,6 +26224,7 @@ var WindowWireSchema = import_zorsh.b.struct({
26107
26224
  customName: OptionStringSchema,
26108
26225
  index: import_zorsh.b.u16(),
26109
26226
  active: import_zorsh.b.bool(),
26227
+ layout: OptionStringSchema,
26110
26228
  panes: import_zorsh.b.vec(PaneWireSchema)
26111
26229
  });
26112
26230
  var SessionWireSchema = import_zorsh.b.struct({
@@ -26555,6 +26673,7 @@ function encodeWindowWire(window2) {
26555
26673
  customName: window2.customName ?? null,
26556
26674
  index: window2.index,
26557
26675
  active: window2.active,
26676
+ layout: window2.layout ?? null,
26558
26677
  panes: window2.panes.map(encodePaneWire)
26559
26678
  };
26560
26679
  }
@@ -26564,10 +26683,14 @@ function encodePaneWire(pane) {
26564
26683
  windowId: pane.windowId,
26565
26684
  index: pane.index,
26566
26685
  title: pane.title ?? null,
26686
+ customName: pane.customName ?? null,
26567
26687
  active: pane.active,
26568
26688
  width: pane.width,
26569
26689
  height: pane.height,
26570
- currentPath: pane.currentPath ?? null
26690
+ currentPath: pane.currentPath ?? null,
26691
+ currentCommand: pane.currentCommand ?? null,
26692
+ left: pane.left ?? null,
26693
+ top: pane.top ?? null
26571
26694
  };
26572
26695
  }
26573
26696
  function decodeDeviceEventPayload(data) {
@@ -26687,6 +26810,7 @@ function decodeWindowWire(wire) {
26687
26810
  customName: wire.customName ?? undefined,
26688
26811
  index: wire.index,
26689
26812
  active: wire.active,
26813
+ layout: wire.layout ?? undefined,
26690
26814
  panes: wire.panes.map(decodePaneWire)
26691
26815
  };
26692
26816
  }
@@ -26696,10 +26820,14 @@ function decodePaneWire(wire) {
26696
26820
  windowId: wire.windowId,
26697
26821
  index: wire.index,
26698
26822
  title: wire.title ?? undefined,
26823
+ customName: wire.customName ?? undefined,
26699
26824
  active: wire.active,
26700
26825
  width: wire.width,
26701
26826
  height: wire.height,
26702
- currentPath: wire.currentPath ?? undefined
26827
+ currentPath: wire.currentPath ?? undefined,
26828
+ currentCommand: wire.currentCommand ?? undefined,
26829
+ left: wire.left ?? undefined,
26830
+ top: wire.top ?? undefined
26703
26831
  };
26704
26832
  }
26705
26833
  // ../shared/src/index.ts
@@ -98808,6 +98936,78 @@ function formatSnapshotRowForLog(line, limit = 160) {
98808
98936
  }
98809
98937
  return `${line.slice(0, Math.max(0, limit - 3))}...`;
98810
98938
  }
98939
+ var WINDOW_SNAPSHOT_FORMAT = [
98940
+ "#{window_id}",
98941
+ "#{window_index}",
98942
+ "#{window_active}",
98943
+ "#{window_layout}",
98944
+ "#{window_name}"
98945
+ ].join(SNAPSHOT_FIELD_SEPARATOR);
98946
+ var PANE_SNAPSHOT_FORMAT = [
98947
+ "#{pane_id}",
98948
+ "#{window_id}",
98949
+ "#{pane_index}",
98950
+ "#{pane_active}",
98951
+ "#{pane_width}",
98952
+ "#{pane_height}",
98953
+ "#{pane_left}",
98954
+ "#{pane_top}",
98955
+ "#{window_active}",
98956
+ "#{pane_title}",
98957
+ "#{pane_current_command}",
98958
+ "#{pane_current_path}"
98959
+ ].join(SNAPSHOT_FIELD_SEPARATOR);
98960
+ function isSnapshotFlag(value) {
98961
+ return value === "0" || value === "1";
98962
+ }
98963
+ var WINDOW_LAYOUT_PATTERN = /^[0-9a-fA-F]{4},[0-9x,{}[\]]+$/;
98964
+ function parseWindowSnapshotRow(line) {
98965
+ const parts = line.split(SNAPSHOT_FIELD_SEPARATOR);
98966
+ if (parts.length < 5) {
98967
+ return null;
98968
+ }
98969
+ const [id, indexRaw, activeRaw, layoutRaw] = parts;
98970
+ const name24 = parts.slice(4).join(SNAPSHOT_FIELD_SEPARATOR);
98971
+ const index = parseSnapshotInteger(indexRaw);
98972
+ if (!isTmuxWindowId(id) || index === null || !isSnapshotFlag(activeRaw)) {
98973
+ return null;
98974
+ }
98975
+ const layout = typeof layoutRaw === "string" && WINDOW_LAYOUT_PATTERN.test(layoutRaw) ? layoutRaw : undefined;
98976
+ return { id, index, active: activeRaw === "1", layout, name: name24 };
98977
+ }
98978
+ function parsePaneSnapshotRow(line) {
98979
+ const parts = line.split(SNAPSHOT_FIELD_SEPARATOR);
98980
+ if (parts.length < 12) {
98981
+ return null;
98982
+ }
98983
+ const [id, windowId, indexRaw, activeRaw, widthRaw, heightRaw, leftRaw, topRaw, windowActiveRaw] = parts;
98984
+ const rest = parts.slice(9);
98985
+ const title = rest.slice(0, rest.length - 2).join(SNAPSHOT_FIELD_SEPARATOR);
98986
+ const currentCommand = rest.at(-2) ?? "";
98987
+ const currentPath = rest.at(-1) ?? "";
98988
+ const index = parseSnapshotInteger(indexRaw);
98989
+ const width = parseSnapshotInteger(widthRaw);
98990
+ const height = parseSnapshotInteger(heightRaw);
98991
+ const left = parseSnapshotInteger(leftRaw);
98992
+ const top = parseSnapshotInteger(topRaw);
98993
+ if (!isTmuxPaneId(id) || !isTmuxWindowId(windowId) || index === null || width === null || height === null || !isSnapshotFlag(activeRaw) || !isSnapshotFlag(windowActiveRaw)) {
98994
+ return null;
98995
+ }
98996
+ return {
98997
+ id,
98998
+ windowId,
98999
+ index,
99000
+ active: activeRaw === "1",
99001
+ width,
99002
+ height,
99003
+ left: left ?? undefined,
99004
+ top: top ?? undefined,
99005
+ windowActive: windowActiveRaw === "1",
99006
+ title: title.trim() ? title : undefined,
99007
+ currentCommand: currentCommand.trim() ? currentCommand.trim() : undefined,
99008
+ currentPath: currentPath.trim() ? currentPath.trim() : undefined
99009
+ };
99010
+ }
98811
99011
  function splitSnapshotFields(line, fieldCount) {
98812
99012
  const parts = line.split(SNAPSHOT_FIELD_SEPARATOR);
98813
99013
  if (parts.length <= fieldCount) {
@@ -99137,6 +99337,96 @@ class LocalExternalTmuxConnection {
99137
99337
  this.callbacks.onError(error51);
99138
99338
  });
99139
99339
  }
99340
+ splitPane(paneId, direction, cwd) {
99341
+ if (!this.connected) {
99342
+ return;
99343
+ }
99344
+ this.splitPaneInternal(paneId, direction, cwd).catch((error51) => {
99345
+ this.callbacks.onError(error51);
99346
+ });
99347
+ }
99348
+ resizePaneById(paneId, size) {
99349
+ if (!this.connected) {
99350
+ return;
99351
+ }
99352
+ this.resizePaneByIdInternal(paneId, size).catch((error51) => {
99353
+ this.callbacks.onError(error51);
99354
+ });
99355
+ }
99356
+ resizeWindow(windowId, cols, rows) {
99357
+ if (!this.connected) {
99358
+ return;
99359
+ }
99360
+ this.resizeWindowInternal(windowId, cols, rows).catch((error51) => {
99361
+ this.callbacks.onError(error51);
99362
+ });
99363
+ }
99364
+ selectLayout(windowId, preset) {
99365
+ if (!this.connected) {
99366
+ return;
99367
+ }
99368
+ this.runAndRefresh(["select-layout", "-t", windowId, preset], true).catch((error51) => {
99369
+ this.callbacks.onError(error51);
99370
+ });
99371
+ }
99372
+ focusPane(windowId, paneId) {
99373
+ if (!this.connected) {
99374
+ return;
99375
+ }
99376
+ this.focusPaneInternal(windowId, paneId).catch((error51) => {
99377
+ this.callbacks.onError(error51);
99378
+ });
99379
+ }
99380
+ movePane(srcPaneId, dstPaneId, position) {
99381
+ if (!this.connected) {
99382
+ return;
99383
+ }
99384
+ const argv = ["move-pane"];
99385
+ argv.push(position === "left" || position === "right" ? "-h" : "-v");
99386
+ if (position === "left" || position === "top") {
99387
+ argv.push("-b");
99388
+ }
99389
+ argv.push("-s", srcPaneId, "-t", dstPaneId);
99390
+ this.runAndRefresh(argv, true).catch((error51) => {
99391
+ this.callbacks.onError(error51);
99392
+ });
99393
+ }
99394
+ breakPane(paneId) {
99395
+ if (!this.connected) {
99396
+ return;
99397
+ }
99398
+ this.breakPaneInternal(paneId).catch((error51) => {
99399
+ this.callbacks.onError(error51);
99400
+ });
99401
+ }
99402
+ async breakPaneInternal(paneId) {
99403
+ const result = await this.runTmux([
99404
+ "break-pane",
99405
+ "-s",
99406
+ paneId,
99407
+ "-t",
99408
+ `${this.sessionName}:`,
99409
+ "-P",
99410
+ "-F",
99411
+ `#{window_id}${SNAPSHOT_FIELD_SEPARATOR}#{pane_id}`
99412
+ ], true);
99413
+ const [windowId, newPaneId] = result.stdout.trim().split(SNAPSHOT_FIELD_SEPARATOR);
99414
+ if (isTmuxWindowId(windowId) && isTmuxPaneId(newPaneId)) {
99415
+ this.activeWindowId = windowId;
99416
+ this.activePaneId = newPaneId;
99417
+ this.callbacks.onEvent({
99418
+ type: "pane-active",
99419
+ data: { windowId, paneId: newPaneId }
99420
+ });
99421
+ }
99422
+ await this.requestSnapshotInternal();
99423
+ }
99424
+ async requestPaneHistory(paneId) {
99425
+ if (!this.connected) {
99426
+ return;
99427
+ }
99428
+ await this.capturePaneHistory(paneId);
99429
+ }
99140
99430
  renameWindow(windowId, name24) {
99141
99431
  if (!this.connected) {
99142
99432
  return;
@@ -99582,15 +99872,66 @@ class LocalExternalTmuxConnection {
99582
99872
  await this.runAndRefresh(["kill-window", "-t", windowId], true);
99583
99873
  }
99584
99874
  async resizePaneInternal(paneId, cols, rows) {
99585
- const safeCols = Math.max(2, Math.floor(cols));
99586
- const safeRows = Math.max(2, Math.floor(rows));
99587
99875
  const windowId = this.findPaneWindowId(paneId) ?? (await this.runTmux(["display-message", "-p", "-t", paneId, "#{window_id}"], true)).stdout.trim();
99588
99876
  if (!windowId) {
99589
99877
  return;
99590
99878
  }
99879
+ await this.resizeWindowInternal(windowId, cols, rows);
99880
+ }
99881
+ async resizeWindowInternal(windowId, cols, rows) {
99882
+ const safeCols = Math.max(2, Math.floor(cols));
99883
+ const safeRows = Math.max(2, Math.floor(rows));
99591
99884
  await this.runTmux(["resize-window", "-t", windowId, "-x", String(safeCols), "-y", String(safeRows)], true);
99592
99885
  await this.requestSnapshotInternal();
99593
99886
  }
99887
+ async resizePaneByIdInternal(paneId, size) {
99888
+ const argv = ["resize-pane", "-t", paneId];
99889
+ if (size.cols !== undefined) {
99890
+ argv.push("-x", String(Math.max(2, Math.floor(size.cols))));
99891
+ }
99892
+ if (size.rows !== undefined) {
99893
+ argv.push("-y", String(Math.max(2, Math.floor(size.rows))));
99894
+ }
99895
+ if (argv.length === 3) {
99896
+ return;
99897
+ }
99898
+ await this.runTmux(argv, true);
99899
+ await this.requestSnapshotInternal();
99900
+ }
99901
+ async splitPaneInternal(paneId, direction, cwd) {
99902
+ const result = await this.runTmux([
99903
+ "split-window",
99904
+ direction === "h" ? "-h" : "-v",
99905
+ "-t",
99906
+ paneId,
99907
+ "-c",
99908
+ cwd ?? this.resolveDefaultWorkingDir(),
99909
+ "-P",
99910
+ "-F",
99911
+ `#{window_id}${SNAPSHOT_FIELD_SEPARATOR}#{pane_id}`
99912
+ ], true);
99913
+ const [windowId, newPaneId] = result.stdout.trim().split(SNAPSHOT_FIELD_SEPARATOR);
99914
+ if (isTmuxWindowId(windowId) && isTmuxPaneId(newPaneId)) {
99915
+ this.activeWindowId = windowId;
99916
+ this.activePaneId = newPaneId;
99917
+ this.callbacks.onEvent({
99918
+ type: "pane-active",
99919
+ data: { windowId, paneId: newPaneId }
99920
+ });
99921
+ }
99922
+ await this.requestSnapshotInternal();
99923
+ }
99924
+ async focusPaneInternal(windowId, paneId) {
99925
+ this.activeWindowId = windowId;
99926
+ this.activePaneId = paneId;
99927
+ await this.runTmux(["select-window", "-t", windowId], true);
99928
+ await this.runTmux(["select-pane", "-t", paneId], true);
99929
+ this.callbacks.onEvent({
99930
+ type: "pane-active",
99931
+ data: { windowId, paneId }
99932
+ });
99933
+ await this.requestSnapshotInternal();
99934
+ }
99594
99935
  async selectPaneInternal(windowId, paneId, size) {
99595
99936
  this.activeWindowId = windowId;
99596
99937
  this.activePaneId = paneId;
@@ -99633,27 +99974,9 @@ class LocalExternalTmuxConnection {
99633
99974
  "-t",
99634
99975
  this.sessionName,
99635
99976
  "-F",
99636
- ["#{window_id}", "#{window_index}", "#{window_name}", "#{window_active}"].join(SNAPSHOT_FIELD_SEPARATOR)
99977
+ WINDOW_SNAPSHOT_FORMAT
99637
99978
  ]),
99638
- this.runTmuxAllowFailure([
99639
- "list-panes",
99640
- "-s",
99641
- "-t",
99642
- this.sessionName,
99643
- "-F",
99644
- [
99645
- "#{pane_id}",
99646
- "#{window_id}",
99647
- "#{pane_index}",
99648
- "#{pane_title}",
99649
- "#{pane_active}",
99650
- "#{pane_width}",
99651
- "#{pane_height}",
99652
- "#{window_active}",
99653
- "#{pane_current_command}",
99654
- "#{pane_current_path}"
99655
- ].join(SNAPSHOT_FIELD_SEPARATOR)
99656
- ])
99979
+ this.runTmuxAllowFailure(["list-panes", "-s", "-t", this.sessionName, "-F", PANE_SNAPSHOT_FORMAT])
99657
99980
  ]);
99658
99981
  const transientResult = [sessionRes, windowsRes, panesRes].find((res) => res.exitCode === TMUX_SPAWN_UNAVAILABLE_EXIT);
99659
99982
  if (transientResult) {
@@ -99707,21 +100030,20 @@ ${panesRes.stderr}`;
99707
100030
  if (!line.trim()) {
99708
100031
  continue;
99709
100032
  }
99710
- const [id, indexRaw, name24, activeRaw] = splitSnapshotFields(line, 4);
99711
- const index = parseSnapshotInteger(indexRaw);
99712
- if (!isTmuxWindowId(id) || index === null || !this.isSnapshotFlag(activeRaw)) {
100033
+ const row = parseWindowSnapshotRow(line);
100034
+ if (!row) {
99713
100035
  console.warn(`[local] ignoring invalid tmux window snapshot row on ${this.deviceId}: ${formatSnapshotRowForLog(line)}`);
99714
100036
  continue;
99715
100037
  }
99716
- const active = activeRaw === "1";
99717
- if (active) {
99718
- this.activeWindowId = id;
100038
+ if (row.active) {
100039
+ this.activeWindowId = row.id;
99719
100040
  }
99720
- this.snapshotWindows.set(id, {
99721
- id,
99722
- index,
99723
- name: name24 ?? "",
99724
- active,
100041
+ this.snapshotWindows.set(row.id, {
100042
+ id: row.id,
100043
+ index: row.index,
100044
+ name: row.name,
100045
+ active: row.active,
100046
+ layout: row.layout,
99725
100047
  panes: []
99726
100048
  });
99727
100049
  }
@@ -99734,35 +100056,34 @@ ${panesRes.stderr}`;
99734
100056
  if (!line.trim()) {
99735
100057
  continue;
99736
100058
  }
99737
- const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw, currentCommandRaw, currentPathRaw] = splitSnapshotFields(line, 10);
99738
- const index = parseSnapshotInteger(indexRaw);
99739
- const width = parseSnapshotInteger(widthRaw);
99740
- const height = parseSnapshotInteger(heightRaw);
99741
- if (!isTmuxPaneId(paneId) || !isTmuxWindowId(windowId) || index === null || width === null || height === null || !this.isSnapshotFlag(activeRaw) || !this.isSnapshotFlag(windowActiveRaw)) {
100059
+ const row = parsePaneSnapshotRow(line);
100060
+ if (!row) {
99742
100061
  console.warn(`[local] ignoring invalid tmux pane snapshot row on ${this.deviceId}: ${formatSnapshotRowForLog(line)}`);
99743
100062
  continue;
99744
100063
  }
99745
100064
  const pane = {
99746
- id: paneId,
99747
- windowId,
99748
- index,
99749
- title: this.pendingPaneTitles.get(paneId) ?? (titleRaw?.trim() ? titleRaw : undefined),
99750
- currentCommand: currentCommandRaw?.trim() ? currentCommandRaw.trim() : undefined,
99751
- currentPath: currentPathRaw?.trim() ? currentPathRaw.trim() : undefined,
99752
- active: activeRaw === "1",
99753
- width,
99754
- height
100065
+ id: row.id,
100066
+ windowId: row.windowId,
100067
+ index: row.index,
100068
+ title: this.pendingPaneTitles.get(row.id) ?? row.title,
100069
+ currentCommand: row.currentCommand,
100070
+ currentPath: row.currentPath,
100071
+ active: row.active,
100072
+ width: row.width,
100073
+ height: row.height,
100074
+ left: row.left,
100075
+ top: row.top
99755
100076
  };
99756
- if (pane.active && windowActiveRaw === "1") {
99757
- this.activePaneId = paneId;
99758
- this.activeWindowId = windowId;
100077
+ if (pane.active && row.windowActive) {
100078
+ this.activePaneId = row.id;
100079
+ this.activeWindowId = row.windowId;
99759
100080
  }
99760
- const window2 = this.snapshotWindows.get(windowId);
100081
+ const window2 = this.snapshotWindows.get(row.windowId);
99761
100082
  if (!window2) {
99762
100083
  continue;
99763
100084
  }
99764
100085
  window2.panes.push(pane);
99765
- this.pendingPaneTitles.delete(paneId);
100086
+ this.pendingPaneTitles.delete(row.id);
99766
100087
  }
99767
100088
  for (const window2 of this.snapshotWindows.values()) {
99768
100089
  window2.panes.sort((left, right) => left.index - right.index);
@@ -100432,6 +100753,96 @@ class SshExternalTmuxConnection {
100432
100753
  this.callbacks.onError(error51);
100433
100754
  });
100434
100755
  }
100756
+ splitPane(paneId, direction, cwd) {
100757
+ if (!this.connected) {
100758
+ return;
100759
+ }
100760
+ this.splitPaneInternal(paneId, direction, cwd).catch((error51) => {
100761
+ this.callbacks.onError(error51);
100762
+ });
100763
+ }
100764
+ resizePaneById(paneId, size) {
100765
+ if (!this.connected) {
100766
+ return;
100767
+ }
100768
+ this.resizePaneByIdInternal(paneId, size).catch((error51) => {
100769
+ this.callbacks.onError(error51);
100770
+ });
100771
+ }
100772
+ resizeWindow(windowId, cols, rows) {
100773
+ if (!this.connected) {
100774
+ return;
100775
+ }
100776
+ this.resizeWindowInternal(windowId, cols, rows).catch((error51) => {
100777
+ this.callbacks.onError(error51);
100778
+ });
100779
+ }
100780
+ selectLayout(windowId, preset) {
100781
+ if (!this.connected) {
100782
+ return;
100783
+ }
100784
+ this.runAndRefresh(["select-layout", "-t", windowId, preset], true).catch((error51) => {
100785
+ this.callbacks.onError(error51);
100786
+ });
100787
+ }
100788
+ focusPane(windowId, paneId) {
100789
+ if (!this.connected) {
100790
+ return;
100791
+ }
100792
+ this.focusPaneInternal(windowId, paneId).catch((error51) => {
100793
+ this.callbacks.onError(error51);
100794
+ });
100795
+ }
100796
+ movePane(srcPaneId, dstPaneId, position) {
100797
+ if (!this.connected) {
100798
+ return;
100799
+ }
100800
+ const argv = ["move-pane"];
100801
+ argv.push(position === "left" || position === "right" ? "-h" : "-v");
100802
+ if (position === "left" || position === "top") {
100803
+ argv.push("-b");
100804
+ }
100805
+ argv.push("-s", srcPaneId, "-t", dstPaneId);
100806
+ this.runAndRefresh(argv, true).catch((error51) => {
100807
+ this.callbacks.onError(error51);
100808
+ });
100809
+ }
100810
+ breakPane(paneId) {
100811
+ if (!this.connected) {
100812
+ return;
100813
+ }
100814
+ this.breakPaneInternal(paneId).catch((error51) => {
100815
+ this.callbacks.onError(error51);
100816
+ });
100817
+ }
100818
+ async breakPaneInternal(paneId) {
100819
+ const result = await this.runTmux([
100820
+ "break-pane",
100821
+ "-s",
100822
+ paneId,
100823
+ "-t",
100824
+ `${this.sessionName}:`,
100825
+ "-P",
100826
+ "-F",
100827
+ `#{window_id}${SNAPSHOT_FIELD_SEPARATOR}#{pane_id}`
100828
+ ], true);
100829
+ const [windowId, newPaneId] = result.stdout.trim().split(SNAPSHOT_FIELD_SEPARATOR);
100830
+ if (isTmuxWindowId(windowId) && isTmuxPaneId(newPaneId)) {
100831
+ this.activeWindowId = windowId;
100832
+ this.activePaneId = newPaneId;
100833
+ this.callbacks.onEvent({
100834
+ type: "pane-active",
100835
+ data: { windowId, paneId: newPaneId }
100836
+ });
100837
+ }
100838
+ await this.requestSnapshotInternal();
100839
+ }
100840
+ async requestPaneHistory(paneId) {
100841
+ if (!this.connected) {
100842
+ return;
100843
+ }
100844
+ await this.capturePaneHistory(paneId);
100845
+ }
100435
100846
  renameWindow(windowId, name24) {
100436
100847
  if (!this.connected) {
100437
100848
  return;
@@ -100942,15 +101353,66 @@ class SshExternalTmuxConnection {
100942
101353
  await this.runAndRefresh(["kill-window", "-t", windowId], true);
100943
101354
  }
100944
101355
  async resizePaneInternal(paneId, cols, rows) {
100945
- const safeCols = Math.max(2, Math.floor(cols));
100946
- const safeRows = Math.max(2, Math.floor(rows));
100947
101356
  const windowId = this.findPaneWindowId(paneId) ?? (await this.runTmux(["display-message", "-p", "-t", paneId, "#{window_id}"], true)).stdout.trim();
100948
101357
  if (!windowId) {
100949
101358
  return;
100950
101359
  }
101360
+ await this.resizeWindowInternal(windowId, cols, rows);
101361
+ }
101362
+ async resizeWindowInternal(windowId, cols, rows) {
101363
+ const safeCols = Math.max(2, Math.floor(cols));
101364
+ const safeRows = Math.max(2, Math.floor(rows));
100951
101365
  await this.runTmux(["resize-window", "-t", windowId, "-x", String(safeCols), "-y", String(safeRows)], true);
100952
101366
  await this.requestSnapshotInternal();
100953
101367
  }
101368
+ async resizePaneByIdInternal(paneId, size) {
101369
+ const argv = ["resize-pane", "-t", paneId];
101370
+ if (size.cols !== undefined) {
101371
+ argv.push("-x", String(Math.max(2, Math.floor(size.cols))));
101372
+ }
101373
+ if (size.rows !== undefined) {
101374
+ argv.push("-y", String(Math.max(2, Math.floor(size.rows))));
101375
+ }
101376
+ if (argv.length === 3) {
101377
+ return;
101378
+ }
101379
+ await this.runTmux(argv, true);
101380
+ await this.requestSnapshotInternal();
101381
+ }
101382
+ async splitPaneInternal(paneId, direction, cwd) {
101383
+ const result = await this.runTmux([
101384
+ "split-window",
101385
+ direction === "h" ? "-h" : "-v",
101386
+ "-t",
101387
+ paneId,
101388
+ "-c",
101389
+ cwd ?? this.resolveDefaultWorkingDir(),
101390
+ "-P",
101391
+ "-F",
101392
+ `#{window_id}${SNAPSHOT_FIELD_SEPARATOR}#{pane_id}`
101393
+ ], true);
101394
+ const [windowId, newPaneId] = result.stdout.trim().split(SNAPSHOT_FIELD_SEPARATOR);
101395
+ if (isTmuxWindowId(windowId) && isTmuxPaneId(newPaneId)) {
101396
+ this.activeWindowId = windowId;
101397
+ this.activePaneId = newPaneId;
101398
+ this.callbacks.onEvent({
101399
+ type: "pane-active",
101400
+ data: { windowId, paneId: newPaneId }
101401
+ });
101402
+ }
101403
+ await this.requestSnapshotInternal();
101404
+ }
101405
+ async focusPaneInternal(windowId, paneId) {
101406
+ this.activeWindowId = windowId;
101407
+ this.activePaneId = paneId;
101408
+ await this.runTmux(["select-window", "-t", windowId], true);
101409
+ await this.runTmux(["select-pane", "-t", paneId], true);
101410
+ this.callbacks.onEvent({
101411
+ type: "pane-active",
101412
+ data: { windowId, paneId }
101413
+ });
101414
+ await this.requestSnapshotInternal();
101415
+ }
100954
101416
  async selectPaneInternal(windowId, paneId, size) {
100955
101417
  this.activeWindowId = windowId;
100956
101418
  this.activePaneId = paneId;
@@ -100993,16 +101455,9 @@ class SshExternalTmuxConnection {
100993
101455
  "-t",
100994
101456
  this.sessionName,
100995
101457
  "-F",
100996
- "#{window_id}|#{window_index}|#{window_name}|#{window_active}"
101458
+ WINDOW_SNAPSHOT_FORMAT
100997
101459
  ]),
100998
- this.runTmuxAllowFailure([
100999
- "list-panes",
101000
- "-s",
101001
- "-t",
101002
- this.sessionName,
101003
- "-F",
101004
- "#{pane_id}|#{window_id}|#{pane_index}|#{pane_title}|#{pane_active}|#{pane_width}|#{pane_height}|#{window_active}|#{pane_current_command}|#{pane_current_path}"
101005
- ])
101460
+ this.runTmuxAllowFailure(["list-panes", "-s", "-t", this.sessionName, "-F", PANE_SNAPSHOT_FORMAT])
101006
101461
  ]);
101007
101462
  if (sessionRes.exitCode !== 0 || windowsRes.exitCode !== 0 || panesRes.exitCode !== 0) {
101008
101463
  const stderrBlob = `${sessionRes.stderr}
@@ -101050,21 +101505,20 @@ ${panesRes.stderr}`;
101050
101505
  if (!line.trim()) {
101051
101506
  continue;
101052
101507
  }
101053
- const [id, indexRaw, name24, activeRaw] = splitSnapshotFields(line, 4);
101054
- const index = parseSnapshotInteger(indexRaw);
101055
- if (!isTmuxWindowId(id) || index === null || !this.isSnapshotFlag(activeRaw)) {
101508
+ const row = parseWindowSnapshotRow(line);
101509
+ if (!row) {
101056
101510
  console.warn(`[ssh] ignoring invalid tmux window snapshot row on ${this.deviceId}: ${formatSnapshotRowForLog(line)}`);
101057
101511
  continue;
101058
101512
  }
101059
- const active = activeRaw === "1";
101060
- if (active) {
101061
- this.activeWindowId = id;
101513
+ if (row.active) {
101514
+ this.activeWindowId = row.id;
101062
101515
  }
101063
- this.snapshotWindows.set(id, {
101064
- id,
101065
- index,
101066
- name: name24 ?? "",
101067
- active,
101516
+ this.snapshotWindows.set(row.id, {
101517
+ id: row.id,
101518
+ index: row.index,
101519
+ name: row.name,
101520
+ active: row.active,
101521
+ layout: row.layout,
101068
101522
  panes: []
101069
101523
  });
101070
101524
  }
@@ -101077,35 +101531,34 @@ ${panesRes.stderr}`;
101077
101531
  if (!line.trim()) {
101078
101532
  continue;
101079
101533
  }
101080
- const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw, currentCommandRaw, currentPathRaw] = splitSnapshotFields(line, 10);
101081
- const index = parseSnapshotInteger(indexRaw);
101082
- const width = parseSnapshotInteger(widthRaw);
101083
- const height = parseSnapshotInteger(heightRaw);
101084
- if (!isTmuxPaneId(paneId) || !isTmuxWindowId(windowId) || index === null || width === null || height === null || !this.isSnapshotFlag(activeRaw) || !this.isSnapshotFlag(windowActiveRaw)) {
101534
+ const row = parsePaneSnapshotRow(line);
101535
+ if (!row) {
101085
101536
  console.warn(`[ssh] ignoring invalid tmux pane snapshot row on ${this.deviceId}: ${formatSnapshotRowForLog(line)}`);
101086
101537
  continue;
101087
101538
  }
101088
101539
  const pane = {
101089
- id: paneId,
101090
- windowId,
101091
- index,
101092
- title: this.pendingPaneTitles.get(paneId) ?? (titleRaw?.trim() ? titleRaw : undefined),
101093
- currentCommand: currentCommandRaw?.trim() ? currentCommandRaw.trim() : undefined,
101094
- currentPath: currentPathRaw?.trim() ? currentPathRaw.trim() : undefined,
101095
- active: activeRaw === "1",
101096
- width,
101097
- height
101540
+ id: row.id,
101541
+ windowId: row.windowId,
101542
+ index: row.index,
101543
+ title: this.pendingPaneTitles.get(row.id) ?? row.title,
101544
+ currentCommand: row.currentCommand,
101545
+ currentPath: row.currentPath,
101546
+ active: row.active,
101547
+ width: row.width,
101548
+ height: row.height,
101549
+ left: row.left,
101550
+ top: row.top
101098
101551
  };
101099
- if (pane.active && windowActiveRaw === "1") {
101100
- this.activePaneId = paneId;
101101
- this.activeWindowId = windowId;
101552
+ if (pane.active && row.windowActive) {
101553
+ this.activePaneId = row.id;
101554
+ this.activeWindowId = row.windowId;
101102
101555
  }
101103
- const window2 = this.snapshotWindows.get(windowId);
101556
+ const window2 = this.snapshotWindows.get(row.windowId);
101104
101557
  if (!window2) {
101105
101558
  continue;
101106
101559
  }
101107
101560
  window2.panes.push(pane);
101108
- this.pendingPaneTitles.delete(paneId);
101561
+ this.pendingPaneTitles.delete(row.id);
101109
101562
  }
101110
101563
  for (const window2 of this.snapshotWindows.values()) {
101111
101564
  window2.panes.sort((left, right) => left.index - right.index);
@@ -101500,6 +101953,30 @@ class DeviceSessionRuntime {
101500
101953
  closePane(paneId) {
101501
101954
  this.connection.closePane(paneId);
101502
101955
  }
101956
+ splitPane(paneId, direction, cwd) {
101957
+ this.connection.splitPane(paneId, direction, cwd);
101958
+ }
101959
+ resizePaneById(paneId, size) {
101960
+ this.connection.resizePaneById(paneId, size);
101961
+ }
101962
+ resizeWindow(windowId, cols, rows) {
101963
+ this.connection.resizeWindow(windowId, cols, rows);
101964
+ }
101965
+ selectLayout(windowId, preset) {
101966
+ this.connection.selectLayout(windowId, preset);
101967
+ }
101968
+ focusPane(windowId, paneId) {
101969
+ this.connection.focusPane(windowId, paneId);
101970
+ }
101971
+ movePane(srcPaneId, dstPaneId, position) {
101972
+ this.connection.movePane(srcPaneId, dstPaneId, position);
101973
+ }
101974
+ breakPane(paneId) {
101975
+ this.connection.breakPane(paneId);
101976
+ }
101977
+ async requestPaneHistory(paneId) {
101978
+ return this.connection.requestPaneHistory(paneId);
101979
+ }
101503
101980
  renameWindow(windowId, name24) {
101504
101981
  this.connection.renameWindow(windowId, name24);
101505
101982
  }
@@ -101622,6 +102099,67 @@ var tmuxRuntimeRegistry = createTmuxRuntimeRegistry({
101622
102099
  }
101623
102100
  });
101624
102101
 
102102
+ // ../../apps/gateway/src/tmux/bell-context.ts
102103
+ function pickPaneById(windows, paneId) {
102104
+ for (const window2 of windows) {
102105
+ const pane = window2.panes.find((item) => item.id === paneId);
102106
+ if (pane) {
102107
+ return { window: window2, pane };
102108
+ }
102109
+ }
102110
+ return null;
102111
+ }
102112
+ function resolvePaneContext(options) {
102113
+ const { deviceId, snapshot, rawData } = options;
102114
+ const raw = rawData ?? {};
102115
+ const bellWindowId = typeof raw.windowId === "string" && raw.windowId ? raw.windowId : undefined;
102116
+ const bellPaneId = typeof raw.paneId === "string" && raw.paneId ? raw.paneId : undefined;
102117
+ if (!snapshot?.session) {
102118
+ return {
102119
+ windowId: bellWindowId,
102120
+ paneId: bellPaneId
102121
+ };
102122
+ }
102123
+ let targetWindow;
102124
+ let targetPane;
102125
+ if (bellPaneId) {
102126
+ const matched = pickPaneById(snapshot.session.windows, bellPaneId);
102127
+ if (matched) {
102128
+ targetWindow = matched.window;
102129
+ targetPane = matched.pane;
102130
+ }
102131
+ }
102132
+ if (!targetWindow && bellWindowId) {
102133
+ targetWindow = snapshot.session.windows.find((window2) => window2.id === bellWindowId);
102134
+ }
102135
+ if (!targetWindow) {
102136
+ targetWindow = snapshot.session.windows.find((window2) => window2.active) ?? snapshot.session.windows[0];
102137
+ }
102138
+ if (!targetPane && targetWindow) {
102139
+ targetPane = (bellPaneId ? targetWindow.panes.find((pane) => pane.id === bellPaneId) : undefined) ?? targetWindow.panes.find((pane) => pane.active) ?? targetWindow.panes[0];
102140
+ }
102141
+ const siteUrl = options.siteUrl.endsWith("/") ? options.siteUrl.slice(0, -1) : options.siteUrl;
102142
+ const paneUrl = targetWindow && targetPane ? `${siteUrl}/devices/${encodeURIComponent(deviceId)}/windows/${encodeURIComponent(targetWindow.id)}/panes/${encodeURIComponent(targetPane.id)}` : undefined;
102143
+ return {
102144
+ windowId: targetWindow?.id ?? bellWindowId,
102145
+ paneId: targetPane?.id ?? bellPaneId,
102146
+ windowIndex: targetWindow?.index,
102147
+ paneIndex: targetPane?.index,
102148
+ paneUrl,
102149
+ paneTitle: targetPane?.title,
102150
+ paneCurrentCommand: targetPane?.currentCommand
102151
+ };
102152
+ }
102153
+
102154
+ // ../../apps/gateway/src/tmux/snapshot-directory.ts
102155
+ var lookup = null;
102156
+ function registerSnapshotLookup(fn) {
102157
+ lookup = fn;
102158
+ }
102159
+ function getDeviceSnapshot(deviceId) {
102160
+ return lookup?.(deviceId) ?? null;
102161
+ }
102162
+
101625
102163
  // ../../apps/gateway/src/agent/secret-scan.ts
101626
102164
  var REDACTED = (type) => `[REDACTED:${type}]`;
101627
102165
  var RULES = [
@@ -103398,6 +103936,12 @@ class AgentRun {
103398
103936
  try {
103399
103937
  const settings = getSiteSettings();
103400
103938
  const device = session.deviceId ? getDeviceById(session.deviceId) : null;
103939
+ const paneContext = session.deviceId && session.paneId ? resolvePaneContext({
103940
+ deviceId: session.deviceId,
103941
+ siteUrl: settings.siteUrl,
103942
+ snapshot: getDeviceSnapshot(session.deviceId),
103943
+ rawData: { paneId: session.paneId }
103944
+ }) : null;
103401
103945
  await this.deps.notify(eventType, {
103402
103946
  site: {
103403
103947
  name: settings.siteName,
@@ -103411,6 +103955,7 @@ class AgentRun {
103411
103955
  },
103412
103956
  tmux: {
103413
103957
  sessionName: device?.session,
103958
+ ...paneContext ?? {},
103414
103959
  paneId: session.paneId ?? undefined
103415
103960
  },
103416
103961
  payload: {
@@ -103883,58 +104428,6 @@ class RuntimeController {
103883
104428
  }
103884
104429
  var runtimeController = new RuntimeController;
103885
104430
 
103886
- // ../../apps/gateway/src/tmux/bell-context.ts
103887
- function pickPaneById(windows, paneId) {
103888
- for (const window2 of windows) {
103889
- const pane = window2.panes.find((item) => item.id === paneId);
103890
- if (pane) {
103891
- return { window: window2, pane };
103892
- }
103893
- }
103894
- return null;
103895
- }
103896
- function resolvePaneContext(options) {
103897
- const { deviceId, snapshot, rawData } = options;
103898
- const raw = rawData ?? {};
103899
- const bellWindowId = typeof raw.windowId === "string" && raw.windowId ? raw.windowId : undefined;
103900
- const bellPaneId = typeof raw.paneId === "string" && raw.paneId ? raw.paneId : undefined;
103901
- if (!snapshot?.session) {
103902
- return {
103903
- windowId: bellWindowId,
103904
- paneId: bellPaneId
103905
- };
103906
- }
103907
- let targetWindow;
103908
- let targetPane;
103909
- if (bellPaneId) {
103910
- const matched = pickPaneById(snapshot.session.windows, bellPaneId);
103911
- if (matched) {
103912
- targetWindow = matched.window;
103913
- targetPane = matched.pane;
103914
- }
103915
- }
103916
- if (!targetWindow && bellWindowId) {
103917
- targetWindow = snapshot.session.windows.find((window2) => window2.id === bellWindowId);
103918
- }
103919
- if (!targetWindow) {
103920
- targetWindow = snapshot.session.windows.find((window2) => window2.active) ?? snapshot.session.windows[0];
103921
- }
103922
- if (!targetPane && targetWindow) {
103923
- targetPane = (bellPaneId ? targetWindow.panes.find((pane) => pane.id === bellPaneId) : undefined) ?? targetWindow.panes.find((pane) => pane.active) ?? targetWindow.panes[0];
103924
- }
103925
- const siteUrl = options.siteUrl.endsWith("/") ? options.siteUrl.slice(0, -1) : options.siteUrl;
103926
- const paneUrl = targetWindow && targetPane ? `${siteUrl}/devices/${encodeURIComponent(deviceId)}/windows/${encodeURIComponent(targetWindow.id)}/panes/${encodeURIComponent(targetPane.id)}` : undefined;
103927
- return {
103928
- windowId: targetWindow?.id ?? bellWindowId,
103929
- paneId: targetPane?.id ?? bellPaneId,
103930
- windowIndex: targetWindow?.index,
103931
- paneIndex: targetPane?.index,
103932
- paneUrl,
103933
- paneTitle: targetPane?.title,
103934
- paneCurrentCommand: targetPane?.currentCommand
103935
- };
103936
- }
103937
-
103938
104431
  // ../../apps/gateway/src/push/supervisor.ts
103939
104432
  var defaultDeps2 = {
103940
104433
  listDevices: () => getAllDevices(),
@@ -106755,8 +107248,8 @@ function getBaseVersion() {
106755
107248
  if (cachedBase !== undefined)
106756
107249
  return cachedBase;
106757
107250
  let base = null;
106758
- if ("0.15.2") {
106759
- base = "0.15.2";
107251
+ if ("0.16.1") {
107252
+ base = "0.16.1";
106760
107253
  }
106761
107254
  if (!base && config.isProd) {
106762
107255
  base = readInstallMeta()?.cliVersion ?? null;
@@ -109276,7 +109769,9 @@ function createBorshClientState() {
109276
109769
  negotiated: false,
109277
109770
  maxFrameBytes: exports_ws_borsh.DEFAULT_MAX_FRAME_BYTES,
109278
109771
  chunkReassembler: new exports_ws_borsh.ChunkReassembler,
109279
- selectedPanes: {}
109772
+ selectedPanes: {},
109773
+ subscribedPanes: {},
109774
+ pendingHistoryFetches: new Map
109280
109775
  };
109281
109776
  }
109282
109777
  function encodeTermOutput(params, seq) {
@@ -109787,6 +110282,15 @@ class SwitchBarrier {
109787
110282
  this.completeTransaction(ws, deviceId);
109788
110283
  pending.callbacks.onLiveResumed?.();
109789
110284
  }
110285
+ getTransactionPaneId(ws, deviceId) {
110286
+ const pending = this.getPending(ws, deviceId);
110287
+ if (!pending)
110288
+ return null;
110289
+ const selectState = sessionStateStore.getOrCreateSelectTransaction(ws, deviceId)?.state;
110290
+ if (selectState !== "ACKED")
110291
+ return null;
110292
+ return pending.context.paneId;
110293
+ }
109790
110294
  getSelectToken(ws, deviceId) {
109791
110295
  return this.getPending(ws, deviceId)?.context.selectToken ?? null;
109792
110296
  }
@@ -109908,6 +110412,7 @@ class WebSocketServer {
109908
110412
  connections = new Map;
109909
110413
  pendingConnectionEntries = new Map;
109910
110414
  windowCustomNames = new Map;
110415
+ paneCustomNames = new Map;
109911
110416
  deps;
109912
110417
  constructor(options = {}) {
109913
110418
  this.deps = {
@@ -109971,7 +110476,7 @@ class WebSocketServer {
109971
110476
  const entry = this.connections.get(deviceId);
109972
110477
  if (!entry)
109973
110478
  return;
109974
- const hasSelectedPaneClient = Array.from(entry.clients).some((client) => Boolean(client.data.borshState.selectedPanes[deviceId]));
110479
+ const hasSelectedPaneClient = Array.from(entry.clients).some((client) => Boolean(client.data.borshState.selectedPanes[deviceId]) || Boolean(client.data.borshState.subscribedPanes[deviceId]?.size));
109975
110480
  if (!hasSelectedPaneClient) {
109976
110481
  this.clearSnapshotPollTimer(entry);
109977
110482
  return;
@@ -110070,6 +110575,8 @@ class WebSocketServer {
110070
110575
  continue;
110071
110576
  entry.clients.delete(ws);
110072
110577
  delete ws.data.borshState.selectedPanes[deviceId];
110578
+ delete ws.data.borshState.subscribedPanes[deviceId];
110579
+ this.clearPendingHistoryFetches(ws, deviceId);
110073
110580
  if (entry.clients.size === 0) {
110074
110581
  console.log(`[ws] no more clients for device ${deviceId}, disconnecting`);
110075
110582
  this.releaseConnectionEntry(deviceId, entry);
@@ -110086,6 +110593,9 @@ class WebSocketServer {
110086
110593
  const entry = this.connections.get(deviceId);
110087
110594
  entry?.runtime.updateDefaultWorkingDir(dir2);
110088
110595
  }
110596
+ getLastSnapshot(deviceId) {
110597
+ return this.connections.get(deviceId)?.lastSnapshot ?? null;
110598
+ }
110089
110599
  closeAll() {
110090
110600
  for (const [deviceId, entry] of this.connections) {
110091
110601
  this.releaseConnectionEntry(deviceId, entry);
@@ -110163,6 +110673,51 @@ class WebSocketServer {
110163
110673
  this.handleReorderPanes(decoded.deviceId, decoded.windowId, decoded.paneIds);
110164
110674
  return;
110165
110675
  }
110676
+ case exports_ws_borsh.KIND_TMUX_SUBSCRIBE_PANES: {
110677
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxSubscribePanesSchema, payload);
110678
+ this.handleSubscribePanes(ws, decoded.deviceId, decoded.paneIds);
110679
+ return;
110680
+ }
110681
+ case exports_ws_borsh.KIND_TMUX_FETCH_PANE_HISTORY: {
110682
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxFetchPaneHistorySchema, payload);
110683
+ this.handleFetchPaneHistory(ws, decoded.deviceId, decoded.paneId, decoded.requestToken);
110684
+ return;
110685
+ }
110686
+ case exports_ws_borsh.KIND_TMUX_RESIZE_PANE: {
110687
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxResizePaneSchema, payload);
110688
+ this.handleResizePaneById(decoded.deviceId, decoded.paneId, decoded.cols ?? undefined, decoded.rows ?? undefined);
110689
+ return;
110690
+ }
110691
+ case exports_ws_borsh.KIND_TMUX_APPLY_STACKED_LAYOUT: {
110692
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxApplyStackedLayoutSchema, payload);
110693
+ this.handleApplyStackedLayout(decoded.deviceId, decoded.windowId, decoded.cols, decoded.rows);
110694
+ return;
110695
+ }
110696
+ case exports_ws_borsh.KIND_TMUX_SPLIT_PANE: {
110697
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxSplitPaneSchema, payload);
110698
+ this.handleSplitPane(decoded.deviceId, decoded.paneId, decoded.direction, decoded.cwd ?? undefined);
110699
+ return;
110700
+ }
110701
+ case exports_ws_borsh.KIND_TMUX_FOCUS_PANE: {
110702
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxFocusPaneSchema, payload);
110703
+ this.handleFocusPane(ws, decoded.deviceId, decoded.windowId, decoded.paneId);
110704
+ return;
110705
+ }
110706
+ case exports_ws_borsh.KIND_TMUX_RENAME_PANE: {
110707
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxRenamePaneSchema, payload);
110708
+ this.handleRenamePane(decoded.deviceId, decoded.paneId, decoded.name);
110709
+ return;
110710
+ }
110711
+ case exports_ws_borsh.KIND_TMUX_MOVE_PANE: {
110712
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxMovePaneSchema, payload);
110713
+ this.handleMovePane(decoded.deviceId, decoded.srcPaneId, decoded.dstPaneId, decoded.position);
110714
+ return;
110715
+ }
110716
+ case exports_ws_borsh.KIND_TMUX_BREAK_PANE: {
110717
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxBreakPaneSchema, payload);
110718
+ this.handleBreakPane(decoded.deviceId, decoded.paneId);
110719
+ return;
110720
+ }
110166
110721
  case exports_ws_borsh.KIND_TERM_INPUT: {
110167
110722
  const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TermInputSchema, payload);
110168
110723
  if (decoded.isComposing)
@@ -110221,7 +110776,7 @@ class WebSocketServer {
110221
110776
  selectedVersion: exports_ws_borsh.CURRENT_VERSION,
110222
110777
  maxFrameBytes: serverMaxFrameBytes,
110223
110778
  heartbeatIntervalMs: 15000,
110224
- capabilities: ["tmex-ws-borsh-v1", "tmex-agent-v1"]
110779
+ capabilities: ["tmex-ws-borsh-v1", "tmex-agent-v1", "tmex-split-v1"]
110225
110780
  };
110226
110781
  const payloadBytes = exports_ws_borsh.encodePayload(exports_ws_borsh.schema.HelloS2CSchema, helloS2C);
110227
110782
  this.sendEnvelope(ws, exports_ws_borsh.KIND_HELLO_S2C, payloadBytes);
@@ -110318,11 +110873,21 @@ class WebSocketServer {
110318
110873
  }
110319
110874
  }
110320
110875
  delete ws.data.borshState.selectedPanes[deviceId];
110876
+ delete ws.data.borshState.subscribedPanes[deviceId];
110877
+ this.clearPendingHistoryFetches(ws, deviceId);
110321
110878
  const disconnectedPayload = exports_ws_borsh.encodePayload(exports_ws_borsh.schema.DeviceDisconnectedSchema, {
110322
110879
  deviceId
110323
110880
  });
110324
110881
  this.sendEnvelope(ws, exports_ws_borsh.KIND_DEVICE_DISCONNECTED, disconnectedPayload);
110325
110882
  }
110883
+ clearPendingHistoryFetches(ws, deviceId) {
110884
+ const prefix = `${deviceId}:`;
110885
+ for (const key of ws.data.borshState.pendingHistoryFetches.keys()) {
110886
+ if (key.startsWith(prefix)) {
110887
+ ws.data.borshState.pendingHistoryFetches.delete(key);
110888
+ }
110889
+ }
110890
+ }
110326
110891
  handleTmuxSelect(ws, data) {
110327
110892
  const deviceId = data.deviceId;
110328
110893
  const entry = this.connections.get(deviceId);
@@ -110407,6 +110972,14 @@ class WebSocketServer {
110407
110972
  const entry = this.connections.get(deviceId);
110408
110973
  if (!entry)
110409
110974
  return;
110975
+ const snapshot = entry.lastSnapshot;
110976
+ if (snapshot?.session?.windows) {
110977
+ const window2 = snapshot.session.windows.find((w) => w.panes && w.panes.some((p) => p.id === paneId));
110978
+ if (window2 && window2.panes && window2.panes.length > 1) {
110979
+ entry.runtime.resizeWindow(window2.id, cols, rows);
110980
+ return;
110981
+ }
110982
+ }
110410
110983
  entry.runtime.resizePane(paneId, cols, rows);
110411
110984
  }
110412
110985
  handleTermPaste(deviceId, paneId, data) {
@@ -110437,6 +111010,46 @@ class WebSocketServer {
110437
111010
  return;
110438
111011
  entry.runtime.closePane(paneId);
110439
111012
  }
111013
+ handleRenamePane(deviceId, paneId, name24) {
111014
+ if (!isTmuxPaneId(paneId))
111015
+ return;
111016
+ const trimmed = name24.trim().slice(0, 64);
111017
+ const names = this.paneCustomNames.get(deviceId);
111018
+ if (!trimmed) {
111019
+ names?.delete(paneId);
111020
+ } else if (names) {
111021
+ names.set(paneId, trimmed);
111022
+ } else {
111023
+ this.paneCustomNames.set(deviceId, new Map([[paneId, trimmed]]));
111024
+ }
111025
+ const entry = this.connections.get(deviceId);
111026
+ if (!entry?.lastSnapshot)
111027
+ return;
111028
+ this.sendSnapshotToClients(entry, entry.lastSnapshot);
111029
+ }
111030
+ handleBreakPane(deviceId, paneId) {
111031
+ const entry = this.connections.get(deviceId);
111032
+ if (!entry || !isTmuxPaneId(paneId))
111033
+ return;
111034
+ entry.runtime.breakPane(paneId);
111035
+ }
111036
+ handleMovePane(deviceId, srcPaneId, dstPaneId, position) {
111037
+ const entry = this.connections.get(deviceId);
111038
+ if (!entry || !isTmuxPaneId(srcPaneId) || !isTmuxPaneId(dstPaneId))
111039
+ return;
111040
+ if (srcPaneId === dstPaneId)
111041
+ return;
111042
+ const positionMap = {
111043
+ 1: "left",
111044
+ 2: "right",
111045
+ 3: "top",
111046
+ 4: "bottom"
111047
+ };
111048
+ const resolved = positionMap[position];
111049
+ if (!resolved)
111050
+ return;
111051
+ entry.runtime.movePane(srcPaneId, dstPaneId, resolved);
111052
+ }
110440
111053
  handleRenameWindow(deviceId, windowId, name24) {
110441
111054
  const trimmed = name24.trim().slice(0, 64);
110442
111055
  const names = this.windowCustomNames.get(deviceId);
@@ -110472,14 +111085,100 @@ class WebSocketServer {
110472
111085
  return;
110473
111086
  this.sendSnapshotToClients(entry, entry.lastSnapshot);
110474
111087
  }
111088
+ handleSubscribePanes(ws, deviceId, paneIds) {
111089
+ const entry = this.connections.get(deviceId);
111090
+ if (!entry)
111091
+ return;
111092
+ const knownPaneIds = new Set(entry.lastSnapshot?.session?.windows.flatMap((window2) => window2.panes.map((pane) => pane.id)) ?? []);
111093
+ const accepted = new Set;
111094
+ for (const paneId of paneIds) {
111095
+ if (isTmuxPaneId(paneId) && knownPaneIds.has(paneId)) {
111096
+ accepted.add(paneId);
111097
+ }
111098
+ }
111099
+ if (accepted.size > 0) {
111100
+ ws.data.borshState.subscribedPanes[deviceId] = accepted;
111101
+ } else {
111102
+ delete ws.data.borshState.subscribedPanes[deviceId];
111103
+ }
111104
+ this.refreshSnapshotPolling(deviceId);
111105
+ }
111106
+ handleFetchPaneHistory(ws, deviceId, paneId, requestToken) {
111107
+ const entry = this.connections.get(deviceId);
111108
+ if (!entry || !isTmuxPaneId(paneId))
111109
+ return;
111110
+ ws.data.borshState.pendingHistoryFetches.set(`${deviceId}:${paneId}`, requestToken);
111111
+ entry.runtime.requestPaneHistory(paneId).catch((error51) => {
111112
+ console.warn(`[ws] fetch pane history failed on ${deviceId}/${paneId}:`, error51);
111113
+ ws.data.borshState.pendingHistoryFetches.delete(`${deviceId}:${paneId}`);
111114
+ });
111115
+ }
111116
+ handleResizePaneById(deviceId, paneId, cols, rows) {
111117
+ const entry = this.connections.get(deviceId);
111118
+ if (!entry || !isTmuxPaneId(paneId))
111119
+ return;
111120
+ if (cols === undefined && rows === undefined)
111121
+ return;
111122
+ entry.runtime.resizePaneById(paneId, { cols, rows });
111123
+ }
111124
+ handleApplyStackedLayout(deviceId, windowId, cols, rows) {
111125
+ const entry = this.connections.get(deviceId);
111126
+ if (!entry)
111127
+ return;
111128
+ if (!this.canSelectWindow(entry, deviceId, windowId))
111129
+ return;
111130
+ if (cols < 2 || rows < 2)
111131
+ return;
111132
+ const window2 = entry.lastSnapshot?.session?.windows.find((candidate) => candidate.id === windowId);
111133
+ const paneCount = window2?.panes.length ?? 0;
111134
+ if (!window2 || paneCount === 0)
111135
+ return;
111136
+ const alreadyStacked = window2.panes.every((pane) => pane.width === cols && pane.height === rows);
111137
+ if (alreadyStacked)
111138
+ return;
111139
+ const TMUX_MAX_WINDOW_COLS = 1e4;
111140
+ const totalCols = paneCount * cols + (paneCount - 1);
111141
+ const clampedCols = Math.min(totalCols, TMUX_MAX_WINDOW_COLS);
111142
+ if (clampedCols !== totalCols) {
111143
+ console.warn(`[ws] stacked layout width clamped on ${deviceId}/${windowId}: ${totalCols} -> ${clampedCols}`);
111144
+ }
111145
+ entry.runtime.resizeWindow(windowId, clampedCols, rows);
111146
+ if (paneCount > 1) {
111147
+ entry.runtime.selectLayout(windowId, "even-horizontal");
111148
+ }
111149
+ }
111150
+ handleSplitPane(deviceId, paneId, direction, cwd) {
111151
+ const entry = this.connections.get(deviceId);
111152
+ if (!entry || !isTmuxPaneId(paneId))
111153
+ return;
111154
+ const dir2 = direction === 2 ? "v" : "h";
111155
+ entry.runtime.splitPane(paneId, dir2, cwd);
111156
+ }
111157
+ handleFocusPane(ws, deviceId, windowId, paneId) {
111158
+ const entry = this.connections.get(deviceId);
111159
+ if (!entry)
111160
+ return;
111161
+ if (!this.canSelectPane(entry, deviceId, windowId, paneId))
111162
+ return;
111163
+ ws.data.borshState.selectedPanes[deviceId] = paneId;
111164
+ this.refreshSnapshotPolling(deviceId);
111165
+ entry.runtime.focusPane(windowId, paneId);
111166
+ }
110475
111167
  applyWindowCustomNames(payload) {
110476
111168
  const names = this.windowCustomNames.get(payload.deviceId);
110477
- if (!names?.size || !payload.session)
111169
+ const paneNames = this.paneCustomNames.get(payload.deviceId);
111170
+ if (!names?.size && !paneNames?.size || !payload.session)
110478
111171
  return payload;
110479
111172
  const liveWindowIds = new Set(payload.session.windows.map((w) => w.id));
110480
- for (const windowId of names.keys()) {
111173
+ for (const windowId of names?.keys() ?? []) {
110481
111174
  if (!liveWindowIds.has(windowId)) {
110482
- names.delete(windowId);
111175
+ names?.delete(windowId);
111176
+ }
111177
+ }
111178
+ const livePaneIds = new Set(payload.session.windows.flatMap((w) => w.panes.map((pane) => pane.id)));
111179
+ for (const paneId of paneNames?.keys() ?? []) {
111180
+ if (!livePaneIds.has(paneId)) {
111181
+ paneNames?.delete(paneId);
110483
111182
  }
110484
111183
  }
110485
111184
  return {
@@ -110487,8 +111186,12 @@ class WebSocketServer {
110487
111186
  session: {
110488
111187
  ...payload.session,
110489
111188
  windows: payload.session.windows.map((window2) => {
110490
- const customName = names.get(window2.id);
110491
- return customName ? { ...window2, customName } : window2;
111189
+ const customName = names?.get(window2.id);
111190
+ const panes = paneNames?.size ? window2.panes.map((pane) => {
111191
+ const paneCustomName = paneNames.get(pane.id);
111192
+ return paneCustomName ? { ...pane, customName: paneCustomName } : pane;
111193
+ }) : window2.panes;
111194
+ return customName || panes !== window2.panes ? { ...window2, ...customName ? { customName } : {}, panes } : window2;
110492
111195
  })
110493
111196
  }
110494
111197
  };
@@ -110627,10 +111330,12 @@ class WebSocketServer {
110627
111330
  if (!entry)
110628
111331
  return;
110629
111332
  for (const client of entry.clients) {
110630
- if (client.data.borshState.selectedPanes[deviceId] !== paneId) {
111333
+ const isFocused = client.data.borshState.selectedPanes[deviceId] === paneId;
111334
+ const isSubscribed = client.data.borshState.subscribedPanes[deviceId]?.has(paneId) ?? false;
111335
+ if (!isFocused && !isSubscribed) {
110631
111336
  continue;
110632
111337
  }
110633
- if (switchBarrier.shouldBufferOutput(client, deviceId)) {
111338
+ if (isFocused && switchBarrier.shouldBufferOutput(client, deviceId)) {
110634
111339
  switchBarrier.bufferOutput(client, deviceId, data);
110635
111340
  continue;
110636
111341
  }
@@ -110664,11 +111369,31 @@ class WebSocketServer {
110664
111369
  if (!entry)
110665
111370
  return;
110666
111371
  const historyBytes = new TextEncoder().encode(data);
111372
+ const fetchKey = `${deviceId}:${paneId}`;
110667
111373
  for (const client of entry.clients) {
110668
- if (client.data.borshState.selectedPanes[deviceId] !== paneId) {
111374
+ const txPaneId = switchBarrier.getTransactionPaneId(client, deviceId);
111375
+ if (txPaneId !== null && txPaneId === paneId) {
111376
+ switchBarrier.sendTermHistory(client, deviceId, paneId, historyBytes, alternateScreen);
111377
+ continue;
111378
+ }
111379
+ if (client.data.borshState.selectedPanes[deviceId] === paneId) {
111380
+ switchBarrier.sendTermHistory(client, deviceId, paneId, historyBytes, alternateScreen);
111381
+ continue;
111382
+ }
111383
+ const requestToken = client.data.borshState.pendingHistoryFetches.get(fetchKey);
111384
+ if (!requestToken) {
110669
111385
  continue;
110670
111386
  }
110671
- switchBarrier.sendTermHistory(client, deviceId, paneId, historyBytes, alternateScreen);
111387
+ client.data.borshState.pendingHistoryFetches.delete(fetchKey);
111388
+ const payloadBytes = exports_ws_borsh.encodePayload(exports_ws_borsh.schema.TermHistorySchema, {
111389
+ deviceId,
111390
+ paneId,
111391
+ selectToken: requestToken,
111392
+ encoding: 1,
111393
+ alternateScreen,
111394
+ data: historyBytes
111395
+ });
111396
+ this.sendChunked(client, exports_ws_borsh.KIND_TERM_HISTORY, payloadBytes);
110672
111397
  }
110673
111398
  }
110674
111399
  broadcastError(deviceId, err) {
@@ -110793,6 +111518,7 @@ async function createGatewayRuntime(options = {}) {
110793
111518
  connectionAlertNotifier.setBroadcaster((deviceId, payload) => {
110794
111519
  wsServer.broadcastDeviceError(deviceId, payload);
110795
111520
  });
111521
+ registerSnapshotLookup((deviceId) => wsServer.getLastSnapshot(deviceId));
110796
111522
  await telegramService.refresh();
110797
111523
  await weixinService.refresh();
110798
111524
  await pushSupervisor.start();