tmex-cli 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22669,6 +22669,8 @@ var I18N_RESOURCES = {
22669
22669
  disconnect: "Disconnect",
22670
22670
  disconnected: "Disconnected",
22671
22671
  connecting: "Connecting...",
22672
+ dragHandle: "Drag to reorder device",
22673
+ reorderFailed: "Failed to reorder devices",
22672
22674
  deleteConfirm: "Delete this device?",
22673
22675
  deleteDescription: 'Device "{{name}}" will be permanently removed. This action cannot be undone.',
22674
22676
  deleteSuccess: "Device deleted",
@@ -23010,6 +23012,8 @@ Time: {{time}}`,
23010
23012
  time: "Time",
23011
23013
  directLink: "Direct Link",
23012
23014
  message: "Message",
23015
+ paneTitle: "Title",
23016
+ process: "Process",
23013
23017
  telegramBell: {
23014
23018
  title: "\uD83D\uDD14 Bell from {{siteName}}: {{terminalTopbarLabel}}",
23015
23019
  viewLink: "Click to view",
@@ -23028,7 +23032,8 @@ Time: {{time}}`,
23028
23032
  summaryTriggered: 'Watch "{{name}}": {{summary}}',
23029
23033
  unconfirmedSuffix: " (model unavailable, not LLM-confirmed)",
23030
23034
  modelUnavailable: 'Watch "{{name}}" model call failed: {{message}}',
23031
- ruleError: 'Watch "{{name}}" failed {{count}} times in a row and has been disabled: {{message}}'
23035
+ ruleError: 'Watch "{{name}}" failed {{count}} times in a row and has been disabled: {{message}}',
23036
+ paneGone: 'Watch "{{name}}" pane ({{paneId}}) was destroyed; the rule has been removed'
23032
23037
  }
23033
23038
  },
