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 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(async ok => {
3038
- if (!ok) {
3039
- return false;
3040
- }
3041
- const handoff = await transferSavedClientSessionToHub(hubProbeBaseUrl, MANAGER_STATE_DIR);
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
- return true;
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
- }, 5_000);
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
- }, 5_000);
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 { dirname, isAbsolute, join, resolve } from 'node:path';
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: dirname(entry),
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: dirname(replacement.entryPath),
260
+ cwd: workingDirectory,
257
261
  env: process.env,
258
262
  detached: true,
259
263
  stdio: 'ignore',
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/client",
3
- "version": "0.1.239",
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.437",
46
- "@livedesk/fast-osx-arm64": "0.1.437",
47
- "@livedesk/fast-osx-x64": "0.1.437",
48
- "@livedesk/fast-win-x64": "0.1.437"
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/hub",
3
- "version": "0.1.40",
3
+ "version": "0.1.41",
4
4
  "description": "LiveDesk local Hub API and browser frame bridge",
5
5
  "type": "module",
6
6
  "main": "src/server.js",
@@ -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
- if (activeLiveStream
9711
- && options.forceRestart !== true
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: safeString(options.restartToken, 128),
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
- ? await publishHubHostTargetWithPendingRoleTakeover('session-received')
4435
- : { ok: true, active: false };
4436
- if (runtimeRole === 'hub') {
4437
- startHubHostTargetLeaseRenewal();
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.501",
4
- "livedeskClientVersion": "0.1.239",
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.437",
56
- "@livedesk/fast-osx-arm64": "0.1.437",
57
- "@livedesk/fast-osx-x64": "0.1.437",
58
- "@livedesk/fast-win-x64": "0.1.437"
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"