tmex-cli 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: {
@@ -23087,7 +23092,7 @@ Time: {{time}}`,
23087
23092
  },
23088
23093
  session: {
23089
23094
  none: "No session selected",
23090
- new: "New session",
23095
+ new: "New agent session",
23091
23096
  switch: "Switch session",
23092
23097
  selectPaneHint: "Select a pane in the Panes tab to start a session",
23093
23098
  noSessions: "No sessions yet",
@@ -23147,6 +23152,8 @@ Time: {{time}}`,
23147
23152
  closePaneConfirmTitle: "Close this pane?",
23148
23153
  closeConfirmDesc: 'Processes running in "{{name}}" will be terminated. This action cannot be undone.',
23149
23154
  menu: "Window actions",
23155
+ dragHandle: "Drag to reorder window",
23156
+ dragHandlePane: "Drag to reorder pane",
23150
23157
  rename: "Rename window",
23151
23158
  renamePlaceholder: "Enter a name",
23152
23159
  renameDesc: "The custom name overrides the title set by the terminal and is kept until the gateway restarts.",
@@ -23359,6 +23366,8 @@ Time: {{time}}`,
23359
23366
  disconnect: "\u65AD\u5F00",
23360
23367
  disconnected: "\u5DF2\u65AD\u5F00",
23361
23368
  connecting: "\u8FDE\u63A5\u4E2D...",
23369
+ dragHandle: "\u62D6\u52A8\u4EE5\u8C03\u6574\u8BBE\u5907\u987A\u5E8F",
23370
+ reorderFailed: "\u8BBE\u5907\u6392\u5E8F\u5931\u8D25",
23362
23371
  deleteConfirm: "\u5220\u9664\u6B64\u8BBE\u5907\uFF1F",
23363
23372
  deleteDescription: '\u8BBE\u5907 "{{name}}" \u5C06\u88AB\u6C38\u4E45\u79FB\u9664\uFF0C\u6B64\u64CD\u4F5C\u65E0\u6CD5\u64A4\u9500\u3002',
23364
23373
  deleteSuccess: "\u8BBE\u5907\u5DF2\u5220\u9664",
@@ -23700,6 +23709,8 @@ Bot\uFF1A{{botName}}
23700
23709
  time: "\u65F6\u95F4",
23701
23710
  directLink: "\u76F4\u8FBE",
23702
23711
  message: "\u4FE1\u606F",
23712
+ paneTitle: "\u6807\u9898",
23713
+ process: "\u8FDB\u7A0B",
23703
23714
  telegramBell: {
23704
23715
  title: "\uD83D\uDD14 \u6765\u81EA {{siteName}} \u7684 Bell\uFF1A{{terminalTopbarLabel}}",
23705
23716
  viewLink: "\u70B9\u51FB\u67E5\u770B",
@@ -23718,7 +23729,8 @@ Bot\uFF1A{{botName}}
23718
23729
  summaryTriggered: "\u76D1\u63A7\u300C{{name}}\u300D\uFF1A{{summary}}",
23719
23730
  unconfirmedSuffix: "\uFF08\u6A21\u578B\u4E0D\u53EF\u7528\uFF0C\u672A\u7ECF LLM \u4E8C\u6B21\u786E\u8BA4\uFF09",
23720
23731
  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}}"
23732
+ ruleError: "\u76D1\u63A7\u300C{{name}}\u300D\u8FDE\u7EED\u5931\u8D25 {{count}} \u6B21\uFF0C\u5DF2\u81EA\u52A8\u505C\u7528\uFF1A{{message}}",
23733
+ paneGone: "\u76D1\u63A7\u300C{{name}}\u300D\u7684 Pane\uFF08{{paneId}}\uFF09\u5DF2\u9500\u6BC1\uFF0C\u89C4\u5219\u5DF2\u81EA\u52A8\u5220\u9664"
23722
23734
  }
23723
23735
  },
23724
23736
  sidebar: {
@@ -23777,7 +23789,7 @@ Bot\uFF1A{{botName}}
23777
23789
  },
23778
23790
  session: {
23779
23791
  none: "\u672A\u9009\u62E9\u4F1A\u8BDD",
23780
- new: "\u65B0\u5EFA\u4F1A\u8BDD",
23792
+ new: "\u65B0\u5EFA Agent \u4F1A\u8BDD",
23781
23793
  switch: "\u5207\u6362\u4F1A\u8BDD",
23782
23794
  selectPaneHint: "\u8BF7\u5728 Panes \u6807\u7B7E\u4E2D\u9009\u62E9\u4E00\u4E2A pane \u6765\u5F00\u542F\u4F1A\u8BDD",
23783
23795
  noSessions: "\u6682\u65E0\u4F1A\u8BDD",
@@ -23837,6 +23849,8 @@ Bot\uFF1A{{botName}}
23837
23849
  closePaneConfirmTitle: "\u5173\u95ED\u6B64\u9762\u677F\uFF1F",
23838
23850
  closeConfirmDesc: '"{{name}}" \u4E2D\u8FD0\u884C\u7684\u8FDB\u7A0B\u5C06\u88AB\u7EC8\u6B62\uFF0C\u6B64\u64CD\u4F5C\u65E0\u6CD5\u64A4\u9500\u3002',
23839
23851
  menu: "\u7A97\u53E3\u64CD\u4F5C",
23852
+ dragHandle: "\u62D6\u52A8\u4EE5\u8C03\u6574\u7A97\u53E3\u987A\u5E8F",
23853
+ dragHandlePane: "\u62D6\u52A8\u4EE5\u8C03\u6574 pane \u987A\u5E8F",
23840
23854
  rename: "\u91CD\u547D\u540D\u7A97\u53E3",
23841
23855
  renamePlaceholder: "\u8F93\u5165\u540D\u79F0",
23842
23856
  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 +24063,8 @@ Bot\uFF1A{{botName}}
24049
24063
  disconnect: "\u5207\u65AD",
24050
24064
  disconnected: "\u5207\u65AD\u6E08\u307F",
24051
24065
  connecting: "\u63A5\u7D9A\u4E2D...",
24066
+ dragHandle: "\u30C9\u30E9\u30C3\u30B0\u3057\u3066\u30C7\u30D0\u30A4\u30B9\u3092\u4E26\u3079\u66FF\u3048",
24067
+ reorderFailed: "\u30C7\u30D0\u30A4\u30B9\u306E\u4E26\u3079\u66FF\u3048\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
24052
24068
  deleteConfirm: "\u3053\u306E\u30C7\u30D0\u30A4\u30B9\u3092\u524A\u9664\u3057\u307E\u3059\u304B\uFF1F",
24053
24069
  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
24070
  deleteSuccess: "\u30C7\u30D0\u30A4\u30B9\u3092\u524A\u9664\u3057\u307E\u3057\u305F",
@@ -24390,6 +24406,8 @@ Bot\uFF1A{{botName}}
24390
24406
  time: "\u6642\u9593",
24391
24407
  directLink: "\u76F4\u63A5\u30EA\u30F3\u30AF",
24392
24408
  message: "\u30E1\u30C3\u30BB\u30FC\u30B8",
24409
+ paneTitle: "\u30BF\u30A4\u30C8\u30EB",
24410
+ process: "\u30D7\u30ED\u30BB\u30B9",
24393
24411
  telegramBell: {
24394
24412
  title: "\uD83D\uDD14 {{siteName}} \u304B\u3089\u306E\u30D9\u30EB\uFF1A{{terminalTopbarLabel}}",
24395
24413
  viewLink: "\u8868\u793A",
@@ -24408,7 +24426,8 @@ Bot\uFF1A{{botName}}
24408
24426
  summaryTriggered: "Watch\u300C{{name}}\u300D\uFF1A{{summary}}",
24409
24427
  unconfirmedSuffix: "\uFF08\u30E2\u30C7\u30EB\u5229\u7528\u4E0D\u53EF\u306E\u305F\u3081 LLM \u672A\u78BA\u8A8D\uFF09",
24410
24428
  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}}"
24429
+ 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}}",
24430
+ 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
24431
  }
24413
24432
  },
24414
24433
  sidebar: {
@@ -24467,7 +24486,7 @@ Bot\uFF1A{{botName}}
24467
24486
  },
24468
24487
  session: {
24469
24488
  none: "\u30BB\u30C3\u30B7\u30E7\u30F3\u672A\u9078\u629E",
24470
- new: "\u65B0\u898F\u30BB\u30C3\u30B7\u30E7\u30F3",
24489
+ new: "\u65B0\u898F\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30BB\u30C3\u30B7\u30E7\u30F3",
24471
24490
  switch: "\u30BB\u30C3\u30B7\u30E7\u30F3\u3092\u5207\u308A\u66FF\u3048",
24472
24491
  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
24492
  noSessions: "\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u3042\u308A\u307E\u305B\u3093",
@@ -24527,6 +24546,8 @@ Bot\uFF1A{{botName}}
24527
24546
  closePaneConfirmTitle: "\u3053\u306E\u30DA\u30A4\u30F3\u3092\u9589\u3058\u307E\u3059\u304B\uFF1F",
24528
24547
  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
24548
  menu: "\u30A6\u30A3\u30F3\u30C9\u30A6\u64CD\u4F5C",
24549
+ dragHandle: "\u30C9\u30E9\u30C3\u30B0\u3057\u3066\u30A6\u30A3\u30F3\u30C9\u30A6\u3092\u4E26\u3079\u66FF\u3048",
24550
+ dragHandlePane: "\u30C9\u30E9\u30C3\u30B0\u3057\u3066\u30DA\u30A4\u30F3\u3092\u4E26\u3079\u66FF\u3048",
24530
24551
  rename: "\u30A6\u30A3\u30F3\u30C9\u30A6\u540D\u3092\u5909\u66F4",
24531
24552
  renamePlaceholder: "\u540D\u524D\u3092\u5165\u529B",
24532
24553
  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 +24713,8 @@ __export(exports_ws_borsh, {
24692
24713
  KIND_TMUX_SET_WINDOW_STYLE: () => KIND_TMUX_SET_WINDOW_STYLE,
24693
24714
  KIND_TMUX_SELECT_WINDOW: () => KIND_TMUX_SELECT_WINDOW,
24694
24715
  KIND_TMUX_SELECT: () => KIND_TMUX_SELECT,
24716
+ KIND_TMUX_REORDER_WINDOWS: () => KIND_TMUX_REORDER_WINDOWS,
24717
+ KIND_TMUX_REORDER_PANES: () => KIND_TMUX_REORDER_PANES,
24695
24718
  KIND_TMUX_RENAME_WINDOW: () => KIND_TMUX_RENAME_WINDOW,
24696
24719
  KIND_TMUX_EVENT: () => KIND_TMUX_EVENT,
24697
24720
  KIND_TMUX_CREATE_WINDOW: () => KIND_TMUX_CREATE_WINDOW,
@@ -24780,6 +24803,8 @@ var KIND_TMUX_EVENT = 519;
24780
24803
  var KIND_STATE_SNAPSHOT = 520;
24781
24804
  var KIND_STATE_SNAPSHOT_DIFF = 521;
24782
24805
  var KIND_TMUX_SET_WINDOW_STYLE = 522;
24806
+ var KIND_TMUX_REORDER_WINDOWS = 523;
24807
+ var KIND_TMUX_REORDER_PANES = 524;
24783
24808
  var KIND_TERM_INPUT = 769;
24784
24809
  var KIND_TERM_PASTE = 770;
24785
24810
  var KIND_TERM_RESIZE = 771;
@@ -24814,6 +24839,8 @@ var VALID_KINDS = new Set([
24814
24839
  KIND_STATE_SNAPSHOT,
24815
24840
  KIND_STATE_SNAPSHOT_DIFF,
24816
24841
  KIND_TMUX_SET_WINDOW_STYLE,
24842
+ KIND_TMUX_REORDER_WINDOWS,
24843
+ KIND_TMUX_REORDER_PANES,
24817
24844
  KIND_TERM_INPUT,
24818
24845
  KIND_TERM_PASTE,
24819
24846
  KIND_TERM_RESIZE,
@@ -24853,6 +24880,8 @@ function kindToString(kind) {
24853
24880
  [KIND_STATE_SNAPSHOT]: "STATE_SNAPSHOT",
24854
24881
  [KIND_STATE_SNAPSHOT_DIFF]: "STATE_SNAPSHOT_DIFF",
24855
24882
  [KIND_TMUX_SET_WINDOW_STYLE]: "TMUX_SET_WINDOW_STYLE",
24883
+ [KIND_TMUX_REORDER_WINDOWS]: "TMUX_REORDER_WINDOWS",
24884
+ [KIND_TMUX_REORDER_PANES]: "TMUX_REORDER_PANES",
24856
24885
  [KIND_TERM_INPUT]: "TERM_INPUT",
24857
24886
  [KIND_TERM_PASTE]: "TERM_PASTE",
24858
24887
  [KIND_TERM_RESIZE]: "TERM_RESIZE",
@@ -24939,6 +24968,8 @@ __export(exports_schema, {
24939
24968
  TmuxSetWindowStyleSchema: () => TmuxSetWindowStyleSchema,
24940
24969
  TmuxSelectWindowSchema: () => TmuxSelectWindowSchema,
24941
24970
  TmuxSelectSchema: () => TmuxSelectSchema,
24971
+ TmuxReorderWindowsSchema: () => TmuxReorderWindowsSchema,
24972
+ TmuxReorderPanesSchema: () => TmuxReorderPanesSchema,
24942
24973
  TmuxRenameWindowSchema: () => TmuxRenameWindowSchema,
24943
24974
  TmuxEventSchema: () => TmuxEventSchema,
24944
24975
  TmuxCreateWindowSchema: () => TmuxCreateWindowSchema,
@@ -25070,6 +25101,15 @@ var TmuxSetWindowStyleSchema = import_zorsh.b.struct({
25070
25101
  deviceId: import_zorsh.b.string(),
25071
25102
  style: import_zorsh.b.string()
25072
25103
  });
25104
+ var TmuxReorderWindowsSchema = import_zorsh.b.struct({
25105
+ deviceId: import_zorsh.b.string(),
25106
+ windowIds: import_zorsh.b.vec(import_zorsh.b.string())
25107
+ });
25108
+ var TmuxReorderPanesSchema = import_zorsh.b.struct({
25109
+ deviceId: import_zorsh.b.string(),
25110
+ windowId: import_zorsh.b.string(),
25111
+ paneIds: import_zorsh.b.vec(import_zorsh.b.string())
25112
+ });
25073
25113
  var TmuxEventSchema = import_zorsh.b.struct({
25074
25114
  deviceId: import_zorsh.b.string(),
25075
25115
  eventType: import_zorsh.b.u8(),
@@ -32145,6 +32185,7 @@ __export(exports_schema2, {
32145
32185
  siteSettings: () => siteSettings,
32146
32186
  llmProviders: () => llmProviders,
32147
32187
  devices: () => devices,
32188
+ deviceTreeOrder: () => deviceTreeOrder,
32148
32189
  deviceRuntimeStatus: () => deviceRuntimeStatus,
32149
32190
  agentSettings: () => agentSettings,
32150
32191
  agentSessions: () => agentSessions,
@@ -32184,6 +32225,7 @@ var devices = sqliteTable("devices", {
32184
32225
  passwordEnc: text("password_enc"),
32185
32226
  privateKeyEnc: text("private_key_enc"),
32186
32227
  privateKeyPassphraseEnc: text("private_key_passphrase_enc"),
32228
+ sortOrder: integer("sort_order").notNull().default(0),
32187
32229
  createdAt: text("created_at").notNull(),
32188
32230
  updatedAt: text("updated_at").notNull()
32189
32231
  }, (table) => [
@@ -32334,6 +32376,12 @@ var watchRuleState = sqliteTable("watch_rule_state", {
32334
32376
  lastError: text("last_error"),
32335
32377
  modelUnavailableNotified: integer("model_unavailable_notified", { mode: "boolean" }).notNull().default(false)
32336
32378
  });
32379
+ var deviceTreeOrder = sqliteTable("device_tree_order", {
32380
+ deviceId: text("device_id").primaryKey().references(() => devices.id, { onDelete: "cascade" }),
32381
+ windows: text("windows", { mode: "json" }).$type().notNull().default([]),
32382
+ panes: text("panes", { mode: "json" }).$type().notNull().default({}),
32383
+ updatedAt: text("updated_at").notNull()
32384
+ });
32337
32385
  var telegramBotChats = sqliteTable("telegram_bot_chats", {
32338
32386
  id: text("id").primaryKey(),
32339
32387
  botId: text("bot_id").notNull().references(() => telegramBots.id, { onDelete: "cascade" }),
@@ -32388,6 +32436,7 @@ function toDevice(row) {
32388
32436
  passwordEnc: optional(row.passwordEnc),
32389
32437
  privateKeyEnc: optional(row.privateKeyEnc),
32390
32438
  privateKeyPassphraseEnc: optional(row.privateKeyPassphraseEnc),
32439
+ sortOrder: row.sortOrder,
32391
32440
  createdAt: row.createdAt,
32392
32441
  updatedAt: row.updatedAt
32393
32442
  };
@@ -32466,6 +32515,8 @@ function ensureSiteSettingsInitialized() {
32466
32515
  function createDevice(device) {
32467
32516
  const orm = getDb();
32468
32517
  orm.transaction((tx) => {
32518
+ const maxRow = tx.select({ value: max(devices.sortOrder) }).from(devices).get();
32519
+ const nextSortOrder = (maxRow?.value ?? -1) + 1;
32469
32520
  tx.insert(devices).values({
32470
32521
  id: device.id,
32471
32522
  name: device.name,
@@ -32479,6 +32530,7 @@ function createDevice(device) {
32479
32530
  passwordEnc: device.passwordEnc ?? null,
32480
32531
  privateKeyEnc: device.privateKeyEnc ?? null,
32481
32532
  privateKeyPassphraseEnc: device.privateKeyPassphraseEnc ?? null,
32533
+ sortOrder: nextSortOrder,
32482
32534
  createdAt: device.createdAt,
32483
32535
  updatedAt: device.updatedAt
32484
32536
  }).run();
@@ -32501,7 +32553,16 @@ function getDeviceById(id) {
32501
32553
  }
32502
32554
  function getAllDevices() {
32503
32555
  const orm = getDb();
32504
- return orm.select().from(devices).orderBy(desc(devices.createdAt)).all().map(toDevice);
32556
+ return orm.select().from(devices).orderBy(asc(devices.sortOrder), desc(devices.createdAt)).all().map(toDevice);
32557
+ }
32558
+ function reorderDevices(orderedIds) {
32559
+ const orm = getDb();
32560
+ const now = new Date().toISOString();
32561
+ orm.transaction((tx) => {
32562
+ orderedIds.forEach((id, index) => {
32563
+ tx.update(devices).set({ sortOrder: index, updatedAt: now }).where(eq(devices.id, id)).run();
32564
+ });
32565
+ });
32505
32566
  }
32506
32567
  function updateDevice(id, updates) {
32507
32568
  const orm = getDb();
@@ -32544,6 +32605,36 @@ function deleteDevice(id) {
32544
32605
  const orm = getDb();
32545
32606
  orm.delete(devices).where(eq(devices.id, id)).run();
32546
32607
  }
32608
+ function getDeviceTreeOrder(deviceId) {
32609
+ const orm = getDb();
32610
+ const row = orm.select().from(deviceTreeOrder).where(eq(deviceTreeOrder.deviceId, deviceId)).get();
32611
+ if (!row) {
32612
+ return { deviceId, windows: [], panes: {} };
32613
+ }
32614
+ return {
32615
+ deviceId: row.deviceId,
32616
+ windows: Array.isArray(row.windows) ? row.windows : [],
32617
+ panes: row.panes && typeof row.panes === "object" ? row.panes : {}
32618
+ };
32619
+ }
32620
+ function setWindowOrder(deviceId, windowIds) {
32621
+ const orm = getDb();
32622
+ const now = new Date().toISOString();
32623
+ orm.insert(deviceTreeOrder).values({ deviceId, windows: windowIds, panes: {}, updatedAt: now }).onConflictDoUpdate({
32624
+ target: deviceTreeOrder.deviceId,
32625
+ set: { windows: windowIds, updatedAt: now }
32626
+ }).run();
32627
+ }
32628
+ function setPaneOrder(deviceId, windowId, paneIds) {
32629
+ const current = getDeviceTreeOrder(deviceId);
32630
+ const nextPanes = { ...current.panes, [windowId]: paneIds };
32631
+ const orm = getDb();
32632
+ const now = new Date().toISOString();
32633
+ orm.insert(deviceTreeOrder).values({ deviceId, windows: current.windows, panes: nextPanes, updatedAt: now }).onConflictDoUpdate({
32634
+ target: deviceTreeOrder.deviceId,
32635
+ set: { panes: nextPanes, updatedAt: now }
32636
+ }).run();
32637
+ }
32547
32638
  function getDeviceRuntimeStatus(deviceId) {
32548
32639
  const orm = getDb();
32549
32640
  const row = orm.select().from(deviceRuntimeStatus).where(eq(deviceRuntimeStatus.deviceId, deviceId)).get();
@@ -86215,9 +86306,6 @@ _a21 = symbol21;
86215
86306
  var defaultDownload2 = createDownload();
86216
86307
 
86217
86308
  // ../../apps/gateway/src/events/index.ts
86218
- function sanitizeMarkdownV2(input) {
86219
- return input.replace(/([_\*\[\]()~`>#+\-=|{}.!\\])/g, "\\$1");
86220
- }
86221
86309
  function escapeTelegramHtmlText(input) {
86222
86310
  return input.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
86223
86311
  }
