@livedesk/client 0.1.250 → 0.1.252

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@livedesk/client",
3
- "version": "0.1.250",
4
- "description": "LiveDesk local remote client",
3
+ "version": "0.1.252",
4
+ "description": "VuvoDesk local remote client",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "client": "bin/livedesk-client.js",
@@ -36,16 +36,16 @@
36
36
  "dependencies": {
37
37
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
38
38
  "ffmpeg-static": "^5.3.0",
39
- "@livedesk/runtime-core": "0.1.5",
39
+ "@livedesk/runtime-core": "0.1.6",
40
40
  "@supabase/supabase-js": "^2.110.0",
41
41
  "node-screenshots": "^0.2.8",
42
42
  "ws": "^8.18.3"
43
43
  },
44
44
  "optionalDependencies": {
45
- "@livedesk/fast-linux-x64": "0.1.446",
46
- "@livedesk/fast-osx-arm64": "0.1.446",
47
- "@livedesk/fast-osx-x64": "0.1.446",
48
- "@livedesk/fast-win-x64": "0.1.446"
45
+ "@livedesk/fast-linux-x64": "0.1.448",
46
+ "@livedesk/fast-osx-arm64": "0.1.448",
47
+ "@livedesk/fast-osx-x64": "0.1.448",
48
+ "@livedesk/fast-win-x64": "0.1.448"
49
49
  },