23034
23039
  sidebar: {
@@ -23085,9 +23090,13 @@ Time: {{time}}`,
23085
23090
  retry: "Retry",
23086
23091
  scrollToBottom: "Scroll to bottom"
23087
23092
  },
23093
+ welcome: {
23094
+ title: "New Agent chat",
23095
+ subtitle: "Describe your task to start working in the selected terminal"
23096
+ },
23088
23097
  session: {
23089
23098
  none: "No session selected",
23090
- new: "New session",
23099
+ new: "New agent session",
23091
23100
  switch: "Switch session",
23092
23101
  selectPaneHint: "Select a pane in the Panes tab to start a session",
23093
23102
  noSessions: "No sessions yet",
@@ -23147,6 +23156,8 @@ Time: {{time}}`,
23147
23156
  closePaneConfirmTitle: "Close this pane?",
23148
23157
  closeConfirmDesc: 'Processes running in "{{name}}" will be terminated. This action cannot be undone.',
23149
23158
  menu: "Window actions",
23159
+ dragHandle: "Drag to reorder window",
23160
+ dragHandlePane: "Drag to reorder pane",
23150
23161
  rename: "Rename window",
23151
23162
  renamePlaceholder: "Enter a name",
23152
23163
  renameDesc: "The custom name overrides the title set by the terminal and is kept until the gateway restarts.",
@@ -23359,6 +23370,8 @@ Time: {{time}}`,
23359
23370
  disconnect: "\u65AD\u5F00",
23360
23371
  disconnected: "\u5DF2\u65AD\u5F00",
23361
23372
  connecting: "\u8FDE\u63A5\u4E2D...",
23373
+ dragHandle: "\u62D6\u52A8\u4EE5\u8C03\u6574\u8BBE\u5907\u987A\u5E8F",
23374
+ reorderFailed: "\u8BBE\u5907\u6392\u5E8F\u5931\u8D25",
23362
23375
  deleteConfirm: "\u5220\u9664\u6B64\u8BBE\u5907\uFF1F",
23363
23376
  deleteDescription: '\u8BBE\u5907 "{{name}}" \u5C06\u88AB\u6C38\u4E45\u79FB\u9664\uFF0C\u6B64\u64CD\u4F5C\u65E0\u6CD5\u64A4\u9500\u3002',
23364
23377
  deleteSuccess: "\u8BBE\u5907\u5DF2\u5220\u9664",
@@ -23700,6 +23713,8 @@ Bot\uFF1A{{botName}}
23700
23713
  time: "\u65F6\u95F4",
23701
23714
  directLink: "\u76F4\u8FBE",
23702
23715
  message: "\u4FE1\u606F",
23716
+ paneTitle: "\u6807\u9898",
23717
+ process: "\u8FDB\u7A0B",
23703
23718
  telegramBell: {
23704
23719
  title: "\uD83D\uDD14 \u6765\u81EA {{siteName}} \u7684 Bell\uFF1A{{terminalTopbarLabel}}",
23705
23720
  viewLink: "\u70B9\u51FB\u67E5\u770B",
@@ -23718,7 +23733,8 @@ Bot\uFF1A{{botName}}
23718
23733
  summaryTriggered: "\u76D1\u63A7\u300C{{name}}\u300D\uFF1A{{summary}}",
23719
23734
  unconfirmedSuffix: "\uFF08\u6A21\u578B\u4E0D\u53EF\u7528\uFF0C\u672A\u7ECF LLM \u4E8C\u6B21\u786E\u8BA4\uFF09",
23720
23735
  modelUnavailable: "\u76D1\u63A7\u300C{{name}}\u300D\u6A21\u578B\u8C03\u7528\u5931\u8D25\uFF1A{{message}}",
23721
- ruleError: "\u76D1\u63A7\u300C{{name}}\u300D\u8FDE\u7EED\u5931\u8D25 {{count}} \u6B21\uFF0C\u5DF2\u81EA\u52A8\u505C\u7528\uFF1A{{message}}"
23736
+ ruleError: "\u76D1\u63A7\u300C{{name}}\u300D\u8FDE\u7EED\u5931\u8D25 {{count}} \u6B21\uFF0C\u5DF2\u81EA\u52A8\u505C\u7528\uFF1A{{message}}",
23737
+ paneGone: "\u76D1\u63A7\u300C{{name}}\u300D\u7684 Pane\uFF08{{paneId}}\uFF09\u5DF2\u9500\u6BC1\uFF0C\u89C4\u5219\u5DF2\u81EA\u52A8\u5220\u9664"
23722
23738
  }
23723
23739
  },
23724
23740
  sidebar: {
@@ -23775,9 +23791,13 @@ Bot\uFF1A{{botName}}
23775
23791
  retry: "\u91CD\u8BD5",
23776
23792
  scrollToBottom: "\u56DE\u5230\u5E95\u90E8"
23777
23793
  },
23794
+ welcome: {
23795
+ title: "\u65B0\u5EFA Agent \u5BF9\u8BDD",
23796
+ subtitle: "\u5411 Agent \u63CF\u8FF0\u4F60\u7684\u9700\u6C42\uFF0C\u5F00\u59CB\u5728\u6240\u9009\u7EC8\u7AEF\u4E2D\u534F\u4F5C"
23797
+ },
23778
23798
  session: {
23779
23799
  none: "\u672A\u9009\u62E9\u4F1A\u8BDD",
23780
- new: "\u65B0\u5EFA\u4F1A\u8BDD",
23800
+ new: "\u65B0\u5EFA Agent \u4F1A\u8BDD",
23781
23801
  switch: "\u5207\u6362\u4F1A\u8BDD",
23782
23802
  selectPaneHint: "\u8BF7\u5728 Panes \u6807\u7B7E\u4E2D\u9009\u62E9\u4E00\u4E2A pane \u6765\u5F00\u542F\u4F1A\u8BDD",
23783
23803
  noSessions: "\u6682\u65E0\u4F1A\u8BDD",
@@ -23837,6 +23857,8 @@ Bot\uFF1A{{botName}}
23837
23857
  closePaneConfirmTitle: "\u5173\u95ED\u6B64\u9762\u677F\uFF1F",
23838
23858
  closeConfirmDesc: '"{{name}}" \u4E2D\u8FD0\u884C\u7684\u8FDB\u7A0B\u5C06\u88AB\u7EC8\u6B62\uFF0C\u6B64\u64CD\u4F5C\u65E0\u6CD5\u64A4\u9500\u3002',
23839
23859
  menu: "\u7A97\u53E3\u64CD\u4F5C",
23860
+ dragHandle: "\u62D6\u52A8\u4EE5\u8C03\u6574\u7A97\u53E3\u987A\u5E8F",
23861
+ dragHandlePane: "\u62D6\u52A8\u4EE5\u8C03\u6574 pane \u987A\u5E8F",
23840
23862
  rename: "\u91CD\u547D\u540D\u7A97\u53E3",
23841
23863
  renamePlaceholder: "\u8F93\u5165\u540D\u79F0",
23842
23864
  renameDesc: "\u81EA\u5B9A\u4E49\u540D\u79F0\u4F1A\u8986\u76D6\u7EC8\u7AEF\u8BBE\u7F6E\u7684\u6807\u9898\uFF0C\u5E76\u4FDD\u7559\u81F3 gateway \u91CD\u542F\u3002",
@@ -24049,6 +24071,8 @@ Bot\uFF1A{{botName}}
24049
24071
  disconnect: "\u5207\u65AD",
24050
24072
  disconnected: "\u5207\u65AD\u6E08\u307F",
24051
24073
  connecting: "\u63A5\u7D9A\u4E2D...",
24074
+ dragHandle: "\u30C9\u30E9\u30C3\u30B0\u3057\u3066\u30C7\u30D0\u30A4\u30B9\u3092\u4E26\u3079\u66FF\u3048",
24075
+ reorderFailed: "\u30C7\u30D0\u30A4\u30B9\u306E\u4E26\u3079\u66FF\u3048\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
24052
24076
  deleteConfirm: "\u3053\u306E\u30C7\u30D0\u30A4\u30B9\u3092\u524A\u9664\u3057\u307E\u3059\u304B\uFF1F",
24053
24077
  deleteDescription: "\u30C7\u30D0\u30A4\u30B9\u300C{{name}}\u300D\u306F\u5B8C\u5168\u306B\u524A\u9664\u3055\u308C\u307E\u3059\u3002\u3053\u306E\u64CD\u4F5C\u306F\u53D6\u308A\u6D88\u305B\u307E\u305B\u3093\u3002",
24054
24078
  deleteSuccess: "\u30C7\u30D0\u30A4\u30B9\u3092\u524A\u9664\u3057\u307E\u3057\u305F",
@@ -24390,6 +24414,8 @@ Bot\uFF1A{{botName}}
24390
24414
  time: "\u6642\u9593",
24391
24415
  directLink: "\u76F4\u63A5\u30EA\u30F3\u30AF",
24392
24416
  message: "\u30E1\u30C3\u30BB\u30FC\u30B8",
24417
+ paneTitle: "\u30BF\u30A4\u30C8\u30EB",
24418
+ process: "\u30D7\u30ED\u30BB\u30B9",
24393
24419
  telegramBell: {
24394
24420
  title: "\uD83D\uDD14 {{siteName}} \u304B\u3089\u306E\u30D9\u30EB\uFF1A{{terminalTopbarLabel}}",
24395
24421
  viewLink: "\u8868\u793A",
@@ -24408,7 +24434,8 @@ Bot\uFF1A{{botName}}
24408
24434
  summaryTriggered: "Watch\u300C{{name}}\u300D\uFF1A{{summary}}",
24409
24435
  unconfirmedSuffix: "\uFF08\u30E2\u30C7\u30EB\u5229\u7528\u4E0D\u53EF\u306E\u305F\u3081 LLM \u672A\u78BA\u8A8D\uFF09",
24410
24436
  modelUnavailable: "Watch\u300C{{name}}\u300D\u306E\u30E2\u30C7\u30EB\u547C\u3073\u51FA\u3057\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF1A{{message}}",
24411
- ruleError: "Watch\u300C{{name}}\u300D\u304C {{count}} \u56DE\u9023\u7D9A\u3067\u5931\u6557\u3057\u305F\u305F\u3081\u81EA\u52D5\u505C\u6B62\u3057\u307E\u3057\u305F\uFF1A{{message}}"
24437
+ ruleError: "Watch\u300C{{name}}\u300D\u304C {{count}} \u56DE\u9023\u7D9A\u3067\u5931\u6557\u3057\u305F\u305F\u3081\u81EA\u52D5\u505C\u6B62\u3057\u307E\u3057\u305F\uFF1A{{message}}",
24438
+ paneGone: "Watch\u300C{{name}}\u300D\u306E\u30DA\u30A4\u30F3\uFF08{{paneId}}\uFF09\u304C\u7834\u68C4\u3055\u308C\u305F\u305F\u3081\u3001\u30EB\u30FC\u30EB\u3092\u524A\u9664\u3057\u307E\u3057\u305F"
24412
24439
  }
24413
24440
  },
24414
24441
  sidebar: {
@@ -24465,9 +24492,13 @@ Bot\uFF1A{{botName}}
24465
24492
  retry: "\u518D\u8A66\u884C",
24466
24493
  scrollToBottom: "\u6700\u4E0B\u90E8\u3078"
24467
24494
  },
24495
+ welcome: {
24496
+ title: "\u65B0\u3057\u3044 Agent \u30C1\u30E3\u30C3\u30C8",
24497
+ subtitle: "\u30BF\u30B9\u30AF\u3092\u5165\u529B\u3057\u3066\u3001\u9078\u629E\u3057\u305F\u7AEF\u672B\u3067\u306E\u4F5C\u696D\u3092\u59CB\u3081\u307E\u3057\u3087\u3046"
24498
+ },
24468
24499
  session: {
24469
24500
  none: "\u30BB\u30C3\u30B7\u30E7\u30F3\u672A\u9078\u629E",
24470
- new: "\u65B0\u898F\u30BB\u30C3\u30B7\u30E7\u30F3",
24501
+ new: "\u65B0\u898F\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30BB\u30C3\u30B7\u30E7\u30F3",
24471
24502
  switch: "\u30BB\u30C3\u30B7\u30E7\u30F3\u3092\u5207\u308A\u66FF\u3048",
24472
24503
  selectPaneHint: "Panes \u30BF\u30D6\u3067\u30DA\u30A4\u30F3\u3092\u9078\u629E\u3057\u3066\u30BB\u30C3\u30B7\u30E7\u30F3\u3092\u958B\u59CB\u3057\u3066\u304F\u3060\u3055\u3044",
24473
24504
  noSessions: "\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u3042\u308A\u307E\u305B\u3093",
@@ -24527,6 +24558,8 @@ Bot\uFF1A{{botName}}
24527
24558
  closePaneConfirmTitle: "\u3053\u306E\u30DA\u30A4\u30F3\u3092\u9589\u3058\u307E\u3059\u304B\uFF1F",
24528
24559
  closeConfirmDesc: '"{{name}}" \u3067\u5B9F\u884C\u4E2D\u306E\u30D7\u30ED\u30BB\u30B9\u306F\u7D42\u4E86\u3055\u308C\u307E\u3059\u3002\u3053\u306E\u64CD\u4F5C\u306F\u53D6\u308A\u6D88\u305B\u307E\u305B\u3093\u3002',
24529
24560
  menu: "\u30A6\u30A3\u30F3\u30C9\u30A6\u64CD\u4F5C",
24561
+ dragHandle: "\u30C9\u30E9\u30C3\u30B0\u3057\u3066\u30A6\u30A3\u30F3\u30C9\u30A6\u3092\u4E26\u3079\u66FF\u3048",
24562
+ dragHandlePane: "\u30C9\u30E9\u30C3\u30B0\u3057\u3066\u30DA\u30A4\u30F3\u3092\u4E26\u3079\u66FF\u3048",
24530
24563
  rename: "\u30A6\u30A3\u30F3\u30C9\u30A6\u540D\u3092\u5909\u66F4",
24531
24564
  renamePlaceholder: "\u540D\u524D\u3092\u5165\u529B",
24532
24565
  renameDesc: "\u30AB\u30B9\u30BF\u30E0\u540D\u306F\u30BF\u30FC\u30DF\u30CA\u30EB\u304C\u8A2D\u5B9A\u3057\u305F\u30BF\u30A4\u30C8\u30EB\u3092\u4E0A\u66F8\u304D\u3057\u3001\u30B2\u30FC\u30C8\u30A6\u30A7\u30A4\u304C\u518D\u8D77\u52D5\u3059\u308B\u307E\u3067\u4FDD\u6301\u3055\u308C\u307E\u3059\u3002",
@@ -24692,6 +24725,8 @@ __export(exports_ws_borsh, {
24692
24725
  KIND_TMUX_SET_WINDOW_STYLE: () => KIND_TMUX_SET_WINDOW_STYLE,
24693
24726
  KIND_TMUX_SELECT_WINDOW: () => KIND_TMUX_SELECT_WINDOW,
24694
24727
  KIND_TMUX_SELECT: () => KIND_TMUX_SELECT,
24728
+ KIND_TMUX_REORDER_WINDOWS: () => KIND_TMUX_REORDER_WINDOWS,
24729
+ KIND_TMUX_REORDER_PANES: () => KIND_TMUX_REORDER_PANES,
24695
24730
  KIND_TMUX_RENAME_WINDOW: () => KIND_TMUX_RENAME_WINDOW,
24696
24731
  KIND_TMUX_EVENT: () => KIND_TMUX_EVENT,
24697
24732
  KIND_TMUX_CREATE_WINDOW: () => KIND_TMUX_CREATE_WINDOW,
@@ -24780,6 +24815,8 @@ var KIND_TMUX_EVENT = 519;
24780
24815
  var KIND_STATE_SNAPSHOT = 520;
24781
24816
  var KIND_STATE_SNAPSHOT_DIFF = 521;
24782
24817
  var KIND_TMUX_SET_WINDOW_STYLE = 522;
24818
+ var KIND_TMUX_REORDER_WINDOWS = 523;
24819
+ var KIND_TMUX_REORDER_PANES = 524;
24783
24820
  var KIND_TERM_INPUT = 769;
24784
24821
  var KIND_TERM_PASTE = 770;
24785
24822
  var KIND_TERM_RESIZE = 771;
@@ -24814,6 +24851,8 @@ var VALID_KINDS = new Set([
24814
24851
  KIND_STATE_SNAPSHOT,
24815
24852
  KIND_STATE_SNAPSHOT_DIFF,
24816
24853
  KIND_TMUX_SET_WINDOW_STYLE,
24854
+ KIND_TMUX_REORDER_WINDOWS,
24855
+ KIND_TMUX_REORDER_PANES,
24817
24856
  KIND_TERM_INPUT,
24818
24857
  KIND_TERM_PASTE,
24819
24858
  KIND_TERM_RESIZE,
@@ -24853,6 +24892,8 @@ function kindToString(kind) {
24853
24892
  [KIND_STATE_SNAPSHOT]: "STATE_SNAPSHOT",
24854
24893
  [KIND_STATE_SNAPSHOT_DIFF]: "STATE_SNAPSHOT_DIFF",
24855
24894
  [KIND_TMUX_SET_WINDOW_STYLE]: "TMUX_SET_WINDOW_STYLE",
24895
+ [KIND_TMUX_REORDER_WINDOWS]: "TMUX_REORDER_WINDOWS",
24896
+ [KIND_TMUX_REORDER_PANES]: "TMUX_REORDER_PANES",
24856
24897
  [KIND_TERM_INPUT]: "TERM_INPUT",
24857
24898
  [KIND_TERM_PASTE]: "TERM_PASTE",
24858
24899
  [KIND_TERM_RESIZE]: "TERM_RESIZE",
@@ -24939,6 +24980,8 @@ __export(exports_schema, {
24939
24980
  TmuxSetWindowStyleSchema: () => TmuxSetWindowStyleSchema,
24940
24981
  TmuxSelectWindowSchema: () => TmuxSelectWindowSchema,
24941
24982
  TmuxSelectSchema: () => TmuxSelectSchema,
24983
+ TmuxReorderWindowsSchema: () => TmuxReorderWindowsSchema,
24984
+ TmuxReorderPanesSchema: () => TmuxReorderPanesSchema,
24942
24985
  TmuxRenameWindowSchema: () => TmuxRenameWindowSchema,
24943
24986
  TmuxEventSchema: () => TmuxEventSchema,
24944
24987
  TmuxCreateWindowSchema: () => TmuxCreateWindowSchema,
@@ -25070,6 +25113,15 @@ var TmuxSetWindowStyleSchema = import_zorsh.b.struct({
25070
25113
  deviceId: import_zorsh.b.string(),
25071
25114
  style: import_zorsh.b.string()
25072
25115
  });
25116
+ var TmuxReorderWindowsSchema = import_zorsh.b.struct({
25117
+ deviceId: import_zorsh.b.string(),
25118
+ windowIds: import_zorsh.b.vec(import_zorsh.b.string())
25119
+ });
25120
+ var TmuxReorderPanesSchema = import_zorsh.b.struct({
25121
+ deviceId: import_zorsh.b.string(),
25122
+ windowId: import_zorsh.b.string(),
25123
+ paneIds: import_zorsh.b.vec(import_zorsh.b.string())
25124
+ });
25073
25125
  var TmuxEventSchema = import_zorsh.b.struct({
25074
25126
  deviceId: import_zorsh.b.string(),
25075
25127
  eventType: import_zorsh.b.u8(),
@@ -32145,6 +32197,7 @@ __export(exports_schema2, {
32145
32197
  siteSettings: () => siteSettings,
32146
32198
  llmProviders: () => llmProviders,
32147
32199
  devices: () => devices,
32200
+ deviceTreeOrder: () => deviceTreeOrder,
32148
32201
  deviceRuntimeStatus: () => deviceRuntimeStatus,
32149
32202
  agentSettings: () => agentSettings,
32150
32203
  agentSessions: () => agentSessions,
@@ -32184,6 +32237,7 @@ var devices = sqliteTable("devices", {
32184
32237
  passwordEnc: text("password_enc"),
32185
32238
  privateKeyEnc: text("private_key_enc"),
32186
32239
  privateKeyPassphraseEnc: text("private_key_passphrase_enc"),
32240
+ sortOrder: integer("sort_order").notNull().default(0),
32187
32241
  createdAt: text("created_at").notNull(),
32188
32242
  updatedAt: text("updated_at").notNull()
32189
32243
  }, (table) => [
@@ -32334,6 +32388,12 @@ var watchRuleState = sqliteTable("watch_rule_state", {
32334
32388
  lastError: text("last_error"),
32335
32389
  modelUnavailableNotified: integer("model_unavailable_notified", { mode: "boolean" }).notNull().default(false)
32336
32390
  });
32391
+ var deviceTreeOrder = sqliteTable("device_tree_order", {
32392
+ deviceId: text("device_id").primaryKey().references(() => devices.id, { onDelete: "cascade" }),
32393
+ windows: text("windows", { mode: "json" }).$type().notNull().default([]),
32394
+ panes: text("panes", { mode: "json" }).$type().notNull().default({}),
32395
+ updatedAt: text("updated_at").notNull()
32396
+ });
32337
32397
  var telegramBotChats = sqliteTable("telegram_bot_chats", {
32338
32398
  id: text("id").primaryKey(),
32339
32399
  botId: text("bot_id").notNull().references(() => telegramBots.id, { onDelete: "cascade" }),
@@ -32388,6 +32448,7 @@ function toDevice(row) {
32388
32448
  passwordEnc: optional(row.passwordEnc),
32389
32449
  privateKeyEnc: optional(row.privateKeyEnc),
32390
32450
  privateKeyPassphraseEnc: optional(row.privateKeyPassphraseEnc),
32451
+ sortOrder: row.sortOrder,
32391
32452
  createdAt: row.createdAt,
32392
32453
  updatedAt: row.updatedAt
32393
32454
  };
@@ -32466,6 +32527,8 @@ function ensureSiteSettingsInitialized() {
32466
32527
  function createDevice(device) {
32467
32528
  const orm = getDb();
32468
32529
  orm.transaction((tx) => {
32530
+ const maxRow = tx.select({ value: max(devices.sortOrder) }).from(devices).get();
32531
+ const nextSortOrder = (maxRow?.value ?? -1) + 1;
32469
32532
  tx.insert(devices).values({
32470
32533
  id: device.id,
32471
32534
  name: device.name,
@@ -32479,6 +32542,7 @@ function createDevice(device) {
32479
32542
  passwordEnc: device.passwordEnc ?? null,
32480
32543
  privateKeyEnc: device.privateKeyEnc ?? null,
32481
32544
  privateKeyPassphraseEnc: device.privateKeyPassphraseEnc ?? null,
32545
+ sortOrder: nextSortOrder,
32482
32546
  createdAt: device.createdAt,
32483
32547
  updatedAt: device.updatedAt
32484
32548
  }).run();
@@ -32501,7 +32565,16 @@ function getDeviceById(id) {
32501
32565
  }
32502
32566
  function getAllDevices() {
32503
32567
  const orm = getDb();
32504
- return orm.select().from(devices).orderBy(desc(devices.createdAt)).all().map(toDevice);
32568
+ return orm.select().from(devices).orderBy(asc(devices.sortOrder), desc(devices.createdAt)).all().map(toDevice);
32569
+ }
32570
+ function reorderDevices(orderedIds) {
32571
+ const orm = getDb();
32572
+ const now = new Date().toISOString();
32573
+ orm.transaction((tx) => {
32574
+ orderedIds.forEach((id, index) => {
32575
+ tx.update(devices).set({ sortOrder: index, updatedAt: now }).where(eq(devices.id, id)).run();
32576
+ });
32577
+ });
32505
32578
  }
32506
32579
  function updateDevice(id, updates) {
32507
32580
  const orm = getDb();
@@ -32544,6 +32617,36 @@ function deleteDevice(id) {
32544
32617
  const orm = getDb();
32545
32618
  orm.delete(devices).where(eq(devices.id, id)).run();
32546
32619
  }
32620
+ function getDeviceTreeOrder(deviceId) {
32621
+ const orm = getDb();
32622
+ const row = orm.select().from(deviceTreeOrder).where(eq(deviceTreeOrder.deviceId, deviceId)).get();
32623
+ if (!row) {
32624
+ return { deviceId, windows: [], panes: {} };
32625
+ }
32626
+ return {
32627
+ deviceId: row.deviceId,
32628
+ windows: Array.isArray(row.windows) ? row.windows : [],
32629
+ panes: row.panes && typeof row.panes === "object" ? row.panes : {}
32630
+ };
32631
+ }
32632
+ function setWindowOrder(deviceId, windowIds) {
32633
+ const orm = getDb();
32634
+ const now = new Date().toISOString();
32635
+ orm.insert(deviceTreeOrder).values({ deviceId, windows: windowIds, panes: {}, updatedAt: now }).onConflictDoUpdate({
32636
+ target: deviceTreeOrder.deviceId,
32637
+ set: { windows: windowIds, updatedAt: now }
32638
+ }).run();
32639
+ }
32640
+ function setPaneOrder(deviceId, windowId, paneIds) {
32641
+ const current = getDeviceTreeOrder(deviceId);
32642
+ const nextPanes = { ...current.panes, [windowId]: paneIds };
32643
+ const orm = getDb();
32644
+ const now = new Date().toISOString();
32645
+ orm.insert(deviceTreeOrder).values({ deviceId, windows: current.windows, panes: nextPanes, updatedAt: now }).onConflictDoUpdate({
32646
+ target: deviceTreeOrder.deviceId,
32647
+ set: { panes: nextPanes, updatedAt: now }
32648
+ }).run();
32649
+ }
32547
32650
  function getDeviceRuntimeStatus(deviceId) {
32548
32651
  const orm = getDb();
32549
32652
  const row = orm.select().from(deviceRuntimeStatus).where(eq(deviceRuntimeStatus.deviceId, deviceId)).get();
@@ -79450,7 +79553,7 @@ async function standardizePrompt({
79450
79553
  function wrapGatewayError(error51) {
79451
79554
  if (!GatewayAuthenticationError.isInstance(error51))
79452
79555
  return error51;
79453
- const isProductionEnv = (process == null ? undefined : "production") === "production";
79556
+ const isProductionEnv = (process == null ? undefined : "development") === "production";
79454
79557
  const moreInfoURL = "https://ai-sdk.dev/unauthenticated-ai-gateway";
79455
79558
  if (isProductionEnv) {
79456
79559
  return new AISDKError({
@@ -86215,9 +86318,6 @@ _a21 = symbol21;
86215
86318
  var defaultDownload2 = createDownload();
86216
86319
 
86217
86320
  // ../../apps/gateway/src/events/index.ts
86218
- function sanitizeMarkdownV2(input) {
86219
- return input.replace(/([_\*\[\]()~`>#+\-=|{}.!\\])/g, "\\$1");
86220
- }
86221
86321
  function escapeTelegramHtmlText(input) {
86222
86322
  return input.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
86223
86323
  }
