livedesk 0.1.598 → 0.1.600

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.
@@ -1,53 +1,53 @@
1
- {
2
- "name": "@livedesk/client",
3
- "version": "0.1.254",
4
- "description": "VuvoDesk local remote client",
5
- "type": "module",
6
- "bin": {
7
- "client": "bin/livedesk-client.js",
8
- "livedesk-client": "bin/livedesk-client.js",
9
- "livedesk-client-node": "bin/livedesk-client-node.js",
10
- "livedesk-client-fast": "bin/livedesk-client-fast.js"
11
- },
12
- "files": [
13
- "bin/",
14
- "src/",
15
- "tests/",
16
- "README.md",
17
- "THIRD_PARTY_NOTICES.md"
18
- ],
19
- "scripts": {
20
- "check": "node --check bin/client-version.js && node --check bin/livedesk-client.js && node --check bin/livedesk-client-node.js && node --check bin/livedesk-client-update-bootstrap.cjs && node --check bin/livedesk-client-fast.js",
21
- "test:version": "node --test tests/client-version.test.mjs",
22
- "pack:dry": "npm pack --dry-run",
23
- "prepublishOnly": "node ../../scripts/livedesk-release-git-gate.mjs"
24
- },
25
- "keywords": [
26
- "livedesk",
27
- "remote",
28
- "agent",
29
- "local",
30
- "desktop"
31
- ],
32
- "license": "MIT",
33
- "engines": {
34
- "node": ">=20"
35
- },
36
- "dependencies": {
37
- "@ffmpeg-installer/ffmpeg": "^1.1.0",
38
- "ffmpeg-static": "^5.3.0",
39
- "@livedesk/runtime-core": "0.1.6",
40
- "@supabase/supabase-js": "^2.110.0",
41
- "node-screenshots": "^0.2.8",
42
- "ws": "^8.18.3"
43
- },
44
- "optionalDependencies": {
45
- "@livedesk/fast-linux-x64": "0.1.450",
46
- "@livedesk/fast-osx-arm64": "0.1.450",
47
- "@livedesk/fast-osx-x64": "0.1.450",
48
- "@livedesk/fast-win-x64": "0.1.450"
49
- },
50
- "publishConfig": {
51
- "access": "public"
52
- }
53
- }
1
+ {
2
+ "name": "@livedesk/client",
3
+ "version": "0.1.256",
4
+ "description": "VuvoDesk local remote client",
5
+ "type": "module",
6
+ "bin": {
7
+ "client": "bin/livedesk-client.js",
8
+ "livedesk-client": "bin/livedesk-client.js",
9
+ "livedesk-client-node": "bin/livedesk-client-node.js",
10
+ "livedesk-client-fast": "bin/livedesk-client-fast.js"
11
+ },
12
+ "files": [
13
+ "bin/",
14
+ "src/",
15
+ "tests/",
16
+ "README.md",
17
+ "THIRD_PARTY_NOTICES.md"
18
+ ],
19
+ "scripts": {
20
+ "check": "node --check bin/client-version.js && node --check bin/livedesk-client.js && node --check bin/livedesk-client-node.js && node --check bin/livedesk-client-update-bootstrap.cjs && node --check bin/livedesk-client-fast.js",
21
+ "test:version": "node --test tests/client-version.test.mjs",
22
+ "pack:dry": "npm pack --dry-run",
23
+ "prepublishOnly": "node ../../scripts/livedesk-release-git-gate.mjs"
24
+ },
25
+ "keywords": [
26
+ "livedesk",
27
+ "remote",
28
+ "agent",
29
+ "local",
30
+ "desktop"
31
+ ],
32
+ "license": "MIT",
33
+ "engines": {
34
+ "node": ">=20"
35
+ },
36
+ "dependencies": {
37
+ "@ffmpeg-installer/ffmpeg": "^1.1.0",
38
+ "ffmpeg-static": "^5.3.0",
39
+ "@livedesk/runtime-core": "0.1.6",
40
+ "@supabase/supabase-js": "^2.110.0",
41
+ "node-screenshots": "^0.2.8",
42
+ "ws": "^8.18.3"
43
+ },
44
+ "optionalDependencies": {
45
+ "@livedesk/fast-linux-x64": "0.1.453",
46
+ "@livedesk/fast-osx-arm64": "0.1.453",
47
+ "@livedesk/fast-osx-x64": "0.1.453",
48
+ "@livedesk/fast-win-x64": "0.1.453"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ }
53
+ }
package/hub/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/hub",
3
- "version": "0.1.50",
3
+ "version": "0.1.51",
4
4
  "description": "VuvoDesk local Hub API and browser frame bridge",
