termdock 1.4.127 → 1.4.129

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/.desktop-dist/main.js +157 -28
  2. package/dist/client/assets/{ModelPreview-B3caplvh.js → ModelPreview-DA71QiMN.js} +1 -1
  3. package/dist/client/assets/{abnfDiagram-VRR7QNED-Pm2cPR47.js → abnfDiagram-VRR7QNED-vwQxXhvY.js} +1 -1
  4. package/dist/client/assets/{arc-Du2jqJEu.js → arc-KcBV2d81.js} +1 -1
  5. package/dist/client/assets/{architectureDiagram-ZJ3FMSHR-UZZ-hCDJ.js → architectureDiagram-ZJ3FMSHR-BKm_EWca.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-677ZJIJ3-DCdHiW0y.js → blockDiagram-677ZJIJ3-DAQx8c-B.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-LMCZKHZV-CI2wB8cp.js → c4Diagram-LMCZKHZV-BeYeekky.js} +1 -1
  8. package/dist/client/assets/channel-jqLwHPeC.js +1 -0
  9. package/dist/client/assets/{chunk-2Q5K7J3B-BOWA0kur.js → chunk-2Q5K7J3B-DHqXZZU-.js} +1 -1
  10. package/dist/client/assets/{chunk-32BRIVSS-7oLxVo5n.js → chunk-32BRIVSS-D1m2Benc.js} +1 -1
  11. package/dist/client/assets/{chunk-5VM5RSS4-CmqxvKXC.js → chunk-5VM5RSS4-CtOKKO1w.js} +1 -1
  12. package/dist/client/assets/{chunk-EX3LRPZG-DORF3Bb-.js → chunk-EX3LRPZG-CXjhbuNm.js} +1 -1
  13. package/dist/client/assets/{chunk-JWPE2WC7-CPf240uh.js → chunk-JWPE2WC7-C0Zq6OdN.js} +1 -1
  14. package/dist/client/assets/{chunk-MOJQB5TN-BXWYBupN.js → chunk-MOJQB5TN-BlkCCLDm.js} +1 -1
  15. package/dist/client/assets/{chunk-RYQCIY6F-DZNPiduN.js → chunk-RYQCIY6F-Cz6TWAav.js} +1 -1
  16. package/dist/client/assets/{chunk-V7JOEXUC-CmDRmHMg.js → chunk-V7JOEXUC-DhLyQr8d.js} +1 -1
  17. package/dist/client/assets/{chunk-VR4S4FIN-DHHyq_Zz.js → chunk-VR4S4FIN-DSnFyHH_.js} +1 -1
  18. package/dist/client/assets/{chunk-XXDRQBXY-C8ImJLqT.js → chunk-XXDRQBXY-C2ISI6ro.js} +1 -1
  19. package/dist/client/assets/classDiagram-OUVF2IWQ-DFjGJuxW.js +1 -0
  20. package/dist/client/assets/classDiagram-v2-EOCWNBFH-DFjGJuxW.js +1 -0
  21. package/dist/client/assets/{cose-bilkent-JH36ORCC-9vG_EL3b.js → cose-bilkent-JH36ORCC-DQVr0EsM.js} +1 -1
  22. package/dist/client/assets/{cynefin-VYW2F7L2-CIs-32JD.js → cynefin-VYW2F7L2-BP6p28mL.js} +1 -1
  23. package/dist/client/assets/{cynefinDiagram-TSTJHNR4-DikbAwAV.js → cynefinDiagram-TSTJHNR4-CPUSyMuB.js} +1 -1
  24. package/dist/client/assets/{dagre-VKFMJZFB-CfrhX7w8.js → dagre-VKFMJZFB-C_zQd2eB.js} +1 -1
  25. package/dist/client/assets/{diagram-FQU43EPY-Dyrs6fiZ.js → diagram-FQU43EPY-RkUQLZyi.js} +1 -1
  26. package/dist/client/assets/{diagram-G47NLZAW-BpT0tI-h.js → diagram-G47NLZAW-CtjAPFXS.js} +1 -1
  27. package/dist/client/assets/{diagram-NH7WQ7WH-CFTgimjj.js → diagram-NH7WQ7WH-C5xtKZ-W.js} +1 -1
  28. package/dist/client/assets/{diagram-OA4YK3LP-ROVSgH9I.js → diagram-OA4YK3LP-CrbMkTb7.js} +1 -1
  29. package/dist/client/assets/{diagram-WEI45ONY-CGcDsOXD.js → diagram-WEI45ONY-DAF4URgC.js} +1 -1
  30. package/dist/client/assets/{ebnfDiagram-CCIWWBDH-BMAXtWJG.js → ebnfDiagram-CCIWWBDH-ni71VSx1.js} +1 -1
  31. package/dist/client/assets/{erDiagram-Q63AITRT-C80qorTS.js → erDiagram-Q63AITRT-DODYotxF.js} +1 -1
  32. package/dist/client/assets/{flowDiagram-23GEKE2U-SHOUH72g.js → flowDiagram-23GEKE2U-CN1Vp7G4.js} +1 -1
  33. package/dist/client/assets/{ganttDiagram-NO4QXBWP-DTCfORwE.js → ganttDiagram-NO4QXBWP-DoVPMnyV.js} +1 -1
  34. package/dist/client/assets/{gitGraphDiagram-IHSO6WYX--f38fniT.js → gitGraphDiagram-IHSO6WYX-jiV9FRlU.js} +1 -1
  35. package/dist/client/assets/{index-wAbbn4Kn.js → index-DPj6Kass.js} +67 -67
  36. package/dist/client/assets/{infoDiagram-FWYZ7A6U-Bjyyad06.js → infoDiagram-FWYZ7A6U-Bk78PinY.js} +1 -1
  37. package/dist/client/assets/{ishikawaDiagram-FXEZZL3T-DIRrTmK4.js → ishikawaDiagram-FXEZZL3T-C3lsh4Lh.js} +1 -1
  38. package/dist/client/assets/{journeyDiagram-5HDEW3XC-DscBOIxr.js → journeyDiagram-5HDEW3XC-CHLuYRBt.js} +1 -1
  39. package/dist/client/assets/{kanban-definition-HUTT4EX6-IDE8xWjr.js → kanban-definition-HUTT4EX6-UXjM1jpV.js} +1 -1
  40. package/dist/client/assets/{linear-EZXDqVdB.js → linear-BKUyrWyw.js} +1 -1
  41. package/dist/client/assets/{mermaid.core-Ctixq-l7.js → mermaid.core-Bhj0Bx21.js} +4 -4
  42. package/dist/client/assets/{mindmap-definition-LN4V7U3C-DbExuHFY.js → mindmap-definition-LN4V7U3C-Dxv1Vfld.js} +1 -1
  43. package/dist/client/assets/{pegDiagram-2B236MQR-BkPjbAG_.js → pegDiagram-2B236MQR-DYZ4d5zF.js} +1 -1
  44. package/dist/client/assets/{pieDiagram-ENE6RG2P-D_lAR-It.js → pieDiagram-ENE6RG2P-BoId8qhV.js} +1 -1
  45. package/dist/client/assets/{quadrantDiagram-ABIIQ3AL-CVF1_nGt.js → quadrantDiagram-ABIIQ3AL-sswrNp8d.js} +1 -1
  46. package/dist/client/assets/{railroadDiagram-RFXS5EU6-C1TDrvOx.js → railroadDiagram-RFXS5EU6-BfYV2CjC.js} +1 -1
  47. package/dist/client/assets/{requirementDiagram-TGXJPOKE-5jOozNKC.js → requirementDiagram-TGXJPOKE-DZhZPZVt.js} +1 -1
  48. package/dist/client/assets/{sankeyDiagram-HTMAVEWB-CKPHCzaS.js → sankeyDiagram-HTMAVEWB-DXKoOi7e.js} +1 -1
  49. package/dist/client/assets/{sequenceDiagram-DBY2YBRQ-tBpAtlZ_.js → sequenceDiagram-DBY2YBRQ-CpulK2HV.js} +1 -1
  50. package/dist/client/assets/{sizeCapture-X5ZJPWSS-Ctwe0aFO.js → sizeCapture-X5ZJPWSS-D-mlzS9r.js} +1 -1
  51. package/dist/client/assets/{stateDiagram-2N3HPSRC-xJM2eLWM.js → stateDiagram-2N3HPSRC-l_ydCaW0.js} +1 -1
  52. package/dist/client/assets/stateDiagram-v2-6OUMAXLB-Gh5mC4sm.js +1 -0
  53. package/dist/client/assets/{swimlanes-5IMT3BWC-DTWYG-dw.js → swimlanes-5IMT3BWC-eEUQLyov.js} +2 -2
  54. package/dist/client/assets/swimlanesDiagram-G3AALYLV-CFuSbo_y.js +8 -0
  55. package/dist/client/assets/{timeline-definition-FHXFAJF6-CDuhXHMB.js → timeline-definition-FHXFAJF6-Bu7sztn9.js} +1 -1
  56. package/dist/client/assets/{vennDiagram-L72KCM5P-BYljcRnF.js → vennDiagram-L72KCM5P-Bat45ZW0.js} +1 -1
  57. package/dist/client/assets/{wardleyDiagram-EHGQE667-Q49XcSX3.js → wardleyDiagram-EHGQE667-Bxn0-4Oq.js} +1 -1
  58. package/dist/client/assets/{xychartDiagram-FW5EYKEG-0nmuMvBg.js → xychartDiagram-FW5EYKEG-C4BdUEul.js} +1 -1
  59. package/dist/client/index.html +1 -1
  60. package/dist/client/sw.js +1 -1
  61. package/dist/server/routes/terminal.js +24 -17
  62. package/dist/server/utils/desktopRuntimeOwner.js +105 -0
  63. package/package.json +1 -1
  64. package/runtime-manifest.json +2 -2
  65. package/dist/client/assets/channel-j6Ch4-AO.js +0 -1
  66. package/dist/client/assets/classDiagram-OUVF2IWQ-DYdO3KAi.js +0 -1
  67. package/dist/client/assets/classDiagram-v2-EOCWNBFH-DYdO3KAi.js +0 -1
  68. package/dist/client/assets/stateDiagram-v2-6OUMAXLB-LbiwUd_W.js +0 -1
  69. package/dist/client/assets/swimlanesDiagram-G3AALYLV-D-h9Zx5q.js +0 -8