@@ -86367,7 +86455,7 @@ class EventNotifier {
86367
86455
  return;
86368
86456
  }
86369
86457
  const message = this.formatTelegramMessage(event, settings);
86370
- await telegramService.sendToAuthorizedChats({ text: message });
86458
+ await telegramService.sendToAuthorizedChats({ text: message, parseMode: "HTML" });
86371
86459
  }
86372
86460
  buildTerminalTopbarLabel(event) {
86373
86461
  const windowLabel = typeof event.tmux?.windowIndex === "number" ? `${event.tmux.windowIndex}` : event.tmux?.windowId ?? "?";
@@ -86378,12 +86466,23 @@ class EventNotifier {
86378
86466
  device: event.device.name
86379
86467
  });
86380
86468
  }
86469
+ buildPaneMetaLines(event) {
86470
+ const lines = [];
86471
+ if (event.tmux?.paneTitle) {
86472
+ lines.push(`${escapeTelegramHtmlText(t2("notification.paneTitle"))}\uFF1A${escapeTelegramHtmlText(event.tmux.paneTitle)}`);
86473
+ }
86474
+ if (event.tmux?.paneCurrentCommand) {
86475
+ lines.push(`${escapeTelegramHtmlText(t2("notification.process"))}\uFF1A${escapeTelegramHtmlText(event.tmux.paneCurrentCommand)}`);
86476
+ }
86477
+ return lines;
86478
+ }
86381
86479
  formatTelegramBellMessage(event) {
86382
86480
  const title = t2("notification.telegramBell.title", {
86383
86481
  siteName: event.site.name,
86384
86482
  terminalTopbarLabel: this.buildTerminalTopbarLabel(event)
86385
86483
  });
86386
86484
  const lines = [escapeTelegramHtmlText(title)];
86485
+ lines.push(...this.buildPaneMetaLines(event));
86387
86486
  const paneUrl = normalizeHttpUrl(buildPaneUrl(event));
86388
86487
  if (paneUrl) {
86389
86488
  const tgSafePaneUrl = encodePercentForTelegramUrl(paneUrl);
@@ -86402,6 +86501,7 @@ class EventNotifier {
86402
86501
  if (body) {
86403
86502
  lines.push(escapeTelegramHtmlText(body));
86404
86503
  }
86504
+ lines.push(...this.buildPaneMetaLines(event));
86405
86505
  const paneUrl = normalizeHttpUrl(buildPaneUrl(event));
86406
86506
  const topbarLabel = this.buildTerminalTopbarLabel(event);
86407
86507
  const footer = `from ${event.site.name}: ${topbarLabel}`;
@@ -86431,23 +86531,26 @@ class EventNotifier {
86431
86531
  watch_model_unavailable: "\uD83D\uDC41\uFE0F",
86432
86532
  watch_rule_error: "\uD83D\uDC41\uFE0F"
86433
86533
  };
86434
- const paneUrl = buildPaneUrl(event);
86534
+ const esc2 = escapeTelegramHtmlText;
86435
86535
  const eventTypeLabel = t2(`notification.eventType.${event.eventType}`);
86436
86536
  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-`
86537
+ `${emojiMap[event.eventType] ?? "\uD83D\uDCE2"} ${esc2(eventTypeLabel)}`,
86538
+ `${esc2(t2("notification.site"))}\uFF1A${esc2(event.site.name)}`,
86539
+ `${esc2(t2("notification.time"))}\uFF1A${esc2(new Date(event.timestamp).toLocaleString(toBCP47(settings.language)))}`,
86540
+ `${esc2(t2("notification.device"))}\uFF1A${esc2(event.device.name)} (${esc2(event.device.type)})`,
86541
+ 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-`,
86542
+ 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
86543
  ];
86444
- if (paneUrl) {
86445
- lines.push(`${t2("notification.directLink")}\uFF1A${paneUrl}`);
86446
- }
86544
+ lines.push(...this.buildPaneMetaLines(event));
86447
86545
  if (event.payload?.message && typeof event.payload.message === "string") {
86448
- lines.push(`${t2("notification.message")}\uFF1A${event.payload.message}`);
86546
+ lines.push(`${esc2(t2("notification.message"))}\uFF1A${esc2(event.payload.message)}`);
86449
86547
  }
86450
- return lines.map((line) => sanitizeMarkdownV2(line)).join(`
86548
+ const paneUrl = normalizeHttpUrl(buildPaneUrl(event));
86549
+ if (paneUrl) {
86550
+ const tgSafePaneUrl = encodePercentForTelegramUrl(paneUrl);
86551
+ lines.push("", `<a href="${escapeTelegramHtmlAttribute(tgSafePaneUrl)}">${esc2(t2("notification.directLink"))}</a>`);
86552
+ }
86553
+ return lines.join(`
86451
86554
  `);
86452
86555
  }
86453
86556
  async generateHmac(secret, message) {
@@ -97172,7 +97275,7 @@ class LocalExternalTmuxConnection {
97172
97275
  "-t",
97173
97276
  this.sessionName,
97174
97277
  "-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}"
97278
+ "#{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
97279
  ])
97177
97280
  ]);
97178
97281
  if (sessionRes.exitCode !== 0 || windowsRes.exitCode !== 0 || panesRes.exitCode !== 0) {
@@ -97244,7 +97347,7 @@ ${panesRes.stderr}`;
97244
97347
  if (!line.trim()) {
97245
97348
  continue;
97246
97349
  }
97247
- const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw] = line.split("\t");
97350
+ const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw, currentCommandRaw] = line.split("\t");
97248
97351
  if (!paneId || !windowId) {
97249
97352
  continue;
97250
97353
  }
@@ -97256,6 +97359,7 @@ ${panesRes.stderr}`;
97256
97359
  windowId,
97257
97360
  index: Number.isNaN(index) ? 0 : index,
97258
97361
  title: this.pendingPaneTitles.get(paneId) ?? (titleRaw?.trim() ? titleRaw : undefined),
97362
+ currentCommand: currentCommandRaw?.trim() ? currentCommandRaw.trim() : undefined,
97259
97363
  active: activeRaw === "1",
97260
97364
  width: Number.isNaN(width) ? 0 : width,
97261
97365
  height: Number.isNaN(height) ? 0 : height
@@ -97776,6 +97880,19 @@ function splitSnapshotFields(line, fieldCount) {
97776
97880
  parts.at(-1) ?? ""
97777
97881
  ];
97778
97882
  }
97883
+ if (fieldCount === 9) {
97884
+ return [
97885
+ parts[0] ?? "",
97886
+ parts[1] ?? "",
97887
+ parts[2] ?? "",
97888
+ parts.slice(3, -5).join(SNAPSHOT_FIELD_SEPARATOR),
97889
+ parts.at(-5) ?? "",
97890
+ parts.at(-4) ?? "",
97891
+ parts.at(-3) ?? "",
97892
+ parts.at(-2) ?? "",
97893
+ parts.at(-1) ?? ""
97894
+ ];
97895
+ }
97779
97896
  return parts;
97780
97897
  }
97781
97898
 
@@ -98405,7 +98522,7 @@ class SshExternalTmuxConnection {
98405
98522
  "-t",
98406
98523
  this.sessionName,
98407
98524
  "-F",
98408
- "#{pane_id}|#{window_id}|#{pane_index}|#{pane_title}|#{pane_active}|#{pane_width}|#{pane_height}|#{window_active}"
98525
+ "#{pane_id}|#{window_id}|#{pane_index}|#{pane_title}|#{pane_active}|#{pane_width}|#{pane_height}|#{window_active}|#{pane_current_command}"
98409
98526
  ])
98410
98527
  ]);
98411
98528
  if (sessionRes.exitCode !== 0 || windowsRes.exitCode !== 0 || panesRes.exitCode !== 0) {
@@ -98477,7 +98594,7 @@ ${panesRes.stderr}`;
98477
98594
  if (!line.trim()) {
98478
98595
  continue;
98479
98596
  }
98480
- const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw] = splitSnapshotFields(line, 8);
98597
+ const [paneId, windowId, indexRaw, titleRaw, activeRaw, widthRaw, heightRaw, windowActiveRaw, currentCommandRaw] = splitSnapshotFields(line, 9);
98481
98598
  if (!paneId || !windowId) {
98482
98599
  continue;
98483
98600
  }
