livedesk 0.1.629 → 0.1.631

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.
Files changed (39) hide show
  1. package/client/package.json +2 -2
  2. package/electron/before-pack.cjs +129 -0
  3. package/electron/electron-builder.linux-x64.yml +4 -2
  4. package/electron/electron-builder.mac-arm64.yml +4 -2
  5. package/electron/electron-builder.mac-x64.yml +4 -2
  6. package/electron/electron-builder.win.yml +4 -2
  7. package/electron/electron-builder.yml +4 -3
  8. package/hub/package.json +4 -3
  9. package/hub/src/console-direct.js +1538 -0
  10. package/hub/src/console-direct.test.mjs +984 -0
  11. package/hub/src/server.js +30 -26
  12. package/package.json +3 -2
  13. package/runtime-core/package.json +2 -2
  14. package/runtime-core/src/console-direct-wire.d.ts +84 -0
  15. package/runtime-core/src/console-direct-wire.js +351 -0
  16. package/runtime-core/src/console-direct-wire.test.mjs +252 -0
  17. package/runtime-core/src/index.js +8 -0
  18. package/scripts/sync-web-dist.js +3 -1
  19. package/web/dist/app.html +3 -3
  20. package/web/dist/app.webmanifest +1 -1
  21. package/web/dist/assets/{AgentSettingsTab-Fm0pWAO5.js → AgentSettingsTab-VwiC7JUN.js} +1 -1
  22. package/web/dist/assets/{AgentsPage-CV9d70zz.js → AgentsPage-DhvGz3nK.js} +1 -1
  23. package/web/dist/assets/{App-jdfxW7Jf.js → App-B6lW0dqi.js} +16 -16
  24. package/web/dist/assets/{CaptureGallery-CCBV6Ry2.js → CaptureGallery-aelE6Zdk.js} +1 -1
  25. package/web/dist/assets/{DesktopUpdatePanel-CrprrEpT.js → DesktopUpdatePanel-_K61p838.js} +1 -1
  26. package/web/dist/assets/{LiveDeskApp-B4-OE2Pc.js → LiveDeskApp-DtvEkJkj.js} +1 -1
  27. package/web/dist/assets/{SettingsPage-Bt1AMVk2.js → SettingsPage-pt2aO7OB.js} +1 -1
  28. package/web/dist/assets/{SettingsTabs-ByTAC0pY.js → SettingsTabs-Crjk_9s3.js} +1 -1
  29. package/web/dist/assets/{ShareFilesPage-B4h4r-vi.js → ShareFilesPage-DHSxFlMx.js} +1 -1
  30. package/web/dist/assets/{SupportPage-CZAgCvAU.js → SupportPage-D4TV6Vpp.js} +1 -1
  31. package/web/dist/assets/app-Dz24Poiu.js +1 -0
  32. package/web/dist/assets/{main-CW1wp0ox.js → main-DvaMzUeB.js} +2 -2
  33. package/web/dist/assets/styles-BQJexgrQ.js +12 -0
  34. package/web/dist/index.html +2 -2
  35. package/web/dist/livedesk-build-evidence.json +42 -42
  36. package/web/dist/sw.js +1 -1
  37. package/hub/src/console-relay.js +0 -465
  38. package/web/dist/assets/app-B1GIt_Z3.js +0 -1
  39. package/web/dist/assets/styles-pFD5jrt-.js +0 -13
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/client",
3
- "version": "0.1.266",
3
+ "version": "0.1.267",
4
4
  "description": "VuvoDesk local remote client",
5
5
  "type": "module",