@@ -3,16 +3,19 @@ import { execFile, spawn } from 'node:child_process';
3
3
  import crypto from 'node:crypto';
4
4
  import dgram from 'node:dgram';
5
5
  import fs from 'node:fs';
6
+ import http from 'node:http';
6
7
  import https from 'node:https';
7
8
  import os from 'node:os';
8
9
  import path from 'node:path';
9
10
  import { promisify } from 'node:util';
10
11
  import { fileURLToPath } from 'node:url';
11
12
  import { desktopStatusTooltip, formatCompactDesktopStatus, menuBarStatusRows, mergeServiceActivity, nextServiceOrigin, normalizeServiceActivity, summarizeServiceActivity, } from './activityStatus.js';
12
- import { checkForDesktopUpdates, checkForRuntimeUpdates, configureDesktopUpdater, ensureLatestRuntime, getDesktopUpdateState, getDesktopRuntimeUpdateState, installDownloadedDesktopUpdate, markDesktopRuntimeRestarting, markDesktopRuntimeRunning, subscribeDesktopRuntimeUpdateState, subscribeDesktopUpdateState, } from './updater.js';
13
+ import { checkForDesktopUpdates, checkForRuntimeUpdates, configureDesktopUpdater, ensureLatestRuntime, getDesktopUpdateState, getDesktopRuntimeUpdateState, installDownloadedDesktopUpdate, markDesktopRuntimeRestartFailed, markDesktopRuntimeRestarting, markDesktopRuntimeRunning, subscribeDesktopRuntimeUpdateState, subscribeDesktopUpdateState, } from './updater.js';
13
14
  import { resolvePackagedRuntime, rollbackDownloadedRuntime, } from './runtime.js';