@@ -86367,7 +86467,7 @@ class EventNotifier {
86367
86467
  return;
86368
86468
  }
86369
86469
  const message = this.formatTelegramMessage(event, settings);
86370
- await telegramService.sendToAuthorizedChats({ text: message });
86470
+ await telegramService.sendToAuthorizedChats({ text: message, parseMode: "HTML" });
86371
86471
  }
86372
86472
  buildTerminalTopbarLabel(event) {
86373
86473
  const windowLabel = typeof event.tmux?.windowIndex === "number" ? `${event.tmux.windowIndex}` : event.tmux?.windowId ?? "?";
@@ -86378,12 +86478,23 @@ class EventNotifier {
86378
86478
  device: event.device.name
86379
86479
  });
86380
86480
  }
86481
+ buildPaneMetaLines(event) {
86482
+ const lines = [];
86483
+ if (event.tmux?.paneTitle) {
86484
+ lines.push(`${escapeTelegramHtmlText(t2("notification.paneTitle"))}\uFF1A${escapeTelegramHtmlText(event.tmux.paneTitle)}`);
86485
+ }
86486
+ if (event.tmux?.paneCurrentCommand) {
86487
+ lines.push(`${escapeTelegramHtmlText(t2("notification.process"))}\uFF1A${escapeTelegramHtmlText(event.tmux.paneCurrentCommand)}`);
86488
+ }
86489
+ return lines;
86490
+ }
86381
86491
  formatTelegramBellMessage(event) {
86382
86492
  const title = t2("notification.telegramBell.title", {
86383
86493
  siteName: event.site.name,
86384
86494
  terminalTopbarLabel: this.buildTerminalTopbarLabel(event)
86385
86495
  });
86386
86496
  const lines = [escapeTelegramHtmlText(title)];
86497
+ lines.push(...this.buildPaneMetaLines(event));
86387
86498
  const paneUrl = normalizeHttpUrl(buildPaneUrl(event));
86388
86499
  if (paneUrl) {
86389
86500
  const tgSafePaneUrl = encodePercentForTelegramUrl(paneUrl);
@@ -86402,6 +86513,7 @@ class EventNotifier {
86402
86513
  if (body) {
86403
86514
  lines.push(escapeTelegramHtmlText(body));
86404
86515
  }
86516
+ lines.push(...this.buildPaneMetaLines(event));
86405
86517
  const paneUrl = normalizeHttpUrl(buildPaneUrl(event));
86406
86518
  const topbarLabel = this.buildTerminalTopbarLabel(event);
86407
86519
  const footer = `from ${event.site.name}: ${topbarLabel}`;
@@ -86431,23 +86543,26 @@ class EventNotifier {
86431
86543
  watch_model_unavailable: "\uD83D\uDC41\uFE0F",
86432
86544
  watch_rule_error: "\uD83D\uDC41\uFE0F"
86433
86545
  };
86434
- const paneUrl = buildPaneUrl(event);
86546
+ const esc2 = escapeTelegramHtmlText;
86435
86547
  const eventTypeLabel = t2(`notification.eventType.${event.eventType}`);
86436
86548
  const lines = [
86437
- `${emojiMap[event.eventType] ?? "\uD83D\uDCE2"} ${eventTypeLabel}`,
86438
- `${t2("notification.site")}\uFF1A${event.site.name}`,
86439
- `${t2("notification.time")}\uFF1A${new Date(event.timestamp).toLocaleString(toBCP47(settings.language))}`,
86440
- `${t2("notification.device")}\uFF1A${event.device.name} (${event.device.type})`,
86441
- event.tmux?.windowIndex !== undefined ? `${t2("notification.window")}\uFF1A${event.tmux.windowIndex} (${event.tmux.windowId ?? "-"})` : event.tmux?.windowId ? `${t2("notification.window")}\uFF1A${event.tmux.windowId}` : `${t2("notification.window")}\uFF1A-`,
86442
- event.tmux?.paneIndex !== undefined ? `${t2("notification.pane")}\uFF1A${event.tmux.paneIndex} (${event.tmux.paneId ?? "-"})` : event.tmux?.paneId ? `${t2("notification.pane")}\uFF1A${event.tmux.paneId}` : `${t2("notification.pane")}\uFF1A-`
86549
+ `${emojiMap[event.eventType] ?? "\uD83D\uDCE2"} ${esc2(eventTypeLabel)}`,
86550
+ `${esc2(t2("notification.site"))}\uFF1A${esc2(event.site.name)}`,
86551
+ `${esc2(t2("notification.time"))}\uFF1A${esc2(new Date(event.timestamp).toLocaleString(toBCP47(settings.language)))}`,
86552
+ `${esc2(t2("notification.device"))}\uFF1A${esc2(event.device.name)} (${esc2(event.device.type)})`,
86553
+ event.tmux?.windowIndex !== undefined ? `${esc2(t2("notification.window"))}\uFF1A${event.tmux.windowIndex} (${esc2(event.tmux.windowId ?? "-")})` : event.tmux?.windowId ? `${esc2(t2("notification.window"))}\uFF1A${esc2(event.tmux.windowId)}` : `${esc2(t2("notification.window"))}\uFF1A-`,
86554
+ event.tmux?.paneIndex !== undefined ? `${esc2(t2("notification.pane"))}\uFF1A${event.tmux.paneIndex} (${esc2(event.tmux.paneId ?? "-")})` : event.tmux?.paneId ? `${esc2(t2("notification.pane"))}\uFF1A${esc2(event.tmux.paneId)}` : `${esc2(t2("notification.pane"))}\uFF1A-`
86443
86555
  ];
86444
- if (paneUrl) {
86445
- lines.push(`${t2("notification.directLink")}\uFF1A${paneUrl}`);
86446
- }
86556
+ lines.push(...this.buildPaneMetaLines(event));
86447
86557
  if (event.payload?.message && typeof event.payload.message === "string") {
86448
- lines.push(`${t2("notification.message")}\uFF1A${event.payload.message}`);
86558
+ lines.push(`${esc2(t2("notification.message"))}\uFF1A${esc2(event.payload.message)}`);
86559
+ }
86560
+ const paneUrl = normalizeHttpUrl(buildPaneUrl(event));
86561
+ if (paneUrl) {
86562
+ const tgSafePaneUrl = encodePercentForTelegramUrl(paneUrl);
86563
+ lines.push("", `<a href="${escapeTelegramHtmlAttribute(tgSafePaneUrl)}">${esc2(t2("notification.directLink"))}</a>`);
86449
86564
  }
86450
- return lines.map((line) => sanitizeMarkdownV2(line)).join(`
86565
+ return lines.join(`
86451
86566
  `);
86452
86567
  }
86453
86568
  async generateHmac(secret, message) {
@@ -97172,7 +97287,7 @@ class LocalExternalTmuxConnection {
97172
97287
  "-t",
97173
97288
  this.sessionName,
97174
97289
  "-F",
97175
- "#{pane_id}\t#{window_id}\t#{pane_index}\t#{pane_title}\t#{pane_active}\t#{pane_width}\t#{pane_height}\t#{window_active}"
97290
+ "#{pane_id}\t#{window_id}\t#{pane_index}\t#{pane_title}\t#{pane_active}\t#{pane_width}\t#{pane_height}\t#{window_active}\t#{pane_current_command}"
97176
97291
  ])
97177
97292
  ]);
97178
97293
  if (sessionRes.exitCode !== 0 || windowsRes.exitCode !== 0 || panesRes.exitCode !== 0) {
@@ -97244,7 +97359,7 @@ ${panesRes.stderr}`;
97244
97359
  if (!line.trim()) {
97245
97360
  continue;
97246
97361
  }
97247
- const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw] = line.split("\t");
97362
+ const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw, currentCommandRaw] = line.split("\t");
97248
97363
  if (!paneId || !windowId) {
97249
97364
  continue;
97250
97365
  }
@@ -97256,6 +97371,7 @@ ${panesRes.stderr}`;
97256
97371
  windowId,
97257
97372
  index: Number.isNaN(index) ? 0 : index,
97258
97373
  title: this.pendingPaneTitles.get(paneId) ?? (titleRaw?.trim() ? titleRaw : undefined),
97374
+ currentCommand: currentCommandRaw?.trim() ? currentCommandRaw.trim() : undefined,
97259
97375
  active: activeRaw === "1",
97260
97376
  width: Number.isNaN(width) ? 0 : width,
97261
97377
  height: Number.isNaN(height) ? 0 : height
@@ -97776,6 +97892,19 @@ function splitSnapshotFields(line, fieldCount) {
97776
97892
  parts.at(-1) ?? ""
97777
97893
  ];
97778
97894
  }
97895
+ if (fieldCount === 9) {
97896
+ return [
97897
+ parts[0] ?? "",
97898
+ parts[1] ?? "",
97899
+ parts[2] ?? "",
97900
+ parts.slice(3, -5).join(SNAPSHOT_FIELD_SEPARATOR),
97901
+ parts.at(-5) ?? "",
97902
+ parts.at(-4) ?? "",
97903
+ parts.at(-3) ?? "",
97904
+ parts.at(-2) ?? "",
97905
+ parts.at(-1) ?? ""
97906
+ ];
97907
+ }
97779
97908
  return parts;
97780
97909
  }
97781
97910
 
@@ -98405,7 +98534,7 @@ class SshExternalTmuxConnection {
98405
98534
  "-t",
98406
98535
  this.sessionName,
98407
98536
  "-F",
98408
- "#{pane_id}|#{window_id}|#{pane_index}|#{pane_title}|#{pane_active}|#{pane_width}|#{pane_height}|#{window_active}"
98537
+ "#{pane_id}|#{window_id}|#{pane_index}|#{pane_title}|#{pane_active}|#{pane_width}|#{pane_height}|#{window_active}|#{pane_current_command}"
98409
98538
  ])
98410
98539
  ]);
98411
98540
  if (sessionRes.exitCode !== 0 || windowsRes.exitCode !== 0 || panesRes.exitCode !== 0) {
@@ -98477,7 +98606,7 @@ ${panesRes.stderr}`;
98477
98606
  if (!line.trim()) {
98478
98607
  continue;
98479
98608
  }
98480
- const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw] = splitSnapshotFields(line, 8);
98609
+ const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw, currentCommandRaw] = splitSnapshotFields(line, 9);
98481
98610
  if (!paneId || !windowId) {
98482
98611
  continue;
98483
98612
  }