@@ -98489,6 +98606,7 @@ ${panesRes.stderr}`;
98489
98606
  windowId,
98490
98607
  index: Number.isNaN(index) ? 0 : index,
98491
98608
  title: this.pendingPaneTitles.get(paneId) ?? (titleRaw?.trim() ? titleRaw : undefined),
98609
+ currentCommand: currentCommandRaw?.trim() ? currentCommandRaw.trim() : undefined,
98492
98610
  active: activeRaw === "1",
98493
98611
  width: Number.isNaN(width) ? 0 : width,
98494
98612
  height: Number.isNaN(height) ? 0 : height
@@ -101292,7 +101410,9 @@ function resolvePaneContext(options) {
101292
101410
  paneId: targetPane?.id ?? bellPaneId,
101293
101411
  windowIndex: targetWindow?.index,
101294
101412
  paneIndex: targetPane?.index,
101295
- paneUrl
101413
+ paneUrl,
101414
+ paneTitle: targetPane?.title,
101415
+ paneCurrentCommand: targetPane?.currentCommand
101296
101416
  };
101297
101417
  }
101298
101418
 
@@ -101324,7 +101444,9 @@ var defaultDeps2 = {
101324
101444
  paneId: bell.paneId,
101325
101445
  windowIndex: bell.windowIndex,
101326
101446
  paneIndex: bell.paneIndex,
101327
- paneUrl: bell.paneUrl
101447
+ paneUrl: bell.paneUrl,
101448
+ paneTitle: bell.paneTitle,
101449
+ paneCurrentCommand: bell.paneCurrentCommand
101328
101450
  },
101329
101451
  payload: {
101330
101452
  message: t2("notification.eventType.terminal_bell")
@@ -101350,7 +101472,9 @@ var defaultDeps2 = {
101350
101472
  paneId: notification.paneId,
101351
101473
  windowIndex: notification.windowIndex,
101352
101474
  paneIndex: notification.paneIndex,
101353
- paneUrl: notification.paneUrl
101475
+ paneUrl: notification.paneUrl,
101476
+ paneTitle: notification.paneTitle,
101477
+ paneCurrentCommand: notification.paneCurrentCommand
101354
101478
  },
101355
101479
  payload: {
101356
101480
  source: notification.source,
@@ -102706,6 +102830,7 @@ var defaultDeps3 = {
102706
102830
  getState: getWatchRuleState,
102707
102831
  upsertState: upsertWatchRuleState,
102708
102832
  updateRule: updateWatchRule,
102833
+ deleteRule: deleteWatchRule,
102709
102834
  acquireRuntime: (deviceId) => tmuxRuntimeRegistry.acquire(deviceId),
102710
102835
  releaseRuntime: (deviceId, runtime) => tmuxRuntimeRegistry.release(deviceId, runtime),
102711
102836
  resolveModel: resolveLanguageModel2,
@@ -102999,7 +103124,12 @@ class WatchService {
102999
103124
  if (!this.rules.has(rule.id)) {
103000
103125
  return;
103001
103126
  }
103002
- await this.recordRuleError(rule, toErrorMessage3(error51), now2);
103127
+ const message = toErrorMessage3(error51);
103128
+ if (isTargetMissingMessage(message)) {
103129
+ await this.handlePaneGone(rule);
103130
+ return;
103131
+ }
103132
+ await this.recordRuleError(rule, message, now2);
103003
103133
  return;
103004
103134
  }
103005
103135
  if (!this.rules.has(rule.id)) {
@@ -103151,6 +103281,22 @@ class WatchService {
103151
103281
  await this.disableRuleForErrors(rule, errors3, message);
103152
103282
  }
103153
103283
  }
103284
+ async handlePaneGone(rule) {
103285
+ this.deps.deleteRule(rule.id);
103286
+ await this.teardownRule(rule.id);
103287
+ this.samples.delete(rule.id);
103288
+ const message = t2("notification.watch.paneGone", {
103289
+ name: rule.name,
103290
+ paneId: rule.paneId
103291
+ });
103292
+ await this.safeNotify("watch_rule_error", rule, {
103293
+ message,
103294
+ ruleId: rule.id,
103295
+ ruleName: rule.name,
103296
+ paneGone: true
103297
+ }, { paneId: rule.paneId });
103298
+ this.broadcastSafe(rule, exports_ws_borsh.WATCH_EVENT_RULE_ERROR, { message });
103299
+ }
103154
103300
  async disableRuleForErrors(rule, errorCount, detail) {
103155
103301
  this.deps.updateRule(rule.id, { enabled: false });
103156
103302
  await this.teardownRule(rule.id);
@@ -103258,7 +103404,9 @@ class WatchService {
103258
103404
  windowIndex: paneContext.windowIndex,
103259
103405
  paneId: paneContext.paneId ?? rule.paneId,
103260
103406
  paneIndex: paneContext.paneIndex,
103261
- paneUrl: paneContext.paneUrl
103407
+ paneUrl: paneContext.paneUrl,
103408
+ paneTitle: paneContext.paneTitle,
103409
+ paneCurrentCommand: paneContext.paneCurrentCommand
103262
103410
  },
103263
103411
  payload
103264
103412
  });
@@ -103906,6 +104054,9 @@ function handleApiRequest(req, _server) {
103906
104054
  if (path === "/api/devices" && req.method === "POST") {
103907
104055
  return handleCreateDevice(req);
103908
104056
  }
104057
+ if (path === "/api/devices/order" && req.method === "PUT") {
104058
+ return handleReorderDevices(req);
104059
+ }
103909
104060
  if (path.match(/^\/api\/devices\/[^/]+$/) && req.method === "GET") {
103910
104061
  return handleGetDevice(path.split("/")[3]);
103911
104062
  }
@@ -104029,12 +104180,13 @@ async function handleCreateDevice(req) {
104029
104180
  passwordEnc: body.password ? await encrypt(body.password) : undefined,
104030
104181
  privateKeyEnc: body.privateKey ? await encrypt(body.privateKey) : undefined,
104031
104182
  privateKeyPassphraseEnc: body.privateKeyPassphrase ? await encrypt(body.privateKeyPassphrase) : undefined,
104183
+ sortOrder: 0,
104032
104184
  createdAt: now2,
104033
104185
  updatedAt: now2
104034
104186
  };
104035
104187
  createDevice(device);
104036
104188
  await pushSupervisor.upsert(device.id);
104037
- return json7({ device }, 201);
104189
+ return json7({ device: getDeviceById(device.id) ?? device }, 201);
104038
104190
  }
104039
104191
  async function handleUpdateDevice(req, id) {
104040
104192
  const existing = getDeviceById(id);
@@ -104071,6 +104223,14 @@ async function handleUpdateDevice(req, id) {
104071
104223
  const device = getDeviceById(id);
104072
104224
  return json7({ device });
104073
104225
  }
104226
+ async function handleReorderDevices(req) {
104227
+ const body = await req.json();
104228
+ if (!Array.isArray(body.deviceIds) || body.deviceIds.some((id) => typeof id !== "string")) {
104229
+ return json7({ error: t2("apiError.invalidRequest") }, 400);
104230
+ }
104231
+ reorderDevices(body.deviceIds);
104232
+ return json7({ devices: getAllDevices().map(enrichDeviceWithRuntime) });
104233
+ }
104074
104234
  async function handleDeleteDevice(id) {
104075
104235
  const existing = getDeviceById(id);
104076
104236
  if (!existing) {
@@ -104933,6 +105093,45 @@ class SwitchBarrier {
104933
105093
  }
104934
105094
  var switchBarrier = new SwitchBarrier;
104935
105095
 
105096
+ // ../../apps/gateway/src/ws/overlay-utils.ts
105097
+ function orderBySaved(items, getId, savedIds) {
105098
+ if (savedIds.length === 0)
105099
+ return items;
105100
+ const byId = new Map(items.map((item) => [getId(item), item]));
105101
+ const used = new Set;
105102
+ const result = [];
105103
+ for (const id of savedIds) {
105104
+ const item = byId.get(id);
105105
+ if (item && !used.has(id)) {
105106
+ result.push(item);
105107
+ used.add(id);
105108
+ }
105109
+ }
105110
+ for (const item of items) {
105111
+ if (!used.has(getId(item)))
105112
+ result.push(item);
105113
+ }
105114
+ return result;
105115
+ }
105116
+ function applyDeviceTreeOverlay(payload, order) {
105117
+ if (!payload.session)
105118
+ return payload;
105119
+ const hasWindowOrder = order.windows.length > 0;
105120
+ const hasPaneOrder = Object.keys(order.panes).length > 0;
105121
+ if (!hasWindowOrder && !hasPaneOrder)
105122
+ return payload;
105123
+ const orderedWindows = orderBySaved(payload.session.windows, (w) => w.id, order.windows).map((window2) => {
105124
+ const savedPaneOrder = order.panes[window2.id];
105125
+ if (!savedPaneOrder || savedPaneOrder.length === 0)
105126
+ return window2;
105127
+ return { ...window2, panes: orderBySaved(window2.panes, (p) => p.id, savedPaneOrder) };
105128
+ });
105129
+ return {
105130
+ ...payload,
105131
+ session: { ...payload.session, windows: orderedWindows }
105132
+ };
105133
+ }
105134
+
104936
105135
  // ../../apps/gateway/src/ws/index.ts
104937
105136
  var defaultDeps5 = {
104938
105137
  acquireRuntime: async (deviceId) => tmuxRuntimeRegistry.acquire(deviceId),
@@ -105183,6 +105382,16 @@ class WebSocketServer {
105183
105382
  this.handleSetWindowStyle(decoded.deviceId, decoded.style);
105184
105383
  return;
105185
105384
  }
105385
+ case exports_ws_borsh.KIND_TMUX_REORDER_WINDOWS: {
105386
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxReorderWindowsSchema, payload);
105387
+ this.handleReorderWindows(decoded.deviceId, decoded.windowIds);
105388
+ return;
105389
+ }
105390
+ case exports_ws_borsh.KIND_TMUX_REORDER_PANES: {
105391
+ const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxReorderPanesSchema, payload);
105392
+ this.handleReorderPanes(decoded.deviceId, decoded.windowId, decoded.paneIds);
105393
+ return;
105394
+ }
105186
105395
  case exports_ws_borsh.KIND_TERM_INPUT: {
105187
105396
  const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TermInputSchema, payload);
105188
105397
  if (decoded.isComposing)
@@ -105321,7 +105530,7 @@ class WebSocketServer {
105321
105530
  });
105322
105531
  this.sendEnvelope(ws, exports_ws_borsh.KIND_DEVICE_CONNECTED, connectedPayload);
105323
105532
  if (entry.lastSnapshot) {
105324
- const snapshotBytes = exports_ws_borsh.encodeStateSnapshot(this.applyWindowCustomNames(entry.lastSnapshot));
105533
+ const snapshotBytes = this.encodeSnapshotWithOverlays(entry.lastSnapshot);
105325
105534
  this.sendChunked(ws, exports_ws_borsh.KIND_STATE_SNAPSHOT, snapshotBytes);
105326
105535
  } else {
105327
105536
  entry.runtime.requestSnapshot();
@@ -105445,6 +105654,20 @@ class WebSocketServer {
105445
105654
  return;
105446
105655
  entry.runtime.setWindowStyle(style);
105447
105656
  }
105657
+ handleReorderWindows(deviceId, windowIds) {
105658
+ setWindowOrder(deviceId, windowIds);
105659
+ const entry = this.connections.get(deviceId);
105660
+ if (!entry?.lastSnapshot)
105661
+ return;
105662
+ this.sendSnapshotToClients(entry, entry.lastSnapshot);
105663
+ }
105664
+ handleReorderPanes(deviceId, windowId, paneIds) {
105665
+ setPaneOrder(deviceId, windowId, paneIds);
105666
+ const entry = this.connections.get(deviceId);
105667
+ if (!entry?.lastSnapshot)
105668
+ return;
105669
+ this.sendSnapshotToClients(entry, entry.lastSnapshot);
105670
+ }
105448
105671
  applyWindowCustomNames(payload) {
105449
105672
  const names = this.windowCustomNames.get(payload.deviceId);
105450
105673
  if (!names?.size || !payload.session)
@@ -105466,8 +105689,12 @@ class WebSocketServer {
105466
105689
  }
105467
105690
  };
105468
105691
  }
105692
+ encodeSnapshotWithOverlays(payload) {
105693
+ const ordered = applyDeviceTreeOverlay(payload, getDeviceTreeOrder(payload.deviceId));
105694
+ return exports_ws_borsh.encodeStateSnapshot(this.applyWindowCustomNames(ordered));
105695
+ }
105469
105696
  sendSnapshotToClients(entry, payload) {
105470
- const payloadBytes = exports_ws_borsh.encodeStateSnapshot(this.applyWindowCustomNames(payload));
105697
+ const payloadBytes = this.encodeSnapshotWithOverlays(payload);
105471
105698
  for (const client of entry.clients) {
105472
105699
  this.sendChunked(client, exports_ws_borsh.KIND_STATE_SNAPSHOT, payloadBytes);
105473
105700
  }