14
15
  import { isExternalLinkStagingUrl, isSafeExternalUrl } from './externalLinks.js';
15
16
  import { shouldThrottleDesktopRenderer } from './windowPolicy.js';
17
+ import { checkConnectedServiceRuntime, getConnectedServiceRuntimeState, restartConnectedServiceRuntime, } from './connectedServiceRuntime.js';
18
+ import { isOwnedDesktopRuntimeTarget } from './runtimeTarget.js';
16
19
  import { canOfferCertificateTrust, downloadCertificateAuthority, isCertificateTrustError, isLocalNetworkHostname, } from './certificateTrust.js';
17
20
  const execFileAsync = promisify(execFile);
18
21
  const currentDir = path.dirname(fileURLToPath(import.meta.url));
@@ -20,6 +23,7 @@ const projectRoot = path.resolve(currentDir, '..');
20
23
  const termdockDir = path.join(os.homedir(), '.termdock');
21
24
  const desktopConfigPath = path.join(termdockDir, 'desktop.json');
22
25
  const serverStatePath = path.join(termdockDir, 'server.json');
26
+ const desktopRuntimeOwnerSocketPath = path.join(termdockDir, 'desktop-runtime-owner.sock');
23
27
  const DEFAULT_LOCAL_URL = 'http://localhost:9834';