@@ -98489,6 +98618,7 @@ ${panesRes.stderr}`;
98489
98618
  windowId,
98490
98619
  index: Number.isNaN(index) ? 0 : index,
98491
98620
  title: this.pendingPaneTitles.get(paneId) ?? (titleRaw?.trim() ? titleRaw : undefined),
98621
+ currentCommand: currentCommandRaw?.trim() ? currentCommandRaw.trim() : undefined,
98492
98622
  active: activeRaw === "1",
98493
98623
  width: Number.isNaN(width) ? 0 : width,
98494
98624
  height: Number.isNaN(height) ? 0 : height
@@ -101292,7 +101422,9 @@ function resolvePaneContext(options) {
101292
101422
  paneId: targetPane?.id ?? bellPaneId,
101293
101423
  windowIndex: targetWindow?.index,
101294
101424
  paneIndex: targetPane?.index,
101295
- paneUrl
101425
+ paneUrl,
101426
+ paneTitle: targetPane?.title,
101427
+ paneCurrentCommand: targetPane?.currentCommand
101296
101428
  };
101297
101429
  }
101298
101430
 
@@ -101324,7 +101456,9 @@ var defaultDeps2 = {
101324
101456
  paneId: bell.paneId,
101325
101457
  windowIndex: bell.windowIndex,
101326
101458
  paneIndex: bell.paneIndex,
101327
- paneUrl: bell.paneUrl
101459
+ paneUrl: bell.paneUrl,
101460
+ paneTitle: bell.paneTitle,
101461
+ paneCurrentCommand: bell.paneCurrentCommand
101328
101462
  },
101329
101463
  payload: {
101330
101464
  message: t2("notification.eventType.terminal_bell")
@@ -101350,7 +101484,9 @@ var defaultDeps2 = {
101350
101484
  paneId: notification.paneId,
101351
101485
  windowIndex: notification.windowIndex,
101352
101486
  paneIndex: notification.paneIndex,
101353
- paneUrl: notification.paneUrl
101487
+ paneUrl: notification.paneUrl,
101488
+ paneTitle: notification.paneTitle,
101489
+ paneCurrentCommand: notification.paneCurrentCommand
101354
101490
  },
101355
101491
  payload: {
101356
101492
  source: notification.source,
@@ -102706,6 +102842,7 @@ var defaultDeps3 = {
102706
102842
  getState: getWatchRuleState,
102707
102843
  upsertState: upsertWatchRuleState,
102708
102844
  updateRule: updateWatchRule,
102845
+ deleteRule: deleteWatchRule,
102709
102846
  acquireRuntime: (deviceId) => tmuxRuntimeRegistry.acquire(deviceId),
102710
102847
  releaseRuntime: (deviceId, runtime) => tmuxRuntimeRegistry.release(deviceId, runtime),
102711
102848
  resolveModel: resolveLanguageModel2,
@@ -102999,7 +103136,12 @@ class WatchService {
102999
103136
  if (!this.rules.has(rule.id)) {
103000
103137
  return;
103001
103138
  }
103002
- await this.recordRuleError(rule, toErrorMessage3(error51), now2);
103139
+ const message = toErrorMessage3(error51);
103140
+ if (isTargetMissingMessage(message)) {
103141
+ await this.handlePaneGone(rule);
103142
+ return;
103143
+ }
103144
+ await this.recordRuleError(rule, message, now2);
103003
103145
  return;
103004
103146
  }
103005
103147
  if (!this.rules.has(rule.id)) {
@@ -103151,6 +103293,22 @@ class WatchService {
103151
103293
  await this.disableRuleForErrors(rule, errors3, message);
103152
103294
  }
103153
103295
  }
103296
+ async handlePaneGone(rule) {
103297
+ this.deps.deleteRule(rule.id);
103298
+ await this.teardownRule(rule.id);
103299
+ this.samples.delete(rule.id);
103300
+ const message = t2("notification.watch.paneGone", {
103301
+ name: rule.name,
103302
+ paneId: rule.paneId
103303
+ });
103304
+ await this.safeNotify("watch_rule_error", rule, {
103305
+ message,
103306
+ ruleId: rule.id,
103307
+ ruleName: rule.name,
103308
+ paneGone: true
103309
+ }, { paneId: rule.paneId });
103310
+ this.broadcastSafe(rule, exports_ws_borsh.WATCH_EVENT_RULE_ERROR, { message });
103311
+ }
103154
103312
  async disableRuleForErrors(rule, errorCount, detail) {
103155
103313
  this.deps.updateRule(rule.id, { enabled: false });
103156
103314
  await this.teardownRule(rule.id);
@@ -103258,7 +103416,9 @@ class WatchService {
103258
103416
  windowIndex: paneContext.windowIndex,
103259
103417
  paneId: paneContext.paneId ?? rule.paneId,
103260
103418
  paneIndex: paneContext.paneIndex,
103261
- paneUrl: paneContext.paneUrl
103419
+ paneUrl: paneContext.paneUrl,
103420
+ paneTitle: paneContext.paneTitle,
103421
+ paneCurrentCommand: paneContext.paneCurrentCommand
103262
103422
  },
103263
103423
  payload
103264
103424
  });
@@ -103906,6 +104066,9 @@ function handleApiRequest(req, _server) {
103906
104066
  if (path === "/api/devices" && req.method === "POST") {
103907
104067
  return handleCreateDevice(req);
103908
104068
  }
104069
+ if (path === "/api/devices/order" && req.method === "PUT") {
104070
+ return handleReorderDevices(req);
104071
+ }
103909
104072
  if (path.match(/^\/api\/devices\/[^/]+$/) && req.method === "GET") {
103910
104073
  return handleGetDevice(path.split("/")[3]);
103911
104074
  }
@@ -104029,12 +104192,13 @@ async function handleCreateDevice(req) {
104029
104192
  passwordEnc: body.password ? await encrypt(body.password) : undefined,
104030
104193
  privateKeyEnc: body.privateKey ? await encrypt(body.privateKey) : undefined,
104031
104194
  privateKeyPassphraseEnc: body.privateKeyPassphrase ? await encrypt(body.privateKeyPassphrase) : undefined,
104195
+ sortOrder: 0,
104032
104196
  createdAt: now2,
104033
104197
  updatedAt: now2
104034
104198
  };
104035
104199
  createDevice(device);
104036
104200
  await pushSupervisor.upsert(device.id);
104037
- return json7({ device }, 201);
104201
+ return json7({ device: getDeviceById(device.id) ?? device }, 201);
104038
104202
  }
104039
104203
  async function handleUpdateDevice(req, id) {
104040
104204
  const existing = getDeviceById(id);
@@ -104071,6 +104235,14 @@ async function handleUpdateDevice(req, id) {
104071
104235
  const device = getDeviceById(id);
104072
104236
  return json7({ device });
104073
104237
  }
104238
+ async function handleReorderDevices(req) {
104239
+ const body = await req.json();
104240
+ if (!Array.isArray(body.deviceIds) || body.deviceIds.some((id) => typeof id !== "string")) {
104241
+ return json7({ error: t2("apiError.invalidRequest") }, 400);
104242
+ }
104243
+ reorderDevices(body.deviceIds);
104244
+ return json7({ devices: getAllDevices().map(enrichDeviceWithRuntime) });
104245
+ }
104074
104246
  async function handleDeleteDevice(id) {
104075
104247
  const existing = getDeviceById(id);
104076
104248
  if (!existing) {
@@ -104933,6 +105105,45 @@ class SwitchBarrier {
104933
105105
  }
104934
105106
  var switchBarrier = new SwitchBarrier;
104935
105107
 
105108
+ // ../../apps/gateway/src/ws/overlay-utils.ts
105109
+ function orderBySaved(items, getId, savedIds) {
105110
+ if (savedIds.length === 0)
105111
+ return items;
105112
+ const byId = new Map(items.map((item) => [getId(item), item]));
105113
+ const used = new Set;
105114
+ const result = [];
105115
+ for (const id of savedIds) {
105116
+ const item = byId.get(id);
105117
+ if (item && !used.has(id)) {
105118
+ result.push(item);
105119
+ used.add(id);
105120
+ }
105121
+ }
105122
+ for (const item of items) {
105123
+ if (!used.has(getId(item)))
105124
+ result.push(item);
105125
+ }
105126
+ return result;
105127
+ }
105128
+ function applyDeviceTreeOverlay(payload, order) {
105129
+ if (!payload.session)
105130
+ return payload;
105131
+ const hasWindowOrder = order.windows.length > 0;
105132
+ const hasPaneOrder = Object.keys(order.panes).length > 0;
105133
+ if (!hasWindowOrder && !hasPaneOrder)
105134
+ return payload;
105135
+ const orderedWindows = orderBySaved(payload.session.windows, (w) => w.id, order.windows).map((window2) => {
105136
+ const savedPaneOrder = order.panes[window2.id];
105137
+ if (!savedPaneOrder || savedPaneOrder.length === 0)
105138
+ return window2;
105139
+ return { ...window2, panes: orderBySaved(window2.panes, (p) => p.id, savedPaneOrder) };
105140
+ });
105141
+ return {
105142
+ ...payload,
105143
+ session: { ...payload.session, windows: orderedWindows }
105144
+ };
105145
+ }
105146
+
104936
105147
  // ../../apps/gateway/src/ws/index.ts
104937
105148
  var defaultDeps5 = {
104938
105149
  acquireRuntime: async (deviceId) => tmuxRuntimeRegistry.acquire(deviceId),
@@ -105183,6 +105394,16 @@ class WebSocketServer {
105183
105394
  this.handleSetWindowStyle(decoded.deviceId, decoded.style);
105184
105395
  return;
105185
105396
  }
105397
+ case exports_ws_borsh.KIND_TMUX_REORDER_WINDOWS: {
105398
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxReorderWindowsSchema, payload);
105399
+ this.handleReorderWindows(decoded.deviceId, decoded.windowIds);
105400
+ return;
105401
+ }
105402
+ case exports_ws_borsh.KIND_TMUX_REORDER_PANES: {
105403
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxReorderPanesSchema, payload);
105404
+ this.handleReorderPanes(decoded.deviceId, decoded.windowId, decoded.paneIds);
105405
+ return;
105406
+ }
105186
105407
  case exports_ws_borsh.KIND_TERM_INPUT: {
105187
105408
  const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TermInputSchema, payload);
105188
105409
  if (decoded.isComposing)
@@ -105321,7 +105542,7 @@ class WebSocketServer {
105321
105542
  });
105322
105543
  this.sendEnvelope(ws, exports_ws_borsh.KIND_DEVICE_CONNECTED, connectedPayload);
105323
105544
  if (entry.lastSnapshot) {
105324
- const snapshotBytes = exports_ws_borsh.encodeStateSnapshot(this.applyWindowCustomNames(entry.lastSnapshot));
105545
+ const snapshotBytes = this.encodeSnapshotWithOverlays(entry.lastSnapshot);
105325
105546
  this.sendChunked(ws, exports_ws_borsh.KIND_STATE_SNAPSHOT, snapshotBytes);
105326
105547
  } else {
105327
105548
  entry.runtime.requestSnapshot();
@@ -105445,6 +105666,20 @@ class WebSocketServer {
105445
105666
  return;
105446
105667
  entry.runtime.setWindowStyle(style);
105447
105668
  }
105669
+ handleReorderWindows(deviceId, windowIds) {
105670
+ setWindowOrder(deviceId, windowIds);
105671
+ const entry = this.connections.get(deviceId);
105672
+ if (!entry?.lastSnapshot)
105673
+ return;
105674
+ this.sendSnapshotToClients(entry, entry.lastSnapshot);
105675
+ }
105676
+ handleReorderPanes(deviceId, windowId, paneIds) {
105677
+ setPaneOrder(deviceId, windowId, paneIds);
105678
+ const entry = this.connections.get(deviceId);
105679
+ if (!entry?.lastSnapshot)
105680
+ return;
105681
+ this.sendSnapshotToClients(entry, entry.lastSnapshot);
105682
+ }
105448
105683
  applyWindowCustomNames(payload) {
105449
105684
  const names = this.windowCustomNames.get(payload.deviceId);
105450
105685
  if (!names?.size || !payload.session)
@@ -105466,8 +105701,12 @@ class WebSocketServer {
105466
105701
  }
105467
105702
  };
105468
105703
  }
105704
+ encodeSnapshotWithOverlays(payload) {
105705
+ const ordered = applyDeviceTreeOverlay(payload, getDeviceTreeOrder(payload.deviceId));
105706
+ return exports_ws_borsh.encodeStateSnapshot(this.applyWindowCustomNames(ordered));
105707
+ }
105469
105708
  sendSnapshotToClients(entry, payload) {
105470
- const payloadBytes = exports_ws_borsh.encodeStateSnapshot(this.applyWindowCustomNames(payload));
105709
+ const payloadBytes = this.encodeSnapshotWithOverlays(payload);
105471
105710
  for (const client of entry.clients) {
105472
105711
  this.sendChunked(client, exports_ws_borsh.KIND_STATE_SNAPSHOT, payloadBytes);
105473
105712
  }