livedesk 0.1.419 → 0.1.421
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/hub/src/agents/agent-tool-registry.js +19 -19
- package/hub/src/agents/codex-agent-runtime.js +2 -2
- package/hub/src/filesystem/shared-folders.js +1 -1
- package/hub/src/mode4-atlas-pool.js +3 -1
- package/hub/src/remote-hub.js +1 -1
- package/hub/src/server.js +13 -9
- package/package.json +1 -1
- package/web/dist/assets/index-CfeAeBc8.js +25 -0
- package/web/dist/assets/{index-Bt3n0Lrm.css → index-TvE2gQGi.css} +1 -1
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-CRb9c7S3.js +0 -25
|
@@ -27,7 +27,7 @@ const readTaskPermission = { ask: 'allow', safeAuto: 'allow', fullAccess: 'allow
|
|
|
27
27
|
export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
28
28
|
{
|
|
29
29
|
name: 'livedesk.list_devices',
|
|
30
|
-
description: 'List connected LiveDesk
|
|
30
|
+
description: 'List connected LiveDesk Clients. This is read-only.',
|
|
31
31
|
category: 'read',
|
|
32
32
|
readOnly: true,
|
|
33
33
|
mutating: false,
|
|
@@ -40,7 +40,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
name: 'livedesk.get_system_health',
|
|
43
|
-
description: 'Read system health from the selected
|
|
43
|
+
description: 'Read system health from the selected Clients.',
|
|
44
44
|
category: 'read',
|
|
45
45
|
readOnly: true,
|
|
46
46
|
mutating: false,
|
|
@@ -53,7 +53,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
name: 'livedesk.get_gpu_status',
|
|
56
|
-
description: 'Read GPU status from the selected
|
|
56
|
+
description: 'Read GPU status from the selected Clients.',
|
|
57
57
|
category: 'read',
|
|
58
58
|
readOnly: true,
|
|
59
59
|
mutating: false,
|
|
@@ -66,7 +66,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
name: 'livedesk.get_disk_status',
|
|
69
|
-
description: 'Read disk status from the selected
|
|
69
|
+
description: 'Read disk status from the selected Clients.',
|
|
70
70
|
category: 'read',
|
|
71
71
|
readOnly: true,
|
|
72
72
|
mutating: false,
|
|
@@ -79,7 +79,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
name: 'livedesk.list_processes',
|
|
82
|
-
description: 'Read process status from the selected
|
|
82
|
+
description: 'Read process status from the selected Clients. Use processName for a named process such as ComfyUI.',
|
|
83
83
|
category: 'read',
|
|
84
84
|
readOnly: true,
|
|
85
85
|
mutating: false,
|
|
@@ -92,7 +92,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
name: 'livedesk.get_service_status',
|
|
95
|
-
description: 'Read service status from the selected
|
|
95
|
+
description: 'Read service status from the selected Clients. Use serviceName when the user names a service.',
|
|
96
96
|
category: 'read',
|
|
97
97
|
readOnly: true,
|
|
98
98
|
mutating: false,
|
|
@@ -105,7 +105,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
105
105
|
},
|
|
106
106
|
{
|
|
107
107
|
name: 'livedesk.collect_diagnostics',
|
|
108
|
-
description: 'Collect the existing safe LiveDesk diagnostics payload from the selected
|
|
108
|
+
description: 'Collect the existing safe LiveDesk diagnostics payload from the selected Clients.',
|
|
109
109
|
category: 'read',
|
|
110
110
|
readOnly: true,
|
|
111
111
|
mutating: false,
|
|
@@ -118,7 +118,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
120
|
name: 'livedesk.control_process',
|
|
121
|
-
description: 'Stop or restart a named process on the selected
|
|
121
|
+
description: 'Stop or restart a named process on the selected Clients. This changes process state.',
|
|
122
122
|
category: 'processControl',
|
|
123
123
|
readOnly: false,
|
|
124
124
|
mutating: true,
|
|
@@ -131,7 +131,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
name: 'livedesk.control_service',
|
|
134
|
-
description: 'Start, stop, or restart a named service on the selected
|
|
134
|
+
description: 'Start, stop, or restart a named service on the selected Clients.',
|
|
135
135
|
category: 'serviceControl',
|
|
136
136
|
readOnly: false,
|
|
137
137
|
mutating: true,
|
|
@@ -157,7 +157,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
157
157
|
},
|
|
158
158
|
{
|
|
159
159
|
name: 'livedesk.close_application',
|
|
160
|
-
description: 'Close a named application process on the selected
|
|
160
|
+
description: 'Close a named application process on the selected Clients.',
|
|
161
161
|
category: 'applicationControl',
|
|
162
162
|
readOnly: false,
|
|
163
163
|
mutating: true,
|
|
@@ -170,7 +170,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
170
170
|
},
|
|
171
171
|
{
|
|
172
172
|
name: 'livedesk.read_file',
|
|
173
|
-
description: 'Read a bounded UTF-8 text file from the selected
|
|
173
|
+
description: 'Read a bounded UTF-8 text file from the selected Clients, with sensitive credential paths rejected.',
|
|
174
174
|
category: 'fileRead',
|
|
175
175
|
readOnly: true,
|
|
176
176
|
mutating: false,
|
|
@@ -183,7 +183,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
183
183
|
},
|
|
184
184
|
{
|
|
185
185
|
name: 'livedesk.write_file',
|
|
186
|
-
description: 'Write bounded text content to a file on the selected
|
|
186
|
+
description: 'Write bounded text content to a file on the selected Clients.',
|
|
187
187
|
category: 'fileWrite',
|
|
188
188
|
readOnly: false,
|
|
189
189
|
mutating: true,
|
|
@@ -196,7 +196,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
196
196
|
},
|
|
197
197
|
{
|
|
198
198
|
name: 'livedesk.delete_file',
|
|
199
|
-
description: 'Delete a selected file or explicitly requested directory on the selected
|
|
199
|
+
description: 'Delete a selected file or explicitly requested directory on the selected Clients.',
|
|
200
200
|
category: 'fileDelete',
|
|
201
201
|
readOnly: false,
|
|
202
202
|
mutating: true,
|
|
@@ -209,7 +209,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
209
209
|
},
|
|
210
210
|
{
|
|
211
211
|
name: 'livedesk.list_directory',
|
|
212
|
-
description: 'List bounded file metadata from a directory on the selected
|
|
212
|
+
description: 'List bounded file metadata from a directory on the selected Clients.',
|
|
213
213
|
category: 'fileRead',
|
|
214
214
|
readOnly: true,
|
|
215
215
|
mutating: false,
|
|
@@ -222,7 +222,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
222
222
|
},
|
|
223
223
|
{
|
|
224
224
|
name: 'livedesk.run_command',
|
|
225
|
-
description: 'Run a bounded command through the selected
|
|
225
|
+
description: 'Run a bounded command through the selected Client command interpreter. This is an audited high-risk action.',
|
|
226
226
|
category: 'shell',
|
|
227
227
|
readOnly: false,
|
|
228
228
|
mutating: true,
|
|
@@ -235,7 +235,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
235
235
|
},
|
|
236
236
|
{
|
|
237
237
|
name: 'livedesk.run_script',
|
|
238
|
-
description: 'Run a bounded script file using the
|
|
238
|
+
description: 'Run a bounded script file using the Client platform interpreter.',
|
|
239
239
|
category: 'script',
|
|
240
240
|
readOnly: false,
|
|
241
241
|
mutating: true,
|
|
@@ -261,7 +261,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
261
261
|
},
|
|
262
262
|
{
|
|
263
263
|
name: 'livedesk.get_network_status',
|
|
264
|
-
description: 'Read bounded network adapter and connectivity status from the selected
|
|
264
|
+
description: 'Read bounded network adapter and connectivity status from the selected Clients.',
|
|
265
265
|
category: 'network',
|
|
266
266
|
readOnly: true,
|
|
267
267
|
mutating: false,
|
|
@@ -274,7 +274,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
274
274
|
},
|
|
275
275
|
{
|
|
276
276
|
name: 'livedesk.power_action',
|
|
277
|
-
description: 'Request an explicit power action on the selected
|
|
277
|
+
description: 'Request an explicit power action on the selected Clients.',
|
|
278
278
|
category: 'systemPower',
|
|
279
279
|
readOnly: false,
|
|
280
280
|
mutating: true,
|
|
@@ -287,7 +287,7 @@ export const AGENT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
287
287
|
},
|
|
288
288
|
{
|
|
289
289
|
name: 'livedesk.system_configuration',
|
|
290
|
-
description: 'Apply one explicitly named system configuration action supported by the
|
|
290
|
+
description: 'Apply one explicitly named system configuration action supported by the Client agent.',
|
|
291
291
|
category: 'systemConfiguration',
|
|
292
292
|
readOnly: false,
|
|
293
293
|
mutating: true,
|
|
@@ -472,7 +472,7 @@ export function createCodexAgentRuntime({
|
|
|
472
472
|
'Never use arbitrary MCP servers, change permissions, forge approvals, request credentials, or invent a tool result.',
|
|
473
473
|
`The Hub has fixed this run to permission mode ${permissionPolicy?.mode || 'ask'} and enforces the policy independently of your instructions.`,
|
|
474
474
|
'Use only the selected connected device IDs below. If the Hub asks for user approval, wait for that approval result and do not work around it.',
|
|
475
|
-
'You may perform multiple safe read-only checks when the request requires a sequence. For example, find
|
|
475
|
+
'You may perform multiple safe read-only checks when the request requires a sequence. For example, find Clients without ComfyUI, then check the service status only on those Clients.',
|
|
476
476
|
`Selected device IDs: ${JSON.stringify(deviceIds)}`,
|
|
477
477
|
'Return a concise Korean or English summary grounded only in tool results. Do not invent results.',
|
|
478
478
|
`User request: ${safeText(instruction, 4000)}`
|
|
@@ -505,7 +505,7 @@ export function createCodexAgentRuntime({
|
|
|
505
505
|
const status = await getStatus();
|
|
506
506
|
if (!status.installed) throw new AgentProviderError('codex-sdk-not-installed', 'Codex SDK is not installed.', { status: 503 });
|
|
507
507
|
if (status.authenticated !== 'signed-in') throw new AgentProviderError('codex-auth-required', 'Sign in with the Codex CLI first.', { status: 401 });
|
|
508
|
-
reportProgress(run, 'preparing-tools', 'Codex is ready. Preparing the LiveDesk tools for this
|
|
508
|
+
reportProgress(run, 'preparing-tools', 'Codex is ready. Preparing the LiveDesk tools for this Client.');
|
|
509
509
|
session = createMcpSession({
|
|
510
510
|
runId: run.runId,
|
|
511
511
|
signal: run.abortController.signal,
|
|
@@ -139,7 +139,7 @@ export class HubSharedFolders {
|
|
|
139
139
|
}
|
|
140
140
|
}));
|
|
141
141
|
}
|
|
142
|
-
folder.message = jobs.length > 0 ? `Syncing ${jobs.length}
|
|
142
|
+
folder.message = jobs.length > 0 ? `Syncing ${jobs.length} Client${jobs.length === 1 ? '' : 's'}` : 'No changed files';
|
|
143
143
|
await this.persist();
|
|
144
144
|
return { ok: true, jobs, files: scan.files.length, totalBytes: scan.totalBytes };
|
|
145
145
|
} finally {
|
|
@@ -20,6 +20,8 @@ export function planMode4AtlasInputTransitions(previous = {}, next = {}) {
|
|
|
20
20
|
const captureSizeChanged = previousIds.size > 0
|
|
21
21
|
&& (Number(previous.tileWidth || 0) !== Number(next.tileWidth || 0)
|
|
22
22
|
|| Number(previous.tileHeight || 0) !== Number(next.tileHeight || 0));
|
|
23
|
+
const captureFpsChanged = previousIds.size > 0
|
|
24
|
+
&& Number(previous.inputFps || 0) !== Number(next.inputFps || 0);
|
|
23
25
|
const stop = [...previousIds].filter(deviceId => !nextIds.has(deviceId));
|
|
24
26
|
const start = [];
|
|
25
27
|
const restart = [];
|
|
@@ -32,7 +34,7 @@ export function planMode4AtlasInputTransitions(previous = {}, next = {}) {
|
|
|
32
34
|
}
|
|
33
35
|
const previousMonitorIndex = Number(previousMonitorSelections[deviceId] || 0);
|
|
34
36
|
const nextMonitorIndex = Number(nextMonitorSelections[deviceId] || 0);
|
|
35
|
-
if (captureSizeChanged || previousMonitorIndex !== nextMonitorIndex) {
|
|
37
|
+
if (captureSizeChanged || captureFpsChanged || previousMonitorIndex !== nextMonitorIndex) {
|
|
36
38
|
restart.push(deviceId);
|
|
37
39
|
} else {
|
|
38
40
|
unchanged.push(deviceId);
|
package/hub/src/remote-hub.js
CHANGED
|
@@ -2330,7 +2330,7 @@ export function createRemoteHub(options = {}) {
|
|
|
2330
2330
|
const replace = options.replace !== false;
|
|
2331
2331
|
const now = new Date();
|
|
2332
2332
|
const platforms = ['win32', 'linux', 'darwin'];
|
|
2333
|
-
const machineKinds = ['Mac mini', 'Mini PC', '
|
|
2333
|
+
const machineKinds = ['Mac mini', 'Mini PC', 'Client', 'Render node', 'Dev box'];
|
|
2334
2334
|
const workloadRoles = ['LLM worker', 'Image worker', 'Video worker', 'Idle reserve', 'Build worker'];
|
|
2335
2335
|
const gpuNames = ['Apple M-series GPU', 'NVIDIA RTX local', 'Radeon Pro', 'Intel Arc', 'Integrated GPU'];
|
|
2336
2336
|
const npuNames = ['Apple Neural Engine', 'Ryzen AI NPU', 'Intel AI Boost', 'Qualcomm Hexagon', 'NPU not present'];
|
package/hub/src/server.js
CHANGED
|
@@ -2306,6 +2306,7 @@ function configureMode4Atlas(ws, payload = {}) {
|
|
|
2306
2306
|
});
|
|
2307
2307
|
const tileWidth = tileSize.width;
|
|
2308
2308
|
const tileHeight = tileSize.height;
|
|
2309
|
+
const inputFps = clampNumber(payload.inputFps, 1, 30, 8);
|
|
2309
2310
|
const previousInputDeviceIds = ws.liveDeskAtlasInputDeviceIds instanceof Set
|
|
2310
2311
|
? new Set(ws.liveDeskAtlasInputDeviceIds)
|
|
2311
2312
|
: new Set();
|
|
@@ -2339,16 +2340,18 @@ function configureMode4Atlas(ws, payload = {}) {
|
|
|
2339
2340
|
}
|
|
2340
2341
|
ws.liveDeskAtlasDeviceIds = new Set(deviceIds);
|
|
2341
2342
|
ws.liveDeskAtlasInputDeviceIds = new Set(captureDeviceIds);
|
|
2342
|
-
ws.liveDeskAtlasInputOptions = { tileWidth, tileHeight, monitorSelections };
|
|
2343
|
+
ws.liveDeskAtlasInputOptions = { tileWidth, tileHeight, inputFps, monitorSelections };
|
|
2343
2344
|
const inputTransitions = planMode4AtlasInputTransitions({
|
|
2344
2345
|
inputDeviceIds: [...previousInputDeviceIds],
|
|
2345
2346
|
tileWidth: previousInputOptions.tileWidth,
|
|
2346
2347
|
tileHeight: previousInputOptions.tileHeight,
|
|
2348
|
+
inputFps: previousInputOptions.inputFps,
|
|
2347
2349
|
monitorSelections: previousInputOptions.monitorSelections
|
|
2348
2350
|
}, {
|
|
2349
2351
|
inputDeviceIds: captureDeviceIds,
|
|
2350
2352
|
tileWidth,
|
|
2351
2353
|
tileHeight,
|
|
2354
|
+
inputFps,
|
|
2352
2355
|
monitorSelections
|
|
2353
2356
|
});
|
|
2354
2357
|
for (const deviceId of inputTransitions.stop) {
|
|
@@ -2368,10 +2371,11 @@ function configureMode4Atlas(ws, payload = {}) {
|
|
|
2368
2371
|
deviceIds,
|
|
2369
2372
|
captureDeviceIds,
|
|
2370
2373
|
inputMode: 'mode2-lzo',
|
|
2371
|
-
outputMode: 'mode4-h264-atlas',
|
|
2372
|
-
tileWidth,
|
|
2373
|
-
tileHeight,
|
|
2374
|
-
|
|
2374
|
+
outputMode: 'mode4-h264-atlas',
|
|
2375
|
+
tileWidth,
|
|
2376
|
+
tileHeight,
|
|
2377
|
+
inputFps,
|
|
2378
|
+
timestamp: new Date().toISOString()
|
|
2375
2379
|
});
|
|
2376
2380
|
}
|
|
2377
2381
|
|
|
@@ -2379,7 +2383,7 @@ function startMode4AtlasInput(ws, deviceId, reason = 'atlas-configure', { forceR
|
|
|
2379
2383
|
const options = ws?.liveDeskAtlasInputOptions;
|
|
2380
2384
|
if (!options || !ws.liveDeskAtlasInputDeviceIds?.has(deviceId)) return { ok: false, error: 'atlas-device-not-configured' };
|
|
2381
2385
|
return remoteHub.startLiveStream(deviceId, {
|
|
2382
|
-
fps:
|
|
2386
|
+
fps: options.inputFps,
|
|
2383
2387
|
maxWidth: options.tileWidth,
|
|
2384
2388
|
maxHeight: options.tileHeight,
|
|
2385
2389
|
quality: 60,
|
|
@@ -2803,7 +2807,7 @@ app.post('/api/settings/agent/run', async (req, res) => {
|
|
|
2803
2807
|
const deviceIds = normalizeDeviceIds(req.body?.deviceIds).slice(0, 500);
|
|
2804
2808
|
const connectedDeviceIds = new Set(connectedAgentDeviceIds());
|
|
2805
2809
|
if (deviceIds.length === 0 || deviceIds.some(deviceId => !connectedDeviceIds.has(deviceId))) {
|
|
2806
|
-
throw new AgentProviderError('agent-target-not-connected', 'Every selected
|
|
2810
|
+
throw new AgentProviderError('agent-target-not-connected', 'Every selected Client must have an active Agent control channel.', { status: 409 });
|
|
2807
2811
|
}
|
|
2808
2812
|
const permissionMode = String(req.body?.permissionMode || 'ask').trim().toLowerCase();
|
|
2809
2813
|
if (!AGENT_PERMISSION_MODES.includes(permissionMode)) {
|
|
@@ -3863,8 +3867,8 @@ app.post('/api/remote/devices/:deviceId/quick-actions', requireHubFeatureAccess,
|
|
|
3863
3867
|
|
|
3864
3868
|
const label = action === 'shutdown' ? 'Shut down' : `${action.slice(0, 1).toUpperCase()}${action.slice(1)}`;
|
|
3865
3869
|
const result = remoteHub.requestAgentTask(req.params.deviceId, {
|
|
3866
|
-
instruction: `${label} this
|
|
3867
|
-
title: `${label}
|
|
3870
|
+
instruction: `${label} this Client. This action was explicitly requested and confirmed from the LiveDesk Hub action panel.`,
|
|
3871
|
+
title: `${label} Client`,
|
|
3868
3872
|
operation: 'system.power',
|
|
3869
3873
|
approvalLevel: 'task-only',
|
|
3870
3874
|
toolArguments: { action, delaySec: 0 },
|