24
28
  const PROTOCOL_VERSION = 1;
25
29
  const HEALTH_TIMEOUT_MS = 3_500;
@@ -64,6 +68,9 @@ let menuBarStatus = null;
64
68
  let menuBarStatusWidth = 0;
65
69
  let floatingWidgetWindow = null;
66
70
  let floatingPositionTimer = null;
71
+ let desktopRuntimeOwnerServer = null;
72
+ let connectedServiceRuntimePollTimer = null;
73
+ let connectedServiceRuntimePollInFlight = false;
67
74
  let isQuitting = false;
68
75
  const FLOATING_WIDGET_WIDTHS = [64, 108, 152];
69
76
  const FLOATING_WIDGET_HEIGHT = 40;
@@ -989,6 +996,7 @@ function desktopRuntimeEnv(runtime = runtimePaths()) {
989
996
  .filter(Boolean)
990
997
  .join(path.delimiter),
991
998
  TERMDOCK_DESKTOP: '1',
999
+ TERMDOCK_DESKTOP_OWNER_SOCKET: desktopRuntimeOwnerSocketPath,
992
1000
  TERMDOCK_BUNDLED_RUNTIME: app.isPackaged ? '1' : '0',
993
1001
  TERMDOCK_VERSION: runtime.version,
994
1002
  TERMDOCK_DESKTOP_SHELL_VERSION: app.getVersion(),
@@ -1134,28 +1142,137 @@ async function startLocalService() {
1134
1142
  }
1135
1143
  async function restartDesktopManagedRuntime() {
1136
1144
  const status = await getLocalServiceStatus();
1137
- if (status.running) {
1138
- if (status.probe?.desktopManaged !== true) {
1139
- throw new Error('当前本机服务不是由桌面版启动的,不能由桌面版自动重启。');
1140
- }
1141
- markDesktopRuntimeRestarting();
1142
- const pid = status.state?.pid;
1143
- if (!pid || !isProcessRunning(pid)) {
1144
- throw new Error('桌面服务状态已失效,请重新打开连接中心。');
1145
+ const update = getDesktopRuntimeUpdateState();
1146
+ if (!status.running || status.probe?.desktopManaged !== true) {
1147
+ throw new Error('当前服务不是由这个 Termdock Desktop 宿主管理的。');
1148
+ }
1149
+ if (update.status !== 'ready' || !update.latestVersion) {
1150
+ throw new Error('没有等待重启的 Runtime 更新。');
1151
+ }
1152
+ markDesktopRuntimeRestarting();
1153
+ const restartTimer = setTimeout(() => {
1154
+ void (async () => {
1155
+ const pid = status.state?.pid;
1156
+ if (!pid || !isProcessRunning(pid)) {
1157
+ throw new Error('本机服务状态已失效,请重试。');
1158
+ }
1159
+ process.kill(pid, 'SIGTERM');
1160
+ const deadline = Date.now() + 15_000;
1161
+ while (isProcessRunning(pid) && Date.now() < deadline) {
1162
+ await new Promise((resolve) => setTimeout(resolve, 150));
1163
+ }
1164
+ if (isProcessRunning(pid))
1165
+ throw new Error(`本机服务 PID ${pid} 未能正常退出。`);
1166
+ const latest = readServerState();
1167
+ if (latest?.pid === pid)
1168
+ fs.rmSync(serverStatePath, { force: true });
1169
+ await startLocalService();
1170
+ })().catch((error) => {
1171
+ markDesktopRuntimeRestartFailed(error);
1172
+ console.error('[desktop-runtime] restart failed', error);
1173
+ });
1174
+ }, 250);
1175
+ restartTimer.unref();
1176
+ return getDesktopRuntimeUpdateState();
1177
+ }
1178
+ function isOwnedDesktopRuntimeWindow(window, status) {
1179
+ const origin = windowServiceOrigins.get(window);
1180
+ if (!origin || !status.running || status.probe?.desktopManaged !== true || !status.state)
1181
+ return false;
1182
+ const localAddresses = new Set(Object.values(os.networkInterfaces())
1183
+ .flatMap((addresses) => addresses?.map((address) => address.address.toLowerCase()) ?? []));
1184
+ return isOwnedDesktopRuntimeTarget({
1185
+ origin,
1186
+ servicePort: status.state.port,
1187
+ desktopManaged: true,
1188
+ localAddresses,
1189
+ });
1190
+ }
1191
+ async function routeRuntimeOperationForWindow(webContents, desktopOperation, serviceOperation) {
1192
+ const sourceWindow = BrowserWindow.fromWebContents(webContents);
1193
+ if (!sourceWindow || !windowServiceOrigins.has(sourceWindow)) {
1194
+ throw new Error('只能从已连接的 Termdock 服务窗口操作 Runtime。');
1195
+ }
1196
+ const status = await getLocalServiceStatus();
1197
+ return isOwnedDesktopRuntimeWindow(sourceWindow, status)
1198
+ ? desktopOperation()
1199
+ : serviceOperation();
1200
+ }
1201
+ function startConnectedServiceRuntimePolling() {
1202
+ if (connectedServiceRuntimePollTimer)
1203
+ return;
1204
+ const poll = async () => {
1205
+ if (connectedServiceRuntimePollInFlight)
1206
+ return;
1207
+ connectedServiceRuntimePollInFlight = true;
1208
+ try {
1209
+ const status = await getLocalServiceStatus();
1210
+ await Promise.all(BrowserWindow.getAllWindows().map(async (window) => {
1211
+ if (window.isDestroyed() || !windowServiceOrigins.has(window))
1212
+ return;
1213
+ if (isOwnedDesktopRuntimeWindow(window, status))
1214
+ return;
1215
+ try {
1216
+ const state = await getConnectedServiceRuntimeState(window.webContents);
1217
+ if (!window.isDestroyed()) {
1218
+ window.webContents.send('desktop:runtime-update-state-changed', state);
1219
+ }
1220
+ }
1221
+ catch {
1222
+ // A disconnected or older service will be retried on the next poll.
1223
+ }
1224
+ }));
1145
1225
  }
1146
- process.kill(pid, 'SIGTERM');
1147
- const deadline = Date.now() + 15_000;
1148
- while (isProcessRunning(pid) && Date.now() < deadline) {
1149
- await new Promise((resolve) => setTimeout(resolve, 150));
1226
+ finally {
1227
+ connectedServiceRuntimePollInFlight = false;
1150
1228
  }
1151
- if (isProcessRunning(pid))
1152
- throw new Error(`桌面服务 PID ${pid} 未能正常退出。`);
1153
- const latest = readServerState();
1154
- if (latest?.pid === pid)
1155
- fs.rmSync(serverStatePath, { force: true });
1156
- }
1157
- await startLocalService();
1158
- return getDesktopRuntimeUpdateState();
1229
+ };
1230
+ void poll();
1231
+ connectedServiceRuntimePollTimer = setInterval(() => void poll(), 2_000);
1232
+ connectedServiceRuntimePollTimer.unref();
1233
+ }
1234
+ function writeRuntimeOwnerResponse(response, statusCode, payload) {
1235
+ response.writeHead(statusCode, { 'content-type': 'application/json; charset=utf-8' });
1236
+ response.end(JSON.stringify(payload));
1237
+ }
1238
+ async function startDesktopRuntimeOwnerServer() {
1239
+ if (desktopRuntimeOwnerServer)
1240
+ return;
1241
+ fs.mkdirSync(termdockDir, { recursive: true, mode: 0o700 });
1242
+ fs.rmSync(desktopRuntimeOwnerSocketPath, { force: true });
1243
+ const server = http.createServer((request, response) => {
1244
+ void (async () => {
1245
+ if (request.method === 'GET' && request.url === '/runtime-update') {
1246
+ writeRuntimeOwnerResponse(response, 200, getDesktopRuntimeUpdateState());
1247
+ return;
1248
+ }
1249
+ if (request.method === 'POST' && request.url === '/runtime-update/check') {
1250
+ writeRuntimeOwnerResponse(response, 200, await checkForRuntimeUpdates());
1251
+ return;
1252
+ }
1253
+ if (request.method === 'POST' && request.url === '/runtime-update/restart') {
1254
+ writeRuntimeOwnerResponse(response, 202, await restartDesktopManagedRuntime());
1255
+ return;
1256
+ }
1257
+ writeRuntimeOwnerResponse(response, 404, { error: '未知的 Desktop Runtime 操作。' });
1258
+ })().catch((error) => {
1259
+ writeRuntimeOwnerResponse(response, 409, {
1260
+ error: error instanceof Error ? error.message : String(error),
1261
+ });
1262
+ });
1263
+ });
1264
+ await new Promise((resolve, reject) => {
1265
+ server.once('error', reject);
1266
+ server.listen(desktopRuntimeOwnerSocketPath, () => {
1267
+ server.off('error', reject);
1268
+ resolve();
1269
+ });
1270
+ });
1271
+ server.on('error', (error) => {
1272
+ console.error('[desktop-runtime] owner socket failed', error);
1273
+ });
1274
+ fs.chmodSync(desktopRuntimeOwnerSocketPath, 0o600);
1275
+ desktopRuntimeOwnerServer = server;
1159
1276
  }
1160
1277
  function shellQuote(value) {
1161
1278
  return `'${value.replace(/'/g, `'\\''`)}'`;
@@ -1650,9 +1767,9 @@ function installIpcHandlers() {
1650
1767
  ipcMain.handle('desktop:update-state', () => getDesktopUpdateState());
1651
1768
  ipcMain.handle('desktop:check-update', () => checkForDesktopUpdates());
1652
1769
  ipcMain.handle('desktop:install-update', () => installDownloadedDesktopUpdate());
1653
- ipcMain.handle('desktop:runtime-update-state', () => getDesktopRuntimeUpdateState());
1654
- ipcMain.handle('desktop:check-runtime-update', () => checkForRuntimeUpdates());
1655
- ipcMain.handle('desktop:restart-runtime', () => restartDesktopManagedRuntime());
1770
+ ipcMain.handle('desktop:runtime-update-state', (event) => routeRuntimeOperationForWindow(event.sender, () => getDesktopRuntimeUpdateState(), () => getConnectedServiceRuntimeState(event.sender)));
1771
+ ipcMain.handle('desktop:check-runtime-update', (event) => routeRuntimeOperationForWindow(event.sender, () => checkForRuntimeUpdates(), () => checkConnectedServiceRuntime(event.sender)));
1772
+ ipcMain.handle('desktop:restart-runtime', (event) => routeRuntimeOperationForWindow(event.sender, () => restartDesktopManagedRuntime(), () => restartConnectedServiceRuntime(event.sender)));
1656
1773
  ipcMain.handle('desktop:show-connection-center', () => showConnectionCenter());
1657
1774
  ipcMain.handle('desktop:reveal-data-directory', async () => {
1658
1775
  fs.mkdirSync(termdockDir, { recursive: true, mode: 0o700 });
@@ -1924,6 +2041,7 @@ function installMenu() {
1924
2041
  app.whenReady().then(async () => {
1925
2042
  triggerLocalNetworkPermission();
1926
2043
  configureLocalServiceCertificateTrust();
2044
+ await startDesktopRuntimeOwnerServer();
1927
2045
  installIpcHandlers();
1928
2046
  installMenu();
1929
2047
  refreshDesktopStatusSurfaces();
@@ -1937,11 +2055,15 @@ app.whenReady().then(async () => {
1937
2055
  }
1938
2056
  });
1939
2057
  subscribeDesktopRuntimeUpdateState((state) => {
1940
- for (const window of BrowserWindow.getAllWindows()) {
1941
- if (!window.isDestroyed())
1942
- window.webContents.send('desktop:runtime-update-state-changed', state);
1943
- }
2058
+ void getLocalServiceStatus().then((status) => {
2059
+ for (const window of BrowserWindow.getAllWindows()) {
2060
+ if (!window.isDestroyed() && isOwnedDesktopRuntimeWindow(window, status)) {
2061
+ window.webContents.send('desktop:runtime-update-state-changed', state);
2062
+ }
2063
+ }
2064
+ });
1944
2065
  });
2066
+ startConnectedServiceRuntimePolling();
1945
2067
  const startupConfig = readDesktopConfig();
1946
2068
  const restoreUrls = startupConfig.openConnectionUrls;
1947
2069
  startupRestoreActive = true;
@@ -2000,5 +2122,12 @@ app.on('window-all-closed', () => {
2000
2122
  });
2001
2123
  app.on('before-quit', () => {
2002
2124
  isQuitting = true;
2125
+ desktopRuntimeOwnerServer?.close();
2126
+ desktopRuntimeOwnerServer = null;
2127
+ if (connectedServiceRuntimePollTimer)
2128
+ clearInterval(connectedServiceRuntimePollTimer);
2129
+ connectedServiceRuntimePollTimer = null;
2130
+ connectedServiceRuntimePollInFlight = false;
2131
+ fs.rmSync(desktopRuntimeOwnerSocketPath, { force: true });
2003
2132
  });
2004
2133
  export { PROTOCOL_VERSION };