50
50
  "publishConfig": {
51
51
  "access": "public"
@@ -217,7 +217,7 @@ export function createWindowsProcessTreeTracker(child, {
217
217
  waitImpl = waitMilliseconds,
218
218
  publishTrackedRecords = null,
219
219
  reportPublisherError = error => console.warn(
220
- `[LiveDesk Client] Windows owned-process manifest warning: ${error?.message || error}`
220
+ `[VuvoDesk Client] Windows owned-process manifest warning: ${error?.message || error}`
221
221
  )
222
222
  } = {}) {
223
223
  const rootPid = Number(child?.pid || 0);
@@ -501,7 +501,7 @@ export async function drainOwnedWindowsAgentTree(child, {
501
501
  : `Exact Windows Agent tree retained pid(s): ${remaining.map(record => record.pid).join(', ')}`
502
502
  );
503
503
  reportTerminationFailure(
504
- `[LiveDesk Client] Exact Windows Agent tree could not be drained after `
504
+ `[VuvoDesk Client] Exact Windows Agent tree could not be drained after `
505
505
  + `${attempts} bounded attempt(s): ${error?.message || error}`
506
506
  );
507
507
  return { ok: false, error, remaining };
@@ -549,7 +549,7 @@ export async function drainOwnedWindowsAgentTreeUntilStopped(child, {
549
549
  return result;
550
550
  }
551
551
  reportTerminationFailure(
552
- `[LiveDesk Client] Exact Windows Agent tree is not drained yet `
552
+ `[VuvoDesk Client] Exact Windows Agent tree is not drained yet `
553
553
  + `(attempt ${attempt}); the launcher will remain alive and retry.`
554
554
  );
555
555
  await waitImpl(Math.max(100, Number(retryForeverMs) || 1000));
@@ -639,7 +639,7 @@ export async function drainOwnedUnixAgentTree(child, {
639
639
  signalOwnedGroup(gracefulSignal);
640
640
  } catch (error) {
641
641
  reportTerminationFailure(
642
- `[LiveDesk Client] Exited Agent group pid=${processId} rejected ${gracefulSignal} `
642
+ `[VuvoDesk Client] Exited Agent group pid=${processId} rejected ${gracefulSignal} `
643
643
  + `(${error?.message || error}); forced cleanup will continue.`
644
644
  );
645
645
  }
@@ -660,7 +660,7 @@ export async function drainOwnedUnixAgentTree(child, {
660
660
  if (!failureReported) {
661
661
  failureReported = true;
662
662
  reportTerminationFailure(
663
- `[LiveDesk Client] Exited Agent group pid=${processId} rejected SIGKILL `
663
+ `[VuvoDesk Client] Exited Agent group pid=${processId} rejected SIGKILL `
664
664
  + `(${error?.message || error}). The launcher will not start a replacement until the group drains.`
665
665
  );
666
666
  }
@@ -669,7 +669,7 @@ export async function drainOwnedUnixAgentTree(child, {
669
669
  if (!failureReported) {
670
670
  failureReported = true;
671
671
  reportTerminationFailure(
672
- `[LiveDesk Client] Exited Agent group pid=${processId} still has capture descendants after SIGKILL. `
672
+ `[VuvoDesk Client] Exited Agent group pid=${processId} still has capture descendants after SIGKILL. `
673
673
  + 'The launcher will not start a replacement until the group drains.'
674
674
  );
675
675
  }
@@ -767,7 +767,7 @@ export function installAgentTerminationHandlers({
767
767
  return;
768
768
  }
769
769
  reportTerminationFailure(
770
- `[LiveDesk Client] Terminal shutdown retained an exact Windows Agent tree: `
770
+ `[VuvoDesk Client] Terminal shutdown retained an exact Windows Agent tree: `
771
771
  + `${result.error?.message || 'bounded drain failed'}. Retrying before exit.`
772
772
  );
773
773
  child.livedeskTreeStopPromise = null;
@@ -799,7 +799,7 @@ export function installAgentTerminationHandlers({
799
799
  signalAgentTree(child, signal, platform, signalProcess);
800
800
  } catch (error) {
801
801
  reportTerminationFailure(
802
- `[LiveDesk Client] Agent tree pid=${processId || 'unknown'} could not receive ${signal} `
802
+ `[VuvoDesk Client] Agent tree pid=${processId || 'unknown'} could not receive ${signal} `
803
803
  + `(${error?.message || error}). Forced cleanup will continue.`
804
804
  );
805
805
  }
@@ -816,7 +816,7 @@ export function installAgentTerminationHandlers({
816
816
  if (!hardFailureReported) {
817
817
  hardFailureReported = true;
818
818
  reportTerminationFailure(
819
- `[LiveDesk Client] Agent tree pid=${processId || 'unknown'} rejected SIGKILL `
819
+ `[VuvoDesk Client] Agent tree pid=${processId || 'unknown'} rejected SIGKILL `
820
820
  + `(${error?.message || error}). The launcher will remain alive and retry.`
821
821
  );
822
822
  }
@@ -826,7 +826,7 @@ export function installAgentTerminationHandlers({
826
826
  if (!hardFailureReported) {
827
827
  hardFailureReported = true;
828
828
  reportTerminationFailure(
829
- `[LiveDesk Client] Agent tree pid=${processId || 'unknown'} is still alive after SIGKILL. `
829
+ `[VuvoDesk Client] Agent tree pid=${processId || 'unknown'} is still alive after SIGKILL. `
830
830
  + 'The launcher will remain alive and keep retrying so capture descendants are not orphaned.'
831
831
  );
832
832
  }
@@ -0,0 +1,66 @@
1
+ import { existsSync } from 'node:fs';
2
+
3
+ export const AGENT_SHELL_NAMES = Object.freeze([
4
+ 'auto',
5
+ 'powershell',
6
+ 'pwsh',
7
+ 'cmd',
8
+ 'sh',
9
+ 'bash',
10
+ 'zsh'
11
+ ]);
12
+
13
+ function unixShellPath(shell, platform, fileExists) {
14
+ if (shell === 'sh') return '/bin/sh';
15
+ if (shell === 'bash') return '/bin/bash';
16
+ if (shell === 'zsh') return '/bin/zsh';
17
+ if (shell === 'pwsh') return 'pwsh';
18
+ if (shell === 'powershell' || shell === 'cmd') {
19
+ throw new Error(`${shell} is not available on ${platform}.`);
20
+ }
21
+ if (platform === 'darwin' && fileExists('/bin/zsh')) return '/bin/zsh';
22
+ if (fileExists('/bin/bash')) return '/bin/bash';
23
+ return '/bin/sh';
24
+ }
25
+
26
+ export function resolveAgentShellCommand({
27
+ platform = process.platform,
28
+ shell = 'auto',
29
+ command = '',
30
+ fileExists = existsSync
31
+ } = {}) {
32
+ const normalizedShell = String(shell || 'auto').trim().toLowerCase();
33
+ if (!AGENT_SHELL_NAMES.includes(normalizedShell)) {
34
+ throw new Error(`Unsupported shell: ${normalizedShell || 'empty'}.`);
35
+ }
36
+ if (platform === 'win32') {
37
+ if (['sh', 'bash', 'zsh'].includes(normalizedShell)) {
38
+ throw new Error(`${normalizedShell} is not available on Windows.`);
39
+ }
40
+ if (normalizedShell === 'cmd') {
41
+ return {
42
+ shell: 'cmd',
43
+ executable: process.env.ComSpec || 'cmd.exe',
44
+ args: ['/d', '/s', '/c', String(command)]
45
+ };
46
+ }
47
+ const powershellCore = normalizedShell === 'pwsh';
48
+ return {
49
+ shell: powershellCore ? 'pwsh' : 'powershell',
50
+ executable: powershellCore ? 'pwsh.exe' : 'powershell.exe',
51
+ args: ['-NoLogo', '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', String(command)]
52
+ };
53
+ }
54
+
55
+ const executable = unixShellPath(normalizedShell, platform, fileExists);
56
+ if (executable.startsWith('/') && !fileExists(executable)) {
57
+ throw new Error(`${normalizedShell} is not installed at ${executable}.`);
58
+ }
59
+ return {
60
+ shell: normalizedShell === 'auto'
61
+ ? executable.endsWith('/zsh') ? 'zsh' : executable.endsWith('/bash') ? 'bash' : 'sh'
62
+ : normalizedShell,
63
+ executable,
64
+ args: ['-lc', String(command)]
65
+ };
66
+ }
@@ -20,8 +20,9 @@ const SUPABASE_URL = process.env.LIVEDESK_SUPABASE_URL || 'https://otbyfkjxrkngv
20
20
  const SUPABASE_PUBLISHABLE_KEY = process.env.LIVEDESK_SUPABASE_PUBLISHABLE_KEY || 'sb_publishable_NpUs0RDJH2YnllsqTKO6TQ_1jTdSsNQ';
21
21
  const CLIENT_STATE_DIR = process.env.LIVEDESK_STATE_DIR || (process.env.LIVEDESK_UNIFIED_RUNTIME === '1' ? join(os.homedir(), '.livedesk') : join(os.homedir(), '.livedesk-client'));
22
22
  const CLIENT_AUTH_PATH = join(CLIENT_STATE_DIR, 'auth.json');
23
- const DEFAULT_TRUSTED_WEB_ORIGINS = Object.freeze([
24
- 'https://livedesk.pages.dev',
23
+ const DEFAULT_TRUSTED_WEB_ORIGINS = Object.freeze([
24
+ 'https://vuvodesk.com',
25
+ 'https://livedesk.pages.dev',
25
26
  'http://127.0.0.1:5173',
26
27
  'http://localhost:5173',
27
28
  'http://127.0.0.1:4173',
@@ -1050,7 +1051,7 @@ function isTrustedLocalRequest(req, host, port, options = {}) {
1050
1051
 
1051
1052
  // Chromium can mark modulepreload/stylesheet requests as cross-site. Static
1052
1053
  // assets are not privileged. An opaque Origin (`null`) is never accepted for
1053
- // an API route because it cannot distinguish the LiveDesk shell from an
1054
+ // an API route because it cannot distinguish the VuvoDesk shell from an
1054
1055
  // attacker-controlled file, sandbox, or data page.
1055
1056
  if (options.allowStaticCrossSite === true) {
1056
1057
  return true;
@@ -1107,7 +1108,7 @@ export function createClientRuntimeServer(options = {}) {
1107
1108
  const initialChoiceMessage = normalizeString(
1108
1109
  options.initialChoiceMessage,
1109
1110
  1000
1110
- ) || 'Existing LiveDesk credentials accepted. Starting the Client.';
1111
+ ) || 'Existing VuvoDesk credentials accepted. Starting the Client.';
1111
1112
  const trustedWebOrigins = createTrustedWebOrigins(port);
1112
1113
  const webDist = resolve(String(options.webDist || process.env.LIVEDESK_WEB_DIST || '').trim() || join(process.cwd(), 'apps', 'web', 'dist'));
1113
1114
  const deviceId = normalizeString(options.deviceId || process.env.LIVEDESK_DEVICE_ID, 160);
@@ -1334,7 +1335,7 @@ export function createClientRuntimeServer(options = {}) {
1334
1335
  state.lastError = '';
1335
1336
  if (state.message.startsWith('Client authentication needs attention:')) {
1336
1337
  state.message = state.agent.state === 'running'
1337
- ? 'Connected to the LiveDesk Hub.'
1338
+ ? 'Connected to the VuvoDesk Hub.'
1338
1339
  : normalizeString(message, 1000) || 'Client credentials accepted. Finding the Hub.';
1339
1340
  }
1340
1341
  }
@@ -1453,7 +1454,7 @@ export function createClientRuntimeServer(options = {}) {
1453
1454
  : pathname.replace(/^\//, '');
1454
1455
  const filePath = resolve(webDist, requested);
1455
1456
  if (!filePath.startsWith(`${webDist}${process.platform === 'win32' ? '\\' : '/'}`) || !existsSync(filePath)) {
1456
- sendText(res, 404, 'LiveDesk web build is not available. Run npm run build.');
1457
+ sendText(res, 404, 'VuvoDesk web build is not available. Run npm run build.');
1457
1458
  return;
1458
1459
  }
1459
1460
  try {
@@ -1500,7 +1501,7 @@ export function createClientRuntimeServer(options = {}) {
1500
1501
  return;
1501
1502
  }
1502
1503
  if (pathname === '/api/health') {
1503
- respondJson(200, { ok: true, product: 'LiveDesk', role: 'client', timestamp: new Date().toISOString() });
1504
+ respondJson(200, { ok: true, product: 'LiveDesk', role: 'client', timestamp: new Date().toISOString() });
1504
1505
  return;
1505
1506
  }
1506
1507
  if (pathname === '/api/client/diagnostics') {
@@ -1582,7 +1583,7 @@ export function createClientRuntimeServer(options = {}) {
1582
1583
  };
1583
1584
  if (!writeSavedSession(session)) throw new Error('refresh-token-required');
1584
1585
  state.auth.persisted = true;
1585
- complete({ type: 'google', session }, 'Signed in. Finding the LiveDesk Hub.');
1586
+ complete({ type: 'google', session }, 'Signed in. Finding the VuvoDesk Hub.');
1586
1587
  res.writeHead(303, { Location: '/', 'Cache-Control': 'no-store' });
1587
1588
  res.end();
1588
1589
  } catch (error) {
@@ -1629,7 +1630,7 @@ export function createClientRuntimeServer(options = {}) {
1629
1630
  respondJson(500, { ok: false, error: message });
1630
1631
  return;
1631
1632
  }
1632
- complete({ type: 'google', session }, 'Signed in. Finding the LiveDesk Hub.');
1633
+ complete({ type: 'google', session }, 'Signed in. Finding the VuvoDesk Hub.');
1633
1634
  respondJson(200, { ok: true, authenticated: true, persisted: true, role: 'client' });
1634
1635
  return;
1635
1636
  }
@@ -1812,7 +1813,7 @@ export function createClientRuntimeServer(options = {}) {
1812
1813
  state.manager = '';
1813
1814
  state.agent.state = 'reconnecting';
1814
1815
  state.lastError = '';
1815
- state.message = 'Refreshing the LiveDesk Hub discovery now.';
1816
+ state.message = 'Refreshing the VuvoDesk Hub discovery now.';
1816
1817
  runtime.update({ state: RuntimeState.RESOLVING_ROLE }, 'client-reconnect-requested');
1817
1818
  runtime.emit('client.reconnect.requested', { deviceId, previousManager: previousManager || '' });
1818
1819
  await options.onReconnect?.();
@@ -1895,7 +1896,7 @@ export function createClientRuntimeServer(options = {}) {
1895
1896
  const hydratedSession = await hydrateClientAccountProfile(normalizedSession);
1896
1897
  if (!writeSavedSession(hydratedSession)) throw new Error('refresh-token-required');
1897
1898
  state.auth.persisted = true;
1898
- complete({ type: 'google', session: hydratedSession }, 'Saved sign-in found. Finding the LiveDesk Hub.');
1899
+ complete({ type: 'google', session: hydratedSession }, 'Saved sign-in found. Finding the VuvoDesk Hub.');
1899
1900
  } catch (error) {
1900
1901
  recordAuthAttempt('rejected', `session-persistence-failed:${normalizeString(error?.message || error, 160)}`);
1901
1902
  }
@@ -385,6 +385,6 @@ export async function installLinuxVideoAcceleration(currentStatus, options = {})
385
385
  ...refreshed,
386
386
  busy: false,
387
387
  restartAgent: true,
388
- message: 'VAAPI hardware video is ready. Restarting the LiveDesk Agent…'
388
+ message: 'VAAPI hardware video is ready. Restarting the VuvoDesk Agent…'
389
389
  };
390
390
  }
@@ -135,13 +135,13 @@ export function writeWindowsOwnedProcessManifest({
135
135
  if (!exactOwner) {
136
136
  return {
137
137
  ok: false,
138
- error: resultError('An exact Windows LiveDesk launcher owner is required.')
138
+ error: resultError('An exact Windows VuvoDesk launcher owner is required.')
139
139
  };
140
140
  }
141
141
  if (!exactRecords) {
142
142
  return {
143
143
  ok: false,
144
- error: resultError('Every Windows LiveDesk process record requires exact PID and CreationDate identity.')
144
+ error: resultError('Every Windows VuvoDesk process record requires exact PID and CreationDate identity.')
145
145
  };
146
146
  }
147
147
  if (!Number.isFinite(nowMs)) {
@@ -177,7 +177,7 @@ function readExactWindowsOwnedProcessManifest({
177
177
  return {
178
178
  ok: false,
179
179
  records: [],
180
- error: resultError('An exact Windows LiveDesk launcher owner is required.')
180
+ error: resultError('An exact Windows VuvoDesk launcher owner is required.')
181
181
  };
182
182
  }
183
183
  if (!Number.isFinite(nowMs)
@@ -210,7 +210,7 @@ function readExactWindowsOwnedProcessManifest({
210
210
  ok: false,
211
211
  records: [],
212
212
  updatedAt,
213
- error: resultError('Unsupported Windows LiveDesk process-manifest version.')
213
+ error: resultError('Unsupported Windows VuvoDesk process-manifest version.')
214
214
  };
215
215
  }
216
216
  if (!ownersMatch(parsed?.owner, exactOwner)) {
@@ -218,7 +218,7 @@ function readExactWindowsOwnedProcessManifest({
218
218
  ok: false,
219
219
  records: [],
220
220
  updatedAt,
221
- error: resultError('Windows LiveDesk process manifest belongs to another launcher generation.')
221
+ error: resultError('Windows VuvoDesk process manifest belongs to another launcher generation.')
222
222
  };
223
223
  }
224
224
  if (!Number.isFinite(updatedAtMs)
@@ -228,7 +228,7 @@ function readExactWindowsOwnedProcessManifest({
228
228
  ok: false,
229
229
  records: [],
230
230
  updatedAt,
231
- error: resultError('Windows LiveDesk process manifest is stale or has an invalid timestamp.')
231
+ error: resultError('Windows VuvoDesk process manifest is stale or has an invalid timestamp.')
232
232
  };
233
233
  }
234
234
  const exactRecords = normalizeRecords(parsed?.records);
@@ -237,7 +237,7 @@ function readExactWindowsOwnedProcessManifest({
237
237
  ok: false,
238
238
  records: [],
239
239
  updatedAt,
240
- error: resultError('Windows LiveDesk process manifest contains an invalid process identity.')
240
+ error: resultError('Windows VuvoDesk process manifest contains an invalid process identity.')
241
241
  };
242
242
  }
243
243
  return {
@@ -327,7 +327,7 @@ export function consumeDeadWindowsOwnedProcessManifest({
327
327
  ok: false,
328
328
  path,
329
329
  consumed: false,
330
- error: resultError('Windows LiveDesk process manifest changed after its exact process set was drained.')
330
+ error: resultError('Windows VuvoDesk process manifest changed after its exact process set was drained.')
331
331
  };
332
332
  }
333
333
 
@@ -374,7 +374,7 @@ export function consumeDeadWindowsOwnedProcessManifest({
374
374
  quarantinePath: restored ? undefined : quarantinePath,
375
375
  consumed: false,
376
376
  error: resultError(
377
- 'Windows LiveDesk process manifest changed during consumption; '
377
+ 'Windows VuvoDesk process manifest changed during consumption; '
378
378
  + `${restored ? 'the moved generation was restored.' : 'the moved generation was preserved.'}`
379
379
  + `${restoreError?.message ? ` ${restoreError.message}` : ''}`
380
380
  )
@@ -15,13 +15,13 @@ test('prints the public launcher version in the user-facing banner', () => {
15
15
  LIVEDESK_NPM_LAUNCHER_NAME: 'livedesk',
16
16
  LIVEDESK_NPM_LAUNCHER_VERSION: '9.8.7'
17
17
  }),
18
- '[LiveDesk Client] livedesk@9.8.7'
18
+ '[VuvoDesk Client] livedesk@9.8.7'
19
19
  );
20
20
  });
21
21
 
22
22
  test('uses the product name for direct client launches', () => {
23
23
  assert.equal(
24
24
  formatClientVersionBanner({}),
25
- `[LiveDesk Client] livedesk@${packageInfo.version}`
25
+ `[VuvoDesk Client] livedesk@${packageInfo.version}`
26
26
  );
27
27
  });