tmex-cli 0.13.0 → 0.15.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.
- package/CHANGELOG.md +13 -19
- package/dist/cli-node.js +492 -87
- package/dist/runtime/server.js +431 -44
- package/package.json +1 -1
- package/resources/fe-dist/assets/{DevicePage-Cj9jwadE.js → DevicePage-kndrXVHE.js} +1 -1
- package/resources/fe-dist/assets/DevicesPage-CZLzOS04.js +1 -0
- package/resources/fe-dist/assets/{FilePage-CbHZVJbn.js → FilePage-CxVqdlbt.js} +1 -1
- package/resources/fe-dist/assets/{SettingsPage-CCV0NSQF.js → SettingsPage-C50JRe91.js} +1 -1
- package/resources/fe-dist/assets/{agent-tab-DPwxh08T.js → agent-tab-BVWxou-d.js} +1 -1
- package/resources/fe-dist/assets/{api-DlcFE5in.js → api-CrHrQflz.js} +1 -1
- package/resources/fe-dist/assets/{arc-Bzmm6y8F.js → arc-fsY_kDTa.js} +1 -1
- package/resources/fe-dist/assets/{architectureDiagram-3BPJPVTR-BdsN6XRe.js → architectureDiagram-3BPJPVTR-Vsg8Cd3e.js} +1 -1
- package/resources/fe-dist/assets/{blockDiagram-GPEHLZMM-CXdQhkqo.js → blockDiagram-GPEHLZMM-G7sC3DZO.js} +1 -1
- package/resources/fe-dist/assets/{c4Diagram-AAUBKEIU-CE_W2_pV.js → c4Diagram-AAUBKEIU-C1AfLOva.js} +1 -1
- package/resources/fe-dist/assets/{card-B_sl9KIo.js → card-CXa-2u8i.js} +1 -1
- package/resources/fe-dist/assets/channel-DS4kWkSb.js +1 -0
- package/resources/fe-dist/assets/{chunk-2J33WTMH-BAdEIJQO.js → chunk-2J33WTMH-C1p02eGI.js} +1 -1
- package/resources/fe-dist/assets/{chunk-4BX2VUAB-BZ0yj21c.js → chunk-4BX2VUAB-C8n2FURp.js} +1 -1
- package/resources/fe-dist/assets/{chunk-55IACEB6-BknLtkSo.js → chunk-55IACEB6-Da0nuNCD.js} +1 -1
- package/resources/fe-dist/assets/{chunk-727SXJPM-CxVON9n5.js → chunk-727SXJPM-C1TXyDEt.js} +1 -1
- package/resources/fe-dist/assets/{chunk-AQP2D5EJ-CLqOK2pR.js → chunk-AQP2D5EJ-CnRKlbXo.js} +1 -1
- package/resources/fe-dist/assets/{chunk-FMBD7UC4-Dt5Vot-R.js → chunk-FMBD7UC4-B8HGrJ3t.js} +1 -1
- package/resources/fe-dist/assets/{chunk-ND2GUHAM-t9HYlb8C.js → chunk-ND2GUHAM-CcN2Ou-o.js} +1 -1
- package/resources/fe-dist/assets/{chunk-QZHKN3VN-DZReNtLB.js → chunk-QZHKN3VN-DfWJ_tl5.js} +1 -1
- package/resources/fe-dist/assets/classDiagram-4FO5ZUOK-BfsrnUi9.js +1 -0
- package/resources/fe-dist/assets/classDiagram-v2-Q7XG4LA2-BfsrnUi9.js +1 -0
- package/resources/fe-dist/assets/{copy-Z9Fsj1r-.js → copy-BveLgJe5.js} +1 -1
- package/resources/fe-dist/assets/{cose-bilkent-S5V4N54A-BCTtGF2n.js → cose-bilkent-S5V4N54A-BkmsTzwU.js} +1 -1
- package/resources/fe-dist/assets/{dagre-BM42HDAG-BQ48EqSj.js → dagre-BM42HDAG-pGgtc4EE.js} +1 -1
- package/resources/fe-dist/assets/{diagram-2AECGRRQ-BXjt2moR.js → diagram-2AECGRRQ-DJxixZvm.js} +1 -1
- package/resources/fe-dist/assets/{diagram-5GNKFQAL-B2bvNTQO.js → diagram-5GNKFQAL-2ITViev7.js} +1 -1
- package/resources/fe-dist/assets/{diagram-KO2AKTUF-DLHWfbBH.js → diagram-KO2AKTUF-EMcadaeo.js} +1 -1
- package/resources/fe-dist/assets/{diagram-LMA3HP47-BCFT3Bur.js → diagram-LMA3HP47-w3sLU7zY.js} +1 -1
- package/resources/fe-dist/assets/{diagram-OG6HWLK6-bNZtxUJ2.js → diagram-OG6HWLK6-B4KGMQr7.js} +1 -1
- package/resources/fe-dist/assets/en_US-Chxeay8F.js +1 -0
- package/resources/fe-dist/assets/{erDiagram-TEJ5UH35-KoAzrx4j.js → erDiagram-TEJ5UH35-CB0P-Wz7.js} +1 -1
- package/resources/fe-dist/assets/{files-tab-DdBDTjfs.js → files-tab-lNenDPFy.js} +1 -1
- package/resources/fe-dist/assets/{flowDiagram-I6XJVG4X-C6wGExWt.js → flowDiagram-I6XJVG4X-CmBc7GAX.js} +1 -1
- package/resources/fe-dist/assets/{ganttDiagram-6RSMTGT7-BIWybjes.js → ganttDiagram-6RSMTGT7-CHNf7S_K.js} +1 -1
- package/resources/fe-dist/assets/{gitGraphDiagram-PVQCEYII-CD6tz24l.js → gitGraphDiagram-PVQCEYII-CabspIF1.js} +1 -1
- package/resources/fe-dist/assets/{index-CUCrFB_J.js → index-BQbq6q_-.js} +1 -1
- package/resources/fe-dist/assets/{index-CwH-l50P.js → index-DOaZjm8K.js} +79 -79
- package/resources/fe-dist/assets/index-DaOR3c0u.css +1 -0
- package/resources/fe-dist/assets/{infoDiagram-5YYISTIA-CrI-qlYw.js → infoDiagram-5YYISTIA-ny6wqvHH.js} +1 -1
- package/resources/fe-dist/assets/{ishikawaDiagram-YF4QCWOH-D9v5anxN.js → ishikawaDiagram-YF4QCWOH-EFCdGVsV.js} +1 -1
- package/resources/fe-dist/assets/ja_JP-BI-C8I9X.js +1 -0
- package/resources/fe-dist/assets/{journeyDiagram-JHISSGLW-BH38CiJ0.js → journeyDiagram-JHISSGLW-Cvi8jO9a.js} +1 -1
- package/resources/fe-dist/assets/{kanban-definition-UN3LZRKU-CKZ3_oXD.js → kanban-definition-UN3LZRKU-nKej8tSo.js} +1 -1
- package/resources/fe-dist/assets/{linear-C_oE01xA.js → linear-leOPyu29.js} +1 -1
- package/resources/fe-dist/assets/{markdown-preview-BtNbNwlP.js → markdown-preview-rqUSs5w8.js} +3 -3
- package/resources/fe-dist/assets/{mermaid.core-4dbvlhht.js → mermaid.core-QvhJBi8f.js} +5 -5
- package/resources/fe-dist/assets/{mindmap-definition-RKZ34NQL-C5o4mnnX.js → mindmap-definition-RKZ34NQL-xWje0B_-.js} +1 -1
- package/resources/fe-dist/assets/{pieDiagram-4H26LBE5-2ss3HotB.js → pieDiagram-4H26LBE5-DT1i53ec.js} +1 -1
- package/resources/fe-dist/assets/{quadrantDiagram-W4KKPZXB-Bolcfx55.js → quadrantDiagram-W4KKPZXB-C1zbS4Tx.js} +1 -1
- package/resources/fe-dist/assets/{requirementDiagram-4Y6WPE33-B-atSHRR.js → requirementDiagram-4Y6WPE33-By_eNRll.js} +1 -1
- package/resources/fe-dist/assets/{sankeyDiagram-5OEKKPKP-ByynRcAV.js → sankeyDiagram-5OEKKPKP-CG7jC05N.js} +1 -1
- package/resources/fe-dist/assets/{send-D0P5wgcD.js → send-CcFyyX2G.js} +1 -1
- package/resources/fe-dist/assets/{sequenceDiagram-3UESZ5HK-CNC9IxV4.js → sequenceDiagram-3UESZ5HK-C9yK_EKN.js} +1 -1
- package/resources/fe-dist/assets/{stateDiagram-AJRCARHV-CqzYDImp.js → stateDiagram-AJRCARHV-B-ROUwGP.js} +1 -1
- package/resources/fe-dist/assets/stateDiagram-v2-BHNVJYJU-iopOcale.js +1 -0
- package/resources/fe-dist/assets/{terminal-settings-panel-cjw9P_wY.js → terminal-settings-panel-CNwWqOMV.js} +1 -1
- package/resources/fe-dist/assets/{timeline-definition-PNZ67QCA-C38KIECs.js → timeline-definition-PNZ67QCA-yMM8VB4U.js} +1 -1
- package/resources/fe-dist/assets/{transfer-toast-5tb-zYhi.js → transfer-toast-mQs0hgyg.js} +1 -1
- package/resources/fe-dist/assets/{triangle-alert-CQzql6mY.js → triangle-alert-DMp7kMmJ.js} +1 -1
- package/resources/fe-dist/assets/{vennDiagram-CIIHVFJN-BJudKfzJ.js → vennDiagram-CIIHVFJN-CE08llZ3.js} +1 -1
- package/resources/fe-dist/assets/{wardley-L42UT6IY-B6p_luMy.js → wardley-L42UT6IY-BKLGCmLJ.js} +1 -1
- package/resources/fe-dist/assets/{wardleyDiagram-YWT4CUSO-DZJeOiWQ.js → wardleyDiagram-YWT4CUSO-BsjwfO3P.js} +1 -1
- package/resources/fe-dist/assets/{xychartDiagram-2RQKCTM6-DOMCute2.js → xychartDiagram-2RQKCTM6-Bhz6AI7w.js} +1 -1
- package/resources/fe-dist/assets/{zap-DWNtdoic.js → zap-DPwn8lbv.js} +1 -1
- package/resources/fe-dist/assets/zh_CN-DE-BaQ3P.js +1 -0
- package/resources/fe-dist/index.html +2 -2
- package/resources/gateway-drizzle/0011_stormy_sauron.sql +1 -0
- package/resources/gateway-drizzle/meta/_journal.json +7 -0
- package/resources/fe-dist/assets/DevicesPage-BbypaGC7.js +0 -1
- package/resources/fe-dist/assets/channel-CuapxAWT.js +0 -1
- package/resources/fe-dist/assets/classDiagram-4FO5ZUOK-C0k136Ud.js +0 -1
- package/resources/fe-dist/assets/classDiagram-v2-Q7XG4LA2-C0k136Ud.js +0 -1
- package/resources/fe-dist/assets/en_US-B07wSHDj.js +0 -1
- package/resources/fe-dist/assets/index-D-q7dOhH.css +0 -1
- package/resources/fe-dist/assets/ja_JP-DjF6Lrmx.js +0 -1
- package/resources/fe-dist/assets/stateDiagram-v2-BHNVJYJU-C3azxyWE.js +0 -1
- package/resources/fe-dist/assets/zh_CN-D10j4J8Y.js +0 -1
package/dist/runtime/server.js
CHANGED
|
@@ -22654,6 +22654,8 @@ var I18N_RESOURCES = {
|
|
|
22654
22654
|
session: "Tmux Session Name",
|
|
22655
22655
|
sessionPlaceholder: "tmex",
|
|
22656
22656
|
sessionHint: 'Leave empty to use default "tmex"',
|
|
22657
|
+
defaultWorkingDir: "Default Working Directory",
|
|
22658
|
+
defaultWorkingDirPlaceholder: "Leave empty for user home directory",
|
|
22657
22659
|
authMode: "Authentication Mode",
|
|
22658
22660
|
authPassword: "Password",
|
|
22659
22661
|
authKey: "Private Key",
|
|
@@ -22708,9 +22710,12 @@ var I18N_RESOURCES = {
|
|
|
22708
22710
|
noDeviceSelected: "No device selected",
|
|
22709
22711
|
windowClosed: "Current window has been closed, please select a window from the sidebar.",
|
|
22710
22712
|
paneClosed: "Current pane has been closed, please select a pane from the sidebar.",
|
|
22711
|
-
bellNotification: "Terminal Bell
|
|
22712
|
-
|
|
22713
|
+
bellNotification: "Terminal Bell",
|
|
22714
|
+
bellDescriptionWithTitle: "Window {{window}} \xB7 {{paneLabel}}",
|
|
22713
22715
|
bellFallback: "Received tmux bell",
|
|
22716
|
+
notificationFallbackTitle: "Terminal Notification",
|
|
22717
|
+
notificationSourceLabel: "From {{source}}",
|
|
22718
|
+
notificationFallbackDetail: "Terminal notification",
|
|
22714
22719
|
paneTitle: "Pane {{index}}",
|
|
22715
22720
|
activePane: "Current Pane",
|
|
22716
22721
|
activeWindow: "Current Window",
|
|
@@ -23117,7 +23122,9 @@ Time: {{time}}`,
|
|
|
23117
23122
|
error: "WebSocket connection error",
|
|
23118
23123
|
checkGateway: "Please check Gateway status",
|
|
23119
23124
|
upgradeFailed: "Upgrade failed",
|
|
23120
|
-
invalidMessage: "Invalid message format"
|
|
23125
|
+
invalidMessage: "Invalid message format",
|
|
23126
|
+
reconnecting: "Reconnecting",
|
|
23127
|
+
reconnect: "Reconnect"
|
|
23121
23128
|
},
|
|
23122
23129
|
wsError: {
|
|
23123
23130
|
checkGateway: "Please check Gateway status"
|
|
@@ -23645,6 +23652,8 @@ Time: {{time}}`,
|
|
|
23645
23652
|
session: "Tmux \u4F1A\u8BDD\u540D\u79F0",
|
|
23646
23653
|
sessionPlaceholder: "tmex",
|
|
23647
23654
|
sessionHint: '\u7559\u7A7A\u5C06\u4F7F\u7528\u9ED8\u8BA4\u503C "tmex"',
|
|
23655
|
+
defaultWorkingDir: "\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55",
|
|
23656
|
+
defaultWorkingDirPlaceholder: "\u7559\u7A7A\u4F7F\u7528\u7528\u6237 home \u76EE\u5F55",
|
|
23648
23657
|
authMode: "\u8BA4\u8BC1\u65B9\u5F0F",
|
|
23649
23658
|
authPassword: "\u5BC6\u7801",
|
|
23650
23659
|
authKey: "\u79C1\u94A5",
|
|
@@ -23699,9 +23708,12 @@ Time: {{time}}`,
|
|
|
23699
23708
|
noDeviceSelected: "\u672A\u9009\u62E9\u8BBE\u5907",
|
|
23700
23709
|
windowClosed: "\u5F53\u524D\u7A97\u53E3\u5DF2\u5173\u95ED\uFF0C\u8BF7\u5728\u4FA7\u8FB9\u680F\u91CD\u65B0\u9009\u62E9\u7A97\u53E3\u3002",
|
|
23701
23710
|
paneClosed: "\u5F53\u524D Pane \u5DF2\u5173\u95ED\uFF0C\u8BF7\u5728\u4FA7\u8FB9\u680F\u91CD\u65B0\u9009\u62E9 Pane\u3002",
|
|
23702
|
-
bellNotification: "\u7EC8\u7AEF Bell
|
|
23703
|
-
|
|
23711
|
+
bellNotification: "\u7EC8\u7AEF Bell",
|
|
23712
|
+
bellDescriptionWithTitle: "\u7A97\u53E3 {{window}} \xB7 {{paneLabel}}",
|
|
23704
23713
|
bellFallback: "\u6536\u5230 tmux bell",
|
|
23714
|
+
notificationFallbackTitle: "\u7EC8\u7AEF\u901A\u77E5",
|
|
23715
|
+
notificationSourceLabel: "\u6765\u81EA {{source}}",
|
|
23716
|
+
notificationFallbackDetail: "\u7EC8\u7AEF\u901A\u77E5",
|
|
23705
23717
|
paneTitle: "Pane {{index}}",
|
|
23706
23718
|
activePane: "\u5F53\u524D pane",
|
|
23707
23719
|
activeWindow: "\u5F53\u524D\u7A97\u53E3",
|
|
@@ -24108,7 +24120,9 @@ Bot\uFF1A{{botName}}
|
|
|
24108
24120
|
error: "WebSocket \u8FDE\u63A5\u9519\u8BEF",
|
|
24109
24121
|
checkGateway: "\u8BF7\u68C0\u67E5 Gateway \u72B6\u6001",
|
|
24110
24122
|
upgradeFailed: "Upgrade failed",
|
|
24111
|
-
invalidMessage: "Invalid message format"
|
|
24123
|
+
invalidMessage: "Invalid message format",
|
|
24124
|
+
reconnecting: "\u91CD\u8FDE\u4E2D",
|
|
24125
|
+
reconnect: "\u91CD\u65B0\u8FDE\u63A5"
|
|
24112
24126
|
},
|
|
24113
24127
|
wsError: {
|
|
24114
24128
|
checkGateway: "\u8BF7\u68C0\u67E5 Gateway \u72B6\u6001"
|
|
@@ -24636,6 +24650,8 @@ Bot\uFF1A{{botName}}
|
|
|
24636
24650
|
session: "Tmux \u30BB\u30C3\u30B7\u30E7\u30F3\u540D",
|
|
24637
24651
|
sessionPlaceholder: "tmex",
|
|
24638
24652
|
sessionHint: "\u7A7A\u306E\u5834\u5408\u3001\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u300Ctmex\u300D\u304C\u4F7F\u7528\u3055\u308C\u307E\u3059",
|
|
24653
|
+
defaultWorkingDir: "\u30C7\u30D5\u30A9\u30EB\u30C8\u4F5C\u696D\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA",
|
|
24654
|
+
defaultWorkingDirPlaceholder: "\u7A7A\u306E\u5834\u5408\u3001\u30E6\u30FC\u30B6\u30FC\u306E\u30DB\u30FC\u30E0\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u4F7F\u7528",
|
|
24639
24655
|
authMode: "\u8A8D\u8A3C\u30E2\u30FC\u30C9",
|
|
24640
24656
|
authPassword: "\u30D1\u30B9\u30EF\u30FC\u30C9",
|
|
24641
24657
|
authKey: "\u79D8\u5BC6\u9375",
|
|
@@ -24690,9 +24706,12 @@ Bot\uFF1A{{botName}}
|
|
|
24690
24706
|
noDeviceSelected: "\u30C7\u30D0\u30A4\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093",
|
|
24691
24707
|
windowClosed: "\u73FE\u5728\u306E\u30A6\u30A3\u30F3\u30C9\u30A6\u306F\u9589\u3058\u3089\u308C\u307E\u3057\u305F\u3002\u30B5\u30A4\u30C9\u30D0\u30FC\u304B\u3089\u30A6\u30A3\u30F3\u30C9\u30A6\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
24692
24708
|
paneClosed: "\u73FE\u5728\u306E\u30DA\u30A4\u30F3\u306F\u9589\u3058\u3089\u308C\u307E\u3057\u305F\u3002\u30B5\u30A4\u30C9\u30D0\u30FC\u304B\u3089\u30DA\u30A4\u30F3\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
24693
|
-
bellNotification: "\u30BF\u30FC\u30DF\u30CA\u30EB\u30D9\u30EB
|
|
24694
|
-
|
|
24709
|
+
bellNotification: "\u30BF\u30FC\u30DF\u30CA\u30EB\u30D9\u30EB",
|
|
24710
|
+
bellDescriptionWithTitle: "\u30A6\u30A3\u30F3\u30C9\u30A6 {{window}} \xB7 {{paneLabel}}",
|
|
24695
24711
|
bellFallback: "tmux \u30D9\u30EB\u3092\u53D7\u4FE1",
|
|
24712
|
+
notificationFallbackTitle: "\u30BF\u30FC\u30DF\u30CA\u30EB\u901A\u77E5",
|
|
24713
|
+
notificationSourceLabel: "{{source}} \u304B\u3089",
|
|
24714
|
+
notificationFallbackDetail: "\u30BF\u30FC\u30DF\u30CA\u30EB\u901A\u77E5",
|
|
24696
24715
|
paneTitle: "\u30DA\u30A4\u30F3 {{index}}",
|
|
24697
24716
|
activePane: "\u73FE\u5728\u306E\u30DA\u30A4\u30F3",
|
|
24698
24717
|
activeWindow: "\u73FE\u5728\u306E\u30A6\u30A3\u30F3\u30C9\u30A6",
|
|
@@ -25099,7 +25118,9 @@ Bot\uFF1A{{botName}}
|
|
|
25099
25118
|
error: "WebSocket \u63A5\u7D9A\u30A8\u30E9\u30FC",
|
|
25100
25119
|
checkGateway: "Gateway \u72B6\u614B\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
25101
25120
|
upgradeFailed: "\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
25102
|
-
invalidMessage: "\u7121\u52B9\u306A\u30E1\u30C3\u30BB\u30FC\u30B8\u5F62\u5F0F"
|
|
25121
|
+
invalidMessage: "\u7121\u52B9\u306A\u30E1\u30C3\u30BB\u30FC\u30B8\u5F62\u5F0F",
|
|
25122
|
+
reconnecting: "\u518D\u63A5\u7D9A\u4E2D",
|
|
25123
|
+
reconnect: "\u518D\u63A5\u7D9A"
|
|
25103
25124
|
},
|
|
25104
25125
|
wsError: {
|
|
25105
25126
|
checkGateway: "Gateway \u72B6\u614B\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
@@ -25627,6 +25648,7 @@ __export(exports_ws_borsh, {
|
|
|
25627
25648
|
KIND_DEVICE_DISCONNECT: () => KIND_DEVICE_DISCONNECT,
|
|
25628
25649
|
KIND_DEVICE_CONNECTED: () => KIND_DEVICE_CONNECTED,
|
|
25629
25650
|
KIND_DEVICE_CONNECT: () => KIND_DEVICE_CONNECT,
|
|
25651
|
+
KIND_CLIPBOARD_WRITE: () => KIND_CLIPBOARD_WRITE,
|
|
25630
25652
|
KIND_CHUNK: () => KIND_CHUNK,
|
|
25631
25653
|
KIND_AGENT_UNSUBSCRIBE: () => KIND_AGENT_UNSUBSCRIBE,
|
|
25632
25654
|
KIND_AGENT_SUBSCRIBE: () => KIND_AGENT_SUBSCRIBE,
|
|
@@ -25698,6 +25720,7 @@ var KIND_TERM_RESIZE = 771;
|
|
|
25698
25720
|
var KIND_TERM_SYNC_SIZE = 772;
|
|
25699
25721
|
var KIND_TERM_OUTPUT = 773;
|
|
25700
25722
|
var KIND_TERM_HISTORY = 774;
|
|
25723
|
+
var KIND_CLIPBOARD_WRITE = 775;
|
|
25701
25724
|
var KIND_SWITCH_ACK = 1025;
|
|
25702
25725
|
var KIND_LIVE_RESUME = 1026;
|
|
25703
25726
|
var KIND_CHUNK = 1281;
|
|
@@ -25734,6 +25757,7 @@ var VALID_KINDS = new Set([
|
|
|
25734
25757
|
KIND_TERM_SYNC_SIZE,
|
|
25735
25758
|
KIND_TERM_OUTPUT,
|
|
25736
25759
|
KIND_TERM_HISTORY,
|
|
25760
|
+
KIND_CLIPBOARD_WRITE,
|
|
25737
25761
|
KIND_SWITCH_ACK,
|
|
25738
25762
|
KIND_LIVE_RESUME,
|
|
25739
25763
|
KIND_CHUNK,
|
|
@@ -25775,6 +25799,7 @@ function kindToString(kind) {
|
|
|
25775
25799
|
[KIND_TERM_SYNC_SIZE]: "TERM_SYNC_SIZE",
|
|
25776
25800
|
[KIND_TERM_OUTPUT]: "TERM_OUTPUT",
|
|
25777
25801
|
[KIND_TERM_HISTORY]: "TERM_HISTORY",
|
|
25802
|
+
[KIND_CLIPBOARD_WRITE]: "CLIPBOARD_WRITE",
|
|
25778
25803
|
[KIND_SWITCH_ACK]: "SWITCH_ACK",
|
|
25779
25804
|
[KIND_LIVE_RESUME]: "LIVE_RESUME",
|
|
25780
25805
|
[KIND_CHUNK]: "CHUNK",
|
|
@@ -25892,6 +25917,7 @@ __export(exports_schema, {
|
|
|
25892
25917
|
DeviceDisconnectSchema: () => DeviceDisconnectSchema,
|
|
25893
25918
|
DeviceConnectedSchema: () => DeviceConnectedSchema,
|
|
25894
25919
|
DeviceConnectSchema: () => DeviceConnectSchema,
|
|
25920
|
+
ClipboardWriteSchema: () => ClipboardWriteSchema,
|
|
25895
25921
|
ChunkSchema: () => ChunkSchema,
|
|
25896
25922
|
BellEventSchema: () => BellEventSchema,
|
|
25897
25923
|
AgentUnsubscribeSchema: () => AgentUnsubscribeSchema,
|
|
@@ -26037,6 +26063,11 @@ var TermHistorySchema = import_zorsh.b.struct({
|
|
|
26037
26063
|
alternateScreen: import_zorsh.b.bool(),
|
|
26038
26064
|
data: import_zorsh.b.bytes()
|
|
26039
26065
|
});
|
|
26066
|
+
var ClipboardWriteSchema = import_zorsh.b.struct({
|
|
26067
|
+
deviceId: import_zorsh.b.string(),
|
|
26068
|
+
paneId: import_zorsh.b.string(),
|
|
26069
|
+
text: import_zorsh.b.string()
|
|
26070
|
+
});
|
|
26040
26071
|
var SwitchAckSchema = import_zorsh.b.struct({
|
|
26041
26072
|
deviceId: import_zorsh.b.string(),
|
|
26042
26073
|
windowId: import_zorsh.b.string(),
|
|
@@ -26141,7 +26172,9 @@ var BellEventSchema = import_zorsh.b.struct({
|
|
|
26141
26172
|
paneId: OptionStringSchema,
|
|
26142
26173
|
windowIndex: OptionU16Schema,
|
|
26143
26174
|
paneIndex: OptionU16Schema,
|
|
26144
|
-
paneUrl: OptionStringSchema
|
|
26175
|
+
paneUrl: OptionStringSchema,
|
|
26176
|
+
paneTitle: OptionStringSchema,
|
|
26177
|
+
paneCurrentCommand: OptionStringSchema
|
|
26145
26178
|
});
|
|
26146
26179
|
var NotificationEventSchema = import_zorsh.b.struct({
|
|
26147
26180
|
source: import_zorsh.b.u8(),
|
|
@@ -26151,7 +26184,9 @@ var NotificationEventSchema = import_zorsh.b.struct({
|
|
|
26151
26184
|
paneId: OptionStringSchema,
|
|
26152
26185
|
windowIndex: OptionU16Schema,
|
|
26153
26186
|
paneIndex: OptionU16Schema,
|
|
26154
|
-
paneUrl: OptionStringSchema
|
|
26187
|
+
paneUrl: OptionStringSchema,
|
|
26188
|
+
paneTitle: OptionStringSchema,
|
|
26189
|
+
paneCurrentCommand: OptionStringSchema
|
|
26155
26190
|
});
|
|
26156
26191
|
// ../shared/src/ws-borsh/codec.ts
|
|
26157
26192
|
var MAGIC = new Uint8Array([84, 88]);
|
|
@@ -26468,7 +26503,9 @@ function encodeEventData(type, data) {
|
|
|
26468
26503
|
paneId: d.paneId ?? null,
|
|
26469
26504
|
windowIndex: d.windowIndex ?? null,
|
|
26470
26505
|
paneIndex: d.paneIndex ?? null,
|
|
26471
|
-
paneUrl: d.paneUrl ?? null
|
|
26506
|
+
paneUrl: d.paneUrl ?? null,
|
|
26507
|
+
paneTitle: d.paneTitle ?? null,
|
|
26508
|
+
paneCurrentCommand: d.paneCurrentCommand ?? null
|
|
26472
26509
|
});
|
|
26473
26510
|
}
|
|
26474
26511
|
case "output":
|
|
@@ -26483,7 +26520,9 @@ function encodeEventData(type, data) {
|
|
|
26483
26520
|
paneId: d.paneId ?? null,
|
|
26484
26521
|
windowIndex: d.windowIndex ?? null,
|
|
26485
26522
|
paneIndex: d.paneIndex ?? null,
|
|
26486
|
-
paneUrl: d.paneUrl ?? null
|
|
26523
|
+
paneUrl: d.paneUrl ?? null,
|
|
26524
|
+
paneTitle: d.paneTitle ?? null,
|
|
26525
|
+
paneCurrentCommand: d.paneCurrentCommand ?? null
|
|
26487
26526
|
});
|
|
26488
26527
|
}
|
|
26489
26528
|
default:
|
|
@@ -26594,7 +26633,9 @@ function decodeEventData(type, data) {
|
|
|
26594
26633
|
paneId: bell.paneId ?? undefined,
|
|
26595
26634
|
windowIndex: bell.windowIndex ?? undefined,
|
|
26596
26635
|
paneIndex: bell.paneIndex ?? undefined,
|
|
26597
|
-
paneUrl: bell.paneUrl ?? undefined
|
|
26636
|
+
paneUrl: bell.paneUrl ?? undefined,
|
|
26637
|
+
paneTitle: bell.paneTitle ?? undefined,
|
|
26638
|
+
paneCurrentCommand: bell.paneCurrentCommand ?? undefined
|
|
26598
26639
|
};
|
|
26599
26640
|
}
|
|
26600
26641
|
case "notification": {
|
|
@@ -26607,7 +26648,9 @@ function decodeEventData(type, data) {
|
|
|
26607
26648
|
paneId: notification.paneId ?? undefined,
|
|
26608
26649
|
windowIndex: notification.windowIndex ?? undefined,
|
|
26609
26650
|
paneIndex: notification.paneIndex ?? undefined,
|
|
26610
|
-
paneUrl: notification.paneUrl ?? undefined
|
|
26651
|
+
paneUrl: notification.paneUrl ?? undefined,
|
|
26652
|
+
paneTitle: notification.paneTitle ?? undefined,
|
|
26653
|
+
paneCurrentCommand: notification.paneCurrentCommand ?? undefined
|
|
26611
26654
|
};
|
|
26612
26655
|
}
|
|
26613
26656
|
default:
|
|
@@ -33148,6 +33191,7 @@ var devices = sqliteTable("devices", {
|
|
|
33148
33191
|
passwordEnc: text("password_enc"),
|
|
33149
33192
|
privateKeyEnc: text("private_key_enc"),
|
|
33150
33193
|
privateKeyPassphraseEnc: text("private_key_passphrase_enc"),
|
|
33194
|
+
defaultWorkingDir: text("default_working_dir"),
|
|
33151
33195
|
sortOrder: integer("sort_order").notNull().default(0),
|
|
33152
33196
|
createdAt: text("created_at").notNull(),
|
|
33153
33197
|
updatedAt: text("updated_at").notNull()
|
|
@@ -33401,6 +33445,7 @@ function toDevice(row) {
|
|
|
33401
33445
|
passwordEnc: optional(row.passwordEnc),
|
|
33402
33446
|
privateKeyEnc: optional(row.privateKeyEnc),
|
|
33403
33447
|
privateKeyPassphraseEnc: optional(row.privateKeyPassphraseEnc),
|
|
33448
|
+
defaultWorkingDir: optional(row.defaultWorkingDir),
|
|
33404
33449
|
sortOrder: row.sortOrder,
|
|
33405
33450
|
createdAt: row.createdAt,
|
|
33406
33451
|
updatedAt: row.updatedAt
|
|
@@ -33528,6 +33573,7 @@ function createDevice(device) {
|
|
|
33528
33573
|
passwordEnc: device.passwordEnc ?? null,
|
|
33529
33574
|
privateKeyEnc: device.privateKeyEnc ?? null,
|
|
33530
33575
|
privateKeyPassphraseEnc: device.privateKeyPassphraseEnc ?? null,
|
|
33576
|
+
defaultWorkingDir: device.defaultWorkingDir ?? null,
|
|
33531
33577
|
sortOrder: nextSortOrder,
|
|
33532
33578
|
createdAt: device.createdAt,
|
|
33533
33579
|
updatedAt: device.updatedAt
|
|
@@ -33597,6 +33643,9 @@ function updateDevice(id, updates) {
|
|
|
33597
33643
|
if (updates.privateKeyPassphraseEnc !== undefined) {
|
|
33598
33644
|
setValues.privateKeyPassphraseEnc = updates.privateKeyPassphraseEnc;
|
|
33599
33645
|
}
|
|
33646
|
+
if (updates.defaultWorkingDir !== undefined) {
|
|
33647
|
+
setValues.defaultWorkingDir = updates.defaultWorkingDir || null;
|
|
33648
|
+
}
|
|
33600
33649
|
orm.update(devices).set(setValues).where(eq(devices.id, id)).run();
|
|
33601
33650
|
}
|
|
33602
33651
|
function deleteDevice(id) {
|
|
@@ -98249,6 +98298,28 @@ function createPaneStreamParser(options) {
|
|
|
98249
98298
|
options.onNotification({ source: "osc1337", body: "RequestAttention" });
|
|
98250
98299
|
}
|
|
98251
98300
|
return;
|
|
98301
|
+
case "52": {
|
|
98302
|
+
const separatorIndex = payload.indexOf(";");
|
|
98303
|
+
if (separatorIndex < 0) {
|
|
98304
|
+
return;
|
|
98305
|
+
}
|
|
98306
|
+
const base64Data = payload.slice(separatorIndex + 1);
|
|
98307
|
+
if (!base64Data || base64Data === "?") {
|
|
98308
|
+
return;
|
|
98309
|
+
}
|
|
98310
|
+
try {
|
|
98311
|
+
const binaryString = atob(base64Data);
|
|
98312
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
98313
|
+
for (let i = 0;i < binaryString.length; i++) {
|
|
98314
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
98315
|
+
}
|
|
98316
|
+
const text3 = new TextDecoder("utf-8", { fatal: false }).decode(bytes);
|
|
98317
|
+
if (text3) {
|
|
98318
|
+
options.onClipboardWrite?.(text3);
|
|
98319
|
+
}
|
|
98320
|
+
} catch {}
|
|
98321
|
+
return;
|
|
98322
|
+
}
|
|
98252
98323
|
case "133": {
|
|
98253
98324
|
const parts = payload.split(";");
|
|
98254
98325
|
const kind = parts[0];
|
|
@@ -98388,7 +98459,7 @@ function createPaneStreamParser(options) {
|
|
|
98388
98459
|
}
|
|
98389
98460
|
if (phase === "osc-params") {
|
|
98390
98461
|
if (byte === 59) {
|
|
98391
|
-
phase = oscKind === "0" || oscKind === "1" || oscKind === "2" || oscKind === "9" || oscKind === "99" || oscKind === "133" || oscKind === "777" || oscKind === "1337" ? "osc-body" : "osc-body-ignore";
|
|
98462
|
+
phase = oscKind === "0" || oscKind === "1" || oscKind === "2" || oscKind === "9" || oscKind === "52" || oscKind === "99" || oscKind === "133" || oscKind === "777" || oscKind === "1337" ? "osc-body" : "osc-body-ignore";
|
|
98392
98463
|
return;
|
|
98393
98464
|
}
|
|
98394
98465
|
if (byte === 7) {
|
|
@@ -98516,7 +98587,8 @@ function createControlModeSubscription(callbacks) {
|
|
|
98516
98587
|
onTitle: (title) => callbacks.onTitle(paneId, title),
|
|
98517
98588
|
onBell: () => callbacks.onBell(paneId),
|
|
98518
98589
|
onNotification: (notification) => callbacks.onNotification(paneId, notification),
|
|
98519
|
-
onPromptMarker: (marker24) => callbacks.onPromptMarker?.(paneId, marker24)
|
|
98590
|
+
onPromptMarker: (marker24) => callbacks.onPromptMarker?.(paneId, marker24),
|
|
98591
|
+
onClipboardWrite: (text3) => callbacks.onClipboardWrite?.(paneId, text3)
|
|
98520
98592
|
});
|
|
98521
98593
|
paneParsers.set(paneId, parser2);
|
|
98522
98594
|
return parser2;
|
|
@@ -98547,6 +98619,11 @@ function createControlModeSubscription(callbacks) {
|
|
|
98547
98619
|
if (STRUCTURE_NOTIFICATION_TYPES.has(notification.type)) {
|
|
98548
98620
|
scheduleStructureChanged();
|
|
98549
98621
|
}
|
|
98622
|
+
if (notification.type === "pause") {
|
|
98623
|
+
callbacks.onPause?.(notification.args.trim());
|
|
98624
|
+
} else if (notification.type === "continue") {
|
|
98625
|
+
callbacks.onContinue?.(notification.args.trim());
|
|
98626
|
+
}
|
|
98550
98627
|
}
|
|
98551
98628
|
const parser = createControlModeParser({
|
|
98552
98629
|
onOutput: (paneId, data) => {
|
|
@@ -98822,6 +98899,8 @@ var CONTROL_RESTART_DELAY_MS = 500;
|
|
|
98822
98899
|
var CONTROL_STABLE_RESET_MS = 1e4;
|
|
98823
98900
|
var CONTROL_STDERR_TAIL_LIMIT = 2048;
|
|
98824
98901
|
var CONTROL_ATTACH_READY_TIMEOUT_MS = 3000;
|
|
98902
|
+
var HEARTBEAT_INTERVAL_MS = 30000;
|
|
98903
|
+
var HEARTBEAT_TIMEOUT_MS = 1e4;
|
|
98825
98904
|
var PARKING_WINDOW_NAME = "tmex-park";
|
|
98826
98905
|
function hasRenderableTerminalContent(value) {
|
|
98827
98906
|
return value.trim().length > 0;
|
|
@@ -98880,6 +98959,11 @@ function defaultSpawnControlClient(argv) {
|
|
|
98880
98959
|
stdin?.end();
|
|
98881
98960
|
} catch {}
|
|
98882
98961
|
subprocess.kill();
|
|
98962
|
+
},
|
|
98963
|
+
write: (data) => {
|
|
98964
|
+
try {
|
|
98965
|
+
stdin?.write(data);
|
|
98966
|
+
} catch {}
|
|
98883
98967
|
}
|
|
98884
98968
|
};
|
|
98885
98969
|
}
|
|
@@ -98907,6 +98991,9 @@ class LocalExternalTmuxConnection {
|
|
|
98907
98991
|
controlRestartCount = 0;
|
|
98908
98992
|
controlStderrTail = "";
|
|
98909
98993
|
spawnUnavailableNotified = false;
|
|
98994
|
+
heartbeatTimer = null;
|
|
98995
|
+
heartbeatPending = false;
|
|
98996
|
+
heartbeatTimeoutTimer = null;
|
|
98910
98997
|
constructor(options, inputDeps = {}) {
|
|
98911
98998
|
this.deviceId = options.deviceId;
|
|
98912
98999
|
this.callbacks = options;
|
|
@@ -99019,7 +99106,10 @@ class LocalExternalTmuxConnection {
|
|
|
99019
99106
|
if (!this.connected) {
|
|
99020
99107
|
return;
|
|
99021
99108
|
}
|
|
99022
|
-
const argv =
|
|
99109
|
+
const argv = ["new-window", "-t", this.sessionName, "-c", this.resolveDefaultWorkingDir()];
|
|
99110
|
+
if (name24) {
|
|
99111
|
+
argv.push("-n", name24);
|
|
99112
|
+
}
|
|
99023
99113
|
this.runAndRefresh(argv).catch((error51) => {
|
|
99024
99114
|
this.callbacks.onError(error51);
|
|
99025
99115
|
});
|
|
@@ -99048,6 +99138,20 @@ class LocalExternalTmuxConnection {
|
|
|
99048
99138
|
this.callbacks.onError(error51);
|
|
99049
99139
|
});
|
|
99050
99140
|
}
|
|
99141
|
+
updateDefaultWorkingDir(dir2) {
|
|
99142
|
+
if (this.device) {
|
|
99143
|
+
this.device = { ...this.device, defaultWorkingDir: dir2 };
|
|
99144
|
+
}
|
|
99145
|
+
if (this.connected) {
|
|
99146
|
+
this.runTmuxAllowFailure([
|
|
99147
|
+
"set-option",
|
|
99148
|
+
"-t",
|
|
99149
|
+
this.sessionName,
|
|
99150
|
+
"default-path",
|
|
99151
|
+
this.resolveDefaultWorkingDir()
|
|
99152
|
+
]);
|
|
99153
|
+
}
|
|
99154
|
+
}
|
|
99051
99155
|
setWindowStyle(style) {
|
|
99052
99156
|
if (!this.connected) {
|
|
99053
99157
|
return;
|
|
@@ -99077,12 +99181,15 @@ class LocalExternalTmuxConnection {
|
|
|
99077
99181
|
const { stdout } = await this.runTmux(["display-message", "-p", "-t", paneId, PANE_META_FORMAT], "silent");
|
|
99078
99182
|
return parsePaneMeta(stdout);
|
|
99079
99183
|
}
|
|
99184
|
+
resolveDefaultWorkingDir() {
|
|
99185
|
+
return this.device?.defaultWorkingDir?.trim() || homedir();
|
|
99186
|
+
}
|
|
99080
99187
|
async ensureSession() {
|
|
99081
99188
|
const exists3 = await this.runTmuxAllowFailure(["has-session", "-t", this.sessionName]);
|
|
99082
99189
|
if (exists3.exitCode === 0) {
|
|
99083
99190
|
return;
|
|
99084
99191
|
}
|
|
99085
|
-
await this.runTmux(["new-session", "-d", "-c",
|
|
99192
|
+
await this.runTmux(["new-session", "-d", "-c", this.resolveDefaultWorkingDir(), "-s", this.sessionName]);
|
|
99086
99193
|
}
|
|
99087
99194
|
async configureSessionOptions() {
|
|
99088
99195
|
await this.runTmuxAllowFailure([
|
|
@@ -99136,6 +99243,13 @@ class LocalExternalTmuxConnection {
|
|
|
99136
99243
|
"COLORTERM",
|
|
99137
99244
|
"truecolor"
|
|
99138
99245
|
]);
|
|
99246
|
+
await this.runTmuxAllowFailure([
|
|
99247
|
+
"set-option",
|
|
99248
|
+
"-t",
|
|
99249
|
+
this.sessionName,
|
|
99250
|
+
"default-path",
|
|
99251
|
+
this.resolveDefaultWorkingDir()
|
|
99252
|
+
]);
|
|
99139
99253
|
await this.configureWindowStyle();
|
|
99140
99254
|
}
|
|
99141
99255
|
async configureWindowStyle(styleValue = config.tmuxWindowStyle) {
|
|
@@ -99212,6 +99326,7 @@ class LocalExternalTmuxConnection {
|
|
|
99212
99326
|
await this.runTmuxAllowFailure(["kill-window", "-t", windowId]);
|
|
99213
99327
|
}
|
|
99214
99328
|
async startControlClient() {
|
|
99329
|
+
this.stopHeartbeat();
|
|
99215
99330
|
let attachReadyResolve = null;
|
|
99216
99331
|
const attachReady = new Promise((resolve3) => {
|
|
99217
99332
|
attachReadyResolve = resolve3;
|
|
@@ -99235,6 +99350,7 @@ class LocalExternalTmuxConnection {
|
|
|
99235
99350
|
console.warn(`[local] tmux control client died during attach on ${this.deviceId}: ${message}`);
|
|
99236
99351
|
throw new Error(message);
|
|
99237
99352
|
}
|
|
99353
|
+
this.startHeartbeat();
|
|
99238
99354
|
}
|
|
99239
99355
|
spawnControlClientProcess(onAttachReady) {
|
|
99240
99356
|
const subscription = createControlModeSubscription({
|
|
@@ -99254,12 +99370,22 @@ class LocalExternalTmuxConnection {
|
|
|
99254
99370
|
onPromptMarker: (paneId, marker24) => {
|
|
99255
99371
|
this.callbacks.onPromptMarker?.(paneId, marker24);
|
|
99256
99372
|
},
|
|
99373
|
+
onClipboardWrite: (paneId, text3) => {
|
|
99374
|
+
this.callbacks.onClipboardWrite?.(paneId, text3);
|
|
99375
|
+
},
|
|
99257
99376
|
onStructureChanged: () => {
|
|
99258
99377
|
this.requestSnapshot();
|
|
99259
99378
|
},
|
|
99379
|
+
onPause: (paneId) => {
|
|
99380
|
+
this.controlProcess?.write("refresh-client -A " + paneId + `:continue
|
|
99381
|
+
`);
|
|
99382
|
+
},
|
|
99260
99383
|
onExit: () => {},
|
|
99261
|
-
onBlockEnd: () => {
|
|
99384
|
+
onBlockEnd: (block) => {
|
|
99262
99385
|
onAttachReady();
|
|
99386
|
+
if (!block.isError && block.lines.length === 1 && block.lines[0] === "tmex-hb") {
|
|
99387
|
+
this.onHeartbeatResponse();
|
|
99388
|
+
}
|
|
99263
99389
|
}
|
|
99264
99390
|
});
|
|
99265
99391
|
const proc = this.deps.spawnControlClient([
|
|
@@ -99299,6 +99425,10 @@ class LocalExternalTmuxConnection {
|
|
|
99299
99425
|
}
|
|
99300
99426
|
}
|
|
99301
99427
|
subscription.end();
|
|
99428
|
+
if (this.controlProcess === proc) {
|
|
99429
|
+
console.warn("[local] control client stdout ended unexpectedly on " + this.deviceId + ", killing process");
|
|
99430
|
+
proc.kill();
|
|
99431
|
+
}
|
|
99302
99432
|
}
|
|
99303
99433
|
async pumpControlStderr(proc) {
|
|
99304
99434
|
const reader = proc.stderr.getReader();
|
|
@@ -99316,12 +99446,55 @@ class LocalExternalTmuxConnection {
|
|
|
99316
99446
|
} catch {}
|
|
99317
99447
|
}
|
|
99318
99448
|
stopControlClient() {
|
|
99449
|
+
this.stopHeartbeat();
|
|
99319
99450
|
const proc = this.controlProcess;
|
|
99320
99451
|
this.controlProcess = null;
|
|
99321
99452
|
this.controlSubscription?.dispose();
|
|
99322
99453
|
this.controlSubscription = null;
|
|
99323
99454
|
proc?.kill();
|
|
99324
99455
|
}
|
|
99456
|
+
startHeartbeat() {
|
|
99457
|
+
this.stopHeartbeat();
|
|
99458
|
+
this.heartbeatTimer = setInterval(() => {
|
|
99459
|
+
this.sendHeartbeat();
|
|
99460
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
99461
|
+
}
|
|
99462
|
+
stopHeartbeat() {
|
|
99463
|
+
if (this.heartbeatTimer) {
|
|
99464
|
+
clearInterval(this.heartbeatTimer);
|
|
99465
|
+
this.heartbeatTimer = null;
|
|
99466
|
+
}
|
|
99467
|
+
if (this.heartbeatTimeoutTimer) {
|
|
99468
|
+
clearTimeout(this.heartbeatTimeoutTimer);
|
|
99469
|
+
this.heartbeatTimeoutTimer = null;
|
|
99470
|
+
}
|
|
99471
|
+
this.heartbeatPending = false;
|
|
99472
|
+
}
|
|
99473
|
+
sendHeartbeat() {
|
|
99474
|
+
if (!this.controlProcess || this.heartbeatPending || !this.connected || this.manualDisconnect) {
|
|
99475
|
+
return;
|
|
99476
|
+
}
|
|
99477
|
+
this.heartbeatPending = true;
|
|
99478
|
+
this.controlProcess.write(`display-message -p "tmex-hb"
|
|
99479
|
+
`);
|
|
99480
|
+
this.heartbeatTimeoutTimer = setTimeout(() => {
|
|
99481
|
+
if (!this.heartbeatPending || !this.connected || this.manualDisconnect) {
|
|
99482
|
+
return;
|
|
99483
|
+
}
|
|
99484
|
+
console.warn(`[local] tmux control client heartbeat timeout on ${this.deviceId}, killing stalled process`);
|
|
99485
|
+
this.controlProcess?.kill();
|
|
99486
|
+
}, HEARTBEAT_TIMEOUT_MS);
|
|
99487
|
+
}
|
|
99488
|
+
onHeartbeatResponse() {
|
|
99489
|
+
if (!this.heartbeatPending) {
|
|
99490
|
+
return;
|
|
99491
|
+
}
|
|
99492
|
+
this.heartbeatPending = false;
|
|
99493
|
+
if (this.heartbeatTimeoutTimer) {
|
|
99494
|
+
clearTimeout(this.heartbeatTimeoutTimer);
|
|
99495
|
+
this.heartbeatTimeoutTimer = null;
|
|
99496
|
+
}
|
|
99497
|
+
}
|
|
99325
99498
|
handleControlClientExit(proc, exitCode) {
|
|
99326
99499
|
if (this.controlProcess !== proc) {
|
|
99327
99500
|
return;
|
|
@@ -99397,7 +99570,7 @@ class LocalExternalTmuxConnection {
|
|
|
99397
99570
|
async closeWindowInternal(windowId) {
|
|
99398
99571
|
const count2 = Number.parseInt((await this.runTmux(["display-message", "-p", "-t", this.sessionName, "#{session_windows}"])).stdout.trim() || "0", 10);
|
|
99399
99572
|
if (count2 <= 1) {
|
|
99400
|
-
await this.runTmux(["new-window", "-d", "-t", this.sessionName]);
|
|
99573
|
+
await this.runTmux(["new-window", "-d", "-t", this.sessionName, "-c", this.resolveDefaultWorkingDir()]);
|
|
99401
99574
|
}
|
|
99402
99575
|
await this.runAndRefresh(["kill-window", "-t", windowId], true);
|
|
99403
99576
|
}
|
|
@@ -100101,6 +100274,8 @@ var CONTROL_RESTART_DELAY_MS2 = 500;
|
|
|
100101
100274
|
var CONTROL_STABLE_RESET_MS2 = 1e4;
|
|
100102
100275
|
var CONTROL_STDERR_TAIL_LIMIT2 = 2048;
|
|
100103
100276
|
var CONTROL_ATTACH_READY_TIMEOUT_MS2 = 3000;
|
|
100277
|
+
var HEARTBEAT_INTERVAL_MS2 = 30000;
|
|
100278
|
+
var HEARTBEAT_TIMEOUT_MS2 = 1e4;
|
|
100104
100279
|
var PARKING_WINDOW_NAME2 = "tmex-park";
|
|
100105
100280
|
|
|
100106
100281
|
class SshExternalTmuxConnection {
|
|
@@ -100124,6 +100299,9 @@ class SshExternalTmuxConnection {
|
|
|
100124
100299
|
controlStartedAt = 0;
|
|
100125
100300
|
controlRestartCount = 0;
|
|
100126
100301
|
controlStderrTail = "";
|
|
100302
|
+
heartbeatTimer = null;
|
|
100303
|
+
heartbeatPending = false;
|
|
100304
|
+
heartbeatTimeoutTimer = null;
|
|
100127
100305
|
sshClient = null;
|
|
100128
100306
|
commandStream = null;
|
|
100129
100307
|
commandStdoutBuffer = "";
|
|
@@ -100221,7 +100399,10 @@ class SshExternalTmuxConnection {
|
|
|
100221
100399
|
if (!this.connected) {
|
|
100222
100400
|
return;
|
|
100223
100401
|
}
|
|
100224
|
-
const argv =
|
|
100402
|
+
const argv = ["new-window", "-t", this.sessionName, "-c", this.resolveDefaultWorkingDir()];
|
|
100403
|
+
if (name24) {
|
|
100404
|
+
argv.push("-n", name24);
|
|
100405
|
+
}
|
|
100225
100406
|
this.runAndRefresh(argv).catch((error51) => {
|
|
100226
100407
|
this.callbacks.onError(error51);
|
|
100227
100408
|
});
|
|
@@ -100250,6 +100431,20 @@ class SshExternalTmuxConnection {
|
|
|
100250
100431
|
this.callbacks.onError(error51);
|
|
100251
100432
|
});
|
|
100252
100433
|
}
|
|
100434
|
+
updateDefaultWorkingDir(dir2) {
|
|
100435
|
+
if (this.device) {
|
|
100436
|
+
this.device = { ...this.device, defaultWorkingDir: dir2 };
|
|
100437
|
+
}
|
|
100438
|
+
if (this.connected) {
|
|
100439
|
+
this.runTmuxAllowFailure([
|
|
100440
|
+
"set-option",
|
|
100441
|
+
"-t",
|
|
100442
|
+
this.sessionName,
|
|
100443
|
+
"default-path",
|
|
100444
|
+
this.resolveDefaultWorkingDir()
|
|
100445
|
+
]);
|
|
100446
|
+
}
|
|
100447
|
+
}
|
|
100253
100448
|
setWindowStyle(style) {
|
|
100254
100449
|
if (!this.connected) {
|
|
100255
100450
|
return;
|
|
@@ -100385,12 +100580,15 @@ class SshExternalTmuxConnection {
|
|
|
100385
100580
|
throw new Error(message);
|
|
100386
100581
|
}
|
|
100387
100582
|
}
|
|
100583
|
+
resolveDefaultWorkingDir() {
|
|
100584
|
+
return this.device?.defaultWorkingDir?.trim() || this.remoteHomeDir;
|
|
100585
|
+
}
|
|
100388
100586
|
async ensureSession() {
|
|
100389
100587
|
const exists3 = await this.runTmuxAllowFailure(["has-session", "-t", this.sessionName]);
|
|
100390
100588
|
if (exists3.exitCode === 0) {
|
|
100391
100589
|
return;
|
|
100392
100590
|
}
|
|
100393
|
-
await this.runTmux(["new-session", "-d", "-c", this.
|
|
100591
|
+
await this.runTmux(["new-session", "-d", "-c", this.resolveDefaultWorkingDir(), "-s", this.sessionName]);
|
|
100394
100592
|
}
|
|
100395
100593
|
async configureSessionOptions() {
|
|
100396
100594
|
await this.runTmuxAllowFailure([
|
|
@@ -100444,6 +100642,13 @@ class SshExternalTmuxConnection {
|
|
|
100444
100642
|
"COLORTERM",
|
|
100445
100643
|
"truecolor"
|
|
100446
100644
|
]);
|
|
100645
|
+
await this.runTmuxAllowFailure([
|
|
100646
|
+
"set-option",
|
|
100647
|
+
"-t",
|
|
100648
|
+
this.sessionName,
|
|
100649
|
+
"default-path",
|
|
100650
|
+
this.resolveDefaultWorkingDir()
|
|
100651
|
+
]);
|
|
100447
100652
|
await this.configureWindowStyle();
|
|
100448
100653
|
}
|
|
100449
100654
|
async configureWindowStyle(styleValue = config.tmuxWindowStyle) {
|
|
@@ -100518,6 +100723,7 @@ class SshExternalTmuxConnection {
|
|
|
100518
100723
|
await this.runTmuxAllowFailure(["kill-window", "-t", windowId]);
|
|
100519
100724
|
}
|
|
100520
100725
|
async startControlClient() {
|
|
100726
|
+
this.stopHeartbeat();
|
|
100521
100727
|
let attachReadyResolve = null;
|
|
100522
100728
|
const attachReady = new Promise((resolve3) => {
|
|
100523
100729
|
attachReadyResolve = resolve3;
|
|
@@ -100539,6 +100745,7 @@ class SshExternalTmuxConnection {
|
|
|
100539
100745
|
if (this.controlChannel !== handle) {
|
|
100540
100746
|
throw new Error(this.controlStderrTail.trim() || "tmux control client channel closed during attach");
|
|
100541
100747
|
}
|
|
100748
|
+
this.startHeartbeat();
|
|
100542
100749
|
}
|
|
100543
100750
|
async openControlChannel(onAttachReady) {
|
|
100544
100751
|
const subscription = createControlModeSubscription({
|
|
@@ -100558,20 +100765,32 @@ class SshExternalTmuxConnection {
|
|
|
100558
100765
|
onPromptMarker: (paneId, marker24) => {
|
|
100559
100766
|
this.callbacks.onPromptMarker?.(paneId, marker24);
|
|
100560
100767
|
},
|
|
100768
|
+
onClipboardWrite: (paneId, text3) => {
|
|
100769
|
+
this.callbacks.onClipboardWrite?.(paneId, text3);
|
|
100770
|
+
},
|
|
100561
100771
|
onStructureChanged: () => {
|
|
100562
100772
|
this.requestSnapshot();
|
|
100563
100773
|
},
|
|
100564
100774
|
onExit: () => {},
|
|
100565
|
-
|
|
100775
|
+
onPause: (paneId) => {
|
|
100776
|
+
if (this.controlChannel === handle) {
|
|
100777
|
+
handle.write("refresh-client -A " + paneId + ":continue" + `
|
|
100778
|
+
`);
|
|
100779
|
+
}
|
|
100780
|
+
},
|
|
100781
|
+
onBlockEnd: (block) => {
|
|
100566
100782
|
onAttachReady();
|
|
100783
|
+
if (!block.isError && block.lines.length === 1 && block.lines[0] === "tmex-hb") {
|
|
100784
|
+
this.onHeartbeatResponse();
|
|
100785
|
+
}
|
|
100567
100786
|
}
|
|
100568
100787
|
});
|
|
100569
|
-
const handle = { stop: () => {} };
|
|
100788
|
+
const handle = { stop: () => {}, write: () => {} };
|
|
100570
100789
|
this.controlChannel = handle;
|
|
100571
100790
|
this.controlSubscription = subscription;
|
|
100572
100791
|
this.controlStartedAt = Date.now();
|
|
100573
100792
|
this.controlStderrTail = "";
|
|
100574
|
-
const
|
|
100793
|
+
const reader = await this.openReaderChannel(`exec ${quoteShellArg(this.tmuxBin)} -C attach-session -t ${quoteShellArg(this.sessionName)}`, {
|
|
100575
100794
|
onData: (data) => {
|
|
100576
100795
|
if (this.controlChannel === handle) {
|
|
100577
100796
|
subscription.push(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
|
|
@@ -100586,16 +100805,60 @@ class SshExternalTmuxConnection {
|
|
|
100586
100805
|
this.handleControlChannelClose(handle);
|
|
100587
100806
|
}
|
|
100588
100807
|
});
|
|
100589
|
-
handle.stop =
|
|
100808
|
+
handle.stop = reader.stop;
|
|
100809
|
+
handle.write = reader.write;
|
|
100590
100810
|
return handle;
|
|
100591
100811
|
}
|
|
100592
100812
|
stopControlClient() {
|
|
100813
|
+
this.stopHeartbeat();
|
|
100593
100814
|
const handle = this.controlChannel;
|
|
100594
100815
|
this.controlChannel = null;
|
|
100595
100816
|
this.controlSubscription?.dispose();
|
|
100596
100817
|
this.controlSubscription = null;
|
|
100597
100818
|
handle?.stop();
|
|
100598
100819
|
}
|
|
100820
|
+
startHeartbeat() {
|
|
100821
|
+
if (this.heartbeatTimer) {
|
|
100822
|
+
clearInterval(this.heartbeatTimer);
|
|
100823
|
+
}
|
|
100824
|
+
if (this.heartbeatTimeoutTimer) {
|
|
100825
|
+
clearTimeout(this.heartbeatTimeoutTimer);
|
|
100826
|
+
}
|
|
100827
|
+
this.heartbeatPending = false;
|
|
100828
|
+
this.heartbeatTimer = setInterval(() => this.sendHeartbeat(), HEARTBEAT_INTERVAL_MS2);
|
|
100829
|
+
}
|
|
100830
|
+
stopHeartbeat() {
|
|
100831
|
+
if (this.heartbeatTimer) {
|
|
100832
|
+
clearInterval(this.heartbeatTimer);
|
|
100833
|
+
this.heartbeatTimer = null;
|
|
100834
|
+
}
|
|
100835
|
+
if (this.heartbeatTimeoutTimer) {
|
|
100836
|
+
clearTimeout(this.heartbeatTimeoutTimer);
|
|
100837
|
+
this.heartbeatTimeoutTimer = null;
|
|
100838
|
+
}
|
|
100839
|
+
this.heartbeatPending = false;
|
|
100840
|
+
}
|
|
100841
|
+
sendHeartbeat() {
|
|
100842
|
+
if (!this.controlChannel || this.heartbeatPending || !this.connected || this.manualDisconnect) {
|
|
100843
|
+
return;
|
|
100844
|
+
}
|
|
100845
|
+
this.heartbeatPending = true;
|
|
100846
|
+
this.controlChannel.write('display-message -p "tmex-hb"' + `
|
|
100847
|
+
`);
|
|
100848
|
+
this.heartbeatTimeoutTimer = setTimeout(() => {
|
|
100849
|
+
if (this.heartbeatPending && this.connected && !this.manualDisconnect) {
|
|
100850
|
+
console.warn(`[ssh] tmux control client heartbeat timeout on ${this.deviceId}, killing stalled channel`);
|
|
100851
|
+
this.controlChannel?.stop();
|
|
100852
|
+
}
|
|
100853
|
+
}, HEARTBEAT_TIMEOUT_MS2);
|
|
100854
|
+
}
|
|
100855
|
+
onHeartbeatResponse() {
|
|
100856
|
+
this.heartbeatPending = false;
|
|
100857
|
+
if (this.heartbeatTimeoutTimer) {
|
|
100858
|
+
clearTimeout(this.heartbeatTimeoutTimer);
|
|
100859
|
+
this.heartbeatTimeoutTimer = null;
|
|
100860
|
+
}
|
|
100861
|
+
}
|
|
100599
100862
|
handleControlChannelClose(handle) {
|
|
100600
100863
|
if (this.controlChannel !== handle) {
|
|
100601
100864
|
return;
|
|
@@ -100665,7 +100928,7 @@ class SshExternalTmuxConnection {
|
|
|
100665
100928
|
async closeWindowInternal(windowId) {
|
|
100666
100929
|
const count2 = Number.parseInt((await this.runTmux(["display-message", "-p", "-t", this.sessionName, "#{session_windows}"])).stdout.trim() || "0", 10);
|
|
100667
100930
|
if (count2 <= 1) {
|
|
100668
|
-
await this.runTmux(["new-window", "-d", "-t", this.sessionName]);
|
|
100931
|
+
await this.runTmux(["new-window", "-d", "-t", this.sessionName, "-c", this.resolveDefaultWorkingDir()]);
|
|
100669
100932
|
}
|
|
100670
100933
|
await this.runAndRefresh(["kill-window", "-t", windowId], true);
|
|
100671
100934
|
}
|
|
@@ -101046,10 +101309,17 @@ printf '\\036TMEX_END %s %d\\036\\n' ${quoteShellArg(commandId)} $?
|
|
|
101046
101309
|
});
|
|
101047
101310
|
stream.write(`${command}
|
|
101048
101311
|
`);
|
|
101049
|
-
return
|
|
101050
|
-
|
|
101051
|
-
|
|
101052
|
-
|
|
101312
|
+
return {
|
|
101313
|
+
stop: () => {
|
|
101314
|
+
stream.end();
|
|
101315
|
+
stream.close();
|
|
101316
|
+
stream.destroy();
|
|
101317
|
+
},
|
|
101318
|
+
write: (data) => {
|
|
101319
|
+
try {
|
|
101320
|
+
stream.write(data);
|
|
101321
|
+
} catch {}
|
|
101322
|
+
}
|
|
101053
101323
|
};
|
|
101054
101324
|
}
|
|
101055
101325
|
isTmuxServerGoneMessage(message) {
|
|
@@ -101135,6 +101405,9 @@ class DeviceSessionRuntime {
|
|
|
101135
101405
|
onPromptMarker: (paneId, marker24) => {
|
|
101136
101406
|
this.broadcast((listener) => listener.onPromptMarker?.(paneId, marker24));
|
|
101137
101407
|
},
|
|
101408
|
+
onClipboardWrite: (paneId, text3) => {
|
|
101409
|
+
this.broadcast((listener) => listener.onClipboardWrite?.(paneId, text3));
|
|
101410
|
+
},
|
|
101138
101411
|
onSnapshot: (payload) => {
|
|
101139
101412
|
this.broadcast((listener) => listener.onSnapshot?.(payload));
|
|
101140
101413
|
},
|
|
@@ -101205,6 +101478,9 @@ class DeviceSessionRuntime {
|
|
|
101205
101478
|
selectWindow(windowId) {
|
|
101206
101479
|
this.connection.selectWindow(windowId);
|
|
101207
101480
|
}
|
|
101481
|
+
updateDefaultWorkingDir(dir2) {
|
|
101482
|
+
this.connection.updateDefaultWorkingDir(dir2);
|
|
101483
|
+
}
|
|
101208
101484
|
createWindow(name24) {
|
|
101209
101485
|
this.connection.createWindow(name24);
|
|
101210
101486
|
}
|
|
@@ -103775,6 +104051,10 @@ class PushSupervisor {
|
|
|
103775
104051
|
}
|
|
103776
104052
|
await this.upsert(deviceId);
|
|
103777
104053
|
}
|
|
104054
|
+
updateDefaultWorkingDir(deviceId, dir2) {
|
|
104055
|
+
const entry = this.entries.get(deviceId);
|
|
104056
|
+
entry?.runtime?.updateDefaultWorkingDir(dir2);
|
|
104057
|
+
}
|
|
103778
104058
|
remove(deviceId) {
|
|
103779
104059
|
const entry = this.entries.get(deviceId);
|
|
103780
104060
|
if (!entry) {
|
|
@@ -104909,6 +105189,49 @@ function typeFromPerms(perms) {
|
|
|
104909
105189
|
return "other";
|
|
104910
105190
|
}
|
|
104911
105191
|
}
|
|
105192
|
+
function unescapeOctal(input) {
|
|
105193
|
+
if (!input.includes("\\"))
|
|
105194
|
+
return input;
|
|
105195
|
+
const result = [];
|
|
105196
|
+
let pendingBytes = [];
|
|
105197
|
+
const flushBytes = () => {
|
|
105198
|
+
if (pendingBytes.length === 0)
|
|
105199
|
+
return;
|
|
105200
|
+
result.push(new TextDecoder().decode(new Uint8Array(pendingBytes)));
|
|
105201
|
+
pendingBytes = [];
|
|
105202
|
+
};
|
|
105203
|
+
let i = 0;
|
|
105204
|
+
while (i < input.length) {
|
|
105205
|
+
if (input[i] !== "\\") {
|
|
105206
|
+
flushBytes();
|
|
105207
|
+
result.push(input[i]);
|
|
105208
|
+
i++;
|
|
105209
|
+
continue;
|
|
105210
|
+
}
|
|
105211
|
+
if (input[i + 1] === "\\") {
|
|
105212
|
+
flushBytes();
|
|
105213
|
+
result.push("\\");
|
|
105214
|
+
i += 2;
|
|
105215
|
+
continue;
|
|
105216
|
+
}
|
|
105217
|
+
if (i + 3 < input.length) {
|
|
105218
|
+
const digits = input.slice(i + 1, i + 4);
|
|
105219
|
+
if (/^[0-7]{3}$/.test(digits)) {
|
|
105220
|
+
const val = parseInt(digits, 8);
|
|
105221
|
+
if (val <= 255) {
|
|
105222
|
+
pendingBytes.push(val);
|
|
105223
|
+
i += 4;
|
|
105224
|
+
continue;
|
|
105225
|
+
}
|
|
105226
|
+
}
|
|
105227
|
+
}
|
|
105228
|
+
flushBytes();
|
|
105229
|
+
result.push("\\");
|
|
105230
|
+
i++;
|
|
105231
|
+
}
|
|
105232
|
+
flushBytes();
|
|
105233
|
+
return result.join("");
|
|
105234
|
+
}
|
|
104912
105235
|
function parseListOnly(stdout) {
|
|
104913
105236
|
const entries = [];
|
|
104914
105237
|
for (const rawLine of stdout.split(`
|
|
@@ -104918,7 +105241,7 @@ function parseListOnly(stdout) {
|
|
|
104918
105241
|
if (!m)
|
|
104919
105242
|
continue;
|
|
104920
105243
|
const type = typeFromPerms(m[1]);
|
|
104921
|
-
let name24 = m[9];
|
|
105244
|
+
let name24 = unescapeOctal(m[9]);
|
|
104922
105245
|
if (type === "symlink") {
|
|
104923
105246
|
const arrow = name24.indexOf(" -> ");
|
|
104924
105247
|
if (arrow >= 0)
|
|
@@ -105067,7 +105390,7 @@ function rsyncTargetArg(spec, remotePath) {
|
|
|
105067
105390
|
return `${spec.targetPrefix}${quoteShellArg(remotePath)}`;
|
|
105068
105391
|
}
|
|
105069
105392
|
function rsyncListArgs(spec, remotePath) {
|
|
105070
|
-
const args = ["--list-only"];
|
|
105393
|
+
const args = ["--list-only", "--8-bit-output"];
|
|
105071
105394
|
if (spec.rsh)
|
|
105072
105395
|
args.push("-e", spec.rsh);
|
|
105073
105396
|
args.push(rsyncTargetArg(spec, remotePath));
|
|
@@ -106422,8 +106745,8 @@ function getBaseVersion() {
|
|
|
106422
106745
|
if (cachedBase !== undefined)
|
|
106423
106746
|
return cachedBase;
|
|
106424
106747
|
let base = null;
|
|
106425
|
-
if ("0.
|
|
106426
|
-
base = "0.
|
|
106748
|
+
if ("0.15.0") {
|
|
106749
|
+
base = "0.15.0";
|
|
106427
106750
|
}
|
|
106428
106751
|
if (!base && config.isProd) {
|
|
106429
106752
|
base = readInstallMeta()?.cliVersion ?? null;
|
|
@@ -108442,6 +108765,7 @@ async function handleCreateDevice(req) {
|
|
|
108442
108765
|
username: body.username,
|
|
108443
108766
|
sshConfigRef: body.sshConfigRef,
|
|
108444
108767
|
session: body.session ?? "tmex",
|
|
108768
|
+
defaultWorkingDir: body.defaultWorkingDir?.trim() || undefined,
|
|
108445
108769
|
authMode: body.authMode,
|
|
108446
108770
|
passwordEnc: body.password ? await encrypt(body.password) : undefined,
|
|
108447
108771
|
privateKeyEnc: body.privateKey ? await encrypt(body.privateKey) : undefined,
|
|
@@ -108473,6 +108797,8 @@ async function handleUpdateDevice(req, id) {
|
|
|
108473
108797
|
updates.sshConfigRef = body.sshConfigRef;
|
|
108474
108798
|
if (body.session !== undefined)
|
|
108475
108799
|
updates.session = body.session;
|
|
108800
|
+
if (body.defaultWorkingDir !== undefined)
|
|
108801
|
+
updates.defaultWorkingDir = body.defaultWorkingDir.trim() || undefined;
|
|
108476
108802
|
if (body.authMode !== undefined)
|
|
108477
108803
|
updates.authMode = body.authMode;
|
|
108478
108804
|
if (body.password !== undefined)
|
|
@@ -108485,6 +108811,8 @@ async function handleUpdateDevice(req, id) {
|
|
|
108485
108811
|
updateDevice(id, updates);
|
|
108486
108812
|
if (shouldReconnectPushSupervisor(existing, updates)) {
|
|
108487
108813
|
await pushSupervisor.reconnect(id);
|
|
108814
|
+
} else if (updates.defaultWorkingDir !== undefined && updates.defaultWorkingDir !== existing.defaultWorkingDir) {
|
|
108815
|
+
pushSupervisor.updateDefaultWorkingDir(id, updates.defaultWorkingDir);
|
|
108488
108816
|
}
|
|
108489
108817
|
const device = getDeviceById(id);
|
|
108490
108818
|
return json9({ device });
|
|
@@ -109614,6 +109942,9 @@ class WebSocketServer {
|
|
|
109614
109942
|
onTerminalHistory: (paneId, data, alternateScreen) => {
|
|
109615
109943
|
this.broadcastTerminalHistory(deviceId, paneId, data, alternateScreen);
|
|
109616
109944
|
},
|
|
109945
|
+
onClipboardWrite: (paneId, text3) => {
|
|
109946
|
+
this.broadcastClipboardWrite(deviceId, paneId, text3);
|
|
109947
|
+
},
|
|
109617
109948
|
onSnapshot: (payload) => {
|
|
109618
109949
|
this.broadcastStateSnapshot(deviceId, payload);
|
|
109619
109950
|
},
|
|
@@ -109741,6 +110072,10 @@ class WebSocketServer {
|
|
|
109741
110072
|
this.connections.delete(deviceId);
|
|
109742
110073
|
}
|
|
109743
110074
|
}
|
|
110075
|
+
updateDefaultWorkingDir(deviceId, dir2) {
|
|
110076
|
+
const entry = this.connections.get(deviceId);
|
|
110077
|
+
entry?.runtime.updateDefaultWorkingDir(dir2);
|
|
110078
|
+
}
|
|
109744
110079
|
closeAll() {
|
|
109745
110080
|
for (const [deviceId, entry] of this.connections) {
|
|
109746
110081
|
this.releaseConnectionEntry(deviceId, entry);
|
|
@@ -110298,6 +110633,22 @@ class WebSocketServer {
|
|
|
110298
110633
|
this.sendChunked(client, exports_ws_borsh.KIND_TERM_OUTPUT, payloadBytes);
|
|
110299
110634
|
}
|
|
110300
110635
|
}
|
|
110636
|
+
broadcastClipboardWrite(deviceId, paneId, text3) {
|
|
110637
|
+
const entry = this.connections.get(deviceId);
|
|
110638
|
+
if (!entry)
|
|
110639
|
+
return;
|
|
110640
|
+
const payloadBytes = exports_ws_borsh.encodePayload(exports_ws_borsh.schema.ClipboardWriteSchema, {
|
|
110641
|
+
deviceId,
|
|
110642
|
+
paneId,
|
|
110643
|
+
text: text3
|
|
110644
|
+
});
|
|
110645
|
+
for (const client of entry.clients) {
|
|
110646
|
+
if (client.data.borshState.selectedPanes[deviceId] !== paneId) {
|
|
110647
|
+
continue;
|
|
110648
|
+
}
|
|
110649
|
+
this.sendEnvelope(client, exports_ws_borsh.KIND_CLIPBOARD_WRITE, payloadBytes);
|
|
110650
|
+
}
|
|
110651
|
+
}
|
|
110301
110652
|
broadcastTerminalHistory(deviceId, paneId, data, alternateScreen) {
|
|
110302
110653
|
const entry = this.connections.get(deviceId);
|
|
110303
110654
|
if (!entry)
|
|
@@ -110496,8 +110847,8 @@ var MESSAGES = {
|
|
|
110496
110847
|
"cli.help": `tmex CLI
|
|
110497
110848
|
|
|
110498
110849
|
Usage:
|
|
110499
|
-
tmex init [--no-interactive --install-dir <path> --host <host> --port <port> --db-path <path> --autostart <true|false> --bun-path <path>]
|
|
110500
|
-
tmex doctor [--install-dir <path>] [--json] [--bun-path <path>]
|
|
110850
|
+
tmex init [--no-interactive --install-dir <path> --host <host> --port <port> --db-path <path> --autostart <true|false> --bun-path <path> --install-deps --skip-dep-check]
|
|
110851
|
+
tmex doctor [--install-dir <path>] [--json] [--bun-path <path>] [--fix]
|
|
110501
110852
|
tmex upgrade [--version <version>] [--install-dir <path>] [--bun-path <path>]
|
|
110502
110853
|
tmex uninstall [--install-dir <path>] [--yes] [--purge]
|
|
110503
110854
|
|
|
@@ -110541,6 +110892,7 @@ Global flags:
|
|
|
110541
110892
|
"init.prompt.serviceName": "Service name (service-name)",
|
|
110542
110893
|
"init.prompt.dirExistsConfirm": "Directory {{installDir}} already exists. Continue (will not delete existing config/db)?",
|
|
110543
110894
|
"init.error.installDirNotEmpty": "Install directory is not empty: {{installDir}}. Use --force to overwrite.",
|
|
110895
|
+
"init.error.noServiceManager": "No supported service manager found (platform: {{platform}}). tmex requires systemd (Linux) or launchd (macOS).",
|
|
110544
110896
|
"init.warning.noServiceManager": "Service manager is not supported on platform {{platform}}. Files are deployed but autostart is not configured.",
|
|
110545
110897
|
"init.done": "Initialization completed.",
|
|
110546
110898
|
"init.summary.installDir": "Install dir",
|
|
@@ -110554,8 +110906,12 @@ Global flags:
|
|
|
110554
110906
|
"doctor.platform.unsupported": "Platform {{platform}} is not officially supported (only macOS and common Linux distros are guaranteed).",
|
|
110555
110907
|
"doctor.bun.ok": "Bun installed: {{version}}",
|
|
110556
110908
|
"doctor.bun.fail": "Bun check failed: {{reason}}",
|
|
110557
|
-
"doctor.tmux.ok": "tmux installed",
|
|
110558
|
-
"doctor.tmux.fail": "tmux not found (tmex requires tmux).",
|
|
110909
|
+
"doctor.tmux.ok": "tmux installed: {{version}}",
|
|
110910
|
+
"doctor.tmux.fail": "tmux not found (tmex requires tmux >= 3.0).",
|
|
110911
|
+
"doctor.tmux.versionLow": "tmux version too low: {{version}} (requires >= 3.0)",
|
|
110912
|
+
"doctor.fix.header": "Attempting to fix issues...",
|
|
110913
|
+
"doctor.fix.skip": "Skipping unfixable item: {{id}}",
|
|
110914
|
+
"doctor.fix.hint": 'Run "tmex doctor --fix" to attempt automatic installation.',
|
|
110559
110915
|
"doctor.ssh.ok": "ssh installed",
|
|
110560
110916
|
"doctor.ssh.missing": "ssh not found; SSH devices will not work.",
|
|
110561
110917
|
"doctor.installDir.exists": "Install directory exists: {{installDir}}",
|
|
@@ -110586,6 +110942,19 @@ Global flags:
|
|
|
110586
110942
|
"uninstall.done": "Uninstall completed.",
|
|
110587
110943
|
"uninstall.summary.installDir": "Install dir",
|
|
110588
110944
|
"uninstall.summary.serviceName": "Service name",
|
|
110945
|
+
"tmux.notFound": "tmux not found. tmex requires tmux >= 3.0 to operate.",
|
|
110946
|
+
"tmux.versionTooLow": "tmux version too low: current {{version}}, required >= 3.0",
|
|
110947
|
+
"deps.install.confirm": "Install {{dep}} now?",
|
|
110948
|
+
"deps.install.running": "Installing {{dep}}...",
|
|
110949
|
+
"deps.install.success": "{{dep}} installed successfully.",
|
|
110950
|
+
"deps.install.failed": "Failed to install {{dep}}.",
|
|
110951
|
+
"deps.install.manual": "Please install manually and retry.",
|
|
110952
|
+
"deps.install.sudoRequired": "This operation requires sudo.",
|
|
110953
|
+
"deps.install.sudoUnavailable": "sudo is not available. Please run as root or install sudo.",
|
|
110954
|
+
"deps.install.nonInteractive": "Missing dependency: {{dep}}. Use --install-deps to install automatically.",
|
|
110955
|
+
"deps.install.hint": "Suggested install command: {{command}}",
|
|
110956
|
+
"deps.install.brewMissing": "Homebrew not found. Install Homebrew first: https://brew.sh",
|
|
110957
|
+
"deps.install.unknownDistro": "Unable to detect Linux distribution. Please install {{dep}} manually.",
|
|
110589
110958
|
"runtime.restartRequested": "Restart requested; exiting for service manager restart.",
|
|
110590
110959
|
"runtime.started": "Service started on {{url}}",
|
|
110591
110960
|
"runtime.frontendMissing": "Frontend assets not found.",
|
|
@@ -110597,8 +110966,8 @@ Global flags:
|
|
|
110597
110966
|
"cli.help": `tmex CLI
|
|
110598
110967
|
|
|
110599
110968
|
\u7528\u6CD5\uFF1A
|
|
110600
|
-
tmex init [--no-interactive --install-dir <path> --host <host> --port <port> --db-path <path> --autostart <true|false> --bun-path <path>]
|
|
110601
|
-
tmex doctor [--install-dir <path>] [--json] [--bun-path <path>]
|
|
110969
|
+
tmex init [--no-interactive --install-dir <path> --host <host> --port <port> --db-path <path> --autostart <true|false> --bun-path <path> --install-deps --skip-dep-check]
|
|
110970
|
+
tmex doctor [--install-dir <path>] [--json] [--bun-path <path>] [--fix]
|
|
110602
110971
|
tmex upgrade [--version <version>] [--install-dir <path>] [--bun-path <path>]
|
|
110603
110972
|
tmex uninstall [--install-dir <path>] [--yes] [--purge]
|
|
110604
110973
|
|
|
@@ -110642,6 +111011,7 @@ Global flags:
|
|
|
110642
111011
|
"init.prompt.serviceName": "\u670D\u52A1\u540D\u79F0\uFF08service-name\uFF09",
|
|
110643
111012
|
"init.prompt.dirExistsConfirm": "\u76EE\u5F55 {{installDir}} \u5DF2\u5B58\u5728\uFF0C\u662F\u5426\u7EE7\u7EED\uFF08\u4E0D\u4F1A\u5220\u9664\u73B0\u6709\u914D\u7F6E\u4E0E\u6570\u636E\u5E93\uFF09\uFF1F",
|
|
110644
111013
|
"init.error.installDirNotEmpty": "\u5B89\u88C5\u76EE\u5F55\u5DF2\u5B58\u5728\u4E14\u975E\u7A7A\uFF1A{{installDir}}\u3002\u5982\u9700\u8986\u76D6\u8BF7\u52A0 --force",
|
|
111014
|
+
"init.error.noServiceManager": "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684\u670D\u52A1\u7BA1\u7406\u5668\uFF08\u5E73\u53F0\uFF1A{{platform}}\uFF09\u3002tmex \u9700\u8981 systemd\uFF08Linux\uFF09\u6216 launchd\uFF08macOS\uFF09\u3002",
|
|
110645
111015
|
"init.warning.noServiceManager": "\u5F53\u524D\u5E73\u53F0 {{platform}} \u672A\u5B9E\u73B0\u81EA\u52A8\u670D\u52A1\u5B89\u88C5\uFF0C\u5DF2\u5B8C\u6210\u6587\u4EF6\u90E8\u7F72\u3002",
|
|
110646
111016
|
"init.done": "\u521D\u59CB\u5316\u5B8C\u6210\u3002",
|
|
110647
111017
|
"init.summary.installDir": "\u5B89\u88C5\u76EE\u5F55",
|
|
@@ -110655,8 +111025,12 @@ Global flags:
|
|
|
110655
111025
|
"doctor.platform.unsupported": "\u5F53\u524D\u5E73\u53F0 {{platform}} \u975E\u5B98\u65B9\u652F\u6301\u8303\u56F4\uFF08\u4EC5\u4FDD\u8BC1 macOS \u4E0E\u5E38\u89C1 Linux \u53D1\u884C\u7248\uFF09\u3002",
|
|
110656
111026
|
"doctor.bun.ok": "Bun \u5DF2\u5B89\u88C5\uFF1A{{version}}",
|
|
110657
111027
|
"doctor.bun.fail": "Bun \u68C0\u67E5\u5931\u8D25\uFF1A{{reason}}",
|
|
110658
|
-
"doctor.tmux.ok": "tmux \u5DF2\u5B89\u88C5",
|
|
110659
|
-
"doctor.tmux.fail": "\u672A\u68C0\u6D4B\u5230 tmux\uFF08tmex \u9700\u8981 tmux \u624D\u80FD\u5DE5\u4F5C\uFF09\u3002",
|
|
111028
|
+
"doctor.tmux.ok": "tmux \u5DF2\u5B89\u88C5\uFF1A{{version}}",
|
|
111029
|
+
"doctor.tmux.fail": "\u672A\u68C0\u6D4B\u5230 tmux\uFF08tmex \u9700\u8981 tmux >= 3.0 \u624D\u80FD\u5DE5\u4F5C\uFF09\u3002",
|
|
111030
|
+
"doctor.tmux.versionLow": "tmux \u7248\u672C\u8FC7\u4F4E\uFF1A{{version}}\uFF08\u8981\u6C42 >= 3.0\uFF09",
|
|
111031
|
+
"doctor.fix.header": "\u6B63\u5728\u5C1D\u8BD5\u4FEE\u590D\u95EE\u9898...",
|
|
111032
|
+
"doctor.fix.skip": "\u8DF3\u8FC7\u65E0\u6CD5\u81EA\u52A8\u4FEE\u590D\u7684\u9879\u76EE\uFF1A{{id}}",
|
|
111033
|
+
"doctor.fix.hint": '\u8FD0\u884C "tmex doctor --fix" \u5C1D\u8BD5\u81EA\u52A8\u5B89\u88C5\u7F3A\u5931\u7684\u4F9D\u8D56\u3002',
|
|
110660
111034
|
"doctor.ssh.ok": "ssh \u5DF2\u5B89\u88C5",
|
|
110661
111035
|
"doctor.ssh.missing": "\u672A\u68C0\u6D4B\u5230 ssh\uFF0C\u8FDC\u7A0B\u8BBE\u5907\u5C06\u4E0D\u53EF\u7528\u3002",
|
|
110662
111036
|
"doctor.installDir.exists": "\u5B89\u88C5\u76EE\u5F55\u5B58\u5728\uFF1A{{installDir}}",
|
|
@@ -110687,6 +111061,19 @@ Global flags:
|
|
|
110687
111061
|
"uninstall.done": "\u5378\u8F7D\u5B8C\u6210\u3002",
|
|
110688
111062
|
"uninstall.summary.installDir": "\u5B89\u88C5\u76EE\u5F55",
|
|
110689
111063
|
"uninstall.summary.serviceName": "\u670D\u52A1\u540D\u79F0",
|
|
111064
|
+
"tmux.notFound": "\u672A\u68C0\u6D4B\u5230 tmux\u3002tmex \u9700\u8981 tmux >= 3.0 \u624D\u80FD\u5DE5\u4F5C\u3002",
|
|
111065
|
+
"tmux.versionTooLow": "tmux \u7248\u672C\u8FC7\u4F4E\uFF1A\u5F53\u524D {{version}}\uFF0C\u8981\u6C42 >= 3.0",
|
|
111066
|
+
"deps.install.confirm": "\u662F\u5426\u73B0\u5728\u5B89\u88C5 {{dep}}\uFF1F",
|
|
111067
|
+
"deps.install.running": "\u6B63\u5728\u5B89\u88C5 {{dep}}...",
|
|
111068
|
+
"deps.install.success": "{{dep}} \u5B89\u88C5\u6210\u529F\u3002",
|
|
111069
|
+
"deps.install.failed": "\u5B89\u88C5 {{dep}} \u5931\u8D25\u3002",
|
|
111070
|
+
"deps.install.manual": "\u8BF7\u624B\u52A8\u5B89\u88C5\u540E\u91CD\u8BD5\u3002",
|
|
111071
|
+
"deps.install.sudoRequired": "\u6B64\u64CD\u4F5C\u9700\u8981 sudo \u6743\u9650\u3002",
|
|
111072
|
+
"deps.install.sudoUnavailable": "sudo \u4E0D\u53EF\u7528\uFF0C\u8BF7\u4EE5 root \u8EAB\u4EFD\u6267\u884C\u6216\u5B89\u88C5 sudo\u3002",
|
|
111073
|
+
"deps.install.nonInteractive": "\u7F3A\u5C11\u4F9D\u8D56\uFF1A{{dep}}\u3002\u4F7F\u7528 --install-deps \u81EA\u52A8\u5B89\u88C5\u3002",
|
|
111074
|
+
"deps.install.hint": "\u5EFA\u8BAE\u5B89\u88C5\u547D\u4EE4\uFF1A{{command}}",
|
|
111075
|
+
"deps.install.brewMissing": "\u672A\u68C0\u6D4B\u5230 Homebrew\uFF0C\u8BF7\u5148\u5B89\u88C5 Homebrew\uFF1Ahttps://brew.sh",
|
|
111076
|
+
"deps.install.unknownDistro": "\u65E0\u6CD5\u68C0\u6D4B Linux \u53D1\u884C\u7248\uFF0C\u8BF7\u624B\u52A8\u5B89\u88C5 {{dep}}\u3002",
|
|
110690
111077
|
"runtime.restartRequested": "\u6536\u5230\u91CD\u542F\u8BF7\u6C42\uFF0C\u9000\u51FA\u5E76\u7B49\u5F85\u670D\u52A1\u7BA1\u7406\u5668\u62C9\u8D77\u3002",
|
|
110691
111078
|
"runtime.started": "\u670D\u52A1\u5DF2\u542F\u52A8\uFF1A{{url}}",
|
|
110692
111079
|
"runtime.frontendMissing": "\u672A\u627E\u5230\u524D\u7AEF\u9759\u6001\u8D44\u6E90\u3002",
|