livedesk 0.1.264 → 0.1.266

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.
@@ -292,16 +292,9 @@ export function createLiveDeskUpdateManager({
292
292
  };
293
293
  const result = supportsDedicated
294
294
  ? remoteHub.sendCommand(device.deviceId, { command: LIVE_DESK_UPDATE_COMMAND, payload })
295
- : remoteHub.requestAgentTask(device.deviceId, {
296
- operation: 'command.run',
297
- title: 'Update LiveDesk client',
298
- instruction: 'Update and restart this LiveDesk client.',
299
- toolArguments: {
300
- command: buildLegacyUpdateCommand(device, credentials, run.latestClientVersion),
301
- timeoutMs: 30_000
302
- },
303
- permissionMode: 'full-access',
304
- approvalLevel: 'once'
295
+ : remoteHub.sendLegacyClientUpdate(device.deviceId, {
296
+ command: buildLegacyUpdateCommand(device, credentials, run.latestClientVersion),
297
+ timeoutMs: 30_000
305
298
  });
306
299
  if (result?.ok !== true) {
307
300
  target.state = 'failed';
@@ -326,7 +319,7 @@ export function createLiveDeskUpdateManager({
326
319
  const outdatedClients = connected.filter(device => !isVersionAtLeast(device.agentVersion, release.latestClientVersion));
327
320
  const needsHubRestart = managerNeedsUpdate || clientPackageNeedsUpdate;
328
321
  if (!managerNeedsUpdate && !clientPackageNeedsUpdate && outdatedClients.length === 0) {
329
- return { ok: false, error: 'LiveDesk is already up to date.', ...getStatus() };
322
+ return { ok: true, state: 'clients-updated', ...getStatus() };
330
323
  }
331
324
  if (needsHubRestart && !restartSupported) {
332
325
  return { ok: false, error: 'Hub launcher restart is unavailable. Start LiveDesk through npx livedesk@latest.', ...getStatus() };
@@ -1387,11 +1387,14 @@ export function createRemoteHub(options = {}) {
1387
1387
  const logEvent = options.logEvent || (() => {});
1388
1388
  const logWarn = options.logWarn || (() => {});
1389
1389
  const emitEvent = options.emitEvent || (() => {});
1390
- const emitFrame = typeof options.emitFrame === 'function' ? options.emitFrame : (() => {});
1391
- const emitAudio = typeof options.emitAudio === 'function' ? options.emitAudio : (() => {});
1392
- const getEffectiveDevicePolicy = typeof options.getEffectiveDevicePolicy === 'function'
1393
- ? options.getEffectiveDevicePolicy
1394
- : (() => ({}));
1390
+ const emitFrame = typeof options.emitFrame === 'function' ? options.emitFrame : (() => {});
1391
+ const emitAudio = typeof options.emitAudio === 'function' ? options.emitAudio : (() => {});
1392
+ const getEffectiveDevicePolicy = typeof options.getEffectiveDevicePolicy === 'function'
1393
+ ? options.getEffectiveDevicePolicy
1394
+ : (() => ({}));
1395
+ const getWelcomeDevicePolicy = typeof options.getWelcomeDevicePolicy === 'function'
1396
+ ? options.getWelcomeDevicePolicy
1397
+ : getEffectiveDevicePolicy;
1395
1398
 
1396
1399
  function getDevicePolicy(device) {
1397
1400
  try {
@@ -2668,7 +2671,7 @@ export function createRemoteHub(options = {}) {
2668
2671
  heartbeatMs,
2669
2672
  frameProtocol: buildRemoteFrameProtocolDescriptor(),
2670
2673
  frameModes: getSupportedRemoteFrameModeProfiles(),
2671
- effectivePolicy: getEffectiveDevicePolicy({ deviceId, capabilities }),
2674
+ effectivePolicy: getWelcomeDevicePolicy({ deviceId, capabilities }),
2672
2675
  serverTime: now
2673
2676
  });
2674
2677
 
@@ -4487,17 +4490,17 @@ export function createRemoteHub(options = {}) {
4487
4490
  return true;
4488
4491
  }
4489
4492
 
4490
- function sendCommand(deviceId, command) {
4493
+ function sendCommand(deviceId, command) {
4491
4494
  const device = devices.get(String(deviceId || ''));
4492
4495
  const commandName = safeString(command?.command || 'ping', 80);
4493
4496
  const requiredPermission = commandName === 'input.control'
4494
4497
  ? 'allowControl'
4495
4498
  : commandName.startsWith('file.transfer')
4496
4499
  ? 'allowFileTransfer'
4497
- : commandName === 'audio.start'
4498
- ? 'allowRemoteAudio'
4500
+ : commandName === 'audio.start'
4501
+ ? 'allowRemoteAudio'
4499
4502
  : commandName === 'livedesk.client-update'
4500
- ? 'allowAgent'
4503
+ ? ''
4501
4504
  : commandName.startsWith('agent.')
4502
4505
  ? 'allowAgent'
4503
4506
  : '';
@@ -4551,8 +4554,44 @@ export function createRemoteHub(options = {}) {
4551
4554
  command: payload.command,
4552
4555
  channel: dedicatedFileSocket ? 'file' : 'control'
4553
4556
  });
4554
- return { ok: true, commandId };
4555
- }
4557
+ return { ok: true, commandId };
4558
+ }
4559
+
4560
+ // Client updates are an explicit Hub maintenance action, not an Agent task.
4561
+ // This legacy path is kept for clients that predate the dedicated update command.
4562
+ function sendLegacyClientUpdate(deviceId, options = {}) {
4563
+ const device = devices.get(String(deviceId || ''));
4564
+ const denied = policyError(device);
4565
+ if (denied) return { ok: false, error: denied };
4566
+ if (!device) return { ok: false, error: 'device-not-found' };
4567
+ if (!device.socket || device.socket.destroyed || !device.connected) {
4568
+ return { ok: false, error: 'device-not-connected' };
4569
+ }
4570
+
4571
+ const command = safeString(options.command, 20000);
4572
+ if (!command) return { ok: false, error: 'client-update-command-missing' };
4573
+ const commandId = safeString(options.commandId, 128) || crypto.randomUUID();
4574
+ const sent = writeJsonLine(device.socket, {
4575
+ type: 'command',
4576
+ commandId,
4577
+ command: 'command.run',
4578
+ payload: {
4579
+ command,
4580
+ timeoutMs: clampNumber(options.timeoutMs, 1000, 120000, 30000),
4581
+ permissionMode: 'full-access'
4582
+ },
4583
+ issuedAt: new Date().toISOString()
4584
+ });
4585
+ if (!sent) return { ok: false, error: 'device-not-connected' };
4586
+ device.counters.commandsSent += 1;
4587
+ emitRemoteEvent('RemoteCommandQueued', device, {
4588
+ commandId,
4589
+ command: 'command.run',
4590
+ maintenance: 'client-update',
4591
+ channel: 'control'
4592
+ });
4593
+ return { ok: true, commandId };
4594
+ }
4556
4595
 
4557
4596
  function sendInputControl(deviceId, input = {}) {
4558
4597
  const device = devices.get(String(deviceId || ''));
@@ -5481,7 +5520,8 @@ export function createRemoteHub(options = {}) {
5481
5520
  retryTaskBatch,
5482
5521
  listDeviceFrames,
5483
5522
  disconnectDevice,
5484
- sendCommand,
5523
+ sendCommand,
5524
+ sendLegacyClientUpdate,
5485
5525
  sendInputControl,
5486
5526
  requestAgentTask,
5487
5527
  requestAgentTaskBatch,
package/hub/src/server.js CHANGED
@@ -261,9 +261,19 @@ const remoteHub = createRemoteHub({
261
261
  logEvent: (_scope, message) => console.log(`[LiveDesk Hub] ${message}`),
262
262
  logWarn: (_scope, message) => console.warn(`[LiveDesk Hub] ${message}`),
263
263
  emitEvent: handleRemoteHubEvent,
264
- emitFrame: broadcastRemoteBinaryFrame,
265
- emitAudio: broadcastRemoteBinaryAudio,
266
- getEffectiveDevicePolicy: ({ deviceId, capabilities }) => buildEffectiveDevicePolicy(liveDeskSettingsStore.getCached(), { deviceId, capabilities })
264
+ emitFrame: broadcastRemoteBinaryFrame,
265
+ emitAudio: broadcastRemoteBinaryAudio,
266
+ getEffectiveDevicePolicy: ({ deviceId, capabilities }) => buildEffectiveDevicePolicy(liveDeskSettingsStore.getCached(), { deviceId, capabilities }),
267
+ getWelcomeDevicePolicy: ({ deviceId, capabilities }) => {
268
+ const policy = buildEffectiveDevicePolicy(liveDeskSettingsStore.getCached(), { deviceId, capabilities });
269
+ const hasClientUpdatePath = capabilities?.clientUpdate === true
270
+ || (Array.isArray(capabilities?.agentTools) && capabilities.agentTools.length > 0);
271
+ if (!hasClientUpdatePath || policy.allowAgent || policy.accessMode === 'block-remote-access') return policy;
272
+ // Compatibility grant for the client-side policy gate. The Hub remains
273
+ // authoritative for every normal Agent command; this only bootstraps the
274
+ // updater on clients that predate livedesk.client-update.
275
+ return { ...policy, allowAgent: true };
276
+ }
267
277
  });
268
278
 
269
279
  function requestHubRestart(request = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livedesk",
3
- "version": "0.1.264",
3
+ "version": "0.1.266",
4
4
  "description": "LiveDesk Hub and client launcher",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
34
- "@livedesk/client": "0.1.135",
34
+ "@livedesk/client": "0.1.136",
35
35
  "@openai/codex-sdk": "0.144.5",
36
36
  "cors": "^2.8.5",
37
37
  "express": "^4.21.2",