livedesk 0.1.501 → 0.1.502
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/bin/livedesk.js +18 -15
- package/bootstrap/hub-auth-handoff.js +3 -3
- package/bootstrap/update-host-client.mjs +14 -3
- package/bootstrap/update-host.mjs +5 -1
- package/client/package.json +5 -5
- package/hub/package.json +1 -1
- package/hub/src/remote-hub.js +34 -5
- package/hub/src/server.js +24 -9
- package/package.json +6 -6
- package/web/dist/assets/{index-PHlwNiVH.js → index-DqXhTKiG.js} +1 -1
- package/web/dist/index.html +1 -1
- package/web/dist/livedesk-build-evidence.json +9 -9
package/bin/livedesk.js
CHANGED
|
@@ -3034,21 +3034,24 @@ async function runManager(args, resolvedRole = null, runtimeLock = null, updateH
|
|
|
3034
3034
|
updatePollId = setInterval(pollUpdateRequest, HUB_UPDATE_POLL_MS);
|
|
3035
3035
|
|
|
3036
3036
|
const hubReady = waitForManager(hubProbeBaseUrl);
|
|
3037
|
-
const hubStartup = hubReady.then(
|
|
3038
|
-
if (!ok) {
|
|
3039
|
-
return false;
|
|
3040
|
-
}
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3037
|
+
const hubStartup = hubReady.then(ok => {
|
|
3038
|
+
if (!ok) {
|
|
3039
|
+
return false;
|
|
3040
|
+
}
|
|
3041
|
+
void transferSavedClientSessionToHub(hubProbeBaseUrl, MANAGER_STATE_DIR).then(handoff => {
|
|
3042
|
+
if (handoff.ok) {
|
|
3043
|
+
reportLauncherUpdate('[LiveDesk Hub] Saved Client sign-in adopted by the Hub.');
|
|
3044
|
+
if (!handoff.hostTargetOk) {
|
|
3045
|
+
reportLauncherUpdate('[LiveDesk Hub] Sign-in was adopted; host publication will continue through lease renewal.', true);
|
|
3046
|
+
}
|
|
3047
|
+
} else if (!handoff.skipped) {
|
|
3048
|
+
reportLauncherUpdate(`[LiveDesk Hub] Saved Client sign-in could not be adopted: ${handoff.reason}. Continue sign-in in the Hub page.`, true);
|
|
3049
|
+
}
|
|
3050
|
+
}).catch(error => {
|
|
3051
|
+
reportLauncherUpdate(`[LiveDesk Hub] Saved Client sign-in could not be adopted: ${error instanceof Error ? error.message : String(error)}. Continue sign-in in the Hub page.`, true);
|
|
3052
|
+
});
|
|
3053
|
+
return true;
|
|
3054
|
+
});
|
|
3052
3055
|
|
|
3053
3056
|
if (options.openBrowserOnStart) {
|
|
3054
3057
|
void hubStartup.then(ok => {
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
PRODUCTION_SUPABASE_PUBLISHABLE_KEY,
|
|
13
13
|
PRODUCTION_SUPABASE_URL
|
|
14
14
|
} from '../runtime-core/src/auth-config.js';
|
|
15
|
-
import { fetchAuthResponse } from '../runtime-core/src/auth-http.js';
|
|
15
|
+
import { AUTH_REQUEST_TIMEOUT_MS, fetchAuthResponse } from '../runtime-core/src/auth-http.js';
|
|
16
16
|
import { normalizeRuntimeAuthSession } from '../runtime-core/src/auth-session.js';
|
|
17
17
|
|
|
18
18
|
const CLIENT_AUTH_STORAGE_KEY = 'livedesk.client.supabase.auth';
|
|
@@ -103,7 +103,7 @@ async function refreshSavedClientSessionForHub(
|
|
|
103
103
|
Accept: 'application/json'
|
|
104
104
|
},
|
|
105
105
|
body: JSON.stringify({ refresh_token: session.refresh_token })
|
|
106
|
-
},
|
|
106
|
+
}, AUTH_REQUEST_TIMEOUT_MS);
|
|
107
107
|
const data = await response.json().catch(() => null);
|
|
108
108
|
if (!response.ok) {
|
|
109
109
|
throw new Error(`saved-client-session-refresh-failed:${response.status}`);
|
|
@@ -163,7 +163,7 @@ export async function transferSavedClientSessionToHub(
|
|
|
163
163
|
refreshToken: resolved.session.refresh_token,
|
|
164
164
|
expiresAt: resolved.session.expires_at
|
|
165
165
|
})
|
|
166
|
-
},
|
|
166
|
+
}, AUTH_REQUEST_TIMEOUT_MS);
|
|
167
167
|
const data = await response.json().catch(() => null);
|
|
168
168
|
if (!response.ok || data?.authenticated !== true) {
|
|
169
169
|
return {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
3
3
|
import net from 'node:net';
|
|
4
4
|
import os from 'node:os';
|
|
5
|
-
import {
|
|
5
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
|
|
8
8
|
export const UPDATE_HOST_PROTOCOL_VERSION = 1;
|
|
@@ -86,6 +86,16 @@ export function getUpdateHostPaths(stateDir) {
|
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
export function getUpdateHostWorkingDirectory(stateDir) {
|
|
90
|
+
return join(normalizedStateDir(stateDir), 'update-host-cwd');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function prepareUpdateHostWorkingDirectory(stateDir) {
|
|
94
|
+
const workingDirectory = getUpdateHostWorkingDirectory(stateDir);
|
|
95
|
+
mkdirSync(workingDirectory, { recursive: true, mode: 0o700 });
|
|
96
|
+
return workingDirectory;
|
|
97
|
+
}
|
|
98
|
+
|
|
89
99
|
export function readUpdateHostStatus(statusPath) {
|
|
90
100
|
try {
|
|
91
101
|
const status = JSON.parse(readFileSync(statusPath, 'utf8'));
|
|
@@ -312,8 +322,9 @@ export async function ensureUpdateHost({
|
|
|
312
322
|
];
|
|
313
323
|
let child;
|
|
314
324
|
try {
|
|
325
|
+
const workingDirectory = prepareUpdateHostWorkingDirectory(paths.stateDir);
|
|
315
326
|
child = spawnImpl(process.execPath, args, {
|
|
316
|
-
cwd:
|
|
327
|
+
cwd: workingDirectory,
|
|
317
328
|
env: buildHostEnvironment(env),
|
|
318
329
|
detached: true,
|
|
319
330
|
stdio: 'ignore',
|
|
@@ -8,6 +8,7 @@ import { dirname, isAbsolute, resolve, sep } from 'node:path';
|
|
|
8
8
|
import { spawn } from 'node:child_process';
|
|
9
9
|
import {
|
|
10
10
|
getUpdateHostPaths,
|
|
11
|
+
prepareUpdateHostWorkingDirectory,
|
|
11
12
|
isValidUpdateHostEnvironmentEntry,
|
|
12
13
|
UPDATE_HOST_MAX_ENVIRONMENT_KEYS,
|
|
13
14
|
UPDATE_HOST_MAX_MESSAGE_BYTES,
|
|
@@ -37,6 +38,8 @@ const replacePid = Number(argumentValue('--replace-pid') || 0);
|
|
|
37
38
|
const stateDir = decodeStateDir();
|
|
38
39
|
if (!stateDir) throw new Error('LiveDesk Update Host requires a state directory.');
|
|
39
40
|
const paths = getUpdateHostPaths(stateDir);
|
|
41
|
+
const workingDirectory = prepareUpdateHostWorkingDirectory(paths.stateDir);
|
|
42
|
+
process.chdir(workingDirectory);
|
|
40
43
|
const token = randomBytes(32).toString('hex');
|
|
41
44
|
const hostId = randomBytes(24).toString('hex');
|
|
42
45
|
const startedAt = new Date().toISOString();
|
|
@@ -117,6 +120,7 @@ function hostStatus() {
|
|
|
117
120
|
hostId,
|
|
118
121
|
token,
|
|
119
122
|
endpoint: paths.endpoint,
|
|
123
|
+
workingDirectory,
|
|
120
124
|
sourceVersion,
|
|
121
125
|
startedAt,
|
|
122
126
|
state: stopping ? 'stopping' : (currentJob && ['accepted', 'running'].includes(currentJob.state) ? 'busy' : 'idle'),
|
|
@@ -253,7 +257,7 @@ function beginHostReplacement() {
|
|
|
253
257
|
'--source-version', replacement.sourceVersion,
|
|
254
258
|
'--replace-pid', String(process.pid)
|
|
255
259
|
], {
|
|
256
|
-
cwd:
|
|
260
|
+
cwd: workingDirectory,
|
|
257
261
|
env: process.env,
|
|
258
262
|
detached: true,
|
|
259
263
|
stdio: 'ignore',
|
package/client/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livedesk/client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.240",
|
|
4
4
|
"description": "LiveDesk local remote client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"ws": "^8.18.3"
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
|
-
"@livedesk/fast-linux-x64": "0.1.
|
|
46
|
-
"@livedesk/fast-osx-arm64": "0.1.
|
|
47
|
-
"@livedesk/fast-osx-x64": "0.1.
|
|
48
|
-
"@livedesk/fast-win-x64": "0.1.
|
|
45
|
+
"@livedesk/fast-linux-x64": "0.1.439",
|
|
46
|
+
"@livedesk/fast-osx-arm64": "0.1.439",
|
|
47
|
+
"@livedesk/fast-osx-x64": "0.1.439",
|
|
48
|
+
"@livedesk/fast-win-x64": "0.1.439"
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
package/hub/package.json
CHANGED
package/hub/src/remote-hub.js
CHANGED
|
@@ -9705,10 +9705,39 @@ export function createRemoteHub(options = {}) {
|
|
|
9705
9705
|
liveStreamReplacementStillPending(activeLiveStream)
|
|
9706
9706
|
? 'stream-restart-superseded'
|
|
9707
9707
|
: 'stream-start-timeout');
|
|
9708
|
-
}
|
|
9709
|
-
const commandId = safeString(options.commandId, 128) || crypto.randomUUID();
|
|
9710
|
-
|
|
9711
|
-
|
|
9708
|
+
}
|
|
9709
|
+
const commandId = safeString(options.commandId, 128) || crypto.randomUUID();
|
|
9710
|
+
const restartToken = safeString(options.restartToken, 128);
|
|
9711
|
+
if (activeLiveStream
|
|
9712
|
+
&& options.forceRestart === true
|
|
9713
|
+
&& restartToken
|
|
9714
|
+
&& safeString(activeLiveStream.restartToken, 128) === restartToken
|
|
9715
|
+
&& liveStreamMatchesOptions(activeLiveStream, normalized)
|
|
9716
|
+
&& liveStreamIsReusable(activeLiveStream)) {
|
|
9717
|
+
emitRemoteEvent('RemoteLiveStreamRestartTokenReused', device, {
|
|
9718
|
+
streamId,
|
|
9719
|
+
commandId: activeLiveStream.commandId,
|
|
9720
|
+
restartToken,
|
|
9721
|
+
captureGeneration: Number(activeLiveStream.captureGeneration || 0)
|
|
9722
|
+
});
|
|
9723
|
+
return {
|
|
9724
|
+
ok: true,
|
|
9725
|
+
commandId: activeLiveStream.commandId,
|
|
9726
|
+
sessionId: device.sessionId,
|
|
9727
|
+
streamId,
|
|
9728
|
+
streamPurpose,
|
|
9729
|
+
fps: Number(activeLiveStream.fps || fps),
|
|
9730
|
+
mode: activeLiveStream.mode || transfer.mode,
|
|
9731
|
+
frameMode: activeLiveStream.frameMode || transfer.frameMode,
|
|
9732
|
+
monitorIndex: Number(activeLiveStream.monitorIndex ?? monitorIndex),
|
|
9733
|
+
captureGeneration: Number(activeLiveStream.captureGeneration || 0),
|
|
9734
|
+
ready: liveStreamHasCurrentFrame(activeLiveStream),
|
|
9735
|
+
pending: activeLiveStream.open !== true,
|
|
9736
|
+
reused: true
|
|
9737
|
+
};
|
|
9738
|
+
}
|
|
9739
|
+
if (activeLiveStream
|
|
9740
|
+
&& options.forceRestart !== true
|
|
9712
9741
|
&& options.reuseExisting === true
|
|
9713
9742
|
&& liveStreamMatchesOptions(activeLiveStream, normalized)
|
|
9714
9743
|
&& liveStreamIsReusable(activeLiveStream)) {
|
|
@@ -9838,7 +9867,7 @@ export function createRemoteHub(options = {}) {
|
|
|
9838
9867
|
monitorIndex,
|
|
9839
9868
|
monitorCount: 1,
|
|
9840
9869
|
startedAt: now,
|
|
9841
|
-
restartToken
|
|
9870
|
+
restartToken,
|
|
9842
9871
|
stoppedAt: '',
|
|
9843
9872
|
stopReason: '',
|
|
9844
9873
|
stopPending: false,
|
package/hub/src/server.js
CHANGED
|
@@ -4430,12 +4430,13 @@ app.post('/api/auth/session', async (req, res) => {
|
|
|
4430
4430
|
expires_at: expiresAt,
|
|
4431
4431
|
user
|
|
4432
4432
|
});
|
|
4433
|
-
const hostTarget = runtimeRole === 'hub'
|
|
4434
|
-
?
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4433
|
+
const hostTarget = runtimeRole === 'hub'
|
|
4434
|
+
? {
|
|
4435
|
+
ok: true,
|
|
4436
|
+
pending: true,
|
|
4437
|
+
active: remoteHub.getStatus({ includeSecrets: false }).hostTargetActive === true
|
|
4438
|
+
}
|
|
4439
|
+
: { ok: true, pending: false, active: false };
|
|
4439
4440
|
const uiSession = hubUiSessionAuthority.issue(user.id);
|
|
4440
4441
|
res.setHeader('Set-Cookie', serializeHubUiSessionCookie(uiSession.sessionId, uiSession.expiresAt, {
|
|
4441
4442
|
secure: isSecureHubHttpRequest(req)
|
|
@@ -4452,6 +4453,9 @@ app.post('/api/auth/session', async (req, res) => {
|
|
|
4452
4453
|
expiresAt: uiSession.expiresAt
|
|
4453
4454
|
}
|
|
4454
4455
|
});
|
|
4456
|
+
if (runtimeRole === 'hub') {
|
|
4457
|
+
scheduleAuthenticatedHubHostTargetPublication('session-received');
|
|
4458
|
+
}
|
|
4455
4459
|
} catch (error) {
|
|
4456
4460
|
const message = error instanceof Error ? error.message : String(error);
|
|
4457
4461
|
const status = authVerificationHttpStatus(message);
|
|
@@ -4737,15 +4741,26 @@ async function clearHubHostTarget(reason = 'shutdown') {
|
|
|
4737
4741
|
return { ok: !error, error, lease: getHubHostTargetLeaseStatus() };
|
|
4738
4742
|
}
|
|
4739
4743
|
|
|
4740
|
-
function startHubHostTargetLeaseRenewal() {
|
|
4744
|
+
function startHubHostTargetLeaseRenewal() {
|
|
4741
4745
|
if (hubHostTargetRenewTimer || runtimeRole !== 'hub') {
|
|
4742
4746
|
return;
|
|
4743
4747
|
}
|
|
4744
4748
|
hubHostTargetRenewTimer = setInterval(() => {
|
|
4745
4749
|
void publishHubHostTargetWithPendingRoleTakeover('renewal');
|
|
4746
4750
|
}, HUB_HOST_TARGET_RENEW_MS);
|
|
4747
|
-
hubHostTargetRenewTimer.unref?.();
|
|
4748
|
-
}
|
|
4751
|
+
hubHostTargetRenewTimer.unref?.();
|
|
4752
|
+
}
|
|
4753
|
+
|
|
4754
|
+
function scheduleAuthenticatedHubHostTargetPublication(reason = 'session-received') {
|
|
4755
|
+
startHubHostTargetLeaseRenewal();
|
|
4756
|
+
setImmediate(() => {
|
|
4757
|
+
void publishHubHostTargetWithPendingRoleTakeover(reason).catch(error => {
|
|
4758
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4759
|
+
updateHubHostTargetLeaseState({ state: 'error', lastError: message });
|
|
4760
|
+
console.error(`[LiveDesk Hub] Host target ${reason} background publish failed: ${message}`);
|
|
4761
|
+
});
|
|
4762
|
+
});
|
|
4763
|
+
}
|
|
4749
4764
|
|
|
4750
4765
|
app.delete('/api/auth/session', async (req, res) => {
|
|
4751
4766
|
noStore(res);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livedesk",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"livedeskClientVersion": "0.1.
|
|
3
|
+
"version": "0.1.502",
|
|
4
|
+
"livedeskClientVersion": "0.1.240",
|
|
5
5
|
"buildFlavor": "production",
|
|
6
6
|
"description": "LiveDesk Hub and client launcher",
|
|
7
7
|
"type": "module",
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"ws": "^8.18.3"
|
|
53
53
|
},
|
|
54
54
|
"optionalDependencies": {
|
|
55
|
-
"@livedesk/fast-linux-x64": "0.1.
|
|
56
|
-
"@livedesk/fast-osx-arm64": "0.1.
|
|
57
|
-
"@livedesk/fast-osx-x64": "0.1.
|
|
58
|
-
"@livedesk/fast-win-x64": "0.1.
|
|
55
|
+
"@livedesk/fast-linux-x64": "0.1.439",
|
|
56
|
+
"@livedesk/fast-osx-arm64": "0.1.439",
|
|
57
|
+
"@livedesk/fast-osx-x64": "0.1.439",
|
|
58
|
+
"@livedesk/fast-win-x64": "0.1.439"
|
|
59
59
|
},
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public"
|