@livedesk/hub 0.1.36 → 0.1.38
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 +32 -32
- package/src/agents/agent-audit-store.js +6 -16
- package/src/agents/agent-permissions.js +27 -33
- package/src/agents/agent-tool-registry.js +322 -340
- package/src/captures/capture-store.js +252 -299
- package/src/filesystem/shared-folders.js +181 -189
- package/src/filesystem/transfer-jobs.js +314 -345
- package/src/live-desk-update.js +615 -683
- package/src/remote-hub.js +85 -654
- package/src/server.js +154 -965
- package/src/settings/settings-schema.js +40 -32
- package/src/settings/settings-store.js +2 -7
- package/src/transport/relay-hub-control.js +1376 -1703
- package/src/transport/udp-hub-transport.js +520 -543
- package/src/transport/udp-rendezvous.js +408 -574
- package/src/security/device-credential-authority.js +0 -406
- package/src/security/security-audit-store.js +0 -260
- package/src/transport/secure-direct-acceptor.js +0 -543
package/package.json
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@livedesk/hub",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "LiveDesk local Hub API and browser frame bridge",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "src/server.js",
|
|
7
|
-
"files": [
|
|
8
|
-
"src/",
|
|
9
|
-
"README.md"
|
|
10
|
-
],
|
|
11
|
-
"scripts": {
|
|
12
|
-
"dev": "node src/server.js",
|
|
13
|
-
"start": "node src/server.js",
|
|
14
|
-
"check": "node --check src/server.js && node --check src/remote-hub.js",
|
|
15
|
-
"prepublishOnly": "node ../../scripts/livedesk-release-git-gate.mjs"
|
|
16
|
-
},
|
|
17
|
-
"dependencies": {
|
|
18
|
-
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
19
|
-
"@livedesk/runtime-core": "0.1.
|
|
20
|
-
"@openai/codex-sdk": "0.145.0",
|
|
21
|
-
"cors": "^2.8.5",
|
|
22
|
-
"express": "^4.21.2",
|
|
23
|
-
"path-to-regexp": "0.1.13",
|
|
24
|
-
"ws": "^8.18.3"
|
|
25
|
-
},
|
|
26
|
-
"engines": {
|
|
27
|
-
"node": ">=20"
|
|
28
|
-
},
|
|
29
|
-
"publishConfig": {
|
|
30
|
-
"access": "public"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@livedesk/hub",
|
|
3
|
+
"version": "0.1.38",
|
|
4
|
+
"description": "LiveDesk local Hub API and browser frame bridge",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/server.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"src/",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"dev": "node src/server.js",
|
|
13
|
+
"start": "node src/server.js",
|
|
14
|
+
"check": "node --check src/server.js && node --check src/remote-hub.js",
|
|
15
|
+
"prepublishOnly": "node ../../scripts/livedesk-release-git-gate.mjs"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
19
|
+
"@livedesk/runtime-core": "0.1.5",
|
|
20
|
+
"@openai/codex-sdk": "0.145.0",
|
|
21
|
+
"cors": "^2.8.5",
|
|
22
|
+
"express": "^4.21.2",
|
|
23
|
+
"path-to-regexp": "0.1.13",
|
|
24
|
+
"ws": "^8.18.3"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { appendFile, mkdir, readFile, rename,
|
|
1
|
+
import { appendFile, mkdir, readFile, rename, writeFile } from 'node:fs/promises';
|
|
2
2
|
import crypto from 'node:crypto';
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
@@ -84,20 +84,10 @@ export function createAgentAuditStore({ dataDir = path.join(os.homedir(), '.live
|
|
|
84
84
|
await writeQueue;
|
|
85
85
|
return record;
|
|
86
86
|
},
|
|
87
|
-
async list({ runId = '', limit = 200 } = {}) {
|
|
87
|
+
async list({ runId = '', limit = 200 } = {}) {
|
|
88
88
|
const current = await load();
|
|
89
89
|
const normalizedLimit = Math.max(1, Math.min(500, Number(limit) || 200));
|
|
90
|
-
return current.filter(item => !runId || item.runId === String(runId)).slice(-normalizedLimit).reverse();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
await rm(filePath, { force: true });
|
|
95
|
-
records = [];
|
|
96
|
-
fileRecordCount = 0;
|
|
97
|
-
rewriteNeeded = false;
|
|
98
|
-
});
|
|
99
|
-
await writeQueue;
|
|
100
|
-
return { ok: true };
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
}
|
|
90
|
+
return current.filter(item => !runId || item.runId === String(runId)).slice(-normalizedLimit).reverse();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -42,19 +42,19 @@ const PRESET_CATEGORIES = Object.freeze({
|
|
|
42
42
|
...DEFAULT_CUSTOM_CATEGORIES,
|
|
43
43
|
userAccount: 'ask'
|
|
44
44
|
},
|
|
45
|
-
'safe-auto': {
|
|
46
|
-
read: 'allow',
|
|
47
|
-
processControl: 'allow',
|
|
48
|
-
serviceControl: 'allow',
|
|
49
|
-
// launch_application accepts an executable path, so allowing it would
|
|
50
|
-
// provide a shell-equivalent escape hatch (for example powershell.exe).
|
|
51
|
-
applicationControl: 'ask',
|
|
52
|
-
fileRead: 'allow',
|
|
53
|
-
fileWrite: 'allow',
|
|
54
|
-
fileDelete: 'ask',
|
|
55
|
-
shell: 'ask',
|
|
56
|
-
// A writable script directory must never become an auto-execution path.
|
|
57
|
-
script: 'ask',
|
|
45
|
+
'safe-auto': {
|
|
46
|
+
read: 'allow',
|
|
47
|
+
processControl: 'allow',
|
|
48
|
+
serviceControl: 'allow',
|
|
49
|
+
// launch_application accepts an executable path, so allowing it would
|
|
50
|
+
// provide a shell-equivalent escape hatch (for example powershell.exe).
|
|
51
|
+
applicationControl: 'ask',
|
|
52
|
+
fileRead: 'allow',
|
|
53
|
+
fileWrite: 'allow',
|
|
54
|
+
fileDelete: 'ask',
|
|
55
|
+
shell: 'ask',
|
|
56
|
+
// A writable script directory must never become an auto-execution path.
|
|
57
|
+
script: 'ask',
|
|
58
58
|
softwareInstall: 'ask',
|
|
59
59
|
network: 'allow',
|
|
60
60
|
systemPower: 'ask',
|
|
@@ -161,17 +161,17 @@ function isSafeAutoRelativePath(value) {
|
|
|
161
161
|
return segments.length > 0 && !segments.includes('..');
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
function safeAutoConstraint(tool, args, mode) {
|
|
165
|
-
if (mode !== 'safe-auto') return '';
|
|
166
|
-
if (tool.category === 'fileWrite' && !isSafeAutoRelativePath(args?.path)) {
|
|
167
|
-
return 'Safe Auto file writes are limited to relative paths inside the LiveDesk files directory.';
|
|
168
|
-
}
|
|
169
|
-
if (tool.category === 'fileWrite') {
|
|
170
|
-
const filePath = String(args?.path || '').trim().replaceAll('\\', '/').toLowerCase();
|
|
171
|
-
if (filePath === 'scripts' || filePath.startsWith('scripts/')) {
|
|
172
|
-
return 'Safe Auto cannot write files inside the script directory.';
|
|
173
|
-
}
|
|
174
|
-
}
|
|
164
|
+
function safeAutoConstraint(tool, args, mode) {
|
|
165
|
+
if (mode !== 'safe-auto') return '';
|
|
166
|
+
if (tool.category === 'fileWrite' && !isSafeAutoRelativePath(args?.path)) {
|
|
167
|
+
return 'Safe Auto file writes are limited to relative paths inside the LiveDesk files directory.';
|
|
168
|
+
}
|
|
169
|
+
if (tool.category === 'fileWrite') {
|
|
170
|
+
const filePath = String(args?.path || '').trim().replaceAll('\\', '/').toLowerCase();
|
|
171
|
+
if (filePath === 'scripts' || filePath.startsWith('scripts/')) {
|
|
172
|
+
return 'Safe Auto cannot write files inside the script directory.';
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
175
|
if (tool.category === 'script') {
|
|
176
176
|
const scriptPath = String(args?.path || '').trim().toLowerCase();
|
|
177
177
|
if (!isSafeAutoRelativePath(scriptPath) || !scriptPath.replaceAll('\\', '/').startsWith('scripts/') || !/\.(ps1|psm1|sh|bash|py|js|mjs|cmd|bat)$/.test(scriptPath)) {
|
|
@@ -181,15 +181,9 @@ function safeAutoConstraint(tool, args, mode) {
|
|
|
181
181
|
return '';
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
export function evaluateAgentToolPermission({ policy, toolName, arguments: args = {}, deviceIds = [] } = {}) {
|
|
185
|
-
const tool = getAgentToolDefinition(toolName);
|
|
186
|
-
if (!tool) return { decision: 'deny', category: 'unknown', risk: 'critical', reason: 'Unknown or unregistered Agent tool.' };
|
|
187
|
-
// This is deliberately redundant with the filtered MCP registry. A future
|
|
188
|
-
// registry edit must not make an AI mutation executable merely by exposing
|
|
189
|
-
// a definition again.
|
|
190
|
-
if (tool.mutating === true || tool.readOnly !== true) {
|
|
191
|
-
return { decision: 'deny', category: tool.category, risk: 'critical', reason: 'AI mutating tools are disabled in the first public product.' };
|
|
192
|
-
}
|
|
184
|
+
export function evaluateAgentToolPermission({ policy, toolName, arguments: args = {}, deviceIds = [] } = {}) {
|
|
185
|
+
const tool = getAgentToolDefinition(toolName);
|
|
186
|
+
if (!tool) return { decision: 'deny', category: 'unknown', risk: 'critical', reason: 'Unknown or unregistered Agent tool.' };
|
|
193
187
|
const allowed = new Set(normalizeIds(policy?.deviceIds));
|
|
194
188
|
const requested = targetIdsFromArgs(args, deviceIds);
|
|
195
189
|
if (requested.some(deviceId => !allowed.has(deviceId))) {
|