@livedesk/hub 0.1.46 → 0.1.47
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/package.json +1 -1
- package/src/agents/agent-result-enrichment.js +66 -66
- package/src/agents/codex-agent-runtime.js +4 -4
- package/src/console-relay.js +424 -424
- package/src/live-desk-update.js +24 -24
- package/src/remote-hub.js +6 -4
- package/src/server.js +92 -92
- package/src/settings/settings-schema.js +3 -2
package/src/live-desk-update.js
CHANGED
|
@@ -241,11 +241,11 @@ function resetReconnectCandidate(target) {
|
|
|
241
241
|
target.stabilityDeadlineAt = '';
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
export function createLiveDeskUpdateManager({
|
|
245
|
-
remoteHub,
|
|
246
|
-
currentManagerVersion,
|
|
247
|
-
currentClientVersion,
|
|
248
|
-
excludedDeviceIds = [],
|
|
244
|
+
export function createLiveDeskUpdateManager({
|
|
245
|
+
remoteHub,
|
|
246
|
+
currentManagerVersion,
|
|
247
|
+
currentClientVersion,
|
|
248
|
+
excludedDeviceIds = [],
|
|
249
249
|
restartSupported = false,
|
|
250
250
|
requestHubRestart,
|
|
251
251
|
fetchImpl = globalThis.fetch,
|
|
@@ -261,16 +261,16 @@ export function createLiveDeskUpdateManager({
|
|
|
261
261
|
let checkPromise = null;
|
|
262
262
|
let run = null;
|
|
263
263
|
let checkTimer = null;
|
|
264
|
-
let runTimer = null;
|
|
265
|
-
const excludedDeviceIdSet = new Set(
|
|
266
|
-
(Array.isArray(excludedDeviceIds) ? excludedDeviceIds : [excludedDeviceIds])
|
|
267
|
-
.map(value => String(value || '').trim())
|
|
268
|
-
.filter(Boolean)
|
|
269
|
-
);
|
|
270
|
-
const connectedClientDevices = () => connectedDevices(remoteHub)
|
|
271
|
-
.filter(device => !excludedDeviceIdSet.has(String(device?.deviceId || '')));
|
|
272
|
-
const knownOfflineClientDevices = () => knownOfflineDevices(remoteHub)
|
|
273
|
-
.filter(device => !excludedDeviceIdSet.has(String(device?.deviceId || '')));
|
|
264
|
+
let runTimer = null;
|
|
265
|
+
const excludedDeviceIdSet = new Set(
|
|
266
|
+
(Array.isArray(excludedDeviceIds) ? excludedDeviceIds : [excludedDeviceIds])
|
|
267
|
+
.map(value => String(value || '').trim())
|
|
268
|
+
.filter(Boolean)
|
|
269
|
+
);
|
|
270
|
+
const connectedClientDevices = () => connectedDevices(remoteHub)
|
|
271
|
+
.filter(device => !excludedDeviceIdSet.has(String(device?.deviceId || '')));
|
|
272
|
+
const knownOfflineClientDevices = () => knownOfflineDevices(remoteHub)
|
|
273
|
+
.filter(device => !excludedDeviceIdSet.has(String(device?.deviceId || '')));
|
|
274
274
|
const effectiveClientBatchSize = Math.max(
|
|
275
275
|
1,
|
|
276
276
|
Math.min(50, Math.floor(Number(clientBatchSize) || LIVE_DESK_UPDATE_CLIENT_BATCH_SIZE))
|
|
@@ -321,7 +321,7 @@ export function createLiveDeskUpdateManager({
|
|
|
321
321
|
const getStatus = () => {
|
|
322
322
|
const managerUpdateAvailable = !!latestRelease
|
|
323
323
|
&& compareVersions(latestRelease.latestManagerVersion, currentManagerVersion) > 0;
|
|
324
|
-
const clientDevices = connectedClientDevices();
|
|
324
|
+
const clientDevices = connectedClientDevices();
|
|
325
325
|
const outdatedClientDevices = latestRelease
|
|
326
326
|
? clientDevices.filter(device => deviceNeedsUpdate(
|
|
327
327
|
device,
|
|
@@ -330,7 +330,7 @@ export function createLiveDeskUpdateManager({
|
|
|
330
330
|
))
|
|
331
331
|
: [];
|
|
332
332
|
const pendingOfflineClientCount = latestRelease
|
|
333
|
-
? knownOfflineClientDevices().filter(device => deviceNeedsUpdate(
|
|
333
|
+
? knownOfflineClientDevices().filter(device => deviceNeedsUpdate(
|
|
334
334
|
device,
|
|
335
335
|
latestRelease.latestManagerVersion,
|
|
336
336
|
latestRelease.latestClientVersion
|
|
@@ -414,9 +414,9 @@ export function createLiveDeskUpdateManager({
|
|
|
414
414
|
if (!run || run.state !== 'failed') return [];
|
|
415
415
|
const currentTime = now();
|
|
416
416
|
const devices = new Map(
|
|
417
|
-
remoteHub.listDevices({ includeDataUrl: false })
|
|
418
|
-
.filter(device => !excludedDeviceIdSet.has(String(device?.deviceId || '')))
|
|
419
|
-
.map(device => [String(device.deviceId), device])
|
|
417
|
+
remoteHub.listDevices({ includeDataUrl: false })
|
|
418
|
+
.filter(device => !excludedDeviceIdSet.has(String(device?.deviceId || '')))
|
|
419
|
+
.map(device => [String(device.deviceId), device])
|
|
420
420
|
);
|
|
421
421
|
return run.targets.filter(target => {
|
|
422
422
|
if (target.state !== 'failed' || !target.dispatchedAt) return false;
|
|
@@ -523,7 +523,7 @@ export function createLiveDeskUpdateManager({
|
|
|
523
523
|
const activeCount = run.targets.filter(target => target.state === 'waiting').length;
|
|
524
524
|
let availableSlots = Math.max(0, run.batchSize - activeCount);
|
|
525
525
|
if (availableSlots <= 0) return true;
|
|
526
|
-
const devices = new Map(connectedClientDevices().map(device => [String(device.deviceId), device]));
|
|
526
|
+
const devices = new Map(connectedClientDevices().map(device => [String(device.deviceId), device]));
|
|
527
527
|
for (const target of run.targets) {
|
|
528
528
|
if (availableSlots <= 0) break;
|
|
529
529
|
if (!['queued', 'pending-offline'].includes(target.state)) continue;
|
|
@@ -562,7 +562,7 @@ export function createLiveDeskUpdateManager({
|
|
|
562
562
|
failRun(`Timed out waiting for ${unfinishedCount} client(s) to finish the rollout.`);
|
|
563
563
|
return;
|
|
564
564
|
}
|
|
565
|
-
const devices = new Map(connectedClientDevices().map(device => [String(device.deviceId), device]));
|
|
565
|
+
const devices = new Map(connectedClientDevices().map(device => [String(device.deviceId), device]));
|
|
566
566
|
for (const target of run.targets) {
|
|
567
567
|
if (target.state === 'failed' || target.state === 'completed') continue;
|
|
568
568
|
const device = devices.get(target.deviceId);
|
|
@@ -689,7 +689,7 @@ export function createLiveDeskUpdateManager({
|
|
|
689
689
|
if (!release) return { ok: false, error: checkError || 'LiveDesk update check failed.', ...getStatus() };
|
|
690
690
|
const managerNeedsUpdate = compareVersions(release.latestManagerVersion, currentManagerVersion) > 0;
|
|
691
691
|
const clientPackageNeedsUpdate = compareVersions(release.latestClientVersion, currentClientVersion) > 0;
|
|
692
|
-
const connected = connectedClientDevices();
|
|
692
|
+
const connected = connectedClientDevices();
|
|
693
693
|
const outdatedClients = connected.filter(device => deviceNeedsUpdate(
|
|
694
694
|
device,
|
|
695
695
|
release.latestManagerVersion,
|
|
@@ -790,7 +790,7 @@ export function createLiveDeskUpdateManager({
|
|
|
790
790
|
if (target.method === 'dedicated'
|
|
791
791
|
&& target.bootstrapRetryCount === 0
|
|
792
792
|
&& isDedicatedBootstrapFailure(failure)) {
|
|
793
|
-
const retryDevice = connectedClientDevices()
|
|
793
|
+
const retryDevice = connectedClientDevices()
|
|
794
794
|
.find(device => String(device.deviceId || '') === target.deviceId);
|
|
795
795
|
const remainingMs = Date.parse(target.deadlineAt || '') - now();
|
|
796
796
|
if (retryDevice?.connected === true && remainingMs >= 10_000) {
|
package/src/remote-hub.js
CHANGED
|
@@ -1164,10 +1164,12 @@ function normalizeRemoteKeyboardKey(value) {
|
|
|
1164
1164
|
return raw === ' ' ? ' ' : safeString(raw, 80);
|
|
1165
1165
|
}
|
|
1166
1166
|
|
|
1167
|
-
function normalizeRemoteKeyboardText(value) {
|
|
1168
|
-
const raw = String(value ?? '').replace(/\0/g, '');
|
|
1169
|
-
|
|
1170
|
-
|
|
1167
|
+
function normalizeRemoteKeyboardText(value) {
|
|
1168
|
+
const raw = String(value ?? '').replace(/\0/g, '');
|
|
1169
|
+
// Remote text is input data, not a label. Preserve leading/trailing spaces
|
|
1170
|
+
// and IME whitespace while keeping every ordered message bounded.
|
|
1171
|
+
return raw.slice(0, 256);
|
|
1172
|
+
}
|
|
1171
1173
|
|
|
1172
1174
|
function safeTaskData(value) {
|
|
1173
1175
|
if (value === undefined || value === null) return undefined;
|
package/src/server.js
CHANGED
|
@@ -7,9 +7,9 @@ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, wri
|
|
|
7
7
|
import { dirname, resolve } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import os from 'node:os';
|
|
10
|
-
import { WebSocketServer } from 'ws';
|
|
11
|
-
import { createRemoteHub } from './remote-hub.js';
|
|
12
|
-
import { createHubConsoleRelay } from './console-relay.js';
|
|
10
|
+
import { WebSocketServer } from 'ws';
|
|
11
|
+
import { createRemoteHub } from './remote-hub.js';
|
|
12
|
+
import { createHubConsoleRelay } from './console-relay.js';
|
|
13
13
|
import {
|
|
14
14
|
buildImmutableRemoteFramePacket,
|
|
15
15
|
createRemoteFramePacketMetrics,
|
|
@@ -40,9 +40,9 @@ import { createAgentDeviceScope, resolveAgentTargetIds } from './agents/agent-de
|
|
|
40
40
|
import { AgentRuntimeError } from './agents/agent-runtime-error.js';
|
|
41
41
|
import { AGENT_PERMISSION_MODES, createAgentPermissionPolicy, evaluateAgentToolPermission, hashAgentPermissionPolicy } from './agents/agent-permissions.js';
|
|
42
42
|
import { createAgentPermissionStore } from './agents/agent-permission-store.js';
|
|
43
|
-
import { createAgentAuditStore } from './agents/agent-audit-store.js';
|
|
44
|
-
import { getAgentToolDefinition } from './agents/agent-tool-registry.js';
|
|
45
|
-
import { enrichAgentTaskResults } from './agents/agent-result-enrichment.js';
|
|
43
|
+
import { createAgentAuditStore } from './agents/agent-audit-store.js';
|
|
44
|
+
import { getAgentToolDefinition } from './agents/agent-tool-registry.js';
|
|
45
|
+
import { enrichAgentTaskResults } from './agents/agent-result-enrichment.js';
|
|
46
46
|
import { LiveDeskSettingsStore, SettingsConflictError } from './settings/settings-store.js';
|
|
47
47
|
import { effectiveDevicePolicy } from './settings/settings-schema.js';
|
|
48
48
|
import { buildEffectiveDevicePolicy } from './settings/effective-device-policy.js';
|
|
@@ -204,22 +204,22 @@ let verifiedLicense = {
|
|
|
204
204
|
let frameClientSeq = 0;
|
|
205
205
|
let inputClientSeq = 0;
|
|
206
206
|
let audioClientSeq = 0;
|
|
207
|
-
let liveDeskUpdateManager = null;
|
|
208
|
-
let hubTransferJobs = null;
|
|
209
|
-
let hubConsoleRelay = null;
|
|
207
|
+
let liveDeskUpdateManager = null;
|
|
208
|
+
let hubTransferJobs = null;
|
|
209
|
+
let hubConsoleRelay = null;
|
|
210
210
|
const HUB_HOST_TARGET_LEASE_MS = Math.max(5000, readPositiveIntegerEnv('LIVEDESK_HOST_TARGET_LEASE_MS', 60_000));
|
|
211
211
|
const HUB_HOST_TARGET_RENEW_MS = Math.max(1000, Math.min(
|
|
212
212
|
readPositiveIntegerEnv('LIVEDESK_HOST_TARGET_RENEW_MS', 20_000),
|
|
213
213
|
Math.max(1000, HUB_HOST_TARGET_LEASE_MS - 1000)
|
|
214
214
|
));
|
|
215
|
-
const HUB_ACCESS_TOKEN_REFRESH_SKEW_MS = 90_000;
|
|
216
|
-
const hubWakeBaseUrl = String(process.env.LIVEDESK_WAKE_URL || 'https://livedesk-wake.lovecrdm.workers.dev').trim();
|
|
217
|
-
const hubConsoleRelayBaseUrl = String(
|
|
218
|
-
process.env.LIVEDESK_CONSOLE_RELAY_URL
|
|
219
|
-
|| (process.env.LIVEDESK_TEST_MODE === '1' || process.env.LIVEDESK_AUTH_TEST_MODE === '1'
|
|
220
|
-
? 'off'
|
|
221
|
-
: 'https://livedesk-wake.lovecrdm.workers.dev')
|
|
222
|
-
).trim();
|
|
215
|
+
const HUB_ACCESS_TOKEN_REFRESH_SKEW_MS = 90_000;
|
|
216
|
+
const hubWakeBaseUrl = String(process.env.LIVEDESK_WAKE_URL || 'https://livedesk-wake.lovecrdm.workers.dev').trim();
|
|
217
|
+
const hubConsoleRelayBaseUrl = String(
|
|
218
|
+
process.env.LIVEDESK_CONSOLE_RELAY_URL
|
|
219
|
+
|| (process.env.LIVEDESK_TEST_MODE === '1' || process.env.LIVEDESK_AUTH_TEST_MODE === '1'
|
|
220
|
+
? 'off'
|
|
221
|
+
: 'https://livedesk-wake.lovecrdm.workers.dev')
|
|
222
|
+
).trim();
|
|
223
223
|
const HUB_WAKE_NOTIFY_RETRY_MS = 60_000;
|
|
224
224
|
let hubHostTargetRenewTimer = null;
|
|
225
225
|
let hubHostTargetRenewInFlight = false;
|
|
@@ -513,19 +513,19 @@ async function getRuntimeAccessToken() {
|
|
|
513
513
|
const accessToken = String(runtimeAccessToken || '').trim();
|
|
514
514
|
const expiresSoon = runtimeAccessTokenExpiresAt > 0
|
|
515
515
|
&& runtimeAccessTokenExpiresAt <= Date.now() + HUB_ACCESS_TOKEN_REFRESH_SKEW_MS;
|
|
516
|
-
if (accessToken && !expiresSoon) {
|
|
517
|
-
return accessToken;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// The packaged Electron main process owns the encrypted refresh token and
|
|
521
|
-
// proactively sends each rotation to this child runtime. A second refresh
|
|
522
|
-
// owner here could consume the one-time token first and make the desktop
|
|
523
|
-
// shell appear signed out after sleep.
|
|
524
|
-
if (desktopMainAuthConfig) {
|
|
525
|
-
return accessToken;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
const refreshToken = String(runtimeRefreshToken || '').trim();
|
|
516
|
+
if (accessToken && !expiresSoon) {
|
|
517
|
+
return accessToken;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// The packaged Electron main process owns the encrypted refresh token and
|
|
521
|
+
// proactively sends each rotation to this child runtime. A second refresh
|
|
522
|
+
// owner here could consume the one-time token first and make the desktop
|
|
523
|
+
// shell appear signed out after sleep.
|
|
524
|
+
if (desktopMainAuthConfig) {
|
|
525
|
+
return accessToken;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const refreshToken = String(runtimeRefreshToken || '').trim();
|
|
529
529
|
if (!refreshToken) {
|
|
530
530
|
return accessToken;
|
|
531
531
|
}
|
|
@@ -629,9 +629,9 @@ async function queryAuthoritativeRuntimeRole() {
|
|
|
629
629
|
},
|
|
630
630
|
SUPABASE_AUTH_TIMEOUT_MS
|
|
631
631
|
);
|
|
632
|
-
if (response.status === 401 || response.status === 403) {
|
|
633
|
-
if (!desktopMainAuthConfig) clearRuntimeSession();
|
|
634
|
-
throw new Error(`hub-role-query-not-authenticated:${response.status}`);
|
|
632
|
+
if (response.status === 401 || response.status === 403) {
|
|
633
|
+
if (!desktopMainAuthConfig) clearRuntimeSession();
|
|
634
|
+
throw new Error(`hub-role-query-not-authenticated:${response.status}`);
|
|
635
635
|
}
|
|
636
636
|
if (!response.ok) {
|
|
637
637
|
throw new Error(`hub-role-query-failed:${response.status}`);
|
|
@@ -813,12 +813,12 @@ function getLiveDeskUpdateStatus() {
|
|
|
813
813
|
}
|
|
814
814
|
|
|
815
815
|
if (process.env.LIVEDESK_DESKTOP_HOST !== '1') {
|
|
816
|
-
liveDeskUpdateManager = createLiveDeskUpdateManager({
|
|
817
|
-
remoteHub,
|
|
818
|
-
currentManagerVersion: process.env.LIVEDESK_MANAGER_VERSION || packageInfo.version,
|
|
819
|
-
currentClientVersion: process.env.LIVEDESK_CLIENT_PACKAGE_VERSION || '',
|
|
820
|
-
excludedDeviceIds: [runtimeDeviceId],
|
|
821
|
-
restartSupported: !!String(process.env.LIVEDESK_HUB_UPDATE_REQUEST_PATH || '').trim(),
|
|
816
|
+
liveDeskUpdateManager = createLiveDeskUpdateManager({
|
|
817
|
+
remoteHub,
|
|
818
|
+
currentManagerVersion: process.env.LIVEDESK_MANAGER_VERSION || packageInfo.version,
|
|
819
|
+
currentClientVersion: process.env.LIVEDESK_CLIENT_PACKAGE_VERSION || '',
|
|
820
|
+
excludedDeviceIds: [runtimeDeviceId],
|
|
821
|
+
restartSupported: !!String(process.env.LIVEDESK_HUB_UPDATE_REQUEST_PATH || '').trim(),
|
|
822
822
|
requestHubRestart
|
|
823
823
|
});
|
|
824
824
|
}
|
|
@@ -1278,16 +1278,16 @@ async function dispatchAgentMcpTool(session, name, args = {}) {
|
|
|
1278
1278
|
remoteHub.cancelTaskBatch(result.batchId);
|
|
1279
1279
|
return { ok: false, error: 'cancelled-by-user', batchId: result.batchId };
|
|
1280
1280
|
}
|
|
1281
|
-
const batch = remoteHub.getTaskBatch(result.batchId);
|
|
1282
|
-
if (!batch) return { ok: false, error: 'task-not-found', batchId: result.batchId };
|
|
1283
|
-
if (!['queued', 'running'].includes(batch.status)) {
|
|
1284
|
-
const taskResults = enrichAgentTaskResults({
|
|
1285
|
-
operation,
|
|
1286
|
-
results: batch.results,
|
|
1287
|
-
devices: remoteHub.listDevices({ includeDataUrl: false })
|
|
1288
|
-
.filter(device => targetIds.includes(device.deviceId))
|
|
1289
|
-
});
|
|
1290
|
-
return {
|
|
1281
|
+
const batch = remoteHub.getTaskBatch(result.batchId);
|
|
1282
|
+
if (!batch) return { ok: false, error: 'task-not-found', batchId: result.batchId };
|
|
1283
|
+
if (!['queued', 'running'].includes(batch.status)) {
|
|
1284
|
+
const taskResults = enrichAgentTaskResults({
|
|
1285
|
+
operation,
|
|
1286
|
+
results: batch.results,
|
|
1287
|
+
devices: remoteHub.listDevices({ includeDataUrl: false })
|
|
1288
|
+
.filter(device => targetIds.includes(device.deviceId))
|
|
1289
|
+
});
|
|
1290
|
+
return {
|
|
1291
1291
|
ok: true,
|
|
1292
1292
|
batchId: result.batchId,
|
|
1293
1293
|
operation,
|
|
@@ -1295,8 +1295,8 @@ async function dispatchAgentMcpTool(session, name, args = {}) {
|
|
|
1295
1295
|
total: batch.total,
|
|
1296
1296
|
completed: batch.completed,
|
|
1297
1297
|
failed: batch.failed,
|
|
1298
|
-
results: taskResults.map(item => ({ deviceId: item.deviceId, deviceName: item.deviceName, status: item.status, stage: item.stage, result: String(item.result || '').slice(0, 3000), data: item.data, error: String(item.error || '').slice(0, 500) }))
|
|
1299
|
-
};
|
|
1298
|
+
results: taskResults.map(item => ({ deviceId: item.deviceId, deviceName: item.deviceName, status: item.status, stage: item.stage, result: String(item.result || '').slice(0, 3000), data: item.data, error: String(item.error || '').slice(0, 500) }))
|
|
1299
|
+
};
|
|
1300
1300
|
}
|
|
1301
1301
|
await delayAgentMcp(200);
|
|
1302
1302
|
}
|
|
@@ -1356,16 +1356,16 @@ const hubSharedFolders = createHubSharedFolders({
|
|
|
1356
1356
|
dataDir: agentDataDir
|
|
1357
1357
|
});
|
|
1358
1358
|
|
|
1359
|
-
const app = express();
|
|
1360
|
-
const httpServer = createServer(app);
|
|
1361
|
-
hubConsoleRelay = createHubConsoleRelay({
|
|
1362
|
-
url: runtimeRole === 'hub' ? hubConsoleRelayBaseUrl : 'off',
|
|
1363
|
-
deviceId: runtimeDeviceId,
|
|
1364
|
-
httpBaseUrl: `http://127.0.0.1:${httpPort}`,
|
|
1365
|
-
getAccessToken: () => getRuntimeAccessToken(),
|
|
1366
|
-
logger: console
|
|
1367
|
-
});
|
|
1368
|
-
const httpConnections = new Set();
|
|
1359
|
+
const app = express();
|
|
1360
|
+
const httpServer = createServer(app);
|
|
1361
|
+
hubConsoleRelay = createHubConsoleRelay({
|
|
1362
|
+
url: runtimeRole === 'hub' ? hubConsoleRelayBaseUrl : 'off',
|
|
1363
|
+
deviceId: runtimeDeviceId,
|
|
1364
|
+
httpBaseUrl: `http://127.0.0.1:${httpPort}`,
|
|
1365
|
+
getAccessToken: () => getRuntimeAccessToken(),
|
|
1366
|
+
logger: console
|
|
1367
|
+
});
|
|
1368
|
+
const httpConnections = new Set();
|
|
1369
1369
|
const frameWss = new WebSocketServer({ noServer: true, perMessageDeflate: false });
|
|
1370
1370
|
const atlasWss = new WebSocketServer({ noServer: true, perMessageDeflate: false });
|
|
1371
1371
|
const inputWss = new WebSocketServer({ noServer: true, perMessageDeflate: false });
|
|
@@ -4249,10 +4249,10 @@ app.get('/api/remote/status', (_req, res) => {
|
|
|
4249
4249
|
runtimeRole,
|
|
4250
4250
|
deviceId: runtimeDeviceId,
|
|
4251
4251
|
deviceName: runtimeDeviceName,
|
|
4252
|
-
roleSource: runtimeRoleSource,
|
|
4253
|
-
agentPackage: '@livedesk/client',
|
|
4254
|
-
consoleRelay: hubConsoleRelay?.inspect() || { enabled: false, state: 'starting' },
|
|
4255
|
-
frameLanes: snapshotFrameLaneResourceHealth(),
|
|
4252
|
+
roleSource: runtimeRoleSource,
|
|
4253
|
+
agentPackage: '@livedesk/client',
|
|
4254
|
+
consoleRelay: hubConsoleRelay?.inspect() || { enabled: false, state: 'starting' },
|
|
4255
|
+
frameLanes: snapshotFrameLaneResourceHealth(),
|
|
4256
4256
|
update: getLiveDeskUpdateStatus()
|
|
4257
4257
|
});
|
|
4258
4258
|
});
|
|
@@ -4484,11 +4484,11 @@ app.post('/api/auth/session', async (req, res) => {
|
|
|
4484
4484
|
csrfToken: uiSession.csrfToken,
|
|
4485
4485
|
expiresAt: uiSession.expiresAt
|
|
4486
4486
|
}
|
|
4487
|
-
});
|
|
4488
|
-
if (runtimeRole === 'hub') {
|
|
4489
|
-
hubConsoleRelay?.refresh();
|
|
4490
|
-
scheduleAuthenticatedHubHostTargetPublication('session-received');
|
|
4491
|
-
}
|
|
4487
|
+
});
|
|
4488
|
+
if (runtimeRole === 'hub') {
|
|
4489
|
+
hubConsoleRelay?.refresh();
|
|
4490
|
+
scheduleAuthenticatedHubHostTargetPublication('session-received');
|
|
4491
|
+
}
|
|
4492
4492
|
} catch (error) {
|
|
4493
4493
|
const message = error instanceof Error ? error.message : String(error);
|
|
4494
4494
|
const status = authVerificationHttpStatus(message);
|
|
@@ -4508,11 +4508,11 @@ function getHubHostTargetLeaseStatus() {
|
|
|
4508
4508
|
...hubHostTargetLeaseState,
|
|
4509
4509
|
renewing: hubHostTargetRenewInFlight,
|
|
4510
4510
|
renewalIntervalMs: HUB_HOST_TARGET_RENEW_MS,
|
|
4511
|
-
leaseDurationMs: HUB_HOST_TARGET_LEASE_MS,
|
|
4512
|
-
authenticated: Boolean(runtimeAccessToken),
|
|
4513
|
-
timerActive: Boolean(hubHostTargetRenewTimer),
|
|
4514
|
-
wake: { ...hubWakeNotificationState },
|
|
4515
|
-
consoleRelay: hubConsoleRelay?.inspect() || { enabled: false, state: 'starting' }
|
|
4511
|
+
leaseDurationMs: HUB_HOST_TARGET_LEASE_MS,
|
|
4512
|
+
authenticated: Boolean(runtimeAccessToken),
|
|
4513
|
+
timerActive: Boolean(hubHostTargetRenewTimer),
|
|
4514
|
+
wake: { ...hubWakeNotificationState },
|
|
4515
|
+
consoleRelay: hubConsoleRelay?.inspect() || { enabled: false, state: 'starting' }
|
|
4516
4516
|
};
|
|
4517
4517
|
}
|
|
4518
4518
|
|
|
@@ -4609,9 +4609,9 @@ async function callHubSupabaseRpc(name, payload, accessToken) {
|
|
|
4609
4609
|
);
|
|
4610
4610
|
const data = await response.json().catch(() => null);
|
|
4611
4611
|
const result = Array.isArray(data) ? data[0] : data;
|
|
4612
|
-
if (response.status === 401 || response.status === 403) {
|
|
4613
|
-
if (!desktopMainAuthConfig) clearRuntimeSession();
|
|
4614
|
-
throw new Error(`${name}-not-authenticated:${response.status}`);
|
|
4612
|
+
if (response.status === 401 || response.status === 403) {
|
|
4613
|
+
if (!desktopMainAuthConfig) clearRuntimeSession();
|
|
4614
|
+
throw new Error(`${name}-not-authenticated:${response.status}`);
|
|
4615
4615
|
}
|
|
4616
4616
|
if (!response.ok) {
|
|
4617
4617
|
throw new Error(`${name}-failed:${response.status}`);
|
|
@@ -4816,11 +4816,11 @@ app.get('/api/hub/status', (_req, res) => {
|
|
|
4816
4816
|
...remoteHub.getStatus({ includeSecrets: false }),
|
|
4817
4817
|
role: 'hub',
|
|
4818
4818
|
deviceId: runtimeDeviceId,
|
|
4819
|
-
deviceName: runtimeDeviceName,
|
|
4820
|
-
roleSource: runtimeRoleSource,
|
|
4821
|
-
runtimeStarted: true,
|
|
4822
|
-
consoleRelay: hubConsoleRelay?.inspect() || { enabled: false, state: 'starting' },
|
|
4823
|
-
hostTargetLease: getHubHostTargetLeaseStatus(),
|
|
4819
|
+
deviceName: runtimeDeviceName,
|
|
4820
|
+
roleSource: runtimeRoleSource,
|
|
4821
|
+
runtimeStarted: true,
|
|
4822
|
+
consoleRelay: hubConsoleRelay?.inspect() || { enabled: false, state: 'starting' },
|
|
4823
|
+
hostTargetLease: getHubHostTargetLeaseStatus(),
|
|
4824
4824
|
update: getLiveDeskUpdateStatus()
|
|
4825
4825
|
});
|
|
4826
4826
|
});
|
|
@@ -5827,14 +5827,14 @@ hubSharedFolders.startAutoSync(
|
|
|
5827
5827
|
() => remoteHub.listDevices({ includeDataUrl: false }).filter(device => device.connected).map(device => device.deviceId),
|
|
5828
5828
|
() => process.env.LIVEDESK_REMOTE_DIRECTORY || 'Desktop/LiveDeskFiles'
|
|
5829
5829
|
);
|
|
5830
|
-
httpServer.listen(httpPort, httpHost, () => {
|
|
5830
|
+
httpServer.listen(httpPort, httpHost, () => {
|
|
5831
5831
|
const status = remoteHub.getStatus({ includeSecrets: true });
|
|
5832
5832
|
const managerVersion = String(process.env.LIVEDESK_MANAGER_VERSION || packageInfo.version || 'dev');
|
|
5833
5833
|
console.log(`[LiveDesk Hub] Version ${managerVersion}`);
|
|
5834
|
-
console.log(`[LiveDesk Hub] HTTP API http://${httpHost}:${httpPort}`);
|
|
5835
|
-
console.log(`[LiveDesk Hub] Client endpoint ${status.agentEndpoint} pair=${status.pairTokenPreview}`);
|
|
5836
|
-
hubConsoleRelay?.start();
|
|
5837
|
-
});
|
|
5834
|
+
console.log(`[LiveDesk Hub] HTTP API http://${httpHost}:${httpPort}`);
|
|
5835
|
+
console.log(`[LiveDesk Hub] Client endpoint ${status.agentEndpoint} pair=${status.pairTokenPreview}`);
|
|
5836
|
+
hubConsoleRelay?.start();
|
|
5837
|
+
});
|
|
5838
5838
|
|
|
5839
5839
|
const roleWatchTimer = runtimeRole === 'hub'
|
|
5840
5840
|
? setInterval(() => { void watchAuthoritativeRuntimeRole(); }, 5000)
|
|
@@ -5915,10 +5915,10 @@ function shutdownHub(signal) {
|
|
|
5915
5915
|
const startedAt = Date.now();
|
|
5916
5916
|
console.log(`[LiveDesk Hub] Shutdown started signal=${signal} grace=${hubShutdownGraceMs}ms timeout=${hubShutdownTimeoutMs}ms.`);
|
|
5917
5917
|
if (roleWatchTimer) clearInterval(roleWatchTimer);
|
|
5918
|
-
clearInterval(browserWebSocketHeartbeatTimer);
|
|
5919
|
-
runSynchronousShutdownStep('update manager close', () => liveDeskUpdateManager?.close());
|
|
5920
|
-
runSynchronousShutdownStep('mobile console relay close', () => hubConsoleRelay?.close());
|
|
5921
|
-
atlasClients.clear();
|
|
5918
|
+
clearInterval(browserWebSocketHeartbeatTimer);
|
|
5919
|
+
runSynchronousShutdownStep('update manager close', () => liveDeskUpdateManager?.close());
|
|
5920
|
+
runSynchronousShutdownStep('mobile console relay close', () => hubConsoleRelay?.close());
|
|
5921
|
+
atlasClients.clear();
|
|
5922
5922
|
runSynchronousShutdownStep('shared folder close', () => hubSharedFolders.close());
|
|
5923
5923
|
|
|
5924
5924
|
const httpClosed = new Promise(resolveClose => {
|
|
@@ -13,7 +13,8 @@ export const DEFAULT_LIVEDESK_SETTINGS = Object.freeze({
|
|
|
13
13
|
approveNewDevices: true,
|
|
14
14
|
startWithComputer: true,
|
|
15
15
|
keepRunningInTray: true,
|
|
16
|
-
showConnectionNotifications: true
|
|
16
|
+
showConnectionNotifications: true,
|
|
17
|
+
showThisComputer: false
|
|
17
18
|
},
|
|
18
19
|
security: {
|
|
19
20
|
accessMode: 'trusted-only',
|
|
@@ -157,7 +158,7 @@ const numbers = (entries) => Object.fromEntries(entries.map(([key, min, max]) =>
|
|
|
157
158
|
|
|
158
159
|
const RULES = {
|
|
159
160
|
connection: {
|
|
160
|
-
...bools(['usePinToAddDevices', 'rotatePinAfterPairing', 'allowNewDevices', 'approveNewDevices', 'startWithComputer', 'keepRunningInTray', 'showConnectionNotifications']),
|
|
161
|
+
...bools(['usePinToAddDevices', 'rotatePinAfterPairing', 'allowNewDevices', 'approveNewDevices', 'startWithComputer', 'keepRunningInTray', 'showConnectionNotifications', 'showThisComputer']),
|
|
161
162
|
...numbers([['pinValidityMinutes', 10, 1440]])
|
|
162
163
|
},
|
|
163
164
|
security: {
|