5
5
  "type": "module",
6
6
  "main": "src/server.js",
@@ -4300,10 +4300,12 @@ export function createRemoteHub(options = {}) {
4300
4300
  device.inputWriteOwner = null;
4301
4301
  device.inputSocketConnectionId = '';
4302
4302
  device.inputOwnerConnectionId = '';
4303
- device.inputOwnerBindingKey = '';
4304
- inputSockets.delete(socket);
4305
- writeOwner?.close?.(reason);
4306
- try {
4303
+ device.inputOwnerBindingKey = '';
4304
+ inputSockets.delete(socket);
4305
+ writeOwner?.close?.(reason);
4306
+ device.inputLastSeenAt = new Date().toISOString();
4307
+ emitRemoteEvent('RemoteInputSocketDisconnected', device, { reason });
4308
+ try {
4307
4309
  writeJsonLine(socket, { type: 'disconnect', reason });
4308
4310
  } catch {
4309
4311
  // Best-effort notice before closing the side channel.
@@ -9026,15 +9028,40 @@ export function createRemoteHub(options = {}) {
9026
9028
  };
9027
9029
  }
9028
9030
 
9029
- function getCurrentInputWriteOwner(device) {
9031
+ function getCurrentInputWriteOwner(device) {
9030
9032
  if (!device?.inputSocket
9031
9033
  || device.inputSocket.destroyed
9032
9034
  || !device.inputWriteOwner
9033
9035
  || !safeString(device.inputSocketConnectionId, 128)) {
9034
9036
  return null;
9035
9037
  }
9036
- return device.inputWriteOwner;
9037
- }
9038
+ return device.inputWriteOwner;
9039
+ }
9040
+
9041
+ function getInputRouteState(deviceId) {
9042
+ const device = devices.get(String(deviceId || ''));
9043
+ if (!device || !device.connected || !device.socket || device.socket.destroyed) {
9044
+ return {
9045
+ deviceId: safeString(deviceId, 160),
9046
+ ready: false,
9047
+ dedicatedInputChannel: false,
9048
+ reason: 'device-not-connected'
9049
+ };
9050
+ }
9051
+
9052
+ const dedicatedInputChannel = readCapabilityFlag(
9053
+ device.capabilities,
9054
+ 'dedicatedInputChannel');
9055
+ const ready = dedicatedInputChannel
9056
+ ? !!getCurrentInputWriteOwner(device)
9057
+ : true;
9058
+ return {
9059
+ deviceId: device.deviceId,
9060
+ ready,
9061
+ dedicatedInputChannel,
9062
+ reason: ready ? 'ready' : 'input-channel-not-connected'
9063
+ };
9064
+ }
9038
9065
 
9039
9066
  function sendInputControl(deviceId, input = {}) {
9040
9067
  const device = devices.get(String(deviceId || ''));
@@ -11835,8 +11862,9 @@ export function createRemoteHub(options = {}) {
11835
11862
  sendClipboardCommand,
11836
11863
  refreshDevicePolicies,
11837
11864
  sendLegacyClientUpdate,
11838
- sendInputControl,
11839
- releaseInputOwner,
11865
+ sendInputControl,
11866
+ getInputRouteState,
11867
+ releaseInputOwner,
11840
11868
  notifyAgentProgress,
11841
11869
  requestAgentTask,
11842
11870
  requestAgentTaskBatch,
package/hub/src/server.js CHANGED
@@ -253,15 +253,35 @@ function readPositiveIntegerEnv(name, fallback) {
253
253
  return Number.isFinite(value) && value > 0 ? Math.round(value) : fallback;
254
254
  }
255
255
 
256
- function secureExactTestTokenMatches(actual, expected) {
256
+ function secureExactTestTokenMatches(actual, expected) {
257
257
  const actualBytes = Buffer.from(String(actual || ''), 'utf8');
258
258
  const expectedBytes = Buffer.from(String(expected || ''), 'utf8');
259
259
  return actualBytes.length > 0
260
260
  && actualBytes.length === expectedBytes.length
261
- && crypto.timingSafeEqual(actualBytes, expectedBytes);
262
- }
263
-
264
- function handleRemoteHubEvent(type, event) {
261
+ && crypto.timingSafeEqual(actualBytes, expectedBytes);
262
+ }
263
+
264
+ function sendRemoteInputRouteState(ws, deviceId, reason = '') {
265
+ const route = remoteHub.getInputRouteState(deviceId);
266
+ sendJson(ws, {
267
+ type: 'RemoteInputRouteState',
268
+ ...route,
269
+ reason: String(reason || route.reason || ''),
270
+ timestamp: new Date().toISOString()
271
+ });
272
+ }
273
+
274
+ function broadcastRemoteInputRouteState(deviceId, reason = '') {
275
+ const normalizedDeviceId = String(deviceId || '').trim();
276
+ if (!normalizedDeviceId) return;
277
+ for (const ws of inputClients) {
278
+ if (ws.readyState === 1 && ws.liveDeskInputDeviceIds?.has(normalizedDeviceId)) {
279
+ sendRemoteInputRouteState(ws, normalizedDeviceId, reason);
280
+ }
281
+ }
282
+ }
283
+
284
+ function handleRemoteHubEvent(type, event) {
265
285
  liveDeskUpdateManager?.handleRemoteEvent(type, event);
266
286
  hubTransferJobs?.handleRemoteEvent(type, event);
267
287
  if (traceRemoteTestEventsEnabled
@@ -297,7 +317,7 @@ function handleRemoteHubEvent(type, event) {
297
317
  }
298
318
  return;
299
319
  }
300
- if (type === 'RemoteInputError') {
320
+ if (type === 'RemoteInputError') {
301
321
  const targetConnectionId = String(event?.hubConnectionId || '').trim();
302
322
  for (const ws of inputClients) {
303
323
  if (targetConnectionId && ws.liveDeskInputClientId !== targetConnectionId) {
@@ -308,11 +328,18 @@ function handleRemoteHubEvent(type, event) {
308
328
  ...event
309
329
  });
310
330
  }
311
- return;
312
- }
313
- if (type === 'RemoteDeviceConnected' || type === 'RemoteDeviceDisconnected') {
314
- connectedDeviceCount = Number(remoteHub.getStatus({ includeSecrets: false }).connectedDeviceCount || 0);
315
- }
331
+ return;
332
+ }
333
+ if (type === 'RemoteInputSocketConnected' || type === 'RemoteInputSocketDisconnected') {
334
+ const deviceId = String(event?.deviceId || event?.device?.deviceId || '').trim();
335
+ broadcastRemoteInputRouteState(deviceId, event?.reason || type);
336
+ return;
337
+ }
338
+ if (type === 'RemoteDeviceConnected' || type === 'RemoteDeviceDisconnected') {
339
+ connectedDeviceCount = Number(remoteHub.getStatus({ includeSecrets: false }).connectedDeviceCount || 0);
340
+ const deviceId = String(event?.deviceId || event?.device?.deviceId || '').trim();
341
+ broadcastRemoteInputRouteState(deviceId, event?.reason || type);
342
+ }
316
343
  if (type !== 'RemoteDeviceConnected') {
317
344
  return;
318
345
  }
@@ -5794,7 +5821,7 @@ frameWss.on('connection', (ws, req) => {
5794
5821
  } catch {
5795
5822
  updateFrameSubscription(ws, {});
5796
5823
  }
5797
- ws.on('message', data => {
5824
+ ws.on('message', data => {
5798
5825
  try {
5799
5826
  const payload = JSON.parse(Buffer.isBuffer(data) ? data.toString('utf8') : String(data || ''));
5800
5827
  if (payload?.type === 'subscribe') {
@@ -5900,11 +5927,29 @@ inputWss.on('connection', ws => {
5900
5927
  try {
5901
5928
  payload = JSON.parse(Buffer.isBuffer(data) ? data.toString('utf8') : String(data || ''));
5902
5929
  } catch {
5903
- sendJson(ws, { type: 'RemoteInputError', error: 'invalid-json' });
5904
- return;
5905
- }
5906
- const deviceId = String(payload?.deviceId || '').trim();
5907
- const inputEventId = String(
5930
+ sendJson(ws, { type: 'RemoteInputError', error: 'invalid-json' });
5931
+ return;
5932
+ }
5933
+ const deviceId = String(payload?.deviceId || '').trim();
5934
+ if (payload?.type === 'watch') {
5935
+ if (!deviceId) {
5936
+ sendJson(ws, { type: 'RemoteInputError', error: 'device-id-required' });
5937
+ return;
5938
+ }
5939
+ for (const previousDeviceId of ws.liveDeskInputDeviceIds) {
5940
+ if (previousDeviceId !== deviceId) {
5941
+ remoteHub.releaseInputOwner(
5942
+ previousDeviceId,
5943
+ ws.liveDeskInputClientId,
5944
+ 'browser-input-target-changed');
5945
+ }
5946
+ }
5947
+ ws.liveDeskInputDeviceIds.clear();
5948
+ ws.liveDeskInputDeviceIds.add(deviceId);
5949
+ sendRemoteInputRouteState(ws, deviceId, 'browser-input-watch');
5950
+ return;
5951
+ }
5952
+ const inputEventId = String(
5908
5953
  payload?.input?.inputEventId
5909
5954
  || payload?.inputEventId
5910
5955
  || payload?.requestId
package/package.json CHANGED
@@ -1,62 +1,62 @@
1
- {
2
- "name": "livedesk",
3
- "version": "0.1.598",
4
- "livedeskClientVersion": "0.1.254",
5
- "buildFlavor": "production",
6
- "description": "VuvoDesk Hub and client launcher",
7
- "type": "module",
8
- "main": "electron/main.mjs",
9
- "bin": {
10
- "livedesk": "bin/livedesk.js"
11
- },
12
- "files": [
13
- "bin/",
14
- "bootstrap/",
15
- "diagnostics/",
16
- "hub/",
17
- "runtime-core/",
18
- "client/",
19
- "electron/",
20
- "scripts/",
21
- "web/",
22
- "README.md"
23
- ],
24
- "scripts": {
25
- "check": "node --check bin/livedesk.js && node --check bootstrap/npm-update-cache.mjs && node --check bootstrap/update-host-client.mjs && node --check bootstrap/update-host.mjs && node --check diagnostics/livedesk-mode3-capture-smoke.mjs && node --check diagnostics/livedesk-mac-physical-gate-core.mjs && node --check diagnostics/livedesk-mac-physical-isolation.mjs && node --check diagnostics/livedesk-transport-physical-core.mjs && node --check diagnostics/livedesk-transport-physical.mjs && node --check scripts/sync-web-dist.js",
26
- "build": "node scripts/sync-web-dist.js",
27
- "prepack": "node scripts/sync-web-dist.js",
28
- "pack:dry": "npm pack --dry-run",
29
- "prepublishOnly": "node ../../scripts/livedesk-release-git-gate.mjs"
30
- },
31
- "keywords": [
32
- "livedesk",
33
- "remote",
34
- "screen-wall",
35
- "hub",
36
- "local"
37
- ],
38
- "license": "MIT",
39
- "engines": {
40
- "node": ">=20"
41
- },
42
- "dependencies": {
43
- "@openai/codex-sdk": "0.145.0",
44
- "@supabase/supabase-js": "^2.110.0",
45
- "cors": "^2.8.5",
46
- "electron-updater": "^6.8.9",
47
- "express": "^4.21.2",
48
- "ffmpeg-static": "^5.3.0",
49
- "node-screenshots": "^0.2.8",
50
- "path-to-regexp": "0.1.13",
51
- "ws": "^8.18.3"
52
- },
53
- "optionalDependencies": {
54
- "@livedesk/fast-linux-x64": "0.1.450",
55
- "@livedesk/fast-osx-arm64": "0.1.450",
56
- "@livedesk/fast-osx-x64": "0.1.450",
57
- "@livedesk/fast-win-x64": "0.1.450"
58
- },
59
- "publishConfig": {
60
- "access": "public"
61
- }
62
- }
1
+ {
2
+ "name": "livedesk",
3
+ "version": "0.1.600",
4
+ "livedeskClientVersion": "0.1.256",
5
+ "buildFlavor": "production",
6
+ "description": "VuvoDesk Hub and client launcher",
7
+ "type": "module",
8
+ "main": "electron/main.mjs",
9
+ "bin": {
10
+ "livedesk": "bin/livedesk.js"
11
+ },
12
+ "files": [
13
+ "bin/",
14
+ "bootstrap/",
15
+ "diagnostics/",
16
+ "hub/",
17
+ "runtime-core/",
18
+ "client/",
19
+ "electron/",
20
+ "scripts/",
21
+ "web/",
22
+ "README.md"
23
+ ],
24
+ "scripts": {
25
+ "check": "node --check bin/livedesk.js && node --check bootstrap/npm-update-cache.mjs && node --check bootstrap/update-host-client.mjs && node --check bootstrap/update-host.mjs && node --check diagnostics/livedesk-mode3-capture-smoke.mjs && node --check diagnostics/livedesk-mac-physical-gate-core.mjs && node --check diagnostics/livedesk-mac-physical-isolation.mjs && node --check diagnostics/livedesk-transport-physical-core.mjs && node --check diagnostics/livedesk-transport-physical.mjs && node --check scripts/sync-web-dist.js",
26
+ "build": "node scripts/sync-web-dist.js",
27
+ "prepack": "node scripts/sync-web-dist.js",
28
+ "pack:dry": "npm pack --dry-run",
29
+ "prepublishOnly": "node ../../scripts/livedesk-release-git-gate.mjs"
30
+ },
31
+ "keywords": [
32
+ "livedesk",
33
+ "remote",
34
+ "screen-wall",
35
+ "hub",
36
+ "local"
37
+ ],
38
+ "license": "MIT",
39
+ "engines": {
40
+ "node": ">=20"
41
+ },
42
+ "dependencies": {
43
+ "@openai/codex-sdk": "0.145.0",
44
+ "@supabase/supabase-js": "^2.110.0",
45
+ "cors": "^2.8.5",
46
+ "electron-updater": "^6.8.9",
47
+ "express": "^4.21.2",
48
+ "ffmpeg-static": "^5.3.0",
49
+ "node-screenshots": "^0.2.8",
50
+ "path-to-regexp": "0.1.13",
51
+ "ws": "^8.18.3"
52
+ },
53
+ "optionalDependencies": {
54
+ "@livedesk/fast-linux-x64": "0.1.453",
55
+ "@livedesk/fast-osx-arm64": "0.1.453",
56
+ "@livedesk/fast-osx-x64": "0.1.453",
57
+ "@livedesk/fast-win-x64": "0.1.453"
58
+ },
59
+ "publishConfig": {
60
+ "access": "public"
61
+ }
62
+ }
@@ -4,7 +4,7 @@
4
4
  "short_name": "VuvoDesk",
5
5
  "description": "Monitor and control your VuvoDesk computers from your phone.",
6
6
  "lang": "en",
7
- "start_url": "/app?pwa=0.1.596",
7
+ "start_url": "/app?pwa=0.1.600",
8
8
  "scope": "/",
9
9
  "display": "standalone",
10
10
  "orientation": "any",