6
6
  "bin": {
@@ -36,7 +36,7 @@
36
36
  "dependencies": {
37
37
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
38
38
  "ffmpeg-static": "^5.3.0",
39
- "@livedesk/runtime-core": "0.1.7",
39
+ "@livedesk/runtime-core": "0.1.8",
40
40
  "@supabase/supabase-js": "^2.110.0",
41
41
  "node-screenshots": "^0.2.8",
42
42
  "ws": "^8.18.3"
@@ -0,0 +1,129 @@
1
+ const { createHash } = require('node:crypto');
2
+ const { existsSync, readFileSync, readdirSync, statSync } = require('node:fs');
3
+ const { isAbsolute, join, posix, relative, resolve, sep } = require('node:path');
4
+
5
+ const EVIDENCE_FILE = 'livedesk-build-evidence.json';
6
+ const EVIDENCE_KIND = 'livedesk-production-web-source-evidence';
7
+
8
+ function fail(code, detail = '') {
9
+ throw new Error(`packaged-web-invalid:${code}${detail ? `:${detail}` : ''}`);
10
+ }
11
+
12
+ function readJson(filePath, label) {
13
+ try {
14
+ return JSON.parse(readFileSync(filePath, 'utf8'));
15
+ } catch (error) {
16
+ fail(`${label}-invalid`, error instanceof Error ? error.message : String(error));
17
+ }
18
+ }
19
+
20
+ function validateManifestPath(value) {
21
+ const manifestPath = String(value || '');
22
+ if (!manifestPath
23
+ || manifestPath.includes('\\')
24
+ || isAbsolute(manifestPath)
25
+ || posix.isAbsolute(manifestPath)
26
+ || posix.normalize(manifestPath) !== manifestPath
27
+ || manifestPath.split('/').some(segment => !segment || segment === '.' || segment === '..')) {
28
+ fail('manifest-path-unsafe', manifestPath || '(empty)');
29
+ }
30
+ return manifestPath;
31
+ }
32
+
33
+ function collectOutputFiles(directory, webRoot, output = []) {
34
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
35
+ const fullPath = join(directory, entry.name);
36
+ if (entry.isDirectory()) {
37
+ collectOutputFiles(fullPath, webRoot, output);
38
+ continue;
39
+ }
40
+ if (!entry.isFile()) fail('output-entry-not-file', relative(webRoot, fullPath));
41
+ const outputPath = relative(webRoot, fullPath).replaceAll('\\', '/');
42
+ if (outputPath !== EVIDENCE_FILE && !outputPath.endsWith('.tmp')) output.push(outputPath);
43
+ }
44
+ return output.sort((left, right) => left.localeCompare(right));
45
+ }
46
+
47
+ function validatePackagedWebOutput(webDirectory, expectedVersion) {
48
+ const webRoot = resolve(String(webDirectory || ''));
49
+ if (!webDirectory || !existsSync(webRoot)) fail('web-root-missing', webRoot);
50
+ const indexPath = join(webRoot, 'index.html');
51
+ const evidencePath = join(webRoot, EVIDENCE_FILE);
52
+ if (!existsSync(indexPath)) fail('index-missing', indexPath);
53
+ if (!existsSync(evidencePath)) fail('evidence-missing', evidencePath);
54
+
55
+ const evidence = readJson(evidencePath, 'evidence');
56
+ if (evidence?.schemaVersion !== 2) fail('evidence-schema', String(evidence?.schemaVersion));
57
+ if (evidence?.kind !== EVIDENCE_KIND) fail('evidence-kind', String(evidence?.kind));
58
+ if (!expectedVersion || evidence?.pwaRelease !== expectedVersion) {
59
+ fail('version-mismatch', `package=${expectedVersion || '(missing)'},web=${evidence?.pwaRelease || '(missing)'}`);
60
+ }
61
+ if (!Array.isArray(evidence.outputManifest) || evidence.outputManifest.length === 0) {
62
+ fail('manifest-empty');
63
+ }
64
+
65
+ const actualPaths = collectOutputFiles(webRoot, webRoot);
66
+ const recordedPaths = [];
67
+ const seenPaths = new Set();
68
+ const aggregateHash = createHash('sha256');
69
+ let outputBytes = 0;
70
+
71
+ for (const item of evidence.outputManifest) {
72
+ const outputPath = validateManifestPath(item?.path);
73
+ if (seenPaths.has(outputPath)) fail('manifest-path-duplicate', outputPath);
74
+ seenPaths.add(outputPath);
75
+ recordedPaths.push(outputPath);
76
+ if (!Number.isSafeInteger(item?.bytes) || item.bytes < 0) fail('manifest-size-invalid', outputPath);
77
+ if (!/^[a-f0-9]{64}$/.test(String(item?.sha256 || ''))) fail('manifest-hash-invalid', outputPath);
78
+
79
+ const filePath = resolve(webRoot, ...outputPath.split('/'));
80
+ const withinRoot = filePath.startsWith(`${webRoot}${sep}`);
81
+ if (!withinRoot) fail('manifest-path-unsafe', outputPath);
82
+ if (!existsSync(filePath) || !statSync(filePath).isFile()) fail('output-missing', outputPath);
83
+ const contents = readFileSync(filePath);
84
+ if (contents.byteLength !== item.bytes) fail('output-size-mismatch', outputPath);
85
+ const sha256 = createHash('sha256').update(contents).digest('hex');
86
+ if (sha256 !== item.sha256) fail('output-hash-mismatch', outputPath);
87
+
88
+ outputBytes += contents.byteLength;
89
+ aggregateHash.update(outputPath);
90
+ aggregateHash.update('\0');
91
+ aggregateHash.update(String(contents.byteLength));
92
+ aggregateHash.update('\0');
93
+ aggregateHash.update(contents);
94
+ aggregateHash.update('\0');
95
+ }
96
+
97
+ if (!seenPaths.has('index.html')) fail('index-not-recorded');
98
+ if (JSON.stringify(recordedPaths) !== JSON.stringify(actualPaths)) fail('manifest-file-set-mismatch');
99
+ if (evidence.outputFileCount !== recordedPaths.length) fail('output-count-mismatch');
100
+ if (evidence.outputBytes !== outputBytes) fail('output-bytes-mismatch');
101
+ if (evidence.outputHash !== aggregateHash.digest('hex')) fail('output-aggregate-hash-mismatch');
102
+
103
+ return {
104
+ webRoot,
105
+ version: expectedVersion,
106
+ outputFileCount: recordedPaths.length,
107
+ outputBytes
108
+ };
109
+ }
110
+
111
+ function validatePackagedWeb(appDir) {
112
+ const packageRoot = resolve(String(appDir || ''));
113
+ if (!appDir || !existsSync(packageRoot)) fail('app-dir-missing', packageRoot);
114
+ const packageInfo = readJson(join(packageRoot, 'package.json'), 'package-json');
115
+ return {
116
+ appDir: packageRoot,
117
+ ...validatePackagedWebOutput(join(packageRoot, 'web', 'dist'), packageInfo?.version)
118
+ };
119
+ }
120
+
121
+ async function beforePack(context) {
122
+ const appDir = context?.packager?.info?.appDir;
123
+ const result = validatePackagedWeb(appDir);
124
+ console.log(`Verified packaged VuvoDesk web UI ${result.version}: ${result.outputFileCount} files, ${result.outputBytes} bytes.`);
125
+ }
126
+
127
+ module.exports = beforePack;
128
+ module.exports.validatePackagedWeb = validatePackagedWeb;
129
+ module.exports.validatePackagedWebOutput = validatePackagedWebOutput;
@@ -14,7 +14,7 @@ files:
14
14
  - "!client/fast/win-x64/**"
15
15
  - "!client/fast/osx-x64/**"
16
16
  - "!client/fast/osx-arm64/**"
17
- asarUnpack:
17
+ asarUnpack:
18
18
  - bin/**
19
19
  - bootstrap/**
20
20
  - client/**
@@ -23,7 +23,9 @@ asarUnpack:
23
23
  - electron/tray.*
24
24
  - hub/**
25
25
  - runtime-core/**
26
- - web/**
26
+ - web/**
27
+ - node_modules/node-datachannel/**
28
+ - node_modules/@node-datachannel/linux-x64-gnu/**
27
29
  linux:
28
30
  icon: packages/livedesk/electron/icon.png
29
31
  category: Utility
@@ -13,7 +13,7 @@ files:
13
13
  - "!client/fast/win-x64/**"
14
14
  - "!client/fast/linux-x64/**"
15
15
  - "!client/fast/osx-x64/**"
16
- asarUnpack:
16
+ asarUnpack:
17
17
  - bin/**
18
18
  - bootstrap/**
19
19
  - client/**
@@ -22,7 +22,9 @@ asarUnpack:
22
22
  - electron/tray.*
23
23
  - hub/**
24
24
  - runtime-core/**
25
- - web/**
25
+ - web/**
26
+ - node_modules/node-datachannel/**
27
+ - node_modules/@node-datachannel/darwin-arm64/**
26
28
  mac:
27
29
  icon: packages/livedesk/electron/icon.icns
28
30
  category: public.app-category.utilities
@@ -13,7 +13,7 @@ files:
13
13
  - "!client/fast/win-x64/**"
14
14
  - "!client/fast/linux-x64/**"
15
15
  - "!client/fast/osx-arm64/**"
16
- asarUnpack:
16
+ asarUnpack:
17
17
  - bin/**
18
18
  - bootstrap/**
19
19
  - client/**
@@ -22,7 +22,9 @@ asarUnpack:
22
22
  - electron/tray.*
23
23
  - hub/**
24
24
  - runtime-core/**
25
- - web/**
25
+ - web/**
26
+ - node_modules/node-datachannel/**
27
+ - node_modules/@node-datachannel/darwin-x64/**
26
28
  mac:
27
29
  icon: packages/livedesk/electron/icon.icns
28
30
  category: public.app-category.utilities
@@ -13,7 +13,7 @@ files:
13
13
  - "!client/fast/linux-x64/**"
14
14
  - "!client/fast/osx-x64/**"
15
15
  - "!client/fast/osx-arm64/**"
16
- asarUnpack:
16
+ asarUnpack:
17
17
  - bin/**
18
18
  - bootstrap/**
19
19
  - client/**
@@ -22,7 +22,9 @@ asarUnpack:
22
22
  - electron/tray.*
23
23
  - hub/**
24
24
  - runtime-core/**
25
- - web/**
25
+ - web/**
26
+ - node_modules/node-datachannel/**
27
+ - node_modules/@node-datachannel/win32-x64-msvc/**
26
28
  win:
27
29
  icon: packages/livedesk/electron/icon.ico
28
30
  target:
@@ -1,7 +1,8 @@
1
1
  appId: com.livedesk.desktop
2
2
  productName: VuvoDesk
3
3
  artifactName: VuvoDesk-${version}-${arch}.${ext}
4
- asar: true
5
- directories:
6
- app: packages/livedesk
4
+ asar: true
5
+ beforePack: packages/livedesk/electron/before-pack.cjs
6
+ directories:
7
+ app: packages/livedesk
7
8
  output: dist/desktop
package/hub/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/hub",
3
- "version": "0.1.56",
3
+ "version": "0.1.57",
4
4
  "description": "VuvoDesk local Hub API and browser frame bridge",
5
5
  "type": "module",
6
6
  "main": "src/server.js",
@@ -11,15 +11,16 @@
11
11
  "scripts": {
12
12
  "dev": "node src/server.js",
13
13
  "start": "node src/server.js",
14
- "check": "node --check src/server.js && node --check src/remote-hub.js && node --check src/remote-clipboard-contract.mjs && node --check src/console-relay.js",
14
+ "check": "node --check src/server.js && node --check src/remote-hub.js && node --check src/remote-clipboard-contract.mjs && node --check src/console-direct.js",
15
15
  "prepublishOnly": "node ../../scripts/livedesk-release-git-gate.mjs"
16
16
  },
17
17
  "dependencies": {
18
18
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
19
- "@livedesk/runtime-core": "0.1.7",
19
+ "@livedesk/runtime-core": "0.1.8",
20
20
  "@openai/codex-sdk": "0.145.0",
21
21
  "cors": "^2.8.5",
22
22
  "express": "^4.21.2",
23
+ "node-datachannel": "0.33.0",
23
24
  "path-to-regexp": "0.1.13",
24
25
  "ws": "^8.18.3"
25
26
  },