@mindexec/cli 0.2.442 → 0.2.444
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/lzo1x.js +110 -0
- package/mode4-atlas-worker.js +440 -0
- package/mode4-atlas.js +130 -0
- package/package.json +6 -1
- package/remote-hub.js +35 -4
- package/server.js +162 -2
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +12 -8
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-remote-codecs.js +75 -2
- package/wwwroot/_framework/{MindExecution.Core.nxjlewduna.dll → MindExecution.Core.4moacskf64.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.vrfi63yg9f.dll → MindExecution.Kernel.pa251cfsz4.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.1rcwhdxl0r.dll → MindExecution.Plugins.Admin.dxyuwmxv1s.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.rx0eieg51y.dll → MindExecution.Plugins.Business.7uj5erqhhn.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.zzczjzhvk1.dll → MindExecution.Plugins.Concept.108rmsxc96.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.bsorcntiwp.dll → MindExecution.Plugins.Directory.ccsy3g0fe5.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.i5j9t4f1jf.dll → MindExecution.Plugins.PlanMaster.1vjpuoe9ff.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.1mpn9satft.dll → MindExecution.Plugins.YouTube.q8ml98phj9.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.mpi1gzau9b.dll → MindExecution.Shared.2pywq19zjy.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.nxykcyxd02.dll → MindExecution.Web.qucbls1wfr.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +21 -21
- package/wwwroot/index.html +1 -1
- package/wwwroot/service-worker-assets.js +25 -25
- package/wwwroot/service-worker.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindexec/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.444",
|
|
4
4
|
"description": "MindExec local runtime and bridge CLI",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"type": "module",
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
"launch-bridge.cjs",
|
|
11
11
|
"server.js",
|
|
12
12
|
"remote-hub.js",
|
|
13
|
+
"lzo1x.js",
|
|
14
|
+
"mode4-atlas.js",
|
|
15
|
+
"mode4-atlas-worker.js",
|
|
13
16
|
"codex-runtime.js",
|
|
14
17
|
"codex-model-catalog.js",
|
|
15
18
|
"port-guard.cjs",
|
|
@@ -59,11 +62,13 @@
|
|
|
59
62
|
"node": ">=20"
|
|
60
63
|
},
|
|
61
64
|
"dependencies": {
|
|
65
|
+
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
62
66
|
"@mindexec/remote": "^0.1.17",
|
|
63
67
|
"@openai/codex-sdk": "^0.144.1",
|
|
64
68
|
"chokidar": "^3.6.0",
|
|
65
69
|
"cors": "^2.8.5",
|
|
66
70
|
"express": "^4.18.2",
|
|
71
|
+
"ffmpeg-static": "^5.3.0",
|
|
67
72
|
"multer": "^2.2.0",
|
|
68
73
|
"playwright-core": "^1.53.0",
|
|
69
74
|
"sharp": "^0.33.2",
|
package/remote-hub.js
CHANGED
|
@@ -60,6 +60,17 @@ const REMOTE_FRAME_MODE_PROFILES = Object.freeze({
|
|
|
60
60
|
modeVersion: 1,
|
|
61
61
|
implemented: true
|
|
62
62
|
}),
|
|
63
|
+
'mode2-lzo': Object.freeze({
|
|
64
|
+
mode: 'mode2-lzo',
|
|
65
|
+
label: 'Mode 2 RGB565 LZO Wall',
|
|
66
|
+
transport: 'ws-binary',
|
|
67
|
+
encoding: 'image-raw',
|
|
68
|
+
codec: 'rgb565',
|
|
69
|
+
compression: 'lzo1x',
|
|
70
|
+
profile: 'mode2-lzo-rgb565-v1',
|
|
71
|
+
modeVersion: 2,
|
|
72
|
+
implemented: true
|
|
73
|
+
}),
|
|
63
74
|
'mode3-h264-hw': Object.freeze({
|
|
64
75
|
mode: 'mode3-h264-hw',
|
|
65
76
|
label: 'Mode 3 H.264 Control',
|
|
@@ -103,6 +114,13 @@ const REMOTE_FRAME_MODE_ALIASES = new Map([
|
|
|
103
114
|
['remotequality', 'remote-quality'],
|
|
104
115
|
['remote_quality', 'remote-quality'],
|
|
105
116
|
['remote-quality', 'remote-quality'],
|
|
117
|
+
['2', 'mode2-lzo'],
|
|
118
|
+
['mode2', 'mode2-lzo'],
|
|
119
|
+
['mode-2', 'mode2-lzo'],
|
|
120
|
+
['mode2-lzo', 'mode2-lzo'],
|
|
121
|
+
['lzo', 'mode2-lzo'],
|
|
122
|
+
['lzo1x', 'mode2-lzo'],
|
|
123
|
+
['rgb565', 'mode2-lzo'],
|
|
106
124
|
['mode3-h264', 'mode3-h264-hw'],
|
|
107
125
|
['mode3-h264-hw', 'mode3-h264-hw'],
|
|
108
126
|
['h264', 'mode3-h264-hw'],
|
|
@@ -2449,6 +2467,12 @@ export function createRemoteHub(options = {}) {
|
|
|
2449
2467
|
fps: Number.isFinite(Number(message.fps)) ? Number(message.fps) : device.activeLiveStream.fps,
|
|
2450
2468
|
streamPurpose: safeString(message.streamPurpose, 32),
|
|
2451
2469
|
monitorIndex: Number.isFinite(Number(message.monitorIndex)) ? Number(message.monitorIndex) : 0,
|
|
2470
|
+
monitorCount: Number.isFinite(Number(message.monitorCount)) ? Number(message.monitorCount) : 0,
|
|
2471
|
+
pixelFormat: safeString(message.pixelFormat, 24),
|
|
2472
|
+
bytesPerPixel: Number.isFinite(Number(message.bytesPerPixel)) ? Number(message.bytesPerPixel) : 0,
|
|
2473
|
+
uncompressedByteLength: Number.isFinite(Number(message.uncompressedByteLength)) ? Number(message.uncompressedByteLength) : 0,
|
|
2474
|
+
sourceWidth: Number.isFinite(Number(message.sourceWidth)) ? Number(message.sourceWidth) : 0,
|
|
2475
|
+
sourceHeight: Number.isFinite(Number(message.sourceHeight)) ? Number(message.sourceHeight) : 0,
|
|
2452
2476
|
h264Format: safeString(message.h264Format, 24),
|
|
2453
2477
|
isKeyFrame: message.isKeyFrame === true,
|
|
2454
2478
|
chunkType: safeString(message.chunkType, 24),
|
|
@@ -3260,9 +3284,11 @@ export function createRemoteHub(options = {}) {
|
|
|
3260
3284
|
|
|
3261
3285
|
const now = new Date().toISOString();
|
|
3262
3286
|
const streamId = safeString(options.streamId, 128) || `live-${Date.now()}`;
|
|
3263
|
-
const
|
|
3287
|
+
const streamPurpose = safeString(options.streamPurpose, 32).toLowerCase();
|
|
3288
|
+
const requestedMode = options.mode || (streamPurpose === 'control' ? 'mode3-h264-hw' : 'mode2-lzo');
|
|
3289
|
+
const fps = clampNumber(options.fps, 1, 30, streamPurpose === 'control' ? 30 : 20);
|
|
3264
3290
|
const commandId = safeString(options.commandId, 128) || crypto.randomUUID();
|
|
3265
|
-
const transfer = buildRemoteFrameTransferDescriptor(
|
|
3291
|
+
const transfer = buildRemoteFrameTransferDescriptor(requestedMode, streamPurpose === 'control' ? 'mode3-h264-hw' : 'mode2-lzo');
|
|
3266
3292
|
device.counters.commandsSent += 1;
|
|
3267
3293
|
device.activeLiveStream = {
|
|
3268
3294
|
streamId,
|
|
@@ -3281,6 +3307,7 @@ export function createRemoteHub(options = {}) {
|
|
|
3281
3307
|
transferProtocolVersion: transfer.transferProtocolVersion,
|
|
3282
3308
|
handshake: transfer.handshake,
|
|
3283
3309
|
fps,
|
|
3310
|
+
streamPurpose,
|
|
3284
3311
|
startedAt: now,
|
|
3285
3312
|
stoppedAt: '',
|
|
3286
3313
|
stopReason: '',
|
|
@@ -3314,9 +3341,11 @@ export function createRemoteHub(options = {}) {
|
|
|
3314
3341
|
|
|
3315
3342
|
const now = new Date().toISOString();
|
|
3316
3343
|
const streamId = safeString(options.streamId, 128) || `live-${Date.now()}`;
|
|
3317
|
-
const
|
|
3344
|
+
const streamPurpose = safeString(options.streamPurpose, 32).toLowerCase();
|
|
3345
|
+
const requestedMode = options.mode || (streamPurpose === 'control' ? 'mode3-h264-hw' : 'mode2-lzo');
|
|
3346
|
+
const fps = clampNumber(options.fps, 1, 30, streamPurpose === 'control' ? 30 : 20);
|
|
3318
3347
|
const commandId = safeString(options.commandId, 128) || crypto.randomUUID();
|
|
3319
|
-
const transfer = buildRemoteFrameTransferDescriptor(
|
|
3348
|
+
const transfer = buildRemoteFrameTransferDescriptor(requestedMode, streamPurpose === 'control' ? 'mode3-h264-hw' : 'mode2-lzo');
|
|
3320
3349
|
const result = sendCommand(deviceId, {
|
|
3321
3350
|
command: 'stream.start',
|
|
3322
3351
|
commandId,
|
|
@@ -3331,6 +3360,7 @@ export function createRemoteHub(options = {}) {
|
|
|
3331
3360
|
transferProtocol: transfer.transferProtocol,
|
|
3332
3361
|
transferProtocolVersion: transfer.transferProtocolVersion,
|
|
3333
3362
|
handshake: transfer.handshake,
|
|
3363
|
+
streamPurpose,
|
|
3334
3364
|
fps,
|
|
3335
3365
|
maxWidth: clampNumber(options.maxWidth, 320, 2560, 960),
|
|
3336
3366
|
maxHeight: clampNumber(options.maxHeight, 180, 1440, 540),
|
|
@@ -3360,6 +3390,7 @@ export function createRemoteHub(options = {}) {
|
|
|
3360
3390
|
transferProtocolVersion: transfer.transferProtocolVersion,
|
|
3361
3391
|
handshake: transfer.handshake,
|
|
3362
3392
|
fps,
|
|
3393
|
+
streamPurpose,
|
|
3363
3394
|
startedAt: now,
|
|
3364
3395
|
stoppedAt: '',
|
|
3365
3396
|
stopReason: '',
|
package/server.js
CHANGED
|
@@ -24,6 +24,7 @@ import { fileURLToPath } from 'url';
|
|
|
24
24
|
import { createCodexRuntime } from './codex-runtime.js';
|
|
25
25
|
import { createCodexModelCatalog } from './codex-model-catalog.js';
|
|
26
26
|
import { createRemoteHub } from './remote-hub.js';
|
|
27
|
+
import { Mode4AtlasSession } from './mode4-atlas.js';
|
|
27
28
|
import portGuard from './port-guard.cjs';
|
|
28
29
|
|
|
29
30
|
const execAsync = promisify(exec);
|
|
@@ -2399,12 +2400,15 @@ app.get('/api/local-files/:id', async (req, res) => {
|
|
|
2399
2400
|
const httpServer = createServer(app);
|
|
2400
2401
|
const wss = new WebSocketServer({ noServer: true });
|
|
2401
2402
|
const remoteFrameWss = new WebSocketServer({ noServer: true });
|
|
2403
|
+
const remoteAtlasWss = new WebSocketServer({ noServer: true });
|
|
2402
2404
|
const remoteInputWss = new WebSocketServer({ noServer: true });
|
|
2403
2405
|
const wsClients = new Set();
|
|
2404
2406
|
const remoteFrameClients = new Set();
|
|
2407
|
+
const remoteAtlasClients = new Map();
|
|
2405
2408
|
const remoteInputClients = new Set();
|
|
2406
2409
|
const shellJobs = new Map();
|
|
2407
2410
|
let remoteFrameClientSeq = 0;
|
|
2411
|
+
let remoteAtlasClientSeq = 0;
|
|
2408
2412
|
let remoteInputClientSeq = 0;
|
|
2409
2413
|
const remoteFrameWsDiagnostics = {
|
|
2410
2414
|
opened: 0,
|
|
@@ -2480,6 +2484,14 @@ httpServer.on('upgrade', (req, socket, head) => {
|
|
|
2480
2484
|
return;
|
|
2481
2485
|
}
|
|
2482
2486
|
|
|
2487
|
+
if (parsed.pathname === '/api/remote/atlas/ws'
|
|
2488
|
+
&& (!bridgeAuthRequired || token === bridgeToken)) {
|
|
2489
|
+
remoteAtlasWss.handleUpgrade(req, socket, head, (ws) => {
|
|
2490
|
+
remoteAtlasWss.emit('connection', ws, req);
|
|
2491
|
+
});
|
|
2492
|
+
return;
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2483
2495
|
if (parsed.pathname === '/api/remote/input/ws'
|
|
2484
2496
|
&& (!bridgeAuthRequired || token === bridgeToken)) {
|
|
2485
2497
|
remoteInputWss.handleUpgrade(req, socket, head, (ws) => {
|
|
@@ -2581,8 +2593,9 @@ function clampRemoteFrameWsNumber(value, min, max, fallback) {
|
|
|
2581
2593
|
}
|
|
2582
2594
|
|
|
2583
2595
|
function normalizeRemoteFrameWsLiveOptions(payload = {}) {
|
|
2584
|
-
const mode = String(payload.frameMode || payload.mode || 'remote-fast').trim() || 'remote-fast';
|
|
2585
2596
|
const streamPurpose = String(payload.streamPurpose || '').trim().toLowerCase();
|
|
2597
|
+
const defaultMode = streamPurpose === 'control' ? 'mode3-h264-hw' : 'mode2-lzo';
|
|
2598
|
+
const mode = String(payload.frameMode || payload.mode || defaultMode).trim() || defaultMode;
|
|
2586
2599
|
const defaultFps = streamPurpose === 'control' || mode === 'mode3-h264-hw' ? 30 : REMOTE_FRAME_WS_DEFAULT_FPS;
|
|
2587
2600
|
return {
|
|
2588
2601
|
fps: clampRemoteFrameWsNumber(payload.fps, 1, 30, defaultFps),
|
|
@@ -2725,6 +2738,12 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
|
|
|
2725
2738
|
sameContentStreak: Number(frame.sameContentStreak || 0) || 0,
|
|
2726
2739
|
streamPurpose: frame.streamPurpose || '',
|
|
2727
2740
|
monitorIndex: Number.isFinite(Number(frame.monitorIndex)) ? Number(frame.monitorIndex) : 0,
|
|
2741
|
+
monitorCount: Number.isFinite(Number(frame.monitorCount)) ? Number(frame.monitorCount) : 0,
|
|
2742
|
+
pixelFormat: frame.pixelFormat || '',
|
|
2743
|
+
bytesPerPixel: Number.isFinite(Number(frame.bytesPerPixel)) ? Number(frame.bytesPerPixel) : 0,
|
|
2744
|
+
uncompressedByteLength: Number.isFinite(Number(frame.uncompressedByteLength)) ? Number(frame.uncompressedByteLength) : 0,
|
|
2745
|
+
sourceWidth: Number.isFinite(Number(frame.sourceWidth)) ? Number(frame.sourceWidth) : 0,
|
|
2746
|
+
sourceHeight: Number.isFinite(Number(frame.sourceHeight)) ? Number(frame.sourceHeight) : 0,
|
|
2728
2747
|
codec: frame.codec || '',
|
|
2729
2748
|
h264Format: frame.h264Format || '',
|
|
2730
2749
|
isKeyFrame: frame.isKeyFrame === true,
|
|
@@ -2733,6 +2752,15 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
|
|
|
2733
2752
|
durationUs: Number.isFinite(Number(frame.durationUs)) ? Number(frame.durationUs) : 0,
|
|
2734
2753
|
streamFrameSeq: Number.isFinite(Number(frame.streamFrameSeq)) ? Number(frame.streamFrameSeq) : 0,
|
|
2735
2754
|
commandId: frame.commandId || ''
|
|
2755
|
+
,layoutVersion: Number(frame.layoutVersion || 0) || 0
|
|
2756
|
+
,atlasComposeMs: Number(frame.atlasComposeMs || 0) || 0
|
|
2757
|
+
,atlasPoolStarved: Number(frame.atlasPoolStarved || 0) || 0
|
|
2758
|
+
,atlasReadyTiles: Number(frame.atlasReadyTiles || 0) || 0
|
|
2759
|
+
,atlasTileCount: Number(frame.atlasTileCount || 0) || 0
|
|
2760
|
+
,hardwareEncoder: frame.hardwareEncoder || ''
|
|
2761
|
+
,platformProfile: frame.platformProfile || ''
|
|
2762
|
+
,workerGeneration: Number(frame.workerGeneration || 0) || 0
|
|
2763
|
+
,encoderGeneration: Number(frame.encoderGeneration || 0) || 0
|
|
2736
2764
|
};
|
|
2737
2765
|
const metaBuffer = Buffer.from(JSON.stringify(metadata), 'utf8');
|
|
2738
2766
|
const header = Buffer.allocUnsafe(4);
|
|
@@ -2740,7 +2768,84 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
|
|
|
2740
2768
|
return Buffer.concat([header, metaBuffer, payload], header.length + metaBuffer.length + payload.length);
|
|
2741
2769
|
}
|
|
2742
2770
|
|
|
2771
|
+
function sendMode4AtlasFrame(ws, output) {
|
|
2772
|
+
if (!ws || ws.readyState !== 1 || !output?.payload?.length) return;
|
|
2773
|
+
const metadata = output.metadata || {};
|
|
2774
|
+
const frameSeq = Number(metadata.frameSeq || 0) || 0;
|
|
2775
|
+
const isKeyFrame = metadata.isKeyFrame === true;
|
|
2776
|
+
const workerGeneration = Math.max(1, Number(metadata.workerGeneration || 1) || 1);
|
|
2777
|
+
const encoderGeneration = Math.max(1, Number(metadata.encoderGeneration || 1) || 1);
|
|
2778
|
+
const streamId = `${ws.remoteAtlasStreamId}-w${workerGeneration}-e${encoderGeneration}`;
|
|
2779
|
+
const width = Number(metadata.width || 1920) || 1920;
|
|
2780
|
+
const height = Number(metadata.height || 1080) || 1080;
|
|
2781
|
+
const frameEvent = {
|
|
2782
|
+
kind: 'live',
|
|
2783
|
+
deviceId: '__mindexec_mode4_atlas__',
|
|
2784
|
+
mimeType: 'video/h264',
|
|
2785
|
+
byteLength: output.payload.length,
|
|
2786
|
+
payload: output.payload,
|
|
2787
|
+
frame: {
|
|
2788
|
+
deviceId: '__mindexec_mode4_atlas__', frameSeq,
|
|
2789
|
+
streamFrameSeq: Number(metadata.streamFrameSeq || frameSeq) || frameSeq,
|
|
2790
|
+
streamId, commandId: streamId, width, height,
|
|
2791
|
+
sourceWidth: width, sourceHeight: height,
|
|
2792
|
+
mimeType: 'video/h264', mode: 'mode4-h264-atlas', frameMode: 'mode4-h264-atlas',
|
|
2793
|
+
frameProfile: 'mode4-h264-atlas-v1', encoding: 'video-atlas', codec: 'h264',
|
|
2794
|
+
compression: 'video/h264', h264Format: 'annexb', isKeyFrame,
|
|
2795
|
+
chunkType: isKeyFrame ? 'key' : 'delta',
|
|
2796
|
+
timestampUs: Number(metadata.timestampUs || 0), durationUs: Number(metadata.durationUs || 0),
|
|
2797
|
+
fps: Number(metadata.fps || 20), capturedAt: new Date().toISOString(), receivedAt: new Date().toISOString(),
|
|
2798
|
+
hardwareEncoder: String(metadata.hardwareEncoder || ''), platformProfile: 'mode4-hub-atlas-worker',
|
|
2799
|
+
workerGeneration, encoderGeneration, layoutVersion: Number(metadata.layoutVersion || 0),
|
|
2800
|
+
atlasComposeMs: Number(metadata.composeMs || 0), atlasPoolStarved: Number(metadata.poolStarved || 0),
|
|
2801
|
+
atlasReadyTiles: Number(metadata.readyTileCount || 0), atlasTileCount: Number(metadata.tileCount || 0)
|
|
2802
|
+
}
|
|
2803
|
+
};
|
|
2804
|
+
const packet = buildRemoteFrameBinaryPacket(frameEvent);
|
|
2805
|
+
if (!packet || ws.bufferedAmount > 8 * 1024 * 1024) return;
|
|
2806
|
+
try { ws.send(packet, { binary: true }); } catch { /* client closed */ }
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2809
|
+
function normalizeRemoteAtlasMonitorSelections(value) {
|
|
2810
|
+
if (!value || typeof value !== 'object') return {};
|
|
2811
|
+
const result = {};
|
|
2812
|
+
for (const [key, entry] of Object.entries(value)) result[String(key)] = Math.max(0, Number(entry) || 0);
|
|
2813
|
+
return result;
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
function configureMode4Atlas(ws, payload = {}) {
|
|
2817
|
+
const deviceIds = normalizeRemoteFrameWsDeviceIds(payload.deviceIds ?? payload.devices ?? payload.deviceId).slice(0, 100);
|
|
2818
|
+
const monitorSelections = normalizeRemoteAtlasMonitorSelections(payload.monitorSelections);
|
|
2819
|
+
const sharpTiles = Number(payload.tileWidth) >= 480 || Number(payload.tileHeight) >= 270;
|
|
2820
|
+
const tileWidth = sharpTiles ? 480 : 320;
|
|
2821
|
+
const tileHeight = sharpTiles ? 270 : 180;
|
|
2822
|
+
ws.remoteAtlasDeviceIds = new Set(deviceIds);
|
|
2823
|
+
ws.remoteAtlasInputOptions = { tileWidth, tileHeight, monitorSelections };
|
|
2824
|
+
ws.remoteAtlasSession.configure({
|
|
2825
|
+
deviceIds,
|
|
2826
|
+
width: clampRemoteFrameWsNumber(payload.width, 640, 3840, 1920),
|
|
2827
|
+
height: clampRemoteFrameWsNumber(payload.height, 360, 2160, 1080),
|
|
2828
|
+
tileWidth, tileHeight,
|
|
2829
|
+
fps: clampRemoteFrameWsNumber(payload.fps, 1, 30, 20)
|
|
2830
|
+
});
|
|
2831
|
+
for (const deviceId of deviceIds) startMode4AtlasInput(ws, deviceId, 'atlas-configure');
|
|
2832
|
+
sendRemoteFrameClientJson(ws, { type: 'Mode4AtlasSubscription', deviceIds, inputMode: 'mode2-lzo', outputMode: 'mode4-h264-atlas', tileWidth, tileHeight, timestamp: new Date().toISOString() });
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2835
|
+
function startMode4AtlasInput(ws, deviceId, reason = 'atlas-configure') {
|
|
2836
|
+
const options = ws?.remoteAtlasInputOptions;
|
|
2837
|
+
if (!options || !ws.remoteAtlasDeviceIds?.has(deviceId)) return { ok: false, error: 'atlas-device-not-configured' };
|
|
2838
|
+
return remoteHub.startLiveStream(deviceId, {
|
|
2839
|
+
fps: 8, maxWidth: options.tileWidth, maxHeight: options.tileHeight, quality: 60,
|
|
2840
|
+
mode: 'mode2-lzo', frameMode: 'mode2-lzo', streamPurpose: 'atlas',
|
|
2841
|
+
monitorIndex: Number(options.monitorSelections?.[deviceId] || 0),
|
|
2842
|
+
streamId: `atlas-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
2843
|
+
restartReason: reason
|
|
2844
|
+
});
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2743
2847
|
function broadcastRemoteBinaryFrame(frameEvent) {
|
|
2848
|
+
for (const session of remoteAtlasClients.values()) session.ingest(frameEvent);
|
|
2744
2849
|
const frame = frameEvent?.frame || {};
|
|
2745
2850
|
remoteFrameWsDiagnostics.framesReceived += 1;
|
|
2746
2851
|
remoteFrameWsDiagnostics.lastFrameAt = new Date().toISOString();
|
|
@@ -2901,6 +3006,44 @@ remoteFrameWss.on('connection', (ws, req) => {
|
|
|
2901
3006
|
});
|
|
2902
3007
|
});
|
|
2903
3008
|
|
|
3009
|
+
remoteAtlasWss.on('connection', (ws) => {
|
|
3010
|
+
ws.binaryType = 'arraybuffer';
|
|
3011
|
+
ws.remoteAtlasClientId = `ratlas-${++remoteAtlasClientSeq}`;
|
|
3012
|
+
ws.remoteAtlasStreamId = `mode4-atlas-${crypto.randomUUID()}`;
|
|
3013
|
+
try { ws._socket?.setNoDelay?.(true); } catch { /* ignore */ }
|
|
3014
|
+
const session = new Mode4AtlasSession({
|
|
3015
|
+
onFrame: output => sendMode4AtlasFrame(ws, output),
|
|
3016
|
+
onLayout: layout => sendRemoteFrameClientJson(ws, { ...layout, type: 'Mode4AtlasLayout' }),
|
|
3017
|
+
onStatus: status => sendRemoteFrameClientJson(ws, { ...status, type: 'Mode4AtlasStatus' })
|
|
3018
|
+
});
|
|
3019
|
+
ws.remoteAtlasSession = session;
|
|
3020
|
+
remoteAtlasClients.set(ws, session);
|
|
3021
|
+
let cleaned = false;
|
|
3022
|
+
const cleanup = () => {
|
|
3023
|
+
if (cleaned) return;
|
|
3024
|
+
cleaned = true;
|
|
3025
|
+
remoteAtlasClients.delete(ws);
|
|
3026
|
+
session.close();
|
|
3027
|
+
ws.remoteAtlasSession = null;
|
|
3028
|
+
};
|
|
3029
|
+
ws.on('message', data => {
|
|
3030
|
+
try {
|
|
3031
|
+
const payload = JSON.parse(Buffer.isBuffer(data) ? data.toString('utf8') : String(data || ''));
|
|
3032
|
+
if (payload?.type === 'subscribe' || payload?.type === 'configure') configureMode4Atlas(ws, payload);
|
|
3033
|
+
} catch {
|
|
3034
|
+
sendRemoteFrameClientJson(ws, { type: 'Mode4AtlasError', error: 'invalid-message' });
|
|
3035
|
+
}
|
|
3036
|
+
});
|
|
3037
|
+
ws.on('close', cleanup);
|
|
3038
|
+
ws.on('error', cleanup);
|
|
3039
|
+
sendRemoteFrameClientJson(ws, {
|
|
3040
|
+
type: 'Mode4AtlasSocketReady',
|
|
3041
|
+
protocol: 'mindexec.remote.atlas.h264.v1',
|
|
3042
|
+
clientId: ws.remoteAtlasClientId,
|
|
3043
|
+
timestamp: new Date().toISOString()
|
|
3044
|
+
});
|
|
3045
|
+
});
|
|
3046
|
+
|
|
2904
3047
|
function sendRemoteInputClientJson(ws, payload) {
|
|
2905
3048
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
2906
3049
|
return false;
|
|
@@ -12411,6 +12554,7 @@ app.get('/api/status', async (req, res) => {
|
|
|
12411
12554
|
wsToken,
|
|
12412
12555
|
wsPath: '/events',
|
|
12413
12556
|
remoteFrameWsPath: '/api/remote/frames/ws',
|
|
12557
|
+
remoteAtlasWsPath: '/api/remote/atlas/ws',
|
|
12414
12558
|
remoteInputWsPath: '/api/remote/input/ws',
|
|
12415
12559
|
bridgeToken,
|
|
12416
12560
|
bridgeTokenHeader,
|
|
@@ -12819,9 +12963,11 @@ app.get('/api/remote/devices/:deviceId/live/frame', (req, res) => {
|
|
|
12819
12963
|
});
|
|
12820
12964
|
|
|
12821
12965
|
app.post('/api/remote/devices/:deviceId/live/start', (req, res) => {
|
|
12966
|
+
const streamPurpose = String(req.body?.streamPurpose || '').trim().toLowerCase();
|
|
12822
12967
|
res.json(remoteHub.startLiveStream(req.params.deviceId, {
|
|
12823
12968
|
streamId: req.body?.streamId,
|
|
12824
|
-
mode: req.body?.frameMode || req.body?.mode || 'mode3-h264-hw',
|
|
12969
|
+
mode: req.body?.frameMode || req.body?.mode || (streamPurpose === 'control' ? 'mode3-h264-hw' : 'mode2-lzo'),
|
|
12970
|
+
streamPurpose,
|
|
12825
12971
|
fps: req.body?.fps,
|
|
12826
12972
|
maxWidth: req.body?.maxWidth,
|
|
12827
12973
|
maxHeight: req.body?.maxHeight,
|
|
@@ -14333,6 +14479,14 @@ async function shutdownBridge(signal) {
|
|
|
14333
14479
|
}
|
|
14334
14480
|
}
|
|
14335
14481
|
|
|
14482
|
+
for (const client of remoteAtlasClients.keys()) {
|
|
14483
|
+
try { client.close(); } catch { /* Ignore close race */ }
|
|
14484
|
+
}
|
|
14485
|
+
for (const session of remoteAtlasClients.values()) {
|
|
14486
|
+
try { session.close(); } catch { /* Ignore atlas worker shutdown errors */ }
|
|
14487
|
+
}
|
|
14488
|
+
remoteAtlasClients.clear();
|
|
14489
|
+
|
|
14336
14490
|
for (const client of remoteInputClients) {
|
|
14337
14491
|
try {
|
|
14338
14492
|
client.close();
|
|
@@ -14347,6 +14501,12 @@ async function shutdownBridge(signal) {
|
|
|
14347
14501
|
// Ignore if already closed
|
|
14348
14502
|
}
|
|
14349
14503
|
|
|
14504
|
+
try {
|
|
14505
|
+
remoteAtlasWss.close();
|
|
14506
|
+
} catch {
|
|
14507
|
+
// Ignore if already closed
|
|
14508
|
+
}
|
|
14509
|
+
|
|
14350
14510
|
try {
|
|
14351
14511
|
remoteInputWss.close();
|
|
14352
14512
|
} catch {
|
|
@@ -15955,7 +15955,7 @@
|
|
|
15955
15955
|
maxWidth: Number(options.maxWidth || 960) || 960,
|
|
15956
15956
|
maxHeight: Number(options.maxHeight || 540) || 540,
|
|
15957
15957
|
quality: Number(options.quality || 60) || 60,
|
|
15958
|
-
mode: String(options.mode || '
|
|
15958
|
+
mode: String(options.mode || 'mode2-lzo'),
|
|
15959
15959
|
streamPurpose: String(options.streamPurpose || 'wall')
|
|
15960
15960
|
};
|
|
15961
15961
|
bodyView._remoteFleetBinaryFrameSession = session;
|
|
@@ -17192,13 +17192,15 @@
|
|
|
17192
17192
|
function applyRemoteFleetFramePatchToPreview(preview, frame) {
|
|
17193
17193
|
if (frame?._remoteFleetBinaryFrame === true
|
|
17194
17194
|
&& frame?._remoteFleetPayloadBlob
|
|
17195
|
-
&& String(frame.codec || '').toLowerCase().includes('h264')
|
|
17196
|
-
|
|
17195
|
+
&& (String(frame.codec || '').toLowerCase().includes('h264')
|
|
17196
|
+
|| (String(frame.frameMode || frame.mode || '').toLowerCase() === 'mode2-lzo'
|
|
17197
|
+
&& String(frame.compression || '').toLowerCase() === 'lzo1x'))
|
|
17198
|
+
&& window.MindExecRemoteCodecs?.decodeFrame) {
|
|
17197
17199
|
const canvas = ensureRemoteFleetFrameCanvas(preview);
|
|
17198
17200
|
if (canvas) {
|
|
17199
17201
|
canvas.style.display = 'block';
|
|
17200
17202
|
preview.querySelector?.('img[data-remote-fleet-frame-image="true"]')?.style.setProperty('display', 'none');
|
|
17201
|
-
window.MindExecRemoteCodecs.
|
|
17203
|
+
window.MindExecRemoteCodecs.decodeFrame(canvas, frame).catch?.(() => undefined);
|
|
17202
17204
|
preview.dataset.remoteFleetFrameKind = String(frame.kind || 'live').toLowerCase();
|
|
17203
17205
|
preview.dataset.remoteFleetFrameSeq = String(frame.frameSeq || 0);
|
|
17204
17206
|
return true;
|
|
@@ -17535,9 +17537,11 @@
|
|
|
17535
17537
|
}
|
|
17536
17538
|
|
|
17537
17539
|
if (frame._remoteFleetPayloadBlob
|
|
17538
|
-
&& String(frame.codec || '').toLowerCase().includes('h264')
|
|
17539
|
-
|
|
17540
|
-
|
|
17540
|
+
&& (String(frame.codec || '').toLowerCase().includes('h264')
|
|
17541
|
+
|| (String(frame.frameMode || frame.mode || '').toLowerCase() === 'mode2-lzo'
|
|
17542
|
+
&& String(frame.compression || '').toLowerCase() === 'lzo1x'))
|
|
17543
|
+
&& window.MindExecRemoteCodecs?.decodeFrame) {
|
|
17544
|
+
const painted = await window.MindExecRemoteCodecs.decodeFrame(session.canvas, frame);
|
|
17541
17545
|
if (painted && session.active) {
|
|
17542
17546
|
session.canvas.dataset.remoteFleetFrameKind = 'live';
|
|
17543
17547
|
session.canvas.dataset.remoteFleetFrameSeq = String(frameSeq || 0);
|
|
@@ -20717,7 +20721,7 @@
|
|
|
20717
20721
|
maxWidth: 960,
|
|
20718
20722
|
maxHeight: 540,
|
|
20719
20723
|
quality: 60,
|
|
20720
|
-
mode: '
|
|
20724
|
+
mode: 'mode2-lzo',
|
|
20721
20725
|
streamPurpose: 'wall'
|
|
20722
20726
|
});
|
|
20723
20727
|
if (!binaryFrameSocketStarted) {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
const decoderByCanvas = new WeakMap();
|
|
5
5
|
const MAX_DECODE_QUEUE = 3;
|
|
6
|
+
const rawFrameByCanvas = new WeakMap();
|
|
6
7
|
|
|
7
8
|
function emit(type, data) {
|
|
8
9
|
window.RuntimeTrace?.emit?.(type, data);
|
|
@@ -30,6 +31,73 @@
|
|
|
30
31
|
state.pending = 0;
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
// LiveDesk Mode 2 payloads are LZO1X-compressed little-endian RGB565.
|
|
35
|
+
// Keep this decoder local to the wall path so H.264 control surfaces remain
|
|
36
|
+
// fully independent.
|
|
37
|
+
function decodeLzo1x(input, outputLength) {
|
|
38
|
+
if (!(input instanceof Uint8Array) || input.length < 3) throw new Error('Invalid LZO1X block');
|
|
39
|
+
const output = new Uint8Array(outputLength);
|
|
40
|
+
const s = { i: 0, o: 0 };
|
|
41
|
+
const need = (n) => { if (s.i + n > input.length) throw new Error('LZO input overrun'); };
|
|
42
|
+
const literals = (n) => {
|
|
43
|
+
need(n);
|
|
44
|
+
if (s.o + n > output.length) throw new Error('LZO output overrun');
|
|
45
|
+
output.set(input.subarray(s.i, s.i + n), s.o); s.i += n; s.o += n;
|
|
46
|
+
};
|
|
47
|
+
const ext = (basis) => { let zeros = 0; while (true) { need(1); if (input[s.i] !== 0) break; zeros++; s.i++; } return zeros * 255 + basis + input[s.i++]; };
|
|
48
|
+
const match = (at, length) => {
|
|
49
|
+
const distance = s.o - at;
|
|
50
|
+
if (distance <= 0 || s.o + length > output.length) throw new Error('LZO match overrun');
|
|
51
|
+
for (let n = 0; n < length; n++) output[s.o++] = output[at + (n % distance)];
|
|
52
|
+
};
|
|
53
|
+
let state = 0; let matchLength = 0;
|
|
54
|
+
if (input[0] >= 22) { s.i++; literals(input[0] - 17); state = 4; }
|
|
55
|
+
else if (input[0] >= 18) { s.i++; state = input[0] - 17; literals(state); }
|
|
56
|
+
while (true) {
|
|
57
|
+
need(1); const instruction = input[s.i++]; let nextState; let at;
|
|
58
|
+
if ((instruction & 0xc0) !== 0) {
|
|
59
|
+
need(1); at = s.o - ((input[s.i++] << 3) + ((instruction >> 2) & 7) + 1); matchLength = (instruction >> 5) + 1; nextState = instruction & 3;
|
|
60
|
+
} else if ((instruction & 0x20) !== 0) {
|
|
61
|
+
matchLength = (instruction & 0x1f) + 2; if (matchLength === 2) matchLength += ext(31); need(2); const encoded = input[s.i++] | (input[s.i++] << 8); at = s.o - ((encoded >> 2) + 1); nextState = encoded & 3;
|
|
62
|
+
} else if ((instruction & 0x10) !== 0) {
|
|
63
|
+
matchLength = (instruction & 7) + 2; if (matchLength === 2) matchLength += ext(7); need(2); const encoded = input[s.i++] | (input[s.i++] << 8); at = s.o - (((instruction & 8) << 11) + (encoded >> 2)); nextState = encoded & 3; if (at === s.o) break; at -= 0x4000;
|
|
64
|
+
} else if (state === 0) {
|
|
65
|
+
let length = instruction + 3; if (length === 3) length += ext(15); literals(length); state = 4; continue;
|
|
66
|
+
} else {
|
|
67
|
+
need(1); nextState = instruction & 3; at = s.o - ((instruction >> 2) + (input[s.i++] << 2) + (state === 4 ? 2049 : 1)); matchLength = state === 4 ? 3 : 2;
|
|
68
|
+
}
|
|
69
|
+
if (at < 0 || s.o + matchLength + nextState > output.length) throw new Error('LZO lookbehind overrun');
|
|
70
|
+
match(at, matchLength); state = nextState; literals(nextState);
|
|
71
|
+
}
|
|
72
|
+
if (matchLength !== 3 || s.i !== input.length || s.o !== output.length) throw new Error('Incomplete LZO block');
|
|
73
|
+
return output;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function decodeMode2Frame(canvas, frame) {
|
|
77
|
+
const payload = frame?._remoteFleetPayloadBlob;
|
|
78
|
+
if (!canvas || !payload) return false;
|
|
79
|
+
const width = Math.max(1, Number(frame.width || 0) | 0);
|
|
80
|
+
const height = Math.max(1, Number(frame.height || 0) | 0);
|
|
81
|
+
const expected = width * height * 2;
|
|
82
|
+
if (Number(frame.bytesPerPixel || 2) !== 2 || (Number(frame.uncompressedByteLength || expected) !== expected)) return false;
|
|
83
|
+
const state = rawFrameByCanvas.get(canvas) || { lastSeq: 0 };
|
|
84
|
+
const seq = Number(frame.streamFrameSeq || frame.frameSeq || 0) || 0;
|
|
85
|
+
if (seq > 0 && seq <= state.lastSeq) return true;
|
|
86
|
+
const compressed = new Uint8Array(await payload.arrayBuffer());
|
|
87
|
+
const rgb565 = decodeLzo1x(compressed, expected);
|
|
88
|
+
const rgba = new Uint8ClampedArray(width * height * 4);
|
|
89
|
+
for (let source = 0, target = 0; source < rgb565.length; source += 2, target += 4) {
|
|
90
|
+
const pixel = rgb565[source] | (rgb565[source + 1] << 8);
|
|
91
|
+
const r = (pixel >> 11) & 31; const g = (pixel >> 5) & 63; const b = pixel & 31;
|
|
92
|
+
rgba[target] = (r << 3) | (r >> 2); rgba[target + 1] = (g << 2) | (g >> 4); rgba[target + 2] = (b << 3) | (b >> 2); rgba[target + 3] = 255;
|
|
93
|
+
}
|
|
94
|
+
canvas.width = width; canvas.height = height;
|
|
95
|
+
canvas.getContext('2d', { alpha: false, desynchronized: true })?.putImageData(new ImageData(rgba, width, height), 0, 0);
|
|
96
|
+
state.lastSeq = seq; rawFrameByCanvas.set(canvas, state);
|
|
97
|
+
emit('remote.mode2.paint', { frameSeq: seq, width, height });
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
|
|
33
101
|
function ensureDecoder(canvas, frame, state) {
|
|
34
102
|
if (typeof VideoDecoder !== 'function' || typeof EncodedVideoChunk !== 'function') {
|
|
35
103
|
return null;
|
|
@@ -88,9 +156,14 @@
|
|
|
88
156
|
|
|
89
157
|
async function decode(canvas, frame) {
|
|
90
158
|
const payload = frame?._remoteFleetPayloadBlob;
|
|
91
|
-
if (!canvas || !payload
|
|
159
|
+
if (!canvas || !payload) {
|
|
92
160
|
return false;
|
|
93
161
|
}
|
|
162
|
+
const mode = String(frame?.frameMode || frame?.mode || '').toLowerCase();
|
|
163
|
+
if (mode === 'mode2-lzo' || String(frame?.compression || '').toLowerCase() === 'lzo1x' || String(frame?.mimeType || '').toLowerCase() === 'application/vnd.livedesk.lzo-rgb565') {
|
|
164
|
+
try { return await decodeMode2Frame(canvas, frame); } catch (error) { emit('remote.mode2.decodeFailed', { error: error?.message || String(error || '') }); return false; }
|
|
165
|
+
}
|
|
166
|
+
if (!String(frame?.codec || '').toLowerCase().includes('h264')) return false;
|
|
94
167
|
const state = getDecoderState(canvas);
|
|
95
168
|
const seq = Number(frame.streamFrameSeq || frame.frameSeq || 0) || 0;
|
|
96
169
|
if (seq > 0 && seq <= state.lastSeq) return true;
|
|
@@ -122,5 +195,5 @@
|
|
|
122
195
|
}
|
|
123
196
|
}
|
|
124
197
|
|
|
125
|
-
window.MindExecRemoteCodecs = Object.freeze({ decodeH264Frame: decode });
|
|
198
|
+
window.MindExecRemoteCodecs = Object.freeze({ decodeH264Frame: decode, decodeFrame: decode });
|
|
126
199
|
})();
|
package/wwwroot/_framework/{MindExecution.Core.nxjlewduna.dll → MindExecution.Core.4moacskf64.dll}
RENAMED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/wwwroot/_framework/{MindExecution.Web.nxykcyxd02.dll → MindExecution.Web.qucbls1wfr.dll}
RENAMED
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mainAssemblyName": "MindExecution.Web",
|
|
3
3
|
"resources": {
|
|
4
|
-
"hash": "sha256-
|
|
4
|
+
"hash": "sha256-vyIwPs5NXG0WvUn1crlwB/OCRyxH6tUNE8CXfOaHuOI=",
|
|
5
5
|
"fingerprinting": {
|
|
6
6
|
"Google.Protobuf.9h59ukbel7.dll": "Google.Protobuf.dll",
|
|
7
7
|
"Markdig.d1j7v41cl1.dll": "Markdig.dll",
|
|
@@ -122,16 +122,16 @@
|
|
|
122
122
|
"System.brmz7yk5qh.dll": "System.dll",
|
|
123
123
|
"netstandard.b50t77veor.dll": "netstandard.dll",
|
|
124
124
|
"System.Private.CoreLib.g6ztz7cmo2.dll": "System.Private.CoreLib.dll",
|
|
125
|
-
"MindExecution.Core.
|
|
126
|
-
"MindExecution.Kernel.
|
|
127
|
-
"MindExecution.Plugins.Admin.
|
|
128
|
-
"MindExecution.Plugins.Business.
|
|
129
|
-
"MindExecution.Plugins.Concept.
|
|
130
|
-
"MindExecution.Plugins.Directory.
|
|
131
|
-
"MindExecution.Plugins.PlanMaster.
|
|
132
|
-
"MindExecution.Plugins.YouTube.
|
|
133
|
-
"MindExecution.Shared.
|
|
134
|
-
"MindExecution.Web.
|
|
125
|
+
"MindExecution.Core.4moacskf64.dll": "MindExecution.Core.dll",
|
|
126
|
+
"MindExecution.Kernel.pa251cfsz4.dll": "MindExecution.Kernel.dll",
|
|
127
|
+
"MindExecution.Plugins.Admin.dxyuwmxv1s.dll": "MindExecution.Plugins.Admin.dll",
|
|
128
|
+
"MindExecution.Plugins.Business.7uj5erqhhn.dll": "MindExecution.Plugins.Business.dll",
|
|
129
|
+
"MindExecution.Plugins.Concept.108rmsxc96.dll": "MindExecution.Plugins.Concept.dll",
|
|
130
|
+
"MindExecution.Plugins.Directory.ccsy3g0fe5.dll": "MindExecution.Plugins.Directory.dll",
|
|
131
|
+
"MindExecution.Plugins.PlanMaster.1vjpuoe9ff.dll": "MindExecution.Plugins.PlanMaster.dll",
|
|
132
|
+
"MindExecution.Plugins.YouTube.q8ml98phj9.dll": "MindExecution.Plugins.YouTube.dll",
|
|
133
|
+
"MindExecution.Shared.2pywq19zjy.dll": "MindExecution.Shared.dll",
|
|
134
|
+
"MindExecution.Web.qucbls1wfr.dll": "MindExecution.Web.dll",
|
|
135
135
|
"dotnet.native.566r55w3xu.js": "dotnet.native.js",
|
|
136
136
|
"dotnet.native.x6q5aixc38.wasm": "dotnet.native.wasm",
|
|
137
137
|
"dotnet.js": "dotnet.js",
|
|
@@ -276,18 +276,18 @@
|
|
|
276
276
|
"System.Xml.XDocument.sn51jas17n.dll": "sha256-GNI2kFgFmPTwzuzwUn8gxK+AzGLUWRJFdg9JzIbrybQ=",
|
|
277
277
|
"System.brmz7yk5qh.dll": "sha256-CfM2miyj1KHApFmqMdLYWio3S/jrdON2pW9Xr2nTwlo=",
|
|
278
278
|
"netstandard.b50t77veor.dll": "sha256-//jQGOXjb8ET8WtXgOJrAxLx6E7zDJ5RjRRutwkvmxo=",
|
|
279
|
-
"MindExecution.Core.
|
|
280
|
-
"MindExecution.Kernel.
|
|
281
|
-
"MindExecution.Plugins.Business.
|
|
282
|
-
"MindExecution.Plugins.Concept.
|
|
283
|
-
"MindExecution.Plugins.PlanMaster.
|
|
284
|
-
"MindExecution.Shared.
|
|
285
|
-
"MindExecution.Web.
|
|
279
|
+
"MindExecution.Core.4moacskf64.dll": "sha256-5OiBWkHcOvL4NsaHtQ7O3z5N1Ba7nTRi3xkehUMMgkE=",
|
|
280
|
+
"MindExecution.Kernel.pa251cfsz4.dll": "sha256-4dswyE6zmKAS+CnExpbXK871UMxIp+a7SPMIMwmZ+2Q=",
|
|
281
|
+
"MindExecution.Plugins.Business.7uj5erqhhn.dll": "sha256-URKvk2etEOiEa/URXJpkYx7aJcPQd1Xs0Yxn3Uqg/ok=",
|
|
282
|
+
"MindExecution.Plugins.Concept.108rmsxc96.dll": "sha256-QTd+zvSVcfwz3gYaKZ3pP0wgxrj9R1aP6qQKsByDRR0=",
|
|
283
|
+
"MindExecution.Plugins.PlanMaster.1vjpuoe9ff.dll": "sha256-M3Fvm8WU5xbx24cTyACzH1IuZXuIY06dkeCfNCgeUT4=",
|
|
284
|
+
"MindExecution.Shared.2pywq19zjy.dll": "sha256-Wjp+pPwb4TDj0YtYTzvNQGIzQI7xAg9DeyO0g/jxyxU=",
|
|
285
|
+
"MindExecution.Web.qucbls1wfr.dll": "sha256-0kpuM4z2XvRReo2Eiy7cJ/SAfoF/dVnn6WChaz//lGc="
|
|
286
286
|
},
|
|
287
287
|
"lazyAssembly": {
|
|
288
|
-
"MindExecution.Plugins.Admin.
|
|
289
|
-
"MindExecution.Plugins.Directory.
|
|
290
|
-
"MindExecution.Plugins.YouTube.
|
|
288
|
+
"MindExecution.Plugins.Admin.dxyuwmxv1s.dll": "sha256-URTQOP1nUuBC2leUgGdGWb+rc/1blCxbpbhRGE1MW/I=",
|
|
289
|
+
"MindExecution.Plugins.Directory.ccsy3g0fe5.dll": "sha256-BFk4mut2rsioBC9unD8+BoxnoJqTJlS5uZV7uXr8i5E=",
|
|
290
|
+
"MindExecution.Plugins.YouTube.q8ml98phj9.dll": "sha256-2vzs6nizBsYO1JjXPxdSi6O7uyZLpqFblwE0q09mvfw="
|
|
291
291
|
}
|
|
292
292
|
},
|
|
293
293
|
"cacheBootResources": true,
|
package/wwwroot/index.html
CHANGED
|
@@ -579,7 +579,7 @@
|
|
|
579
579
|
}
|
|
580
580
|
|
|
581
581
|
const base = '_content/MindExecution.Shared/js/';
|
|
582
|
-
const scriptVersion = '20260717-livedesk-h264-
|
|
582
|
+
const scriptVersion = '20260717-livedesk-wall-lzo-control-h264-v937';
|
|
583
583
|
const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
|
|
584
584
|
console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
|
|
585
585
|
const criticalScripts = [
|