tmex-cli 0.16.4 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -7
- package/dist/runtime/server.js +702 -337
- package/package.json +2 -1
- package/resources/fe-dist/assets/DevicePage-B-4Wp5gx.js +24 -0
- package/resources/fe-dist/assets/{DevicesPage-CJF229QB.js → DevicesPage-D3GQd_MI.js} +1 -1
- package/resources/fe-dist/assets/{FilePage-CkEaJiW3.js → FilePage-C45pl7_F.js} +2 -2
- package/resources/fe-dist/assets/SettingsPage-DEkQrJzi.js +39 -0
- package/resources/fe-dist/assets/{agent-tab-6MAsxcE4.js → agent-tab-BnKrqJP2.js} +2 -2
- package/resources/fe-dist/assets/api-5IhJ49aS.js +5 -0
- package/resources/fe-dist/assets/{arc-BAINpc3Q.js → arc-DBxiTdY2.js} +1 -1
- package/resources/fe-dist/assets/{architectureDiagram-3BPJPVTR-CWFap8y8.js → architectureDiagram-3BPJPVTR-Dcd70ntw.js} +1 -1
- package/resources/fe-dist/assets/{blockDiagram-GPEHLZMM-BnR3WVDx.js → blockDiagram-GPEHLZMM-LsFpH20h.js} +1 -1
- package/resources/fe-dist/assets/{c4Diagram-AAUBKEIU-BT4ZOccY.js → c4Diagram-AAUBKEIU-BswGzO6B.js} +1 -1
- package/resources/fe-dist/assets/{card-TMGETMIE.js → card-Bav-X9c4.js} +1 -1
- package/resources/fe-dist/assets/channel-hAJp4tg-.js +1 -0
- package/resources/fe-dist/assets/{chunk-2J33WTMH-B4Tvbi6K.js → chunk-2J33WTMH-C0yl1OR1.js} +1 -1
- package/resources/fe-dist/assets/{chunk-4BX2VUAB-e7mC2fAZ.js → chunk-4BX2VUAB-Dwo9vDDk.js} +1 -1
- package/resources/fe-dist/assets/{chunk-55IACEB6-CIYZgFr_.js → chunk-55IACEB6-Dz9e7vav.js} +1 -1
- package/resources/fe-dist/assets/{chunk-727SXJPM-Cp8xQ_Up.js → chunk-727SXJPM-ZkqwcZ6G.js} +1 -1
- package/resources/fe-dist/assets/{chunk-AQP2D5EJ-C-NtHCtH.js → chunk-AQP2D5EJ-79MMuY3h.js} +1 -1
- package/resources/fe-dist/assets/{chunk-FMBD7UC4-DmjdaPSW.js → chunk-FMBD7UC4-Vw8e6XCy.js} +1 -1
- package/resources/fe-dist/assets/{chunk-ND2GUHAM-Zg5krkW_.js → chunk-ND2GUHAM-um7O2-xi.js} +1 -1
- package/resources/fe-dist/assets/{chunk-QZHKN3VN-BIuK8Di1.js → chunk-QZHKN3VN-D8FuV91c.js} +1 -1
- package/resources/fe-dist/assets/classDiagram-4FO5ZUOK-SSiS3KfC.js +1 -0
- package/resources/fe-dist/assets/classDiagram-v2-Q7XG4LA2-SSiS3KfC.js +1 -0
- package/resources/fe-dist/assets/{copy-BfbLkQQH.js → copy-Cawnv2-o.js} +1 -1
- package/resources/fe-dist/assets/{cose-bilkent-S5V4N54A-DjsBN2Gw.js → cose-bilkent-S5V4N54A-gidx-z0G.js} +1 -1
- package/resources/fe-dist/assets/{dagre-BM42HDAG-EHYEOgd4.js → dagre-BM42HDAG-C54CUHrk.js} +1 -1
- package/resources/fe-dist/assets/{diagram-2AECGRRQ-DP2qaS44.js → diagram-2AECGRRQ-DFGI1MJu.js} +1 -1
- package/resources/fe-dist/assets/{diagram-5GNKFQAL-CXjsd6rW.js → diagram-5GNKFQAL-D7POJY8A.js} +1 -1
- package/resources/fe-dist/assets/{diagram-KO2AKTUF-C3imvzg0.js → diagram-KO2AKTUF-CvV1GMLL.js} +1 -1
- package/resources/fe-dist/assets/{diagram-LMA3HP47-BWfVIlqx.js → diagram-LMA3HP47-BbfJVUKI.js} +1 -1
- package/resources/fe-dist/assets/{diagram-OG6HWLK6-DjPzNtRm.js → diagram-OG6HWLK6-CV6Q6IxH.js} +1 -1
- package/resources/fe-dist/assets/download-ZSRF6UU6.js +6 -0
- package/resources/fe-dist/assets/en_US-xzwBD2oK.js +1 -0
- package/resources/fe-dist/assets/{erDiagram-TEJ5UH35-B0NYaEtR.js → erDiagram-TEJ5UH35-BPgvqV_L.js} +1 -1
- package/resources/fe-dist/assets/{files-tab-BFIlXST7.js → files-tab-BQhhr5Wi.js} +15 -15
- package/resources/fe-dist/assets/{flowDiagram-I6XJVG4X-CdStxlad.js → flowDiagram-I6XJVG4X-CKXjL0zg.js} +1 -1
- package/resources/fe-dist/assets/{ganttDiagram-6RSMTGT7-DdEyq_eg.js → ganttDiagram-6RSMTGT7-D58QnW85.js} +1 -1
- package/resources/fe-dist/assets/{gitGraphDiagram-PVQCEYII-DVt7acpU.js → gitGraphDiagram-PVQCEYII-BwB9zJYk.js} +1 -1
- package/resources/fe-dist/assets/index-C4Fdxowt.css +1 -0
- package/resources/fe-dist/assets/{index-C1akMMWP.js → index-CxD8veUJ.js} +16 -16
- package/resources/fe-dist/assets/{index-c9jmHxDX.js → index-DDvqV24J.js} +1 -1
- package/resources/fe-dist/assets/{infoDiagram-5YYISTIA-BfBQlpuG.js → infoDiagram-5YYISTIA-DGZZJ51K.js} +1 -1
- package/resources/fe-dist/assets/{ishikawaDiagram-YF4QCWOH-DUn8fG3F.js → ishikawaDiagram-YF4QCWOH-DKEV0i-O.js} +1 -1
- package/resources/fe-dist/assets/ja_JP-Dd1FrxOk.js +1 -0
- package/resources/fe-dist/assets/{journeyDiagram-JHISSGLW-D1YteFVs.js → journeyDiagram-JHISSGLW-Dvt5MIiS.js} +1 -1
- package/resources/fe-dist/assets/{kanban-definition-UN3LZRKU-Do0o8nlT.js → kanban-definition-UN3LZRKU-BrLCK6I8.js} +1 -1
- package/resources/fe-dist/assets/{linear-Bmap7qQK.js → linear-LNJ3BF_d.js} +1 -1
- package/resources/fe-dist/assets/{markdown-preview-ByBN48Ac.js → markdown-preview-Cqdqjc1H.js} +3 -3
- package/resources/fe-dist/assets/{mermaid.core-CloKtMOb.js → mermaid.core-Cy4PFTl-.js} +5 -5
- package/resources/fe-dist/assets/{mindmap-definition-RKZ34NQL-BFPgS54r.js → mindmap-definition-RKZ34NQL-JOcL1ZTP.js} +1 -1
- package/resources/fe-dist/assets/{pieDiagram-4H26LBE5-DwY4DDxv.js → pieDiagram-4H26LBE5-_1o-TTd6.js} +1 -1
- package/resources/fe-dist/assets/{quadrantDiagram-W4KKPZXB-3jSLHV3z.js → quadrantDiagram-W4KKPZXB-7Ggy2jhO.js} +1 -1
- package/resources/fe-dist/assets/{requirementDiagram-4Y6WPE33-DHrqJmHL.js → requirementDiagram-4Y6WPE33-CH_udJzB.js} +1 -1
- package/resources/fe-dist/assets/{sankeyDiagram-5OEKKPKP-CIaPmx-2.js → sankeyDiagram-5OEKKPKP-DO9ymHJb.js} +1 -1
- package/resources/fe-dist/assets/{send-CAJeq7VS.js → send-D0SbMcl5.js} +1 -1
- package/resources/fe-dist/assets/{sequenceDiagram-3UESZ5HK-DhRU1sO_.js → sequenceDiagram-3UESZ5HK-BfxbUo5S.js} +1 -1
- package/resources/fe-dist/assets/{stateDiagram-AJRCARHV-DZWC0te0.js → stateDiagram-AJRCARHV-ChJ5OE86.js} +1 -1
- package/resources/fe-dist/assets/stateDiagram-v2-BHNVJYJU-yafZZKAc.js +1 -0
- package/resources/fe-dist/assets/terminal-settings-panel-CFkXHe7W.js +25 -0
- package/resources/fe-dist/assets/{timeline-definition-PNZ67QCA-Y0cAlUby.js → timeline-definition-PNZ67QCA-CIlpfkBn.js} +1 -1
- package/resources/fe-dist/assets/{transfer-toast-yJBQc29j.js → transfer-toast-DvU8-v2e.js} +1 -1
- package/resources/fe-dist/assets/{triangle-alert-Bs89Dzy0.js → triangle-alert-BI3hbdo6.js} +1 -1
- package/resources/fe-dist/assets/{vennDiagram-CIIHVFJN-BVWElA6Q.js → vennDiagram-CIIHVFJN-NqSGMHBa.js} +1 -1
- package/resources/fe-dist/assets/{wardley-L42UT6IY-BBf8FmIs.js → wardley-L42UT6IY-bOJt96SM.js} +1 -1
- package/resources/fe-dist/assets/{wardleyDiagram-YWT4CUSO-Cyk4va1x.js → wardleyDiagram-YWT4CUSO-DAgFPWOP.js} +1 -1
- package/resources/fe-dist/assets/{xychartDiagram-2RQKCTM6-DmEvYdFT.js → xychartDiagram-2RQKCTM6-D5rVqEFB.js} +1 -1
- package/resources/fe-dist/assets/{zap-B28XlJER.js → zap-D-Szn4JY.js} +1 -1
- package/resources/fe-dist/assets/zh_CN-DVIa9MQX.js +1 -0
- package/resources/fe-dist/index.html +2 -2
- package/resources/gateway-drizzle/0015_wise_mongu.sql +1 -0
- package/resources/gateway-drizzle/0016_cheerful_scarecrow.sql +17 -0
- package/resources/gateway-drizzle/meta/_journal.json +14 -0
- package/resources/fe-dist/assets/DevicePage-DxFUn3eM.js +0 -24
- package/resources/fe-dist/assets/SettingsPage-BjsRYOBG.js +0 -39
- package/resources/fe-dist/assets/api-B3b18azE.js +0 -10
- package/resources/fe-dist/assets/channel-C_D-Pin5.js +0 -1
- package/resources/fe-dist/assets/classDiagram-4FO5ZUOK-BKAkOexI.js +0 -1
- package/resources/fe-dist/assets/classDiagram-v2-Q7XG4LA2-BKAkOexI.js +0 -1
- package/resources/fe-dist/assets/en_US-BihUhDmr.js +0 -1
- package/resources/fe-dist/assets/index-j9kTGUS5.css +0 -1
- package/resources/fe-dist/assets/ja_JP-f5sXmz8W.js +0 -1
- package/resources/fe-dist/assets/stateDiagram-v2-BHNVJYJU-BJcIn84l.js +0 -1
- package/resources/fe-dist/assets/terminal-settings-panel-BiDSWGtf.js +0 -25
- package/resources/fe-dist/assets/zh_CN-CPdvelFW.js +0 -1
package/dist/runtime/server.js
CHANGED
|
@@ -22735,7 +22735,8 @@ var I18N_RESOURCES = {
|
|
|
22735
22735
|
copied: "Copied to clipboard",
|
|
22736
22736
|
copyFailed: "Copy failed",
|
|
22737
22737
|
pasteFailed: "Could not read clipboard, check browser permissions",
|
|
22738
|
-
clearSelection: "Dismiss selection"
|
|
22738
|
+
clearSelection: "Dismiss selection",
|
|
22739
|
+
fileLinkNotFound: "File does not exist or is not accessible"
|
|
22739
22740
|
},
|
|
22740
22741
|
settings: {
|
|
22741
22742
|
title: "System Settings",
|
|
@@ -23751,7 +23752,8 @@ Time: {{time}}`,
|
|
|
23751
23752
|
copied: "\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F",
|
|
23752
23753
|
copyFailed: "\u590D\u5236\u5931\u8D25",
|
|
23753
23754
|
pasteFailed: "\u65E0\u6CD5\u8BFB\u53D6\u526A\u8D34\u677F\uFF0C\u8BF7\u68C0\u67E5\u6D4F\u89C8\u5668\u6743\u9650",
|
|
23754
|
-
clearSelection: "\u53D6\u6D88\u9009\u62E9"
|
|
23755
|
+
clearSelection: "\u53D6\u6D88\u9009\u62E9",
|
|
23756
|
+
fileLinkNotFound: "\u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u8BBF\u95EE"
|
|
23755
23757
|
},
|
|
23756
23758
|
settings: {
|
|
23757
23759
|
title: "\u7CFB\u7EDF\u8BBE\u7F6E",
|
|
@@ -24767,7 +24769,8 @@ Bot\uFF1A{{botName}}
|
|
|
24767
24769
|
copied: "\u30AF\u30EA\u30C3\u30D7\u30DC\u30FC\u30C9\u306B\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F",
|
|
24768
24770
|
copyFailed: "\u30B3\u30D4\u30FC\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
24769
24771
|
pasteFailed: "\u30AF\u30EA\u30C3\u30D7\u30DC\u30FC\u30C9\u3092\u8AAD\u307F\u53D6\u308C\u307E\u305B\u3093\u3002\u30D6\u30E9\u30A6\u30B6\u306E\u6A29\u9650\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
24770
|
-
clearSelection: "\u9078\u629E\u3092\u89E3\u9664"
|
|
24772
|
+
clearSelection: "\u9078\u629E\u3092\u89E3\u9664",
|
|
24773
|
+
fileLinkNotFound: "\u30D5\u30A1\u30A4\u30EB\u304C\u5B58\u5728\u3057\u306A\u3044\u304B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093"
|
|
24771
24774
|
},
|
|
24772
24775
|
settings: {
|
|
24773
24776
|
title: "\u30B7\u30B9\u30C6\u30E0\u8A2D\u5B9A",
|
|
@@ -25651,12 +25654,14 @@ __export(exports_ws_borsh, {
|
|
|
25651
25654
|
encodeTmuxEventPayload: () => encodeTmuxEventPayload,
|
|
25652
25655
|
encodeStateSnapshot: () => encodeStateSnapshot,
|
|
25653
25656
|
encodePayload: () => encodePayload,
|
|
25657
|
+
encodePaneModes: () => encodePaneModes,
|
|
25654
25658
|
encodeEnvelope: () => encodeEnvelope,
|
|
25655
25659
|
encodeDeviceEventPayload: () => encodeDeviceEventPayload,
|
|
25656
25660
|
encodeChunk: () => encodeChunk,
|
|
25657
25661
|
decodeTmuxEventPayload: () => decodeTmuxEventPayload,
|
|
25658
25662
|
decodeStateSnapshot: () => decodeStateSnapshot,
|
|
25659
25663
|
decodePayload: () => decodePayload,
|
|
25664
|
+
decodePaneModes: () => decodePaneModes,
|
|
25660
25665
|
decodeEnvelopeAndPayload: () => decodeEnvelopeAndPayload,
|
|
25661
25666
|
decodeEnvelope: () => decodeEnvelope,
|
|
25662
25667
|
decodeDeviceEventPayload: () => decodeDeviceEventPayload,
|
|
@@ -25670,6 +25675,11 @@ __export(exports_ws_borsh, {
|
|
|
25670
25675
|
WATCH_EVENT_MODEL_UNAVAILABLE: () => WATCH_EVENT_MODEL_UNAVAILABLE,
|
|
25671
25676
|
SITE_THEME_LIGHT: () => SITE_THEME_LIGHT,
|
|
25672
25677
|
SITE_THEME_DARK: () => SITE_THEME_DARK,
|
|
25678
|
+
PANE_MODE_MOUSE_UTF8: () => PANE_MODE_MOUSE_UTF8,
|
|
25679
|
+
PANE_MODE_MOUSE_STANDARD: () => PANE_MODE_MOUSE_STANDARD,
|
|
25680
|
+
PANE_MODE_MOUSE_SGR: () => PANE_MODE_MOUSE_SGR,
|
|
25681
|
+
PANE_MODE_MOUSE_BUTTON: () => PANE_MODE_MOUSE_BUTTON,
|
|
25682
|
+
PANE_MODE_MOUSE_ALL: () => PANE_MODE_MOUSE_ALL,
|
|
25673
25683
|
MAX_CHUNK_STREAMS: () => MAX_CHUNK_STREAMS,
|
|
25674
25684
|
MAX_CHUNKS_PER_MESSAGE: () => MAX_CHUNKS_PER_MESSAGE,
|
|
25675
25685
|
MAGIC: () => MAGIC,
|
|
@@ -25703,6 +25713,7 @@ __export(exports_ws_borsh, {
|
|
|
25703
25713
|
KIND_STATE_SNAPSHOT_DIFF: () => KIND_STATE_SNAPSHOT_DIFF,
|
|
25704
25714
|
KIND_STATE_SNAPSHOT: () => KIND_STATE_SNAPSHOT,
|
|
25705
25715
|
KIND_SITE_THEME_UPDATE: () => KIND_SITE_THEME_UPDATE,
|
|
25716
|
+
KIND_SETTINGS_UPDATE: () => KIND_SETTINGS_UPDATE,
|
|
25706
25717
|
KIND_PONG: () => KIND_PONG,
|
|
25707
25718
|
KIND_PING: () => KIND_PING,
|
|
25708
25719
|
KIND_LIVE_RESUME: () => KIND_LIVE_RESUME,
|
|
@@ -25737,6 +25748,7 @@ __export(exports_ws_borsh, {
|
|
|
25737
25748
|
ERROR_FRAME_TOO_LARGE: () => ERROR_FRAME_TOO_LARGE,
|
|
25738
25749
|
ERROR_DEVICE_NOT_FOUND: () => ERROR_DEVICE_NOT_FOUND,
|
|
25739
25750
|
ERROR_DEVICE_CONNECT_FAILED: () => ERROR_DEVICE_CONNECT_FAILED,
|
|
25751
|
+
EMPTY_PANE_MODE_FLAGS: () => EMPTY_PANE_MODE_FLAGS,
|
|
25740
25752
|
DEFAULT_MAX_FRAME_BYTES: () => DEFAULT_MAX_FRAME_BYTES,
|
|
25741
25753
|
ChunkReassembler: () => ChunkReassembler,
|
|
25742
25754
|
CURRENT_VERSION: () => CURRENT_VERSION,
|
|
@@ -25804,6 +25816,7 @@ var KIND_AGENT_UNSUBSCRIBE = 1538;
|
|
|
25804
25816
|
var KIND_AGENT_EVENT = 1539;
|
|
25805
25817
|
var KIND_WATCH_EVENT = 1793;
|
|
25806
25818
|
var KIND_SITE_THEME_UPDATE = 2049;
|
|
25819
|
+
var KIND_SETTINGS_UPDATE = 2050;
|
|
25807
25820
|
var VALID_KINDS = new Set([
|
|
25808
25821
|
KIND_HELLO_C2S,
|
|
25809
25822
|
KIND_HELLO_S2C,
|
|
@@ -25850,7 +25863,8 @@ var VALID_KINDS = new Set([
|
|
|
25850
25863
|
KIND_AGENT_UNSUBSCRIBE,
|
|
25851
25864
|
KIND_AGENT_EVENT,
|
|
25852
25865
|
KIND_WATCH_EVENT,
|
|
25853
|
-
KIND_SITE_THEME_UPDATE
|
|
25866
|
+
KIND_SITE_THEME_UPDATE,
|
|
25867
|
+
KIND_SETTINGS_UPDATE
|
|
25854
25868
|
]);
|
|
25855
25869
|
function isValidKind(kind) {
|
|
25856
25870
|
return VALID_KINDS.has(kind);
|
|
@@ -25902,7 +25916,8 @@ function kindToString(kind) {
|
|
|
25902
25916
|
[KIND_AGENT_UNSUBSCRIBE]: "AGENT_UNSUBSCRIBE",
|
|
25903
25917
|
[KIND_AGENT_EVENT]: "AGENT_EVENT",
|
|
25904
25918
|
[KIND_WATCH_EVENT]: "WATCH_EVENT",
|
|
25905
|
-
[KIND_SITE_THEME_UPDATE]: "SITE_THEME_UPDATE"
|
|
25919
|
+
[KIND_SITE_THEME_UPDATE]: "SITE_THEME_UPDATE",
|
|
25920
|
+
[KIND_SETTINGS_UPDATE]: "SETTINGS_UPDATE"
|
|
25906
25921
|
};
|
|
25907
25922
|
return kindMap[kind] ?? `UNKNOWN(0x${kind.toString(16).padStart(4, "0")})`;
|
|
25908
25923
|
}
|
|
@@ -25945,6 +25960,7 @@ __export(exports_schema, {
|
|
|
25945
25960
|
StateSnapshotDiffSchema: () => StateSnapshotDiffSchema,
|
|
25946
25961
|
SiteThemeUpdateS2CSchema: () => SiteThemeUpdateS2CSchema,
|
|
25947
25962
|
SiteThemeUpdateC2SSchema: () => SiteThemeUpdateC2SSchema,
|
|
25963
|
+
SettingsUpdateS2CSchema: () => SettingsUpdateS2CSchema,
|
|
25948
25964
|
SessionWireSchema: () => SessionWireSchema,
|
|
25949
25965
|
SITE_THEME_LIGHT: () => SITE_THEME_LIGHT,
|
|
25950
25966
|
SITE_THEME_DARK: () => SITE_THEME_DARK,
|
|
@@ -26160,6 +26176,7 @@ var TermHistorySchema = import_zorsh.b.struct({
|
|
|
26160
26176
|
selectToken: import_zorsh.b.bytes(16),
|
|
26161
26177
|
encoding: import_zorsh.b.u8(),
|
|
26162
26178
|
alternateScreen: import_zorsh.b.bool(),
|
|
26179
|
+
modes: import_zorsh.b.u8(),
|
|
26163
26180
|
data: import_zorsh.b.bytes()
|
|
26164
26181
|
});
|
|
26165
26182
|
var ClipboardWriteSchema = import_zorsh.b.struct({
|
|
@@ -26302,6 +26319,10 @@ var SiteThemeUpdateS2CSchema = import_zorsh.b.struct({
|
|
|
26302
26319
|
theme: import_zorsh.b.u8(),
|
|
26303
26320
|
serverTimestamp: import_zorsh.b.u64()
|
|
26304
26321
|
});
|
|
26322
|
+
var SettingsUpdateS2CSchema = import_zorsh.b.struct({
|
|
26323
|
+
namespace: import_zorsh.b.string(),
|
|
26324
|
+
serverTimestamp: import_zorsh.b.u64()
|
|
26325
|
+
});
|
|
26305
26326
|
// ../shared/src/ws-borsh/agent.ts
|
|
26306
26327
|
var AGENT_EVENT_SYNC = 1;
|
|
26307
26328
|
var AGENT_EVENT_STATUS = 2;
|
|
@@ -26360,6 +26381,31 @@ class WsBorshError extends Error {
|
|
|
26360
26381
|
this.name = "WsBorshError";
|
|
26361
26382
|
}
|
|
26362
26383
|
}
|
|
26384
|
+
// ../shared/src/ws-borsh/pane-modes.ts
|
|
26385
|
+
var PANE_MODE_MOUSE_STANDARD = 1 << 0;
|
|
26386
|
+
var PANE_MODE_MOUSE_BUTTON = 1 << 1;
|
|
26387
|
+
var PANE_MODE_MOUSE_ALL = 1 << 2;
|
|
26388
|
+
var PANE_MODE_MOUSE_SGR = 1 << 3;
|
|
26389
|
+
var PANE_MODE_MOUSE_UTF8 = 1 << 4;
|
|
26390
|
+
var EMPTY_PANE_MODE_FLAGS = {
|
|
26391
|
+
mouseStandard: false,
|
|
26392
|
+
mouseButton: false,
|
|
26393
|
+
mouseAll: false,
|
|
26394
|
+
mouseSgr: false,
|
|
26395
|
+
mouseUtf8: false
|
|
26396
|
+
};
|
|
26397
|
+
function encodePaneModes(flags) {
|
|
26398
|
+
return (flags.mouseStandard ? PANE_MODE_MOUSE_STANDARD : 0) | (flags.mouseButton ? PANE_MODE_MOUSE_BUTTON : 0) | (flags.mouseAll ? PANE_MODE_MOUSE_ALL : 0) | (flags.mouseSgr ? PANE_MODE_MOUSE_SGR : 0) | (flags.mouseUtf8 ? PANE_MODE_MOUSE_UTF8 : 0);
|
|
26399
|
+
}
|
|
26400
|
+
function decodePaneModes(bits) {
|
|
26401
|
+
return {
|
|
26402
|
+
mouseStandard: (bits & PANE_MODE_MOUSE_STANDARD) !== 0,
|
|
26403
|
+
mouseButton: (bits & PANE_MODE_MOUSE_BUTTON) !== 0,
|
|
26404
|
+
mouseAll: (bits & PANE_MODE_MOUSE_ALL) !== 0,
|
|
26405
|
+
mouseSgr: (bits & PANE_MODE_MOUSE_SGR) !== 0,
|
|
26406
|
+
mouseUtf8: (bits & PANE_MODE_MOUSE_UTF8) !== 0
|
|
26407
|
+
};
|
|
26408
|
+
}
|
|
26363
26409
|
// ../shared/src/ws-borsh/codec.ts
|
|
26364
26410
|
var MAGIC = new Uint8Array([84, 88]);
|
|
26365
26411
|
var CURRENT_VERSION = 1;
|
|
@@ -28369,6 +28415,7 @@ function getBooleanEnv(key, defaultValue) {
|
|
|
28369
28415
|
var config = {
|
|
28370
28416
|
masterKey: process.env.TMEX_MASTER_KEY,
|
|
28371
28417
|
port: Number.parseInt(getEnv("GATEWAY_PORT", "9663"), 10),
|
|
28418
|
+
bindHost: getEnv("TMEX_BIND_HOST", "0.0.0.0"),
|
|
28372
28419
|
baseUrl: getEnv("TMEX_BASE_URL", "http://127.0.0.1:8085"),
|
|
28373
28420
|
siteNameDefault: getEnv("TMEX_SITE_NAME", "tmex"),
|
|
28374
28421
|
databaseUrl: getEnv("DATABASE_URL", "./tmex.db"),
|
|
@@ -33403,6 +33450,7 @@ var siteSettings = sqliteTable("site_settings", {
|
|
|
33403
33450
|
sshReconnectDelaySeconds: integer("ssh_reconnect_delay_seconds").notNull(),
|
|
33404
33451
|
language: text("language").notNull().default("en_US"),
|
|
33405
33452
|
theme: text("theme").notNull().default("dark"),
|
|
33453
|
+
disabledNotificationChannels: text("disabled_notification_channels", { mode: "json" }).$type().notNull().default([]),
|
|
33406
33454
|
updatedAt: text("updated_at").notNull()
|
|
33407
33455
|
}, (table) => [
|
|
33408
33456
|
check("site_settings_singleton_check", sql`${table.id} = 1`),
|
|
@@ -33487,10 +33535,7 @@ var agentSettings = sqliteTable("agent_settings", {
|
|
|
33487
33535
|
}),
|
|
33488
33536
|
defaultModelId: text("default_model_id"),
|
|
33489
33537
|
updatedAt: text("updated_at").notNull()
|
|
33490
|
-
}, (table) => [
|
|
33491
|
-
check("agent_settings_singleton_check", sql`${table.id} = 1`),
|
|
33492
|
-
check("agent_settings_search_provider_check", sql`${table.searchProvider} in ('none', 'tavily', 'brave')`)
|
|
33493
|
-
]);
|
|
33538
|
+
}, (table) => [check("agent_settings_singleton_check", sql`${table.id} = 1`)]);
|
|
33494
33539
|
var agentSessions = sqliteTable("agent_sessions", {
|
|
33495
33540
|
id: text("id").primaryKey(),
|
|
33496
33541
|
title: text("title").notNull(),
|
|
@@ -33702,6 +33747,7 @@ function toSiteSettings(row) {
|
|
|
33702
33747
|
sshReconnectDelaySeconds: row.sshReconnectDelaySeconds,
|
|
33703
33748
|
language: normalizeLocale(row.language),
|
|
33704
33749
|
theme: row.theme,
|
|
33750
|
+
disabledNotificationChannels: Array.isArray(row.disabledNotificationChannels) ? row.disabledNotificationChannels : [],
|
|
33705
33751
|
updatedAt: row.updatedAt
|
|
33706
33752
|
};
|
|
33707
33753
|
}
|
|
@@ -33786,6 +33832,7 @@ function ensureSiteSettingsInitialized() {
|
|
|
33786
33832
|
sshReconnectMaxRetries: config.sshReconnectMaxRetriesDefault,
|
|
33787
33833
|
sshReconnectDelaySeconds: config.sshReconnectDelaySecondsDefault,
|
|
33788
33834
|
language: normalizeLocale(config.languageDefault),
|
|
33835
|
+
disabledNotificationChannels: [],
|
|
33789
33836
|
updatedAt: now
|
|
33790
33837
|
}).onConflictDoNothing({ target: siteSettings.id }).run();
|
|
33791
33838
|
}
|
|
@@ -33996,6 +34043,7 @@ function updateSiteSettings(updates) {
|
|
|
33996
34043
|
sshReconnectDelaySeconds: updates.sshReconnectDelaySeconds ?? current.sshReconnectDelaySeconds,
|
|
33997
34044
|
language: updates.language ? normalizeLocale(updates.language) : current.language,
|
|
33998
34045
|
theme: updates.theme ?? current.theme,
|
|
34046
|
+
disabledNotificationChannels: updates.disabledNotificationChannels ?? current.disabledNotificationChannels,
|
|
33999
34047
|
updatedAt: new Date().toISOString()
|
|
34000
34048
|
};
|
|
34001
34049
|
const orm = getDb();
|
|
@@ -34008,7 +34056,8 @@ function updateSiteSettings(updates) {
|
|
|
34008
34056
|
enableNotificationPush: next.enableNotificationPush,
|
|
34009
34057
|
enableBellPush: next.enableBellPush,
|
|
34010
34058
|
enableBellSound: next.enableBellSound,
|
|
34011
|
-
theme: next.theme
|
|
34059
|
+
theme: next.theme,
|
|
34060
|
+
disabledNotificationChannels: next.disabledNotificationChannels
|
|
34012
34061
|
}).where(eq(siteSettings.id, 1)).run();
|
|
34013
34062
|
siteSettingsCache = { value: next, expiresAt: Date.now() + SITE_SETTINGS_TTL_MS };
|
|
34014
34063
|
if (instance.language !== next.language) {
|
|
@@ -88882,11 +88931,18 @@ var weixinChannel = new WeixinChannel;
|
|
|
88882
88931
|
class EventNotifier {
|
|
88883
88932
|
bellThrottleMap = new Map;
|
|
88884
88933
|
notificationThrottleMap = new Map;
|
|
88885
|
-
channels =
|
|
88886
|
-
|
|
88887
|
-
|
|
88888
|
-
|
|
88889
|
-
|
|
88934
|
+
channels = new Map;
|
|
88935
|
+
constructor() {
|
|
88936
|
+
this.registerChannel(webhookChannel);
|
|
88937
|
+
this.registerChannel(telegramChannel);
|
|
88938
|
+
this.registerChannel(weixinChannel);
|
|
88939
|
+
}
|
|
88940
|
+
registerChannel(channel) {
|
|
88941
|
+
if (this.channels.has(channel.id)) {
|
|
88942
|
+
throw new Error(`notification channel already registered: ${channel.id}`);
|
|
88943
|
+
}
|
|
88944
|
+
this.channels.set(channel.id, channel);
|
|
88945
|
+
}
|
|
88890
88946
|
async notify(eventType, event) {
|
|
88891
88947
|
const fullEvent = {
|
|
88892
88948
|
...event,
|
|
@@ -88902,7 +88958,9 @@ class EventNotifier {
|
|
|
88902
88958
|
return;
|
|
88903
88959
|
}
|
|
88904
88960
|
}
|
|
88905
|
-
|
|
88961
|
+
const disabled = new Set(getSiteSettings().disabledNotificationChannels);
|
|
88962
|
+
const active = [...this.channels.values()].filter((channel) => !disabled.has(channel.id));
|
|
88963
|
+
await Promise.all(active.map((channel) => channel.notify(eventType, fullEvent)));
|
|
88906
88964
|
}
|
|
88907
88965
|
shouldPassBellThrottle(event) {
|
|
88908
88966
|
const settings = getSiteSettings();
|
|
@@ -98120,7 +98178,7 @@ function buildLocalTmuxEnv(resolvedPath, baseEnv = process.env) {
|
|
|
98120
98178
|
}
|
|
98121
98179
|
|
|
98122
98180
|
// ../../apps/gateway/src/tmux-client/capture-history.ts
|
|
98123
|
-
var PANE_SCREEN_INFO_FORMAT = "#{alternate_on} #{cursor_x} #{cursor_y} #{pane_height}";
|
|
98181
|
+
var PANE_SCREEN_INFO_FORMAT = "#{alternate_on} #{cursor_x} #{cursor_y} #{pane_height}" + " #{mouse_standard_flag} #{mouse_button_flag} #{mouse_all_flag} #{mouse_sgr_flag} #{mouse_utf8_flag}";
|
|
98124
98182
|
function parsePaneScreenInfo(stdout) {
|
|
98125
98183
|
const parts = stdout.trim().split(/\s+/);
|
|
98126
98184
|
const toInt = (value) => {
|
|
@@ -98134,7 +98192,14 @@ function parsePaneScreenInfo(stdout) {
|
|
|
98134
98192
|
alternateScreen: parts[0] === "1",
|
|
98135
98193
|
cursorX: toInt(parts[1]),
|
|
98136
98194
|
cursorY: toInt(parts[2]),
|
|
98137
|
-
paneHeight: toInt(parts[3])
|
|
98195
|
+
paneHeight: toInt(parts[3]),
|
|
98196
|
+
modes: {
|
|
98197
|
+
mouseStandard: parts[4] === "1",
|
|
98198
|
+
mouseButton: parts[5] === "1",
|
|
98199
|
+
mouseAll: parts[6] === "1",
|
|
98200
|
+
mouseSgr: parts[7] === "1",
|
|
98201
|
+
mouseUtf8: parts[8] === "1"
|
|
98202
|
+
}
|
|
98138
98203
|
};
|
|
98139
98204
|
}
|
|
98140
98205
|
var PANE_META_FORMAT = "#{pane_width} #{pane_height} #{alternate_on} #{cursor_x} #{cursor_y} #{pane_current_command}";
|
|
@@ -100235,14 +100300,25 @@ class LocalExternalTmuxConnection {
|
|
|
100235
100300
|
await this.capturePaneHistory(paneId);
|
|
100236
100301
|
await this.requestSnapshotInternal();
|
|
100237
100302
|
}
|
|
100238
|
-
async
|
|
100303
|
+
async fetchPaneHistory(paneId) {
|
|
100239
100304
|
const screenInfo = parsePaneScreenInfo((await this.runTmux(["display-message", "-p", "-t", paneId, PANE_SCREEN_INFO_FORMAT], true)).stdout);
|
|
100240
100305
|
const alternateScreen = screenInfo.alternateScreen;
|
|
100241
100306
|
const normal = (await this.runTmux(["capture-pane", "-t", paneId, "-S", "-", "-E", "-", "-e", "-J", "-N", "-p"], true)).stdout;
|
|
100242
100307
|
const alternate = (await this.runTmux(["capture-pane", "-t", paneId, "-a", "-S", "-", "-E", "-", "-e", "-J", "-N", "-p", "-q"], true)).stdout;
|
|
100243
100308
|
const history = alternateScreen ? hasRenderableTerminalContent(normal) ? normal : alternate : normal || alternate;
|
|
100244
|
-
if (history) {
|
|
100245
|
-
|
|
100309
|
+
if (!history) {
|
|
100310
|
+
return null;
|
|
100311
|
+
}
|
|
100312
|
+
return {
|
|
100313
|
+
data: appendCursorRestore(history, screenInfo),
|
|
100314
|
+
alternateScreen,
|
|
100315
|
+
modes: encodePaneModes(screenInfo.modes)
|
|
100316
|
+
};
|
|
100317
|
+
}
|
|
100318
|
+
async capturePaneHistory(paneId) {
|
|
100319
|
+
const captured = await this.fetchPaneHistory(paneId);
|
|
100320
|
+
if (captured) {
|
|
100321
|
+
this.callbacks.onTerminalHistory(paneId, captured.data, captured.alternateScreen, captured.modes);
|
|
100246
100322
|
}
|
|
100247
100323
|
}
|
|
100248
100324
|
async requestSnapshotInternal() {
|
|
@@ -101825,14 +101901,25 @@ class SshExternalTmuxConnection {
|
|
|
101825
101901
|
await this.capturePaneHistory(paneId);
|
|
101826
101902
|
await this.requestSnapshotInternal();
|
|
101827
101903
|
}
|
|
101828
|
-
async
|
|
101904
|
+
async fetchPaneHistory(paneId) {
|
|
101829
101905
|
const screenInfo = parsePaneScreenInfo((await this.runTmux(["display-message", "-p", "-t", paneId, PANE_SCREEN_INFO_FORMAT], true)).stdout);
|
|
101830
101906
|
const alternateScreen = screenInfo.alternateScreen;
|
|
101831
101907
|
const normal = (await this.runTmux(["capture-pane", "-t", paneId, "-S", "-", "-E", "-", "-e", "-J", "-N", "-p"], true, 30000)).stdout;
|
|
101832
101908
|
const alternate = (await this.runTmux(["capture-pane", "-t", paneId, "-a", "-S", "-", "-E", "-", "-e", "-J", "-N", "-p", "-q"], true, 30000)).stdout;
|
|
101833
101909
|
const history = alternateScreen ? hasRenderableTerminalContent2(normal) ? normal : alternate : normal || alternate;
|
|
101834
|
-
if (history) {
|
|
101835
|
-
|
|
101910
|
+
if (!history) {
|
|
101911
|
+
return null;
|
|
101912
|
+
}
|
|
101913
|
+
return {
|
|
101914
|
+
data: appendCursorRestore(history, screenInfo),
|
|
101915
|
+
alternateScreen,
|
|
101916
|
+
modes: encodePaneModes(screenInfo.modes)
|
|
101917
|
+
};
|
|
101918
|
+
}
|
|
101919
|
+
async capturePaneHistory(paneId) {
|
|
101920
|
+
const captured = await this.fetchPaneHistory(paneId);
|
|
101921
|
+
if (captured) {
|
|
101922
|
+
this.callbacks.onTerminalHistory(paneId, captured.data, captured.alternateScreen, captured.modes);
|
|
101836
101923
|
}
|
|
101837
101924
|
}
|
|
101838
101925
|
async requestSnapshotInternal() {
|
|
@@ -102269,8 +102356,8 @@ class DeviceSessionRuntime {
|
|
|
102269
102356
|
onTerminalOutput: (paneId, data) => {
|
|
102270
102357
|
this.broadcast((listener) => listener.onTerminalOutput?.(paneId, data));
|
|
102271
102358
|
},
|
|
102272
|
-
onTerminalHistory: (paneId, data, alternateScreen) => {
|
|
102273
|
-
this.broadcast((listener) => listener.onTerminalHistory?.(paneId, data, alternateScreen));
|
|
102359
|
+
onTerminalHistory: (paneId, data, alternateScreen, modes) => {
|
|
102360
|
+
this.broadcast((listener) => listener.onTerminalHistory?.(paneId, data, alternateScreen, modes));
|
|
102274
102361
|
},
|
|
102275
102362
|
onPromptMarker: (paneId, marker24) => {
|
|
102276
102363
|
this.broadcast((listener) => listener.onPromptMarker?.(paneId, marker24));
|
|
@@ -102384,6 +102471,9 @@ class DeviceSessionRuntime {
|
|
|
102384
102471
|
async requestPaneHistory(paneId) {
|
|
102385
102472
|
return this.connection.requestPaneHistory(paneId);
|
|
102386
102473
|
}
|
|
102474
|
+
async fetchPaneHistory(paneId) {
|
|
102475
|
+
return this.connection.fetchPaneHistory(paneId);
|
|
102476
|
+
}
|
|
102387
102477
|
renameWindow(windowId, name24) {
|
|
102388
102478
|
this.connection.renameWindow(windowId, name24);
|
|
102389
102479
|
}
|
|
@@ -103589,68 +103679,98 @@ function validateFetchUrl(rawUrl) {
|
|
|
103589
103679
|
}
|
|
103590
103680
|
return { url: url2 };
|
|
103591
103681
|
}
|
|
103592
|
-
|
|
103593
|
-
|
|
103594
|
-
|
|
103595
|
-
|
|
103596
|
-
|
|
103597
|
-
|
|
103598
|
-
|
|
103599
|
-
|
|
103600
|
-
|
|
103601
|
-
|
|
103602
|
-
|
|
103603
|
-
|
|
103604
|
-
|
|
103605
|
-
|
|
103606
|
-
|
|
103607
|
-
|
|
103682
|
+
var searchProviderRegistry = new Map;
|
|
103683
|
+
function registerSearchProvider(provider) {
|
|
103684
|
+
if (searchProviderRegistry.has(provider.id)) {
|
|
103685
|
+
throw new Error(`search provider already registered: ${provider.id}`);
|
|
103686
|
+
}
|
|
103687
|
+
searchProviderRegistry.set(provider.id, provider);
|
|
103688
|
+
}
|
|
103689
|
+
function getSearchProviders() {
|
|
103690
|
+
return [...searchProviderRegistry.values()];
|
|
103691
|
+
}
|
|
103692
|
+
function getSearchProvider(id) {
|
|
103693
|
+
return searchProviderRegistry.get(id);
|
|
103694
|
+
}
|
|
103695
|
+
var TAVILY_DEFAULT_ENDPOINT = "https://api.tavily.com/search";
|
|
103696
|
+
var BRAVE_DEFAULT_ENDPOINT = "https://api.search.brave.com/res/v1/web/search";
|
|
103697
|
+
var tavilyProvider = {
|
|
103698
|
+
id: "tavily",
|
|
103699
|
+
label: "Tavily",
|
|
103700
|
+
isConfigured: (settings) => Boolean(settings.tavilyApiKeyEnc),
|
|
103701
|
+
async search(query, settings, deps) {
|
|
103702
|
+
const apiKey = await decrypt(settings.tavilyApiKeyEnc ?? "");
|
|
103703
|
+
const fetchImpl = deps?.fetchImpl ?? fetch;
|
|
103704
|
+
const endpoint = deps?.endpoint ?? TAVILY_DEFAULT_ENDPOINT;
|
|
103705
|
+
const response = await fetchImpl(endpoint, {
|
|
103706
|
+
method: "POST",
|
|
103707
|
+
headers: {
|
|
103708
|
+
"Content-Type": "application/json",
|
|
103709
|
+
Authorization: `Bearer ${apiKey}`
|
|
103710
|
+
},
|
|
103711
|
+
body: JSON.stringify({
|
|
103712
|
+
api_key: apiKey,
|
|
103713
|
+
query,
|
|
103714
|
+
max_results: WEB_SEARCH_MAX_RESULTS
|
|
103715
|
+
}),
|
|
103716
|
+
signal: AbortSignal.timeout(FETCH_URL_TIMEOUT_MS)
|
|
103717
|
+
});
|
|
103718
|
+
if (!response.ok) {
|
|
103719
|
+
throw new Error(`Tavily search failed: HTTP ${response.status}`);
|
|
103720
|
+
}
|
|
103721
|
+
const payload = await response.json();
|
|
103722
|
+
return (payload.results ?? []).map((item) => ({
|
|
103723
|
+
title: item.title ?? "",
|
|
103724
|
+
url: item.url ?? "",
|
|
103725
|
+
snippet: item.content ?? ""
|
|
103726
|
+
}));
|
|
103608
103727
|
}
|
|
103609
|
-
|
|
103610
|
-
|
|
103611
|
-
|
|
103612
|
-
|
|
103613
|
-
|
|
103614
|
-
|
|
103615
|
-
|
|
103616
|
-
|
|
103617
|
-
|
|
103618
|
-
|
|
103619
|
-
|
|
103620
|
-
|
|
103621
|
-
|
|
103622
|
-
|
|
103623
|
-
|
|
103624
|
-
|
|
103625
|
-
|
|
103626
|
-
|
|
103627
|
-
|
|
103628
|
-
|
|
103728
|
+
};
|
|
103729
|
+
var braveProvider = {
|
|
103730
|
+
id: "brave",
|
|
103731
|
+
label: "Brave",
|
|
103732
|
+
isConfigured: (settings) => Boolean(settings.braveApiKeyEnc),
|
|
103733
|
+
async search(query, settings, deps) {
|
|
103734
|
+
const apiKey = await decrypt(settings.braveApiKeyEnc ?? "");
|
|
103735
|
+
const fetchImpl = deps?.fetchImpl ?? fetch;
|
|
103736
|
+
const url2 = new URL(deps?.endpoint ?? BRAVE_DEFAULT_ENDPOINT);
|
|
103737
|
+
url2.searchParams.set("q", query);
|
|
103738
|
+
url2.searchParams.set("count", String(WEB_SEARCH_MAX_RESULTS));
|
|
103739
|
+
const response = await fetchImpl(url2.toString(), {
|
|
103740
|
+
headers: {
|
|
103741
|
+
Accept: "application/json",
|
|
103742
|
+
"X-Subscription-Token": apiKey
|
|
103743
|
+
},
|
|
103744
|
+
signal: AbortSignal.timeout(FETCH_URL_TIMEOUT_MS)
|
|
103745
|
+
});
|
|
103746
|
+
if (!response.ok) {
|
|
103747
|
+
throw new Error(`Brave search failed: HTTP ${response.status}`);
|
|
103748
|
+
}
|
|
103749
|
+
const payload = await response.json();
|
|
103750
|
+
return (payload.web?.results ?? []).map((item) => ({
|
|
103751
|
+
title: item.title ?? "",
|
|
103752
|
+
url: item.url ?? "",
|
|
103753
|
+
snippet: item.description ?? ""
|
|
103754
|
+
}));
|
|
103629
103755
|
}
|
|
103630
|
-
|
|
103631
|
-
|
|
103632
|
-
|
|
103633
|
-
url: item.url ?? "",
|
|
103634
|
-
snippet: item.description ?? ""
|
|
103635
|
-
}));
|
|
103636
|
-
}
|
|
103756
|
+
};
|
|
103757
|
+
registerSearchProvider(tavilyProvider);
|
|
103758
|
+
registerSearchProvider(braveProvider);
|
|
103637
103759
|
async function createWebSearchTool(options = {}) {
|
|
103638
103760
|
const settings = options.settings ?? getAgentSettings();
|
|
103639
|
-
|
|
103640
|
-
|
|
103641
|
-
|
|
103642
|
-
|
|
103643
|
-
if (
|
|
103644
|
-
const apiKey = await decrypt(settings.tavilyApiKeyEnc);
|
|
103645
|
-
search = (query) => searchTavily(apiKey, query, { fetchImpl, tavilyEndpoint });
|
|
103646
|
-
} else if (settings.searchProvider === "brave" && settings.braveApiKeyEnc) {
|
|
103647
|
-
const apiKey = await decrypt(settings.braveApiKeyEnc);
|
|
103648
|
-
search = (query) => searchBrave(apiKey, query, { fetchImpl, braveEndpoint });
|
|
103649
|
-
}
|
|
103650
|
-
if (!search) {
|
|
103761
|
+
if (settings.searchProvider === "none") {
|
|
103762
|
+
return null;
|
|
103763
|
+
}
|
|
103764
|
+
const provider = searchProviderRegistry.get(settings.searchProvider);
|
|
103765
|
+
if (!provider || !provider.isConfigured(settings)) {
|
|
103651
103766
|
return null;
|
|
103652
103767
|
}
|
|
103653
|
-
const
|
|
103768
|
+
const endpoint = options.endpointOverrides?.[provider.id] ?? (provider.id === "tavily" ? options.tavilyEndpoint : provider.id === "brave" ? options.braveEndpoint : undefined);
|
|
103769
|
+
const deps = {
|
|
103770
|
+
fetchImpl: options.fetchImpl ?? fetch,
|
|
103771
|
+
endpoint
|
|
103772
|
+
};
|
|
103773
|
+
const searchFn = (query) => provider.search(query, settings, deps);
|
|
103654
103774
|
return tool({
|
|
103655
103775
|
description: "Search the web. Returns a JSON array of results with title, url and snippet.",
|
|
103656
103776
|
inputSchema: exports_external.object({
|
|
@@ -105414,6 +105534,22 @@ class PushSupervisor {
|
|
|
105414
105534
|
}
|
|
105415
105535
|
var pushSupervisor = new PushSupervisor;
|
|
105416
105536
|
|
|
105537
|
+
// ../../apps/gateway/src/settings/broadcaster.ts
|
|
105538
|
+
var broadcaster = null;
|
|
105539
|
+
function registerSettingsBroadcaster(fn) {
|
|
105540
|
+
broadcaster = fn;
|
|
105541
|
+
}
|
|
105542
|
+
function broadcastSettingsUpdate(namespace) {
|
|
105543
|
+
broadcaster?.(namespace);
|
|
105544
|
+
}
|
|
105545
|
+
var treeOverlayBridge = null;
|
|
105546
|
+
function registerTreeOverlayBridge(bridge) {
|
|
105547
|
+
treeOverlayBridge = bridge;
|
|
105548
|
+
}
|
|
105549
|
+
function getTreeOverlayBridge() {
|
|
105550
|
+
return treeOverlayBridge;
|
|
105551
|
+
}
|
|
105552
|
+
|
|
105417
105553
|
// ../../apps/gateway/src/api/agent.ts
|
|
105418
105554
|
var WRITE_MODES = ["confirm", "auto"];
|
|
105419
105555
|
var MAX_STEPS_MIN = 1;
|
|
@@ -105953,6 +106089,126 @@ function json3(data, status = 200) {
|
|
|
105953
106089
|
});
|
|
105954
106090
|
}
|
|
105955
106091
|
|
|
106092
|
+
// ../../apps/gateway/src/capabilities.ts
|
|
106093
|
+
var API_VERSION = 1;
|
|
106094
|
+
var GATEWAY_CAPABILITIES = ["tmex-ws-borsh-v1", "tmex-agent-v1", "tmex-split-v1"];
|
|
106095
|
+
|
|
106096
|
+
// ../../apps/gateway/src/system/version.ts
|
|
106097
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
106098
|
+
import { resolve as resolve4 } from "path";
|
|
106099
|
+
|
|
106100
|
+
// ../../apps/gateway/src/system/install-info.ts
|
|
106101
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
106102
|
+
import { resolve as resolve3 } from "path";
|
|
106103
|
+
function resolveInstallDir() {
|
|
106104
|
+
const feDist = process.env.TMEX_FE_DIST_DIR;
|
|
106105
|
+
if (feDist) {
|
|
106106
|
+
return resolve3(feDist, "..", "..");
|
|
106107
|
+
}
|
|
106108
|
+
return process.cwd();
|
|
106109
|
+
}
|
|
106110
|
+
function readInstallMeta() {
|
|
106111
|
+
const metaPath = resolve3(resolveInstallDir(), "install-meta.json");
|
|
106112
|
+
try {
|
|
106113
|
+
if (!existsSync4(metaPath))
|
|
106114
|
+
return null;
|
|
106115
|
+
return JSON.parse(readFileSync3(metaPath, "utf8"));
|
|
106116
|
+
} catch {
|
|
106117
|
+
return null;
|
|
106118
|
+
}
|
|
106119
|
+
}
|
|
106120
|
+
function deploymentFromPlatform(platform) {
|
|
106121
|
+
if (platform === "darwin")
|
|
106122
|
+
return "launchd";
|
|
106123
|
+
if (platform === "linux")
|
|
106124
|
+
return "systemd";
|
|
106125
|
+
return "none";
|
|
106126
|
+
}
|
|
106127
|
+
function getInstallInfo() {
|
|
106128
|
+
if (!config.isProd) {
|
|
106129
|
+
return {
|
|
106130
|
+
installedViaCli: false,
|
|
106131
|
+
deployment: "none",
|
|
106132
|
+
installDir: null,
|
|
106133
|
+
serviceName: null,
|
|
106134
|
+
cliVersion: null,
|
|
106135
|
+
bunPath: null
|
|
106136
|
+
};
|
|
106137
|
+
}
|
|
106138
|
+
const meta3 = readInstallMeta();
|
|
106139
|
+
if (!meta3) {
|
|
106140
|
+
return {
|
|
106141
|
+
installedViaCli: false,
|
|
106142
|
+
deployment: "none",
|
|
106143
|
+
installDir: resolveInstallDir(),
|
|
106144
|
+
serviceName: null,
|
|
106145
|
+
cliVersion: null,
|
|
106146
|
+
bunPath: null
|
|
106147
|
+
};
|
|
106148
|
+
}
|
|
106149
|
+
return {
|
|
106150
|
+
installedViaCli: true,
|
|
106151
|
+
deployment: deploymentFromPlatform(meta3.platform ?? process.platform),
|
|
106152
|
+
installDir: meta3.installDir ?? resolveInstallDir(),
|
|
106153
|
+
serviceName: meta3.serviceName ?? null,
|
|
106154
|
+
cliVersion: meta3.cliVersion ?? null,
|
|
106155
|
+
bunPath: meta3.bunPath ?? null
|
|
106156
|
+
};
|
|
106157
|
+
}
|
|
106158
|
+
|
|
106159
|
+
// ../../apps/gateway/src/system/version.ts
|
|
106160
|
+
var cachedBase;
|
|
106161
|
+
function readRepoPackageVersion() {
|
|
106162
|
+
const dir2 = import.meta.dir;
|
|
106163
|
+
if (!dir2)
|
|
106164
|
+
return null;
|
|
106165
|
+
const path = resolve4(dir2, "../../../../packages/app/package.json");
|
|
106166
|
+
try {
|
|
106167
|
+
if (!existsSync5(path))
|
|
106168
|
+
return null;
|
|
106169
|
+
const pkg = JSON.parse(readFileSync4(path, "utf8"));
|
|
106170
|
+
return pkg.version ?? null;
|
|
106171
|
+
} catch {
|
|
106172
|
+
return null;
|
|
106173
|
+
}
|
|
106174
|
+
}
|
|
106175
|
+
function getBaseVersion() {
|
|
106176
|
+
if (cachedBase !== undefined)
|
|
106177
|
+
return cachedBase;
|
|
106178
|
+
let base = null;
|
|
106179
|
+
if ("0.17.0") {
|
|
106180
|
+
base = "0.17.0";
|
|
106181
|
+
}
|
|
106182
|
+
if (!base && config.isProd) {
|
|
106183
|
+
base = readInstallMeta()?.cliVersion ?? null;
|
|
106184
|
+
}
|
|
106185
|
+
if (!base) {
|
|
106186
|
+
base = readRepoPackageVersion();
|
|
106187
|
+
}
|
|
106188
|
+
cachedBase = base ?? "unknown";
|
|
106189
|
+
return cachedBase;
|
|
106190
|
+
}
|
|
106191
|
+
function getDisplayVersion() {
|
|
106192
|
+
return formatDisplayVersion(getBaseVersion(), config.isProd);
|
|
106193
|
+
}
|
|
106194
|
+
|
|
106195
|
+
// ../../apps/gateway/src/api/capabilities.ts
|
|
106196
|
+
function handleCapabilitiesApiRequest(req, path) {
|
|
106197
|
+
if (path === "/api/capabilities" && req.method === "GET") {
|
|
106198
|
+
return handleGetCapabilities();
|
|
106199
|
+
}
|
|
106200
|
+
return null;
|
|
106201
|
+
}
|
|
106202
|
+
function handleGetCapabilities() {
|
|
106203
|
+
return new Response(JSON.stringify({
|
|
106204
|
+
serverImpl: "tmex-gateway",
|
|
106205
|
+
serverVersion: getDisplayVersion(),
|
|
106206
|
+
apiVersion: API_VERSION,
|
|
106207
|
+
wsProtocolVersion: exports_ws_borsh.CURRENT_VERSION,
|
|
106208
|
+
capabilities: [...GATEWAY_CAPABILITIES]
|
|
106209
|
+
}), { status: 200, headers: { "Content-Type": "application/json" } });
|
|
106210
|
+
}
|
|
106211
|
+
|
|
105956
106212
|
// ../../apps/gateway/src/db/file-roots.ts
|
|
105957
106213
|
function getFileRoots() {
|
|
105958
106214
|
const orm = getDb();
|
|
@@ -106000,7 +106256,7 @@ function deleteFileRoot(id) {
|
|
|
106000
106256
|
}
|
|
106001
106257
|
|
|
106002
106258
|
// ../../apps/gateway/src/files/device-storage.ts
|
|
106003
|
-
import { mkdtempSync as mkdtempSync2, readFileSync as
|
|
106259
|
+
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync5, realpathSync, rmSync as rmSync2, statSync } from "fs";
|
|
106004
106260
|
import { tmpdir as tmpdir2 } from "os";
|
|
106005
106261
|
import { join as join5 } from "path";
|
|
106006
106262
|
|
|
@@ -106201,10 +106457,10 @@ function acquireGlobalSlot() {
|
|
|
106201
106457
|
active += 1;
|
|
106202
106458
|
return Promise.resolve();
|
|
106203
106459
|
}
|
|
106204
|
-
return new Promise((
|
|
106460
|
+
return new Promise((resolve5) => {
|
|
106205
106461
|
globalWaiters.push(() => {
|
|
106206
106462
|
active += 1;
|
|
106207
|
-
|
|
106463
|
+
resolve5();
|
|
106208
106464
|
});
|
|
106209
106465
|
});
|
|
106210
106466
|
}
|
|
@@ -106812,7 +107068,7 @@ async function copyToBuffer(spec, normPath) {
|
|
|
106812
107068
|
}
|
|
106813
107069
|
if (res.exitCode !== 0)
|
|
106814
107070
|
return fail(classifyRsyncFailure(res.exitCode, res.stderr), res.stderr);
|
|
106815
|
-
return ok(
|
|
107071
|
+
return ok(readFileSync5(dest));
|
|
106816
107072
|
} finally {
|
|
106817
107073
|
try {
|
|
106818
107074
|
rmSync2(dir2, { recursive: true, force: true });
|
|
@@ -107209,6 +107465,7 @@ async function handleCreateRoot(req) {
|
|
|
107209
107465
|
return json4({ error: t2("apiError.fileRootDuplicate") }, 400);
|
|
107210
107466
|
}
|
|
107211
107467
|
const record2 = createFileRoot({ deviceId, path, enabled: body.enabled ?? true });
|
|
107468
|
+
broadcastSettingsUpdate("file-roots");
|
|
107212
107469
|
return json4({ root: toRootDto(record2) }, 201);
|
|
107213
107470
|
}
|
|
107214
107471
|
async function handleUpdateRoot(req, id) {
|
|
@@ -107244,12 +107501,14 @@ async function handleUpdateRoot(req, id) {
|
|
|
107244
107501
|
const updated = updateFileRoot(id, updates);
|
|
107245
107502
|
if (!updated)
|
|
107246
107503
|
return json4({ error: t2("apiError.notFound") }, 404);
|
|
107504
|
+
broadcastSettingsUpdate("file-roots");
|
|
107247
107505
|
return json4({ root: toRootDto(updated) });
|
|
107248
107506
|
}
|
|
107249
107507
|
function handleDeleteRoot(id) {
|
|
107250
107508
|
const okDelete = deleteFileRoot(id);
|
|
107251
107509
|
if (!okDelete)
|
|
107252
107510
|
return json4({ error: t2("apiError.notFound") }, 404);
|
|
107511
|
+
broadcastSettingsUpdate("file-roots");
|
|
107253
107512
|
return json4({ success: true });
|
|
107254
107513
|
}
|
|
107255
107514
|
async function handleList(url2) {
|
|
@@ -107569,7 +107828,19 @@ function handleFilesApiRequest(req, path) {
|
|
|
107569
107828
|
|
|
107570
107829
|
// ../../apps/gateway/src/api/llm.ts
|
|
107571
107830
|
var PROTOCOLS = ["openai-chat", "openai-responses"];
|
|
107572
|
-
|
|
107831
|
+
function isValidSearchProvider(value) {
|
|
107832
|
+
if (typeof value !== "string") {
|
|
107833
|
+
return false;
|
|
107834
|
+
}
|
|
107835
|
+
return value === "none" || getSearchProvider(value) !== undefined;
|
|
107836
|
+
}
|
|
107837
|
+
function toSearchProviderInfos(settings) {
|
|
107838
|
+
return getSearchProviders().map((provider) => ({
|
|
107839
|
+
id: provider.id,
|
|
107840
|
+
label: provider.label,
|
|
107841
|
+
isConfigured: provider.isConfigured(settings)
|
|
107842
|
+
}));
|
|
107843
|
+
}
|
|
107573
107844
|
function handleLlmApiRequest(req, path) {
|
|
107574
107845
|
if (path === "/api/llm/providers" && req.method === "GET") {
|
|
107575
107846
|
return handleListProviders();
|
|
@@ -107693,6 +107964,7 @@ async function handleCreateProvider(req) {
|
|
|
107693
107964
|
apiKeyEnc: await encrypt(apiKey),
|
|
107694
107965
|
enabled: body.enabled ?? true
|
|
107695
107966
|
});
|
|
107967
|
+
broadcastSettingsUpdate("llm");
|
|
107696
107968
|
const { provider, modelsError } = await refreshModelsCache(created);
|
|
107697
107969
|
return json5({ provider: toProviderDto(provider), ...modelsError ? { modelsError } : {} }, 201);
|
|
107698
107970
|
}
|
|
@@ -107757,6 +108029,7 @@ async function handleUpdateProvider(req, id) {
|
|
|
107757
108029
|
if (!provider) {
|
|
107758
108030
|
return json5({ error: t2("apiError.llmProviderNotFound") }, 404);
|
|
107759
108031
|
}
|
|
108032
|
+
broadcastSettingsUpdate("llm");
|
|
107760
108033
|
const credentialsChanged = updates.baseUrl !== undefined && updates.baseUrl !== existing.baseUrl || updates.apiKeyEnc !== undefined;
|
|
107761
108034
|
let modelsError;
|
|
107762
108035
|
if (credentialsChanged) {
|
|
@@ -107772,6 +108045,7 @@ async function handleDeleteProvider(id) {
|
|
|
107772
108045
|
return json5({ error: t2("apiError.llmProviderNotFound") }, 404);
|
|
107773
108046
|
}
|
|
107774
108047
|
deleteLlmProvider(id);
|
|
108048
|
+
broadcastSettingsUpdate("llm");
|
|
107775
108049
|
return json5({ success: true });
|
|
107776
108050
|
}
|
|
107777
108051
|
async function handleRefreshProviderModels(id) {
|
|
@@ -107786,7 +108060,11 @@ async function handleRefreshProviderModels(id) {
|
|
|
107786
108060
|
return json5({ models });
|
|
107787
108061
|
}
|
|
107788
108062
|
async function handleGetSettings() {
|
|
107789
|
-
|
|
108063
|
+
const record2 = getAgentSettings();
|
|
108064
|
+
return json5({
|
|
108065
|
+
settings: toSettingsDto(record2),
|
|
108066
|
+
searchProviders: toSearchProviderInfos(record2)
|
|
108067
|
+
});
|
|
107790
108068
|
}
|
|
107791
108069
|
async function handleUpdateSettings(req) {
|
|
107792
108070
|
const raw = await readJsonObjectBody2(req);
|
|
@@ -107796,7 +108074,7 @@ async function handleUpdateSettings(req) {
|
|
|
107796
108074
|
const body = raw;
|
|
107797
108075
|
const updates = {};
|
|
107798
108076
|
if (body.searchProvider !== undefined) {
|
|
107799
|
-
if (!
|
|
108077
|
+
if (!isValidSearchProvider(body.searchProvider)) {
|
|
107800
108078
|
return json5({ error: t2("apiError.llmSearchProviderInvalid") }, 400);
|
|
107801
108079
|
}
|
|
107802
108080
|
updates.searchProvider = body.searchProvider;
|
|
@@ -107831,6 +108109,7 @@ async function handleUpdateSettings(req) {
|
|
|
107831
108109
|
updates.braveApiKeyEnc = value ? await encrypt(value) : null;
|
|
107832
108110
|
}
|
|
107833
108111
|
const settings = updateAgentSettings(updates);
|
|
108112
|
+
broadcastSettingsUpdate("llm");
|
|
107834
108113
|
return json5({ settings: toSettingsDto(settings) });
|
|
107835
108114
|
}
|
|
107836
108115
|
function json5(data, status = 200) {
|
|
@@ -107841,103 +108120,6 @@ function json5(data, status = 200) {
|
|
|
107841
108120
|
}
|
|
107842
108121
|
});
|
|
107843
108122
|
}
|
|
107844
|
-
|
|
107845
|
-
// ../../apps/gateway/src/system/install-info.ts
|
|
107846
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
107847
|
-
import { resolve as resolve3 } from "path";
|
|
107848
|
-
function resolveInstallDir() {
|
|
107849
|
-
const feDist = process.env.TMEX_FE_DIST_DIR;
|
|
107850
|
-
if (feDist) {
|
|
107851
|
-
return resolve3(feDist, "..", "..");
|
|
107852
|
-
}
|
|
107853
|
-
return process.cwd();
|
|
107854
|
-
}
|
|
107855
|
-
function readInstallMeta() {
|
|
107856
|
-
const metaPath = resolve3(resolveInstallDir(), "install-meta.json");
|
|
107857
|
-
try {
|
|
107858
|
-
if (!existsSync4(metaPath))
|
|
107859
|
-
return null;
|
|
107860
|
-
return JSON.parse(readFileSync4(metaPath, "utf8"));
|
|
107861
|
-
} catch {
|
|
107862
|
-
return null;
|
|
107863
|
-
}
|
|
107864
|
-
}
|
|
107865
|
-
function deploymentFromPlatform(platform) {
|
|
107866
|
-
if (platform === "darwin")
|
|
107867
|
-
return "launchd";
|
|
107868
|
-
if (platform === "linux")
|
|
107869
|
-
return "systemd";
|
|
107870
|
-
return "none";
|
|
107871
|
-
}
|
|
107872
|
-
function getInstallInfo() {
|
|
107873
|
-
if (!config.isProd) {
|
|
107874
|
-
return {
|
|
107875
|
-
installedViaCli: false,
|
|
107876
|
-
deployment: "none",
|
|
107877
|
-
installDir: null,
|
|
107878
|
-
serviceName: null,
|
|
107879
|
-
cliVersion: null,
|
|
107880
|
-
bunPath: null
|
|
107881
|
-
};
|
|
107882
|
-
}
|
|
107883
|
-
const meta3 = readInstallMeta();
|
|
107884
|
-
if (!meta3) {
|
|
107885
|
-
return {
|
|
107886
|
-
installedViaCli: false,
|
|
107887
|
-
deployment: "none",
|
|
107888
|
-
installDir: resolveInstallDir(),
|
|
107889
|
-
serviceName: null,
|
|
107890
|
-
cliVersion: null,
|
|
107891
|
-
bunPath: null
|
|
107892
|
-
};
|
|
107893
|
-
}
|
|
107894
|
-
return {
|
|
107895
|
-
installedViaCli: true,
|
|
107896
|
-
deployment: deploymentFromPlatform(meta3.platform ?? process.platform),
|
|
107897
|
-
installDir: meta3.installDir ?? resolveInstallDir(),
|
|
107898
|
-
serviceName: meta3.serviceName ?? null,
|
|
107899
|
-
cliVersion: meta3.cliVersion ?? null,
|
|
107900
|
-
bunPath: meta3.bunPath ?? null
|
|
107901
|
-
};
|
|
107902
|
-
}
|
|
107903
|
-
|
|
107904
|
-
// ../../apps/gateway/src/system/version.ts
|
|
107905
|
-
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
107906
|
-
import { resolve as resolve4 } from "path";
|
|
107907
|
-
var cachedBase;
|
|
107908
|
-
function readRepoPackageVersion() {
|
|
107909
|
-
const dir2 = import.meta.dir;
|
|
107910
|
-
if (!dir2)
|
|
107911
|
-
return null;
|
|
107912
|
-
const path = resolve4(dir2, "../../../../packages/app/package.json");
|
|
107913
|
-
try {
|
|
107914
|
-
if (!existsSync5(path))
|
|
107915
|
-
return null;
|
|
107916
|
-
const pkg = JSON.parse(readFileSync5(path, "utf8"));
|
|
107917
|
-
return pkg.version ?? null;
|
|
107918
|
-
} catch {
|
|
107919
|
-
return null;
|
|
107920
|
-
}
|
|
107921
|
-
}
|
|
107922
|
-
function getBaseVersion() {
|
|
107923
|
-
if (cachedBase !== undefined)
|
|
107924
|
-
return cachedBase;
|
|
107925
|
-
let base = null;
|
|
107926
|
-
if ("0.16.4") {
|
|
107927
|
-
base = "0.16.4";
|
|
107928
|
-
}
|
|
107929
|
-
if (!base && config.isProd) {
|
|
107930
|
-
base = readInstallMeta()?.cliVersion ?? null;
|
|
107931
|
-
}
|
|
107932
|
-
if (!base) {
|
|
107933
|
-
base = readRepoPackageVersion();
|
|
107934
|
-
}
|
|
107935
|
-
cachedBase = base ?? "unknown";
|
|
107936
|
-
return cachedBase;
|
|
107937
|
-
}
|
|
107938
|
-
function getDisplayVersion() {
|
|
107939
|
-
return formatDisplayVersion(getBaseVersion(), config.isProd);
|
|
107940
|
-
}
|
|
107941
108123
|
// ../../apps/gateway/src/system/semver.ts
|
|
107942
108124
|
function parse5(input) {
|
|
107943
108125
|
const match = input.trim().match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
|
|
@@ -108346,6 +108528,7 @@ async function handleUpdateTheme(req) {
|
|
|
108346
108528
|
updateSiteSettings({ theme });
|
|
108347
108529
|
broadcastThemeChange(theme);
|
|
108348
108530
|
broadcastSiteThemeUpdateS2C(theme);
|
|
108531
|
+
broadcastSettingsUpdate("theme");
|
|
108349
108532
|
return json8({ theme, serverTimestamp });
|
|
108350
108533
|
}
|
|
108351
108534
|
function json8(data, status = 200) {
|
|
@@ -108355,6 +108538,126 @@ function json8(data, status = 200) {
|
|
|
108355
108538
|
});
|
|
108356
108539
|
}
|
|
108357
108540
|
|
|
108541
|
+
// ../../apps/gateway/src/api/tree-order.ts
|
|
108542
|
+
function handleTreeOrderApiRequest(req, path) {
|
|
108543
|
+
const treeOrderMatch = path.match(/^\/api\/devices\/([^/]+)\/tree-order$/);
|
|
108544
|
+
if (treeOrderMatch && req.method === "GET") {
|
|
108545
|
+
return handleGetTreeOrder(decodeURIComponent(treeOrderMatch[1]));
|
|
108546
|
+
}
|
|
108547
|
+
if (treeOrderMatch && req.method === "PUT") {
|
|
108548
|
+
return handlePutTreeOrder(req, decodeURIComponent(treeOrderMatch[1]));
|
|
108549
|
+
}
|
|
108550
|
+
const windowNameMatch = path.match(/^\/api\/devices\/([^/]+)\/windows\/([^/]+)\/name$/);
|
|
108551
|
+
if (windowNameMatch && req.method === "PATCH") {
|
|
108552
|
+
return handlePatchWindowName(req, decodeURIComponent(windowNameMatch[1]), decodeURIComponent(windowNameMatch[2]));
|
|
108553
|
+
}
|
|
108554
|
+
const paneNameMatch = path.match(/^\/api\/devices\/([^/]+)\/panes\/([^/]+)\/name$/);
|
|
108555
|
+
if (paneNameMatch && req.method === "PATCH") {
|
|
108556
|
+
return handlePatchPaneName(req, decodeURIComponent(paneNameMatch[1]), decodeURIComponent(paneNameMatch[2]));
|
|
108557
|
+
}
|
|
108558
|
+
return null;
|
|
108559
|
+
}
|
|
108560
|
+
function isStringArray(value) {
|
|
108561
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
108562
|
+
}
|
|
108563
|
+
async function handleGetTreeOrder(deviceId) {
|
|
108564
|
+
if (!getDeviceById(deviceId)) {
|
|
108565
|
+
return json9({ error: t2("apiError.deviceNotFound") }, 404);
|
|
108566
|
+
}
|
|
108567
|
+
const order = getDeviceTreeOrder(deviceId);
|
|
108568
|
+
const names = getTreeOverlayBridge()?.getCustomNames(deviceId) ?? { windows: {}, panes: {} };
|
|
108569
|
+
return json9({
|
|
108570
|
+
deviceId,
|
|
108571
|
+
windows: order.windows,
|
|
108572
|
+
panes: order.panes,
|
|
108573
|
+
windowNames: names.windows,
|
|
108574
|
+
paneNames: names.panes
|
|
108575
|
+
});
|
|
108576
|
+
}
|
|
108577
|
+
async function handlePutTreeOrder(req, deviceId) {
|
|
108578
|
+
if (!getDeviceById(deviceId)) {
|
|
108579
|
+
return json9({ error: t2("apiError.deviceNotFound") }, 404);
|
|
108580
|
+
}
|
|
108581
|
+
let body;
|
|
108582
|
+
try {
|
|
108583
|
+
body = await req.json();
|
|
108584
|
+
} catch {
|
|
108585
|
+
return json9({ error: t2("apiError.invalidRequest") }, 400);
|
|
108586
|
+
}
|
|
108587
|
+
const hasWindows = body.windows !== undefined;
|
|
108588
|
+
const hasPanes = body.panes !== undefined;
|
|
108589
|
+
if (!hasWindows && !hasPanes) {
|
|
108590
|
+
return json9({ error: t2("apiError.invalidRequest") }, 400);
|
|
108591
|
+
}
|
|
108592
|
+
if (hasWindows && !isStringArray(body.windows)) {
|
|
108593
|
+
return json9({ error: t2("apiError.invalidRequest") }, 400);
|
|
108594
|
+
}
|
|
108595
|
+
if (hasPanes && (typeof body.panes !== "object" || body.panes === null || Array.isArray(body.panes) || !Object.values(body.panes).every(isStringArray))) {
|
|
108596
|
+
return json9({ error: t2("apiError.invalidRequest") }, 400);
|
|
108597
|
+
}
|
|
108598
|
+
const bridge = getTreeOverlayBridge();
|
|
108599
|
+
if (!bridge) {
|
|
108600
|
+
return json9({ error: "settings service not ready" }, 503);
|
|
108601
|
+
}
|
|
108602
|
+
if (hasWindows) {
|
|
108603
|
+
bridge.reorderWindows(deviceId, body.windows);
|
|
108604
|
+
}
|
|
108605
|
+
if (hasPanes) {
|
|
108606
|
+
for (const [windowId, paneIds] of Object.entries(body.panes)) {
|
|
108607
|
+
bridge.reorderPanes(deviceId, windowId, paneIds);
|
|
108608
|
+
}
|
|
108609
|
+
}
|
|
108610
|
+
const order = getDeviceTreeOrder(deviceId);
|
|
108611
|
+
return json9({ deviceId, windows: order.windows, panes: order.panes });
|
|
108612
|
+
}
|
|
108613
|
+
async function handlePatchWindowName(req, deviceId, windowId) {
|
|
108614
|
+
if (!getDeviceById(deviceId)) {
|
|
108615
|
+
return json9({ error: t2("apiError.deviceNotFound") }, 404);
|
|
108616
|
+
}
|
|
108617
|
+
const name24 = await readNameBody(req);
|
|
108618
|
+
if (name24 === null) {
|
|
108619
|
+
return json9({ error: t2("apiError.invalidRequest") }, 400);
|
|
108620
|
+
}
|
|
108621
|
+
const bridge = getTreeOverlayBridge();
|
|
108622
|
+
if (!bridge) {
|
|
108623
|
+
return json9({ error: "settings service not ready" }, 503);
|
|
108624
|
+
}
|
|
108625
|
+
bridge.renameWindow(deviceId, windowId, name24);
|
|
108626
|
+
return json9({ deviceId, windowId, name: name24.trim().slice(0, 64) });
|
|
108627
|
+
}
|
|
108628
|
+
async function handlePatchPaneName(req, deviceId, paneId) {
|
|
108629
|
+
if (!getDeviceById(deviceId)) {
|
|
108630
|
+
return json9({ error: t2("apiError.deviceNotFound") }, 404);
|
|
108631
|
+
}
|
|
108632
|
+
if (!isTmuxPaneId(paneId)) {
|
|
108633
|
+
return json9({ error: t2("apiError.invalidRequest") }, 400);
|
|
108634
|
+
}
|
|
108635
|
+
const name24 = await readNameBody(req);
|
|
108636
|
+
if (name24 === null) {
|
|
108637
|
+
return json9({ error: t2("apiError.invalidRequest") }, 400);
|
|
108638
|
+
}
|
|
108639
|
+
const bridge = getTreeOverlayBridge();
|
|
108640
|
+
if (!bridge) {
|
|
108641
|
+
return json9({ error: "settings service not ready" }, 503);
|
|
108642
|
+
}
|
|
108643
|
+
bridge.renamePane(deviceId, paneId, name24);
|
|
108644
|
+
return json9({ deviceId, paneId, name: name24.trim().slice(0, 64) });
|
|
108645
|
+
}
|
|
108646
|
+
async function readNameBody(req) {
|
|
108647
|
+
try {
|
|
108648
|
+
const body = await req.json();
|
|
108649
|
+
return typeof body.name === "string" ? body.name : null;
|
|
108650
|
+
} catch {
|
|
108651
|
+
return null;
|
|
108652
|
+
}
|
|
108653
|
+
}
|
|
108654
|
+
function json9(data, status = 200) {
|
|
108655
|
+
return new Response(JSON.stringify(data), {
|
|
108656
|
+
status,
|
|
108657
|
+
headers: { "Content-Type": "application/json" }
|
|
108658
|
+
});
|
|
108659
|
+
}
|
|
108660
|
+
|
|
108358
108661
|
// ../../apps/gateway/src/db/watch.ts
|
|
108359
108662
|
function createWatchRule(input) {
|
|
108360
108663
|
const orm = getDb();
|
|
@@ -109453,35 +109756,35 @@ async function handleListRules(req) {
|
|
|
109453
109756
|
if (paneId) {
|
|
109454
109757
|
rules = rules.filter((rule) => rule.paneId === paneId);
|
|
109455
109758
|
}
|
|
109456
|
-
return
|
|
109759
|
+
return json10({ rules: rules.map(toRuleDto) });
|
|
109457
109760
|
}
|
|
109458
109761
|
async function handleCreateRule(req, deps) {
|
|
109459
109762
|
const raw = await readJsonObjectBody3(req);
|
|
109460
109763
|
if (!raw) {
|
|
109461
|
-
return
|
|
109764
|
+
return json10({ error: t2("apiError.invalidRequest") }, 400);
|
|
109462
109765
|
}
|
|
109463
109766
|
const body = raw;
|
|
109464
109767
|
const name24 = typeof body.name === "string" ? body.name.trim() : "";
|
|
109465
109768
|
if (!name24) {
|
|
109466
|
-
return
|
|
109769
|
+
return json10({ error: t2("apiError.watchNameRequired") }, 400);
|
|
109467
109770
|
}
|
|
109468
109771
|
const deviceId = typeof body.deviceId === "string" ? body.deviceId.trim() : "";
|
|
109469
109772
|
if (!deviceId) {
|
|
109470
|
-
return
|
|
109773
|
+
return json10({ error: t2("apiError.agentDeviceRequired") }, 400);
|
|
109471
109774
|
}
|
|
109472
109775
|
if (!getDeviceById(deviceId)) {
|
|
109473
|
-
return
|
|
109776
|
+
return json10({ error: t2("apiError.deviceNotFound") }, 404);
|
|
109474
109777
|
}
|
|
109475
109778
|
const paneId = typeof body.paneId === "string" ? body.paneId.trim() : "";
|
|
109476
109779
|
if (!paneId) {
|
|
109477
|
-
return
|
|
109780
|
+
return json10({ error: t2("apiError.agentPaneRequired") }, 400);
|
|
109478
109781
|
}
|
|
109479
109782
|
if (!TRIGGER_TYPES.includes(body.triggerType)) {
|
|
109480
|
-
return
|
|
109783
|
+
return json10({ error: t2("apiError.watchTriggerTypeInvalid") }, 400);
|
|
109481
109784
|
}
|
|
109482
109785
|
const parsed = parseRuleFields(raw);
|
|
109483
109786
|
if (!parsed.ok) {
|
|
109484
|
-
return
|
|
109787
|
+
return json10({ error: parsed.error }, 400);
|
|
109485
109788
|
}
|
|
109486
109789
|
const fields = parsed.fields;
|
|
109487
109790
|
const effective = {
|
|
@@ -109494,7 +109797,7 @@ async function handleCreateRule(req, deps) {
|
|
|
109494
109797
|
};
|
|
109495
109798
|
const semanticError = validateRuleSemantics(effective);
|
|
109496
109799
|
if (semanticError) {
|
|
109497
|
-
return
|
|
109800
|
+
return json10({ error: semanticError }, 400);
|
|
109498
109801
|
}
|
|
109499
109802
|
const rule = createWatchRule({
|
|
109500
109803
|
name: name24,
|
|
@@ -109517,50 +109820,50 @@ async function handleCreateRule(req, deps) {
|
|
|
109517
109820
|
cooldownSeconds: fields.cooldownSeconds
|
|
109518
109821
|
});
|
|
109519
109822
|
await deps.service.refreshRule(rule.id);
|
|
109520
|
-
return
|
|
109823
|
+
return json10({ rule: toRuleDto(rule), state: null }, 201);
|
|
109521
109824
|
}
|
|
109522
109825
|
async function handleGetRule(id) {
|
|
109523
109826
|
const rule = getWatchRuleById(id);
|
|
109524
109827
|
if (!rule) {
|
|
109525
|
-
return
|
|
109828
|
+
return json10({ error: t2("apiError.watchRuleNotFound") }, 404);
|
|
109526
109829
|
}
|
|
109527
109830
|
const state = getWatchRuleState(id);
|
|
109528
|
-
return
|
|
109831
|
+
return json10({ rule: toRuleDto(rule), state: state ? toStateDto(state) : null });
|
|
109529
109832
|
}
|
|
109530
109833
|
async function handleUpdateRule(req, id, deps) {
|
|
109531
109834
|
const existing = getWatchRuleById(id);
|
|
109532
109835
|
if (!existing) {
|
|
109533
|
-
return
|
|
109836
|
+
return json10({ error: t2("apiError.watchRuleNotFound") }, 404);
|
|
109534
109837
|
}
|
|
109535
109838
|
const raw = await readJsonObjectBody3(req);
|
|
109536
109839
|
if (!raw) {
|
|
109537
|
-
return
|
|
109840
|
+
return json10({ error: t2("apiError.invalidRequest") }, 400);
|
|
109538
109841
|
}
|
|
109539
109842
|
const body = raw;
|
|
109540
109843
|
const updates = {};
|
|
109541
109844
|
if (body.name !== undefined) {
|
|
109542
109845
|
const name24 = typeof body.name === "string" ? body.name.trim() : "";
|
|
109543
109846
|
if (!name24) {
|
|
109544
|
-
return
|
|
109847
|
+
return json10({ error: t2("apiError.watchNameRequired") }, 400);
|
|
109545
109848
|
}
|
|
109546
109849
|
updates.name = name24;
|
|
109547
109850
|
}
|
|
109548
109851
|
if (body.paneId !== undefined) {
|
|
109549
109852
|
const paneId = typeof body.paneId === "string" ? body.paneId.trim() : "";
|
|
109550
109853
|
if (!paneId) {
|
|
109551
|
-
return
|
|
109854
|
+
return json10({ error: t2("apiError.agentPaneRequired") }, 400);
|
|
109552
109855
|
}
|
|
109553
109856
|
updates.paneId = paneId;
|
|
109554
109857
|
}
|
|
109555
109858
|
if (body.triggerType !== undefined) {
|
|
109556
109859
|
if (!TRIGGER_TYPES.includes(body.triggerType)) {
|
|
109557
|
-
return
|
|
109860
|
+
return json10({ error: t2("apiError.watchTriggerTypeInvalid") }, 400);
|
|
109558
109861
|
}
|
|
109559
109862
|
updates.triggerType = body.triggerType;
|
|
109560
109863
|
}
|
|
109561
109864
|
const parsed = parseRuleFields(raw);
|
|
109562
109865
|
if (!parsed.ok) {
|
|
109563
|
-
return
|
|
109866
|
+
return json10({ error: parsed.error }, 400);
|
|
109564
109867
|
}
|
|
109565
109868
|
const fields = parsed.fields;
|
|
109566
109869
|
Object.assign(updates, fields);
|
|
@@ -109574,32 +109877,32 @@ async function handleUpdateRule(req, id, deps) {
|
|
|
109574
109877
|
};
|
|
109575
109878
|
const semanticError = validateRuleSemantics(effective);
|
|
109576
109879
|
if (semanticError) {
|
|
109577
|
-
return
|
|
109880
|
+
return json10({ error: semanticError }, 400);
|
|
109578
109881
|
}
|
|
109579
109882
|
const rule = updateWatchRule(id, updates);
|
|
109580
109883
|
if (!rule) {
|
|
109581
|
-
return
|
|
109884
|
+
return json10({ error: t2("apiError.watchRuleNotFound") }, 404);
|
|
109582
109885
|
}
|
|
109583
109886
|
await deps.service.refreshRule(id);
|
|
109584
109887
|
const state = getWatchRuleState(id);
|
|
109585
|
-
return
|
|
109888
|
+
return json10({ rule: toRuleDto(rule), state: state ? toStateDto(state) : null });
|
|
109586
109889
|
}
|
|
109587
109890
|
async function handleDeleteRule(id, deps) {
|
|
109588
109891
|
const existing = getWatchRuleById(id);
|
|
109589
109892
|
if (!existing) {
|
|
109590
|
-
return
|
|
109893
|
+
return json10({ error: t2("apiError.watchRuleNotFound") }, 404);
|
|
109591
109894
|
}
|
|
109592
109895
|
deleteWatchRule(id);
|
|
109593
109896
|
await deps.service.removeRule(id);
|
|
109594
|
-
return
|
|
109897
|
+
return json10({ success: true });
|
|
109595
109898
|
}
|
|
109596
109899
|
async function handleGetRuleState(id, deps) {
|
|
109597
109900
|
const rule = getWatchRuleById(id);
|
|
109598
109901
|
if (!rule) {
|
|
109599
|
-
return
|
|
109902
|
+
return json10({ error: t2("apiError.watchRuleNotFound") }, 404);
|
|
109600
109903
|
}
|
|
109601
109904
|
const state = getWatchRuleState(id);
|
|
109602
|
-
return
|
|
109905
|
+
return json10({
|
|
109603
109906
|
state: state ? toStateDto(state) : null,
|
|
109604
109907
|
samples: deps.service.getSamples(id)
|
|
109605
109908
|
});
|
|
@@ -109623,17 +109926,17 @@ function buildAssistPrompt(description, screen) {
|
|
|
109623
109926
|
async function handleAssistRegex(req, deps) {
|
|
109624
109927
|
const raw = await readJsonObjectBody3(req);
|
|
109625
109928
|
if (!raw) {
|
|
109626
|
-
return
|
|
109929
|
+
return json10({ error: t2("apiError.invalidRequest") }, 400);
|
|
109627
109930
|
}
|
|
109628
109931
|
const body = raw;
|
|
109629
109932
|
const description = typeof body.description === "string" ? body.description.trim() : "";
|
|
109630
109933
|
if (!description) {
|
|
109631
|
-
return
|
|
109934
|
+
return json10({ error: t2("apiError.watchAssistDescriptionRequired") }, 400);
|
|
109632
109935
|
}
|
|
109633
109936
|
let providerId = null;
|
|
109634
109937
|
if (body.providerId !== undefined && body.providerId !== null) {
|
|
109635
109938
|
if (typeof body.providerId !== "string" || !getLlmProviderById(body.providerId)) {
|
|
109636
|
-
return
|
|
109939
|
+
return json10({ error: t2("apiError.llmProviderNotFound") }, 400);
|
|
109637
109940
|
}
|
|
109638
109941
|
providerId = body.providerId;
|
|
109639
109942
|
}
|
|
@@ -109643,7 +109946,7 @@ async function handleAssistRegex(req, deps) {
|
|
|
109643
109946
|
const paneId = typeof body.paneId === "string" ? body.paneId.trim() : "";
|
|
109644
109947
|
if (deviceId && paneId) {
|
|
109645
109948
|
if (!getDeviceById(deviceId)) {
|
|
109646
|
-
return
|
|
109949
|
+
return json10({ error: t2("apiError.deviceNotFound") }, 404);
|
|
109647
109950
|
}
|
|
109648
109951
|
try {
|
|
109649
109952
|
screen = await deps.captureScreen(deviceId, paneId);
|
|
@@ -109664,14 +109967,14 @@ async function handleAssistRegex(req, deps) {
|
|
|
109664
109967
|
object3 = result.object;
|
|
109665
109968
|
} catch (error51) {
|
|
109666
109969
|
const detail = error51 instanceof Error ? error51.message : String(error51);
|
|
109667
|
-
return
|
|
109970
|
+
return json10({ error: t2("apiError.watchAssistModelUnavailable", { detail }) }, 502);
|
|
109668
109971
|
}
|
|
109669
109972
|
let regex;
|
|
109670
109973
|
try {
|
|
109671
109974
|
regex = compileWatchPattern(object3.pattern, object3.flags);
|
|
109672
109975
|
} catch (error51) {
|
|
109673
109976
|
const detail = error51 instanceof Error ? error51.message : String(error51);
|
|
109674
|
-
return
|
|
109977
|
+
return json10({ error: t2("apiError.watchPatternInvalid", { detail }) }, 502);
|
|
109675
109978
|
}
|
|
109676
109979
|
const preview = [];
|
|
109677
109980
|
if (screen) {
|
|
@@ -109685,7 +109988,7 @@ async function handleAssistRegex(req, deps) {
|
|
|
109685
109988
|
match = regex.exec(screen);
|
|
109686
109989
|
}
|
|
109687
109990
|
}
|
|
109688
|
-
return
|
|
109991
|
+
return json10({
|
|
109689
109992
|
pattern: object3.pattern,
|
|
109690
109993
|
flags: object3.flags,
|
|
109691
109994
|
extractGroup: object3.extractGroup >= 0 ? object3.extractGroup : 0,
|
|
@@ -109693,7 +109996,7 @@ async function handleAssistRegex(req, deps) {
|
|
|
109693
109996
|
preview
|
|
109694
109997
|
});
|
|
109695
109998
|
}
|
|
109696
|
-
function
|
|
109999
|
+
function json10(data, status = 200) {
|
|
109697
110000
|
return new Response(JSON.stringify(data), {
|
|
109698
110001
|
status,
|
|
109699
110002
|
headers: {
|
|
@@ -109800,11 +110103,25 @@ function normalizeSiteSettingsInput(body) {
|
|
|
109800
110103
|
}
|
|
109801
110104
|
updates.language = value;
|
|
109802
110105
|
}
|
|
110106
|
+
if (body.disabledNotificationChannels !== undefined) {
|
|
110107
|
+
if (!Array.isArray(body.disabledNotificationChannels) || !body.disabledNotificationChannels.every((item) => typeof item === "string")) {
|
|
110108
|
+
throw new Error(t2("apiError.invalidRequest"));
|
|
110109
|
+
}
|
|
110110
|
+
updates.disabledNotificationChannels = [
|
|
110111
|
+
...new Set(body.disabledNotificationChannels.map((item) => item.trim()).filter(Boolean))
|
|
110112
|
+
];
|
|
110113
|
+
}
|
|
109803
110114
|
return updates;
|
|
109804
110115
|
}
|
|
109805
110116
|
function handleApiRequest(req, _server) {
|
|
109806
110117
|
const url2 = new URL(req.url);
|
|
109807
110118
|
const path = url2.pathname;
|
|
110119
|
+
if (path === "/api/capabilities") {
|
|
110120
|
+
const capabilitiesResponse = handleCapabilitiesApiRequest(req, path);
|
|
110121
|
+
if (capabilitiesResponse) {
|
|
110122
|
+
return capabilitiesResponse;
|
|
110123
|
+
}
|
|
110124
|
+
}
|
|
109808
110125
|
if (path === "/api/devices" && req.method === "GET") {
|
|
109809
110126
|
return handleGetDevices();
|
|
109810
110127
|
}
|
|
@@ -109826,6 +110143,12 @@ function handleApiRequest(req, _server) {
|
|
|
109826
110143
|
if (path.match(/^\/api\/devices\/[^/]+\/test-connection$/) && req.method === "POST") {
|
|
109827
110144
|
return handleTestConnection(path.split("/")[3]);
|
|
109828
110145
|
}
|
|
110146
|
+
if (path.startsWith("/api/devices/")) {
|
|
110147
|
+
const treeOrderResponse = handleTreeOrderApiRequest(req, path);
|
|
110148
|
+
if (treeOrderResponse) {
|
|
110149
|
+
return treeOrderResponse;
|
|
110150
|
+
}
|
|
110151
|
+
}
|
|
109829
110152
|
if (path === "/api/settings/site" && req.method === "GET") {
|
|
109830
110153
|
return handleGetSiteSettings();
|
|
109831
110154
|
}
|
|
@@ -109947,13 +110270,13 @@ function handleApiRequest(req, _server) {
|
|
|
109947
110270
|
return handleGetManifest(req.method);
|
|
109948
110271
|
}
|
|
109949
110272
|
if (path === "/healthz" && req.method === "GET") {
|
|
109950
|
-
return
|
|
110273
|
+
return json11({
|
|
109951
110274
|
status: "ok",
|
|
109952
110275
|
restarting: runtimeController.isRestarting(),
|
|
109953
110276
|
env: "development"
|
|
109954
110277
|
});
|
|
109955
110278
|
}
|
|
109956
|
-
return
|
|
110279
|
+
return json11({ error: t2("apiError.notFound") }, 404);
|
|
109957
110280
|
}
|
|
109958
110281
|
function enrichDeviceWithRuntime(device) {
|
|
109959
110282
|
const status = getDeviceRuntimeStatus(device.id);
|
|
@@ -109967,22 +110290,22 @@ function enrichDeviceWithRuntime(device) {
|
|
|
109967
110290
|
}
|
|
109968
110291
|
async function handleGetDevices() {
|
|
109969
110292
|
const devices2 = getAllDevices().map(enrichDeviceWithRuntime);
|
|
109970
|
-
return
|
|
110293
|
+
return json11({ devices: devices2 });
|
|
109971
110294
|
}
|
|
109972
110295
|
async function handleGetDevice(id) {
|
|
109973
110296
|
const device = getDeviceById(id);
|
|
109974
110297
|
if (!device) {
|
|
109975
|
-
return
|
|
110298
|
+
return json11({ error: t2("apiError.deviceNotFound") }, 404);
|
|
109976
110299
|
}
|
|
109977
|
-
return
|
|
110300
|
+
return json11({ device: enrichDeviceWithRuntime(device) });
|
|
109978
110301
|
}
|
|
109979
110302
|
async function handleCreateDevice(req) {
|
|
109980
110303
|
const body = await req.json();
|
|
109981
110304
|
if (!body.name || !body.type || !body.authMode) {
|
|
109982
|
-
return
|
|
110305
|
+
return json11({ error: t2("apiError.missingFields") }, 400);
|
|
109983
110306
|
}
|
|
109984
110307
|
if (body.type === "ssh" && !body.host && !body.sshConfigRef) {
|
|
109985
|
-
return
|
|
110308
|
+
return json11({ error: t2("apiError.sshRequiresHost") }, 400);
|
|
109986
110309
|
}
|
|
109987
110310
|
const now2 = new Date().toISOString();
|
|
109988
110311
|
const device = {
|
|
@@ -110004,13 +110327,14 @@ async function handleCreateDevice(req) {
|
|
|
110004
110327
|
updatedAt: now2
|
|
110005
110328
|
};
|
|
110006
110329
|
createDevice(device);
|
|
110330
|
+
broadcastSettingsUpdate("devices");
|
|
110007
110331
|
await pushSupervisor.upsert(device.id);
|
|
110008
|
-
return
|
|
110332
|
+
return json11({ device: getDeviceById(device.id) ?? device }, 201);
|
|
110009
110333
|
}
|
|
110010
110334
|
async function handleUpdateDevice(req, id) {
|
|
110011
110335
|
const existing = getDeviceById(id);
|
|
110012
110336
|
if (!existing) {
|
|
110013
|
-
return
|
|
110337
|
+
return json11({ error: t2("apiError.deviceNotFound") }, 404);
|
|
110014
110338
|
}
|
|
110015
110339
|
const body = await req.json();
|
|
110016
110340
|
const updates = {};
|
|
@@ -110038,80 +110362,85 @@ async function handleUpdateDevice(req, id) {
|
|
|
110038
110362
|
updates.privateKeyPassphraseEnc = await encrypt(body.privateKeyPassphrase);
|
|
110039
110363
|
}
|
|
110040
110364
|
updateDevice(id, updates);
|
|
110365
|
+
broadcastSettingsUpdate("devices");
|
|
110041
110366
|
if (shouldReconnectPushSupervisor(existing, updates)) {
|
|
110042
110367
|
await pushSupervisor.reconnect(id);
|
|
110043
110368
|
} else if (updates.defaultWorkingDir !== undefined && updates.defaultWorkingDir !== existing.defaultWorkingDir) {
|
|
110044
110369
|
pushSupervisor.updateDefaultWorkingDir(id, updates.defaultWorkingDir);
|
|
110045
110370
|
}
|
|
110046
110371
|
const device = getDeviceById(id);
|
|
110047
|
-
return
|
|
110372
|
+
return json11({ device });
|
|
110048
110373
|
}
|
|
110049
110374
|
async function handleReorderDevices(req) {
|
|
110050
110375
|
const body = await req.json();
|
|
110051
110376
|
if (!Array.isArray(body.deviceIds) || body.deviceIds.some((id) => typeof id !== "string")) {
|
|
110052
|
-
return
|
|
110377
|
+
return json11({ error: t2("apiError.invalidRequest") }, 400);
|
|
110053
110378
|
}
|
|
110054
110379
|
reorderDevices(body.deviceIds);
|
|
110055
|
-
|
|
110380
|
+
broadcastSettingsUpdate("devices");
|
|
110381
|
+
return json11({ devices: getAllDevices().map(enrichDeviceWithRuntime) });
|
|
110056
110382
|
}
|
|
110057
110383
|
async function handleDeleteDevice(id) {
|
|
110058
110384
|
const existing = getDeviceById(id);
|
|
110059
110385
|
if (!existing) {
|
|
110060
|
-
return
|
|
110386
|
+
return json11({ error: t2("apiError.deviceNotFound") }, 404);
|
|
110061
110387
|
}
|
|
110062
110388
|
deleteDevice(id);
|
|
110389
|
+
broadcastSettingsUpdate("devices");
|
|
110063
110390
|
pushSupervisor.remove(id);
|
|
110064
|
-
return
|
|
110391
|
+
return json11({ success: true });
|
|
110065
110392
|
}
|
|
110066
110393
|
async function handleTestConnection(id) {
|
|
110067
110394
|
return handleDeviceTestConnection(id);
|
|
110068
110395
|
}
|
|
110069
110396
|
async function handleGetSiteSettings() {
|
|
110070
|
-
return
|
|
110397
|
+
return json11({ settings: getSiteSettings() });
|
|
110071
110398
|
}
|
|
110072
110399
|
async function handleUpdateSiteSettings(req) {
|
|
110073
110400
|
try {
|
|
110074
110401
|
const body = await req.json();
|
|
110075
110402
|
const updates = normalizeSiteSettingsInput(body);
|
|
110076
110403
|
const settings = updateSiteSettings(updates);
|
|
110077
|
-
|
|
110404
|
+
broadcastSettingsUpdate("site");
|
|
110405
|
+
return json11({ settings });
|
|
110078
110406
|
} catch (err) {
|
|
110079
|
-
return
|
|
110407
|
+
return json11({ error: err instanceof Error ? err.message : t2("apiError.invalidRequest") }, 400);
|
|
110080
110408
|
}
|
|
110081
110409
|
}
|
|
110082
110410
|
async function handleGetTerminalShortcuts() {
|
|
110083
|
-
return
|
|
110411
|
+
return json11({ settings: getTerminalShortcutSettings() });
|
|
110084
110412
|
}
|
|
110085
110413
|
async function handleUpdateTerminalShortcuts(req) {
|
|
110086
110414
|
try {
|
|
110087
110415
|
const body = await req.json();
|
|
110088
110416
|
const updates = normalizeTerminalShortcutsInput(body);
|
|
110089
110417
|
const settings = updateTerminalShortcutSettings(updates);
|
|
110090
|
-
|
|
110418
|
+
broadcastSettingsUpdate("terminal-shortcuts");
|
|
110419
|
+
return json11({ settings });
|
|
110091
110420
|
} catch (err) {
|
|
110092
|
-
return
|
|
110421
|
+
return json11({ error: err instanceof Error ? err.message : t2("apiError.invalidRequest") }, 400);
|
|
110093
110422
|
}
|
|
110094
110423
|
}
|
|
110095
110424
|
async function handleRestartGateway() {
|
|
110096
110425
|
setTimeout(() => {
|
|
110097
110426
|
runtimeController.requestRestart();
|
|
110098
110427
|
}, 50);
|
|
110099
|
-
return
|
|
110428
|
+
return json11({
|
|
110100
110429
|
success: true,
|
|
110101
110430
|
message: t2("settings.restartScheduled")
|
|
110102
110431
|
});
|
|
110103
110432
|
}
|
|
110104
110433
|
async function handleGetTelegramBots() {
|
|
110105
110434
|
const bots = getTelegramBotsWithStats();
|
|
110106
|
-
return
|
|
110435
|
+
return json11({ bots });
|
|
110107
110436
|
}
|
|
110108
110437
|
async function handleCreateTelegramBot(req) {
|
|
110109
110438
|
const body = await req.json();
|
|
110110
110439
|
if (!body.name?.trim()) {
|
|
110111
|
-
return
|
|
110440
|
+
return json11({ error: t2("apiError.botNameRequired") }, 400);
|
|
110112
110441
|
}
|
|
110113
110442
|
if (!body.token?.trim()) {
|
|
110114
|
-
return
|
|
110443
|
+
return json11({ error: t2("apiError.botTokenRequired") }, 400);
|
|
110115
110444
|
}
|
|
110116
110445
|
const now2 = new Date().toISOString();
|
|
110117
110446
|
createTelegramBot({
|
|
@@ -110124,27 +110453,28 @@ async function handleCreateTelegramBot(req) {
|
|
|
110124
110453
|
createdAt: now2,
|
|
110125
110454
|
updatedAt: now2
|
|
110126
110455
|
});
|
|
110456
|
+
broadcastSettingsUpdate("telegram");
|
|
110127
110457
|
await telegramService.refresh();
|
|
110128
|
-
return
|
|
110458
|
+
return json11({ success: true }, 201);
|
|
110129
110459
|
}
|
|
110130
110460
|
async function handleUpdateTelegramBot(req, botId) {
|
|
110131
110461
|
const existing = getTelegramBotById(botId);
|
|
110132
110462
|
if (!existing) {
|
|
110133
|
-
return
|
|
110463
|
+
return json11({ error: t2("apiError.botNotFound") }, 404);
|
|
110134
110464
|
}
|
|
110135
110465
|
const body = await req.json();
|
|
110136
110466
|
const updates = {};
|
|
110137
110467
|
if (body.name !== undefined) {
|
|
110138
110468
|
const value = body.name.trim();
|
|
110139
110469
|
if (!value) {
|
|
110140
|
-
return
|
|
110470
|
+
return json11({ error: t2("apiError.botNameRequired") }, 400);
|
|
110141
110471
|
}
|
|
110142
110472
|
updates.name = value;
|
|
110143
110473
|
}
|
|
110144
110474
|
if (body.token !== undefined) {
|
|
110145
110475
|
const token = body.token.trim();
|
|
110146
110476
|
if (!token) {
|
|
110147
|
-
return
|
|
110477
|
+
return json11({ error: t2("apiError.botTokenRequired") }, 400);
|
|
110148
110478
|
}
|
|
110149
110479
|
updates.tokenEnc = await encrypt(token);
|
|
110150
110480
|
}
|
|
@@ -110155,70 +110485,74 @@ async function handleUpdateTelegramBot(req, botId) {
|
|
|
110155
110485
|
updates.allowAuthRequests = body.allowAuthRequests;
|
|
110156
110486
|
}
|
|
110157
110487
|
updateTelegramBot(botId, updates);
|
|
110488
|
+
broadcastSettingsUpdate("telegram");
|
|
110158
110489
|
await telegramService.refresh();
|
|
110159
|
-
return
|
|
110490
|
+
return json11({ success: true });
|
|
110160
110491
|
}
|
|
110161
110492
|
async function handleDeleteTelegramBot(botId) {
|
|
110162
110493
|
const existing = getTelegramBotById(botId);
|
|
110163
110494
|
if (!existing) {
|
|
110164
|
-
return
|
|
110495
|
+
return json11({ error: t2("apiError.botNotFound") }, 404);
|
|
110165
110496
|
}
|
|
110166
110497
|
deleteTelegramBot(botId);
|
|
110498
|
+
broadcastSettingsUpdate("telegram");
|
|
110167
110499
|
await telegramService.refresh();
|
|
110168
|
-
return
|
|
110500
|
+
return json11({ success: true });
|
|
110169
110501
|
}
|
|
110170
110502
|
async function handleListTelegramChats(botId) {
|
|
110171
110503
|
const existing = getTelegramBotById(botId);
|
|
110172
110504
|
if (!existing) {
|
|
110173
|
-
return
|
|
110505
|
+
return json11({ error: t2("apiError.botNotFound") }, 404);
|
|
110174
110506
|
}
|
|
110175
110507
|
const chats = listTelegramChatsByBot(botId);
|
|
110176
|
-
return
|
|
110508
|
+
return json11({ chats });
|
|
110177
110509
|
}
|
|
110178
110510
|
async function handleApproveTelegramChat(botId, chatId) {
|
|
110179
110511
|
const existing = getTelegramBotById(botId);
|
|
110180
110512
|
if (!existing) {
|
|
110181
|
-
return
|
|
110513
|
+
return json11({ error: t2("apiError.botNotFound") }, 404);
|
|
110182
110514
|
}
|
|
110183
110515
|
const chat = approveTelegramChat(botId, chatId);
|
|
110184
110516
|
if (!chat) {
|
|
110185
|
-
return
|
|
110517
|
+
return json11({ error: t2("apiError.chatNotFound") }, 404);
|
|
110186
110518
|
}
|
|
110519
|
+
broadcastSettingsUpdate("telegram");
|
|
110187
110520
|
const settings = getSiteSettings();
|
|
110188
110521
|
await telegramService.sendTestMessage(botId, chatId, t2("telegram.approveMessageTemplate", {
|
|
110189
110522
|
botName: existing.name,
|
|
110190
110523
|
time: new Date().toLocaleString(toBCP47(settings.language))
|
|
110191
110524
|
}));
|
|
110192
|
-
return
|
|
110525
|
+
return json11({ chat });
|
|
110193
110526
|
}
|
|
110194
110527
|
async function handleDeleteTelegramChat(botId, chatId) {
|
|
110195
110528
|
const existing = getTelegramBotById(botId);
|
|
110196
110529
|
if (!existing) {
|
|
110197
|
-
return
|
|
110530
|
+
return json11({ error: t2("apiError.botNotFound") }, 404);
|
|
110198
110531
|
}
|
|
110199
110532
|
deleteTelegramChat(botId, chatId);
|
|
110200
|
-
|
|
110533
|
+
broadcastSettingsUpdate("telegram");
|
|
110534
|
+
return json11({ success: true });
|
|
110201
110535
|
}
|
|
110202
110536
|
async function handleTestTelegramChat(botId, chatId) {
|
|
110203
110537
|
const bot = getTelegramBotById(botId);
|
|
110204
110538
|
if (!bot) {
|
|
110205
|
-
return
|
|
110539
|
+
return json11({ error: t2("apiError.botNotFound") }, 404);
|
|
110206
110540
|
}
|
|
110207
110541
|
const settings = getSiteSettings();
|
|
110208
110542
|
await telegramService.sendTestMessage(botId, chatId, t2("telegram.testMessageTemplate", {
|
|
110209
110543
|
siteName: settings.siteName,
|
|
110210
110544
|
time: new Date().toLocaleString(toBCP47(settings.language))
|
|
110211
110545
|
}));
|
|
110212
|
-
return
|
|
110546
|
+
return json11({ success: true });
|
|
110213
110547
|
}
|
|
110214
110548
|
async function handleGetWeixinAccounts() {
|
|
110215
110549
|
const accounts = getWeixinAccountsWithStats();
|
|
110216
|
-
return
|
|
110550
|
+
return json11({ accounts });
|
|
110217
110551
|
}
|
|
110218
110552
|
async function handleCreateWeixinAccount(req) {
|
|
110219
110553
|
const body = await req.json();
|
|
110220
110554
|
if (!body.name?.trim()) {
|
|
110221
|
-
return
|
|
110555
|
+
return json11({ error: t2("weixin.accountNameRequired") }, 400);
|
|
110222
110556
|
}
|
|
110223
110557
|
const now2 = new Date().toISOString();
|
|
110224
110558
|
const id = v4_default();
|
|
@@ -110235,19 +110569,20 @@ async function handleCreateWeixinAccount(req) {
|
|
|
110235
110569
|
createdAt: now2,
|
|
110236
110570
|
updatedAt: now2
|
|
110237
110571
|
});
|
|
110238
|
-
|
|
110572
|
+
broadcastSettingsUpdate("weixin");
|
|
110573
|
+
return json11({ success: true, accountId: id }, 201);
|
|
110239
110574
|
}
|
|
110240
110575
|
async function handleUpdateWeixinAccount(req, accountId) {
|
|
110241
110576
|
const existing = getWeixinAccountById(accountId);
|
|
110242
110577
|
if (!existing) {
|
|
110243
|
-
return
|
|
110578
|
+
return json11({ error: t2("weixin.accountNotFound") }, 404);
|
|
110244
110579
|
}
|
|
110245
110580
|
const body = await req.json();
|
|
110246
110581
|
const updates = {};
|
|
110247
110582
|
if (body.name !== undefined) {
|
|
110248
110583
|
const value = body.name.trim();
|
|
110249
110584
|
if (!value) {
|
|
110250
|
-
return
|
|
110585
|
+
return json11({ error: t2("weixin.accountNameRequired") }, 400);
|
|
110251
110586
|
}
|
|
110252
110587
|
updates.name = value;
|
|
110253
110588
|
}
|
|
@@ -110258,54 +110593,57 @@ async function handleUpdateWeixinAccount(req, accountId) {
|
|
|
110258
110593
|
updates.allowAuthRequests = body.allowAuthRequests;
|
|
110259
110594
|
}
|
|
110260
110595
|
updateWeixinAccount(accountId, updates);
|
|
110596
|
+
broadcastSettingsUpdate("weixin");
|
|
110261
110597
|
await weixinService.refresh();
|
|
110262
|
-
return
|
|
110598
|
+
return json11({ success: true });
|
|
110263
110599
|
}
|
|
110264
110600
|
async function handleDeleteWeixinAccount(accountId) {
|
|
110265
110601
|
const existing = getWeixinAccountById(accountId);
|
|
110266
110602
|
if (!existing) {
|
|
110267
|
-
return
|
|
110603
|
+
return json11({ error: t2("weixin.accountNotFound") }, 404);
|
|
110268
110604
|
}
|
|
110269
110605
|
deleteWeixinAccount(accountId);
|
|
110606
|
+
broadcastSettingsUpdate("weixin");
|
|
110270
110607
|
await weixinService.refresh();
|
|
110271
|
-
return
|
|
110608
|
+
return json11({ success: true });
|
|
110272
110609
|
}
|
|
110273
110610
|
async function handleStartWeixinLogin(accountId) {
|
|
110274
110611
|
const existing = getWeixinAccountById(accountId);
|
|
110275
110612
|
if (!existing) {
|
|
110276
|
-
return
|
|
110613
|
+
return json11({ error: t2("weixin.accountNotFound") }, 404);
|
|
110277
110614
|
}
|
|
110278
110615
|
try {
|
|
110279
110616
|
const result = await weixinService.startLogin(accountId);
|
|
110280
|
-
return
|
|
110617
|
+
return json11(result);
|
|
110281
110618
|
} catch (err) {
|
|
110282
|
-
return
|
|
110619
|
+
return json11({ error: err instanceof Error ? err.message : t2("weixin.loginFailed") }, 502);
|
|
110283
110620
|
}
|
|
110284
110621
|
}
|
|
110285
110622
|
async function handleGetWeixinLoginStatus(accountId) {
|
|
110286
110623
|
const existing = getWeixinAccountById(accountId);
|
|
110287
110624
|
if (!existing) {
|
|
110288
|
-
return
|
|
110625
|
+
return json11({ error: t2("weixin.accountNotFound") }, 404);
|
|
110289
110626
|
}
|
|
110290
|
-
return
|
|
110627
|
+
return json11(weixinService.getLoginStatus(accountId));
|
|
110291
110628
|
}
|
|
110292
110629
|
async function handleListWeixinUsers(accountId) {
|
|
110293
110630
|
const existing = getWeixinAccountById(accountId);
|
|
110294
110631
|
if (!existing) {
|
|
110295
|
-
return
|
|
110632
|
+
return json11({ error: t2("weixin.accountNotFound") }, 404);
|
|
110296
110633
|
}
|
|
110297
110634
|
const users = listWeixinUsersByAccount(accountId);
|
|
110298
|
-
return
|
|
110635
|
+
return json11({ users });
|
|
110299
110636
|
}
|
|
110300
110637
|
async function handleApproveWeixinUser(accountId, userId) {
|
|
110301
110638
|
const existing = getWeixinAccountById(accountId);
|
|
110302
110639
|
if (!existing) {
|
|
110303
|
-
return
|
|
110640
|
+
return json11({ error: t2("weixin.accountNotFound") }, 404);
|
|
110304
110641
|
}
|
|
110305
110642
|
const user = approveWeixinUser(accountId, userId);
|
|
110306
110643
|
if (!user) {
|
|
110307
|
-
return
|
|
110644
|
+
return json11({ error: t2("weixin.userNotFound") }, 404);
|
|
110308
110645
|
}
|
|
110646
|
+
broadcastSettingsUpdate("weixin");
|
|
110309
110647
|
const settings = getSiteSettings();
|
|
110310
110648
|
try {
|
|
110311
110649
|
await weixinService.sendTestMessage(accountId, userId, t2("weixin.approveMessageTemplate", {
|
|
@@ -110315,12 +110653,12 @@ async function handleApproveWeixinUser(accountId, userId) {
|
|
|
110315
110653
|
} catch (err) {
|
|
110316
110654
|
console.error("[weixin] approve ack failed:", err);
|
|
110317
110655
|
}
|
|
110318
|
-
return
|
|
110656
|
+
return json11({ user });
|
|
110319
110657
|
}
|
|
110320
110658
|
async function handleTestWeixinUser(accountId, userId) {
|
|
110321
110659
|
const existing = getWeixinAccountById(accountId);
|
|
110322
110660
|
if (!existing) {
|
|
110323
|
-
return
|
|
110661
|
+
return json11({ error: t2("weixin.accountNotFound") }, 404);
|
|
110324
110662
|
}
|
|
110325
110663
|
const settings = getSiteSettings();
|
|
110326
110664
|
try {
|
|
@@ -110329,14 +110667,14 @@ async function handleTestWeixinUser(accountId, userId) {
|
|
|
110329
110667
|
time: new Date().toLocaleString(toBCP47(settings.language))
|
|
110330
110668
|
}));
|
|
110331
110669
|
} catch (err) {
|
|
110332
|
-
return
|
|
110670
|
+
return json11({ error: err instanceof Error ? err.message : t2("weixin.testMessageFailed") }, 400);
|
|
110333
110671
|
}
|
|
110334
|
-
return
|
|
110672
|
+
return json11({ success: true });
|
|
110335
110673
|
}
|
|
110336
110674
|
async function handleTestWeixinAccount(accountId) {
|
|
110337
110675
|
const existing = getWeixinAccountById(accountId);
|
|
110338
110676
|
if (!existing) {
|
|
110339
|
-
return
|
|
110677
|
+
return json11({ error: t2("weixin.accountNotFound") }, 404);
|
|
110340
110678
|
}
|
|
110341
110679
|
const settings = getSiteSettings();
|
|
110342
110680
|
try {
|
|
@@ -110345,26 +110683,27 @@ async function handleTestWeixinAccount(accountId) {
|
|
|
110345
110683
|
time: new Date().toLocaleString(toBCP47(settings.language))
|
|
110346
110684
|
}));
|
|
110347
110685
|
} catch (err) {
|
|
110348
|
-
return
|
|
110686
|
+
return json11({ error: err instanceof Error ? err.message : t2("weixin.testMessageFailed") }, 400);
|
|
110349
110687
|
}
|
|
110350
|
-
return
|
|
110688
|
+
return json11({ success: true });
|
|
110351
110689
|
}
|
|
110352
110690
|
async function handleDeleteWeixinUser(accountId, userId) {
|
|
110353
110691
|
const existing = getWeixinAccountById(accountId);
|
|
110354
110692
|
if (!existing) {
|
|
110355
|
-
return
|
|
110693
|
+
return json11({ error: t2("weixin.accountNotFound") }, 404);
|
|
110356
110694
|
}
|
|
110357
110695
|
deleteWeixinUser(accountId, userId);
|
|
110358
|
-
|
|
110696
|
+
broadcastSettingsUpdate("weixin");
|
|
110697
|
+
return json11({ success: true });
|
|
110359
110698
|
}
|
|
110360
110699
|
async function handleGetWebhooks() {
|
|
110361
110700
|
const webhooks = getAllWebhookEndpoints();
|
|
110362
|
-
return
|
|
110701
|
+
return json11({ webhooks });
|
|
110363
110702
|
}
|
|
110364
110703
|
async function handleCreateWebhook(req) {
|
|
110365
110704
|
const body = await req.json();
|
|
110366
110705
|
if (!body.url || !body.secret) {
|
|
110367
|
-
return
|
|
110706
|
+
return json11({ error: t2("apiError.urlAndSecretRequired") }, 400);
|
|
110368
110707
|
}
|
|
110369
110708
|
const now2 = new Date().toISOString();
|
|
110370
110709
|
const endpoint = {
|
|
@@ -110377,11 +110716,13 @@ async function handleCreateWebhook(req) {
|
|
|
110377
110716
|
updatedAt: now2
|
|
110378
110717
|
};
|
|
110379
110718
|
createWebhookEndpoint(endpoint);
|
|
110380
|
-
|
|
110719
|
+
broadcastSettingsUpdate("webhooks");
|
|
110720
|
+
return json11({ webhook: endpoint }, 201);
|
|
110381
110721
|
}
|
|
110382
110722
|
async function handleDeleteWebhook(id) {
|
|
110383
110723
|
deleteWebhookEndpoint(id);
|
|
110384
|
-
|
|
110724
|
+
broadcastSettingsUpdate("webhooks");
|
|
110725
|
+
return json11({ success: true });
|
|
110385
110726
|
}
|
|
110386
110727
|
async function handleGetManifest(method) {
|
|
110387
110728
|
const settings = getSiteSettings();
|
|
@@ -110420,7 +110761,7 @@ function manifestJson(data, method) {
|
|
|
110420
110761
|
}
|
|
110421
110762
|
});
|
|
110422
110763
|
}
|
|
110423
|
-
function
|
|
110764
|
+
function json11(data, status = 200, headers = {}) {
|
|
110424
110765
|
return new Response(JSON.stringify(data), {
|
|
110425
110766
|
status,
|
|
110426
110767
|
headers: {
|
|
@@ -110496,8 +110837,7 @@ function createBorshClientState() {
|
|
|
110496
110837
|
maxFrameBytes: exports_ws_borsh.DEFAULT_MAX_FRAME_BYTES,
|
|
110497
110838
|
chunkReassembler: new exports_ws_borsh.ChunkReassembler,
|
|
110498
110839
|
selectedPanes: {},
|
|
110499
|
-
subscribedPanes: {}
|
|
110500
|
-
pendingHistoryFetches: new Map
|
|
110840
|
+
subscribedPanes: {}
|
|
110501
110841
|
};
|
|
110502
110842
|
}
|
|
110503
110843
|
function encodeTermOutput(params, seq) {
|
|
@@ -110929,7 +111269,7 @@ class SwitchBarrier {
|
|
|
110929
111269
|
}
|
|
110930
111270
|
pending.callbacks.onAckSent?.();
|
|
110931
111271
|
}
|
|
110932
|
-
sendTermHistory(ws, deviceId, paneId, historyData, alternateScreen) {
|
|
111272
|
+
sendTermHistory(ws, deviceId, paneId, historyData, alternateScreen, modes) {
|
|
110933
111273
|
const pending = this.getPending(ws, deviceId);
|
|
110934
111274
|
if (!pending)
|
|
110935
111275
|
return;
|
|
@@ -110956,6 +111296,7 @@ class SwitchBarrier {
|
|
|
110956
111296
|
selectToken: context2.selectToken,
|
|
110957
111297
|
encoding: 2,
|
|
110958
111298
|
alternateScreen,
|
|
111299
|
+
modes,
|
|
110959
111300
|
data: historyData
|
|
110960
111301
|
}, borshState.seqGen, borshState.maxFrameBytes);
|
|
110961
111302
|
sendToClient(ws, historyMessages);
|
|
@@ -111151,6 +111492,7 @@ class WebSocketServer {
|
|
|
111151
111492
|
currentTheme = null;
|
|
111152
111493
|
themeSignalLast = new Map;
|
|
111153
111494
|
lastThemeTimestamp = 0n;
|
|
111495
|
+
lastSettingsTimestamp = 0n;
|
|
111154
111496
|
pendingTmuxTheme = null;
|
|
111155
111497
|
themeApplyInFlight = false;
|
|
111156
111498
|
lastBroadcastTheme = new Map;
|
|
@@ -111197,8 +111539,8 @@ class WebSocketServer {
|
|
|
111197
111539
|
onTerminalOutput: (paneId, data) => {
|
|
111198
111540
|
this.broadcastTerminalOutput(deviceId, paneId, data);
|
|
111199
111541
|
},
|
|
111200
|
-
onTerminalHistory: (paneId, data, alternateScreen) => {
|
|
111201
|
-
this.broadcastTerminalHistory(deviceId, paneId, data, alternateScreen);
|
|
111542
|
+
onTerminalHistory: (paneId, data, alternateScreen, modes) => {
|
|
111543
|
+
this.broadcastTerminalHistory(deviceId, paneId, data, alternateScreen, modes);
|
|
111202
111544
|
},
|
|
111203
111545
|
onClipboardWrite: (paneId, text3) => {
|
|
111204
111546
|
this.broadcastClipboardWrite(deviceId, paneId, text3);
|
|
@@ -111321,7 +111663,6 @@ class WebSocketServer {
|
|
|
111321
111663
|
entry.clients.delete(ws);
|
|
111322
111664
|
delete ws.data.borshState.selectedPanes[deviceId];
|
|
111323
111665
|
delete ws.data.borshState.subscribedPanes[deviceId];
|
|
111324
|
-
this.clearPendingHistoryFetches(ws, deviceId);
|
|
111325
111666
|
if (entry.clients.size === 0) {
|
|
111326
111667
|
console.log(`[ws] no more clients for device ${deviceId}, disconnecting`);
|
|
111327
111668
|
this.releaseConnectionEntry(deviceId, entry);
|
|
@@ -111400,7 +111741,7 @@ class WebSocketServer {
|
|
|
111400
111741
|
}
|
|
111401
111742
|
case exports_ws_borsh.KIND_TMUX_RENAME_WINDOW: {
|
|
111402
111743
|
const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxRenameWindowSchema, payload);
|
|
111403
|
-
this.
|
|
111744
|
+
this.renameWindow(decoded.deviceId, decoded.windowId, decoded.name);
|
|
111404
111745
|
return;
|
|
111405
111746
|
}
|
|
111406
111747
|
case exports_ws_borsh.KIND_TMUX_SET_WINDOW_STYLE: {
|
|
@@ -111410,12 +111751,12 @@ class WebSocketServer {
|
|
|
111410
111751
|
}
|
|
111411
111752
|
case exports_ws_borsh.KIND_TMUX_REORDER_WINDOWS: {
|
|
111412
111753
|
const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxReorderWindowsSchema, payload);
|
|
111413
|
-
this.
|
|
111754
|
+
this.reorderWindows(decoded.deviceId, decoded.windowIds);
|
|
111414
111755
|
return;
|
|
111415
111756
|
}
|
|
111416
111757
|
case exports_ws_borsh.KIND_TMUX_REORDER_PANES: {
|
|
111417
111758
|
const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxReorderPanesSchema, payload);
|
|
111418
|
-
this.
|
|
111759
|
+
this.reorderPanes(decoded.deviceId, decoded.windowId, decoded.paneIds);
|
|
111419
111760
|
return;
|
|
111420
111761
|
}
|
|
111421
111762
|
case exports_ws_borsh.KIND_TMUX_SUBSCRIBE_PANES: {
|
|
@@ -111450,7 +111791,7 @@ class WebSocketServer {
|
|
|
111450
111791
|
}
|
|
111451
111792
|
case exports_ws_borsh.KIND_TMUX_RENAME_PANE: {
|
|
111452
111793
|
const decoded = exports_ws_borsh.decodePayload(exports_ws_borsh.schema.TmuxRenamePaneSchema, payload);
|
|
111453
|
-
this.
|
|
111794
|
+
this.renamePane(decoded.deviceId, decoded.paneId, decoded.name);
|
|
111454
111795
|
return;
|
|
111455
111796
|
}
|
|
111456
111797
|
case exports_ws_borsh.KIND_TMUX_MOVE_PANE: {
|
|
@@ -111522,11 +111863,11 @@ class WebSocketServer {
|
|
|
111522
111863
|
agentWsHub.registerClient(ws);
|
|
111523
111864
|
const helloS2C = {
|
|
111524
111865
|
serverImpl: "tmex-gateway",
|
|
111525
|
-
serverVersion:
|
|
111866
|
+
serverVersion: getDisplayVersion(),
|
|
111526
111867
|
selectedVersion: exports_ws_borsh.CURRENT_VERSION,
|
|
111527
111868
|
maxFrameBytes: serverMaxFrameBytes,
|
|
111528
111869
|
heartbeatIntervalMs: 15000,
|
|
111529
|
-
capabilities: [
|
|
111870
|
+
capabilities: [...GATEWAY_CAPABILITIES]
|
|
111530
111871
|
};
|
|
111531
111872
|
const payloadBytes = exports_ws_borsh.encodePayload(exports_ws_borsh.schema.HelloS2CSchema, helloS2C);
|
|
111532
111873
|
this.sendEnvelope(ws, exports_ws_borsh.KIND_HELLO_S2C, payloadBytes);
|
|
@@ -111624,20 +111965,11 @@ class WebSocketServer {
|
|
|
111624
111965
|
}
|
|
111625
111966
|
delete ws.data.borshState.selectedPanes[deviceId];
|
|
111626
111967
|
delete ws.data.borshState.subscribedPanes[deviceId];
|
|
111627
|
-
this.clearPendingHistoryFetches(ws, deviceId);
|
|
111628
111968
|
const disconnectedPayload = exports_ws_borsh.encodePayload(exports_ws_borsh.schema.DeviceDisconnectedSchema, {
|
|
111629
111969
|
deviceId
|
|
111630
111970
|
});
|
|
111631
111971
|
this.sendEnvelope(ws, exports_ws_borsh.KIND_DEVICE_DISCONNECTED, disconnectedPayload);
|
|
111632
111972
|
}
|
|
111633
|
-
clearPendingHistoryFetches(ws, deviceId) {
|
|
111634
|
-
const prefix = `${deviceId}:`;
|
|
111635
|
-
for (const key of ws.data.borshState.pendingHistoryFetches.keys()) {
|
|
111636
|
-
if (key.startsWith(prefix)) {
|
|
111637
|
-
ws.data.borshState.pendingHistoryFetches.delete(key);
|
|
111638
|
-
}
|
|
111639
|
-
}
|
|
111640
|
-
}
|
|
111641
111973
|
handleTmuxSelect(ws, data) {
|
|
111642
111974
|
const deviceId = data.deviceId;
|
|
111643
111975
|
const entry = this.connections.get(deviceId);
|
|
@@ -111765,7 +112097,7 @@ class WebSocketServer {
|
|
|
111765
112097
|
return;
|
|
111766
112098
|
entry.runtime.closePane(paneId);
|
|
111767
112099
|
}
|
|
111768
|
-
|
|
112100
|
+
renamePane(deviceId, paneId, name24) {
|
|
111769
112101
|
if (!isTmuxPaneId(paneId))
|
|
111770
112102
|
return;
|
|
111771
112103
|
const trimmed = name24.trim().slice(0, 64);
|
|
@@ -111777,6 +112109,7 @@ class WebSocketServer {
|
|
|
111777
112109
|
} else {
|
|
111778
112110
|
this.paneCustomNames.set(deviceId, new Map([[paneId, trimmed]]));
|
|
111779
112111
|
}
|
|
112112
|
+
this.broadcastSettingsUpdate("tree-order");
|
|
111780
112113
|
const entry = this.connections.get(deviceId);
|
|
111781
112114
|
if (!entry?.lastSnapshot)
|
|
111782
112115
|
return;
|
|
@@ -111805,7 +112138,7 @@ class WebSocketServer {
|
|
|
111805
112138
|
return;
|
|
111806
112139
|
entry.runtime.movePane(srcPaneId, dstPaneId, resolved);
|
|
111807
112140
|
}
|
|
111808
|
-
|
|
112141
|
+
renameWindow(deviceId, windowId, name24) {
|
|
111809
112142
|
const trimmed = name24.trim().slice(0, 64);
|
|
111810
112143
|
const names = this.windowCustomNames.get(deviceId);
|
|
111811
112144
|
if (!trimmed) {
|
|
@@ -111815,11 +112148,18 @@ class WebSocketServer {
|
|
|
111815
112148
|
} else {
|
|
111816
112149
|
this.windowCustomNames.set(deviceId, new Map([[windowId, trimmed]]));
|
|
111817
112150
|
}
|
|
112151
|
+
this.broadcastSettingsUpdate("tree-order");
|
|
111818
112152
|
const entry = this.connections.get(deviceId);
|
|
111819
112153
|
if (!entry?.lastSnapshot)
|
|
111820
112154
|
return;
|
|
111821
112155
|
this.sendSnapshotToClients(entry, entry.lastSnapshot);
|
|
111822
112156
|
}
|
|
112157
|
+
getCustomNames(deviceId) {
|
|
112158
|
+
return {
|
|
112159
|
+
windows: Object.fromEntries(this.windowCustomNames.get(deviceId) ?? []),
|
|
112160
|
+
panes: Object.fromEntries(this.paneCustomNames.get(deviceId) ?? [])
|
|
112161
|
+
};
|
|
112162
|
+
}
|
|
111823
112163
|
handleSetWindowStyle(deviceId, style) {
|
|
111824
112164
|
const entry = this.connections.get(deviceId);
|
|
111825
112165
|
if (!entry)
|
|
@@ -111848,6 +112188,7 @@ class WebSocketServer {
|
|
|
111848
112188
|
updateSiteSettings({ theme: themeName });
|
|
111849
112189
|
this.scheduleTmuxThemeApply(themeName);
|
|
111850
112190
|
this.broadcastSiteThemeUpdateS2C(themeName);
|
|
112191
|
+
this.broadcastSettingsUpdate("theme");
|
|
111851
112192
|
}
|
|
111852
112193
|
scheduleTmuxThemeApply(theme) {
|
|
111853
112194
|
this.pendingTmuxTheme = theme;
|
|
@@ -111885,6 +112226,21 @@ class WebSocketServer {
|
|
|
111885
112226
|
this.sendEnvelope(client, exports_ws_borsh.KIND_SITE_THEME_UPDATE, payloadBytes);
|
|
111886
112227
|
}
|
|
111887
112228
|
}
|
|
112229
|
+
broadcastSettingsUpdate(namespace) {
|
|
112230
|
+
const now2 = BigInt(Date.now());
|
|
112231
|
+
if (now2 <= this.lastSettingsTimestamp) {
|
|
112232
|
+
this.lastSettingsTimestamp += 1n;
|
|
112233
|
+
} else {
|
|
112234
|
+
this.lastSettingsTimestamp = now2;
|
|
112235
|
+
}
|
|
112236
|
+
const payloadBytes = exports_ws_borsh.encodePayload(exports_ws_borsh.schema.SettingsUpdateS2CSchema, {
|
|
112237
|
+
namespace,
|
|
112238
|
+
serverTimestamp: this.lastSettingsTimestamp
|
|
112239
|
+
});
|
|
112240
|
+
for (const client of this.connectedClients) {
|
|
112241
|
+
this.sendEnvelope(client, exports_ws_borsh.KIND_SETTINGS_UPDATE, payloadBytes);
|
|
112242
|
+
}
|
|
112243
|
+
}
|
|
111888
112244
|
async handleSiteThemeChange(theme) {
|
|
111889
112245
|
if (theme !== "dark" && theme !== "light") {
|
|
111890
112246
|
return;
|
|
@@ -111930,15 +112286,17 @@ class WebSocketServer {
|
|
|
111930
112286
|
}
|
|
111931
112287
|
}
|
|
111932
112288
|
}
|
|
111933
|
-
|
|
112289
|
+
reorderWindows(deviceId, windowIds) {
|
|
111934
112290
|
setWindowOrder(deviceId, windowIds);
|
|
112291
|
+
this.broadcastSettingsUpdate("tree-order");
|
|
111935
112292
|
const entry = this.connections.get(deviceId);
|
|
111936
112293
|
if (!entry?.lastSnapshot)
|
|
111937
112294
|
return;
|
|
111938
112295
|
this.sendSnapshotToClients(entry, entry.lastSnapshot);
|
|
111939
112296
|
}
|
|
111940
|
-
|
|
112297
|
+
reorderPanes(deviceId, windowId, paneIds) {
|
|
111941
112298
|
setPaneOrder(deviceId, windowId, paneIds);
|
|
112299
|
+
this.broadcastSettingsUpdate("tree-order");
|
|
111942
112300
|
const entry = this.connections.get(deviceId);
|
|
111943
112301
|
if (!entry?.lastSnapshot)
|
|
111944
112302
|
return;
|
|
@@ -111966,10 +112324,21 @@ class WebSocketServer {
|
|
|
111966
112324
|
const entry = this.connections.get(deviceId);
|
|
111967
112325
|
if (!entry || !isTmuxPaneId(paneId))
|
|
111968
112326
|
return;
|
|
111969
|
-
|
|
111970
|
-
|
|
112327
|
+
entry.runtime.fetchPaneHistory(paneId).then((captured) => {
|
|
112328
|
+
if (!captured)
|
|
112329
|
+
return;
|
|
112330
|
+
const payloadBytes = exports_ws_borsh.encodePayload(exports_ws_borsh.schema.TermHistorySchema, {
|
|
112331
|
+
deviceId,
|
|
112332
|
+
paneId,
|
|
112333
|
+
selectToken: requestToken,
|
|
112334
|
+
encoding: 1,
|
|
112335
|
+
alternateScreen: captured.alternateScreen,
|
|
112336
|
+
modes: captured.modes,
|
|
112337
|
+
data: new TextEncoder().encode(captured.data)
|
|
112338
|
+
});
|
|
112339
|
+
this.sendChunked(ws, exports_ws_borsh.KIND_TERM_HISTORY, payloadBytes);
|
|
112340
|
+
}).catch((error51) => {
|
|
111971
112341
|
console.warn(`[ws] fetch pane history failed on ${deviceId}/${paneId}:`, error51);
|
|
111972
|
-
ws.data.borshState.pendingHistoryFetches.delete(`${deviceId}:${paneId}`);
|
|
111973
112342
|
});
|
|
111974
112343
|
}
|
|
111975
112344
|
handleResizePaneById(deviceId, paneId, cols, rows) {
|
|
@@ -112226,36 +112595,20 @@ class WebSocketServer {
|
|
|
112226
112595
|
this.sendEnvelope(client, exports_ws_borsh.KIND_CLIPBOARD_WRITE, payloadBytes);
|
|
112227
112596
|
}
|
|
112228
112597
|
}
|
|
112229
|
-
broadcastTerminalHistory(deviceId, paneId, data, alternateScreen) {
|
|
112598
|
+
broadcastTerminalHistory(deviceId, paneId, data, alternateScreen, modes) {
|
|
112230
112599
|
const entry = this.connections.get(deviceId);
|
|
112231
112600
|
if (!entry)
|
|
112232
112601
|
return;
|
|
112233
112602
|
const historyBytes = new TextEncoder().encode(data);
|
|
112234
|
-
const fetchKey = `${deviceId}:${paneId}`;
|
|
112235
112603
|
for (const client of entry.clients) {
|
|
112236
112604
|
const txPaneId = switchBarrier.getTransactionPaneId(client, deviceId);
|
|
112237
112605
|
if (txPaneId !== null && txPaneId === paneId) {
|
|
112238
|
-
switchBarrier.sendTermHistory(client, deviceId, paneId, historyBytes, alternateScreen);
|
|
112606
|
+
switchBarrier.sendTermHistory(client, deviceId, paneId, historyBytes, alternateScreen, modes);
|
|
112239
112607
|
continue;
|
|
112240
112608
|
}
|
|
112241
112609
|
if (client.data.borshState.selectedPanes[deviceId] === paneId) {
|
|
112242
|
-
switchBarrier.sendTermHistory(client, deviceId, paneId, historyBytes, alternateScreen);
|
|
112243
|
-
continue;
|
|
112244
|
-
}
|
|
112245
|
-
const requestToken = client.data.borshState.pendingHistoryFetches.get(fetchKey);
|
|
112246
|
-
if (!requestToken) {
|
|
112247
|
-
continue;
|
|
112610
|
+
switchBarrier.sendTermHistory(client, deviceId, paneId, historyBytes, alternateScreen, modes);
|
|
112248
112611
|
}
|
|
112249
|
-
client.data.borshState.pendingHistoryFetches.delete(fetchKey);
|
|
112250
|
-
const payloadBytes = exports_ws_borsh.encodePayload(exports_ws_borsh.schema.TermHistorySchema, {
|
|
112251
|
-
deviceId,
|
|
112252
|
-
paneId,
|
|
112253
|
-
selectToken: requestToken,
|
|
112254
|
-
encoding: 1,
|
|
112255
|
-
alternateScreen,
|
|
112256
|
-
data: historyBytes
|
|
112257
|
-
});
|
|
112258
|
-
this.sendChunked(client, exports_ws_borsh.KIND_TERM_HISTORY, payloadBytes);
|
|
112259
112612
|
}
|
|
112260
112613
|
}
|
|
112261
112614
|
broadcastError(deviceId, err) {
|
|
@@ -112387,6 +112740,16 @@ async function createGatewayRuntime(options = {}) {
|
|
|
112387
112740
|
}, (theme) => {
|
|
112388
112741
|
wsServer.broadcastSiteThemeUpdateS2C(theme);
|
|
112389
112742
|
});
|
|
112743
|
+
registerSettingsBroadcaster((namespace) => {
|
|
112744
|
+
wsServer.broadcastSettingsUpdate(namespace);
|
|
112745
|
+
});
|
|
112746
|
+
registerTreeOverlayBridge({
|
|
112747
|
+
reorderWindows: (deviceId, windowIds) => wsServer.reorderWindows(deviceId, windowIds),
|
|
112748
|
+
reorderPanes: (deviceId, windowId, paneIds) => wsServer.reorderPanes(deviceId, windowId, paneIds),
|
|
112749
|
+
renameWindow: (deviceId, windowId, name24) => wsServer.renameWindow(deviceId, windowId, name24),
|
|
112750
|
+
renamePane: (deviceId, paneId, name24) => wsServer.renamePane(deviceId, paneId, name24),
|
|
112751
|
+
getCustomNames: (deviceId) => wsServer.getCustomNames(deviceId)
|
|
112752
|
+
});
|
|
112390
112753
|
await telegramService.refresh();
|
|
112391
112754
|
await weixinService.refresh();
|
|
112392
112755
|
await pushSupervisor.start();
|
|
@@ -112435,6 +112798,8 @@ async function createGatewayRuntime(options = {}) {
|
|
|
112435
112798
|
async stop() {
|
|
112436
112799
|
connectionAlertNotifier.setBroadcaster(null);
|
|
112437
112800
|
registerThemeBroadcaster(null);
|
|
112801
|
+
registerSettingsBroadcaster(null);
|
|
112802
|
+
registerTreeOverlayBridge(null);
|
|
112438
112803
|
wsServer.closeAll();
|
|
112439
112804
|
await watchService.stop();
|
|
112440
112805
|
await agentSupervisor.stop();
|