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.
Files changed (82) hide show
  1. package/CHANGELOG.md +13 -19
  2. package/dist/cli-node.js +492 -87
  3. package/dist/runtime/server.js +431 -44
  4. package/package.json +1 -1
  5. package/resources/fe-dist/assets/{DevicePage-Cj9jwadE.js → DevicePage-kndrXVHE.js} +1 -1
  6. package/resources/fe-dist/assets/DevicesPage-CZLzOS04.js +1 -0
  7. package/resources/fe-dist/assets/{FilePage-CbHZVJbn.js → FilePage-CxVqdlbt.js} +1 -1
  8. package/resources/fe-dist/assets/{SettingsPage-CCV0NSQF.js → SettingsPage-C50JRe91.js} +1 -1
  9. package/resources/fe-dist/assets/{agent-tab-DPwxh08T.js → agent-tab-BVWxou-d.js} +1 -1
  10. package/resources/fe-dist/assets/{api-DlcFE5in.js → api-CrHrQflz.js} +1 -1
  11. package/resources/fe-dist/assets/{arc-Bzmm6y8F.js → arc-fsY_kDTa.js} +1 -1
  12. package/resources/fe-dist/assets/{architectureDiagram-3BPJPVTR-BdsN6XRe.js → architectureDiagram-3BPJPVTR-Vsg8Cd3e.js} +1 -1
  13. package/resources/fe-dist/assets/{blockDiagram-GPEHLZMM-CXdQhkqo.js → blockDiagram-GPEHLZMM-G7sC3DZO.js} +1 -1
  14. package/resources/fe-dist/assets/{c4Diagram-AAUBKEIU-CE_W2_pV.js → c4Diagram-AAUBKEIU-C1AfLOva.js} +1 -1
  15. package/resources/fe-dist/assets/{card-B_sl9KIo.js → card-CXa-2u8i.js} +1 -1
  16. package/resources/fe-dist/assets/channel-DS4kWkSb.js +1 -0
  17. package/resources/fe-dist/assets/{chunk-2J33WTMH-BAdEIJQO.js → chunk-2J33WTMH-C1p02eGI.js} +1 -1
  18. package/resources/fe-dist/assets/{chunk-4BX2VUAB-BZ0yj21c.js → chunk-4BX2VUAB-C8n2FURp.js} +1 -1
  19. package/resources/fe-dist/assets/{chunk-55IACEB6-BknLtkSo.js → chunk-55IACEB6-Da0nuNCD.js} +1 -1
  20. package/resources/fe-dist/assets/{chunk-727SXJPM-CxVON9n5.js → chunk-727SXJPM-C1TXyDEt.js} +1 -1
  21. package/resources/fe-dist/assets/{chunk-AQP2D5EJ-CLqOK2pR.js → chunk-AQP2D5EJ-CnRKlbXo.js} +1 -1
  22. package/resources/fe-dist/assets/{chunk-FMBD7UC4-Dt5Vot-R.js → chunk-FMBD7UC4-B8HGrJ3t.js} +1 -1
  23. package/resources/fe-dist/assets/{chunk-ND2GUHAM-t9HYlb8C.js → chunk-ND2GUHAM-CcN2Ou-o.js} +1 -1
  24. package/resources/fe-dist/assets/{chunk-QZHKN3VN-DZReNtLB.js → chunk-QZHKN3VN-DfWJ_tl5.js} +1 -1
  25. package/resources/fe-dist/assets/classDiagram-4FO5ZUOK-BfsrnUi9.js +1 -0
  26. package/resources/fe-dist/assets/classDiagram-v2-Q7XG4LA2-BfsrnUi9.js +1 -0
  27. package/resources/fe-dist/assets/{copy-Z9Fsj1r-.js → copy-BveLgJe5.js} +1 -1
  28. package/resources/fe-dist/assets/{cose-bilkent-S5V4N54A-BCTtGF2n.js → cose-bilkent-S5V4N54A-BkmsTzwU.js} +1 -1
  29. package/resources/fe-dist/assets/{dagre-BM42HDAG-BQ48EqSj.js → dagre-BM42HDAG-pGgtc4EE.js} +1 -1
  30. package/resources/fe-dist/assets/{diagram-2AECGRRQ-BXjt2moR.js → diagram-2AECGRRQ-DJxixZvm.js} +1 -1
  31. package/resources/fe-dist/assets/{diagram-5GNKFQAL-B2bvNTQO.js → diagram-5GNKFQAL-2ITViev7.js} +1 -1
  32. package/resources/fe-dist/assets/{diagram-KO2AKTUF-DLHWfbBH.js → diagram-KO2AKTUF-EMcadaeo.js} +1 -1
  33. package/resources/fe-dist/assets/{diagram-LMA3HP47-BCFT3Bur.js → diagram-LMA3HP47-w3sLU7zY.js} +1 -1
  34. package/resources/fe-dist/assets/{diagram-OG6HWLK6-bNZtxUJ2.js → diagram-OG6HWLK6-B4KGMQr7.js} +1 -1
  35. package/resources/fe-dist/assets/en_US-Chxeay8F.js +1 -0
  36. package/resources/fe-dist/assets/{erDiagram-TEJ5UH35-KoAzrx4j.js → erDiagram-TEJ5UH35-CB0P-Wz7.js} +1 -1
  37. package/resources/fe-dist/assets/{files-tab-DdBDTjfs.js → files-tab-lNenDPFy.js} +1 -1
  38. package/resources/fe-dist/assets/{flowDiagram-I6XJVG4X-C6wGExWt.js → flowDiagram-I6XJVG4X-CmBc7GAX.js} +1 -1
  39. package/resources/fe-dist/assets/{ganttDiagram-6RSMTGT7-BIWybjes.js → ganttDiagram-6RSMTGT7-CHNf7S_K.js} +1 -1
  40. package/resources/fe-dist/assets/{gitGraphDiagram-PVQCEYII-CD6tz24l.js → gitGraphDiagram-PVQCEYII-CabspIF1.js} +1 -1
  41. package/resources/fe-dist/assets/{index-CUCrFB_J.js → index-BQbq6q_-.js} +1 -1
  42. package/resources/fe-dist/assets/{index-CwH-l50P.js → index-DOaZjm8K.js} +79 -79
  43. package/resources/fe-dist/assets/index-DaOR3c0u.css +1 -0
  44. package/resources/fe-dist/assets/{infoDiagram-5YYISTIA-CrI-qlYw.js → infoDiagram-5YYISTIA-ny6wqvHH.js} +1 -1
  45. package/resources/fe-dist/assets/{ishikawaDiagram-YF4QCWOH-D9v5anxN.js → ishikawaDiagram-YF4QCWOH-EFCdGVsV.js} +1 -1
  46. package/resources/fe-dist/assets/ja_JP-BI-C8I9X.js +1 -0
  47. package/resources/fe-dist/assets/{journeyDiagram-JHISSGLW-BH38CiJ0.js → journeyDiagram-JHISSGLW-Cvi8jO9a.js} +1 -1
  48. package/resources/fe-dist/assets/{kanban-definition-UN3LZRKU-CKZ3_oXD.js → kanban-definition-UN3LZRKU-nKej8tSo.js} +1 -1
  49. package/resources/fe-dist/assets/{linear-C_oE01xA.js → linear-leOPyu29.js} +1 -1
  50. package/resources/fe-dist/assets/{markdown-preview-BtNbNwlP.js → markdown-preview-rqUSs5w8.js} +3 -3
  51. package/resources/fe-dist/assets/{mermaid.core-4dbvlhht.js → mermaid.core-QvhJBi8f.js} +5 -5
  52. package/resources/fe-dist/assets/{mindmap-definition-RKZ34NQL-C5o4mnnX.js → mindmap-definition-RKZ34NQL-xWje0B_-.js} +1 -1
  53. package/resources/fe-dist/assets/{pieDiagram-4H26LBE5-2ss3HotB.js → pieDiagram-4H26LBE5-DT1i53ec.js} +1 -1
  54. package/resources/fe-dist/assets/{quadrantDiagram-W4KKPZXB-Bolcfx55.js → quadrantDiagram-W4KKPZXB-C1zbS4Tx.js} +1 -1
  55. package/resources/fe-dist/assets/{requirementDiagram-4Y6WPE33-B-atSHRR.js → requirementDiagram-4Y6WPE33-By_eNRll.js} +1 -1
  56. package/resources/fe-dist/assets/{sankeyDiagram-5OEKKPKP-ByynRcAV.js → sankeyDiagram-5OEKKPKP-CG7jC05N.js} +1 -1
  57. package/resources/fe-dist/assets/{send-D0P5wgcD.js → send-CcFyyX2G.js} +1 -1
  58. package/resources/fe-dist/assets/{sequenceDiagram-3UESZ5HK-CNC9IxV4.js → sequenceDiagram-3UESZ5HK-C9yK_EKN.js} +1 -1
  59. package/resources/fe-dist/assets/{stateDiagram-AJRCARHV-CqzYDImp.js → stateDiagram-AJRCARHV-B-ROUwGP.js} +1 -1
  60. package/resources/fe-dist/assets/stateDiagram-v2-BHNVJYJU-iopOcale.js +1 -0
  61. package/resources/fe-dist/assets/{terminal-settings-panel-cjw9P_wY.js → terminal-settings-panel-CNwWqOMV.js} +1 -1
  62. package/resources/fe-dist/assets/{timeline-definition-PNZ67QCA-C38KIECs.js → timeline-definition-PNZ67QCA-yMM8VB4U.js} +1 -1
  63. package/resources/fe-dist/assets/{transfer-toast-5tb-zYhi.js → transfer-toast-mQs0hgyg.js} +1 -1
  64. package/resources/fe-dist/assets/{triangle-alert-CQzql6mY.js → triangle-alert-DMp7kMmJ.js} +1 -1
  65. package/resources/fe-dist/assets/{vennDiagram-CIIHVFJN-BJudKfzJ.js → vennDiagram-CIIHVFJN-CE08llZ3.js} +1 -1
  66. package/resources/fe-dist/assets/{wardley-L42UT6IY-B6p_luMy.js → wardley-L42UT6IY-BKLGCmLJ.js} +1 -1
  67. package/resources/fe-dist/assets/{wardleyDiagram-YWT4CUSO-DZJeOiWQ.js → wardleyDiagram-YWT4CUSO-BsjwfO3P.js} +1 -1
  68. package/resources/fe-dist/assets/{xychartDiagram-2RQKCTM6-DOMCute2.js → xychartDiagram-2RQKCTM6-Bhz6AI7w.js} +1 -1
  69. package/resources/fe-dist/assets/{zap-DWNtdoic.js → zap-DPwn8lbv.js} +1 -1
  70. package/resources/fe-dist/assets/zh_CN-DE-BaQ3P.js +1 -0
  71. package/resources/fe-dist/index.html +2 -2
  72. package/resources/gateway-drizzle/0011_stormy_sauron.sql +1 -0
  73. package/resources/gateway-drizzle/meta/_journal.json +7 -0
  74. package/resources/fe-dist/assets/DevicesPage-BbypaGC7.js +0 -1
  75. package/resources/fe-dist/assets/channel-CuapxAWT.js +0 -1
  76. package/resources/fe-dist/assets/classDiagram-4FO5ZUOK-C0k136Ud.js +0 -1
  77. package/resources/fe-dist/assets/classDiagram-v2-Q7XG4LA2-C0k136Ud.js +0 -1
  78. package/resources/fe-dist/assets/en_US-B07wSHDj.js +0 -1
  79. package/resources/fe-dist/assets/index-D-q7dOhH.css +0 -1
  80. package/resources/fe-dist/assets/ja_JP-DjF6Lrmx.js +0 -1
  81. package/resources/fe-dist/assets/stateDiagram-v2-BHNVJYJU-C3azxyWE.js +0 -1
  82. package/resources/fe-dist/assets/zh_CN-D10j4J8Y.js +0 -1
@@ -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 Notification",
22712
- bellDescription: "Window {{window}} \xB7 Pane {{pane}}",
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 \u63D0\u9192",
23703
- bellDescription: "\u7A97\u53E3 {{window}} \xB7 Pane {{pane}}",
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\u901A\u77E5",
24694
- bellDescription: "\u30A6\u30A3\u30F3\u30C9\u30A6 {{window}} \xB7 \u30DA\u30A4\u30F3 {{pane}}",
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 = name24 ? ["new-window", "-t", this.sessionName, "-n", name24] : ["new-window", "-t", this.sessionName];
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", homedir(), "-s", this.sessionName]);
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 = name24 ? ["new-window", "-t", this.sessionName, "-n", name24] : ["new-window", "-t", this.sessionName];
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.remoteHomeDir, "-s", this.sessionName]);
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
- onBlockEnd: () => {
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 stopReader = await this.openReaderChannel(`exec ${quoteShellArg(this.tmuxBin)} -C attach-session -t ${quoteShellArg(this.sessionName)}`, {
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 = stopReader;
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
- stream.end();
101051
- stream.close();
101052
- stream.destroy();
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.13.0") {
106426
- base = "0.13.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",